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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/CMakeLists.txt85
-rw-r--r--source/blender/editors/Makefile34
-rw-r--r--source/blender/editors/SConscript35
-rw-r--r--source/blender/editors/animation/Makefile54
-rw-r--r--source/blender/editors/animation/SConscript9
-rw-r--r--source/blender/editors/animation/anim_channels.c1714
-rw-r--r--source/blender/editors/animation/anim_deps.c239
-rw-r--r--source/blender/editors/animation/anim_draw.c315
-rw-r--r--source/blender/editors/animation/anim_filter.c1404
-rw-r--r--source/blender/editors/animation/anim_intern.h18
-rw-r--r--source/blender/editors/animation/anim_ipo_utils.c219
-rw-r--r--source/blender/editors/animation/anim_markers.c878
-rw-r--r--source/blender/editors/animation/anim_ops.c408
-rw-r--r--source/blender/editors/animation/drivers.c292
-rw-r--r--source/blender/editors/animation/keyframes_draw.c660
-rw-r--r--source/blender/editors/animation/keyframes_edit.c683
-rw-r--r--source/blender/editors/animation/keyframes_general.c548
-rw-r--r--source/blender/editors/animation/keyframing.c1455
-rw-r--r--source/blender/editors/animation/keyingsets.c1178
-rw-r--r--source/blender/editors/armature/BIF_generate.h45
-rw-r--r--source/blender/editors/armature/BIF_retarget.h160
-rw-r--r--source/blender/editors/armature/Makefile59
-rw-r--r--source/blender/editors/armature/SConscript11
-rw-r--r--source/blender/editors/armature/armature_intern.h101
-rw-r--r--source/blender/editors/armature/armature_ops.c269
-rw-r--r--source/blender/editors/armature/editarmature.c5675
-rw-r--r--source/blender/editors/armature/editarmature_generate.c329
-rw-r--r--source/blender/editors/armature/editarmature_retarget.c2962
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c3383
-rw-r--r--source/blender/editors/armature/meshlaplacian.c1920
-rw-r--r--source/blender/editors/armature/meshlaplacian.h85
-rw-r--r--source/blender/editors/armature/poselib.c1492
-rw-r--r--source/blender/editors/armature/poseobject.c1707
-rw-r--r--source/blender/editors/armature/reeb.c3725
-rw-r--r--source/blender/editors/armature/reeb.h200
-rw-r--r--source/blender/editors/curve/Makefile57
-rw-r--r--source/blender/editors/curve/SConscript11
-rw-r--r--source/blender/editors/curve/curve_intern.h109
-rw-r--r--source/blender/editors/curve/curve_ops.c243
-rw-r--r--source/blender/editors/curve/editcurve.c5232
-rw-r--r--source/blender/editors/curve/editfont.c1625
-rw-r--r--source/blender/editors/curve/lorem.c513
-rw-r--r--source/blender/editors/datafiles/B.blend.c3076
-rw-r--r--source/blender/editors/datafiles/Bfont.c136
-rw-r--r--source/blender/editors/datafiles/Makefile49
-rw-r--r--source/blender/editors/datafiles/SConscript9
-rw-r--r--source/blender/editors/datafiles/bfont.ttf.c5992
-rw-r--r--source/blender/editors/datafiles/blenderbuttons.c4103
-rw-r--r--source/blender/editors/datafiles/bmonofont.ttf.c9681
-rw-r--r--source/blender/editors/datafiles/preview.blend.c13952
-rw-r--r--source/blender/editors/datafiles/prvicons.c304
-rw-r--r--source/blender/editors/datafiles/splash.jpg.c2483
-rw-r--r--source/blender/editors/gpencil/Makefile57
-rw-r--r--source/blender/editors/gpencil/SConscript11
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c1064
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c740
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c1715
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h81
-rw-r--r--source/blender/editors/include/BIF_gl.h77
-rw-r--r--source/blender/editors/include/BIF_glutil.h216
-rw-r--r--source/blender/editors/include/BIF_retopo.h110
-rw-r--r--source/blender/editors/include/BIF_transform.h165
-rw-r--r--source/blender/editors/include/ED_anim_api.h352
-rw-r--r--source/blender/editors/include/ED_armature.h151
-rw-r--r--source/blender/editors/include/ED_curve.h64
-rw-r--r--source/blender/editors/include/ED_datafiles.h56
-rw-r--r--source/blender/editors/include/ED_fileselect.h103
-rw-r--r--source/blender/editors/include/ED_fluidsim.h52
-rw-r--r--source/blender/editors/include/ED_gpencil.h83
-rw-r--r--source/blender/editors/include/ED_image.h63
-rw-r--r--source/blender/editors/include/ED_interface.h0
-rw-r--r--source/blender/editors/include/ED_keyframes_draw.h98
-rw-r--r--source/blender/editors/include/ED_keyframes_edit.h159
-rw-r--r--source/blender/editors/include/ED_keyframing.h213
-rw-r--r--source/blender/editors/include/ED_markers.h51
-rw-r--r--source/blender/editors/include/ED_mesh.h174
-rw-r--r--source/blender/editors/include/ED_node.h35
-rw-r--r--source/blender/editors/include/ED_object.h92
-rw-r--r--source/blender/editors/include/ED_particle.h74
-rw-r--r--source/blender/editors/include/ED_previewrender.h79
-rw-r--r--source/blender/editors/include/ED_screen.h138
-rw-r--r--source/blender/editors/include/ED_screen_types.h57
-rw-r--r--source/blender/editors/include/ED_sculpt.h45
-rw-r--r--source/blender/editors/include/ED_sequencer.h31
-rw-r--r--source/blender/editors/include/ED_space_api.h70
-rw-r--r--source/blender/editors/include/ED_text.h36
-rw-r--r--source/blender/editors/include/ED_transform.h33
-rw-r--r--source/blender/editors/include/ED_types.h54
-rw-r--r--source/blender/editors/include/ED_util.h74
-rw-r--r--source/blender/editors/include/ED_uvedit.h63
-rw-r--r--source/blender/editors/include/ED_view3d.h138
-rw-r--r--source/blender/editors/include/UI_interface.h617
-rw-r--r--source/blender/editors/include/UI_interface_icons.h70
-rw-r--r--source/blender/editors/include/UI_resources.h962
-rw-r--r--source/blender/editors/include/UI_view2d.h192
-rw-r--r--source/blender/editors/interface/Makefile61
-rw-r--r--source/blender/editors/interface/SConscript20
-rw-r--r--source/blender/editors/interface/interface.c3066
-rw-r--r--source/blender/editors/interface/interface_anim.c157
-rw-r--r--source/blender/editors/interface/interface_api.c91
-rw-r--r--source/blender/editors/interface/interface_draw.c1125
-rw-r--r--source/blender/editors/interface/interface_handlers.c3823
-rw-r--r--source/blender/editors/interface/interface_icons.c977
-rw-r--r--source/blender/editors/interface/interface_intern.h392
-rw-r--r--source/blender/editors/interface/interface_layout.c1308
-rw-r--r--source/blender/editors/interface/interface_panel.c1656
-rw-r--r--source/blender/editors/interface/interface_regions.c2389
-rw-r--r--source/blender/editors/interface/interface_style.c263
-rw-r--r--source/blender/editors/interface/interface_utils.c1060
-rw-r--r--source/blender/editors/interface/interface_widgets.c1866
-rw-r--r--source/blender/editors/interface/keyval.c540
-rw-r--r--source/blender/editors/interface/resources.c987
-rw-r--r--source/blender/editors/interface/view2d.c1965
-rw-r--r--source/blender/editors/interface/view2d_ops.c1311
-rw-r--r--source/blender/editors/mesh/Makefile57
-rw-r--r--source/blender/editors/mesh/SConscript11
-rw-r--r--source/blender/editors/mesh/editdeform.c1089
-rw-r--r--source/blender/editors/mesh/editface.c727
-rw-r--r--source/blender/editors/mesh/editmesh.c2029
-rw-r--r--source/blender/editors/mesh/editmesh_add.c1641
-rw-r--r--source/blender/editors/mesh/editmesh_lib.c2280
-rw-r--r--source/blender/editors/mesh/editmesh_loop.c735
-rw-r--r--source/blender/editors/mesh/editmesh_mods.c4610
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c7088
-rw-r--r--source/blender/editors/mesh/mesh_intern.h237
-rw-r--r--source/blender/editors/mesh/mesh_ops.c296
-rw-r--r--source/blender/editors/mesh/meshtools.c1135
-rw-r--r--source/blender/editors/object/Makefile54
-rw-r--r--source/blender/editors/object/SConscript16
-rw-r--r--source/blender/editors/object/editconstraint.c891
-rw-r--r--source/blender/editors/object/editgroup.c257
-rw-r--r--source/blender/editors/object/editkey.c562
-rw-r--r--source/blender/editors/object/editlattice.c343
-rw-r--r--source/blender/editors/object/object_edit.c6523
-rw-r--r--source/blender/editors/object/object_intern.h88
-rw-r--r--source/blender/editors/object/object_ops.c148
-rw-r--r--source/blender/editors/physics/Makefile57
-rw-r--r--source/blender/editors/physics/SConscript11
-rw-r--r--source/blender/editors/physics/ed_fluidsim.c1149
-rw-r--r--source/blender/editors/physics/editparticle.c3924
-rw-r--r--source/blender/editors/physics/physics_intern.h38
-rw-r--r--source/blender/editors/preview/Makefile57
-rw-r--r--source/blender/editors/preview/SConscript12
-rw-r--r--source/blender/editors/preview/previewrender.c1084
-rw-r--r--source/blender/editors/preview/previewrender_intern.h69
-rw-r--r--source/blender/editors/screen/CMakeLists.txt83
-rw-r--r--source/blender/editors/screen/Makefile56
-rw-r--r--source/blender/editors/screen/SConscript16
-rw-r--r--source/blender/editors/screen/area.c910
-rw-r--r--source/blender/editors/screen/glutil.c853
-rw-r--r--source/blender/editors/screen/screen_context.c85
-rw-r--r--source/blender/editors/screen/screen_edit.c1500
-rw-r--r--source/blender/editors/screen/screen_intern.h68
-rw-r--r--source/blender/editors/screen/screen_ops.c2469
-rw-r--r--source/blender/editors/screen/screendump.c335
-rw-r--r--source/blender/editors/sculpt_paint/Makefile57
-rw-r--r--source/blender/editors/sculpt_paint/SConscript11
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c5189
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h64
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c32
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c182
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c1868
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c2150
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h67
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_stroke.c274
-rw-r--r--source/blender/editors/space_action/Makefile54
-rw-r--r--source/blender/editors/space_action/SConscript9
-rw-r--r--source/blender/editors/space_action/action_draw.c1246
-rw-r--r--source/blender/editors/space_action/action_edit.c1315
-rw-r--r--source/blender/editors/space_action/action_header.c1753
-rw-r--r--source/blender/editors/space_action/action_intern.h126
-rw-r--r--source/blender/editors/space_action/action_ops.c174
-rw-r--r--source/blender/editors/space_action/action_select.c997
-rw-r--r--source/blender/editors/space_action/space_action.c447
-rw-r--r--source/blender/editors/space_api/Makefile50
-rw-r--r--source/blender/editors/space_api/SConscript15
-rw-r--r--source/blender/editors/space_api/space.c45
-rw-r--r--source/blender/editors/space_api/spacetypes.c249
-rw-r--r--source/blender/editors/space_buttons/Makefile55
-rw-r--r--source/blender/editors/space_buttons/SConscript18
-rw-r--r--source/blender/editors/space_buttons/buttons_header.c221
-rw-r--r--source/blender/editors/space_buttons/buttons_intern.h85
-rw-r--r--source/blender/editors/space_buttons/buttons_object.c218
-rw-r--r--source/blender/editors/space_buttons/buttons_scene.c469
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c313
-rw-r--r--source/blender/editors/space_file/Makefile61
-rw-r--r--source/blender/editors/space_file/SConscript16
-rw-r--r--source/blender/editors/space_file/file_draw.c612
-rw-r--r--source/blender/editors/space_file/file_header.c187
-rw-r--r--source/blender/editors/space_file/file_intern.h72
-rw-r--r--source/blender/editors/space_file/file_ops.c644
-rw-r--r--source/blender/editors/space_file/filelist.c897
-rw-r--r--source/blender/editors/space_file/filelist.h94
-rw-r--r--source/blender/editors/space_file/filesel.c244
-rw-r--r--source/blender/editors/space_file/fsmenu.c349
-rw-r--r--source/blender/editors/space_file/fsmenu.h84
-rw-r--r--source/blender/editors/space_file/space_file.c447
-rw-r--r--source/blender/editors/space_file/writeimage.c252
-rw-r--r--source/blender/editors/space_graph/Makefile54
-rw-r--r--source/blender/editors/space_graph/SConscript9
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c1015
-rw-r--r--source/blender/editors/space_graph/graph_draw.c1397
-rw-r--r--source/blender/editors/space_graph/graph_edit.c1715
-rw-r--r--source/blender/editors/space_graph/graph_header.c241
-rw-r--r--source/blender/editors/space_graph/graph_intern.h151
-rw-r--r--source/blender/editors/space_graph/graph_ops.c248
-rw-r--r--source/blender/editors/space_graph/graph_select.c945
-rw-r--r--source/blender/editors/space_graph/space_graph.c592
-rw-r--r--source/blender/editors/space_image/Makefile55
-rw-r--r--source/blender/editors/space_image/SConscript10
-rw-r--r--source/blender/editors/space_image/image_draw.c693
-rw-r--r--source/blender/editors/space_image/image_header.c969
-rw-r--r--source/blender/editors/space_image/image_intern.h91
-rw-r--r--source/blender/editors/space_image/image_ops.c1631
-rw-r--r--source/blender/editors/space_image/image_panels.c1463
-rw-r--r--source/blender/editors/space_image/image_render.c177
-rw-r--r--source/blender/editors/space_image/space_image.c791
-rw-r--r--source/blender/editors/space_info/Makefile55
-rw-r--r--source/blender/editors/space_info/SConscript17
-rw-r--r--source/blender/editors/space_info/info_header.c455
-rw-r--r--source/blender/editors/space_info/info_intern.h39
-rw-r--r--source/blender/editors/space_info/space_info.c283
-rw-r--r--source/blender/editors/space_nla/Makefile54
-rw-r--r--source/blender/editors/space_nla/SConscript9
-rw-r--r--source/blender/editors/space_nla/nla_header.c130
-rw-r--r--source/blender/editors/space_nla/nla_intern.h39
-rw-r--r--source/blender/editors/space_nla/space_nla.c297
-rw-r--r--source/blender/editors/space_node/Makefile57
-rw-r--r--source/blender/editors/space_node/SConscript18
-rw-r--r--source/blender/editors/space_node/drawnode.c2691
-rw-r--r--source/blender/editors/space_node/node_draw.c1138
-rw-r--r--source/blender/editors/space_node/node_edit.c2535
-rw-r--r--source/blender/editors/space_node/node_header.c788
-rw-r--r--source/blender/editors/space_node/node_intern.h119
-rw-r--r--source/blender/editors/space_node/node_ops.c84
-rw-r--r--source/blender/editors/space_node/node_select.c293
-rw-r--r--source/blender/editors/space_node/node_state.c208
-rw-r--r--source/blender/editors/space_node/space_node.c353
-rw-r--r--source/blender/editors/space_outliner/Makefile54
-rw-r--r--source/blender/editors/space_outliner/SConscript10
-rw-r--r--source/blender/editors/space_outliner/outliner.c4475
-rw-r--r--source/blender/editors/space_outliner/outliner_header.c307
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h146
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c71
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c288
-rw-r--r--source/blender/editors/space_script/Makefile54
-rw-r--r--source/blender/editors/space_script/SConscript16
-rw-r--r--source/blender/editors/space_script/script_edit.c88
-rw-r--r--source/blender/editors/space_script/script_header.c130
-rw-r--r--source/blender/editors/space_script/script_intern.h45
-rw-r--r--source/blender/editors/space_script/script_ops.c72
-rw-r--r--source/blender/editors/space_script/space_script.c249
-rw-r--r--source/blender/editors/space_sequencer/Makefile56
-rw-r--r--source/blender/editors/space_sequencer/SConscript10
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c644
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c1096
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c2388
-rw-r--r--source/blender/editors/space_sequencer/sequencer_header.c455
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h144
-rw-r--r--source/blender/editors/space_sequencer/sequencer_ops.c182
-rw-r--r--source/blender/editors/space_sequencer/sequencer_scopes.c701
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c819
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c243
-rw-r--r--source/blender/editors/space_sound/Makefile54
-rw-r--r--source/blender/editors/space_sound/SConscript9
-rw-r--r--source/blender/editors/space_sound/sound_header.c130
-rw-r--r--source/blender/editors/space_sound/sound_intern.h39
-rw-r--r--source/blender/editors/space_sound/space_sound.c270
-rw-r--r--source/blender/editors/space_text/Makefile55
-rw-r--r--source/blender/editors/space_text/SConscript13
-rw-r--r--source/blender/editors/space_text/space_text.c424
-rw-r--r--source/blender/editors/space_text/text_draw.c1381
-rw-r--r--source/blender/editors/space_text/text_header.c644
-rw-r--r--source/blender/editors/space_text/text_intern.h159
-rw-r--r--source/blender/editors/space_text/text_ops.c2547
-rw-r--r--source/blender/editors/space_text/text_python.c541
-rw-r--r--source/blender/editors/space_time/Makefile54
-rw-r--r--source/blender/editors/space_time/SConscript10
-rw-r--r--source/blender/editors/space_time/space_time.c335
-rw-r--r--source/blender/editors/space_time/time_header.c572
-rw-r--r--source/blender/editors/space_time/time_intern.h44
-rw-r--r--source/blender/editors/space_time/time_ops.c148
-rw-r--r--source/blender/editors/space_view3d/Makefile58
-rw-r--r--source/blender/editors/space_view3d/SConscript11
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c2571
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c590
-rw-r--r--source/blender/editors/space_view3d/drawobject.c5407
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c804
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c1805
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c2118
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c2330
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c5581
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h156
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c232
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c1843
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c1148
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c1482
-rw-r--r--source/blender/editors/transform/Makefile54
-rw-r--r--source/blender/editors/transform/SConscript11
-rw-r--r--source/blender/editors/transform/transform.c4680
-rw-r--r--source/blender/editors/transform/transform.h639
-rw-r--r--source/blender/editors/transform/transform_constraints.c1113
-rw-r--r--source/blender/editors/transform/transform_conversions.c5061
-rw-r--r--source/blender/editors/transform/transform_generics.c1299
-rw-r--r--source/blender/editors/transform/transform_input.c329
-rw-r--r--source/blender/editors/transform/transform_manipulator.c1685
-rw-r--r--source/blender/editors/transform/transform_ndofinput.c155
-rw-r--r--source/blender/editors/transform/transform_numinput.c279
-rw-r--r--source/blender/editors/transform/transform_ops.c642
-rw-r--r--source/blender/editors/transform/transform_orientations.c891
-rw-r--r--source/blender/editors/transform/transform_snap.c1755
-rw-r--r--source/blender/editors/util/Makefile54
-rw-r--r--source/blender/editors/util/SConscript10
-rw-r--r--source/blender/editors/util/ed_util.c122
-rw-r--r--source/blender/editors/util/editmode_undo.c365
-rw-r--r--source/blender/editors/util/undo.c242
-rw-r--r--source/blender/editors/util/util_intern.h38
-rw-r--r--source/blender/editors/uvedit/Makefile55
-rw-r--r--source/blender/editors/uvedit/SConscript10
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c856
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h81
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c3147
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c4509
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.h97
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c1343
325 files changed, 274742 insertions, 0 deletions
diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt
new file mode 100644
index 00000000000..06b0fb4ab41
--- /dev/null
+++ b/source/blender/editors/CMakeLists.txt
@@ -0,0 +1,85 @@
+# $Id: CMakeLists.txt 12931 2007-12-17 18:20:48Z theeth $
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+FILE(GLOB SRC */*.c)
+
+SET(INC ../windowmanager
+ ../editors/include
+ ../../../intern/guardedalloc ../../../intern/memutil
+ ../blenlib ../makesdna ../makesrna ../blenkernel
+ ../include ../../../intern/bmfont ../imbuf ../render/extern/include
+ ../../../intern/bsp/extern ../radiosity/extern/include
+ ../../../intern/decimation/extern ../blenloader ../python
+ ../../kernel/gen_system ../../../intern/SoundSystem ../readstreamglue
+ ../quicktime ../../../intern/elbeem/extern
+ ../../../intern/ghost ../../../intern/opennl/extern ../../../extern/glew/include
+ ../nodes
+ ../gpu
+ ../blenfont
+ ${SDL_INC}
+)
+
+IF(WITH_INTERNATIONAL)
+ SET(INC ${INC} ../ftfont)
+ ADD_DEFINITIONS(-DINTERNATIONAL)
+ ADD_DEFINITIONS(-DFTGL_STATIC_LIBRARY)
+ENDIF(WITH_INTERNATIONAL)
+
+IF(WITH_OPENEXR)
+ ADD_DEFINITIONS(-DWITH_OPENEXR)
+ENDIF(WITH_OPENEXR)
+
+IF(WITH_OPENJPEG)
+ ADD_DEFINITIONS(-DWITH_OPENJPEG)
+ENDIF(WITH_OPENJPEG)
+
+IF(WITH_QUICKTIME)
+ SET(INC ${INC} ${QUICKTIME_INC})
+ ADD_DEFINITIONS(-DWITH_QUICKTIME)
+ENDIF(WITH_QUICKTIME)
+
+IF(WITH_FFMPEG)
+ SET(INC ${INC} ${FFMPEG_INC})
+ ADD_DEFINITIONS(-DWITH_FFMPEG)
+ENDIF(WITH_FFMPEG)
+
+IF(WITH_PYTHON)
+ SET(INC ${INC} ${PYTHON_INC})
+ELSE(WITH_PYTHON)
+ ADD_DEFINITIONS(-DDISABLE_PYTHON)
+ENDIF(WITH_PYTHON)
+
+IF(WIN32)
+ SET(INC ${INC} ${PTHREADS_INC})
+ENDIF(WIN32)
+
+# TODO buildinfo
+IF(BF_BUILDINFO)
+ ADD_DEFINITIONS(-DNAN_BUILDINFO)
+ENDIF(BF_BUILDINFO)
+
+BLENDERLIB_NOLIST(bf_editors "${SRC}" "${INC}")
+
diff --git a/source/blender/editors/Makefile b/source/blender/editors/Makefile
new file mode 100644
index 00000000000..8a819195fbd
--- /dev/null
+++ b/source/blender/editors/Makefile
@@ -0,0 +1,34 @@
+#
+# $Id: Makefile
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) Blender Foundation.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/editors
+DIRS = armature mesh animation object sculpt_paint datafiles transform screen curve gpencil physics preview uvedit space_outliner space_time space_view3d interface util space_api space_graph space_image space_node space_buttons space_info space_file space_sound space_action space_nla space_script space_text space_sequencer
+
+include nan_subdirs.mk
diff --git a/source/blender/editors/SConscript b/source/blender/editors/SConscript
new file mode 100644
index 00000000000..a99d21b19a4
--- /dev/null
+++ b/source/blender/editors/SConscript
@@ -0,0 +1,35 @@
+#!/usr/bin/python
+Import ('env')
+
+
+SConscript(['datafiles/SConscript',
+ 'space_api/SConscript',
+ 'util/SConscript',
+ 'interface/SConscript',
+ 'animation/SConscript',
+ 'armature/SConscript',
+ 'mesh/SConscript',
+ 'object/SConscript',
+ 'curve/SConscript',
+ 'gpencil/SConscript',
+ 'physics/SConscript',
+ 'preview/SConscript',
+ 'space_buttons/SConscript',
+ 'space_file/SConscript',
+ 'space_image/SConscript',
+ 'space_info/SConscript',
+ 'space_graph/SConscript',
+ 'space_node/SConscript',
+ 'space_outliner/SConscript',
+ 'space_time/SConscript',
+ 'space_view3d/SConscript',
+ 'space_sound/SConscript',
+ 'space_action/SConscript',
+ 'space_nla/SConscript',
+ 'space_script/SConscript',
+ 'space_text/SConscript',
+ 'space_sequencer/SConscript',
+ 'transform/SConscript',
+ 'screen/SConscript',
+ 'sculpt_paint/SConscript',
+ 'uvedit/SConscript'])
diff --git a/source/blender/editors/animation/Makefile b/source/blender/editors/animation/Makefile
new file mode 100644
index 00000000000..19b62891b63
--- /dev/null
+++ b/source/blender/editors/animation/Makefile
@@ -0,0 +1,54 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_animation
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/animation/SConscript b/source/blender/editors/animation/SConscript
new file mode 100644
index 00000000000..4597a612c7c
--- /dev/null
+++ b/source/blender/editors/animation/SConscript
@@ -0,0 +1,9 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+
+env.BlenderLib ( 'bf_editors_animation', sources, Split(incs), [], libtype=['core'], priority=[125] )
diff --git a/source/blender/editors/animation/anim_channels.c b/source/blender/editors/animation/anim_channels.c
new file mode 100644
index 00000000000..9e0e50a8de5
--- /dev/null
+++ b/source/blender/editors/animation/anim_channels.c
@@ -0,0 +1,1714 @@
+/**
+ * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_listBase.h"
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_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 "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_world_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "BKE_action.h"
+#include "BKE_depsgraph.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+#include "BKE_context.h"
+#include "BKE_utildefines.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframes_edit.h" // XXX move the select modes out of there!
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* ************************************************************************** */
+/* CHANNELS API */
+
+/* -------------------------- Internal Macros ------------------------------- */
+
+/* set/clear/toggle macro
+ * - channel - channel with a 'flag' member that we're setting
+ * - smode - 0=clear, 1=set, 2=toggle
+ * - sflag - bitflag to set
+ */
+#define ACHANNEL_SET_FLAG(channel, smode, sflag) \
+ { \
+ if (smode == ACHANNEL_SETFLAG_TOGGLE) (channel)->flag ^= (sflag); \
+ else if (smode == ACHANNEL_SETFLAG_ADD) (channel)->flag |= (sflag); \
+ else (channel)->flag &= ~(sflag); \
+ }
+
+/* set/clear/toggle macro, where the flag is negative
+ * - channel - channel with a 'flag' member that we're setting
+ * - smode - 0=clear, 1=set, 2=toggle
+ * - sflag - bitflag to set
+ */
+#define ACHANNEL_SET_FLAG_NEG(channel, smode, sflag) \
+ { \
+ if (smode == ACHANNEL_SETFLAG_TOGGLE) (channel)->flag ^= (sflag); \
+ else if (smode == ACHANNEL_SETFLAG_ADD) (channel)->flag &= ~(sflag); \
+ else (channel)->flag |= (sflag); \
+ }
+
+/* -------------------------- Exposed API ----------------------------------- */
+
+/* Set the given animation-channel as the active one for the active context */
+void ANIM_set_active_channel (void *data, short datatype, int filter, void *channel_data, short channel_type)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+
+ /* try to build list of filtered items */
+ // XXX we don't need/supply animcontext for now, since in this case, there's nothing really essential there that isn't already covered
+ ANIM_animdata_filter(NULL, &anim_data, filter, data, datatype);
+ if (anim_data.first == NULL)
+ return;
+
+ /* only clear the 'active' flag for the channels of the same type */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ /* skip if types don't match */
+ if (channel_type != ale->type)
+ continue;
+
+ /* flag to set depends on type */
+ switch (ale->type) {
+ case ANIMTYPE_GROUP:
+ {
+ bActionGroup *agrp= (bActionGroup *)ale->data;
+
+ ACHANNEL_SET_FLAG(agrp, ACHANNEL_SETFLAG_CLEAR, AGRP_ACTIVE);
+ }
+ break;
+ case ANIMTYPE_FCURVE:
+ {
+ FCurve *fcu= (FCurve *)ale->data;
+
+ ACHANNEL_SET_FLAG(fcu, ACHANNEL_SETFLAG_CLEAR, FCURVE_ACTIVE);
+ }
+ break;
+ }
+ }
+
+ /* set active flag */
+ if (channel_data) {
+ switch (channel_type) {
+ case ANIMTYPE_GROUP:
+ {
+ bActionGroup *agrp= (bActionGroup *)channel_data;
+ agrp->flag |= AGRP_ACTIVE;
+ }
+ break;
+ case ANIMTYPE_FCURVE:
+ {
+ FCurve *fcu= (FCurve *)channel_data;
+ fcu->flag |= FCURVE_ACTIVE;
+ }
+ break;
+ }
+ }
+
+ /* clean up */
+ BLI_freelistN(&anim_data);
+}
+
+/* Deselect all animation channels
+ * - data: pointer to datatype, as contained in bAnimContext
+ * - datatype: the type of data that 'data' represents (eAnimCont_Types)
+ * - test: check if deselecting instead of selecting
+ * - sel: eAnimChannels_SetFlag;
+ */
+void ANIM_deselect_anim_channels (void *data, short datatype, short test, short sel)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter= ANIMFILTER_VISIBLE;
+ ANIM_animdata_filter(NULL, &anim_data, filter, data, datatype);
+
+ /* See if we should be selecting or deselecting */
+ if (test) {
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ if (sel == 0)
+ break;
+
+ switch (ale->type) {
+ case ANIMTYPE_SCENE:
+ if (ale->flag & SCE_DS_SELECTED)
+ sel= ACHANNEL_SETFLAG_CLEAR;
+ break;
+ case ANIMTYPE_OBJECT:
+ if (ale->flag & SELECT)
+ sel= ACHANNEL_SETFLAG_CLEAR;
+ break;
+ case ANIMTYPE_FILLACTD:
+ if (ale->flag & ACT_SELECTED)
+ sel= ACHANNEL_SETFLAG_CLEAR;
+ break;
+ case ANIMTYPE_GROUP:
+ if (ale->flag & AGRP_SELECTED)
+ sel= ACHANNEL_SETFLAG_CLEAR;
+ break;
+ case ANIMTYPE_FCURVE:
+ if (ale->flag & FCURVE_SELECTED)
+ sel= ACHANNEL_SETFLAG_CLEAR;
+ break;
+ }
+ }
+ }
+
+ /* Now set the flags */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ switch (ale->type) {
+ case ANIMTYPE_SCENE:
+ {
+ Scene *scene= (Scene *)ale->data;
+
+ ACHANNEL_SET_FLAG(scene, sel, SCE_DS_SELECTED);
+ }
+ break;
+ case ANIMTYPE_OBJECT:
+ {
+ Base *base= (Base *)ale->data;
+ Object *ob= base->object;
+
+ ACHANNEL_SET_FLAG(base, sel, SELECT);
+ ACHANNEL_SET_FLAG(ob, sel, SELECT);
+ }
+ break;
+ case ANIMTYPE_FILLACTD:
+ {
+ bAction *act= (bAction *)ale->data;
+
+ ACHANNEL_SET_FLAG(act, sel, ACT_SELECTED);
+ }
+ break;
+ case ANIMTYPE_GROUP:
+ {
+ bActionGroup *agrp= (bActionGroup *)ale->data;
+
+ ACHANNEL_SET_FLAG(agrp, sel, AGRP_SELECTED);
+ agrp->flag &= ~AGRP_ACTIVE;
+ }
+ break;
+ case ANIMTYPE_FCURVE:
+ {
+ FCurve *fcu= (FCurve *)ale->data;
+
+ ACHANNEL_SET_FLAG(fcu, sel, FCURVE_SELECTED);
+ fcu->flag &= ~FCURVE_ACTIVE;
+ }
+ break;
+ }
+ }
+
+ /* Cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* ************************************************************************** */
+/* OPERATORS */
+
+/* ****************** Rearrange Channels Operator ******************* */
+/* This operator only works for Action Editor mode for now, as having it elsewhere makes things difficult */
+
+#if 0 // XXX old animation system - needs to be updated for new system...
+
+/* constants for channel rearranging */
+/* WARNING: don't change exising ones without modifying rearrange func accordingly */
+enum {
+ REARRANGE_ACTCHAN_TOP= -2,
+ REARRANGE_ACTCHAN_UP= -1,
+ REARRANGE_ACTCHAN_DOWN= 1,
+ REARRANGE_ACTCHAN_BOTTOM= 2
+};
+
+/* make sure all action-channels belong to a group (and clear action's list) */
+static void split_groups_action_temp (bAction *act, bActionGroup *tgrp)
+{
+ bActionChannel *achan;
+ bActionGroup *agrp;
+
+ /* Separate action-channels into lists per group */
+ for (agrp= act->groups.first; agrp; agrp= agrp->next) {
+ if (agrp->channels.first) {
+ achan= agrp->channels.last;
+ act->chanbase.first= achan->next;
+
+ achan= agrp->channels.first;
+ achan->prev= NULL;
+
+ achan= agrp->channels.last;
+ achan->next= NULL;
+ }
+ }
+
+ /* Initialise memory for temp-group */
+ memset(tgrp, 0, sizeof(bActionGroup));
+ tgrp->flag |= (AGRP_EXPANDED|AGRP_TEMP);
+ strcpy(tgrp->name, "#TempGroup");
+
+ /* Move any action-channels not already moved, to the temp group */
+ if (act->chanbase.first) {
+ /* start of list */
+ achan= act->chanbase.first;
+ achan->prev= NULL;
+ tgrp->channels.first= achan;
+ act->chanbase.first= NULL;
+
+ /* end of list */
+ achan= act->chanbase.last;
+ achan->next= NULL;
+ tgrp->channels.last= achan;
+ act->chanbase.last= NULL;
+ }
+
+ /* Add temp-group to list */
+ BLI_addtail(&act->groups, tgrp);
+}
+
+/* link lists of channels that groups have */
+static void join_groups_action_temp (bAction *act)
+{
+ bActionGroup *agrp;
+ bActionChannel *achan;
+
+ for (agrp= act->groups.first; agrp; agrp= agrp->next) {
+ ListBase tempGroup;
+
+ /* add list of channels to action's channels */
+ tempGroup= agrp->channels;
+ addlisttolist(&act->chanbase, &agrp->channels);
+ agrp->channels= tempGroup;
+
+ /* clear moved flag */
+ agrp->flag &= ~AGRP_MOVED;
+
+ /* if temp-group... remove from list (but don't free as it's on the stack!) */
+ if (agrp->flag & AGRP_TEMP) {
+ BLI_remlink(&act->groups, agrp);
+ break;
+ }
+ }
+
+ /* clear "moved" flag from all achans */
+ for (achan= act->chanbase.first; achan; achan= achan->next)
+ achan->flag &= ~ACHAN_MOVED;
+}
+
+
+static short rearrange_actchannel_is_ok (Link *channel, short type)
+{
+ if (type == ANIMTYPE_GROUP) {
+ bActionGroup *agrp= (bActionGroup *)channel;
+
+ if (SEL_AGRP(agrp) && !(agrp->flag & AGRP_MOVED))
+ return 1;
+ }
+ else if (type == ANIMTYPE_ACHAN) {
+ bActionChannel *achan= (bActionChannel *)channel;
+
+ if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED))
+ return 1;
+ }
+
+ return 0;
+}
+
+static short rearrange_actchannel_after_ok (Link *channel, short type)
+{
+ if (type == ANIMTYPE_GROUP) {
+ bActionGroup *agrp= (bActionGroup *)channel;
+
+ if (agrp->flag & AGRP_TEMP)
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static short rearrange_actchannel_top (ListBase *list, Link *channel, short type)
+{
+ if (rearrange_actchannel_is_ok(channel, type)) {
+ /* take it out off the chain keep data */
+ BLI_remlink(list, channel);
+
+ /* make it first element */
+ BLI_insertlinkbefore(list, list->first, channel);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static short rearrange_actchannel_up (ListBase *list, Link *channel, short type)
+{
+ if (rearrange_actchannel_is_ok(channel, type)) {
+ Link *prev= channel->prev;
+
+ if (prev) {
+ /* take it out off the chain keep data */
+ BLI_remlink(list, channel);
+
+ /* push it up */
+ BLI_insertlinkbefore(list, prev, channel);
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static short rearrange_actchannel_down (ListBase *list, Link *channel, short type)
+{
+ if (rearrange_actchannel_is_ok(channel, type)) {
+ Link *next = (channel->next) ? channel->next->next : NULL;
+
+ if (next) {
+ /* take it out off the chain keep data */
+ BLI_remlink(list, channel);
+
+ /* move it down */
+ BLI_insertlinkbefore(list, next, channel);
+
+ return 1;
+ }
+ else if (rearrange_actchannel_after_ok(list->last, type)) {
+ /* take it out off the chain keep data */
+ BLI_remlink(list, channel);
+
+ /* add at end */
+ BLI_addtail(list, channel);
+
+ return 1;
+ }
+ else {
+ /* take it out off the chain keep data */
+ BLI_remlink(list, channel);
+
+ /* add just before end */
+ BLI_insertlinkbefore(list, list->last, channel);
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static short rearrange_actchannel_bottom (ListBase *list, Link *channel, short type)
+{
+ if (rearrange_actchannel_is_ok(channel, type)) {
+ if (rearrange_actchannel_after_ok(list->last, type)) {
+ /* take it out off the chain keep data */
+ BLI_remlink(list, channel);
+
+ /* add at end */
+ BLI_addtail(list, channel);
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+/* Change the order of action-channels
+ * mode: REARRANGE_ACTCHAN_*
+ */
+static void rearrange_action_channels (bAnimContext *ac, short mode)
+{
+ bAction *act;
+ bActionChannel *achan, *chan;
+ bActionGroup *agrp, *grp;
+ bActionGroup tgrp;
+
+ short (*rearrange_func)(ListBase *, Link *, short);
+ short do_channels = 1;
+
+ /* Get the active action, exit if none are selected */
+ act= (bAction *)ac->data;
+
+ /* exit if invalid mode */
+ switch (mode) {
+ case REARRANGE_ACTCHAN_TOP:
+ rearrange_func= rearrange_actchannel_top;
+ break;
+ case REARRANGE_ACTCHAN_UP:
+ rearrange_func= rearrange_actchannel_up;
+ break;
+ case REARRANGE_ACTCHAN_DOWN:
+ rearrange_func= rearrange_actchannel_down;
+ break;
+ case REARRANGE_ACTCHAN_BOTTOM:
+ rearrange_func= rearrange_actchannel_bottom;
+ break;
+ default:
+ return;
+ }
+
+ /* make sure we're only operating with groups */
+ split_groups_action_temp(act, &tgrp);
+
+ /* rearrange groups first (and then, only consider channels if the groups weren't moved) */
+ #define GET_FIRST(list) ((mode > 0) ? (list.first) : (list.last))
+ #define GET_NEXT(item) ((mode > 0) ? (item->next) : (item->prev))
+
+ for (agrp= GET_FIRST(act->groups); agrp; agrp= grp) {
+ /* Get next group to consider */
+ grp= GET_NEXT(agrp);
+
+ /* try to do group first */
+ if (rearrange_func(&act->groups, (Link *)agrp, ANIMTYPE_GROUP)) {
+ do_channels= 0;
+ agrp->flag |= AGRP_MOVED;
+ }
+ }
+
+ if (do_channels) {
+ for (agrp= GET_FIRST(act->groups); agrp; agrp= grp) {
+ /* Get next group to consider */
+ grp= GET_NEXT(agrp);
+
+ /* only consider action-channels if they're visible (group expanded) */
+ if (EXPANDED_AGRP(agrp)) {
+ for (achan= GET_FIRST(agrp->channels); achan; achan= chan) {
+ /* Get next channel to consider */
+ chan= GET_NEXT(achan);
+
+ /* Try to do channel */
+ if (rearrange_func(&agrp->channels, (Link *)achan, ANIMTYPE_ACHAN))
+ achan->flag |= ACHAN_MOVED;
+ }
+ }
+ }
+ }
+ #undef GET_FIRST
+ #undef GET_NEXT
+
+ /* assemble lists into one list (and clear moved tags) */
+ join_groups_action_temp(act);
+}
+
+/* ------------------- */
+
+static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data - only for Action Editor (for now) */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ if (ac.datatype != ANIMCONT_ACTION)
+ return OPERATOR_PASS_THROUGH;
+
+ /* get mode, then rearrange channels */
+ mode= RNA_enum_get(op->ptr, "direction");
+ rearrange_action_channels(&ac, mode);
+
+ /* set notifier tha things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void ANIM_OT_channels_move_up (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Move Channel(s) Up";
+ ot->idname= "ANIM_OT_channels_move_up";
+
+ /* api callbacks */
+ ot->exec= animchannels_rearrange_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", NULL /* XXX add enum for this */, REARRANGE_ACTCHAN_UP, "Direction", "");
+}
+
+void ANIM_OT_channels_move_down (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Move Channel(s) Down";
+ ot->idname= "ANIM_OT_channels_move_down";
+
+ /* api callbacks */
+ ot->exec= animchannels_rearrange_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", NULL /* XXX add enum for this */, REARRANGE_ACTCHAN_DOWN, "Direction", "");
+}
+
+void ANIM_OT_channels_move_top (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Move Channel(s) to Top";
+ ot->idname= "ANIM_OT_channels_move_to_top";
+
+ /* api callbacks */
+ ot->exec= animchannels_rearrange_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", NULL /* XXX add enum for this */, REARRANGE_ACTCHAN_TOP, "Direction", "");
+}
+
+void ANIM_OT_channels_move_bottom (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Move Channel(s) to Bottom";
+ ot->idname= "ANIM_OT_channels_move_to_bottom";
+
+ /* api callbacks */
+ ot->exec= animchannels_rearrange_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", NULL /* XXX add enum for this */, REARRANGE_ACTCHAN_BOTTOM, "Direction", "");
+}
+
+#endif // XXX old animation system - needs to be updated for new system...
+
+
+/* ******************** Toggle Channel Visibility Operator *********************** */
+
+static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ short vis= ACHANNEL_SETFLAG_ADD;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* See if we should be making showing all selected or hiding */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ if (vis == ACHANNEL_SETFLAG_CLEAR)
+ break;
+
+ if (ale->flag & FCURVE_VISIBLE)
+ vis= ACHANNEL_SETFLAG_CLEAR;
+ }
+
+ /* Now set the flags */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ FCurve *fcu= (FCurve *)ale->data;
+ ACHANNEL_SET_FLAG(fcu, vis, FCURVE_VISIBLE);
+ }
+
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+
+ /* set notifier tha things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
+
+ return OPERATOR_FINISHED;
+}
+
+void ANIM_OT_channels_visibility_toggle (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Toggle Visibility";
+ ot->idname= "ANIM_OT_channels_visibility_toggle";
+
+ /* api callbacks */
+ ot->exec= animchannels_visibility_toggle_exec;
+ ot->poll= ED_operator_ipo_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ********************** Set Flags Operator *********************** */
+
+enum {
+// ACHANNEL_SETTING_SELECT = 0,
+ ACHANNEL_SETTING_PROTECT = 1,
+ ACHANNEL_SETTING_MUTE,
+ ACHANNEL_SETTING_VISIBLE,
+ ACHANNEL_SETTING_EXPAND,
+} eAnimChannel_Settings;
+
+/* defines for setting animation-channel flags */
+EnumPropertyItem prop_animchannel_setflag_types[] = {
+ {ACHANNEL_SETFLAG_CLEAR, "DISABLE", "Disable", ""},
+ {ACHANNEL_SETFLAG_ADD, "ENABLE", "Enable", ""},
+ {ACHANNEL_SETFLAG_TOGGLE, "TOGGLE", "Toggle", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* defines for set animation-channel settings */
+EnumPropertyItem prop_animchannel_settings_types[] = {
+ {ACHANNEL_SETTING_PROTECT, "PROTECT", "Protect", ""},
+ {ACHANNEL_SETTING_MUTE, "MUTE", "Mute", ""},
+ {0, NULL, NULL, NULL}
+};
+
+
+/* ------------------- */
+
+/* macro to be used in setflag_anim_channels */
+#define ASUBCHANNEL_SEL_OK(ale) ( (onlysel == 0) || \
+ ((ale->id) && (GS(ale->id->name)==ID_OB) && (((Object *)ale->id)->flag & SELECT)) )
+
+/* Set/clear a particular flag (setting) for all selected + visible channels
+ * setting: the setting to modify
+ * mode: eAnimChannels_SetFlag
+ * onlysel: only selected channels get the flag set
+ */
+static void setflag_anim_channels (bAnimContext *ac, short setting, short mode, short onlysel)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
+ if (onlysel) filter |= ANIMFILTER_SEL;
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* affect selected channels */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ switch (ale->type) {
+ case ANIMTYPE_OBJECT:
+ {
+ Base *base= (Base *)ale->data;
+ Object *ob= base->object;
+
+ if (setting == ACHANNEL_SETTING_EXPAND) {
+ // XXX - settings should really be moved out of ob->nlaflag
+ if (mode == ACHANNEL_SETFLAG_TOGGLE) ob->nlaflag ^= OB_ADS_COLLAPSED;
+ else if (mode == ACHANNEL_SETFLAG_ADD) ob->nlaflag &= ~OB_ADS_COLLAPSED;
+ else ob->nlaflag |= OB_ADS_COLLAPSED;
+ }
+ }
+ break;
+
+ case ANIMTYPE_FILLACTD:
+ {
+ bAction *act= (bAction *)ale->data;
+
+ if (ASUBCHANNEL_SEL_OK(ale)) {
+ if (setting == ACHANNEL_SETTING_EXPAND) {
+ ACHANNEL_SET_FLAG_NEG(act, mode, ACT_COLLAPSED);
+ }
+ }
+ }
+ break;
+ case ANIMTYPE_FILLDRIVERS:
+ {
+ AnimData *adt= (AnimData *)ale->data;
+
+ if (ASUBCHANNEL_SEL_OK(ale)) {
+ if (setting == ACHANNEL_SETTING_EXPAND) {
+ ACHANNEL_SET_FLAG_NEG(adt, mode, ADT_DRIVERS_COLLAPSED);
+ }
+ }
+ }
+ break;
+ case ANIMTYPE_FILLMATD:
+ {
+ Object *ob= (Object *)ale->data;
+
+ // XXX - settings should really be moved out of ob->nlaflag
+ if ((onlysel == 0) || (ob->flag & SELECT)) {
+ if (setting == ACHANNEL_SETTING_EXPAND) {
+ if (mode == ACHANNEL_SETFLAG_TOGGLE) ob->nlaflag ^= OB_ADS_SHOWMATS;
+ else if (mode == ACHANNEL_SETFLAG_ADD) ob->nlaflag |= OB_ADS_SHOWMATS;
+ else ob->nlaflag &= ~OB_ADS_SHOWMATS;
+ }
+ }
+ }
+ break;
+
+ case ANIMTYPE_DSMAT:
+ {
+ Material *ma= (Material *)ale->data;
+
+ if (ASUBCHANNEL_SEL_OK(ale)) {
+ if (setting == ACHANNEL_SETTING_EXPAND) {
+ ACHANNEL_SET_FLAG(ma, mode, MA_DS_EXPAND);
+ }
+ }
+ }
+ break;
+ case ANIMTYPE_DSLAM:
+ {
+ Lamp *la= (Lamp *)ale->data;
+
+ if (ASUBCHANNEL_SEL_OK(ale)) {
+ if (setting == ACHANNEL_SETTING_EXPAND) {
+ ACHANNEL_SET_FLAG(la, mode, LA_DS_EXPAND);
+ }
+ }
+ }
+ break;
+ case ANIMTYPE_DSCAM:
+ {
+ Camera *ca= (Camera *)ale->data;
+
+ if (ASUBCHANNEL_SEL_OK(ale)) {
+ if (setting == ACHANNEL_SETTING_EXPAND) {
+ ACHANNEL_SET_FLAG(ca, mode, CAM_DS_EXPAND);
+ }
+ }
+ }
+ break;
+ case ANIMTYPE_DSCUR:
+ {
+ Curve *cu= (Curve *)ale->data;
+
+ if (ASUBCHANNEL_SEL_OK(ale)) {
+ if (setting == ACHANNEL_SETTING_EXPAND) {
+ ACHANNEL_SET_FLAG(cu, mode, CU_DS_EXPAND);
+ }
+ }
+ }
+ break;
+ case ANIMTYPE_DSSKEY:
+ {
+ Key *key= (Key *)ale->data;
+
+ if (ASUBCHANNEL_SEL_OK(ale)) {
+ if (setting == ACHANNEL_SETTING_EXPAND) {
+ ACHANNEL_SET_FLAG(key, mode, KEYBLOCK_DS_EXPAND);
+ }
+ }
+ }
+ break;
+ case ANIMTYPE_DSWOR:
+ {
+ World *wo= (World *)ale->data;
+
+ if (ASUBCHANNEL_SEL_OK(ale)) {
+ if (setting == ACHANNEL_SETTING_EXPAND) {
+ ACHANNEL_SET_FLAG(wo, mode, WO_DS_EXPAND);
+ }
+ }
+ }
+ break;
+
+ case ANIMTYPE_GROUP:
+ {
+ bActionGroup *agrp= (bActionGroup *)ale->data;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_PROTECT:
+ ACHANNEL_SET_FLAG(agrp, mode, AGRP_PROTECTED);
+ break;
+ case ACHANNEL_SETTING_EXPAND:
+ ACHANNEL_SET_FLAG(agrp, mode, AGRP_EXPANDED);
+ break;
+ }
+ }
+ break;
+ case ANIMTYPE_FCURVE:
+ {
+ FCurve *fcu= (FCurve *)ale->data;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_MUTE:
+ ACHANNEL_SET_FLAG(fcu, mode, FCURVE_MUTED);
+ break;
+ case ACHANNEL_SETTING_PROTECT:
+ ACHANNEL_SET_FLAG(fcu, mode, FCURVE_PROTECTED);
+ break;
+ case ACHANNEL_SETTING_VISIBLE:
+ ACHANNEL_SET_FLAG(fcu, mode, FCURVE_VISIBLE);
+ break;
+ }
+ }
+ break;
+ case ANIMTYPE_GPLAYER:
+ {
+ bGPDlayer *gpl= (bGPDlayer *)ale->data;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_MUTE:
+ ACHANNEL_SET_FLAG(gpl, mode, GP_LAYER_HIDE);
+ break;
+ case ACHANNEL_SETTING_PROTECT:
+ ACHANNEL_SET_FLAG(gpl, mode, GP_LAYER_LOCKED);
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int animchannels_setflag_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode, setting;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* mode (eAnimChannels_SetFlag), setting (eAnimChannel_Settings) */
+ mode= RNA_enum_get(op->ptr, "mode");
+ setting= RNA_enum_get(op->ptr, "type");
+
+ /* modify setting */
+ setflag_anim_channels(&ac, setting, mode, 1);
+
+ /* set notifier tha things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void ANIM_OT_channels_setting_enable (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Enable Channel Setting";
+ ot->idname= "ANIM_OT_channels_setting_enable";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= animchannels_setflag_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ /* flag-setting mode */
+ RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_ADD, "Mode", "");
+ /* setting to set */
+ RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
+}
+
+void ANIM_OT_channels_setting_disable (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Disable Channel Setting";
+ ot->idname= "ANIM_OT_channels_setting_disable";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= animchannels_setflag_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ /* flag-setting mode */
+ RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_CLEAR, "Mode", "");
+ /* setting to set */
+ RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
+}
+
+void ANIM_OT_channels_setting_toggle (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Toggle Channel Setting";
+ ot->idname= "ANIM_OT_channels_setting_toggle";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= animchannels_setflag_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ /* flag-setting mode */
+ RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", "");
+ /* setting to set */
+ RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
+}
+
+// XXX currently, this is a separate operator, but perhaps we could in future specify in keymaps whether to call invoke or exec?
+void ANIM_OT_channels_editable_toggle (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Toggle Channel Editability";
+ ot->idname= "ANIM_OT_channels_editable_toggle";
+
+ /* api callbacks */
+ ot->exec= animchannels_setflag_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ /* flag-setting mode */
+ RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", "");
+ /* setting to set */
+ RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, ACHANNEL_SETTING_PROTECT, "Type", "");
+}
+
+/* ********************** Expand Channels Operator *********************** */
+
+static int animchannels_expand_exec (bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short onlysel= 1;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* only affect selected channels? */
+ if (RNA_boolean_get(op->ptr, "all"))
+ onlysel= 0;
+
+ /* modify setting */
+ setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_ADD, onlysel);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
+
+ return OPERATOR_FINISHED;
+}
+
+void ANIM_OT_channels_expand (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Expand Channels";
+ ot->idname= "ANIM_OT_channels_expand";
+
+ /* api callbacks */
+ ot->exec= animchannels_expand_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "all", 0, "All", "Expand all channels (not just selected ones)");
+}
+
+/* ********************** Collapse Channels Operator *********************** */
+
+static int animchannels_collapse_exec (bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short onlysel= 1;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* only affect selected channels? */
+ if (RNA_boolean_get(op->ptr, "all"))
+ onlysel= 0;
+
+ /* modify setting */
+ setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_CLEAR, onlysel);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
+
+ return OPERATOR_FINISHED;
+}
+
+void ANIM_OT_channels_collapse (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Collapse Channels";
+ ot->idname= "ANIM_OT_channels_collapse";
+
+ /* api callbacks */
+ ot->exec= animchannels_collapse_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "all", 0, "All", "Collapse all channels (not just selected ones)");
+}
+
+/* ********************** Select All Operator *********************** */
+
+static int animchannels_deselectall_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* 'standard' behaviour - check if selected, then apply relevant selection */
+ if (RNA_boolean_get(op->ptr, "invert"))
+ ANIM_deselect_anim_channels(ac.data, ac.datatype, 0, ACHANNEL_SETFLAG_TOGGLE);
+ else
+ ANIM_deselect_anim_channels(ac.data, ac.datatype, 1, ACHANNEL_SETFLAG_ADD);
+
+ /* set notifier tha things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
+
+ return OPERATOR_FINISHED;
+}
+
+void ANIM_OT_channels_select_all_toggle (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select All";
+ ot->idname= "ANIM_OT_channels_select_all_toggle";
+
+ /* api callbacks */
+ ot->exec= animchannels_deselectall_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
+}
+
+/* ******************** Borderselect Operator *********************** */
+
+static void borderselect_anim_channels (bAnimContext *ac, rcti *rect, short selectmode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ View2D *v2d= &ac->ar->v2d;
+ rctf rectf;
+ float ymin=0, ymax=(float)(-ACHANNEL_HEIGHT);
+
+ /* convert border-region to view coordinates */
+ UI_view2d_region_to_view(v2d, rect->xmin, rect->ymin+2, &rectf.xmin, &rectf.ymin);
+ UI_view2d_region_to_view(v2d, rect->xmax, rect->ymax-2, &rectf.xmax, &rectf.ymax);
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop over data, doing border select */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ ymin= ymax - ACHANNEL_STEP;
+
+ /* if channel is within border-select region, alter it */
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
+ /* only the following types can be selected */
+ switch (ale->type) {
+ case ANIMTYPE_OBJECT: /* object */
+ {
+ Base *base= (Base *)ale->data;
+ Object *ob= base->object;
+
+ ACHANNEL_SET_FLAG(base, selectmode, SELECT);
+ ACHANNEL_SET_FLAG(ob, selectmode, SELECT);
+ }
+ break;
+ case ANIMTYPE_GROUP: /* action group */
+ {
+ bActionGroup *agrp= (bActionGroup *)ale->data;
+
+ ACHANNEL_SET_FLAG(agrp, selectmode, AGRP_SELECTED);
+ agrp->flag &= ~AGRP_ACTIVE;
+ }
+ break;
+ case ANIMTYPE_FCURVE: /* F-Curve channel */
+ {
+ FCurve *fcu = (FCurve *)ale->data;
+
+ ACHANNEL_SET_FLAG(fcu, selectmode, FCURVE_SELECTED);
+ }
+ break;
+ case ANIMTYPE_GPLAYER: /* grease-pencil layer */
+ {
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+
+ ACHANNEL_SET_FLAG(gpl, selectmode, GP_LAYER_SELECT);
+ }
+ break;
+ }
+ }
+
+ /* set minimum extent to be the maximum of the next channel */
+ ymax= ymin;
+ }
+
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int animchannels_borderselect_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ rcti rect;
+ short selectmode=0;
+ int event;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get settings from operator */
+ rect.xmin= RNA_int_get(op->ptr, "xmin");
+ rect.ymin= RNA_int_get(op->ptr, "ymin");
+ rect.xmax= RNA_int_get(op->ptr, "xmax");
+ rect.ymax= RNA_int_get(op->ptr, "ymax");
+
+ event= RNA_int_get(op->ptr, "event_type");
+ if (event == LEFTMOUSE) // FIXME... hardcoded
+ selectmode = ACHANNEL_SETFLAG_ADD;
+ else
+ selectmode = ACHANNEL_SETFLAG_CLEAR;
+
+ /* apply borderselect animation channels */
+ borderselect_anim_channels(&ac, &rect, selectmode);
+
+ return OPERATOR_FINISHED;
+}
+
+void ANIM_OT_channels_select_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Border Select";
+ ot->idname= "ANIM_OT_channels_select_border";
+
+ /* api callbacks */
+ ot->invoke= WM_border_select_invoke;
+ ot->exec= animchannels_borderselect_exec;
+ ot->modal= WM_border_select_modal;
+
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* rna */
+ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+}
+
+/* ******************** Mouse-Click Operator *********************** */
+/* Depending on the channel that was clicked on, the mouse click will activate whichever
+ * part of the channel is relevant.
+ *
+ * NOTE: eventually, this should probably be phased out when many of these things are replaced with buttons
+ */
+
+static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, short selectmode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get the channel that was clicked on */
+ /* filter channels */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
+ filter= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get channel from index */
+ ale= BLI_findlink(&anim_data, channel_index);
+ if (ale == NULL) {
+ /* channel not found */
+ printf("Error: animation channel (index = %d) not found in mouse_anim_channels() \n", channel_index);
+
+ BLI_freelistN(&anim_data);
+ return;
+ }
+
+ /* selectmode -1 is a special case for ActionGroups only, which selects all of the channels underneath it only... */
+ // TODO: should this feature be extended to work with other channel types too?
+ if ((selectmode == -1) && (ale->type != ANIMTYPE_GROUP)) {
+ /* normal channels should not behave normally in this case */
+ BLI_freelistN(&anim_data);
+ return;
+ }
+
+ /* action to take depends on what channel we've got */
+ switch (ale->type) {
+ case ANIMTYPE_SCENE:
+ {
+ Scene *sce= (Scene *)ale->data;
+
+ if (x < 16) {
+ /* toggle expand */
+ sce->flag ^= SCE_DS_COLLAPSED;
+ }
+ else {
+ /* set selection status */
+ if (selectmode == SELECT_INVERT) {
+ /* swap select */
+ sce->flag ^= SCE_DS_SELECTED;
+ }
+ else {
+ sce->flag |= SCE_DS_SELECTED;
+ }
+ }
+ }
+ break;
+ case ANIMTYPE_OBJECT:
+ {
+ bDopeSheet *ads= (bDopeSheet *)ac->data;
+ Scene *sce= (Scene *)ads->source;
+ Base *base= (Base *)ale->data;
+ Object *ob= base->object;
+
+ if (x < 16) {
+ /* toggle expand */
+ ob->nlaflag ^= OB_ADS_COLLAPSED; // XXX
+ }
+ else {
+ /* set selection status */
+ if (selectmode == SELECT_INVERT) {
+ /* swap select */
+ base->flag ^= SELECT;
+ ob->flag= base->flag;
+ }
+ else {
+ Base *b;
+
+ /* deleselect all */
+ for (b= sce->base.first; b; b= b->next) {
+ b->flag &= ~SELECT;
+ b->object->flag= b->flag;
+ }
+
+ /* select object now */
+ base->flag |= SELECT;
+ ob->flag |= SELECT;
+ }
+
+ /* xxx should be ED_base_object_activate(), but we need context pointer for that... */
+ //set_active_base(base);
+ }
+ }
+ break;
+ case ANIMTYPE_FILLACTD:
+ {
+ bAction *act= (bAction *)ale->data;
+ act->flag ^= ACT_COLLAPSED;
+ }
+ break;
+ case ANIMTYPE_FILLDRIVERS:
+ {
+ AnimData *adt= (AnimData* )ale->data;
+ adt->flag ^= ADT_DRIVERS_COLLAPSED;
+ }
+ break;
+ case ANIMTYPE_FILLMATD:
+ {
+ Object *ob= (Object *)ale->data;
+ ob->nlaflag ^= OB_ADS_SHOWMATS; // XXX
+ }
+ break;
+
+ case ANIMTYPE_DSMAT:
+ {
+ Material *ma= (Material *)ale->data;
+ ma->flag ^= MA_DS_EXPAND;
+ }
+ break;
+ case ANIMTYPE_DSLAM:
+ {
+ Lamp *la= (Lamp *)ale->data;
+ la->flag ^= LA_DS_EXPAND;
+ }
+ break;
+ case ANIMTYPE_DSCAM:
+ {
+ Camera *ca= (Camera *)ale->data;
+ ca->flag ^= CAM_DS_EXPAND;
+ }
+ break;
+ case ANIMTYPE_DSCUR:
+ {
+ Curve *cu= (Curve *)ale->data;
+ cu->flag ^= CU_DS_EXPAND;
+ }
+ break;
+ case ANIMTYPE_DSSKEY:
+ {
+ Key *key= (Key *)ale->data;
+ key->flag ^= KEYBLOCK_DS_EXPAND;
+ }
+ break;
+ case ANIMTYPE_DSWOR:
+ {
+ World *wo= (World *)ale->data;
+ wo->flag ^= WO_DS_EXPAND;
+ }
+ break;
+
+ case ANIMTYPE_GROUP:
+ {
+ bActionGroup *agrp= (bActionGroup *)ale->data;
+ short offset= (ELEM3(ac->datatype, ANIMCONT_DOPESHEET, ANIMCONT_FCURVES, ANIMCONT_DRIVERS))? 18 : 0;
+
+ if ((x < (offset+17)) && (agrp->channels.first)) {
+ /* toggle expand */
+ agrp->flag ^= AGRP_EXPANDED;
+ }
+ else if (x >= (ACHANNEL_NAMEWIDTH-ACHANNEL_BUTTON_WIDTH)) {
+ /* toggle protection/locking */
+ agrp->flag ^= AGRP_PROTECTED;
+ }
+ else {
+ /* select/deselect group */
+ if (selectmode == SELECT_INVERT) {
+ /* inverse selection status of this group only */
+ agrp->flag ^= AGRP_SELECTED;
+ }
+ else if (selectmode == -1) {
+ /* select all in group (and deselect everthing else) */
+ FCurve *fcu;
+
+ /* deselect all other channels */
+ ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+
+ /* only select channels in group and group itself */
+ for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next)
+ fcu->flag |= FCURVE_SELECTED;
+ agrp->flag |= AGRP_SELECTED;
+ }
+ else {
+ /* select group by itself */
+ ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ agrp->flag |= AGRP_SELECTED;
+ }
+
+ /* if group is selected now, make group the 'active' one in the visible list */
+ if (agrp->flag & AGRP_SELECTED)
+ ANIM_set_active_channel(ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
+ }
+ }
+ break;
+ case ANIMTYPE_FCURVE:
+ {
+ FCurve *fcu= (FCurve *)ale->data;
+ short offset;
+
+ if (ac->datatype != ANIMCONT_ACTION) {
+ /* for now, special case for materials */
+ if (ale->ownertype == ANIMTYPE_DSMAT)
+ offset= 21;
+ else
+ offset= 18;
+ }
+ else
+ offset = 0;
+
+ if (x >= (ACHANNEL_NAMEWIDTH-ACHANNEL_BUTTON_WIDTH)) {
+ /* toggle protection (only if there's a toggle there) */
+ if (fcu->bezt)
+ fcu->flag ^= FCURVE_PROTECTED;
+ }
+ else if (x >= (ACHANNEL_NAMEWIDTH-2*ACHANNEL_BUTTON_WIDTH)) {
+ /* toggle mute */
+ fcu->flag ^= FCURVE_MUTED;
+ }
+ else if ((x < (offset+17)) && (ac->spacetype==SPACE_IPO)) {
+ /* toggle visibility */
+ fcu->flag ^= FCURVE_VISIBLE;
+ }
+ else {
+ /* select/deselect */
+ if (selectmode == SELECT_INVERT) {
+ /* inverse selection status of this F-Curve only */
+ fcu->flag ^= FCURVE_SELECTED;
+ }
+ else {
+ /* select F-Curve by itself */
+ ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ fcu->flag |= FCURVE_SELECTED;
+ }
+
+ /* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */
+ if (fcu->flag & FCURVE_SELECTED)
+ ANIM_set_active_channel(ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
+ }
+ }
+ break;
+ case ANIMTYPE_GPDATABLOCK:
+ {
+ bGPdata *gpd= (bGPdata *)ale->data;
+
+ /* toggle expand */
+ gpd->flag ^= GP_DATA_EXPAND;
+ }
+ break;
+ case ANIMTYPE_GPLAYER:
+ {
+#if 0 // XXX future of this is unclear
+ bGPdata *gpd= (bGPdata *)ale->owner;
+ bGPDlayer *gpl= (bGPDlayer *)ale->data;
+
+ if (x >= (ACHANNEL_NAMEWIDTH-16)) {
+ /* toggle lock */
+ gpl->flag ^= GP_LAYER_LOCKED;
+ }
+ else if (x >= (ACHANNEL_NAMEWIDTH-32)) {
+ /* toggle hide */
+ gpl->flag ^= GP_LAYER_HIDE;
+ }
+ else {
+ /* select/deselect */
+ //if (G.qual & LR_SHIFTKEY) {
+ //select_gplayer_channel(gpd, gpl, SELECT_INVERT);
+ //}
+ //else {
+ //deselect_gpencil_layers(data, 0);
+ //select_gplayer_channel(gpd, gpl, SELECT_INVERT);
+ //}
+ }
+#endif // XXX future of this is unclear
+ }
+ break;
+ case ANIMTYPE_SHAPEKEY:
+ /* TODO: shapekey channels cannot be selected atm... */
+ break;
+ default:
+ printf("Error: Invalid channel type in mouse_anim_channels() \n");
+ }
+
+ /* free channels */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+/* handle clicking */
+static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ bAnimContext ac;
+ Scene *scene;
+ ARegion *ar;
+ View2D *v2d;
+ int mval[2], channel_index;
+ short selectmode;
+ float x, y;
+
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get useful pointers from animation context data */
+ scene= ac.scene;
+ ar= ac.ar;
+ v2d= &ar->v2d;
+
+ /* get mouse coordinates (in region coordinates) */
+ mval[0]= (event->x - ar->winrct.xmin);
+ mval[1]= (event->y - ar->winrct.ymin);
+
+ /* select mode is either replace (deselect all, then add) or add/extend */
+ if (RNA_boolean_get(op->ptr, "extend"))
+ selectmode= SELECT_INVERT;
+ else if (RNA_boolean_get(op->ptr, "children_only"))
+ selectmode= -1; /* this is a bit of a special case for ActionGroups only... should it be removed or extended to all instead? */
+ else
+ selectmode= SELECT_REPLACE;
+
+ /* figure out which channel user clicked in
+ * Note: although channels technically start at y= ACHANNEL_FIRST, we need to adjust by half a channel's height
+ * so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use
+ * ACHANNEL_HEIGHT_HALF.
+ */
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
+ UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index);
+
+ /* handle mouse-click in the relevant channel then */
+ mouse_anim_channels(&ac, x, channel_index, selectmode);
+
+ /* set notifier tha things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
+
+ return OPERATOR_FINISHED;
+}
+
+void ANIM_OT_channels_click (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mouse Click on Channels";
+ ot->idname= "ANIM_OT_channels_click";
+
+ /* api callbacks */
+ ot->invoke= animchannels_mouseclick_invoke;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
+ RNA_def_boolean(ot->srna, "children_only", 0, "Select Children Only", ""); // CTRLKEY|SHIFTKEY
+}
+
+/* ************************************************************************** */
+/* Operator Registration */
+
+void ED_operatortypes_animchannels(void)
+{
+ WM_operatortype_append(ANIM_OT_channels_select_all_toggle);
+ WM_operatortype_append(ANIM_OT_channels_select_border);
+ WM_operatortype_append(ANIM_OT_channels_click);
+
+ WM_operatortype_append(ANIM_OT_channels_setting_enable);
+ WM_operatortype_append(ANIM_OT_channels_setting_disable);
+ WM_operatortype_append(ANIM_OT_channels_setting_toggle);
+
+ // XXX does this need to be a separate operator?
+ WM_operatortype_append(ANIM_OT_channels_editable_toggle);
+
+ // XXX these need to be updated for new system... todo...
+ //WM_operatortype_append(ANIM_OT_channels_move_up);
+ //WM_operatortype_append(ANIM_OT_channels_move_down);
+ //WM_operatortype_append(ANIM_OT_channels_move_top);
+ //WM_operatortype_append(ANIM_OT_channels_move_bottom);
+
+ WM_operatortype_append(ANIM_OT_channels_expand);
+ WM_operatortype_append(ANIM_OT_channels_collapse);
+
+ WM_operatortype_append(ANIM_OT_channels_visibility_toggle);
+}
+
+void ED_keymap_animchannels(wmWindowManager *wm)
+{
+ ListBase *keymap = WM_keymap_listbase(wm, "Animation_Channels", 0, 0);
+
+ /* selection */
+ /* click-select */
+ // XXX for now, only leftmouse....
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_click", LEFTMOUSE, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_click", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_click", LEFTMOUSE, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "children_only", 1);
+
+ /* deselect all */
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", AKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1);
+
+ /* borderselect */
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", BKEY, KM_PRESS, 0, 0);
+
+ /* settings */
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_toggle", WKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_enable", WKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_disable", WKEY, KM_PRESS, KM_ALT, 0);
+
+ /* settings - specialised hotkeys */
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_editable_toggle", TABKEY, KM_PRESS, 0, 0);
+
+ /* expand/collapse */
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_expand", PADPLUSKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_collapse", PADMINUS, KM_PRESS, 0, 0);
+
+ RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_expand", PADPLUSKEY, KM_PRESS, KM_CTRL, 0)->ptr, "all", 1);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_collapse", PADMINUS, KM_PRESS, KM_CTRL, 0)->ptr, "all", 1);
+
+ /* rearranging - actions only */
+ //WM_keymap_add_item(keymap, "ANIM_OT_channels_move_up", PAGEUPKEY, KM_PRESS, KM_SHIFT, 0);
+ //WM_keymap_add_item(keymap, "ANIM_OT_channels_move_down", PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0);
+ //WM_keymap_add_item(keymap, "ANIM_OT_channels_move_to_top", PAGEUPKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
+ //WM_keymap_add_item(keymap, "ANIM_OT_channels_move_to_bottom", PAGEDOWNKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
+
+ /* Graph Editor only */
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_visibility_toggle", VKEY, KM_PRESS, 0, 0);
+}
+
+/* ************************************************************************** */
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c
new file mode 100644
index 00000000000..1ff2169bf61
--- /dev/null
+++ b/source/blender/editors/animation/anim_deps.c
@@ -0,0 +1,239 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation, Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_action.h"
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_anim_api.h"
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* ***************** depsgraph calls and anim updates ************* */
+/* ***************** only these can be called from editors ******** */
+
+/* generic update flush, reads from context Screen (layers) and scene */
+/* this is for compliancy, later it can do all windows etc */
+void ED_anim_dag_flush_update(const bContext *C)
+{
+ Scene *scene= CTX_data_scene(C);
+ bScreen *screen= CTX_wm_screen(C);
+
+ DAG_scene_flush_update(scene, ED_screen_view3d_layers(screen), 0);
+}
+
+/* flushes changes from object to all relations in scene */
+void ED_anim_object_flush_update(const bContext *C, Object *ob)
+{
+ Scene *scene= CTX_data_scene(C);
+ bScreen *screen= CTX_wm_screen(C);
+
+ DAG_object_update_flags(scene, ob, ED_screen_view3d_layers(screen));
+}
+
+
+/* **************************** animation tool notifiers ******************************** */
+
+/* Send notifiers on behalf of animation editing tools, based on various context info
+ * - data_changed: eAnimData_Changed
+ */
+void ANIM_animdata_send_notifiers (bContext *C, bAnimContext *ac, short data_changed)
+{
+ /* types of notifiers to send, depends on the editor context */
+ switch (ac->datatype) {
+ case ANIMCONT_DOPESHEET: /* dopesheet */
+ case ANIMCONT_FCURVES: /* fcurve editor */
+ case ANIMCONT_DRIVERS: /* drivers editor */ // XXX probably this will need separate handling, since these are part of dependency system
+ {
+ /* what action was taken */
+ switch (data_changed) {
+ case ANIM_CHANGED_KEYFRAMES_VALUES:
+ /* keyframe values changed, so transform may have changed */
+ // XXX what about other cases? maybe we need general ND_KEYFRAMES or ND_ANIMATION?
+ WM_event_add_notifier(C, NC_OBJECT|ND_KEYS|ND_TRANSFORM, NULL);
+ break;
+ case ANIM_CHANGED_KEYFRAMES_SELECT:
+ WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, NULL);
+ break;
+ case ANIM_CHANGED_CHANNELS:
+ // XXX err... check available datatypes in dopesheet first?
+ // FIXME: this currently doesn't work (to update own view)
+ WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE|ND_OB_SELECT, ac->scene);
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE|ND_BONE_SELECT, NULL);
+ break;
+ }
+
+ // XXX for now, at least update own editor!
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+ break;
+
+ case ANIMCONT_ACTION: /* action editor */
+ {
+ Object *obact= CTX_data_active_object(C);
+
+ switch (data_changed) {
+ case ANIM_CHANGED_KEYFRAMES_VALUES:
+ /* keyframe values changed, so transform may have changed */
+ // XXX what about other cases? maybe we need general ND_KEYFRAMES or ND_ANIMATION?
+ WM_event_add_notifier(C, NC_OBJECT|ND_KEYS|ND_TRANSFORM, obact);
+ break;
+ case ANIM_CHANGED_KEYFRAMES_SELECT:
+ WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, obact);
+ break;
+ case ANIM_CHANGED_CHANNELS:
+ // XXX err... check available datatypes in dopesheet first?
+ // FIXME: this currently doesn't work (to update own view)
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE|ND_BONE_SELECT, obact);
+ break;
+ }
+
+ // XXX for now, at least update own editor!
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+ break;
+
+ default: /* some other data... just update area for now */
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+}
+
+/* **************************** pose <-> action syncing ******************************** */
+/* Summary of what needs to be synced between poses and actions:
+ * 1) Flags
+ * a) Visibility (only for pose to action)
+ * b) Selection status (both ways)
+ * 2) Group settings (only for pose to action) - do we also need to make sure same groups exist?
+ * 3) Grouping (only for pose to action for now)
+ */
+
+/* Notifier from Action/Dopesheet (this may be extended to include other things such as Python...)
+ * Channels in action changed, so update pose channels/groups to reflect changes.
+ *
+ * An object (usually 'active' Object) needs to be supplied, so that its Pose-Channels can be synced with
+ * the channels in its active Action.
+ */
+void ANIM_action_to_pose_sync (Object *ob)
+{
+ bAction *act= (bAction *)ob->action;
+ bActionChannel *achan;
+ bPoseChannel *pchan;
+
+ /* error checking */
+ if ((ob == NULL) || (ob->type != OB_ARMATURE) || ELEM(NULL, act, ob->pose))
+ return;
+
+ /* 1b) loop through all Action-Channels (there should be fewer channels to search through here in general) */
+ for (achan= act->chanbase.first; achan; achan= achan->next) {
+ /* find matching pose-channel */
+ pchan= get_pose_channel(ob->pose, achan->name);
+
+ /* sync active and selected flags */
+ if (pchan && pchan->bone) {
+ /* selection */
+ if (achan->flag & ACHAN_SELECTED)
+ pchan->bone->flag |= BONE_SELECTED;
+ else
+ pchan->bone->flag &= ~BONE_SELECTED;
+
+ /* active */
+ if (achan->flag & ACHAN_HILIGHTED)
+ pchan->bone->flag |= BONE_ACTIVE;
+ else
+ pchan->bone->flag &= ~BONE_ACTIVE;
+ }
+ }
+
+ // TODO: add grouping changes too? For now, these tools aren't exposed to users in animation editors yet...
+}
+
+/* Notifier from 3D-View/Outliner (this is likely to include other sources too...)
+ * Pose channels/groups changed, so update action channels
+ *
+ * An object (usually 'active' Object) needs to be supplied, so that its Pose-Channels can be synced with
+ * the channels in its active Action.
+ */
+void ANIM_pose_to_action_sync (Object *ob, ScrArea *sa)
+{
+ SpaceAction *saction= (SpaceAction *)sa->spacedata.first;
+ bArmature *arm= (bArmature *)ob->data;
+ bAction *act= (bAction *)ob->action;
+ bActionChannel *achan;
+ //bActionGroup *agrp, *bgrp;
+ bPoseChannel *pchan;
+
+ /* error checking */
+ if ((ob == NULL) || (ob->type != OB_ARMATURE) || ELEM3(NULL, arm, act, ob->pose))
+ return;
+
+ /* 1) loop through all Action-Channels (there should be fewer channels to search through here in general) */
+ for (achan= act->chanbase.first; achan; achan= achan->next) {
+ /* find matching pose-channel */
+ pchan= get_pose_channel(ob->pose, achan->name);
+
+ /* sync selection and visibility settings */
+ if (pchan && pchan->bone) {
+ /* visibility - if layer is hidden, or if bone itself is hidden */
+ if (!(saction->flag & SACTION_NOHIDE) && !(saction->pin)) {
+ if (!(pchan->bone->layer & arm->layer) || (pchan->bone->flag & BONE_HIDDEN_P))
+ achan->flag |= ACHAN_HIDDEN;
+ else
+ achan->flag &= ~ACHAN_HIDDEN;
+ }
+
+ /* selection */
+ if (pchan->bone->flag & BONE_SELECTED)
+ achan->flag |= ACHAN_SELECTED;
+ else
+ achan->flag &= ~ACHAN_SELECTED;
+ }
+ }
+
+ // XXX step 2 needs to be coded still... currently missing action/bone group API to do any more work here...
+ // XXX step 3 needs to be coded still... it's a messy case to deal with (we'll use the temp indices for this?)
+}
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
new file mode 100644
index 00000000000..7f07de80754
--- /dev/null
+++ b/source/blender/editors/animation/anim_draw.c
@@ -0,0 +1,315 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_action.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_fcurve.h"
+#include "BKE_object.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframes_edit.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+/* XXX */
+extern void ui_rasterpos_safe(float x, float y, float aspect);
+
+/* *************************************************** */
+/* CURRENT FRAME DRAWING */
+
+/* Draw current frame number in a little green box beside the current frame indicator */
+static void draw_cfra_number (Scene *scene, View2D *v2d, float cfra, short time)
+{
+ float xscale, yscale, x, y;
+ char str[32];
+ short slen;
+
+ /* because the frame number text is subject to the same scaling as the contents of the view */
+ UI_view2d_getscale(v2d, &xscale, &yscale);
+ glScalef(1.0f/xscale, 1.0f, 1.0f);
+
+ if (time)
+ sprintf(str, " %.2f", FRA2TIME(CFRA));
+ else
+ sprintf(str, " %d", CFRA);
+ slen= (short)UI_GetStringWidth(str) - 1;
+
+ /* get starting coordinates for drawing */
+ x= cfra * xscale;
+ y= 18;
+
+ /* draw green box around/behind text */
+ UI_ThemeColorShadeAlpha(TH_CFRAME, 0, -100);
+ glRectf(x, y, x+slen, y+15);
+
+ /* draw current frame number - black text */
+ UI_ThemeColor(TH_TEXT);
+ UI_DrawString(x-5, y+3, str); // XXX may need to be updated for font stuff
+
+ /* restore view transform */
+ glScalef(xscale, 1.0, 1.0);
+}
+
+/* General call for drawing current frame indicator in a */
+void ANIM_draw_cfra (const bContext *C, View2D *v2d, short flag)
+{
+ Scene *scene= CTX_data_scene(C);
+ float vec[2];
+
+ /* Draw a light green line to indicate current frame */
+ vec[0]= (float)(scene->r.cfra * scene->r.framelen);
+
+ UI_ThemeColor(TH_CFRAME);
+ glLineWidth(2.0);
+
+ glBegin(GL_LINE_STRIP);
+ vec[1]= v2d->cur.ymin;
+ glVertex2fv(vec);
+
+ vec[1]= v2d->cur.ymax;
+ glVertex2fv(vec);
+ glEnd();
+
+ /* Draw dark green line if slow-parenting/time-offset is enabled */
+ if (flag & DRAWCFRA_SHOW_TIMEOFS) {
+ Object *ob= (scene->basact) ? (scene->basact->object) : 0;
+
+ // XXX ob->ipoflag is depreceated!
+ if ((ob) && (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0f)) {
+ vec[0]-= give_timeoffset(ob); /* could avoid calling twice */
+
+ UI_ThemeColorShade(TH_CFRAME, -30);
+
+ glBegin(GL_LINE_STRIP);
+ /*vec[1]= v2d->cur.ymax;*/ // this is set already. this line is only included
+ glVertex2fv(vec);
+
+ vec[1]= v2d->cur.ymin;
+ glVertex2fv(vec);
+ glEnd();
+ }
+ }
+
+ glLineWidth(1.0);
+
+ /* Draw current frame number in a little box */
+ if (flag & DRAWCFRA_SHOW_NUMBOX) {
+ UI_view2d_view_orthoSpecial(C, v2d, 1);
+ draw_cfra_number(scene, v2d, vec[0], (flag & DRAWCFRA_UNIT_SECONDS));
+ }
+}
+
+/* *************************************************** */
+/* PREVIEW RANGE 'CURTAINS' */
+/* Note: 'Preview Range' tools are defined in anim_ops.c */
+
+/* Draw preview range 'curtains' for highlighting where the animation data is */
+void ANIM_draw_previewrange (const bContext *C, View2D *v2d)
+{
+ Scene *scene= CTX_data_scene(C);
+
+ /* only draw this if preview range is set */
+ if (scene->r.psfra) {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
+
+ /* only draw two separate 'curtains' if there's no overlap between them */
+ if (PSFRA < PEFRA) {
+ glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
+ glRectf((float)PEFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ }
+ else {
+ glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ }
+
+ glDisable(GL_BLEND);
+ }
+}
+
+/* *************************************************** */
+/* NLA-MAPPING UTILITIES (required for drawing and also editing keyframes) */
+
+/* Obtain the Object providing NLA-scaling for the given channel (if applicable) */
+Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
+{
+ /* sanity checks */
+ if (ac == NULL)
+ return NULL;
+
+ /* handling depends on the type of animation-context we've got */
+ if (ac->datatype == ANIMCONT_ACTION) {
+ /* Action Editor (action mode) or Graph Editor (ipo mode):
+ * Only use if editor is not pinned, and active object has action
+ */
+ if (ac->obact && ac->obact->action) {
+ SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
+
+ if (saction->pin == 0)
+ return ac->obact;
+ }
+ }
+ else if ((ac->datatype == ANIMCONT_DOPESHEET) && (ale)) {
+ /* Dopesheet:
+ * Only if channel is available, and is owned by an Object with an Action
+ */
+ if ((ale->id) && (GS(ale->id->name) == ID_OB)) {
+ Object *ob= (Object *)ale->id;
+
+ if (ob->action)
+ return ob;
+ }
+ }
+ // XXX todo: add F-Curves mode (Graph Editor) ...
+
+ /* no appropriate object found */
+ return NULL;
+}
+
+/* Set/clear temporary mapping of coordinates from 'local-action' time to 'global-nla-scaled' time
+ * - the old mapping is stored in a static var, but that shouldn't be too bad as UI drawing
+ * (where this is called) is single-threaded anyway
+ */
+// XXX was called: map_active_strip()
+void ANIM_nla_mapping_draw(gla2DDrawInfo *di, Object *ob, short restore)
+{
+ static rctf stored;
+
+ if (restore) {
+ /* restore un-mapped coordinates */
+ gla2DSetMap(di, &stored);
+ }
+ else {
+ /* set mapped coordinates */
+ rctf map;
+
+ gla2DGetMap(di, &stored);
+ map= stored;
+
+ map.xmin= get_action_frame(ob, map.xmin);
+ map.xmax= get_action_frame(ob, map.xmax);
+
+ if (map.xmin == map.xmax) map.xmax += 1.0f;
+ gla2DSetMap(di, &map);
+ }
+}
+
+/* ------------------- */
+
+/* helper function for ANIM_nla_mapping_apply_ipocurve() -> "restore", i.e. mapping points back to IPO-time */
+static short bezt_nlamapping_restore(BeztEditData *bed, BezTriple *bezt)
+{
+ /* object providing scaling is stored in 'data', only_keys option is stored in i1 */
+ Object *ob= (Object *)bed->data;
+ short only_keys= (short)bed->i1;
+
+ /* adjust BezTriple handles only if allowed to */
+ if (only_keys == 0) {
+ bezt->vec[0][0]= get_action_frame(ob, bezt->vec[0][0]);
+ bezt->vec[2][0]= get_action_frame(ob, bezt->vec[2][0]);
+ }
+ bezt->vec[1][0]= get_action_frame(ob, bezt->vec[1][0]);
+
+ return 0;
+}
+
+/* helper function for ANIM_nla_mapping_apply_ipocurve() -> "apply", i.e. mapping points to NLA-mapped global time */
+static short bezt_nlamapping_apply(BeztEditData *bed, BezTriple *bezt)
+{
+ /* object providing scaling is stored in 'data', only_keys option is stored in i1 */
+ Object *ob= (Object *)bed->data;
+ short only_keys= (short)bed->i1;
+
+ /* adjust BezTriple handles only if allowed to */
+ if (only_keys == 0) {
+ bezt->vec[0][0]= get_action_frame_inv(ob, bezt->vec[0][0]);
+ bezt->vec[2][0]= get_action_frame_inv(ob, bezt->vec[2][0]);
+ }
+ bezt->vec[1][0]= get_action_frame_inv(ob, bezt->vec[1][0]);
+
+ return 0;
+}
+
+
+
+/* Apply/Unapply NLA mapping to all keyframes in the nominated F-Curve
+ * - restore = whether to map points back to non-mapped time
+ * - only_keys = whether to only adjust the location of the center point of beztriples
+ */
+void ANIM_nla_mapping_apply_fcurve(Object *ob, FCurve *fcu, short restore, short only_keys)
+{
+ BeztEditData bed;
+ BeztEditFunc map_cb;
+
+ /* init edit data
+ * - ob is stored in 'data'
+ * - only_keys is stored in 'i1'
+ */
+ memset(&bed, 0, sizeof(BeztEditData));
+ bed.data= (void *)ob;
+ bed.i1= (int)only_keys;
+
+ /* get editing callback */
+ if (restore)
+ map_cb= bezt_nlamapping_restore;
+ else
+ map_cb= bezt_nlamapping_apply;
+
+ /* apply to F-Curve */
+ ANIM_fcurve_keys_bezier_loop(&bed, fcu, NULL, map_cb, NULL);
+}
+
+/* *************************************************** */
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
new file mode 100644
index 00000000000..881d2d95ca4
--- /dev/null
+++ b/source/blender/editors/animation/anim_filter.c
@@ -0,0 +1,1404 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* This file contains a system used to provide a layer of abstraction between sources
+ * of animation data and tools in Animation Editors. The method used here involves
+ * generating a list of edit structures which enable tools to naively perform the actions
+ * they require without all the boiler-plate associated with loops within loops and checking
+ * for cases to ignore.
+ *
+ * While this is primarily used for the Action/Dopesheet Editor (and its accessory modes),
+ * the IPO Editor also uses this for it's channel list and for determining which curves
+ * are being edited.
+ *
+ * Note: much of the original system this was based on was built before the creation of the RNA
+ * system. In future, it would be interesting to replace some parts of this code with RNA queries,
+ * however, RNA does not eliminate some of the boiler-plate reduction benefits presented by this
+ * system, so if any such work does occur, it should only be used for the internals used here...
+ *
+ * -- Joshua Leung, Dec 2008
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_world_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_key.h"
+#include "BKE_object.h"
+#include "BKE_material.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "ED_anim_api.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+/* ************************************************************ */
+/* Blender Context <-> Animation Context mapping */
+
+/* ----------- Private Stuff - Action Editor ------------- */
+
+/* Get shapekey data being edited (for Action Editor -> ShapeKey mode) */
+/* Note: there's a similar function in key.c (ob_get_key) */
+Key *actedit_get_shapekeys (bAnimContext *ac, SpaceAction *saction)
+{
+ Scene *scene= ac->scene;
+ Object *ob;
+ Key *key;
+
+ ob = OBACT;
+ if (ob == NULL)
+ return NULL;
+
+ /* XXX pinning is not available in 'ShapeKey' mode... */
+ //if (saction->pin) return NULL;
+
+ /* shapekey data is stored with geometry data */
+ switch (ob->type) {
+ case OB_MESH:
+ key= ((Mesh *)ob->data)->key;
+ break;
+
+ case OB_LATTICE:
+ key= ((Lattice *)ob->data)->key;
+ break;
+
+ case OB_CURVE:
+ case OB_SURF:
+ key= ((Curve *)ob->data)->key;
+ break;
+
+ default:
+ return NULL;
+ }
+
+ if (key) {
+ if (key->type == KEY_RELATIVE)
+ return key;
+ }
+
+ return NULL;
+}
+
+/* Get data being edited in Action Editor (depending on current 'mode') */
+static short actedit_get_context (bAnimContext *ac, SpaceAction *saction)
+{
+ /* sync settings with current view status, then return appropriate data */
+ switch (saction->mode) {
+ case SACTCONT_ACTION: /* 'Action Editor' */
+ /* if not pinned, sync with active object */
+ if (saction->pin == 0) {
+ if (ac->obact && ac->obact->adt)
+ saction->action = ac->obact->adt->action;
+ else
+ saction->action= NULL;
+ }
+
+ ac->datatype= ANIMCONT_ACTION;
+ ac->data= saction->action;
+
+ ac->mode= saction->mode;
+ return 1;
+
+ case SACTCONT_SHAPEKEY: /* 'ShapeKey Editor' */
+ ac->datatype= ANIMCONT_SHAPEKEY;
+ ac->data= actedit_get_shapekeys(ac, saction);
+
+ ac->mode= saction->mode;
+ return 1;
+
+ case SACTCONT_GPENCIL: /* Grease Pencil */ // XXX review how this mode is handled...
+ ac->datatype=ANIMCONT_GPENCIL;
+ //ac->data= CTX_wm_screen(C); // FIXME: add that dopesheet type thing here!
+ ac->data= NULL; // !!!
+
+ ac->mode= saction->mode;
+ return 1;
+
+ case SACTCONT_DOPESHEET: /* DopeSheet */
+ /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+ saction->ads.source= (ID *)ac->scene;
+
+ ac->datatype= ANIMCONT_DOPESHEET;
+ ac->data= &saction->ads;
+
+ ac->mode= saction->mode;
+ return 1;
+
+ default: /* unhandled yet */
+ ac->datatype= ANIMCONT_NONE;
+ ac->data= NULL;
+
+ ac->mode= -1;
+ return 0;
+ }
+}
+
+/* ----------- Private Stuff - IPO Editor ------------- */
+
+/* Get data being edited in Graph Editor (depending on current 'mode') */
+static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo)
+{
+ /* init dopesheet data if non-existant (i.e. for old files) */
+ if (sipo->ads == NULL)
+ sipo->ads= MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
+
+ /* sync settings with current view status, then return appropriate data */
+ switch (sipo->mode) {
+ case SIPO_MODE_ANIMATION: /* Animation F-Curve Editor */
+ /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+ sipo->ads->source= (ID *)ac->scene;
+ sipo->ads->filterflag &= ~ADS_FILTER_ONLYDRIVERS;
+
+ ac->datatype= ANIMCONT_FCURVES;
+ ac->data= sipo->ads;
+
+ ac->mode= sipo->mode;
+ return 1;
+
+ case SIPO_MODE_DRIVERS: /* Driver F-Curve Editor */
+ /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+ sipo->ads->source= (ID *)ac->scene;
+ sipo->ads->filterflag |= ADS_FILTER_ONLYDRIVERS;
+
+ ac->datatype= ANIMCONT_DRIVERS;
+ ac->data= sipo->ads;
+
+ ac->mode= sipo->mode;
+ return 1;
+
+ default: /* unhandled yet */
+ ac->datatype= ANIMCONT_NONE;
+ ac->data= NULL;
+
+ ac->mode= -1;
+ return 0;
+ }
+}
+
+/* ----------- Public API --------------- */
+
+/* Obtain current anim-data context, given that context info from Blender context has already been set
+ * - AnimContext to write to is provided as pointer to var on stack so that we don't have
+ * allocation/freeing costs (which are not that avoidable with channels).
+ */
+short ANIM_animdata_context_getdata (bAnimContext *ac)
+{
+ ScrArea *sa= ac->sa;
+ short ok= 0;
+
+ /* context depends on editor we are currently in */
+ if (sa) {
+ switch (sa->spacetype) {
+ case SPACE_ACTION:
+ {
+ SpaceAction *saction= (SpaceAction *)sa->spacedata.first;
+ ok= actedit_get_context(ac, saction);
+ }
+ break;
+
+ case SPACE_IPO:
+ {
+ SpaceIpo *sipo= (SpaceIpo *)sa->spacedata.first;
+ ok= graphedit_get_context(ac, sipo);
+ }
+ break;
+ }
+ }
+
+ /* check if there's any valid data */
+ if (ok && ac->data)
+ return 1;
+ else
+ return 0;
+}
+
+/* Obtain current anim-data context from Blender Context info
+ * - AnimContext to write to is provided as pointer to var on stack so that we don't have
+ * allocation/freeing costs (which are not that avoidable with channels).
+ * - Clears data and sets the information from Blender Context which is useful
+ */
+short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= CTX_wm_region(C);
+ Scene *scene= CTX_data_scene(C);
+
+ /* clear old context info */
+ if (ac == NULL) return 0;
+ memset(ac, 0, sizeof(bAnimContext));
+
+ /* get useful default context settings from context */
+ ac->scene= scene;
+ ac->obact= (scene && scene->basact)? scene->basact->object : NULL;
+ ac->sa= sa;
+ ac->ar= ar;
+ ac->spacetype= (sa) ? sa->spacetype : 0;
+ ac->regiontype= (ar) ? ar->regiontype : 0;
+
+ /* get data context info */
+ return ANIM_animdata_context_getdata(ac);
+}
+
+/* ************************************************************ */
+/* Blender Data <-- Filter --> Channels to be operated on */
+
+/* quick macro to test if AnimData is usable */
+#define ANIMDATA_HAS_KEYS(id) ((id)->adt && (id)->adt->action)
+
+/* quick macro to test if AnimData is usable for drivers */
+#define ANIMDATA_HAS_DRIVERS(id) ((id)->adt && (id)->adt->drivers.first)
+
+/* quick macro to test if a anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */
+#define ANIMCHANNEL_SELOK(test_func) \
+ ( !(filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) || \
+ ((filter_mode & ANIMFILTER_SEL) && test_func) || \
+ ((filter_mode & ANIMFILTER_UNSEL) && test_func==0) )
+
+/* ----------- 'Private' Stuff --------------- */
+
+/* this function allocates memory for a new bAnimListElem struct for the
+ * provided animation channel-data.
+ */
+bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, short ownertype, ID *owner_id)
+{
+ bAnimListElem *ale= NULL;
+
+ /* only allocate memory if there is data to convert */
+ if (data) {
+ /* allocate and set generic data */
+ ale= MEM_callocN(sizeof(bAnimListElem), "bAnimListElem");
+
+ ale->data= data;
+ ale->type= datatype;
+ // XXX what is the point of the owner data?
+ ale->owner= owner;
+ ale->ownertype= ownertype;
+
+ ale->id= owner_id;
+
+ /* do specifics */
+ switch (datatype) {
+ case ANIMTYPE_SCENE:
+ {
+ Scene *sce= (Scene *)data;
+
+ ale->flag= sce->flag;
+
+ ale->key_data= sce;
+ ale->datatype= ALE_SCE;
+ }
+ break;
+ case ANIMTYPE_OBJECT:
+ {
+ Base *base= (Base *)data;
+ Object *ob= base->object;
+
+ ale->flag= ob->flag;
+
+ ale->key_data= ob;
+ ale->datatype= ALE_OB;
+ }
+ break;
+ case ANIMTYPE_FILLACTD:
+ {
+ bAction *act= (bAction *)data;
+
+ ale->flag= act->flag;
+
+ ale->key_data= act;
+ ale->datatype= ALE_ACT;
+ }
+ break;
+ case ANIMTYPE_FILLDRIVERS:
+ {
+ AnimData *adt= (AnimData *)data;
+
+ ale->flag= adt->flag;
+
+ // XXX... drivers don't show summary for now
+ ale->key_data= NULL;
+ ale->datatype= ALE_NONE;
+ }
+ break;
+ case ANIMTYPE_FILLMATD:
+ {
+ Object *ob= (Object *)data;
+
+ ale->flag= FILTER_MAT_OBJC(ob);
+
+ ale->key_data= NULL;
+ ale->datatype= ALE_NONE;
+ }
+ break;
+
+ case ANIMTYPE_DSMAT:
+ {
+ Material *ma= (Material *)data;
+ AnimData *adt= ma->adt;
+
+ ale->flag= FILTER_MAT_OBJD(ma);
+
+ ale->key_data= (adt) ? adt->action : NULL;
+ ale->datatype= ALE_ACT;
+ }
+ break;
+ case ANIMTYPE_DSLAM:
+ {
+ Lamp *la= (Lamp *)data;
+ AnimData *adt= la->adt;
+
+ ale->flag= FILTER_LAM_OBJD(la);
+
+ ale->key_data= (adt) ? adt->action : NULL;
+ ale->datatype= ALE_ACT;
+ }
+ break;
+ case ANIMTYPE_DSCAM:
+ {
+ Camera *ca= (Camera *)data;
+ AnimData *adt= ca->adt;
+
+ ale->flag= FILTER_CAM_OBJD(ca);
+
+ ale->key_data= (adt) ? adt->action : NULL;
+ ale->datatype= ALE_ACT;
+ }
+ break;
+ case ANIMTYPE_DSCUR:
+ {
+ Curve *cu= (Curve *)data;
+ AnimData *adt= cu->adt;
+
+ ale->flag= FILTER_CUR_OBJD(cu);
+
+ ale->key_data= (adt) ? adt->action : NULL;
+ ale->datatype= ALE_ACT;
+ }
+ break;
+ case ANIMTYPE_DSSKEY:
+ {
+ Key *key= (Key *)data;
+ AnimData *adt= key->adt;
+
+ ale->flag= FILTER_SKE_OBJD(key);
+
+ ale->key_data= (adt) ? adt->action : NULL;
+ ale->datatype= ALE_ACT;
+ }
+ break;
+ case ANIMTYPE_DSWOR:
+ {
+ World *wo= (World *)data;
+ AnimData *adt= wo->adt;
+
+ ale->flag= FILTER_WOR_SCED(wo);
+
+ ale->key_data= (adt) ? adt->action : NULL;
+ ale->datatype= ALE_ACT;
+ }
+ break;
+
+ case ANIMTYPE_GROUP:
+ {
+ bActionGroup *agrp= (bActionGroup *)data;
+
+ ale->flag= agrp->flag;
+
+ ale->key_data= NULL;
+ ale->datatype= ALE_GROUP;
+ }
+ break;
+ case ANIMTYPE_FCURVE:
+ {
+ FCurve *fcu= (FCurve *)data;
+
+ ale->flag= fcu->flag;
+
+ ale->key_data= fcu;
+ ale->datatype= ALE_FCURVE;
+ }
+ break;
+
+ case ANIMTYPE_GPLAYER:
+ {
+ bGPDlayer *gpl= (bGPDlayer *)data;
+
+ ale->flag= gpl->flag;
+
+ ale->key_data= NULL;
+ ale->datatype= ALE_GPFRAME;
+ }
+ break;
+ }
+ }
+
+ /* return created datatype */
+ return ale;
+}
+
+/* ----------------------------------------- */
+
+
+static int animdata_filter_fcurves (ListBase *anim_data, FCurve *first, bActionGroup *grp, void *owner, short ownertype, int filter_mode, ID *owner_id)
+{
+ bAnimListElem *ale = NULL;
+ FCurve *fcu;
+ int items = 0;
+
+ /* loop over F-Curves - assume that the caller of this has already checked that these should be included
+ * NOTE: we need to check if the F-Curves belong to the same group, as this gets called for groups too...
+ */
+ for (fcu= first; ((fcu) && (fcu->grp==grp)); fcu= fcu->next) {
+ /* only include if visible (Graph Editor check, not channels check) */
+ if (!(filter_mode & ANIMFILTER_CURVEVISIBLE) || (fcu->flag & FCURVE_VISIBLE)) {
+ /* only work with this channel and its subchannels if it is editable */
+ if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_FCU(fcu)) {
+ /* only include this curve if selected in a way consistent with the filtering requirements */
+ if ( ANIMCHANNEL_SELOK(SEL_FCU(fcu)) ) {
+ /* only include if this curve is active */
+ if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) {
+ /* owner/ownertype will be either object or action-channel, depending if it was dopesheet or part of an action */
+ ale= make_new_animlistelem(fcu, ANIMTYPE_FCURVE, owner, ownertype, owner_id);
+
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* return the number of items added to the list */
+ return items;
+}
+
+static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter_mode, void *owner, short ownertype, ID *owner_id)
+{
+ bAnimListElem *ale=NULL;
+ bActionGroup *agrp;
+ FCurve *lastchan=NULL;
+ int items = 0;
+
+ /* loop over groups */
+ // XXX in future, we need to be prepared for nestled groups...
+ for (agrp= act->groups.first; agrp; agrp= agrp->next) {
+ /* add this group as a channel first */
+ if ((filter_mode & ANIMFILTER_CHANNELS) || !(filter_mode & ANIMFILTER_CURVESONLY)) {
+ /* check if filtering by selection */
+ if ( ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) ) {
+ ale= make_new_animlistelem(agrp, ANIMTYPE_GROUP, NULL, ANIMTYPE_NONE, owner_id);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+ }
+
+ /* store reference to last channel of group */
+ if (agrp->channels.last)
+ lastchan= agrp->channels.last;
+
+
+ /* there are some situations, where only the channels of the action group should get considered */
+ if (!(filter_mode & ANIMFILTER_ACTGROUPED) || (agrp->flag & AGRP_ACTIVE)) {
+ /* filters here are a bit convoulted...
+ * - groups show a "summary" of keyframes beside their name which must accessable for tools which handle keyframes
+ * - groups can be collapsed (and those tools which are only interested in channels rely on knowing that group is closed)
+ *
+ * cases when we should include F-Curves inside group:
+ * - we don't care about visibility
+ * - group is expanded
+ * - we're interested in keyframes, but not if they appear in selected channels
+ */
+ // XXX what was the selection check here for again?
+ if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) ||
+ ( /*ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) &&*/ (filter_mode & ANIMFILTER_CURVESONLY) ) )
+ {
+ if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
+ // XXX the 'owner' info here needs review...
+ items += animdata_filter_fcurves(anim_data, agrp->channels.first, agrp, owner, ownertype, filter_mode, owner_id);
+
+ /* remove group from filtered list if last element is group
+ * (i.e. only if group had channels, which were all hidden)
+ */
+ // XXX this is really hacky... it should be fixed in a much more elegant way!
+ if ( (ale) && (anim_data->last == ale) &&
+ (ale->data == agrp) && (agrp->channels.first) )
+ {
+ BLI_freelinkN(anim_data, ale);
+ items--;
+ }
+ }
+ }
+ }
+ }
+
+ /* loop over un-grouped F-Curves (only if we're not only considering those channels in the animive group) */
+ if (!(filter_mode & ANIMFILTER_ACTGROUPED)) {
+ // XXX the 'owner' info here needs review...
+ items += animdata_filter_fcurves(anim_data, (lastchan)?(lastchan->next):(act->curves.first), NULL, owner, ownertype, filter_mode, owner_id);
+ }
+
+ /* return the number of items added to the list */
+ return items;
+}
+
+static int animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_mode, void *owner, short ownertype, ID *owner_id)
+{
+ bAnimListElem *ale;
+ KeyBlock *kb;
+ //FCurve *fcu;
+ int i, items=0;
+
+ /* are we filtering for display or editing */
+ if (filter_mode & ANIMFILTER_CHANNELS) {
+ /* for display - loop over shapekeys, adding ipo-curve references where needed */
+ kb= key->block.first;
+
+ /* loop through possible shapekeys, manually creating entries */
+ for (i= 1; i < key->totkey; i++) {
+ ale= MEM_callocN(sizeof(bAnimListElem), "bAnimListElem");
+ kb = kb->next; /* do this even on the first try, as the first is 'Basis' (which doesn't get included) */
+
+ ale->data= kb;
+ ale->type= ANIMTYPE_SHAPEKEY; /* 'abused' usage of this type */
+ ale->owner= key;
+ ale->ownertype= ANIMTYPE_SHAPEKEY;
+ ale->datatype= ALE_NONE;
+ ale->index = i;
+
+#if 0 // XXX fixme... old system
+ if (key->ipo) {
+ for (icu= key->ipo->curve.first; icu; icu=icu->next) {
+ if (icu->adrcode == i) {
+ ale->key_data= icu;
+ ale->datatype= ALE_ICU;
+ break;
+ }
+ }
+ }
+#endif // XXX fixme... old system
+
+ ale->id= owner_id;
+
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+ else {
+#if 0 // XXX fixme... old system
+ /* loop over ipo curves if present - for editing */
+ if (key->ipo) {
+ if (filter_mode & ANIMFILTER_IPOKEYS) {
+ ale= make_new_animlistelem(key->ipo, ANIMTYPE_IPO, key, ANIMTYPE_SHAPEKEY);
+ if (ale) {
+ if (owned) ale->id= owner;
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+ else {
+ items += animdata_filter_ipocurves(anim_data, key->ipo, filter_mode, key, ANIMTYPE_SHAPEKEY, (owned)?(owner):(NULL));
+ }
+ }
+#endif // XXX fixme... old system
+ }
+
+ /* return the number of items added to the list */
+ return items;
+}
+
+#if 0
+// FIXME: switch this to use the bDopeSheet...
+static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter_mode)
+{
+ bAnimListElem *ale;
+ ScrArea *sa, *curarea;
+ bGPdata *gpd;
+ bGPDlayer *gpl;
+ int items = 0;
+
+ /* check if filtering types are appropriate */
+ {
+ /* special hack for fullscreen area (which must be this one then):
+ * - we use the curarea->full as screen to get spaces from, since the
+ * old (pre-fullscreen) screen was stored there...
+ * - this is needed as all data would otherwise disappear
+ */
+ // XXX need to get new alternative for curarea
+ if ((curarea->full) && (curarea->spacetype==SPACE_ACTION))
+ sc= curarea->full;
+
+ /* loop over spaces in current screen, finding gpd blocks (could be slow!) */
+ for (sa= sc->areabase.first; sa; sa= sa->next) {
+ /* try to get gp data */
+ // XXX need to put back grease pencil api...
+ gpd= gpencil_data_getactive(sa);
+ if (gpd == NULL) continue;
+
+ /* add gpd as channel too (if for drawing, and it has layers) */
+ if ((filter_mode & ANIMFILTER_CHANNELS) && (gpd->layers.first)) {
+ /* add to list */
+ ale= make_new_animlistelem(gpd, ANIMTYPE_GPDATABLOCK, sa, ANIMTYPE_SPECIALDATA);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+
+ /* only add layers if they will be visible (if drawing channels) */
+ if ( !(filter_mode & ANIMFILTER_VISIBLE) || (EXPANDED_GPD(gpd)) ) {
+ /* loop over layers as the conditions are acceptable */
+ for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
+ /* only if selected */
+ if ( ANIMCHANNEL_SELOK(SEL_GPL(gpl)) ) {
+ /* only if editable */
+ if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
+ /* add to list */
+ ale= make_new_animlistelem(gpl, ANIMTYPE_GPLAYER, gpd, ANIMTYPE_GPDATABLOCK);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* return the number of items added to the list */
+ return items;
+}
+#endif
+
+
+static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+{
+ ListBase mats = {NULL, NULL};
+ LinkData *ld;
+
+ bAnimListElem *ale=NULL;
+ Object *ob= base->object;
+ int items=0, a=0;
+
+ /* firstly check that we actuallly have some materials, by gathering all materials in a temp list */
+ for (a=0; a < ob->totcol; a++) {
+ Material *ma= give_current_material(ob, a);
+
+ /* for now, if no material returned, skip (this shouldn't confuse the user I hope) */
+ if (ELEM3(NULL, ma, ma->adt, ma->adt->action)) continue;
+
+ /* make a temp list elem for this */
+ ld= MEM_callocN(sizeof(LinkData), "DopeSheet-MaterialCache");
+ ld->data= ma;
+ BLI_addtail(&mats, ld);
+ }
+
+ /* if there were no channels found, no need to carry on */
+ if (mats.first == NULL)
+ return 0;
+
+ /* include materials-expand widget? */
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+ ale= make_new_animlistelem(ob, ANIMTYPE_FILLMATD, base, ANIMTYPE_OBJECT, (ID *)ob);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+
+ /* add materials? */
+ if (FILTER_MAT_OBJC(ob) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+ /* for each material in cache, add channels */
+ for (ld= mats.first; ld; ld= ld->next) {
+ Material *ma= (Material *)ld->data;
+
+ /* include material-expand widget? */
+ // hmm... do we need to store the index of this material in the array anywhere?
+ if (filter_mode & ANIMFILTER_CHANNELS) {
+ ale= make_new_animlistelem(ma, ANIMTYPE_DSMAT, base, ANIMTYPE_OBJECT, (ID *)ma);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+
+ /* add material's F-Curve channels? */
+ if (FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+ // XXX the 'owner' info here is still subject to improvement
+ items += animdata_filter_action(anim_data, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);
+ }
+ }
+ }
+
+ /* free cache */
+ BLI_freelistN(&mats);
+
+ /* return the number of items added to the list */
+ return items;
+}
+
+static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+{
+ bAnimListElem *ale=NULL;
+ Object *ob= base->object;
+ IdAdtTemplate *iat= ob->data;
+ AnimData *adt= iat->adt;
+ short type=0, expanded=0;
+ int items= 0;
+
+ /* get settings based on data type */
+ switch (ob->type) {
+ case OB_CAMERA: /* ------- Camera ------------ */
+ {
+ Camera *ca= (Camera *)ob->data;
+
+ type= ANIMTYPE_DSCAM;
+ expanded= FILTER_CAM_OBJD(ca);
+ }
+ break;
+ case OB_LAMP: /* ---------- Lamp ----------- */
+ {
+ Lamp *la= (Lamp *)ob->data;
+
+ type= ANIMTYPE_DSLAM;
+ expanded= FILTER_LAM_OBJD(la);
+ }
+ break;
+ case OB_CURVE: /* ------- Curve ---------- */
+ {
+ Curve *cu= (Curve *)ob->data;
+
+ type= ANIMTYPE_DSCUR;
+ expanded= FILTER_CUR_OBJD(cu);
+ }
+ break;
+ }
+
+ /* special exception for drivers instead of action */
+ if (ads->filterflag & ADS_FILTER_ONLYDRIVERS)
+ expanded= EXPANDED_DRVD(adt);
+
+ /* include data-expand widget? */
+ if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
+ ale= make_new_animlistelem(iat, type, base, ANIMTYPE_OBJECT, (ID *)iat);
+ if (ale) BLI_addtail(anim_data, ale);
+ }
+
+ /* add object-data animation channels? */
+ if ((expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+ /* Action or Drivers? */
+ if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) {
+ // XXX the 'owner' info here is still subject to improvement
+ items += animdata_filter_action(anim_data, iat->adt->action, filter_mode, iat, type, (ID *)iat);
+ }
+ else {
+ // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
+ items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat);
+ }
+ }
+
+ /* return the number of items added to the list */
+ return items;
+}
+
+static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+{
+ bAnimListElem *ale=NULL;
+ Object *ob= base->object;
+ Key *key= ob_get_key(ob);
+ int items = 0;
+
+ /* add this object as a channel first */
+ if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
+ /* check if filtering by selection */
+ if ANIMCHANNEL_SELOK((base->flag & SELECT)) {
+ ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE, NULL);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+ }
+
+ /* if collapsed, don't go any further (unless adding keyframes only) */
+ if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & ANIMFILTER_CURVESONLY) )
+ return items;
+
+ /* Action or Drivers */
+ if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) {
+ /* Action? */
+ if (ANIMDATA_HAS_KEYS(ob) /*&& !(ads->filterflag & ADS_FILTER_NOACTS)*/) {
+ AnimData *adt= ob->adt;
+
+ /* include action-expand widget? */
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+ ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, base, ANIMTYPE_OBJECT, (ID *)ob);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+
+ /* add F-Curve channels? */
+ if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
+ // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
+ items += animdata_filter_action(anim_data, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
+ }
+ }
+ }
+ else {
+ /* Drivers */
+ if (ANIMDATA_HAS_DRIVERS(ob)) {
+ AnimData *adt= ob->adt;
+
+ /* include drivers-expand widget? */
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+ ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, base, ANIMTYPE_OBJECT, (ID *)ob);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+
+ /* add F-Curve channels (drivers are F-Curves) */
+ if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
+ // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
+ items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)ob);
+ }
+ }
+ }
+
+ /* ShapeKeys? */
+ if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
+ /* Animation or Drivers */
+ if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) {
+ /* include shapekey-expand widget? */
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+ ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+
+ /* add channels */
+ if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+ items += animdata_filter_shapekey(anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
+ }
+ }
+ else {
+ /* Drivers */
+ if (ANIMDATA_HAS_DRIVERS(key)) {
+ AnimData *adt= key->adt;
+
+ /* include shapekey-expand widget? */
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+ ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+
+ /* add F-Curve channels (drivers are F-Curves) */
+ if (FILTER_SKE_OBJD(key)/*EXPANDED_DRVD(adt)*/ || !(filter_mode & ANIMFILTER_CHANNELS)) {
+ // XXX owner info is messed up now...
+ items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)key);
+ }
+ }
+ }
+ }
+
+
+ /* Materials? */
+ if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT))
+ items += animdata_filter_dopesheet_mats(anim_data, ads, base, filter_mode);
+
+ /* Object Data */
+ switch (ob->type) {
+ case OB_CAMERA: /* ------- Camera ------------ */
+ {
+ Camera *ca= (Camera *)ob->data;
+
+ if ((ads->filterflag & ADS_FILTER_NOCAM) == 0) {
+ if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) {
+ if (ANIMDATA_HAS_KEYS(ca))
+ items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
+ }
+ else {
+ if (ANIMDATA_HAS_DRIVERS(ca))
+ items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
+ }
+ }
+ }
+ break;
+ case OB_LAMP: /* ---------- Lamp ----------- */
+ {
+ Lamp *la= (Lamp *)ob->data;
+
+ if ((ads->filterflag & ADS_FILTER_NOLAM) == 0) {
+ if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) {
+ if (ANIMDATA_HAS_KEYS(la))
+ items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
+ }
+ else {
+ if (ANIMDATA_HAS_DRIVERS(la))
+ items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
+ }
+ }
+ }
+ break;
+ case OB_CURVE: /* ------- Curve ---------- */
+ {
+ Curve *cu= (Curve *)ob->data;
+
+ if ((ads->filterflag & ADS_FILTER_NOCUR) == 0) {
+ if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) {
+ if (ANIMDATA_HAS_KEYS(cu))
+ items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
+ }
+ else {
+ if (ANIMDATA_HAS_DRIVERS(cu))
+ items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
+ }
+ }
+ }
+ break;
+ }
+
+ /* return the number of items added to the list */
+ return items;
+}
+
+static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
+{
+ World *wo= sce->world;
+ bAnimListElem *ale;
+ int items = 0;
+
+ /* add scene as a channel first (even if we aren't showing scenes we still need to show the scene's sub-data */
+ if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
+ /* check if filtering by selection */
+ if (ANIMCHANNEL_SELOK( (sce->flag & SCE_DS_SELECTED) )) {
+ ale= make_new_animlistelem(sce, ANIMTYPE_SCENE, NULL, ANIMTYPE_NONE, NULL);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+ }
+
+ /* if collapsed, don't go any further (unless adding keyframes only) */
+ if ( (EXPANDED_SCEC(sce) == 0) && !(filter_mode & ANIMFILTER_CURVESONLY) )
+ return items;
+
+ /* Action or Drivers */
+ if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) {
+ /* Action? */
+ if (ANIMDATA_HAS_KEYS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE)) {
+ AnimData *adt= sce->adt;
+
+ /* include action-expand widget? */
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+ ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, sce, ANIMTYPE_SCENE, (ID *)sce);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+
+ /* add F-Curve channels? */
+ if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
+ items += animdata_filter_action(anim_data, adt->action, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce);
+ }
+ }
+ }
+ else {
+ /* Drivers */
+ if (ANIMDATA_HAS_DRIVERS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE)) {
+ AnimData *adt= sce->adt;
+
+ /* include drivers-expand widget? */
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+ ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, sce, ANIMTYPE_SCENE, (ID *)sce);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+
+ /* add F-Curve channels (drivers are F-Curves) */
+ if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
+ items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, sce, ANIMTYPE_SCENE, filter_mode, (ID *)sce);
+ }
+ }
+ }
+
+ /* world */
+ if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) {
+ /* Animation or Drivers */
+ if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) {
+ AnimData *adt= wo->adt;
+
+ /* include world-expand widget? */
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+ ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)sce);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+
+ /* add channels */
+ if (FILTER_WOR_SCED(wo) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+ items += animdata_filter_action(anim_data, adt->action, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo);
+ }
+ }
+ else {
+ /* Drivers */
+ if (ANIMDATA_HAS_DRIVERS(wo)) {
+ AnimData *adt= wo->adt;
+
+ /* include shapekey-expand widget? */
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+ ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)wo);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+
+ /* add F-Curve channels (drivers are F-Curves) */
+ if (FILTER_WOR_SCED(wo)/*EXPANDED_DRVD(adt)*/ || !(filter_mode & ANIMFILTER_CHANNELS)) {
+ // XXX owner info is messed up now...
+ items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, wo, ANIMTYPE_DSWOR, filter_mode, (ID *)wo);
+ }
+ }
+ }
+ }
+
+ /* return the number of items added to the list */
+ return items;
+}
+
+// TODO: implement pinning... (if and when pinning is done, what we need to do is to provide freeing mechanisms - to protect against data that was deleted)
+static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int filter_mode)
+{
+ Scene *sce= (Scene *)ads->source;
+ Base *base;
+ int items = 0;
+
+ /* check that we do indeed have a scene */
+ if ((ads->source == NULL) || (GS(ads->source->name)!=ID_SCE)) {
+ printf("DopeSheet Error: Not scene! \n");
+ return 0;
+ }
+
+ /* scene-linked animation */
+ // TODO: sequencer, composite nodes - are we to include those here too?
+ {
+ short sceOk, worOk;
+
+ /* check filtering-flags if ok */
+ if (ads->filterflag) {
+ if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) {
+ sceOk= (ANIMDATA_HAS_DRIVERS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE));
+ worOk= ((sce->world) && ANIMDATA_HAS_DRIVERS(sce->world) && !(ads->filterflag & ADS_FILTER_NOWOR));
+ }
+ else {
+ sceOk= (ANIMDATA_HAS_KEYS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE));
+ worOk= ((sce->world) && ANIMDATA_HAS_KEYS(sce->world) && !(ads->filterflag & ADS_FILTER_NOWOR));
+ }
+ }
+ else {
+ sceOk= (ANIMDATA_HAS_KEYS(sce));
+ worOk= ((sce->world) && ANIMDATA_HAS_KEYS(sce->world));
+ }
+
+ /* check if not all bad (i.e. so there is something to show) */
+ if ( !(!sceOk && !worOk) ) {
+ /* add scene data to the list of filtered channels */
+ items += animdata_filter_dopesheet_scene(anim_data, ads, sce, filter_mode);
+ }
+ }
+
+
+ /* loop over all bases in the scene */
+ for (base= sce->base.first; base; base= base->next) {
+ /* check if there's an object (all the relevant checks are done in the ob-function) */
+ if (base->object) {
+ Object *ob= base->object;
+ Key *key= ob_get_key(ob);
+ short actOk, keyOk, dataOk, matOk;
+
+ /* firstly, check if object can be included, by the following fanimors:
+ * - if only visible, must check for layer and also viewport visibility
+ * - if only selected, must check if object is selected
+ * - there must be animation data to edit
+ */
+ // TODO: if cache is implemented, just check name here, and then
+ if (filter_mode & ANIMFILTER_VISIBLE) {
+ /* layer visibility */
+ if ((ob->lay & sce->lay)==0) continue;
+
+ /* outliner restrict-flag */
+ if (ob->restrictflag & OB_RESTRICT_VIEW) continue;
+ }
+
+ /* additionally, dopesheet filtering also affects what objects to consider */
+ if (ads->filterflag) {
+ /* check selection and object type filters */
+ if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) || (base == sce->basact)) ) {
+ /* only selected should be shown */
+ continue;
+ }
+
+ /* check filters for datatypes */
+ if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) {
+ actOk= (ANIMDATA_HAS_DRIVERS(ob));
+ keyOk= ((key) && ANIMDATA_HAS_DRIVERS(key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS));
+ }
+ else {
+ actOk= ANIMDATA_HAS_KEYS(ob);
+ keyOk= ((key) && ANIMDATA_HAS_KEYS(key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS));
+ }
+
+ /* materials - only for geometric types */
+ matOk= 0; /* by default, not ok... */
+ if ( !(ads->filterflag & ADS_FILTER_NOMAT) && (ob->totcol) &&
+ ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) )
+ {
+ int a;
+
+ /* firstly check that we actuallly have some materials */
+ for (a=0; a < ob->totcol; a++) {
+ Material *ma= give_current_material(ob, a);
+
+ /* if material has relevant animation data, break */
+ if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) {
+ if (ANIMDATA_HAS_DRIVERS(ma)) {
+ matOk= 1;
+ break;
+ }
+ }
+ else {
+ if (ANIMDATA_HAS_KEYS(ma)) {
+ matOk= 1;
+ break;
+ }
+ }
+ }
+ }
+
+ /* data */
+ switch (ob->type) {
+ case OB_CAMERA: /* ------- Camera ------------ */
+ {
+ Camera *ca= (Camera *)ob->data;
+ if (ads->filterflag & ADS_FILTER_ONLYDRIVERS)
+ dataOk= (ANIMDATA_HAS_DRIVERS(ca) && !(ads->filterflag & ADS_FILTER_NOCAM));
+ else
+ dataOk= (ANIMDATA_HAS_KEYS(ca) && !(ads->filterflag & ADS_FILTER_NOCAM));
+ }
+ break;
+ case OB_LAMP: /* ---------- Lamp ----------- */
+ {
+ Lamp *la= (Lamp *)ob->data;
+ if (ads->filterflag & ADS_FILTER_ONLYDRIVERS)
+ dataOk= (ANIMDATA_HAS_DRIVERS(la) && !(ads->filterflag & ADS_FILTER_NOLAM));
+ else
+ dataOk= (ANIMDATA_HAS_KEYS(la) && !(ads->filterflag & ADS_FILTER_NOLAM));
+ }
+ break;
+ default: /* --- other --- */
+ dataOk= 0;
+ break;
+ }
+
+ /* check if all bad (i.e. nothing to show) */
+ if (!actOk && !keyOk && !dataOk && !matOk)
+ continue;
+ }
+ else {
+ /* check data-types */
+ actOk= ANIMDATA_HAS_KEYS(ob);
+ keyOk= (key != NULL);
+
+ /* materials - only for geometric types */
+ matOk= 0; /* by default, not ok... */
+ if (ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) && (ob->totcol))
+ {
+ int a;
+
+ /* firstly check that we actuallly have some materials */
+ for (a=0; a < ob->totcol; a++) {
+ Material *ma= give_current_material(ob, a);
+
+ if ((ma) && ANIMDATA_HAS_KEYS(ma)) {
+ matOk= 1;
+ break;
+ }
+ }
+ }
+
+ /* data */
+ switch (ob->type) {
+ case OB_CAMERA: /* ------- Camera ------------ */
+ {
+ Camera *ca= (Camera *)ob->data;
+ dataOk= ANIMDATA_HAS_KEYS(ca);
+ }
+ break;
+ case OB_LAMP: /* ---------- Lamp ----------- */
+ {
+ Lamp *la= (Lamp *)ob->data;
+ dataOk= ANIMDATA_HAS_KEYS(la);
+ }
+ break;
+ case OB_CURVE: /* -------- Curve ---------- */
+ {
+ Curve *cu= (Curve *)ob->data;
+ dataOk= ANIMDATA_HAS_KEYS(cu);
+ }
+ break;
+ default: /* --- other --- */
+ dataOk= 0;
+ break;
+ }
+
+ /* check if all bad (i.e. nothing to show) */
+ if (!actOk && !keyOk && !dataOk && !matOk)
+ continue;
+ }
+
+ /* since we're still here, this object should be usable */
+ items += animdata_filter_dopesheet_ob(anim_data, ads, base, filter_mode);
+ }
+ }
+
+ /* return the number of items in the list */
+ return items;
+}
+
+/* ----------- Public API --------------- */
+
+/* This function filters the active data source to leave only animation channels suitable for
+ * usage by the caller. It will return the length of the list
+ *
+ * *anim_data: is a pointer to a ListBase, to which the filtered animation channels
+ * will be placed for use.
+ * filter_mode: how should the data be filtered - bitmapping accessed flags
+ */
+int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode, void *data, short datatype)
+{
+ int items = 0;
+
+ /* only filter data if there's somewhere to put it */
+ if (data && anim_data) {
+ bAnimListElem *ale, *next;
+ Object *obact= (ac) ? ac->obact : NULL;
+
+ /* firstly filter the data */
+ switch (datatype) {
+ case ANIMCONT_ACTION:
+ items= animdata_filter_action(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE, (ID *)obact);
+ break;
+
+ case ANIMCONT_SHAPEKEY:
+ items= animdata_filter_shapekey(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE, (ID *)obact);
+ break;
+
+ case ANIMCONT_GPENCIL:
+ //items= animdata_filter_gpencil(anim_data, data, filter_mode);
+ break;
+
+ case ANIMCONT_DOPESHEET:
+ case ANIMCONT_FCURVES:
+ case ANIMCONT_DRIVERS:
+ items= animdata_filter_dopesheet(anim_data, data, filter_mode);
+ break;
+ }
+
+ /* remove any weedy entries */
+ // XXX this is weedy code!
+ for (ale= anim_data->first; ale; ale= next) {
+ next= ale->next;
+
+ if (ale->type == ANIMTYPE_NONE) {
+ items--;
+ BLI_freelinkN(anim_data, ale);
+ }
+ }
+ }
+
+ /* return the number of items in the list */
+ return items;
+}
+
+/* ************************************************************ */
diff --git a/source/blender/editors/animation/anim_intern.h b/source/blender/editors/animation/anim_intern.h
new file mode 100644
index 00000000000..e903007fbc0
--- /dev/null
+++ b/source/blender/editors/animation/anim_intern.h
@@ -0,0 +1,18 @@
+/* Testing code for 2.5 animation system
+ * Copyright 2009, Joshua Leung
+ */
+
+#ifndef ANIM_INTERN_H
+#define ANIM_INTERN_H
+
+
+/* KeyingSets/Keyframing Interface ------------- */
+
+/* list of builtin KeyingSets (defined in keyingsets.c) */
+extern ListBase builtin_keyingsets;
+
+short keyingset_context_ok_poll(bContext *C, KeyingSet *ks);
+
+short modifykey_get_context_data (bContext *C, ListBase *dsources, KeyingSet *ks);
+
+#endif // ANIM_INTERN_H
diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c
new file mode 100644
index 00000000000..4d4079a260a
--- /dev/null
+++ b/source/blender/editors/animation/anim_ipo_utils.c
@@ -0,0 +1,219 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2005. Full recode
+ * Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* This file contains code for presenting F-Curves and other animation data
+ * in the UI (especially for use in the Animation Editors).
+ *
+ * -- Joshua Leung, Dec 2008
+ */
+
+
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_key_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_key.h"
+#include "BKE_utildefines.h"
+
+#include "UI_resources.h"
+#include "ED_anim_api.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+
+/* ----------------------- Getter functions ----------------------- */
+
+/* gets the appropriate icon for the given blocktype */
+// XXX some of these will be depreceated?
+int geticon_anim_blocktype(short blocktype)
+{
+ switch (blocktype) {
+ case ID_OB:
+ return ICON_OBJECT_DATA;
+ case ID_PO:
+ return ICON_POSE_HLT;
+ case ID_KE:
+ return ICON_SHAPEKEY_DATA;
+ case ID_MA:
+ return ICON_MATERIAL;
+ case ID_WO:
+ return ICON_WORLD;
+ case ID_CU:
+ return ICON_CURVE_DATA;
+ case ID_CA:
+ return ICON_CAMERA;
+ case ID_LA:
+ return ICON_LAMP;
+ case ID_TE:
+ return ICON_TEXTURE;
+ case ID_CO:
+ return ICON_CONSTRAINT;
+ case ID_FLUIDSIM:
+ return ICON_WORLD; // uggh
+ default:
+ return 0; // what about blank icon?
+ }
+}
+
+/* Write into "name" buffer, the name of the property (retrieved using RNA from the curve's settings)
+ * WARNING: name buffer we're writing to cannot exceed 128 chars (check action_draw.c for details)
+ */
+// TODO: have an extra var to indicate if prop was valid?
+void getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
+{
+ /* sanity checks */
+ if (name == NULL)
+ return;
+ else if ELEM3(NULL, id, fcu, fcu->rna_path) {
+ if (fcu == NULL)
+ sprintf(name, "<invalid>");
+ else if (fcu->rna_path == NULL)
+ sprintf(name, "<no path>");
+ else /* id == NULL */
+ BLI_snprintf(name, 128, "%s[%d]", fcu->rna_path, fcu->array_index);
+ }
+ else {
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+
+ /* get RNA pointer, and resolve the path */
+ RNA_id_pointer_create(id, &id_ptr);
+
+ /* try to resolve the path */
+ if (RNA_path_resolve(&id_ptr, fcu->rna_path, &ptr, &prop)) {
+ char *structname=NULL, *propname=NULL, *arrayname=NULL, arrayindbuf[16];
+ PropertyRNA *nameprop;
+
+ /* For now, name will consist of 3 parts: struct-name, property name, array index
+ * There are several options possible:
+ * 1) <struct-name>.<property-name>.<array-index>
+ * i.e. Bone1.Location.X, or Object.Location.X
+ * 2) <array-index> <property-name> (<struct name>)
+ * i.e. X Location (Bone1), or X Location (Object)
+ *
+ * Currently, option 2 is in use, to try and make it easier to quickly identify F-Curves (it does have
+ * problems with looking rather odd though). Option 1 is better in terms of revealing a consistent sense of
+ * hierarchy though, which isn't so clear with option 2.
+ */
+
+ /* for structname, we use a custom name if one is available */
+ // xxx we might want an icon from types?
+ // xxx it is hard to differentiate between object and bone channels then, if ob + bone motion occur together...
+ nameprop= RNA_struct_name_property(ptr.type);
+ if (nameprop) {
+ /* this gets a string which will need to be freed */
+ structname= RNA_property_string_get_alloc(&ptr, nameprop, NULL, 0);
+ }
+ else
+ structname= (char *)RNA_struct_ui_name(ptr.type);
+
+ /* Property Name is straightforward */
+ propname= (char *)RNA_property_ui_name(prop);
+
+ /* Array Index - only if applicable */
+ if (RNA_property_array_length(prop)) {
+ // XXX the format of these is not final... we don't know how this will go yet
+ // format 1 style
+ //static char *vectoritem[4]= {".X", ".Y", ".Z", ".W"};
+ //static char *quatitem[4]= {".W", ".X", ".Y", ".Z"};
+ //static char *coloritem[4]= {".R", ".G", ".B", ".A"};
+ // format 2 style
+ static char *vectoritem[4]= {"X ", "Y ", "Z ", "W "};
+ static char *quatitem[4]= {"W ", "X ", "Y ", "Z "};
+ static char *coloritem[4]= {"R ", "G ", "B ", "A "};
+
+ int tot= RNA_property_array_length(prop);
+ int propsubtype= RNA_property_subtype(prop);
+
+ /* get string to use for array index */
+ if ((tot == 4) && (propsubtype == PROP_ROTATION))
+ arrayname= quatitem[fcu->array_index];
+ else if ( (tot <= 4) && ((propsubtype == PROP_VECTOR) || (propsubtype == PROP_ROTATION)) )
+ arrayname= vectoritem[fcu->array_index];
+ else if ((tot <= 4) && (propsubtype == PROP_COLOR))
+ arrayname= coloritem[fcu->array_index];
+ else {
+ /* we need to write the index to a temp buffer (in py syntax), as it is a number... */
+ sprintf(arrayindbuf, "[%d]", fcu->array_index);
+ arrayname= &arrayindbuf[0];
+ }
+ }
+ else {
+ /* no array index */
+ arrayname= "";
+ }
+
+ /* putting this all together into the buffer */
+ // XXX we need to check for invalid names...
+ //BLI_snprintf(name, 128, "%s.%s%s", structname, propname, arrayname); // format 1
+ BLI_snprintf(name, 128, "%s%s (%s)", arrayname, propname, structname); // format 2
+
+ /* free temp name if nameprop is set */
+ if (nameprop)
+ MEM_freeN(structname);
+ }
+ else {
+ /* invalid path */
+ BLI_snprintf(name, 128, "\"%s[%d]\"", fcu->rna_path, fcu->array_index);
+ }
+ }
+}
+
+/* ------------------------------- Color Codes for F-Curve Channels ---------------------------- */
+
+/* used for FCURVE_COLOR_AUTO_RAINBOW */
+// XXX this still doesn't work too great when there are more than 32 curves (which happens most of the time)
+void ipo_rainbow (int cur, int tot, float *out)
+{
+ float dfac, fac, sat;
+
+ dfac= (float)(1.0/( (float)tot+1.0));
+
+ /* this calculation makes 2 or 4 different cycles of rainbow colors */
+ if(cur< tot/2) fac= (float)(cur*2.0f*dfac);
+ else fac= (float)((cur-tot/2)*2.0f*dfac +dfac);
+ if(tot > 32) fac= fac*1.95f;
+ if(fac>1.0f) fac-= 1.0f;
+
+ if(fac>0.5f && fac<0.8f) sat= 0.5f;
+ else sat= 0.6f;
+
+ //return hsv_to_cpack(fac, sat, 1.0f);
+ hsv_to_rgb(fac, sat, 1.0f, out, out+1, out+2);
+}
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
new file mode 100644
index 00000000000..58e3aa8e172
--- /dev/null
+++ b/source/blender/editors/animation/anim_markers.c
@@ -0,0 +1,878 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view2d_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_view2d.h"
+#include "UI_resources.h"
+
+#include "ED_markers.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+/* ************* Marker API **************** */
+
+static ListBase *context_get_markers(const bContext *C)
+{
+
+#if 0
+ /* XXX get them from pose */
+ if ((slink->spacetype == SPACE_ACTION) && (saction->flag & SACTION_POSEMARKERS_MOVE)) {
+ if (saction->action)
+ markers= &saction->action->markers;
+ else
+ markers= NULL;
+ }
+ else
+#endif
+
+ return &CTX_data_scene(C)->markers;
+}
+
+/* ************* Marker Drawing ************ */
+
+/* function to draw markers */
+static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag)
+{
+ float xpos, ypixels, xscale, yscale;
+ int icon_id= 0;
+
+ xpos = marker->frame;
+
+ /* no time correction for framelen! space is drawn with old values */
+ ypixels= v2d->mask.ymax-v2d->mask.ymin;
+ UI_view2d_getscale(v2d, &xscale, &yscale);
+
+ glScalef(1.0/xscale, 1.0, 1.0);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ /* vertical line - dotted */
+ if (flag & DRAW_MARKERS_LINES) {
+ setlinestyle(3);
+
+ if (marker->flag & SELECT)
+ glColor4ub(255, 255, 255, 96);
+ else
+ glColor4ub(0, 0, 0, 96);
+
+ glBegin(GL_LINES);
+ glVertex2f((xpos*xscale)+0.5, 12);
+ glVertex2f((xpos*xscale)+0.5, 34*yscale); /* a bit lazy but we know it cant be greater then 34 strips high*/
+ glEnd();
+
+ setlinestyle(0);
+ }
+
+ /* 5 px to offset icon to align properly, space / pixels corrects for zoom */
+ if (flag & DRAW_MARKERS_LOCAL) {
+ icon_id= (marker->flag & ACTIVE) ? ICON_PMARKER_ACT :
+ (marker->flag & SELECT) ? ICON_PMARKER_SEL :
+ ICON_PMARKER;
+ }
+ else {
+ icon_id= (marker->flag & SELECT) ? ICON_MARKER_HLT :
+ ICON_MARKER;
+ }
+
+ UI_icon_draw(xpos*xscale-5.0, 16.0, icon_id);
+
+ glBlendFunc(GL_ONE, GL_ZERO);
+ glDisable(GL_BLEND);
+
+ /* and the marker name too, shifted slightly to the top-right */
+ if (marker->name && marker->name[0]) {
+ float x, y;
+
+ if(marker->flag & SELECT) {
+ UI_ThemeColor(TH_TEXT_HI);
+ x= xpos*xscale+4.0;
+ y= (ypixels<=39.0)?(ypixels-10.0):29.0;
+ }
+ else {
+ UI_ThemeColor(TH_TEXT);
+ if((marker->frame <= cfra) && (marker->frame+5 > cfra)) {
+ x= xpos*xscale+4.0;
+ y= (ypixels<=39.0)?(ypixels-10.0):29.0;
+ }
+ else {
+ x= xpos*xscale+4.0;
+ y= 17.0;
+ }
+ }
+ UI_DrawString(x, y, marker->name);
+ }
+ glScalef(xscale, 1.0, 1.0);
+}
+
+/* Draw Scene-Markers in time window */
+void draw_markers_time(const bContext *C, int flag)
+{
+ ListBase *markers= context_get_markers(C);
+ View2D *v2d= UI_view2d_fromcontext(C);
+ TimeMarker *marker;
+
+ if(markers == NULL)
+ return;
+
+ /* unselected markers are drawn at the first time */
+ for (marker= markers->first; marker; marker= marker->next) {
+ if (!(marker->flag & SELECT)) draw_marker(v2d, marker, CTX_data_scene(C)->r.cfra, flag);
+ }
+
+ /* selected markers are drawn later */
+ for (marker= markers->first; marker; marker= marker->next) {
+ if (marker->flag & SELECT) draw_marker(v2d, marker, CTX_data_scene(C)->r.cfra, flag);
+ }
+}
+
+
+
+/* ************************** add markers *************************** */
+
+/* add TimeMarker at curent frame */
+static int ed_marker_add(bContext *C, wmOperator *op)
+{
+ ListBase *markers= context_get_markers(C);
+ TimeMarker *marker;
+ int frame= CTX_data_scene(C)->r.cfra;
+
+ if(markers == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* two markers can't be at the same place */
+ for(marker= markers->first; marker; marker= marker->next)
+ if(marker->frame == frame)
+ return OPERATOR_CANCELLED;
+
+ /* deselect all */
+ for(marker= markers->first; marker; marker= marker->next)
+ marker->flag &= ~SELECT;
+
+ marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
+ marker->flag= SELECT;
+ marker->frame= frame;
+ sprintf(marker->name, "Frame %d", frame); // XXX - temp code only
+ BLI_addtail(markers, marker);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static void MARKER_OT_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Time Marker";
+ ot->idname= "MARKER_OT_add";
+
+ /* api callbacks */
+ ot->exec= ed_marker_add;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ************************** transform markers *************************** */
+
+
+/* operator state vars used:
+ frs: delta movement
+
+functions:
+
+ init() check selection, add customdata with old values and some lookups
+
+ apply() do the actual movement
+
+ exit() cleanup, send notifier
+
+ cancel() to escpae from modal
+
+callbacks:
+
+ exec() calls init, apply, exit
+
+ invoke() calls init, adds modal handler
+
+ modal() accept modal events while doing it, ends with apply and exit, or cancel
+
+*/
+
+typedef struct MarkerMove {
+ SpaceLink *slink;
+ ListBase *markers;
+ int event_type; /* store invoke-event, to verify */
+ int *oldframe, evtx, firstx;
+} MarkerMove;
+
+/* copy selection to temp buffer */
+/* return 0 if not OK */
+static int ed_marker_move_init(bContext *C, wmOperator *op)
+{
+ ListBase *markers= context_get_markers(C);
+ MarkerMove *mm;
+ TimeMarker *marker;
+ int totmark=0;
+ int a;
+
+ if(markers == NULL) return 0;
+
+ for (marker= markers->first; marker; marker= marker->next)
+ if (marker->flag & SELECT) totmark++;
+
+ if (totmark==0) return 0;
+
+ op->customdata= mm= MEM_callocN(sizeof(MarkerMove), "Markermove");
+ mm->slink= CTX_wm_space_data(C);
+ mm->markers= markers;
+ mm->oldframe= MEM_callocN(totmark*sizeof(int), "MarkerMove oldframe");
+
+ for (a=0, marker= markers->first; marker; marker= marker->next) {
+ if (marker->flag & SELECT) {
+ mm->oldframe[a]= marker->frame;
+ a++;
+ }
+ }
+
+ return 1;
+}
+
+/* free stuff */
+static void ed_marker_move_exit(bContext *C, wmOperator *op)
+{
+ MarkerMove *mm= op->customdata;
+
+ MEM_freeN(mm->oldframe);
+ MEM_freeN(op->customdata);
+ op->customdata= NULL;
+}
+
+static int ed_marker_move_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+{
+ if(ed_marker_move_init(C, op)) {
+ MarkerMove *mm= op->customdata;
+
+ mm->evtx= evt->x;
+ mm->firstx= evt->x;
+ mm->event_type= evt->type;
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ /* reset frs delta */
+ RNA_int_set(op->ptr, "frames", 0);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+/* note, init has to be called succesfully */
+static void ed_marker_move_apply(bContext *C, wmOperator *op)
+{
+ MarkerMove *mm= op->customdata;
+ TimeMarker *marker;
+ int a, offs;
+
+ offs= RNA_int_get(op->ptr, "frames");
+ for (a=0, marker= mm->markers->first; marker; marker= marker->next) {
+ if (marker->flag & SELECT) {
+ marker->frame= mm->oldframe[a] + offs;
+ a++;
+ }
+ }
+}
+
+/* only for modal */
+static void ed_marker_move_cancel(bContext *C, wmOperator *op)
+{
+ RNA_int_set(op->ptr, "frames", 0);
+ ed_marker_move_apply(C, op);
+ ed_marker_move_exit(C, op);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
+}
+
+
+
+static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt)
+{
+ Scene *scene= CTX_data_scene(C);
+ MarkerMove *mm= op->customdata;
+ View2D *v2d= UI_view2d_fromcontext(C);
+ TimeMarker *marker, *selmarker=NULL;
+ float dx, fac;
+ char str[256];
+
+ switch(evt->type) {
+ case ESCKEY:
+ ed_marker_move_cancel(C, op);
+ return OPERATOR_CANCELLED;
+
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE:
+ if(WM_modal_tweak_exit(evt, mm->event_type)) {
+ ed_marker_move_exit(C, op);
+ WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
+ return OPERATOR_FINISHED;
+ }
+
+ break;
+ case MOUSEMOVE:
+
+ dx= v2d->mask.xmax-v2d->mask.xmin;
+ dx= (v2d->cur.xmax-v2d->cur.xmin)/dx;
+
+ if (evt->x != mm->evtx) { /* XXX maybe init for firsttime */
+ int a, offs, totmark=0;
+
+ mm->evtx= evt->x;
+
+ fac= ((float)(evt->x - mm->firstx)*dx);
+
+ if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND))
+ apply_keyb_grid(evt->shift, evt->ctrl, &fac, 0.0, FPS, 0.1*FPS, 0);
+ else
+ apply_keyb_grid(evt->shift, evt->ctrl, &fac, 0.0, 1.0, 0.1, U.flag & USER_AUTOGRABGRID);
+
+ offs= (int)fac;
+ RNA_int_set(op->ptr, "frames", offs);
+ ed_marker_move_apply(C, op);
+
+ /* cruft below is for header print */
+ for (a=0, marker= mm->markers->first; marker; marker= marker->next) {
+ if (marker->flag & SELECT) {
+ selmarker= marker;
+ a++; totmark++;
+ }
+ }
+
+ if (totmark==1) {
+ /* we print current marker value */
+ if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) {
+ SpaceTime *stime= (SpaceTime *)mm->slink;
+ if (stime->flag & TIME_DRAWFRAMES)
+ sprintf(str, "Marker %d offset %d", selmarker->frame, offs);
+ else
+ sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
+ }
+ else if (mm->slink->spacetype == SPACE_ACTION) {
+#if 0
+XXX if (saction->flag & SACTION_DRAWTIME)
+ sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
+ else
+ sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
+#endif
+ }
+ else {
+ sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
+ }
+ }
+ else {
+ /* we only print the offset */
+ if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) {
+ SpaceTime *stime= (SpaceTime *)mm->slink;
+ if (stime->flag & TIME_DRAWFRAMES)
+ sprintf(str, "Marker offset %d ", offs);
+ else
+ sprintf(str, "Marker offset %.2f ", FRA2TIME(offs));
+ }
+#if 0
+XXX else if (mm->slink->spacetype == SPACE_ACTION) {
+ if (saction->flag & SACTION_DRAWTIME)
+ sprintf(str, "Marker offset %.2f ", FRA2TIME(offs));
+ else
+ sprintf(str, "Marker offset %.2f ", (double)(offs));
+ }
+#endif
+ else {
+ sprintf(str, "Marker offset %.2f ", (double)(offs));
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
+ // headerprint(str); XXX
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int ed_marker_move_exec(bContext *C, wmOperator *op)
+{
+ if(ed_marker_move_init(C, op)) {
+ ed_marker_move_apply(C, op);
+ ed_marker_move_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_PASS_THROUGH;
+}
+
+static void MARKER_OT_move(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Move Time Marker";
+ ot->idname= "MARKER_OT_move";
+
+ /* api callbacks */
+ ot->exec= ed_marker_move_exec;
+ ot->invoke= ed_marker_move_invoke;
+ ot->modal= ed_marker_move_modal;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* rna storage */
+ RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX);
+}
+
+/* ************************** duplicate markers *************************** */
+
+/* operator state vars used:
+ frs: delta movement
+
+functions:
+
+ apply() do the actual duplicate
+
+callbacks:
+
+ exec() calls apply, move_exec
+
+ invoke() calls apply, move_invoke
+
+ modal() uses move_modal
+
+*/
+
+
+/* duplicate selected TimeMarkers */
+static void ed_marker_duplicate_apply(bContext *C, wmOperator *op)
+{
+ ListBase *markers= context_get_markers(C);
+ TimeMarker *marker, *newmarker;
+
+ if(markers == NULL) return;
+
+ /* go through the list of markers, duplicate selected markers and add duplicated copies
+ * to the begining of the list (unselect original markers) */
+ for(marker= markers->first; marker; marker= marker->next) {
+ if(marker->flag & SELECT){
+ /* unselect selected marker */
+ marker->flag &= ~SELECT;
+ /* create and set up new marker */
+ newmarker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
+ newmarker->flag= SELECT;
+ newmarker->frame= marker->frame;
+ BLI_strncpy(newmarker->name, marker->name, sizeof(marker->name));
+ /* new marker is added to the begining of list */
+ BLI_addhead(markers, newmarker);
+ }
+ }
+}
+
+static int ed_marker_duplicate_exec(bContext *C, wmOperator *op)
+{
+ ed_marker_duplicate_apply(C, op);
+ ed_marker_move_exec(C, op); /* assumes frs delta set */
+
+ return OPERATOR_FINISHED;
+
+}
+
+static int ed_marker_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+{
+ ed_marker_duplicate_apply(C, op);
+ return ed_marker_move_invoke(C, op, evt);
+}
+
+static void MARKER_OT_duplicate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Duplicate Time Marker";
+ ot->idname= "MARKER_OT_duplicate";
+
+ /* api callbacks */
+ ot->exec= ed_marker_duplicate_exec;
+ ot->invoke= ed_marker_duplicate_invoke;
+ ot->modal= ed_marker_move_modal;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* rna storage */
+ RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX);
+}
+
+/* ************************** selection ************************************/
+
+/* select/deselect TimeMarker at current frame */
+static void select_timeline_marker_frame(ListBase *markers, int frame, unsigned char shift)
+{
+ TimeMarker *marker;
+ int select=0;
+
+ for(marker= markers->first; marker; marker= marker->next) {
+ /* if Shift is not set, then deselect Markers */
+ if(!shift) marker->flag &= ~SELECT;
+ /* this way a not-shift select will allways give 1 selected marker */
+ if((marker->frame == frame) && (!select)) {
+ if(marker->flag & SELECT)
+ marker->flag &= ~SELECT;
+ else
+ marker->flag |= SELECT;
+ select = 1;
+ }
+ }
+}
+
+int find_nearest_marker_time(ListBase *markers, float dx)
+{
+ TimeMarker *marker, *nearest= NULL;
+ float dist, min_dist= 1000000;
+
+ for(marker= markers->first; marker; marker= marker->next) {
+ dist = ABS((float)marker->frame - dx);
+ if(dist < min_dist){
+ min_dist= dist;
+ nearest= marker;
+ }
+ }
+
+ if(nearest) return nearest->frame;
+ else return (int)floor(dx); /* hrmf? */
+}
+
+
+static int ed_marker_select(bContext *C, wmEvent *evt, int extend)
+{
+ ListBase *markers= context_get_markers(C);
+ View2D *v2d= UI_view2d_fromcontext(C);
+ float viewx;
+ int x, y, cfra;
+
+ if(markers == NULL)
+ return OPERATOR_PASS_THROUGH;
+
+ x= evt->x - CTX_wm_region(C)->winrct.xmin;
+ y= evt->y - CTX_wm_region(C)->winrct.ymin;
+
+ UI_view2d_region_to_view(v2d, x, y, &viewx, NULL);
+
+ cfra= find_nearest_marker_time(markers, viewx);
+
+ if (extend)
+ select_timeline_marker_frame(markers, cfra, 1);
+ else
+ select_timeline_marker_frame(markers, cfra, 0);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
+
+ /* allowing tweaks */
+ return OPERATOR_PASS_THROUGH;
+}
+
+static int ed_marker_select_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+{
+ short extend= RNA_boolean_get(op->ptr, "extend");
+ return ed_marker_select(C, evt, extend);
+}
+
+static void MARKER_OT_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Time Marker";
+ ot->idname= "MARKER_OT_select";
+
+ /* api callbacks */
+ ot->invoke= ed_marker_select_invoke;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "extend the selection");
+}
+
+/* *************************** border select markers **************** */
+
+/* operator state vars used: (added by default WM callbacks)
+ xmin, ymin
+ xmax, ymax
+
+customdata: the wmGesture pointer, with subwindow
+
+callbacks:
+
+ exec() has to be filled in by user
+
+ invoke() default WM function
+ adds modal handler
+
+ modal() default WM function
+ accept modal events while doing it, calls exec(), handles ESC and border drawing
+
+ poll() has to be filled in by user for context
+*/
+
+static int ed_marker_border_select_exec(bContext *C, wmOperator *op)
+{
+ View2D *v2d= UI_view2d_fromcontext(C);
+ ListBase *markers= context_get_markers(C);
+ TimeMarker *marker;
+ float xminf, xmaxf, yminf, ymaxf;
+ int event_type= RNA_int_get(op->ptr, "event_type");
+ int xmin= RNA_int_get(op->ptr, "xmin");
+ int xmax= RNA_int_get(op->ptr, "xmax");
+ int ymin= RNA_int_get(op->ptr, "ymin");
+ int ymax= RNA_int_get(op->ptr, "ymax");
+
+ UI_view2d_region_to_view(v2d, xmin, ymin, &xminf, &yminf);
+ UI_view2d_region_to_view(v2d, xmax, ymax, &xmaxf, &ymaxf);
+
+ /* XXX disputable */
+ if(yminf > 30.0f || ymaxf < 0.0f)
+ return 0;
+
+ if(markers == NULL)
+ return 0;
+
+ /* XXX marker context */
+ for(marker= markers->first; marker; marker= marker->next) {
+ if ((marker->frame > xminf) && (marker->frame <= xmaxf)) {
+ switch (event_type) {
+ case LEFTMOUSE:
+ if ((marker->flag & SELECT) == 0)
+ marker->flag |= SELECT;
+ break;
+ case RIGHTMOUSE:
+ if (marker->flag & SELECT)
+ marker->flag &= ~SELECT;
+ break;
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
+
+ return 1;
+}
+
+static void MARKER_OT_select_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Marker Border select";
+ ot->idname= "MARKER_OT_select_border";
+
+ /* api callbacks */
+ ot->exec= ed_marker_border_select_exec;
+ ot->invoke= WM_border_select_invoke;
+ ot->modal= WM_border_select_modal;
+
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* rna */
+ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+}
+
+/* *********************** (de)select all ***************** */
+
+static int ed_marker_select_all_exec(bContext *C, wmOperator *op)
+{
+ ListBase *markers= context_get_markers(C);
+ TimeMarker *marker;
+ int select= RNA_int_get(op->ptr, "select_type");
+
+ if(markers == NULL)
+ return OPERATOR_CANCELLED;
+
+ if(RNA_boolean_get(op->ptr, "select_swap")) {
+ for(marker= markers->first; marker; marker= marker->next) {
+ if(marker->flag & SELECT)
+ break;
+ }
+ if(marker)
+ select= 0;
+ else
+ select= 1;
+ }
+
+ for(marker= markers->first; marker; marker= marker->next) {
+ if(select)
+ marker->flag |= SELECT;
+ else
+ marker->flag &= ~SELECT;
+ }
+
+ WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static int ed_marker_select_all_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+{
+ RNA_boolean_set(op->ptr, "select_swap", 1);
+
+ return ed_marker_select_all_exec(C, op);
+}
+
+static void MARKER_OT_select_all_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "(De)select all markers";
+ ot->idname= "MARKER_OT_select_all_toggle";
+
+ /* api callbacks */
+ ot->exec= ed_marker_select_all_exec;
+ ot->invoke= ed_marker_select_all_invoke;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* rna */
+ RNA_def_boolean(ot->srna, "select_swap", 0, "Select Swap", "");
+ RNA_def_int(ot->srna, "select_type", 0, INT_MIN, INT_MAX, "Select Type", "", INT_MIN, INT_MAX);
+}
+
+/* ******************************* remove marker ***************** */
+
+/* remove selected TimeMarkers */
+static int ed_marker_delete_exec(bContext *C, wmOperator *op)
+{
+ ListBase *markers= context_get_markers(C);
+ TimeMarker *marker, *nmarker;
+ short changed= 0;
+
+ if(markers == NULL)
+ return OPERATOR_CANCELLED;
+
+ for(marker= markers->first; marker; marker= nmarker) {
+ nmarker= marker->next;
+ if(marker->flag & SELECT) {
+ BLI_freelinkN(markers, marker);
+ changed= 1;
+ }
+ }
+
+ if(changed) {
+ WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
+ }
+ return OPERATOR_FINISHED;
+}
+
+
+static void MARKER_OT_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete Markers";
+ ot->idname= "MARKER_OT_delete";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= ed_marker_delete_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+
+/* ************************** registration **********************************/
+
+/* called in screen_ops.c:ED_operatortypes_screen() */
+void ED_marker_operatortypes(void)
+{
+ WM_operatortype_append(MARKER_OT_add);
+ WM_operatortype_append(MARKER_OT_move);
+ WM_operatortype_append(MARKER_OT_duplicate);
+ WM_operatortype_append(MARKER_OT_select);
+ WM_operatortype_append(MARKER_OT_select_border);
+ WM_operatortype_append(MARKER_OT_select_all_toggle);
+ WM_operatortype_append(MARKER_OT_delete);
+}
+
+/* called in screen_ops.c:ED_keymap_screen() */
+void ED_marker_keymap(wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "Markers", 0, 0);
+
+ WM_keymap_verify_item(keymap, "MARKER_OT_add", MKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "MARKER_OT_move", EVT_TWEAK_S, KM_ANY, 0, 0);
+ WM_keymap_verify_item(keymap, "MARKER_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_verify_item(keymap, "MARKER_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "MARKER_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1);
+ WM_keymap_verify_item(keymap, "MARKER_OT_select_border", BKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "MARKER_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "MARKER_OT_delete", XKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "MARKER_OT_move", GKEY, KM_PRESS, 0, 0);
+
+}
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
new file mode 100644
index 00000000000..e899cc1d520
--- /dev/null
+++ b/source/blender/editors/animation/anim_ops.c
@@ -0,0 +1,408 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation, Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_utildefines.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h" // XXX remove?
+#include "ED_markers.h"
+#include "ED_screen.h"
+
+/* ********************** frame change operator ***************************/
+
+/* Set any flags that are necessary to indicate modal time-changing operation */
+static int change_frame_init(bContext *C, wmOperator *op)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+
+ if (curarea == NULL)
+ return 0;
+
+ if (curarea->spacetype == SPACE_TIME) {
+ SpaceTime *stime= (SpaceTime*)CTX_wm_space_data(C);
+
+ /* timeline displays frame number only when dragging indicator */
+ // XXX make this more in line with other anim editors?
+ stime->flag |= TIME_CFRA_NUM;
+ }
+
+ return 1;
+}
+
+/* Set the new frame number */
+static void change_frame_apply(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ int cfra;
+
+ /* get frame, and clamp to MINFRAME */
+ cfra= RNA_int_get(op->ptr, "frame");
+
+ if (cfra < MINFRAME) cfra= MINFRAME;
+ CFRA= cfra;
+
+ WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+}
+
+/* Clear any temp flags */
+static void change_frame_exit(bContext *C, wmOperator *op)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+
+ if (curarea == NULL)
+ return;
+
+ if (curarea->spacetype == SPACE_TIME) {
+ SpaceTime *stime= (SpaceTime*)CTX_wm_space_data(C);
+
+ /* timeline displays frame number only when dragging indicator */
+ // XXX make this more in line with other anim editors?
+ stime->flag &= ~TIME_CFRA_NUM;
+ }
+}
+
+/* ---- */
+
+/* Non-modal callback for running operator without user input */
+static int change_frame_exec(bContext *C, wmOperator *op)
+{
+ if (!change_frame_init(C, op))
+ return OPERATOR_CANCELLED;
+
+ change_frame_apply(C, op);
+ change_frame_exit(C, op);
+ return OPERATOR_FINISHED;
+}
+
+/* ---- */
+
+/* Get frame from mouse coordinates */
+static int frame_from_event(bContext *C, wmEvent *event)
+{
+ ARegion *region= CTX_wm_region(C);
+ float viewx;
+ int x, y;
+
+ /* convert screen coordinates to region coordinates */
+ x= event->x - region->winrct.xmin;
+ y= event->y - region->winrct.ymin;
+
+ /* convert from region coordinates to View2D 'tot' space */
+ UI_view2d_region_to_view(&region->v2d, x, y, &viewx, NULL);
+
+ /* round result to nearest int (frames are ints!) */
+ return (int)floor(viewx+0.5f);
+}
+
+/* Modal Operator init */
+static int change_frame_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ /* Change to frame that mouse is over before adding modal handler,
+ * as user could click on a single frame (jump to frame) as well as
+ * click-dragging over a range (modal scrubbing).
+ */
+ RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
+
+ change_frame_init(C, op);
+ change_frame_apply(C, op);
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* In case modal operator is cancelled */
+static int change_frame_cancel(bContext *C, wmOperator *op)
+{
+ change_frame_exit(C, op);
+ return OPERATOR_CANCELLED;
+}
+
+/* Modal event handling of frame changing */
+static int change_frame_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ /* execute the events */
+ switch (event->type) {
+ case ESCKEY:
+ change_frame_exit(C, op);
+ return OPERATOR_FINISHED;
+
+ case MOUSEMOVE:
+ RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
+ change_frame_apply(C, op);
+ break;
+
+ case LEFTMOUSE:
+ case RIGHTMOUSE:
+ /* we check for either mouse-button to end, as checking for ACTIONMOUSE (which is used to init
+ * the modal op) doesn't work for some reason
+ */
+ if (event->val==0) {
+ change_frame_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void ANIM_OT_change_frame(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Change frame";
+ ot->idname= "ANIM_OT_change_frame";
+
+ /* api callbacks */
+ ot->exec= change_frame_exec;
+ ot->invoke= change_frame_invoke;
+ ot->cancel= change_frame_cancel;
+ ot->modal= change_frame_modal;
+
+ /* rna */
+ RNA_def_int(ot->srna, "frame", 0, 1, MAXFRAME, "Frame", "", 1, MAXFRAME);
+}
+
+/* ****************** set preview range operator ****************************/
+
+static int previewrange_define_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ ARegion *ar= CTX_wm_region(C);
+ float sfra, efra;
+ int xmin, xmax;
+
+ /* get min/max values from border select rect (already in region coordinates, not screen) */
+ xmin= RNA_int_get(op->ptr, "xmin");
+ xmax= RNA_int_get(op->ptr, "xmax");
+
+ /* convert min/max values to frames (i.e. region to 'tot' rect) */
+ UI_view2d_region_to_view(&ar->v2d, xmin, 0, &sfra, NULL);
+ UI_view2d_region_to_view(&ar->v2d, xmax, 0, &efra, NULL);
+
+ /* set start/end frames for preview-range
+ * - must clamp within allowable limits
+ * - end must not be before start (though this won't occur most of the time)
+ */
+ if (sfra < 1) sfra = 1.0f;
+ if (efra < 1) efra = 1.0f;
+ if (efra < sfra) efra= sfra;
+
+ scene->r.psfra= (int)floor(sfra + 0.5f);
+ scene->r.pefra= (int)floor(efra + 0.5f);
+
+ return OPERATOR_FINISHED;
+}
+
+void ANIM_OT_previewrange_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Preview Range";
+ ot->idname= "ANIM_OT_previewrange_set";
+
+ /* api callbacks */
+ ot->invoke= WM_border_select_invoke;
+ ot->exec= previewrange_define_exec;
+ ot->modal= WM_border_select_modal;
+
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* rna */
+ /* used to define frame range */
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ /* these are not used, but are needed by borderselect gesture operator stuff */
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+}
+
+/* ****************** clear preview range operator ****************************/
+
+static int previewrange_clear_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ ScrArea *curarea= CTX_wm_area(C);
+
+ /* sanity checks */
+ if (ELEM(NULL, scene, curarea))
+ return OPERATOR_CANCELLED;
+
+ /* simply clear values */
+ scene->r.psfra= 0;
+ scene->r.pefra= 0;
+
+ ED_area_tag_redraw(curarea);
+
+ return OPERATOR_FINISHED;
+}
+
+void ANIM_OT_previewrange_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Clear Preview Range";
+ ot->idname= "ANIM_OT_previewrange_clear";
+
+ /* api callbacks */
+ ot->exec= previewrange_clear_exec;
+
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ****************** time display toggle operator ****************************/
+
+static int toggle_time_exec(bContext *C, wmOperator *op)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+
+ if (curarea == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* simply toggle draw frames flag in applicable spaces */
+ // XXX or should relevant spaces define their own version of this?
+ switch (curarea->spacetype) {
+ case SPACE_TIME: /* TimeLine */
+ {
+ SpaceTime *stime= (SpaceTime *)CTX_wm_space_data(C);
+ stime->flag ^= TIME_DRAWFRAMES;
+ }
+ break;
+ case SPACE_ACTION: /* Action Editor */
+ {
+ SpaceAction *saction= (SpaceAction *)CTX_wm_space_data(C);
+ saction->flag ^= SACTION_DRAWTIME;
+ }
+ break;
+ case SPACE_IPO: /* Graph Editor */
+ {
+ SpaceIpo *sipo= (SpaceIpo *)CTX_wm_space_data(C);
+ sipo->flag ^= SIPO_DRAWTIME;
+ }
+ break;
+ case SPACE_NLA: /* NLA Editor */
+ {
+ SpaceNla *snla= (SpaceNla *)CTX_wm_space_data(C);
+ snla->flag ^= SNLA_DRAWTIME;
+ }
+ break;
+ case SPACE_SEQ: /* Sequencer */
+ {
+ SpaceSeq *sseq= (SpaceSeq *)CTX_wm_space_data(C);
+ sseq->flag ^= SEQ_DRAWFRAMES;
+ }
+ break;
+
+ default: /* editor doesn't show frames */
+ return OPERATOR_CANCELLED; // XXX or should we pass through instead?
+ }
+
+ ED_area_tag_redraw(curarea);
+
+ return OPERATOR_FINISHED;
+}
+
+void ANIM_OT_time_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Toggle Frames/Seconds";
+ ot->idname= "ANIM_OT_time_toggle";
+
+ /* api callbacks */
+ ot->exec= toggle_time_exec;
+
+ ot->poll= ED_operator_areaactive;
+}
+
+/* ************************** registration **********************************/
+
+void ED_operatortypes_anim(void)
+{
+ WM_operatortype_append(ANIM_OT_change_frame);
+ WM_operatortype_append(ANIM_OT_time_toggle);
+
+ WM_operatortype_append(ANIM_OT_previewrange_set);
+ WM_operatortype_append(ANIM_OT_previewrange_clear);
+
+ // XXX this is used all over... maybe for screen instead?
+ WM_operatortype_append(ANIM_OT_insert_keyframe);
+ WM_operatortype_append(ANIM_OT_delete_keyframe);
+ WM_operatortype_append(ANIM_OT_insert_keyframe_menu);
+ //WM_operatortype_append(ANIM_OT_delete_keyframe_menu);
+ WM_operatortype_append(ANIM_OT_insert_keyframe_button);
+ WM_operatortype_append(ANIM_OT_delete_keyframe_button);
+ WM_operatortype_append(ANIM_OT_delete_keyframe_old); // xxx remove?
+
+ WM_operatortype_append(ANIM_OT_add_driver_button);
+ WM_operatortype_append(ANIM_OT_remove_driver_button);
+
+ WM_operatortype_append(ANIM_OT_keyingset_add_new);
+ WM_operatortype_append(ANIM_OT_keyingset_add_destination);
+}
+
+void ED_keymap_anim(wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "Animation", 0, 0);
+
+ /* frame management */
+ /* NOTE: 'ACTIONMOUSE' not 'LEFTMOUSE', as user may have swapped mouse-buttons */
+ WM_keymap_verify_item(keymap, "ANIM_OT_change_frame", ACTIONMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "ANIM_OT_time_toggle", TKEY, KM_PRESS, KM_CTRL, 0);
+
+ /* preview range */
+ WM_keymap_verify_item(keymap, "ANIM_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_verify_item(keymap, "ANIM_OT_previewrange_clear", PKEY, KM_PRESS, KM_ALT, 0);
+}
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
new file mode 100644
index 00000000000..9c401289011
--- /dev/null
+++ b/source/blender/editors/animation/drivers.c
@@ -0,0 +1,292 @@
+/* Testing code for 2.5 animation system
+ * Copyright 2009, Joshua Leung
+ */
+
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_dynstr.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_key_types.h"
+#include "DNA_object_types.h"
+#include "DNA_material_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_action.h"
+#include "BKE_constraint.h"
+#include "BKE_fcurve.h"
+#include "BKE_utildefines.h"
+#include "BKE_context.h"
+#include "BKE_report.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_edit.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_types.h"
+
+/* ************************************************** */
+/* Animation Data Validation */
+
+/* Get (or add relevant data to be able to do so) F-Curve from the driver stack,
+ * for the given Animation Data block. This assumes that all the destinations are valid.
+ */
+FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_index, short add)
+{
+ AnimData *adt;
+ FCurve *fcu;
+
+ /* sanity checks */
+ if ELEM(NULL, id, rna_path)
+ return NULL;
+
+ /* init animdata if none available yet */
+ adt= BKE_animdata_from_id(id);
+ if ((adt == NULL) && (add))
+ adt= BKE_id_add_animdata(id);
+ if (adt == NULL) {
+ /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
+ return NULL;
+ }
+
+ /* try to find f-curve matching for this setting
+ * - add if not found and allowed to add one
+ * TODO: add auto-grouping support? how this works will need to be resolved
+ */
+ fcu= list_find_fcurve(&adt->drivers, rna_path, array_index);
+
+ if ((fcu == NULL) && (add)) {
+ /* use default settings to make a F-Curve */
+ fcu= MEM_callocN(sizeof(FCurve), "FCurve");
+
+ fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
+
+ /* store path - make copy, and store that */
+ fcu->rna_path= BLI_strdupn(rna_path, strlen(rna_path));
+ fcu->array_index= array_index;
+
+ /* add some new driver data */
+ fcu->driver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
+
+ /* add simple generator modifier for driver so that there is some visible representation */
+ fcurve_add_modifier(fcu, FMODIFIER_TYPE_GENERATOR);
+
+ /* just add F-Curve to end of driver list */
+ BLI_addtail(&adt->drivers, fcu);
+ }
+
+ /* return the F-Curve */
+ return fcu;
+}
+
+/* ************************************************** */
+/* Driver Management API */
+
+/* Main Driver Management API calls:
+ * Add a new driver for the specified property on the given ID block
+ */
+short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short flag)
+{
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ FCurve *fcu;
+
+ /* validate pointer first - exit if failure */
+ RNA_id_pointer_create(id, &id_ptr);
+ if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
+ printf("Insert Key: Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path);
+ return 0;
+ }
+
+ /* create F-Curve with Driver */
+ fcu= verify_driver_fcurve(id, rna_path, array_index, 1);
+
+ /* done */
+ return (fcu != NULL);
+}
+
+/* Main Driver Management API calls:
+ * Remove the driver for the specified property on the given ID block (if available)
+ */
+short ANIM_remove_driver (struct ID *id, const char rna_path[], int array_index, short flag)
+{
+ AnimData *adt;
+ FCurve *fcu;
+
+ /* get F-Curve
+ * Note: here is one of the places where we don't want new F-Curve + Driver added!
+ * so 'add' var must be 0
+ */
+ /* we don't check the validity of the path here yet, but it should be ok... */
+ fcu= verify_driver_fcurve(id, rna_path, array_index, 0);
+ adt= BKE_animdata_from_id(id);
+
+ /* only continue if we have an driver to remove */
+ if (adt && fcu) {
+ /* remove F-Curve from driver stack, then free it */
+ BLI_remlink(&adt->drivers, fcu);
+ free_fcurve(fcu);
+
+ /* done successfully */
+ return 1;
+ }
+
+ /* failed */
+ return 0;
+}
+
+
+/* ************************************************** */
+/* UI-Button Interface */
+
+/* Add Driver Button Operator ------------------------ */
+
+static int add_driver_button_exec (bContext *C, wmOperator *op)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop= NULL;
+ char *path;
+ short success= 0;
+ int a, index, length, all= RNA_boolean_get(op->ptr, "all");
+
+ /* try to insert keyframe using property retrieved from UI */
+ memset(&ptr, 0, sizeof(PointerRNA));
+ uiAnimContextProperty(C, &ptr, &prop, &index);
+
+ if (ptr.data && prop && RNA_property_animateable(ptr.data, prop)) {
+ path= RNA_path_from_ID_to_property(&ptr, prop);
+
+ if (path) {
+ if (all) {
+ length= RNA_property_array_length(prop);
+
+ if (length) index= 0;
+ else length= 1;
+ }
+ else
+ length= 1;
+
+ for (a=0; a<length; a++)
+ success+= ANIM_add_driver(ptr.id.data, path, index+a, 0);
+
+ MEM_freeN(path);
+ }
+ }
+
+ if (success) {
+ /* send updates */
+ ED_anim_dag_flush_update(C);
+
+ /* for now, only send ND_KEYS for KeyingSets */
+ WM_event_add_notifier(C, ND_KEYS, NULL); // XXX
+ }
+
+ return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
+}
+
+void ANIM_OT_add_driver_button (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Driver";
+ ot->idname= "ANIM_OT_add_driver_button";
+
+ /* callbacks */
+ ot->exec= add_driver_button_exec;
+ //op->poll= ???
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Insert a keyframe for all element of the array.");
+}
+
+/* Remove Driver Button Operator ------------------------ */
+
+static int remove_driver_button_exec (bContext *C, wmOperator *op)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop= NULL;
+ char *path;
+ short success= 0;
+ int a, index, length, all= RNA_boolean_get(op->ptr, "all");
+
+ /* try to insert keyframe using property retrieved from UI */
+ memset(&ptr, 0, sizeof(PointerRNA));
+ uiAnimContextProperty(C, &ptr, &prop, &index);
+
+ if (ptr.data && prop) {
+ path= RNA_path_from_ID_to_property(&ptr, prop);
+
+ if (path) {
+ if (all) {
+ length= RNA_property_array_length(prop);
+
+ if(length) index= 0;
+ else length= 1;
+ }
+ else
+ length= 1;
+
+ for (a=0; a<length; a++)
+ success+= ANIM_remove_driver(ptr.id.data, path, index+a, 0);
+
+ MEM_freeN(path);
+ }
+ }
+
+
+ if (success) {
+ /* send updates */
+ ED_anim_dag_flush_update(C);
+
+ /* for now, only send ND_KEYS for KeyingSets */
+ WM_event_add_notifier(C, ND_KEYS, NULL); // XXX
+ }
+
+ return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
+}
+
+void ANIM_OT_remove_driver_button (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Remove Driver";
+ ot->idname= "ANIM_OT_remove_driver_button";
+
+ /* callbacks */
+ ot->exec= remove_driver_button_exec;
+ //op->poll= ???
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Delete keyfames from all elements of the array.");
+}
+
+/* ************************************************** */
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
new file mode 100644
index 00000000000..cfbd6d2bced
--- /dev/null
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -0,0 +1,660 @@
+/**
+ * $Id: drawaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* System includes ----------------------------------------------------- */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+/* Types --------------------------------------------------------------- */
+
+#include "DNA_listBase.h"
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_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 "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_action.h"
+#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+#include "BKE_global.h" // XXX remove me!
+#include "BKE_context.h"
+#include "BKE_utildefines.h"
+
+/* Everything from source (BIF, BDR, BSE) ------------------------------ */
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_draw.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+/* *************************** Keyframe Drawing *************************** */
+
+static void add_bezt_to_keycolumnslist(ListBase *keys, BezTriple *bezt)
+{
+ /* The equivalent of add_to_cfra_elem except this version
+ * makes ActKeyColumns - one of the two datatypes required
+ * for action editor drawing.
+ */
+ ActKeyColumn *ak, *akn;
+
+ if (ELEM(NULL, keys, bezt)) return;
+
+ /* try to any existing key to replace, or where to insert after */
+ for (ak= keys->last; ak; ak= ak->prev) {
+ /* do because of double keys */
+ if (ak->cfra == bezt->vec[1][0]) {
+ /* set selection status and 'touched' status */
+ if (BEZSELECTED(bezt)) ak->sel = SELECT;
+ ak->modified += 1;
+
+ return;
+ }
+ else if (ak->cfra < bezt->vec[1][0]) break;
+ }
+
+ /* add new block */
+ akn= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
+ if (ak) BLI_insertlinkafter(keys, ak, akn);
+ else BLI_addtail(keys, akn);
+
+ akn->cfra= bezt->vec[1][0];
+ akn->modified += 1;
+
+ // TODO: handle type = bezt->h1 or bezt->h2
+ akn->handle_type= 0;
+
+ if (BEZSELECTED(bezt))
+ akn->sel = SELECT;
+ else
+ akn->sel = 0;
+}
+
+static void add_bezt_to_keyblockslist(ListBase *blocks, FCurve *fcu, int index)
+{
+ /* The equivalent of add_to_cfra_elem except this version
+ * makes ActKeyBlocks - one of the two datatypes required
+ * for action editor drawing.
+ */
+ ActKeyBlock *ab, *abn;
+ BezTriple *beztn=NULL, *prev=NULL;
+ BezTriple *bezt;
+ int v;
+
+ /* get beztriples */
+ beztn= (fcu->bezt + index);
+
+ /* we need to go through all beztriples, as they may not be in order (i.e. during transform) */
+ for (v=0, bezt=fcu->bezt; v < fcu->totvert; v++, bezt++) {
+ /* skip if beztriple is current */
+ if (v != index) {
+ /* check if beztriple is immediately before */
+ if (beztn->vec[1][0] > bezt->vec[1][0]) {
+ /* check if closer than previous was */
+ if (prev) {
+ if (prev->vec[1][0] < bezt->vec[1][0])
+ prev= bezt;
+ }
+ else {
+ prev= bezt;
+ }
+ }
+ }
+ }
+
+ /* check if block needed - same value(s)?
+ * -> firstly, handles must have same central value as each other
+ * -> secondly, handles which control that section of the curve must be constant
+ */
+ if ((!prev) || (!beztn)) return;
+ if (IS_EQ(beztn->vec[1][1], prev->vec[1][1])==0) return;
+ if (IS_EQ(beztn->vec[1][1], beztn->vec[0][1])==0) return;
+ if (IS_EQ(prev->vec[1][1], prev->vec[2][1])==0) return;
+
+ /* try to find a keyblock that starts on the previous beztriple
+ * Note: we can't search from end to try to optimise this as it causes errors there's
+ * an A ___ B |---| B situation
+ */
+ // FIXME: here there is a bug where we are trying to get the summary for the following channels
+ // A|--------------|A ______________ B|--------------|B
+ // A|------------------------------------------------|A
+ // A|----|A|---|A|-----------------------------------|A
+ for (ab= blocks->first; ab; ab= ab->next) {
+ /* check if alter existing block or add new block */
+ if (ab->start == prev->vec[1][0]) {
+ /* set selection status and 'touched' status */
+ if (BEZSELECTED(beztn)) ab->sel = SELECT;
+ ab->modified += 1;
+
+ return;
+ }
+ else if (ab->start < prev->vec[1][0]) break;
+ }
+
+ /* add new block */
+ abn= MEM_callocN(sizeof(ActKeyBlock), "ActKeyBlock");
+ if (ab) BLI_insertlinkbefore(blocks, ab, abn);
+ else BLI_addtail(blocks, abn);
+
+ abn->start= prev->vec[1][0];
+ abn->end= beztn->vec[1][0];
+ abn->val= beztn->vec[1][1];
+
+ if (BEZSELECTED(prev) || BEZSELECTED(beztn))
+ abn->sel = SELECT;
+ else
+ abn->sel = 0;
+ abn->modified = 1;
+}
+
+/* helper function - find actkeycolumn that occurs on cframe */
+static ActKeyColumn *cfra_find_actkeycolumn (ListBase *keys, float cframe)
+{
+ ActKeyColumn *ak, *ak2;
+
+ if (keys==NULL)
+ return NULL;
+
+ /* search from both ends at the same time, and stop if we find match or if both ends meet */
+ for (ak=keys->first, ak2=keys->last; ak && ak2; ak=ak->next, ak2=ak2->prev) {
+ /* return whichever end encounters the frame */
+ if (ak->cfra == cframe)
+ return ak;
+ if (ak2->cfra == cframe)
+ return ak2;
+
+ /* no matches on either end, so return NULL */
+ if (ak == ak2)
+ return NULL;
+ }
+
+ return NULL;
+}
+
+#if 0 // disabled, as some intel cards have problems with this
+/* Draw a simple diamond shape with a filled in center (in screen space) */
+static void draw_key_but(int x, int y, short w, short h, int sel)
+{
+ int xmin= x, ymin= y;
+ int xmax= x+w-1, ymax= y+h-1;
+ int xc= (xmin+xmax)/2, yc= (ymin+ymax)/2;
+
+ /* interior - hardcoded colors (for selected and unselected only) */
+ if (sel) glColor3ub(0xF1, 0xCA, 0x13);
+ else glColor3ub(0xE9, 0xE9, 0xE9);
+
+ glBegin(GL_QUADS);
+ glVertex2i(xc, ymin);
+ glVertex2i(xmax, yc);
+ glVertex2i(xc, ymax);
+ glVertex2i(xmin, yc);
+ glEnd();
+
+
+ /* outline */
+ glColor3ub(0, 0, 0);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2i(xc, ymin);
+ glVertex2i(xmax, yc);
+ glVertex2i(xc, ymax);
+ glVertex2i(xmin, yc);
+ glEnd();
+}
+#endif
+
+static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, float ypos)
+{
+ ActKeyColumn *ak;
+ ActKeyBlock *ab;
+
+ glEnable(GL_BLEND);
+
+ /* draw keyblocks */
+ if (blocks) {
+ for (ab= blocks->first; ab; ab= ab->next) {
+ short startCurves, endCurves, totCurves;
+
+ /* find out how many curves occur at each keyframe */
+ ak= cfra_find_actkeycolumn(keys, ab->start);
+ startCurves = (ak)? ak->totcurve: 0;
+
+ ak= cfra_find_actkeycolumn(keys, ab->end);
+ endCurves = (ak)? ak->totcurve: 0;
+
+ /* only draw keyblock if it appears in at all of the keyframes at lowest end */
+ if (!startCurves && !endCurves)
+ continue;
+ else
+ totCurves = (startCurves>endCurves)? endCurves: startCurves;
+
+ if (ab->totcurve >= totCurves) {
+ int sc_xa, sc_xb, sc_ya, sc_yb;
+
+ /* get co-ordinates of block */
+ gla2DDrawTranslatePt(di, ab->start, ypos, &sc_xa, &sc_ya);
+ gla2DDrawTranslatePt(di, ab->end, ypos, &sc_xb, &sc_yb);
+
+ /* draw block */
+ if (ab->sel)
+ UI_ThemeColor4(TH_STRIP_SELECT);
+ else
+ UI_ThemeColor4(TH_STRIP);
+ glRectf((float)sc_xa, (float)sc_ya-3, (float)sc_xb, (float)sc_yb+5);
+ }
+ }
+ }
+
+ /* draw keys */
+ if (keys) {
+ for (ak= keys->first; ak; ak= ak->next) {
+ int sc_x, sc_y;
+
+ /* get co-ordinate to draw at */
+ gla2DDrawTranslatePt(di, ak->cfra, ypos, &sc_x, &sc_y);
+
+ /* draw using icons - old way which is slower but more proven */
+ if (ak->sel & SELECT) UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE2, 1.0f);
+ else UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE3, 1.0f);
+
+ /* draw using OpenGL - slightly uglier but faster */
+ // NOTE: disabled for now, as some intel cards seem to have problems with this
+ //draw_key_but(sc_x-5, sc_y-4, 11, 11, (ak->sel & SELECT));
+ }
+ }
+
+ glDisable(GL_BLEND);
+}
+
+/* *************************** Channel Drawing Funcs *************************** */
+
+void draw_scene_channel(gla2DDrawInfo *di, ActKeysInc *aki, Scene *sce, float ypos)
+{
+ ListBase keys = {0, 0};
+ ListBase blocks = {0, 0};
+
+ scene_to_keylist(sce, &keys, &blocks, aki);
+ draw_keylist(di, &keys, &blocks, ypos);
+
+ BLI_freelistN(&keys);
+ BLI_freelistN(&blocks);
+}
+
+void draw_object_channel(gla2DDrawInfo *di, ActKeysInc *aki, Object *ob, float ypos)
+{
+ ListBase keys = {0, 0};
+ ListBase blocks = {0, 0};
+
+ ob_to_keylist(ob, &keys, &blocks, aki);
+ draw_keylist(di, &keys, &blocks, ypos);
+
+ BLI_freelistN(&keys);
+ BLI_freelistN(&blocks);
+}
+
+void draw_fcurve_channel(gla2DDrawInfo *di, ActKeysInc *aki, FCurve *fcu, float ypos)
+{
+ ListBase keys = {0, 0};
+ ListBase blocks = {0, 0};
+
+ fcurve_to_keylist(fcu, &keys, &blocks, aki);
+ draw_keylist(di, &keys, &blocks, ypos);
+
+ BLI_freelistN(&keys);
+ BLI_freelistN(&blocks);
+}
+
+void draw_agroup_channel(gla2DDrawInfo *di, ActKeysInc *aki, bActionGroup *agrp, float ypos)
+{
+ ListBase keys = {0, 0};
+ ListBase blocks = {0, 0};
+
+ agroup_to_keylist(agrp, &keys, &blocks, aki);
+ draw_keylist(di, &keys, &blocks, ypos);
+
+ BLI_freelistN(&keys);
+ BLI_freelistN(&blocks);
+}
+
+void draw_action_channel(gla2DDrawInfo *di, ActKeysInc *aki, bAction *act, float ypos)
+{
+ ListBase keys = {0, 0};
+ ListBase blocks = {0, 0};
+
+ action_to_keylist(act, &keys, &blocks, aki);
+ draw_keylist(di, &keys, &blocks, ypos);
+
+ BLI_freelistN(&keys);
+ BLI_freelistN(&blocks);
+}
+
+void draw_gpl_channel(gla2DDrawInfo *di, ActKeysInc *aki, bGPDlayer *gpl, float ypos)
+{
+ ListBase keys = {0, 0};
+
+ gpl_to_keylist(gpl, &keys, NULL, aki);
+ draw_keylist(di, &keys, NULL, ypos);
+ BLI_freelistN(&keys);
+}
+
+/* *************************** Keyframe List Conversions *************************** */
+
+void scene_to_keylist(Scene *sce, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
+{
+ if (sce) {
+ bDopeSheet *ads= (aki)? (aki->ads) : NULL;
+ AnimData *adt;
+ int filterflag;
+
+ /* get filterflag */
+ if (ads)
+ filterflag= ads->filterflag;
+ else if ((aki) && (aki->actmode == -1)) /* only set like this by NLA */
+ filterflag= ADS_FILTER_NLADUMMY;
+ else
+ filterflag= 0;
+
+ /* scene animdata */
+ if ((sce->adt) && !(filterflag & ADS_FILTER_NOSCE)) {
+ adt= sce->adt;
+
+ // TODO: when we adapt NLA system, this needs to be the NLA-scaled version
+ if (adt->action)
+ action_to_keylist(adt->action, keys, blocks, aki);
+ }
+
+ /* world animdata */
+ if ((sce->world) && (sce->world->adt) && !(filterflag & ADS_FILTER_NOWOR)) {
+ adt= sce->world->adt;
+
+ // TODO: when we adapt NLA system, this needs to be the NLA-scaled version
+ if (adt->action)
+ action_to_keylist(adt->action, keys, blocks, aki);
+ }
+ }
+}
+
+void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
+{
+ Key *key= ob_get_key(ob);
+
+ if (ob) {
+ bDopeSheet *ads= (aki)? (aki->ads) : NULL;
+ int filterflag;
+
+ /* get filterflag */
+ if (ads)
+ filterflag= ads->filterflag;
+ else
+ filterflag= 0;
+
+ /* Add action keyframes */
+ if (ob->adt && ob->adt->action)
+ action_nlascaled_to_keylist(ob, ob->adt->action, keys, blocks, aki);
+
+ /* Add shapekey keyframes (only if dopesheet allows, if it is available) */
+ // TODO: when we adapt NLA system, this needs to be the NLA-scaled version
+ if ((key && key->adt && key->adt->action) && !(filterflag & ADS_FILTER_NOSHAPEKEYS))
+ action_to_keylist(key->adt->action, keys, blocks, aki);
+
+#if 0 // XXX old animation system
+ /* Add material keyframes (only if dopesheet allows, if it is available) */
+ if ((ob->totcol) && !(filterflag & ADS_FILTER_NOMAT)) {
+ short a;
+
+ for (a=0; a<ob->totcol; a++) {
+ Material *ma= give_current_material(ob, a);
+
+ if (ELEM(NULL, ma, ma->ipo) == 0)
+ ipo_to_keylist(ma->ipo, keys, blocks, aki);
+ }
+ }
+
+ /* Add object data keyframes */
+ switch (ob->type) {
+ case OB_CAMERA: /* ------- Camera ------------ */
+ {
+ Camera *ca= (Camera *)ob->data;
+ if ((ca->ipo) && !(filterflag & ADS_FILTER_NOCAM))
+ ipo_to_keylist(ca->ipo, keys, blocks, aki);
+ }
+ break;
+ case OB_LAMP: /* ---------- Lamp ----------- */
+ {
+ Lamp *la= (Lamp *)ob->data;
+ if ((la->ipo) && !(filterflag & ADS_FILTER_NOLAM))
+ ipo_to_keylist(la->ipo, keys, blocks, aki);
+ }
+ break;
+ case OB_CURVE: /* ------- Curve ---------- */
+ {
+ Curve *cu= (Curve *)ob->data;
+ if ((cu->ipo) && !(filterflag & ADS_FILTER_NOCUR))
+ ipo_to_keylist(cu->ipo, keys, blocks, aki);
+ }
+ break;
+ }
+#endif // XXX old animation system
+ }
+}
+
+static short bezt_in_aki_range (ActKeysInc *aki, BezTriple *bezt)
+{
+ /* when aki == NULL, we don't care about range */
+ if (aki == NULL)
+ return 1;
+
+ /* if start and end are both 0, then don't care about range */
+ if (IS_EQ(aki->start, 0) && IS_EQ(aki->end, 0))
+ return 1;
+
+ /* if nla-scaling is in effect, apply appropriate scaling adjustments */
+#if 0 // XXX this was from some buggy code... do not port for now
+ if (aki->ob) {
+ float frame= get_action_frame_inv(aki->ob, bezt->vec[1][0]);
+ return IN_RANGE(frame, aki->start, aki->end);
+ }
+ else {
+ /* check if in range */
+ return IN_RANGE(bezt->vec[1][0], aki->start, aki->end);
+ }
+#endif // XXX this was from some buggy code... do not port for now
+ return 1;
+}
+
+void fcurve_to_keylist(FCurve *fcu, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
+{
+ BezTriple *bezt;
+ ActKeyColumn *ak, *ak2;
+ ActKeyBlock *ab, *ab2;
+ int v;
+
+ if (fcu && fcu->totvert && fcu->bezt) {
+ /* loop through beztriples, making ActKeys and ActKeyBlocks */
+ bezt= fcu->bezt;
+
+ for (v=0; v < fcu->totvert; v++, bezt++) {
+ /* only if keyframe is in range (optimisation) */
+ if (bezt_in_aki_range(aki, bezt)) {
+ add_bezt_to_keycolumnslist(keys, bezt);
+ if (blocks) add_bezt_to_keyblockslist(blocks, fcu, v);
+ }
+ }
+
+ /* update the number of curves that elements have appeared in */
+ if (keys) {
+ for (ak=keys->first, ak2=keys->last; ak && ak2; ak=ak->next, ak2=ak2->prev) {
+ if (ak->modified) {
+ ak->modified = 0;
+ ak->totcurve += 1;
+ }
+
+ if (ak == ak2)
+ break;
+
+ if (ak2->modified) {
+ ak2->modified = 0;
+ ak2->totcurve += 1;
+ }
+ }
+ }
+ if (blocks) {
+ for (ab=blocks->first, ab2=blocks->last; ab && ab2; ab=ab->next, ab2=ab2->prev) {
+ if (ab->modified) {
+ ab->modified = 0;
+ ab->totcurve += 1;
+ }
+
+ if (ab == ab2)
+ break;
+
+ if (ab2->modified) {
+ ab2->modified = 0;
+ ab2->totcurve += 1;
+ }
+ }
+ }
+ }
+}
+
+void agroup_to_keylist(bActionGroup *agrp, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
+{
+ FCurve *fcu;
+
+ if (agrp) {
+ /* loop through F-Curves */
+ for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) {
+ fcurve_to_keylist(fcu, keys, blocks, aki);
+ }
+ }
+}
+
+void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
+{
+ FCurve *fcu;
+
+ if (act) {
+ /* loop through F-Curves */
+ for (fcu= act->curves.first; fcu; fcu= fcu->next) {
+ fcurve_to_keylist(fcu, keys, blocks, aki);
+ }
+ }
+}
+
+void action_nlascaled_to_keylist(Object *ob, bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
+{
+ FCurve *fcu;
+ Object *oldob= NULL;
+
+ /* although apply and clearing NLA-scaling pre-post creating keylist does impact on performance,
+ * the effects should be fairly minimal, as we're already going through the keyframes multiple times
+ * already for blocks too...
+ */
+ if (act) {
+ /* if 'aki' is provided, store it's current ob to restore later as it might not be the same */
+ if (aki) {
+ oldob= aki->ob;
+ aki->ob= ob;
+ }
+
+ /* loop through F-Curves
+ * - scaling correction only does times for center-points, so should be faster
+ */
+ for (fcu= act->curves.first; fcu; fcu= fcu->next) {
+ ANIM_nla_mapping_apply_fcurve(ob, fcu, 0, 1);
+ fcurve_to_keylist(fcu, keys, blocks, aki);
+ ANIM_nla_mapping_apply_fcurve(ob, fcu, 1, 1);
+ }
+
+ /* if 'aki' is provided, restore ob */
+ if (aki)
+ aki->ob= oldob;
+ }
+}
+
+void gpl_to_keylist(bGPDlayer *gpl, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
+{
+ bGPDframe *gpf;
+ ActKeyColumn *ak;
+
+ if (gpl && keys) {
+ /* loop over frames, converting directly to 'keyframes' (should be in order too) */
+ for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+ ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
+ BLI_addtail(keys, ak);
+
+ ak->cfra= (float)gpf->framenum;
+ ak->modified = 1;
+ ak->handle_type= 0;
+
+ if (gpf->flag & GP_FRAME_SELECT)
+ ak->sel = SELECT;
+ else
+ ak->sel = 0;
+ }
+ }
+}
+
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
new file mode 100644
index 00000000000..bef44448829
--- /dev/null
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -0,0 +1,683 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_action.h"
+#include "BKE_fcurve.h"
+#include "BKE_key.h"
+#include "BKE_utildefines.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframes_edit.h"
+#include "ED_markers.h"
+
+/* This file defines an API and set of callback-operators for non-destructive editing of keyframe data.
+ *
+ * Two API functions are defined for actually performing the operations on the data:
+ * ANIM_fcurve_keys_bezier_loop()
+ * which take the data they operate on, a few callbacks defining what operations to perform.
+ *
+ * As operators which work on keyframes usually apply the same operation on all BezTriples in
+ * every channel, the code has been optimised providing a set of functions which will get the
+ * appropriate bezier-modify function to set. These functions (ANIM_editkeyframes_*) will need
+ * to be called before getting any channels.
+ *
+ * A set of 'validation' callbacks are provided for checking if a BezTriple should be operated on.
+ * These should only be used when using a 'general' BezTriple editor (i.e. selection setters which
+ * don't check existing selection status).
+ *
+ * - Joshua Leung, Dec 2008
+ */
+
+/* ************************************************************************** */
+/* Keyframe Editing Loops - Exposed API */
+
+/* --------------------------- Base Functions ------------------------------------ */
+
+/* This function is used to loop over BezTriples in the given F-Curve, applying a given
+ * operation on them, and optionally applies an F-Curve validation function afterwards.
+ */
+short ANIM_fcurve_keys_bezier_loop(BeztEditData *bed, FCurve *fcu, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb)
+{
+ BezTriple *bezt;
+ int b;
+
+ /* sanity check */
+ if (ELEM(NULL, fcu, fcu->bezt))
+ return 0;
+
+ /* if function to apply to bezier curves is set, then loop through executing it on beztriples */
+ if (bezt_cb) {
+ /* if there's a validation func, include that check in the loop
+ * (this is should be more efficient than checking for it in every loop)
+ */
+ if (bezt_ok) {
+ for (b=0, bezt=fcu->bezt; b < fcu->totvert; b++, bezt++) {
+ /* Only operate on this BezTriple if it fullfills the criteria of the validation func */
+ if (bezt_ok(bed, bezt)) {
+ /* Exit with return-code '1' if function returns positive
+ * This is useful if finding if some BezTriple satisfies a condition.
+ */
+ if (bezt_cb(bed, bezt)) return 1;
+ }
+ }
+ }
+ else {
+ for (b=0, bezt=fcu->bezt; b < fcu->totvert; b++, bezt++) {
+ /* Exit with return-code '1' if function returns positive
+ * This is useful if finding if some BezTriple satisfies a condition.
+ */
+ if (bezt_cb(bed, bezt)) return 1;
+ }
+ }
+ }
+
+ /* if fcu_cb (F-Curve post-editing callback) has been specified then execute it */
+ if (fcu_cb)
+ fcu_cb(fcu);
+
+ /* done */
+ return 0;
+}
+
+/* -------------------------------- Further Abstracted (Not Exposed Directly) ----------------------------- */
+
+/* This function is used to loop over the keyframe data in an Action Group */
+static short agrp_keys_bezier_loop(BeztEditData *bed, bActionGroup *agrp, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb)
+{
+ FCurve *fcu;
+
+ /* only iterate over the F-Curves that are in this group */
+ for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) {
+ if (ANIM_fcurve_keys_bezier_loop(bed, fcu, bezt_ok, bezt_cb, fcu_cb))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* This function is used to loop over the keyframe data in an Action */
+static short act_keys_bezier_loop(BeztEditData *bed, bAction *act, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb)
+{
+ FCurve *fcu;
+
+ /* just loop through all F-Curves */
+ for (fcu= act->curves.first; fcu; fcu= fcu->next) {
+ if (ANIM_fcurve_keys_bezier_loop(bed, fcu, bezt_ok, bezt_cb, fcu_cb))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* This function is used to loop over the keyframe data of an AnimData block */
+static short adt_keys_bezier_loop(BeztEditData *bed, AnimData *adt, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag)
+{
+ /* drivers or actions? */
+ if (filterflag & ADS_FILTER_ONLYDRIVERS) {
+ FCurve *fcu;
+
+ /* just loop through all F-Curves acting as Drivers */
+ for (fcu= adt->drivers.first; fcu; fcu= fcu->next) {
+ if (ANIM_fcurve_keys_bezier_loop(bed, fcu, bezt_ok, bezt_cb, fcu_cb))
+ return 1;
+ }
+ }
+ else if (adt->action) {
+ /* call the function for actions */
+ if (act_keys_bezier_loop(bed, adt->action, bezt_ok, bezt_cb, fcu_cb))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* This function is used to loop over the keyframe data in an Object */
+static short ob_keys_bezier_loop(BeztEditData *bed, Object *ob, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag)
+{
+ Key *key= ob_get_key(ob);
+
+ /* firstly, Object's own AnimData */
+ if (ob->adt)
+ adt_keys_bezier_loop(bed, ob->adt, bezt_ok, bezt_cb, fcu_cb, filterflag);
+
+ /* shapekeys */
+ if ((key && key->adt) && !(filterflag & ADS_FILTER_NOSHAPEKEYS))
+ adt_keys_bezier_loop(bed, key->adt, bezt_ok, bezt_cb, fcu_cb, filterflag);
+
+ // FIXME: add materials, etc. (but drawing code doesn't do it yet too! :)
+
+ return 0;
+}
+
+/* This function is used to loop over the keyframe data in a Scene */
+static short scene_keys_bezier_loop(BeztEditData *bed, Scene *sce, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag)
+{
+ World *wo= sce->world;
+
+ /* Scene's own animation */
+ if (sce->adt)
+ adt_keys_bezier_loop(bed, sce->adt, bezt_ok, bezt_cb, fcu_cb, filterflag);
+
+ /* World */
+ if (wo && wo->adt)
+ adt_keys_bezier_loop(bed, wo->adt, bezt_ok, bezt_cb, fcu_cb, filterflag);
+
+ return 0;
+}
+
+/* --- */
+
+/* This function is used to apply operation to all keyframes, regardless of the type */
+short ANIM_animchannel_keys_bezier_loop(BeztEditData *bed, bAnimListElem *ale, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag)
+{
+ /* sanity checks */
+ if (ale == NULL)
+ return 0;
+
+ /* method to use depends on the type of keyframe data */
+ switch (ale->datatype) {
+ /* direct keyframe data (these loops are exposed) */
+ case ALE_FCURVE: /* F-Curve */
+ return ANIM_fcurve_keys_bezier_loop(bed, ale->key_data, bezt_ok, bezt_cb, fcu_cb);
+
+ /* indirect 'summaries' (these are not exposed directly)
+ * NOTE: must keep this code in sync with the drawing code and also the filtering code!
+ */
+ case ALE_GROUP: /* action group */
+ return agrp_keys_bezier_loop(bed, (bActionGroup *)ale->data, bezt_ok, bezt_cb, fcu_cb);
+ case ALE_ACT: /* action */
+ return act_keys_bezier_loop(bed, (bAction *)ale->data, bezt_ok, bezt_cb, fcu_cb);
+
+ case ALE_OB: /* object */
+ return ob_keys_bezier_loop(bed, (Object *)ale->data, bezt_ok, bezt_cb, fcu_cb, filterflag);
+ case ALE_SCE: /* scene */
+ return scene_keys_bezier_loop(bed, (Scene *)ale->data, bezt_ok, bezt_cb, fcu_cb, filterflag);
+ }
+
+ return 0;
+}
+
+/* This function is used to apply operation to all keyframes, regardless of the type without needed an AnimListElem wrapper */
+short ANIM_animchanneldata_keys_bezier_loop(BeztEditData *bed, void *data, int keytype, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag)
+{
+ /* sanity checks */
+ if (data == NULL)
+ return 0;
+
+ /* method to use depends on the type of keyframe data */
+ switch (keytype) {
+ /* direct keyframe data (these loops are exposed) */
+ case ALE_FCURVE: /* F-Curve */
+ return ANIM_fcurve_keys_bezier_loop(bed, data, bezt_ok, bezt_cb, fcu_cb);
+
+ /* indirect 'summaries' (these are not exposed directly)
+ * NOTE: must keep this code in sync with the drawing code and also the filtering code!
+ */
+ case ALE_GROUP: /* action group */
+ return agrp_keys_bezier_loop(bed, (bActionGroup *)data, bezt_ok, bezt_cb, fcu_cb);
+ case ALE_ACT: /* action */
+ return act_keys_bezier_loop(bed, (bAction *)data, bezt_ok, bezt_cb, fcu_cb);
+
+ case ALE_OB: /* object */
+ return ob_keys_bezier_loop(bed, (Object *)data, bezt_ok, bezt_cb, fcu_cb, filterflag);
+ case ALE_SCE: /* scene */
+ return scene_keys_bezier_loop(bed, (Scene *)data, bezt_ok, bezt_cb, fcu_cb, filterflag);
+ }
+
+ return 0;
+}
+
+/* ************************************************************************** */
+/* Keyframe Integrity Tools */
+
+/* Rearrange keyframes if some are out of order */
+// used to be recalc_*_ipos() where * was object or action
+void ANIM_editkeyframes_refresh(bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter animation data */
+ filter= ANIMFILTER_CURVESONLY;
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop over ipo-curves that are likely to have been edited, and check them */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ FCurve *fcu= ale->key_data;
+
+ /* make sure keyframes in F-curve are all in order, and handles are in valid positions */
+ sort_time_fcurve(fcu);
+ testhandles_fcurve(fcu);
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+}
+
+/* ************************************************************************** */
+/* BezTriple Validation Callbacks */
+
+static short ok_bezier_frame(BeztEditData *bed, BezTriple *bezt)
+{
+ /* frame is stored in f1 property (this float accuracy check may need to be dropped?) */
+ return IS_EQ(bezt->vec[1][0], bed->f1);
+}
+
+static short ok_bezier_framerange(BeztEditData *bed, BezTriple *bezt)
+{
+ /* frame range is stored in float properties */
+ return ((bezt->vec[1][0] > bed->f1) && (bezt->vec[1][0] < bed->f2));
+}
+
+static short ok_bezier_selected(BeztEditData *bed, BezTriple *bezt)
+{
+ /* this macro checks all beztriple handles for selection... */
+ return BEZSELECTED(bezt);
+}
+
+static short ok_bezier_value(BeztEditData *bed, BezTriple *bezt)
+{
+ /* value is stored in f1 property
+ * - this float accuracy check may need to be dropped?
+ * - should value be stored in f2 instead so that we won't have conflicts when using f1 for frames too?
+ */
+ return IS_EQ(bezt->vec[1][1], bed->f1);
+}
+
+static short ok_bezier_valuerange(BeztEditData *bed, BezTriple *bezt)
+{
+ /* value range is stored in float properties */
+ return ((bezt->vec[1][1] > bed->f1) && (bezt->vec[1][1] < bed->f2));
+}
+
+static short ok_bezier_region(BeztEditData *bed, BezTriple *bezt)
+{
+ /* rect is stored in data property (it's of type rectf, but may not be set) */
+ if (bed->data)
+ return BLI_in_rctf(bed->data, bezt->vec[1][0], bezt->vec[1][1]);
+ else
+ return 0;
+}
+
+
+BeztEditFunc ANIM_editkeyframes_ok(short mode)
+{
+ /* eEditKeyframes_Validate */
+ switch (mode) {
+ case BEZT_OK_FRAME: /* only if bezt falls on the right frame (float) */
+ return ok_bezier_frame;
+ case BEZT_OK_FRAMERANGE: /* only if bezt falls within the specified frame range (floats) */
+ return ok_bezier_framerange;
+ case BEZT_OK_SELECTED: /* only if bezt is selected (self) */
+ return ok_bezier_selected;
+ case BEZT_OK_VALUE: /* only if bezt value matches (float) */
+ return ok_bezier_value;
+ case BEZT_OK_VALUERANGE: /* only if bezier falls within the specified value range (floats) */
+ return ok_bezier_valuerange;
+ case BEZT_OK_REGION: /* only if bezier falls within the specified rect (data -> rectf) */
+ return ok_bezier_region;
+ default: /* nothing was ok */
+ return NULL;
+ }
+}
+
+/* ******************************************* */
+/* Assorted Utility Functions */
+
+/* helper callback for <animeditor>_cfrasnap_exec() -> used to help get the average time of all selected beztriples */
+short bezt_calc_average(BeztEditData *bed, BezTriple *bezt)
+{
+ /* only if selected */
+ if (bezt->f2 & SELECT) {
+ /* store average time in float (only do rounding at last step */
+ bed->f1 += bezt->vec[1][0];
+
+ /* increment number of items */
+ bed->i1++;
+ }
+
+ return 0;
+}
+
+/* ******************************************* */
+/* Transform */
+
+static short snap_bezier_nearest(BeztEditData *bed, BezTriple *bezt)
+{
+ if (bezt->f2 & SELECT)
+ bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5));
+ return 0;
+}
+
+static short snap_bezier_nearestsec(BeztEditData *bed, BezTriple *bezt)
+{
+ const Scene *scene= bed->scene;
+ const float secf = (float)FPS;
+
+ if (bezt->f2 & SELECT)
+ bezt->vec[1][0]= ((float)floor(bezt->vec[1][0]/secf + 0.5f) * secf);
+ return 0;
+}
+
+static short snap_bezier_cframe(BeztEditData *bed, BezTriple *bezt)
+{
+ const Scene *scene= bed->scene;
+ if (bezt->f2 & SELECT)
+ bezt->vec[1][0]= (float)CFRA;
+ return 0;
+}
+
+static short snap_bezier_nearmarker(BeztEditData *bed, BezTriple *bezt)
+{
+ //if (bezt->f2 & SELECT)
+ // bezt->vec[1][0]= (float)find_nearest_marker_time(bezt->vec[1][0]); // XXX missing function!
+ return 0;
+}
+
+static short snap_bezier_horizontal(BeztEditData *bed, BezTriple *bezt)
+{
+ if (bezt->f2 & SELECT) {
+ 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;
+ }
+ return 0;
+}
+
+// calchandles_ipocurve
+BeztEditFunc ANIM_editkeyframes_snap(short type)
+{
+ /* eEditKeyframes_Snap */
+ switch (type) {
+ case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */
+ return snap_bezier_nearest;
+ case SNAP_KEYS_CURFRAME: /* snap to current frame */
+ return snap_bezier_cframe;
+ case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */
+ return snap_bezier_nearmarker;
+ case SNAP_KEYS_NEARSEC: /* snap to nearest second */
+ return snap_bezier_nearestsec;
+ case SNAP_KEYS_HORIZONTAL: /* snap handles to same value */
+ return snap_bezier_horizontal;
+ default: /* just in case */
+ return snap_bezier_nearest;
+ }
+}
+
+/* --------- */
+
+static short mirror_bezier_cframe(BeztEditData *bed, BezTriple *bezt)
+{
+ const Scene *scene= bed->scene;
+ float diff;
+
+ if (bezt->f2 & SELECT) {
+ diff= ((float)CFRA - bezt->vec[1][0]);
+ bezt->vec[1][0]= ((float)CFRA + diff);
+ }
+
+ return 0;
+}
+
+static short mirror_bezier_yaxis(BeztEditData *bed, BezTriple *bezt)
+{
+ float diff;
+
+ if (bezt->f2 & SELECT) {
+ diff= (0.0f - bezt->vec[1][0]);
+ bezt->vec[1][0]= (0.0f + diff);
+ }
+
+ return 0;
+}
+
+static short mirror_bezier_xaxis(BeztEditData *bed, BezTriple *bezt)
+{
+ float diff;
+
+ if (bezt->f2 & SELECT) {
+ diff= (0.0f - bezt->vec[1][1]);
+ bezt->vec[1][1]= (0.0f + diff);
+ }
+
+ return 0;
+}
+
+static short mirror_bezier_marker(BeztEditData *bed, BezTriple *bezt)
+{
+ /* mirroring time stored in f1 */
+ if (bezt->f2 & SELECT) {
+ const float diff= (bed->f1 - bezt->vec[1][0]);
+ bezt->vec[1][0]= (bed->f1 + diff);
+ }
+
+ return 0;
+}
+
+/* Note: for markers case, need to set global vars (eww...) */
+// calchandles_fcurve
+BeztEditFunc ANIM_editkeyframes_mirror(short type)
+{
+ switch (type) {
+ case MIRROR_KEYS_CURFRAME: /* mirror over current frame */
+ return mirror_bezier_cframe;
+ case MIRROR_KEYS_YAXIS: /* mirror over frame 0 */
+ return mirror_bezier_yaxis;
+ case MIRROR_KEYS_XAXIS: /* mirror over value 0 */
+ return mirror_bezier_xaxis;
+ case MIRROR_KEYS_MARKER: /* mirror over marker */
+ return mirror_bezier_marker;
+ default: /* just in case */
+ return mirror_bezier_yaxis;
+ break;
+ }
+}
+
+/* ******************************************* */
+/* Settings */
+
+/* Sets the selected bezier handles to type 'auto' */
+static short set_bezier_auto(BeztEditData *bed, BezTriple *bezt)
+{
+ if((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
+ if (bezt->f1 & SELECT) bezt->h1= 1; /* the secret code for auto */
+ if (bezt->f3 & SELECT) bezt->h2= 1;
+
+ /* if the handles are not of the same type, set them
+ * to type free
+ */
+ 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;
+ }
+ }
+ return 0;
+}
+
+/* Sets the selected bezier handles to type 'vector' */
+static short set_bezier_vector(BeztEditData *bed, BezTriple *bezt)
+{
+ if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
+ if (bezt->f1 & SELECT) bezt->h1= HD_VECT;
+ if (bezt->f3 & SELECT) bezt->h2= HD_VECT;
+
+ /* if the handles are not of the same type, set them
+ * to type free
+ */
+ 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;
+ }
+ }
+ return 0;
+}
+
+/* Queries if the handle should be set to 'free' or 'align' */
+static short bezier_isfree(BeztEditData *bed, BezTriple *bezt)
+{
+ if ((bezt->f1 & SELECT) && (bezt->h1)) return 1;
+ if ((bezt->f3 & SELECT) && (bezt->h2)) return 1;
+ return 0;
+}
+
+/* Sets selected bezier handles to type 'align' */
+static short set_bezier_align(BeztEditData *bed, BezTriple *bezt)
+{
+ if (bezt->f1 & SELECT) bezt->h1= HD_ALIGN;
+ if (bezt->f3 & SELECT) bezt->h2= HD_ALIGN;
+ return 0;
+}
+
+/* Sets selected bezier handles to type 'free' */
+static short set_bezier_free(BeztEditData *bed, BezTriple *bezt)
+{
+ if (bezt->f1 & SELECT) bezt->h1= HD_FREE;
+ if (bezt->f3 & SELECT) bezt->h2= HD_FREE;
+ return 0;
+}
+
+/* Set all Bezier Handles to a single type */
+// calchandles_fcurve
+BeztEditFunc ANIM_editkeyframes_handles(short code)
+{
+ switch (code) {
+ case HD_AUTO: /* auto */
+ return set_bezier_auto;
+ case HD_VECT: /* vector */
+ return set_bezier_vector;
+ case HD_FREE: /* free */
+ return set_bezier_free;
+ case HD_ALIGN: /* align */
+ return set_bezier_align;
+
+ default: /* free or align? */
+ return bezier_isfree;
+ }
+}
+
+/* ------- */
+
+static short set_bezt_constant(BeztEditData *bed, BezTriple *bezt)
+{
+ if (bezt->f2 & SELECT)
+ bezt->ipo= BEZT_IPO_CONST;
+ return 0;
+}
+
+static short set_bezt_linear(BeztEditData *bed, BezTriple *bezt)
+{
+ if (bezt->f2 & SELECT)
+ bezt->ipo= BEZT_IPO_LIN;
+ return 0;
+}
+
+static short set_bezt_bezier(BeztEditData *bed, BezTriple *bezt)
+{
+ if (bezt->f2 & SELECT)
+ bezt->ipo= BEZT_IPO_BEZ;
+ return 0;
+}
+
+/* Set the interpolation type of the selected BezTriples in each IPO curve to the specified one */
+// ANIM_editkeyframes_ipocurve_ipotype() !
+BeztEditFunc ANIM_editkeyframes_ipo(short code)
+{
+ switch (code) {
+ case BEZT_IPO_CONST: /* constant */
+ return set_bezt_constant;
+ case BEZT_IPO_LIN: /* linear */
+ return set_bezt_linear;
+ default: /* bezier */
+ return set_bezt_bezier;
+ }
+}
+
+/* ******************************************* */
+/* Selection */
+
+static short select_bezier_add(BeztEditData *bed, BezTriple *bezt)
+{
+ /* Select the bezier triple */
+ BEZ_SEL(bezt);
+ return 0;
+}
+
+static short select_bezier_subtract(BeztEditData *bed, BezTriple *bezt)
+{
+ /* Deselect the bezier triple */
+ BEZ_DESEL(bezt);
+ return 0;
+}
+
+static short select_bezier_invert(BeztEditData *bed, BezTriple *bezt)
+{
+ /* Invert the selection for the bezier triple */
+ bezt->f2 ^= SELECT;
+ if (bezt->f2 & SELECT) {
+ bezt->f1 |= SELECT;
+ bezt->f3 |= SELECT;
+ }
+ else {
+ bezt->f1 &= ~SELECT;
+ bezt->f3 &= ~SELECT;
+ }
+ return 0;
+}
+
+// NULL
+BeztEditFunc ANIM_editkeyframes_select(short selectmode)
+{
+ switch (selectmode) {
+ case SELECT_ADD: /* add */
+ return select_bezier_add;
+ case SELECT_SUBTRACT: /* subtract */
+ return select_bezier_subtract;
+ case SELECT_INVERT: /* invert */
+ return select_bezier_invert;
+ default: /* replace (need to clear all, then add) */
+ return select_bezier_add;
+ }
+}
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
new file mode 100644
index 00000000000..48ca06fb73d
--- /dev/null
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -0,0 +1,548 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation
+ * All rights reserved.
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_action.h"
+#include "BKE_fcurve.h"
+#include "BKE_key.h"
+#include "BKE_utildefines.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_edit.h"
+
+/* This file contains code for various keyframe-editing tools which are 'destructive'
+ * (i.e. they will modify the order of the keyframes, and change the size of the array).
+ * While some of these tools may eventually be moved out into blenkernel, for now, it is
+ * fine to have these calls here.
+ *
+ * There are also a few tools here which cannot be easily coded for in the other system (yet).
+ * These may also be moved around at some point, but for now, they
+ *
+ * - Joshua Leung, Dec 2008
+ */
+
+/* **************************************************** */
+
+/* Only delete the nominated keyframe from provided ipo-curve.
+ * Not recommended to be used many times successively. For that
+ * there is delete_ipo_keys().
+ */
+void delete_fcurve_key(FCurve *fcu, int index, short do_recalc)
+{
+ /* firstly check that index is valid */
+ if (index < 0)
+ index *= -1;
+ if (fcu == NULL)
+ return;
+ if (index >= fcu->totvert)
+ return;
+
+ /* Delete this key */
+ memmove(&fcu->bezt[index], &fcu->bezt[index+1], sizeof(BezTriple)*(fcu->totvert-index-1));
+ fcu->totvert--;
+
+ /* recalc handles - only if it won't cause problems */
+ if (do_recalc)
+ calchandles_fcurve(fcu);
+}
+
+/* Delete selected keyframes in given F-Curve */
+void delete_fcurve_keys(FCurve *fcu)
+{
+ int i;
+
+ /* Delete selected BezTriples */
+ for (i=0; i < fcu->totvert; i++) {
+ if (fcu->bezt[i].f2 & SELECT) {
+ memmove(&fcu->bezt[i], &fcu->bezt[i+1], sizeof(BezTriple)*(fcu->totvert-i-1));
+ fcu->totvert--;
+ i--;
+ }
+ }
+
+ /* Free the array of BezTriples if there are not keyframes */
+ if (fcu->totvert == 0) {
+ if (fcu->bezt)
+ MEM_freeN(fcu->bezt);
+ fcu->bezt= NULL;
+ }
+
+#if 0 // XXX for now, we don't get rid of empty curves...
+ /* Only delete if there isn't an ipo-driver still hanging around on an empty curve */
+ if ((icu->totvert==0) && (icu->driver==NULL)) {
+ BLI_remlink(&ipo->curve, icu);
+ free_ipo_curve(icu);
+ }
+#endif
+}
+
+/* ---------------- */
+
+/* duplicate selected keyframes for the given F-Curve */
+void duplicate_fcurve_keys(FCurve *fcu)
+{
+ BezTriple *newbezt;
+ int i;
+
+ if (fcu == NULL)
+ return;
+
+ // XXX this does not take into account sample data...
+ for (i=0; i < fcu->totvert; i++) {
+ /* If a key is selected */
+ if (fcu->bezt[i].f2 & SELECT) {
+ /* Expand the list */
+ newbezt = MEM_callocN(sizeof(BezTriple) * (fcu->totvert+1), "beztriple");
+
+ memcpy(newbezt, fcu->bezt, sizeof(BezTriple) * (i+1));
+ memcpy(newbezt+i+1, fcu->bezt+i, sizeof(BezTriple));
+ memcpy(newbezt+i+2, fcu->bezt+i+1, sizeof (BezTriple) *(fcu->totvert-(i+1)));
+ fcu->totvert++;
+
+ /* reassign pointers... (free old, and add new) */
+ MEM_freeN(fcu->bezt);
+ fcu->bezt=newbezt;
+
+ /* Unselect the current key */
+ BEZ_DESEL(&fcu->bezt[i]);
+ i++;
+
+ /* Select the copied key */
+ BEZ_SEL(&fcu->bezt[i]);
+ }
+ }
+}
+
+/* **************************************************** */
+/* Various Tools */
+
+/* Basic IPO-Curve 'cleanup' function that removes 'double points' and unnecessary keyframes on linear-segments only */
+void clean_fcurve(FCurve *fcu, float thresh)
+{
+ BezTriple *old_bezts, *bezt, *beztn;
+ BezTriple *lastb;
+ int totCount, i;
+
+ /* check if any points */
+ if ((fcu == NULL) || (fcu->totvert <= 1))
+ return;
+
+ /* make a copy of the old BezTriples, and clear IPO curve */
+ old_bezts = fcu->bezt;
+ totCount = fcu->totvert;
+ fcu->bezt = NULL;
+ fcu->totvert = 0;
+
+ /* now insert first keyframe, as it should be ok */
+ bezt = old_bezts;
+ insert_vert_fcurve(fcu, bezt->vec[1][0], bezt->vec[1][1], 0);
+
+ /* Loop through BezTriples, comparing them. Skip any that do
+ * not fit the criteria for "ok" points.
+ */
+ for (i=1; i<totCount; i++) {
+ float prev[2], cur[2], next[2];
+
+ /* get BezTriples and their values */
+ if (i < (totCount - 1)) {
+ beztn = (old_bezts + (i+1));
+ next[0]= beztn->vec[1][0]; next[1]= beztn->vec[1][1];
+ }
+ else {
+ beztn = NULL;
+ next[0] = next[1] = 0.0f;
+ }
+ lastb= (fcu->bezt + (fcu->totvert - 1));
+ bezt= (old_bezts + i);
+
+ /* get references for quicker access */
+ prev[0] = lastb->vec[1][0]; prev[1] = lastb->vec[1][1];
+ cur[0] = bezt->vec[1][0]; cur[1] = bezt->vec[1][1];
+
+ /* check if current bezt occurs at same time as last ok */
+ if (IS_EQT(cur[0], prev[0], thresh)) {
+ /* If there is a next beztriple, and if occurs at the same time, only insert
+ * if there is a considerable distance between the points, and also if the
+ * current is further away than the next one is to the previous.
+ */
+ if (beztn && (IS_EQT(cur[0], next[0], thresh)) &&
+ (IS_EQT(next[1], prev[1], thresh)==0))
+ {
+ /* only add if current is further away from previous */
+ if (cur[1] > next[1]) {
+ if (IS_EQT(cur[1], prev[1], thresh) == 0) {
+ /* add new keyframe */
+ insert_vert_fcurve(fcu, cur[0], cur[1], 0);
+ }
+ }
+ }
+ else {
+ /* only add if values are a considerable distance apart */
+ if (IS_EQT(cur[1], prev[1], thresh) == 0) {
+ /* add new keyframe */
+ insert_vert_fcurve(fcu, cur[0], cur[1], 0);
+ }
+ }
+ }
+ else {
+ /* checks required are dependent on whether this is last keyframe or not */
+ if (beztn) {
+ /* does current have same value as previous and next? */
+ if (IS_EQT(cur[1], prev[1], thresh) == 0) {
+ /* add new keyframe*/
+ insert_vert_fcurve(fcu, cur[0], cur[1], 0);
+ }
+ else if (IS_EQT(cur[1], next[1], thresh) == 0) {
+ /* add new keyframe */
+ insert_vert_fcurve(fcu, cur[0], cur[1], 0);
+ }
+ }
+ else {
+ /* add if value doesn't equal that of previous */
+ if (IS_EQT(cur[1], prev[1], thresh) == 0) {
+ /* add new keyframe */
+ insert_vert_fcurve(fcu, cur[0], cur[1], 0);
+ }
+ }
+ }
+ }
+
+ /* now free the memory used by the old BezTriples */
+ if (old_bezts)
+ MEM_freeN(old_bezts);
+}
+
+/* ---------------- */
+
+/* temp struct used for smooth_ipo */
+typedef struct tSmooth_Bezt {
+ float *h1, *h2, *h3; /* bezt->vec[0,1,2][1] */
+} tSmooth_Bezt;
+
+/* Use a weighted moving-means method to reduce intensity of fluctuations */
+void smooth_fcurve (FCurve *fcu)
+{
+ BezTriple *bezt;
+ int i, x, totSel = 0;
+
+ /* first loop through - count how many verts are selected, and fix up handles
+ * this is done for both modes
+ */
+ bezt= fcu->bezt;
+ for (i=0; i < fcu->totvert; i++, bezt++) {
+ if (BEZSELECTED(bezt)) {
+ /* line point's handles up with point's vertical position */
+ 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;
+
+ /* add value to total */
+ totSel++;
+ }
+ }
+
+ /* if any points were selected, allocate tSmooth_Bezt points to work on */
+ if (totSel >= 3) {
+ tSmooth_Bezt *tarray, *tsb;
+
+ /* allocate memory in one go */
+ tsb= tarray= MEM_callocN(totSel*sizeof(tSmooth_Bezt), "tSmooth_Bezt Array");
+
+ /* populate tarray with data of selected points */
+ bezt= fcu->bezt;
+ for (i=0, x=0; (i < fcu->totvert) && (x < totSel); i++, bezt++) {
+ if (BEZSELECTED(bezt)) {
+ /* tsb simply needs pointer to vec, and index */
+ tsb->h1 = &bezt->vec[0][1];
+ tsb->h2 = &bezt->vec[1][1];
+ tsb->h3 = &bezt->vec[2][1];
+
+ /* advance to the next tsb to populate */
+ if (x < totSel- 1)
+ tsb++;
+ else
+ break;
+ }
+ }
+
+ /* calculate the new smoothed F-Curve's with weighted averages:
+ * - this is done with two passes
+ * - uses 5 points for each operation (which stores in the relevant handles)
+ * - previous: w/a ratio = 3:5:2:1:1
+ * - next: w/a ratio = 1:1:2:5:3
+ */
+
+ /* round 1: calculate previous and next */
+ tsb= tarray;
+ for (i=0; i < totSel; i++, tsb++) {
+ /* don't touch end points (otherwise, curves slowly explode) */
+ if (ELEM(i, 0, (totSel-1)) == 0) {
+ const tSmooth_Bezt *tP1 = tsb - 1;
+ const tSmooth_Bezt *tP2 = (i-2 > 0) ? (tsb - 2) : (NULL);
+ const tSmooth_Bezt *tN1 = tsb + 1;
+ const tSmooth_Bezt *tN2 = (i+2 < totSel) ? (tsb + 2) : (NULL);
+
+ const float p1 = *tP1->h2;
+ const float p2 = (tP2) ? (*tP2->h2) : (*tP1->h2);
+ const float c1 = *tsb->h2;
+ const float n1 = *tN1->h2;
+ const float n2 = (tN2) ? (*tN2->h2) : (*tN1->h2);
+
+ /* calculate previous and next */
+ *tsb->h1= (3*p2 + 5*p1 + 2*c1 + n1 + n2) / 12;
+ *tsb->h3= (p2 + p1 + 2*c1 + 5*n1 + 3*n2) / 12;
+ }
+ }
+
+ /* round 2: calculate new values and reset handles */
+ tsb= tarray;
+ for (i=0; i < totSel; i++, tsb++) {
+ /* calculate new position by averaging handles */
+ *tsb->h2 = (*tsb->h1 + *tsb->h3) / 2;
+
+ /* reset handles now */
+ *tsb->h1 = *tsb->h2;
+ *tsb->h3 = *tsb->h2;
+ }
+
+ /* free memory required for tarray */
+ MEM_freeN(tarray);
+}
+
+ /* recalculate handles */
+ calchandles_fcurve(fcu);
+}
+
+/* **************************************************** */
+/* Copy/Paste Tools */
+/* - The copy/paste buffer currently stores a set of temporary F-Curves containing only the keyframes
+ * that were selected in each of the original F-Curves
+ * - All pasted frames are offset by the same amount. This is calculated as the difference in the times of
+ * the current frame and the 'first keyframe' (i.e. the earliest one in all channels).
+ * - The earliest frame is calculated per copy operation.
+ */
+
+/* globals for copy/paste data (like for other copy/paste buffers) */
+ListBase animcopybuf = {NULL, NULL};
+static float animcopy_firstframe= 999999999.0f;
+
+/* datatype for use in copy/paste buffer */
+// XXX F-Curve editor should use this too
+typedef struct tAnimCopybufItem {
+ struct tAnimCopybufItem *next, *prev;
+
+ ID *id; /* ID which owns the curve */
+ bActionGroup *grp; /* Action Group */
+ char *rna_path; /* RNA-Path */
+ int array_index; /* array index */
+
+ int totvert; /* number of keyframes stored for this channel */
+ BezTriple *bezt; /* keyframes in buffer */
+} tAnimCopybufItem;
+
+
+/* This function frees any MEM_calloc'ed copy/paste buffer data */
+// XXX find some header to put this in!
+void free_anim_copybuf (void)
+{
+ tAnimCopybufItem *aci, *acn;
+
+ /* free each buffer element */
+ for (aci= animcopybuf.first; aci; aci= acn) {
+ acn= aci->next;
+
+ /* free keyframes */
+ if (aci->bezt)
+ MEM_freeN(aci->bezt);
+
+ /* free RNA-path */
+ if (aci->rna_path)
+ MEM_freeN(aci->rna_path);
+
+ /* free ourself */
+ BLI_freelinkN(&animcopybuf, aci);
+ }
+
+ /* restore initial state */
+ animcopybuf.first= animcopybuf.last= NULL;
+ animcopy_firstframe= 999999999.0f;
+}
+
+/* ------------------- */
+
+/* This function adds data to the keyframes copy/paste buffer, freeing existing data first */
+short copy_animedit_keys (bAnimContext *ac, ListBase *anim_data)
+{
+ bAnimListElem *ale;
+
+ /* clear buffer first */
+ free_anim_copybuf();
+
+ /* assume that each of these is an F-Curve */
+ for (ale= anim_data->first; ale; ale= ale->next) {
+ FCurve *fcu= (FCurve *)ale->key_data;
+ tAnimCopybufItem *aci;
+ BezTriple *bezt, *newbuf;
+ int i;
+
+ /* firstly, check if F-Curve has any selected keyframes
+ * - skip if no selected keyframes found (so no need to create unnecessary copy-buffer data)
+ * - this check should also eliminate any problems associated with using sample-data
+ */
+ if (ANIM_fcurve_keys_bezier_loop(NULL, fcu, NULL, ANIM_editkeyframes_ok(BEZT_OK_SELECTED), NULL) == 0)
+ continue;
+
+ /* init copybuf item info */
+ aci= MEM_callocN(sizeof(tAnimCopybufItem), "AnimCopybufItem");
+ aci->id= ale->id;
+ aci->grp= fcu->grp;
+ aci->rna_path= MEM_dupallocN(fcu->rna_path);
+ aci->array_index= fcu->array_index;
+ BLI_addtail(&animcopybuf, aci);
+
+ /* add selected keyframes to buffer */
+ // TODO: currently, we resize array everytime we add a new vert - this works ok as long as it is assumed only a few keys are copied
+ for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (BEZSELECTED(bezt)) {
+ /* add to buffer */
+ newbuf= MEM_callocN(sizeof(BezTriple)*(aci->totvert+1), "copybuf beztriple");
+
+ /* assume that since we are just resizing the array, just copy all existing data across */
+ if (aci->bezt)
+ memcpy(newbuf, aci->bezt, sizeof(BezTriple)*(aci->totvert));
+
+ /* copy current beztriple across too */
+ *(newbuf + aci->totvert)= *bezt;
+
+ /* free old array and set the new */
+ if (aci->bezt) MEM_freeN(aci->bezt);
+ aci->bezt= newbuf;
+ aci->totvert++;
+
+ /* check if this is the earliest frame encountered so far */
+ if (bezt->vec[1][0] < animcopy_firstframe)
+ animcopy_firstframe= bezt->vec[1][0];
+ }
+ }
+
+ }
+
+ /* check if anything ended up in the buffer */
+ if (ELEM(NULL, animcopybuf.first, animcopybuf.last))
+ return -1;
+
+ /* everything went fine */
+ return 0;
+}
+
+/* This function pastes data from the keyframes copy/paste buffer */
+short paste_animedit_keys (bAnimContext *ac, ListBase *anim_data)
+{
+ bAnimListElem *ale;
+ const Scene *scene= (ac->scene);
+ const float offset = (float)(CFRA - animcopy_firstframe);
+ short no_name= 0;
+
+ /* check if buffer is empty */
+ if (ELEM(NULL, animcopybuf.first, animcopybuf.last)) {
+ //error("No data in buffer to paste");
+ return -1;
+ }
+ /* check if single channel in buffer (disregard names if so) */
+ if (animcopybuf.first == animcopybuf.last)
+ no_name= 1;
+
+ /* from selected channels */
+ for (ale= anim_data->first; ale; ale= ale->next) {
+ FCurve *fcu = (FCurve *)ale->data; /* destination F-Curve */
+ tAnimCopybufItem *aci= NULL;
+ BezTriple *bezt;
+ int i;
+
+ /* find buffer item to paste from
+ * - if names don't matter (i.e. only 1 channel in buffer), don't check id/group
+ * - if names do matter, only check if id-type is ok for now (group check is not that important)
+ * - most importantly, rna-paths should match (array indices are unimportant for now)
+ */
+ // TODO: the matching algorithm here is pathetic!
+ for (aci= animcopybuf.first; aci; aci= aci->next) {
+ /* check that paths exist */
+ if (aci->rna_path && fcu->rna_path) {
+ if (strcmp(aci->rna_path, fcu->rna_path) == 0) {
+ /* should be a match unless there's more than one of these */
+ if ((no_name) || (aci->array_index == fcu->array_index))
+ break;
+ }
+ }
+ }
+
+
+ /* copy the relevant data from the matching buffer curve */
+ if (aci) {
+ /* just start pasting, with the the first keyframe on the current frame, and so on */
+ for (i=0, bezt=aci->bezt; i < aci->totvert; i++, bezt++) {
+ /* temporarily apply offset to src beztriple while copying */
+ bezt->vec[0][0] += offset;
+ bezt->vec[1][0] += offset;
+ bezt->vec[2][0] += offset;
+
+ /* insert the keyframe */
+ insert_bezt_fcurve(fcu, bezt);
+
+ /* un-apply offset from src beztriple after copying */
+ bezt->vec[0][0] -= offset;
+ bezt->vec[1][0] -= offset;
+ bezt->vec[2][0] -= offset;
+ }
+
+ /* recalculate F-Curve's handles? */
+ calchandles_fcurve(fcu);
+ }
+ }
+
+ return 0;
+}
+
+/* **************************************************** */
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
new file mode 100644
index 00000000000..c341e32db8c
--- /dev/null
+++ b/source/blender/editors/animation/keyframing.c
@@ -0,0 +1,1455 @@
+/* Testing code for 2.5 animation system
+ * Copyright 2009, Joshua Leung
+ */
+
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_dynstr.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_key_types.h"
+#include "DNA_object_types.h"
+#include "DNA_material_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_action.h"
+#include "BKE_constraint.h"
+#include "BKE_fcurve.h"
+#include "BKE_utildefines.h"
+#include "BKE_context.h"
+#include "BKE_report.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_edit.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_types.h"
+
+#include "anim_intern.h"
+
+/* ******************************************* */
+/* Animation Data Validation */
+
+/* Get (or add relevant data to be able to do so) the Active Action for the given
+ * Animation Data block, given an ID block where the Animation Data should reside.
+ */
+bAction *verify_adt_action (ID *id, short add)
+{
+ AnimData *adt;
+
+ /* init animdata if none available yet */
+ adt= BKE_animdata_from_id(id);
+ if ((adt == NULL) && (add))
+ adt= BKE_id_add_animdata(id);
+ if (adt == NULL) {
+ /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
+ return NULL;
+ }
+
+ /* init action if none available yet */
+ // TODO: need some wizardry to handle NLA stuff correct
+ if ((adt->action == NULL) && (add))
+ adt->action= add_empty_action("Action");
+
+ /* return the action */
+ return adt->action;
+}
+
+/* Get (or add relevant data to be able to do so) F-Curve from the Active Action,
+ * for the given Animation Data block. This assumes that all the destinations are valid.
+ */
+FCurve *verify_fcurve (bAction *act, const char group[], const char rna_path[], const int array_index, short add)
+{
+ bActionGroup *grp;
+ FCurve *fcu;
+
+ /* sanity checks */
+ if ELEM(NULL, act, rna_path)
+ return NULL;
+
+ /* try to find f-curve matching for this setting
+ * - add if not found and allowed to add one
+ * TODO: add auto-grouping support? how this works will need to be resolved
+ */
+ if (act)
+ fcu= list_find_fcurve(&act->curves, rna_path, array_index);
+ else
+ fcu= NULL;
+
+ if ((fcu == NULL) && (add)) {
+ /* use default settings to make a F-Curve */
+ fcu= MEM_callocN(sizeof(FCurve), "FCurve");
+
+ fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
+ if (act->curves.first==NULL)
+ fcu->flag |= FCURVE_ACTIVE; /* first one added active */
+
+ /* store path - make copy, and store that */
+ fcu->rna_path= BLI_strdupn(rna_path, strlen(rna_path));
+ fcu->array_index= array_index;
+
+ /* if a group name has been provided, try to add or find a group, then add F-Curve to it */
+ if (group) {
+ /* try to find group */
+ grp= action_groups_find_named(act, group);
+
+ /* no matching groups, so add one */
+ if (grp == NULL) {
+ /* Add a new group, and make it active */
+ grp= MEM_callocN(sizeof(bActionGroup), "bActionGroup");
+
+ grp->flag = AGRP_SELECTED;
+ BLI_snprintf(grp->name, 64, group);
+
+ BLI_addtail(&act->groups, grp);
+ BLI_uniquename(&act->groups, grp, "Group", '.', offsetof(bActionGroup, name), 64);
+ }
+
+ /* add F-Curve to group */
+ action_groups_add_channel(act, grp, fcu);
+ }
+ else {
+ /* just add F-Curve to end of Action's list */
+ BLI_addtail(&act->curves, fcu);
+ }
+ }
+
+ /* return the F-Curve */
+ return fcu;
+}
+
+/* ************************************************** */
+/* KEYFRAME INSERTION */
+
+/* -------------- BezTriple Insertion -------------------- */
+
+/* threshold for inserting keyframes - threshold here should be good enough for now, but should become userpref */
+#define BEZT_INSERT_THRESH 0.00001f
+
+/* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_icu)
+ * Returns the index to insert at (data already at that index will be offset if replace is 0)
+ */
+static int binarysearch_bezt_index (BezTriple array[], float frame, int arraylen, short *replace)
+{
+ int start=0, end=arraylen;
+ int loopbreaker= 0, maxloop= arraylen * 2;
+
+ /* initialise replace-flag first */
+ *replace= 0;
+
+ /* sneaky optimisations (don't go through searching process if...):
+ * - keyframe to be added is to be added out of current bounds
+ * - keyframe to be added would replace one of the existing ones on bounds
+ */
+ if ((arraylen <= 0) || (array == NULL)) {
+ printf("Warning: binarysearch_bezt_index() encountered invalid array \n");
+ return 0;
+ }
+ else {
+ /* check whether to add before/after/on */
+ float framenum;
+
+ /* 'First' Keyframe (when only one keyframe, this case is used) */
+ framenum= array[0].vec[1][0];
+ if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) {
+ *replace = 1;
+ return 0;
+ }
+ else if (frame < framenum)
+ return 0;
+
+ /* 'Last' Keyframe */
+ framenum= array[(arraylen-1)].vec[1][0];
+ if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) {
+ *replace= 1;
+ return (arraylen - 1);
+ }
+ else if (frame > framenum)
+ return arraylen;
+ }
+
+
+ /* most of the time, this loop is just to find where to put it
+ * 'loopbreaker' is just here to prevent infinite loops
+ */
+ for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
+ /* compute and get midpoint */
+ int mid = start + ((end - start) / 2); /* we calculate the midpoint this way to avoid int overflows... */
+ float midfra= array[mid].vec[1][0];
+
+ /* check if exactly equal to midpoint */
+ if (IS_EQT(frame, midfra, BEZT_INSERT_THRESH)) {
+ *replace = 1;
+ return mid;
+ }
+
+ /* repeat in upper/lower half */
+ if (frame > midfra)
+ start= mid + 1;
+ else if (frame < midfra)
+ end= mid - 1;
+ }
+
+ /* print error if loop-limit exceeded */
+ if (loopbreaker == (maxloop-1)) {
+ printf("Error: binarysearch_bezt_index() was taking too long \n");
+
+ // include debug info
+ printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen);
+ }
+
+ /* not found, so return where to place it */
+ return start;
+}
+
+/* This function adds a given BezTriple to an F-Curve. It will allocate
+ * memory for the array if needed, and will insert the BezTriple into a
+ * suitable place in chronological order.
+ *
+ * NOTE: any recalculate of the F-Curve that needs to be done will need to
+ * be done by the caller.
+ */
+int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt)
+{
+ BezTriple *newb;
+ int i= 0;
+
+ if (fcu->bezt) {
+ short replace = -1;
+ i = binarysearch_bezt_index(fcu->bezt, bezt->vec[1][0], fcu->totvert, &replace);
+
+ if (replace) {
+ /* sanity check: 'i' may in rare cases exceed arraylen */
+ // FIXME: do not overwrite handletype if just replacing...?
+ if ((i >= 0) && (i < fcu->totvert))
+ *(fcu->bezt + i) = *bezt;
+ }
+ else {
+ /* add new */
+ newb= MEM_callocN((fcu->totvert+1)*sizeof(BezTriple), "beztriple");
+
+ /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */
+ if (i > 0)
+ memcpy(newb, fcu->bezt, i*sizeof(BezTriple));
+
+ /* add beztriple to paste at index i */
+ *(newb + i)= *bezt;
+
+ /* add the beztriples that occur after the beztriple to be pasted (originally in icu) */
+ if (i < fcu->totvert)
+ memcpy(newb+i+1, fcu->bezt+i, (fcu->totvert-i)*sizeof(BezTriple));
+
+ /* replace (+ free) old with new */
+ MEM_freeN(fcu->bezt);
+ fcu->bezt= newb;
+
+ fcu->totvert++;
+ }
+ }
+ else {
+ // TODO: need to check for old sample-data now...
+ fcu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple");
+ *(fcu->bezt)= *bezt;
+ fcu->totvert= 1;
+ }
+
+
+ /* we need to return the index, so that some tools which do post-processing can
+ * detect where we added the BezTriple in the array
+ */
+ return i;
+}
+
+/* This function is a wrapper for insert_bezt_icu, and should be used when
+ * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere
+ * else yet.
+ *
+ * 'fast' - is only for the python API where importing BVH's would take an extreamly long time.
+ */
+void insert_vert_fcurve (FCurve *fcu, float x, float y, short fast)
+{
+ BezTriple beztr;
+ int a;
+
+ /* set all three points, for nicer start position */
+ memset(&beztr, 0, sizeof(BezTriple));
+ beztr.vec[0][0]= x;
+ beztr.vec[0][1]= y;
+ beztr.vec[1][0]= x;
+ beztr.vec[1][1]= y;
+ beztr.vec[2][0]= x;
+ beztr.vec[2][1]= y;
+ beztr.ipo= U.ipo_new; /* use default interpolation mode here... */
+ beztr.f1= beztr.f2= beztr.f3= SELECT;
+ beztr.h1= beztr.h2= HD_AUTO; // XXX what about when we replace an old one?
+
+ /* add temp beztriple to keyframes */
+ a= insert_bezt_fcurve(fcu, &beztr);
+
+ /* what if 'a' is a negative index?
+ * for now, just exit to prevent any segfaults
+ */
+ if (a < 0) return;
+
+ /* don't recalculate handles if fast is set
+ * - this is a hack to make importers faster
+ * - we may calculate twice (see editipo_changed(), due to autohandle needing two calculations)
+ */
+ if (!fast) calchandles_fcurve(fcu);
+
+ /* set handletype and interpolation */
+ if (fcu->totvert > 2) {
+ BezTriple *bezt= (fcu->bezt + a);
+ char h1, h2;
+
+ /* set handles (autohandles by default) */
+ h1= h2= HD_AUTO;
+
+ if (a > 0) h1= (bezt-1)->h2;
+ if (a < fcu->totvert-1) h2= (bezt+1)->h1;
+
+ bezt->h1= h1;
+ bezt->h2= h2;
+
+ /* set interpolation from previous (if available) */
+ if (a > 0) bezt->ipo= (bezt-1)->ipo;
+ else if (a < fcu->totvert-1) bezt->ipo= (bezt+1)->ipo;
+
+ /* don't recalculate handles if fast is set
+ * - this is a hack to make importers faster
+ * - we may calculate twice (see editipo_changed(), due to autohandle needing two calculations)
+ */
+ if (!fast) calchandles_fcurve(fcu);
+ }
+}
+
+/* -------------- 'Smarter' Keyframing Functions -------------------- */
+/* return codes for new_key_needed */
+enum {
+ KEYNEEDED_DONTADD = 0,
+ KEYNEEDED_JUSTADD,
+ KEYNEEDED_DELPREV,
+ KEYNEEDED_DELNEXT
+} eKeyNeededStatus;
+
+/* This helper function determines whether a new keyframe is needed */
+/* Cases where keyframes should not be added:
+ * 1. Keyframe to be added bewteen two keyframes with similar values
+ * 2. Keyframe to be added on frame where two keyframes are already situated
+ * 3. Keyframe lies at point that intersects the linear line between two keyframes
+ */
+static short new_key_needed (FCurve *fcu, float cFrame, float nValue)
+{
+ BezTriple *bezt=NULL, *prev=NULL;
+ int totCount, i;
+ float valA = 0.0f, valB = 0.0f;
+
+ /* safety checking */
+ if (fcu == NULL) return KEYNEEDED_JUSTADD;
+ totCount= fcu->totvert;
+ if (totCount == 0) return KEYNEEDED_JUSTADD;
+
+ /* loop through checking if any are the same */
+ bezt= fcu->bezt;
+ for (i=0; i<totCount; i++) {
+ float prevPosi=0.0f, prevVal=0.0f;
+ float beztPosi=0.0f, beztVal=0.0f;
+
+ /* get current time+value */
+ beztPosi= bezt->vec[1][0];
+ beztVal= bezt->vec[1][1];
+
+ if (prev) {
+ /* there is a keyframe before the one currently being examined */
+
+ /* get previous time+value */
+ prevPosi= prev->vec[1][0];
+ prevVal= prev->vec[1][1];
+
+ /* keyframe to be added at point where there are already two similar points? */
+ if (IS_EQ(prevPosi, cFrame) && IS_EQ(beztPosi, cFrame) && IS_EQ(beztPosi, prevPosi)) {
+ return KEYNEEDED_DONTADD;
+ }
+
+ /* keyframe between prev+current points ? */
+ if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) {
+ /* is the value of keyframe to be added the same as keyframes on either side ? */
+ if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) {
+ return KEYNEEDED_DONTADD;
+ }
+ else {
+ float realVal;
+
+ /* get real value of curve at that point */
+ realVal= evaluate_fcurve(fcu, cFrame);
+
+ /* compare whether it's the same as proposed */
+ if (IS_EQ(realVal, nValue))
+ return KEYNEEDED_DONTADD;
+ else
+ return KEYNEEDED_JUSTADD;
+ }
+ }
+
+ /* new keyframe before prev beztriple? */
+ if (cFrame < prevPosi) {
+ /* A new keyframe will be added. However, whether the previous beztriple
+ * stays around or not depends on whether the values of previous/current
+ * beztriples and new keyframe are the same.
+ */
+ if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal))
+ return KEYNEEDED_DELNEXT;
+ else
+ return KEYNEEDED_JUSTADD;
+ }
+ }
+ else {
+ /* just add a keyframe if there's only one keyframe
+ * and the new one occurs before the exisiting one does.
+ */
+ if ((cFrame < beztPosi) && (totCount==1))
+ return KEYNEEDED_JUSTADD;
+ }
+
+ /* continue. frame to do not yet passed (or other conditions not met) */
+ if (i < (totCount-1)) {
+ prev= bezt;
+ bezt++;
+ }
+ else
+ break;
+ }
+
+ /* Frame in which to add a new-keyframe occurs after all other keys
+ * -> If there are at least two existing keyframes, then if the values of the
+ * last two keyframes and the new-keyframe match, the last existing keyframe
+ * gets deleted as it is no longer required.
+ * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last
+ * keyframe is not equal to last keyframe.
+ */
+ bezt= (fcu->bezt + (fcu->totvert - 1));
+ valA= bezt->vec[1][1];
+
+ if (prev)
+ valB= prev->vec[1][1];
+ else
+ valB= bezt->vec[1][1] + 1.0f;
+
+ if (IS_EQ(valA, nValue) && IS_EQ(valA, valB))
+ return KEYNEEDED_DELPREV;
+ else
+ return KEYNEEDED_JUSTADD;
+}
+
+/* ------------------ RNA Data-Access Functions ------------------ */
+
+/* Try to read value using RNA-properties obtained already */
+static float setting_get_rna_value (PointerRNA *ptr, PropertyRNA *prop, int index)
+{
+ float value= 0.0f;
+
+ switch (RNA_property_type(prop)) {
+ case PROP_BOOLEAN:
+ if (RNA_property_array_length(prop))
+ value= (float)RNA_property_boolean_get_index(ptr, prop, index);
+ else
+ value= (float)RNA_property_boolean_get(ptr, prop);
+ break;
+ case PROP_INT:
+ if (RNA_property_array_length(prop))
+ value= (float)RNA_property_int_get_index(ptr, prop, index);
+ else
+ value= (float)RNA_property_int_get(ptr, prop);
+ break;
+ case PROP_FLOAT:
+ if (RNA_property_array_length(prop))
+ value= RNA_property_float_get_index(ptr, prop, index);
+ else
+ value= RNA_property_float_get(ptr, prop);
+ break;
+ case PROP_ENUM:
+ value= (float)RNA_property_enum_get(ptr, prop);
+ break;
+ default:
+ break;
+ }
+
+ return value;
+}
+
+/* ------------------ 'Visual' Keyframing Functions ------------------ */
+
+/* internal status codes for visualkey_can_use */
+enum {
+ VISUALKEY_NONE = 0,
+ VISUALKEY_LOC,
+ VISUALKEY_ROT,
+};
+
+/* This helper function determines if visual-keyframing should be used when
+ * inserting keyframes for the given channel. As visual-keyframing only works
+ * on Object and Pose-Channel blocks, this should only get called for those
+ * blocktypes, when using "standard" keying but 'Visual Keying' option in Auto-Keying
+ * settings is on.
+ */
+static short visualkey_can_use (PointerRNA *ptr, PropertyRNA *prop)
+{
+ bConstraint *con= NULL;
+ short searchtype= VISUALKEY_NONE;
+ char *identifier= NULL;
+
+ /* validate data */
+ // TODO: this check is probably not needed, but it won't hurt
+ if (ELEM3(NULL, ptr, ptr->data, prop))
+ return 0;
+
+ /* get first constraint and determine type of keyframe constraints to check for
+ * - constraints can be on either Objects or PoseChannels, so we only check if the
+ * ptr->type is RNA_Object or RNA_PoseChannel, which are the RNA wrapping-info for
+ * those structs, allowing us to identify the owner of the data
+ */
+ if (ptr->type == &RNA_Object) {
+ /* Object */
+ Object *ob= (Object *)ptr->data;
+
+ con= ob->constraints.first;
+ identifier= (char *)RNA_property_identifier(prop);
+ }
+ else if (ptr->type == &RNA_PoseChannel) {
+ /* Pose Channel */
+ bPoseChannel *pchan= (bPoseChannel *)ptr->data;
+
+ con= pchan->constraints.first;
+ identifier= (char *)RNA_property_identifier(prop);
+ }
+
+ /* check if any data to search using */
+ if (ELEM(NULL, con, identifier))
+ return 0;
+
+ /* location or rotation identifiers only... */
+ if (strstr(identifier, "location"))
+ searchtype= VISUALKEY_LOC;
+ else if (strstr(identifier, "rotation"))
+ searchtype= VISUALKEY_ROT;
+ else {
+ printf("visualkey_can_use() failed: identifier - '%s' \n", identifier);
+ return 0;
+ }
+
+
+ /* only search if a searchtype and initial constraint are available */
+ if (searchtype && con) {
+ for (; con; con= con->next) {
+ /* only consider constraint if it is not disabled, and has influence */
+ if (con->flag & CONSTRAINT_DISABLE) continue;
+ if (con->enforce == 0.0f) continue;
+
+ /* some constraints may alter these transforms */
+ switch (con->type) {
+ /* multi-transform constraints */
+ case CONSTRAINT_TYPE_CHILDOF:
+ return 1;
+ case CONSTRAINT_TYPE_TRANSFORM:
+ return 1;
+ case CONSTRAINT_TYPE_FOLLOWPATH:
+ return 1;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ return 1;
+
+ /* single-transform constraits */
+ case CONSTRAINT_TYPE_TRACKTO:
+ if (searchtype==VISUALKEY_ROT) return 1;
+ break;
+ case CONSTRAINT_TYPE_ROTLIMIT:
+ if (searchtype==VISUALKEY_ROT) return 1;
+ break;
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ if (searchtype==VISUALKEY_LOC) return 1;
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ if (searchtype==VISUALKEY_ROT) return 1;
+ break;
+ case CONSTRAINT_TYPE_DISTLIMIT:
+ if (searchtype==VISUALKEY_LOC) return 1;
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ if (searchtype==VISUALKEY_LOC) return 1;
+ break;
+ case CONSTRAINT_TYPE_LOCKTRACK:
+ if (searchtype==VISUALKEY_ROT) return 1;
+ break;
+ case CONSTRAINT_TYPE_MINMAX:
+ if (searchtype==VISUALKEY_LOC) return 1;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ /* when some condition is met, this function returns, so here it can be 0 */
+ return 0;
+}
+
+/* This helper function extracts the value to use for visual-keyframing
+ * In the event that it is not possible to perform visual keying, try to fall-back
+ * to using the default method. Assumes that all data it has been passed is valid.
+ */
+static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_index)
+{
+ char *identifier= (char *)RNA_property_identifier(prop);
+
+ /* handle for Objects or PoseChannels only
+ * - constraints can be on either Objects or PoseChannels, so we only check if the
+ * ptr->type is RNA_Object or RNA_PoseChannel, which are the RNA wrapping-info for
+ * those structs, allowing us to identify the owner of the data
+ * - assume that array_index will be sane
+ */
+ if (ptr->type == &RNA_Object) {
+ Object *ob= (Object *)ptr->data;
+
+ /* parented objects are not supported, as the effects of the parent
+ * are included in the matrix, which kindof beats the point
+ */
+ if (ob->parent == NULL) {
+ /* only Location or Rotation keyframes are supported now */
+ if (strstr(identifier, "location")) {
+ return ob->obmat[3][array_index];
+ }
+ else if (strstr(identifier, "rotation")) {
+ float eul[3];
+
+ Mat4ToEul(ob->obmat, eul);
+ return eul[array_index];
+ }
+ }
+ }
+ else if (ptr->type == &RNA_PoseChannel) {
+ Object *ob= (Object *)ptr->id.data; /* we assume that this is always set, and is an object */
+ bPoseChannel *pchan= (bPoseChannel *)ptr->data;
+ float tmat[4][4];
+
+ /* Although it is not strictly required for this particular space conversion,
+ * arg1 must not be null, as there is a null check for the other conversions to
+ * be safe. Therefore, the active object is passed here, and in many cases, this
+ * will be what owns the pose-channel that is getting this anyway.
+ */
+ Mat4CpyMat4(tmat, pchan->pose_mat);
+ constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+
+ /* Loc, Rot/Quat keyframes are supported... */
+ if (strstr(identifier, "location")) {
+ /* only use for non-connected bones */
+ if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED))
+ return tmat[3][array_index];
+ else if (pchan->bone->parent == NULL)
+ return tmat[3][array_index];
+ }
+ else if (strstr(identifier, "euler_rotation")) {
+ float eul[3];
+
+ /* euler-rotation test before standard rotation, as standard rotation does quats */
+ Mat4ToEul(tmat, eul);
+ return eul[array_index];
+ }
+ else if (strstr(identifier, "rotation")) {
+ float trimat[3][3], quat[4];
+
+ Mat3CpyMat4(trimat, tmat);
+ Mat3ToQuat_is_ok(trimat, quat);
+
+ return quat[array_index];
+ }
+ }
+
+ /* as the function hasn't returned yet, read value from system in the default way */
+ return setting_get_rna_value(ptr, prop, array_index);
+}
+
+/* ------------------------- Insert Key API ------------------------- */
+
+/* Main Keyframing API call:
+ * Use this when validation of necessary animation data isn't necessary as it
+ * already exists. It will insert a keyframe using the current value being keyframed.
+ *
+ * The flag argument is used for special settings that alter the behaviour of
+ * the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
+ * and extra keyframe filtering.
+ */
+short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag)
+{
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ FCurve *fcu;
+
+ /* validate pointer first - exit if failure */
+ RNA_id_pointer_create(id, &id_ptr);
+ if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
+ printf("Insert Key: Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path);
+ return 0;
+ }
+
+ /* get F-Curve - if no action is provided, keyframe to the default one attached to this ID-block */
+ if (act == NULL)
+ act= verify_adt_action(id, 1);
+ fcu= verify_fcurve(act, group, rna_path, array_index, 1);
+
+ /* only continue if we have an F-Curve to add keyframe to */
+ if (fcu) {
+ float curval= 0.0f;
+
+ /* set additional flags for the F-Curve (i.e. only integer values) */
+ if (RNA_property_type(prop) != PROP_FLOAT)
+ fcu->flag |= FCURVE_INT_VALUES;
+
+ /* apply special time tweaking */
+ // XXX check on this stuff...
+ if (GS(id->name) == ID_OB) {
+ //Object *ob= (Object *)id;
+
+ /* apply NLA-scaling (if applicable) */
+ //cfra= get_action_frame(ob, cfra);
+
+ /* ancient time-offset cruft */
+ //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
+ // /* actually frametofloat calc again! */
+ // cfra-= give_timeoffset(ob)*scene->r.framelen;
+ //}
+ }
+
+ /* obtain value to give keyframe */
+ if ( (flag & INSERTKEY_MATRIX) &&
+ (visualkey_can_use(&ptr, prop)) )
+ {
+ /* visual-keying is only available for object and pchan datablocks, as
+ * it works by keyframing using a value extracted from the final matrix
+ * instead of using the kt system to extract a value.
+ */
+ curval= visualkey_get_value(&ptr, prop, array_index);
+ }
+ else {
+ /* read value from system */
+ curval= setting_get_rna_value(&ptr, prop, array_index);
+ }
+
+ /* only insert keyframes where they are needed */
+ if (flag & INSERTKEY_NEEDED) {
+ short insert_mode;
+
+ /* check whether this curve really needs a new keyframe */
+ insert_mode= new_key_needed(fcu, cfra, curval);
+
+ /* insert new keyframe at current frame */
+ if (insert_mode)
+ insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
+
+ /* delete keyframe immediately before/after newly added */
+ switch (insert_mode) {
+ case KEYNEEDED_DELPREV:
+ delete_fcurve_key(fcu, fcu->totvert-2, 1);
+ break;
+ case KEYNEEDED_DELNEXT:
+ delete_fcurve_key(fcu, 1, 1);
+ break;
+ }
+
+ /* only return success if keyframe added */
+ if (insert_mode)
+ return 1;
+ }
+ else {
+ /* just insert keyframe */
+ insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
+
+ /* return success */
+ return 1;
+ }
+ }
+
+ /* return failure */
+ return 0;
+}
+
+/* ************************************************** */
+/* KEYFRAME DELETION */
+
+/* Main Keyframing API call:
+ * Use this when validation of necessary animation data isn't necessary as it
+ * already exists. It will delete a keyframe at the current frame.
+ *
+ * The flag argument is used for special settings that alter the behaviour of
+ * the keyframe deletion. These include the quick refresh options.
+ */
+short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag)
+{
+ FCurve *fcu = NULL;
+
+ /* get F-Curve
+ * Note: here is one of the places where we don't want new Action + F-Curve added!
+ * so 'add' var must be 0
+ */
+ if (act == NULL) {
+ /* if no action is provided, use the default one attached to this ID-block */
+ AnimData *adt= BKE_animdata_from_id(id);
+ act= adt->action;
+ }
+ /* we don't check the validity of the path here yet, but it should be ok... */
+ fcu= verify_fcurve(act, group, rna_path, array_index, 0);
+
+ /* only continue if we have an F-Curve to remove keyframes from */
+ if (act && fcu) {
+ short found = -1;
+ int i;
+
+ /* apply special time tweaking */
+ if (GS(id->name) == ID_OB) {
+ //Object *ob= (Object *)id;
+
+ /* apply NLA-scaling (if applicable) */
+ // cfra= get_action_frame(ob, cfra);
+
+ /* ancient time-offset cruft */
+ //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
+ // /* actually frametofloat calc again! */
+ // cfra-= give_timeoffset(ob)*scene->r.framelen;
+ //}
+ }
+
+ /* try to find index of beztriple to get rid of */
+ i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
+ if (found) {
+ /* delete the key at the index (will sanity check + do recalc afterwards) */
+ delete_fcurve_key(fcu, i, 1);
+
+ /* Only delete curve too if there are no points (we don't need to check for drivers, as they're kept separate) */
+ if (fcu->totvert == 0) {
+ BLI_remlink(&act->curves, fcu);
+ free_fcurve(fcu);
+ }
+
+ /* return success */
+ return 1;
+ }
+ }
+
+ /* return failure */
+ return 0;
+}
+
+/* ******************************************* */
+/* KEYFRAME MODIFICATION */
+
+/* mode for commonkey_modifykey */
+enum {
+ COMMONKEY_MODE_INSERT = 0,
+ COMMONKEY_MODE_DELETE,
+} eCommonModifyKey_Modes;
+
+/* Polling callback for use with ANIM_*_keyframe() operators
+ * This is based on the standard ED_operator_areaactive callback,
+ * except that it does special checks for a few spacetypes too...
+ */
+static int modify_key_op_poll(bContext *C)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ Scene *scene= CTX_data_scene(C);
+
+ /* if no area or active scene */
+ if (ELEM(NULL, sa, scene))
+ return 0;
+
+ /* if Outliner, only allow in DataBlocks view */
+ if (sa->spacetype == SPACE_OUTLINER) {
+ SpaceOops *so= (SpaceOops *)CTX_wm_space_data(C);
+
+ if ((so->outlinevis != SO_DATABLOCKS))
+ return 0;
+ }
+
+ /* TODO: checks for other space types can be added here */
+
+ /* should be fine */
+ return 1;
+}
+
+/* Insert Key Operator ------------------------ */
+
+static int insert_key_exec (bContext *C, wmOperator *op)
+{
+ ListBase dsources = {NULL, NULL};
+ Scene *scene= CTX_data_scene(C);
+ KeyingSet *ks= NULL;
+ int type= RNA_int_get(op->ptr, "type");
+ float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
+ short success;
+
+ /* type is the Keying Set the user specified to use when calling the operator:
+ * - type == 0: use scene's active Keying Set
+ * - type > 0: use a user-defined Keying Set from the active scene
+ * - type < 0: use a builtin Keying Set
+ */
+ if (type == 0)
+ type= scene->active_keyingset;
+ if (type > 0)
+ ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
+ else
+ ks= BLI_findlink(&builtin_keyingsets, -type-1);
+
+ /* report failures */
+ if (ks == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get context info for relative Keying Sets */
+ if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
+ /* exit if no suitable data obtained */
+ if (modifykey_get_context_data(C, &dsources, ks) == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No suitable context info for active Keying Set");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ /* try to insert keyframes for the channels specified by KeyingSet */
+ success= modify_keyframes(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ printf("KeyingSet '%s' - Successfully added %d Keyframes \n", ks->name, success);
+
+ /* report failure? */
+ if (success == 0)
+ BKE_report(op->reports, RPT_WARNING, "Keying Set failed to insert any keyframes");
+
+ /* free temp context-data if available */
+ if (dsources.first) {
+ /* we assume that there is no extra data that needs to be freed from here... */
+ BLI_freelistN(&dsources);
+ }
+
+ /* send updates */
+ ED_anim_dag_flush_update(C);
+
+ /* for now, only send ND_KEYS for KeyingSets */
+ WM_event_add_notifier(C, ND_KEYS, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void ANIM_OT_insert_keyframe (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Insert Keyframe";
+ ot->idname= "ANIM_OT_insert_keyframe";
+
+ /* callbacks */
+ ot->exec= insert_key_exec;
+ ot->poll= modify_key_op_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* settings */
+ RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1);
+}
+
+/* Insert Key Operator (With Menu) ------------------------ */
+
+/* XXX
+ * This operator pops up a menu which sets gets the index of the keyingset to use,
+ * setting the global settings, and calling the insert-keyframe operator using these
+ * settings
+ */
+
+static int insert_key_menu_invoke (bContext *C, wmOperator *op, wmEvent *event)
+{
+ Scene *scene= CTX_data_scene(C);
+ KeyingSet *ks;
+ uiMenuItem *head;
+ int i = 0;
+
+ head= uiPupMenuBegin("Insert Keyframe", 0);
+
+ /* active Keying Set */
+ uiMenuItemIntO(head, "Active Keying Set", 0, "ANIM_OT_insert_keyframe_menu", "type", i++);
+ uiMenuSeparator(head);
+
+ /* user-defined Keying Sets
+ * - these are listed in the order in which they were defined for the active scene
+ */
+ if (scene->keyingsets.first) {
+ for (ks= scene->keyingsets.first; ks; ks= ks->next)
+ uiMenuItemIntO(head, ks->name, 0, "ANIM_OT_insert_keyframe_menu", "type", i++);
+ uiMenuSeparator(head);
+ }
+
+ /* builtin Keying Sets */
+ // XXX polling the entire list may lag
+ i= -1;
+ for (ks= builtin_keyingsets.first; ks; ks= ks->next) {
+ /* only show KeyingSet if context is suitable */
+ if (keyingset_context_ok_poll(C, ks)) {
+ uiMenuItemIntO(head, ks->name, 0, "ANIM_OT_insert_keyframe_menu", "type", i--);
+ }
+ }
+
+ uiPupMenuEnd(C, head);
+
+ return OPERATOR_CANCELLED;
+}
+
+void ANIM_OT_insert_keyframe_menu (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Insert Keyframe";
+ ot->idname= "ANIM_OT_insert_keyframe_menu";
+
+ /* callbacks */
+ ot->invoke= insert_key_menu_invoke;
+ ot->exec= insert_key_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties
+ * - NOTE: here the type is int not enum, since many of the indicies here are determined dynamically
+ */
+ RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1);
+}
+
+/* Delete Key Operator ------------------------ */
+
+static int delete_key_exec (bContext *C, wmOperator *op)
+{
+ ListBase dsources = {NULL, NULL};
+ Scene *scene= CTX_data_scene(C);
+ KeyingSet *ks= NULL;
+ int type= RNA_int_get(op->ptr, "type");
+ float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
+ short success;
+
+ /* type is the Keying Set the user specified to use when calling the operator:
+ * - type == 0: use scene's active Keying Set
+ * - type > 0: use a user-defined Keying Set from the active scene
+ * - type < 0: use a builtin Keying Set
+ */
+ if (type == 0)
+ type= scene->active_keyingset;
+ if (type > 0)
+ ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
+ else
+ ks= BLI_findlink(&builtin_keyingsets, -type-1);
+
+ /* report failure */
+ if (ks == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get context info for relative Keying Sets */
+ if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
+ /* exit if no suitable data obtained */
+ if (modifykey_get_context_data(C, &dsources, ks) == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No suitable context info for active Keying Set");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ /* try to insert keyframes for the channels specified by KeyingSet */
+ success= modify_keyframes(C, &dsources, NULL, ks, MODIFYKEY_MODE_DELETE, cfra);
+ printf("KeyingSet '%s' - Successfully removed %d Keyframes \n", ks->name, success);
+
+ /* report failure? */
+ if (success == 0)
+ BKE_report(op->reports, RPT_WARNING, "Keying Set failed to remove any keyframes");
+
+ /* free temp context-data if available */
+ if (dsources.first) {
+ /* we assume that there is no extra data that needs to be freed from here... */
+ BLI_freelistN(&dsources);
+ }
+
+ /* send updates */
+ ED_anim_dag_flush_update(C);
+
+ /* for now, only send ND_KEYS for KeyingSets */
+ WM_event_add_notifier(C, ND_KEYS, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void ANIM_OT_delete_keyframe (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete Keyframe";
+ ot->idname= "ANIM_OT_delete_keyframe";
+
+ /* callbacks */
+ ot->exec= delete_key_exec;
+ ot->poll= modify_key_op_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties
+ * - NOTE: here the type is int not enum, since many of the indicies here are determined dynamically
+ */
+ RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1);
+}
+
+/* Delete Key Operator ------------------------ */
+
+/* XXX WARNING:
+ * This is currently just a basic operator, which work in 3d-view context on objects only.
+ * Should this be kept? It does have advantages over a version which requires selecting a keyingset to use...
+ * -- Joshua Leung, Jan 2009
+ */
+
+static int delete_key_old_exec (bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
+
+ // XXX more comprehensive tests will be needed
+ CTX_DATA_BEGIN(C, Base*, base, selected_bases)
+ {
+ Object *ob= base->object;
+ ID *id= (ID *)ob;
+ FCurve *fcu, *fcn;
+ short success= 0;
+
+ /* loop through all curves in animdata and delete keys on this frame */
+ if (ob->adt) {
+ AnimData *adt= ob->adt;
+ bAction *act= adt->action;
+
+ for (fcu= act->curves.first; fcu; fcu= fcn) {
+ fcn= fcu->next;
+ success+= delete_keyframe(id, NULL, NULL, fcu->rna_path, fcu->array_index, cfra, 0);
+ }
+ }
+
+ printf("Ob '%s' - Successfully removed %d keyframes \n", id->name+2, success);
+
+ ob->recalc |= OB_RECALC_OB;
+ }
+ CTX_DATA_END;
+
+ /* send updates */
+ ED_anim_dag_flush_update(C);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void ANIM_OT_delete_keyframe_old (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete Keyframe";
+ ot->idname= "ANIM_OT_delete_keyframe_old";
+
+ /* callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= delete_key_old_exec;
+
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+/* Insert Key Button Operator ------------------------ */
+
+static int insert_key_button_exec (bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ PointerRNA ptr;
+ PropertyRNA *prop= NULL;
+ char *path;
+ float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
+ short success= 0;
+ int a, index, length, all= RNA_boolean_get(op->ptr, "all");
+
+ /* try to insert keyframe using property retrieved from UI */
+ memset(&ptr, 0, sizeof(PointerRNA));
+ uiAnimContextProperty(C, &ptr, &prop, &index);
+
+ if(ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
+ path= RNA_path_from_ID_to_property(&ptr, prop);
+
+ if(path) {
+ if(all) {
+ length= RNA_property_array_length(prop);
+
+ if(length) index= 0;
+ else length= 1;
+ }
+ else
+ length= 1;
+
+ for(a=0; a<length; a++)
+ success+= insert_keyframe(ptr.id.data, NULL, NULL, path, index+a, cfra, 0);
+
+ MEM_freeN(path);
+ }
+ }
+
+ if(success) {
+ /* send updates */
+ ED_anim_dag_flush_update(C);
+
+ /* for now, only send ND_KEYS for KeyingSets */
+ WM_event_add_notifier(C, ND_KEYS, NULL);
+ }
+
+ return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
+}
+
+void ANIM_OT_insert_keyframe_button (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Insert Keyframe";
+ ot->idname= "ANIM_OT_insert_keyframe_button";
+
+ /* callbacks */
+ ot->exec= insert_key_button_exec;
+ ot->poll= modify_key_op_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Insert a keyframe for all element of the array.");
+}
+
+/* Delete Key Button Operator ------------------------ */
+
+static int delete_key_button_exec (bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ PointerRNA ptr;
+ PropertyRNA *prop= NULL;
+ char *path;
+ float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
+ short success= 0;
+ int a, index, length, all= RNA_boolean_get(op->ptr, "all");
+
+ /* try to insert keyframe using property retrieved from UI */
+ memset(&ptr, 0, sizeof(PointerRNA));
+ uiAnimContextProperty(C, &ptr, &prop, &index);
+
+ if(ptr.data && prop) {
+ path= RNA_path_from_ID_to_property(&ptr, prop);
+
+ if(path) {
+ if(all) {
+ length= RNA_property_array_length(prop);
+
+ if(length) index= 0;
+ else length= 1;
+ }
+ else
+ length= 1;
+
+ for(a=0; a<length; a++)
+ success+= delete_keyframe(ptr.id.data, NULL, NULL, path, index+a, cfra, 0);
+
+ MEM_freeN(path);
+ }
+ }
+
+
+ if(success) {
+ /* send updates */
+ ED_anim_dag_flush_update(C);
+
+ /* for now, only send ND_KEYS for KeyingSets */
+ WM_event_add_notifier(C, ND_KEYS, NULL);
+ }
+
+ return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
+}
+
+void ANIM_OT_delete_keyframe_button (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete Keyframe";
+ ot->idname= "ANIM_OT_delete_keyframe_button";
+
+ /* callbacks */
+ ot->exec= delete_key_button_exec;
+ ot->poll= modify_key_op_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Delete keyfames from all elements of the array.");
+}
+
+/* ******************************************* */
+/* KEYFRAME DETECTION */
+
+/* --------------- API/Per-Datablock Handling ------------------- */
+
+/* Checks whether an Action has a keyframe for a given frame
+ * Since we're only concerned whether a keyframe exists, we can simply loop until a match is found...
+ */
+short action_frame_has_keyframe (bAction *act, float frame, short filter)
+{
+ FCurve *fcu;
+
+ /* can only find if there is data */
+ if (act == NULL)
+ return 0;
+
+ /* if only check non-muted, check if muted */
+ if ((filter & ANIMFILTER_KEYS_MUTED) || (act->flag & ACT_MUTED))
+ return 0;
+
+ /* loop over F-Curves, using binary-search to try to find matches
+ * - this assumes that keyframes are only beztriples
+ */
+ for (fcu= act->curves.first; fcu; fcu= fcu->next) {
+ /* only check if there are keyframes (currently only of type BezTriple) */
+ if (fcu->bezt && fcu->totvert) {
+ /* we either include all regardless of muting, or only non-muted */
+ if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED)==0) {
+ short replace = -1;
+ int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace);
+
+ /* binarysearch_bezt_index will set replace to be 0 or 1
+ * - obviously, 1 represents a match
+ */
+ if (replace) {
+ /* sanity check: 'i' may in rare cases exceed arraylen */
+ if ((i >= 0) && (i < fcu->totvert))
+ return 1;
+ }
+ }
+ }
+ }
+
+ /* nothing found */
+ return 0;
+}
+
+/* Checks whether an Object has a keyframe for a given frame */
+short object_frame_has_keyframe (Object *ob, float frame, short filter)
+{
+ /* error checking */
+ if (ob == NULL)
+ return 0;
+
+ /* check own animation data - specifically, the action it contains */
+ if ((ob->adt) && (ob->adt->action)) {
+ if (action_frame_has_keyframe(ob->adt->action, frame, filter))
+ return 1;
+ }
+
+ /* try shapekey keyframes (if available, and allowed by filter) */
+ if ( !(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOSKEY) ) {
+ Key *key= ob_get_key(ob);
+
+ /* shapekeys can have keyframes ('Relative Shape Keys')
+ * or depend on time (old 'Absolute Shape Keys')
+ */
+
+ /* 1. test for relative (with keyframes) */
+ if (id_frame_has_keyframe((ID *)key, frame, filter))
+ return 1;
+
+ /* 2. test for time */
+ // TODO... yet to be implemented (this feature may evolve before then anyway)
+ }
+
+ /* try materials */
+ if ( !(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOMAT) ) {
+ /* if only active, then we can skip a lot of looping */
+ if (filter & ANIMFILTER_KEYS_ACTIVE) {
+ Material *ma= give_current_material(ob, (ob->actcol + 1));
+
+ /* we only retrieve the active material... */
+ if (id_frame_has_keyframe((ID *)ma, frame, filter))
+ return 1;
+ }
+ else {
+ int a;
+
+ /* loop over materials */
+ for (a=0; a<ob->totcol; a++) {
+ Material *ma= give_current_material(ob, a+1);
+
+ if (id_frame_has_keyframe((ID *)ma, frame, filter))
+ return 1;
+ }
+ }
+ }
+
+ /* nothing found */
+ return 0;
+}
+
+/* --------------- API ------------------- */
+
+/* Checks whether a keyframe exists for the given ID-block one the given frame */
+short id_frame_has_keyframe (ID *id, float frame, short filter)
+{
+ /* sanity checks */
+ if (id == NULL)
+ return 0;
+
+ /* perform special checks for 'macro' types */
+ switch (GS(id->name)) {
+ case ID_OB: /* object */
+ return object_frame_has_keyframe((Object *)id, frame, filter);
+ break;
+
+ case ID_SCE: /* scene */
+ // XXX TODO... for now, just use 'normal' behaviour
+ // break;
+
+ default: /* 'normal type' */
+ {
+ AnimData *adt= BKE_animdata_from_id(id);
+
+ /* only check keyframes in active action */
+ if (adt)
+ return action_frame_has_keyframe(adt->action, frame, filter);
+ }
+ break;
+ }
+
+
+ /* no keyframe found */
+ return 0;
+}
+
+/* ************************************************** */
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
new file mode 100644
index 00000000000..0f5cef51bdb
--- /dev/null
+++ b/source/blender/editors/animation/keyingsets.c
@@ -0,0 +1,1178 @@
+/* Testing code for 2.5 animation system
+ * Copyright 2009, Joshua Leung
+ */
+
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_dynstr.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_key_types.h"
+#include "DNA_object_types.h"
+#include "DNA_material_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_action.h"
+#include "BKE_constraint.h"
+#include "BKE_fcurve.h"
+#include "BKE_utildefines.h"
+#include "BKE_context.h"
+#include "BKE_report.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_edit.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_types.h"
+
+#include "anim_intern.h"
+
+/* ************************************************** */
+/* KEYING SETS - EDITING API */
+
+/* Operators ------------------------------------------- */
+
+/* These operators are only provided for scripting/macro usage, not for direct
+ * calling from the UI since they wrap some of the data-access API code for these
+ * (defined in blenkernel) which have quite a few properties.
+ */
+
+/* ----- */
+
+static int keyingset_add_destination_exec (bContext *C, wmOperator *op)
+{
+ PointerRNA ptr;
+ KeyingSet *ks= NULL;
+ ID *id= NULL;
+ char rna_path[256], group_name[64]; // xxx
+ short groupmode=0, flag=0;
+ int array_index=0;
+
+ /* get settings from operator properties */
+ ptr = RNA_pointer_get(op->ptr, "keyingset");
+ if (ptr.data)
+ ks= (KeyingSet *)ptr.data;
+
+ ptr = RNA_pointer_get(op->ptr, "id");
+ if (ptr.data)
+ id= (ID *)ptr.data;
+
+ groupmode= RNA_enum_get(op->ptr, "grouping_method");
+ RNA_string_get(op->ptr, "group_name", group_name);
+
+ RNA_string_get(op->ptr, "rna_path", rna_path);
+ array_index= RNA_int_get(op->ptr, "array_index");
+
+ if (RNA_boolean_get(op->ptr, "entire_array"))
+ flag |= KSP_FLAG_WHOLE_ARRAY;
+
+ /* if enough args are provided, call API method */
+ if (ks) {
+ BKE_keyingset_add_destination(ks, id, group_name, rna_path, array_index, flag, groupmode);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Keying Set could not be added.");
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void ANIM_OT_keyingset_add_destination (wmOperatorType *ot)
+{
+ // XXX: this is also defined in rna_animation.c
+ static EnumPropertyItem prop_mode_grouping_items[] = {
+ {KSP_GROUP_NAMED, "NAMED", "Named Group", ""},
+ {KSP_GROUP_NONE, "NONE", "None", ""},
+ {KSP_GROUP_KSNAME, "KEYINGSET", "Keying Set Name", ""},
+ {0, NULL, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "Add Keying Set Destination";
+ ot->idname= "ANIM_OT_keyingset_add_destination";
+
+ /* callbacks */
+ ot->exec= keyingset_add_destination_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* props */
+ /* pointers */ // xxx - do we want to directly expose these?
+ RNA_def_pointer_runtime(ot->srna, "keyingset", &RNA_KeyingSet, "Keying Set", "Keying Set to add destination to.");
+ RNA_def_pointer_runtime(ot->srna, "id", &RNA_ID, "ID", "ID-block for the destination.");
+ /* grouping */
+ RNA_def_enum(ot->srna, "grouping_method", prop_mode_grouping_items, KSP_GROUP_NAMED, "Grouping Method", "Method used to define which Group-name to use.");
+ RNA_def_string(ot->srna, "group_name", "", 64, "Group Name", "Name of Action Group to assign destination to (only if grouping mode is to use this name).");
+ /* rna-path */
+ RNA_def_string(ot->srna, "rna_path", "", 256, "RNA-Path", "RNA-Path to destination property."); // xxx hopefully this is long enough
+ RNA_def_int(ot->srna, "array_index", 0, 0, INT_MAX, "Array Index", "If applicable, the index ", 0, INT_MAX);
+ /* flags */
+ RNA_def_boolean(ot->srna, "entire_array", 1, "Entire Array", "hen an 'array/vector' type is chosen (Location, Rotation, Color, etc.), entire array is to be used.");
+
+}
+
+/* ----- */
+
+static int keyingset_add_new_exec (bContext *C, wmOperator *op)
+{
+ Scene *sce= CTX_data_scene(C);
+ KeyingSet *ks= NULL;
+ short flag=0, keyingflag=0;
+ char name[64];
+
+ /* get settings from operator properties */
+ RNA_string_get(op->ptr, "name", name);
+
+ if (RNA_boolean_get(op->ptr, "absolute"))
+ flag |= KEYINGSET_ABSOLUTE;
+ if (RNA_boolean_get(op->ptr, "insertkey_needed"))
+ keyingflag |= INSERTKEY_NEEDED;
+ if (RNA_boolean_get(op->ptr, "insertkey_visual"))
+ keyingflag |= INSERTKEY_MATRIX;
+
+ /* call the API func, and set the active keyingset index */
+ ks= BKE_keyingset_add(&sce->keyingsets, name, flag, keyingflag);
+
+ if (ks) {
+ sce->active_keyingset= BLI_countlist(&sce->keyingsets);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Keying Set could not be added.");
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void ANIM_OT_keyingset_add_new (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Keying Set";
+ ot->idname= "ANIM_OT_keyingset_add_new";
+
+ /* callbacks */
+ ot->exec= keyingset_add_new_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* props */
+ /* name */
+ RNA_def_string(ot->srna, "name", "KeyingSet", 64, "Name", "Name of Keying Set");
+ /* flags */
+ RNA_def_boolean(ot->srna, "absolute", 1, "Absolute", "Keying Set defines specific paths/settings to be keyframed (i.e. is not reliant on context info)");
+ /* keying flags */
+ RNA_def_boolean(ot->srna, "insertkey_needed", 0, "Insert Keyframes - Only Needed", "Only insert keyframes where they're needed in the relevant F-Curves.");
+ RNA_def_boolean(ot->srna, "insertkey_visual", 0, "Insert Keyframes - Visual", "Insert keyframes based on 'visual transforms'.");
+}
+
+/* UI API --------------------------------------------- */
+
+/* Build menu-string of available keying-sets (allocates memory for string)
+ * NOTE: mode must not be longer than 64 chars
+ */
+char *ANIM_build_keyingsets_menu (ListBase *list, short for_edit)
+{
+ DynStr *pupds= BLI_dynstr_new();
+ KeyingSet *ks;
+ char buf[64];
+ char *str;
+ int i;
+
+ /* add title first */
+ BLI_dynstr_append(pupds, "Keying Sets%t|");
+
+ /* add dummy entries for none-active */
+ if (for_edit) {
+ BLI_dynstr_append(pupds, "Add New%x-1|");
+ BLI_dynstr_append(pupds, " %x0|");
+ }
+ else
+ BLI_dynstr_append(pupds, "<No Keying Set Active>%x0|");
+
+ /* loop through keyingsets, adding them */
+ for (ks=list->first, i=1; ks; ks=ks->next, i++) {
+ if (for_edit == 0)
+ BLI_dynstr_append(pupds, "KS: ");
+
+ BLI_dynstr_append(pupds, ks->name);
+ BLI_snprintf( buf, 64, "%%x%d%s", i, ((ks->next)?"|":"") );
+ BLI_dynstr_append(pupds, buf);
+ }
+
+ /* convert to normal MEM_malloc'd string */
+ str= BLI_dynstr_get_cstring(pupds);
+ BLI_dynstr_free(pupds);
+
+ return str;
+}
+
+
+/* ******************************************* */
+/* KEYING SETS - BUILTIN */
+
+#if 0 // XXX old keyingsets code based on adrcodes... to be restored in due course
+
+/* ------------- KeyingSet Defines ------------ */
+/* Note: these must all be named with the defks_* prefix, otherwise the template macro will not work! */
+
+/* macro for defining keyingset contexts */
+#define KSC_TEMPLATE(ctx_name) {&defks_##ctx_name[0], NULL, sizeof(defks_##ctx_name)/sizeof(bKeyingSet)}
+
+/* --- */
+
+/* check if option not available for deleting keys */
+static short incl_non_del_keys (bKeyingSet *ks, const char mode[])
+{
+ /* as optimisation, assume that it is sufficient to check only first letter
+ * of mode (int comparison should be faster than string!)
+ */
+ //if (strcmp(mode, "Delete")==0)
+ if (mode && mode[0]=='D')
+ return 0;
+
+ return 1;
+}
+
+/* Object KeyingSets ------ */
+
+/* check if include shapekey entry */
+static short incl_v3d_ob_shapekey (bKeyingSet *ks, const char mode[])
+{
+ //Object *ob= (G.obedit)? (G.obedit) : (OBACT); // XXX
+ Object *ob= NULL;
+ char *newname= NULL;
+
+ if(ob==NULL)
+ return 0;
+
+ /* not available for delete mode */
+ if (strcmp(mode, "Delete")==0)
+ return 0;
+
+ /* check if is geom object that can get shapekeys */
+ switch (ob->type) {
+ /* geometry? */
+ case OB_MESH: newname= "Mesh"; break;
+ case OB_CURVE: newname= "Curve"; break;
+ case OB_SURF: newname= "Surface"; break;
+ case OB_LATTICE: newname= "Lattice"; break;
+
+ /* not geometry! */
+ default:
+ return 0;
+ }
+
+ /* if ks is shapekey entry (this could be callled for separator before too!) */
+ if (ks->flag == -3)
+ BLI_strncpy(ks->name, newname, sizeof(ks->name));
+
+ /* if it gets here, it's ok */
+ return 1;
+}
+
+/* array for object keyingset defines */
+bKeyingSet defks_v3d_object[] =
+{
+ /* include_cb, adrcode-getter, name, blocktype, flag, chan_num, adrcodes */
+ {NULL, "Loc", ID_OB, 0, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}},
+ {NULL, "Rot", ID_OB, 0, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
+ {NULL, "Scale", ID_OB, 0, 3, {OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "LocRot", ID_OB, 0, 6,
+ {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
+ OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
+
+ {NULL, "LocScale", ID_OB, 0, 6,
+ {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
+ OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
+
+ {NULL, "LocRotScale", ID_OB, 0, 9,
+ {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
+ OB_ROT_X,OB_ROT_Y,OB_ROT_Z,
+ OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
+
+ {NULL, "RotScale", ID_OB, 0, 6,
+ {OB_ROT_X,OB_ROT_Y,OB_ROT_Z,
+ OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
+
+ {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
+
+ {incl_non_del_keys, "VisualLoc", ID_OB, INSERTKEY_MATRIX, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}},
+ {incl_non_del_keys, "VisualRot", ID_OB, INSERTKEY_MATRIX, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
+
+ {incl_non_del_keys, "VisualLocRot", ID_OB, INSERTKEY_MATRIX, 6,
+ {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
+ OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "Layer", ID_OB, 0, 1, {OB_LAY}}, // icky option...
+ {NULL, "Available", ID_OB, -2, 0, {0}},
+
+ {incl_v3d_ob_shapekey, "%l%l", 0, -1, 0, {0}}, // separator (linked to shapekey entry)
+ {incl_v3d_ob_shapekey, "<ShapeKey>", ID_OB, -3, 0, {0}}
+};
+
+/* PoseChannel KeyingSets ------ */
+
+/* array for posechannel keyingset defines */
+bKeyingSet defks_v3d_pchan[] =
+{
+ /* include_cb, name, blocktype, flag, chan_num, adrcodes */
+ {NULL, "Loc", ID_PO, 0, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}},
+ {NULL, "Rot", ID_PO, COMMONKEY_PCHANROT, 1, {KAG_CHAN_EXTEND}},
+ {NULL, "Scale", ID_PO, 0, 3, {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "LocRot", ID_PO, COMMONKEY_PCHANROT, 4,
+ {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,
+ KAG_CHAN_EXTEND}},
+
+ {NULL, "LocScale", ID_PO, 0, 6,
+ {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,
+ AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
+
+ {NULL, "LocRotScale", ID_PO, COMMONKEY_PCHANROT, 7,
+ {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z,
+ KAG_CHAN_EXTEND}},
+
+ {NULL, "RotScale", ID_PO, 0, 4,
+ {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z,
+ KAG_CHAN_EXTEND}},
+
+ {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
+
+ {incl_non_del_keys, "VisualLoc", ID_PO, INSERTKEY_MATRIX, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}},
+ {incl_non_del_keys, "VisualRot", ID_PO, INSERTKEY_MATRIX|COMMONKEY_PCHANROT, 1, {KAG_CHAN_EXTEND}},
+
+ {incl_non_del_keys, "VisualLocRot", ID_PO, INSERTKEY_MATRIX|COMMONKEY_PCHANROT, 4,
+ {AC_LOC_X,AC_LOC_Y,AC_LOC_Z, KAG_CHAN_EXTEND}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "Available", ID_PO, -2, 0, {0}}
+};
+
+/* Material KeyingSets ------ */
+
+/* array for material keyingset defines */
+bKeyingSet defks_buts_shading_mat[] =
+{
+ /* include_cb, name, blocktype, flag, chan_num, adrcodes */
+ {NULL, "RGB", ID_MA, 0, 3, {MA_COL_R,MA_COL_G,MA_COL_B}},
+ {NULL, "Alpha", ID_MA, 0, 1, {MA_ALPHA}},
+ {NULL, "Halo Size", ID_MA, 0, 1, {MA_HASIZE}},
+ {NULL, "Mode", ID_MA, 0, 1, {MA_MODE}}, // evil bitflags
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "All Color", ID_MA, 0, 18,
+ {MA_COL_R,MA_COL_G,MA_COL_B,
+ MA_ALPHA,MA_HASIZE, MA_MODE,
+ MA_SPEC_R,MA_SPEC_G,MA_SPEC_B,
+ MA_REF,MA_EMIT,MA_AMB,MA_SPEC,MA_HARD,
+ MA_MODE,MA_TRANSLU,MA_ADD}},
+
+ {NULL, "All Mirror", ID_MA, 0, 5,
+ {MA_RAYM,MA_FRESMIR,MA_FRESMIRI,
+ MA_FRESTRA,MA_FRESTRAI}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "Ofs", ID_MA, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
+ {NULL, "Size", ID_MA, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
+
+ {NULL, "All Mapping", ID_MA, COMMONKEY_ADDMAP, 14,
+ {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
+ MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
+ MAP_R,MAP_G,MAP_B,MAP_DVAR,
+ MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "Available", ID_MA, -2, 0, {0}}
+};
+
+/* World KeyingSets ------ */
+
+/* array for world keyingset defines */
+bKeyingSet defks_buts_shading_wo[] =
+{
+ /* include_cb, name, blocktype, flag, chan_num, adrcodes */
+ {NULL, "Zenith RGB", ID_WO, 0, 3, {WO_ZEN_R,WO_ZEN_G,WO_ZEN_B}},
+ {NULL, "Horizon RGB", ID_WO, 0, 3, {WO_HOR_R,WO_HOR_G,WO_HOR_B}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "Mist", ID_WO, 0, 4, {WO_MISI,WO_MISTDI,WO_MISTSTA,WO_MISTHI}},
+ {NULL, "Stars", ID_WO, 0, 5, {WO_STAR_R,WO_STAR_G,WO_STAR_B,WO_STARDIST,WO_STARSIZE}},
+
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "Ofs", ID_WO, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
+ {NULL, "Size", ID_WO, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
+
+ {NULL, "All Mapping", ID_WO, COMMONKEY_ADDMAP, 14,
+ {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
+ MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
+ MAP_R,MAP_G,MAP_B,MAP_DVAR,
+ MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "Available", ID_WO, -2, 0, {0}}
+};
+
+/* Lamp KeyingSets ------ */
+
+/* array for lamp keyingset defines */
+bKeyingSet defks_buts_shading_la[] =
+{
+ /* include_cb, name, blocktype, flag, chan_num, adrcodes */
+ {NULL, "RGB", ID_LA, 0, 3, {LA_COL_R,LA_COL_G,LA_COL_B}},
+ {NULL, "Energy", ID_LA, 0, 1, {LA_ENERGY}},
+ {NULL, "Spot Size", ID_LA, 0, 1, {LA_SPOTSI}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "Ofs", ID_LA, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
+ {NULL, "Size", ID_LA, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
+
+ {NULL, "All Mapping", ID_LA, COMMONKEY_ADDMAP, 14,
+ {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
+ MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
+ MAP_R,MAP_G,MAP_B,MAP_DVAR,
+ MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "Available", ID_LA, -2, 0, {0}}
+};
+
+/* Texture KeyingSets ------ */
+
+/* array for texture keyingset defines */
+bKeyingSet defks_buts_shading_tex[] =
+{
+ /* include_cb, name, blocktype, flag, chan_num, adrcodes */
+ {NULL, "Clouds", ID_TE, 0, 5,
+ {TE_NSIZE,TE_NDEPTH,TE_NTYPE,
+ TE_MG_TYP,TE_N_BAS1}},
+
+ {NULL, "Marble", ID_TE, 0, 7,
+ {TE_NSIZE,TE_NDEPTH,TE_NTYPE,
+ TE_TURB,TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
+
+ {NULL, "Stucci", ID_TE, 0, 5,
+ {TE_NSIZE,TE_NTYPE,TE_TURB,
+ TE_MG_TYP,TE_N_BAS1}},
+
+ {NULL, "Wood", ID_TE, 0, 6,
+ {TE_NSIZE,TE_NTYPE,TE_TURB,
+ TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
+
+ {NULL, "Magic", ID_TE, 0, 2, {TE_NDEPTH,TE_TURB}},
+
+ {NULL, "Blend", ID_TE, 0, 1, {TE_MG_TYP}},
+
+ {NULL, "Musgrave", ID_TE, 0, 6,
+ {TE_MG_TYP,TE_MGH,TE_MG_LAC,
+ TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN}},
+
+ {NULL, "Voronoi", ID_TE, 0, 9,
+ {TE_VNW1,TE_VNW2,TE_VNW3,TE_VNW4,
+ TE_VNMEXP,TE_VN_DISTM,TE_VN_COLT,
+ TE_ISCA,TE_NSIZE}},
+
+ {NULL, "Distorted Noise", ID_TE, 0, 4,
+ {TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN,TE_DISTA}},
+
+ {NULL, "Color Filter", ID_TE, 0, 5,
+ {TE_COL_R,TE_COL_G,TE_COL_B,TE_BRIGHT,TE_CONTRA}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "Available", ID_TE, -2, 0, {0}}
+};
+
+/* Object Buttons KeyingSets ------ */
+
+/* check if include particles entry */
+static short incl_buts_ob (bKeyingSet *ks, const char mode[])
+{
+ //Object *ob= OBACT; // xxx
+ Object *ob= NULL;
+ /* only if object is mesh type */
+
+ if(ob==NULL) return 0;
+ return (ob->type == OB_MESH);
+}
+
+/* array for texture keyingset defines */
+bKeyingSet defks_buts_object[] =
+{
+ /* include_cb, name, blocktype, flag, chan_num, adrcodes */
+ {incl_buts_ob, "Surface Damping", ID_OB, 0, 1, {OB_PD_SDAMP}},
+ {incl_buts_ob, "Random Damping", ID_OB, 0, 1, {OB_PD_RDAMP}},
+ {incl_buts_ob, "Permeability", ID_OB, 0, 1, {OB_PD_PERM}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "Force Strength", ID_OB, 0, 1, {OB_PD_FSTR}},
+ {NULL, "Force Falloff", ID_OB, 0, 1, {OB_PD_FFALL}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "Available", ID_OB, -2, 0, {0}} // this will include ob-transforms too!
+};
+
+/* Camera Buttons KeyingSets ------ */
+
+/* check if include internal-renderer entry */
+static short incl_buts_cam1 (bKeyingSet *ks, const char mode[])
+{
+ Scene *scene= NULL; // FIXME this will cause a crash, but we need an extra arg first!
+ /* only if renderer is internal renderer */
+ return (scene->r.renderer==R_INTERN);
+}
+
+/* check if include external-renderer entry */
+static short incl_buts_cam2 (bKeyingSet *ks, const char mode[])
+{
+ Scene *scene= NULL; // FIXME this will cause a crash, but we need an extra arg first!
+ /* only if renderer is internal renderer */
+ return (scene->r.renderer!=R_INTERN);
+}
+
+/* array for camera keyingset defines */
+bKeyingSet defks_buts_cam[] =
+{
+ /* include_cb, name, blocktype, flag, chan_num, adrcodes */
+ {NULL, "Lens", ID_CA, 0, 1, {CAM_LENS}},
+ {NULL, "Clipping", ID_CA, 0, 2, {CAM_STA,CAM_END}},
+ {NULL, "Focal Distance", ID_CA, 0, 1, {CAM_YF_FDIST}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+
+ {incl_buts_cam2, "Aperture", ID_CA, 0, 1, {CAM_YF_APERT}},
+ {incl_buts_cam1, "Viewplane Shift", ID_CA, 0, 2, {CAM_SHIFT_X,CAM_SHIFT_Y}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "Available", ID_CA, -2, 0, {0}}
+};
+
+/* --- */
+
+/* Keying Context Defines - Must keep in sync with enumeration (eKS_Contexts) */
+bKeyingContext ks_contexts[] =
+{
+ KSC_TEMPLATE(v3d_object),
+ KSC_TEMPLATE(v3d_pchan),
+
+ KSC_TEMPLATE(buts_shading_mat),
+ KSC_TEMPLATE(buts_shading_wo),
+ KSC_TEMPLATE(buts_shading_la),
+ KSC_TEMPLATE(buts_shading_tex),
+
+ KSC_TEMPLATE(buts_object),
+ KSC_TEMPLATE(buts_cam)
+};
+
+/* Keying Context Enumeration - Must keep in sync with definitions*/
+typedef enum eKS_Contexts {
+ KSC_V3D_OBJECT = 0,
+ KSC_V3D_PCHAN,
+
+ KSC_BUTS_MAT,
+ KSC_BUTS_WO,
+ KSC_BUTS_LA,
+ KSC_BUTS_TEX,
+
+ KSC_BUTS_OB,
+ KSC_BUTS_CAM,
+
+ /* make sure this last one remains untouched! */
+ KSC_TOT_TYPES
+} eKS_Contexts;
+
+
+#endif // XXX old keyingsets code based on adrcodes... to be restored in due course
+
+/* Macros for Declaring KeyingSets ------------------- */
+
+/* A note about this system for declaring built-in Keying Sets:
+ * One may ask, "What is the purpose of all of these macros and static arrays?" and
+ * "Why not call the KeyingSets API defined in BKE_animsys.h?". The answer is two-fold.
+ *
+ * 1) Firstly, we use static arrays of struct definitions instead of function calls, as
+ * it reduces the start-up overhead and allocated-memory footprint of Blender. If we called
+ * the KeyingSets API to build these sets, the overhead of checking for unique names, allocating
+ * memory for each and every path and KeyingSet, scattered around in RAM, all of which would increase
+ * the startup time (which is totally unacceptable) and could lead to fragmentation+slower access times.
+ * 2) Since we aren't using function calls, we need a nice way of defining these KeyingSets in a way which
+ * is easily readable and less prone to breakage from changes to the underlying struct definitions. Further,
+ * adding additional entries SHOULD NOT require custom code to be written to access these new entries/sets.
+ * Therefore, here we have a system with nice, human-readable statements via macros, and static arrays which
+ * are linked together using more special macros + struct definitions, allowing for such a generic + simple
+ * initialisation function (init_builtin_keyingsets()) compared with that of something like the Nodes system.
+ *
+ * -- Joshua Leung, April 2009
+ */
+
+/* Struct type for declaring builtin KeyingSets in as entries in static arrays*/
+typedef struct bBuiltinKeyingSet {
+ KeyingSet ks; /* the KeyingSet to build */
+ int tot; /* the total number of paths defined */
+ KS_Path paths[64]; /* the paths for the KeyingSet to use */
+} bBuiltinKeyingSet;
+
+ /* WARNING: the following macros must be kept in sync with the
+ * struct definitions in DNA_anim_types.h!
+ */
+
+/* macro for defining a builtin KeyingSet */
+#define BI_KS_DEFINE_BEGIN(name, keyingflag) \
+ {{NULL, NULL, {NULL, NULL}, name, KEYINGSET_BUILTIN, keyingflag},
+
+/* macro to finish defining a builtin KeyingSet */
+#define BI_KS_DEFINE_END \
+ }
+
+/* macro to start defining paths for a builtin KeyingSet */
+#define BI_KS_PATHS_BEGIN(tot) \
+ tot, {
+
+/* macro to finish defining paths for a builtin KeyingSet */
+#define BI_KS_PATHS_END \
+ }
+
+/* macro for defining a builtin KeyingSet's path */
+#define BI_KSP_DEFINE(id_type, templates, prop_path, array_index, flag, groupflag) \
+ {NULL, NULL, NULL, "", id_type, templates, prop_path, array_index, flag, groupflag}
+
+/* macro for defining a builtin KeyingSet with no paths (use in place of BI_KS_PAHTS_BEGIN/END block) */
+#define BI_KS_PATHS_NONE \
+ 0, {0}
+
+/* ---- */
+
+/* Struct type for finding all the arrays of builtin KeyingSets */
+typedef struct bBuiltinKSContext {
+ bBuiltinKeyingSet *bks; /* array of KeyingSet definitions */
+ int tot; /* number of KeyingSets in this array */
+} bBuiltinKSContext;
+
+/* macro for defining builtin KeyingSet sets
+ * NOTE: all the arrays of sets must follow this naming convention!
+ */
+#define BKSC_TEMPLATE(ctx_name) {&def_builtin_keyingsets_##ctx_name[0], sizeof(def_builtin_keyingsets_##ctx_name)/sizeof(bBuiltinKeyingSet)}
+
+
+/* 3D-View Builtin KeyingSets ------------------------ */
+
+static bBuiltinKeyingSet def_builtin_keyingsets_v3d[] =
+{
+ /* Simple Keying Sets ************************************* */
+ /* Keying Set - "Location" ---------- */
+ BI_KS_DEFINE_BEGIN("Location", 0)
+ BI_KS_PATHS_BEGIN(1)
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM)
+ BI_KS_PATHS_END
+ BI_KS_DEFINE_END,
+
+ /* Keying Set - "Rotation" ---------- */
+ BI_KS_DEFINE_BEGIN("Rotation", 0)
+ BI_KS_PATHS_BEGIN(1)
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM)
+ BI_KS_PATHS_END
+ BI_KS_DEFINE_END,
+
+ /* Keying Set - "Scaling" ---------- */
+ BI_KS_DEFINE_BEGIN("Scaling", 0)
+ BI_KS_PATHS_BEGIN(1)
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "scale", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM)
+ BI_KS_PATHS_END
+ BI_KS_DEFINE_END,
+
+ /* Compound Keying Sets *********************************** */
+ /* Keying Set - "LocRot" ---------- */
+ BI_KS_DEFINE_BEGIN("LocRot", 0)
+ BI_KS_PATHS_BEGIN(2)
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM),
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM)
+ BI_KS_PATHS_END
+ BI_KS_DEFINE_END,
+
+ /* Keying Set - "LocRotScale" ---------- */
+ BI_KS_DEFINE_BEGIN("LocRotScale", 0)
+ BI_KS_PATHS_BEGIN(3)
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM),
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM),
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "scale", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM)
+ BI_KS_PATHS_END
+ BI_KS_DEFINE_END,
+
+ /* Keying Sets with Keying Flags ************************* */
+ /* Keying Set - "VisualLoc" ---------- */
+ BI_KS_DEFINE_BEGIN("VisualLoc", 0)
+ BI_KS_PATHS_BEGIN(1)
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", INSERTKEY_MATRIX, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM)
+ BI_KS_PATHS_END
+ BI_KS_DEFINE_END,
+
+ /* Keying Set - "Rotation" ---------- */
+ BI_KS_DEFINE_BEGIN("VisualRot", 0)
+ BI_KS_PATHS_BEGIN(1)
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "rotation", INSERTKEY_MATRIX, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM)
+ BI_KS_PATHS_END
+ BI_KS_DEFINE_END,
+
+ /* Keying Set - "VisualLocRot" ---------- */
+ BI_KS_DEFINE_BEGIN("VisualLocRot", 0)
+ BI_KS_PATHS_BEGIN(2)
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", INSERTKEY_MATRIX, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM),
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "rotation", INSERTKEY_MATRIX, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM)
+ BI_KS_PATHS_END
+ BI_KS_DEFINE_END
+};
+
+/* All Builtin KeyingSets ------------------------ */
+
+/* total number of builtin KeyingSet contexts */
+#define MAX_BKSC_TYPES 1
+
+/* array containing all the available builtin KeyingSets definition sets
+ * - size of this is MAX_BKSC_TYPES+1 so that we don't smash the stack
+ */
+static bBuiltinKSContext def_builtin_keyingsets[MAX_BKSC_TYPES+1] =
+{
+ BKSC_TEMPLATE(v3d)
+ /* add more contexts above this line... */
+};
+
+
+/* ListBase of these KeyingSets chained up ready for usage
+ * NOTE: this is exported to keyframing.c for use...
+ */
+ListBase builtin_keyingsets = {NULL, NULL};
+
+/* Utility API ------------------------ */
+
+/* Link up all of the builtin Keying Sets when starting up Blender
+ * This is called from WM_init() in wm_init_exit.c
+ */
+void init_builtin_keyingsets (void)
+{
+ bBuiltinKSContext *bksc;
+ bBuiltinKeyingSet *bks;
+ int bksc_i, bks_i;
+
+ /* loop over all the sets of KeyingSets, setting them up, and chaining them to the builtins list */
+ for (bksc_i= 0, bksc= &def_builtin_keyingsets[0]; bksc_i < MAX_BKSC_TYPES; bksc_i++, bksc++)
+ {
+ /* for each set definitions for a builtin KeyingSet, chain the paths to that KeyingSet and add */
+ for (bks_i= 0, bks= bksc->bks; bks_i < bksc->tot; bks_i++, bks++)
+ {
+ KeyingSet *ks= &bks->ks;
+ KS_Path *ksp;
+ int pIndex;
+
+ /* loop over paths, linking them to the KeyingSet and each other */
+ for (pIndex= 0, ksp= &bks->paths[0]; pIndex < bks->tot; pIndex++, ksp++)
+ BLI_addtail(&ks->paths, ksp);
+
+ /* add KeyingSet to builtin sets list */
+ BLI_addtail(&builtin_keyingsets, ks);
+ }
+ }
+}
+
+
+/* Get the first builtin KeyingSet with the given name, which occurs after the given one (or start of list if none given) */
+KeyingSet *ANIM_builtin_keyingset_get_named (KeyingSet *prevKS, char name[])
+{
+ KeyingSet *ks, *first=NULL;
+
+ /* sanity checks - any name to check? */
+ if (name[0] == 0)
+ return NULL;
+
+ /* get first KeyingSet to use */
+ if (prevKS && prevKS->next)
+ first= prevKS->next;
+ else
+ first= builtin_keyingsets.first;
+
+ /* loop over KeyingSets checking names */
+ for (ks= first; ks; ks= ks->next) {
+ if (strcmp(name, ks->name) == 0)
+ return ks;
+ }
+
+ /* no matches found */
+ return NULL;
+}
+
+/* ******************************************* */
+/* KEYFRAME MODIFICATION */
+
+/* KeyingSet Menu Helpers ------------ */
+
+/* Extract the maximum set of requirements from the KeyingSet */
+static int keyingset_relative_get_templates (KeyingSet *ks)
+{
+ KS_Path *ksp;
+ int templates= 0;
+
+ /* loop over the paths (could be slow to do for a number of KeyingSets)? */
+ for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
+ /* add the destination's templates to the set of templates required for the set */
+ templates |= ksp->templates;
+ }
+
+ return templates;
+}
+
+/* Check if context data is suitable for the given absolute Keying Set */
+short keyingset_context_ok_poll (bContext *C, KeyingSet *ks)
+{
+ ScrArea *sa= CTX_wm_area(C);
+
+ /* data retrieved from context depends on active editor */
+ if (sa == NULL) return 0;
+
+ switch (sa->spacetype) {
+ case SPACE_VIEW3D:
+ {
+ Object *obact= CTX_data_active_object(C);
+
+ /* if in posemode, check if 'pose-channels' requested for in KeyingSet */
+ if ((obact && obact->pose) && (obact->flag & OB_POSEMODE)) {
+ /* check for posechannels */
+
+ }
+ else {
+ /* check for selected object */
+
+ }
+ }
+ break;
+ }
+
+
+ return 1;
+}
+
+/* KeyingSet Context Operations ------------ */
+
+/* Get list of data-sources from context (in 3D-View) for inserting keyframes using the given relative Keying Set */
+static short modifykey_get_context_v3d_data (bContext *C, ListBase *dsources, KeyingSet *ks)
+{
+ bCommonKeySrc *cks;
+ Object *obact= CTX_data_active_object(C);
+ int templates;
+ short ok= 0;
+
+ /* get the templates in use in this KeyingSet which we should supply data for */
+ templates = keyingset_relative_get_templates(ks);
+
+ /* check if the active object is in PoseMode (i.e. only deal with bones) */
+ // TODO: check with the templates to see what we really need to store
+ if ((obact && obact->pose) && (obact->flag & OB_POSEMODE)) {
+ /* Pose Mode: Selected bones */
+#if 0
+ //set_pose_keys(ob); /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */
+
+ /* loop through posechannels */
+ //for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+ // if (pchan->flag & POSE_KEY) {
+ // }
+ //}
+#endif
+
+ CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans)
+ {
+ /* add a new keying-source */
+ cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
+ BLI_addtail(dsources, cks);
+
+ /* set necessary info */
+ cks->id= &obact->id;
+ cks->pchan= pchan;
+
+ if (templates & KSP_TEMPLATE_CONSTRAINT)
+ cks->con= constraints_get_active(&pchan->constraints);
+
+ ok= 1;
+ }
+ CTX_DATA_END;
+ }
+ else {
+ /* Object Mode: Selected objects */
+ CTX_DATA_BEGIN(C, Base*, base, selected_bases)
+ {
+ Object *ob= base->object;
+
+ /* add a new keying-source */
+ cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
+ BLI_addtail(dsources, cks);
+
+ /* set necessary info */
+ cks->id= &ob->id;
+
+ if (templates & KSP_TEMPLATE_CONSTRAINT)
+ cks->con= constraints_get_active(&ob->constraints);
+
+ ok= 1;
+ }
+ CTX_DATA_END;
+ }
+
+ /* return whether any data was extracted */
+ return ok;
+}
+
+/* Get list of data-sources from context for inserting keyframes using the given relative Keying Set */
+short modifykey_get_context_data (bContext *C, ListBase *dsources, KeyingSet *ks)
+{
+ ScrArea *sa= CTX_wm_area(C);
+
+ /* for now, the active area is used to determine what set of contexts apply */
+ if (sa == NULL)
+ return 0;
+
+ switch (sa->spacetype) {
+ case SPACE_VIEW3D: /* 3D-View: Selected Objects or Bones */
+ return modifykey_get_context_v3d_data(C, dsources, ks);
+ }
+
+ /* nothing happened */
+ return 0;
+}
+
+/* KeyingSet Operations (Insert/Delete Keyframes) ------------ */
+
+/* Given a KeyingSet and context info (if required), modify keyframes for the channels specified
+ * by the KeyingSet. This takes into account many of the different combinations of using KeyingSets.
+ * Returns the number of channels that keyframes were added to
+ */
+int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra)
+{
+ KS_Path *ksp;
+ int kflag=0, success= 0;
+ char *groupname= NULL;
+
+ /* get flags to use */
+ if (mode == MODIFYKEY_MODE_INSERT) {
+ /* use KeyingSet's flags as base */
+ kflag= ks->keyingflag;
+
+ /* suppliment with info from the context */
+ if (IS_AUTOKEY_FLAG(AUTOMATKEY)) kflag |= INSERTKEY_MATRIX;
+ if (IS_AUTOKEY_FLAG(INSERTNEEDED)) kflag |= INSERTKEY_NEEDED;
+ // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
+ }
+ else if (mode == MODIFYKEY_MODE_DELETE)
+ kflag= 0;
+
+ /* check if the KeyingSet is absolute or not (i.e. does it requires sources info) */
+ if (ks->flag & KEYINGSET_ABSOLUTE) {
+ /* Absolute KeyingSets are simpler to use, as all the destination info has already been
+ * provided by the user, and is stored, ready to use, in the KeyingSet paths.
+ */
+ for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
+ int arraylen, i;
+
+ /* get pointer to name of group to add channels to */
+ if (ksp->groupmode == KSP_GROUP_NONE)
+ groupname= NULL;
+ else if (ksp->groupmode == KSP_GROUP_KSNAME)
+ groupname= ks->name;
+ else
+ groupname= ksp->group;
+
+ /* init arraylen and i - arraylen should be greater than i so that
+ * normal non-array entries get keyframed correctly
+ */
+ i= ksp->array_index;
+ arraylen= i+1;
+
+ /* get length of array if whole array option is enabled */
+ if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) {
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+
+ RNA_id_pointer_create(ksp->id, &id_ptr);
+ if (RNA_path_resolve(&id_ptr, ksp->rna_path, &ptr, &prop) && prop)
+ arraylen= RNA_property_array_length(prop);
+ }
+
+ /* for each possible index, perform operation
+ * - assume that arraylen is greater than index
+ */
+ for (; i < arraylen; i++) {
+ /* action to take depends on mode */
+ if (mode == MODIFYKEY_MODE_INSERT)
+ success+= insert_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag);
+ else if (mode == MODIFYKEY_MODE_DELETE)
+ success+= delete_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag);
+ }
+
+ /* send notifiers and set recalc-flags */
+ // TODO: hopefully this doesn't result in execessive flooding of the notifier stack
+ if (C && ksp->id) {
+ switch (GS(ksp->id->name)) {
+ case ID_OB: /* Object (or Object-Related) Keyframes */
+ {
+ Object *ob= (Object *)ksp->id;
+
+ ob->recalc |= OB_RECALC;
+ WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, ksp->id);
+ }
+ break;
+ case ID_MA: /* Material Keyframes */
+ WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, ksp->id);
+ break;
+ }
+ }
+ }
+ }
+ else if (dsources && dsources->first) {
+ /* for each one of the 'sources', resolve the template markers and expand arrays, then insert keyframes */
+ bCommonKeySrc *cks;
+
+ /* for each 'source' for keyframe data, resolve each of the paths from the KeyingSet */
+ for (cks= dsources->first; cks; cks= cks->next) {
+ /* for each path in KeyingSet, construct a path using the templates */
+ for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
+ DynStr *pathds= BLI_dynstr_new();
+ char *path = NULL;
+ int arraylen, i;
+
+ /* set initial group name */
+ groupname= (cks->id) ? cks->id->name+2 : NULL;
+
+ /* construct the path */
+ // FIXME: this currently only works with a few hardcoded cases
+ if ((ksp->templates & KSP_TEMPLATE_PCHAN) && (cks->pchan)) {
+ /* add basic pose-channel path access */
+ BLI_dynstr_append(pathds, "pose.pose_channels[\"");
+ BLI_dynstr_append(pathds, cks->pchan->name);
+ BLI_dynstr_append(pathds, "\"]");
+
+ /* override default group name */
+ groupname= cks->pchan->name;
+ }
+ if ((ksp->templates & KSP_TEMPLATE_CONSTRAINT) && (cks->con)) {
+ /* add basic constraint path access */
+ BLI_dynstr_append(pathds, "constraints[\"");
+ BLI_dynstr_append(pathds, cks->con->name);
+ BLI_dynstr_append(pathds, "\"]");
+
+ /* override default group name */
+ groupname= cks->con->name;
+ }
+ {
+ /* add property stored in KeyingSet Path */
+ if (BLI_dynstr_get_len(pathds))
+ BLI_dynstr_append(pathds, ".");
+ BLI_dynstr_append(pathds, ksp->rna_path);
+
+ /* convert to C-string */
+ path= BLI_dynstr_get_cstring(pathds);
+ BLI_dynstr_free(pathds);
+ }
+
+ /* get pointer to name of group to add channels to
+ * - KSP_GROUP_TEMPLATE_ITEM is handled above while constructing the paths
+ */
+ if (ksp->groupmode == KSP_GROUP_NONE)
+ groupname= NULL;
+ else if (ksp->groupmode == KSP_GROUP_KSNAME)
+ groupname= ks->name;
+ else if (ksp->groupmode == KSP_GROUP_NAMED)
+ groupname= ksp->group;
+
+ /* init arraylen and i - arraylen should be greater than i so that
+ * normal non-array entries get keyframed correctly
+ */
+ i= ksp->array_index;
+ arraylen= i+1;
+
+ /* get length of array if whole array option is enabled */
+ if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) {
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+
+ RNA_id_pointer_create(cks->id, &id_ptr);
+ if (RNA_path_resolve(&id_ptr, path, &ptr, &prop) && prop)
+ arraylen= RNA_property_array_length(prop);
+ }
+
+ /* for each possible index, perform operation
+ * - assume that arraylen is greater than index
+ */
+ for (; i < arraylen; i++) {
+ /* action to take depends on mode */
+ if (mode == MODIFYKEY_MODE_INSERT)
+ success+= insert_keyframe(cks->id, act, groupname, path, i, cfra, kflag);
+ else if (mode == MODIFYKEY_MODE_DELETE)
+ success+= delete_keyframe(cks->id, act, groupname, path, i, cfra, kflag);
+ }
+
+ /* free the path */
+ MEM_freeN(path);
+ }
+
+ /* send notifiers and set recalc-flags */
+ // TODO: hopefully this doesn't result in execessive flooding of the notifier stack
+ if (C && cks->id) {
+ switch (GS(cks->id->name)) {
+ case ID_OB: /* Object (or Object-Related) Keyframes */
+ {
+ Object *ob= (Object *)cks->id;
+
+ ob->recalc |= OB_RECALC;
+ WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, cks->id);
+ }
+ break;
+ case ID_MA: /* Material Keyframes */
+ WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, cks->id);
+ break;
+ }
+ }
+ }
+ }
+
+ /* return the number of channels successfully affected */
+ return success;
+}
+
+/* ************************************************** */
diff --git a/source/blender/editors/armature/BIF_generate.h b/source/blender/editors/armature/BIF_generate.h
new file mode 100644
index 00000000000..bde079c45fb
--- /dev/null
+++ b/source/blender/editors/armature/BIF_generate.h
@@ -0,0 +1,45 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BIF_GENERATE_H
+#define BIF_GENERATE_H
+
+struct ToolSettings;
+struct EditBone;
+struct BArcIterator;
+struct bArmature;
+struct ListBase;
+
+typedef int(NextSubdivisionFunc)(struct ToolSettings*, struct BArcIterator*, int, int, float[3], float[3]);
+
+float calcArcCorrelation(struct BArcIterator *iter, int start, int end, float v0[3], float n[3]);
+
+int nextFixedSubdivision(struct ToolSettings *toolsettings, struct BArcIterator *iter, int start, int end, float head[3], float p[3]);
+int nextLengthSubdivision(struct ToolSettings *toolsettings, struct BArcIterator *iter, int start, int end, float head[3], float p[3]);
+int nextAdaptativeSubdivision(struct ToolSettings *toolsettings, struct BArcIterator *iter, int start, int end, float head[3], float p[3]);
+
+struct EditBone * subdivideArcBy(struct ToolSettings *toolsettings, struct bArmature *arm, ListBase *editbones, struct BArcIterator *iter, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion);
+
+void setBoneRollFromNormal(struct EditBone *bone, float *no, float invmat[][4], float tmat[][3]);
+
+
+#endif /* BIF_GENERATE_H */
diff --git a/source/blender/editors/armature/BIF_retarget.h b/source/blender/editors/armature/BIF_retarget.h
new file mode 100644
index 00000000000..c39f410424a
--- /dev/null
+++ b/source/blender/editors/armature/BIF_retarget.h
@@ -0,0 +1,160 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BIF_RETARGET_H
+#define BIF_RETARGET_H
+
+#include "DNA_listBase.h"
+
+#include "BLI_graph.h"
+#include "BLI_ghash.h"
+#include "BLI_threads.h"
+
+#include "reeb.h"
+
+struct Object;
+struct bArmature;
+struct bContext;
+
+struct EditBone;
+
+struct RigJoint;
+struct RigGraph;
+struct RigNode;
+struct RigArc;
+struct RigEdge;
+
+#define USE_THREADS
+
+typedef struct RigGraph {
+ ListBase arcs;
+ ListBase nodes;
+
+ float length;
+
+ FreeArc free_arc;
+ FreeNode free_node;
+ RadialSymmetry radial_symmetry;
+ AxialSymmetry axial_symmetry;
+ /*********************************/
+
+ int flag;
+
+ ListBase controls;
+ ListBase* editbones;
+
+ struct RigNode *head;
+ ReebGraph *link_mesh;
+
+
+ struct ThreadedWorker *worker;
+
+ GHash *bones_map; /* map of editbones by name */
+ GHash *controls_map; /* map of rigcontrols by bone pointer */
+
+ struct Object *ob;
+} RigGraph;
+
+typedef struct RigNode {
+ void *next, *prev;
+ float p[3];
+ int flag;
+
+ int degree;
+ struct BArc **arcs;
+
+ int subgraph_index;
+
+ int symmetry_level;
+ int symmetry_flag;
+ float symmetry_axis[3];
+ /*********************************/
+
+ ReebNode *link_mesh;
+} RigNode;
+
+typedef struct RigArc {
+ void *next, *prev;
+ RigNode *head, *tail;
+ int flag;
+
+ float length;
+
+ int symmetry_level;
+ int symmetry_group;
+ int symmetry_flag;
+ /*********************************/
+
+ ListBase edges;
+ int count;
+ ReebArc *link_mesh;
+} RigArc;
+
+typedef struct RigEdge {
+ struct RigEdge *next, *prev;
+ float head[3], tail[3];
+ float length;
+ float angle; /* angle to next edge */
+ float up_angle; /* angle between up_axis and the joint normal (defined as Previous edge CrossProduct Current edge */
+ struct EditBone *bone;
+ float up_axis[3];
+} RigEdge;
+
+/* Graph flags */
+#define RIG_FREE_BONELIST 1
+
+/* Control flags */
+#define RIG_CTRL_HEAD_DONE 1
+#define RIG_CTRL_TAIL_DONE 2
+#define RIG_CTRL_PARENT_DEFORM 4
+#define RIG_CTRL_FIT_ROOT 8
+#define RIG_CTRL_FIT_BONE 16
+
+#define RIG_CTRL_DONE (RIG_CTRL_HEAD_DONE|RIG_CTRL_TAIL_DONE)
+
+/* Control tail flags */
+typedef enum {
+ TL_NONE = 0,
+ TL_TAIL,
+ TL_HEAD
+} LinkTailMode;
+
+typedef struct RigControl {
+ struct RigControl *next, *prev;
+ float head[3], tail[3];
+ struct EditBone *bone;
+ struct EditBone *link;
+ struct EditBone *link_tail;
+ float up_axis[3];
+ float offset[3];
+ float qrot[4]; /* for dual linked bones, store the rotation of the linked bone for the finalization */
+ int flag;
+ LinkTailMode tail_mode;
+} RigControl;
+
+void BIF_retargetArc(struct bContext *C, ReebArc *earc, RigGraph *template_rigg);
+RigGraph *RIG_graphFromArmature(struct bContext *C, struct Object *ob, struct bArmature *arm);
+int RIG_nbJoints(RigGraph *rg);
+char *RIG_nameBone(RigGraph *rg, int arc_index, int bone_index);
+void RIG_freeRigGraph(BGraph *rg);
+
+#endif /* BIF_RETARGET_H */
diff --git a/source/blender/editors/armature/Makefile b/source/blender/editors/armature/Makefile
new file mode 100644
index 00000000000..f8cbb5ab37e
--- /dev/null
+++ b/source/blender/editors/armature/Makefile
@@ -0,0 +1,59 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_armature
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+CPPFLAGS += -I$(NAN_BMFONT)/include
+CPPFLAGS += -I$(NAN_OPENNL)/include
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I../../gpu
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../render/extern/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/armature/SConscript b/source/blender/editors/armature/SConscript
new file mode 100644
index 00000000000..e4e42a27b36
--- /dev/null
+++ b/source/blender/editors/armature/SConscript
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' ../../render/extern/include #/intern/guardedalloc #intern/bmfont'
+incs += ' ../../gpu ../../makesrna #/intern/opennl/extern'
+
+env.BlenderLib ( 'bf_editors_armature', sources, Split(incs), [], libtype=['core'], priority=[44] )
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
new file mode 100644
index 00000000000..646c75f50bf
--- /dev/null
+++ b/source/blender/editors/armature/armature_intern.h
@@ -0,0 +1,101 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_ARMATURE_INTERN_H
+#define ED_ARMATURE_INTERN_H
+
+/* internal exports only */
+struct wmOperatorType;
+
+/* editarmature.c operators */
+void ARMATURE_OT_bone_primitive_add(struct wmOperatorType *ot);
+void ARMATURE_OT_bones_align(struct wmOperatorType *ot);
+void ARMATURE_OT_calculate_roll(struct wmOperatorType *ot);
+void ARMATURE_OT_switch_direction(struct wmOperatorType *ot);
+void ARMATURE_OT_subdivs(struct wmOperatorType *ot);
+void ARMATURE_OT_subdivide_simple(struct wmOperatorType *ot);
+void ARMATURE_OT_subdivide_multi(struct wmOperatorType *ot);
+void ARMATURE_OT_parent_set(struct wmOperatorType *ot);
+void ARMATURE_OT_parent_clear(struct wmOperatorType *ot);
+void ARMATURE_OT_select_all_toggle(struct wmOperatorType *ot);
+void ARMATURE_OT_select_invert(struct wmOperatorType *ot);
+void ARMATURE_OT_select_hierarchy(struct wmOperatorType *ot);
+void ARMATURE_OT_select_linked(struct wmOperatorType *ot);
+void ARMATURE_OT_delete(struct wmOperatorType *ot);
+void ARMATURE_OT_duplicate_selected(struct wmOperatorType *ot);
+void ARMATURE_OT_extrude(struct wmOperatorType *ot);
+void ARMATURE_OT_click_extrude(struct wmOperatorType *ot);
+
+void POSE_OT_hide(struct wmOperatorType *ot);
+void POSE_OT_reveal(struct wmOperatorType *ot);
+void POSE_OT_rot_clear(struct wmOperatorType *ot);
+void POSE_OT_loc_clear(struct wmOperatorType *ot);
+void POSE_OT_scale_clear(struct wmOperatorType *ot);
+void POSE_OT_select_all_toggle(struct wmOperatorType *ot);
+void POSE_OT_select_invert(struct wmOperatorType *ot);
+void POSE_OT_select_parent(struct wmOperatorType *ot);
+void POSE_OT_select_hierarchy(struct wmOperatorType *ot);
+void POSE_OT_select_linked(struct wmOperatorType *ot);
+
+void SKETCH_OT_gesture(struct wmOperatorType *ot);
+void SKETCH_OT_delete(struct wmOperatorType *ot);
+void SKETCH_OT_draw_stroke(struct wmOperatorType *ot);
+void SKETCH_OT_draw_preview(struct wmOperatorType *ot);
+void SKETCH_OT_finish_stroke(struct wmOperatorType *ot);
+void SKETCH_OT_cancel_stroke(struct wmOperatorType *ot);
+void SKETCH_OT_select(struct wmOperatorType *ot);
+
+/* PoseLib */
+void POSELIB_OT_pose_add(struct wmOperatorType *ot);
+void POSELIB_OT_pose_remove(struct wmOperatorType *ot);
+void POSELIB_OT_pose_rename(struct wmOperatorType *ot);
+void POSELIB_OT_browse_interactive(struct wmOperatorType *ot);
+
+/* editarmature.c */
+struct bArmature;
+struct EditBone;
+struct ListBase;
+
+void make_boneList(struct ListBase *edbo, struct ListBase *bones, struct EditBone *parent);
+struct EditBone *addEditBone(struct bArmature *arm, char *name);
+void BIF_sk_selectStroke(struct bContext *C, short mval[2], short extend);
+
+/* duplicate method */
+void preEditBoneDuplicate(struct ListBase *editbones);
+struct EditBone *duplicateEditBone(struct EditBone *curBone, char *name, struct ListBase *editbones, struct Object *ob);
+void updateDuplicateSubtarget(struct EditBone *dupBone, struct ListBase *editbones, struct Object *ob);
+
+/* duplicate method (cross objects */
+
+/* editbones is the target list */
+struct EditBone *duplicateEditBoneObjects(struct EditBone *curBone, char *name, struct ListBase *editbones, struct Object *src_ob, struct Object *dst_ob);
+
+/* editbones is the source list */
+void updateDuplicateSubtargetObjects(struct EditBone *dupBone, struct ListBase *editbones, struct Object *src_ob, struct Object *dst_ob);
+
+#endif /* ED_ARMATURE_INTERN_H */
+
diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c
new file mode 100644
index 00000000000..5c31883834c
--- /dev/null
+++ b/source/blender/editors/armature/armature_ops.c
@@ -0,0 +1,269 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_armature.h"
+#include "ED_screen.h"
+#include "ED_object.h"
+
+#include "armature_intern.h"
+
+/* ************************** quick tests **********************************/
+
+/* XXX This is a quick test operator to print names of all EditBones in context
+ * that should be removed once tool coding starts...
+ */
+
+static int armature_test_exec (bContext *C, wmOperator *op)
+{
+ printf("EditMode Armature Test: \n");
+
+ printf("\tSelected Bones \n");
+ CTX_DATA_BEGIN(C, EditBone*, ebone, selected_bones)
+ {
+ printf("\t\tEditBone '%s' \n", ebone->name);
+ }
+ CTX_DATA_END;
+
+ printf("\tEditable Bones \n");
+ CTX_DATA_BEGIN(C, EditBone*, ebone, selected_editable_bones)
+ {
+ printf("\t\tEditBone '%s' \n", ebone->name);
+ }
+ CTX_DATA_END;
+
+ printf("\tActive Bone \n");
+ {
+ EditBone *ebone= CTX_data_active_bone(C);
+ if (ebone) printf("\t\tEditBone '%s' \n", ebone->name);
+ else printf("\t\t<None> \n");
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_test(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Test Context";
+ ot->idname= "ARMATURE_OT_test";
+
+ /* api callbacks */
+ ot->exec= armature_test_exec;
+}
+
+/* ************************** registration **********************************/
+
+/* Both operators ARMATURE_OT_xxx and POSE_OT_xxx here */
+void ED_operatortypes_armature(void)
+{
+ /* EDIT ARMATURE */
+ WM_operatortype_append(ARMATURE_OT_bone_primitive_add);
+
+ WM_operatortype_append(ARMATURE_OT_bones_align);
+ WM_operatortype_append(ARMATURE_OT_calculate_roll);
+ WM_operatortype_append(ARMATURE_OT_switch_direction);
+ WM_operatortype_append(ARMATURE_OT_subdivs);
+ WM_operatortype_append(ARMATURE_OT_subdivide_simple);
+ WM_operatortype_append(ARMATURE_OT_subdivide_multi);
+
+ WM_operatortype_append(ARMATURE_OT_parent_set);
+ WM_operatortype_append(ARMATURE_OT_parent_clear);
+
+ WM_operatortype_append(ARMATURE_OT_select_all_toggle);
+ WM_operatortype_append(ARMATURE_OT_select_invert);
+ WM_operatortype_append(ARMATURE_OT_select_hierarchy);
+ WM_operatortype_append(ARMATURE_OT_select_linked);
+
+ WM_operatortype_append(ARMATURE_OT_delete);
+ WM_operatortype_append(ARMATURE_OT_duplicate_selected);
+ WM_operatortype_append(ARMATURE_OT_extrude);
+ WM_operatortype_append(ARMATURE_OT_click_extrude);
+
+ /* SKETCH */
+ WM_operatortype_append(SKETCH_OT_gesture);
+ WM_operatortype_append(SKETCH_OT_delete);
+ WM_operatortype_append(SKETCH_OT_draw_stroke);
+ WM_operatortype_append(SKETCH_OT_draw_preview);
+ WM_operatortype_append(SKETCH_OT_finish_stroke);
+ WM_operatortype_append(SKETCH_OT_cancel_stroke);
+ WM_operatortype_append(SKETCH_OT_select);
+
+ /* POSE */
+ WM_operatortype_append(POSE_OT_hide);
+ WM_operatortype_append(POSE_OT_reveal);
+
+ WM_operatortype_append(POSE_OT_rot_clear);
+ WM_operatortype_append(POSE_OT_loc_clear);
+ WM_operatortype_append(POSE_OT_scale_clear);
+
+ WM_operatortype_append(POSE_OT_select_all_toggle);
+ WM_operatortype_append(POSE_OT_select_invert);
+
+ WM_operatortype_append(POSE_OT_select_parent);
+ WM_operatortype_append(POSE_OT_select_hierarchy);
+ WM_operatortype_append(POSE_OT_select_linked);
+
+ /* POSELIB */
+ WM_operatortype_append(POSELIB_OT_browse_interactive);
+
+ WM_operatortype_append(POSELIB_OT_pose_add);
+ WM_operatortype_append(POSELIB_OT_pose_remove);
+ WM_operatortype_append(POSELIB_OT_pose_rename);
+
+ /* TESTS */
+ WM_operatortype_append(ARMATURE_OT_test); // XXX temp test for context iterators... to be removed
+}
+
+void ED_keymap_armature(wmWindowManager *wm)
+{
+ ListBase *keymap;
+ wmKeymapItem *kmi;
+
+ /* Armature ------------------------ */
+ keymap= WM_keymap_listbase(wm, "Armature", 0, 0);
+
+ /* only set in editmode armature, by space_view3d listener */
+// WM_keymap_add_item(keymap, "ARMATURE_OT_hide", HKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "ARMATURE_OT_bones_align", AKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
+ WM_keymap_add_item(keymap, "ARMATURE_OT_calculate_roll", NKEY, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "ARMATURE_OT_switch_direction", FKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "ARMATURE_OT_bone_primitive_add", AKEY, KM_PRESS, KM_SHIFT, 0);
+ /* only the menu-version of subdivide is registered in keymaps for now */
+ WM_keymap_add_item(keymap, "ARMATURE_OT_subdivs", SKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "ARMATURE_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "ARMATURE_OT_parent_clear", PKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "ARMATURE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "ARMATURE_OT_select_invert", IKEY, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "ARMATURE_OT_test", TKEY, KM_PRESS, 0, 0); // XXX temp test for context iterators... to be removed
+
+ kmi= WM_keymap_add_item(keymap, "ARMATURE_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_PARENT);
+ RNA_boolean_set(kmi->ptr, "extend", 0);
+ kmi= WM_keymap_add_item(keymap, "ARMATURE_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_PARENT);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+
+ kmi= WM_keymap_add_item(keymap, "ARMATURE_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD);
+ RNA_boolean_set(kmi->ptr, "extend", 0);
+ kmi= WM_keymap_add_item(keymap, "ARMATURE_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+
+ WM_keymap_add_item(keymap, "ARMATURE_OT_select_linked", LKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "ARMATURE_OT_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "ARMATURE_OT_duplicate_selected", DKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "ARMATURE_OT_extrude", EKEY, KM_PRESS, 0, 0);
+ kmi= WM_keymap_add_item(keymap, "ARMATURE_OT_extrude", EKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "forked", 1);
+ WM_keymap_add_item(keymap, "ARMATURE_OT_click_extrude", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
+
+ /* Armature -> Etch-A-Ton ------------------------ */
+ WM_keymap_add_item(keymap, "SKETCH_OT_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SKETCH_OT_finish_stroke", SELECTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SKETCH_OT_cancel_stroke", ESCKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SKETCH_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
+
+ /* Pose ------------------------ */
+ /* only set in posemode, by space_view3d listener */
+ keymap= WM_keymap_listbase(wm, "Pose", 0, 0);
+
+ WM_keymap_add_item(keymap, "POSE_OT_hide", HKEY, KM_PRESS, 0, 0);
+ kmi= WM_keymap_add_item(keymap, "POSE_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "unselected", 1);
+ WM_keymap_add_item(keymap, "POSE_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
+ /*clear pose*/
+ WM_keymap_add_item(keymap, "POSE_OT_rot_clear", RKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "POSE_OT_loc_clear", GKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "POSE_OT_scale_clear", SKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "POSE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "POSE_OT_select_invert", IKEY, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "POSE_OT_select_parent", PKEY, KM_PRESS, KM_SHIFT, 0);
+
+ kmi= WM_keymap_add_item(keymap, "POSE_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_PARENT);
+ RNA_boolean_set(kmi->ptr, "extend", 0);
+ kmi= WM_keymap_add_item(keymap, "POSE_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_PARENT);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+
+ kmi= WM_keymap_add_item(keymap, "POSE_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD);
+ RNA_boolean_set(kmi->ptr, "extend", 0);
+ kmi= WM_keymap_add_item(keymap, "POSE_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+
+ WM_keymap_add_item(keymap, "POSE_OT_select_linked", LKEY, KM_PRESS, 0, 0);
+
+ // XXX this should probably be in screen instead... here for testing purposes in the meantime... - Aligorith
+ WM_keymap_verify_item(keymap, "ANIM_OT_insert_keyframe_menu", IKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "ANIM_OT_delete_keyframe_old", IKEY, KM_PRESS, KM_ALT, 0);
+
+ /* Pose -> PoseLib ------------- */
+ /* only set in posemode, by space_view3d listener */
+ WM_keymap_add_item(keymap, "POSELIB_OT_browse_interactive", LKEY, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "POSELIB_OT_pose_add", LKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "POSELIB_OT_pose_remove", LKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "POSELIB_OT_pose_rename", LKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
+}
+
diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c
new file mode 100644
index 00000000000..80f51f3797c
--- /dev/null
+++ b/source/blender/editors/armature/editarmature.c
@@ -0,0 +1,5675 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2002-2009 full recode.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_ID.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_nla_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_curve_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_ghash.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_constraint.h"
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
+#include "BKE_subsurf.h"
+#include "BKE_utildefines.h"
+#include "BKE_modifier.h"
+#include "PIL_time.h"
+
+#include "BIF_gl.h"
+#include "BIF_transform.h"
+#include "BIF_generate.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_armature.h"
+#include "ED_mesh.h"
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+#include "ED_view3d.h"
+
+#include "UI_interface.h"
+
+#include "armature_intern.h"
+#include "meshlaplacian.h"
+
+#if 0
+#include "reeb.h"
+#endif
+
+/* ************* XXX *************** */
+static int okee() {return 0;}
+static int pupmenu() {return 0;}
+static void waitcursor() {};
+static void error() {};
+static void error_libdata() {}
+static void BIF_undo_push() {}
+static void adduplicate() {}
+/* ************* XXX *************** */
+
+/* **************** tools on Editmode Armature **************** */
+
+/* Sync selection to parent for connected children */
+static void armature_sync_selection(ListBase *edbo)
+{
+ EditBone *ebo;
+
+ for (ebo=edbo->first; ebo; ebo= ebo->next) {
+ if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) {
+ if (ebo->parent->flag & BONE_TIPSEL)
+ ebo->flag |= BONE_ROOTSEL;
+ else
+ ebo->flag &= ~BONE_ROOTSEL;
+ }
+
+ if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL))
+ ebo->flag |= BONE_SELECTED;
+ else
+ ebo->flag &= ~BONE_SELECTED;
+ }
+}
+
+/* converts Bones to EditBone list, used for tools as well */
+void make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent)
+{
+ EditBone *eBone;
+ Bone *curBone;
+ float delta[3];
+ float premat[3][3];
+ float postmat[3][3];
+ float imat[3][3];
+ float difmat[3][3];
+
+ 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;
+ BLI_strncpy(eBone->name, curBone->name, 32);
+ eBone->flag = curBone->flag;
+
+ /* fix selection flags */
+ if (eBone->flag & BONE_SELECTED) {
+ eBone->flag |= BONE_TIPSEL;
+ if (eBone->parent && (eBone->flag & BONE_CONNECTED))
+ eBone->parent->flag |= BONE_TIPSEL;
+ else
+ eBone->flag |= BONE_ROOTSEL;
+ }
+ else
+ eBone->flag &= ~BONE_ROOTSEL;
+
+ VECCOPY(eBone->head, curBone->arm_head);
+ VECCOPY(eBone->tail, curBone->arm_tail);
+
+ eBone->roll= 0.0f;
+
+ /* roll fixing */
+ VecSubf(delta, eBone->tail, eBone->head);
+ vec_roll_to_mat3(delta, 0.0f, postmat);
+
+ Mat3CpyMat4(premat, curBone->arm_mat);
+
+ Mat3Inv(imat, postmat);
+ Mat3MulMat3(difmat, imat, premat);
+
+ eBone->roll = (float)atan2(difmat[2][0], difmat[2][2]);
+
+ /* rest of stuff copy */
+ eBone->length= curBone->length;
+ eBone->dist= curBone->dist;
+ eBone->weight= curBone->weight;
+ eBone->xwidth= curBone->xwidth;
+ eBone->zwidth= curBone->zwidth;
+ eBone->ease1= curBone->ease1;
+ eBone->ease2= curBone->ease2;
+ eBone->rad_head= curBone->rad_head;
+ eBone->rad_tail= curBone->rad_tail;
+ eBone->segments = curBone->segments;
+ eBone->layer = curBone->layer;
+
+ BLI_addtail(edbo, eBone);
+
+ /* Add children if necessary */
+ if (curBone->childbase.first)
+ make_boneList(edbo, &curBone->childbase, eBone);
+ }
+}
+
+/* nasty stuff for converting roll in editbones into bones */
+/* also sets restposition in armature (arm_mat) */
+static void fix_bonelist_roll (ListBase *bonelist, ListBase *editbonelist)
+{
+ Bone *curBone;
+ EditBone *ebone;
+ float premat[3][3];
+ float postmat[3][3];
+ float difmat[3][3];
+ float imat[3][3];
+ float delta[3];
+
+ for (curBone=bonelist->first; curBone; curBone=curBone->next) {
+ /* sets local matrix and arm_mat (restpos) */
+ where_is_armature_bone(curBone, curBone->parent);
+
+ /* Find the associated editbone */
+ for (ebone = editbonelist->first; ebone; ebone=ebone->next)
+ if ((Bone*)ebone->temp == curBone)
+ break;
+
+ if (ebone) {
+ /* Get the ebone premat */
+ VecSubf(delta, ebone->tail, ebone->head);
+ vec_roll_to_mat3(delta, ebone->roll, premat);
+
+ /* Get the bone postmat */
+ Mat3CpyMat4(postmat, curBone->arm_mat);
+
+ Mat3Inv(imat, premat);
+ Mat3MulMat3(difmat, imat, postmat);
+#if 0
+ printf ("Bone %s\n", curBone->name);
+ printmatrix4("premat", premat);
+ printmatrix4("postmat", postmat);
+ printmatrix4("difmat", difmat);
+ printf ("Roll = %f\n", (-atan2(difmat[2][0], difmat[2][2]) * (180.0/M_PI)));
+#endif
+ curBone->roll = (float)-atan2(difmat[2][0], difmat[2][2]);
+
+ /* and set restposition again */
+ where_is_armature_bone(curBone, curBone->parent);
+ }
+ fix_bonelist_roll(&curBone->childbase, editbonelist);
+ }
+}
+
+/* put EditMode back in Object */
+void ED_armature_from_edit(Scene *scene, Object *obedit)
+{
+ bArmature *arm= obedit->data;
+ EditBone *eBone, *neBone;
+ Bone *newBone;
+ Object *obt;
+
+ /* armature bones */
+ free_bones(arm);
+
+ /* remove zero sized bones, this gives instable restposes */
+ for (eBone=arm->edbo->first; eBone; eBone= neBone) {
+ float len= VecLenf(eBone->head, eBone->tail);
+ neBone= eBone->next;
+ if (len <= 0.000001f) { /* FLT_EPSILON is too large? */
+ EditBone *fBone;
+
+ /* Find any bones that refer to this bone */
+ for (fBone=arm->edbo->first; fBone; fBone= fBone->next) {
+ if (fBone->parent==eBone)
+ fBone->parent= eBone->parent;
+ }
+ printf("Warning: removed zero sized bone: %s\n", eBone->name);
+ BLI_freelinkN(arm->edbo, eBone);
+ }
+ }
+
+ /* Copy the bones from the editData into the armature */
+ for (eBone=arm->edbo->first; eBone; eBone=eBone->next) {
+ newBone= MEM_callocN(sizeof(Bone), "bone");
+ eBone->temp= newBone; /* Associate the real Bones with the EditBones */
+
+ BLI_strncpy(newBone->name, eBone->name, 32);
+ memcpy(newBone->head, eBone->head, sizeof(float)*3);
+ memcpy(newBone->tail, eBone->tail, sizeof(float)*3);
+ newBone->flag= eBone->flag;
+ if (eBone->flag & BONE_ACTIVE)
+ newBone->flag |= BONE_SELECTED; /* important, editbones can be active with only 1 point selected */
+ newBone->roll = 0.0f;
+
+ newBone->weight = eBone->weight;
+ newBone->dist = eBone->dist;
+
+ newBone->xwidth = eBone->xwidth;
+ newBone->zwidth = eBone->zwidth;
+ newBone->ease1= eBone->ease1;
+ newBone->ease2= eBone->ease2;
+ newBone->rad_head= eBone->rad_head;
+ newBone->rad_tail= eBone->rad_tail;
+ newBone->segments= eBone->segments;
+ newBone->layer = eBone->layer;
+ }
+
+ /* Fix parenting in a separate pass to ensure ebone->bone connections
+ are valid at this point */
+ for (eBone=arm->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[3][3];
+ float M_parentRest[3][3];
+ float iM_parentRest[3][3];
+ float delta[3];
+
+ /* Get the parent's matrix (rotation only) */
+ VecSubf(delta, eBone->parent->tail, eBone->parent->head);
+ vec_roll_to_mat3(delta, eBone->parent->roll, M_parentRest);
+
+ /* Get this bone's matrix (rotation only) */
+ VecSubf(delta, eBone->tail, eBone->head);
+ vec_roll_to_mat3(delta, eBone->roll, M_boneRest);
+
+ /* Invert the parent matrix */
+ Mat3Inv(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);
+
+ Mat3MulVecfl(iM_parentRest, newBone->head);
+ Mat3MulVecfl(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 */
+ /* also builds restposition again (like where_is_armature) */
+ fix_bonelist_roll(&arm->bonebase, arm->edbo);
+
+ /* so all users of this armature should get rebuilt */
+ for (obt= G.main->object.first; obt; obt= obt->id.next) {
+ if (obt->data==arm)
+ armature_rebuild_pose(obt, arm);
+ }
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+}
+
+
+
+void apply_rot_armature (Scene *scene, Object *ob, float mat[3][3])
+{
+ EditBone *ebone;
+ bArmature *arm= ob->data;
+ float scale = Mat3ToScalef(mat); /* store the scale of the matrix here to use on envelopes */
+
+ /* Put the armature into editmode */
+ ED_armature_to_edit(ob);
+
+ /* Do the rotations */
+ for (ebone = arm->edbo->first; ebone; ebone=ebone->next){
+ Mat3MulVecfl(mat, ebone->head);
+ Mat3MulVecfl(mat, ebone->tail);
+
+ ebone->rad_head *= scale;
+ ebone->rad_tail *= scale;
+ ebone->dist *= scale;
+ }
+
+ /* Turn the list into an armature */
+ ED_armature_from_edit(scene, ob);
+ ED_armature_edit_free(ob);
+}
+
+/* 0 == do center, 1 == center new, 2 == center cursor */
+void docenter_armature (Scene *scene, View3D *v3d, Object *ob, int centermode)
+{
+ Object *obedit= scene->obedit; // XXX get from context
+ EditBone *ebone;
+ bArmature *arm= ob->data;
+ float cent[3] = {0.0f, 0.0f, 0.0f};
+ float min[3], max[3];
+ float omat[3][3];
+
+ /* Put the armature into editmode */
+ if(ob!=obedit)
+ ED_armature_to_edit(ob);
+
+ /* Find the centerpoint */
+ if (centermode == 2) {
+ float *fp= give_cursor(scene, v3d);
+ VECCOPY(cent, fp);
+ Mat4Invert(ob->imat, ob->obmat);
+ Mat4MulVecfl(ob->imat, cent);
+ }
+ else {
+ INIT_MINMAX(min, max);
+
+ for (ebone= arm->edbo->first; ebone; ebone=ebone->next) {
+ DO_MINMAX(ebone->head, min, max);
+ DO_MINMAX(ebone->tail, min, max);
+ }
+
+ cent[0]= (min[0] + max[0]) / 2.0f;
+ cent[1]= (min[1] + max[1]) / 2.0f;
+ cent[2]= (min[2] + max[2]) / 2.0f;
+ }
+
+ /* Do the adjustments */
+ for (ebone= arm->edbo->first; ebone; ebone=ebone->next) {
+ VecSubf(ebone->head, ebone->head, cent);
+ VecSubf(ebone->tail, ebone->tail, cent);
+ }
+
+ /* Turn the list into an armature */
+ ED_armature_from_edit(scene, ob);
+
+ /* Adjust object location for new centerpoint */
+ if(centermode && obedit==NULL) {
+ Mat3CpyMat4(omat, ob->obmat);
+
+ Mat3MulVecfl(omat, cent);
+ ob->loc[0] += cent[0];
+ ob->loc[1] += cent[1];
+ ob->loc[2] += cent[2];
+ }
+ else
+ ED_armature_edit_free(ob);
+}
+
+/* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */
+static void applyarmature_fix_boneparents (Scene *scene, Object *armob)
+{
+ Object workob, *ob;
+
+ /* go through all objects in database */
+ for (ob= G.main->object.first; ob; ob= ob->id.next) {
+ /* if parent is bone in this armature, apply corrections */
+ if ((ob->parent == armob) && (ob->partype == PARBONE)) {
+ /* apply current transform from parent (not yet destroyed),
+ * then calculate new parent inverse matrix
+ */
+ ED_object_apply_obmat(ob);
+
+ what_does_parent(scene, ob, &workob);
+ Mat4Invert(ob->parentinv, workob.obmat);
+ }
+ }
+}
+
+static EditBone *editbone_name_exists (ListBase *edbo, char *name)
+{
+ EditBone *eBone;
+
+ for (eBone=edbo->first; eBone; eBone=eBone->next) {
+ if (!strcmp(name, eBone->name))
+ return eBone;
+ }
+ return NULL;
+}
+
+/* note: there's a unique_bone_name() too! */
+void unique_editbone_name (ListBase *edbo, char *name, EditBone *bone)
+{
+ EditBone *dupli;
+ char tempname[64];
+ int number;
+ char *dot;
+
+ dupli = editbone_name_exists(edbo, name);
+
+ if (dupli && bone != dupli) {
+ /* Strip off the suffix, if it's a number */
+ number= strlen(name);
+ if (number && isdigit(name[number-1])) {
+ dot= strrchr(name, '.'); // last occurrance
+ if (dot)
+ *dot=0;
+ }
+
+ for (number = 1; number <= 999; number++) {
+ sprintf(tempname, "%s.%03d", name, number);
+ if (!editbone_name_exists(edbo, tempname)) {
+ BLI_strncpy(name, tempname, 32);
+ return;
+ }
+ }
+ }
+}
+
+/* set the current pose as the restpose */
+void apply_armature_pose2bones(Scene *scene, Object *obedit)
+{
+ bArmature *arm= obedit->data;
+ bPose *pose;
+ bPoseChannel *pchan;
+ EditBone *curbone;
+
+ /* don't check if editmode (should be done by caller) */
+ if (object_data_is_libdata(obedit)) {
+ error_libdata();
+ return;
+ }
+
+ /* helpful warnings... */
+ // TODO: add warnings to be careful about actions, applying deforms first, etc.
+
+ /* Get editbones of active armature to alter */
+ ED_armature_to_edit(obedit);
+
+ /* get pose of active object and move it out of posemode */
+ pose= obedit->pose;
+
+ for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) {
+ curbone= editbone_name_exists(arm->edbo, pchan->name);
+
+ /* simply copy the head/tail values from pchan over to curbone */
+ VECCOPY(curbone->head, pchan->pose_head);
+ VECCOPY(curbone->tail, pchan->pose_tail);
+
+ /* fix roll:
+ * 1. find auto-calculated roll value for this bone now
+ * 2. remove this from the 'visual' y-rotation
+ */
+ {
+ float premat[3][3], imat[3][3],pmat[3][3], tmat[3][3];
+ float delta[3], eul[3];
+
+ /* obtain new auto y-rotation */
+ VecSubf(delta, curbone->tail, curbone->head);
+ vec_roll_to_mat3(delta, 0.0, premat);
+ Mat3Inv(imat, premat);
+
+ /* get pchan 'visual' matrix */
+ Mat3CpyMat4(pmat, pchan->pose_mat);
+
+ /* remove auto from visual and get euler rotation */
+ Mat3MulMat3(tmat, imat, pmat);
+ Mat3ToEul(tmat, eul);
+
+ /* just use this euler-y as new roll value */
+ curbone->roll= eul[1];
+ }
+
+ /* clear transform values for pchan */
+ pchan->loc[0]= pchan->loc[1]= pchan->loc[2]= 0;
+ pchan->quat[1]= pchan->quat[2]= pchan->quat[3]= 0;
+ pchan->quat[0]= pchan->size[0]= pchan->size[1]= pchan->size[2]= 1;
+
+ /* set anim lock */
+ curbone->flag |= BONE_UNKEYED;
+ }
+
+ /* convert editbones back to bones */
+ ED_armature_from_edit(scene, obedit);
+
+ /* flush positions of posebones */
+ where_is_pose(scene, obedit);
+
+ /* fix parenting of objects which are bone-parented */
+ applyarmature_fix_boneparents(scene, obedit);
+
+ BIF_undo_push("Apply new restpose");
+}
+
+
+/* Helper function for armature joining - link fixing */
+static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone)
+{
+ Object *ob;
+ bPose *pose;
+ bPoseChannel *pchant;
+ bConstraint *con;
+
+ /* let's go through all objects in database */
+ for (ob= G.main->object.first; ob; ob= ob->id.next) {
+ /* do some object-type specific things */
+ if (ob->type == OB_ARMATURE) {
+ pose= ob->pose;
+ for (pchant= pose->chanbase.first; pchant; pchant= pchant->next) {
+ for (con= pchant->constraints.first; con; con= con->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ /* constraint targets */
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ if (ct->tar == srcArm) {
+ if (strcmp(ct->subtarget, "")==0) {
+ ct->tar = tarArm;
+ }
+ else if (strcmp(ct->subtarget, pchan->name)==0) {
+ ct->tar = tarArm;
+ strcpy(ct->subtarget, curbone->name);
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+
+ /* action constraint? */
+ if (con->type == CONSTRAINT_TYPE_ACTION) {
+ bActionConstraint *data= con->data; // XXX old animation system
+ bAction *act;
+ bActionChannel *achan;
+
+ if (data->act) {
+ act= data->act;
+
+ for (achan= act->chanbase.first; achan; achan= achan->next) {
+ if (strcmp(achan->name, pchan->name)==0)
+ BLI_strncpy(achan->name, curbone->name, 32);
+ }
+ }
+ }
+
+ }
+ }
+ }
+
+ /* fix object-level constraints */
+ if (ob != srcArm) {
+ for (con= ob->constraints.first; con; con= con->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ /* constraint targets */
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ if (ct->tar == srcArm) {
+ if (strcmp(ct->subtarget, "")==0) {
+ ct->tar = tarArm;
+ }
+ else if (strcmp(ct->subtarget, pchan->name)==0) {
+ ct->tar = tarArm;
+ strcpy(ct->subtarget, curbone->name);
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+ }
+ }
+
+ /* See if an object is parented to this armature */
+ if (ob->parent && (ob->parent == srcArm)) {
+ /* Is object parented to a bone of this src armature? */
+ if (ob->partype==PARBONE) {
+ /* bone name in object */
+ if (!strcmp(ob->parsubstr, pchan->name))
+ BLI_strncpy(ob->parsubstr, curbone->name, 32);
+ }
+
+ /* make tar armature be new parent */
+ ob->parent = tarArm;
+ }
+ }
+}
+
+int join_armature(Scene *scene, View3D *v3d)
+{
+ Object *ob= scene->basact->object; // XXX context
+ bArmature *arm= ob->data;
+ Base *base, *nextbase;
+ bPose *pose, *opose;
+ bPoseChannel *pchan, *pchann;
+ EditBone *curbone;
+ float mat[4][4], oimat[4][4];
+
+ /* Ensure we're not in editmode and that the active object is an armature*/
+ if (ob->type!=OB_ARMATURE) return 0;
+ if (arm->edbo) return 0;
+
+ if (object_data_is_libdata(ob)) {
+ error_libdata();
+ return 0;
+ }
+
+ /* Get editbones of active armature to add editbones to */
+ ED_armature_to_edit(ob);
+
+ /* get pose of active object and move it out of posemode */
+ pose= ob->pose;
+ ob->flag &= ~OB_POSEMODE;
+
+ for (base=FIRSTBASE; base; base=nextbase) {
+ nextbase = base->next;
+ if (TESTBASE(v3d, base)){
+ if ((base->object->type==OB_ARMATURE) && (base->object!=ob)) {
+ bArmature *curarm= base->object->data;
+
+ /* Make a list of editbones in current armature */
+ ED_armature_to_edit(base->object);
+
+ /* Get Pose of current armature */
+ opose= base->object->pose;
+ base->object->flag &= ~OB_POSEMODE;
+ BASACT->flag &= ~OB_POSEMODE;
+
+ /* Find the difference matrix */
+ Mat4Invert(oimat, ob->obmat);
+ Mat4MulMat4(mat, base->object->obmat, oimat);
+
+ /* Copy bones and posechannels from the object to the edit armature */
+ for (pchan=opose->chanbase.first; pchan; pchan=pchann) {
+ pchann= pchan->next;
+ curbone= editbone_name_exists(curarm->edbo, pchan->name);
+
+ /* Get new name */
+ unique_editbone_name(arm->edbo, curbone->name, NULL);
+
+ /* Transform the bone */
+ {
+ float premat[4][4];
+ float postmat[4][4];
+ float difmat[4][4];
+ float imat[4][4];
+ float temp[3][3];
+ float delta[3];
+
+ /* Get the premat */
+ VecSubf(delta, curbone->tail, curbone->head);
+ vec_roll_to_mat3(delta, curbone->roll, temp);
+
+ Mat4MulMat34(premat, temp, mat);
+
+ Mat4MulVecfl(mat, curbone->head);
+ Mat4MulVecfl(mat, curbone->tail);
+
+ /* Get the postmat */
+ VecSubf(delta, curbone->tail, curbone->head);
+ vec_roll_to_mat3(delta, curbone->roll, temp);
+ Mat4CpyMat3(postmat, temp);
+
+ /* Find the roll */
+ Mat4Invert(imat, premat);
+ Mat4MulMat4(difmat, postmat, imat);
+
+ curbone->roll -= (float)atan2(difmat[2][0], difmat[2][2]);
+ }
+
+ /* Fix Constraints and Other Links to this Bone and Armature */
+ joined_armature_fix_links(ob, base->object, pchan, curbone);
+
+ /* Rename pchan */
+ BLI_strncpy(pchan->name, curbone->name, sizeof(pchan->name));
+
+ /* Jump Ship! */
+ BLI_remlink(curarm->edbo, curbone);
+ BLI_addtail(arm->edbo, curbone);
+
+ BLI_remlink(&opose->chanbase, pchan);
+ BLI_addtail(&pose->chanbase, pchan);
+ }
+
+ ED_base_object_free_and_unlink(scene, base);
+ }
+ }
+ }
+
+ DAG_scene_sort(scene); // because we removed object(s)
+
+ ED_armature_from_edit(scene, ob);
+ ED_armature_edit_free(ob);
+
+ return 1;
+}
+
+/* Helper function for armature separating - link fixing */
+static void separated_armature_fix_links(Object *origArm, Object *newArm)
+{
+ Object *ob;
+ bPoseChannel *pchan, *pcha, *pchb;
+ bConstraint *con;
+ ListBase *opchans, *npchans;
+
+ /* get reference to list of bones in original and new armatures */
+ opchans= &origArm->pose->chanbase;
+ npchans= &newArm->pose->chanbase;
+
+ /* let's go through all objects in database */
+ for (ob= G.main->object.first; ob; ob= ob->id.next) {
+ /* do some object-type specific things */
+ if (ob->type == OB_ARMATURE) {
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ for (con= pchan->constraints.first; con; con= con->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ /* constraint targets */
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ /* any targets which point to original armature are redirected to the new one only if:
+ * - the target isn't origArm/newArm itself
+ * - the target is one that can be found in newArm/origArm
+ */
+ if ((ct->tar == origArm) && (ct->subtarget[0] != 0)) {
+ for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
+ /* check if either one matches */
+ if ( (strcmp(pcha->name, ct->subtarget)==0) ||
+ (strcmp(pchb->name, ct->subtarget)==0) )
+ {
+ ct->tar= newArm;
+ break;
+ }
+
+ /* check if both ends have met (to stop checking) */
+ if (pcha == pchb) break;
+ }
+ }
+ else if ((ct->tar == newArm) && (ct->subtarget[0] != 0)) {
+ for (pcha=opchans->first, pchb=opchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
+ /* check if either one matches */
+ if ( (strcmp(pcha->name, ct->subtarget)==0) ||
+ (strcmp(pchb->name, ct->subtarget)==0) )
+ {
+ ct->tar= origArm;
+ break;
+ }
+
+ /* check if both ends have met (to stop checking) */
+ if (pcha == pchb) break;
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+ }
+ }
+ }
+
+ /* fix object-level constraints */
+ if (ob != origArm) {
+ for (con= ob->constraints.first; con; con= con->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ /* constraint targets */
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ /* any targets which point to original armature are redirected to the new one only if:
+ * - the target isn't origArm/newArm itself
+ * - the target is one that can be found in newArm/origArm
+ */
+ if ((ct->tar == origArm) && (ct->subtarget[0] != 0)) {
+ for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
+ /* check if either one matches */
+ if ( (strcmp(pcha->name, ct->subtarget)==0) ||
+ (strcmp(pchb->name, ct->subtarget)==0) )
+ {
+ ct->tar= newArm;
+ break;
+ }
+
+ /* check if both ends have met (to stop checking) */
+ if (pcha == pchb) break;
+ }
+ }
+ else if ((ct->tar == newArm) && (ct->subtarget[0] != 0)) {
+ for (pcha=opchans->first, pchb=opchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
+ /* check if either one matches */
+ if ( (strcmp(pcha->name, ct->subtarget)==0) ||
+ (strcmp(pchb->name, ct->subtarget)==0) )
+ {
+ ct->tar= origArm;
+ break;
+ }
+
+ /* check if both ends have met (to stop checking) */
+ if (pcha == pchb) break;
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+ }
+ }
+
+ /* See if an object is parented to this armature */
+ if ((ob->parent) && (ob->parent == origArm)) {
+ /* Is object parented to a bone of this src armature? */
+ if (ob->partype==PARBONE) {
+ /* bone name in object */
+ for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
+ /* check if either one matches */
+ if ( (strcmp(pcha->name, ob->parsubstr)==0) ||
+ (strcmp(pchb->name, ob->parsubstr)==0) )
+ {
+ ob->parent= newArm;
+ break;
+ }
+
+ /* check if both ends have met (to stop checking) */
+ if (pcha == pchb) break;
+ }
+ }
+ }
+ }
+}
+
+/* Helper function for armature separating - remove certain bones from the given armature
+ * sel: remove selected bones from the armature, otherwise the unselected bones are removed
+ * (ob is not in editmode)
+ */
+static void separate_armature_bones (Scene *scene, Object *ob, short sel)
+{
+ bArmature *arm= (bArmature *)ob->data;
+ bPoseChannel *pchan, *pchann;
+ EditBone *curbone;
+
+ /* make local set of editbones to manipulate here */
+ ED_armature_to_edit(ob);
+
+ /* go through pose-channels, checking if a bone should be removed */
+ for (pchan=ob->pose->chanbase.first; pchan; pchan=pchann) {
+ pchann= pchan->next;
+ curbone= editbone_name_exists(arm->edbo, pchan->name);
+
+ /* check if bone needs to be removed */
+ if ( (sel && (curbone->flag & BONE_SELECTED)) ||
+ (!sel && !(curbone->flag & BONE_SELECTED)) )
+ {
+ EditBone *ebo;
+ bPoseChannel *pchn;
+
+ /* clear the bone->parent var of any bone that had this as its parent */
+ for (ebo= arm->edbo->first; ebo; ebo= ebo->next) {
+ if (ebo->parent == curbone) {
+ ebo->parent= NULL;
+ ebo->temp= NULL; /* this is needed to prevent random crashes with in ED_armature_from_edit */
+ ebo->flag &= ~BONE_CONNECTED;
+ }
+ }
+
+ /* clear the pchan->parent var of any pchan that had this as its parent */
+ for (pchn= ob->pose->chanbase.first; pchn; pchn=pchn->next) {
+ if (pchn->parent == pchan)
+ pchn->parent= NULL;
+ }
+
+ /* free any of the extra-data this pchan might have */
+ if (pchan->path) MEM_freeN(pchan->path);
+ free_constraints(&pchan->constraints);
+
+ /* get rid of unneeded bone */
+ BLI_freelinkN(arm->edbo, curbone);
+ BLI_freelinkN(&ob->pose->chanbase, pchan);
+ }
+ }
+
+ /* exit editmode (recalculates pchans too) */
+ ED_armature_from_edit(scene, ob);
+ ED_armature_edit_free(ob);
+}
+
+/* separate selected bones into their armature */
+void separate_armature (Scene *scene, View3D *v3d)
+{
+ Object *obedit= scene->obedit; // XXX get from context
+ Object *oldob, *newob;
+ Base *base, *oldbase, *newbase;
+ bArmature *arm;
+
+ if ( okee("Separate")==0 ) return;
+
+ waitcursor(1);
+
+ arm= obedit->data;
+
+ /* we are going to do this as follows (unlike every other instance of separate):
+ * 1. exit editmode +posemode for active armature/base. Take note of what this is.
+ * 2. duplicate base - BASACT is the new one now
+ * 3. for each of the two armatures, enter editmode -> remove appropriate bones -> exit editmode + recalc
+ * 4. fix constraint links
+ * 5. make original armature active and enter editmode
+ */
+
+ /* 1) only edit-base selected */
+ base= FIRSTBASE;
+ for (base= FIRSTBASE; base; base= base->next) {
+ if (base->lay & v3d->lay) {
+ if (base->object==obedit) base->flag |= 1;
+ else base->flag &= ~1;
+ }
+ }
+
+ /* 1) store starting settings and exit editmode */
+ oldob= obedit;
+ oldbase= BASACT;
+ oldob->flag &= ~OB_POSEMODE;
+ oldbase->flag &= ~OB_POSEMODE;
+
+ ED_armature_from_edit(scene, obedit);
+ ED_armature_edit_free(obedit);
+
+ /* 2) duplicate base */
+ adduplicate(1, USER_DUP_ARM); /* no transform and zero so do get a linked dupli */
+
+ newbase= BASACT; /* basact is set in adduplicate() */
+ newob= newbase->object;
+ newbase->flag &= ~SELECT;
+
+
+ /* 3) remove bones that shouldn't still be around on both armatures */
+ separate_armature_bones(scene, oldob, 1);
+ separate_armature_bones(scene, newob, 0);
+
+
+ /* 4) fix links before depsgraph flushes */ // err... or after?
+ separated_armature_fix_links(oldob, newob);
+
+ DAG_object_flush_update(scene, oldob, OB_RECALC_DATA); /* this is the original one */
+ DAG_object_flush_update(scene, newob, OB_RECALC_DATA); /* this is the separated one */
+
+
+ /* 5) restore original conditions */
+ obedit= oldob;
+ BASACT= oldbase;
+ BASACT->flag |= SELECT;
+
+ ED_armature_to_edit(obedit);
+
+ /* recalc/redraw + cleanup */
+ waitcursor(0);
+
+ BIF_undo_push("Separate Armature");
+}
+
+/* **************** END tools on Editmode Armature **************** */
+/* **************** PoseMode & EditMode *************************** */
+
+/* only for opengl selection indices */
+Bone *get_indexed_bone (Object *ob, int index)
+{
+ bPoseChannel *pchan;
+ int a= 0;
+
+ if(ob->pose==NULL) return NULL;
+ index>>=16; // bone selection codes use left 2 bytes
+
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next, a++) {
+ if(a==index) return pchan->bone;
+ }
+ return NULL;
+}
+
+/* See if there are any selected bones in this buffer */
+/* only bones from base are checked on */
+static void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short findunsel)
+{
+ Object *obedit= scene->obedit; // XXX get from context
+ Bone *bone;
+ EditBone *ebone;
+ void *firstunSel=NULL, *firstSel=NULL, *data;
+ unsigned int hitresult;
+ short i, takeNext=0, sel;
+
+ for (i=0; i< hits; i++){
+ hitresult = buffer[3+(i*4)];
+
+ if (!(hitresult & BONESEL_NOSEL)) { // -1
+ if(hitresult & BONESEL_ANY) { // to avoid including objects in selection
+
+ hitresult &= ~(BONESEL_ANY);
+ /* Determine what the current bone is */
+ if (obedit==NULL || base->object!=obedit) {
+ /* no singular posemode, so check for correct object */
+ if(base->selcol == (hitresult & 0xFFFF)) {
+ bone = get_indexed_bone(base->object, hitresult);
+
+ if (findunsel)
+ sel = (bone->flag & BONE_SELECTED);
+ else
+ sel = !(bone->flag & BONE_SELECTED);
+
+ data = bone;
+ }
+ else {
+ data= NULL;
+ sel= 0;
+ }
+ }
+ else{
+ bArmature *arm= obedit->data;
+
+ ebone = BLI_findlink(arm->edbo, hitresult);
+ if (findunsel)
+ sel = (ebone->flag & BONE_SELECTED);
+ else
+ sel = !(ebone->flag & BONE_SELECTED);
+
+ data = ebone;
+ }
+
+ if(data) {
+ if (sel) {
+ if(!firstSel) firstSel= data;
+ takeNext=1;
+ }
+ else {
+ if (!firstunSel)
+ firstunSel=data;
+ if (takeNext)
+ return data;
+ }
+ }
+ }
+ }
+ }
+
+ if (firstunSel)
+ return firstunSel;
+ else
+ return firstSel;
+}
+
+
+
+/* used by posemode as well editmode */
+/* only checks scene->basact! */
+/* x and y are mouse coords (area space) */
+static void *get_nearest_bone (bContext *C, short findunsel, int x, int y)
+{
+ ViewContext vc;
+ rcti rect;
+ unsigned int buffer[MAXPICKBUF];
+ short hits;
+
+ view3d_set_viewcontext(C, &vc);
+
+ // rect.xmin= ... mouseco!
+ rect.xmin= rect.xmax= x;
+ rect.ymin= rect.ymax= y;
+
+ glInitNames();
+ hits= view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
+
+ if (hits>0)
+ return get_bone_from_selectbuffer(vc.scene, vc.scene->basact, buffer, hits, findunsel);
+
+ return NULL;
+}
+
+/* helper for setflag_sel_bone() */
+static void bone_setflag (int *bone, int flag, short mode)
+{
+ if (bone && flag) {
+ /* exception for inverse flags */
+ if (flag == BONE_NO_DEFORM) {
+ if (mode == 2)
+ *bone |= flag;
+ else if (mode == 1)
+ *bone &= ~flag;
+ else
+ *bone ^= flag;
+ }
+ else {
+ if (mode == 2)
+ *bone &= ~flag;
+ else if (mode == 1)
+ *bone |= flag;
+ else
+ *bone ^= flag;
+ }
+ }
+}
+
+/* Get the first available child of an editbone */
+static EditBone *editbone_get_child(bArmature *arm, EditBone *pabone, short use_visibility)
+{
+ EditBone *curbone, *chbone=NULL;
+
+ for (curbone= arm->edbo->first; curbone; curbone= curbone->next) {
+ if (curbone->parent == pabone) {
+ if (use_visibility) {
+ if ((arm->layer & curbone->layer) && !(pabone->flag & BONE_HIDDEN_A))
+ chbone = curbone;
+ }
+ else
+ chbone = curbone;
+ }
+ }
+
+ return chbone;
+}
+
+
+/* used by posemode and editmode */
+void setflag_armature (Scene *scene, short mode)
+{
+ Object *obedit= scene->obedit; // XXX get from context
+ Object *ob;
+ bArmature *arm;
+ int flag;
+
+ /* get data */
+ if (obedit)
+ ob= obedit;
+ else if (OBACT)
+ ob= OBACT;
+ else
+ return;
+ arm= (bArmature *)ob->data;
+
+ /* get flag to set (sync these with the ones used in eBone_Flag */
+ if (mode == 2)
+ flag= pupmenu("Disable Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5|Locked%x6");
+ else if (mode == 1)
+ flag= pupmenu("Enable Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5|Locked%x6");
+ else
+ flag= pupmenu("Toggle Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5|Locked%x6");
+ switch (flag) {
+ case 1: flag = BONE_DRAWWIRE; break;
+ case 2: flag = BONE_NO_DEFORM; break;
+ case 3: flag = BONE_MULT_VG_ENV; break;
+ case 4: flag = BONE_HINGE; break;
+ case 5: flag = BONE_NO_SCALE; break;
+ case 6: flag = BONE_EDITMODE_LOCKED; break;
+ default: return;
+ }
+
+ /* determine which mode armature is in */
+ if ((!obedit) && (ob->flag & OB_POSEMODE)) {
+ /* deal with pose channels */
+ bPoseChannel *pchan;
+
+ /* set setting */
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
+ if (pchan->bone->flag & BONE_SELECTED) {
+ bone_setflag(&pchan->bone->flag, flag, mode);
+ }
+ }
+ }
+ }
+ else if (obedit) {
+ /* deal with editbones */
+ EditBone *curbone;
+
+ /* set setting */
+ for (curbone= arm->edbo->first; curbone; curbone= curbone->next) {
+ if (arm->layer & curbone->layer) {
+ if (curbone->flag & BONE_SELECTED) {
+ bone_setflag(&curbone->flag, flag, mode);
+ }
+ }
+ }
+ }
+
+ BIF_undo_push("Change Bone Setting");
+}
+
+/* **************** END PoseMode & EditMode *************************** */
+/* **************** Posemode stuff ********************** */
+
+
+static void selectconnected_posebonechildren (Object *ob, Bone *bone)
+{
+ Bone *curBone;
+ int shift= 0; // XXX
+
+ if (!(bone->flag & BONE_CONNECTED))
+ return;
+
+ // XXX old cruft! use notifiers instead
+ //select_actionchannel_by_name (ob->action, bone->name, !(shift));
+
+ if (shift)
+ bone->flag &= ~BONE_SELECTED;
+ else
+ bone->flag |= BONE_SELECTED;
+
+ for (curBone=bone->childbase.first; curBone; curBone=curBone->next){
+ selectconnected_posebonechildren (ob, curBone);
+ }
+}
+
+/* within active object context */
+/* previously known as "selectconnected_posearmature" */
+static int pose_select_connected_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Bone *bone, *curBone, *next= NULL;
+ int shift= 0; // XXX in pose mode, Shift+L is bound to another command
+ // named "PoseLib Add Current Pose"
+ int x, y;
+ ARegion *ar;
+ Object *ob= CTX_data_edit_object(C);
+ ar= CTX_wm_region(C);
+
+ x= event->x - ar->winrct.xmin;
+ y= event->y - ar->winrct.ymin;
+
+ view3d_operator_needs_opengl(C);
+
+ if (shift)
+ bone= get_nearest_bone(C, 0, x, y);
+ else
+ bone= get_nearest_bone(C, 1, x, y);
+
+ if (!bone)
+ return OPERATOR_CANCELLED;
+
+ /* Select parents */
+ for (curBone=bone; curBone; curBone=next){
+ // XXX old cruft! use notifiers instead
+ //select_actionchannel_by_name (ob->action, curBone->name, !(shift));
+ if (shift)
+ curBone->flag &= ~BONE_SELECTED;
+ else
+ curBone->flag |= BONE_SELECTED;
+
+ if (curBone->flag & BONE_CONNECTED)
+ next=curBone->parent;
+ else
+ next=NULL;
+ }
+
+ /* Select children */
+ for (curBone=bone->childbase.first; curBone; curBone=next){
+ selectconnected_posebonechildren (ob, curBone);
+ }
+
+ // XXX this only counted the number of pose channels selected
+ //countall(); // flushes selection!
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Connected";
+ ot->idname= "POSE_OT_select_linked";
+
+ /* api callbacks */
+ ot->exec= NULL;
+ ot->invoke= pose_select_connected_invoke;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+}
+
+/* **************** END Posemode stuff ********************** */
+/* **************** EditMode stuff ********************** */
+
+/* called in space.c */
+/* previously "selectconnected_armature" */
+static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ bArmature *arm;
+ EditBone *bone, *curBone, *next;
+ int shift= 0; // XXX
+ int x, y;
+ ARegion *ar;
+ Object *obedit= CTX_data_edit_object(C);
+ arm= obedit->data;
+ ar= CTX_wm_region(C);
+
+ x= event->x - ar->winrct.xmin;
+ y= event->y - ar->winrct.ymin;
+
+ view3d_operator_needs_opengl(C);
+
+ if (shift)
+ bone= get_nearest_bone(C, 0, x, y);
+ else
+ bone= get_nearest_bone(C, 1, x, y);
+
+ if (!bone)
+ return OPERATOR_CANCELLED;
+
+ /* Select parents */
+ for (curBone=bone; curBone; curBone=next){
+ if (shift){
+ curBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+ }
+ else{
+ curBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+ }
+
+ if (curBone->flag & BONE_CONNECTED)
+ next=curBone->parent;
+ else
+ next=NULL;
+ }
+
+ /* Select children */
+ while (bone){
+ for (curBone=arm->edbo->first; curBone; curBone=next){
+ next = curBone->next;
+ if (curBone->parent == bone){
+ if (curBone->flag & BONE_CONNECTED){
+ if (shift)
+ 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;
+
+ }
+
+ armature_sync_selection(arm->edbo);
+
+ /* BIF_undo_push("Select connected"); */
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Connected";
+ ot->idname= "ARMATURE_OT_select_linked";
+
+ /* api callbacks */
+ ot->exec= NULL;
+ ot->invoke= armature_select_linked_invoke;
+ ot->poll= ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+}
+
+/* does bones and points */
+/* note that BONE ROOT only gets drawn for root bones (or without IK) */
+static EditBone *get_nearest_editbonepoint (ViewContext *vc, short mval[2], ListBase *edbo, int findunsel, int *selmask)
+{
+ EditBone *ebone;
+ rcti rect;
+ unsigned int buffer[MAXPICKBUF];
+ unsigned int hitresult, besthitresult=BONESEL_NOSEL;
+ int i, mindep= 4;
+ short hits;
+
+ glInitNames();
+
+ rect.xmin= mval[0]-5;
+ rect.xmax= mval[0]+5;
+ rect.ymin= mval[1]-5;
+ rect.ymax= mval[1]+5;
+
+ hits= view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
+ if(hits==0) {
+ rect.xmin= mval[0]-12;
+ rect.xmax= mval[0]+12;
+ rect.ymin= mval[1]-12;
+ rect.ymax= mval[1]+12;
+ hits= view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
+ }
+ /* See if there are any selected bones in this group */
+ if (hits>0) {
+
+ if(hits==1) {
+ if (!(buffer[3] & BONESEL_NOSEL))
+ besthitresult= buffer[3];
+ }
+ else {
+ for (i=0; i< hits; i++) {
+ hitresult= buffer[3+(i*4)];
+ if (!(hitresult & BONESEL_NOSEL)) {
+ int dep;
+
+ ebone = BLI_findlink(edbo, hitresult & ~BONESEL_ANY);
+
+ /* clicks on bone points get advantage */
+ if( hitresult & (BONESEL_ROOT|BONESEL_TIP)) {
+ /* but also the unselected one */
+ if(findunsel) {
+ if( (hitresult & BONESEL_ROOT) && (ebone->flag & BONE_ROOTSEL)==0)
+ dep= 1;
+ else if( (hitresult & BONESEL_TIP) && (ebone->flag & BONE_TIPSEL)==0)
+ dep= 1;
+ else
+ dep= 2;
+ }
+ else dep= 2;
+ }
+ else {
+ /* bone found */
+ if(findunsel) {
+ if((ebone->flag & BONE_SELECTED)==0)
+ dep= 2;
+ else
+ dep= 3;
+ }
+ else dep= 3;
+ }
+ if(dep < mindep) {
+ mindep= dep;
+ besthitresult= hitresult;
+ }
+ }
+ }
+ }
+
+ if (!(besthitresult & BONESEL_NOSEL)) {
+
+ ebone= BLI_findlink(edbo, besthitresult & ~BONESEL_ANY);
+
+ *selmask = 0;
+ if (besthitresult & BONESEL_ROOT)
+ *selmask |= BONE_ROOTSEL;
+ if (besthitresult & BONESEL_TIP)
+ *selmask |= BONE_TIPSEL;
+ if (besthitresult & BONESEL_BONE)
+ *selmask |= BONE_SELECTED;
+ return ebone;
+ }
+ }
+ *selmask = 0;
+ return NULL;
+}
+
+static void delete_bone(ListBase *edbo, EditBone* exBone)
+{
+ EditBone *curBone;
+
+ /* Find any bones that refer to this bone */
+ for (curBone=edbo->first;curBone;curBone=curBone->next) {
+ if (curBone->parent==exBone) {
+ curBone->parent=exBone->parent;
+ curBone->flag &= ~BONE_CONNECTED;
+ }
+ }
+
+ BLI_freelinkN(edbo, exBone);
+}
+
+/* context: editmode armature */
+EditBone *ED_armature_bone_get_mirrored(ListBase *edbo, EditBone *ebo)
+{
+ EditBone *eboflip= NULL;
+ char name[32];
+
+ if (ebo == NULL)
+ return NULL;
+
+ BLI_strncpy(name, ebo->name, sizeof(name));
+ bone_flip_name(name, 0); // 0 = don't strip off number extensions
+
+ for (eboflip= edbo->first; eboflip; eboflip=eboflip->next) {
+ if (ebo != eboflip) {
+ if (!strcmp (name, eboflip->name))
+ break;
+ }
+ }
+
+ return eboflip;
+}
+
+
+/* previously delete_armature */
+/* only editmode! */
+static int armature_delete_selected_exec(bContext *C, wmOperator *op)
+{
+ bArmature *arm;
+ EditBone *curBone, *next;
+ bConstraint *con;
+ Object *obedit= CTX_data_edit_object(C); // XXX get from context
+ arm = obedit->data;
+
+ /* cancel if nothing selected */
+ if (CTX_DATA_COUNT(C, selected_bones) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* if (okee("Erase selected bone(s)")==0) return; */
+
+ /* Select mirrored bones */
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
+ if (arm->layer & curBone->layer) {
+ if (curBone->flag & BONE_SELECTED) {
+ next = ED_armature_bone_get_mirrored(arm->edbo, curBone);
+ if (next)
+ next->flag |= BONE_SELECTED;
+ }
+ }
+ }
+ }
+
+ /* First erase any associated pose channel */
+ if (obedit->pose) {
+ bPoseChannel *chan, *next;
+ for (chan=obedit->pose->chanbase.first; chan; chan=next) {
+ next= chan->next;
+ curBone = editbone_name_exists(arm->edbo, chan->name);
+
+ if (curBone && (curBone->flag & BONE_SELECTED) && (arm->layer & curBone->layer)) {
+ free_constraints(&chan->constraints);
+ BLI_freelinkN (&obedit->pose->chanbase, chan);
+ }
+ else {
+ for (con= chan->constraints.first; con; con= con->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ if (ct->tar == obedit) {
+ if (ct->subtarget[0]) {
+ curBone = editbone_name_exists(arm->edbo, ct->subtarget);
+ if (curBone && (curBone->flag & BONE_SELECTED) && (arm->layer & curBone->layer)) {
+ con->flag |= CONSTRAINT_DISABLE;
+ ct->subtarget[0]= 0;
+ }
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+ }
+ }
+ }
+ }
+
+
+ for (curBone=arm->edbo->first;curBone;curBone=next) {
+ next=curBone->next;
+ if (arm->layer & curBone->layer) {
+ if (curBone->flag & BONE_SELECTED)
+ delete_bone(arm->edbo, curBone);
+ }
+ }
+
+
+ armature_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete Selected Bone(s)";
+ ot->idname= "ARMATURE_OT_delete";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = armature_delete_selected_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* toggle==0: deselect
+ * toggle==1: swap (based on test)
+ * toggle==2: only active tag
+ * toggle==3: swap (no test)
+ */
+void deselectall_armature(Object *obedit, int toggle, int doundo)
+{
+ bArmature *arm= obedit->data;
+ EditBone *eBone;
+ int sel=1;
+
+ if(toggle==1) {
+ /* Determine if there are any selected bones
+ And therefore whether we are selecting or deselecting */
+ for (eBone=arm->edbo->first;eBone;eBone=eBone->next){
+ // if(arm->layer & eBone->layer) {
+ if (eBone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)){
+ sel=0;
+ break;
+ }
+ // }
+ }
+ }
+ else sel= toggle;
+
+ /* Set the flags */
+ for (eBone=arm->edbo->first;eBone;eBone=eBone->next) {
+ if (sel==3) {
+ /* invert selection of bone */
+ if ((arm->layer & eBone->layer) && (eBone->flag & BONE_HIDDEN_A)==0) {
+ eBone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ eBone->flag &= ~BONE_ACTIVE;
+ }
+ }
+ else if (sel==1) {
+ /* select bone */
+ if(arm->layer & eBone->layer && (eBone->flag & BONE_HIDDEN_A)==0) {
+ eBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ if(eBone->parent)
+ eBone->parent->flag |= (BONE_TIPSEL);
+ }
+ }
+ else if (sel==2) {
+ /* clear active flag */
+ eBone->flag &= ~(BONE_ACTIVE);
+ }
+ else {
+ /* deselect bone */
+ eBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE);
+ }
+ }
+
+ armature_sync_selection(arm->edbo);
+ if (doundo) {
+ if (sel==1) BIF_undo_push("Select All");
+ else BIF_undo_push("Deselect All");
+ }
+}
+
+
+/* context: editmode armature in view3d */
+void mouse_armature(bContext *C, short mval[2], int extend)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ bArmature *arm= obedit->data;
+ ViewContext vc;
+ EditBone *nearBone = NULL, *ebone;
+ int selmask;
+
+ view3d_set_viewcontext(C, &vc);
+
+ BIF_sk_selectStroke(C, mval, extend);
+
+ nearBone= get_nearest_editbonepoint(&vc, mval, arm->edbo, 1, &selmask);
+ if (nearBone) {
+
+ if (!extend)
+ deselectall_armature(obedit, 0, 0);
+
+ /* by definition the non-root connected bones have no root point drawn,
+ so a root selection needs to be delivered to the parent tip */
+
+ if(selmask & BONE_SELECTED) {
+ if(nearBone->parent && (nearBone->flag & BONE_CONNECTED)) {
+ /* click in a chain */
+ if(extend) {
+ /* hold shift inverts this bone's selection */
+ if(nearBone->flag & BONE_SELECTED) {
+ /* deselect this bone */
+ nearBone->flag &= ~(BONE_TIPSEL|BONE_SELECTED);
+ /* only deselect parent tip if it is not selected */
+ if(!(nearBone->parent->flag & BONE_SELECTED))
+ nearBone->parent->flag &= ~BONE_TIPSEL;
+ }
+ else {
+ /* select this bone */
+ nearBone->flag |= BONE_TIPSEL;
+ nearBone->parent->flag |= BONE_TIPSEL;
+ }
+ }
+ else {
+ /* select this bone */
+ nearBone->flag |= BONE_TIPSEL;
+ nearBone->parent->flag |= BONE_TIPSEL;
+ }
+ }
+ else {
+ if(extend) {
+ /* hold shift inverts this bone's selection */
+ if(nearBone->flag & BONE_SELECTED)
+ nearBone->flag &= ~(BONE_TIPSEL|BONE_ROOTSEL);
+ else
+ nearBone->flag |= (BONE_TIPSEL|BONE_ROOTSEL);
+ }
+ else nearBone->flag |= (BONE_TIPSEL|BONE_ROOTSEL);
+ }
+ }
+ else {
+ if (extend && (nearBone->flag & selmask))
+ nearBone->flag &= ~selmask;
+ else
+ nearBone->flag |= selmask;
+ }
+
+ armature_sync_selection(arm->edbo);
+
+ if(nearBone) {
+ /* then now check for active status */
+ for (ebone=arm->edbo->first;ebone;ebone=ebone->next) ebone->flag &= ~BONE_ACTIVE;
+ if(nearBone->flag & BONE_SELECTED) nearBone->flag |= BONE_ACTIVE;
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
+ }
+}
+
+void ED_armature_edit_free(struct Object *ob)
+{
+ bArmature *arm= ob->data;
+
+ /* Clear the editbones list */
+ if (arm->edbo) {
+ if (arm->edbo->first)
+ BLI_freelistN(arm->edbo);
+ MEM_freeN(arm->edbo);
+ arm->edbo= NULL;
+ }
+}
+
+void ED_armature_edit_remake(Object *obedit)
+{
+ if(okee("Reload original data")==0) return;
+
+ ED_armature_to_edit(obedit);
+
+// BIF_undo_push("Delete bone");
+}
+
+/* Put armature in EditMode */
+void ED_armature_to_edit(Object *ob)
+{
+ bArmature *arm= ob->data;
+
+ ED_armature_edit_free(ob);
+ arm->edbo= MEM_callocN(sizeof(ListBase), "edbo armature");
+ make_boneList(arm->edbo, &arm->bonebase,NULL);
+
+// BIF_freeTemplates(); /* force template update when entering editmode */
+}
+
+
+/* adjust bone roll to align Z axis with vector
+ * vec is in local space and is normalized
+ */
+float ED_rollBoneToVector(EditBone *bone, float new_up_axis[3])
+{
+ float mat[3][3], nor[3], up_axis[3], vec[3];
+ float roll;
+
+ VecSubf(nor, bone->tail, bone->head);
+
+ vec_roll_to_mat3(nor, 0, mat);
+ VECCOPY(up_axis, mat[2]);
+
+ roll = NormalizedVecAngle2(new_up_axis, up_axis);
+
+ Crossf(vec, up_axis, new_up_axis);
+
+ if (Inpf(vec, nor) < 0)
+ {
+ roll = -roll;
+ }
+
+ return roll;
+}
+
+
+/* Set roll value for given bone -> Z-Axis Point up (original method) */
+void auto_align_ebone_zaxisup(Scene *scene, View3D *v3d, EditBone *ebone)
+{
+ float delta[3], curmat[3][3];
+ float xaxis[3]={1.0f, 0.0f, 0.0f}, yaxis[3], zaxis[3]={0.0f, 0.0f, 1.0f};
+ float targetmat[3][3], imat[3][3], diffmat[3][3];
+
+ /* Find the current bone matrix */
+ VecSubf(delta, ebone->tail, ebone->head);
+ vec_roll_to_mat3(delta, 0.0f, curmat);
+
+ /* Make new matrix based on y axis & z-up */
+ VECCOPY(yaxis, curmat[1]);
+
+ Mat3One(targetmat);
+ VECCOPY(targetmat[0], xaxis);
+ VECCOPY(targetmat[1], yaxis);
+ VECCOPY(targetmat[2], zaxis);
+ Mat3Ortho(targetmat);
+
+ /* Find the difference between the two matrices */
+ Mat3Inv(imat, targetmat);
+ Mat3MulMat3(diffmat, imat, curmat);
+
+ // old-method... let's see if using mat3_to_vec_roll is more accurate
+ //ebone->roll = atan2(diffmat[2][0], diffmat[2][2]);
+ mat3_to_vec_roll(diffmat, delta, &ebone->roll);
+}
+
+/* Set roll value for given bone -> Z-Axis point towards cursor */
+void auto_align_ebone_tocursor(Scene *scene, View3D *v3d, EditBone *ebone)
+{
+ Object *obedit= scene->obedit; // XXX get from context
+ float *cursor= give_cursor(scene, v3d);
+ float delta[3], curmat[3][3];
+ float mat[4][4], tmat[4][4], imat[4][4];
+ float rmat[4][4], rot[3];
+ float vec[3];
+
+ /* find the current bone matrix as a 4x4 matrix (in Armature Space) */
+ VecSubf(delta, ebone->tail, ebone->head);
+ vec_roll_to_mat3(delta, ebone->roll, curmat);
+ Mat4CpyMat3(mat, curmat);
+ VECCOPY(mat[3], ebone->head);
+
+ /* multiply bone-matrix by object matrix (so that bone-matrix is in WorldSpace) */
+ Mat4MulMat4(tmat, mat, obedit->obmat);
+ Mat4Invert(imat, tmat);
+
+ /* find position of cursor relative to bone */
+ VecMat4MulVecfl(vec, imat, cursor);
+
+ /* check that cursor is in usable position */
+ if ((IS_EQ(vec[0], 0)==0) && (IS_EQ(vec[2], 0)==0)) {
+ /* Compute a rotation matrix around y */
+ rot[1] = (float)atan2(vec[0], vec[2]);
+ rot[0] = rot[2] = 0.0f;
+ EulToMat4(rot, rmat);
+
+ /* Multiply the bone matrix by rotation matrix. This should be new bone-matrix */
+ Mat4MulMat4(tmat, rmat, mat);
+ Mat3CpyMat4(curmat, tmat);
+
+ /* Now convert from new bone-matrix, back to a roll value (in radians) */
+ mat3_to_vec_roll(curmat, delta, &ebone->roll);
+ }
+}
+
+
+static EnumPropertyItem prop_calc_roll_types[] = {
+ {0, "GLOBALUP", "Z-Axis Up", ""},
+ {1, "CURSOR", "Z-Axis to Cursor", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int armature_calc_roll_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ View3D *v3d= (View3D *)CTX_wm_space_data(C);
+ Object *ob= CTX_data_edit_object(C);
+ void (*roll_func)(Scene *, View3D *, EditBone *) = NULL;
+
+ /* specific method used to calculate roll depends on mode */
+ switch (RNA_enum_get(op->ptr, "type")) {
+ case 1: /* Z-Axis point towards cursor */
+ roll_func= auto_align_ebone_tocursor;
+ break;
+ default: /* Z-Axis Point Up */
+ roll_func= auto_align_ebone_zaxisup;
+ break;
+ }
+
+ /* recalculate roll on selected bones */
+ CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
+ /* roll func is a callback which assumes that all is well */
+ roll_func(scene, v3d, ebone);
+ }
+ CTX_DATA_END;
+
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_calculate_roll(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Recalculate Roll";
+ ot->idname= "ARMATURE_OT_calculate_roll";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = armature_calc_roll_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", prop_calc_roll_types, 0, "Type", "");
+}
+
+/* **************** undo for armatures ************** */
+
+static void undoBones_to_editBones(void *lbuv, void *lbev)
+{
+ ListBase *lbu= lbuv;
+ ListBase *edbo= lbev;
+ EditBone *ebo, *newebo;
+
+ BLI_freelistN(edbo);
+
+ /* copy */
+ for(ebo= lbu->first; ebo; ebo= ebo->next) {
+ newebo= MEM_dupallocN(ebo);
+ ebo->temp= newebo;
+ BLI_addtail(edbo, newebo);
+ }
+
+ /* set pointers */
+ for(newebo= edbo->first; newebo; newebo= newebo->next) {
+ if(newebo->parent) newebo->parent= newebo->parent->temp;
+ }
+ /* be sure they dont hang ever */
+ for(newebo= edbo->first; newebo; newebo= newebo->next) {
+ newebo->temp= NULL;
+ }
+}
+
+static void *editBones_to_undoBones(void *lbev)
+{
+ ListBase *edbo= lbev;
+ ListBase *lb;
+ EditBone *ebo, *newebo;
+
+ lb= MEM_callocN(sizeof(ListBase), "listbase undo");
+
+ /* copy */
+ for(ebo= edbo->first; ebo; ebo= ebo->next) {
+ newebo= MEM_dupallocN(ebo);
+ ebo->temp= newebo;
+ BLI_addtail(lb, newebo);
+ }
+
+ /* set pointers */
+ for(newebo= lb->first; newebo; newebo= newebo->next) {
+ if(newebo->parent) newebo->parent= newebo->parent->temp;
+ }
+
+ return lb;
+}
+
+static void free_undoBones(void *lbv)
+{
+ ListBase *lb= lbv;
+
+ BLI_freelistN(lb);
+ MEM_freeN(lb);
+}
+
+static void *get_armature_edit(bContext *C)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ if(obedit && obedit->type==OB_ARMATURE) {
+ bArmature *arm= obedit->data;
+ return arm->edbo;
+ }
+ return NULL;
+}
+
+/* and this is all the undo system needs to know */
+void undo_push_armature(bContext *C, char *name)
+{
+ // XXX solve getdata()
+ undo_editmode_push(C, name, get_armature_edit, free_undoBones, undoBones_to_editBones, editBones_to_undoBones, NULL);
+}
+
+
+
+/* **************** END EditMode stuff ********************** */
+/* *************** Adding stuff in editmode *************** */
+
+/* default bone add, returns it selected, but without tail set */
+EditBone *addEditBone(bArmature *arm, char *name)
+{
+ EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone");
+
+ BLI_strncpy(bone->name, name, 32);
+ unique_editbone_name(arm->edbo, bone->name, NULL);
+
+ BLI_addtail(arm->edbo, bone);
+
+ bone->flag |= BONE_TIPSEL;
+ bone->weight= 1.0f;
+ bone->dist= 0.25f;
+ bone->xwidth= 0.1f;
+ bone->zwidth= 0.1f;
+ bone->ease1= 1.0f;
+ bone->ease2= 1.0f;
+ bone->rad_head= 0.10f;
+ bone->rad_tail= 0.05f;
+ bone->segments= 1;
+ bone->layer= arm->layer;
+
+ return bone;
+}
+
+/* default bone add, returns it selected, but without tail set */
+static EditBone *add_editbone(Object *obedit, char *name)
+{
+ bArmature *arm= obedit->data;
+
+ return addEditBone(arm, name);
+}
+
+/* v3d and rv3d are allowed to be NULL */
+void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d)
+{
+ Object *obedit= scene->obedit; // XXX get from context
+ float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
+ EditBone *bone;
+
+ VECCOPY(curs, give_cursor(scene, v3d));
+
+ /* Get inverse point for head and orientation for tail */
+ Mat4Invert(obedit->imat, obedit->obmat);
+ Mat4MulVecfl(obedit->imat, curs);
+
+ if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
+ Mat3CpyMat4(obmat, rv3d->viewmat);
+ else Mat3One(obmat);
+
+ Mat3CpyMat4(viewmat, obedit->obmat);
+ Mat3MulMat3(totmat, obmat, viewmat);
+ Mat3Inv(imat, totmat);
+
+ deselectall_armature(obedit, 0, 0);
+
+ /* Create a bone */
+ bone= add_editbone(obedit, "Bone");
+
+ VECCOPY(bone->head, curs);
+
+ if ( (U.flag & USER_ADD_VIEWALIGNED) )
+ VecAddf(bone->tail, bone->head, imat[1]); // bone with unit length 1
+ else
+ VecAddf(bone->tail, bone->head, imat[2]); // bone with unit length 1, pointing up Z
+
+}
+
+
+/* previously addvert_armature */
+/* the ctrl-click method */
+static int armature_click_extrude_exec(bContext *C, wmOperator *op)
+{
+ View3D *v3d;
+ bArmature *arm;
+ EditBone *ebone, *newbone, *flipbone;
+ float *curs, mat[3][3],imat[3][3];
+ int a, to_root= 0;
+ Object *obedit;
+ Scene *scene;
+
+ scene = CTX_data_scene(C);
+ v3d= CTX_wm_view3d(C);
+ obedit= CTX_data_edit_object(C);
+ arm= obedit->data;
+
+ /* find the active or selected bone */
+ for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (ebone->flag & (BONE_ACTIVE|BONE_TIPSEL))
+ break;
+ }
+ }
+
+ if (ebone==NULL) {
+ for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (ebone->flag & (BONE_ACTIVE|BONE_ROOTSEL))
+ break;
+ }
+ }
+ if (ebone == NULL)
+ return OPERATOR_CANCELLED;
+
+ to_root= 1;
+ }
+
+ deselectall_armature(obedit, 0, 0);
+
+ /* we re-use code for mirror editing... */
+ flipbone= NULL;
+ if (arm->flag & ARM_MIRROR_EDIT)
+ flipbone= ED_armature_bone_get_mirrored(arm->edbo, ebone);
+
+ for (a=0; a<2; a++) {
+ if (a==1) {
+ if (flipbone==NULL)
+ break;
+ else {
+ SWAP(EditBone *, flipbone, ebone);
+ }
+ }
+
+ newbone= add_editbone(obedit, ebone->name);
+ newbone->flag |= BONE_ACTIVE;
+
+ if (to_root) {
+ VECCOPY(newbone->head, ebone->head);
+ newbone->rad_head= ebone->rad_tail;
+ newbone->parent= ebone->parent;
+ }
+ else {
+ VECCOPY(newbone->head, ebone->tail);
+ newbone->rad_head= ebone->rad_tail;
+ newbone->parent= ebone;
+ newbone->flag |= BONE_CONNECTED;
+ }
+
+ curs= give_cursor(scene, v3d);
+ VECCOPY(newbone->tail, curs);
+ VecSubf(newbone->tail, newbone->tail, obedit->obmat[3]);
+
+ if (a==1)
+ newbone->tail[0]= -newbone->tail[0];
+
+ Mat3CpyMat4(mat, obedit->obmat);
+ Mat3Inv(imat, mat);
+ Mat3MulVecfl(imat, newbone->tail);
+
+ newbone->length= VecLenf(newbone->head, newbone->tail);
+ newbone->rad_tail= newbone->length*0.05f;
+ newbone->dist= newbone->length*0.25f;
+
+ }
+
+ armature_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+static int armature_click_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ /* TODO most of this code is copied from set3dcursor_invoke,
+ it would be better to reuse code in set3dcursor_invoke */
+
+ /* temporarily change 3d cursor position */
+ Scene *scene;
+ ARegion *ar;
+ View3D *v3d;
+ RegionView3D *rv3d;
+ float dx, dy, fz, *fp = NULL, dvec[3], oldcurs[3];
+ short mx, my, mval[2];
+ int retv;
+
+ scene= CTX_data_scene(C);
+ ar= CTX_wm_region(C);
+ v3d = CTX_wm_view3d(C);
+ rv3d= CTX_wm_region_view3d(C);
+
+ fp= give_cursor(scene, v3d);
+
+ VECCOPY(oldcurs, fp);
+
+ mx= event->x - ar->winrct.xmin;
+ my= event->y - ar->winrct.ymin;
+ project_short_noclip(ar, fp, mval);
+
+ initgrabz(rv3d, fp[0], fp[1], fp[2]);
+
+ if(mval[0]!=IS_CLIPPED) {
+
+ window_to_3d_delta(ar, dvec, mval[0]-mx, mval[1]-my);
+ VecSubf(fp, fp, dvec);
+ }
+ else {
+
+ dx= ((float)(mx-(ar->winx/2)))*rv3d->zfac/(ar->winx/2);
+ dy= ((float)(my-(ar->winy/2)))*rv3d->zfac/(ar->winy/2);
+
+ fz= rv3d->persmat[0][3]*fp[0]+ rv3d->persmat[1][3]*fp[1]+ rv3d->persmat[2][3]*fp[2]+ rv3d->persmat[3][3];
+ fz= fz/rv3d->zfac;
+
+ fp[0]= (rv3d->persinv[0][0]*dx + rv3d->persinv[1][0]*dy+ rv3d->persinv[2][0]*fz)-rv3d->ofs[0];
+ fp[1]= (rv3d->persinv[0][1]*dx + rv3d->persinv[1][1]*dy+ rv3d->persinv[2][1]*fz)-rv3d->ofs[1];
+ fp[2]= (rv3d->persinv[0][2]*dx + rv3d->persinv[1][2]*dy+ rv3d->persinv[2][2]*fz)-rv3d->ofs[2];
+ }
+
+ /* extrude to the where new cursor is and store the operation result */
+ retv= armature_click_extrude_exec(C, op);
+
+ /* restore previous 3d cursor position */
+ VECCOPY(fp, oldcurs);
+
+ return retv;
+}
+
+void ARMATURE_OT_click_extrude(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Click-Extrude";
+ ot->idname= "ARMATURE_OT_click_extrude";
+
+ /* api callbacks */
+ ot->invoke = armature_click_extrude_invoke;
+ ot->exec = armature_click_extrude_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+}
+
+/* adds an EditBone between the nominated locations (should be in the right space) */
+static EditBone *add_points_bone (Object *obedit, float head[], float tail[])
+{
+ EditBone *ebo;
+
+ ebo= add_editbone(obedit, "Bone");
+
+ VECCOPY(ebo->head, head);
+ VECCOPY(ebo->tail, tail);
+
+ return ebo;
+}
+
+
+static EditBone *get_named_editbone(ListBase *edbo, char *name)
+{
+ EditBone *eBone;
+
+ if (name) {
+ for (eBone=edbo->first; eBone; eBone=eBone->next) {
+ if (!strcmp(name, eBone->name))
+ return eBone;
+ }
+ }
+
+ return NULL;
+}
+
+/* Call this before doing any duplications
+ * */
+void preEditBoneDuplicate(ListBase *editbones)
+{
+ EditBone *eBone;
+
+ /* clear temp */
+ for (eBone = editbones->first; eBone; eBone = eBone->next)
+ {
+ eBone->temp = NULL;
+ }
+}
+
+/*
+ * Note: When duplicating cross objects, editbones here is the list of bones
+ * from the SOURCE object but ob is the DESTINATION object
+ * */
+void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Object *src_ob, Object *dst_ob)
+{
+ /* If an edit bone has been duplicated, lets
+ * update it's constraints if the subtarget
+ * they point to has also been duplicated
+ */
+ EditBone *oldtarget, *newtarget;
+ bPoseChannel *chan;
+ bConstraint *curcon;
+ ListBase *conlist;
+
+ if ( (chan = verify_pose_channel(dst_ob->pose, dupBone->name)) ) {
+ if ( (conlist = &chan->constraints) ) {
+ for (curcon = conlist->first; curcon; curcon=curcon->next) {
+ /* does this constraint have a subtarget in
+ * this armature?
+ */
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(curcon, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ if ((ct->tar == src_ob) && (ct->subtarget[0])) {
+ ct->tar = dst_ob; /* update target */
+ oldtarget = get_named_editbone(editbones, ct->subtarget);
+ if (oldtarget) {
+ /* was the subtarget bone duplicated too? If
+ * so, update the constraint to point at the
+ * duplicate of the old subtarget.
+ */
+ if (oldtarget->temp) {
+ newtarget = (EditBone *) oldtarget->temp;
+ strcpy(ct->subtarget, newtarget->name);
+ }
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(curcon, &targets, 0);
+ }
+ }
+ }
+ }
+}
+
+void updateDuplicateSubtarget(EditBone *dupBone, ListBase *editbones, Object *ob)
+{
+ updateDuplicateSubtargetObjects(dupBone, editbones, ob, ob);
+}
+
+
+EditBone *duplicateEditBoneObjects(EditBone *curBone, char *name, ListBase *editbones, Object *src_ob, Object *dst_ob)
+{
+ EditBone *eBone = MEM_callocN(sizeof(EditBone), "addup_editbone");
+
+ /* Copy data from old bone to new bone */
+ memcpy(eBone, curBone, sizeof(EditBone));
+
+ curBone->temp = eBone;
+ eBone->temp = curBone;
+
+ if (name != NULL)
+ {
+ BLI_strncpy(eBone->name, name, 32);
+ }
+
+ unique_editbone_name(editbones, eBone->name, NULL);
+ BLI_addtail(editbones, eBone);
+
+ /* Lets duplicate the list of constraints that the
+ * current bone has.
+ */
+ if (src_ob->pose) {
+ bPoseChannel *chanold, *channew;
+ ListBase *listold, *listnew;
+
+ chanold = verify_pose_channel(src_ob->pose, curBone->name);
+ if (chanold) {
+ listold = &chanold->constraints;
+ if (listold) {
+ /* WARNING: this creates a new posechannel, but there will not be an attached bone
+ * yet as the new bones created here are still 'EditBones' not 'Bones'.
+ */
+ channew =
+ verify_pose_channel(dst_ob->pose, eBone->name);
+ if (channew) {
+ /* copy transform locks */
+ channew->protectflag = chanold->protectflag;
+
+ /* copy bone group */
+ channew->agrp_index= chanold->agrp_index;
+
+ /* ik (dof) settings */
+ channew->ikflag = chanold->ikflag;
+ VECCOPY(channew->limitmin, chanold->limitmin);
+ VECCOPY(channew->limitmax, chanold->limitmax);
+ VECCOPY(channew->stiffness, chanold->stiffness);
+ channew->ikstretch= chanold->ikstretch;
+
+ /* constraints */
+ listnew = &channew->constraints;
+ copy_constraints(listnew, listold);
+
+ /* custom shape */
+ channew->custom= chanold->custom;
+ }
+ }
+ }
+ }
+
+ return eBone;
+}
+
+EditBone *duplicateEditBone(EditBone *curBone, char *name, ListBase *editbones, Object *ob)
+{
+ return duplicateEditBoneObjects(curBone, name, editbones, ob, ob);
+}
+
+/* previously adduplicate_armature */
+static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
+{
+ bArmature *arm;
+ EditBone *eBone = NULL;
+ EditBone *curBone;
+ EditBone *firstDup=NULL; /* The beginning of the duplicated bones in the edbo list */
+
+ Object *obedit= CTX_data_edit_object(C);
+ arm= obedit->data;
+
+ /* cancel if nothing selected */
+ if (CTX_DATA_COUNT(C, selected_bones) == 0)
+ return OPERATOR_CANCELLED;
+
+ armature_sync_selection(arm->edbo); // XXX why is this needed?
+
+ preEditBoneDuplicate(arm->edbo);
+
+ /* Select mirrored bones */
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
+ if (EBONE_VISIBLE(arm, curBone)) {
+ if (curBone->flag & BONE_SELECTED) {
+ eBone = ED_armature_bone_get_mirrored(arm->edbo, curBone);
+ if (eBone)
+ eBone->flag |= BONE_SELECTED;
+ }
+ }
+ }
+ }
+
+
+ /* Find the selected bones and duplicate them as needed */
+ for (curBone=arm->edbo->first; curBone && curBone!=firstDup; curBone=curBone->next) {
+ if (EBONE_VISIBLE(arm, curBone)) {
+ 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));
+
+ curBone->temp = eBone;
+ eBone->temp = curBone;
+
+ unique_editbone_name(arm->edbo, eBone->name, NULL);
+ BLI_addtail(arm->edbo, eBone);
+ if (!firstDup)
+ firstDup=eBone;
+
+ /* Lets duplicate the list of constraints that the
+ * current bone has.
+ */
+ if (obedit->pose) {
+ bPoseChannel *chanold, *channew;
+ ListBase *listold, *listnew;
+
+ chanold = verify_pose_channel(obedit->pose, curBone->name);
+ if (chanold) {
+ listold = &chanold->constraints;
+ if (listold) {
+ /* WARNING: this creates a new posechannel, but there will not be an attached bone
+ * yet as the new bones created here are still 'EditBones' not 'Bones'.
+ */
+ channew =
+ verify_pose_channel(obedit->pose, eBone->name);
+ if (channew) {
+ /* copy transform locks */
+ channew->protectflag = chanold->protectflag;
+
+ /* copy bone group */
+ channew->agrp_index= chanold->agrp_index;
+
+ /* ik (dof) settings */
+ channew->ikflag = chanold->ikflag;
+ VECCOPY(channew->limitmin, chanold->limitmin);
+ VECCOPY(channew->limitmax, chanold->limitmax);
+ VECCOPY(channew->stiffness, chanold->stiffness);
+ channew->ikstretch= chanold->ikstretch;
+
+ /* constraints */
+ listnew = &channew->constraints;
+ copy_constraints(listnew, listold);
+
+ /* custom shape */
+ channew->custom= chanold->custom;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Run though the list and fix the pointers */
+ for (curBone=arm->edbo->first; curBone && curBone!=firstDup; curBone=curBone->next) {
+ if (EBONE_VISIBLE(arm, curBone)) {
+ if (curBone->flag & BONE_SELECTED) {
+ eBone=(EditBone*) curBone->temp;
+
+ if (!curBone->parent) {
+ /* If this bone has no parent,
+ * Set the duplicate->parent to NULL
+ */
+ eBone->parent = NULL;
+ }
+ else if (curBone->parent->temp) {
+ /* If this bone has a parent that was duplicated,
+ * Set the duplicate->parent to the curBone->parent->temp
+ */
+ eBone->parent= (EditBone *)curBone->parent->temp;
+ }
+ else {
+ /* If this bone has a parent that IS not selected,
+ * Set the duplicate->parent to the curBone->parent
+ */
+ eBone->parent=(EditBone*) curBone->parent;
+ eBone->flag &= ~BONE_CONNECTED;
+ }
+
+ /* Lets try to fix any constraint subtargets that might
+ * have been duplicated
+ */
+ updateDuplicateSubtarget(eBone, arm->edbo, obedit);
+ }
+ }
+ }
+
+ /* Deselect the old bones and select the new ones */
+ for (curBone=arm->edbo->first; curBone && curBone!=firstDup; curBone=curBone->next) {
+ if (EBONE_VISIBLE(arm, curBone))
+ curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+static int armature_duplicate_selected_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ int retv= armature_duplicate_selected_exec(C, op);
+
+ if (retv == OPERATOR_FINISHED) {
+ RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
+ WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+ }
+
+ return retv;
+}
+
+void ARMATURE_OT_duplicate_selected(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Duplicate Selected Bone(s)";
+ ot->idname= "ARMATURE_OT_duplicate_selected";
+
+ /* api callbacks */
+ ot->invoke = armature_duplicate_selected_invoke;
+ ot->exec = armature_duplicate_selected_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* to give to transform */
+ RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+}
+
+
+/* *************** END Adding stuff in editmode *************** */
+/* ************** Add/Remove stuff in editmode **************** */
+
+/* temporary data-structure for merge/fill bones */
+typedef struct EditBonePoint {
+ struct EditBonePoint *next, *prev;
+
+ EditBone *head_owner; /* EditBone which uses this point as a 'head' point */
+ EditBone *tail_owner; /* EditBone which uses this point as a 'tail' point */
+
+ float vec[3]; /* the actual location of the point in local/EditMode space */
+} EditBonePoint;
+
+/* find chain-tips (i.e. bones without children) */
+static void chains_find_tips (ListBase *edbo, ListBase *list)
+{
+ EditBone *curBone, *ebo;
+ LinkData *ld;
+
+ /* note: this is potentially very slow ... there's got to be a better way */
+ for (curBone= edbo->first; curBone; curBone= curBone->next) {
+ short stop= 0;
+
+ /* is this bone contained within any existing chain? (skip if so) */
+ for (ld= list->first; ld; ld= ld->next) {
+ for (ebo= ld->data; ebo; ebo= ebo->parent) {
+ if (ebo == curBone) {
+ stop= 1;
+ break;
+ }
+ }
+
+ if (stop) break;
+ }
+ /* skip current bone if it is part of an existing chain */
+ if (stop) continue;
+
+ /* is any existing chain part of the chain formed by this bone? */
+ stop= 0;
+ for (ebo= curBone->parent; ebo; ebo= ebo->parent) {
+ for (ld= list->first; ld; ld= ld->next) {
+ if (ld->data == ebo) {
+ ld->data= curBone;
+ stop= 1;
+ break;
+ }
+ }
+
+ if (stop) break;
+ }
+ /* current bone has already been added to a chain? */
+ if (stop) continue;
+
+ /* add current bone to a new chain */
+ ld= MEM_callocN(sizeof(LinkData), "BoneChain");
+ ld->data= curBone;
+ BLI_addtail(list, ld);
+ }
+}
+
+
+static void fill_add_joint (EditBone *ebo, short eb_tail, ListBase *points)
+{
+ EditBonePoint *ebp;
+ float vec[3];
+ short found= 0;
+
+ if (eb_tail) {
+ VECCOPY(vec, ebo->tail);
+ }
+ else {
+ VECCOPY(vec, ebo->head);
+ }
+
+ for (ebp= points->first; ebp; ebp= ebp->next) {
+ if (VecEqual(ebp->vec, vec)) {
+ if (eb_tail) {
+ if ((ebp->head_owner) && (ebp->head_owner->parent == ebo)) {
+ /* so this bone's tail owner is this bone */
+ ebp->tail_owner= ebo;
+ found= 1;
+ break;
+ }
+ }
+ else {
+ if ((ebp->tail_owner) && (ebo->parent == ebp->tail_owner)) {
+ /* so this bone's head owner is this bone */
+ ebp->head_owner= ebo;
+ found = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ /* allocate a new point if no existing point was related */
+ if (found == 0) {
+ ebp= MEM_callocN(sizeof(EditBonePoint), "EditBonePoint");
+
+ if (eb_tail) {
+ VECCOPY(ebp->vec, ebo->tail);
+ ebp->tail_owner= ebo;
+ }
+ else {
+ VECCOPY(ebp->vec, ebo->head);
+ ebp->head_owner= ebo;
+ }
+
+ BLI_addtail(points, ebp);
+ }
+}
+
+/* bone adding between selected joints */
+void fill_bones_armature(Scene *scene, View3D *v3d)
+{
+ Object *obedit= scene->obedit; // XXX get from context
+ bArmature *arm= obedit->data;
+ EditBone *ebo, *newbone=NULL;
+ ListBase points = {NULL, NULL};
+ int count;
+
+ /* loop over all bones, and only consider if visible */
+ for (ebo= arm->edbo->first; ebo; ebo= ebo->next) {
+ if (EBONE_VISIBLE(arm, ebo)) {
+ if (!(ebo->flag & BONE_CONNECTED) && (ebo->flag & BONE_ROOTSEL))
+ fill_add_joint(ebo, 0, &points);
+ if (ebo->flag & BONE_TIPSEL)
+ fill_add_joint(ebo, 1, &points);
+ }
+ }
+
+ /* the number of joints determines how we fill:
+ * 1) between joint and cursor (joint=head, cursor=tail)
+ * 2) between the two joints (order is dependent on active-bone/hierachy)
+ * 3+) error (a smarter method involving finding chains needs to be worked out
+ */
+ count= BLI_countlist(&points);
+
+ if (count == 0) {
+ error("No joints selected");
+ return;
+ }
+ else if (count == 1) {
+ EditBonePoint *ebp;
+ float *fp, curs[3];
+
+ /* Get Points - selected joint */
+ ebp= (EditBonePoint *)points.first;
+
+ /* Get points - cursor (tail) */
+ fp= give_cursor(scene, v3d);
+ VECCOPY (curs, fp);
+
+ Mat4Invert(obedit->imat, obedit->obmat);
+ Mat4MulVecfl(obedit->imat, curs);
+
+ /* Create a bone */
+ newbone= add_points_bone(obedit, ebp->vec, curs);
+ }
+ else if (count == 2) {
+ EditBonePoint *ebp, *ebp2;
+ float head[3], tail[3];
+ short headtail = 0;
+
+ /* check that the points don't belong to the same bone */
+ ebp= (EditBonePoint *)points.first;
+ ebp2= ebp->next;
+
+ if ((ebp->head_owner==ebp2->tail_owner) && (ebp->head_owner!=NULL)) {
+ error("Same bone selected...");
+ BLI_freelistN(&points);
+ return;
+ }
+ if ((ebp->tail_owner==ebp2->head_owner) && (ebp->tail_owner!=NULL)) {
+ error("Same bone selected...");
+ BLI_freelistN(&points);
+ return;
+ }
+
+ /* find which one should be the 'head' */
+ if ((ebp->head_owner && ebp2->head_owner) || (ebp->tail_owner && ebp2->tail_owner)) {
+ /* rule: whichever one is closer to 3d-cursor */
+ float curs[3], *fp= give_cursor(scene, v3d);
+ float vecA[3], vecB[3];
+ float distA, distB;
+
+ /* get cursor location */
+ VECCOPY(curs, fp);
+
+ Mat4Invert(obedit->imat, obedit->obmat);
+ Mat4MulVecfl(obedit->imat, curs);
+
+ /* get distances */
+ VecSubf(vecA, ebp->vec, curs);
+ VecSubf(vecB, ebp2->vec, curs);
+ distA= VecLength(vecA);
+ distB= VecLength(vecB);
+
+ /* compare distances - closer one therefore acts as direction for bone to go */
+ headtail= (distA < distB) ? 2 : 1;
+ }
+ else if (ebp->head_owner) {
+ headtail = 1;
+ }
+ else if (ebp2->head_owner) {
+ headtail = 2;
+ }
+
+ /* assign head/tail combinations */
+ if (headtail == 2) {
+ VECCOPY(head, ebp->vec);
+ VECCOPY(tail, ebp2->vec);
+ }
+ else if (headtail == 1) {
+ VECCOPY(head, ebp2->vec);
+ VECCOPY(tail, ebp->vec);
+ }
+
+ /* add new bone and parent it to the appropriate end */
+ if (headtail) {
+ newbone= add_points_bone(obedit, head, tail);
+
+ /* do parenting (will need to set connected flag too) */
+ if (headtail == 2) {
+ /* ebp tail or head - tail gets priority */
+ if (ebp->tail_owner)
+ newbone->parent= ebp->tail_owner;
+ else
+ newbone->parent= ebp->head_owner;
+ }
+ else {
+ /* ebp2 tail or head - tail gets priority */
+ if (ebp2->tail_owner)
+ newbone->parent= ebp2->tail_owner;
+ else
+ newbone->parent= ebp2->head_owner;
+ }
+
+ newbone->flag |= BONE_CONNECTED;
+ }
+ }
+ else {
+ // FIXME.. figure out a method for multiple bones
+ error("Too many points selected");
+ printf("Points selected: %d \n", count);
+ BLI_freelistN(&points);
+ return;
+ }
+
+ /* free points */
+ BLI_freelistN(&points);
+
+ /* undo + updates */
+ BIF_undo_push("Fill Bones");
+}
+
+/* this function merges between two bones, removes them and those in-between,
+ * and adjusts the parent relationships for those in-between
+ */
+static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone *endchild, ListBase *chains)
+{
+ bArmature *arm= obedit->data;
+ EditBone *ebo, *ebone, *newbone;
+ LinkData *chain;
+ float head[3], tail[3];
+
+ /* check if same bone */
+ if (start == end) {
+ printf("Error: same bone! \n");
+ printf("\tstart = %s, end = %s \n", start->name, end->name);
+ }
+
+ /* step 1: add a new bone
+ * - head = head/tail of start (default head)
+ * - tail = head/tail of end (default tail)
+ * - parent = parent of start
+ */
+ if ((start->flag & BONE_TIPSEL) && !(start->flag & (BONE_SELECTED|BONE_ACTIVE))) {
+ VECCOPY(head, start->tail);
+ }
+ else {
+ VECCOPY(head, start->head);
+ }
+ if ((end->flag & BONE_ROOTSEL) && !(end->flag & (BONE_SELECTED|BONE_ACTIVE))) {
+ VECCOPY(tail, end->head);
+ }
+ else {
+ VECCOPY(tail, end->tail);
+ }
+ newbone= add_points_bone(obedit, head, tail);
+ newbone->parent = start->parent;
+
+ /* step 2a: parent children of in-between bones to newbone */
+ for (chain= chains->first; chain; chain= chain->next) {
+ /* ick: we need to check if parent of each bone in chain is one of the bones in the */
+ for (ebo= chain->data; ebo; ebo= ebo->parent) {
+ short found= 0;
+
+ /* try to find which bone from the list to be removed, is the parent */
+ for (ebone= end; ebone; ebone= ebone->parent) {
+ if (ebo->parent == ebone) {
+ found= 1;
+ break;
+ }
+ }
+
+ /* adjust this bone's parent to newbone then */
+ if (found) {
+ ebo->parent= newbone;
+ break;
+ }
+ }
+ }
+
+ /* step 2b: parent child of end to newbone (child from this chain) */
+ if (endchild)
+ endchild->parent= newbone;
+
+ /* step 3: delete all bones between and including start and end */
+ for (ebo= end; ebo; ebo= ebone) {
+ ebone= (ebo == start) ? (NULL) : (ebo->parent);
+ BLI_freelinkN(arm->edbo, ebo);
+ }
+}
+
+/* bone merging - has a menu! */
+void merge_armature(Scene *scene)
+{
+ Object *obedit= scene->obedit; // XXX get from context
+ bArmature *arm= obedit->data;
+ short val= 0;
+
+ /* process a menu to determine how to merge */
+ // TODO: there's room for more modes of merging stuff...
+ val= pupmenu("Merge Selected Bones%t|Within Chains%x1");
+ if (val <= 0) return;
+
+ if (val == 1) {
+ /* go down chains, merging bones */
+ ListBase chains = {NULL, NULL};
+ LinkData *chain, *nchain;
+ EditBone *ebo;
+
+ /* get chains (ends on chains) */
+ chains_find_tips(arm->edbo, &chains);
+ if (chains.first == NULL) return;
+
+ /* each 'chain' is the last bone in the chain (with no children) */
+ for (chain= chains.first; chain; chain= nchain) {
+ EditBone *bstart= NULL, *bend= NULL;
+ EditBone *bchild= NULL, *child=NULL;
+
+ /* temporarily remove chain from list of chains */
+ nchain= chain->next;
+ BLI_remlink(&chains, chain);
+
+ /* only consider bones that are visible and selected */
+ for (ebo=chain->data; ebo; child=ebo, ebo=ebo->parent) {
+ /* check if visible + selected */
+ if ( EBONE_VISIBLE(arm, ebo) &&
+ ((ebo->flag & BONE_CONNECTED) || (ebo->parent==NULL)) &&
+ (ebo->flag & (BONE_SELECTED|BONE_ACTIVE)) )
+ {
+ /* set either end or start (end gets priority, unless it is already set) */
+ if (bend == NULL) {
+ bend= ebo;
+ bchild= child;
+ }
+ else
+ bstart= ebo;
+ }
+ else {
+ /* chain is broken... merge any continous segments then clear */
+ if (bstart && bend)
+ bones_merge(obedit, bstart, bend, bchild, &chains);
+
+ bstart = NULL;
+ bend = NULL;
+ bchild = NULL;
+ }
+ }
+
+ /* merge from bstart to bend if something not merged */
+ if (bstart && bend)
+ bones_merge(obedit, bstart, bend, bchild, &chains);
+
+ /* put back link */
+ BLI_insertlinkbefore(&chains, nchain, chain);
+ }
+
+ BLI_freelistN(&chains);
+ }
+
+ /* undo + updates */
+ armature_sync_selection(arm->edbo);
+ BIF_undo_push("Merge Bones");
+}
+
+/* ************** END Add/Remove stuff in editmode ************ */
+/* *************** Tools in editmode *********** */
+
+
+void hide_selected_armature_bones(Scene *scene)
+{
+ Object *obedit= scene->obedit; // XXX get from context
+ bArmature *arm= obedit->data;
+ EditBone *ebone;
+
+ for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (ebone->flag & (BONE_SELECTED)) {
+ ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE);
+ ebone->flag |= BONE_HIDDEN_A;
+ }
+ }
+ }
+ armature_sync_selection(arm->edbo);
+ BIF_undo_push("Hide Bones");
+}
+
+void hide_unselected_armature_bones(Scene *scene)
+{
+ Object *obedit= scene->obedit; // XXX get from context
+ bArmature *arm= obedit->data;
+ EditBone *ebone;
+
+ for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
+ bArmature *arm= obedit->data;
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (ebone->flag & (BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL));
+ else {
+ ebone->flag &= ~BONE_ACTIVE;
+ ebone->flag |= BONE_HIDDEN_A;
+ }
+ }
+ }
+ armature_sync_selection(arm->edbo);
+ BIF_undo_push("Hide Unselected Bones");
+}
+
+void show_all_armature_bones(Scene *scene)
+{
+ Object *obedit= scene->obedit; // XXX get from context
+ bArmature *arm= obedit->data;
+ EditBone *ebone;
+
+ for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
+ if(arm->layer & ebone->layer) {
+ if (ebone->flag & BONE_HIDDEN_A) {
+ ebone->flag |= (BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
+ ebone->flag &= ~BONE_HIDDEN_A;
+ }
+ }
+ }
+ armature_sync_selection(arm->edbo);
+ BIF_undo_push("Reveal Bones");
+}
+
+/* previously extrude_armature */
+/* context; editmode armature */
+/* if forked && mirror-edit: makes two bones with flipped names */
+static int armature_extrude_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit;
+ bArmature *arm;
+ EditBone *newbone, *ebone, *flipbone, *first=NULL;
+ int a, totbone= 0, do_extrude;
+ int forked = RNA_boolean_get(op->ptr, "forked");
+
+ obedit= CTX_data_edit_object(C);
+ arm= obedit->data;
+
+ /* since we allow root extrude too, we have to make sure selection is OK */
+ for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (ebone->flag & BONE_ROOTSEL) {
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ if (ebone->parent->flag & BONE_TIPSEL)
+ ebone->flag &= ~BONE_ROOTSEL;
+ }
+ }
+ }
+ }
+
+ /* Duplicate the necessary bones */
+ for (ebone = arm->edbo->first; ((ebone) && (ebone!=first)); ebone=ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ /* we extrude per definition the tip */
+ do_extrude= 0;
+ if (ebone->flag & (BONE_TIPSEL|BONE_SELECTED))
+ do_extrude= 1;
+ else if (ebone->flag & BONE_ROOTSEL) {
+ /* but, a bone with parent deselected we do the root... */
+ if (ebone->parent && (ebone->parent->flag & BONE_TIPSEL));
+ else do_extrude= 2;
+ }
+
+ if (do_extrude) {
+ /* we re-use code for mirror editing... */
+ flipbone= NULL;
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ flipbone= ED_armature_bone_get_mirrored(arm->edbo, ebone);
+ if (flipbone) {
+ forked= 0; // we extrude 2 different bones
+ if (flipbone->flag & (BONE_TIPSEL|BONE_ROOTSEL|BONE_SELECTED))
+ /* don't want this bone to be selected... */
+ flipbone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE);
+ }
+ if ((flipbone==NULL) && (forked))
+ flipbone= ebone;
+ }
+
+ for (a=0; a<2; a++) {
+ if (a==1) {
+ if (flipbone==NULL)
+ break;
+ else {
+ SWAP(EditBone *, flipbone, ebone);
+ }
+ }
+
+ totbone++;
+ newbone = MEM_callocN(sizeof(EditBone), "extrudebone");
+
+ if (do_extrude==1) {
+ VECCOPY (newbone->head, ebone->tail);
+ VECCOPY (newbone->tail, newbone->head);
+ newbone->parent = ebone;
+
+ newbone->flag = ebone->flag & BONE_TIPSEL; // copies it, in case mirrored bone
+
+ if (newbone->parent) newbone->flag |= BONE_CONNECTED;
+ }
+ else {
+ VECCOPY(newbone->head, ebone->head);
+ VECCOPY(newbone->tail, ebone->head);
+ newbone->parent= ebone->parent;
+
+ newbone->flag= BONE_TIPSEL;
+
+ if (newbone->parent && (ebone->flag & BONE_CONNECTED)) {
+ newbone->flag |= BONE_CONNECTED;
+ }
+ }
+
+ newbone->weight= ebone->weight;
+ newbone->dist= ebone->dist;
+ newbone->xwidth= ebone->xwidth;
+ newbone->zwidth= ebone->zwidth;
+ newbone->ease1= ebone->ease1;
+ newbone->ease2= ebone->ease2;
+ newbone->rad_head= ebone->rad_tail; // dont copy entire bone...
+ newbone->rad_tail= ebone->rad_tail;
+ newbone->segments= 1;
+ newbone->layer= ebone->layer;
+
+ BLI_strncpy (newbone->name, ebone->name, 32);
+
+ if (flipbone && forked) { // only set if mirror edit
+ if (strlen(newbone->name)<30) {
+ if (a==0) strcat(newbone->name, "_L");
+ else strcat(newbone->name, "_R");
+ }
+ }
+ unique_editbone_name(arm->edbo, newbone->name, NULL);
+
+ /* Add the new bone to the list */
+ BLI_addtail(arm->edbo, newbone);
+ if (!first)
+ first = newbone;
+
+ /* restore ebone if we were flipping */
+ if (a==1 && flipbone)
+ SWAP(EditBone *, flipbone, ebone);
+ }
+ }
+
+ /* Deselect the old bone */
+ ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE);
+ }
+ }
+ /* if only one bone, make this one active */
+ if (totbone==1 && first) first->flag |= BONE_ACTIVE;
+
+ if (totbone==0) return OPERATOR_CANCELLED;
+
+ /* Transform the endpoints */
+ armature_sync_selection(arm->edbo);
+
+ return OPERATOR_FINISHED;
+}
+
+static int armature_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ if (OPERATOR_CANCELLED == armature_extrude_exec(C, op))
+ return OPERATOR_CANCELLED;
+
+ RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
+ WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_extrude(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude";
+ ot->idname= "ARMATURE_OT_extrude";
+
+ /* api callbacks */
+ ot->invoke= armature_extrude_invoke;
+ ot->exec= armature_extrude_exec;
+ ot->poll= ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "forked", 0, "Forked", "");
+ /* to give to transform */
+ RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+}
+/* ********************** Bone Add ********************/
+
+/*op makes a new bone and returns it with its tip selected */
+
+static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
+{
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ Object *obedit = CTX_data_edit_object(C);
+ EditBone *bone;
+ float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
+ char name[32];
+
+ RNA_string_get(op->ptr, "name", name);
+
+ VECCOPY(curs, give_cursor(CTX_data_scene(C),CTX_wm_view3d(C)));
+
+ /* Get inverse point for head and orientation for tail */
+ Mat4Invert(obedit->imat, obedit->obmat);
+ Mat4MulVecfl(obedit->imat, curs);
+
+ if (U.flag & USER_ADD_VIEWALIGNED)
+ Mat3CpyMat4(obmat, rv3d->viewmat);
+ else Mat3One(obmat);
+
+ Mat3CpyMat4(viewmat, obedit->obmat);
+ Mat3MulMat3(totmat, obmat, viewmat);
+ Mat3Inv(imat, totmat);
+
+ deselectall_armature(obedit, 0, 0);
+
+ /* Create a bone */
+ bone= add_editbone(obedit, name);
+
+ VECCOPY(bone->head, curs);
+
+ if(U.flag & USER_ADD_VIEWALIGNED)
+ VecAddf(bone->tail, bone->head, imat[1]); // bone with unit length 1
+ else
+ VecAddf(bone->tail, bone->head, imat[2]); // bone with unit length 1, pointing up Z
+
+ WM_event_add_notifier(C, NC_OBJECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_bone_primitive_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Bone";
+ ot->idname= "ARMATURE_OT_bone_primitive_add";
+
+ /* api callbacks */
+ ot->exec = armature_bone_primitive_add_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_string(ot->srna, "name", "Bone", 32, "Name", "Name of the newly created bone");
+
+}
+
+
+/* ----------- */
+
+/* Subdivide Operators:
+ * This group of operators all use the same 'exec' callback, but they are called
+ * through several different operators - a combined menu (which just calls the exec in the
+ * appropriate ways), and two separate ones.
+ */
+
+static int armature_subdivide_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ bArmature *arm= obedit->data;
+ EditBone *newbone, *tbone;
+ int numcuts, i;
+
+ /* there may not be a number_cuts property defined (for 'simple' subdivide) */
+ if (RNA_property_is_set(op->ptr, "number_cuts"))
+ numcuts= RNA_int_get(op->ptr, "number_cuts");
+ else
+ numcuts= 1;
+
+ /* loop over all editable bones */
+ // XXX the old code did this in reverse order though!
+ CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
+ {
+ for (i=numcuts+1; i>1; i--) {
+ /* compute cut ratio first */
+ float cutratio= 1.0f / (float)i;
+ float cutratioI= 1.0f - cutratio;
+
+ float val1[3];
+ float val2[3];
+ float val3[3];
+
+ newbone= MEM_mallocN(sizeof(EditBone), "ebone subdiv");
+ *newbone = *ebone;
+ BLI_addtail(arm->edbo, newbone);
+
+ /* calculate location of newbone->head */
+ VECCOPY(val1, ebone->head);
+ VECCOPY(val2, ebone->tail);
+ VECCOPY(val3, newbone->head);
+
+ val3[0]= val1[0]*cutratio + val2[0]*cutratioI;
+ val3[1]= val1[1]*cutratio + val2[1]*cutratioI;
+ val3[2]= val1[2]*cutratio + val2[2]*cutratioI;
+
+ VECCOPY(newbone->head, val3);
+ VECCOPY(newbone->tail, ebone->tail);
+ VECCOPY(ebone->tail, newbone->head);
+
+ newbone->rad_head= 0.5f * (ebone->rad_head + ebone->rad_tail);
+ ebone->rad_tail= newbone->rad_head;
+
+ newbone->flag |= BONE_CONNECTED;
+
+ unique_editbone_name(arm->edbo, newbone->name, NULL);
+
+ /* correct parent bones */
+ for (tbone = arm->edbo->first; tbone; tbone=tbone->next) {
+ if (tbone->parent==ebone)
+ tbone->parent= newbone;
+ }
+ newbone->parent= ebone;
+ }
+ }
+ CTX_DATA_END;
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void ARMATURE_OT_subdivide_simple(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Subdivide Simple";
+ ot->idname= "ARMATURE_OT_subdivide_simple";
+
+ /* api callbacks */
+ ot->exec = armature_subdivide_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+void ARMATURE_OT_subdivide_multi(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Subdivide Multi";
+ ot->idname= "ARMATURE_OT_subdivide_multi";
+
+ /* api callbacks */
+ ot->exec = armature_subdivide_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* Properties */
+ RNA_def_int(ot->srna, "number_cuts", 2, 1, 10, "Number of Cuts", "", 1, INT_MAX);
+}
+
+
+
+static int armature_subdivs_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ uiMenuItem *head;
+
+ head= uiPupMenuBegin("Subdivision Type", 0);
+ uiMenuItemsEnumO(head, "ARMATURE_OT_subdivs", "type");
+ uiPupMenuEnd(C, head);
+
+ return OPERATOR_CANCELLED;
+}
+
+static int armature_subdivs_exec(bContext *C, wmOperator *op)
+{
+ switch (RNA_int_get(op->ptr, "type"))
+ {
+ case 0: /* simple */
+ RNA_int_set(op->ptr, "number_cuts", 1);
+ armature_subdivide_exec(C, op);
+ break;
+ case 1: /* multi */
+ armature_subdivide_exec(C, op);
+ break;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_subdivs(wmOperatorType *ot)
+{
+ static EnumPropertyItem type_items[]= {
+ {0, "SIMPLE", "Simple", ""},
+ {1, "MULTI", "Multi", ""},
+ {0, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "subdivs";
+ ot->idname= "ARMATURE_OT_subdivs";
+
+ /* api callbacks */
+ ot->invoke= armature_subdivs_invoke;
+ ot->exec= armature_subdivs_exec;
+
+ ot->poll= ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
+
+ /* this is temp, the ops are different, but they are called from subdivs, so all the possible props should be here as well*/
+ RNA_def_int(ot->srna, "number_cuts", 2, 1, 10, "Number of Cuts", "", 1, INT_MAX);
+}
+
+/* ----------- */
+
+/* Switch Direction operator:
+ * Currently, this does not use context loops, as context loops do not make it
+ * easy to retrieve any hierarchial/chain relationships which are necessary for
+ * this to be done easily.
+ */
+
+static int armature_switch_direction_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_edit_object(C);
+ bArmature *arm= (bArmature *)ob->data;
+ ListBase chains = {NULL, NULL};
+ LinkData *chain;
+
+ /* get chains of bones (ends on chains) */
+ chains_find_tips(arm->edbo, &chains);
+ if (chains.first == NULL) return OPERATOR_CANCELLED;
+
+ /* loop over chains, only considering selected and visible bones */
+ for (chain= chains.first; chain; chain= chain->next) {
+ EditBone *ebo, *child=NULL, *parent=NULL;
+
+ /* loop over bones in chain */
+ for (ebo= chain->data; ebo; ebo= parent) {
+ /* parent is this bone's original parent
+ * - we store this, as the next bone that is checked is this one
+ * but the value of ebo->parent may change here...
+ */
+ parent= ebo->parent;
+
+ /* only if selected and editable */
+ if (EBONE_VISIBLE(arm, ebo) && EBONE_EDITABLE(ebo)) {
+ /* swap head and tail coordinates */
+ SWAP(float, ebo->head[0], ebo->tail[0]);
+ SWAP(float, ebo->head[1], ebo->tail[1]);
+ SWAP(float, ebo->head[2], ebo->tail[2]);
+
+ /* do parent swapping:
+ * - use 'child' as new parent
+ * - connected flag is only set if points are coincidental
+ */
+ ebo->parent= child;
+ if ((child) && VecEqual(ebo->head, child->tail))
+ ebo->flag |= BONE_CONNECTED;
+ else
+ ebo->flag &= ~BONE_CONNECTED;
+
+ /* get next bones
+ * - child will become the new parent of next bone
+ */
+ child= ebo;
+ }
+ else {
+ /* not swapping this bone, however, if its 'parent' got swapped, unparent us from it
+ * as it will be facing in opposite direction
+ */
+ if ((parent) && (EBONE_VISIBLE(arm, parent) && EBONE_EDITABLE(parent))) {
+ ebo->parent= NULL;
+ ebo->flag &= ~BONE_CONNECTED;
+ }
+
+ /* get next bones
+ * - child will become new parent of next bone (not swapping occurred,
+ * so set to NULL to prevent infinite-loop)
+ */
+ child= NULL;
+ }
+ }
+ }
+
+ /* free chains */
+ BLI_freelistN(&chains);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_switch_direction(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Switch Direction";
+ ot->idname= "ARMATURE_OT_switch_direction";
+
+ /* api callbacks */
+ ot->exec = armature_switch_direction_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+/* ***************** Parenting *********************** */
+
+/* armature parenting options */
+#define ARM_PAR_CONNECT 1
+#define ARM_PAR_OFFSET 2
+
+/* check for null, before calling! */
+static void bone_connect_to_existing_parent(EditBone *bone)
+{
+ bone->flag |= BONE_CONNECTED;
+ VECCOPY(bone->head, bone->parent->tail);
+ bone->rad_head = bone->parent->rad_tail;
+}
+
+static void bone_connect_to_new_parent(ListBase *edbo, EditBone *selbone, EditBone *actbone, short mode)
+{
+ EditBone *ebone;
+ float offset[3];
+
+ if ((selbone->parent) && (selbone->flag & BONE_CONNECTED))
+ selbone->parent->flag &= ~(BONE_TIPSEL);
+
+ /* make actbone the parent of selbone */
+ selbone->parent= actbone;
+
+ /* in actbone tree we cannot have a loop */
+ for (ebone= actbone->parent; ebone; ebone= ebone->parent) {
+ if (ebone->parent==selbone) {
+ ebone->parent= NULL;
+ ebone->flag &= ~BONE_CONNECTED;
+ }
+ }
+
+ if (mode == ARM_PAR_CONNECT) {
+ /* Connected: Child bones will be moved to the parent tip */
+ selbone->flag |= BONE_CONNECTED;
+ VecSubf(offset, actbone->tail, selbone->head);
+
+ VECCOPY(selbone->head, actbone->tail);
+ selbone->rad_head= actbone->rad_tail;
+
+ VecAddf(selbone->tail, selbone->tail, offset);
+
+ /* offset for all its children */
+ for (ebone = edbo->first; ebone; ebone=ebone->next) {
+ EditBone *par;
+
+ for (par= ebone->parent; par; par= par->parent) {
+ if (par==selbone) {
+ VecAddf(ebone->head, ebone->head, offset);
+ VecAddf(ebone->tail, ebone->tail, offset);
+ break;
+ }
+ }
+ }
+ }
+ else {
+ /* Offset: Child bones will retain their distance from the parent tip */
+ selbone->flag &= ~BONE_CONNECTED;
+ }
+}
+
+static EnumPropertyItem prop_editarm_make_parent_types[] = {
+ {ARM_PAR_CONNECT, "CONNECTED", "Connected", ""},
+ {ARM_PAR_OFFSET, "OFFSET", "Keep Offset", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int armature_parent_set_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_edit_object(C);
+ bArmature *arm= (bArmature *)ob->data;
+ EditBone *actbone = CTX_data_active_bone(C);
+ EditBone *actmirb = NULL;
+ short val = RNA_enum_get(op->ptr, "type");
+
+ /* there must be an active bone */
+ if (actbone == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Operation requires an Active Bone");
+ return OPERATOR_CANCELLED;
+ }
+ else if (arm->flag & ARM_MIRROR_EDIT) {
+ /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
+ * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone
+ * (i.e. selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
+ * This is useful for arm-chains, for example parenting lower arm to upper arm
+ * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
+ * then just use actbone. Useful when doing upper arm to spine.
+ */
+ actmirb= ED_armature_bone_get_mirrored(arm->edbo, actbone);
+ if (actmirb == NULL)
+ actmirb= actbone;
+ }
+
+ /* if there is only 1 selected bone, we assume that that is the active bone,
+ * since a user will need to have clicked on a bone (thus selecting it) to make it active
+ */
+ if (CTX_DATA_COUNT(C, selected_editable_bones) <= 1) {
+ /* When only the active bone is selected, and it has a parent,
+ * connect it to the parent, as that is the only possible outcome.
+ */
+ if (actbone->parent) {
+ bone_connect_to_existing_parent(actbone);
+
+ if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
+ bone_connect_to_existing_parent(actmirb);
+ }
+ }
+ else {
+ /* Parent 'selected' bones to the active one
+ * - the context iterator contains both selected bones and their mirrored copies,
+ * so we assume that unselected bones are mirrored copies of some selected bone
+ * - since the active one (and/or its mirror) will also be selected, we also need
+ * to check that we are not trying to opearate on them, since such an operation
+ * would cause errors
+ */
+
+ /* parent selected bones to the active one */
+ CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
+ if (ELEM(ebone, actbone, actmirb) == 0) {
+ if (ebone->flag & BONE_SELECTED)
+ bone_connect_to_new_parent(arm->edbo, ebone, actbone, val);
+ else
+ bone_connect_to_new_parent(arm->edbo, ebone, actmirb, val);
+ }
+ }
+ CTX_DATA_END;
+ }
+
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int armature_parent_set_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ EditBone *actbone = CTX_data_active_bone(C);
+ uiMenuItem *head= uiPupMenuBegin("Make Parent ", 0);
+ int allchildbones = 0;
+
+ CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
+ if (ebone != actbone) {
+ if (ebone->parent != actbone) allchildbones= 1;
+ }
+ }
+ CTX_DATA_END;
+
+ uiMenuItemEnumO(head, "", 0, "ARMATURE_OT_parent_set", "type", ARM_PAR_CONNECT);
+
+ /* ob becomes parent, make the associated menus */
+ if (allchildbones)
+ uiMenuItemEnumO(head, "", 0, "ARMATURE_OT_parent_set", "type", ARM_PAR_OFFSET);
+
+ uiPupMenuEnd(C, head);
+
+ return OPERATOR_CANCELLED;
+}
+
+void ARMATURE_OT_parent_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Make Parent";
+ ot->idname= "ARMATURE_OT_parent_set";
+
+ /* api callbacks */
+ ot->invoke = armature_parent_set_invoke;
+ ot->exec = armature_parent_set_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", prop_editarm_make_parent_types, 0, "ParentType", "Type of parenting");
+}
+
+static EnumPropertyItem prop_editarm_clear_parent_types[] = {
+ {1, "CLEAR", "Clear Parent", ""},
+ {2, "DISCONNECT", "Disconnect Bone", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static void editbone_clear_parent(EditBone *ebone, int mode)
+{
+ if (ebone->parent) {
+ /* for nice selection */
+ ebone->parent->flag &= ~(BONE_TIPSEL);
+ }
+
+ if (mode==1) ebone->parent= NULL;
+ ebone->flag &= ~BONE_CONNECTED;
+}
+
+static int armature_parent_clear_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_edit_object(C);
+ bArmature *arm= (bArmature *)ob->data;
+ int val = RNA_enum_get(op->ptr, "type");
+
+ CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
+ editbone_clear_parent(ebone, val);
+ }
+ CTX_DATA_END;
+
+ armature_sync_selection(arm->edbo);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_parent_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Clear Parent";
+ ot->idname= "ARMATURE_OT_parent_clear";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = armature_parent_clear_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", prop_editarm_clear_parent_types, 0, "ClearType", "What way to clear parenting");
+}
+
+/* **************** Selections ******************/
+
+static int armature_select_invert_exec(bContext *C, wmOperator *op)
+{
+ /* Set the flags */
+ CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) {
+ /* select bone */
+ ebone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ ebone->flag &= ~BONE_ACTIVE;
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_select_invert(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Invert Selection";
+ ot->idname= "ARMATURE_OT_select_invert";
+
+ /* api callbacks */
+ ot->exec= armature_select_invert_exec;
+ ot->poll= ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+static int armature_de_select_all_exec(bContext *C, wmOperator *op)
+{
+ int sel=1;
+
+ /* Determine if there are any selected bones
+ And therefore whether we are selecting or deselecting */
+ if (CTX_DATA_COUNT(C, selected_bones) > 0) sel=0;
+
+ /* Set the flags */
+ CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) {
+ if (sel==1) {
+ /* select bone */
+ ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ if(ebone->parent)
+ ebone->parent->flag |= (BONE_TIPSEL);
+ }
+ else {
+ /* deselect bone */
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE);
+ }
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_select_all_toggle(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "deselect all editbone";
+ ot->idname= "ARMATURE_OT_select_all_toggle";
+
+ /* api callbacks */
+ ot->exec= armature_de_select_all_exec;
+ ot->poll= ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+
+/* ********************* select hierarchy operator ************** */
+
+static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Object *ob;
+ bArmature *arm;
+ EditBone *curbone, *pabone, *chbone;
+ int direction = RNA_enum_get(op->ptr, "direction");
+ int add_to_sel = RNA_boolean_get(op->ptr, "extend");
+
+ ob= obedit;
+ arm= (bArmature *)ob->data;
+
+ for (curbone= arm->edbo->first; curbone; curbone= curbone->next) {
+ if (EBONE_VISIBLE(arm, curbone)) {
+ if (curbone->flag & (BONE_ACTIVE)) {
+ if (direction == BONE_SELECT_PARENT) {
+ if (curbone->parent == NULL) continue;
+ else pabone = curbone->parent;
+
+ if (EBONE_VISIBLE(arm, pabone)) {
+ pabone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+ if (pabone->parent) pabone->parent->flag |= BONE_TIPSEL;
+
+ if (!add_to_sel) curbone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+ curbone->flag &= ~BONE_ACTIVE;
+ break;
+ }
+
+ }
+ else { // BONE_SELECT_CHILD
+ chbone = editbone_get_child(arm, curbone, 1);
+ if (chbone == NULL) continue;
+
+ if (EBONE_VISIBLE(arm, chbone)) {
+ chbone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+
+ if (!add_to_sel) {
+ curbone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL);
+ if (curbone->parent) curbone->parent->flag &= ~BONE_TIPSEL;
+ }
+ curbone->flag &= ~BONE_ACTIVE;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ armature_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
+{
+ static EnumPropertyItem direction_items[]= {
+ {BONE_SELECT_PARENT, "PARENT", "Select Parent", ""},
+ {BONE_SELECT_CHILD, "CHILD", "Select Child", ""},
+ {0, NULL, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name= "Select Hierarchy";
+ ot->idname= "ARMATURE_OT_select_hierarchy";
+
+ /* api callbacks */
+ ot->exec= armature_select_hierarchy_exec;
+ ot->poll= ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items,
+ BONE_SELECT_PARENT, "Direction", "");
+ RNA_def_boolean(ot->srna, "extend", 0, "Add to Selection", "");
+}
+
+/* ***************** EditBone Alignment ********************* */
+
+/* helper to fix a ebone position if its parent has moved due to alignment*/
+static void fix_connected_bone(EditBone *ebone)
+{
+ float diff[3];
+
+ if (!(ebone->parent) || !(ebone->flag & BONE_CONNECTED) || VecEqual(ebone->parent->tail, ebone->head))
+ return;
+
+ /* if the parent has moved we translate child's head and tail accordingly*/
+ VecSubf(diff, ebone->parent->tail, ebone->head);
+ VecAddf(ebone->head, ebone->head, diff);
+ VecAddf(ebone->tail, ebone->tail, diff);
+ return;
+}
+
+/* helper to recursively find chains of connected bones starting at ebone and fix their position */
+static void fix_editbone_connected_children(ListBase *edbo, EditBone *ebone)
+{
+ EditBone *selbone;
+
+ for (selbone = edbo->first; selbone; selbone=selbone->next) {
+ if ((selbone->parent) && (selbone->parent == ebone) && (selbone->flag & BONE_CONNECTED)) {
+ fix_connected_bone(selbone);
+ fix_editbone_connected_children(edbo, selbone);
+ }
+ }
+ return;
+}
+
+static void bone_align_to_bone(ListBase *edbo, EditBone *selbone, EditBone *actbone)
+{
+ float selboneaxis[3], actboneaxis[3], length;
+
+ VecSubf(actboneaxis, actbone->tail, actbone->head);
+ Normalize(actboneaxis);
+
+ VecSubf(selboneaxis, selbone->tail, selbone->head);
+ length = VecLength(selboneaxis);
+
+ VecMulf(actboneaxis, length);
+ VecAddf(selbone->tail, selbone->head, actboneaxis);
+ selbone->roll = actbone->roll;
+
+ /* if the bone being aligned has connected descendants they must be moved
+ according to their parent new position, otherwise they would be left
+ in an unconsistent state: connected but away from the parent*/
+ fix_editbone_connected_children(edbo, selbone);
+ return;
+}
+
+static int armature_align_bones_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_edit_object(C);
+ bArmature *arm= (bArmature *)ob->data;
+ EditBone *actbone= CTX_data_active_bone(C);
+ EditBone *actmirb= NULL;
+
+ /* there must be an active bone */
+ if (actbone == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Operation requires an Active Bone");
+ return OPERATOR_CANCELLED;
+ }
+ else if (arm->flag & ARM_MIRROR_EDIT) {
+ /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
+ * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone
+ * (i.e. selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
+ * This is useful for arm-chains, for example parenting lower arm to upper arm
+ * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
+ * then just use actbone. Useful when doing upper arm to spine.
+ */
+ actmirb= ED_armature_bone_get_mirrored(arm->edbo, actbone);
+ if (actmirb == NULL)
+ actmirb= actbone;
+ }
+
+ /* if there is only 1 selected bone, we assume that that is the active bone,
+ * since a user will need to have clicked on a bone (thus selecting it) to make it active
+ */
+ if (CTX_DATA_COUNT(C, selected_editable_bones) <= 1) {
+ /* When only the active bone is selected, and it has a parent,
+ * align it to the parent, as that is the only possible outcome.
+ */
+ if (actbone->parent) {
+ bone_align_to_bone(arm->edbo, actbone, actbone->parent);
+
+ if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
+ bone_align_to_bone(arm->edbo, actmirb, actmirb->parent);
+ }
+ }
+ else {
+ /* Align 'selected' bones to the active one
+ * - the context iterator contains both selected bones and their mirrored copies,
+ * so we assume that unselected bones are mirrored copies of some selected bone
+ * - since the active one (and/or its mirror) will also be selected, we also need
+ * to check that we are not trying to opearate on them, since such an operation
+ * would cause errors
+ */
+
+ /* align selected bones to the active one */
+ CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) {
+ if (ELEM(ebone, actbone, actmirb) == 0) {
+ if (ebone->flag & BONE_SELECTED)
+ bone_align_to_bone(arm->edbo, ebone, actbone);
+ else
+ bone_align_to_bone(arm->edbo, ebone, actmirb);
+ }
+ }
+ CTX_DATA_END;
+ }
+
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_bones_align(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Align Bones";
+ ot->idname= "ARMATURE_OT_bones_align";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = armature_align_bones_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ***************** Pose tools ********************* */
+
+/* helper for function below */
+static int clear_active_flag(Object *ob, Bone *bone, void *data)
+{
+ bone->flag &= ~BONE_ACTIVE;
+ return 0;
+}
+
+
+// XXX bone_looper is only to be used when we want to access settings (i.e. editability/visibility/selected) that context doesn't offer
+static int bone_looper(Object *ob, Bone *bone, void *data,
+ int (*bone_func)(Object *, Bone *, void *))
+{
+ /* We want to apply the function bone_func to every bone
+ * in an armature -- feed bone_looper the first bone and
+ * a pointer to the bone_func and watch it go!. The int count
+ * can be useful for counting bones with a certain property
+ * (e.g. skinnable)
+ */
+ int count = 0;
+
+ if (bone) {
+ /* only do bone_func if the bone is non null */
+ count += bone_func(ob, bone, data);
+
+ /* try to execute bone_func for the first child */
+ count += bone_looper(ob, bone->childbase.first, data, bone_func);
+
+ /* try to execute bone_func for the next bone at this
+ * depth of the recursion.
+ */
+ count += bone_looper(ob, bone->next, data, bone_func);
+ }
+
+ return count;
+}
+
+/* called from editview.c, for mode-less pose selection */
+/* assumes scene obact and basact is still on old situation */
+int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short extend)
+{
+ Object *ob= base->object;
+ Bone *nearBone;
+
+ if (!ob || !ob->pose) return 0;
+
+ nearBone= get_bone_from_selectbuffer(scene, base, buffer, hits, 1);
+
+ if (nearBone) {
+ bArmature *arm= ob->data;
+
+ /* since we do unified select, we don't shift+select a bone if the armature object was not active yet */
+ if (!(extend) || (base != scene->basact)) {
+ ED_pose_deselectall(ob, 0, 0);
+ nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE);
+
+ // XXX old cruft! use notifiers instead
+ //select_actionchannel_by_name(ob->action, nearBone->name, 1);
+ }
+ else {
+ if (nearBone->flag & BONE_SELECTED) {
+ /* if not active, we make it active */
+ if((nearBone->flag & BONE_ACTIVE)==0) {
+ bone_looper(ob, arm->bonebase.first, NULL, clear_active_flag);
+ nearBone->flag |= BONE_ACTIVE;
+ }
+ else {
+ nearBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE);
+
+ // XXX old cruft! use notifiers instead
+ //select_actionchannel_by_name(ob->action, nearBone->name, 0);
+ }
+ }
+ else {
+ bone_looper(ob, arm->bonebase.first, NULL, clear_active_flag);
+
+ nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE);
+
+ // XXX old cruft! use notifiers instead
+ //select_actionchannel_by_name(ob->action, nearBone->name, 1);
+ }
+ }
+
+ /* in weightpaint we select the associated vertex group too */
+ if (G.f & G_WEIGHTPAINT) {
+ if (nearBone->flag & BONE_ACTIVE) {
+ vertexgroup_select_by_name(OBACT, nearBone->name);
+ DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA);
+ }
+ }
+
+ }
+
+ return nearBone!=NULL;
+}
+
+/* test==0: deselect all
+ test==1: swap select (apply to all the opposite of current situation)
+ test==2: only clear active tag
+ test==3: swap select (no test / inverse selection status of all independently)
+*/
+void ED_pose_deselectall (Object *ob, int test, int doundo)
+{
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+ int selectmode= 0;
+
+ /* we call this from outliner too */
+ if (ELEM(NULL, ob, ob->pose)) return;
+
+ /* Determine if we're selecting or deselecting */
+ if (test==1) {
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ((pchan->bone->layer & arm->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) {
+ if (pchan->bone->flag & BONE_SELECTED)
+ break;
+ }
+ }
+
+ if (pchan == NULL)
+ selectmode= 1;
+ }
+ else if (test == 2)
+ selectmode= 2;
+
+ /* Set the flags accordingly */
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ((pchan->bone->layer & arm->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) {
+ if (test==3) {
+ pchan->bone->flag ^= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+ pchan->bone->flag &= ~BONE_ACTIVE;
+ }
+ else {
+ if (selectmode==0) pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE);
+ else if (selectmode==1) pchan->bone->flag |= BONE_SELECTED;
+ else pchan->bone->flag &= ~BONE_ACTIVE;
+ }
+ }
+ }
+
+ //countall(); // XXX need an equivalent to this...
+
+ if (doundo) {
+ if (selectmode==1) BIF_undo_push("Select All");
+ else BIF_undo_push("Deselect All");
+ }
+}
+
+static int bone_skinnable(Object *ob, Bone *bone, void *datap)
+{
+ /* Bones that are deforming
+ * are regarded to be "skinnable" and are eligible for
+ * auto-skinning.
+ *
+ * This function performs 2 functions:
+ *
+ * a) It returns 1 if the bone is skinnable.
+ * If we loop over all bones with this
+ * function, we can count the number of
+ * skinnable bones.
+ * b) If the pointer data is non null,
+ * it is treated like a handle to a
+ * bone pointer -- the bone pointer
+ * is set to point at this bone, and
+ * the pointer the handle points to
+ * is incremented to point to the
+ * next member of an array of pointers
+ * to bones. This way we can loop using
+ * this function to construct an array of
+ * pointers to bones that point to all
+ * skinnable bones.
+ */
+ Bone ***hbone;
+ int a, segments;
+ struct { Object *armob; void *list; int heat; } *data = datap;
+
+ if(!(G.f & G_WEIGHTPAINT) || !(bone->flag & BONE_HIDDEN_P)) {
+ if (!(bone->flag & BONE_NO_DEFORM)) {
+ if (data->heat && data->armob->pose && get_pose_channel(data->armob->pose, bone->name))
+ segments = bone->segments;
+ else
+ segments = 1;
+
+ if (data->list != NULL) {
+ hbone = (Bone ***) &data->list;
+
+ for (a=0; a<segments; a++) {
+ **hbone = bone;
+ ++*hbone;
+ }
+ }
+ return segments;
+ }
+ }
+ return 0;
+}
+
+static int add_defgroup_unique_bone(Object *ob, Bone *bone, void *data)
+{
+ /* This group creates a vertex group to ob that has the
+ * same name as bone (provided the bone is skinnable).
+ * If such a vertex group aleady exist the routine exits.
+ */
+ if (!(bone->flag & BONE_NO_DEFORM)) {
+ if (!get_named_vertexgroup(ob,bone->name)) {
+ add_defgroup_name(ob, bone->name);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int dgroup_skinnable(Object *ob, Bone *bone, void *datap)
+{
+ /* Bones that are deforming
+ * are regarded to be "skinnable" and are eligible for
+ * auto-skinning.
+ *
+ * This function performs 2 functions:
+ *
+ * a) If the bone is skinnable, it creates
+ * a vertex group for ob that has
+ * the name of the skinnable bone
+ * (if one doesn't exist already).
+ * b) If the pointer data is non null,
+ * it is treated like a handle to a
+ * bDeformGroup pointer -- the
+ * bDeformGroup pointer is set to point
+ * to the deform group with the bone's
+ * name, and the pointer the handle
+ * points to is incremented to point to the
+ * next member of an array of pointers
+ * to bDeformGroups. This way we can loop using
+ * this function to construct an array of
+ * pointers to bDeformGroups, all with names
+ * of skinnable bones.
+ */
+ bDeformGroup ***hgroup, *defgroup;
+ int a, segments;
+ struct { Object *armob; void *list; int heat; } *data= datap;
+
+ if (!(G.f & G_WEIGHTPAINT) || !(bone->flag & BONE_HIDDEN_P)) {
+ if (!(bone->flag & BONE_NO_DEFORM)) {
+ if (data->heat && data->armob->pose && get_pose_channel(data->armob->pose, bone->name))
+ segments = bone->segments;
+ else
+ segments = 1;
+
+ if (!(defgroup = get_named_vertexgroup(ob, bone->name)))
+ defgroup = add_defgroup_name(ob, bone->name);
+
+ if (data->list != NULL) {
+ hgroup = (bDeformGroup ***) &data->list;
+
+ for (a=0; a<segments; a++) {
+ **hgroup = defgroup;
+ ++*hgroup;
+ }
+ }
+ return segments;
+ }
+ }
+ return 0;
+}
+
+static void add_vgroups__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
+{
+ /* DerivedMesh mapFunc for getting final coords in weight paint mode */
+
+ float (*verts)[3] = userData;
+ VECCOPY(verts[index], co);
+}
+
+static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], int numbones, Bone **bonelist, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3], int *selected, float scale)
+{
+ /* Create vertex group weights from envelopes */
+
+ Bone *bone;
+ bDeformGroup *dgroup;
+ float distance;
+ int i, iflip, j;
+
+ /* for each vertex in the mesh */
+ for (i=0; i < mesh->totvert; i++) {
+ iflip = (dgroupflip)? mesh_get_x_mirror_vert(ob, i): 0;
+
+ /* for each skinnable bone */
+ for (j=0; j < numbones; ++j) {
+ if (!selected[j])
+ continue;
+
+ bone = bonelist[j];
+ dgroup = dgrouplist[j];
+
+ /* store the distance-factor from the vertex to the bone */
+ distance = distfactor_to_bone (verts[i], root[j], tip[j],
+ bone->rad_head * scale, bone->rad_tail * scale, bone->dist * scale);
+
+ /* add the vert to the deform group if weight!=0.0 */
+ if (distance!=0.0)
+ add_vert_to_defgroup (ob, dgroup, i, distance, WEIGHT_REPLACE);
+ else
+ remove_vert_defgroup (ob, dgroup, i);
+
+ /* do same for mirror */
+ if (dgroupflip && dgroupflip[j] && iflip >= 0) {
+ if (distance!=0.0)
+ add_vert_to_defgroup (ob, dgroupflip[j], iflip, distance,
+ WEIGHT_REPLACE);
+ else
+ remove_vert_defgroup (ob, dgroupflip[j], iflip);
+ }
+ }
+ }
+}
+
+void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int mirror)
+{
+ /* This functions implements the automatic computation of vertex group
+ * weights, either through envelopes or using a heat equilibrium.
+ *
+ * This function can be called both when parenting a mesh to an armature,
+ * or in weightpaint + posemode. In the latter case selection is taken
+ * into account and vertex weights can be mirrored.
+ *
+ * The mesh vertex positions used are either the final deformed coords
+ * from the derivedmesh in weightpaint mode, the final subsurf coords
+ * when parenting, or simply the original mesh coords.
+ */
+
+ bArmature *arm= par->data;
+ Bone **bonelist, *bone;
+ bDeformGroup **dgrouplist, **dgroupflip;
+ bDeformGroup *dgroup, *curdg;
+ bPoseChannel *pchan;
+ Mesh *mesh;
+ Mat4 *bbone = NULL;
+ float (*root)[3], (*tip)[3], (*verts)[3];
+ int *selected;
+ int numbones, vertsfilled = 0, i, j, segments = 0;
+ int wpmode = (G.f & G_WEIGHTPAINT);
+ struct { Object *armob; void *list; int heat; } looper_data;
+
+ looper_data.armob = par;
+ looper_data.heat= heat;
+ looper_data.list= NULL;
+
+ /* count the number of skinnable bones */
+ numbones = bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable);
+
+ if (numbones == 0)
+ return;
+
+ /* create an array of pointer to bones that are skinnable
+ * and fill it with all of the skinnable bones */
+ bonelist = MEM_callocN(numbones*sizeof(Bone *), "bonelist");
+ looper_data.list= bonelist;
+ bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable);
+
+ /* create an array of pointers to the deform groups that
+ * coorespond to the skinnable bones (creating them
+ * as necessary. */
+ dgrouplist = MEM_callocN(numbones*sizeof(bDeformGroup *), "dgrouplist");
+ dgroupflip = MEM_callocN(numbones*sizeof(bDeformGroup *), "dgroupflip");
+
+ looper_data.list= dgrouplist;
+ bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable);
+
+ /* create an array of root and tip positions transformed into
+ * global coords */
+ root = MEM_callocN(numbones*sizeof(float)*3, "root");
+ tip = MEM_callocN(numbones*sizeof(float)*3, "tip");
+ selected = MEM_callocN(numbones*sizeof(int), "selected");
+
+ for (j=0; j < numbones; ++j) {
+ bone = bonelist[j];
+ dgroup = dgrouplist[j];
+
+ /* handle bbone */
+ if (heat) {
+ if (segments == 0) {
+ segments = 1;
+ bbone = NULL;
+
+ if ((par->pose) && (pchan=get_pose_channel(par->pose, bone->name))) {
+ if (bone->segments > 1) {
+ segments = bone->segments;
+ bbone = b_bone_spline_setup(pchan, 1);
+ }
+ }
+ }
+
+ segments--;
+ }
+
+ /* compute root and tip */
+ if (bbone) {
+ VECCOPY(root[j], bbone[segments].mat[3]);
+ Mat4MulVecfl(bone->arm_mat, root[j]);
+ if ((segments+1) < bone->segments) {
+ VECCOPY(tip[j], bbone[segments+1].mat[3])
+ Mat4MulVecfl(bone->arm_mat, tip[j]);
+ }
+ else
+ VECCOPY(tip[j], bone->arm_tail)
+ }
+ else {
+ VECCOPY(root[j], bone->arm_head);
+ VECCOPY(tip[j], bone->arm_tail);
+ }
+
+ Mat4MulVecfl(par->obmat, root[j]);
+ Mat4MulVecfl(par->obmat, tip[j]);
+
+ /* set selected */
+ if (wpmode) {
+ if ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))
+ selected[j] = 1;
+ }
+ else
+ selected[j] = 1;
+
+ /* find flipped group */
+ if (mirror) {
+ char name[32];
+
+ BLI_strncpy(name, dgroup->name, 32);
+ // 0 = don't strip off number extensions
+ bone_flip_name(name, 0);
+
+ for (curdg = ob->defbase.first; curdg; curdg=curdg->next) {
+ if (!strcmp(curdg->name, name))
+ break;
+ }
+
+ dgroupflip[j] = curdg;
+ }
+ }
+
+ /* create verts */
+ mesh = (Mesh*)ob->data;
+ verts = MEM_callocN(mesh->totvert*sizeof(*verts), "closestboneverts");
+
+ if (wpmode) {
+ /* if in weight paint mode, use final verts from derivedmesh */
+ DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+
+ if (dm->foreachMappedVert) {
+ dm->foreachMappedVert(dm, add_vgroups__mapFunc, (void*)verts);
+ vertsfilled = 1;
+ }
+
+ dm->release(dm);
+ }
+ else if (modifiers_findByType(ob, eModifierType_Subsurf)) {
+ /* is subsurf on? Lets use the verts on the limit surface then.
+ * = same amount of vertices as mesh, but vertices moved to the
+ * subsurfed position, like for 'optimal'. */
+ subsurf_calculate_limit_positions(mesh, verts);
+ vertsfilled = 1;
+ }
+
+ /* transform verts to global space */
+ for (i=0; i < mesh->totvert; i++) {
+ if (!vertsfilled)
+ VECCOPY(verts[i], mesh->mvert[i].co)
+ Mat4MulVecfl(ob->obmat, verts[i]);
+ }
+
+ /* compute the weights based on gathered vertices and bones */
+ if (heat) {
+ heat_bone_weighting(ob, mesh, verts, numbones, dgrouplist, dgroupflip,
+ root, tip, selected);
+ }
+ else {
+ envelope_bone_weighting(ob, mesh, verts, numbones, bonelist, dgrouplist,
+ dgroupflip, root, tip, selected, Mat4ToScalef(par->obmat));
+ }
+
+ /* free the memory allocated */
+ MEM_freeN(bonelist);
+ MEM_freeN(dgrouplist);
+ MEM_freeN(dgroupflip);
+ MEM_freeN(root);
+ MEM_freeN(tip);
+ MEM_freeN(selected);
+ MEM_freeN(verts);
+}
+
+void create_vgroups_from_armature(Scene *scene, Object *ob, Object *par)
+{
+ /* Lets try to create some vertex groups
+ * based on the bones of the parent armature.
+ */
+ bArmature *arm= par->data;
+ short mode;
+
+ /* Prompt the user on whether/how they want the vertex groups
+ * added to the child mesh */
+ mode= pupmenu("Create Vertex Groups? %t|"
+ "Don't Create Groups %x1|"
+ "Name Groups %x2|"
+ "Create From Envelopes %x3|"
+ "Create From Bone Heat %x4|");
+
+ mode= 3; // XXX
+
+ switch (mode) {
+ case 2:
+ /* Traverse the bone list, trying to create empty vertex
+ * groups cooresponding to the bone.
+ */
+ bone_looper(ob, arm->bonebase.first, NULL,
+ add_defgroup_unique_bone);
+ if (ob->type == OB_MESH)
+ create_dverts(ob->data);
+
+ break;
+
+ case 3:
+ case 4:
+ /* Traverse the bone list, trying to create vertex groups
+ * that are populated with the vertices for which the
+ * bone is closest.
+ */
+ add_verts_to_dgroups(scene, ob, par, (mode == 4), 0);
+ break;
+ }
+}
+/* ************* Clear Pose *****************************/
+
+static int pose_clear_scale_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+
+ /* only clear those channels that are not locked */
+ CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) {
+ if ((pchan->protectflag & OB_LOCK_SCALEX)==0)
+ pchan->size[0]= 1.0f;
+ if ((pchan->protectflag & OB_LOCK_SCALEY)==0)
+ pchan->size[1]= 1.0f;
+ if ((pchan->protectflag & OB_LOCK_SCALEZ)==0)
+ pchan->size[2]= 1.0f;
+
+ /* the current values from IPO's may not be zero, so tag as unkeyed */
+ //pchan->bone->flag |= BONE_UNKEYED;
+ }
+ CTX_DATA_END;
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_scale_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Clear Pose Scale";
+ ot->idname= "POSE_OT_scale_clear";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = pose_clear_scale_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int pose_clear_loc_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+
+ /* only clear those channels that are not locked */
+ CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) {
+ if ((pchan->protectflag & OB_LOCK_LOCX)==0)
+ pchan->loc[0]= 0.0f;
+ if ((pchan->protectflag & OB_LOCK_LOCY)==0)
+ pchan->loc[1]= 0.0f;
+ if ((pchan->protectflag & OB_LOCK_LOCZ)==0)
+ pchan->loc[2]= 0.0f;
+
+ /* the current values from IPO's may not be zero, so tag as unkeyed */
+ //pchan->bone->flag |= BONE_UNKEYED;
+ }
+ CTX_DATA_END;
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_loc_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Clear Pose Location";
+ ot->idname= "POSE_OT_loc_clear";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = pose_clear_loc_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int pose_clear_rot_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+
+ /* only clear those channels that are not locked */
+ CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) {
+ if (pchan->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ)) {
+ float eul[3], oldeul[3], quat1[4];
+
+ if (pchan->rotmode == PCHAN_ROT_QUAT) {
+ QUATCOPY(quat1, pchan->quat);
+ QuatToEul(pchan->quat, oldeul);
+ }
+ else {
+ VECCOPY(oldeul, pchan->eul);
+ }
+ eul[0]= eul[1]= eul[2]= 0.0f;
+
+ if (pchan->protectflag & OB_LOCK_ROTX)
+ eul[0]= oldeul[0];
+ if (pchan->protectflag & OB_LOCK_ROTY)
+ eul[1]= oldeul[1];
+ if (pchan->protectflag & OB_LOCK_ROTZ)
+ eul[2]= oldeul[2];
+
+ if (pchan->rotmode == PCHAN_ROT_QUAT) {
+ EulToQuat(eul, pchan->quat);
+ /* quaternions flip w sign to accumulate rotations correctly */
+ if ((quat1[0]<0.0f && pchan->quat[0]>0.0f) || (quat1[0]>0.0f && pchan->quat[0]<0.0f)) {
+ QuatMulf(pchan->quat, -1.0f);
+ }
+ }
+ else {
+ VECCOPY(pchan->eul, eul);
+ }
+ }
+ else {
+ if (pchan->rotmode == PCHAN_ROT_QUAT) {
+ pchan->quat[1]=pchan->quat[2]=pchan->quat[3]= 0.0f;
+ pchan->quat[0]= 1.0f;
+ }
+ else {
+ pchan->eul[0]= pchan->eul[1]= pchan->eul[2]= 0.0f;
+ }
+ }
+
+ /* the current values from IPO's may not be zero, so tag as unkeyed */
+ //pchan->bone->flag |= BONE_UNKEYED;
+ }
+ CTX_DATA_END;
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_rot_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Clear Pose Rotation";
+ ot->idname= "POSE_OT_rot_clear";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = pose_clear_rot_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+
+/* ***************** selections ********************** */
+
+static int pose_select_invert_exec(bContext *C, wmOperator *op)
+{
+
+ /* Set the flags */
+ CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pchans) {
+ pchan->bone->flag ^= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+ pchan->bone->flag &= ~BONE_ACTIVE;
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_select_invert(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Invert Selection";
+ ot->idname= "POSE_OT_select_invert";
+
+ /* api callbacks */
+ ot->exec= pose_select_invert_exec;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+static int pose_de_select_all_exec(bContext *C, wmOperator *op)
+{
+ int sel=1;
+
+ /* Determine if there are any selected bones
+ And therefore whether we are selecting or deselecting */
+ if (CTX_DATA_COUNT(C, selected_pchans) > 0) sel=0;
+
+ /* Set the flags */
+ CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pchans) {
+ /* select pchan */
+ if (sel==0) pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE);
+ else pchan->bone->flag |= BONE_SELECTED;
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_select_all_toggle(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "deselect all bones";
+ ot->idname= "POSE_OT_select_all_toggle";
+
+ /* api callbacks */
+ ot->exec= pose_de_select_all_exec;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+
+static int pose_select_parent_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_active_object(C);
+ bPoseChannel *pchan,*parent;
+
+ /* Determine if there is an active bone */
+ pchan=CTX_data_active_pchan(C);
+ if (pchan) {
+ parent=pchan->parent;
+ if ((parent) && !(parent->bone->flag & BONE_HIDDEN_P)) {
+ parent->bone->flag |= BONE_SELECTED;
+ parent->bone->flag |= BONE_ACTIVE;
+ pchan->bone->flag &= ~BONE_ACTIVE;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_select_parent(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "select parent bone";
+ ot->idname= "POSE_OT_select_parent";
+
+ /* api callbacks */
+ ot->exec= pose_select_parent_exec;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+
+/* ************* hide/unhide pose bones ******************* */
+
+static int hide_selected_pose_bone(Object *ob, Bone *bone, void *ptr)
+{
+ bArmature *arm= ob->data;
+
+ if (arm->layer & bone->layer) {
+ if (bone->flag & BONE_SELECTED) {
+ bone->flag |= BONE_HIDDEN_P;
+ bone->flag &= ~(BONE_SELECTED|BONE_ACTIVE);
+ }
+ }
+ return 0;
+}
+
+static int hide_unselected_pose_bone(Object *ob, Bone *bone, void *ptr)
+{
+ bArmature *arm= ob->data;
+
+ if (arm->layer & bone->layer) {
+ // hrm... typo here?
+ if (~bone->flag & BONE_SELECTED) {
+ bone->flag |= BONE_HIDDEN_P;
+ bone->flag &= ~BONE_ACTIVE;
+ }
+ }
+ return 0;
+}
+
+/* active object is armature in posemode, poll checked */
+static int pose_hide_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_active_object(C);
+ bArmature *arm= ob->data;
+
+ if(RNA_boolean_get(op->ptr, "unselected"))
+ bone_looper(ob, arm->bonebase.first, NULL,
+ hide_unselected_pose_bone);
+ else
+ bone_looper(ob, arm->bonebase.first, NULL,
+ hide_selected_pose_bone);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_hide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Hide Selected";
+ ot->idname= "POSE_OT_hide";
+
+ /* api callbacks */
+ ot->exec= pose_hide_exec;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "");
+}
+
+static int show_pose_bone(Object *ob, Bone *bone, void *ptr)
+{
+ bArmature *arm= ob->data;
+
+ if (arm->layer & bone->layer) {
+ if (bone->flag & BONE_HIDDEN_P) {
+ bone->flag &= ~BONE_HIDDEN_P;
+ bone->flag |= BONE_SELECTED;
+ }
+ }
+
+ return 0;
+}
+
+/* active object is armature in posemode, poll checked */
+static int pose_reveal_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_active_object(C);
+ bArmature *arm= ob->data;
+
+ bone_looper(ob, arm->bonebase.first, NULL, show_pose_bone);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_reveal(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Reveal Selected";
+ ot->idname= "POSE_OT_reveal";
+
+ /* api callbacks */
+ ot->exec= pose_reveal_exec;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ************* RENAMING DISASTERS ************ */
+
+/* note: there's a unique_editbone_name() too! */
+void unique_bone_name (bArmature *arm, char *name)
+{
+ char tempname[64];
+ int number;
+ char *dot;
+
+ if (get_named_bone(arm, name)) {
+
+ /* Strip off the suffix, if it's a number */
+ number= strlen(name);
+ if(number && isdigit(name[number-1])) {
+ dot= strrchr(name, '.'); // last occurrance
+ if (dot)
+ *dot=0;
+ }
+
+ for (number = 1; number <=999; number++) {
+ sprintf (tempname, "%s.%03d", name, number);
+ if (!get_named_bone(arm, tempname)) {
+ BLI_strncpy (name, tempname, 32);
+ return;
+ }
+ }
+ }
+}
+
+#define MAXBONENAME 32
+/* helper call for armature_bone_rename */
+static void constraint_bone_name_fix(Object *ob, ListBase *conlist, char *oldname, char *newname)
+{
+ bConstraint *curcon;
+ bConstraintTarget *ct;
+
+ for (curcon = conlist->first; curcon; curcon=curcon->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon);
+ ListBase targets = {NULL, NULL};
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(curcon, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ if (ct->tar == ob) {
+ if (!strcmp(ct->subtarget, oldname) )
+ BLI_strncpy(ct->subtarget, newname, MAXBONENAME);
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(curcon, &targets, 0);
+ }
+ }
+}
+
+/* called by UI for renaming a bone */
+/* warning: make sure the original bone was not renamed yet! */
+/* seems messy, but thats what you get with not using pointers but channel names :) */
+void armature_bone_rename(Object *ob, char *oldnamep, char *newnamep)
+{
+ bArmature *arm= ob->data;
+ char newname[MAXBONENAME];
+ char oldname[MAXBONENAME];
+
+ /* names better differ! */
+ if(strncmp(oldnamep, newnamep, MAXBONENAME)) {
+
+ /* we alter newname string... so make copy */
+ BLI_strncpy(newname, newnamep, MAXBONENAME);
+ /* we use oldname for search... so make copy */
+ BLI_strncpy(oldname, oldnamep, MAXBONENAME);
+
+ /* now check if we're in editmode, we need to find the unique name */
+ if (arm->edbo) {
+ EditBone *eBone;
+
+ eBone= editbone_name_exists(arm->edbo, oldname);
+ if (eBone) {
+ unique_editbone_name(arm->edbo, newname, NULL);
+ BLI_strncpy(eBone->name, newname, MAXBONENAME);
+ }
+ else return;
+ }
+ else {
+ Bone *bone= get_named_bone(arm, oldname);
+
+ if (bone) {
+ unique_bone_name (arm, newname);
+ BLI_strncpy(bone->name, newname, MAXBONENAME);
+ }
+ else return;
+ }
+
+ /* do entire dbase - objects */
+ for (ob= G.main->object.first; ob; ob= ob->id.next) {
+ /* we have the object using the armature */
+ if (arm==ob->data) {
+ Object *cob;
+ //bAction *act;
+ //bActionChannel *achan;
+ //bActionStrip *strip;
+
+ /* Rename action channel if necessary */
+#if 0 // XXX old animation system
+ act = ob->action;
+ if (act && !act->id.lib) {
+ /* Find the appropriate channel */
+ achan= get_action_channel(act, oldname);
+ if (achan)
+ BLI_strncpy(achan->name, newname, MAXBONENAME);
+ }
+#endif // XXX old animation system
+
+ /* Rename the pose channel, if it exists */
+ if (ob->pose) {
+ bPoseChannel *pchan = get_pose_channel(ob->pose, oldname);
+ if (pchan)
+ BLI_strncpy(pchan->name, newname, MAXBONENAME);
+ }
+
+ /* check all nla-strips too */
+#if 0 // XXX old animation system
+ for (strip= ob->nlastrips.first; strip; strip= strip->next) {
+ /* Rename action channel if necessary */
+ act = strip->act;
+ if (act && !act->id.lib) {
+ /* Find the appropriate channel */
+ achan= get_action_channel(act, oldname);
+ if (achan)
+ BLI_strncpy(achan->name, newname, MAXBONENAME);
+ }
+ }
+#endif // XXX old animation system
+
+ /* Update any object constraints to use the new bone name */
+ for (cob= G.main->object.first; cob; cob= cob->id.next) {
+ if (cob->constraints.first)
+ constraint_bone_name_fix(ob, &cob->constraints, oldname, newname);
+ if (cob->pose) {
+ bPoseChannel *pchan;
+ for (pchan = cob->pose->chanbase.first; pchan; pchan=pchan->next) {
+ constraint_bone_name_fix(ob, &pchan->constraints, oldname, newname);
+ }
+ }
+ }
+ }
+
+ /* See if an object is parented to this armature */
+ if (ob->parent && (ob->parent->data == arm)) {
+ if (ob->partype==PARBONE) {
+ /* bone name in object */
+ if (!strcmp(ob->parsubstr, oldname))
+ BLI_strncpy(ob->parsubstr, newname, MAXBONENAME);
+ }
+ }
+
+ if (modifiers_usesArmature(ob, arm)) {
+ bDeformGroup *dg;
+ /* bone name in defgroup */
+ for (dg=ob->defbase.first; dg; dg=dg->next) {
+ if (!strcmp(dg->name, oldname))
+ BLI_strncpy(dg->name, newname, MAXBONENAME);
+ }
+ }
+ }
+
+ /* do entire db - ipo's for the drivers */
+#if 0 // XXX old animation system
+ for (ipo= G.main->ipo.first; ipo; ipo= ipo->id.next) {
+ IpoCurve *icu;
+
+ /* check each curve's driver */
+ for (icu= ipo->curve.first; icu; icu= icu->next) {
+ IpoDriver *icd= icu->driver;
+
+ if ((icd) && (icd->ob)) {
+ ob= icd->ob;
+
+ if (icu->driver->type == IPO_DRIVER_TYPE_NORMAL) {
+ if (!strcmp(oldname, icd->name))
+ BLI_strncpy(icd->name, newname, MAXBONENAME);
+ }
+ else {
+ /* TODO: pydrivers need to be treated differently */
+ }
+ }
+ }
+ }
+#endif // XXX old animation system
+ }
+}
+
+/* context editmode object */
+void armature_flip_names(Scene *scene)
+{
+ Object *obedit= scene->obedit; // XXX get from context
+ bArmature *arm= obedit->data;
+ EditBone *ebone;
+ char newname[32];
+
+ for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
+ if (arm->layer & ebone->layer) {
+ if (ebone->flag & BONE_SELECTED) {
+ BLI_strncpy(newname, ebone->name, sizeof(newname));
+ bone_flip_name(newname, 1); // 1 = do strip off number extensions
+ armature_bone_rename(obedit, ebone->name, newname);
+ }
+ }
+ }
+
+ BIF_undo_push("Flip names");
+}
+
+/* context: edtimode armature */
+void armature_autoside_names(Scene *scene, short axis)
+{
+ Object *obedit= scene->obedit; // XXX get from context
+ bArmature *arm= obedit->data;
+ EditBone *ebone;
+ char newname[32];
+
+ for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
+ if (arm->layer & ebone->layer) {
+ if (ebone->flag & BONE_SELECTED) {
+ BLI_strncpy(newname, ebone->name, sizeof(newname));
+ bone_autoside_name(newname, 1, axis, ebone->head[axis], ebone->tail[axis]);
+ armature_bone_rename(obedit, ebone->name, newname);
+ }
+ }
+ }
+
+ BIF_undo_push("Auto-side name");
+}
+
+/* if editbone (partial) selected, copy data */
+/* context; editmode armature, with mirror editing enabled */
+void transform_armature_mirror_update(Object *obedit)
+{
+ bArmature *arm= obedit->data;
+ EditBone *ebo, *eboflip;
+
+ for (ebo= arm->edbo->first; ebo; ebo=ebo->next) {
+ /* no layer check, correct mirror is more important */
+ if (ebo->flag & (BONE_TIPSEL|BONE_ROOTSEL)) {
+ eboflip= ED_armature_bone_get_mirrored(arm->edbo, ebo);
+
+ if (eboflip) {
+ /* we assume X-axis flipping for now */
+ if (ebo->flag & BONE_TIPSEL) {
+ EditBone *children;
+
+ eboflip->tail[0]= -ebo->tail[0];
+ eboflip->tail[1]= ebo->tail[1];
+ eboflip->tail[2]= ebo->tail[2];
+ eboflip->rad_tail= ebo->rad_tail;
+
+ /* Also move connected children, in case children's name aren't mirrored properly */
+ for (children=arm->edbo->first; children; children=children->next) {
+ if (children->parent == eboflip && children->flag & BONE_CONNECTED) {
+ VECCOPY(children->head, eboflip->tail);
+ children->rad_head = ebo->rad_tail;
+ }
+ }
+ }
+ if (ebo->flag & BONE_ROOTSEL) {
+ eboflip->head[0]= -ebo->head[0];
+ eboflip->head[1]= ebo->head[1];
+ eboflip->head[2]= ebo->head[2];
+ eboflip->rad_head= ebo->rad_head;
+
+ /* Also move connected parent, in case parent's name isn't mirrored properly */
+ if (eboflip->parent && eboflip->flag & BONE_CONNECTED)
+ {
+ EditBone *parent = eboflip->parent;
+ VECCOPY(parent->tail, eboflip->head);
+ parent->rad_tail = ebo->rad_head;
+ }
+ }
+ if (ebo->flag & BONE_SELECTED) {
+ eboflip->dist= ebo->dist;
+ eboflip->roll= -ebo->roll;
+ eboflip->xwidth= ebo->xwidth;
+ eboflip->zwidth= ebo->zwidth;
+ }
+ }
+ }
+ }
+}
+
+
+/*****************************************************************************************************/
+/*************************************** SKELETON GENERATOR ******************************************/
+/*****************************************************************************************************/
+
+#if 0
+
+/**************************************** SUBDIVISION ALGOS ******************************************/
+
+EditBone * subdivideByAngle(Scene *scene, Object *obedit, ReebArc *arc, ReebNode *head, ReebNode *tail)
+{
+ bArmature *arm= obedit->data;
+ EditBone *lastBone = NULL;
+
+ if (scene->toolsettings->skgen_options & SKGEN_CUT_ANGLE)
+ {
+ ReebArcIterator arc_iter;
+ BArcIterator *iter = (BArcIterator*)&arc_iter;
+ float *previous = NULL, *current = NULL;
+ EditBone *child = NULL;
+ EditBone *parent = NULL;
+ EditBone *root = NULL;
+ float angleLimit = (float)cos(scene->toolsettings->skgen_angle_limit * M_PI / 180.0f);
+
+ parent = add_editbone(obedit, "Bone");
+ parent->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
+ VECCOPY(parent->head, head->p);
+
+ root = parent;
+
+ initArcIterator(iter, arc, head);
+ IT_next(iter);
+ previous = iter->p;
+
+ for (IT_next(iter);
+ IT_stopped(iter) == 0;
+ previous = iter->p, IT_next(iter))
+ {
+ float vec1[3], vec2[3];
+ float len1, len2;
+
+ current = iter->p;
+
+ VecSubf(vec1, previous, parent->head);
+ VecSubf(vec2, current, previous);
+
+ len1 = Normalize(vec1);
+ len2 = Normalize(vec2);
+
+ if (len1 > 0.0f && len2 > 0.0f && Inpf(vec1, vec2) < angleLimit)
+ {
+ VECCOPY(parent->tail, previous);
+
+ child = add_editbone(obedit, "Bone");
+ VECCOPY(child->head, parent->tail);
+ child->parent = parent;
+ child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
+
+ parent = child; /* new child is next parent */
+ }
+ }
+ VECCOPY(parent->tail, tail->p);
+
+ /* If the bone wasn't subdivided, delete it and return NULL
+ * to let subsequent subdivision methods do their thing.
+ * */
+ if (parent == root)
+ {
+ delete_bone(arm->edbo, parent);
+ parent = NULL;
+ }
+
+ lastBone = parent; /* set last bone in the chain */
+ }
+
+ return lastBone;
+}
+
+EditBone * test_subdivideByCorrelation(Scene *scene, Object *obedit, ReebArc *arc, ReebNode *head, ReebNode *tail)
+{
+ EditBone *lastBone = NULL;
+
+ if (scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION)
+ {
+ float invmat[4][4] = { {1, 0, 0, 0},
+ {0, 1, 0, 0},
+ {0, 0, 1, 0},
+ {0, 0, 0, 1}};
+ float tmat[3][3] = { {1, 0, 0},
+ {0, 1, 0},
+ {0, 0, 1}};
+ ReebArcIterator arc_iter;
+ BArcIterator *iter = (BArcIterator*)&arc_iter;
+ bArmature *arm= obedit->data;
+
+ initArcIterator(iter, arc, head);
+
+ lastBone = subdivideArcBy(arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
+ }
+
+ return lastBone;
+}
+
+float arcLengthRatio(ReebArc *arc)
+{
+ float arcLength = 0.0f;
+ float embedLength = 0.0f;
+ int i;
+
+ arcLength = VecLenf(arc->head->p, arc->tail->p);
+
+ if (arc->bcount > 0)
+ {
+ /* Add the embedding */
+ for ( i = 1; i < arc->bcount; i++)
+ {
+ embedLength += VecLenf(arc->buckets[i - 1].p, arc->buckets[i].p);
+ }
+ /* Add head and tail -> embedding vectors */
+ embedLength += VecLenf(arc->head->p, arc->buckets[0].p);
+ embedLength += VecLenf(arc->tail->p, arc->buckets[arc->bcount - 1].p);
+ }
+ else
+ {
+ embedLength = arcLength;
+ }
+
+ return embedLength / arcLength;
+}
+
+EditBone * test_subdivideByLength(Scene *scene, Object *obedit, ReebArc *arc, ReebNode *head, ReebNode *tail)
+{
+ EditBone *lastBone = NULL;
+ if ((scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) &&
+ arcLengthRatio(arc) >= G.scene->toolsettings->skgen_length_ratio)
+ {
+ float invmat[4][4] = { {1, 0, 0, 0},
+ {0, 1, 0, 0},
+ {0, 0, 1, 0},
+ {0, 0, 0, 1}};
+ float tmat[3][3] = { {1, 0, 0},
+ {0, 1, 0},
+ {0, 0, 1}};
+ ReebArcIterator arc_iter;
+ BArcIterator *iter = (BArcIterator*)&arc_iter;
+ bArmature *arm= obedit->data;
+
+ initArcIterator(iter, arc, head);
+
+ lastBone = subdivideArcBy(arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision);
+ }
+
+ return lastBone;
+}
+
+/***************************************** MAIN ALGORITHM ********************************************/
+
+void generateSkeletonFromReebGraph(Scene *scene, ReebGraph *rg)
+{
+ Object *obedit= scene->obedit; // XXX get from context
+ GHash *arcBoneMap = NULL;
+ ReebArc *arc = NULL;
+ ReebNode *node = NULL;
+ Object *src = NULL;
+ Object *dst = NULL;
+
+ src = scene->basact->object;
+
+ if (obedit != NULL)
+ {
+ ED_armature_from_edit(scene, obedit);
+ ED_armature_edit_free(obedit);
+ }
+
+ dst = add_object(scene, OB_ARMATURE);
+ ED_object_base_init_from_view(NULL, scene->basact); // XXX NULL is C
+ obedit= scene->basact->object;
+
+ /* Copy orientation from source */
+ VECCOPY(dst->loc, src->obmat[3]);
+ Mat4ToEul(src->obmat, dst->rot);
+ Mat4ToSize(src->obmat, dst->size);
+
+ where_is_object(scene, obedit);
+
+ ED_armature_to_edit(obedit);
+
+ arcBoneMap = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ BLI_markdownSymmetry((BGraph*)rg, rg->nodes.first, scene->toolsettings->skgen_symmetry_limit);
+
+ for (arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ EditBone *lastBone = NULL;
+ ReebNode *head, *tail;
+ int i;
+
+ /* Find out the direction of the arc through simple heuristics (in order of priority) :
+ *
+ * 1- Arcs on primary symmetry axis (symmetry == 1) point up (head: high weight -> tail: low weight)
+ * 2- Arcs starting on a primary axis point away from it (head: node on primary axis)
+ * 3- Arcs point down (head: low weight -> tail: high weight)
+ *
+ * Finally, the arc direction is stored in its flag: 1 (low -> high), -1 (high -> low)
+ */
+
+ /* if arc is a symmetry axis, internal bones go up the tree */
+ if (arc->symmetry_level == 1 && arc->tail->degree != 1)
+ {
+ head = arc->tail;
+ tail = arc->head;
+
+ arc->flag = -1; /* mark arc direction */
+ }
+ /* Bones point AWAY from the symmetry axis */
+ else if (arc->head->symmetry_level == 1)
+ {
+ head = arc->head;
+ tail = arc->tail;
+
+ arc->flag = 1; /* mark arc direction */
+ }
+ else if (arc->tail->symmetry_level == 1)
+ {
+ head = arc->tail;
+ tail = arc->head;
+
+ arc->flag = -1; /* mark arc direction */
+ }
+ /* otherwise, always go from low weight to high weight */
+ else
+ {
+ head = arc->head;
+ tail = arc->tail;
+
+ arc->flag = 1; /* mark arc direction */
+ }
+
+ /* Loop over subdivision methods */
+ for (i = 0; lastBone == NULL && i < SKGEN_SUB_TOTAL; i++)
+ {
+ switch(scene->toolsettings->skgen_subdivisions[i])
+ {
+ case SKGEN_SUB_LENGTH:
+ lastBone = test_subdivideByLength(scene, obedit, arc, head, tail);
+ break;
+ case SKGEN_SUB_ANGLE:
+ lastBone = subdivideByAngle(scene, obedit, arc, head, tail);
+ break;
+ case SKGEN_SUB_CORRELATION:
+ lastBone = test_subdivideByCorrelation(scene, obedit, arc, head, tail);
+ break;
+ }
+ }
+
+ if (lastBone == NULL)
+ {
+ EditBone *bone;
+ bone = add_editbone(obedit, "Bone");
+ bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
+
+ VECCOPY(bone->head, head->p);
+ VECCOPY(bone->tail, tail->p);
+
+ /* set first and last bone, since there's only one */
+ lastBone = bone;
+ }
+
+ BLI_ghash_insert(arcBoneMap, arc, lastBone);
+ }
+
+ /* Second pass, setup parent relationship between arcs */
+ for (node = rg->nodes.first; node; node = node->next)
+ {
+ ReebArc *incomingArc = NULL;
+ int i;
+
+ for (i = 0; i < node->degree; i++)
+ {
+ arc = (ReebArc*)node->arcs[i];
+
+ /* if arc is incoming into the node */
+ if ((arc->head == node && arc->flag == -1) || (arc->tail == node && arc->flag == 1))
+ {
+ if (incomingArc == NULL)
+ {
+ incomingArc = arc;
+ /* loop further to make sure there's only one incoming arc */
+ }
+ else
+ {
+ /* skip this node if more than one incomingArc */
+ incomingArc = NULL;
+ break; /* No need to look further, we are skipping already */
+ }
+ }
+ }
+
+ if (incomingArc != NULL)
+ {
+ EditBone *parentBone = BLI_ghash_lookup(arcBoneMap, incomingArc);
+
+ /* Look for outgoing arcs and parent their bones */
+ for (i = 0; i < node->degree; i++)
+ {
+ arc = node->arcs[i];
+
+ /* if arc is outgoing from the node */
+ if ((arc->head == node && arc->flag == 1) || (arc->tail == node && arc->flag == -1))
+ {
+ EditBone *childBone = BLI_ghash_lookup(arcBoneMap, arc);
+
+ /* find the root bone */
+ while(childBone->parent != NULL)
+ {
+ childBone = childBone->parent;
+ }
+
+ childBone->parent = parentBone;
+ childBone->flag |= BONE_CONNECTED;
+ }
+ }
+ }
+ }
+
+ BLI_ghash_free(arcBoneMap, NULL, NULL);
+
+ BIF_undo_push("Generate Skeleton");
+}
+
+void generateSkeleton(Scene *scene)
+{
+ ReebGraph *reebg;
+
+// setcursor_space(SPACE_VIEW3D, CURSOR_WAIT);
+
+ reebg = BIF_ReebGraphFromEditMesh();
+
+ generateSkeletonFromReebGraph(scene, reebg);
+
+ REEB_freeGraph(reebg);
+
+ //setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
+}
+
+#endif
diff --git a/source/blender/editors/armature/editarmature_generate.c b/source/blender/editors/armature/editarmature_generate.c
new file mode 100644
index 00000000000..6d271375c64
--- /dev/null
+++ b/source/blender/editors/armature/editarmature_generate.c
@@ -0,0 +1,329 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * editarmature.c: Interface for creating and posing armature objects
+ */
+
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_scene_types.h"
+#include "DNA_armature_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_graph.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_context.h"
+
+#include "ED_armature.h"
+#include "armature_intern.h"
+#include "BIF_generate.h"
+
+void setBoneRollFromNormal(EditBone *bone, float *no, float invmat[][4], float tmat[][3])
+{
+ if (no != NULL && !VecIsNull(no))
+ {
+ float tangent[3], vec[3], normal[3];
+
+ VECCOPY(normal, no);
+ Mat3MulVecfl(tmat, normal);
+
+ VecSubf(tangent, bone->tail, bone->head);
+ Projf(vec, tangent, normal);
+ VecSubf(normal, normal, vec);
+
+ Normalize(normal);
+
+ bone->roll = ED_rollBoneToVector(bone, normal);
+ }
+}
+
+float calcArcCorrelation(BArcIterator *iter, int start, int end, float v0[3], float n[3])
+{
+ int len = 2 + abs(end - start);
+
+ if (len > 2)
+ {
+ float avg_t = 0.0f;
+ float s_t = 0.0f;
+ float s_xyz = 0.0f;
+ int i;
+
+ /* First pass, calculate average */
+ for (i = start; i <= end; i++)
+ {
+ float v[3];
+
+ IT_peek(iter, i);
+ VecSubf(v, iter->p, v0);
+ avg_t += Inpf(v, n);
+ }
+
+ avg_t /= Inpf(n, n);
+ avg_t += 1.0f; /* adding start (0) and end (1) values */
+ avg_t /= len;
+
+ /* Second pass, calculate s_xyz and s_t */
+ for (i = start; i <= end; i++)
+ {
+ float v[3], d[3];
+ float dt;
+
+ IT_peek(iter, i);
+ VecSubf(v, iter->p, v0);
+ Projf(d, v, n);
+ VecSubf(v, v, d);
+
+ dt = VecLength(d) - avg_t;
+
+ s_t += dt * dt;
+ s_xyz += Inpf(v, v);
+ }
+
+ /* adding start(0) and end(1) values to s_t */
+ s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t);
+
+ return 1.0f - s_xyz / s_t;
+ }
+ else
+ {
+ return 1.0f;
+ }
+}
+
+int nextFixedSubdivision(ToolSettings *toolsettings, BArcIterator *iter, int start, int end, float head[3], float p[3])
+{
+ static float stroke_length = 0;
+ static float current_length;
+ static char n;
+ float *v1, *v2;
+ float length_threshold;
+ int i;
+
+ if (stroke_length == 0)
+ {
+ current_length = 0;
+
+ IT_peek(iter, start);
+ v1 = iter->p;
+
+ for (i = start + 1; i <= end; i++)
+ {
+ IT_peek(iter, i);
+ v2 = iter->p;
+
+ stroke_length += VecLenf(v1, v2);
+
+ v1 = v2;
+ }
+
+ n = 0;
+ current_length = 0;
+ }
+
+ n++;
+
+ length_threshold = n * stroke_length / toolsettings->skgen_subdivision_number;
+
+ IT_peek(iter, start);
+ v1 = iter->p;
+
+ /* < and not <= because we don't care about end, it is P_EXACT anyway */
+ for (i = start + 1; i < end; i++)
+ {
+ IT_peek(iter, i);
+ v2 = iter->p;
+
+ current_length += VecLenf(v1, v2);
+
+ if (current_length >= length_threshold)
+ {
+ VECCOPY(p, v2);
+ return i;
+ }
+
+ v1 = v2;
+ }
+
+ stroke_length = 0;
+
+ return -1;
+}
+int nextAdaptativeSubdivision(ToolSettings *toolsettings, BArcIterator *iter, int start, int end, float head[3], float p[3])
+{
+ float correlation_threshold = toolsettings->skgen_correlation_limit;
+ float *start_p;
+ float n[3];
+ int i;
+
+ IT_peek(iter, start);
+ start_p = iter->p;
+
+ for (i = start + 2; i <= end; i++)
+ {
+ /* Calculate normal */
+ IT_peek(iter, i);
+ VecSubf(n, iter->p, head);
+
+ if (calcArcCorrelation(iter, start, i, start_p, n) < correlation_threshold)
+ {
+ IT_peek(iter, i - 1);
+ VECCOPY(p, iter->p);
+ return i - 1;
+ }
+ }
+
+ return -1;
+}
+
+int nextLengthSubdivision(ToolSettings *toolsettings, BArcIterator *iter, int start, int end, float head[3], float p[3])
+{
+ float lengthLimit = toolsettings->skgen_length_limit;
+ int same = 1;
+ int i;
+
+ i = start + 1;
+ while (i <= end)
+ {
+ float *vec0;
+ float *vec1;
+
+ IT_peek(iter, i - 1);
+ vec0 = iter->p;
+
+ IT_peek(iter, i);
+ vec1 = iter->p;
+
+ /* If lengthLimit hits the current segment */
+ if (VecLenf(vec1, head) > lengthLimit)
+ {
+ if (same == 0)
+ {
+ float dv[3], off[3];
+ float a, b, c, f;
+
+ /* Solve quadratic distance equation */
+ VecSubf(dv, vec1, vec0);
+ a = Inpf(dv, dv);
+
+ VecSubf(off, vec0, head);
+ b = 2 * Inpf(dv, off);
+
+ c = Inpf(off, off) - (lengthLimit * lengthLimit);
+
+ f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a);
+
+ //printf("a %f, b %f, c %f, f %f\n", a, b, c, f);
+
+ if (isnan(f) == 0 && f < 1.0f)
+ {
+ VECCOPY(p, dv);
+ VecMulf(p, f);
+ VecAddf(p, p, vec0);
+ }
+ else
+ {
+ VECCOPY(p, vec1);
+ }
+ }
+ else
+ {
+ float dv[3];
+
+ VecSubf(dv, vec1, vec0);
+ Normalize(dv);
+
+ VECCOPY(p, dv);
+ VecMulf(p, lengthLimit);
+ VecAddf(p, p, head);
+ }
+
+ return i - 1; /* restart at lower bound */
+ }
+ else
+ {
+ i++;
+ same = 0; // Reset same
+ }
+ }
+
+ return -1;
+}
+
+EditBone * subdivideArcBy(ToolSettings *toolsettings, bArmature *arm, ListBase *editbones, BArcIterator *iter, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion)
+{
+ EditBone *lastBone = NULL;
+ EditBone *child = NULL;
+ EditBone *parent = NULL;
+ int bone_start = 0;
+ int end = iter->length;
+ int index;
+
+ IT_head(iter);
+
+ parent = addEditBone(arm, "Bone");
+ VECCOPY(parent->head, iter->p);
+
+ index = next_subdividion(toolsettings, iter, bone_start, end, parent->head, parent->tail);
+ while (index != -1)
+ {
+ IT_peek(iter, index);
+
+ child = addEditBone(arm, "Bone");
+ VECCOPY(child->head, parent->tail);
+ child->parent = parent;
+ child->flag |= BONE_CONNECTED;
+
+ /* going to next bone, fix parent */
+ Mat4MulVecfl(invmat, parent->tail);
+ Mat4MulVecfl(invmat, parent->head);
+ setBoneRollFromNormal(parent, iter->no, invmat, tmat);
+
+ parent = child; // new child is next parent
+ bone_start = index; // start next bone from current index
+
+ index = next_subdividion(toolsettings, iter, bone_start, end, parent->head, parent->tail);
+ }
+
+ iter->tail(iter);
+
+ VECCOPY(parent->tail, iter->p);
+
+ /* fix last bone */
+ Mat4MulVecfl(invmat, parent->tail);
+ Mat4MulVecfl(invmat, parent->head);
+ setBoneRollFromNormal(parent, iter->no, invmat, tmat);
+ lastBone = parent;
+
+ return lastBone;
+}
diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c
new file mode 100644
index 00000000000..68e8b45e7d2
--- /dev/null
+++ b/source/blender/editors/armature/editarmature_retarget.c
@@ -0,0 +1,2962 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Martin Poirier
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * autoarmature.c: Interface for automagically manipulating armature (retarget, created, ...)
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "DNA_ID.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_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"
+#include "BLI_editVert.h"
+#include "BLI_ghash.h"
+#include "BLI_graph.h"
+#include "BLI_rand.h"
+#include "BLI_threads.h"
+
+//#include "BDR_editobject.h"
+
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+#include "BKE_constraint.h"
+#include "BKE_armature.h"
+#include "BKE_context.h"
+
+#include "ED_armature.h"
+#include "ED_util.h"
+
+#include "BIF_retarget.h"
+
+#include "PIL_time.h"
+
+//#include "mydevice.h"
+#include "reeb.h" // FIX ME
+//#include "blendef.h"
+
+#include "armature_intern.h"
+
+/************ RIG RETARGET DATA STRUCTURES ***************/
+
+typedef struct MemoNode {
+ float weight;
+ int next;
+} MemoNode;
+
+typedef struct RetargetParam {
+ RigGraph *rigg;
+ RigArc *iarc;
+ RigNode *inode_start;
+ bContext *context;
+} RetargetParam;
+
+typedef enum
+{
+ RETARGET_LENGTH,
+ RETARGET_AGGRESSIVE
+} RetargetMode;
+
+typedef enum
+{
+ METHOD_BRUTE_FORCE = 0,
+ METHOD_MEMOIZE = 1
+} RetargetMethod;
+
+typedef enum
+{
+ ARC_FREE = 0,
+ ARC_TAKEN = 1,
+ ARC_USED = 2
+} ArcUsageFlags;
+
+RigGraph *GLOBAL_RIGG = NULL;
+
+/*******************************************************************************************************/
+
+void *exec_retargetArctoArc(void *param);
+
+static void RIG_calculateEdgeAngles(RigEdge *edge_first, RigEdge *edge_second);
+float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float qrot[4]);
+
+/* two levels */
+#define SHAPE_LEVELS (SHAPE_RADIX * SHAPE_RADIX)
+
+/*********************************** EDITBONE UTILS ****************************************************/
+
+int countEditBoneChildren(ListBase *list, EditBone *parent)
+{
+ EditBone *ebone;
+ int count = 0;
+
+ for (ebone = list->first; ebone; ebone = ebone->next)
+ {
+ if (ebone->parent == parent)
+ {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+EditBone* nextEditBoneChild(ListBase *list, EditBone *parent, int n)
+{
+ EditBone *ebone;
+
+ for (ebone = list->first; ebone; ebone = ebone->next)
+ {
+ if (ebone->parent == parent)
+ {
+ if (n == 0)
+ {
+ return ebone;
+ }
+ n--;
+ }
+ }
+
+ return NULL;
+}
+
+void getEditBoneRollUpAxis(EditBone *bone, float roll, float up_axis[3])
+{
+ float mat[3][3], nor[3];
+
+ VecSubf(nor, bone->tail, bone->head);
+
+ vec_roll_to_mat3(nor, roll, mat);
+ VECCOPY(up_axis, mat[2]);
+}
+
+float rollBoneByQuatAligned(EditBone *bone, float old_up_axis[3], float qrot[4], float qroll[4], float aligned_axis[3])
+{
+ float nor[3], new_up_axis[3], x_axis[3], z_axis[3];
+
+ VECCOPY(new_up_axis, old_up_axis);
+ QuatMulVecf(qrot, new_up_axis);
+
+ VecSubf(nor, bone->tail, bone->head);
+
+ Crossf(x_axis, nor, aligned_axis);
+ Crossf(z_axis, x_axis, nor);
+
+ Normalize(new_up_axis);
+ Normalize(x_axis);
+ Normalize(z_axis);
+
+ if (Inpf(new_up_axis, x_axis) < 0)
+ {
+ VecMulf(x_axis, -1);
+ }
+
+ if (Inpf(new_up_axis, z_axis) < 0)
+ {
+ VecMulf(z_axis, -1);
+ }
+
+ if (NormalizedVecAngle2(x_axis, new_up_axis) < NormalizedVecAngle2(z_axis, new_up_axis))
+ {
+ RotationBetweenVectorsToQuat(qroll, new_up_axis, x_axis); /* set roll rotation quat */
+ return ED_rollBoneToVector(bone, x_axis);
+ }
+ else
+ {
+ RotationBetweenVectorsToQuat(qroll, new_up_axis, z_axis); /* set roll rotation quat */
+ return ED_rollBoneToVector(bone, z_axis);
+ }
+}
+
+float rollBoneByQuatJoint(RigEdge *edge, RigEdge *previous, float qrot[4], float qroll[4], float up_axis[3])
+{
+ if (previous == NULL)
+ {
+ /* default to up_axis if no previous */
+ return rollBoneByQuatAligned(edge->bone, edge->up_axis, qrot, qroll, up_axis);
+ }
+ else
+ {
+ float new_up_axis[3];
+ float vec_first[3], vec_second[3], normal[3];
+
+ if (previous->bone)
+ {
+ VecSubf(vec_first, previous->bone->tail, previous->bone->head);
+ }
+ else if (previous->prev->bone)
+ {
+ VecSubf(vec_first, edge->bone->head, previous->prev->bone->tail);
+ }
+ else
+ {
+ /* default to up_axis if first bone in the chain is an offset */
+ return rollBoneByQuatAligned(edge->bone, edge->up_axis, qrot, qroll, up_axis);
+ }
+
+ VecSubf(vec_second, edge->bone->tail, edge->bone->head);
+
+ Normalize(vec_first);
+ Normalize(vec_second);
+
+ Crossf(normal, vec_first, vec_second);
+ Normalize(normal);
+
+ AxisAngleToQuat(qroll, vec_second, edge->up_angle);
+
+ QuatMulVecf(qroll, normal);
+
+ VECCOPY(new_up_axis, edge->up_axis);
+ QuatMulVecf(qrot, new_up_axis);
+
+ Normalize(new_up_axis);
+
+ /* real qroll between normal and up_axis */
+ RotationBetweenVectorsToQuat(qroll, new_up_axis, normal);
+
+ return ED_rollBoneToVector(edge->bone, normal);
+ }
+}
+
+float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float qrot[4])
+{
+ float new_up_axis[3];
+
+ VECCOPY(new_up_axis, old_up_axis);
+ QuatMulVecf(qrot, new_up_axis);
+
+ Normalize(new_up_axis);
+
+ return ED_rollBoneToVector(bone, new_up_axis);
+}
+
+/************************************ DESTRUCTORS ******************************************************/
+
+void RIG_freeRigArc(BArc *arc)
+{
+ BLI_freelistN(&((RigArc*)arc)->edges);
+}
+
+void RIG_freeRigGraph(BGraph *rg)
+{
+ RigGraph *rigg = (RigGraph*)rg;
+ BNode *node;
+ BArc *arc;
+
+#ifdef USE_THREADS
+ BLI_destroy_worker(rigg->worker);
+#endif
+
+ if (rigg->link_mesh)
+ {
+ REEB_freeGraph(rigg->link_mesh);
+ }
+
+ for (arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ RIG_freeRigArc(arc);
+ }
+ BLI_freelistN(&rg->arcs);
+
+ for (node = rg->nodes.first; node; node = node->next)
+ {
+ BLI_freeNode(rg, (BNode*)node);
+ }
+ BLI_freelistN(&rg->nodes);
+
+ BLI_freelistN(&rigg->controls);
+
+ BLI_ghash_free(rigg->bones_map, NULL, NULL);
+ BLI_ghash_free(rigg->controls_map, NULL, NULL);
+
+ if (rigg->flag & RIG_FREE_BONELIST)
+ {
+ BLI_freelistN(rigg->editbones);
+ MEM_freeN(rigg->editbones);
+ }
+
+ MEM_freeN(rg);
+}
+
+/************************************* ALLOCATORS ******************************************************/
+
+static RigGraph *newRigGraph()
+{
+ RigGraph *rg;
+ int totthread;
+
+ rg = MEM_callocN(sizeof(RigGraph), "rig graph");
+
+ rg->head = NULL;
+
+ rg->bones_map = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp);
+ rg->controls_map = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp);
+
+ rg->free_arc = RIG_freeRigArc;
+ rg->free_node = NULL;
+
+#ifdef USE_THREADS
+// if(G.scene->r.mode & R_FIXED_THREADS)
+// {
+// totthread = G.scene->r.threads;
+// }
+// else
+// {
+ totthread = BLI_system_thread_count();
+// }
+
+ rg->worker = BLI_create_worker(exec_retargetArctoArc, totthread, 20); /* fix number of threads */
+#endif
+
+ return rg;
+}
+
+static RigArc *newRigArc(RigGraph *rg)
+{
+ RigArc *arc;
+
+ arc = MEM_callocN(sizeof(RigArc), "rig arc");
+ arc->count = 0;
+ BLI_addtail(&rg->arcs, arc);
+
+ return arc;
+}
+
+static RigControl *newRigControl(RigGraph *rg)
+{
+ RigControl *ctrl;
+
+ ctrl = MEM_callocN(sizeof(RigControl), "rig control");
+
+ BLI_addtail(&rg->controls, ctrl);
+
+ return ctrl;
+}
+
+static RigNode *newRigNodeHead(RigGraph *rg, RigArc *arc, float p[3])
+{
+ RigNode *node;
+ node = MEM_callocN(sizeof(RigNode), "rig node");
+ BLI_addtail(&rg->nodes, node);
+
+ VECCOPY(node->p, p);
+ node->degree = 1;
+ node->arcs = NULL;
+
+ arc->head = node;
+
+ return node;
+}
+
+static void addRigNodeHead(RigGraph *rg, RigArc *arc, RigNode *node)
+{
+ node->degree++;
+
+ arc->head = node;
+}
+
+static RigNode *newRigNode(RigGraph *rg, float p[3])
+{
+ RigNode *node;
+ node = MEM_callocN(sizeof(RigNode), "rig node");
+ BLI_addtail(&rg->nodes, node);
+
+ VECCOPY(node->p, p);
+ node->degree = 0;
+ node->arcs = NULL;
+
+ return node;
+}
+
+static RigNode *newRigNodeTail(RigGraph *rg, RigArc *arc, float p[3])
+{
+ RigNode *node = newRigNode(rg, p);
+
+ node->degree = 1;
+ arc->tail = node;
+
+ return node;
+}
+
+static void RIG_appendEdgeToArc(RigArc *arc, RigEdge *edge)
+{
+ BLI_addtail(&arc->edges, edge);
+
+ if (edge->prev == NULL)
+ {
+ VECCOPY(edge->head, arc->head->p);
+ }
+ else
+ {
+ RigEdge *last_edge = edge->prev;
+ VECCOPY(edge->head, last_edge->tail);
+ RIG_calculateEdgeAngles(last_edge, edge);
+ }
+
+ edge->length = VecLenf(edge->head, edge->tail);
+
+ arc->length += edge->length;
+
+ arc->count += 1;
+}
+
+static void RIG_addEdgeToArc(RigArc *arc, float tail[3], EditBone *bone)
+{
+ RigEdge *edge;
+
+ edge = MEM_callocN(sizeof(RigEdge), "rig edge");
+
+ VECCOPY(edge->tail, tail);
+ edge->bone = bone;
+
+ if (bone)
+ {
+ getEditBoneRollUpAxis(bone, bone->roll, edge->up_axis);
+ }
+
+ RIG_appendEdgeToArc(arc, edge);
+}
+/************************************** CLONING TEMPLATES **********************************************/
+
+static void renameTemplateBone(char *name, char *template_name, ListBase *editbones, char *side_string, char *num_string)
+{
+ int i, j;
+
+ for (i = 0, j = 0; template_name[i] != '\0' && i < 31 && j < 31; i++)
+ {
+ if (template_name[i] == '&')
+ {
+ if (template_name[i+1] == 'S' || template_name[i+1] == 's')
+ {
+ j += sprintf(name + j, side_string);
+ i++;
+ }
+ else if (template_name[i+1] == 'N' || template_name[i+1] == 'n')
+ {
+ j += sprintf(name + j, num_string);
+ i++;
+ }
+ else
+ {
+ name[j] = template_name[i];
+ j++;
+ }
+ }
+ else
+ {
+ name[j] = template_name[i];
+ j++;
+ }
+ }
+
+ name[j] = '\0';
+
+ unique_editbone_name(editbones, name, NULL);
+}
+
+static RigControl *cloneControl(RigGraph *rg, RigGraph *src_rg, RigControl *src_ctrl, GHash *ptr_hash, char *side_string, char *num_string)
+{
+ RigControl *ctrl;
+ char name[32];
+
+ ctrl = newRigControl(rg);
+
+ VECCOPY(ctrl->head, src_ctrl->head);
+ VECCOPY(ctrl->tail, src_ctrl->tail);
+ VECCOPY(ctrl->up_axis, src_ctrl->up_axis);
+ VECCOPY(ctrl->offset, src_ctrl->offset);
+
+ ctrl->tail_mode = src_ctrl->tail_mode;
+ ctrl->flag = src_ctrl->flag;
+
+ renameTemplateBone(name, src_ctrl->bone->name, rg->editbones, side_string, num_string);
+ ctrl->bone = duplicateEditBoneObjects(src_ctrl->bone, name, rg->editbones, src_rg->ob, rg->ob);
+ ctrl->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE);
+ BLI_ghash_insert(ptr_hash, src_ctrl->bone, ctrl->bone);
+
+ ctrl->link = src_ctrl->link;
+ ctrl->link_tail = src_ctrl->link_tail;
+
+ return ctrl;
+}
+
+static RigArc *cloneArc(RigGraph *rg, RigGraph *src_rg, RigArc *src_arc, GHash *ptr_hash, char *side_string, char *num_string)
+{
+ RigEdge *src_edge;
+ RigArc *arc;
+
+ arc = newRigArc(rg);
+
+ arc->head = BLI_ghash_lookup(ptr_hash, src_arc->head);
+ arc->tail = BLI_ghash_lookup(ptr_hash, src_arc->tail);
+
+ arc->head->degree++;
+ arc->tail->degree++;
+
+ arc->length = src_arc->length;
+
+ arc->count = src_arc->count;
+
+ for (src_edge = src_arc->edges.first; src_edge; src_edge = src_edge->next)
+ {
+ RigEdge *edge;
+
+ edge = MEM_callocN(sizeof(RigEdge), "rig edge");
+
+ VECCOPY(edge->head, src_edge->head);
+ VECCOPY(edge->tail, src_edge->tail);
+ VECCOPY(edge->up_axis, src_edge->up_axis);
+
+ edge->length = src_edge->length;
+ edge->angle = src_edge->angle;
+ edge->up_angle = src_edge->up_angle;
+
+ if (src_edge->bone != NULL)
+ {
+ char name[32];
+ renameTemplateBone(name, src_edge->bone->name, rg->editbones, side_string, num_string);
+ edge->bone = duplicateEditBoneObjects(src_edge->bone, name, rg->editbones, src_rg->ob, rg->ob);
+ edge->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE);
+ BLI_ghash_insert(ptr_hash, src_edge->bone, edge->bone);
+ }
+
+ BLI_addtail(&arc->edges, edge);
+ }
+
+ return arc;
+}
+
+static RigGraph *cloneRigGraph(RigGraph *src, ListBase *editbones, Object *ob, char *side_string, char *num_string)
+{
+ GHash *ptr_hash;
+ RigNode *node;
+ RigArc *arc;
+ RigControl *ctrl;
+ RigGraph *rg;
+
+ ptr_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ rg = newRigGraph();
+
+ rg->ob = ob;
+ rg->editbones = editbones;
+
+ preEditBoneDuplicate(rg->editbones); /* prime bones for duplication */
+ preEditBoneDuplicate(src->editbones); /* prime bones for duplication */
+
+ /* Clone nodes */
+ for (node = src->nodes.first; node; node = node->next)
+ {
+ RigNode *cloned_node = newRigNode(rg, node->p);
+ BLI_ghash_insert(ptr_hash, node, cloned_node);
+ }
+
+ rg->head = BLI_ghash_lookup(ptr_hash, src->head);
+
+ /* Clone arcs */
+ for (arc = src->arcs.first; arc; arc = arc->next)
+ {
+ cloneArc(rg, src, arc, ptr_hash, side_string, num_string);
+ }
+
+ /* Clone controls */
+ for (ctrl = src->controls.first; ctrl; ctrl = ctrl->next)
+ {
+ cloneControl(rg, src, ctrl, ptr_hash, side_string, num_string);
+ }
+
+ /* Relink bones properly */
+ for (arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ RigEdge *edge;
+
+ for (edge = arc->edges.first; edge; edge = edge->next)
+ {
+ if (edge->bone != NULL)
+ {
+ EditBone *bone;
+
+ updateDuplicateSubtargetObjects(edge->bone, src->editbones, src->ob, rg->ob);
+
+ if (edge->bone->parent)
+ {
+ bone = BLI_ghash_lookup(ptr_hash, edge->bone->parent);
+
+ if (bone != NULL)
+ {
+ edge->bone->parent = bone;
+ }
+ else
+ {
+ /* disconnect since parent isn't cloned
+ * this will only happen when cloning from selected bones
+ * */
+ edge->bone->flag &= ~BONE_CONNECTED;
+ }
+ }
+ }
+ }
+ }
+
+ for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
+ {
+ EditBone *bone;
+
+ updateDuplicateSubtargetObjects(ctrl->bone, src->editbones, src->ob, rg->ob);
+
+ if (ctrl->bone->parent)
+ {
+ bone = BLI_ghash_lookup(ptr_hash, ctrl->bone->parent);
+
+ if (bone != NULL)
+ {
+ ctrl->bone->parent = bone;
+ }
+ else
+ {
+ /* disconnect since parent isn't cloned
+ * this will only happen when cloning from selected bones
+ * */
+ ctrl->bone->flag &= ~BONE_CONNECTED;
+ }
+ }
+
+ ctrl->link = BLI_ghash_lookup(ptr_hash, ctrl->link);
+ ctrl->link_tail = BLI_ghash_lookup(ptr_hash, ctrl->link_tail);
+ }
+
+ BLI_ghash_free(ptr_hash, NULL, NULL);
+
+ return rg;
+}
+
+
+/*******************************************************************************************************/
+
+static void RIG_calculateEdgeAngles(RigEdge *edge_first, RigEdge *edge_second)
+{
+ float vec_first[3], vec_second[3];
+
+ VecSubf(vec_first, edge_first->tail, edge_first->head);
+ VecSubf(vec_second, edge_second->tail, edge_second->head);
+
+ Normalize(vec_first);
+ Normalize(vec_second);
+
+ edge_first->angle = NormalizedVecAngle2(vec_first, vec_second);
+
+ if (edge_second->bone != NULL)
+ {
+ float normal[3];
+
+ Crossf(normal, vec_first, vec_second);
+ Normalize(normal);
+
+ edge_second->up_angle = NormalizedVecAngle2(normal, edge_second->up_axis);
+ }
+}
+
+/************************************ CONTROL BONES ****************************************************/
+
+static void RIG_addControlBone(RigGraph *rg, EditBone *bone)
+{
+ RigControl *ctrl = newRigControl(rg);
+ ctrl->bone = bone;
+ VECCOPY(ctrl->head, bone->head);
+ VECCOPY(ctrl->tail, bone->tail);
+ getEditBoneRollUpAxis(bone, bone->roll, ctrl->up_axis);
+ ctrl->tail_mode = TL_NONE;
+
+ BLI_ghash_insert(rg->controls_map, bone->name, ctrl);
+}
+
+static int RIG_parentControl(RigControl *ctrl, EditBone *link)
+{
+ if (link)
+ {
+ float offset[3];
+ int flag = 0;
+
+ VecSubf(offset, ctrl->bone->head, link->head);
+
+ /* if root matches, check for direction too */
+ if (Inpf(offset, offset) < 0.0001)
+ {
+ float vbone[3], vparent[3];
+
+ flag |= RIG_CTRL_FIT_ROOT;
+
+ VecSubf(vbone, ctrl->bone->tail, ctrl->bone->head);
+ VecSubf(vparent, link->tail, link->head);
+
+ /* test for opposite direction */
+ if (Inpf(vbone, vparent) > 0)
+ {
+ float nor[3];
+ float len;
+
+ Crossf(nor, vbone, vparent);
+
+ len = Inpf(nor, nor);
+ if (len < 0.0001)
+ {
+ flag |= RIG_CTRL_FIT_BONE;
+ }
+ }
+ }
+
+ /* Bail out if old one is automatically better */
+ if (flag < ctrl->flag)
+ {
+ return 0;
+ }
+
+ /* if there's already a link
+ * overwrite only if new link is higher in the chain */
+ if (ctrl->link && flag == ctrl->flag)
+ {
+ EditBone *bone = NULL;
+
+ for (bone = ctrl->link; bone; bone = bone->parent)
+ {
+ /* if link is in the chain, break and use that one */
+ if (bone == link)
+ {
+ break;
+ }
+ }
+
+ /* not in chain, don't update link */
+ if (bone == NULL)
+ {
+ return 0;
+ }
+ }
+
+
+ ctrl->link = link;
+ ctrl->flag = flag;
+
+ VECCOPY(ctrl->offset, offset);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static void RIG_reconnectControlBones(RigGraph *rg)
+{
+ RigControl *ctrl;
+ int change = 1;
+
+ /* first pass, link to deform bones */
+ for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
+ {
+ bPoseChannel *pchan;
+ bConstraint *con;
+ int found = 0;
+
+ /* DO SOME MAGIC HERE */
+ for (pchan= rg->ob->pose->chanbase.first; pchan; pchan= pchan->next)
+ {
+ for (con= pchan->constraints.first; con; con= con->next)
+ {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ /* constraint targets */
+ if (cti && cti->get_constraint_targets)
+ {
+ int target_index;
+
+ cti->get_constraint_targets(con, &targets);
+
+ for (target_index = 0, ct= targets.first; ct; target_index++, ct= ct->next)
+ {
+ if ((ct->tar == rg->ob) && strcmp(ct->subtarget, ctrl->bone->name) == 0)
+ {
+ /* SET bone link to bone corresponding to pchan */
+ EditBone *link = BLI_ghash_lookup(rg->bones_map, pchan->name);
+
+ /* Making sure bone is in this armature */
+ if (link != NULL)
+ {
+ /* for pole targets, link to parent bone instead, if possible */
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC && target_index == 1)
+ {
+ if (link->parent && BLI_ghash_haskey(rg->bones_map, link->parent->name))
+ {
+ link = link->parent;
+ }
+ }
+
+ found = RIG_parentControl(ctrl, link);
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+ }
+ }
+
+ /* if not found yet, check parent */
+ if (found == 0)
+ {
+ if (ctrl->bone->parent)
+ {
+ /* make sure parent is a deforming bone
+ * NULL if not
+ * */
+ EditBone *link = BLI_ghash_lookup(rg->bones_map, ctrl->bone->parent->name);
+
+ found = RIG_parentControl(ctrl, link);
+ }
+
+ /* check if bone is not superposed on another one */
+ {
+ RigArc *arc;
+ RigArc *best_arc = NULL;
+ EditBone *link = NULL;
+
+ for (arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ RigEdge *edge;
+ for (edge = arc->edges.first; edge; edge = edge->next)
+ {
+ if (edge->bone)
+ {
+ int fit = 0;
+
+ fit = VecLenf(ctrl->bone->head, edge->bone->head) < 0.0001;
+ fit = fit || VecLenf(ctrl->bone->tail, edge->bone->tail) < 0.0001;
+
+ if (fit)
+ {
+ /* pick the bone on the arc with the lowest symmetry level
+ * means you connect control to the trunk of the skeleton */
+ if (best_arc == NULL || arc->symmetry_level < best_arc->symmetry_level)
+ {
+ best_arc = arc;
+ link = edge->bone;
+ }
+ }
+ }
+ }
+ }
+
+ found = RIG_parentControl(ctrl, link);
+ }
+ }
+
+ /* if not found yet, check child */
+ if (found == 0)
+ {
+ RigArc *arc;
+ RigArc *best_arc = NULL;
+ EditBone *link = NULL;
+
+ for (arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ RigEdge *edge;
+ for (edge = arc->edges.first; edge; edge = edge->next)
+ {
+ if (edge->bone && edge->bone->parent == ctrl->bone)
+ {
+ /* pick the bone on the arc with the lowest symmetry level
+ * means you connect control to the trunk of the skeleton */
+ if (best_arc == NULL || arc->symmetry_level < best_arc->symmetry_level)
+ {
+ best_arc = arc;
+ link = edge->bone;
+ }
+ }
+ }
+ }
+
+ found = RIG_parentControl(ctrl, link);
+ }
+
+ }
+
+
+ /* second pass, make chains in control bones */
+ while (change)
+ {
+ change = 0;
+
+ for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
+ {
+ /* if control is not linked yet */
+ if (ctrl->link == NULL)
+ {
+ bPoseChannel *pchan;
+ bConstraint *con;
+ RigControl *ctrl_parent = NULL;
+ RigControl *ctrl_child;
+ int found = 0;
+
+ if (ctrl->bone->parent)
+ {
+ ctrl_parent = BLI_ghash_lookup(rg->controls_map, ctrl->bone->parent->name);
+ }
+
+ /* check constraints first */
+
+ /* DO SOME MAGIC HERE */
+ for (pchan= rg->ob->pose->chanbase.first; pchan; pchan= pchan->next)
+ {
+ for (con= pchan->constraints.first; con; con= con->next)
+ {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ /* constraint targets */
+ if (cti && cti->get_constraint_targets)
+ {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next)
+ {
+ if ((ct->tar == rg->ob) && strcmp(ct->subtarget, ctrl->bone->name) == 0)
+ {
+ /* SET bone link to ctrl corresponding to pchan */
+ RigControl *link = BLI_ghash_lookup(rg->controls_map, pchan->name);
+
+ /* if owner is a control bone, link with it */
+ if (link && link->link)
+ {
+ RIG_parentControl(ctrl, link->bone);
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+ }
+ }
+
+ if (found == 0)
+ {
+ /* check if parent is already linked */
+ if (ctrl_parent && ctrl_parent->link)
+ {
+ RIG_parentControl(ctrl, ctrl_parent->bone);
+ change = 1;
+ }
+ else
+ {
+ /* check childs */
+ for (ctrl_child = rg->controls.first; ctrl_child; ctrl_child = ctrl_child->next)
+ {
+ /* if a child is linked, link to that one */
+ if (ctrl_child->link && ctrl_child->bone->parent == ctrl->bone)
+ {
+ RIG_parentControl(ctrl, ctrl_child->bone);
+ change = 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* third pass, link control tails */
+ for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
+ {
+ /* fit bone already means full match, so skip those */
+ if ((ctrl->flag & RIG_CTRL_FIT_BONE) == 0)
+ {
+ GHashIterator ghi;
+
+ /* look on deform bones first */
+ BLI_ghashIterator_init(&ghi, rg->bones_map);
+
+ for( ; !BLI_ghashIterator_isDone(&ghi); BLI_ghashIterator_step(&ghi))
+ {
+ EditBone *bone = (EditBone*)BLI_ghashIterator_getValue(&ghi);
+
+ /* don't link with parent */
+ if (bone->parent != ctrl->bone)
+ {
+ if (VecLenf(ctrl->bone->tail, bone->head) < 0.01)
+ {
+ ctrl->tail_mode = TL_HEAD;
+ ctrl->link_tail = bone;
+ break;
+ }
+ else if (VecLenf(ctrl->bone->tail, bone->tail) < 0.01)
+ {
+ ctrl->tail_mode = TL_TAIL;
+ ctrl->link_tail = bone;
+ break;
+ }
+ }
+ }
+
+ /* if we haven't found one yet, look in control bones */
+ if (ctrl->tail_mode == TL_NONE)
+ {
+ }
+ }
+ }
+
+}
+
+/*******************************************************************************************************/
+
+static void RIG_joinArcs(RigGraph *rg, RigNode *node, RigArc *joined_arc1, RigArc *joined_arc2)
+{
+ RigEdge *edge, *next_edge;
+
+ /* ignore cases where joint is at start or end */
+ if (joined_arc1->head == joined_arc2->head || joined_arc1->tail == joined_arc2->tail)
+ {
+ return;
+ }
+
+ /* swap arcs to make sure arc1 is before arc2 */
+ if (joined_arc1->head == joined_arc2->tail)
+ {
+ RigArc *tmp = joined_arc1;
+ joined_arc1 = joined_arc2;
+ joined_arc2 = tmp;
+ }
+
+ for (edge = joined_arc2->edges.first; edge; edge = next_edge)
+ {
+ next_edge = edge->next;
+
+ RIG_appendEdgeToArc(joined_arc1, edge);
+ }
+
+ joined_arc1->tail = joined_arc2->tail;
+
+ joined_arc2->edges.first = joined_arc2->edges.last = NULL;
+
+ BLI_removeArc((BGraph*)rg, (BArc*)joined_arc2);
+
+ BLI_removeNode((BGraph*)rg, (BNode*)node);
+}
+
+static void RIG_removeNormalNodes(RigGraph *rg)
+{
+ RigNode *node, *next_node;
+
+ for (node = rg->nodes.first; node; node = next_node)
+ {
+ next_node = node->next;
+
+ if (node->degree == 2)
+ {
+ RigArc *arc, *joined_arc1 = NULL, *joined_arc2 = NULL;
+
+ for (arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ if (arc->head == node || arc->tail == node)
+ {
+ if (joined_arc1 == NULL)
+ {
+ joined_arc1 = arc;
+ }
+ else
+ {
+ joined_arc2 = arc;
+ break;
+ }
+ }
+ }
+
+ RIG_joinArcs(rg, node, joined_arc1, joined_arc2);
+ }
+ }
+}
+
+static void RIG_removeUneededOffsets(RigGraph *rg)
+{
+ RigArc *arc;
+
+ for (arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ RigEdge *first_edge, *last_edge;
+
+ first_edge = arc->edges.first;
+ last_edge = arc->edges.last;
+
+ if (first_edge->bone == NULL)
+ {
+ if (first_edge->bone == NULL && VecLenf(first_edge->tail, arc->head->p) <= 0.001)
+ {
+ BLI_remlink(&arc->edges, first_edge);
+ MEM_freeN(first_edge);
+ }
+ else if (arc->head->degree == 1)
+ {
+ RigNode *new_node = (RigNode*)BLI_FindNodeByPosition((BGraph*)rg, first_edge->tail, 0.001);
+
+ if (new_node)
+ {
+ BLI_remlink(&arc->edges, first_edge);
+ MEM_freeN(first_edge);
+ BLI_replaceNodeInArc((BGraph*)rg, (BArc*)arc, (BNode*)new_node, (BNode*)arc->head);
+ }
+ else
+ {
+ RigEdge *next_edge = first_edge->next;
+
+ if (next_edge)
+ {
+ BLI_remlink(&arc->edges, first_edge);
+ MEM_freeN(first_edge);
+
+ VECCOPY(arc->head->p, next_edge->head);
+ }
+ }
+ }
+ else
+ {
+ /* check if all arc connected start with a null edge */
+ RigArc *other_arc;
+ for (other_arc = rg->arcs.first; other_arc; other_arc = other_arc->next)
+ {
+ if (other_arc != arc)
+ {
+ RigEdge *test_edge;
+ if (other_arc->head == arc->head)
+ {
+ test_edge = other_arc->edges.first;
+
+ if (test_edge->bone != NULL)
+ {
+ break;
+ }
+ }
+ else if (other_arc->tail == arc->head)
+ {
+ test_edge = other_arc->edges.last;
+
+ if (test_edge->bone != NULL)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ if (other_arc == NULL)
+ {
+ RigNode *new_node = (RigNode*)BLI_FindNodeByPosition((BGraph*)rg, first_edge->tail, 0.001);
+
+ if (new_node)
+ {
+ /* remove null edge in other arcs too */
+ for (other_arc = rg->arcs.first; other_arc; other_arc = other_arc->next)
+ {
+ if (other_arc != arc)
+ {
+ RigEdge *test_edge;
+ if (other_arc->head == arc->head)
+ {
+ BLI_replaceNodeInArc((BGraph*)rg, (BArc*)other_arc, (BNode*)new_node, (BNode*)other_arc->head);
+ test_edge = other_arc->edges.first;
+ BLI_remlink(&other_arc->edges, test_edge);
+ MEM_freeN(test_edge);
+ }
+ else if (other_arc->tail == arc->head)
+ {
+ BLI_replaceNodeInArc((BGraph*)rg, (BArc*)other_arc, (BNode*)new_node, (BNode*)other_arc->tail);
+ test_edge = other_arc->edges.last;
+ BLI_remlink(&other_arc->edges, test_edge);
+ MEM_freeN(test_edge);
+ }
+ }
+ }
+
+ BLI_remlink(&arc->edges, first_edge);
+ MEM_freeN(first_edge);
+ BLI_replaceNodeInArc((BGraph*)rg, (BArc*)arc, (BNode*)new_node, (BNode*)arc->head);
+ }
+ else
+ {
+ RigEdge *next_edge = first_edge->next;
+
+ if (next_edge)
+ {
+ BLI_remlink(&arc->edges, first_edge);
+ MEM_freeN(first_edge);
+
+ VECCOPY(arc->head->p, next_edge->head);
+
+ /* remove null edge in other arcs too */
+ for (other_arc = rg->arcs.first; other_arc; other_arc = other_arc->next)
+ {
+ if (other_arc != arc)
+ {
+ RigEdge *test_edge;
+ if (other_arc->head == arc->head)
+ {
+ test_edge = other_arc->edges.first;
+ BLI_remlink(&other_arc->edges, test_edge);
+ MEM_freeN(test_edge);
+ }
+ else if (other_arc->tail == arc->head)
+ {
+ test_edge = other_arc->edges.last;
+ BLI_remlink(&other_arc->edges, test_edge);
+ MEM_freeN(test_edge);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (last_edge->bone == NULL)
+ {
+ if (VecLenf(last_edge->head, arc->tail->p) <= 0.001)
+ {
+ BLI_remlink(&arc->edges, last_edge);
+ MEM_freeN(last_edge);
+ }
+ else if (arc->tail->degree == 1)
+ {
+ RigNode *new_node = (RigNode*)BLI_FindNodeByPosition((BGraph*)rg, last_edge->head, 0.001);
+
+ if (new_node)
+ {
+ RigEdge *previous_edge = last_edge->prev;
+
+ BLI_remlink(&arc->edges, last_edge);
+ MEM_freeN(last_edge);
+ BLI_replaceNodeInArc((BGraph*)rg, (BArc*)arc, (BNode*)new_node, (BNode*)arc->tail);
+
+ /* set previous angle to 0, since there's no following edges */
+ if (previous_edge)
+ {
+ previous_edge->angle = 0;
+ }
+ }
+ else
+ {
+ RigEdge *previous_edge = last_edge->prev;
+
+ if (previous_edge)
+ {
+ BLI_remlink(&arc->edges, last_edge);
+ MEM_freeN(last_edge);
+
+ VECCOPY(arc->tail->p, previous_edge->tail);
+ previous_edge->angle = 0;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bone, RigNode *starting_node, int selected)
+{
+ EditBone *bone, *last_bone = root_bone;
+ RigArc *arc = NULL;
+ int contain_head = 0;
+
+ for(bone = root_bone; bone; bone = nextEditBoneChild(list, bone, 0))
+ {
+ int nb_children;
+
+ if (selected == 0 || (bone->flag & BONE_SELECTED))
+ {
+ if ((bone->flag & BONE_NO_DEFORM) == 0)
+ {
+ BLI_ghash_insert(rg->bones_map, bone->name, bone);
+
+ if (arc == NULL)
+ {
+ arc = newRigArc(rg);
+
+ if (starting_node == NULL)
+ {
+ starting_node = newRigNodeHead(rg, arc, root_bone->head);
+ }
+ else
+ {
+ addRigNodeHead(rg, arc, starting_node);
+ }
+ }
+
+ if (bone->parent && (bone->flag & BONE_CONNECTED) == 0)
+ {
+ RIG_addEdgeToArc(arc, bone->head, NULL);
+ }
+
+ RIG_addEdgeToArc(arc, bone->tail, bone);
+
+ last_bone = bone;
+
+ if (strcmp(bone->name, "head") == 0)
+ {
+ contain_head = 1;
+ }
+ }
+ else if ((bone->flag & BONE_EDITMODE_LOCKED) == 0) /* ignore locked bones */
+ {
+ RIG_addControlBone(rg, bone);
+ }
+ }
+
+ nb_children = countEditBoneChildren(list, bone);
+ if (nb_children > 1)
+ {
+ RigNode *end_node = NULL;
+ int i;
+
+ if (arc != NULL)
+ {
+ end_node = newRigNodeTail(rg, arc, bone->tail);
+ }
+ else
+ {
+ end_node = newRigNode(rg, bone->tail);
+ }
+
+ for (i = 0; i < nb_children; i++)
+ {
+ root_bone = nextEditBoneChild(list, bone, i);
+ RIG_arcFromBoneChain(rg, list, root_bone, end_node, selected);
+ }
+
+ /* arc ends here, break */
+ break;
+ }
+ }
+
+ /* If the loop exited without forking */
+ if (arc != NULL && bone == NULL)
+ {
+ newRigNodeTail(rg, arc, last_bone->tail);
+ }
+
+ if (contain_head)
+ {
+ rg->head = arc->tail;
+ }
+}
+
+/*******************************************************************************************************/
+static void RIG_findHead(RigGraph *rg)
+{
+ if (rg->head == NULL)
+ {
+ if (BLI_countlist(&rg->arcs) == 1)
+ {
+ RigArc *arc = rg->arcs.first;
+
+ rg->head = (RigNode*)arc->head;
+ }
+ else
+ {
+ RigArc *arc;
+
+ for (arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ RigEdge *edge = arc->edges.last;
+
+ if (edge->bone->flag & (BONE_TIPSEL|BONE_SELECTED))
+ {
+ rg->head = arc->tail;
+ break;
+ }
+ }
+ }
+
+ if (rg->head == NULL)
+ {
+ rg->head = rg->nodes.first;
+ }
+ }
+}
+
+/*******************************************************************************************************/
+
+void RIG_printNode(RigNode *node, char name[])
+{
+ printf("%s %p %i <%0.3f, %0.3f, %0.3f>\n", name, node, node->degree, node->p[0], node->p[1], node->p[2]);
+
+ if (node->symmetry_flag & SYM_TOPOLOGICAL)
+ {
+ if (node->symmetry_flag & SYM_AXIAL)
+ printf("Symmetry AXIAL\n");
+ else if (node->symmetry_flag & SYM_RADIAL)
+ printf("Symmetry RADIAL\n");
+
+ printvecf("symmetry axis", node->symmetry_axis);
+ }
+}
+
+void RIG_printArcBones(RigArc *arc)
+{
+ RigEdge *edge;
+
+ for (edge = arc->edges.first; edge; edge = edge->next)
+ {
+ if (edge->bone)
+ printf("%s ", edge->bone->name);
+ else
+ printf("---- ");
+ }
+ printf("\n");
+}
+
+void RIG_printCtrl(RigControl *ctrl, char *indent)
+{
+ char text[128];
+
+ printf("%sBone: %s\n", indent, ctrl->bone->name);
+ printf("%sLink: %s\n", indent, ctrl->link ? ctrl->link->name : "!NONE!");
+
+ sprintf(text, "%soffset", indent);
+ printvecf(text, ctrl->offset);
+
+ printf("%sFlag: %i\n", indent, ctrl->flag);
+}
+
+void RIG_printLinkedCtrl(RigGraph *rg, EditBone *bone, int tabs)
+{
+ RigControl *ctrl;
+ char indent[64];
+ char *s = indent;
+ int i;
+
+ for (i = 0; i < tabs; i++)
+ {
+ s[0] = '\t';
+ s++;
+ }
+ s[0] = 0;
+
+ for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
+ {
+ if (ctrl->link == bone)
+ {
+ RIG_printCtrl(ctrl, indent);
+ RIG_printLinkedCtrl(rg, ctrl->bone, tabs + 1);
+ }
+ }
+}
+
+void RIG_printArc(RigGraph *rg, RigArc *arc)
+{
+ RigEdge *edge;
+
+ RIG_printNode((RigNode*)arc->head, "head");
+
+ for (edge = arc->edges.first; edge; edge = edge->next)
+ {
+ printf("\tinner joints %0.3f %0.3f %0.3f\n", edge->tail[0], edge->tail[1], edge->tail[2]);
+ printf("\t\tlength %f\n", edge->length);
+ printf("\t\tangle %f\n", edge->angle * 180 / M_PI);
+ if (edge->bone)
+ {
+ printf("\t\t%s\n", edge->bone->name);
+ RIG_printLinkedCtrl(rg, edge->bone, 3);
+ }
+ }
+ printf("symmetry level: %i flag: %i group %i\n", arc->symmetry_level, arc->symmetry_flag, arc->symmetry_group);
+
+ RIG_printNode((RigNode*)arc->tail, "tail");
+}
+
+void RIG_printGraph(RigGraph *rg)
+{
+ RigArc *arc;
+
+ printf("---- ARCS ----\n");
+ for (arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ RIG_printArc(rg, arc);
+ printf("\n");
+ }
+
+ if (rg->head)
+ {
+ RIG_printNode(rg->head, "HEAD NODE:");
+ }
+ else
+ {
+ printf("HEAD NODE: NONE\n");
+ }
+}
+
+/*******************************************************************************************************/
+
+RigGraph *RIG_graphFromArmature(bContext *C, Object *ob, bArmature *arm)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ EditBone *ebone;
+ RigGraph *rg;
+
+ rg = newRigGraph();
+
+ if (obedit == ob)
+ {
+ bArmature *arm = obedit->data;
+ rg->editbones = arm->edbo;
+ }
+ else
+ {
+ rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones");
+ make_boneList(rg->editbones, &arm->bonebase, NULL);
+ rg->flag |= RIG_FREE_BONELIST;
+ }
+
+ rg->ob = ob;
+
+ /* Do the rotations */
+ for (ebone = rg->editbones->first; ebone; ebone=ebone->next){
+ if (ebone->parent == NULL)
+ {
+ RIG_arcFromBoneChain(rg, rg->editbones, ebone, NULL, 0);
+ }
+ }
+
+ BLI_removeDoubleNodes((BGraph*)rg, 0.001);
+
+ RIG_removeNormalNodes(rg);
+
+ RIG_removeUneededOffsets(rg);
+
+ BLI_buildAdjacencyList((BGraph*)rg);
+
+ RIG_findHead(rg);
+
+ BLI_markdownSymmetry((BGraph*)rg, (BNode*)rg->head, scene->toolsettings->skgen_symmetry_limit);
+
+ RIG_reconnectControlBones(rg); /* after symmetry, because we use levels to find best match */
+
+ if (BLI_isGraphCyclic((BGraph*)rg))
+ {
+ printf("armature cyclic\n");
+ }
+
+ return rg;
+}
+
+RigGraph *armatureSelectedToGraph(bContext *C, Object *ob, bArmature *arm)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ EditBone *ebone;
+ RigGraph *rg;
+
+ rg = newRigGraph();
+
+ if (obedit == ob)
+ {
+ rg->editbones = arm->edbo;
+ }
+ else
+ {
+ rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones");
+ make_boneList(rg->editbones, &arm->bonebase, NULL);
+ rg->flag |= RIG_FREE_BONELIST;
+ }
+
+ rg->ob = ob;
+
+ /* Do the rotations */
+ for (ebone = rg->editbones->first; ebone; ebone=ebone->next){
+ if (ebone->parent == NULL)
+ {
+ RIG_arcFromBoneChain(rg, rg->editbones, ebone, NULL, 1);
+ }
+ }
+
+ BLI_removeDoubleNodes((BGraph*)rg, 0.001);
+
+ RIG_removeNormalNodes(rg);
+
+ RIG_removeUneededOffsets(rg);
+
+ BLI_buildAdjacencyList((BGraph*)rg);
+
+ RIG_findHead(rg);
+
+ BLI_markdownSymmetry((BGraph*)rg, (BNode*)rg->head, scene->toolsettings->skgen_symmetry_limit);
+
+ RIG_reconnectControlBones(rg); /* after symmetry, because we use levels to find best match */
+
+ if (BLI_isGraphCyclic((BGraph*)rg))
+ {
+ printf("armature cyclic\n");
+ }
+
+ return rg;
+}
+/************************************ GENERATING *****************************************************/
+
+#if 0
+static EditBone *add_editbonetolist(char *name, ListBase *list)
+{
+ EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone");
+
+ BLI_strncpy(bone->name, name, 32);
+ unique_editbone_name(list, bone->name, NULL);
+
+ BLI_addtail(list, bone);
+
+ bone->flag |= BONE_TIPSEL;
+ bone->weight= 1.0F;
+ bone->dist= 0.25F;
+ bone->xwidth= 0.1;
+ bone->zwidth= 0.1;
+ bone->ease1= 1.0;
+ bone->ease2= 1.0;
+ bone->rad_head= 0.10;
+ bone->rad_tail= 0.05;
+ bone->segments= 1;
+ bone->layer= 1;//arm->layer;
+
+ return bone;
+}
+#endif
+
+void generateMissingArcsFromNode(RigGraph *rigg, ReebNode *node, int multi_level_limit)
+{
+ while (node->multi_level > multi_level_limit && node->link_up)
+ {
+ node = node->link_up;
+ }
+
+ while (node->multi_level < multi_level_limit && node->link_down)
+ {
+ node = node->link_down;
+ }
+
+ if (node->multi_level == multi_level_limit)
+ {
+ int i;
+
+ for (i = 0; i < node->degree; i++)
+ {
+ ReebArc *earc = node->arcs[i];
+
+ if (earc->flag == ARC_FREE && earc->head == node)
+ {
+ ReebNode *other = BIF_otherNodeFromIndex(earc, node);
+
+ earc->flag = ARC_USED;
+
+ //generateBonesForArc(rigg, earc, node, other);
+ generateMissingArcsFromNode(rigg, other, multi_level_limit);
+ }
+ }
+ }
+}
+
+void generateMissingArcs(RigGraph *rigg)
+{
+ ReebGraph *reebg = rigg->link_mesh;
+ int multi_level_limit = 5;
+
+ for (reebg = rigg->link_mesh; reebg; reebg = reebg->link_up)
+ {
+ ReebArc *earc;
+
+ for (earc = reebg->arcs.first; earc; earc = earc->next)
+ {
+ if (earc->flag == ARC_USED)
+ {
+ generateMissingArcsFromNode(rigg, earc->head, multi_level_limit);
+ generateMissingArcsFromNode(rigg, earc->tail, multi_level_limit);
+ }
+ }
+ }
+}
+
+/************************************ RETARGETTING *****************************************************/
+
+static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], float tail[3], float qrot[4], float resize);
+
+static void repositionTailControl(RigGraph *rigg, RigControl *ctrl);
+
+static void finalizeControl(RigGraph *rigg, RigControl *ctrl, float resize)
+{
+ if ((ctrl->flag & RIG_CTRL_DONE) == RIG_CTRL_DONE)
+ {
+ RigControl *ctrl_child;
+
+#if 0
+ printf("CTRL: %s LINK: %s", ctrl->bone->name, ctrl->link->name);
+
+ if (ctrl->link_tail)
+ {
+ printf(" TAIL: %s", ctrl->link_tail->name);
+ }
+
+ printf("\n");
+#endif
+
+ /* if there was a tail link: apply link, recalc resize factor and qrot */
+ if (ctrl->tail_mode != TL_NONE)
+ {
+ float *tail_vec = NULL;
+ float v1[3], v2[3], qtail[4];
+
+ if (ctrl->tail_mode == TL_TAIL)
+ {
+ tail_vec = ctrl->link_tail->tail;
+ }
+ else if (ctrl->tail_mode == TL_HEAD)
+ {
+ tail_vec = ctrl->link_tail->head;
+ }
+
+ VecSubf(v1, ctrl->bone->tail, ctrl->bone->head);
+ VecSubf(v2, tail_vec, ctrl->bone->head);
+
+ VECCOPY(ctrl->bone->tail, tail_vec);
+
+ RotationBetweenVectorsToQuat(qtail, v1, v2);
+ QuatMul(ctrl->qrot, qtail, ctrl->qrot);
+
+ resize = VecLength(v2) / VecLenf(ctrl->head, ctrl->tail);
+ }
+
+ ctrl->bone->roll = rollBoneByQuat(ctrl->bone, ctrl->up_axis, ctrl->qrot);
+
+ /* Cascade to connected control bones */
+ for (ctrl_child = rigg->controls.first; ctrl_child; ctrl_child = ctrl_child->next)
+ {
+ if (ctrl_child->link == ctrl->bone)
+ {
+ repositionControl(rigg, ctrl_child, ctrl->bone->head, ctrl->bone->tail, ctrl->qrot, resize);
+ }
+ if (ctrl_child->link_tail == ctrl->bone)
+ {
+ repositionTailControl(rigg, ctrl_child);
+ }
+ }
+ }
+}
+
+static void repositionTailControl(RigGraph *rigg, RigControl *ctrl)
+{
+ ctrl->flag |= RIG_CTRL_TAIL_DONE;
+
+ finalizeControl(rigg, ctrl, 1); /* resize will be recalculated anyway so we don't need it */
+}
+
+static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], float tail[3], float qrot[4], float resize)
+{
+ float parent_offset[3], tail_offset[3];
+
+ VECCOPY(parent_offset, ctrl->offset);
+ VecMulf(parent_offset, resize);
+ QuatMulVecf(qrot, parent_offset);
+
+ VecAddf(ctrl->bone->head, head, parent_offset);
+
+ ctrl->flag |= RIG_CTRL_HEAD_DONE;
+
+ QUATCOPY(ctrl->qrot, qrot);
+
+ if (ctrl->tail_mode == TL_NONE)
+ {
+ VecSubf(tail_offset, ctrl->tail, ctrl->head);
+ VecMulf(tail_offset, resize);
+ QuatMulVecf(qrot, tail_offset);
+
+ VecAddf(ctrl->bone->tail, ctrl->bone->head, tail_offset);
+
+ ctrl->flag |= RIG_CTRL_TAIL_DONE;
+ }
+
+ finalizeControl(rigg, ctrl, resize);
+}
+
+static void repositionBone(bContext *C, RigGraph *rigg, RigEdge *edge, float vec0[3], float vec1[3], float up_axis[3])
+{
+ Scene *scene = CTX_data_scene(C);
+ EditBone *bone;
+ RigControl *ctrl;
+ float qrot[4], resize;
+ float v1[3], v2[3];
+ float l1, l2;
+
+ bone = edge->bone;
+
+ VecSubf(v1, edge->tail, edge->head);
+ VecSubf(v2, vec1, vec0);
+
+ l1 = Normalize(v1);
+ l2 = Normalize(v2);
+
+ resize = l2 / l1;
+
+ RotationBetweenVectorsToQuat(qrot, v1, v2);
+
+ VECCOPY(bone->head, vec0);
+ VECCOPY(bone->tail, vec1);
+
+ if (!VecIsNull(up_axis))
+ {
+ float qroll[4];
+
+ if (scene->toolsettings->skgen_retarget_roll == SK_RETARGET_ROLL_VIEW)
+ {
+ bone->roll = rollBoneByQuatAligned(bone, edge->up_axis, qrot, qroll, up_axis);
+ }
+ else if (scene->toolsettings->skgen_retarget_roll == SK_RETARGET_ROLL_JOINT)
+ {
+ bone->roll = rollBoneByQuatJoint(edge, edge->prev, qrot, qroll, up_axis);
+ }
+ else
+ {
+ QuatOne(qroll);
+ }
+
+ QuatMul(qrot, qroll, qrot);
+ }
+ else
+ {
+ bone->roll = rollBoneByQuat(bone, edge->up_axis, qrot);
+ }
+
+ for (ctrl = rigg->controls.first; ctrl; ctrl = ctrl->next)
+ {
+ if (ctrl->link == bone)
+ {
+ repositionControl(rigg, ctrl, vec0, vec1, qrot, resize);
+ }
+ if (ctrl->link_tail == bone)
+ {
+ repositionTailControl(rigg, ctrl);
+ }
+ }
+}
+
+static RetargetMode detectArcRetargetMode(RigArc *arc);
+static void retargetArctoArcLength(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start);
+
+
+static RetargetMode detectArcRetargetMode(RigArc *iarc)
+{
+ RetargetMode mode = RETARGET_AGGRESSIVE;
+ ReebArc *earc = iarc->link_mesh;
+ RigEdge *edge;
+ int large_angle = 0;
+ float avg_angle = 0;
+ float avg_length = 0;
+ int nb_edges = 0;
+
+
+ for (edge = iarc->edges.first; edge; edge = edge->next)
+ {
+ avg_angle += edge->angle;
+ nb_edges++;
+ }
+
+ avg_angle /= nb_edges - 1; /* -1 because last edge doesn't have an angle */
+
+ avg_length = iarc->length / nb_edges;
+
+
+ if (nb_edges > 2)
+ {
+ for (edge = iarc->edges.first; edge; edge = edge->next)
+ {
+ if (fabs(edge->angle - avg_angle) > M_PI / 6)
+ {
+ large_angle = 1;
+ }
+ }
+ }
+ else if (nb_edges == 2 && avg_angle > 0)
+ {
+ large_angle = 1;
+ }
+
+
+ if (large_angle == 0)
+ {
+ mode = RETARGET_LENGTH;
+ }
+
+ if (earc->bcount <= (iarc->count - 1))
+ {
+ mode = RETARGET_LENGTH;
+ }
+
+ mode = RETARGET_AGGRESSIVE;
+
+ return mode;
+}
+
+#ifndef USE_THREADS
+static void printMovesNeeded(int *positions, int nb_positions)
+{
+ int moves = 0;
+ int i;
+
+ for (i = 0; i < nb_positions; i++)
+ {
+ moves += positions[i] - (i + 1);
+ }
+
+ printf("%i moves needed\n", moves);
+}
+
+static void printPositions(int *positions, int nb_positions)
+{
+ int i;
+
+ for (i = 0; i < nb_positions; i++)
+ {
+ printf("%i ", positions[i]);
+ }
+ printf("\n");
+}
+#endif
+
+#define MAX_COST FLT_MAX /* FIX ME */
+
+static float costDistance(BArcIterator *iter, float *vec0, float *vec1, int i0, int i1, float distance_weight)
+{
+ EmbedBucket *bucket = NULL;
+ float max_dist = 0;
+ float v1[3], v2[3], c[3];
+ float v1_inpf;
+
+ if (distance_weight > 0)
+ {
+ VecSubf(v1, vec0, vec1);
+
+ v1_inpf = Inpf(v1, v1);
+
+ if (v1_inpf > 0)
+ {
+ int j;
+ for (j = i0 + 1; j < i1 - 1; j++)
+ {
+ float dist;
+
+ bucket = IT_peek(iter, j);
+
+ VecSubf(v2, bucket->p, vec1);
+
+ Crossf(c, v1, v2);
+
+ dist = Inpf(c, c) / v1_inpf;
+
+ max_dist = dist > max_dist ? dist : max_dist;
+ }
+
+ return distance_weight * max_dist;
+ }
+ else
+ {
+ return MAX_COST;
+ }
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static float costAngle(float original_angle, float vec_first[3], float vec_second[3], float angle_weight)
+{
+ if (angle_weight > 0)
+ {
+ float current_angle;
+
+ if (!VecIsNull(vec_first) && !VecIsNull(vec_second))
+ {
+ current_angle = saacos(Inpf(vec_first, vec_second));
+
+ return angle_weight * fabs(current_angle - original_angle);
+ }
+ else
+ {
+ return angle_weight * M_PI;
+ }
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static float costLength(float original_length, float current_length, float length_weight)
+{
+ if (current_length == 0)
+ {
+ return MAX_COST;
+ }
+ else
+ {
+ float length_ratio = fabs((current_length - original_length) / original_length);
+ return length_weight * length_ratio * length_ratio;
+ }
+}
+
+#if 0
+static float calcCostLengthDistance(BArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec1, float *vec2, int i1, int i2)
+{
+ float vec[3];
+ float length;
+
+ VecSubf(vec, vec2, vec1);
+ length = Normalize(vec);
+
+ return costLength(edge->length, length) + costDistance(iter, vec1, vec2, i1, i2);
+}
+#endif
+
+static float calcCostAngleLengthDistance(BArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec0, float *vec1, float *vec2, int i1, int i2, float angle_weight, float length_weight, float distance_weight)
+{
+ float vec_second[3], vec_first[3];
+ float length2;
+ float new_cost = 0;
+
+ VecSubf(vec_second, vec2, vec1);
+ length2 = Normalize(vec_second);
+
+
+ /* Angle cost */
+ if (edge->prev)
+ {
+ VecSubf(vec_first, vec1, vec0);
+ Normalize(vec_first);
+
+ new_cost += costAngle(edge->prev->angle, vec_first, vec_second, angle_weight);
+ }
+
+ /* Length cost */
+ new_cost += costLength(edge->length, length2, length_weight);
+
+ /* Distance cost */
+ new_cost += costDistance(iter, vec1, vec2, i1, i2, distance_weight);
+
+ return new_cost;
+}
+
+static int indexMemoNode(int nb_positions, int previous, int current, int joints_left)
+{
+ return joints_left * nb_positions * nb_positions + current * nb_positions + previous;
+}
+
+static void copyMemoPositions(int *positions, MemoNode *table, int nb_positions, int joints_left)
+{
+ int previous = 0, current = 0;
+ int i = 0;
+
+ for (i = 0; joints_left > 0; joints_left--, i++)
+ {
+ MemoNode *node;
+ node = table + indexMemoNode(nb_positions, previous, current, joints_left);
+
+ positions[i] = node->next;
+
+ previous = current;
+ current = node->next;
+ }
+}
+
+static MemoNode * solveJoints(MemoNode *table, BArcIterator *iter, float **vec_cache, int nb_joints, int nb_positions, int previous, int current, RigEdge *edge, int joints_left, float angle_weight, float length_weight, float distance_weight)
+{
+ MemoNode *node;
+ int index = indexMemoNode(nb_positions, previous, current, joints_left);
+
+ node = table + index;
+
+ if (node->weight != 0)
+ {
+ return node;
+ }
+ else if (joints_left == 0)
+ {
+ float *vec0 = vec_cache[previous];
+ float *vec1 = vec_cache[current];
+ float *vec2 = vec_cache[nb_positions + 1];
+
+ node->weight = calcCostAngleLengthDistance(iter, vec_cache, edge, vec0, vec1, vec2, current, iter->length, angle_weight, length_weight, distance_weight);
+
+ return node;
+ }
+ else
+ {
+ MemoNode *min_node = NULL;
+ float *vec0 = vec_cache[previous];
+ float *vec1 = vec_cache[current];
+ float min_weight;
+ int min_next;
+ int next;
+
+ for (next = current + 1; next <= nb_positions - (joints_left - 1); next++)
+ {
+ MemoNode *next_node;
+ float *vec2 = vec_cache[next];
+ float weight = 0;
+
+ /* ADD WEIGHT OF PREVIOUS - CURRENT - NEXT triple */
+ weight = calcCostAngleLengthDistance(iter, vec_cache, edge, vec0, vec1, vec2, current, next, angle_weight, length_weight, distance_weight);
+
+ if (weight >= MAX_COST)
+ {
+ continue;
+ }
+
+ /* add node weight */
+ next_node = solveJoints(table, iter, vec_cache, nb_joints, nb_positions, current, next, edge->next, joints_left - 1, angle_weight, length_weight, distance_weight);
+ weight += next_node->weight;
+
+ if (min_node == NULL || weight < min_weight)
+ {
+ min_weight = weight;
+ min_node = next_node;
+ min_next = next;
+ }
+ }
+
+ if (min_node)
+ {
+ node->weight = min_weight;
+ node->next = min_next;
+ return node;
+ }
+ else
+ {
+ node->weight = MAX_COST;
+ return node;
+ }
+ }
+
+}
+
+static int testFlipArc(RigArc *iarc, RigNode *inode_start)
+{
+ ReebArc *earc = iarc->link_mesh;
+ ReebNode *enode_start = BIF_NodeFromIndex(earc, inode_start->link_mesh);
+
+ /* no flip needed if both nodes are the same */
+ if ((enode_start == earc->head && inode_start == iarc->head) || (enode_start == earc->tail && inode_start == iarc->tail))
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+static void retargetArctoArcAggresive(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
+{
+ ReebArcIterator arc_iter;
+ BArcIterator *iter = (BArcIterator*)&arc_iter;
+ RigEdge *edge;
+ EmbedBucket *bucket = NULL;
+ ReebNode *node_start, *node_end;
+ ReebArc *earc = iarc->link_mesh;
+ float angle_weight = 1.0; // GET FROM CONTEXT
+ float length_weight = 1.0;
+ float distance_weight = 1.0;
+ float min_cost = FLT_MAX;
+ float *vec0, *vec1;
+ int *best_positions;
+ int nb_edges = BLI_countlist(&iarc->edges);
+ int nb_joints = nb_edges - 1;
+ RetargetMethod method = METHOD_MEMOIZE;
+ int i;
+
+ if (nb_joints > earc->bcount)
+ {
+ printf("NOT ENOUGH BUCKETS!\n");
+ return;
+ }
+
+ best_positions = MEM_callocN(sizeof(int) * nb_joints, "Best positions");
+
+ if (testFlipArc(iarc, inode_start))
+ {
+ node_start = earc->tail;
+ node_end = earc->head;
+ }
+ else
+ {
+ node_start = earc->head;
+ node_end = earc->tail;
+ }
+
+ /* equal number of joints and potential position, just fill them in */
+ if (nb_joints == earc->bcount)
+ {
+ int i;
+
+ /* init with first values */
+ for (i = 0; i < nb_joints; i++)
+ {
+ best_positions[i] = i + 1;
+ }
+ }
+ if (method == METHOD_MEMOIZE)
+ {
+ int nb_positions = earc->bcount;
+ int nb_memo_nodes = nb_positions * nb_positions * (nb_joints + 1);
+ MemoNode *table = MEM_callocN(nb_memo_nodes * sizeof(MemoNode), "memoization table");
+ MemoNode *result;
+ float **positions_cache = MEM_callocN(sizeof(float*) * (nb_positions + 2), "positions cache");
+ int i;
+
+ positions_cache[0] = node_start->p;
+ positions_cache[nb_positions + 1] = node_end->p;
+
+ initArcIterator(iter, earc, node_start);
+
+ for (i = 1; i <= nb_positions; i++)
+ {
+ EmbedBucket *bucket = IT_peek(iter, i);
+ positions_cache[i] = bucket->p;
+ }
+
+ result = solveJoints(table, iter, positions_cache, nb_joints, earc->bcount, 0, 0, iarc->edges.first, nb_joints, angle_weight, length_weight, distance_weight);
+
+ min_cost = result->weight;
+ copyMemoPositions(best_positions, table, earc->bcount, nb_joints);
+
+ MEM_freeN(table);
+ MEM_freeN(positions_cache);
+ }
+
+ vec0 = node_start->p;
+ initArcIterator(iter, earc, node_start);
+
+#ifndef USE_THREADS
+ printPositions(best_positions, nb_joints);
+ printMovesNeeded(best_positions, nb_joints);
+ printf("min_cost %f\n", min_cost);
+ printf("buckets: %i\n", earc->bcount);
+#endif
+
+ /* set joints to best position */
+ for (edge = iarc->edges.first, i = 0;
+ edge;
+ edge = edge->next, i++)
+ {
+ float *no = NULL;
+ if (i < nb_joints)
+ {
+ bucket = IT_peek(iter, best_positions[i]);
+ vec1 = bucket->p;
+ no = bucket->no;
+ }
+ else
+ {
+ vec1 = node_end->p;
+ no = node_end->no;
+ }
+
+ if (edge->bone)
+ {
+ repositionBone(C, rigg, edge, vec0, vec1, no);
+ }
+
+ vec0 = vec1;
+ }
+
+ MEM_freeN(best_positions);
+}
+
+static void retargetArctoArcLength(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
+{
+ ReebArcIterator arc_iter;
+ BArcIterator *iter = (BArcIterator*)&arc_iter;
+ ReebArc *earc = iarc->link_mesh;
+ ReebNode *node_start, *node_end;
+ RigEdge *edge;
+ EmbedBucket *bucket = NULL;
+ float embedding_length = 0;
+ float *vec0 = NULL;
+ float *vec1 = NULL;
+ float *previous_vec = NULL;
+
+
+ if (testFlipArc(iarc, inode_start))
+ {
+ node_start = (ReebNode*)earc->tail;
+ node_end = (ReebNode*)earc->head;
+ }
+ else
+ {
+ node_start = (ReebNode*)earc->head;
+ node_end = (ReebNode*)earc->tail;
+ }
+
+ initArcIterator(iter, earc, node_start);
+
+ bucket = IT_next(iter);
+
+ vec0 = node_start->p;
+
+ while (bucket != NULL)
+ {
+ vec1 = bucket->p;
+
+ embedding_length += VecLenf(vec0, vec1);
+
+ vec0 = vec1;
+ bucket = IT_next(iter);
+ }
+
+ embedding_length += VecLenf(node_end->p, vec1);
+
+ /* fit bones */
+ initArcIterator(iter, earc, node_start);
+
+ bucket = IT_next(iter);
+
+ vec0 = node_start->p;
+ previous_vec = vec0;
+ vec1 = bucket->p;
+
+ for (edge = iarc->edges.first; edge; edge = edge->next)
+ {
+ float new_bone_length = edge->length / iarc->length * embedding_length;
+ float *no = NULL;
+ float length = 0;
+
+ while (bucket && new_bone_length > length)
+ {
+ length += VecLenf(previous_vec, vec1);
+ bucket = IT_next(iter);
+ previous_vec = vec1;
+ vec1 = bucket->p;
+ no = bucket->no;
+ }
+
+ if (bucket == NULL)
+ {
+ vec1 = node_end->p;
+ no = node_end->no;
+ }
+
+ /* no need to move virtual edges (space between unconnected bones) */
+ if (edge->bone)
+ {
+ repositionBone(C, rigg, edge, vec0, vec1, no);
+ }
+
+ vec0 = vec1;
+ previous_vec = vec1;
+ }
+}
+
+static void retargetArctoArc(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
+{
+#ifdef USE_THREADS
+ RetargetParam *p = MEM_callocN(sizeof(RetargetParam), "RetargetParam");
+
+ p->rigg = rigg;
+ p->iarc = iarc;
+ p->inode_start = inode_start;
+ p->context = C;
+
+ BLI_insert_work(rigg->worker, p);
+#else
+ RetargetParam p;
+
+ p.rigg = rigg;
+ p.iarc = iarc;
+ p.inode_start = inode_start;
+ p.context = C;
+
+ exec_retargetArctoArc(&p);
+#endif
+}
+
+void *exec_retargetArctoArc(void *param)
+{
+ RetargetParam *p = (RetargetParam*)param;
+ RigGraph *rigg = p->rigg;
+ RigArc *iarc = p->iarc;
+ bContext *C = p->context;
+ RigNode *inode_start = p->inode_start;
+ ReebArc *earc = iarc->link_mesh;
+
+ if (BLI_countlist(&iarc->edges) == 1)
+ {
+ RigEdge *edge = iarc->edges.first;
+
+ if (testFlipArc(iarc, inode_start))
+ {
+ repositionBone(C, rigg, edge, earc->tail->p, earc->head->p, earc->head->no);
+ }
+ else
+ {
+ repositionBone(C, rigg, edge, earc->head->p, earc->tail->p, earc->tail->no);
+ }
+ }
+ else
+ {
+ RetargetMode mode = detectArcRetargetMode(iarc);
+
+ if (mode == RETARGET_AGGRESSIVE)
+ {
+ retargetArctoArcAggresive(C, rigg, iarc, inode_start);
+ }
+ else
+ {
+ retargetArctoArcLength(C, rigg, iarc, inode_start);
+ }
+ }
+
+#ifdef USE_THREADS
+ MEM_freeN(p);
+#endif
+
+ return NULL;
+}
+
+static void matchMultiResolutionNode(RigGraph *rigg, RigNode *inode, ReebNode *top_node)
+{
+ ReebNode *enode = top_node;
+ ReebGraph *reebg = BIF_graphForMultiNode(rigg->link_mesh, enode);
+ int ishape, eshape;
+
+ ishape = BLI_subtreeShape((BGraph*)rigg, (BNode*)inode, NULL, 0) % SHAPE_LEVELS;
+ eshape = BLI_subtreeShape((BGraph*)reebg, (BNode*)enode, NULL, 0) % SHAPE_LEVELS;
+
+ inode->link_mesh = enode;
+
+ while (ishape == eshape && enode->link_down)
+ {
+ inode->link_mesh = enode;
+
+ enode = enode->link_down;
+ reebg = BIF_graphForMultiNode(rigg->link_mesh, enode); /* replace with call to link_down once that exists */
+ eshape = BLI_subtreeShape((BGraph*)reebg, (BNode*)enode, NULL, 0) % SHAPE_LEVELS;
+ }
+}
+
+static void markMultiResolutionChildArc(ReebNode *end_enode, ReebNode *enode)
+{
+ int i;
+
+ for(i = 0; i < enode->degree; i++)
+ {
+ ReebArc *earc = (ReebArc*)enode->arcs[i];
+
+ if (earc->flag == ARC_FREE)
+ {
+ earc->flag = ARC_TAKEN;
+
+ if (earc->tail->degree > 1 && earc->tail != end_enode)
+ {
+ markMultiResolutionChildArc(end_enode, earc->tail);
+ }
+ break;
+ }
+ }
+}
+
+static void markMultiResolutionArc(ReebArc *start_earc)
+{
+ if (start_earc->link_up)
+ {
+ ReebArc *earc;
+ for (earc = start_earc->link_up ; earc; earc = earc->link_up)
+ {
+ earc->flag = ARC_TAKEN;
+
+ if (earc->tail->index != start_earc->tail->index)
+ {
+ markMultiResolutionChildArc(earc->tail, earc->tail);
+ }
+ }
+ }
+}
+
+static void matchMultiResolutionArc(RigGraph *rigg, RigNode *start_node, RigArc *next_iarc, ReebArc *next_earc)
+{
+ ReebNode *enode = next_earc->head;
+ ReebGraph *reebg = BIF_graphForMultiNode(rigg->link_mesh, enode);
+ int ishape, eshape;
+
+ ishape = BLI_subtreeShape((BGraph*)rigg, (BNode*)start_node, (BArc*)next_iarc, 1) % SHAPE_LEVELS;
+ eshape = BLI_subtreeShape((BGraph*)reebg, (BNode*)enode, (BArc*)next_earc, 1) % SHAPE_LEVELS;
+
+ while (ishape != eshape && next_earc->link_up)
+ {
+ next_earc->flag = ARC_TAKEN; // mark previous as taken, to prevent backtrack on lower levels
+
+ next_earc = next_earc->link_up;
+ reebg = reebg->link_up;
+ enode = next_earc->head;
+ eshape = BLI_subtreeShape((BGraph*)reebg, (BNode*)enode, (BArc*)next_earc, 1) % SHAPE_LEVELS;
+ }
+
+ next_earc->flag = ARC_USED;
+ next_iarc->link_mesh = next_earc;
+
+ /* mark all higher levels as taken too */
+ markMultiResolutionArc(next_earc);
+// while (next_earc->link_up)
+// {
+// next_earc = next_earc->link_up;
+// next_earc->flag = ARC_TAKEN;
+// }
+}
+
+static void matchMultiResolutionStartingNode(RigGraph *rigg, ReebGraph *reebg, RigNode *inode)
+{
+ ReebNode *enode;
+ int ishape, eshape;
+
+ enode = reebg->nodes.first;
+
+ ishape = BLI_subtreeShape((BGraph*)rigg, (BNode*)inode, NULL, 0) % SHAPE_LEVELS;
+ eshape = BLI_subtreeShape((BGraph*)rigg->link_mesh, (BNode*)enode, NULL, 0) % SHAPE_LEVELS;
+
+ while (ishape != eshape && reebg->link_up)
+ {
+ reebg = reebg->link_up;
+
+ enode = reebg->nodes.first;
+
+ eshape = BLI_subtreeShape((BGraph*)reebg, (BNode*)enode, NULL, 0) % SHAPE_LEVELS;
+ }
+
+ inode->link_mesh = enode;
+}
+
+static void findCorrespondingArc(RigGraph *rigg, RigArc *start_arc, RigNode *start_node, RigArc *next_iarc, int root)
+{
+ ReebNode *enode = start_node->link_mesh;
+ ReebArc *next_earc;
+ int symmetry_level = next_iarc->symmetry_level;
+ int symmetry_group = next_iarc->symmetry_group;
+ int symmetry_flag = next_iarc->symmetry_flag;
+ int i;
+
+ next_iarc->link_mesh = NULL;
+
+// if (root)
+// {
+// printf("-----------------------\n");
+// printf("MATCHING LIMB\n");
+// RIG_printArcBones(next_iarc);
+// }
+
+ for(i = 0; i < enode->degree; i++)
+ {
+ next_earc = (ReebArc*)enode->arcs[i];
+
+// if (next_earc->flag == ARC_FREE)
+// {
+// printf("candidate (level %i ?= %i) (flag %i ?= %i) (group %i ?= %i)\n",
+// symmetry_level, next_earc->symmetry_level,
+// symmetry_flag, next_earc->symmetry_flag,
+// symmetry_group, next_earc->symmetry_flag);
+// }
+
+ if (next_earc->flag == ARC_FREE &&
+ next_earc->symmetry_flag == symmetry_flag &&
+ next_earc->symmetry_group == symmetry_group &&
+ next_earc->symmetry_level == symmetry_level)
+ {
+// printf("CORRESPONDING ARC FOUND\n");
+// printf("flag %i -- level %i -- flag %i -- group %i\n", next_earc->flag, next_earc->symmetry_level, next_earc->symmetry_flag, next_earc->symmetry_group);
+
+ matchMultiResolutionArc(rigg, start_node, next_iarc, next_earc);
+ break;
+ }
+ }
+
+ /* not found, try at higher nodes (lower node might have filtered internal arcs, messing shape of tree */
+ if (next_iarc->link_mesh == NULL)
+ {
+// printf("NO CORRESPONDING ARC FOUND - GOING TO HIGHER LEVELS\n");
+
+ if (enode->link_up)
+ {
+ start_node->link_mesh = enode->link_up;
+ findCorrespondingArc(rigg, start_arc, start_node, next_iarc, 0);
+ }
+ }
+
+ /* still not found, print debug info */
+ if (root && next_iarc->link_mesh == NULL)
+ {
+ start_node->link_mesh = enode; /* linking back with root node */
+
+// printf("NO CORRESPONDING ARC FOUND\n");
+// RIG_printArcBones(next_iarc);
+//
+// printf("ON NODE %i, multilevel %i\n", enode->index, enode->multi_level);
+//
+// printf("LOOKING FOR\n");
+// printf("flag %i -- level %i -- flag %i -- group %i\n", ARC_FREE, symmetry_level, symmetry_flag, symmetry_group);
+//
+// printf("CANDIDATES\n");
+// for(i = 0; i < enode->degree; i++)
+// {
+// next_earc = (ReebArc*)enode->arcs[i];
+// printf("flag %i -- level %i -- flag %i -- group %i\n", next_earc->flag, next_earc->symmetry_level, next_earc->symmetry_flag, next_earc->symmetry_group);
+// }
+
+ /* Emergency matching */
+ for(i = 0; i < enode->degree; i++)
+ {
+ next_earc = (ReebArc*)enode->arcs[i];
+
+ if (next_earc->flag == ARC_FREE && next_earc->symmetry_level == symmetry_level)
+ {
+// printf("USING: \n");
+// printf("flag %i -- level %i -- flag %i -- group %i\n", next_earc->flag, next_earc->symmetry_level, next_earc->symmetry_flag, next_earc->symmetry_group);
+ matchMultiResolutionArc(rigg, start_node, next_iarc, next_earc);
+ break;
+ }
+ }
+ }
+
+}
+
+static void retargetSubgraph(bContext *C, RigGraph *rigg, RigArc *start_arc, RigNode *start_node)
+{
+ RigNode *inode = start_node;
+ int i;
+
+ /* no start arc on first node */
+ if (start_arc)
+ {
+ ReebNode *enode = start_node->link_mesh;
+ ReebArc *earc = start_arc->link_mesh;
+
+ retargetArctoArc(C, rigg, start_arc, start_node);
+
+ enode = BIF_otherNodeFromIndex(earc, enode);
+ inode = (RigNode*)BLI_otherNode((BArc*)start_arc, (BNode*)inode);
+
+ /* match with lowest node with correct shape */
+ matchMultiResolutionNode(rigg, inode, enode);
+ }
+
+ for(i = 0; i < inode->degree; i++)
+ {
+ RigArc *next_iarc = (RigArc*)inode->arcs[i];
+
+ /* no back tracking */
+ if (next_iarc != start_arc)
+ {
+ findCorrespondingArc(rigg, start_arc, inode, next_iarc, 1);
+ if (next_iarc->link_mesh)
+ {
+ retargetSubgraph(C, rigg, next_iarc, inode);
+ }
+ }
+ }
+}
+
+static void finishRetarget(RigGraph *rigg)
+{
+#ifdef USE_THREADS
+ BLI_end_worker(rigg->worker);
+#endif
+}
+
+static void adjustGraphs(bContext *C, RigGraph *rigg)
+{
+ Scene *scene = CTX_data_scene(C);
+ bArmature *arm= rigg->ob->data;
+ RigArc *arc;
+
+ for (arc = rigg->arcs.first; arc; arc = arc->next)
+ {
+ if (arc->link_mesh)
+ {
+ retargetArctoArc(C, rigg, arc, arc->head);
+ }
+ }
+
+ finishRetarget(rigg);
+
+ /* Turn the list into an armature */
+ arm->edbo = rigg->editbones;
+ ED_armature_from_edit(scene, rigg->ob);
+
+ ED_undo_push(C, "Retarget Skeleton");
+}
+
+static void retargetGraphs(bContext *C, RigGraph *rigg)
+{
+ Scene *scene = CTX_data_scene(C);
+ bArmature *arm= rigg->ob->data;
+ ReebGraph *reebg = rigg->link_mesh;
+ RigNode *inode;
+
+ /* flag all ReebArcs as free */
+ BIF_flagMultiArcs(reebg, ARC_FREE);
+
+ /* return to first level */
+ reebg = rigg->link_mesh;
+
+ inode = rigg->head;
+
+ matchMultiResolutionStartingNode(rigg, reebg, inode);
+
+ retargetSubgraph(C, rigg, NULL, inode);
+
+ //generateMissingArcs(rigg);
+
+ finishRetarget(rigg);
+
+ /* Turn the list into an armature */
+ arm->edbo = rigg->editbones;
+ ED_armature_from_edit(scene, rigg->ob);
+}
+
+char *RIG_nameBone(RigGraph *rg, int arc_index, int bone_index)
+{
+ RigArc *arc = BLI_findlink(&rg->arcs, arc_index);
+ RigEdge *iedge;
+
+ if (arc == NULL)
+ {
+ return "None";
+ }
+
+ if (bone_index == BLI_countlist(&arc->edges))
+ {
+ return "Last joint";
+ }
+
+ iedge = BLI_findlink(&arc->edges, bone_index);
+
+ if (iedge == NULL)
+ {
+ return "Done";
+ }
+
+ if (iedge->bone == NULL)
+ {
+ return "Bone offset";
+ }
+
+ return iedge->bone->name;
+}
+
+int RIG_nbJoints(RigGraph *rg)
+{
+ RigArc *arc;
+ int total = 0;
+
+ total += BLI_countlist(&rg->nodes);
+
+ for (arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ total += BLI_countlist(&arc->edges) - 1; /* -1 because end nodes are already counted */
+ }
+
+ return total;
+}
+
+void BIF_freeRetarget()
+{
+ if (GLOBAL_RIGG)
+ {
+ RIG_freeRigGraph((BGraph*)GLOBAL_RIGG);
+ GLOBAL_RIGG = NULL;
+ }
+}
+
+void BIF_retargetArmature(bContext *C)
+{
+ ReebGraph *reebg;
+ double start_time, end_time;
+ double gstart_time, gend_time;
+ double reeb_time, rig_time, retarget_time, total_time;
+
+ gstart_time = start_time = PIL_check_seconds_timer();
+
+ reebg = BIF_ReebGraphMultiFromEditMesh(C);
+
+ end_time = PIL_check_seconds_timer();
+ reeb_time = end_time - start_time;
+
+ printf("Reeb Graph created\n");
+
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ Object *ob = base->object;
+
+ if (ob->type==OB_ARMATURE)
+ {
+ RigGraph *rigg;
+ bArmature *arm;
+
+ arm = ob->data;
+
+ /* Put the armature into editmode */
+
+
+ start_time = PIL_check_seconds_timer();
+
+ rigg = RIG_graphFromArmature(C, ob, arm);
+
+ end_time = PIL_check_seconds_timer();
+ rig_time = end_time - start_time;
+
+ printf("Armature graph created\n");
+
+ //RIG_printGraph(rigg);
+
+ rigg->link_mesh = reebg;
+
+ printf("retargetting %s\n", ob->id.name);
+
+ start_time = PIL_check_seconds_timer();
+
+ retargetGraphs(C, rigg);
+
+ end_time = PIL_check_seconds_timer();
+ retarget_time = end_time - start_time;
+
+ BIF_freeRetarget();
+
+ GLOBAL_RIGG = rigg;
+
+ break; /* only one armature at a time */
+ }
+ }
+ CTX_DATA_END;
+
+
+ gend_time = PIL_check_seconds_timer();
+
+ total_time = gend_time - gstart_time;
+
+ printf("-----------\n");
+ printf("runtime: \t%.3f\n", total_time);
+ printf("reeb: \t\t%.3f (%.1f%%)\n", reeb_time, reeb_time / total_time * 100);
+ printf("rig: \t\t%.3f (%.1f%%)\n", rig_time, rig_time / total_time * 100);
+ printf("retarget: \t%.3f (%.1f%%)\n", retarget_time, retarget_time / total_time * 100);
+ printf("-----------\n");
+
+ ED_undo_push(C, "Retarget Skeleton");
+
+ // XXX
+// allqueue(REDRAWVIEW3D, 0);
+}
+
+void BIF_retargetArc(bContext *C, ReebArc *earc, RigGraph *template_rigg)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ bArmature *armedit = obedit->data;
+ Object *ob;
+ RigGraph *rigg;
+ RigArc *iarc;
+ bArmature *arm;
+ char *side_string = scene->toolsettings->skgen_side_string;
+ char *num_string = scene->toolsettings->skgen_num_string;
+ int free_template = 0;
+
+ if (template_rigg)
+ {
+ ob = template_rigg->ob;
+ arm = ob->data;
+ }
+ else
+ {
+ free_template = 1;
+ ob = obedit;
+ arm = ob->data;
+ template_rigg = armatureSelectedToGraph(C, ob, arm);
+ }
+
+ if (template_rigg->arcs.first == NULL)
+ {
+// XXX
+// error("No Template and no deforming bones selected");
+ return;
+ }
+
+ rigg = cloneRigGraph(template_rigg, armedit->edbo, obedit, side_string, num_string);
+
+ iarc = rigg->arcs.first;
+
+ iarc->link_mesh = earc;
+ iarc->head->link_mesh = earc->head;
+ iarc->tail->link_mesh = earc->tail;
+
+ retargetArctoArc(C, rigg, iarc, iarc->head);
+
+ finishRetarget(rigg);
+
+ /* free template if it comes from the edit armature */
+ if (free_template)
+ {
+ RIG_freeRigGraph((BGraph*)template_rigg);
+ }
+ RIG_freeRigGraph((BGraph*)rigg);
+
+// XXX
+// allqueue(REDRAWVIEW3D, 0);
+}
+
+void BIF_adjustRetarget(bContext *C)
+{
+ if (GLOBAL_RIGG)
+ {
+ adjustGraphs(C, GLOBAL_RIGG);
+ }
+}
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
new file mode 100644
index 00000000000..45605ad472d
--- /dev/null
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -0,0 +1,3383 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_userdef_types.h"
+
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_graph.h"
+#include "BLI_ghash.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_object.h"
+#include "BKE_anim.h"
+#include "BKE_context.h"
+
+#include "ED_view3d.h"
+#include "ED_screen.h"
+
+#include "BIF_gl.h"
+#include "UI_resources.h"
+//#include "BIF_screen.h"
+//#include "BIF_space.h"
+//#include "BIF_mywindow.h"
+#include "ED_armature.h"
+#include "armature_intern.h"
+//#include "BIF_sketch.h"
+#include "BIF_retarget.h"
+#include "BIF_generate.h"
+//#include "BIF_interface.h"
+
+#include "BIF_transform.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+//#include "blendef.h"
+//#include "mydevice.h"
+#include "reeb.h"
+
+typedef enum SK_PType
+{
+ PT_CONTINUOUS,
+ PT_EXACT,
+} SK_PType;
+
+typedef enum SK_PMode
+{
+ PT_SNAP,
+ PT_PROJECT,
+} SK_PMode;
+
+typedef struct SK_Point
+{
+ float p[3];
+ float no[3];
+ SK_PType type;
+ SK_PMode mode;
+} SK_Point;
+
+typedef struct SK_Stroke
+{
+ struct SK_Stroke *next, *prev;
+
+ SK_Point *points;
+ int nb_points;
+ int buf_size;
+ int selected;
+} SK_Stroke;
+
+#define SK_OVERDRAW_LIMIT 5
+
+typedef struct SK_Overdraw
+{
+ SK_Stroke *target;
+ int start, end;
+ int count;
+} SK_Overdraw;
+
+#define SK_Stroke_BUFFER_INIT_SIZE 20
+
+typedef struct SK_DrawData
+{
+ short mval[2];
+ short previous_mval[2];
+ SK_PType type;
+} SK_DrawData;
+
+typedef struct SK_Intersection
+{
+ struct SK_Intersection *next, *prev;
+ SK_Stroke *stroke;
+ int before;
+ int after;
+ int gesture_index;
+ float p[3];
+ float lambda; /* used for sorting intersection points */
+} SK_Intersection;
+
+typedef struct SK_Sketch
+{
+ ListBase strokes;
+ SK_Stroke *active_stroke;
+ SK_Stroke *gesture;
+ SK_Point next_point;
+ SK_Overdraw over;
+} SK_Sketch;
+
+typedef struct SK_StrokeIterator {
+ HeadFct head;
+ TailFct tail;
+ PeekFct peek;
+ NextFct next;
+ NextNFct nextN;
+ PreviousFct previous;
+ StoppedFct stopped;
+
+ float *p, *no;
+
+ int length;
+ int index;
+ /*********************************/
+ SK_Stroke *stroke;
+ int start;
+ int end;
+ int stride;
+} SK_StrokeIterator;
+
+typedef struct SK_Gesture {
+ SK_Stroke *stk;
+ SK_Stroke *segments;
+
+ ListBase intersections;
+ ListBase self_intersections;
+
+ int nb_self_intersections;
+ int nb_intersections;
+ int nb_segments;
+} SK_Gesture;
+
+typedef int (*GestureDetectFct)(bContext*, SK_Gesture*, SK_Sketch *);
+typedef void (*GestureApplyFct)(bContext*, SK_Gesture*, SK_Sketch *);
+
+typedef struct SK_GestureAction {
+ char name[64];
+ GestureDetectFct detect;
+ GestureApplyFct apply;
+} SK_GestureAction;
+
+SK_Sketch *GLOBAL_sketch = NULL;
+SK_Point boneSnap;
+int LAST_SNAP_POINT_VALID = 0;
+float LAST_SNAP_POINT[3];
+
+/******************** PROTOTYPES ******************************/
+
+void initStrokeIterator(BArcIterator *iter, SK_Stroke *stk, int start, int end);
+
+void sk_deleteSelectedStrokes(SK_Sketch *sketch);
+
+void sk_freeStroke(SK_Stroke *stk);
+void sk_freeSketch(SK_Sketch *sketch);
+
+SK_Point *sk_lastStrokePoint(SK_Stroke *stk);
+
+int sk_detectCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
+void sk_applyCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
+int sk_detectTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
+void sk_applyTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
+int sk_detectCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
+void sk_applyCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
+int sk_detectDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
+void sk_applyDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
+int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
+void sk_applyMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
+int sk_detectReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
+void sk_applyReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
+int sk_detectConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
+void sk_applyConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
+
+
+void sk_resetOverdraw(SK_Sketch *sketch);
+int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk);
+
+/******************** GESTURE ACTIONS ******************************/
+
+SK_GestureAction GESTURE_ACTIONS[] =
+ {
+ {"Cut", sk_detectCutGesture, sk_applyCutGesture},
+ {"Trim", sk_detectTrimGesture, sk_applyTrimGesture},
+ {"Command", sk_detectCommandGesture, sk_applyCommandGesture},
+ {"Delete", sk_detectDeleteGesture, sk_applyDeleteGesture},
+ {"Merge", sk_detectMergeGesture, sk_applyMergeGesture},
+ {"Reverse", sk_detectReverseGesture, sk_applyReverseGesture},
+ {"Convert", sk_detectConvertGesture, sk_applyConvertGesture},
+ {"", NULL, NULL}
+ };
+
+/******************** TEMPLATES UTILS *************************/
+
+char *TEMPLATES_MENU = NULL;
+int TEMPLATES_CURRENT = 0;
+GHash *TEMPLATES_HASH = NULL;
+RigGraph *TEMPLATE_RIGG = NULL;
+
+void BIF_makeListTemplates(bContext *C)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ Base *base;
+ int index = 0;
+
+ if (TEMPLATES_HASH != NULL)
+ {
+ BLI_ghash_free(TEMPLATES_HASH, NULL, NULL);
+ }
+
+ TEMPLATES_HASH = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
+ TEMPLATES_CURRENT = 0;
+
+ for ( base = FIRSTBASE; base; base = base->next )
+ {
+ Object *ob = base->object;
+
+ if (ob != obedit && ob->type == OB_ARMATURE)
+ {
+ index++;
+ BLI_ghash_insert(TEMPLATES_HASH, SET_INT_IN_POINTER(index), ob);
+
+ if (ob == scene->toolsettings->skgen_template)
+ {
+ TEMPLATES_CURRENT = index;
+ }
+ }
+ }
+}
+
+char *BIF_listTemplates(bContext *C)
+{
+ GHashIterator ghi;
+ char menu_header[] = "Template%t|None%x0|";
+ char *p;
+
+ if (TEMPLATES_MENU != NULL)
+ {
+ MEM_freeN(TEMPLATES_MENU);
+ }
+
+ TEMPLATES_MENU = MEM_callocN(sizeof(char) * (BLI_ghash_size(TEMPLATES_HASH) * 32 + 30), "skeleton template menu");
+
+ p = TEMPLATES_MENU;
+
+ p += sprintf(TEMPLATES_MENU, "%s", menu_header);
+
+ BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
+
+ while (!BLI_ghashIterator_isDone(&ghi))
+ {
+ Object *ob = BLI_ghashIterator_getValue(&ghi);
+ int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi));
+
+ p += sprintf(p, "|%s%%x%i", ob->id.name+2, key);
+
+ BLI_ghashIterator_step(&ghi);
+ }
+
+ return TEMPLATES_MENU;
+}
+
+int BIF_currentTemplate(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ if (TEMPLATES_CURRENT == 0 && scene->toolsettings->skgen_template != NULL)
+ {
+ GHashIterator ghi;
+ BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
+
+ while (!BLI_ghashIterator_isDone(&ghi))
+ {
+ Object *ob = BLI_ghashIterator_getValue(&ghi);
+ int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi));
+
+ if (ob == scene->toolsettings->skgen_template)
+ {
+ TEMPLATES_CURRENT = key;
+ break;
+ }
+
+ BLI_ghashIterator_step(&ghi);
+ }
+ }
+
+ return TEMPLATES_CURRENT;
+}
+
+RigGraph* sk_makeTemplateGraph(bContext *C, Object *ob)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ if (ob == obedit)
+ {
+ return NULL;
+ }
+
+ if (ob != NULL)
+ {
+ if (TEMPLATE_RIGG && TEMPLATE_RIGG->ob != ob)
+ {
+ RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
+ TEMPLATE_RIGG = NULL;
+ }
+
+ if (TEMPLATE_RIGG == NULL)
+ {
+ bArmature *arm;
+
+ arm = ob->data;
+
+ TEMPLATE_RIGG = RIG_graphFromArmature(C, ob, arm);
+ }
+ }
+
+ return TEMPLATE_RIGG;
+}
+
+int BIF_nbJointsTemplate(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ RigGraph *rg = sk_makeTemplateGraph(C, scene->toolsettings->skgen_template);
+
+ if (rg)
+ {
+ return RIG_nbJoints(rg);
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+char * BIF_nameBoneTemplate(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ SK_Sketch *stk = GLOBAL_sketch;
+ RigGraph *rg;
+ int index = 0;
+
+ if (stk && stk->active_stroke != NULL)
+ {
+ index = stk->active_stroke->nb_points;
+ }
+
+ rg = sk_makeTemplateGraph(C, scene->toolsettings->skgen_template);
+
+ if (rg == NULL)
+ {
+ return "";
+ }
+
+ return RIG_nameBone(rg, 0, index);
+}
+
+void BIF_freeTemplates(bContext *C)
+{
+ if (TEMPLATES_MENU != NULL)
+ {
+ MEM_freeN(TEMPLATES_MENU);
+ TEMPLATES_MENU = NULL;
+ }
+
+ if (TEMPLATES_HASH != NULL)
+ {
+ BLI_ghash_free(TEMPLATES_HASH, NULL, NULL);
+ TEMPLATES_HASH = NULL;
+ }
+
+ if (TEMPLATE_RIGG != NULL)
+ {
+ RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
+ TEMPLATE_RIGG = NULL;
+ }
+}
+
+void BIF_setTemplate(bContext *C, int index)
+{
+ Scene *scene = CTX_data_scene(C);
+ if (index > 0)
+ {
+ scene->toolsettings->skgen_template = BLI_ghash_lookup(TEMPLATES_HASH, SET_INT_IN_POINTER(index));
+ }
+ else
+ {
+ scene->toolsettings->skgen_template = NULL;
+
+ if (TEMPLATE_RIGG != NULL)
+ {
+ RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
+ }
+ TEMPLATE_RIGG = NULL;
+ }
+}
+
+/*********************** CONVERSION ***************************/
+
+void sk_autoname(bContext *C, ReebArc *arc)
+{
+ Scene *scene = CTX_data_scene(C);
+ if (scene->toolsettings->skgen_retarget_options & SK_RETARGET_AUTONAME)
+ {
+ if (arc == NULL)
+ {
+ char *num = scene->toolsettings->skgen_num_string;
+ int i = atoi(num);
+ i++;
+ BLI_snprintf(num, 8, "%i", i);
+ }
+ else
+ {
+ char *side = scene->toolsettings->skgen_side_string;
+ int valid = 0;
+ int caps = 0;
+
+ if (BLI_streq(side, ""))
+ {
+ valid = 1;
+ }
+ else if (BLI_streq(side, "R") || BLI_streq(side, "L"))
+ {
+ valid = 1;
+ caps = 1;
+ }
+ else if (BLI_streq(side, "r") || BLI_streq(side, "l"))
+ {
+ valid = 1;
+ caps = 0;
+ }
+
+ if (valid)
+ {
+ if (arc->head->p[0] < 0)
+ {
+ BLI_snprintf(side, 8, caps?"R":"r");
+ }
+ else
+ {
+ BLI_snprintf(side, 8, caps?"L":"l");
+ }
+ }
+ }
+ }
+}
+
+ReebNode *sk_pointToNode(SK_Point *pt, float imat[][4], float tmat[][3])
+{
+ ReebNode *node;
+
+ node = MEM_callocN(sizeof(ReebNode), "reeb node");
+ VECCOPY(node->p, pt->p);
+ Mat4MulVecfl(imat, node->p);
+
+ VECCOPY(node->no, pt->no);
+ Mat3MulVecfl(tmat, node->no);
+
+ return node;
+}
+
+ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[][4], float tmat[][3])
+{
+ ReebArc *arc;
+ int i;
+
+ arc = MEM_callocN(sizeof(ReebArc), "reeb arc");
+ arc->head = sk_pointToNode(stk->points, imat, tmat);
+ arc->tail = sk_pointToNode(sk_lastStrokePoint(stk), imat, tmat);
+
+ arc->bcount = stk->nb_points - 2; /* first and last are nodes, don't count */
+ arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "Buckets");
+
+ for (i = 0; i < arc->bcount; i++)
+ {
+ VECCOPY(arc->buckets[i].p, stk->points[i + 1].p);
+ Mat4MulVecfl(imat, arc->buckets[i].p);
+
+ VECCOPY(arc->buckets[i].no, stk->points[i + 1].no);
+ Mat3MulVecfl(tmat, arc->buckets[i].no);
+ }
+
+ return arc;
+}
+
+void sk_retargetStroke(bContext *C, SK_Stroke *stk)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ float imat[4][4];
+ float tmat[3][3];
+ ReebArc *arc;
+ RigGraph *rg;
+
+ Mat4Invert(imat, obedit->obmat);
+
+ Mat3CpyMat4(tmat, obedit->obmat);
+ Mat3Transp(tmat);
+
+ arc = sk_strokeToArc(stk, imat, tmat);
+
+ sk_autoname(C, arc);
+
+ rg = sk_makeTemplateGraph(C, scene->toolsettings->skgen_template);
+
+ BIF_retargetArc(C, arc, rg);
+
+ sk_autoname(C, NULL);
+
+ MEM_freeN(arc->head);
+ MEM_freeN(arc->tail);
+ REEB_freeArc((BArc*)arc);
+}
+
+/**************************************************************/
+
+void sk_freeSketch(SK_Sketch *sketch)
+{
+ SK_Stroke *stk, *next;
+
+ for (stk = sketch->strokes.first; stk; stk = next)
+ {
+ next = stk->next;
+
+ sk_freeStroke(stk);
+ }
+
+ MEM_freeN(sketch);
+}
+
+SK_Sketch* sk_createSketch()
+{
+ SK_Sketch *sketch;
+
+ sketch = MEM_callocN(sizeof(SK_Sketch), "SK_Sketch");
+
+ sketch->active_stroke = NULL;
+ sketch->gesture = NULL;
+
+ sketch->strokes.first = NULL;
+ sketch->strokes.last = NULL;
+
+ return sketch;
+}
+
+void sk_initPoint(bContext *C, SK_Point *pt)
+{
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ VECCOPY(pt->no, rv3d->viewinv[2]);
+ Normalize(pt->no);
+ /* more init code here */
+}
+
+void sk_copyPoint(SK_Point *dst, SK_Point *src)
+{
+ memcpy(dst, src, sizeof(SK_Point));
+}
+
+void sk_allocStrokeBuffer(SK_Stroke *stk)
+{
+ stk->points = MEM_callocN(sizeof(SK_Point) * stk->buf_size, "SK_Point buffer");
+}
+
+void sk_freeStroke(SK_Stroke *stk)
+{
+ MEM_freeN(stk->points);
+ MEM_freeN(stk);
+}
+
+SK_Stroke* sk_createStroke()
+{
+ SK_Stroke *stk;
+
+ stk = MEM_callocN(sizeof(SK_Stroke), "SK_Stroke");
+
+ stk->selected = 0;
+ stk->nb_points = 0;
+ stk->buf_size = SK_Stroke_BUFFER_INIT_SIZE;
+
+ sk_allocStrokeBuffer(stk);
+
+ return stk;
+}
+
+void sk_shrinkStrokeBuffer(SK_Stroke *stk)
+{
+ if (stk->nb_points < stk->buf_size)
+ {
+ SK_Point *old_points = stk->points;
+
+ stk->buf_size = stk->nb_points;
+
+ sk_allocStrokeBuffer(stk);
+
+ memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
+
+ MEM_freeN(old_points);
+ }
+}
+
+void sk_growStrokeBuffer(SK_Stroke *stk)
+{
+ if (stk->nb_points == stk->buf_size)
+ {
+ SK_Point *old_points = stk->points;
+
+ stk->buf_size *= 2;
+
+ sk_allocStrokeBuffer(stk);
+
+ memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
+
+ MEM_freeN(old_points);
+ }
+}
+
+void sk_growStrokeBufferN(SK_Stroke *stk, int n)
+{
+ if (stk->nb_points + n > stk->buf_size)
+ {
+ SK_Point *old_points = stk->points;
+
+ while (stk->nb_points + n > stk->buf_size)
+ {
+ stk->buf_size *= 2;
+ }
+
+ sk_allocStrokeBuffer(stk);
+
+ memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
+
+ MEM_freeN(old_points);
+ }
+}
+
+
+void sk_replaceStrokePoint(SK_Stroke *stk, SK_Point *pt, int n)
+{
+ memcpy(stk->points + n, pt, sizeof(SK_Point));
+}
+
+void sk_insertStrokePoint(SK_Stroke *stk, SK_Point *pt, int n)
+{
+ int size = stk->nb_points - n;
+
+ sk_growStrokeBuffer(stk);
+
+ memmove(stk->points + n + 1, stk->points + n, size * sizeof(SK_Point));
+
+ memcpy(stk->points + n, pt, sizeof(SK_Point));
+
+ stk->nb_points++;
+}
+
+void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt)
+{
+ sk_growStrokeBuffer(stk);
+
+ memcpy(stk->points + stk->nb_points, pt, sizeof(SK_Point));
+
+ stk->nb_points++;
+}
+
+void sk_insertStrokePoints(SK_Stroke *stk, SK_Point *pts, int len, int start, int end)
+{
+ int size = end - start + 1;
+
+ sk_growStrokeBufferN(stk, len - size);
+
+ if (len != size)
+ {
+ int tail_size = stk->nb_points - end + 1;
+
+ memmove(stk->points + start + len, stk->points + end + 1, tail_size * sizeof(SK_Point));
+ }
+
+ memcpy(stk->points + start, pts, len * sizeof(SK_Point));
+
+ stk->nb_points += len - size;
+}
+
+void sk_trimStroke(SK_Stroke *stk, int start, int end)
+{
+ int size = end - start + 1;
+
+ if (start > 0)
+ {
+ memmove(stk->points, stk->points + start, size * sizeof(SK_Point));
+ }
+
+ stk->nb_points = size;
+}
+
+void sk_straightenStroke(SK_Stroke *stk, int start, int end, float p_start[3], float p_end[3])
+{
+ SK_Point pt1, pt2;
+ SK_Point *prev, *next;
+ float delta_p[3];
+ int i, total;
+
+ total = end - start;
+
+ VecSubf(delta_p, p_end, p_start);
+
+ prev = stk->points + start;
+ next = stk->points + end;
+
+ VECCOPY(pt1.p, p_start);
+ VECCOPY(pt1.no, prev->no);
+ pt1.mode = prev->mode;
+ pt1.type = prev->type;
+
+ VECCOPY(pt2.p, p_end);
+ VECCOPY(pt2.no, next->no);
+ pt2.mode = next->mode;
+ pt2.type = next->type;
+
+ sk_insertStrokePoint(stk, &pt1, start + 1); /* insert after start */
+ sk_insertStrokePoint(stk, &pt2, end + 1); /* insert before end (since end was pushed back already) */
+
+ for (i = 1; i < total; i++)
+ {
+ float delta = (float)i / (float)total;
+ float *p = stk->points[start + 1 + i].p;
+
+ VECCOPY(p, delta_p);
+ VecMulf(p, delta);
+ VecAddf(p, p, p_start);
+ }
+}
+
+void sk_polygonizeStroke(SK_Stroke *stk, int start, int end)
+{
+ int offset;
+ int i;
+
+ /* find first exact points outside of range */
+ for (;start > 0; start--)
+ {
+ if (stk->points[start].type == PT_EXACT)
+ {
+ break;
+ }
+ }
+
+ for (;end < stk->nb_points - 1; end++)
+ {
+ if (stk->points[end].type == PT_EXACT)
+ {
+ break;
+ }
+ }
+
+ offset = start + 1;
+
+ for (i = start + 1; i < end; i++)
+ {
+ if (stk->points[i].type == PT_EXACT)
+ {
+ if (offset != i)
+ {
+ memcpy(stk->points + offset, stk->points + i, sizeof(SK_Point));
+ }
+
+ offset++;
+ }
+ }
+
+ /* some points were removes, move end of array */
+ if (offset < end)
+ {
+ int size = stk->nb_points - end;
+ memmove(stk->points + offset, stk->points + end, size * sizeof(SK_Point));
+ stk->nb_points = offset + size;
+ }
+}
+
+void sk_flattenStroke(SK_Stroke *stk, int start, int end)
+{
+ float normal[3], distance[3];
+ float limit;
+ int i, total;
+
+ total = end - start + 1;
+
+ VECCOPY(normal, stk->points[start].no);
+
+ VecSubf(distance, stk->points[end].p, stk->points[start].p);
+ Projf(normal, distance, normal);
+ limit = Normalize(normal);
+
+ for (i = 1; i < total - 1; i++)
+ {
+ float d = limit * i / total;
+ float offset[3];
+ float *p = stk->points[start + i].p;
+
+ VecSubf(distance, p, stk->points[start].p);
+ Projf(distance, distance, normal);
+
+ VECCOPY(offset, normal);
+ VecMulf(offset, d);
+
+ VecSubf(p, p, distance);
+ VecAddf(p, p, offset);
+ }
+}
+
+void sk_removeStroke(SK_Sketch *sketch, SK_Stroke *stk)
+{
+ if (sketch->active_stroke == stk)
+ {
+ sketch->active_stroke = NULL;
+ }
+
+ BLI_remlink(&sketch->strokes, stk);
+ sk_freeStroke(stk);
+}
+
+void sk_reverseStroke(SK_Stroke *stk)
+{
+ SK_Point *old_points = stk->points;
+ int i = 0;
+
+ sk_allocStrokeBuffer(stk);
+
+ for (i = 0; i < stk->nb_points; i++)
+ {
+ sk_copyPoint(stk->points + i, old_points + stk->nb_points - 1 - i);
+ }
+
+ MEM_freeN(old_points);
+}
+
+
+void sk_cancelStroke(SK_Sketch *sketch)
+{
+ if (sketch->active_stroke != NULL)
+ {
+ sk_resetOverdraw(sketch);
+ sk_removeStroke(sketch, sketch->active_stroke);
+ }
+}
+
+/* Apply reverse Chaikin filter to simplify the polyline
+ * */
+void sk_filterStroke(SK_Stroke *stk, int start, int end)
+{
+ SK_Point *old_points = stk->points;
+ int nb_points = stk->nb_points;
+ int i, j;
+
+ return;
+
+ if (start == -1)
+ {
+ start = 0;
+ end = stk->nb_points - 1;
+ }
+
+ sk_allocStrokeBuffer(stk);
+ stk->nb_points = 0;
+
+ /* adding points before range */
+ for (i = 0; i < start; i++)
+ {
+ sk_appendStrokePoint(stk, old_points + i);
+ }
+
+ for (i = start, j = start; i <= end; i++)
+ {
+ if (i - j == 3)
+ {
+ SK_Point pt;
+ float vec[3];
+
+ sk_copyPoint(&pt, &old_points[j+1]);
+
+ pt.p[0] = 0;
+ pt.p[1] = 0;
+ pt.p[2] = 0;
+
+ VECCOPY(vec, old_points[j].p);
+ VecMulf(vec, -0.25);
+ VecAddf(pt.p, pt.p, vec);
+
+ VECCOPY(vec, old_points[j+1].p);
+ VecMulf(vec, 0.75);
+ VecAddf(pt.p, pt.p, vec);
+
+ VECCOPY(vec, old_points[j+2].p);
+ VecMulf(vec, 0.75);
+ VecAddf(pt.p, pt.p, vec);
+
+ VECCOPY(vec, old_points[j+3].p);
+ VecMulf(vec, -0.25);
+ VecAddf(pt.p, pt.p, vec);
+
+ sk_appendStrokePoint(stk, &pt);
+
+ j += 2;
+ }
+
+ /* this might be uneeded when filtering last continuous stroke */
+ if (old_points[i].type == PT_EXACT)
+ {
+ sk_appendStrokePoint(stk, old_points + i);
+ j = i;
+ }
+ }
+
+ /* adding points after range */
+ for (i = end + 1; i < nb_points; i++)
+ {
+ sk_appendStrokePoint(stk, old_points + i);
+ }
+
+ MEM_freeN(old_points);
+
+ sk_shrinkStrokeBuffer(stk);
+}
+
+void sk_filterLastContinuousStroke(SK_Stroke *stk)
+{
+ int start, end;
+
+ end = stk->nb_points -1;
+
+ for (start = end - 1; start > 0 && stk->points[start].type == PT_CONTINUOUS; start--)
+ {
+ /* nothing to do here*/
+ }
+
+ if (end - start > 1)
+ {
+ sk_filterStroke(stk, start, end);
+ }
+}
+
+SK_Point *sk_lastStrokePoint(SK_Stroke *stk)
+{
+ SK_Point *pt = NULL;
+
+ if (stk->nb_points > 0)
+ {
+ pt = stk->points + (stk->nb_points - 1);
+ }
+
+ return pt;
+}
+
+void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int end)
+{
+ float rgb[3];
+ int i;
+
+ if (id != -1)
+ {
+ glLoadName(id);
+
+ glBegin(GL_LINE_STRIP);
+
+ for (i = 0; i < stk->nb_points; i++)
+ {
+ glVertex3fv(stk->points[i].p);
+ }
+
+ glEnd();
+
+ }
+ else
+ {
+ float d_rgb[3] = {1, 1, 1};
+
+ VECCOPY(rgb, color);
+ VecSubf(d_rgb, d_rgb, rgb);
+ VecMulf(d_rgb, 1.0f / (float)stk->nb_points);
+
+ glBegin(GL_LINE_STRIP);
+
+ for (i = 0; i < stk->nb_points; i++)
+ {
+ if (i >= start && i <= end)
+ {
+ glColor3f(0.3, 0.3, 0.3);
+ }
+ else
+ {
+ glColor3fv(rgb);
+ }
+ glVertex3fv(stk->points[i].p);
+ VecAddf(rgb, rgb, d_rgb);
+ }
+
+ glEnd();
+
+#if 0
+ glColor3f(0, 0, 1);
+ glBegin(GL_LINES);
+
+ for (i = 0; i < stk->nb_points; i++)
+ {
+ float *p = stk->points[i].p;
+ float *no = stk->points[i].no;
+ glVertex3fv(p);
+ glVertex3f(p[0] + no[0], p[1] + no[1], p[2] + no[2]);
+ }
+
+ glEnd();
+#endif
+
+ glColor3f(0, 0, 0);
+ glBegin(GL_POINTS);
+
+ for (i = 0; i < stk->nb_points; i++)
+ {
+ if (stk->points[i].type == PT_EXACT)
+ {
+ glVertex3fv(stk->points[i].p);
+ }
+ }
+
+ glEnd();
+ }
+
+// glColor3f(1, 1, 1);
+// glBegin(GL_POINTS);
+//
+// for (i = 0; i < stk->nb_points; i++)
+// {
+// if (stk->points[i].type == PT_CONTINUOUS)
+// {
+// glVertex3fv(stk->points[i].p);
+// }
+// }
+//
+// glEnd();
+}
+
+void drawSubdividedStrokeBy(ToolSettings *toolsettings, BArcIterator *iter, NextSubdivisionFunc next_subdividion)
+{
+ float head[3], tail[3];
+ int bone_start = 0;
+ int end = iter->length;
+ int index;
+
+ iter->head(iter);
+ VECCOPY(head, iter->p);
+
+ glColor3f(0, 1, 0);
+ glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) * 2);
+ glBegin(GL_POINTS);
+
+ index = next_subdividion(toolsettings, iter, bone_start, end, head, tail);
+ while (index != -1)
+ {
+ glVertex3fv(tail);
+
+ VECCOPY(head, tail);
+ bone_start = index; // start next bone from current index
+
+ index = next_subdividion(toolsettings, iter, bone_start, end, head, tail);
+ }
+
+ glEnd();
+ glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+}
+
+void sk_drawStrokeSubdivision(ToolSettings *toolsettings, SK_Stroke *stk)
+{
+ int head_index = -1;
+ int i;
+
+ if (toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
+ {
+ return;
+ }
+
+
+ for (i = 0; i < stk->nb_points; i++)
+ {
+ SK_Point *pt = stk->points + i;
+
+ if (pt->type == PT_EXACT || i == stk->nb_points - 1) /* stop on exact or on last point */
+ {
+ if (head_index == -1)
+ {
+ head_index = i;
+ }
+ else
+ {
+ if (i - head_index > 1)
+ {
+ SK_StrokeIterator sk_iter;
+ BArcIterator *iter = (BArcIterator*)&sk_iter;
+
+ initStrokeIterator(iter, stk, head_index, i);
+
+ if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
+ {
+ drawSubdividedStrokeBy(toolsettings, iter, nextAdaptativeSubdivision);
+ }
+ else if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
+ {
+ drawSubdividedStrokeBy(toolsettings, iter, nextLengthSubdivision);
+ }
+ else if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
+ {
+ drawSubdividedStrokeBy(toolsettings, iter, nextFixedSubdivision);
+ }
+
+ }
+
+ head_index = i;
+ }
+ }
+ }
+}
+
+SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, short mval[2], int *dist, int *index, int all_pts)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SK_Point *pt = NULL;
+ int i;
+
+ for (i = 0; i < stk->nb_points; i++)
+ {
+ if (all_pts || stk->points[i].type == PT_EXACT)
+ {
+ short pval[2];
+ int pdist;
+
+ project_short_noclip(ar, stk->points[i].p, pval);
+
+ pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
+
+ if (pdist < *dist)
+ {
+ *dist = pdist;
+ pt = stk->points + i;
+
+ if (index != NULL)
+ {
+ *index = i;
+ }
+ }
+ }
+ }
+
+ return pt;
+}
+
+SK_Point *sk_snapPointArmature(bContext *C, Object *ob, ListBase *ebones, short mval[2], int *dist)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SK_Point *pt = NULL;
+ EditBone *bone;
+
+ for (bone = ebones->first; bone; bone = bone->next)
+ {
+ float vec[3];
+ short pval[2];
+ int pdist;
+
+ if ((bone->flag & BONE_CONNECTED) == 0)
+ {
+ VECCOPY(vec, bone->head);
+ Mat4MulVecfl(ob->obmat, vec);
+ project_short_noclip(ar, vec, pval);
+
+ pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
+
+ if (pdist < *dist)
+ {
+ *dist = pdist;
+ pt = &boneSnap;
+ VECCOPY(pt->p, vec);
+ pt->type = PT_EXACT;
+ }
+ }
+
+
+ VECCOPY(vec, bone->tail);
+ Mat4MulVecfl(ob->obmat, vec);
+ project_short_noclip(ar, vec, pval);
+
+ pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
+
+ if (pdist < *dist)
+ {
+ *dist = pdist;
+ pt = &boneSnap;
+ VECCOPY(pt->p, vec);
+ pt->type = PT_EXACT;
+ }
+ }
+
+ return pt;
+}
+
+void sk_resetOverdraw(SK_Sketch *sketch)
+{
+ sketch->over.target = NULL;
+ sketch->over.start = -1;
+ sketch->over.end = -1;
+ sketch->over.count = 0;
+}
+
+int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk)
+{
+ return sketch->over.target &&
+ sketch->over.count >= SK_OVERDRAW_LIMIT &&
+ (sketch->over.target == stk || stk == NULL) &&
+ (sketch->over.start != -1 || sketch->over.end != -1);
+}
+
+void sk_updateOverdraw(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
+{
+ if (sketch->over.target == NULL)
+ {
+ SK_Stroke *target;
+ int closest_index = -1;
+ int dist = SNAP_MIN_DISTANCE * 2;
+
+// /* If snapping, don't start overdraw */ Can't do that, snap is embed too now
+// if (sk_lastStrokePoint(stk)->mode == PT_SNAP)
+// {
+// return;
+// }
+
+ for (target = sketch->strokes.first; target; target = target->next)
+ {
+ if (target != stk)
+ {
+ int index;
+
+ SK_Point *spt = sk_snapPointStroke(C, target, dd->mval, &dist, &index, 1);
+
+ if (spt != NULL)
+ {
+ sketch->over.target = target;
+ closest_index = index;
+ }
+ }
+ }
+
+ if (sketch->over.target != NULL)
+ {
+ if (closest_index > -1)
+ {
+ if (sk_lastStrokePoint(stk)->type == PT_EXACT)
+ {
+ sketch->over.count = SK_OVERDRAW_LIMIT;
+ }
+ else
+ {
+ sketch->over.count++;
+ }
+ }
+
+ if (stk->nb_points == 1)
+ {
+ sketch->over.start = closest_index;
+ }
+ else
+ {
+ sketch->over.end = closest_index;
+ }
+ }
+ }
+ else if (sketch->over.target != NULL)
+ {
+ SK_Point *closest_pt = NULL;
+ int dist = SNAP_MIN_DISTANCE * 2;
+ int index;
+
+ closest_pt = sk_snapPointStroke(C, sketch->over.target, dd->mval, &dist, &index, 1);
+
+ if (closest_pt != NULL)
+ {
+ if (sk_lastStrokePoint(stk)->type == PT_EXACT)
+ {
+ sketch->over.count = SK_OVERDRAW_LIMIT;
+ }
+ else
+ {
+ sketch->over.count++;
+ }
+
+ sketch->over.end = index;
+ }
+ else
+ {
+ sketch->over.end = -1;
+ }
+ }
+}
+
+/* return 1 on reverse needed */
+int sk_adjustIndexes(SK_Sketch *sketch, int *start, int *end)
+{
+ int retval = 0;
+
+ *start = sketch->over.start;
+ *end = sketch->over.end;
+
+ if (*start == -1)
+ {
+ *start = 0;
+ }
+
+ if (*end == -1)
+ {
+ *end = sketch->over.target->nb_points - 1;
+ }
+
+ if (*end < *start)
+ {
+ int tmp = *start;
+ *start = *end;
+ *end = tmp;
+ retval = 1;
+ }
+
+ return retval;
+}
+
+void sk_endOverdraw(SK_Sketch *sketch)
+{
+ SK_Stroke *stk = sketch->active_stroke;
+
+ if (sk_hasOverdraw(sketch, NULL))
+ {
+ int start;
+ int end;
+
+ if (sk_adjustIndexes(sketch, &start, &end))
+ {
+ sk_reverseStroke(stk);
+ }
+
+ if (stk->nb_points > 1)
+ {
+ stk->points->type = sketch->over.target->points[start].type;
+ sk_lastStrokePoint(stk)->type = sketch->over.target->points[end].type;
+ }
+
+ sk_insertStrokePoints(sketch->over.target, stk->points, stk->nb_points, start, end);
+
+ sk_removeStroke(sketch, stk);
+
+ sk_resetOverdraw(sketch);
+ }
+}
+
+
+void sk_startStroke(SK_Sketch *sketch)
+{
+ SK_Stroke *stk = sk_createStroke();
+
+ BLI_addtail(&sketch->strokes, stk);
+ sketch->active_stroke = stk;
+
+ sk_resetOverdraw(sketch);
+}
+
+void sk_endStroke(bContext *C, SK_Sketch *sketch)
+{
+ Scene *scene = CTX_data_scene(C);
+ sk_shrinkStrokeBuffer(sketch->active_stroke);
+
+ if (scene->toolsettings->bone_sketching & BONE_SKETCHING_ADJUST)
+ {
+ sk_endOverdraw(sketch);
+ }
+
+ sketch->active_stroke = NULL;
+}
+
+void sk_updateDrawData(SK_DrawData *dd)
+{
+ dd->type = PT_CONTINUOUS;
+
+ dd->previous_mval[0] = dd->mval[0];
+ dd->previous_mval[1] = dd->mval[1];
+}
+
+float sk_distanceDepth(bContext *C, float p1[3], float p2[3])
+{
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ float vec[3];
+ float distance;
+
+ VecSubf(vec, p1, p2);
+
+ Projf(vec, vec, rv3d->viewinv[2]);
+
+ distance = VecLength(vec);
+
+ if (Inpf(rv3d->viewinv[2], vec) > 0)
+ {
+ distance *= -1;
+ }
+
+ return distance;
+}
+
+void sk_interpolateDepth(bContext *C, SK_Stroke *stk, int start, int end, float length, float distance)
+{
+ ARegion *ar = CTX_wm_region(C);
+ ScrArea *sa = CTX_wm_area(C);
+ View3D *v3d = sa->spacedata.first;
+
+ float progress = 0;
+ int i;
+
+ progress = VecLenf(stk->points[start].p, stk->points[start - 1].p);
+
+ for (i = start; i <= end; i++)
+ {
+ float ray_start[3], ray_normal[3];
+ float delta = VecLenf(stk->points[i].p, stk->points[i + 1].p);
+ short pval[2];
+
+ project_short_noclip(ar, stk->points[i].p, pval);
+ viewray(ar, v3d, pval, ray_start, ray_normal);
+
+ VecMulf(ray_normal, distance * progress / length);
+ VecAddf(stk->points[i].p, stk->points[i].p, ray_normal);
+
+ progress += delta ;
+ }
+}
+
+void sk_projectDrawPoint(bContext *C, float vec[3], SK_Stroke *stk, SK_DrawData *dd)
+{
+ ARegion *ar = CTX_wm_region(C);
+ /* copied from grease pencil, need fixing */
+ SK_Point *last = sk_lastStrokePoint(stk);
+ short cval[2];
+ float fp[3] = {0, 0, 0};
+ float dvec[3];
+
+ if (last != NULL)
+ {
+ VECCOPY(fp, last->p);
+ }
+
+ initgrabz(ar->regiondata, fp[0], fp[1], fp[2]);
+
+ /* method taken from editview.c - mouse_cursor() */
+ project_short_noclip(ar, fp, cval);
+ window_to_3d_delta(ar, dvec, cval[0] - dd->mval[0], cval[1] - dd->mval[1]);
+ VecSubf(vec, fp, dvec);
+}
+
+int sk_getStrokeDrawPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
+{
+ pt->type = dd->type;
+ pt->mode = PT_PROJECT;
+ sk_projectDrawPoint(C, pt->p, stk, dd);
+
+ return 1;
+}
+
+int sk_addStrokeDrawPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
+{
+ SK_Point pt;
+
+ sk_initPoint(C, &pt);
+
+ sk_getStrokeDrawPoint(C, &pt, sketch, stk, dd);
+
+ sk_appendStrokePoint(stk, &pt);
+
+ return 1;
+}
+
+int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
+{
+ Scene *scene = CTX_data_scene(C);
+ int point_added = 0;
+
+ if (scene->snap_mode == SCE_SNAP_MODE_VOLUME)
+ {
+ ListBase depth_peels;
+ DepthPeel *p1, *p2;
+ float *last_p = NULL;
+ float dist = FLT_MAX;
+ float p[3];
+
+ depth_peels.first = depth_peels.last = NULL;
+
+ peelObjectsContext(C, &depth_peels, dd->mval);
+
+ if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS)
+ {
+ last_p = stk->points[stk->nb_points - 1].p;
+ }
+ else if (LAST_SNAP_POINT_VALID)
+ {
+ last_p = LAST_SNAP_POINT;
+ }
+
+
+ for (p1 = depth_peels.first; p1; p1 = p1->next)
+ {
+ if (p1->flag == 0)
+ {
+ float vec[3];
+ float new_dist;
+
+ p2 = NULL;
+ p1->flag = 1;
+
+ /* if peeling objects, take the first and last from each object */
+ if (scene->snap_flag & SCE_SNAP_PEEL_OBJECT)
+ {
+ DepthPeel *peel;
+ for (peel = p1->next; peel; peel = peel->next)
+ {
+ if (peel->ob == p1->ob)
+ {
+ peel->flag = 1;
+ p2 = peel;
+ }
+ }
+ }
+ /* otherwise, pair first with second and so on */
+ else
+ {
+ for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next)
+ {
+ /* nothing to do here */
+ }
+ }
+
+ if (p2)
+ {
+ p2->flag = 1;
+
+ VecAddf(vec, p1->p, p2->p);
+ VecMulf(vec, 0.5f);
+ }
+ else
+ {
+ VECCOPY(vec, p1->p);
+ }
+
+ if (last_p == NULL)
+ {
+ VECCOPY(p, vec);
+ dist = 0;
+ break;
+ }
+
+ new_dist = VecLenf(last_p, vec);
+
+ if (new_dist < dist)
+ {
+ VECCOPY(p, vec);
+ dist = new_dist;
+ }
+ }
+ }
+
+ if (dist != FLT_MAX)
+ {
+ pt->type = dd->type;
+ pt->mode = PT_SNAP;
+ VECCOPY(pt->p, p);
+
+ point_added = 1;
+ }
+
+ BLI_freelistN(&depth_peels);
+ }
+ else
+ {
+ SK_Stroke *snap_stk;
+ float vec[3];
+ float no[3];
+ int found = 0;
+ int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
+
+ /* snap to strokes */
+ // if (scene->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */
+ for (snap_stk = sketch->strokes.first; snap_stk; snap_stk = snap_stk->next)
+ {
+ SK_Point *spt = NULL;
+ if (snap_stk == stk)
+ {
+ spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 0);
+ }
+ else
+ {
+ spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 1);
+ }
+
+ if (spt != NULL)
+ {
+ VECCOPY(pt->p, spt->p);
+ point_added = 1;
+ }
+ }
+
+ /* try to snap to closer object */
+ found = snapObjectsContext(C, dd->mval, &dist, vec, no, SNAP_NOT_SELECTED);
+ if (found == 1)
+ {
+ pt->type = dd->type;
+ pt->mode = PT_SNAP;
+ VECCOPY(pt->p, vec);
+
+ point_added = 1;
+ }
+ }
+
+ return point_added;
+}
+
+int sk_addStrokeSnapPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
+{
+ int point_added;
+ SK_Point pt;
+
+ sk_initPoint(C, &pt);
+
+ point_added = sk_getStrokeSnapPoint(C, &pt, sketch, stk, dd);
+
+ if (point_added)
+ {
+ float final_p[3];
+ float length, distance;
+ int total;
+ int i;
+
+ VECCOPY(final_p, pt.p);
+
+ sk_projectDrawPoint(C, pt.p, stk, dd);
+ sk_appendStrokePoint(stk, &pt);
+
+ /* update all previous point to give smooth Z progresion */
+ total = 0;
+ length = 0;
+ for (i = stk->nb_points - 2; i > 0; i--)
+ {
+ length += VecLenf(stk->points[i].p, stk->points[i + 1].p);
+ total++;
+ if (stk->points[i].mode == PT_SNAP || stk->points[i].type == PT_EXACT)
+ {
+ break;
+ }
+ }
+
+ if (total > 1)
+ {
+ distance = sk_distanceDepth(C, final_p, stk->points[i].p);
+
+ sk_interpolateDepth(C, stk, i + 1, stk->nb_points - 2, length, distance);
+ }
+
+ VECCOPY(stk->points[stk->nb_points - 1].p, final_p);
+
+ point_added = 1;
+ }
+
+ return point_added;
+}
+
+void sk_addStrokePoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
+{
+ Scene *scene = CTX_data_scene(C);
+ int point_added = 0;
+
+ if (snap)
+ {
+ point_added = sk_addStrokeSnapPoint(C, sketch, stk, dd);
+ }
+
+ if (point_added == 0)
+ {
+ point_added = sk_addStrokeDrawPoint(C, sketch, stk, dd);
+ }
+
+ if (stk == sketch->active_stroke && scene->toolsettings->bone_sketching & BONE_SKETCHING_ADJUST)
+ {
+ sk_updateOverdraw(C, sketch, stk, dd);
+ }
+}
+
+void sk_getStrokePoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
+{
+ int point_added = 0;
+
+ if (snap)
+ {
+ point_added = sk_getStrokeSnapPoint(C, pt, sketch, stk, dd);
+ LAST_SNAP_POINT_VALID = 1;
+ VECCOPY(LAST_SNAP_POINT, pt->p);
+ }
+ else
+ {
+ LAST_SNAP_POINT_VALID = 0;
+ }
+
+ if (point_added == 0)
+ {
+ point_added = sk_getStrokeDrawPoint(C, pt, sketch, stk, dd);
+ }
+}
+
+void sk_endContinuousStroke(SK_Stroke *stk)
+{
+ stk->points[stk->nb_points - 1].type = PT_EXACT;
+}
+
+void sk_updateNextPoint(SK_Sketch *sketch, SK_Stroke *stk)
+{
+ if (stk)
+ {
+ memcpy(&sketch->next_point, stk->points[stk->nb_points - 1].p, sizeof(SK_Point));
+ }
+}
+
+int sk_stroke_filtermval(SK_DrawData *dd)
+{
+ int retval = 0;
+ if (ABS(dd->mval[0] - dd->previous_mval[0]) + ABS(dd->mval[1] - dd->previous_mval[1]) > U.gp_manhattendist)
+ {
+ retval = 1;
+ }
+
+ return retval;
+}
+
+void sk_initDrawData(SK_DrawData *dd, short mval[2])
+{
+ dd->mval[0] = mval[0];
+ dd->mval[1] = mval[1];
+ dd->previous_mval[0] = -1;
+ dd->previous_mval[1] = -1;
+ dd->type = PT_EXACT;
+}
+/********************************************/
+
+static void* headPoint(void *arg);
+static void* tailPoint(void *arg);
+static void* nextPoint(void *arg);
+static void* nextNPoint(void *arg, int n);
+static void* peekPoint(void *arg, int n);
+static void* previousPoint(void *arg);
+static int iteratorStopped(void *arg);
+
+static void initIteratorFct(SK_StrokeIterator *iter)
+{
+ iter->head = headPoint;
+ iter->tail = tailPoint;
+ iter->peek = peekPoint;
+ iter->next = nextPoint;
+ iter->nextN = nextNPoint;
+ iter->previous = previousPoint;
+ iter->stopped = iteratorStopped;
+}
+
+static SK_Point* setIteratorValues(SK_StrokeIterator *iter, int index)
+{
+ SK_Point *pt = NULL;
+
+ if (index >= 0 && index < iter->length)
+ {
+ pt = &(iter->stroke->points[iter->start + (iter->stride * index)]);
+ iter->p = pt->p;
+ iter->no = pt->no;
+ }
+ else
+ {
+ iter->p = NULL;
+ iter->no = NULL;
+ }
+
+ return pt;
+}
+
+void initStrokeIterator(BArcIterator *arg, SK_Stroke *stk, int start, int end)
+{
+ SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
+
+ initIteratorFct(iter);
+ iter->stroke = stk;
+
+ if (start < end)
+ {
+ iter->start = start + 1;
+ iter->end = end - 1;
+ iter->stride = 1;
+ }
+ else
+ {
+ iter->start = start - 1;
+ iter->end = end + 1;
+ iter->stride = -1;
+ }
+
+ iter->length = iter->stride * (iter->end - iter->start + 1);
+
+ iter->index = -1;
+}
+
+
+static void* headPoint(void *arg)
+{
+ SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
+ SK_Point *result = NULL;
+
+ result = &(iter->stroke->points[iter->start - iter->stride]);
+ iter->p = result->p;
+ iter->no = result->no;
+
+ return result;
+}
+
+static void* tailPoint(void *arg)
+{
+ SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
+ SK_Point *result = NULL;
+
+ result = &(iter->stroke->points[iter->end + iter->stride]);
+ iter->p = result->p;
+ iter->no = result->no;
+
+ return result;
+}
+
+static void* nextPoint(void *arg)
+{
+ SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
+ SK_Point *result = NULL;
+
+ iter->index++;
+ if (iter->index < iter->length)
+ {
+ result = setIteratorValues(iter, iter->index);
+ }
+
+ return result;
+}
+
+static void* nextNPoint(void *arg, int n)
+{
+ SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
+ SK_Point *result = NULL;
+
+ iter->index += n;
+
+ /* check if passed end */
+ if (iter->index < iter->length)
+ {
+ result = setIteratorValues(iter, iter->index);
+ }
+
+ return result;
+}
+
+static void* peekPoint(void *arg, int n)
+{
+ SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
+ SK_Point *result = NULL;
+ int index = iter->index + n;
+
+ /* check if passed end */
+ if (index < iter->length)
+ {
+ result = setIteratorValues(iter, index);
+ }
+
+ return result;
+}
+
+static void* previousPoint(void *arg)
+{
+ SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
+ SK_Point *result = NULL;
+
+ if (iter->index > 0)
+ {
+ iter->index--;
+ result = setIteratorValues(iter, iter->index);
+ }
+
+ return result;
+}
+
+static int iteratorStopped(void *arg)
+{
+ SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
+
+ if (iter->index >= iter->length)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void sk_convertStroke(bContext *C, SK_Stroke *stk)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ bArmature *arm = obedit->data;
+ SK_Point *head;
+ EditBone *parent = NULL;
+ float invmat[4][4]; /* move in caller function */
+ float tmat[3][3];
+ int head_index = 0;
+ int i;
+
+ head = NULL;
+
+ Mat4Invert(invmat, obedit->obmat);
+
+ Mat3CpyMat4(tmat, obedit->obmat);
+ Mat3Transp(tmat);
+
+ for (i = 0; i < stk->nb_points; i++)
+ {
+ SK_Point *pt = stk->points + i;
+
+ if (pt->type == PT_EXACT)
+ {
+ if (head == NULL)
+ {
+ head_index = i;
+ head = pt;
+ }
+ else
+ {
+ EditBone *bone = NULL;
+ EditBone *new_parent;
+
+ if (i - head_index > 1)
+ {
+ SK_StrokeIterator sk_iter;
+ BArcIterator *iter = (BArcIterator*)&sk_iter;
+
+ initStrokeIterator(iter, stk, head_index, i);
+
+ if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
+ {
+ bone = subdivideArcBy(scene->toolsettings, arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
+ }
+ else if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
+ {
+ bone = subdivideArcBy(scene->toolsettings, arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision);
+ }
+ else if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
+ {
+ bone = subdivideArcBy(scene->toolsettings, arm, arm->edbo, iter, invmat, tmat, nextFixedSubdivision);
+ }
+ }
+
+ if (bone == NULL)
+ {
+ bone = addEditBone(arm, "Bone");
+
+ VECCOPY(bone->head, head->p);
+ VECCOPY(bone->tail, pt->p);
+
+ Mat4MulVecfl(invmat, bone->head);
+ Mat4MulVecfl(invmat, bone->tail);
+ setBoneRollFromNormal(bone, head->no, invmat, tmat);
+ }
+
+ new_parent = bone;
+ bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
+
+ /* move to end of chain */
+ while (bone->parent != NULL)
+ {
+ bone = bone->parent;
+ bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
+ }
+
+ if (parent != NULL)
+ {
+ bone->parent = parent;
+ bone->flag |= BONE_CONNECTED;
+ }
+
+ parent = new_parent;
+ head_index = i;
+ head = pt;
+ }
+ }
+ }
+}
+
+void sk_convert(bContext *C, SK_Sketch *sketch)
+{
+ Scene *scene = CTX_data_scene(C);
+ SK_Stroke *stk;
+
+ for (stk = sketch->strokes.first; stk; stk = stk->next)
+ {
+ if (stk->selected == 1)
+ {
+ if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
+ {
+ sk_retargetStroke(C, stk);
+ }
+ else
+ {
+ sk_convertStroke(C, stk);
+ }
+// XXX
+// allqueue(REDRAWBUTSEDIT, 0);
+ }
+ }
+}
+/******************* GESTURE *************************/
+
+
+/* returns the number of self intersections */
+int sk_getSelfIntersections(bContext *C, ListBase *list, SK_Stroke *gesture)
+{
+ ARegion *ar = CTX_wm_region(C);
+ int added = 0;
+ int s_i;
+
+ for (s_i = 0; s_i < gesture->nb_points - 1; s_i++)
+ {
+ float s_p1[3] = {0, 0, 0};
+ float s_p2[3] = {0, 0, 0};
+ int g_i;
+
+ project_float(ar, gesture->points[s_i].p, s_p1);
+ project_float(ar, gesture->points[s_i + 1].p, s_p2);
+
+ /* start checking from second next, because two consecutive cannot intersect */
+ for (g_i = s_i + 2; g_i < gesture->nb_points - 1; g_i++)
+ {
+ float g_p1[3] = {0, 0, 0};
+ float g_p2[3] = {0, 0, 0};
+ float vi[3];
+ float lambda;
+
+ project_float(ar, gesture->points[g_i].p, g_p1);
+ project_float(ar, gesture->points[g_i + 1].p, g_p2);
+
+ if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
+ {
+ SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
+
+ isect->gesture_index = g_i;
+ isect->before = s_i;
+ isect->after = s_i + 1;
+ isect->stroke = gesture;
+
+ VecSubf(isect->p, gesture->points[s_i + 1].p, gesture->points[s_i].p);
+ VecMulf(isect->p, lambda);
+ VecAddf(isect->p, isect->p, gesture->points[s_i].p);
+
+ BLI_addtail(list, isect);
+
+ added++;
+ }
+ }
+ }
+
+ return added;
+}
+
+int cmpIntersections(void *i1, void *i2)
+{
+ SK_Intersection *isect1 = i1, *isect2 = i2;
+
+ if (isect1->stroke == isect2->stroke)
+ {
+ if (isect1->before < isect2->before)
+ {
+ return -1;
+ }
+ else if (isect1->before > isect2->before)
+ {
+ return 1;
+ }
+ else
+ {
+ if (isect1->lambda < isect2->lambda)
+ {
+ return -1;
+ }
+ else if (isect1->lambda > isect2->lambda)
+ {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+/* returns the maximum number of intersections per stroke */
+int sk_getIntersections(bContext *C, ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture)
+{
+ ARegion *ar = CTX_wm_region(C);
+ ScrArea *sa = CTX_wm_area(C);
+ View3D *v3d = sa->spacedata.first;
+ SK_Stroke *stk;
+ int added = 0;
+
+ for (stk = sketch->strokes.first; stk; stk = stk->next)
+ {
+ int s_added = 0;
+ int s_i;
+
+ for (s_i = 0; s_i < stk->nb_points - 1; s_i++)
+ {
+ float s_p1[3] = {0, 0, 0};
+ float s_p2[3] = {0, 0, 0};
+ int g_i;
+
+ project_float(ar, stk->points[s_i].p, s_p1);
+ project_float(ar, stk->points[s_i + 1].p, s_p2);
+
+ for (g_i = 0; g_i < gesture->nb_points - 1; g_i++)
+ {
+ float g_p1[3] = {0, 0, 0};
+ float g_p2[3] = {0, 0, 0};
+ float vi[3];
+ float lambda;
+
+ project_float(ar, gesture->points[g_i].p, g_p1);
+ project_float(ar, gesture->points[g_i + 1].p, g_p2);
+
+ if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
+ {
+ SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
+ float ray_start[3], ray_end[3];
+ short mval[2];
+
+ isect->gesture_index = g_i;
+ isect->before = s_i;
+ isect->after = s_i + 1;
+ isect->stroke = stk;
+ isect->lambda = lambda;
+
+ mval[0] = (short)(vi[0]);
+ mval[1] = (short)(vi[1]);
+ viewline(ar, v3d, mval, ray_start, ray_end);
+
+ LineIntersectLine( stk->points[s_i].p,
+ stk->points[s_i + 1].p,
+ ray_start,
+ ray_end,
+ isect->p,
+ vi);
+
+ BLI_addtail(list, isect);
+
+ s_added++;
+ }
+ }
+ }
+
+ added = MAX2(s_added, added);
+ }
+
+ BLI_sortlist(list, cmpIntersections);
+
+ return added;
+}
+
+int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture)
+{
+ SK_StrokeIterator sk_iter;
+ BArcIterator *iter = (BArcIterator*)&sk_iter;
+
+ float CORRELATION_THRESHOLD = 0.99f;
+ float *vec;
+ int i, j;
+
+ sk_appendStrokePoint(segments, &gesture->points[0]);
+ vec = segments->points[segments->nb_points - 1].p;
+
+ initStrokeIterator(iter, gesture, 0, gesture->nb_points - 1);
+
+ for (i = 1, j = 0; i < gesture->nb_points; i++)
+ {
+ float n[3];
+
+ /* Calculate normal */
+ VecSubf(n, gesture->points[i].p, vec);
+
+ if (calcArcCorrelation(iter, j, i, vec, n) < CORRELATION_THRESHOLD)
+ {
+ j = i - 1;
+ sk_appendStrokePoint(segments, &gesture->points[j]);
+ vec = segments->points[segments->nb_points - 1].p;
+ segments->points[segments->nb_points - 1].type = PT_EXACT;
+ }
+ }
+
+ sk_appendStrokePoint(segments, &gesture->points[gesture->nb_points - 1]);
+
+ return segments->nb_points - 1;
+}
+
+int sk_detectCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
+{
+ if (gest->nb_segments == 1 && gest->nb_intersections == 1)
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+void sk_applyCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
+{
+ SK_Intersection *isect;
+
+ for (isect = gest->intersections.first; isect; isect = isect->next)
+ {
+ SK_Point pt;
+
+ pt.type = PT_EXACT;
+ pt.mode = PT_PROJECT; /* take mode from neighbouring points */
+ VECCOPY(pt.p, isect->p);
+
+ sk_insertStrokePoint(isect->stroke, &pt, isect->after);
+ }
+}
+
+int sk_detectTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
+{
+ if (gest->nb_segments == 2 && gest->nb_intersections == 1 && gest->nb_self_intersections == 0)
+ {
+ float s1[3], s2[3];
+ float angle;
+
+ VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p);
+ VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p);
+
+ angle = VecAngle2(s1, s2);
+
+ if (angle > 60 && angle < 120)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void sk_applyTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
+{
+ SK_Intersection *isect;
+ float trim_dir[3];
+
+ VecSubf(trim_dir, gest->segments->points[2].p, gest->segments->points[1].p);
+
+ for (isect = gest->intersections.first; isect; isect = isect->next)
+ {
+ SK_Point pt;
+ float stroke_dir[3];
+
+ pt.type = PT_EXACT;
+ pt.mode = PT_PROJECT; /* take mode from neighbouring points */
+ VECCOPY(pt.p, isect->p);
+
+ VecSubf(stroke_dir, isect->stroke->points[isect->after].p, isect->stroke->points[isect->before].p);
+
+ /* same direction, trim end */
+ if (Inpf(stroke_dir, trim_dir) > 0)
+ {
+ sk_replaceStrokePoint(isect->stroke, &pt, isect->after);
+ sk_trimStroke(isect->stroke, 0, isect->after);
+ }
+ /* else, trim start */
+ else
+ {
+ sk_replaceStrokePoint(isect->stroke, &pt, isect->before);
+ sk_trimStroke(isect->stroke, isect->before, isect->stroke->nb_points - 1);
+ }
+
+ }
+}
+
+int sk_detectCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
+{
+ if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 1)
+ {
+ SK_Intersection *isect, *self_isect;
+
+ /* get the the last intersection of the first pair */
+ for( isect = gest->intersections.first; isect; isect = isect->next )
+ {
+ if (isect->stroke == isect->next->stroke)
+ {
+ isect = isect->next;
+ break;
+ }
+ }
+
+ self_isect = gest->self_intersections.first;
+
+ if (isect && isect->gesture_index < self_isect->gesture_index)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void sk_applyCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
+{
+ SK_Intersection *isect;
+ int command = 1;
+
+// XXX
+// command = pupmenu("Action %t|Flatten %x1|Straighten %x2|Polygonize %x3");
+ if(command < 1) return;
+
+ for (isect = gest->intersections.first; isect; isect = isect->next)
+ {
+ SK_Intersection *i2;
+
+ i2 = isect->next;
+
+ if (i2 && i2->stroke == isect->stroke)
+ {
+ switch (command)
+ {
+ case 1:
+ sk_flattenStroke(isect->stroke, isect->before, i2->after);
+ break;
+ case 2:
+ sk_straightenStroke(isect->stroke, isect->before, i2->after, isect->p, i2->p);
+ break;
+ case 3:
+ sk_polygonizeStroke(isect->stroke, isect->before, i2->after);
+ break;
+ }
+
+ isect = i2;
+ }
+ }
+}
+
+int sk_detectDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
+{
+ if (gest->nb_segments == 2 && gest->nb_intersections == 2)
+ {
+ float s1[3], s2[3];
+ float angle;
+
+ VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p);
+ VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p);
+
+ angle = VecAngle2(s1, s2);
+
+ if (angle > 120)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void sk_applyDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
+{
+ SK_Intersection *isect;
+
+ for (isect = gest->intersections.first; isect; isect = isect->next)
+ {
+ /* only delete strokes that are crossed twice */
+ if (isect->next && isect->next->stroke == isect->stroke)
+ {
+ isect = isect->next;
+
+ sk_removeStroke(sketch, isect->stroke);
+ }
+ }
+}
+
+int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
+{
+ ARegion *ar = CTX_wm_region(C);
+ if (gest->nb_segments > 2 && gest->nb_intersections == 2)
+ {
+ short start_val[2], end_val[2];
+ short dist;
+
+ project_short_noclip(ar, gest->stk->points[0].p, start_val);
+ project_short_noclip(ar, sk_lastStrokePoint(gest->stk)->p, end_val);
+
+ dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1]));
+
+ /* if gesture is a circle */
+ if ( dist <= 20 )
+ {
+ SK_Intersection *isect;
+
+ /* check if it circled around an exact point */
+ for (isect = gest->intersections.first; isect; isect = isect->next)
+ {
+ /* only delete strokes that are crossed twice */
+ if (isect->next && isect->next->stroke == isect->stroke)
+ {
+ int start_index, end_index;
+ int i;
+
+ start_index = MIN2(isect->after, isect->next->after);
+ end_index = MAX2(isect->before, isect->next->before);
+
+ for (i = start_index; i <= end_index; i++)
+ {
+ if (isect->stroke->points[i].type == PT_EXACT)
+ {
+ return 1; /* at least one exact point found, stop detect here */
+ }
+ }
+
+ /* skip next */
+ isect = isect->next;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+void sk_applyMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
+{
+ SK_Intersection *isect;
+
+ /* check if it circled around an exact point */
+ for (isect = gest->intersections.first; isect; isect = isect->next)
+ {
+ /* only merge strokes that are crossed twice */
+ if (isect->next && isect->next->stroke == isect->stroke)
+ {
+ int start_index, end_index;
+ int i;
+
+ start_index = MIN2(isect->after, isect->next->after);
+ end_index = MAX2(isect->before, isect->next->before);
+
+ for (i = start_index; i <= end_index; i++)
+ {
+ /* if exact, switch to continuous */
+ if (isect->stroke->points[i].type == PT_EXACT)
+ {
+ isect->stroke->points[i].type = PT_CONTINUOUS;
+ }
+ }
+
+ /* skip next */
+ isect = isect->next;
+ }
+ }
+}
+
+int sk_detectReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
+{
+ if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 0)
+ {
+ SK_Intersection *isect;
+
+ /* check if it circled around an exact point */
+ for (isect = gest->intersections.first; isect; isect = isect->next)
+ {
+ /* only delete strokes that are crossed twice */
+ if (isect->next && isect->next->stroke == isect->stroke)
+ {
+ float start_v[3], end_v[3];
+ float angle;
+
+ if (isect->gesture_index < isect->next->gesture_index)
+ {
+ VecSubf(start_v, isect->p, gest->stk->points[0].p);
+ VecSubf(end_v, sk_lastStrokePoint(gest->stk)->p, isect->next->p);
+ }
+ else
+ {
+ VecSubf(start_v, isect->next->p, gest->stk->points[0].p);
+ VecSubf(end_v, sk_lastStrokePoint(gest->stk)->p, isect->p);
+ }
+
+ angle = VecAngle2(start_v, end_v);
+
+ if (angle > 120)
+ {
+ return 1;
+ }
+
+ /* skip next */
+ isect = isect->next;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void sk_applyReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
+{
+ SK_Intersection *isect;
+
+ for (isect = gest->intersections.first; isect; isect = isect->next)
+ {
+ /* only reverse strokes that are crossed twice */
+ if (isect->next && isect->next->stroke == isect->stroke)
+ {
+ sk_reverseStroke(isect->stroke);
+
+ /* skip next */
+ isect = isect->next;
+ }
+ }
+}
+
+int sk_detectConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
+{
+ if (gest->nb_segments == 3 && gest->nb_self_intersections == 1)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+void sk_applyConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
+{
+ sk_convert(C, sketch);
+}
+
+static void sk_initGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
+{
+ gest->intersections.first = gest->intersections.last = NULL;
+ gest->self_intersections.first = gest->self_intersections.last = NULL;
+
+ gest->segments = sk_createStroke();
+ gest->stk = sketch->gesture;
+
+ gest->nb_self_intersections = sk_getSelfIntersections(C, &gest->self_intersections, gest->stk);
+ gest->nb_intersections = sk_getIntersections(C, &gest->intersections, sketch, gest->stk);
+ gest->nb_segments = sk_getSegments(gest->segments, gest->stk);
+}
+
+static void sk_freeGesture(SK_Gesture *gest)
+{
+ sk_freeStroke(gest->segments);
+ BLI_freelistN(&gest->intersections);
+ BLI_freelistN(&gest->self_intersections);
+}
+
+void sk_applyGesture(bContext *C, SK_Sketch *sketch)
+{
+ SK_Gesture gest;
+ SK_GestureAction *act;
+
+ sk_initGesture(C, &gest, sketch);
+
+ /* detect and apply */
+ for (act = GESTURE_ACTIONS; act->apply != NULL; act++)
+ {
+ if (act->detect(C, &gest, sketch))
+ {
+ act->apply(C, &gest, sketch);
+ break;
+ }
+ }
+
+ sk_freeGesture(&gest);
+}
+
+/********************************************/
+
+void sk_deleteSelectedStrokes(SK_Sketch *sketch)
+{
+ SK_Stroke *stk, *next;
+
+ for (stk = sketch->strokes.first; stk; stk = next)
+ {
+ next = stk->next;
+
+ if (stk->selected == 1)
+ {
+ sk_removeStroke(sketch, stk);
+ }
+ }
+}
+
+void sk_selectAllSketch(SK_Sketch *sketch, int mode)
+{
+ SK_Stroke *stk = NULL;
+
+ if (mode == -1)
+ {
+ for (stk = sketch->strokes.first; stk; stk = stk->next)
+ {
+ stk->selected = 0;
+ }
+ }
+ else if (mode == 0)
+ {
+ for (stk = sketch->strokes.first; stk; stk = stk->next)
+ {
+ stk->selected = 1;
+ }
+ }
+ else if (mode == 1)
+ {
+ int selected = 1;
+
+ for (stk = sketch->strokes.first; stk; stk = stk->next)
+ {
+ selected &= stk->selected;
+ }
+
+ selected ^= 1;
+
+ for (stk = sketch->strokes.first; stk; stk = stk->next)
+ {
+ stk->selected = selected;
+ }
+ }
+}
+
+void sk_selectStroke(bContext *C, SK_Sketch *sketch, short mval[2], int extend)
+{
+ ViewContext vc;
+ rcti rect;
+ unsigned int buffer[MAXPICKBUF];
+ short hits;
+
+ view3d_set_viewcontext(C, &vc);
+
+ rect.xmin= mval[0]-5;
+ rect.xmax= mval[0]+5;
+ rect.ymin= mval[1]-5;
+ rect.ymax= mval[1]+5;
+
+ hits= view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
+
+ if (hits>0)
+ {
+ int besthitresult = -1;
+
+ if(hits == 1) {
+ besthitresult = buffer[3];
+ }
+ else {
+ besthitresult = buffer[3];
+ /* loop and get best hit */
+ }
+
+ if (besthitresult > 0)
+ {
+ SK_Stroke *selected_stk = BLI_findlink(&sketch->strokes, besthitresult - 1);
+
+ if (extend == 0)
+ {
+ sk_selectAllSketch(sketch, -1);
+
+ selected_stk->selected = 1;
+ }
+ else
+ {
+ selected_stk->selected ^= 1;
+ }
+
+
+ }
+ }
+}
+
+void sk_queueRedrawSketch(SK_Sketch *sketch)
+{
+ if (sketch->active_stroke != NULL)
+ {
+ SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
+
+ if (last != NULL)
+ {
+// XXX
+// allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+}
+
+void sk_drawSketch(Scene *scene, SK_Sketch *sketch, int with_names)
+{
+ SK_Stroke *stk;
+
+ glDisable(GL_DEPTH_TEST);
+
+ glLineWidth(UI_GetThemeValuef(TH_VERTEX_SIZE));
+ glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+
+ if (with_names)
+ {
+ int id;
+ for (id = 1, stk = sketch->strokes.first; stk; id++, stk = stk->next)
+ {
+ sk_drawStroke(stk, id, NULL, -1, -1);
+ }
+
+ glLoadName(-1);
+ }
+ else
+ {
+ float selected_rgb[3] = {1, 0, 0};
+ float unselected_rgb[3] = {1, 0.5, 0};
+
+ for (stk = sketch->strokes.first; stk; stk = stk->next)
+ {
+ int start = -1;
+ int end = -1;
+
+ if (sk_hasOverdraw(sketch, stk))
+ {
+ sk_adjustIndexes(sketch, &start, &end);
+ }
+
+ sk_drawStroke(stk, -1, (stk->selected==1?selected_rgb:unselected_rgb), start, end);
+
+ if (stk->selected == 1)
+ {
+ sk_drawStrokeSubdivision(scene->toolsettings, stk);
+ }
+ }
+
+ /* only draw gesture in active area */
+ if (sketch->gesture != NULL /*&& area_is_active_area(G.vd->area)*/)
+ {
+ float gesture_rgb[3] = {0, 0.5, 1};
+ sk_drawStroke(sketch->gesture, -1, gesture_rgb, -1, -1);
+ }
+
+ if (sketch->active_stroke != NULL)
+ {
+ SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
+
+ if (scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK)
+ {
+ sk_drawStrokeSubdivision(scene->toolsettings, sketch->active_stroke);
+ }
+
+ if (last != NULL)
+ {
+ glEnable(GL_LINE_STIPPLE);
+ glColor3fv(selected_rgb);
+ glBegin(GL_LINE_STRIP);
+
+ glVertex3fv(last->p);
+ glVertex3fv(sketch->next_point.p);
+
+ glEnd();
+
+ glDisable(GL_LINE_STIPPLE);
+
+ switch (sketch->next_point.mode)
+ {
+ case PT_SNAP:
+ glColor3f(0, 1, 0);
+ break;
+ case PT_PROJECT:
+ glColor3f(0, 0, 0);
+ break;
+ }
+
+ glBegin(GL_POINTS);
+
+ glVertex3fv(sketch->next_point.p);
+
+ glEnd();
+ }
+ }
+ }
+
+ glLineWidth(1.0);
+ glPointSize(1.0);
+
+ glEnable(GL_DEPTH_TEST);
+}
+
+int sk_finish_stroke(bContext *C, SK_Sketch *sketch)
+{
+ Scene *scene = CTX_data_scene(C);
+
+ if (sketch->active_stroke != NULL)
+ {
+ SK_Stroke *stk = sketch->active_stroke;
+
+ sk_endStroke(C, sketch);
+
+ if (scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK)
+ {
+ if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
+ {
+ sk_retargetStroke(C, stk);
+ }
+ else
+ {
+ sk_convertStroke(C, stk);
+ }
+// XXX
+// BIF_undo_push("Convert Sketch");
+ sk_removeStroke(sketch, stk);
+// XXX
+// allqueue(REDRAWBUTSEDIT, 0);
+ }
+
+// XXX
+// allqueue(REDRAWVIEW3D, 0);
+ return 1;
+ }
+
+ return 0;
+}
+
+void sk_start_draw_stroke(SK_Sketch *sketch)
+{
+ if (sketch->active_stroke == NULL)
+ {
+ sk_startStroke(sketch);
+ sk_selectAllSketch(sketch, -1);
+
+ sketch->active_stroke->selected = 1;
+ }
+}
+
+void sk_start_draw_gesture(SK_Sketch *sketch)
+{
+ sketch->gesture = sk_createStroke();
+}
+
+int sk_draw_stroke(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
+{
+ if (sk_stroke_filtermval(dd))
+ {
+ sk_addStrokePoint(C, sketch, stk, dd, snap);
+ sk_updateDrawData(dd);
+ sk_updateNextPoint(sketch, stk);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int ValidSketchViewContext(ViewContext *vc)
+{
+ Object *obedit = vc->obedit;
+ Scene *scene= vc->scene;
+
+ if (obedit &&
+ obedit->type == OB_ARMATURE &&
+ scene->toolsettings->bone_sketching & BONE_SKETCHING)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int BDR_drawSketchNames(ViewContext *vc)
+{
+ if (ValidSketchViewContext(vc))
+ {
+ if (GLOBAL_sketch != NULL)
+ {
+ sk_drawSketch(vc->scene, GLOBAL_sketch, 1);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void BDR_drawSketch(bContext *C)
+{
+ if (ED_operator_sketch_mode(C))
+ {
+ if (GLOBAL_sketch != NULL)
+ {
+ sk_drawSketch(CTX_data_scene(C), GLOBAL_sketch, 0);
+ }
+ }
+}
+
+static int sketch_delete(bContext *C, wmOperator *op, wmEvent *event)
+{
+ if (GLOBAL_sketch != NULL)
+ {
+ sk_deleteSelectedStrokes(GLOBAL_sketch);
+// allqueue(REDRAWVIEW3D, 0);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void BIF_sk_selectStroke(bContext *C, short mval[2], short extend)
+{
+ if (GLOBAL_sketch != NULL)
+ {
+ sk_selectStroke(C, GLOBAL_sketch, mval, extend);
+ }
+}
+
+void BIF_convertSketch(bContext *C)
+{
+ if (ED_operator_sketch_full_mode(C))
+ {
+ if (GLOBAL_sketch != NULL)
+ {
+ sk_convert(C, GLOBAL_sketch);
+// BIF_undo_push("Convert Sketch");
+// allqueue(REDRAWVIEW3D, 0);
+// allqueue(REDRAWBUTSEDIT, 0);
+ }
+ }
+}
+
+void BIF_deleteSketch(bContext *C)
+{
+ if (ED_operator_sketch_full_mode(C))
+ {
+ if (GLOBAL_sketch != NULL)
+ {
+ sk_deleteSelectedStrokes(GLOBAL_sketch);
+// BIF_undo_push("Convert Sketch");
+// allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+}
+
+//void BIF_selectAllSketch(bContext *C, int mode)
+//{
+// if (BIF_validSketchMode(C))
+// {
+// if (GLOBAL_sketch != NULL)
+// {
+// sk_selectAllSketch(GLOBAL_sketch, mode);
+//// XXX
+//// allqueue(REDRAWVIEW3D, 0);
+// }
+// }
+//}
+
+void BIF_freeSketch(bContext *C)
+{
+ if (GLOBAL_sketch != NULL)
+ {
+ sk_freeSketch(GLOBAL_sketch);
+ GLOBAL_sketch = NULL;
+ }
+}
+
+static int sketch_cancel(bContext *C, wmOperator *op, wmEvent *event)
+{
+ if (GLOBAL_sketch != NULL)
+ {
+ sk_cancelStroke(GLOBAL_sketch);
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_PASS_THROUGH;
+}
+
+static int sketch_finish(bContext *C, wmOperator *op, wmEvent *event)
+{
+ if (GLOBAL_sketch != NULL)
+ {
+ if (sk_finish_stroke(C, GLOBAL_sketch))
+ {
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return OPERATOR_FINISHED;
+ }
+ }
+ return OPERATOR_PASS_THROUGH;
+}
+
+static int sketch_select(bContext *C, wmOperator *op, wmEvent *event)
+{
+ if (GLOBAL_sketch != NULL)
+ {
+ short extend = 0;
+ sk_selectStroke(C, GLOBAL_sketch, event->mval, extend);
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static int sketch_draw_stroke_cancel(bContext *C, wmOperator *op)
+{
+ sk_cancelStroke(GLOBAL_sketch);
+ MEM_freeN(op->customdata);
+ return OPERATOR_CANCELLED;
+}
+
+static int sketch_draw_stroke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ short snap = RNA_boolean_get(op->ptr, "snap");
+ SK_DrawData *dd;
+
+ if (GLOBAL_sketch == NULL)
+ {
+ GLOBAL_sketch = sk_createSketch();
+ }
+
+ op->customdata = dd = MEM_callocN(sizeof("SK_DrawData"), "SketchDrawData");
+ sk_initDrawData(dd, event->mval);
+
+ sk_start_draw_stroke(GLOBAL_sketch);
+
+ sk_draw_stroke(C, GLOBAL_sketch, GLOBAL_sketch->active_stroke, dd, snap);
+
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int sketch_draw_gesture_cancel(bContext *C, wmOperator *op)
+{
+ sk_cancelStroke(GLOBAL_sketch);
+ MEM_freeN(op->customdata);
+ return OPERATOR_CANCELLED;
+}
+
+static int sketch_draw_gesture(bContext *C, wmOperator *op, wmEvent *event)
+{
+ short snap = RNA_boolean_get(op->ptr, "snap");
+ SK_DrawData *dd;
+
+ if (GLOBAL_sketch == NULL)
+ {
+ GLOBAL_sketch = sk_createSketch();
+ }
+
+ op->customdata = dd = MEM_callocN(sizeof("SK_DrawData"), "SketchDrawData");
+ sk_initDrawData(dd, event->mval);
+
+ sk_start_draw_gesture(GLOBAL_sketch);
+ sk_draw_stroke(C, GLOBAL_sketch, GLOBAL_sketch->gesture, dd, snap);
+
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int sketch_draw_modal(bContext *C, wmOperator *op, wmEvent *event, short gesture, SK_Stroke *stk)
+{
+ short snap = RNA_boolean_get(op->ptr, "snap");
+ SK_DrawData *dd = op->customdata;
+ int retval = OPERATOR_RUNNING_MODAL;
+
+ switch (event->type)
+ {
+ case LEFTCTRLKEY:
+ case RIGHTCTRLKEY:
+ snap = event->ctrl;
+ RNA_boolean_set(op->ptr, "snap", snap);
+ break;
+ case MOUSEMOVE:
+ dd->mval[0] = event->mval[0];
+ dd->mval[1] = event->mval[1];
+ sk_draw_stroke(C, GLOBAL_sketch, stk, dd, snap);
+ ED_area_tag_redraw(CTX_wm_area(C));
+ break;
+ case ESCKEY:
+ op->type->cancel(C, op);
+ ED_area_tag_redraw(CTX_wm_area(C));
+ retval = OPERATOR_CANCELLED;
+ break;
+ case LEFTMOUSE:
+ if (event->val == 0)
+ {
+ if (gesture == 0)
+ {
+ sk_endContinuousStroke(stk);
+ sk_filterLastContinuousStroke(stk);
+ sk_updateNextPoint(GLOBAL_sketch, stk);
+ ED_area_tag_redraw(CTX_wm_area(C));
+ MEM_freeN(op->customdata);
+ retval = OPERATOR_FINISHED;
+ }
+ else
+ {
+ sk_endContinuousStroke(stk);
+ sk_filterLastContinuousStroke(stk);
+
+ if (stk->nb_points > 1)
+ {
+ /* apply gesture here */
+ sk_applyGesture(C, GLOBAL_sketch);
+ }
+
+ sk_freeStroke(stk);
+ GLOBAL_sketch->gesture = NULL;
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ MEM_freeN(op->customdata);
+ retval = OPERATOR_FINISHED;
+ }
+ }
+ break;
+ }
+
+ return retval;
+}
+
+static int sketch_draw_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ return sketch_draw_modal(C, op, event, 0, GLOBAL_sketch->active_stroke);
+}
+
+static int sketch_draw_gesture_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ return sketch_draw_modal(C, op, event, 1, GLOBAL_sketch->gesture);
+}
+
+static int sketch_draw_preview(bContext *C, wmOperator *op, wmEvent *event)
+{
+ short snap = RNA_boolean_get(op->ptr, "snap");
+
+ if (GLOBAL_sketch != NULL)
+ {
+ SK_Sketch *sketch = GLOBAL_sketch;
+ SK_DrawData dd;
+
+ sk_initDrawData(&dd, event->mval);
+ sk_getStrokePoint(C, &sketch->next_point, sketch, sketch->active_stroke, &dd, snap);
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
+}
+
+/* ============================================== Poll Functions ============================================= */
+
+int ED_operator_sketch_mode_active_stroke(bContext *C)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (obedit &&
+ obedit->type == OB_ARMATURE &&
+ scene->toolsettings->bone_sketching & BONE_SKETCHING &&
+ GLOBAL_sketch != NULL &&
+ GLOBAL_sketch->active_stroke != NULL)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int ED_operator_sketch_mode_gesture(bContext *C)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (obedit &&
+ obedit->type == OB_ARMATURE &&
+ scene->toolsettings->bone_sketching & BONE_SKETCHING &&
+ (scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK) == 0 &&
+ GLOBAL_sketch != NULL &&
+ GLOBAL_sketch->active_stroke == NULL)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int ED_operator_sketch_full_mode(bContext *C)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (obedit &&
+ obedit->type == OB_ARMATURE &&
+ scene->toolsettings->bone_sketching & BONE_SKETCHING &&
+ (scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK) == 0)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int ED_operator_sketch_mode(bContext *C)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (obedit &&
+ obedit->type == OB_ARMATURE &&
+ scene->toolsettings->bone_sketching & BONE_SKETCHING)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/* ================================================ Operators ================================================ */
+
+void SKETCH_OT_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "delete";
+ ot->idname= "SKETCH_OT_delete";
+
+ /* api callbacks */
+ ot->invoke= sketch_delete;
+
+ ot->poll= ED_operator_sketch_full_mode;
+
+ /* flags */
+// ot->flag= OPTYPE_UNDO;
+}
+
+void SKETCH_OT_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "select";
+ ot->idname= "SKETCH_OT_select";
+
+ /* api callbacks */
+ ot->invoke= sketch_select;
+
+ ot->poll= ED_operator_sketch_full_mode;
+
+ /* flags */
+// ot->flag= OPTYPE_UNDO;
+}
+
+void SKETCH_OT_cancel_stroke(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "cancel stroke";
+ ot->idname= "SKETCH_OT_cancel_stroke";
+
+ /* api callbacks */
+ ot->invoke= sketch_cancel;
+
+ ot->poll= ED_operator_sketch_mode_active_stroke;
+
+ /* flags */
+// ot->flag= OPTYPE_UNDO;
+}
+
+void SKETCH_OT_finish_stroke(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "end stroke";
+ ot->idname= "SKETCH_OT_finish_stroke";
+
+ /* api callbacks */
+ ot->invoke= sketch_finish;
+
+ ot->poll= ED_operator_sketch_mode_active_stroke;
+
+ /* flags */
+// ot->flag= OPTYPE_UNDO;
+}
+
+void SKETCH_OT_draw_preview(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "draw preview";
+ ot->idname= "SKETCH_OT_draw_preview";
+
+ /* api callbacks */
+ ot->invoke= sketch_draw_preview;
+
+ ot->poll= ED_operator_sketch_mode_active_stroke;
+
+ RNA_def_boolean(ot->srna, "snap", 0, "Snap", "");
+
+ /* flags */
+// ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+void SKETCH_OT_draw_stroke(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "draw stroke";
+ ot->idname= "SKETCH_OT_draw_stroke";
+
+ /* api callbacks */
+ ot->invoke = sketch_draw_stroke;
+ ot->modal = sketch_draw_stroke_modal;
+ ot->cancel = sketch_draw_stroke_cancel;
+
+ ot->poll= ED_operator_sketch_mode;
+
+ RNA_def_boolean(ot->srna, "snap", 0, "Snap", "");
+
+ /* flags */
+// ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+void SKETCH_OT_gesture(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "gesture";
+ ot->idname= "SKETCH_OT_gesture";
+
+ /* api callbacks */
+ ot->invoke = sketch_draw_gesture;
+ ot->modal = sketch_draw_gesture_modal;
+ ot->cancel = sketch_draw_gesture_cancel;
+
+ ot->poll= ED_operator_sketch_mode_gesture;
+
+ RNA_def_boolean(ot->srna, "snap", 0, "Snap", "");
+
+ /* flags */
+// ot->flag= OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
new file mode 100644
index 00000000000..8807b21e653
--- /dev/null
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -0,0 +1,1920 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * meshlaplacian.c: Algorithms using the mesh laplacian.
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_edgehash.h"
+#include "BLI_memarena.h"
+
+#include "BKE_DerivedMesh.h"
+#include "BKE_utildefines.h"
+
+#ifdef RIGID_DEFORM
+#include "BLI_editVert.h"
+#include "BLI_polardecomp.h"
+#endif
+
+#include "RE_raytrace.h"
+
+#include "ONL_opennl.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+#include "ED_armature.h"
+#include "ED_mesh.h"
+
+#include "meshlaplacian.h"
+
+
+/* ************* XXX *************** */
+static void waitcursor() {}
+static void progress_bar() {}
+static void start_progress_bar() {}
+static void end_progress_bar() {}
+static void error() {}
+/* ************* XXX *************** */
+
+
+/************************** Laplacian System *****************************/
+
+struct LaplacianSystem {
+ NLContext context; /* opennl context */
+
+ int totvert, totface;
+
+ float **verts; /* vertex coordinates */
+ float *varea; /* vertex weights for laplacian computation */
+ char *vpinned; /* vertex pinning */
+ int (*faces)[3]; /* face vertex indices */
+ float (*fweights)[3]; /* cotangent weights per face */
+
+ int areaweights; /* use area in cotangent weights? */
+ int storeweights; /* store cotangent weights in fweights */
+ int nlbegun; /* nlBegin(NL_SYSTEM/NL_MATRIX) done */
+
+ EdgeHash *edgehash; /* edge hash for construction */
+
+ struct HeatWeighting {
+ Mesh *mesh;
+ float (*verts)[3]; /* vertex coordinates */
+ float (*vnors)[3]; /* vertex normals */
+
+ float (*root)[3]; /* bone root */
+ float (*tip)[3]; /* bone tip */
+ int numbones;
+
+ float *H; /* diagonal H matrix */
+ float *p; /* values from all p vectors */
+ float *mindist; /* minimum distance to a bone for all vertices */
+
+ RayTree *raytree; /* ray tracing acceleration structure */
+ MFace **vface; /* a face that the vertex belongs to */
+ } heat;
+
+#ifdef RIGID_DEFORM
+ struct RigidDeformation {
+ EditMesh *mesh;
+
+ float (*R)[3][3];
+ float (*rhs)[3];
+ float (*origco)[3];
+ int thrownerror;
+ } rigid;
+#endif
+};
+
+/* Laplacian matrix construction */
+
+/* Computation of these weights for the laplacian is based on:
+ "Discrete Differential-Geometry Operators for Triangulated 2-Manifolds",
+ Meyer et al, 2002. Section 3.5, formula (8).
+
+ We do it a bit different by going over faces instead of going over each
+ vertex and adjacent faces, since we don't store this adjacency. Also, the
+ formulas are tweaked a bit to work for non-manifold meshes. */
+
+static void laplacian_increase_edge_count(EdgeHash *edgehash, int v1, int v2)
+{
+ void **p = BLI_edgehash_lookup_p(edgehash, v1, v2);
+
+ if(p)
+ *p = (void*)((intptr_t)*p + (intptr_t)1);
+ else
+ BLI_edgehash_insert(edgehash, v1, v2, (void*)(intptr_t)1);
+}
+
+static int laplacian_edge_count(EdgeHash *edgehash, int v1, int v2)
+{
+ return (int)(intptr_t)BLI_edgehash_lookup(edgehash, v1, v2);
+}
+
+static float cotan_weight(float *v1, float *v2, float *v3)
+{
+ float a[3], b[3], c[3], clen;
+
+ VecSubf(a, v2, v1);
+ VecSubf(b, v3, v1);
+ Crossf(c, a, b);
+
+ clen = VecLength(c);
+
+ if (clen == 0.0f)
+ return 0.0f;
+
+ return Inpf(a, b)/clen;
+}
+
+static void laplacian_triangle_area(LaplacianSystem *sys, int i1, int i2, int i3)
+{
+ float t1, t2, t3, len1, len2, len3, area;
+ float *varea= sys->varea, *v1, *v2, *v3;
+ int obtuse = 0;
+
+ v1= sys->verts[i1];
+ v2= sys->verts[i2];
+ v3= sys->verts[i3];
+
+ t1= cotan_weight(v1, v2, v3);
+ t2= cotan_weight(v2, v3, v1);
+ t3= cotan_weight(v3, v1, v2);
+
+ if(VecAngle3(v2, v1, v3) > 90) obtuse= 1;
+ else if(VecAngle3(v1, v2, v3) > 90) obtuse= 2;
+ else if(VecAngle3(v1, v3, v2) > 90) obtuse= 3;
+
+ if (obtuse > 0) {
+ area= AreaT3Dfl(v1, v2, v3);
+
+ varea[i1] += (obtuse == 1)? area: area*0.5;
+ varea[i2] += (obtuse == 2)? area: area*0.5;
+ varea[i3] += (obtuse == 3)? area: area*0.5;
+ }
+ else {
+ len1= VecLenf(v2, v3);
+ len2= VecLenf(v1, v3);
+ len3= VecLenf(v1, v2);
+
+ t1 *= len1*len1;
+ t2 *= len2*len2;
+ t3 *= len3*len3;
+
+ varea[i1] += (t2 + t3)*0.25f;
+ varea[i2] += (t1 + t3)*0.25f;
+ varea[i3] += (t1 + t2)*0.25f;
+ }
+}
+
+static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int i2, int i3)
+{
+ float t1, t2, t3;
+ float *varea= sys->varea, *v1, *v2, *v3;
+
+ v1= sys->verts[i1];
+ v2= sys->verts[i2];
+ v3= sys->verts[i3];
+
+ /* instead of *0.5 we divided by the number of faces of the edge, it still
+ needs to be verified that this is indeed the correct thing to do! */
+ t1= cotan_weight(v1, v2, v3)/laplacian_edge_count(sys->edgehash, i2, i3);
+ t2= cotan_weight(v2, v3, v1)/laplacian_edge_count(sys->edgehash, i3, i1);
+ t3= cotan_weight(v3, v1, v2)/laplacian_edge_count(sys->edgehash, i1, i2);
+
+ nlMatrixAdd(i1, i1, (t2+t3)*varea[i1]);
+ nlMatrixAdd(i2, i2, (t1+t3)*varea[i2]);
+ nlMatrixAdd(i3, i3, (t1+t2)*varea[i3]);
+
+ nlMatrixAdd(i1, i2, -t3*varea[i1]);
+ nlMatrixAdd(i2, i1, -t3*varea[i2]);
+
+ nlMatrixAdd(i2, i3, -t1*varea[i2]);
+ nlMatrixAdd(i3, i2, -t1*varea[i3]);
+
+ nlMatrixAdd(i3, i1, -t2*varea[i3]);
+ nlMatrixAdd(i1, i3, -t2*varea[i1]);
+
+ if(sys->storeweights) {
+ sys->fweights[f][0]= t1*varea[i1];
+ sys->fweights[f][1]= t2*varea[i2];
+ sys->fweights[f][2]= t3*varea[i3];
+ }
+}
+
+LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface, int lsq)
+{
+ LaplacianSystem *sys;
+
+ sys= MEM_callocN(sizeof(LaplacianSystem), "LaplacianSystem");
+
+ sys->verts= MEM_callocN(sizeof(float*)*totvert, "LaplacianSystemVerts");
+ sys->vpinned= MEM_callocN(sizeof(char)*totvert, "LaplacianSystemVpinned");
+ sys->faces= MEM_callocN(sizeof(int)*3*totface, "LaplacianSystemFaces");
+
+ sys->totvert= 0;
+ sys->totface= 0;
+
+ sys->areaweights= 1;
+ sys->storeweights= 0;
+
+ /* create opennl context */
+ nlNewContext();
+ nlSolverParameteri(NL_NB_VARIABLES, totvert);
+ if(lsq)
+ nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
+
+ sys->context= nlGetCurrent();
+
+ return sys;
+}
+
+void laplacian_add_vertex(LaplacianSystem *sys, float *co, int pinned)
+{
+ sys->verts[sys->totvert]= co;
+ sys->vpinned[sys->totvert]= pinned;
+ sys->totvert++;
+}
+
+void laplacian_add_triangle(LaplacianSystem *sys, int v1, int v2, int v3)
+{
+ sys->faces[sys->totface][0]= v1;
+ sys->faces[sys->totface][1]= v2;
+ sys->faces[sys->totface][2]= v3;
+ sys->totface++;
+}
+
+void laplacian_system_construct_end(LaplacianSystem *sys)
+{
+ int (*face)[3];
+ int a, totvert=sys->totvert, totface=sys->totface;
+
+ laplacian_begin_solve(sys, 0);
+
+ sys->varea= MEM_callocN(sizeof(float)*totvert, "LaplacianSystemVarea");
+
+ sys->edgehash= BLI_edgehash_new();
+ for(a=0, face=sys->faces; a<sys->totface; a++, face++) {
+ laplacian_increase_edge_count(sys->edgehash, (*face)[0], (*face)[1]);
+ laplacian_increase_edge_count(sys->edgehash, (*face)[1], (*face)[2]);
+ laplacian_increase_edge_count(sys->edgehash, (*face)[2], (*face)[0]);
+ }
+
+ if(sys->areaweights)
+ for(a=0, face=sys->faces; a<sys->totface; a++, face++)
+ laplacian_triangle_area(sys, (*face)[0], (*face)[1], (*face)[2]);
+
+ for(a=0; a<totvert; a++) {
+ if(sys->areaweights) {
+ if(sys->varea[a] != 0.0f)
+ sys->varea[a]= 0.5f/sys->varea[a];
+ }
+ else
+ sys->varea[a]= 1.0f;
+
+ /* for heat weighting */
+ if(sys->heat.H)
+ nlMatrixAdd(a, a, sys->heat.H[a]);
+ }
+
+ if(sys->storeweights)
+ sys->fweights= MEM_callocN(sizeof(float)*3*totface, "LaplacianFWeight");
+
+ for(a=0, face=sys->faces; a<totface; a++, face++)
+ laplacian_triangle_weights(sys, a, (*face)[0], (*face)[1], (*face)[2]);
+
+ MEM_freeN(sys->faces);
+ sys->faces= NULL;
+
+ if(sys->varea) {
+ MEM_freeN(sys->varea);
+ sys->varea= NULL;
+ }
+
+ BLI_edgehash_free(sys->edgehash, NULL);
+ sys->edgehash= NULL;
+}
+
+void laplacian_system_delete(LaplacianSystem *sys)
+{
+ if(sys->verts) MEM_freeN(sys->verts);
+ if(sys->varea) MEM_freeN(sys->varea);
+ if(sys->vpinned) MEM_freeN(sys->vpinned);
+ if(sys->faces) MEM_freeN(sys->faces);
+ if(sys->fweights) MEM_freeN(sys->fweights);
+
+ nlDeleteContext(sys->context);
+ MEM_freeN(sys);
+}
+
+void laplacian_begin_solve(LaplacianSystem *sys, int index)
+{
+ int a;
+
+ if (!sys->nlbegun) {
+ nlBegin(NL_SYSTEM);
+
+ if(index >= 0) {
+ for(a=0; a<sys->totvert; a++) {
+ if(sys->vpinned[a]) {
+ nlSetVariable(0, a, sys->verts[a][index]);
+ nlLockVariable(a);
+ }
+ }
+ }
+
+ nlBegin(NL_MATRIX);
+ sys->nlbegun = 1;
+ }
+}
+
+void laplacian_add_right_hand_side(LaplacianSystem *sys, int v, float value)
+{
+ nlRightHandSideAdd(0, v, value);
+}
+
+int laplacian_system_solve(LaplacianSystem *sys)
+{
+ nlEnd(NL_MATRIX);
+ nlEnd(NL_SYSTEM);
+ sys->nlbegun = 0;
+
+ //nlPrintMatrix();
+
+ return nlSolveAdvanced(NULL, NL_TRUE);
+}
+
+float laplacian_system_get_solution(int v)
+{
+ return nlGetVariable(0, v);
+}
+
+/************************* Heat Bone Weighting ******************************/
+/* From "Automatic Rigging and Animation of 3D Characters"
+ Ilya Baran and Jovan Popovic, SIGGRAPH 2007 */
+
+#define C_WEIGHT 1.0f
+#define WEIGHT_LIMIT_START 0.05f
+#define WEIGHT_LIMIT_END 0.025f
+#define DISTANCE_EPSILON 1e-4f
+
+/* Raytracing for vertex to bone visibility */
+
+static LaplacianSystem *HeatSys = NULL;
+
+static void heat_ray_coords_func(RayFace *face, float **v1, float **v2, float **v3, float **v4)
+{
+ MFace *mface= (MFace*)face;
+ float (*verts)[3]= HeatSys->heat.verts;
+
+ *v1= verts[mface->v1];
+ *v2= verts[mface->v2];
+ *v3= verts[mface->v3];
+ *v4= (mface->v4)? verts[mface->v4]: NULL;
+}
+
+static int heat_ray_check_func(Isect *is, int ob, RayFace *face)
+{
+ float *v1, *v2, *v3, *v4, nor[3];
+
+ /* don't intersect if the ray faces along the face normal */
+ heat_ray_coords_func(face, &v1, &v2, &v3, &v4);
+
+ if(v4) CalcNormFloat4(v1, v2, v3, v4, nor);
+ else CalcNormFloat(v1, v2, v3, nor);
+
+ return (INPR(nor, is->vec) < 0);
+}
+
+static void heat_ray_tree_create(LaplacianSystem *sys)
+{
+ Mesh *me = sys->heat.mesh;
+ RayTree *tree;
+ MFace *mface;
+ float min[3], max[3];
+ int a;
+
+ /* create a raytrace tree from the mesh */
+ INIT_MINMAX(min, max);
+
+ for(a=0; a<me->totvert; a++)
+ DO_MINMAX(sys->heat.verts[a], min, max);
+
+ tree= RE_ray_tree_create(64, me->totface, min, max,
+ heat_ray_coords_func, heat_ray_check_func, NULL, NULL);
+
+ sys->heat.vface= MEM_callocN(sizeof(MFace*)*me->totvert, "HeatVFaces");
+
+ HeatSys= sys;
+
+ for(a=0, mface=me->mface; a<me->totface; a++, mface++) {
+ RE_ray_tree_add_face(tree, 0, mface);
+
+ sys->heat.vface[mface->v1]= mface;
+ sys->heat.vface[mface->v2]= mface;
+ sys->heat.vface[mface->v3]= mface;
+ if(mface->v4) sys->heat.vface[mface->v4]= mface;
+ }
+
+ HeatSys= NULL;
+
+ RE_ray_tree_done(tree);
+
+ sys->heat.raytree= tree;
+}
+
+static int heat_ray_bone_visible(LaplacianSystem *sys, int vertex, int bone)
+{
+ Isect isec;
+ MFace *mface;
+ float dir[3];
+ int visible;
+
+ mface= sys->heat.vface[vertex];
+ if(!mface)
+ return 1;
+
+ /* setup isec */
+ memset(&isec, 0, sizeof(isec));
+ isec.mode= RE_RAY_SHADOW;
+ isec.lay= -1;
+ isec.face_last= NULL;
+ isec.faceorig= mface;
+
+ VECCOPY(isec.start, sys->heat.verts[vertex]);
+ PclosestVL3Dfl(isec.end, isec.start,
+ sys->heat.root[bone], sys->heat.tip[bone]);
+
+ /* add an extra offset to the start position to avoid self intersection */
+ VECSUB(dir, isec.end, isec.start);
+ Normalize(dir);
+ VecMulf(dir, 1e-5);
+ VecAddf(isec.start, isec.start, dir);
+
+ HeatSys= sys;
+ visible= !RE_ray_tree_intersect(sys->heat.raytree, &isec);
+ HeatSys= NULL;
+
+ return visible;
+}
+
+static float heat_bone_distance(LaplacianSystem *sys, int vertex, int bone)
+{
+ float closest[3], d[3], dist, cosine;
+
+ /* compute euclidian distance */
+ PclosestVL3Dfl(closest, sys->heat.verts[vertex],
+ sys->heat.root[bone], sys->heat.tip[bone]);
+
+ VecSubf(d, sys->heat.verts[vertex], closest);
+ dist= Normalize(d);
+
+ /* if the vertex normal does not point along the bone, increase distance */
+ cosine= INPR(d, sys->heat.vnors[vertex]);
+
+ return dist/(0.5f*(cosine + 1.001f));
+}
+
+static int heat_bone_closest(LaplacianSystem *sys, int vertex, int bone)
+{
+ float dist;
+
+ dist= heat_bone_distance(sys, vertex, bone);
+
+ if(dist <= sys->heat.mindist[vertex]*(1.0f + DISTANCE_EPSILON))
+ if(heat_ray_bone_visible(sys, vertex, bone))
+ return 1;
+
+ return 0;
+}
+
+static void heat_set_H(LaplacianSystem *sys, int vertex)
+{
+ float dist, mindist, h;
+ int j, numclosest = 0;
+
+ mindist= 1e10;
+
+ /* compute minimum distance */
+ for(j=0; j<sys->heat.numbones; j++) {
+ dist= heat_bone_distance(sys, vertex, j);
+
+ if(dist < mindist)
+ mindist= dist;
+ }
+
+ sys->heat.mindist[vertex]= mindist;
+
+ /* count number of bones with approximately this minimum distance */
+ for(j=0; j<sys->heat.numbones; j++)
+ if(heat_bone_closest(sys, vertex, j))
+ numclosest++;
+
+ sys->heat.p[vertex]= (numclosest > 0)? 1.0f/numclosest: 0.0f;
+
+ /* compute H entry */
+ if(numclosest > 0) {
+ if(mindist > 1e-5)
+ h= numclosest*C_WEIGHT/(mindist*mindist);
+ else
+ h= 1e10f;
+ }
+ else
+ h= 0.0f;
+
+ sys->heat.H[vertex]= h;
+}
+
+void heat_calc_vnormals(LaplacianSystem *sys)
+{
+ float fnor[3];
+ int a, v1, v2, v3, (*face)[3];
+
+ sys->heat.vnors= MEM_callocN(sizeof(float)*3*sys->totvert, "HeatVNors");
+
+ for(a=0, face=sys->faces; a<sys->totface; a++, face++) {
+ v1= (*face)[0];
+ v2= (*face)[1];
+ v3= (*face)[2];
+
+ CalcNormFloat(sys->verts[v1], sys->verts[v2], sys->verts[v3], fnor);
+
+ VecAddf(sys->heat.vnors[v1], sys->heat.vnors[v1], fnor);
+ VecAddf(sys->heat.vnors[v2], sys->heat.vnors[v2], fnor);
+ VecAddf(sys->heat.vnors[v3], sys->heat.vnors[v3], fnor);
+ }
+
+ for(a=0; a<sys->totvert; a++)
+ Normalize(sys->heat.vnors[a]);
+}
+
+static void heat_laplacian_create(LaplacianSystem *sys)
+{
+ Mesh *me = sys->heat.mesh;
+ MFace *mface;
+ int a;
+
+ /* heat specific definitions */
+ sys->heat.mindist= MEM_callocN(sizeof(float)*me->totvert, "HeatMinDist");
+ sys->heat.H= MEM_callocN(sizeof(float)*me->totvert, "HeatH");
+ sys->heat.p= MEM_callocN(sizeof(float)*me->totvert, "HeatP");
+
+ /* add verts and faces to laplacian */
+ for(a=0; a<me->totvert; a++)
+ laplacian_add_vertex(sys, sys->heat.verts[a], 0);
+
+ for(a=0, mface=me->mface; a<me->totface; a++, mface++) {
+ laplacian_add_triangle(sys, mface->v1, mface->v2, mface->v3);
+ if(mface->v4)
+ laplacian_add_triangle(sys, mface->v1, mface->v3, mface->v4);
+ }
+
+ /* for distance computation in set_H */
+ heat_calc_vnormals(sys);
+
+ for(a=0; a<me->totvert; a++)
+ heat_set_H(sys, a);
+}
+
+static float heat_limit_weight(float weight)
+{
+ float t;
+
+ if(weight < WEIGHT_LIMIT_END) {
+ return 0.0f;
+ }
+ else if(weight < WEIGHT_LIMIT_START) {
+ t= (weight - WEIGHT_LIMIT_END)/(WEIGHT_LIMIT_START - WEIGHT_LIMIT_END);
+ return t*WEIGHT_LIMIT_START;
+ }
+ else
+ return weight;
+}
+
+void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numbones, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3], int *selected)
+{
+ LaplacianSystem *sys;
+ MFace *mface;
+ float solution, weight;
+ int *vertsflipped = NULL;
+ int a, totface, j, bbone, firstsegment, lastsegment, thrownerror = 0;
+
+ /* count triangles */
+ for(totface=0, a=0, mface=me->mface; a<me->totface; a++, mface++) {
+ totface++;
+ if(mface->v4) totface++;
+ }
+
+ /* create laplacian */
+ sys = laplacian_system_construct_begin(me->totvert, totface, 1);
+
+ sys->heat.mesh= me;
+ sys->heat.verts= verts;
+ sys->heat.root= root;
+ sys->heat.tip= tip;
+ sys->heat.numbones= numbones;
+
+ heat_ray_tree_create(sys);
+ heat_laplacian_create(sys);
+
+ laplacian_system_construct_end(sys);
+
+ if(dgroupflip) {
+ vertsflipped = MEM_callocN(sizeof(int)*me->totvert, "vertsflipped");
+ for(a=0; a<me->totvert; a++)
+ vertsflipped[a] = mesh_get_x_mirror_vert(ob, a);
+ }
+
+ /* compute weights per bone */
+ for(j=0; j<numbones; j++) {
+ if(!selected[j])
+ continue;
+
+ firstsegment= (j == 0 || dgrouplist[j-1] != dgrouplist[j]);
+ lastsegment= (j == numbones-1 || dgrouplist[j] != dgrouplist[j+1]);
+ bbone= !(firstsegment && lastsegment);
+
+ /* clear weights */
+ if(bbone && firstsegment) {
+ for(a=0; a<me->totvert; a++) {
+ remove_vert_defgroup(ob, dgrouplist[j], a);
+ if(vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0)
+ remove_vert_defgroup(ob, dgroupflip[j], vertsflipped[a]);
+ }
+ }
+
+ /* fill right hand side */
+ laplacian_begin_solve(sys, -1);
+
+ for(a=0; a<me->totvert; a++)
+ if(heat_bone_closest(sys, a, j))
+ laplacian_add_right_hand_side(sys, a,
+ sys->heat.H[a]*sys->heat.p[a]);
+
+ /* solve */
+ if(laplacian_system_solve(sys)) {
+ /* load solution into vertex groups */
+ for(a=0; a<me->totvert; a++) {
+ solution= laplacian_system_get_solution(a);
+
+ if(bbone) {
+ if(solution > 0.0f)
+ add_vert_to_defgroup(ob, dgrouplist[j], a, solution,
+ WEIGHT_ADD);
+ }
+ else {
+ weight= heat_limit_weight(solution);
+ if(weight > 0.0f)
+ add_vert_to_defgroup(ob, dgrouplist[j], a, weight,
+ WEIGHT_REPLACE);
+ else
+ remove_vert_defgroup(ob, dgrouplist[j], a);
+ }
+
+ /* do same for mirror */
+ if(vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
+ if(bbone) {
+ if(solution > 0.0f)
+ add_vert_to_defgroup(ob, dgroupflip[j], vertsflipped[a],
+ solution, WEIGHT_ADD);
+ }
+ else {
+ weight= heat_limit_weight(solution);
+ if(weight > 0.0f)
+ add_vert_to_defgroup(ob, dgroupflip[j], vertsflipped[a],
+ weight, WEIGHT_REPLACE);
+ else
+ remove_vert_defgroup(ob, dgroupflip[j], vertsflipped[a]);
+ }
+ }
+ }
+ }
+ else if(!thrownerror) {
+ error("Bone Heat Weighting:"
+ " failed to find solution for one or more bones");
+ thrownerror= 1;
+ break;
+ }
+
+ /* remove too small vertex weights */
+ if(bbone && lastsegment) {
+ for(a=0; a<me->totvert; a++) {
+ weight= get_vert_defgroup(ob, dgrouplist[j], a);
+ weight= heat_limit_weight(weight);
+ if(weight <= 0.0f)
+ remove_vert_defgroup(ob, dgrouplist[j], a);
+
+ if(vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
+ weight= get_vert_defgroup(ob, dgroupflip[j], vertsflipped[a]);
+ weight= heat_limit_weight(weight);
+ if(weight <= 0.0f)
+ remove_vert_defgroup(ob, dgroupflip[j], vertsflipped[a]);
+ }
+ }
+ }
+ }
+
+ /* free */
+ if(vertsflipped) MEM_freeN(vertsflipped);
+
+ RE_ray_tree_free(sys->heat.raytree);
+ MEM_freeN(sys->heat.vface);
+
+ MEM_freeN(sys->heat.mindist);
+ MEM_freeN(sys->heat.H);
+ MEM_freeN(sys->heat.p);
+ MEM_freeN(sys->heat.vnors);
+
+ laplacian_system_delete(sys);
+}
+
+#ifdef RIGID_DEFORM
+/********************** As-Rigid-As-Possible Deformation ******************/
+/* From "As-Rigid-As-Possible Surface Modeling",
+ Olga Sorkine and Marc Alexa, ESGP 2007. */
+
+/* investigate:
+ - transpose R in orthogonal
+ - flipped normals and per face adding
+ - move cancelling to transform, make origco pointer
+*/
+
+static LaplacianSystem *RigidDeformSystem = NULL;
+
+static void rigid_add_half_edge_to_R(LaplacianSystem *sys, EditVert *v1, EditVert *v2, float w)
+{
+ float e[3], e_[3];
+ int i;
+
+ VecSubf(e, sys->rigid.origco[v1->tmp.l], sys->rigid.origco[v2->tmp.l]);
+ VecSubf(e_, v1->co, v2->co);
+
+ /* formula (5) */
+ for (i=0; i<3; i++) {
+ sys->rigid.R[v1->tmp.l][i][0] += w*e[0]*e_[i];
+ sys->rigid.R[v1->tmp.l][i][1] += w*e[1]*e_[i];
+ sys->rigid.R[v1->tmp.l][i][2] += w*e[2]*e_[i];
+ }
+}
+
+static void rigid_add_edge_to_R(LaplacianSystem *sys, EditVert *v1, EditVert *v2, float w)
+{
+ rigid_add_half_edge_to_R(sys, v1, v2, w);
+ rigid_add_half_edge_to_R(sys, v2, v1, w);
+}
+
+static void rigid_orthogonalize_R(float R[][3])
+{
+ HMatrix M, Q, S;
+
+ Mat4CpyMat3(M, R);
+ polar_decomp(M, Q, S);
+ Mat3CpyMat4(R, Q);
+}
+
+static void rigid_add_half_edge_to_rhs(LaplacianSystem *sys, EditVert *v1, EditVert *v2, float w)
+{
+ /* formula (8) */
+ float Rsum[3][3], rhs[3];
+
+ if (sys->vpinned[v1->tmp.l])
+ return;
+
+ Mat3AddMat3(Rsum, sys->rigid.R[v1->tmp.l], sys->rigid.R[v2->tmp.l]);
+ Mat3Transp(Rsum);
+
+ VecSubf(rhs, sys->rigid.origco[v1->tmp.l], sys->rigid.origco[v2->tmp.l]);
+ Mat3MulVecfl(Rsum, rhs);
+ VecMulf(rhs, 0.5f);
+ VecMulf(rhs, w);
+
+ VecAddf(sys->rigid.rhs[v1->tmp.l], sys->rigid.rhs[v1->tmp.l], rhs);
+}
+
+static void rigid_add_edge_to_rhs(LaplacianSystem *sys, EditVert *v1, EditVert *v2, float w)
+{
+ rigid_add_half_edge_to_rhs(sys, v1, v2, w);
+ rigid_add_half_edge_to_rhs(sys, v2, v1, w);
+}
+
+void rigid_deform_iteration()
+{
+ LaplacianSystem *sys= RigidDeformSystem;
+ EditMesh *em;
+ EditVert *eve;
+ EditFace *efa;
+ int a, i;
+
+ if(!sys)
+ return;
+
+ nlMakeCurrent(sys->context);
+ em= sys->rigid.mesh;
+
+ /* compute R */
+ memset(sys->rigid.R, 0, sizeof(float)*3*3*sys->totvert);
+ memset(sys->rigid.rhs, 0, sizeof(float)*3*sys->totvert);
+
+ for(a=0, efa=em->faces.first; efa; efa=efa->next, a++) {
+ rigid_add_edge_to_R(sys, efa->v1, efa->v2, sys->fweights[a][2]);
+ rigid_add_edge_to_R(sys, efa->v2, efa->v3, sys->fweights[a][0]);
+ rigid_add_edge_to_R(sys, efa->v3, efa->v1, sys->fweights[a][1]);
+
+ if(efa->v4) {
+ a++;
+ rigid_add_edge_to_R(sys, efa->v1, efa->v3, sys->fweights[a][2]);
+ rigid_add_edge_to_R(sys, efa->v3, efa->v4, sys->fweights[a][0]);
+ rigid_add_edge_to_R(sys, efa->v4, efa->v1, sys->fweights[a][1]);
+ }
+ }
+
+ for(a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
+ rigid_orthogonalize_R(sys->rigid.R[a]);
+ eve->tmp.l= a;
+ }
+
+ /* compute right hand sides for solving */
+ for(a=0, efa=em->faces.first; efa; efa=efa->next, a++) {
+ rigid_add_edge_to_rhs(sys, efa->v1, efa->v2, sys->fweights[a][2]);
+ rigid_add_edge_to_rhs(sys, efa->v2, efa->v3, sys->fweights[a][0]);
+ rigid_add_edge_to_rhs(sys, efa->v3, efa->v1, sys->fweights[a][1]);
+
+ if(efa->v4) {
+ a++;
+ rigid_add_edge_to_rhs(sys, efa->v1, efa->v3, sys->fweights[a][2]);
+ rigid_add_edge_to_rhs(sys, efa->v3, efa->v4, sys->fweights[a][0]);
+ rigid_add_edge_to_rhs(sys, efa->v4, efa->v1, sys->fweights[a][1]);
+ }
+ }
+
+ /* solve for positions, for X,Y and Z separately */
+ for(i=0; i<3; i++) {
+ laplacian_begin_solve(sys, i);
+
+ for(a=0; a<sys->totvert; a++)
+ if(!sys->vpinned[a])
+ laplacian_add_right_hand_side(sys, a, sys->rigid.rhs[a][i]);
+
+ if(laplacian_system_solve(sys)) {
+ for(a=0, eve=em->verts.first; eve; eve=eve->next, a++)
+ eve->co[i]= laplacian_system_get_solution(a);
+ }
+ else {
+ if(!sys->rigid.thrownerror) {
+ error("RigidDeform: failed to find solution.");
+ sys->rigid.thrownerror= 1;
+ }
+ break;
+ }
+ }
+}
+
+static void rigid_laplacian_create(LaplacianSystem *sys)
+{
+ EditMesh *em = sys->rigid.mesh;
+ EditVert *eve;
+ EditFace *efa;
+ int a;
+
+ /* add verts and faces to laplacian */
+ for(a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
+ laplacian_add_vertex(sys, eve->co, eve->pinned);
+ eve->tmp.l= a;
+ }
+
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ laplacian_add_triangle(sys,
+ efa->v1->tmp.l, efa->v2->tmp.l, efa->v3->tmp.l);
+ if(efa->v4)
+ laplacian_add_triangle(sys,
+ efa->v1->tmp.l, efa->v3->tmp.l, efa->v4->tmp.l);
+ }
+}
+
+void rigid_deform_begin(EditMesh *em)
+{
+ LaplacianSystem *sys;
+ EditVert *eve;
+ EditFace *efa;
+ int a, totvert, totface;
+
+ /* count vertices, triangles */
+ for(totvert=0, eve=em->verts.first; eve; eve=eve->next)
+ totvert++;
+
+ for(totface=0, efa=em->faces.first; efa; efa=efa->next) {
+ totface++;
+ if(efa->v4) totface++;
+ }
+
+ /* create laplacian */
+ sys = laplacian_system_construct_begin(totvert, totface, 0);
+
+ sys->rigid.mesh= em;
+ sys->rigid.R = MEM_callocN(sizeof(float)*3*3*totvert, "RigidDeformR");
+ sys->rigid.rhs = MEM_callocN(sizeof(float)*3*totvert, "RigidDeformRHS");
+ sys->rigid.origco = MEM_callocN(sizeof(float)*3*totvert, "RigidDeformCo");
+
+ for(a=0, eve=em->verts.first; eve; eve=eve->next, a++)
+ VecCopyf(sys->rigid.origco[a], eve->co);
+
+ sys->areaweights= 0;
+ sys->storeweights= 1;
+
+ rigid_laplacian_create(sys);
+
+ laplacian_system_construct_end(sys);
+
+ RigidDeformSystem = sys;
+}
+
+void rigid_deform_end(int cancel)
+{
+ LaplacianSystem *sys = RigidDeformSystem;
+
+ if(sys) {
+ EditMesh *em = sys->rigid.mesh;
+ EditVert *eve;
+ int a;
+
+ if(cancel)
+ for(a=0, eve=em->verts.first; eve; eve=eve->next, a++)
+ if(!eve->pinned)
+ VecCopyf(eve->co, sys->rigid.origco[a]);
+
+ if(sys->rigid.R) MEM_freeN(sys->rigid.R);
+ if(sys->rigid.rhs) MEM_freeN(sys->rigid.rhs);
+ if(sys->rigid.origco) MEM_freeN(sys->rigid.origco);
+
+ /* free */
+ laplacian_system_delete(sys);
+ }
+
+ RigidDeformSystem = NULL;
+}
+#endif
+
+/************************** Harmonic Coordinates ****************************/
+/* From "Harmonic Coordinates for Character Articulation",
+ Pushkar Joshi, Mark Meyer, Tony DeRose, Brian Green and Tom Sanocki,
+ SIGGRAPH 2007. */
+
+#define EPSILON 0.0001f
+
+#define MESHDEFORM_TAG_UNTYPED 0
+#define MESHDEFORM_TAG_BOUNDARY 1
+#define MESHDEFORM_TAG_INTERIOR 2
+#define MESHDEFORM_TAG_EXTERIOR 3
+
+#define MESHDEFORM_LEN_THRESHOLD 1e-6
+
+#define MESHDEFORM_MIN_INFLUENCE 0.0005
+
+static int MESHDEFORM_OFFSET[7][3] =
+ {{0,0,0}, {1,0,0}, {-1,0,0}, {0,1,0}, {0,-1,0}, {0,0,1}, {0,0,-1}};
+
+typedef struct MDefBoundIsect {
+ float co[3], uvw[4];
+ int nvert, v[4], facing;
+ float len;
+} MDefBoundIsect;
+
+typedef struct MDefBindInfluence {
+ struct MDefBindInfluence *next;
+ float weight;
+ int vertex;
+} MDefBindInfluence;
+
+typedef struct MeshDeformBind {
+ /* grid dimensions */
+ float min[3], max[3];
+ float width[3], halfwidth[3];
+ int size, size3;
+
+ /* meshes */
+ DerivedMesh *cagedm;
+ float (*cagecos)[3];
+ float (*vertexcos)[3];
+ int totvert, totcagevert;
+
+ /* grids */
+ MemArena *memarena;
+ MDefBoundIsect *(*boundisect)[6];
+ int *semibound;
+ int *tag;
+ float *phi, *totalphi;
+
+ /* mesh stuff */
+ int *inside;
+ float *weights;
+ MDefBindInfluence **dyngrid;
+ float cagemat[4][4];
+
+ /* direct solver */
+ int *varidx;
+
+ /* raytrace */
+ RayTree *raytree;
+} MeshDeformBind;
+
+/* ray intersection */
+
+/* our own triangle intersection, so we can fully control the epsilons and
+ * prevent corner case from going wrong*/
+static int meshdeform_tri_intersect(float orig[3], float end[3], float vert0[3],
+ float vert1[3], float vert2[3], float *isectco, float *uvw)
+{
+ float edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
+ float det,inv_det, u, v, dir[3], isectdir[3];
+
+ VECSUB(dir, end, orig);
+
+ /* find vectors for two edges sharing vert0 */
+ VECSUB(edge1, vert1, vert0);
+ VECSUB(edge2, vert2, vert0);
+
+ /* begin calculating determinant - also used to calculate U parameter */
+ Crossf(pvec, dir, edge2);
+
+ /* if determinant is near zero, ray lies in plane of triangle */
+ det = INPR(edge1, pvec);
+
+ if (det == 0.0f)
+ return 0;
+ inv_det = 1.0f / det;
+
+ /* calculate distance from vert0 to ray origin */
+ VECSUB(tvec, orig, vert0);
+
+ /* calculate U parameter and test bounds */
+ u = INPR(tvec, pvec) * inv_det;
+ if (u < -EPSILON || u > 1.0f+EPSILON)
+ return 0;
+
+ /* prepare to test V parameter */
+ Crossf(qvec, tvec, edge1);
+
+ /* calculate V parameter and test bounds */
+ v = INPR(dir, qvec) * inv_det;
+ if (v < -EPSILON || u + v > 1.0f+EPSILON)
+ return 0;
+
+ isectco[0]= (1.0f - u - v)*vert0[0] + u*vert1[0] + v*vert2[0];
+ isectco[1]= (1.0f - u - v)*vert0[1] + u*vert1[1] + v*vert2[1];
+ isectco[2]= (1.0f - u - v)*vert0[2] + u*vert1[2] + v*vert2[2];
+
+ uvw[0]= 1.0 - u - v;
+ uvw[1]= u;
+ uvw[2]= v;
+
+ /* check if it is within the length of the line segment */
+ VECSUB(isectdir, isectco, orig);
+
+ if(INPR(dir, isectdir) < -EPSILON)
+ return 0;
+
+ if(INPR(dir, dir) + EPSILON < INPR(isectdir, isectdir))
+ return 0;
+
+ return 1;
+}
+
+/* blender's raytracer is not use now, even though it is much faster. it can
+ * give problems with rays falling through, so we use our own intersection
+ * function above with tweaked epsilons */
+
+#if 0
+static MeshDeformBind *MESHDEFORM_BIND = NULL;
+
+static void meshdeform_ray_coords_func(RayFace *face, float **v1, float **v2, float **v3, float **v4)
+{
+ MFace *mface= (MFace*)face;
+ float (*cagecos)[3]= MESHDEFORM_BIND->cagecos;
+
+ *v1= cagecos[mface->v1];
+ *v2= cagecos[mface->v2];
+ *v3= cagecos[mface->v3];
+ *v4= (mface->v4)? cagecos[mface->v4]: NULL;
+}
+
+static int meshdeform_ray_check_func(Isect *is, RayFace *face)
+{
+ return 1;
+}
+
+static void meshdeform_ray_tree_create(MeshDeformBind *mdb)
+{
+ MFace *mface;
+ float min[3], max[3];
+ int a, totface;
+
+ /* create a raytrace tree from the mesh */
+ INIT_MINMAX(min, max);
+
+ for(a=0; a<mdb->totcagevert; a++)
+ DO_MINMAX(mdb->cagecos[a], min, max)
+
+ MESHDEFORM_BIND= mdb;
+
+ mface= mdb->cagedm->getFaceArray(mdb->cagedm);
+ totface= mdb->cagedm->getNumFaces(mdb->cagedm);
+
+ mdb->raytree= RE_ray_tree_create(64, totface, min, max,
+ meshdeform_ray_coords_func, meshdeform_ray_check_func);
+
+ for(a=0; a<totface; a++, mface++)
+ RE_ray_tree_add_face(mdb->raytree, mface);
+
+ RE_ray_tree_done(mdb->raytree);
+}
+
+static void meshdeform_ray_tree_free(MeshDeformBind *mdb)
+{
+ MESHDEFORM_BIND= NULL;
+ RE_ray_tree_free(mdb->raytree);
+}
+#endif
+
+static int meshdeform_intersect(MeshDeformBind *mdb, Isect *isec)
+{
+ MFace *mface;
+ float face[4][3], co[3], uvw[3], len, nor[3];
+ int f, hit, is= 0, totface;
+
+ isec->labda= 1e10;
+
+ mface= mdb->cagedm->getFaceArray(mdb->cagedm);
+ totface= mdb->cagedm->getNumFaces(mdb->cagedm);
+
+ for(f=0; f<totface; f++, mface++) {
+ VECCOPY(face[0], mdb->cagecos[mface->v1]);
+ VECCOPY(face[1], mdb->cagecos[mface->v2]);
+ VECCOPY(face[2], mdb->cagecos[mface->v3]);
+
+ if(mface->v4) {
+ VECCOPY(face[3], mdb->cagecos[mface->v4]);
+ hit= meshdeform_tri_intersect(isec->start, isec->end, face[0], face[1], face[2], co, uvw);
+
+ if(hit) {
+ CalcNormFloat(face[0], face[1], face[2], nor);
+ }
+ else {
+ hit= meshdeform_tri_intersect(isec->start, isec->end, face[0], face[2], face[3], co, uvw);
+ CalcNormFloat(face[0], face[2], face[3], nor);
+ }
+ }
+ else {
+ hit= meshdeform_tri_intersect(isec->start, isec->end, face[0], face[1], face[2], co, uvw);
+ CalcNormFloat(face[0], face[1], face[2], nor);
+ }
+
+ if(hit) {
+ len= VecLenf(isec->start, co)/VecLenf(isec->start, isec->end);
+ if(len < isec->labda) {
+ isec->labda= len;
+ isec->face= mface;
+ isec->isect= (INPR(isec->vec, nor) <= 0.0f);
+ is= 1;
+ }
+ }
+ }
+
+ return is;
+}
+
+static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, float *co1, float *co2)
+{
+ MDefBoundIsect *isect;
+ Isect isec;
+ float (*cagecos)[3];
+ MFace *mface;
+ float vert[4][3], len;
+ static float epsilon[3]= {0, 0, 0}; //1e-4, 1e-4, 1e-4};
+
+ /* setup isec */
+ memset(&isec, 0, sizeof(isec));
+ isec.mode= RE_RAY_MIRROR; /* we want the closest intersection */
+ isec.lay= -1;
+ isec.face_last= NULL;
+ isec.faceorig= NULL;
+ isec.labda= 1e10f;
+
+ VECADD(isec.start, co1, epsilon);
+ VECADD(isec.end, co2, epsilon);
+ VECSUB(isec.vec, isec.end, isec.start);
+
+#if 0
+ /*if(RE_ray_tree_intersect(mdb->raytree, &isec)) {*/
+#endif
+
+ if(meshdeform_intersect(mdb, &isec)) {
+ len= isec.labda;
+ mface= isec.face;
+
+ /* create MDefBoundIsect */
+ isect= BLI_memarena_alloc(mdb->memarena, sizeof(*isect));
+
+ /* compute intersection coordinate */
+ isect->co[0]= co1[0] + isec.vec[0]*len;
+ isect->co[1]= co1[1] + isec.vec[1]*len;
+ isect->co[2]= co1[2] + isec.vec[2]*len;
+
+ isect->len= VecLenf(co1, isect->co);
+ if(isect->len < MESHDEFORM_LEN_THRESHOLD)
+ isect->len= MESHDEFORM_LEN_THRESHOLD;
+
+ isect->v[0]= mface->v1;
+ isect->v[1]= mface->v2;
+ isect->v[2]= mface->v3;
+ isect->v[3]= mface->v4;
+ isect->nvert= (mface->v4)? 4: 3;
+
+ isect->facing= isec.isect;
+
+ /* compute mean value coordinates for interpolation */
+ cagecos= mdb->cagecos;
+ VECCOPY(vert[0], cagecos[mface->v1]);
+ VECCOPY(vert[1], cagecos[mface->v2]);
+ VECCOPY(vert[2], cagecos[mface->v3]);
+ if(mface->v4) VECCOPY(vert[3], cagecos[mface->v4]);
+ MeanValueWeights(vert, isect->nvert, isect->co, isect->uvw);
+
+ return isect;
+ }
+
+ return NULL;
+}
+
+static int meshdeform_inside_cage(MeshDeformBind *mdb, float *co)
+{
+ MDefBoundIsect *isect;
+ float outside[3], start[3], dir[3];
+ int i, counter;
+
+ for(i=1; i<=6; i++) {
+ counter = 0;
+
+ outside[0] = co[0] + (mdb->max[0] - mdb->min[0] + 1.0f)*MESHDEFORM_OFFSET[i][0];
+ outside[1] = co[1] + (mdb->max[1] - mdb->min[1] + 1.0f)*MESHDEFORM_OFFSET[i][1];
+ outside[2] = co[2] + (mdb->max[2] - mdb->min[2] + 1.0f)*MESHDEFORM_OFFSET[i][2];
+
+ VECCOPY(start, co);
+ VECSUB(dir, outside, start);
+ Normalize(dir);
+
+ isect = meshdeform_ray_tree_intersect(mdb, start, outside);
+ if(isect && !isect->facing)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* solving */
+
+static int meshdeform_index(MeshDeformBind *mdb, int x, int y, int z, int n)
+{
+ int size= mdb->size;
+
+ x += MESHDEFORM_OFFSET[n][0];
+ y += MESHDEFORM_OFFSET[n][1];
+ z += MESHDEFORM_OFFSET[n][2];
+
+ if(x < 0 || x >= mdb->size)
+ return -1;
+ if(y < 0 || y >= mdb->size)
+ return -1;
+ if(z < 0 || z >= mdb->size)
+ return -1;
+
+ return x + y*size + z*size*size;
+}
+
+static void meshdeform_cell_center(MeshDeformBind *mdb, int x, int y, int z, int n, float *center)
+{
+ x += MESHDEFORM_OFFSET[n][0];
+ y += MESHDEFORM_OFFSET[n][1];
+ z += MESHDEFORM_OFFSET[n][2];
+
+ center[0]= mdb->min[0] + x*mdb->width[0] + mdb->halfwidth[0];
+ center[1]= mdb->min[1] + y*mdb->width[1] + mdb->halfwidth[1];
+ center[2]= mdb->min[2] + z*mdb->width[2] + mdb->halfwidth[2];
+}
+
+static void meshdeform_add_intersections(MeshDeformBind *mdb, int x, int y, int z)
+{
+ MDefBoundIsect *isect;
+ float center[3], ncenter[3];
+ int i, a;
+
+ a= meshdeform_index(mdb, x, y, z, 0);
+ meshdeform_cell_center(mdb, x, y, z, 0, center);
+
+ /* check each outgoing edge for intersection */
+ for(i=1; i<=6; i++) {
+ if(meshdeform_index(mdb, x, y, z, i) == -1)
+ continue;
+
+ meshdeform_cell_center(mdb, x, y, z, i, ncenter);
+
+ isect= meshdeform_ray_tree_intersect(mdb, center, ncenter);
+ if(isect) {
+ mdb->boundisect[a][i-1]= isect;
+ mdb->tag[a]= MESHDEFORM_TAG_BOUNDARY;
+ }
+ }
+}
+
+static void meshdeform_bind_floodfill(MeshDeformBind *mdb)
+{
+ int *stack, *tag= mdb->tag;
+ int a, b, i, xyz[3], stacksize, size= mdb->size;
+
+ stack= MEM_callocN(sizeof(int)*mdb->size3, "MeshDeformBindStack");
+
+ /* we know lower left corner is EXTERIOR because of padding */
+ tag[0]= MESHDEFORM_TAG_EXTERIOR;
+ stack[0]= 0;
+ stacksize= 1;
+
+ /* floodfill exterior tag */
+ while(stacksize > 0) {
+ a= stack[--stacksize];
+
+ xyz[2]= a/(size*size);
+ xyz[1]= (a - xyz[2]*size*size)/size;
+ xyz[0]= a - xyz[1]*size - xyz[2]*size*size;
+
+ for(i=1; i<=6; i++) {
+ b= meshdeform_index(mdb, xyz[0], xyz[1], xyz[2], i);
+
+ if(b != -1) {
+ if(tag[b] == MESHDEFORM_TAG_UNTYPED ||
+ (tag[b] == MESHDEFORM_TAG_BOUNDARY && !mdb->boundisect[a][i-1])) {
+ tag[b]= MESHDEFORM_TAG_EXTERIOR;
+ stack[stacksize++]= b;
+ }
+ }
+ }
+ }
+
+ /* other cells are interior */
+ for(a=0; a<size*size*size; a++)
+ if(tag[a]==MESHDEFORM_TAG_UNTYPED)
+ tag[a]= MESHDEFORM_TAG_INTERIOR;
+
+#if 0
+ {
+ int tb, ti, te, ts;
+ tb= ti= te= ts= 0;
+ for(a=0; a<size*size*size; a++)
+ if(tag[a]==MESHDEFORM_TAG_BOUNDARY)
+ tb++;
+ else if(tag[a]==MESHDEFORM_TAG_INTERIOR)
+ ti++;
+ else if(tag[a]==MESHDEFORM_TAG_EXTERIOR) {
+ te++;
+
+ if(mdb->semibound[a])
+ ts++;
+ }
+
+ printf("interior %d exterior %d boundary %d semi-boundary %d\n", ti, te, tb, ts);
+ }
+#endif
+
+ MEM_freeN(stack);
+}
+
+static float meshdeform_boundary_phi(MeshDeformBind *mdb, MDefBoundIsect *isect, int cagevert)
+{
+ int a;
+
+ for(a=0; a<isect->nvert; a++)
+ if(isect->v[a] == cagevert)
+ return isect->uvw[a];
+
+ return 0.0f;
+}
+
+static float meshdeform_interp_w(MeshDeformBind *mdb, float *gridvec, float *vec, int cagevert)
+{
+ float dvec[3], ivec[3], wx, wy, wz, result=0.0f;
+ float weight, totweight= 0.0f;
+ int i, a, x, y, z;
+
+ for(i=0; i<3; i++) {
+ ivec[i]= (int)gridvec[i];
+ dvec[i]= gridvec[i] - ivec[i];
+ }
+
+ for(i=0; i<8; i++) {
+ if(i & 1) { x= ivec[0]+1; wx= dvec[0]; }
+ else { x= ivec[0]; wx= 1.0f-dvec[0]; }
+
+ if(i & 2) { y= ivec[1]+1; wy= dvec[1]; }
+ else { y= ivec[1]; wy= 1.0f-dvec[1]; }
+
+ if(i & 4) { z= ivec[2]+1; wz= dvec[2]; }
+ else { z= ivec[2]; wz= 1.0f-dvec[2]; }
+
+ CLAMP(x, 0, mdb->size-1);
+ CLAMP(y, 0, mdb->size-1);
+ CLAMP(z, 0, mdb->size-1);
+
+ a= meshdeform_index(mdb, x, y, z, 0);
+ weight= wx*wy*wz;
+ result += weight*mdb->phi[a];
+ totweight += weight;
+ }
+
+ if(totweight > 0.0f)
+ result /= totweight;
+
+ return result;
+}
+
+static void meshdeform_check_semibound(MeshDeformBind *mdb, int x, int y, int z)
+{
+ int i, a;
+
+ a= meshdeform_index(mdb, x, y, z, 0);
+ if(mdb->tag[a] != MESHDEFORM_TAG_EXTERIOR)
+ return;
+
+ for(i=1; i<=6; i++)
+ if(mdb->boundisect[a][i-1])
+ mdb->semibound[a]= 1;
+}
+
+static float meshdeform_boundary_total_weight(MeshDeformBind *mdb, int x, int y, int z)
+{
+ float weight, totweight= 0.0f;
+ int i, a;
+
+ a= meshdeform_index(mdb, x, y, z, 0);
+
+ /* count weight for neighbour cells */
+ for(i=1; i<=6; i++) {
+ if(meshdeform_index(mdb, x, y, z, i) == -1)
+ continue;
+
+ if(mdb->boundisect[a][i-1])
+ weight= 1.0f/mdb->boundisect[a][i-1]->len;
+ else if(!mdb->semibound[a])
+ weight= 1.0f/mdb->width[0];
+ else
+ weight= 0.0f;
+
+ totweight += weight;
+ }
+
+ return totweight;
+}
+
+static void meshdeform_matrix_add_cell(MeshDeformBind *mdb, int x, int y, int z)
+{
+ MDefBoundIsect *isect;
+ float weight, totweight;
+ int i, a, acenter;
+
+ acenter= meshdeform_index(mdb, x, y, z, 0);
+ if(mdb->tag[acenter] == MESHDEFORM_TAG_EXTERIOR)
+ return;
+
+ nlMatrixAdd(mdb->varidx[acenter], mdb->varidx[acenter], 1.0f);
+
+ totweight= meshdeform_boundary_total_weight(mdb, x, y, z);
+ for(i=1; i<=6; i++) {
+ a= meshdeform_index(mdb, x, y, z, i);
+ if(a == -1 || mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR)
+ continue;
+
+ isect= mdb->boundisect[acenter][i-1];
+ if (!isect) {
+ weight= (1.0f/mdb->width[0])/totweight;
+ nlMatrixAdd(mdb->varidx[acenter], mdb->varidx[a], -weight);
+ }
+ }
+}
+
+static void meshdeform_matrix_add_rhs(MeshDeformBind *mdb, int x, int y, int z, int cagevert)
+{
+ MDefBoundIsect *isect;
+ float rhs, weight, totweight;
+ int i, a, acenter;
+
+ acenter= meshdeform_index(mdb, x, y, z, 0);
+ if(mdb->tag[acenter] == MESHDEFORM_TAG_EXTERIOR)
+ return;
+
+ totweight= meshdeform_boundary_total_weight(mdb, x, y, z);
+ for(i=1; i<=6; i++) {
+ a= meshdeform_index(mdb, x, y, z, i);
+ if(a == -1)
+ continue;
+
+ isect= mdb->boundisect[acenter][i-1];
+
+ if (isect) {
+ weight= (1.0f/isect->len)/totweight;
+ rhs= weight*meshdeform_boundary_phi(mdb, isect, cagevert);
+ nlRightHandSideAdd(0, mdb->varidx[acenter], rhs);
+ }
+ }
+}
+
+static void meshdeform_matrix_add_semibound_phi(MeshDeformBind *mdb, int x, int y, int z, int cagevert)
+{
+ MDefBoundIsect *isect;
+ float rhs, weight, totweight;
+ int i, a;
+
+ a= meshdeform_index(mdb, x, y, z, 0);
+ if(!mdb->semibound[a])
+ return;
+
+ mdb->phi[a]= 0.0f;
+
+ totweight= meshdeform_boundary_total_weight(mdb, x, y, z);
+ for(i=1; i<=6; i++) {
+ isect= mdb->boundisect[a][i-1];
+
+ if (isect) {
+ weight= (1.0f/isect->len)/totweight;
+ rhs= weight*meshdeform_boundary_phi(mdb, isect, cagevert);
+ mdb->phi[a] += rhs;
+ }
+ }
+}
+
+static void meshdeform_matrix_add_exterior_phi(MeshDeformBind *mdb, int x, int y, int z, int cagevert)
+{
+ float phi, totweight;
+ int i, a, acenter;
+
+ acenter= meshdeform_index(mdb, x, y, z, 0);
+ if(mdb->tag[acenter] != MESHDEFORM_TAG_EXTERIOR || mdb->semibound[acenter])
+ return;
+
+ phi= 0.0f;
+ totweight= 0.0f;
+ for(i=1; i<=6; i++) {
+ a= meshdeform_index(mdb, x, y, z, i);
+
+ if(a != -1 && mdb->semibound[a]) {
+ phi += mdb->phi[a];
+ totweight += 1.0f;
+ }
+ }
+
+ if(totweight != 0.0f)
+ mdb->phi[acenter]= phi/totweight;
+}
+
+static void meshdeform_matrix_solve(MeshDeformBind *mdb)
+{
+ NLContext *context;
+ float vec[3], gridvec[3];
+ int a, b, x, y, z, totvar;
+ char message[1024];
+
+ /* setup variable indices */
+ mdb->varidx= MEM_callocN(sizeof(int)*mdb->size3, "MeshDeformDSvaridx");
+ for(a=0, totvar=0; a<mdb->size3; a++)
+ mdb->varidx[a]= (mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR)? -1: totvar++;
+
+ if(totvar == 0) {
+ MEM_freeN(mdb->varidx);
+ return;
+ }
+
+ progress_bar(0, "Starting mesh deform solve");
+
+ /* setup opennl solver */
+ nlNewContext();
+ context= nlGetCurrent();
+
+ nlSolverParameteri(NL_NB_VARIABLES, totvar);
+ nlSolverParameteri(NL_NB_ROWS, totvar);
+ nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 1);
+
+ nlBegin(NL_SYSTEM);
+ nlBegin(NL_MATRIX);
+
+ /* build matrix */
+ for(z=0; z<mdb->size; z++)
+ for(y=0; y<mdb->size; y++)
+ for(x=0; x<mdb->size; x++)
+ meshdeform_matrix_add_cell(mdb, x, y, z);
+
+ /* solve for each cage vert */
+ for(a=0; a<mdb->totcagevert; a++) {
+ if(a != 0) {
+ nlBegin(NL_SYSTEM);
+ nlBegin(NL_MATRIX);
+ }
+
+ /* fill in right hand side and solve */
+ for(z=0; z<mdb->size; z++)
+ for(y=0; y<mdb->size; y++)
+ for(x=0; x<mdb->size; x++)
+ meshdeform_matrix_add_rhs(mdb, x, y, z, a);
+
+ nlEnd(NL_MATRIX);
+ nlEnd(NL_SYSTEM);
+
+#if 0
+ nlPrintMatrix();
+#endif
+
+ if(nlSolveAdvanced(NULL, NL_TRUE)) {
+ for(z=0; z<mdb->size; z++)
+ for(y=0; y<mdb->size; y++)
+ for(x=0; x<mdb->size; x++)
+ meshdeform_matrix_add_semibound_phi(mdb, x, y, z, a);
+
+ for(z=0; z<mdb->size; z++)
+ for(y=0; y<mdb->size; y++)
+ for(x=0; x<mdb->size; x++)
+ meshdeform_matrix_add_exterior_phi(mdb, x, y, z, a);
+
+ for(b=0; b<mdb->size3; b++) {
+ if(mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR)
+ mdb->phi[b]= nlGetVariable(0, mdb->varidx[b]);
+ mdb->totalphi[b] += mdb->phi[b];
+ }
+
+ if(mdb->weights) {
+ /* static bind : compute weights for each vertex */
+ for(b=0; b<mdb->totvert; b++) {
+ if(mdb->inside[b]) {
+ VECCOPY(vec, mdb->vertexcos[b]);
+ Mat4MulVecfl(mdb->cagemat, vec);
+ gridvec[0]= (vec[0] - mdb->min[0] - mdb->halfwidth[0])/mdb->width[0];
+ gridvec[1]= (vec[1] - mdb->min[1] - mdb->halfwidth[1])/mdb->width[1];
+ gridvec[2]= (vec[2] - mdb->min[2] - mdb->halfwidth[2])/mdb->width[2];
+
+ mdb->weights[b*mdb->totcagevert + a]= meshdeform_interp_w(mdb, gridvec, vec, a);
+ }
+ }
+ }
+ else {
+ MDefBindInfluence *inf;
+
+ /* dynamic bind */
+ for(b=0; b<mdb->size3; b++) {
+ if(mdb->phi[b] >= MESHDEFORM_MIN_INFLUENCE) {
+ inf= BLI_memarena_alloc(mdb->memarena, sizeof(*inf));
+ inf->vertex= a;
+ inf->weight= mdb->phi[b];
+ inf->next= mdb->dyngrid[b];
+ mdb->dyngrid[b]= inf;
+ }
+ }
+ }
+ }
+ else {
+ error("Mesh Deform: failed to find solution.");
+ break;
+ }
+
+ sprintf(message, "Mesh deform solve %d / %d |||", a+1, mdb->totcagevert);
+ progress_bar((float)(a+1)/(float)(mdb->totcagevert), message);
+ }
+
+#if 0
+ /* sanity check */
+ for(b=0; b<mdb->size3; b++)
+ if(mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR)
+ if(fabs(mdb->totalphi[b] - 1.0f) > 1e-4)
+ printf("totalphi deficiency [%s|%d] %d: %.10f\n",
+ (mdb->tag[b] == MESHDEFORM_TAG_INTERIOR)? "interior": "boundary", mdb->semibound[b], mdb->varidx[b], mdb->totalphi[b]);
+#endif
+
+ /* free */
+ MEM_freeN(mdb->varidx);
+
+ nlDeleteContext(context);
+}
+
+void harmonic_coordinates_bind(Scene *scene, MeshDeformModifierData *mmd, float (*vertexcos)[3], int totvert, float cagemat[][4])
+{
+ MeshDeformBind mdb;
+ MDefBindInfluence *inf;
+ MDefInfluence *mdinf;
+ MDefCell *cell;
+ MVert *mvert;
+ float center[3], vec[3], maxwidth, totweight;
+ int a, b, x, y, z, totinside, offset;
+
+ waitcursor(1);
+ start_progress_bar();
+
+ memset(&mdb, 0, sizeof(MeshDeformBind));
+
+ /* get mesh and cage mesh */
+ mdb.vertexcos= vertexcos;
+ mdb.totvert= totvert;
+
+ mdb.cagedm= mesh_create_derived_no_deform(scene, mmd->object, NULL, CD_MASK_BAREMESH);
+ mdb.totcagevert= mdb.cagedm->getNumVerts(mdb.cagedm);
+ mdb.cagecos= MEM_callocN(sizeof(*mdb.cagecos)*mdb.totcagevert, "MeshDeformBindCos");
+ Mat4CpyMat4(mdb.cagemat, cagemat);
+
+ mvert= mdb.cagedm->getVertArray(mdb.cagedm);
+ for(a=0; a<mdb.totcagevert; a++)
+ VECCOPY(mdb.cagecos[a], mvert[a].co)
+
+ /* compute bounding box of the cage mesh */
+ INIT_MINMAX(mdb.min, mdb.max);
+
+ for(a=0; a<mdb.totcagevert; a++)
+ DO_MINMAX(mdb.cagecos[a], mdb.min, mdb.max);
+
+ /* allocate memory */
+ mdb.size= (2<<(mmd->gridsize-1)) + 2;
+ mdb.size3= mdb.size*mdb.size*mdb.size;
+ mdb.tag= MEM_callocN(sizeof(int)*mdb.size3, "MeshDeformBindTag");
+ mdb.phi= MEM_callocN(sizeof(float)*mdb.size3, "MeshDeformBindPhi");
+ mdb.totalphi= MEM_callocN(sizeof(float)*mdb.size3, "MeshDeformBindTotalPhi");
+ mdb.boundisect= MEM_callocN(sizeof(*mdb.boundisect)*mdb.size3, "MDefBoundIsect");
+ mdb.semibound= MEM_callocN(sizeof(int)*mdb.size3, "MDefSemiBound");
+
+ mdb.inside= MEM_callocN(sizeof(int)*mdb.totvert, "MDefInside");
+
+ if(mmd->flag & MOD_MDEF_DYNAMIC_BIND)
+ mdb.dyngrid= MEM_callocN(sizeof(MDefBindInfluence*)*mdb.size3, "MDefDynGrid");
+ else
+ mdb.weights= MEM_callocN(sizeof(float)*mdb.totvert*mdb.totcagevert, "MDefWeights");
+
+ mdb.memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
+ BLI_memarena_use_calloc(mdb.memarena);
+
+ /* make bounding box equal size in all directions, add padding, and compute
+ * width of the cells */
+ maxwidth = -1.0f;
+ for(a=0; a<3; a++)
+ if(mdb.max[a]-mdb.min[a] > maxwidth)
+ maxwidth= mdb.max[a]-mdb.min[a];
+
+ for(a=0; a<3; a++) {
+ center[a]= (mdb.min[a]+mdb.max[a])*0.5f;
+ mdb.min[a]= center[a] - maxwidth*0.5f;
+ mdb.max[a]= center[a] + maxwidth*0.5f;
+
+ mdb.width[a]= (mdb.max[a]-mdb.min[a])/(mdb.size-4);
+ mdb.min[a] -= 2.1f*mdb.width[a];
+ mdb.max[a] += 2.1f*mdb.width[a];
+
+ mdb.width[a]= (mdb.max[a]-mdb.min[a])/mdb.size;
+ mdb.halfwidth[a]= mdb.width[a]*0.5f;
+ }
+
+ progress_bar(0, "Setting up mesh deform system");
+
+#if 0
+ /* create ray tree */
+ meshdeform_ray_tree_create(&mdb);
+#endif
+
+ totinside= 0;
+ for(a=0; a<mdb.totvert; a++) {
+ VECCOPY(vec, mdb.vertexcos[a]);
+ Mat4MulVecfl(mdb.cagemat, vec);
+ mdb.inside[a]= meshdeform_inside_cage(&mdb, vec);
+ if(mdb.inside[a])
+ totinside++;
+ }
+
+ /* free temporary MDefBoundIsects */
+ BLI_memarena_free(mdb.memarena);
+ mdb.memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
+
+ /* start with all cells untyped */
+ for(a=0; a<mdb.size3; a++)
+ mdb.tag[a]= MESHDEFORM_TAG_UNTYPED;
+
+ /* detect intersections and tag boundary cells */
+ for(z=0; z<mdb.size; z++)
+ for(y=0; y<mdb.size; y++)
+ for(x=0; x<mdb.size; x++)
+ meshdeform_add_intersections(&mdb, x, y, z);
+
+#if 0
+ /* free ray tree */
+ meshdeform_ray_tree_free(&mdb);
+#endif
+
+ /* compute exterior and interior tags */
+ meshdeform_bind_floodfill(&mdb);
+
+ for(z=0; z<mdb.size; z++)
+ for(y=0; y<mdb.size; y++)
+ for(x=0; x<mdb.size; x++)
+ meshdeform_check_semibound(&mdb, x, y, z);
+
+ /* solve */
+ meshdeform_matrix_solve(&mdb);
+
+ /* assign results */
+ mmd->bindcos= (float*)mdb.cagecos;
+ mmd->totvert= mdb.totvert;
+ mmd->totcagevert= mdb.totcagevert;
+ Mat4CpyMat4(mmd->bindmat, mmd->object->obmat);
+
+ if(mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
+ mmd->totinfluence= 0;
+ for(a=0; a<mdb.size3; a++)
+ for(inf=mdb.dyngrid[a]; inf; inf=inf->next)
+ mmd->totinfluence++;
+
+ /* convert MDefBindInfluences to smaller MDefInfluences */
+ mmd->dyngrid= MEM_callocN(sizeof(MDefCell)*mdb.size3, "MDefDynGrid");
+ mmd->dyninfluences= MEM_callocN(sizeof(MDefInfluence)*mmd->totinfluence, "MDefInfluence");
+ offset= 0;
+ for(a=0; a<mdb.size3; a++) {
+ cell= &mmd->dyngrid[a];
+ cell->offset= offset;
+
+ totweight= 0.0f;
+ mdinf= mmd->dyninfluences + cell->offset;
+ for(inf=mdb.dyngrid[a]; inf; inf=inf->next, mdinf++) {
+ mdinf->weight= inf->weight;
+ mdinf->vertex= inf->vertex;
+ totweight += mdinf->weight;
+ cell->totinfluence++;
+ }
+
+ if(totweight > 0.0f) {
+ mdinf= mmd->dyninfluences + cell->offset;
+ for(b=0; b<cell->totinfluence; b++, mdinf++)
+ mdinf->weight /= totweight;
+ }
+
+ offset += cell->totinfluence;
+ }
+
+ mmd->dynverts= mdb.inside;
+ mmd->dyngridsize= mdb.size;
+ VECCOPY(mmd->dyncellmin, mdb.min);
+ mmd->dyncellwidth= mdb.width[0];
+ MEM_freeN(mdb.dyngrid);
+ }
+ else {
+ mmd->bindweights= mdb.weights;
+ MEM_freeN(mdb.inside);
+ }
+
+ /* transform bindcos to world space */
+ for(a=0; a<mdb.totcagevert; a++)
+ Mat4MulVecfl(mmd->object->obmat, mmd->bindcos+a*3);
+
+ /* free */
+ mdb.cagedm->release(mdb.cagedm);
+ MEM_freeN(mdb.tag);
+ MEM_freeN(mdb.phi);
+ MEM_freeN(mdb.totalphi);
+ MEM_freeN(mdb.boundisect);
+ MEM_freeN(mdb.semibound);
+ BLI_memarena_free(mdb.memarena);
+
+ end_progress_bar();
+ waitcursor(0);
+}
+
diff --git a/source/blender/editors/armature/meshlaplacian.h b/source/blender/editors/armature/meshlaplacian.h
new file mode 100644
index 00000000000..00c0aefaec7
--- /dev/null
+++ b/source/blender/editors/armature/meshlaplacian.h
@@ -0,0 +1,85 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * BIF_meshlaplacian.h: Algorithms using the mesh laplacian.
+ */
+
+#ifndef BIF_MESHLAPLACIAN_H
+#define BIF_MESHLAPLACIAN_H
+
+//#define RIGID_DEFORM
+
+struct Scene;
+struct Object;
+struct Mesh;
+struct bDeformGroup;
+struct MeshDeformModifierData;
+
+#ifdef RIGID_DEFORM
+struct EditMesh;
+#endif
+
+/* Laplacian System */
+
+struct LaplacianSystem;
+typedef struct LaplacianSystem LaplacianSystem;
+
+LaplacianSystem *laplacian_construct_begin(int totvert, int totface, int lsq);
+
+void laplacian_add_vertex(LaplacianSystem *sys, float *co, int pinned);
+void laplacian_add_triangle(LaplacianSystem *sys, int v1, int v2, int v3);
+
+void laplacian_construct_end(LaplacianSystem *sys);
+void laplacian_delete(LaplacianSystem *sys);
+
+void laplacian_begin_solve(LaplacianSystem *sys, int index);
+void laplacian_add_right_hand_side(LaplacianSystem *sys, int v, float value);
+int laplacian_system_solve(LaplacianSystem *sys);
+float laplacian_system_get_solution(int v);
+
+/* Heat Weighting */
+
+void heat_bone_weighting(struct Object *ob, struct Mesh *me, float (*verts)[3],
+ int numbones, struct bDeformGroup **dgrouplist,
+ struct bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3],
+ int *selected);
+
+#ifdef RIGID_DEFORM
+/* As-Rigid-As-Possible Deformation */
+
+void rigid_deform_begin(struct EditMesh *em);
+void rigid_deform_iteration(void);
+void rigid_deform_end(int cancel);
+#endif
+
+/* Harmonic Coordinates */
+
+void harmonic_coordinates_bind(struct Scene *scene, struct MeshDeformModifierData *mmd,
+ float (*vertexcos)[3], int totvert, float cagemat[][4]);
+
+#endif
+
diff --git a/source/blender/editors/armature/poselib.c b/source/blender/editors/armature/poselib.c
new file mode 100644
index 00000000000..fc5b98b1690
--- /dev/null
+++ b/source/blender/editors/armature/poselib.c
@@ -0,0 +1,1492 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h"
+
+#include "DNA_listBase.h"
+#include "DNA_anim_types.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_object_force.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_depsgraph.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+
+#include "BKE_global.h"
+#include "BKE_context.h"
+#include "BKE_report.h"
+#include "BKE_utildefines.h"
+
+#include "PIL_time.h" /* sleep */
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "ED_anim_api.h"
+#include "ED_armature.h"
+#include "ED_keyframes_draw.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_edit.h"
+#include "ED_screen.h"
+
+#include "armature_intern.h"
+
+/* ******* XXX ********** */
+
+static void BIF_undo_push() {}
+static void error() {}
+
+static void action_set_activemarker() {}
+
+/* ************************************************************* */
+/* == POSE-LIBRARY TOOL FOR BLENDER ==
+ *
+ * Overview:
+ * This tool allows animators to store a set of frequently used poses to dump into
+ * the active action to help in "budget" productions to quickly block out new actions.
+ * It acts as a kind of "glorified clipboard for poses", allowing for naming of poses.
+ *
+ * Features:
+ * - PoseLibs are simply normal Actions
+ * - Each "pose" is simply a set of keyframes that occur on a particular frame
+ * -> a set of TimeMarkers that belong to each Action, help 'label' where a 'pose' can be
+ * found in the Action
+ * - The Scrollwheel or PageUp/Down buttons when used in a special mode or after pressing/holding
+ * [a modifier] key, cycles through the poses available for the active pose's poselib, allowing the
+ * animator to preview what action best suits that pose
+ */
+/* ************************************************************* */
+
+/* gets list of poses in poselib as a string usable for pupmenu() */
+char *poselib_build_poses_menu (bAction *act, char title[])
+{
+ DynStr *pupds= BLI_dynstr_new();
+ TimeMarker *marker;
+ char *str;
+ char buf[64];
+ int i;
+
+ /* add title first */
+ sprintf(buf, "%s%%t|", title);
+ BLI_dynstr_append(pupds, buf);
+
+ /* loop through markers, adding them */
+ for (marker=act->markers.first, i=1; marker; marker=marker->next, i++) {
+ BLI_dynstr_append(pupds, marker->name);
+
+ sprintf(buf, "%%x%d", i);
+ BLI_dynstr_append(pupds, buf);
+
+ if (marker->next)
+ BLI_dynstr_append(pupds, "|");
+ }
+
+ /* convert to normal MEM_malloc'd string */
+ str= BLI_dynstr_get_cstring(pupds);
+ BLI_dynstr_free(pupds);
+
+ return str;
+}
+
+/* gets the first available frame in poselib to store a pose on
+ * - frames start from 1, and a pose should occur on every frame... 0 is error!
+ */
+int poselib_get_free_index (bAction *act)
+{
+ TimeMarker *marker;
+ int low=0, high=0;
+
+ /* sanity checks */
+ if (ELEM(NULL, act, act->markers.first)) return 1;
+
+ /* loop over poses finding various values (poses are not stored in chronological order) */
+ for (marker= act->markers.first; marker; marker= marker->next) {
+ /* only increase low if value is 1 greater than low, to find "gaps" where
+ * poses were removed from the poselib
+ */
+ if (marker->frame == (low + 1))
+ low++;
+
+ /* value replaces high if it is the highest value encountered yet */
+ if (marker->frame > high)
+ high= marker->frame;
+ }
+
+ /* - if low is not equal to high, then low+1 is a gap
+ * - if low is equal to high, then high+1 is the next index (add at end)
+ */
+ if (low < high)
+ return (low + 1);
+ else
+ return (high + 1);
+}
+
+/* returns the active pose for a poselib */
+TimeMarker *poselib_get_active_pose (bAction *act)
+{
+ if ((act) && (act->active_marker))
+ return BLI_findlink(&act->markers, act->active_marker-1);
+ else
+ return NULL;
+}
+
+/* ************************************************************* */
+
+/* Initialise a new poselib (whether it is needed or not) */
+bAction *poselib_init_new (Object *ob)
+{
+ /* sanity checks - only for armatures */
+ if (ELEM(NULL, ob, ob->pose))
+ return NULL;
+
+ /* init object's poselib action (unlink old one if there) */
+ if (ob->poselib)
+ ob->poselib->id.us--;
+ ob->poselib= add_empty_action("PoseLib");
+
+ return ob->poselib;
+}
+
+/* Initialise a new poselib (checks if that needs to happen) */
+bAction *poselib_validate (Object *ob)
+{
+ if (ELEM(NULL, ob, ob->pose))
+ return NULL;
+ else if (ob->poselib == NULL)
+ return poselib_init_new(ob);
+ else
+ return ob->poselib;
+}
+
+
+/* This tool automagically generates/validates poselib data so that it corresponds to the data
+ * in the action. This is for use in making existing actions usable as poselibs.
+ */
+// TODO: operatorfy me!
+void poselib_validate_act (bAction *act)
+{
+ ListBase keys = {NULL, NULL};
+ ActKeyColumn *ak;
+ TimeMarker *marker, *markern;
+
+ /* validate action and poselib */
+ if (act == NULL) {
+ error("No Action to validate");
+ return;
+ }
+
+ /* determine which frames have keys */
+ action_to_keylist(act, &keys, NULL, NULL);
+
+ /* for each key, make sure there is a correspnding pose */
+ for (ak= keys.first; ak; ak= ak->next) {
+ /* check if any pose matches this */
+ for (marker= act->markers.first; marker; marker= marker->next) {
+ if (IS_EQ(marker->frame, ak->cfra)) {
+ marker->flag = -1;
+ break;
+ }
+ }
+
+ /* add new if none found */
+ if (marker == NULL) {
+ char name[64];
+
+ /* add pose to poselib */
+ marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker");
+
+ strcpy(name, "Pose");
+ BLI_strncpy(marker->name, name, sizeof(marker->name));
+
+ marker->frame= (int)ak->cfra;
+ marker->flag= -1;
+
+ BLI_addtail(&act->markers, marker);
+ }
+ }
+
+ /* remove all untagged poses (unused), and remove all tags */
+ for (marker= act->markers.first; marker; marker= markern) {
+ markern= marker->next;
+
+ if (marker->flag != -1)
+ BLI_freelinkN(&act->markers, marker);
+ else
+ marker->flag = 0;
+ }
+
+ /* free temp memory */
+ BLI_freelistN(&keys);
+
+ BIF_undo_push("PoseLib Validate Action");
+}
+
+/* ************************************************************* */
+
+/* Pointers to the builtin KeyingSets that we want to use */
+static KeyingSet *poselib_ks_locrotscale = NULL; /* quaternion rotations */
+static KeyingSet *poselib_ks_locrotscale2 = NULL; /* euler rotations */ // XXX FIXME...
+static short poselib_ks_need_init= 1; /* have the above been obtained yet? */
+
+/* Make sure the builtin KeyingSets are initialised properly
+ * (only gets called on first run of poselib_add_current_pose).
+ */
+static void poselib_get_builtin_keyingsets (void)
+{
+ /* only if we haven't got these yet */
+ // FIXME: this assumes that we will always get the builtin sets...
+ if (poselib_ks_need_init) {
+ /* LocRotScale (quaternions) */
+ poselib_ks_locrotscale= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale");
+
+ /* LocRotScale (euler) */
+ //ks_locrotscale2= ANIM_builtin_keyingset_get_named(ks_locrotscale, "LocRotScale");
+ poselib_ks_locrotscale2= poselib_ks_locrotscale; // FIXME: for now, just use the same one...
+
+ /* clear flag requesting init */
+ poselib_ks_need_init= 0;
+ }
+}
+
+/* ----- */
+
+static void poselib_add_menu_invoke__replacemenu (bContext *C, uiMenuItem *head, void *arg)
+{
+ Object *ob= CTX_data_active_object(C);
+ bAction *act= ob->poselib;
+ TimeMarker *marker;
+
+ /* add each marker to this menu */
+ for (marker= act->markers.first; marker; marker= marker->next)
+ uiMenuItemIntO(head, marker->name, ICON_ARMATURE_DATA, "POSELIB_OT_pose_add", "frame", marker->frame);
+}
+
+static int poselib_add_menu_invoke (bContext *C, wmOperator *op, wmEvent *evt)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+ bArmature *arm= (ob) ? ob->data : NULL;
+ bPose *pose= (ob) ? ob->pose : NULL;
+ uiMenuItem *head;
+
+ /* sanity check */
+ if (ELEM3(NULL, ob, arm, pose))
+ return OPERATOR_CANCELLED;
+
+ /* start building */
+ head= uiPupMenuBegin(op->type->name, 0);
+ uiMenuContext(head, WM_OP_EXEC_DEFAULT);
+
+ /* add new (adds to the first unoccupied frame) */
+ uiMenuItemIntO(head, "Add New", 0, "POSELIB_OT_pose_add", "frame", poselib_get_free_index(ob->poselib));
+
+ /* check if we have any choices to add a new pose in any other way */
+ if ((ob->poselib) && (ob->poselib->markers.first)) {
+ /* add new (on current frame) */
+ uiMenuItemIntO(head, "Add New (Current Frame)", 0, "POSELIB_OT_pose_add", "frame", CFRA);
+
+ /* replace existing - submenu */
+ uiMenuLevel(head, "Replace Existing...", poselib_add_menu_invoke__replacemenu);
+ }
+
+ uiPupMenuEnd(C, head);
+
+ /* this operator is only for a menu, not used further */
+ return OPERATOR_CANCELLED;
+}
+
+
+static int poselib_add_exec (bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_active_object(C);
+ bAction *act = poselib_validate(ob);
+ bArmature *arm= (ob) ? ob->data : NULL;
+ bPose *pose= (ob) ? ob->pose : NULL;
+ bPoseChannel *pchan;
+ TimeMarker *marker;
+ int frame= RNA_int_get(op->ptr, "frame");
+ char name[64];
+
+ bCommonKeySrc cks;
+ ListBase dsources = {&cks, &cks};
+
+ /* sanity check (invoke should have checked this anyway) */
+ if (ELEM3(NULL, ob, arm, pose))
+ return OPERATOR_CANCELLED;
+
+ /* get name to give to pose */
+ RNA_string_get(op->ptr, "name", name);
+
+ /* add pose to poselib - replaces any existing pose there
+ * - for the 'replace' option, this should end up finding the appropriate marker,
+ * so no new one will be added
+ */
+ for (marker= act->markers.first; marker; marker= marker->next) {
+ if (marker->frame == frame) {
+ BLI_strncpy(marker->name, name, sizeof(marker->name));
+ break;
+ }
+ }
+ if (marker == NULL) {
+ marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker");
+
+ BLI_strncpy(marker->name, name, sizeof(marker->name));
+ marker->frame= frame;
+
+ BLI_addtail(&act->markers, marker);
+ }
+
+ /* validate name */
+ BLI_uniquename(&act->markers, marker, "Pose", '.', offsetof(TimeMarker, name), 64);
+
+ /* make sure we've got KeyingSets to use */
+ poselib_get_builtin_keyingsets();
+
+ /* init common-key-source for use by KeyingSets */
+ memset(&cks, 0, sizeof(bCommonKeySrc));
+ cks.id= &ob->id;
+
+ /* loop through selected posechannels, keying their pose to the action */
+ for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
+ /* check if available */
+ if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
+ if (pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE)) {
+ /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
+ cks.pchan= pchan;
+
+ /* KeyingSet to use depends on rotation mode */
+ if (pchan->rotmode)
+ modify_keyframes(C, &dsources, act, poselib_ks_locrotscale2, MODIFYKEY_MODE_INSERT, (float)frame);
+ else
+ modify_keyframes(C, &dsources, act, poselib_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)frame);
+ }
+ }
+ }
+
+ /* store new 'active' pose number */
+ act->active_marker= BLI_countlist(&act->markers);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+
+void POSELIB_OT_pose_add (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "PoseLib Add Pose";
+ ot->idname= "POSELIB_OT_pose_add";
+ ot->description= "Add the current Pose to the active Pose Library";
+
+ /* api callbacks */
+ ot->invoke= poselib_add_menu_invoke;
+ ot->exec= poselib_add_exec;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "frame", 1, 0, INT_MAX, "Frame", "Frame to store pose on", 0, INT_MAX);
+ RNA_def_string(ot->srna, "name", "Pose", 64, "Pose Name", "Name of newly added Pose");
+}
+
+/* ----- */
+
+static int poselib_stored_pose_menu_invoke (bContext *C, wmOperator *op, wmEvent *evt)
+{
+ Object *ob= CTX_data_active_object(C);
+ bAction *act= (ob) ? ob->poselib : NULL;
+ TimeMarker *marker;
+ uiMenuItem *head;
+ int i;
+
+ /* sanity check */
+ if (ELEM(NULL, ob, act))
+ return OPERATOR_CANCELLED;
+
+ /* start building */
+ head= uiPupMenuBegin(op->type->name, 0);
+ uiMenuContext(head, WM_OP_EXEC_DEFAULT);
+
+ /* add each marker to this menu */
+ for (marker=act->markers.first, i=0; marker; marker= marker->next, i++)
+ uiMenuItemIntO(head, marker->name, ICON_ARMATURE_DATA, op->idname, "index", i);
+
+ uiPupMenuEnd(C, head);
+
+ /* this operator is only for a menu, not used further */
+ return OPERATOR_CANCELLED;
+}
+
+
+
+static int poselib_remove_exec (bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_active_object(C);
+ bAction *act= (ob) ? ob->poselib : NULL;
+ TimeMarker *marker;
+ FCurve *fcu;
+
+ /* check if valid poselib */
+ if (act == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Object doesn't have PoseLib data");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get index (and pointer) of pose to remove */
+ marker= BLI_findlink(&act->markers, RNA_int_get(op->ptr, "index"));
+ if (marker == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Invalid index for Pose");
+ }
+
+ /* remove relevant keyframes */
+ for (fcu= act->curves.first; fcu; fcu= fcu->next) {
+ BezTriple *bezt;
+ int i;
+
+ if (fcu->bezt) {
+ for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ /* check if remove */
+ if (IS_EQ(bezt->vec[1][0], marker->frame)) {
+ delete_fcurve_key(fcu, i, 1);
+ break;
+ }
+ }
+ }
+ }
+
+ /* remove poselib from list */
+ BLI_freelinkN(&act->markers, marker);
+
+ /* fix active pose number */
+ act->active_marker= 0;
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void POSELIB_OT_pose_remove (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "PoseLib Remove Pose";
+ ot->idname= "POSELIB_OT_pose_remove";
+ ot->description= "Remove nth pose from the active Pose Library";
+
+ /* api callbacks */
+ ot->invoke= poselib_stored_pose_menu_invoke;
+ ot->exec= poselib_remove_exec;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "The index of the pose to remove", 0, INT_MAX);
+}
+
+
+
+static int poselib_rename_exec (bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_active_object(C);
+ bAction *act= (ob) ? ob->poselib : NULL;
+ TimeMarker *marker;
+ char newname[64];
+
+ /* check if valid poselib */
+ if (act == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Object doesn't have PoseLib data");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get index (and pointer) of pose to remove */
+ marker= BLI_findlink(&act->markers, RNA_int_get(op->ptr, "index"));
+ if (marker == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Invalid index for Pose");
+ }
+
+ /* get new name */
+ RNA_string_get(op->ptr, "name", newname);
+
+ /* copy name and validate it */
+ BLI_strncpy(marker->name, newname, sizeof(marker->name));
+ BLI_uniquename(&act->markers, marker, "Pose", '.', offsetof(TimeMarker, name), 64);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void POSELIB_OT_pose_rename (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "PoseLib Rename Pose";
+ ot->idname= "POSELIB_OT_pose_rename";
+ ot->description= "Rename nth pose from the active Pose Library";
+
+ /* api callbacks */
+ ot->invoke= poselib_stored_pose_menu_invoke;
+ ot->exec= poselib_rename_exec;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "The index of the pose to remove", 0, INT_MAX);
+ RNA_def_string(ot->srna, "name", "RenamedPose", 64, "New Pose Name", "New name for pose");
+}
+
+/* ************************************************************* */
+
+/* Simple struct for storing settings/data for use during PoseLib preview */
+typedef struct tPoseLib_PreviewData {
+ ListBase backups; /* tPoseLib_Backup structs for restoring poses */
+ ListBase searchp; /* LinkData structs storing list of poses which match the current search-string */
+
+ Scene *scene; /* active scene */
+ ScrArea *sa; /* active area */
+
+ PointerRNA rna_ptr; /* RNA-Pointer to Object 'ob' */
+ Object *ob; /* object to work on */
+ bArmature *arm; /* object's armature data */
+ bPose *pose; /* object's pose */
+ bAction *act; /* poselib to use */
+ TimeMarker *marker; /* 'active' pose */
+
+ short state; /* state of main loop */
+ short redraw; /* redraw/update settings during main loop */
+ short flag; /* flags for various settings */
+
+ int selcount; /* number of selected elements to work on */
+ int totcount; /* total number of elements to work on */
+
+ char headerstr[200]; /* Info-text to print in header */
+
+ char searchstr[64]; /* (Part of) Name to search for to filter poses that get shown */
+ char searchold[64]; /* Previously set searchstr (from last loop run), so that we can detected when to rebuild searchp */
+ short search_cursor; /* position of cursor in searchstr (cursor occurs before the item at the nominated index) */
+} tPoseLib_PreviewData;
+
+/* defines for tPoseLib_PreviewData->state values */
+enum {
+ PL_PREVIEW_ERROR = -1,
+ PL_PREVIEW_RUNNING,
+ PL_PREVIEW_CONFIRM,
+ PL_PREVIEW_CANCEL,
+ PL_PREVIEW_RUNONCE
+};
+
+/* defines for tPoseLib_PreviewData->redraw values */
+enum {
+ PL_PREVIEW_NOREDRAW = 0,
+ PL_PREVIEW_REDRAWALL,
+ PL_PREVIEW_REDRAWHEADER,
+};
+
+/* defines for tPoseLib_PreviewData->flag values */
+enum {
+ PL_PREVIEW_FIRSTTIME = (1<<0),
+ PL_PREVIEW_SHOWORIGINAL = (1<<1)
+};
+
+/* ---------------------------- */
+
+/* simple struct for storing backup info */
+typedef struct tPoseLib_Backup {
+ struct tPoseLib_Backup *next, *prev;
+
+ bPoseChannel *pchan;
+ bPoseChannel olddata;
+} tPoseLib_Backup;
+
+/* Makes a copy of the current pose for restoration purposes - doesn't do constraints currently */
+static void poselib_backup_posecopy (tPoseLib_PreviewData *pld)
+{
+ bActionGroup *agrp;
+ bPoseChannel *pchan;
+
+ /* for each posechannel that has an actionchannel in */
+ for (agrp= pld->act->groups.first; agrp; agrp= agrp->next) {
+ /* try to find posechannel */
+ pchan= get_pose_channel(pld->pose, agrp->name);
+
+ /* backup data if available */
+ if (pchan) {
+ tPoseLib_Backup *plb;
+
+ /* store backup */
+ plb= MEM_callocN(sizeof(tPoseLib_Backup), "tPoseLib_Backup");
+
+ plb->pchan= pchan;
+ memcpy(&plb->olddata, plb->pchan, sizeof(bPoseChannel));
+
+ BLI_addtail(&pld->backups, plb);
+
+ /* mark as being affected */
+ if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))
+ pld->selcount++;
+ pld->totcount++;
+ }
+ }
+}
+
+/* Restores original pose - doesn't do constraints currently */
+static void poselib_backup_restore (tPoseLib_PreviewData *pld)
+{
+ tPoseLib_Backup *plb;
+
+ for (plb= pld->backups.first; plb; plb= plb->next) {
+ memcpy(plb->pchan, &plb->olddata, sizeof(bPoseChannel));
+ }
+}
+
+/* ---------------------------- */
+
+/* Applies the appropriate stored pose from the pose-library to the current pose
+ * - assumes that a valid object, with a poselib has been supplied
+ * - gets the string to print in the header
+ * - this code is based on the code for extract_pose_from_action in blenkernel/action.c
+ */
+static void poselib_apply_pose (tPoseLib_PreviewData *pld)
+{
+ PointerRNA *ptr= &pld->rna_ptr;
+ bArmature *arm= pld->arm;
+ bPose *pose= pld->pose;
+ bPoseChannel *pchan;
+ bAction *act= pld->act;
+ bActionGroup *agrp;
+
+ BeztEditData bed;
+ BeztEditFunc group_ok_cb;
+ int frame= 1;
+
+ /* get the frame */
+ if (pld->marker)
+ frame= pld->marker->frame;
+ else
+ return;
+
+
+ /* init settings for testing groups for keyframes */
+ group_ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
+ memset(&bed, 0, sizeof(BeztEditData));
+ bed.f1= ((float)frame) - 0.5f;
+ bed.f2= ((float)frame) + 0.5f;
+
+
+ /* start applying - only those channels which have a key at this point in time! */
+ for (agrp= act->groups.first; agrp; agrp= agrp->next) {
+ /* check if group has any keyframes */
+ if (ANIM_animchanneldata_keys_bezier_loop(&bed, agrp, ALE_GROUP, NULL, group_ok_cb, NULL, 0)) {
+ /* has keyframe on this frame, so try to get a PoseChannel with this name */
+ pchan= get_pose_channel(pose, agrp->name);
+
+ if (pchan) {
+ short ok= 0;
+
+ /* check if this bone should get any animation applied */
+ if (pld->selcount == 0) {
+ /* if no bones are selected, then any bone is ok */
+ ok= 1;
+ }
+ else if (pchan->bone) {
+ /* only ok if bone is visible and selected */
+ if ( (pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE)) &&
+ (pchan->bone->flag & BONE_HIDDEN_P)==0 &&
+ (pchan->bone->layer & arm->layer) )
+ ok = 1;
+ }
+
+ if (ok)
+ animsys_evaluate_action_group(ptr, act, agrp, NULL, (float)frame);
+ }
+ }
+ }
+}
+
+/* Auto-keys/tags bones affected by the pose used from the poselib */
+static void poselib_keytag_pose (Scene *scene, tPoseLib_PreviewData *pld)
+{
+ bPose *pose= pld->pose;
+ bPoseChannel *pchan;
+ bAction *act= pld->act;
+ bActionGroup *agrp;
+
+ /* start tagging/keying */
+ for (agrp= act->groups.first; agrp; agrp= agrp->next) {
+ /* only for selected action channels */
+ if (agrp->flag & AGRP_SELECTED) {
+ pchan= get_pose_channel(pose, agrp->name);
+
+ if (pchan) {
+#if 0 // XXX old animation system
+ // TODO: use a standard autokeying function in future (to allow autokeying-editkeys to work)
+ if (IS_AUTOKEY_MODE(NORMAL)) {
+ ID *id= &pld->ob->id;
+
+ /* Set keys on pose */
+ if (pchan->flag & POSE_ROT) {
+ insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0);
+ }
+ if (pchan->flag & POSE_SIZE) {
+ insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0);
+ }
+ if (pchan->flag & POSE_LOC) {
+ insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0);
+ }
+
+ /* clear any unkeyed tags */
+ if (pchan->bone)
+ pchan->bone->flag &= ~BONE_UNKEYED;
+ }
+ else {
+ /* add unkeyed tags */
+ if (pchan->bone)
+ pchan->bone->flag |= BONE_UNKEYED;
+ }
+#endif // XXX old animation system
+
+ }
+ }
+ }
+}
+
+/* Apply the relevant changes to the pose */
+static void poselib_preview_apply (bContext *C, wmOperator *op)
+{
+ tPoseLib_PreviewData *pld= (tPoseLib_PreviewData *)op->customdata;
+
+ /* only recalc pose (and its dependencies) if pose has changed */
+ if (pld->redraw == PL_PREVIEW_REDRAWALL) {
+ /* don't clear pose if firsttime */
+ if ((pld->flag & PL_PREVIEW_FIRSTTIME)==0)
+ poselib_backup_restore(pld);
+ else
+ pld->flag &= ~PL_PREVIEW_FIRSTTIME;
+
+ /* pose should be the right one to draw (unless we're temporarily not showing it) */
+ if ((pld->flag & PL_PREVIEW_SHOWORIGINAL)==0) {
+ RNA_int_set(op->ptr, "pose_index", BLI_findindex(&pld->act->markers, pld->marker));
+ poselib_apply_pose(pld);
+ }
+ else
+ RNA_int_set(op->ptr, "pose_index", -2); /* -2 means don't apply any pose */
+
+ /* old optimize trick... this enforces to bypass the depgraph
+ * - note: code copied from transform_generics.c -> recalcData()
+ */
+ // FIXME: shouldn't this use the builtin stuff?
+ if ((pld->arm->flag & ARM_DELAYDEFORM)==0)
+ DAG_object_flush_update(pld->scene, pld->ob, OB_RECALC_DATA); /* sets recalc flags */
+ else
+ where_is_pose(pld->scene, pld->ob);
+ }
+
+ /* do header print - if interactively previewing */
+ if (pld->state == PL_PREVIEW_RUNNING) {
+ if (pld->flag & PL_PREVIEW_SHOWORIGINAL) {
+ sprintf(pld->headerstr, "PoseLib Previewing Pose: [Showing Original Pose] | Use Tab to start previewing poses again");
+ ED_area_headerprint(pld->sa, pld->headerstr);
+ }
+ else if (pld->searchstr[0]) {
+ char tempstr[65];
+ char markern[64];
+ short index;
+
+ /* get search-string */
+ index= pld->search_cursor;
+
+ if (IN_RANGE(index, 0, 64)) {
+ memcpy(&tempstr[0], &pld->searchstr[0], index);
+ tempstr[index]= '|';
+ memcpy(&tempstr[index+1], &pld->searchstr[index], 64-index);
+ }
+ else {
+ strncpy(tempstr, pld->searchstr, 64);
+ }
+
+ /* get marker name */
+ if (pld->marker)
+ strcpy(markern, pld->marker->name);
+ else
+ strcpy(markern, "No Matches");
+
+ sprintf(pld->headerstr, "PoseLib Previewing Pose: Filter - [%s] | Current Pose - \"%s\" | Use ScrollWheel or PageUp/Down to change", tempstr, markern);
+ ED_area_headerprint(pld->sa, pld->headerstr);
+ }
+ else {
+ sprintf(pld->headerstr, "PoseLib Previewing Pose: \"%s\" | Use ScrollWheel or PageUp/Down to change", pld->marker->name);
+ ED_area_headerprint(pld->sa, pld->headerstr);
+ }
+ }
+
+ /* request drawing of view + clear redraw flag */
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM|ND_POSE, pld->ob);
+ pld->redraw= PL_PREVIEW_NOREDRAW;
+}
+
+/* ---------------------------- */
+
+/* This helper function is called during poselib_preview_poses to find the
+ * pose to preview next (after a change event)
+ */
+static void poselib_preview_get_next (tPoseLib_PreviewData *pld, int step)
+{
+ /* check if we no longer have search-string, but don't have any marker */
+ if (pld->marker == NULL) {
+ if ((step) && (pld->searchstr[0] == 0))
+ pld->marker= pld->act->markers.first;
+ }
+
+ /* the following operations assume that there is a starting point and direction */
+ if ((pld->marker) && (step)) {
+ /* search-string dictates a special approach */
+ if (pld->searchstr[0]) {
+ TimeMarker *marker;
+ LinkData *ld, *ldn, *ldc;
+
+ /* free and rebuild if needed (i.e. if search-str changed) */
+ if (strcmp(pld->searchstr, pld->searchold)) {
+ /* free list of temporary search matches */
+ BLI_freelistN(&pld->searchp);
+
+ /* generate a new list of search matches */
+ for (marker= pld->act->markers.first; marker; marker= marker->next) {
+ /* does the name partially match?
+ * - don't worry about case, to make it easier for users to quickly input a name (or
+ * part of one), which is the whole point of this feature
+ */
+ if (BLI_strcasestr(marker->name, pld->searchstr)) {
+ /* make link-data to store reference to it */
+ ld= MEM_callocN(sizeof(LinkData), "PoseMatch");
+ ld->data= marker;
+ BLI_addtail(&pld->searchp, ld);
+ }
+ }
+
+ /* set current marker to NULL (so that we start from first) */
+ pld->marker= NULL;
+ }
+
+ /* check if any matches */
+ if (pld->searchp.first == NULL) {
+ pld->marker= NULL;
+ return;
+ }
+
+ /* find first match */
+ for (ldc= pld->searchp.first; ldc; ldc= ldc->next) {
+ if (ldc->data == pld->marker)
+ break;
+ }
+ if (ldc == NULL)
+ ldc= pld->searchp.first;
+
+ /* Loop through the matches in a cyclic fashion, incrementing/decrementing step as appropriate
+ * until step == 0. At this point, marker should be the correct marker.
+ */
+ if (step > 0) {
+ for (ld=ldc; ld && step; ld=ldn, step--)
+ ldn= (ld->next) ? ld->next : pld->searchp.first;
+ }
+ else {
+ for (ld=ldc; ld && step; ld=ldn, step++)
+ ldn= (ld->prev) ? ld->prev : pld->searchp.last;
+ }
+
+ /* set marker */
+ if (ld)
+ pld->marker= ld->data;
+ }
+ else {
+ TimeMarker *marker, *next;
+
+ /* Loop through the markers in a cyclic fashion, incrementing/decrementing step as appropriate
+ * until step == 0. At this point, marker should be the correct marker.
+ */
+ if (step > 0) {
+ for (marker=pld->marker; marker && step; marker=next, step--)
+ next= (marker->next) ? marker->next : pld->act->markers.first;
+ }
+ else {
+ for (marker=pld->marker; marker && step; marker=next, step++)
+ next= (marker->prev) ? marker->prev : pld->act->markers.last;
+ }
+
+ /* it should be fairly impossible for marker to be NULL */
+ if (marker)
+ pld->marker= marker;
+ }
+ }
+}
+
+/* specially handle events for searching */
+static void poselib_preview_handle_search (tPoseLib_PreviewData *pld, unsigned short event, char ascii)
+{
+ /* try doing some form of string manipulation first */
+ switch (event) {
+ case BACKSPACEKEY:
+ if (pld->searchstr[0] && pld->search_cursor) {
+ short len= strlen(pld->searchstr);
+ short index= pld->search_cursor;
+ short i;
+
+ for (i = index; i <= len; i++)
+ pld->searchstr[i-1] = pld->searchstr[i];
+
+ pld->search_cursor--;
+
+ poselib_preview_get_next(pld, 1);
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ return;
+ }
+ break;
+
+ case DELKEY:
+ if (pld->searchstr[0] && pld->searchstr[1]) {
+ short len= strlen(pld->searchstr);
+ short index= pld->search_cursor;
+ int i;
+
+ if (index < len) {
+ for (i = index; i < len; i++)
+ pld->searchstr[i] = pld->searchstr[i+1];
+
+ poselib_preview_get_next(pld, 1);
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ return;
+ }
+ }
+ break;
+ }
+
+ if (ascii) {
+ /* character to add to the string */
+ short index= pld->search_cursor;
+ short len= (pld->searchstr[0]) ? strlen(pld->searchstr) : 0;
+ short i;
+
+ if (len) {
+ for (i = len; i > index; i--)
+ pld->searchstr[i]= pld->searchstr[i-1];
+ }
+ else
+ pld->searchstr[1]= 0;
+
+ pld->searchstr[index]= ascii;
+ pld->search_cursor++;
+
+ poselib_preview_get_next(pld, 1);
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ }
+}
+
+/* handle events for poselib_preview_poses */
+static int poselib_preview_handle_event (bContext *C, wmOperator *op, wmEvent *event)
+{
+ tPoseLib_PreviewData *pld= op->customdata;
+ int ret = OPERATOR_RUNNING_MODAL;
+
+ /* backup stuff that needs to occur before every operation
+ * - make a copy of searchstr, so that we know if cache needs to be rebuilt
+ */
+ strcpy(pld->searchold, pld->searchstr);
+
+ /* if we're currently showing the original pose, only certain events are handled */
+ if (pld->flag & PL_PREVIEW_SHOWORIGINAL) {
+ switch (event->type) {
+ /* exit - cancel */
+ case ESCKEY:
+ case RIGHTMOUSE:
+ pld->state= PL_PREVIEW_CANCEL;
+ break;
+
+ /* exit - confirm */
+ case LEFTMOUSE:
+ case RETKEY:
+ case PADENTER:
+ case SPACEKEY:
+ pld->state= PL_PREVIEW_CONFIRM;
+ break;
+
+ /* view manipulation */
+ /* we add pass through here, so that the operators responsible for these can still run,
+ * even though we still maintain control (as RUNNING_MODAL flag is still set too)
+ */
+ case PAD0: case PAD1: case PAD2: case PAD3: case PAD4:
+ case PAD5: case PAD6: case PAD7: case PAD8: case PAD9:
+ case PADPLUSKEY: case PADMINUS: case MIDDLEMOUSE:
+ //pld->redraw= PL_PREVIEW_REDRAWHEADER;
+ ret |= OPERATOR_PASS_THROUGH;
+ break;
+
+ /* quicky compare to original */
+ case TABKEY:
+ /* only respond to one event */
+ if (event->val == 0) {
+ pld->flag &= ~PL_PREVIEW_SHOWORIGINAL;
+ pld->redraw= PL_PREVIEW_REDRAWALL;
+ }
+ break;
+ }
+
+ /* EXITS HERE... */
+ return ret;
+ }
+
+ /* NORMAL EVENT HANDLING... */
+ /* searching takes priority over normal activity */
+ switch (event->type) {
+ /* exit - cancel */
+ case ESCKEY:
+ case RIGHTMOUSE:
+ pld->state= PL_PREVIEW_CANCEL;
+ break;
+
+ /* exit - confirm */
+ case LEFTMOUSE:
+ case RETKEY:
+ case PADENTER:
+ case SPACEKEY:
+ pld->state= PL_PREVIEW_CONFIRM;
+ break;
+
+ /* toggle between original pose and poselib pose*/
+ case TABKEY:
+ /* only respond to one event */
+ if (event->val == 0) {
+ pld->flag |= PL_PREVIEW_SHOWORIGINAL;
+ pld->redraw= PL_PREVIEW_REDRAWALL;
+ }
+ break;
+
+ /* change to previous pose (cyclic) */
+ case PAGEUPKEY:
+ case WHEELUPMOUSE:
+ poselib_preview_get_next(pld, -1);
+ pld->redraw= PL_PREVIEW_REDRAWALL;
+ break;
+
+ /* change to next pose (cyclic) */
+ case PAGEDOWNKEY:
+ case WHEELDOWNMOUSE:
+ poselib_preview_get_next(pld, 1);
+ pld->redraw= PL_PREVIEW_REDRAWALL;
+ break;
+
+ /* jump 5 poses (cyclic, back) */
+ case DOWNARROWKEY:
+ poselib_preview_get_next(pld, -5);
+ pld->redraw= PL_PREVIEW_REDRAWALL;
+ break;
+
+ /* jump 5 poses (cyclic, forward) */
+ case UPARROWKEY:
+ poselib_preview_get_next(pld, 5);
+ pld->redraw= PL_PREVIEW_REDRAWALL;
+ break;
+
+ /* change to next pose or searching cursor control */
+ case RIGHTARROWKEY:
+ if (pld->searchstr[0]) {
+ /* move text-cursor to the right */
+ if (pld->search_cursor < strlen(pld->searchstr))
+ pld->search_cursor++;
+ pld->redraw= PL_PREVIEW_REDRAWHEADER;
+ }
+ else {
+ /* change to next pose (cyclic) */
+ poselib_preview_get_next(pld, 1);
+ pld->redraw= PL_PREVIEW_REDRAWALL;
+ }
+ break;
+
+ /* change to next pose or searching cursor control */
+ case LEFTARROWKEY:
+ if (pld->searchstr[0]) {
+ /* move text-cursor to the left */
+ if (pld->search_cursor)
+ pld->search_cursor--;
+ pld->redraw= PL_PREVIEW_REDRAWHEADER;
+ }
+ else {
+ /* change to previous pose (cyclic) */
+ poselib_preview_get_next(pld, -1);
+ pld->redraw= PL_PREVIEW_REDRAWALL;
+ }
+ break;
+
+ /* change to first pose or start of searching string */
+ case HOMEKEY:
+ if (pld->searchstr[0]) {
+ pld->search_cursor= 0;
+ pld->redraw= PL_PREVIEW_REDRAWHEADER;
+ }
+ else {
+ /* change to first pose */
+ pld->marker= pld->act->markers.first;
+ pld->act->active_marker= 1;
+
+ pld->redraw= PL_PREVIEW_REDRAWALL;
+ }
+ break;
+
+ /* change to last pose or start of searching string */
+ case ENDKEY:
+ if (pld->searchstr[0]) {
+ pld->search_cursor= strlen(pld->searchstr);
+ pld->redraw= PL_PREVIEW_REDRAWHEADER;
+ }
+ else {
+ /* change to last pose */
+ pld->marker= pld->act->markers.last;
+ pld->act->active_marker= BLI_countlist(&pld->act->markers);
+
+ pld->redraw= PL_PREVIEW_REDRAWALL;
+ }
+ break;
+
+ /* view manipulation */
+ /* we add pass through here, so that the operators responsible for these can still run,
+ * even though we still maintain control (as RUNNING_MODAL flag is still set too)
+ */
+ case MIDDLEMOUSE:
+ //pld->redraw= PL_PREVIEW_REDRAWHEADER;
+ ret |= OPERATOR_PASS_THROUGH;
+ break;
+
+ /* view manipulation, or searching */
+ case PAD0: case PAD1: case PAD2: case PAD3: case PAD4:
+ case PAD5: case PAD6: case PAD7: case PAD8: case PAD9:
+ case PADPLUSKEY: case PADMINUS:
+ if (pld->searchstr[0]) {
+ /* searching... */
+ poselib_preview_handle_search(pld, event->type, event->ascii);
+ }
+ else {
+ /* view manipulation (see above) */
+ //pld->redraw= PL_PREVIEW_REDRAWHEADER;
+ ret |= OPERATOR_PASS_THROUGH;
+ }
+ break;
+
+ /* otherwise, assume that searching might be able to handle it */
+ default:
+ poselib_preview_handle_search(pld, event->type, event->ascii);
+ break;
+ }
+
+ return ret;
+}
+
+/* ---------------------------- */
+
+/* Init PoseLib Previewing data */
+static void poselib_preview_init_data (bContext *C, wmOperator *op)
+{
+ tPoseLib_PreviewData *pld;
+ Object *ob= CTX_data_active_object(C);
+ int pose_index = RNA_int_get(op->ptr, "pose_index");
+
+ /* set up preview state info */
+ op->customdata= pld= MEM_callocN(sizeof(tPoseLib_PreviewData), "PoseLib Preview Data");
+
+ /* get basic data */
+ pld->ob= ob;
+ pld->arm= (ob) ? (ob->data) : NULL;
+ pld->pose= (ob) ? (ob->pose) : NULL;
+ pld->act= (ob) ? (ob->poselib) : NULL;
+
+ pld->scene= CTX_data_scene(C);
+ pld->sa= CTX_wm_area(C);
+
+ /* get starting pose based on RNA-props for this operator */
+ if (pose_index == -1)
+ pld->marker= poselib_get_active_pose(pld->act);
+ else if (pose_index == -2)
+ pld->flag |= PL_PREVIEW_SHOWORIGINAL;
+ else
+ pld->marker= (pld->act) ? BLI_findlink(&pld->act->markers, pose_index) : NULL;
+
+ /* check if valid poselib */
+ if (ELEM3(NULL, pld->ob, pld->pose, pld->arm)) {
+ BKE_report(op->reports, RPT_ERROR, "PoseLib is only for Armatures in PoseMode");
+ pld->state= PL_PREVIEW_ERROR;
+ return;
+ }
+ if (pld->act == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Object doesn't have a valid PoseLib");
+ pld->state= PL_PREVIEW_ERROR;
+ return;
+ }
+ if (pld->marker == NULL) {
+ if (pld->act->markers.first) {
+ /* just use first one then... */
+ pld->marker= pld->act->markers.first;
+ if (pose_index > -2) printf("PoseLib had no active pose\n");
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "PoseLib has no poses to preview/apply");
+ pld->state= PL_PREVIEW_ERROR;
+ return;
+ }
+ }
+
+ /* get ID pointer for applying poses */
+ RNA_id_pointer_create(&ob->id, &pld->rna_ptr);
+
+ /* make backups for restoring pose */
+ poselib_backup_posecopy(pld);
+
+ /* set flags for running */
+ pld->state= PL_PREVIEW_RUNNING;
+ pld->redraw= PL_PREVIEW_REDRAWALL;
+ pld->flag |= PL_PREVIEW_FIRSTTIME;
+
+ /* set depsgraph flags */
+ /* make sure the lock is set OK, unlock can be accidentally saved? */
+ pld->pose->flag |= POSE_LOCKED;
+ pld->pose->flag &= ~POSE_DO_UNLOCK;
+
+ /* clear strings + search */
+ strcpy(pld->headerstr, "");
+ strcpy(pld->searchstr, "");
+ strcpy(pld->searchold, "");
+ pld->search_cursor= 0;
+}
+
+/* After previewing poses */
+static void poselib_preview_cleanup (bContext *C, wmOperator *op)
+{
+ tPoseLib_PreviewData *pld= (tPoseLib_PreviewData *)op->customdata;
+ Scene *scene= pld->scene;
+ Object *ob= pld->ob;
+ bPose *pose= pld->pose;
+ bArmature *arm= pld->arm;
+ bAction *act= pld->act;
+ TimeMarker *marker= pld->marker;
+
+ /* redraw the header so that it doesn't show any of our stuff anymore */
+ ED_area_headerprint(pld->sa, NULL);
+
+ /* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
+ pose->flag |= POSE_DO_UNLOCK;
+
+ /* clear pose if cancelled */
+ if (pld->state == PL_PREVIEW_CANCEL) {
+ poselib_backup_restore(pld);
+
+ /* old optimize trick... this enforces to bypass the depgraph
+ * - note: code copied from transform_generics.c -> recalcData()
+ */
+ if ((arm->flag & ARM_DELAYDEFORM)==0)
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA); /* sets recalc flags */
+ else
+ where_is_pose(scene, ob);
+
+ }
+ else if (pld->state == PL_PREVIEW_CONFIRM) {
+ /* tag poses as appropriate */
+ poselib_keytag_pose(scene, pld);
+
+ /* change active pose setting */
+ act->active_marker= BLI_findindex(&act->markers, marker) + 1;
+ action_set_activemarker(act, marker, 0);
+
+ /* Update event for pose and deformation children */
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+ /* updates */
+ if (IS_AUTOKEY_MODE(scene, NORMAL)) {
+ //remake_action_ipos(ob->action);
+ }
+ else {
+ /* need to trick depgraph, action is not allowed to execute on pose */
+ where_is_pose(scene, ob);
+ ob->recalc= 0;
+ }
+ }
+
+ /* free memory used for backups */
+ BLI_freelistN(&pld->backups);
+ BLI_freelistN(&pld->searchp);
+
+ /* free temp data for operator */
+ MEM_freeN(pld);
+ op->customdata= NULL;
+}
+
+/* End previewing operation */
+static int poselib_preview_exit (bContext *C, wmOperator *op)
+{
+ tPoseLib_PreviewData *pld= op->customdata;
+
+ /* finish up */
+ poselib_preview_cleanup(C, op);
+
+ if (ELEM(pld->state, PL_PREVIEW_CANCEL, PL_PREVIEW_ERROR))
+ return OPERATOR_CANCELLED;
+ else
+ return OPERATOR_FINISHED;
+}
+
+/* Cancel previewing operation (called when exiting Blender) */
+static int poselib_preview_cancel (bContext *C, wmOperator *op)
+{
+ poselib_preview_exit(C, op);
+ return OPERATOR_CANCELLED;
+}
+
+/* main modal status check */
+static int poselib_preview_modal (bContext *C, wmOperator *op, wmEvent *event)
+{
+ tPoseLib_PreviewData *pld= op->customdata;
+ int ret;
+
+ /* 1) check state to see if we're still running */
+ if (pld->state != PL_PREVIEW_RUNNING)
+ return poselib_preview_exit(C, op);
+
+ /* 2) handle events */
+ ret= poselib_preview_handle_event(C, op, event);
+
+ /* 3) apply changes and redraw, otherwise, confirming goes wrong */
+ if (pld->redraw)
+ poselib_preview_apply(C, op);
+
+ return ret;
+}
+
+/* Modal Operator init */
+static int poselib_preview_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ tPoseLib_PreviewData *pld;
+
+ /* check if everything is ok, and init settings for modal operator */
+ poselib_preview_init_data(C, op);
+ pld= (tPoseLib_PreviewData *)op->customdata;
+
+ if (pld->state == PL_PREVIEW_ERROR) {
+ /* an error occurred, so free temp mem used */
+ poselib_preview_cleanup(C, op);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* do initial apply to have something to look at */
+ poselib_preview_apply(C, op);
+
+ /* add temp handler if we're running as a modal operator */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* Repeat operator */
+static int poselib_preview_exec (bContext *C, wmOperator *op)
+{
+ tPoseLib_PreviewData *pld;
+
+ /* check if everything is ok, and init settings for modal operator */
+ poselib_preview_init_data(C, op);
+ pld= (tPoseLib_PreviewData *)op->customdata;
+
+ if (pld->state == PL_PREVIEW_ERROR) {
+ /* an error occurred, so free temp mem used */
+ poselib_preview_cleanup(C, op);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* the exec() callback is effectively a 'run-once' scenario, so set the state to that
+ * so that everything draws correctly
+ */
+ pld->state = PL_PREVIEW_RUNONCE;
+
+ /* apply the active pose */
+ poselib_preview_apply(C, op);
+
+ /* now, set the status to exit */
+ pld->state = PL_PREVIEW_CONFIRM;
+
+ /* cleanup */
+ return poselib_preview_exit(C, op);
+}
+
+void POSELIB_OT_browse_interactive (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "PoseLib Browse Poses";
+ ot->idname= "POSELIB_OT_browse_interactive";
+ ot->description= "Interactively browse poses in 3D-View";
+
+ /* api callbacks */
+ ot->invoke= poselib_preview_invoke;
+ ot->modal= poselib_preview_modal;
+ ot->cancel= poselib_preview_cancel;
+ ot->exec= poselib_preview_exec;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "pose_index", -1, -2, INT_MAX, "Pose", "Index of the pose to apply (-2 for no change to pose, -1 for poselib active pose)", 0, INT_MAX);
+}
diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c
new file mode 100644
index 00000000000..3d8d446c579
--- /dev/null
+++ b/source/blender/editors/armature/poseobject.c
@@ -0,0 +1,1707 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Ton Roosendaal, Blender Foundation '05, full recode.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * support for animation modes - Reevan McKay
+ */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_blender.h"
+#include "BKE_context.h"
+#include "BKE_constraint.h"
+#include "BKE_deform.h"
+#include "BKE_depsgraph.h"
+#include "BKE_displist.h"
+#include "BKE_fcurve.h"
+#include "BKE_global.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_transform.h" /* for autokey TFM_TRANSLATION, etc */
+#include "BIF_gl.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_armature.h"
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_object.h"
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "armature_intern.h"
+
+/* ************* XXX *************** */
+static int movetolayer_short_buts() {return 1;}
+static int okee() {return 0;}
+static int pupmenu() {return 0;}
+static void waitcursor() {};
+static void error() {};
+static void BIF_undo_push() {}
+static void countall() {}
+static void add_constraint() {}
+static void autokeyframe_pose_cb_func() {}
+/* ************* XXX *************** */
+
+/* This function is used to indicate that a bone is selected and needs keyframes inserted */
+void set_pose_keys (Object *ob)
+{
+ bArmature *arm= ob->data;
+ bPoseChannel *chan;
+
+ if (ob->pose){
+ for (chan=ob->pose->chanbase.first; chan; chan=chan->next){
+ Bone *bone= chan->bone;
+ if ((bone) && (bone->flag & BONE_SELECTED) && (arm->layer & bone->layer))
+ chan->flag |= POSE_KEY;
+ else
+ chan->flag &= ~POSE_KEY;
+ }
+ }
+}
+
+/* This function is used to process the necessary updates for */
+void ED_armature_enter_posemode(bContext *C, Base *base)
+{
+ Object *ob= base->object;
+
+ if (ob->id.lib){
+ error ("Can't pose libdata");
+ return;
+ }
+
+ switch (ob->type){
+ case OB_ARMATURE:
+
+ ob->flag |= OB_POSEMODE;
+ base->flag= ob->flag;
+
+ WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_POSE, NULL);
+
+ break;
+ default:
+ return;
+ }
+ ED_view3d_exit_paint_modes(C);
+}
+
+void ED_armature_exit_posemode(bContext *C, Base *base)
+{
+ if(base) {
+ Object *ob= base->object;
+
+ ob->flag &= ~OB_POSEMODE;
+ base->flag= ob->flag;
+
+ WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
+ }
+}
+
+/* if a selected or active bone is protected, throw error (oonly if warn==1) and return 1 */
+/* only_selected==1 : the active bone is allowed to be protected */
+static short pose_has_protected_selected(Object *ob, short only_selected, short warn)
+{
+ /* check protection */
+ if (ob->proxy) {
+ bPoseChannel *pchan;
+ bArmature *arm= ob->data;
+
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (pchan->bone && (pchan->bone->layer & arm->layer)) {
+ if (pchan->bone->layer & arm->layer_protected) {
+ if (only_selected && (pchan->bone->flag & BONE_ACTIVE));
+ else if (pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED))
+ break;
+ }
+ }
+ }
+ if (pchan) {
+ if (warn) error("Cannot change Proxy protected bones");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* only for real IK, not for auto-IK */
+int ED_pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan)
+{
+ bConstraint *con;
+ Bone *bone;
+
+ /* No need to check if constraint is active (has influence),
+ * since all constraints with CONSTRAINT_IK_AUTO are active */
+ for(con= pchan->constraints.first; con; con= con->next) {
+ if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
+ bKinematicConstraint *data= con->data;
+ if((data->flag & CONSTRAINT_IK_AUTO)==0)
+ return 1;
+ }
+ }
+ for(bone= pchan->bone->childbase.first; bone; bone= bone->next) {
+ pchan= get_pose_channel(ob->pose, bone->name);
+ if(pchan && ED_pose_channel_in_IK_chain(ob, pchan))
+ return 1;
+ }
+ return 0;
+}
+
+/* ********************************************** */
+
+/* For the object with pose/action: create path curves for selected bones
+ * This recalculates the WHOLE path within the pchan->pathsf and pchan->pathef range
+ */
+void pose_calculate_path(bContext *C, Scene *scene, Object *ob)
+{
+ bArmature *arm;
+ bPoseChannel *pchan;
+ Base *base;
+ float *fp;
+ int cfra;
+ int sfra, efra;
+
+ if (ob==NULL || ob->pose==NULL)
+ return;
+ arm= ob->data;
+
+ /* version patch for older files here (do_versions patch too complicated) */
+ if ((arm->pathsf == 0) || (arm->pathef == 0)) {
+ arm->pathsf = SFRA;
+ arm->pathef = EFRA;
+ }
+ if (arm->pathsize == 0) {
+ arm->pathsize = 1;
+ }
+
+ /* set frame values */
+ cfra= CFRA;
+ sfra = arm->pathsf;
+ efra = arm->pathef;
+ if (efra <= sfra) {
+ error("Can't calculate paths when pathlen <= 0");
+ return;
+ }
+
+ waitcursor(1);
+
+ /* hack: for unsaved files, set OB_RECALC so that paths can get calculated */
+ if ((ob->recalc & OB_RECALC)==0) {
+ ob->recalc |= OB_RECALC;
+ ED_anim_object_flush_update(C, ob);
+ }
+ else
+ ED_anim_object_flush_update(C, ob);
+
+
+ /* malloc the path blocks */
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) {
+ if (arm->layer & pchan->bone->layer) {
+ pchan->pathlen= efra-sfra+1;
+ pchan->pathsf= sfra;
+ pchan->pathef= efra+1;
+ if (pchan->path)
+ MEM_freeN(pchan->path);
+ pchan->path= MEM_callocN(3*pchan->pathlen*sizeof(float), "pchan path");
+ }
+ }
+ }
+
+ for (CFRA=sfra; CFRA<=efra; CFRA++) {
+ /* do all updates */
+ for (base= FIRSTBASE; base; base= base->next) {
+ if (base->object->recalc) {
+ int temp= base->object->recalc;
+ object_handle_update(scene, base->object);
+ base->object->recalc= temp;
+ }
+ }
+
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) {
+ if (arm->layer & pchan->bone->layer) {
+ if (pchan->path) {
+ fp= pchan->path+3*(CFRA-sfra);
+
+ if (arm->pathflag & ARM_PATH_HEADS) {
+ VECCOPY(fp, pchan->pose_head);
+ }
+ else {
+ VECCOPY(fp, pchan->pose_tail);
+ }
+
+ Mat4MulVecfl(ob->obmat, fp);
+ }
+ }
+ }
+ }
+ }
+
+ waitcursor(0);
+
+ CFRA= cfra;
+}
+
+/* For the object with pose/action: update paths for those that have got them
+ * This should selectively update paths that exist...
+ */
+void pose_recalculate_paths(bContext *C, Scene *scene, Object *ob)
+{
+ bArmature *arm;
+ bPoseChannel *pchan;
+ Base *base;
+ float *fp;
+ int cfra;
+ int sfra, efra;
+
+ if (ob==NULL || ob->pose==NULL)
+ return;
+ arm= ob->data;
+
+ /* set frame values */
+ cfra = CFRA;
+ sfra = efra = cfra;
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
+ if (pchan->path) {
+ /* if the pathsf and pathef aren't initialised, abort! */
+ if (ELEM(0, pchan->pathsf, pchan->pathef))
+ return;
+
+ /* try to increase area to do (only as much as needed) */
+ sfra= MIN2(sfra, pchan->pathsf);
+ efra= MAX2(efra, pchan->pathef);
+ }
+ }
+ }
+ if (efra <= sfra) return;
+
+ waitcursor(1);
+
+ /* hack: for unsaved files, set OB_RECALC so that paths can get calculated */
+ if ((ob->recalc & OB_RECALC)==0) {
+ ob->recalc |= OB_RECALC;
+ ED_anim_object_flush_update(C, ob);
+ }
+ else
+ ED_anim_object_flush_update(C, ob);
+
+ for (CFRA=sfra; CFRA<=efra; CFRA++) {
+ /* do all updates */
+ for (base= FIRSTBASE; base; base= base->next) {
+ if (base->object->recalc) {
+ int temp= base->object->recalc;
+ object_handle_update(scene, base->object);
+ base->object->recalc= temp;
+ }
+ }
+
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
+ if (pchan->path) {
+ /* only update if:
+ * - in range of this pchan's existing path
+ * - ... insert evil filtering/optimising conditions here...
+ */
+ if (IN_RANGE(CFRA, pchan->pathsf, pchan->pathef)) {
+ fp= pchan->path+3*(CFRA-sfra);
+
+ if (arm->pathflag & ARM_PATH_HEADS) {
+ VECCOPY(fp, pchan->pose_head);
+ }
+ else {
+ VECCOPY(fp, pchan->pose_tail);
+ }
+
+ Mat4MulVecfl(ob->obmat, fp);
+ }
+ }
+ }
+ }
+ }
+
+ waitcursor(0);
+
+ CFRA= cfra;
+ ob->pose->flag &= ~POSE_RECALCPATHS;
+}
+
+/* for the object with pose/action: clear path curves for selected bones only */
+void pose_clear_paths(Object *ob)
+{
+ bPoseChannel *pchan;
+
+ if (ob==NULL || ob->pose==NULL)
+ return;
+
+ /* free the path blocks */
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) {
+ if (pchan->path) {
+ MEM_freeN(pchan->path);
+ pchan->path= NULL;
+ }
+ }
+ }
+
+}
+
+
+
+void pose_select_constraint_target(Scene *scene)
+{
+ Object *obedit= scene->obedit; // XXX context
+ Object *ob= OBACT;
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+ bConstraint *con;
+
+ /* paranoia checks */
+ if (!ob && !ob->pose) return;
+ if (ob==obedit || (ob->flag & OB_POSEMODE)==0) return;
+
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (arm->layer & pchan->bone->layer) {
+ if (pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) {
+ for (con= pchan->constraints.first; con; con= con->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ if ((ct->tar == ob) && (ct->subtarget[0])) {
+ bPoseChannel *pchanc= get_pose_channel(ob->pose, ct->subtarget);
+ if(pchanc)
+ pchanc->bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 1);
+ }
+ }
+ }
+ }
+ }
+
+ BIF_undo_push("Select constraint target");
+
+}
+
+/* ******************* select hierarchy operator ************* */
+
+static int pose_select_hierarchy_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_active_object(C);
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+ Bone *curbone, *pabone, *chbone;
+ int direction = RNA_enum_get(op->ptr, "direction");
+ int add_to_sel = RNA_boolean_get(op->ptr, "extend");
+
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ curbone= pchan->bone;
+
+ if (arm->layer & curbone->layer) {
+ if (curbone->flag & (BONE_ACTIVE)) {
+ if (direction == BONE_SELECT_PARENT) {
+
+ if (pchan->parent == NULL) continue;
+ else pabone= pchan->parent->bone;
+
+ if ((arm->layer & pabone->layer) && !(pabone->flag & BONE_HIDDEN_P)) {
+
+ if (!add_to_sel) curbone->flag &= ~BONE_SELECTED;
+ curbone->flag &= ~BONE_ACTIVE;
+ pabone->flag |= (BONE_ACTIVE|BONE_SELECTED);
+
+ // XXX notifiers need to be sent to other editors to update
+ break;
+ }
+ } else { // BONE_SELECT_CHILD
+
+ if (pchan->child == NULL) continue;
+ else chbone = pchan->child->bone;
+
+ if ((arm->layer & chbone->layer) && !(chbone->flag & BONE_HIDDEN_P)) {
+
+ if (!add_to_sel) curbone->flag &= ~BONE_SELECTED;
+ curbone->flag &= ~BONE_ACTIVE;
+ chbone->flag |= (BONE_ACTIVE|BONE_SELECTED);
+
+ // XXX notifiers need to be sent to other editors to update
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_select_hierarchy(wmOperatorType *ot)
+{
+ static EnumPropertyItem direction_items[]= {
+ {BONE_SELECT_PARENT, "PARENT", "Select Parent", ""},
+ {BONE_SELECT_CHILD, "CHILD", "Select Child", ""},
+ {0, NULL, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name= "Select Hierarchy";
+ ot->idname= "POSE_OT_select_hierarchy";
+
+ /* api callbacks */
+ ot->exec= pose_select_hierarchy_exec;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items,
+ BONE_SELECT_PARENT, "Direction", "");
+ RNA_def_boolean(ot->srna, "extend", 0, "Add to Selection", "");
+
+}
+
+
+void pose_add_IK(Scene *scene)
+{
+ Object *obedit= scene->obedit; // XXX context
+ Object *ob= OBACT;
+
+ /* paranoia checks */
+ if(!ob && !ob->pose) return;
+ if(ob==obedit || (ob->flag & OB_POSEMODE)==0) return;
+
+ add_constraint(1); /* 1 means only IK */
+}
+
+/* context: all selected channels */
+void pose_clear_IK(Scene *scene)
+{
+ Object *obedit= scene->obedit; // XXX context
+ Object *ob= OBACT;
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+ bConstraint *con;
+ bConstraint *next;
+
+ /* paranoia checks */
+ if(!ob && !ob->pose) return;
+ if(ob==obedit || (ob->flag & OB_POSEMODE)==0) return;
+
+ if(pose_has_protected_selected(ob, 0, 1))
+ return;
+
+ if(okee("Remove IK constraint(s)")==0) return;
+
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if(arm->layer & pchan->bone->layer) {
+ if(pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) {
+
+ for(con= pchan->constraints.first; con; con= next) {
+ next= con->next;
+ if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
+ BLI_remlink(&pchan->constraints, con);
+ free_constraint_data(con);
+ MEM_freeN(con);
+ }
+ }
+ pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
+ }
+ }
+ }
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA); // and all its relations
+
+ BIF_undo_push("Remove IK constraint(s)");
+}
+
+void pose_clear_constraints(Scene *scene)
+{
+ Object *obedit= scene->obedit; // XXX context
+ Object *ob= OBACT;
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+
+ /* paranoia checks */
+ if(!ob && !ob->pose) return;
+ if(ob==obedit || (ob->flag & OB_POSEMODE)==0) return;
+
+ if(pose_has_protected_selected(ob, 0, 1))
+ return;
+
+ if(okee("Remove Constraints")==0) return;
+
+ /* find active */
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if(arm->layer & pchan->bone->layer) {
+ if(pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) {
+ free_constraints(&pchan->constraints);
+ pchan->constflag= 0;
+ }
+ }
+ }
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA); // and all its relations
+
+ BIF_undo_push("Remove Constraint(s)");
+
+}
+
+
+void pose_copy_menu(Scene *scene)
+{
+ Object *obedit= scene->obedit; // XXX context
+ Object *ob= OBACT;
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan, *pchanact;
+ short nr=0;
+ int i=0;
+
+ /* paranoia checks */
+ if (ELEM(NULL, ob, ob->pose)) return;
+ if ((ob==obedit) || (ob->flag & OB_POSEMODE)==0) return;
+
+ /* find active */
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (pchan->bone->flag & BONE_ACTIVE)
+ break;
+ }
+
+ if (pchan==NULL) return;
+ pchanact= pchan;
+
+ /* if proxy-protected bones selected, some things (such as locks + displays) shouldn't be changable,
+ * but for constraints (just add local constraints)
+ */
+ if (pose_has_protected_selected(ob, 1, 0)) {
+ i= BLI_countlist(&(pchanact->constraints)); /* if there are 24 or less, allow for the user to select constraints */
+ if (i < 25)
+ nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|Constraints...%x5");
+ else
+ nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4");
+ }
+ else {
+ i= BLI_countlist(&(pchanact->constraints)); /* if there are 24 or less, allow for the user to select constraints */
+ if (i < 25)
+ nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|Constraints...%x5|%l|Transform Locks%x6|IK Limits%x7|Bone Shape%x8");
+ else
+ nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|%l|Transform Locks%x6|IK Limits%x7|Bone Shape%x8");
+ }
+
+ if (nr <= 0)
+ return;
+
+ if (nr != 5) {
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ( (arm->layer & pchan->bone->layer) &&
+ (pchan->bone->flag & BONE_SELECTED) &&
+ (pchan != pchanact) )
+ {
+ switch (nr) {
+ case 1: /* Local Location */
+ VECCOPY(pchan->loc, pchanact->loc);
+ break;
+ case 2: /* Local Rotation */
+ QUATCOPY(pchan->quat, pchanact->quat);
+ break;
+ case 3: /* Local Size */
+ VECCOPY(pchan->size, pchanact->size);
+ break;
+ case 4: /* All Constraints */
+ {
+ ListBase tmp_constraints = {NULL, NULL};
+
+ /* copy constraints to tmpbase and apply 'local' tags before
+ * appending to list of constraints for this channel
+ */
+ copy_constraints(&tmp_constraints, &pchanact->constraints);
+ if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) {
+ bConstraint *con;
+
+ /* add proxy-local tags */
+ for (con= tmp_constraints.first; con; con= con->next)
+ con->flag |= CONSTRAINT_PROXY_LOCAL;
+ }
+ addlisttolist(&pchan->constraints, &tmp_constraints);
+
+ /* update flags (need to add here, not just copy) */
+ pchan->constflag |= pchanact->constflag;
+
+ if (ob->pose)
+ ob->pose->flag |= POSE_RECALC;
+ }
+ break;
+ case 6: /* Transform Locks */
+ pchan->protectflag = pchanact->protectflag;
+ break;
+ case 7: /* IK (DOF) settings */
+ {
+ pchan->ikflag = pchanact->ikflag;
+ VECCOPY(pchan->limitmin, pchanact->limitmin);
+ VECCOPY(pchan->limitmax, pchanact->limitmax);
+ VECCOPY(pchan->stiffness, pchanact->stiffness);
+ pchan->ikstretch= pchanact->ikstretch;
+ }
+ break;
+ case 8: /* Custom Bone Shape */
+ pchan->custom = pchanact->custom;
+ break;
+ case 9: /* Visual Location */
+ armature_loc_pose_to_bone(pchan, pchanact->pose_mat[3], pchan->loc);
+ break;
+ case 10: /* Visual Rotation */
+ {
+ float delta_mat[4][4], quat[4];
+
+ armature_mat_pose_to_bone(pchan, pchanact->pose_mat, delta_mat);
+ Mat4ToQuat(delta_mat, quat);
+ QUATCOPY(pchan->quat, quat);
+ }
+ break;
+ case 11: /* Visual Size */
+ {
+ float delta_mat[4][4], size[4];
+
+ armature_mat_pose_to_bone(pchan, pchanact->pose_mat, delta_mat);
+ Mat4ToSize(delta_mat, size);
+ VECCOPY(pchan->size, size);
+ }
+ }
+ }
+ }
+ }
+ else { /* constraints, optional (note: max we can have is 24 constraints) */
+ bConstraint *con, *con_back;
+ int const_toggle[24];
+ ListBase const_copy = {NULL, NULL};
+
+ BLI_duplicatelist(&const_copy, &(pchanact->constraints));
+
+ /* build the puplist of constraints */
+ for (con = pchanact->constraints.first, i=0; con; con=con->next, i++){
+ const_toggle[i]= 1;
+// add_numbut(i, TOG|INT, con->name, 0, 0, &(const_toggle[i]), "");
+ }
+
+// if (!do_clever_numbuts("Select Constraints", i, REDRAW)) {
+// BLI_freelistN(&const_copy);
+// return;
+// }
+
+ /* now build a new listbase from the options selected */
+ for (i=0, con=const_copy.first; con; i++) {
+ /* if not selected, free/remove it from the list */
+ if (!const_toggle[i]) {
+ con_back= con->next;
+ BLI_freelinkN(&const_copy, con);
+ con= con_back;
+ }
+ else
+ con= con->next;
+ }
+
+ /* Copy the temo listbase to the selected posebones */
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ( (arm->layer & pchan->bone->layer) &&
+ (pchan->bone->flag & BONE_SELECTED) &&
+ (pchan!=pchanact) )
+ {
+ ListBase tmp_constraints = {NULL, NULL};
+
+ /* copy constraints to tmpbase and apply 'local' tags before
+ * appending to list of constraints for this channel
+ */
+ copy_constraints(&tmp_constraints, &const_copy);
+ if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) {
+ bConstraint *con;
+
+ /* add proxy-local tags */
+ for (con= tmp_constraints.first; con; con= con->next)
+ con->flag |= CONSTRAINT_PROXY_LOCAL;
+ }
+ addlisttolist(&pchan->constraints, &tmp_constraints);
+
+ /* update flags (need to add here, not just copy) */
+ pchan->constflag |= pchanact->constflag;
+ }
+ }
+ BLI_freelistN(&const_copy);
+ update_pose_constraint_flags(ob->pose); /* we could work out the flags but its simpler to do this */
+
+ if (ob->pose)
+ ob->pose->flag |= POSE_RECALC;
+ }
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA); // and all its relations
+
+ BIF_undo_push("Copy Pose Attributes");
+
+}
+
+/* ******************** copy/paste pose ********************** */
+
+static bPose *g_posebuf=NULL;
+
+void free_posebuf(void)
+{
+ if (g_posebuf) {
+ // was copied without constraints
+ BLI_freelistN (&g_posebuf->chanbase);
+ MEM_freeN (g_posebuf);
+ }
+ g_posebuf=NULL;
+}
+
+void copy_posebuf (Scene *scene)
+{
+ Object *ob= OBACT;
+
+ if (!ob || !ob->pose){
+ error ("No Pose");
+ return;
+ }
+
+ free_posebuf();
+
+ set_pose_keys(ob); // sets chan->flag to POSE_KEY if bone selected
+ copy_pose(&g_posebuf, ob->pose, 0);
+
+}
+
+void paste_posebuf (Scene *scene, int flip)
+{
+ Object *ob= OBACT;
+ bPoseChannel *chan, *pchan;
+ float eul[4];
+ char name[32];
+
+ if (!ob || !ob->pose)
+ return;
+
+ if (!g_posebuf){
+ error ("Copy buffer is empty");
+ return;
+ }
+
+ /*
+ // disabled until protected bones in proxies follow the rules everywhere else!
+ if(pose_has_protected_selected(ob, 1, 1))
+ return;
+ */
+
+ /* Safely merge all of the channels in this pose into
+ any existing pose */
+ for (chan=g_posebuf->chanbase.first; chan; chan=chan->next) {
+ if (chan->flag & POSE_KEY) {
+ BLI_strncpy(name, chan->name, sizeof(name));
+ if (flip)
+ bone_flip_name (name, 0); // 0 = don't strip off number extensions
+
+ /* only copy when channel exists, poses are not meant to add random channels to anymore */
+ pchan= get_pose_channel(ob->pose, name);
+
+ if (pchan) {
+ /* only loc rot size */
+ /* only copies transform info for the pose */
+ VECCOPY(pchan->loc, chan->loc);
+ VECCOPY(pchan->size, chan->size);
+ QUATCOPY(pchan->quat, chan->quat);
+ pchan->flag= chan->flag;
+
+ if (flip) {
+ pchan->loc[0]*= -1;
+
+ QuatToEul(pchan->quat, eul);
+ eul[1]*= -1;
+ eul[2]*= -1;
+ EulToQuat(eul, pchan->quat);
+ }
+
+#if 0 // XXX old animation system
+ if (autokeyframe_cfra_can_key(ob)) {
+ ID *id= &ob->id;
+
+ /* Set keys on pose */
+ if (chan->flag & POSE_ROT) {
+ insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0);
+ }
+ if (chan->flag & POSE_SIZE) {
+ insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0);
+ }
+ if (chan->flag & POSE_LOC) {
+ insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0);
+ }
+
+ /* clear any unkeyed tags */
+ if (chan->bone)
+ chan->bone->flag &= ~BONE_UNKEYED;
+ }
+ else {
+ /* add unkeyed tags */
+ if (chan->bone)
+ chan->bone->flag |= BONE_UNKEYED;
+ }
+#endif // XXX old animation system
+ }
+ }
+ }
+
+ /* Update event for pose and deformation children */
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+ if (IS_AUTOKEY_ON(scene)) {
+// XXX remake_action_ipos(ob->action);
+ }
+ else {
+ /* need to trick depgraph, action is not allowed to execute on pose */
+ where_is_pose(scene, ob);
+ ob->recalc= 0;
+ }
+
+ BIF_undo_push("Paste Action Pose");
+}
+
+/* ********************************************** */
+
+/* context weightpaint and deformer in posemode */
+void pose_adds_vgroups(Scene *scene, Object *meshobj, int heatweights)
+{
+// XXX extern VPaint Gwp; /* from vpaint */
+ Object *poseobj= modifiers_isDeformedByArmature(meshobj);
+
+ if(poseobj==NULL || (poseobj->flag & OB_POSEMODE)==0) {
+ error("The active object must have a deforming armature in pose mode");
+ return;
+ }
+
+// XXX add_verts_to_dgroups(meshobj, poseobj, heatweights, (Gwp.flag & VP_MIRROR_X));
+
+ if(heatweights)
+ BIF_undo_push("Apply Bone Heat Weights to Vertex Groups");
+ else
+ BIF_undo_push("Apply Bone Envelopes to Vertex Groups");
+
+
+ // and all its relations
+ DAG_object_flush_update(scene, meshobj, OB_RECALC_DATA);
+}
+
+/* ********************************************** */
+
+/* adds a new pose-group */
+void pose_add_posegroup (Scene *scene)
+{
+ Object *ob= OBACT;
+ bPose *pose= (ob) ? ob->pose : NULL;
+ bActionGroup *grp;
+
+ if (ELEM(NULL, ob, ob->pose))
+ return;
+
+ grp= MEM_callocN(sizeof(bActionGroup), "PoseGroup");
+ strcpy(grp->name, "Group");
+ BLI_addtail(&pose->agroups, grp);
+ BLI_uniquename(&pose->agroups, grp, "Group", '.', offsetof(bActionGroup, name), 32);
+
+ pose->active_group= BLI_countlist(&pose->agroups);
+
+ BIF_undo_push("Add Bone Group");
+
+}
+
+/* Remove the active bone-group */
+void pose_remove_posegroup (Scene *scene)
+{
+ Object *ob= OBACT;
+ bPose *pose= (ob) ? ob->pose : NULL;
+ bActionGroup *grp = NULL;
+ bPoseChannel *pchan;
+
+ /* sanity checks */
+ if (ELEM(NULL, ob, pose))
+ return;
+ if (pose->active_group <= 0)
+ return;
+
+ /* get group to remove */
+ grp= BLI_findlink(&pose->agroups, pose->active_group-1);
+ if (grp) {
+ /* adjust group references (the trouble of using indices!):
+ * - firstly, make sure nothing references it
+ * - also, make sure that those after this item get corrected
+ */
+ for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (pchan->agrp_index == pose->active_group)
+ pchan->agrp_index= 0;
+ else if (pchan->agrp_index > pose->active_group)
+ pchan->agrp_index--;
+ }
+
+ /* now, remove it from the pose */
+ BLI_freelinkN(&pose->agroups, grp);
+ pose->active_group= 0;
+
+ BIF_undo_push("Remove Bone Group");
+ }
+
+}
+
+char *build_posegroups_menustr (bPose *pose, short for_pupmenu)
+{
+ DynStr *pupds= BLI_dynstr_new();
+ bActionGroup *grp;
+ char *str;
+ char buf[16];
+ int i;
+
+ /* add title first (and the "none" entry) */
+ BLI_dynstr_append(pupds, "Bone Group%t|");
+ if (for_pupmenu)
+ BLI_dynstr_append(pupds, "Add New%x0|");
+ else
+ BLI_dynstr_append(pupds, "BG: [None]%x0|");
+
+ /* loop through groups, adding them */
+ for (grp= pose->agroups.first, i=1; grp; grp=grp->next, i++) {
+ if (for_pupmenu == 0)
+ BLI_dynstr_append(pupds, "BG: ");
+ BLI_dynstr_append(pupds, grp->name);
+
+ sprintf(buf, "%%x%d", i);
+ BLI_dynstr_append(pupds, buf);
+
+ if (grp->next)
+ BLI_dynstr_append(pupds, "|");
+ }
+
+ /* convert to normal MEM_malloc'd string */
+ str= BLI_dynstr_get_cstring(pupds);
+ BLI_dynstr_free(pupds);
+
+ return str;
+}
+
+/* Assign selected pchans to the bone group that the user selects */
+void pose_assign_to_posegroup (Scene *scene, short active)
+{
+ Object *ob= OBACT;
+ bArmature *arm= (ob) ? ob->data : NULL;
+ bPose *pose= (ob) ? ob->pose : NULL;
+ bPoseChannel *pchan;
+ char *menustr;
+ int nr;
+ short done= 0;
+
+ /* sanity checks */
+ if (ELEM3(NULL, ob, pose, arm))
+ return;
+
+ /* get group to affect */
+ if ((active==0) || (pose->active_group <= 0)) {
+ menustr= build_posegroups_menustr(pose, 1);
+ nr= 0; // XXX pupmenu_col(menustr, 20);
+ MEM_freeN(menustr);
+
+ if (nr < 0)
+ return;
+ else if (nr == 0) {
+ /* add new - note: this does an undo push and sets active group */
+ pose_add_posegroup(scene);
+ }
+ else
+ pose->active_group= nr;
+ }
+
+ /* add selected bones to group then */
+ for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ((pchan->bone->flag & BONE_SELECTED) && (pchan->bone->layer & arm->layer)) {
+ pchan->agrp_index= pose->active_group;
+ done= 1;
+ }
+ }
+
+ if (done)
+ BIF_undo_push("Add Bones To Group");
+
+}
+
+/* Remove selected pchans from their bone groups */
+void pose_remove_from_posegroups (Scene *scene)
+{
+ Object *ob= OBACT;
+ bArmature *arm= (ob) ? ob->data : NULL;
+ bPose *pose= (ob) ? ob->pose : NULL;
+ bPoseChannel *pchan;
+ short done= 0;
+
+ /* sanity checks */
+ if (ELEM3(NULL, ob, pose, arm))
+ return;
+
+ /* remove selected bones from their groups */
+ for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ((pchan->bone->flag & BONE_SELECTED) && (pchan->bone->layer & arm->layer)) {
+ if (pchan->agrp_index) {
+ pchan->agrp_index= 0;
+ done= 1;
+ }
+ }
+ }
+
+ if (done)
+ BIF_undo_push("Remove Bones From Groups");
+
+}
+
+/* Ctrl-G in 3D-View while in PoseMode */
+void pgroup_operation_with_menu (Scene *scene)
+{
+ Object *ob= OBACT;
+ bArmature *arm= (ob) ? ob->data : NULL;
+ bPose *pose= (ob) ? ob->pose : NULL;
+ bPoseChannel *pchan= NULL;
+ int mode;
+
+ /* sanity checks */
+ if (ELEM3(NULL, ob, pose, arm))
+ return;
+
+ /* check that something is selected */
+ for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ((pchan->bone->flag & BONE_SELECTED) && (pchan->bone->layer & arm->layer))
+ break;
+ }
+ if (pchan == NULL)
+ return;
+
+ /* get mode of action */
+ if (pchan)
+ mode= pupmenu("Bone Groups%t|Add Selected to Active Group%x1|Add Selected to Group%x2|%|Remove Selected From Groups%x3|Remove Active Group%x4");
+ else
+ mode= pupmenu("Bone Groups%t|Add New Group%x5|Remove Active Group%x4");
+
+ /* handle mode */
+ switch (mode) {
+ case 1:
+ pose_assign_to_posegroup(scene, 1);
+ break;
+ case 2:
+ pose_assign_to_posegroup(scene, 0);
+ break;
+ case 5:
+ pose_add_posegroup(scene);
+ break;
+ case 3:
+ pose_remove_from_posegroups(scene);
+ break;
+ case 4:
+ pose_remove_posegroup(scene);
+ break;
+ }
+}
+
+/* ********************************************** */
+
+static short pose_select_same_group (Object *ob)
+{
+ bPose *pose= (ob)? ob->pose : NULL;
+ bArmature *arm= (ob)? ob->data : NULL;
+ bPoseChannel *pchan, *chan;
+ short changed= 0;
+
+ if (ELEM3(NULL, ob, pose, arm))
+ return 0;
+
+ /* loop in loop... bad and slow! */
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (arm->layer & pchan->bone->layer) {
+ if (pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) {
+
+ /* only if group matches (and is not selected or current bone) */
+ for (chan= ob->pose->chanbase.first; chan; chan= chan->next) {
+ if (arm->layer & chan->bone->layer) {
+ if (pchan->agrp_index == chan->agrp_index) {
+ chan->bone->flag |= BONE_SELECTED;
+ changed= 1;
+ }
+ }
+ }
+
+ }
+ }
+ }
+
+ return changed;
+}
+
+static short pose_select_same_layer (Object *ob)
+{
+ bPose *pose= (ob)? ob->pose : NULL;
+ bArmature *arm= (ob)? ob->data : NULL;
+ bPoseChannel *pchan;
+ short layers= 0, changed= 0;
+
+ if (ELEM3(NULL, ob, pose, arm))
+ return 0;
+
+ /* figure out what bones are selected */
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (arm->layer & pchan->bone->layer) {
+ if (pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) {
+ layers |= pchan->bone->layer;
+ }
+ }
+ }
+ if (layers == 0)
+ return 0;
+
+ /* select bones that are on same layers as layers flag */
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (arm->layer & pchan->bone->layer) {
+ if (layers & pchan->bone->layer) {
+ pchan->bone->flag |= BONE_SELECTED;
+ changed= 1;
+ }
+ }
+ }
+
+ return changed;
+}
+
+void pose_select_grouped (Scene *scene, short nr)
+{
+ short changed = 0;
+
+ if (nr == 1) changed= pose_select_same_group(OBACT);
+ else if (nr == 2) changed= pose_select_same_layer(OBACT);
+
+ if (changed) {
+ countall();
+ BIF_undo_push("Select Grouped");
+ }
+}
+
+/* Shift-G in 3D-View while in PoseMode */
+void pose_select_grouped_menu (Scene *scene)
+{
+ short nr;
+
+ /* here we go */
+ nr= pupmenu("Select Grouped%t|In Same Group%x1|In Same Layer%x2");
+ pose_select_grouped(scene, nr);
+}
+
+/* ********************************************** */
+
+/* context active object */
+void pose_flip_names(Scene *scene)
+{
+ Object *obedit= scene->obedit; // XXX context
+ Object *ob= OBACT;
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+ char newname[32];
+
+ /* paranoia checks */
+ if(!ob && !ob->pose) return;
+ if(ob==obedit || (ob->flag & OB_POSEMODE)==0) return;
+
+ if(pose_has_protected_selected(ob, 0, 1))
+ return;
+
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if(arm->layer & pchan->bone->layer) {
+ if(pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) {
+ BLI_strncpy(newname, pchan->name, sizeof(newname));
+ bone_flip_name(newname, 1); // 1 = do strip off number extensions
+ armature_bone_rename(ob, pchan->name, newname);
+ }
+ }
+ }
+
+ BIF_undo_push("Flip names");
+}
+
+/* context active object */
+void pose_autoside_names(Scene *scene, short axis)
+{
+ Object *obedit= scene->obedit; // XXX context
+ Object *ob= OBACT;
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+ char newname[32];
+
+ /* paranoia checks */
+ if (ELEM(NULL, ob, ob->pose)) return;
+ if (ob==obedit || (ob->flag & OB_POSEMODE)==0) return;
+
+ if (pose_has_protected_selected(ob, 0, 1))
+ return;
+
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if(arm->layer & pchan->bone->layer) {
+ if(pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) {
+ BLI_strncpy(newname, pchan->name, sizeof(newname));
+ bone_autoside_name(newname, 1, axis, pchan->bone->head[axis], pchan->bone->tail[axis]);
+ armature_bone_rename(ob, pchan->name, newname);
+ }
+ }
+ }
+
+ BIF_undo_push("Flip names");
+}
+
+/* context active object, or weightpainted object with armature in posemode */
+void pose_activate_flipped_bone(Scene *scene)
+{
+ Object *ob= OBACT;
+ bArmature *arm= ob->data;
+
+ if(ob==NULL) return;
+
+ if(G.f & G_WEIGHTPAINT) {
+ ob= modifiers_isDeformedByArmature(ob);
+ }
+ if(ob && (ob->flag & OB_POSEMODE)) {
+ bPoseChannel *pchan, *pchanf;
+
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if(arm->layer & pchan->bone->layer) {
+ if(pchan->bone->flag & BONE_ACTIVE)
+ break;
+ }
+ }
+ if(pchan) {
+ char name[32];
+
+ BLI_strncpy(name, pchan->name, 32);
+ bone_flip_name(name, 1); // 0 = do not strip off number extensions
+
+ pchanf= get_pose_channel(ob->pose, name);
+ if(pchanf && pchanf!=pchan) {
+ pchan->bone->flag &= ~(BONE_SELECTED|BONE_ACTIVE);
+ pchanf->bone->flag |= (BONE_SELECTED|BONE_ACTIVE);
+
+ /* in weightpaint we select the associated vertex group too */
+ if(G.f & G_WEIGHTPAINT) {
+ vertexgroup_select_by_name(OBACT, name);
+ DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA);
+ }
+
+ // XXX notifiers need to be sent to other editors to update
+
+ }
+ }
+ }
+}
+
+/* This function pops up the move-to-layer popup widgets when the user
+ * presses either SHIFT-MKEY or MKEY in PoseMode OR EditMode (for Armatures)
+ */
+void pose_movetolayer(Scene *scene)
+{
+ Object *obedit= scene->obedit; // XXX context
+ Object *ob= OBACT;
+ bArmature *arm;
+ short lay= 0;
+ short shift= 0; // XXX
+
+ if (ob==NULL) return;
+ arm= ob->data;
+
+ if (shift) {
+ /* armature layers */
+ lay= arm->layer;
+ if ( movetolayer_short_buts(&lay, "Armature Layers")==0 ) return;
+ if (lay==0) return;
+ arm->layer= lay;
+ if(ob->pose)
+ ob->pose->proxy_layer= lay;
+
+ }
+ else if (obedit) {
+ /* the check for editbone layer moving needs to occur before posemode one to work */
+ EditBone *ebo;
+ EditBone *flipBone;
+
+ for (ebo= arm->edbo->first; ebo; ebo= ebo->next) {
+ if (arm->layer & ebo->layer) {
+ if (ebo->flag & BONE_SELECTED)
+ lay |= ebo->layer;
+ }
+ }
+ if (lay==0) return;
+
+ if ( movetolayer_short_buts(&lay, "Bone Layers")==0 ) return;
+ if (lay==0) return;
+
+ for (ebo= arm->edbo->first; ebo; ebo= ebo->next) {
+ if (arm->layer & ebo->layer) {
+ if (ebo->flag & BONE_SELECTED) {
+ ebo->layer= lay;
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ flipBone = ED_armature_bone_get_mirrored(arm->edbo, ebo);
+ if (flipBone)
+ flipBone->layer = lay;
+ }
+ }
+ }
+ }
+
+ BIF_undo_push("Move Bone Layer");
+ }
+ else if (ob->flag & OB_POSEMODE) {
+ /* pose-channel layers */
+ bPoseChannel *pchan;
+
+ if (pose_has_protected_selected(ob, 0, 1))
+ return;
+
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (arm->layer & pchan->bone->layer) {
+ if (pchan->bone->flag & BONE_SELECTED)
+ lay |= pchan->bone->layer;
+ }
+ }
+ if (lay==0) return;
+
+ if ( movetolayer_short_buts(&lay, "Bone Layers")==0 ) return;
+ if (lay==0) return;
+
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (arm->layer & pchan->bone->layer) {
+ if (pchan->bone->flag & BONE_SELECTED)
+ pchan->bone->layer= lay;
+ }
+ }
+
+ BIF_undo_push("Move Bone Layer");
+ }
+}
+
+#if 0
+// XXX old sys
+/* for use with pose_relax only */
+static int pose_relax_icu(struct IpoCurve *icu, float framef, float *val, float *frame_prev, float *frame_next)
+{
+ if (!icu) {
+ return 0;
+ }
+ else {
+ BezTriple *bezt = icu->bezt;
+
+ BezTriple *bezt_prev=NULL, *bezt_next=NULL;
+ float w1, w2, wtot;
+ int i;
+
+ for (i=0; i < icu->totvert; i++, bezt++) {
+ if (bezt->vec[1][0] < framef - 0.5) {
+ bezt_prev = bezt;
+ } else {
+ break;
+ }
+ }
+
+ if (bezt_prev==NULL) return 0;
+
+ /* advance to the next, dont need to advance i */
+ bezt = bezt_prev+1;
+
+ for (; i < icu->totvert; i++, bezt++) {
+ if (bezt->vec[1][0] > framef + 0.5) {
+ bezt_next = bezt;
+ break;
+ }
+ }
+
+ if (bezt_next==NULL) return 0;
+
+ if (val) {
+ w1 = framef - bezt_prev->vec[1][0];
+ w2 = bezt_next->vec[1][0] - framef;
+ wtot = w1 + w2;
+ w1=w1/wtot;
+ w2=w2/wtot;
+#if 0
+ val = (bezt_prev->vec[1][1] * w2) + (bezt_next->vec[1][1] * w1);
+#else
+ /* apply the value with a hard coded 6th */
+ *val = (((bezt_prev->vec[1][1] * w2) + (bezt_next->vec[1][1] * w1)) + (*val * 5.0f)) / 6.0f;
+#endif
+ }
+
+ if (frame_prev) *frame_prev = bezt_prev->vec[1][0];
+ if (frame_next) *frame_next = bezt_next->vec[1][0];
+
+ return 1;
+ }
+}
+#endif
+
+void pose_relax(Scene *scene)
+{
+ Object *ob = OBACT;
+ bPose *pose;
+ bAction *act;
+ bArmature *arm;
+
+// IpoCurve *icu_w, *icu_x, *icu_y, *icu_z;
+
+ bPoseChannel *pchan;
+// bActionChannel *achan;
+// float framef = F_CFRA;
+// float frame_prev, frame_next;
+// float quat_prev[4], quat_next[4], quat_interp[4], quat_orig[4];
+
+ int do_scale = 0;
+ int do_loc = 0;
+ int do_quat = 0;
+ int flag = 0;
+// int do_x, do_y, do_z;
+
+ if (!ob) return;
+
+ pose = ob->pose;
+ act = ob->action;
+ arm = (bArmature *)ob->data;
+
+ if (!pose || !act || !arm) return;
+
+ for (pchan=pose->chanbase.first; pchan; pchan= pchan->next) {
+
+ pchan->bone->flag &= ~BONE_TRANSFORM;
+
+ if (pchan->bone->layer & arm->layer) {
+ if (pchan->bone->flag & BONE_SELECTED) {
+ /* do we have an ipo curve? */
+#if 0 // XXX old animation system
+ achan= get_action_channel(act, pchan->name);
+
+ if (achan && achan->ipo) {
+ /*calc_ipo(achan->ipo, ctime);*/
+
+ do_x = pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_X), framef, &pchan->loc[0], NULL, NULL);
+ do_y = pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_Y), framef, &pchan->loc[1], NULL, NULL);
+ do_z = pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_Z), framef, &pchan->loc[2], NULL, NULL);
+ do_loc += do_x + do_y + do_z;
+
+ do_x = pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_X), framef, &pchan->size[0], NULL, NULL);
+ do_y = pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_Y), framef, &pchan->size[1], NULL, NULL);
+ do_z = pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_Z), framef, &pchan->size[2], NULL, NULL);
+ do_scale += do_x + do_y + do_z;
+
+ if( ((icu_w = find_ipocurve(achan->ipo, AC_QUAT_W))) &&
+ ((icu_x = find_ipocurve(achan->ipo, AC_QUAT_X))) &&
+ ((icu_y = find_ipocurve(achan->ipo, AC_QUAT_Y))) &&
+ ((icu_z = find_ipocurve(achan->ipo, AC_QUAT_Z))) )
+ {
+ /* use the quatw keyframe as a basis for others */
+ if (pose_relax_icu(icu_w, framef, NULL, &frame_prev, &frame_next)) {
+ /* get 2 quats */
+ quat_prev[0] = eval_icu(icu_w, frame_prev);
+ quat_prev[1] = eval_icu(icu_x, frame_prev);
+ quat_prev[2] = eval_icu(icu_y, frame_prev);
+ quat_prev[3] = eval_icu(icu_z, frame_prev);
+
+ quat_next[0] = eval_icu(icu_w, frame_next);
+ quat_next[1] = eval_icu(icu_x, frame_next);
+ quat_next[2] = eval_icu(icu_y, frame_next);
+ quat_next[3] = eval_icu(icu_z, frame_next);
+
+#if 0
+ /* apply the setting, completely smooth */
+ QuatInterpol(pchan->quat, quat_prev, quat_next, (framef-frame_prev) / (frame_next-frame_prev) );
+#else
+ /* tricky interpolation */
+ QuatInterpol(quat_interp, quat_prev, quat_next, (framef-frame_prev) / (frame_next-frame_prev) );
+ QUATCOPY(quat_orig, pchan->quat);
+ QuatInterpol(pchan->quat, quat_orig, quat_interp, 1.0f/6.0f);
+ /* done */
+#endif
+ do_quat++;
+ }
+ }
+
+ /* apply BONE_TRANSFORM tag so that autokeying will pick it up */
+ pchan->bone->flag |= BONE_TRANSFORM;
+ }
+
+#endif // XXX old animation system
+ }
+ }
+ }
+
+ ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
+
+ /* do auto-keying */
+ if (do_loc) flag |= TFM_TRANSLATION;
+ if (do_scale) flag |= TFM_RESIZE;
+ if (do_quat) flag |= TFM_ROTATION;
+ autokeyframe_pose_cb_func(ob, flag, 0);
+
+ /* clear BONE_TRANSFORM flags */
+ for (pchan=pose->chanbase.first; pchan; pchan= pchan->next)
+ pchan->bone->flag &= ~ BONE_TRANSFORM;
+
+ /* do depsgraph flush */
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ BIF_undo_push("Relax Pose");
+}
+
+/* for use in insertkey, ensure rotation goes other way around */
+void pose_flipquats(Scene *scene)
+{
+ Object *ob = OBACT;
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+
+ if(ob->pose==NULL)
+ return;
+
+ /* find sel bones */
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if(pchan->bone && (pchan->bone->flag & BONE_SELECTED) && (pchan->bone->layer & arm->layer)) {
+ /* quaternions have 720 degree range */
+ pchan->quat[0]= -pchan->quat[0];
+ pchan->quat[1]= -pchan->quat[1];
+ pchan->quat[2]= -pchan->quat[2];
+ pchan->quat[3]= -pchan->quat[3];
+ }
+ }
+
+ /* do autokey */
+ autokeyframe_pose_cb_func(ob, TFM_ROTATION, 0);
+}
+
+/* context: active channel */
+void pose_special_editmenu(Scene *scene)
+{
+#if 0
+ Object *obedit= scene->obedit; // XXX context
+ Object *ob= OBACT;
+ short nr;
+
+ /* paranoia checks */
+ if(!ob && !ob->pose) return;
+ if(ob==obedit || (ob->flag & OB_POSEMODE)==0) return;
+
+ nr= pupmenu("Specials%t|Select Constraint Target%x1|Flip Left-Right Names%x2|Calculate Paths%x3|Clear Paths%x4|Clear User Transform %x5|Relax Pose %x6|%l|AutoName Left-Right%x7|AutoName Front-Back%x8|AutoName Top-Bottom%x9");
+ if(nr==1) {
+ pose_select_constraint_target(scene);
+ }
+ else if(nr==2) {
+ pose_flip_names();
+ }
+ else if(nr==3) {
+ pose_calculate_path(C, ob);
+ }
+ else if(nr==4) {
+ pose_clear_paths(ob);
+ }
+ else if(nr==5) {
+ pose_clear_user_transforms(scene, ob);
+ }
+ else if(nr==6) {
+ pose_relax();
+ }
+ else if(ELEM3(nr, 7, 8, 9)) {
+ pose_autoside_names(nr-7);
+ }
+#endif
+}
+
+/* Restore selected pose-bones to 'action'-defined pose */
+void pose_clear_user_transforms(Scene *scene, Object *ob)
+{
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+
+ if (ob->pose == NULL)
+ return;
+
+ /* find selected bones */
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (pchan->bone && (pchan->bone->flag & BONE_SELECTED) && (pchan->bone->layer & arm->layer)) {
+ /* just clear the BONE_UNKEYED flag, allowing this bone to get overwritten by actions again */
+ pchan->bone->flag &= ~BONE_UNKEYED;
+ }
+ }
+
+ /* clear pose locking flag
+ * - this will only clear the user-defined pose in the selected bones, where BONE_UNKEYED has been cleared
+ */
+ ob->pose->flag |= POSE_DO_UNLOCK;
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ BIF_undo_push("Clear User Transform");
+}
+
diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c
new file mode 100644
index 00000000000..5a636672f29
--- /dev/null
+++ b/source/blender/editors/armature/reeb.c
@@ -0,0 +1,3725 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Martin Poirier
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <string.h> // for memcpy
+#include <stdio.h>
+#include <stdlib.h> // for qsort
+#include <float.h>
+
+#include "PIL_time.h"
+
+#include "DNA_listBase.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_object_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_armature_types.h"
+
+#include "BKE_context.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_edgehash.h"
+#include "BLI_ghash.h"
+#include "BLI_heap.h"
+
+//#include "BDR_editobject.h"
+
+#include "BMF_Api.h"
+
+#include "ED_mesh.h"
+#include "ED_armature.h"
+//#include "BIF_interface.h"
+//#include "BIF_toolbox.h"
+//#include "BIF_graphics.h"
+#include "BIF_gl.h"
+#include "UI_resources.h"
+
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+#include "BKE_customdata.h"
+
+//#include "blendef.h"
+
+#include "ONL_opennl.h"
+
+#include "reeb.h"
+
+
+ReebGraph *GLOBAL_RG = NULL;
+ReebGraph *FILTERED_RG = NULL;
+
+/*
+ * Skeleton generation algorithm based on:
+ * "Harmonic Skeleton for Realistic Character Animation"
+ * Gregoire Aujay, Franck Hetroy, Francis Lazarus and Christine Depraz
+ * SIGGRAPH 2007
+ *
+ * Reeb graph generation algorithm based on:
+ * "Robust On-line Computation of Reeb Graphs: Simplicity and Speed"
+ * Valerio Pascucci, Giorgio Scorzelli, Peer-Timo Bremer and Ajith Mascarenhas
+ * SIGGRAPH 2007
+ *
+ * */
+
+#define DEBUG_REEB
+#define DEBUG_REEB_NODE
+
+typedef struct VertexData
+{
+ float w; /* weight */
+ int i; /* index */
+ ReebNode *n;
+} VertexData;
+
+typedef struct EdgeIndex
+{
+ EditEdge **edges;
+ int *offset;
+} EdgeIndex;
+
+typedef enum {
+ MERGE_LOWER,
+ MERGE_HIGHER,
+ MERGE_APPEND
+} MergeDirection;
+
+int mergeArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1);
+void mergeArcEdges(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc, MergeDirection direction);
+int mergeConnectedArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1);
+EditEdge * NextEdgeForVert(EdgeIndex *indexed_edges, int index);
+void mergeArcFaces(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc);
+void addFacetoArc(ReebArc *arc, EditFace *efa);
+
+void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count);
+void REEB_AxialSymmetry(BNode* root_node, BNode* node1, BNode* node2, struct BArc* barc1, BArc* barc2);
+
+void flipArcBuckets(ReebArc *arc);
+
+
+/***************************************** UTILS **********************************************/
+
+VertexData *allocVertexData(EditMesh *em)
+{
+ VertexData *data;
+ EditVert *eve;
+ int totvert, index;
+
+ totvert = BLI_countlist(&em->verts);
+
+ data = MEM_callocN(sizeof(VertexData) * totvert, "VertexData");
+
+ for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next)
+ {
+ data[index].i = index;
+ data[index].w = 0;
+ eve->tmp.p = data + index;
+ }
+
+ return data;
+}
+
+int indexData(EditVert *eve)
+{
+ return ((VertexData*)eve->tmp.p)->i;
+}
+
+float weightData(EditVert *eve)
+{
+ return ((VertexData*)eve->tmp.p)->w;
+}
+
+void weightSetData(EditVert *eve, float w)
+{
+ ((VertexData*)eve->tmp.p)->w = w;
+}
+
+ReebNode* nodeData(EditVert *eve)
+{
+ return ((VertexData*)eve->tmp.p)->n;
+}
+
+void nodeSetData(EditVert *eve, ReebNode *n)
+{
+ ((VertexData*)eve->tmp.p)->n = n;
+}
+
+void REEB_freeArc(BArc *barc)
+{
+ ReebArc *arc = (ReebArc*)barc;
+ BLI_freelistN(&arc->edges);
+
+ if (arc->buckets)
+ MEM_freeN(arc->buckets);
+
+ if (arc->faces)
+ BLI_ghash_free(arc->faces, NULL, NULL);
+
+ MEM_freeN(arc);
+}
+
+void REEB_freeGraph(ReebGraph *rg)
+{
+ ReebArc *arc;
+ ReebNode *node;
+
+ // free nodes
+ for( node = rg->nodes.first; node; node = node->next )
+ {
+ BLI_freeNode((BGraph*)rg, (BNode*)node);
+ }
+ BLI_freelistN(&rg->nodes);
+
+ // free arcs
+ arc = rg->arcs.first;
+ while( arc )
+ {
+ ReebArc *next = arc->next;
+ REEB_freeArc((BArc*)arc);
+ arc = next;
+ }
+
+ // free edge map
+ BLI_edgehash_free(rg->emap, NULL);
+
+ /* free linked graph */
+ if (rg->link_up)
+ {
+ REEB_freeGraph(rg->link_up);
+ }
+
+ MEM_freeN(rg);
+}
+
+ReebGraph * newReebGraph()
+{
+ ReebGraph *rg;
+ rg = MEM_callocN(sizeof(ReebGraph), "reeb graph");
+
+ rg->totnodes = 0;
+ rg->emap = BLI_edgehash_new();
+
+
+ rg->free_arc = REEB_freeArc;
+ rg->free_node = NULL;
+ rg->radial_symmetry = REEB_RadialSymmetry;
+ rg->axial_symmetry = REEB_AxialSymmetry;
+
+ return rg;
+}
+
+void BIF_flagMultiArcs(ReebGraph *rg, int flag)
+{
+ for ( ; rg; rg = rg->link_up)
+ {
+ BLI_flagArcs((BGraph*)rg, flag);
+ }
+}
+
+ReebNode * addNode(ReebGraph *rg, EditVert *eve)
+{
+ float weight;
+ ReebNode *node = NULL;
+
+ weight = weightData(eve);
+
+ node = MEM_callocN(sizeof(ReebNode), "reeb node");
+
+ node->flag = 0; // clear flag on init
+ node->symmetry_level = 0;
+ node->arcs = NULL;
+ node->degree = 0;
+ node->weight = weight;
+ node->index = rg->totnodes;
+ VECCOPY(node->p, eve->co);
+
+ BLI_addtail(&rg->nodes, node);
+ rg->totnodes++;
+
+ nodeSetData(eve, node);
+
+ return node;
+}
+
+ReebNode * copyNode(ReebGraph *rg, ReebNode *node)
+{
+ ReebNode *cp_node = NULL;
+
+ cp_node = MEM_callocN(sizeof(ReebNode), "reeb node copy");
+
+ memcpy(cp_node, node, sizeof(ReebNode));
+
+ cp_node->prev = NULL;
+ cp_node->next = NULL;
+ cp_node->arcs = NULL;
+
+ cp_node->link_up = NULL;
+ cp_node->link_down = NULL;
+
+ BLI_addtail(&rg->nodes, cp_node);
+ rg->totnodes++;
+
+ return cp_node;
+}
+
+void relinkNodes(ReebGraph *low_rg, ReebGraph *high_rg)
+{
+ ReebNode *low_node, *high_node;
+
+ if (low_rg == NULL || high_rg == NULL)
+ {
+ return;
+ }
+
+ for (low_node = low_rg->nodes.first; low_node; low_node = low_node->next)
+ {
+ for (high_node = high_rg->nodes.first; high_node; high_node = high_node->next)
+ {
+ if (low_node->index == high_node->index)
+ {
+ high_node->link_down = low_node;
+ low_node->link_up = high_node;
+ break;
+ }
+ }
+ }
+}
+
+ReebNode *BIF_otherNodeFromIndex(ReebArc *arc, ReebNode *node)
+{
+ return (arc->head->index == node->index) ? arc->tail : arc->head;
+}
+
+ReebNode *BIF_NodeFromIndex(ReebArc *arc, ReebNode *node)
+{
+ return (arc->head->index == node->index) ? arc->head : arc->tail;
+}
+
+ReebNode *BIF_lowestLevelNode(ReebNode *node)
+{
+ while (node->link_down)
+ {
+ node = node->link_down;
+ }
+
+ return node;
+}
+
+ReebArc * copyArc(ReebGraph *rg, ReebArc *arc)
+{
+ ReebArc *cp_arc;
+ ReebNode *node;
+
+ cp_arc = MEM_callocN(sizeof(ReebArc), "reeb arc copy");
+
+ memcpy(cp_arc, arc, sizeof(ReebArc));
+
+ cp_arc->link_up = arc;
+
+ cp_arc->head = NULL;
+ cp_arc->tail = NULL;
+
+ cp_arc->prev = NULL;
+ cp_arc->next = NULL;
+
+ cp_arc->edges.first = NULL;
+ cp_arc->edges.last = NULL;
+
+ /* copy buckets */
+ cp_arc->buckets = MEM_callocN(sizeof(EmbedBucket) * cp_arc->bcount, "embed bucket");
+ memcpy(cp_arc->buckets, arc->buckets, sizeof(EmbedBucket) * cp_arc->bcount);
+
+ /* copy faces map */
+ cp_arc->faces = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ mergeArcFaces(rg, cp_arc, arc);
+
+ /* find corresponding head and tail */
+ for (node = rg->nodes.first; node && (cp_arc->head == NULL || cp_arc->tail == NULL); node = node->next)
+ {
+ if (node->index == arc->head->index)
+ {
+ cp_arc->head = node;
+ }
+ else if (node->index == arc->tail->index)
+ {
+ cp_arc->tail = node;
+ }
+ }
+
+ BLI_addtail(&rg->arcs, cp_arc);
+
+ return cp_arc;
+}
+
+ReebGraph * copyReebGraph(ReebGraph *rg, int level)
+{
+ ReebNode *node;
+ ReebArc *arc;
+ ReebGraph *cp_rg = newReebGraph();
+
+ cp_rg->resolution = rg->resolution;
+ cp_rg->length = rg->length;
+ cp_rg->link_up = rg;
+ cp_rg->multi_level = level;
+
+ /* Copy nodes */
+ for (node = rg->nodes.first; node; node = node->next)
+ {
+ ReebNode *cp_node = copyNode(cp_rg, node);
+ cp_node->multi_level = level;
+ }
+
+ /* Copy arcs */
+ for (arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ copyArc(cp_rg, arc);
+ }
+
+ BLI_buildAdjacencyList((BGraph*)cp_rg);
+
+ return cp_rg;
+}
+
+ReebGraph *BIF_graphForMultiNode(ReebGraph *rg, ReebNode *node)
+{
+ ReebGraph *multi_rg = rg;
+
+ while(multi_rg && multi_rg->multi_level != node->multi_level)
+ {
+ multi_rg = multi_rg->link_up;
+ }
+
+ return multi_rg;
+}
+
+ReebEdge * copyEdge(ReebEdge *edge)
+{
+ ReebEdge *newEdge = NULL;
+
+ newEdge = MEM_callocN(sizeof(ReebEdge), "reeb edge");
+ memcpy(newEdge, edge, sizeof(ReebEdge));
+
+ newEdge->next = NULL;
+ newEdge->prev = NULL;
+
+ return newEdge;
+}
+
+void printArc(ReebArc *arc)
+{
+ ReebEdge *edge;
+ ReebNode *head = (ReebNode*)arc->head;
+ ReebNode *tail = (ReebNode*)arc->tail;
+ printf("arc: (%i) %f -> (%i) %f\n", head->index, head->weight, tail->index, tail->weight);
+
+ for(edge = arc->edges.first; edge ; edge = edge->next)
+ {
+ printf("\tedge (%i, %i)\n", edge->v1->index, edge->v2->index);
+ }
+}
+
+void flipArc(ReebArc *arc)
+{
+ ReebNode *tmp;
+ tmp = arc->head;
+ arc->head = arc->tail;
+ arc->tail = tmp;
+
+ flipArcBuckets(arc);
+}
+
+#ifdef DEBUG_REEB_NODE
+void NodeDegreeDecrement(ReebGraph *rg, ReebNode *node)
+{
+ node->degree--;
+
+// if (node->degree == 0)
+// {
+// printf("would remove node %i\n", node->index);
+// }
+}
+
+void NodeDegreeIncrement(ReebGraph *rg, ReebNode *node)
+{
+// if (node->degree == 0)
+// {
+// printf("first connect node %i\n", node->index);
+// }
+
+ node->degree++;
+}
+
+#else
+#define NodeDegreeDecrement(rg, node) {node->degree--;}
+#define NodeDegreeIncrement(rg, node) {node->degree++;}
+#endif
+
+void repositionNodes(ReebGraph *rg)
+{
+ BArc *arc = NULL;
+ BNode *node = NULL;
+
+ // Reset node positions
+ for(node = rg->nodes.first; node; node = node->next)
+ {
+ node->p[0] = node->p[1] = node->p[2] = 0;
+ }
+
+ for(arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ if (((ReebArc*)arc)->bcount > 0)
+ {
+ float p[3];
+
+ VECCOPY(p, ((ReebArc*)arc)->buckets[0].p);
+ VecMulf(p, 1.0f / arc->head->degree);
+ VecAddf(arc->head->p, arc->head->p, p);
+
+ VECCOPY(p, ((ReebArc*)arc)->buckets[((ReebArc*)arc)->bcount - 1].p);
+ VecMulf(p, 1.0f / arc->tail->degree);
+ VecAddf(arc->tail->p, arc->tail->p, p);
+ }
+ }
+}
+
+void verifyNodeDegree(ReebGraph *rg)
+{
+#ifdef DEBUG_REEB
+ ReebNode *node = NULL;
+ ReebArc *arc = NULL;
+
+ for(node = rg->nodes.first; node; node = node->next)
+ {
+ int count = 0;
+ for(arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ if (arc->head == node || arc->tail == node)
+ {
+ count++;
+ }
+ }
+ if (count != node->degree)
+ {
+ printf("degree error in node %i: expected %i got %i\n", node->index, count, node->degree);
+ }
+ if (node->degree == 0)
+ {
+ printf("zero degree node %i with weight %f\n", node->index, node->weight);
+ }
+ }
+#endif
+}
+
+void verifyBucketsArc(ReebGraph *rg, ReebArc *arc)
+{
+ ReebNode *head = (ReebNode*)arc->head;
+ ReebNode *tail = (ReebNode*)arc->tail;
+
+ if (arc->bcount > 0)
+ {
+ int i;
+ for(i = 0; i < arc->bcount; i++)
+ {
+ if (arc->buckets[i].nv == 0)
+ {
+ printArc(arc);
+ printf("count error in bucket %i/%i\n", i+1, arc->bcount);
+ }
+ }
+
+ if (ceil(head->weight) != arc->buckets[0].val)
+ {
+ printArc(arc);
+ printf("alloc error in first bucket: %f should be %f \n", arc->buckets[0].val, ceil(head->weight));
+ }
+ if (floor(tail->weight) != arc->buckets[arc->bcount - 1].val)
+ {
+ printArc(arc);
+ printf("alloc error in last bucket: %f should be %f \n", arc->buckets[arc->bcount - 1].val, floor(tail->weight));
+ }
+ }
+}
+
+void verifyBuckets(ReebGraph *rg)
+{
+#ifdef DEBUG_REEB
+ ReebArc *arc = NULL;
+ for(arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ verifyBucketsArc(rg, arc);
+ }
+#endif
+}
+
+void verifyFaces(ReebGraph *rg)
+{
+#ifdef DEBUG_REEB
+ int total = 0;
+ ReebArc *arc = NULL;
+ for(arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ total += BLI_ghash_size(arc->faces);
+ }
+
+#endif
+}
+
+void verifyArcs(ReebGraph *rg)
+{
+ ReebArc *arc;
+
+ for (arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ if (arc->head->weight > arc->tail->weight)
+ {
+ printf("FLIPPED ARC!\n");
+ }
+ }
+}
+
+void verifyMultiResolutionLinks(ReebGraph *rg, int level)
+{
+#ifdef DEBUG_REEB
+ ReebGraph *lower_rg = rg->link_up;
+
+ if (lower_rg)
+ {
+ ReebArc *arc;
+
+ for (arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ if (BLI_findindex(&lower_rg->arcs, arc->link_up) == -1)
+ {
+ printf("missing arc %p for level %i\n", arc->link_up, level);
+ printf("Source arc was ---\n");
+ printArc(arc);
+
+ arc->link_up = NULL;
+ }
+ }
+
+
+ verifyMultiResolutionLinks(lower_rg, level + 1);
+ }
+#endif
+}
+/***************************************** BUCKET UTILS **********************************************/
+
+void addVertToBucket(EmbedBucket *b, float co[3])
+{
+ b->nv++;
+ VecLerpf(b->p, b->p, co, 1.0f / b->nv);
+}
+
+void removeVertFromBucket(EmbedBucket *b, float co[3])
+{
+ VecMulf(b->p, (float)b->nv);
+ VecSubf(b->p, b->p, co);
+ b->nv--;
+ VecMulf(b->p, 1.0f / (float)b->nv);
+}
+
+void mergeBuckets(EmbedBucket *bDst, EmbedBucket *bSrc)
+{
+ if (bDst->nv > 0 && bSrc->nv > 0)
+ {
+ bDst->nv += bSrc->nv;
+ VecLerpf(bDst->p, bDst->p, bSrc->p, (float)bSrc->nv / (float)(bDst->nv));
+ }
+ else if (bSrc->nv > 0)
+ {
+ bDst->nv = bSrc->nv;
+ VECCOPY(bDst->p, bSrc->p);
+ }
+}
+
+void mergeArcBuckets(ReebArc *aDst, ReebArc *aSrc, float start, float end)
+{
+ if (aDst->bcount > 0 && aSrc->bcount > 0)
+ {
+ int indexDst = 0, indexSrc = 0;
+
+ start = MAX3(start, aDst->buckets[0].val, aSrc->buckets[0].val);
+
+ while(indexDst < aDst->bcount && aDst->buckets[indexDst].val < start)
+ {
+ indexDst++;
+ }
+
+ while(indexSrc < aSrc->bcount && aSrc->buckets[indexSrc].val < start)
+ {
+ indexSrc++;
+ }
+
+ for( ; indexDst < aDst->bcount &&
+ indexSrc < aSrc->bcount &&
+ aDst->buckets[indexDst].val <= end &&
+ aSrc->buckets[indexSrc].val <= end
+
+ ; indexDst++, indexSrc++)
+ {
+ mergeBuckets(aDst->buckets + indexDst, aSrc->buckets + indexSrc);
+ }
+ }
+}
+
+void flipArcBuckets(ReebArc *arc)
+{
+ int i, j;
+
+ for (i = 0, j = arc->bcount - 1; i < j; i++, j--)
+ {
+ EmbedBucket tmp;
+
+ tmp = arc->buckets[i];
+ arc->buckets[i] = arc->buckets[j];
+ arc->buckets[j] = tmp;
+ }
+}
+
+int countArcBuckets(ReebArc *arc)
+{
+ return (int)(floor(arc->tail->weight) - ceil(arc->head->weight)) + 1;
+}
+
+void allocArcBuckets(ReebArc *arc)
+{
+ int i;
+ float start = ceil(arc->head->weight);
+ arc->bcount = countArcBuckets(arc);
+
+ if (arc->bcount > 0)
+ {
+ arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "embed bucket");
+
+ for(i = 0; i < arc->bcount; i++)
+ {
+ arc->buckets[i].val = start + i;
+ }
+ }
+ else
+ {
+ arc->buckets = NULL;
+ }
+
+}
+
+void resizeArcBuckets(ReebArc *arc)
+{
+ EmbedBucket *oldBuckets = arc->buckets;
+ int oldBCount = arc->bcount;
+
+ if (countArcBuckets(arc) == oldBCount)
+ {
+ return;
+ }
+
+ allocArcBuckets(arc);
+
+ if (oldBCount != 0 && arc->bcount != 0)
+ {
+ int oldStart = (int)oldBuckets[0].val;
+ int oldEnd = (int)oldBuckets[oldBCount - 1].val;
+ int newStart = (int)arc->buckets[0].val;
+ int newEnd = (int)arc->buckets[arc->bcount - 1].val;
+ int oldOffset = 0;
+ int newOffset = 0;
+ int len;
+
+ if (oldStart < newStart)
+ {
+ oldOffset = newStart - oldStart;
+ }
+ else
+ {
+ newOffset = oldStart - newStart;
+ }
+
+ len = MIN2(oldEnd - (oldStart + oldOffset) + 1, newEnd - (newStart - newOffset) + 1);
+
+ memcpy(arc->buckets + newOffset, oldBuckets + oldOffset, len * sizeof(EmbedBucket));
+ }
+
+ if (oldBuckets != NULL)
+ {
+ MEM_freeN(oldBuckets);
+ }
+}
+
+void reweightBuckets(ReebArc *arc)
+{
+ int i;
+ float start = ceil((arc->head)->weight);
+
+ if (arc->bcount > 0)
+ {
+ for(i = 0; i < arc->bcount; i++)
+ {
+ arc->buckets[i].val = start + i;
+ }
+ }
+}
+
+static void interpolateBuckets(ReebArc *arc, float *start_p, float *end_p, int start_index, int end_index)
+{
+ int total;
+ int j;
+
+ total = end_index - start_index + 2;
+
+ for (j = start_index; j <= end_index; j++)
+ {
+ EmbedBucket *empty = arc->buckets + j;
+ empty->nv = 1;
+ VecLerpf(empty->p, start_p, end_p, (float)(j - start_index + 1) / total);
+ }
+}
+
+void fillArcEmptyBuckets(ReebArc *arc)
+{
+ float *start_p, *end_p;
+ int start_index = 0, end_index = 0;
+ int missing = 0;
+ int i;
+
+ start_p = arc->head->p;
+
+ for(i = 0; i < arc->bcount; i++)
+ {
+ EmbedBucket *bucket = arc->buckets + i;
+
+ if (missing)
+ {
+ if (bucket->nv > 0)
+ {
+ missing = 0;
+
+ end_p = bucket->p;
+ end_index = i - 1;
+
+ interpolateBuckets(arc, start_p, end_p, start_index, end_index);
+ }
+ }
+ else
+ {
+ if (bucket->nv == 0)
+ {
+ missing = 1;
+
+ if (i > 0)
+ {
+ start_p = arc->buckets[i - 1].p;
+ }
+ start_index = i;
+ }
+ }
+ }
+
+ if (missing)
+ {
+ end_p = arc->tail->p;
+ end_index = arc->bcount - 1;
+
+ interpolateBuckets(arc, start_p, end_p, start_index, end_index);
+ }
+}
+
+static void ExtendArcBuckets(ReebArc *arc)
+{
+ ReebArcIterator arc_iter;
+ BArcIterator *iter = (BArcIterator*)&arc_iter;
+ EmbedBucket *last_bucket, *first_bucket;
+ float *previous = NULL;
+ float average_length = 0, length;
+ int padding_head = 0, padding_tail = 0;
+
+ if (arc->bcount == 0)
+ {
+ return; /* failsafe, shouldn't happen */
+ }
+
+ initArcIterator(iter, arc, arc->head);
+ IT_next(iter);
+ previous = iter->p;
+
+ for ( IT_next(iter);
+ IT_stopped(iter) == 0;
+ previous = iter->p, IT_next(iter)
+ )
+ {
+ average_length += VecLenf(previous, iter->p);
+ }
+ average_length /= (arc->bcount - 1);
+
+ first_bucket = arc->buckets;
+ last_bucket = arc->buckets + (arc->bcount - 1);
+
+ length = VecLenf(first_bucket->p, arc->head->p);
+ if (length > 2 * average_length)
+ {
+ padding_head = (int)floor(length / average_length);
+ }
+
+ length = VecLenf(last_bucket->p, arc->tail->p);
+ if (length > 2 * average_length)
+ {
+ padding_tail = (int)floor(length / average_length);
+ }
+
+ if (padding_head + padding_tail > 0)
+ {
+ EmbedBucket *old_buckets = arc->buckets;
+
+ arc->buckets = MEM_callocN(sizeof(EmbedBucket) * (padding_head + arc->bcount + padding_tail), "embed bucket");
+ memcpy(arc->buckets + padding_head, old_buckets, arc->bcount * sizeof(EmbedBucket));
+
+ arc->bcount = padding_head + arc->bcount + padding_tail;
+
+ MEM_freeN(old_buckets);
+ }
+
+ if (padding_head > 0)
+ {
+ interpolateBuckets(arc, arc->head->p, first_bucket->p, 0, padding_head);
+ }
+
+ if (padding_tail > 0)
+ {
+ interpolateBuckets(arc, last_bucket->p, arc->tail->p, arc->bcount - padding_tail, arc->bcount - 1);
+ }
+}
+
+/* CALL THIS ONLY AFTER FILTERING, SINCE IT MESSES UP WEIGHT DISTRIBUTION */
+void extendGraphBuckets(ReebGraph *rg)
+{
+ ReebArc *arc;
+
+ for (arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ ExtendArcBuckets(arc);
+ }
+}
+
+/**************************************** LENGTH CALCULATIONS ****************************************/
+
+void calculateArcLength(ReebArc *arc)
+{
+ ReebArcIterator arc_iter;
+ BArcIterator *iter = (BArcIterator*)&arc_iter;
+ float *vec0, *vec1;
+
+ arc->length = 0;
+
+ initArcIterator(iter, arc, arc->head);
+
+ vec0 = arc->head->p;
+ vec1 = arc->head->p; /* in case there's no embedding */
+
+ while (IT_next(iter))
+ {
+ vec1 = iter->p;
+
+ arc->length += VecLenf(vec0, vec1);
+
+ vec0 = vec1;
+ }
+
+ arc->length += VecLenf(arc->tail->p, vec1);
+}
+
+void calculateGraphLength(ReebGraph *rg)
+{
+ ReebArc *arc;
+
+ for (arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ calculateArcLength(arc);
+ }
+}
+
+/**************************************** SYMMETRY HANDLING ******************************************/
+
+void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count)
+{
+ ReebNode *node = (ReebNode*)root_node;
+ float axis[3];
+ int i;
+
+ VECCOPY(axis, root_node->symmetry_axis);
+
+ /* first pass, merge incrementally */
+ for (i = 0; i < count - 1; i++)
+ {
+ ReebNode *node1, *node2;
+ ReebArc *arc1, *arc2;
+ float tangent[3];
+ float normal[3];
+ int j = i + 1;
+
+ VecAddf(tangent, ring[i].n, ring[j].n);
+ Crossf(normal, tangent, axis);
+
+ node1 = (ReebNode*)BLI_otherNode(ring[i].arc, root_node);
+ node2 = (ReebNode*)BLI_otherNode(ring[j].arc, root_node);
+
+ arc1 = (ReebArc*)ring[i].arc;
+ arc2 = (ReebArc*)ring[j].arc;
+
+ /* mirror first node and mix with the second */
+ BLI_mirrorAlongAxis(node1->p, root_node->p, normal);
+ VecLerpf(node2->p, node2->p, node1->p, 1.0f / (j + 1));
+
+ /* Merge buckets
+ * there shouldn't be any null arcs here, but just to be safe
+ * */
+ if (arc1->bcount > 0 && arc2->bcount > 0)
+ {
+ ReebArcIterator arc_iter1, arc_iter2;
+ BArcIterator *iter1 = (BArcIterator*)&arc_iter1;
+ BArcIterator *iter2 = (BArcIterator*)&arc_iter2;
+ EmbedBucket *bucket1 = NULL, *bucket2 = NULL;
+
+ initArcIterator(iter1, arc1, (ReebNode*)root_node);
+ initArcIterator(iter2, arc2, (ReebNode*)root_node);
+
+ bucket1 = IT_next(iter1);
+ bucket2 = IT_next(iter2);
+
+ /* Make sure they both start at the same value */
+ while(bucket1 && bucket2 && bucket1->val < bucket2->val)
+ {
+ bucket1 = IT_next(iter1);
+ }
+
+ while(bucket1 && bucket2 && bucket2->val < bucket1->val)
+ {
+ bucket2 = IT_next(iter2);
+ }
+
+
+ for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2))
+ {
+ bucket2->nv += bucket1->nv; /* add counts */
+
+ /* mirror on axis */
+ BLI_mirrorAlongAxis(bucket1->p, root_node->p, normal);
+ /* add bucket2 in bucket1 */
+ VecLerpf(bucket2->p, bucket2->p, bucket1->p, (float)bucket1->nv / (float)(bucket2->nv));
+ }
+ }
+ }
+
+ /* second pass, mirror back on previous arcs */
+ for (i = count - 1; i > 0; i--)
+ {
+ ReebNode *node1, *node2;
+ ReebArc *arc1, *arc2;
+ float tangent[3];
+ float normal[3];
+ int j = i - 1;
+
+ VecAddf(tangent, ring[i].n, ring[j].n);
+ Crossf(normal, tangent, axis);
+
+ node1 = (ReebNode*)BLI_otherNode(ring[i].arc, root_node);
+ node2 = (ReebNode*)BLI_otherNode(ring[j].arc, root_node);
+
+ arc1 = (ReebArc*)ring[i].arc;
+ arc2 = (ReebArc*)ring[j].arc;
+
+ /* copy first node than mirror */
+ VECCOPY(node2->p, node1->p);
+ BLI_mirrorAlongAxis(node2->p, root_node->p, normal);
+
+ /* Copy buckets
+ * there shouldn't be any null arcs here, but just to be safe
+ * */
+ if (arc1->bcount > 0 && arc2->bcount > 0)
+ {
+ ReebArcIterator arc_iter1, arc_iter2;
+ BArcIterator *iter1 = (BArcIterator*)&arc_iter1;
+ BArcIterator *iter2 = (BArcIterator*)&arc_iter2;
+ EmbedBucket *bucket1 = NULL, *bucket2 = NULL;
+
+ initArcIterator(iter1, arc1, node);
+ initArcIterator(iter2, arc2, node);
+
+ bucket1 = IT_next(iter1);
+ bucket2 = IT_next(iter2);
+
+ /* Make sure they both start at the same value */
+ while(bucket1 && bucket1->val < bucket2->val)
+ {
+ bucket1 = IT_next(iter1);
+ }
+
+ while(bucket2 && bucket2->val < bucket1->val)
+ {
+ bucket2 = IT_next(iter2);
+ }
+
+
+ for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2))
+ {
+ /* copy and mirror back to bucket2 */
+ bucket2->nv = bucket1->nv;
+ VECCOPY(bucket2->p, bucket1->p);
+ BLI_mirrorAlongAxis(bucket2->p, node->p, normal);
+ }
+ }
+ }
+}
+
+void REEB_AxialSymmetry(BNode* root_node, BNode* node1, BNode* node2, struct BArc* barc1, BArc* barc2)
+{
+ ReebArc *arc1, *arc2;
+ float nor[3], p[3];
+
+ arc1 = (ReebArc*)barc1;
+ arc2 = (ReebArc*)barc2;
+
+ VECCOPY(nor, root_node->symmetry_axis);
+
+ /* mirror node2 along axis */
+ VECCOPY(p, node2->p);
+ BLI_mirrorAlongAxis(p, root_node->p, nor);
+
+ /* average with node1 */
+ VecAddf(node1->p, node1->p, p);
+ VecMulf(node1->p, 0.5f);
+
+ /* mirror back on node2 */
+ VECCOPY(node2->p, node1->p);
+ BLI_mirrorAlongAxis(node2->p, root_node->p, nor);
+
+ /* Merge buckets
+ * there shouldn't be any null arcs here, but just to be safe
+ * */
+ if (arc1->bcount > 0 && arc2->bcount > 0)
+ {
+ ReebArcIterator arc_iter1, arc_iter2;
+ BArcIterator *iter1 = (BArcIterator*)&arc_iter1;
+ BArcIterator *iter2 = (BArcIterator*)&arc_iter2;
+ EmbedBucket *bucket1 = NULL, *bucket2 = NULL;
+
+ initArcIterator(iter1, arc1, (ReebNode*)root_node);
+ initArcIterator(iter2, arc2, (ReebNode*)root_node);
+
+ bucket1 = IT_next(iter1);
+ bucket2 = IT_next(iter2);
+
+ /* Make sure they both start at the same value */
+ while(bucket1 && bucket1->val < bucket2->val)
+ {
+ bucket1 = IT_next(iter1);
+ }
+
+ while(bucket2 && bucket2->val < bucket1->val)
+ {
+ bucket2 = IT_next(iter2);
+ }
+
+
+ for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2))
+ {
+ bucket1->nv += bucket2->nv; /* add counts */
+
+ /* mirror on axis */
+ BLI_mirrorAlongAxis(bucket2->p, root_node->p, nor);
+ /* add bucket2 in bucket1 */
+ VecLerpf(bucket1->p, bucket1->p, bucket2->p, (float)bucket2->nv / (float)(bucket1->nv));
+
+ /* copy and mirror back to bucket2 */
+ bucket2->nv = bucket1->nv;
+ VECCOPY(bucket2->p, bucket1->p);
+ BLI_mirrorAlongAxis(bucket2->p, root_node->p, nor);
+ }
+ }
+}
+
+/************************************** ADJACENCY LIST *************************************************/
+
+
+/****************************************** SMOOTHING **************************************************/
+
+void postprocessGraph(ReebGraph *rg, char mode)
+{
+ ReebArc *arc;
+ float fac1 = 0, fac2 = 1, fac3 = 0;
+
+ switch(mode)
+ {
+ case SKGEN_AVERAGE:
+ fac1 = fac2 = fac3 = 1.0f / 3.0f;
+ break;
+ case SKGEN_SMOOTH:
+ fac1 = fac3 = 0.25f;
+ fac2 = 0.5f;
+ break;
+ case SKGEN_SHARPEN:
+ fac1 = fac2 = -0.25f;
+ fac2 = 1.5f;
+ break;
+ default:
+// XXX
+// error("Unknown post processing mode");
+ return;
+ }
+
+ for(arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ EmbedBucket *buckets = arc->buckets;
+ int bcount = arc->bcount;
+ int index;
+
+ for(index = 1; index < bcount - 1; index++)
+ {
+ VecLerpf(buckets[index].p, buckets[index].p, buckets[index - 1].p, fac1 / (fac1 + fac2));
+ VecLerpf(buckets[index].p, buckets[index].p, buckets[index + 1].p, fac3 / (fac1 + fac2 + fac3));
+ }
+ }
+}
+
+/********************************************SORTING****************************************************/
+
+int compareNodesWeight(void *vnode1, void *vnode2)
+{
+ ReebNode *node1 = (ReebNode*)vnode1;
+ ReebNode *node2 = (ReebNode*)vnode2;
+
+ if (node1->weight < node2->weight)
+ {
+ return -1;
+ }
+ if (node1->weight > node2->weight)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void sortNodes(ReebGraph *rg)
+{
+ BLI_sortlist(&rg->nodes, compareNodesWeight);
+}
+
+int compareArcsWeight(void *varc1, void *varc2)
+{
+ ReebArc *arc1 = (ReebArc*)varc1;
+ ReebArc *arc2 = (ReebArc*)varc2;
+ ReebNode *node1 = (ReebNode*)arc1->head;
+ ReebNode *node2 = (ReebNode*)arc2->head;
+
+ if (node1->weight < node2->weight)
+ {
+ return -1;
+ }
+ if (node1->weight > node2->weight)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void sortArcs(ReebGraph *rg)
+{
+ BLI_sortlist(&rg->arcs, compareArcsWeight);
+}
+/******************************************* JOINING ***************************************************/
+
+void reweightArc(ReebGraph *rg, ReebArc *arc, ReebNode *start_node, float start_weight)
+{
+ ReebNode *node;
+ float old_weight;
+ float end_weight = start_weight + ABS(arc->tail->weight - arc->head->weight);
+ int i;
+
+ node = (ReebNode*)BLI_otherNode((BArc*)arc, (BNode*)start_node);
+
+ /* prevent backtracking */
+ if (node->flag == 1)
+ {
+ return;
+ }
+
+ if (arc->tail == start_node)
+ {
+ flipArc(arc);
+ }
+
+ start_node->flag = 1;
+
+ for (i = 0; i < node->degree; i++)
+ {
+ ReebArc *next_arc = node->arcs[i];
+
+ reweightArc(rg, next_arc, node, end_weight);
+ }
+
+ /* update only if needed */
+ if (arc->head->weight != start_weight || arc->tail->weight != end_weight)
+ {
+ old_weight = arc->head->weight; /* backup head weight, other arcs need it intact, it will be fixed by the source arc */
+
+ arc->head->weight = start_weight;
+ arc->tail->weight = end_weight;
+
+ reweightBuckets(arc);
+ resizeArcBuckets(arc);
+ fillArcEmptyBuckets(arc);
+
+ arc->head->weight = old_weight;
+ }
+}
+
+void reweightSubgraph(ReebGraph *rg, ReebNode *start_node, float start_weight)
+{
+ int i;
+
+ BLI_flagNodes((BGraph*)rg, 0);
+
+ for (i = 0; i < start_node->degree; i++)
+ {
+ ReebArc *next_arc = start_node->arcs[i];
+
+ reweightArc(rg, next_arc, start_node, start_weight);
+ }
+ start_node->weight = start_weight;
+}
+
+int joinSubgraphsEnds(ReebGraph *rg, float threshold, int nb_subgraphs)
+{
+ int joined = 0;
+ int subgraph;
+
+ for (subgraph = 1; subgraph <= nb_subgraphs; subgraph++)
+ {
+ ReebNode *start_node, *end_node;
+ ReebNode *min_node_start = NULL, *min_node_end = NULL;
+ float min_distance = FLT_MAX;
+
+ for (start_node = rg->nodes.first; start_node; start_node = start_node->next)
+ {
+ if (start_node->subgraph_index == subgraph && start_node->degree == 1)
+ {
+
+ for (end_node = rg->nodes.first; end_node; end_node = end_node->next)
+ {
+ if (end_node->subgraph_index != subgraph)
+ {
+ float distance = VecLenf(start_node->p, end_node->p);
+
+ if (distance < threshold && distance < min_distance)
+ {
+ min_distance = distance;
+ min_node_end = end_node;
+ min_node_start = start_node;
+ }
+ }
+ }
+ }
+ }
+
+ end_node = min_node_end;
+ start_node = min_node_start;
+
+ if (end_node && start_node)
+ {
+ ReebArc *start_arc, *end_arc;
+ int merging = 0;
+
+ start_arc = start_node->arcs[0];
+ end_arc = end_node->arcs[0];
+
+ if (start_arc->tail == start_node)
+ {
+ reweightSubgraph(rg, end_node, start_node->weight);
+
+ start_arc->tail = end_node;
+
+ merging = 1;
+ }
+ else if (start_arc->head == start_node)
+ {
+ reweightSubgraph(rg, start_node, end_node->weight);
+
+ start_arc->head = end_node;
+
+ merging = 2;
+ }
+
+ if (merging)
+ {
+ BLI_ReflagSubgraph((BGraph*)rg, end_node->flag, subgraph);
+
+ resizeArcBuckets(start_arc);
+ fillArcEmptyBuckets(start_arc);
+
+ NodeDegreeIncrement(rg, end_node);
+ BLI_rebuildAdjacencyListForNode((BGraph*)rg, (BNode*)end_node);
+
+ BLI_removeNode((BGraph*)rg, (BNode*)start_node);
+ }
+
+ joined = 1;
+ }
+ }
+
+ return joined;
+}
+
+/* Reweight graph from smallest node, fix fliped arcs */
+void fixSubgraphsOrientation(ReebGraph *rg, int nb_subgraphs)
+{
+ int subgraph;
+
+ for (subgraph = 1; subgraph <= nb_subgraphs; subgraph++)
+ {
+ ReebNode *node;
+ ReebNode *start_node = NULL;
+
+ for (node = rg->nodes.first; node; node = node->next)
+ {
+ if (node->subgraph_index == subgraph)
+ {
+ if (start_node == NULL || node->weight < start_node->weight)
+ {
+ start_node = node;
+ }
+ }
+ }
+
+ if (start_node)
+ {
+ reweightSubgraph(rg, start_node, start_node->weight);
+ }
+ }
+}
+
+int joinSubgraphs(ReebGraph *rg, float threshold)
+{
+ int nb_subgraphs;
+ int joined = 0;
+
+ BLI_buildAdjacencyList((BGraph*)rg);
+
+ if (BLI_isGraphCyclic((BGraph*)rg))
+ {
+ /* don't deal with cyclic graphs YET */
+ return 0;
+ }
+
+ /* sort nodes before flagging subgraphs to make sure root node is subgraph 0 */
+ sortNodes(rg);
+
+ nb_subgraphs = BLI_FlagSubgraphs((BGraph*)rg);
+
+ /* Harmonic function can create flipped arcs, take the occasion to fix them */
+// XXX
+// if (G.scene->toolsettings->skgen_options & SKGEN_HARMONIC)
+// {
+ fixSubgraphsOrientation(rg, nb_subgraphs);
+// }
+
+ if (nb_subgraphs > 1)
+ {
+ joined |= joinSubgraphsEnds(rg, threshold, nb_subgraphs);
+
+ if (joined)
+ {
+ removeNormalNodes(rg);
+ BLI_buildAdjacencyList((BGraph*)rg);
+ }
+ }
+
+ return joined;
+}
+
+/****************************************** FILTERING **************************************************/
+
+float lengthArc(ReebArc *arc)
+{
+#if 0
+ ReebNode *head = (ReebNode*)arc->head;
+ ReebNode *tail = (ReebNode*)arc->tail;
+
+ return tail->weight - head->weight;
+#else
+ return arc->length;
+#endif
+}
+
+int compareArcs(void *varc1, void *varc2)
+{
+ ReebArc *arc1 = (ReebArc*)varc1;
+ ReebArc *arc2 = (ReebArc*)varc2;
+ float len1 = lengthArc(arc1);
+ float len2 = lengthArc(arc2);
+
+ if (len1 < len2)
+ {
+ return -1;
+ }
+ if (len1 > len2)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void filterArc(ReebGraph *rg, ReebNode *newNode, ReebNode *removedNode, ReebArc * srcArc, int merging)
+{
+ ReebArc *arc = NULL, *nextArc = NULL;
+
+ if (merging)
+ {
+ /* first pass, merge buckets for arcs that spawned the two nodes into the source arc*/
+ for(arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ if (arc->head == srcArc->head && arc->tail == srcArc->tail && arc != srcArc)
+ {
+ ReebNode *head = srcArc->head;
+ ReebNode *tail = srcArc->tail;
+ mergeArcBuckets(srcArc, arc, head->weight, tail->weight);
+ }
+ }
+ }
+
+ /* second pass, replace removedNode by newNode, remove arcs that are collapsed in a loop */
+ arc = rg->arcs.first;
+ while(arc)
+ {
+ nextArc = arc->next;
+
+ if (arc->head == removedNode || arc->tail == removedNode)
+ {
+ if (arc->head == removedNode)
+ {
+ arc->head = newNode;
+ }
+ else
+ {
+ arc->tail = newNode;
+ }
+
+ // Remove looped arcs
+ if (arc->head == arc->tail)
+ {
+ // v1 or v2 was already newNode, since we're removing an arc, decrement degree
+ NodeDegreeDecrement(rg, newNode);
+
+ // If it's srcArc, it'll be removed later, so keep it for now
+ if (arc != srcArc)
+ {
+ BLI_remlink(&rg->arcs, arc);
+ REEB_freeArc((BArc*)arc);
+ }
+ }
+ else
+ {
+ /* flip arcs that flipped, can happen on diamond shapes, mostly on null arcs */
+ if (arc->head->weight > arc->tail->weight)
+ {
+ flipArc(arc);
+ }
+ //newNode->degree++; // incrementing degree since we're adding an arc
+ NodeDegreeIncrement(rg, newNode);
+ mergeArcFaces(rg, arc, srcArc);
+
+ if (merging)
+ {
+ ReebNode *head = arc->head;
+ ReebNode *tail = arc->tail;
+
+ // resize bucket list
+ resizeArcBuckets(arc);
+ mergeArcBuckets(arc, srcArc, head->weight, tail->weight);
+
+ /* update length */
+ arc->length += srcArc->length;
+ }
+ }
+ }
+
+ arc = nextArc;
+ }
+}
+
+void filterNullReebGraph(ReebGraph *rg)
+{
+ ReebArc *arc = NULL, *nextArc = NULL;
+
+ arc = rg->arcs.first;
+ while(arc)
+ {
+ nextArc = arc->next;
+ // Only collapse arcs too short to have any embed bucket
+ if (arc->bcount == 0)
+ {
+ ReebNode *newNode = (ReebNode*)arc->head;
+ ReebNode *removedNode = (ReebNode*)arc->tail;
+ float blend;
+
+ blend = (float)newNode->degree / (float)(newNode->degree + removedNode->degree); // blending factors
+
+ VecLerpf(newNode->p, removedNode->p, newNode->p, blend);
+
+ filterArc(rg, newNode, removedNode, arc, 0);
+
+ // Reset nextArc, it might have changed
+ nextArc = arc->next;
+
+ BLI_remlink(&rg->arcs, arc);
+ REEB_freeArc((BArc*)arc);
+
+ BLI_removeNode((BGraph*)rg, (BNode*)removedNode);
+ }
+
+ arc = nextArc;
+ }
+}
+
+int filterInternalExternalReebGraph(ReebGraph *rg, float threshold_internal, float threshold_external)
+{
+ ReebArc *arc = NULL, *nextArc = NULL;
+ int value = 0;
+
+ BLI_sortlist(&rg->arcs, compareArcs);
+
+ for (arc = rg->arcs.first; arc; arc = nextArc)
+ {
+ nextArc = arc->next;
+
+ // Only collapse non-terminal arcs that are shorter than threshold
+ if (threshold_internal > 0 && arc->head->degree > 1 && arc->tail->degree > 1 && (lengthArc(arc) < threshold_internal))
+ {
+ ReebNode *newNode = NULL;
+ ReebNode *removedNode = NULL;
+
+ /* Always remove lower node, so arcs don't flip */
+ newNode = arc->head;
+ removedNode = arc->tail;
+
+ filterArc(rg, newNode, removedNode, arc, 1);
+
+ // Reset nextArc, it might have changed
+ nextArc = arc->next;
+
+ BLI_remlink(&rg->arcs, arc);
+ REEB_freeArc((BArc*)arc);
+
+ BLI_removeNode((BGraph*)rg, (BNode*)removedNode);
+ value = 1;
+ }
+
+ // Only collapse terminal arcs that are shorter than threshold
+ else if (threshold_external > 0 && (arc->head->degree == 1 || arc->tail->degree == 1) && (lengthArc(arc) < threshold_external))
+ {
+ ReebNode *terminalNode = NULL;
+ ReebNode *middleNode = NULL;
+ ReebNode *removedNode = NULL;
+
+ // Assign terminal and middle nodes
+ if (arc->head->degree == 1)
+ {
+ terminalNode = arc->head;
+ middleNode = arc->tail;
+ }
+ else
+ {
+ terminalNode = arc->tail;
+ middleNode = arc->head;
+ }
+
+ if (middleNode->degree == 2 && middleNode != rg->nodes.first)
+ {
+#if 1
+ // If middle node is a normal node, it will be removed later
+ // Only if middle node is not the root node
+ /* USE THIS IF YOU WANT TO PROLONG ARCS TO THEIR TERMINAL NODES
+ * FOR HANDS, THIS IS NOT THE BEST RESULT
+ * */
+ continue;
+#else
+ removedNode = terminalNode;
+
+ // removing arc, so we need to decrease the degree of the remaining node
+ NodeDegreeDecrement(rg, middleNode);
+#endif
+ }
+ // Otherwise, just plain remove of the arc
+ else
+ {
+ removedNode = terminalNode;
+
+ // removing arc, so we need to decrease the degree of the remaining node
+ NodeDegreeDecrement(rg, middleNode);
+ }
+
+ // Reset nextArc, it might have changed
+ nextArc = arc->next;
+
+ BLI_remlink(&rg->arcs, arc);
+ REEB_freeArc((BArc*)arc);
+
+ BLI_removeNode((BGraph*)rg, (BNode*)removedNode);
+ value = 1;
+ }
+ }
+
+ return value;
+}
+
+int filterCyclesReebGraph(ReebGraph *rg, float distance_threshold)
+{
+ ReebArc *arc1, *arc2;
+ ReebArc *next2;
+ int filtered = 0;
+
+ for (arc1 = rg->arcs.first; arc1; arc1 = arc1->next)
+ {
+ for (arc2 = arc1->next; arc2; arc2 = next2)
+ {
+ next2 = arc2->next;
+ if (arc1 != arc2 && arc1->head == arc2->head && arc1->tail == arc2->tail)
+ {
+ mergeArcEdges(rg, arc1, arc2, MERGE_APPEND);
+ mergeArcFaces(rg, arc1, arc2);
+ mergeArcBuckets(arc1, arc2, arc1->head->weight, arc1->tail->weight);
+
+ NodeDegreeDecrement(rg, arc1->head);
+ NodeDegreeDecrement(rg, arc1->tail);
+
+ BLI_remlink(&rg->arcs, arc2);
+ REEB_freeArc((BArc*)arc2);
+
+ filtered = 1;
+ }
+ }
+ }
+
+ return filtered;
+}
+
+int filterSmartReebGraph(ReebGraph *rg, float threshold)
+{
+ int value = 0;
+#if 0 //XXX
+ ReebArc *arc = NULL, *nextArc = NULL;
+
+ BLI_sortlist(&rg->arcs, compareArcs);
+
+#ifdef DEBUG_REEB
+ {
+ EditFace *efa;
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next) {
+ efa->tmp.fp = -1;
+ }
+ }
+#endif
+
+ arc = rg->arcs.first;
+ while(arc)
+ {
+ nextArc = arc->next;
+
+ /* need correct normals and center */
+ recalc_editnormals();
+
+ // Only test terminal arcs
+ if (arc->head->degree == 1 || arc->tail->degree == 1)
+ {
+ GHashIterator ghi;
+ int merging = 0;
+ int total = BLI_ghash_size(arc->faces);
+ float avg_angle = 0;
+ float avg_vec[3] = {0,0,0};
+
+ for(BLI_ghashIterator_init(&ghi, arc->faces);
+ !BLI_ghashIterator_isDone(&ghi);
+ BLI_ghashIterator_step(&ghi))
+ {
+ EditFace *efa = BLI_ghashIterator_getValue(&ghi);
+
+#if 0
+ ReebArcIterator arc_iter;
+ BArcIterator *iter = (BArcIterator*)&arc_iter;
+ EmbedBucket *bucket = NULL;
+ EmbedBucket *previous = NULL;
+ float min_distance = -1;
+ float angle = 0;
+
+ initArcIterator(iter, arc, arc->head);
+
+ bucket = nextBucket(iter);
+
+ while (bucket != NULL)
+ {
+ float *vec0 = NULL;
+ float *vec1 = bucket->p;
+ float midpoint[3], tangent[3];
+ float distance;
+
+ /* first bucket. Previous is head */
+ if (previous == NULL)
+ {
+ vec0 = arc->head->p;
+ }
+ /* Previous is a valid bucket */
+ else
+ {
+ vec0 = previous->p;
+ }
+
+ VECCOPY(midpoint, vec1);
+
+ distance = VecLenf(midpoint, efa->cent);
+
+ if (min_distance == -1 || distance < min_distance)
+ {
+ min_distance = distance;
+
+ VecSubf(tangent, vec1, vec0);
+ Normalize(tangent);
+
+ angle = Inpf(tangent, efa->n);
+ }
+
+ previous = bucket;
+ bucket = nextBucket(iter);
+ }
+
+ avg_angle += saacos(fabs(angle));
+#ifdef DEBUG_REEB
+ efa->tmp.fp = saacos(fabs(angle));
+#endif
+#else
+ VecAddf(avg_vec, avg_vec, efa->n);
+#endif
+ }
+
+
+#if 0
+ avg_angle /= total;
+#else
+ VecMulf(avg_vec, 1.0 / total);
+ avg_angle = Inpf(avg_vec, avg_vec);
+#endif
+
+ arc->angle = avg_angle;
+
+ if (avg_angle > threshold)
+ merging = 1;
+
+ if (merging)
+ {
+ ReebNode *terminalNode = NULL;
+ ReebNode *middleNode = NULL;
+ ReebNode *newNode = NULL;
+ ReebNode *removedNode = NULL;
+ int merging = 0;
+
+ // Assign terminal and middle nodes
+ if (arc->head->degree == 1)
+ {
+ terminalNode = arc->head;
+ middleNode = arc->tail;
+ }
+ else
+ {
+ terminalNode = arc->tail;
+ middleNode = arc->head;
+ }
+
+ // If middle node is a normal node, merge to terminal node
+ if (middleNode->degree == 2)
+ {
+ merging = 1;
+ newNode = terminalNode;
+ removedNode = middleNode;
+ }
+ // Otherwise, just plain remove of the arc
+ else
+ {
+ merging = 0;
+ newNode = middleNode;
+ removedNode = terminalNode;
+ }
+
+ // Merging arc
+ if (merging)
+ {
+ filterArc(rg, newNode, removedNode, arc, 1);
+ }
+ else
+ {
+ // removing arc, so we need to decrease the degree of the remaining node
+ //newNode->degree--;
+ NodeDegreeDecrement(rg, newNode);
+ }
+
+ // Reset nextArc, it might have changed
+ nextArc = arc->next;
+
+ BLI_remlink(&rg->arcs, arc);
+ REEB_freeArc((BArc*)arc);
+
+ BLI_freelinkN(&rg->nodes, removedNode);
+ value = 1;
+ }
+ }
+
+ arc = nextArc;
+ }
+
+ #endif
+
+ return value;
+}
+
+void filterGraph(ReebGraph *rg, short options, float threshold_internal, float threshold_external)
+{
+ int done = 1;
+
+ calculateGraphLength(rg);
+
+ if ((options & SKGEN_FILTER_EXTERNAL) == 0)
+ {
+ threshold_external = 0;
+ }
+
+ if ((options & SKGEN_FILTER_INTERNAL) == 0)
+ {
+ threshold_internal = 0;
+ }
+
+ if (threshold_internal > 0 || threshold_external > 0)
+ {
+ /* filter until there's nothing more to do */
+ while (done == 1)
+ {
+ done = 0; /* no work done yet */
+
+ done = filterInternalExternalReebGraph(rg, threshold_internal, threshold_external);
+ }
+ }
+
+ if (options & SKGEN_FILTER_SMART)
+ {
+ filterSmartReebGraph(rg, 0.5);
+ filterCyclesReebGraph(rg, 0.5);
+ }
+
+ repositionNodes(rg);
+
+ /* Filtering might have created degree 2 nodes, so remove them */
+ removeNormalNodes(rg);
+}
+
+void finalizeGraph(ReebGraph *rg, char passes, char method)
+{
+ int i;
+
+ BLI_buildAdjacencyList((BGraph*)rg);
+
+ sortNodes(rg);
+
+ sortArcs(rg);
+
+ for(i = 0; i < passes; i++)
+ {
+ postprocessGraph(rg, method);
+ }
+
+ extendGraphBuckets(rg);
+}
+
+/************************************** WEIGHT SPREADING ***********************************************/
+
+int compareVerts( const void* a, const void* b )
+{
+ EditVert *va = *(EditVert**)a;
+ EditVert *vb = *(EditVert**)b;
+ int value = 0;
+
+ if (weightData(va) < weightData(vb))
+ {
+ value = -1;
+ }
+ else if (weightData(va) > weightData(vb))
+ {
+ value = 1;
+ }
+
+ return value;
+}
+
+void spreadWeight(EditMesh *em)
+{
+ EditVert **verts, *eve;
+ float lastWeight = 0.0f;
+ int totvert = BLI_countlist(&em->verts);
+ int i;
+ int work_needed = 1;
+
+ verts = MEM_callocN(sizeof(EditVert*) * totvert, "verts array");
+
+ for(eve = em->verts.first, i = 0; eve; eve = eve->next, i++)
+ {
+ verts[i] = eve;
+ }
+
+ while(work_needed == 1)
+ {
+ work_needed = 0;
+ qsort(verts, totvert, sizeof(EditVert*), compareVerts);
+
+ for(i = 0; i < totvert; i++)
+ {
+ eve = verts[i];
+
+ if (i == 0 || (weightData(eve) - lastWeight) > FLT_EPSILON)
+ {
+ lastWeight = weightData(eve);
+ }
+ else
+ {
+ work_needed = 1;
+ weightSetData(eve, lastWeight + FLT_EPSILON * 2);
+ lastWeight = weightData(eve);
+ }
+ }
+ }
+
+ MEM_freeN(verts);
+}
+
+/******************************************** EXPORT ***************************************************/
+
+void exportNode(FILE *f, char *text, ReebNode *node)
+{
+ fprintf(f, "%s i:%i w:%f d:%i %f %f %f\n", text, node->index, node->weight, node->degree, node->p[0], node->p[1], node->p[2]);
+}
+
+void REEB_exportGraph(ReebGraph *rg, int count)
+{
+ ReebArc *arc;
+ char filename[128];
+ FILE *f;
+
+ if (count == -1)
+ {
+ sprintf(filename, "test.txt");
+ }
+ else
+ {
+ sprintf(filename, "test%05i.txt", count);
+ }
+ f = fopen(filename, "w");
+
+ for(arc = rg->arcs.first; arc; arc = arc->next)
+ {
+ int i;
+ float p[3];
+
+ exportNode(f, "v1", arc->head);
+
+ for(i = 0; i < arc->bcount; i++)
+ {
+ fprintf(f, "b nv:%i %f %f %f\n", arc->buckets[i].nv, arc->buckets[i].p[0], arc->buckets[i].p[1], arc->buckets[i].p[2]);
+ }
+
+ VecAddf(p, arc->tail->p, arc->head->p);
+ VecMulf(p, 0.5f);
+
+ fprintf(f, "angle %0.3f %0.3f %0.3f %0.3f %i\n", p[0], p[1], p[2], arc->angle, BLI_ghash_size(arc->faces));
+ exportNode(f, "v2", arc->tail);
+ }
+
+ fclose(f);
+}
+
+/***************************************** MAIN ALGORITHM **********************************************/
+
+/* edges alone will create zero degree nodes, use this function to remove them */
+void removeZeroNodes(ReebGraph *rg)
+{
+ ReebNode *node, *next_node;
+
+ for (node = rg->nodes.first; node; node = next_node)
+ {
+ next_node = node->next;
+
+ if (node->degree == 0)
+ {
+ BLI_removeNode((BGraph*)rg, (BNode*)node);
+ }
+ }
+}
+
+void removeNormalNodes(ReebGraph *rg)
+{
+ ReebArc *arc, *nextArc;
+
+ // Merge degree 2 nodes
+ for(arc = rg->arcs.first; arc; arc = nextArc)
+ {
+ nextArc = arc->next;
+
+ while (arc->head->degree == 2 || arc->tail->degree == 2)
+ {
+ // merge at v1
+ if (arc->head->degree == 2)
+ {
+ ReebArc *connectedArc = (ReebArc*)BLI_findConnectedArc((BGraph*)rg, (BArc*)arc, (BNode*)arc->head);
+
+ /* If arcs are one after the other */
+ if (arc->head == connectedArc->tail)
+ {
+ /* remove furthest arc */
+ if (arc->tail->weight < connectedArc->head->weight)
+ {
+ mergeConnectedArcs(rg, arc, connectedArc);
+ nextArc = arc->next;
+ }
+ else
+ {
+ mergeConnectedArcs(rg, connectedArc, arc);
+ break; /* arc was removed, move to next */
+ }
+ }
+ /* Otherwise, arcs are side by side */
+ else
+ {
+ /* Don't do anything, we need to keep the lowest node, even if degree 2 */
+ break;
+ }
+ }
+
+ // merge at v2
+ if (arc->tail->degree == 2)
+ {
+ ReebArc *connectedArc = (ReebArc*)BLI_findConnectedArc((BGraph*)rg, (BArc*)arc, (BNode*)arc->tail);
+
+ /* If arcs are one after the other */
+ if (arc->tail == connectedArc->head)
+ {
+ /* remove furthest arc */
+ if (arc->head->weight < connectedArc->tail->weight)
+ {
+ mergeConnectedArcs(rg, arc, connectedArc);
+ nextArc = arc->next;
+ }
+ else
+ {
+ mergeConnectedArcs(rg, connectedArc, arc);
+ break; /* arc was removed, move to next */
+ }
+ }
+ /* Otherwise, arcs are side by side */
+ else
+ {
+ /* Don't do anything, we need to keep the lowest node, even if degree 2 */
+ break;
+ }
+ }
+ }
+ }
+
+}
+
+int edgeEquals(ReebEdge *e1, ReebEdge *e2)
+{
+ return (e1->v1 == e2->v1 && e1->v2 == e2->v2);
+}
+
+ReebArc *nextArcMappedToEdge(ReebArc *arc, ReebEdge *e)
+{
+ ReebEdge *nextEdge = NULL;
+ ReebEdge *edge = NULL;
+ ReebArc *result = NULL;
+
+ /* Find the ReebEdge in the edge list */
+ for(edge = arc->edges.first; edge && !edgeEquals(edge, e); edge = edge->next)
+ { }
+
+ nextEdge = edge->nextEdge;
+
+ if (nextEdge != NULL)
+ {
+ result = nextEdge->arc;
+ }
+
+ return result;
+}
+
+void addFacetoArc(ReebArc *arc, EditFace *efa)
+{
+ BLI_ghash_insert(arc->faces, efa, efa);
+}
+
+void mergeArcFaces(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc)
+{
+ GHashIterator ghi;
+
+ for(BLI_ghashIterator_init(&ghi, aSrc->faces);
+ !BLI_ghashIterator_isDone(&ghi);
+ BLI_ghashIterator_step(&ghi))
+ {
+ EditFace *efa = BLI_ghashIterator_getValue(&ghi);
+ BLI_ghash_insert(aDst->faces, efa, efa);
+ }
+}
+
+void mergeArcEdges(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc, MergeDirection direction)
+{
+ ReebEdge *e = NULL;
+
+ if (direction == MERGE_APPEND)
+ {
+ for(e = aSrc->edges.first; e; e = e->next)
+ {
+ e->arc = aDst; // Edge is stolen by new arc
+ }
+
+ addlisttolist(&aDst->edges , &aSrc->edges);
+ }
+ else
+ {
+ for(e = aSrc->edges.first; e; e = e->next)
+ {
+ ReebEdge *newEdge = copyEdge(e);
+
+ newEdge->arc = aDst;
+
+ BLI_addtail(&aDst->edges, newEdge);
+
+ if (direction == MERGE_LOWER)
+ {
+ void **p = BLI_edgehash_lookup_p(rg->emap, e->v1->index, e->v2->index);
+
+ newEdge->nextEdge = e;
+
+ // if edge was the first in the list, point the edit edge to the new reeb edge instead.
+ if (*p == e)
+ {
+ *p = (void*)newEdge;
+ }
+ // otherwise, advance in the list until the predecessor is found then insert it there
+ else
+ {
+ ReebEdge *previous = (ReebEdge*)*p;
+
+ while(previous->nextEdge != e)
+ {
+ previous = previous->nextEdge;
+ }
+
+ previous->nextEdge = newEdge;
+ }
+ }
+ else
+ {
+ newEdge->nextEdge = e->nextEdge;
+ e->nextEdge = newEdge;
+ }
+ }
+ }
+}
+
+// return 1 on full merge
+int mergeConnectedArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1)
+{
+ int result = 0;
+ ReebNode *removedNode = NULL;
+
+ a0->length += a1->length;
+
+ mergeArcEdges(rg, a0, a1, MERGE_APPEND);
+ mergeArcFaces(rg, a0, a1);
+
+ // Bring a0 to the combine length of both arcs
+ if (a0->tail == a1->head)
+ {
+ removedNode = a0->tail;
+ a0->tail = a1->tail;
+ }
+ else if (a0->head == a1->tail)
+ {
+ removedNode = a0->head;
+ a0->head = a1->head;
+ }
+
+ resizeArcBuckets(a0);
+ // Merge a1 in a0
+ mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight);
+
+ // remove a1 from graph
+ BLI_remlink(&rg->arcs, a1);
+ REEB_freeArc((BArc*)a1);
+
+ BLI_removeNode((BGraph*)rg, (BNode*)removedNode);
+ result = 1;
+
+ return result;
+}
+// return 1 on full merge
+int mergeArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1)
+{
+ int result = 0;
+ // TRIANGLE POINTS DOWN
+ if (a0->head->weight == a1->head->weight) // heads are the same
+ {
+ if (a0->tail->weight == a1->tail->weight) // tails also the same, arcs can be totally merge together
+ {
+ mergeArcEdges(rg, a0, a1, MERGE_APPEND);
+ mergeArcFaces(rg, a0, a1);
+
+ mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight);
+
+ // Adjust node degree
+ //a1->head->degree--;
+ NodeDegreeDecrement(rg, a1->head);
+ //a1->tail->degree--;
+ NodeDegreeDecrement(rg, a1->tail);
+
+ // remove a1 from graph
+ BLI_remlink(&rg->arcs, a1);
+
+ REEB_freeArc((BArc*)a1);
+ result = 1;
+ }
+ else if (a0->tail->weight > a1->tail->weight) // a1->tail->weight is in the middle
+ {
+ mergeArcEdges(rg, a1, a0, MERGE_LOWER);
+ mergeArcFaces(rg, a1, a0);
+
+ // Adjust node degree
+ //a0->head->degree--;
+ NodeDegreeDecrement(rg, a0->head);
+ //a1->tail->degree++;
+ NodeDegreeIncrement(rg, a1->tail);
+
+ mergeArcBuckets(a1, a0, a1->head->weight, a1->tail->weight);
+ a0->head = a1->tail;
+ resizeArcBuckets(a0);
+ }
+ else // a0>n2 is in the middle
+ {
+ mergeArcEdges(rg, a0, a1, MERGE_LOWER);
+ mergeArcFaces(rg, a0, a1);
+
+ // Adjust node degree
+ //a1->head->degree--;
+ NodeDegreeDecrement(rg, a1->head);
+ //a0->tail->degree++;
+ NodeDegreeIncrement(rg, a0->tail);
+
+ mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight);
+ a1->head = a0->tail;
+ resizeArcBuckets(a1);
+ }
+ }
+ // TRIANGLE POINTS UP
+ else if (a0->tail->weight == a1->tail->weight) // tails are the same
+ {
+ if (a0->head->weight > a1->head->weight) // a0->head->weight is in the middle
+ {
+ mergeArcEdges(rg, a0, a1, MERGE_HIGHER);
+ mergeArcFaces(rg, a0, a1);
+
+ // Adjust node degree
+ //a1->tail->degree--;
+ NodeDegreeDecrement(rg, a1->tail);
+ //a0->head->degree++;
+ NodeDegreeIncrement(rg, a0->head);
+
+ mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight);
+ a1->tail = a0->head;
+ resizeArcBuckets(a1);
+ }
+ else // a1->head->weight is in the middle
+ {
+ mergeArcEdges(rg, a1, a0, MERGE_HIGHER);
+ mergeArcFaces(rg, a1, a0);
+
+ // Adjust node degree
+ //a0->tail->degree--;
+ NodeDegreeDecrement(rg, a0->tail);
+ //a1->head->degree++;
+ NodeDegreeIncrement(rg, a1->head);
+
+ mergeArcBuckets(a1, a0, a1->head->weight, a1->tail->weight);
+ a0->tail = a1->head;
+ resizeArcBuckets(a0);
+ }
+ }
+ else
+ {
+ // Need something here (OR NOT)
+ }
+
+ return result;
+}
+
+void glueByMergeSort(ReebGraph *rg, ReebArc *a0, ReebArc *a1, ReebEdge *e0, ReebEdge *e1)
+{
+ int total = 0;
+ while (total == 0 && a0 != a1 && a0 != NULL && a1 != NULL)
+ {
+ total = mergeArcs(rg, a0, a1);
+
+ if (total == 0) // if it wasn't a total merge, go forward
+ {
+ if (a0->tail->weight < a1->tail->weight)
+ {
+ a0 = nextArcMappedToEdge(a0, e0);
+ }
+ else
+ {
+ a1 = nextArcMappedToEdge(a1, e1);
+ }
+ }
+ }
+}
+
+void mergePaths(ReebGraph *rg, ReebEdge *e0, ReebEdge *e1, ReebEdge *e2)
+{
+ ReebArc *a0, *a1, *a2;
+ a0 = e0->arc;
+ a1 = e1->arc;
+ a2 = e2->arc;
+
+ glueByMergeSort(rg, a0, a1, e0, e1);
+ glueByMergeSort(rg, a0, a2, e0, e2);
+}
+
+ReebEdge * createArc(ReebGraph *rg, ReebNode *node1, ReebNode *node2)
+{
+ ReebEdge *edge;
+
+ edge = BLI_edgehash_lookup(rg->emap, node1->index, node2->index);
+
+ // Only add existing edges that haven't been added yet
+ if (edge == NULL)
+ {
+ ReebArc *arc;
+ ReebNode *v1, *v2;
+ float len, offset;
+ int i;
+
+ arc = MEM_callocN(sizeof(ReebArc), "reeb arc");
+ edge = MEM_callocN(sizeof(ReebEdge), "reeb edge");
+
+ arc->flag = 0; // clear flag on init
+ arc->symmetry_level = 0;
+ arc->faces = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ if (node1->weight <= node2->weight)
+ {
+ v1 = node1;
+ v2 = node2;
+ }
+ else
+ {
+ v1 = node2;
+ v2 = node1;
+ }
+
+ arc->head = v1;
+ arc->tail = v2;
+
+ // increase node degree
+ //v1->degree++;
+ NodeDegreeIncrement(rg, v1);
+ //v2->degree++;
+ NodeDegreeIncrement(rg, v2);
+
+ BLI_edgehash_insert(rg->emap, node1->index, node2->index, edge);
+
+ edge->arc = arc;
+ edge->nextEdge = NULL;
+ edge->v1 = v1;
+ edge->v2 = v2;
+
+ BLI_addtail(&rg->arcs, arc);
+ BLI_addtail(&arc->edges, edge);
+
+ /* adding buckets for embedding */
+ allocArcBuckets(arc);
+
+ offset = arc->head->weight;
+ len = arc->tail->weight - arc->head->weight;
+
+#if 0
+ /* This is the actual embedding filling described in the paper
+ * the problem is that it only works with really dense meshes
+ */
+ if (arc->bcount > 0)
+ {
+ addVertToBucket(&(arc->buckets[0]), arc->head->co);
+ addVertToBucket(&(arc->buckets[arc->bcount - 1]), arc->tail->co);
+ }
+#else
+ for(i = 0; i < arc->bcount; i++)
+ {
+ float co[3];
+ float f = (arc->buckets[i].val - offset) / len;
+
+ VecLerpf(co, v1->p, v2->p, f);
+ addVertToBucket(&(arc->buckets[i]), co);
+ }
+#endif
+
+ }
+
+ return edge;
+}
+
+void addTriangleToGraph(ReebGraph *rg, ReebNode * n1, ReebNode * n2, ReebNode * n3, EditFace *efa)
+{
+ ReebEdge *re1, *re2, *re3;
+ ReebEdge *e1, *e2, *e3;
+ float len1, len2, len3;
+
+ re1 = createArc(rg, n1, n2);
+ re2 = createArc(rg, n2, n3);
+ re3 = createArc(rg, n3, n1);
+
+ addFacetoArc(re1->arc, efa);
+ addFacetoArc(re2->arc, efa);
+ addFacetoArc(re3->arc, efa);
+
+ len1 = (float)fabs(n1->weight - n2->weight);
+ len2 = (float)fabs(n2->weight - n3->weight);
+ len3 = (float)fabs(n3->weight - n1->weight);
+
+ /* The rest of the algorithm assumes that e1 is the longest edge */
+
+ if (len1 >= len2 && len1 >= len3)
+ {
+ e1 = re1;
+ e2 = re2;
+ e3 = re3;
+ }
+ else if (len2 >= len1 && len2 >= len3)
+ {
+ e1 = re2;
+ e2 = re1;
+ e3 = re3;
+ }
+ else
+ {
+ e1 = re3;
+ e2 = re2;
+ e3 = re1;
+ }
+
+ /* And e2 is the lowest edge
+ * If e3 is lower than e2, swap them
+ */
+ if (e3->v1->weight < e2->v1->weight)
+ {
+ ReebEdge *etmp = e2;
+ e2 = e3;
+ e3 = etmp;
+ }
+
+
+ mergePaths(rg, e1, e2, e3);
+}
+
+ReebGraph * generateReebGraph(EditMesh *em, int subdivisions)
+{
+ ReebGraph *rg;
+ EditVert *eve;
+ EditFace *efa;
+ int index;
+ int totvert;
+ int totfaces;
+
+#ifdef DEBUG_REEB
+ int countfaces = 0;
+#endif
+
+ rg = newReebGraph();
+
+ rg->resolution = subdivisions;
+
+ totvert = BLI_countlist(&em->verts);
+ totfaces = BLI_countlist(&em->faces);
+
+ renormalizeWeight(em, 1.0f);
+
+ /* Spread weight to minimize errors */
+ spreadWeight(em);
+
+ renormalizeWeight(em, (float)rg->resolution);
+
+ /* Adding vertice */
+ for(index = 0, eve = em->verts.first; eve; eve = eve->next)
+ {
+ if (eve->h == 0)
+ {
+ addNode(rg, eve);
+ eve->f2 = 0;
+ index++;
+ }
+ }
+
+ /* Adding face, edge per edge */
+ for(efa = em->faces.first; efa; efa = efa->next)
+ {
+ if (efa->h == 0)
+ {
+ ReebNode *n1, *n2, *n3;
+
+ n1 = nodeData(efa->v1);
+ n2 = nodeData(efa->v2);
+ n3 = nodeData(efa->v3);
+
+ addTriangleToGraph(rg, n1, n2, n3, efa);
+
+ if (efa->v4)
+ {
+ ReebNode *n4 = nodeData(efa->v4);
+ addTriangleToGraph(rg, n1, n3, n4, efa);
+ }
+#ifdef DEBUG_REEB
+ countfaces++;
+ if (countfaces % 100 == 0)
+ {
+ printf("\rface %i of %i", countfaces, totfaces);
+ }
+#endif
+ }
+ }
+
+ printf("\n");
+
+ removeZeroNodes(rg);
+
+ removeNormalNodes(rg);
+
+ return rg;
+}
+
+/***************************************** WEIGHT UTILS **********************************************/
+
+void renormalizeWeight(EditMesh *em, float newmax)
+{
+ EditVert *eve;
+ float minimum, maximum, range;
+
+ if (em == NULL || BLI_countlist(&em->verts) == 0)
+ return;
+
+ /* First pass, determine maximum and minimum */
+ eve = em->verts.first;
+ minimum = weightData(eve);
+ maximum = minimum;
+ for(eve = em->verts.first; eve; eve = eve->next)
+ {
+ maximum = MAX2(maximum, weightData(eve));
+ minimum = MIN2(minimum, weightData(eve));
+ }
+
+ range = maximum - minimum;
+
+ /* Normalize weights */
+ for(eve = em->verts.first; eve; eve = eve->next)
+ {
+ float weight = (weightData(eve) - minimum) / range * newmax;
+ weightSetData(eve, weight);
+ }
+}
+
+
+int weightFromLoc(EditMesh *em, int axis)
+{
+ EditVert *eve;
+
+ if (em == NULL || BLI_countlist(&em->verts) == 0 || axis < 0 || axis > 2)
+ return 0;
+
+ /* Copy coordinate in weight */
+ for(eve = em->verts.first; eve; eve = eve->next)
+ {
+ weightSetData(eve, eve->co[axis]);
+ }
+
+ return 1;
+}
+
+static float cotan_weight(float *v1, float *v2, float *v3)
+{
+ float a[3], b[3], c[3], clen;
+
+ VecSubf(a, v2, v1);
+ VecSubf(b, v3, v1);
+ Crossf(c, a, b);
+
+ clen = VecLength(c);
+
+ if (clen == 0.0f)
+ return 0.0f;
+
+ return Inpf(a, b)/clen;
+}
+
+void addTriangle(EditVert *v1, EditVert *v2, EditVert *v3, long e1, long e2, long e3)
+{
+ /* Angle opposite e1 */
+ float t1= cotan_weight(v1->co, v2->co, v3->co) / e2;
+
+ /* Angle opposite e2 */
+ float t2 = cotan_weight(v2->co, v3->co, v1->co) / e3;
+
+ /* Angle opposite e3 */
+ float t3 = cotan_weight(v3->co, v1->co, v2->co) / e1;
+
+ int i1 = indexData(v1);
+ int i2 = indexData(v2);
+ int i3 = indexData(v3);
+
+ nlMatrixAdd(i1, i1, t2+t3);
+ nlMatrixAdd(i2, i2, t1+t3);
+ nlMatrixAdd(i3, i3, t1+t2);
+
+ nlMatrixAdd(i1, i2, -t3);
+ nlMatrixAdd(i2, i1, -t3);
+
+ nlMatrixAdd(i2, i3, -t1);
+ nlMatrixAdd(i3, i2, -t1);
+
+ nlMatrixAdd(i3, i1, -t2);
+ nlMatrixAdd(i1, i3, -t2);
+}
+
+int weightToHarmonic(EditMesh *em, EdgeIndex *indexed_edges)
+{
+ NLboolean success;
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+ int totvert = 0;
+ int index;
+ int rval;
+
+ /* Find local extrema */
+ for(eve = em->verts.first; eve; eve = eve->next)
+ {
+ totvert++;
+ }
+
+ /* Solve with openNL */
+
+ nlNewContext();
+
+ nlSolverParameteri(NL_NB_VARIABLES, totvert);
+
+ nlBegin(NL_SYSTEM);
+
+ /* Find local extrema */
+ for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next)
+ {
+ if (eve->h == 0)
+ {
+ EditEdge *eed;
+ int maximum = 1;
+ int minimum = 1;
+
+ NextEdgeForVert(indexed_edges, -1); /* Reset next edge */
+ for(eed = NextEdgeForVert(indexed_edges, index); eed && (maximum || minimum); eed = NextEdgeForVert(indexed_edges, index))
+ {
+ EditVert *eve2;
+
+ if (eed->v1 == eve)
+ {
+ eve2 = eed->v2;
+ }
+ else
+ {
+ eve2 = eed->v1;
+ }
+
+ if (eve2->h == 0)
+ {
+ /* Adjacent vertex is bigger, not a local maximum */
+ if (weightData(eve2) > weightData(eve))
+ {
+ maximum = 0;
+ }
+ /* Adjacent vertex is smaller, not a local minimum */
+ else if (weightData(eve2) < weightData(eve))
+ {
+ minimum = 0;
+ }
+ }
+ }
+
+ if (maximum || minimum)
+ {
+ float w = weightData(eve);
+ eve->f1 = 0;
+ nlSetVariable(0, index, w);
+ nlLockVariable(index);
+ }
+ else
+ {
+ eve->f1 = 1;
+ }
+ }
+ }
+
+ nlBegin(NL_MATRIX);
+
+ /* Zero edge weight */
+ for(eed = em->edges.first; eed; eed = eed->next)
+ {
+ eed->tmp.l = 0;
+ }
+
+ /* Add faces count to the edge weight */
+ for(efa = em->faces.first; efa; efa = efa->next)
+ {
+ if (efa->h == 0)
+ {
+ efa->e1->tmp.l++;
+ efa->e2->tmp.l++;
+ efa->e3->tmp.l++;
+
+ if (efa->e4)
+ {
+ efa->e4->tmp.l++;
+ }
+ }
+ }
+
+ /* Add faces angle to the edge weight */
+ for(efa = em->faces.first; efa; efa = efa->next)
+ {
+ if (efa->h == 0)
+ {
+ if (efa->v4 == NULL)
+ {
+ addTriangle(efa->v1, efa->v2, efa->v3, efa->e1->tmp.l, efa->e2->tmp.l, efa->e3->tmp.l);
+ }
+ else
+ {
+ addTriangle(efa->v1, efa->v2, efa->v3, efa->e1->tmp.l, efa->e2->tmp.l, 2);
+ addTriangle(efa->v3, efa->v4, efa->v1, efa->e3->tmp.l, efa->e4->tmp.l, 2);
+ }
+ }
+ }
+
+ nlEnd(NL_MATRIX);
+
+ nlEnd(NL_SYSTEM);
+
+ success = nlSolveAdvanced(NULL, NL_TRUE);
+
+ if (success)
+ {
+ rval = 1;
+ for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next)
+ {
+ weightSetData(eve, nlGetVariable(0, index));
+ }
+ }
+ else
+ {
+ rval = 0;
+ }
+
+ nlDeleteContext(nlGetCurrent());
+
+ return rval;
+}
+
+
+EditEdge * NextEdgeForVert(EdgeIndex *indexed_edges, int index)
+{
+ static int offset = -1;
+
+ /* Reset method, call with NULL mesh pointer */
+ if (index == -1)
+ {
+ offset = -1;
+ return NULL;
+ }
+
+ /* first pass, start at the head of the list */
+ if (offset == -1)
+ {
+ offset = indexed_edges->offset[index];
+ }
+ /* subsequent passes, start on the next edge */
+ else
+ {
+ offset++;
+ }
+
+ return indexed_edges->edges[offset];
+}
+
+void shortestPathsFromVert(EditMesh *em, EditVert *starting_vert, EdgeIndex *indexed_edges)
+{
+ Heap *edge_heap;
+ EditVert *current_eve = NULL;
+ EditEdge *eed = NULL;
+ EditEdge *select_eed = NULL;
+
+ edge_heap = BLI_heap_new();
+
+ current_eve = starting_vert;
+
+ /* insert guard in heap, when that is returned, no more edges */
+ BLI_heap_insert(edge_heap, FLT_MAX, NULL);
+
+ /* Initialize edge flag */
+ for(eed= em->edges.first; eed; eed= eed->next)
+ {
+ eed->f1 = 0;
+ }
+
+ while (BLI_heap_size(edge_heap) > 0)
+ {
+ float current_weight;
+
+ current_eve->f1 = 1; /* mark vertex as selected */
+
+ /* Add all new edges connected to current_eve to the list */
+ NextEdgeForVert(indexed_edges, -1); // Reset next edge
+ for(eed = NextEdgeForVert(indexed_edges, indexData(current_eve)); eed; eed = NextEdgeForVert(indexed_edges, indexData(current_eve)))
+ {
+ if (eed->f1 == 0)
+ {
+ BLI_heap_insert(edge_heap, weightData(current_eve) + eed->tmp.fp, eed);
+ eed->f1 = 1;
+ }
+ }
+
+ /* Find next shortest edge with unselected verts */
+ do
+ {
+ current_weight = BLI_heap_node_value(BLI_heap_top(edge_heap));
+ select_eed = BLI_heap_popmin(edge_heap);
+ } while (select_eed != NULL && select_eed->v1->f1 != 0 && select_eed->v2->f1);
+
+ if (select_eed != NULL)
+ {
+ select_eed->f1 = 2;
+
+ if (select_eed->v1->f1 == 0) /* v1 is the new vertex */
+ {
+ current_eve = select_eed->v1;
+ }
+ else /* otherwise, it's v2 */
+ {
+ current_eve = select_eed->v2;
+ }
+
+ weightSetData(current_eve, current_weight);
+ }
+ }
+
+ BLI_heap_free(edge_heap, NULL);
+}
+
+void freeEdgeIndex(EdgeIndex *indexed_edges)
+{
+ MEM_freeN(indexed_edges->offset);
+ MEM_freeN(indexed_edges->edges);
+}
+
+void buildIndexedEdges(EditMesh *em, EdgeIndex *indexed_edges)
+{
+ EditVert *eve;
+ EditEdge *eed;
+ int totvert = 0;
+ int tot_indexed = 0;
+ int offset = 0;
+
+ totvert = BLI_countlist(&em->verts);
+
+ indexed_edges->offset = MEM_callocN(totvert * sizeof(int), "EdgeIndex offset");
+
+ for(eed = em->edges.first; eed; eed = eed->next)
+ {
+ if (eed->v1->h == 0 && eed->v2->h == 0)
+ {
+ tot_indexed += 2;
+ indexed_edges->offset[indexData(eed->v1)]++;
+ indexed_edges->offset[indexData(eed->v2)]++;
+ }
+ }
+
+ tot_indexed += totvert;
+
+ indexed_edges->edges = MEM_callocN(tot_indexed * sizeof(EditEdge*), "EdgeIndex edges");
+
+ /* setting vert offsets */
+ for(eve = em->verts.first; eve; eve = eve->next)
+ {
+ if (eve->h == 0)
+ {
+ int d = indexed_edges->offset[indexData(eve)];
+ indexed_edges->offset[indexData(eve)] = offset;
+ offset += d + 1;
+ }
+ }
+
+ /* adding edges in array */
+ for(eed = em->edges.first; eed; eed= eed->next)
+ {
+ if (eed->v1->h == 0 && eed->v2->h == 0)
+ {
+ int i;
+ for (i = indexed_edges->offset[indexData(eed->v1)]; i < tot_indexed; i++)
+ {
+ if (indexed_edges->edges[i] == NULL)
+ {
+ indexed_edges->edges[i] = eed;
+ break;
+ }
+ }
+
+ for (i = indexed_edges->offset[indexData(eed->v2)]; i < tot_indexed; i++)
+ {
+ if (indexed_edges->edges[i] == NULL)
+ {
+ indexed_edges->edges[i] = eed;
+ break;
+ }
+ }
+ }
+ }
+}
+
+int weightFromDistance(EditMesh *em, EdgeIndex *indexed_edges)
+{
+ EditVert *eve;
+ int totedge = 0;
+ int totvert = 0;
+ int vCount = 0;
+
+ totvert = BLI_countlist(&em->verts);
+
+ if (em == NULL || totvert == 0)
+ {
+ return 0;
+ }
+
+ totedge = BLI_countlist(&em->edges);
+
+ if (totedge == 0)
+ {
+ return 0;
+ }
+
+ /* Initialize vertice flag and find at least one selected vertex */
+ for(eve = em->verts.first; eve; eve = eve->next)
+ {
+ eve->f1 = 0;
+ if (eve->f & SELECT)
+ {
+ vCount = 1;
+ }
+ }
+
+ if (vCount == 0)
+ {
+ return 0; /* no selected vert, failure */
+ }
+ else
+ {
+ EditEdge *eed;
+ int allDone = 0;
+
+ /* Calculate edge weight */
+ for(eed = em->edges.first; eed; eed= eed->next)
+ {
+ if (eed->v1->h == 0 && eed->v2->h == 0)
+ {
+ eed->tmp.fp = VecLenf(eed->v1->co, eed->v2->co);
+ }
+ }
+
+ /* Apply dijkstra spf for each selected vert */
+ for(eve = em->verts.first; eve; eve = eve->next)
+ {
+ if (eve->f & SELECT)
+ {
+ shortestPathsFromVert(em, eve, indexed_edges);
+ }
+ }
+
+ /* connect unselected islands */
+ while (allDone == 0)
+ {
+ EditVert *selected_eve = NULL;
+ float selected_weight = 0;
+ float min_distance = FLT_MAX;
+
+ allDone = 1;
+
+ for (eve = em->verts.first; eve; eve = eve->next)
+ {
+ /* for every vertex visible that hasn't been processed yet */
+ if (eve->h == 0 && eve->f1 != 1)
+ {
+ EditVert *closest_eve;
+
+ /* find the closest processed vertex */
+ for (closest_eve = em->verts.first; closest_eve; closest_eve = closest_eve->next)
+ {
+ /* vertex is already processed and distance is smaller than current minimum */
+ if (closest_eve->f1 == 1)
+ {
+ float distance = VecLenf(closest_eve->co, eve->co);
+ if (distance < min_distance)
+ {
+ min_distance = distance;
+ selected_eve = eve;
+ selected_weight = weightData(closest_eve);
+ }
+ }
+ }
+ }
+ }
+
+ if (selected_eve)
+ {
+ allDone = 0;
+
+ weightSetData(selected_eve, selected_weight + min_distance);
+ shortestPathsFromVert(em, selected_eve, indexed_edges);
+ }
+ }
+ }
+
+ for(eve = em->verts.first; eve && vCount == 0; eve = eve->next)
+ {
+ if (eve->f1 == 0)
+ {
+ printf("vertex not reached\n");
+ break;
+ }
+ }
+
+ return 1;
+}
+
+/****************************************** BUCKET ITERATOR **************************************************/
+
+static void* headNode(void *arg);
+static void* tailNode(void *arg);
+static void* nextBucket(void *arg);
+static void* nextNBucket(void *arg, int n);
+static void* peekBucket(void *arg, int n);
+static void* previousBucket(void *arg);
+static int iteratorStopped(void *arg);
+
+static void initIteratorFct(ReebArcIterator *iter)
+{
+ iter->head = headNode;
+ iter->tail = tailNode;
+ iter->peek = peekBucket;
+ iter->next = nextBucket;
+ iter->nextN = nextNBucket;
+ iter->previous = previousBucket;
+ iter->stopped = iteratorStopped;
+}
+
+static void setIteratorValues(ReebArcIterator *iter, EmbedBucket *bucket)
+{
+ if (bucket)
+ {
+ iter->p = bucket->p;
+ iter->no = bucket->no;
+ }
+ else
+ {
+ iter->p = NULL;
+ iter->no = NULL;
+ }
+}
+
+void initArcIterator(BArcIterator *arg, ReebArc *arc, ReebNode *head)
+{
+ ReebArcIterator *iter = (ReebArcIterator*)arg;
+
+ initIteratorFct(iter);
+ iter->arc = arc;
+
+ if (head == arc->head)
+ {
+ iter->start = 0;
+ iter->end = arc->bcount - 1;
+ iter->stride = 1;
+ }
+ else
+ {
+ iter->start = arc->bcount - 1;
+ iter->end = 0;
+ iter->stride = -1;
+ }
+
+ iter->length = arc->bcount;
+
+ iter->index = -1;
+}
+
+void initArcIteratorStart(BArcIterator *arg, struct ReebArc *arc, struct ReebNode *head, int start)
+{
+ ReebArcIterator *iter = (ReebArcIterator*)arg;
+
+ initIteratorFct(iter);
+ iter->arc = arc;
+
+ if (head == arc->head)
+ {
+ iter->start = start;
+ iter->end = arc->bcount - 1;
+ iter->stride = 1;
+ }
+ else
+ {
+ iter->start = arc->bcount - 1 - start;
+ iter->end = 0;
+ iter->stride = -1;
+ }
+
+ iter->index = -1;
+
+ iter->length = arc->bcount - start;
+
+ if (start >= arc->bcount)
+ {
+ iter->start = iter->end; /* stop iterator since it's past its end */
+ }
+}
+
+void initArcIterator2(BArcIterator *arg, ReebArc *arc, int start, int end)
+{
+ ReebArcIterator *iter = (ReebArcIterator*)arg;
+
+ initIteratorFct(iter);
+ iter->arc = arc;
+
+ iter->start = start;
+ iter->end = end;
+
+ if (end > start)
+ {
+ iter->stride = 1;
+ }
+ else
+ {
+ iter->stride = -1;
+ }
+
+ iter->index = -1;
+
+ iter->length = abs(iter->end - iter->start) + 1;
+}
+
+static void* headNode(void *arg)
+{
+ ReebArcIterator *iter = (ReebArcIterator*)arg;
+ ReebNode *node;
+
+ if (iter->start < iter->end)
+ {
+ node = iter->arc->head;
+ }
+ else
+ {
+ node = iter->arc->tail;
+ }
+
+ iter->p = node->p;
+ iter->no = node->no;
+
+ return node;
+}
+
+static void* tailNode(void *arg)
+{
+ ReebArcIterator *iter = (ReebArcIterator*)arg;
+ ReebNode *node;
+
+ if (iter->start < iter->end)
+ {
+ node = iter->arc->tail;
+ }
+ else
+ {
+ node = iter->arc->head;
+ }
+
+ iter->p = node->p;
+ iter->no = node->no;
+
+ return node;
+}
+
+static void* nextBucket(void *arg)
+{
+ ReebArcIterator *iter = (ReebArcIterator*)arg;
+ EmbedBucket *result = NULL;
+
+ iter->index++;
+
+ if (iter->index < iter->length)
+ {
+ result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]);
+ }
+
+ setIteratorValues(iter, result);
+ return result;
+}
+
+static void* nextNBucket(void *arg, int n)
+{
+ ReebArcIterator *iter = (ReebArcIterator*)arg;
+ EmbedBucket *result = NULL;
+
+ iter->index += n;
+
+ /* check if passed end */
+ if (iter->index < iter->length)
+ {
+ result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]);
+ }
+
+ setIteratorValues(iter, result);
+ return result;
+}
+
+static void* peekBucket(void *arg, int n)
+{
+ ReebArcIterator *iter = (ReebArcIterator*)arg;
+ EmbedBucket *result = NULL;
+ int index = iter->index + n;
+
+ /* check if passed end */
+ if (index < iter->length)
+ {
+ result = &(iter->arc->buckets[iter->start + (iter->stride * index)]);
+ }
+
+ setIteratorValues(iter, result);
+ return result;
+}
+
+static void* previousBucket(void *arg)
+{
+ ReebArcIterator *iter = (ReebArcIterator*)arg;
+ EmbedBucket *result = NULL;
+
+ if (iter->index > 0)
+ {
+ iter->index--;
+ result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]);
+ }
+
+ setIteratorValues(iter, result);
+ return result;
+}
+
+static int iteratorStopped(void *arg)
+{
+ ReebArcIterator *iter = (ReebArcIterator*)arg;
+
+ if (iter->index >= iter->length)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/************************ PUBLIC FUNCTIONS *********************************************/
+
+ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ EditMesh *em =( (Mesh*)obedit->data)->edit_mesh;
+ EdgeIndex indexed_edges;
+ VertexData *data;
+ ReebGraph *rg = NULL;
+ ReebGraph *rgi, *previous;
+ int i, nb_levels = REEB_MAX_MULTI_LEVEL;
+
+ if (em == NULL)
+ return NULL;
+
+ data = allocVertexData(em);
+
+ buildIndexedEdges(em, &indexed_edges);
+
+ if (weightFromDistance(em, &indexed_edges) == 0)
+ {
+ // XXX error("No selected vertex\n");
+ freeEdgeIndex(&indexed_edges);
+ return NULL;
+ }
+
+ renormalizeWeight(em, 1.0f);
+
+ if (scene->toolsettings->skgen_options & SKGEN_HARMONIC)
+ {
+ weightToHarmonic(em, &indexed_edges);
+ }
+
+ freeEdgeIndex(&indexed_edges);
+
+ rg = generateReebGraph(em, scene->toolsettings->skgen_resolution);
+
+ /* Remove arcs without embedding */
+ filterNullReebGraph(rg);
+
+ /* smart filter and loop filter on basic level */
+ filterGraph(rg, SKGEN_FILTER_SMART, 0, 0);
+
+ repositionNodes(rg);
+
+ /* Filtering might have created degree 2 nodes, so remove them */
+ removeNormalNodes(rg);
+
+ joinSubgraphs(rg, 1.0);
+
+ BLI_buildAdjacencyList((BGraph*)rg);
+
+ /* calc length before copy, so we have same length on all levels */
+ BLI_calcGraphLength((BGraph*)rg);
+
+ previous = NULL;
+ for (i = 0; i <= nb_levels; i++)
+ {
+ rgi = rg;
+
+ /* don't filter last level */
+ if (i > 0)
+ {
+ float internal_threshold;
+ float external_threshold;
+
+ /* filter internal progressively in second half only*/
+ if (i > nb_levels / 2)
+ {
+ internal_threshold = rg->length * scene->toolsettings->skgen_threshold_internal;
+ }
+ else
+ {
+ internal_threshold = rg->length * scene->toolsettings->skgen_threshold_internal * (2 * i / (float)nb_levels);
+ }
+
+ external_threshold = rg->length * scene->toolsettings->skgen_threshold_external * (i / (float)nb_levels);
+
+ filterGraph(rgi, scene->toolsettings->skgen_options, internal_threshold, external_threshold);
+ }
+
+ if (i < nb_levels)
+ {
+ rg = copyReebGraph(rgi, i + 1);
+ }
+
+ finalizeGraph(rgi, scene->toolsettings->skgen_postpro_passes, scene->toolsettings->skgen_postpro);
+
+ BLI_markdownSymmetry((BGraph*)rgi, rgi->nodes.first, scene->toolsettings->skgen_symmetry_limit);
+
+ if (previous != NULL)
+ {
+ relinkNodes(rgi, previous);
+ }
+ previous = rgi;
+ }
+
+ verifyMultiResolutionLinks(rg, 0);
+
+ MEM_freeN(data);
+
+ return rg;
+}
+
+#if 0
+
+ReebGraph *BIF_ReebGraphFromEditMesh(void)
+{
+ EditMesh *em = G.editMesh;
+ EdgeIndex indexed_edges;
+ VertexData *data;
+ ReebGraph *rg = NULL;
+
+ if (em == NULL)
+ return NULL;
+
+ data = allocVertexData(em);
+
+ buildIndexedEdges(em, &indexed_edges);
+
+ if (weightFromDistance(em, &indexed_edges) == 0)
+ {
+ error("No selected vertex\n");
+ freeEdgeIndex(&indexed_edges);
+ freeEdgeIndex(&indexed_edges);
+ return NULL;
+ }
+
+ renormalizeWeight(em, 1.0f);
+
+ if (G.scene->toolsettings->skgen_options & SKGEN_HARMONIC)
+ {
+ weightToHarmonic(em, &indexed_edges);
+ }
+
+ freeEdgeIndex(&indexed_edges);
+
+#ifdef DEBUG_REEB
+ weightToVCol(em, 1);
+#endif
+
+ rg = generateReebGraph(em, G.scene->toolsettings->skgen_resolution);
+
+
+ /* Remove arcs without embedding */
+ filterNullReebGraph(rg);
+
+ /* smart filter and loop filter on basic level */
+ filterGraph(rg, SKGEN_FILTER_SMART, 0, 0);
+
+ repositionNodes(rg);
+
+ /* Filtering might have created degree 2 nodes, so remove them */
+ removeNormalNodes(rg);
+
+ joinSubgraphs(rg, 1.0);
+
+ BLI_buildAdjacencyList((BGraph*)rg);
+
+ /* calc length before copy, so we have same length on all levels */
+ BLI_calcGraphLength((BGraph*)rg);
+
+ filterGraph(rg, G.scene->toolsettings->skgen_options, G.scene->toolsettings->skgen_threshold_internal, G.scene->toolsettings->skgen_threshold_external);
+
+ finalizeGraph(rg, G.scene->toolsettings->skgen_postpro_passes, G.scene->toolsettings->skgen_postpro);
+
+#ifdef DEBUG_REEB
+ REEB_exportGraph(rg, -1);
+
+ arcToVCol(rg, em, 0);
+ //angleToVCol(em, 1);
+#endif
+
+ printf("DONE\n");
+ printf("%i subgraphs\n", BLI_FlagSubgraphs((BGraph*)rg));
+
+ MEM_freeN(data);
+
+ return rg;
+}
+
+void BIF_GlobalReebFree()
+{
+ if (GLOBAL_RG != NULL)
+ {
+ REEB_freeGraph(GLOBAL_RG);
+ GLOBAL_RG = NULL;
+ }
+}
+
+void BIF_GlobalReebGraphFromEditMesh(void)
+{
+ ReebGraph *rg;
+
+ BIF_GlobalReebFree();
+
+ rg = BIF_ReebGraphMultiFromEditMesh();
+
+ GLOBAL_RG = rg;
+}
+
+void REEB_draw()
+{
+ ReebGraph *rg;
+ ReebArc *arc;
+ int i = 0;
+
+ if (GLOBAL_RG == NULL)
+ {
+ return;
+ }
+
+ if (GLOBAL_RG->link_up && G.scene->toolsettings->skgen_options & SKGEN_DISP_ORIG)
+ {
+ for (rg = GLOBAL_RG; rg->link_up; rg = rg->link_up) ;
+ }
+ else
+ {
+ i = G.scene->toolsettings->skgen_multi_level;
+
+ for (rg = GLOBAL_RG; rg->multi_level != i && rg->link_up; rg = rg->link_up) ;
+ }
+
+ glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
+
+ glDisable(GL_DEPTH_TEST);
+ for (arc = rg->arcs.first; arc; arc = arc->next, i++)
+ {
+ ReebArcIterator arc_iter;
+ BArcIterator *iter = (BArcIterator*)&arc_iter;
+ float vec[3];
+ char text[128];
+ char *s = text;
+
+ glLineWidth(BIF_GetThemeValuef(TH_VERTEX_SIZE) + 2);
+ glColor3f(0, 0, 0);
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(arc->head->p);
+
+ if (arc->bcount)
+ {
+ initArcIterator(iter, arc, arc->head);
+ for (IT_next(iter); IT_stopped(iter) == 0; IT_next(iter))
+ {
+ glVertex3fv(iter->p);
+ }
+ }
+
+ glVertex3fv(arc->tail->p);
+ glEnd();
+
+ glLineWidth(BIF_GetThemeValuef(TH_VERTEX_SIZE));
+
+ if (arc->symmetry_level == 1)
+ {
+ glColor3f(1, 0, 0);
+ }
+ else if (arc->symmetry_flag == SYM_SIDE_POSITIVE || arc->symmetry_flag == SYM_SIDE_NEGATIVE)
+ {
+ glColor3f(1, 0.5f, 0);
+ }
+ else if (arc->symmetry_flag >= SYM_SIDE_RADIAL)
+ {
+ glColor3f(0.5f, 1, 0);
+ }
+ else
+ {
+ glColor3f(1, 1, 0);
+ }
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(arc->head->p);
+
+ if (arc->bcount)
+ {
+ initArcIterator(iter, arc, arc->head);
+ for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter))
+ {
+ glVertex3fv(iter->p);
+ }
+ }
+
+ glVertex3fv(arc->tail->p);
+ glEnd();
+
+
+ if (G.scene->toolsettings->skgen_options & SKGEN_DISP_EMBED)
+ {
+ glColor3f(1, 1, 1);
+ glBegin(GL_POINTS);
+ glVertex3fv(arc->head->p);
+ glVertex3fv(arc->tail->p);
+
+ glColor3f(0.5f, 0.5f, 1);
+ if (arc->bcount)
+ {
+ initArcIterator(iter, arc, arc->head);
+ for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter))
+ {
+ glVertex3fv(iter->p);
+ }
+ }
+ glEnd();
+ }
+
+ if (G.scene->toolsettings->skgen_options & SKGEN_DISP_INDEX)
+ {
+ VecLerpf(vec, arc->head->p, arc->tail->p, 0.5f);
+ s += sprintf(s, "%i (%i-%i-%i) ", i, arc->symmetry_level, arc->symmetry_flag, arc->symmetry_group);
+
+ if (G.scene->toolsettings->skgen_options & SKGEN_DISP_WEIGHT)
+ {
+ s += sprintf(s, "w:%0.3f ", arc->tail->weight - arc->head->weight);
+ }
+
+ if (G.scene->toolsettings->skgen_options & SKGEN_DISP_LENGTH)
+ {
+ s += sprintf(s, "l:%0.3f", arc->length);
+ }
+
+ glColor3f(0, 1, 0);
+ glRasterPos3fv(vec);
+ BMF_DrawString( G.fonts, text);
+ }
+
+ if (G.scene->toolsettings->skgen_options & SKGEN_DISP_INDEX)
+ {
+ sprintf(text, " %i", arc->head->index);
+ glRasterPos3fv(arc->head->p);
+ BMF_DrawString( G.fonts, text);
+
+ sprintf(text, " %i", arc->tail->index);
+ glRasterPos3fv(arc->tail->p);
+ BMF_DrawString( G.fonts, text);
+ }
+ }
+ glEnable(GL_DEPTH_TEST);
+
+ glLineWidth(1.0);
+ glPointSize(1.0);
+}
+
+#endif
diff --git a/source/blender/editors/armature/reeb.h b/source/blender/editors/armature/reeb.h
new file mode 100644
index 00000000000..3bdd55509ad
--- /dev/null
+++ b/source/blender/editors/armature/reeb.h
@@ -0,0 +1,200 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Martin Poirier
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef REEB_H_
+#define REEB_H_
+
+#define WITH_BF_REEB
+
+#include "DNA_listBase.h"
+
+#include "BLI_graph.h"
+
+struct GHash;
+struct EdgeHash;
+struct ReebArc;
+struct ReebEdge;
+struct ReebNode;
+
+typedef struct ReebGraph {
+ ListBase arcs;
+ ListBase nodes;
+
+ float length;
+
+ FreeArc free_arc;
+ FreeNode free_node;
+ RadialSymmetry radial_symmetry;
+ AxialSymmetry axial_symmetry;
+ /*********************************/
+
+ int resolution;
+ int totnodes;
+ struct EdgeHash *emap;
+ int multi_level;
+ struct ReebGraph *link_up; /* for multi resolution filtering, points to higher levels */
+} ReebGraph;
+
+typedef struct EmbedBucket {
+ float val;
+ int nv;
+ float p[3];
+ float no[3]; /* if non-null, normal of the bucket */
+} EmbedBucket;
+
+typedef struct ReebNode {
+ void *next, *prev;
+ float p[3];
+ int flag;
+
+ int degree;
+ struct ReebArc **arcs;
+
+ int subgraph_index;
+
+ int symmetry_level;
+ int symmetry_flag;
+ float symmetry_axis[3];
+ /*********************************/
+
+ float no[3];
+
+ int index;
+ float weight;
+ int multi_level;
+ struct ReebNode *link_down; /* for multi resolution filtering, points to lower levels, if present */
+ struct ReebNode *link_up;
+} ReebNode;
+
+typedef struct ReebEdge {
+ struct ReebEdge *next, *prev;
+ struct ReebArc *arc;
+ struct ReebNode *v1, *v2;
+ struct ReebEdge *nextEdge;
+ int flag;
+} ReebEdge;
+
+typedef struct ReebArc {
+ void *next, *prev;
+ struct ReebNode *head, *tail;
+ int flag;
+
+ float length;
+
+ int symmetry_level;
+ int symmetry_group;
+ int symmetry_flag;
+ /*********************************/
+
+ ListBase edges;
+ int bcount;
+ struct EmbedBucket *buckets;
+
+ struct GHash *faces;
+ float angle;
+ struct ReebArc *link_up; /* for multi resolution filtering, points to higher levels */
+} ReebArc;
+
+typedef struct ReebArcIterator {
+ HeadFct head;
+ TailFct tail;
+ PeekFct peek;
+ NextFct next;
+ NextNFct nextN;
+ PreviousFct previous;
+ StoppedFct stopped;
+
+ float *p, *no;
+
+ int length;
+ int index;
+ /*********************************/
+ struct ReebArc *arc;
+ int start;
+ int end;
+ int stride;
+} ReebArcIterator;
+
+struct EditMesh;
+struct EdgeIndex;
+
+int weightToHarmonic(struct EditMesh *em, struct EdgeIndex *indexed_edges);
+int weightFromDistance(struct EditMesh *em, struct EdgeIndex *indexed_edges);
+int weightFromLoc(struct EditMesh *me, int axis);
+void weightToVCol(struct EditMesh *em, int index);
+void arcToVCol(struct ReebGraph *rg, struct EditMesh *em, int index);
+void angleToVCol(struct EditMesh *em, int index);
+void renormalizeWeight(struct EditMesh *em, float newmax);
+
+ReebGraph * generateReebGraph(struct EditMesh *me, int subdivisions);
+ReebGraph * newReebGraph();
+
+void initArcIterator(BArcIterator *iter, struct ReebArc *arc, struct ReebNode *head);
+void initArcIterator2(BArcIterator *iter, struct ReebArc *arc, int start, int end);
+void initArcIteratorStart(BArcIterator *iter, struct ReebArc *arc, struct ReebNode *head, int start);
+
+/* Filtering */
+void filterNullReebGraph(ReebGraph *rg);
+int filterSmartReebGraph(ReebGraph *rg, float threshold);
+int filterExternalReebGraph(ReebGraph *rg, float threshold);
+int filterInternalReebGraph(ReebGraph *rg, float threshold);
+
+/* Post-Build processing */
+void repositionNodes(ReebGraph *rg);
+void postprocessGraph(ReebGraph *rg, char mode);
+void removeNormalNodes(ReebGraph *rg);
+
+void sortNodes(ReebGraph *rg);
+void sortArcs(ReebGraph *rg);
+
+/*------------ Sanity check ------------*/
+void verifyBuckets(ReebGraph *rg);
+void verifyFaces(ReebGraph *rg);
+
+/*********************** PUBLIC *********************************/
+
+#define REEB_MAX_MULTI_LEVEL 10
+
+struct bContext;
+
+ReebGraph *BIF_ReebGraphFromEditMesh(void);
+ReebGraph *BIF_ReebGraphMultiFromEditMesh(struct bContext *C);
+void BIF_flagMultiArcs(ReebGraph *rg, int flag);
+
+void BIF_GlobalReebGraphFromEditMesh(void);
+void BIF_GlobalReebFree(void);
+
+ReebNode *BIF_otherNodeFromIndex(ReebArc *arc, ReebNode *node);
+ReebNode *BIF_NodeFromIndex(ReebArc *arc, ReebNode *node);
+ReebNode *BIF_lowestLevelNode(ReebNode *node);
+
+ReebGraph *BIF_graphForMultiNode(ReebGraph *rg, ReebNode *node);
+
+void REEB_freeGraph(ReebGraph *rg);
+void REEB_freeArc(BArc *barc);
+void REEB_exportGraph(ReebGraph *rg, int count);
+void REEB_draw();
+
+
+#endif /*REEB_H_*/
diff --git a/source/blender/editors/curve/Makefile b/source/blender/editors/curve/Makefile
new file mode 100644
index 00000000000..b27749ce6fd
--- /dev/null
+++ b/source/blender/editors/curve/Makefile
@@ -0,0 +1,57 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_curve
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+CPPFLAGS += -I$(NAN_BMFONT)/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I$(NAN_ELBEEM)/include
+
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../gpu
+CPPFLAGS += -I../../render/extern/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/curve/SConscript b/source/blender/editors/curve/SConscript
new file mode 100644
index 00000000000..92c982db611
--- /dev/null
+++ b/source/blender/editors/curve/SConscript
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' #/intern/guardedalloc #intern/bmfont ../../gpu'
+incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
+
+env.BlenderLib ( 'bf_editors_curve', sources, Split(incs), [], libtype=['core'], priority=[45] )
diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h
new file mode 100644
index 00000000000..a73a54323ee
--- /dev/null
+++ b/source/blender/editors/curve/curve_intern.h
@@ -0,0 +1,109 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_CURVE_INTERN_H
+#define ED_CURVE_INTERN_H
+
+/* internal exports only */
+struct wmOperatorType;
+
+/* lorem.c */
+char *ED_lorem;
+
+/* editfont.c */
+enum { DEL_ALL, DEL_NEXT_CHAR, DEL_PREV_CHAR, DEL_SELECTION, DEL_NEXT_SEL, DEL_PREV_SEL };
+enum { CASE_LOWER, CASE_UPPER };
+enum { LINE_BEGIN, LINE_END, PREV_CHAR, NEXT_CHAR, PREV_WORD, NEXT_WORD,
+ PREV_LINE, NEXT_LINE, PREV_PAGE, NEXT_PAGE };
+
+void FONT_OT_text_insert(struct wmOperatorType *ot);
+void FONT_OT_line_break(struct wmOperatorType *ot);
+void FONT_OT_insert_lorem(struct wmOperatorType *ot);
+
+void FONT_OT_case_toggle(struct wmOperatorType *ot);
+void FONT_OT_case_set(struct wmOperatorType *ot);
+void FONT_OT_style_toggle(struct wmOperatorType *ot);
+void FONT_OT_style_set(struct wmOperatorType *ot);
+void FONT_OT_material_set(struct wmOperatorType *ot);
+
+void FONT_OT_text_copy(struct wmOperatorType *ot);
+void FONT_OT_text_cut(struct wmOperatorType *ot);
+void FONT_OT_text_paste(struct wmOperatorType *ot);
+void FONT_OT_file_paste(struct wmOperatorType *ot);
+void FONT_OT_buffer_paste(struct wmOperatorType *ot);
+
+void FONT_OT_move(struct wmOperatorType *ot);
+void FONT_OT_move_select(struct wmOperatorType *ot);
+void FONT_OT_delete(struct wmOperatorType *ot);
+
+void FONT_OT_change_character(struct wmOperatorType *ot);
+void FONT_OT_change_spacing(struct wmOperatorType *ot);
+
+/* editcurve.c */
+void CURVE_OT_hide(struct wmOperatorType *ot);
+void CURVE_OT_reveal(struct wmOperatorType *ot);
+
+void CURVE_OT_separate(struct wmOperatorType *ot);
+void CURVE_OT_duplicate(struct wmOperatorType *ot);
+void CURVE_OT_delete(struct wmOperatorType *ot);
+
+void CURVE_OT_spline_type_set(struct wmOperatorType *ot);
+void CURVE_OT_radius_set(struct wmOperatorType *ot);
+void CURVE_OT_spline_weight_set(struct wmOperatorType *ot);
+void CURVE_OT_handle_type_set(struct wmOperatorType *ot);
+void CURVE_OT_smooth_set(struct wmOperatorType *ot);
+void CURVE_OT_tilt_clear(struct wmOperatorType *ot);
+
+void CURVE_OT_smooth(struct wmOperatorType *ot);
+void CURVE_OT_smooth_radius(struct wmOperatorType *ot);
+
+void CURVE_OT_de_select_first(struct wmOperatorType *ot);
+void CURVE_OT_de_select_last(struct wmOperatorType *ot);
+void CURVE_OT_select_all_toggle(struct wmOperatorType *ot);
+void CURVE_OT_select_invert(struct wmOperatorType *ot);
+void CURVE_OT_select_linked(struct wmOperatorType *ot);
+void CURVE_OT_select_row(struct wmOperatorType *ot);
+void CURVE_OT_select_next(struct wmOperatorType *ot);
+void CURVE_OT_select_previous(struct wmOperatorType *ot);
+void CURVE_OT_select_more(struct wmOperatorType *ot);
+void CURVE_OT_select_less(struct wmOperatorType *ot);
+void CURVE_OT_select_random(struct wmOperatorType *ot);
+void CURVE_OT_select_every_nth(struct wmOperatorType *ot);
+
+void CURVE_OT_switch_direction(struct wmOperatorType *ot);
+void CURVE_OT_subdivide(struct wmOperatorType *ot);
+void CURVE_OT_make_segment(struct wmOperatorType *ot);
+void CURVE_OT_spin(struct wmOperatorType *ot);
+void CURVE_OT_vertex_add(struct wmOperatorType *ot);
+void CURVE_OT_extrude(struct wmOperatorType *ot);
+void CURVE_OT_cyclic_toggle(struct wmOperatorType *ot);
+
+void CURVE_OT_specials_menu(struct wmOperatorType *ot);
+
+#endif /* ED_UTIL_INTERN_H */
+
diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c
new file mode 100644
index 00000000000..c27c498f55e
--- /dev/null
+++ b/source/blender/editors/curve/curve_ops.c
@@ -0,0 +1,243 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_object.h"
+
+#include "BIF_transform.h"
+
+#include "UI_interface.h"
+
+#include "curve_intern.h"
+
+
+/**************************** menus *****************************/
+
+static int specials_menu_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ uiMenuItem *head;
+
+ head= uiPupMenuBegin("Specials", 0);
+ uiMenuItemO(head, 0, "CURVE_OT_subdivide");
+ uiMenuItemO(head, 0, "CURVE_OT_switch_direction");
+ uiMenuItemO(head, 0, "CURVE_OT_spline_weight_set");
+ uiMenuItemO(head, 0, "CURVE_OT_radius_set");
+ uiMenuItemO(head, 0, "CURVE_OT_smooth");
+ uiMenuItemO(head, 0, "CURVE_OT_smooth_radius");
+ uiPupMenuEnd(C, head);
+
+ return OPERATOR_CANCELLED;
+}
+
+void CURVE_OT_specials_menu(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Specials Menu";
+ ot->idname= "CURVE_OT_specials_menu";
+
+ /* api clastbacks */
+ ot->invoke= specials_menu_invoke;
+ ot->poll= ED_operator_editsurfcurve;
+}
+
+/************************* registration ****************************/
+
+void ED_operatortypes_curve(void)
+{
+ WM_operatortype_append(FONT_OT_text_insert);
+ WM_operatortype_append(FONT_OT_line_break);
+ WM_operatortype_append(FONT_OT_insert_lorem);
+
+ WM_operatortype_append(FONT_OT_case_toggle);
+ WM_operatortype_append(FONT_OT_case_set);
+ WM_operatortype_append(FONT_OT_style_toggle);
+ WM_operatortype_append(FONT_OT_style_set);
+ WM_operatortype_append(FONT_OT_material_set);
+
+ WM_operatortype_append(FONT_OT_text_copy);
+ WM_operatortype_append(FONT_OT_text_cut);
+ WM_operatortype_append(FONT_OT_text_paste);
+ WM_operatortype_append(FONT_OT_file_paste);
+ WM_operatortype_append(FONT_OT_buffer_paste);
+
+ WM_operatortype_append(FONT_OT_move);
+ WM_operatortype_append(FONT_OT_move_select);
+ WM_operatortype_append(FONT_OT_delete);
+
+ WM_operatortype_append(FONT_OT_change_character);
+ WM_operatortype_append(FONT_OT_change_spacing);
+
+ WM_operatortype_append(CURVE_OT_hide);
+ WM_operatortype_append(CURVE_OT_reveal);
+
+ WM_operatortype_append(CURVE_OT_separate);
+ WM_operatortype_append(CURVE_OT_duplicate);
+ WM_operatortype_append(CURVE_OT_delete);
+
+ WM_operatortype_append(CURVE_OT_spline_type_set);
+ WM_operatortype_append(CURVE_OT_radius_set);
+ WM_operatortype_append(CURVE_OT_spline_weight_set);
+ WM_operatortype_append(CURVE_OT_handle_type_set);
+ WM_operatortype_append(CURVE_OT_smooth_set);
+ WM_operatortype_append(CURVE_OT_tilt_clear);
+
+ WM_operatortype_append(CURVE_OT_smooth);
+ WM_operatortype_append(CURVE_OT_smooth_radius);
+
+ WM_operatortype_append(CURVE_OT_de_select_first);
+ WM_operatortype_append(CURVE_OT_de_select_last);
+ WM_operatortype_append(CURVE_OT_select_all_toggle);
+ WM_operatortype_append(CURVE_OT_select_invert);
+ WM_operatortype_append(CURVE_OT_select_linked);
+ WM_operatortype_append(CURVE_OT_select_row);
+ WM_operatortype_append(CURVE_OT_select_next);
+ WM_operatortype_append(CURVE_OT_select_previous);
+ WM_operatortype_append(CURVE_OT_select_more);
+ WM_operatortype_append(CURVE_OT_select_less);
+ WM_operatortype_append(CURVE_OT_select_random);
+ WM_operatortype_append(CURVE_OT_select_every_nth);
+
+ WM_operatortype_append(CURVE_OT_switch_direction);
+ WM_operatortype_append(CURVE_OT_subdivide);
+ WM_operatortype_append(CURVE_OT_make_segment);
+ WM_operatortype_append(CURVE_OT_spin);
+ WM_operatortype_append(CURVE_OT_vertex_add);
+ WM_operatortype_append(CURVE_OT_extrude);
+ WM_operatortype_append(CURVE_OT_cyclic_toggle);
+
+ WM_operatortype_append(CURVE_OT_specials_menu);
+}
+
+void ED_keymap_curve(wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "Font", 0, 0);
+
+ /* only set in editmode font, by space_view3d listener */
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_style_toggle", BKEY, KM_PRESS, KM_CTRL, 0)->ptr, "style", CU_BOLD);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_style_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "style", CU_ITALIC);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_style_toggle", UKEY, KM_PRESS, KM_CTRL, 0)->ptr, "style", CU_UNDERLINE);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_delete", DELKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_NEXT_SEL);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_delete", BACKSPACEKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_PREV_SEL);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_delete", BACKSPACEKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_ALL);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", HOMEKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_BEGIN);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", ENDKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_END);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_CHAR);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_CHAR);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", PREV_WORD);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", NEXT_WORD);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_LINE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_LINE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", PAGEUPKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_PAGE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", PAGEDOWNKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_PAGE);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", HOMEKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", LINE_BEGIN);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", ENDKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", LINE_END);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", LEFTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", PREV_CHAR);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", RIGHTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", NEXT_CHAR);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", LEFTARROWKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0)->ptr, "type", PREV_WORD);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", RIGHTARROWKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0)->ptr, "type", NEXT_WORD);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", UPARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", PREV_LINE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", DOWNARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", NEXT_LINE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", PAGEUPKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", PREV_PAGE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", NEXT_PAGE);
+
+ RNA_int_set(WM_keymap_add_item(keymap, "FONT_OT_change_spacing", LEFTARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "delta", -1);
+ RNA_int_set(WM_keymap_add_item(keymap, "FONT_OT_change_spacing", RIGHTARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "delta", 1);
+ RNA_int_set(WM_keymap_add_item(keymap, "FONT_OT_change_character", UPARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "delta", 1);
+ RNA_int_set(WM_keymap_add_item(keymap, "FONT_OT_change_character", DOWNARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "delta", -1);
+
+ WM_keymap_add_item(keymap, "FONT_OT_text_copy", CKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "FONT_OT_text_cut", XKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "FONT_OT_text_paste", PKEY, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "FONT_OT_line_break", RETKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "FONT_OT_text_insert", KM_TEXTINPUT, KM_ANY, KM_ANY, 0); // last!
+
+ /* only set in editmode curve, by space_view3d listener */
+ keymap= WM_keymap_listbase(wm, "Curve", 0, 0);
+
+ WM_keymap_add_item(keymap, "OBJECT_OT_curve_add", AKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "CURVE_OT_vertex_add", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "CURVE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "CURVE_OT_select_row", RKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "CURVE_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "CURVE_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "CURVE_OT_select_linked", LKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "CURVE_OT_select_linked", LKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "deselect", 1);
+
+ WM_keymap_add_item(keymap, "CURVE_OT_separate", PKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "CURVE_OT_extrude", EKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "CURVE_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "CURVE_OT_make_segment", FKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "CURVE_OT_cyclic_toggle", CKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "CURVE_OT_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "CURVE_OT_delete", DELKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "CURVE_OT_tilt_clear", TKEY, KM_PRESS, KM_ALT, 0);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TFM_OT_transform", TKEY, KM_PRESS, 0, 0)->ptr, "mode", TFM_TILT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CURVE_OT_handle_type_set", HKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", 1);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CURVE_OT_handle_type_set", HKEY, KM_PRESS, 0, 0)->ptr, "type", 3);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CURVE_OT_handle_type_set", VKEY, KM_PRESS, 0, 0)->ptr, "type", 2);
+
+ WM_keymap_add_item(keymap, "CURVE_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "CURVE_OT_hide", HKEY, KM_PRESS, KM_ALT|KM_CTRL, 0);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CURVE_OT_hide", HKEY, KM_PRESS, KM_ALT|KM_SHIFT, 0)->ptr, "unselected", 1);
+
+ WM_keymap_add_item(keymap, "CURVE_OT_specials_menu", WKEY, KM_PRESS, 0, 0);
+}
+
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
new file mode 100644
index 00000000000..72806a79c50
--- /dev/null
+++ b/source/blender/editors/curve/editcurve.c
@@ -0,0 +1,5232 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <string.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+#include <stdlib.h>
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_dynstr.h"
+#include "BLI_rand.h"
+
+#include "DNA_curve_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_space_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
+#include "BKE_global.h"
+#include "BKE_key.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
+#include "BKE_utildefines.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_anim_api.h"
+#include "ED_curve.h"
+#include "ED_keyframes_edit.h"
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+#include "ED_view3d.h"
+
+#include "UI_interface.h"
+
+#include "BIF_transform.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+/* still need to eradicate a few :( */
+#define callocstructN(x,y,name) (x*)MEM_callocN((y)* sizeof(x),name)
+
+/* for curve objects in editmode that can have hidden handles */
+#define BEZSELECTED_HIDDENHANDLES(bezt) ((G.f & G_HIDDENHANDLES) ? (bezt)->f2 & SELECT : BEZSELECTED(bezt))
+
+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}
+};
+
+ListBase *curve_get_editcurve(Object *ob)
+{
+ if(ob && ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ Curve *cu= ob->data;
+ return cu->editnurb;
+ }
+ return NULL;
+}
+
+/* this replaces the active flag used in uv/face mode */
+void set_actNurb(Object *obedit, Nurb *nu)
+{
+ Curve *cu= obedit->data;
+
+ if(nu==NULL)
+ cu->actnu = -1;
+ else
+ cu->actnu = BLI_findindex(cu->editnurb, nu);
+}
+
+Nurb *get_actNurb(Object *obedit)
+{
+ Curve *cu= obedit->data;
+
+ return BLI_findlink(cu->editnurb, cu->actnu);
+}
+
+/* ******************* SELECTION FUNCTIONS ********************* */
+
+#define HIDDEN 1
+#define VISIBLE 0
+
+#define FIRST 1
+#define LAST 0
+
+
+/* returns 1 in case (de)selection was successful */
+static short select_beztriple(BezTriple *bezt, short selstatus, short flag, short hidden)
+{
+ if(bezt) {
+ if((bezt->hide==0) || (hidden==1)) {
+ if(selstatus==1) { /* selects */
+ bezt->f1 |= flag;
+ bezt->f2 |= flag;
+ bezt->f3 |= flag;
+ return 1;
+ }
+ else { /* deselects */
+ bezt->f1 &= ~flag;
+ bezt->f2 &= ~flag;
+ bezt->f3 &= ~flag;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* returns 1 in case (de)selection was successful */
+static short select_bpoint(BPoint *bp, short selstatus, short flag, short hidden)
+{
+ if(bp) {
+ if((bp->hide==0) || (hidden==1)) {
+ if(selstatus==1) {
+ bp->f1 |= flag;
+ return 1;
+ }
+ else {
+ bp->f1 &= ~flag;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static short swap_selection_beztriple(BezTriple *bezt)
+{
+ if(bezt->f2 & SELECT)
+ return select_beztriple(bezt, DESELECT, 1, VISIBLE);
+ else
+ return select_beztriple(bezt, SELECT, 1, VISIBLE);
+}
+
+static short swap_selection_bpoint(BPoint *bp)
+{
+ if(bp->f1 & SELECT)
+ return select_bpoint(bp, DESELECT, 1, VISIBLE);
+ else
+ return select_bpoint(bp, SELECT, 1, VISIBLE);
+}
+
+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 & SELECT) || (bezt->f2 & SELECT) || (bezt->f3 & SELECT) ) return 1;
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if( (bp->f1 & SELECT) ) 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 (BEZSELECTED_HIDDENHANDLES(bezt)) sel++;
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if( (bp->f1 & SELECT) ) sel++;
+ bp++;
+ }
+ }
+ return sel;
+}
+
+/* ******************* PRINTS ********************* */
+
+void printknots(Object *obedit)
+{
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ int a, num;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ 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]);
+ }
+ }
+ }
+}
+
+/* ********************* LOAD and MAKE *************** */
+
+/* load editNurb in object */
+void load_editNurb(Object *obedit)
+{
+ ListBase *editnurb= curve_get_editcurve(obedit);
+
+ if(obedit==NULL) return;
+
+ if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ Curve *cu= obedit->data;
+ Nurb *nu, *newnu;
+ KeyBlock *actkey;
+ int totvert= count_curveverts(editnurb);
+
+ /* are there keys? */
+ actkey = ob_get_keyblock(obedit);
+ if(actkey) {
+ /* active key: the vertices */
+
+ if(totvert) {
+ if(actkey->data) MEM_freeN(actkey->data);
+
+ actkey->data= MEM_callocN(cu->key->elemsize*totvert, "actkey->data");
+ actkey->totelem= totvert;
+
+ curve_to_key(cu, actkey, editnurb);
+ }
+ }
+
+ if(cu->key && actkey!=cu->key->refkey) {
+ ;
+ }
+ else {
+ freeNurblist(&(cu->nurb));
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ newnu= duplicateNurb(nu);
+ BLI_addtail(&(cu->nurb), newnu);
+
+ if((nu->type & 7)==CU_NURBS) {
+ clamp_nurb_order_u(nu);
+ }
+ }
+ }
+ }
+
+ set_actNurb(obedit, NULL);
+}
+
+/* make copy in cu->editnurb */
+void make_editNurb(Object *obedit)
+{
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu, *newnu;
+ KeyBlock *actkey;
+
+ if(obedit==NULL) return;
+
+ if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ Curve *cu= obedit->data;
+
+ if(editnurb)
+ freeNurblist(editnurb);
+ else
+ editnurb= cu->editnurb= MEM_callocN(sizeof(ListBase), "editnurb");
+
+ nu= cu->nurb.first;
+ cu->lastselbp= NULL; /* for select row */
+
+ while(nu) {
+ newnu= duplicateNurb(nu);
+ test2DNurb(newnu); // after join, or any other creation of curve
+ BLI_addtail(editnurb, newnu);
+ nu= nu->next;
+ }
+
+ actkey = ob_get_keyblock(obedit);
+ if(actkey) {
+ // XXX strcpy(G.editModeTitleExtra, "(Key) ");
+ key_to_curve(actkey, cu, editnurb);
+ }
+ }
+
+ set_actNurb(obedit, NULL);
+}
+
+void free_editNurb(Object *obedit)
+{
+ Curve *cu= obedit->data;
+
+ if(cu->editnurb) {
+ freeNurblist(cu->editnurb);
+ MEM_freeN(cu->editnurb);
+ cu->editnurb= NULL;
+ }
+}
+
+/******************** separate operator ***********************/
+
+static int separate_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Nurb *nu, *nu1;
+ Object *oldob, *newob;
+ Base *oldbase, *newbase;
+ Curve *oldcu, *newcu;
+ ListBase *oldedit, *newedit;
+
+ oldbase= CTX_data_active_base(C);
+ oldob= oldbase->object;
+ oldcu= oldob->data;
+ oldedit= oldcu->editnurb;
+
+ if(oldcu->key) {
+ BKE_report(op->reports, RPT_ERROR, "Can't separate a curve with vertex keys.");
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_cursor_wait(1);
+
+ /* 1. duplicate the object and data */
+ newbase= ED_object_add_duplicate(scene, oldbase, 0); /* 0 = fully linked */
+ ED_base_object_select(newbase, BA_DESELECT);
+ newob= newbase->object;
+
+ newcu= newob->data= copy_curve(oldcu);
+ newcu->editnurb= NULL;
+ oldcu->id.us--; /* because new curve is a copy: reduce user count */
+
+ /* 2. put new object in editmode and clear it */
+ make_editNurb(newob);
+ newedit= newcu->editnurb;
+ freeNurblist(newedit);
+
+ /* 3. move over parts from old object */
+ for(nu= oldedit->first; nu; nu=nu1) {
+ nu1= nu->next;
+
+ if(isNurbsel(nu)) {
+ BLI_remlink(oldedit, nu);
+ BLI_addtail(newedit, nu);
+ }
+ }
+
+ /* 4. put old object out of editmode */
+ load_editNurb(newob);
+ free_editNurb(newob);
+
+ DAG_object_flush_update(scene, oldob, OB_RECALC_DATA); /* this is the original one */
+ DAG_object_flush_update(scene, newob, OB_RECALC_DATA); /* this is the separated one */
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, oldob);
+
+ WM_cursor_wait(0);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_separate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Separate";
+ ot->idname= "CURVE_OT_separate";
+
+ /* api callbacks */
+ ot->exec= separate_exec;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ******************* FLAGS ********************* */
+
+static short isNurbselUV(Nurb *nu, int *u, int *v, int flag)
+{
+ /* return u!=-1: 1 row in u-direction selected. U has value between 0-pntsv
+ * return v!=-1: 1 collumn in v-direction selected. V has value between 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; /* because sel==1 is still ok */
+ }
+
+ 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;
+}
+
+static void setflagsNurb(ListBase *editnurb, short flag)
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ 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++;
+ }
+ }
+ }
+}
+
+static void rotateflagNurb(ListBase *editnurb, short flag, float *cent, float rotmat[][3])
+{
+ /* all verts with (flag & 'flag') rotate */
+ Nurb *nu;
+ BPoint *bp;
+ int a;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ 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++;
+ }
+ }
+ }
+}
+
+static void translateflagNurb(ListBase *editnurb, short flag, float *vec)
+{
+ /* all verts with ('flag' & flag) translate */
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ 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);
+ }
+}
+
+static void weightflagNurb(ListBase *editnurb, short flag, float w, int mode) /* mode==0: replace, mode==1: multiply */
+{
+ Nurb *nu;
+ BPoint *bp;
+ int a;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ 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++;
+ }
+ }
+ }
+}
+
+static int deleteflagNurb(bContext *C, wmOperator *op, int flag)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Curve *cu= obedit->data;
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu, *next;
+ BPoint *bp, *bpn, *newbp;
+ int a, b, newu, newv, sel;
+
+ if(obedit && obedit->type==OB_SURF);
+ else return OPERATOR_CANCELLED;
+
+ cu->lastselbp= NULL;
+
+ nu= editnurb->first;
+ while(nu) {
+ next= nu->next;
+
+ /* is entire nurb selected */
+ 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); nu=NULL;
+ }
+ else {
+ /* is nurb in U direction selected */
+ 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) {
+ /* delete */
+ 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;
+ clamp_nurb_order_v(nu);
+
+ makeknots(nu, 2);
+ }
+ else {
+ /* is the nurb in V direction selected */
+ 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) {
+ /* delete */
+ 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) { /* make a U spline */
+ nu->pntsu= nu->pntsv;
+ nu->pntsv= 1;
+ SWAP(short, nu->orderu, nu->orderv);
+ clamp_nurb_order_u(nu);
+ if(nu->knotsv) MEM_freeN(nu->knotsv);
+ nu->knotsv= NULL;
+ }
+ else {
+ nu->pntsu= newu;
+ clamp_nurb_order_u(nu);
+ }
+ makeknots(nu, 1);
+ }
+ }
+ }
+ nu= next;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+/* only for OB_SURF */
+static short extrudeflagNurb(ListBase *editnurb, int flag)
+{
+ Nurb *nu;
+ BPoint *bp, *bpn, *newbp;
+ int ok= 0, a, u, v, len;
+
+ 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--) {
+ select_bpoint(bp, SELECT, flag, HIDDEN);
+ select_bpoint(newbp, DESELECT, flag, HIDDEN);
+ bp++;
+ newbp++;
+ }
+
+ nu->pntsv= 2;
+ nu->orderv= 2;
+ makeknots(nu, 2);
+ }
+ }
+ else {
+ /* which row or collumn is selected */
+
+ if( isNurbselUV(nu, &u, &v, flag) ) {
+
+ /* deselect all */
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ select_bpoint(bp, DESELECT, flag, HIDDEN);
+ bp++;
+ }
+
+ if(u==0 || u== nu->pntsv-1) { /* row in u-direction selected */
+ 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--) {
+ select_bpoint(bp, SELECT, flag, HIDDEN);
+ bp++;
+ }
+
+ MEM_freeN(nu->bp);
+ nu->bp= newbp;
+ nu->pntsv++;
+ makeknots(nu, 2);
+ }
+ else if(v==0 || v== nu->pntsu-1) { /* collumn in v-direction selected */
+ 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++;
+ makeknots(nu, 1);
+ }
+ }
+ }
+ nu= nu->next;
+ }
+
+ return ok;
+}
+
+static void adduplicateflagNurb(Object *obedit, short flag)
+{
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ 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) ) {
+ select_beztriple(bezt, DESELECT, flag, HIDDEN);
+ 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);
+ set_actNurb(obedit, 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--) {
+ select_beztriple(bezt1, SELECT, flag, HIDDEN);
+ bezt1++;
+ }
+
+ if(nu->flagu & CU_CYCLIC) {
+ if(starta!=0 || enda!=nu->pntsu-1) {
+ newnu->flagu &= ~CU_CYCLIC;
+ }
+ }
+ }
+ bezt++;
+ }
+ }
+ else if(nu->pntsv==1) { /* because UV Nurb has a different method for dupli */
+ bp= nu->bp;
+ for(a=0; a<nu->pntsu; a++) {
+ enda= -1;
+ starta= a;
+ while(bp->f1 & flag) {
+ select_bpoint(bp, DESELECT, flag, HIDDEN);
+ 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));
+ set_actNurb(obedit, 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--) {
+ select_bpoint(bp1, SELECT, flag, HIDDEN);
+ bp1++;
+ }
+
+ if(nu->flagu & CU_CYCLIC) {
+ if(starta!=0 || enda!=nu->pntsu-1) {
+ newnu->flagu &= ~CU_CYCLIC;
+ }
+ }
+
+ /* knots */
+ newnu->knotsu= NULL;
+ makeknots(newnu, 1);
+ }
+ bp++;
+ }
+ }
+ else {
+ /* a rectangular area in nurb has to be selected */
+ 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);
+ set_actNurb(obedit, newnu);
+ newnu->pntsu= newu;
+ newnu->pntsv= newv;
+ newnu->bp =
+ (BPoint*)MEM_mallocN(newu * newv * sizeof(BPoint), "adduplicateN6");
+ clamp_nurb_order_u(newnu);
+ clamp_nurb_order_v(newnu);
+
+ newnu->knotsu= newnu->knotsv= NULL;
+
+ 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));
+ select_bpoint(bp1, DESELECT, flag, HIDDEN);
+ bp++;
+ }
+ }
+ }
+ if (check_valid_nurb_u(newnu)) {
+ if(nu->pntsu==newnu->pntsu && nu->knotsu) {
+ newnu->knotsu= MEM_dupallocN( nu->knotsu );
+ } else {
+ makeknots(newnu, 1);
+ }
+ }
+ if (check_valid_nurb_v(newnu)) {
+ if(nu->pntsv==newnu->pntsv && nu->knotsv) {
+ newnu->knotsv= MEM_dupallocN( nu->knotsv );
+ } else {
+ makeknots(newnu, 2);
+ }
+ }
+ }
+ MEM_freeN(usel);
+ }
+ }
+
+ nu= nu->prev;
+ }
+
+ /* actnu changed */
+}
+
+/**************** switch direction operator ***************/
+
+static int switch_direction_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+
+ for(nu= editnurb->first; nu; nu= nu->next)
+ if(isNurbsel(nu))
+ switchdirectionNurb(nu);
+
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_switch_direction(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Switch Direction";
+ ot->idname= "CURVE_OT_switch_direction";
+
+ /* api callbacks */
+ ot->exec= switch_direction_exec;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/****************** set weight operator *******************/
+
+static int set_weight_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ float weight= RNA_float_get(op->ptr, "weight");
+ int a;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if(nu->bezt) {
+ for(bezt=nu->bezt, a=0; a<nu->pntsu; a++, bezt++) {
+ if(bezt->f2 & SELECT)
+ bezt->weight= weight;
+ }
+ }
+ else if(nu->bp) {
+ for(bp=nu->bp, a=0; a<nu->pntsu*nu->pntsv; a++, bp++) {
+ if(bp->f1 & SELECT)
+ bp->weight= weight;
+ }
+ }
+ }
+
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_spline_weight_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Curve Weight";
+ ot->idname= "CURVE_OT_spline_weight_set";
+
+ /* api callbacks */
+ ot->exec= set_weight_exec;
+ ot->invoke= WM_operator_redo;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float_percentage(ot->srna, "weight", 1.0f, 0.0f, 1.0f, "Weight", "", 0.0f, 1.0f);
+}
+
+/******************* set radius operator ******************/
+
+static int set_radius_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ float radius= RNA_float_get(op->ptr, "radius");
+ int a;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if(nu->bezt) {
+ for(bezt=nu->bezt, a=0; a<nu->pntsu; a++, bezt++) {
+ if(bezt->f2 & SELECT)
+ bezt->radius= radius;
+ }
+ }
+ else if(nu->bp) {
+ for(bp=nu->bp, a=0; a<nu->pntsu*nu->pntsv; a++, bp++) {
+ if(bp->f1 & SELECT)
+ bp->radius= radius;
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_radius_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Curve Radius";
+ ot->idname= "CURVE_OT_radius_set";
+
+ /* api callbacks */
+ ot->exec= set_radius_exec;
+ ot->invoke= WM_operator_redo;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float(ot->srna, "radius", 1.0f, 0.0f, FLT_MAX, "Radius", "", 0.0001f, 10.0f);
+}
+
+/********************* smooth operator ********************/
+
+static int smooth_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BezTriple *bezt, *beztOrig;
+ BPoint *bp, *bpOrig;
+ float val, newval, offset;
+ int a, i, change = 0;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if(nu->bezt) {
+ change = 0;
+ beztOrig = MEM_dupallocN( nu->bezt );
+ for(bezt=nu->bezt+1, a=1; a<nu->pntsu-1; a++, bezt++) {
+ if(bezt->f2 & SELECT) {
+ for(i=0; i<3; i++) {
+ val = bezt->vec[1][i];
+ newval = ((beztOrig+(a-1))->vec[1][i] * 0.5) + ((beztOrig+(a+1))->vec[1][i] * 0.5);
+ offset = (val*((1.0/6.0)*5)) + (newval*(1.0/6.0)) - val;
+ /* offset handles */
+ bezt->vec[1][i] += offset;
+ bezt->vec[0][i] += offset;
+ bezt->vec[2][i] += offset;
+ }
+ change = 1;
+ }
+ }
+ MEM_freeN(beztOrig);
+ if (change)
+ calchandlesNurb(nu);
+ } else if (nu->bp) {
+ bpOrig = MEM_dupallocN( nu->bp );
+ /* Same as above, keep these the same! */
+ for(bp=nu->bp+1, a=1; a<nu->pntsu-1; a++, bp++) {
+ if(bp->f1 & SELECT) {
+ for(i=0; i<3; i++) {
+ val = bp->vec[i];
+ newval = ((bpOrig+(a-1))->vec[i] * 0.5) + ((bpOrig+(a+1))->vec[i] * 0.5);
+ offset = (val*((1.0/6.0)*5)) + (newval*(1.0/6.0)) - val;
+
+ bp->vec[i] += offset;
+ }
+ }
+ }
+ MEM_freeN(bpOrig);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_smooth(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Smooth";
+ ot->idname= "CURVE_OT_smooth";
+
+ /* api callbacks */
+ ot->exec= smooth_exec;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/**************** smooth curve radius operator *************/
+
+/* TODO, make smoothing distance based */
+static int smooth_radius_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ /* use for smoothing */
+ int last_sel;
+ int start_sel, end_sel; /* selection indicies, inclusive */
+ float start_rad, end_rad, fac, range;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if(nu->bezt) {
+
+ for (last_sel=0; last_sel < nu->pntsu; last_sel++) {
+ /* loop over selection segments of a curve, smooth each */
+
+ /* Start BezTriple code, this is duplicated below for points, make sure these functions stay in sync */
+ start_sel = end_sel = -1;
+ for(bezt=nu->bezt+last_sel, a=last_sel; a<nu->pntsu; a++, bezt++) {
+ if(bezt->f2 & SELECT) {
+ start_sel = a;
+ break;
+ }
+ }
+ /* incase there are no other selected verts */
+ end_sel = start_sel;
+ for(bezt=nu->bezt+(start_sel+1), a=start_sel+1; a<nu->pntsu; a++, bezt++) {
+ if((bezt->f2 & SELECT)==0) {
+ break;
+ }
+ end_sel = a;
+ }
+
+ if (start_sel == -1) {
+ last_sel = nu->pntsu; /* next... */
+ } else {
+ last_sel = end_sel; /* before we modify it */
+
+ /* now blend between start and end sel */
+ start_rad = end_rad = -1.0;
+
+ if (start_sel == end_sel) {
+ /* simple, only 1 point selected */
+ if (start_sel>0) start_rad = (nu->bezt+start_sel-1)->radius;
+ if (end_sel!=-1 && end_sel < nu->pntsu) end_rad = (nu->bezt+start_sel+1)->radius;
+
+ if (start_rad >= 0.0 && end_rad >= 0.0) (nu->bezt+start_sel)->radius = (start_rad + end_rad)/2;
+ else if (start_rad >= 0.0) (nu->bezt+start_sel)->radius = start_rad;
+ else if (end_rad >= 0.0) (nu->bezt+start_sel)->radius = end_rad;
+ } else {
+ /* if endpoints selected, then use them */
+ if (start_sel==0) {
+ start_rad = (nu->bezt+start_sel)->radius;
+ start_sel++; /* we dont want to edit the selected endpoint */
+ } else {
+ start_rad = (nu->bezt+start_sel-1)->radius;
+ }
+ if (end_sel==nu->pntsu-1) {
+ end_rad = (nu->bezt+end_sel)->radius;
+ end_sel--; /* we dont want to edit the selected endpoint */
+ } else {
+ end_rad = (nu->bezt+end_sel+1)->radius;
+ }
+
+ /* Now Blend between the points */
+ range = (float)(end_sel - start_sel) + 2.0f;
+ for(bezt=nu->bezt+start_sel, a=start_sel; a<=end_sel; a++, bezt++) {
+ fac = (float)(1+a-start_sel) / range;
+ bezt->radius = start_rad*(1.0-fac) + end_rad*fac;
+ }
+ }
+ }
+ }
+ } else if (nu->bp) {
+ /* Same as above, keep these the same! */
+ for (last_sel=0; last_sel < nu->pntsu; last_sel++) {
+ /* loop over selection segments of a curve, smooth each */
+
+ /* Start BezTriple code, this is duplicated below for points, make sure these functions stay in sync */
+ start_sel = end_sel = -1;
+ for(bp=nu->bp+last_sel, a=last_sel; a<nu->pntsu; a++, bp++) {
+ if(bp->f1 & SELECT) {
+ start_sel = a;
+ break;
+ }
+ }
+ /* incase there are no other selected verts */
+ end_sel = start_sel;
+ for(bp=nu->bp+(start_sel+1), a=start_sel+1; a<nu->pntsu; a++, bp++) {
+ if((bp->f1 & SELECT)==0) {
+ break;
+ }
+ end_sel = a;
+ }
+
+ if (start_sel == -1) {
+ last_sel = nu->pntsu; /* next... */
+ } else {
+ last_sel = end_sel; /* before we modify it */
+
+ /* now blend between start and end sel */
+ start_rad = end_rad = -1.0;
+
+ if (start_sel == end_sel) {
+ /* simple, only 1 point selected */
+ if (start_sel>0) start_rad = (nu->bp+start_sel-1)->radius;
+ if (end_sel!=-1 && end_sel < nu->pntsu) end_rad = (nu->bp+start_sel+1)->radius;
+
+ if (start_rad >= 0.0 && end_rad >= 0.0) (nu->bp+start_sel)->radius = (start_rad + end_rad)/2;
+ else if (start_rad >= 0.0) (nu->bp+start_sel)->radius = start_rad;
+ else if (end_rad >= 0.0) (nu->bp+start_sel)->radius = end_rad;
+ } else {
+ /* if endpoints selected, then use them */
+ if (start_sel==0) {
+ start_rad = (nu->bp+start_sel)->radius;
+ start_sel++; /* we dont want to edit the selected endpoint */
+ } else {
+ start_rad = (nu->bp+start_sel-1)->radius;
+ }
+ if (end_sel==nu->pntsu-1) {
+ end_rad = (nu->bp+end_sel)->radius;
+ end_sel--; /* we dont want to edit the selected endpoint */
+ } else {
+ end_rad = (nu->bp+end_sel+1)->radius;
+ }
+
+ /* Now Blend between the points */
+ range = (float)(end_sel - start_sel) + 2.0f;
+ for(bp=nu->bp+start_sel, a=start_sel; a<=end_sel; a++, bp++) {
+ fac = (float)(1+a-start_sel) / range;
+ bp->radius = start_rad*(1.0-fac) + end_rad*fac;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_smooth_radius(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Smooth Curve Radius";
+ ot->idname= "CURVE_OT_smooth_radius";
+
+ /* api clastbacks */
+ ot->exec= smooth_radius_exec;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/***************** selection utility *************************/
+
+/* next == 1 -> select next */
+/* next == -1 -> select previous */
+/* cont == 1 -> select continuously */
+/* selstatus, inverts behaviour */
+static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short selstatus)
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+ short lastsel= 0, sel=0;
+
+ if(next==0) return;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ lastsel=0;
+ if((nu->type & 7)==CU_BEZIER) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ if(next < 0) bezt= (nu->bezt + (a-1));
+ while(a--) {
+ if(a-abs(next) < 0) break;
+ sel= 0;
+ if((lastsel==0) && (bezt->hide==0) && ((bezt->f2 & SELECT) || (selstatus==0))) {
+ bezt+=next;
+ if(!(bezt->f2 & SELECT) || (selstatus==0)) {
+ sel= select_beztriple(bezt, selstatus, 1, VISIBLE);
+ if((sel==1) && (cont==0)) lastsel= 1;
+ }
+ }
+ else {
+ bezt+=next;
+ lastsel= 0;
+ }
+ /* move around in zigzag way so that we go through each */
+ bezt-=(next-next/abs(next));
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ if(next < 0) bp= (nu->bp + (a-1));
+ while(a--) {
+ if(a-abs(next) < 0) break;
+ sel=0;
+ if((lastsel==0) && (bp->hide==0) && ((bp->f1 & SELECT) || (selstatus==0))) {
+ bp+=next;
+ if(!(bp->f1 & SELECT) || (selstatus==0)) {
+ sel= select_bpoint(bp, selstatus, 1, VISIBLE);
+ if((sel==1) && (cont==0)) lastsel= 1;
+ }
+ }
+ else {
+ bp+=next;
+ lastsel= 0;
+ }
+ /* move around in zigzag way so that we go through each */
+ bp-=(next-next/abs(next));
+ }
+ }
+ }
+}
+
+/**************** select start/end operators **************/
+
+/* (de)selects first or last of visible part of each Nurb depending on selFirst */
+/* selFirst: defines the end of which to select */
+/* doswap: defines if selection state of each first/last control point is swapped */
+/* selstatus: selection status in case doswap is false */
+void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatus)
+{
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+ short sel;
+
+ if(obedit==0) return;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ sel= 0;
+ if((nu->type & 7)==CU_BEZIER) {
+ a= nu->pntsu;
+
+ /* which point? */
+ if(selfirst==0) { /* select last */
+ bezt= (nu->bezt + (a-1));
+ }
+ else { /* select first */
+ bezt= nu->bezt;
+ }
+
+ while(a--) {
+ if(doswap) sel= swap_selection_beztriple(bezt);
+ else sel= select_beztriple(bezt, selstatus, 1, VISIBLE);
+
+ if(sel==1) break;
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+
+ /* which point? */
+ if(selfirst==0) { /* select last */
+ bp= (nu->bp + (a-1));
+ }
+ else{ /* select first */
+ bp= nu->bp;
+ }
+
+ while(a--) {
+ if (bp->hide == 0) {
+ if(doswap) sel= swap_selection_bpoint(bp);
+ else sel= select_bpoint(bp, selstatus, 1, VISIBLE);
+
+ if(sel==1) break;
+ }
+ }
+ }
+ }
+}
+
+static int de_select_first_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+
+ selectend_nurb(obedit, FIRST, 1, DESELECT);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_de_select_first(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select or Deselect First";
+ ot->idname= "CURVE_OT_de_select_first";
+
+ /* api cfirstbacks */
+ ot->exec= de_select_first_exec;
+ ot->poll= ED_operator_editcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int de_select_last_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+
+ selectend_nurb(obedit, LAST, 1, DESELECT);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_de_select_last(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select or Deselect Last";
+ ot->idname= "CURVE_OT_de_select_last";
+
+ /* api clastbacks */
+ ot->exec= de_select_last_exec;
+ ot->poll= ED_operator_editcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/******************* de select all operator ***************/
+
+static short nurb_has_selected_cps(ListBase *editnurb)
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if((nu->type & 7)==CU_BEZIER) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ if(bezt->hide==0) {
+ if((bezt->f1 & SELECT)
+ || (bezt->f2 & SELECT)
+ || (bezt->f3 & SELECT)) return 1;
+ }
+ bezt++;
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ if((bp->hide==0) && (bp->f1 & SELECT)) return 1;
+ bp++;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int de_select_all_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+
+ if(nurb_has_selected_cps(editnurb)) { /* deselect all */
+ selectend_nurb(obedit, FIRST, 0, DESELECT); /* set first control points as unselected */
+ select_adjacent_cp(editnurb, 1, 1, DESELECT); /* cascade selection */
+ }
+ else { /* select all */
+ selectend_nurb(obedit, FIRST, 0, SELECT); /* set first control points as selected */
+ select_adjacent_cp(editnurb, 1, 1, SELECT); /* cascade selection */
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_all_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select or Deselect All";
+ ot->idname= "CURVE_OT_select_all_toggle";
+
+ /* api callbacks */
+ ot->exec= de_select_all_exec;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************** hide operator *********************/
+
+static int hide_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a, sel, invert= RNA_boolean_get(op->ptr, "unselected");
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ sel= 0;
+ while(a--) {
+ if(invert == 0 && BEZSELECTED_HIDDENHANDLES(bezt)) {
+ select_beztriple(bezt, DESELECT, 1, HIDDEN);
+ bezt->hide= 1;
+ }
+ else if(invert && !BEZSELECTED_HIDDENHANDLES(bezt)) {
+ select_beztriple(bezt, DESELECT, 1, HIDDEN);
+ bezt->hide= 1;
+ }
+ if(bezt->hide) sel++;
+ bezt++;
+ }
+ if(sel==nu->pntsu) nu->hide= 1;
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ sel= 0;
+ while(a--) {
+ if(invert==0 && (bp->f1 & SELECT)) {
+ select_bpoint(bp, DESELECT, 1, HIDDEN);
+ bp->hide= 1;
+ }
+ else if(invert && (bp->f1 & SELECT)==0) {
+ select_bpoint(bp, DESELECT, 1, HIDDEN);
+ bp->hide= 1;
+ }
+ if(bp->hide) sel++;
+ bp++;
+ }
+ if(sel==nu->pntsu*nu->pntsv) nu->hide= 1;
+ }
+ }
+
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_hide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Hide Selected";
+ ot->idname= "CURVE_OT_hide";
+
+ /* api callbacks */
+ ot->exec= hide_exec;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected.");
+}
+
+/********************** reveal operator *********************/
+
+static int reveal_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ nu->hide= 0;
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->hide) {
+ select_beztriple(bezt, SELECT, 1, HIDDEN);
+ bezt->hide= 0;
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp->hide) {
+ select_bpoint(bp, SELECT, 1, HIDDEN);
+ bp->hide= 0;
+ }
+ bp++;
+ }
+ }
+ }
+
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_reveal(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Reveal Hidden";
+ ot->idname= "CURVE_OT_reveal";
+
+ /* api callbacks */
+ ot->exec= reveal_exec;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************** select invert operator *********************/
+
+static int select_invert_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->hide==0) {
+ bezt->f2 ^= SELECT; /* always do the center point */
+ if ((G.f & G_HIDDENHANDLES)==0) {
+ bezt->f1 ^= SELECT;
+ bezt->f3 ^= SELECT;
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ swap_selection_bpoint(bp);
+ bp++;
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_invert(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Invert";
+ ot->idname= "CURVE_OT_select_invert";
+
+ /* api callbacks */
+ ot->exec= select_invert_exec;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************** subdivide operator *********************/
+
+/** 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
+*/
+
+static int subdivide_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BezTriple *prevbezt, *bezt, *beztnew, *beztn;
+ BPoint *bp, *prevbp, *bpnew, *bpn;
+ float vec[15];
+ int a, b, sel, amount, *usel, *vsel;
+
+ // printf("*** subdivideNurb: entering subdivide\n");
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ amount= 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.
+ */
+ /* count */
+ if(nu->flagu & CU_CYCLIC) {
+ 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_HIDDENHANDLES(prevbezt) && BEZSELECTED_HIDDENHANDLES(bezt) ) amount++;
+ prevbezt= bezt;
+ bezt++;
+ }
+
+ if(amount) {
+ /* insert */
+ beztnew =
+ (BezTriple*)MEM_mallocN((amount + nu->pntsu) * sizeof(BezTriple), "subdivNurb");
+ beztn= beztnew;
+ if(nu->flagu & CU_CYCLIC) {
+ 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++;
+
+ if( BEZSELECTED_HIDDENHANDLES(prevbezt) && BEZSELECTED_HIDDENHANDLES(bezt) ) {
+ memcpy(beztn, bezt, sizeof(BezTriple));
+
+ /* midpoint subdividing */
+ VecMidf(vec, prevbezt->vec[1], prevbezt->vec[2]);
+ VecMidf(vec+3, prevbezt->vec[2], bezt->vec[0]);
+ VecMidf(vec+6, bezt->vec[0], bezt->vec[1]);
+
+ VecMidf(vec+9, vec, vec+3);
+ VecMidf(vec+12, vec+3, vec+6);
+
+ /* change handle of prev beztn */
+ VECCOPY((beztn-1)->vec[2], vec);
+ /* new point */
+ VECCOPY(beztn->vec[0], vec+9);
+ VecMidf(beztn->vec[1], vec+9, vec+12);
+ VECCOPY(beztn->vec[2], vec+12);
+ /* handle of next bezt */
+ if(a==0 && (nu->flagu & CU_CYCLIC)) {VECCOPY(beztnew->vec[0], vec+6);}
+ else {VECCOPY(bezt->vec[0], vec+6);}
+
+ beztn->radius = (prevbezt->radius + bezt->radius)/2.0f;
+ beztn->weight = (prevbezt->weight + bezt->weight)/2.0f;
+
+ beztn++;
+ }
+
+ prevbezt= bezt;
+ bezt++;
+ }
+ /* last point */
+ if((nu->flagu & CU_CYCLIC)==0) memcpy(beztn, prevbezt, sizeof(BezTriple));
+
+ MEM_freeN(nu->bezt);
+ nu->bezt= beztnew;
+ nu->pntsu+= amount;
+
+ 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
+ */
+ /* count */
+ if(nu->flagu & CU_CYCLIC) {
+ a= nu->pntsu;
+ bp= nu->bp;
+ prevbp= bp+(a-1);
+ }
+ else {
+ a= nu->pntsu-1;
+ prevbp= nu->bp;
+ bp= prevbp+1;
+ }
+ while(a--) {
+ if( (bp->f1 & SELECT) && (prevbp->f1 & SELECT) ) amount++;
+ prevbp= bp;
+ bp++;
+ }
+
+ if(amount) {
+ /* insert */
+ bpnew =
+ (BPoint*)MEM_mallocN((amount + nu->pntsu) * sizeof(BPoint), "subdivNurb2");
+ bpn= bpnew;
+
+ if(nu->flagu & CU_CYCLIC) {
+ 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 & SELECT) && (prevbp->f1 & SELECT) ) {
+ // 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 & CU_CYCLIC)==0) memcpy(bpn, prevbp, sizeof(BPoint)); /* last point */
+
+ MEM_freeN(nu->bp);
+ nu->bp= bpnew;
+ nu->pntsu+= amount;
+
+ if(nu->type & CU_NURBS) {
+ makeknots(nu, 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.
+ */
+ /* selection-arrays */
+ 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 & SELECT) {
+ usel[b]++;
+ vsel[a]++;
+ sel++;
+ }
+ bp++;
+ }
+ }
+ if( sel == (nu->pntsu*nu->pntsv) ) { /* subdivide entire nurb */
+ /* 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;
+ /* first subdivide rows */
+ 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);
+ }
+ /* now insert new */
+ 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);
+ makeknots(nu, 2);
+ } /* End of 'if(sel== nu->pntsu*nu->pntsv)' (subdivide entire NURB) */
+ else {
+ /* subdivide in v direction? */
+ 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);
+ }
+ else {
+ /* or in u direction? */
+ 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); /* shift knots
+ forward */
+ }
+ }
+ }
+ MEM_freeN(usel);
+ MEM_freeN(vsel);
+
+ } /* End of 'if((nu->type & 7)==CU_NURBS)' */
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_subdivide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Subdivide";
+ ot->idname= "CURVE_OT_subdivide";
+
+ /* api callbacks */
+ ot->exec= subdivide_exec;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/******************** find nearest ************************/
+
+static void findnearestNurbvert__doClosest(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y)
+{
+ struct { BPoint *bp; BezTriple *bezt; Nurb *nurb; int dist, hpoint, select, mval[2]; } *data = userData;
+
+ short flag;
+ short temp;
+
+ if (bp) {
+ flag = bp->f1;
+ } else {
+ if (beztindex==0) {
+ flag = bezt->f1;
+ } else if (beztindex==1) {
+ flag = bezt->f2;
+ } else {
+ flag = bezt->f3;
+ }
+ }
+
+ temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
+ if ((flag&1)==data->select) temp += 5;
+ if (bezt && beztindex==1) temp += 3; /* middle points get a small disadvantage */
+
+ if (temp<data->dist) {
+ data->dist = temp;
+
+ data->bp = bp;
+ data->bezt = bezt;
+ data->nurb = nu;
+ data->hpoint = bezt?beztindex:0;
+ }
+}
+
+static short findnearestNurbvert(ViewContext *vc, short sel, int mval[2], Nurb **nurb, BezTriple **bezt, BPoint **bp)
+{
+ /* sel==1: selected gets a disadvantage */
+ /* in nurb and bezt or bp the nearest is written */
+ /* return 0 1 2: handlepunt */
+ struct { BPoint *bp; BezTriple *bezt; Nurb *nurb; int dist, hpoint, select, mval[2]; } data = {0};
+
+ data.dist = 100;
+ data.hpoint = 0;
+ data.select = sel;
+ data.mval[0] = mval[0];
+ data.mval[1] = mval[1];
+
+ nurbs_foreachScreenVert(vc, findnearestNurbvert__doClosest, &data);
+
+ *nurb = data.nurb;
+ *bezt = data.bezt;
+ *bp = data.bp;
+
+ return data.hpoint;
+}
+
+static void findselectedNurbvert(ListBase *editnurb, Nurb **nu, BezTriple **bezt, BPoint **bp)
+{
+ /* in nu and (bezt or bp) selected are written if there's 1 sel. */
+ /* if more points selected in 1 spline: return only nu, bezt and bp are 0 */
+ Nurb *nu1;
+ BezTriple *bezt1;
+ BPoint *bp1;
+ int a;
+
+ *nu= 0;
+ *bezt= 0;
+ *bp= 0;
+ for(nu1= editnurb->first; nu1; nu1= nu1->next) {
+ if((nu1->type & 7)==CU_BEZIER) {
+ bezt1= nu1->bezt;
+ a= nu1->pntsu;
+ while(a--) {
+ if( (bezt1->f1 & SELECT) || (bezt1->f2 & SELECT) || (bezt1->f3 & SELECT) ) {
+ 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++;
+ }
+ }
+ }
+}
+
+/***************** set spline type operator *******************/
+
+static int convertspline(short type, Nurb *nu)
+{
+ BezTriple *bezt;
+ BPoint *bp;
+ int a, c, nr;
+
+ if((nu->type & 7)==CU_POLY) {
+ if(type==CU_BEZIER) { /* to Bezier with 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;
+ bezt->weight= bp->weight;
+ bezt->radius= bp->radius;
+ bp++;
+ bezt++;
+ }
+ MEM_freeN(nu->bp);
+ nu->bp= 0;
+ nu->pntsu= nr;
+ nu->type &= ~7;
+ nu->type |= CU_BEZIER;
+ calchandlesNurb(nu);
+ }
+ else if(type==CU_NURBS) {
+ nu->type &= ~7;
+ nu->type |= CU_NURBS;
+ nu->orderu= 4;
+ nu->flagu &= CU_CYCLIC; /* disable all flags except for cyclic */
+ nu->flagu += 4;
+ makeknots(nu, 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) { /* to Poly or Nurb */
+ nr= 3*nu->pntsu;
+ nu->bp = 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) {
+ /* vector handle becomes 1 poly vertice */
+ VECCOPY(bp->vec, bezt->vec[1]);
+ bp->vec[3]= 1.0;
+ bp->f1= bezt->f2;
+ nr-= 2;
+ bp->radius= bezt->radius;
+ bp->weight= bezt->weight;
+ 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->radius= bezt->radius;
+ bp->weight= bezt->weight;
+ 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 & CU_CYCLIC) c= nu->orderu-1;
+ else c= 0;
+ if(type== 4) {
+ nu->flagu &= CU_CYCLIC; /* disable all flags except for cyclic */
+ nu->flagu += 4;
+ makeknots(nu, 1);
+ }
+ }
+ }
+ else if((nu->type & 7)==CU_NURBS) {
+ if(type==0) { /* to Poly */
+ nu->type &= ~7;
+ if(nu->knotsu) MEM_freeN(nu->knotsu); /* python created nurbs have a knotsu of zero */
+ nu->knotsu= NULL;
+ if(nu->knotsv) MEM_freeN(nu->knotsv);
+ nu->knotsv= NULL;
+ }
+ else if(type==CU_BEZIER) { /* to Bezier */
+ nr= nu->pntsu/3;
+
+ if(nr<2)
+ return 1; /* conversion impossible */
+ else {
+ bezt = 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;
+ bezt->radius= bp->radius;
+ bezt->weight= bp->weight;
+ bp++;
+ bezt++;
+ }
+ MEM_freeN(nu->bp);
+ nu->bp= 0;
+ MEM_freeN(nu->knotsu);
+ nu->knotsu= NULL;
+ nu->pntsu= nr;
+ nu->type &= ~7;
+ nu->type |= CU_BEZIER;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int set_spline_type_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ int changed=0, type= RNA_enum_get(op->ptr, "type");
+
+ if(type==CU_CARDINAL || type==CU_BSPLINE) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented yet");
+ return OPERATOR_CANCELLED;
+ }
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if(isNurbsel(nu)) {
+ if(convertspline(type, nu))
+ BKE_report(op->reports, RPT_ERROR, "No conversion possible");
+ else
+ changed= 1;
+ }
+ }
+
+ return (changed)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
+}
+
+void CURVE_OT_spline_type_set(wmOperatorType *ot)
+{
+ static EnumPropertyItem type_items[]= {
+ {CU_POLY, "POLY", "Poly", ""},
+ {CU_BEZIER, "BEZIER", "Bezier", ""},
+ {CU_CARDINAL, "CARDINAL", "Cardinal", ""},
+ {CU_BSPLINE, "B_SPLINE", "B-Spline", ""},
+ {CU_NURBS, "NURBS", "NURBS", ""},
+ {0, NULL, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "Set Spline Type";
+ ot->idname= "CURVE_OT_spline_type_set";
+
+ /* api callbacks */
+ ot->exec= set_spline_type_exec;
+ ot->poll= ED_operator_editcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", type_items, CU_POLY, "Type", "Spline type");
+}
+
+/***************** set handle type operator *******************/
+
+static int set_handle_type_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+
+ sethandlesNurb(editnurb, RNA_enum_get(op->ptr, "type"));
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_handle_type_set(wmOperatorType *ot)
+{
+ static EnumPropertyItem type_items[]= {
+ {1, "AUTOMATIC", "Automatic", ""},
+ {2, "VECTOR", "Vector", ""},
+ {3, "TOGGLE_FREE_ALIGN", "Toggle Free/Align", ""},
+ {5, "ALIGN", "Align", ""},
+ {6, "FREE_ALIGN", "Free Align", ""},
+ {0, NULL, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "Set Handle Type";
+ ot->idname= "CURVE_OT_handle_type_set";
+
+ /* api callbacks */
+ ot->exec= set_handle_type_exec;
+ ot->poll= ED_operator_editcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", type_items, CU_POLY, "Type", "Spline type");
+}
+
+/***************** make segment operator **********************/
+
+/* ******************** SKINNING LOFTING!!! ******************** */
+
+static void switchdirection_knots(float *base, int tot)
+{
+ float *fp1, *fp2, *tempf;
+ int a;
+
+ if(base==NULL || tot==0) return;
+
+ /* reverse knots */
+ a= tot;
+ fp1= base;
+ fp2= fp1+(a-1);
+ a/= 2;
+ while(fp1!=fp2 && a>0) {
+ SWAP(float, *fp1, *fp2);
+ a--;
+ fp1++;
+ fp2--;
+ }
+ /* and make in increasing order again */
+ 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);
+}
+
+static 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);
+}
+
+static 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 & SELECT) 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 */
+
+static void make_selection_list_nurb(ListBase *editnurb)
+{
+ ListBase nbase= {0, 0};
+ NurbSort *nus, *nustest, *headdo, *taildo;
+ Nurb *nu;
+ BPoint *bp;
+ float dist, headdist, taildist;
+ int a;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ 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);
+
+
+ }
+ }
+
+ /* 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);
+ }
+ }
+}
+
+static void merge_2_nurb(wmOperator *op, ListBase *editnurb, 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 ) {
+ BKE_report(op->reports, RPT_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;
+ 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++;
+ select_bpoint(bp, SELECT, 1, HIDDEN);
+ }
+ else {
+ *bp= *bp2; bp2++;
+ }
+ }
+ }
+
+ if((nu1->type & 7)==CU_NURBS) {
+ /* merge knots */
+ makeknots(nu1, 1);
+
+ /* make knots, for merged curved for example */
+ makeknots(nu1, 2);
+ }
+
+ MEM_freeN(temp);
+ BLI_remlink(editnurb, nu2);
+ freeNurb(nu2);
+}
+
+static int merge_nurb(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ NurbSort *nus1, *nus2;
+ int ok= 1;
+
+ make_selection_list_nurb(editnurb);
+
+ if(nsortbase.first == nsortbase.last) {
+ BLI_freelistN(&nsortbase);
+ BKE_report(op->reports, RPT_ERROR, "Too few selections to merge.");
+ return OPERATOR_CANCELLED;
+ }
+
+ 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) {
+ BKE_report(op->reports, RPT_ERROR, "Resolution doesn't match");
+ BLI_freelistN(&nsortbase);
+ return OPERATOR_CANCELLED;
+ }
+
+ while(nus2) {
+ merge_2_nurb(op, editnurb, nus1->nu, nus2->nu);
+ nus2= nus2->next;
+ }
+
+ BLI_freelistN(&nsortbase);
+
+ set_actNurb(obedit, NULL);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+static int make_segment_exec(bContext *C, wmOperator *op)
+{
+ /* joins 2 curves */
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu, *nu1=0, *nu2=0;
+ BezTriple *bezt;
+ BPoint *bp;
+ float *fp, offset;
+ int a;
+
+ /* first decide if this is a surface merge! */
+ if(obedit->type==OB_SURF) nu= editnurb->first;
+ else nu= NULL;
+
+ 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 & SELECT) || ((nu->bp+nu->pntsu-1)->f1 & SELECT));
+ else break;
+ }
+ }
+ }
+ nu= nu->next;
+ }
+
+ if(nu)
+ return merge_nurb(C, op);
+
+ /* find both nurbs and points, nu1 will be put behind nu2 */
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if((nu->flagu & CU_CYCLIC)==0) { /* not cyclic */
+ if( (nu->type & 7)==CU_BEZIER ) {
+ bezt= nu->bezt;
+ if(nu1==0) {
+ if( BEZSELECTED_HIDDENHANDLES(bezt) ) nu1= nu;
+ else {
+ bezt= bezt+(nu->pntsu-1);
+ if( BEZSELECTED_HIDDENHANDLES(bezt) ) {
+ nu1= nu;
+ switchdirectionNurb(nu);
+ }
+ }
+ }
+ else if(nu2==0) {
+ if( BEZSELECTED_HIDDENHANDLES(bezt) ) {
+ nu2= nu;
+ switchdirectionNurb(nu);
+ }
+ else {
+ bezt= bezt+(nu->pntsu-1);
+ if( BEZSELECTED_HIDDENHANDLES(bezt) ) {
+ nu2= nu;
+ }
+ }
+ }
+ else break;
+ }
+ else if(nu->pntsv==1) {
+ bp= nu->bp;
+ if(nu1==0) {
+ if( bp->f1 & SELECT) nu1= nu;
+ else {
+ bp= bp+(nu->pntsu-1);
+ if( bp->f1 & SELECT ) {
+ nu1= nu;
+ switchdirectionNurb(nu);
+ }
+ }
+ }
+ else if(nu2==0) {
+ if( bp->f1 & SELECT ) {
+ nu2= nu;
+ switchdirectionNurb(nu);
+ }
+ else {
+ bp= bp+(nu->pntsu-1);
+ if( bp->f1 & SELECT ) {
+ nu2= nu;
+ }
+ }
+ }
+ else break;
+ }
+ }
+ }
+
+ 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); nu2= NULL;
+ 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);
+
+ /* now join the knots */
+ if((nu1->type & 7)==CU_NURBS) {
+ if(nu1->knotsu==NULL) {
+ makeknots(nu1, 1);
+ }
+ else {
+ 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); nu2= NULL;
+ }
+ }
+
+ set_actNurb(obedit, NULL); /* for selected */
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Can't make segment");
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void CURVE_OT_make_segment(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Make Segment";
+ ot->idname= "CURVE_OT_make_segment";
+
+ /* api callbacks */
+ ot->exec= make_segment_exec;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/***************** pick select from 3d view **********************/
+
+void mouse_nurb(bContext *C, short mval[2], int extend)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Curve *cu= obedit->data;
+ ViewContext vc;
+ Nurb *nu;
+ BezTriple *bezt=0;
+ BPoint *bp=0;
+ int location[2];
+ short hand;
+
+ view3d_set_viewcontext(C, &vc);
+
+ location[0]= mval[0];
+ location[1]= mval[1];
+ hand= findnearestNurbvert(&vc, 1, location, &nu, &bezt, &bp);
+
+ if(bezt || bp) {
+ if(extend==0) {
+
+ setflagsNurb(editnurb, 0);
+
+ if(bezt) {
+
+ if(hand==1) select_beztriple(bezt, SELECT, 1, HIDDEN);
+ else if(hand==0) bezt->f1|= SELECT;
+ else bezt->f3|= SELECT;
+ }
+ else {
+ cu->lastselbp= bp;
+ select_bpoint(bp, SELECT, 1, HIDDEN);
+ }
+
+ }
+ else {
+ if(bezt) {
+ if(hand==1) {
+ if(bezt->f2 & SELECT) select_beztriple(bezt, DESELECT, 1, HIDDEN);
+ else select_beztriple(bezt, SELECT, 1, HIDDEN);
+ } else if(hand==0) {
+ bezt->f1 ^= SELECT;
+ } else {
+ bezt->f3 ^= SELECT;
+ }
+ }
+ else {
+ if(bp->f1 & SELECT) select_bpoint(bp, DESELECT, 1, HIDDEN);
+ else {
+ select_bpoint(bp, SELECT, 1, HIDDEN);
+ cu->lastselbp= bp;
+ }
+ }
+
+ }
+
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ if(nu!=get_actNurb(obedit))
+ set_actNurb(obedit, nu);
+}
+
+/******************** spin operator ***********************/
+
+/* from what I can gather, the mode==0 magic number spins and bridges the nurbs based on the
+ * orientation of the global 3d view (yuck yuck!) mode==1 does the same, but doesn't bridge up
+ * up the new geometry, mode==2 now does the same as 0, but aligned to world axes, not the view.
+*/
+static int spin_nurb(bContext *C, Scene *scene, Object *obedit, float *dvec, short mode)
+{
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ View3D *v3d= CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ 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, changed= 0;
+
+ if(mode != 2 && rv3d) Mat3CpyMat4(persmat, rv3d->viewmat);
+ else Mat3One(persmat);
+ Mat3Inv(persinv, persmat);
+
+ /* imat and center and size */
+ Mat3CpyMat4(bmat, obedit->obmat);
+ Mat3Inv(imat, bmat);
+
+ if(v3d) {
+ curs= give_cursor(scene, v3d);
+ VECCOPY(cent, curs);
+ }
+ else
+ cent[0]= cent[1]= cent[2]= 0.0f;
+
+ VecSubf(cent, cent, obedit->obmat[3]);
+ Mat3MulVecfl(imat,cent);
+
+ if(dvec || mode==2 || !rv3d) {
+ n[0]=n[1]= 0.0;
+ n[2]= 1.0;
+ } else {
+ n[0]= rv3d->viewinv[2][0];
+ n[1]= rv3d->viewinv[2][1];
+ n[2]= rv3d->viewinv[2][2];
+ Normalize(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 || mode==2) ok= extrudeflagNurb(editnurb, 1);
+ else adduplicateflagNurb(obedit, 1);
+
+ if(ok==0)
+ return changed;
+
+ changed= 1;
+
+ rotateflagNurb(editnurb, 1,cent,rotmat);
+
+ if(mode==0 || mode==2) {
+ if( (a & 1)==0 ) {
+ rotateflagNurb(editnurb, 1,cent,scalemat1);
+ weightflagNurb(editnurb, 1, 0.25*sqrt(2.0), 1);
+ }
+ else {
+ rotateflagNurb(editnurb, 1,cent,scalemat2);
+ weightflagNurb(editnurb, 1, 4.0/sqrt(2.0), 1);
+ }
+ }
+ if(dvec) {
+ Mat3MulVecfl(bmat,dvec);
+ translateflagNurb(editnurb, 1,dvec);
+ }
+ }
+
+ if(ok) {
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if(isNurbsel(nu)) {
+ nu->orderv= 4;
+ nu->flagv |= CU_CYCLIC;
+ makeknots(nu, 2);
+ }
+ }
+ }
+
+ return changed;
+}
+
+static int spin_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+
+ if(!spin_nurb(C, scene, obedit, 0, 0)) {
+ BKE_report(op->reports, RPT_ERROR, "Can't spin");
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_spin(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Spin";
+ ot->idname= "CURVE_OT_spin";
+
+ /* api callbacks */
+ ot->exec= spin_exec;
+ ot->poll= ED_operator_editsurf;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/***************** add vertex operator **********************/
+
+static int addvert_Nurb(bContext *C, short mode, float location[3])
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BezTriple *bezt, *newbezt = NULL;
+ BPoint *bp, *newbp = NULL;
+ float mat[3][3],imat[3][3], temp[3];
+
+ Mat3CpyMat4(mat, obedit->obmat);
+ Mat3Inv(imat,mat);
+
+ findselectedNurbvert(editnurb, &nu, &bezt, &bp);
+ if(bezt==0 && bp==0) return OPERATOR_CANCELLED;
+
+ if((nu->type & 7)==CU_BEZIER) {
+ /* which bezpoint? */
+ if(bezt== nu->bezt) { /* first */
+ BEZ_DESEL(bezt);
+ newbezt =
+ (BezTriple*)MEM_callocN((nu->pntsu+1) * sizeof(BezTriple), "addvert_Nurb");
+ memcpy(newbezt+1, bezt, nu->pntsu*sizeof(BezTriple));
+ *newbezt= *bezt;
+ BEZ_SEL(newbezt);
+ newbezt->h2= newbezt->h1;
+ VECCOPY(temp, bezt->vec[1]);
+ MEM_freeN(nu->bezt);
+ nu->bezt= newbezt;
+ bezt= newbezt+1;
+ }
+ else if(bezt== (nu->bezt+nu->pntsu-1)) { /* last */
+ BEZ_DESEL(bezt);
+ 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;
+ BEZ_SEL(newbezt);
+ newbezt->h2= newbezt->h1;
+ bezt= nu->bezt+nu->pntsu-1;
+ }
+ else bezt= 0;
+
+ if(bezt) {
+ nu->pntsu++;
+
+ 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 {
+ VECCOPY(newbezt->vec[1], location);
+ VecSubf(newbezt->vec[1],newbezt->vec[1], 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) {
+ /* which b-point? */
+ if(bp== nu->bp) { /* first */
+ 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;
+ bp= newbp + 1;
+ }
+ else if(bp== (nu->bp+nu->pntsu-1)) { /* last */
+ 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;
+ bp= newbp - 1;
+ }
+ else bp= 0;
+
+ if(bp) {
+ nu->pntsu++;
+
+ makeknots(nu, 1);
+
+ if(mode=='e') {
+ VECCOPY(newbp->vec, bp->vec);
+ }
+ else {
+ VECCOPY(newbp->vec, location);
+ VecSubf(newbp->vec, newbp->vec, obedit->obmat[3]);
+ Mat3MulVecfl(imat,newbp->vec);
+ newbp->vec[3]= 1.0;
+ }
+ }
+ }
+
+ // XXX retopo_do_all();
+
+ test2DNurb(nu);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+static int add_vertex_exec(bContext *C, wmOperator *op)
+{
+ float location[3];
+
+ RNA_float_get_array(op->ptr, "location", location);
+ return addvert_Nurb(C, 0, location);
+}
+
+static int add_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ ViewContext vc;
+ float location[3];
+ short mval[2];
+
+ if(rv3d && !RNA_property_is_set(op->ptr, "location")) {
+ view3d_set_viewcontext(C, &vc);
+
+ mval[0]= event->x - vc.ar->winrct.xmin;
+ mval[1]= event->y - vc.ar->winrct.ymin;
+
+ view3d_get_view_aligned_coordinate(&vc, location, mval);
+ RNA_float_set_array(op->ptr, "location", location);
+ }
+
+ return add_vertex_exec(C, op);
+}
+
+void CURVE_OT_vertex_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Vertex";
+ ot->idname= "CURVE_OT_vertex_add";
+
+ /* api callbacks */
+ ot->exec= add_vertex_exec;
+ ot->invoke= add_vertex_invoke;
+ ot->poll= ED_operator_editcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float_vector(ot->srna, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location", "Location to add new vertex at.", -1e4, 1e4);
+}
+
+/***************** extrude operator **********************/
+
+static int extrude_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+
+ /* first test: curve? */
+ for(nu= editnurb->first; nu; nu= nu->next)
+ if(nu->pntsv==1 && isNurbsel_count(nu)==1)
+ break;
+
+ if(obedit->type==OB_CURVE || nu) {
+ addvert_Nurb(C, 'e', NULL);
+ }
+ else {
+ if(extrudeflagNurb(editnurb, 1)) { /* '1'= flag */
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static int extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ if(extrude_exec(C, op) == OPERATOR_FINISHED) {
+ RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
+ WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void CURVE_OT_extrude(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude";
+ ot->idname= "CURVE_OT_extrude";
+
+ /* api callbacks */
+ ot->exec= extrude_exec;
+ ot->invoke= extrude_invoke;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* to give to transform */
+ RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+}
+
+/***************** make cyclic operator **********************/
+
+static int toggle_cyclic_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a, direction= RNA_enum_get(op->ptr, "direction");
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if( nu->pntsu>1 || nu->pntsv>1) {
+ if( (nu->type & 7)==CU_POLY ) {
+ a= nu->pntsu;
+ bp= nu->bp;
+ while(a--) {
+ if( bp->f1 & SELECT ) {
+ nu->flagu ^= CU_CYCLIC;
+ break;
+ }
+ bp++;
+ }
+ }
+ else if( (nu->type & 7)==CU_BEZIER ) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ if( BEZSELECTED_HIDDENHANDLES(bezt) ) {
+ nu->flagu ^= CU_CYCLIC;
+ break;
+ }
+ bezt++;
+ }
+ calchandlesNurb(nu);
+ }
+ else if(nu->pntsv==1 && (nu->type & 7)==CU_NURBS) {
+ if (nu->knotsu) { /* if check_valid_nurb_u fails the knotsu can be NULL */
+ a= nu->pntsu;
+ bp= nu->bp;
+ while(a--) {
+ if( bp->f1 & SELECT ) {
+ nu->flagu ^= CU_CYCLIC;
+ makeknots(nu, 1); /* 1==u type is ignored for cyclic curves */
+ break;
+ }
+ bp++;
+ }
+ }
+ }
+ else if(nu->type==CU_NURBS) {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+
+ if( bp->f1 & SELECT) {
+ if(direction==0 && nu->pntsu>1) {
+ nu->flagu ^= CU_CYCLIC;
+ makeknots(nu, 1); /* 1==u type is ignored for cyclic curves */
+ }
+ if(direction==1 && nu->pntsv>1) {
+ nu->flagv ^= CU_CYCLIC;
+ makeknots(nu, 2); /* 2==v type is ignored for cyclic curves */
+ }
+ break;
+ }
+ bp++;
+ }
+
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+static int toggle_cyclic_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ uiMenuItem *head;
+ Nurb *nu;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if(nu->pntsu>1 || nu->pntsv>1) {
+ if(nu->type==CU_NURBS) {
+ head= uiPupMenuBegin("Direction", 0);
+ uiMenuItemsEnumO(head, op->type->idname, "direction");
+ uiPupMenuEnd(C, head);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ }
+
+ return toggle_cyclic_exec(C, op);
+}
+
+void CURVE_OT_cyclic_toggle(wmOperatorType *ot)
+{
+ static EnumPropertyItem direction_items[]= {
+ {0, "CYCLIC_U", "Cyclic U", ""},
+ {1, "CYCLIC_V", "Cyclic V", ""},
+ {0, NULL, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "Toggle Cyclic";
+ ot->idname= "CURVE_OT_cyclic_toggle";
+
+ /* api callbacks */
+ ot->exec= toggle_cyclic_exec;
+ ot->invoke= toggle_cyclic_invoke;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to make surface cyclic in.");
+}
+
+/***************** select linked operator ******************/
+
+static int select_linked_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ ViewContext vc;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a, location[2], deselect;
+
+ if(!rv3d)
+ return OPERATOR_CANCELLED;
+
+ deselect= RNA_boolean_get(op->ptr, "deselect");
+ RNA_int_get_array(op->ptr, "location", location);
+
+ view3d_set_viewcontext(C, &vc);
+ findnearestNurbvert(&vc, 1, location, &nu, &bezt, &bp);
+
+ if(bezt) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ if(deselect) select_beztriple(bezt, DESELECT, 1, VISIBLE);
+ else select_beztriple(bezt, SELECT, 1, VISIBLE);
+ bezt++;
+ }
+ }
+ else if(bp) {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ if(deselect) select_bpoint(bp, DESELECT, 1, VISIBLE);
+ else select_bpoint(bp, SELECT, 1, VISIBLE);
+ bp++;
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+static int select_linked_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ int location[2];
+
+ location[0]= event->x - ar->winrct.xmin;
+ location[1]= event->y - ar->winrct.ymin;
+ RNA_int_set_array(op->ptr, "location", location);
+
+ return select_linked_exec(C, op);
+}
+
+void CURVE_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Linked";
+ ot->idname= "CURVE_OT_select_linked";
+
+ /* api callbacks */
+ ot->exec= select_linked_exec;
+ ot->invoke= select_linked_invoke;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect linked control points rather than selecting them.");
+ RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "", 0, 16384);
+}
+
+/***************** select row operator **********************/
+
+static int select_row_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Curve *cu= obedit->data;
+ 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 OPERATOR_CANCELLED;
+ if(cu->lastselbp==NULL)
+ return OPERATOR_CANCELLED;
+
+ /* find the correct nurb and toggle with u of v */
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ bp= nu->bp;
+ for(v=0; v<nu->pntsv; v++) {
+ for(u=0; u<nu->pntsu; u++, bp++) {
+ if(bp==cu->lastselbp) {
+ if(bp->f1 & SELECT) {
+ ok= 1;
+ break;
+ }
+ }
+ }
+ if(ok) break;
+ }
+
+ if(ok) {
+ if(last==cu->lastselbp) {
+ direction= 1-direction;
+ setflagsNurb(editnurb, 0);
+ }
+ last= cu->lastselbp;
+
+ bp= nu->bp;
+ for(a=0; a<nu->pntsv; a++) {
+ for(b=0; b<nu->pntsu; b++, bp++) {
+ if(direction) {
+ if(a==v) select_bpoint(bp, SELECT, 1, VISIBLE);
+ }
+ else {
+ if(b==u) select_bpoint(bp, SELECT, 1, VISIBLE);
+ }
+ }
+ }
+
+ break;
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_row(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Control Point Row";
+ ot->idname= "CURVE_OT_select_row";
+
+ /* api callbacks */
+ ot->exec= select_row_exec;
+ ot->poll= ED_operator_editsurf;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/***************** select next operator **********************/
+
+static int select_next_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+
+ select_adjacent_cp(editnurb, 1, 0, SELECT);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_next(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Next";
+ ot->idname= "CURVE_OT_select_next";
+
+ /* api callbacks */
+ ot->exec= select_next_exec;
+ ot->poll= ED_operator_editcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/***************** select previous operator **********************/
+
+static int select_previous_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+
+ select_adjacent_cp(editnurb, -1, 0, SELECT);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_previous(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Previous";
+ ot->idname= "CURVE_OT_select_previous";
+
+ /* api callbacks */
+ ot->exec= select_previous_exec;
+ ot->poll= ED_operator_editcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/***************** select more operator **********************/
+
+static int select_more_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BPoint *bp, *tempbp;
+ int a;
+ short sel= 0;
+ short *selbpoints;
+
+ /* note that NURBS surface is a special case because we mimic */
+ /* the behaviour of "select more" of mesh tools. */
+ /* The algorithm is designed to work in planar cases so it */
+ /* may not be optimal always (example: end of NURBS sphere) */
+ if(obedit->type==OB_SURF) {
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ selbpoints= MEM_callocN(sizeof(short)*a-nu->pntsu, "selectlist");
+ while(a > 0) {
+ if((selbpoints[a]!=1) && (bp->hide==0) && (bp->f1 & SELECT)) {
+ /* upper control point */
+ if(a%nu->pntsu != 0) {
+ tempbp= bp-1;
+ if(!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, 1, VISIBLE);
+ }
+
+ /* left control point. select only if it is not selected already */
+ if(a-nu->pntsu > 0) {
+ sel= 0;
+ tempbp= bp+nu->pntsu;
+ if(!(tempbp->f1 & SELECT)) sel= select_bpoint(tempbp, SELECT, 1, VISIBLE);
+ /* make sure selected bpoint is discarded */
+ if(sel == 1) selbpoints[a-nu->pntsu]= 1;
+ }
+
+ /* right control point */
+ if(a+nu->pntsu < nu->pntsu*nu->pntsv) {
+ tempbp= bp-nu->pntsu;
+ if(!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, 1, VISIBLE);
+ }
+
+ /* lower control point. skip next bp in case selection was made */
+ if(a%nu->pntsu != 1) {
+ sel= 0;
+ tempbp= bp+1;
+ if(!(tempbp->f1 & 1)) sel= select_bpoint(tempbp, SELECT, 1, VISIBLE);
+ if(sel) {
+ bp++;
+ a--;
+ }
+ }
+ }
+
+ bp++;
+ a--;
+ }
+
+ MEM_freeN(selbpoints);
+ }
+ }
+ else {
+ select_adjacent_cp(editnurb, 1, 0, SELECT);
+ select_adjacent_cp(editnurb, -1, 0, SELECT);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_more(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select More";
+ ot->idname= "CURVE_OT_select_more";
+
+ /* api callbacks */
+ ot->exec= select_more_exec;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/******************** select less operator *****************/
+
+/* basic method: deselect if control point doesn't have all neighbours selected */
+static int select_less_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+ short sel= 0, lastsel= 0;
+ short *selbpoints;
+
+ if(obedit->type==OB_SURF) {
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ selbpoints= MEM_callocN(sizeof(short)*a, "selectlist");
+ while(a--) {
+ if((bp->hide==0) && (bp->f1 & SELECT)) {
+ sel= 0;
+
+ /* check if neighbours have been selected */
+ /* edges of surface are an exception */
+ if((a+1)%nu->pntsu==0) sel++;
+ else {
+ bp--;
+ if((selbpoints[a+1]==1) || ((bp->hide==0) && (bp->f1 & SELECT))) sel++;
+ bp++;
+ }
+
+ if((a+1)%nu->pntsu==1) sel++;
+ else {
+ bp++;
+ if((bp->hide==0) && (bp->f1 & SELECT)) sel++;
+ bp--;
+ }
+
+ if(a+1 > nu->pntsu*nu->pntsv-nu->pntsu) sel++;
+ else {
+ bp-=nu->pntsu;
+ if((selbpoints[a+nu->pntsu]==1) || ((bp->hide==0) && (bp->f1 & SELECT))) sel++;
+ bp+=nu->pntsu;
+ }
+
+ if(a < nu->pntsu) sel++;
+ else {
+ bp+=nu->pntsu;
+ if((bp->hide==0) && (bp->f1 & SELECT)) sel++;
+ bp-=nu->pntsu;
+ }
+
+ if(sel!=4) {
+ select_bpoint(bp, DESELECT, 1, VISIBLE);
+ selbpoints[a]= 1;
+ }
+ }
+ else lastsel= 0;
+
+ bp++;
+ }
+
+ MEM_freeN(selbpoints);
+ }
+ }
+ else {
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ lastsel=0;
+ /* check what type of curve/nurb it is */
+ if((nu->type & 7)==CU_BEZIER) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ if((bezt->hide==0) && (bezt->f2 & SELECT)) {
+ if(lastsel==1) sel= 1;
+ else sel= 0;
+
+ /* check if neighbours have been selected */
+ /* first and last are exceptions */
+ if(a==nu->pntsu-1) sel++;
+ else {
+ bezt--;
+ if((bezt->hide==0) && (bezt->f2 & SELECT)) sel++;
+ bezt++;
+ }
+
+ if(a==0) sel++;
+ else {
+ bezt++;
+ if((bezt->hide==0) && (bezt->f2 & SELECT)) sel++;
+ bezt--;
+ }
+
+ if(sel!=2) {
+ select_beztriple(bezt, DESELECT, 1, VISIBLE);
+ lastsel= 1;
+ }
+ else lastsel= 0;
+ }
+ else lastsel= 0;
+
+ bezt++;
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ if((lastsel==0) && (bp->hide==0) && (bp->f1 & SELECT)) {
+ if(lastsel!=0) sel= 1;
+ else sel= 0;
+
+ /* first and last are exceptions */
+ if(a==nu->pntsu*nu->pntsv-1) sel++;
+ else {
+ bp--;
+ if((bp->hide==0) && (bp->f1 & SELECT)) sel++;
+ bp++;
+ }
+
+ if(a==0) sel++;
+ else {
+ bp++;
+ if((bp->hide==0) && (bp->f1 & SELECT)) sel++;
+ bp--;
+ }
+
+ if(sel!=2) {
+ select_bpoint(bp, DESELECT, 1, VISIBLE);
+ lastsel= 1;
+ }
+ else lastsel= 0;
+ }
+ else lastsel= 0;
+
+ bp++;
+ }
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_less(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Less";
+ ot->idname= "CURVE_OT_select_less";
+
+ /* api callbacks */
+ ot->exec= select_less_exec;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************** select random *********************/
+
+/* this function could be moved elsewhere as it can be reused in other parts of the source needing randomized list */
+/* returns list containing -1 in indices that have been left out of the list. otherwise index contains reference */
+/* to next index. basically *list contains a linked list */
+static void generate_pickable_list(int *list, int size, int pickamount)
+{
+ int i, j, removable;
+
+ BLI_srand( BLI_rand() ); /* random seed */
+
+ /* generate list in form 0->1, 1->2, 2->3, ... i-2->i-1, i->0 */
+ for(i=0; i<size; i++) {
+ if(i == size-1) list[i]= 0;
+ else list[i]= i+1;
+ }
+
+ for(i=0; i<size-pickamount; i++) {
+ removable= floor(BLI_frand()*(size-1)+0.5); /* with rounding. frand returns [0,1] */
+
+ /* seek proper item as the one randomly selected might not be appropriate */
+ for(j=0; j<size; j++, removable++) {
+ if(list[removable] != -1) break;
+ if(removable == size-1) removable= -1;
+ }
+
+ /* pick unwanted item out of the list */
+ list[list[removable]]= -1; /* mark former last as invalid */
+
+ if(list[removable] == size-1) list[removable]= 0;
+ else list[removable]= list[removable]+1;
+ }
+}
+
+static int select_random_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ float percent= RNA_float_get(op->ptr, "percent");
+ int amounttoselect, amountofcps, a, i, k= 0;
+ int *itemstobeselected;
+
+ if(percent == 0.0f)
+ return OPERATOR_CANCELLED;
+
+ amountofcps= count_curveverts_without_handles(editnurb);
+ itemstobeselected= MEM_callocN(sizeof(int) * amountofcps, "selectitems");
+ amounttoselect= floor(percent * amountofcps + 0.5);
+ generate_pickable_list(itemstobeselected, amountofcps, amounttoselect);
+
+ /* select elements */
+ for(i=1, nu= editnurb->first; nu; nu= nu->next) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(itemstobeselected[k] != -1) select_beztriple(bezt, SELECT, 1, VISIBLE);
+ k++;
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(itemstobeselected[k] != -1) select_bpoint(bp, SELECT, 1, VISIBLE);
+ k++;
+ bp++;
+ }
+ }
+ }
+
+ MEM_freeN(itemstobeselected);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_random(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Random";
+ ot->idname= "CURVE_OT_select_random";
+
+ /* api callbacks */
+ ot->exec= select_random_exec;
+ ot->invoke= WM_operator_redo;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float_percentage(ot->srna, "percent", 0.5f, 0.0f, 1.0f, "Percent", "Percentage of vertices to select randomly.", 0.0001f, 1.0f);
+}
+
+/********************** select every nth *********************/
+
+static int select_every_nth_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ int n= RNA_int_get(op->ptr, "n");
+
+ select_adjacent_cp(editnurb, n, 1, SELECT);
+ select_adjacent_cp(editnurb, -n, 1, SELECT);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_every_nth(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Every Nth";
+ ot->idname= "CURVE_OT_select_every_nth";
+
+ /* api callbacks */
+ ot->exec= select_every_nth_exec;
+ ot->invoke= WM_operator_redo;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "n", 2, 2, INT_MAX, "N", "Select every Nth element", 2, 25);
+}
+
+/********************** add duplicate operator *********************/
+
+static int duplicate_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+
+ adduplicateflagNurb(obedit, 1);
+
+ return OPERATOR_FINISHED;
+}
+
+static int duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ duplicate_exec(C, op);
+
+ RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
+ WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_duplicate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Duplicate";
+ ot->idname= "CURVE_OT_duplicate";
+
+ /* api callbacks */
+ ot->exec= duplicate_exec;
+ ot->invoke= duplicate_invoke;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* to give to transform */
+ RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+}
+
+/********************** delete operator *********************/
+
+static int delete_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu, *next, *nu1;
+ BezTriple *bezt, *bezt1, *bezt2;
+ BPoint *bp, *bp1, *bp2;
+ int a, cut= 0, type= RNA_enum_get(op->ptr, "type");
+
+ if(obedit->type==OB_SURF) {
+ if(type==0) deleteflagNurb(C, op, 1);
+ else freeNurblist(editnurb);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+ }
+
+ if(type==0) {
+ /* first loop, can we remove entire pieces? */
+ 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_HIDDENHANDLES(bezt) );
+ else break;
+ a--;
+ bezt++;
+ }
+ if(a==0) {
+ BLI_remlink(editnurb, nu);
+ freeNurb(nu); nu= NULL;
+ }
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ if(a) {
+ while(a) {
+ if(bp->f1 & SELECT);
+ else break;
+ a--;
+ bp++;
+ }
+ if(a==0) {
+ BLI_remlink(editnurb, nu);
+ freeNurb(nu); nu= NULL;
+ }
+ }
+ }
+
+ /* Never allow the order to exceed the number of points
+ - note, this is ok but changes unselected nurbs, disable for now */
+ /*
+ if ((nu!= NULL) && ((nu->type & 7)==CU_NURBS)) {
+ clamp_nurb_order_u(nu);
+ }
+ */
+ nu= next;
+ }
+ /* 2nd loop, delete small pieces: just for curves */
+ nu= editnurb->first;
+ while(nu) {
+ next= nu->next;
+ type= 0;
+ if( (nu->type & 7)==CU_BEZIER ) {
+ bezt= nu->bezt;
+ for(a=0;a<nu->pntsu;a++) {
+ if( BEZSELECTED_HIDDENHANDLES(bezt) ) {
+ memmove(bezt, bezt+1, (nu->pntsu-a-1)*sizeof(BezTriple));
+ nu->pntsu--;
+ a--;
+ type= 1;
+ }
+ else bezt++;
+ }
+ if(type) {
+ 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 & SELECT ) {
+ memmove(bp, bp+1, (nu->pntsu-a-1)*sizeof(BPoint));
+ nu->pntsu--;
+ a--;
+ type= 1;
+ }
+ else {
+ bp++;
+ }
+ }
+ if(type) {
+ bp1 = (BPoint*)MEM_mallocN(nu->pntsu * sizeof(BPoint), "delNurb2");
+ memcpy(bp1, nu->bp, (nu->pntsu)*sizeof(BPoint) );
+ MEM_freeN(nu->bp);
+ nu->bp= bp1;
+
+ /* Never allow the order to exceed the number of points\
+ - note, this is ok but changes unselected nurbs, disable for now */
+ /*
+ if ((nu->type & 7)==CU_NURBS) {
+ clamp_nurb_order_u(nu);
+ }*/
+ }
+ makeknots(nu, 1);
+ }
+ nu= next;
+ }
+ }
+ else if(type==1) { /* erase segment */
+ /* find the 2 selected points */
+ 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_HIDDENHANDLES(bezt) ) {
+ bezt1= bezt;
+ bezt2= bezt+1;
+ if( (bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT) ) ;
+ else { /* maybe do not make cyclic */
+ if(a==0 && (nu->flagu & CU_CYCLIC) ) {
+ bezt2= bezt+(nu->pntsu-1);
+ if( (bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT) ) {
+ nu->flagu &= ~CU_CYCLIC;
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+ }
+ 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 & SELECT ) {
+ bp1= bp;
+ bp2= bp+1;
+ if( bp2->f1 & 1 ) ;
+ else { /* maybe do not make cyclic */
+ if(a==0 && (nu->flagu & CU_CYCLIC) ) {
+ bp2= bp+(nu->pntsu-1);
+ if( bp2->f1 & SELECT ) {
+ nu->flagu &= ~CU_CYCLIC;
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+ }
+ cut= a;
+ nu1= nu;
+ break;
+ }
+ bp++;
+ }
+ }
+ if(nu1) break;
+
+ nu= nu->next;
+ }
+ if(nu1) {
+ if(bezt1) {
+ if(nu1->pntsu==2) { /* remove completely */
+ BLI_remlink(editnurb, nu);
+ freeNurb(nu); nu = NULL;
+ }
+ else if(nu1->flagu & CU_CYCLIC) { /* 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 &= ~CU_CYCLIC;
+ MEM_freeN(bezt);
+ calchandlesNurb(nu);
+ }
+ else { /* add new curve */
+
+/* seems to be an error here... but where? (a can become zero) */
+
+ 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) { /* remove completely */
+ BLI_remlink(editnurb, nu);
+ freeNurb(nu); nu= NULL;
+ }
+ else if(nu1->flagu & CU_CYCLIC) { /* 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 &= ~CU_CYCLIC;
+ MEM_freeN(bp);
+ }
+ else { /* add new curve */
+ 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(type==2)
+ freeNurblist(editnurb);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+static int delete_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ uiMenuItem *head;
+
+ if(obedit->type==OB_SURF) {
+ head= uiPupMenuBegin("Delete", 0);
+ uiMenuItemEnumO(head, "", 0, op->type->idname, "type", 0);
+ uiMenuItemEnumO(head, "", 0, op->type->idname, "type", 2);
+ uiPupMenuEnd(C, head);
+ }
+ else {
+ head= uiPupMenuBegin("Delete", 0);
+ uiMenuItemsEnumO(head, op->type->idname, "type");
+ uiPupMenuEnd(C, head);
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void CURVE_OT_delete(wmOperatorType *ot)
+{
+ static EnumPropertyItem type_items[] = {
+ {0, "SELECTED", "Selected", ""},
+ {1, "SEGMENT", "Segment", ""},
+ {2, "ALL", "All", ""},
+ {0, NULL, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "Delete";
+ ot->idname= "CURVE_OT_delete";
+
+ /* api callbacks */
+ ot->exec= delete_exec;
+ ot->invoke= delete_invoke;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "Which elements to delete.");
+}
+
+/********************** set smooth operator *********************/
+
+static int set_smooth_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ int clear= RNA_boolean_get(op->ptr, "clear");
+
+ if(obedit->type != OB_CURVE)
+ return OPERATOR_CANCELLED;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if(isNurbsel(nu)) {
+ if(!clear) nu->flag |= CU_SMOOTH;
+ else nu->flag &= ~CU_SMOOTH;
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_smooth_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Smooth";
+ ot->idname= "CURVE_OT_smooth_set";
+
+ /* api callbacks */
+ ot->exec= set_smooth_exec;
+ ot->poll= ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear smooth shading to solid for selection instead of enabling it.");
+}
+
+/************** join operator, to be used externally? ****************/
+
+int join_curve(bContext *C, wmOperator *op, int type)
+{
+ View3D *v3d= CTX_wm_view3d(C);
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_edit_object(C);
+ Base *base, *nextb;
+ Curve *cu;
+ Nurb *nu, *newnu;
+ BezTriple *bezt;
+ BPoint *bp;
+ ListBase tempbase;
+ float imat[4][4], cmat[4][4];
+ int a;
+
+ // XXX not integrated yet, to be called by object/ module? */
+
+ if(object_data_is_libdata(ob)) {
+ BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata");
+ return OPERATOR_CANCELLED;
+ }
+
+ if(ob->type!=type)
+ return 0;
+
+ tempbase.first= tempbase.last= 0;
+
+ /* trasnform all selected curves inverse in obact */
+ Mat4Invert(imat, ob->obmat);
+
+ for(base= FIRSTBASE; base; base=nextb) {
+ nextb= base->next;
+
+ if(TESTBASE(v3d, base)) {
+ if(base->object->type==type) {
+ if(base->object != ob) {
+
+ cu= base->object->data;
+
+ if(cu->nurb.first) {
+ /* watch it: switch order here really goes wrong */
+ 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;
+ }
+ }
+
+ ED_base_object_free_and_unlink(scene, base);
+ }
+ }
+ }
+ }
+
+ cu= ob->data;
+ addlisttolist(&cu->nurb, &tempbase);
+
+ DAG_scene_sort(scene); // because we removed object(s), call before editmode!
+
+ ED_object_enter_editmode(C, EM_WAITCURSOR);
+ ED_object_exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR);
+
+ // BIF_undo_push("Join");
+
+ return OPERATOR_FINISHED;
+}
+
+/************ add primitive, used by object/ module ****************/
+
+Nurb *add_nurbs_primitive(bContext *C, int type, int newname)
+{
+ static int xzproj= 0; /* this function calls itself... */
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ View3D *v3d= CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ Nurb *nu = NULL;
+ BezTriple *bezt;
+ BPoint *bp;
+ float *curs, cent[3],vec[3],imat[3][3],mat[3][3];
+ float fac,cmat[3][3], grid;
+ int a, b, cutype, stype;
+
+ cutype= type & CU_TYPE; // poly, bezier, nurbs, etc
+ stype= type & CU_PRIMITIVE;
+
+ if (v3d) grid = v3d->grid;
+ else grid = 1.0;
+
+ /* imat and center and size */
+ if(obedit) {
+
+ Mat3CpyMat4(mat, obedit->obmat);
+ if(v3d) {
+ curs= give_cursor(scene, v3d);
+ VECCOPY(cent, curs);
+ }
+ else
+ cent[0]= cent[1]= cent[2]= 0.0f;
+
+ cent[0]-= obedit->obmat[3][0];
+ cent[1]-= obedit->obmat[3][1];
+ cent[2]-= obedit->obmat[3][2];
+
+ if(rv3d) {
+ if (!(newname) || U.flag & USER_ADD_VIEWALIGNED || !rv3d)
+ Mat3CpyMat4(imat, rv3d->viewmat);
+ else
+ Mat3One(imat);
+
+ Mat3MulVecfl(imat, cent);
+ Mat3MulMat3(cmat, imat, mat);
+ Mat3Inv(imat, cmat);
+ }
+ setflagsNurb(editnurb, 0);
+ }
+ else {
+ return NULL;
+ }
+
+ /* these types call this function to return a Nurb */
+ if (stype!=CU_PRIM_TUBE && stype!=CU_PRIM_DONUT) {
+ nu = (Nurb*)MEM_callocN(sizeof(Nurb), "addNurbprim");
+ nu->type= type;
+ nu->resolu= 4;
+ nu->resolv= 4;
+ }
+
+ switch(stype) {
+ case CU_PRIM_CURVE: /* curve */
+ nu->resolu= 12; /* set as 4 above */
+ if(newname) {
+ rename_id((ID *)obedit, "Curve");
+ rename_id((ID *)obedit->data, "Curve");
+ }
+ if(cutype==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= SELECT;
+ bezt->radius = 1.0;
+
+ for(a=0;a<3;a++) {
+ VECCOPY(bezt->vec[a], cent);
+ }
+ bezt->vec[1][0]+= -grid;
+ bezt->vec[0][0]+= -1.5*grid;
+ bezt->vec[0][1]+= -0.5*grid;
+ bezt->vec[2][0]+= -0.5*grid;
+ bezt->vec[2][1]+= 0.5*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= SELECT;
+ bezt->radius = bezt->weight = 1.0;
+
+ for(a=0;a<3;a++) {
+ VECCOPY(bezt->vec[a], cent);
+ }
+ bezt->vec[1][0]+= 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= SELECT;
+ bp->radius = bp->weight = 1.0;
+ }
+
+ bp= nu->bp;
+ bp->vec[0]+= -1.5*grid;
+ bp++;
+ bp->vec[0]+= -grid;
+ bp->vec[1]+= grid;
+ bp++;
+ bp->vec[0]+= grid;
+ bp->vec[1]+= grid;
+ bp++;
+ bp->vec[0]+= 1.5*grid;
+
+ bp= nu->bp;
+ for(a=0;a<4;a++, bp++) Mat3MulVecfl(imat,bp->vec);
+
+ if(cutype==CU_NURBS) {
+ nu->knotsu= 0; /* makeknots allocates */
+ makeknots(nu, 1);
+ }
+
+ }
+ break;
+ case CU_PRIM_PATH: /* 5 point path */
+ nu->pntsu= 5;
+ nu->pntsv= 1;
+ nu->orderu= 5;
+ nu->flagu= 2; /* endpoint */
+ nu->resolu= 8;
+ 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= SELECT;
+ bp->radius = bp->weight = 1.0;
+ }
+
+ bp= nu->bp;
+ bp->vec[0]+= -2.0*grid;
+ bp++;
+ bp->vec[0]+= -grid;
+ bp++; bp++;
+ bp->vec[0]+= grid;
+ bp++;
+ bp->vec[0]+= 2.0*grid;
+
+ bp= nu->bp;
+ for(a=0;a<5;a++, bp++) Mat3MulVecfl(imat,bp->vec);
+
+ if(cutype==CU_NURBS) {
+ nu->knotsu= 0; /* makeknots allocates */
+ makeknots(nu, 1);
+ }
+
+ break;
+ case CU_PRIM_CIRCLE: /* circle */
+ nu->resolu= 12; /* set as 4 above */
+ if(newname) {
+ rename_id((ID *)obedit, "CurveCircle");
+ rename_id((ID *)obedit->data, "CurveCircle");
+ }
+ if(cutype==CU_BEZIER) {
+ nu->pntsu= 4;
+ nu->bezt= callocstructN(BezTriple, 4, "addNurbprim1");
+ nu->flagu= CU_CYCLIC;
+ 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= SELECT;
+ bezt->vec[1][0]+= -grid;
+ for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
+ bezt->radius = bezt->weight = 1.0;
+
+ bezt++;
+ for(a=0;a<3;a++) {
+ VECCOPY(bezt->vec[a], cent);
+ }
+ bezt->h1= bezt->h2= HD_AUTO;
+ bezt->f1= bezt->f2= bezt->f3= SELECT;
+ bezt->vec[1][1]+= grid;
+ for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
+ bezt->radius = bezt->weight = 1.0;
+
+ bezt++;
+ for(a=0;a<3;a++) {
+ VECCOPY(bezt->vec[a], cent);
+ }
+ bezt->h1= bezt->h2= HD_AUTO;
+ bezt->f1= bezt->f2= bezt->f3= SELECT;
+ bezt->vec[1][0]+= grid;
+ for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
+ bezt->radius = bezt->weight = 1.0;
+
+ bezt++;
+ for(a=0;a<3;a++) {
+ VECCOPY(bezt->vec[a], cent);
+ }
+ bezt->h1= bezt->h2= HD_AUTO;
+ bezt->f1= bezt->f2= bezt->f3= SELECT;
+ bezt->vec[1][1]+= -grid;
+ for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
+ bezt->radius = bezt->weight = 1.0;
+
+ calchandlesNurb(nu);
+ }
+ else if( cutype==CU_NURBS ) { /* nurb */
+ nu->pntsu= 8;
+ nu->pntsv= 1;
+ nu->orderu= 4;
+ nu->bp= callocstructN(BPoint, 8, "addNurbprim6");
+ nu->flagu= CU_CYCLIC;
+ bp= nu->bp;
+
+ for(a=0; a<8; a++) {
+ bp->f1= SELECT;
+ VECCOPY(bp->vec, cent);
+
+ if(xzproj==0) {
+ bp->vec[0]+= nurbcircle[a][0]*grid;
+ bp->vec[1]+= nurbcircle[a][1]*grid;
+ }
+ else {
+ bp->vec[0]+= 0.25*nurbcircle[a][0]*grid-.75*grid;
+ bp->vec[2]+= 0.25*nurbcircle[a][1]*grid;
+ }
+ if(a & 1) bp->vec[3]= 0.25*sqrt(2.0);
+ else bp->vec[3]= 1.0;
+ Mat3MulVecfl(imat,bp->vec);
+ bp->radius = bp->weight = 1.0;
+
+ bp++;
+ }
+
+ makeknots(nu, 1);
+ }
+ break;
+ case CU_PRIM_PATCH: /* 4x4 patch */
+ if( cutype==CU_NURBS ) { /* nurb */
+ if(newname) {
+ rename_id((ID *)obedit, "Surf");
+ rename_id((ID *)obedit->data, "Surf");
+ }
+
+ nu->pntsu= 4;
+ nu->pntsv= 4;
+ nu->orderu= 4;
+ nu->orderv= 4;
+ nu->flag= CU_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= SELECT;
+ fac= (float)a -1.5;
+ bp->vec[0]+= fac*grid;
+ fac= (float)b -1.5;
+ bp->vec[1]+= fac*grid;
+ if(a==1 || a==2) if(b==1 || b==2) {
+ bp->vec[2]+= grid;
+ }
+ Mat3MulVecfl(imat,bp->vec);
+ bp->vec[3]= 1.0;
+ bp++;
+ }
+ }
+
+ makeknots(nu, 1);
+ makeknots(nu, 2);
+ }
+ break;
+ case CU_PRIM_TUBE: /* tube */
+ if( cutype==CU_NURBS ) {
+ if(newname) {
+ rename_id((ID *)obedit, "SurfTube");
+ rename_id((ID *)obedit->data, "SurfTube");
+ }
+
+ nu= add_nurbs_primitive(C, CU_NURBS|CU_PRIM_CIRCLE, 0); /* circle */
+ nu->resolu= 4;
+ nu->flag= CU_SMOOTH;
+ BLI_addtail(editnurb, nu); /* temporal for extrude and translate */
+ vec[0]=vec[1]= 0.0;
+ vec[2]= -grid;
+ Mat3MulVecfl(imat, vec);
+ translateflagNurb(editnurb, 1, vec);
+ extrudeflagNurb(editnurb, 1);
+ vec[0]= -2*vec[0];
+ vec[1]= -2*vec[1];
+ vec[2]= -2*vec[2];
+ translateflagNurb(editnurb, 1, vec);
+
+ BLI_remlink(editnurb, nu);
+
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a-- >0) {
+ bp->f1 |= SELECT;
+ bp++;
+ }
+ }
+ break;
+ case CU_PRIM_SPHERE: /* sphere */
+ if( cutype==CU_NURBS ) {
+ if(newname) {
+ rename_id((ID *)obedit, "SurfSphere");
+ rename_id((ID *)obedit->data, "SurfSphere");
+ }
+
+ nu->pntsu= 5;
+ nu->pntsv= 1;
+ nu->orderu= 3;
+ nu->resolu= 4;
+ nu->resolv= 4;
+ nu->flag= CU_SMOOTH;
+ nu->bp= callocstructN(BPoint, 5, "addNurbprim6");
+ nu->flagu= 0;
+ bp= nu->bp;
+
+ for(a=0; a<5; a++) {
+ bp->f1= SELECT;
+ VECCOPY(bp->vec, cent);
+ bp->vec[0]+= nurbcircle[a][0]*grid;
+ bp->vec[2]+= nurbcircle[a][1]*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);
+
+ BLI_addtail(editnurb, nu); /* temporal for spin */
+ if(newname && (U.flag & USER_ADD_VIEWALIGNED) == 0)
+ spin_nurb(C, scene, obedit, 0, 2);
+ else
+ spin_nurb(C, scene, obedit, 0, 0);
+
+ makeknots(nu, 2);
+
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a-- >0) {
+ bp->f1 |= SELECT;
+ bp++;
+ }
+ BLI_remlink(editnurb, nu);
+ }
+ break;
+ case CU_PRIM_DONUT: /* donut */
+ if( cutype==CU_NURBS ) {
+ if(newname) {
+ rename_id((ID *)obedit, "SurfDonut");
+ rename_id((ID *)obedit->data, "SurfDonut");
+ }
+
+ xzproj= 1;
+ nu= add_nurbs_primitive(C, CU_NURBS|CU_PRIM_CIRCLE, 0); /* circle */
+ xzproj= 0;
+ nu->resolu= 4;
+ nu->resolv= 4;
+ nu->flag= CU_SMOOTH;
+ BLI_addtail(editnurb, nu); /* temporal for extrude and translate */
+ if(newname && (U.flag & USER_ADD_VIEWALIGNED) == 0)
+ spin_nurb(C, scene, obedit, 0, 2);
+ else
+ spin_nurb(C, scene, obedit, 0, 0);
+
+ BLI_remlink(editnurb, nu);
+
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a-- >0) {
+ bp->f1 |= SELECT;
+ bp++;
+ }
+
+ }
+ break;
+ }
+
+ /* always do: */
+ nu->flag= CU_SMOOTH;
+
+ test2DNurb(nu);
+
+ return nu;
+}
+
+/***************** clear tilt operator ********************/
+
+static int clear_tilt_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if( nu->bezt ) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(BEZSELECTED_HIDDENHANDLES(bezt)) bezt->alfa= 0.0;
+ bezt++;
+ }
+ }
+ else if(nu->bp) {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp->f1 & SELECT) bp->alfa= 0.0;
+ bp++;
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_tilt_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Clear Tilt";
+ ot->idname= "CURVE_OT_tilt_clear";
+
+ /* api callbacks */
+ ot->exec= clear_tilt_exec;
+ ot->poll= ED_operator_editcurve;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/****************** undo for curves ****************/
+
+static void undoCurve_to_editCurve(void *lbu, void *lbe)
+{
+ ListBase *lb= lbu;
+ ListBase *editnurb= lbe;
+ Nurb *nu, *newnu;
+
+ freeNurblist(editnurb);
+
+ /* copy */
+ for(nu= lb->first; nu; nu= nu->next) {
+ newnu= duplicateNurb(nu);
+ BLI_addtail(editnurb, newnu);
+ }
+}
+
+static void *editCurve_to_undoCurve(void *lbe)
+{
+ ListBase *editnurb= lbe;
+ ListBase *lb;
+ Nurb *nu, *newnu;
+
+ lb= MEM_callocN(sizeof(ListBase), "listbase undo");
+
+ /* copy */
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ newnu= duplicateNurb(nu);
+ BLI_addtail(lb, newnu);
+ }
+ return lb;
+}
+
+static void free_undoCurve(void *lbv)
+{
+ ListBase *lb= lbv;
+
+ freeNurblist(lb);
+ MEM_freeN(lb);
+}
+
+static void *get_data(bContext *C)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ return curve_get_editcurve(obedit);
+}
+
+/* and this is all the undo system needs to know */
+void undo_push_curve(bContext *C, char *name)
+{
+ undo_editmode_push(C, name, get_data, free_undoCurve, undoCurve_to_editCurve, editCurve_to_undoCurve, NULL);
+}
+
+/***************** XXX old cruft ********************/
+
+void default_curve_ipo(Scene *scene, Curve *cu)
+{
+#if 0 // XXX old animation system
+ IpoCurve *icu;
+ BezTriple *bezt;
+
+ if(cu->ipo) return;
+
+ cu->ipo= add_ipo(scene, "CurveIpo", ID_CU);
+
+ icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
+
+ icu->blocktype= ID_CU;
+ icu->adrcode= CU_SPEED;
+ icu->flag= IPO_VISIBLE|IPO_SELECT|IPO_AUTO_HORIZ;
+ 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);
+#endif // XXX old animation system
+}
+
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
new file mode 100644
index 00000000000..ec4e79a7e5a
--- /dev/null
+++ b/source/blender/editors/curve/editfont.c
@@ -0,0 +1,1625 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <wchar.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_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_text_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_font.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_curve.h"
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+
+#include "curve_intern.h"
+
+#define MAXTEXT 32766
+
+/************************* utilities ******************************/
+
+static char findaccent(char char1, unsigned int 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;
+}
+
+
+void update_string(Curve *cu)
+{
+ EditFont *ef= cu->editfont;
+ int len;
+
+ // Free the old curve string
+ MEM_freeN(cu->str);
+
+ // Calculate the actual string length in UTF-8 variable characters
+ len = wcsleninu8(ef->textbuf);
+
+ // Alloc memory for UTF-8 variable char length string
+ cu->str = MEM_callocN(len + sizeof(wchar_t), "str");
+
+ // Copy the wchar to UTF-8
+ wcs2utf8s(cu->str, ef->textbuf);
+}
+
+static int insert_into_textbuf(Object *obedit, unsigned long c)
+{
+ Curve *cu= obedit->data;
+
+ if(cu->len<MAXTEXT-1) {
+ EditFont *ef= cu->editfont;
+ int x;
+
+ for(x= cu->len; x>cu->pos; x--) ef->textbuf[x]= ef->textbuf[x-1];
+ for(x= cu->len; x>cu->pos; x--) ef->textbufinfo[x]= ef->textbufinfo[x-1];
+ ef->textbuf[cu->pos]= c;
+ ef->textbufinfo[cu->pos] = cu->curinfo;
+ ef->textbufinfo[cu->pos].kern = 0;
+ if(obedit->actcol>0)
+ ef->textbufinfo[cu->pos].mat_nr = obedit->actcol;
+ else
+ ef->textbufinfo[cu->pos].mat_nr = 0;
+
+ cu->pos++;
+ cu->len++;
+ ef->textbuf[cu->len]='\0';
+
+ update_string(cu);
+
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static void text_update_edited(bContext *C, Scene *scene, Object *obedit, int recalc, int mode)
+{
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+
+ if(cu->pos)
+ cu->curinfo = ef->textbufinfo[cu->pos-1];
+ else
+ cu->curinfo = ef->textbufinfo[0];
+
+ if(obedit->totcol>0)
+ obedit->actcol= ef->textbufinfo[cu->pos-1].mat_nr;
+
+ update_string(cu);
+ BKE_text_to_curve(scene, obedit, mode);
+
+ if(recalc)
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+}
+
+/********************** insert lorem operator *********************/
+
+static int insert_lorem_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ char *p, *p2;
+ int i;
+ static char *lastlorem;
+
+ if(lastlorem)
+ p= lastlorem;
+ else
+ p= ED_lorem;
+
+ i= rand()/(RAND_MAX/6)+4;
+
+ for(p2=p; *p2 && i; p2++) {
+ insert_into_textbuf(obedit, *p2);
+
+ if(*p2=='.')
+ i--;
+ }
+
+ lastlorem = p2+1;
+ if(strlen(lastlorem)<5)
+ lastlorem = ED_lorem;
+
+ insert_into_textbuf(obedit, '\n');
+ insert_into_textbuf(obedit, '\n');
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void FONT_OT_insert_lorem(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Insert Lorem";
+ ot->idname= "FONT_OT_insert_lorem";
+
+ /* api callbacks */
+ ot->exec= insert_lorem_exec;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/******************* paste file operator ********************/
+
+/* note this handles both ascii and utf8 unicode, previously
+ * there were 3 functions that did effectively the same thing. */
+
+static int paste_file(bContext *C, ReportList *reports, char *filename)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+ FILE *fp;
+ int filelen;
+ char *strp;
+
+ fp= fopen(filename, "r");
+
+ if(!fp) {
+ if(reports)
+ BKE_reportf(reports, RPT_ERROR, "Failed to open file %s.", filename);
+ return OPERATOR_CANCELLED;
+ }
+
+ fseek(fp, 0L, SEEK_END);
+ filelen = ftell(fp);
+ fseek(fp, 0L, SEEK_SET);
+
+ strp= MEM_callocN(filelen+4, "tempstr");
+
+ // fread() instead of read(), because windows read() converts text
+ // to DOS \r\n linebreaks, causing double linebreaks in the 3d text
+ filelen = fread(strp, 1, filelen, fp);
+ fclose(fp);
+ strp[filelen]= 0;
+
+ if(cu->len+filelen<MAXTEXT) {
+ int tmplen;
+ wchar_t *mem = MEM_callocN((sizeof(wchar_t)*filelen)+(4*sizeof(wchar_t)), "temporary");
+ tmplen = utf8towchar(mem, strp);
+ wcscat(ef->textbuf, mem);
+ MEM_freeN(mem);
+ cu->len += tmplen;
+ cu->pos= cu->len;
+ }
+ MEM_freeN(strp);
+
+ text_update_edited(C, scene, obedit, 1, 0);
+
+ return OPERATOR_FINISHED;
+}
+
+static int paste_file_exec(bContext *C, wmOperator *op)
+{
+ char *filename;
+ int retval;
+
+ filename= RNA_string_get_alloc(op->ptr, "filename", NULL, 0);
+ retval= paste_file(C, op->reports, filename);
+ MEM_freeN(filename);
+
+ return retval;
+}
+
+static int paste_file_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ if(RNA_property_is_set(op->ptr, "filename"))
+ return paste_file_exec(C, op);
+
+ WM_event_add_fileselect(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void FONT_OT_file_paste(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Paste File";
+ ot->idname= "FONT_OT_file_paste";
+
+ /* api callbacks */
+ ot->exec= paste_file_exec;
+ ot->invoke= paste_file_invoke;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_string_file_path(ot->srna, "filename", "", 0, "Filename", "File path of text file to load.");
+}
+
+/******************* paste buffer operator ********************/
+
+static int paste_buffer_exec(bContext *C, wmOperator *op)
+{
+ char *filename;
+
+#ifdef WIN32
+ filename= "C:\\windows\\temp\\cutbuf.txt";
+
+// The following is more likely to work on all Win32 installations.
+// suggested by Douglas Toltzman. Needs windows include files...
+/*
+ char tempFileName[MAX_PATH];
+ DWORD pathlen;
+ static const char cutbufname[]="cutbuf.txt";
+
+ if((pathlen=GetTempPath(sizeof(tempFileName),tempFileName)) > 0 &&
+ pathlen + sizeof(cutbufname) <= sizeof(tempFileName))
+ {
+ strcat(tempFileName,cutbufname);
+ filename= tempFilename;
+ }
+*/
+#else
+ filename= "/tmp/.cutbuffer";
+#endif
+
+ return paste_file(C, NULL, filename);
+}
+
+void FONT_OT_buffer_paste(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Paste Buffer";
+ ot->idname= "FONT_OT_buffer_paste";
+
+ /* api callbacks */
+ ot->exec= paste_buffer_exec;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/******************* text to object operator ********************/
+
+static void txt_add_object(bContext *C, TextLine *firstline, int totline, float offset[3])
+{
+ Scene *scene= CTX_data_scene(C);
+ Curve *cu;
+ Object *obedit;
+ Base *base;
+ struct TextLine *tmp;
+ int nchars = 0, a;
+
+ obedit= add_object(scene, OB_FONT);
+ base= scene->basact;
+
+ ED_object_base_init_from_view(C, base);
+ where_is_object(scene, obedit);
+
+ obedit->loc[0] += offset[0];
+ obedit->loc[1] += offset[1];
+ obedit->loc[2] += offset[2];
+
+ cu= obedit->data;
+ cu->vfont= get_builtin_font();
+ cu->vfont->id.us++;
+
+ for(tmp=firstline, a=0; cu->len<MAXTEXT && a<totline; tmp=tmp->next, a++)
+ nchars += strlen(tmp->line) + 1;
+
+ if(cu->str) MEM_freeN(cu->str);
+ if(cu->strinfo) MEM_freeN(cu->strinfo);
+
+ cu->str= MEM_callocN(nchars+4, "str");
+ cu->strinfo= MEM_callocN((nchars+4)*sizeof(CharInfo), "strinfo");
+
+ cu->str[0]= '\0';
+ cu->len= 0;
+ cu->pos= 0;
+
+ for(tmp=firstline, a=0; cu->len<MAXTEXT && a<totline; tmp=tmp->next, a++) {
+ strcat(cu->str, tmp->line);
+ cu->len+= strlen(tmp->line);
+
+ if(tmp->next) {
+ strcat(cu->str, "\n");
+ cu->len++;
+ }
+
+ cu->pos= cu->len;
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|NA_ADDED, obedit);
+}
+
+void ED_text_to_object(bContext *C, Text *text, int split_lines)
+{
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ TextLine *line;
+ float offset[3];
+ int linenum= 0;
+
+ if(!text || !text->lines.first) return;
+
+ if(split_lines) {
+ for(line=text->lines.first; line; line=line->next) {
+ /* skip lines with no text, but still make space for them */
+ if(line->line[0] == '\0') {
+ linenum++;
+ continue;
+ }
+
+ /* do the translation */
+ offset[0] = 0;
+ offset[1] = -linenum;
+ offset[2] = 0;
+
+ if(rv3d)
+ Mat4Mul3Vecfl(rv3d->viewinv, offset);
+
+ txt_add_object(C, line, 1, offset);
+
+ linenum++;
+ }
+ }
+ else {
+ offset[0]= 0.0f;
+ offset[1]= 0.0f;
+ offset[2]= 0.0f;
+
+ txt_add_object(C, text->lines.first, BLI_countlist(&text->lines), offset);
+ }
+}
+
+/********************** utilities ***************************/
+
+static short next_word(Curve *cu)
+{
+ short s;
+ for(s=cu->pos; (cu->str[s]) && (cu->str[s]!=' ') && (cu->str[s]!='\n') &&
+ (cu->str[s]!=1) && (cu->str[s]!='\r'); s++);
+ if(cu->str[s]) return(s+1); else return(s);
+}
+
+static short prev_word(Curve *cu)
+{
+ short s;
+
+ if(cu->pos==0) return(0);
+ for(s=cu->pos-2; (cu->str[s]) && (cu->str[s]!=' ') && (cu->str[s]!='\n') &&
+ (cu->str[s]!=1) && (cu->str[s]!='\r'); s--);
+ if(cu->str[s]) return(s+1); else return(s);
+}
+
+static int kill_selection(Object *obedit, int ins) /* 1 == new character */
+{
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+ int selend, selstart, direction;
+ int offset = 0;
+ int getfrom;
+
+ direction = BKE_font_getselection(obedit, &selstart, &selend);
+ if(direction) {
+ int size;
+ if(ins) offset = 1;
+ if(cu->pos >= selstart) cu->pos = selstart+offset;
+ if((direction == -1) && ins) {
+ selstart++;
+ selend++;
+ }
+ getfrom = selend+offset;
+ if(ins==0) getfrom++;
+ size = (cu->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset*sizeof(wchar_t));
+ memmove(ef->textbuf+selstart, ef->textbuf+getfrom, size);
+ memmove(ef->textbufinfo+selstart, ef->textbufinfo+getfrom, ((cu->len-selstart)+offset)*sizeof(CharInfo));
+ cu->len -= (selend-selstart)+offset;
+ cu->selstart = cu->selend = 0;
+ }
+
+ return(direction);
+}
+
+/******************* set style operator ********************/
+
+static EnumPropertyItem style_items[]= {
+ {CU_BOLD, "BOLD", "Bold", ""},
+ {CU_ITALIC, "ITALIC", "Italic", ""},
+ {CU_UNDERLINE, "UNDERLINE", "Underline", ""},
+ {0, NULL, NULL, NULL}};
+
+static int set_style(bContext *C, int style, int clear)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+ int i, selstart, selend;
+
+ if(!BKE_font_getselection(obedit, &selstart, &selend))
+ return OPERATOR_CANCELLED;
+
+ for(i=selstart; i<=selend; i++) {
+ if(clear)
+ ef->textbufinfo[i].flag &= ~style;
+ else
+ ef->textbufinfo[i].flag |= style;
+ }
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+static int set_style_exec(bContext *C, wmOperator *op)
+{
+ int style, clear;
+
+ style= RNA_enum_get(op->ptr, "style");
+ clear= RNA_enum_get(op->ptr, "clear");
+
+ return set_style(C, style, clear);
+}
+
+void FONT_OT_style_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Style";
+ ot->idname= "FONT_OT_style_set";
+
+ /* api callbacks */
+ ot->exec= set_style_exec;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "style", style_items, CU_BOLD, "Style", "Style to set selection to.");
+ RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear style rather than setting it.");
+}
+
+/******************* toggle style operator ********************/
+
+static int toggle_style_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Curve *cu= obedit->data;
+ int style, clear, selstart, selend;
+
+ if(!BKE_font_getselection(obedit, &selstart, &selend))
+ return OPERATOR_CANCELLED;
+
+ style= RNA_enum_get(op->ptr, "style");
+
+ cu->curinfo.flag ^= style;
+ clear= (cu->curinfo.flag & style) == 0;
+
+ return set_style(C, style, clear);
+}
+
+void FONT_OT_style_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Toggle Style";
+ ot->idname= "FONT_OT_style_toggle";
+
+ /* api callbacks */
+ ot->exec= toggle_style_exec;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "style", style_items, CU_BOLD, "Style", "Style to set selection to.");
+}
+
+/******************* set material operator ********************/
+
+static int set_material_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+ int i, mat_nr, selstart, selend;
+
+ if(!BKE_font_getselection(obedit, &selstart, &selend))
+ return OPERATOR_CANCELLED;
+
+ if(RNA_property_is_set(op->ptr, "index"))
+ mat_nr= RNA_int_get(op->ptr, "index");
+ else
+ mat_nr= obedit->actcol;
+
+ for(i=selstart; i<=selend; i++)
+ ef->textbufinfo[i].mat_nr = mat_nr;
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void FONT_OT_material_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Material";
+ ot->idname= "FONT_OT_material_set";
+
+ /* api callbacks */
+ ot->exec= set_material_exec;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Material Index", "Material slot index.", 0, INT_MAX);
+}
+
+/******************* copy text operator ********************/
+
+static void copy_selection(Object *obedit)
+{
+ int selstart, selend;
+
+ if(BKE_font_getselection(obedit, &selstart, &selend)) {
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+
+ memcpy(ef->copybuf, ef->textbuf+selstart, ((selend-selstart)+1)*sizeof(wchar_t));
+ ef->copybuf[(selend-selstart)+1]=0;
+ memcpy(ef->copybufinfo, ef->textbufinfo+selstart, ((selend-selstart)+1)*sizeof(CharInfo));
+ }
+}
+
+static int copy_text_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+
+ copy_selection(obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void FONT_OT_text_copy(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Copy Text";
+ ot->idname= "FONT_OT_text_copy";
+
+ /* api callbacks */
+ ot->exec= copy_text_exec;
+ ot->poll= ED_operator_editfont;
+}
+
+/******************* cut text operator ********************/
+
+static int cut_text_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ int selstart, selend;
+
+ if(!BKE_font_getselection(obedit, &selstart, &selend))
+ return OPERATOR_CANCELLED;
+
+ copy_selection(obedit);
+ kill_selection(obedit, 0);
+
+ text_update_edited(C, scene, obedit, 1, 0);
+
+ return OPERATOR_FINISHED;
+}
+
+void FONT_OT_text_cut(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Cut Text";
+ ot->idname= "FONT_OT_text_cut";
+
+ /* api callbacks */
+ ot->exec= cut_text_exec;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/******************* paste text operator ********************/
+
+static int paste_selection(Object *obedit, ReportList *reports)
+{
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+ int len= wcslen(ef->copybuf);
+
+ // Verify that the copy buffer => [copy buffer len] + cu->len < MAXTEXT
+ if(cu->len + len <= MAXTEXT) {
+ if(len) {
+ int size = (cu->len * sizeof(wchar_t)) - (cu->pos*sizeof(wchar_t)) + sizeof(wchar_t);
+ memmove(ef->textbuf+cu->pos+len, ef->textbuf+cu->pos, size);
+ memcpy(ef->textbuf+cu->pos, ef->copybuf, len * sizeof(wchar_t));
+
+ memmove(ef->textbufinfo+cu->pos+len, ef->textbufinfo+cu->pos, (cu->len-cu->pos+1)*sizeof(CharInfo));
+ memcpy(ef->textbufinfo+cu->pos, ef->copybufinfo, len*sizeof(CharInfo));
+
+ cu->len += len;
+ cu->pos += len;
+
+ return 1;
+ }
+ }
+ else
+ BKE_report(reports, RPT_WARNING, "Text too long.");
+
+ return 0;
+}
+
+static int paste_text_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+
+ if(!paste_selection(obedit, op->reports))
+ return OPERATOR_CANCELLED;
+
+ text_update_edited(C, scene, obedit, 1, 0);
+
+ return OPERATOR_FINISHED;
+}
+
+void FONT_OT_text_paste(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Paste Text";
+ ot->idname= "FONT_OT_text_paste";
+
+ /* api callbacks */
+ ot->exec= paste_text_exec;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/************************ move operator ************************/
+
+static EnumPropertyItem move_type_items[]= {
+ {LINE_BEGIN, "LINE_BEGIN", "Line Begin", ""},
+ {LINE_END, "LINE_END", "Line End", ""},
+ {PREV_CHAR, "PREVIOUS_CHARACTER", "Previous Character", ""},
+ {NEXT_CHAR, "NEXT_CHARACTER", "Next Character", ""},
+ {PREV_WORD, "PREVIOUS_WORD", "Previous Word", ""},
+ {NEXT_WORD, "NEXT_WORD", "Next Word", ""},
+ {PREV_LINE, "PREVIOUS_LINE", "Previous Line", ""},
+ {NEXT_LINE, "NEXT_LINE", "Next Line", ""},
+ {PREV_PAGE, "PREVIOUS_PAGE", "Previous Page", ""},
+ {NEXT_PAGE, "NEXT_PAGE", "Next Page", ""},
+ {0, NULL, NULL, NULL}};
+
+static int move_cursor(bContext *C, int type, int select)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+ int cursmove= 0;
+
+ switch(type) {
+ case LINE_BEGIN:
+ if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+ while(cu->pos>0) {
+ if(ef->textbuf[cu->pos-1]=='\n') break;
+ if(ef->textbufinfo[cu->pos-1].flag & CU_WRAP ) break;
+ cu->pos--;
+ }
+ cursmove=FO_CURS;
+ break;
+
+ case LINE_END:
+ if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+ while(cu->pos<cu->len) {
+ if(ef->textbuf[cu->pos]==0) break;
+ if(ef->textbuf[cu->pos]=='\n') break;
+ if(ef->textbufinfo[cu->pos].flag & CU_WRAP ) break;
+ cu->pos++;
+ }
+ cursmove=FO_CURS;
+ break;
+
+ case PREV_WORD:
+ if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+ cu->pos= prev_word(cu);
+ cursmove= FO_CURS;
+ break;
+
+ case NEXT_WORD:
+ if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+ cu->pos= next_word(cu);
+ cursmove= FO_CURS;
+ break;
+
+ case PREV_CHAR:
+ if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+ cu->pos--;
+ cursmove=FO_CURS;
+ break;
+
+ case NEXT_CHAR:
+ if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+ cu->pos++;
+ cursmove= FO_CURS;
+
+ break;
+
+ case PREV_LINE:
+ if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+ cursmove=FO_CURSUP;
+ break;
+
+ case NEXT_LINE:
+ if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+ cursmove= FO_CURSDOWN;
+ break;
+
+ case PREV_PAGE:
+ if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+ cursmove=FO_PAGEUP;
+ break;
+
+ case NEXT_PAGE:
+ if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+ cursmove=FO_PAGEDOWN;
+ break;
+ }
+
+ if(!cursmove)
+ return OPERATOR_CANCELLED;
+
+ if(select == 0) {
+ if(cu->selstart) {
+ cu->selstart = cu->selend = 0;
+ update_string(cu);
+ BKE_text_to_curve(scene, obedit, FO_SELCHANGE);
+ }
+ }
+
+ 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;
+
+ text_update_edited(C, scene, obedit, select, cursmove);
+
+ if(select)
+ cu->selend = cu->pos;
+
+ return OPERATOR_FINISHED;
+}
+
+static int move_exec(bContext *C, wmOperator *op)
+{
+ int type= RNA_enum_get(op->ptr, "type");
+
+ return move_cursor(C, type, 0);
+}
+
+void FONT_OT_move(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Move Cursor";
+ ot->idname= "FONT_OT_move";
+
+ /* api callbacks */
+ ot->exec= move_exec;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to.");
+}
+
+/******************* move select operator ********************/
+
+static int move_select_exec(bContext *C, wmOperator *op)
+{
+ int type= RNA_enum_get(op->ptr, "type");
+
+ return move_cursor(C, type, 1);
+}
+
+void FONT_OT_move_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Move Select";
+ ot->idname= "FONT_OT_move_select";
+
+ /* api callbacks */
+ ot->exec= move_select_exec;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to, to make a selection.");
+}
+
+/************************* change spacing **********************/
+
+static int change_spacing_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+ int kern, delta= RNA_int_get(op->ptr, "delta");
+
+ kern = ef->textbufinfo[cu->pos-1].kern;
+ kern += delta;
+ CLAMP(kern, -20, 20);
+
+ if(ef->textbufinfo[cu->pos-1].kern == kern)
+ return OPERATOR_CANCELLED;
+
+ ef->textbufinfo[cu->pos-1].kern = kern;
+
+ text_update_edited(C, scene, obedit, 1, 0);
+
+ return OPERATOR_FINISHED;
+}
+
+void FONT_OT_change_spacing(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Change Spacing";
+ ot->idname= "FONT_OT_change_spacing";
+
+ /* api callbacks */
+ ot->exec= change_spacing_exec;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "delta", 1, -20, 20, "Delta", "Amount to decrease or increasing character spacing with.", -20, 20);
+}
+
+/************************* change character **********************/
+
+static int change_character_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+ int character, delta= RNA_int_get(op->ptr, "delta");
+
+ if(cu->pos <= 0)
+ return OPERATOR_CANCELLED;
+
+ character= ef->textbuf[cu->pos - 1];
+ character += delta;
+ CLAMP(character, 0, 255);
+
+ if(character == ef->textbuf[cu->pos - 1])
+ return OPERATOR_CANCELLED;
+
+ ef->textbuf[cu->pos - 1]= character;
+
+ text_update_edited(C, scene, obedit, 1, 0);
+
+ return OPERATOR_FINISHED;
+}
+
+void FONT_OT_change_character(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Change Character";
+ ot->idname= "FONT_OT_change_character";
+
+ /* api callbacks */
+ ot->exec= change_character_exec;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "delta", 1, -255, 255, "Delta", "Number to increase or decrease character code with.", -255, 255);
+}
+
+/******************* line break operator ********************/
+
+static int line_break_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+ int ctrl= RNA_enum_get(op->ptr, "ctrl");
+
+ if(ctrl) {
+ insert_into_textbuf(obedit, 1);
+ if(ef->textbuf[cu->pos]!='\n')
+ insert_into_textbuf(obedit, '\n');
+ }
+ else
+ insert_into_textbuf(obedit, '\n');
+
+ cu->selstart = cu->selend = 0;
+
+ text_update_edited(C, scene, obedit, 1, 0);
+
+ return OPERATOR_FINISHED;
+}
+
+void FONT_OT_line_break(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Line Break";
+ ot->idname= "FONT_OT_line_break";
+
+ /* api callbacks */
+ ot->exec= line_break_exec;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "ctrl", 0, "Ctrl", ""); // XXX what is this?
+}
+
+/******************* delete operator **********************/
+
+static EnumPropertyItem delete_type_items[]= {
+ {DEL_ALL, "ALL", "All", ""},
+ {DEL_NEXT_CHAR, "NEXT_CHARACTER", "Next Character", ""},
+ {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", "Previous Character", ""},
+ {DEL_SELECTION, "SELECTION", "Selection", ""},
+ {DEL_NEXT_SEL, "NEXT_OR_SELECTION", "Next or Selection", ""},
+ {DEL_PREV_SEL, "PREVIOUS_OR_SELECTION", "Previous or Selection", ""},
+ {0, NULL, NULL, NULL}};
+
+static int delete_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+ int x, selstart, selend, type= RNA_enum_get(op->ptr, "type");
+
+ if(cu->len == 0)
+ return OPERATOR_CANCELLED;
+
+ if(BKE_font_getselection(obedit, &selstart, &selend)) {
+ if(type == DEL_NEXT_SEL) type= DEL_SELECTION;
+ else if(type == DEL_PREV_SEL) type= DEL_SELECTION;
+ }
+ else {
+ if(type == DEL_NEXT_SEL) type= DEL_NEXT_CHAR;
+ else if(type == DEL_PREV_SEL) type= DEL_PREV_CHAR;
+ }
+
+ switch(type) {
+ case DEL_ALL:
+ cu->len = cu->pos = 0;
+ ef->textbuf[0]= 0;
+ break;
+ case DEL_SELECTION:
+ if(!kill_selection(obedit, 0))
+ return OPERATOR_CANCELLED;
+ break;
+ case DEL_PREV_CHAR:
+ if(cu->pos<=0)
+ return OPERATOR_CANCELLED;
+
+ for(x=cu->pos;x<=cu->len;x++)
+ ef->textbuf[x-1]= ef->textbuf[x];
+ for(x=cu->pos;x<=cu->len;x++)
+ ef->textbufinfo[x-1]= ef->textbufinfo[x];
+
+ cu->pos--;
+ ef->textbuf[--cu->len]='\0';
+ break;
+ case DEL_NEXT_CHAR:
+ if(cu->pos>=cu->len)
+ return OPERATOR_CANCELLED;
+
+ for(x=cu->pos;x<cu->len;x++)
+ ef->textbuf[x]= ef->textbuf[x+1];
+ for(x=cu->pos;x<cu->len;x++)
+ ef->textbufinfo[x]= ef->textbufinfo[x+1];
+
+ ef->textbuf[--cu->len]='\0';
+ break;
+ default:
+ return OPERATOR_CANCELLED;
+ }
+
+ text_update_edited(C, scene, obedit, 1, 0);
+
+ return OPERATOR_FINISHED;
+}
+
+void FONT_OT_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete";
+ ot->idname= "FONT_OT_delete";
+
+ /* api callbacks */
+ ot->exec= delete_exec;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", delete_type_items, DEL_ALL, "Type", "Which part of the text to delete.");
+}
+
+/*********************** insert text operator *************************/
+
+static int insert_text_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ char *inserted_utf8;
+ wchar_t *inserted_text, first;
+ int len;
+
+ if(!RNA_property_is_set(op->ptr, "text"))
+ return OPERATOR_CANCELLED;
+
+ inserted_utf8= RNA_string_get_alloc(op->ptr, "text", NULL, 0);
+ len= strlen(inserted_utf8);
+
+ inserted_text= MEM_callocN(sizeof(wchar_t)*(len+1), "FONT_insert_text");
+ utf8towchar(inserted_text, inserted_utf8);
+ first= inserted_text[0];
+
+ MEM_freeN(inserted_text);
+ MEM_freeN(inserted_utf8);
+
+ if(!first)
+ return OPERATOR_CANCELLED;
+
+ insert_into_textbuf(obedit, first);
+ kill_selection(obedit, 1);
+ text_update_edited(C, scene, obedit, 1, 0);
+
+ return OPERATOR_FINISHED;
+}
+
+static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+ static int accentcode= 0;
+ unsigned long ascii = evt->ascii;
+ int alt= evt->alt, shift= evt->shift, ctrl= evt->ctrl;
+ int event= evt->type, val= evt->val;
+ wchar_t inserted_text[2]= {0};
+
+ if(RNA_property_is_set(op->ptr, "text"))
+ return insert_text_exec(C, op);
+
+ /* tab should exit editmode, but we allow it to be typed using modifier keys */
+ if(event==TABKEY) {
+ if((alt||ctrl||shift) == 0)
+ return OPERATOR_PASS_THROUGH;
+ else
+ ascii= 9;
+ }
+ else if(event==BACKSPACEKEY)
+ ascii= 0;
+
+ if(val && ascii) {
+ /* handle case like TAB (== 9) */
+ if((ascii > 31 && ascii < 254 && ascii != 127) || (ascii==13) || (ascii==10) || (ascii==8)) {
+ if(accentcode) {
+ if(cu->pos>0) {
+ inserted_text[0]= findaccent(ef->textbuf[cu->pos-1], ascii);
+ ef->textbuf[cu->pos-1]= inserted_text[0];
+ }
+ accentcode= 0;
+ }
+ else if(cu->len<MAXTEXT-1) {
+ if(alt) {
+ /* might become obsolete, apple has default values for this, other OS's too? */
+ 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=='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;
+ }
+
+ inserted_text[0]= ascii;
+ insert_into_textbuf(obedit, ascii);
+ }
+
+ kill_selection(obedit, 1);
+ text_update_edited(C, scene, obedit, 1, 0);
+ }
+ else {
+ inserted_text[0]= ascii;
+ insert_into_textbuf(obedit, ascii);
+ text_update_edited(C, scene, obedit, 1, 0);
+ }
+ }
+ else if(val && event == BACKSPACEKEY) {
+ if(alt && cu->len!=0 && cu->pos>0)
+ accentcode= 1;
+
+ return OPERATOR_PASS_THROUGH;
+ }
+ else
+ return OPERATOR_PASS_THROUGH;
+
+ if(inserted_text[0]) {
+ /* store as utf8 in RNA string */
+ char inserted_utf8[8] = {0};
+
+ wcs2utf8s(inserted_utf8, inserted_text);
+ RNA_string_set(op->ptr, "text", inserted_utf8);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void FONT_OT_text_insert(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Insert Text";
+ ot->idname= "FONT_OT_text_insert";
+
+ /* api callbacks */
+ ot->exec= insert_text_exec;
+ ot->invoke= insert_text_invoke;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_string(ot->srna, "text", "", 0, "Text", "Text to insert at the cursor position.");
+}
+
+/***************** editmode enter/exit ********************/
+
+void make_editText(Object *obedit)
+{
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+
+ if(ef==NULL) {
+ ef= cu->editfont= MEM_callocN(sizeof(EditFont), "editfont");
+
+ ef->textbuf= MEM_callocN((MAXTEXT+4)*sizeof(wchar_t), "texteditbuf");
+ ef->textbufinfo= MEM_callocN((MAXTEXT+4)*sizeof(CharInfo), "texteditbufinfo");
+ ef->copybuf= MEM_callocN((MAXTEXT+4)*sizeof(wchar_t), "texteditcopybuf");
+ ef->copybufinfo= MEM_callocN((MAXTEXT+4)*sizeof(CharInfo), "texteditcopybufinfo");
+ ef->oldstr= MEM_callocN((MAXTEXT+4)*sizeof(wchar_t), "oldstrbuf");
+ ef->oldstrinfo= MEM_callocN((MAXTEXT+4)*sizeof(wchar_t), "oldstrbuf");
+ }
+
+ // Convert the original text to wchar_t
+ utf8towchar(ef->textbuf, cu->str);
+ wcscpy(ef->oldstr, ef->textbuf);
+
+ cu->len= wcslen(ef->textbuf);
+
+ memcpy(ef->textbufinfo, cu->strinfo, (cu->len)*sizeof(CharInfo));
+ memcpy(ef->oldstrinfo, cu->strinfo, (cu->len)*sizeof(CharInfo));
+
+ if(cu->pos>cu->len) cu->pos= cu->len;
+
+ if(cu->pos)
+ cu->curinfo = ef->textbufinfo[cu->pos-1];
+ else
+ cu->curinfo = ef->textbufinfo[0];
+
+ // Convert to UTF-8
+ update_string(cu);
+}
+
+void load_editText(Object *obedit)
+{
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+
+ MEM_freeN(ef->oldstr);
+ ef->oldstr= NULL;
+ MEM_freeN(ef->oldstrinfo);
+ ef->oldstrinfo= NULL;
+
+ update_string(cu);
+
+ if(cu->strinfo)
+ MEM_freeN(cu->strinfo);
+ cu->strinfo= MEM_callocN((cu->len+4)*sizeof(CharInfo), "texteditinfo");
+ memcpy(cu->strinfo, ef->textbufinfo, (cu->len)*sizeof(CharInfo));
+
+ cu->len= strlen(cu->str);
+
+ /* this memory system is weak... */
+
+ if(cu->selboxes) {
+ MEM_freeN(cu->selboxes);
+ cu->selboxes= NULL;
+ }
+}
+
+void free_editText(Object *obedit)
+{
+ BKE_free_editfont((Curve *)obedit->data);
+}
+
+/********************** set case operator *********************/
+
+static EnumPropertyItem case_items[]= {
+ {CASE_LOWER, "LOWER", "Lower", ""},
+ {CASE_UPPER, "UPPER", "Upper", ""},
+ {0, NULL, NULL, NULL}};
+
+static int set_case(bContext *C, int ccase)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+ wchar_t *str;
+ int len;
+
+ len= wcslen(ef->textbuf);
+ str= ef->textbuf;
+ while(len) {
+ if(*str>='a' && *str<='z')
+ *str-= 32;
+ len--;
+ str++;
+ }
+
+ if(ccase == CASE_LOWER) {
+ len= wcslen(ef->textbuf);
+ str= ef->textbuf;
+ while(len) {
+ if(*str>='A' && *str<='Z') {
+ *str+= 32;
+ }
+ len--;
+ str++;
+ }
+ }
+
+ text_update_edited(C, scene, obedit, 1, 0);
+
+ return OPERATOR_FINISHED;
+}
+
+static int set_case_exec(bContext *C, wmOperator *op)
+{
+ return set_case(C, RNA_enum_get(op->ptr, "case"));
+}
+
+void FONT_OT_case_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Case";
+ ot->idname= "FONT_OT_case_set";
+
+ /* api callbacks */
+ ot->exec= set_case_exec;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "case", case_items, CASE_LOWER, "Case", "Lower or upper case.");
+}
+
+/********************** toggle case operator *********************/
+
+static int toggle_case_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Curve *cu= obedit->data;
+ EditFont *ef= cu->editfont;
+ wchar_t *str;
+ int len, ccase= CASE_UPPER;
+
+ len= wcslen(ef->textbuf);
+ str= ef->textbuf;
+ while(len) {
+ if(*str>='a' && *str<='z') {
+ ccase= CASE_LOWER;
+ break;
+ }
+
+ len--;
+ str++;
+ }
+
+ return set_case(C, ccase);
+}
+
+void FONT_OT_case_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Toggle Case";
+ ot->idname= "FONT_OT_case_toggle";
+
+ /* api callbacks */
+ ot->exec= toggle_case_exec;
+ ot->poll= ED_operator_editfont;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* **************** undo for font object ************** */
+
+static void undoFont_to_editFont(void *strv, void *ecu)
+{
+ Curve *cu= (Curve *)ecu;
+ EditFont *ef= cu->editfont;
+ char *str= strv;
+
+ cu->pos= *((short *)str);
+ cu->len= *((short *)(str+2));
+
+ memcpy(ef->textbuf, str+4, (cu->len+1)*sizeof(wchar_t));
+ memcpy(ef->textbufinfo, str+4 + (cu->len+1)*sizeof(wchar_t), cu->len*sizeof(CharInfo));
+
+ cu->selstart = cu->selend = 0;
+
+ update_string(cu);
+}
+
+static void *editFont_to_undoFont(void *ecu)
+{
+ Curve *cu= (Curve *)ecu;
+ EditFont *ef= cu->editfont;
+ char *str;
+
+ // The undo buffer includes [MAXTEXT+6]=actual string and [MAXTEXT+4]*sizeof(CharInfo)=charinfo
+ str= MEM_callocN((MAXTEXT+6)*sizeof(wchar_t) + (MAXTEXT+4)*sizeof(CharInfo), "string undo");
+
+ // Copy the string and string information
+ memcpy(str+4, ef->textbuf, (cu->len+1)*sizeof(wchar_t));
+ memcpy(str+4 + (cu->len+1)*sizeof(wchar_t), ef->textbufinfo, cu->len*sizeof(CharInfo));
+
+ *((short *)str)= cu->pos;
+ *((short *)(str+2))= cu->len;
+
+ return str;
+}
+
+static void free_undoFont(void *strv)
+{
+ MEM_freeN(strv);
+}
+
+static void *get_undoFont(bContext *C)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ if(obedit && obedit->type==OB_FONT) {
+ return obedit->data;
+ }
+ return NULL;
+}
+
+/* and this is all the undo system needs to know */
+void undo_push_font(bContext *C, char *name)
+{
+ undo_editmode_push(C, name, get_undoFont, free_undoFont, undoFont_to_editFont, editFont_to_undoFont, NULL);
+}
+
diff --git a/source/blender/editors/curve/lorem.c b/source/blender/editors/curve/lorem.c
new file mode 100644
index 00000000000..e552f99d0e8
--- /dev/null
+++ b/source/blender/editors/curve/lorem.c
@@ -0,0 +1,513 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "curve_intern.h"
+
+char *ED_lorem =
+"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. "
+"Aliquam tristique interdum sem. "
+"Nullam pretium, tortor non euismod varius, nulla odio sodales nulla, at bibendum lorem metus sed nulla. "
+"Vestibulum in lectus at pede blandit viverra. "
+"Fusce scelerisque ipsum nec enim. "
+"Fusce euismod nunc id enim. "
+"In venenatis cursus arcu. "
+"Aenean quis dui. "
+"Maecenas laoreet. "
+"Nulla tempor, arcu pulvinar pretium suscipit, tortor wisi dapibus libero, id ornare felis ipsum suscipit purus. "
+"Maecenas ipsum. "
+"Morbi cursus. "
+"Vestibulum diam purus, commodo et, convallis eu, posuere at, ligula. "
+"Nulla aliquam aliquet lorem. "
+"Nunc et mauris hendrerit est bibendum suscipit. "
+"Donec pellentesque libero eu nisl. "
+"Pellentesque eget libero. "
+"Donec tempus ipsum sed quam. "
+"Sed blandit nunc quis enim. "
+"Quisque lectus diam, adipiscing hendrerit, placerat non, pulvinar id, felis. "
+"In congue magna sit amet urna. "
+"Nunc non augue sed nisl dictum laoreet. "
+"Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. "
+"In venenatis dapibus massa. "
+"Nulla hendrerit sapien et quam. "
+"Nunc ac magna lobortis tellus tincidunt posuere. "
+"Cras augue mauris, mattis lobortis, fermentum at, semper ac, tellus. "
+"Cras vitae ligula sit amet sem posuere iaculis. "
+"Aliquam condimentum eleifend felis. "
+"Ut sit amet sapien. "
+"Suspendisse potenti. "
+"Mauris urna. "
+"Ut eu enim eu ante porta vestibulum. "
+"Aenean scelerisque est ac felis. "
+"Suspendisse auctor. "
+"Nunc pellentesque. "
+"Morbi laoreet ante et nibh. "
+"Donec feugiat arcu eget enim. "
+"Morbi vehicula tortor ac ipsum. "
+"Quisque lacus arcu, elementum ac, faucibus vel, posuere id, est. "
+"Proin commodo gravida sem. "
+"Vivamus tincidunt vehicula libero. "
+"Phasellus wisi. "
+"Maecenas pretium tellus eu sapien. "
+"Nunc sit amet nunc. "
+"In hac habitasse platea dictumst. "
+"Aenean dictum neque sed tortor. "
+"Donec et erat. "
+"Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed justo turpis, scelerisque ut, mattis sit amet, ornare rutrum, massa. "
+"Vestibulum bibendum enim sit amet velit. "
+"Vivamus tellus ipsum, luctus ut, consectetuer vitae, dignissim non, ligula. "
+"Phasellus lacinia wisi at est. "
+"Donec elit wisi, commodo non, placerat in, convallis id, elit. "
+"Nunc dolor dolor, vestibulum id, bibendum vitae, lacinia id, erat. "
+"Cras sit amet eros. "
+"Suspendisse suscipit lobortis lectus. "
+"Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. "
+"Cras orci. "
+"Praesent massa urna, lobortis semper, auctor a, pretium vitae, tellus. "
+"Curabitur at purus. "
+"Morbi tortor quam, imperdiet venenatis, egestas a, cursus eu, est. "
+"Nunc interdum lectus sit amet libero. "
+"Quisque dignissim placerat ligula. "
+"Nunc porttitor posuere arcu. "
+"Mauris faucibus quam at massa. "
+"Vivamus sodales aliquet mauris. "
+"In id ante. "
+"Pellentesque varius ipsum in arcu. "
+"Fusce mauris lacus, tristique ac, lobortis quis, lobortis luctus, pede. "
+"Sed wisi. "
+"Vestibulum mattis. "
+"Maecenas hendrerit sem nec purus. "
+"Proin id quam. "
+"Cras nec mauris. "
+"Integer orci. "
+"Nullam dui sem, molestie sed, egestas quis, cursus in, magna. "
+"Mauris neque lacus, consectetuer nec, sagittis eu, porttitor eget, dui. "
+"Fusce consectetuer. "
+"Donec nec tellus quis leo lobortis ullamcorper. "
+"Etiam metus urna, aliquet pretium, ultrices eu, cursus ut, turpis. "
+"Morbi bibendum vehicula lectus. "
+"Sed non ante vitae arcu pellentesque tempor. "
+"Fusce sed ligula in sem tempor imperdiet. "
+"Aliquam vel est. "
+"Phasellus sollicitudin sollicitudin nibh. "
+"Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. "
+"Sed vel leo nec eros blandit imperdiet. "
+"Nulla facilisi. "
+"Suspendisse lobortis, dui ut fringilla hendrerit, justo purus ullamcorper ligula, ultricies ultrices dolor enim in libero. "
+"Sed elementum, pede eget porta convallis, dui nulla dignissim pede, eget vehicula odio ante at sem. "
+"Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "
+"Sed ullamcorper tincidunt ipsum. "
+"Fusce risus nibh, accumsan sit amet, tempus eget, tristique ac, neque. "
+"Sed quis lorem ut tortor facilisis fermentum. "
+"Fusce pulvinar quam sit amet ipsum. "
+"Morbi ac elit quis tellus malesuada blandit. "
+"Maecenas suscipit sollicitudin sem. "
+"Nam sed eros vel lacus lobortis congue. "
+"Proin interdum nunc lobortis orci. "
+"Donec egestas enim eu odio. "
+"Vestibulum id metus. "
+"Pellentesque auctor, sem varius luctus tempus, libero magna cursus neque, et porttitor diam diam quis purus. "
+"Vestibulum sit amet dolor. "
+"Nulla in magna. "
+"Cras id diam at lectus faucibus placerat. "
+"Nunc porta posuere sapien. "
+"Etiam scelerisque. "
+"Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. "
+"Aliquam pellentesque mi sed tortor. "
+"Maecenas eleifend diam non urna. "
+"Donec luctus pharetra tellus. "
+"Proin ac ipsum eget libero bibendum volutpat. "
+"Cras id tellus. "
+"Nulla non risus. "
+"In dolor. "
+"Fusce scelerisque quam in massa ultrices porta. "
+"Morbi ut dolor eu massa egestas condimentum. "
+"Mauris vulputate. "
+"In hac habitasse platea dictumst. "
+"Suspendisse potenti. "
+"Mauris vehicula leo in tortor. "
+"Mauris vel erat a urna laoreet semper. "
+"Pellentesque ut metus ac tellus commodo eleifend. "
+"Suspendisse quis urna. "
+"Curabitur lacinia dignissim dui. "
+"Nam nec ante. "
+"In id enim. "
+"Aenean mattis enim. "
+"In ut neque porttitor risus hendrerit tincidunt. "
+"Suspendisse potenti. "
+"Ut vestibulum lectus vitae tortor. "
+"Duis velit. "
+"Nulla facilisi. "
+"Integer sit amet urna. "
+"Cras varius tortor in pede. "
+"Sed facilisis. "
+"Praesent lacinia libero nec nibh. "
+"Donec aliquam risus non nisl. "
+"Nam a nunc et felis tempor feugiat. "
+"Nunc metus. "
+"Vestibulum euismod, metus in semper laoreet, urna ipsum pharetra lorem, sed ultricies magna lorem sit amet wisi. "
+"Sed wisi. "
+"Nullam facilisis elit sed nisl. "
+"Phasellus mattis leo nec massa. "
+"Aenean malesuada. "
+"Cras wisi erat, lobortis nec, cursus eget, lobortis at, libero. "
+"In massa nisl, rutrum non, cursus nec, faucibus sed, lacus. "
+"Pellentesque malesuada. "
+"Cras euismod, neque ac suscipit tempus, velit lorem luctus elit, dapibus rhoncus wisi est ut sem. "
+"Proin vulputate enim in eros elementum accumsan. "
+"Ut lorem nisl, hendrerit et, interdum nec, lacinia in, dolor. "
+"Duis nec quam. "
+"Praesent velit felis, posuere id, luctus quis, laoreet ut, ipsum. "
+"Praesent eget arcu. "
+"Mauris massa felis, ornare non, ultrices id, tristique in, elit. "
+"Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "
+"Phasellus vulputate, mi ac bibendum facilisis, libero enim suscipit leo, non nonummy pede diam eget nibh. "
+"Sed tempus. "
+"Aenean interdum suscipit dui. "
+"Aliquam erat volutpat. "
+"Ut malesuada. "
+"Nam commodo, nulla ut fringilla rutrum, orci elit viverra diam, vitae mollis odio odio et purus. "
+"Aliquam erat volutpat. "
+"Sed aliquet lobortis ipsum. "
+"In ut est. "
+"Etiam condimentum. "
+"Vestibulum pellentesque tortor pulvinar lacus. "
+"Aenean orci. "
+"Suspendisse lacus nulla, nonummy a, dictum vitae, egestas quis, eros. "
+"Donec auctor gravida nisl. "
+"Cras ac est rutrum augue pulvinar ornare. "
+"Phasellus mauris nibh, vulputate in, rhoncus imperdiet, dapibus eget, lacus. "
+"Nam nunc mauris, suscipit at, ultricies a, facilisis at, tellus. "
+"Nam accumsan mollis libero. "
+"Vivamus condimentum mattis est. "
+"Donec lacus. "
+"Nullam ac sapien id massa lobortis molestie. "
+"Pellentesque elementum. "
+"Proin ut purus. "
+"Integer et sapien quis turpis commodo mollis. "
+"Nulla consequat. "
+"Proin a wisi ut tellus blandit elementum. "
+"Aliquam nulla lorem, bibendum ac, malesuada vel, elementum et, metus. "
+"Phasellus egestas nibh et ligula. "
+"Vivamus diam odio, lacinia quis, malesuada quis, sollicitudin ut, eros. "
+"Phasellus aliquet lorem ac ipsum. "
+"Sed cursus tellus ac orci. "
+"Phasellus at nulla. "
+"Donec porta sodales ante. "
+"Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "
+"Sed id lectus at massa ullamcorper tristique. "
+"Suspendisse porttitor lacus. "
+"In hac habitasse platea dictumst. "
+"Nunc non turpis. "
+"Sed sagittis. "
+"Morbi laoreet scelerisque dui. "
+"Nam arcu tellus, tempor vitae, vestibulum et, imperdiet ut, velit. "
+"In sit amet augue a arcu volutpat suscipit. "
+"Donec dictum ultrices lectus. "
+"Phasellus a purus et orci dictum lacinia. "
+"Ut leo. "
+"Cras semper, lorem sit amet tincidunt congue, justo eros varius pede, in bibendum turpis lectus non eros. "
+"Phasellus quam. "
+"Suspendisse mattis sollicitudin magna. "
+"Aenean facilisis diam vel nisl nonummy condimentum. "
+"Suspendisse vel dolor. "
+"Vestibulum nonummy. "
+"Mauris imperdiet semper ante. "
+"Maecenas vulputate eros. "
+"Vestibulum ac dolor. "
+"Fusce risus metus, aliquet eget, facilisis et, feugiat vel, orci. "
+"Ut at nunc id ante sodales vulputate. "
+"Duis tristique mattis ante. "
+"Vestibulum neque mauris, laoreet id, congue interdum, aliquet ut, diam. "
+"Nulla volutpat blandit magna. "
+"Donec accumsan congue diam. "
+"Etiam vel dui eget nisl tempor varius. "
+"Cras dictum massa sed enim. "
+"Cras urna tortor, fringilla ac, ullamcorper in, euismod vel, arcu. "
+"Morbi posuere luctus augue. "
+"Aliquam dui dui, adipiscing in, lobortis eu, luctus eu, nulla. "
+"Cras velit pede, ullamcorper sit amet, feugiat in, auctor vitae, ante. "
+"Suspendisse dictum fringilla mauris. "
+"In a nibh. "
+"Donec ac ligula. "
+"In quam. "
+"Praesent vitae urna ultricies sem aliquam placerat. "
+"Aliquam erat volutpat. "
+"Nam est. "
+"Donec faucibus sodales metus. "
+"Ut congue. "
+"Donec arcu tellus, pharetra ac, vulputate ac, mollis sed, lectus. "
+"Nulla facilisi. "
+"Nullam volutpat nunc et felis. "
+"Sed pede odio, tincidunt in, volutpat malesuada, feugiat gravida, nulla. "
+"Nulla aliquam pede vitae arcu. "
+"Proin velit elit, nonummy sit amet, elementum vitae, varius vitae, dolor. "
+"Donec rutrum ipsum eu mi. "
+"Aliquam et sem. "
+"In adipiscing rhoncus velit. "
+"Nam viverra scelerisque arcu. "
+"Aliquam sem. "
+"Sed tincidunt nulla quis massa. "
+"Mauris faucibus tempus nunc. "
+"Phasellus condimentum. "
+"Curabitur aliquet iaculis sapien. "
+"Nunc rhoncus, odio vitae bibendum dignissim, tellus libero commodo ipsum, ut sollicitudin nisl nisl vel justo. "
+"Nulla facilisi. "
+"Praesent blandit enim ut justo. "
+"Proin elementum, elit eget accumsan pulvinar, orci quam auctor neque, sed convallis diam purus vel felis. "
+"Sed orci leo, eleifend vel, blandit non, semper eu, purus. "
+"Proin bibendum, libero ac consectetuer commodo, eros sapien blandit nisl, eu eleifend nibh nibh vel lectus. "
+"Vivamus placerat. "
+"Integer odio dolor, pharetra non, sodales id, viverra eget, diam. "
+"Nunc mauris magna, egestas quis, feugiat id, fermentum viverra, mi. "
+"Aenean suscipit nisl non nunc. "
+"Proin quis lectus ac tellus nonummy commodo. "
+"Nunc eget diam ac elit vestibulum auctor. "
+"Etiam vulputate, odio sed lacinia consequat, justo mi vulputate purus, sit amet euismod libero metus sed tortor. "
+"Maecenas ac elit sed lorem vulputate gravida. "
+"Proin lectus eros, ullamcorper id, volutpat quis, condimentum tincidunt, sapien. "
+"Sed et massa eget lorem aliquet tempus. "
+"Duis porttitor nisl non risus. "
+"Nam id quam. "
+"Nullam est. "
+"Proin orci diam, posuere et, pharetra commodo, dictum vel, enim. "
+"Proin eget erat. "
+"Donec nisl. "
+"Maecenas auctor velit ut pede. "
+"Nunc vitae lectus nec libero tincidunt hendrerit. "
+"Quisque varius, erat ultrices ultrices euismod, purus lacus dictum eros, at condimentum enim dui nec magna. "
+"Morbi diam. "
+"Phasellus sed est. "
+"Phasellus nec libero in arcu fringilla sollicitudin. "
+"In rutrum nisl at arcu. "
+"Nulla facilisi. "
+"Mauris dignissim. "
+"Etiam est mauris, pharetra sed, viverra et, tincidunt sed, neque. "
+"Ut at lectus id nibh luctus ornare. "
+"Mauris varius porttitor risus. "
+"Ut vulputate aliquet risus. "
+"Vestibulum luctus neque sit amet nunc. "
+"Duis fermentum nibh. "
+"Pellentesque dapibus. "
+"Proin eros libero, aliquam non, condimentum a, sodales ut, turpis. "
+"Integer accumsan mi sed lorem. "
+"Vestibulum pellentesque sodales nisl. "
+"Nulla eu justo quis dui pretium rhoncus. "
+"Praesent viverra commodo mi. "
+"Maecenas dolor libero, viverra a, elementum vitae, aliquet vitae, dui. "
+"Mauris convallis lectus et mi. "
+"Mauris sagittis. "
+"Sed arcu. "
+"Pellentesque auctor. "
+"Donec pellentesque purus non tellus. "
+"Ut leo wisi, ultrices sit amet, ultrices eu, gravida ac, libero. "
+"Mauris fermentum dapibus diam. "
+"Integer quis lacus dapibus odio pellentesque varius. "
+"Fusce pede quam, vehicula ut, pulvinar et, tincidunt sed, felis. "
+"Curabitur eros enim, vulputate sed, aliquam ac, euismod ac, erat. "
+"Ut dignissim, lacus a interdum iaculis, enim orci posuere nunc, nec ultricies lectus risus in odio. "
+"Etiam et massa id dui commodo vehicula. "
+"Nunc blandit tortor quis dui. "
+"Quisque nisl. "
+"Sed venenatis blandit ligula. "
+"Fusce viverra imperdiet magna. "
+"Donec eget nunc quis est pharetra lobortis. "
+"Vestibulum quis lectus. "
+"Mauris vel orci lobortis nunc fermentum bibendum. "
+"Pellentesque eget leo. "
+"Morbi vel urna sit amet erat fermentum facilisis. "
+"Sed vulputate, libero et sollicitudin congue, wisi lectus sodales dolor, eget molestie magna orci vel tellus. "
+"Sed tempor ante et enim. "
+"Mauris elit. "
+"Curabitur ullamcorper vehicula massa. "
+"Sed viverra. "
+"Duis nulla. "
+"Nam bibendum. "
+"Nam tortor lorem, ullamcorper vitae, dictum sed, posuere eu, justo. "
+"Aliquam adipiscing arcu vitae turpis. "
+"Donec malesuada posuere libero. "
+"Ut sed tellus. "
+"Fusce sed nunc eget nisl dapibus malesuada. "
+"Suspendisse potenti. "
+"Integer tristique libero et metus. "
+"Vivamus posuere. "
+"Maecenas non sem non quam fermentum blandit. "
+"Duis risus tellus, rutrum vitae, imperdiet nec, malesuada nec, ipsum. "
+"Nunc quam dolor, luctus eget, placerat non, rhoncus at, tellus. "
+"Duis pede lectus, mattis adipiscing, tempor ut, porta at, mi. "
+"Pellentesque risus nulla, sodales sed, interdum id, nonummy vitae, ligula. "
+"Morbi pulvinar pede ut massa. "
+"Nunc risus mauris, tincidunt et, faucibus eu, suscipit vel, orci. "
+"In faucibus felis in arcu. "
+"Nulla sit amet elit. "
+"Nulla erat sapien, sagittis eget, dignissim eget, viverra eu, felis. "
+"Nam ac ipsum. "
+"Suspendisse vulputate turpis vel sem lacinia ullamcorper. "
+"Mauris ornare ipsum sed ligula. "
+"Duis facilisis neque quis orci. "
+"Nullam et erat et orci lacinia pellentesque. "
+"Donec ac ipsum. "
+"Duis molestie ipsum ac arcu. "
+"Aenean congue accumsan ante. "
+"Integer bibendum, leo ut ornare aliquam, nunc erat condimentum arcu, ut pulvinar mi augue et nulla. "
+"Quisque lacinia aliquet wisi. "
+"Vivamus nec dui. "
+"Etiam wisi leo, euismod vitae, vulputate a, dictum vitae, quam. "
+"Quisque quis tortor. "
+"Etiam interdum. "
+"In massa erat, porttitor sed, tincidunt vel, vehicula fringilla, augue. "
+"Nulla vel urna. "
+"In libero mi, pretium sed, mattis tempus, sagittis sed, massa. "
+"Suspendisse quam wisi, fermentum quis, sagittis at, consequat eget, odio. "
+"Nullam imperdiet, purus quis aliquam cursus, turpis odio egestas justo, placerat gravida turpis wisi vel tortor. "
+"Nunc ultricies porta purus. "
+"Proin elementum erat ac orci. "
+"Ut vel magna nec mi feugiat tincidunt. "
+"Ut ligula. "
+"Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec et magna in diam porta nonummy. "
+"Maecenas ut sem in turpis fermentum viverra. "
+"Suspendisse at orci. "
+"Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "
+"Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque rutrum eleifend justo. "
+"Nullam vitae pede. "
+"Donec condimentum nibh et odio. "
+"Sed et metus. "
+"Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. "
+"Nam tempus. "
+"Sed ac wisi. "
+"In hac habitasse platea dictumst. "
+"Sed sed wisi. "
+"Ut facilisis tellus non ligula. "
+"Integer metus. "
+"In lacinia dui. "
+"Curabitur ornare. "
+"Mauris vel urna. "
+"Nam consectetuer dignissim urna. "
+"Nunc elementum porttitor erat. "
+"Sed blandit, risus non commodo nonummy, ligula erat fermentum nibh, eu facilisis ante neque sed sem. "
+"Etiam scelerisque justo eget wisi. "
+"Nunc dignissim. "
+"Proin pulvinar quam non lectus. "
+"Proin ut turpis quis augue pellentesque dictum. "
+"Fusce et lorem. "
+"Aliquam urna lacus, blandit sed, vestibulum sit amet, placerat et, dolor. "
+"Curabitur auctor erat nec lorem. "
+"Phasellus urna wisi, lacinia ut, molestie tincidunt, condimentum id, odio. "
+"Curabitur convallis ullamcorper justo. "
+"Donec vestibulum est ac quam. "
+"Nullam vitae elit eu massa varius vulputate. "
+"Nulla facilisi. "
+"Suspendisse potenti. "
+"Praesent non libero. "
+"Nullam tristique massa id magna viverra commodo. "
+"Vestibulum libero tortor, luctus ac, viverra congue, consectetuer vel, libero. "
+"Aenean arcu augue, luctus id, laoreet pulvinar, dictum sed, lectus. "
+"Donec vestibulum volutpat dolor. "
+"Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "
+"Pellentesque augue turpis, laoreet nec, malesuada at, nonummy vitae, nibh. "
+"Etiam orci sapien, congue in, porttitor sit amet, rutrum vel, nibh. "
+"Integer eu lorem. "
+"Mauris pretium leo et elit. "
+"In nonummy ultricies sapien. "
+"Mauris varius. "
+"Mauris sed libero. "
+"Curabitur ullamcorper elit eu purus. "
+"Vestibulum velit pede, semper sit amet, lobortis vitae, tincidunt vel, dui. "
+"Nulla neque ante, sagittis eu, vestibulum et, lacinia a, libero. "
+"Morbi sit amet wisi. "
+"Pellentesque non felis quis arcu bibendum ornare. "
+"Aenean enim metus, commodo eu, hendrerit nonummy, euismod ut, quam. "
+"Nulla eleifend nisl quis dolor. "
+"Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. "
+"Maecenas pellentesque massa in erat molestie molestie. "
+"Mauris dignissim dapibus libero. "
+"Sed sed risus id neque dictum ornare. "
+"Sed eu ligula at felis sodales accumsan. "
+"Sed interdum, urna non pharetra hendrerit, quam mi ornare libero, id fringilla tortor orci non velit. "
+"Aliquam nec risus. "
+"Donec at nunc vitae tellus molestie vestibulum. "
+"Pellentesque vel justo. "
+"Duis ligula libero, vulputate quis, adipiscing bibendum, feugiat vitae, velit. "
+"Vivamus et arcu. "
+"Fusce eget quam. "
+"Ut ante. "
+"Suspendisse feugiat metus non ipsum. "
+"Nulla tempus leo ut mi. "
+"Curabitur vitae nisl. "
+"Vivamus elementum. "
+"Etiam a orci. "
+"Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus urna quam, tincidunt at, ultrices vel, feugiat eget, nulla. "
+"Maecenas lacus magna, nonummy eu, iaculis sed, consectetuer quis, enim. "
+"Praesent a eros. "
+"Aliquam nonummy dignissim neque. "
+"Nulla enim. "
+"Praesent molestie, orci quis tristique volutpat, lacus metus luctus sapien, et facilisis eros neque id sapien. "
+"Nunc condimentum dolor vel orci. "
+"Integer wisi diam, porttitor sit amet, feugiat in, dapibus in, lectus. "
+"Aliquam erat volutpat. "
+"Quisque mollis turpis vitae tortor. "
+"Mauris turpis mi, pretium ut, ultrices sed, porta in, justo. "
+"Suspendisse posuere. "
+"Quisque ultricies lacus vitae enim. "
+"Donec lacus. "
+"Suspendisse potenti. "
+"Donec molestie, magna sed euismod dictum, magna magna interdum diam, vitae sagittis leo lorem ac neque. "
+"Cras metus. "
+"Quisque nunc. "
+"Duis consectetuer. "
+"Vestibulum gravida sollicitudin urna. "
+"Integer volutpat, massa quis ultrices pulvinar, eros purus dignissim nunc, eget rhoncus enim lectus quis tortor. "
+"Integer lacinia quam quis erat convallis mattis. "
+"Suspendisse iaculis posuere velit. "
+"Etiam tellus enim, aliquet nec, laoreet a, molestie non, velit. "
+"Quisque lacus velit, eleifend imperdiet, fringilla id, dapibus scelerisque, lectus. "
+"Nulla quis lorem. "
+"Nulla malesuada neque et dui. "
+"Phasellus malesuada ultricies odio. "
+"Phasellus vitae ligula. "
+"Pellentesque feugiat arcu at erat. "
+"Vivamus ut eros ut lorem pulvinar iaculis. "
+"Proin lobortis ipsum id nunc. "
+"Curabitur vel massa. "
+"Suspendisse nulla ipsum, malesuada vel, posuere eget, mollis at, risus. "
+"Vestibulum sed diam id est dapibus ultrices. "
+"Proin tempus, eros a scelerisque vestibulum, ipsum arcu aliquam mi, ut feugiat libero odio in nisl. "
+"Quisque et massa a mauris luctus congue. "
+"Ut id eros. "
+"Fusce ante eros, pharetra non, molestie tristique, bibendum sit amet, wisi. "
+"Phasellus rutrum, dolor et semper elementum, eros ante malesuada massa, sed sollicitudin lectus velit et massa. "
+"In auctor. "
+"Aliquam erat volutpat. "
+"Etiam risus leo, vulputate suscipit, sollicitudin et, sodales eget, nisl. "
+"Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Curabitur lobortis, libero ac laoreet mollis, ligula leo porta wisi, ut euismod felis ligula id elit. "
+"Vivamus malesuada nulla eu enim. "
+"Donec accumsan faucibus orci. "
+"Nulla lacinia ante. "
+"Praesent at nibh. "
+"Mauris porta dignissim wisi. "
+"Ut lacinia tortor nec nunc. "
+"Phasellus et augue. "
+"Integer rhoncus, libero a pellentesque rhoncus, tortor sapien lobortis pede, eget condimentum sapien risus vitae elit. "
+"Suspendisse sed turpis ut dolor placerat dignissim. "
+"Quisque quis leo. "
+"Cras ultrices. "
+"Maecenas hendrerit auctor tortor. "
+"Etiam sit amet arcu. ";
diff --git a/source/blender/editors/datafiles/B.blend.c b/source/blender/editors/datafiles/B.blend.c
new file mode 100644
index 00000000000..0a33fc99013
--- /dev/null
+++ b/source/blender/editors/datafiles/B.blend.c
@@ -0,0 +1,3076 @@
+/* DataToC output of file <B_blend> */
+
+int datatoc_B_blend_size= 98212;
+char datatoc_B_blend[]= {
+ 66, 76, 69, 78,
+ 68, 69, 82, 95,118, 50, 52, 49, 82, 69, 78, 68, 32, 0, 0, 0,144,240,255,191, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+250, 0, 0, 0, 83, 99,101,110,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 83, 82, 0, 0,
+116, 0, 0, 0, 8,237,195, 8,109, 0, 0, 0, 1, 0, 0, 0, 96, 40,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 83, 82, 49, 45, 65,110,105,109, 97,116,105,111,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+232,150,192, 8,168,240,195, 8,232,240,195, 8, 24,247,195, 8, 96,247,195, 8,152, 31,196, 8,136,251,196, 8, 0, 0,231, 3,
+143, 1,174, 4,232, 3, 32, 3, 1, 0, 1, 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, 68, 65, 84, 65, 20, 0, 0, 0,232,150,192, 8,110, 0, 0, 0, 1, 0, 0, 0,168,237,195, 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,237,195, 8,110, 0, 0, 0, 1, 0, 0, 0,
+232,237,195, 8,232,150,192, 8, 0, 0, 0, 0, 0, 0, 32, 3, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,232,237,195, 8,
+110, 0, 0, 0, 1, 0, 0, 0, 40,238,195, 8,168,237,195, 8, 0, 0, 0, 0,232, 3, 32, 3, 0, 0, 0, 0, 68, 65, 84, 65,
+ 20, 0, 0, 0, 40,238,195, 8,110, 0, 0, 0, 1, 0, 0, 0,104,238,195, 8,232,237,195, 8, 0, 0, 0, 0,232, 3, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,104,238,195, 8,110, 0, 0, 0, 1, 0, 0, 0,168,238,195, 8, 40,238,195, 8,
+ 0, 0, 0, 0,232, 3,248, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,168,238,195, 8,110, 0, 0, 0, 1, 0, 0, 0,
+232,238,195, 8,104,238,195, 8, 0, 0, 0, 0, 0, 0, 6, 3, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,232,238,195, 8,
+110, 0, 0, 0, 1, 0, 0, 0, 40,239,195, 8,168,238,195, 8, 0, 0, 0, 0,232, 3, 6, 3, 0, 0, 0, 0, 68, 65, 84, 65,
+ 20, 0, 0, 0, 40,239,195, 8,110, 0, 0, 0, 1, 0, 0, 0,104,239,195, 8,232,238,195, 8, 0, 0, 0, 0,160, 2,248, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,104,239,195, 8,110, 0, 0, 0, 1, 0, 0, 0,168,239,195, 8, 40,239,195, 8,
+ 0, 0, 0, 0,160, 2, 6, 3, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,168,239,195, 8,110, 0, 0, 0, 1, 0, 0, 0,
+232,239,195, 8,104,239,195, 8, 0, 0, 0, 0, 0, 0,188, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,232,239,195, 8,
+110, 0, 0, 0, 1, 0, 0, 0, 40,240,195, 8,168,239,195, 8, 0, 0, 0, 0,232, 3,188, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 20, 0, 0, 0, 40,240,195, 8,110, 0, 0, 0, 1, 0, 0, 0,104,240,195, 8,232,239,195, 8, 0, 0, 0, 0,204, 0,248, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,104,240,195, 8,110, 0, 0, 0, 1, 0, 0, 0,168,240,195, 8, 40,240,195, 8,
+ 0, 0, 0, 0,204, 0, 6, 3, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,168,240,195, 8,110, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0,104,240,195, 8, 0, 0, 0, 0,204, 0,188, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,232,240,195, 8,
+111, 0, 0, 0, 1, 0, 0, 0, 48,241,195, 8, 0, 0, 0, 0,168,237,195, 8,232,237,195, 8, 1, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0, 48,241,195, 8,111, 0, 0, 0, 1, 0, 0, 0,120,241,195, 8,232,240,195, 8,232,150,192, 8,
+ 40,238,195, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,120,241,195, 8,111, 0, 0, 0, 1, 0, 0, 0,
+192,241,195, 8, 48,241,195, 8,168,237,195, 8,168,238,195, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+192,241,195, 8,111, 0, 0, 0, 1, 0, 0, 0, 8,242,195, 8,120,241,195, 8,232,237,195, 8,232,238,195, 8, 1, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 8,242,195, 8,111, 0, 0, 0, 1, 0, 0, 0, 80,242,195, 8,192,241,195, 8,
+168,238,195, 8,232,238,195, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 80,242,195, 8,111, 0, 0, 0,
+ 1, 0, 0, 0,152,242,195, 8, 8,242,195, 8,104,238,195, 8, 40,239,195, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0,152,242,195, 8,111, 0, 0, 0, 1, 0, 0, 0,224,242,195, 8, 80,242,195, 8,232,238,195, 8,104,239,195, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,224,242,195, 8,111, 0, 0, 0, 1, 0, 0, 0, 40,243,195, 8,
+152,242,195, 8, 40,239,195, 8,104,239,195, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 40,243,195, 8,
+111, 0, 0, 0, 1, 0, 0, 0,112,243,195, 8,224,242,195, 8,104,238,195, 8,232,238,195, 8, 1, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0,112,243,195, 8,111, 0, 0, 0, 1, 0, 0, 0,184,243,195, 8, 40,243,195, 8,232,150,192, 8,
+168,239,195, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,184,243,195, 8,111, 0, 0, 0, 1, 0, 0, 0,
+ 0,244,195, 8,112,243,195, 8,104,238,195, 8,232,239,195, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+ 0,244,195, 8,111, 0, 0, 0, 1, 0, 0, 0, 72,244,195, 8,184,243,195, 8, 40,238,195, 8,232,239,195, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 72,244,195, 8,111, 0, 0, 0, 1, 0, 0, 0,144,244,195, 8, 0,244,195, 8,
+168,239,195, 8,232,239,195, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,144,244,195, 8,111, 0, 0, 0,
+ 1, 0, 0, 0,216,244,195, 8, 72,244,195, 8, 40,239,195, 8, 40,240,195, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0,216,244,195, 8,111, 0, 0, 0, 1, 0, 0, 0, 32,245,195, 8,144,244,195, 8,168,238,195, 8,104,240,195, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 32,245,195, 8,111, 0, 0, 0, 1, 0, 0, 0,104,245,195, 8,
+216,244,195, 8,104,239,195, 8,104,240,195, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,104,245,195, 8,
+111, 0, 0, 0, 1, 0, 0, 0,176,245,195, 8, 32,245,195, 8, 40,240,195, 8,104,240,195, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0,176,245,195, 8,111, 0, 0, 0, 1, 0, 0, 0,248,245,195, 8,104,245,195, 8,168,239,195, 8,
+168,240,195, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,248,245,195, 8,111, 0, 0, 0, 1, 0, 0, 0,
+ 64,246,195, 8,176,245,195, 8,232,239,195, 8,168,240,195, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+ 64,246,195, 8,111, 0, 0, 0, 1, 0, 0, 0,136,246,195, 8,248,245,195, 8,104,238,195, 8, 40,240,195, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,136,246,195, 8,111, 0, 0, 0, 1, 0, 0, 0,208,246,195, 8, 64,246,195, 8,
+ 40,240,195, 8,168,240,195, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,208,246,195, 8,111, 0, 0, 0,
+ 1, 0, 0, 0, 24,247,195, 8,136,246,195, 8,168,238,195, 8,168,239,195, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0, 24,247,195, 8,111, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,208,246,195, 8,104,240,195, 8,168,240,195, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0, 96,247,195, 8,113, 0, 0, 0, 1, 0, 0, 0,104, 5,196, 8,
+ 0, 0, 0, 0,232,150,192, 8,168,239,195, 8,232,239,195, 8, 40,238,195, 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,232, 3, 0, 0,
+ 0, 0, 0, 0,187, 0, 0, 0, 0, 0, 0, 0,232, 3, 0, 0,161, 0, 0, 0,187, 0, 0, 0, 0, 0, 0, 0,232, 3, 0, 0,
+ 0, 0, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 4,233, 3,161, 0, 3, 0, 3, 0, 79, 1, 0, 0, 7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232, 2,196, 8,232, 3,196, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 88,248,195, 8, 24, 2,196, 8, 68, 65, 84, 65,164, 0, 0, 0, 88,248,195, 8,112, 0, 0, 0, 1, 0, 0, 0, 40,249,195, 8,
+ 0, 0, 0, 0, 76,105,110,107, 32, 97,110,100, 32, 77, 97,116,101,114,105, 97,108,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0, 40,249,195, 8,112, 0, 0, 0, 1, 0, 0, 0,248,249,195, 8, 88,248,195, 8, 77,101,115,104,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,
+105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 1, 0, 0,
+ 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+248,249,195, 8,112, 0, 0, 0, 1, 0, 0, 0,200,250,195, 8, 40,249,195, 8, 65,110,105,109, 32,115,101,116,116,105,110,103,
+115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,200,250,195, 8,112, 0, 0, 0,
+ 1, 0, 0, 0,152,251,195, 8,248,249,195, 8, 68,114, 97,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 1, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,152,251,195, 8,112, 0, 0, 0, 1, 0, 0, 0,104,252,195, 8,
+200,250,195, 8, 67,111,110,115,116,114, 97,105,110,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,140, 2, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0,104,252,195, 8,112, 0, 0, 0, 1, 0, 0, 0, 56,253,195, 8,152,251,195, 8, 69,102,102,101,
+ 99,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 98,106,101,
+ 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,210, 3, 0, 0,
+162, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+ 56,253,195, 8,112, 0, 0, 0, 1, 0, 0, 0, 8,254,195, 8,104,252,195, 8, 72,111,111,107,115, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 1, 0, 0, 62, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,250,195, 8, 68, 65, 84, 65,164, 0, 0, 0, 8,254,195, 8,112, 0, 0, 0,
+ 1, 0, 0, 0,216,254,195, 8, 56,253,195, 8, 80, 97,114,116,105, 99,108,101, 32, 73,110,116,101,114, 97, 99,116,105,111,110,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 2, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,152,251,195, 8, 68, 65, 84, 65,164, 0, 0, 0,216,254,195, 8,112, 0, 0, 0, 1, 0, 0, 0,168,255,195, 8,
+ 8,254,195, 8, 83,111,102,116, 98,111,100,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,140, 2, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152,251,195, 8,
+ 68, 65, 84, 65,164, 0, 0, 0,168,255,195, 8,112, 0, 0, 0, 1, 0, 0, 0,120, 0,196, 8,216,254,195, 8, 79,117,116,112,
+117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,
+101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+120, 0,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 72, 1,196, 8,168,255,195, 8, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 1, 0, 0, 62, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 72, 1,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0, 24, 2,196, 8,120, 0,196, 8, 65,110,105,109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 2, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 24, 2,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 72, 1,196, 8, 70,111,114,109, 97,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,210, 3, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,212, 0, 0, 0,232, 2,196, 8, 94, 0, 0, 0, 1, 0, 0, 0,232, 3,196, 8, 0, 0, 0, 0, 4, 0, 0, 0,
+ 51, 51, 51, 63, 1, 86,141, 44, 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,193, 0, 64,212, 68, 0, 0, 0,193, 0, 0,104, 67, 0, 0, 0,193,145,133,185, 68, 0, 0, 0,193, 0, 0,104, 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,233, 3,161, 0, 0, 0, 0, 0, 1, 0, 1, 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,150, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 84, 1, 0, 0,232, 3,196, 8, 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+232, 2,196, 8, 5, 0, 0, 0, 51, 51, 51, 63, 1, 86,141, 44, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0,104, 5,196, 8,113, 0, 0, 0,
+ 1, 0, 0, 0, 96, 6,196, 8, 96,247,195, 8,168,238,195, 8,168,237,195, 8,232,237,195, 8,232,238,195, 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,232, 3, 0, 0, 7, 3, 0, 0, 32, 3, 0, 0, 0, 0, 0, 0,232, 3, 0, 0, 7, 3, 0, 0, 33, 3, 0, 0,
+ 0, 0, 0, 0,232, 3, 0, 0, 32, 3, 0, 0, 32, 3, 0, 0, 0, 0, 0, 0, 1, 0, 7, 7,233, 3, 1, 0, 3, 0, 3, 1,
+196, 2, 0, 0, 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, 68, 65, 84, 65,204, 0, 0, 0, 96, 6,196, 8,113, 0, 0, 0,
+ 1, 0, 0, 0, 88, 13,196, 8,104, 5,196, 8, 40,240,195, 8,104,240,195, 8,104,239,195, 8, 40,239,195, 8, 0, 0, 0, 0,
+ 71,187,204, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,186,252,191, 61, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,128, 0, 0, 0,128,111, 18, 3,187, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,
+205, 0, 0, 0,159, 2, 0, 0,249, 0, 0, 0, 5, 3, 0, 0,205, 0, 0, 0,159, 2, 0, 0,249, 0, 0, 0, 19, 1, 0, 0,
+205, 0, 0, 0,159, 2, 0, 0, 20, 1, 0, 0, 5, 3, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1,211, 1,242, 1, 1, 0, 3, 0,
+251, 2, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 8,196, 8,216, 11,196, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 88, 7,196, 8, 40, 8,196, 8, 68, 65, 84, 65,164, 0, 0, 0, 88, 7,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0, 40, 8,196, 8, 0, 0, 0, 0, 84,114, 97,110,115,102,111,114,109, 32, 80,114,111,112,101,114,116,105,101,115,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86,105,101,119, 51,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,140, 0,210, 0, 62, 1,204, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 40, 8,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 88, 7,196, 8, 51, 68, 32, 86,105,101,119,112,111,114,116, 32,112,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 86,105,101,119, 51,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, 8, 0, 8, 0, 62, 1,204, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,180, 2, 0, 0,248, 8,196, 8, 89, 0, 0, 0, 1, 0, 0, 0,216, 11,196, 8, 0, 0, 0, 0, 1, 0, 0, 0,
+ 51, 51, 51, 63, 1, 86,156, 60, 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, 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, 71,187,204, 61, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,186,252,191, 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,178, 13, 32, 65, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,148,173, 42, 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, 71,187,204, 61, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,186,252,191, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0,128,
+111, 18, 3,187, 0, 0, 0,128, 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,148,173, 42, 65, 0, 0, 7, 0, 40, 9,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 0, 0, 0, 8, 24, 0, 0, 12, 66, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,
+205,204,204, 61, 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,
+ 32, 0, 1, 0, 7, 0,175, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0,221,162, 77, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,221,162, 77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,221,162, 77, 64,
+ 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 84, 1, 0, 0,216, 11,196, 8, 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+248, 8,196, 8, 5, 0, 0, 0, 51, 51, 51, 63, 1, 86,156, 60, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0, 88, 13,196, 8,113, 0, 0, 0,
+ 1, 0, 0, 0,240, 24,196, 8, 96, 6,196, 8, 40,239,195, 8,104,239,195, 8,232,238,195, 8,104,238,195, 8, 0, 0, 0, 0,
+ 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,
+161, 2, 0, 0,232, 3, 0, 0,249, 0, 0, 0, 5, 3, 0, 0,161, 2, 0, 0,232, 3, 0, 0,249, 0, 0, 0, 19, 1, 0, 0,
+161, 2, 0, 0,232, 3, 0, 0, 20, 1, 0, 0, 5, 3, 0, 0, 0, 0, 0, 0, 1, 0, 2, 2, 72, 1,242, 1, 3, 0, 3, 0,
+203, 1, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 15,196, 8,112, 23,196, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 80, 14,196, 8, 80, 14,196, 8, 68, 65, 84, 65,164, 0, 0, 0, 80, 14,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84,114, 97,110,115,102,111,114,109, 32, 80,114,111,112,101,114,116,105,101,115,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73,112,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, 33, 0,167, 0, 62, 1,204, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0, 32, 15,196, 8, 93, 0, 0, 0, 1, 0, 0, 0,120, 16,196, 8,
+ 0, 0, 0, 0, 2, 0, 0, 0, 51, 51, 51, 63, 1, 86,160, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 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,242, 1, 0, 0, 16, 0, 0, 0, 7, 1, 0, 0,
+ 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 7, 1, 0, 0, 16, 0, 0, 0,242, 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, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 12,197, 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, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66,
+ 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,122, 67,205,204,204,189,
+205,204,140, 63, 68, 65, 84, 65,196, 0, 0, 0,120, 16,196, 8, 97, 0, 0, 0, 1, 0, 0, 0,104, 17,196, 8, 32, 15,196, 8,
+ 3, 0, 0, 0, 51, 51, 51, 63, 1, 86,160, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,182, 67, 0, 0,209,195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,182, 67, 0, 0,190,195, 0, 0, 0,181, 0, 0, 0, 0,
+ 16, 0, 0, 0, 0, 0, 0, 0,124, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,
+124, 1, 0, 0, 0, 0, 0, 0,124, 1, 0, 0, 0, 0,190,195, 0, 0,190,195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,
+ 0, 0,128, 63, 1, 0, 1, 0, 1, 0, 1, 0,108, 1,124, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,142, 3,
+ 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, 68, 65, 84, 65,
+160, 0, 0, 0,104, 17,196, 8,166, 0, 0, 0, 1, 0, 0, 0, 56, 18,196, 8,120, 16,196, 8, 11, 0, 0, 0, 51, 51, 51, 63,
+ 1, 86,160, 92, 0, 0,128,192, 0, 0,122, 67, 0, 0,128,192, 0, 0,127, 67, 0, 0,128,192, 0, 0, 72, 66, 0, 0,128,192,
+ 0, 0,127, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 1, 0, 0, 0, 0, 0, 0,
+ 16, 0, 0, 0, 0, 0, 0, 0,124, 1, 0, 0, 16, 0, 0, 0,124, 1, 0, 0, 0, 0,128, 63, 0,128,129, 67, 0, 0,250, 70,
+ 0,128,129, 67,205,204,204, 61, 0, 0, 32, 65, 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, 68, 65, 84, 65,120, 0, 0, 0, 56, 18,196, 8,100, 0, 0, 0,
+ 1, 0, 0, 0,224, 18,196, 8,104, 17,196, 8, 9, 0, 0, 0, 51, 51, 51, 63, 1, 86,160, 92, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,240, 3,197, 8, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 12, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,205,204,204, 61, 5, 0, 0, 0,
+ 17, 0, 0, 0,114, 1, 0, 0,116, 1, 0, 0, 5, 0, 0, 0, 17, 0, 0, 0, 2, 0, 0, 0,116, 1, 0, 0, 68, 65, 84, 65,
+164, 0, 0, 0,224, 18,196, 8, 99, 0, 0, 0, 1, 0, 0, 0,176, 19,196, 8, 56, 18,196, 8, 13, 0, 0, 0, 51, 51, 51, 63,
+ 1, 86,160, 92, 0, 0, 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,122, 68, 0, 0, 0, 0, 0, 0,122, 68, 0, 0,160,192, 0, 0,130, 66, 0, 0, 0, 0, 0, 0,182, 67,108, 1, 0, 0,
+124, 1, 0, 0, 0, 0, 0, 0,124, 1, 0, 0,196, 0, 0, 0,108, 1, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,196, 0, 0, 0,
+108, 1, 0, 0, 16, 0, 0, 0,124, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,122, 68, 0, 0,122, 68,205,204,204, 61,
+ 0, 0, 72, 66, 10, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,176, 0, 0, 0,176, 19,196, 8,
+177, 0, 0, 0, 1, 0, 0, 0,144, 20,196, 8,224, 18,196, 8, 12, 0, 0, 0, 51, 51, 51, 63, 1, 86,160, 92, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 0, 0, 2, 66, 0, 0,128,193, 0, 0,247, 67, 0, 0, 0,191,
+ 0, 0, 2, 66, 0, 0,128,193, 0, 0,247, 67,108, 1, 0, 0,124, 1, 0, 0, 0, 0, 0, 0, 14, 2, 0, 0,128, 0, 0, 0,
+108, 1, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,128, 0, 0, 0,108, 1, 0, 0, 16, 0, 0, 0, 14, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,250, 70, 0, 0,122, 68, 10,215, 35, 60, 0, 0, 72, 66, 10, 0, 0, 0, 0, 0, 0, 2, 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, 0, 0, 68, 65, 84, 65,180, 2, 0, 0,
+144, 20,196, 8, 89, 0, 0, 0, 1, 0, 0, 0,112, 23,196, 8,176, 19,196, 8, 1, 0, 0, 0, 51, 51, 51, 63, 1, 86,160, 92,
+ 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 32, 65, 1, 0, 7, 0, 40, 9,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 3, 0, 0, 0, 0, 24, 0, 0, 12, 66, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 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, 20, 0, 0, 0, 7, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 84, 1, 0, 0,112, 23,196, 8, 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,144, 20,196, 8, 5, 0, 0, 0,
+ 51, 51, 51, 63, 1, 86,160, 92, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0,240, 24,196, 8,113, 0, 0, 0, 1, 0, 0, 0,152, 31,196, 8,
+ 88, 13,196, 8,168,240,195, 8, 40,240,195, 8,104,238,195, 8,232,239,195, 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,205, 0, 0, 0,232, 3, 0, 0,
+189, 0, 0, 0,247, 0, 0, 0,205, 0, 0, 0,232, 3, 0, 0,189, 0, 0, 0,215, 0, 0, 0,205, 0, 0, 0,232, 3, 0, 0,
+216, 0, 0, 0,247, 0, 0, 0, 0, 0, 0, 0, 1, 0, 15, 15, 28, 3, 32, 0, 3, 0, 3, 0,192, 2, 0, 0, 7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136, 27,196, 8, 24, 30,196, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+232, 25,196, 8,184, 26,196, 8, 68, 65, 84, 65,164, 0, 0, 0,232, 25,196, 8,112, 0, 0, 0, 1, 0, 0, 0,184, 26,196, 8,
+ 0, 0, 0, 0, 76,105,110,107, 32, 97,110,100, 32, 77, 97,116,101,114,105, 97,108,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0,184, 26,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,232, 25,196, 8, 77,101,115,104,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,
+105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 1, 0, 0,
+ 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,148, 0, 0, 0,
+136, 27,196, 8,102, 0, 0, 0, 1, 0, 0, 0, 72, 28,196, 8, 0, 0, 0, 0, 15, 0, 0, 0, 51, 51, 51, 63, 1, 86,170, 76,
+ 0, 0,128,192, 0, 0,122, 67, 0, 0, 0, 0, 0, 0, 16, 66,123, 10, 4,194,181,186,152, 67, 0, 0, 0, 0, 0, 0, 16, 66,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 28, 3, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0,128, 63, 0, 0, 16, 66, 0, 0,250, 70, 0, 0, 16, 66,
+205,204,204, 61, 0, 0, 32, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0,
+ 68, 65, 84, 65,160, 0, 0, 0, 72, 28,196, 8,166, 0, 0, 0, 1, 0, 0, 0, 24, 29,196, 8,136, 27,196, 8, 11, 0, 0, 0,
+ 51, 51, 51, 63, 1, 86,170, 76, 0, 0,128,192, 0, 0,122, 67, 0, 0,128,192, 0, 0,127, 67, 0, 0,128,192, 0, 0, 72, 66,
+ 0, 0,128,192, 0, 0,127, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,233, 3, 0, 0,
+ 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,233, 3, 0, 0, 16, 0, 0, 0, 36, 0, 0, 0, 0, 0,128, 63, 0,128,129, 67,
+ 0, 0,250, 70, 0,128,129, 67,205,204,204, 61, 0, 0, 32, 65, 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, 68, 65, 84, 65,212, 0, 0, 0, 24, 29,196, 8,
+ 94, 0, 0, 0, 1, 0, 0, 0, 24, 30,196, 8, 72, 28,196, 8, 4, 0, 0, 0, 51, 51, 51, 63, 1, 86,170, 76, 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,193, 0, 0, 35, 68, 0, 0, 0,193,
+ 0, 0,104, 67,135, 22, 0,193,178, 16, 96, 68,112, 74,103, 67, 0, 0,104, 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,251, 4, 1, 0, 0, 0, 0, 0, 4, 0, 1, 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,150, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 84, 1, 0, 0, 24, 30,196, 8, 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 24, 29,196, 8, 5, 0, 0, 0, 51, 51, 51, 63,
+ 1, 86,170, 76, 0, 0, 0, 0, 0, 0, 0, 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, 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,
+ 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0,152, 31,196, 8,113, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,240, 24,196, 8,
+168,239,195, 8,168,238,195, 8,104,240,195, 8,168,240,195, 8, 0, 0, 0, 0,159,125, 11, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,186,252,191, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0,128,111, 18, 3,187,
+ 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0,203, 0, 0, 0,189, 0, 0, 0,
+ 5, 3, 0, 0, 0, 0, 0, 0,203, 0, 0, 0,189, 0, 0, 0,215, 0, 0, 0, 0, 0, 0, 0,203, 0, 0, 0,216, 0, 0, 0,
+ 5, 3, 0, 0, 0, 0, 0, 0, 1, 0, 3, 3,204, 0, 46, 2, 3, 0, 3, 0,145, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 34,196, 8,224, 38,196, 8, 0, 0, 0, 0, 0, 0, 0, 0,144, 32,196, 8,
+ 96, 33,196, 8, 68, 65, 84, 65,164, 0, 0, 0,144, 32,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 96, 33,196, 8, 0, 0, 0, 0,
+ 84,114, 97,110,115,102,111,114,109, 32, 80,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 86,105,101,119, 51,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,
+140, 0,210, 0, 62, 1,204, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+164, 0, 0, 0, 96, 33,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,144, 32,196, 8, 51, 68, 32, 86,105,101,119,112,
+111,114,116, 32,112,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86,105,101,119, 51,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, 8, 0, 8, 0, 62, 1,204, 0,
+ 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,196, 0, 0, 0, 48, 34,196, 8,
+ 97, 0, 0, 0, 1, 0, 0, 0, 0, 36,196, 8, 0, 0, 0, 0, 3, 0, 0, 0, 51, 51, 51, 63, 1, 89, 2, 28, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 67, 0, 0,190,194, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 60, 67, 0,128, 11,196, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 46, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,204, 0, 0, 0, 0, 0, 0, 0, 46, 2, 0, 0, 0, 0,192,194,
+ 0,128, 11,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 1, 0, 1, 0, 1, 0, 1, 0,188, 0, 46, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,142, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 32, 35,196, 8, 1, 0, 0, 0, 1, 0, 0, 0, 68, 65, 84, 65, 12, 0, 0, 0, 32, 35,196, 8,128, 0, 0, 0, 1, 0, 0, 0,
+ 10, 0, 0, 0, 10, 0, 0, 0, 88, 35,196, 8, 68, 65, 84, 65,120, 0, 0, 0, 88, 35,196, 8,127, 0, 0, 0, 10, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0,136,251,196, 8, 0, 0, 0, 0, 1, 0, 1, 0,160, 2,197, 8, 0, 0, 0, 0, 1, 0, 1, 0,
+ 72, 12,197, 8, 0, 0, 0, 0, 1, 0, 1, 0, 24, 22,197, 8, 0, 0, 0, 0, 1, 0, 1, 0,184, 18,197, 8, 0, 0, 0, 0,
+ 1, 0, 1, 0, 8, 21,197, 8, 0, 0, 0, 0, 1, 0, 1, 0,152, 15,197, 8, 0, 0, 0, 0, 1, 0, 1, 0,120, 1,197, 8,
+ 0, 0, 0, 0, 1, 0, 1, 0, 40, 9,197, 8, 0, 0, 0, 0, 1, 0, 1, 0,216, 0,197, 8, 68, 65, 84, 65,180, 2, 0, 0,
+ 0, 36,196, 8, 89, 0, 0, 0, 1, 0, 0, 0,224, 38,196, 8, 48, 34,196, 8, 1, 0, 0, 0, 51, 51, 51, 63, 1, 89, 2, 28,
+ 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, 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,159,125, 11, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,186,252,191, 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,102,233,234, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,148,173, 42, 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,159,125, 11, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,186,252,191, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0,128,111, 18, 3,187, 0, 0, 0,128,
+ 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,
+148,173, 42, 65, 0, 0, 7, 0, 40, 9,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 3, 0, 0, 0, 8, 24, 0, 0, 12, 66, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,205,204,204, 61, 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, 32, 0, 1, 0, 7, 0,175, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 88,134, 55, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 88,134, 55, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,134, 55, 64, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 84, 1, 0, 0,224, 38,196, 8, 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 36,196, 8, 5, 0, 0, 0,
+ 51, 51, 51, 63, 1, 89, 2, 28, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 83, 82, 0, 0,116, 0, 0, 0, 96, 40,196, 8,109, 0, 0, 0, 1, 0, 0, 0,192, 99,196, 8,
+ 8,237,195, 8, 0, 0, 0, 0, 0, 0, 0, 0, 83, 82, 50, 45, 77,111,100,101,108, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 41,196, 8,192, 42,196, 8, 0, 43,196, 8,136, 45,196, 8,208, 45,196, 8,
+144, 86,196, 8,136,251,196, 8, 1, 0, 0, 5,254,255,253, 3, 0, 5, 0, 4, 1, 0, 2, 0, 0, 0, 0, 0, 1, 0, 8, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 0, 41,196, 8,110, 0, 0, 0,
+ 1, 0, 0, 0, 64, 41,196, 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,
+ 64, 41,196, 8,110, 0, 0, 0, 1, 0, 0, 0,128, 41,196, 8, 0, 41,196, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0,128, 41,196, 8,110, 0, 0, 0, 1, 0, 0, 0,192, 41,196, 8, 64, 41,196, 8, 0, 0, 0, 0,
+ 0, 5, 0, 4, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,192, 41,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 0, 42,196, 8,
+128, 41,196, 8, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 0, 42,196, 8,110, 0, 0, 0,
+ 1, 0, 0, 0, 64, 42,196, 8,192, 41,196, 8, 0, 0, 0, 0, 0, 0,236, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+ 64, 42,196, 8,110, 0, 0, 0, 1, 0, 0, 0,128, 42,196, 8, 0, 42,196, 8, 0, 0, 0, 0, 0, 5,236, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0,128, 42,196, 8,110, 0, 0, 0, 1, 0, 0, 0,192, 42,196, 8, 64, 42,196, 8, 0, 0, 0, 0,
+ 0, 0,224, 3, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,192, 42,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+128, 42,196, 8, 0, 0, 0, 0, 0, 5,224, 3, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 0, 43,196, 8,111, 0, 0, 0,
+ 1, 0, 0, 0, 72, 43,196, 8, 0, 0, 0, 0, 64, 41,196, 8,128, 41,196, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0, 72, 43,196, 8,111, 0, 0, 0, 1, 0, 0, 0,144, 43,196, 8, 0, 43,196, 8, 0, 41,196, 8,192, 41,196, 8,
+ 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,144, 43,196, 8,111, 0, 0, 0, 1, 0, 0, 0,216, 43,196, 8,
+ 72, 43,196, 8, 0, 41,196, 8, 0, 42,196, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,216, 43,196, 8,
+111, 0, 0, 0, 1, 0, 0, 0, 32, 44,196, 8,144, 43,196, 8,192, 41,196, 8, 64, 42,196, 8, 1, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0, 32, 44,196, 8,111, 0, 0, 0, 1, 0, 0, 0,104, 44,196, 8,216, 43,196, 8, 0, 42,196, 8,
+ 64, 42,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,104, 44,196, 8,111, 0, 0, 0, 1, 0, 0, 0,
+176, 44,196, 8, 32, 44,196, 8, 64, 41,196, 8,128, 42,196, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+176, 44,196, 8,111, 0, 0, 0, 1, 0, 0, 0,248, 44,196, 8,104, 44,196, 8,128, 41,196, 8,192, 42,196, 8, 1, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,248, 44,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 64, 45,196, 8,176, 44,196, 8,
+128, 42,196, 8,192, 42,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 64, 45,196, 8,111, 0, 0, 0,
+ 1, 0, 0, 0,136, 45,196, 8,248, 44,196, 8, 0, 42,196, 8,128, 42,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0,136, 45,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 64, 45,196, 8, 64, 42,196, 8,192, 42,196, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0,208, 45,196, 8,113, 0, 0, 0, 1, 0, 0, 0,152, 85,196, 8,
+ 0, 0, 0, 0, 0, 41,196, 8, 0, 42,196, 8, 64, 42,196, 8,192, 41,196, 8, 0, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,183, 64, 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,226,215,163,188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,
+ 0, 0, 0, 0,235, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,209, 0, 0, 0,235, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,
+ 0, 0, 0, 0,208, 0, 0, 0, 5, 0, 4, 0, 2, 0, 4, 4, 1, 5,209, 0, 1, 1, 1, 0, 79, 1, 0, 0, 7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 79,196, 8, 24, 84,196, 8, 56,189,193, 8,112,188,195, 8,
+200, 46,196, 8,144,165,193, 8, 68, 65, 84, 65,164, 0, 0, 0,200, 46,196, 8,112, 0, 0, 0, 1, 0, 0, 0,152, 47,196, 8,
+ 0, 0, 0, 0, 80,114,101,118,105,101,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0,152, 47,196, 8,112, 0, 0, 0, 1, 0, 0, 0,104, 48,196, 8,200, 46,196, 8, 76, 97,109,112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 1, 0, 0,
+ 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+104, 48,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 56, 49,196, 8,152, 47,196, 8, 83,112,111,116, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 2, 0, 0, 62, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 56, 49,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0, 8, 50,196, 8,104, 48,196, 8, 84,101,120,116,117,114,101, 32, 97,110,100, 32, 73,110,112,117,116, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,210, 3, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 8, 50,196, 8,112, 0, 0, 0, 1, 0, 0, 0,216, 50,196, 8,
+ 56, 49,196, 8, 77, 97,112, 32, 84,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, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,210, 3, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 49,196, 8,
+ 68, 65, 84, 65,164, 0, 0, 0,216, 50,196, 8,112, 0, 0, 0, 1, 0, 0, 0,168, 51,196, 8, 8, 50,196, 8, 80,114,101,118,
+105,101,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,
+114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+168, 51,196, 8,112, 0, 0, 0, 1, 0, 0, 0,120, 52,196, 8,216, 50,196, 8, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 1, 0, 0, 62, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,120, 52,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0, 72, 53,196, 8,168, 51,196, 8, 80,114,101,118,105,101,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87,111,114,108,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, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 72, 53,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 24, 54,196, 8,
+120, 52,196, 8, 87,111,114,108,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, 87,111,114,108,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, 70, 1, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0, 24, 54,196, 8,112, 0, 0, 0, 1, 0, 0, 0,232, 54,196, 8, 72, 53,196, 8, 77,105,115,116,
+ 32, 83,116, 97,114,115, 32, 80,104,121,115,105, 99,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87,111,114,108,
+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,140, 2, 0, 0,
+ 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+232, 54,196, 8,112, 0, 0, 0, 1, 0, 0, 0,184, 55,196, 8, 24, 54,196, 8, 84,101,120,116,117,114,101, 32, 97,110,100, 32,
+ 73,110,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87,111,114,108,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,210, 3, 0, 0, 62, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,184, 55,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0,136, 56,196, 8,232, 54,196, 8, 77, 97,112, 32, 84,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, 87,111,114,108,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,210, 3, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,232, 54,196, 8, 68, 65, 84, 65,164, 0, 0, 0,136, 56,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 88, 57,196, 8,
+184, 55,196, 8, 79,117,116,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0, 88, 57,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 40, 58,196, 8,136, 56,196, 8, 82,101,110,100,
+101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,
+101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 1, 0, 0,
+ 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+ 40, 58,196, 8,112, 0, 0, 0, 1, 0, 0, 0,248, 58,196, 8, 88, 57,196, 8, 65,110,105,109, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 2, 0, 0, 62, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,248, 58,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0,200, 59,196, 8, 40, 58,196, 8, 70,111,114,109, 97,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,210, 3, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,200, 59,196, 8,112, 0, 0, 0, 1, 0, 0, 0,152, 60,196, 8,
+248, 58,196, 8, 76,105,110,107, 32, 97,110,100, 32, 77, 97,116,101,114,105, 97,108,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,204, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0,152, 60,196, 8,112, 0, 0, 0, 1, 0, 0, 0,104, 61,196, 8,200, 59,196, 8, 77,101,115,104,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,
+105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 1, 0, 0,
+ 62, 1,204, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+104, 61,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 56, 62,196, 8,152, 60,196, 8, 77,101,115,104, 32, 84,111,111,108,115, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 2, 0, 0, 62, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 56, 62,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0, 8, 63,196, 8,104, 61,196, 8, 77,101,115,104, 32, 84,111,111,108,115, 32, 49, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 5, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 8, 63,196, 8,112, 0, 0, 0, 1, 0, 0, 0,216, 63,196, 8,
+ 56, 62,196, 8, 67, 97,109,101,114, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 70, 1, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0,216, 63,196, 8,112, 0, 0, 0, 1, 0, 0, 0,168, 64,196, 8, 8, 63,196, 8, 83,104, 97,100,
+101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,
+114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 2, 0, 0,
+ 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 76,196, 8, 68, 65, 84, 65,164, 0, 0, 0,
+168, 64,196, 8,112, 0, 0, 0, 1, 0, 0, 0,120, 65,196, 8,216, 63,196, 8, 84,101,120,116,117,114,101, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,210, 3, 0, 0, 62, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,120, 65,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0, 72, 66,196, 8,168, 64,196, 8, 65,110,105,109, 32,115,101,116,116,105,110,103,115, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 72, 66,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 24, 67,196, 8,
+120, 65,196, 8, 68,114, 97,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 70, 1, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0, 24, 67,196, 8,112, 0, 0, 0, 1, 0, 0, 0,232, 67,196, 8, 72, 66,196, 8, 67,111,110,115,
+116,114, 97,105,110,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 98,106,101,
+ 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 2, 0, 0,
+ 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+232, 67,196, 8,112, 0, 0, 0, 1, 0, 0, 0,184, 68,196, 8, 24, 67,196, 8, 83, 99,114,105,112,116,108,105,110,107,115, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 99,114,105,112,116, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,184, 68,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0,136, 69,196, 8,232, 67,196, 8, 69,102,102,101, 99,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 2, 0, 0,162, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 24, 67,196, 8, 68, 65, 84, 65,164, 0, 0, 0,136, 69,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 88, 70,196, 8,
+184, 68,196, 8, 77, 97,112, 32, 73,110,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,210, 3, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 64,196, 8,
+ 68, 65, 84, 65,164, 0, 0, 0, 88, 70,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 40, 71,196, 8,136, 69,196, 8, 77, 97,112, 32,
+ 84,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, 77, 97,116,101,
+114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,210, 3, 0, 0,
+ 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 64,196, 8, 68, 65, 84, 65,164, 0, 0, 0,
+ 40, 71,196, 8,112, 0, 0, 0, 1, 0, 0, 0,248, 71,196, 8, 88, 70,196, 8, 65,110,105,109, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65,110,105,109, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,248, 71,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0,200, 72,196, 8, 40, 71,196, 8, 83,111,117,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, 83,111,117,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, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,200, 72,196, 8,112, 0, 0, 0, 1, 0, 0, 0,152, 73,196, 8,
+248, 71,196, 8, 76,105,115,116,101,110,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 83,111,117,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, 70, 1, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0,152, 73,196, 8,112, 0, 0, 0, 1, 0, 0, 0,104, 74,196, 8,200, 72,196, 8, 83,101,113,117,
+101,110, 99,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,111,117,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,140, 2, 0, 0,
+ 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+104, 74,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 56, 75,196, 8,152, 73,196, 8, 65,114,109, 97,116,117,114,101, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 1, 0, 0, 62, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 56, 75,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0, 8, 76,196, 8,104, 74,196, 8, 82, 97,109,112,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 1, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,168, 51,196, 8, 68, 65, 84, 65,164, 0, 0, 0, 8, 76,196, 8,112, 0, 0, 0, 1, 0, 0, 0,216, 76,196, 8,
+ 56, 75,196, 8, 77,105,114,114,111,114, 32, 84,114, 97,110,115,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,140, 2, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0,216, 76,196, 8,112, 0, 0, 0, 1, 0, 0, 0,168, 77,196, 8, 8, 76,196, 8, 77,105,115,116,
+ 32, 47, 32, 83,116, 97,114,115, 32, 47, 32, 80,104,121,115,105, 99,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87,111,114,108,
+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,140, 2, 0, 0,
+ 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+168, 77,196, 8,112, 0, 0, 0, 1, 0, 0, 0,120, 78,196, 8,216, 76,196, 8, 65,109, 98, 32, 79, 99, 99, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87,111,114,108,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,140, 2, 0, 0, 62, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 76,196, 8, 68, 65, 84, 65,164, 0, 0, 0,120, 78,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0, 8,158,193, 8,168, 77,196, 8, 83,104, 97,100,111,119, 32, 97,110,100, 32, 83,112,111,116, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 2, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 8,158,193, 8,112, 0, 0, 0, 1, 0, 0, 0,144,165,193, 8,
+120, 78,196, 8, 77,111,100,105,102,105,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,140, 2, 0, 0, 62, 1,204, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0,144,165,193, 8,112, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 8,158,193, 8, 83,104, 97,112,
+101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,
+105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 2, 0, 0,
+ 62, 1,204, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 8,158,193, 8, 68, 65, 84, 65,212, 0, 0, 0,
+ 72, 79,196, 8, 94, 0, 0, 0, 1, 0, 0, 0, 72, 80,196, 8, 0, 0, 0, 0, 4, 0, 0, 0, 51, 51, 51, 63,208, 45,196, 8,
+ 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,193, 0,192,202, 68,
+ 0, 0, 0,193, 0, 0,104, 67, 0, 0, 0,193, 40,224,182, 68, 0, 0, 0,193, 0, 0,104, 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, 1, 5,209, 0, 0, 0, 0, 0, 4, 0, 1, 0, 0, 0, 4, 0, 24, 22,197, 8, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,141, 0, 0, 0, 0, 0,109, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,180, 2, 0, 0, 72, 80,196, 8, 89, 0, 0, 0, 1, 0, 0, 0, 40, 83,196, 8, 72, 79,196, 8, 1, 0, 0, 0,
+ 51, 51, 51, 63,208, 45,196, 8, 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, 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, 0, 0,140, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,183, 64, 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,161, 14,106, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 15, 51, 62, 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, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 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, 32, 65, 1, 0, 7, 0, 40, 9,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 24, 0, 0, 12, 66, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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,
+ 16, 0, 1, 0, 7, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,196, 0, 0, 0, 40, 83,196, 8, 97, 0, 0, 0, 1, 0, 0, 0, 24, 84,196, 8,
+ 72, 80,196, 8, 3, 0, 0, 0, 51, 51, 51, 63,208, 45,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,192,192, 0, 0,160, 64, 0, 0, 0, 0,205,204,140, 65,201, 82, 5,194,124,171, 30, 66, 49,238,226, 64,140,108,168, 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, 1, 5, 0, 0, 0, 0, 0, 0,245, 0, 0, 0, 0, 0, 32, 65, 0, 0,128, 64, 0, 0,160, 67, 0, 0,160, 67,
+ 10,215, 35, 60, 0, 0, 0, 64, 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,142, 3, 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,
+ 68, 65, 84, 65, 84, 1, 0, 0, 24, 84,196, 8, 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 40, 83,196, 8, 5, 0, 0, 0,
+ 51, 51, 51, 63,208, 45,196, 8, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0,152, 85,196, 8,113, 0, 0, 0, 1, 0, 0, 0,144, 86,196, 8,
+208, 45,196, 8,128, 42,196, 8, 64, 41,196, 8,128, 41,196, 8,192, 42,196, 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, 5, 0, 0,
+225, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,225, 3, 0, 0,251, 3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,
+252, 3, 0, 0, 0, 4, 0, 0, 7, 0, 6, 0, 1, 0, 7, 7, 1, 5, 5, 0, 1, 1, 1, 1,196, 2, 0, 0, 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, 32, 27,194, 8,176,231,195, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0,144, 86,196, 8,113, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+152, 85,196, 8, 0, 42,196, 8,128, 42,196, 8,192, 42,196, 8, 64, 42,196, 8, 0, 0, 0, 0,184,119,162, 61, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,183,240, 14, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+111, 18,131,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,
+237, 0, 0, 0,223, 3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,237, 0, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,
+ 8, 1, 0, 0,223, 3, 0, 0, 9, 0, 8, 0, 1, 0, 1, 1, 1, 5,216, 2, 1, 0, 1, 0, 5, 3, 0, 0, 7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 89,196, 8, 64, 98,196, 8,104,176,195, 8,104,176,195, 8,
+136, 87,196, 8, 88, 88,196, 8, 68, 65, 84, 65,164, 0, 0, 0,136, 87,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 88, 88,196, 8,
+ 0, 0, 0, 0, 84,114, 97,110,115,102,111,114,109, 32, 80,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 86,105,101,119, 51,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, 44, 0, 21, 2, 62, 1,204, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0, 88, 88,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,136, 87,196, 8, 86,105,101,119,
+ 32, 80,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86,105,101,119,
+ 51,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, 84, 1, 8, 0,
+ 62, 1,204, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,180, 2, 0, 0,
+ 40, 89,196, 8, 89, 0, 0, 0, 1, 0, 0, 0, 8, 92,196, 8, 0, 0, 0, 0, 1, 0, 0, 0, 51, 51, 51, 63,144, 86,196, 8,
+ 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, 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,184,119,162, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,183,240, 14, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 18,131,187, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,123,176, 73, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 25, 62,229, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,121,195, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,184,119,162, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,183,240, 14, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 18,131,187, 0, 0, 0, 0,
+ 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 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,
+123,176, 73, 65, 0, 0, 7, 0, 40, 9,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 3, 0,251,255, 8, 8, 0, 0, 12, 66, 0, 0,128, 63, 0, 0,128, 63,189, 57,161, 60,205,204,204, 61, 0, 0,250, 67,
+ 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128,193, 55,143, 63, 0,174,255,192, 88, 23,141,191, 60, 0, 1, 0, 7, 0,175, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 3, 0,255,255,170,239,188, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+170,239,188, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,170,239,188, 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, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 40, 1, 0, 0, 8, 92,196, 8, 93, 0, 0, 0, 1, 0, 0, 0, 96, 93,196, 8, 40, 89,196, 8, 2, 0, 0, 0,
+ 51, 51, 51, 63,144, 86,196, 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,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, 50, 2, 0, 0, 16, 0, 0, 0,168, 3, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,
+ 16, 0, 0, 0,168, 3, 0, 0, 16, 0, 0, 0, 50, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 72, 12,197, 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, 29, 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, 0, 0, 0, 0, 0, 0,122, 67,205,204,204,189,205,204,140, 63, 68, 65, 84, 65,
+196, 0, 0, 0, 96, 93,196, 8, 97, 0, 0, 0, 1, 0, 0, 0, 96, 96,196, 8, 8, 92,196, 8, 3, 0, 0, 0, 51, 51, 51, 63,
+144, 86,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,246, 24,167, 65,102,102,174,193,
+122, 20,238, 65, 75, 95,116,194, 75, 95,116, 66, 51, 51, 9,194, 51, 51, 9, 66, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,
+ 50, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,233, 3, 0, 0, 0, 0, 0, 0,
+ 50, 2, 0, 0, 0, 0, 32, 65, 0, 0,128, 64, 0, 0,160, 67, 0, 0,160, 67, 10,215, 35, 60, 0, 0, 0, 64, 0, 0, 0, 0,
+ 1, 0, 0, 0,233, 3, 50, 2, 0, 0, 0, 0, 80, 94,196, 8, 8, 96,196, 8, 0, 0,143, 3, 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, 68, 65, 84, 65, 44, 0, 0, 0, 80, 94,196, 8,
+129, 0, 0, 0, 1, 0, 0, 0,168, 94,196, 8, 0, 0, 0, 0, 66, 79, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,113, 61, 10,192,
+ 0, 0, 0, 0, 0, 0, 0, 0, 72, 12,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 44, 0, 0, 0,168, 94,196, 8,
+129, 0, 0, 0, 1, 0, 0, 0, 0, 95,196, 8, 80, 94,196, 8, 69, 77, 4, 0, 0, 0, 0, 0, 0, 0,192, 64,205,204,124, 65,
+ 0, 0, 0, 0, 0, 0, 0, 0, 24, 22,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 44, 0, 0, 0, 0, 95,196, 8,
+129, 0, 0, 0, 1, 0, 0, 0, 88, 95,196, 8,168, 94,196, 8, 65, 77, 5, 0, 0, 0, 0, 0,235, 49,126, 65, 98, 62,200, 65,
+ 0, 0, 0, 0, 0, 0, 0, 0,184, 18,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 44, 0, 0, 0, 88, 95,196, 8,
+129, 0, 0, 0, 1, 0, 0, 0,176, 95,196, 8, 0, 95,196, 8, 66, 79, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 65,
+ 0, 0, 0, 0, 0, 0, 0, 0,152, 15,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 44, 0, 0, 0,176, 95,196, 8,
+129, 0, 0, 0, 1, 0, 0, 0, 8, 96,196, 8, 88, 95,196, 8, 66, 79, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,164,112, 61, 65,
+ 0, 0, 0, 0, 0, 0, 0, 0, 40, 9,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 44, 0, 0, 0, 8, 96,196, 8,
+129, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,176, 95,196, 8, 67, 83, 0, 0, 0, 0, 0, 0, 0, 0,192, 64,102,102,174,193,
+ 0, 0, 0, 0, 0, 0, 0, 0,136,251,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,176, 0, 0, 0, 96, 96,196, 8,
+177, 0, 0, 0, 1, 0, 0, 0, 64, 97,196, 8, 96, 93,196, 8, 12, 0, 0, 0, 51, 51, 51, 63,144, 86,196, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,122, 68, 0, 0, 0, 0, 0, 0,122, 68, 0, 0,160,192,
+ 0, 0,130, 66, 0, 0, 0, 0, 0,128, 8, 68,217, 3, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 50, 2, 0, 0,128, 0, 0, 0,
+217, 3, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,128, 0, 0, 0,217, 3, 0, 0, 16, 0, 0, 0, 50, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,250, 70, 0, 0,122, 68, 10,215, 35, 60, 0, 0, 72, 66, 10, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,212, 0, 0, 0,
+ 64, 97,196, 8, 94, 0, 0, 0, 1, 0, 0, 0, 64, 98,196, 8, 96, 96,196, 8, 4, 0, 0, 0, 51, 51, 51, 63,144, 86,196, 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,224,159, 68,
+ 0, 0,160,193, 0, 0,100, 67,246, 56,165, 67, 26, 29,110, 68, 13,102,183,193,246, 25,161, 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, 0, 0, 0, 0, 0, 0, 0, 0,150, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 84, 1, 0, 0, 64, 98,196, 8, 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 64, 97,196, 8, 5, 0, 0, 0,
+ 51, 51, 51, 63,144, 86,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0,
+ 83, 97,118,101, 32, 70,105,108,101, 0, 78, 84, 0, 32, 80, 73, 67, 84, 85, 82, 69, 83, 0, 0, 47, 85,115,101,114,115, 47,116,
+111,110, 47, 68,101,115,107,116,111,112, 47, 0,117,109,112, 98,117,103, 32, 70,111,108,100,101,114, 47, 0,101,110,100,101,114,
+ 46, 97,112,112, 47, 67,111,110,116,101,110,116,115, 47, 82,101,115,111,117,114, 99,101,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,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,117,110,116,105,116,108,101,100,
+ 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, 8, 0, 11, 0, 1, 0, 0, 0,251, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 0, 83, 82, 0, 0,116, 0, 0, 0,192, 99,196, 8,109, 0, 0, 0, 1, 0, 0, 0,232,163,196, 8,
+ 96, 40,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 83, 82, 51, 45, 77, 97,116,101,114,105, 97,108, 0,111,100,101,108, 32, 83,105,
+110,103, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 96,100,196, 8,160,103,196, 8,224,103,196, 8, 16,110,196, 8, 88,110,196, 8,
+ 56,156,196, 8,136,251,196, 8, 0, 0,231, 3,143, 1,174, 4,232, 3, 32, 3, 1, 0, 3, 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, 68, 65, 84, 65, 20, 0, 0, 0, 96,100,196, 8,110, 0, 0, 0,
+ 1, 0, 0, 0,160,100,196, 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,
+160,100,196, 8,110, 0, 0, 0, 1, 0, 0, 0,224,100,196, 8, 96,100,196, 8, 0, 0, 0, 0, 0, 0, 32, 3, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0,224,100,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 32,101,196, 8,160,100,196, 8, 0, 0, 0, 0,
+232, 3, 32, 3, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 32,101,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 96,101,196, 8,
+224,100,196, 8, 0, 0, 0, 0,232, 3, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 96,101,196, 8,110, 0, 0, 0,
+ 1, 0, 0, 0,160,101,196, 8, 32,101,196, 8, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+160,101,196, 8,110, 0, 0, 0, 1, 0, 0, 0,224,101,196, 8, 96,101,196, 8, 0, 0, 0, 0,232, 3, 60, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0,224,101,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 32,102,196, 8,160,101,196, 8, 0, 0, 0, 0,
+ 0, 0, 6, 3, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 32,102,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 96,102,196, 8,
+224,101,196, 8, 0, 0, 0, 0,232, 3, 6, 3, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 96,102,196, 8,110, 0, 0, 0,
+ 1, 0, 0, 0,160,102,196, 8, 32,102,196, 8, 0, 0, 0, 0, 44, 3, 60, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+160,102,196, 8,110, 0, 0, 0, 1, 0, 0, 0,224,102,196, 8, 96,102,196, 8, 0, 0, 0, 0, 44, 3, 6, 3, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0,224,102,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 32,103,196, 8,160,102,196, 8, 0, 0, 0, 0,
+ 0, 0,176, 1, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 32,103,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 96,103,196, 8,
+224,102,196, 8, 0, 0, 0, 0, 44, 3,176, 1, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 96,103,196, 8,110, 0, 0, 0,
+ 1, 0, 0, 0,160,103,196, 8, 32,103,196, 8, 0, 0, 0, 0,164, 1,176, 1, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+160,103,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 96,103,196, 8, 0, 0, 0, 0,164, 1, 6, 3, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0,224,103,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 40,104,196, 8, 0, 0, 0, 0,160,100,196, 8,
+224,100,196, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 40,104,196, 8,111, 0, 0, 0, 1, 0, 0, 0,
+112,104,196, 8,224,103,196, 8, 96,100,196, 8, 32,101,196, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+112,104,196, 8,111, 0, 0, 0, 1, 0, 0, 0,184,104,196, 8, 40,104,196, 8, 96,100,196, 8, 96,101,196, 8, 1, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,184,104,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 0,105,196, 8,112,104,196, 8,
+ 32,101,196, 8,160,101,196, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 0,105,196, 8,111, 0, 0, 0,
+ 1, 0, 0, 0, 72,105,196, 8,184,104,196, 8, 96,101,196, 8,160,101,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0, 72,105,196, 8,111, 0, 0, 0, 1, 0, 0, 0,144,105,196, 8, 0,105,196, 8,160,100,196, 8,224,101,196, 8,
+ 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,144,105,196, 8,111, 0, 0, 0, 1, 0, 0, 0,216,105,196, 8,
+ 72,105,196, 8,224,100,196, 8, 32,102,196, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,216,105,196, 8,
+111, 0, 0, 0, 1, 0, 0, 0, 32,106,196, 8,144,105,196, 8,224,101,196, 8, 32,102,196, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0, 32,106,196, 8,111, 0, 0, 0, 1, 0, 0, 0,104,106,196, 8,216,105,196, 8,160,101,196, 8,
+ 32,102,196, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,104,106,196, 8,111, 0, 0, 0, 1, 0, 0, 0,
+176,106,196, 8, 32,106,196, 8, 96,101,196, 8, 96,102,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+176,106,196, 8,111, 0, 0, 0, 1, 0, 0, 0,248,106,196, 8,104,106,196, 8,160,101,196, 8, 96,102,196, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,248,106,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 64,107,196, 8,176,106,196, 8,
+ 32,102,196, 8,160,102,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 64,107,196, 8,111, 0, 0, 0,
+ 1, 0, 0, 0,136,107,196, 8,248,106,196, 8, 96,102,196, 8,160,102,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0,136,107,196, 8,111, 0, 0, 0, 1, 0, 0, 0,208,107,196, 8, 64,107,196, 8, 96,101,196, 8,224,102,196, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,208,107,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 24,108,196, 8,
+136,107,196, 8,224,101,196, 8,224,102,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 24,108,196, 8,
+111, 0, 0, 0, 1, 0, 0, 0, 96,108,196, 8,208,107,196, 8,160,102,196, 8, 32,103,196, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0, 96,108,196, 8,111, 0, 0, 0, 1, 0, 0, 0,168,108,196, 8, 24,108,196, 8, 96,102,196, 8,
+ 32,103,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,168,108,196, 8,111, 0, 0, 0, 1, 0, 0, 0,
+240,108,196, 8, 96,108,196, 8,224,102,196, 8, 32,103,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+240,108,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 56,109,196, 8,168,108,196, 8,224,102,196, 8, 96,103,196, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 56,109,196, 8,111, 0, 0, 0, 1, 0, 0, 0,128,109,196, 8,240,108,196, 8,
+ 32,103,196, 8, 96,103,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,128,109,196, 8,111, 0, 0, 0,
+ 1, 0, 0, 0,200,109,196, 8, 56,109,196, 8,224,101,196, 8,160,103,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0,200,109,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 16,110,196, 8,128,109,196, 8,160,102,196, 8,160,103,196, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 16,110,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+200,109,196, 8, 96,103,196, 8,160,103,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0, 88,110,196, 8,
+113, 0, 0, 0, 1, 0, 0, 0,112,122,196, 8, 0, 0, 0, 0, 96,100,196, 8, 96,101,196, 8,160,101,196, 8, 32,101,196, 8,
+ 0, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,183, 64, 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,226,215,163,188,
+ 0, 0, 0, 0, 0, 0, 0, 0,232, 3, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0,232, 3, 0, 0, 0, 0, 0, 0,
+ 26, 0, 0, 0, 0, 0, 0, 0,232, 3, 0, 0, 27, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 1, 0, 15, 15,233, 3, 33, 0,
+ 1, 1, 1, 0,192, 2, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,144,114,196, 8,
+240,120,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 80,111,196, 8,192,113,196, 8, 68, 65, 84, 65,164, 0, 0, 0, 80,111,196, 8,
+112, 0, 0, 0, 1, 0, 0, 0, 32,112,196, 8, 0, 0, 0, 0, 79,117,116,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 32,112,196, 8,112, 0, 0, 0, 1, 0, 0, 0,
+240,112,196, 8, 80,111,196, 8, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 70, 1, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,240,112,196, 8,112, 0, 0, 0, 1, 0, 0, 0,192,113,196, 8, 32,112,196, 8,
+ 65,110,105,109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+140, 2, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+164, 0, 0, 0,192,113,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,240,112,196, 8, 70,111,114,109, 97,116, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,210, 3, 0, 0, 62, 1,204, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,148, 0, 0, 0,144,114,196, 8,
+102, 0, 0, 0, 1, 0, 0, 0, 80,115,196, 8, 0, 0, 0, 0, 15, 0, 0, 0, 51, 51, 51, 63, 1, 86,239, 92, 0, 0,128,192,
+ 0, 0,126, 67, 0, 0, 0, 0, 0, 0, 16, 65, 0, 0,128,192, 0, 0,126, 67, 0, 0, 0, 0, 0, 0, 16, 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,
+233, 3, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0,128, 63, 0, 0, 16, 65, 0, 0,250, 70, 0, 0, 16, 65,205,204,204, 61,
+ 0, 0, 32, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 68, 65, 84, 65,
+160, 0, 0, 0, 80,115,196, 8,166, 0, 0, 0, 1, 0, 0, 0, 32,116,196, 8,144,114,196, 8, 11, 0, 0, 0, 51, 51, 51, 63,
+ 1, 86,239, 92, 0, 0,128,192, 0, 0,122, 67, 0, 0,128,192, 0, 0,127, 67, 0, 0,128,192, 0, 0, 72, 66, 0, 0,128,192,
+ 0, 0,127, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,233, 3, 0, 0, 0, 0, 0, 0,
+ 16, 0, 0, 0, 0, 0, 0, 0,233, 3, 0, 0, 16, 0, 0, 0, 9, 0, 0, 0, 0, 0,128, 63, 0,128,129, 67, 0, 0,250, 70,
+ 0,128,129, 67,205,204,204, 61, 0, 0, 32, 65, 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, 68, 65, 84, 65,212, 0, 0, 0, 32,116,196, 8, 94, 0, 0, 0,
+ 1, 0, 0, 0, 32,117,196, 8, 80,115,196, 8, 4, 0, 0, 0, 51, 51, 51, 63, 1, 86,239, 92, 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,193, 0, 0,163, 68, 0, 0, 0,193, 0, 0,104, 67,
+ 63, 0, 0,193,172, 3,182, 68, 0, 0, 0,193, 0, 0,104, 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,
+251, 4,209, 0, 0, 0, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,109, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,180, 2, 0, 0,
+ 32,117,196, 8, 89, 0, 0, 0, 1, 0, 0, 0, 0,120,196, 8, 32,116,196, 8, 1, 0, 0, 0, 51, 51, 51, 63, 1, 86,239, 92,
+ 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, 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, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,183, 64, 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,161, 14,106, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 99, 15, 51, 62, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 32, 65, 1, 0, 7, 0, 40, 9,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 3, 0, 0, 0, 0, 24, 0, 0, 12, 66, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 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, 16, 0, 1, 0, 7, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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,196, 0, 0, 0, 0,120,196, 8, 97, 0, 0, 0, 1, 0, 0, 0,240,120,196, 8, 32,117,196, 8, 3, 0, 0, 0,
+ 51, 51, 51, 63, 1, 86,239, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,192, 0, 0,160, 64,
+ 0, 0, 0, 0,205,204,140, 65,201, 82, 5,194,124,171, 30, 66, 49,238,226, 64,140,108,168, 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, 1, 5, 0, 0,
+ 0, 0, 0, 0,245, 0, 0, 0, 0, 0, 32, 65, 0, 0,128, 64, 0, 0,160, 67, 0, 0,160, 67, 10,215, 35, 60, 0, 0, 0, 64,
+ 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,142, 3, 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, 68, 65, 84, 65, 84, 1, 0, 0,
+240,120,196, 8, 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,120,196, 8, 5, 0, 0, 0, 51, 51, 51, 63, 1, 86,239, 92,
+ 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0,
+ 68, 65, 84, 65,204, 0, 0, 0,112,122,196, 8,113, 0, 0, 0, 1, 0, 0, 0,104,123,196, 8, 88,110,196, 8,224,101,196, 8,
+160,100,196, 8,224,100,196, 8, 32,102,196, 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,232, 3, 0, 0, 7, 3, 0, 0, 32, 3, 0, 0,
+ 0, 0, 0, 0,232, 3, 0, 0, 7, 3, 0, 0, 33, 3, 0, 0, 0, 0, 0, 0,232, 3, 0, 0, 32, 3, 0, 0, 32, 3, 0, 0,
+ 0, 0, 0, 0, 1, 0, 7, 7,233, 3, 1, 0, 1, 1, 1, 1,196, 2, 0, 0, 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,
+ 68, 65, 84, 65,204, 0, 0, 0,104,123,196, 8,113, 0, 0, 0, 1, 0, 0, 0,216,140,196, 8,112,122,196, 8, 96,102,196, 8,
+160,102,196, 8, 32,102,196, 8,160,101,196, 8, 0, 0, 0, 0,255,255, 71, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,255,255,139, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 13,128,191, 0, 0,128,191,
+ 0, 0, 0,128, 0, 0, 0,128, 74,215, 76,190, 0, 0, 0,128, 45, 3, 0, 0,232, 3, 0, 0, 61, 0, 0, 0, 5, 3, 0, 0,
+ 45, 3, 0, 0,232, 3, 0, 0, 61, 0, 0, 0, 87, 0, 0, 0, 45, 3, 0, 0,232, 3, 0, 0, 88, 0, 0, 0, 5, 3, 0, 0,
+ 0, 0, 0, 0, 1, 0, 4, 4,188, 0,174, 2, 1, 1, 1, 0,179, 1,126, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 32,134,196, 8, 88,139,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 96,124,196, 8, 80,133,196, 8,
+ 68, 65, 84, 65,164, 0, 0, 0, 96,124,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 48,125,196, 8, 0, 0, 0, 0, 79,117,116,112,
+117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,
+101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+ 48,125,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 0,126,196, 8, 96,124,196, 8, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,255, 62, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 0,126,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0,208,126,196, 8, 48,125,196, 8, 65,110,105,109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,254, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,208,126,196, 8,112, 0, 0, 0, 1, 0, 0, 0,160,127,196, 8,
+ 0,126,196, 8, 70,111,114,109, 97,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 72,253, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0,160,127,196, 8,112, 0, 0, 0, 1, 0, 0, 0,112,128,196, 8,208,126,196, 8, 80,114,101,118,
+105,101,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,
+114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+112,128,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 64,129,196, 8,160,127,196, 8, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,255, 62, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 64,129,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0, 16,130,196, 8,112,128,196, 8, 83,104, 97,100,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,254, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 16,130,196, 8,112, 0, 0, 0, 1, 0, 0, 0,224,130,196, 8,
+ 64,129,196, 8, 84,101,120,116,117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,252, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0,224,130,196, 8,112, 0, 0, 0, 1, 0, 0, 0,176,131,196, 8, 16,130,196, 8, 77, 97,112, 32,
+ 73,110,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,
+114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,251,
+ 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+176,131,196, 8,112, 0, 0, 0, 1, 0, 0, 0,128,132,196, 8,224,130,196, 8, 77, 97,112, 32, 84,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, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,252, 62, 1,204, 0, 4, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,128,132,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0, 80,133,196, 8,176,131,196, 8, 82, 97,109,112,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,255, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,112,128,196, 8, 68, 65, 84, 65,164, 0, 0, 0, 80,133,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+128,132,196, 8, 77,105,114,114,111,114, 32, 84,114, 97,110,115,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 72,253, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,212, 0, 0, 0, 32,134,196, 8, 94, 0, 0, 0, 1, 0, 0, 0, 32,135,196, 8, 0, 0, 0, 0, 4, 0, 0, 0,
+ 51, 51, 51, 63, 1, 86,249,156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0,193, 0, 0,163, 67, 0,128,148,196, 0, 0,104, 67, 0, 0, 0,193, 0, 0,163, 67,170,175,118,196,255,255,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,188, 0,174, 2, 0, 0, 0, 0, 3, 0, 1, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,141, 0, 0, 0, 0, 0,150, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,180, 2, 0, 0, 32,135,196, 8, 89, 0, 0, 0, 1, 0, 0, 0, 0,138,196, 8,
+ 32,134,196, 8, 1, 0, 0, 0, 51, 51, 51, 63, 1, 86,249,156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+188, 74,140, 62,166,194, 72,191, 33,132, 14, 63, 0, 0, 0, 0, 41,120,117, 63,135,105, 54, 62,200, 80, 98,190, 0, 0, 0, 0,
+239,220,151, 61, 31, 40, 24, 63, 94,255, 76, 63, 0, 0, 0, 0,175,149, 97, 63,230,187,142,189,122,166,182,193, 0, 0,128, 63,
+186, 74,140, 62, 35,120,117, 63,254,220,151, 61, 0, 0, 0, 0,160,194, 72,191,131,105, 54, 62, 30, 40, 24, 63, 0, 0, 0, 0,
+ 32,132, 14, 63,190, 80, 98,190, 94,255, 76, 63, 0, 0, 0, 0, 92,160, 70, 65,162, 28,188,192,224, 17,146, 65, 0, 0,128, 63,
+197, 52, 91, 63,228,148, 91,191,186,146, 14,191, 33,132, 14,191,223,197, 63, 64,106,131, 71, 62,246,103, 98, 62,200, 80, 98, 62,
+ 52, 73,109, 62,225,107, 38, 63, 93, 20, 77,191, 94,255, 76,191,240, 60, 48, 64,130, 29,156,189,128, 31,181, 65,122,166,182, 65,
+252,146,179, 61,173, 25,157, 62, 75, 99,194, 60, 0, 0,165, 50,214,141, 55,191,192,199, 38, 62,176, 28, 11, 63, 0,128, 24,181,
+167, 58,120,194,184, 22,235, 65, 49,140,182,194, 27,247,159,192, 5, 26,118, 66, 44,106,233,193,230, 4,181, 66,126, 7,160, 64,
+255,255, 71, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,139, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 28, 13,128,191, 0, 0,128,191, 0, 0, 0,128, 0, 0, 0,128, 74,215, 76,190, 0, 0, 0,128,
+188, 74,140, 62,166,194, 72,191, 33,132, 14, 63, 0, 0, 0, 0, 41,120,117, 63,135,105, 54, 62,200, 80, 98,190, 0, 0, 0, 0,
+239,220,151, 61, 31, 40, 24, 63, 94,255, 76, 63, 0, 0, 0, 0,175,149, 97, 63,230,187,142,189,122,166,182,193, 0, 0,128, 63,
+218, 31, 64, 63, 36, 17,139,190,182,154, 36,190,156,165, 20,191,221, 79,187, 65, 1, 0, 0, 0, 40, 9,197, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 0, 10, 0, 0, 24, 0, 0, 12, 66, 0, 0,128, 63,
+ 0, 0, 0, 0, 0, 0, 0, 0,205,204,204, 61, 0, 0,250, 67,104,217, 30, 63,106, 40, 52, 63,116, 39,251, 62, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,100, 0, 0, 0, 7, 0,175, 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, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 40, 1, 0, 0, 0,138,196, 8, 93, 0, 0, 0,
+ 1, 0, 0, 0, 88,139,196, 8, 32,135,196, 8, 2, 0, 0, 0, 51, 51, 51, 63, 1, 86,249,156, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 84, 1, 0, 0, 88,139,196, 8, 96, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0,138,196, 8, 5, 0, 0, 0, 51, 51, 51, 63, 1, 86,249,156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 83, 65, 86, 69, 32, 70, 73, 76, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 47,117,115,114, 47,104,111,109,101, 47,105,110,116,114,114, 47, 98,108,101,110,100,101,114, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,117,110,116,105,116,108,101,100, 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, 8, 0, 24, 0, 1, 0, 0, 0,203, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0,216,140,196, 8,
+113, 0, 0, 0, 1, 0, 0, 0,136,148,196, 8,104,123,196, 8, 96,101,196, 8,224,102,196, 8, 32,103,196, 8, 96,102,196, 8,
+ 0, 0, 0, 0, 85,240, 46, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,237,119,206, 61, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0,128,111, 18, 3,187, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,128, 63, 0, 0, 0, 0, 43, 3, 0, 0, 61, 0, 0, 0,175, 1, 0, 0, 0, 0, 0, 0, 43, 3, 0, 0, 61, 0, 0, 0,
+ 87, 0, 0, 0, 0, 0, 0, 0, 43, 3, 0, 0, 88, 0, 0, 0,175, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 44, 3, 88, 1,
+ 1, 0, 1, 0,251, 2, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,208,141,196, 8,
+ 8,147,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,180, 2, 0, 0,208,141,196, 8,
+ 89, 0, 0, 0, 1, 0, 0, 0,176,144,196, 8, 0, 0, 0, 0, 1, 0, 0, 0, 51, 51, 51, 63, 1, 87, 7,236, 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, 0, 0,104,217, 30, 63,
+106, 40, 52, 63,116, 39,251, 62, 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,104,217, 30,191,
+106, 40, 52,191,116, 39,251,190, 0, 0,128, 63, 85,240, 46, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+237,119,206, 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,202, 25,217, 60,
+235, 76,145, 61, 70,151,128,186, 0, 0,128, 63,172, 79,187, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1,181, 30, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0,128,255,255,249,195, 0, 0, 0, 0,103,217, 30,191,
+106, 40, 52,191,116, 39,251,190, 0, 0,128, 63, 85,240, 46, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+237,119,206, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0,128,111, 18, 3,187, 0, 0, 0,128, 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,104,217, 30, 63,
+106, 40, 52, 63,116, 39,251, 62, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,172, 79,187, 65,
+ 0, 0, 7, 0, 40, 9,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 0,
+ 10, 0, 8, 24, 0, 0, 12, 66, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,205,204,204, 61, 0, 0,250, 67,104,217, 30, 63,
+106, 40, 52, 63,116, 39,251, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100, 0, 1, 0, 7, 0,175, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0, 0, 0, 69,104,138, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,104,138, 64,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,104,138, 64, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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,
+212, 0, 0, 0,176,144,196, 8, 94, 0, 0, 0, 1, 0, 0, 0,176,145,196, 8,208,141,196, 8, 4, 0, 0, 0, 51, 51, 51, 63,
+ 1, 87, 7,236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,224,159, 68, 0, 0, 0, 0, 0, 0,100, 67,172, 62, 57, 67, 44,184,136, 68,169,101, 28,195, 16,147,173, 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, 0, 0, 0, 0, 0, 0, 0, 0,150, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,176,145,196, 8, 93, 0, 0, 0, 1, 0, 0, 0, 8,147,196, 8,176,144,196, 8,
+ 2, 0, 0, 0, 51, 51, 51, 63, 1, 87, 7,236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 84, 1, 0, 0, 8,147,196, 8, 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,176,145,196, 8, 5, 0, 0, 0,
+ 51, 51, 51, 63, 1, 87, 7,236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0,
+ 83, 65, 86, 69, 32, 70, 73, 76, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 85,115,101,114,115, 47,116,
+111,110, 47, 68,101,115,107,116,111,112, 47, 0,100,101,114, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,117,110,116,105,116,108,101,100,
+ 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, 8, 0, 0, 0, 1, 0, 0, 0,203, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0,136,148,196, 8,113, 0, 0, 0, 1, 0, 0, 0, 56,156,196, 8,
+216,140,196, 8, 96,103,196, 8,160,103,196, 8,160,102,196, 8, 32,103,196, 8, 0, 0, 0, 0,173,101,182, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 36,209, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+154, 65,128,191, 0, 0,128,191, 0, 0, 0,128, 0, 0, 0,128, 72, 1, 77,190, 0, 0, 0,128,165, 1, 0, 0, 43, 3, 0, 0,
+177, 1, 0, 0, 5, 3, 0, 0,165, 1, 0, 0, 43, 3, 0, 0,177, 1, 0, 0,177, 1, 0, 0,165, 1, 0, 0, 43, 3, 0, 0,
+177, 1, 0, 0, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,135, 1, 85, 1, 3, 0, 1, 0, 83, 2, 0, 0, 7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,149,196, 8,184,154,196, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,180, 2, 0, 0,128,149,196, 8, 89, 0, 0, 0, 1, 0, 0, 0, 96,152,196, 8,
+ 0, 0, 0, 0, 1, 0, 0, 0, 51, 51, 51, 63, 1, 87, 12,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+221,149, 47, 63, 85,126,162,190, 8,165, 39, 63, 0, 0, 0, 0, 51, 70, 58, 63,225,251,159, 62,149, 84, 28,191, 0, 0, 0, 0,
+191, 56, 49,188, 54, 53,101, 63, 50,247,227, 62, 0, 0, 0, 0, 90, 38,173,190,254,221,192,190,152, 9, 52,193, 0, 0,128, 63,
+223,149, 47, 63, 55, 70, 58, 63,192, 56, 49,188, 0, 0, 0, 0, 87,126,162,190,228,251,159, 62, 56, 53,101, 63, 0, 0, 0, 0,
+ 7,165, 39, 63,150, 84, 28,191, 50,247,227, 62, 0, 0, 0, 0,110,101,239, 64,151, 62,208,192, 77,255,170, 64, 0, 0,128, 63,
+144, 52,122, 63, 39,192, 4,191,244,250, 39,191, 8,165, 39,191,228,183,132, 63, 75,179, 2, 63,180,164, 28, 63,149, 84, 28, 63,
+118,137,124,188,232, 64,187, 63, 8,108,228,190, 50,247,227,190, 18,188,246,190,141,144, 29,191,216, 49, 49, 65,152, 9, 52, 65,
+116,112,246, 62,142,184, 2, 63, 64,191,248,187, 0, 0,144,179, 64,230, 70,190,226,211, 67, 62,254, 71, 12, 63, 0, 0, 0, 52,
+211,120, 21,194,144, 5, 2, 66, 7,136,213,193,193,214,159,192,219, 38, 19, 66,196,173,255,193,155,101,210, 65,173, 40,160, 64,
+173,101,182, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 36,209, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,154, 65,128,191, 0, 0,128,191, 0, 0, 0,128, 0, 0, 0,128, 72, 1, 77,190, 0, 0, 0,128,
+221,149, 47, 63, 85,126,162,190, 8,165, 39, 63, 0, 0, 0, 0, 51, 70, 58, 63,225,251,159, 62,149, 84, 28,191, 0, 0, 0, 0,
+191, 56, 49,188, 54, 53,101, 63, 50,247,227, 62, 0, 0, 0, 0, 90, 38,173,190,254,221,192,190,152, 9, 52,193, 0, 0,128, 63,
+241, 22, 72, 63, 78,162,246,190, 44, 8, 90,190, 3, 35,171,190,221, 79,187, 65, 2, 0, 0, 0, 40, 9,197, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 0, 10, 0, 8, 24, 0, 0, 12, 66, 0, 0,128, 63,
+ 0, 0,128, 63, 0, 0, 0, 0,205,204,204, 61, 0, 0,250, 67,104,217, 30, 63,106, 40, 52, 63,116, 39,251, 62, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,100, 0, 0, 0, 7, 0,175, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0,221,224, 65, 64,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,221,224, 65, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,221,224, 65, 64, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,212, 0, 0, 0, 96,152,196, 8, 94, 0, 0, 0,
+ 1, 0, 0, 0, 96,153,196, 8,128,149,196, 8, 4, 0, 0, 0, 51, 51, 51, 63, 1, 87, 12,124, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,224,159, 68, 0, 0, 0, 0, 0, 0,100, 67,
+172, 62, 57, 67, 44,184,136, 68,169,101, 28,195, 16,147,173, 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, 0, 0,
+ 0, 0, 0, 0, 0, 0,150, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,
+ 96,153,196, 8, 93, 0, 0, 0, 1, 0, 0, 0,184,154,196, 8, 96,152,196, 8, 2, 0, 0, 0, 51, 51, 51, 63, 1, 87, 12,124,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 84, 1, 0, 0,184,154,196, 8,
+ 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 96,153,196, 8, 5, 0, 0, 0, 51, 51, 51, 63, 1, 87, 12,124, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 83, 65, 86, 69, 32, 70, 73, 76, 69, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 85,115,101,114,115, 47,116,111,110, 47, 68,101,115,107,116,111,112, 47, 0,
+100,101,114, 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, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,117,110,116,105,116,108,101,100, 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, 8, 0, 0, 0,
+ 1, 0, 0, 0,203, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+204, 0, 0, 0, 56,156,196, 8,113, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,136,148,196, 8,224,102,196, 8,224,101,196, 8,
+160,103,196, 8, 96,103,196, 8, 0, 0, 0, 0,152, 38,151, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 7, 43,186, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0,128,111, 18, 3,187, 0, 0, 0,128, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0,163, 1, 0, 0,177, 1, 0, 0, 5, 3, 0, 0, 0, 0, 0, 0,
+163, 1, 0, 0,177, 1, 0, 0,177, 1, 0, 0, 0, 0, 0, 0,163, 1, 0, 0,177, 1, 0, 0, 5, 3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1,164, 1, 85, 1, 3, 0, 1, 0, 83, 2, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 48,157,196, 8,104,162,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+180, 2, 0, 0, 48,157,196, 8, 89, 0, 0, 0, 1, 0, 0, 0, 16,160,196, 8, 0, 0, 0, 0, 1, 0, 0, 0, 51, 51, 51, 63,
+ 1, 87, 17, 12, 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,128,
+ 0, 0, 0, 0, 0, 0, 0,128,174, 2, 19, 51,255,255,127,191, 0, 0, 0, 0, 0, 0, 0, 0,255,255,127, 63,174, 2, 19, 51,
+ 0, 0, 0, 0, 58,248, 30,192, 45,161,118,192,107, 40, 52,191, 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, 51, 1, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,128,191,176, 2, 19, 51,
+ 0, 0, 0, 0, 59,248, 30, 64,107, 40, 52,191, 48,161,118, 64, 0, 0,128, 63,152, 38,151, 61, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 80,209, 85, 49,110, 18, 3, 59, 0, 0, 0, 0, 0, 0, 0, 0, 6, 43,186, 61,234,137,150,174,
+ 0, 0, 0, 0,195,184, 59,190,143, 90,179,190, 79,123,184, 58, 0, 0,128, 63, 74,202, 88, 65, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 53, 0, 0,128, 52, 85, 3, 48, 65, 0, 0, 0, 0, 0, 0,128,171, 1, 0,250, 67,160,144,143,183,
+ 0, 0, 0, 0, 59,248, 30, 64,106, 40, 52,191, 48,161,118, 64, 0, 0,128, 63,152, 38,151, 61, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 7, 43,186, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0,128,111, 18, 3,187,
+ 0, 0, 0,128, 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,128,
+ 0, 0, 0, 0, 0, 0, 0,128,174, 2, 19, 51,255,255,127,191, 0, 0, 0, 0, 0, 0, 0, 0,255,255,127, 63,174, 2, 19, 51,
+ 0, 0, 0, 0, 58,248, 30,192, 45,161,118,192,107, 40, 52,191, 0, 0,128, 63,243, 4, 53, 63,243, 4, 53,191, 0, 0, 0, 0,
+ 0, 0, 0, 0, 73,202, 88, 65, 0, 0, 1, 0, 40, 9,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 3, 0, 10, 0, 8, 24, 0, 0, 12, 66, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,205,204,204, 61,
+ 0, 0,250, 67, 58,248, 30,192,106, 40, 52, 63, 46,161,118,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100, 0, 2, 0,
+ 7, 0,175, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0,162,217,154, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,162,217,154, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,162,217,154, 64, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,212, 0, 0, 0, 16,160,196, 8, 94, 0, 0, 0, 1, 0, 0, 0, 16,161,196, 8, 48,157,196, 8,
+ 4, 0, 0, 0, 51, 51, 51, 63, 1, 87, 17, 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,224,159, 68, 0, 0, 0, 0, 0, 0,100, 67,172, 62, 57, 67, 44,184,136, 68,169,101, 28,195,
+ 16,147,173, 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, 0, 0, 0, 0, 0, 0, 0, 0,150, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0, 16,161,196, 8, 93, 0, 0, 0, 1, 0, 0, 0,
+104,162,196, 8, 16,160,196, 8, 2, 0, 0, 0, 51, 51, 51, 63, 1, 87, 17, 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,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, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 84, 1, 0, 0,104,162,196, 8, 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 16,161,196, 8, 5, 0, 0, 0, 51, 51, 51, 63, 1, 87, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 32, 0, 0, 0, 83, 65, 86, 69, 32, 70, 73, 76, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 47, 85,115,101,114,115, 47,116,111,110, 47, 68,101,115,107,116,111,112, 47, 0,100,101,114, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+117,110,116,105,116,108,101,100, 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, 8, 0, 0, 0, 1, 0, 0, 0,203, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 83, 82, 0, 0,116, 0, 0, 0,232,163,196, 8,109, 0, 0, 0,
+ 1, 0, 0, 0,136,207,196, 8,192, 99,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 83, 82, 52, 45, 83,101,113,117,101,110, 99,101,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,136,164,196, 8,200,167,196, 8, 8,168,196, 8,
+168,173,196, 8,240,173,196, 8, 96,201,196, 8,136,251,196, 8, 0, 0,231, 3,143, 1,174, 4,232, 3, 32, 3, 1, 0, 4, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+136,164,196, 8,110, 0, 0, 0, 1, 0, 0, 0,200,164,196, 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,200,164,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 8,165,196, 8,136,164,196, 8, 0, 0, 0, 0,
+ 0, 0, 32, 3, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 8,165,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 72,165,196, 8,
+200,164,196, 8, 0, 0, 0, 0,232, 3, 32, 3, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 72,165,196, 8,110, 0, 0, 0,
+ 1, 0, 0, 0,136,165,196, 8, 8,165,196, 8, 0, 0, 0, 0,232, 3, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+136,165,196, 8,110, 0, 0, 0, 1, 0, 0, 0,200,165,196, 8, 72,165,196, 8, 0, 0, 0, 0, 0, 0,200, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0,200,165,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 8,166,196, 8,136,165,196, 8, 0, 0, 0, 0,
+232, 3,200, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 8,166,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 72,166,196, 8,
+200,165,196, 8, 0, 0, 0, 0, 0, 0, 6, 3, 1, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 72,166,196, 8,110, 0, 0, 0,
+ 1, 0, 0, 0,136,166,196, 8, 8,166,196, 8, 0, 0, 0, 0,232, 3, 6, 3, 1, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+136,166,196, 8,110, 0, 0, 0, 1, 0, 0, 0,200,166,196, 8, 72,166,196, 8, 0, 0, 0, 0, 0, 0,244, 1, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0,200,166,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 8,167,196, 8,136,166,196, 8, 0, 0, 0, 0,
+232, 3,244, 1, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 8,167,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 72,167,196, 8,
+200,166,196, 8, 0, 0, 0, 0, 84, 2,244, 1, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 72,167,196, 8,110, 0, 0, 0,
+ 1, 0, 0, 0,136,167,196, 8, 8,167,196, 8, 0, 0, 0, 0, 84, 2, 6, 3, 1, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+136,167,196, 8,110, 0, 0, 0, 1, 0, 0, 0,200,167,196, 8, 72,167,196, 8, 0, 0, 0, 0, 0, 0, 4, 1, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0,200,167,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,136,167,196, 8, 0, 0, 0, 0,
+232, 3, 4, 1, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 8,168,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 80,168,196, 8,
+ 0, 0, 0, 0,200,164,196, 8, 8,165,196, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 80,168,196, 8,
+111, 0, 0, 0, 1, 0, 0, 0,152,168,196, 8, 8,168,196, 8,136,164,196, 8, 72,165,196, 8, 1, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0,152,168,196, 8,111, 0, 0, 0, 1, 0, 0, 0,224,168,196, 8, 80,168,196, 8,136,164,196, 8,
+136,165,196, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,224,168,196, 8,111, 0, 0, 0, 1, 0, 0, 0,
+ 40,169,196, 8,152,168,196, 8, 72,165,196, 8,200,165,196, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+ 40,169,196, 8,111, 0, 0, 0, 1, 0, 0, 0,112,169,196, 8,224,168,196, 8,136,165,196, 8,200,165,196, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,112,169,196, 8,111, 0, 0, 0, 1, 0, 0, 0,184,169,196, 8, 40,169,196, 8,
+200,164,196, 8, 8,166,196, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,184,169,196, 8,111, 0, 0, 0,
+ 1, 0, 0, 0, 0,170,196, 8,112,169,196, 8, 8,165,196, 8, 72,166,196, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0, 0,170,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 72,170,196, 8,184,169,196, 8, 8,166,196, 8, 72,166,196, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 72,170,196, 8,111, 0, 0, 0, 1, 0, 0, 0,144,170,196, 8,
+ 0,170,196, 8, 8,166,196, 8,136,166,196, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,144,170,196, 8,
+111, 0, 0, 0, 1, 0, 0, 0,216,170,196, 8, 72,170,196, 8, 72,166,196, 8,200,166,196, 8, 1, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0,216,170,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 32,171,196, 8,144,170,196, 8,136,166,196, 8,
+200,166,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 32,171,196, 8,111, 0, 0, 0, 1, 0, 0, 0,
+104,171,196, 8,216,170,196, 8,136,166,196, 8, 8,167,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+104,171,196, 8,111, 0, 0, 0, 1, 0, 0, 0,176,171,196, 8, 32,171,196, 8,200,166,196, 8, 8,167,196, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,176,171,196, 8,111, 0, 0, 0, 1, 0, 0, 0,248,171,196, 8,104,171,196, 8,
+ 8,166,196, 8, 72,167,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,248,171,196, 8,111, 0, 0, 0,
+ 1, 0, 0, 0, 64,172,196, 8,176,171,196, 8, 72,166,196, 8, 72,167,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0, 64,172,196, 8,111, 0, 0, 0, 1, 0, 0, 0,136,172,196, 8,248,171,196, 8, 8,167,196, 8, 72,167,196, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,136,172,196, 8,111, 0, 0, 0, 1, 0, 0, 0,208,172,196, 8,
+ 64,172,196, 8,136,165,196, 8,136,167,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,208,172,196, 8,
+111, 0, 0, 0, 1, 0, 0, 0, 24,173,196, 8,136,172,196, 8,136,166,196, 8,136,167,196, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0, 24,173,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 96,173,196, 8,208,172,196, 8,200,166,196, 8,
+200,167,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 96,173,196, 8,111, 0, 0, 0, 1, 0, 0, 0,
+168,173,196, 8, 24,173,196, 8,200,165,196, 8,200,167,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+168,173,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 96,173,196, 8,136,167,196, 8,200,167,196, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0,240,173,196, 8,113, 0, 0, 0, 1, 0, 0, 0,168,180,196, 8, 0, 0, 0, 0,
+136,164,196, 8,136,165,196, 8,200,165,196, 8, 72,165,196, 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,232, 3, 0, 0, 0, 0, 0, 0,
+199, 0, 0, 0, 0, 0, 0, 0,232, 3, 0, 0,173, 0, 0, 0,199, 0, 0, 0, 0, 0, 0, 0,232, 3, 0, 0, 0, 0, 0, 0,
+172, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 4,233, 3,173, 0, 1, 0, 1, 1,139, 1, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40,178,196, 8, 40,179,196, 8, 0, 0, 0, 0, 0, 0, 0, 0,232,174,196, 8,
+ 88,177,196, 8, 68, 65, 84, 65,164, 0, 0, 0,232,174,196, 8,112, 0, 0, 0, 1, 0, 0, 0,184,175,196, 8, 0, 0, 0, 0,
+ 79,117,116,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+164, 0, 0, 0,184,175,196, 8,112, 0, 0, 0, 1, 0, 0, 0,136,176,196, 8,232,174,196, 8, 82,101,110,100,101,114, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 1, 0, 0, 62, 1,204, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,136,176,196, 8,
+112, 0, 0, 0, 1, 0, 0, 0, 88,177,196, 8,184,175,196, 8, 65,110,105,109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 2, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 88,177,196, 8,112, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0,136,176,196, 8, 70,111,114,109, 97,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,210, 3, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65,212, 0, 0, 0, 40,178,196, 8, 94, 0, 0, 0, 1, 0, 0, 0, 40,179,196, 8, 0, 0, 0, 0,
+ 4, 0, 0, 0, 51, 51, 51, 63, 1, 87, 30,252, 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,193, 0, 0,163, 68, 0, 0, 0,193, 0, 0,104, 67, 0, 0, 0,193,118,149,172, 68, 0, 0, 0,193,
+ 0, 0,104, 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,233, 3,173, 0, 0, 0, 0, 0, 0, 0,255,255,
+ 0, 0, 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, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 84, 1, 0, 0, 40,179,196, 8, 96, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 40,178,196, 8, 5, 0, 0, 0, 51, 51, 51, 63, 1, 87, 30,252, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0,168,180,196, 8,
+113, 0, 0, 0, 1, 0, 0, 0,160,181,196, 8,240,173,196, 8, 8,166,196, 8,200,164,196, 8, 8,165,196, 8, 72,166,196, 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,232, 3, 0, 0, 7, 3, 0, 0, 32, 3, 0, 0, 0, 0, 0, 0,232, 3, 0, 0, 7, 3, 0, 0,
+ 33, 3, 0, 0, 0, 0, 0, 0,232, 3, 0, 0, 32, 3, 0, 0, 32, 3, 0, 0, 0, 0, 0, 0, 1, 0, 7, 7,233, 3, 1, 0,
+ 1, 0, 1, 1,196, 2, 0, 0, 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, 68, 65, 84, 65,204, 0, 0, 0,160,181,196, 8,
+113, 0, 0, 0, 1, 0, 0, 0,136,188,196, 8,168,180,196, 8,136,165,196, 8,136,167,196, 8,200,167,196, 8,200,165,196, 8,
+ 0, 0, 0, 0,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,232, 3, 0, 0,201, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0,232, 3, 0, 0,201, 0, 0, 0,
+227, 0, 0, 0, 0, 0, 0, 0,232, 3, 0, 0,228, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 1, 0, 15, 15,233, 3, 32, 0,
+ 1, 0, 1, 1,192, 2, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152,182,196, 8,
+ 8,187,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,148, 0, 0, 0,152,182,196, 8,
+102, 0, 0, 0, 1, 0, 0, 0, 88,183,196, 8, 0, 0, 0, 0, 15, 0, 0, 0, 51, 51, 51, 63, 1, 87, 38,188, 0, 0,128,192,
+ 0, 0,126, 67, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0,128,192, 0, 0,126, 67, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+233, 3, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 66, 0, 0,250, 70, 0, 0, 0, 66,205,204,204, 61,
+ 0, 0, 32, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 68, 65, 84, 65,
+164, 0, 0, 0, 88,183,196, 8, 95, 0, 0, 0, 1, 0, 0, 0, 40,184,196, 8,152,182,196, 8, 8, 0, 0, 0, 51, 51, 51, 63,
+ 1, 87, 38,188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,
+ 32, 0, 0, 0, 16, 0, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0,233, 3, 0, 0, 16, 0, 0, 0,
+ 32, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 68, 65, 84, 65,180, 2, 0, 0, 40,184,196, 8,
+ 89, 0, 0, 0, 1, 0, 0, 0, 8,187,196, 8, 88,183,196, 8, 1, 0, 0, 0, 51, 51, 51, 63, 1, 87, 38,188, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,102,102,102, 65,
+ 0, 0, 7, 0, 40, 9,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 0,
+ 0, 0, 0, 24, 0, 0, 12, 66, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 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, 20, 0, 0, 0, 7, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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,
+ 84, 1, 0, 0, 8,187,196, 8, 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 40,184,196, 8, 5, 0, 0, 0, 51, 51, 51, 63,
+ 1, 87, 38,188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,
+ 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0,136,188,196, 8,113, 0, 0, 0, 1, 0, 0, 0,176,194,196, 8,160,181,196, 8,
+ 8,167,196, 8, 72,167,196, 8, 72,166,196, 8,200,166,196, 8, 0, 0, 0, 0,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, 85, 2, 0, 0,232, 3, 0, 0,245, 1, 0, 0,
+ 5, 3, 0, 0, 85, 2, 0, 0,232, 3, 0, 0,245, 1, 0, 0,245, 1, 0, 0, 85, 2, 0, 0,232, 3, 0, 0,245, 1, 0, 0,
+ 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8,148, 1, 17, 1, 3, 0, 1, 1, 9, 1, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,189,196, 8, 48,193,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,128,189,196, 8, 95, 0, 0, 0, 1, 0, 0, 0, 80,190,196, 8, 0, 0, 0, 0,
+ 8, 0, 0, 0, 51, 51, 51, 63, 1, 87, 42,204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+180, 2, 0, 0, 80,190,196, 8, 89, 0, 0, 0, 1, 0, 0, 0, 48,193,196, 8,128,189,196, 8, 1, 0, 0, 0, 51, 51, 51, 63,
+ 1, 87, 42,204, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,102,102,102, 65, 0, 0, 7, 0, 40, 9,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 24, 0, 0, 12, 66, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 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, 20, 0, 0, 0,
+ 7, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 84, 1, 0, 0, 48,193,196, 8, 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 80,190,196, 8,
+ 5, 0, 0, 0, 51, 51, 51, 63, 1, 87, 42,204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0,176,194,196, 8,113, 0, 0, 0, 1, 0, 0, 0,
+ 96,201,196, 8,136,188,196, 8,136,166,196, 8, 8,166,196, 8, 72,167,196, 8, 8,167,196, 8, 0, 0, 0, 0,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,
+ 83, 2, 0, 0,245, 1, 0, 0, 5, 3, 0, 0, 0, 0, 0, 0, 83, 2, 0, 0,245, 1, 0, 0, 15, 2, 0, 0, 0, 0, 0, 0,
+ 83, 2, 0, 0, 16, 2, 0, 0, 5, 3, 0, 0, 0, 0, 0, 0, 1, 0, 2, 2, 84, 2,246, 0, 1, 0, 1, 0,203, 1, 0, 0,
+ 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,195,196, 8,224,199,196, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 40, 1, 0, 0,168,195,196, 8, 93, 0, 0, 0, 1, 0, 0, 0,
+ 0,197,196, 8, 0, 0, 0, 0, 2, 0, 0, 0, 51, 51, 51, 63, 1, 87, 46, 28, 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,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,246, 0, 0, 0, 16, 0, 0, 0,
+ 19, 2, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 19, 2, 0, 0, 16, 0, 0, 0,246, 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, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 0, 0, 0, 0,
+ 0, 0, 83, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160,192, 0, 0,210, 66,
+205,204,204,189,205,204,140, 63, 68, 65, 84, 65,180, 2, 0, 0, 0,197,196, 8, 89, 0, 0, 0, 1, 0, 0, 0,224,199,196, 8,
+168,195,196, 8, 1, 0, 0, 0, 51, 51, 51, 63, 1, 87, 46, 28, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,102,102,102, 65, 0, 0, 7, 0, 40, 9,197, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 24, 0, 0, 12, 66, 0, 0,128, 63,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 20, 0, 0, 0, 7, 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, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 84, 1, 0, 0,224,199,196, 8, 96, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0,197,196, 8, 5, 0, 0, 0, 51, 51, 51, 63, 1, 87, 46, 28, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 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, 0, 0, 0, 0,
+ 57, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0,
+ 96,201,196, 8,113, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,176,194,196, 8,136,167,196, 8,136,166,196, 8,200,166,196, 8,
+200,167,196, 8, 0, 0, 0, 0,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,232, 3, 0, 0, 5, 1, 0, 0,243, 1, 0, 0, 0, 0, 0, 0,232, 3, 0, 0,
+ 5, 1, 0, 0, 31, 1, 0, 0, 0, 0, 0, 0,232, 3, 0, 0, 32, 1, 0, 0,243, 1, 0, 0, 0, 0, 0, 0, 1, 0, 8, 8,
+233, 3,212, 0, 1, 0, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 88,202,196, 8, 8,206,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+ 88,202,196, 8, 95, 0, 0, 0, 1, 0, 0, 0, 40,203,196, 8, 0, 0, 0, 0, 8, 0, 0, 0, 51, 51, 51, 63, 1, 87, 49,172,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,212, 0, 0, 0,
+ 16, 0, 0, 0,233, 3, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0,233, 3, 0, 0, 16, 0, 0, 0,212, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 68, 65, 84, 65,180, 2, 0, 0, 40,203,196, 8, 89, 0, 0, 0,
+ 1, 0, 0, 0, 8,206,196, 8, 88,202,196, 8, 1, 0, 0, 0, 51, 51, 51, 63, 1, 87, 49,172, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,102,102,102, 65, 0, 0, 7, 0,
+ 40, 9,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 24,
+ 0, 0, 12, 66, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 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, 20, 0, 0, 0, 7, 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,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 84, 1, 0, 0,
+ 8,206,196, 8, 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 40,203,196, 8, 5, 0, 0, 0, 51, 51, 51, 63, 1, 87, 49,172,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0,
+ 83, 82, 0, 0,116, 0, 0, 0,136,207,196, 8,109, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,232,163,196, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 83, 82, 53, 45, 83, 99,114,105,112,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 40,208,196, 8,104,210,196, 8,168,210,196, 8,152,214,196, 8,224,214,196, 8,176,236,196, 8,136,251,196, 8,
+ 0, 0,231, 3,143, 1,174, 4,232, 3, 32, 3, 1, 0, 5, 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, 68, 65, 84, 65, 20, 0, 0, 0, 40,208,196, 8,110, 0, 0, 0, 1, 0, 0, 0,104,208,196, 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,104,208,196, 8,110, 0, 0, 0,
+ 1, 0, 0, 0,168,208,196, 8, 40,208,196, 8, 0, 0, 0, 0, 0, 0, 32, 3, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+168,208,196, 8,110, 0, 0, 0, 1, 0, 0, 0,232,208,196, 8,104,208,196, 8, 0, 0, 0, 0,232, 3, 32, 3, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0,232,208,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 40,209,196, 8,168,208,196, 8, 0, 0, 0, 0,
+232, 3, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 40,209,196, 8,110, 0, 0, 0, 1, 0, 0, 0,104,209,196, 8,
+232,208,196, 8, 0, 0, 0, 0, 0, 0,212, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,104,209,196, 8,110, 0, 0, 0,
+ 1, 0, 0, 0,168,209,196, 8, 40,209,196, 8, 0, 0, 0, 0, 0, 0, 6, 3, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+168,209,196, 8,110, 0, 0, 0, 1, 0, 0, 0,232,209,196, 8,104,209,196, 8, 0, 0, 0, 0,232, 3, 6, 3, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0,232,209,196, 8,110, 0, 0, 0, 1, 0, 0, 0, 40,210,196, 8,168,209,196, 8, 0, 0, 0, 0,
+156, 1,212, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 40,210,196, 8,110, 0, 0, 0, 1, 0, 0, 0,104,210,196, 8,
+232,209,196, 8, 0, 0, 0, 0,156, 1, 6, 3, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,104,210,196, 8,110, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 40,210,196, 8, 0, 0, 0, 0,156, 1, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+168,210,196, 8,111, 0, 0, 0, 1, 0, 0, 0,240,210,196, 8, 0, 0, 0, 0,104,208,196, 8,168,208,196, 8, 1, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,240,210,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 56,211,196, 8,168,210,196, 8,
+104,208,196, 8,104,209,196, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 56,211,196, 8,111, 0, 0, 0,
+ 1, 0, 0, 0,128,211,196, 8,240,210,196, 8,168,208,196, 8,168,209,196, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0,128,211,196, 8,111, 0, 0, 0, 1, 0, 0, 0,200,211,196, 8, 56,211,196, 8,104,209,196, 8,168,209,196, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,200,211,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 16,212,196, 8,
+128,211,196, 8, 40,209,196, 8,232,209,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 16,212,196, 8,
+111, 0, 0, 0, 1, 0, 0, 0, 88,212,196, 8,200,211,196, 8,104,209,196, 8, 40,210,196, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0, 88,212,196, 8,111, 0, 0, 0, 1, 0, 0, 0,160,212,196, 8, 16,212,196, 8,168,209,196, 8,
+ 40,210,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,160,212,196, 8,111, 0, 0, 0, 1, 0, 0, 0,
+232,212,196, 8, 88,212,196, 8,232,209,196, 8, 40,210,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+232,212,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 48,213,196, 8,160,212,196, 8, 40,209,196, 8,104,209,196, 8, 1, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 48,213,196, 8,111, 0, 0, 0, 1, 0, 0, 0,120,213,196, 8,232,212,196, 8,
+ 40,208,196, 8, 40,209,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,120,213,196, 8,111, 0, 0, 0,
+ 1, 0, 0, 0,192,213,196, 8, 48,213,196, 8, 40,208,196, 8,104,210,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0,192,213,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 8,214,196, 8,120,213,196, 8,232,208,196, 8,104,210,196, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 8,214,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 80,214,196, 8,
+192,213,196, 8,232,209,196, 8,104,210,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 80,214,196, 8,
+111, 0, 0, 0, 1, 0, 0, 0,152,214,196, 8, 8,214,196, 8, 40,210,196, 8,104,210,196, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0,152,214,196, 8,111, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 80,214,196, 8,232,208,196, 8,
+168,209,196, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0,224,214,196, 8,113, 0, 0, 0, 1, 0, 0, 0,
+216,215,196, 8, 0, 0, 0, 0,104,209,196, 8,104,208,196, 8,168,208,196, 8,168,209,196, 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,
+232, 3, 0, 0, 7, 3, 0, 0, 32, 3, 0, 0, 0, 0, 0, 0,232, 3, 0, 0, 7, 3, 0, 0, 33, 3, 0, 0, 0, 0, 0, 0,
+232, 3, 0, 0, 32, 3, 0, 0, 32, 3, 0, 0, 0, 0, 0, 0, 1, 0, 7, 7,233, 3, 1, 0, 3, 0, 3, 1,196, 2, 0, 0,
+ 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, 68, 65, 84, 65,204, 0, 0, 0,216,215,196, 8,113, 0, 0, 0, 1, 0, 0, 0,
+208,222,196, 8,224,214,196, 8, 40,209,196, 8,104,209,196, 8, 40,210,196, 8,232,209,196, 8, 0, 0, 0, 0,122,214,248, 61,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,186,252,191, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,
+ 0, 0, 0,128,111, 18, 3,187, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0,
+155, 1, 0, 0,213, 0, 0, 0, 5, 3, 0, 0, 0, 0, 0, 0,155, 1, 0, 0,213, 0, 0, 0,239, 0, 0, 0, 0, 0, 0, 0,
+155, 1, 0, 0,240, 0, 0, 0, 5, 3, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1,156, 1, 22, 2, 1, 0, 3, 0,251, 2, 0, 0,
+ 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,112,218,196, 8, 80,221,196, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0,208,216,196, 8,160,217,196, 8, 68, 65, 84, 65,164, 0, 0, 0,208,216,196, 8,112, 0, 0, 0, 1, 0, 0, 0,
+160,217,196, 8, 0, 0, 0, 0, 84,114, 97,110,115,102,111,114,109, 32, 80,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 86,105,101,119, 51,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,140, 0,210, 0, 62, 1,204, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,160,217,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,208,216,196, 8,
+ 51, 68, 32, 86,105,101,119,112,111,114,116, 32,112,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 86,105,101,119, 51,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,
+ 8, 0, 8, 0, 62, 1,204, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+180, 2, 0, 0,112,218,196, 8, 89, 0, 0, 0, 1, 0, 0, 0, 80,221,196, 8, 0, 0, 0, 0, 1, 0, 0, 0, 51, 51, 51, 63,
+ 1, 89, 46,124, 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, 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,122,214,248, 61, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,186,252,191, 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, 38,175, 3, 65, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,148,173, 42, 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,122,214,248, 61, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,186,252,191, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0,128,111, 18, 3,187,
+ 0, 0, 0,128, 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,148,173, 42, 65, 0, 0, 7, 0, 40, 9,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 3, 0, 0, 0, 8, 24, 0, 0, 12, 66, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,205,204,204, 61,
+ 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, 32, 0, 1, 0,
+ 7, 0,175, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0,232,197, 63, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,232,197, 63, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,197, 63, 64, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 84, 1, 0, 0, 80,221,196, 8, 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,112,218,196, 8,
+ 5, 0, 0, 0, 51, 51, 51, 63, 1, 89, 46,124, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0,208,222,196, 8,113, 0, 0, 0, 1, 0, 0, 0,
+176,236,196, 8,216,215,196, 8,104,210,196, 8, 40,210,196, 8,168,209,196, 8,232,208,196, 8, 0, 0, 0, 0, 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,157, 1, 0, 0,
+232, 3, 0, 0, 0, 0, 0, 0, 5, 3, 0, 0,157, 1, 0, 0,232, 3, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0,157, 1, 0, 0,
+232, 3, 0, 0, 27, 0, 0, 0, 5, 3, 0, 0, 0, 0, 0, 0, 1, 0, 9, 9, 76, 2,235, 2, 3, 0, 3, 0,165, 2, 0, 0,
+ 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152,224,196, 8, 48,235,196, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0,200,223,196, 8,200,223,196, 8, 68, 65, 84, 65,164, 0, 0, 0,200,223,196, 8,112, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 84,114, 97,110,115,102,111,114,109, 32, 80,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 73,112,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, 33, 0,167, 0, 62, 1,204, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65,120, 0, 0, 0,152,224,196, 8,100, 0, 0, 0, 1, 0, 0, 0, 64,225,196, 8, 0, 0, 0, 0,
+ 9, 0, 0, 0, 51, 51, 51, 63, 1, 89, 47,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 3,197, 8,
+ 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,205,204,204, 61, 5, 0, 0, 0, 17, 0, 0, 0,225, 2, 0, 0,227, 2, 0, 0,
+ 5, 0, 0, 0, 17, 0, 0, 0,207, 2, 0, 0,227, 2, 0, 0, 68, 65, 84, 65,184, 0, 0, 0, 64,225,196, 8, 98, 0, 0, 0,
+ 1, 0, 0, 0, 40,226,196, 8,152,224,196, 8, 6, 0, 0, 0, 51, 51, 51, 63, 1, 89, 47,124, 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, 0, 0, 0, 0,128, 67, 0, 0,120,190, 0, 0,159, 63,
+ 0, 0,242,190, 0,128,188, 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, 0, 0, 0, 0, 0, 0, 0, 0,124, 1, 0, 0, 0, 0, 0, 0,242, 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,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 40, 1, 0, 0, 40,226,196, 8, 93, 0, 0, 0, 1, 0, 0, 0,128,227,196, 8, 64,225,196, 8, 2, 0, 0, 0, 51, 51, 51, 63,
+ 1, 89, 47,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,242, 1, 0, 0, 16, 0, 0, 0, 59, 1, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0,
+ 59, 1, 0, 0, 16, 0, 0, 0,242, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 72, 12,197, 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, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 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,122, 67,205,204,204,189,205,204,140, 63, 68, 65, 84, 65,196, 0, 0, 0,
+128,227,196, 8, 97, 0, 0, 0, 1, 0, 0, 0,208,229,196, 8, 40,226,196, 8, 3, 0, 0, 0, 51, 51, 51, 63, 1, 89, 47,124,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,182, 67, 0, 0,209,195, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,182, 67, 0, 0,190,195, 0, 0, 0,181, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,124, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,124, 1, 0, 0, 0, 0, 0, 0,124, 1, 0, 0,
+ 0, 0,190,195, 0, 0,190,195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 1, 0, 1, 0, 1, 0, 1, 0,
+108, 1,124, 1, 0, 0, 0, 0,112,228,196, 8,120,229,196, 8, 0, 0,142, 3, 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, 68, 65, 84, 65, 44, 0, 0, 0,112,228,196, 8,129, 0, 0, 0,
+ 1, 0, 0, 0,200,228,196, 8, 0, 0, 0, 0, 66, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 65, 0, 0, 0, 0,
+ 0, 0, 0, 0,152, 15,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 44, 0, 0, 0,200,228,196, 8,129, 0, 0, 0,
+ 1, 0, 0, 0, 32,229,196, 8,112,228,196, 8, 66, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,164,112, 61, 65, 0, 0, 0, 0,
+ 0, 0, 0, 0, 40, 9,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 44, 0, 0, 0, 32,229,196, 8,129, 0, 0, 0,
+ 1, 0, 0, 0,120,229,196, 8,200,228,196, 8, 66, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,113, 61, 10,192, 0, 0, 0, 0,
+ 0, 0, 0, 0, 72, 12,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 44, 0, 0, 0,120,229,196, 8,129, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 32,229,196, 8, 69, 77, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21,174,143, 65, 0, 0, 0, 0,
+ 0, 0, 0, 0, 24, 22,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,208,229,196, 8,166, 0, 0, 0,
+ 1, 0, 0, 0,160,230,196, 8,128,227,196, 8, 11, 0, 0, 0, 51, 51, 51, 63, 1, 89, 47,124, 0, 0,128,192, 0, 0,122, 67,
+ 0, 0,128,192, 0, 0,127, 67, 0, 0,128,192, 0, 0, 72, 66, 0, 0,128,192, 0, 0,127, 67, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 1, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,124, 1, 0, 0,
+ 16, 0, 0, 0,124, 1, 0, 0, 0, 0,128, 63, 0,128,129, 67, 0, 0,250, 70, 0,128,129, 67,205,204,204, 61, 0, 0, 32, 65,
+ 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, 68, 65, 84, 65,164, 0, 0, 0,160,230,196, 8, 99, 0, 0, 0, 1, 0, 0, 0,112,231,196, 8,208,229,196, 8,
+ 13, 0, 0, 0, 51, 51, 51, 63, 1, 89, 47,124, 0, 0, 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,122, 68, 0, 0, 0, 0, 0, 0,122, 68, 0, 0,160,192, 0, 0,130, 66, 0, 0, 0, 0,
+ 0, 0,182, 67,108, 1, 0, 0,124, 1, 0, 0, 0, 0, 0, 0,124, 1, 0, 0,196, 0, 0, 0,108, 1, 0, 0, 0, 0, 0, 0,
+ 16, 0, 0, 0,196, 0, 0, 0,108, 1, 0, 0, 16, 0, 0, 0,124, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,122, 68,
+ 0, 0,122, 68,205,204,204, 61, 0, 0, 72, 66, 10, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+176, 0, 0, 0,112,231,196, 8,177, 0, 0, 0, 1, 0, 0, 0, 80,232,196, 8,160,230,196, 8, 12, 0, 0, 0, 51, 51, 51, 63,
+ 1, 89, 47,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 0, 0, 2, 66, 0, 0,128,193,
+ 0, 0,247, 67, 0, 0, 0,191, 0, 0, 2, 66, 0, 0,128,193, 0, 0,247, 67,108, 1, 0, 0,124, 1, 0, 0, 0, 0, 0, 0,
+ 14, 2, 0, 0,128, 0, 0, 0,108, 1, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,128, 0, 0, 0,108, 1, 0, 0, 16, 0, 0, 0,
+ 14, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,250, 70, 0, 0,122, 68, 10,215, 35, 60, 0, 0, 72, 66, 10, 0, 0, 0,
+ 0, 0, 0, 2, 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, 0, 0,
+ 68, 65, 84, 65,180, 2, 0, 0, 80,232,196, 8, 89, 0, 0, 0, 1, 0, 0, 0, 48,235,196, 8,112,231,196, 8, 1, 0, 0, 0,
+ 51, 51, 51, 63, 1, 89, 47,124, 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, 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, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 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, 32, 65, 1, 0, 7, 0, 40, 9,197, 8, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 24, 0, 0, 12, 66, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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,
+ 20, 0, 0, 0, 7, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 84, 1, 0, 0, 48,235,196, 8, 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 80,232,196, 8, 5, 0, 0, 0, 51, 51, 51, 63, 1, 89, 47,124, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 68, 65, 84, 65,204, 0, 0, 0,176,236,196, 8,113, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0,208,222,196, 8, 40,208,196, 8, 40,209,196, 8,232,209,196, 8,104,210,196, 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,155, 1, 0, 0, 0, 0, 0, 0,211, 0, 0, 0, 0, 0, 0, 0,155, 1, 0, 0,185, 0, 0, 0,211, 0, 0, 0,
+ 0, 0, 0, 0,155, 1, 0, 0, 0, 0, 0, 0,184, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 4,156, 1,185, 0, 3, 0, 3, 0,
+ 79, 1, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8,249,196, 8, 8,250,196, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0,168,237,196, 8, 56,248,196, 8, 68, 65, 84, 65,164, 0, 0, 0,168,237,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0,120,238,196, 8, 0, 0, 0, 0, 76,105,110,107, 32, 97,110,100, 32, 77, 97,116,101,114,105, 97,108,115, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,120,238,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 72,239,196, 8,
+168,237,196, 8, 77,101,115,104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 70, 1, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0, 72,239,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 24,240,196, 8,120,238,196, 8, 65,110,105,109,
+ 32,115,101,116,116,105,110,103,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 98,106,101,
+ 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+ 24,240,196, 8,112, 0, 0, 0, 1, 0, 0, 0,232,240,196, 8, 72,239,196, 8, 68,114, 97,119, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 1, 0, 0, 62, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,232,240,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0,184,241,196, 8, 24,240,196, 8, 67,111,110,115,116,114, 97,105,110,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 2, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,184,241,196, 8,112, 0, 0, 0, 1, 0, 0, 0,136,242,196, 8,
+232,240,196, 8, 69,102,102,101, 99,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,210, 3, 0, 0,162, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0,136,242,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 88,243,196, 8,184,241,196, 8, 72,111,111,107,
+115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 98,106,101,
+ 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 1, 0, 0,
+ 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,240,196, 8, 68, 65, 84, 65,164, 0, 0, 0,
+ 88,243,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 40,244,196, 8,136,242,196, 8, 80, 97,114,116,105, 99,108,101, 32, 73,110,116,
+101,114, 97, 99,116,105,111,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 2, 0, 0, 62, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,240,196, 8, 68, 65, 84, 65,164, 0, 0, 0, 40,244,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0,248,244,196, 8, 88,243,196, 8, 83,111,102,116, 98,111,100,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 2, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,232,240,196, 8, 68, 65, 84, 65,164, 0, 0, 0,248,244,196, 8,112, 0, 0, 0, 1, 0, 0, 0,200,245,196, 8,
+ 40,244,196, 8, 79,117,116,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,164, 0, 0, 0,200,245,196, 8,112, 0, 0, 0, 1, 0, 0, 0,152,246,196, 8,248,244,196, 8, 82,101,110,100,
+101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,
+101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 1, 0, 0,
+ 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,
+152,246,196, 8,112, 0, 0, 0, 1, 0, 0, 0,104,247,196, 8,200,245,196, 8, 65,110,105,109, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 2, 0, 0, 62, 1,204, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0,104,247,196, 8,112, 0, 0, 0,
+ 1, 0, 0, 0, 56,248,196, 8,152,246,196, 8, 70,111,114,109, 97,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,210, 3, 0, 0, 62, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,164, 0, 0, 0, 56,248,196, 8,112, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+104,247,196, 8, 83, 99,114,105,112,116,108,105,110,107,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 83, 99,114,105,112,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,212, 0, 0, 0, 8,249,196, 8, 94, 0, 0, 0, 1, 0, 0, 0, 8,250,196, 8, 0, 0, 0, 0, 4, 0, 0, 0,
+ 51, 51, 51, 63, 1, 89, 48,124, 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,193, 0, 0,163, 67, 0, 0, 0,193, 0, 0,104, 67, 0, 0, 0,193, 35,159, 3, 68, 0, 0, 0,193, 0, 0,104, 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,156, 1,185, 0, 0, 0, 0, 0, 5, 0,255,255, 0, 0, 5, 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, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 84, 1, 0, 0, 8,250,196, 8, 96, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 8,249,196, 8, 5, 0, 0, 0, 51, 51, 51, 63, 1, 89, 48,124, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 83, 67, 0, 0,244, 3, 0, 0,136,251,196, 8, 87, 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, 83, 99,101,110,101, 0,116, 97,103,101,
+ 0, 97,105,110, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 40, 9,197, 8,160, 2,197, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0,168,255,196, 8, 56, 0,197, 8,168,255,196, 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, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,205,204,204, 61, 0, 0, 0, 0,128, 0,197, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49,197, 8, 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,
+ 0, 0,128, 2,224, 1, 60, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0,100, 0,141, 0, 32, 3, 88, 2,
+100, 0,100, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,128, 63, 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, 24, 0, 4, 0, 0, 0, 90, 0, 16, 0, 23, 0, 1, 0, 0, 0,128, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 8, 0, 25, 0, 10, 0, 0, 0, 0, 0, 0, 64, 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,128, 63, 0, 0, 0, 0,205,204, 76, 63,102,102,102, 63, 0, 0,128, 63, 0, 0,128, 64,
+ 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98, 97, 99,107, 98,117,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,116,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,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,102,116,121,112,101, 0, 64, 38, 35, 0, 0, 0, 0, 0, 64, 94, 0, 0, 64, 38, 94, 0, 0, 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, 68,172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,226,187, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 28, 0, 0, 0,
+168,255,196, 8, 79, 0, 0, 0, 1, 0, 0, 0,240,255,196, 8, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+128, 2,108, 1, 72, 12,197, 8, 68, 65, 84, 65, 28, 0, 0, 0,240,255,196, 8, 79, 0, 0, 0, 1, 0, 0, 0, 56, 0,197, 8,
+168,255,196, 8, 1, 0, 0, 0, 2, 0, 0, 0, 0, 4, 0, 0, 78, 3,159, 1,152, 15,197, 8, 68, 65, 84, 65, 28, 0, 0, 0,
+ 56, 0,197, 8, 79, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,240,255,196, 8, 1, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0,
+251, 3, 33, 0, 40, 9,197, 8, 68, 65, 84, 65, 40, 0, 0, 0,128, 0,197, 8, 78, 0, 0, 0, 1, 0, 0, 0, 44, 1, 0, 0,
+ 1, 0, 2, 0, 1, 0, 2, 0, 0, 0, 1, 0,244, 1,200, 0,100, 0, 20, 0, 16, 39, 0, 0,205,204,204, 61, 0, 0,240, 65,
+ 0, 0, 0, 64, 68, 65, 84, 65, 28, 0, 0, 0, 48, 49,197, 8, 86, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 90, 0, 9, 0,
+ 1, 0, 0, 0, 0, 0,128, 63,111, 18,131, 58, 32, 0, 32, 0, 32, 0, 0, 0, 67, 65, 0, 0,116, 0, 0, 0,216, 0,197, 8,
+ 23, 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, 97,109,101,114, 97, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0,205,204, 76, 62,
+ 0, 0, 0, 0,205,204,204, 61, 0, 0,200, 66, 0, 0, 12, 66,161, 14,234, 64, 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, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 0, 0,
+252, 0, 0, 0,120, 1,197, 8, 31, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 76, 65, 83,112,111,116, 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,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,247,255,239, 65,
+ 0, 0,150, 66,154,153, 25, 62, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 64, 11, 3, 0, 46, 26,128, 63, 25, 4,240, 65,
+ 0, 0, 52, 66, 0, 0,128, 63, 0, 0, 64, 64, 1, 0, 1, 0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 79, 0, 0, 32, 1, 0, 0,160, 2,197, 8, 77, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 79, 87,111,114,108,100, 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, 0, 0, 0, 0, 0, 0, 0, 0,128,174,103, 61,112, 29, 98, 62,
+205,204,204, 62, 0, 0, 0, 0,205,204,204, 61,205,204,204, 61,205,204,204, 61, 0, 0, 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, 0, 0, 0, 0, 0, 0,
+205,204, 28, 65, 0, 0, 0, 0, 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, 64, 0, 0, 0, 0, 0, 0,112, 65, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, 0, 0, 0, 0, 0, 0,128, 63,205,204, 76, 61, 0, 0, 5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 88, 0, 0,100, 0, 0, 0,240, 3,197, 8, 21, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 84, 88, 84,101,120,116, 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, 0, 0, 0, 0, 7, 0, 0, 0, 1, 0, 0, 0,128, 4,197, 8,128, 4,197, 8,128, 4,197, 8,128, 4,197, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0,248, 4,197, 8,255,255,255,255, 0, 4, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+128, 4,197, 8, 20, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200, 4,197, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 69, 69, 82, 70, 68, 65, 84, 65, 4, 0, 0, 0,200, 4,197, 8, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 79, 66, 0, 0,
+244, 2, 0, 0, 40, 9,197, 8, 71, 0, 0, 0, 1, 0, 0, 0, 72, 12,197, 8, 0, 0, 0, 0, 1, 89, 70,108, 0, 0, 0, 0,
+ 79, 66, 67, 97,109,101,114, 97, 0, 97,109,101,114, 97, 46, 48, 48, 49, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 0,197, 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,110,101,239, 64,150, 62,208,192, 78,255,170, 64, 0, 0, 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, 42,254,141, 63,192, 57, 49, 60, 34,159, 80, 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,128, 63, 0, 0, 0, 0, 0, 0, 0, 0,222,149, 47, 63,
+ 53, 70, 58, 63,222, 56, 49,188, 0, 0, 0, 0, 86,126,162,190,227,251,159, 62, 55, 53,101, 63, 0, 0, 0, 0, 7,165, 39, 63,
+149, 84, 28,191, 51,247,227, 62, 0, 0, 0, 0,110,101,239, 64,150, 62,208,192, 78,255,170, 64, 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,
+157,190,215, 49,167,170, 4, 52, 0, 0, 0,128,129,116,157,178, 1, 0,128, 63, 33, 69, 15, 51, 0, 0, 0,128, 73,254, 67, 51,
+243, 97,106, 49, 0, 0,128, 63, 0, 0, 0,128, 3, 0, 64, 52,183,164,157, 39, 0, 0,128, 53, 0, 0,128, 63, 1, 0, 0, 0,
+ 0, 4, 0, 0, 0, 0, 0, 0, 5, 0, 1, 0, 0, 0, 0, 0, 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, 6, 41,100, 63, 0, 0,128, 63,205,204,204, 62, 0, 0, 0, 0, 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,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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,244, 2, 0, 0, 72, 12,197, 8, 71, 0, 0, 0, 1, 0, 0, 0,152, 15,197, 8, 40, 9,197, 8,
+ 1, 89,123, 92, 0, 0, 0, 0, 79, 66, 67,117, 98,101, 0,112,104,101,114,101, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 22,197, 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,104, 15,197, 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,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,222,149, 47, 63, 52, 70, 58, 63,179, 56, 49,188, 0, 0, 0,128, 86,126,162,190,227,251,159, 62, 56, 53,101, 63,
+ 0, 0, 0,128, 7,165, 39, 63,149, 84, 28,191, 50,247,227, 62, 0, 0, 0,128,110,101,239, 64,151, 62,208,192, 77,255,170, 64,
+ 0, 0,128, 63, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 68, 0, 1, 0, 2, 0, 0, 0, 0, 0, 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, 62,
+ 0, 0, 0, 0,205,204,204, 61, 0, 0, 0, 0, 4, 0, 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,128, 63, 0, 64, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 24,218,193, 8,200, 29,197, 8, 68, 65, 84, 65, 4, 0, 0, 0,104, 15,197, 8, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 79, 66, 0, 0,244, 2, 0, 0,152, 15,197, 8, 71, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 72, 12,197, 8,
+ 1, 89,121, 92, 0, 0, 0, 0, 79, 66, 76, 97,109,112, 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, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 1,197, 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,154,112,130, 64,183,178,128, 63,112,236,188, 64, 0, 0, 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,229,123, 38, 63, 87, 43, 98, 61,229,229,238, 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,128, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54,236,148,190, 25,134,116, 63,236, 13, 98,189, 0, 0, 0, 0,221,102, 69,191, 57,174, 76,190, 34,194, 26, 63,
+ 0, 0, 0, 0, 37,255, 16, 63,241,161, 95, 62,164,111, 75, 63, 0, 0, 0, 0,154,112,130, 64,183,178,128, 63,112,236,188, 64,
+ 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, 53,236,148,190,222,102, 69,191, 37,255, 16, 63, 0, 0, 0,128, 24,134,116, 63, 57,174, 76,190,240,161, 95, 62,
+ 0, 0, 0,128,235, 13, 98,189, 34,194, 26, 63,166,111, 75, 63, 0, 0, 0,128,208, 19, 13, 63,234, 65,102,190, 10, 10,231,192,
+ 0, 0,128, 63, 1, 0, 0, 0, 0, 4, 0, 0, 0, 0, 68, 0, 5, 0, 1, 0, 0, 0, 0, 0, 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, 62,
+ 0, 0, 0, 0,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, 64, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 65, 0, 0,156, 1, 0, 0,184, 18,197, 8, 33, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 65, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,205,204, 76, 63,205,204, 76, 63,205,204, 76, 63,
+ 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 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, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63,205,204, 76, 63,
+ 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 63, 0, 0, 0, 0, 0, 0,160, 63,
+ 0, 0, 0, 0, 2, 0, 2, 0, 50, 0, 0, 6, 3, 0, 1, 3, 0, 0, 0, 0, 1, 0, 4, 0, 12, 0, 4, 0, 0, 0, 0, 63,
+ 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0,128, 64, 0, 0, 0, 63,205,204,204, 61, 0, 0, 0, 63,
+205,204,204, 61,205,204,204, 61, 0, 0,128, 63, 1, 8, 1, 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,128, 20,197, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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,
+ 88, 0, 0, 0,128, 20,197, 8, 25, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 21,197, 8,
+ 1, 2, 3, 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, 16, 0, 0, 0,
+ 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0,128, 63,
+205,204, 76, 62, 0, 0, 0, 0, 84, 69, 0, 0,228, 0, 0, 0, 8, 21,197, 8, 30, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 84,101,120, 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, 0, 0,128, 62, 0, 0,160, 64, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,
+ 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 64, 0, 0, 0, 64, 0, 0,128, 63, 0, 0,128, 63,
+ 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, 32, 64, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0, 5, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63,
+ 1, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0,205,204,204, 60, 0, 0, 0, 0, 1, 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,
+ 77, 69, 0, 0,188, 0, 0, 0, 24, 22,197, 8, 46, 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, 67,117, 98,101, 0,112,104,101,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0,232, 31,194, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23,197, 8, 88, 0,194, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0,216, 21,194, 8,120, 28,194, 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, 8, 0, 0, 0, 12, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 0, 0,128, 51, 0, 0, 0,180,
+ 0, 0, 0, 0, 4, 0,128, 63, 4, 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, 0, 30, 0, 4, 0, 1, 0, 1, 0, 1, 0, 0, 0, 68, 65, 84, 65, 4, 0, 0, 0, 0, 23,197, 8, 0, 0, 0, 0,
+ 1, 0, 0, 0,184, 18,197, 8, 68, 65, 84, 65,160, 0, 0, 0,216, 21,194, 8, 51, 0, 0, 0, 8, 0, 0, 0, 0, 0,128, 63,
+255,255,127, 63, 0, 0,128,191,230, 73,230, 73, 26,182, 3,255, 0, 0,128, 63, 0, 0,128,191, 0, 0,128,191,230, 73, 26,182,
+ 26,182, 3,255, 1, 0,128,191,253,255,127,191, 0, 0,128,191, 26,182, 26,182, 26,182, 3,255,250,255,127,191, 3, 0,128, 63,
+ 0, 0,128,191, 26,182,230, 73, 26,182, 3,255, 4, 0,128, 63,247,255,127, 63, 0, 0,128, 63,230, 73,230, 73,230, 73, 3,255,
+245,255,127, 63, 5, 0,128,191, 0, 0,128, 63,230, 73, 26,182,230, 73, 3,255, 3, 0,128,191,250,255,127,191, 0, 0,128, 63,
+ 26,182, 26,182,230, 73, 3,255,255,255,127,191, 0, 0,128, 63, 0, 0,128, 63, 26,182,230, 73,230, 73, 3,255, 68, 65, 84, 65,
+144, 0, 0, 0,120, 28,194, 8, 48, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 35, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 35, 0,
+ 1, 0, 0, 0, 5, 0, 0, 0, 0, 0, 35, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 35, 0, 2, 0, 0, 0, 6, 0, 0, 0,
+ 0, 0, 35, 0, 3, 0, 0, 0, 7, 0, 0, 0, 0, 0, 35, 0, 4, 0, 0, 0, 5, 0, 0, 0, 0, 0, 35, 0, 4, 0, 0, 0,
+ 7, 0, 0, 0, 0, 0, 35, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 35, 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 35, 0,
+ 68, 65, 84, 65,120, 0, 0, 0, 88, 0,194, 8, 47, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
+ 4, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 2, 2, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 2, 71, 76, 79, 66, 24, 0, 0, 0,160,240,255,191,114, 0, 0, 0, 1, 0, 0, 0,
+ 96, 40,196, 8,136,251,196, 8, 1, 0, 0, 1, 0, 0, 0, 0,128, 32, 4, 0, 0, 0, 0, 0, 85, 83, 69, 82,168, 7, 0, 0,
+224,226,172, 8,108, 0, 0, 0, 1, 0, 0, 0, 33, 24, 0, 0, 63, 2, 0, 0, 5, 0, 0, 0, 47,116,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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 85,115,101,114,115,
+ 47,116,111,110, 47, 68,101,115,107,116,111,112, 47, 0, 45,112,111,119,101,114,112, 99, 47, 98,105,110, 47, 98,108,101,110,100,
+101,114, 46, 97,112,112, 47, 67,111,110,116,101,110,116,115, 47, 82,101,115,111,117,114, 99,101, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 0, 0, 0, 0,
+ 3, 0, 0, 0, 48, 52, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 8, 0, 0, 11, 0, 0, 0, 0, 0, 64, 0,
+ 5, 0, 2, 0, 0,104, 97,108,107, 98,111, 97,114,100, 46,116,116,102, 0, 55, 46, 53, 46, 48, 45,112,111,119,101,114,112, 99,
+ 47, 98,105,110, 47, 98,108,101,110,100,101,114, 46, 97,112,112, 47, 67,111,110,116,101,110,116,115, 47, 82,101,115,111,117,114,
+ 99,101,115, 47, 46, 98,102,111,110,116, 46,116,116,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,200, 32,197, 8,216, 40,197, 8, 32, 0, 0, 0, 5, 0, 5, 0, 1, 0, 0, 0, 0, 0, 0, 0,205,204, 76, 63,
+205,204, 76, 63,205,204, 76, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 30, 90,100,191,
+154,153,153, 62,102,102,102, 63, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 31,250,254, 62, 9, 0, 0, 63,156,153, 25, 63,
+ 0, 0, 0, 0,205,204, 76, 62,205,204, 76, 62,205,204, 76, 62, 0, 0,128, 63, 44,135, 22, 63, 32,133,235, 62,184,243,125, 62,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,195, 73, 76, 63, 42,135, 86, 63, 0, 0,128, 63, 0, 0, 0, 0, 1, 43,135, 61,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 16, 47, 93, 62, 58,180,200,190, 24, 47, 93,190, 0, 0, 0, 0, 14, 0, 0, 0,
+ 25, 0, 15, 0,120, 0, 0, 0, 60, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,224, 7, 0, 0,200, 32,197, 8,
+106, 0, 0, 0, 1, 0, 0, 0,216, 40,197, 8, 0, 0, 0, 0, 68,101,102, 97,117,108,116, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160,160,160,255,160,160,160,255,173,160,147,255,138,158,161,255,
+161,161,174,255,161,153,167,255,144,144,144,255,144,144,144,255,198,119,119,255,160,160,160,255, 0, 0, 0,255,255,255,255,255,
+210,210,210,255,218,218,218,255,127,127,127,255, 0, 0, 0,255,255,255,255,255, 1, 0, 0, 0,180,180,180,255, 0, 0, 0,255,
+255,255,255,255,195,195,195,255,255,255,255, 40,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 92, 92, 92,255, 0, 0, 0,255,
+255,136,255,255, 0, 0, 0, 40,255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,176,176, 48,255,
+230,150, 50,255, 75, 75, 75,255, 0, 50,150, 30,200,100,200, 60,255,138, 48,255, 34,221,221,255,200,200,200,255, 80,200,255, 80,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+115,115,115,255, 0, 0, 0,255,255,255,255,255,195,195,195,255,165,165,165,127,160,160,160,100,127,112,112,100, 0, 0, 0, 0,
+ 92, 92, 92,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 40,255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255,
+ 0, 0, 0,255,176,176, 48,255,230,150, 50,255, 75, 75, 75,255, 0, 50,150, 30,200,100,200, 60,255,138, 48,255, 34,221,221,255,
+200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 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,255, 0, 0, 0,255,255,255,255,255,182,182,182,255,165,165,165,127,160,160,160,100,
+127,112,112,100,160,160,208,255, 92, 92, 92,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 40,255,187,255,255,255,255,255,255,
+255,112,255,255,255,255,112,255, 0, 0, 0,255,176,176, 48,255,230,150, 50,255, 75, 75, 75,255, 0, 50,150, 30,200,100,200, 60,
+255,138, 48,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,120,120,255, 0, 0, 0,255,255,255,255,255,195,195,195,255,
+255,255,255,150,172,172,172,100,112,112,112,100, 96,192, 64,255, 94, 94, 94,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 40,
+255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,176,176, 48,255,230,150, 50,255, 75, 75, 75,255,
+ 0, 50,150, 30,200,100,200, 60,255,138, 48,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,153,153,153,255, 0, 0, 0,255,
+255,255,255,255,195,195,195,255,165,165,165,127,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 92, 92, 92,255, 0, 0, 0,255,
+255,136,255,255, 0, 0, 0, 40,255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,176,176, 48,255,
+230,150, 50,255, 75, 75, 75,255, 0, 50,150, 30,200,100,200, 60,255,138, 48,255, 34,221,221,255,200,200,200,255, 80,200,255, 80,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+153,153,153,255, 0, 0, 0,255,255,255,255,255,195,195,195,255,165,165,165,127,173,173,173,255,127,112,112,100, 0, 0, 0, 0,
+140,140,140,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 40,255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255,
+ 0, 0, 0,255,176,176, 48,255,230,150, 50,255, 75, 75, 75,255, 0, 50,150, 30,200,100,200, 60,255,138, 48,255, 34,221,221,255,
+200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,116,116,116,255, 0, 0, 0,255,255,255,255,255,182,182,182,255,165,165,165,127,172,172,172,255,
+ 84, 44, 31,100, 17, 27, 60,100, 94, 94, 94,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 40,255,187,255,255,255,255,255,255,
+255,112,255,255,255,255,112,255, 0, 0, 0,255,176,176, 48,255,230,150, 50,255, 75, 75, 75,255,166,166,166,255,200,100,200, 60,
+255,138, 48,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,116,116,116,255, 0, 0, 0,255,255,255,255,255,182,182,182,255,
+165,165,165,127,172,172,172,255, 84, 44, 31,100, 17, 27, 60,100, 94, 94, 94,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 40,
+255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,176,176, 48,255,230,150, 50,255, 75, 75, 75,255,
+ 0, 50,150, 30,200,100,200, 60,255,138, 48,255, 34,221,221,255,200,200,200,255, 80,200,255, 80,228,156,198,255,255,255,170,255,
+ 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,115,115,115,255, 0, 0, 0,255,
+255,255,255,255,195,195,195,255,165,165,165,127,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 92, 92, 92,255, 0, 0, 0,255,
+255,136,255,255, 0, 0, 0, 40,255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,176,176, 48,255,
+230,150, 50,255, 75, 75, 75,255, 0, 50,150, 30,200,100,200, 60,255,138, 48,255, 34,221,221,255,200,200,200,255, 80,200,255, 80,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 53, 53, 53,255, 0, 0, 0,255,255,255,255,255,195,195,195,255,165,165,165,127,160,160,160,100,127,112,112,100, 0, 0, 0, 0,
+ 92, 92, 92,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 40,255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255,
+ 0, 0, 0,255,176,176, 48,255,230,150, 50,255, 75, 75, 75,255, 0, 50,150, 40,200,100,200, 80,255,138, 48,255, 34,221,221,255,
+200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,110,110,110,255, 0, 0, 0,255,255,255,255,255,195,195,195,255,165,165,165,127,170,170,186,255,
+127,112,112,100, 0, 0, 0, 0, 92, 92, 92,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 40,255,187,255,255,255,255,255,255,
+255,112,255,255,255,255,112,255, 0, 0, 0,255,176,176, 48,255,230,150, 50,255, 75, 75, 75,255, 0, 50,150, 30,200,100,200, 60,
+255,138, 48,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,153,153,153,255, 0, 0, 0,255,255,255,255,255,195,195,195,255,
+165,165,165,127,143,143,143,255,198,119,119,255,255, 0, 0,255, 92, 92, 92,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 40,
+255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,176,176, 48,255,230,150, 50,255, 75, 75, 75,255,
+ 0, 50,150, 30,200,100,200, 60,255,138, 48,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 4, 0, 0,100, 0, 0,255, 0, 0,200,255,128, 0, 80,255, 95, 95, 0,255, 0,100, 50,255,153,153,153,255, 0, 0, 0,255,
+255,255,255,255,195,195,195,255,165,165,165,127,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 92, 92, 92,255, 0, 0, 0,255,
+255,136,255,255, 0, 0, 0, 40,255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,176,176, 48,255,
+230,150, 50,255, 75, 75, 75,255, 0, 50,150, 30,200,100,200, 60,255,138, 48,255, 34,221,221,255,200,200,200,255, 80,200,255, 80,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+153,153,153,255, 0, 0, 0,255,255,255,255,255,195,195,195,255,165,165,165,127,173,173,173,255,127,112,112,100, 0, 0, 0, 0,
+140,140,140,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 40,255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255,
+ 0, 0, 0,255,176,176, 48,255,230,150, 50,255, 75, 75, 75,255, 0, 50,150, 30,200,100,200, 60,255,138, 48,255, 34,221,221,255,
+200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 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,224, 7, 0, 0,216, 40,197, 8,106, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+200, 32,197, 8, 82,111,117,110,100,101,100, 0, 0,101,119, 32, 85,115,101,114, 32, 84,104,101,109,101, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,176,176,176,255,107,107,107,255,177,177,177,255,178,178,178,255,143,143,143,255,143,143,143,255,
+107,107,107,255,198,119,119,255,143,143,143,255, 0, 0, 0,255,255,255,255,255, 0, 0, 0,111, 0, 0, 33, 83,255,130, 0,255,
+255,255,255,255, 0, 0, 0,255, 2, 0, 0, 0,107,107,107,255, 0, 0, 0,255,255,255,255,255,107,107,107,255,175,175,175, 51,
+160,160,160,100,127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255,
+255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,
+200,100,200, 60, 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, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0,255,255,255,255,255,
+107,107,107,255, 0, 0, 0, 51,160,160,160,100,127,112,112,100, 0, 0, 0, 0,143,143,143,255, 0, 0, 0,255,217,217,217,255,
+ 0, 0, 0, 40,255,255,255,255,255,130, 0,255, 0, 0, 0,255,255,130, 0,255, 0, 0, 0,255,255,255,255,255,230,150, 50,255,
+ 0, 0, 0, 0,255,255,255, 10,255,130, 0, 60,255,138, 48,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255,
+ 0, 0, 0,255,255,255,255,255,107,107,107,255,165,165,165,150,160,160,160,100,127,112,112,100,255,130, 0,255, 88, 88, 88,255,
+ 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,
+144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,107,107,107,255, 0, 0, 0,255,255,255,255,255,107,107,107,255,107,107,107,150,107,107,107,100,143,143,143,100,
+ 96,192, 64,255, 94, 94, 94,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255,255,255,255,255,255,255,255,255,
+255,130, 0,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0,255,255,255,255,255,107,107,107,255,165,165,165,150,
+160,160,160,100,127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255,
+255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,
+200,100,200, 60, 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, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,158,158,158,255, 0, 0, 0,255,255,255,255,255,
+158,158,158,255,165,165,165,150,140,140,140,255,127,112,112,100, 0, 0, 0, 0,112,112, 96,255, 0, 0, 0,255,255,136,255,255,
+ 0, 0, 0, 0,255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255,
+ 0, 0, 0,255,255,255,255,255,107,107,107,255,165,165,165,150,107,107,107,255,178,178,178,100,255,130, 0,100, 94, 94, 94,255,
+ 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,
+144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0,143,143,143,255,200,100,200, 60, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,107,107,107,255, 0, 0, 0,255,255,255,255,255,143,143,143,255,165,165,165,150,107,107,107,255,178,178,178,100,
+255,130, 0,100, 94, 94, 94,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255,255,255,255,255,255,112,255,255,
+255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,228,156,198,255,255,255,170,255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0,255,255,255,255,255,107,107,107,255,165,165,165,150,
+160,160,160,100,127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255,
+255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,
+200,100,200, 60, 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, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 53, 53,255, 0, 0, 0,255,255,255,255,255,
+195,195,195,255,165,165,165,150,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255,
+ 0, 0, 0, 0,255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255,
+ 0, 0, 0,255,255,255,255,255,195,195,195,255,165,165,165,150,143,143,143,255,127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255,
+ 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,
+144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,153,153,153,255, 0, 0, 0,255,255,255,255,255,153,153,153,255,165,165,165,150,143,143,143,255,198,119,119,255,
+255, 0, 0,255, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255,255,255,255,255,255,112,255,255,
+255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 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, 0, 0, 0,100, 0, 0,255, 0, 0,200,255,
+128, 0, 80,255, 95, 95, 0,255, 0,100, 50,255,107,107,107,255, 0, 0, 0,255,255,255,255,255,107,107,107,255,165,165,165,150,
+160,160,160,100,127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255,
+255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,
+200,100,200, 60, 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, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,158,158,158,255, 0, 0, 0,255,255,255,255,255,
+158,158,158,255,165,165,165,150,140,140,140,255,127,112,112,100, 0, 0, 0, 0,112,112, 96,255, 0, 0, 0,255,255,136,255,255,
+ 0, 0, 0, 0,255,187,255,255,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 78, 65, 49,
+ 60,100, 0, 0, 16,170,197, 8, 0, 0, 0, 0, 1, 0, 0, 0, 83, 68, 78, 65, 78, 65, 77, 69,196, 5, 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, 99,117,114,118, 97,108, 0,116,121,112,
+101, 0, 97,100,114, 99,111,100,101, 0,116,111,116,101,108,101,109, 0, 42,100, 97,116, 97, 0, 42,119,101,105,103,104,116,115,
+ 0,110, 97,109,101, 91, 51, 50, 93, 0,118,103,114,111,117,112, 91, 51, 50, 93, 0,115,108,105,100,101,114,109,105,110, 0,115,
+108,105,100,101,114,109, 97,120, 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, 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, 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, 42,102,111,114,109, 97,116, 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,112,
+ 97,115,115,101,112, 97,114,116, 97,108,112,104, 97, 0,112, 97,100, 49, 0, 99,108,105,112,115,116, 97, 0, 99,108,105,112,101,
+110,100, 0,108,101,110,115, 0,111,114,116,104,111, 95,115, 99, 97,108,101, 0,100,114, 97,119,115,105,122,101, 0, 89, 70, 95,
+100,111,102,100,105,115,116, 0, 89, 70, 95, 97,112,101,114,116,117,114,101, 0, 89, 70, 95, 98,107,104,116,121,112,101, 0, 89,
+ 70, 95, 98,107,104, 98,105, 97,115, 0, 89, 70, 95, 98,107,104,114,111,116, 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,108, 97,115,116,117,115,101,100, 0, 97,110,105,109,115,112,101,101,100, 0,114,101,115,101,114,118,101,100, 49, 0,114,101,
+115,101,114,118,101,100, 50, 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,100,105,115,112,102, 97, 99, 0,119, 97,114,
+112,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,100,101,112,116,104, 0,114,101, 99, 97,108, 99, 0,108, 97,115,116,115,105,122,101, 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,109,103, 95, 72, 0,109,
+103, 95,108, 97, 99,117,110, 97,114,105,116,121, 0,109,103, 95,111, 99,116, 97,118,101,115, 0,109,103, 95,111,102,102,115,101,
+116, 0,109,103, 95,103, 97,105,110, 0,100,105,115,116, 95, 97,109,111,117,110,116, 0,110,115, 95,111,117,116,115, 99, 97,108,
+101, 0,118,110, 95,119, 49, 0,118,110, 95,119, 50, 0,118,110, 95,119, 51, 0,118,110, 95,119, 52, 0,118,110, 95,109,101,120,
+112, 0,118,110, 95,100,105,115,116,109, 0,118,110, 95, 99,111,108,116,121,112,101, 0,110,111,105,115,101,100,101,112,116,104,
+ 0,110,111,105,115,101,116,121,112,101, 0,110,111,105,115,101, 98, 97,115,105,115, 0,110,111,105,115,101, 98, 97,115,105,115,
+ 50, 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, 99,104,101, 99,107,101,114,100,105,115,116, 0,110, 97, 98,108, 97, 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,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,114, 97,121, 95,115, 97,109,112, 0,114, 97,121, 95,115, 97,109,
+112,121, 0,114, 97,121, 95,115, 97,109,112,122, 0,114, 97,121, 95,115, 97,109,112, 95,116,121,112,101, 0, 97,114,101, 97, 95,
+115,104, 97,112,101, 0, 97,114,101, 97, 95,115,105,122,101, 0, 97,114,101, 97, 95,115,105,122,101,121, 0, 97,114,101, 97, 95,
+115,105,122,101,122, 0,116,101,120, 97, 99,116, 0,115,104, 97,100,104, 97,108,111,115,116,101,112, 0, 89, 70, 95,110,117,109,
+112,104,111,116,111,110,115, 0, 89, 70, 95,110,117,109,115,101, 97,114, 99,104, 0, 89, 70, 95,112,104,100,101,112,116,104, 0,
+ 89, 70, 95,117,115,101,113,109, 99, 0, 89, 70, 95, 98,117,102,115,105,122,101, 0, 89, 70, 95,112, 97,100, 0, 89, 70, 95, 99,
+ 97,117,115,116,105, 99, 98,108,117,114, 0, 89, 70, 95,108,116,114, 97,100,105,117,115, 0, 89, 70, 95,103,108,111,119,105,110,
+116, 0, 89, 70, 95,103,108,111,119,111,102,115, 0, 89, 70, 95,112, 97,100, 51, 0, 89, 70, 95,103,108,111,119,116,121,112,101,
+ 0, 89, 70, 95,112, 97,100, 50, 0, 42,109,116,101,120, 91, 49, 48, 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,114, 97,121, 95,
+109,105,114,114,111,114, 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,
+116,114, 97,110,115,108,117, 99,101,110, 99,121, 0,102,114,101,115,110,101,108, 95,109,105,114, 0,102,114,101,115,110,101,108,
+ 95,109,105,114, 95,105, 0,102,114,101,115,110,101,108, 95,116,114, 97, 0,102,114,101,115,110,101,108, 95,116,114, 97, 95,105,
+ 0,102,105,108,116,101,114, 0,114, 97,121, 95,100,101,112,116,104, 0,114, 97,121, 95,100,101,112,116,104, 95,116,114, 97, 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,115,116,114, 97,110,100, 95,115,116, 97, 0,115,116,
+114, 97,110,100, 95,101,110,100, 0,115,116,114, 97,110,100, 95,101, 97,115,101, 0,114,103, 98,115,101,108, 0,112,114, 95,116,
+121,112,101, 0,112,114, 95, 98, 97, 99,107, 0,112,114, 95,108, 97,109,112, 0,115,101,112,116,101,120, 0,112, 97,100, 52, 0,
+112, 97,100, 53, 0,100,105,102,102, 95,115,104, 97,100,101,114, 0,115,112,101, 99, 95,115,104, 97,100,101,114, 0,114,111,117,
+103,104,110,101,115,115, 0,114,101,102,114, 97, 99, 0,112, 97,114, 97,109, 91, 52, 93, 0,114,109,115, 0,100, 97,114,107,110,
+101,115,115, 0, 42,114, 97,109,112, 95, 99,111,108, 0, 42,114, 97,109,112, 95,115,112,101, 99, 0,114, 97,109,112,105,110, 95,
+ 99,111,108, 0,114, 97,109,112,105,110, 95,115,112,101, 99, 0,114, 97,109,112, 98,108,101,110,100, 95, 99,111,108, 0,114, 97,
+109,112, 98,108,101,110,100, 95,115,112,101, 99, 0,114, 97,109,112, 95,115,104,111,119, 0,112, 97,100, 51, 0,114, 97,109,112,
+102, 97, 99, 95, 99,111,108, 0,114, 97,109,112,102, 97, 99, 95,115,112,101, 99, 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,112, 97,100, 50, 0, 89, 70, 95, 97,114, 0, 89, 70, 95, 97,103, 0, 89, 70, 95, 97, 98, 0, 89, 70, 95,100,115, 99, 97,108,
+101, 0, 89, 70, 95,100,112,119,114, 0, 89, 70, 95,100,115,109,112, 0, 89, 70, 95,112,114,101,115,101,116, 0, 89, 70, 95,100,
+106,105,116, 0,110, 97,109,101, 91, 50, 53, 54, 93, 0,115, 99, 97,108,101, 0, 42, 98, 98, 0,105, 49, 0,106, 49, 0,107, 49,
+ 0,105, 50, 0,106, 50, 0,107, 50, 0,115,101,108, 99,111,108, 49, 0,115,101,108, 99,111,108, 50, 0,113,117, 97,116, 91, 52,
+ 93, 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, 42,109, 97,116,
+ 0, 42,105,109, 97,116, 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,119,101,105,103,104,116, 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,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, 99,104, 97,114,105,100,120, 0,107,101,114,110, 0,104, 0,110,117,114,
+ 98, 0, 42, 98,101,118,111, 98,106, 0, 42,116, 97,112,101,114,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,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,119,111,114,100,115,112, 97, 99,
+101, 0,117,108,112,111,115, 0,117,108,104,101,105,103,104,116, 0,120,111,102, 0,121,111,102, 0,108,105,110,101,119,105,100,
+116,104, 0, 42,115,116,114, 0,102, 97,109,105,108,121, 91, 50, 52, 93, 0, 42,118,102,111,110,116, 0, 42,118,102,111,110,116,
+ 98, 0, 42,118,102,111,110,116,105, 0, 42,118,102,111,110,116, 98,105, 0,115,101,112, 99,104, 97,114, 0,116,111,116, 98,111,
+120, 0, 97, 99,116, 98,111,120, 0, 42,116, 98, 0,115,101,108,115,116, 97,114,116, 0,115,101,108,101,110,100, 0, 42,115,116,
+114,105,110,102,111, 0, 99,117,114,105,110,102,111, 0, 42,111, 98, 0,110, 97,109,101, 91, 49, 50, 56, 93, 0,109, 97,120,114,
+ 99,116, 0,116,111,116,114, 99,116, 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,114,116, 0, 98,105,116,109, 97,115,107, 0, 42,100,114,105,118,101,114, 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,117,110,119,114, 97,
+112, 0,101,102,102,101, 99,116, 0, 42,109,102, 97, 99,101, 0, 42,116,102, 97, 99,101, 0, 42,100,102, 97, 99,101, 0, 42,109,
+118,101,114,116, 0, 42,109,101,100,103,101, 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,
+101,100,103,101, 0,116,111,116,102, 97, 99,101, 0, 99,117, 98,101,109, 97,112,115,105,122,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,115,117, 98,115,117,114,102,116,121,112,101, 0,118,
+ 49, 0,118, 50, 0,118, 51, 0,118, 52, 0,101,100, 99,111,100,101, 0, 99,114,101, 97,115,101, 0,100,101,102, 95,110,114, 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,
+ 42,101,114,114,111,114, 0,109,111,100,105,102,105,101,114, 0,115,117, 98,100,105,118, 84,121,112,101, 0,108,101,118,101,108,
+115, 0,114,101,110,100,101,114, 76,101,118,101,108,115, 0, 42,101,109, 67, 97, 99,104,101, 0, 42,109, 67, 97, 99,104,101, 0,
+115,116, 97,114,116, 0,108,101,110,103,116,104, 0,114, 97,110,100,111,109,105,122,101, 0,115,101,101,100, 0, 97,120,105,115,
+ 0,116,111,108,101,114, 97,110, 99,101, 0,112,101,114, 99,101,110,116, 0,102, 97, 99,101, 67,111,117,110,116, 0,115,116, 97,
+114,116,120, 0,115,116, 97,114,116,121, 0,104,101,105,103,104,116, 0,110, 97,114,114,111,119, 0,115,112,101,101,100, 0,100,
+ 97,109,112, 0,116,105,109,101,111,102,102,115, 0,108,105,102,101,116,105,109,101, 0,100,101,102,111,114,109,102,108, 97,103,
+ 0,112, 97,114,101,110,116,105,110,118, 91, 52, 93, 91, 52, 93, 0, 99,101,110,116, 91, 51, 93, 0,102, 97,108,108,111,102,102,
+ 0, 42,105,110,100,101,120, 97,114, 0,116,111,116,105,110,100,101,120, 0,102,111,114, 99,101, 0,111,112,101,114, 97,116,105,
+111,110, 0,112,110,116,115,119, 0,111,112,110,116,115,117, 0,111,112,110,116,115,118, 0,111,112,110,116,115,119, 0,116,121,
+112,101,117, 0,116,121,112,101,118, 0,116,121,112,101,119, 0,102,117, 0,102,118, 0,102,119, 0,100,117, 0,100,118, 0,100,
+119, 0, 42,100,101,102, 0,118,101, 99, 91, 56, 93, 91, 51, 93, 0,100,118,101, 99, 91, 51, 93, 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,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, 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,109,111,100,105,102,105,101,114,115, 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,100,113,117, 97,116,
+ 91, 52, 93, 0,111, 98,109, 97,116, 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,110,108, 97,102,108,
+ 97,103, 0,112,114,111,116,101, 99,116,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,115,111,102,116,116,105,109,101, 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,115,111,102,116,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, 99,111,110,115,116,114, 97,105,110,116,115, 0,110,108, 97,115,116,114,105,112,
+115, 0,104,111,111,107,115, 0, 42,112,100, 0, 42,115,111,102,116, 0, 42,108,105,102,101, 0,108, 98,117,102, 0,112,111,114,
+116, 0,102,108,117,105,100,115,105,109, 70,108, 97,103, 0,115,104, 97,112,101,110,114, 0,115,104, 97,112,101,102,108, 97,103,
+ 0, 42,102,108,117,105,100,115,105,109, 83,101,116,116,105,110,103,115, 0, 42,100,101,114,105,118,101,100, 68,101,102,111,114,
+109, 0, 42,100,101,114,105,118,101,100, 70,105,110, 97,108, 0,109, 97,116, 91, 52, 93, 91, 52, 93, 0, 99,117,114,105,110,100,
+101,120, 0, 97, 99,116,105,118,101, 0,100,101,102,108,101, 99,116, 0,102,111,114, 99,101,102,105,101,108,100, 0,112,100,101,
+102, 95,100, 97,109,112, 0,112,100,101,102, 95,114,100, 97,109,112, 0,112,100,101,102, 95,112,101,114,109, 0,102, 95,115,116,
+114,101,110,103,116,104, 0,102, 95,112,111,119,101,114, 0,109, 97,120,100,105,115,116, 0,112,100,101,102, 95,115, 98,100, 97,
+109,112, 0,112,100,101,102, 95,115, 98,105,102,116, 0,112,100,101,102, 95,115, 98,111,102,116, 0,116,111,116,112,111,105,110,
+116, 0,116,111,116,115,112,114,105,110,103, 0, 42, 98,112,111,105,110,116, 0, 42, 98,115,112,114,105,110,103, 0,110,111,100,
+101,109, 97,115,115, 0,103,114, 97,118, 0,109,101,100,105, 97,102,114,105, 99,116, 0,114,107,108,105,109,105,116, 0,112,104,
+121,115,105, 99,115, 95,115,112,101,101,100, 0,103,111, 97,108,115,112,114,105,110,103, 0,103,111, 97,108,102,114,105, 99,116,
+ 0,109,105,110,103,111, 97,108, 0,109, 97,120,103,111, 97,108, 0,100,101,102,103,111, 97,108, 0,118,101,114,116,103,114,111,
+117,112, 0,105,110,115,112,114,105,110,103, 0,105,110,102,114,105, 99,116, 0,101,102,114, 97, 0,105,110,116,101,114,118, 97,
+108, 0, 42, 42,107,101,121,115, 0,116,111,116,112,111,105,110,116,107,101,121, 0,115,104,111,119, 95, 97,100,118, 97,110, 99,
+101,100,111,112,116,105,111,110,115, 0,114,101,115,111,108,117,116,105,111,110,120,121,122, 0,112,114,101,118,105,101,119,114,
+101,115,120,121,122, 0,114,101, 97,108,115,105,122,101, 0,103,117,105, 68,105,115,112,108, 97,121, 77,111,100,101, 0,114,101,
+110,100,101,114, 68,105,115,112,108, 97,121, 77,111,100,101, 0,118,105,115, 99,111,115,105,116,121, 86, 97,108,117,101, 0,118,
+105,115, 99,111,115,105,116,121, 77,111,100,101, 0,118,105,115, 99,111,115,105,116,121, 69,120,112,111,110,101,110,116, 0,103,
+114, 97,118,120, 0,103,114, 97,118,121, 0,103,114, 97,118,122, 0, 97,110,105,109, 83,116, 97,114,116, 0, 97,110,105,109, 69,
+110,100, 0,103,115,116, 97,114, 0,109, 97,120, 82,101,102,105,110,101, 0,105,110,105, 86,101,108,120, 0,105,110,105, 86,101,
+108,121, 0,105,110,105, 86,101,108,122, 0, 42,111,114,103, 77,101,115,104, 0, 42,109,101,115,104, 83,117,114,102, 97, 99,101,
+ 0, 42,109,101,115,104, 66, 66, 0,115,117,114,102,100, 97,116, 97, 80, 97,116,104, 91, 50, 52, 48, 93, 0, 98, 98, 83,116, 97,
+114,116, 91, 51, 93, 0, 98, 98, 83,105,122,101, 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,101,120,112, 0,114, 97,110,103,101, 0,
+108,105,110,102, 97, 99, 0,108,111,103,102, 97, 99, 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,112,104,121,115,105, 99,115, 69,110,103,105,110,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, 97,111,100,105,115,116,
+ 0, 97,111,100,105,115,116,102, 97, 99, 0, 97,111,101,110,101,114,103,121, 0, 97,111, 98,105, 97,115, 0, 97,111,109,111,100,
+101, 0, 97,111,115, 97,109,112, 0, 97,111,109,105,120, 0, 97,111, 99,111,108,111,114, 0, 42, 97,111,115,112,104,101,114,101,
+ 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,101,108, 99,111,108, 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, 97,
+118,105, 99,111,100,101, 99,110, 97,109,101, 91, 49, 50, 56, 93, 0, 42, 99,100, 80, 97,114,109,115, 0, 42,112, 97,100, 0, 99,
+100, 83,105,122,101, 0,113,116, 99,111,100,101, 99,110, 97,109,101, 91, 49, 50, 56, 93, 0,109,105,120,114, 97,116,101, 0,109,
+ 97,105,110, 0,112, 97,100, 91, 51, 93, 0, 42, 97,118,105, 99,111,100,101, 99,100, 97,116, 97, 0, 42,113,116, 99,111,100,101,
+ 99,100, 97,116, 97, 0, 99,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, 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,100,105,109,101,110,115,105,111,
+110,115,112,114,101,115,101,116, 0,102,105,108,116,101,114,116,121,112,101, 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,114,101,110,100,101,
+114,101,114, 0,111, 99,114,101,115, 0,114,112, 97,100, 91, 50, 93, 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,103, 97,117,115,115, 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,112,111,115,116,104,117,101, 0,112,111,115,116,115, 97,
+116, 0,100,105,116,104,101,114, 95,105,110,116,101,110,115,105,116,121, 0,122,109,105,110, 0,102,111, 99,117,115, 0,122,103,
+ 97,109,109, 97, 0,122,115,105,103,109, 97, 0,122, 98,108,117,114, 0, 71, 73,113,117, 97,108,105,116,121, 0, 71, 73, 99, 97,
+ 99,104,101, 0, 71, 73,109,101,116,104,111,100, 0, 71, 73,112,104,111,116,111,110,115, 0, 71, 73,100,105,114,101, 99,116, 0,
+ 89, 70, 95, 65, 65, 0, 89, 70,101,120,112,111,114,116,120,109,108, 0, 89, 70, 95,110,111, 98,117,109,112, 0, 89, 70, 95, 99,
+108, 97,109,112,114,103, 98, 0,121,102,112, 97,100, 49, 0, 71, 73,100,101,112,116,104, 0, 71, 73, 99, 97,117,115,100,101,112,
+116,104, 0, 71, 73,112,105,120,101,108,115,112,101,114,115, 97,109,112,108,101, 0, 71, 73,112,104,111,116,111,110, 99,111,117,
+110,116, 0, 71, 73,109,105,120,112,104,111,116,111,110,115, 0, 71, 73,112,104,111,116,111,110,114, 97,100,105,117,115, 0, 89,
+ 70, 95,110,117,109,112,114,111, 99,115, 0, 89, 70, 95,114, 97,121,100,101,112,116,104, 0, 89, 70, 95, 65, 65,112, 97,115,115,
+101,115, 0, 89, 70, 95, 65, 65,115, 97,109,112,108,101,115, 0, 71, 73,115,104, 97,100,111,119,113,117, 97,108,105,116,121, 0,
+ 71, 73,114,101,102,105,110,101,109,101,110,116, 0, 71, 73,112,111,119,101,114, 0, 71, 73,105,110,100,105,114,112,111,119,101,
+114, 0, 89, 70, 95,103, 97,109,109, 97, 0, 89, 70, 95,101,120,112,111,115,117,114,101, 0, 89, 70, 95,114, 97,121, 98,105, 97,
+115, 0, 89, 70, 95, 65, 65,112,105,120,101,108,115,105,122,101, 0, 89, 70, 95, 65, 65,116,104,114,101,115,104,111,108,100, 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,102,114, 97,109,101, 0,110, 97,109,101, 91, 54, 52, 93, 0, 99,111,114,110,101,114,116,121,112,
+101, 0,101,100,105,116, 98,117,116,102,108, 97,103, 0,100,101,103,114, 0,115,116,101,112, 0,116,117,114,110, 0,101,120,116,
+114, 95,111,102,102,115, 0,100,111,117, 98,108,105,109,105,116, 0,115,101,103,109,101,110,116,115, 0,114,105,110,103,115, 0,
+118,101,114,116,105, 99,101,115, 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,116,119, 99,101,110,
+116, 91, 51, 93, 0,116,119,109,105,110, 91, 51, 93, 0,116,119,109, 97,120, 91, 51, 93, 0,115,101,108,101, 99,116,109,111,100,
+101, 0,112,114,111,112,111,114,116,105,111,110, 97,108, 0,112,114,111,112, 95,109,111,100,101, 0,101,100,105,116, 98,117,116,
+115,105,122,101, 0, 42,101,100, 0, 42,114, 97,100,105,111, 0,102,114, 97,109,105,110,103, 0, 42,116,111,111,108,115,101,116,
+116,105,110,103,115, 0, 97,117,100,105,111, 0,109, 97,114,107,101,114,115, 0, 42,116,104,101, 68, 97,103, 0,100, 97,103,105,
+115,118, 97,108,105,100, 0,100, 97,103,102,108, 97,103,115, 0,100,105,114,116,121, 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, 98,108,111, 99,107,115, 99,
+ 97,108,101, 0, 42, 97,114,101, 97, 0, 98,108,111, 99,107,104, 97,110,100,108,101,114, 91, 56, 93, 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,119,105,110,109, 97,116, 49, 91, 52, 93, 91, 52, 93, 0,
+118,105,101,119,109, 97,116, 49, 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,103,114,105,100,118,105,101,119, 0,112,105,120,115,105,122,101, 0,110,101, 97,114, 0,102, 97,114, 0,103,
+114,105,100,108,105,110,101,115, 0,118,105,101,119, 98,117,116, 0,103,114,105,100,102,108, 97,103, 0,109,111,100,101,115,101,
+108,101, 99,116, 0,109,101,110,117,110,114, 0,116,101,120,110,114, 0,116,119,116,121,112,101, 0,116,119,109,111,100,101, 0,
+116,119,102,108, 97,103, 0,116,119,100,114, 97,119,102,108, 97,103, 0,116,119,109, 97,116, 91, 52, 93, 91, 52, 93, 0, 99,108,
+105,112, 91, 52, 93, 91, 52, 93, 0, 42, 99,108,105,112, 98, 98, 0, 97,102,116,101,114,100,114, 97,119, 0,122, 98,117,102, 0,
+120,114, 97,121, 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,111,108,100,119,105,110,120, 0,111,108,100,119,
+105,110,121, 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, 97,
+ 99,116,110, 97,109,101, 91, 51, 50, 93, 0, 99,111,110,115,116,110, 97,109,101, 91, 51, 50, 93, 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,108,111, 99,107, 0,109,101,100,105, 97,110, 91, 51,
+ 93, 0, 99,117,114,115,101,110,115, 0, 99,117,114, 97, 99,116, 0, 97,108,105,103,110, 0,116, 97, 98,111, 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,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,114,101, 95, 97,108,105,103,110, 0,111,108,100,107,101,121,112,114,101,115,115,
+ 0,116, 97, 98, 91, 55, 93, 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,116,114,101,101, 0, 42,116,114,101,101,115,116,
+111,114,101, 0,111,117,116,108,105,110,101,118,105,115, 0,115,116,111,114,101,102,108, 97,103, 0,100,101,112,115, 95,102,108,
+ 97,103,115, 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,115,104,111,119,108,105,110,101,110,114,115, 0,116, 97, 98,110,117,109, 98,101,114, 0, 99,117,114,114,116, 97, 98, 95,
+115,101,116, 0,115,104,111,119,115,121,110,116, 97,120, 0,117,110,117,115,101,100, 95,112, 97,100,100, 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,115, 99,114,105,112,116,
+ 0,114,101,100,114, 97,119,115, 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,109,120, 0,109,121, 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,111,117,
+116,108,105,110,101, 91, 52, 93, 0,110,101,117,116,114, 97,108, 91, 52, 93, 0, 97, 99,116,105,111,110, 91, 52, 93, 0,115,101,
+116,116,105,110,103, 91, 52, 93, 0,115,101,116,116,105,110,103, 49, 91, 52, 93, 0,115,101,116,116,105,110,103, 50, 91, 52, 93,
+ 0,110,117,109, 91, 52, 93, 0,116,101,120,116,102,105,101,108,100, 91, 52, 93, 0,116,101,120,116,102,105,101,108,100, 95,104,
+105, 91, 52, 93, 0,112,111,112,117,112, 91, 52, 93, 0,116,101,120,116, 91, 52, 93, 0,116,101,120,116, 95,104,105, 91, 52, 93,
+ 0,109,101,110,117, 95, 98, 97, 99,107, 91, 52, 93, 0,109,101,110,117, 95,105,116,101,109, 91, 52, 93, 0,109,101,110,117, 95,
+104,105,108,105,116,101, 91, 52, 93, 0,109,101,110,117, 95,116,101,120,116, 91, 52, 93, 0,109,101,110,117, 95,116,101,120,116,
+ 95,104,105, 91, 52, 93, 0, 98,117,116, 95,100,114, 97,119,116,121,112,101, 0,112, 97,100, 49, 91, 51, 93, 0, 98, 97, 99,107,
+ 91, 52, 93, 0,104,101, 97,100,101,114, 91, 52, 93, 0,112, 97,110,101,108, 91, 52, 93, 0,115,104, 97,100,101, 49, 91, 52, 93,
+ 0,115,104, 97,100,101, 50, 91, 52, 93, 0,104,105,108,105,116,101, 91, 52, 93, 0,103,114,105,100, 91, 52, 93, 0,119,105,114,
+101, 91, 52, 93, 0,115,101,108,101, 99,116, 91, 52, 93, 0,108, 97,109,112, 91, 52, 93, 0, 97, 99,116,105,118,101, 91, 52, 93,
+ 0,116,114, 97,110,115,102,111,114,109, 91, 52, 93, 0,118,101,114,116,101,120, 91, 52, 93, 0,118,101,114,116,101,120, 95,115,
+101,108,101, 99,116, 91, 52, 93, 0,101,100,103,101, 91, 52, 93, 0,101,100,103,101, 95,115,101,108,101, 99,116, 91, 52, 93, 0,
+101,100,103,101, 95,115,101, 97,109, 91, 52, 93, 0,101,100,103,101, 95,102, 97, 99,101,115,101,108, 91, 52, 93, 0,102, 97, 99,
+101, 91, 52, 93, 0,102, 97, 99,101, 95,115,101,108,101, 99,116, 91, 52, 93, 0,102, 97, 99,101, 95,100,111,116, 91, 52, 93, 0,
+110,111,114,109, 97,108, 91, 52, 93, 0, 98,111,110,101, 95,115,111,108,105,100, 91, 52, 93, 0, 98,111,110,101, 95,112,111,115,
+101, 91, 52, 93, 0,115,116,114,105,112, 91, 52, 93, 0,115,116,114,105,112, 95,115,101,108,101, 99,116, 91, 52, 93, 0,118,101,
+114,116,101,120, 95,115,105,122,101, 0,102, 97, 99,101,100,111,116, 95,115,105,122,101, 0, 98,112, 97,100, 91, 50, 93, 0,115,
+121,110,116, 97,120,108, 91, 52, 93, 0,115,121,110,116, 97,120,110, 91, 52, 93, 0,115,121,110,116, 97,120, 98, 91, 52, 93, 0,
+115,121,110,116, 97,120,118, 91, 52, 93, 0,115,121,110,116, 97,120, 99, 91, 52, 93, 0,116,117,105, 0,116, 98,117,116,115, 0,
+116,118, 51,100, 0,116,102,105,108,101, 0,116,105,112,111, 0,116,105,110,102,111, 0,116,115,110,100, 0,116, 97, 99,116, 0,
+116,110,108, 97, 0,116,115,101,113, 0,116,105,109, 97, 0,116,105,109, 97,115,101,108, 0,116,101,120,116, 0,116,111,111,112,
+115, 0,116,116,105,109,101, 0,115,112,101, 99, 91, 52, 93, 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, 49, 54, 48, 93, 0,102,111,110,116,100,105,114, 91, 49, 54, 48, 93, 0,114,101,110,100,101,
+114,100,105,114, 91, 49, 54, 48, 93, 0,116,101,120,116,117,100,105,114, 91, 49, 54, 48, 93, 0,112,108,117,103,116,101,120,100,
+105,114, 91, 49, 54, 48, 93, 0,112,108,117,103,115,101,113,100,105,114, 91, 49, 54, 48, 93, 0,112,121,116,104,111,110,100,105,
+114, 91, 49, 54, 48, 93, 0,115,111,117,110,100,100,105,114, 91, 49, 54, 48, 93, 0,121,102,101,120,112,111,114,116,100,105,114,
+ 91, 49, 54, 48, 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,119,104,101,101,108,108,105,110,101,115, 99,114,111,108,108, 0,117,105,102,108, 97,103, 0,108, 97,110,103,117, 97,103,
+101, 0,117,115,101,114,112,114,101,102, 0,118,105,101,119,122,111,111,109, 0, 99,111,110,115,111,108,101, 95, 98,117,102,102,
+101,114, 0, 99,111,110,115,111,108,101, 95,111,117,116, 0,109,105,120, 98,117,102,115,105,122,101, 0,102,111,110,116,115,105,
+122,101, 0,101,110, 99,111,100,105,110,103, 0,116,114, 97,110,115,111,112,116,115, 0,109,101,110,117,116,104,114,101,115,104,
+111,108,100, 49, 0,109,101,110,117,116,104,114,101,115,104,111,108,100, 50, 0,102,111,110,116,110, 97,109,101, 91, 50, 53, 54,
+ 93, 0,116,104,101,109,101,115, 0,117,110,100,111,115,116,101,112,115, 0, 99,117,114,115,115,105,122,101, 0,116, 98, 95,108,
+101,102,116,109,111,117,115,101, 0,116, 98, 95,114,105,103,104,116,109,111,117,115,101, 0,108,105,103,104,116, 91, 51, 93, 0,
+116,119, 95,104,111,116,115,112,111,116, 0,116,119, 95,102,108, 97,103, 0,116,119, 95,104, 97,110,100,108,101,115,105,122,101,
+ 0,116,119, 95,115,105,122,101, 0,116,101,120,116,105,109,101,111,117,116, 0,116,101,120, 99,111,108,108,101, 99,116,114, 97,
+116,101, 0,111, 98, 99,101,110,116,101,114, 95,100,105, 97, 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,101,110,100,120, 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,104, 97,110,100,108,101,114, 91, 56, 93, 0, 42,110,101,119,118, 0,118,101,
+ 99, 0, 42,118, 49, 0, 42,118, 50, 0,112, 97,110,101,108,110, 97,109,101, 91, 54, 52, 93, 0,116, 97, 98,110, 97,109,101, 91,
+ 54, 52, 93, 0,111,102,115,120, 0,111,102,115,121, 0, 99,111,110,116,114,111,108, 0,111,108,100, 95,111,102,115,120, 0,111,
+108,100, 95,111,102,115,121, 0,115,111,114,116, 99,111,117,110,116,101,114, 0, 42,112, 97,110,101,108,116, 97, 98, 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,112, 97,110,101,108,115, 0, 42, 99,117,114,115, 99,114,101,101,110, 0,
+ 42, 99,117,114,115, 99,101,110,101, 0,100,105,115,112,108, 97,121,109,111,100,101, 0,102,105,108,101,102,108, 97,103,115, 0,
+103,108,111, 98, 97,108,102, 0,110, 97,109,101, 91, 56, 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,111,114,120, 0,111,114,121, 0, 42,110,101,119,115,
+101,113, 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,111,117,110,100, 0,108,101,118,101,108, 0,112, 97,110, 0, 99,117,114,112,111,115, 0,115,116,114,111,
+ 98,101, 0, 42,101,102,102,101, 99,116,100, 97,116, 97, 0, 42,111,108,100, 98, 97,115,101,112, 0, 42,112, 97,114,115,101,113,
+ 0, 42,115,101,113, 98, 97,115,101,112, 0,109,101,116, 97,115,116, 97, 99,107, 0,101,100,103,101, 87,105,100,116,104, 0, 97,
+110,103,108,101, 0,102,111,114,119, 97,114,100, 0,119,105,112,101,116,121,112,101, 0,102, 77,105,110,105, 0,102, 67,108, 97,
+109,112, 0,102, 66,111,111,115,116, 0,100, 68,105,115,116, 0,100, 81,117, 97,108,105,116,121, 0, 98, 78,111, 67,111,109,112,
+ 0, 98,117,116,116,121,112,101, 0,117,115,101,114,106,105,116, 0,115,116, 97, 0,101,110,100, 0,116,111,116,112, 97,114,116,
+ 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,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,111,109, 97,
+116, 0,116,105,109,101,116,101,120, 0,115,112,101,101,100,116,101,120, 0,102,108, 97,103, 50, 0,102,108, 97,103, 50,110,101,
+103, 0,118,101,114,116,103,114,111,117,112, 95,118, 0,118,103,114,111,117,112,110, 97,109,101, 91, 51, 50, 93, 0,118,103,114,
+111,117,112,110, 97,109,101, 95,118, 91, 51, 50, 93, 0, 42,107,101,121,115, 0,109,105,110,102, 97, 99, 0,117,115,101,100, 0,
+ 42,105,100, 0,117,115,101,100,101,108,101,109, 0,100,120, 0,100,121, 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,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, 97,120,105,
+115,102, 0, 98,117,116,116,111,110, 0, 98,117,116,116,111,110,102, 0,104, 97,116, 0,104, 97,116,102, 0,112,114,101, 99,105,
+115,105,111,110, 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,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,114,101,115,101,114,118,101,100, 51, 0,115,110,100,110,114, 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,102, 97, 99, 0,118,105,115,105,102, 97, 99, 0,115,108,
+111,119, 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,115,116,114,101, 97,109,
+ 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,115,116,114,101, 97,109,108,101,110, 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, 49, 48, 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, 98,111,110,101, 95,109, 97,116, 91, 51, 93, 91, 51, 93,
+ 0, 97,114,109, 95,104,101, 97,100, 91, 51, 93, 0, 97,114,109, 95,116, 97,105,108, 91, 51, 93, 0, 97,114,109, 95,109, 97,116,
+ 91, 52, 93, 91, 52, 93, 0,120,119,105,100,116,104, 0,122,119,105,100,116,104, 0,101, 97,115,101, 49, 0,101, 97,115,101, 50,
+ 0,114, 97,100, 95,104,101, 97,100, 0,114, 97,100, 95,116, 97,105,108, 0, 98,111,110,101, 99,108, 97,115,115, 0, 98,111,110,
+101, 98, 97,115,101, 0, 99,104, 97,105,110, 98, 97,115,101, 0,103,104,111,115,116,101,112, 0,103,104,111,115,116,115,105,122,
+101, 0, 99,111,110,115,116,102,108, 97,103, 0,105,107,102,108, 97,103, 0, 42, 98,111,110,101, 0, 42, 99,104,105,108,100, 0,
+105,107,116,114,101,101, 0, 42, 98, 95, 98,111,110,101, 95,109, 97,116,115, 0, 99,104, 97,110, 95,109, 97,116, 91, 52, 93, 91,
+ 52, 93, 0,112,111,115,101, 95,109, 97,116, 91, 52, 93, 91, 52, 93, 0,112,111,115,101, 95,104,101, 97,100, 91, 51, 93, 0,112,
+111,115,101, 95,116, 97,105,108, 91, 51, 93, 0,108,105,109,105,116,109,105,110, 91, 51, 93, 0,108,105,109,105,116,109, 97,120,
+ 91, 51, 93, 0,115,116,105,102,102,110,101,115,115, 91, 51, 93, 0,105,107,115,116,114,101,116, 99,104, 0, 99,104, 97,110, 98,
+ 97,115,101, 0,115,116,114,105,100,101, 95,111,102,102,115,101,116, 91, 51, 93, 0, 97, 99,116,110,114, 0,116,105,109,101,115,
+108,105,100,101, 0,110, 97,109,101, 91, 51, 48, 93, 0,101,110,102,111,114, 99,101, 0, 42,116, 97,114, 0,105,116,101,114, 97,
+116,105,111,110,115, 0,114,111,111,116, 98,111,110,101, 0,115,117, 98,116, 97,114,103,101,116, 91, 51, 50, 93, 0,111,114,105,
+101,110,116,119,101,105,103,104,116, 0,103,114, 97, 98,116, 97,114,103,101,116, 91, 51, 93, 0,109,105,110,109, 97,120,102,108,
+ 97,103, 0,115,116,105, 99,107,121, 0,115,116,117, 99,107, 0, 99, 97, 99,104,101, 91, 51, 93, 0,108,111, 99, 97,108, 0,108,
+111, 99,107,102,108, 97,103, 0,102,111,108,108,111,119,102,108, 97,103, 0,111,102,102,115,101,116, 91, 51, 93, 0,122,109, 97,
+120, 0,118,111,108,109,111,100,101, 0,112,108, 97,110,101, 0,111,114,103,108,101,110,103,116,104, 0, 98,117,108,103,101, 0,
+115,116,114,105,100,101, 95, 97,120,105,115, 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,115,116,114,105,100,101, 99,104, 97,110,
+110,101,108, 91, 51, 50, 93, 0, 84, 89, 80, 69,219, 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, 66,111,117,110,
+100, 66,111,120, 0, 77,101,116, 97, 66, 97,108,108, 0, 66,101,122, 84,114,105,112,108,101, 0, 66, 80,111,105,110,116, 0, 78,
+117,114, 98, 0, 67,104, 97,114, 73,110,102,111, 0, 84,101,120,116, 66,111,120, 0, 67,117,114,118,101, 0, 80, 97,116,104, 0,
+ 73,112,111, 68,114,105,118,101,114, 0, 73,112,111, 67,117,114,118,101, 0, 84, 70, 97, 99,101, 0, 77,101,115,104, 0, 77, 70,
+ 97, 99,101, 0, 77, 86,101,114,116, 0, 77, 69,100,103,101, 0, 77, 68,101,102,111,114,109, 86,101,114,116, 0, 77, 67,111,108,
+ 0, 77, 83,116,105, 99,107,121, 0, 79, 99, 73,110,102,111, 0, 77, 68,101,102,111,114,109, 87,101,105,103,104,116, 0, 77,111,
+100,105,102,105,101,114, 68, 97,116, 97, 0, 83,117, 98,115,117,114,102, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 76,
+ 97,116,116,105, 99,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 67,117,114,118,101, 77,111,100,105,102,105,101,114,
+ 68, 97,116, 97, 0, 66,117,105,108,100, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 77,105,114,114,111,114, 77,111,100,
+105,102,105,101,114, 68, 97,116, 97, 0, 68,101, 99,105,109, 97,116,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 87,
+ 97,118,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 65,114,109, 97,116,117,114,101, 77,111,100,105,102,105,101,114,
+ 68, 97,116, 97, 0, 72,111,111,107, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 83,111,102,116, 98,111,100,121, 77,111,
+100,105,102,105,101,114, 68, 97,116, 97, 0, 66,111,111,108,101, 97,110, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 76,
+ 97,116,116,105, 99,101, 0, 98, 68,101,102,111,114,109, 71,114,111,117,112, 0, 76, 66,117,102, 0, 98, 65, 99,116,105,111,110,
+ 0, 98, 80,111,115,101, 0, 80, 97,114,116, 68,101,102,108,101, 99,116, 0, 83,111,102,116, 66,111,100,121, 0, 76,105,102,101,
+ 0, 70,108,117,105,100,115,105,109, 83,101,116,116,105,110,103,115, 0, 68,101,114,105,118,101,100, 77,101,115,104, 0, 79, 98,
+ 72,111,111,107, 0, 83, 66, 86,101,114,116,101,120, 0, 66,111,100,121, 80,111,105,110,116, 0, 66,111,100,121, 83,112,114,105,
+110,103, 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, 81,117,105, 99,107,116,105,109,101, 67,111,100,101, 99, 68, 97,116, 97, 0, 65,117,100,105,111, 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, 84,105,109,101, 77, 97,114,107,101,114, 0,
+ 84,111,111,108, 83,101,116,116,105,110,103,115, 0, 83, 99,101,110,101, 0, 71,114,111,117,112, 0, 68, 97,103, 70,111,114,101,
+115,116, 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, 84,114,101,101, 83,116,111,114,
+101, 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, 83, 99,114,105,112,116, 0, 83, 99,114,105,112,116, 0, 83,112, 97, 99,101, 84,105,109,101, 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, 84,104,101,109,101, 85, 73, 0, 84,104,101,109,101, 83,112, 97, 99,101, 0, 98, 84,104,101,109,101, 0, 83,111,108,105,100,
+ 76,105,103,104,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, 80, 97,110,101,108, 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, 98, 83,111,117,110,100,
+ 0, 77,101,116, 97, 83,116, 97, 99,107, 0, 69,100,105,116,105,110,103, 0, 87,105,112,101, 86, 97,114,115, 0, 71,108,111,119,
+ 86, 97,114,115, 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, 84,114,101,101, 83,116,111,114,101, 69,108,101,109, 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, 74,111,121,115,116,105, 99,107, 83,101,110,115,111,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, 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, 70,114,101,101, 67, 97,109,101,114, 97, 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, 66,111,110,101, 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, 67,104, 97,110,110,101,108, 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, 77,105,
+110, 77, 97,120, 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, 76,111, 99,107, 84,114, 97, 99,107, 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, 68,105,115,116, 97,110, 99,101, 76,105,109,105,116, 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, 83,116,114,101,116, 99,
+104, 84,111, 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, 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,104, 0,116, 0, 16, 0, 24, 0,
+100, 0, 20, 0,116, 0, 48, 1, 0, 0, 0, 0, 88, 0,244, 2,228, 0, 80, 1, 24, 0,136, 1,128, 0,252, 0, 52, 0,156, 1,
+ 64, 1, 0, 0,108, 0, 96, 0,132, 0, 56, 0, 28, 0, 56, 0, 8, 0, 16, 0, 44, 1, 0, 0,140, 0, 84, 0, 60, 0,188, 0,
+ 20, 0, 20, 0, 12, 0, 12, 0, 4, 0, 8, 0, 24, 0, 8, 0, 52, 0, 68, 0, 88, 0, 88, 0, 68, 0, 60, 0, 60, 0, 92, 0,
+ 64, 0,180, 0, 52, 0, 64, 0,108, 0, 40, 0, 12, 0, 56, 0, 24, 0, 44, 0, 92, 0, 0, 0, 84, 1, 0, 0,208, 0, 16, 0,
+ 0, 0, 0, 0, 32, 1, 40, 0, 28, 0,176, 0,144, 0, 16, 0, 16, 3, 16, 0, 80, 0, 28, 0,244, 3, 68, 0, 0, 0, 36, 0,
+180, 2, 36, 0,204, 0,120, 0, 36, 0, 40, 1,212, 0,164, 0, 84, 1, 0, 0, 0, 0,196, 0, 12, 0,184, 0,164, 0,120, 0,
+ 32, 0, 0, 0,148, 0,224, 2, 0, 0, 0, 0, 72, 0,136, 0,224, 7, 56, 0,168, 7,116, 0, 20, 0, 24, 0,164, 0, 24, 0,
+104, 0,188, 0,160, 1,172, 0, 32, 1, 16, 0, 28, 0, 12, 0, 24, 0, 16, 0, 24, 0,236, 0, 0, 0, 56, 0, 12, 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, 64, 0,128, 0, 4, 0,
+ 60, 0, 12, 0, 60, 0, 20, 0, 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, 40, 0, 0, 0, 64, 0,160, 0, 48, 0,112, 1, 20, 0, 4, 1, 80, 0, 68, 1, 60, 0,176, 0, 44, 0, 52, 0, 76, 0,
+ 44, 0, 44, 0, 44, 0, 60, 0, 56, 0, 44, 0, 20, 0, 60, 0, 24, 0, 52, 0, 88, 0, 0, 0, 83, 84, 82, 67,192, 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, 13, 0, 28, 0, 0, 0,
+ 28, 0, 1, 0, 7, 0, 27, 0, 7, 0, 28, 0, 2, 0, 29, 0, 2, 0, 30, 0, 4, 0, 31, 0, 9, 0, 32, 0, 7, 0, 33, 0,
+ 0, 0, 34, 0, 0, 0, 35, 0, 7, 0, 36, 0, 7, 0, 37, 0, 29, 0, 12, 0, 24, 0, 18, 0, 28, 0, 38, 0, 0, 0, 39, 0,
+ 4, 0, 40, 0, 7, 0, 28, 0, 11, 0, 41, 0, 27, 0, 42, 0, 24, 0, 43, 0, 2, 0, 29, 0, 2, 0, 44, 0, 2, 0, 45, 0,
+ 2, 0, 16, 0, 30, 0, 5, 0, 24, 0, 46, 0, 2, 0, 47, 0, 2, 0, 48, 0, 2, 0, 49, 0, 4, 0, 17, 0, 31, 0, 6, 0,
+ 31, 0, 0, 0, 31, 0, 1, 0, 0, 0, 50, 0, 0, 0, 51, 0, 4, 0, 52, 0, 4, 0, 53, 0, 32, 0, 13, 0, 24, 0, 18, 0,
+ 0, 0, 54, 0, 4, 0, 55, 0, 4, 0, 56, 0, 11, 0, 57, 0, 31, 0, 58, 0, 31, 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, 33, 0, 5, 0, 4, 0, 66, 0, 4, 0, 67, 0, 4, 0, 55, 0,
+ 4, 0, 17, 0, 9, 0, 32, 0, 34, 0, 17, 0, 24, 0, 18, 0, 2, 0, 29, 0, 2, 0, 16, 0, 7, 0, 68, 0, 7, 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, 2, 0, 77, 0,
+ 2, 0, 78, 0, 7, 0, 79, 0, 27, 0, 42, 0, 30, 0, 80, 0, 35, 0, 23, 0, 24, 0, 18, 0, 0, 0, 21, 0, 36, 0, 81, 0,
+ 37, 0, 82, 0, 37, 0, 83, 0, 2, 0, 84, 0, 2, 0, 16, 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, 2, 0, 91, 0, 2, 0, 92, 0, 4, 0, 93, 0, 4, 0, 94, 0, 33, 0, 95, 0, 7, 0, 96, 0,
+ 4, 0, 97, 0, 2, 0, 98, 0, 2, 0, 99, 0, 4, 0,100, 0, 38, 0, 24, 0, 2, 0,101, 0, 2, 0,102, 0, 2, 0,103, 0,
+ 2, 0,104, 0, 39, 0,105, 0, 40, 0,106, 0, 0, 0,107, 0, 0, 0,108, 0, 0, 0,109, 0, 0, 0,110, 0, 7, 0,111, 0,
+ 7, 0,112, 0, 2, 0,113, 0, 2, 0,114, 0, 7, 0,115, 0, 7, 0,116, 0, 7, 0,117, 0, 7, 0,118, 0, 7, 0,119, 0,
+ 7, 0,120, 0, 7, 0,121, 0, 7, 0,122, 0, 7, 0,123, 0, 7, 0,124, 0, 41, 0, 14, 0, 0, 0, 21, 0, 9, 0,125, 0,
+ 0, 0,126, 0, 0, 0,127, 0, 4, 0,128, 0, 4, 0,129, 0, 9, 0,130, 0, 7, 0,131, 0, 7, 0,132, 0, 7, 0,133, 0,
+ 4, 0,134, 0, 9, 0,135, 0, 4, 0,136, 0, 4, 0, 17, 0, 42, 0, 6, 0, 7, 0,115, 0, 7, 0,116, 0, 7, 0,117, 0,
+ 7, 0,137, 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,138, 0,
+ 42, 0,139, 0, 44, 0, 16, 0, 39, 0,105, 0, 35, 0,140, 0, 35, 0,141, 0, 7, 0,142, 0, 2, 0, 29, 0, 2, 0,143, 0,
+ 7, 0, 70, 0, 7, 0, 71, 0, 4, 0,144, 0, 2, 0,145, 0, 2, 0,146, 0, 2, 0, 84, 0, 2, 0, 85, 0, 2, 0,147, 0,
+ 2, 0,148, 0, 4, 0, 69, 0, 40, 0, 52, 0, 24, 0, 18, 0, 7, 0,149, 0, 7, 0,150, 0, 7, 0,151, 0, 7, 0,152, 0,
+ 7, 0,153, 0, 7, 0,154, 0, 7, 0,155, 0, 7, 0,156, 0, 7, 0,157, 0, 7, 0,158, 0, 7, 0,159, 0, 7, 0,160, 0,
+ 7, 0,161, 0, 7, 0,162, 0, 7, 0,163, 0, 7, 0,164, 0, 7, 0,165, 0, 7, 0,166, 0, 7, 0,167, 0, 7, 0,168, 0,
+ 2, 0,169, 0, 2, 0,170, 0, 2, 0,171, 0, 2, 0,172, 0, 2, 0,173, 0, 2, 0,174, 0, 2, 0,175, 0, 2, 0, 16, 0,
+ 2, 0, 29, 0, 2, 0,143, 0, 7, 0,176, 0, 7, 0,177, 0, 7, 0,178, 0, 7, 0,179, 0, 2, 0,180, 0, 2, 0,181, 0,
+ 2, 0,182, 0, 2, 0, 52, 0, 7, 0,183, 0, 7, 0,184, 0, 2, 0,185, 0, 2, 0,186, 0, 2, 0,187, 0, 2, 0,188, 0,
+ 7, 0,121, 0, 27, 0, 42, 0, 35, 0,140, 0, 41, 0,189, 0, 43, 0,190, 0, 44, 0,191, 0, 2, 0,192, 0, 45, 0, 50, 0,
+ 24, 0, 18, 0, 2, 0, 29, 0, 2, 0,193, 0, 2, 0,114, 0, 2, 0,194, 0, 7, 0,115, 0, 7, 0,116, 0, 7, 0,117, 0,
+ 7, 0,118, 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, 7, 0,201, 0,
+ 2, 0,202, 0, 2, 0,203, 0, 7, 0, 70, 0, 7, 0, 71, 0, 7, 0,204, 0, 7, 0,205, 0, 7, 0,206, 0, 2, 0,207, 0,
+ 2, 0,208, 0, 2, 0,209, 0, 2, 0,210, 0, 2, 0,211, 0, 2, 0, 17, 0, 7, 0,212, 0, 7, 0,213, 0, 7, 0,214, 0,
+ 2, 0,215, 0, 2, 0,216, 0, 4, 0,217, 0, 4, 0,218, 0, 2, 0,219, 0, 2, 0,220, 0, 2, 0,221, 0, 2, 0,222, 0,
+ 7, 0,223, 0, 7, 0,224, 0, 7, 0,225, 0, 7, 0,226, 0, 7, 0,227, 0, 2, 0,228, 0, 2, 0,229, 0, 38, 0,230, 0,
+ 27, 0, 42, 0, 30, 0, 80, 0, 46, 0, 2, 0, 24, 0, 18, 0, 27, 0, 42, 0, 47, 0, 95, 0, 24, 0, 18, 0, 2, 0,114, 0,
+ 2, 0,231, 0, 7, 0,115, 0, 7, 0,116, 0, 7, 0,117, 0, 7, 0,232, 0, 7, 0,233, 0, 7, 0,234, 0, 7, 0,235, 0,
+ 7, 0,236, 0, 7, 0,237, 0, 7, 0,238, 0, 7, 0,239, 0, 7, 0,240, 0, 7, 0,241, 0, 7, 0,242, 0, 7, 0,243, 0,
+ 7, 0,244, 0, 7, 0,245, 0, 7, 0,246, 0, 7, 0,247, 0, 7, 0,248, 0, 7, 0,249, 0, 7, 0,250, 0, 7, 0,251, 0,
+ 7, 0,252, 0, 7, 0,253, 0, 7, 0,254, 0, 7, 0,255, 0, 7, 0, 0, 1, 2, 0, 1, 1, 2, 0, 2, 1, 2, 0, 3, 1,
+ 0, 0, 4, 1, 0, 0, 5, 1, 4, 0,193, 0, 4, 0, 6, 1, 2, 0, 7, 1, 2, 0, 8, 1, 2, 0, 9, 1, 2, 0, 10, 1,
+ 7, 0, 11, 1, 7, 0, 12, 1, 7, 0, 13, 1, 7, 0, 14, 1, 7, 0, 15, 1, 7, 0, 16, 1, 7, 0, 17, 1, 0, 0, 18, 1,
+ 0, 0,215, 0, 0, 0, 19, 1, 0, 0, 17, 0, 2, 0, 20, 1, 2, 0, 21, 1, 2, 0, 22, 1, 2, 0, 23, 1, 4, 0, 24, 1,
+ 2, 0, 25, 1, 2, 0, 26, 1, 7, 0, 27, 1, 7, 0, 28, 1, 7, 0, 29, 1, 7, 0, 30, 1, 7, 0, 31, 1, 2, 0,101, 0,
+ 2, 0,102, 0, 43, 0, 32, 1, 43, 0, 33, 1, 0, 0, 34, 1, 0, 0, 35, 1, 0, 0, 36, 1, 0, 0, 37, 1, 2, 0, 38, 1,
+ 2, 0, 39, 1, 7, 0, 40, 1, 7, 0, 41, 1, 38, 0,230, 0, 27, 0, 42, 0, 7, 0, 42, 1, 7, 0, 43, 1, 7, 0, 44, 1,
+ 7, 0, 45, 1, 7, 0, 46, 1, 2, 0, 47, 1, 2, 0, 48, 1, 7, 0, 49, 1, 7, 0, 50, 1, 7, 0, 51, 1, 7, 0, 52, 1,
+ 7, 0, 53, 1, 4, 0, 54, 1, 4, 0, 55, 1, 4, 0, 56, 1, 30, 0, 80, 0, 48, 0, 6, 0, 24, 0, 18, 0, 0, 0, 57, 1,
+ 7, 0, 58, 1, 7, 0, 17, 0, 49, 0, 32, 0, 33, 0, 95, 0, 50, 0, 26, 0, 50, 0, 0, 0, 50, 0, 1, 0, 51, 0, 59, 1,
+ 4, 0, 60, 1, 4, 0, 61, 1, 4, 0, 62, 1, 4, 0, 63, 1, 4, 0, 64, 1, 4, 0, 65, 1, 2, 0, 29, 0, 2, 0, 16, 0,
+ 2, 0, 66, 1, 2, 0, 67, 1, 7, 0, 4, 0, 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 68, 1, 7, 0, 69, 1, 7, 0, 70, 1,
+ 7, 0, 71, 1, 7, 0, 72, 1, 7, 0, 73, 1, 7, 0, 74, 1, 7, 0, 52, 0, 7, 0, 75, 1, 7, 0, 76, 1, 52, 0, 15, 0,
+ 24, 0, 18, 0, 51, 0, 59, 1, 11, 0, 77, 1, 11, 0, 78, 1, 27, 0, 42, 0, 47, 0, 79, 1, 2, 0, 16, 0, 2, 0, 80, 1,
+ 4, 0,113, 0, 7, 0, 81, 1, 7, 0,112, 0, 7, 0, 82, 1, 7, 0, 83, 1, 7, 0, 84, 1, 7, 0, 85, 1, 53, 0, 10, 0,
+ 7, 0, 86, 1, 7, 0, 87, 1, 7, 0, 88, 1, 7, 0, 17, 0, 2, 0, 89, 1, 2, 0, 90, 1, 0, 0, 91, 1, 0, 0, 92, 1,
+ 0, 0, 93, 1, 0, 0, 94, 1, 54, 0, 5, 0, 7, 0, 95, 1, 7, 0, 87, 1, 7, 0, 88, 1, 2, 0, 91, 1, 2, 0, 94, 1,
+ 55, 0, 20, 0, 55, 0, 0, 0, 55, 0, 1, 0, 2, 0, 29, 0, 2, 0, 96, 1, 2, 0, 94, 1, 2, 0, 16, 0, 2, 0, 97, 1,
+ 2, 0, 98, 1, 2, 0, 99, 1, 2, 0,100, 1, 2, 0,101, 1, 2, 0,102, 1, 2, 0,103, 1, 2, 0,104, 1, 7, 0,105, 1,
+ 7, 0,106, 1, 54, 0,107, 1, 53, 0,108, 1, 4, 0,109, 1, 4, 0, 17, 0, 56, 0, 5, 0, 2, 0,110, 1, 2, 0, 96, 1,
+ 0, 0, 16, 0, 0, 0, 17, 0, 2, 0, 48, 1, 57, 0, 4, 0, 7, 0, 4, 0, 7, 0, 5, 0, 7, 0, 7, 0, 7, 0,111, 1,
+ 58, 0, 54, 0, 24, 0, 18, 0, 51, 0, 59, 1, 11, 0,112, 1, 11, 0, 78, 1, 39, 0,113, 1, 39, 0,114, 1, 39, 0,115, 1,
+ 27, 0, 42, 0, 59, 0,116, 1, 29, 0,117, 1, 47, 0, 79, 1, 11, 0,118, 1, 7, 0, 81, 1, 7, 0,112, 0, 7, 0, 82, 1,
+ 4, 0,113, 0, 2, 0,119, 1, 2, 0, 80, 1, 2, 0, 16, 0, 2, 0,120, 1, 7, 0,121, 1, 7, 0,122, 1, 7, 0,123, 1,
+ 2, 0, 99, 1, 2, 0,100, 1, 2, 0, 52, 0, 2, 0, 57, 0, 2, 0, 27, 0, 2, 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, 7, 0,131, 1, 7, 0,132, 1, 7, 0,133, 1, 7, 0,134, 1,
+ 0, 0,135, 1, 0, 0,136, 1, 48, 0,137, 1, 48, 0,138, 1, 48, 0,139, 1, 48, 0,140, 1, 4, 0,141, 1, 4, 0,142, 1,
+ 4, 0,143, 1, 4, 0, 17, 0, 57, 0,144, 1, 4, 0,145, 1, 4, 0,146, 1, 56, 0,147, 1, 56, 0,148, 1, 60, 0, 6, 0,
+ 39, 0,149, 1, 2, 0, 25, 0, 2, 0, 30, 0, 2, 0, 29, 0, 2, 0, 16, 0, 0, 0,150, 1, 61, 0, 19, 0, 61, 0, 0, 0,
+ 61, 0, 1, 0, 54, 0,107, 1, 53, 0,108, 1, 23, 0,151, 1, 23, 0,152, 1, 2, 0, 25, 0, 2, 0, 30, 0, 2, 0,153, 1,
+ 2, 0,154, 1, 2, 0,155, 1, 2, 0,156, 1, 2, 0, 16, 0, 2, 0,157, 1, 7, 0, 10, 0, 7, 0, 11, 0, 4, 0,158, 1,
+ 7, 0, 28, 0, 60, 0,159, 1, 62, 0, 8, 0, 9, 0,160, 1, 7, 0,161, 1, 4, 0,162, 1, 0, 0, 16, 0, 0, 0,163, 1,
+ 2, 0,193, 0, 2, 0,164, 1, 2, 0,165, 1, 63, 0, 32, 0, 24, 0, 18, 0, 51, 0, 59, 1, 11, 0,166, 1, 27, 0, 42, 0,
+ 29, 0,117, 1, 47, 0, 79, 1, 64, 0,167, 1, 62, 0,168, 1, 9, 0,169, 1, 65, 0,170, 1, 66, 0,171, 1, 67, 0,172, 1,
+ 68, 0,173, 1, 69, 0,174, 1, 63, 0,175, 1, 70, 0,176, 1, 9, 0,177, 1, 4, 0,154, 1, 4, 0,178, 1, 4, 0,179, 1,
+ 4, 0,113, 0, 7, 0, 81, 1, 7, 0,112, 0, 7, 0, 82, 1, 7, 0,180, 1, 7, 0, 17, 0, 2, 0,181, 1, 2, 0, 16, 0,
+ 2, 0,182, 1, 2, 0,183, 1, 2, 0, 80, 1, 2, 0,184, 1, 64, 0, 8, 0, 4, 0,185, 1, 4, 0,186, 1, 4, 0,187, 1,
+ 4, 0,188, 1, 0, 0, 17, 0, 0, 0, 96, 1, 0, 0,189, 1, 0, 0, 16, 0, 66, 0, 5, 0, 4, 0,185, 1, 4, 0,186, 1,
+ 0, 0,190, 1, 0, 0, 17, 0, 2, 0, 16, 0, 71, 0, 2, 0, 4, 0,191, 1, 7, 0, 88, 1, 67, 0, 3, 0, 71, 0,192, 1,
+ 4, 0,193, 1, 4, 0, 16, 0, 65, 0, 4, 0, 7, 0,194, 1, 2, 0,195, 1, 0, 0, 16, 0, 0, 0, 96, 1, 68, 0, 4, 0,
+ 0, 0,137, 0, 0, 0,115, 0, 0, 0,116, 0, 0, 0,117, 0, 69, 0, 1, 0, 7, 0,196, 1, 72, 0, 6, 0, 72, 0, 0, 0,
+ 72, 0, 1, 0, 4, 0, 29, 0, 4, 0,193, 0, 0, 0, 34, 0, 0, 0,197, 1, 73, 0, 7, 0, 72, 0,198, 1, 2, 0,199, 1,
+ 2, 0,200, 1, 2, 0,201, 1, 2, 0, 55, 0, 9, 0,202, 1, 9, 0,203, 1, 74, 0, 3, 0, 72, 0,198, 1, 39, 0,105, 0,
+ 0, 0, 34, 0, 75, 0, 3, 0, 72, 0,198, 1, 39, 0,105, 0, 0, 0, 34, 0, 76, 0, 5, 0, 72, 0,198, 1, 7, 0,204, 1,
+ 7, 0,205, 1, 4, 0,206, 1, 4, 0,207, 1, 77, 0, 4, 0, 72, 0,198, 1, 2, 0,208, 1, 2, 0, 16, 0, 7, 0,209, 1,
+ 78, 0, 3, 0, 72, 0,198, 1, 7, 0,210, 1, 4, 0,211, 1, 79, 0, 12, 0, 72, 0,198, 1, 2, 0, 16, 0, 2, 0, 17, 0,
+ 7, 0,212, 1, 7, 0,213, 1, 7, 0,214, 1, 7, 0,121, 1, 7, 0,215, 1, 7, 0,216, 1, 7, 0,217, 1, 7, 0,218, 1,
+ 7, 0,219, 1, 80, 0, 5, 0, 72, 0,198, 1, 2, 0,220, 1, 2, 0, 69, 0, 4, 0, 48, 1, 39, 0,105, 0, 81, 0, 9, 0,
+ 72, 0,198, 1, 39, 0,105, 0, 7, 0,221, 1, 7, 0,222, 1, 7, 0,223, 1, 4, 0,224, 1, 4, 0,225, 1, 7, 0,226, 1,
+ 0, 0, 34, 0, 82, 0, 1, 0, 72, 0,198, 1, 83, 0, 4, 0, 72, 0,198, 1, 39, 0,105, 0, 4, 0,227, 1, 4, 0, 17, 0,
+ 84, 0, 23, 0, 24, 0, 18, 0, 2, 0, 97, 1, 2, 0, 98, 1, 2, 0,228, 1, 2, 0, 16, 0, 2, 0,229, 1, 2, 0,230, 1,
+ 2, 0,231, 1, 2, 0, 48, 1, 0, 0,232, 1, 0, 0,233, 1, 0, 0,234, 1, 0, 0, 29, 0, 4, 0, 17, 0, 7, 0,235, 1,
+ 7, 0,236, 1, 7, 0,237, 1, 7, 0,238, 1, 7, 0,239, 1, 7, 0,240, 1, 54, 0,241, 1, 27, 0, 42, 0, 29, 0,117, 1,
+ 85, 0, 3, 0, 85, 0, 0, 0, 85, 0, 1, 0, 0, 0, 34, 0, 51, 0, 1, 0, 7, 0,242, 1, 70, 0, 2, 0, 7, 0,243, 1,
+ 7, 0,112, 0, 86, 0, 4, 0, 2, 0, 22, 0, 2, 0,244, 1, 4, 0, 17, 0, 39, 0,245, 1, 39, 0, 95, 0, 24, 0, 18, 0,
+ 2, 0, 29, 0, 2, 0,246, 1, 4, 0,247, 1, 4, 0,248, 1, 4, 0,249, 1, 0, 0,250, 1, 9, 0,251, 1, 39, 0,252, 1,
+ 39, 0,253, 1, 27, 0, 42, 0, 59, 0,116, 1, 51, 0, 59, 1, 87, 0,254, 1, 88, 0,255, 1, 9, 0, 32, 0, 11, 0, 0, 2,
+ 11, 0,166, 1, 11, 0, 1, 2, 11, 0, 78, 1, 11, 0, 2, 2, 11, 0, 3, 2, 47, 0, 79, 1, 7, 0, 81, 1, 7, 0, 4, 2,
+ 7, 0, 5, 2, 7, 0,112, 0, 7, 0, 6, 2, 7, 0, 82, 1, 7, 0, 7, 2, 7, 0, 68, 1, 7, 0, 8, 2, 7, 0, 9, 2,
+ 7, 0,221, 1, 7, 0,142, 0, 4, 0,231, 0, 2, 0, 16, 0, 2, 0, 10, 2, 2, 0, 11, 2, 2, 0, 12, 2, 2, 0, 13, 2,
+ 2, 0, 14, 2, 2, 0, 15, 2, 2, 0, 16, 2, 2, 0, 17, 2, 2, 0, 18, 2, 2, 0, 19, 2, 2, 0, 20, 2, 2, 0, 21, 2,
+ 2, 0, 22, 2, 2, 0, 23, 2, 2, 0, 24, 2, 7, 0, 25, 2, 7, 0, 26, 2, 7, 0, 27, 2, 7, 0, 28, 2, 7, 0, 29, 2,
+ 7, 0, 30, 2, 7, 0, 31, 2, 7, 0, 32, 2, 7, 0, 33, 2, 0, 0, 34, 2, 0, 0, 35, 2, 0, 0, 80, 1, 0, 0, 36, 2,
+ 30, 0, 80, 0, 11, 0, 37, 2, 11, 0, 38, 2, 11, 0, 39, 2, 11, 0, 40, 2, 9, 0,177, 1, 7, 0, 41, 2, 2, 0, 42, 2,
+ 2, 0, 43, 2, 7, 0,162, 1, 4, 0, 44, 2, 4, 0, 45, 2, 2, 0, 46, 2, 2, 0,147, 0, 7, 0, 47, 2, 11, 0, 48, 2,
+ 11, 0, 49, 2, 11, 0, 50, 2, 89, 0, 51, 2, 90, 0, 52, 2, 91, 0, 53, 2, 86, 0, 54, 2, 86, 0, 55, 2, 2, 0, 56, 2,
+ 0, 0, 57, 2, 0, 0, 58, 2, 7, 0,181, 1, 92, 0, 59, 2, 93, 0, 60, 2, 93, 0, 61, 2, 94, 0, 14, 0, 94, 0, 0, 0,
+ 94, 0, 1, 0, 39, 0,252, 1, 7, 0,221, 1, 7, 0, 62, 2, 7, 0,222, 1, 7, 0,223, 1, 0, 0, 34, 0, 4, 0,224, 1,
+ 4, 0,225, 1, 4, 0, 63, 2, 2, 0, 29, 0, 2, 0, 64, 2, 7, 0,226, 1, 89, 0, 13, 0, 2, 0, 65, 2, 2, 0, 66, 2,
+ 2, 0, 16, 0, 2, 0, 17, 0, 7, 0, 67, 2, 7, 0, 68, 2, 7, 0, 69, 2, 7, 0, 70, 2, 7, 0, 71, 2, 7, 0, 72, 2,
+ 7, 0, 73, 2, 7, 0, 74, 2, 7, 0, 75, 2, 95, 0, 1, 0, 7, 0, 95, 1, 90, 0, 26, 0, 4, 0, 76, 2, 4, 0, 77, 2,
+ 96, 0, 78, 2, 97, 0, 79, 2, 7, 0, 26, 2, 7, 0, 80, 2, 7, 0, 81, 2, 7, 0, 82, 2, 7, 0, 83, 2, 7, 0, 84, 2,
+ 7, 0, 85, 2, 7, 0, 86, 2, 7, 0, 87, 2, 7, 0, 88, 2, 7, 0, 89, 2, 2, 0, 90, 2, 2, 0, 69, 0, 7, 0, 91, 2,
+ 7, 0, 92, 2, 2, 0,187, 0, 2, 0, 93, 2, 2, 0, 94, 2, 2, 0, 48, 1, 95, 0, 95, 2, 4, 0, 96, 2, 4, 0, 44, 0,
+ 92, 0, 26, 0, 2, 0, 29, 0, 2, 0, 97, 2, 2, 0, 98, 2, 2, 0, 99, 2, 7, 0,100, 2, 2, 0,101, 2, 2, 0,102, 2,
+ 7, 0,103, 2, 2, 0,104, 2, 2, 0,105, 2, 7, 0,106, 2, 7, 0,107, 2, 7, 0,108, 2, 7, 0,109, 2, 7, 0,110, 2,
+ 7, 0,111, 2, 4, 0,112, 2, 7, 0,113, 2, 7, 0,114, 2, 7, 0,115, 2, 63, 0,116, 2, 63, 0,117, 2, 63, 0,118, 2,
+ 0, 0,119, 2, 7, 0,120, 2, 7, 0,121, 2, 98, 0, 56, 0, 24, 0, 18, 0, 2, 0,114, 0, 2, 0,194, 0, 2, 0,215, 0,
+ 2, 0,122, 2, 7, 0,123, 2, 7, 0,124, 2, 7, 0,125, 2, 7, 0,126, 2, 7, 0,127, 2, 7, 0,128, 2, 7, 0,129, 2,
+ 7, 0,130, 2, 7, 0,238, 0, 7, 0,240, 0, 7, 0,239, 0, 7, 0,131, 2, 4, 0,132, 2, 7, 0,133, 2, 7, 0,134, 2,
+ 7, 0,135, 2, 7, 0,136, 2, 7, 0,137, 2, 7, 0,138, 2, 7, 0,139, 2, 2, 0,140, 2, 2, 0,193, 0, 4, 0,141, 2,
+ 7, 0,142, 2, 7, 0,143, 2, 7, 0,144, 2, 7, 0,145, 2, 7, 0,146, 2, 7, 0,147, 2, 7, 0,148, 2, 7, 0,149, 2,
+ 7, 0,150, 2, 7, 0,151, 2, 7, 0,152, 2, 7, 0,153, 2, 2, 0,154, 2, 2, 0,155, 2, 2, 0,156, 2, 2, 0,157, 2,
+ 7, 0,158, 2, 7, 0,159, 2, 7, 0,160, 2, 7, 0,161, 2, 2, 0,162, 2, 2, 0,163, 2, 2, 0,164, 2, 2, 0,165, 2,
+ 7, 0,166, 2, 27, 0, 42, 0, 38, 0,230, 0, 30, 0, 80, 0, 99, 0, 16, 0, 2, 0,167, 2, 2, 0,168, 2, 2, 0,169, 2,
+ 2, 0, 16, 0, 2, 0,170, 2, 2, 0,171, 2, 2, 0,172, 2, 2, 0,173, 2, 2, 0,174, 2, 2, 0,175, 2, 2, 0,176, 2,
+ 2, 0,177, 2, 4, 0,178, 2, 7, 0,179, 2, 7, 0,180, 2, 7, 0,181, 2,100, 0, 8, 0,100, 0, 0, 0,100, 0, 1, 0,
+ 4, 0,231, 0, 4, 0,182, 2, 4, 0, 16, 0, 2, 0,183, 2, 2, 0,184, 2, 39, 0,105, 0,101, 0, 13, 0, 9, 0,185, 2,
+ 9, 0,186, 2, 4, 0,187, 2, 4, 0,188, 2, 4, 0,189, 2, 4, 0,190, 2, 4, 0,191, 2, 4, 0,192, 2, 4, 0,193, 2,
+ 4, 0,194, 2, 4, 0,195, 2, 4, 0, 17, 0, 0, 0,196, 2,102, 0, 5, 0, 9, 0,197, 2, 9, 0,198, 2, 4, 0,199, 2,
+ 4, 0, 48, 1, 0, 0,200, 2,103, 0, 4, 0, 4, 0,201, 2, 7, 0,202, 2, 2, 0, 16, 0, 2, 0,203, 2,104, 0, 98, 0,
+101, 0,204, 2,102, 0,205, 2, 2, 0,206, 2, 2, 0,187, 0, 2, 0, 93, 2, 2, 0,207, 2, 2, 0,208, 2, 2, 0, 16, 0,
+ 7, 0, 26, 2, 7, 0,209, 2, 7, 0,210, 2, 7, 0,211, 2, 7, 0,212, 2, 7, 0,213, 2, 2, 0,214, 2, 2, 0,215, 2,
+ 2, 0,216, 2, 2, 0,217, 2, 2, 0,146, 0, 2, 0,218, 2, 2, 0,219, 2, 2, 0,220, 2, 2, 0,221, 2, 2, 0,222, 2,
+ 2, 0,223, 2, 2, 0, 17, 0, 2, 0, 66, 0, 2, 0,224, 2, 2, 0,225, 2, 2, 0,226, 2, 2, 0,227, 2, 2, 0,228, 2,
+ 2, 0,229, 2, 2, 0,230, 2, 23, 0,231, 2, 23, 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, 4, 0,193, 0, 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, 7, 0,181, 2, 7, 0,248, 2, 7, 0,249, 2, 7, 0,250, 2,
+ 7, 0,251, 2, 7, 0,252, 2, 7, 0,253, 2, 7, 0,254, 2, 7, 0,255, 2, 7, 0, 0, 3, 7, 0, 1, 3, 7, 0, 2, 3,
+ 7, 0, 3, 3, 7, 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, 4, 0, 15, 3, 4, 0, 16, 3, 4, 0, 17, 3, 4, 0, 18, 3,
+ 4, 0, 19, 3, 7, 0, 20, 3, 4, 0, 21, 3, 4, 0, 22, 3, 4, 0, 23, 3, 4, 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, 7, 0, 32, 3, 7, 0, 33, 3, 0, 0, 34, 3,
+ 0, 0, 35, 3, 0, 0, 36, 3,105, 0, 5, 0, 7, 0, 37, 3, 0, 0, 29, 0, 0, 0, 69, 0, 0, 0, 48, 1, 0, 0, 39, 1,
+106, 0, 5, 0,106, 0, 0, 0,106, 0, 1, 0, 4, 0, 38, 3, 0, 0, 39, 3, 4, 0, 16, 0,107, 0, 13, 0, 2, 0, 40, 3,
+ 2, 0, 41, 3, 2, 0, 42, 3, 2, 0, 43, 3, 2, 0, 44, 3, 2, 0, 69, 0, 7, 0, 45, 3, 7, 0, 46, 3, 2, 0, 47, 3,
+ 2, 0, 48, 3, 2, 0, 49, 3, 0, 0, 48, 1, 0, 0, 39, 1,108, 0, 31, 0, 24, 0, 18, 0, 39, 0, 50, 3, 98, 0, 51, 3,
+108, 0, 52, 3, 35, 0,140, 0, 11, 0, 53, 3,100, 0, 54, 3,109, 0, 55, 3, 7, 0, 56, 3, 7, 0, 57, 3, 7, 0, 58, 3,
+ 7, 0, 59, 3, 4, 0,231, 0, 2, 0, 60, 3, 2, 0, 17, 0, 2, 0, 61, 3, 2, 0, 62, 3, 7, 0, 63, 3, 9, 0, 64, 3,
+ 99, 0, 65, 3, 9, 0,177, 1,105, 0, 66, 3,107, 0, 67, 3,104, 0,115, 0,103, 0, 68, 3, 30, 0, 80, 0, 11, 0, 69, 3,
+110, 0, 70, 3, 2, 0, 71, 3, 2, 0, 72, 3, 4, 0, 73, 3,111, 0, 10, 0, 35, 0,140, 0, 40, 0,106, 0, 7, 0,132, 1,
+ 7, 0,133, 1, 7, 0, 66, 0, 7, 0, 74, 3, 7, 0, 75, 3, 2, 0, 76, 3, 2, 0, 77, 3, 4, 0, 78, 3,112, 0, 53, 0,
+113, 0, 0, 0,113, 0, 1, 0, 4, 0, 79, 3, 7, 0, 80, 3,114, 0, 81, 3, 2, 0, 82, 3, 7, 0, 83, 3, 7, 0, 84, 3,
+ 7, 0, 85, 3, 7, 0, 86, 3, 7, 0, 87, 3, 7, 0, 88, 3, 7, 0, 89, 3, 7, 0,196, 0, 2, 0, 90, 3, 2, 0, 91, 3,
+ 39, 0, 50, 3,111, 0, 92, 3,112, 0, 93, 3, 2, 0,169, 2, 2, 0, 94, 3, 4, 0,231, 0, 4, 0, 95, 3, 2, 0, 96, 3,
+ 2, 0, 97, 3, 2, 0, 98, 3, 2, 0, 16, 0, 7, 0, 72, 0, 7, 0, 99, 3, 7, 0,100, 3, 7, 0,101, 3, 7, 0,102, 3,
+ 7, 0,103, 3, 7, 0,111, 0, 7, 0, 56, 3, 2, 0,104, 3, 2, 0,105, 3, 2, 0,106, 3, 2, 0,107, 3, 2, 0,108, 3,
+ 2, 0,109, 3, 2, 0,110, 3, 2, 0,111, 3, 2, 0,112, 3, 2, 0,113, 3, 7, 0,114, 3, 7, 0,115, 3, 51, 0,116, 3,
+ 11, 0,117, 3, 2, 0,118, 3, 2, 0,163, 1, 2, 0,119, 3, 2, 0, 48, 1,115, 0, 16, 0, 23, 0, 22, 0, 23, 0, 24, 0,
+ 22, 0,120, 3, 22, 0,121, 3, 22, 0,122, 3, 7, 0,123, 3, 7, 0,124, 3, 7, 0,125, 3, 7, 0,126, 3, 2, 0,127, 3,
+ 2, 0,128, 3, 2, 0,129, 3, 2, 0,130, 3, 2, 0,131, 3, 2, 0,132, 3, 4, 0, 16, 0,113, 0, 6, 0,113, 0, 0, 0,
+113, 0, 1, 0, 4, 0, 79, 3, 7, 0, 80, 3,114, 0, 81, 3, 2, 0, 82, 3,116, 0, 6, 0,113, 0, 0, 0,113, 0, 1, 0,
+ 4, 0, 79, 3, 7, 0, 80, 3,114, 0, 81, 3, 2, 0, 82, 3,117, 0, 26, 0,113, 0, 0, 0,113, 0, 1, 0, 4, 0, 79, 3,
+ 7, 0, 80, 3,114, 0, 81, 3, 2, 0, 82, 3, 4, 0,133, 3, 4, 0, 48, 1,115, 0,134, 3, 9, 0,135, 3, 11, 0,136, 3,
+ 27, 0, 42, 0, 24, 0, 43, 0, 0, 0,137, 3, 0, 0,138, 3, 2, 0,139, 3, 2, 0,140, 3, 2, 0,141, 3, 2, 0,142, 3,
+ 2, 0, 26, 0, 2, 0, 25, 0, 2, 0,108, 3, 2, 0,143, 3, 4, 0, 16, 0, 7, 0,144, 3, 23, 0, 22, 0,118, 0, 31, 0,
+113, 0, 0, 0,113, 0, 1, 0, 4, 0, 79, 3, 7, 0, 80, 3,114, 0, 81, 3, 2, 0, 82, 3, 2, 0,145, 3, 2, 0,146, 3,
+ 2, 0,147, 3, 2, 0,148, 3,115, 0,134, 3, 2, 0,149, 3, 2, 0,108, 3, 2, 0,140, 3, 2, 0,150, 3, 9, 0,151, 3,
+ 2, 0,109, 3, 0, 0,152, 3, 0, 0,153, 3, 2, 0,154, 3, 2, 0,155, 3, 4, 0, 78, 3, 2, 0,156, 3, 2, 0,157, 3,
+ 2, 0,158, 3, 2, 0, 18, 2, 2, 0,159, 3, 2, 0, 69, 0, 4, 0,160, 3, 0, 0,215, 0, 0, 0,161, 3,119, 0, 10, 0,
+113, 0, 0, 0,113, 0, 1, 0, 4, 0, 79, 3, 7, 0, 80, 3,114, 0, 81, 3, 2, 0, 82, 3,115, 0,134, 3, 2, 0,149, 3,
+ 2, 0, 74, 3, 4, 0, 48, 1,120, 0, 24, 0,113, 0, 0, 0,113, 0, 1, 0, 4, 0, 79, 3, 7, 0, 80, 3,114, 0, 81, 3,
+ 2, 0, 82, 3,121, 0,162, 3, 4, 0,163, 3, 0, 0,164, 3, 0, 0,165, 3, 0, 0,166, 3, 2, 0, 29, 0, 2, 0,167, 3,
+ 2, 0, 16, 0, 2, 0,168, 3, 2, 0,169, 3, 2, 0,170, 3,122, 0,171, 3, 2, 0,172, 3, 2, 0,138, 0, 2, 0,173, 3,
+ 2, 0,174, 3, 9, 0,175, 3, 2, 0,176, 3,123, 0, 19, 0,113, 0, 0, 0,113, 0, 1, 0, 4, 0, 79, 3, 7, 0, 80, 3,
+114, 0, 81, 3, 2, 0, 82, 3,115, 0,134, 3, 11, 0,177, 3, 2, 0,140, 3, 2, 0,178, 3, 2, 0, 16, 0, 2, 0,157, 1,
+ 9, 0,151, 3, 11, 0,179, 3,124, 0,180, 3, 2, 0, 29, 0, 2, 0,181, 3, 2, 0,182, 3, 2, 0,183, 3,125, 0, 17, 0,
+113, 0, 0, 0,113, 0, 1, 0, 4, 0, 79, 3, 7, 0, 80, 3,114, 0, 81, 3, 2, 0, 82, 3,115, 0,134, 3, 35, 0,184, 3,
+ 7, 0, 74, 3, 2, 0,193, 0, 2, 0,108, 3, 2, 0,185, 3, 2, 0,186, 3, 7, 0,132, 1, 7, 0,133, 1, 2, 0, 16, 0,
+ 2, 0,143, 3,126, 0, 10, 0,113, 0, 0, 0,113, 0, 1, 0, 4, 0, 79, 3, 7, 0, 80, 3,114, 0, 81, 3, 2, 0, 82, 3,
+ 2, 0,108, 3, 2, 0,143, 3, 4, 0, 17, 0,115, 0,134, 3,127, 0, 22, 0,113, 0, 0, 0,113, 0, 1, 0, 4, 0, 79, 3,
+ 7, 0, 80, 3,114, 0, 81, 3, 2, 0, 82, 3, 32, 0,187, 3, 4, 0,188, 3, 4, 0,189, 3, 2, 0, 55, 0, 2, 0,108, 3,
+ 4, 0,190, 3, 4, 0,191, 3, 4, 0,192, 3, 4, 0,193, 3, 4, 0,194, 3, 4, 0,195, 3, 4, 0,196, 3, 4, 0,197, 3,
+ 7, 0,198, 3, 22, 0,199, 3, 22, 0,200, 3,128, 0, 9, 0,113, 0, 0, 0,113, 0, 1, 0, 4, 0, 79, 3, 7, 0, 80, 3,
+114, 0, 81, 3,129, 0,201, 3, 4, 0, 48, 1, 2, 0, 55, 0, 2, 0,108, 3,130, 0, 8, 0,113, 0, 0, 0,113, 0, 1, 0,
+ 4, 0, 79, 3, 7, 0, 80, 3,114, 0, 81, 3,115, 0,134, 3, 4, 0, 16, 0, 4, 0,202, 3,131, 0, 81, 0,113, 0, 0, 0,
+113, 0, 1, 0, 4, 0, 79, 3, 7, 0, 80, 3,114, 0, 81, 3, 0, 0,203, 3, 4, 0,204, 3, 2, 0,193, 0, 2, 0,205, 3,
+ 2, 0,206, 3, 2, 0,207, 3, 2, 0,208, 3, 2, 0,209, 3, 2, 0,210, 3, 2, 0,211, 3, 2, 0,212, 3, 2, 0,213, 3,
+ 2, 0,214, 3, 2, 0,215, 3, 2, 0,216, 3, 2, 0,217, 3, 2, 0,218, 3, 2, 0,219, 3, 2, 0,220, 3, 2, 0,221, 3,
+ 2, 0,222, 3, 2, 0,223, 3, 2, 0,224, 3, 2, 0,225, 3, 2, 0,226, 3, 2, 0,227, 3, 2, 0,228, 3, 2, 0,229, 3,
+ 2, 0,230, 3, 2, 0,231, 3, 2, 0,232, 3, 2, 0,233, 3, 2, 0,234, 3, 2, 0,235, 3, 2, 0,236, 3, 2, 0,237, 3,
+ 2, 0,238, 3, 2, 0,239, 3, 2, 0,240, 3, 2, 0,241, 3, 2, 0,242, 3, 2, 0,243, 3, 2, 0,244, 3, 2, 0,245, 3,
+ 2, 0,246, 3, 2, 0,247, 3, 2, 0,248, 3, 2, 0,249, 3, 2, 0,250, 3, 2, 0,251, 3, 0, 0,252, 3, 0, 0,253, 3,
+ 0, 0,254, 3, 0, 0,255, 3,132, 0, 0, 4,132, 0, 1, 4, 4, 0, 2, 4, 4, 0, 3, 4, 4, 0, 4, 4, 4, 0, 5, 4,
+ 4, 0, 6, 4, 7, 0, 7, 4, 7, 0, 8, 4, 7, 0, 9, 4, 2, 0, 10, 4, 2, 0, 11, 4, 2, 0, 12, 4, 2, 0, 13, 4,
+133, 0, 14, 4,133, 0, 15, 4, 2, 0, 16, 4, 2, 0, 17, 4, 4, 0, 48, 1, 37, 0, 18, 4, 9, 0,175, 3, 9, 0, 19, 4,
+134, 0, 19, 0, 0, 0, 20, 4, 0, 0, 21, 4, 0, 0, 22, 4, 0, 0, 23, 4, 0, 0, 24, 4, 0, 0, 25, 4, 0, 0, 26, 4,
+ 0, 0, 27, 4, 0, 0, 28, 4, 0, 0, 29, 4, 0, 0, 30, 4, 0, 0, 31, 4, 0, 0, 32, 4, 0, 0, 33, 4, 0, 0, 34, 4,
+ 0, 0, 35, 4, 0, 0, 36, 4, 0, 0, 37, 4, 0, 0, 38, 4,135, 0, 36, 0, 0, 0, 39, 4, 0, 0, 30, 4, 0, 0, 31, 4,
+ 0, 0, 40, 4, 0, 0, 41, 4, 0, 0, 42, 4, 0, 0, 43, 4, 0, 0, 44, 4, 0, 0, 45, 4, 0, 0, 46, 4, 0, 0, 47, 4,
+ 0, 0, 48, 4, 0, 0, 49, 4, 0, 0, 50, 4, 0, 0, 51, 4, 0, 0, 52, 4, 0, 0, 53, 4, 0, 0, 54, 4, 0, 0, 55, 4,
+ 0, 0, 56, 4, 0, 0, 57, 4, 0, 0, 58, 4, 0, 0, 59, 4, 0, 0, 60, 4, 0, 0, 61, 4, 0, 0, 62, 4, 0, 0, 63, 4,
+ 0, 0, 64, 4, 0, 0, 65, 4, 0, 0, 66, 4, 0, 0, 67, 4, 0, 0, 68, 4, 0, 0, 69, 4, 0, 0, 70, 4, 0, 0, 71, 4,
+ 0, 0, 72, 4,136, 0, 18, 0,136, 0, 0, 0,136, 0, 1, 0, 0, 0, 34, 0,134, 0, 73, 4,135, 0, 74, 4,135, 0, 75, 4,
+135, 0, 76, 4,135, 0, 77, 4,135, 0, 78, 4,135, 0, 79, 4,135, 0, 80, 4,135, 0, 81, 4,135, 0, 82, 4,135, 0, 83, 4,
+135, 0, 84, 4,135, 0, 85, 4,135, 0, 86, 4,135, 0, 87, 4,137, 0, 5, 0, 4, 0, 16, 0, 4, 0, 17, 0, 7, 0,162, 1,
+ 7, 0, 88, 4, 7, 0, 95, 1,138, 0, 45, 0, 4, 0, 16, 0, 4, 0, 89, 4, 4, 0, 90, 4, 0, 0, 91, 4, 0, 0, 92, 4,
+ 0, 0, 93, 4, 0, 0, 94, 4, 0, 0, 95, 4, 0, 0, 96, 4, 0, 0, 97, 4, 0, 0, 98, 4, 0, 0, 99, 4, 2, 0,100, 4,
+ 2, 0,101, 4, 4, 0,102, 4, 4, 0,103, 4, 4, 0,104, 4, 4, 0,105, 4, 2, 0,106, 4, 2, 0,107, 4, 2, 0,108, 4,
+ 2, 0,109, 4, 4, 0,110, 4, 4, 0,111, 4, 2, 0,112, 4, 2, 0,113, 4, 2, 0,114, 4, 2, 0,115, 4, 0, 0,116, 4,
+ 11, 0,117, 4, 2, 0,118, 4, 2, 0,119, 4, 2, 0,120, 4, 2, 0,121, 4,137, 0,122, 4, 2, 0,123, 4, 2, 0,124, 4,
+ 2, 0,125, 4, 2, 0,126, 4, 4, 0,127, 4, 4, 0,128, 4, 2, 0,129, 4, 2, 0, 69, 0, 2, 0, 48, 1, 2, 0, 39, 1,
+139, 0, 18, 0, 24, 0, 18, 0, 11, 0,130, 4, 11, 0,131, 4, 11, 0,132, 4,108, 0,133, 4, 2, 0,212, 1, 2, 0,134, 4,
+ 2, 0,213, 1, 2, 0,135, 4, 2, 0,136, 4, 2, 0,137, 4, 2, 0,138, 4, 2, 0,139, 4, 2, 0,140, 4, 2, 0, 17, 0,
+ 2, 0,141, 4, 2, 0,142, 4, 2, 0,143, 4,140, 0, 5, 0,140, 0, 0, 0,140, 0, 1, 0,140, 0,144, 4, 12, 0,145, 4,
+ 4, 0, 16, 0,141, 0, 7, 0,141, 0, 0, 0,141, 0, 1, 0,140, 0,146, 4,140, 0,147, 4, 2, 0,232, 2, 2, 0, 16, 0,
+ 4, 0, 17, 0,142, 0, 16, 0,142, 0, 0, 0,142, 0, 1, 0, 0, 0,148, 4, 0, 0,149, 4, 2, 0,150, 4, 2, 0,151, 4,
+ 2, 0,136, 4, 2, 0,137, 4, 2, 0, 16, 0, 2, 0, 64, 2, 2, 0,152, 4, 2, 0, 17, 0, 2, 0,153, 4, 2, 0,154, 4,
+ 4, 0,155, 4,142, 0,156, 4,114, 0, 30, 0,114, 0, 0, 0,114, 0, 1, 0,140, 0,146, 4,140, 0,147, 4,140, 0,157, 4,
+140, 0,158, 4,139, 0,159, 4, 7, 0,160, 4, 22, 0,152, 1, 22, 0,161, 4, 22, 0,162, 4, 2, 0,163, 4, 2, 0,164, 4,
+ 2, 0,165, 4, 0, 0, 79, 3, 0, 0,166, 4, 2, 0,167, 4, 2, 0,168, 4, 0, 0,169, 4, 0, 0,170, 4, 0, 0,171, 4,
+ 0, 0,172, 4, 2, 0,173, 4, 2, 0,174, 4, 2, 0,175, 4, 2, 0, 16, 0, 30, 0, 80, 0, 11, 0,176, 4, 11, 0,177, 4,
+ 11, 0,178, 4,143, 0, 7, 0, 9, 0,179, 4, 9, 0,180, 4, 2, 0,181, 4, 2, 0,233, 2, 4, 0,182, 4, 4, 0,183, 4,
+ 4, 0, 17, 0,144, 0, 8, 0, 0, 0,184, 4, 37, 0, 82, 0,144, 0,185, 4,144, 0,186, 4,144, 0,187, 4, 2, 0, 84, 0,
+ 2, 0,188, 4, 4, 0, 17, 0,145, 0, 11, 0,145, 0, 0, 0,145, 0, 1, 0, 2, 0,157, 1, 2, 0, 52, 0, 2, 0, 15, 0,
+ 2, 0,189, 4,144, 0,190, 4, 0, 0,165, 3, 2, 0,191, 4, 2, 0,192, 4, 4, 0, 17, 0,146, 0, 10, 0, 0, 0, 57, 1,
+ 9, 0,125, 0, 0, 0,126, 0, 4, 0,129, 0, 4, 0,136, 0, 9, 0,130, 0, 7, 0,132, 0, 7, 0,133, 0, 9, 0,134, 0,
+ 9, 0,135, 0,147, 0, 38, 0,147, 0, 0, 0,147, 0, 1, 0,147, 0,193, 4, 9, 0, 13, 0, 0, 0, 14, 0, 2, 0, 16, 0,
+ 2, 0, 29, 0, 4, 0, 52, 0, 4, 0,204, 1, 4, 0,194, 4, 4, 0,195, 4, 4, 0,196, 4, 4, 0,197, 4, 4, 0,198, 4,
+ 4, 0,146, 0, 4, 0,199, 4, 4, 0,200, 4, 7, 0,201, 4, 7, 0,202, 4, 4, 0,187, 0,145, 0,203, 4,144, 0,204, 4,
+ 27, 0, 42, 0,108, 0,133, 4, 36, 0, 81, 0, 7, 0,205, 4, 7, 0,206, 4,146, 0,189, 0,147, 0,207, 4,147, 0,208, 4,
+147, 0,209, 4, 11, 0,210, 4,148, 0,211, 4, 7, 0,212, 4, 7, 0,213, 4, 4, 0,214, 4, 7, 0,215, 4, 9, 0,216, 4,
+149, 0, 4, 0,149, 0, 0, 0,149, 0, 1, 0, 11, 0,217, 4,147, 0,218, 4,150, 0, 6, 0, 11, 0,219, 4, 11, 0,210, 4,
+ 11, 0,220, 4, 2, 0, 16, 0, 2, 0,157, 1, 4, 0, 17, 0,151, 0, 4, 0, 7, 0,221, 4, 7, 0,222, 4, 2, 0,223, 4,
+ 2, 0,224, 4,152, 0, 6, 0, 7, 0,225, 4, 7, 0,226, 4, 7, 0,227, 4, 7, 0,228, 4, 4, 0,229, 4, 4, 0,230, 4,
+153, 0, 6, 0,153, 0, 0, 0,153, 0, 1, 0, 2, 0, 29, 0, 2, 0, 16, 0, 2, 0,231, 4, 2, 0,157, 1,154, 0, 8, 0,
+154, 0, 0, 0,154, 0, 1, 0, 2, 0, 29, 0, 2, 0, 16, 0, 2, 0,231, 4, 2, 0,157, 1, 7, 0, 52, 0, 7, 0,187, 0,
+155, 0, 41, 0,155, 0, 0, 0,155, 0, 1, 0, 2, 0, 29, 0, 2, 0, 16, 0, 2, 0,231, 4, 2, 0,143, 0, 2, 0, 90, 2,
+ 2, 0,232, 4, 7, 0,233, 4, 7, 0,234, 4, 7, 0,219, 1, 4, 0,235, 4, 4, 0, 44, 0, 4, 0,207, 1, 7, 0,236, 4,
+ 7, 0,237, 4, 7, 0,238, 4, 7, 0,239, 4, 7, 0,240, 4, 7, 0,241, 4, 7, 0,217, 1, 7, 0,184, 0, 7, 0,242, 4,
+ 7, 0,243, 4, 7, 0,244, 4, 7, 0,245, 4, 2, 0,246, 4, 2, 0,247, 4, 2, 0,248, 4, 2, 0,249, 4, 2, 0,250, 4,
+ 2, 0,251, 4, 2, 0,252, 4, 2, 0,253, 4, 2, 0,254, 4, 2, 0,255, 4, 2, 0, 78, 1, 2, 0, 0, 5, 0, 0, 1, 5,
+ 0, 0, 2, 5,156, 0, 3, 5,157, 0, 16, 0,157, 0, 0, 0,157, 0, 1, 0, 2, 0, 29, 0, 2, 0, 16, 0, 2, 0,231, 4,
+ 2, 0,143, 0, 7, 0,212, 1, 7, 0,213, 1, 7, 0,214, 1, 7, 0,121, 1, 7, 0,215, 1, 7, 0,216, 1, 7, 0, 4, 5,
+ 7, 0,217, 1, 7, 0,218, 1, 7, 0,219, 1,158, 0, 5, 0, 2, 0, 29, 0, 2, 0,188, 4, 2, 0, 16, 0, 2, 0, 5, 5,
+ 24, 0, 6, 5,124, 0, 3, 0, 4, 0, 31, 0, 4, 0, 7, 5,158, 0, 32, 0,159, 0, 12, 0,159, 0, 0, 0,159, 0, 1, 0,
+ 2, 0, 29, 0, 2, 0, 16, 0, 2, 0, 34, 2, 2, 0, 94, 1, 7, 0, 4, 0, 7, 0, 5, 0, 7, 0, 8, 5, 7, 0, 9, 5,
+ 24, 0, 6, 5, 11, 0, 10, 5,160, 0, 11, 0,160, 0, 0, 0,160, 0, 1, 0, 0, 0, 34, 0, 2, 0, 29, 0, 2, 0, 11, 5,
+ 4, 0, 12, 5, 4, 0, 13, 5, 2, 0, 16, 0, 2, 0, 17, 0, 9, 0, 14, 5, 9, 0, 15, 5,161, 0, 5, 0, 0, 0, 34, 0,
+ 7, 0,196, 0, 7, 0, 16, 5, 4, 0, 17, 5, 4, 0, 17, 0,162, 0, 4, 0, 2, 0, 29, 0, 2, 0, 16, 0, 2, 0, 69, 0,
+ 2, 0, 48, 1,163, 0, 4, 0, 0, 0, 34, 0, 47, 0, 18, 5, 7, 0,196, 0, 7, 0, 17, 0,164, 0, 6, 0, 2, 0, 19, 5,
+ 2, 0, 20, 5, 2, 0, 29, 0, 2, 0, 21, 5, 0, 0, 22, 5, 0, 0, 23, 5,165, 0, 5, 0, 4, 0, 29, 0, 4, 0, 17, 0,
+ 0, 0, 34, 0, 0, 0, 24, 5, 0, 0, 25, 5,166, 0, 6, 0, 0, 0, 34, 0, 0, 0, 26, 5, 2, 0, 27, 5, 2, 0,217, 1,
+ 2, 0,193, 0, 2, 0, 48, 1,167, 0, 5, 0, 0, 0, 34, 0, 7, 0,222, 4, 7, 0,135, 2, 2, 0, 16, 0, 2, 0,208, 1,
+168, 0, 3, 0, 0, 0, 34, 0, 4, 0,207, 1, 4, 0, 28, 5,169, 0, 7, 0, 0, 0, 34, 0, 7, 0,135, 2, 0, 0, 29, 5,
+ 0, 0, 30, 5, 2, 0,193, 0, 2, 0, 69, 0, 4, 0, 31, 5,170, 0, 3, 0, 39, 0, 32, 5, 0, 0, 33, 5, 0, 0, 34, 5,
+171, 0, 17, 0,171, 0, 0, 0,171, 0, 1, 0, 2, 0, 29, 0, 2, 0, 11, 5, 2, 0, 16, 0, 2, 0, 35, 5, 2, 0, 36, 5,
+ 2, 0, 37, 5, 2, 0, 69, 0, 2, 0, 48, 1, 0, 0, 34, 0, 9, 0, 32, 0,172, 0, 38, 5, 39, 0,149, 1, 2, 0, 39, 5,
+ 2, 0, 40, 5, 4, 0, 17, 0,173, 0, 10, 0, 0, 0, 34, 0, 2, 0, 29, 0, 2, 0, 17, 0, 4, 0,208, 1, 4, 0, 41, 5,
+ 4, 0, 42, 5, 4, 0, 43, 5, 4, 0, 44, 5, 4, 0, 45, 5, 4, 0, 46, 5,174, 0, 1, 0, 0, 0, 47, 5,175, 0, 1, 0,
+ 32, 0,187, 3,172, 0, 18, 0,172, 0, 0, 0,172, 0, 1, 0,172, 0, 48, 5, 2, 0, 29, 0, 2, 0, 16, 0, 2, 0, 49, 5,
+ 2, 0, 37, 5, 2, 0, 11, 5, 2, 0, 50, 5, 2, 0, 48, 1, 2, 0, 39, 1, 0, 0, 34, 0, 9, 0, 32, 0,176, 0, 38, 5,
+171, 0, 51, 5, 2, 0, 52, 5, 2, 0, 53, 5, 4, 0, 24, 1,177, 0, 3, 0, 4, 0, 54, 5, 4, 0, 17, 0, 39, 0,149, 1,
+178, 0, 13, 0, 87, 0, 55, 5, 2, 0, 29, 0, 2, 0, 16, 0, 2, 0,233, 4, 2, 0,234, 4, 0, 0, 34, 0, 2, 0, 56, 5,
+ 2, 0, 57, 5, 7, 0, 58, 5, 2, 0, 59, 5, 2, 0, 99, 0, 2, 0,100, 0, 2, 0, 60, 5,179, 0, 9, 0, 2, 0, 16, 0,
+ 2, 0, 61, 5, 2, 0,233, 4, 2, 0,234, 4,148, 0,211, 4, 2, 0, 29, 0, 2, 0, 62, 5, 2, 0, 63, 5, 2, 0, 64, 5,
+180, 0, 7, 0, 2, 0, 16, 0, 2, 0, 61, 5, 2, 0,233, 4, 2, 0,234, 4, 2, 0, 29, 0, 2, 0, 65, 5, 7, 0, 66, 5,
+181, 0, 9, 0, 4, 0, 54, 5, 2, 0, 29, 0, 2, 0, 16, 0, 39, 0,149, 1, 63, 0, 67, 5, 0, 0, 34, 0, 7, 0, 68, 5,
+ 2, 0, 69, 5, 2, 0, 17, 0,182, 0, 5, 0, 2, 0, 29, 0, 2, 0, 16, 0, 4, 0, 17, 0,108, 0,133, 4, 39, 0, 50, 3,
+183, 0, 5, 0, 4, 0, 16, 0, 4, 0, 29, 0, 0, 0, 34, 0, 0, 0, 24, 5, 39, 0,149, 1,184, 0, 12, 0, 4, 0, 16, 0,
+ 4, 0, 29, 0, 7, 0, 70, 5, 7, 0, 71, 5, 7, 0, 81, 1, 7, 0, 82, 1, 7, 0, 4, 2, 7, 0, 7, 2, 7, 0, 72, 5,
+ 7, 0, 73, 5, 7, 0, 74, 5, 0, 0, 75, 5,185, 0, 9, 0, 2, 0, 16, 0, 2, 0, 29, 0, 2, 0,233, 4, 2, 0,234, 4,
+ 0, 0, 34, 0, 2, 0, 69, 0, 2, 0, 24, 0, 2, 0, 76, 5, 2, 0, 77, 5,186, 0, 8, 0, 39, 0,149, 1, 7, 0,214, 1,
+ 7, 0, 78, 5, 7, 0,244, 1, 7, 0, 79, 5, 2, 0, 16, 0, 2, 0,208, 1, 7, 0, 80, 5,187, 0, 7, 0, 2, 0, 16, 0,
+ 2, 0,217, 1, 7, 0, 81, 5, 7, 0, 82, 5, 7, 0, 83, 5, 7, 0, 84, 5, 7, 0, 85, 5,188, 0, 10, 0, 2, 0, 16, 0,
+ 2, 0, 29, 0, 2, 0,233, 4, 2, 0,234, 4, 0, 0, 34, 0, 2, 0, 69, 0, 2, 0, 24, 0, 2, 0, 76, 5, 2, 0, 77, 5,
+109, 0, 55, 3,189, 0, 7, 0, 4, 0,207, 1, 4, 0, 86, 5, 4, 0, 87, 5, 4, 0, 88, 5, 7, 0, 89, 5, 7, 0, 90, 5,
+ 0, 0, 29, 5,190, 0, 7, 0, 0, 0, 91, 5, 39, 0, 92, 5, 0, 0, 33, 5, 2, 0, 93, 5, 2, 0, 69, 0, 4, 0, 48, 1,
+ 0, 0, 34, 5,191, 0, 6, 0, 2, 0, 16, 0, 2, 0, 29, 0, 2, 0,233, 4, 2, 0,234, 4, 0, 0, 94, 5, 0, 0, 95, 5,
+192, 0, 1, 0, 4, 0, 16, 0,176, 0, 10, 0,176, 0, 0, 0,176, 0, 1, 0,176, 0, 48, 5, 2, 0, 29, 0, 2, 0, 16, 0,
+ 2, 0, 11, 5, 2, 0, 96, 5, 0, 0, 34, 0, 9, 0, 32, 0, 39, 0,149, 1,193, 0, 10, 0, 7, 0, 27, 2, 7, 0, 97, 5,
+ 7, 0, 98, 5, 7, 0, 99, 5, 7, 0,100, 5, 4, 0, 16, 0, 7, 0,101, 5, 7, 0,102, 5, 7, 0,103, 5, 7, 0, 17, 0,
+148, 0, 22, 0, 24, 0, 18, 0, 0, 0, 21, 0,194, 0,104, 5, 9, 0,105, 5, 33, 0, 95, 0, 33, 0,106, 5, 9, 0,107, 5,
+ 27, 0, 42, 0, 7, 0, 66, 5, 7, 0,108, 5, 7, 0,109, 5, 7, 0,110, 5, 7, 0,111, 5, 7, 0,112, 5, 7, 0,113, 5,
+ 4, 0, 55, 0, 4, 0,114, 5, 4, 0,115, 5, 4, 0,116, 5, 0, 0,117, 5, 0, 0,118, 5, 0, 0,119, 5,195, 0, 6, 0,
+ 24, 0, 18, 0, 7, 0,120, 5, 7, 0,121, 5, 7, 0,122, 5, 2, 0,123, 5, 2, 0,124, 5,196, 0, 14, 0,113, 0, 0, 0,
+113, 0, 1, 0, 4, 0, 79, 3, 7, 0, 80, 3,114, 0, 81, 3,115, 0,134, 3,148, 0,211, 4, 2, 0,193, 0, 2, 0, 61, 5,
+ 2, 0,132, 1, 2, 0,133, 1, 2, 0, 16, 0, 2, 0,143, 3, 4, 0, 48, 1,197, 0, 6, 0,197, 0, 0, 0,197, 0, 1, 0,
+ 2, 0,187, 0, 2, 0, 93, 2, 7, 0,206, 2, 0, 0, 34, 0,198, 0, 31, 0,198, 0, 0, 0,198, 0, 1, 0,197, 0,125, 5,
+ 2, 0,246, 1, 2, 0, 17, 0, 4, 0,247, 1, 4, 0,248, 1, 4, 0,249, 1, 39, 0,252, 1, 39, 0,253, 1, 27, 0, 42, 0,
+ 7, 0, 81, 1, 7, 0, 4, 2, 7, 0, 5, 2, 7, 0,112, 0, 7, 0, 6, 2, 7, 0, 82, 1, 7, 0, 7, 2, 7, 0, 68, 1,
+ 7, 0, 8, 2, 7, 0, 9, 2, 7, 0,221, 1, 7, 0,142, 0, 4, 0,231, 0, 0, 0, 11, 2, 0, 0, 12, 2, 0, 0, 13, 2,
+ 0, 0, 14, 2, 7, 0, 25, 2, 7, 0, 26, 2, 7, 0,126, 5,199, 0, 4, 0,199, 0, 0, 0,199, 0, 1, 0, 39, 0,149, 1,
+ 11, 0,127, 5,109, 0, 4, 0, 24, 0, 18, 0, 11, 0,128, 5, 11, 0,129, 5,197, 0,130, 5,200, 0, 25, 0,200, 0, 0, 0,
+200, 0, 1, 0,200, 0,252, 1, 11, 0,131, 5, 0, 0, 34, 0, 7, 0,132, 5, 7, 0,133, 5, 7, 0,134, 5, 7, 0,135, 5,
+ 4, 0, 16, 0, 7, 0,136, 5, 7, 0,137, 5, 7, 0,138, 5, 7, 0,196, 0, 7, 0, 88, 1, 7, 0,139, 5, 7, 0,205, 1,
+ 7, 0,140, 5, 7, 0,141, 5, 7, 0,142, 5, 7, 0,143, 5, 7, 0,144, 5, 7, 0,112, 0, 2, 0,145, 5, 2, 0, 47, 3,
+201, 0, 8, 0, 24, 0, 18, 0, 11, 0,146, 5, 11, 0,147, 5, 4, 0, 16, 0, 4, 0,169, 2, 4, 0,220, 1, 2, 0,148, 5,
+ 2, 0,149, 5,202, 0, 29, 0,202, 0, 0, 0,202, 0, 1, 0, 11, 0, 48, 2, 0, 0, 34, 0, 2, 0, 16, 0, 2, 0,150, 5,
+ 2, 0,151, 5, 2, 0,119, 1, 2, 0, 16, 2, 2, 0, 17, 0, 2, 0, 69, 0, 2, 0, 48, 1,200, 0,152, 5,202, 0,252, 1,
+202, 0,153, 5, 11, 0,154, 5, 9, 0,155, 5, 7, 0, 81, 1, 7, 0,112, 0, 7, 0, 68, 1, 7, 0,156, 5, 7, 0,157, 5,
+ 7, 0,158, 5, 7, 0,159, 5, 7, 0,160, 5, 7, 0,161, 5, 7, 0,162, 5, 7, 0,163, 5, 7, 0,116, 1, 88, 0, 3, 0,
+ 11, 0,164, 5, 4, 0, 16, 0, 7, 0,165, 5,203, 0, 7, 0,203, 0, 0, 0,203, 0, 1, 0, 27, 0, 42, 0, 11, 0, 0, 2,
+ 4, 0, 16, 0, 0, 0, 34, 0, 4, 0, 99, 0, 87, 0, 2, 0, 24, 0, 18, 0, 11, 0,164, 5,204, 0, 14, 0,113, 0, 0, 0,
+113, 0, 1, 0, 4, 0, 79, 3, 7, 0, 80, 3,114, 0, 81, 3, 2, 0, 82, 3,115, 0,134, 3, 87, 0,254, 1, 4, 0, 16, 0,
+ 2, 0,140, 3, 2, 0,166, 5, 2, 0,143, 3, 2, 0, 17, 0, 7, 0,167, 5,205, 0, 5, 0,205, 0, 0, 0,205, 0, 1, 0,
+ 27, 0, 42, 0, 2, 0, 16, 0, 0, 0,168, 5,206, 0, 8, 0,206, 0, 0, 0,206, 0, 1, 0, 9, 0, 32, 0, 2, 0, 29, 0,
+ 2, 0, 16, 0, 2, 0, 99, 0, 0, 0,168, 5, 7, 0,169, 5,207, 0, 11, 0, 39, 0,170, 5, 7, 0,209, 1, 2, 0,171, 5,
+ 2, 0, 16, 0, 4, 0,172, 5, 4, 0, 17, 0, 0, 0,173, 5, 7, 0, 88, 1, 7, 0,174, 5, 7, 0,175, 5, 7, 0, 48, 1,
+208, 0, 4, 0, 39, 0,170, 5, 4, 0, 99, 0, 4, 0,100, 0, 0, 0,173, 5,209, 0, 4, 0, 39, 0,170, 5, 4, 0, 16, 0,
+ 4, 0, 99, 0, 0, 0,173, 5,210, 0, 4, 0, 39, 0,170, 5, 4, 0, 16, 0, 4, 0, 99, 0, 0, 0,173, 5,211, 0, 7, 0,
+ 39, 0,170, 5, 4, 0,176, 5, 7, 0,186, 0, 2, 0,177, 5, 2, 0,178, 5, 7, 0,179, 5, 0, 0,173, 5,212, 0, 9, 0,
+ 39, 0,170, 5, 2, 0, 29, 0, 2, 0,180, 5, 2, 0,204, 1, 2, 0,234, 4, 7, 0, 78, 5, 7, 0,244, 1, 87, 0, 55, 5,
+ 0, 0,173, 5,213, 0, 4, 0, 39, 0,170, 5, 4, 0, 13, 2, 4, 0,181, 5, 0, 0,173, 5,214, 0, 5, 0, 39, 0,170, 5,
+ 7, 0,186, 0, 4, 0,182, 5, 4, 0, 13, 2, 4, 0, 14, 2,215, 0, 6, 0, 39, 0,170, 5, 0, 0,173, 5, 7, 0, 69, 0,
+ 7, 0, 48, 1, 7, 0,113, 5, 7, 0,183, 5,216, 0, 6, 0, 7, 0, 8, 0, 7, 0, 9, 0, 7, 0, 10, 0, 7, 0, 11, 0,
+ 7, 0, 0, 3, 7, 0,184, 5,217, 0, 6, 0, 39, 0,170, 5, 4, 0,185, 5, 4, 0,186, 5, 7, 0,187, 5, 7, 0,188, 5,
+ 0, 0,173, 5,218, 0, 17, 0,218, 0, 0, 0,218, 0, 1, 0, 2, 0, 16, 0, 2, 0,193, 0, 2, 0,189, 5, 2, 0, 17, 0,
+ 27, 0, 42, 0, 87, 0, 55, 5, 7, 0,204, 1, 7, 0,234, 4, 7, 0,190, 5, 7, 0,191, 5, 7, 0,192, 5, 7, 0,193, 5,
+ 7, 0, 56, 5, 7, 0,194, 5, 0, 0,195, 5, 69, 78, 68, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
diff --git a/source/blender/editors/datafiles/Bfont.c b/source/blender/editors/datafiles/Bfont.c
new file mode 100644
index 00000000000..4080a0d369f
--- /dev/null
+++ b/source/blender/editors/datafiles/Bfont.c
@@ -0,0 +1,136 @@
+/* DataToC output of file <Bfont> */
+/*
+ * $Id: Bfont.c 125 2002-11-25 12:02:15Z mein $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+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/editors/datafiles/Makefile b/source/blender/editors/datafiles/Makefile
new file mode 100644
index 00000000000..4162125623e
--- /dev/null
+++ b/source/blender/editors/datafiles/Makefile
@@ -0,0 +1,49 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_datafiles
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+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$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/datafiles/SConscript b/source/blender/editors/datafiles/SConscript
new file mode 100644
index 00000000000..8fb2ed6888e
--- /dev/null
+++ b/source/blender/editors/datafiles/SConscript
@@ -0,0 +1,9 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' #/intern/guardedalloc'
+
+env.BlenderLib ( 'bf_editor_datafiles', sources, Split(incs), [], libtype=['core'], priority=[135] )
diff --git a/source/blender/editors/datafiles/bfont.ttf.c b/source/blender/editors/datafiles/bfont.ttf.c
new file mode 100644
index 00000000000..a52d6ded28a
--- /dev/null
+++ b/source/blender/editors/datafiles/bfont.ttf.c
@@ -0,0 +1,5992 @@
+/* DataToC output of file <bfont_ttf> */
+
+int datatoc_bfont_ttf_size= 191532;
+char datatoc_bfont_ttf[]= {
+ 0, 1, 0, 0, 0, 17, 1, 0, 0, 4, 0, 16,
+ 79, 83, 47, 50,150,230,175, 11, 0, 0, 1,152, 0, 0, 0, 86, 99,109, 97,112, 83, 13, 80,227, 0, 0, 28, 64, 0, 0, 3,138,
+ 99,118,116, 32, 0,105, 29, 57, 0, 0, 37,224, 0, 0, 1,254,102,101, 97,116,128, 29, 10, 57, 0, 2,233,124, 0, 0, 0, 80,
+102,112,103,109,113, 52,118,106, 0, 0, 31,204, 0, 0, 0,171,103,108,121,102, 31, 47,248,201, 0, 0, 53, 40, 0, 1,229,240,
+104,101, 97,100,232, 93,169,219, 0, 0, 1, 28, 0, 0, 0, 54,104,104,101, 97, 12,184, 14,241, 0, 0, 1, 84, 0, 0, 0, 36,
+104,109,116,120,203, 81,215, 70, 0, 0, 1,240, 0, 0, 26, 78,107,101,114,110,239,172, 97,238, 0, 2, 27, 24, 0, 0, 60, 6,
+108,111, 99, 97,253, 73,117,214, 0, 0, 39,224, 0, 0, 13, 72,109, 97,120,112, 10,234, 6,122, 0, 0, 1,120, 0, 0, 0, 32,
+109,111,114,120,223,111, 12,226, 0, 2,213, 8, 0, 0, 20,116,110, 97,109,101,179,203,190,182, 0, 2, 87, 32, 0, 0, 65, 55,
+112,111,115,116, 15, 42,244, 94, 0, 2,152, 88, 0, 0, 60,174,112,114,101,112, 59, 7,241, 0, 0, 0, 32,120, 0, 0, 5,104,
+112,114,111,112, 68,181,210, 32, 0, 2,233,204, 0, 0, 2, 96, 0, 1, 0, 0, 0, 2,204,204, 16,228, 33, 70, 95, 15, 60,245,
+ 2, 27, 8, 0, 0, 0, 0, 0,192,243, 73,110, 0, 0, 0, 0,192,243, 73,110,247,214,252,235, 13,114, 8, 75, 0, 0, 0, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 7,109,254, 29, 0, 0, 13,226,247,214,252,109, 13,114, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,132, 0, 1, 0, 0, 6,163, 0, 93, 0, 9, 0,112, 0, 8, 0, 2, 0, 16, 0, 64,
+ 0, 8, 0, 0, 4, 21, 5,104, 0, 8, 0, 3, 0, 1, 4, 14, 1,144, 0, 5, 0, 0, 5, 51, 5,153, 0, 0, 3,215, 5, 51,
+ 5,153, 0, 0, 0, 0, 0,102, 2, 18, 0, 0, 2, 11, 6, 3, 3, 8, 4, 2, 2, 4,224, 0, 38,255, 64, 0, 4,255, 0, 4,
+ 0, 32, 0, 0, 0, 0, 80,102, 69,100, 0, 64, 0, 13,255,253, 6, 20,254, 20, 1,154, 7,109, 1,227, 96, 0, 1,255,191,255,
+ 0, 0, 0, 0, 4,205, 0,102, 0, 0, 0, 0, 2,170, 0, 0, 2,139, 0, 0, 3, 53, 1, 53, 3,174, 0,197, 6,180, 0,158,
+ 5, 23, 0,170, 7,154, 0,113, 6, 61, 0,129, 2, 51, 0,197, 3, 31, 0,176, 3, 31, 0,164, 4, 0, 0, 61, 6,180, 0,217,
+ 2,139, 0,158, 2,227, 0,100, 2,139, 0,219, 2,178, 0, 0, 5, 23, 0,135, 5, 23, 0,225, 5, 23, 0,150, 5, 23, 0,156,
+ 5, 23, 0,100, 5, 23, 0,158, 5, 23, 0,143, 5, 23, 0,168, 5, 23, 0,139, 5, 23, 0,129, 2,178, 0,240, 2,178, 0,158,
+ 6,180, 0,217, 6,180, 0,217, 6,180, 0,217, 4, 63, 0,147, 8, 0, 0,135, 5,121, 0, 16, 5,125, 0,201, 5,150, 0,115,
+ 6, 41, 0,201, 5, 14, 0,201, 4,154, 0,201, 6, 51, 0,115, 6, 4, 0,201, 2, 92, 0,201, 2, 92,255,150, 5, 63, 0,201,
+ 4,117, 0,201, 6,231, 0,201, 5,252, 0,201, 6, 76, 0,115, 4,211, 0,201, 6, 76, 0,115, 5,143, 0,201, 5, 20, 0,135,
+ 4,227,255,250, 5,219, 0,178, 5,121, 0, 16, 7,233, 0, 68, 5,123, 0, 61, 4,227,255,252, 5,123, 0, 92, 3, 31, 0,176,
+ 2,178, 0, 0, 3, 31, 0,199, 6,180, 0,217, 4, 0,255,236, 4, 0, 0,170, 4,231, 0,123, 5, 20, 0,186, 4,102, 0,113,
+ 5, 20, 0,113, 4,236, 0,113, 2,209, 0, 47, 5, 20, 0,113, 5, 18, 0,186, 2, 57, 0,193, 2, 57,255,219, 4,162, 0,186,
+ 2, 57, 0,193, 7,203, 0,186, 5, 18, 0,186, 4,229, 0,113, 5, 20, 0,186, 5, 20, 0,113, 3, 74, 0,186, 4, 43, 0,111,
+ 3, 35, 0, 55, 5, 18, 0,174, 4,188, 0, 61, 6,139, 0, 86, 4,188, 0, 59, 4,188, 0, 61, 4, 51, 0, 88, 5, 23, 1, 0,
+ 2,178, 1, 4, 5, 23, 1, 0, 6,180, 0,217, 5, 23, 0, 0, 3, 53, 1, 53, 5, 23, 0,172, 5, 23, 0,129, 5, 23, 0, 94,
+ 5, 23, 0, 82, 2,178, 1, 4, 4, 0, 0, 92, 4, 0, 0,215, 8, 0, 1, 27, 3,197, 0,115, 4,229, 0,158, 6,180, 0,217,
+ 2,227, 0,100, 8, 0, 1, 27, 4, 0, 0,213, 4, 0, 0,195, 6,180, 0,217, 3, 53, 0, 94, 3, 53, 0, 98, 4, 0, 1,115,
+ 5, 23, 0,174, 5, 23, 0,158, 2,139, 0,219, 4, 0, 1, 35, 3, 53, 0,137, 3,197, 0, 96, 4,229, 0,193, 7,193, 0,137,
+ 7,193, 0,137, 7,193, 0, 98, 4, 63, 0,143, 5,121, 0, 16, 5,121, 0, 16, 5,121, 0, 16, 5,121, 0, 16, 5,121, 0, 16,
+ 5,121, 0, 16, 7,203, 0, 8, 5,150, 0,115, 5, 14, 0,201, 5, 14, 0,201, 5, 14, 0,201, 5, 14, 0,201, 2, 92, 0,201,
+ 2, 92, 0,201, 2, 92, 0,201, 2, 92, 0,201, 6, 51, 0, 10, 5,252, 0,201, 6, 76, 0,115, 6, 76, 0,115, 6, 76, 0,115,
+ 6, 76, 0,115, 6, 76, 0,115, 6,180, 1, 25, 6, 76, 0,102, 5,219, 0,178, 5,219, 0,178, 5,219, 0,178, 5,219, 0,178,
+ 4,227,255,252, 4,215, 0,201, 5, 10, 0,186, 4,231, 0,123, 4,231, 0,123, 4,231, 0,123, 4,231, 0,123, 4,231, 0,123,
+ 4,231, 0,123, 7,219, 0,123, 4,102, 0,113, 4,236, 0,113, 4,236, 0,113, 4,236, 0,113, 4,236, 0,113, 2, 57,255,199,
+ 2, 57, 0,144, 2, 57,255,222, 2, 57,255,244, 4,229, 0,113, 5, 18, 0,186, 4,229, 0,113, 4,229, 0,113, 4,229, 0,113,
+ 4,229, 0,113, 4,229, 0,113, 6,180, 0,217, 4,229, 0, 72, 5, 18, 0,174, 5, 18, 0,174, 5, 18, 0,174, 5, 18, 0,174,
+ 4,188, 0, 61, 5, 20, 0,186, 4,188, 0, 61, 5,121, 0, 16, 4,231, 0,123, 5,121, 0, 16, 4,231, 0,123, 5,121, 0, 16,
+ 4,231, 0,123, 5,150, 0,115, 4,102, 0,113, 5,150, 0,115, 4,102, 0,113, 5,150, 0,115, 4,102, 0,113, 5,150, 0,115,
+ 4,102, 0,113, 6, 41, 0,201, 5, 20, 0,113, 6, 51, 0, 10, 5, 20, 0,113, 5, 14, 0,201, 4,236, 0,113, 5, 14, 0,201,
+ 4,236, 0,113, 5, 14, 0,201, 4,236, 0,113, 5, 14, 0,201, 4,236, 0,113, 5, 14, 0,201, 4,236, 0,113, 6, 51, 0,115,
+ 5, 20, 0,113, 6, 51, 0,115, 5, 20, 0,113, 6, 51, 0,115, 5, 20, 0,113, 6, 51, 0,115, 5, 20, 0,113, 6, 4, 0,201,
+ 5, 18, 0,186, 7, 84, 0,201, 5,143, 0,120, 2, 92, 0,201, 2, 57,255,211, 2, 92, 0, 3, 2, 57,255,242, 2, 92, 0,201,
+ 2, 57,255,228, 2, 92, 0,176, 2, 57, 0,150, 2, 92, 0,201, 2, 57, 0,193, 4,184, 0,201, 4,114, 0,193, 2, 92,255,150,
+ 2, 57,255,219, 5, 63, 0,201, 4,162, 0,186, 4,162, 0,186, 4,117, 0,201, 2, 88, 0,193, 4,117, 0,201, 2, 57, 0,136,
+ 4,117, 0,201, 3, 0, 0,193, 4,117, 0,201, 2,188, 0,193, 4,127,255,242, 2, 70, 0, 2, 5,252, 0,201, 5, 18, 0,186,
+ 5,252, 0,201, 5, 18, 0,186, 5,252, 0,201, 5, 18, 0,186, 6,130, 0,205, 5,252, 0,213, 5, 18, 0,186, 6, 76, 0,115,
+ 4,229, 0,113, 6, 76, 0,115, 4,229, 0,113, 6, 76, 0,115, 4,229, 0,113, 8,143, 0,115, 8, 47, 0,113, 5,143, 0,201,
+ 3, 74, 0,186, 5,143, 0,201, 3, 74, 0,130, 5,143, 0,201, 3, 74, 0,186, 5, 20, 0,135, 4, 43, 0,111, 5, 20, 0,135,
+ 4, 43, 0,111, 5, 20, 0,135, 4, 43, 0,111, 5, 20, 0,135, 4, 43, 0,111, 4,227,255,250, 3, 35, 0, 55, 4,227,255,250,
+ 3, 35, 0, 55, 4,227,255,250, 3, 35, 0, 55, 5,219, 0,178, 5, 18, 0,174, 5,219, 0,178, 5, 18, 0,174, 5,219, 0,178,
+ 5, 18, 0,174, 5,219, 0,178, 5, 18, 0,174, 5,219, 0,178, 5, 18, 0,174, 5,219, 0,178, 5, 18, 0,174, 7,233, 0, 68,
+ 6,139, 0, 86, 4,227,255,252, 4,188, 0, 61, 4,227,255,252, 5,123, 0, 92, 4, 51, 0, 88, 5,123, 0, 92, 4, 51, 0, 88,
+ 5,123, 0, 92, 4, 51, 0, 88, 2,209, 0, 47, 5, 20, 0, 32, 5,225,255,151, 5,125, 0,201, 5, 20, 0,186, 5,125, 0, 0,
+ 5, 20, 0, 0, 5,160, 0,115, 5,150, 0,115, 4,102, 0,113, 6, 51, 0, 10, 6,141,255,151, 5,125, 0,201, 5, 20, 0,113,
+ 4,229, 0,113, 5, 14, 0,131, 6, 76, 0,117, 4,234, 0,164, 4,154,255,150, 2,209,255,127, 6, 51, 0,115, 5,126, 0, 8,
+ 7,180, 0,186, 2,212, 0,201, 2, 92, 0, 10, 5,133, 0,201, 4,162, 0,185, 2, 57, 0, 10, 4,188, 0, 61, 7,203, 0,178,
+ 5,252,255,150, 5, 18, 0,186, 6, 76, 0,115, 7, 78, 0,103, 4,229, 0,118, 7,151, 0,115, 6, 19, 0,113, 5, 55,255,151,
+ 5, 20, 0,184, 4,215, 0,201, 5, 20, 0, 69, 4, 43, 0,100, 5, 14, 0,201, 2,176,254,242, 3, 35, 0, 55, 4,227, 0, 24,
+ 3, 35, 0, 55, 4,227,255,250, 6,221, 0,173, 5, 18, 0,176, 6, 29, 0, 78, 5,196, 0,201, 5,145,255,252, 6,112, 0, 61,
+ 5,123, 0, 92, 4, 51, 0, 88, 5, 84, 0,160, 5, 84, 0, 92, 4,159, 0,104, 4, 51, 0,113, 5, 23, 0,150, 5, 84, 0, 93,
+ 4,159, 0,104, 4, 21, 0, 88, 5, 20, 0,186, 2, 92, 0,201, 3,240, 0,201, 3,172, 0, 20, 2, 93, 0,201, 11, 96, 0,201,
+ 10,100, 0,201, 9, 60, 0,113, 6,175, 0,201, 6, 75, 0,201, 3,167, 0,193, 7,115, 0,201, 7,100, 0,201, 6, 97, 0,186,
+ 5,121, 0, 16, 4,231, 0,123, 2, 92, 0,201, 2, 57,255,224, 6, 76, 0,115, 4,229, 0,113, 5,219, 0,178, 5, 18, 0,174,
+ 5,219, 0,178, 5, 18, 0,174, 5,219, 0,178, 5, 18, 0,174, 5,219, 0,178, 5, 18, 0,174, 5,219, 0,178, 5, 18, 0,174,
+ 4,236, 0, 0, 5,121, 0, 16, 4,231, 0,123, 5,121, 0, 16, 4,231, 0,123, 7,203, 0, 8, 7,219, 0,123, 6, 51, 0,115,
+ 5, 20, 0,113, 6, 51, 0,115, 5, 20, 0,113, 5, 63, 0,201, 4,162, 0,186, 6, 76, 0,115, 4,229, 0,113, 6, 76, 0,115,
+ 4,229, 0,113, 5, 84, 0,160, 4,159, 0,220, 2, 57,255,219, 11, 96, 0,201, 10,100, 0,201, 9, 60, 0,113, 6, 51, 0,115,
+ 5, 20, 0,113, 8,231, 0,201, 5,117, 0,201, 5,252, 0,201, 5, 18, 0,186, 5,121, 0, 16, 4,231, 0,123, 7,203, 0, 8,
+ 7,219, 0,123, 6, 76, 0,102, 4,229, 0, 72, 5,121, 0, 16, 4,231, 0,123, 5,121, 0, 16, 4,231, 0,123, 5, 14, 0,201,
+ 4,236, 0,113, 5, 14, 0,201, 4,236, 0,113, 2, 92, 0,201, 2, 57,255,195, 2, 92, 0,201, 2, 57,255,228, 6, 76, 0,115,
+ 4,229, 0,113, 6, 76, 0,115, 4,229, 0,113, 5,143, 0,201, 3, 74, 0,130, 5,143, 0,201, 3, 74, 0,186, 5,219, 0,178,
+ 5, 18, 0,174, 5,219, 0,178, 5, 18, 0,174, 5, 20, 0,135, 4, 43, 0,111, 4,227,255,250, 3, 35, 0, 55, 5, 4, 0,156,
+ 4, 44, 0, 71, 6, 4, 0,201, 5, 18, 0,186, 5,226, 0,201, 6,180, 0,113, 5,150, 0,113, 4,226, 0,113, 5,123, 0, 92,
+ 4, 51, 0, 88, 5,121, 0, 16, 4,231, 0,123, 5, 14, 0,201, 4,236, 0,113, 6, 76, 0,115, 4,229, 0,113, 6, 76, 0,115,
+ 4,229, 0,113, 6, 76, 0,115, 4,229, 0,113, 6, 76, 0,115, 4,229, 0,113, 4,227,255,252, 4,188, 0, 61, 3,204, 0,138,
+ 6,190, 0,186, 3,209, 0, 55, 2, 57,255,219, 7,252, 0,113, 7,252, 0,113, 5,121,255,253, 5,150, 0, 11, 4,102, 0, 9,
+ 4,117, 0, 10, 4,227,255,178, 4, 43, 0,111, 4, 51, 0, 88, 4,211, 0, 80, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0,
+ 8, 0, 0, 0, 8, 0, 0, 0, 3, 60, 0,117, 3, 49, 0,117, 1,102,255,233, 2, 18, 0,117, 2, 93, 0, 71, 2, 94, 0, 71,
+ 3, 8, 0, 32, 4, 31, 0, 54, 2,251, 0, 38, 2, 51, 0,197, 3,174, 0,197, 2,139, 0,174, 2,139, 0,178, 2,139, 0,196,
+ 2,117, 0,117, 2,117, 0,117, 2,245, 0,117, 2,245, 0,117, 4, 0, 1, 11, 4, 0, 1, 11, 4, 0, 0,193, 4, 0, 0,193,
+ 4, 0, 0,193, 4, 0, 0,193, 2, 51, 0,214, 4, 0, 0,213, 4, 0, 1,115, 4, 0, 0,170, 2, 51, 0,214, 4, 0, 0,213,
+ 4, 0, 0,170, 4, 0, 1,115, 2,178, 0,111, 2,178, 0,111, 2,117, 0,117, 2,117, 0,117, 4, 0, 1, 31, 4, 0, 1, 31,
+ 3, 77, 0,193, 4, 0, 1, 31, 4, 0, 0,199, 4, 0, 1,154, 4, 0, 0,238, 4, 0, 1, 76, 4, 0, 0,182, 4, 0, 0,240,
+ 2,134,255,255, 4, 0, 0,239, 3,104, 0,117, 1, 84, 0,121, 2,252, 0,117, 3,141, 0,117, 2,245, 0,117, 3,242, 0,214,
+ 3,242, 0,214, 3,242, 0,214, 3,242, 0,214, 3,242, 0,214, 4, 0, 0,193, 4, 0, 0,213, 4, 0, 1, 21, 4, 0, 0,238,
+ 4, 0, 0,182, 0, 0,252,168, 0, 0,253,113, 0, 0,252,191, 0, 0,252,180, 0, 0,252,217, 0, 0,251,236, 0, 0,252,191,
+ 0, 0,253,164, 0, 0,252,213, 0, 0,253, 55, 0, 0,252,236, 0, 0,252,244, 0, 0,252,197, 0, 0,253,188, 0, 0,252,240,
+ 0, 0,252, 93, 0, 0,252,191, 0, 0,252,191, 0, 0,254, 31, 0, 0,253,144, 0, 0,253,144, 0, 0,255,121, 0, 0,252,168,
+ 0, 0,253,113, 0, 0,253, 12, 0, 0,253,188, 0, 0,254, 85, 0, 0,254,240, 0, 0,253,129, 0, 0,253, 11, 0, 0,253, 11,
+ 0, 0,253, 11, 0, 0,253, 11, 0, 0,253,122, 0, 0,253,119, 0, 0,253,154, 0, 0,252,213, 0, 0,252,236, 0, 0,253,106,
+ 0, 0,253, 35, 0, 0,253, 76, 0, 0,253,188, 0, 0,252,240, 0, 0,252, 99, 0, 0,252,197, 0, 0,252,191, 0, 0,252,191,
+ 0, 0,252,191, 0, 0,252,180, 0, 0,252,217, 0, 0,251,236, 0, 0,251,236, 0, 0,251,140, 0, 0,253,120, 0, 0,250,237,
+ 0, 0,251,104, 0, 0,250, 18, 0, 0,253,249, 0, 0,252,241, 0, 0,252,240, 0, 0,252, 99, 0, 0,253, 43, 0, 0,254, 6,
+ 0, 0,251,236, 0, 0,252,168, 0, 0,253,113, 0, 0,252,180, 0, 0,253,133, 0, 0,252,231, 0, 0,253,198, 0, 0,252,213,
+ 0, 0,253, 31, 0, 0,253, 21, 0, 0,253, 31, 0, 0,252,182, 0, 0,253, 72, 0, 0, 0, 0, 0, 0,252, 99, 0, 0,253, 51,
+ 0, 0,253,120, 0, 0,252,191, 0, 0,253, 43, 0, 0,253,120, 0, 0,255, 46, 0, 0,252,112, 0, 0,252,112, 0, 0,253, 42,
+ 0, 0,252,112, 0, 0,252,119, 2, 58, 0,160, 2, 58, 0,160, 4, 0, 1,182, 2,178, 0,158, 4, 0, 1,115, 4, 0, 0,215,
+ 5,138, 0, 16, 2,139, 0,219, 5,248,255,231, 6,248,255,243, 3, 68,255,237, 6,128,255,242, 6,153,255,225, 6,155,255,219,
+ 2,181, 0, 5, 5,121, 0, 16, 5,125, 0,201, 4,117, 0,201, 5,121, 0, 16, 5, 14, 0,201, 5,123, 0, 92, 6, 4, 0,201,
+ 6, 76, 0,115, 2, 92, 0,201, 5, 63, 0,201, 5,121, 0, 16, 6,231, 0,201, 5,252, 0,201, 5, 14, 0,201, 6, 76, 0,115,
+ 6, 4, 0,201, 4,211, 0,201, 5, 14, 0,201, 4,227,255,250, 4,227,255,252, 6, 76, 0,115, 5,123, 0, 61, 6, 76, 0,115,
+ 6, 29, 0, 78, 2, 92, 0,201, 4,227,255,252, 5, 70, 0,113, 4, 99, 0,133, 5, 60, 0,186, 2,181, 0,166, 4,161, 0,149,
+ 5, 70, 0,113, 5, 27, 0,191, 4,188, 0, 32, 4,229, 0,113, 4, 83, 0,133, 4, 90, 0,107, 5, 18, 0,186, 4,229, 0,113,
+ 2,181, 0,166, 4,183, 0,191, 4,188, 0, 61, 5, 23, 0,174, 4,120, 0, 74, 4,118, 0,107, 4,229, 0,113, 4,209, 0, 74,
+ 5, 20, 0,186, 4,178, 0,113, 5, 18, 0,113, 4,209, 0,100, 4,161, 0,149, 5, 71, 0,111, 4,159, 0, 59, 5, 71, 0,112,
+ 6,179, 0,135, 2,181, 0, 5, 4,161, 0,149, 4,229, 0,113, 4,161, 0,149, 6,179, 0,135, 4,234, 0,166, 4,244, 0,112,
+ 5,151, 0, 87, 6,189,255,225, 5,151, 0, 87, 5, 71, 0,112, 6,179, 0, 65, 5, 79, 0,111, 6, 76, 0,115, 4,229, 0,113,
+ 5, 48, 0,139, 4,178, 0,113, 4,154, 0,201, 3,171,255, 64, 5, 71, 0,179, 5, 71, 0,191, 6,236, 0,114, 5, 5, 0,119,
+ 7,120, 0,115, 6,179, 0,135, 6, 17, 0,115, 5, 70, 0,113, 6, 85, 0,201, 4,235, 0, 45, 5,126, 0, 79, 4,219, 0,100,
+ 6, 36, 0,115, 5, 0, 0, 54, 5,152, 0,115, 4,229, 0,113, 4,227, 0, 44, 4, 74, 0, 55, 5, 79, 0,111, 5, 20, 0,183,
+ 4,102, 0,113, 2, 57,255,219, 6, 76, 0,115, 4,236, 0,113, 4,236, 0,196, 4,215, 0,201, 5, 20, 0,186, 5,150, 0,115,
+ 6,231, 0,201, 5, 53, 0,127, 5, 20, 0, 85, 5,160, 0,115, 5,150, 0,115, 5,160, 0,115, 5, 14, 0,201, 5, 14, 0,201,
+ 6, 74,255,250, 4,117, 0,201, 5,150, 0,115, 5, 20, 0,135, 2, 92, 0,201, 2, 92, 0,201, 2, 92,255,150, 8,192, 0, 54,
+ 8, 92, 0,201, 6, 74,255,250, 5, 63, 0,201, 5,252, 0,201, 4,224, 0, 35, 6, 4, 0,201, 5,121, 0, 16, 5,125, 0,201,
+ 5,125, 0,201, 4,117, 0,201, 6, 54, 0, 49, 5, 14, 0,201, 6,232, 0, 59, 5, 23, 0,156, 5,252, 0,201, 5,252, 0,201,
+ 5, 63, 0,201, 6, 4, 0, 54, 6,231, 0,201, 6, 4, 0,201, 6, 76, 0,115, 6, 4, 0,201, 4,211, 0,201, 5,150, 0,115,
+ 4,227,255,250, 4,224, 0, 35, 6, 76, 0,115, 5,123, 0, 61, 6, 54, 0,201, 5,124, 0,175, 8, 6, 0,201, 8, 52, 0,201,
+ 6,169, 0, 50, 7, 15, 0,201, 5,125, 0,201, 5,150, 0,111, 8, 63, 0,211, 5,143, 0, 59, 4,231, 0,123, 4,229, 0,113,
+ 4,176, 0,186, 3,238, 0,186, 5, 96, 0, 50, 4,236, 0,113, 5,222, 0, 50, 4, 83, 0,133, 5, 65, 0,193, 5, 65, 0,193,
+ 4,213, 0,191, 5, 29, 0, 46, 6, 9, 0,193, 5, 73, 0,193, 4,229, 0,113, 5, 71, 0,193, 5, 20, 0,186, 4,102, 0,113,
+ 4, 59, 0, 5, 4,188, 0, 61, 7, 85, 0,113, 4,188, 0, 59, 5,114, 0,193, 4,186, 0,150, 6,251, 0,193, 7, 36, 0,193,
+ 5,160, 0, 42, 6, 31, 0,193, 4,183, 0,193, 4,100, 0,113, 6,128, 0,193, 4,208, 0, 50, 4,236, 0,113, 4,236, 0,113,
+ 5, 39, 0, 40, 3,238, 0,186, 4,100, 0,113, 4, 43, 0,111, 2, 57, 0,193, 2, 57,255,244, 2, 57,255,219, 7, 48, 0, 46,
+ 7, 34, 0,193, 5, 25, 0, 40, 4,213, 0,191, 5, 65, 0,193, 4,188, 0, 61, 5, 76, 0,193, 7,120, 0,115, 6,179, 0,135,
+ 5,125, 0, 33, 4,183, 0, 58, 7,138, 0,211, 5,254, 0,193, 7, 9, 0, 16, 6, 68, 0, 51, 9, 71, 0,201, 8, 3, 0,193,
+ 6, 76, 0,115, 4,229, 0,107, 8, 55, 0,201, 6,152, 0,193, 5, 23, 0,115, 4, 83, 0, 91, 6, 76, 0,115, 5, 71, 0,112,
+ 6, 76, 0,115, 4,229, 0,113, 6, 64, 0, 16, 5, 82, 0, 50, 6, 64, 0, 16, 5, 82, 0, 50, 5,150, 0,113, 4,226, 0,113,
+ 7,160, 0,115, 6, 17, 0,113, 7,120, 0,115, 6,179, 0,135, 7,120, 0,115, 6,179, 0,135, 5,150, 0,115, 4,102, 0,113,
+ 4,192, 0, 50, 0, 0,251,218, 0, 0,251,247, 0, 0,252, 34, 0, 0,252, 34, 3, 88,247,214, 3, 88,248, 88, 6, 46, 0,201,
+ 5,106, 0,193, 5,125, 0, 33, 4,183, 0, 38, 4,211, 0,201, 5, 20, 0,186, 4,117, 0,201, 3,238, 0,186, 4,117, 0, 71,
+ 3,238, 0, 56, 4,254, 0,201, 4, 61, 0,186, 6,232, 0, 59, 5,222, 0, 50, 5, 23, 0,156, 4, 83, 0,133, 5, 63, 0,201,
+ 4,213, 0,191, 5, 63, 0,201, 4,213, 0,191, 5, 63, 0, 33, 4,162, 0, 61, 6,107, 0, 50, 5,191, 0, 42, 6, 4, 0,201,
+ 5, 73, 0,193, 8, 29, 0,201, 7, 4, 0,193, 8,166, 0,201, 7, 83, 0,193, 6, 94, 0,115, 5, 54, 0,113, 5,150, 0,115,
+ 4,102, 0,113, 4,227,255,250, 4, 59, 0, 5, 4,227,255,252, 4,188, 0, 61, 4,227,255,252, 4,188, 0, 61, 5,123, 0, 61,
+ 4,188, 0, 59, 7,121,255,250, 6,116, 0, 5, 5,124, 0,175, 4,186, 0,150, 5,124, 0,175, 4,186, 0,150, 5,124, 0,175,
+ 5, 18, 0,186, 7,135, 0, 20, 5,211, 0, 15, 7,135, 0, 20, 5,211, 0, 15, 2, 57, 0,193, 6,232, 0, 59, 5,222, 0, 50,
+ 5, 63, 0,201, 4,213, 0,191, 6, 53, 0, 54, 5, 93, 0, 46, 6, 4, 0,201, 5, 73, 0,193, 6, 54, 0,201, 5,114, 0,193,
+ 5,124, 0,175, 4,186, 0,150, 7, 26, 0,201, 6, 50, 0,193, 5,121, 0, 16, 4,231, 0,123, 5,121, 0, 16, 4,231, 0,123,
+ 7,203, 0, 8, 7,219, 0,123, 5, 14, 0,201, 4,236, 0,113, 6, 76, 0,117, 4,236, 0, 0, 6, 76, 0,117, 4,236, 1, 43,
+ 6,232, 0, 59, 5,222, 0, 50, 5, 23, 0,156, 4, 83, 0,133, 5, 84, 0,160, 4,159, 0, 0, 5,252, 0,201, 5, 65, 0,193,
+ 5,252, 0,201, 5, 65, 0,193, 6, 76, 0,115, 4,229, 0,113, 6, 76, 0,115, 4,229, 0, 0, 6, 76, 0,115, 4,229, 1, 74,
+ 5,150, 0,111, 4,100, 0,113, 4,224, 0, 35, 4,188, 0, 61, 4,224, 0, 35, 4,188, 0, 61, 4,224, 0, 35, 4,188, 0, 61,
+ 5,124, 0,175, 4,186, 0,150, 4,117, 0,201, 3,238, 0,186, 7, 15, 0,201, 6, 31, 0,193, 5,125, 0,145, 4,183, 0,113,
+ 8, 12, 0,145, 7, 45, 0,113, 7,204, 0,201, 6,244, 0,171, 5,110, 0,201, 4,181, 0,171, 8,147, 0, 54, 7,168, 0, 46,
+ 8,148, 0,201, 7,189, 0,193, 6, 51, 0,115, 5, 71, 0, 0, 6, 47,255,250, 5,176, 0, 5, 6,239, 0,178, 5,219, 0,178,
+ 7, 15, 0,178, 7, 15, 0,178, 5,219, 0,178, 5, 38, 0,155, 5,219, 0,178, 5,219, 0,178, 6,206, 0,178, 7, 15, 0,178,
+ 5,219, 0,178, 5, 8, 0,178, 6,151, 0,178, 7,228, 0, 65, 5,219, 0,178, 5,168, 0,178, 5, 38, 0,143, 7, 15, 0,178,
+ 6, 55, 0, 92, 7, 15, 0,178, 5,219, 0,140, 6,185, 0, 92, 5,219, 0,178, 5,219, 0,178, 5,219, 0,178, 6, 83, 0,178,
+ 5, 38, 0,155, 7, 15, 0,178, 5,219, 0,178, 7, 15, 0,178, 5, 20, 0,135, 5,219, 0,178, 5,219, 0,140, 6,101, 0,178,
+ 6, 76, 0,115, 6, 82, 0, 92, 6, 76, 0,115, 5, 20, 0,135, 2,117, 0,117, 2,139, 0,178, 4, 0, 0, 94, 4, 0, 0,120,
+ 3, 34, 0,158, 4, 54, 0, 94, 4, 0, 0, 90, 7,203, 0,186, 5, 18, 0,186, 5,147, 0,113, 5,157, 0,186, 5, 18, 0,174,
+ 5,147, 0,113, 4, 68, 0,174, 5, 18, 0,186, 5,154, 0,186, 5,147, 0,113, 5, 18, 0,186, 3, 59, 0,193, 7,189, 0,186,
+ 5, 32, 0,113, 5, 18, 0,174, 5, 18, 0,186, 5, 20, 0,113, 5,157, 0,186, 5, 18, 0,174, 5, 70, 0,174, 2, 57,255,219,
+ 6, 20, 0, 49, 4, 32, 0,159, 5, 18, 0,186, 3,159, 0, 70, 7,203, 0, 0, 4, 32, 0,159, 5, 18, 0,186, 5, 18, 0,174,
+ 5,145, 0,174, 7,202, 0,174, 5, 18, 0,186, 5, 20, 0,113, 3, 59, 0,193, 7,202, 0,174, 5, 47, 0, 0, 4,229, 0,113,
+ 5, 8, 0,122, 6, 26, 0,174, 2,178, 0,240, 3,119, 0, 96, 2,149, 0,219, 5,121, 0, 16, 4,231, 0,123, 5,125, 0,201,
+ 5, 20, 0,186, 5,125, 0,201, 5, 20, 0,186, 5,125, 0,201, 5, 20, 0,186, 5,150, 0,115, 4,102, 0,113, 6, 41, 0,201,
+ 5, 20, 0,113, 6, 41, 0,201, 5, 20, 0,113, 6, 41, 0,201, 5, 20, 0,113, 6, 41, 0,201, 5, 20, 0,113, 6, 41, 0,201,
+ 5, 20, 0,113, 5, 14, 0,201, 4,236, 0,113, 5, 14, 0,201, 4,236, 0,113, 5, 14, 0,201, 4,236, 0,113, 5, 14, 0,201,
+ 4,236, 0,113, 5, 14, 0,201, 4,236, 0,113, 4,154, 0,201, 2,209, 0, 47, 6, 51, 0,115, 5, 20, 0,113, 6, 4, 0,201,
+ 5, 18, 0,186, 6, 4, 0,201, 5, 18, 0,186, 6, 4, 0,201, 5, 18,255,235, 6, 4, 0, 17, 5, 18, 0, 2, 6, 4, 0,201,
+ 5, 18, 0,186, 2, 92, 0, 0, 2, 57, 0, 39, 2, 92, 0,201, 2, 57, 0,193, 5, 63, 0,201, 4,162, 0,186, 5, 63, 0,201,
+ 4,162, 0,186, 5, 63, 0,201, 4,162, 0,186, 4,117, 0,201, 2, 57, 0,182, 4,117, 0, 3, 2, 57,255,242, 4,117, 0,201,
+ 2, 57, 0, 39, 4,117, 0,201, 2, 57,255,222, 6,231, 0,201, 7,203, 0,186, 6,231, 0,201, 7,203, 0,186, 6,231, 0,201,
+ 7,203, 0,186, 5,252, 0,201, 5, 18, 0,186, 5,252, 0,201, 5, 18, 0,186, 5,252, 0,201, 5, 18, 0,186, 5,252, 0,201,
+ 5, 18, 0,186, 6, 76, 0,115, 4,229, 0,113, 6, 76, 0,115, 4,229, 0,113, 6, 76, 0,115, 4,229, 0,113, 6, 76, 0,115,
+ 4,229, 0,113, 4,211, 0,201, 5, 20, 0,186, 4,211, 0,201, 5, 20, 0,186, 5,143, 0,201, 3, 74, 0,186, 5,143, 0,201,
+ 3, 74, 0,186, 5,143, 0,201, 3, 74, 0,186, 5,143, 0,201, 3, 74, 0, 84, 5, 20, 0,135, 4, 43, 0,111, 5, 20, 0,135,
+ 4, 43, 0,111, 5, 20, 0,135, 4, 43, 0,111, 5, 20, 0,135, 4, 43, 0,111, 5, 20, 0,135, 4, 43, 0,111, 4,227,255,250,
+ 3, 35, 0, 55, 4,227,255,250, 3, 35, 0, 55, 4,227,255,250, 3, 35, 0, 55, 4,227,255,250, 3, 35, 0, 55, 5,219, 0,178,
+ 5, 18, 0,174, 5,219, 0,178, 5, 18, 0,174, 5,219, 0,178, 5, 18, 0,174, 5,219, 0,178, 5, 18, 0,174, 5,219, 0,178,
+ 5, 18, 0,174, 5,121, 0, 16, 4,188, 0, 61, 5,121, 0, 16, 4,188, 0, 61, 7,233, 0, 68, 6,139, 0, 86, 7,233, 0, 68,
+ 6,139, 0, 86, 7,233, 0, 68, 6,139, 0, 86, 7,233, 0, 68, 6,139, 0, 86, 7,233, 0, 68, 6,139, 0, 86, 5,123, 0, 61,
+ 4,188, 0, 59, 5,123, 0, 61, 4,188, 0, 59, 4,227,255,252, 4,188, 0, 61, 5,123, 0, 92, 4, 51, 0, 88, 5,123, 0, 92,
+ 4, 51, 0, 88, 5,123, 0, 92, 4, 51, 0, 88, 5, 18, 0,186, 3, 35, 0, 4, 6,139, 0, 86, 4,188, 0, 61, 4,231, 0,123,
+ 2,209, 0, 47, 5,121, 0, 16, 4,231, 0,123, 5,121, 0, 16, 4,231, 0,123, 5,121, 0, 16, 4,231, 0,123, 5,121, 0, 16,
+ 4,231, 0,123, 5,121, 0, 16, 4,231, 0,123, 5,121, 0, 16, 4,231, 0,123, 5,121, 0, 16, 4,231, 0,123, 5,121, 0, 16,
+ 4,231, 0,123, 5,121, 0, 16, 4,231, 0,123, 5,121, 0, 16, 4,231, 0,123, 5,121, 0, 16, 4,231, 0,123, 5,121, 0, 16,
+ 4,231, 0,123, 5, 14, 0,201, 4,236, 0,113, 5, 14, 0,201, 4,236, 0,113, 5, 14, 0,201, 4,236, 0,113, 5, 14, 0,201,
+ 4,236, 0,113, 5, 14, 0,201, 4,236, 0,113, 5, 14, 0,201, 4,236, 0,113, 5, 14, 0,201, 4,236, 0,113, 5, 14, 0,201,
+ 4,236, 0,113, 2, 92, 0, 90, 2, 57, 0, 68, 2, 92, 0,200, 2, 57, 0,183, 6, 76, 0,115, 4,229, 0,113, 6, 76, 0,115,
+ 4,229, 0,113, 6, 76, 0,115, 4,229, 0,113, 6, 76, 0,115, 4,229, 0,113, 6, 76, 0,115, 4,229, 0,113, 6, 76, 0,115,
+ 4,229, 0,113, 6, 76, 0,115, 4,229, 0,113, 7, 78, 0,103, 4,229, 0,118, 7, 78, 0,103, 4,229, 0,118, 7, 78, 0,103,
+ 4,229, 0,118, 7, 78, 0,103, 4,229, 0,118, 7, 78, 0,103, 4,229, 0,118, 5,219, 0,178, 5, 18, 0,174, 5,219, 0,178,
+ 5, 18, 0,174, 6,221, 0,173, 5, 18, 0,176, 6,221, 0,173, 5, 18, 0,176, 6,221, 0,173, 5, 18, 0,176, 6,221, 0,173,
+ 5, 18, 0,176, 6,221, 0,173, 5, 18, 0,176, 4,227,255,252, 4,188, 0, 61, 4,227,255,252, 4,188, 0, 61, 4,227,255,252,
+ 4,188, 0, 61, 4,227,255,252, 4,188, 0, 61, 4, 0, 1,134, 4, 0, 1,115, 4, 0, 1,134, 4, 0, 0, 0, 8, 0, 0, 0,
+ 4, 0, 0, 0, 8, 0, 0, 0, 2,163, 0, 0, 2, 0, 0, 0, 1, 86, 0, 0, 5, 23, 0, 0, 2,139, 0, 0, 1,153, 0, 0,
+ 0,204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,227, 0,100, 2,227, 0,100,
+ 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 1, 4, 4, 0,255,236, 2,139, 0,174, 2,139, 0,178,
+ 2,139, 0,174, 2,139, 0,178, 4, 37, 0,174, 4, 37, 0,174, 4, 37, 0,174, 4, 37, 0,174, 4, 0, 0, 57, 4, 0, 0, 57,
+ 4,184, 1, 51, 4,184, 1, 51, 2,173, 0,236, 5, 87, 0,236, 8, 0, 0,236, 2,139, 0,220, 10,188, 0,113, 13,226, 0,113,
+ 1,209, 0, 40, 2,253, 0, 40, 4, 41, 0, 40, 1,209, 0, 40, 2,253, 0, 40, 4, 41, 0, 40, 2,182, 0, 11, 3, 51, 0,158,
+ 3, 51, 0,193, 6,180, 0,195, 3,226, 0,147, 4, 63, 0,147, 4, 0,255,236, 6,110,255,167, 6,110,255,167, 2, 0,255,170,
+ 8, 0, 0, 61, 4, 0, 0,221, 1, 86,254,137, 3, 31, 0,176, 3, 31, 0,176, 7, 96, 0, 73, 5,221, 0,147, 5,221, 0,147,
+ 3,240, 0,111, 5, 23, 0,236, 4, 0, 0,216, 4, 0, 0,216, 4, 0, 0, 61, 2,178, 1, 29, 6,110,255,167, 4, 0, 0, 61,
+ 3,153, 0,145, 6,180, 0,217, 6,110,255,167, 6,180, 1, 56, 4,176, 0,250, 5, 78, 0, 40, 6,180, 1,102, 6,180, 1,102,
+ 2,139, 0,219, 6, 97, 0,100, 6,180, 0,112, 2,139, 0,219, 2,139, 0,219, 3, 53, 0, 87, 1,110, 0,121, 3, 53, 0, 63,
+ 3, 53, 0,102, 3, 53, 0, 92, 3, 53, 0,108, 3, 53, 0, 89, 3, 53, 0, 83, 4, 57, 0,137, 4, 57, 0,137, 4, 57, 0,137,
+ 1,247, 0,111, 1,247, 0,103, 3, 49, 0,117, 3, 53, 0, 87, 3, 53, 0,137, 3, 53, 0, 94, 3, 53, 0, 98, 3, 53, 0, 63,
+ 3, 53, 0,102, 3, 53, 0, 92, 3, 53, 0,108, 3, 53, 0, 89, 3, 53, 0, 83, 4, 57, 0,137, 4, 57, 0,137, 4, 57, 0,137,
+ 1,247, 0,111, 1,247, 0,103, 7, 4, 0, 86, 5, 23, 0,115, 5, 23, 0, 96, 5, 23, 0,133, 5, 23, 0,129, 7,203, 0,186,
+ 5,252, 0,117, 10, 46, 0,201, 8,151, 0,201, 7,233, 0, 59, 6, 70, 0, 95, 5, 23, 0,129, 5, 23, 0, 0, 5, 23, 0, 40,
+ 5, 23, 0, 20, 8,117, 0, 27, 5, 23, 0, 68, 6, 49, 0,117, 5, 33, 0,170, 0, 0,252, 61, 0, 0,252, 61, 8, 38, 0, 67,
+ 8,252, 0,195, 5, 35,255,214, 8, 38, 0, 60, 8,137, 0, 60, 7,157, 0,195, 5, 18, 0, 72, 5, 18, 0, 34, 5,148, 0,106,
+ 3, 78,255,228, 9, 81, 0,201, 8, 0, 1, 27, 5,148, 0,110, 6,131, 0, 83, 6, 87, 0,118, 7, 44, 0,169, 8, 40, 1, 3,
+ 8,152,255,252, 8, 0, 1, 39, 6, 29, 0, 78, 6, 29, 0, 78, 5, 63, 0,201, 5,121, 0, 16, 6,214, 0,125, 4,154, 0,201,
+ 3,178, 0,104, 5,246, 0,103, 9,141, 0,151, 6, 61, 0, 59, 7,193, 0,137, 7,193, 0, 94, 7,193, 0,137, 7,193, 0, 94,
+ 7,193, 0, 98, 7,193, 0, 63, 7,193, 0,137, 7,193, 0,102, 7,193, 0,137, 7,193, 0, 98, 7,193, 0,102, 7,193, 0,108,
+ 4,139, 0,137, 2, 92, 0,201, 3,240, 0,201, 5,132, 0,201, 7, 98, 0,201, 5,121, 0, 16, 7, 97, 0, 16, 8,245, 0, 16,
+ 10,137, 0, 16, 7, 87, 0,201, 5,123, 0, 61, 7,119, 0, 61, 9, 13, 0, 61, 4,117, 0,201, 5,150, 0,115, 6, 41, 0,201,
+ 6,231, 0,201, 2, 57, 0,193, 3,169, 0,193, 5, 25, 0,193, 6,126, 0,193, 4,188, 0, 61, 6,125, 0, 61, 7,237, 0, 61,
+ 9, 93, 0, 61, 6,141, 0,193, 4,188, 0, 59, 6,148, 0, 59, 8, 4, 0, 59, 2, 57, 0,193, 4,102, 0,113, 5, 20, 0,113,
+ 7,203, 0,186, 9,246, 0,121, 6, 41, 0,201, 9,246, 0,121, 5,160, 0,115, 6,180, 0,100, 6,180, 1,163, 6,180, 0,117,
+ 6,180, 1,163, 6,180, 0,100, 6,180, 1,163, 6,180, 1, 32, 6,180, 1, 32, 6,180, 1, 32, 6,180, 1, 32, 6,180, 0,100,
+ 6,180, 0,217, 6,180, 0,217, 6,180, 0,217, 1, 86,254,137, 5, 24, 1,138, 5, 2, 0,190, 5, 2, 1, 68, 2,139, 0,219,
+ 5, 25, 0, 61, 5, 25, 0, 61, 5, 25, 0, 61, 5,106, 0,221, 6,170, 0,221, 8, 0, 0,247, 6,180, 0,217, 8, 0, 0,172,
+ 3, 31, 0,183, 3, 31, 0,164, 7, 44, 0,152, 7, 44, 0,152, 7, 44, 0,152, 7, 44, 0,152, 7, 44, 0,152, 7, 44, 0,152,
+ 7, 44, 0,152, 7, 44, 0,152, 7, 44, 0,152, 7, 44, 0,152, 7, 44, 0,170, 5, 30, 0,170, 5,220, 0, 0, 5,131, 0, 47,
+ 5, 10, 0, 47, 5, 10, 0, 47, 7,188, 0, 47, 7,188, 0, 47, 5,125, 0, 47, 6,227, 0,111, 9,157, 0,170, 9,157, 0,174,
+ 9,145, 0,174, 9,125, 0,174, 12, 60, 0,174, 8, 52, 0, 30, 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, 3, 0, 0, 0, 3, 0, 0, 0, 28,
+ 0, 1, 0, 0, 0, 0, 2,132, 0, 3, 0, 1, 0, 0, 0, 28, 0, 4, 2,104, 0, 0, 0,150, 0,128, 0, 6, 0, 22, 0, 0,
+ 0,126, 2, 65, 2, 89, 2, 98, 2,112, 2,117, 2,146, 2,233, 2,238, 2,243, 2,247, 3, 78, 3, 83, 3, 88, 3, 93, 3, 98,
+ 3,117, 3,122, 3,126, 3,138, 3,140, 3,161, 3,206, 4,134, 4,206, 4,249, 5, 15, 5, 86, 5, 95, 5,135, 5,138, 6, 12,
+ 30,155, 30,249, 31,191, 31,254, 32, 39, 32, 94, 32,113, 32,142, 32,175, 32,177, 32,181, 32,215, 33, 0, 33, 6, 33, 9, 33, 15,
+ 33, 17, 33, 19, 33, 24, 33, 30, 33, 34, 33, 39, 33, 43, 33, 46, 33, 50, 33, 53, 33, 59, 33, 75, 33,131, 33,153, 33,181, 34, 30,
+ 35, 25, 35, 37, 35, 42, 36,105, 38,177, 40, 0,251, 6,251, 23,255,253,255,255, 0, 0, 0, 0, 0, 32, 0,160, 2, 89, 2, 98,
+ 2,112, 2,117, 2,146, 2,176, 2,236, 2,243, 2,247, 3, 0, 3, 81, 3, 87, 3, 92, 3, 96, 3,116, 3,122, 3,126, 3,132,
+ 3,140, 3,142, 3,163, 3,208, 4,136, 4,208, 5, 0, 5, 49, 5, 89, 5, 97, 5,137, 6, 12, 30, 0, 30,160, 31,191, 31,253,
+ 32, 0, 32, 48, 32,112, 32,116, 32,160, 32,177, 32,180, 32,214, 33, 0, 33, 3, 33, 9, 33, 14, 33, 17, 33, 19, 33, 22, 33, 28,
+ 33, 32, 33, 38, 33, 42, 33, 46, 33, 50, 33, 52, 33, 59, 33, 75, 33, 83, 33,144, 33,181, 34, 18, 35, 24, 35, 37, 35, 41, 36, 96,
+ 38,176, 40, 0,251, 0,251, 19,255,253,255,255, 0, 0,255,227,255,194,255,171,255,163,255,150,255,146,255,118,255, 89,255, 87,
+255, 83,255, 80,255, 72,255, 70,255, 67,255, 64,255, 62,255, 45,255, 41,255, 38,255, 33,255, 32,255, 31,255, 30,255, 29,255, 28,
+255, 27,255, 21,254,244,254,242,254,241,254,240,254,111,230,124,230,120,229,179,229,118,229,117,229,109,229, 92,229, 90,229, 73,
+229, 72,229, 70,229, 38,228,254,228,252,228,250,228,246,228,245,228,244,228,242,228,239,228,238,228,235,228,233,228,231,228,228,
+228,227,228,222,228,207,228,200,228,188,228,161,228, 69,227, 76,227, 65,227, 62,226, 9,223,195,222,117, 11,118, 11,106, 6,133,
+ 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 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, 6, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 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, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 0,134,135,
+137,139,147,152,158,163,162,164,166,165,167,169,171,170,172,173,175,174,176,177,179,181,180,182,184,183,188,187,189,190, 0,114,
+100,101,105, 0,120,161,112,107, 0,118,106, 0,136,154, 0,115, 0, 0,103,119, 0, 0, 0, 0, 0,108,124, 0,168,186,129, 99,
+110, 0, 0, 0, 0,109,125, 0, 98,130,133,151, 0, 0, 0, 0, 0, 0, 0, 0,185, 0,193, 0, 0, 0, 0, 0, 0, 0, 0,121,
+ 0, 0, 0,132,140,131,141,138,143,144,145,142,149,150, 0,148,156,157,155, 0, 0, 0,113, 0, 0, 0,122, 0, 0, 0, 0, 0,
+183, 7, 6, 5, 4, 3, 2, 1, 0, 44, 32, 16,176, 2, 37, 73,100,176, 64, 81, 88, 32,200, 89, 33, 45, 44,176, 2, 37, 73,100,
+176, 64, 81, 88, 32,200, 89, 33, 45, 44, 32, 16, 7, 32,176, 0, 80,176, 13,121, 32,184,255,255, 80, 88, 4, 27, 5, 89,176, 5,
+ 28,176, 3, 37, 8,176, 4, 37, 35,225, 32,176, 0, 80,176, 13,121, 32,184,255,255, 80, 88, 4, 27, 5, 89,176, 5, 28,176, 3,
+ 37, 8,225, 45, 44, 75, 80, 88, 32,176,253, 69, 68, 89, 33, 45, 44,176, 2, 37, 69, 96, 68, 45, 44, 75, 83, 88,176, 2, 37,176,
+ 2, 37, 69, 68, 89, 33, 33, 45, 44, 69, 68, 45, 44,176, 2, 37,176, 2, 37, 73,176, 5, 37,176, 5, 37, 73, 96,176, 32, 99,104,
+ 32,138, 16,138, 35, 58,138, 16,101, 58, 45, 0,184, 2,128, 64,255,251,254, 3,250, 20, 3,249, 37, 3,248, 50, 3,247,150, 3,
+246, 14, 3,245,254, 3,244,254, 3,243, 37, 3,242, 14, 3,241,150, 3,240, 37, 3,239,138, 65, 5,239,254, 3,238,150, 3,237,
+150, 3,236,250, 3,235,250, 3,234,254, 3,233, 58, 3,232, 66, 3,231,254, 3,230, 50, 3,229,228, 83, 5,229,150, 3,228,138,
+ 65, 5,228, 83, 3,227,226, 47, 5,227,250, 3,226, 47, 3,225,254, 3,224,254, 3,223, 50, 3,222, 20, 3,221,150, 3,220,254,
+ 3,219, 18, 3,218,125, 3,217,187, 3,216,254, 3,214,138, 65, 5,214,125, 3,213,212, 71, 5,213,125, 3,212, 71, 3,211,210,
+ 27, 5,211,254, 3,210, 27, 3,209,254, 3,208,254, 3,207,254, 3,206,254, 3,205,150, 3,204,203, 30, 5,204,254, 3,203, 30,
+ 3,202, 50, 3,201,254, 3,198,133, 17, 5,198, 28, 3,197, 22, 3,196,254, 3,195,254, 3,194,254, 3,193,254, 3,192,254, 3,
+191,254, 3,190,254, 3,189,254, 3,188,254, 3,187,254, 3,186, 17, 3,185,134, 37, 5,185,254, 3,184,183,187, 5,184,254, 3,
+183,182, 93, 5,183,187, 3,183,128, 4,182,181, 37, 5,182, 93, 64,255, 3,182, 64, 4,181, 37, 3,180,254, 3,179,150, 3,178,
+254, 3,177,254, 3,176,254, 3,175,254, 3,174,100, 3,173, 14, 3,172,171, 37, 5,172,100, 3,171,170, 18, 5,171, 37, 3,170,
+ 18, 3,169,138, 65, 5,169,250, 3,168,254, 3,167,254, 3,166,254, 3,165, 18, 3,164,254, 3,163,162, 14, 5,163, 50, 3,162,
+ 14, 3,161,100, 3,160,138, 65, 5,160,150, 3,159,254, 3,158,157, 12, 5,158,254, 3,157, 12, 3,156,155, 25, 5,156,100, 3,
+155,154, 16, 5,155, 25, 3,154, 16, 3,153, 10, 3,152,254, 3,151,150, 13, 5,151,254, 3,150, 13, 3,149,138, 65, 5,149,150,
+ 3,148,147, 14, 5,148, 40, 3,147, 14, 3,146,250, 3,145,144,187, 5,145,254, 3,144,143, 93, 5,144,187, 3,144,128, 4,143,
+142, 37, 5,143, 93, 3,143, 64, 4,142, 37, 3,141,254, 3,140,139, 46, 5,140,254, 3,139, 46, 3,138,134, 37, 5,138, 65, 3,
+137,136, 11, 5,137, 20, 3,136, 11, 3,135,134, 37, 5,135,100, 3,134,133, 17, 5,134, 37, 3,133, 17, 3,132,254, 3,131,130,
+ 17, 5,131,254, 3,130, 17, 3,129,254, 3,128,254, 3,127,254, 3, 64,255,126,125,125, 5,126,254, 3,125,125, 3,124,100, 3,
+123, 84, 21, 5,123, 37, 3,122,254, 3,121,254, 3,120, 14, 3,119, 12, 3,118, 10, 3,117,254, 3,116,250, 3,115,250, 3,114,
+250, 3,113,250, 3,112,254, 3,111,254, 3,110,254, 3,108, 33, 3,107,254, 3,106, 17, 66, 5,106, 83, 3,105,254, 3,104,125,
+ 3,103, 17, 66, 5,102,254, 3,101,254, 3,100,254, 3, 99,254, 3, 98,254, 3, 97, 58, 3, 96,250, 3, 94, 12, 3, 93,254, 3,
+ 91,254, 3, 90,254, 3, 89, 88, 10, 5, 89,250, 3, 88, 10, 3, 87, 22, 25, 5, 87, 50, 3, 86,254, 3, 85, 84, 21, 5, 85, 66,
+ 3, 84, 21, 3, 83, 1, 16, 5, 83, 24, 3, 82, 20, 3, 81, 74, 19, 5, 81,254, 3, 80, 11, 3, 79,254, 3, 78, 77, 16, 5, 78,
+254, 3, 77, 16, 3, 76,254, 3, 75, 74, 19, 5, 75,254, 3, 74, 73, 16, 5, 74, 19, 3, 73, 29, 13, 5, 73, 16, 3, 72, 13, 3,
+ 71,254, 3, 70,150, 3, 69,150, 3, 68,254, 3, 67, 2, 45, 5, 67,250, 3, 66,187, 3, 65, 75, 3, 64,254, 3, 63,254, 3, 62,
+ 61, 18, 5, 62, 20, 3, 61, 60, 15, 5, 61, 18, 3, 60, 59, 13, 5, 60, 64,255, 15, 3, 59, 13, 3, 58,254, 3, 57,254, 3, 56,
+ 55, 20, 5, 56,250, 3, 55, 54, 16, 5, 55, 20, 3, 54, 53, 11, 5, 54, 16, 3, 53, 11, 3, 52, 30, 3, 51, 13, 3, 50, 49, 11,
+ 5, 50,254, 3, 49, 11, 3, 48, 47, 11, 5, 48, 13, 3, 47, 11, 3, 46, 45, 9, 5, 46, 16, 3, 45, 9, 3, 44, 50, 3, 43, 42,
+ 37, 5, 43,100, 3, 42, 41, 18, 5, 42, 37, 3, 41, 18, 3, 40, 39, 37, 5, 40, 65, 3, 39, 37, 3, 38, 37, 11, 5, 38, 15, 3,
+ 37, 11, 3, 36,254, 3, 35,254, 3, 34, 15, 3, 33, 1, 16, 5, 33, 18, 3, 32,100, 3, 31,250, 3, 30, 29, 13, 5, 30,100, 3,
+ 29, 13, 3, 28, 17, 66, 5, 28,254, 3, 27,250, 3, 26, 66, 3, 25, 17, 66, 5, 25,254, 3, 24,100, 3, 23, 22, 25, 5, 23,254,
+ 3, 22, 1, 16, 5, 22, 25, 3, 21,254, 3, 20,254, 3, 19,254, 3, 18, 17, 66, 5, 18,254, 3, 17, 2, 45, 5, 17, 66, 3, 16,
+125, 3, 15,100, 3, 14,254, 3, 13, 12, 22, 5, 13,254, 3, 12, 1, 16, 5, 12, 22, 3, 11,254, 3, 10, 16, 3, 9,254, 3, 8,
+ 2, 45, 5, 8,254, 3, 7, 20, 3, 6,100, 3, 4, 1, 16, 5, 4,254, 3, 64, 21, 3, 2, 45, 5, 3,254, 3, 2, 1, 16, 5,
+ 2, 45, 3, 1, 16, 3, 0,254, 3, 1,184, 1,100,133,141, 1, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 0, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 29, 1, 53, 0,184, 0,203, 0,203, 0,193, 0,170,
+ 0,156, 1,166, 0,184, 0,102, 0, 0, 0,113, 0,203, 0,160, 2,178, 0,133, 0,117, 0,184, 0,195, 1,203, 1,137, 2, 45,
+ 0,203, 0,166, 0,240, 0,211, 0,170, 0,135, 0,203, 3,170, 4, 0, 1, 74, 0, 51, 0,203, 0, 0, 0,217, 5, 2, 0,244,
+ 1, 84, 0,180, 0,156, 1, 57, 1, 20, 1, 57, 7, 6, 4, 0, 4, 78, 4,180, 4, 82, 4,184, 4,231, 4,205, 0, 55, 4,115,
+ 4,205, 4, 96, 4,115, 1, 51, 3,162, 5, 86, 5,166, 5, 86, 5, 57, 3,197, 2, 18, 0,201, 0, 31, 0,184, 1,223, 0,115,
+ 0,186, 3,233, 3, 51, 3,188, 4, 68, 4, 14, 0,223, 3,205, 3,170, 0,229, 3,170, 4, 4, 0, 0, 0,203, 0,143, 0,164,
+ 0,123, 0,184, 0, 20, 1,111, 0,127, 2,123, 2, 82, 0,143, 0,199, 5,205, 0,154, 0,154, 0,111, 0,203, 0,205, 1,158,
+ 1,211, 0,240, 0,186, 1,131, 0,213, 0,152, 3, 4, 2, 72, 0,158, 1,213, 0,193, 0,203, 0,246, 0,131, 3, 84, 2,127,
+ 0, 0, 3, 51, 2,102, 0,211, 0,199, 0,164, 0,205, 0,143, 0,154, 0,115, 4, 0, 5,213, 1, 10, 0,254, 2, 43, 0,164,
+ 0,180, 0,156, 0, 0, 0, 98, 0,156, 0, 0, 0, 29, 3, 45, 5,213, 5,213, 5,213, 5,240, 0,127, 0,123, 0, 84, 0,164,
+ 6,184, 6, 20, 7, 35, 1,211, 0,184, 0,203, 0,166, 1,195, 1,236, 6,147, 0,160, 0,211, 3, 92, 3,113, 3,219, 1,133,
+ 4, 35, 4,168, 4, 72, 0,143, 1, 57, 1, 20, 1, 57, 3, 96, 0,143, 5,213, 1,154, 6, 20, 7, 35, 6,102, 1,121, 4, 96,
+ 4, 96, 4, 96, 4,123, 0,156, 0, 0, 2,119, 4, 96, 1,170, 0,233, 4, 96, 7, 98, 0,123, 0,197, 0,127, 2,123, 0, 0,
+ 0,180, 2, 82, 5,205, 0,102, 0,188, 0,102, 0,119, 6, 16, 0,205, 1, 59, 1,133, 3,137, 0,143, 0,123, 0, 0, 0, 29,
+ 0,205, 7, 74, 4, 47, 0,156, 0,156, 0, 0, 7,125, 0,111, 0, 0, 0,111, 3, 53, 0,106, 0,111, 0,123, 0,174, 0,178,
+ 0, 45, 3,150, 0,143, 2,123, 0,246, 0,131, 3, 84, 6, 55, 5,246, 0,143, 0,156, 4,225, 2,102, 0,143, 1,141, 2,246,
+ 0,205, 3, 68, 0, 41, 0,102, 4,238, 0,115, 0, 0, 20, 0, 0,150, 0, 0, 0, 0, 0, 34, 0, 34, 0, 34, 0, 34, 0, 84,
+ 0,138, 0,246, 1,162, 2, 54, 3,106, 3,148, 3,204, 3,248, 4, 70, 4,112, 4,140, 4,162, 4,182, 4,220, 5, 30, 5, 86,
+ 5,212, 6, 72, 6,166, 7, 6, 7,114, 7,184, 8, 34, 8,140, 8,172, 8,212, 9, 16, 9, 50, 9,110, 9,218, 10,154, 11, 20,
+ 11,108, 11,184, 11,248, 12, 40, 12, 82, 12,166, 12,212, 12,248, 13, 48, 13,196, 13,230, 14,100, 14,184, 14,254, 15, 62, 15,164,
+ 16, 46, 16,170, 16,226, 17, 36, 17,148, 18,114, 18,196, 19, 38, 19,134, 19,182, 19,220, 20, 6, 20, 40, 20, 62, 20,102, 20,252,
+ 21, 72, 21,148, 21,224, 22, 74, 22,150, 22,250, 23, 54, 23, 94, 23,156, 24, 20, 24, 50, 24,148, 24,208, 25, 34, 25,114, 25,194,
+ 25,250, 26,170, 26,232, 27, 36, 27,182, 28,200, 29,138, 30,112, 30,214, 31, 68, 31, 92, 31,210, 32, 20, 32, 20, 32, 92, 32,194,
+ 33, 30, 33,170, 34, 60, 34, 96, 35, 4, 35, 96, 35,242, 36, 96, 36,198, 36,226, 36,248, 37,158, 37,196, 38, 0, 38, 56, 38,136,
+ 38,230, 39, 14, 39,104, 39,150, 39,172, 39,220, 40, 8, 40, 76, 40,180, 40,196, 40,212, 40,228, 41, 96, 41,108, 41,120, 41,142,
+ 41,166, 41,190, 42, 94, 42,202, 42,214, 42,226, 42,238, 43, 0, 43, 18, 43, 30, 43, 42, 43, 60, 43, 78, 43,180, 43,204, 43,216,
+ 43,228, 43,250, 44, 20, 44, 44, 44,144, 45, 44, 45, 56, 45, 68, 45, 92, 45,120, 45,132, 45,200, 46, 92, 46,110, 46,128, 46,144,
+ 46,166, 46,194, 46,226, 47,192, 47,204, 47,216, 47,228, 47,246, 48, 8, 48, 20, 48, 32, 48, 50, 48, 68, 49, 28, 49, 40, 49, 52,
+ 49, 64, 49, 80, 49,102, 49,124, 49,170, 50,100, 50,112, 50,124, 50,140, 50,164, 50,176, 51, 0, 51, 24, 51, 46, 51, 66, 51, 88,
+ 51,104, 51,116, 51,128, 51,140, 51,152, 51,170, 51,182, 51,194, 51,206, 51,224, 51,236, 51,248, 52, 12, 52, 20, 52,114, 52,126,
+ 52,144, 52,162, 52,180, 52,192, 52,204, 52,216, 52,228, 52,246, 53, 12, 53, 30, 53, 48, 53, 60, 53, 72, 53, 90, 53,102, 53,114,
+ 53,126, 53,150, 53,184, 53,252, 54, 70, 54, 88, 54,106, 54,124, 54,142, 54,160, 54,178, 54,190, 54,202, 54,226, 55, 0, 55, 18,
+ 55, 36, 55, 54, 55, 72, 55, 84, 55, 96, 55,216, 55,228, 56, 0, 56, 12, 56, 30, 56, 42, 56, 60, 56, 72, 56, 98, 56,160, 56,232,
+ 56,250, 57, 12, 57, 24, 57, 36, 57, 60, 57, 82, 57, 94, 57,166, 57,244, 58, 10, 58, 26, 58, 48, 58, 64, 58, 76, 58, 88, 58,168,
+ 59, 60, 59, 72, 59, 84, 59, 96, 59,108, 59,126, 59,146, 59,158, 59,170, 59,190, 59,208, 59,220, 59,232, 59,252, 60, 14, 60, 26,
+ 60, 38, 60, 60, 60, 78, 60,144, 60,220, 60,242, 61, 4, 61, 28, 61, 46, 61, 68, 61, 86, 61,104, 61,122, 61,134, 61,146, 61,158,
+ 61,170, 61,188, 61,206, 61,224, 61,240, 62, 2, 62, 14, 62, 26, 62, 38, 62, 50, 62, 62, 62, 82, 62,126, 62,228, 63, 72, 63, 80,
+ 63,170, 63,240, 64, 68, 64,140, 64,202, 65, 0, 65, 8, 65, 82, 65,144, 65,192, 66, 8, 66, 54, 66,142, 66,234, 67, 42, 67,134,
+ 67,234, 68,116, 68,212, 69, 2, 69, 58, 69, 98, 69,230, 70, 22, 70, 58, 70,112, 70,216, 70,224, 71, 48, 71, 60, 71, 72, 71,130,
+ 71,184, 72, 4, 72,102, 72,164, 72,226, 73,134, 73,142, 73,196, 73,240, 74, 56, 74,134, 74,204, 74,216, 74,228, 75, 58, 75,106,
+ 75,142, 75,186, 75,222, 76, 2, 76, 62, 76,122, 76,180, 76,234, 77, 32, 77, 96, 77,156, 77,214, 78, 0, 78, 14, 78, 26, 78, 60,
+ 78, 68, 78, 80, 78, 92, 78,104, 78,116, 78,128, 78,140, 78,152, 78,164, 78,176, 78,192, 78,208, 78,228, 78,248, 79, 4, 79, 20,
+ 79, 36, 79, 54, 79, 66, 79, 78, 79, 90, 79,102, 79,114, 79,126, 79,138, 79,150, 79,158, 79,170, 79,182, 79,194, 79,206, 79,218,
+ 79,230, 80, 38, 80,118, 80,140, 80,152, 80,164, 80,198, 80,210, 80,222, 80,234, 80,246, 81, 2, 81, 14, 81, 34, 81, 46, 81, 58,
+ 81, 70, 81, 84, 81, 96, 81,146, 81,190, 81,202, 81,214, 81,226, 81,238, 81,250, 82, 6, 82, 18, 82, 30, 82, 42, 82, 54, 82, 66,
+ 82, 78, 82, 90, 82,102, 82,114, 82,126, 82,138, 82,150, 82,162, 82,174, 82,186, 82,198, 82,210, 82,222, 82,234, 82,246, 83, 2,
+ 83, 14, 83, 26, 83, 38, 83, 50, 83, 62, 83, 74, 83, 86, 83, 98, 83,110, 83,186, 84, 8, 84, 20, 84, 54, 84, 94, 84,176, 85, 10,
+ 85, 92, 85,130, 85,168, 85,180, 85,192, 85,204, 85,216, 85,228, 85,240, 85,252, 86, 8, 86, 20, 86, 32, 86, 44, 86, 56, 86, 68,
+ 86, 80, 86,122, 86,188, 86,240, 87, 34, 87,112, 87,190, 87,246, 88, 62, 88,128, 88,154, 88,194, 89, 22, 89, 66, 89,108, 89,108,
+ 89,108, 89,108, 89,108, 89,108, 89,166, 89,238, 90, 30, 90, 78, 90,116, 90,166, 90,220, 90,248, 91, 26, 91, 34, 91, 42, 91, 50,
+ 91, 58, 91, 76, 91,104, 91,134, 91,180, 91,228, 91,248, 92, 12, 92, 32, 92, 52, 92, 98, 92,144, 92,168, 92,176, 92,190, 92,206,
+ 92,230, 92,240, 93, 0, 93, 14, 93, 34, 93, 48, 93, 58, 93, 68, 93, 86, 93,104, 93,126, 93,140, 93,210, 93,234, 94, 32, 94, 80,
+ 94,176, 94,230, 95, 2, 95, 28, 95, 70, 95, 90, 95,166, 95,194, 95,242, 96, 12, 96, 50, 96, 82, 96,120, 96,146, 96,156, 96,168,
+ 96,188, 96,198, 96,244, 96,254, 97, 8, 97, 18, 97, 28, 97, 38, 97, 48, 97, 58, 97, 68, 97, 78, 97,136, 97,146, 97,156, 97,166,
+ 97,180, 97,194, 97,216, 97,230, 97,240, 98, 4, 98, 24, 98, 42, 98, 56, 98, 66, 98, 76, 98, 94, 98,112, 98,128, 98,186, 98,214,
+ 98,232, 98,250, 99, 16, 99, 30, 99, 54, 99, 78, 99, 88, 99, 98, 99,108, 99,126, 99,136, 99,146, 99,160, 99,178, 99,214, 99,224,
+ 99,234, 99,244, 99,254,100, 8,100, 18,100, 28,100, 38,100, 84,100, 98,100,112,100,128,100,144,100,154,100,164,100,186,100,222,
+100,248,101, 40,101, 54,101, 64,101, 74,101, 84,101, 94,101,104,101,114,101,132,101,152,101,172,101,188,101,250,102, 14,102, 26,
+102, 54,102, 74,102,106,102,118,102,128,102,160,102,170,102,180,102,190,102,248,103, 2,103, 22,103, 46,103, 70,103, 96,103,104,
+103,144,103,168,103,180,103,188,103,202,103,216,103,230,103,242,104, 0,104, 12,104, 24,104, 32,104, 40,104, 68,104,122,104,130,
+104,138,104,146,104,234,104,242,104,250,105, 44,105, 52,105, 60,105,108,105,116,105,124,105,132,105,194,105,202,105,210,105,218,
+105,226,106, 44,106,132,106,150,106,168,106,180,106,192,106,204,106,216,106,228,107,144,107,228,108, 36,108,150,108,254,109, 80,
+109,142,109,234,110, 18,110, 82,110,148,110,156,110,228,111, 66,111, 74,111,136,111,210,112, 40,112,116,112,164,112,234,113, 78,
+113,184,114, 2,114, 80,114, 92,114,104,114,116,114,128,114,140,114,228,115, 40,115, 92,115,106,115,118,115,218,116, 16,116, 96,
+116,150,116,200,117, 2,117, 56,117, 64,117,118,117,164,117,186,117,248,118, 38,118,134,118,200,118,252,119, 40,119,102,119,218,
+120, 22,120, 78,120,168,121, 2,121, 76,121,152,121,182,121,210,122, 26,122, 80,122, 88,122, 96,122,154,122,210,123, 8,123, 16,
+123, 24,123, 32,123, 62,123, 92,123,148,123,156,123,168,123,180,123,192,123,204,123,250,124, 6,124, 96,124,104,124,112,124,130,
+124,138,124,196,124,246,125, 26,125, 38,125, 50,125, 62,125, 86,125, 94,125,158,125,166,125,194,126, 10,126, 18,126,118,126,126,
+126,212,126,224,126,232,127, 26,127, 34,127, 42,127, 50,127, 86,127, 94,127,102,127,110,127,178,128, 18,128, 26,128, 70,128,118,
+128,162,128,216,129, 24,129, 44,129,102,129,192,130, 32,130,116,130,124,130,234,131, 64,131, 92,131,162,131,170,132, 14,132,116,
+132,172,132,184,132,246,133, 40,133,108,133,152,133,160,133,200,133,208,133,216,133,254,134, 6,134,142,134,150,134,194,134,242,
+135, 30,135, 84,135,150,135,170,135,230,136, 22,136,110,136,200,136,212,136,224,137, 26,137, 38,137,114,137,122,137,130,137,148,
+137,156,137,214,138, 10,138, 56,138, 68,138, 80,138, 92,138,116,138,196,138,204,138,212,139, 8,139, 80,139,136,139,172,139,208,
+140, 0,140, 48,140,100,140,152,140,214,141, 18,141,124,141,240,141,248,142, 0,142, 66,142,132,142,172,143,114,143,170,143,182,
+143,190,143,198,144, 66,144,184,144,196,144,208,145, 50,145,118,145,164,145,206,146, 0,146, 76,146,108,146,126,146,144,146,190,
+147, 28,147, 58,147,108,147,156,147,208,147,254,148, 58,148, 90,148,122,148,148,148,174,148,218,149, 10,149, 58,149,106,149,118,
+149,130,149,162,149,192,149,230,150, 10,150, 46,150, 82,150,114,150,144,150,174,150,204,150,232,151, 4,151, 52,151,102,151,200,
+152, 38,152, 50,152, 62,152, 86,152,110,152,118,152,142,152,174,152,206,152,242,153, 22,153, 52,153, 82,153,118,153,154,153,194,
+153,232,154, 8,154, 16,154, 88,154,156,154,168,154,180,154,188,154,206,154,224,155, 14,155, 64,155,102,155,144,155,182,155,218,
+155,248,156, 22,156, 58,156, 94,156,132,156,170,156,192,156,208,156,232,157, 4,157, 12,157, 20,157, 38,157, 56,157, 64,157, 72,
+157, 84,157, 96,157,114,157,126,157,138,157,150,157,158,157,166,157,178,157,190,157,202,157,214,157,238,158, 4,158, 12,158, 20,
+158, 32,158, 44,158, 56,158, 68,158, 80,158, 92,158,104,158,116,158,128,158,140,158,152,158,164,158,186,158,208,158,220,158,232,
+159, 18,159, 60,159,136,159,206,160, 30,160,108,160,170,160,232,161, 32,161, 86,161, 94,161,140,161,148,161,156,161,198,161,240,
+162, 36,162, 86,162,150,162,200,162,250,163, 64,163,110,163,160,163,244,164, 52,164, 86,164,116,164,162,164,240,165, 18,165, 54,
+165,144,165,192,166, 2,166, 52,166,120,166,170,166,226,167, 4,167, 60,167,102,167,174,167,224,167,232,168, 24,168, 32,168, 66,
+168,154,168,190,168,198,169, 30,169, 38,169,114,169,122,169,130,169,144,169,176,169,184,169,222,169,240,170, 88,170,158,170,242,
+171, 54,171,128,171,210,172, 10,172, 76,172,200,173, 22,173, 82,173,114,173,226,174, 92,174,154,174,162,175, 34,175,100,175,218,
+176, 58,176, 66,176,154,176,250,177, 2,177,104,177,112,177,228,178, 70,178, 78,178,144,178,252,179, 58,179, 66,179, 96,179,206,
+180, 50,180, 58,180,204,181, 12,181, 44,181, 70,181, 86,181, 98,181,110,181,122,181,134,181,146,181,158,181,170,181,182,181,196,
+181,208,181,220,181,232,181,244,182, 0,182, 12,182, 24,182, 36,182, 48,182, 60,182, 72,182, 84,182, 96,182,108,182,120,182,132,
+182,144,182,156,182,168,182,186,182,202,182,214,182,226,182,238,182,250,183, 6,183, 18,183, 30,183, 42,183, 54,183, 66,183, 78,
+183, 90,183,102,183,114,183,126,183,140,183,152,183,164,183,178,183,190,183,202,183,214,183,226,183,238,183,250,184, 6,184, 22,
+184, 34,184, 46,184, 60,184, 72,184, 84,184, 98,184,110,184,122,184,134,184,146,184,158,184,170,184,182,184,194,184,206,184,218,
+184,230,184,242,184,254,185, 10,185, 22,185, 34,185, 50,185, 62,185, 74,185, 86,185, 98,185,112,185,124,185,136,185,148,185,160,
+185,172,185,184,185,196,185,210,185,222,185,234,185,246,186, 2,186, 14,186, 26,186, 38,186, 56,186, 72,186, 84,186, 96,186,108,
+186,120,186,132,186,144,186,156,186,168,186,180,186,194,186,206,186,218,186,230,186,242,186,254,187, 10,187, 22,187, 34,187, 46,
+187, 58,187, 70,187, 82,187, 94,187,106,187,118,187,130,187,142,187,154,187,166,187,178,187,190,187,202,187,214,187,226,187,238,
+187,250,188, 6,188, 18,188, 30,188, 42,188, 54,188, 66,188, 80,188, 92,188,104,188,116,188,128,188,140,188,152,188,164,188,176,
+188,188,188,200,188,212,188,224,188,236,188,248,189, 4,189, 16,189, 28,189, 40,189, 52,189, 64,189, 76,189, 88,189,100,189,112,
+189,124,189,136,189,148,189,160,189,172,189,184,189,196,189,208,189,220,189,232,189,244,190, 0,190, 12,190, 24,190, 36,190, 50,
+190, 62,190, 74,190, 86,190, 98,190,110,190,122,190,134,190,146,190,158,190,170,190,186,190,198,190,210,190,222,190,234,190,246,
+191, 2,191, 14,191, 26,191, 38,191, 50,191, 62,191, 74,191, 86,191, 98,191,110,191,122,191,134,191,150,191,162,191,174,191,186,
+191,198,191,210,191,222,191,234,191,246,192, 2,192, 14,192, 26,192, 38,192, 50,192, 62,192, 74,192, 86,192, 98,192,110,192,122,
+192,134,192,146,192,158,192,170,192,182,192,194,192,206,192,218,192,230,192,242,192,254,193, 12,193, 24,193, 80,193, 88,193,142,
+193,142,193,142,193,142,193,142,193,142,193,142,193,142,193,142,193,142,193,142,193,142,193,142,193,142,193,142,193,142,193,142,
+193,164,193,172,193,194,193,216,193,236,194, 0,194, 12,194, 24,194, 54,194, 84,194,112,194,130,194,176,194,222,195, 12,195, 38,
+195, 82,195,148,195,180,195,194,195,206,195,224,196, 10,196, 22,196,220,197,100,197,116,197,128,197,144,197,158,197,170,197,186,
+197,204,198, 4,198, 62,198, 86,198,100,198,162,198,172,198,220,199, 12,199, 34,199, 52,199, 64,199,100,199,124,199,148,199,160,
+199,172,199,186,199,220,199,248,200, 16,200, 40,200, 50,200, 72,200, 84,200, 98,200,116,200,124,200,134,200,176,200,202,200,222,
+200,254,201, 36,201, 54,201, 84,201,134,201,158,201,188,201,230,202, 8,202,142,202,192,203, 8,203, 28,203,116,203,186,203,212,
+203,226,203,246,204, 18,204, 48,204,106,204,116,204,126,204,136,204,146,204,156,204,166,204,176,204,186,204,196,204,206,204,216,
+204,226,204,236,204,246,205, 0,205, 58,205,146,205,218,205,250,206, 46,206,112,206,178,207, 36,207,140,207,226,208, 20,208, 32,
+208,250,209, 30,209, 74,209,174,209,250,210, 74,210,148,210,168,210,188,211, 28,211, 42,211,190,212, 12,212, 88,212,100,212,146,
+212,198,213, 16,213, 80,213, 92,213,176,214, 10,214,136,214,222,215,106,215,186,215,234,216, 48,216, 56,216,112,216,120,216,128,
+216,196,216,218,217, 4,217, 88,217,154,217,232,217,248,218, 8,218, 24,218, 40,218, 56,218, 72,218, 88,218,104,218,120,218,136,
+218,152,218,168,218,180,218,188,218,200,218,216,218,228,218,236,218,248,219, 8,219, 28,219, 40,219, 48,219, 60,219, 76,219, 84,
+219, 92,219,100,219,108,219,116,219,128,219,144,219,156,219,164,219,176,219,192,219,212,219,224,219,232,219,244,220, 4,220, 12,
+220, 20,220, 28,220, 36,220,102,221, 36,221,146,221,154,221,242,222, 74,222,162,222,250,223,138,224, 28,224, 52,224, 76,224,100,
+224,124,224,152,224,174,224,204,225, 22,225, 58,225, 68,225, 78,225, 88,225,110,225,158,225,170,225,182,225,242,226,184,227, 54,
+227, 72,227,100,227,120,227,140,228, 68,229, 70,230,142,231, 86,232, 92,233,142,234, 74,235,200,236,252,238, 50,238, 74,238,126,
+238,126,238,214,239, 32,239, 96,239,208,240, 48,240,112,240,236,241, 84,241,168,241,246,242, 78,242,178,242,248,242,248,242,248,
+242,248,242,248,242,248,242,248,242,248,242,248,242,248,242,248,242,248,242,248,242,248,242,248,242,248,242,248,242,248,242,248,
+242,248,242,248,242,248,242,248,242,248,242,248,242,248,242,248,242,248,242,248,242,248,242,248,242,248,242,248, 0, 2, 0,102,
+254,150, 4,102, 5,164, 0, 3, 0, 7, 0, 26, 64, 12, 4,251, 0, 6,251, 1, 8, 5,127, 2, 4, 0, 47,196,212,236, 49, 0,
+ 16,212,236,212,236, 48, 19, 17, 33, 17, 37, 33, 17, 33,102, 4, 0,252,115, 3, 27,252,229,254,150, 7, 14,248,242,114, 6, 41,
+ 0, 2, 1, 53, 0, 0, 2, 0, 5,213, 0, 3, 0, 9, 0, 53, 64, 15, 7, 0,131, 4,129, 2, 8, 7, 5, 1, 3, 4, 0, 0,
+ 10, 16,252, 75,176, 11, 84, 88,185, 0, 0,255,192, 56, 89, 60,236, 50, 57, 57, 49, 0, 47,228,252,204, 48, 1,182, 0, 11, 32,
+ 11, 80, 11, 3, 93, 37, 51, 21, 35, 17, 51, 17, 3, 35, 3, 1, 53,203,203,203, 20,162, 21,254,254, 5,213,253,113,254,155, 1,
+101, 0, 0, 0, 0, 2, 0,197, 3,170, 2,233, 5,213, 0, 3, 0, 7, 0, 66, 64, 15, 5, 1,132, 4, 0,129, 8, 4, 5, 6,
+ 0, 5, 2, 4, 8, 16,252, 75,176, 18, 84, 75,176, 19, 84, 91, 88,185, 0, 2,255,192, 56, 89,252,220,236, 49, 0, 16,244, 60,
+236, 50, 48, 1, 64, 15, 48, 9, 64, 9, 80, 9, 96, 9,112, 9,160, 9,191, 9, 7, 93, 1, 17, 35, 17, 33, 17, 35, 17, 1,111,
+170, 2, 36,170, 5,213,253,213, 2, 43,253,213, 2, 43, 0, 0, 0, 2, 0,158, 0, 0, 6, 23, 5,190, 0, 3, 0, 31, 0, 96,
+ 64, 49, 27, 11, 0,135, 7, 4, 29, 9, 5, 25, 13, 2,135, 23, 19, 15, 21, 17, 31, 30, 28, 27, 26, 23, 22, 21, 20, 19, 18, 17,
+ 16, 14, 13, 12, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 26, 10, 24, 6, 32, 16,252,204, 23, 57, 49, 0, 47, 60,212, 60, 60,252,
+ 60, 60,212, 60, 60,196, 50,236, 50, 50, 48, 64, 17, 11, 1, 11, 2, 11, 12, 11, 13, 20, 4, 26, 17, 26, 18, 20, 31, 8, 1, 93,
+ 1, 33, 3, 33, 11, 1, 33, 19, 51, 3, 33, 21, 33, 3, 33, 21, 33, 3, 35, 19, 33, 3, 35, 19, 33, 53, 33, 19, 33, 53, 33, 19,
+ 4, 23,254,221, 84, 1, 37, 68,104, 1, 36,105,160,103, 1, 56,254,161, 82, 1, 62,254,155,104,160,103,254,219,103,161,104,254,
+197, 1, 96, 84,254,190, 1,105,102, 3,133,254,178, 3,135,254, 97, 1,159,254, 97,154,254,178,153,254, 98, 1,158,254, 98, 1,
+158,153, 1, 78,154, 1,159, 0, 0, 3, 0,170,254,211, 4,109, 6, 20, 0, 33, 0, 40, 0, 47, 0,189, 64, 85, 34, 2, 10, 11,
+ 10, 39, 1, 38, 40, 2, 11, 11, 10, 29, 1, 30, 28, 2, 47, 41, 47, 27, 2, 41, 41, 47, 66, 19, 17, 16, 34, 10, 27, 41, 4, 23,
+ 6, 9, 42, 33, 5, 2, 23,134, 22, 6,134, 5, 17, 35, 26,138, 22,137, 16, 0, 42,138, 5,137, 2, 45, 8, 22, 10, 30, 7, 41,
+ 26, 18, 3, 0, 9, 34, 16, 9, 3, 1, 7, 38, 8, 13, 5, 6, 48, 16,252, 75,176, 9, 84, 88,185, 0, 5,255,192, 56, 89, 75,
+176, 12, 84, 75,176, 16, 84, 91, 75,176, 15, 84, 91, 88,185, 0, 5, 0, 64, 56, 89, 60,236,244, 23, 60,252, 23, 60,244,228,236,
+ 49, 0, 47,228,236,196,212,228,236, 50,196, 16,238, 16,238, 17, 18, 57, 17, 57, 17, 18, 23, 57, 17, 18, 57, 48, 75, 83, 88, 7,
+ 16, 4,237, 7, 16, 14,237, 17, 23, 57, 7, 16, 14,237, 17, 23, 57, 7, 16, 4,237, 89, 34, 1, 35, 3, 46, 1, 39, 53, 30, 1,
+ 23, 17, 46, 1, 53, 52, 54, 55, 53, 51, 21, 30, 1, 23, 21, 46, 1, 39, 17, 30, 1, 21, 20, 6, 7, 3, 17, 14, 1, 21, 20, 22,
+ 23, 17, 62, 1, 53, 52, 38, 2,180,100, 1,105,210,106,102,209,111,221,201,218,204,100, 93,174, 83, 83,175, 92,227,214,227,214,
+100,116,122,113,225,127,129,123,254,211, 1, 45, 2, 45, 45,180, 64, 65, 1, 1,200, 36,172,150,163,188, 14,235,232, 4, 31, 27,
+175, 42, 46, 4,254, 85, 35,180,156,169,195, 15, 3, 0, 1,154, 13,106, 88, 86, 96,213,254, 79, 17,110, 90, 88,104, 0, 0, 0,
+ 0, 5, 0,113,255,227, 7, 41, 5,240, 0, 11, 0, 23, 0, 35, 0, 39, 0, 51, 0,137, 64, 54, 36, 15, 37, 38, 37, 38, 15, 39,
+ 36, 39, 66, 0,146, 12, 30,146, 46,141, 24,146, 36, 6,146, 12,141, 38, 18,140, 40, 36,145, 52, 39, 33, 27, 37, 9, 3, 13, 21,
+ 14, 9, 13, 15, 33, 13, 43, 14, 27, 13, 15, 49, 11, 52, 16,252, 75,176, 9, 84, 75,176, 11, 84, 91, 75,176, 12, 84, 91, 75,176,
+ 20, 84, 91, 75,176, 14, 84, 91, 75,176, 13, 84, 91, 88,185, 0, 49,255,192, 56, 89,196,236,244,236, 16,238,246,238, 17, 57, 17,
+ 18, 57, 49, 0, 16,228, 50,244, 60,228,236, 16,238,246,238, 16,238, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 5,237, 89, 34, 1,
+ 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 39, 50, 22, 21, 20, 6, 35, 34, 38, 53, 52, 54, 1, 34, 6, 21, 20, 22, 51, 50, 54,
+ 53, 52, 38, 37, 51, 1, 35, 19, 50, 22, 21, 20, 6, 35, 34, 38, 53, 52, 54, 5,209, 87, 99, 99, 87, 85, 99, 99, 85,158,186,187,
+157,160,186,187,252,151, 86, 99, 98, 87, 87, 99,100, 3, 49,160,252, 90,160, 31,158,188,187,159,159,185,186, 2,145,148,132,130,
+149,149,130,131,149,127,220,187,187,219,219,187,188,219, 2, 97,149,130,132,148,148,132,129,150,127,249,243, 6, 13,219,187,189,
+218,219,188,186,220, 0, 0, 0, 0, 2, 0,129,255,227, 5,254, 5,240, 0, 9, 0, 48, 1,205, 64,150, 13, 1, 14, 12,134, 17,
+ 18, 17, 11,134, 10, 11, 18, 18, 17, 9,134, 0, 9, 21, 22, 21, 7, 1, 6, 8,134, 22, 22, 21, 2, 1, 3, 1,134, 29, 30, 29,
+ 0,134, 9, 0, 30, 30, 29, 32, 31, 2, 33, 30, 17, 10, 19, 10, 23, 22, 21, 3, 24, 20, 17, 19, 10, 7, 8, 2, 6, 9, 17, 19,
+ 19, 10, 2, 1, 2, 3, 0, 17, 10, 19, 10, 23, 22, 2, 24, 21, 17, 19, 10, 20, 17, 19, 19, 10, 66, 18, 11, 9, 3, 6, 0, 10,
+ 30, 3, 40, 21, 14, 6, 40, 39, 6,149, 24, 43,149, 39,148, 36,145, 24,140, 14, 19, 10, 46, 11, 14, 9, 0, 46, 18, 21, 39, 14,
+ 30, 3, 46, 18, 39, 33, 14, 17, 15, 19, 33, 3, 18, 27, 16, 49, 16,252,236,196,212,212,236, 16,198,238, 17, 57, 17, 18, 57, 57,
+ 17, 57, 57, 17, 57, 17, 57, 49, 0, 47,198,228,246,230,238, 16,238, 16,198, 17, 18, 57, 17, 23, 57, 17, 23, 57, 48, 75, 83, 88,
+ 7, 16, 5,237, 7, 5,237, 17, 23, 57, 7, 16, 5,237, 17, 23, 57, 7, 16, 5,237, 17, 23, 57, 7, 5,237, 17, 23, 57, 7, 16,
+ 5,237, 17, 23, 57, 7, 16, 8,237, 7, 16, 14,237, 17, 23, 57, 7, 16, 14,237, 17, 23, 57, 7, 16, 8,237, 7, 16, 8,237, 7,
+ 16, 14,237, 17, 23, 57, 89, 34,178, 15, 50, 1, 1, 93, 64,178, 7, 11, 5, 34, 9, 41, 28, 0, 28, 1, 31, 2, 23, 11, 42, 0,
+ 42, 1, 38, 18, 58, 0, 52, 18, 68, 11, 94, 0, 89, 1, 90, 10, 85, 18, 90, 26, 90, 31, 89, 48,103, 30,123, 0,155, 0,154, 1,
+153, 2,151, 8,149, 11,147, 21,149, 22,149, 34,153, 45, 31, 9, 11, 9, 12, 8, 17, 12, 39, 12, 40, 24, 2, 27, 9, 25, 11, 25,
+ 12, 25, 17, 28, 20, 28, 21, 22, 29, 31, 50, 39, 0, 39, 1, 41, 9, 35, 18, 42, 19, 42, 20, 40, 21, 47, 50, 59, 9, 52, 18, 57,
+ 19, 63, 50, 74, 9, 76, 20, 75, 21, 70, 25, 79, 50, 86, 1, 90, 9, 89, 12, 85, 18, 89, 19, 92, 31, 95, 50,106, 12,105, 17, 96,
+ 50,117, 1,121, 12,122, 17,147, 0,147, 1,151, 2,149, 5,156, 7,156, 8,159, 8,154, 9,155, 11,154, 12,144, 50,160, 50,176,
+ 50, 57, 93, 0, 93, 1, 14, 1, 21, 20, 22, 51, 50, 54, 55, 9, 1, 62, 1, 55, 51, 6, 2, 7, 1, 35, 39, 14, 1, 35, 34, 0,
+ 53, 52, 54, 55, 46, 1, 53, 52, 54, 51, 50, 22, 23, 21, 46, 1, 35, 34, 6, 21, 20, 22, 1,242, 91, 85,212,160, 95,166, 73,254,
+123, 1,252, 59, 66, 6,186, 12,104, 93, 1, 23,252,143,104,228,131,241,254,206,134,134, 48, 50,222,184, 83,165, 85, 87,158, 68,
+105,131, 59, 3, 35, 81,161, 88,146,194, 63, 64, 2,143,253,248, 89,203,114,132,254,254,126,254,227,147, 89, 87, 1, 19,215,128,
+225, 99, 63,125, 60,162,197, 36, 36,182, 47, 49,111, 88, 51,103, 0, 1, 0,197, 3,170, 1,111, 5,213, 0, 3, 0, 55, 64, 10,
+ 1,132, 0,129, 4, 0, 5, 2, 4, 4, 16,252, 75,176, 18, 84, 75,176, 19, 84, 91, 88,185, 0, 2,255,192, 56, 89,236, 49, 0,
+ 16,244,236, 48, 1, 64, 13, 64, 5, 80, 5, 96, 5,112, 5,144, 5,160, 5, 6, 93, 1, 17, 35, 17, 1,111,170, 5,213,253,213,
+ 2, 43, 0, 0, 0, 1, 0,176,254,242, 2,123, 6, 18, 0, 13, 0, 55, 64, 15, 6,152, 0,151, 14, 13, 7, 0, 3, 18, 6, 0,
+ 19, 10, 14, 16,220, 75,176, 19, 84, 88,185, 0, 10,255,192, 56, 89, 75,176, 15, 84, 88,185, 0, 10, 0, 64, 56, 89,228, 50,236,
+ 17, 57, 57, 49, 0, 16,252,236, 48, 1, 6, 2, 21, 20, 18, 23, 35, 38, 2, 53, 52, 18, 55, 2,123,134,130,131,133,160,150,149,
+148,151, 6, 18,230,254, 62,231,231,254, 59,229,235, 1,198,224,223, 1,196,236, 0, 1, 0,164,254,242, 2,111, 6, 18, 0, 13,
+ 0, 31, 64, 15, 7,152, 0,151, 14, 7, 1, 0, 11, 18, 4, 19, 8, 0, 14, 16,220, 60,244,236, 17, 57, 57, 49, 0, 16,252,236,
+ 48, 19, 51, 22, 18, 21, 20, 2, 7, 35, 54, 18, 53, 52, 2,164,160,150,149,149,150,160,133,131,131, 6, 18,236,254, 60,223,224,
+254, 58,235,229, 1,197,231,231, 1,194, 0, 0, 0, 1, 0, 61, 2, 74, 3,195, 5,240, 0, 17, 0, 78, 64, 44, 16, 13, 11, 0,
+ 4, 12, 9, 7, 4, 2, 4, 8, 3,153, 5, 17, 12,153, 10, 1, 14,145, 18, 8, 12, 10, 3, 9, 6, 17, 3, 1, 3, 2, 0, 20,
+ 15, 4, 11, 9, 20, 13, 6, 18, 16,212, 60,228, 50,220, 60,228, 50, 23, 57, 17, 18, 23, 57, 49, 0, 16,244,212, 60,236, 50,196,
+236, 50, 23, 57, 18, 23, 57, 48, 1, 13, 1, 7, 37, 17, 35, 17, 5, 39, 45, 1, 55, 5, 17, 51, 17, 37, 3,195,254,153, 1,103,
+ 58,254,176,114,254,176, 58, 1,103,254,153, 58, 1, 80,114, 1, 80, 4,223,194,195, 98,203,254,135, 1,121,203, 98,195,194, 99,
+203, 1,121,254,135,203, 0, 0, 0, 1, 0,217, 0, 0, 5,219, 5, 4, 0, 11, 0, 35, 64, 17, 0, 9, 1,156, 7, 3, 5, 2,
+ 21, 4, 0, 23, 10, 6, 21, 8, 12, 16,220,252, 60,252, 60,236, 49, 0, 47,212, 60,252, 60,196, 48, 1, 17, 33, 21, 33, 17, 35,
+ 17, 33, 53, 33, 17, 3,174, 2, 45,253,211,168,253,211, 2, 45, 5, 4,253,211,170,253,211, 2, 45,170, 2, 45, 0, 1, 0,158,
+255, 18, 1,195, 0,254, 0, 5, 0, 25, 64, 12, 3,158, 0,131, 6, 3, 4, 1, 25, 0, 24, 6, 16,252,236,212,204, 49, 0, 16,
+252,236, 48, 55, 51, 21, 3, 35, 19,240,211,164,129, 82,254,172,254,192, 1, 64, 0, 1, 0,100, 1,223, 2,127, 2,131, 0, 3,
+ 0, 17,182, 0,156, 2, 4, 1, 0, 4, 16,220,204, 49, 0, 16,212,236, 48, 19, 33, 21, 33,100, 2, 27,253,229, 2,131,164, 0,
+ 0, 1, 0,219, 0, 0, 1,174, 0,254, 0, 3, 0, 17,183, 0,131, 2, 1, 25, 0, 24, 4, 16,252,236, 49, 0, 47,236, 48, 55,
+ 51, 21, 35,219,211,211,254,254, 0, 1, 0, 0,255, 66, 2,178, 5,213, 0, 3, 0, 45, 64, 20, 0, 26, 1, 2, 1, 2, 26, 3,
+ 0, 3, 66, 2,159, 0,129, 4, 2, 0, 1, 3, 47,196, 57, 57, 49, 0, 16,244,236, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 5,
+237, 89, 34, 1, 51, 1, 35, 2, 8,170,253,248,170, 5,213,249,109, 0, 0, 0, 0, 2, 0,135,255,227, 4,143, 5,240, 0, 11,
+ 0, 23, 0, 35, 64, 19, 6,160, 18, 0,160, 12,145, 18,140, 24, 9, 28, 15, 30, 3, 28, 21, 27, 24, 16,252,236,244,236, 49, 0,
+ 16,228,244,236, 16,238, 48, 1, 34, 2, 17, 16, 18, 51, 50, 18, 17, 16, 2, 39, 50, 0, 17, 16, 0, 35, 34, 0, 17, 16, 0, 2,
+139,156,157,157,156,157,157,157,157,251, 1, 9,254,247,251,251,254,247, 1, 9, 5, 80,254,205,254,204,254,205,254,205, 1, 51,
+ 1, 51, 1, 52, 1, 51,160,254,115,254,134,254,135,254,115, 1,141, 1,121, 1,122, 1,141, 0, 0, 1, 0,225, 0, 0, 4, 90,
+ 5,213, 0, 10, 0, 64, 64, 21, 66, 3,160, 4, 2,160, 5,129, 7, 0,160, 9, 8, 31, 6, 28, 3, 0, 31, 1, 11, 16,212, 75,
+176, 15, 84, 88,185, 0, 1, 0, 64, 56, 89,236,196,252,236, 49, 0, 47,236, 50,244,236,212,236, 48, 75, 83, 88, 89, 34, 1,180,
+ 15, 3, 15, 4, 2, 93, 55, 33, 17, 5, 53, 37, 51, 17, 33, 21, 33,254, 1, 74,254,153, 1,101,202, 1, 74,252,164,170, 4,115,
+ 72,184, 72,250,213,170, 0, 0, 0, 1, 0,150, 0, 0, 4, 74, 5,240, 0, 28, 0,154, 64, 39, 25, 26, 27, 3, 24, 28, 17, 5,
+ 4, 0, 17, 5, 5, 4, 66, 16,161, 17,148, 13,160, 20,145, 4, 0,160, 2, 0, 16, 10, 2, 1, 10, 28, 23, 16, 3, 6, 29, 16,
+252, 75,176, 21, 84, 75,176, 22, 84, 91, 75,176, 20, 84, 91, 88,185, 0, 3,255,192, 56, 89,196,212,236,192,192, 17, 18, 57, 49,
+ 0, 47,236, 50,244,236,244,236, 48, 75, 83, 88, 7, 16, 5,237, 7, 5,237, 17, 23, 57, 89, 34, 1, 64, 50, 85, 4, 86, 5, 86,
+ 7,122, 4,122, 5,118, 27,135, 25, 7, 4, 0, 4, 25, 4, 26, 4, 27, 5, 28,116, 0,118, 6,117, 26,115, 27,116, 28,130, 0,
+134, 25,130, 26,130, 27,130, 28,168, 0,168, 27, 17, 93, 0, 93, 37, 33, 21, 33, 53, 54, 0, 55, 62, 1, 53, 52, 38, 35, 34, 6,
+ 7, 53, 62, 1, 51, 50, 4, 21, 20, 6, 7, 6, 0, 1,137, 2,193,252, 76,115, 1,141, 51, 97, 77,167,134, 95,211,120,122,212,
+ 88,232, 1, 20, 69, 91, 25,254,244,170,170,170,119, 1,145, 58,109,151, 73,119,150, 66, 67,204, 49, 50,232,194, 92,165,112, 29,
+254,235, 0, 0, 0, 1, 0,156,255,227, 4,115, 5,240, 0, 40, 0,112, 64, 46, 0, 21, 19, 10,134, 9, 31,134, 32, 19,160, 21,
+ 13,160, 9,147, 6, 28,160, 32,147, 35,145, 6,140, 21,163, 41, 22, 28, 19, 0, 3, 20, 25, 28, 38, 32, 16, 28, 3, 20, 31, 9,
+ 6, 41, 16,252, 75,176, 22, 84, 75,176, 20, 84, 91, 88,185, 0, 9,255,192, 56, 89,196,196,212,236,244,236, 17, 23, 57, 57, 49,
+ 0, 16,236,228,244,228,236, 16,230,238, 16,238, 16,238, 16,238, 17, 18, 57, 48, 1, 64, 9,100, 30, 97, 31, 97, 32,100, 33, 4,
+ 0, 93, 1, 30, 1, 21, 20, 4, 33, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 43, 1, 53, 51, 50, 54, 53, 52, 38, 35, 34,
+ 6, 7, 53, 62, 1, 51, 50, 4, 21, 20, 6, 3, 63,145,163,254,208,254,232, 94,199,106, 84,200,109,190,199,185,165,174,182,149,
+158,163,152, 83,190,114,115,201, 89,230, 1, 12,142, 3, 37, 31,196,144,221,242, 37, 37,195, 49, 50,150,143,132,149,166,119,112,
+115,123, 36, 38,180, 32, 32,209,178,124,171, 0, 0, 2, 0,100, 0, 0, 4,164, 5,213, 0, 2, 0, 13, 0,129, 64, 29, 1, 13,
+ 3, 13, 0, 3, 3, 13, 66, 0, 3, 11, 7,160, 5, 1, 3,129, 9, 1, 12, 10, 0, 28, 6, 8, 4, 12, 14, 16,220, 75,176, 11,
+ 84, 75,176, 13, 84, 91, 88,185, 0, 12,255,192, 56, 89,212, 60,196,236, 50, 17, 57, 49, 0, 47,228,212, 60,236, 50, 18, 57, 48,
+ 75, 83, 88, 7, 16, 4,201, 7, 16, 5,201, 89, 34, 1, 64, 42, 11, 0, 42, 0, 72, 0, 89, 0,105, 0,119, 0,138, 0, 7, 22,
+ 1, 43, 0, 38, 1, 43, 3, 54, 1, 78, 1, 79, 12, 79, 13, 86, 1,102, 1,117, 1,122, 3,133, 1, 13, 93, 0, 93, 9, 1, 33,
+ 3, 51, 17, 51, 21, 35, 17, 35, 17, 33, 53, 3, 6,254, 2, 1,254, 53,254,213,213,201,253, 94, 5, 37,252,227, 3,205,252, 51,
+168,254,160, 1, 96,195, 0, 0, 0, 1, 0,158,255,227, 4,100, 5,213, 0, 29, 0, 94, 64, 35, 4, 26, 7, 17,134, 16, 29, 26,
+160, 7, 20,160, 16,137, 13, 2,160, 0,129, 13,140, 7,164, 30, 23, 28, 1, 10, 3, 28, 0, 10, 16, 6, 30, 16,252, 1, 75,176,
+ 22, 84, 75,176, 20, 84, 91, 88,185, 0, 16,255,192, 56, 89, 75,176, 15, 84, 88,185, 0, 16, 0, 64, 56, 89,196,212,236, 16,196,
+238, 49, 0, 16,228,228,244,236, 16,230,238, 16,254,196, 16,238, 17, 18, 57, 48, 19, 33, 21, 33, 17, 62, 1, 51, 50, 0, 21, 20,
+ 0, 33, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 35, 34, 6, 7,221, 3, 25,253,160, 44, 88, 44,250, 1, 36,254,212,254,
+239, 94,195,104, 90,192,107,173,202,202,173, 81,161, 84, 5,213,170,254,146, 15, 15,254,238,234,241,254,245, 32, 32,203, 49, 48,
+182,156,156,182, 36, 38, 0, 0, 0, 2, 0,143,255,227, 4,150, 5,240, 0, 11, 0, 36, 0, 88, 64, 36, 19, 6, 0, 13,134, 12,
+ 0,160, 22, 6,160, 28, 22,165, 16,160, 12,137, 34,145, 28,140, 37, 12, 34, 9, 28, 25, 30, 19, 28, 3, 33, 31, 27, 37, 16,252,
+236,236,244,236,228, 49, 0, 16,228,244,228,252,228, 16,238, 16,238, 16,238, 17, 18, 57, 48, 64, 20,203, 0,203, 1,205, 2,205,
+ 3,205, 4,203, 5,203, 6, 7,164, 30,178, 30, 2, 93, 1, 93, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 1, 21, 46, 1,
+ 35, 34, 2, 3, 62, 1, 51, 50, 0, 21, 20, 0, 35, 32, 0, 17, 16, 0, 33, 50, 22, 2,164,136,159,159,136,136,159,159, 1, 9,
+ 76,155, 76,200,211, 15, 59,178,107,225, 1, 5,254,240,226,254,253,254,238, 1, 80, 1, 27, 76,155, 3, 59,186,162,161,187,187,
+161,162,186, 2,121,184, 36, 38,254,242,254,239, 87, 93,254,239,235,230,254,234, 1,141, 1,121, 1, 98, 1,165, 30, 0, 0, 0,
+ 0, 1, 0,168, 0, 0, 4,104, 5,213, 0, 6, 0, 99, 64, 24, 5, 17, 2, 3, 2, 3, 17, 4, 5, 4, 66, 5,160, 0,129, 3,
+ 5, 3, 1, 4, 1, 0, 6, 7, 16,252,204,196, 17, 57, 57, 49, 0, 47,244,236, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 5,237,
+ 89, 34, 1, 75,176, 22, 84, 88,189, 0, 7, 0, 64, 0, 1, 0, 7, 0, 7,255,192, 56, 17, 55, 56, 89, 64, 18, 88, 2, 1, 6,
+ 3, 26, 5, 57, 5, 72, 5,103, 3,176, 0,176, 6, 7, 93, 0, 93, 19, 33, 21, 1, 35, 1, 33,168, 3,192,253,226,211, 1,254,
+253, 51, 5,213, 86,250,129, 5, 43, 0, 0, 0, 0, 3, 0,139,255,227, 4,139, 5,240, 0, 11, 0, 35, 0, 47, 0, 67, 64, 37,
+ 24, 12, 0,160, 39, 6,160, 30, 45,160, 18,145, 30,140, 39,163, 48, 24, 12, 36, 42, 28, 21, 36, 28, 15, 9, 28, 21, 27, 30, 3,
+ 28, 15, 33, 27, 48, 16,252,196,236,244,196,236, 16,238, 16,238, 17, 57, 57, 49, 0, 16,236,228,244,236, 16,238, 16,238, 57, 57,
+ 48, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 37, 46, 1, 53, 52, 36, 51, 50, 22, 21, 20, 6, 7, 30, 1, 21, 20, 4, 35,
+ 34, 36, 53, 52, 54, 19, 20, 22, 51, 50, 54, 53, 52, 38, 35, 34, 6, 2,139,144,165,165,144,144,166,165,254,165,130,145, 0,255,
+222,223,254,145,129,146,163,254,247,247,247,254,247,164, 72,145,131,130,147,147,130,131,145, 2,197,154,135,135,154,155,134,135,
+154, 86, 32,178,128,179,208,208,179,128,178, 32, 34,198,143,217,232,232,217,143,198, 1, 97,116,130,130,116,116,130,130, 0, 0,
+ 0, 2, 0,129,255,227, 4,135, 5,240, 0, 24, 0, 36, 0, 88, 64, 35, 7, 31, 25, 1,134, 0, 25,160, 10,165, 4,160, 0,137,
+ 22, 31,160, 16,145, 22,140, 37, 7, 28, 28, 33, 19, 30, 0, 34, 34, 28, 13, 27, 37, 16,252,236,228,244,236,236, 49, 0, 16,228,
+244,236, 16,230,254,245,238, 16,238, 17, 18, 57, 48, 64, 22,196, 25,194, 26,192, 27,192, 28,192, 29,194, 30,196, 31, 7,170, 18,
+188, 18,233, 18, 3, 93, 1, 93, 55, 53, 30, 1, 51, 50, 18, 19, 14, 1, 35, 34, 0, 53, 52, 0, 51, 32, 0, 17, 16, 0, 33, 34,
+ 38, 1, 50, 54, 53, 52, 38, 35, 34, 6, 21, 20, 22,225, 76,156, 75,200,211, 15, 58,178,108,224,254,251, 1, 16,226, 1, 3, 1,
+ 17,254,177,254,229, 76,156, 1, 62,136,159,159,136,136,159,159, 31,184, 36, 38, 1, 13, 1, 18, 86, 92, 1, 15,235,230, 1, 22,
+254,115,254,134,254,159,254, 91, 30, 2,151,186,162,161,187,187,161,162,186, 0, 0, 2, 0,240, 0, 0, 1,195, 4, 35, 0, 3,
+ 0, 7, 0, 28, 64, 14, 6,131, 4,166, 0,131, 2, 5, 1, 3, 4, 0, 24, 8, 16,252, 60,236, 50, 49, 0, 47,236,244,236, 48,
+ 55, 51, 21, 35, 17, 51, 21, 35,240,211,211,211,211,254,254, 4, 35,254, 0, 0, 0, 2, 0,158,255, 18, 1,195, 4, 35, 0, 3,
+ 0, 9, 0, 37, 64, 19, 2,131, 0, 7,158, 4,131, 0,166, 10, 7, 8, 5, 1, 25, 4, 0, 24, 10, 16,252, 60,236, 50,212,204,
+ 49, 0, 16,228,252,236, 16,238, 48, 19, 51, 21, 35, 17, 51, 21, 3, 35, 19,240,211,211,211,164,129, 82, 4, 35,254,253,217,172,
+254,192, 1, 64, 0, 1, 0,217, 0, 94, 5,219, 4,166, 0, 6, 0, 77, 64, 42, 2,156, 3, 4, 3, 1,156, 0, 1, 4, 4, 3,
+ 1,156, 2, 1, 5, 6, 5, 0,156, 6, 5, 66, 5, 4, 2, 1, 0, 5, 3,168, 6,167, 7, 1, 2, 0, 36, 4, 35, 7, 16,252,
+236, 50, 57, 49, 0, 16,244,236, 23, 57, 48, 75, 83, 88, 7, 4,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 4,237, 89, 34, 9,
+ 2, 21, 1, 53, 1, 5,219,251,248, 4, 8,250,254, 5, 2, 3,240,254,145,254,147,182, 1,209,166, 1,209, 0, 0, 2, 0,217,
+ 1, 96, 5,219, 3,162, 0, 3, 0, 7, 0, 28, 64, 13, 0,156, 2, 6,156, 4, 8, 5, 1, 4, 0, 35, 8, 16,252, 60,196, 50,
+ 49, 0, 16,212,236,212,236, 48, 19, 33, 21, 33, 21, 33, 21, 33,217, 5, 2,250,254, 5, 2,250,254, 3,162,168,240,170, 0, 0,
+ 0, 1, 0,217, 0, 94, 5,219, 4,166, 0, 6, 0, 79, 64, 43, 6,156, 0, 6, 3, 4, 3, 5,156, 4, 4, 3, 0,156, 1, 2,
+ 1, 6,156, 5, 6, 2, 2, 1, 66, 6, 5, 3, 2, 0, 5, 4,168, 1,167, 7, 6, 2, 36, 4, 0, 35, 7, 16,252, 60,236, 57,
+ 49, 0, 16,244,236, 23, 57, 48, 75, 83, 88, 7, 16, 8,237, 7, 16, 4,237, 7, 16, 4,237, 7, 16, 8,237, 89, 34, 19, 53, 1,
+ 21, 1, 53, 1,217, 5, 2,250,254, 4, 6, 3,240,182,254, 47,166,254, 47,182, 1,109, 0, 0, 0, 2, 0,147, 0, 0, 3,176,
+ 5,240, 0, 3, 0, 36, 0,101, 64, 43, 36, 30, 9, 6, 4, 10, 29, 19, 4, 0, 20,134, 19,136, 16,149, 23,145, 0,131, 2, 29,
+ 26, 13, 9, 5, 4, 10, 30, 1, 13, 28, 26, 4, 28, 5, 1, 3, 0, 38, 26, 19, 37, 16,220, 75,176, 12, 84, 88,185, 0, 19,255,
+192, 56, 89,196,252,236,212,236, 16,238, 17, 57, 57, 17, 18, 57, 17, 18, 57, 49, 0, 47,238,246,254,244,238, 16,205, 17, 57, 57,
+ 23, 57, 48, 1,182,121, 9,122, 10,122, 32, 3, 93, 37, 51, 21, 35, 19, 35, 53, 52, 54, 63, 1, 62, 1, 53, 52, 38, 35, 34, 6,
+ 7, 53, 62, 1, 51, 50, 22, 21, 20, 6, 15, 1, 14, 1, 7, 14, 1, 21, 1,135,203,203,197,191, 56, 90, 90, 57, 51,131,108, 79,
+179, 97, 94,193,103,184,223, 72, 90, 88, 47, 39, 8, 6, 6,254,254, 1,145,154,101,130, 86, 89, 53, 94, 49, 89,110, 70, 67,188,
+ 57, 56,194,159, 76,137, 86, 86, 47, 53, 25, 21, 60, 52, 0, 0, 0, 2, 0,135,254,156, 7,113, 5,162, 0, 11, 0, 76, 0,149,
+ 64, 50, 24, 12, 3, 9,169, 25, 21, 27, 3,169, 76, 15, 52, 51, 15,172, 48,169, 55, 21,172, 36,169, 55, 67, 77, 51, 52, 30, 26,
+ 0, 40, 18, 6, 24, 12, 40, 26, 43, 30, 40, 73, 18, 43, 42, 40, 73, 44, 61, 77, 16,220,236,252,236, 16,254,253,254, 60,198, 16,
+238, 17, 18, 57, 57, 49, 0, 16,212,196,252,236, 16,254,237,212,198, 16,197,238, 50, 16,196,238, 17, 57, 57, 48, 0, 75,176, 9,
+ 84, 75,176, 12, 84, 91, 75,176, 16, 84, 91, 75,176, 19, 84, 91, 75,176, 20, 84, 91, 88,189, 0, 77,255,192, 0, 1, 0, 77, 0,
+ 77, 0, 64, 56, 17, 55, 56, 89, 64, 9, 15, 78, 31, 78, 47, 78, 63, 78, 4, 1, 93, 1, 20, 22, 51, 50, 54, 53, 52, 38, 35, 34,
+ 6, 1, 14, 1, 35, 34, 38, 53, 52, 54, 51, 50, 22, 23, 53, 51, 17, 62, 1, 53, 52, 38, 39, 38, 36, 35, 34, 6, 7, 6, 2, 21,
+ 20, 18, 23, 22, 4, 51, 50, 54, 55, 23, 6, 4, 35, 34, 36, 39, 38, 2, 53, 52, 18, 55, 54, 36, 51, 50, 4, 23, 30, 1, 21, 16,
+ 0, 5, 2,250,142,124,123,141,144,122,121,143, 2, 33, 60,155,103,172,215,216,171,103,156, 59,143,146,165, 63, 64,104,254,213,
+176,123,226, 96,157,177,115,109,105, 1, 20,157,129,249,104, 90,125,254,217,152,185,254,184,128,128,134,136,126,129, 1, 82,189,
+212, 1,107,123, 75, 79,254,194,254,232, 2, 25,143,163,164,142,140,165,164,254, 72, 77, 73,249,200,200,250, 75, 76,131,253, 32,
+ 22,223,177,107,188, 80,131,139, 65, 64,102,254,181,193,159,254,234,106,104,109, 87, 81,111, 97,103,131,125,125, 1, 73,189,182,
+ 1, 74,125,127,135,174,160, 98,230,123,254,249,254,208, 6, 0, 0, 2, 0, 16, 0, 0, 5,104, 5,213, 0, 2, 0, 10, 0,186,
+ 64, 65, 0, 17, 1, 0, 4, 5, 4, 2, 17, 5, 5, 4, 1, 17, 10, 3, 10, 0, 17, 2, 0, 3, 3, 10, 7, 17, 5, 4, 6, 17,
+ 5, 5, 4, 9, 17, 3, 10, 8, 17, 10, 3, 10, 66, 0, 3, 7,149, 1, 3,129, 9, 5, 9, 8, 7, 6, 4, 3, 2, 1, 0, 9,
+ 5, 10, 11, 16,212,196, 23, 57, 49, 0, 47, 60,228,212,236, 18, 57, 48, 75, 83, 88, 7, 16, 5,237, 7, 5,237, 7, 16, 5,237,
+ 7, 5,237, 7, 16, 8,237, 7, 16, 5,237, 7, 16, 5,237, 7, 16, 8,237, 89, 34,178, 32, 12, 1, 1, 93, 64, 58, 15, 0, 88,
+ 0,118, 0,112, 0,140, 0, 5, 7, 1, 8, 2, 6, 3, 9, 4, 22, 1, 25, 2, 86, 1, 88, 2, 80, 12,103, 1,104, 2,120, 1,
+118, 2,124, 3,114, 4,119, 7,120, 8,135, 1,136, 2,128, 12,152, 2,153, 3,150, 4, 23, 93, 0, 93, 9, 1, 33, 1, 51, 1,
+ 35, 3, 33, 3, 35, 2,188,254,238, 2, 37,254,123,229, 2, 57,210,136,253, 95,136,213, 5, 14,253, 25, 3,174,250, 43, 1,127,
+254,129, 0, 0, 0, 3, 0,201, 0, 0, 4,236, 5,213, 0, 8, 0, 17, 0, 32, 0, 67, 64, 35, 25, 0,149, 10, 9,149, 18,129,
+ 1,149, 10,173, 31, 17, 11, 8, 2, 19, 25, 31, 5, 0, 14, 28, 22, 5, 25, 28, 46, 9, 0, 28, 18, 4, 33, 16,252,236, 50,252,
+236,212,236, 17, 23, 57, 57, 57, 49, 0, 47,236,236,244,236, 16,238, 57, 48,178, 15, 34, 1, 1, 93, 1, 17, 33, 50, 54, 53, 52,
+ 38, 35, 1, 17, 33, 50, 54, 53, 52, 38, 35, 37, 33, 50, 22, 21, 20, 6, 7, 30, 1, 21, 20, 4, 35, 33, 1,147, 1, 68,163,157,
+157,163,254,188, 1, 43,148,145,145,148,254, 11, 2, 4,231,250,128,124,149,165,254,240,251,253,232, 2,201,253,221,135,139,140,
+133, 2,102,254, 62,111,114,113,112,166,192,177,137,162, 20, 32,203,152,200,218, 0, 1, 0,115,255,227, 5, 39, 5,240, 0, 25,
+ 0, 54, 64, 26, 13,161, 14,174, 10,149, 17, 1,161, 0,174, 4,149, 23,145, 17,140, 26, 7, 25, 13, 0, 48, 20, 16, 26, 16,252,
+236, 50,236, 49, 0, 16,228,244,236,244,236, 16,238,246,238, 48,180, 15, 27, 31, 27, 2, 1, 93, 1, 21, 46, 1, 35, 32, 0, 17,
+ 16, 0, 33, 50, 54, 55, 21, 14, 1, 35, 32, 0, 17, 16, 0, 33, 50, 22, 5, 39,102,231,130,255, 0,254,240, 1, 16, 1, 0,130,
+231,102,106,237,132,254,173,254,122, 1,134, 1, 83,134,237, 5, 98,213, 95, 94,254,199,254,216,254,217,254,199, 94, 95,211, 72,
+ 72, 1,159, 1,103, 1,104, 1,159, 71, 0, 0, 0, 2, 0,201, 0, 0, 5,176, 5,213, 0, 8, 0, 17, 0, 46, 64, 21, 0,149,
+ 9,129, 1,149, 16, 8, 2, 16, 10, 0, 5, 25, 13, 50, 0, 28, 9, 4, 18, 16,252,236,244,236, 17, 57, 57, 57, 57, 49, 0, 47,
+236,244,236, 48,178, 96, 19, 1, 1, 93, 1, 17, 51, 32, 0, 17, 16, 0, 33, 37, 33, 32, 0, 17, 16, 0, 41, 1, 1,147,244, 1,
+ 53, 1, 31,254,225,254,203,254, 66, 1,159, 1,178, 1,150,254,104,254, 80,254, 97, 5, 47,251,119, 1, 24, 1, 46, 1, 44, 1,
+ 23,166,254,151,254,128,254,126,254,150, 0, 0, 0, 1, 0,201, 0, 0, 4,139, 5,213, 0, 11, 0, 46, 64, 21, 6,149, 4, 2,
+149, 0,129, 8,149, 4,173, 10, 5, 1, 9, 7, 3, 28, 0, 4, 12, 16,252,236, 50,212,196,196, 49, 0, 47,236,236,244,236, 16,
+238, 48,178, 31, 13, 1, 1, 93, 19, 33, 21, 33, 17, 33, 21, 33, 17, 33, 21, 33,201, 3,176,253, 26, 2,199,253, 57, 2,248,252,
+ 62, 5,213,170,254, 70,170,253,227,170, 0, 0, 0, 1, 0,201, 0, 0, 4, 35, 5,213, 0, 9, 0, 41, 64, 18, 6,149, 4, 2,
+149, 0,129, 4,173, 8, 5, 1, 7, 3, 28, 0, 4, 10, 16,252,236, 50,212,196, 49, 0, 47,236,244,236, 16,238, 48,178, 15, 11,
+ 1, 1, 93, 19, 33, 21, 33, 17, 33, 21, 33, 17, 35,201, 3, 90,253,112, 2, 80,253,176,202, 5,213,170,254, 72,170,253, 55, 0,
+ 0, 1, 0,115,255,227, 5,139, 5,240, 0, 29, 0, 57, 64, 32, 0, 5, 27, 1,149, 3, 27,149, 8, 18,161, 17,174, 21,149, 14,
+145, 8,140, 30, 2, 0, 28, 17, 52, 4, 51, 24, 25, 11, 16, 30, 16,252,236,252,228,252,196, 49, 0, 16,228,244,236,244,236, 16,
+254,212,238, 17, 57, 57, 48, 37, 17, 33, 53, 33, 17, 6, 4, 35, 32, 0, 17, 16, 0, 33, 50, 4, 23, 21, 46, 1, 35, 32, 0, 17,
+ 16, 0, 33, 50, 54, 4,195,254,182, 2, 18,117,254,230,160,254,162,254,117, 1,139, 1, 94,146, 1, 7,111,112,252,139,254,238,
+254,237, 1, 19, 1, 18,107,168,213, 1,145,166,253,127, 83, 85, 1,153, 1,109, 1,110, 1,153, 72, 70,215, 95, 96,254,206,254,
+209,254,210,254,206, 37, 0, 0, 0, 1, 0,201, 0, 0, 5, 59, 5,213, 0, 11, 0, 44, 64, 20, 8,149, 2,173, 4, 0,129, 10,
+ 6, 7, 3, 28, 5, 56, 9, 1, 28, 0, 4, 12, 16,252,236, 50,252,236, 50, 49, 0, 47, 60,228, 50,252,236, 48,178, 80, 13, 1,
+ 1, 93, 19, 51, 17, 33, 17, 51, 17, 35, 17, 33, 17, 35,201,202, 2,222,202,202,253, 34,202, 5,213,253,156, 2,100,250, 43, 2,
+199,253, 57, 0, 0, 1, 0,201, 0, 0, 1,147, 5,213, 0, 3, 0, 46,183, 0,175, 2, 1, 28, 0, 4, 4, 16,252, 75,176, 16,
+ 84, 88,185, 0, 0, 0, 64, 56, 89,236, 49, 0, 47,236, 48, 1, 64, 13, 48, 5, 64, 5, 80, 5, 96, 5,143, 5,159, 5, 6, 93,
+ 19, 51, 17, 35,201,202,202, 5,213,250, 43, 0, 0, 1,255,150,254,102, 1,147, 5,213, 0, 11, 0, 66, 64, 19, 11, 2, 0, 7,
+149, 5,176, 0,129, 12, 5, 8, 6, 57, 1, 28, 0, 4, 12, 16,252, 75,176, 16, 84, 88,185, 0, 0, 0, 64, 56, 89,236,228, 57,
+ 57, 49, 0, 16,228,252,236, 17, 57, 57, 48, 1, 64, 13, 48, 13, 64, 13, 80, 13, 96, 13,143, 13,159, 13, 6, 93, 19, 51, 17, 16,
+ 6, 43, 1, 53, 51, 50, 54, 53,201,202,205,227, 77, 63,134,110, 5,213,250,147,254,242,244,170,150,194, 0, 0, 0, 1, 0,201,
+ 0, 0, 5,106, 5,213, 0, 10, 0,239, 64, 40, 8, 17, 5, 6, 5, 7, 17, 6, 6, 5, 3, 17, 4, 5, 4, 2, 17, 5, 5, 4,
+ 66, 8, 5, 2, 3, 3, 0,175, 9, 6, 5, 1, 4, 6, 8, 1, 28, 0, 4, 11, 16,252,236, 50,212,196, 17, 57, 49, 0, 47, 60,
+236, 50, 23, 57, 48, 75, 83, 88, 7, 16, 4,237, 7, 16, 5,237, 7, 16, 5,237, 7, 16, 4,237, 89, 34,178, 8, 3, 1, 1, 93,
+ 64,146, 20, 2, 1, 4, 2, 9, 8, 22, 2, 40, 5, 40, 8, 55, 2, 54, 5, 52, 8, 71, 2, 70, 5, 67, 8, 85, 2,103, 2,118,
+ 2,119, 5,131, 2,136, 5,143, 8,148, 2,155, 8,231, 2, 21, 6, 3, 9, 5, 9, 6, 27, 3, 25, 7, 5, 10, 3, 10, 7, 24,
+ 3, 40, 5, 43, 6, 42, 7, 54, 4, 54, 5, 54, 6, 53, 7, 48, 12, 65, 3, 64, 4, 69, 5, 64, 6, 64, 7, 64, 12, 98, 3, 96,
+ 4,104, 5,103, 7,119, 5,112, 12,139, 3,139, 5,142, 6,143, 7,143, 12,154, 3,157, 6,157, 7,182, 3,181, 7,197, 3,197,
+ 7,215, 3,214, 7,232, 3,233, 4,232, 5,234, 6,247, 3,248, 5,249, 6, 44, 93,113, 0, 93,113, 19, 51, 17, 1, 33, 9, 1,
+ 33, 1, 17, 35,201,202, 2,158, 1, 4,253, 27, 3, 26,254,246,253, 51,202, 5,213,253,137, 2,119,253, 72,252,227, 2,207,253,
+ 49, 0, 0, 0, 0, 1, 0,201, 0, 0, 4,106, 5,213, 0, 5, 0, 37, 64, 12, 2,149, 0,129, 4, 1, 28, 3, 58, 0, 4, 6,
+ 16,252,236,236, 49, 0, 47,228,236, 48, 64, 9, 48, 7, 80, 7,128, 3,128, 4, 4, 1, 93, 19, 51, 17, 33, 21, 33,201,202, 2,
+215,252, 95, 5,213,250,213,170, 0, 1, 0,201, 0, 0, 6, 31, 5,213, 0, 12, 0,191, 64, 52, 3, 17, 7, 8, 7, 2, 17, 1,
+ 2, 8, 8, 7, 2, 17, 3, 2, 9, 10, 9, 1, 17, 10, 10, 9, 66, 10, 7, 2, 3, 8, 3, 0,175, 8, 11, 5, 9, 8, 3, 2,
+ 1, 5, 10, 6, 28, 4, 62, 10, 28, 0, 4, 13, 16,252,236,252,236, 17, 23, 57, 49, 0, 47, 60,196,236, 50, 17, 23, 57, 48, 75,
+ 83, 88, 7, 16, 5,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,237, 89, 34,178,112, 14, 1, 1, 93, 64, 86, 3, 7, 15, 8,
+ 15, 9, 2, 10, 21, 2, 20, 7, 19, 10, 38, 2, 38, 7, 32, 7, 38, 10, 32, 10, 52, 7, 53, 10,105, 2,124, 2,123, 7,121, 10,
+128, 2,130, 7,130, 10,144, 2, 22, 4, 1, 11, 3, 19, 1, 27, 3, 35, 1, 44, 3, 39, 8, 40, 9, 52, 1, 60, 3, 86, 8, 89,
+ 9,101, 8,106, 9,118, 8,121, 9,129, 1,141, 3,149, 1,155, 3, 20, 93, 0, 93, 19, 33, 9, 1, 33, 17, 35, 17, 1, 35, 1,
+ 17, 35,201, 1, 45, 1,125, 1,127, 1, 45,197,254,127,203,254,127,196, 5,213,252, 8, 3,248,250, 43, 5, 31,252, 0, 4, 0,
+250,225, 0, 0, 0, 1, 0,201, 0, 0, 5, 51, 5,213, 0, 9, 0,121, 64, 30, 7, 17, 1, 2, 1, 2, 17, 6, 7, 6, 66, 7,
+ 2, 3, 0,175, 8, 5, 6, 1, 7, 2, 28, 4, 54, 7, 28, 0, 4, 10, 16,252,236,252,236, 17, 57, 57, 49, 0, 47, 60,236, 50,
+ 57, 57, 48, 75, 83, 88, 7, 16, 4,237, 7, 16, 4,237, 89, 34,178, 31, 11, 1, 1, 93, 64, 48, 54, 2, 56, 7, 72, 2, 71, 7,
+105, 2,102, 7,128, 2, 7, 6, 1, 9, 6, 21, 1, 26, 6, 70, 1, 73, 6, 87, 1, 88, 6,101, 1,105, 6,121, 6,133, 1,138,
+ 6,149, 1,154, 6,159, 11, 16, 93, 0, 93, 19, 33, 1, 17, 51, 17, 33, 1, 17, 35,201, 1, 16, 2,150,196,254,240,253,106,196,
+ 5,213,251, 31, 4,225,250, 43, 4,225,251, 31, 0, 2, 0,115,255,227, 5,217, 5,240, 0, 11, 0, 23, 0, 35, 64, 19, 6,149,
+ 18, 0,149, 12,145, 18,140, 24, 9, 25, 15, 51, 3, 25, 21, 16, 24, 16,252,236,252,236, 49, 0, 16,228,244,236, 16,238, 48, 1,
+ 34, 0, 17, 16, 0, 51, 50, 0, 17, 16, 0, 39, 32, 0, 17, 16, 0, 33, 32, 0, 17, 16, 0, 3, 39,220,254,253, 1, 3,220,220,
+ 1, 1,254,255,220, 1, 58, 1,120,254,136,254,198,254,197,254,135, 1,121, 5, 76,254,184,254,229,254,230,254,184, 1, 72, 1,
+ 26, 1, 27, 1, 72,164,254, 91,254,158,254,159,254, 91, 1,164, 1, 98, 1, 98, 1,165, 0, 0, 0, 2, 0,201, 0, 0, 4,141,
+ 5,213, 0, 8, 0, 19, 0, 58, 64, 24, 1,149, 16, 0,149, 9,129, 18, 16, 10, 8, 2, 4, 0, 5, 25, 13, 63, 17, 0, 28, 9,
+ 4, 20, 16,252,236, 50,252,236, 17, 23, 57, 49, 0, 47,244,236,212,236, 48, 64, 11, 15, 21, 31, 21, 63, 21, 95, 21,175, 21, 5,
+ 1, 93, 1, 17, 51, 50, 54, 53, 52, 38, 35, 37, 33, 50, 4, 21, 20, 4, 43, 1, 17, 35, 1,147,254,141,154,154,141,254, 56, 1,
+200,251, 1, 1,254,255,251,254,202, 5, 47,253,207,146,135,134,146,166,227,219,221,226,253,168, 0, 2, 0,115,254,248, 5,217,
+ 5,240, 0, 11, 0, 29, 0, 82, 64, 42, 17, 16, 2, 15, 1, 12, 13, 12, 14, 1, 13, 13, 12, 66, 15, 30, 12, 6,149, 18, 0,149,
+ 24,145, 18,140, 13, 30, 13, 27, 15, 12, 3, 9, 25, 27, 51, 3, 25, 21, 16, 30, 16,252,236,252,236, 17, 57, 57, 17, 57, 49, 0,
+ 16,196,228,244,236, 16,238, 57, 18, 57, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 5,237, 23, 57, 89, 34, 1, 34, 0, 17, 16, 0,
+ 51, 50, 0, 17, 16, 0, 19, 1, 35, 39, 14, 1, 35, 32, 0, 17, 16, 0, 33, 32, 0, 17, 16, 2, 3, 39,220,254,253, 1, 3,220,
+220, 1, 1,254,255, 63, 1, 10,244,221, 33, 35, 16,254,197,254,135, 1,121, 1, 59, 1, 58, 1,120,209, 5, 76,254,184,254,229,
+254,230,254,184, 1, 72, 1, 26, 1, 27, 1, 72,250,207,254,221,239, 2, 2, 1,165, 1, 97, 1, 98, 1,165,254, 91,254,158,254,
+252,254,142, 0, 0, 2, 0,201, 0, 0, 5, 84, 5,213, 0, 19, 0, 28, 0,177, 64, 53, 9, 8, 7, 3, 10, 6, 17, 3, 4, 3,
+ 5, 17, 4, 4, 3, 66, 6, 4, 0, 21, 3, 4, 21,149, 9, 20,149, 13,129, 11, 4, 5, 6, 3, 17, 9, 0, 28, 22, 14, 5, 10,
+ 25, 25, 4, 17, 63, 20, 10, 28, 12, 4, 29, 16,252,236, 50,252,196,236, 17, 23, 57, 17, 57, 57, 57, 49, 0, 47, 60,244,236,212,
+236, 18, 57, 18, 57, 18, 57, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 5,237, 17, 23, 57, 89, 34,178, 64, 30, 1, 1, 93, 64, 66,
+122, 19, 1, 5, 0, 5, 1, 5, 2, 6, 3, 7, 4, 21, 0, 21, 1, 20, 2, 22, 3, 23, 4, 37, 0, 37, 1, 37, 2, 38, 3, 39,
+ 6, 38, 7, 38, 8, 38, 9, 32, 30, 54, 1, 54, 2, 70, 1, 70, 2,104, 5,117, 4,117, 5,119, 19,136, 6,136, 7,152, 6,152,
+ 7, 31, 93, 0, 93, 1, 30, 1, 23, 19, 35, 3, 46, 1, 43, 1, 17, 35, 17, 33, 32, 22, 21, 20, 6, 1, 17, 51, 50, 54, 53, 52,
+ 38, 35, 3,141, 65,123, 62,205,217,191, 74,139,120,220,202, 1,200, 1, 0,252,131,253,137,254,146,149,149,146, 2,188, 22,144,
+126,254,104, 1,127,150, 98,253,137, 5,213,214,216,141,186, 2, 79,253,238,135,131,131,133, 0, 0, 1, 0,135,255,227, 4,162,
+ 5,240, 0, 39, 0,126, 64, 60, 13, 12, 2, 14, 11, 2, 30, 31, 30, 8, 9, 2, 7, 10, 2, 31, 31, 30, 66, 10, 11, 30, 31, 4,
+ 21, 1, 0, 21,161, 20,148, 24,149, 17, 4,149, 0,148, 37,145, 17,140, 40, 30, 10, 11, 31, 27, 7, 0, 34, 27, 25, 14, 45, 7,
+ 25, 20, 34, 40, 16,220,196,236,252,236,228, 17, 18, 57, 57, 57, 57, 49, 0, 16,228,244,228,236, 16,238,246,238, 16,198, 17, 23,
+ 57, 48, 75, 83, 88, 7, 16, 14,237, 17, 23, 57, 7, 16, 14,237, 17, 23, 57, 89, 34,178, 15, 41, 1, 1, 93,182, 31, 41, 47, 41,
+ 79, 41, 3, 93, 1, 21, 46, 1, 35, 34, 6, 21, 20, 22, 31, 1, 30, 1, 21, 20, 4, 33, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53,
+ 52, 38, 47, 1, 46, 1, 53, 52, 36, 51, 50, 22, 4, 72,115,204, 95,165,179,119,166,122,226,215,254,221,254,231,106,239,128,123,
+236,114,173,188,135,154,123,226,202, 1, 23,245,105,218, 5,164,197, 55, 54,128,118, 99,101, 31, 25, 43,217,182,217,224, 48, 47,
+208, 69, 70,136,126,110,124, 31, 24, 45,192,171,198,228, 38, 0, 0, 1,255,250, 0, 0, 4,233, 5,213, 0, 7, 0, 74, 64, 14,
+ 6, 2,149, 0,129, 4, 1, 64, 3, 28, 0, 64, 5, 8, 16,212,228,252,228, 49, 0, 47,244,236, 50, 48, 1, 75,176, 10, 84, 88,
+189, 0, 8, 0, 64, 0, 1, 0, 8, 0, 8,255,192, 56, 17, 55, 56, 89, 64, 19, 0, 9, 31, 0, 16, 1, 16, 2, 31, 7, 16, 9,
+ 64, 9,112, 9,159, 9, 9, 93, 3, 33, 21, 33, 17, 35, 17, 33, 6, 4,239,253,238,203,253,238, 5,213,170,250,213, 5, 43, 0,
+ 0, 1, 0,178,255,227, 5, 41, 5,213, 0, 17, 0, 64, 64, 22, 8, 2, 17, 11, 0, 5,149, 14,140, 9, 0,129, 18, 8, 28, 10,
+ 56, 1, 28, 0, 65, 18, 16,252, 75,176, 16, 84, 88,185, 0, 0,255,192, 56, 89,236,252,236, 49, 0, 16,228, 50,244,236, 17, 57,
+ 57, 57, 57, 48, 1,182, 31, 19,143, 19,159, 19, 3, 93, 19, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 16, 0, 33, 32, 0, 17,
+178,203,174,195,194,174,203,254,223,254,230,254,229,254,223, 5,213,252,117,240,211,211,240, 3,139,252, 92,254,220,254,214, 1,
+ 42, 1, 36, 0, 0, 1, 0, 16, 0, 0, 5,104, 5,213, 0, 6, 0,183, 64, 39, 4, 17, 5, 6, 5, 3, 17, 2, 3, 6, 6, 5,
+ 3, 17, 4, 3, 0, 1, 0, 2, 17, 1, 1, 0, 66, 3, 4, 1,175, 0, 6, 4, 3, 2, 0, 5, 5, 1, 7, 16,212,196, 23, 57,
+ 49, 0, 47,236, 50, 57, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,237, 89, 34,178, 80, 8, 1,
+ 1, 93, 64, 98, 0, 3, 42, 3, 71, 4, 71, 5, 90, 3,125, 3,131, 3, 7, 6, 0, 7, 2, 8, 4, 9, 6, 21, 1, 20, 2, 26,
+ 4, 26, 5, 42, 0, 38, 1, 38, 2, 41, 4, 41, 5, 37, 6, 32, 8, 56, 0, 51, 1, 51, 2, 60, 4, 60, 5, 55, 6, 72, 0, 69,
+ 1, 69, 2, 73, 4, 73, 5, 71, 6, 89, 0, 86, 6,102, 2,105, 4,105, 5,122, 0,118, 1,118, 2,121, 4,121, 5,117, 6,128,
+ 8,152, 0,151, 6, 41, 93, 0, 93, 33, 1, 51, 9, 1, 51, 1, 2, 74,253,198,211, 1,217, 1,218,210,253,199, 5,213,251, 23,
+ 4,233,250, 43, 0, 1, 0, 68, 0, 0, 7,166, 5,213, 0, 12, 1,123, 64, 73, 5, 26, 6, 5, 9, 10, 9, 4, 26, 10, 9, 3,
+ 26, 10, 11, 10, 2, 26, 1, 2, 11, 11, 10, 6, 17, 7, 8, 7, 5, 17, 4, 5, 8, 8, 7, 2, 17, 3, 2, 12, 0, 12, 1, 17,
+ 0, 0, 12, 66, 10, 5, 2, 3, 6, 3, 0,175, 11, 8, 12, 11, 10, 9, 8, 6, 5, 4, 3, 2, 1, 11, 7, 0, 13, 16,212,204,
+ 23, 57, 49, 0, 47, 60,236, 50, 50, 23, 57, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,237, 7,
+ 16, 8,237, 7, 16, 5,237, 7, 5,237, 7, 16, 8,237, 89, 34,178, 0, 14, 1, 1, 93, 64,242, 6, 2, 6, 5, 2, 10, 0, 10,
+ 0, 10, 18, 10, 40, 5, 36, 10, 32, 10, 62, 2, 62, 5, 52, 10, 48, 10, 76, 2, 77, 5, 66, 10, 64, 10, 89, 2,106, 2,107, 5,
+103, 10, 96, 10,123, 2,127, 2,124, 5,127, 5,128, 10,150, 2,149, 5, 29, 7, 0, 9, 2, 8, 3, 0, 4, 6, 5, 0, 5, 0,
+ 6, 1, 7, 4, 8, 0, 8, 7, 9, 0, 9, 4, 10, 10, 12, 0, 14, 26, 3, 21, 4, 21, 8, 25, 12, 16, 14, 32, 4, 33, 5, 32,
+ 6, 32, 7, 32, 8, 35, 9, 36, 10, 37, 11, 32, 14, 32, 14, 60, 2, 58, 3, 53, 4, 51, 5, 48, 8, 54, 9, 57, 11, 63, 12, 48,
+ 14, 70, 0, 70, 1, 74, 2, 64, 4, 69, 5, 64, 5, 66, 6, 66, 7, 66, 8, 64, 8, 64, 9, 68, 10, 77, 12, 64, 14, 64, 14, 88,
+ 2, 86, 8, 89, 12, 80, 14,102, 2,103, 3, 97, 4, 98, 5, 96, 6, 96, 7, 96, 8,100, 9,100, 10,100, 11,119, 0,118, 1,123,
+ 2,120, 3,119, 4,116, 5,121, 6,121, 7,119, 8,112, 8,120, 12,127, 12,127, 14,134, 2,135, 3,136, 4,137, 5,133, 9,138,
+ 11,143, 14,151, 4,159, 14,175, 14, 91, 93, 0, 93, 19, 51, 9, 1, 51, 9, 1, 51, 1, 35, 9, 1, 35, 68,204, 1, 58, 1, 57,
+227, 1, 58, 1, 57,205,254,137,254,254,197,254,194,254, 5,213,251, 18, 4,238,251, 18, 4,238,250, 43, 5, 16,250,240, 0, 0,
+ 0, 1, 0, 61, 0, 0, 5, 59, 5,213, 0, 11, 0,102, 64, 6, 13, 4, 6, 0, 10, 12, 16,212,196,220,196,196, 49,180,128, 0,
+127, 10, 2, 93, 0, 64, 5, 3, 0,175, 9, 6, 47, 60,236, 50, 48, 75,176, 66, 80, 88, 64, 20, 7, 17, 6, 6, 5, 9, 17, 10,
+ 11, 10, 3, 17, 4, 5, 4, 1, 17, 0, 11, 0, 5, 7, 16,236, 7, 16,236, 7, 16,236, 7, 16,236, 64, 20, 11, 10, 3, 7, 0,
+ 8, 9, 4, 7, 0, 5, 9, 4, 6, 1, 2, 10, 3, 6, 1, 15, 15, 15, 15, 89, 19, 51, 9, 1, 51, 9, 1, 35, 9, 1, 35, 1,
+129,217, 1,115, 1,117,217,254, 32, 2, 0,217,254, 92,254, 89,218, 2, 21, 5,213,253,213, 2, 43,253, 51,252,248, 2,123,253,
+133, 3, 29, 0, 0, 1,255,252, 0, 0, 4,231, 5,213, 0, 8, 0,148, 64, 40, 3, 17, 4, 5, 4, 2, 17, 1, 2, 5, 5, 4,
+ 2, 17, 3, 2, 8, 0, 8, 1, 17, 0, 0, 8, 66, 2, 3, 0,175, 6, 2, 7, 4, 64, 5, 28, 0, 64, 7, 9, 16,212,228,252,
+228, 18, 57, 49, 0, 47,236, 50, 57, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,237, 89, 34,178,
+ 0, 10, 1, 1, 93, 64, 60, 5, 2, 20, 2, 53, 2, 48, 2, 48, 5, 48, 8, 70, 2, 64, 2, 64, 5, 64, 8, 81, 2, 81, 5, 81,
+ 8,101, 2,132, 2,147, 2, 16, 22, 1, 26, 3, 31, 10, 38, 1, 41, 3, 55, 1, 56, 3, 64, 10,103, 1,104, 3,120, 3,112, 10,
+159, 10, 13, 93, 0, 93, 3, 51, 9, 1, 51, 1, 17, 35, 17, 4,217, 1,158, 1,155,217,253,240,203, 5,213,253,154, 2,102,252,
+242,253, 57, 2,199, 0, 0, 0, 0, 1, 0, 92, 0, 0, 5, 31, 5,213, 0, 9, 0,144, 64, 27, 3, 17, 7, 8, 7, 8, 17, 2,
+ 3, 2, 66, 8,149, 0,129, 3,149, 5, 8, 3, 0, 1, 66, 4, 0, 6, 10, 16,220, 75,176, 9, 84, 75,176, 10, 84, 91, 88,185,
+ 0, 6,255,192, 56, 89,196,212,228, 17, 57, 57, 49, 0, 47,236,244,236, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 5,237, 89, 34,
+ 1, 64, 64, 5, 2, 10, 7, 24, 7, 41, 2, 38, 7, 56, 7, 72, 2, 71, 7, 72, 8, 9, 5, 3, 11, 8, 0, 11, 22, 3, 26, 8,
+ 16, 11, 47, 11, 53, 3, 57, 8, 63, 11, 71, 3, 74, 8, 79, 11, 85, 3, 89, 8,102, 3,105, 8,111, 11,119, 3,120, 8,127, 11,
+159, 11, 22, 93, 0, 93, 19, 33, 21, 1, 33, 21, 33, 53, 1, 33,115, 4,149,252, 80, 3,199,251, 61, 3,176,252,103, 5,213,154,
+251,111,170,154, 4,145, 0, 0, 0, 1, 0,176,254,242, 2, 88, 6, 20, 0, 7, 0, 59, 64, 15, 4,169, 6,178, 2,169, 0,177,
+ 8, 5, 1, 3, 67, 0, 8, 16,220, 75,176, 12, 84, 88,185, 0, 0, 0, 64, 56, 89, 75,176, 18, 84, 75,176, 19, 84, 91, 88,185,
+ 0, 0,255,192, 56, 89,252,204, 50, 49, 0, 16,252,236,244,236, 48, 19, 33, 21, 35, 17, 51, 21, 33,176, 1,168,240,240,254, 88,
+ 6, 20,143,249,252,143, 0, 0, 0, 1, 0, 0,255, 66, 2,178, 5,213, 0, 3, 0, 45, 64, 20, 2, 26, 1, 1, 0, 0, 26, 3,
+ 3, 2, 66, 1,159, 0,129, 4, 2, 0, 1, 3, 47,196, 57, 57, 49, 0, 16,244,236, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 5,
+237, 89, 34, 19, 1, 35, 1,170, 2, 8,170,253,248, 5,213,249,109, 6,147, 0, 0, 1, 0,199,254,242, 2,111, 6, 20, 0, 7,
+ 0, 48, 64, 16, 3,169, 1,178, 5,169, 0,177, 8, 0, 67, 4, 6, 2, 4, 8, 16,252, 75,176, 15, 84, 75,176, 16, 84, 91, 88,
+185, 0, 2, 0, 64, 56, 89, 60,220,236, 49, 0, 16,252,236,244,236, 48, 1, 17, 33, 53, 51, 17, 35, 53, 2,111,254, 88,239,239,
+ 6, 20,248,222,143, 6, 4,143, 0, 1, 0,217, 3,168, 5,219, 5,213, 0, 6, 0, 24, 64, 10, 3, 4, 1, 0,129, 7, 3, 1,
+ 5, 7, 16,220,204, 57, 49, 0, 16,244,204, 50, 57, 48, 9, 1, 35, 9, 1, 35, 1, 3,188, 2, 31,201,254, 72,254, 72,201, 2,
+ 31, 5,213,253,211, 1,139,254,117, 2, 45, 0, 0, 1,255,236,254, 29, 4, 20,254,172, 0, 3, 0, 15,181, 0,169, 1, 0, 2,
+ 4, 16,196,196, 49, 0,212,236, 48, 1, 21, 33, 53, 4, 20,251,216,254,172,143,143, 0, 0, 0, 0, 1, 0,170, 4,240, 2,137,
+ 6,102, 0, 3, 0, 49, 64, 9, 1,180, 0,179, 4, 3, 68, 1, 4, 16,220,236, 49, 0, 16,244,236, 48, 0, 75,176, 9, 84, 75,
+176, 14, 84, 91, 88,189, 0, 4,255,192, 0, 1, 0, 4, 0, 4, 0, 64, 56, 17, 55, 56, 89, 9, 1, 35, 1, 1,111, 1, 26,153,
+254,186, 6,102,254,138, 1,118, 0, 2, 0,123,255,227, 4, 45, 4,123, 0, 10, 0, 37, 0,188, 64, 39, 25, 31, 11, 23, 9, 14,
+ 0,169, 23, 6,185, 14, 17, 32,134, 31,186, 28,185, 35,184, 17,140, 23, 12, 0, 23, 3, 24, 13, 9, 8, 11, 31, 3, 8, 20, 69,
+ 38, 16,252,236,204,212,236, 50, 50, 17, 57, 57, 49, 0, 47,196,228,244,252,244,236, 16,198,238, 16,238, 17, 57, 17, 57, 18, 57,
+ 48, 64,110, 48, 29, 48, 30, 48, 31, 48, 32, 48, 33, 48, 34, 63, 39, 64, 29, 64, 30, 64, 31, 64, 32, 64, 33, 64, 34, 80, 29, 80,
+ 30, 80, 31, 80, 32, 80, 33, 80, 34, 80, 39,112, 39,133, 29,135, 30,135, 31,135, 32,135, 33,133, 34,144, 39,160, 39,240, 39, 30,
+ 48, 30, 48, 31, 48, 32, 48, 33, 64, 30, 64, 31, 64, 32, 64, 33, 80, 30, 80, 31, 80, 32, 80, 33, 96, 30, 96, 31, 96, 32, 96, 33,
+112, 30,112, 31,112, 32,112, 33,128, 30,128, 31,128, 32,128, 33, 24, 93, 1, 93, 1, 34, 6, 21, 20, 22, 51, 50, 54, 61, 1, 55,
+ 17, 35, 53, 14, 1, 35, 34, 38, 53, 52, 54, 51, 33, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 2,190,223,172,129,111,
+153,185,184,184, 63,188,136,172,203,253,251, 1, 2,167,151, 96,182, 84,101,190, 90,243,240, 2, 51,102,123, 98,115,217,180, 41,
+ 76,253,129,170,102, 97,193,162,189,192, 18,127,139, 46, 46,170, 39, 39,252, 0, 0, 2, 0,186,255,227, 4,164, 6, 20, 0, 11,
+ 0, 28, 0, 56, 64, 25, 3,185, 12, 15, 9,185, 24, 21,140, 15,184, 27,151, 25, 0, 18, 18, 71, 24, 12, 6, 8, 26, 70, 29, 16,
+252,236, 50, 50,244,236, 49, 0, 47,236,228,244,196,236, 16,198,238, 48,182, 96, 30,128, 30,160, 30, 3, 1, 93, 1, 52, 38, 35,
+ 34, 6, 21, 20, 22, 51, 50, 54, 1, 62, 1, 51, 50, 0, 17, 16, 2, 35, 34, 38, 39, 21, 35, 17, 51, 3,229,167,146,146,167,167,
+146,146,167,253,142, 58,177,123,204, 0,255,255,204,123,177, 58,185,185, 2, 47,203,231,231,203,203,231,231, 2, 82,100, 97,254,
+188,254,248,254,248,254,188, 97,100,168, 6, 20, 0, 1, 0,113,255,227, 3,231, 4,123, 0, 25, 0, 63, 64, 27, 0,134, 1,136,
+ 4, 14,134, 13,136, 10,185, 17, 4,185, 23,184, 17,140, 26, 7, 18, 13, 0, 72, 20, 69, 26, 16,252,228, 50,236, 49, 0, 16,228,
+244,236, 16,254,244,238, 16,245,238, 48, 64, 11, 15, 27, 16, 27,128, 27,144, 27,160, 27, 5, 1, 93, 1, 21, 46, 1, 35, 34, 6,
+ 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 0, 17, 16, 0, 33, 50, 22, 3,231, 78,157, 80,179,198,198,179, 80,157, 78, 77,
+165, 93,253,254,214, 1, 45, 1, 6, 85,162, 4, 53,172, 43, 43,227,205,205,227, 43, 43,170, 36, 36, 1, 62, 1, 14, 1, 18, 1,
+ 58, 35, 0, 0, 0, 2, 0,113,255,227, 4, 90, 6, 20, 0, 16, 0, 28, 0, 56, 64, 25, 26,185, 0, 14, 20,185, 5, 8,140, 14,
+184, 1,151, 3, 23, 4, 0, 8, 2, 71, 17, 18, 11, 69, 29, 16,252,236,244,236, 50, 50, 49, 0, 47,236,228,244,196,236, 16,196,
+238, 48,182, 96, 30,128, 30,160, 30, 3, 1, 93, 1, 17, 51, 17, 35, 53, 14, 1, 35, 34, 2, 17, 16, 0, 51, 50, 22, 1, 20, 22,
+ 51, 50, 54, 53, 52, 38, 35, 34, 6, 3,162,184,184, 58,177,124,203,255, 0,255,203,124,177,253,199,167,146,146,168,168,146,146,
+167, 3,182, 2, 94,249,236,168,100, 97, 1, 68, 1, 8, 1, 8, 1, 68, 97,254, 21,203,231,231,203,203,231,231, 0, 2, 0,113,
+255,227, 4,127, 4,123, 0, 20, 0, 27, 0,112, 64, 36, 0, 21, 1, 9,134, 8,136, 5, 21,169, 1, 5,185, 12, 1,187, 24,185,
+ 18,184, 12,140, 28, 27, 21, 2, 8, 21, 8, 0, 75, 2, 18, 15, 69, 28, 16,252,236,244,236,196, 17, 18, 57, 49, 0, 16,228,244,
+236,228, 16,238, 16,238, 16,244,238, 17, 18, 57, 48, 64, 41, 63, 29,112, 29,160, 29,208, 29,240, 29, 5, 63, 0, 63, 1, 63, 2,
+ 63, 21, 63, 27, 5, 44, 7, 47, 8, 47, 9, 44, 10,111, 0,111, 1,111, 2,111, 21,111, 27, 9, 93,113, 1, 93, 1, 21, 33, 30,
+ 1, 51, 50, 54, 55, 21, 14, 1, 35, 32, 0, 17, 16, 0, 51, 50, 0, 7, 46, 1, 35, 34, 6, 7, 4,127,252,178, 12,205,183,106,
+199, 98, 99,208,107,254,244,254,199, 1, 41,252,226, 1, 7,184, 2,165,136,154,185, 14, 2, 94, 90,190,199, 52, 52,174, 42, 44,
+ 1, 56, 1, 10, 1, 19, 1, 67,254,221,196,151,180,174,158, 0, 0, 1, 0, 47, 0, 0, 2,248, 6, 20, 0, 19, 0, 89, 64, 28,
+ 5, 16, 1, 12, 8,169, 6, 1,135, 0,151, 14, 6,188, 10, 2, 19, 7, 0, 7, 9, 5, 8, 13, 15, 11, 76, 20, 16,252, 75,176,
+ 10, 84, 88,185, 0, 11, 0, 64, 56, 89, 75,176, 14, 84, 88,185, 0, 11,255,192, 56, 89, 60,196,252, 60,196,196, 18, 57, 57, 49,
+ 0, 47,228, 50,252,236, 16,238, 50, 18, 57, 57, 48, 1,182, 64, 21, 80, 21,160, 21, 3, 93, 1, 21, 35, 34, 6, 29, 1, 33, 21,
+ 33, 17, 35, 17, 35, 53, 51, 53, 52, 54, 51, 2,248,176, 99, 77, 1, 47,254,209,185,176,176,174,189, 6, 20,153, 80,104, 99,143,
+252, 47, 3,209,143, 78,187,171, 0, 2, 0,113,254, 86, 4, 90, 4,123, 0, 11, 0, 40, 0, 74, 64, 35, 25, 12, 29, 9, 18,134,
+ 19, 22,185, 15, 3,185, 38, 35,184, 39,188, 9,185, 15,189, 26, 29, 38, 25, 0, 8, 12, 71, 6, 18, 18, 32, 69, 41, 16,252,196,
+236,244,236, 50, 50, 49, 0, 47,196,228,236,228,244,196,236, 16,254,213,238, 17, 18, 57, 57, 48,182, 96, 42,128, 42,160, 42, 3,
+ 1, 93, 1, 52, 38, 35, 34, 6, 21, 20, 22, 51, 50, 54, 23, 16, 2, 33, 34, 38, 39, 53, 30, 1, 51, 50, 54, 61, 1, 14, 1, 35,
+ 34, 2, 17, 16, 18, 51, 50, 22, 23, 53, 51, 3,162,165,149,148,165,165,148,149,165,184,254,254,250, 97,172, 81, 81,158, 82,181,
+180, 57,178,124,206,252,252,206,124,178, 57,184, 2, 61,200,220,220,200,199,220,220,235,254,226,254,233, 29, 30,179, 44, 42,189,
+191, 91, 99, 98, 1, 58, 1, 3, 1, 4, 1, 58, 98, 99,170, 0, 0, 1, 0,186, 0, 0, 4,100, 6, 20, 0, 19, 0, 52, 64, 25,
+ 3, 9, 0, 3, 14, 1, 6,135, 14, 17,184, 12,151, 10, 1, 2, 8, 0, 78, 13, 9, 8, 11, 70, 20, 16,252,236, 50,244,236, 49,
+ 0, 47, 60,236,244,196,236, 17, 18, 23, 57, 48,178, 96, 21, 1, 1, 93, 1, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51,
+ 17, 62, 1, 51, 50, 22, 4,100,184,124,124,149,172,185,185, 66,179,117,193,198, 2,164,253, 92, 2,158,159,158,190,164,253,135,
+ 6, 20,253,158,101,100,239, 0, 0, 2, 0,193, 0, 0, 1,121, 6, 20, 0, 3, 0, 7, 0, 43, 64, 14, 6,190, 4,177, 0,188,
+ 2, 5, 1, 8, 4, 0, 70, 8, 16,252, 60,236, 50, 49, 0, 47,228,252,236, 48, 64, 11, 16, 9, 64, 9, 80, 9, 96, 9,112, 9,
+ 5, 1, 93, 19, 51, 17, 35, 17, 51, 21, 35,193,184,184,184,184, 4, 96,251,160, 6, 20,233, 0, 0, 2,255,219,254, 86, 1,121,
+ 6, 20, 0, 11, 0, 15, 0, 68, 64, 28, 11, 2, 7, 0, 14,190, 12, 7,135, 5,189, 0,188, 12,177, 16, 8, 16, 5, 6, 79, 13,
+ 1, 8, 12, 0, 70, 16, 16,252, 60,236, 50,228, 57, 18, 57, 49, 0, 16,236,228,244,236, 16,238, 17, 18, 57, 57, 48, 64, 11, 16,
+ 17, 64, 17, 80, 17, 96, 17,112, 17, 5, 1, 93, 19, 51, 17, 20, 6, 43, 1, 53, 51, 50, 54, 53, 17, 51, 21, 35,193,184,163,181,
+ 70, 49,105, 76,184,184, 4, 96,251,140,214,192,156, 97,153, 6, 40,233, 0, 0, 0, 1, 0,186, 0, 0, 4,156, 6, 20, 0, 10,
+ 0,188, 64, 41, 8, 17, 5, 6, 5, 7, 17, 6, 6, 5, 3, 17, 4, 5, 4, 2, 17, 5, 5, 4, 66, 8, 5, 2, 3, 3,188, 0,
+151, 9, 6, 5, 1, 4, 6, 8, 1, 8, 0, 70, 11, 16,252,236, 50,212,196, 17, 57, 49, 0, 47, 60,236,228, 23, 57, 48, 75, 83,
+ 88, 7, 16, 4,237, 7, 16, 5,237, 7, 16, 5,237, 7, 16, 4,237, 89, 34,178, 16, 12, 1, 1, 93, 64, 95, 4, 2, 10, 8, 22,
+ 2, 39, 2, 41, 5, 43, 8, 86, 2,102, 2,103, 8,115, 2,119, 5,130, 2,137, 5,142, 8,147, 2,150, 5,151, 8,163, 2, 18,
+ 9, 5, 9, 6, 2, 11, 3, 10, 7, 40, 3, 39, 4, 40, 5, 43, 6, 43, 7, 64, 12,104, 3, 96, 12,137, 3,133, 4,137, 5,141,
+ 6,143, 7,154, 3,151, 7,170, 3,167, 5,182, 7,197, 7,214, 7,247, 3,240, 3,247, 4,240, 4, 26, 93,113, 0, 93, 19, 51,
+ 17, 1, 51, 9, 1, 35, 1, 17, 35,186,185, 2, 37,235,253,174, 2,107,240,253,199,185, 6, 20,252,105, 1,227,253,244,253,172,
+ 2, 35,253,221, 0, 1, 0,193, 0, 0, 1,121, 6, 20, 0, 3, 0, 34,183, 0,151, 2, 1, 8, 0, 70, 4, 16,252,236, 49, 0,
+ 47,236, 48, 64, 13, 16, 5, 64, 5, 80, 5, 96, 5,112, 5,240, 5, 6, 1, 93, 19, 51, 17, 35,193,184,184, 6, 20,249,236, 0,
+ 0, 1, 0,186, 0, 0, 7, 29, 4,123, 0, 34, 0, 90, 64, 38, 6, 18, 9, 24, 15, 0, 6, 29, 7, 21, 12,135, 29, 32, 3,184,
+ 27,188, 25, 16, 7, 0, 17, 15, 8, 8, 6, 80, 17, 8, 15, 80, 28, 24, 8, 26, 70, 35, 16,252,236, 50,252,252,252,236, 17, 18,
+ 57, 49, 0, 47, 60, 60,228,244, 60,196,236, 50, 17, 18, 23, 57, 48, 64, 19, 48, 36, 80, 36,112, 36,144, 36,160, 36,160, 36,191,
+ 36,223, 36,255, 36, 9, 1, 93, 1, 62, 1, 51, 50, 22, 21, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 52, 38, 35, 34, 6,
+ 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 22, 4, 41, 69,192,130,175,190,185,114,117,143,166,185,114,119,141,166,185,185, 63,176,
+121,122,171, 3,137,124,118,245,226,253, 92, 2,158,161,156,190,164,253,135, 2,158,162,155,191,163,253,135, 4, 96,174,103, 98,
+124, 0, 0, 0, 0, 1, 0,186, 0, 0, 4,100, 4,123, 0, 19, 0, 54, 64, 25, 3, 9, 0, 3, 14, 1, 6,135, 14, 17,184, 12,
+188, 10, 1, 2, 8, 0, 78, 13, 9, 8, 11, 70, 20, 16,252,236, 50,244,236, 49, 0, 47, 60,228,244,196,236, 17, 18, 23, 57, 48,
+180, 96, 21,207, 21, 2, 1, 93, 1, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 22, 4,100,184,124,
+124,149,172,185,185, 66,179,117,193,198, 2,164,253, 92, 2,158,159,158,190,164,253,135, 4, 96,174,101,100,239, 0, 2, 0,113,
+255,227, 4,117, 4,123, 0, 11, 0, 23, 0, 74, 64, 19, 6,185, 18, 0,185, 12,184, 18,140, 24, 9, 18, 15, 81, 3, 18, 21, 69,
+ 24, 16,252,236,244,236, 49, 0, 16,228,244,236, 16,238, 48, 64, 35, 63, 25,123, 0,123, 6,127, 7,127, 8,127, 9,127, 10,127,
+ 11,123, 12,127, 13,127, 14,127, 15,127, 16,127, 17,123, 18,160, 25,240, 25, 17, 1, 93, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53,
+ 52, 38, 39, 50, 0, 17, 16, 0, 35, 34, 0, 17, 16, 0, 2,115,148,172,171,149,147,172,172,147,240, 1, 18,254,238,240,241,254,
+239, 1, 17, 3,223,231,201,201,231,232,200,199,233,156,254,200,254,236,254,237,254,199, 1, 57, 1, 19, 1, 20, 1, 56, 0, 0,
+ 0, 2, 0,186,254, 86, 4,164, 4,123, 0, 16, 0, 28, 0, 62, 64, 27, 26,185, 0, 14, 20,185, 5, 8,184, 14,140, 1,189, 3,
+188, 29, 17, 18, 11, 71, 23, 4, 0, 8, 2, 70, 29, 16,252,236, 50, 50,244,236, 49, 0, 16,228,228,228,244,196,236, 16,196,238,
+ 48, 64, 9, 96, 30,128, 30,160, 30,224, 30, 4, 1, 93, 37, 17, 35, 17, 51, 21, 62, 1, 51, 50, 0, 17, 16, 2, 35, 34, 38, 1,
+ 52, 38, 35, 34, 6, 21, 20, 22, 51, 50, 54, 1,115,185,185, 58,177,123,204, 0,255,255,204,123,177, 2, 56,167,146,146,167,167,
+146,146,167,168,253,174, 6, 10,170,100, 97,254,188,254,248,254,248,254,188, 97, 1,235,203,231,231,203,203,231,231, 0, 0, 0,
+ 0, 2, 0,113,254, 86, 4, 90, 4,123, 0, 11, 0, 28, 0, 62, 64, 27, 3,185, 12, 15, 9,185, 24, 21,184, 15,140, 27,189, 25,
+188, 29, 24, 12, 6, 8, 26, 71, 0, 18, 18, 69, 29, 16,252,236,244,236, 50, 50, 49, 0, 16,228,228,228,244,196,236, 16,198,238,
+ 48, 64, 9, 96, 30,128, 30,160, 30,224, 30, 4, 1, 93, 1, 20, 22, 51, 50, 54, 53, 52, 38, 35, 34, 6, 1, 14, 1, 35, 34, 2,
+ 17, 16, 0, 51, 50, 22, 23, 53, 51, 17, 35, 1, 47,167,146,146,168,168,146,146,167, 2,115, 58,177,124,203,255, 0,255,203,124,
+177, 58,184,184, 2, 47,203,231,231,203,203,231,231,253,174,100, 97, 1, 68, 1, 8, 1, 8, 1, 68, 97,100,170,249,246, 0, 0,
+ 0, 1, 0,186, 0, 0, 3, 74, 4,123, 0, 17, 0, 48, 64, 20, 6, 11, 7, 0, 17, 11, 3,135, 14,184, 9,188, 7, 10, 6, 8,
+ 0, 8, 70, 18, 16,252,196,236, 50, 49, 0, 47,228,244,236,196,212,204, 17, 18, 57, 48,180, 80, 19,159, 19, 2, 1, 93, 1, 46,
+ 1, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 22, 23, 3, 74, 31, 73, 44,156,167,185,185, 58,186,133, 19, 46, 28, 3,
+180, 18, 17,203,190,253,178, 4, 96,174,102, 99, 5, 5, 0, 0, 0, 1, 0,111,255,227, 3,199, 4,123, 0, 39, 0,231, 64, 60,
+ 13, 12, 2, 14, 11, 83, 31, 30, 8, 9, 2, 7, 10, 83, 30, 31, 30, 66, 10, 11, 30, 31, 4, 21, 0,134, 1,137, 4, 20,134, 21,
+137, 24,185, 17, 4,185, 37,184, 17,140, 40, 30, 10, 11, 31, 27, 7, 0, 82, 27, 8, 14, 7, 8, 20, 34, 69, 40, 16,252,196,236,
+212,236,228, 17, 18, 57, 57, 57, 57, 49, 0, 16,228,244,236, 16,254,245,238, 16,245,238, 18, 23, 57, 48, 75, 83, 88, 7, 16, 14,
+237, 17, 23, 57, 7, 14,237, 17, 23, 57, 89, 34,178, 0, 39, 1, 1, 93, 64,109, 28, 10, 28, 11, 28, 12, 46, 9, 44, 10, 44, 11,
+ 44, 12, 59, 9, 59, 10, 59, 11, 59, 12, 11, 32, 0, 32, 1, 36, 2, 40, 10, 40, 11, 42, 19, 47, 20, 47, 21, 42, 22, 40, 30, 40,
+ 31, 41, 32, 41, 33, 36, 39,134, 10,134, 11,134, 12,134, 13, 18, 0, 0, 0, 1, 2, 2, 6, 10, 6, 11, 3, 12, 3, 13, 3, 14,
+ 3, 15, 3, 16, 3, 25, 3, 26, 3, 27, 3, 28, 4, 29, 9, 39, 47, 41, 63, 41, 95, 41,127, 41,128, 41,144, 41,160, 41,240, 41,
+ 24, 93, 0, 93,113, 1, 21, 46, 1, 35, 34, 6, 21, 20, 22, 31, 1, 30, 1, 21, 20, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54,
+ 53, 52, 38, 47, 1, 46, 1, 53, 52, 54, 51, 50, 22, 3,139, 78,168, 90,137,137, 98,148, 63,196,165,247,216, 90,195,108,102,198,
+ 97,130,140,101,171, 64,171,152,224,206,102,180, 4, 63,174, 40, 40, 84, 84, 64, 73, 33, 14, 42,153,137,156,182, 35, 35,190, 53,
+ 53, 89, 81, 75, 80, 37, 15, 36,149,130,158,172, 30, 0, 0, 0, 0, 1, 0, 55, 0, 0, 2,242, 5,158, 0, 19, 0, 56, 64, 25,
+ 14, 5, 8, 15, 3,169, 0, 17, 1,188, 8,135, 10, 11, 8, 9, 2, 4, 0, 8, 16, 18, 14, 70, 20, 16,252, 60,196,252, 60,196,
+ 50, 57, 57, 49, 0, 47,236,244, 60,196,236, 50, 17, 57, 57, 48,178,175, 21, 1, 1, 93, 1, 17, 33, 21, 33, 17, 20, 22, 59, 1,
+ 21, 35, 34, 38, 53, 17, 35, 53, 51, 17, 1,119, 1,123,254,133, 75,115,189,189,213,162,135,135, 5,158,254,194,143,253,160,137,
+ 78,154,159,210, 2, 96,143, 1, 62, 0, 0, 0, 0, 1, 0,174,255,227, 4, 88, 4, 96, 0, 19, 0, 54, 64, 25, 3, 9, 0, 3,
+ 14, 1, 6,135, 14, 17,140, 10, 1,188, 12, 13, 9, 8, 11, 78, 2, 8, 0, 70, 20, 16,252,236,244,236, 50, 49, 0, 47,228, 50,
+244,196,236, 17, 18, 23, 57, 48,180, 96, 21,207, 21, 2, 1, 93, 19, 17, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 35, 53, 14,
+ 1, 35, 34, 38,174,184,124,124,149,173,184,184, 67,177,117,193,200, 1,186, 2,166,253, 97,159,159,190,164, 2,123,251,160,172,
+102, 99,240, 0, 0, 1, 0, 61, 0, 0, 4,127, 4, 96, 0, 6, 0,251, 64, 39, 3, 17, 4, 5, 4, 2, 17, 1, 2, 5, 5, 4,
+ 2, 17, 3, 2, 6, 0, 6, 1, 17, 0, 0, 6, 66, 2, 3, 0,191, 5, 6, 5, 3, 2, 1, 5, 4, 0, 7, 16,212, 75,176, 10,
+ 84, 88,185, 0, 0, 0, 64, 56, 89, 75,176, 20, 84, 75,176, 21, 84, 91, 88,185, 0, 0,255,192, 56, 89,196, 23, 57, 49, 0, 47,
+236, 50, 57, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,237, 89, 34, 1, 64,142, 72, 2,106, 2,
+123, 2,127, 2,134, 2,128, 2,145, 2,164, 2, 8, 6, 0, 6, 1, 9, 3, 9, 4, 21, 0, 21, 1, 26, 3, 26, 4, 38, 0, 38,
+ 1, 41, 3, 41, 4, 32, 8, 53, 0, 53, 1, 58, 3, 58, 4, 48, 8, 70, 0, 70, 1, 73, 3, 73, 4, 70, 5, 72, 6, 64, 8, 86,
+ 0, 86, 1, 89, 3, 89, 4, 80, 8,102, 0,102, 1,105, 3,105, 4,103, 5,104, 6, 96, 8,117, 0,116, 1,123, 3,123, 4,117,
+ 5,122, 6,133, 0,133, 1,137, 3,137, 4,137, 5,134, 6,150, 0,150, 1,151, 2,154, 3,152, 4,152, 5,151, 6,168, 5,167,
+ 6,176, 8,192, 8,223, 8,255, 8, 62, 93, 0, 93, 19, 51, 9, 1, 51, 1, 35, 61,195, 1, 94, 1, 94,195,254, 92,250, 4, 96,
+252, 84, 3,172,251,160, 0, 0, 0, 1, 0, 86, 0, 0, 6, 53, 4, 96, 0, 12, 1,235, 64, 73, 5, 85, 6, 5, 9, 10, 9, 4,
+ 85, 10, 9, 3, 85, 10, 11, 10, 2, 85, 1, 2, 11, 11, 10, 6, 17, 7, 8, 7, 5, 17, 4, 5, 8, 8, 7, 2, 17, 3, 2, 12,
+ 0, 12, 1, 17, 0, 0, 12, 66, 10, 5, 2, 3, 6, 3, 0,191, 11, 8, 12, 11, 10, 9, 8, 6, 5, 4, 3, 2, 1, 11, 7, 0,
+ 13, 16,212, 75,176, 10, 84, 75,176, 17, 84, 91, 75,176, 18, 84, 91, 75,176, 19, 84, 91, 75,176, 11, 84, 91, 88,185, 0, 0, 0,
+ 64, 56, 89, 1, 75,176, 12, 84, 75,176, 13, 84, 91, 75,176, 16, 84, 91, 88,185, 0, 0,255,192, 56, 89,204, 23, 57, 49, 0, 47,
+ 60,236, 50, 50, 23, 57, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,237, 7, 16, 8,237, 7, 16,
+ 5,237, 7, 5,237, 7, 16, 8,237, 89, 34, 1, 64,255, 5, 2, 22, 2, 22, 5, 34, 10, 53, 10, 73, 2, 73, 5, 70, 10, 64, 10,
+ 91, 2, 91, 5, 85, 10, 80, 10,110, 2,110, 5,102, 10,121, 2,127, 2,121, 5,127, 5,135, 2,153, 2,152, 5,148, 10,188, 2,
+188, 5,206, 2,199, 3,207, 5, 29, 5, 2, 9, 3, 6, 4, 11, 5, 10, 8, 11, 9, 4, 11, 5, 12, 21, 2, 25, 3, 22, 4, 26,
+ 5, 27, 8, 27, 9, 20, 11, 21, 12, 37, 0, 37, 1, 35, 2, 39, 3, 33, 4, 37, 5, 34, 6, 34, 7, 37, 8, 39, 9, 36, 10, 33,
+ 11, 35, 12, 57, 3, 54, 4, 54, 8, 57, 12, 48, 14, 70, 2, 72, 3, 70, 4, 64, 4, 66, 5, 64, 6, 64, 7, 64, 8, 68, 9, 68,
+ 10, 68, 11, 64, 14, 64, 14, 86, 0, 86, 1, 86, 2, 80, 4, 81, 5, 82, 6, 82, 7, 80, 8, 83, 9, 84, 10, 85, 11, 99, 0,100,
+ 1,101, 2,106, 3,101, 4,106, 5,106, 6,106, 7,110, 9, 97, 11,103, 12,111, 14,117, 0,117, 1,121, 2,125, 3,120, 4,125,
+ 5,122, 6,127, 6,122, 7,127, 7,120, 8,121, 9,127, 9,123, 10,118, 11,125, 12,135, 2,136, 5,143, 14,151, 0,151, 1,148,
+ 2,147, 3,156, 4,155, 5,152, 6,152, 7,153, 8, 64, 47,150, 12,159, 14,166, 0,166, 1,164, 2,164, 3,171, 4,171, 5,169,
+ 6,169, 7,171, 8,164, 12,175, 14,181, 2,177, 3,189, 4,187, 5,184, 9,191, 14,196, 2,195, 3,204, 4,202, 5,121, 93, 0,
+ 93, 19, 51, 27, 1, 51, 27, 1, 51, 1, 35, 11, 1, 35, 86,184,230,229,217,230,229,184,254,219,217,241,242,217, 4, 96,252,150,
+ 3,106,252,150, 3,106,251,160, 3,150,252,106, 0, 1, 0, 59, 0, 0, 4,121, 4, 96, 0, 11, 1, 67, 64, 70, 5, 17, 6, 7,
+ 6, 4, 17, 3, 4, 7, 7, 6, 4, 17, 5, 4, 1, 2, 1, 3, 17, 2, 2, 1, 11, 17, 0, 1, 0, 10, 17, 9, 10, 1, 1, 0,
+ 10, 17, 11, 10, 7, 8, 7, 9, 17, 8, 8, 7, 66, 10, 7, 4, 1, 4, 8, 0,191, 5, 2, 10, 7, 4, 1, 4, 8, 0, 2, 8,
+ 6, 12, 16,212, 75,176, 10, 84, 75,176, 15, 84, 91, 75,176, 16, 84, 91, 75,176, 17, 84, 91, 88,185, 0, 6, 0, 64, 56, 89, 75,
+176, 20, 84, 88,185, 0, 6,255,192, 56, 89,196,212,196, 17, 23, 57, 49, 0, 47, 60,236, 50, 23, 57, 48, 75, 83, 88, 7, 16, 5,
+237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,237, 7, 16, 5,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,237, 89, 34, 1,
+ 64,152, 10, 4, 4, 10, 26, 4, 21, 10, 38, 10, 61, 4, 49, 10, 85, 4, 87, 7, 88, 10,102, 10,118, 1,122, 4,118, 7,116, 10,
+141, 4,130, 10,153, 4,159, 4,151, 7,146, 10,144, 10,166, 1,169, 4,175, 4,165, 7,163, 10,160, 10, 28, 10, 3, 4, 5, 5,
+ 9, 10, 11, 26, 3, 21, 5, 21, 9, 26, 11, 41, 3, 38, 5, 37, 9, 42, 11, 32, 13, 58, 1, 57, 3, 55, 5, 52, 7, 54, 9, 57,
+ 11, 48, 13, 73, 3, 70, 5, 69, 9, 74, 11, 64, 13, 89, 0, 86, 1, 89, 2, 89, 3, 87, 5, 86, 6, 89, 7, 86, 8, 86, 9, 89,
+ 11, 80, 13,111, 13,120, 1,127, 13,155, 1,148, 7,171, 1,164, 7,176, 13,207, 13,223, 13,255, 13, 47, 93, 0, 93, 9, 2, 35,
+ 9, 1, 35, 9, 1, 51, 9, 1, 4,100,254,107, 1,170,217,254,186,254,186,217, 1,179,254,114,217, 1, 41, 1, 41, 4, 96,253,
+223,253,193, 1,184,254, 72, 2, 74, 2, 22,254,113, 1,143, 0, 0, 1, 0, 61,254, 86, 4,127, 4, 96, 0, 15, 1,139, 64, 67,
+ 7, 8, 2, 9, 17, 0, 15, 10, 17, 11, 10, 0, 0, 15, 14, 17, 15, 0, 15, 13, 17, 12, 13, 0, 0, 15, 13, 17, 14, 13, 10, 11,
+ 10, 12, 17, 11, 11, 10, 66, 13, 11, 9, 16, 0, 11, 5,135, 3,189, 14, 11,188, 16, 14, 13, 12, 10, 9, 6, 3, 0, 8, 15, 4,
+ 15, 11, 16, 16,212, 75,176, 10, 84, 75,176, 8, 84, 91, 88,185, 0, 11, 0, 64, 56, 89, 75,176, 20, 84, 88,185, 0, 11,255,192,
+ 56, 89,196,196, 17, 23, 57, 49, 0, 16,228, 50,244,236, 17, 57, 17, 57, 18, 57, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 8,237,
+ 7, 16, 8,237, 7, 16, 5,237, 7, 16, 8,237, 7, 5,237, 23, 50, 89, 34, 1, 64,240, 6, 0, 5, 8, 6, 9, 3, 13, 22, 10,
+ 23, 13, 16, 13, 35, 13, 53, 13, 73, 10, 79, 10, 78, 13, 90, 9, 90, 10,106, 10,135, 13,128, 13,147, 13, 18, 10, 0, 10, 9, 6,
+ 11, 5, 12, 11, 14, 11, 15, 23, 1, 21, 2, 16, 4, 16, 5, 23, 10, 20, 11, 20, 12, 26, 14, 26, 15, 39, 0, 36, 1, 36, 2, 32,
+ 4, 32, 5, 41, 8, 40, 9, 37, 10, 36, 11, 36, 12, 39, 13, 42, 14, 42, 15, 32, 17, 55, 0, 53, 1, 53, 2, 48, 4, 48, 5, 56,
+ 10, 54, 11, 54, 12, 56, 13, 57, 14, 57, 15, 48, 17, 65, 0, 64, 1, 64, 2, 64, 3, 64, 4, 64, 5, 64, 6, 64, 7, 64, 8, 66,
+ 9, 69, 10, 71, 13, 73, 14, 73, 15, 64, 17, 84, 0, 81, 1, 81, 2, 85, 3, 80, 4, 80, 5, 86, 6, 85, 7, 86, 8, 87, 9, 87,
+ 10, 85, 11, 85, 12, 89, 14, 89, 15, 80, 17,102, 1,102, 2,104, 10,105, 14,105, 15, 96, 17,123, 8,120, 14,120, 15,137, 0,138,
+ 9,133, 11,133, 12,137, 13,137, 14,137, 15,153, 9,149, 11,149, 12,154, 14,154, 15,164, 11,164, 12,171, 14,171, 15,176, 17,207,
+ 17,223, 17,255, 17,101, 93, 0, 93, 5, 14, 1, 43, 1, 53, 51, 50, 54, 63, 1, 1, 51, 9, 1, 51, 2,147, 78,148,124,147,108,
+ 76, 84, 51, 33,254, 59,195, 1, 94, 1, 94,195,104,200,122,154, 72,134, 84, 4, 78,252,148, 3,108, 0, 0, 0, 0, 1, 0, 88,
+ 0, 0, 3,219, 4, 96, 0, 9, 0,157, 64, 26, 8, 17, 2, 3, 2, 3, 17, 7, 8, 7, 66, 8,169, 0,188, 3,169, 5, 8, 3,
+ 1, 0, 4, 1, 6, 10, 16,220, 75,176, 11, 84, 75,176, 12, 84, 91, 88,185, 0, 6,255,192, 56, 89, 75,176, 19, 84, 88,185, 0,
+ 6, 0, 64, 56, 89,196, 50,196, 17, 57, 57, 49, 0, 47,236,244,236, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 5,237, 89, 34, 1,
+ 64, 66, 5, 2, 22, 2, 38, 2, 71, 2, 73, 7, 5, 11, 8, 15, 11, 24, 3, 27, 8, 43, 8, 32, 11, 54, 3, 57, 8, 48, 11, 64,
+ 1, 64, 2, 69, 3, 64, 4, 64, 5, 67, 8, 87, 3, 89, 8, 95, 11, 96, 1, 96, 2,102, 3, 96, 4, 96, 5, 98, 8,127, 11,128,
+ 11,175, 11, 27, 93, 0, 93, 19, 33, 21, 1, 33, 21, 33, 53, 1, 33,113, 3,106,253, 76, 2,180,252,125, 2,180,253,101, 4, 96,
+168,252,219,147,168, 3, 37, 0, 0, 1, 1, 0,254,178, 4, 23, 6, 20, 0, 36, 0,119, 64, 52, 25, 15, 21, 11, 6, 37, 9, 26,
+ 16, 21, 29, 11, 5, 32, 33, 3, 0, 11,169, 9, 0,169, 1,192, 9, 21,169, 19,177, 37, 12, 9, 10, 5, 36, 22, 25, 0, 29, 10,
+ 5, 19, 2, 20, 0, 32, 25, 67, 10, 15, 5, 37, 16,212, 75,176, 12, 84, 88,185, 0, 5, 0, 64, 56, 89, 60,196,252, 60,196, 50,
+ 57, 57, 17, 18, 57, 17, 18, 57, 57, 17, 18, 57, 57, 49, 0, 16,252,236,196,244,236, 16,238, 18, 23, 57, 18, 57, 17, 57, 57, 17,
+ 18, 57, 17, 18, 57, 57, 48, 1,178, 0, 38, 1, 93, 5, 21, 35, 34, 38, 61, 1, 52, 38, 43, 1, 53, 51, 50, 54, 61, 1, 52, 54,
+ 59, 1, 21, 35, 34, 6, 29, 1, 20, 6, 7, 30, 1, 29, 1, 20, 22, 51, 4, 23, 62,249,169,108,142, 61, 61,143,107,169,249, 62,
+ 68,141, 86, 91,110,111, 90, 86,141,190,144,148,221,239,151,116,143,115,149,240,221,147,143, 88,141,248,157,142, 25, 27,142,156,
+248,141, 88, 0, 0, 1, 1, 4,254, 29, 1,174, 6, 29, 0, 3, 0, 18,183, 1, 0,177, 4, 0, 5, 2, 4, 16,212,236, 49, 0,
+ 16,252,204, 48, 1, 17, 35, 17, 1,174,170, 6, 29,248, 0, 8, 0, 0, 0, 0, 0, 1, 1, 0,254,178, 4, 23, 6, 20, 0, 36,
+ 0,135, 64, 54, 31, 37, 27, 22, 12, 15, 8, 27, 11, 21, 25, 15, 4, 5, 32, 3, 0, 25,169, 27, 0,169, 35,192, 27, 15,169, 17,
+177, 37, 28, 25, 26, 21, 15, 1, 4, 0, 8, 26, 21, 35, 18, 4, 0, 26, 31, 21, 67, 16, 0, 11, 4, 37, 16,212, 75,176, 10, 84,
+ 88,185, 0, 4,255,192, 56, 89, 75,176, 14, 84, 88,185, 0, 4, 0, 64, 56, 89, 60,196, 50,252, 60,196, 17, 18, 57, 57, 17, 18,
+ 57, 17, 18, 57, 57, 17, 18, 57, 57, 49, 0, 16,252,236,196,244,236, 16,238, 18, 23, 57, 17, 18, 57, 57, 17, 57, 17, 57, 57, 17,
+ 18, 57, 48, 1,178, 0, 38, 1, 93, 5, 51, 50, 54, 61, 1, 52, 54, 55, 46, 1, 61, 1, 52, 38, 43, 1, 53, 51, 50, 22, 29, 1,
+ 20, 22, 59, 1, 21, 35, 34, 6, 29, 1, 20, 6, 43, 1, 1, 0, 70,140, 85, 90,111,111, 90, 85,140, 70, 63,249,167,108,142, 62,
+ 62,142,108,167,249, 63,190, 86,143,248,156,142, 27, 25,142,157,248,142, 87,143,147,221,240,149,115,143,116,151,239,221,148, 0,
+ 0, 1, 0,217, 1,211, 5,219, 3, 49, 0, 29, 0, 35, 64, 16, 1, 16, 27, 12, 0, 19, 4,156, 27, 19,156, 12, 30, 0, 15, 30,
+ 16,212,196, 49, 0, 16,212,252,212,236, 16,192, 17, 18, 57, 57, 48, 1, 21, 14, 1, 35, 34, 39, 38, 39, 38, 39, 38, 35, 34, 6,
+ 7, 53, 62, 1, 51, 50, 23, 22, 23, 22, 23, 22, 51, 50, 54, 5,219,105,179, 97,110,146, 11, 5, 7, 15,155, 94, 88,172, 98,105,
+179, 97,110,147, 10, 5, 8, 14,155, 94, 86,169, 3, 49,178, 79, 68, 59, 4, 2, 3, 5, 62, 77, 83,178, 79, 69, 60, 4, 2, 3,
+ 5, 62, 76, 0, 0, 2, 1, 53, 0, 0, 2, 0, 5,213, 0, 3, 0, 9, 0, 98, 64, 15, 7, 0,131, 2,129, 4, 8, 7, 4, 0,
+ 3, 5, 1, 0, 10, 16,252, 60,236, 50, 57, 57, 49, 0, 47,244,252,204, 48, 1, 75,176, 11, 84, 88,189, 0, 10, 0, 64, 0, 1,
+ 0, 10, 0, 10,255,192, 56, 17, 55, 56, 89, 1, 75,176, 15, 84, 75,176, 16, 84, 91, 75,176, 19, 84, 91, 88,189, 0, 10,255,192,
+ 0, 1, 0, 10, 0, 10, 0, 64, 56, 17, 55, 56, 89,182, 0, 11, 32, 11, 80, 11, 3, 93, 1, 35, 53, 51, 17, 35, 17, 19, 51, 19,
+ 2, 0,203,203,203, 21,162, 20, 4,215,254,250, 43, 2,143, 1,101,254,155, 0, 0, 2, 0,172,254,199, 4, 35, 5,152, 0, 6,
+ 0, 33, 0, 81, 64, 43, 19, 22, 20, 0, 15, 12, 1, 11, 7,134, 8,136, 11, 16,134, 15,136, 12,185, 20, 22, 11,185, 29, 31, 28,
+184, 22,140, 34, 28, 21, 0, 9, 30, 19, 11, 15, 7, 4, 18, 25, 34, 16,220,236,212, 60,212, 60, 60,236, 50, 50, 49, 0, 16,228,
+244, 60,196,236, 16,196,254,244,238, 16,245,238, 18, 57, 17, 18, 57, 17, 18, 57, 48, 37, 17, 14, 1, 21, 20, 22, 1, 21, 46, 1,
+ 39, 3, 62, 1, 55, 21, 14, 1, 7, 17, 35, 17, 38, 0, 17, 16, 0, 55, 17, 51, 19, 30, 1, 2,166,147,164,164, 2, 16, 74,136,
+ 68, 1, 70,137, 72, 65,137, 77,102,241,254,247, 1, 9,241,102, 1, 73,137,131, 3, 88, 18,226,184,185,226, 3,161,172, 41, 42,
+ 3,252,160, 5, 42, 39,170, 30, 35, 7,254,228, 1, 32, 20, 1, 51, 1, 1, 1, 2, 1, 50, 22, 1, 31,254,225, 4, 33, 0, 0,
+ 0, 1, 0,129, 0, 0, 4, 98, 5,240, 0, 27, 0, 96, 64, 33, 7, 22, 8, 1,134, 0, 18, 10,169, 20, 8, 12, 4,160, 0,148,
+ 25,145, 16, 12,160, 14, 0, 13, 9, 11, 7, 28, 19, 15, 21, 17, 28, 16,220, 60,204,204,252, 60,196,212,196, 49, 0, 47,236, 50,
+244,228,236, 16,212, 60,238, 50, 16,238, 17, 57, 57, 48, 1, 75,176, 12, 84, 88,189, 0, 28,255,192, 0, 1, 0, 28, 0, 28, 0,
+ 64, 56, 17, 55, 56, 89,180, 54, 1, 54, 2, 2, 0, 93, 1, 21, 46, 1, 35, 34, 6, 29, 1, 33, 21, 33, 17, 33, 21, 33, 53, 51,
+ 17, 35, 53, 51, 53, 16, 54, 51, 50, 22, 4, 78, 76,136, 61,148,116, 1,135,254,121, 2, 45,252, 31,236,199,199,214,232, 61,151,
+ 5,180,182, 41, 41,155,212,215,143,254, 47,170,170, 1,209,143,238, 1, 5,243, 31, 0, 0, 0, 0, 2, 0, 94, 0, 82, 4,188,
+ 4,178, 0, 35, 0, 47, 0,131, 64, 73, 3, 9, 27, 21, 4, 45, 30, 0, 39, 28, 2, 33, 29, 12, 18, 45, 20, 11, 10, 3, 19, 15,
+ 1, 29, 45,185, 19,235, 15,236, 39,185, 29,235, 33, 48, 30, 12, 0, 18, 4, 42, 36, 20, 48, 28, 21, 27, 42, 29, 19, 28, 24, 9,
+ 3, 36, 11, 10, 1, 3, 2, 36, 40, 2,115, 6,116, 42, 40, 28,115, 24, 48, 16,220,228,236,244,228,236, 18, 23, 57, 18, 57, 57,
+ 17, 18, 57, 57, 18, 57, 57, 17, 18, 57, 17, 18, 23, 57, 49, 0, 16,212,228,236,244,228,236, 16,192, 17, 18, 23, 57, 18, 57, 57,
+ 17, 18, 57, 57, 17, 57, 57, 18, 23, 57, 48, 1, 55, 23, 7, 30, 1, 21, 20, 6, 7, 23, 7, 39, 14, 1, 35, 34, 38, 39, 7, 39,
+ 55, 46, 1, 53, 52, 54, 55, 39, 55, 23, 62, 1, 51, 50, 22, 19, 52, 38, 35, 34, 6, 21, 20, 22, 51, 50, 54, 3,123,207,114,206,
+ 37, 36, 38, 40,209,114,207, 59,116, 61, 58,120, 61,207,113,207, 37, 37, 38, 38,207,115,207, 55,116, 64, 60,117, 92,155,114,112,
+158,157,113,113,156, 3,225,209,115,206, 59,119, 62, 63,115, 57,207,113,207, 40, 38, 37, 37,207,115,206, 62,118, 58, 64,116, 56,
+206,115,207, 39, 37, 36,254,124,112,154,154,112,114,156,157, 0, 0, 1, 0, 82, 0, 0, 4,195, 5,213, 0, 24, 0,198, 64, 70,
+ 16, 2, 17, 22, 17, 15, 2, 14, 15, 22, 22, 17, 15, 2, 16, 15, 8, 13, 8, 14, 2, 13, 13, 8, 66, 15, 11, 9, 4, 0,211, 23,
+ 6, 18, 11,211, 20, 9, 16, 13,129, 2, 12, 9, 14, 3, 5, 22, 15, 3, 21, 18, 16, 3, 0, 17,102, 19, 0,101, 1, 28, 13,102,
+ 10, 5,101, 7, 3, 25, 16,212, 60,236, 50,236,252,236, 50,236, 18, 23, 57, 18, 57, 57, 17, 23, 57, 49, 0, 47,228, 50,212, 60,
+236, 50,212, 60,236, 50, 17, 18, 57, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,237, 89, 34, 1,
+ 75,176, 12, 84, 88,189, 0, 25,255,192, 0, 1, 0, 25, 0, 25, 0, 64, 56, 17, 55, 56, 89, 64, 40,134, 15,144, 15,166, 15,160,
+ 15,181, 15, 5, 39, 12, 39, 13, 39, 14, 41, 16, 40, 17, 40, 18, 55, 14, 57, 16,135, 12,136, 18,166, 13,165, 14,170, 16,169, 17,
+ 14, 93, 0, 93, 1, 33, 17, 35, 17, 33, 53, 33, 53, 39, 33, 53, 33, 1, 51, 9, 1, 51, 1, 33, 21, 33, 7, 21, 33, 4,141,254,
+ 99,201,254, 96, 1,160, 84,254,180, 1, 8,254,195,190, 1,123, 1,121,191,254,194, 1, 8,254,181, 84, 1,159, 1,199,254, 57,
+ 1,199,123, 51,155,123, 2, 74,253, 68, 2,188,253,182,123,155, 51, 0, 0, 0, 0, 2, 1, 4,254,162, 1,174, 5,152, 0, 3,
+ 0, 7, 0, 28, 64, 13, 1,245, 0, 4,245, 5, 8, 4, 0, 5, 6, 2, 8, 16,220, 60,236, 50, 49, 0, 16,212,236,212,236, 48,
+ 1, 17, 35, 17, 19, 17, 35, 17, 1,174,170,170,170, 1,152,253, 10, 2,246, 4, 0,253, 10, 2,246, 0, 0, 0, 0, 2, 0, 92,
+255, 61, 3,162, 5,240, 0, 11, 0, 62, 0,145, 64, 60, 47, 48, 42, 6, 0, 23, 29, 48, 54, 4, 13, 39,138, 38, 13,138, 12, 42,
+198, 38,197, 35, 16,198, 12,197, 60,145, 35, 63, 47, 6, 0, 23, 48, 4, 19, 29, 45, 9, 54, 3, 19, 87, 57, 45, 87, 32, 9, 87,
+ 12, 34, 26, 57, 38, 34, 3, 87, 51, 63, 16,220,236,228,196,212,228,236,212,236, 16,238, 17, 57, 17, 18, 57, 17, 23, 57, 57, 49,
+ 0, 16,196,244,228,236, 16,230,238, 16,238, 16,238, 17, 23, 57, 57, 57, 17, 18, 57, 48, 1, 75,176, 10, 84, 75,176, 11, 84, 91,
+ 75,176, 12, 84, 91, 75,176, 14, 84, 91, 88,189, 0, 63, 0, 64, 0, 1, 0, 63, 0, 63,255,192, 56, 17, 55, 56, 89, 1, 14, 1,
+ 21, 20, 22, 23, 62, 1, 53, 52, 38, 19, 21, 46, 1, 35, 34, 6, 21, 20, 23, 22, 23, 30, 1, 21, 20, 6, 7, 30, 1, 21, 20, 6,
+ 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 47, 1, 46, 1, 53, 52, 54, 55, 46, 1, 53, 52, 54, 51, 50, 22, 1,123, 63, 62,
+139,250, 63, 62,143,204, 83,143, 56, 97,108,206, 26, 14,211,131, 92, 93, 62, 57,204,173, 73,154, 88, 87,148, 58,102,113,221, 25,
+214,128, 93, 91, 59, 59,200,166, 73,153, 3,168, 46, 90, 46, 76,133,135, 45, 91, 46, 75,136, 2,147,164, 39, 39, 80, 71, 90,115,
+ 15, 8,119,154,101, 90,140, 53, 52,109, 64,142,168, 29, 29,164, 39, 39, 84, 76,102,123, 14,120,153,102, 91,143, 49, 44,112, 69,
+130,159, 29, 0, 0, 2, 0,215, 5, 70, 3, 41, 6, 16, 0, 3, 0, 7, 0,146, 64, 14, 6, 2,206, 4, 0,205, 8, 1,100, 0,
+ 5,100, 4, 8, 16,220,252,212,236, 49, 0, 16,252, 60,236, 50, 48, 0, 75,176, 10, 84, 75,176, 13, 84, 91, 88,189, 0, 8, 0,
+ 64, 0, 1, 0, 8, 0, 8,255,192, 56, 17, 55, 56, 89, 1, 75,176, 12, 84, 75,176, 13, 84, 91, 75,176, 14, 84, 91, 75,176, 23,
+ 84, 91, 88,189, 0, 8,255,192, 0, 1, 0, 8, 0, 8, 0, 64, 56, 17, 55, 56, 89, 1, 75,176, 15, 84, 75,176, 25, 84, 91, 88,
+189, 0, 8, 0, 64, 0, 1, 0, 8, 0, 8,255,192, 56, 17, 55, 56, 89, 64, 17, 96, 1, 96, 2, 96, 5, 96, 6,112, 1,112, 2,
+112, 5,112, 6, 8, 93, 1, 51, 21, 35, 37, 51, 21, 35, 2, 94,203,203,254,121,203,203, 6, 16,202,202,202, 0, 0, 3, 1, 27,
+ 0, 0, 6,229, 5,205, 0, 23, 0, 47, 0, 73, 0, 67, 64, 38, 61,203, 62, 58,204, 65,202, 36, 49,203, 48, 52,204, 71,202, 24,
+201, 0,200, 36,201, 12, 55, 97, 68, 61, 48, 94, 42, 9, 6, 68, 94, 30, 9, 6, 18, 74, 16,220,204,252,236, 16,254,237, 50, 16,
+238, 49, 0, 47,238,246,254,253,238,214,238, 16,253,238,214,238, 48, 1, 50, 4, 23, 22, 18, 21, 20, 2, 7, 6, 4, 35, 34, 36,
+ 39, 38, 2, 53, 52, 18, 55, 54, 36, 23, 34, 6, 7, 14, 1, 21, 20, 22, 23, 30, 1, 51, 50, 54, 55, 62, 1, 53, 52, 38, 39, 46,
+ 1, 23, 21, 46, 1, 35, 34, 6, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 53, 52, 54, 51, 50, 22, 4, 0,152, 1, 7,
+109,109,108,108,109,109,254,249,152,152,254,249,109,109,108,108,109,109, 1, 7,152,131,226, 94, 94, 96, 96, 94, 94,226,131,132,
+227, 94, 93, 93, 94, 92, 94,227,167, 66,130, 66,149,167,171,155, 64,122, 66, 67,137, 70,216,251,251,216, 73,136, 5,205,110,109,
+109,254,250,154,152,254,251,109,109,110,110,109,109, 1, 5,152,154, 1, 6,109,109,110,103, 94, 94, 94,229,130,129,227, 94, 94,
+ 95, 95, 94, 93,226,131,133,227, 93, 94, 94,245,129, 33, 32,175,157,159,174, 31, 34,127, 29, 28,244,208,209,242, 28, 0, 0, 0,
+ 0, 3, 0,115, 1,213, 3, 59, 5,240, 0, 3, 0, 30, 0, 41, 0, 95, 64, 51, 40, 7, 37, 4, 31, 18, 24, 16, 2,227, 0, 31,
+221, 16, 0,225, 37,221, 5, 10, 25,223, 24,222, 21,221, 10,224, 28,145, 42, 0, 24, 13, 31, 16, 34, 6, 2, 1, 40, 17, 6,107,
+ 4,108, 24, 34,107, 13, 42, 16,220,236,204,252,236, 50, 50,192,192, 17, 18, 57, 57, 17, 18, 57, 49, 0, 16,244,228,252,244,236,
+ 16,196,238,237,214,238, 16,238, 17, 18, 57, 18, 57, 17, 57, 57, 48, 19, 33, 21, 33, 1, 17, 35, 53, 14, 1, 35, 34, 38, 53, 52,
+ 54, 59, 1, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 5, 34, 6, 21, 20, 22, 51, 50, 54, 61, 1,139, 2,176,253, 80,
+ 2,174,149, 44,144, 93,128,152,191,188,182,117,117, 62,136, 68, 73,145, 69,183,179,254,236,161,126, 98, 82,104,130, 2, 80,123,
+ 2,184,254, 64,112, 63, 68,135,113,135,138, 4, 91, 91, 34, 34,127, 28, 28,176,240, 67, 79, 64, 77,144,114, 29, 0, 2, 0,158,
+ 0,141, 4, 37, 4, 35, 0, 6, 0, 13, 0,134, 64, 73, 3,232, 4, 5, 4, 2,232, 1, 2, 5, 5, 4, 2,232, 3, 2, 6, 0,
+ 6, 1,232, 0, 0, 6, 10,232, 11, 12, 11, 9,232, 8, 9, 12, 12, 11, 9,232, 10, 9, 13, 7, 13, 8,232, 7, 7, 13, 66, 9,
+ 2, 11, 4,231, 7, 0,166, 14, 9, 12, 5, 2, 7, 3, 0,111, 5, 10, 7,111, 12,110, 14, 16,252,252, 60,212,236, 50, 17, 57,
+ 17, 18, 57, 49, 0, 16,244, 60,236, 50, 57, 57, 48, 75, 83, 88, 7, 16, 4,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 4,237,
+ 7, 16, 4,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 4,237, 89, 34, 1, 21, 9, 1, 21, 1, 53, 19, 21, 9, 1, 21, 1, 53,
+ 4, 37,254,211, 1, 45,254, 43, 35,254,211, 1, 45,254, 43, 4, 35,191,254,244,254,244,191, 1,162, 82, 1,162,191,254,244,254,
+244,191, 1,162, 82, 0, 0, 0, 0, 1, 0,217, 1, 31, 5,219, 3, 94, 0, 5, 0, 23, 64, 10, 4,156, 2, 0, 6, 3, 23, 1,
+ 0, 6, 16,220,212,236, 49, 0, 16,212,196,236, 48, 19, 33, 17, 35, 17, 33,217, 5, 2,168,251,166, 3, 94,253,193, 1,149, 0,
+ 0, 1, 0,100, 1,223, 2,127, 2,131, 0, 3, 0, 17,182, 0,156, 2, 4, 1, 0, 4, 16,220,204, 49, 0, 16,212,236, 48, 19,
+ 33, 21, 33,100, 2, 27,253,229, 2,131,164, 0, 0, 4, 1, 27, 0, 0, 6,229, 5,205, 0, 23, 0, 47, 0, 56, 0, 76, 0, 96,
+ 64, 54, 69, 66, 67, 63, 50,201, 72, 48,201, 57, 74, 67,202, 12, 57,202, 0,201, 24,200, 12,201, 36, 72, 69, 51, 48, 4, 49, 66,
+ 60, 63, 57, 54, 73, 49, 96, 75, 54, 96, 67, 60, 94, 18, 9, 30, 75, 94, 6, 9, 30, 95, 42, 77, 16,220,228,252,236, 16,254,253,
+196,238, 16,238, 50, 17, 57, 57, 18, 57, 18, 23, 57, 49, 0, 47,238,246,254,237, 16,237, 50, 16,238,214,238, 57, 18, 57, 57, 48,
+ 1, 34, 6, 7, 14, 1, 21, 20, 22, 23, 30, 1, 51, 50, 54, 55, 62, 1, 53, 52, 38, 39, 46, 1, 39, 50, 4, 23, 22, 18, 21, 20,
+ 2, 7, 6, 4, 35, 34, 36, 39, 38, 2, 53, 52, 18, 55, 54, 36, 19, 35, 17, 51, 50, 54, 53, 52, 38, 39, 50, 22, 21, 20, 6, 7,
+ 30, 1, 31, 1, 35, 39, 46, 1, 43, 1, 17, 35, 17, 4, 0,131,226, 94, 94, 96, 96, 94, 94,226,131,132,227, 94, 93, 93, 94, 92,
+ 94,227,132,152, 1, 7,109,109,108,108,109,109,254,249,152,152,254,249,109,109,108,108,109,109, 1, 7,125,123,123,110, 87, 88,
+102,176,174,105, 96, 24, 67, 46,137,172,129, 59, 73, 54, 66,155, 5,102, 94, 94, 94,229,130,129,227, 94, 94, 95, 95, 94, 93,226,
+131,133,227, 93, 94, 94,103,110,109,109,254,250,154,152,254,251,109,109,110,110,109,109, 1, 5,152,154, 1, 6,109,109,110,254,
+ 98,254,236, 62, 75, 76, 63,103,119,121, 86,112, 17, 8, 77, 73,223,209, 96, 51,254,156, 3, 68, 0, 1, 0,213, 5, 98, 3, 43,
+ 5,246, 0, 3, 0, 47,183, 2,239, 0,238, 4, 1, 0, 4, 16,212,204, 49, 0, 16,252,236, 48, 0, 75,176, 9, 84, 75,176, 14,
+ 84, 91, 88,189, 0, 4,255,192, 0, 1, 0, 4, 0, 4, 0, 64, 56, 17, 55, 56, 89, 19, 33, 21, 33,213, 2, 86,253,170, 5,246,
+148, 0, 0, 0, 0, 2, 0,195, 3,117, 3, 61, 5,240, 0, 11, 0, 26, 0, 32, 64, 17, 6,195, 21,196, 0,195, 12,145, 27, 9,
+ 90, 18, 91, 3, 90, 24, 27, 16,220,236,252,236, 49, 0, 16,244,236,252,236, 48, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38,
+ 39, 50, 22, 23, 30, 1, 21, 20, 6, 35, 34, 38, 53, 52, 54, 2, 0, 80,110,110, 80, 80,110,111, 79, 64,118, 43, 46, 46,185,134,
+135,180,184, 5,111,111, 80, 79,109,109, 79, 79,112,129, 49, 46, 45,114, 66,132,183,180,135,134,186, 0, 0, 0, 0, 2, 0,217,
+ 0, 0, 5,219, 5, 4, 0, 11, 0, 15, 0, 46, 64, 24, 5,208, 7, 3,156, 0,208, 9, 1, 12,156, 14, 13, 2, 21, 4, 0, 23,
+ 12, 8, 21, 10, 6, 16, 16,212, 60,236, 50,252, 60,236, 50, 49, 0, 47,236,212, 60,236,252, 60,236, 48, 1, 17, 33, 21, 33, 17,
+ 35, 17, 33, 53, 33, 17, 1, 33, 21, 33, 3,174, 2, 45,253,211,168,253,211, 2, 45,253,211, 5, 2,250,254, 5, 4,254,125,170,
+254,125, 1,131,170, 1,131,251,166,170, 0, 0, 0, 1, 0, 94, 2,156, 2,180, 5,240, 0, 24, 0, 74, 64, 36, 0,125, 6, 4,
+ 0, 23,125, 6, 6, 4, 66, 4, 2, 0, 14,221, 15, 0,221, 2,247, 11,221, 15, 18,145, 25, 0, 14, 8,126, 1, 21, 14, 3, 25,
+ 16,220,196,212,196,236, 17, 57, 49, 0, 16,244,196,236,252,236, 16,238, 17, 18, 57, 48, 75, 83, 88, 7, 16, 5,237, 23, 50, 7,
+ 5,237, 89, 34, 1, 33, 21, 33, 53, 54, 55, 0, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 21, 20, 1, 6, 1, 12, 1,
+168,253,170, 34, 63, 1, 88,104, 85, 52,122, 72, 77,133, 57,145,174,254,181, 56, 3, 14,114,110, 31, 56, 1, 49, 94, 66, 81, 35,
+ 35,123, 28, 28,132,108,139,254,228, 48, 0, 0, 0, 1, 0, 98, 2,141, 2,205, 5,240, 0, 40, 0, 72, 64, 39, 0, 21, 19, 10,
+221, 9, 31,221, 32, 19,221, 21, 13,221, 9,248, 6,247, 28,221, 32,248, 35,145, 41, 22, 19, 0, 20, 25,126, 38, 16,126, 3, 20,
+ 31, 9, 41, 16,220,196,196,212,236,212,236, 17, 57, 57, 57, 49, 0, 16,244,228,236,252,228,236,212,236, 16,238, 16,238, 17, 18,
+ 57, 48, 1, 30, 1, 21, 20, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 43, 1, 53, 51, 50, 54, 53, 52, 38, 35, 34,
+ 6, 7, 53, 62, 1, 51, 50, 22, 21, 20, 6, 2, 12, 92,101,190,177, 57,125, 70, 52,119, 67,109,120,111,108, 86, 94, 94, 97,100,
+ 95, 40,102, 81, 73,128, 55,144,169, 90, 4, 96, 18,109, 82,124,134, 21, 20,121, 27, 26, 79, 70, 74, 76,108, 63, 60, 58, 61, 18,
+ 23,115, 17, 18,118, 99, 69, 96, 0, 1, 1,115, 4,238, 3, 82, 6,102, 0, 3, 0, 49, 64, 9, 2,180, 0,179, 4, 3, 68, 1,
+ 4, 16,212,236, 49, 0, 16,244,236, 48, 0, 75,176, 9, 84, 75,176, 14, 84, 91, 88,189, 0, 4,255,192, 0, 1, 0, 4, 0, 4,
+ 0, 64, 56, 17, 55, 56, 89, 1, 51, 1, 35, 2,139,199,254,186,153, 6,102,254,136, 0, 0, 0, 0, 1, 0,174,254, 86, 4,229,
+ 4, 96, 0, 32, 0, 77, 64, 37, 19, 25, 31, 3, 22, 6, 3, 9, 12, 3, 1, 18, 15, 6,135, 28, 22,140, 10, 1,188, 0,189, 33,
+ 25, 9, 18, 9, 8, 11, 78, 31, 2, 8, 0, 70, 33, 16,252,236, 50,244,236,196, 18, 57, 49, 0, 16,228,228, 50,244, 60,236,220,
+196, 17, 23, 57, 17, 18, 23, 57, 48,182, 31, 34, 96, 34,207, 34, 3, 1, 93, 19, 17, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17,
+ 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 39, 14, 1, 35, 34, 38, 39, 17,174,184,138,135,148,149,184, 35, 37, 9, 32, 28,
+ 41, 73, 35, 69, 82, 15, 50,145, 98,102,143, 42,254, 86, 6, 10,253, 72,145,148,168,168, 2,141,252,162, 60, 57, 11, 12,148, 23,
+ 22, 78, 80, 79, 79, 78, 78,253,215, 0, 0, 0, 0, 1, 0,158,255, 59, 4, 57, 5,213, 0, 13, 0, 37, 64, 18, 8, 2, 4,193,
+ 0,129, 6, 2, 14, 0, 7, 93, 5, 3, 93, 1, 11, 14, 16,212,212,252,220,236, 57, 49, 0, 16,196, 50,244,236, 17, 57, 48, 1,
+ 33, 17, 35, 17, 35, 17, 35, 17, 46, 1, 53, 52, 36, 2,121, 1,192,141,190,142,215,235, 1, 4, 5,213,249,102, 6, 31,249,225,
+ 3, 78, 17,221,184,190,232, 0, 0, 1, 0,219, 2, 72, 1,174, 3, 70, 0, 3, 0, 18,183, 2,131, 0, 4, 1, 25, 0, 4, 16,
+212,236, 49, 0, 16,212,236, 48, 19, 51, 21, 35,219,211,211, 3, 70,254, 0, 0, 0, 1, 1, 35,254,117, 2,193, 0, 0, 0, 19,
+ 0, 31, 64, 14, 9, 6, 10, 13,243, 6, 0, 19, 0, 16, 39, 3, 9, 20, 16,220,212,236,212,204, 49, 0, 47,212,252,196, 18, 57,
+ 48, 33, 30, 1, 21, 20, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 39, 2, 84, 55, 54,120,118, 46, 87, 43, 34, 74,
+ 47, 59, 60, 43, 45, 62,105, 48, 89, 91, 12, 12,131, 17, 15, 48, 46, 30, 87, 61, 0, 1, 0,137, 2,156, 2,197, 5,223, 0, 10,
+ 0, 44, 64, 24, 7, 0,221, 9, 3,221, 4, 2,221, 9,247, 5,145, 11, 8,124, 6, 93, 3,124, 1,124, 0, 11, 16,220,244,228,
+252,228, 49, 0, 16,244,236,236,212,236, 16,238, 50, 48, 19, 51, 17, 7, 53, 55, 51, 17, 51, 21, 33,156,204,223,230,137,205,253,
+215, 3, 10, 2, 99, 41,116, 39,253, 43,110, 0, 0, 3, 0, 96, 1,213, 3,100, 5,240, 0, 3, 0, 15, 0, 27, 0, 46, 64, 25,
+ 2,227, 0,225, 22,221, 10,224, 16,221, 4,145, 28, 0, 19, 13, 1, 25,107, 7,108, 19,107, 13, 28, 16,220,236,252,236, 57, 17,
+ 18, 57, 49, 0, 16,244,236,244,236,252,236, 48, 19, 33, 21, 33, 1, 50, 22, 21, 20, 6, 35, 34, 38, 53, 52, 54, 23, 34, 6, 21,
+ 20, 22, 51, 50, 54, 53, 52, 38,139, 2,176,253, 80, 1, 88,179,206,206,179,179,208,208,179,105,126,127,104,105,125,124, 2, 80,
+123, 4, 27,221,191,191,219,220,190,191,221,115,161,136,133,160,160,133,137,160, 0, 2, 0,193, 0,141, 4, 72, 4, 35, 0, 6,
+ 0, 13, 0,134, 64, 73, 12,232, 13, 12, 9, 10, 9, 11,232, 10, 10, 9, 13,232, 7, 8, 7, 12,232, 11, 12, 8, 8, 7, 5,232,
+ 6, 5, 2, 3, 2, 4,232, 3, 3, 2, 6,232, 0, 1, 0, 5,232, 4, 5, 1, 1, 0, 66, 12, 5, 10, 3,231, 7, 0,166, 14,
+ 12, 8, 1, 5, 0, 8,111, 10, 7, 1,111, 3, 0,112, 14, 16,252, 60,252,212, 60,236, 18, 57, 17, 18, 57, 49, 0, 16,244, 60,
+236, 50, 57, 57, 48, 75, 83, 88, 7, 16, 8,237, 7, 16, 4,237, 7, 16, 4,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 4,237,
+ 7, 16, 4,237, 7, 16, 8,237, 89, 34, 19, 1, 21, 1, 53, 9, 1, 37, 1, 21, 1, 53, 9, 1,193, 1,213,254, 43, 1, 45,254,
+211, 1,178, 1,213,254, 43, 1, 45,254,211, 4, 35,254, 94, 82,254, 94,191, 1, 12, 1, 12,191,254, 94, 82,254, 94,191, 1, 12,
+ 1, 12, 0, 0,255,255, 0,137,255,227, 7,127, 5,240, 16, 39, 5,206, 4,139,253,100, 16, 38, 0,123, 0, 0, 16, 7, 6, 90,
+ 3, 53, 0, 0,255,255, 0,137,255,227, 7, 63, 5,240, 16, 38, 0,123, 0, 0, 16, 39, 6, 90, 3, 53, 0, 0, 16, 7, 0,116,
+ 4,139,253,100,255,255, 0, 98,255,227, 7,127, 5,240, 16, 39, 5,206, 4,139,253,100, 16, 38, 0,117, 0, 0, 16, 7, 6, 90,
+ 3, 53, 0, 0, 0, 2, 0,143,255,227, 3,172, 5,213, 0, 32, 0, 36, 0,134, 64, 47, 32, 26, 5, 2, 4, 6, 25, 0, 16,134,
+ 15,136, 12, 0, 33,131, 35, 12,149, 19,140, 35,129, 37, 6, 34, 25, 22, 9, 5, 1, 0, 26, 34, 9, 0, 28, 1, 34, 28, 33, 38,
+ 15, 9, 28, 22, 37, 16,220,236,212,252,236,212,236, 17, 18, 57, 17, 18, 57, 17, 18, 57, 18, 57, 49, 0, 16,228,244,236, 16,254,
+205, 16,244,238, 18, 57, 57, 23, 57, 48, 1, 75,176, 16, 84, 75,176, 18, 84, 91, 75,176, 19, 84, 91, 88,189, 0, 37,255,192, 0,
+ 1, 0, 37, 0, 37, 0, 64, 56, 17, 55, 56, 89, 64, 11,116, 4,116, 5,116, 6,116, 7,118, 28, 5, 93, 1, 51, 21, 20, 6, 15,
+ 1, 14, 1, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 53, 52, 54, 63, 1, 62, 1, 55, 62, 1, 53, 19, 35, 53, 51, 1,
+244,190, 55, 90, 90, 58, 51,131,109, 78,180, 96, 94,192,103,184,224, 73, 89, 88, 48, 38, 8, 7, 6,196,202,202, 4, 68,156,101,
+130, 87, 88, 53, 94, 49, 89,110, 70, 67,188, 57, 56,194,159, 76,137, 86, 86, 47, 53, 25, 21, 60, 54, 1, 14,254,255,255, 0, 16,
+ 0, 0, 5,104, 5,213, 18, 38, 0, 36, 0, 0, 16, 7, 6,135, 4,188, 1,117,255,255, 0, 16, 0, 0, 5,104, 5,213, 18, 38,
+ 0, 36, 0, 0, 16, 7, 6,133, 4,188, 1,117,255,255, 0, 16, 0, 0, 5,104, 5,213, 18, 38, 0, 36, 0, 0, 17, 7, 6,136,
+ 4,188, 1,117, 0, 16,180, 5, 13, 17, 10, 7, 43, 64, 5, 15, 13, 0, 17, 2, 93, 49, 0, 0,255,255, 0, 16, 0, 0, 5,104,
+ 5,213, 18, 38, 0, 36, 0, 0, 17, 7, 6,134, 4,188, 1,117, 0, 20,180, 10, 20, 35, 5, 7, 43, 64, 9, 64, 20, 79, 35, 32,
+ 20, 47, 35, 4, 93, 49, 0, 0,255,255, 0, 16, 0, 0, 5,104, 5,213, 18, 38, 0, 36, 0, 0, 17, 7, 6,132, 4,188, 1,117,
+ 0, 20,180, 10, 18, 13, 5, 7, 43, 64, 9, 48, 18, 63, 13, 0, 18, 15, 13, 4, 93, 49, 0, 0, 0, 3, 0, 16, 0, 0, 5,104,
+ 7,109, 0, 11, 0, 14, 0, 33, 0,203, 64, 84, 12, 17, 13, 12, 27, 28, 27, 14, 17, 28, 27, 30, 17, 28, 27, 29, 17, 28, 28, 27,
+ 13, 17, 33, 15, 33, 12, 17, 14, 12, 15, 15, 33, 32, 17, 15, 33, 31, 17, 33, 15, 33, 66, 12, 27, 15, 13, 9, 3,193, 21, 9, 30,
+149, 13, 9,142, 32, 28, 30, 29, 28, 24, 32, 31, 33, 13, 18, 6, 14, 24, 12, 6, 27, 0, 86, 24, 28, 15, 6, 86, 18, 28, 33, 34,
+ 16,212,196,212,236, 50, 16,212,238, 50, 17, 57, 17, 57, 17, 18, 57, 17, 57, 57, 17, 18, 57, 57, 49, 0, 47, 60,230,214,238, 16,
+212,238, 17, 18, 57, 57, 57, 48, 75, 83, 88, 7, 16, 5,237, 7, 5,237, 7, 16, 8,237, 7, 16, 5,237, 7, 16, 5,237, 7, 5,
+237, 7, 5,237, 7, 16, 8,237, 89, 34,178, 32, 35, 1, 1, 93, 64, 32, 26, 12,115, 12,155, 12, 3, 7, 15, 8, 27, 80, 35,102,
+ 13,105, 14,117, 13,123, 14,121, 28,121, 29,118, 32,118, 33,128, 35, 12, 93, 0, 93, 1, 52, 38, 35, 34, 6, 21, 20, 22, 51, 50,
+ 54, 3, 1, 33, 1, 46, 1, 53, 52, 54, 51, 50, 22, 21, 20, 6, 7, 1, 35, 3, 33, 3, 35, 3, 84, 89, 63, 64, 87, 88, 63, 63,
+ 89,152,254,240, 2, 33,254, 88, 61, 62,159,115,114,161, 63, 60, 2, 20,210,136,253, 95,136,213, 6, 90, 63, 89, 87, 65, 63, 88,
+ 88,254,243,253, 25, 3, 78, 41,115, 73,115,160,161,114, 70,118, 41,250,139, 1,127,254,129, 0, 0, 2, 0, 8, 0, 0, 7, 72,
+ 5,213, 0, 15, 0, 19, 0,135, 64, 57, 17, 17, 14, 15, 14, 16, 17, 15, 15, 14, 13, 17, 15, 14, 12, 17, 14, 15, 14, 66, 5,149,
+ 3, 11,149, 17, 1,149, 16,149, 0,129, 17, 7,149, 3,173, 13, 9, 17, 16, 15, 13, 12, 5, 14, 10, 0, 4, 8, 6, 2, 28, 18,
+ 10, 14, 20, 16,212,212, 60,236, 50,212,196,196, 17, 18, 23, 57, 49, 0, 47, 60,236,236,196,244,236,236, 16,238, 16,238, 48, 75,
+ 83, 88, 7, 16, 5,237, 7, 5,237, 7, 16, 5,237, 7, 16, 5,237, 89, 34,178,128, 21, 1, 1, 93, 64, 19,103, 17,119, 16,119,
+ 17,134, 12,133, 16,150, 17,144, 21,160, 21,191, 21, 9, 93, 1, 21, 33, 17, 33, 21, 33, 17, 33, 21, 33, 17, 33, 3, 35, 1, 23,
+ 1, 33, 17, 7, 53,253, 27, 2,199,253, 57, 2,248,252, 61,253,240,160,205, 2,113,139,254,182, 1,203, 5,213,170,254, 70,170,
+253,227,170, 1,127,254,129, 5,213,158,252,240, 3, 16, 0, 0,255,255, 0,115,254,117, 5, 39, 5,240, 18, 38, 0, 38, 0, 0,
+ 16, 7, 0,122, 1, 45, 0, 0,255,255, 0,201, 0, 0, 4,139, 5,213, 18, 38, 0, 40, 0, 0, 16, 7, 6,135, 4,158, 1,117,
+255,255, 0,201, 0, 0, 4,139, 5,213, 18, 38, 0, 40, 0, 0, 16, 7, 6,133, 4,158, 1,117,255,255, 0,201, 0, 0, 4,139,
+ 5,213, 18, 38, 0, 40, 0, 0, 17, 7, 6,136, 4,158, 1,117, 0, 7, 64, 3, 64, 12, 1, 93, 49, 0, 0, 0,255,255, 0,201,
+ 0, 0, 4,139, 5,213, 18, 38, 0, 40, 0, 0, 17, 7, 6,132, 4,158, 1,117, 0, 9, 64, 5, 64, 12, 64, 16, 2, 93, 49, 0,
+255,255, 0,201, 0, 0, 1,147, 5,213, 18, 38, 0, 44, 0, 0, 16, 7, 6,135, 3, 47, 1,117,255,255, 0,201, 0, 0, 1,147,
+ 5,213, 18, 38, 0, 44, 0, 0, 16, 7, 6,133, 3, 47, 1,117,255,255, 0,201, 0, 0, 1,147, 5,213, 18, 38, 0, 44, 0, 0,
+ 17, 7, 6,136, 3, 47, 1,117, 0, 8,180, 1, 6, 10, 0, 7, 43, 49, 0, 0,255,255, 0,201, 0, 0, 1,147, 5,213, 18, 38,
+ 0, 44, 0, 0, 17, 7, 6,132, 3, 47, 1,117, 0, 8,180, 0, 10, 7, 1, 7, 43, 49, 0, 0, 0, 2, 0, 10, 0, 0, 5,186,
+ 5,213, 0, 12, 0, 25, 0,103, 64, 32, 16, 9,169, 11, 13,149, 0,129, 18,149, 14, 11, 7, 7, 1, 25, 19, 4, 15, 13, 22, 25,
+ 4, 50, 10, 17, 13, 28, 8, 0,121, 26, 16,244, 60,236, 50,196,244,236, 16,196, 23, 57, 49, 0, 47,198, 50,238,246,238, 16,238,
+ 50, 48, 64, 40, 32, 27,127, 27,176, 27, 3,159, 9,159, 10,159, 11,159, 12,159, 14,159, 15,159, 16,159, 17,191, 9,191, 10,191,
+ 11,191, 12,191, 14,191, 15,191, 16,191, 17, 16, 93, 1, 93, 19, 33, 32, 0, 17, 16, 0, 41, 1, 17, 35, 53, 51, 19, 17, 33, 21,
+ 33, 17, 51, 32, 0, 17, 16, 0, 33,211, 1,160, 1,177, 1,150,254,105,254, 80,254, 96,201,201,203, 1, 80,254,176,243, 1, 53,
+ 1, 31,254,225,254,203, 5,213,254,151,254,128,254,126,254,150, 2,188,144, 1,227,254, 29,144,253,234, 1, 24, 1, 46, 1, 44,
+ 1, 23, 0, 0,255,255, 0,201, 0, 0, 5, 51, 5,213, 18, 38, 0, 49, 0, 0, 17, 7, 6,134, 4,254, 1,117, 0, 20,180, 0,
+ 19, 34, 4, 7, 43, 64, 9, 48, 19, 63, 34, 16, 19, 31, 34, 4, 93, 49, 0, 0,255,255, 0,115,255,227, 5,217, 5,240, 18, 38,
+ 0, 50, 0, 0, 16, 7, 6,135, 5, 39, 1,117,255,255, 0,115,255,227, 5,217, 5,240, 18, 38, 0, 50, 0, 0, 16, 7, 6,133,
+ 5, 39, 1,117,255,255, 0,115,255,227, 5,217, 5,240, 18, 38, 0, 50, 0, 0, 17, 7, 6,136, 5, 39, 1,117, 0, 16,180, 15,
+ 26, 30, 21, 7, 43, 64, 5, 31, 26, 16, 30, 2, 93, 49, 0, 0,255,255, 0,115,255,227, 5,217, 5,240, 18, 38, 0, 50, 0, 0,
+ 17, 7, 6,134, 5, 39, 1,117, 0, 24,180, 3, 33, 48, 9, 7, 43, 64, 13, 48, 33, 63, 48, 32, 33, 47, 48, 16, 33, 31, 48, 6,
+ 93, 49, 0, 0,255,255, 0,115,255,227, 5,217, 5,240, 18, 38, 0, 50, 0, 0, 17, 7, 6,132, 5, 39, 1,117, 0, 20,180, 3,
+ 31, 26, 9, 7, 43, 64, 9, 64, 31, 79, 26, 16, 31, 31, 26, 4, 93, 49, 0, 0, 0, 1, 1, 25, 0, 63, 5,156, 4,197, 0, 11,
+ 0,133, 64, 77, 10,156, 11, 10, 7, 8, 7, 9,156, 8, 8, 7, 4,156, 3, 4, 7, 7, 6, 5,156, 6, 7, 6, 4,156, 5, 4,
+ 1, 2, 1, 3,156, 2, 2, 1, 11,156, 0, 1, 0, 10,156, 9, 10, 1, 1, 0, 66, 10, 8, 7, 6, 4, 2, 1, 0, 8, 5, 3,
+ 11, 9, 12, 11, 10, 9, 7, 5, 4, 3, 1, 8, 2, 0, 8, 6, 12, 16,212, 60,204, 50, 23, 57, 49, 0, 16,212, 60,204, 50, 23,
+ 57, 48, 75, 83, 88, 7, 16, 8,237, 7, 16, 5,237, 7, 16, 5,237, 7, 16, 8,237, 7, 16, 5,237, 7, 16, 8,237, 7, 16, 5,
+237, 7, 16, 8,237, 89, 34, 9, 2, 7, 9, 1, 39, 9, 1, 55, 9, 1, 5,156,254, 55, 1,201,119,254, 53,254, 53,118, 1,200,
+254, 56,118, 1,203, 1,203, 4, 76,254, 53,254, 55,121, 1,203,254, 53,121, 1,201, 1,203,121,254, 53, 1,203, 0, 3, 0,102,
+255,186, 5,229, 6, 23, 0, 9, 0, 19, 0, 43, 0,158, 64, 60, 29, 31, 26, 13, 43, 44, 19, 10, 1, 0, 4, 13, 41, 38, 32, 20,
+ 13, 4, 42, 38, 30, 26, 4,149, 38, 13,149, 26,145, 38,140, 44, 43, 44, 42, 20, 23, 16, 32, 30, 35, 19, 10, 1, 0, 4, 29, 41,
+ 16, 7, 31, 7, 25, 35, 51, 16, 25, 23, 16, 44, 16,252,236,252,236,192, 17, 18, 57, 57, 23, 57, 18, 57, 57, 17, 18, 57, 57, 17,
+ 57, 49, 0, 16,228,244,236, 16,238, 16,192, 16,192, 17, 18, 57, 57, 18, 57, 18, 23, 57, 18, 57, 17, 18, 57, 57, 48, 64, 42, 87,
+ 0, 90, 21, 87, 25, 85, 33,106, 21,101, 33,123, 21,118, 28,117, 33, 9, 70, 19, 89, 0, 86, 19,106, 0,100, 19,100, 28,106, 40,
+124, 0,115, 19,118, 28,122, 40, 11, 93, 1, 93, 9, 1, 30, 1, 51, 50, 0, 17, 52, 38, 39, 46, 1, 35, 34, 0, 17, 20, 22, 23,
+ 7, 38, 2, 53, 16, 0, 33, 50, 22, 23, 55, 23, 7, 22, 18, 21, 16, 0, 33, 34, 38, 39, 7, 39, 4,182,253, 51, 62,161, 95,220,
+ 1, 1, 39,121, 61,161, 95,220,254,253, 39, 39,134, 78, 79, 1,121, 1, 59,130,221, 87,162,102,170, 78, 80,254,136,254,198,128,
+221, 91,162,103, 4, 88,252,178, 64, 67, 1, 72, 1, 26,112,184,184, 64, 67,254,184,254,229,112,188, 68,158,102, 1, 8,160, 1,
+ 98, 1,165, 77, 75,191, 89,198,103,254,246,158,254,159,254, 91, 75, 75,191, 88,255,255, 0,178,255,227, 5, 41, 5,213, 18, 38,
+ 0, 56, 0, 0, 16, 7, 6,135, 4,238, 1,117,255,255, 0,178,255,227, 5, 41, 5,213, 18, 38, 0, 56, 0, 0, 16, 7, 6,133,
+ 4,238, 1,117,255,255, 0,178,255,227, 5, 41, 5,213, 18, 38, 0, 56, 0, 0, 17, 7, 6,136, 4,238, 1,117, 0, 20,180, 10,
+ 20, 24, 0, 7, 43, 64, 9, 47, 20, 32, 24, 31, 20, 16, 24, 4, 93, 49, 0, 0,255,255, 0,178,255,227, 5, 41, 5,213, 18, 38,
+ 0, 56, 0, 0, 17, 7, 6,132, 4,238, 1,117, 0, 28,180, 1, 25, 20, 9, 7, 43, 64, 17, 80, 25, 95, 20, 64, 25, 79, 20, 32,
+ 25, 47, 20, 16, 25, 31, 20, 8, 93, 49, 0, 0,255,255,255,252, 0, 0, 4,231, 5,213, 18, 38, 0, 60, 0, 0, 16, 7, 6,133,
+ 4,115, 1,117, 0, 2, 0,201, 0, 0, 4,141, 5,213, 0, 12, 0, 21, 0, 61, 64, 27, 14,149, 9, 13,149, 2,246, 0,129, 11,
+ 21, 15, 9, 3, 4, 1, 18, 25, 6, 63, 13, 10, 1, 28, 0, 4, 22, 16,252,236, 50, 50,252,236, 17, 23, 57, 49, 0, 47,244,252,
+236,212,236, 48, 64, 9, 15, 23, 31, 23, 63, 23, 95, 23, 4, 1, 93, 19, 51, 17, 51, 50, 4, 21, 20, 4, 43, 1, 17, 35, 19, 17,
+ 51, 50, 54, 53, 52, 38, 35,201,202,254,251, 1, 1,254,255,251,254,202,202,254,141,154,153,142, 5,213,254,248,225,220,220,226,
+254,174, 4, 39,253,209,146,134,134,145, 0, 0, 0, 1, 0,186,255,227, 4,172, 6, 20, 0, 47, 0,154, 64, 48, 45, 39, 33, 12,
+ 4, 6, 13, 32, 0, 4, 42, 22,134, 23, 26,185, 19, 42,185, 3,151, 19,140, 46, 12, 9, 13, 29, 32, 33, 39, 9, 8, 36, 39, 8,
+ 6, 29, 8, 36, 16, 22, 45, 8, 16, 0, 70, 48, 16,252,196,252,204, 16,198,238,212,238, 16,238, 17, 57, 57, 18, 57, 18, 57, 49,
+ 0, 47,228,254,238, 16,254,213,238, 18, 23, 57, 23, 57, 48, 64, 64, 15, 5, 15, 6, 15, 7, 15, 39, 15, 40,138, 12,138, 13, 7,
+ 10, 6, 10, 7, 10, 11, 10, 12, 10, 13, 10, 31, 13, 32, 10, 33, 12, 34, 4, 38, 25, 13, 25, 31, 25, 32, 58, 32, 58, 33, 77, 31,
+ 77, 32, 73, 33, 73, 34,106, 31,106, 32,165, 6,165, 7,166, 32, 24, 93, 1, 93, 19, 52, 54, 51, 50, 22, 23, 14, 1, 21, 20, 22,
+ 31, 1, 30, 1, 21, 20, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 47, 1, 46, 1, 53, 52, 54, 55, 46, 1, 35, 34,
+ 6, 21, 17, 35,186,239,218,208,219, 3,151,168, 58, 65, 57,166, 96,225,211, 64,136, 73, 80,140, 65,116,120, 59,101, 92, 96, 87,
+167,151, 8,131,113,130,136,187, 4,113,200,219,232,224, 8,115, 96, 47, 81, 42, 37,106,142,100,172,183, 25, 24,164, 30, 29, 95,
+ 91, 63, 84, 62, 55, 59,135, 91,127,172, 29,103,112,139,131,251,147, 0, 0, 0,255,255, 0,123,255,227, 4, 45, 6,102, 18, 38,
+ 0, 68, 0, 0, 17, 6, 0, 67, 82, 0, 0, 11, 64, 7, 63, 38, 47, 38, 31, 38, 3, 93, 49, 0,255,255, 0,123,255,227, 4, 45,
+ 6,102, 18, 38, 0, 68, 0, 0, 17, 6, 0,118, 82, 0, 0, 11, 64, 7, 63, 38, 47, 38, 31, 38, 3, 93, 49, 0,255,255, 0,123,
+255,227, 4, 45, 6,102, 18, 38, 0, 68, 0, 0, 17, 6, 2, 31, 82, 0, 0, 8,180, 11, 40, 44, 20, 7, 43, 49,255,255, 0,123,
+255,227, 4, 45, 6, 55, 18, 38, 0, 68, 0, 0, 17, 6, 2, 53, 82, 0, 0, 20,180, 20, 46, 60, 11, 7, 43, 64, 9, 32, 46, 47,
+ 60, 16, 46, 31, 60, 4, 93, 49,255,255, 0,123,255,227, 4, 45, 6, 16, 18, 38, 0, 68, 0, 0, 17, 6, 0,106, 82, 0, 0, 32,
+180, 20, 45, 40, 11, 7, 43, 64, 21,127, 40,111, 40, 80, 45, 95, 40, 64, 45, 79, 40, 48, 45, 63, 40, 0, 45, 15, 40, 10, 93, 49,
+255,255, 0,123,255,227, 4, 45, 7, 6, 18, 38, 0, 68, 0, 0, 17, 6, 2, 51, 82, 0, 0, 37, 64, 14, 38, 44, 20, 44, 38, 11,
+ 7, 50, 56, 20, 56, 50, 11, 7, 43, 16,196, 43, 16,196, 49, 0, 64, 9, 63, 53, 63, 47, 15, 53, 15, 47, 4, 93, 48, 0, 0, 0,
+ 0, 3, 0,123,255,227, 7,111, 4,123, 0, 6, 0, 51, 0, 62, 1, 3, 64, 67, 39, 45, 37, 61, 14, 13, 0, 52,169, 37, 22,134,
+ 21,136, 18, 0,169, 14, 58, 18,185, 28, 25, 46,134, 45,186, 42, 3,185, 14,187, 7, 49, 10,184, 31, 25,140, 37, 63, 52, 55, 38,
+ 6, 15, 0, 37, 55, 28, 7, 38, 15, 21, 0, 8, 13, 61, 38, 8, 15, 45, 55, 8, 34, 69, 63, 16,252,236,204,212,252, 60,212,236,
+196, 17, 18, 57, 57, 17, 57, 17, 18, 57, 17, 18, 57, 49, 0, 16,196,228, 50,244, 60,196,228,252, 60,244,236, 16,196,238, 50, 16,
+238, 16,244,238, 16,238, 17, 57, 17, 57, 17, 18, 57, 48, 64,129, 48, 43, 48, 44, 48, 45, 48, 46, 48, 47, 48, 48, 64, 43, 64, 44,
+ 64, 45, 64, 46, 64, 47, 64, 48, 80, 43, 80, 44, 80, 45, 80, 46, 80, 47, 80, 48,133, 43,133, 48,128, 64,144, 64,160, 64,176, 64,
+192, 64,208, 64,224, 64,224, 64,240, 64, 29, 63, 0, 63, 6, 63, 13, 63, 14, 63, 15, 5, 48, 44, 48, 45, 48, 46, 48, 47, 64, 44,
+ 64, 45, 64, 46, 64, 47, 80, 44, 80, 45, 80, 46, 80, 47,111, 0,111, 6,111, 13,111, 14,111, 15, 96, 44, 96, 45, 96, 46, 96, 47,
+112, 44,112, 45,112, 46,112, 47,128, 44,128, 45,128, 46,128, 47, 29, 93,113, 1, 93, 1, 46, 1, 35, 34, 6, 7, 3, 62, 1, 51,
+ 50, 0, 29, 1, 33, 30, 1, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 39, 14, 1, 35, 34, 38, 53, 52, 54, 51, 33, 53, 52, 38, 35,
+ 34, 6, 7, 53, 62, 1, 51, 50, 22, 3, 34, 6, 21, 20, 22, 51, 50, 54, 61, 1, 6,182, 1,165,137,153,185, 14, 68, 74,212,132,
+226, 1, 8,252,178, 12,204,183,104,200,100,100,208,106,167,248, 77, 73,216,143,189,210,253,251, 1, 2,167,151, 96,182, 84,101,
+190, 90,142,213,239,223,172,129,111,153,185, 2,148,151,180,174,158, 1, 48, 90, 94,254,221,250, 90,191,200, 53, 53,174, 42, 44,
+121,119,120,120,187,168,189,192, 18,127,139, 46, 46,170, 39, 39, 96,254, 24,102,123, 98,115,217,180, 41, 0, 0,255,255, 0,113,
+254,117, 3,231, 4,123, 18, 38, 0, 70, 0, 0, 16, 7, 0,122, 0,143, 0, 0,255,255, 0,113,255,227, 4,127, 6,102, 18, 38,
+ 0, 72, 0, 0, 16, 7, 0, 67, 0,139, 0, 0,255,255, 0,113,255,227, 4,127, 6,102, 18, 38, 0, 72, 0, 0, 16, 7, 0,118,
+ 0,139, 0, 0,255,255, 0,113,255,227, 4,127, 6,102, 18, 38, 0, 72, 0, 0, 17, 7, 2, 31, 0,139, 0, 0, 0, 8,180, 21,
+ 30, 34, 27, 7, 43, 49, 0, 0,255,255, 0,113,255,227, 4,127, 6, 16, 18, 38, 0, 72, 0, 0, 17, 7, 0,106, 0,139, 0, 0,
+ 0, 7, 64, 3, 64, 32, 1, 93, 49, 0, 0, 0,255,255,255,199, 0, 0, 1,166, 6,102, 18, 38, 0,243, 0, 0, 16, 7, 0, 67,
+255, 29, 0, 0,255,255, 0,144, 0, 0, 2,111, 6,102, 18, 38, 0,243, 0, 0, 16, 7, 0,118,255, 29, 0, 0,255,255,255,222,
+ 0, 0, 2, 92, 6,102, 18, 38, 0,243, 0, 0, 17, 7, 2, 31,255, 29, 0, 0, 0, 8,180, 1, 6, 10, 0, 7, 43, 49, 0, 0,
+255,255,255,244, 0, 0, 2, 70, 6, 16, 18, 38, 0,243, 0, 0, 17, 7, 0,106,255, 29, 0, 0, 0, 8,180, 0, 10, 7, 1, 7,
+ 43, 49, 0, 0, 0, 2, 0,113,255,227, 4,117, 6, 20, 0, 14, 0, 40, 1, 39, 64, 94, 37,123, 38, 37, 30, 35, 30, 36,123, 35,
+ 35, 30, 15,123, 35, 30, 40,123, 39, 40, 30, 35, 30, 38, 39, 40, 39, 37, 36, 37, 40, 40, 39, 34, 35, 34, 31, 32, 31, 33, 32, 32,
+ 31, 66, 40, 39, 38, 37, 34, 33, 32, 31, 8, 35, 30, 3, 15, 35, 3,185, 27, 9,185, 21,140, 27, 35,177, 41, 38, 39, 18, 12, 33,
+ 32, 24, 40, 37, 35, 34, 31, 5, 30, 15, 6, 12, 18, 18, 81, 6, 18, 24, 69, 41, 16,252,236,244,236, 17, 57, 57, 23, 57, 18, 57,
+ 57, 17, 18, 57, 57, 49, 0, 16,236,196,244,236, 16,238, 18, 57, 18, 57, 18, 23, 57, 48, 75, 83, 88, 7, 16, 14,201, 7, 16, 8,
+201, 7, 16, 8,201, 7, 16, 14,201, 7, 16, 8,237, 7, 14,237, 7, 16, 5,237, 7, 16, 8,237, 89, 34,178, 63, 42, 1, 1, 93,
+ 64,118, 22, 37, 43, 31, 40, 34, 47, 35, 47, 36, 41, 37, 45, 38, 45, 39, 42, 40, 54, 37, 70, 37, 88, 32, 88, 33, 96, 32, 96, 33,
+102, 34,117, 32,117, 33,117, 34, 19, 37, 35, 37, 36, 38, 38, 38, 39, 39, 40, 54, 36, 54, 37, 70, 36, 69, 37, 90, 32, 90, 33, 98,
+ 32, 98, 33,127, 0,127, 1,127, 2,122, 3,123, 9,127, 10,127, 11,127, 12,127, 13,127, 14,127, 15,127, 16,127, 17,127, 18,127,
+ 19,127, 20,123, 21,122, 27,122, 28,127, 29,127, 30,118, 32,118, 33,120, 34,160, 42,240, 42, 39, 93, 0, 93, 1, 46, 1, 35, 34,
+ 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 19, 22, 18, 21, 20, 0, 35, 34, 0, 17, 52, 0, 51, 50, 22, 23, 39, 5, 39, 37, 39, 51,
+ 23, 37, 23, 5, 3, 70, 50, 88, 41,167,185,174,146,145,174, 54, 9,126,114,254,228,230,231,254,229, 1, 20,221, 18, 52, 42,159,
+254,193, 33, 1, 25,181,228,127, 1, 77, 33,254,217, 3,147, 17, 16,216,195,188,222,222,188,122,188, 1, 38,143,254,224,173,255,
+254,201, 1, 55, 0,255,250, 1, 55, 5, 5,180,107, 99, 92,204,145,111, 97, 98,255,255, 0,186, 0, 0, 4,100, 6, 55, 18, 38,
+ 0, 81, 0, 0, 16, 7, 2, 53, 0,152, 0, 0,255,255, 0,113,255,227, 4,117, 6,102, 18, 38, 0, 82, 0, 0, 16, 6, 0, 67,
+115, 0, 0, 0,255,255, 0,113,255,227, 4,117, 6,102, 18, 38, 0, 82, 0, 0, 16, 6, 0,118,115, 0, 0, 0,255,255, 0,113,
+255,227, 4,117, 6,102, 18, 38, 0, 82, 0, 0, 17, 6, 2, 31,115, 0, 0, 8,180, 15, 26, 30, 21, 7, 43, 49,255,255, 0,113,
+255,227, 4,117, 6, 55, 18, 38, 0, 82, 0, 0, 17, 6, 2, 53,115, 0, 0, 20,180, 21, 32, 46, 15, 7, 43, 64, 9, 32, 32, 47,
+ 46, 16, 32, 31, 46, 4, 93, 49,255,255, 0,113,255,227, 4,117, 6, 16, 18, 38, 0, 82, 0, 0, 17, 6, 0,106,115, 0, 0, 20,
+180, 3, 31, 26, 9, 7, 43, 64, 9, 64, 31, 79, 26, 48, 31, 63, 26, 4, 93, 49, 0, 3, 0,217, 0,150, 5,219, 4,111, 0, 3,
+ 0, 7, 0, 11, 0, 41, 64, 20, 0,234, 2, 6,234, 4, 2, 8,156, 4, 10, 12, 9, 5, 1,114, 4, 0, 8, 12, 16,220,212, 60,
+252, 60,196, 49, 0, 16,212,196,252,196, 16,238, 16,238, 48, 1, 51, 21, 35, 17, 51, 21, 35, 1, 33, 21, 33, 2,223,246,246,246,
+246,253,250, 5, 2,250,254, 4,111,246,254, 18,245, 2, 65,170, 0, 3, 0, 72,255,162, 4,156, 4,188, 0, 9, 0, 19, 0, 43,
+ 0,228, 64, 60, 43, 44, 38, 31, 29, 26, 19, 10, 1, 0, 4, 13, 41, 38, 32, 20, 13, 4, 42, 38, 30, 26, 4,185, 38, 13,185, 26,
+184, 38,140, 44, 43, 44, 42, 20, 23, 16, 32, 30, 35, 19, 10, 1, 0, 4, 16, 7, 31, 29, 7, 18, 35, 81, 41, 16, 18, 23, 69, 44,
+ 16,252,236, 50,244,236, 50,192, 17, 18, 23, 57, 18, 57, 57, 17, 18, 57, 57, 17, 57, 49, 0, 16,228,244,236, 16,238, 16,192, 16,
+192, 17, 18, 57, 57, 18, 57, 18, 23, 57, 17, 57, 57, 17, 18, 57, 48, 64,112, 40, 1, 63, 45, 89, 20, 86, 28, 85, 29, 86, 32,106,
+ 21,102, 33,127, 0,123, 4,127, 5,127, 6,127, 7,127, 8,127, 9,127, 10,127, 11,127, 12,123, 13,122, 21,123, 26,127, 27,127,
+ 28,127, 29,127, 30,127, 31,127, 32,123, 33,127, 34,127, 35,127, 36,127, 37,123, 38,155, 25,149, 37,168, 25,160, 45,240, 45, 38,
+ 89, 0, 86, 19, 85, 29, 90, 40,105, 0,102, 19,101, 28,106, 40,122, 0,116, 19,118, 28,122, 40,137, 30,149, 24,154, 36,162, 24,
+173, 36, 17, 93, 1, 93, 9, 1, 30, 1, 51, 50, 54, 53, 52, 38, 39, 46, 1, 35, 34, 6, 21, 20, 22, 23, 7, 46, 1, 53, 16, 0,
+ 51, 50, 22, 23, 55, 23, 7, 30, 1, 21, 16, 0, 35, 34, 38, 39, 7, 39, 3,137,254, 25, 41,103, 65,147,172, 20, 92, 42,103, 62,
+151,169, 19, 20,125, 54, 54, 1, 17,241, 93,159, 67,139, 95,146, 53, 54,254,238,240, 96,161, 63,139, 96, 3, 33,253,176, 42, 40,
+232,200, 79,117,154, 41, 41,235,211, 72,110, 46,151, 77,197,119, 1, 20, 1, 56, 51, 52,168, 79,179, 77,198,120,254,237,254,199,
+ 52, 51,168, 78,255,255, 0,174,255,227, 4, 88, 6,102, 18, 38, 0, 88, 0, 0, 16, 6, 0, 67,123, 0, 0, 0,255,255, 0,174,
+255,227, 4, 88, 6,102, 18, 38, 0, 88, 0, 0, 16, 6, 0,118,123, 0, 0, 0,255,255, 0,174,255,227, 4, 88, 6,102, 18, 38,
+ 0, 88, 0, 0, 17, 6, 2, 31,123, 0, 0, 8,180, 11, 22, 26, 1, 7, 43, 49,255,255, 0,174,255,227, 4, 88, 6, 16, 18, 38,
+ 0, 88, 0, 0, 17, 6, 0,106,123, 0, 0, 24,180, 2, 26, 23, 10, 7, 43, 64, 13, 64, 26, 79, 23, 48, 26, 63, 23, 0, 26, 15,
+ 23, 6, 93, 49,255,255, 0, 61,254, 86, 4,127, 6,102, 18, 38, 0, 92, 0, 0, 16, 6, 0,118, 94, 0, 0, 0, 0, 2, 0,186,
+254, 86, 4,164, 6, 20, 0, 16, 0, 28, 0, 62, 64, 27, 20,185, 5, 8, 26,185, 0, 14,140, 8,184, 1,189, 3,151, 29, 17, 18,
+ 11, 71, 23, 4, 0, 8, 2, 70, 29, 16,252,236, 50, 50,244,236, 49, 0, 16,236,228,228,244,196,236, 16,198,238, 48, 64, 9, 96,
+ 30,128, 30,160, 30,224, 30, 4, 1, 93, 37, 17, 35, 17, 51, 17, 62, 1, 51, 50, 0, 17, 16, 2, 35, 34, 38, 1, 52, 38, 35, 34,
+ 6, 21, 20, 22, 51, 50, 54, 1,115,185,185, 58,177,123,204, 0,255,255,204,123,177, 2, 56,167,146,146,167,167,146,146,167,168,
+253,174, 7,190,253,162,100, 97,254,188,254,248,254,248,254,188, 97, 1,235,203,231,231,203,203,231,231, 0, 0,255,255, 0, 61,
+254, 86, 4,127, 6, 16, 18, 38, 0, 92, 0, 0, 17, 6, 0,106, 94, 0, 0, 22,180, 24, 23, 18, 25, 7, 43, 64, 11, 48, 23, 63,
+ 18, 32, 23, 47, 18, 31, 18, 5, 93, 49, 0, 0,255,255, 0, 16, 0, 0, 5,104, 7, 49, 16, 39, 0,113, 0,188, 1, 59, 19, 6,
+ 0, 36, 0, 0, 0, 16,180, 14, 3, 2, 9, 7, 43, 64, 5, 64, 3, 79, 2, 2, 93, 49, 0, 0,255,255, 0,123,255,227, 4, 45,
+ 5,246, 16, 38, 0,113, 74, 0, 19, 6, 0, 68, 0, 0, 0, 16,180, 24, 3, 2, 15, 7, 43, 64, 5,111, 2,127, 3, 2, 93, 49,
+255,255, 0, 16, 0, 0, 5,104, 7,146, 16, 39, 2, 49, 0,206, 1, 74, 19, 6, 0, 36, 0, 0, 0, 18,180, 24, 0, 8, 19, 7,
+ 43, 49, 0, 64, 5,111, 0,111, 8, 2, 93, 48,255,255, 0,123,255,227, 4, 45, 6, 31, 16, 38, 2, 49, 79,215, 19, 6, 0, 68,
+ 0, 0, 0, 8,180, 34, 0, 8, 25, 7, 43, 49,255,255, 0, 16,254,117, 5,165, 5,213, 16, 39, 2, 52, 2,228, 0, 0, 18, 6,
+ 0, 36, 0, 0,255,255, 0,123,254,117, 4,128, 4,123, 16, 39, 2, 52, 1,191, 0, 0, 18, 6, 0, 68, 0, 0,255,255, 0,115,
+255,227, 5, 39, 5,240, 18, 38, 0, 38, 0, 0, 16, 7, 6,133, 5, 45, 1,117,255,255, 0,113,255,227, 3,231, 6,102, 18, 38,
+ 0, 70, 0, 0, 16, 7, 0,118, 0,137, 0, 0,255,255, 0,115,255,227, 5, 39, 5,240, 16, 39, 6,136, 5, 76, 1,117, 19, 6,
+ 0, 38, 0, 0, 0, 9,178, 4, 4, 30, 16, 60, 61, 47, 49, 0,255,255, 0,113,255,227, 3,231, 6,102, 16, 39, 2, 31, 0,164,
+ 0, 0, 18, 6, 0, 70, 0, 0,255,255, 0,115,255,227, 5, 39, 5,240, 16, 39, 6,140, 5, 76, 1,117, 18, 6, 0, 38, 0, 0,
+255,255, 0,113,255,227, 3,231, 6, 16, 16, 39, 2, 50, 0,164, 0, 0, 18, 6, 0, 70, 0, 0,255,255, 0,115,255,227, 5, 39,
+ 5,240, 18, 38, 0, 38, 0, 0, 17, 7, 6,137, 5, 45, 1,117, 0, 7, 64, 3, 31, 29, 1, 93, 49, 0, 0, 0,255,255, 0,113,
+255,227, 3,231, 6,102, 18, 38, 0, 70, 0, 0, 16, 7, 2, 32, 0,137, 0, 0,255,255, 0,201, 0, 0, 5,176, 5,213, 16, 38,
+ 0, 39, 0, 0, 16, 7, 6,137, 4,236, 1,137,255,255, 0,113,255,227, 4, 90, 6, 20, 18, 38, 0, 71, 0, 0, 17, 7, 6,131,
+ 5, 20, 0, 0, 0, 11, 64, 7, 95, 29, 63, 29, 31, 29, 3, 93, 49, 0, 0, 0,255,255, 0, 10, 0, 0, 5,186, 5,213, 16, 6,
+ 0,146, 0, 0, 0, 2, 0,113,255,227, 4,244, 6, 20, 0, 24, 0, 36, 0, 74, 64, 36, 7, 3,211, 9, 1,249, 34,185, 0, 22,
+ 28,185, 13, 16,140, 22,184, 5,151, 11, 2, 31, 12, 4, 3, 0, 8, 8, 10, 6, 71, 25, 18, 19, 69, 37, 16,252,236,244, 60,196,
+252, 23, 60,196, 49, 0, 47,236,228,244,196,236, 16,196,238,253, 60,238, 50, 48,182, 96, 38,128, 38,160, 38, 3, 1, 93, 1, 17,
+ 33, 53, 33, 53, 51, 21, 51, 21, 35, 17, 35, 53, 14, 1, 35, 34, 2, 17, 16, 0, 51, 50, 22, 1, 20, 22, 51, 50, 54, 53, 52, 38,
+ 35, 34, 6, 3,162,254,186, 1, 70,184,154,154,184, 58,177,124,203,255, 0,255,203,124,177,253,199,167,146,146,168,168,146,146,
+167, 3,182, 1, 78,125,147,147,125,250,252,168,100, 97, 1, 68, 1, 8, 1, 8, 1, 68, 97,254, 21,203,231,231,203,203,231,231,
+255,255, 0,201, 0, 0, 4,139, 7, 51, 16, 39, 0,113, 0,161, 1, 61, 18, 6, 0, 40, 0, 0,255,255, 0,113,255,227, 4,127,
+ 5,246, 16, 39, 0,113, 0,150, 0, 0, 19, 6, 0, 72, 0, 0, 0, 7, 64, 3,112, 0, 1, 93, 49, 0, 0, 0,255,255, 0,201,
+ 0, 0, 4,139, 5,213, 16, 39, 6,139, 4,161, 1,117, 19, 6, 0, 40, 0, 0, 0, 7, 64, 3, 64, 0, 1, 93, 49, 0, 0, 0,
+255,255, 0,113,255,227, 4,127, 6, 72, 16, 39, 2, 49, 0,150, 0, 0, 19, 6, 0, 72, 0, 0, 0, 7, 64, 3,112, 0, 1, 93,
+ 49, 0, 0, 0,255,255, 0,201, 0, 0, 4,139, 5,213, 16, 39, 6,140, 4,161, 1,117, 18, 6, 0, 40, 0, 0,255,255, 0,113,
+255,227, 4,127, 6, 16, 16, 39, 2, 50, 0,150, 0, 0, 18, 6, 0, 72, 0, 0,255,255, 0,201,254,117, 4,141, 5,213, 16, 39,
+ 2, 52, 1,204, 0, 0, 18, 6, 0, 40, 0, 0,255,255, 0,113,254,117, 4,127, 4,123, 16, 39, 2, 52, 1,120, 0, 0, 18, 6,
+ 0, 72, 0, 0,255,255, 0,201, 0, 0, 4,139, 5,213, 18, 38, 0, 40, 0, 0, 17, 7, 6,137, 4,166, 1,111, 0, 7, 64, 3,
+ 64, 12, 1, 93, 49, 0, 0, 0,255,255, 0,113,255,227, 4,127, 6, 97, 18, 38, 0, 72, 0, 0, 17, 7, 2, 32, 0,148,255,251,
+ 0, 16,180, 0, 33, 29, 15, 7, 43, 64, 5, 15, 33, 0, 29, 2, 93, 49, 0, 0,255,255, 0,115,255,227, 5,139, 5,240, 16, 39,
+ 6,136, 5, 92, 1,117, 19, 6, 0, 42, 0, 0, 0, 9,178, 4, 4, 21, 16, 60, 61, 47, 49, 0,255,255, 0,113,254, 86, 4, 90,
+ 6,102, 16, 38, 2, 31,104, 0, 19, 6, 0, 74, 0, 0, 0, 9,178, 4, 4, 10, 16, 60, 61, 47, 49, 0, 0, 0,255,255, 0,115,
+255,227, 5,139, 5,240, 18, 38, 0, 42, 0, 0, 16, 7, 6,139, 5, 27, 1,117,255,255, 0,113,254, 86, 4, 90, 6, 72, 18, 38,
+ 0, 74, 0, 0, 16, 7, 2, 49, 0,139, 0, 0,255,255, 0,115,255,227, 5,139, 5,240, 16, 39, 6,140, 5, 92, 1,117, 19, 6,
+ 0, 42, 0, 0, 0, 8, 0, 64, 3, 63, 0, 1, 93, 48, 0, 0,255,255, 0,113,254, 86, 4, 90, 6, 16, 16, 38, 2, 50,104, 0,
+ 18, 6, 0, 74, 0, 0, 0, 0,255,255, 0,115,254, 1, 5,139, 5,240, 16, 39, 2,110, 5, 94,255,237, 18, 6, 0, 42, 0, 0,
+255,255, 0,113,254, 86, 4, 90, 6, 52, 16, 39, 2, 90, 3,224, 1, 12, 18, 6, 0, 74, 0, 0,255,255, 0,201, 0, 0, 5, 59,
+ 5,213, 16, 39, 6,136, 5, 2, 1,117, 19, 6, 0, 43, 0, 0, 0, 20,180, 12, 2, 6, 7, 7, 43, 64, 9, 47, 2, 32, 6, 31,
+ 2, 16, 6, 4, 93, 49, 0, 0,255,255, 0,186, 0, 0, 4,100, 6, 20, 16, 39, 6,136, 3, 22, 1,117, 19, 6, 0, 75, 0, 0,
+ 0, 42,180, 20, 2, 6, 19, 7, 43, 49, 0, 75,176, 14, 81, 88,187, 0, 20,255,192, 0, 19,255,192, 56, 56, 89, 64, 13,144, 20,
+144, 19,128, 20,128, 19, 64, 20, 64, 19, 6, 93, 0, 2, 0,201, 0, 0, 6,139, 5,213, 0, 19, 0, 23, 0, 58, 64, 30, 6, 2,
+ 18,149, 9, 20, 17, 12,149, 21,173, 4, 0,129, 14, 10, 7, 12, 23, 4, 28, 5, 56, 18, 13, 20, 1, 28, 0, 24, 16,220,236, 50,
+ 50,204,252,236, 50, 50,204, 49, 0, 47, 60,228, 50,252,236,220, 50, 50,236, 50, 50, 48, 1, 51, 21, 33, 53, 51, 21, 51, 21, 35,
+ 17, 35, 17, 33, 17, 35, 17, 35, 53, 51, 23, 21, 33, 53, 1,113,202, 2,222,202,168,168,202,253, 34,202,168,168,202, 2,222, 5,
+213,224,224,224,164,251,175, 2,199,253, 57, 4, 81,164,164,224,224, 0, 0, 0, 0, 1, 0,120, 0, 0, 4,159, 6, 20, 0, 27,
+ 0, 62, 64, 33, 3, 9, 0, 3, 22, 1, 14, 18,135, 13, 21, 6,135, 22, 25,184, 16,151, 10, 1, 2, 8, 0, 78, 19, 14, 17, 21,
+ 9, 8, 16, 11, 28, 16,220, 50,236, 50, 50,204,204,244,236, 49, 0, 47, 60,236,244,196,236,220, 50,236, 50, 17, 18, 23, 57, 48,
+ 1, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 35, 53, 51, 53, 51, 21, 33, 21, 33, 17, 62, 1, 51, 50, 22, 4,159,184,124,
+124,149,172,185,125,125,185, 1, 96,254,160, 66,179,117,193,198, 2,164,253, 92, 2,158,159,158,190,164,253,135, 4,246,164,122,
+122,164,254,188,101,100,239, 0,255,255, 0,201, 0, 0, 1,147, 5,213, 16, 39, 6,134, 3, 46, 1,117, 19, 6, 0, 44, 0, 0,
+ 0, 8,180, 30, 9, 24, 31, 7, 43, 49, 0, 0,255,255,255,211, 0, 0, 2,103, 6, 55, 16, 39, 2, 53,255, 29, 0, 0, 19, 6,
+ 0,243, 0, 0, 0, 8,180, 28, 8, 22, 29, 7, 43, 49, 0, 0,255,255, 0, 3, 0, 0, 2, 89, 7, 49, 16, 39, 0,113,255, 46,
+ 1, 59, 19, 6, 0, 44, 0, 0, 0, 8,180, 4, 3, 2, 5, 7, 43, 49, 0, 0,255,255,255,242, 0, 0, 2, 72, 5,245, 16, 39,
+ 0,113,255, 29,255,255, 19, 6, 0,243, 0, 0, 0, 8,180, 4, 3, 2, 5, 7, 43, 49, 0, 0,255,255, 0,201, 0, 0, 1,147,
+ 5,213, 16, 39, 6,139, 3, 46, 1,117, 19, 6, 0, 44, 0, 0, 0, 8,180, 14, 0, 8, 15, 7, 43, 49, 0, 0,255,255,255,228,
+ 0, 0, 2, 86, 6, 72, 16, 39, 2, 49,255, 29, 0, 0, 19, 6, 0,243, 0, 0, 0, 8,180, 14, 0, 8, 15, 7, 43, 49, 0, 0,
+255,255, 0,176,254,117, 2, 37, 5,213, 16, 39, 2, 52,255,100, 0, 0, 18, 6, 0, 44, 0, 0,255,255, 0,150,254,117, 2, 11,
+ 6, 20, 16, 39, 2, 52,255, 74, 0, 0, 18, 6, 0, 76, 0, 0,255,255, 0,201, 0, 0, 1,147, 5,213, 18, 38, 0, 44, 0, 0,
+ 17, 7, 6,140, 3, 47, 1,117, 0, 19,179, 6, 1, 7, 0, 16, 60, 16, 60, 49, 0,180, 63, 7, 63, 6, 2, 93, 48, 0, 0, 0,
+ 0, 1, 0,193, 0, 0, 1,121, 4, 96, 0, 3, 0, 32,183, 0,191, 2, 1, 8, 0, 70, 4, 16,252,236, 49, 0, 47,236, 48, 64,
+ 11, 16, 5, 64, 5, 80, 5, 96, 5,112, 5, 5, 1, 93, 19, 51, 17, 35,193,184,184, 4, 96,251,160, 0, 0, 0,255,255, 0,201,
+254,102, 3,239, 5,213, 16, 39, 0, 45, 2, 92, 0, 0, 17, 6, 0, 44, 0, 0, 0, 8, 64, 3, 17, 4, 1, 16,236, 49, 0, 0,
+255,255, 0,193,254, 86, 3,177, 6, 20, 16, 39, 0, 77, 2, 56, 0, 0, 17, 6, 0, 76, 0, 0, 0, 8, 64, 3, 25, 70, 1, 16,
+236, 49, 0, 0,255,255,255,150,254,102, 1,147, 5,213, 16, 39, 6,136, 3, 46, 1,117, 19, 6, 0, 45, 0, 0, 0, 8,180, 8,
+ 2, 6, 7, 7, 43, 49, 0, 0,255,255,255,219,254, 86, 2, 92, 6,102, 16, 39, 2, 31,255, 29, 0, 0, 19, 6, 1,249, 0, 0,
+ 0, 8,180, 8, 2, 6, 7, 7, 43, 49, 0, 0,255,255, 0,201,254, 30, 5,106, 5,213, 16, 39, 2,110, 5, 27, 0, 10, 18, 6,
+ 0, 46, 0, 0,255,255, 0,186,254, 30, 4,156, 6, 20, 16, 39, 2,110, 4,172, 0, 10, 18, 6, 0, 78, 0, 0, 0, 1, 0,186,
+ 0, 0, 4,156, 4, 96, 0, 10, 0,187, 64, 40, 8, 17, 5, 6, 5, 7, 17, 6, 6, 5, 3, 17, 4, 5, 4, 2, 17, 5, 5, 4,
+ 66, 8, 5, 2, 3, 3, 0,188, 9, 6, 5, 1, 4, 6, 8, 1, 8, 0, 70, 11, 16,252,236, 50,212,196, 17, 57, 49, 0, 47, 60,
+236, 50, 23, 57, 48, 75, 83, 88, 7, 16, 4,237, 7, 16, 5,237, 7, 16, 5,237, 7, 16, 4,237, 89, 34,178, 16, 12, 1, 1, 93,
+ 64, 95, 4, 2, 10, 8, 22, 2, 39, 2, 41, 5, 43, 8, 86, 2,102, 2,103, 8,115, 2,119, 5,130, 2,137, 5,142, 8,147, 2,
+150, 5,151, 8,163, 2, 18, 9, 5, 9, 6, 2, 11, 3, 10, 7, 40, 3, 39, 4, 40, 5, 43, 6, 43, 7, 64, 12,104, 3, 96, 12,
+137, 3,133, 4,137, 5,141, 6,143, 7,154, 3,151, 7,170, 3,167, 5,182, 7,197, 7,214, 7,247, 3,240, 3,247, 4,240, 4,
+ 26, 93,113, 0, 93, 19, 51, 17, 1, 51, 9, 1, 35, 1, 17, 35,186,185, 2, 37,235,253,174, 2,107,240,253,199,185, 4, 96,254,
+ 27, 1,229,253,242,253,174, 2, 33,253,223, 0,255,255, 0,201, 0, 0, 4,106, 5,213, 16, 39, 6,133, 3,110, 1,118, 18, 6,
+ 0, 47, 0, 0,255,255, 0,193, 0, 0, 1,121, 6, 20, 16, 39, 6,133, 3, 90, 1,118, 19, 6, 0, 79, 0, 0, 0, 30,177, 3,
+ 4, 16, 60, 49, 0, 75,176, 14, 81, 88,185, 0, 0, 0, 64, 56, 89, 64, 7,159, 0,143, 0, 79, 0, 3, 93, 48,255,255, 0,201,
+254, 30, 4,106, 5,213, 16, 39, 2,110, 4,155, 0, 10, 18, 6, 0, 47, 0, 0,255,255, 0,136,254, 30, 1,174, 6, 20, 16, 39,
+ 2,110, 3, 30, 0, 10, 19, 6, 0, 79, 0, 0, 0, 7, 64, 3, 64, 0, 1, 93, 49, 0, 0, 0,255,255, 0,201, 0, 0, 4,106,
+ 5,213, 16, 39, 6,131, 2,159,255,195, 18, 6, 0, 47, 0, 0,255,255, 0,193, 0, 0, 1,121, 6, 20, 16, 39, 6,131, 2, 57,
+ 0, 2, 17, 6, 0, 79, 0, 0, 0, 9, 64, 5,143, 0, 31, 0, 2, 93, 49, 0,255,255, 0,201, 0, 0, 4,106, 5,213, 16, 39,
+ 0,121, 2, 49, 0,119, 18, 6, 0, 47, 0, 0,255,255, 0,193, 0, 0, 2,132, 6, 20, 16, 39, 0,121, 0,214, 0,115, 17, 6,
+ 0, 79, 0, 0, 0, 23, 75,176, 13, 81, 75,176, 17, 83, 75,176, 24, 81, 90, 91, 88,185, 0, 0, 0, 64, 56, 89, 49, 0, 0, 0,
+ 0, 1,255,242, 0, 0, 4,117, 5,213, 0, 13, 0, 63, 64, 30, 12, 11, 10, 4, 3, 2, 6, 0, 6,149, 0,129, 8, 3, 4, 1,
+ 11, 14, 0, 4, 5, 1, 28, 12, 7, 58, 9, 0,121, 14, 16,244, 60,236,196,252, 60,196, 17, 18, 57, 17, 18, 57, 49, 0, 47,228,
+236, 17, 23, 57, 48,180, 48, 15, 80, 15, 2, 1, 93, 19, 51, 17, 37, 23, 1, 17, 33, 21, 33, 17, 7, 39, 55,211,203, 1, 57, 80,
+254,119, 2,215,252, 94,148, 77,225, 5,213,253,152,219,111,254,238,253,227,170, 2, 59,106,110,158, 0, 0, 0, 0, 1, 0, 2,
+ 0, 0, 2, 72, 6, 20, 0, 11, 0, 94, 64, 26, 10, 9, 8, 4, 3, 2, 6, 0,151, 6, 3, 4, 1, 9, 10, 0, 4,122, 5, 1,
+ 8, 10,122, 7, 0, 12, 16,212, 60,228,252, 60,228, 17, 18, 57, 17, 18, 57, 49, 0, 47,236, 23, 57, 48, 1, 75,176, 16, 84, 88,
+189, 0, 12, 0, 64, 0, 1, 0, 12, 0, 12,255,192, 56, 17, 55, 56, 89, 64, 19, 16, 13, 64, 13, 80, 13, 96, 13,115, 4,122, 10,
+112, 13,224, 13,240, 13, 9, 93, 19, 51, 17, 55, 23, 7, 17, 35, 17, 7, 39, 55,199,184,125, 76,201,184,123, 74,197, 6, 20,253,
+166, 90,106,141,252,227, 2,154, 88,106,141, 0,255,255, 0,201, 0, 0, 5, 51, 5,213, 16, 39, 6,133, 4,197, 1,118, 19, 6,
+ 0, 49, 0, 0, 0, 7, 64, 3, 79, 0, 1, 93, 49, 0, 0, 0,255,255, 0,186, 0, 0, 4,100, 6,109, 16, 38, 0,118, 66, 7,
+ 19, 6, 0, 81, 0, 0, 0, 9, 64, 5, 63, 0, 79, 0, 2, 93, 49, 0, 0, 0,255,255, 0,201,254, 30, 5, 51, 5,213, 16, 39,
+ 2,110, 5, 0, 0, 10, 18, 6, 0, 49, 0, 0,255,255, 0,186,254, 30, 4,100, 4,123, 16, 39, 2,110, 4,144, 0, 10, 18, 6,
+ 0, 81, 0, 0,255,255, 0,201, 0, 0, 5, 51, 5,213, 18, 38, 0, 49, 0, 0, 17, 7, 6,137, 4,245, 1,103, 0, 20,180, 4,
+ 15, 11, 0, 7, 43, 64, 9, 47, 15, 32, 11, 31, 15, 16, 11, 4, 93, 49, 0, 0,255,255, 0,186, 0, 0, 4,100, 6,102, 18, 38,
+ 0, 81, 0, 0, 17, 7, 2, 32, 0,141, 0, 0, 0, 16,180, 0, 25, 21, 12, 7, 43, 64, 5, 15, 25, 0, 21, 2, 93, 49, 0, 0,
+255,255, 0,205, 0, 0, 5,185, 5,213, 16, 39, 0, 81, 1, 85, 0, 0, 16, 6, 2, 21, 27, 0, 0, 1, 0,213,254, 86, 5, 39,
+ 5,213, 0, 19, 0, 74, 64, 33, 17, 17, 1, 2, 1, 2, 17, 16, 17, 16, 66, 11,149, 10, 17, 2, 3, 0,175, 16, 19, 11, 16, 1,
+ 17, 2, 28, 4, 54, 17, 28, 0, 20, 16,220,236,252,236, 17, 57, 57,204, 49, 0, 47, 60,236, 50, 57, 57,220,236, 48, 75, 83, 88,
+ 7, 16, 4,237, 7, 16, 4,237, 89, 34,178, 31, 21, 1, 1, 93, 19, 51, 1, 17, 51, 17, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54,
+ 53, 1, 17, 35,213,184, 2,226,184, 82, 81,181,254,233,105, 38, 38,253, 30,184, 5,213,251,131, 4,125,250, 23,214, 96, 96,156,
+ 48, 49,173, 4,125,251,131, 0, 0, 1, 0,186,254, 86, 4,100, 4,123, 0, 31, 0, 59, 64, 28, 13, 19, 0, 3, 24, 21, 7,135,
+ 6, 16,135, 24, 28,184, 22,188, 21, 7, 13, 8, 0, 78, 19, 23, 8, 22, 70, 32, 16,252,236, 50,244,236,196, 49, 0, 47,228,244,
+196,236,212,236, 17, 18, 23, 57, 48,180, 96, 33,207, 33, 2, 1, 93, 1, 17, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 53, 17, 52,
+ 38, 35, 34, 6, 21, 17, 35, 17, 51, 21, 54, 55, 54, 51, 50, 23, 22, 4,100, 82, 81,181,254,233,105, 38, 38,124,124,149,172,185,
+185, 66, 89, 90,117,193, 99, 99, 2,164,253, 72,214, 96, 96,156, 48, 49,153, 2,178,159,158,190,164,253,135, 4, 96,174,101, 50,
+ 50,119,120, 0,255,255, 0,115,255,227, 5,217, 7, 49, 16, 39, 0,113, 1, 39, 1, 59, 19, 6, 0, 50, 0, 0, 0, 16,180, 13,
+ 2, 3, 7, 7, 43, 64, 5, 31, 2, 16, 3, 2, 93, 49, 0, 0,255,255, 0,113,255,227, 4,117, 5,245, 16, 38, 0,113,115,255,
+ 19, 6, 0, 82, 0, 0, 0, 8,180, 19, 2, 3, 25, 7, 43, 49,255,255, 0,115,255,227, 5,217, 5,240, 16, 39, 6,139, 5, 39,
+ 1,117, 19, 6, 0, 50, 0, 0, 0, 16,180, 17, 0, 8, 23, 7, 43, 64, 5, 16, 0, 31, 8, 2, 93, 49, 0, 0,255,255, 0,113,
+255,227, 4,117, 6, 72, 16, 38, 2, 49,115, 0, 19, 6, 0, 82, 0, 0, 0, 8,180, 29, 8, 0, 35, 7, 43, 49,255,255, 0,115,
+255,227, 5,217, 5,240, 16, 39, 6,141, 5, 39, 1,117, 18, 6, 0, 50, 0, 0,255,255, 0,113,255,227, 4,117, 6,102, 16, 39,
+ 2, 54, 0,160, 0, 0, 18, 6, 0, 82, 0, 0, 0, 2, 0,115, 0, 0, 8, 12, 5,213, 0, 16, 0, 25, 0, 59, 64, 31, 5,149,
+ 3, 17, 1,149, 0,129, 24, 7,149, 3,173, 9, 24, 18, 16, 10, 21, 6, 2, 28, 17, 0, 4, 8, 21, 25, 13, 16, 26, 16,252,236,
+212,196,196,212,236, 50, 18, 57, 57, 57, 57, 49, 0, 47,236,236, 50,244,236, 50, 16,238, 48, 1, 21, 33, 17, 33, 21, 33, 17, 33,
+ 21, 33, 32, 0, 17, 16, 0, 33, 23, 35, 32, 0, 17, 16, 0, 33, 51, 7,250,253, 26, 2,199,253, 57, 2,248,251,215,254, 79,254,
+ 65, 1,191, 1,177,103,129,254,191,254,192, 1, 64, 1, 65,129, 5,213,170,254, 70,170,253,227,170, 1,124, 1,112, 1,109, 1,
+124,170,254,225,254,224,254,223,254,223, 0, 0, 0, 3, 0,113,255,227, 7,195, 4,123, 0, 6, 0, 39, 0, 51, 0,132, 64, 49,
+ 7, 8, 0, 16,134, 15,136, 12, 0,169, 8, 46, 12,185, 22, 19, 40, 3,185, 8,187, 34, 37, 31,184, 25, 19,140, 52, 6, 0, 22,
+ 34, 49, 9, 15, 0, 8, 7, 75, 49, 18, 9, 81, 43, 18, 28, 69, 52, 16,252,236,244,252,244,236,196, 17, 18, 57, 57, 18, 57, 49,
+ 0, 16,228, 50,244, 60,196,228,236, 50, 16,196,238, 50, 16,238, 16,244,238, 17, 18, 57, 48, 64, 37, 63, 53, 95, 53,112, 53,159,
+ 53,207, 53,208, 53,240, 53, 7, 63, 0, 63, 6, 63, 7, 63, 8, 63, 9, 5,111, 0,111, 6,111, 7,111, 8,111, 9, 5, 93,113,
+ 1, 93, 1, 46, 1, 35, 34, 6, 7, 5, 21, 33, 30, 1, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 39, 14, 1, 35, 34, 0, 17, 16,
+ 0, 51, 50, 22, 23, 62, 1, 51, 50, 0, 37, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 7, 10, 2,164,137,153,185, 14, 3, 72,
+252,178, 12,204,183,106,200, 98,100,208,106,160,242, 81, 71,209,140,241,254,239, 1, 17,241,140,211, 66, 78,232,143,226, 1, 8,
+250,176,148,172,171,149,147,172,172, 2,148,152,179,174,158, 53, 90,190,199, 52, 52,174, 42, 44,110,109,110,109, 1, 57, 1, 19,
+ 1, 20, 1, 56,111,108,107,112,254,221,135,231,201,201,231,232,200,199,233, 0,255,255, 0,201, 0, 0, 5, 84, 5,213, 16, 39,
+ 6,133, 4,149, 1,118, 18, 6, 0, 53, 0, 0,255,255, 0,186, 0, 0, 3,149, 6,109, 16, 38, 0,118, 66, 7, 18, 6, 0, 85,
+ 0, 0, 0, 0,255,255, 0,201,254, 30, 5, 84, 5,213, 16, 39, 2,110, 5, 16, 0, 10, 18, 6, 0, 53, 0, 0,255,255, 0,130,
+254, 30, 3, 74, 4,123, 16, 39, 2,110, 3, 24, 0, 10, 18, 6, 0, 85, 0, 0,255,255, 0,201, 0, 0, 5, 84, 5,213, 18, 38,
+ 0, 53, 0, 0, 17, 7, 6,137, 4,125, 1,103, 0, 8, 0, 64, 3, 95, 29, 1, 93, 48, 0, 0,255,255, 0,186, 0, 0, 3, 90,
+ 6,102, 18, 38, 0, 85, 0, 0, 17, 6, 2, 32, 27, 0, 0, 16,180, 17, 23, 19, 9, 7, 43, 64, 5, 15, 23, 0, 19, 2, 93, 49,
+255,255, 0,135,255,227, 4,162, 5,240, 16, 39, 6,133, 4,149, 1,118, 18, 6, 0, 54, 0, 0,255,255, 0,111,255,227, 3,199,
+ 6,109, 16, 38, 0,118, 66, 7, 18, 6, 0, 86, 0, 0, 0, 0,255,255, 0,135,255,227, 4,162, 5,240, 16, 39, 6,136, 4,147,
+ 1,117, 19, 6, 0, 54, 0, 0, 0, 11,180, 4, 32, 21, 41, 41, 16, 73, 99, 58, 49, 0, 0, 0,255,255, 0,111,255,227, 3,199,
+ 6,102, 16, 38, 2, 31, 37, 0, 19, 6, 0, 86, 0, 0, 0, 11,180, 4, 32, 21, 41, 41, 16, 73, 99, 58, 49, 0,255,255, 0,135,
+254,117, 4,162, 5,240, 18, 38, 0, 54, 0, 0, 16, 7, 0,122, 0,139, 0, 0,255,255, 0,111,254,117, 3,199, 4,123, 18, 38,
+ 0, 86, 0, 0, 16, 6, 0,122, 23, 0, 0, 0,255,255, 0,135,255,227, 4,162, 5,240, 18, 38, 0, 54, 0, 0, 17, 7, 6,137,
+ 4,139, 1,117, 0, 11,180, 43, 32, 14, 34, 34, 16, 73, 99, 58, 49, 0, 0, 0,255,255, 0,111,255,227, 3,199, 6,102, 18, 38,
+ 0, 86, 0, 0, 17, 6, 2, 32, 23, 0, 0, 11,180, 43, 32, 14, 34, 34, 16, 73, 99, 58, 49, 0,255,255,255,250,254,117, 4,233,
+ 5,213, 16, 38, 0,122, 80, 0, 18, 6, 0, 55, 0, 0, 0, 0,255,255, 0, 55,254,117, 2,242, 5,158, 16, 38, 0,122,225, 0,
+ 18, 6, 0, 87, 0, 0, 0, 0,255,255,255,250, 0, 0, 4,233, 5,213, 18, 38, 0, 55, 0, 0, 17, 7, 6,137, 4,115, 1,103,
+ 0, 16,180, 1, 13, 9, 0, 7, 43, 49, 0, 64, 3, 95, 8, 1, 93, 48, 0, 0,255,255, 0, 55, 0, 0, 2,242, 5,158, 18, 38,
+ 0, 87, 0, 0, 17, 7, 6,131, 2, 55, 0,112, 0, 7, 64, 3,143, 20, 1, 93, 49, 0, 0, 0, 0, 1,255,250, 0, 0, 4,233,
+ 5,213, 0, 15, 0, 70, 64, 24, 7, 11,149, 4, 12, 9, 3, 15,149, 0,129, 9, 5, 1, 64, 7, 3, 28, 12, 0, 64, 10, 14, 16,
+ 16,212, 60,228,204,252, 60,228,204, 49, 0, 47,244,236, 50, 16,212, 60,236, 50, 48, 1, 64, 19, 0, 17, 31, 0, 16, 1, 16, 2,
+ 31, 15, 16, 17, 64, 17,112, 17,159, 17, 9, 93, 3, 33, 21, 33, 17, 33, 21, 33, 17, 35, 17, 33, 53, 33, 17, 33, 6, 4,239,253,
+238, 1, 9,254,247,203,254,247, 1, 9,253,238, 5,213,170,253,192,170,253,191, 2, 65,170, 2, 64, 0, 0, 0, 0, 1, 0, 55,
+ 0, 0, 2,242, 5,158, 0, 29, 0, 67, 64, 31, 8, 22,169, 5, 23, 4, 26,169, 0, 1, 27,188, 13,135, 16, 16, 13, 14, 2, 6,
+ 8, 4, 0, 8, 23, 27, 21, 25, 29, 70, 30, 16,252, 60, 60,196, 50,252, 60, 60,196,196, 50, 57, 57, 49, 0, 47,236,244, 60,196,
+252, 60,220, 60,236, 50, 48,178,175, 31, 1, 1, 93, 1, 17, 33, 21, 33, 21, 51, 21, 35, 21, 20, 23, 22, 59, 1, 21, 35, 34, 39,
+ 38, 61, 1, 35, 53, 51, 53, 35, 53, 51, 17, 1,119, 1,123,254,133,190,190, 37, 38,115,189,189,213, 81, 81,135,135,135,135, 5,
+158,254,194,143,233,142,233,137, 39, 39,154, 80, 79,210,233,142,233,143, 1, 62,255,255, 0,178,255,227, 5, 41, 5,213, 16, 39,
+ 6,134, 4,238, 1,117, 19, 6, 0, 56, 0, 0, 0, 16,180, 31, 9, 24, 39, 7, 43, 64, 5, 16, 9, 31, 24, 2, 93, 49, 0, 0,
+255,255, 0,174,255,227, 4, 88, 6, 55, 16, 39, 2, 53, 0,131, 0, 0, 19, 6, 0, 88, 0, 0, 0, 8,180, 30, 8, 22, 38, 7,
+ 43, 49, 0, 0,255,255, 0,178,255,227, 5, 41, 7, 49, 16, 39, 0,113, 0,238, 1, 59, 19, 6, 0, 56, 0, 0, 0, 20,180, 5,
+ 3, 2, 13, 7, 43, 64, 9, 47, 2, 32, 3, 31, 2, 16, 3, 4, 93, 49, 0, 0,255,255, 0,174,255,227, 4, 88, 5,245, 16, 39,
+ 0,113, 0,131,255,255, 19, 6, 0, 88, 0, 0, 0, 8,180, 6, 3, 2, 14, 7, 43, 49, 0, 0,255,255, 0,178,255,227, 5, 41,
+ 5,213, 16, 39, 6,139, 4,238, 1,117, 19, 6, 0, 56, 0, 0, 0, 16,180, 15, 0, 8, 23, 7, 43, 64, 5, 16, 0, 31, 8, 2,
+ 93, 49, 0, 0,255,255, 0,174,255,227, 4, 88, 6, 72, 16, 39, 2, 49, 0,131, 0, 0, 19, 6, 0, 88, 0, 0, 0, 8,180, 16,
+ 0, 8, 24, 7, 43, 49, 0, 0,255,255, 0,178,255,227, 5, 41, 8, 75, 18, 38, 0, 56, 0, 0, 17, 7, 2, 51, 0,240, 1, 69,
+ 0, 9, 64, 5, 64, 30, 64, 18, 2, 93, 49, 0,255,255, 0,174,255,227, 4, 88, 6,202, 18, 38, 0, 88, 0, 0, 17, 6, 2, 51,
+124,196, 0, 9, 64, 5, 64, 20, 64, 32, 2, 93, 49, 0, 0, 0,255,255, 0,178,255,227, 5, 41, 5,213, 16, 39, 6,141, 4,238,
+ 1,117, 18, 6, 0, 56, 0, 0,255,255, 0,174,255,227, 4, 94, 6,102, 16, 39, 2, 54, 0,176, 0, 0, 18, 6, 0, 88, 0, 0,
+255,255, 0,178,254,101, 5, 41, 5,213, 18, 38, 0, 56, 0, 0, 16, 7, 2, 52, 0,250,255,240,255,255, 0,174,254,117, 4,232,
+ 4, 96, 18, 38, 0, 88, 0, 0, 16, 7, 2, 52, 2, 39, 0, 0,255,255, 0, 68, 0, 0, 7,166, 5,213, 16, 39, 6,136, 5,245,
+ 1,124, 19, 6, 0, 58, 0, 0, 0, 8,180, 21, 2, 6, 20, 7, 43, 49, 0, 0,255,255, 0, 86, 0, 0, 6, 53, 6,109, 16, 39,
+ 2, 31, 1, 69, 0, 7, 19, 6, 0, 90, 0, 0, 0, 8,180, 21, 2, 6, 20, 7, 43, 49, 0, 0,255,255,255,252, 0, 0, 4,231,
+ 5,213, 16, 39, 6,136, 4,114, 1,124, 19, 6, 0, 60, 0, 0, 0, 8,180, 11, 2, 6, 7, 7, 43, 49, 0, 0,255,255, 0, 61,
+254, 86, 4,127, 6,109, 16, 38, 2, 31, 94, 7, 19, 6, 0, 92, 0, 0, 0, 8,180, 24, 2, 6, 23, 7, 43, 49,255,255,255,252,
+ 0, 0, 4,231, 5,213, 18, 38, 0, 60, 0, 0, 17, 7, 6,132, 4,115, 1,117, 0, 8,180, 0, 16, 11, 4, 7, 43, 49, 0, 0,
+255,255, 0, 92, 0, 0, 5, 31, 5,213, 16, 39, 6,133, 4,149, 1,118, 18, 6, 0, 61, 0, 0,255,255, 0, 88, 0, 0, 3,219,
+ 6,109, 16, 38, 0,118, 66, 7, 18, 6, 0, 93, 0, 0, 0, 0,255,255, 0, 92, 0, 0, 5, 31, 5,213, 16, 39, 6,140, 4,168,
+ 1, 98, 18, 6, 0, 61, 0, 0,255,255, 0, 88, 0, 0, 3,219, 6, 16, 16, 38, 2, 50, 0, 0, 18, 6, 0, 93, 0, 0, 0, 0,
+255,255, 0, 92, 0, 0, 5, 31, 5,213, 18, 38, 0, 61, 0, 0, 16, 7, 6,137, 4,190, 1,117,255,255, 0, 88, 0, 0, 3,219,
+ 6,102, 18, 38, 0, 93, 0, 0, 17, 6, 2, 32, 27, 0, 0, 16,180, 1, 15, 11, 0, 7, 43, 64, 5, 15, 15, 0, 11, 2, 93, 49,
+ 0, 1, 0, 47, 0, 0, 2,248, 6, 20, 0, 16, 0, 35, 64, 18, 11,135, 10,151, 1, 2,169, 5,188, 1, 10, 16, 8, 4, 6, 2,
+ 76, 17, 16,252, 60,204,252,204, 49, 0, 47,244,236, 16,244,236, 48, 33, 35, 17, 35, 53, 51, 53, 52, 54, 59, 1, 21, 35, 34, 7,
+ 6, 21, 1,152,185,176,176,174,189,174,176, 99, 39, 38, 3,209,143, 78,187,171,153, 40, 41,103, 0, 2, 0, 32,255,227, 4,164,
+ 6, 20, 0, 15, 0, 44, 0, 68, 64, 37, 4,185, 16, 20, 12,185, 32, 28,140, 20,184, 34, 41, 37,169, 44, 36, 39,151, 34, 46, 69,
+ 0, 18, 24, 71, 42, 32, 6, 44, 40, 8, 37, 35, 39, 70, 45, 16,252, 60,204,236, 50, 50, 50,204,244,236,236, 49, 0, 47,244,220,
+ 60,236, 50, 16,228,244,196,236, 16,198,238, 48, 1, 52, 39, 38, 35, 34, 7, 6, 21, 20, 23, 22, 51, 50, 55, 54, 1, 54, 55, 54,
+ 51, 50, 23, 22, 17, 16, 7, 6, 35, 34, 39, 38, 39, 21, 35, 17, 35, 53, 51, 53, 51, 21, 33, 21, 33, 3,229, 83, 84,146,146, 84,
+ 83, 83, 84,146,146, 84, 83,253,142, 58, 89, 88,123,204,127,128,128,127,204,123, 88, 89, 58,185,154,154,185, 1, 69,254,187, 2,
+ 47,203,116,115,115,116,203,203,116,115,115,116, 2, 82,100, 48, 49,162,162,254,248,254,248,162,162, 49, 48,100,168, 5, 4,125,
+147,147,125, 0, 0, 3,255,151, 0, 0, 5, 80, 5,213, 0, 8, 0, 17, 0, 41, 0, 67, 64, 35, 25, 0,149, 10, 9,149, 18,129,
+ 1,149, 10,173, 31, 17, 11, 8, 2, 19, 25, 31, 5, 0, 14, 28, 22, 5, 25, 28, 46, 9, 0, 28, 18, 4, 42, 16,252,236, 50,252,
+236,212,236, 17, 23, 57, 57, 57, 49, 0, 47,236,236,244,236, 16,238, 57, 48,178, 15, 34, 1, 1, 93, 1, 17, 33, 50, 54, 53, 52,
+ 38, 35, 1, 17, 33, 50, 54, 53, 52, 38, 35, 37, 33, 50, 22, 21, 20, 6, 7, 30, 1, 21, 20, 4, 35, 33, 17, 34, 6, 29, 1, 35,
+ 53, 52, 54, 1,247, 1, 68,163,157,157,163,254,188, 1, 43,148,145,145,148,254, 11, 2, 4,231,250,128,124,149,165,254,240,251,
+253,232,132,118,156,192, 2,201,253,221,135,139,140,133, 2,102,254, 62,111,114,113,112,166,192,177,137,162, 20, 32,203,152,200,
+218, 5, 48, 95,105, 49, 70,181,163, 0, 0, 0,255,255, 0,201, 0, 0, 4,236, 5,213, 18, 6, 3, 46, 0, 0, 0, 2, 0,186,
+255,227, 4,164, 6, 20, 0, 22, 0, 38, 0, 56, 64, 31, 27,185, 0, 4, 35,185, 16, 12,140, 4,184, 18, 22,169, 19,151, 18, 40,
+ 69, 20, 23, 18, 8, 71, 16, 31, 22, 8, 19, 70, 39, 16,252,236, 50, 50,244,236,196,236, 49, 0, 47,244,236, 16,228,244,196,236,
+ 16,198,238, 48, 1, 54, 55, 54, 51, 50, 23, 22, 17, 16, 7, 6, 35, 34, 39, 38, 39, 21, 35, 17, 33, 21, 37, 1, 52, 39, 38, 35,
+ 34, 7, 6, 21, 20, 23, 22, 51, 50, 55, 54, 1,115, 58, 89, 88,123,204,127,128,128,127,204,123, 88, 89, 58,185, 3, 78,253,107,
+ 2,114, 83, 84,146,146, 84, 83, 83, 84,146,146, 84, 83, 3,182,100, 48, 49,162,162,254,248,254,248,162,162, 49, 48,100,168, 6,
+ 20,166, 1,252,192,203,116,115,115,116,203,203,116,115,115,116, 0, 2, 0, 0, 0, 0, 4,236, 5,213, 0, 10, 0, 23, 0, 51,
+ 64, 12, 23, 11, 25, 0, 25, 16, 46, 5, 11, 28, 21, 22, 47,220,236, 50,252,236,196, 16,204, 49, 64, 9, 5,149, 12,173, 11,129,
+ 6,149, 20, 0, 47,236,228,244,236,179, 21, 21, 11, 20, 17, 18, 57, 47, 48, 1, 52, 39, 38, 35, 33, 17, 33, 50, 55, 54, 1, 17,
+ 33, 50, 4, 21, 20, 4, 35, 33, 17, 35, 1, 4, 23, 79, 78,163,254,188, 1, 68,163, 78, 79,253,124, 1, 78,251, 1, 16,254,240,
+251,253,232,201, 1, 56, 1,183,139, 68, 67,253,221, 68, 67, 4,168,253,154,218,222,221,218, 4, 68, 1,145, 0, 0, 2, 0, 0,
+255,227, 4,164, 6, 21, 0, 18, 0, 30, 0, 62, 64, 13, 17, 18, 32, 19, 18, 6, 71, 13, 25, 18, 8, 15, 16, 47,220,236, 50, 50,
+244,236,196, 16,204, 49, 64, 14, 0, 22,185, 3,184, 14, 12, 28,185, 9,140, 17,151, 14, 0, 47,228,244,236,196, 16,244,236,196,
+179, 15, 15, 17, 14, 17, 18, 57, 47, 48, 1, 62, 1, 51, 50, 0, 17, 16, 2, 35, 34, 38, 39, 21, 35, 17, 35, 1, 51, 1, 52, 38,
+ 35, 34, 6, 21, 20, 22, 51, 50, 54, 1,115, 58,177,123,204, 0,255,255,204,123,177, 58,185,186, 1, 34, 81, 2,114,167,146,146,
+167,167,146,146,167, 3,182,100, 97,254,188,254,248,254,248,254,188, 97,100,168, 4, 68, 1,209,252, 26,203,231,231,203,203,231,
+231, 0, 0, 0, 0, 1, 0,115,255,227, 5, 39, 5,240, 0, 25, 0, 48, 64, 27, 25,134, 0,136, 22,149, 3,145, 26, 13,134, 12,
+136, 16,149, 9,140, 26, 27, 16, 19, 25, 6, 48, 13, 0, 26, 16,220, 60,244,236,236, 49, 0, 16,244,236,244,236, 16,244,236,244,
+236, 48, 19, 62, 1, 51, 32, 0, 17, 16, 0, 33, 34, 38, 39, 53, 30, 1, 51, 32, 0, 17, 16, 0, 33, 34, 6, 7,115,104,237,134,
+ 1, 83, 1,134,254,122,254,173,132,237,106,102,231,130, 1, 0, 1, 16,254,240,255, 0,130,231,102, 5, 98, 71, 71,254, 97,254,
+152,254,153,254, 97, 72, 72,211, 95, 94, 1, 57, 1, 39, 1, 40, 1, 57, 94, 95, 0, 1, 0,115,255,227, 6, 90, 7,100, 0, 36,
+ 0, 0, 1, 54, 55, 54, 59, 1, 21, 35, 34, 6, 29, 1, 46, 1, 35, 32, 0, 17, 16, 0, 33, 50, 54, 55, 21, 14, 1, 35, 32, 0,
+ 17, 16, 0, 33, 50, 23, 22, 4, 97, 16, 83,102,227, 77, 63,134,110,102,231,130,255, 0,254,240, 1, 16, 1, 0,130,231,102,106,
+237,132,254,173,254,122, 1,134, 1, 83,134,118, 13, 5,197,195, 98,122,170,150,194,213, 95, 94,254,199,254,216,254,217,254,199,
+ 94, 95,211, 72, 72, 1,159, 1,103, 1,104, 1,159, 36, 3, 0, 0, 1, 0,113,255,227, 4,205, 5,203, 0, 33, 0, 0, 1, 54,
+ 55, 54, 59, 1, 21, 35, 34, 6, 29, 1, 46, 1, 35, 34, 6, 16, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 0, 17, 16, 0, 33, 50,
+ 3, 49, 9, 70, 82,181, 70, 49,105, 76, 78,157, 80,179,198,198,179, 80,157, 78, 77,165, 93,253,254,214, 1, 45, 1, 6, 72, 4,
+111,169, 83, 96,156, 97,153,172, 43, 43,227,254,102,227, 43, 43,170, 36, 36, 1, 62, 1, 14, 1, 18, 1, 58, 0,255,255, 0, 10,
+ 0, 0, 5,186, 5,213, 16, 6, 0,146, 0, 0, 0, 2,255,151, 0, 0, 6, 20, 5,213, 0, 8, 0, 26, 0, 46, 64, 21, 0,149,
+ 9,129, 1,149, 16, 8, 2, 16, 10, 0, 5, 25, 13, 50, 0, 28, 9, 4, 27, 16,252,236,244,236, 17, 57, 57, 57, 57, 49, 0, 47,
+236,244,236, 48,178, 96, 19, 1, 1, 93, 1, 17, 51, 32, 0, 17, 16, 0, 33, 37, 33, 32, 0, 17, 16, 0, 41, 1, 17, 34, 6, 29,
+ 1, 35, 53, 52, 54, 1,247,244, 1, 53, 1, 31,254,225,254,203,254, 66, 1,159, 1,178, 1,150,254,104,254, 80,254, 97,132,118,
+156,192, 5, 47,251,119, 1, 24, 1, 46, 1, 44, 1, 23,166,254,151,254,128,254,126,254,150, 5, 48, 95,105, 49, 70,181,163, 0,
+ 0, 2, 0,201, 0, 0, 4,236, 5,213, 0, 7, 0, 20, 0, 46, 64, 12, 22, 8, 4, 19, 28, 10, 46, 0, 25, 14, 16, 21, 16,252,
+236,244,236, 50,196,196, 49, 64, 12, 19,149, 9,129, 10, 4,149, 18,173, 3,149, 10, 0, 47,236,244,236, 16,244,236, 48, 1, 16,
+ 41, 1, 17, 33, 34, 6, 17, 33, 17, 33, 34, 36, 53, 52, 36, 51, 33, 17, 33, 1,158, 1, 64, 1, 68,254,188,163,157, 3, 78,253,
+232,251,254,240, 1, 16,251, 1, 78,253,124, 1,183,254,239, 2, 35,135, 3,147,250, 43,218,222,221,218, 1,192, 0, 2, 0,113,
+255,227, 4, 90, 6, 20, 0, 17, 0, 25, 0, 0, 1, 17, 5, 53, 33, 17, 35, 53, 14, 1, 35, 34, 2, 16, 0, 51, 50, 22, 0, 16,
+ 22, 32, 54, 16, 38, 32, 3,162,253,107, 3, 77,184, 58,177,123,204,255, 0,255,204,123,177,253,200,167, 1, 36,167,167,254,220,
+ 3,182, 1,185, 1,166,249,236,168,100, 97, 1, 68, 2, 16, 1, 68, 97,254,224,254,106,231,231, 1,150,231, 0, 0, 2, 0,113,
+254, 86, 4,117, 4, 99, 0, 28, 0, 45, 0, 0, 23, 22, 51, 50, 53, 52, 37, 38, 39, 38, 17, 16, 55, 54, 51, 50, 23, 22, 17, 20,
+ 7, 6, 7, 22, 21, 16, 33, 34, 39, 1, 54, 55, 54, 53, 52, 39, 38, 35, 34, 6, 21, 20, 23, 22, 23, 22,250,102,239,253,254,248,
+208,117,142,137,137,240,239,138,137,137, 53, 75,156,254, 71,221,120, 1,232, 68, 55, 86, 85, 86,149,147,172, 91, 97,126, 64,203,
+ 70,117, 92, 48, 37,112,135, 1, 21, 1, 9,156,157,157,156,254,237,204,165, 64, 36, 79,141,254,240, 70, 1,216, 29, 73,113,204,
+203,114,115,232,190,199, 96,103, 11, 6, 0, 0, 0, 1, 0,131, 0, 0, 4, 69, 5,213, 0, 11, 0, 43, 64, 9, 13, 5, 9, 28,
+ 0, 11, 7, 2, 12, 16,220,196,196,212,236, 50,196, 49, 64, 12, 10,149, 11,129, 2, 6,149, 7,173, 3,149, 2, 0, 47,236,244,
+236, 16,244,236, 48, 1, 17, 33, 53, 33, 17, 33, 53, 33, 17, 33, 53, 4, 69,252, 62, 2,248,253, 57, 2,199,253, 26, 5,213,250,
+ 43,170, 2, 29,170, 1,186,170, 0, 2, 0,117,255,227, 5,217, 5,240, 0, 19, 0, 26, 0, 68, 64, 38, 1, 20, 0, 8,161, 7,
+174, 4, 0,149, 20, 23,149, 17, 0,149, 20,173, 4,149, 11,145, 17,140, 27, 1, 20, 26, 26, 25, 15, 51, 20, 25, 7, 0, 16, 27,
+ 16,252,196,236,244,236, 17, 18, 57, 49, 0, 16,228,244,236,244,228, 16,238, 16,238, 16,244,238, 17, 18, 57, 48, 19, 33, 16, 0,
+ 33, 34, 6, 7, 53, 54, 36, 51, 32, 0, 17, 16, 0, 33, 32, 0, 55, 22, 0, 51, 50, 0, 55,117, 4,143,254,237,254,238,139,252,
+112,111, 1, 7,146, 1, 94, 1,139,254,136,254,198,254,183,254,151,220, 13, 0,255,202,202, 0,255, 13, 3, 12, 1, 12, 1, 50,
+ 96, 95,215, 70, 72,254,103,254,146,254,159,254, 91, 1,183,204,195,254,228, 1, 28,195, 0, 0, 0, 1, 0,164,255,227, 4,123,
+ 5,240, 0, 40, 0, 64, 64, 36, 10,134, 9,136, 13,149, 6,145, 41, 0, 22,149, 19,173, 41, 31,134, 32,136, 28,149, 35,140, 41,
+ 42, 20, 9, 31, 16, 25, 3, 25, 25, 38, 16, 41, 16,252,236,212,236,212,196,196,204, 49, 0, 16,244,236,244,236, 16,244,236, 57,
+ 16,244,236,244,236, 48, 1, 46, 1, 53, 52, 36, 51, 50, 22, 23, 21, 46, 1, 35, 34, 6, 21, 20, 22, 59, 1, 21, 35, 34, 6, 21,
+ 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 32, 36, 53, 52, 54, 1,216,131,142, 1, 12,230, 89,201,115,114,190, 83,152,163,158,149,
+182,174,165,185,199,190,109,200, 84,106,199, 94,254,232,254,208,163, 3, 37, 33,171,124,178,209, 32, 32,180, 38, 36,123,115,112,
+119,166,149,132,143,150, 50, 49,195, 37, 37,242,221,144,196, 0, 0, 1,255,150,254,102, 4, 35, 5,213, 0, 17, 0, 65, 64, 31,
+ 17, 8, 18, 13,149, 12,176, 18, 6,149, 4, 2,149, 0,129, 4,173, 18, 17, 8, 0, 7, 12, 5, 1, 7, 3, 28, 0, 4, 18, 16,
+252,236, 50,212,196,196, 17, 18, 57, 57, 49, 0, 16,236,244,236, 16,238, 16,244,236, 16, 57, 57, 48,178, 15, 11, 1, 1, 93, 19,
+ 33, 21, 33, 17, 33, 21, 33, 17, 16, 6, 43, 1, 53, 51, 50, 54, 53,201, 3, 90,253,112, 2, 80,253,176,205,227, 77, 63,134,110,
+ 5,213,170,254, 72,170,253,159,254,242,244,170,150,194, 0, 0, 0, 1,255,127,254, 86, 2,248, 6, 20, 0, 27, 0,101, 64, 35,
+ 19, 10, 15,135, 13,189, 29, 5, 24, 1, 20, 8,169, 6, 1,135, 0,151, 22, 6,188, 28, 2, 27, 7, 0, 7, 9, 5, 8, 21, 23,
+ 19, 76, 28, 16,252, 75,176, 10, 84, 88,185, 0, 19, 0, 64, 56, 89, 75,176, 22, 84, 88,185, 0, 19,255,192, 56, 89, 60,196,252,
+ 60,196,196, 18, 57, 57, 49, 0, 16,228, 50,252,236, 16,238, 50, 18, 57, 57, 16,244,236, 57, 57, 48, 1,182, 64, 29, 80, 29,160,
+ 29, 3, 93, 1, 21, 35, 34, 6, 29, 1, 33, 21, 33, 17, 20, 6, 43, 1, 53, 51, 50, 54, 53, 17, 35, 53, 51, 53, 52, 54, 51, 2,
+248,176, 99, 77, 1, 47,254,209,174,189,174,176, 99, 77,176,176,174,189, 6, 20,153, 80,104, 99,143,251,235,187,171,153, 80,104,
+ 4, 42,143, 78,187,171, 0, 0, 0, 1, 0,115,255,227, 6,151, 7,100, 0, 38, 0, 70, 64, 39, 22,149, 21, 39, 0, 5, 36, 1,
+149, 3, 36,149, 8, 26,161, 27, 30,149, 14,145, 8,140, 39, 21, 2, 0, 28, 4, 17, 28, 26, 52, 4, 51, 33, 25, 11, 70, 39, 16,
+252,236,252,244,236, 16,252,196,196, 49, 0, 16,228,244,252,244,204, 16,254,212,238, 17, 57, 57, 16,220,236, 48, 37, 17, 33, 53,
+ 33, 17, 6, 4, 35, 32, 0, 17, 16, 0, 33, 50, 22, 23, 52, 54, 59, 1, 21, 35, 34, 6, 29, 1, 46, 1, 35, 32, 0, 17, 16, 0,
+ 33, 50, 54, 4,195,254,182, 2, 18,117,254,230,160,254,162,254,117, 1,139, 1, 94, 91,163, 68,201,227, 77, 63,134,110,112,252,
+139,254,238,254,237, 1, 19, 1, 18,107,168,213, 1,145,166,253,127, 83, 85, 1,153, 1,109, 1,110, 1,153, 25, 25,188,234,170,
+150,194,215, 95, 96,254,206,254,209,254,210,254,206, 37, 0, 0, 0, 2, 0, 8,254, 82, 5,118, 5,213, 0, 15, 0, 37, 0,149,
+ 64, 13, 39, 80, 18, 1, 18, 4, 25, 23, 12, 25, 31, 36, 38, 16,212,212,236,212,236,212, 93,196,181, 16, 8, 0, 3, 4, 12, 17,
+ 18, 23, 57, 49, 64, 10, 0,149, 27,189, 17, 37, 18, 36,129, 38, 0, 16,228, 50, 50, 50,244,236,179, 31, 23, 8, 27, 17, 18, 57,
+ 57, 48, 64, 12, 19, 17, 17, 18, 18, 8, 35, 37, 17, 36, 36, 8, 7, 5, 16,236, 60, 7, 16,236, 60,182, 19, 17, 8, 18, 8, 36,
+ 8, 7, 8, 16,236,182, 35, 17, 8, 36, 8, 18, 8, 7, 8, 16,236,180, 16, 37, 19, 17, 35, 15, 64, 16, 22, 21, 20, 3, 23, 19,
+ 36, 8, 34, 33, 32, 3, 31, 35, 18, 8, 4, 7, 17, 18, 23, 57, 7, 17, 18, 23, 57, 1, 50, 55, 54, 53, 52, 39, 38, 39, 6, 7,
+ 6, 21, 20, 23, 22, 19, 1, 51, 1, 22, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 53, 52, 55, 54, 55, 1, 51, 2,191, 54, 44, 28,
+ 31, 51, 44, 44, 51, 31, 28, 44, 54, 1,217,222,253,186,104, 67, 46, 75,100,155,155,100, 75, 46, 67,104,253,186,222,254,253, 32,
+ 20, 66, 57, 73,121, 92, 92,121, 73, 57, 66, 20, 32, 3,122, 3, 94,251,207,200,174,119, 66,139, 65, 87, 87, 65,139, 66,119,174,
+200, 4, 49, 0, 0, 1, 0,186, 0, 0, 7, 71, 6, 20, 0, 67, 0, 0, 1, 52, 38, 35, 34, 6, 7, 17, 35, 17, 51, 17, 52, 54,
+ 51, 50, 22, 21, 17, 20, 23, 22, 59, 1, 50, 63, 1, 53, 51, 63, 2, 53, 51, 55, 53, 51, 53, 55, 51, 53, 63, 2, 54, 53, 52, 39,
+ 38, 39, 33, 22, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 35, 7, 6, 39, 38, 53, 4,100,198,193,117,179, 66,185,185,172,149,124,
+124, 81, 82,181, 70,225,142, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 35, 30, 66, 54, 56,114,254,190, 46, 76, 77, 55, 15, 24,
+ 66, 88, 88,144, 51,103, 40, 38, 2,164,232,239,100,101, 2, 98,249,236, 2,121,164,190,158,156,254,245,214, 96, 96,146, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 42, 47,119,161,136,110,113,100, 12, 44, 45, 72, 21, 36,100,146,158, 98, 97, 1, 2, 50,
+ 49,153, 0, 0, 0, 1, 0,201, 0, 0, 2,198, 5,213, 0, 11, 0, 46, 64, 16, 11, 2, 0, 6,149, 0,129, 7, 5, 8, 6, 1,
+ 28, 0, 4, 12, 16,252, 75,176, 16, 84, 88,185, 0, 0, 0, 64, 56, 89,236,196, 57, 57, 49, 0, 47,228,236, 17, 57, 57, 48, 1,
+ 19, 51, 17, 20, 22, 59, 1, 21, 35, 34, 38, 17,201,202,110,134, 63, 77,227,205, 5,213,252, 45,194,150,170,244, 1, 14, 0, 0,
+ 0, 1, 0, 10, 0, 0, 2, 82, 5,213, 0, 11, 0, 69, 64, 17, 2, 11,149, 5, 8, 0,175, 6, 3, 5, 1, 28, 10, 8, 0, 4,
+ 12, 16,252, 60,196, 75,176, 16, 84, 88,187, 0, 8, 0, 64, 0, 0, 0, 64, 56, 56, 89,236, 50,196, 49, 0, 47,236,220, 60,244,
+ 50, 48, 1, 64, 13, 48, 13, 64, 13, 80, 13, 96, 13,143, 13,159, 13, 6, 93, 19, 51, 17, 51, 21, 35, 17, 35, 17, 35, 53, 51,201,
+202,191,191,202,191,191, 5,213,253, 22,170,253,191, 2, 65,170, 0, 1, 0,201, 0, 0, 5,221, 5,222, 0, 18, 0, 0, 1, 54,
+ 31, 1, 55, 39, 38, 7, 6, 7, 1, 17, 35, 17, 51, 17, 1, 33, 1, 4, 80, 62, 58,172,105,237, 96, 76, 53, 71,253,203,202,202,
+ 2,205, 1, 10,252,230, 4,254, 59, 33,141,116,176, 72, 39, 27, 67,253,236, 2,119,250, 43, 2,207,253, 49, 3, 29, 0, 0, 0,
+ 0, 1, 0,185, 0, 0, 4,156, 6, 20, 0, 18, 0,193, 64, 44, 16, 17, 13, 14, 13, 15, 17, 14, 14, 13, 11, 17, 12, 13, 12, 10,
+ 17, 13, 13, 12, 66, 16, 13, 10, 3, 6,149, 3,151, 11,188, 17, 14, 4, 13, 9, 12, 14, 16, 9, 8, 0, 70, 19, 16,252,236, 50,
+212,196, 17, 57,196, 49, 0, 47, 60,228,252,228, 23, 57, 48, 75, 83, 88, 7, 16, 4,237, 7, 16, 5,237, 7, 16, 5,237, 7, 16,
+ 4,237, 89, 34,178, 16, 12, 1, 1, 93, 64, 95, 4, 10, 10, 16, 22, 10, 39, 10, 41, 13, 43, 16, 86, 10,102, 10,103, 16,115, 10,
+119, 13,130, 10,137, 13,142, 16,147, 10,150, 13,151, 16,163, 10, 18, 17, 5, 17, 6, 10, 11, 11, 10, 15, 40, 11, 39, 12, 40, 13,
+ 43, 14, 43, 15, 64, 20,104, 11, 96, 20,137, 11,133, 12,137, 13,141, 14,143, 15,154, 11,151, 15,170, 11,167, 13,182, 15,197, 15,
+214, 15,247, 11,240, 11,247, 12,240, 12, 26, 93,113, 0, 93, 19, 52, 54, 59, 1, 21, 35, 34, 6, 21, 17, 1, 51, 9, 1, 35, 1,
+ 17, 35,185,163,181,191,168,105, 76, 2, 37,235,253,174, 2,107,240,253,199,185, 4,126,214,192,156, 97,153,253,255, 1,227,253,
+244,253,172, 2, 35,253,221, 0, 0, 1, 0, 10, 0, 0, 2, 42, 6, 20, 0, 11, 0, 50, 64, 7, 5, 1, 8, 8, 0, 70, 12, 16,
+252, 60,236, 50, 49, 0, 64, 8, 2, 11,169, 5, 8, 0,151, 6, 47,236,212, 60,236, 50, 48, 64, 13, 16, 13, 64, 13, 80, 13, 96,
+ 13,112, 13,240, 13, 6, 1, 93, 19, 51, 17, 51, 21, 35, 17, 35, 17, 35, 53, 51,193,184,177,177,184,183,183, 6, 20,253, 56,144,
+253, 68, 2,188,144, 0, 0, 0, 0, 1, 0, 61, 0, 0, 4,127, 6, 20, 0, 15, 0, 0, 51, 1, 39, 5, 39, 37, 39, 51, 23, 37,
+ 23, 5, 1, 35, 9, 1, 61, 1,235, 71,254,212, 33, 1, 41, 75,200, 52, 1, 58, 33,254,201, 1,237,195,254,198,254,126, 4, 50,
+188,101, 99, 99,197,138,104, 97,104,250,215, 3, 60,252,196, 0, 0, 1, 0,178,255,227, 7, 39, 5,213, 0, 35, 0, 0, 37, 14,
+ 1, 35, 34, 38, 53, 17, 51, 17, 20, 23, 22, 51, 50, 54, 53, 17, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 35, 53, 14, 1, 35,
+ 34, 38, 3,166, 69,192,130,175,190,203, 39, 57,117,143,166,203,114,119,123,166,203,203, 63,176,121,122,171,213,124,118,245,226,
+ 4, 27,251,239,186, 53, 78,190,164, 3,236,251,239,162,155,191,163, 3,236,250, 41,174,103, 98,124, 0, 0, 0, 0, 1,255,150,
+254,102, 5, 51, 5,213, 0, 17, 0,140, 64, 41, 7, 17, 1, 2, 1, 2, 17, 6, 7, 6, 66, 8, 17, 0, 13,149, 12,176, 18, 7,
+ 2, 3, 0,175, 5, 6, 1, 7, 2, 28, 4, 54, 11, 14, 12, 57, 7, 28, 0, 4, 18, 16,252,236,228, 57, 57,252,236, 17, 57, 57,
+ 49, 0, 47,236, 50, 57, 57, 16,252,236, 17, 57, 57, 48, 75, 83, 88, 7, 16, 4,237, 7, 16, 4,237, 89, 34,178, 31, 11, 1, 1,
+ 93, 64, 48, 54, 2, 56, 7, 72, 2, 71, 7,105, 2,102, 7,128, 2, 7, 6, 1, 9, 6, 21, 1, 26, 6, 70, 1, 73, 6, 87, 1,
+ 88, 6,101, 1,105, 6,121, 6,133, 1,138, 6,149, 1,154, 6,159, 19, 16, 93, 0, 93, 19, 33, 1, 17, 51, 17, 33, 1, 17, 16,
+ 6, 43, 1, 53, 51, 50, 54, 53,201, 1, 16, 2,150,196,254,240,253,106,205,227, 71, 63,134,110, 5,213,251, 31, 4,225,250, 43,
+ 4,225,251,135,254,242,244,170,150,194, 0, 0,255,255, 0,186,254, 86, 4,100, 4,123, 16, 6, 2,213, 0, 0, 0, 3, 0,115,
+255,227, 5,217, 5,240, 0, 11, 0, 18, 0, 25, 0, 47, 64, 11, 25, 16, 25, 6, 51, 15, 19, 25, 0, 16, 26, 16,252,236, 50,244,
+236, 50, 49, 0, 64, 14, 22,149, 9, 15,149, 19,173, 12,149, 3,145, 9,140, 26, 16,228,244,236,244,228, 16,236, 48, 19, 16, 0,
+ 33, 32, 0, 17, 16, 0, 33, 32, 0, 1, 34, 2, 7, 33, 38, 2, 1, 22, 0, 51, 50, 0, 55,115, 1,121, 1, 59, 1, 58, 1,120,
+254,136,254,198,254,197,254,135, 2,180,232,239, 6, 3,186, 6,239,253, 66, 13, 0,255,202,202, 0,255, 13, 2,233, 1, 98, 1,
+165,254, 91,254,158,254,159,254, 91, 1,164, 3,197,254,172,236,236, 1, 84,253, 26,195,254,228, 1, 28,195, 0,255,255, 0,103,
+255,227, 6,195, 5,240, 16, 38, 0, 50,244, 0, 16, 7, 2, 99, 6, 72, 0, 11,255,255, 0,118,255,227, 4,211, 4,235, 16, 39,
+ 2, 99, 4, 88, 0, 11, 16, 6, 0, 82, 5, 0, 0, 2, 0,115,255,227, 6,207, 5,240, 0, 10, 0, 30, 0, 0, 1, 34, 0, 17,
+ 16, 0, 51, 50, 55, 17, 38, 1, 17, 52, 38, 35, 17, 6, 33, 32, 0, 16, 0, 33, 50, 23, 33, 50, 22, 25, 1, 3, 39,220,254,253,
+ 1, 3,220,175,128,138, 2, 57,110,122,188,254,198,254,197,254,135, 1,121, 1, 59,112, 97, 1, 39,227,205, 5, 76,254,184,254,
+229,254,230,254,184,164, 3,125,164,250,180, 3,211,194,150,251,139,211, 1,164, 2,196, 1,165, 27,244,254,242,252, 45, 0, 0,
+ 0, 2, 0,113,254, 86, 5, 89, 4,123, 0, 9, 0, 30, 0, 0, 1, 38, 7, 6, 16, 22, 32, 55, 17, 38, 1, 17, 52, 38, 35, 17,
+ 6, 35, 34, 0, 17, 16, 0, 51, 50, 23, 51, 50, 22, 21, 17, 2,115,147, 87, 86,171, 1, 42, 44, 44, 1,153, 76,105,137,240,241,
+254,239, 1, 17,241,100, 82,216,181,163, 3,223, 2,117,116,254,110,231, 89, 2,168, 95,250,119, 4,116,153, 97,252,188,157, 1,
+ 57, 1, 19, 1, 20, 1, 56, 27,192,214,251,140, 0, 2,255,151, 0, 0, 4,241, 5,213, 0, 8, 0, 28, 0, 58, 64, 24, 1,149,
+ 16, 0,149, 9,129, 18, 16, 10, 8, 2, 4, 0, 5, 25, 13, 63, 17, 0, 28, 9, 4, 29, 16,252,236, 50,252,236, 17, 23, 57, 49,
+ 0, 47,244,236,212,236, 48, 64, 11, 15, 21, 31, 21, 63, 21, 95, 21,175, 21, 5, 1, 93, 1, 17, 51, 50, 54, 53, 52, 38, 35, 37,
+ 33, 50, 4, 21, 20, 4, 43, 1, 17, 35, 17, 34, 6, 29, 1, 35, 53, 52, 54, 1,247,254,141,154,154,141,254, 56, 1,200,251, 1,
+ 1,254,255,251,254,202,132,118,156,192, 5, 47,253,207,146,135,134,146,166,227,219,221,226,253,168, 5, 48, 95,105, 49, 70,181,
+163, 0, 0, 0, 0, 2, 0,184,254, 86, 4,164, 6, 20, 0, 24, 0, 36, 0, 79, 64, 36, 35,185, 0, 23, 29,185, 14, 17,184, 23,
+140, 1,189, 37, 3, 12, 9,169, 6,151, 37, 26, 18, 20, 71, 6, 9, 3, 7, 32, 12, 0, 8, 2, 70, 37, 16,252,236, 50, 50,204,
+ 17, 57, 57,244,236, 49, 0, 16,244,236, 57, 57, 16,228,228,244,196,236, 16,196,238, 48, 64, 9, 96, 39,128, 39,160, 39,224, 39,
+ 4, 1, 93, 37, 17, 35, 3, 52, 54, 59, 1, 21, 35, 34, 6, 29, 1, 62, 1, 51, 50, 0, 17, 16, 2, 35, 34, 38, 1, 52, 38, 35,
+ 34, 6, 21, 20, 22, 51, 50, 54, 1,115,185, 1,163,181,254,231,105, 76, 58,177,123,204, 0,255,255,204,123,177, 2, 56,167,146,
+146,167,167,146,146,167,168,253,174, 6, 40,214,192,156, 97,153,200,100, 97,254,188,254,248,254,248,254,188, 97, 1,235,203,231,
+231,203,203,231,231, 0, 0, 0, 0, 2, 0,201,254, 86, 4,166, 5,213, 0, 29, 0, 38, 0, 0, 19, 51, 17, 51, 50, 4, 16, 7,
+ 6, 7, 22, 23, 19, 22, 23, 22, 59, 1, 21, 35, 34, 39, 38, 39, 3, 38, 43, 1, 17, 35, 1, 51, 50, 54, 16, 38, 43, 1, 17,201,
+202,254,251, 1, 1,129,101,178, 10, 9,144, 54, 39, 42, 76, 59, 98,127, 71, 74, 78,153, 21, 46,119,202, 1, 2,198,141,154,153,
+142,254, 5,213,254,248,225,254, 72,113, 89, 19, 20, 23,254,146,136, 34, 36,154, 61, 63,198, 1,133, 53,254,174, 1,248,146, 1,
+ 12,145,253,209, 0, 1, 0, 69,255,227, 4, 96, 5,240, 0, 39, 0, 0, 19, 62, 1, 51, 50, 4, 21, 20, 6, 15, 1, 14, 1, 21,
+ 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 32, 36, 53, 52, 54, 63, 1, 62, 1, 53, 52, 38, 35, 34, 6, 7,159,114,218,105,245, 1,
+ 23,202,226,123,154,135,188,173,114,236,123,128,239,106,254,231,254,221,215,226,122,166,119,179,165, 95,204,115, 5,164, 38, 38,
+228,198,171,192, 45, 24, 31,124,110,126,136, 70, 69,208, 47, 48,224,217,182,217, 43, 25, 31,101, 99,118,128, 54, 55, 0, 0, 0,
+ 0, 1, 0,100,255,227, 3,188, 4,123, 0, 39, 0,207, 64, 17, 10, 30, 29, 9, 13, 33, 20, 33, 8, 6, 13, 8, 0, 82, 26, 69,
+ 40, 16,252,228,236,212,236,196, 17, 18, 57, 57, 57, 57, 49, 64, 25, 30, 29, 10, 9, 4, 19, 0,134, 39,137, 36, 20,134, 19,137,
+ 16,185, 23, 36,185, 3,184, 23,140, 40, 0, 16,228,244,236, 16,254,245,238, 16,245,238, 18, 23, 57, 48, 64, 18, 27, 28, 2, 26,
+ 29, 83, 9, 10, 32, 31, 2, 33, 30, 83, 10, 10, 9, 66, 75, 83, 88, 7, 16, 14,237, 17, 23, 57, 7, 14,237, 17, 23, 57, 89, 34,
+178, 0, 1, 1, 1, 93, 64, 17, 47, 41, 63, 41, 95, 41,127, 41,128, 41,144, 41,160, 41,240, 41, 8, 93, 64, 37, 32, 0, 32, 39,
+ 36, 38, 40, 30, 40, 29, 42, 21, 47, 20, 47, 19, 42, 18, 40, 10, 40, 9, 41, 8, 41, 7, 36, 1,134, 30,134, 29,134, 28,134, 27,
+ 18, 0, 93, 64, 23, 28, 30, 28, 29, 28, 28, 46, 31, 44, 30, 44, 29, 44, 28, 59, 31, 59, 30, 59, 29, 59, 28, 11,113, 19, 62, 1,
+ 51, 50, 22, 21, 20, 6, 15, 1, 14, 1, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 53, 52, 54, 63, 1, 62, 1, 53, 52,
+ 38, 35, 34, 6, 7,160, 76,180,102,206,224,152,171, 64,171,101,140,130, 97,198,102,108,195, 90,216,247,165,196, 63,148, 98,137,
+137, 90,168, 78, 4, 63, 30, 30,172,158,130,149, 36, 15, 37, 80, 75, 81, 89, 53, 53,190, 35, 35,182,156,137,153, 42, 14, 33, 73,
+ 64, 84, 84, 40, 40, 0, 0, 0,255,255, 0,201, 0, 0, 4,139, 5,213, 16, 6, 2,193, 0, 0, 0, 2,254,242,254, 86, 2,215,
+ 6, 20, 0, 8, 0, 33, 0, 0, 19, 38, 39, 38, 35, 34, 7, 6, 51, 5, 3, 20, 23, 22, 59, 1, 21, 35, 34, 39, 38, 53, 17, 35,
+ 32, 53, 52, 33, 50, 23, 22, 23, 51, 21,180, 7, 18, 33,110,124, 3, 3,119, 1,120, 2, 39, 37,100,176,174,195, 81, 87,190,254,
+242, 1, 47,181, 82, 53, 18,191, 5, 4, 45, 23, 48, 65, 51,154,251, 61,103, 41, 40,153, 86, 92,180, 4,174,210,216, 96, 64,111,
+155, 0, 0, 0, 0, 1, 0, 55,254, 86, 2,242, 5,158, 0, 29, 0, 0, 1, 17, 33, 21, 33, 17, 20, 22, 59, 1, 21, 20, 6, 43,
+ 1, 53, 51, 50, 54, 61, 1, 35, 34, 38, 53, 17, 35, 53, 51, 17, 1,119, 1,123,254,133, 75,115,189,164,180, 70, 48,106, 76, 5,
+213,162,135,135, 5,158,254,194,143,253,160,137, 78,174,214,192,156, 97,153, 20,159,210, 2, 96,143, 1, 62, 0, 0, 1, 0, 24,
+ 0, 0, 4,233, 5,213, 0, 15, 0, 88, 64, 21, 13, 10, 12, 6, 2,149, 0,129, 4, 0, 7, 1, 64, 3, 28, 5, 11, 28, 13, 5,
+ 16, 16,212,212,236, 16,252,228, 57, 57, 49, 0, 47,244,236, 50,196, 57, 57, 48, 1, 75,176, 10, 84, 88,189, 0, 16, 0, 64, 0,
+ 1, 0, 16, 0, 16,255,192, 56, 17, 55, 56, 89, 64, 19, 0, 17, 31, 0, 16, 1, 16, 2, 31, 7, 16, 17, 64, 17,112, 17,159, 17,
+ 9, 93, 1, 33, 21, 33, 17, 35, 17, 35, 34, 6, 29, 1, 35, 53, 52, 54, 1,174, 3, 59,253,238,203, 94,132,118,156,192, 5,213,
+170,250,213, 5, 43, 90,105, 49, 70,181,163, 0, 0, 1, 0, 55, 0, 0, 2,242, 6, 20, 0, 27, 0, 73, 64, 16, 25, 22, 11, 8,
+ 4, 23, 9, 2, 4, 0, 8, 16, 19, 14, 70, 28, 16,252, 60,196,252, 60,196, 50, 50, 23, 57, 49, 0, 64, 19, 19, 0, 25,135, 22,
+151, 10, 14, 5, 8, 15, 3,169, 17, 1,188, 8,135, 10, 47,236,244, 60,236, 50, 17, 57, 57, 16,244,236, 57, 57, 48,178,175, 21,
+ 1, 1, 93, 1, 21, 33, 21, 33, 17, 20, 22, 59, 1, 21, 35, 34, 38, 53, 17, 35, 53, 51, 53, 52, 54, 59, 1, 21, 35, 34, 6, 1,
+119, 1,123,254,133, 75,115,189,189,213,162,135,135,174,189,174,176, 99, 77, 4,195, 99,143,253,160,137, 78,154,159,210, 2, 96,
+143, 78,187,171,153, 81, 0, 0, 0, 1,255,250,254,102, 4,233, 5,213, 0, 15, 0, 84, 64, 20, 7,149, 10,189, 16, 14, 2,149,
+ 0,129, 16, 8, 1, 64, 3, 28, 0, 64, 13, 16, 16,212,228,252,228,196, 49, 0, 16,244,236, 50, 16,244,236, 48, 1, 75,176, 10,
+ 84, 88,189, 0, 16, 0, 64, 0, 1, 0, 16, 0, 16,255,192, 56, 17, 55, 56, 89, 64, 19, 0, 17, 31, 0, 16, 1, 16, 2, 31, 15,
+ 16, 17, 64, 17,112, 17,159, 17, 17, 93, 3, 33, 21, 33, 17, 20, 22, 59, 1, 21, 35, 34, 38, 25, 1, 33, 6, 4,239,253,238,110,
+134, 63, 78,227,205,253,238, 5,213,170,251, 61,194,150,170,244, 1, 14, 4,195,255,255, 0,173,255,247, 6, 95, 5,233, 16, 38,
+ 0, 56,251, 20, 16, 7, 2, 99, 5,228, 0, 11,255,255, 0,176,255,227, 5,105, 4,235, 16, 39, 2, 99, 4,238, 0, 11, 16, 6,
+ 0, 88, 2, 0, 0, 1, 0, 78,255,227, 5,207, 5,202, 0, 31, 0, 58, 64, 16, 3, 6, 25, 40, 16, 0, 28, 51, 22, 15, 12, 25,
+ 18, 22, 16, 32, 16,252,196,252,196, 16,244,196,236,252,196, 49, 0, 64, 14, 19, 15, 31, 3,149, 2, 16,129, 32, 9,149, 25,140,
+ 32, 16,244,236, 16,252, 60,236, 50, 50, 50, 48, 1, 53, 33, 21, 22, 18, 21, 20, 0, 35, 34, 0, 53, 52, 18, 55, 53, 33, 21, 33,
+ 6, 2, 21, 16, 0, 33, 32, 0, 17, 52, 2, 39, 5,207,253,168,177,198,254,248,216,216,254,247,199,178,253,168, 1, 63,158,145,
+ 1,127, 1, 49, 1, 47, 1,129,142,161, 5, 24,178,178, 97,254,180,202,240,254,222, 1, 35,239,202, 1, 76, 97,178,178,139,254,
+214,184,254,194,254,118, 1,137, 1, 53,194, 1, 40,141, 0, 0, 0, 1, 0,201,255,254, 5,118, 5,213, 0, 26, 0, 0, 37, 35,
+ 34, 38, 53, 17, 35, 17, 16, 23, 22, 31, 1, 32, 0, 17, 52, 2, 47, 1, 21, 22, 23, 22, 21, 20, 0, 2,198, 63,134,110,202,103,
+ 97,232, 77, 1, 47, 1,129,142,161,179,110, 65, 99,254,248,170,150,194, 3,211,252, 45,254,242,122,116, 6, 2, 1,137, 1, 53,
+194, 1, 40,141, 1, 68, 87,109,166,202,240,254,222, 0, 0, 0, 0, 1,255,252, 0, 0, 5,220, 5,237, 0, 16, 0, 0, 9, 1,
+ 54, 55, 54, 23, 5, 7, 39, 6, 7, 1, 17, 35, 17, 1, 51, 2,115, 1, 72, 52, 49, 66,109, 1, 13, 78,198, 85, 38,254,138,203,
+253,240,217, 3,111, 1,235, 78, 40, 54, 49,122,135,101, 6, 57,253,205,253, 57, 2,199, 3, 14, 0, 1, 0, 61,254, 86, 5,150,
+ 4,112, 0, 23, 0, 0, 5, 14, 1, 43, 1, 53, 51, 50, 54, 63, 1, 1, 51, 9, 1, 54, 55, 54, 31, 1, 7, 39, 38, 7, 2,147,
+ 78,148,124,147,108, 76, 84, 51, 33,254, 59,195, 1, 94, 1, 23, 50, 81, 97,101,215, 53,195, 81, 28,104,200,122,154, 72,134, 84,
+ 4, 78,252,148, 2,187,126, 41, 50, 48,101,147, 94, 39, 69, 0, 0, 1, 0, 92, 0, 0, 5, 31, 5,213, 0, 17, 0, 0, 19, 33,
+ 21, 1, 33, 21, 33, 1, 33, 21, 33, 53, 1, 33, 53, 33, 1, 33,115, 4,149,254,112, 1, 25,254,115,254, 84, 3,199,251, 61, 1,
+185,254,213, 1,159, 1,131,252,103, 5,213,154,254, 17,144,253,238,170,154, 2, 34,144, 1,223, 0, 1, 0, 88, 0, 0, 3,219,
+ 4, 96, 0, 17, 0, 0, 19, 33, 21, 3, 51, 21, 33, 1, 33, 21, 33, 53, 1, 35, 53, 33, 1, 33,113, 3,106,251,194,254,194,254,
+195, 2,180,252,125, 1, 43,212, 1, 80, 1, 13,253,101, 4, 96,168,254,220,144,254,143,147,168, 1, 92,144, 1, 57, 0, 0, 0,
+ 0, 1, 0,160,255,193, 4,248, 5,213, 0, 37, 0, 0, 37, 50, 55, 54, 53, 52, 39, 38, 43, 1, 53, 1, 33, 53, 33, 21, 1, 50,
+ 23, 22, 23, 22, 21, 20, 15, 1, 6, 7, 6, 33, 34, 39, 38, 39, 53, 22, 23, 22, 2,168,192, 99,100, 92, 93,165,174, 1,129,252,
+252, 4, 0,254,101,106,128, 98, 86, 81, 59, 28, 20, 45,152,254,232,119,125,126,134,106,127,126,107, 75, 75,143,134, 73, 74,166,
+ 1,220,170,168,254, 36, 56, 42,109,104,138,151, 85, 41, 29, 36,121, 19, 18, 37,195, 49, 25, 25, 0, 1, 0, 92,255,193, 4,180,
+ 5,213, 0, 37, 0, 0, 37, 50, 55, 54, 55, 21, 6, 7, 6, 35, 32, 39, 38, 47, 1, 38, 53, 52, 55, 54, 55, 54, 51, 1, 53, 33,
+ 21, 33, 1, 21, 35, 34, 7, 6, 21, 20, 23, 22, 2,172,137,126,127,106,134,126,125,119,254,232,152, 45, 20, 28, 59, 81, 86, 98,
+128,106,254,101, 4, 0,252,252, 1,129,174,165, 93, 92,100, 99,107, 25, 25, 49,195, 37, 18, 19,121, 36, 29, 41, 85,151,138,104,
+109, 42, 56, 1,220,168,170,254, 36,166, 74, 73,134,143, 75, 75, 0, 1, 0,104,254, 76, 4, 63, 4, 96, 0, 36, 0, 0, 1, 34,
+ 7, 6, 7, 6, 21, 20, 31, 1, 22, 23, 22, 33, 50, 55, 54, 55, 53, 14, 1, 35, 34, 39, 38, 53, 52, 55, 54, 59, 1, 53, 1, 33,
+ 53, 33, 21, 2, 91,106,128, 98, 86, 81, 59, 28, 28, 37,152, 1, 24, 94, 99,100,106, 84,200,109,190, 99,100, 92, 93,165,174,254,
+ 82, 2,155,252,150, 1,220, 56, 42,109,104,138,138, 98, 41, 36, 29,121, 18, 19, 37,195, 49, 50, 75, 75,143,132, 75, 74,166, 1,
+243,147,168, 0, 0, 1, 0,113,254, 86, 3,232, 4, 96, 0, 31, 0, 0, 1, 50, 55, 54, 55, 21, 6, 7, 6, 35, 32, 17, 52, 37,
+ 36, 53, 52, 35, 33, 1, 33, 53, 33, 21, 1, 32, 21, 16, 5, 6, 21, 20, 2,127, 84, 77, 79, 81, 87, 80, 86, 97,254, 32, 1,150,
+ 1, 28,235,254,222, 1,229,253,101, 3,106,254,158, 1,111,254, 48,226,254,238, 21, 21, 44,179, 32, 13, 14, 1, 25,238, 53, 37,
+ 98,124, 2, 56,147,168,254,100,229,254,236, 49, 24, 97,139, 0, 0, 1, 0,150, 0, 0, 4, 74, 5,240, 0, 34, 0, 0, 37, 33,
+ 21, 33, 53, 1, 55, 33, 53, 33, 54, 55, 54, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 4, 21, 20, 7, 6, 7, 51, 21, 35,
+ 7, 1,137, 2,193,252, 76, 1, 58,115,254,167, 1,226, 95, 37, 39,167,134, 95,211,120,122,212, 88,232, 1, 20, 34, 31, 74,104,
+236, 48,170,170,170, 1, 64,117,144,109, 72, 76, 73,119,150, 66, 67,204, 49, 50,232,194, 92, 82, 73, 96,144, 49, 0, 1, 0, 93,
+255,193, 4,249, 5,213, 0, 40, 0, 0, 1, 50, 23, 22, 23, 22, 21, 20, 15, 1, 6, 7, 6, 33, 32, 39, 38, 47, 1, 38, 53, 51,
+ 20, 23, 22, 32, 55, 54, 53, 52, 39, 38, 35, 33, 21, 35, 17, 33, 21, 33, 17, 3, 6,104,130, 99, 85, 81, 59, 28, 20, 45,152,254,
+232,254,220,152, 45, 20, 28, 59,201,100, 99, 1,124, 99,100, 92, 93,165,254,193,202, 3,161,253, 41, 3, 81, 56, 43,108,104,138,
+151, 85, 41, 29, 36,121,121, 36, 29, 41, 85,151,143, 75, 75, 75, 75,143,134, 73, 74, 1, 3, 45,170,254, 37, 0, 0, 1, 0,104,
+254, 76, 4, 63, 4, 96, 0, 37, 0, 0, 1, 50, 23, 22, 23, 22, 21, 20, 15, 1, 6, 7, 6, 33, 34, 39, 38, 39, 53, 30, 1, 51,
+ 50, 55, 54, 53, 52, 39, 38, 35, 33, 53, 51, 19, 33, 21, 33, 3, 2, 76,105,129, 99, 85, 81, 59, 28, 20, 45,152,254,232, 94, 99,
+100,106, 84,200,109,190, 99,100, 92, 93,165,254,158, 1, 3, 3, 22,253,162, 3, 1,220, 56, 43,108,104,138,151, 85, 41, 29, 36,
+121, 18, 19, 37,195, 49, 50, 75, 75,143,134, 73, 74,168, 2,132,170,254, 38, 0, 0, 1, 0, 88,255,227, 3,165, 5,158, 0, 36,
+ 0, 0, 1, 7, 22, 23, 22, 21, 20, 7, 6, 33, 34, 39, 38, 39, 53, 22, 23, 22, 51, 50, 55, 54, 55, 52, 39, 38, 43, 1, 19, 35,
+ 53, 51, 17, 51, 17, 51, 21, 2, 33, 2,170,112,108,110,137,254,237, 85, 81, 81, 76, 73, 84, 78, 80,179, 99, 57, 1, 58, 86,192,
+ 62, 2,229,229,202,231, 3,230,125, 30,119,115,170,186,125,157, 18, 17, 35,172, 40, 24, 22,114, 65,133, 98, 76,114, 1, 15,164,
+ 1, 20,254,236,164, 0, 0, 0, 0, 2, 0,186,254, 86, 4,164, 4,123, 0, 14, 0, 23, 0, 0, 5, 17, 35, 17, 51, 21, 54, 55,
+ 54, 51, 50, 23, 22, 21, 16, 1, 0, 53, 52, 39, 38, 35, 34, 7, 1,115,185,185, 52,135, 81,210,184, 77, 78,252,207, 2,114, 57,
+ 56,120,220,173,122,254,208, 6, 10,170, 66, 82, 49,112,113,153,254, 87,254,228, 1,144,249,133, 66, 65,239, 0, 0, 1, 0,201,
+254, 86, 1,147, 5,213, 0, 3, 0, 0, 19, 51, 17, 35,201,202,202, 5,213,248,129, 0, 0, 0,255,255, 0,201,254, 86, 3, 39,
+ 5,213, 16, 39, 1,130, 1,148, 0, 0, 16, 6, 1,130, 0, 0, 0, 1, 0, 20,254, 86, 3,156, 5,213, 0, 19, 0, 0, 1, 51,
+ 17, 33, 21, 33, 21, 33, 21, 33, 17, 35, 17, 33, 53, 33, 53, 33, 53, 33, 1,115,202, 1, 95,254,161, 1, 95,254,161,202,254,161,
+ 1, 95,254,161, 1, 95, 5,213,253,151,168,240,170,253, 44, 2,212,170,240,168,255,255, 0,201, 0, 0, 1,148, 5,213, 16, 6,
+ 0, 4,148, 0,255,255, 0,201, 0, 0, 10,208, 5,213, 16, 39, 1, 63, 5,177, 0, 0, 16, 6, 0, 39, 0, 0,255,255, 0,201,
+ 0, 0, 9,176, 6,102, 16, 39, 1, 64, 5,213, 0, 0, 16, 6, 0, 39, 0, 0,255,255, 0,113,255,227, 8,145, 6,102, 16, 39,
+ 1, 64, 4,182, 0, 0, 16, 6, 0, 71, 0, 0,255,255, 0,201,254,102, 6, 36, 5,213, 16, 39, 0, 45, 4,145, 0, 0, 16, 6,
+ 0, 47, 0, 0,255,255, 0,201,254, 86, 5,222, 6, 20, 16, 39, 0, 77, 4,101, 0, 0, 16, 6, 0, 47, 0, 0,255,255, 0,193,
+254, 86, 2,239, 6, 20, 16, 39, 0, 77, 1,118, 0, 0, 16, 6, 0, 79, 0, 0,255,255, 0,201,254,102, 6,242, 5,213, 16, 39,
+ 0, 45, 5, 95, 0, 0, 16, 6, 0, 49, 0, 0,255,255, 0,201,254, 86, 6,183, 6, 20, 16, 39, 0, 77, 5, 62, 0, 0, 16, 6,
+ 0, 49, 0, 0,255,255, 0,186,254, 86, 5,222, 6, 20, 16, 39, 0, 77, 4,101, 0, 0, 16, 6, 0, 81, 0, 0,255,255, 0, 16,
+ 0, 0, 5,104, 5,213, 18, 38, 0, 36, 0, 0, 17, 7, 6,137, 4,190, 1,117, 0, 6,177, 14, 0, 16, 60, 49,255,255, 0,123,
+255,227, 4, 45, 6,102, 18, 38, 0, 68, 0, 0, 17, 6, 2, 32, 90, 0, 0, 8,180, 11, 43, 39, 20, 7, 43, 49,255,255, 0,201,
+ 0, 0, 1,147, 5,213, 18, 38, 0, 44, 0, 0, 17, 7, 6,137, 3, 47, 1,117, 0, 11,180, 7, 32, 1, 0, 0, 16, 73, 99, 58,
+ 49, 0, 0, 0,255,255,255,224, 0, 0, 2, 94, 6,102, 18, 38, 0,243, 0, 0, 17, 7, 2, 32,255, 31, 0, 0, 0, 11,180, 7,
+ 32, 1, 0, 0, 16, 73, 99, 58, 49, 0, 0, 0,255,255, 0,115,255,227, 5,217, 5,240, 18, 38, 0, 50, 0, 0, 16, 7, 6,137,
+ 5, 39, 1,117,255,255, 0,113,255,227, 4,117, 6,102, 18, 38, 0, 82, 0, 0, 17, 6, 2, 32,118, 0, 0, 6,177, 27, 12, 16,
+ 60, 49, 0, 0,255,255, 0,178,255,227, 5, 41, 5,213, 18, 38, 0, 56, 0, 0, 17, 7, 6,137, 4,246, 1,117, 0, 6,177, 21,
+ 5, 16, 60, 49,255,255, 0,174,255,227, 4, 88, 6,102, 18, 38, 0, 88, 0, 0, 17, 6, 2, 32,118, 0, 0, 11,180, 23, 32, 11,
+ 1, 1, 16, 73, 99, 58, 49, 0,255,255, 0,178,255,227, 5, 41, 5,213, 16, 38, 6,143, 48, 0, 18, 2, 0, 56, 0, 0, 0, 0,
+255,255, 0,174,255,227, 4, 88, 7, 49, 16, 39, 0,113, 0,123, 1, 59, 18, 6, 0,190, 0, 0,255,255, 0,178,255,227, 5, 41,
+ 5,213, 16, 38, 0, 56, 0, 0, 16, 6, 6,146, 54, 0, 0, 0,255,255, 0,174,255,227, 4, 88, 4, 96, 16, 38, 0, 88, 0, 0,
+ 16, 7, 6,146,255,190,254,200,255,255, 0,178,255,227, 5, 41, 5,213, 16, 38, 0, 56, 0, 0, 16, 6, 6,151, 48, 0, 0, 0,
+255,255, 0,174,255,227, 4, 88, 4, 96, 16, 38, 0, 88, 0, 0, 16, 7, 6,151,255,196,254,200,255,255, 0,178,255,227, 5, 41,
+ 5,213, 16, 38, 0, 56, 0, 0, 16, 6, 6,147, 48, 6, 0, 0,255,255, 0,174,255,227, 4, 88, 4, 96, 16, 38, 0, 88, 0, 0,
+ 16, 7, 6,147,255,190,254,200,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 16, 6, 2, 4, 0, 0,255,255, 0, 16, 0, 0, 5,104,
+ 5,213, 18, 34, 0, 36, 0, 0, 16, 6, 6,143, 0, 0, 0, 0,255,255, 0,123,255,227, 4, 45, 7, 49, 18, 38, 0,166, 0, 0,
+ 16, 7, 0,113, 0, 82, 1, 59,255,255, 0, 16, 0, 0, 5,104, 5,213, 18, 34, 0, 36, 0, 0, 16, 6, 6,145, 0, 0, 0, 0,
+255,255, 0,123,255,227, 4, 45, 4,123, 18, 34, 0, 68, 0, 0, 16, 7, 6,145,255,147,254,193,255,255, 0, 8, 0, 0, 7, 72,
+ 7, 52, 16, 39, 0,113, 2,215, 1, 62, 18, 6, 0,136, 0, 0,255,255, 0,123,255,227, 7,111, 5,242, 16, 39, 0,113, 1,232,
+255,252, 18, 6, 0,168, 0, 0, 0, 1, 0,115,255,227, 6, 4, 5,240, 0, 37, 0, 0, 1, 21, 6, 4, 35, 32, 0, 17, 16, 0,
+ 33, 50, 4, 23, 21, 46, 1, 35, 32, 0, 17, 16, 0, 33, 50, 54, 55, 53, 35, 53, 51, 53, 33, 53, 33, 17, 51, 21, 5,139,117,254,
+230,160,254,162,254,117, 1,139, 1, 94,146, 1, 7,111,112,252,139,254,238,254,237, 1, 19, 1, 18,107,168, 67,253,253,254,182,
+ 2, 18,121, 1,138,255, 83, 85, 1,153, 1,109, 1,110, 1,153, 72, 70,215, 95, 96,254,206,254,209,254,210,254,206, 37, 39,181,
+ 88,132,166,254,214, 88, 0, 0, 0, 2, 0,113,254, 86, 4,250, 4,123, 0, 11, 0, 52, 0, 0, 1, 52, 38, 35, 34, 6, 21, 20,
+ 22, 51, 50, 54, 3, 54, 61, 1, 14, 1, 35, 34, 2, 17, 16, 18, 51, 50, 22, 23, 53, 51, 17, 20, 7, 51, 21, 35, 6, 7, 6, 33,
+ 34, 38, 39, 53, 30, 1, 51, 50, 55, 54, 55, 5, 53, 3,162,165,149,148,165,165,148,149,165, 22, 22, 57,178,124,206,252,252,206,
+124,178, 57,184, 19,179,198, 31, 58,127,254,250, 97,172, 81, 81,158, 82,181, 90, 21, 17,253,132, 2, 61,200,220,220,200,199,220,
+220,254, 79, 71, 94, 91, 99, 98, 1, 58, 1, 3, 1, 4, 1, 58, 98, 99,170,252, 43,110, 88, 70, 93, 64,140, 29, 30,179, 44, 42,
+ 95, 23, 28, 1, 70, 0, 0, 0,255,255, 0,115,255,227, 5,139, 5,240, 18, 34, 0, 42, 0, 0, 17, 7, 6,137, 5, 74, 1,117,
+ 0, 16,177, 33, 14, 16, 60, 64, 7,148, 33, 84, 33, 36, 33, 3, 93, 49, 0, 0,255,255, 0,113,254, 86, 4, 90, 6, 99, 16, 34,
+ 2, 32, 74,253, 18, 2, 0, 74, 0, 0, 0, 0,255,255, 0,201, 0, 0, 5,106, 5,213, 16, 39, 6,137, 4,162, 1,117, 18, 2,
+ 0, 46, 0, 0,255,255, 0,186, 0, 0, 4,156, 6, 20, 18, 34, 0, 78, 0, 0, 17, 7, 6,137, 3, 26, 1,117, 0, 42,180, 1,
+ 16, 12, 0, 7, 43, 49, 0, 75,176, 14, 81, 88,187, 0, 1,255,192, 0, 0,255,192, 56, 56, 89, 64, 13,144, 1,144, 0,128, 1,
+128, 0, 64, 1, 64, 0, 6, 93,255,255, 0,115,254,101, 5,217, 5,240, 16, 39, 2, 52, 1, 52,255,240, 18, 6, 0, 50, 0, 0,
+255,255, 0,113,254,101, 4,117, 4,123, 16, 39, 2, 52, 0,128,255,240, 18, 6, 0, 82, 0, 0,255,255, 0,115,254,101, 5,217,
+ 7, 49, 16, 39, 0,113, 1, 39, 1, 59, 18, 6, 1,172, 0, 0,255,255, 0,113,254,101, 4,117, 5,245, 16, 38, 0,113,115,255,
+ 18, 6, 1,173, 0, 0, 0, 0,255,255, 0,160,255,193, 4,248, 5,213, 16, 39, 6,137, 4,190, 1,117, 18, 2, 1,121, 0, 0,
+255,255, 0,220, 4,238, 3, 90, 6,102, 16, 38, 2, 32, 27, 0, 16, 6, 2, 8, 0, 0, 0, 0,255,255,255,219,254, 86, 2,100,
+ 6,102, 16, 39, 2, 32,255, 37, 0, 0, 17, 6, 1,249, 0, 0, 0, 11,180, 3, 32, 8, 7, 7, 16, 73, 99, 58, 49, 0, 0, 0,
+255,255, 0,201, 0, 0, 10,208, 5,213, 16, 39, 0, 61, 5,177, 0, 0, 16, 6, 0, 39, 0, 0,255,255, 0,201, 0, 0, 9,176,
+ 5,213, 16, 39, 0, 93, 5,213, 0, 0, 16, 6, 0, 39, 0, 0,255,255, 0,113,255,227, 8,145, 6, 20, 16, 39, 0, 93, 4,182,
+ 0, 0, 16, 6, 0, 71, 0, 0,255,255, 0,115,255,227, 5,139, 7,107, 18, 34, 0, 42, 0, 0, 16, 67, 0,118, 1, 22, 2,240,
+ 64, 0, 44,204,255,255, 0,113,254, 86, 4, 90, 6, 99, 18, 34, 0, 74, 0, 0, 16, 2, 0,118, 27,253, 0, 0, 0, 1, 0,201,
+255,227, 8, 45, 5,213, 0, 29, 0, 0, 1, 17, 20, 7, 6, 33, 32, 39, 38, 53, 17, 33, 17, 35, 17, 51, 17, 33, 17, 51, 17, 20,
+ 23, 22, 23, 50, 55, 54, 53, 17, 8, 45,100, 96,254,230,254,237,103,100,253, 34,202,202, 2,222,202, 62, 61,153,148, 66, 62, 4,
+ 96,253, 90,223,128,120,120,118,233, 1, 13,253, 57, 5,213,253,156, 2,100,251,236,159, 80, 78, 1, 79, 75,164, 2,159, 0, 0,
+ 0, 2, 0,201,254, 86, 5, 2, 5,240, 0, 14, 0, 23, 0, 0, 37, 17, 35, 17, 51, 21, 54, 55, 54, 51, 50, 23, 22, 21, 16, 1,
+ 0, 17, 52, 39, 38, 35, 34, 3, 1,147,202,202, 56,145, 87,226,198, 83, 84,252,145, 2,161, 61, 60,129,237,186,156,253,186, 7,
+127,185, 72, 87, 53,120,122,164,254, 55,254,206, 1,174, 1, 12,143, 71, 70,254,255, 0, 0, 0,255,255, 0,201, 0, 0, 5, 51,
+ 5,213, 16, 39, 6,135, 5, 30, 1,117, 18, 2, 0, 49, 0, 0,255,255, 0,186, 0, 0, 4,100, 6,100, 18, 34, 0, 81, 0, 0,
+ 16, 3, 0, 67, 1, 24,255,254,255,255, 0, 16, 0, 0, 5,104, 7,109, 16, 34, 0,135, 0, 0, 16, 7, 6,133, 6, 92, 1,125,
+255,255, 0,123,255,227, 4, 45, 7, 6, 16, 34, 0,167, 0, 0, 16, 7, 6,133, 5,236, 1,125,255,255, 0, 8, 0, 0, 7, 72,
+ 5,213, 16, 39, 6,133, 6, 92, 1,118, 18, 2, 0,136, 0, 0,255,255, 0,123,255,227, 7,111, 6, 99, 18, 34, 0,168, 0, 0,
+ 16, 3, 0,118, 1,101,255,253,255,255, 0,102,255,186, 5,229, 6, 23, 16, 39, 6,133, 4,254, 1,118, 18, 2, 0,154, 0, 0,
+255,255, 0, 72,255,162, 4,156, 6, 99, 18, 34, 0,186, 0, 0, 16, 2, 0,118, 28,253, 0, 0,255,255, 0, 16, 0, 0, 5,104,
+ 5,213, 18, 34, 0, 36, 0, 0, 16, 7, 6,142, 4,229, 1,122,255,255, 0,123,255,227, 4, 45, 6,100, 16, 35, 2, 87, 4,152,
+255,254, 18, 2, 0, 68, 0, 0,255,255, 0, 16, 0, 0, 5,104, 5,213, 18, 34, 0, 36, 0, 0, 16, 7, 6,138, 4,188, 1, 62,
+255,255, 0,123,255,227, 4, 45, 6, 72, 16, 35, 2, 89, 4,101, 0, 0, 18, 6, 0, 68, 0, 0,255,255, 0,201, 0, 0, 4,139,
+ 5,213, 18, 34, 0, 40, 0, 0, 16, 7, 6,142, 4,165, 1,122,255,255, 0,113,255,227, 4,127, 6, 99, 16, 35, 2, 87, 4,186,
+255,253, 18, 2, 0, 72, 0, 0,255,255, 0,201, 0, 0, 4,139, 5,213, 18, 34, 0, 40, 0, 0, 16, 7, 6,138, 4,166, 1, 62,
+255,255, 0,113,255,227, 4,127, 6, 72, 16, 35, 2, 89, 4,169, 0, 0, 18, 2, 0, 72, 0, 0,255,255, 0,201, 0, 0, 1,147,
+ 5,213, 18, 34, 0, 44, 0, 0, 16, 7, 6,142, 3, 89, 1,122,255,255,255,195, 0, 0, 2,129, 6, 99, 16, 35, 2, 87, 3,102,
+255,253, 18, 2, 0,243, 0, 0,255,255, 0,201, 0, 0, 1,147, 5,213, 18, 34, 0, 44, 0, 0, 16, 7, 6,138, 3, 62, 1, 62,
+255,255,255,227, 0, 0, 2, 86, 6, 72, 16, 35, 2, 89, 3, 36, 0, 0, 18, 2, 0,243, 0, 0,255,255, 0,115,255,227, 5,217,
+ 5,240, 18, 34, 0, 50, 0, 0, 16, 7, 6,142, 5, 65, 1,122,255,255, 0,113,255,227, 4,117, 6,100, 16, 35, 2, 87, 4,159,
+255,254, 18, 2, 0, 82, 0, 0,255,255, 0,115,255,227, 5,217, 5,240, 18, 34, 0, 50, 0, 0, 16, 7, 6,138, 5, 28, 1, 62,
+255,255, 0,113,255,227, 4,117, 6, 72, 16, 35, 2, 89, 4,152, 0, 0, 18, 2, 0, 82, 0, 0,255,255, 0,201, 0, 0, 5, 84,
+ 5,213, 18, 34, 0, 53, 0, 0, 16, 7, 6,142, 4,121, 1,122,255,255, 0,130, 0, 0, 3, 74, 6, 99, 16, 35, 2, 87, 4, 37,
+255,253, 18, 2, 0, 85, 0, 0,255,255, 0,201, 0, 0, 5, 84, 5,213, 18, 34, 0, 53, 0, 0, 16, 7, 6,138, 4,128, 1, 62,
+255,255, 0,186, 0, 0, 3, 94, 6, 72, 16, 35, 2, 89, 4, 45, 0, 0, 18, 2, 0, 85, 0, 0,255,255, 0,178,255,227, 5, 41,
+ 5,213, 18, 34, 0, 56, 0, 0, 16, 7, 6,142, 5, 21, 1,122,255,255, 0,174,255,227, 4, 88, 6,100, 16, 35, 2, 87, 4,212,
+255,254, 18, 2, 0, 88, 0, 0,255,255, 0,178,255,227, 5, 41, 5,213, 18, 34, 0, 56, 0, 0, 16, 7, 6,138, 4,236, 1, 62,
+255,255, 0,174,255,227, 4, 88, 6, 72, 16, 35, 2, 89, 4,171, 0, 0, 18, 2, 0, 88, 0, 0,255,255, 0,135,254, 20, 4,162,
+ 5,240, 16, 39, 2,110, 4,118, 0, 0, 18, 6, 0, 54, 0, 0,255,255, 0,111,254, 20, 3,199, 4,123, 16, 39, 2,110, 4, 44,
+ 0, 0, 18, 6, 0, 86, 0, 0,255,255,255,250,254, 20, 4,233, 5,213, 16, 39, 2,110, 4, 83, 0, 0, 18, 6, 0, 55, 0, 0,
+255,255, 0, 55,254, 20, 2,242, 5,158, 16, 39, 2,110, 4, 0, 0, 0, 18, 6, 0, 87, 0, 0, 0, 1, 0,156,254, 82, 4,115,
+ 5,240, 0, 49, 0, 0, 19, 54, 55, 54, 55, 54, 53, 52, 38, 35, 34, 15, 1, 53, 55, 54, 55, 54, 53, 52, 39, 38, 7, 34, 7, 6,
+ 7, 53, 54, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 7, 22, 23, 22, 21, 20, 7, 6, 5, 6, 7,156,199,194,165,126, 98,146, 91,
+ 63, 70,240,248,142,106, 79, 81, 95, 99,105,113, 89,120,119, 96,129,101,192,132,134, 71, 82,120,138, 81, 89,150,130,254,208,218,
+181,254,242, 64, 88, 75,121, 94,142,113,134, 31,106,171,106, 61,118, 88,144,123, 53, 63, 1, 58, 46, 80,190, 66, 42, 56,104,105,
+178,170, 99,113, 77, 19,109,119,113,218,142,123,129, 92, 40, 0, 0, 1, 0, 71,254, 79, 3,188, 4,123, 0, 50, 0, 0, 19, 54,
+ 55, 54, 55, 54, 53, 52, 39, 38, 35, 34, 15, 1, 53, 55, 54, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 7, 53, 54, 55, 54, 51, 50,
+ 23, 22, 21, 20, 7, 6, 7, 22, 23, 22, 21, 20, 7, 6, 5, 6, 7, 71,178,176,148,114, 88, 66, 65, 82, 57, 63,216,223,124, 99,
+ 71, 73, 78, 96, 92,104, 79,109, 96, 98,115, 91,171,121,120, 64, 73,108,124, 73, 80,135,120,254,241,196,163,254,209, 51, 72, 60,
+ 99, 76,115, 91, 55, 54, 25, 86,139, 85, 47, 99, 71,116, 96, 47, 50, 47, 35, 67,154, 48, 39, 46, 85, 85,144,137, 81, 91, 63, 15,
+ 88, 97, 91,177,115,102,102, 74, 33, 0, 0, 0,255,255, 0,201, 0, 0, 5, 59, 5,213, 16, 39, 6,137, 5, 4, 1,117, 18, 2,
+ 0, 43, 0, 0,255,255, 0,186, 0, 0, 4,100, 6, 20, 16, 39, 6,137, 3, 33, 1,117, 19, 2, 0, 75, 0, 0, 0, 42,180, 20,
+ 5, 1, 19, 7, 43, 49, 0, 75,176, 14, 81, 88,187, 0, 20,255,192, 0, 19,255,192, 56, 56, 89, 64, 13,144, 20,144, 19,128, 20,
+128, 19, 64, 20, 64, 19, 6, 93, 0, 1, 0,201,254, 86, 5, 25, 5,240, 0, 23, 0, 0, 1, 17, 35, 17, 52, 39, 38, 35, 34, 7,
+ 6, 21, 17, 35, 17, 51, 21, 54, 55, 54, 51, 50, 23, 22, 5, 25,201, 78, 76,153,179,109,106,202,202, 78,105,105,154,227,116,117,
+ 3,125,250,217, 5, 41,212,109,107,129,126,222,252,178, 5,213,241,135, 66, 67,159,159, 0, 0, 0, 3, 0,113,255,112, 6, 68,
+ 6, 20, 0, 7, 0, 40, 0, 52, 0, 0, 37, 22, 51, 50, 53, 52, 39, 34, 7, 54, 51, 50, 21, 16, 33, 34, 39, 6, 7, 35, 54, 55,
+ 38, 53, 6, 7, 6, 35, 34, 39, 38, 16, 55, 54, 51, 50, 23, 22, 23, 17, 51, 0, 16, 23, 22, 32, 55, 54, 16, 39, 38, 32, 7, 4,
+182, 17, 37,160, 52, 52,202,110,136,244,254,170, 73, 53, 34, 24,196, 29, 67, 48, 58, 88, 89,124,203,128,127,127,128,203,124, 89,
+ 88, 58,184,252,213, 83, 84, 1, 36, 84, 84, 84, 84,254,220, 84,130, 5,175, 45, 1, 32,184,206,254,191, 15, 72, 58, 69,147, 60,
+ 36,100, 48, 49,162,162, 2, 16,162,162, 49, 48,100, 2, 94,252,230,254,106,116,115,115,116, 1,150,116,115,115, 0, 2, 0,113,
+255,227, 5, 37, 5,240, 0, 12, 0, 59, 0, 0, 1, 34, 7, 6, 16, 23, 22, 32, 55, 54, 53, 52, 38, 3, 14, 1, 21, 20, 23, 22,
+ 51, 50, 55, 54, 53, 52, 39, 38, 39, 53, 50, 23, 22, 21, 20, 6, 7, 22, 23, 22, 21, 20, 7, 6, 32, 39, 38, 53, 52, 55, 54, 55,
+ 38, 39, 38, 53, 52, 55, 54, 33, 2,203,184,106,107,107,106, 1,112,107,107,212,244,130,170, 95, 59,204,168, 95, 96, 76,109,130,
+228,150,139,170,152,172, 95, 96,156,155,253,186,155,156, 96, 97,171,171, 67, 85,130,116, 1, 1, 2,197, 77, 77,254,242, 77, 77,
+ 77, 78,134,135,154, 2, 39, 3,124, 79, 69, 72, 45, 65, 65,136,158, 43, 77, 8,100,104, 97,186,128,178, 32, 34, 99, 99,143,217,
+116,116,116,116,217,143, 99, 99, 34, 31, 70, 89, 88,130, 83, 74, 0, 2, 0,113,255,227, 4,113, 5, 47, 0, 13, 0, 52, 0, 0,
+ 1, 34, 7, 6, 16, 23, 22, 32, 55, 54, 53, 52, 39, 38, 19, 22, 21, 20, 7, 6, 7, 22, 23, 22, 21, 20, 7, 6, 32, 39, 38, 53,
+ 52, 54, 55, 38, 39, 38, 53, 52, 55, 23, 6, 20, 23, 22, 51, 50, 55, 54, 53, 52, 39, 2,113,144, 83, 82, 82, 83, 1, 32, 83, 83,
+ 83, 82,254, 58, 52, 73,129,146, 82, 81,133,132,254, 18,132,133,164,146,142, 61, 52, 63,161, 43, 73, 72,131,130, 73, 74, 44, 2,
+197, 77, 77,254,242, 77, 77, 77, 78,134,135, 77, 77, 2,106, 82,112,153, 64, 89, 32, 34, 99, 99,143,217,116,116,116,116,217,143,
+198, 34, 35, 86, 75,142,106, 88, 32, 65,232, 65, 65, 65, 65,116,119, 62, 0, 0, 0, 1, 0, 92,254, 86, 5, 31, 5,213, 0, 21,
+ 0, 0, 5, 16, 7, 6, 43, 1, 53, 51, 50, 55, 54, 61, 1, 33, 53, 1, 33, 53, 33, 21, 1, 33, 5, 31,158, 72,114,254,233,105,
+ 38, 38,251,245, 3,176,252,103, 4,149,252, 80, 3,199, 20,254,223, 80, 37,156, 48, 49,153, 20,154, 4,145,170,154,251,111, 0,
+ 0, 1, 0, 88,254, 86, 3,219, 4, 96, 0, 21, 0, 0, 5, 16, 7, 6, 43, 1, 53, 51, 50, 55, 54, 61, 1, 33, 53, 1, 33, 53,
+ 33, 21, 1, 33, 3,219,158, 72,114,254,233,105, 38, 38,253, 53, 2,180,253,101, 3,106,253, 76, 2,180, 20,254,223, 80, 37,156,
+ 48, 49,153, 20,168, 3, 37,147,168,252,219, 0,255,255, 0, 16, 0, 0, 5,104, 7, 80, 18, 34, 0, 36, 0, 0, 16, 3, 2, 50,
+ 0,196, 1, 64,255,255, 0,123,255,227, 4, 45, 6, 18, 18, 34, 0, 68, 0, 0, 16, 2, 2, 50, 95, 2, 0, 0,255,255, 0,201,
+254,117, 4,139, 5,213, 18, 34, 0, 40, 0, 0, 16, 3, 0,122, 0,162, 0, 0,255,255, 0,113,254,117, 4,127, 4,123, 18, 34,
+ 0, 72, 0, 0, 16, 2, 0,122,123, 0, 0, 0,255,255, 0,115,255,227, 5,217, 5,240, 18, 34, 0, 50, 0, 0, 16, 6, 6,143,
+ 98, 0, 0, 0,255,255, 0,113,255,227, 4,117, 7, 49, 18, 38, 0,184, 0, 0, 16, 7, 0,113, 0,115, 1, 59,255,255, 0,115,
+255,227, 5,217, 5,240, 18, 34, 0, 50, 0, 0, 16, 6, 6,150,105, 0, 0, 0,255,255, 0,113,255,227, 4,117, 4,123, 16, 38,
+ 0, 82, 0, 0, 16, 7, 6,150,255,181,254,182,255,255, 0,115,255,227, 5,217, 5,240, 16, 39, 6,140, 5, 39, 1,116, 18, 6,
+ 0, 50, 0, 0,255,255, 0,113,255,227, 4,117, 6, 16, 16, 38, 2, 50,115, 0, 18, 6, 0, 82, 0, 0, 0, 0,255,255, 0,115,
+255,227, 5,217, 5,240, 18, 34, 0, 50, 0, 0, 16, 6, 6,145,106, 0, 0, 0,255,255, 0,113,255,227, 4,117, 7, 49, 18, 38,
+ 1,241, 0, 0, 16, 7, 0,113, 0,115, 1, 59,255,255,255,252, 0, 0, 4,231, 7, 49, 16, 39, 0,113, 0,114, 1, 59, 18, 6,
+ 0, 60, 0, 0,255,255, 0, 61,254, 86, 4,127, 5,245, 16, 38, 0,113, 94,255, 18, 6, 0, 92, 0, 0, 0, 0, 0, 2, 0,138,
+255,112, 3, 92, 6, 14, 0, 7, 0, 25, 0, 0, 37, 22, 51, 50, 53, 52, 39, 34, 7, 54, 51, 50, 21, 16, 33, 34, 39, 6, 7, 35,
+ 54, 55, 38, 55, 17, 51, 1,206, 17, 37,160, 52, 52,202,110,136,244,254,170, 73, 53, 34, 24,196, 29, 67, 49, 1,184,130, 5,175,
+ 45, 1, 32,184,206,254,191, 15, 72, 58, 69,147, 60, 90, 5, 48, 0, 2, 0,186,255,112, 6, 78, 4,123, 0, 7, 0, 43, 0, 0,
+ 37, 22, 51, 50, 53, 52, 39, 34, 7, 54, 51, 50, 21, 16, 33, 34, 39, 6, 7, 35, 54, 55, 38, 55, 17, 52, 38, 35, 34, 6, 21, 17,
+ 35, 17, 51, 21, 54, 55, 54, 51, 50, 23, 22, 21, 4,192, 17, 37,160, 52, 52,202,110,136,244,254,170, 73, 53, 34, 24,196, 29, 67,
+ 49, 1,124,124,149,172,185,185, 66, 89, 90,117,193, 99, 99,130, 5,175, 45, 1, 32,184,206,254,191, 15, 72, 58, 69,147, 60, 90,
+ 1,192,159,158,190,164,253,135, 4, 96,174,101, 50, 50,119,120,232, 0, 0, 0, 0, 2, 0, 55,255,112, 3, 97, 5,158, 0, 7,
+ 0, 33, 0, 0, 37, 22, 51, 50, 53, 52, 39, 34, 7, 54, 51, 50, 21, 16, 33, 34, 39, 6, 7, 35, 54, 55, 38, 53, 17, 35, 53, 51,
+ 17, 51, 17, 33, 21, 33, 1,211, 17, 37,160, 52, 52,202,110,136,244,254,170, 73, 54, 33, 24,196, 29, 67, 49,135,135,185, 1,123,
+254,133,130, 5,175, 45, 1, 32,184,206,254,191, 15, 72, 58, 69,147, 60, 90, 2,243,143, 1, 62,254,194,143, 0, 0, 1,255,219,
+254, 86, 1,121, 4, 96, 0, 11, 0, 56, 64, 21, 11, 2, 7, 0, 7,135, 5,189, 0,188, 12, 8, 12, 5, 6, 79, 1, 8, 0, 70,
+ 12, 16,252,236,228, 57, 18, 57, 49, 0, 16,228,244,236, 17, 18, 57, 57, 48, 64, 11, 16, 13, 64, 13, 80, 13, 96, 13,112, 13, 5,
+ 1, 93, 19, 51, 17, 20, 6, 43, 1, 53, 51, 50, 54, 53,193,184,163,181, 70, 49,105, 76, 4, 96,251,140,214,192,156, 97,153, 0,
+ 0, 3, 0,113,255,227, 7,140, 6, 20, 0, 7, 0, 37, 0, 45, 0, 0, 0, 16, 22, 32, 54, 16, 38, 32, 5, 62, 1, 51, 50, 0,
+ 16, 2, 35, 34, 38, 39, 21, 43, 1, 53, 14, 1, 35, 34, 2, 16, 0, 51, 50, 22, 23, 17, 59, 1, 0, 16, 38, 32, 6, 16, 22, 32,
+ 1, 47,167, 1, 36,168,168,254,220, 2,133, 58,177,123,204, 0,255,255,204,123,177, 58, 1,184, 58,177,124,203,255, 0,255,203,
+124,177, 58,184, 1, 2,114,167,254,220,167,167, 1, 36, 2,250,254,106,231,231, 1,150,231, 43,100, 97,254,188,253,240,254,188,
+ 97,100,168,168,100, 97, 1, 68, 2, 16, 1, 68, 97,100, 2, 94,251, 80, 1,150,231,231,254,106,231, 0, 0, 0, 0, 3, 0,113,
+254, 86, 7,140, 4,123, 0, 7, 0, 37, 0, 45, 0, 0, 0, 16, 38, 32, 6, 16, 22, 32, 37, 17, 43, 1, 17, 14, 1, 35, 34, 2,
+ 16, 0, 51, 50, 22, 23, 53, 59, 1, 21, 62, 1, 51, 50, 0, 16, 2, 35, 34, 38, 0, 16, 22, 32, 54, 16, 38, 32, 6,205,167,254,
+220,167,167, 1, 36,254, 53, 1,184, 58,177,124,203,255, 0,255,203,124,177, 58,184, 1, 58,177,123,204, 0,255,255,204,123,177,
+252,154,167, 1, 36,168,168,254,220, 1,100, 1,150,231,231,254,106,231, 43,253,174, 2, 82,100, 97, 1, 68, 2, 16, 1, 68, 97,
+100,170,170,100, 97,254,188,253,240,254,188, 97, 2,182,254,106,231,231, 1,150,231, 0, 0, 0, 0, 3,255,253,255,186, 5,124,
+ 6, 23, 0, 18, 0, 22, 0, 25, 0, 0, 1, 51, 19, 1, 23, 9, 1, 35, 3, 33, 15, 1, 35, 7, 39, 35, 55, 39, 55, 9, 1, 51,
+ 1, 3, 33, 3, 2, 74,229,134, 1, 97,102,254,112, 1,124,210,136,253,214,205, 50, 70, 59, 82, 2, 1, 20, 47, 2,144,254,238,
+ 22, 1,111,189, 1, 93,106, 5,213,254,161, 1,161, 89,254, 39,252, 27, 1,127,241,142, 70, 70, 1, 17, 56, 4,196,253, 25, 1,
+177,254, 79, 1, 31, 0, 0, 0, 0, 2, 0, 11,255,186, 5,139, 6, 23, 0, 31, 0, 40, 0, 0, 23, 39, 19, 38, 17, 16, 0, 33,
+ 50, 23, 22, 23, 55, 23, 7, 21, 38, 39, 1, 22, 23, 22, 33, 50, 54, 55, 21, 14, 1, 35, 32, 39, 19, 1, 35, 38, 35, 32, 0, 17,
+ 20,114,102,220,117, 1,134, 1, 83,134,118, 61, 58,101,102, 99, 46, 49,252,244, 9, 11,136, 1, 0,130,231,102,106,237,132,254,
+180,194, 57, 2,216, 1,116,130,255, 0,254,240, 70, 88, 1, 5,187, 1, 23, 1,104, 1,159, 36, 18, 27,120, 89,118,187, 43, 33,
+252,102, 13, 12,157, 94, 95,211, 72, 72,199, 1, 21, 3, 92, 47,254,199,254,216,173, 0, 0, 0, 0, 2, 0, 9,255,162, 4, 93,
+ 4,188, 0, 31, 0, 39, 0, 0, 23, 39, 55, 38, 53, 16, 0, 33, 50, 23, 22, 23, 55, 23, 7, 21, 38, 39, 1, 22, 23, 22, 51, 50,
+ 54, 55, 21, 14, 1, 35, 34, 39, 19, 1, 38, 35, 34, 6, 21, 20,105, 96,189, 85, 1, 45, 1, 6, 85, 81, 46, 45, 89, 95,118, 25,
+ 24,253,211, 7, 6, 99,179, 80,157, 78, 77,165, 93,240,147, 55, 1,238, 71, 71,179,198, 94, 78,230,141,204, 1, 18, 1, 58, 17,
+ 10, 16,108, 79,143, 85, 14, 11,253, 94, 8, 8,113, 43, 43,170, 36, 36,144, 1, 5, 2, 86, 17,227,205,103, 0, 0, 1, 0, 10,
+ 0, 0, 4,106, 5,213, 0, 13, 0, 0, 19, 51, 17, 51, 21, 35, 17, 33, 21, 33, 17, 35, 53, 51,201,202,191,191, 2,215,252, 95,
+191,191, 5,213,253,119,144,253,238,170, 2,188,144, 0, 0, 0, 0, 2,255,178,255,186, 5, 49, 6, 23, 0, 15, 0, 18, 0, 0,
+ 3, 39, 55, 23, 33, 21, 33, 17, 1, 7, 1, 17, 35, 17, 1, 35, 1, 17, 33, 6, 72,102, 56, 4,153,253,238, 2, 90,103,254, 13,
+203,254, 34, 52, 2, 18,254,212, 5,105, 85, 89, 66,170,253,174,253, 57, 88, 2, 77,253,249, 2,247, 2, 52,254,158, 1, 98, 0,
+ 0, 1, 0,111,254, 16, 4, 25, 4,123, 0, 55, 0, 0, 1, 52, 38, 47, 1, 46, 1, 53, 52, 54, 51, 50, 22, 23, 21, 46, 1, 35,
+ 34, 6, 21, 20, 22, 31, 1, 22, 23, 22, 21, 20, 7, 6, 7, 31, 1, 22, 51, 21, 35, 34, 39, 38, 47, 1, 38, 39, 38, 39, 38, 39,
+ 53, 30, 1, 51, 50, 54, 3, 10,101,171, 64,171,152,224,206,102,180, 76, 78,168, 90,137,137, 98,148, 63,198, 80, 83,123, 87,132,
+159,147, 42, 76, 39, 84,114, 71, 89,237, 30, 36, 16, 17, 97,108,102,198, 97,130,140, 1, 39, 75, 80, 37, 15, 36,149,130,158,172,
+ 30, 30,174, 40, 40, 84, 84, 64, 73, 33, 14, 44, 75, 76,137,156, 91, 64, 19,159,126, 36,154, 61, 38, 91,243, 30, 16, 3, 2, 18,
+ 35,190, 53, 53, 89, 0, 0, 0, 0, 1, 0, 88,254, 16, 4, 51, 4, 96, 0, 24, 0, 0, 19, 33, 21, 1, 22, 23, 1, 23, 22, 59,
+ 1, 21, 35, 34, 39, 38, 47, 1, 38, 43, 1, 61, 1, 1, 33,113, 3,106,253, 78, 92, 49, 1, 8,147, 42, 76,108,147, 84,114, 71,
+ 89,237, 61, 90, 94, 2,180,253,101, 4, 96,168,252,221, 16, 49,254,248,126, 36,154, 61, 38, 91,243, 63,156, 12, 3, 37, 0, 0,
+ 0, 1, 0, 80, 0, 0, 4,141, 5,213, 0, 25, 0, 0, 1, 51, 50, 54, 16, 38, 43, 1, 34, 7, 6, 7, 53, 54, 55, 54, 59, 1,
+ 50, 4, 16, 4, 43, 1, 17, 35, 1,160,241,141,154,153,142,254, 69, 90, 86, 78, 76, 81, 81, 85,254,251, 1, 1,254,255,251, 39,
+202, 3, 0,146, 1, 12,145, 22, 21, 43,182, 35, 17, 18,225,254, 72,226,253,166, 0, 1, 0,117, 2,156, 2,197, 6, 4, 0, 19,
+ 0, 48, 64, 7, 21, 0, 3, 14, 10, 11, 20, 16,212,220, 60, 47,204,204, 75,176, 13, 81, 88,177, 21, 64, 56, 89, 49,178,127, 21,
+ 1, 93, 0, 64, 6, 6, 17, 12, 2, 11, 20, 16,212, 60,196,212,204, 48, 1, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51,
+ 17, 62, 1, 51, 50, 22, 2,196,116, 78, 78, 94,108,117,117, 41,113, 74,121,125, 4, 23,254,133, 1,119, 89, 89,107, 92,254,158,
+ 3,103,254,171, 56, 56,134, 0, 0, 1, 0,117, 2,156, 2,197, 6, 4, 0, 27, 0, 59, 64, 8, 29, 0, 3, 16, 22, 10, 11, 28,
+ 16,212,220, 60,204, 47,204,204, 75,176, 13, 81, 88,177, 29, 64, 56, 89, 49,178,127, 29, 1, 93, 0, 64, 7, 6, 25, 17, 15, 2,
+ 11, 28, 16,212, 60,212,204,212,204,180, 13,131, 25,131, 6, 93, 48, 1, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 52, 54,
+ 59, 1, 21, 35, 34, 6, 29, 1, 62, 1, 51, 50, 22, 2,196,116, 78, 78, 94,108,117,103,114,160,146, 66, 48, 41,113, 74,121,125,
+ 4, 23,254,133, 1,119, 89, 89,107, 92,254,158, 2,132,120,107, 87, 54, 86,114, 56, 56,134, 0, 0, 2,255,233, 1,173, 0,238,
+ 6, 3, 0, 13, 0, 17, 0, 35, 64, 7, 19, 15, 1, 8, 14, 0, 18, 16,220, 60,204,220, 60,204, 49, 0, 64, 7, 14, 17, 0, 8,
+ 7, 0, 18, 16,212,212,204, 16,220,204, 48, 19, 51, 17, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 53, 17, 51, 21, 35,122,116, 52,
+ 51,114, 44, 31, 66, 24, 24,116,116, 5, 15,253,130,120, 54, 54, 88, 27, 27, 86, 3,114,130, 0, 0, 1, 0,117, 2,156, 2, 19,
+ 5, 31, 0, 17, 0, 31, 64, 5, 17, 11, 7, 8, 18, 16,220,204, 0,204, 49, 0, 64, 7, 0, 17, 7, 3, 14, 9, 8, 47,196,212,
+204, 16,212,204, 48, 1, 46, 1, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 22, 23, 2, 18, 19, 46, 28, 98,105,117,117,
+ 36,117, 84, 12, 29, 18, 4,175, 10, 9,113,107,254,182, 2,115, 97, 57, 55, 2, 3, 0, 0, 0, 0, 1, 0, 71, 2,141, 1,228,
+ 5, 15, 0, 21, 0, 0, 19, 22, 23, 22, 51, 50, 55, 54, 53, 17, 51, 17, 35, 53, 6, 7, 6, 35, 34, 39, 38, 39, 71, 20, 23, 23,
+ 27, 99, 52, 53,116,116, 37, 58, 59, 84, 12, 14, 15, 17, 2,252, 10, 5, 4, 57, 56,107, 1, 74,253,141, 97, 57, 27, 28, 1, 2,
+ 2, 0, 0, 0, 0, 1, 0, 71, 1,173, 2,117, 5, 15, 0, 32, 0, 0, 19, 22, 23, 22, 51, 50, 55, 54, 53, 17, 51, 17, 21, 20,
+ 22, 59, 1, 21, 35, 34, 38, 61, 1, 35, 53, 6, 7, 6, 35, 34, 39, 38, 39, 71, 20, 23, 23, 27, 99, 52, 53,116, 48, 66, 31, 44,
+114,102, 1, 37, 58, 60, 83, 12, 14, 15, 17, 2,252, 10, 5, 4, 57, 56,107, 1, 74,253,141, 11, 86, 54, 88,108,120, 11, 97, 57,
+ 27, 28, 1, 2, 2, 0, 0, 0, 0, 2, 0, 32, 2,156, 2,143, 5, 15, 0, 22, 0, 33, 0, 0, 1, 30, 1, 21, 20, 7, 6, 43,
+ 1, 17, 51, 17, 51, 50, 55, 54, 63, 1, 51, 7, 6, 7, 6, 1, 51, 50, 55, 54, 53, 52, 39, 38, 43, 1, 1,155, 67, 70, 67, 68,
+137,244,116,107, 61, 37, 37, 40,102,123,110, 33, 33, 34,254,215,125, 75, 39, 41, 41, 39, 75,125, 3,233, 15, 78, 59, 91, 45, 45,
+ 2,115,254,247, 21, 20, 63,161,171, 53, 30, 30,255, 0, 23, 24, 47, 46, 24, 25, 0, 1, 0, 54, 2,156, 3,233, 5, 15, 0, 12,
+ 0, 0, 19, 51, 27, 1, 51, 27, 1, 51, 3, 35, 11, 1, 35, 54,116,145,144,137,145,144,116,185,136,152,153,136, 5, 15,254, 23,
+ 1,233,254, 23, 1,233,253,141, 2, 2,253,254, 0, 1, 0, 38, 1,173, 2,213, 5, 15, 0, 17, 0, 0, 1, 6, 7, 6, 43, 1,
+ 53, 51, 50, 55, 54, 63, 1, 1, 51, 27, 1, 51, 1,159, 49, 47, 46, 78, 93, 68, 48, 26, 27, 32, 21,254,226,123,221,220,123, 2,
+ 98,112, 34, 35, 87, 20, 20, 75, 47, 2,105,254, 22, 1,234, 0,255,255, 0,197, 3,170, 1,111, 5,213, 18, 2, 0, 10, 0, 0,
+255,255, 0,197, 3,170, 2,233, 5,213, 18, 2, 0, 5, 0, 0,255,255, 0,174, 3,233, 1,211, 5,213, 16, 6, 5,141, 0, 0,
+255,255, 0,178, 3,254, 1,215, 5,213, 16, 6, 5,142, 0, 0, 0, 1, 0,196, 4,238, 1,233, 6,218, 0, 5, 0, 0, 1, 21,
+ 19, 35, 3, 53, 1,151, 82,129,164, 6,218,172,254,192, 1, 64,172, 0, 0, 0, 0, 1, 0,117, 3,239, 1,135, 6, 20, 0, 16,
+ 0, 0, 19, 52, 53, 50, 54, 53, 52, 38, 35, 52, 53, 50, 23, 22, 20, 7, 6,117, 64, 88, 88, 64,115, 80, 79, 79, 80, 3,239, 61,
+ 62, 88, 64, 63, 88, 61, 62, 80, 79,230, 80, 80, 0, 1, 0,117, 3,239, 1,135, 6, 20, 0, 16, 0, 0, 1, 34, 39, 38, 52, 55,
+ 54, 51, 20, 21, 34, 6, 21, 20, 22, 51, 20, 1,135,115, 80, 79, 79, 80,115, 64, 88, 88, 64, 3,239, 80, 80,230, 79, 80, 62, 61,
+ 88, 63, 64, 88, 62, 0, 0, 0, 0, 1, 0,117, 2,156, 2,137, 6, 2, 0, 28, 0, 0, 1, 51, 50, 55, 54, 53, 38, 39, 38, 35,
+ 34, 7, 6, 7, 53, 54, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 7, 17, 35, 1, 20, 39,121, 55, 36, 1, 35, 63,113, 50, 50, 49,
+ 49, 48, 51, 51, 53,174, 87, 68, 68, 70,107,128, 4, 91, 64, 42, 55, 75, 36, 64, 12, 12, 24, 96, 20, 9, 10, 88, 70,104, 95, 64,
+ 67, 17,254,147, 0, 1, 0,117, 2,156, 2,137, 6, 2, 0, 28, 0, 0, 1, 17, 35, 17, 38, 39, 38, 53, 52, 55, 54, 51, 50, 23,
+ 22, 23, 21, 38, 39, 38, 35, 34, 7, 6, 7, 20, 23, 22, 51, 1,234,127,107, 71, 68, 69, 87,173, 53, 51, 51, 48, 49, 50, 49, 50,
+113, 62, 36, 1, 37, 54,121, 4, 91,254, 65, 1,109, 17, 67, 64, 95,104, 70, 88, 10, 9, 20, 96, 24, 12, 12, 64, 36, 75, 55, 42,
+ 64, 0, 0, 0, 0, 1, 1, 11, 4, 50, 2,245, 6,176, 0, 6, 0, 0, 1, 37, 21, 13, 1, 21, 37, 1, 11, 1,234,254,153, 1,
+103,254, 22, 5,187,245,139,180,180,139,245, 0, 0, 1, 1, 11, 4, 50, 2,245, 6,176, 0, 6, 0, 0, 1, 5, 53, 45, 1, 53,
+ 5, 2,245,254, 22, 1,103,254,153, 1,234, 5, 39,245,139,180,180,139,245, 0, 0, 1, 0,193, 4,124, 3, 63, 6,102, 0, 6,
+ 0, 0, 1, 3, 51, 27, 1, 51, 3, 1,182,245,139,180,180,139,245, 4,124, 1,234,254,153, 1,103,254, 22, 0, 0, 1, 0,193,
+ 4,124, 3, 63, 6,102, 0, 6, 0, 0, 1, 51, 19, 35, 11, 1, 35, 1,182,148,245,139,180,180,139, 6,102,254, 22, 1,103,254,
+153, 0, 0, 0, 0, 1, 0,193, 4,238, 3, 63, 6,102, 0, 6, 0, 55, 64, 12, 4, 5, 2,180, 0,179, 7, 4, 2,117, 6, 7,
+ 16,220,236, 57, 49, 0, 16,244,236, 50, 57, 48, 0, 75,176, 9, 84, 75,176, 14, 84, 91, 88,189, 0, 7,255,192, 0, 1, 0, 7,
+ 0, 7, 0, 64, 56, 17, 55, 56, 89, 1, 51, 19, 35, 39, 7, 35, 1,182,148,245,139,180,180,139, 6,102,254,136,245,245, 0, 0,
+ 0, 1, 0,193, 4,238, 3, 63, 6,102, 0, 6, 0, 55, 64, 12, 3, 0,180, 4, 1,179, 7, 3, 5,117, 1, 7, 16,220,236, 57,
+ 49, 0, 16,244, 60,236, 57, 48, 0, 75,176, 9, 84, 75,176, 14, 84, 91, 88,189, 0, 7,255,192, 0, 1, 0, 7, 0, 7, 0, 64,
+ 56, 17, 55, 56, 89, 1, 3, 51, 23, 55, 51, 3, 1,182,245,139,180,180,139,245, 4,238, 1,120,245,245,254,136, 0, 1, 0,214,
+ 3,231, 1, 94, 6, 18, 0, 3, 0, 19, 64, 4, 5, 0, 3, 4, 16,220,220,204, 49, 0, 64, 2, 3, 2, 47,196, 48, 1, 17, 35,
+ 17, 1, 94,136, 6, 18,253,213, 2, 43, 0, 0,255,255, 0,213, 5, 98, 3, 43, 5,246, 16, 6, 0,113, 0, 0, 0, 1, 1,115,
+ 4,238, 3, 82, 6,102, 0, 3, 0, 0, 1, 51, 1, 35, 2,139,199,254,186,153, 6,102,254,136, 0, 1, 0,170, 4,240, 2,137,
+ 6,102, 0, 3, 0, 0, 9, 1, 35, 1, 1,111, 1, 26,153,254,186, 6,102,254,138, 1,118, 0, 0, 1, 0,214,254,209, 1, 94,
+ 0,252, 0, 3, 0, 19, 64, 4, 5, 0, 3, 4, 16,220,220,204, 49, 0, 64, 2, 3, 2, 47,196, 48, 37, 17, 35, 17, 1, 94,136,
+252,253,213, 2, 43, 0, 0, 0,255,255, 0,213,254,192, 3, 43,255, 84, 16, 7, 0,113, 0, 0,249, 94, 0, 0, 0, 1, 0,170,
+254, 28, 2,137,255,146, 0, 3, 0, 0, 5, 1, 35, 1, 1,111, 1, 26,153,254,186,110,254,138, 1,118, 0, 0, 0, 1, 1,115,
+254, 28, 3, 82,255,148, 0, 3, 0, 0, 5, 51, 1, 35, 2,139,199,254,186,153,108,254,136, 0, 0, 2, 0,111, 0, 0, 1,212,
+ 4, 35, 0, 2, 0, 5, 0, 0, 1, 3, 33, 3, 19, 33, 1, 33,178, 1,101,179,179,254,155, 2,217, 1, 74,253, 39,254,182, 0,
+ 0, 1, 0,111, 2,216, 1,212, 4, 35, 0, 2, 0, 0, 1, 3, 33, 1, 33,178, 1,101, 2,217, 1, 74, 0, 0,255,255, 0,117,
+ 1,254, 1,135, 4, 35, 16, 7, 2, 23, 0, 0,254, 15, 0, 0,255,255, 0,117, 1,254, 1,135, 4, 35, 16, 7, 2, 24, 0, 0,
+254, 15, 0, 0, 0, 1, 1, 31, 1,212, 2,225, 3,150, 0, 7, 0, 0, 1, 21, 33, 53, 51, 17, 51, 17, 2,225,254, 62,150,150,
+ 2,106,150,150, 1, 44,254,212, 0, 1, 1, 31, 1,212, 2,225, 3,150, 0, 7, 0, 0, 1, 53, 33, 21, 35, 17, 35, 17, 1, 31,
+ 1,194,150,150, 3, 0,150,150,254,212, 1, 44, 0, 1, 0,193, 1,137, 3, 23, 3,223, 0, 11, 0, 0, 1, 53, 51, 21, 51, 21,
+ 35, 21, 35, 53, 35, 53, 1,162,148,225,225,148,225, 2,254,225,225,148,225,225,148, 0, 0, 0, 0, 1, 1, 31, 2,106, 2,225,
+ 3, 0, 0, 3, 0, 0, 1, 33, 53, 33, 2,225,254, 62, 1,194, 2,106,150, 0, 0, 1, 0,199, 5, 41, 3, 57, 6, 72, 0, 13,
+ 0, 87, 64, 14, 11,240, 4, 7, 0,179, 14, 7, 86, 8, 1, 86, 0, 14, 16,220,236,212,236, 49, 0, 16,244, 60,212,236, 48, 0,
+ 75,176, 9, 84, 88,189, 0, 14,255,192, 0, 1, 0, 14, 0, 14, 0, 64, 56, 17, 55, 56, 89, 0, 75,176, 15, 84, 75,176, 16, 84,
+ 91, 75,176, 17, 84, 91, 88,189, 0, 14, 0, 64, 0, 1, 0, 14, 0, 14,255,192, 56, 17, 55, 56, 89, 19, 51, 30, 1, 51, 50, 54,
+ 55, 51, 14, 1, 35, 34, 38,199,118, 11, 97, 87, 86, 96, 13,118, 10,158,145,145,158, 6, 72, 75, 75, 74, 76,143,144,144, 0, 0,
+ 0, 1, 1,154, 5, 68, 2,102, 6, 16, 0, 3, 0, 21, 64, 9, 2,131, 0,205, 4, 1, 25, 0, 4, 16,212,236, 49, 0, 16,252,
+236, 48, 0, 1, 51, 21, 35, 1,154,204,204, 6, 16,204, 0, 0, 0, 2, 0,238, 4,225, 3, 18, 7, 6, 0, 11, 0, 23, 0, 32,
+ 64, 17, 3,193, 21,242, 9,193, 15,241, 24, 0, 86, 12,120, 6, 86, 18, 24, 16,212,236,244,236, 49, 0, 16,244,236,244,236, 48,
+ 1, 52, 38, 35, 34, 6, 21, 20, 22, 51, 50, 54, 55, 20, 6, 35, 34, 38, 53, 52, 54, 51, 50, 22, 2,152, 88, 64, 65, 87, 87, 65,
+ 64, 88,122,159,115,115,159,159,115,115,159, 5,244, 63, 88, 87, 64, 65, 87, 88, 64,115,160,160,115,115,159,159, 0, 1, 1, 76,
+254,117, 2,193, 0, 0, 0, 19, 0, 32, 64, 15, 11, 14, 10, 7,243, 14,244, 0, 1, 0, 10, 4, 39, 17, 20, 16,212,236,196,212,
+204, 49, 0, 47,252,252,196, 18, 57, 48, 33, 51, 14, 1, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 53, 52, 54, 1,184,
+119, 45, 43, 55, 54, 32, 62, 31, 38, 68, 30,122,115, 53, 61, 88, 31, 46, 46, 15, 15,133, 10, 10, 87, 93, 48,105, 0, 1, 0,182,
+ 5, 29, 3, 74, 6, 55, 0, 27, 0, 99, 64, 36, 0, 18, 7, 14, 11, 4, 1, 18, 7, 15, 11, 4, 18,195, 25, 7, 4,195, 21, 11,
+237, 28, 15, 1, 14, 0, 7, 21, 86, 22,119, 7, 86, 8,118, 28, 16,244,236,252,236, 17, 57, 57, 57, 57, 49, 0, 16,252, 60,252,
+212, 60,236, 17, 18, 57, 17, 18, 57, 17, 18, 57, 17, 18, 57, 48, 0, 75,176, 9, 84, 75,176, 12, 84, 91, 88,189, 0, 28,255,192,
+ 0, 1, 0, 28, 0, 28, 0, 64, 56, 17, 55, 56, 89, 1, 39, 46, 1, 35, 34, 6, 7, 35, 62, 1, 51, 50, 22, 31, 1, 30, 1, 51,
+ 50, 54, 55, 51, 14, 1, 35, 34, 38, 1,252, 57, 22, 33, 13, 38, 36, 2,125, 2,102, 91, 38, 64, 37, 57, 22, 33, 13, 38, 36, 2,
+125, 2,102, 91, 38, 64, 5, 90, 55, 20, 19, 73, 82,135,147, 28, 33, 55, 20, 19, 73, 82,135,147, 28, 0, 0, 0, 0, 2, 0,240,
+ 4,238, 3,174, 6,102, 0, 3, 0, 7, 0, 66, 64, 17, 6, 2,180, 4, 0,179, 8, 4, 7, 3, 0, 5, 1, 3, 5, 7, 8, 16,
+212,220,212,204, 17, 57, 17, 18, 57, 49, 0, 16,244, 60,236, 50, 48, 0, 75,176, 9, 84, 75,176, 14, 84, 91, 88,189, 0, 8,255,
+192, 0, 1, 0, 8, 0, 8, 0, 64, 56, 17, 55, 56, 89, 1, 51, 3, 35, 3, 51, 3, 35, 2,252,178,248,135,129,170,223,137, 6,
+102,254,136, 1,120,254,136, 0, 0, 1,255,255, 1,222, 2,173, 4, 8, 0, 15, 0, 0, 3, 37, 51, 21, 20, 23, 22, 59, 1, 21,
+ 35, 34, 39, 38, 53, 5, 1, 1, 22,184, 38, 38,105, 43, 64,175, 87, 82,254,235, 3,100,164,148,153, 49, 48,156, 96, 90,200,162,
+ 0, 1, 0,239, 4,238, 3, 16, 6,102, 0, 11, 0, 0, 1, 39, 7, 35, 55, 39, 51, 23, 55, 51, 7, 23, 2, 92, 92, 93,180,181,
+181,180, 93, 92,180,182,182, 4,238, 97, 97,187,189, 96, 96,189,187, 0, 0, 0, 0, 2, 0,117, 1,170, 2,253, 5, 15, 0, 13,
+ 0, 21, 0, 0, 1, 22, 21, 20, 7, 4, 39, 38, 55, 3, 51, 23, 55, 51, 1, 6, 23, 22, 51, 50, 55, 52, 2, 5,178,242,254,246,
+ 1, 1,182,250,137,191,183,137,254,188,140, 3, 2,134,128, 1, 3,220,249,180,129, 3, 3,135,192,241, 1, 47,224,224,254,138,
+174,152, 77, 77,140, 0, 0, 0, 0, 1, 0,121, 2,156, 0,238, 6, 4, 0, 3, 0, 13,177, 2, 3, 47,204, 49, 0,177, 0, 3,
+ 47,196, 48, 19, 51, 17, 35,122,116,116, 6, 3,252,153, 0, 0, 0, 1, 0,117, 2,156, 2,144, 5, 47, 0, 50, 0, 0, 1, 21,
+ 38, 39, 38, 35, 34, 7, 6, 21, 20, 23, 22, 31, 1, 22, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 39, 53, 22, 23, 22, 51, 50, 54,
+ 53, 52, 39, 38, 47, 1, 38, 39, 38, 53, 52, 55, 54, 51, 50, 23, 22, 2,106, 49, 53, 52, 57, 87, 43, 43, 31, 31, 93, 40,125, 50,
+ 52, 78, 77,136, 57, 62, 61, 68, 64, 63, 62, 61, 82, 88, 32, 28,111, 40,108, 48, 48, 71, 70,130, 64, 57, 57, 5, 13, 97, 22, 11,
+ 11, 23, 24, 47, 36, 20, 21, 18, 8, 24, 42, 43, 77, 87, 51, 51, 10, 10, 19,107, 30, 15, 15, 50, 45, 42, 23, 20, 23, 8, 21, 41,
+ 42, 73, 88, 48, 49, 9, 8, 0, 0, 1, 0,117, 2,156, 3, 33, 5, 15, 0, 11, 0, 0, 1, 3, 1, 35, 39, 7, 35, 1, 3, 51,
+ 23, 55, 3, 20,255, 1, 12,137,205,205,137, 1, 18,251,137,187,187, 5, 15,254,207,254,190,246,246, 1, 72, 1, 43,223,223, 0,
+ 0, 1, 0,117, 2,156, 2,137, 6, 2, 0, 28, 0, 0, 1, 17, 35, 17, 38, 39, 38, 53, 52, 55, 54, 51, 50, 23, 22, 23, 21, 38,
+ 39, 38, 35, 34, 7, 6, 7, 20, 23, 22, 51, 1,234,127,107, 71, 68, 69, 87,173, 53, 51, 51, 48, 49, 50, 49, 50,113, 62, 36, 1,
+ 37, 54,121, 4, 91,254, 65, 1,109, 17, 67, 64, 95,104, 70, 88, 10, 9, 20, 96, 24, 12, 12, 64, 36, 75, 55, 42, 64, 0, 0, 0,
+ 0, 1, 0,214, 0, 0, 3, 29, 5, 88, 0, 5, 0, 21, 64, 9, 1,169, 3, 0, 0, 8, 4, 2, 6, 16,196,212,236, 49, 0, 47,
+212,236, 48, 33, 17, 33, 53, 33, 17, 2,149,254, 65, 2, 71, 4,208,136,250,168, 0, 1, 0,214, 0, 0, 3, 29, 5, 88, 0, 7,
+ 0, 39, 64, 24, 63, 4, 63, 1, 47, 4, 47, 1, 31, 4, 31, 1, 6, 1,169, 4, 5, 0, 0, 4, 8, 6, 2, 8, 16,196,212,236,
+ 50, 49, 0, 47,212,220,236, 93, 48, 33, 17, 33, 53, 33, 17, 51, 17, 2,149,254, 65, 1,191,136, 3,156,136, 1, 52,250,168, 0,
+ 0, 1, 0,214, 0, 0, 3, 29, 5, 88, 0, 7, 0, 25, 64, 11, 1,169, 4, 5, 0, 0, 4, 8, 6, 2, 8, 16,196,212,236, 50,
+ 49, 0, 47,212,220,236, 48, 33, 17, 33, 53, 33, 17, 51, 17, 2,149,254, 65, 1,191,136, 2,104,136, 2,104,250,168, 0, 0, 0,
+ 0, 1, 0,214, 0, 0, 3, 29, 5, 88, 0, 7, 0, 39, 64, 24,112, 4,112, 1, 48, 4, 48, 1, 16, 4, 16, 1, 6, 4,169, 1,
+ 5, 0, 0, 4, 8, 6, 2, 8, 16,196,212,236, 50, 49, 0, 47,212,220,236, 93, 48, 33, 17, 33, 53, 33, 17, 51, 17, 2,149,254,
+ 65, 1,191,136, 1, 52,136, 3,156,250,168, 0, 0, 1, 0,214, 0, 0, 3, 29, 5, 88, 0, 5, 0, 21, 64, 9, 1, 0,169, 4,
+ 0, 8, 2, 4, 6, 16,196,212,236, 49, 0, 47,236,196, 48, 37, 17, 51, 17, 33, 53, 2,149,136,253,185,136, 4,208,250,168,136,
+255,255, 0,193,253,236, 3, 63,255,214, 16, 3, 2, 29, 0, 0,249,112, 0, 0,255,255, 0,213, 4,226, 3, 43, 6,118, 18, 35,
+ 0,113, 0, 0, 0,128, 18, 2, 0,113, 0,128, 0, 2, 1, 21, 4,238, 2,235, 6,102, 0, 3, 0, 7, 0, 0, 1, 51, 17, 35,
+ 1, 51, 17, 35, 1, 21,150,150, 1, 64,150,150, 6,102,254,136, 1,120,254,136,255,255, 0,238,253, 46, 3, 18,255, 83, 16, 7,
+ 2, 51, 0, 0,248, 77, 0, 0, 0, 1, 0,182,254,118, 3, 74,255,144, 0, 27, 0, 0, 1, 39, 46, 1, 35, 34, 6, 7, 35, 62,
+ 1, 51, 50, 22, 31, 1, 30, 1, 51, 50, 54, 55, 51, 14, 1, 35, 34, 38, 1,252, 57, 22, 33, 13, 38, 36, 2,125, 2,102, 91, 38,
+ 64, 37, 57, 22, 33, 13, 38, 36, 2,125, 2,102, 91, 38, 64,254,179, 55, 20, 19, 73, 82,135,147, 28, 33, 55, 20, 19, 73, 82,135,
+147, 28, 0, 0,255,255,252,168, 4,240,254,135, 6,102, 16, 7, 0, 67,251,254, 0, 0, 0, 0,255,255,253,113, 4,238,255, 80,
+ 6,102, 16, 7, 0,118,251,254, 0, 0, 0, 0,255,255,252,191, 4,238,255, 61, 6,102, 16, 7, 2, 31,251,254, 0, 0, 0, 0,
+255,255,252,180, 5, 29,255, 72, 6, 55, 16, 7, 2, 53,251,254, 0, 0, 0, 0,255,255,252,217, 5, 98,255, 47, 5,246, 16, 7,
+ 0,113,252, 4, 0, 0, 0, 0,255,255,251,236, 5,124, 0, 20, 6, 11, 16, 7, 5,171,252, 0, 0, 0, 0, 0,255,255,252,191,
+ 5, 41,255, 49, 6, 72, 16, 7, 2, 49,251,248, 0, 0, 0, 0,255,255,253,164, 5, 68,254,112, 6, 16, 16, 7, 2, 50,252, 10,
+ 0, 0, 0, 0,255,255,252,213, 5, 70,255, 39, 6, 16, 16, 7, 0,106,251,254, 0, 0, 0, 0, 0, 1,253, 55, 4,242,254,247,
+ 6,123, 0, 25, 0, 34, 64, 9, 20, 86, 64, 5,128, 12, 86, 25, 13, 47,204,236, 26,220, 26,236, 49, 0, 64, 6, 23,193, 64, 2,
+192, 13, 47, 26,220, 26,236, 48, 1, 54, 51, 50, 22, 21, 20, 15, 1, 6, 7, 6, 21, 35, 53, 52, 54, 63, 1, 54, 53, 52, 38, 35,
+ 34, 7,253, 55,112,105,104,127, 88, 44, 35, 4, 7,119, 30, 51, 45, 46, 62, 71, 90,100, 6, 72, 51, 85, 67, 61, 65, 32, 26, 9,
+ 16, 32, 12, 40, 54, 37, 34, 34, 40, 21, 36, 52,255,255,252,236, 4,225,255, 16, 7, 6, 16, 7, 2, 51,251,254, 0, 0, 0, 0,
+255,255,252,244, 4,238,255,178, 6,102, 16, 7, 2, 54,252, 4, 0, 0, 0, 0,255,255,252,197, 4,238,255, 67, 6,102, 16, 7,
+ 2, 32,252, 4, 0, 0, 0, 0, 0, 1,253,188, 4,236,254, 68, 6,168, 0, 3, 0, 0, 1, 17, 35, 17,254, 68,136, 6,168,254,
+ 68, 1,188, 0,255,255,252,240, 4,236,255, 16, 6,168, 16, 39, 2, 85,255, 52, 0, 0, 16, 7, 2, 85, 0,204, 0, 0, 0, 0,
+ 0, 2,252, 93, 4,238,255, 27, 6,102, 0, 3, 0, 7, 0, 0, 1, 19, 35, 3, 33, 19, 35, 3,253, 15,205,135,248, 2, 0,190,
+137,223, 6,102,254,136, 1,120,254,136, 1,120,255,255,252,191, 5, 41,255, 49, 6,214, 16, 39, 2, 50,252, 4, 0,198, 16, 7,
+ 2, 49,251,248, 0, 0, 0, 0,255,255,252,191, 5, 41,255, 49, 6, 72, 16, 15, 2, 49,255,248, 11,113,192, 0, 0, 1,254, 31,
+ 3,233,255, 68, 5, 40, 0, 3, 0, 10, 64, 3, 2, 1, 4, 0, 16,212,204, 48, 1, 35, 19, 51,254,242,211,164,129, 3,233, 1,
+ 63, 0, 0, 0, 0, 1,253,144, 4,194,254,130, 6,193, 0, 8, 0, 0, 1, 16, 35, 53, 22, 53, 35, 53, 51,254,130,242,112,112,
+242, 5,195,254,255,123, 3,137,254, 0, 0, 0, 0, 1,253,144, 4,194,254,130, 6,193, 0, 8, 0, 0, 1, 53, 51, 21, 35, 20,
+ 55, 21, 34,253,144,241,111,112,242, 5,195,254,254,137, 3,123, 0, 1,255,121, 4,154, 0,135, 6, 18, 0, 3, 0, 0, 3, 51,
+ 3, 35, 64,199,117,153, 6, 18,254,136, 0, 0,255,255,252,168,253,223,254,135,255, 85, 16, 7, 0, 67,251,254,248,239, 0, 0,
+255,255,253,113,253,221,255, 80,255, 85, 16, 7, 0,118,251,254,248,239, 0, 0, 0, 1,253, 12,253, 38,254, 68,255, 16, 0, 7,
+ 0, 0, 1, 53, 51, 17, 35, 53, 35, 53,253,188,136,136,176,254, 95,177,254, 22,177,136, 0, 0, 0, 1,253,188,253, 38,254,244,
+255, 16, 0, 7, 0, 0, 1, 51, 21, 35, 21, 35, 17, 51,254, 68,176,176,136,136,254, 95,136,177, 1,234, 0, 0, 0, 1,254, 85,
+ 5,134, 0, 63, 7,112, 0, 5, 0, 0, 3, 33, 53, 33, 17, 35, 73,254,158, 1,234,136, 6,232,136,254, 22, 0, 0, 1,254,240,
+ 3,107, 0,123, 4,224, 0, 19, 0, 49, 64, 6, 7, 86, 14, 4, 17, 0, 47, 75,176, 12, 84, 75,176, 13, 84, 91, 75,176, 14, 84,
+ 91, 88,185, 0, 0, 0, 64, 56, 89,220, 50,220,236, 49, 0, 64, 5, 10, 4,193, 0, 17, 47,196,252,204, 48, 1, 53, 30, 1, 51,
+ 50, 54, 53, 52, 38, 39, 51, 30, 1, 21, 20, 6, 35, 34, 38,254,240, 61, 88, 31, 46, 46, 15, 15,133, 10, 10, 87, 93, 48,105, 3,
+215,119, 45, 43, 55, 54, 32, 62, 31, 38, 68, 30,122,115, 53, 0, 0, 1,253,129,252,235,254,147,255, 16, 0, 16, 0, 0, 5, 20,
+ 21, 34, 6, 21, 20, 22, 51, 20, 21, 34, 39, 38, 52, 55, 54,254,147, 64, 88, 88, 64,115, 80, 79, 79, 80,240, 62, 61, 88, 64, 63,
+ 88, 62, 61, 79, 80,230, 80, 80, 0, 1,253, 11,253,215,254,245,255, 16, 0, 7, 0, 0, 1, 51, 21, 33, 53, 51, 53, 51,254, 68,
+177,254, 22,177,136,254, 95,136,136,177, 0, 0, 0, 1,253, 11,253,215,254,245,255, 16, 0, 7, 0, 0, 1, 35, 53, 33, 21, 35,
+ 21, 35,253,188,177, 1,234,177,136,254,136,136,136,177, 0, 0, 0, 1,253, 11,253, 38,254,245,255, 16, 0, 11, 0, 0, 1, 35,
+ 53, 51, 53, 51, 21, 51, 21, 35, 21, 35,253,188,177,177,136,177,177,136,253,215,136,177,177,136,177, 0, 0, 0, 0, 1,253, 11,
+254,136,254,245,255, 16, 0, 3, 0, 0, 1, 53, 33, 21,253, 11, 1,234,254,136,136,136, 0, 0, 0, 1,253,122,254, 86,255,208,
+ 0,128, 0, 13, 0, 0, 39, 21, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 61, 1, 48, 82, 81,181,254,233,105, 38, 38,128,148,214,
+ 96, 96,156, 48, 49,153,148, 0, 0, 1,253,119,254, 86,255,205, 0,128, 0, 13, 0, 0, 37, 51, 21, 20, 23, 22, 59, 1, 21, 35,
+ 34, 39, 38, 53,253,119,184, 38, 38,105,233,254,181, 81, 82,128,148,153, 49, 48,156, 96, 96,214,255,255,253,154,254,135,254,102,
+255, 83, 16, 7, 2, 50,252, 0,249, 67, 0, 0,255,255,252,213,254,137,255, 39,255, 83, 16, 7, 0,106,251,254,249, 67, 0, 0,
+255,255,252,236,253, 46,255, 16,255, 83, 16, 7, 2, 51,251,254,248, 77, 0, 0, 0, 1,253,106,254, 20,254,143,255, 84, 0, 3,
+ 0, 10, 64, 3, 3, 0, 4, 0, 16,212,204, 48, 5, 51, 3, 35,253,188,211,164,129,172,254,192,255,255,253, 35,254,117,254,193,
+ 0, 0, 16, 7, 0,122,252, 0, 0, 0, 0, 0,255,255,253, 76,254,117,254,193, 0, 0, 16, 7, 2, 52,252, 0, 0, 0, 0, 0,
+ 0, 1,253,188,253,152,254, 68,255, 84, 0, 3, 0, 0, 5, 17, 35, 17,254, 68,136,172,254, 68, 1,188, 0, 0, 0, 1,252,240,
+254, 10,255, 23,255, 84, 0, 7, 0, 0, 7, 17, 35, 53, 33, 21, 35, 17,233,137,254,235,137,172,254,182,194,194, 1, 74, 0, 0,
+ 0, 1,252, 99,254, 57,255,152,255, 88, 0, 20, 0, 0, 1, 6, 35, 34, 3, 52, 53, 51, 22, 51, 50, 55, 51, 22, 23, 50, 55, 51,
+ 2, 7, 34,253,254, 60,116,218, 17,117, 14,104,101, 15,118, 12,105,102, 15,118, 15,220,116,254,139, 82, 1, 26, 2, 3,150,150,
+149, 1,150,254,226, 1, 0, 0,255,255,252,197,253,218,255, 67,255, 82, 16, 7, 2, 32,252, 4,248,236, 0, 0,255,255,252,191,
+253,221,255, 61,255, 85, 16, 7, 2, 31,251,254,248,239, 0, 0,255,255,252,191,254, 57,255, 49,255, 88, 16, 7, 2, 49,251,248,
+249, 16, 0, 0,255,255,252,191,254, 54,255, 49,255, 85, 16, 15, 2, 49,255,248, 4,126,192, 0,255,255,252,180,254, 57,255, 72,
+255, 83, 16, 7, 2, 53,251,254,249, 28, 0, 0,255,255,252,217,254,192,255, 47,255, 84, 16, 7, 2, 38,252, 4, 0, 0, 0, 0,
+255,255,251,236,254, 29, 0, 20,254,172, 16, 7, 0, 66,252, 0, 0, 0, 0, 0,255,255,251,236,254, 29, 0, 20,255,238, 16, 7,
+ 5,140,252, 0, 0, 0, 0, 0, 0, 1,251,140, 1,236,255,173, 3, 12, 0, 27, 0, 0, 3, 21, 14, 1, 35, 34, 39, 38, 39, 46,
+ 1, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 23, 22, 23, 22, 51, 50, 54, 83, 75,143, 79, 90,113, 22, 11, 77,103, 51, 79,141, 73,
+ 78,146, 83, 53,100, 74, 12, 21,116, 93, 70,137, 3, 12,174, 59, 55, 51, 10, 4, 33, 24, 59, 63,174, 60, 54, 22, 31, 5, 10, 55,
+ 61, 0, 0, 0, 0, 1,253,119, 1,196,255,136, 2,104, 0, 3, 0, 0, 3, 21, 33, 53,120,253,240, 2,104,164,164, 0, 0, 0,
+ 0, 1,250,237, 1,196,255,255, 2,104, 0, 3, 0, 0, 1, 53, 33, 21,250,237, 5, 18, 1,196,164,164, 0, 0, 0, 1,251,104,
+255,162,255,188, 4,188, 0, 3, 0, 0, 5, 39, 1, 23,251,200, 96, 3,245, 95, 94, 78, 4,204, 79, 0, 0, 0, 0, 1,250, 18,
+255,186,255,145, 6, 23, 0, 3, 0, 0, 5, 39, 1, 23,250,121,103, 5, 25,102, 70, 88, 6, 5, 89, 0, 0, 0,255,255,253,249,
+253, 59,255, 11,255, 96, 16, 15, 2,100,252,140,252, 75,192, 0,255,255,252,241,254, 91,255, 24,255,165, 16, 15, 2,114,252, 8,
+253,175,192, 0, 0, 2,252,240,253, 46,255, 23,255, 84, 0, 3, 0, 7, 0, 0, 7, 17, 33, 17, 1, 17, 33, 17,233,253,217, 1,
+158,254,235,172,253,218, 2, 38,254, 98, 1, 22,254,234, 0, 0, 0, 1,252, 99,254, 57,255,152,255, 88, 0, 20, 0, 0, 5, 54,
+ 51, 50, 19, 20, 21, 35, 38, 35, 34, 7, 35, 38, 39, 34, 7, 35, 18, 55, 50,253,254, 59,116,218, 17,118, 13,103,102, 16,118, 11,
+105,102, 15,118, 15,220,116,250, 82,254,230, 2, 3,150,150,149, 1,150, 1, 30, 1, 0, 0, 0, 0, 1,253, 42, 4,242,254,230,
+ 6,174, 0, 11, 0, 0, 1, 7, 39, 55, 39, 55, 23, 55, 23, 7, 23, 7,254, 8,125, 96,125,125, 96,125,125, 96,125,125, 96, 5,
+112,125, 96,125,125, 96,125,125, 96,125,125, 96, 0, 1,254, 6, 4,194,255, 32, 6,210, 0, 29, 0, 0, 1, 46, 1, 53, 52, 54,
+ 55, 21, 14, 1, 21, 20, 23, 22, 31, 1, 30, 1, 21, 20, 6, 7, 53, 62, 1, 53, 52, 39, 38, 39,254, 67, 33, 28,147,135, 82, 73,
+ 9, 12, 18, 55, 33, 28,147,135, 82, 73, 9, 12, 18, 5,199, 28, 48, 28, 80, 81, 2,110, 2, 27, 28, 10, 12, 15, 14, 43, 28, 48,
+ 28, 80, 81, 2,110, 2, 27, 28, 10, 12, 15, 14,255,255,251,236, 4, 58, 0, 20, 6, 11, 16, 39, 5,171,252, 0, 0, 0, 16, 7,
+ 5,171,252, 0,254,190, 0, 0,255,255,252,168, 4,240,254,135, 6,102, 16, 7, 0, 67,251,254, 0, 0, 0, 0,255,255,253,113,
+ 4,238,255, 80, 6,102, 16, 7, 0,118,251,254, 0, 0, 0, 0,255,255,252,180, 5, 29,255, 72, 6, 55, 16, 7, 2, 53,251,254,
+ 0, 0, 0, 0,255,255,253,132, 4,194,254,118, 6, 97, 16, 7, 5,114,251,254, 0, 0, 0, 0,255,255,252,231, 5, 70,255, 98,
+ 7,210, 16, 7, 2,166,252, 16, 0, 0, 0, 0,255,255,253,198,254, 86,254,162,255,164, 16, 7, 2,163,252, 16, 0, 0, 0, 0,
+ 0, 1,252,213, 5, 29,255, 43, 6, 73, 0, 7, 0, 0, 3, 35, 53, 33, 21, 35, 17, 33,213,150,254,214,150, 2, 86, 5, 29,150,
+150, 1, 44, 0, 0, 2,253, 31,254, 50,254,225,255,184, 0, 3, 0, 7, 0, 0, 1, 33, 53, 33, 53, 33, 53, 33,254,225,254, 62,
+ 1,194,254, 62, 1,194,254, 50,120,150,120, 0, 0, 2,253, 21,254, 20,254,235,255,140, 0, 3, 0, 7, 0, 0, 5, 51, 17, 35,
+ 1, 51, 17, 35,253, 21,150,150, 1, 64,150,150,116,254,136, 1,120,254,136, 0, 0, 1,253, 31,254, 20,254,225,255,214, 0, 5,
+ 0, 0, 5, 33, 17, 35, 17, 33,253, 31, 1,194,150,254,212, 42,254, 62, 1, 44, 0, 1,252,182, 4,238,255, 74, 6,102, 0, 39,
+ 0, 0, 1, 55, 51, 7, 22, 23, 22, 51, 50, 55, 54, 55, 51, 6, 7, 6, 35, 34, 39, 38, 39, 7, 35, 55, 38, 39, 38, 35, 34, 7,
+ 6, 7, 35, 54, 55, 54, 51, 50, 23, 22,253,255, 66,109,107, 11, 22, 16, 13, 38, 18, 18, 2,125, 2, 51, 51, 91, 38, 32, 30, 33,
+ 66,110,107, 13, 20, 16, 13, 38, 18, 18, 2,125, 2, 51, 51, 91, 38, 32, 30, 5,255,103,169, 9, 14, 10, 36, 37, 82,135, 74, 73,
+ 14, 13, 29,103,168, 11, 13, 10, 36, 37, 82,135, 74, 73, 14, 13, 0, 2,253, 72, 4,137,254,176, 6,204, 0, 3, 0, 7, 0, 0,
+ 1, 51, 21, 35, 19, 51, 21, 35,253, 72,150,150,210,150,150, 5, 31,150, 2, 67,150, 0, 0, 0,255,255, 0, 0, 0, 0, 0, 0,
+ 0, 0, 16, 34, 6,134, 0,183, 16, 3, 6,134, 0, 0, 0,167, 0, 1,252, 99,254, 40,255,157,255,194, 0, 13, 0, 0, 1, 55,
+ 33, 23, 35, 39, 55, 51, 7, 33, 39, 51, 23, 7,254,112,132,254, 25,132,127,175,175,127,132, 1,231,132,126,175,175,254, 40,155,
+155,205,205,155,155,205,205, 0, 0, 1,253, 51,254, 20,254,205,255,164, 0, 8, 0, 0, 1, 35, 53, 7, 53, 55, 23, 21, 39,254,
+ 50,100,155,205,205,155,254, 20,231,132,126,175,175,126,132, 0, 0, 1,253,120, 4,225,254,136, 7, 6, 0, 16, 0, 0, 1, 6,
+ 7, 6, 21, 20, 23, 22, 23, 21, 38, 39, 38, 52, 55, 54, 55,254,136, 64, 42, 44, 44, 42, 64,114, 78, 80, 80, 78,114, 6,139, 1,
+ 42, 44, 64, 65, 43, 43, 1,123, 1, 79, 80,230, 80, 78, 1, 0,255,255,252,191, 5, 41,255, 49, 6,216, 16, 39, 2, 89, 0, 0,
+ 0,144, 16, 6, 2, 79, 0,229,255,255,253, 42,253, 84,254,230,255, 16, 16, 7, 2,133, 0, 0,248, 98, 0, 0, 0, 1,253,120,
+ 4,225,254,136, 7, 6, 0, 16, 0, 0, 1, 53, 22, 23, 22, 20, 7, 6, 7, 53, 54, 55, 54, 53, 52, 39, 38,253,120,114, 78, 80,
+ 80, 78,114, 64, 42, 44, 44, 42, 6,139,123, 1, 78, 80,230, 80, 79, 1,123, 1, 43, 43, 65, 64, 44, 42, 0, 0,255,255,255, 46,
+ 5, 68,255,250, 6, 16, 16, 7, 2, 50,253,148, 0, 0, 0, 0,255,255,252,112,254, 27, 3,144,255,133, 16, 7, 5,172,252,201,
+ 0, 0, 0, 0,255,255,252,112, 6,107, 3,144, 7,213, 16, 7, 5,172,252,201, 8, 80, 0, 0, 0, 1,253, 42, 5, 29, 2,214,
+ 6, 55, 0, 35, 0, 0, 3, 39, 38, 39, 38, 35, 34, 7, 6, 7, 35, 54, 55, 54, 51, 50, 23, 22, 31, 1, 22, 23, 22, 51, 50, 55,
+ 54, 55, 51, 6, 7, 6, 35, 34, 39, 38, 4,144, 28, 79, 44, 36,101, 53, 70, 5,162, 4,113,112,200, 91, 63, 57, 90,144, 28, 79,
+ 44, 36, 97, 57, 71, 4,162, 4,113,112,200, 91, 63, 57, 5, 90, 55, 11, 18, 10, 36, 48, 71,135, 74, 73, 14, 13, 34, 55, 11, 18,
+ 10, 36, 44, 75,135, 74, 73, 14, 13, 0, 0, 0,255,255,252,112, 6, 4, 3,144, 7,110, 16, 7, 5,173,252,201, 0, 0, 0, 0,
+ 0, 1,252,119,254, 40, 3,147,255,194, 0, 8, 0, 0, 1, 53, 33, 39, 51, 23, 7, 35, 55,252,119, 6,115,132,126,175,175,126,
+132,254,195,100,155,205,205,155, 0, 1, 0,160, 4,116, 1,159, 6,102, 0, 3, 0, 17, 64, 6, 1, 0, 4, 2, 0, 4, 16,212,
+204, 49, 0, 16,212,204, 48, 27, 1, 51, 3,160, 65,190,110, 4,116, 1,242,254, 14, 0, 0, 0, 0, 1, 0,160,254, 86, 1,159,
+ 0, 72, 0, 3, 0, 17, 64, 6, 2, 3, 4, 0, 2, 4, 16,212,204, 49, 0, 16,212,204, 48, 37, 3, 35, 19, 1,159, 65,190,110,
+ 72,254, 14, 1,242, 0, 0, 0, 0, 1, 1,182,254, 86, 2,146,255,164, 0, 13, 0, 0, 1, 35, 34, 39, 38, 61, 1, 51, 21, 20,
+ 23, 22, 59, 1, 2,146,148, 26, 26, 20,149, 10, 12, 14, 35,254, 86, 33, 26, 46,229,229, 14, 12, 13, 0, 0, 0,255,255, 0,158,
+255, 18, 1,195, 4, 35, 18, 6, 0, 30, 0, 0, 0, 1, 1,115, 4,238, 3, 82, 6,102, 0, 3, 0, 49, 64, 9, 2,180, 0,179,
+ 4, 3, 68, 1, 4, 16,212,236, 49, 0, 16,244,236, 48, 0, 75,176, 9, 84, 75,176, 14, 84, 91, 88,189, 0, 4,255,192, 0, 1,
+ 0, 4, 0, 4, 0, 64, 56, 17, 55, 56, 89, 1, 51, 1, 35, 2,139,199,254,186,153, 6,102,254,136, 0, 0, 0,255,255, 0,215,
+ 5, 70, 3, 82, 7,210, 18, 38, 0,106, 0, 0, 17, 7, 2,165, 0, 0, 1,108, 0, 20, 0, 64, 7,175, 8,159, 8, 95, 8, 3,
+ 93, 64, 5, 95, 8, 15, 8, 2,113, 48, 0, 0,255,255, 0, 16, 0, 0, 5,104, 6,102, 16, 39, 2,165,254,218, 0, 0, 16, 6,
+ 2,176, 0, 0,255,255, 0,219, 2, 72, 1,174, 3, 70, 18, 6, 0,121, 0, 0,255,255,255,231, 0, 0, 5,117, 6,102, 16, 39,
+ 2,165,254,116, 0, 0, 16, 7, 2,180, 0,234, 0, 0, 0, 0,255,255,255,243, 0, 0, 6, 31, 6,102, 16, 39, 2,165,254,128,
+ 0, 0, 16, 7, 2,182, 0,228, 0, 0, 0, 0,255,255,255,237, 0, 0, 2,125, 6,102, 16, 39, 2,165,254,122, 0, 0, 16, 7,
+ 2,184, 0,234, 0, 0, 0, 0,255,255,255,242,255,227, 6, 1, 6,102, 16, 39, 2,165,254,127, 0, 0, 16, 6, 2,190, 40, 0,
+255,255,255,225, 0, 0, 6,145, 6,102, 16, 39, 2,165,254,110, 0, 0, 16, 7, 2,195, 1,170, 0, 0, 0, 0,255,255,255,219,
+ 0, 0, 6, 5, 6,102, 16, 39, 2,165,254,104, 0, 0, 16, 6, 2,199, 54, 0,255,255, 0, 5, 0, 0, 2,128, 7,210, 16, 39,
+ 2,166,255, 46, 0, 0, 18, 6, 2,215, 15, 0,255,255, 0, 16, 0, 0, 5,104, 5,213, 18, 6, 0, 36, 0, 0,255,255, 0,201,
+ 0, 0, 4,236, 5,213, 18, 6, 0, 37, 0, 0, 0, 1, 0,201, 0, 0, 4,106, 5,213, 0, 5, 0, 25, 64, 12, 4,149, 1,129,
+ 0, 7, 2, 4, 28, 1, 4, 6, 16,252,252,204,196, 49, 0, 47,244,236, 48, 51, 17, 33, 21, 33, 17,201, 3,161,253, 41, 5,213,
+170,250,213, 0, 0, 2, 0, 16, 0, 0, 5,104, 5,213, 0, 2, 0, 6, 0, 61, 64, 12, 66, 0,149, 4,129, 1,149, 3, 8, 6,
+ 3, 7, 16,212,196,196, 49, 0, 47,236,244,236, 48, 75, 83, 88, 64, 18, 0, 17, 5, 4, 3, 2, 17, 6, 6, 5, 0, 17, 4, 1,
+ 17, 3, 3, 4, 5, 7, 16,236, 16,236, 7, 16,236, 8, 16,236, 89, 9, 1, 33, 5, 1, 51, 1, 2,188,254,102, 3, 53,251,185,
+ 2, 58,229, 2, 57, 5, 14,251,154,168, 5,213,250, 43, 0, 0,255,255, 0,201, 0, 0, 4,139, 5,213, 18, 6, 0, 40, 0, 0,
+255,255, 0, 92, 0, 0, 5, 31, 5,213, 18, 6, 0, 61, 0, 0,255,255, 0,201, 0, 0, 5, 59, 5,213, 18, 6, 0, 43, 0, 0,
+ 0, 3, 0,115,255,227, 5,217, 5,240, 0, 3, 0, 18, 0, 33, 0, 50, 64, 28, 4,149, 19,145, 34, 3,149, 0,173, 34, 11,149,
+ 26,140, 34, 35, 16, 1, 15, 25, 22, 51, 0, 8, 25, 30, 16, 34, 16,252,236,196,244,236,196,236, 49, 0, 16,244,236, 16,244,236,
+ 16,244,236, 48, 1, 33, 21, 33, 1, 34, 7, 6, 17, 16, 0, 51, 50, 55, 54, 17, 16, 39, 38, 39, 32, 0, 17, 16, 7, 6, 33, 32,
+ 39, 38, 17, 16, 55, 54, 1,197, 2,194,253, 62, 1, 98,220,129,130, 1, 3,220,220,129,128,128,129,220, 1, 58, 1,120,188,188,
+254,198,254,197,188,189,189,188, 3,112,170, 2,134,164,164,254,229,254,230,254,184,164,164, 1, 26, 1, 27,164,164,164,254, 91,
+254,158,254,159,210,211,210,210, 1, 98, 1, 98,211,210, 0, 0,255,255, 0,201, 0, 0, 1,147, 5,213, 18, 6, 0, 44, 0, 0,
+255,255, 0,201, 0, 0, 5,106, 5,213, 18, 6, 0, 46, 0, 0, 0, 1, 0, 16, 0, 0, 5,104, 5,213, 0, 6, 0, 60, 64, 11,
+ 66, 6,149, 2,129, 5, 1, 8, 4, 1, 7, 16,212,196,196, 49, 0, 47, 60,244,236, 48, 75, 83, 88, 64, 18, 6, 17, 3, 2, 1,
+ 5, 17, 4, 4, 3, 6, 17, 2, 0, 17, 1, 1, 2, 5, 7, 16,236, 16,236, 7, 16,236, 8, 16,236, 89, 51, 35, 1, 51, 1, 35,
+ 1,229,213, 2, 58,229, 2, 57,210,254, 38, 5,213,250, 43, 5, 14, 0, 0, 0,255,255, 0,201, 0, 0, 6, 31, 5,213, 18, 6,
+ 0, 48, 0, 0,255,255, 0,201, 0, 0, 5, 51, 5,213, 18, 6, 0, 49, 0, 0, 0, 3, 0,201, 0, 0, 4, 98, 5,213, 0, 3,
+ 0, 7, 0, 11, 0, 42, 64, 22, 7,149, 4,129, 11, 3,149, 0,173, 8,149, 11, 13, 4, 1, 9, 5, 0, 8, 4, 4, 12, 16,252,
+ 60,196,212, 60,196,236, 49, 0, 47,236,244,236, 16,244,236, 48, 1, 33, 21, 33, 3, 33, 21, 33, 17, 33, 21, 33, 1, 50, 2,199,
+253, 57,105, 3,153,252,103, 3,153,252,103, 3,113,170, 3, 14,170,251,127,170,255,255, 0,115,255,227, 5,217, 5,240, 18, 6,
+ 0, 50, 0, 0,255,255, 0,201, 0, 0, 5, 59, 5,213, 18, 6, 3, 60, 0, 0,255,255, 0,201, 0, 0, 4,141, 5,213, 18, 6,
+ 0, 51, 0, 0, 0, 1, 0,201, 0, 0, 4,139, 5,213, 0, 11, 0, 70, 64, 17, 66, 10, 6,149, 7,129, 0, 4,149, 3, 13, 1,
+ 8, 4, 7, 4, 12, 16,252, 60,212, 60,204, 49, 0, 47,236, 50,244,236, 50, 48, 75, 83, 88, 64, 18, 11, 17, 5, 5, 4, 10, 17,
+ 6, 6, 5, 11, 17, 5, 0, 17, 4, 5, 4, 5, 7, 16,236, 16,236, 7, 16,236, 8, 16,236, 89, 37, 33, 21, 33, 53, 9, 1, 53,
+ 33, 21, 33, 1, 1,177, 2,218,252, 62, 1,223,254, 33, 3,176,253, 56, 1,223,170,170,170, 2,112, 2, 17,170,170,253,243, 0,
+255,255,255,250, 0, 0, 4,233, 5,213, 18, 6, 0, 55, 0, 0,255,255,255,252, 0, 0, 4,231, 5,213, 18, 6, 0, 60, 0, 0,
+255,255, 0,115, 0, 0, 5,217, 5,213, 18, 6, 3, 65, 0, 0,255,255, 0, 61, 0, 0, 5, 59, 5,213, 18, 6, 0, 59, 0, 0,
+ 0, 1, 0,115, 0, 0, 5,219, 5,213, 0, 29, 0, 46, 64, 23, 16, 13,149, 27, 2, 21, 14, 7,129, 0, 31, 21, 28, 22, 2, 14,
+ 28, 27, 15, 8, 28, 7, 30, 16,220,236,212, 60,252, 60,212,236,204, 49, 0, 47,228, 50, 50,220, 60,236, 50, 48, 33, 54, 39, 34,
+ 39, 38, 3, 17, 51, 17, 16, 23, 22, 23, 17, 51, 17, 54, 55, 54, 25, 1, 51, 17, 2, 7, 6, 35, 6, 23, 2,194, 1, 1,214,188,
+184, 5,213,130,110,138,202,138,110,130,213, 5,184,188,214, 1, 1,134,176,210,204, 1,104, 1,153,254,103,254,230,164,140, 14,
+ 3,241,252, 15, 14,140,164, 1, 26, 1,153,254,103,254,152,204,210, 72,238, 0, 0, 1, 0, 78, 0, 0, 5,207, 5,231, 0, 38,
+ 0, 51, 64, 27, 11,149, 30,145, 38, 3, 18, 21,149, 2, 20, 3, 7, 25, 40, 16, 0, 34, 51, 26, 18, 14, 25, 21, 26, 16, 39, 16,
+252,196,252,196, 16,244,196,236,252,196, 49, 0, 47, 60,236, 50, 50, 50,244,236, 48, 37, 21, 33, 53, 54, 55, 54, 53, 52, 39, 38,
+ 35, 34, 0, 21, 20, 23, 22, 23, 21, 33, 53, 33, 38, 39, 38, 53, 16, 55, 54, 33, 32, 23, 22, 17, 20, 7, 6, 7, 5,207,253,168,
+177, 99, 99,132,132,216,216,254,247, 99,100,178,253,168, 1, 63,158, 73, 72,192,191, 1, 49, 1, 47,193,192, 71, 71,161,178,178,
+178, 97,166,166,202,240,145,145,254,221,239,202,166,166, 97,178,178,139,149,149,184, 1, 62,197,197,197,196,254,203,194,148,148,
+141, 0, 0, 0,255,255, 0,201, 0, 0, 1,147, 5,213, 16, 39, 6,132, 3, 47, 1,117, 19, 6, 2,184, 0, 0, 0, 8,180, 9,
+ 3, 6, 8, 7, 43, 49, 0, 0,255,255,255,252, 0, 0, 4,231, 5,213, 16, 39, 6,132, 4,113, 1,117, 19, 6, 2,195, 0, 0,
+ 0, 8,180, 12, 2, 7, 8, 7, 43, 49, 0, 0,255,255, 0,113,255,230, 4,229, 6,102, 18, 38, 2,207, 0, 0, 16, 6, 2,165,
+110, 0, 0, 0,255,255, 0,133,255,227, 3,200, 6,102, 16, 38, 2,165, 80, 0, 18, 6, 2,211, 0, 0, 0, 0,255,255, 0,186,
+254, 86, 4,100, 6,102, 16, 39, 2,165, 0,198, 0, 0, 18, 6, 2,213, 0, 0,255,255, 0,166, 0, 0, 2,152, 6,102, 18, 38,
+ 2,215, 0, 0, 16, 7, 2,165,255, 70, 0, 0,255,255, 0,149,255,226, 4, 42, 7,210, 18, 38, 2,227, 0, 0, 16, 6, 2,166,
+ 27, 0, 0, 0, 0, 2, 0,113,255,230, 4,229, 4,122, 0, 13, 0, 42, 0,200, 64, 11, 18, 17, 7, 44, 16, 23, 7, 18, 37, 69,
+ 43, 16,252,236,212,196,196, 18, 57, 57, 64, 10, 63, 16, 47, 16, 31, 16, 3,143, 16, 1, 93,113, 0, 64, 17, 18, 17, 11, 3,185,
+ 41,184, 25, 11,185, 33,140, 15,188, 22,135, 25, 47,236,228,244,236, 16,244,236, 17, 57, 57, 5, 64, 20, 29, 17, 0, 17, 14, 17,
+ 18, 17, 17, 16, 15, 17, 14, 17, 0, 17, 29, 17, 17, 16, 7, 16, 60,236,236,236, 8, 7, 16, 60,236,236, 49, 48, 1, 64, 11,132,
+ 18,134, 17,136, 1,137, 13,128, 16, 5, 93, 64, 19, 73, 19, 73, 18, 73, 28, 74, 29, 78, 13, 76, 0, 78, 1, 73, 14, 75, 17, 9,
+ 93, 64, 17, 58, 14, 57, 18, 58, 17, 56, 29, 56, 17, 63, 13, 60, 0, 62, 1, 8, 93, 64, 11, 43, 13, 43, 1, 42, 0, 41, 14, 41,
+ 17, 5, 93, 64, 13, 25, 15, 24, 14, 27, 13, 27, 1, 26, 0, 25, 17, 6, 93, 0, 64, 5, 43, 30, 43, 31, 2, 93, 1, 39, 38, 39,
+ 38, 7, 6, 21, 20, 23, 22, 51, 50, 55, 27, 1, 51, 3, 23, 22, 23, 22, 59, 1, 21, 35, 34, 39, 38, 39, 6, 7, 6, 39, 38, 39,
+ 38, 17, 16, 55, 54, 55, 36, 3, 78, 44, 45,178,134, 61, 77, 75, 76,121,134, 72,164, 99,164,205, 40, 9, 35, 41, 32, 88,110, 94,
+ 84, 41, 17, 44, 96, 44,143,234,115,117,127,141,198, 1, 55, 2, 9,231,236, 1, 1,111,137,183,220,105,107,213, 1,231, 1, 37,
+253,161,219, 49, 41, 48,156, 84, 42, 88,107, 91, 42, 1, 2,150,156, 1, 20, 1, 41,135,151, 3, 5, 0, 0, 0, 0, 2, 0,191,
+254, 86, 4,137, 6, 33, 0, 14, 0, 28, 0, 55, 64, 15, 24, 18, 7, 30, 69, 19, 18, 11, 22, 0, 28, 8, 3, 70, 29, 16,252,236,
+ 50,196,212,236,228,212,236, 49, 0, 64, 14, 26,185, 5, 9, 21,185, 22, 17,185, 13,140, 2,189, 29, 16,236,244,236,212,252, 57,
+212,236, 48, 37, 17, 35, 17, 16, 33, 32, 19, 18, 7, 4, 19, 18, 37, 38, 3, 22, 55, 32, 17, 16, 5, 53, 4, 17, 52, 7, 32, 17,
+ 1,121,185, 1,170, 1,176, 2, 3,175, 1, 23, 1, 2,254, 28,212, 89,111,197, 1, 32,254, 48, 1,107,234,254,251, 69,254, 17,
+ 6, 3, 1,200,254,127,254,238,100, 90,254,245,254, 37, 1, 1, 1, 73,174, 1, 1, 58, 1, 26, 22,170, 6, 1, 70,220, 1,254,
+200, 0, 0, 0, 0, 1, 0, 32,254, 86, 4,127, 4, 96, 0, 14, 0, 64, 64, 7, 16, 3, 7, 8, 4, 12, 15, 16,212,212,252,212,
+196, 49, 0, 64, 7, 2, 12,191, 6,189, 4, 7, 47, 60,236,228, 50, 48, 5, 64, 18, 1, 17, 8, 7, 2, 17, 3, 4, 3, 14, 13,
+ 1, 17, 0, 17, 7, 8, 7, 7, 16,236,236, 57, 57, 7, 16,236, 8,236, 1, 19, 1, 51, 1, 17, 35, 17, 1, 38, 43, 1, 53, 51,
+ 50, 1,105,245, 1, 94,195,254, 59,184,254,218, 44, 95, 49, 70,197, 3,176,253, 76, 3,100,251,160,254, 86, 1,170, 3, 68,126,
+158, 0, 0, 0, 0, 2, 0,113,255,227, 4,117, 5,240, 0, 28, 0, 45, 0, 84, 64, 20, 6, 5, 40, 4, 47, 69, 28, 40, 18, 10,
+ 81, 18, 4, 18, 24, 33, 18, 18, 69, 46, 16,252,236,212,236, 16,244,178,127, 10, 1, 93,236,196,236, 17, 18, 57, 57, 0, 64, 14,
+ 6, 5, 37, 2, 28, 0, 2,185, 26, 37,185, 14,140, 46, 16,244,236,212,252,212,204, 17, 18, 57, 57, 64, 6, 22, 29, 83, 5, 6,
+ 5, 7, 14, 16,236, 57, 49, 48, 1, 38, 35, 34, 21, 20, 5, 22, 23, 22, 17, 16, 7, 6, 35, 34, 39, 38, 17, 52, 55, 54, 55, 38,
+ 53, 16, 33, 50, 23, 1, 6, 7, 6, 21, 20, 23, 22, 51, 50, 54, 53, 52, 39, 38, 39, 38, 3,236,102,239,253, 1, 8,208,117,142,
+137,137,240,239,138,137,137, 53, 75,156, 1,185,221,120,254, 24, 68, 55, 86, 85, 86,149,147,172, 91, 97,126, 64, 5, 17, 70,117,
+ 92, 48, 37,112,135,254,235,254,247,156,157,157,156, 1, 19,204,165, 64, 36, 79,141, 1, 16, 70,254, 40, 29, 73,113,204,203,114,
+115,232,190,199, 96,103, 11, 6, 0, 1, 0,133,255,227, 3,200, 4,124, 0, 50, 0, 61, 64, 34, 12,134, 11,136, 16,185, 8,184,
+ 51, 27,169, 24, 51, 39,134, 40,136, 35,185, 44,140, 51, 52, 25, 11, 39, 20, 8, 4, 31, 8, 48, 69, 51, 16,252,236,212,236,212,
+196,196,196, 49, 0, 16,244,236,244,236, 16,212,236, 16,244,236,244,236, 48, 1, 38, 39, 38, 53, 52, 55, 54, 51, 50, 22, 23, 21,
+ 38, 39, 38, 35, 34, 7, 6, 21, 20, 23, 22, 59, 1, 21, 35, 34, 7, 6, 21, 20, 23, 22, 51, 50, 55, 54, 55, 21, 6, 7, 6, 35,
+ 34, 39, 38, 53, 52, 54, 1,139,112, 60, 60,114,113,196, 76,170, 98, 97, 80, 81, 71,119, 69, 70, 68, 67,116,155,148,137, 72, 78,
+ 84, 85,151, 93, 85, 85, 71, 90, 84, 85, 80,238,129,129,138, 2, 92, 24, 65, 64, 93,141, 79, 78, 24, 24,167, 29, 13, 13, 46, 46,
+ 64, 70, 45, 44,152, 51, 56, 88, 90, 56, 56, 18, 19, 37,171, 28, 14, 14, 91, 91,173,108,146, 0, 0, 1, 0,107,254, 82, 3,248,
+ 6, 20, 0, 29, 0, 62, 64, 11, 10, 14, 18, 31, 4, 25, 24, 28, 18, 20, 30, 16,212,236,212,212,212,196,252,204, 75,176, 16, 81,
+ 88,185, 0, 22, 0, 64, 56, 89, 49, 0, 64, 14, 8,185, 10, 0,185, 18,140, 30, 26, 23,135, 24,151, 30, 16,244,236, 50, 16,244,
+236,220,236, 48, 37, 22, 23, 22, 21, 20, 7, 6, 35, 52, 53, 22, 55, 54, 53, 52, 39, 38, 35, 32, 3, 16, 1, 33, 53, 33, 21, 0,
+ 17, 16, 2,202,132, 79, 84, 74, 80,163, 69, 42, 32, 32, 31, 58,253,162, 1, 2, 59,253,236, 3,102,253, 44,127, 1, 75, 79,120,
+115, 80, 87, 75, 76, 5, 44, 35, 37, 53, 44, 42, 2, 51, 1,236, 1, 89,185,185,254,148,254, 39,254,105, 0, 0, 0, 1, 0,186,
+254, 86, 4,100, 4,123, 0, 21, 0, 49, 64, 22, 6,135, 14, 18,184, 12,188, 2,189, 11, 23, 70, 3, 8, 0, 78, 9, 13, 8, 12,
+ 70, 22, 16,252,236, 50,244,236,236, 49, 0, 47,236,228,244,196,236, 48, 64, 5,160, 23,128, 23, 2, 1, 93, 1, 17, 35, 17, 52,
+ 38, 35, 34, 6, 21, 17, 35, 17, 51, 21, 54, 55, 54, 51, 50, 23, 22, 4,100,184,124,124,149,172,185,185, 66, 89, 90,117,193, 99,
+ 99, 2,164,251,178, 4, 72,159,158,190,164,253,135, 4, 96,174,101, 50, 50,119,120, 0, 0, 0, 0, 3, 0,113,255,233, 4,117,
+ 6, 36, 0, 8, 0, 17, 0, 33, 0, 63, 64, 27, 13,185, 18,151, 34, 1,149, 17, 34, 5,185, 26,140, 34, 35, 69, 0, 9, 18, 22,
+ 81, 1, 17, 18, 30, 69, 34, 16,252,236, 50,244,178,127, 22, 1, 93,236, 50,236, 49, 0, 16,244,236, 16,212,236, 16,244,236, 48,
+ 64, 5,160, 35,128, 35, 2, 1, 93, 1, 33, 18, 23, 22, 51, 50, 55, 54, 19, 2, 39, 38, 35, 34, 7, 6, 3, 1, 50, 23, 22, 17,
+ 16, 7, 6, 35, 34, 39, 38, 17, 16, 55, 54, 3,177,253,131, 15, 69, 86,149,150, 83, 73, 9, 28, 54, 86,147,153, 81, 64, 19, 1,
+ 61,240,137,137,137,137,240,241,136,137,137,136, 2,198,254,213,127,156,157,138, 1,201, 1, 28,100,158,156,126,254,252, 2,180,
+212,211,254,138,254,139,212,213,213,212, 1,117, 1,118,211,212, 0, 1, 0,166, 0, 0, 2,110, 4, 96, 0, 13, 0, 27, 64, 7,
+ 15, 6, 0, 8, 13, 70, 14, 16,252,252,212,196, 49, 0, 64, 5, 13,188, 5,135, 8, 47,236,228, 48, 1, 17, 20, 23, 22, 59, 1,
+ 21, 35, 34, 39, 38, 53, 3, 1, 99, 34, 36,108, 89,111,180, 82, 82, 1, 4, 96,253, 43,145, 46, 48,156, 96, 98,212, 2,202, 0,
+ 0, 1, 0,191, 0, 0, 4,133, 4, 96, 0, 11, 0, 73, 64, 9, 13, 6, 4, 9, 1, 8, 11, 70, 12, 16,252,236, 50,196,212,196,
+ 49, 0, 64, 5, 3, 0,188, 7, 11, 47, 60,228, 50, 48, 64, 22, 8, 17, 9, 4, 5, 7, 17, 6, 6, 5, 8, 5, 9, 4, 3, 17,
+ 4, 2, 17, 9, 9, 4, 7, 16, 4,236, 16, 5,236, 9, 60, 60, 7, 16, 5,236, 16, 8,236, 19, 51, 17, 1, 51, 9, 1, 35, 1,
+ 7, 17, 35,191,190, 1,227,224,254, 71, 1,254,225,254, 98,137,190, 4, 96,254, 47, 1,209,254, 90,253, 70, 2, 66,129,254, 63,
+ 0, 1, 0, 61, 0, 0, 4,127, 6, 21, 0, 13, 0, 70, 64, 5, 15, 1, 11, 5, 14, 16,212,196,212,196, 49, 0, 64, 6, 10,135,
+ 11,151, 2, 5, 47, 60,244,236, 48, 64, 24, 3, 17, 1, 0, 6, 4, 17, 5, 6, 5, 7, 17, 6, 17, 3, 17, 1, 0, 0, 2, 17,
+ 0, 1, 0, 7, 16, 5,236, 16, 9,236,236, 5,236, 7, 16, 5,236, 16, 8,236, 9, 1, 35, 9, 1, 35, 1, 39, 38, 43, 1, 53,
+ 23, 22, 2,122, 2, 5,195,254,198,254,126,195, 1,235, 74, 47,107, 96,117,226, 5,101,250,155, 3, 60,252,196, 4, 50,198,126,
+158, 2, 3, 0,255,255, 0,174,254, 86, 4,229, 4, 96, 16, 6, 0,119, 0, 0, 0, 1, 0, 74, 0, 0, 4, 24, 4, 96, 0, 21,
+ 0, 65, 64, 7, 23, 7, 18, 17, 0, 1, 22, 16,212,196,212,236,196, 49, 64, 4, 11, 1,188, 0, 0, 47,228, 50, 48, 64, 21, 20,
+ 19, 18, 17, 21, 17, 6, 5, 4, 3, 7, 3, 17, 1, 0, 0, 2, 17, 1, 1, 0, 7, 16, 5,236, 16, 9,236, 18, 23, 57, 5,236,
+ 18, 23, 57, 33, 1, 51, 1, 54, 55, 54, 55, 54, 39, 38, 39, 51, 49, 22, 23, 22, 21, 20, 7, 6, 7, 1,160,254,170,198, 1, 33,
+120,100, 76, 4, 2, 24, 28,106,186, 69, 46, 42,136,177,123, 4, 96,252, 84,124,172,129,112, 53,100,119,131, 89,124,114, 78,196,
+175,228,116, 0, 0, 1, 0,107,254, 82, 4, 1, 6, 20, 0, 38, 0, 64, 64, 15, 10, 14, 18, 40, 4, 34, 29, 28, 32, 18, 24, 37,
+ 18, 20, 39, 16,212,236,212,236,212,212,196,212,196,252,204, 49, 64, 18, 8,185, 10, 0,185, 18,140, 39, 22, 35,135, 34, 30, 27,
+135, 28,151, 39, 0, 16,244,252, 60,212,236, 57, 16,244,236,220,236, 48, 37, 22, 23, 22, 21, 20, 7, 6, 35, 52, 53, 22, 55, 54,
+ 53, 52, 39, 38, 35, 32, 17, 16, 37, 36, 17, 52, 55, 35, 53, 33, 21, 32, 17, 20, 5, 21, 36, 19, 18, 2,218,132, 79, 84, 74, 80,
+163, 69, 42, 32, 32, 31, 58,253,145, 1, 77,254,232,220,208, 3, 21,253,139, 2, 16,253,198, 2, 1,127, 1, 75, 79,120,115, 80,
+ 87, 75, 76, 5, 44, 35, 37, 53, 44, 42, 1,181, 1, 44, 88, 36, 1, 4,197, 82,185,185,254,221,191, 9,170, 22,254,188,254,241,
+255,255, 0,113,255,227, 4,117, 4,123, 18, 6, 0, 82, 0, 0, 0, 1, 0, 74,255,217, 4,152, 4, 96, 0, 23, 0, 47, 64, 11,
+ 25, 10, 1, 18, 8, 3, 19, 8, 0, 22, 24, 16,220,196,236,212,236,196,196,204, 49, 64, 12, 7,135, 14,140, 21, 3, 19, 23,135,
+ 0,188, 21, 0, 47,244,236, 50, 50, 16,244,236, 48, 19, 33, 21, 35, 17, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 53, 17,
+ 33, 17, 35, 17, 35, 74, 4, 49,141, 49, 55, 15, 44, 7, 35, 74, 37,120, 92,254, 99,188,143, 4, 96,184,253, 80, 72, 63, 5, 1,
+133, 13, 12,131,176, 2,156,252, 88, 3,168, 0, 0, 2, 0,186,254, 86, 4,164, 4,123, 0, 17, 0, 29, 0, 49, 64, 25, 21,185,
+ 4,184, 30, 27,185, 10,140, 15,189, 30, 31, 69, 18, 18, 7, 81, 13, 8, 24, 18, 16, 70, 30, 16,252,236,236,244,178,127, 7, 1,
+ 93,236,236, 49, 0, 16,236,244,236, 16,244,236, 48, 1, 54, 55, 54, 51, 50, 0, 17, 16, 2, 35, 34, 38, 39, 17, 35, 17, 52, 5,
+ 52, 38, 35, 34, 6, 21, 20, 22, 51, 50, 54, 1, 20, 61,151, 59,182,204, 0,255,255,204,123,177, 58,185, 3, 43,167,146,146,167,
+167,146,146,167, 3,152,102, 90, 35,254,188,254,248,254,248,254,188, 97,100,253,174, 3,207,231,221,203,231,231,203,203,231,231,
+ 0, 1, 0,113,254, 82, 3,231, 4,123, 0, 36, 0, 54, 64, 12, 29, 33, 18, 23, 38, 9, 72, 16, 18, 3, 69, 37, 16,252,236,244,
+204,212,252,196, 49, 64, 17, 27,185, 29, 19,185, 0,140, 37, 9,134, 10,136, 13,185, 6,184, 37, 0, 16,244,252,244,236, 16,244,
+236,220,236, 48, 5, 32, 0, 17, 16, 0, 33, 50, 22, 23, 21, 46, 1, 35, 34, 6, 21, 20, 22, 51, 50, 23, 22, 21, 20, 7, 6, 35,
+ 52, 53, 22, 55, 54, 53, 52, 39, 38, 2,168,254,243,254,214, 1, 45, 1, 6, 85,162, 76, 78,157, 80,179,198,198,175,131, 80, 84,
+ 74, 80,163, 69, 42, 32, 32, 31, 29, 1, 62, 1, 14, 1, 18, 1, 58, 35, 35,172, 43, 43,227,205,205,227, 76, 79,120,115, 80, 87,
+ 75, 76, 5, 44, 35, 37, 53, 44, 42, 0, 0, 0, 0, 2, 0,113,255,227, 4,214, 4, 98, 0, 13, 0, 30, 0, 49, 64, 11, 32, 15,
+ 10, 18, 19, 81, 4, 18, 27, 69, 31, 16,252,236,244,178,127, 19, 1, 93,236,212,196, 49, 64, 12, 7,185, 23,140, 31, 17,135, 0,
+185, 14,188, 31, 0, 16,244,236,236, 16,244,236, 48, 1, 34, 7, 6, 21, 20, 22, 51, 50, 54, 53, 52, 39, 38, 39, 5, 21, 35, 22,
+ 21, 16, 7, 6, 35, 34, 39, 38, 17, 16, 55, 54, 2,115,152, 82, 86,171,149,147,172, 86, 79,154, 2, 99,206,109,137,137,240,241,
+136,137,137,114, 3,206,110,115,190,201,231,232,200,183,122,110,147, 1,184,156,221,254,237,156,157,157,156, 1, 19, 1, 20,156,
+130, 0, 0, 0, 0, 1, 0,100, 0, 0, 4,109, 4, 96, 0, 17, 0, 35, 64, 8, 19, 13, 3, 15, 8, 12, 10, 18, 16,212,196,252,
+196,196,196, 49, 0, 64, 8, 15, 11,135, 12,188, 2,185, 5, 47,236,244,236, 50, 48, 37, 22, 59, 1, 21, 35, 34, 39, 38, 53, 17,
+ 33, 53, 33, 21, 33, 17, 20, 2,230, 36,108, 89,111,180, 82, 82,254, 92, 4, 9,254, 87,204, 48,156, 96, 98,212, 2, 18,184,184,
+253,227,145, 0, 0, 1, 0,149,255,226, 4, 42, 4, 96, 0, 28, 0, 43, 64, 10, 30, 69, 9, 18, 19, 0, 8, 28, 70, 29, 16,252,
+236,212,236,228, 64, 7, 63, 30, 63, 9, 63, 19, 3, 93, 49, 0, 64, 6, 13, 28,188, 5,185, 23, 47,236,244, 60, 48, 1, 17, 20,
+ 23, 22, 51, 50, 55, 54, 55, 54, 39, 38, 39, 51, 49, 22, 23, 22, 21, 20, 7, 6, 39, 34, 39, 38, 53, 3, 1, 82, 50, 55,107,150,
+105, 59, 15, 8, 30, 28,106,186, 70, 45, 42,128,156,254,179,101, 98, 1, 4, 96,253, 43,135, 64, 69,208,118,187,102,128,119,131,
+ 90,123,115,154,253,187,228, 1,120,118,197, 2,202, 0, 0, 0, 0, 2, 0,111,254, 86, 4,210, 4,104, 0, 10, 0, 41, 0, 61,
+ 64, 16, 43, 69, 7, 18, 15, 19, 2, 8, 30, 22, 40, 35, 18, 26, 69, 42, 16,252,236,212, 60,204,252, 60,212,236,236, 49, 0, 64,
+ 16, 0, 31,185, 11, 30,184, 42, 3, 39,135, 19, 22,140, 21,189, 42, 16,236,244, 60,236, 50, 16,244, 60,236, 50, 48, 1, 34, 21,
+ 17, 50, 55, 54, 39, 38, 39, 38, 39, 50, 23, 22, 19, 18, 7, 6, 35, 17, 35, 17, 34, 39, 38, 17, 2, 55, 54, 55, 21, 6, 7, 6,
+ 23, 22, 23, 22, 51, 17, 16, 3, 61, 65, 94, 96, 86, 1, 1, 85, 70, 54,144,123,133, 4, 4,141,133,199,183,199,134,136, 1,137,
+104,164, 66, 58, 87, 1, 1, 85, 76,113, 3,203,145,253, 82,104, 93,223,208,112, 91,157,132,141,254,217,254,241,161,152,254,110,
+ 1,145,153,156, 1, 19, 1, 30,146,109, 28,163, 23, 78,115,190,202,115,103, 2,175, 1, 46, 0, 0, 1, 0, 59,254, 85, 4,100,
+ 4, 97, 0, 23, 0,118, 64, 12, 17, 16, 5, 4, 4, 9, 25, 20, 15, 3, 9, 24, 16,212,196,212,196,196, 18, 23, 57, 0, 64, 18,
+ 17, 16, 5, 4, 4, 19, 8,135, 14, 9,188, 24, 19,135, 22, 3,189, 24, 16,244, 60,236, 16,244, 60,236, 17, 23, 57, 5, 64, 20,
+ 14, 17, 15, 16, 15, 12, 17, 5, 5, 4, 2, 17, 3, 4, 3, 0, 17, 17, 17, 16, 7, 16,236, 7, 16,236, 7, 16,236, 7, 16,236,
+ 64, 20, 16, 17, 12, 15, 2, 13, 17, 12, 14, 3, 4, 14, 3, 5, 0, 1, 15, 2, 5, 0, 15, 15, 15, 15, 49, 48, 5, 3, 1, 35,
+ 1, 3, 38, 43, 1, 53, 23, 4, 23, 19, 1, 51, 1, 19, 22, 59, 1, 21, 39, 36, 2,220,149,254,205,217, 1,178,182, 49,154, 49,
+ 70, 1, 2, 65,148, 1, 51,217,254, 78,182, 49,154, 49, 70,254,254,250, 1,127,253,208, 3, 24, 1,215,126,158, 2, 7,167,254,
+129, 2, 48,252,232,254, 41,126,158, 2, 7, 0, 0, 1, 0,112,254, 86, 4,209, 4, 96, 0, 27, 0, 54, 64, 13, 29, 19, 8, 20,
+ 25, 13, 8, 0, 12, 6, 8, 5, 28, 16,220,236,212, 60,252, 60,212,236,204, 49, 0, 64, 14, 19, 12, 5,188, 28, 14, 11,135, 25,
+ 0,140, 27,189, 28, 16,236,244, 60,236, 50, 16,244, 60, 60, 48, 5, 38, 39, 38, 53, 17, 51, 17, 20, 23, 22, 23, 17, 51, 17, 54,
+ 55, 54, 53, 17, 51, 17, 20, 7, 6, 7, 17, 35, 2, 69,231,107,131,186, 85, 74,124,183,131, 67, 85,186,131,118,220,183, 25, 37,
+ 97,119,243, 2,137,253,126,183, 76, 66, 14, 3,213,252, 44, 14, 66, 84,175, 2,129,253,120,252,110, 99, 35,254,110, 0, 0, 0,
+ 0, 1, 0,135,255,226, 6, 40, 4, 96, 0, 26, 0, 56, 64, 20, 18, 18, 19, 28, 69, 16, 18, 21, 11, 8, 12, 7, 18, 2, 5, 18,
+ 4, 2, 69, 27, 16,252,220,236, 16,236,212,252,212,236,236,220,236, 49, 0, 64, 9, 11, 18, 4,188, 14, 9,135, 23, 0, 47, 60,
+236, 50,244, 60,196, 48, 5, 32, 17, 52, 19, 51, 2, 21, 2, 51, 50, 3, 51, 2, 55, 54, 17, 52, 3, 51, 18, 21, 18, 37, 36, 3,
+ 2, 2, 38,254, 97,155,198,143, 1,223,207, 4,170, 4,207,222,143,198,155, 2,254, 95,254,241, 34, 41, 29, 2, 82,235, 1, 64,
+254,192,240,254, 79, 2, 26,253,227, 3, 2, 1,175,240, 1, 64,254,192,235,253,173, 1, 1, 1, 42,254,213, 0,255,255, 0, 5,
+ 0, 0, 2,125, 6, 16, 18, 38, 2,215, 15, 0, 16, 7, 0,106,255, 46, 0, 0,255,255, 0,149,255,226, 4, 42, 6, 16, 16, 38,
+ 0,106, 29, 0, 18, 6, 2,227, 0, 0, 0, 0,255,255, 0,113,255,227, 4,117, 6,102, 16, 38, 2,165,125, 0, 18, 6, 2,221,
+ 0, 0, 0, 0,255,255, 0,149,255,226, 4, 42, 6,102, 16, 38, 2,165, 34, 0, 18, 6, 2,227, 0, 0, 0, 0,255,255, 0,135,
+255,226, 6, 40, 6,102, 18, 38, 2,231, 0, 0, 16, 7, 2,165, 1, 89, 0, 0, 0, 3, 0,166,255,233, 4, 77, 6, 36, 0, 13,
+ 0, 37, 0, 53, 0, 0, 1, 50, 55, 54, 55, 54, 53, 52, 39, 38, 39, 38, 7, 6, 1, 22, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38,
+ 3, 2, 55, 54, 23, 22, 23, 22, 23, 22, 7, 6, 7, 6, 7, 6, 35, 16, 23, 22, 51, 50, 55, 54, 55, 52, 39, 38, 1,105, 80, 84,
+119, 68,121, 36, 50,117,122, 93, 54, 1,238, 96, 59, 91, 59,126,246,252,139,111, 1, 1,120,134,210,164,107,111, 1, 1, 55, 38,
+251, 67, 93, 74, 78, 58, 80,174,143, 87, 24, 1, 79, 94, 3,112, 1, 3, 61,108,147, 87, 53, 73, 9, 10,196,112,254,203, 65, 75,
+117,143,130, 95,213,213,168, 1,161, 1,139,190,213, 1, 1,111,115,155,128,107, 75,150, 15, 3, 2,254,234,128,176,156, 45, 86,
+123, 72, 86, 0, 0, 2, 0,112,255,233, 4,118, 6, 36, 0, 11, 0, 40, 0, 0, 1, 54, 39, 38, 35, 34, 7, 6, 21, 20, 23, 22,
+ 5, 4, 39, 38, 17, 52, 55, 54, 51, 50, 23, 22, 3, 2, 7, 6, 35, 34, 39, 38, 19, 23, 2, 23, 22, 51, 50, 55, 54, 3,174, 6,
+ 55, 75,140, 83, 64, 56,121, 74, 1, 19,254,204,131,211,104,104,175,209,135,128, 9, 9,128,137,240,237,140,149, 12,195, 33,117,
+ 85,150,144, 89, 95, 3,112,246,126,170, 71, 66, 90,153,107, 65,160, 9, 74,120, 1, 39,160,110,112,212,200,254,127,254,125,198,
+213,213,225, 1,210, 1,254,130,215,155,156,166, 0, 1, 0, 87, 0, 0, 5, 81, 5,223, 0, 27, 0, 0, 1, 6, 3, 6, 21, 17,
+ 35, 17, 52, 39, 2, 39, 38, 7, 53, 54, 23, 4, 19, 18, 37, 54, 23, 22, 7, 6, 39, 38, 4, 70,160, 82, 42,203, 42, 82,160,116,
+120, 67,160, 1, 67, 72,107, 1, 31,111, 64,120, 54, 33,117, 86, 5, 17, 72,254,243,141,165,253,118, 2,138,165,141, 1, 13, 72,
+ 52, 26,170, 21, 24, 48,254,114, 1,123, 67, 26, 49, 93,150, 86, 26, 18, 0, 0,255,255,255,225, 0, 0, 6,161, 6,102, 16, 39,
+ 2,165,254,110, 0, 0, 16, 7, 2,239, 1, 80, 0, 0, 0, 0,255,255, 0, 87, 0, 0, 5, 81, 5,223, 16, 39, 6,132, 4,197,
+ 1,117, 18, 6, 2,239, 0, 0, 0, 3, 0,112,254, 86, 4,209, 6, 20, 0, 21, 0, 30, 0, 39, 0, 65, 64, 16, 41, 26, 18, 6,
+ 9, 1, 30, 8, 12, 20, 32, 36, 18, 16, 69, 40, 16,252,236,212, 60, 60,252, 60, 60,212,236,196, 49, 64, 18, 30, 32,135, 1, 20,
+184, 40, 22, 31,135, 9, 12,140, 21,151, 11,189, 40, 0, 16,236,228,244, 60,252, 60, 16,244, 60,252, 60, 48, 1, 17, 50, 23, 22,
+ 17, 16, 7, 6, 35, 17, 35, 17, 34, 39, 38, 17, 16, 55, 54, 51, 17, 19, 50, 55, 54, 55, 54, 39, 38, 35, 3, 17, 34, 7, 6, 23,
+ 22, 23, 22, 2,252,199,133,137,137,133,199,183,199,134,136,136,134,199,183,113, 77, 84, 1, 1, 86, 77,113,183,113, 76, 87, 1,
+ 1, 85, 76, 6, 20,254, 99,153,156,254,237,254,237,156,153,254,111, 1,145,153,156, 1, 19, 1, 19,156,153, 1,157,250,119,103,
+115,202,200,117,103,252,184, 3, 72,103,117,200,202,115,103, 0, 0, 2, 0, 65,255,226, 6,109, 4, 96, 0, 16, 0, 30, 0, 0,
+ 19, 53, 33, 21, 35, 22, 21, 16, 37, 36, 3, 2, 33, 32, 17, 52, 55, 41, 1, 6, 21, 16, 51, 50, 3, 51, 2, 55, 54, 17, 52, 65,
+ 6, 44,147, 77,254, 97,254,241, 34, 41,254,248,254, 97, 77, 4, 58,252,146, 71,222,207, 4,170, 4,207,222, 3,168,184,184,207,
+164,253,173, 1, 1, 1, 42,254,213, 2, 82,164,207,209,167,254, 79, 2, 26,253,227, 3, 3, 1,174,167, 0, 0, 0, 1, 0,111,
+254, 91, 4,206, 4,103, 0, 47, 0, 0, 5, 38, 39, 38, 55, 7, 2, 7, 6, 39, 38, 55, 54, 55, 54, 39, 38, 35, 34, 7, 53, 54,
+ 23, 22, 23, 22, 7, 55, 18, 55, 54, 23, 22, 7, 6, 7, 6, 23, 22, 51, 50, 55, 2, 7, 6, 39, 53, 4, 3,249,246, 33, 21, 24,
+189, 96,200,141, 3, 1, 61, 96,136, 91, 43, 26,142, 57, 91, 82,126,246, 33, 19, 42,189, 96,200,141, 3, 1, 61, 96,136, 91, 43,
+ 26,142, 57, 91, 38,205,152,173, 1, 55, 10, 32,240,156, 99,108,254,247,124, 89,145, 68, 84,132,124,203,169,104,108,224, 61, 17,
+ 34,238,140,112,108, 1, 9,124, 89,145, 68, 84,132,124,203,169,104,108,253,224,102, 77, 90,160,160, 0, 0, 0, 0, 2, 0,115,
+254, 88, 5,217, 5,240, 0, 15, 0, 25, 0, 0, 5, 17, 35, 17, 38, 39, 38, 16, 0, 33, 32, 0, 17, 16, 7, 6, 2, 32, 0, 17,
+ 16, 0, 32, 0, 17, 16, 3,132,184,252,160,189, 1,121, 1, 59, 1, 58, 1,120,188,159,123,254, 72,254,253, 1, 3, 1,184, 1,
+ 1, 24,254,112, 1,144, 26,179,210, 2,196, 1,165,254, 91,254,158,254,159,210,179, 5, 73,254,184,254,229,254,230,254,184, 1,
+ 72, 1, 26, 1, 27, 0, 0, 0, 0, 2, 0,113,254, 86, 4,117, 4,123, 0, 10, 0, 27, 0, 0, 1, 34, 6, 16, 22, 51, 50, 54,
+ 53, 52, 38, 3, 17, 35, 17, 38, 39, 38, 17, 16, 0, 51, 50, 0, 17, 16, 7, 6, 2,115,148,172,171,149,147,172,172, 57,170,190,
+107,137, 1, 17,241,240, 1, 18,137,106, 3,223,231,254,110,231,232,200,199,233,252, 9,254,110, 1,146, 27,125,156, 1, 19, 1,
+ 20, 1, 56,254,200,254,236,254,237,156,123, 0, 0, 1, 0,139,254, 82, 4,171, 5,213, 0, 36, 0, 0, 1, 32, 7, 6, 17, 16,
+ 23, 22, 51, 50, 23, 22, 21, 20, 7, 6, 35, 52, 53, 22, 55, 54, 53, 52, 39, 38, 35, 32, 39, 38, 17, 16, 55, 54, 41, 1, 21, 3,
+ 70,254,243, 96,123, 91,109,200,122, 89, 84, 74, 80,163, 69, 42, 32, 32, 31, 58,254,192,142,149,185,138, 1,120, 1,101, 5, 43,
+119,152,254,205,254,181,127,152, 84, 79,120,115, 80, 87, 75, 76, 5, 44, 35, 37, 53, 44, 42,203,214, 1,101, 1, 78,237,177,170,
+ 0, 1, 0,113,254, 82, 4, 81, 4, 97, 0, 34, 0, 0, 1, 34, 7, 6, 21, 20, 22, 51, 50, 23, 22, 21, 20, 7, 6, 35, 52, 53,
+ 22, 55, 54, 53, 52, 39, 38, 35, 34, 0, 17, 52, 55, 54, 5, 33, 21, 2,172,216, 62, 99,198,110,131, 80, 84, 74, 80,163, 69, 42,
+ 32, 32, 32, 57,204,254,214,151,104, 1, 52, 1,173, 3,168, 72,113,192,205,227, 76, 79,120,115, 80, 87, 75, 76, 5, 44, 35, 37,
+ 53, 44, 42, 1, 62, 1, 14,243,188,131, 1,184,255,255, 0,201, 0, 0, 4, 35, 5,213, 18, 6, 0, 41, 0, 0, 0, 1,255, 64,
+254, 86, 3, 70, 6, 20, 0, 35, 0, 0, 51, 17, 52, 55, 54, 51, 50, 22, 23, 21, 46, 1, 35, 34, 7, 6, 21, 17, 33, 21, 33, 17,
+ 20, 7, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 55, 54,238,136, 96,169, 49, 99, 51, 36, 82, 44,120, 58, 75, 1, 65,254,191,139,
+ 98,173, 57,102, 46, 49,100, 48, 87, 64, 82, 4,130,160,142,100, 18, 18,164, 28, 29, 62, 81,111,254,201,143,253, 63,146,165,115,
+ 21, 22,164, 31, 33, 75, 95, 0, 0, 1, 0,179,255,252, 4,212, 5,213, 0, 23, 0, 0, 1, 3, 1, 3, 6, 23, 22, 55, 21, 34,
+ 39, 38, 55, 19, 1, 19, 54, 39, 38, 7, 53, 50, 23, 22, 2, 54,110, 3, 12,234, 39, 27, 66,131,230, 81, 95, 19,154,253, 6,172,
+ 39, 27, 66,131,230, 81, 95, 4,135,254, 91, 1,126,253, 44, 96, 42,108, 35,189, 70, 82,182, 1,218,254,145, 2,144, 96, 42,108,
+ 35,189, 70, 82, 0, 1, 0,191, 0, 0, 4,136, 6, 19, 0, 7, 0, 0, 9, 1, 35, 19, 33, 1, 51, 3, 4,136,254,231,184,226,
+253, 38, 1, 25,184,226, 3,112,252,144, 2,198, 3, 77,253, 93, 0, 1, 0,114,254, 86, 6, 96, 5,241, 0, 33, 0, 0, 1, 17,
+ 35, 17, 6, 7, 53, 54, 5, 4, 19, 18, 17, 16, 3, 35, 0, 17, 16, 39, 6, 7, 6, 23, 17, 35, 54, 17, 52, 63, 1, 38, 37, 38,
+ 2, 81,170,205,104,208, 1,130, 1,217,237,214,246,225, 1, 4, 82, 56,121, 69, 5,205, 2,182,187,208,254,164, 48, 5, 58,253,
+140, 2, 73, 75,105,198,215, 8, 10,254,216,254,241,253,189,254, 88,254,146, 1, 76, 1,202, 1,209,125, 32, 92, 52,208,253,198,
+ 33, 2, 20,247,143,141,249, 11, 1, 0, 0, 0, 0, 1, 0,119,254,144, 4,150, 4,120, 0, 22, 0, 0, 1, 3, 35, 1, 38, 39,
+ 1, 35, 1, 38, 39, 38, 35, 53, 32, 23, 22, 19, 18, 17, 35, 16, 39, 3,110,239,185, 1,100, 14, 50,254, 70,185, 2, 31, 98, 46,
+188,211, 1, 45,242,224,172,116,168, 96, 1, 52,254,204, 1,192, 35, 77,253,208, 2,176,127, 33,132,164,216,200,254, 80,254,223,
+254,137, 1, 94,246, 0, 0, 0, 0, 1, 0,115,254, 75, 7, 5, 5,213, 0, 61, 0, 0, 1, 52, 3, 38, 39, 35, 22, 19, 22, 21,
+ 16, 7, 6, 35, 34, 39, 38, 61, 1, 35, 21, 20, 7, 6, 35, 34, 39, 38, 17, 52, 55, 18, 55, 35, 6, 7, 2, 21, 16, 23, 22, 51,
+ 50, 55, 54, 55, 22, 23, 22, 23, 6, 7, 6, 7, 23, 54, 55, 36, 55, 54, 55, 54, 7, 5,100, 56, 95,250, 84,135, 67, 71, 65,134,
+116, 70, 70,199, 71, 72,114,125, 73, 72, 67,135, 84,249, 93, 59,100,123,121,211,146,101,100, 39, 39,100, 68,103,164,205,121,138,
+ 97,140,118, 1, 20,180,219, 68, 61, 2,224,194, 1, 21,156,130, 70,254,191,159,183,254,217,119,109,105,104,198,241,241,198,104,
+105,109,107, 1, 51,183,159, 1, 65, 70,127,159,254,242,201,254,104,180,177, 94, 94,173,173, 94, 65, 23,128, 81, 48, 24,133, 23,
+ 42,100,136,166,230,203, 0, 0, 0, 1, 0,135,254, 85, 6, 40, 4, 96, 0, 37, 0, 0, 33, 36, 3, 2, 33, 32, 17, 52, 19, 51,
+ 2, 21, 2, 23, 22, 3, 51, 2, 55, 54, 17, 52, 3, 51, 18, 21, 22, 7, 6, 7, 6, 7, 6, 7, 39, 54, 55, 54, 4,136,254,237,
+ 30, 35,254,242,254, 97,135,218,143, 1,223,208, 5,170, 3,206,222,143,218,135, 1, 57,105,197,154,210,107,112, 91, 81,139,199,
+ 1, 1, 13,254,242, 2, 53,235, 1, 64,254,192,240,254,151, 1, 1, 1,212,254, 43, 2, 2, 1,104,240, 1, 64,254,192,235,209,
+132,244,158,123, 73, 37, 16,108, 11, 43, 63, 0, 0, 1, 0,115,254, 86, 5, 72, 5,240, 0, 29, 0, 0, 1, 6, 7, 6, 17, 20,
+ 23, 22, 51, 50, 55, 54, 25, 1, 51, 17, 35, 17, 6, 7, 6, 35, 32, 39, 38, 17, 16, 19, 54, 37, 2,236,180, 96,133,110, 98,195,
+196, 98, 99,217,217, 68,104,104,170,255, 0,156,162,186,151, 1, 40, 5, 74, 18,132,185,254,238,249,171,152,152,153, 1, 11, 2,
+236,248,129, 2,144,132, 64, 63,213,221, 1, 71, 1, 54, 1, 8,213, 1, 0, 0, 0, 1, 0,113,254, 86, 4,140, 4,123, 0, 26,
+ 0, 0, 1, 6, 7, 6, 21, 20, 23, 22, 32, 54, 53, 17, 51, 17, 35, 17, 14, 1, 35, 34, 39, 38, 53, 52, 55, 54, 51, 2,139,154,
+ 80,114, 94, 83, 1, 76,168,184,184, 58,177,144,218,133,137,158,127,253, 3,253, 14, 99,141,208,189,129,116,231,203, 2, 49,249,
+246, 2, 82,100, 97,162,168,248,236,200,162, 0, 0, 1, 0,201,254, 75, 5,226, 5,213, 0, 37, 0, 0, 1, 32, 23, 22, 17, 20,
+ 7, 6, 7, 6, 7, 6, 7, 39, 54, 55, 54, 55, 54, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 21, 17, 35, 17, 51, 17, 54, 55, 54,
+ 3, 76, 1, 39,177,190, 60, 67,170,195,241,185, 73, 97,134,125,217,152,136, 44, 54,126,115,205,203,115,113,202,202, 78,105,105,
+ 4,123,179,194,254,253,204,161,178,128,147, 69, 53, 12,133, 22, 50, 87,122,109,104,127,192,157,150,134,129,126,222,254, 39, 5,
+213,253,154,135, 66, 67, 0, 0, 0, 2, 0, 45,255,227, 4,146, 4,154, 0, 23, 0, 77, 0, 0, 1, 38, 35, 34, 7, 6, 7, 6,
+ 7, 6, 21, 20, 23, 22, 23, 22, 23, 22, 51, 50, 55, 54, 55, 54, 37, 22, 21, 20, 7, 6, 33, 34, 39, 38, 35, 34, 7, 39, 54, 51,
+ 50, 23, 22, 51, 50, 55, 54, 53, 52, 39, 6, 7, 6, 7, 6, 39, 38, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 51,
+ 50, 23, 54, 55, 23, 6, 3, 44,127,141, 31, 55, 29, 37, 29, 16, 14, 12, 15, 24, 26, 35, 32, 30, 25, 71, 59, 73, 36, 1, 11,108,
+127,111,254,247,141, 99, 75, 53, 65, 81, 84,135, 95,130, 82, 63, 91,157, 79, 75, 49, 27, 31, 70,117,102, 71, 41, 72, 50, 64, 48,
+ 41, 30, 29, 31, 46, 62, 80,101, 94,210,144, 56, 42,136, 55, 3, 68,152, 22, 11, 33, 26, 32, 27, 33, 32, 21, 28, 17, 20, 6, 5,
+ 25, 20, 49, 24, 50,192,212,176,156,136, 46, 35, 65,147, 76, 46, 35, 94, 89,127,140,113, 25, 23, 52, 43, 38, 2, 1, 10, 7, 34,
+ 26, 72, 52, 66, 59, 59, 61, 47, 63, 34, 43,159, 86,104, 80,146, 0, 1, 0, 79,254, 86, 5, 11, 5,246, 0, 33, 0, 0, 5, 4,
+ 33, 32, 1, 0, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 7, 35, 54, 55, 54, 33, 32, 23, 22, 21, 20, 7, 0, 1, 22, 51, 32, 55,
+ 4,250,255, 0,254,237,254,175,254,185, 2,186,179,108,108, 99,164,180, 94, 35, 24,240, 44, 86,163, 1, 24, 1, 19,161,162,162,
+254,247,254, 24,156,213, 1, 41,232,236,190, 1,163, 1,241,219,132,156,141,101, 93,146, 54, 63,161,102,194,144,145,241,216,182,
+254,242,254,133,181,179, 0, 0, 0, 1, 0,100,254, 86, 4,106, 4,123, 0, 32, 0, 0, 1, 6, 35, 32, 1, 0, 55, 54, 53, 52,
+ 39, 38, 35, 34, 7, 6, 7, 35, 54, 55, 54, 51, 50, 4, 21, 20, 7, 6, 1, 22, 51, 50, 55, 4, 92,218,234,254,238,254,222, 2,
+ 66,167, 92, 92, 84,139,153, 80, 30, 20,204, 37, 73,139,238,232, 1, 20,138,175,254, 47,145,169,253,197,254,239,153, 1,121, 1,
+ 89,194,107,125,111, 83, 75,117, 44, 50,129, 82,156,232,194,164,156,197,254,224,186,144, 0, 0, 0, 2, 0,115, 0, 0, 5,182,
+ 5,239, 0, 2, 0, 53, 0, 0, 37, 33, 9, 3, 38, 39, 38, 35, 34, 15, 1, 53, 54, 55, 54, 51, 50, 23, 22, 23, 9, 1, 54, 55,
+ 54, 51, 50, 23, 22, 23, 21, 39, 38, 35, 34, 7, 6, 7, 9, 1, 22, 23, 22, 59, 1, 21, 33, 53, 51, 50, 55, 54, 1,218, 2,110,
+254,205,254, 20, 1,128,254,220, 19, 26, 34, 63, 25, 22, 69, 33, 32, 31, 28,114, 75, 44, 47, 1, 2, 1, 9, 52, 39, 75,114, 29,
+ 30, 32, 33, 68, 23, 24, 60, 38, 19, 26,254,210, 1,116, 6, 7, 29, 69, 71,250,195, 71, 72, 26, 12,170, 1,202,254,104, 2, 61,
+ 1,187, 29, 26, 34, 4, 10,187, 11, 5, 5, 67, 40, 70,254,129, 1,127, 75, 35, 67, 5, 5, 11,187, 10, 4, 34, 17, 38,254, 69,
+253,195, 9, 8, 33,170,170, 33, 15, 0, 0, 0, 0, 3, 0, 54, 0, 0, 4,203, 4,123, 0, 0, 0, 3, 0, 54, 0, 0, 37, 41,
+ 1, 3, 9, 1, 3, 38, 39, 38, 35, 34, 15, 1, 53, 54, 55, 54, 51, 50, 23, 22, 23, 27, 1, 54, 55, 54, 51, 50, 23, 22, 23, 21,
+ 39, 38, 35, 34, 7, 6, 7, 3, 1, 22, 23, 22, 59, 1, 21, 33, 53, 51, 50, 55, 54, 4,203,252,207, 1,204,228,254, 91, 1, 57,
+239, 21, 17, 29, 54, 21, 19, 58, 28, 27, 26, 24,131, 64, 37, 40,197,197, 40, 37, 64,131, 24, 26, 27, 28, 58, 19, 21, 54, 29, 17,
+ 21,246, 1, 45, 6, 5, 25, 58, 73,251,107, 73, 58, 25, 5,158, 1, 56,254,238, 1,164, 1, 61, 28, 14, 25, 3, 7,141, 8, 4,
+ 4, 51, 30, 53,254,250, 1, 6, 53, 30, 51, 4, 4, 8,141, 7, 3, 25, 14, 28,254,184,254,103, 8, 5, 25,158,158, 25, 5, 0,
+ 0, 2, 0,115,255,227, 5, 37, 6, 16, 0, 29, 0, 43, 0, 0, 1, 36, 7, 6, 7, 54, 55, 54, 51, 50, 0, 16, 0, 33, 32, 39,
+ 38, 17, 16, 55, 54, 33, 50, 55, 54, 55, 21, 6, 7, 6, 18, 16, 38, 35, 34, 7, 6, 21, 20, 23, 22, 51, 50, 55, 3, 42,254,214,
+ 87, 56, 22, 81, 85,123,130,245, 1, 50,254,206,254,249,254,206,164,163,139,124, 1,176,115,149,160, 75, 94,151,108,142,200,186,
+188,104,105,105,101,191,188, 98, 5, 45, 2,115, 74,160, 86, 34, 49,254,188,253,240,254,188,156,155, 1, 80, 1,222,210,187, 10,
+ 10, 39,177, 36, 8, 6,252, 65, 1,130,230,115,116,192,189,120,115,115, 0, 0, 0, 2, 0,113,255,227, 4, 91, 6, 16, 0, 31,
+ 0, 47, 0, 0, 1, 38, 7, 6, 7, 54, 55, 54, 51, 50, 23, 22, 16, 7, 6, 35, 34, 39, 38, 17, 16, 55, 54, 33, 50, 55, 54, 55,
+ 21, 6, 7, 6, 19, 52, 39, 38, 35, 34, 7, 6, 21, 20, 23, 22, 51, 50, 55, 54, 2,155,227, 73, 44, 20, 41,101, 91,120,204,127,
+128,128,127,219,255,137,136,116,103, 1, 79, 95, 92, 83, 71, 93, 69, 90,168, 83, 84,146,149, 86, 88, 88, 84,151,148, 82, 83, 5,
+ 55, 2,120, 74,169, 70, 54, 49,162,162,253,240,162,162,156,155, 1, 80, 1,222,210,187, 10, 10, 39,167, 39, 5, 6,252,248,205,
+114,115,115,116,203,199,120,115,115,116, 0, 0, 0, 1, 0, 44,254, 86, 4,183, 5,213, 0, 15, 0, 0, 1, 17, 35, 53, 33, 17,
+ 35, 17, 33, 21, 35, 17, 33, 17, 51, 17, 4,183,203,254,235,203,254,235,203, 1,224,203, 4, 96,254,242,100,250,160, 5, 96,100,
+ 1, 14, 1,117,254,139, 0, 0, 0, 1, 0, 55,254, 85, 4, 20, 5,207, 0, 15, 0, 0, 1, 17, 35, 53, 35, 17, 35, 17, 35, 21,
+ 35, 17, 33, 17, 51, 17, 4, 20,173,229,185,229,173, 1,146,185, 4, 95,255, 0,112,250,134, 5,122,112, 1, 0, 1,112,254,144,
+ 0, 1, 0,111,255,242, 4,206, 4,103, 0, 43, 0, 0, 1, 2, 7, 6, 39, 38, 55, 54, 55, 54, 39, 38, 35, 34, 7, 53, 54, 23,
+ 22, 23, 22, 7, 55, 18, 55, 54, 23, 22, 7, 6, 7, 6, 23, 22, 51, 50, 55, 21, 6, 39, 38, 39, 38, 55, 2, 40, 96,200,141, 3,
+ 1, 61, 96,136, 91, 43, 26,142, 57, 91, 82,126,246, 33, 19, 42,189, 96,200,141, 3, 1, 61, 96,136, 91, 43, 26,142, 57, 91, 82,
+126,246, 33, 19, 42, 1,153,254,247,124, 89,145, 68, 84,132,124,203,169,104,108,224, 61, 17, 32,240,140,112,108, 1, 9,124, 89,
+145, 68, 84,132,124,203,169,104,108,224, 61, 17, 32,240,140,112, 0, 2, 0,183,254, 86, 4,164, 4,123, 0, 21, 0, 29, 0, 0,
+ 19, 54, 55, 54, 55, 54, 51, 50, 0, 16, 2, 35, 34, 38, 39, 18, 41, 1, 21, 33, 32, 19, 36, 16, 38, 32, 6, 16, 22, 32,186, 2,
+ 88, 61,151, 59,182,204, 0,255,255,204,123,177, 58, 5, 1, 32, 1,244,254, 28,254, 10, 6, 3, 45,167,254,220,167,167, 1, 36,
+ 2, 37,204,167,102, 90, 35,254,188,253,240,254,188, 97,100,254, 88,170, 2,218, 52, 1,150,231,231,254,106,231,255,255, 0,113,
+255,227, 3,231, 4,123, 18, 6, 0, 70, 0, 0,255,255,255,219,254, 86, 1,121, 6, 20, 18, 6, 0, 77, 0, 0, 0, 3, 0,115,
+255,227, 5,217, 5,240, 0, 7, 0, 15, 0, 26, 0, 0, 1, 33, 18, 23, 22, 32, 55, 54, 19, 38, 39, 38, 32, 7, 6, 7, 1, 32,
+ 0, 17, 16, 0, 33, 32, 0, 16, 0, 5, 3,252, 69, 8,122,129, 1,184,129,119, 1, 22, 98,129,254, 72,129, 96, 25, 1,214, 1,
+ 58, 1,120,254,136,254,198,254,197,254,135, 1,121, 2,198,254,255,154,164,164,153, 1,172,186,126,164,164,121,191, 2,128,254,
+ 91,254,158,254,159,254, 91, 1,164, 2,196, 1,165, 0, 0, 0, 0, 1, 0,113,255,227, 3,216, 4,123, 0, 33, 0, 0, 1, 38,
+ 39, 38, 35, 34, 7, 6, 7, 33, 21, 33, 22, 23, 22, 51, 50, 63, 1, 21, 7, 6, 35, 32, 39, 38, 16, 55, 54, 33, 50, 23, 22, 23,
+ 3,216, 37, 37, 99,106,183,102, 95, 18, 2,165,253, 91, 18, 95,102,183,128, 77, 74, 79,104,107,254,244,156,157,157,156, 1, 12,
+101,110, 40, 39, 3,174, 13, 10, 26, 99, 92,169,144,169, 92, 99, 26, 25,167, 18, 22,156,156, 2, 40,156,156, 22, 8, 12, 0, 0,
+ 0, 1, 0,196,255,227, 4, 43, 4,123, 0, 33, 0, 0, 19, 53, 54, 55, 54, 51, 32, 23, 22, 16, 7, 6, 33, 34, 47, 1, 53, 23,
+ 22, 51, 50, 55, 54, 55, 33, 53, 33, 38, 39, 38, 35, 34, 7, 6,196, 39, 40,110,101, 1, 12,156,157,157,156,254,244,107,104, 79,
+ 74, 77,128,183,102, 95, 18,253, 91, 2,165, 18, 95,102,183,106, 99, 37, 3,174,163, 12, 8, 22,156,156,253,216,156,156, 22, 18,
+167, 25, 26, 99, 92,169,144,169, 92, 99, 26, 10,255,255, 0,201, 0, 0, 4,141, 5,213, 18, 6, 0,160, 0, 0,255,255, 0,186,
+254, 86, 4,164, 6, 20, 18, 6, 0,192, 0, 0,255,255, 0,115,255,227, 5, 39, 5,240, 18, 6, 0, 38, 0, 0, 0, 1, 0,201,
+ 0, 0, 6, 31, 5,213, 0, 12, 0, 0, 19, 33, 9, 1, 33, 17, 35, 17, 1, 35, 1, 17, 35,201, 1, 45, 1,125, 1,127, 1, 45,
+197,254,127,203,254,127,196, 5,213,254, 33, 1,223,250, 43, 5, 31,254, 25, 1,231,250,225, 0, 0, 1, 0,127,254, 86, 4,179,
+ 4, 96, 0, 12, 0, 0, 19, 33, 19, 1, 33, 17, 35, 17, 1, 35, 1, 17, 35,127, 1, 27,254, 1, 0, 1, 27,185,254,236,153,254,
+235,185, 4, 96,254,123, 1,133,251,160, 3,178,254, 96, 1,160,250,164, 0, 0, 0, 2, 0, 85,254, 86, 4,164, 4,123, 0, 24,
+ 0, 32, 0, 0, 23, 17, 52, 55, 54, 55, 54, 51, 50, 0, 16, 2, 35, 34, 38, 39, 17, 33, 21, 33, 21, 35, 53, 35, 53, 0, 16, 38,
+ 32, 6, 16, 22, 32,186, 90, 61,151, 59,182,204, 0,255,255,204,123,177, 58, 1,229,254, 27,185,101, 3,144,167,254,220,167,167,
+ 1, 36,144, 2,181,231,140,102, 90, 35,254,188,253,240,254,188, 97,100,254,200,170,112,112,170, 1,244, 1,150,231,231,254,106,
+231, 0, 0, 0,255,255, 0,115,255,227, 5, 39, 5,240, 18, 6, 1, 72, 0, 0,255,255, 0,115,255,227, 5, 39, 5,240, 18, 38,
+ 3, 22, 0, 0, 16, 7, 0,121, 2, 51, 0, 0,255,255, 0,115,255,227, 5, 39, 5,240, 16, 39, 0,121, 0,228, 0, 0, 18, 6,
+ 3, 26, 0, 0,255,255, 0,201, 0, 0, 4,139, 5,213, 18, 38, 3, 50, 0, 0, 16, 7, 6,135, 4,238, 1,117,255,255, 0,201,
+ 0, 0, 4,139, 5,213, 18, 38, 3, 50, 0, 0, 16, 7, 6,132, 4,229, 1,117, 0, 1,255,250,254,102, 5,172, 5,213, 0, 29,
+ 0, 0, 37, 16, 6, 43, 1, 53, 51, 50, 55, 54, 53, 17, 52, 38, 35, 33, 17, 35, 17, 33, 53, 33, 21, 33, 17, 33, 50, 23, 22, 21,
+ 5,172,204,228, 76, 62,134, 56, 55,124,124,254,136,203,254, 82, 4,139,253,238, 1,161,186,113,109,104,254,242,244,170, 75, 75,
+194, 1, 34,159,158,253, 57, 5, 43,170,170,254, 70,119,114,238,255,255, 0,201, 0, 0, 4,106, 5,213, 18, 38, 3, 48, 0, 0,
+ 16, 7, 6,133, 4,174, 1,117, 0, 1, 0,115,255,227, 5, 39, 5,240, 0, 36, 0, 58, 64, 32, 36,149, 35,173, 37, 26,161, 25,
+174, 30,149, 21,145, 37, 8,161, 9,174, 4,149, 13,140, 37, 38, 35, 25, 8, 34, 0, 25, 17, 37, 16,220,236, 50,212, 60,204,204,
+ 49, 0, 16,244,236,244,236, 16,244,236,244,236, 16,244,236, 48, 1, 18, 23, 22, 33, 50, 55, 54, 55, 21, 6, 7, 6, 35, 32, 39,
+ 38, 17, 16, 55, 54, 33, 50, 23, 22, 23, 21, 38, 39, 38, 35, 32, 7, 6, 7, 33, 21, 1, 72, 7,129,136, 1, 0,130,116,115,102,
+106,119,118,132,254,173,195,195,195,195, 1, 83,134,118,119,104,102,115,116,130,255, 0,136,103, 25, 2,178, 2,199,254,242,147,
+157, 47, 47, 95,211, 72, 36, 36,207,208, 1,103, 1,104,207,208, 36, 35, 71,213, 95, 47, 47,156,119,198,170, 0,255,255, 0,135,
+255,227, 4,162, 5,240, 18, 6, 0, 54, 0, 0,255,255, 0,201, 0, 0, 1,147, 5,213, 18, 6, 0, 44, 0, 0,255,255, 0,201,
+ 0, 0, 1,147, 5,213, 18, 38, 3, 35, 0, 0, 17, 7, 6,132, 3, 47, 1,117, 0, 8,180, 0, 10, 7, 1, 7, 43, 49, 0, 0,
+255,255,255,150,254,102, 1,147, 5,213, 18, 6, 0, 45, 0, 0, 0, 2, 0, 54,255,227, 8, 47, 5,213, 0, 22, 0, 33, 0, 0,
+ 1, 33, 21, 16, 3, 6, 5, 53, 54, 55, 18, 25, 1, 33, 17, 51, 50, 4, 21, 20, 4, 35, 33, 1, 52, 39, 38, 43, 1, 17, 51, 50,
+ 55, 54, 4,112,254, 27,132, 98,254,145,212, 67,117, 3,120,234,251, 1, 16,254,240,251,254, 76, 2,234, 79, 78,163,224,224,161,
+ 80, 79, 5, 43,213,254, 24,254,170,253, 56,167, 46,168, 1, 37, 2, 53, 1, 27,253,154,218,222,221,218, 1,183,139, 68, 67,253,
+221, 68, 67, 0, 0, 2, 0,201, 0, 0, 7,204, 5,213, 0, 18, 0, 29, 0, 0, 33, 17, 33, 17, 35, 17, 51, 17, 33, 17, 51, 17,
+ 51, 50, 4, 21, 20, 4, 35, 1, 52, 39, 38, 43, 1, 17, 51, 50, 55, 54, 4, 13,253,134,202,202, 2,122,202,234,251, 1, 16,254,
+240,251, 1, 54, 79, 78,163,224,224,161, 80, 79, 2,199,253, 57, 5,213,253,156, 2,100,253,154,218,222,221,218, 1,183,139, 68,
+ 67,253,221, 68, 67, 0, 0, 0, 0, 1,255,250, 0, 0, 5,172, 5,213, 0, 20, 0, 0, 1, 50, 23, 22, 21, 17, 35, 17, 52, 38,
+ 35, 33, 17, 35, 17, 33, 53, 33, 21, 33, 17, 4, 20,186,113,109,201,124,124,254,136,203,254, 82, 4,139,253,238, 3,113,119,114,
+238,254,102, 1,138,159,158,253, 57, 5, 43,170,170,254, 70, 0,255,255, 0,201, 0, 0, 5,106, 5,213, 18, 38, 3, 55, 0, 0,
+ 16, 7, 6,133, 4,238, 1,117,255,255, 0,201, 0, 0, 5, 51, 5,213, 18, 38, 3, 53, 0, 0, 16, 7, 6,135, 4,229, 1,117,
+255,255, 0, 35,255,227, 4,189, 5,213, 16, 39, 6,139, 4,114, 1,117, 18, 6, 3, 64, 0, 0, 0, 1, 0,201,254, 86, 5, 59,
+ 5,213, 0, 11, 0, 0, 41, 1, 17, 51, 17, 33, 17, 51, 17, 33, 17, 35, 2,188,254, 13,202, 2,222,202,254, 74,201, 5,213,250,
+213, 5, 43,250, 43,254, 86, 0,255,255, 0, 16, 0, 0, 5,104, 5,213, 18, 6, 0, 36, 0, 0, 0, 2, 0,201, 0, 0, 4,236,
+ 5,213, 0, 10, 0, 23, 0, 44, 64, 24, 13,149, 23,129, 22, 5,149, 14,173, 6,149, 22, 25, 11, 0, 25, 18, 46, 5, 13, 28, 23,
+ 4, 24, 16,252,236, 50,244,236,196,204, 49, 0, 47,236,244,236, 16,244,236, 48, 1, 52, 39, 38, 35, 33, 17, 33, 50, 55, 54, 17,
+ 21, 33, 17, 33, 50, 4, 21, 20, 4, 35, 33, 17, 4, 23, 79, 78,163,254,188, 1, 68,163, 78, 79,253,124, 1, 78,251, 1, 16,254,
+240,251,253,232, 1,183,139, 68, 67,253,221, 68, 67, 4,168,166,254, 64,218,222,221,218, 5,213,255,255, 0,201, 0, 0, 4,236,
+ 5,213, 18, 6, 0, 37, 0, 0, 0, 1, 0,201, 0, 0, 4,106, 5,213, 0, 5, 0, 25, 64, 12, 4,149, 1,129, 0, 7, 2, 4,
+ 28, 1, 4, 6, 16,252,252,204,196, 49, 0, 47,244,236, 48, 51, 17, 33, 21, 33, 17,201, 3,161,253, 41, 5,213,170,250,213, 0,
+ 0, 2, 0, 49,254, 86, 6, 3, 5,213, 0, 7, 0, 23, 0, 53, 64, 15, 2, 28, 14, 25, 19, 28, 16, 23, 3, 28, 13, 20, 28, 23,
+ 24, 16,220,236,212,236, 16,212,236,204,212,236, 49, 0, 64, 12, 3,149, 13,129, 18, 22,189, 15, 0, 23,149, 20, 47,236, 50, 50,
+236, 50,244,236, 48, 37, 33, 17, 33, 21, 16, 3, 6, 5, 54, 55, 18, 25, 1, 33, 17, 51, 17, 35, 17, 33, 17, 35, 17, 1,200, 2,
+168,254, 27,132, 24,254,168,132, 50,117, 3,120,201,201,251,192,201,170, 4,129,212,254, 17,254,177, 61, 50, 57,126, 1, 37, 2,
+ 53, 1, 26,250,213,253,172, 1,170,254, 86, 2, 84, 0, 0, 0,255,255, 0,201, 0, 0, 4,139, 5,213, 18, 6, 0, 40, 0, 0,
+ 0, 1, 0, 59, 0, 0, 6,173, 5,213, 0, 21, 0,110, 64, 22, 66, 2, 20, 16,129, 14, 8, 12,149, 0, 18,173, 6, 10, 14, 23,
+ 8, 21, 28, 11, 20, 22, 16,212, 60,252, 60,196, 49, 0, 47, 60, 60,244, 60,236, 50, 16,244, 60, 60, 48, 75, 83, 88, 64, 36, 4,
+ 17, 7, 2, 1, 5, 17, 6, 7, 6, 4, 17, 1, 3, 17, 2, 2, 1, 15, 17, 18, 13, 12, 16, 17, 17, 18, 17, 15, 17, 12, 14, 17,
+ 13, 13, 12, 5, 7, 16,236, 16,236, 7, 16,236, 8, 16,236, 5, 7, 16,236, 16,236, 7, 16,236, 8, 16,236, 89, 1, 51, 1, 51,
+ 9, 1, 35, 1, 35, 17, 35, 17, 35, 1, 35, 9, 1, 51, 1, 51, 17, 51, 3,217,149, 1, 52,217,254,162, 1,144,217,254,155,150,
+202,150,254,155,217, 1,144,254,162,217, 1, 52,149,202, 3,113, 2,100,253, 71,252,228, 2,199,253, 57, 2,199,253, 57, 3, 28,
+ 2,185,253,156, 2,100, 0, 0,255,255, 0,156,255,227, 4,115, 5,240, 18, 6, 0, 22, 0, 0, 0, 1, 0,201, 0, 0, 5, 51,
+ 5,213, 0, 9, 0,121, 64, 30, 3, 17, 9, 9, 8, 8, 17, 4, 4, 3, 66, 8, 3, 9, 6,175, 2, 5, 9, 4, 7, 3, 28, 0,
+ 54, 7, 28, 6, 4, 10, 16,252,236,252,236, 17, 57, 57, 49, 0, 47, 60,236, 50, 57, 57, 48, 75, 83, 88, 7, 16, 4,237, 7, 16,
+ 4,237, 89, 34,178, 31, 11, 1, 1, 93, 64, 48, 54, 8, 56, 3, 72, 8, 71, 3,105, 8,102, 3,128, 8, 7, 6, 4, 9, 9, 21,
+ 4, 26, 9, 70, 4, 73, 9, 87, 4, 88, 9,101, 4,105, 9,121, 9,133, 4,138, 9,149, 4,154, 9,159, 11, 16, 93, 0, 93, 1,
+ 17, 35, 17, 1, 33, 17, 51, 17, 1, 5, 51,196,253,106,254,240,196, 2,150, 5,213,250, 43, 4,225,251, 31, 5,213,251, 31, 4,
+225, 0, 0, 0,255,255, 0,201, 0, 0, 5, 51, 5,213, 16, 39, 6,139, 4,245, 1,117, 18, 6, 3, 53, 0, 0,255,255, 0,201,
+ 0, 0, 5,106, 5,213, 18, 6, 0, 46, 0, 0, 0, 1, 0, 54,255,228, 5, 58, 5,213, 0, 15, 0, 38, 64, 20, 11,149, 6,129,
+ 9, 1,149, 0,140, 9, 17, 4, 10, 28, 7, 11, 28, 6, 1, 16, 16,212,212,236,212,236,236, 49, 0, 47,244,236, 16,244,236, 48,
+ 23, 53, 54, 55, 18, 25, 1, 33, 17, 35, 17, 33, 21, 16, 3, 6, 54,212, 67,117, 3,120,202,254, 27,132, 98, 28,167, 46,168, 1,
+ 37, 2, 53, 1, 26,250, 43, 5, 43,212,254, 24,254,170,253, 0,255,255, 0,201, 0, 0, 6, 31, 5,213, 18, 6, 0, 48, 0, 0,
+255,255, 0,201, 0, 0, 5, 59, 5,213, 18, 6, 0, 43, 0, 0,255,255, 0,115,255,227, 5,217, 5,240, 18, 6, 0, 50, 0, 0,
+ 0, 1, 0,201, 0, 0, 5, 59, 5,213, 0, 7, 0, 31, 64, 16, 4,149, 7,129, 2, 6, 9, 4, 3, 28, 0, 4, 28, 7, 4, 8,
+ 16,252,236,212,236,236, 49, 0, 47, 60,244,236, 48, 1, 17, 35, 17, 33, 17, 35, 17, 5, 59,202,253, 34,202, 5,213,250, 43, 5,
+ 43,250,213, 5,213, 0, 0, 0,255,255, 0,201, 0, 0, 4,141, 5,213, 18, 6, 0, 51, 0, 0,255,255, 0,115,255,227, 5, 39,
+ 5,240, 18, 6, 0, 38, 0, 0,255,255,255,250, 0, 0, 4,233, 5,213, 18, 6, 0, 55, 0, 0, 0, 1, 0, 35,255,227, 4,189,
+ 5,213, 0, 17, 0, 65, 64, 14, 66, 6,149, 5,140, 16, 13,129, 18, 19, 17, 6, 13, 18, 16,212,196,212,196, 49, 0, 16,228, 50,
+244,236, 48, 75, 83, 88, 64, 18, 15, 17, 0, 13, 12, 16, 17, 17, 17, 0, 15, 17, 12, 14, 17, 13, 13, 12, 5, 7, 16,236, 16,236,
+ 7, 16,236, 8, 16,236, 89, 37, 6, 7, 6, 43, 1, 53, 51, 50, 55, 54, 63, 1, 1, 51, 9, 1, 51, 2,143, 22, 31,103,227, 77,
+ 63,140, 49, 14, 8, 45,254, 33,217, 1,115, 1,117,217,181, 51, 37,122,170, 75, 22, 18,106, 4,107,252,148, 3,108, 0, 0, 0,
+ 0, 3, 0,115, 0, 0, 5,217, 5,213, 0, 8, 0, 17, 0, 39, 0, 59, 64, 31, 17, 0,149, 29, 26, 27,129, 39, 9, 8,149, 37,
+ 18, 39, 41, 16, 13, 25, 33, 18, 0, 27, 28, 37, 17, 28, 4, 25, 22, 16, 40, 16,252,236,212, 60, 60,252, 60, 60,212,236,236, 49,
+ 0, 47,220, 60,236, 50, 16,244,220, 60,236, 50, 48, 1, 6, 7, 6, 21, 20, 23, 22, 23, 51, 54, 55, 54, 53, 52, 39, 38, 39, 3,
+ 38, 39, 38, 17, 16, 55, 54, 55, 53, 51, 21, 22, 23, 22, 17, 16, 7, 6, 7, 21, 35, 2,194,150, 98,130,130, 98,150,202,150, 98,
+128,128, 98,150,202,244,158,189,189,157,245,202,244,157,188,188,157,244,202, 4,142, 21, 87,115,198,197,115, 87, 21, 21, 87,115,
+197,198,115, 87, 21,252, 16, 22,134,160, 1, 15, 1, 15,161,135, 22,159,159, 23,134,161,254,241,254,242,161,134, 23,157, 0, 0,
+255,255, 0, 61, 0, 0, 5, 59, 5,213, 18, 6, 0, 59, 0, 0, 0, 1, 0,201,254, 86, 6, 4, 5,213, 0, 11, 0, 40, 64, 21,
+ 6, 2,129, 11,189, 8, 4,149, 1, 13, 0, 28, 9, 6, 28, 7, 3, 28, 2, 4, 12, 16,252,236,212,236,212,236,204, 49, 0, 47,
+236, 50,236,244, 60, 48, 41, 1, 17, 51, 17, 33, 17, 51, 17, 51, 17, 35, 5, 59,251,142,202, 2,222,202,201,201, 5,213,250,213,
+ 5, 43,250,213,253,172, 0, 0, 0, 1, 0,175, 0, 0, 4,179, 5,213, 0, 16, 0, 35, 64, 18, 2,149, 12,173, 14, 7,129, 0,
+ 18, 4, 1, 14, 28, 15, 8, 28, 7, 17, 16,220,236,212,236, 50,236, 49, 0, 47,228, 50,244,236, 48, 33, 17, 33, 34, 39, 38, 53,
+ 17, 51, 17, 20, 22, 51, 33, 17, 51, 17, 3,232,254, 95,186,113,109,201,124,124, 1,120,203, 2,199,119,114,238, 1, 55,254,217,
+159,158, 2,100,250, 43, 0, 0, 0, 1, 0,201, 0, 0, 7, 57, 5,213, 0, 11, 0, 40, 64, 21, 10, 2, 6,129, 0, 8,149, 5,
+ 13, 4, 2, 28, 3, 10, 28, 11, 7, 28, 6, 4, 12, 16,252,236,212,252,212,236,236, 49, 0, 47,236, 50,244, 60,196, 48, 37, 33,
+ 17, 51, 17, 33, 17, 51, 17, 33, 17, 51, 4,102, 2, 9,202,249,144,202, 2, 9,202,170, 5, 43,250, 43, 5,213,250,213, 4,221,
+ 0, 1, 0,201,254, 86, 8, 2, 5,213, 0, 15, 0, 49, 64, 26, 6, 10, 2,129, 15,189, 12, 8, 4,149, 1, 17, 0, 28, 13, 10,
+ 28, 11, 6, 28, 7, 3, 28, 2, 4, 16, 16,252,236,212,252,212,236,212,236,204, 49, 0, 47,236, 50, 50,236,244, 60,196, 48, 41,
+ 1, 17, 51, 17, 33, 17, 51, 17, 33, 17, 51, 17, 51, 17, 35, 7, 57,249,144,202, 2, 9,202, 2, 9,202,201,201, 5,213,250,213,
+ 4,221,251, 35, 5, 43,250,213,253,172, 0, 0, 0, 2, 0, 50, 0, 0, 6, 24, 5,213, 0, 12, 0, 23, 0, 42, 64, 22, 2,149,
+ 3,129, 0, 18,149, 5,173, 19,149, 0, 16, 13, 25, 9, 18, 4, 28, 1, 3, 24, 16,204,220,236, 50,212,236,204, 49, 0, 47,236,
+244,236, 16,244,236, 48, 33, 17, 33, 53, 33, 17, 33, 50, 4, 21, 20, 4, 35, 1, 52, 39, 38, 35, 33, 17, 33, 50, 55, 54, 1,245,
+254, 61, 2,141, 1, 78,251, 1, 16,254,240,251, 1, 54, 79, 78,163,254,188, 1, 68,161, 80, 79, 5, 43,170,253,154,218,222,221,
+218, 1,183,139, 68, 67,253,221, 68, 67, 0, 0,255,255, 0,201, 0, 0, 6, 70, 5,213, 16, 39, 0, 44, 4,179, 0, 0, 17, 6,
+ 3, 73, 0, 0, 0, 13, 64, 6, 27, 4, 1, 28, 0, 21, 16,220,252,236, 49, 0, 0, 2, 0,201, 0, 0, 4,236, 5,213, 0, 10,
+ 0, 21, 0, 36, 64, 19, 5,149, 13,173, 11,129, 6,149, 21, 23, 0, 25, 17, 5, 12, 28, 11, 4, 22, 16,252,236, 50,212,236,204,
+ 49, 0, 47,236,228,244,236, 48, 1, 52, 39, 38, 35, 33, 17, 33, 50, 55, 54, 1, 51, 17, 33, 50, 4, 21, 20, 4, 35, 33, 4, 23,
+ 79, 78,163,254,188, 1, 68,163, 78, 79,252,178,202, 1, 78,251, 1, 16,254,240,251,253,232, 1,183,139, 68, 67,253,221, 68, 67,
+ 4,168,253,154,218,222,221,218, 0, 1, 0,111,255,227, 5, 35, 5,240, 0, 36, 0, 58, 64, 32, 1,149, 2,173, 37, 11,161, 12,
+174, 7,149, 16,145, 37, 29,161, 28,174, 33,149, 24,140, 37, 38, 0, 3, 25, 20, 2, 29, 12, 37, 16,220, 60,204,212,236, 50,204,
+ 49, 0, 16,244,236,244,236, 16,244,236,244,236, 16,244,236, 48, 1, 33, 53, 33, 38, 39, 38, 33, 34, 7, 6, 7, 53, 54, 55, 54,
+ 51, 32, 23, 22, 17, 16, 7, 6, 33, 34, 39, 38, 39, 53, 22, 23, 22, 51, 32, 55, 54, 4, 78,253, 70, 2,178, 25,103,136,255, 0,
+130,116,115,102,104,119,118,134, 1, 83,195,195,195,195,254,173,132,118,119,106,102,115,116,130, 1, 0,136,129, 2,199,170,198,
+119,156, 47, 47, 95,213, 71, 35, 36,208,207,254,152,254,153,208,207, 36, 36, 72,211, 95, 47, 47,157,147, 0, 0, 0, 2, 0,211,
+255,227, 7,204, 5,240, 0, 15, 0, 38, 0, 56, 64, 31, 0,149, 20,145, 39, 8,149, 28,140, 39, 33,149, 38,173, 36,129, 35, 40,
+ 12, 25, 24, 4, 25, 32, 16, 33, 37, 28, 36, 4, 39, 16,252,236, 50,212, 60,236,212,236,204, 49, 0, 47,228,244,236, 16,244,236,
+ 16,244,236, 48, 1, 34, 7, 6, 17, 16, 23, 22, 51, 50, 55, 54, 17, 16, 39, 38, 1, 18, 55, 54, 33, 32, 23, 22, 17, 16, 7, 6,
+ 33, 32, 39, 38, 3, 35, 17, 35, 17, 51, 17, 5, 26,220,130,129,129,130,220,220,128,129,129,128,252,119, 30,151,189, 1, 59, 1,
+ 58,188,188,188,188,254,198,254,197,189,179, 9,201,202,202, 5, 76,164,164,254,229,254,230,164,164,164,164, 1, 26, 1, 27,164,
+164,254, 37, 1, 5,168,210,210,211,254,158,254,159,210,211,210,200, 1, 74,253, 57, 5,213,253,156, 0, 0, 0, 0, 2, 0, 59,
+ 0, 0, 4,198, 5,213, 0, 19, 0, 28, 0, 69, 64, 22, 66, 21,149, 6,129, 16, 11,149, 27,173, 9, 16, 30, 4, 10, 20, 28, 7,
+ 24, 25, 3, 29, 16,212,236,212,236, 50,236, 49, 0, 47, 60,244,236, 16,244,236, 48, 75, 83, 88, 64, 13, 13, 12, 11, 3, 10, 14,
+ 17, 17, 15, 17, 16, 17, 16, 5, 7, 16,236, 16,236, 17, 23, 57, 89, 1, 46, 1, 53, 52, 54, 41, 1, 17, 35, 17, 35, 34, 6, 7,
+ 3, 35, 19, 62, 1, 1, 35, 34, 6, 21, 20, 22, 59, 1, 2, 2,125,131,252, 1, 0, 1,200,202,220,120,139, 74,191,217,205, 62,
+123, 2, 59,254,146,149,149,146,254, 2,188, 36,186,141,216,214,250, 43, 2,119, 98,150,254,129, 1,152,126,144, 2,137,133,131,
+131,135, 0, 0,255,255, 0,123,255,227, 4, 45, 4,123, 18, 6, 0, 68, 0, 0, 0, 2, 0,113,255,227, 4,117, 5,240, 0, 28,
+ 0, 45, 0, 73, 64, 40, 29, 22, 44,185, 6, 46, 0,134, 28,136, 2,185, 26, 46, 37,185, 14,140, 46, 29, 40, 22, 33, 4, 47, 69,
+ 28, 40, 18, 10, 81, 18, 4, 18, 24, 33, 18, 18, 69, 46, 16,252,236,212,236, 16,244,236,196,236, 17, 18, 57, 18, 57, 49, 0, 16,
+244,236, 16,212,236,244,236, 16,212,236, 57, 57, 48, 1, 38, 35, 34, 21, 20, 5, 22, 23, 22, 17, 16, 7, 6, 35, 34, 39, 38, 17,
+ 52, 55, 54, 55, 38, 53, 16, 33, 50, 23, 1, 6, 7, 6, 21, 20, 23, 22, 51, 50, 54, 53, 52, 39, 38, 39, 38, 3,236,102,239,253,
+ 1, 8,208,117,142,137,137,240,239,138,137,137, 53, 75,156, 1,185,221,120,254, 24, 68, 55, 86, 85, 86,149,147,172, 91, 97,126,
+ 64, 5, 17, 70,117, 92, 48, 37,112,135,254,235,254,247,156,157,157,156, 1, 19,204,165, 64, 36, 79,141, 1, 16, 70,254, 40, 29,
+ 73,113,204,203,114,115,232,190,199, 96,103, 11, 6, 0, 0, 0, 0, 3, 0,186, 0, 0, 4, 62, 4, 96, 0, 10, 0, 21, 0, 38,
+ 0, 45, 64, 24, 0,169, 12, 38, 11,169, 22,188, 1,169, 38, 17, 18, 26, 40, 6, 18, 33, 0, 11, 8, 22, 70, 39, 16,252,236, 50,
+212,236,204,212,236, 49, 0, 47,236,244,236, 16,212,236, 48, 1, 17, 33, 50, 55, 54, 53, 52, 39, 38, 35, 1, 17, 51, 50, 55, 54,
+ 53, 52, 39, 38, 35, 37, 33, 50, 22, 21, 20, 7, 6, 7, 30, 1, 21, 20, 7, 6, 35, 33, 1,114, 1, 6,129, 66, 63, 63, 69,126,
+254,250,242,117, 61, 58, 58, 61,117,254, 86, 1,182,197,212, 54, 54,106,127,140,116,115,214,254, 57, 2, 2,254,151, 46, 44, 91,
+ 94, 41, 45, 1,197,254,218, 38, 36, 75, 72, 36, 37,153,144,133,103, 60, 61, 15, 24,152,114,150, 82, 82, 0, 0, 0, 1, 0,186,
+ 0, 0, 3,208, 4, 96, 0, 5, 0, 25, 64, 12, 4,169, 1,188, 0, 7, 2, 4, 8, 1, 70, 6, 16,252,252,204,196, 49, 0, 47,
+244,236, 48, 51, 17, 33, 21, 33, 17,186, 3, 22,253,162, 4, 96,170,252, 74, 0, 0, 2, 0, 50,254, 86, 5, 46, 4, 96, 0, 7,
+ 0, 23, 0, 53, 64, 15, 2, 8, 14, 25, 19, 8, 16, 23, 3, 8, 13, 20, 8, 23, 24, 16,220,236,212,236, 16,212,236,204,212,236,
+ 49, 0, 64, 12, 3,169, 13,188, 18, 22,189, 15, 0, 23,169, 20, 47,236, 50, 50,236, 50,244,236, 48, 37, 33, 17, 33, 21, 16, 7,
+ 6, 5, 54, 55, 54, 17, 53, 33, 17, 51, 17, 35, 17, 33, 17, 35, 17, 1,166, 2, 24,254,123,118, 20,254,237, 91, 40, 98, 2,245,
+184,184,252,116,184,153, 3, 46,134,254,109,223, 17, 37, 40, 85,211, 1,163,212,252, 57,253,189, 1,170,254, 86, 2, 67, 0, 0,
+255,255, 0,113,255,227, 4,127, 4,123, 18, 6, 0, 72, 0, 0, 0, 1, 0, 50, 0, 0, 5,173, 4, 96, 0, 21, 0,109, 64, 21,
+ 66, 2, 20, 16,188, 14, 8, 12,169, 0, 18, 6, 10, 14, 23, 8, 21, 8, 11, 20, 22, 16,212, 60,252, 60,196, 49, 0, 47, 60, 60,
+212, 60,236, 50, 16,244, 60, 60, 48, 75, 83, 88, 64, 36, 4, 17, 7, 2, 1, 5, 17, 6, 7, 6, 4, 17, 1, 3, 17, 2, 2, 1,
+ 15, 17, 18, 13, 12, 16, 17, 17, 18, 17, 15, 17, 12, 14, 17, 13, 13, 12, 5, 7, 16,236, 16,236, 7, 16,236, 8, 16,236, 5, 7,
+ 16,236, 16,236, 7, 16,236, 8, 16,236, 89, 1, 51, 1, 51, 9, 1, 35, 1, 35, 17, 35, 17, 35, 1, 35, 9, 1, 51, 1, 51, 17,
+ 51, 3, 75,113, 1, 2,196,254,215, 1, 84,197,254,213,114,183,114,254,213,197, 1, 84,254,215,196, 1, 2,113,183, 2,161, 1,
+191,253,245,253,171, 2, 9,253,247, 2, 9,253,247, 2, 85, 2, 11,254, 65, 1,191, 0, 0, 0, 0, 1, 0,133,255,227, 3,200,
+ 4,124, 0, 49, 0, 60, 64, 33, 38,134, 39,136, 34,185, 42,184, 50, 24,169, 25, 50, 11,134, 10,136, 15,185, 6,140, 50, 30, 18,
+ 46, 51, 19, 18, 3, 25, 39, 11, 50, 16,220,196,196,212,236,204,212,236, 49, 0, 16,244,236,252,236, 16,212,236, 16,244,236,252,
+236, 48, 1, 30, 1, 21, 20, 4, 35, 34, 39, 38, 39, 53, 22, 23, 22, 51, 50, 55, 54, 53, 52, 39, 38, 43, 1, 53, 51, 50, 55, 54,
+ 53, 52, 39, 38, 35, 34, 7, 6, 7, 53, 62, 1, 51, 50, 23, 22, 21, 20, 7, 6, 2,194,124,138,254,254,238, 80, 85, 84, 90, 71,
+ 85, 85, 93,151, 85, 84, 78, 72,137,148,155,116, 67, 68, 70, 69,119, 71, 81, 80, 97, 98,170, 76,196,113,114, 60, 60, 2, 92, 24,
+146,108,173,182, 14, 14, 28,171, 37, 19, 18, 56, 56, 90, 88, 56, 51,152, 44, 45, 70, 64, 46, 46, 13, 13, 29,167, 24, 24, 78, 79,
+141, 93, 64, 65, 0, 1, 0,193, 0, 0, 4,128, 4, 96, 0, 9, 0, 63, 64, 21, 66, 8, 3, 9, 6,188, 2, 5, 11, 70, 9, 4,
+ 7, 3, 8, 0, 7, 8, 6, 70, 10, 16,252,236,212,236, 17, 57, 57,236, 49, 0, 47, 60,228, 50, 57, 57, 48, 75, 83, 88, 64, 10,
+ 3, 17, 9, 9, 8, 8, 17, 4, 4, 3, 7, 16,236, 7, 16,236, 89, 1, 17, 35, 17, 1, 35, 17, 51, 17, 1, 4,128,183,253,228,
+236,183, 2, 27, 4, 96,251,160, 3,131,252,125, 4, 96,252,127, 3,129, 0, 0,255,255, 0,193, 0, 0, 4,128, 6, 20, 16, 39,
+ 2, 49, 0,160,255,204, 18, 6, 3, 85, 0, 0, 0, 1, 0,191, 0, 0, 4,161, 4, 96, 0, 10, 0, 70, 64, 17, 66, 3, 0,188,
+ 7, 10, 12, 5, 1, 4, 6, 8, 1, 8, 0, 70, 11, 16,252,236, 50,212,196, 17, 57,196, 49, 0, 47, 60,228, 50, 48, 75, 83, 88,
+ 64, 16, 7, 17, 6, 8, 17, 5, 6, 5, 2, 17, 5, 3, 17, 4, 5, 4, 5, 7, 16,236, 4, 16,236, 7, 16,236, 5, 16,236, 89,
+ 19, 51, 17, 1, 51, 9, 1, 35, 1, 17, 35,191,185, 2, 37,235,253,174, 2,107,240,253,199,185, 4, 96,254, 29, 1,227,253,244,
+253,172, 2, 35,253,221, 0, 0, 0, 1, 0, 46,255,227, 4,115, 4, 96, 0, 15, 0, 38, 64, 20, 11,169, 6,188, 9, 1,169, 0,
+140, 9, 17, 70, 10, 8, 7, 11, 8, 6, 1, 16, 16,212,212,236,212,236,236, 49, 0, 47,244,236, 16,244,236, 48, 23, 53, 54, 55,
+ 54, 17, 53, 33, 17, 35, 17, 33, 21, 16, 3, 6, 46,179, 59, 98, 2,245,184,254,123,118, 94, 29,153, 27,127,207, 1,167,212,251,
+160, 3,199,134,254,146,254,252,207, 0, 0, 0, 0, 1, 0,193, 0, 0, 5, 72, 4, 96, 0, 12, 0, 77, 64, 22, 66, 10, 7, 2,
+ 3, 8, 3, 0,188, 9, 6, 12, 14, 70, 7, 8, 4, 10, 8, 0, 70, 13, 16,252,236,220,236,236, 49, 0, 47, 60,196,236, 50, 17,
+ 23, 57, 48, 75, 83, 88, 64, 18, 2, 17, 8, 10, 9, 3, 17, 7, 8, 7, 2, 17, 9, 1, 17, 10, 10, 9, 5, 7, 16,237, 16,237,
+ 7, 16,237, 8, 16,237, 89, 19, 33, 9, 1, 33, 17, 35, 17, 1, 35, 1, 17, 35,193, 1, 6, 1, 62, 1, 63, 1, 4,178,254,203,
+184,254,202,178, 4, 96,253, 18, 2,238,251,160, 3,176,253, 39, 2,217,252, 80, 0, 1, 0,193, 0, 0, 4,136, 4, 96, 0, 11,
+ 0, 39, 64, 20, 9,169, 2, 4, 0,188, 7, 11, 13, 70, 8, 4, 8, 5, 9, 1, 8, 0, 70, 12, 16,252,236, 50,220,236, 50,236,
+ 49, 0, 47, 60,228, 50,220,236, 48, 19, 51, 17, 33, 17, 51, 17, 35, 17, 33, 17, 35,193,184, 2, 87,184,184,253,169,184, 4, 96,
+254, 51, 1,205,251,160, 2, 4,253,252, 0, 0,255,255, 0,113,255,227, 4,117, 4,123, 18, 6, 0, 82, 0, 0, 0, 1, 0,193,
+ 0, 0, 4,136, 4, 96, 0, 7, 0, 40, 64, 16, 4,169, 7,188, 2, 6, 3, 8, 9, 70, 0, 4, 8, 7, 70, 8, 16,252,236,212,
+236,236, 49, 0, 47, 60,244,236, 48, 64, 5,160, 9,128, 9, 2, 1, 93, 1, 17, 35, 17, 33, 17, 35, 17, 4,136,184,253,169,184,
+ 4, 96,251,160, 3,198,252, 58, 4, 96, 0, 0,255,255, 0,186,254, 86, 4,164, 4,123, 18, 6, 0, 83, 0, 0,255,255, 0,113,
+255,227, 3,231, 4,123, 18, 6, 0, 70, 0, 0, 0, 1, 0, 5, 0, 0, 4, 54, 4, 96, 0, 7, 0, 37, 64, 13, 3, 7,169, 0,
+188, 5, 9, 1, 3, 8, 0, 6, 8, 16,212,204,252,204,204, 49, 0, 47,244,236, 50, 48, 64, 5,160, 9,128, 9, 2, 1, 93, 19,
+ 33, 21, 33, 17, 35, 17, 33, 5, 4, 49,254, 66,181,254, 66, 4, 96,170,252, 74, 3,182, 0, 0,255,255, 0, 61,254, 86, 4,127,
+ 4, 96, 18, 6, 0, 92, 0, 0, 0, 3, 0,113,254, 86, 6,228, 5,213, 0, 15, 0, 52, 0, 67, 0, 64, 64, 35, 57, 12,185, 39,
+ 28,184, 33,151, 68, 64, 4,185, 47, 21,140, 16,189, 68, 69, 69, 53, 18, 43, 17, 8, 33, 8, 51, 61, 34, 0, 18, 25, 69, 68, 16,
+252,236,212, 60, 60,252, 60, 60,212,236,236, 49, 0, 16,236,244, 60,236, 50, 16,228,244, 60,236, 50, 48, 1, 20, 23, 22, 51, 50,
+ 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 1, 17, 6, 7, 6, 35, 34, 39, 38, 17, 16, 18, 51, 50, 23, 22, 23, 17, 51, 17, 54, 55,
+ 54, 51, 50, 23, 22, 17, 16, 7, 6, 35, 34, 39, 38, 39, 17, 1, 52, 39, 38, 35, 34, 7, 6, 21, 20, 22, 51, 50, 55, 54, 1, 52,
+ 68, 67,133,133, 69, 68, 68, 69,133,133, 67, 68, 2, 26, 45, 77, 76,101,201,116,117,232,202,100, 77, 76, 46,185, 46, 77, 76,100,
+203,115,116,116,116,202,102, 76, 77, 44, 2, 28, 67, 68,133,134, 69, 69,138,134,133, 68, 67, 2, 47,214,109,109,109,110,213,213,
+110,109,109,109,251, 81, 2, 57, 83, 44, 45,155,156, 1, 17, 1, 22, 1, 58, 43, 44, 83, 2, 4,253,252, 83, 44, 43,157,157,254,
+234,254,239,156,155, 43, 44, 83,253,201, 3,217,214,109,109,109,110,213,212,220,109,109, 0, 0,255,255, 0, 59, 0, 0, 4,121,
+ 4, 96, 18, 6, 0, 91, 0, 0, 0, 1, 0,193,254, 86, 5, 64, 4, 96, 0, 11, 0, 40, 64, 21, 6, 2,188, 11,189, 8, 4,169,
+ 1, 13, 0, 8, 9, 6, 8, 7, 3, 8, 2, 70, 12, 16,252,236,212,236,212,236,204, 49, 0, 47,236, 50,236,244, 60, 48, 41, 1,
+ 17, 51, 17, 33, 17, 51, 17, 51, 17, 35, 4,136,252, 57,184, 2, 87,184,184,184, 4, 96,252, 57, 3,199,252, 57,253,189, 0, 0,
+ 0, 1, 0,150, 0, 0, 4, 0, 4, 96, 0, 17, 0, 34, 64, 17, 2,169, 13, 15, 7,188, 0, 19, 70, 1, 15, 8, 16, 8, 8, 7,
+ 18, 16,220,236,212,236, 50,236, 49, 0, 47,228, 50,212,236, 48, 33, 17, 33, 34, 39, 38, 61, 1, 51, 21, 20, 23, 22, 51, 33, 17,
+ 51, 17, 3, 72,254,169,153,102, 92,184, 52, 53,104, 1, 41,184, 2, 9, 95, 86,184,234,211,117, 59, 59, 1,190,251,160, 0, 0,
+ 0, 1, 0,193, 0, 0, 6, 58, 4, 96, 0, 11, 0, 40, 64, 21, 10, 2, 6,188, 0, 8,169, 5, 13, 70, 2, 8, 3, 10, 8, 11,
+ 7, 8, 6, 70, 12, 16,252,236,212,252,212,236,236, 49, 0, 47,236, 50,244, 60,196, 48, 37, 33, 17, 51, 17, 33, 17, 51, 17, 33,
+ 17, 51, 3,217, 1,169,184,250,135,184, 1,168,184,153, 3,199,251,160, 4, 96,252, 57, 3,140, 0, 1, 0,193,254, 86, 6,242,
+ 4, 96, 0, 15, 0, 49, 64, 26, 6, 10, 2,188, 15,189, 12, 8, 4,169, 1, 17, 0, 8, 13, 10, 8, 11, 6, 8, 7, 3, 8, 2,
+ 70, 16, 16,252,236,212,252,212,236,212,236,204, 49, 0, 47,236, 50, 50,236,244, 60,196, 48, 41, 1, 17, 51, 17, 33, 17, 51, 17,
+ 33, 17, 51, 17, 51, 17, 35, 6, 58,250,135,184, 1,168,184, 1,169,184,184,184, 4, 96,252, 57, 3,140,252,116, 3,199,252, 57,
+253,189, 0, 0, 0, 2, 0, 42, 0, 0, 5, 46, 4, 96, 0, 10, 0, 25, 0, 42, 64, 22, 12,169, 13,188, 25, 5,169, 15, 6,169,
+ 25, 27, 69, 0, 18, 20, 5, 14, 8, 11, 13, 26, 16,204,220,236, 50,212,236,236, 49, 0, 47,236,212,236, 16,244,236, 48, 1, 52,
+ 39, 38, 35, 33, 17, 33, 50, 55, 54, 1, 33, 53, 33, 17, 33, 50, 23, 22, 21, 20, 7, 6, 35, 33, 4,106, 62, 67,128,254,249, 1,
+ 7,129, 66, 62,253, 64,254,128, 2, 56, 1, 15,208,121,116,116,115,214,254, 57, 1, 76, 94, 42, 46,254,151, 46, 43, 2,212,154,
+254, 59, 85, 82,168,168, 82, 82,255,255, 0,193, 0, 0, 5,105, 4, 96, 16, 38, 3,105, 0, 0, 17, 7, 0,243, 3,240, 0, 0,
+ 0, 13, 64, 6, 29, 70, 25, 8, 24, 18, 16,220,252,236, 49, 0, 0, 2, 0,193, 0, 0, 4, 69, 4, 96, 0, 10, 0, 23, 0, 36,
+ 64, 19, 5,169, 13, 11,188, 6,169, 23, 25, 69, 0, 18, 18, 5, 12, 8, 11, 70, 24, 16,252,236, 50,212,236,236, 49, 0, 47,236,
+228,212,236, 48, 1, 52, 39, 38, 35, 33, 17, 33, 50, 55, 54, 1, 51, 17, 33, 50, 23, 22, 21, 20, 7, 6, 35, 33, 3,129, 62, 67,
+128,254,249, 1, 7,129, 66, 62,253, 64,184, 1, 15,208,121,116,116,115,214,254, 57, 1, 76, 94, 42, 46,254,151, 46, 43, 3,110,
+254, 59, 85, 82,168,168, 82, 82, 0, 1, 0,113,255,227, 3,231, 4,123, 0, 28, 0, 0, 1, 34, 7, 21, 54, 51, 50, 23, 22, 23,
+ 33, 21, 33, 6, 7, 6, 35, 34, 39, 21, 22, 51, 32, 55, 54, 17, 16, 39, 38, 1,180,166,157,161,154,230, 92, 34, 12,254, 52, 1,
+212, 13,158, 85,120,157,158,147,189, 1, 11,148,135,151,148, 4,123, 70,172, 86,180, 65, 87,143,244, 94, 51, 86,170, 72,172,157,
+ 1, 3, 1, 17,157,158, 0, 0, 0, 2, 0,193,255,227, 6, 16, 4,123, 0, 14, 0, 36, 0, 56, 64, 31, 0,185, 19,184, 37, 8,
+185, 26,140, 37, 31,169, 36, 34,188, 33, 38, 69, 11, 18, 22, 4, 18, 30, 15, 31, 35, 8, 34, 70, 37, 16,252,236, 50,212, 60,236,
+212,236,236, 49, 0, 47,228,212,236, 16,244,236, 16,244,236, 48, 1, 34, 7, 6, 21, 20, 23, 22, 51, 50, 54, 53, 52, 39, 38, 1,
+ 54, 55, 54, 51, 50, 0, 17, 16, 7, 6, 35, 34, 39, 38, 39, 35, 17, 35, 17, 51, 17, 4, 14,148, 86, 86, 85, 86,149,147,172, 86,
+ 86,253,113, 19,112,137,240,240, 1, 18,137,137,240,241,136,127, 9,148,184,184, 3,223,115,116,201,201,116,115,232,200,199,116,
+117,254,194,190,128,156,254,200,254,236,254,237,156,157,157,145,248,253,247, 4, 96,254, 65, 0, 0, 2, 0, 50, 0, 0, 4, 15,
+ 4, 96, 0, 22, 0, 33, 0, 68, 64, 21, 66, 24,169, 7,188, 18, 12,169, 32, 10, 18, 35, 70, 11, 23, 8, 8, 28, 18, 3, 34, 16,
+212,236,212,236, 50,236, 49, 0, 47, 60,212,236, 16,244,236, 48, 75, 83, 88, 64, 13, 15, 14, 13, 3, 12, 16, 17, 19, 17, 17, 18,
+ 19, 18, 5, 7, 16,236, 16,236, 17, 23, 57, 89, 1, 46, 1, 53, 52, 55, 54, 51, 33, 17, 35, 17, 35, 34, 7, 6, 7, 3, 35, 19,
+ 54, 55, 54, 1, 35, 34, 7, 6, 21, 20, 23, 22, 59, 1, 1,181,106,112,107,108,217, 1,132,185,169, 97, 59, 59, 63,162,195,174,
+ 53, 52, 53, 1,216,198,119, 63, 64, 64, 63,119,198, 2, 13, 27,140,105,162, 81, 80,251,160, 1,217, 37, 36,113,254,225, 1, 50,
+ 94, 54, 54, 1,201, 42, 42, 84, 83, 43, 43, 0,255,255, 0,113,255,227, 4,127, 6,107, 16, 38, 0, 67, 90, 5, 18, 6, 3, 82,
+ 0, 0, 0, 0,255,255, 0,113,255,227, 4,127, 6, 16, 16, 39, 0,106, 0,150, 0, 0, 18, 6, 3, 82, 0, 0, 0, 1, 0, 40,
+254, 86, 4,107, 6, 20, 0, 40, 0, 0, 19, 35, 53, 51, 53, 51, 21, 33, 21, 33, 17, 54, 55, 54, 51, 50, 23, 22, 21, 17, 20, 7,
+ 6, 43, 1, 53, 51, 50, 55, 54, 53, 17, 52, 38, 35, 34, 7, 6, 21, 17, 35,193,153,153,185, 1, 70,254,186, 66, 89, 90,117,185,
+107, 99, 82, 81,181, 70, 49,110, 33, 38,124,124,154, 81, 86,185, 5, 4,125,147,147,125,254, 87,101, 50, 50,119,110,242,253,159,
+214, 96, 96,156, 48, 55,147, 2, 91,159,158, 95,101,158,253,222,255,255, 0,186, 0, 0, 3,216, 6,109, 16, 39, 0,118, 0,134,
+ 0, 7, 18, 6, 3, 80, 0, 0, 0, 1, 0,113,255,227, 3,231, 4,123, 0, 28, 0, 58, 64, 33, 2,134, 3,136, 5, 19,134, 18,
+136, 16,185, 21, 10,169, 11,187, 5,185, 0,184, 21,140, 29, 10, 12, 9, 18, 18, 2, 72, 25, 69, 29, 16,252,228, 50,252, 50,204,
+ 49, 0, 16,228,244,236,244,238, 16,254,244,238, 16,245,238, 48, 1, 50, 23, 21, 38, 35, 34, 7, 6, 7, 33, 21, 33, 22, 23, 22,
+ 51, 50, 55, 21, 6, 35, 32, 39, 38, 17, 16, 55, 54, 2,164,166,157,161,154,230, 92, 34, 12, 1,204,254, 44, 13,158, 85,120,157,
+158,147,188,254,243,148,134,151,149, 4,123, 70,172, 86,180, 65, 87,143,244, 94, 51, 86,170, 72,173,157, 1, 2, 1, 17,157,158,
+255,255, 0,111,255,227, 3,199, 4,123, 18, 6, 0, 86, 0, 0,255,255, 0,193, 0, 0, 1,121, 6, 20, 18, 6, 0, 76, 0, 0,
+255,255,255,244, 0, 0, 2, 70, 6, 16, 18, 38, 0,243, 0, 0, 17, 7, 0,106,255, 29, 0, 0, 0, 8,180, 0, 10, 7, 1, 7,
+ 43, 49, 0, 0,255,255,255,219,254, 86, 1,121, 6, 20, 18, 6, 0, 77, 0, 0, 0, 2, 0, 46,255,227, 6,190, 4, 96, 0, 23,
+ 0, 34, 0, 0, 1, 33, 21, 16, 3, 6, 5, 53, 54, 55, 54, 17, 53, 33, 17, 51, 50, 23, 22, 16, 7, 6, 35, 33, 1, 52, 39, 38,
+ 43, 1, 17, 51, 50, 55, 54, 3,158,254,152,118, 94,254,204,179, 59, 98, 2,216,171,208,121,116,116,115,214,254,157, 2, 92, 62,
+ 67,128,163,163,129, 66, 62, 3,199,134,254,146,254,252,207, 29,153, 27,127,207, 1,167,212,254, 59, 85, 82,254,176, 82, 82, 1,
+ 76, 94, 42, 46,254,151, 46, 43, 0, 2, 0,193, 0, 0, 6,188, 4, 96, 0, 10, 0, 30, 0, 0, 1, 52, 39, 38, 43, 1, 17, 51,
+ 50, 55, 54, 5, 17, 33, 17, 35, 17, 51, 17, 33, 17, 51, 17, 51, 50, 23, 22, 16, 7, 6, 35, 5,248, 62, 66,129,163,163,129, 66,
+ 62,253,164,253,221,184,184, 2, 35,184,171,208,121,116,116,115,214, 1, 76, 95, 42, 45,254,151, 46, 43,242, 2, 2,253,254, 4,
+ 96,254, 59, 1,197,254, 59, 85, 82,254,176, 82, 82, 0, 0, 0, 0, 1, 0, 40, 0, 0, 4,107, 6, 20, 0, 30, 0, 0, 19, 35,
+ 53, 51, 53, 51, 21, 33, 21, 33, 17, 54, 55, 54, 51, 50, 23, 22, 21, 17, 35, 17, 52, 38, 35, 34, 7, 6, 21, 17, 35,193,153,153,
+185, 1, 70,254,186, 66, 89, 90,117,189,103, 99,184,124,124,152, 83, 86,185, 5, 4,125,147,147,125,254, 87,101, 50, 50,119,115,
+237,253,179, 2, 71,159,158, 95, 98,161,253,222,255,255, 0,191, 0, 0, 4,161, 6,109, 16, 39, 0,118, 0,228, 0, 7, 18, 6,
+ 3, 87, 0, 0,255,255, 0,193, 0, 0, 4,128, 6,107, 16, 38, 0, 67,100, 5, 18, 6, 3, 85, 0, 0, 0, 0,255,255, 0, 61,
+254, 86, 4,127, 6, 20, 16, 38, 2, 49, 94,204, 18, 6, 3, 96, 0, 0, 0, 0, 0, 1, 0,193,254, 86, 4,136, 4, 96, 0, 11,
+ 0, 0, 33, 17, 35, 17, 33, 17, 51, 17, 33, 17, 51, 17, 2,255,184,254,122,184, 2, 87,184,254, 86, 1,170, 4, 96,252, 58, 3,
+198,251,160, 0, 0, 1, 0,115,255,227, 7, 5, 5,213, 0, 52, 0, 0, 1, 22, 51, 50, 55, 54, 61, 1, 51, 21, 20, 23, 22, 51,
+ 50, 55, 54, 17, 52, 39, 2, 39, 51, 22, 23, 18, 21, 16, 7, 6, 35, 34, 39, 38, 39, 6, 7, 6, 35, 34, 39, 38, 17, 52, 19, 54,
+ 55, 51, 6, 3, 6, 21, 16, 1,146, 73,125,114, 72, 71,199, 70, 70,116,134, 65, 71, 67,135, 84,250, 95, 56,100,123,123,209,146,
+101,100, 39, 39,100,101,146,211,121,123,100, 59, 93,249, 84,135, 67, 1, 90,109,105,104,198,241,241,198,104,105,109,119, 1, 39,
+183,159, 1, 65, 70,130,156,254,231,190,254,102,178,177, 94, 94,173,173, 94, 94,177,180, 1,152,201, 1, 14,159,127, 70,254,191,
+159,183,254,205,255,255, 0,135,255,226, 6, 40, 4, 96, 16, 2, 2,231, 0, 0,255,255, 0, 33, 0, 0, 4,236, 5,213, 16, 2,
+ 3,168, 0, 0, 0, 2, 0, 58, 0, 0, 4, 69, 5,213, 0, 19, 0, 30, 0, 0, 1, 17, 33, 50, 23, 22, 16, 7, 6, 35, 33, 17,
+ 35, 53, 51, 17, 51, 17, 51, 21, 1, 52, 39, 38, 35, 33, 17, 33, 50, 55, 54, 1,121, 1, 15,208,121,116,116,115,214,254, 57,135,
+135,184,175, 1, 89, 62, 67,128,254,249, 1, 7,129, 66, 62, 3,209,254,202, 85, 82,254,176, 82, 82, 3,209,143, 1,117,254,139,
+143,253,123, 94, 42, 46,254,151, 46, 43, 0, 0, 0, 1, 0,211,255,227, 7, 27, 5,240, 0, 43, 0, 0, 1, 17, 35, 17, 51, 17,
+ 51, 18, 55, 54, 33, 50, 23, 22, 23, 21, 38, 39, 38, 35, 32, 7, 6, 7, 33, 21, 33, 18, 23, 22, 33, 50, 55, 54, 55, 21, 6, 7,
+ 6, 35, 32, 39, 38, 3, 1,157,202,202,210, 30,157,195, 1, 83,134,118,119,104,102,115,116,130,255, 0,136,103, 25, 2,178,253,
+ 70, 7,129,137, 0,255,130,116,115,102,106,119,118,132,254,173,195,186, 9, 2,199,253, 57, 5,213,253,156, 1, 8,167,208, 36,
+ 35, 71,213, 95, 47, 47,156,119,198,170,254,243,148,157, 47, 47, 95,211, 72, 36, 36,207,198, 1, 79, 0, 0, 0, 0, 1, 0,193,
+255,227, 5,129, 4,123, 0, 35, 0, 0, 1, 50, 23, 21, 38, 35, 34, 7, 6, 7, 33, 21, 33, 22, 23, 22, 51, 50, 55, 21, 6, 35,
+ 32, 39, 38, 39, 35, 17, 35, 17, 51, 17, 51, 54, 55, 54, 4, 62,166,157,161,154,230, 92, 34, 12, 1,204,254, 44, 13,158, 85,120,
+157,158,147,188,254,243,148,123, 10,147,184,184,152, 23,122,151, 4,123, 70,172, 86,180, 65, 87,143,244, 94, 51, 86,170, 72,173,
+144,228,253,252, 4, 96,254, 51,202,128,158, 0, 0, 2, 0, 16, 0, 0, 6,248, 5,213, 0, 3, 0, 15, 0, 0, 1, 11, 1, 31,
+ 1, 17, 35, 17, 39, 1, 35, 1, 51, 1, 35, 1, 4,106,230,231,231,102,202,222,254,175,225, 3, 2,229, 3, 1,225,254,175, 3,
+ 63, 1,192,254, 64,119,172,253,228, 2, 27,114,253,115, 5,213,250, 43, 2,142, 0, 2, 0, 51, 0, 0, 6, 17, 4, 96, 0, 3,
+ 0, 15, 0, 0, 1, 11, 1, 31, 1, 17, 35, 17, 39, 1, 35, 1, 51, 1, 35, 1, 3,226,192,192,192, 93,184,179,254,226,195, 2,
+142,195, 2,141,195,254,226, 2,112, 1, 74,254,182, 87,131,254,106, 1,149, 81,254, 26, 4, 96,251,160, 1,231, 0, 2, 0,201,
+ 0, 0, 9, 20, 5,213, 0, 3, 0, 23, 0, 0, 1, 11, 1, 23, 5, 33, 17, 35, 17, 51, 17, 33, 1, 51, 1, 35, 1, 7, 17, 35,
+ 17, 39, 1, 35, 6,134,230,231,231,253,251,253,248,202,202, 2, 95, 1, 60,229, 3, 1,225,254,175,220,202,222,254,175,225, 3,
+ 63, 1,192,254, 64,119, 1,253, 57, 5,213,253,156, 2,100,250, 43, 2,142,114,253,228, 2, 27,114,253,115, 0, 0, 2, 0,193,
+ 0, 0, 7,208, 4, 96, 0, 3, 0, 23, 0, 0, 1, 11, 1, 23, 5, 33, 17, 35, 17, 51, 17, 33, 1, 51, 1, 35, 1, 7, 17, 35,
+ 17, 39, 1, 35, 5,161,192,192,192,254, 45,254,107,184,184, 1,233, 1, 30,195, 2,141,195,254,226,177,184,179,254,226,195, 2,
+112, 1, 74,254,182, 87, 50,254, 25, 4, 96,254, 23, 1,233,251,160, 1,231, 81,254,106, 1,149, 81,254, 26, 0, 0, 2, 0,115,
+ 0, 0, 5,217, 5,213, 0, 23, 0, 26, 0, 0, 1, 17, 35, 17, 6, 7, 6, 17, 35, 16, 55, 54, 55, 1, 33, 1, 22, 23, 22, 17,
+ 35, 16, 39, 38, 39, 1, 33, 3,139,202,147,100,130,213,189,120,170,254, 81, 5, 18,254, 80,164,116,188,213,128, 96,248, 1, 62,
+253,131, 2, 89,253,167, 2, 89, 28,126,164,254,229, 1, 98,210,134, 49, 2,234,253, 19, 50,130,210,254,158, 1, 30,161,122,202,
+ 2, 40, 0, 0, 0, 2, 0,107, 0, 0, 4,123, 4, 96, 0, 2, 0, 26, 0, 0, 1, 33, 19, 9, 1, 22, 23, 22, 17, 35, 52, 39,
+ 38, 39, 17, 35, 17, 6, 7, 6, 21, 35, 16, 55, 54, 55, 1, 3, 69,254, 93,209, 2, 8,254,187,107, 75,137,195, 86, 58, 86,184,
+ 83, 56, 86,194,137, 74,108,254,187, 3,182,254,150, 2, 20,253,204, 38, 86,156,254,236,199,116, 79, 26,254, 92, 1,162, 26, 75,
+116,201, 1, 20,156, 85, 39, 2, 52, 0, 0, 0, 0, 2, 0,201, 0, 0, 7,196, 5,213, 0, 30, 0, 33, 0, 0, 9, 1, 33, 1,
+ 22, 23, 22, 17, 35, 16, 39, 38, 39, 17, 35, 17, 6, 7, 6, 17, 35, 16, 55, 54, 55, 33, 17, 35, 17, 51, 17, 5, 1, 33, 3,239,
+254,159, 5, 18,254, 80,164,116,188,213,128, 96,153,202,147,100,130,213,189, 85,110,253,181,202,202, 3,132, 1, 62,253,131, 3,
+113, 2,100,253, 19, 50,130,210,254,158, 1, 30,161,122, 32,253,167, 2, 89, 28,126,164,254,229, 1, 98,210, 95, 52,253, 57, 5,
+213,253,156,110, 2, 40, 0, 0, 0, 2, 0,193, 0, 0, 6, 46, 4, 96, 0, 30, 0, 33, 0, 0, 9, 1, 33, 1, 22, 23, 22, 17,
+ 35, 52, 39, 38, 39, 17, 35, 17, 6, 7, 6, 21, 35, 16, 55, 54, 55, 33, 17, 35, 17, 51, 17, 1, 33, 19, 3, 55,254,231, 4, 16,
+254,187,107, 75,137,195, 86, 58, 86,184, 83, 56, 86,194,137, 27, 31,254,146,184,184, 3,127,254, 93,209, 2,119, 1,233,253,204,
+ 38, 86,156,254,236,199,116, 79, 26,254, 92, 1,162, 26, 75,116,201, 1, 20,156, 31, 24,254, 25, 4, 96,254, 23, 1, 63,254,150,
+ 0, 1, 0,115,254, 86, 4,115, 5,240, 0, 75, 0, 0, 5, 50, 23, 22, 23, 21, 38, 39, 38, 35, 32, 39, 38, 53, 52, 55, 54, 51,
+ 50, 23, 22, 51, 50, 55, 54, 53, 52, 39, 38, 43, 1, 53, 51, 50, 55, 54, 53, 52, 39, 38, 35, 34, 6, 7, 53, 54, 55, 54, 51, 50,
+ 23, 22, 21, 20, 7, 6, 7, 22, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 35, 34, 7, 6, 21, 20, 23, 22, 2,187, 60, 91, 96, 86,
+ 71,103,134, 25,254,205,114,163, 63, 71, 99, 46,132, 73,100, 91, 85, 63, 92, 91,167,174,182,149, 79, 79, 81, 82,152, 83,190,114,
+115,100,101, 89,230,134,134, 71, 71,131,147, 80, 81,115,152,198, 86, 76, 85, 42, 40, 32, 24,117, 94,209, 6, 6, 38,167, 41, 8,
+ 10, 67, 96,147,144, 72, 81, 45, 25, 90, 65,121,122, 74, 73,166, 59, 60,112,115, 61, 62, 36, 38,180, 32, 16, 16,104,105,178,124,
+ 85, 86, 33, 31, 96, 98,134,208,102,136, 36, 42, 36, 27, 67, 87, 39, 32, 0, 0, 0, 2, 0, 91,254,116, 3,200, 6,102, 0, 73,
+ 0, 80, 0, 0, 37, 50, 55, 54, 53, 52, 39, 38, 43, 1, 53, 51, 50, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 7, 53, 62, 1, 51,
+ 50, 23, 22, 21, 20, 7, 6, 7, 30, 1, 21, 20, 6, 39, 38, 39, 38, 35, 34, 7, 6, 21, 20, 23, 22, 51, 50, 23, 22, 23, 21, 38,
+ 39, 38, 35, 32, 39, 38, 53, 52, 55, 54, 51, 50, 23, 22, 11, 1, 51, 23, 55, 51, 3, 2, 75, 87, 59, 54, 78, 72,137,148,155,116,
+ 67, 68, 70, 69,119, 71, 81, 80, 97, 98,170, 76,196,113,114, 60, 60,112,124,138,238,168, 78, 59, 75, 32, 36, 25, 19, 98,106,140,
+ 82, 46, 93, 59, 59, 88,132, 1,254,254, 96,137, 52, 58, 86, 51,103, 62, 62,245,139,180,180,139,245,153, 49, 45, 91, 76, 56, 51,
+152, 44, 45, 70, 64, 46, 46, 13, 13, 29,167, 24, 24, 78, 79,141, 93, 64, 65, 24, 24,146, 96,161,182, 5, 2, 28, 35, 30, 23, 76,
+ 99, 25, 27, 5, 11, 26,139, 34, 6, 9, 56, 81,152,141, 59, 68, 36, 21, 4, 85, 1,120,245,245,254,136, 0, 0,255,255, 0,115,
+ 0, 0, 5,219, 5,213, 18, 2, 2,198, 0, 0,255,255, 0,112,254, 86, 4,209, 4, 96, 18, 2, 2,230, 0, 0, 0, 3, 0,115,
+255,227, 5,217, 5,240, 0, 9, 0, 20, 0, 35, 0, 0, 1, 5, 39, 5, 18, 23, 22, 32, 55, 54, 17, 38, 39, 38, 35, 34, 7, 6,
+ 7, 37, 23, 3, 32, 23, 22, 17, 16, 7, 6, 33, 32, 39, 38, 16, 55, 54, 5, 4,254,104,230,254,194, 8,122,129, 1,184,129,120,
+ 25, 95,129,220,218,131, 98, 24, 1,144,230,159, 1, 58,188,188,188,188,254,198,254,197,188,189,189,188, 2,199,110,200, 90,254,
+255,155,164,164,152, 1,174,189,122,164,164,123,188,110,200, 2,217,210,211,254,158,254,159,210,211,210,210, 2,196,211,210, 0,
+ 0, 3, 0,113,255,227, 4,117, 4,123, 0, 10, 0, 21, 0, 36, 0, 0, 1, 37, 23, 55, 38, 39, 38, 35, 34, 7, 6, 3, 22, 23,
+ 22, 51, 50, 55, 54, 55, 5, 39, 19, 50, 0, 17, 16, 7, 6, 35, 34, 39, 38, 17, 16, 55, 54, 1, 57, 1, 7,150,213, 17, 62, 86,
+147,149, 85, 63, 22, 8, 76, 86,149,147, 86, 76, 9,254,243,150,101,240, 1, 18,137,137,240,241,136,137,137,136, 2,148, 70,120,
+ 50,129, 85,117,115, 85,254,237,173,101,115,116,103,170, 70,130, 2, 59,254,200,254,236,254,237,156,157,157,156, 1, 19, 1, 20,
+156,156, 0, 0, 0, 1, 0, 16, 0, 0, 6, 39, 5,240, 0, 20, 0, 0, 33, 35, 1, 51, 9, 1, 18, 55, 54, 51, 50, 22, 23, 21,
+ 39, 38, 35, 34, 7, 6, 7, 3, 47,229,253,198,211, 1,217, 1, 56,115, 96, 78,148, 31, 62, 33, 68, 22, 25, 73, 34, 71, 84, 5,
+213,251, 23, 3, 61, 1, 50, 82, 67, 10, 11,187, 10, 4, 34, 67,221, 0, 0, 0, 0, 1, 0, 50, 0, 0, 5, 31, 4,123, 0, 21,
+ 1, 56, 64, 5, 23, 8, 4, 19, 22, 16, 75,176, 10, 84, 88,185, 0, 19, 0, 64, 56, 89, 75,176, 20, 84, 75,176, 21, 84, 91, 88,
+185, 0, 19,255,192, 56, 89,212,212,196,196,180, 21, 17, 18, 4, 19, 17, 18, 57, 57, 57, 49, 64, 10, 9,134, 8, 12,185, 4,184,
+ 19,188, 18, 0, 47,228,244,228,212,236, 48,182, 21, 17, 20, 17, 19, 19, 18, 7, 5, 16,236, 4,236,183, 3, 2, 1, 0, 17, 16,
+ 16, 17, 7, 5, 16,236, 50, 50, 50, 64, 26, 12, 15, 15, 9, 15, 8, 11, 16, 10, 3, 10, 2, 12, 1, 10, 0, 8, 21, 9, 17, 8,
+ 18, 8, 20, 7, 19, 64, 16, 25, 16, 25, 0, 31, 22, 26, 17, 29, 18, 28, 21, 29, 20, 29, 19, 64, 12, 43, 1, 41, 16, 41, 0, 40,
+ 21, 38, 20, 38, 19, 64, 18, 51, 15, 52, 1, 50, 16, 51, 0, 54, 21, 54, 20, 54, 19, 55, 17, 52, 18, 64, 24, 74, 2, 74, 16, 74,
+ 0, 77, 1, 72, 21, 70, 19, 70, 20, 70, 17, 74, 18, 79, 9, 79, 8, 79, 23, 64, 28, 90, 2, 92, 1, 91, 16, 91, 0, 95, 22, 93,
+ 21, 94, 20, 95, 19, 94, 18, 90, 17, 90, 15, 95, 23, 95, 9, 95, 8, 64, 26,107, 15,107, 2,105, 1,111, 1,106, 16,106, 0,105,
+ 21,102, 20,102, 19,105, 18,111, 9,111, 8,111, 23, 64, 18,124, 2,127, 1,122, 16,122, 21,122, 0,119, 17,124, 18,117, 20,118,
+ 19,176, 84, 1, 93, 64, 17, 6, 21, 25, 21, 39, 21, 54, 21, 74, 21, 91, 21,106, 21,127, 21, 8, 0, 93, 1, 54, 55, 54, 51, 50,
+ 23, 22, 23, 21, 39, 38, 35, 34, 7, 6, 7, 1, 35, 1, 51, 1, 3, 59, 80,102, 66,129, 26, 26, 27, 28, 58, 19, 21, 54, 29, 65,
+ 61,254,228,250,254, 92,195, 1, 94, 3, 36,213, 79, 51, 4, 4, 8,141, 7, 3, 25, 55,162,253, 10, 4, 96,252, 84, 0, 0, 0,
+ 0, 3, 0, 16, 0, 0, 6, 39, 7,108, 0, 3, 0, 7, 0, 28, 0, 0, 1, 19, 35, 3, 37, 19, 35, 3, 19, 35, 1, 51, 9, 1,
+ 18, 55, 54, 51, 50, 22, 23, 21, 39, 38, 35, 34, 7, 6, 7, 1,253,144,135,174, 1,238,134,137,157,137,229,253,198,211, 1,217,
+ 1, 56,115, 96, 78,148, 31, 62, 33, 68, 22, 25, 73, 34, 71, 84, 7,107,254,248, 1, 8, 1,254,247, 1, 9,248,148, 5,213,251,
+ 23, 3, 61, 1, 50, 82, 67, 10, 11,187, 10, 4, 34, 67,221, 0,255,255, 0, 50, 0, 0, 5, 31, 6,102, 16, 35, 2, 87, 4,194,
+ 0, 0, 18, 2, 3,146, 0, 0,255,255, 0,113,255,227, 5, 37, 5,240, 16, 2, 1,228, 0, 0,255,255, 0,113,255,227, 4,113,
+ 5, 47, 16, 2, 1,229, 0, 0, 0, 2, 0,115,255,227, 7, 45, 5,240, 0, 41, 0, 82, 0, 0, 37, 51, 50, 55, 54, 53, 52, 39,
+ 38, 43, 1, 6, 7, 6, 7, 6, 34, 39, 38, 39, 38, 39, 35, 34, 7, 6, 21, 20, 23, 22, 59, 1, 54, 55, 54, 55, 54, 50, 23, 22,
+ 23, 22, 7, 35, 32, 39, 38, 16, 55, 54, 33, 51, 54, 55, 54, 55, 54, 50, 23, 22, 23, 22, 23, 51, 32, 23, 22, 17, 16, 7, 6, 33,
+ 35, 6, 7, 6, 7, 6, 34, 39, 38, 39, 38, 4, 93, 30,235,114,128,128,114,235, 30, 11, 15, 22, 27, 26, 62, 26, 27, 22, 16, 10,
+ 46,235,114,130,130,114,235, 46, 10, 16, 22, 27, 26, 62, 26, 27, 22, 16,254, 46,254,161,152,189,189,152, 1, 95, 45, 11, 16, 22,
+ 27, 26, 62, 26, 31, 18, 16, 11, 29, 1, 94,152,188,188,152,254,162, 29, 10, 17, 22, 27, 26, 62, 26, 31, 18, 16,194,145,164,242,
+243,164,145, 20, 14, 21, 12, 11, 11, 12, 21, 16, 18,145,164,243,242,164,145, 18, 16, 21, 12, 11, 11, 12, 21, 16,161,170,210, 2,
+116,211,170, 21, 15, 21, 12, 11, 11, 14, 19, 17, 19,170,211,254,198,254,199,210,171, 19, 17, 21, 12, 11, 11, 14, 19, 17, 0, 0,
+ 0, 2, 0,113,255,227, 5,161, 4,123, 0, 38, 0, 80, 0, 0, 37, 51, 50, 55, 54, 53, 52, 39, 38, 43, 1, 6, 7, 14, 1, 34,
+ 38, 39, 38, 39, 35, 34, 7, 6, 21, 20, 23, 22, 59, 1, 54, 55, 62, 1, 50, 23, 22, 23, 22, 7, 35, 32, 39, 38, 53, 52, 55, 54,
+ 33, 51, 54, 55, 54, 55, 54, 50, 23, 22, 23, 22, 23, 51, 32, 23, 22, 21, 20, 7, 6, 33, 35, 6, 7, 6, 7, 6, 34, 39, 38, 39,
+ 38, 3,114, 45,161, 72, 86, 86, 63,170, 45, 7, 10, 18, 44, 52, 44, 18, 10, 7, 45,163, 71, 86, 85, 72,163, 45, 7, 10, 18, 44,
+ 52, 22, 27, 13, 9,201, 46,254,255,120,137,137,116, 1, 5, 46, 7, 9, 13, 27, 22, 52, 22, 27, 13, 9, 7, 46, 1, 2,119,137,
+137,116,254,251, 46, 7, 9, 13, 27, 22, 52, 22, 27, 13, 9,164, 96,116,183,167,131, 97, 11, 10, 17, 20, 20, 17, 10, 11, 95,116,
+184,188,112, 95, 11, 10, 17, 20, 10, 12, 15, 10,147,137,156,238,233,162,136, 10, 10, 15, 12, 10, 10, 12, 15, 10, 10,136,156,239,
+232,162,137, 10, 10, 15, 12, 10, 10, 12, 15, 10,255,255, 0,115,255,227, 7, 5, 7,183, 16, 35, 3,160, 6, 44, 1, 61, 16, 2,
+ 3,125, 0, 0,255,255, 0,135,255,226, 6, 40, 6,100, 16, 35, 3,160, 5,196,255,234, 16, 2, 3,126, 0, 0, 0, 2, 0,115,
+255,227, 7, 5, 7, 51, 0, 11, 0, 64, 0, 0, 1, 7, 35, 39, 35, 7, 35, 39, 35, 7, 35, 39, 3, 22, 51, 50, 55, 54, 61, 1,
+ 51, 21, 20, 23, 22, 51, 50, 55, 54, 17, 52, 39, 2, 39, 51, 22, 23, 18, 21, 16, 7, 6, 35, 34, 39, 38, 39, 6, 7, 6, 35, 34,
+ 39, 38, 17, 52, 19, 54, 55, 51, 6, 3, 6, 21, 16, 5,126,100, 50, 50,175, 50, 50, 50,175, 50, 50,100,104, 73,125,114, 72, 71,
+199, 70, 70,116,134, 65, 71, 67,135, 84,250, 95, 56,100,123,123,209,146,101,100, 39, 39,100,101,146,211,121,123,100, 59, 93,249,
+ 84,135, 67, 7, 51,200,100,100,100,100,200,250, 39,109,105,104,198,241,241,198,104,105,109,119, 1, 39,183,159, 1, 65, 70,130,
+156,254,231,190,254,102,178,177, 94, 94,173,173, 94, 94,177,180, 1,152,201, 1, 14,159,127, 70,254,191,159,183,254,205, 0, 0,
+ 0, 2, 0,135,255,226, 6, 40, 5,224, 0, 11, 0, 38, 0, 0, 1, 7, 35, 39, 35, 7, 35, 39, 35, 7, 35, 39, 19, 32, 17, 52,
+ 19, 51, 2, 21, 2, 51, 50, 3, 51, 2, 55, 54, 17, 52, 3, 51, 18, 21, 18, 37, 36, 3, 2, 5, 27,100, 50, 50,175, 50, 50, 50,
+175, 50, 50,100,143,254, 97,155,198,143, 1,223,207, 4,170, 4,207,222,143,198,155, 2,254, 95,254,241, 34, 41, 5,224,200,100,
+100,100,100,200,250, 3, 2, 82,235, 1, 64,254,192,240,254, 79, 2, 26,253,227, 3, 2, 1,175,240, 1, 64,254,192,235,253,173,
+ 1, 1, 1, 42,254,213, 0, 0, 0, 1, 0,115,254, 86, 5, 39, 5,240, 0, 25, 0, 0, 33, 35, 32, 39, 38, 17, 16, 0, 33, 50,
+ 22, 23, 21, 46, 1, 35, 32, 0, 17, 16, 23, 22, 51, 33, 17, 35, 3,250,174,254,165,187,195, 1,134, 1, 83,134,237,104,102,231,
+130,255, 0,254,240,136,152,240, 1,107,201,198,208, 1, 83, 1,104, 1,159, 71, 71,213, 95, 94,254,199,254,216,254,211,130,148,
+253,176, 0, 0, 0, 1, 0,113,254, 86, 3,231, 4,123, 0, 24, 0, 0, 33, 32, 39, 38, 53, 16, 0, 33, 50, 22, 23, 21, 46, 1,
+ 35, 34, 6, 21, 20, 22, 59, 1, 17, 35, 17, 2,152,254,251,141,149, 1, 45, 1, 6, 85,162, 76, 78,157, 80,179,198,198,179,245,
+201,150,159,250, 1, 18, 1, 58, 35, 35,172, 43, 43,227,205,185,227,253,195, 1,170, 0, 0, 0, 0, 1, 0, 50, 0, 52, 4,142,
+ 5,188, 0, 27, 0, 0, 1, 55, 39, 55, 23, 55, 23, 7, 23, 7, 39, 7, 23, 7, 39, 7, 23, 7, 39, 7, 39, 55, 39, 55, 23, 55,
+ 39, 55, 2, 59,105,216,100,216,125,174,125,216,100,216,105,216,100,216,105,216,100,216,125,174,125,216,100,216,105,216,100, 3,
+129,181,125,174,125,216,100,216,125,174,125,181,125,174,125,181,125,174,125,216,100,216,125,174,125,181,125,174, 0, 1,251,218,
+ 4,222,255, 66, 6,122, 0, 47, 0, 0, 1, 33, 20, 7, 6, 7, 6, 7, 6, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54,
+ 55, 54, 51, 33, 52, 55, 54, 55, 54, 55, 54, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6,254,185,254, 51, 10, 11,
+ 19, 20, 25, 24, 56, 24, 25, 20, 19, 11, 10, 10, 11, 19, 20, 25, 24, 28, 1,205, 10, 11, 19, 20, 25, 24, 56, 24, 25, 20, 20, 10,
+ 10, 10, 11, 19, 20, 25, 24, 5,103, 27, 25, 27, 18, 19, 11, 10, 10, 11, 19, 18, 27, 25, 27, 28, 25, 27, 18, 19, 11, 10, 27, 25,
+ 27, 18, 19, 11, 10, 10, 11, 19, 21, 24, 25, 28, 27, 25, 27, 18, 19, 11, 10, 0, 0, 1,251,247, 5, 41,254,249, 6, 77, 0, 17,
+ 0, 0, 1, 54, 51, 50, 23, 22, 23, 51, 38, 39, 38, 35, 34, 7, 6, 7, 21, 54,253, 18, 93, 91, 70, 56, 48, 11,118, 10, 79, 86,
+138,124,120, 72,141,138, 5,149, 47, 42, 36, 77,143, 72, 77, 67, 41, 40,134, 23, 0, 1,252, 34, 4,227,254,248, 6,117, 0, 7,
+ 0, 0, 1, 21, 33, 21, 35, 17, 51, 21,254,248,253,192,150,150, 5,247,150,126, 1,146,126, 0, 0, 1,252, 34, 4,227,254,248,
+ 6,117, 0, 7, 0, 0, 1, 33, 53, 51, 17, 35, 53, 33,252, 34, 2, 64,150,150,253,192, 5,247,126,254,110,126,255,255,247,214,
+254,144, 3, 70, 7, 96, 16, 43, 2, 49,255,142, 4,216,192, 0, 16, 43, 2, 49,251, 15, 8,177,192, 0, 16, 43, 2, 49, 4, 13,
+ 8,177,192, 0, 16, 43, 2, 49,252, 96, 5,249,192, 0, 16, 43, 2, 49, 2,188, 5,249,192, 0, 16, 43, 2, 49,252, 96, 11,105,
+192, 0, 16, 43, 2, 49, 2,188, 11,105,192, 0, 16, 11, 2, 49,255,142, 12,137,192, 0, 0, 0, 0, 8,248, 88,253,195, 2,194,
+ 8, 45, 0, 5, 0, 11, 0, 17, 0, 23, 0, 29, 0, 35, 0, 41, 0, 47, 0, 0, 39, 55, 23, 19, 7, 3, 1, 7, 39, 3, 55, 19,
+ 1, 39, 55, 37, 23, 5, 1, 23, 7, 5, 39, 37, 1, 53, 51, 5, 21, 45, 1, 21, 35, 37, 53, 5, 1, 35, 53, 19, 51, 11, 1, 51,
+ 21, 3, 35, 19,107,150,121,111, 92,169,251,119,150,121,111, 92,169, 5, 31,150,122, 1, 86, 92,254,227,250, 76,149,121,254,169,
+ 91, 1, 28, 6, 96,172, 1, 64,254,192,248,194,172,254,192, 1, 64, 4, 95,211,164,129, 82,211,211,164,129, 82, 90,150,121,254,
+169, 92, 1, 29, 5,181,150,121, 1, 87, 92,254,227,254,241,149,122,110, 91,169,251,119,150,121,111, 92,168, 2, 24,212,164,130,
+ 82,212,212,164,130, 82, 2,223,172, 1, 64,254,192,248,194,172,254,192, 1, 64, 0, 1, 0,201,254, 86, 5,252, 5,213, 0, 14,
+ 0, 0, 33, 35, 17, 1, 33, 17, 51, 17, 1, 33, 17, 51, 21, 1, 35, 5, 51,196,253,106,254,240,196, 2,150, 1, 16,201,254,146,
+134, 4,225,251, 31, 5,213,251, 31, 4,225,250,213,170,254, 86, 0, 2, 0,193,254, 86, 5, 56, 6, 20, 0, 14, 0, 28, 0, 0,
+ 33, 35, 17, 1, 35, 17, 51, 17, 1, 51, 17, 51, 21, 1, 35, 1, 51, 30, 1, 51, 50, 54, 55, 51, 14, 1, 35, 34, 38, 4,128,183,
+253,228,236,183, 2, 27,237,184,254,222,123,253,205,118, 10, 98, 86, 86, 96, 14,118, 10,158,146,144,158, 3,131,252,125, 4, 96,
+252,127, 3,129,252, 57,153,254, 86, 7,190, 75, 75, 74, 76,143,144,144, 0, 0, 0, 2, 0, 33, 0, 0, 4,236, 5,213, 0, 18,
+ 0, 29, 0, 0, 1, 21, 33, 50, 4, 21, 20, 4, 35, 33, 17, 35, 53, 51, 53, 51, 21, 51, 21, 1, 52, 39, 38, 35, 33, 17, 33, 50,
+ 55, 54, 1,147, 1, 78,251, 1, 16,254,240,251,253,232,168,168,202,168, 1,220, 79, 78,163,254,188, 1, 68,163, 78, 79, 4, 81,
+226,218,222,221,218, 4, 81,164,224,224,164,253,102,139, 68, 67,253,221, 68, 67, 0, 2, 0, 38, 0, 0, 4, 69, 5,158, 0, 10,
+ 0, 30, 0, 0, 1, 52, 39, 38, 35, 33, 17, 33, 50, 55, 54, 1, 17, 33, 50, 23, 22, 16, 7, 6, 35, 33, 17, 35, 53, 51, 17, 51,
+ 17, 51, 21, 3,129, 62, 67,128,254,249, 1, 7,129, 66, 62,253,248, 1, 15,208,121,116,116,115,214,254, 57,155,155,184,157, 1,
+ 76, 94, 42, 46,254,151, 46, 43, 2,223,254,202, 85, 82,254,176, 82, 82, 3,209,143, 1, 62,254,194,143, 0, 0, 0, 2, 0,201,
+ 0, 0, 4,225, 5,213, 0, 14, 0, 27, 0, 0, 1, 23, 7, 39, 6, 43, 1, 17, 35, 17, 33, 50, 4, 21, 20, 39, 54, 55, 52, 38,
+ 43, 1, 17, 51, 50, 55, 39, 55, 4, 85,140,106,146,126,214,254,202, 1,200,251, 1, 1,226, 12, 1,154,141,254,254,114, 71,215,
+106, 3, 35,117,126,123, 83,253,168, 5,213,227,219,146, 45, 44, 57,134,146,253,207, 47,180,126, 0, 2, 0,186,254, 86, 4,164,
+ 4,123, 0, 13, 0, 35, 0, 0, 37, 39, 55, 23, 54, 53, 52, 38, 32, 6, 16, 22, 51, 50, 5, 23, 7, 39, 6, 35, 34, 38, 39, 17,
+ 35, 17, 51, 21, 62, 1, 51, 50, 0, 16, 7, 6, 3, 42,140,110,138, 79,167,254,220,167,167,146, 70, 1, 27,147,111,149, 87,108,
+123,177, 58,185,185, 58,177,123,204, 0,255,128, 12,152,167, 93,165,115,197,203,231,231,254,106,231, 20,174, 93,179, 46, 97,100,
+253,174, 6, 10,170,100, 97,254,188,253,240,162, 15, 0, 0, 0, 0, 1, 0,201, 0, 0, 4,106, 7, 7, 0, 7, 0, 27, 64, 13,
+ 3, 6,149, 1,129, 0, 3, 4, 6, 28, 1, 4, 8, 16,252,252,220,204, 49, 0, 47,244,236,204, 48, 51, 17, 33, 17, 51, 17, 33,
+ 17,201, 2,216,201,253, 41, 5,213, 1, 50,254, 36,250,213, 0, 0, 1, 0,186, 0, 0, 3,208, 5,154, 0, 7, 0, 27, 64, 13,
+ 3, 6,169, 1,188, 0, 3, 4, 6, 8, 1, 70, 8, 16,252,252,220,204, 49, 0, 47,244,236,204, 48, 51, 17, 33, 17, 51, 17, 33,
+ 17,186, 2, 94,184,253,162, 4, 96, 1, 58,254, 28,252, 74, 0, 0, 1, 0, 71, 0, 0, 4,106, 5,213, 0, 13, 0, 0, 19, 51,
+ 17, 33, 21, 33, 17, 33, 21, 33, 17, 35, 17, 35, 71,130, 3,161,253, 41, 2, 35,253,221,202,130, 3,232, 1,237,170,254,189,170,
+252,194, 3, 62, 0, 1, 0, 56, 0, 0, 3,208, 4, 96, 0, 13, 0, 0, 51, 17, 35, 53, 51, 17, 33, 21, 33, 17, 33, 21, 33, 17,
+186,130,130, 3, 22,253,162, 1,160,254, 96, 1,244,170, 1,194,170,254,232,170,254, 12, 0, 0, 0, 1, 0,201,254,102, 4,204,
+ 5,213, 0, 27, 0, 0, 1, 17, 35, 17, 33, 21, 33, 17, 33, 50, 23, 22, 21, 17, 16, 6, 43, 1, 53, 51, 50, 55, 54, 53, 17, 52,
+ 38, 35, 1,147,202, 3,161,253, 41, 1,161,186,113,109,204,228, 76, 62,134, 56, 55,124,124, 2,199,253, 57, 5,213,170,254, 70,
+119,114,238,254,206,254,242,244,170, 75, 75,194, 1, 34,159,158, 0, 1, 0,186,254, 86, 4, 11, 4, 96, 0, 29, 0, 0, 1, 17,
+ 35, 17, 33, 21, 33, 17, 51, 32, 23, 22, 21, 17, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 53, 17, 52, 39, 38, 35, 1,114,184, 3,
+ 22,253,162,250, 1, 7, 70, 82, 82, 81,181,193,172,110, 33, 38, 38, 49,134, 1,231,254, 25, 4, 96,170,254,193, 71, 81,229,254,
+242,214, 96, 96,156, 48, 55,147, 1, 8,170, 32, 41, 0, 0, 0, 0, 1, 0, 59,254, 86, 6,194, 5,213, 0, 25, 0, 0, 37, 51,
+ 17, 35, 17, 35, 1, 35, 17, 35, 17, 35, 1, 35, 9, 1, 51, 1, 51, 17, 51, 17, 51, 1, 51, 1, 6, 87,107,197, 41,254,155,150,
+202,150,254,155,217, 1,144,254,162,217, 1, 52,149,202,149, 1, 52,217,254,162,170,253,172, 1,170, 2,199,253, 57, 2,199,253,
+ 57, 3, 28, 2,185,253,156, 2,100,253,156, 2,100,253, 71, 0, 0, 1, 0, 50,254, 86, 5,193, 4, 96, 0, 25, 0, 0, 37, 51,
+ 17, 35, 17, 35, 1, 35, 17, 35, 17, 35, 1, 35, 9, 1, 51, 1, 51, 17, 51, 17, 51, 1, 51, 1, 5, 85,108,184, 33,254,213,114,
+183,114,254,213,197, 1, 84,254,215,196, 1, 2,113,183,113, 1, 2,196,254,215,153,253,189, 1,170, 2, 9,253,247, 2, 9,253,
+247, 2, 85, 2, 11,254, 65, 1,191,254, 65, 1,191,253,245, 0,255,255, 0,156,254,117, 4,115, 5,240, 16, 38, 0,122, 57, 0,
+ 16, 6, 3, 52, 0, 0, 0, 0,255,255, 0,133,254,117, 3,200, 4,124, 16, 38, 0,122,206, 0, 16, 6, 3, 84, 0, 0, 0, 0,
+ 0, 1, 0,201,254, 86, 5,106, 5,213, 0, 14, 0, 0, 37, 51, 17, 35, 17, 35, 1, 17, 35, 17, 51, 17, 1, 33, 1, 4,193,169,
+197, 69,253, 51,202,202, 2,158, 1, 4,253, 27,170,253,172, 1,170, 2,207,253, 49, 5,213,253,137, 2,119,253, 72, 0, 0, 0,
+ 0, 1, 0,191,254, 86, 4,161, 4, 96, 0, 14, 0, 0, 37, 51, 17, 35, 17, 35, 1, 17, 35, 17, 51, 17, 1, 51, 1, 4, 2,159,
+184, 56,253,199,185,185, 2, 37,235,253,174,153,253,189, 1,170, 2, 35,253,221, 4, 96,254, 29, 1,227,253,244, 0, 1, 0,201,
+ 0, 0, 5,106, 5,213, 0, 18, 0, 0, 1, 39, 17, 35, 17, 51, 17, 55, 17, 51, 21, 1, 33, 9, 1, 33, 1, 21, 35, 1,224, 77,
+202,202, 77,100, 1,237, 1, 4,253, 27, 3, 26,254,246,253,228,100, 2,130, 77,253, 49, 5,213,253,137, 73, 1, 81,243, 1,208,
+253, 72,252,227, 2, 30,248, 0, 0, 1, 0,191, 0, 0, 4,161, 4, 96, 0, 18, 0, 0, 1, 21, 35, 53, 39, 17, 35, 17, 51, 17,
+ 55, 53, 55, 21, 1, 51, 9, 1, 35, 2, 29,101, 64,185,185, 64,101, 1,128,235,253,174, 2,107,240, 1,132,138,235, 62,253,221,
+ 4, 96,254, 29, 56,217, 2,130, 1, 82,253,244,253,172, 0, 0, 0, 1, 0, 33, 0, 0, 5,106, 5,213, 0, 18, 0, 0, 19, 35,
+ 53, 51, 53, 51, 21, 51, 21, 35, 21, 1, 33, 9, 1, 33, 1, 17, 35,201,168,168,202,168,168, 2,158, 1, 4,253, 27, 3, 26,254,
+246,253, 51,202, 4, 81,164,224,224,164,243, 2,119,253, 72,252,227, 2,207,253, 49, 0, 0, 0, 0, 1, 0, 61, 0, 0, 4,156,
+ 6, 20, 0, 18, 0, 0, 1, 17, 1, 51, 9, 1, 35, 1, 17, 35, 17, 35, 53, 51, 53, 51, 21, 33, 21, 1,115, 2, 37,235,253,174,
+ 2,107,240,253,199,185,125,125,185, 1, 96, 4,246,253,135, 1,227,253,244,253,172, 2, 35,253,221, 4,246,164,122,122,164, 0,
+ 0, 1, 0, 50, 0, 0, 6,150, 5,213, 0, 12, 0, 0, 1, 33, 53, 33, 17, 1, 33, 9, 1, 33, 1, 17, 35, 1,245,254, 61, 2,
+141, 2,158, 1, 4,253, 27, 3, 26,254,246,253, 51,202, 5, 43,170,253,137, 2,119,253, 72,252,227, 2,207,253, 49, 0, 0, 0,
+ 0, 1, 0, 42, 0, 0, 5,139, 4, 96, 0, 12, 0, 0, 1, 33, 53, 33, 17, 1, 51, 9, 1, 35, 1, 17, 35, 1,169,254,129, 2,
+ 56, 2, 37,235,253,174, 2,107,240,253,199,185, 3,198,154,254, 29, 1,227,253,244,253,172, 2, 35,253,221, 0, 0, 1, 0,201,
+254, 86, 6, 4, 5,213, 0, 15, 0, 0, 33, 17, 33, 17, 35, 17, 51, 17, 33, 17, 51, 17, 51, 17, 35, 17, 4,113,253, 34,202,202,
+ 2,222,202,201,201, 2,199,253, 57, 5,213,253,156, 2,100,250,213,253,172, 1,170, 0, 0, 0, 0, 1, 0,193,254, 86, 5, 64,
+ 4, 96, 0, 15, 0, 0, 37, 51, 17, 35, 17, 35, 17, 33, 17, 35, 17, 51, 17, 33, 17, 51, 4,136,184,184,184,253,169,184,184, 2,
+ 87,184,153,253,189, 1,170, 2, 4,253,252, 4, 96,254, 51, 1,205, 0, 0, 0, 0, 1, 0,201, 0, 0, 8, 18, 5,213, 0, 13,
+ 0, 0, 1, 17, 35, 17, 33, 17, 35, 17, 51, 17, 33, 17, 33, 21, 5, 59,202,253, 34,202,202, 2,222, 3,161, 5, 43,250,213, 2,
+199,253, 57, 5,213,253,156, 2,100,170, 0, 0, 0, 1, 0,193, 0, 0, 6,230, 4, 96, 0, 13, 0, 0, 1, 17, 35, 17, 33, 17,
+ 35, 17, 51, 17, 33, 17, 33, 21, 4,136,184,253,169,184,184, 2, 87, 3, 22, 3,182,252, 74, 2, 4,253,252, 4, 96,254, 51, 1,
+205,170, 0, 0, 0, 1, 0,201,254,102, 8,116, 5,213, 0, 29, 0, 0, 1, 17, 35, 17, 33, 17, 35, 17, 33, 17, 33, 50, 23, 22,
+ 21, 17, 16, 6, 43, 1, 53, 51, 50, 55, 54, 53, 17, 52, 38, 35, 5, 59,202,253, 34,202, 4,114, 1,161,186,113,109,204,228, 76,
+ 62,134, 56, 55,124,124, 2,199,253, 57, 5, 43,250,213, 5,213,253,156,119,114,238,254,206,254,242,244,170, 75, 75,194, 1, 34,
+159,158, 0, 0, 0, 1, 0,193,254, 86, 7, 33, 4, 96, 0, 31, 0, 0, 1, 17, 35, 17, 33, 17, 35, 17, 33, 17, 51, 32, 23, 22,
+ 21, 17, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 53, 17, 52, 39, 38, 7, 4,136,184,253,169,184, 3,199,250, 1, 7, 70, 82, 82,
+ 81,181,193,172,110, 33, 38, 38, 49,134, 1,231,254, 25, 3,198,252, 58, 4, 96,254, 23, 71, 81,229,254,242,214, 96, 96,156, 48,
+ 55,147, 1, 8,164, 38, 46, 5, 0, 2, 0,115,255, 45, 6, 39, 5,240, 0, 50, 0, 64, 0, 0, 37, 38, 17, 52, 55, 54, 51, 50,
+ 22, 21, 20, 7, 6, 7, 22, 51, 50, 55, 21, 6, 35, 4, 39, 6, 35, 36, 39, 38, 17, 16, 55, 54, 33, 50, 23, 22, 23, 21, 38, 39,
+ 38, 35, 32, 7, 6, 17, 16, 23, 22, 51, 50, 55, 54, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 21, 16, 3, 69,100, 96, 95,169,168,
+192,102, 74,120,117,142, 84, 71, 73, 82,254,233,190, 68, 76,254,197,188,189,195,195, 1, 83,117,135,129, 94, 92,125,125,121,255,
+ 0,136,136,130,129,220, 15,217, 73, 48, 97, 43, 43, 73, 74, 43, 43,136,185, 1, 19,220,125,125,250,220,214,157,115, 63, 93, 24,
+166, 22, 1,192, 10, 1,209,210, 1, 98, 1,104,207,208, 36, 34, 62,183, 55, 47, 47,156,157,254,216,254,232,166,164, 46, 36, 63,
+127,214,120, 69, 71, 69, 70,121,254,228, 0, 0, 0, 2, 0,113,255, 82, 5, 4, 4,123, 0, 12, 0, 63, 0, 0, 37, 54, 55, 54,
+ 53, 52, 38, 35, 34, 7, 6, 21, 20, 7, 38, 53, 52, 55, 54, 51, 22, 23, 22, 21, 20, 7, 6, 7, 22, 51, 50, 55, 21, 6, 35, 34,
+ 39, 6, 35, 32, 39, 38, 17, 16, 55, 54, 33, 50, 23, 22, 23, 21, 38, 39, 38, 35, 34, 7, 6, 21, 20, 23, 22, 51, 3, 87, 33, 22,
+ 86, 48, 41, 44, 24, 27,143, 51, 77, 78,131,132, 78, 77,137, 39, 56, 72,101, 90, 62, 70, 82,235,137, 53, 60,254,253,138,137,151,
+150, 1, 6, 85, 81, 81, 76, 67, 90, 73, 85,179, 99, 99, 85, 84,171,173, 21, 29,113,135, 72, 84, 42, 46, 78,179,155,133,194,155,
+ 87, 88, 1, 88, 87,165,181,154, 44, 30, 52, 20,158, 18,151, 6,157,156, 1, 19, 1, 18,157,157, 17, 18, 35,152, 25, 22, 19,113,
+114,205,201,116,115, 0, 0, 0,255,255, 0,115,254,117, 5, 39, 5,240, 16, 39, 0,122, 1, 45, 0, 0, 16, 6, 3, 62, 0, 0,
+255,255, 0,113,254,117, 3,231, 4,123, 16, 39, 0,122, 0,143, 0, 0, 16, 6, 3, 94, 0, 0, 0, 1,255,250,254, 86, 4,233,
+ 5,213, 0, 11, 0, 0, 37, 51, 17, 35, 17, 35, 17, 33, 53, 33, 21, 33, 2,215,201,201,203,253,238, 4,239,253,238,170,253,172,
+ 1,170, 5, 43,170,170, 0, 0, 0, 1, 0, 5,254, 86, 4, 54, 4, 96, 0, 11, 0, 0, 37, 51, 17, 35, 17, 35, 17, 33, 53, 33,
+ 21, 33, 2,120,184,184,181,254, 66, 4, 49,254, 66,153,253,189, 1,170, 3,182,170,170, 0, 0,255,255,255,252, 0, 0, 4,231,
+ 5,213, 18, 6, 0, 60, 0, 0, 0, 1, 0, 61,254, 86, 4,127, 4, 96, 0, 8, 0, 0, 37, 17, 35, 17, 1, 51, 9, 1, 51, 2,
+197,195,254, 59,195, 1, 94, 1, 94,195, 18,254, 68, 1,188, 4, 78,252,148, 3,108, 0, 0, 0, 0, 1,255,252, 0, 0, 4,231,
+ 5,213, 0, 14, 0, 0, 9, 1, 51, 9, 1, 51, 1, 33, 21, 33, 17, 35, 17, 33, 53, 2, 12,253,240,217, 1,158, 1,155,217,253,
+240, 2, 12,253,244,203,253,244, 2,199, 3, 14,253,154, 2,102,252,242,170,253,227, 2, 29,170, 0, 1, 0, 61,254, 86, 4,127,
+ 4, 96, 0, 14, 0, 0, 5, 17, 35, 17, 33, 53, 33, 1, 51, 9, 1, 51, 1, 33, 21, 2,197,195,254, 59, 1,197,254, 59,195, 1,
+ 94, 1, 94,195,254, 70, 1,186,124,254,210, 1, 46,142, 4, 78,252,148, 3,108,251,178,142, 0, 0, 1, 0, 61,254, 86, 5, 59,
+ 5,213, 0, 15, 0, 0, 37, 51, 17, 35, 17, 35, 9, 1, 35, 9, 1, 51, 9, 1, 51, 1, 4,203,112,197, 20,254, 92,254, 89,218,
+ 2, 21,254, 47,217, 1,115, 1,117,217,254, 32,170,253,172, 1,170, 2,123,253,133, 3, 29, 2,184,253,213, 2, 43,253, 51, 0,
+ 0, 1, 0, 59,254, 86, 4,121, 4, 96, 0, 15, 0, 0, 37, 51, 17, 35, 17, 35, 9, 1, 35, 9, 1, 51, 9, 1, 51, 1, 4, 8,
+113,184, 33,254,186,254,186,217, 1,179,254,114,217, 1, 41, 1, 41,217,254,107,153,253,189, 1,170, 1,184,254, 72, 2, 74, 2,
+ 22,254,113, 1,143,253,223, 0, 0, 1,255,250,254, 86, 7, 71, 5,213, 0, 15, 0, 0, 37, 33, 17, 51, 17, 51, 17, 35, 17, 33,
+ 17, 33, 53, 33, 21, 33, 2,214, 2,222,202,201,201,251,142,253,238, 4,239,253,238,170, 5, 43,250,213,253,172, 1,170, 5, 43,
+170,170, 0, 0, 0, 1, 0, 5,254, 86, 6, 66, 4, 96, 0, 15, 0, 0, 37, 33, 17, 51, 17, 51, 17, 35, 17, 33, 17, 33, 53, 33,
+ 21, 33, 2,120, 2, 90,184,184,184,252, 57,254, 66, 4, 49,254, 66,153, 3,199,252, 57,253,189, 1,170, 3,182,170,170, 0, 0,
+ 0, 1, 0,175,254, 86, 5,124, 5,213, 0, 20, 0, 0, 37, 51, 17, 35, 17, 35, 17, 33, 34, 39, 38, 53, 17, 51, 17, 20, 22, 51,
+ 33, 17, 51, 4,179,201,201,203,254, 95,186,113,109,201,124,124, 1,120,203,170,253,172, 1,170, 2,199,119,114,238, 1, 55,254,
+217,159,158, 2,100, 0, 0, 0, 0, 1, 0,150,254, 86, 4,184, 4, 96, 0, 21, 0, 0, 37, 51, 17, 35, 17, 35, 17, 33, 34, 39,
+ 38, 61, 1, 51, 21, 20, 23, 22, 51, 33, 17, 51, 4, 0,184,184,184,254,169,153,102, 92,184, 52, 53,104, 1, 41,184,153,253,189,
+ 1,170, 2, 9, 95, 86,184,234,211,117, 59, 59, 1,190, 0, 0, 0, 1, 0,175, 0, 0, 4,179, 5,213, 0, 24, 0, 0, 1, 35,
+ 34, 39, 38, 53, 17, 51, 17, 20, 22, 59, 1, 17, 51, 17, 51, 17, 51, 17, 35, 17, 35, 17, 35, 2,130, 59,186,113,109,201,124,124,
+ 18,144,214,203,203,214,144, 2,199,119,114,238, 1, 55,254,217,159,158, 1, 57,254,199, 2,100,250, 43, 2,199,254,207, 0, 0,
+ 0, 1, 0,150, 0, 0, 4, 0, 4, 96, 0, 24, 0, 0, 1, 53, 51, 21, 51, 17, 51, 17, 35, 17, 35, 21, 35, 53, 35, 34, 39, 38,
+ 61, 1, 51, 21, 20, 23, 22, 1,249,160,175,184,184,175,160, 8,153,102, 92,184, 52, 43, 2,164,194,196, 1,190,251,160, 2, 9,
+196,196, 95, 86,184,234,211,117, 59, 48, 0, 0, 0, 1, 0,175, 0, 0, 4,179, 5,213, 0, 16, 0, 0, 1, 17, 33, 50, 23, 22,
+ 21, 17, 35, 17, 52, 38, 35, 33, 17, 35, 17, 1,122, 1,161,186,113,109,201,124,124,254,136,203, 5,213,253,156,119,114,238,254,
+102, 1,138,159,158,253, 57, 5,213, 0, 0, 0,255,255, 0,186, 0, 0, 4,100, 6, 20, 16, 6, 0, 75, 0, 0, 0, 2, 0, 20,
+255,227, 7, 20, 5,240, 0, 33, 0, 41, 0, 0, 1, 18, 55, 54, 33, 32, 23, 22, 19, 33, 16, 0, 33, 50, 54, 55, 21, 6, 4, 35,
+ 32, 39, 38, 3, 6, 39, 38, 61, 1, 51, 21, 20, 23, 22, 37, 33, 38, 39, 38, 32, 7, 6, 1,178, 34,150,188, 1, 58, 1, 67,181,
+187, 1,251,112, 1, 18, 1, 18,139,252,112,111,254,249,146,254,162,197,188, 10,170,118,122,170, 75, 66, 1, 64, 3,173, 24, 98,
+130,254, 72,128, 97, 3,109, 1, 7,170,210,210,219,254,132,254,244,254,206, 96, 95,215, 70, 72,205,194, 1, 85, 1,103,107,223,
+ 76, 62,157, 68, 57, 2,191,124,164,164,124, 0, 0, 2, 0, 15,255,226, 5,102, 4,123, 0, 34, 0, 41, 0, 0, 1, 34, 39, 38,
+ 61, 1, 51, 21, 20, 23, 22, 51, 54, 55, 54, 33, 50, 0, 29, 1, 33, 30, 1, 51, 50, 54, 55, 21, 6, 7, 6, 39, 36, 39, 38, 1,
+ 46, 1, 35, 34, 6, 7, 1, 88,144, 89, 96,156, 48, 57, 74, 26,116,146, 0,255,226, 1, 7,252,178, 12,205,183,106,199, 98, 99,
+104,110,101,254,243,156,148, 3, 78, 2,165,136,154,185, 14, 2, 4, 82, 90,172, 70, 49,151, 33, 38,197,130,161,254,221,250, 90,
+190,199, 52, 52,174, 42, 22, 23, 1, 5,151,144, 1,133,151,180,174,158, 0, 0,255,255, 0, 20,254,117, 7, 20, 5,240, 16, 39,
+ 2, 52, 2,188, 0, 0, 16, 6, 3,216, 0, 0,255,255, 0, 15,254,117, 5,102, 4,123, 16, 39, 2, 52, 1,231, 0, 0, 16, 6,
+ 3,217, 0, 0,255,255, 0,193, 0, 0, 1,121, 6, 20, 16, 6, 0, 79, 0, 0,255,255, 0, 59, 0, 0, 6,173, 5,213, 16, 39,
+ 6,139, 5,116, 1,117, 17, 6, 3, 51, 0, 0, 0, 8,180, 34, 0, 8, 35, 7, 43, 49, 0, 0,255,255, 0, 50, 0, 0, 5,173,
+ 6, 72, 16, 39, 2, 49, 0,240, 0, 0, 19, 6, 3, 83, 0, 0, 0, 8,180, 34, 0, 8, 35, 7, 43, 49, 0, 0, 0, 1, 0,201,
+254,102, 5, 53, 5,213, 0, 28, 0, 0, 1, 51, 50, 23, 22, 21, 17, 16, 6, 43, 1, 53, 51, 50, 55, 54, 53, 17, 52, 38, 35, 33,
+ 17, 35, 17, 51, 17, 1, 33, 2,169,139,186,113,109,204,228, 76, 62,134, 56, 55,124,124,254,136,202,202, 2,158, 1, 4, 3,113,
+119,114,238,254,206,254,242,244,170, 75, 75,194, 1, 34,159,158,253, 57, 5,213,253,137, 2,119, 0, 1, 0,191,254, 86, 4,136,
+ 4, 96, 0, 30, 0, 0, 1, 51, 32, 23, 22, 21, 17, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 53, 17, 52, 39, 38, 35, 33, 17, 35,
+ 17, 51, 17, 1, 51, 2, 94, 20, 1, 5, 72, 82, 82, 81,181,193,172,110, 33, 38, 38, 44,139,254,252,185,185, 2, 37,235, 2,119,
+ 71, 81,229,254,242,214, 96, 96,156, 48, 55,147, 1, 8,166, 36, 41,254, 25, 4, 96,254, 29, 1,227, 0, 0, 0, 0, 1, 0, 54,
+254, 86, 6, 3, 5,213, 0, 20, 0, 0, 33, 35, 17, 33, 21, 16, 3, 6, 5, 53, 54, 55, 18, 25, 1, 33, 17, 51, 21, 1, 35, 5,
+ 58,202,254, 27,132, 98,254,145,212, 67,117, 3,120,201,254,146,134, 5, 43,212,254, 24,254,170,253, 56,167, 46,168, 1, 37, 2,
+ 53, 1, 26,250,213,170,254, 86, 0, 2, 0, 46,254, 86, 5, 43, 4, 96, 0, 0, 0, 21, 0, 0, 9, 1, 51, 21, 1, 35, 19, 35,
+ 17, 33, 21, 16, 3, 6, 5, 53, 54, 55, 54, 17, 53, 33,253,180, 6,191,184,254,222,123,229,184,254,123,118, 94,254,204,179, 59,
+ 98, 2,245, 8, 0,248,153,153,254, 86, 1,170, 3,199,134,254,146,254,252,207, 29,153, 27,127,207, 1,167,212, 0, 1, 0,201,
+254,102, 5, 59, 5,213, 0, 21, 0, 0, 37, 17, 33, 17, 35, 17, 51, 17, 33, 17, 51, 17, 16, 7, 6, 43, 1, 53, 51, 50, 55, 54,
+ 4,113,253, 34,202,202, 2,222,202,103,103,227, 76, 62,134, 56, 55,104, 2, 95,253, 57, 5,213,253,156, 2,100,250,147,254,242,
+122,122,170, 75, 75, 0, 0, 0, 0, 1, 0,193,254, 86, 4,136, 4, 96, 0, 21, 0, 0, 5, 17, 33, 17, 35, 17, 51, 17, 33, 17,
+ 51, 17, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 3,208,253,169,184,184, 2, 87,184, 82, 81,181,193,172,110, 33, 38, 20, 2, 24,
+253,252, 4, 96,254, 51, 1,205,251,140,214, 96, 96,156, 48, 55, 0, 1, 0,201,254, 86, 6, 4, 5,213, 0, 16, 0, 0, 33, 35,
+ 17, 33, 17, 35, 17, 51, 17, 33, 17, 51, 17, 51, 21, 1, 35, 5, 59,202,253, 34,202,202, 2,222,202,201,254,146,134, 2,199,253,
+ 57, 5,213,253,156, 2,100,250,213,170,254, 86, 0, 1, 0,193,254, 86, 5, 64, 4, 96, 0, 16, 0, 0, 33, 35, 17, 33, 17, 35,
+ 17, 51, 17, 33, 17, 51, 17, 51, 21, 1, 35, 4,136,184,253,169,184,184, 2, 87,184,184,254,222,123, 2, 4,253,252, 4, 96,254,
+ 51, 1,205,252, 57,153,254, 86, 0, 1, 0,175,254, 86, 4,179, 5,213, 0, 20, 0, 0, 37, 17, 33, 34, 39, 38, 53, 17, 51, 17,
+ 20, 22, 51, 33, 17, 51, 17, 35, 17, 35, 17, 3,232,254, 95,186,113,109,201,124,124, 1,120,203,203,201,170, 2, 29,119,114,238,
+ 1, 55,254,217,159,158, 2,100,250, 43,254, 86, 2, 84, 0, 0, 0, 1, 0,150,254, 86, 4, 0, 4, 96, 0, 21, 0, 0, 37, 17,
+ 33, 34, 39, 38, 61, 1, 51, 21, 20, 23, 22, 51, 33, 17, 51, 17, 35, 17, 35, 17, 3, 72,254,169,153,102, 92,184, 52, 53,104, 1,
+ 41,184,184,184,153, 1,112, 95, 86,184,234,211,117, 59, 59, 1,190,251,160,254, 86, 2, 67, 0, 0, 1, 0,201,254, 86, 6,232,
+ 5,213, 0, 17, 0, 0, 37, 51, 21, 1, 35, 1, 35, 17, 1, 35, 1, 17, 35, 17, 33, 9, 1, 33, 6, 31,201,254,146,134, 1, 43,
+197,254,127,203,254,127,196, 1, 45, 1,125, 1,127, 1, 45,170,170,254, 86, 1,170, 5, 31,252, 0, 4, 0,250,225, 5,213,252,
+ 8, 3,248, 0, 0, 1, 0,193,254, 86, 6, 0, 4, 96, 0, 17, 0, 0, 37, 51, 21, 1, 35, 19, 35, 17, 1, 35, 1, 17, 35, 17,
+ 33, 9, 1, 33, 5, 72,184,254,222,123,229,178,254,203,184,254,202,178, 1, 6, 1, 62, 1, 63, 1, 4,153,153,254, 86, 1,170,
+ 3,176,253, 39, 2,217,252, 80, 4, 96,253, 18, 2,238, 0, 0,255,255, 0, 16, 0, 0, 5,104, 7,146, 16, 39, 2, 49, 0,206,
+ 1, 74, 17, 6, 3, 45, 0, 0, 0, 18,180, 24, 0, 8, 19, 7, 43, 49, 0, 64, 5,111, 0,111, 8, 2, 93, 48,255,255, 0,123,
+255,227, 4, 45, 6, 31, 16, 38, 2, 49, 79,215, 19, 6, 3, 77, 0, 0, 0, 8,180, 34, 0, 8, 25, 7, 43, 49,255,255, 0, 16,
+ 0, 0, 5,104, 5,213, 16, 38, 3, 45, 0, 0, 17, 7, 6,132, 4,188, 1,117, 0, 20,180, 10, 18, 13, 5, 7, 43, 64, 9, 48,
+ 18, 63, 13, 0, 18, 15, 13, 4, 93, 49, 0, 0,255,255, 0,123,255,227, 4, 45, 6, 16, 18, 38, 3, 77, 0, 0, 17, 6, 0,106,
+ 82, 0, 0, 32,180, 20, 45, 40, 11, 7, 43, 64, 21,127, 40,111, 40, 80, 45, 95, 40, 64, 45, 79, 40, 48, 45, 63, 40, 0, 45, 15,
+ 40, 10, 93, 49,255,255, 0, 8, 0, 0, 7, 72, 5,213, 18, 6, 0,136, 0, 0,255,255, 0,123,255,227, 7,111, 4,123, 18, 6,
+ 0,168, 0, 0,255,255, 0,201, 0, 0, 4,139, 5,213, 16, 39, 6,139, 4,161, 1,117, 17, 6, 3, 50, 0, 0, 0, 7, 64, 3,
+ 64, 0, 1, 93, 49, 0, 0, 0,255,255, 0,113,255,227, 4,127, 6, 72, 16, 39, 2, 49, 0,150, 0, 0, 19, 6, 3, 82, 0, 0,
+ 0, 7, 64, 3,112, 0, 1, 93, 49, 0, 0, 0,255,255, 0,117,255,227, 5,217, 5,240, 16, 6, 1, 81, 0, 0,255,255, 0, 0,
+ 0, 0, 0, 0, 0, 0, 16, 6, 2, 4, 0, 0,255,255, 0,117,255,227, 5,217, 5,240, 16, 39, 6,132, 5, 32, 1,117, 16, 6,
+ 3,243, 0, 0,255,255, 1, 43, 5, 70, 3,125, 6, 16, 16, 38, 0,106, 84, 0, 16, 6, 3,244, 0, 0, 0, 0,255,255, 0, 59,
+ 0, 0, 6,173, 5,213, 16, 39, 6,132, 5,116, 1,117, 17, 6, 3, 51, 0, 0, 0, 8,180, 28, 7, 2, 29, 7, 43, 49, 0, 0,
+255,255, 0, 50, 0, 0, 5,173, 6, 16, 16, 39, 0,106, 0,240, 0, 0, 18, 6, 3, 83, 0, 0,255,255, 0,156,255,227, 4,115,
+ 5,240, 16, 39, 6,132, 4,135, 1,117, 16, 6, 3, 52, 0, 0,255,255, 0,133,255,227, 3,200, 6, 16, 16, 38, 0,106, 58, 0,
+ 16, 6, 3, 84, 0, 0, 0, 0,255,255, 0,160,255,193, 4,248, 5,213, 16, 6, 1,121, 0, 0,255,255, 0, 0, 0, 0, 0, 0,
+ 0, 0, 16, 6, 2, 8, 0, 0,255,255, 0,201, 0, 0, 5, 51, 7, 49, 16, 39, 0,113, 0,245, 1, 59, 16, 6, 3, 53, 0, 0,
+255,255, 0,193, 0, 0, 4,128, 5,245, 16, 39, 0,113, 0,137,255,255, 16, 6, 3, 85, 0, 0,255,255, 0,201, 0, 0, 5, 51,
+ 5,213, 16, 39, 6,132, 4,245, 1,117, 16, 6, 3, 53, 0, 0,255,255, 0,193, 0, 0, 4,128, 6, 16, 16, 39, 0,106, 0,137,
+ 0, 0, 16, 6, 3, 85, 0, 0,255,255, 0,115,255,227, 5,217, 5,240, 16, 38, 3, 59, 0, 0, 17, 7, 6,132, 5, 39, 1,117,
+ 0, 20,180, 3, 31, 26, 9, 7, 43, 64, 9, 64, 31, 79, 26, 16, 31, 31, 26, 4, 93, 49, 0, 0,255,255, 0,113,255,227, 4,117,
+ 6, 16, 18, 38, 3, 91, 0, 0, 17, 6, 0,106,115, 0, 0, 20,180, 3, 31, 26, 9, 7, 43, 64, 9, 64, 31, 79, 26, 48, 31, 63,
+ 26, 4, 93, 49,255,255, 0,115,255,227, 5,217, 5,240, 16, 6, 3, 17, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 16, 6,
+ 2, 7, 0, 0,255,255, 0,115,255,227, 5,217, 5,240, 18, 38, 4, 3, 0, 0, 16, 7, 6,132, 5, 39, 1,117,255,255, 1, 74,
+ 5, 70, 3,156, 6, 16, 18, 38, 4, 4, 0, 0, 16, 6, 0,106,115, 0, 0, 0,255,255, 0,111,255,227, 5, 35, 5,240, 16, 39,
+ 6,132, 4,103, 1,117, 16, 6, 3, 74, 0, 0,255,255, 0,113,255,227, 3,231, 6, 16, 16, 38, 0,106,226, 0, 16, 6, 3,106,
+ 0, 0, 0, 0,255,255, 0, 35,255,227, 4,189, 7, 49, 16, 39, 0,113, 0,114, 1, 59, 16, 6, 3, 64, 0, 0,255,255, 0, 61,
+254, 86, 4,127, 5,245, 16, 38, 0,113, 94,255, 16, 6, 3, 96, 0, 0, 0, 0,255,255, 0, 35,255,227, 4,189, 5,213, 16, 39,
+ 6,132, 4,114, 1,117, 16, 6, 3, 64, 0, 0,255,255, 0, 61,254, 86, 4,127, 6, 16, 16, 38, 0,106, 94, 0, 16, 6, 3, 96,
+ 0, 0, 0, 0,255,255, 0, 35,255,227, 4,189, 5,213, 16, 39, 6,141, 4,114, 1,117, 16, 6, 3, 64, 0, 0,255,255, 0, 61,
+254, 86, 4,127, 6,102, 16, 38, 2, 54, 94, 0, 16, 6, 3, 96, 0, 0, 0, 0,255,255, 0,175, 0, 0, 4,179, 5,213, 16, 39,
+ 6,132, 4,204, 1,117, 16, 6, 3, 68, 0, 0,255,255, 0,150, 0, 0, 4, 0, 6, 16, 16, 38, 0,106, 94, 0, 16, 6, 3,100,
+ 0, 0, 0, 0, 0, 1, 0,201,254, 86, 4,106, 5,213, 0, 9, 0, 0, 37, 51, 17, 35, 17, 35, 17, 33, 21, 33, 1,147,201,201,
+202, 3,161,253, 41,170,253,172, 1,170, 5,213,170, 0, 0, 0, 0, 1, 0,186,254, 86, 3,208, 4, 96, 0, 9, 0, 0, 37, 51,
+ 17, 35, 17, 35, 17, 33, 21, 33, 1,114,184,184,184, 3, 22,253,162,153,253,189, 1,170, 4, 96,170, 0, 0, 0,255,255, 0,201,
+ 0, 0, 6, 70, 5,213, 18, 38, 3, 72, 0, 0, 16, 7, 6,132, 5,183, 1,117,255,255, 0,193, 0, 0, 5,105, 6, 16, 16, 38,
+ 3,104, 0, 0, 16, 7, 0,106, 1, 8, 0, 0, 0, 2, 0,145, 0, 0, 4,180, 5,213, 0, 10, 0, 21, 0, 0, 1, 20, 23, 22,
+ 51, 33, 17, 33, 34, 7, 6, 1, 17, 33, 34, 36, 53, 52, 36, 51, 33, 17, 1,102, 79, 78,163, 1, 68,254,188,163, 78, 79, 3, 78,
+253,232,251,254,240, 1, 16,251, 1, 78, 1,183,138, 67, 68, 2, 35, 67, 68, 3,147,250, 43,218,221,222,218, 2,102, 0, 0, 0,
+ 0, 2, 0,113, 0, 0, 3,245, 4, 96, 0, 10, 0, 22, 0, 0, 1, 20, 23, 22, 51, 33, 17, 33, 34, 7, 6, 1, 17, 33, 34, 39,
+ 38, 16, 55, 54, 51, 33, 17, 1, 53, 62, 66,129, 1, 7,254,249,128, 67, 62, 2,192,254, 57,214,115,116,116,121,208, 1, 15, 1,
+ 76, 90, 43, 46, 1,105, 46, 42, 2,182,251,160, 82, 82, 1, 80, 82, 85, 1,197, 0, 2, 0,145,255,227, 7, 67, 5,213, 0, 12,
+ 0, 48, 0, 0, 1, 33, 34, 7, 6, 16, 23, 22, 51, 50, 55, 54, 53, 19, 6, 7, 6, 7, 6, 35, 34, 39, 38, 53, 52, 36, 51, 33,
+ 17, 51, 3, 20, 23, 22, 51, 50, 55, 54, 53, 17, 51, 17, 20, 7, 6, 35, 34, 39, 38, 3,234,254,188,163, 78, 79, 79, 95,129,180,
+ 75, 86, 33, 12, 14, 51,106, 94,110,238,129,136, 1, 16,251, 1, 78,202, 1, 63, 52,112,105, 59, 63,202,110,104,215,217,102, 49,
+ 2,201, 67, 68,254,234, 80, 95,109,125,159,254,221, 29, 28, 96, 54, 49,129,137,202,222,218, 2,102,251,236,143, 91, 74, 74, 79,
+155, 2,159,253, 90,224,127,120,120, 57, 0, 0, 0, 2, 0,113,255,227, 6,115, 4, 96, 0, 12, 0, 46, 0, 0, 1, 33, 34, 7,
+ 6, 21, 20, 22, 51, 50, 55, 54, 53, 19, 6, 7, 6, 35, 34, 38, 53, 52, 55, 54, 51, 33, 17, 51, 17, 20, 23, 22, 51, 50, 55, 54,
+ 53, 17, 51, 17, 20, 7, 6, 35, 34, 39, 38, 3, 61,254,249,128, 67, 62,129,106,148, 92, 45, 49, 67, 93, 94,136,172,203,116,121,
+208, 1, 15,184, 62, 60,106,104, 60, 62,184,100,104,206,211,100, 31, 2, 2, 46, 42, 94, 92,115,109, 52,156,254,246,108, 48, 49,
+193,166,170, 82, 85, 1,197,253, 97,159, 80, 79, 79, 82,157, 1, 65,254,184,236,115,120,120, 37, 0, 1, 0,201,255,227, 7, 3,
+ 5,240, 0, 55, 0, 0, 1, 52, 39, 38, 43, 1, 53, 51, 50, 55, 54, 53, 52, 39, 38, 35, 34, 6, 7, 53, 54, 55, 54, 51, 50, 23,
+ 22, 21, 20, 7, 6, 7, 22, 23, 22, 21, 20, 23, 22, 51, 50, 55, 54, 53, 17, 51, 17, 20, 7, 6, 35, 34, 39, 38, 39, 38, 3,170,
+ 92, 93,165,174,182,149, 79, 79, 81, 82,152, 83,190,114,115,100,101, 89,230,134,134, 71, 71,131,145, 82, 81, 63, 52,112,105, 59,
+ 63,202,110,104,215,217,102, 48, 28, 33, 1,178,132, 74, 75,166, 59, 60,112,115, 61, 62, 36, 38,180, 32, 16, 16,104,105,178,124,
+ 85, 86, 33, 31, 98, 98,144,128, 91, 74, 74, 79,155, 2,159,253, 90,224,127,120,120, 56, 80, 97, 0, 1, 0,171,255,227, 6, 70,
+ 4,124, 0, 53, 0, 0, 1, 52, 39, 38, 43, 1, 53, 51, 50, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 7, 53, 62, 1, 51, 50, 23,
+ 22, 21, 20, 7, 6, 7, 22, 23, 22, 21, 20, 23, 22, 51, 50, 55, 54, 53, 17, 51, 17, 20, 7, 6, 35, 34, 39, 38, 3, 19, 78, 72,
+137,148,155,116, 67, 68, 70, 69,119, 71, 81, 80, 97, 98,170, 76,196,113,114, 60, 60,112,129, 64, 69, 62, 61,105,104, 60, 62,184,
+100,104,206,199,112, 98, 1, 56,102, 56, 51,152, 44, 45, 70, 64, 46, 46, 13, 13, 29,167, 24, 24, 78, 79,141, 93, 64, 65, 24, 25,
+ 72, 79, 72, 88, 68, 69, 79, 82,157, 1, 65,254,184,236,115,120,117,101, 0, 0, 0, 1, 0,201,254, 86, 5, 60, 5,240, 0, 41,
+ 0, 0, 33, 35, 17, 52, 39, 38, 43, 1, 53, 51, 50, 55, 54, 53, 52, 39, 38, 35, 34, 6, 7, 53, 54, 55, 54, 51, 50, 23, 22, 21,
+ 20, 7, 6, 7, 22, 23, 22, 21, 17, 51, 17, 35, 4,115,201, 92, 93,165,174,182,149, 79, 79, 81, 82,152, 83,190,114,115,100,101,
+ 89,230,134,134, 71, 71,131,145, 82, 81,201,201, 1,177,133, 74, 75,166, 59, 60,112,115, 61, 62, 36, 38,180, 32, 16, 16,104,105,
+178,124, 85, 86, 33, 31, 98, 97,146,254,249,253,172, 0, 0, 0, 0, 1, 0,171,254, 86, 4,131, 4,124, 0, 41, 0, 0, 37, 51,
+ 17, 35, 17, 35, 17, 52, 39, 38, 43, 1, 53, 51, 50, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 7, 53, 62, 1, 51, 50, 23, 22, 21,
+ 20, 7, 6, 7, 22, 23, 22, 21, 3,200,187,184,184, 78, 72,137,148,155,116, 67, 68, 70, 69,119, 71, 81, 80, 97, 98,170, 76,196,
+113,114, 60, 60,112,126, 67, 69,153,253,189, 1,170, 1, 70, 88, 56, 51,152, 44, 45, 70, 64, 46, 46, 13, 13, 29,167, 24, 24, 78,
+ 79,141, 93, 64, 65, 24, 24, 73, 75,106, 0, 0, 0, 1, 0, 54,255,227, 7,202, 5,213, 0, 33, 0, 0, 1, 17, 20, 23, 22, 51,
+ 50, 55, 54, 53, 17, 51, 17, 20, 7, 6, 35, 34, 39, 38, 53, 17, 33, 21, 16, 3, 6, 5, 53, 54, 55, 18, 25, 1, 5, 58, 63, 52,
+112,105, 59, 63,202,110,104,215,214,105,110,254, 27,132, 98,254,145,212, 67,117, 5,213,251,236,143, 91, 74, 74, 79,155, 2,159,
+253, 90,224,127,120,120,125,226, 3,113,212,254, 24,254,170,253, 56,167, 46,168, 1, 37, 2, 53, 1, 26, 0, 0, 0, 1, 0, 46,
+255,227, 6,238, 4, 96, 0, 32, 0, 0, 1, 17, 20, 22, 51, 50, 55, 54, 53, 17, 51, 17, 20, 7, 6, 35, 34, 39, 38, 53, 17, 33,
+ 21, 16, 3, 6, 5, 53, 54, 55, 54, 17, 53, 4,115,122,103,104, 60, 62,184,100,104,206,199,112, 98,254,123,118, 94,254,204,179,
+ 59, 98, 4, 96,253, 4, 87,138, 79, 82,157, 1, 65,254,184,236,115,120,117,101,123, 2,143,134,254,146,254,252,207, 29,153, 27,
+127,207, 1,167,212, 0, 0, 0,255,255, 0,201,255,227, 8, 45, 5,213, 16, 2, 1,184, 0, 0, 0, 1, 0,193,255,227, 7, 3,
+ 4, 96, 0, 28, 0, 0, 1, 17, 20, 22, 51, 50, 55, 54, 53, 17, 51, 17, 20, 7, 6, 35, 34, 39, 38, 61, 1, 33, 17, 35, 17, 51,
+ 17, 33, 17, 4,136,122,103,104, 60, 62,184,100,104,206,199,112, 98,253,169,184,184, 2, 87, 4, 96,253, 4, 87,138, 79, 82,157,
+ 1, 65,254,184,236,115,120,117,101,123,204,253,252, 4, 96,254, 51, 1,205, 0,255,255, 0,115,255,227, 5,139, 5,240, 16, 2,
+ 0, 42, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 16, 2, 2, 5, 0, 0, 0, 1,255,250,255,227, 5,102, 5,213, 0, 25,
+ 0, 0, 1, 17, 20, 23, 22, 51, 50, 55, 54, 53, 17, 51, 17, 20, 7, 6, 35, 34, 39, 38, 53, 17, 33, 53, 33, 21, 2,215, 63, 52,
+111,105, 59, 63,202,110,104,215,214,105,110,253,238, 4,239, 5, 43,252,150,143, 91, 74, 74, 79,155, 2,159,253, 90,224,127,120,
+120,125,226, 3,113,170,170, 0, 0, 1, 0, 5,255,227, 4,246, 4, 96, 0, 25, 0, 0, 1, 17, 20, 23, 22, 51, 50, 55, 54, 53,
+ 17, 51, 17, 20, 7, 6, 35, 34, 39, 38, 53, 17, 33, 53, 33, 21, 2,120, 62, 61,105,104, 60, 62,184,100,104,206,199,112, 98,254,
+ 66, 4, 49, 3,182,253,174, 86, 70, 69, 79, 82,157, 1, 65,254,184,236,115,120,117,101,123, 2,126,170,170, 0, 0, 1, 0,178,
+255,227, 6,160, 5,213, 0, 33, 0, 0, 37, 6, 7, 6, 33, 32, 0, 25, 1, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 20, 7,
+ 51, 50, 23, 22, 29, 1, 35, 53, 52, 39, 38, 35, 4,239, 42, 45,144,254,230,254,229,254,223,203,174,195,194,174,203, 9, 44,148,
+ 96, 96,156, 48, 55, 81,248, 82, 46,149, 1, 42, 1, 36, 3,164,252,117,240,211,211,240, 3,139,252, 92, 71, 67, 91, 91,171, 70,
+ 49,108, 42, 49, 0, 1, 0,178, 0, 0, 5, 41, 5,242, 0, 32, 0, 0, 33, 35, 17, 16, 0, 33, 32, 23, 22, 17, 21, 35, 53, 52,
+ 38, 35, 34, 6, 29, 1, 33, 50, 23, 22, 29, 1, 35, 53, 52, 39, 38, 35, 33, 1,125,203, 1, 33, 1, 27, 1, 23,147,145,203,174,
+194,195,174, 2, 88,149, 95, 96,156, 48, 55, 81,253,168, 3,164, 1, 36, 1, 42,149,146,254,217, 57, 32,240,211,211,240,157, 91,
+ 91,171, 70, 49,108, 42, 49, 0, 0, 2, 0,178, 0, 0, 6,196, 5,242, 0, 28, 0, 40, 0, 0, 1, 51, 50, 23, 22, 29, 1, 35,
+ 53, 52, 39, 38, 43, 1, 17, 35, 17, 33, 34, 39, 38, 53, 52, 55, 54, 33, 32, 0, 17, 3, 17, 52, 38, 35, 34, 6, 21, 20, 23, 22,
+ 51, 5, 41, 71,149, 95, 96,156, 48, 55, 81, 71,203,254, 42,201,159,110,144,152, 1, 19, 1, 27, 1, 33,203,174,195,194,174, 53,
+ 90,166, 2,114, 91, 91,171, 70, 49,108, 42, 49,254, 61, 1,195,179,124,224,253,142,149,254,214,254,220,254,206, 1, 25,240,211,
+211,175,149, 73,124, 0, 0, 0, 0, 1, 0,178, 0, 0, 6,196, 5,242, 0, 32, 0, 0, 1, 51, 50, 23, 22, 29, 1, 35, 53, 52,
+ 39, 38, 43, 1, 17, 35, 17, 52, 38, 35, 34, 7, 6, 29, 1, 35, 53, 16, 0, 33, 32, 23, 22, 5, 23, 89,149, 95, 96,156, 48, 55,
+ 81, 71,203,174,194,195, 87, 87,203, 1, 33, 1, 27, 1, 26,144, 90, 4, 96, 91, 91,171, 70, 49,108, 42, 49,252, 79, 3,139,240,
+211,106,106,239, 32, 57, 1, 36, 1, 42,149, 92, 0, 1, 0,178,255,227, 5, 41, 5,213, 0, 32, 0, 0, 19, 16, 0, 33, 32, 55,
+ 54, 61, 1, 35, 21, 20, 6, 35, 34, 38, 53, 17, 33, 50, 23, 22, 29, 1, 51, 53, 52, 39, 38, 35, 33, 17, 35,178, 1, 33, 1, 27,
+ 1, 23,147,145,203,174,194,195,174, 2, 88, 81, 55, 48,156, 96, 95,149,253,168,203, 2, 49,254,220,254,214,149,146,227, 57, 32,
+172,211,211,240, 1,103, 49, 42,108, 49, 70,171, 91, 91, 1,117, 0, 2, 0,155,255, 8, 4,186, 5,240, 0, 33, 0, 43, 0, 0,
+ 37, 33, 54, 55, 6, 7, 6, 35, 34, 0, 53, 52, 0, 51, 32, 23, 22, 3, 2, 3, 50, 23, 22, 29, 1, 35, 53, 52, 39, 38, 35, 33,
+ 17, 51, 18, 32, 54, 53, 52, 38, 32, 6, 21, 20, 1,102, 1, 15,232, 60, 48, 28, 73,124,224,254,251, 1, 16,226, 1, 8,131,155,
+ 58, 52,231,149, 95, 96,156, 48, 55, 81,253, 53,203,167, 1, 16,159,159,254,240,159,175,225,208, 39, 17, 46, 1, 15,235,230, 1,
+ 22,198,234,254,169,254,207,254,247, 91, 91,171, 70, 49,108, 42, 49, 1, 76, 1, 76,186,162,161,187,187,161,162, 0, 1, 0,178,
+255, 8, 5, 41, 5,213, 0, 29, 0, 0, 37, 33, 50, 23, 22, 29, 1, 35, 53, 52, 39, 38, 35, 33, 17, 51, 17, 33, 50, 23, 22, 29,
+ 1, 35, 53, 52, 39, 38, 35, 33, 1,125, 1,133,149, 95, 96,156, 48, 55, 81,253,176,203, 2, 88,149, 95, 96,156, 48, 55, 81,253,
+168,175, 91, 91,171, 70, 49,108, 42, 49, 5,213,254,139, 91, 91,171, 70, 49,108, 42, 49, 0, 0, 0, 1, 0,178,255, 8, 5, 41,
+ 5,242, 0, 31, 0, 0, 51, 17, 16, 0, 33, 32, 23, 22, 17, 21, 35, 53, 52, 38, 35, 34, 7, 6, 21, 17, 33, 50, 23, 22, 29, 1,
+ 35, 53, 52, 39, 38, 35,178, 1, 33, 1, 27, 1, 19,151,145,203,174,194,197, 85, 87, 2, 88,149, 95, 96,156, 48, 55, 81, 3,164,
+ 1, 36, 1, 42,149,142,254,213, 57, 32,240,211,106,108,237,253, 36, 91, 91,171, 70, 49,108, 42, 49, 0, 0, 0, 0, 2, 0,178,
+ 0, 0, 6,142, 5,242, 0, 43, 0, 56, 0, 0, 1, 35, 21, 20, 7, 6, 7, 6, 39, 38, 39, 38, 55, 54, 51, 33, 38, 39, 38, 35,
+ 34, 6, 21, 17, 35, 17, 16, 0, 33, 32, 23, 22, 23, 51, 50, 23, 22, 29, 1, 35, 53, 52, 39, 38, 33, 35, 34, 21, 20, 23, 22, 51,
+ 50, 55, 54, 53, 52, 5, 58, 17,103,105,152,146,109,130, 2, 1, 73, 78, 75, 1, 40, 22, 42, 87,194,195,174,203, 1, 33, 1, 27,
+ 1, 19,151, 92, 33, 37,149, 95, 96,156, 48, 53,254,208,187,153, 57, 58, 69, 53, 58, 46, 3,177, 32,223,114,115, 10, 10, 84,102,
+189,147, 76, 81, 82, 50,106,211,240,252,117, 3,164, 1, 36, 1, 42,149, 91,162, 91, 91,171, 70, 49,106, 44, 49,135,105, 45, 45,
+ 81, 64,147, 17, 0, 2, 0,178, 0, 0, 6,196, 5,242, 0, 28, 0, 40, 0, 0, 1, 35, 17, 16, 0, 33, 32, 39, 38, 17, 52, 55,
+ 54, 51, 33, 17, 51, 17, 51, 50, 23, 22, 29, 1, 35, 53, 52, 39, 38, 41, 1, 34, 7, 6, 21, 20, 22, 51, 50, 54, 53, 5,112, 71,
+254,223,254,229,254,237,152,144,110,159,201, 1,214,203, 71,149, 95, 96,156, 48, 55,254,157,254, 84,166, 90, 53,174,194,195,174,
+ 3,177,254,157,254,220,254,214,149,142, 1, 46,224,124,179, 1,146,254,110, 91, 91,171, 70, 49,108, 42, 49,125, 72,149,224,211,
+211,240, 0, 0, 0, 1, 0,178, 0, 0, 5, 41, 5,213, 0, 20, 0, 0, 19, 51, 17, 54, 51, 32, 23, 22, 17, 21, 35, 53, 52, 38,
+ 35, 34, 7, 6, 21, 17, 35,178,203,160,209, 1, 19,151,145,203,174,194,193, 89, 87,203, 5,213,254, 59,100,149,142,254,213, 75,
+ 50,240,211,106,103,242,253,243, 0, 1, 0,178,255, 8, 4, 86, 5,213, 0, 15, 0, 0, 1, 17, 33, 50, 23, 22, 29, 1, 35, 53,
+ 52, 39, 38, 35, 33, 17, 1,125, 1,133,149, 95, 96,156, 48, 55, 81,253,176, 5,213,250,218, 91, 91,171, 70, 49,108, 42, 49, 5,
+213, 0, 0, 0, 0, 1, 0,178,255,227, 5,231, 5,213, 0, 27, 0, 0, 1, 17, 16, 23, 22, 51, 50, 55, 54, 53, 17, 51, 17, 20,
+ 7, 6, 35, 34, 39, 38, 25, 1, 33, 17, 35, 17, 51, 17, 3,124, 37, 51,120,129, 42, 37,203,113, 88,210,198,100,113,254,204,203,
+203, 4, 96,253,215,254,229, 62, 87, 87, 75,135, 2,176,253, 55,213,125, 98, 98,112, 1,105, 1,147,252, 79, 5,213,254,139, 0,
+ 0, 2, 0, 65,255,227, 7,153, 6,205, 0, 34, 0, 47, 0, 0, 1, 22, 17, 16, 0, 33, 32, 0, 17, 16, 55, 35, 6, 39, 38, 61,
+ 1, 51, 21, 20, 23, 22, 51, 33, 50, 23, 22, 29, 1, 35, 53, 52, 39, 38, 35, 37, 34, 7, 6, 17, 16, 0, 32, 0, 17, 16, 39, 38,
+ 5,214,201,254,136,254,198,254,197,254,135,195,103,148, 96, 96,156, 48, 55, 81, 4,176,149, 95, 96,156, 48, 55, 81,253,168,225,
+124,130, 1, 3, 1,184, 1, 1,128,121, 5, 38,225,254,164,254,159,254, 91, 1,164, 1, 98, 1, 99,218, 1, 92, 91,171, 70, 49,
+108, 42, 49, 91, 91,171, 70, 49,108, 42, 49, 32,158,164,254,229,254,230,254,184, 1, 72, 1, 26, 1, 22,169,158, 0, 1, 0,178,
+ 0, 0, 5, 41, 5,213, 0, 20, 0, 0, 33, 35, 17, 6, 35, 32, 39, 38, 25, 1, 51, 17, 20, 22, 51, 50, 55, 54, 61, 1, 51, 5,
+ 41,203,160,209,254,237,152,144,203,174,194,193, 89, 87,203, 1,197,100,149,142, 1, 43, 2, 38,253,243,240,211,105,104,242,152,
+ 0, 1, 0,178,255, 8, 5, 41, 5,213, 0, 18, 0, 0, 9, 2, 33, 50, 23, 22, 29, 1, 35, 53, 52, 39, 38, 35, 33, 53, 9, 1,
+ 3,117, 1,119,252,201, 2, 32,149, 95, 96,156, 48, 55, 81,252,221, 3, 49,254,107, 5,213,254,174,252, 44, 91, 91,171, 70, 49,
+108, 42, 49,175, 3,192, 1,102, 0, 3, 0,143,255,210, 4,201, 5,240, 0, 38, 0, 44, 0, 54, 0, 0, 37, 6, 35, 34, 39, 38,
+ 55, 54, 51, 50, 23, 54, 55, 6, 7, 6, 35, 34, 0, 53, 52, 0, 51, 32, 23, 22, 3, 2, 7, 6, 7, 22, 55, 54, 55, 21, 6, 7,
+ 6, 37, 38, 7, 6, 23, 22, 18, 32, 54, 53, 52, 38, 32, 6, 21, 20, 2,174,110, 86,172, 73,103, 2, 5,201,178,148,131,114, 48,
+ 28, 73,124,224,254,251, 1, 16,226, 1, 8,131,155, 58, 55,190, 32, 36, 84, 46,129,126,103,152,154,254,206, 93, 42, 86, 31, 24,
+181, 1, 16,159,159,254,240,159, 28, 64, 35, 50,110,245,154,119,239, 39, 17, 46, 1, 15,235,230, 1, 22,198,234,254,169,254,191,
+204, 34, 37, 22, 3, 7,100,192, 89, 1, 3,198, 81, 4, 8, 60, 45, 2, 38,186,162,161,187,187,161,162, 0, 0, 0, 1, 0,178,
+255, 8, 6,196, 5,242, 0, 30, 0, 0, 33, 17, 52, 38, 35, 34, 7, 6, 29, 1, 35, 53, 16, 0, 33, 32, 0, 25, 1, 51, 50, 23,
+ 22, 29, 1, 35, 53, 52, 39, 38, 35, 4, 94,174,194,197, 85, 87,203, 1, 33, 1, 27, 1, 26, 1, 33, 71,149, 95, 96,156, 48, 55,
+ 81, 3,139,240,211,106,106,239, 32, 57, 1, 36, 1, 42,254,214,254,220,253, 11, 91, 91,171, 70, 49,108, 42, 49, 0, 2, 0, 92,
+255,226, 5,133, 5,213, 0, 13, 0, 43, 0, 0, 1, 17, 20, 22, 51, 50, 55, 54, 61, 1, 52, 39, 38, 35, 33, 35, 53, 51, 53, 52,
+ 55, 54, 51, 33, 21, 33, 34, 7, 6, 21, 33, 50, 23, 22, 21, 17, 35, 53, 6, 35, 32, 39, 38, 17, 1,217,174,194,193, 89, 87, 48,
+ 55, 81,253, 12,178,178, 96, 95,149, 3, 35,253, 12, 81, 55, 48, 2, 88,149, 95, 96,203,160,209,254,231,146,144, 3,177,254,152,
+240,211,106,103,242,161,108, 42, 49,175, 20,171, 91, 91,175, 49, 42,107, 91, 91,171,253, 1, 70,100,149,148, 1, 37, 0, 0, 0,
+ 0, 1, 0,178,255,227, 6,196, 5,213, 0, 29, 0, 0, 1, 17, 16, 0, 33, 32, 0, 25, 1, 51, 17, 20, 22, 51, 50, 54, 53, 17,
+ 33, 50, 23, 22, 29, 1, 35, 53, 52, 39, 38, 35, 5, 41,254,223,254,230,254,229,254,223,203,174,195,194,174, 1, 18,149, 95, 96,
+156, 48, 55, 81, 5, 38,253, 11,254,220,254,214, 1, 42, 1, 36, 3,164,252,117,240,211,211,240, 3,139, 91, 91,171, 70, 49,108,
+ 42, 49, 0, 0, 0, 1, 0,140,255,227, 5, 83, 5,242, 0, 44, 0, 0, 19, 52, 55, 54, 33, 32, 23, 22, 21, 20, 7, 6, 7, 30,
+ 1, 21, 20, 4, 32, 36, 53, 51, 20, 23, 22, 32, 54, 53, 52, 38, 35, 33, 53, 33, 50, 54, 53, 52, 39, 38, 35, 34, 7, 6, 7,173,
+155,144, 1, 23, 1, 20,147,155, 73, 73,129,146,163,254,247,253, 74,254,248,202, 82, 83, 1,232,166,165,245,253,191, 2, 65,230,
+147, 99, 97,181,181, 97, 87, 11, 4,171,143, 96, 88, 88, 96,143,128, 91, 89, 32, 34,198,175,245,232,231,246,162, 78, 77,155,162,
+167,154,159,130,116, 89, 49, 48, 48, 43, 74, 0, 0, 1, 0, 92,255,227, 6,110, 6,205, 0, 30, 0, 0, 1, 17, 20, 22, 51, 50,
+ 55, 54, 61, 1, 51, 21, 16, 0, 33, 32, 0, 25, 1, 35, 34, 39, 38, 61, 1, 51, 21, 20, 23, 22, 51, 2,194,174,194,197, 85, 87,
+203,254,223,254,229,254,230,254,223, 71,149, 95, 96,156, 48, 55, 81, 5,213,252,117,240,211,105,107,239, 32, 57,254,220,254,214,
+ 1, 42, 1, 36, 2,245, 91, 91,171, 70, 49,108, 42, 49, 0, 0, 0, 1, 0,178,255,225, 5, 41, 6,147, 0, 32, 0, 0, 1, 20,
+ 23, 22, 51, 50, 55, 54, 61, 1, 51, 21, 16, 7, 6, 37, 36, 39, 38, 53, 16, 55, 54, 37, 55, 37, 53, 5, 21, 5, 4, 7, 6, 1,
+122, 90, 91,190,195, 87, 87,203,145,159,254,244,254,208,123,144, 61,129, 1,115,150,253, 57, 4, 17,254,164,254,153, 87, 47, 2,
+ 7,175,104,105,105,107,239, 32, 57,254,220,149,165, 16, 18,131,155,234, 1, 38,100,224,161, 65,140,190,190,190,156,161,158, 85,
+ 0, 1, 0,178, 0, 0, 5, 41, 5,242, 0, 17, 0, 0, 51, 17, 16, 0, 33, 32, 0, 25, 1, 35, 17, 52, 38, 35, 34, 6, 21, 17,
+178, 1, 33, 1, 27, 1, 26, 1, 33,203,174,194,195,174, 3,164, 1, 36, 1, 42,254,214,254,220,252, 92, 3,139,240,211,211,240,
+252,117, 0, 0, 0, 1, 0,178,255, 66, 5, 41, 5,244, 0, 32, 0, 0, 1, 52, 39, 38, 35, 34, 7, 6, 29, 1, 35, 53, 16, 55,
+ 54, 5, 4, 23, 22, 21, 16, 7, 6, 5, 7, 5, 21, 37, 53, 37, 36, 55, 54, 4, 97, 90, 91,190,195, 87, 87,203,144,160, 1, 12,
+ 1, 48,122,145, 61,129,254,141,150, 2,199,251,239, 1, 92, 1,103, 87, 47, 3,206,175,103,106,106,106,239, 32, 57, 1, 36,149,
+165, 16, 18,131,155,234,254,218,100,224,161, 65,140,190,190,190,156,161,158, 85, 0, 1, 0,178, 0, 0, 5,161, 5,242, 0, 24,
+ 0, 0, 1, 17, 35, 17, 6, 7, 6, 29, 1, 35, 53, 16, 55, 54, 33, 32, 23, 22, 25, 1, 35, 17, 52, 39, 38, 3,144,203,136, 75,
+117,203,174,145, 1, 57, 1, 41,159,175,203,117, 66, 5, 71,252,148, 3,108, 19, 80,124,221, 32, 57, 1, 5,180,149,149,163,254,
+234,252, 92, 3,139,204,141, 80, 0, 2, 0,155,255, 8, 4,186, 5,240, 0, 29, 0, 43, 0, 0, 37, 38, 39, 38, 17, 52, 0, 51,
+ 32, 23, 22, 3, 2, 3, 50, 23, 22, 29, 1, 35, 53, 52, 39, 38, 35, 33, 17, 51, 21, 33, 55, 54, 55, 54, 39, 38, 39, 38, 32, 6,
+ 21, 20, 23, 22, 2,162, 69,240,202, 1, 16,226, 1, 8,131,155, 58, 52,231,149, 95, 96,156, 48, 55, 81,253, 53,203, 1, 20,171,
+101, 15, 63, 28, 25, 55, 79,254,240,159,151,163,220,220,170,142, 1, 4,230, 1, 22,198,234,254,169,254,207,254,247, 91, 91,171,
+ 70, 49,108, 42, 49, 1, 76,157,195,194, 44,189,215,190, 64, 94,187,161,170,116,126, 0, 0, 0, 0, 1, 0,178, 0, 0, 6,196,
+ 5,242, 0, 31, 0, 0, 1, 51, 50, 23, 22, 29, 1, 35, 53, 52, 39, 38, 43, 1, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17,
+ 16, 0, 33, 32, 23, 22, 5, 23, 89,149, 95, 96,156, 48, 55, 81, 71,203,174,194,195,174,203, 1, 33, 1, 27, 1, 26,144, 90, 4,
+ 96, 91, 91,171, 70, 49,108, 42, 49,252, 79, 3,139,240,211,211,240,252,117, 3,164, 1, 36, 1, 42,149, 92, 0,255,255, 0,178,
+255,227, 5, 41, 5,213, 18, 6, 0, 56, 0, 0, 0, 1, 0,178,255, 8, 6,196, 5,213, 0, 32, 0, 0, 41, 1, 50, 23, 22, 29,
+ 1, 51, 53, 52, 39, 38, 43, 1, 17, 35, 17, 20, 7, 6, 35, 34, 38, 61, 1, 35, 21, 16, 23, 22, 33, 50, 55, 4, 94, 1, 18, 81,
+ 55, 48,156, 96, 95,149, 71,203, 87, 89,193,194,174,203,144,152, 1, 19,209,160, 49, 42,108, 49, 70,171, 91, 91, 5, 38,253,243,
+242,104,105,211,240,152,177,254,215,144,149,100,255,255, 0,135,255,227, 4,162, 5,240, 18, 6, 0, 54, 0, 0, 0, 1, 0,178,
+ 0, 0, 5, 41, 5,242, 0, 18, 0, 0, 51, 17, 16, 0, 33, 32, 23, 22, 17, 21, 35, 53, 52, 38, 35, 34, 6, 21, 17,178, 1, 33,
+ 1, 27, 1, 19,151,145,203,174,194,195,174, 3,164, 1, 36, 1, 42,149,142,254,213, 57, 32,240,211,211,240,252,117, 0, 0, 0,
+ 0, 2, 0,140,255,227, 5, 83, 5,242, 0, 43, 0, 57, 0, 0, 1, 30, 1, 21, 20, 4, 32, 36, 53, 51, 20, 23, 22, 32, 54, 53,
+ 52, 38, 35, 34, 7, 6, 7, 34, 35, 54, 55, 54, 55, 38, 39, 38, 53, 52, 55, 54, 33, 32, 23, 22, 21, 20, 7, 6, 1, 34, 7, 6,
+ 21, 20, 22, 51, 50, 54, 53, 52, 39, 38, 4, 30,146,163,254,247,253, 74,254,248,202, 82, 83, 1,232,166,165,245,226,101, 31, 5,
+102,103, 3, 35, 82,146,129, 72, 74,155,147, 1, 19, 1, 20,147,155, 73, 73,254, 80,180, 97, 99,147,229,230,147, 99, 97, 3, 87,
+ 34,198,175,245,232,231,246,162, 78, 77,155,162,167,154, 77, 28, 12, 28, 42, 99, 34, 32, 89, 91,128,143, 96, 88, 88, 94,145,128,
+ 91, 89, 1,217, 48, 49, 89,116,130,130,116, 89, 49, 48, 0, 0, 0, 1, 0,178, 0, 0, 6, 12, 5,213, 0, 21, 0, 0, 1, 53,
+ 52, 38, 35, 34, 7, 6, 21, 17, 35, 17, 51, 17, 54, 51, 32, 23, 22, 23, 51, 21, 4, 94,174,194,193, 89, 87,203,203,160,209, 1,
+ 19,151,117, 24,231, 1,219, 50,240,211,106,103,242,253,243, 5,213,254, 59,100,149,115,226,175,255,255, 0,115, 0, 0, 5,217,
+ 5,213, 18, 6, 2,196, 0, 0, 0, 2, 0, 92, 0, 0, 5,227, 5,242, 0, 44, 0, 60, 0, 0, 1, 17, 52, 55, 54, 51, 50, 23,
+ 22, 21, 20, 7, 6, 35, 34, 39, 21, 33, 50, 23, 22, 29, 1, 35, 53, 52, 39, 38, 35, 33, 17, 35, 17, 35, 34, 39, 38, 61, 1, 51,
+ 21, 20, 23, 22, 51, 1, 6, 7, 6, 21, 20, 23, 22, 23, 22, 55, 54, 53, 52, 39, 38, 1,208,146,141,235,244,132,145,145,132,244,
+246, 73, 1,244,149, 95, 96,156, 48, 55, 81,254, 12,203, 32,149, 95, 96,156, 48, 55, 81, 2, 42,138, 93, 87, 87, 93,138,136, 95,
+ 87, 87, 95, 2,114, 2, 8,149,115,112,112,122,144,149,122,112, 83,218, 91, 91,171, 70, 49,108, 42, 49,254, 61, 1,195, 91, 91,
+171, 70, 49,108, 42, 49, 2,220, 1, 65, 62, 84, 93, 61, 66, 1, 1, 68, 61, 91, 86, 62, 67, 0,255,255, 0,115,255,227, 5,217,
+ 5,240, 18, 6, 0, 50, 0, 0, 0, 3, 0,135,255,227, 4,162, 5,240, 0, 8, 0, 19, 0, 46, 0, 0, 1, 17, 54, 55, 54, 53,
+ 52, 39, 38, 1, 17, 52, 39, 34, 7, 6, 21, 20, 23, 22, 5, 23, 30, 1, 21, 20, 4, 33, 34, 38, 39, 53, 22, 23, 22, 23, 17, 38,
+ 39, 38, 53, 52, 55, 54, 51, 50, 21, 2,185,113, 71, 94, 67, 67,254,188, 57, 53, 43, 26, 60, 38, 1, 5, 48,226,215,254,221,254,
+231,106,239,128,123,118, 69, 66,190, 91,101, 75, 91,165,231, 2,148,253,248, 11, 52, 68,126,110, 62, 61, 1, 18, 1,132, 62, 2,
+ 64, 37,145, 99, 51, 31, 65, 10, 43,217,182,217,224, 48, 47,208, 69, 35, 20, 10, 2, 44, 44, 87, 96,171,215, 97,114,201, 0, 0,
+255,255, 0,117, 3,239, 1,135, 6, 20, 16, 6, 2, 24, 0, 0,255,255, 0,178, 3,254, 1,215, 5,213, 16, 6, 2, 21, 0, 0,
+ 0, 1, 0, 94, 4,241, 3,169, 6,194, 0, 3, 0, 0, 1, 35, 1, 51, 1, 51,213, 2,118,213, 4,241, 1,209, 0, 1, 0,120,
+ 4,241, 3,134, 7, 37, 0, 17, 0, 0, 1, 34, 7, 6, 21, 35, 52, 55, 54, 51, 50, 55, 54, 53, 51, 20, 7, 6, 1,255, 91, 82,
+ 66,152,104,106,181, 91, 82, 66,152,104,106, 5,205, 84, 68, 68,130,106,108, 84, 68, 68,130,106,108, 0, 0, 0,255,255, 0,158,
+ 4,240, 2,125, 6,102, 16, 6, 0, 67,244, 0, 0, 1, 0, 94, 4,229, 3,189, 7, 55, 0, 21, 0, 0, 19, 35, 52, 55, 18, 33,
+ 32, 23, 18, 33, 34, 17, 51, 20, 51, 50, 39, 38, 39, 38, 7, 6,252,158, 32,113, 1, 51, 1, 85, 55, 75,254,193,251,152, 97,121,
+ 38, 34,205,206, 57, 25, 4,241,211, 83, 1, 32,252,254,170, 1, 8,122,158,140, 2, 1,179, 78, 0, 1, 0, 90, 4,241, 3,178,
+ 7, 37, 0, 5, 0, 0, 27, 1, 51, 3, 33, 21, 90,170,170,125, 2,129, 4,241, 2, 52,254, 98,150, 0, 0, 0, 0, 1, 0,186,
+255,230, 7, 29, 4, 98, 0, 38, 0, 94, 64, 17, 0, 18, 20, 30, 27, 8, 29, 80, 18, 8, 20, 80, 10, 8, 8, 70, 39, 16,252,236,
+252,252,252,252, 60, 17, 18, 57, 49, 64, 22, 7, 20, 10, 26, 17, 0, 6, 31, 8, 13, 23,135, 31, 4, 35,140, 29, 27, 18, 8,188,
+ 29, 0, 47,244, 60, 60, 16,244, 60,196,236, 50, 17, 18, 23, 57, 48, 64, 19, 48, 40, 80, 40,112, 40,144, 40,160, 40,160, 40,191,
+ 40,223, 40,255, 40, 9, 1, 93, 37, 6, 7, 6, 35, 34, 38, 53, 17, 51, 17, 20, 22, 51, 50, 55, 54, 53, 17, 51, 17, 20, 22, 51,
+ 50, 54, 53, 17, 51, 17, 35, 53, 6, 7, 6, 35, 34, 39, 38, 3,174, 69, 96, 96,130,175,190,185,114,117,143, 83, 83,185,114,119,
+141,166,185,185, 63, 88, 88,121,122, 86, 85,216,124, 58, 60,246,226, 2,164,253, 98,162,156, 96, 94,164, 2,122,253, 98,162,156,
+192,162, 2,122,251,160,174,104, 48, 50, 62, 62, 0, 1, 0,186,254, 86, 4,100, 4,123, 0, 23, 0, 63, 64, 30, 1, 7, 22, 3,
+ 16, 10, 4,135, 16, 19,184, 14,188, 10, 23, 9,169, 10, 0, 8, 9, 22, 78, 11, 15, 7, 8, 13, 70, 24, 16,252,236, 50, 50,244,
+ 60,236, 49, 0, 47,252,204, 16,228,244,196,236, 17, 18, 23, 57, 48,180, 96, 25,207, 25, 2, 1, 93, 1, 17, 52, 38, 35, 34, 6,
+ 21, 17, 33, 21, 33, 17, 35, 17, 51, 21, 62, 1, 51, 50, 22, 21, 17, 3,172,124,124,149,172, 2,241,253, 15,185,185, 66,179,117,
+193,198, 1, 44, 1,114,159,158,190,164,254, 54,175,254, 86, 6, 10,174,101,100,239,232,254,136, 0, 2, 0,113,254, 86, 5, 47,
+ 4,123, 0, 11, 0, 32, 0, 60, 64, 14, 34, 30, 26, 14, 6, 8, 12, 28, 71, 0, 18, 20, 69, 33, 16,252,236,244, 60,236, 50, 50,
+220,212, 49, 64, 18, 3,185, 14, 17, 9,185, 26, 23,184, 17,140, 30,169, 12,189, 27,188, 33, 0, 16,228,228,236,228,244,196,236,
+ 16,198,238, 48, 1, 20, 22, 51, 50, 54, 53, 52, 38, 35, 34, 6, 1, 35, 17, 14, 1, 35, 34, 2, 17, 16, 0, 51, 50, 22, 23, 53,
+ 51, 17, 51, 21, 35, 1, 47,167,146,146,168,168,146,146,167, 3, 43,184, 58,177,124,203,255, 0,255,203,124,177, 58,184,213,213,
+ 2, 47,203,231,231,203,203,231,231,251, 92, 2, 82,100, 97, 1, 68, 1, 8, 1, 8, 1, 68, 97,100,170,252, 79,175, 0, 0, 0,
+ 0, 1, 0,186,254, 86, 5, 57, 4,123, 0, 23, 0, 61, 64, 13, 25, 22, 3, 8, 0, 21, 78, 9, 13, 8, 12, 70, 24, 16,252,236,
+ 50,244, 60,236,220,196, 49, 64, 13, 6,135, 14, 17,184, 12,188, 2,189, 21,169, 11, 0, 0, 47, 60,236,236,228,244,196,236,181,
+ 9, 3, 20, 3, 14, 10, 17, 18, 23, 57, 48, 33, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 22, 21,
+ 17, 51, 21, 4,100,184,124,124,149,172,185,185, 66,179,117,193,198,213,254, 86, 4, 72,159,158,190,164,253,135, 4, 96,174,101,
+100,239,232,254, 11,175, 0, 0, 0, 1, 0,174,255,227, 4, 88, 6, 20, 0, 26, 0, 63, 64, 30, 7, 15, 0, 3, 20, 3, 11,135,
+ 20, 23,140, 18, 17, 5,169, 4,188, 18, 19, 15, 8, 4, 17, 78, 6, 2, 8, 0, 70, 27, 16,252,236, 50,244, 60,236, 50, 49, 0,
+ 47,244,252,204, 16,244,196,236, 17, 18, 23, 57, 48,180, 96, 28,207, 28, 2, 1, 93, 19, 17, 51, 17, 33, 21, 33, 17, 20, 23, 22,
+ 51, 50, 55, 54, 53, 17, 51, 17, 35, 53, 14, 1, 35, 34, 39, 38,174,184, 2,242,253, 14, 62, 62,124,152, 84, 86,184,184, 67,177,
+117,193,100,100, 1,186, 4, 90,254, 76,170,254, 11,159, 80, 79, 95, 98,161, 1, 59,252,224,172,102, 99,120,120, 0, 2, 0,113,
+254, 86, 5, 47, 4,123, 0, 18, 0, 30, 0, 60, 64, 13, 32, 1, 16, 4, 25, 8, 18, 71, 19, 18, 10, 69, 31, 16,252,236,244,236,
+ 50, 50,220,212, 49, 64, 19, 22,185, 4, 7, 28,185, 16, 13,184, 7,140, 31, 1,169, 2,189, 17,188, 31, 0, 16,228,244,236, 16,
+228,244,196,236, 16,198,238, 48, 1, 51, 21, 33, 17, 14, 1, 35, 34, 2, 17, 16, 0, 51, 50, 22, 23, 53, 51, 1, 20, 22, 51, 50,
+ 54, 53, 52, 38, 35, 34, 6, 4, 90,213,254,115, 58,177,124,203,255, 0,255,203,124,177, 58,184,252,213,167,146,146,168,168,146,
+146,167,254,248,162, 2, 82,100, 97, 1, 68, 1, 8, 1, 8, 1, 68, 97,100,170,253,207,203,231,231,203,203,231,231, 0, 0, 0,
+ 0, 1, 0,174,255, 26, 3,224, 6, 20, 0, 19, 0, 44, 64, 12, 21, 5, 15, 18, 14, 5, 8, 3, 8, 1, 70, 20, 16,252,252, 60,
+220,212,236, 16,196, 49, 64, 10, 7,169, 4,188, 14, 9,169, 2,151, 1, 0, 47,228,236,204,244,236, 48, 41, 1, 17, 51, 17, 33,
+ 21, 33, 17, 51, 50, 23, 22, 29, 1, 35, 53, 52, 39, 38, 2, 83,254, 91,184, 2,122,253,134,237,152, 77, 96,156, 48, 49, 6, 20,
+254, 76,170,252,249, 73, 91,171, 70, 49,105, 38, 38, 0, 0, 0, 0, 1, 0,186,254, 86, 4,100, 4,123, 0, 21, 0, 62, 64, 30,
+ 1, 7, 20, 3, 14, 21, 4,135, 14, 17,184, 12,188, 21, 9,169, 10,189, 21, 0, 8, 9, 20, 78, 13, 7, 8, 11, 70, 22, 16,252,
+236, 50,244, 60,236, 49, 0, 47,252,236, 16,228,244,196,236, 17, 18, 23, 57, 48,180, 96, 23,207, 23, 2, 1, 93, 33, 17, 52, 38,
+ 35, 34, 6, 21, 17, 33, 21, 33, 17, 51, 21, 62, 1, 51, 50, 22, 21, 17, 3,172,124,124,149,172, 2,241,252, 86,185, 66,179,117,
+193,198, 2,158,159,158,190,164,252,140,175, 6, 10,174,101,100,239,232,253, 92, 0, 2, 0,186,254, 86, 5, 54, 4,123, 0, 32,
+ 0, 41, 0,117, 64, 12, 43, 19, 1, 18, 18, 71, 7, 11, 8, 9, 70, 42, 16,252,236, 50,244,236,220,196,179, 36, 18, 29, 7, 16,
+220,252,179, 33, 18, 21, 18, 16,212,236,178, 0, 33, 36, 73, 83, 88,179, 29, 9, 36, 7, 16, 60, 16, 60, 89, 49, 64, 15, 38,185,
+ 25,140, 42, 4,185, 12, 15,184, 11,188, 9,189, 42, 0, 16,236,228,244,196,236, 16,244,236, 64, 6, 18, 1,169, 21, 33, 38, 16,
+220, 60,252, 60,178, 0, 4, 1, 73, 83, 88,181, 18, 1,169, 21, 33, 38, 16, 60, 60,252, 60, 89, 48, 1, 51, 52, 38, 35, 34, 6,
+ 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 0, 17, 51, 21, 35, 6, 7, 6, 7, 6, 39, 38, 53, 52, 55, 54, 5, 35, 34, 23, 22, 51,
+ 50, 55, 54, 3, 35,194,167,146,146,167,185,185, 58,177,123,204, 0,255,146,162, 29, 53, 96,172,160, 52,120, 66,100, 1, 66,152,
+159, 5, 5,139, 74, 52, 28, 2, 47,203,231,231,203,252, 39, 6, 10,170,100, 97,254,188,254,248,175,161, 90,161, 1, 2, 43,104,
+124,123, 78,118,175,144,113,113, 60, 0, 0, 0, 0, 2, 0,113,255,227, 5, 47, 6, 20, 0, 12, 0, 31, 0, 52, 64, 13, 33, 30,
+ 0, 27, 8, 13, 29, 71, 5, 18, 21, 69, 32, 16,252,236,244, 60,236, 50,220,196, 49, 64, 14, 8,185, 18,140, 32, 31, 0,169, 26,
+ 29,188, 28,151, 32, 0, 16,228,244, 60,252, 60, 16,244,236, 48, 1, 33, 34, 7, 6, 21, 20, 22, 51, 50, 55, 54, 53, 19, 17, 16,
+ 5, 6, 35, 34, 2, 17, 52, 55, 54, 51, 33, 17, 51, 17, 51, 21, 3,162,254,198,136, 98, 79,167,146,154, 77, 83,184,254,236, 75,
+149,246,255,127,125,249, 1, 60,184,213, 3,182,122, 97,172,203,231,107,115,212, 1,135,254, 67,254,175,154, 43, 1, 68, 1, 8,
+223,171,167, 1,180,254, 76,170, 0, 1, 0,186,254, 86, 4,100, 6, 20, 0, 19, 0, 53, 64, 26, 3, 9, 0, 3, 14, 1, 6,135,
+ 14, 17,184, 12,151, 10,189, 1, 2, 8, 0, 78, 13, 9, 8, 11, 70, 20, 16,252,236, 50,244,236, 49, 0, 47,236,236,244,196,236,
+ 17, 18, 23, 57, 48,178, 96, 21, 1, 1, 93, 1, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 17, 62, 1, 51, 50, 22, 4,
+100,184,124,124,149,172,185,185, 66,179,117,193,198, 2,164,253, 92, 2,158,159,158,190,164,251,221, 7,190,253,158,101,100,239,
+ 0, 1, 0,193,254, 86, 2,215, 4, 96, 0, 5, 0, 32, 64, 7, 7, 1, 5, 8, 3, 70, 6, 16,252,252,212,196, 49, 0, 64, 8,
+ 4,188, 6, 0,169, 3,189, 6, 16,244,228, 16,228, 48, 1, 33, 21, 33, 17, 51, 1,121, 1, 94,253,234,184,254,248,162, 6, 10,
+ 0, 1, 0,186,254, 86, 7, 28, 6, 20, 0, 40, 0,105, 64, 15, 32, 29, 8, 31, 80, 40, 8, 20, 80, 8, 11, 8, 9, 70, 41, 16,
+252,236, 50,244,252,244,252, 60, 49, 64, 18, 4,135, 12, 16,184, 31, 25,135, 33, 36,140, 29,188, 10,151, 8,189, 31, 0, 47,236,
+228,228,244,196,236, 16,244,196,236,181, 40, 21, 28, 3, 33, 29, 17, 18, 23, 57,181, 20, 0, 7, 3, 12, 32, 17, 18, 23, 57, 48,
+ 64, 19, 48, 41, 80, 41,112, 41,144, 41,160, 41,160, 41,191, 41,223, 41,255, 41, 9, 1, 93, 1, 52, 39, 38, 35, 34, 6, 21, 17,
+ 35, 17, 51, 17, 54, 55, 54, 51, 50, 23, 22, 29, 1, 20, 23, 22, 51, 50, 54, 53, 17, 51, 17, 35, 53, 14, 1, 35, 34, 39, 38, 53,
+ 3,143, 62, 62,124,120,172,185,185, 99, 38, 89,107,193, 99, 99, 62, 56,110,140,173,184,184, 67,177,108,175, 98,100, 2,158,159,
+ 79, 79,190,164,251,221, 7,190,253,158,129, 22, 50,119,120,232,227,151, 88, 79,190,164, 2,123,251,160,172,102, 99,120,123,228,
+ 0, 2, 0,113,255,226, 4,188, 6, 20, 0, 14, 0, 48, 0, 92, 64, 11, 50, 32, 12, 18, 36, 71, 5, 18, 44, 69, 49, 16,252,236,
+244,236,220,196,180, 18, 18, 27, 23, 44, 16,220,220,236, 49, 64, 17, 1, 32,169, 48, 31,188, 49, 24,169, 23,151, 49, 8,185, 40,
+140, 49, 0, 16,244,236, 16,244,236, 16,244, 60,252, 60, 48,180, 33, 30, 34, 29, 34, 5, 7, 16, 60, 60,181, 0, 17, 33, 15, 17,
+ 30, 16,236, 16,236,178, 14, 16, 0, 16, 60, 60, 1, 35, 34, 7, 6, 21, 20, 22, 51, 50, 55, 54, 55, 54, 39, 1, 39, 38, 53, 52,
+ 55, 54, 59, 1, 21, 35, 38, 23, 22, 31, 1, 33, 21, 33, 19, 22, 21, 20, 7, 6, 39, 38, 39, 38, 17, 52, 55, 54, 51, 2,195, 91,
+165, 65, 83,167,146,173, 93, 46, 3, 2, 23,254,221, 83, 22, 68, 56, 49,147, 78, 47, 1, 1, 15, 86, 1,144,254,201,174, 33,133,
+135,226,247,127,127,127,113,218, 3,182, 90,115,186,203,231,150, 73, 82, 92, 43, 2, 43,152, 40, 86, 76, 45, 37,175, 1, 41, 36,
+ 27,158,170,254,182, 63,137,166,141,143, 1, 1,161,162, 1, 8,235,174,152, 0, 0, 1, 0,174,254, 86, 4, 88, 6, 20, 0, 19,
+ 0, 58, 64, 28, 3, 9, 0, 3, 14, 10, 6,135, 14, 17,140, 1,151, 10,188, 12,189, 20, 13, 9, 8, 11, 78, 2, 8, 0, 70, 20,
+ 16,252,236,244,236, 50, 49, 0, 16,236,228,228,244,196,236, 17, 18, 23, 57, 48,180, 96, 21,207, 21, 2, 1, 93, 19, 17, 51, 17,
+ 20, 22, 51, 50, 54, 53, 17, 51, 17, 35, 17, 14, 1, 35, 34, 38,174,184,124,124,149,173,184,184, 67,177,117,193,200, 1,186, 4,
+ 90,251,173,159,159,190,164, 2,123,249,246, 2, 86,102, 99,240,255,255, 0,186, 0, 0, 4,100, 6, 20, 18, 6, 0, 75, 0, 0,
+ 0, 2, 0,113,255,227, 4, 90, 6, 20, 0, 11, 0, 52, 0,101, 64, 10, 18, 6, 8, 16, 71, 0, 18, 25, 69, 53, 16,252,236,244,
+252, 60, 64, 13, 40, 18, 39, 39, 42, 37, 37, 18, 42, 30, 18, 51, 16, 16,220,252,212,236, 17, 18, 57, 47,236,178, 12, 16, 28, 17,
+ 18, 57, 49, 64, 16, 46,169, 32, 9,185, 28,184, 18, 3,185, 19, 22,140, 39,151, 18, 0, 47,228,244,196,236, 16,244,236,220,236,
+178, 12, 9, 28, 17, 18, 57, 48, 64, 9, 96, 54,128, 54,160, 54,224, 54, 4, 1, 93, 1, 20, 22, 51, 50, 54, 53, 52, 38, 35, 34,
+ 6, 1, 22, 23, 22, 25, 1, 35, 53, 14, 1, 35, 34, 2, 17, 16, 0, 51, 50, 53, 38, 43, 1, 34, 39, 38, 53, 52, 55, 51, 6, 21,
+ 20, 23, 22, 59, 1, 50, 23, 22, 21, 20, 1, 47,167,146,146,168,168,146,146,167, 1,233,110, 68,144,184, 58,177,124,203,255, 1,
+ 0,202, 87, 1, 67,118, 62, 31, 30, 33,184, 37, 8, 17, 26,147, 55, 41, 29, 2, 47,203,231,231,203,203,231,231, 1,107, 29, 80,
+168,254,219,253,213,168,100, 97, 1, 68, 1, 8, 1, 8, 1, 69, 60, 54, 29, 29,112, 71, 53, 80, 48, 14, 7, 15, 44, 33, 75, 55,
+ 0, 1, 0,186,254, 86, 5, 57, 4,123, 0, 21, 0, 59, 64, 12, 23, 0, 3, 8, 21, 78, 9, 13, 8, 12, 70, 22, 16,252,236, 50,
+244,236,220,196, 49, 64, 13, 6,135, 14, 17,184, 12,188, 11, 0,169, 2,189, 11, 0, 47,252,236, 16,228,244,196,236,181, 9, 3,
+ 20, 3, 14, 10, 17, 18, 23, 57, 48, 1, 21, 33, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 22, 21, 17, 5,
+ 57,254,115,124,124,149,172,185,185, 66,179,117,193,198,254,248,162, 4, 72,159,158,190,164,253,135, 4, 96,174,101,100,239,232,
+252, 84, 0, 0, 0, 2, 0,174,255,227, 4, 88, 6, 20, 0, 29, 0, 45, 0, 98, 64, 12, 2, 40, 8, 20, 0, 78, 32, 8, 14, 10,
+ 70, 46, 16,252, 60,236,244, 60,236, 50,182, 16, 13, 45, 26, 4, 0, 14, 17, 18, 23, 57,183, 25, 8, 16, 30, 8, 13, 16, 13, 7,
+ 16,236, 16,236, 1,176, 13, 47, 49, 64, 18, 37,135, 3, 6,140, 1, 30, 14,169, 25, 15,188, 1, 21,134, 20,151, 1, 0, 47,244,
+236, 16,244, 60,252, 60, 16,244,196,236,181, 33, 10, 40, 3, 15, 3, 17, 18, 23, 57, 48, 1, 17, 35, 53, 14, 1, 35, 34, 39, 38,
+ 61, 1, 52, 55, 35, 53, 51, 54, 55, 36, 55, 21, 6, 7, 6, 7, 51, 50, 23, 22, 37, 6, 29, 1, 20, 23, 22, 51, 50, 54, 61, 1,
+ 52, 39, 38, 35, 4, 88,184, 67,177,117,195, 98,100,122,122,218,112,152, 1, 27,173,141,221, 62, 66,105,176,130, 79,253,152,138,
+ 62, 65,121,149,173, 26, 99, 87, 2, 32,253,224,172,102, 99,120,123,228, 73,233,202,170,128, 96,174, 38,175, 36,132, 37, 56,195,
+118,143,198,229, 74,162, 77, 79,190,164, 59,207, 41,158, 0, 0, 0, 1, 0,174,255,227, 5, 10, 6, 20, 0, 43, 0, 63, 64, 15,
+ 45, 23, 17, 18, 28, 37, 9, 8, 36, 78, 2, 8, 0, 70, 44, 16,252,236,244,236, 50,220,236,220,196, 49, 64, 19, 0, 3, 9, 3,
+ 38, 1, 23,169, 22,151, 36, 6,135, 38, 41,140, 1,188, 36, 0, 47,228,244,196,236, 16,244,236, 17, 18, 23, 57, 48, 19, 17, 51,
+ 17, 20, 22, 51, 50, 54, 53, 17, 52, 39, 38, 47, 1, 38, 55, 54, 55, 54, 59, 1, 21, 35, 34, 7, 6, 21, 20, 31, 1, 22, 23, 22,
+ 21, 17, 35, 53, 14, 1, 35, 34, 38,174,184,124,124,149,173, 3, 3, 10, 77, 46, 1, 4, 61, 60,139,236,236, 40, 21, 24, 17, 96,
+ 19, 4, 7,184, 67,177,117,193,200, 1,186, 2,166,253, 97,159,159,190,164, 1,151, 19, 22, 32, 23,188,112, 48,129, 46, 45,175,
+ 9, 11, 23, 31, 42,243, 47, 23, 40, 20,252,132,172,102, 99,240,255,255,255,219,254, 86, 1,121, 4, 96, 18, 6, 1,249, 0, 0,
+ 0, 1, 0, 49,255,227, 5, 90, 6, 20, 0, 35, 0, 71, 64, 15, 37, 14, 11, 8, 12, 78, 3, 8, 22, 27, 33, 0, 18, 27, 36, 16,
+212,252,204, 16,220,236,244,236, 50,196, 49, 64, 23, 10, 4, 21, 3, 15, 12, 33,169, 32,151, 13, 22,169, 3, 12,188, 13, 7,135,
+ 15, 18,140, 13, 0, 47,244,196,236, 16,244, 60,236, 16,244,236, 17, 18, 23, 57, 48, 19, 20, 59, 1, 17, 20, 22, 51, 50, 54, 53,
+ 17, 51, 17, 35, 53, 14, 1, 35, 34, 38, 53, 17, 35, 34, 39, 38, 55, 54, 55, 54, 59, 1, 21, 35, 34,242,131,243,124,124,149,173,
+184,184, 67,177,117,193,200, 59,149, 94, 83, 3, 3, 87,115,118, 89, 89,131, 4,234,138,253, 97,159,159,190,164, 2,123,251,160,
+172,102, 99,240,231, 1,252, 94, 83,145,131, 66, 87,175, 0, 0, 0, 1, 0,159,254, 86, 3,150, 4,124, 0, 31, 0, 84, 64, 12,
+ 33, 69, 16, 18, 5, 29, 2, 18, 11, 22, 70, 32, 16,252, 60,236,212, 60,236,228, 49, 64, 13, 5,169, 6,189, 32, 22,134, 23, 20,
+185, 25,184, 32, 0, 16,244,236,212,236, 16,252,236, 48, 64, 10, 0, 31, 29, 31, 17, 0, 17, 13, 14, 13, 7, 5, 16,236,236, 1,
+ 73, 80, 88,177, 31, 29, 16, 60, 89,179, 30, 31, 14, 13, 7, 4, 16, 60, 5, 6, 21, 20, 51, 33, 21, 33, 34, 39, 38, 39, 38, 55,
+ 1, 54, 39, 38, 39, 38, 7, 6, 7, 53, 54, 23, 22, 23, 22, 21, 20, 7, 1,134, 14, 47, 1,238,253,195, 87, 58, 37, 2, 2, 38,
+ 1,205, 68, 1, 1, 47, 67,141,120,188,188,161,195,132, 81, 69,192, 19, 21, 32,162, 69, 44, 65, 56, 56, 2,173,102, 93, 68, 64,
+ 90, 1, 1,120,198,106, 1, 1,170,104,136,154,101, 0, 0, 0,255,255, 0,186, 0, 0, 4,100, 4,123, 18, 6, 0, 81, 0, 0,
+ 0, 1, 0, 70,254, 86, 3, 59, 4, 96, 0, 37, 0, 88, 64, 17, 16, 18, 35, 35, 5, 26, 39, 5, 11, 26, 30, 18, 21, 2, 18, 11,
+ 38, 16,212,236,220,236,204, 16,220,196, 17, 18, 57, 47,236, 49, 64, 14, 35, 16, 5, 27, 27,169, 26,188, 38, 5,169, 6,189, 38,
+ 0, 16,252,236, 16,244,236, 17, 18, 57, 57, 48,182, 37, 17, 0, 17, 13, 14, 13, 7, 4, 16,236,236,182, 19, 17, 18, 17, 32, 33,
+ 32, 7, 4, 16,236,236, 5, 6, 21, 20, 51, 33, 21, 33, 34, 39, 38, 53, 52, 55, 1, 54, 55, 54, 47, 1, 38, 53, 52, 55, 54, 59,
+ 1, 21, 35, 38, 21, 20, 31, 1, 22, 21, 20, 7, 1, 40, 14, 51, 1,238,253,195, 87, 58, 39, 36, 1, 70, 31, 1, 2, 91,149, 76,
+ 22, 50,214,115,101, 96, 54,142,103, 43,182, 17, 33, 32,162, 69, 47, 62, 65, 47, 1,173, 40, 60, 69, 99,163, 83,101, 40, 50,122,
+175, 1, 58, 46, 59,155,112,110,117, 57, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 16, 6, 2, 6, 0, 0, 0, 2, 0,159,
+254, 86, 3,150, 4,123, 0, 27, 0, 41, 0, 99, 64, 14, 43, 69, 40, 18, 5, 25, 2, 18, 11, 34, 18, 17, 69, 42, 16,252,236, 60,
+236,212, 60,236,228, 49, 64, 10, 5,169, 6,189, 42, 30,185, 21,184, 42, 0, 16,244,236, 16,252,236, 48, 64, 11, 26, 27, 27, 17,
+ 0, 17, 37, 14, 13, 38, 13, 7, 5, 16, 60, 60,236,236, 4, 16, 60,178, 0, 27, 25, 1, 73, 80, 88,177, 27, 25, 16, 60, 89, 64,
+ 9, 37, 17, 36, 17, 14, 38, 13, 15, 14, 7, 8, 16,236,236, 5, 6, 21, 20, 51, 33, 21, 33, 34, 39, 38, 39, 38, 63, 1, 3, 38,
+ 53, 52, 55, 54, 51, 50, 23, 22, 21, 20, 7, 3, 38, 35, 34, 7, 6, 21, 20, 23, 27, 1, 54, 39, 38, 1,134, 14, 47, 1,238,253,
+195, 87, 58, 37, 2, 2, 38,145,141, 40, 96, 91,175,212,115, 68, 69,159, 72,100, 59, 54, 59, 33, 88,191, 68, 1, 1,192, 19, 21,
+ 32,162, 69, 44, 65, 55, 57,217, 1,228,137, 70,163,109,103,171,101,139,154,101, 1,139, 89, 45, 49,103, 60,120,254,191, 1, 26,
+101, 94, 89, 0, 0, 1, 0,186, 0, 0, 4,116, 4,123, 0, 28, 0,103, 64, 13, 28, 9, 2, 18, 25, 21, 78, 13, 9, 8, 11, 70,
+ 29, 16,252,236, 50,244, 60,236, 16,220, 49, 64, 12, 6,135, 14, 17,184, 12,188, 28, 25,169, 26, 10, 0, 47, 60,236, 50,228,244,
+196,236,181, 21, 2, 9, 3, 14, 10, 17, 18, 23, 57, 48,177, 23, 0, 16, 60, 64, 8, 23, 17, 0, 24, 17, 28, 0, 28, 7, 5, 16,
+236, 16,236, 1,178, 0, 23, 21, 73, 80, 88,177, 23, 21, 16, 60, 89,180, 96, 30,207, 30, 2, 1, 93, 1, 54, 55, 54, 39, 38, 35,
+ 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 23, 22, 21, 20, 7, 1, 33, 21, 33, 53, 3, 82, 90, 1, 1, 64, 62,124,149,172,
+185,185, 66,179,117,205,127, 65, 71,254,250, 1, 87,253,223, 1,232,110,132, 96, 82, 79,190,164,253,135, 4, 96,174,101,100,185,
+ 94,119,176, 85,254,199,175,175,255,255, 0,174,255,227, 4, 88, 4, 96, 18, 6, 0, 88, 0, 0, 0, 1, 0,174,254, 86, 5, 45,
+ 6, 20, 0, 21, 0, 61, 64, 12, 23, 13, 15, 9, 8, 11, 78, 2, 8, 0, 70, 22, 16,252,236,244,236, 50,220,196, 49, 64, 21, 3,
+ 9, 0, 3, 16, 1, 6,135, 16, 19,140, 10,151, 1,188, 22, 13,169, 15,189, 22, 0, 16,252,236, 16,228,228,244,196,236, 17, 18,
+ 23, 57, 48, 19, 17, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 51, 21, 33, 17, 14, 1, 35, 34, 38,174,184,124,124,149,173,184,
+213,254,115, 67,177,117,193,200, 1,186, 2,166,253, 97,159,159,190,164, 4, 47,248,228,162, 2, 86,102, 99,240, 0, 1, 0,174,
+255,227, 7, 28, 4,123, 0, 37, 0,105, 64, 15, 12, 8, 10, 80, 21, 1, 8, 2, 20, 80, 31, 8, 29, 70, 38, 16,252,236,252, 60,
+252, 60,252,236, 49, 64, 17, 15,135, 3, 6,184, 10, 34,135, 22, 25,140, 10, 1, 29,188, 20, 10, 0, 47, 60,244, 60, 16,244,196,
+236, 16,244,196,236,181, 28, 31, 0, 3, 22, 29, 17, 18, 23, 57,181, 9, 12, 19, 3, 3, 10, 17, 18, 23, 57, 48, 64, 19, 48, 39,
+ 80, 39,112, 39,144, 39,160, 39,160, 39,191, 39,223, 39,255, 39, 9, 1, 93, 1, 17, 51, 21, 62, 1, 51, 50, 22, 21, 17, 35, 17,
+ 52, 38, 35, 34, 7, 6, 21, 17, 35, 53, 14, 1, 35, 34, 38, 53, 17, 51, 17, 20, 22, 51, 50, 55, 54, 3,143,184, 66,179, 89,193,
+198,184,124,124,122, 85, 86,184, 67,177,100,193,200,184,124,124,130, 88, 87, 1,229, 2,123,174,101,100,239,232,253, 92, 2,158,
+159,158, 95, 96,163,253,135,172,102, 99,240,231, 2,166,253, 97,159,159, 95, 92, 0, 1, 0,186,254, 86, 4,100, 4,123, 0, 19,
+ 0, 55, 64, 26, 3, 9, 0, 3, 14, 1, 6,135, 14, 17,184, 12,188, 10,189, 1, 2, 8, 0, 78, 13, 9, 8, 11, 70, 20, 16,252,
+236, 50,244,236, 49, 0, 47,236,228,244,196,236, 17, 18, 23, 57, 48,180, 96, 21,207, 21, 2, 1, 93, 1, 17, 35, 17, 52, 38, 35,
+ 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 22, 4,100,184,124,124,149,172,185,185, 66,179,117,193,198, 2,164,253, 92, 2,
+158,159,158,190,164,251,221, 6, 10,174,101,100,239, 0, 0, 0,255,255, 0,113,254, 86, 4, 90, 4,123, 18, 6, 0, 74, 0, 0,
+ 0, 1, 0,193, 0, 0, 2,215, 4, 96, 0, 5, 0, 29, 64, 7, 7, 1, 5, 8, 3, 70, 6, 16,252,252,212,196, 49, 0, 64, 6,
+ 4,188, 3, 1,169, 2, 47,236, 16,228, 48, 37, 33, 21, 33, 17, 51, 1,121, 1, 94,253,234,184,175,175, 4, 96, 0, 1, 0,174,
+254, 86, 7, 28, 6, 20, 0, 37, 0,107, 64, 15, 12, 8, 10, 80, 21, 1, 8, 2, 20, 80, 31, 8, 29, 70, 38, 16,252,236,252, 60,
+252, 60,252,236, 49, 64, 19, 15,135, 3, 6,184, 10, 34,135, 22, 25,140, 10, 29,188, 1,151, 20,189, 10, 0, 47,236,228,244, 16,
+244,196,236, 16,244,196,236,181, 28, 31, 0, 3, 22, 29, 17, 18, 23, 57,181, 9, 12, 19, 3, 3, 10, 17, 18, 23, 57, 48, 64, 19,
+ 48, 39, 80, 39,112, 39,144, 39,160, 39,160, 39,191, 39,223, 39,255, 39, 9, 1, 93, 1, 17, 51, 17, 62, 1, 51, 50, 22, 21, 17,
+ 35, 17, 52, 38, 35, 34, 7, 6, 21, 17, 35, 17, 14, 1, 35, 34, 38, 53, 17, 51, 17, 20, 22, 51, 50, 55, 54, 3,143,184, 66,179,
+ 89,193,198,184,124,124,118, 89, 86,184, 67,177,100,193,200,184,124,124,130, 88, 87, 1,229, 4, 47,253,158,101,100,239,232,253,
+ 92, 2,158,159,158, 95, 92,167,251,221, 2, 86,102, 99,240,231, 2,166,253, 97,159,159, 95, 92, 0, 2, 0, 0,254, 86, 4,191,
+ 4,123, 0, 24, 0, 36, 0, 85, 64, 16, 38, 69, 11, 19, 25, 18, 11, 71, 31, 22, 4, 18, 8, 23, 2, 1, 47,220, 60,236, 50, 50,
+ 50,244,236,196, 16,228, 49, 64, 22, 34,185, 17, 14, 28,185, 5, 8,184, 14,140, 37, 20, 24,169, 18, 2, 22,189, 3,188, 37, 0,
+ 16,228,236,220, 60,252, 60, 16,228,244,196,236, 16,196,238,178, 0, 22, 24, 73, 80, 88,177, 22, 24, 16, 60, 89, 48, 21, 53, 51,
+ 17, 51, 21, 62, 1, 51, 50, 0, 17, 16, 2, 35, 34, 38, 39, 17, 33, 21, 33, 21, 35, 53, 1, 52, 38, 35, 34, 6, 21, 20, 22, 51,
+ 50, 54,213,185, 58,177,123,204, 0,255,255,204,123,177, 58, 2,233,253, 23,185, 3, 43,167,146,146,167,167,146,146,167,250,150,
+ 4,196,170,100, 97,254,188,254,248,254,248,254,188, 97,100,254,244,150,176,176, 3, 41,203,231,231,203,203,231,231, 0, 0, 0,
+255,255, 0,113,255,227, 4,117, 4,123, 18, 6, 0, 82, 0, 0, 0, 3, 0,122,254, 86, 4,150, 6, 43, 0, 34, 0, 45, 0, 54,
+ 0,117, 64, 17, 56, 51, 18, 28, 32, 22, 46, 8, 0, 35, 10, 42, 18, 5, 14, 69, 55, 16,252, 60,236,220, 60, 60,252, 60, 60,220,
+236,196, 49, 64, 18, 5,134, 4, 38,185, 18,151, 55, 47, 9,135, 4, 32, 0,140, 34,189, 55, 0, 16,236,244, 60,196,236, 50, 16,
+244,236, 16,236,179, 23, 35, 0, 18, 17, 18, 57, 57,178, 14, 35, 18, 17, 18, 57,182, 26, 51, 46, 10, 4, 32, 23, 17, 18, 23, 57,
+ 48,180, 23, 35, 24, 24, 44, 7, 4, 16, 60, 60,181, 46, 17, 23, 10, 17, 35, 16,236, 16,236, 5, 38, 39, 38, 39, 53, 22, 23, 22,
+ 23, 17, 38, 39, 38, 53, 52, 55, 54, 55, 54, 23, 22, 21, 17, 23, 22, 23, 22, 21, 16, 7, 6, 35, 17, 35, 25, 1, 52, 39, 38, 7,
+ 6, 21, 22, 23, 22, 5, 17, 50, 55, 54, 53, 52, 39, 38, 2, 44, 68,100,125,141, 49,211, 75, 99,231,102,101,112, 95,152,123, 53,
+ 83, 35,194, 97,108,146,126,162,184, 69, 85, 24, 64, 1, 59, 39, 1, 71, 93, 55, 95, 69, 56, 24, 2, 17, 21, 71,187, 31, 73, 26,
+ 1, 2,163, 45, 97, 96,165,147,113, 96, 1, 2, 52, 79,148,254,169, 7, 45, 98,108,235,254,218,105, 90,254,110, 5,141, 1, 33,
+115, 3, 2, 29, 79, 59,115, 58, 36,246,253,129, 43, 73,191,179, 74, 62, 0, 0, 0, 1, 0,174,255,227, 5,182, 6, 20, 0, 21,
+ 0, 56, 64, 12, 23, 13, 15, 9, 8, 11, 78, 2, 8, 0, 70, 22, 16,252,236,244,236, 50,220,196, 49, 64, 18, 3, 9, 0, 3, 16,
+ 10, 6,135, 16, 19,140, 1,151, 10,188, 13,169, 15, 0, 47,236,228,228,244,196,236, 17, 18, 23, 57, 48, 19, 17, 51, 17, 20, 22,
+ 51, 50, 54, 53, 17, 51, 17, 33, 21, 33, 53, 14, 1, 35, 34, 38,174,184,124,124,149,173,184, 1, 94,253,234, 67,177,117,193,200,
+ 1,186, 4, 90,251,173,159,159,190,164, 2,123,252, 79,175,172,102, 99,240, 0, 0, 2, 0,240, 0, 0, 1,195, 3, 82, 0, 3,
+ 0, 7, 0, 29, 64, 7, 5, 1, 3, 4, 0, 24, 8, 16,252, 60,236, 50, 49, 0, 64, 6, 6,131, 4, 0,131, 2, 47,236, 47,236,
+ 48, 55, 51, 21, 35, 17, 51, 21, 35,240,211,211,211,211,254,254, 3, 82,254, 0, 0, 1, 0, 96, 1,164, 3, 33, 2,238, 0, 11,
+ 0, 0, 1, 30, 1, 55, 21, 14, 1, 34, 38, 39, 51, 22, 1, 85, 32,222,205, 44,228,255,157, 20,167, 16, 2, 99, 24, 1, 65,162,
+ 14, 55,170,159, 87, 0, 0, 0, 0, 1, 0,219, 0, 0, 2, 0, 1,236, 0, 5, 0, 0, 33, 35, 53, 19, 51, 3, 1,174,211,164,
+129, 82,172, 1, 64,254,192, 0,255,255, 0, 16,253, 46, 5,104, 5,213, 16, 39, 2, 70, 0,183, 0, 0, 18, 2, 0, 36, 0, 0,
+255,255, 0,123,253, 46, 4, 45, 4,123, 16, 38, 2, 70,107, 0, 18, 2, 0, 68, 0, 0, 0, 0,255,255, 0,201, 0, 0, 4,236,
+ 7, 80, 18, 34, 0, 37, 0, 0, 16, 3, 2, 50, 0,173, 1, 64,255,255, 0,186,255,227, 4,164, 7,133, 16, 39, 2, 79, 3, 22,
+ 1,117, 18, 6, 0, 69, 0, 0,255,255, 0,201,254,135, 4,236, 5,213, 18, 34, 0, 37, 0, 0, 16, 3, 2,107, 4,165, 0, 0,
+255,255, 0,186,254,135, 4,164, 6, 20, 18, 34, 0, 69, 0, 0, 16, 3, 2,107, 4,154, 0, 0,255,255, 0,201,254,192, 4,236,
+ 5,213, 18, 34, 0, 37, 0, 0, 16, 3, 2, 38, 0,151, 0, 0,255,255, 0,186,254,192, 4,164, 6, 20, 18, 34, 0, 69, 0, 0,
+ 16, 3, 2, 38, 0,143, 0, 0,255,255, 0,115,254,117, 5, 39, 7,107, 18, 34, 0,137, 0, 0, 16, 67, 0,118, 0,254, 2,240,
+ 64, 0, 44,204,255,255, 0,113,254,117, 3,231, 6,102, 18, 34, 0,169, 0, 0, 16, 2, 0,118, 67, 0, 0, 0,255,255, 0,201,
+ 0, 0, 5,176, 7, 80, 18, 34, 0, 39, 0, 0, 16, 3, 2, 50, 0,253, 1, 64,255,255, 0,113,255,227, 4,110, 7,133, 16, 39,
+ 2, 79, 5,254, 1,117, 18, 6, 0, 71, 0, 0,255,255, 0,201,254,135, 5,176, 5,213, 16, 35, 2,107, 4,174, 0, 0, 16, 2,
+ 0, 39, 0, 0,255,255, 0,113,254,135, 4, 90, 6, 20, 16, 35, 2,107, 4,122, 0, 0, 16, 2, 0, 71, 0, 0,255,255, 0,201,
+254,192, 5,176, 5,213, 18, 34, 0, 39, 0, 0, 16, 3, 2, 38, 0,232, 0, 0,255,255, 0,113,254,192, 4, 90, 6, 20, 18, 34,
+ 0, 71, 0, 0, 16, 2, 2, 38, 79, 0, 0, 0,255,255, 0,201,254,119, 5,176, 5,213, 18, 34, 0, 39, 0, 0, 16, 2, 0,122,
+ 91, 2, 0, 0,255,255, 0,113,254,117, 4, 90, 6, 20, 18, 34, 0, 71, 0, 0, 16, 2, 0,122,246, 0, 0, 0,255,255, 0,201,
+254, 24, 5,176, 5,213, 16, 39, 2, 31, 0,166,249, 42, 18, 6, 0, 39, 0, 0,255,255, 0,113,254, 24, 4, 90, 6, 20, 16, 39,
+ 2, 31, 0, 94,249, 42, 18, 6, 0, 71, 0, 0,255,255, 0,201, 0, 0, 4,139, 5,213, 18, 34, 0, 40, 0, 0, 16, 6, 6,149,
+238, 0, 0, 0,255,255, 0,113,255,227, 4,127, 4,123, 16, 39, 6,149,255,217,255, 4, 16, 6, 0, 72, 0, 0,255,255, 0,201,
+ 0, 0, 4,139, 5,213, 18, 34, 0, 40, 0, 0, 16, 6, 6,148,236, 0, 0, 0,255,255, 0,113,255,227, 4,127, 4,123, 16, 38,
+ 0, 72, 0, 0, 16, 7, 6,148,255,215,255, 4,255,255, 0,201,253,221, 4,139, 5,213, 18, 34, 0, 40, 0, 0, 16, 3, 2,117,
+ 4,177, 0, 0,255,255, 0,113,253,221, 4,127, 4,123, 18, 34, 0, 72, 0, 0, 16, 3, 2,117, 4,176, 0, 0,255,255, 0,201,
+254,118, 4,139, 5,213, 18, 34, 0, 40, 0, 0, 16, 3, 2, 71, 0,179, 0, 0,255,255, 0,113,254,118, 4,127, 4,123, 18, 34,
+ 0, 72, 0, 0, 16, 3, 2, 71, 0,155, 0, 0,255,255, 0,201,254,117, 4,139, 7,102, 18, 34, 0, 40, 0, 0, 16, 99, 2, 49,
+ 0,218, 1,190, 64, 0, 57,153, 16, 3, 0,122, 0,190, 0, 0,255,255, 0,113,254,117, 4,127, 6, 72, 18, 34, 0, 72, 0, 0,
+ 16, 35, 2, 49, 0,135, 0, 0, 16, 2, 0,122, 75, 0, 0, 0,255,255, 0,201, 0, 0, 4, 35, 7, 80, 18, 34, 0, 41, 0, 0,
+ 16, 3, 2, 50, 0,118, 1, 64,255,255, 0, 47, 0, 0, 2,248, 7, 80, 18, 34, 0, 73, 0, 0, 16, 3, 2, 50, 0, 12, 1, 64,
+255,255, 0,115,255,227, 5,139, 7, 24, 18, 34, 0, 42, 0, 0, 16, 3, 2, 34, 1, 50, 1, 34,255,255, 0,113,254, 86, 4, 90,
+ 5,246, 18, 34, 0, 74, 0, 0, 16, 2, 2, 34, 73, 0, 0, 0,255,255, 0,201, 0, 0, 5, 59, 7, 80, 18, 34, 0, 43, 0, 0,
+ 16, 3, 2, 50, 1, 20, 1, 64,255,255, 0,186, 0, 0, 4,100, 7,133, 16, 39, 2, 79, 3, 22, 1,117, 18, 6, 0, 75, 0, 0,
+255,255, 0,201,254,135, 5, 59, 5,213, 16, 35, 2,107, 5, 2, 0, 0, 16, 2, 0, 43, 0, 0,255,255, 0,186,254,135, 4,100,
+ 6, 20, 16, 35, 2,107, 4,143, 0, 0, 16, 2, 0, 75, 0, 0,255,255, 0,201, 0, 0, 5, 59, 7, 80, 18, 34, 0, 43, 0, 0,
+ 16, 3, 0,106, 1, 8, 1, 64,255,255,255,235, 0, 0, 4,100, 7,133, 16, 39, 2, 80, 3, 22, 1,117, 18, 6, 0, 75, 0, 0,
+255,255, 0, 17,254,116, 5, 59, 5,213, 18, 34, 0, 43, 0, 0, 16, 3, 0,122,254,238,255,255,255,255, 0, 2,254,116, 4,100,
+ 6, 20, 18, 34, 0, 75, 0, 0, 16, 3, 0,122,254,223,255,255,255,255, 0,201,254, 57, 5, 59, 5,213, 18, 34, 0, 43, 0, 0,
+ 16, 3, 2,118, 5, 10, 0, 0,255,255, 0,186,254, 57, 4,100, 6, 20, 18, 34, 0, 75, 0, 0, 16, 3, 2,118, 4,149, 0, 0,
+255,255, 0, 0,254,118, 2,148, 5,213, 18, 34, 0, 44, 0, 0, 16, 3, 2, 71,255, 74, 0, 0,255,255, 0, 39,254,118, 2, 56,
+ 6, 20, 18, 34, 0, 76, 0, 0, 16, 66, 2, 71,150, 0, 51, 51, 64, 0, 0, 0,255,255, 0,201, 0, 0, 1,147, 5,213, 18, 34,
+ 0, 44, 0, 0, 16, 7, 6,146,254,116, 0, 0,255,255, 0,193, 0, 0, 1,121, 4, 96, 18, 34, 0,243, 0, 0, 16, 7, 6,146,
+254, 97,254,188,255,255, 0,201, 0, 0, 5,106, 7,107, 18, 34, 0, 46, 0, 0, 16, 67, 0,118, 0,164, 2,240, 64, 0, 44,204,
+255,255, 0,186, 0, 0, 4,156, 6, 20, 16, 39, 6,133, 3, 90, 1,118, 18, 2, 0, 78, 0, 0,255,255, 0,201,254,135, 5,106,
+ 5,213, 18, 34, 0, 46, 0, 0, 16, 3, 2,107, 4,220, 0, 0,255,255, 0,186,254,135, 4,156, 6, 20, 18, 34, 0, 78, 0, 0,
+ 16, 3, 2,107, 4,145, 0, 0,255,255, 0,201,254,192, 5,106, 5,213, 18, 34, 0, 46, 0, 0, 16, 3, 2, 38, 1, 13, 0, 0,
+255,255, 0,186,254,192, 4,156, 6, 20, 18, 34, 0, 78, 0, 0, 16, 2, 2, 38,118, 0, 0, 0,255,255, 0,201,254,135, 4,106,
+ 5,213, 16, 35, 2,107, 4,154, 0, 0, 16, 2, 0, 47, 0, 0,255,255, 0,182,254,135, 1,131, 6, 20, 16, 35, 2,107, 3, 28,
+ 0, 0, 16, 2, 0, 79, 0, 0,255,255, 0, 3,254,136, 4,106, 7,107, 16, 39, 2, 76, 3, 42, 1,117, 16, 39, 2,107, 4,153,
+ 0, 1, 18, 6, 0, 47, 0, 0,255,255,255,241,254,135, 2, 72, 7, 49, 16, 35, 0,113,255, 28, 1, 59, 16, 2, 4,179, 0, 0,
+255,255, 0,201,254,192, 4,106, 5,213, 18, 34, 0, 47, 0, 0, 16, 3, 2, 38, 0,142, 0, 0,255,255, 0, 39,254,192, 2, 7,
+ 6, 20, 18, 34, 0, 79, 0, 0, 16, 67, 2, 38,255,125, 0, 0, 51, 51, 64, 0,255,255, 0,201,254, 23, 4,106, 5,213, 16, 39,
+ 2, 31, 0,151,249, 41, 18, 6, 0, 47, 0, 0,255,255,255,222,254, 23, 2, 92, 6, 20, 16, 39, 2, 31,255, 29,249, 41, 18, 6,
+ 0, 79, 0, 0,255,255, 0,201, 0, 0, 6, 31, 7,107, 18, 34, 0, 48, 0, 0, 16, 67, 0,118, 1, 66, 2,240, 64, 0, 44,204,
+255,255, 0,186, 0, 0, 7, 29, 6,102, 18, 34, 0, 80, 0, 0, 16, 3, 0,118, 1,148, 0, 0,255,255, 0,201, 0, 0, 6, 31,
+ 7, 80, 18, 34, 0, 48, 0, 0, 16, 3, 2, 50, 1,119, 1, 64,255,255, 0,186, 0, 0, 7, 29, 6, 16, 16, 39, 2, 50, 2, 70,
+ 0, 0, 18, 6, 0, 80, 0, 0,255,255, 0,201,254,135, 6, 31, 5,213, 16, 35, 2,107, 5,116, 0, 0, 16, 2, 0, 48, 0, 0,
+255,255, 0,186,254,135, 7, 29, 4,123, 16, 35, 2,107, 5,230, 0, 0, 16, 2, 0, 80, 0, 0,255,255, 0,201, 0, 0, 5, 51,
+ 5,213, 16, 39, 6,140, 4,254, 1, 92, 18, 6, 0, 49, 0, 0,255,255, 0,186, 0, 0, 4,100, 5,193, 16, 39, 2, 50, 0,143,
+255,177, 18, 6, 0, 81, 0, 0,255,255, 0,201,254,135, 5, 51, 5,213, 16, 35, 2,107, 4,254, 0, 0, 16, 2, 0, 49, 0, 0,
+255,255, 0,186,254,135, 4,100, 4,123, 16, 35, 2,107, 4,143, 0, 0, 16, 2, 0, 81, 0, 0,255,255, 0,201,254,192, 5, 51,
+ 5,213, 18, 34, 0, 49, 0, 0, 16, 3, 2, 38, 0,247, 0, 0,255,255, 0,186,254,192, 4,100, 4,123, 18, 34, 0, 81, 0, 0,
+ 16, 3, 2, 38, 0,140, 0, 0,255,255, 0,201,254, 21, 5, 51, 5,213, 16, 39, 2, 31, 0,254,249, 39, 18, 6, 0, 49, 0, 0,
+255,255, 0,186,254, 21, 4,100, 4,123, 16, 39, 2, 31, 0,149,249, 39, 18, 6, 0, 81, 0, 0,255,255, 0,115,255,227, 5,217,
+ 5,240, 18, 34, 0, 50, 0, 0, 16, 6, 6,154,102, 0, 0, 0,255,255, 0,113,255,227, 4,117, 4,123, 18, 34, 0, 82, 0, 0,
+ 16, 7, 6,154,255,178,254,178,255,255, 0,115,255,227, 5,217, 5,240, 18, 34, 0, 50, 0, 0, 16, 6, 6,152,108, 0, 0, 0,
+255,255, 0,113,255,227, 4,117, 7, 15, 18, 34, 0, 82, 0, 0, 16, 39, 0,106, 0,111, 0,255, 16, 7, 6,134, 4,114, 0, 18,
+255,255, 0,115,255,227, 5,217, 5,240, 18, 34, 0, 50, 0, 0, 16, 6, 6,149,106, 0, 0, 0,255,255, 0,113,255,227, 4,117,
+ 4,123, 16, 38, 0, 82, 0, 0, 16, 7, 6,149,255,181,255, 4,255,255, 0,115,255,227, 5,217, 5,240, 18, 34, 0, 50, 0, 0,
+ 16, 6, 6,148,104, 0, 0, 0,255,255, 0,113,255,227, 4,117, 4,123, 16, 39, 6,148,255,185,255, 4, 16, 6, 0, 82, 0, 0,
+255,255, 0,201, 0, 0, 4,141, 7,107, 18, 34, 0, 51, 0, 0, 16, 67, 0,118, 0, 65, 2,240, 64, 0, 44,204,255,255, 0,186,
+254, 86, 4,164, 6,102, 18, 34, 0, 83, 0, 0, 16, 2, 0,118, 50, 0, 0, 0,255,255, 0,201, 0, 0, 4,141, 7, 80, 18, 34,
+ 0, 51, 0, 0, 16, 3, 2, 50, 0,132, 1, 64,255,255, 0,186,254, 86, 4,164, 6, 16, 16, 39, 2, 50, 0,217, 0, 0, 18, 6,
+ 0, 83, 0, 0,255,255, 0,201, 0, 0, 5, 84, 7, 80, 18, 34, 0, 53, 0, 0, 16, 3, 2, 50, 0,131, 1, 64,255,255, 0,186,
+ 0, 0, 3, 74, 6, 18, 18, 34, 0, 85, 0, 0, 16, 2, 2, 50, 19, 2, 0, 0,255,255, 0,201,254,135, 5, 84, 5,213, 16, 35,
+ 2,107, 4,125, 0, 0, 16, 2, 0, 53, 0, 0,255,255, 0,186,254,135, 3, 74, 4,123, 16, 35, 2,107, 3, 32, 0, 0, 16, 2,
+ 0, 85, 0, 0,255,255, 0,201,254,135, 5, 84, 7, 51, 16, 99, 0,113, 0,122, 1, 50, 64, 0, 64,110, 16, 2, 4,214, 0, 0,
+255,255, 0,186,254,135, 3, 74, 5,245, 16, 34, 0,113, 24,255, 16, 2, 4,215, 0, 0, 0, 0,255,255, 0,201,254,192, 5, 84,
+ 5,213, 18, 34, 0, 53, 0, 0, 16, 3, 2, 38, 0,229, 0, 0,255,255, 0, 84,254,192, 3, 74, 4,123, 18, 34, 0, 85, 0, 0,
+ 16, 3, 2, 38,255,127, 0, 0,255,255, 0,135,255,227, 4,162, 7, 80, 18, 34, 0, 54, 0, 0, 16, 3, 2, 50, 0,184, 1, 64,
+255,255, 0,111,255,227, 3,199, 6, 16, 16, 38, 2, 50, 37, 0, 18, 6, 0, 86, 0, 0, 0, 0,255,255, 0,135,254,135, 4,162,
+ 5,240, 16, 35, 2,107, 4,138, 0, 0, 16, 2, 0, 54, 0, 0,255,255, 0,111,254,135, 3,199, 4,123, 16, 35, 2,107, 4, 21,
+ 0, 0, 16, 2, 0, 86, 0, 0,255,255, 0,135,255,227, 4,162, 7,107, 18, 34, 0, 54, 0, 0, 16, 35, 2, 50,255,164, 1, 90,
+ 16, 67, 0,118, 0,242, 2,240, 64, 0, 44,204,255,255, 0,111,255,227, 3,226, 6,102, 18, 34, 0, 86, 0, 0, 16, 34, 2, 50,
+140, 86, 16, 3, 0,118, 0,144, 0, 0, 0, 0,255,255, 0,135,255,227, 4,162, 5,240, 16, 38, 6,153,228, 0, 18, 2, 0, 54,
+ 0, 0, 0, 0,255,255, 0,111,255,227, 3,199, 7,176, 16, 38, 1, 35, 0, 0, 16, 7, 2, 50, 0, 34, 1,160,255,255, 0,135,
+254,135, 4,162, 7, 80, 18, 34, 4,222, 0, 0, 16, 3, 2, 50, 0,155, 1, 64,255,255, 0,111,254,135, 3,199, 6, 18, 18, 34,
+ 4,223, 0, 0, 16, 2, 2, 50, 42, 2, 0, 0,255,255,255,250, 0, 0, 4,233, 7, 80, 18, 34, 0, 55, 0, 0, 16, 3, 2, 50,
+ 0,114, 1, 64,255,255, 0, 55, 0, 0, 2,242, 7, 47, 18, 34, 0, 87, 0, 0, 16, 3, 2, 50,255, 35, 1, 31,255,255,255,250,
+254,135, 4,233, 5,213, 16, 35, 2,107, 4,113, 0, 0, 16, 2, 0, 55, 0, 0,255,255, 0, 55,254,135, 2,242, 5,158, 16, 35,
+ 2,107, 3,232, 0, 0, 16, 2, 0, 87, 0, 0,255,255,255,250,254,192, 4,233, 5,213, 18, 34, 0, 55, 0, 0, 16, 2, 2, 38,
+ 98, 0, 0, 0,255,255, 0, 55,254,192, 2,242, 5,158, 18, 34, 0, 87, 0, 0, 16, 66, 2, 38, 60, 0, 51, 51, 64, 0, 0, 0,
+255,255,255,250,254, 21, 4,233, 5,213, 16, 39, 2, 31, 0,114,249, 39, 18, 6, 0, 55, 0, 0,255,255, 0, 55,254, 20, 3, 39,
+ 5,158, 16, 39, 2, 31,255,232,249, 38, 18, 6, 0, 87, 0, 0,255,255, 0,178,254,137, 5, 41, 5,213, 16, 35, 2,108, 4,240,
+ 0, 0, 18, 2, 0, 56, 0, 0,255,255, 0,174,254,137, 4, 88, 4, 96, 16, 35, 2,108, 4,123, 0, 0, 18, 2, 0, 88, 0, 0,
+255,255, 0,178,254,118, 5, 41, 5,213, 18, 34, 0, 56, 0, 0, 16, 3, 2, 71, 0,242, 0, 0,255,255, 0,174,254,118, 4, 88,
+ 4, 96, 18, 34, 0, 88, 0, 0, 16, 3, 2, 71, 0,143, 0, 0,255,255, 0,178,253,221, 5, 41, 5,213, 18, 34, 0, 56, 0, 0,
+ 16, 3, 2,117, 4,224, 0, 0,255,255, 0,174,253,221, 4, 88, 4, 96, 18, 34, 0, 88, 0, 0, 16, 3, 2,117, 4,117, 0, 0,
+255,255, 0,178,255,227, 5, 41, 5,213, 16, 38, 6,154, 46, 0, 18, 2, 0, 56, 0, 0, 0, 0,255,255, 0,174,255,227, 4, 88,
+ 7,236, 16, 38, 1, 43, 0, 0, 16, 7, 0,118, 0,150, 1,134,255,255, 0,178,255,227, 5, 41, 5,213, 16, 38, 6,144, 50, 0,
+ 18, 2, 0, 56, 0, 0, 0, 0,255,255, 0,174,255,227, 4, 88, 4, 96, 16, 39, 6,144,255,200,254,192, 18, 2, 0, 88, 0, 0,
+255,255, 0, 16, 0, 0, 5,104, 7,125, 18, 34, 0, 57, 0, 0, 16, 3, 2, 53, 0,237, 1, 70,255,255, 0, 61, 0, 0, 4,127,
+ 6, 55, 18, 34, 0, 89, 0, 0, 16, 2, 2, 53,109, 0, 0, 0,255,255, 0, 16,254,135, 5,104, 5,213, 16, 38, 0, 57, 0, 0,
+ 16, 7, 2,107, 4,188, 0, 0,255,255, 0, 61,254,135, 4,127, 4, 96, 16, 38, 0, 89, 0, 0, 16, 7, 2,107, 4, 94, 0, 0,
+255,255, 0, 68, 0, 0, 7,166, 5,213, 16, 39, 6,135, 5,245, 1,124, 18, 6, 0, 58, 0, 0,255,255, 0, 86, 0, 0, 6, 53,
+ 6,107, 16, 39, 0, 67, 1, 9, 0, 5, 18, 6, 0, 90, 0, 0,255,255, 0, 68, 0, 0, 7,166, 5,213, 16, 39, 6,133, 5,245,
+ 1,124, 18, 6, 0, 58, 0, 0,255,255, 0, 86, 0, 0, 6, 53, 6,109, 16, 39, 0,118, 1,134, 0, 7, 18, 6, 0, 90, 0, 0,
+255,255, 0, 68, 0, 0, 7,166, 7, 52, 16, 39, 0,106, 1,245, 1, 36, 18, 6, 0, 58, 0, 0,255,255, 0, 86, 0, 0, 6, 53,
+ 5,191, 16, 39, 0,106, 1, 69,255,175, 18, 6, 0, 90, 0, 0,255,255, 0, 68, 0, 0, 7,166, 7, 80, 18, 34, 0, 58, 0, 0,
+ 16, 3, 2, 50, 1,245, 1, 64,255,255, 0, 86, 0, 0, 6, 53, 6, 18, 18, 34, 0, 90, 0, 0, 16, 3, 2, 50, 1, 71, 0, 2,
+255,255, 0, 68,254,135, 7,166, 5,213, 18, 34, 0, 58, 0, 0, 16, 3, 2,107, 5,251, 0, 0,255,255, 0, 86,254,135, 6, 53,
+ 4, 96, 18, 34, 0, 90, 0, 0, 16, 3, 2,107, 5, 74, 0, 0,255,255, 0, 61, 0, 0, 5, 59, 7, 80, 18, 34, 0, 59, 0, 0,
+ 16, 3, 2, 50, 0,202, 1, 64,255,255, 0, 59, 0, 0, 4,121, 6, 18, 18, 34, 0, 91, 0, 0, 16, 2, 2, 50,103, 2, 0, 0,
+255,255, 0, 61, 0, 0, 5, 59, 7, 78, 18, 34, 0, 59, 0, 0, 16, 3, 0,106, 0,202, 1, 62,255,255, 0, 59, 0, 0, 4,121,
+ 6, 16, 18, 34, 0, 91, 0, 0, 16, 2, 0,106,102, 0, 0, 0,255,255,255,252, 0, 0, 4,231, 7, 80, 18, 34, 0, 60, 0, 0,
+ 16, 3, 2, 50, 0,112, 1, 64,255,255, 0, 61,254, 86, 4,127, 6, 16, 18, 34, 0, 92, 0, 0, 16, 2, 2, 50,102, 0, 0, 0,
+255,255, 0, 92, 0, 0, 5, 31, 7,107, 18, 34, 0, 61, 0, 0, 16, 67, 2, 31, 0,190, 2,240, 64, 0, 44,204,255,255, 0, 88,
+ 0, 0, 3,219, 6,102, 18, 34, 0, 93, 0, 0, 16, 2, 2, 31, 26, 0, 0, 0,255,255, 0, 92,254,135, 5, 31, 5,213, 18, 34,
+ 0, 61, 0, 0, 16, 3, 2,107, 4,217, 0, 0,255,255, 0, 88,254,135, 3,219, 4, 96, 18, 34, 0, 93, 0, 0, 16, 3, 2,107,
+ 4, 49, 0, 0,255,255, 0, 92,254,192, 5, 31, 5,213, 18, 34, 0, 61, 0, 0, 16, 3, 2, 38, 0,199, 0, 0,255,255, 0, 88,
+254,192, 3,219, 4, 96, 18, 34, 0, 93, 0, 0, 16, 2, 2, 38, 27, 0, 0, 0,255,255, 0,186,254,192, 4,100, 6, 20, 18, 34,
+ 0, 75, 0, 0, 16, 2, 2, 38,102, 0, 0, 0,255,255, 0, 4, 0, 0, 2,242, 7, 78, 18, 34, 0, 87, 0, 0, 16, 3, 0,106,
+255, 45, 1, 62,255,255, 0, 86, 0, 0, 6, 53, 7, 6, 18, 34, 0, 90, 0, 0, 16, 3, 2, 51, 1, 66, 0, 0,255,255, 0, 61,
+254, 86, 4,127, 7, 6, 18, 34, 0, 92, 0, 0, 16, 3, 2, 51, 0,129, 0, 0,255,255, 0,123,255,227, 5, 97, 6, 20, 18, 34,
+ 0, 68, 0, 0, 16, 3, 2, 23, 3,218, 0, 0,255,255, 0, 47, 0, 0, 2,248, 7, 80, 18, 34, 1, 65, 0, 0, 16, 3, 2, 50,
+255,253, 1, 64,255,255, 0, 16,254,135, 5,104, 5,213, 16, 35, 2,107, 4,183, 0, 0, 18, 2, 0, 36, 0, 0,255,255, 0,123,
+254,135, 4, 45, 4,123, 16, 35, 2,107, 4, 33, 0, 0, 18, 2, 0, 68, 0, 0,255,255, 0, 16, 0, 0, 5,104, 7,240, 18, 38,
+ 0, 36, 0, 0, 16, 7, 2, 81, 4,188, 1,117,255,255, 0,123,255,227, 4, 45, 6,123, 18, 38, 0, 68, 0, 0, 16, 7, 2, 81,
+ 4, 84, 0, 0,255,255, 0, 16, 0, 0, 5,104, 5,213, 18, 34, 0, 36, 0, 0, 16, 6, 6,155, 0, 0, 0, 0,255,255, 0,123,
+255,227, 4, 45, 4,123, 16, 39, 6,155,255,151,254,139, 16, 6, 0, 68, 0, 0,255,255, 0, 16, 0, 0, 5,104, 5,213, 18, 34,
+ 0, 36, 0, 0, 16, 6, 6,156, 0, 0, 0, 0,255,255, 0,123,255,227, 4, 45, 4,123, 16, 38, 0, 68, 0, 0, 16, 7, 6,156,
+255,148,254,140,255,255, 0, 16, 0, 0, 5,104, 5,213, 18, 34, 0, 36, 0, 0, 16, 6, 6,162, 0, 0, 0, 0,255,255, 0,123,
+255,227, 4, 45, 4,123, 16, 39, 6,162,255,150,254,139, 16, 6, 0, 68, 0, 0,255,255, 0, 16, 0, 0, 5,104, 5,213, 18, 34,
+ 0, 36, 0, 0, 16, 6, 6,157, 0, 0, 0, 0,255,255, 0,123,255,227, 4, 45, 4,123, 16, 39, 6,157,255,150,254,139, 16, 6,
+ 0, 68, 0, 0,255,255, 0, 16,254,135, 5,104, 5,213, 16, 35, 2,107, 4,175, 0, 0, 18, 2, 0,132, 0, 0,255,255, 0,123,
+254,135, 4, 45, 6,102, 18, 34, 0,164, 0, 0, 16, 3, 2,107, 4, 34, 0, 0,255,255, 0, 16, 0, 0, 5,104, 5,213, 18, 34,
+ 0, 36, 0, 0, 16, 6, 6,159, 0, 0, 0, 0,255,255, 0,123,255,227, 4, 45, 4,123, 16, 39, 6,159,255,145,254,170, 16, 6,
+ 0, 68, 0, 0,255,255, 0, 16, 0, 0, 5,104, 5,213, 18, 34, 0, 36, 0, 0, 16, 6, 6,160, 0, 0, 0, 0,255,255, 0,123,
+255,227, 4, 45, 4,123, 16, 39, 6,160,255,146,254,170, 16, 6, 0, 68, 0, 0,255,255, 0, 16, 0, 0, 5,104, 5,213, 18, 34,
+ 0, 36, 0, 0, 16, 6, 6,161, 0, 0, 0, 0,255,255, 0,123,255,227, 4, 45, 4,123, 16, 39, 6,161,255,148,254,170, 16, 6,
+ 0, 68, 0, 0,255,255, 0, 16, 0, 0, 5,104, 5,213, 18, 34, 0, 36, 0, 0, 16, 6, 6,158, 0, 0, 0, 0,255,255, 0,123,
+255,227, 4, 45, 4,123, 16, 38, 0, 68, 0, 0, 16, 7, 6,158,255,146,254,170,255,255, 0, 16,254,135, 5,104, 7,146, 18, 34,
+ 0,196, 0, 0, 16, 3, 2,107, 4,192, 0, 0,255,255, 0,123,254,135, 4, 45, 6, 31, 18, 34, 0,197, 0, 0, 16, 3, 2,107,
+ 4, 51, 0, 0,255,255, 0,201,254,135, 4,139, 5,213, 16, 38, 0, 40, 0, 0, 16, 7, 2,107, 4,158, 0, 0,255,255, 0,113,
+254,135, 4,127, 4,123, 16, 38, 0, 72, 0, 0, 16, 7, 2,107, 4,139, 0, 0,255,255, 0,201, 0, 0, 4,139, 7,240, 18, 38,
+ 0, 40, 0, 0, 16, 7, 2, 81, 4,158, 1,117,255,255, 0,113,255,227, 4,127, 6,123, 18, 38, 0, 72, 0, 0, 16, 7, 2, 81,
+ 4,141, 0, 0,255,255, 0,201, 0, 0, 4,139, 7, 69, 16, 99, 2, 53, 0,185, 2, 76, 64, 0, 51, 51, 18, 2, 0, 40, 0, 0,
+255,255, 0,113,255,227, 4,127, 6, 55, 16, 35, 2, 53, 0,151, 0, 0, 18, 2, 0, 72, 0, 0,255,255, 0,201, 0, 0, 4,139,
+ 5,213, 18, 34, 0, 40, 0, 0, 16, 6, 6,155, 0, 0, 0, 0,255,255, 0,113,255,227, 4,127, 4,123, 16, 39, 6,155,255,208,
+254,139, 16, 6, 0, 72, 0, 0,255,255, 0,201, 0, 0, 4,139, 5,213, 18, 34, 0, 40, 0, 0, 16, 6, 6,156,238, 0, 0, 0,
+255,255, 0,113,255,227, 4,127, 4,123, 16, 39, 6,156,255,208,254,140, 16, 6, 0, 72, 0, 0,255,255, 0,201, 0, 0, 4,139,
+ 5,213, 18, 34, 0, 40, 0, 0, 16, 6, 6,162,238, 0, 0, 0,255,255, 0,113,255,227, 4,127, 4,123, 16, 38, 0, 72, 0, 0,
+ 16, 7, 6,162,255,208,254,139,255,255, 0,201, 0, 0, 4,139, 5,213, 18, 34, 0, 40, 0, 0, 16, 6, 6,157,234, 0, 0, 0,
+255,255, 0,113,255,227, 4,127, 4,123, 16, 39, 6,157,255,209,254,139, 16, 6, 0, 72, 0, 0,255,255, 0,201,254,135, 4,139,
+ 5,213, 18, 34, 0,140, 0, 0, 16, 7, 2,107, 4,158, 0, 0,255,255, 0,113,254,135, 4,127, 6,102, 16, 39, 2,107, 4,139,
+ 0, 0, 16, 38, 5, 49, 0, 0, 16, 7, 2, 31, 0,139, 0, 0,255,255, 0, 90, 0, 0, 2, 26, 7,240, 18, 38, 0, 44, 0, 0,
+ 16, 7, 2, 81, 3, 35, 1,117,255,255, 0, 68, 0, 0, 2, 4, 6,124, 18, 34, 0,243, 0, 0, 16, 7, 2, 81, 3, 13, 0, 1,
+255,255, 0,200,254,135, 1,148, 5,213, 16, 38, 0, 44, 0, 0, 16, 7, 2,107, 3, 46, 0, 0,255,255, 0,183,254,135, 1,131,
+ 6, 20, 16, 38, 0, 76, 0, 0, 16, 7, 2,107, 3, 29, 0, 0,255,255, 0,115,254,135, 5,217, 5,240, 16, 38, 0, 50, 0, 0,
+ 16, 7, 2,107, 5, 39, 0, 0,255,255, 0,113,254,135, 4,117, 4,123, 16, 38, 0, 82, 0, 0, 16, 7, 2,107, 4,115, 0, 0,
+255,255, 0,115,255,227, 5,217, 7,240, 18, 38, 0, 50, 0, 0, 16, 7, 2, 81, 5, 39, 1,117,255,255, 0,113,255,227, 4,117,
+ 6,123, 18, 38, 0, 82, 0, 0, 16, 7, 2, 81, 4,125, 0, 0,255,255, 0,115,255,227, 5,217, 5,240, 18, 34, 0, 50, 0, 0,
+ 16, 6, 6,155,108, 0, 0, 0,255,255, 0,113,255,227, 4,117, 4,123, 16, 39, 6,155,255,182,254,139, 16, 6, 0, 82, 0, 0,
+255,255, 0,115,255,227, 5,217, 5,240, 18, 34, 0, 50, 0, 0, 16, 6, 6,156,106, 0, 0, 0,255,255, 0,113,255,227, 4,117,
+ 4,123, 16, 39, 6,156,255,181,254,140, 16, 6, 0, 82, 0, 0,255,255, 0,115,255,227, 5,217, 5,240, 18, 34, 0, 50, 0, 0,
+ 16, 6, 6,162,106, 0, 0, 0,255,255, 0,113,255,227, 4,117, 4,123, 16, 39, 6,162,255,182,254,139, 16, 6, 0, 82, 0, 0,
+255,255, 0,115,255,227, 5,217, 5,240, 18, 34, 0, 50, 0, 0, 16, 6, 6,157,101, 0, 0, 0,255,255, 0,113,255,227, 4,117,
+ 4,123, 16, 39, 6,157,255,182,254,139, 16, 6, 0, 82, 0, 0,255,255, 0,115,254,135, 5,217, 5,240, 18, 34, 0,150, 0, 0,
+ 16, 7, 2,107, 5, 39, 0, 0,255,255, 0,113,254,135, 4,117, 6,102, 16, 39, 2,107, 4,115, 0, 0, 16, 38, 5, 69, 0, 0,
+ 16, 6, 2, 31,115, 0, 0, 0,255,255, 0,103,255,227, 6,195, 5,240, 16, 39, 6,133, 5, 39, 1,117, 18, 2, 1, 98, 0, 0,
+255,255, 0,118,255,227, 4,211, 6,102, 16, 38, 0,118,115, 0, 18, 2, 1, 99, 0, 0, 0, 0,255,255, 0,103,255,227, 6,195,
+ 5,240, 16, 39, 6,135, 5, 39, 1,117, 18, 2, 1, 98, 0, 0,255,255, 0,118,255,227, 4,211, 6,102, 16, 38, 0, 67,115, 0,
+ 18, 2, 1, 99, 0, 0, 0, 0,255,255, 0,103,255,227, 6,195, 7,240, 18, 34, 1, 98, 0, 0, 16, 7, 2, 81, 5, 39, 1,117,
+255,255, 0,118,255,227, 4,211, 6,123, 18, 38, 1, 99, 0, 0, 16, 7, 2, 81, 4,125, 0, 0,255,255, 0,103,255,227, 6,195,
+ 5,240, 16, 39, 6,134, 5, 39, 1,117, 18, 2, 1, 98, 0, 0,255,255, 0,118,255,227, 4,211, 6, 55, 16, 38, 2, 53,115, 0,
+ 18, 2, 1, 99, 0, 0, 0, 0,255,255, 0,103,254,135, 6,195, 5,240, 18, 34, 1, 98, 0, 0, 16, 7, 2,107, 5, 39, 0, 0,
+255,255, 0,118,254,135, 4,211, 4,235, 18, 34, 1, 99, 0, 0, 16, 7, 2,107, 4,115, 0, 0,255,255, 0,178,254,135, 5, 41,
+ 5,213, 16, 38, 0, 56, 0, 0, 16, 7, 2,107, 4,245, 0, 0,255,255, 0,174,254,135, 4, 88, 4, 96, 16, 38, 0, 88, 0, 0,
+ 16, 7, 2,107, 4,123, 0, 0,255,255, 0,178,255,227, 5, 41, 7,240, 18, 38, 0, 56, 0, 0, 16, 7, 2, 81, 4,238, 1,117,
+255,255, 0,174,255,227, 4, 88, 6,123, 18, 38, 0, 88, 0, 0, 16, 7, 2, 81, 4,125, 0, 0,255,255, 0,173,255,247, 6, 95,
+ 5,233, 16, 39, 6,133, 4,238, 1,117, 18, 2, 1,113, 0, 0,255,255, 0,176,255,227, 5,105, 6,102, 16, 38, 0,118,123, 0,
+ 18, 2, 1,114, 0, 0, 0, 0,255,255, 0,173,255,247, 6, 95, 5,233, 16, 39, 6,135, 4,238, 1,117, 18, 2, 1,113, 0, 0,
+255,255, 0,176,255,227, 5,105, 6,102, 16, 38, 0, 67,123, 0, 18, 2, 1,114, 0, 0, 0, 0,255,255, 0,173,255,247, 6, 95,
+ 7,240, 18, 34, 1,113, 0, 0, 16, 7, 2, 81, 4,238, 1,117,255,255, 0,176,255,227, 5,105, 6,123, 18, 34, 1,114, 0, 0,
+ 16, 7, 2, 81, 4,125, 0, 0,255,255, 0,173,255,247, 6, 95, 5,233, 16, 39, 6,134, 4,238, 1,117, 18, 2, 1,113, 0, 0,
+255,255, 0,176,255,227, 5,105, 6, 55, 16, 35, 2, 53, 0,128, 0, 0, 18, 2, 1,114, 0, 0,255,255, 0,173,254,135, 6, 95,
+ 5,233, 18, 34, 1,113, 0, 0, 16, 7, 2,107, 4,245, 0, 0,255,255, 0,176,254,135, 5,105, 4,235, 18, 34, 1,114, 0, 0,
+ 16, 7, 2,107, 4,123, 0, 0,255,255,255,252, 0, 0, 4,231, 5,213, 18, 38, 0, 60, 0, 0, 16, 7, 6,135, 4,114, 1,124,
+255,255, 0, 61,254, 86, 4,127, 6,107, 18, 38, 0, 92, 0, 0, 16, 6, 0, 67, 33, 5, 0, 0,255,255,255,252,254,130, 4,231,
+ 5,213, 16, 35, 2,107, 4,118,255,251, 18, 2, 0, 60, 0, 0,255,255, 0, 61,254, 86, 4,127, 4, 96, 16, 35, 2,107, 5,116,
+ 0, 0, 18, 2, 0, 92, 0, 0,255,255,255,252, 0, 0, 4,231, 7,247, 18, 38, 0, 60, 0, 0, 16, 7, 2, 81, 4,114, 1,124,
+255,255, 0, 61,254, 86, 4,127, 6,130, 18, 38, 0, 92, 0, 0, 16, 7, 2, 81, 4, 96, 0, 7,255,255,255,252, 0, 0, 4,231,
+ 7, 69, 16, 99, 2, 53, 0,121, 2, 76, 64, 0, 51, 51, 18, 2, 0, 60, 0, 0,255,255, 0, 61,254, 86, 4,127, 6, 55, 16, 34,
+ 2, 53,119, 0, 18, 2, 0, 92, 0, 0, 0, 0, 0, 1, 1,134, 4,194, 2,120, 6, 97, 0, 8, 0, 72,180, 5, 8, 7, 2, 9,
+ 16,212, 60,220,178, 63, 8, 1, 93,192, 49,182, 0, 6, 7, 6, 3, 2, 9, 0, 16,212,180, 63, 2, 95, 2, 2, 93,176, 17, 75,
+ 80, 88,204, 27,192, 89,204,204,178, 63, 7, 1, 93, 17, 57, 48,177, 6, 3, 73,177, 7, 6, 73, 80, 88,179, 5, 64, 6, 64, 56,
+ 56, 89, 1, 16, 35, 53, 22, 53, 35, 53, 51, 2,120,242,134,133,241, 5,205,254,245,103, 3,157,158, 0, 0, 0,255,255, 1,115,
+ 4,238, 3, 82, 6,102, 16, 6, 0,118, 0, 0, 0, 1, 1,134, 4,194, 2,120, 6, 97, 0, 8, 0, 72,180, 2, 7, 4, 0, 9,
+ 16,212,192,220,178, 63, 7, 1, 93, 60, 49,182, 0, 3, 2, 3, 6, 7, 9, 0, 16,212,180, 63, 7, 95, 7, 2, 93,176, 17, 75,
+ 80, 88,204, 27,192, 89,204,204,178, 63, 2, 1, 93, 17, 57, 48,177, 3, 6, 73,177, 2, 3, 73, 80, 88,179, 3, 64, 4, 64, 56,
+ 56, 89, 1, 53, 51, 21, 35, 20, 55, 21, 34, 1,134,242,134,134,242, 5,205,148,158,157, 3,103, 0, 1, 0,100, 1,223, 2,127,
+ 2,131, 0, 3, 0, 17,182, 0,156, 2, 4, 1, 0, 4, 16,220,204, 49, 0, 16,212,236, 48, 19, 33, 21, 33,100, 2, 27,253,229,
+ 2,131,164, 0,255,255, 0,100, 1,223, 2,127, 2,131, 18, 6, 5,133, 0, 0, 0, 1, 0, 0, 1,233, 4, 0, 2,121, 0, 3,
+ 0, 16,182, 2,169, 0,233, 4, 1, 0, 47,198, 49, 0, 16,252,236, 48, 17, 33, 21, 33, 4, 0,252, 0, 2,121,144, 0, 0, 0,
+ 0, 1, 0, 0, 1,233, 4, 0, 2,121, 0, 3, 0, 16,182, 2,169, 0,233, 4, 1, 0, 47,198, 49, 0, 16,252,236, 48, 17, 33,
+ 21, 33, 4, 0,252, 0, 2,121,144, 0, 0, 0, 0, 1, 0, 0, 1,233, 8, 0, 2,121, 0, 3, 0, 15,181, 2,169, 0, 4, 1,
+ 0, 47,204, 49, 0, 16,212,236, 48, 17, 33, 21, 33, 8, 0,248, 0, 2,121,144, 0, 1, 0, 0, 1,233, 8, 0, 2,121, 0, 3,
+ 0, 15,181, 2,169, 0, 4, 1, 0, 47,204, 49, 0, 16,212,236, 48, 17, 33, 21, 33, 8, 0,248, 0, 2,121,144,255,255, 1, 4,
+254, 29, 2,248, 6, 29, 16, 34, 0, 95, 0, 0, 16, 3, 0, 95, 1, 74, 0, 0,255,255,255,236,254, 29, 4, 20,255,238, 16, 38,
+ 0, 66, 0, 0, 16, 7, 0, 66, 0, 0, 1, 66, 0, 1, 0,174, 3,233, 1,211, 5,213, 0, 5, 0, 24, 64, 11, 0,158, 3,129,
+ 6, 3, 4, 0, 25, 1, 6, 16,220,252,212,204, 49, 0, 16,244,236, 48, 1, 35, 53, 19, 51, 3, 1,129,211,164,129, 82, 3,233,
+173, 1, 63,254,193, 0, 0, 0, 0, 1, 0,178, 3,254, 1,215, 5,213, 0, 5, 0, 24, 64, 11, 3,158, 0,129, 6, 3, 4, 1,
+ 25, 0, 6, 16,220,236,212,204, 49, 0, 16,244,236, 48, 1, 51, 21, 3, 35, 19, 1, 4,211,164,129, 82, 5,213,152,254,193, 1,
+ 63, 0, 0, 0, 0, 1, 0,174,255, 18, 1,211, 0,254, 0, 5, 0, 24, 64, 11, 3,158, 0,131, 6, 3, 4, 1, 25, 0, 6, 16,
+212,236,212,204, 49, 0, 16,252,236, 48, 37, 51, 21, 3, 35, 19, 1, 0,211,164,129, 82,254,172,254,192, 1, 64, 0, 1, 0,178,
+ 3,254, 1,215, 5,213, 0, 5, 0, 0, 1, 21, 19, 35, 3, 53, 1,133, 82,129,164, 5,213,152,254,193, 1, 63,152, 0, 0, 0,
+ 0, 2, 0,174, 3,233, 3,109, 5,213, 0, 5, 0, 11, 0, 39, 64, 19, 6, 0,158, 9, 3,129, 12, 9, 10, 6, 25, 7, 3, 4,
+ 7, 0, 25, 1, 12, 16,220,252,204,212,204, 16,254,212,206, 49, 0, 16,244, 60,236, 50, 48, 1, 35, 53, 19, 51, 3, 5, 35, 53,
+ 19, 51, 3, 1,129,211,164,129, 82, 1,154,211,164,129, 82, 3,233,173, 1, 63,254,193,173,173, 1, 63,254,193, 0, 2, 0,174,
+ 3,233, 3,109, 5,213, 0, 5, 0, 11, 0, 39, 64, 19, 9, 3,158, 6, 0,129, 12, 9, 10, 7, 25, 6, 1, 3, 4, 1, 25, 0,
+ 12, 16,220,236,212,204, 16,220,238,212,206, 49, 0, 16,244, 60,236, 50, 48, 1, 51, 21, 3, 35, 19, 37, 51, 21, 3, 35, 19, 1,
+ 0,211,164,129, 82, 1,154,211,164,129, 82, 5,213,172,254,192, 1, 64,172,172,254,192, 1, 64, 0, 2, 0,174,255, 18, 3,109,
+ 0,254, 0, 5, 0, 11, 0, 39, 64, 19, 9, 3,158, 6, 0,131, 12, 3, 4, 1, 25, 0, 7, 9, 10, 7, 25, 6, 12, 16,220,236,
+212,204, 16,220,238,212,206, 49, 0, 16,252, 60,236, 50, 48, 37, 51, 21, 3, 35, 19, 37, 51, 21, 3, 35, 19, 2,154,211,164,129,
+ 82,254,102,211,164,129, 82,254,172,254,192, 1, 64,172,172,254,192, 1, 64, 0, 0, 2, 0,174, 3,233, 3,109, 5,213, 0, 5,
+ 0, 11, 0, 0, 1, 21, 19, 35, 3, 53, 33, 21, 19, 35, 3, 53, 1,129, 82,129,164, 2,109, 82,129,164, 5,213,173,254,193, 1,
+ 63,173,173,254,193, 1, 63,173, 0, 1, 0, 57,255, 59, 3,199, 5,213, 0, 11, 0, 39, 64, 20, 8, 4,185, 10, 2, 0,129, 6,
+194, 12, 3, 89, 5, 1, 87, 9, 89, 7, 0, 12, 16,212, 60,236,252, 60,236, 49, 0, 16,228,244,212, 60,236, 50, 48, 1, 51, 17,
+ 33, 21, 33, 17, 35, 17, 33, 53, 33, 1,168,176, 1,111,254,145,176,254,145, 1,111, 5,213,254, 92,153,251,163, 4, 93,153, 0,
+ 0, 1, 0, 57,255, 59, 3,199, 5,213, 0, 19, 0, 62, 64, 32, 18, 6,185, 0, 16, 8,185, 10, 4, 0, 2, 14, 10, 12,129, 2,
+194, 20, 15, 0, 89, 17, 13, 1, 87, 9, 5, 89, 11, 7, 3, 20, 16,212, 60, 60,236, 50,252, 60, 60,236, 50, 49, 0, 16,228,244,
+196, 50, 16,196, 50, 16,238, 50, 16,238, 50, 48, 37, 33, 17, 35, 17, 33, 53, 33, 17, 33, 53, 33, 17, 51, 17, 33, 21, 33, 17, 33,
+ 3,199,254,145,176,254,145, 1,111,254,145, 1,111,176, 1,111,254,145, 1,111,223,254, 92, 1,164,154, 2, 31,153, 1,164,254,
+ 92,153,253,225, 0, 1, 1, 51, 1,209, 3,133, 4, 33, 0, 11, 0, 18,183, 9,199, 3, 12, 6, 92, 0, 12, 16,212,236, 49, 0,
+ 16,212,236, 48, 1, 52, 54, 51, 50, 22, 21, 20, 6, 35, 34, 38, 1, 51,173,126,124,171,172,125,125,172, 2,250,124,171,171,124,
+125,172,172, 0, 0, 1, 1, 51, 1,129, 3,213, 4,113, 0, 2, 0, 0, 1, 17, 1, 1, 51, 2,162, 1,129, 2,240,254,136, 0,
+ 0, 1, 0,236, 0, 0, 1,193, 0,254, 0, 3, 0, 0, 55, 51, 21, 35,236,213,213,254,254, 0, 0, 2, 0,236, 0, 0, 4,107,
+ 0,254, 0, 3, 0, 7, 0, 0, 37, 51, 21, 35, 37, 51, 21, 35, 3,150,213,213,253, 86,213,213,254,254,254,254, 0, 3, 0,236,
+ 0, 0, 7, 20, 0,254, 0, 3, 0, 7, 0, 11, 0, 35, 64, 17, 8, 4, 0,131, 10, 6, 2, 4, 25, 5, 0, 25, 1, 9, 25, 8,
+ 12, 16,212,252,212,236,212,236, 49, 0, 47, 60, 60,236, 50, 50, 48, 37, 51, 21, 35, 37, 51, 21, 35, 37, 51, 21, 35, 3,150,212,
+212, 2,169,213,213,250,173,213,213,254,254,254,254,254,254, 0, 0, 1, 0,220, 2,107, 1,175, 3,105, 0, 3, 0, 0, 19, 51,
+ 21, 35,220,211,211, 3,105,254, 0, 7, 0,113,255,227, 10, 76, 5,240, 0, 11, 0, 23, 0, 35, 0, 39, 0, 51, 0, 63, 0, 75,
+ 0,174, 64, 68, 36, 15, 37, 38, 37, 38, 15, 39, 36, 39, 66, 64, 0,146, 12, 46,146, 30,141, 40,146, 24, 70, 6,146, 52, 12,141,
+ 58, 38, 18,140, 36, 24,145, 76, 37, 73, 67, 39, 49, 43, 67, 13, 61, 9, 13, 15, 14, 3, 13, 21, 49, 13, 27, 61, 14, 73, 13, 21,
+ 55, 43, 13, 27, 14, 33, 11, 76, 16,252,228,236,212,196,236,228, 16,238, 16,238,246,238, 16,238, 17, 18, 57, 17, 18, 57, 49, 0,
+ 16,228, 50,244, 60, 60,228, 50,236, 50, 16,238,246,238, 16,238, 50, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 5,237, 89, 34, 1,
+ 75,176, 20, 84, 75,176, 9, 84, 91, 75,176, 11, 84, 91, 75,176, 12, 84, 91, 75,176, 13, 84, 91, 75,176, 14, 84, 91, 88,189, 0,
+ 76, 0, 64, 0, 1, 0, 76, 0, 76,255,192, 56, 17, 55, 56, 89, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 39, 50, 22, 21,
+ 20, 6, 35, 34, 38, 53, 52, 54, 1, 50, 22, 21, 20, 6, 35, 34, 38, 53, 52, 54, 33, 51, 1, 35, 19, 34, 6, 21, 20, 22, 51, 50,
+ 54, 53, 52, 38, 1, 50, 22, 21, 20, 6, 35, 34, 38, 53, 52, 54, 23, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 8,244, 87,100,
+100, 87, 85, 99, 99, 85,158,186,187,157,160,186,187,249,116,158,188,187,159,159,185,186, 4, 37,160,252, 90,160, 31, 86, 99, 98,
+ 87, 87, 99,100, 3,178,158,186,187,157,160,186,187,159, 87, 99, 99, 87, 85, 99, 99, 2,145,148,132,130,149,149,130,131,149,127,
+220,187,187,219,219,187,188,219, 2,224,219,187,189,218,219,188,186,220,249,243, 5,142,149,130,132,148,148,132,129,150,253,159,
+220,187,187,219,219,187,188,219,127,148,132,130,149,149,130,131,149, 0, 0, 0, 0, 9, 0,113,255,227, 13,114, 5,240, 0, 11,
+ 0, 22, 0, 34, 0, 45, 0, 55, 0, 59, 0, 69, 0, 80, 0, 92, 0, 0, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 39, 50,
+ 22, 16, 6, 35, 34, 38, 53, 52, 54, 5, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 39, 50, 22, 16, 6, 35, 34, 38, 53, 52, 54,
+ 0, 32, 22, 21, 20, 6, 32, 38, 53, 52, 37, 51, 1, 35, 18, 34, 6, 21, 20, 22, 50, 54, 53, 52, 1, 50, 22, 16, 6, 35, 34, 38,
+ 53, 52, 54, 23, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 12, 26, 87,100,100, 87, 85, 99, 99, 85,158,186,187,157,160,186,187,
+253,121, 87,100,100, 87, 85, 99, 99, 85,158,186,187,157,160,186,187,248,214, 1, 60,188,187,254,194,185, 4,223,160,252, 90,160,
+117,172, 99, 98,174, 99, 3, 78,158,186,187,157,160,186,187,159, 87, 99, 99, 87, 85, 99, 99, 2,145,148,132,130,149,149,130,131,
+149,127,220,254,138,219,219,187,188,219,127,148,132,130,149,149,130,131,149,127,220,254,138,219,219,187,188,219, 2,224,219,187,
+189,218,219,188,186,220,249,243, 5,142,149,130,132,148,148,132,129,254, 53,220,254,138,219,219,187,188,219,127,148,132,130,149,
+149,130,131,149, 0, 1, 0, 40, 4, 96, 1,160, 5,213, 0, 3, 0, 0, 27, 1, 51, 1, 40,173,203,254,223, 4, 96, 1,117,254,
+139, 0, 0, 0,255,255, 0, 40, 4, 96, 2,204, 5,213, 16, 38, 5,159, 0, 0, 16, 7, 5,159, 1, 44, 0, 0,255,255, 0, 40,
+ 4, 96, 3,248, 5,213, 16, 39, 5,159, 1, 44, 0, 0, 16, 38, 5,159, 0, 0, 16, 7, 5,159, 2, 88, 0, 0, 0, 1, 0, 40,
+ 4, 96, 1,160, 5,213, 0, 3, 0, 0, 1, 35, 1, 51, 1,160, 87,254,223,203, 4, 96, 1,117,255,255, 0, 40, 4, 96, 2,204,
+ 5,213, 16, 38, 5,162, 0, 0, 16, 7, 5,162, 1, 44, 0, 0,255,255, 0, 40, 4, 96, 3,248, 5,213, 16, 38, 5,162, 0, 0,
+ 16, 39, 5,162, 2, 88, 0, 0, 16, 7, 5,162, 1, 44, 0, 0, 0, 1, 0, 11,254, 29, 2,171,255,195, 0, 5, 0, 0, 1, 35,
+ 39, 7, 35, 1, 2,171,148,187,188,149, 1, 82,254, 29,249,249, 1,166, 0, 0, 0, 1, 0,158, 0,141, 2,115, 4, 35, 0, 6,
+ 0, 71, 64, 37, 3,232, 4, 5, 4, 2,232, 1, 2, 5, 5, 4, 2,232, 3, 2, 6, 0, 6, 1,232, 0, 6, 66, 2, 4,231, 0,
+166, 7, 2, 3, 0,111, 5,110, 7, 16,252,236, 50, 57, 49, 0, 16,244,236, 57, 48, 75, 83, 88, 7, 4,237, 7, 16, 8,237, 7,
+ 16, 8,237, 7, 16, 4,237, 89, 34, 1, 21, 9, 1, 21, 1, 53, 2,115,254,211, 1, 45,254, 43, 4, 35,191,254,244,254,244,191,
+ 1,162, 82, 0, 0, 1, 0,193, 0,141, 2,150, 4, 35, 0, 6, 0, 73, 64, 38, 5,232, 6, 5, 2, 3, 2, 4,232, 3, 3, 2,
+ 6,232, 0, 1, 0, 5,232, 4, 5, 1, 1, 0, 66, 5, 3,231, 0,166, 7, 5, 1,111, 3, 0,112, 7, 16,252, 60,236, 57, 49,
+ 0, 16,244,236, 57, 48, 75, 83, 88, 7, 16, 8,237, 7, 16, 4,237, 7, 16, 4,237, 7, 16, 8,237, 89, 34, 19, 1, 21, 1, 53,
+ 9, 1,193, 1,213,254, 43, 1, 45,254,211, 4, 35,254, 94, 82,254, 94,191, 1, 12, 1, 12, 0,255,255, 0,195, 0, 4, 5,235,
+ 5,204, 18, 34, 0,153, 0, 75, 16, 35, 0, 17,255,232, 2, 78, 16, 35, 0, 17, 2, 22, 0, 4, 16, 35, 0, 17, 4, 61, 2, 78,
+ 16, 3, 0, 17, 2, 22, 4,206,255,255, 0,147, 0, 0, 3, 79, 5,213, 16, 39, 0, 4,255, 94, 0, 0, 16, 7, 0, 4, 1, 79,
+ 0, 0, 0, 0, 0, 3, 0,147, 0, 0, 3,176, 5,240, 0, 23, 0, 27, 0, 36, 0, 0, 1, 35, 17, 6, 7, 6, 7, 53, 62, 1,
+ 51, 50, 22, 21, 20, 6, 15, 1, 14, 1, 7, 14, 1, 21, 3, 51, 21, 35, 19, 17, 55, 62, 1, 53, 52, 39, 38, 2, 76,191, 31, 32,
+ 90, 97, 94,193,103,184,223, 72, 90, 88, 47, 39, 8, 6, 6,197,203,203,197, 45, 57, 51, 65, 37, 1,145, 3,173, 8, 13, 35, 67,
+188, 57, 56,194,159, 76,137, 86, 86, 47, 53, 25, 21, 60, 52,254,242,254, 5, 66,254, 82, 45, 53, 94, 49, 89, 55, 31, 0, 0, 0,
+255,255,255,236, 5,124, 4, 20, 6, 11, 16, 7, 0, 66, 0, 0, 7, 95, 0, 0, 0, 1,255,167,254, 27, 6,199,255,133, 0, 13,
+ 0, 37,179, 4, 15, 10, 14, 16,196,212,196,179, 7, 0, 15, 14, 17, 18, 57, 57, 49, 64, 7, 11, 3, 10, 4, 7, 0, 14, 0, 16,
+212,220,220, 60,204, 50, 48, 1, 50, 36, 55, 21, 6, 4, 35, 34, 36, 39, 53, 22, 4, 3, 54,231, 1,197,229,235,254, 58,224,223,
+254, 60,236,230, 1,194,254,181,104,104,126,118,118,117,119,126,105,103, 0, 0, 0, 1,255,167, 6, 4, 6,199, 7,110, 0, 13,
+ 0, 37,179, 4, 15, 10, 14, 16,196,212,196,179, 7, 0, 15, 14, 17, 18, 57, 57, 49, 64, 7, 10, 4, 11, 3, 0, 7, 14, 0, 16,
+212,220,220, 60,204, 50, 48, 1, 50, 4, 23, 21, 38, 36, 35, 34, 4, 7, 53, 54, 36, 3, 54,224, 1,198,235,229,254, 59,231,231,
+254, 62,230,236, 1,196, 7,110,118,118,126,104,104,103,105,126,119,117, 0, 0, 0, 1,255,170,254, 29, 2, 73, 1,213, 0, 7,
+ 0, 0, 1, 51, 9, 1, 35, 11, 1, 35, 1,231, 98,254,226, 1, 30, 98,237,237, 99, 1,213,254, 36,254, 36, 1,138,254,118, 0,
+255,255, 0, 61,255,197, 7,195, 6,131, 16, 35, 0, 13, 0, 0,253,123, 16, 35, 0, 13, 4, 0,253,123, 16, 3, 0, 13, 2, 0,
+ 0,147, 0, 0,255,255, 0,221, 2,129, 3, 51, 3, 95, 18, 67, 2, 34, 0, 8,250,110, 64, 0, 96, 0, 0, 0, 0, 1,254,137,
+255,227, 2,205, 5,240, 0, 3, 0, 43, 64, 19, 0, 15, 1, 2, 1, 2, 15, 3, 0, 3, 66, 2,140, 0,145, 4, 1, 3, 4, 16,
+212,204, 49, 0, 16,228,228, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 5,237, 89, 34, 1, 51, 1, 35, 2, 45,160,252, 92,160, 5,
+240,249,243, 0, 0, 1, 0,176,254,242, 2, 88, 6, 20, 0, 11, 0, 0, 1, 17, 51, 21, 33, 17, 33, 21, 35, 17, 51, 21, 1,104,
+240,254, 88, 1,168,240,240, 2, 94,253, 35,143, 7, 34,143,253, 35, 74, 0, 0, 0, 1, 0,176,254,242, 2, 88, 6, 20, 0, 11,
+ 0, 0, 19, 53, 51, 17, 35, 53, 33, 17, 33, 53, 51, 17,176,240,240, 1,168,254, 88,240, 2, 94, 74, 2,221,143,248,222,143, 2,
+221, 0, 0, 0,255,255, 0, 73, 0, 0, 7, 23, 5,240, 16, 38, 0, 34,182, 0, 16, 7, 0, 34, 3,102, 0, 0,255,255, 0,147,
+ 0, 0, 5, 74, 5,240, 16, 38, 0, 34, 0, 0, 16, 7, 0, 4, 3, 74, 0, 0,255,255, 0,147, 0, 0, 5, 74, 5,240, 16, 39,
+ 0, 4,255, 94, 0, 0, 16, 7, 0, 34, 1,154, 0, 0, 0, 0, 0, 1, 0,111, 0, 0, 3,161, 4,132, 0, 19, 0, 0, 37, 51,
+ 21, 35, 53, 7, 35, 19, 35, 53, 33, 19, 33, 53, 33, 21, 3, 51, 21, 35, 1,254,169,209, 3,180,224,249, 1, 36,168,253,157, 3,
+ 50,195,165,208,102,102, 7, 7, 2, 15,102, 1,139,132, 67,254, 52,102, 0, 0, 0, 1, 0,236,255, 59, 4,135, 5,213, 0, 13,
+ 0, 0, 1, 33, 17, 51, 17, 51, 17, 51, 17, 62, 1, 53, 52, 36, 2,172,254, 64,141,190,142,215,235,254,252, 5,213,249,102, 6,
+ 31,249,225, 3, 78, 17,221,184,190,232, 0, 0, 0, 2, 0,216, 1,194, 3, 40, 4, 18, 0, 3, 0, 11, 0, 0, 1, 51, 17, 7,
+ 43, 1, 34, 38, 53, 52, 54, 51, 2,121,175,175,118, 2,125,172,173,126, 4, 18,253,177, 1,172,125,124,171, 0, 0, 2, 0,216,
+ 1,194, 3, 40, 4, 18, 0, 3, 0, 11, 0, 0, 1, 39, 17, 59, 1, 50, 22, 21, 20, 6, 43, 1, 1,135,175,175,118,126,173,172,
+125, 2, 1,194, 1, 2, 79,171,124,125,172, 0,255,255, 0, 61,255,197, 3,195, 3,107, 18, 3, 0, 13, 0, 0,253,123, 0, 0,
+ 0, 2, 1, 29,255, 18, 2, 66, 4, 35, 0, 3, 0, 9, 0, 0, 1, 35, 21, 51, 17, 35, 21, 19, 51, 3, 1,240,211,211,211,164,
+129, 82, 4, 35,254,253,217,172,254,192, 1, 64,255,255,255,167,254, 27, 6,199, 7,110, 16, 38, 5,172, 0, 0, 16, 6, 5,173,
+ 0, 0, 0, 0,255,255, 0, 61,255,242, 3,195, 7,111, 18, 35, 0, 13, 0, 0,253,168, 16, 3, 0, 13, 0, 0, 1,127, 0, 0,
+255,255, 0,145,255, 66, 3, 67, 5,213, 16, 35, 0, 18, 0,145, 0, 0, 16, 35, 0, 17, 1,142, 0, 0, 16, 3, 0, 17,255,217,
+ 4, 72, 0, 0,255,255, 0,217, 1,211, 5,219, 3, 49, 18, 2, 0, 97, 0, 0,255,255,255,167,254, 20, 6,199,255,126, 16, 7,
+ 5,173, 0, 0,248, 16, 0, 0, 0, 1, 1, 56, 0,200, 5,124, 5, 13, 0, 23, 0, 0, 1, 17, 35, 17, 7, 39, 55, 33, 53, 33,
+ 39, 55, 23, 17, 51, 17, 55, 23, 7, 33, 21, 33, 23, 7, 3,170,160,249,113,249,254,159, 1, 97,250,113,250,160,250,113,250, 1,
+ 97,254,159,250,113, 2, 41,254,159, 1, 96,249,114,249,160,250,114,251, 1, 98,254,158,250,113,250,160,249,114, 0, 3, 0,250,
+ 1, 50, 3,182, 4,182, 0, 3, 0, 7, 0, 11, 0, 0, 19, 53, 51, 21, 1, 53, 51, 21, 3, 53, 51, 21,250,200, 1, 44,200,200,
+200, 2,144,200,200,254,162,200,200, 2,188,200,200, 0, 0, 0,255,255, 0, 40, 4, 96, 5, 36, 5,213, 16, 39, 5,159, 1, 44,
+ 0, 0, 16, 38, 5,159, 0, 0, 16, 39, 5,159, 3,132, 0, 0, 16, 7, 5,159, 2, 88, 0, 0, 0, 4, 1,102, 1, 0, 5, 78,
+ 4,232, 0, 3, 0, 7, 0, 11, 0, 15, 0, 0, 1, 53, 51, 21, 33, 53, 51, 21, 1, 53, 51, 21, 3, 53, 51, 21, 1,102,200, 2,
+ 88,200,253,168,200,200,200, 2,144,200,200,200,200,254,112,200,200, 3, 32,200,200, 0, 0, 0, 0, 5, 1,102, 0,246, 5, 78,
+ 4,222, 0, 3, 0, 7, 0, 11, 0, 15, 0, 19, 0, 0, 1, 53, 51, 21, 19, 53, 51, 21, 3, 53, 51, 21, 1, 53, 51, 21, 3, 53,
+ 51, 21, 2,246,200,200,200,200,200,252, 44,200,220,200, 2,134,200,200,254,112,200,200, 3, 32,200,200,252,244,200,200, 3, 12,
+200,200, 0, 0, 0, 2, 0,219, 0, 0, 1,174, 5,213, 0, 3, 0, 7, 0, 0, 19, 51, 21, 35, 17, 51, 21, 35,219,211,211,211,
+211, 5,213,254,252, 39,254, 0, 0, 4, 0,100,254,229, 5,253, 6,239, 0, 3, 0, 7, 0, 11, 0, 15, 0, 0, 19, 51, 21, 35,
+ 37, 51, 21, 35, 1, 51, 21, 35, 17, 51, 21, 35,100,211,211, 4,198,211,211,253,157,211,211,211,211, 3,105,254,254,254, 4,132,
+254,249,242,254, 0, 5, 0,112, 0, 0, 6, 68, 5,213, 0, 3, 0, 7, 0, 11, 0, 15, 0, 27, 0, 0, 37, 53, 51, 21, 3, 53,
+ 51, 21, 1, 53, 51, 21, 3, 53, 51, 21, 1, 17, 35, 17, 33, 53, 33, 17, 51, 17, 33, 21, 4,134,200,200,200,252, 44,200,220,200,
+ 1,124,160,253,102, 2,154,160, 2,154,246,200,200, 3, 32,200,200,252,244,200,200, 3, 12,200,200,254,132,253,102, 2,154,160,
+ 2,155,253,101,160, 0, 0, 0, 0, 3, 0,219, 0, 80, 1,174, 5, 62, 0, 3, 0, 7, 0, 11, 0, 0, 19, 51, 21, 35, 17, 51,
+ 21, 35, 17, 51, 21, 35,219,211,211,211,211,211,211, 5, 62,254,253, 14,254, 2,246,254, 0, 0, 0, 4, 0,219, 0, 17, 1,174,
+ 5,119, 0, 3, 0, 7, 0, 11, 0, 15, 0, 0, 19, 51, 21, 35, 17, 51, 21, 35, 17, 51, 21, 35, 17, 51, 21, 35,219,211,211,211,
+211,211,211,211,211, 2,137,254, 3,236,254,252,150,254, 3,240,254, 0, 0, 0, 0, 2, 0, 87, 2,141, 2,238, 5,240, 0, 13,
+ 0, 25, 0, 0, 0, 34, 7, 6, 21, 20, 23, 22, 50, 55, 54, 53, 52, 47, 1, 50, 22, 21, 20, 6, 35, 34, 38, 53, 52, 54, 2, 8,
+202, 50, 51, 51, 50,202, 50, 51, 51,151,161,170,170,161,162,170,170, 5,151, 86, 86,172,173, 86, 86, 86, 86,173,172, 86,175,222,
+211,212,222,222,212,211,222, 0, 0, 2, 0,121, 2,156, 0,238, 6, 4, 0, 3, 0, 7, 0, 31, 64, 6, 9, 5, 1, 4, 0, 8,
+ 16,220, 60,220, 60,204, 49, 0, 64, 6, 4, 7, 0, 3, 0, 8, 16,212,196, 16,220,204, 48, 19, 51, 17, 35, 17, 51, 21, 35,122,
+116,116,116,116, 5, 15,253,141, 3,103,130, 0, 0, 2, 0, 63, 2,156, 2,244, 5,223, 0, 2, 0, 13, 0,212, 64, 22, 0, 3,
+ 11, 7,221, 5, 1, 9,247, 3,145, 14, 1, 12, 10, 0, 93, 6, 8, 4, 12, 14, 16,220,212, 60,196,236, 50, 17, 57, 49, 0, 16,
+244,252,212, 60,236, 50, 18, 57, 48, 1, 75,176, 14, 84, 75,176, 15, 84, 91, 75,176, 16, 84, 91, 75,176, 17, 84, 91, 75,176, 11,
+ 84, 91, 75,176, 10, 84, 91, 88,189, 0, 14, 0, 64, 0, 1, 0, 14, 0, 14,255,192, 56, 17, 55, 56, 89, 0, 75,176, 17, 84, 75,
+176, 14, 84, 91, 88,189, 0, 14,255,192, 0, 1, 0, 14, 0, 14, 0, 64, 56, 17, 55, 56, 89, 64, 84, 11, 1, 29, 1, 47, 1, 57,
+ 1, 73, 1, 70, 3, 89, 3,105, 3,139, 3,171, 3,187, 3, 11, 1, 0, 15, 1, 15, 2, 15, 5, 15, 6, 15, 7, 15, 8, 15, 11,
+ 15, 12, 15, 13, 19, 0, 31, 1, 31, 2, 31, 5, 31, 6, 31, 7, 31, 8, 31, 11, 31, 12, 31, 13, 34, 0, 53, 0, 71, 0, 75, 13,
+ 83, 0, 91, 13,101, 0,132, 0,165, 0,181, 0, 30, 93, 1, 93, 9, 1, 33, 3, 51, 17, 51, 21, 35, 21, 35, 53, 33, 53, 1,221,
+254,203, 1, 53, 22,166,135,135,144,254, 98, 5,102,254, 93, 2, 28,253,228,109,186,186,121, 0, 0, 1, 0,102, 2,141, 2,211,
+ 5,223, 0, 32, 0, 0, 19, 33, 21, 33, 21, 54, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 35, 34, 38, 39, 53, 22, 23, 22, 51, 50,
+ 54, 52, 38, 35, 34, 6, 7,142, 1,254,254,121, 28, 29, 28, 28,161, 94, 94, 97, 96,176, 60,126, 66, 57, 62, 62, 69,111,130,130,
+111, 52,104, 54, 5,223, 95,204, 9, 4, 4, 77, 76,131,135, 75, 74, 18, 18,113, 27, 14, 13,102,174,102, 20, 21, 0, 2, 0, 92,
+ 2,141, 2,243, 5,240, 0, 15, 0, 47, 0, 0, 1, 34, 7, 6, 21, 20, 23, 22, 51, 50, 55, 54, 53, 52, 39, 38, 19, 21, 38, 39,
+ 38, 35, 34, 7, 6, 7, 54, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 35, 34, 38, 53, 52, 55, 54, 51, 50, 23, 22, 1,179, 88, 51,
+ 51, 51, 51, 88, 87, 51, 51, 51, 51,171, 49, 50, 50, 49,128, 68, 68, 10, 38, 57, 58, 68,145, 84, 84, 88, 87,145,167,176,108,108,
+182, 49, 50, 50, 4,109, 52, 53, 91, 90, 52, 53, 53, 52, 90, 91, 53, 52, 1, 98,103, 20, 10, 11, 75, 76,153, 49, 26, 26, 76, 77,
+132,127, 79, 78,222,212,198,117,118, 8, 9, 0, 0, 1, 0,108, 2,156, 2,213, 5,223, 0, 6, 0, 0, 19, 33, 21, 1, 35, 1,
+ 33,108, 2,105,254,164,136, 1, 72,254, 51, 5,223, 48,252,237, 2,228, 0, 0, 0, 3, 0, 89, 2,141, 2,236, 5,240, 0, 12,
+ 0, 42, 0, 58, 0, 0, 0, 34, 7, 6, 21, 20, 22, 51, 50, 55, 54, 52, 39, 37, 38, 39, 38, 53, 52, 54, 32, 23, 22, 21, 20, 7,
+ 6, 7, 22, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 53, 52, 55, 54, 55, 20, 23, 22, 51, 50, 55, 54, 53, 52, 39, 38, 35, 34, 7,
+ 6, 2, 0,186, 53, 53,106, 93, 92, 54, 53, 53,254,236, 84, 46, 47,164, 1, 30, 82, 81, 46, 47, 83, 90, 56, 53, 85, 86,158,159,
+ 85, 86, 53, 54, 45, 47, 46, 85, 81, 49, 48, 48, 47, 83, 83, 48, 47, 4, 42, 44, 43, 75, 76, 86, 44, 43,150, 43, 93, 18, 49, 50,
+ 72,100,116, 58, 58,100, 74, 48, 49, 18, 18, 58, 55, 80,121, 65, 65, 65, 65,121, 78, 57, 56,198, 63, 38, 37, 37, 36, 65, 63, 38,
+ 37, 37, 36, 0, 0, 2, 0, 83, 2,141, 2,233, 5,240, 0, 31, 0, 46, 0, 0, 19, 53, 22, 23, 22, 51, 50, 55, 54, 55, 6, 7,
+ 6, 35, 34, 38, 53, 52, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 19, 50, 54, 53, 52, 39, 38, 35, 34, 7, 6, 21,
+ 20, 23, 22,145, 49, 50, 50, 48,129, 68, 67, 10, 35, 60, 57, 69,144,168, 87, 88,145,167, 87, 88,107,108,182, 49, 50, 50,204, 88,
+102, 51, 51, 88, 85, 53, 52, 52, 51, 2,174,103, 20, 11, 10, 75, 75,154, 47, 27, 26,152,132,129, 77, 78,111,111,212,198,117,118,
+ 8, 9, 1,114,104, 92, 90, 52, 53, 53, 52, 90, 92, 52, 52, 0, 0, 1, 0,137, 2,156, 3,176, 5,107, 0, 11, 0, 0, 1, 17,
+ 33, 21, 33, 17, 35, 17, 33, 53, 33, 17, 2, 81, 1, 95,254,161,105,254,161, 1, 95, 5,107,254,200, 95,254,200, 1, 56, 95, 1,
+ 56, 0, 0, 0, 0, 1, 0,137, 3,212, 3,176, 4, 51, 0, 3, 0, 0, 19, 33, 21, 33,137, 3, 39,252,217, 4, 51, 95, 0, 0,
+ 0, 2, 0,137, 3, 97, 3,176, 4,165, 0, 3, 0, 7, 0, 0, 19, 33, 21, 33, 21, 33, 21, 33,137, 3, 39,252,217, 3, 39,252,
+217, 4,165, 94,135, 95, 0, 0, 0, 1, 0,111, 2, 5, 1,144, 6, 2, 0, 13, 0, 0, 1, 14, 1, 16, 22, 23, 35, 38, 39, 38,
+ 52, 55, 54, 55, 1,144, 84, 82, 82, 84,101, 94, 47, 47, 47, 46, 95, 6, 2,129,252,254,254,254,128,131,128,127,250,127,126,132,
+ 0, 1, 0,103, 2, 5, 1,136, 6, 2, 0, 15, 0, 0, 19, 51, 22, 23, 22, 20, 7, 6, 7, 35, 54, 55, 54, 16, 39, 38,103,101,
+ 95, 47, 46, 46, 47, 95,101, 84, 41, 42, 42, 41, 6, 2,132,126,127,250,127,128,131,128,127,127, 1, 2,126,126, 0, 1, 0,117,
+ 2,156, 2,197, 5, 31, 0, 19, 0, 48, 64, 7, 21, 0, 3, 14, 10, 11, 20, 16,212,220, 60, 47,204,204, 75,176, 13, 81, 88,177,
+ 21, 64, 56, 89, 49,178,127, 21, 1, 93, 0, 64, 6, 6, 17, 12, 2, 11, 20, 16,212, 60,196,212,204, 48, 1, 17, 35, 17, 52, 38,
+ 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 22, 2,196,116, 78, 78, 94,108,117,117, 41,113, 74,121,125, 4, 23,254,133,
+ 1,119, 89, 89,107, 92,254,158, 2,115, 97, 56, 56,134, 0, 0,255,255, 0, 87,255,241, 2,238, 3, 84, 16, 7, 5,204, 0, 0,
+253,100, 0, 0,255,255, 0,137, 0, 0, 2,197, 3, 67, 16, 7, 0,123, 0, 0,253,100, 0, 0,255,255, 0, 94, 0, 0, 2,180,
+ 3, 84, 16, 7, 0,116, 0, 0,253,100, 0, 0,255,255, 0, 98,255,241, 2,205, 3, 84, 16, 7, 0,117, 0, 0,253,100, 0, 0,
+255,255, 0, 63, 0, 0, 2,244, 3, 67, 16, 7, 5,206, 0, 0,253,100, 0, 0,255,255, 0,102,255,241, 2,211, 3, 67, 16, 7,
+ 5,207, 0, 0,253,100, 0, 0,255,255, 0, 92,255,241, 2,243, 3, 84, 16, 7, 5,208, 0, 0,253,100, 0, 0,255,255, 0,108,
+ 0, 0, 2,213, 3, 67, 16, 7, 5,209, 0, 0,253,100, 0, 0,255,255, 0, 89,255,241, 2,236, 3, 84, 16, 7, 5,210, 0, 0,
+253,100, 0, 0,255,255, 0, 83,255,241, 2,233, 3, 84, 16, 7, 5,211, 0, 0,253,100, 0, 0,255,255, 0,137, 0, 0, 3,176,
+ 2,207, 16, 7, 5,212, 0, 0,253,100, 0, 0,255,255, 0,137, 1, 56, 3,176, 1,151, 16, 7, 5,213, 0, 0,253,100, 0, 0,
+255,255, 0,137, 0,197, 3,176, 2, 9, 16, 7, 5,214, 0, 0,253,100, 0, 0,255,255, 0,111,255,105, 1,144, 3,102, 16, 7,
+ 5,215, 0, 0,253,100, 0, 0,255,255, 0,103,255,105, 1,136, 3,102, 16, 7, 5,216, 0, 0,253,100, 0, 0, 0, 1, 0, 86,
+ 0, 0, 6,174, 5,214, 0, 35, 0, 0, 1, 14, 1, 35, 34, 0, 16, 0, 51, 50, 22, 23, 21, 46, 1, 35, 34, 6, 16, 22, 51, 50,
+ 54, 55, 17, 33, 21, 33, 17, 33, 21, 33, 17, 33, 21, 33, 3,221, 79,178, 99,254,254,219, 1, 37,254,101,177, 78, 76,173, 98,192,
+204,204,192, 98,173, 76, 2,196,253,211, 2, 22,253,234, 2, 58,253, 47, 1,184, 54, 54, 1, 55, 2, 28, 1, 55, 53, 54,159, 71,
+ 70,234,254, 68,234, 70, 71, 2, 10,128,254,181,128,254,107,128, 0, 3, 0,115,255,166, 4,190, 6, 57, 0, 39, 0, 46, 0, 52,
+ 0, 0, 1, 22, 23, 55, 51, 7, 22, 23, 21, 38, 39, 1, 51, 50, 54, 55, 21, 14, 1, 35, 34, 39, 7, 35, 55, 38, 39, 7, 35, 55,
+ 38, 39, 38, 17, 16, 55, 54, 37, 55, 51, 7, 6, 7, 6, 17, 20, 23, 1, 38, 39, 1, 22, 23, 3,104, 65, 62, 30,155, 47, 40, 37,
+ 58, 64,254,193, 18,119,211, 93, 97,216,121, 27, 26, 18,155, 25, 65, 57, 38,155, 65, 19, 17,178,178,160, 1, 8, 21,156,227,145,
+ 88,125, 82, 2, 52, 62, 67,254,193, 53, 65, 5,235, 8, 19,105,165, 22, 28,213, 60, 41,251,151, 94, 95,211, 72, 72, 2, 63, 87,
+ 18, 30,135,230, 18, 21,207, 1,103, 1,104,208,185, 20, 75,252, 31,112,157,254,216,238,148, 3,203, 19, 4,251,149, 40, 21, 0,
+ 0, 1, 0, 96,255,228, 4,179, 5,240, 0, 44, 0, 0, 37, 54, 55, 54, 55, 21, 14, 1, 35, 32, 0, 17, 16, 0, 33, 50, 22, 23,
+ 21, 46, 1, 35, 34, 2, 17, 16, 23, 22, 23, 17, 51, 21, 62, 1, 51, 50, 22, 31, 1, 46, 1, 35, 34, 6, 21, 3, 46, 97, 88,106,
+ 93, 97,217,121,254,202,254,155, 1,101, 1, 54,123,217, 95, 93,212,119,234,249,124, 94,153,152, 48,154,110, 15, 38, 23, 1, 26,
+ 60, 36,128,139,138, 7, 39, 47, 95,211, 72, 71, 1,158, 1,103, 1,104, 1,159, 71, 71,213, 95, 94,254,199,254,216,254,217,156,
+117, 30, 3, 93,157, 92, 89, 4, 5,170, 16, 15,182,171, 0, 0, 0, 1, 0,133, 0, 0, 4,203, 5,213, 0, 17, 0, 0, 1, 17,
+ 33, 21, 33, 17, 33, 21, 33, 17, 51, 21, 35, 17, 35, 17, 35, 53, 1,113, 3, 90,253,112, 2, 80,253,176,250,250,202,236, 1,126,
+ 4, 87,170,254, 72,170,254,181, 69,254,199, 1, 57, 69, 0, 0, 0, 1, 0,129, 0, 0, 4, 98, 5,240, 0, 35, 0, 0, 1, 17,
+ 33, 21, 33, 53, 51, 17, 35, 53, 51, 53, 35, 53, 51, 53, 16, 54, 51, 50, 22, 23, 21, 46, 1, 35, 34, 6, 29, 1, 33, 21, 33, 21,
+ 33, 21, 2, 53, 2, 45,252, 31,236,191,191,199,199,214,232, 61,151, 79, 76,136, 61,148,116, 1,135,254,121, 1,143, 1,236,254,
+190,170,170, 1, 66,143,143,143, 95, 1, 5,243, 31, 29,182, 41, 41,155,212, 72,143,143,143, 0, 0, 1, 0,186,255,189, 7, 29,
+ 4,171, 0, 42, 0, 0, 1, 22, 23, 62, 1, 51, 50, 22, 21, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 52, 39, 1, 35, 1,
+ 38, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 23, 55, 51, 3,204, 61, 32, 69,192,130,175,190,185,114,117,143,166,185,
+ 14,254,240,128, 1, 59, 53, 81,141,166,185,185, 63,176,121, 74, 60, 22,128, 4, 33, 59, 93,124,118,245,226,253, 92, 2,158,161,
+156,190,164,253,135, 2,158, 82, 60,252,145, 3,250, 36,191,163,253,135, 4, 96,174,103, 98, 23, 71, 0, 0, 0, 0, 5, 0,117,
+ 0, 0, 5,135, 5,213, 0, 2, 0, 6, 0, 34, 0, 38, 0, 41, 0, 0, 1, 39, 21, 19, 39, 35, 21, 3, 33, 19, 51, 17, 51, 17,
+ 51, 21, 35, 21, 51, 21, 35, 17, 33, 3, 35, 17, 35, 17, 35, 53, 51, 53, 35, 53, 51, 5, 23, 51, 53, 3, 23, 53, 2, 75, 79,182,
+ 56,126,196, 1, 16,211,229,196,195,195,195,195,254,240,211,229,196,195,195,195,195, 2, 18, 56,126, 79, 79, 3,175,206,206,254,
+242,147,147, 3, 52,253,218, 2, 38,253,218,123,147,123,253,218, 2, 38,253,218, 2, 38,123,147,123,123,147,147,254,242,206,206,
+ 0, 2, 0,201,255,227, 9,206, 5,213, 0, 8, 0, 80, 0, 0, 1, 17, 51, 50, 54, 53, 52, 38, 35, 1, 6, 7, 6, 43, 1, 17,
+ 35, 17, 33, 50, 23, 22, 23, 51, 17, 51, 17, 33, 21, 33, 17, 20, 22, 59, 1, 53, 30, 1, 51, 50, 54, 53, 52, 38, 47, 1, 46, 1,
+ 53, 52, 54, 51, 50, 22, 23, 21, 46, 1, 35, 34, 6, 21, 20, 22, 31, 1, 30, 1, 21, 20, 6, 35, 34, 38, 39, 53, 35, 34, 38, 53,
+ 17, 1,135,239,133,145,145,133, 1,221, 6,113,122,236,239,190, 1,173,236,122, 87, 24, 81,174, 1,101,254,155, 71,108,171, 96,
+187, 91,122,132, 95,161, 60,161,143,211,194, 96,169, 72, 74,158, 85,129,129, 93,139, 59,185,155,233,203, 85,183,102,171,201,152,
+ 5, 47,253,207,146,135,134,146,254,204,200,106,113,253,168, 5,213,113, 82,136, 1, 62,254,194,143,253,160,137, 78, 35, 53, 53,
+ 89, 81, 75, 80, 37, 15, 36,149,130,158,172, 30, 30,174, 40, 40, 84, 84, 64, 73, 33, 14, 42,153,137,156,182, 35, 35, 1,159,210,
+ 2, 96, 0, 0, 0, 2, 0,201,255,227, 8, 51, 5,213, 0, 7, 0, 69, 0, 0, 1, 17, 51, 50, 54, 16, 38, 35, 1, 23, 35, 3,
+ 46, 1, 43, 1, 17, 35, 17, 33, 32, 22, 21, 20, 6, 7, 30, 1, 31, 1, 22, 23, 22, 51, 50, 54, 53, 52, 38, 47, 1, 46, 1, 53,
+ 52, 54, 51, 50, 22, 23, 21, 46, 1, 35, 34, 6, 21, 20, 22, 31, 1, 30, 1, 21, 20, 6, 35, 34, 39, 38, 1,147,254,146,149,149,
+146, 2,191, 4,217,191, 74,139,120,220,202, 1,200, 1, 0,252,131,125, 65,123, 62, 91, 98, 96, 99, 97,130,140,101,171, 64,171,
+152,224,206,102,180, 76, 78,168, 90,137,137, 98,148, 63,196,165,247,216, 90, 97, 44, 5, 47,253,238,135, 1, 6,133,250,216, 7,
+ 1,127,150, 98,253,137, 5,213,214,216,141,186, 36, 22,144,126,180, 51, 25, 27, 89, 81, 75, 80, 37, 15, 36,149,130,158,172, 30,
+ 30,174, 40, 40, 84, 84, 64, 73, 33, 14, 42,153,137,156,182, 18, 8, 0, 0, 0, 0, 6, 0, 59, 0, 0, 7,174, 5,213, 0, 31,
+ 0, 34, 0, 38, 0, 41, 0, 45, 0, 49, 0, 0, 19, 39, 35, 53, 51, 39, 51, 23, 33, 55, 51, 23, 33, 55, 51, 7, 51, 21, 35, 7,
+ 51, 21, 35, 3, 35, 3, 35, 3, 35, 3, 35, 53, 5, 27, 1, 1, 23, 33, 55, 1, 27, 2, 7, 51, 39, 33, 23, 33, 55,182, 30, 93,
+ 58, 49,204, 48, 2, 19, 48,227, 48, 2, 19, 48,205, 49, 57, 93, 29,122,158,225,254,218,195,220,254,224,159, 4,192,165,165,254,
+117, 29, 1,145, 29,251, 32,165,165,229, 29,125, 28,253, 76, 29, 1,145, 29, 4, 15,117,143,194,194,194,194,194,194,143,117,143,
+252,128, 3,128,252,128, 3,128,143,143,253,103, 2,153, 1, 4,117,117,254,252,253,103, 2,153, 1, 4,117,117,117,117, 0, 0,
+ 0, 2, 0, 95,255,227, 5,241, 5,213, 0, 13, 0, 27, 0, 0, 19, 37, 32, 0, 25, 1, 35, 17, 52, 38, 35, 33, 17, 35, 41, 1,
+ 34, 0, 25, 1, 51, 17, 20, 22, 51, 33, 3, 51, 95, 2, 7, 0,255, 1, 6,184,157,176,254,177,184, 5,142,253,253,255,254,250,
+184,157,176, 1, 83, 4,184, 5,210, 3,254,214,254,220,254,145, 1, 86,240,211,250,178, 1, 42, 1, 36, 1,111,254,170,240,211,
+ 5, 78, 0, 0,255,255, 0,129,254,192, 5, 4, 6, 20, 18, 34, 0,211, 16, 0, 16, 3, 2, 38, 0,138, 0, 0, 0, 1, 0, 0,
+255,227, 4,143, 5,240, 0, 49, 1, 28, 64, 58, 32, 18,211, 34, 16, 43, 7,211, 9, 25,161, 26,174, 22,149, 29, 1,161, 0,174,
+ 4,149, 47,145, 29,140, 41, 9, 50, 43, 34, 33, 41, 35, 38, 18, 16, 10, 3, 13, 9, 17, 8, 44, 32, 38, 19, 7, 17, 8, 17, 13,
+ 28, 25, 0, 38, 42, 33, 47, 60,212,196, 50,252,196,196, 18, 57, 57, 18, 57, 57, 17, 18, 57, 17, 23, 57, 18, 57, 57, 17, 57, 57,
+ 49, 0, 16,196, 50,228,244,236,244,236, 16,238,246,238, 16,238, 50,221, 60,238, 50, 48, 1, 75,176, 9, 84, 75,176, 12, 84, 91,
+ 75,176, 13, 84, 91, 75,176, 15, 84, 91, 75,176, 23, 84, 91, 75,176, 24, 84, 91, 88,189, 0, 50,255,192, 0, 1, 0, 50, 0, 50,
+ 0, 64, 56, 17, 55, 56, 89, 64,122, 14, 0, 14, 1, 11, 2, 11, 49, 84, 20,105, 12,108, 14,110, 15,111, 16,111, 17,111, 18,111,
+ 19,105, 20,107, 31,111, 32,111, 33,111, 34,111, 35,110, 36,108, 37,105, 39,105, 45,159, 7,159, 8,159, 9,159, 10,159, 11,159,
+ 12,159, 13,159, 14,159, 15,159, 16,159, 17,159, 18,159, 19,150, 31,159, 32,159, 33,159, 34,159, 35,159, 36,159, 37,159, 38,159,
+ 39,159, 40,159, 41,159, 42,159, 43,159, 44,157, 45, 50, 0, 8, 0, 9, 16, 8, 16, 9, 32, 8, 32, 9, 85, 21, 83, 30,106, 21,
+103, 31, 10, 93, 0, 93, 1, 21, 46, 1, 35, 34, 6, 7, 33, 7, 33, 14, 1, 21, 20, 22, 23, 33, 7, 33, 30, 1, 51, 50, 54, 55,
+ 21, 14, 1, 35, 34, 0, 3, 35, 55, 51, 52, 38, 53, 52, 54, 53, 35, 55, 51, 18, 0, 51, 50, 22, 4,143, 91,169,102,157,202, 32,
+ 2, 65, 55,253,230, 2, 1, 1, 2, 1,190, 56,254,138, 32,202,157,102,169, 91, 89,185, 96,237,254,203, 40,211, 55,139, 1, 1,
+194, 55,156, 40, 1, 54,236, 98,185, 5, 98,213,105, 90,200,187,123, 24, 46, 35, 32, 46, 24,123,187,202, 90,105,211, 72, 72, 1,
+ 34, 1, 3,123, 23, 47, 32, 35, 47, 23,123, 1, 1, 1, 34, 71, 0, 1, 0, 40, 0, 0, 5, 22, 5,213, 0, 17, 0, 0, 19, 17,
+ 51, 17, 1, 51, 1, 33, 21, 33, 1, 35, 1, 17, 35, 17, 35, 53,191,189, 2,117,243,253,128, 1,170,254, 88, 2,176,249,253, 95,
+189,151, 3, 84, 2,129,253,137, 2,119,253,127,115,253, 31, 2,207,253, 49, 2,225,115, 0, 0, 0, 1, 0, 20, 0, 0, 5, 3,
+ 5,213, 0, 23, 0, 0, 1, 17, 33, 53, 33, 21, 33, 17, 55, 23, 5, 21, 55, 23, 5, 17, 35, 17, 7, 39, 37, 53, 7, 39, 2, 38,
+253,238, 4,239,253,238,229, 80,254,203,230, 80,254,202,203,231, 77, 1, 52,232, 77, 3,141, 1,158,170,170,254,241,161,111,216,
+136,162,111,217,253,184, 1,186,161,110,217,136,162,110, 0, 0, 0, 4, 0, 27,254,117, 8, 90, 5,200, 0, 23, 0, 35, 0, 48,
+ 0, 59, 0, 0, 51, 55, 51, 54, 55, 19, 34, 6, 29, 1, 7, 16, 55, 54, 33, 51, 50, 0, 21, 16, 3, 6, 4, 33, 55, 51, 32, 0,
+ 17, 52, 38, 43, 1, 3, 2, 6, 1, 19, 26, 1, 51, 32, 17, 16, 0, 35, 34, 39, 3, 19, 22, 51, 50, 18, 53, 52, 35, 34, 3, 7,
+ 28,148, 56,116, 42,172,130,150,194,160,160, 1,138, 64,226, 1, 4,238,124,254,172,254,212, 48,118, 1, 24, 1, 68,150,128, 80,
+134, 52, 74, 2,140,160, 74,230,192, 1, 72,254,178,224, 52, 92, 86,124, 74, 74,132,176,150,156, 68, 26,160, 82,211, 3, 95,166,
+145, 24, 94, 1, 17,159,161,254,234,241,254,119,254,218,152,122,160, 1,168, 1,110,174,208,253, 88,254,255,161,253,139, 3, 44,
+ 1,115, 1, 66,254,165,254,206,254, 55, 35,254, 82, 2,109, 78, 1, 67,246,245,254,185,130, 0, 0, 4, 0, 68, 0, 0, 4,162,
+ 5,213, 0, 29, 0, 36, 0, 43, 0, 49, 0, 0, 19, 53, 35, 53, 51, 17, 33, 50, 23, 22, 23, 51, 21, 35, 22, 20, 7, 51, 21, 35,
+ 6, 7, 6, 43, 1, 17, 35, 17, 35, 53, 5, 33, 21, 51, 50, 55, 54, 1, 33, 38, 39, 38, 43, 1, 5, 33, 21, 33, 54, 52,151, 82,
+ 82, 1,200,251,129, 76, 31, 92, 72, 1, 1, 71, 90, 31, 77,129,251,254,202, 83, 3, 28,254, 1,254,141, 77, 23,254, 17, 1,255,
+ 16, 23, 77,141,254, 2, 35,253,221, 2, 35, 2, 3,236, 86,116, 1, 31,113, 68,106,116, 21, 44, 21,116,107, 68,113,253,168, 3,
+120,116,116,122, 73, 22, 1, 89, 27, 21, 73,237, 86, 21, 44, 0, 0, 1, 0,117,255,227, 5,188, 5,240, 0, 54, 0, 0, 1, 54,
+ 55, 54, 55, 33, 53, 33, 54, 55, 54, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 4, 21, 20, 7, 51, 21, 33, 6, 15, 1, 33,
+ 21, 33, 6, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 32, 36, 53, 52, 55, 35, 53, 1, 92, 4, 22, 74,128,254, 53, 3,146, 12,
+ 13, 59,179,165, 95,204,115,114,218,105,245, 1, 23, 25,175,254,253,103,216, 67, 2,133,252, 83, 49,188,173,114,236,123,128,239,
+106,254,231,254,221, 18,168, 2,161, 7, 22, 74, 44,123, 8, 9, 43,107,118,128, 54, 55,197, 38, 38,228,198, 85, 66,123, 92, 42,
+ 13,123, 59, 94,126,136, 70, 69,208, 47, 48,224,217, 75, 63,123, 0, 2, 0,170,254,211, 4,119, 6, 20, 0, 33, 0, 44, 0, 0,
+ 1, 21, 38, 39, 38, 35, 17, 50, 55, 54, 55, 21, 6, 7, 6, 7, 17, 35, 17, 38, 39, 38, 17, 53, 16, 55, 54, 55, 53, 55, 21, 22,
+ 23, 22, 1, 3, 6, 7, 6, 7, 6, 23, 22, 23, 22, 4,119, 91, 84, 85,101,101, 85, 84, 91, 89, 92, 89, 91,100,185,115,212,212,
+121,178,101, 93, 89, 92,254,138, 1, 91, 67,118, 15, 14, 14, 25,108, 67, 4,164,213,105, 45, 45,251,241, 45, 45,105,211, 72, 36,
+ 34, 2,254,240, 1, 21, 23,117,214, 1, 57, 17, 1, 66,203,116, 23,230, 2,226, 2, 34, 35,251,163, 3,249, 23, 66,117,170,161,
+102,180,108, 67, 0, 1,252, 61, 4,122,255,203, 6, 20, 0, 8, 0, 0, 3, 33, 23, 35, 39, 55, 51, 7, 33, 53,253, 27,132,126,
+175,175,126,132, 2,229, 5, 21,155,205,205,155, 0, 1,252, 61, 4,122,255,203, 6, 20, 0, 8, 0, 0, 1, 53, 33, 39, 51, 23,
+ 7, 35, 55,252, 61, 2,229,132,126,175,175,126,132, 5, 21,100,155,205,205,155, 0, 4, 0, 67,255,207, 7,216, 6, 4, 0, 10,
+ 0, 36, 0, 40, 0, 66, 0, 0, 1, 34, 6, 21, 20, 22, 51, 50, 54, 61, 1, 55, 17, 35, 53, 14, 1, 35, 34, 38, 53, 52, 54, 51,
+ 23, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 37, 51, 1, 35, 1, 21, 46, 1, 35, 34, 6, 21, 20, 22, 51, 50, 54, 55, 21,
+ 14, 1, 35, 34, 38, 53, 52, 54, 51, 50, 22, 2, 15,160,112, 83, 72,102,127,188,188, 3,153,109,141,166,205,198,169,111,103, 68,
+129, 99, 92,148, 71,194,193, 2,176,216,252, 68,216, 5,169, 94,111, 56,121,137,137,121, 56,111, 94, 73,130, 73,202,236,238,209,
+ 67,128, 3,246, 66, 82, 67, 73,148,130, 10, 77,254, 13, 62, 5, 79,158,129,150,155, 6, 87, 92, 32, 55,178, 36, 30,202,250,249,
+203, 3,132,178, 52, 30,156,148,147,157, 31, 52,177, 34, 27,250,209,212,249, 27,255,255, 0,195,255,240, 8,140, 5,240, 16, 38,
+ 0,114, 0, 0, 16, 71, 0, 38, 3, 70, 0, 12, 65,117, 62, 82, 0, 2,255,214, 0, 0, 5, 24, 5,213, 0, 8, 0, 43, 0,153,
+184, 0, 44, 47,184, 0, 45, 47,184, 0, 21,220,184, 0, 0,220,184, 0, 44, 16,184, 0, 40,208,184, 0, 40, 47,184, 0, 4,220,
+ 65, 27, 0, 22, 0, 4, 0, 38, 0, 4, 0, 54, 0, 4, 0, 70, 0, 4, 0, 86, 0, 4, 0,102, 0, 4, 0,118, 0, 4, 0,134,
+ 0, 4, 0,150, 0, 4, 0,166, 0, 4, 0,182, 0, 4, 0,198, 0, 4, 0,214, 0, 4, 0, 13, 93, 65, 5, 0,229, 0, 4, 0,
+245, 0, 4, 0, 2, 93,184, 0, 0, 16,184, 0, 9,208,184, 0, 21, 16,184, 0, 11,208,184, 0, 21, 16,184, 0, 31,208,184, 0,
+ 0, 16,184, 0, 35,208, 0,184, 0, 10, 47,186, 0, 33, 0, 34, 0, 3, 43,184, 0, 33, 16, 48, 49, 1, 6, 7, 6, 21, 20, 23,
+ 22, 23, 17, 53, 51, 21, 22, 23, 22, 23, 21, 38, 39, 38, 39, 17, 54, 55, 54, 55, 21, 6, 7, 6, 7, 21, 33, 21, 33, 53, 38, 39,
+ 38, 17, 16, 55, 54, 1,119, 73, 51, 99, 99, 51, 73,202, 56, 54, 81, 76, 78, 78, 55, 56, 56, 55, 78, 78, 77, 82, 52, 56, 2,215,
+252, 95,161,107,149,151,105, 4,179, 29, 58,114,205,205,113, 59, 29, 3,212,122,110, 4, 11, 18, 35,172, 43, 22, 15, 4,252,164,
+ 4, 16, 21, 43,170, 36, 18, 11, 4, 42,170,222, 32,114,159, 1, 14, 1, 18,157,110, 0, 0, 0, 0, 4, 0, 60,255,207, 7,229,
+ 6, 4, 0, 25, 0, 29, 0, 40, 0, 50, 0, 0, 1, 21, 46, 1, 35, 34, 6, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38,
+ 53, 52, 54, 51, 50, 22, 37, 51, 1, 35, 1, 34, 6, 21, 20, 22, 51, 50, 54, 16, 38, 36, 32, 22, 21, 20, 6, 32, 38, 53, 52, 3,
+ 6, 94,111, 56,121,137,137,121, 56,111, 94, 73,130, 73,202,236,238,209, 67,128, 2,221,216,252, 68,216, 4,107, 97,118,118, 97,
+ 96,119,119,254,223, 1,130,218,218,254,126,217, 5,151,178, 52, 30,156,148,147,157, 31, 52,177, 34, 29,252,209,212,249, 27, 75,
+249,203, 3, 4,158,146,145,159,160, 1, 32,160,157,248,213,212,248,248,212,213, 0, 3, 0, 60,255,207, 8, 77, 6, 4, 0, 19,
+ 0, 45, 0, 49, 0, 0, 1, 17, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 35, 53, 14, 1, 35, 34, 38, 1, 21, 46, 1, 35, 34,
+ 6, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 53, 52, 54, 51, 50, 22, 37, 51, 1, 35, 5, 92,188, 81, 80, 99,117,188,
+188, 6,144, 96,158,161,253,170, 94,111, 56,121,137,137,121, 56,111, 94, 73,130, 73,202,236,238,209, 67,128, 2,221,216,252, 68,
+216, 1, 76, 2, 16,253,245,114,105,129,117, 1,240,252,144, 68, 9, 80,193, 4,255,178, 52, 30,156,148,147,157, 31, 52,177, 34,
+ 29,252,209,212,249, 27, 75,249,203, 0, 0, 0,255,255, 0,195, 0, 0, 7, 38, 5,240, 16, 34, 0,114, 0, 0, 16, 3, 0, 41,
+ 3, 3, 0, 0, 0, 1, 0, 72, 0, 0, 4,135, 6, 20, 0, 25, 0, 0, 1, 3, 35, 19, 62, 1, 53, 52, 38, 35, 34, 6, 7, 3,
+ 35, 1, 51, 3, 62, 1, 51, 50, 22, 21, 20, 6, 4,117,131,185,131, 9, 10,106, 95,148,217, 32,121,184, 1, 47,184,119, 70,218,
+120,148,163, 9, 2,164,253, 92, 2,157, 47, 72, 21, 84, 94,200,166,253,147, 6, 20,253,156, 94,109,160,145, 36, 82, 0, 0, 0,
+ 0, 1, 0, 34, 0, 0, 4, 98, 6, 20, 0, 29, 0, 0, 1, 54, 55, 54, 51, 50, 23, 22, 7, 3, 35, 19, 54, 38, 35, 34, 6, 7,
+ 3, 35, 19, 35, 55, 51, 55, 51, 7, 33, 7, 33, 1,148, 85, 99,100,117,193, 76, 75, 45,131,184,130, 31, 93,124,149,209, 32,123,
+185,249,154, 25,154, 28,185, 28, 2, 64, 25,253,192, 3,178,101, 50, 50,119,120,232,253, 92, 2,158,159,158,190,164,253,135, 5,
+ 4,125,147,147,125, 0, 0, 0, 0, 2, 0,106,255,227, 5, 70, 5,240, 0, 33, 0, 50, 0, 0, 63, 1, 54, 51, 50, 23, 22, 51,
+ 50, 55, 54, 53, 52, 39, 38, 53, 52, 63, 1, 6, 21, 20, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 35, 34, 19, 54, 51, 50, 23, 22,
+ 51, 50, 55, 7, 6, 35, 34, 38, 35, 34, 7,106,140,111,117, 57,132,144, 33,121,100, 71, 62, 80, 80,213, 80, 80, 53,202,186,242,
+ 54,129,133, 56, 94,110,109,141,123,127,122,128,125,125,200,139,111,143,214,143,122,128, 90,165, 39, 80, 86,137, 97, 75,126,112,
+146,109,100,160,140,139,121,107,148, 98,188, 94,242,222, 79, 80, 5, 54, 56, 49, 47, 58,170, 58, 98, 58, 0, 0, 0, 2,255,228,
+255,227, 2,210, 5,240, 0, 28, 0, 38, 0, 0, 1, 22, 51, 50, 55, 51, 6, 7, 6, 35, 34, 39, 7, 35, 54, 55, 38, 53, 52, 55,
+ 18, 55, 54, 51, 50, 21, 6, 7, 2, 1, 18, 19, 54, 53, 52, 35, 6, 3, 6, 1, 48, 41, 87, 58, 75,133, 60, 70, 76, 70,156, 63,
+ 75,156,108, 80, 10, 31,117,104, 72,123,125, 1, 18, 72,254,184,187, 57, 30, 25,109, 97, 27, 1, 12,200,115,102, 53, 57,139,110,
+147,137, 78, 85,152,152, 2, 59,117, 81,173, 78, 93,254,131,254,247, 1, 92, 1, 22,147, 38, 69, 87,253,250,145,255,255, 0,201,
+ 0, 0, 8,240, 5,240, 16, 39, 0,124, 5,140, 0, 0, 16, 6, 0, 49, 0, 0, 0, 4, 1, 27, 0, 0, 6,229, 5,202, 0, 12,
+ 0, 25, 0, 34, 0, 45, 0, 0, 1, 22, 17, 16, 0, 33, 32, 0, 3, 16, 0, 33, 32, 6, 33, 32, 0, 17, 18, 0, 33, 32, 0, 17,
+ 16, 39, 5, 17, 51, 50, 54, 53, 52, 38, 35, 37, 33, 50, 22, 21, 20, 6, 43, 1, 17, 35, 6, 11,218,254, 74,254,209,254,207,254,
+ 82, 6, 1,180, 1, 49, 1, 50, 41,254,247,254,250,254,134, 5, 1,117, 1, 6, 1, 7, 1,121,187,253,211,178, 99,107,107, 99,
+254,193, 1, 63,176,180,180,176,178,141, 4,241,219,254,206,254,208,254, 76, 1,180, 1, 48, 1, 48, 1,182,101,254,133,254,249,
+254,251,254,135, 1,121, 1, 5, 1, 9,187,119,254,175, 88, 81, 80, 88,100,137,131,133,135,254,152, 0, 0, 0, 0, 2, 0,110,
+254, 59, 5, 67, 3,246, 0, 48, 0, 60, 0, 0, 1, 6, 21, 20, 23, 54, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 35, 34, 39, 54,
+ 55, 22, 51, 50, 55, 54, 53, 52, 39, 38, 35, 34, 1, 18, 21, 20, 7, 6, 35, 34, 39, 38, 53, 16, 55, 38, 53, 52, 55, 3, 6, 21,
+ 20, 23, 22, 23, 50, 55, 54, 53, 52, 2, 53,136, 31, 91,171,219,132,131, 70, 73,156,121,174,101, 76, 18, 9, 41,113,122, 93, 69,
+ 38, 32, 74,189,254,159,135, 69, 89,131,113, 58, 63,223, 46,232,148,129, 31, 48, 46, 65, 28, 32, 3,198,130,190, 77,107,101,148,
+189, 76, 80,171,218,215,167, 60, 43, 29, 40,140,104,195,124, 72, 61,254,121,254,222,124,157,110,142, 61, 66,134, 1, 11,252,158,
+127,238,164,252,239,198,123,117, 46, 70, 1, 47, 52, 95, 78, 0, 0, 2, 0, 83,255,227, 6,108, 5,241, 0, 73, 0, 88, 0, 0,
+ 5, 38, 53, 52, 39, 38, 35, 34, 15, 1, 21, 20, 7, 6, 35, 34, 39, 38, 53, 22, 23, 20, 23, 22, 50, 55, 54, 53, 17, 52, 39, 38,
+ 35, 34, 7, 6, 20, 23, 22, 51, 23, 34, 39, 38, 53, 52, 55, 54, 51, 50, 23, 22, 23, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 7,
+ 50, 23, 22, 23, 22, 21, 20, 23, 55, 23, 1, 22, 21, 17, 55, 54, 55, 54, 53, 52, 39, 38, 35, 34, 7, 5, 2, 82, 22, 40, 79, 42,
+ 92,120,103,103,140,141,102,103, 45, 46, 64, 64,144, 63, 64, 64, 63, 92, 81, 65, 64, 64, 64, 83, 54,151,102,103,103,102,151,162,
+101, 30, 16,211,187,112, 47, 36,126, 65, 66,125, 58, 49, 36, 27, 32, 45,144, 42,252,164, 21,154,144, 77, 74, 74, 24, 31, 64,102,
+ 29,183,159,140, 91,166, 43, 56,199,206,118,117,117,118,176, 12, 12,122, 86, 87, 87, 87,150, 2,155,149, 88, 87, 87, 86,202, 86,
+ 87, 92,117,118,156,157,117,117,117, 35, 32, 98, 87, 14, 49,177, 87,123,124, 94, 49, 36,104,123,131,128,118, 67, 91, 4, 83, 75,
+ 92,254,149, 71, 67,104,102,121,151, 32, 10, 47, 0, 5, 0,118, 0, 0, 5,225, 5,213, 0, 7, 0, 27, 0, 31, 0, 39, 0, 48,
+ 0, 0, 1, 22, 23, 19, 51, 3, 38, 39, 32, 43, 1, 17, 33, 17, 33, 32, 22, 21, 20, 6, 7, 30, 1, 23, 19, 33, 3, 38, 1, 17,
+ 51, 17, 1, 17, 38, 35, 33, 17, 33, 50, 55, 54, 55, 54, 53, 52, 39, 38, 39, 3, 46, 78,102,142,200,142, 96, 90,254,164,120, 20,
+254,110, 2,168, 1, 0,252,132,124, 64,124, 62,204,254, 72,190, 74,253,186,198, 1,238, 34, 38,254,194, 1, 62, 38,138, 58, 40,
+ 94, 94, 38, 60, 2,119, 47,201,254,229, 1, 27,192, 56,253,137, 5,213,214,216,141,186, 36, 22,144,126,254,104, 1,127,150, 3,
+ 92,250,243, 5, 13,253,110, 2,142, 4,253,106, 27, 21, 37, 84,164,158, 88, 36, 20, 0, 0, 0, 0, 2, 0,169, 0, 0, 6,131,
+ 5,213, 0, 8, 0, 31, 0,167,184, 0, 32, 47,184, 0, 33, 47,184, 0, 32, 16,184, 0, 14,208,184, 0, 14, 47,184, 0, 13,220,
+184, 0, 0,208,184, 0, 33, 16,184, 0, 19,220,184, 0, 5,220, 65, 5, 0,234, 0, 5, 0,250, 0, 5, 0, 2, 93, 65, 27, 0,
+ 25, 0, 5, 0, 41, 0, 5, 0, 57, 0, 5, 0, 73, 0, 5, 0, 89, 0, 5, 0,105, 0, 5, 0,121, 0, 5, 0,137, 0, 5, 0,
+153, 0, 5, 0,169, 0, 5, 0,185, 0, 5, 0,201, 0, 5, 0,217, 0, 5, 0, 13, 93,184, 0, 9,208,184, 0, 9, 47,186, 0,
+ 30, 0, 14, 0, 19, 17, 18, 57, 0,184, 0, 13, 47,184, 0, 26, 47,184, 0, 29, 47,186, 0, 15, 0, 0, 0, 3, 43,184, 0, 15,
+ 16,186, 0, 2, 0, 11, 0, 3, 43,184, 0, 2, 16, 48, 49, 1, 17, 51, 50, 54, 53, 52, 38, 35, 1, 6, 43, 1, 17, 35, 17, 33,
+ 50, 4, 21, 20, 7, 23, 55, 51, 9, 1, 35, 11, 1, 35, 1, 1,115,254,141,154,154,141, 1, 32,115,173,254,202, 1,200,251, 1,
+ 1, 78,174,190,232,254,205, 1, 67,233,207,212,232, 1, 73, 5, 47,253,207,146,135,134,146,253, 95, 54,253,168, 5,213,227,219,
+172,107,219,234,254,134,254,107, 1, 4,254,252, 1,149, 0, 0, 0, 2, 1, 3, 3,139, 6, 40, 5,216, 0, 39, 0, 52, 0, 0,
+ 1, 21, 46, 1, 35, 34, 6, 21, 20, 22, 31, 1, 30, 1, 21, 20, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 47, 1,
+ 46, 1, 53, 52, 54, 51, 50, 22, 55, 51, 27, 1, 51, 17, 35, 17, 3, 35, 3, 17, 35, 2,230, 85, 87, 39, 65, 71, 47, 69, 56,112,
+105,144,140, 52,115, 71, 91,100, 47, 69, 75, 55, 63, 56,112, 99,138,124, 51,105,208,184,161,162,184,138,140,135,141,137, 5,183,
+ 89, 34, 19, 42, 47, 40, 32, 11, 9, 18, 86, 65, 79, 91, 19, 21, 96, 42, 24, 44, 50, 44, 42, 10, 9, 18, 77, 61, 72, 92, 15, 5,
+254,172, 1, 84,253,200, 1,148,254,216, 1, 40,254,108, 0, 0, 0, 3,255,252, 0, 0, 8, 48, 4, 96, 0, 7, 0, 19, 0, 25,
+ 0, 0, 3, 33, 21, 33, 17, 35, 17, 33, 5, 33, 21, 33, 17, 33, 21, 33, 17, 33, 21, 33, 1, 51, 17, 33, 21, 33, 4, 3,179,254,
+114,152,254,115, 2,224, 2,111,254, 22, 1,213,254, 43, 1,246,253,133, 2,239,133, 1,224,253,155, 4, 96,128,252, 32, 3,224,
+ 96,102,254,247,102,254,187,102, 3,128,252,230,102, 0, 0, 0, 0, 2, 1, 39, 3,147, 6, 70, 5,213, 0, 12, 0, 20, 0, 62,
+ 64, 33, 1, 6, 7, 16, 10, 4, 18, 14, 9, 3, 6,201, 13, 2, 0,129, 21, 1, 9, 5, 98, 3, 9, 98, 11, 13, 99, 15, 98, 19,
+ 99, 17, 21, 16,212,228,252,228,212,236,212,236, 17, 57, 49, 0, 16,244, 60, 60,236, 23, 50,212, 60, 60,196, 17, 57, 48, 1, 27,
+ 1, 51, 17, 35, 17, 3, 35, 3, 17, 35, 17, 35, 21, 35, 17, 35, 17, 35, 53, 4, 74,174,164,170,113,195, 55,203,114,113,203,114,
+201, 5,213,255, 0, 1, 0,253,190, 1,228,254,209, 1, 47,254, 28, 2, 66, 94,254, 28, 1,228, 94, 0, 0, 0,255,255, 0, 78,
+ 0, 0, 5,207, 5,231, 16, 6, 2,199, 0, 0, 0, 1, 0, 78,255,227, 5,207, 5,202, 0, 30, 0, 0, 1, 53, 33, 21, 22, 18,
+ 21, 20, 0, 32, 0, 53, 52, 18, 55, 53, 33, 21, 33, 6, 2, 21, 16, 0, 33, 32, 0, 17, 52, 2, 39, 5,207,253,168,177,198,254,
+248,254, 80,254,247,199,178,253,168, 1, 63,158,145, 1,127, 1, 49, 1, 47, 1,129,142,161, 5, 24,178,178, 97,254,180,202,240,
+254,222, 1, 35,239,202, 1, 76, 97,178,178,139,254,214,184,254,194,254,118, 1,137, 1, 53,194, 1, 40,141, 0,255,255, 0,201,
+ 0, 0, 5,106, 5,213, 16, 6, 0, 46, 0, 0,255,255, 0, 16, 0, 0, 5,104, 7,109, 16, 6, 0,135, 0, 0, 0, 2, 0,125,
+255,231, 6, 89, 5, 45, 0, 26, 0, 41, 0, 0, 37, 22, 23, 22, 32, 55, 54, 55, 51, 6, 7, 6, 32, 36, 2, 53, 52, 18, 36, 51,
+ 50, 4, 18, 21, 33, 34, 21, 53, 20, 51, 33, 50, 53, 17, 38, 39, 38, 35, 34, 7, 6, 7, 1,144, 67, 93,150, 1, 74,152,106, 77,
+111, 95,142,179,254,122,254,155,198,201, 1,103,190,189, 1,103,202,251, 74, 19, 19, 3,144, 20, 70, 95,152,159,160,152, 95, 68,
+228, 77, 51, 84, 84, 60, 96,120, 71, 90,179, 1, 65,175,176, 1, 69,174,174,254,187,176, 19, 73, 19, 19, 1,112, 80, 51, 82, 81,
+ 52, 79, 0, 0, 0, 1, 0,201, 0, 0, 4, 35, 5,213, 0, 9, 0, 0, 41, 1, 53, 33, 17, 33, 53, 33, 17, 51, 4, 35,252,166,
+ 2,144,253,176, 2, 80,202,170, 1,184,170, 2,201, 0, 0, 0, 0, 2, 0,104,255,231, 3, 74, 3, 41, 0, 11, 0, 23, 0, 0,
+ 1, 52, 38, 35, 34, 2, 21, 20, 22, 51, 50, 18, 3, 50, 22, 21, 20, 2, 35, 34, 38, 53, 52, 18, 2,169, 87, 79,109,141, 86, 80,
+109,141,194,152,203,221,162,152,203,221, 1,247,116,125,254,254,207,116,123, 1, 4, 1,253,216,163,198,254,255,216,163,198, 1,
+ 1, 0, 0, 0, 0, 1, 0,103,255,227, 5,178, 5,240, 0, 54, 0, 0, 9, 1, 22, 21, 20, 7, 52, 39, 1, 7, 6, 31, 1, 22,
+ 21, 20, 7, 6, 43, 1, 53, 54, 53, 52, 47, 1, 38, 53, 52, 63, 1, 39, 38, 53, 52, 55, 20, 23, 9, 1, 39, 38, 53, 52, 55, 20,
+ 31, 1, 22, 21, 20, 7, 52, 47, 1, 3,196, 1,139, 99,144, 50,252,251,155, 62, 66,172,100, 61, 86, 69,245,196, 47, 98, 53,140,
+154,241, 99,144, 50, 2,108, 1, 25,116, 99,144, 50,182, 99,144, 50, 18, 2,208,254,117, 99, 49,130, 76, 83, 50, 3, 5,156, 63,
+ 66,172,100,106,108, 44, 62, 56, 63, 93, 29, 47, 99, 54,103, 85,141,155,241, 99, 49,130, 76, 83, 50,253,150, 1, 25,116, 99, 49,
+130, 76, 83, 50,182, 99, 49,130, 76, 83, 50, 18, 0, 4, 0,151, 0, 0, 9, 76, 4, 96, 0, 9, 0, 12, 0, 20, 0, 32, 0, 0,
+ 19, 33, 21, 33, 17, 33, 21, 33, 17, 35, 1, 3, 33, 1, 51, 1, 35, 39, 33, 7, 35, 1, 51, 27, 1, 51, 9, 1, 35, 9, 1, 35,
+ 1,151, 2,131,254, 20, 1,188,254, 68,151, 3,131,181, 1,106,255, 0,151, 1,119,138, 90,254, 68, 90,140, 3,214,143,245,246,
+144,254,195, 1, 82,144,254,235,254,233,144, 1, 96, 4, 96,128,254,182,127,253,233, 3, 8,254, 67, 2, 53,252,128,230,230, 3,
+128,254,179, 1, 77,254, 82,254, 46, 1,125,254,131, 1,222, 0, 0, 2, 0, 59,255,227, 5,184, 5,240, 0, 38, 0, 48, 0, 0,
+ 9, 1, 14, 1, 7, 35, 54, 18, 55, 1, 51, 23, 62, 1, 51, 50, 0, 21, 20, 6, 7, 30, 1, 21, 20, 6, 35, 34, 38, 39, 53, 30,
+ 1, 51, 50, 54, 53, 52, 38, 55, 62, 1, 53, 52, 38, 35, 34, 6, 7, 3,186,254, 4, 59, 66, 6,186, 12,104, 93,254,233,252,143,
+104,228,131,241, 1, 50,134,134, 48, 50,222,184, 83,165, 85, 87,158, 68,105,131, 59, 50, 91, 85,212,160, 95,166, 73, 2, 64, 2,
+ 8, 89,203,114,132, 1, 2,126, 1, 29,147, 89, 87,254,237,215,128,225, 99, 63,125, 60,162,197, 36, 36,182, 47, 49,111, 88, 51,
+103,206, 81,161, 88,146,194, 63, 64, 0, 0, 0,255,255, 0,137,255,227, 7, 88, 5,240, 16, 34, 0,123, 0, 0, 16, 39, 6, 90,
+ 3, 53, 0, 0, 16, 3, 0,117, 4,139,253,100,255,255, 0, 94,255,227, 7, 88, 5,240, 16, 34, 0,116, 0, 0, 16, 39, 6, 90,
+ 3, 53, 0, 0, 16, 3, 0,117, 4,139,253,100,255,255, 0,137,255,227, 7, 94, 5,240, 16, 34, 0,123, 0, 0, 16, 39, 6, 90,
+ 3, 53, 0, 0, 16, 3, 5,207, 4,139,253,100,255,255, 0, 94,255,227, 7, 94, 5,240, 16, 34, 0,116, 0, 0, 16, 39, 6, 90,
+ 3, 53, 0, 0, 16, 3, 5,207, 4,139,253,100,255,255, 0, 98,255,227, 7, 94, 5,240, 16, 34, 0,117, 0, 0, 16, 39, 6, 90,
+ 3, 53, 0, 0, 16, 3, 5,207, 4,139,253,100,255,255, 0, 63,255,227, 7, 94, 5,240, 16, 34, 5,206, 0, 0, 16, 39, 6, 90,
+ 3, 53, 0, 0, 16, 3, 5,207, 4,139,253,100,255,255, 0,137,255,227, 7,126, 5,240, 16, 34, 0,123, 0, 0, 16, 39, 6, 90,
+ 3, 53, 0, 0, 16, 3, 5,208, 4,139,253,100,255,255, 0,102,255,227, 7,126, 5,240, 16, 34, 5,207, 0, 0, 16, 39, 6, 90,
+ 3, 53, 0, 0, 16, 3, 5,208, 4,139,253,100,255,255, 0,137,255,227, 7,119, 5,240, 16, 34, 0,123, 0, 0, 16, 39, 6, 90,
+ 3, 53, 0, 0, 16, 3, 5,210, 4,139,253,100,255,255, 0, 98,255,227, 7,119, 5,240, 16, 34, 0,117, 0, 0, 16, 39, 6, 90,
+ 3, 53, 0, 0, 16, 3, 5,210, 4,139,253,100,255,255, 0,102,255,227, 7,119, 5,240, 16, 34, 5,207, 0, 0, 16, 39, 6, 90,
+ 3, 53, 0, 0, 16, 3, 5,210, 4,139,253,100,255,255, 0,108,255,227, 7,119, 5,240, 16, 34, 5,209, 0, 0, 16, 39, 6, 90,
+ 3, 53, 0, 0, 16, 3, 5,210, 4,139,253,100,255,255, 0,137,255,227, 6, 2, 5,240, 16, 34, 0,123, 0, 0, 16, 7, 6, 90,
+ 3, 53, 0, 0,255,255, 0,201, 0, 0, 1,147, 5,213, 16, 6, 0, 44, 0, 0,255,255, 0,201, 0, 0, 3, 39, 5,213, 16, 38,
+ 0, 44, 0, 0, 16, 7, 0, 44, 1,148, 0, 0,255,255, 0,201, 0, 0, 4,187, 5,213, 16, 38, 0, 44, 0, 0, 16, 39, 0, 44,
+ 1,148, 0, 0, 16, 7, 0, 44, 3, 40, 0, 0,255,255, 0,201, 0, 0, 7, 81, 5,213, 16, 38, 0, 44, 0, 0, 16, 7, 0, 57,
+ 1,233, 0, 0,255,255, 0, 16, 0, 0, 5,104, 5,213, 16, 6, 0, 57, 0, 0,255,255, 0, 16, 0, 0, 6,152, 5,213, 16, 38,
+ 0, 57, 0, 0, 16, 7, 0, 44, 5, 5, 0, 0,255,255, 0, 16, 0, 0, 8, 44, 5,213, 16, 38, 0, 57, 0, 0, 16, 39, 0, 44,
+ 5, 5, 0, 0, 16, 7, 0, 44, 6,153, 0, 0,255,255, 0, 16, 0, 0, 9,192, 5,213, 16, 38, 0, 57, 0, 0, 16, 39, 0, 44,
+ 5, 5, 0, 0, 16, 39, 0, 44, 6,153, 0, 0, 16, 7, 0, 44, 8, 45, 0, 0,255,255, 0,201, 0, 0, 7, 23, 5,213, 16, 38,
+ 0, 44, 0, 0, 16, 7, 0, 59, 1,220, 0, 0,255,255, 0, 61, 0, 0, 5, 59, 5,213, 16, 6, 0, 59, 0, 0,255,255, 0, 61,
+ 0, 0, 6,174, 5,213, 16, 38, 0, 59, 0, 0, 16, 7, 0, 44, 5, 27, 0, 0,255,255, 0, 61, 0, 0, 8, 66, 5,213, 16, 38,
+ 0, 59, 0, 0, 16, 39, 0, 44, 5, 27, 0, 0, 16, 7, 0, 44, 6,175, 0, 0,255,255, 0,201, 0, 0, 4,106, 5,213, 16, 6,
+ 0, 47, 0, 0,255,255, 0,115,255,227, 5, 39, 5,240, 16, 6, 0, 38, 0, 0,255,255, 0,201, 0, 0, 5,176, 5,213, 16, 6,
+ 0, 39, 0, 0,255,255, 0,201, 0, 0, 6, 31, 5,213, 16, 6, 0, 48, 0, 0,255,255, 0,193, 0, 0, 1,121, 6, 20, 16, 6,
+ 0, 76, 0, 0,255,255, 0,193, 0, 0, 2,233, 6, 20, 16, 38, 0, 76, 0, 0, 16, 7, 0, 76, 1,112, 0, 0,255,255, 0,193,
+ 0, 0, 4, 89, 6, 20, 16, 38, 0, 76, 0, 0, 16, 39, 0, 76, 1,112, 0, 0, 16, 7, 0, 76, 2,224, 0, 0,255,255, 0,193,
+ 0, 0, 6, 65, 6, 20, 16, 38, 0, 76, 0, 0, 16, 7, 0, 89, 1,194, 0, 0,255,255, 0, 61, 0, 0, 4,127, 4, 96, 16, 6,
+ 0, 89, 0, 0,255,255, 0, 61, 0, 0, 5,189, 6, 20, 16, 38, 0, 89, 0, 0, 16, 7, 0, 76, 4, 68, 0, 0,255,255, 0, 61,
+ 0, 0, 7, 45, 6, 20, 16, 38, 0, 89, 0, 0, 16, 39, 0, 76, 4, 68, 0, 0, 16, 7, 0, 76, 5,180, 0, 0,255,255, 0, 61,
+ 0, 0, 8,157, 6, 20, 16, 38, 0, 89, 0, 0, 16, 39, 0, 76, 4, 68, 0, 0, 16, 39, 0, 76, 5,180, 0, 0, 16, 7, 0, 76,
+ 7, 36, 0, 0,255,255, 0,193, 0, 0, 6, 74, 6, 20, 16, 38, 0, 76, 0, 0, 16, 7, 0, 91, 1,209, 0, 0,255,255, 0, 59,
+ 0, 0, 4,121, 4, 96, 16, 6, 0, 91, 0, 0,255,255, 0, 59, 0, 0, 5,212, 6, 20, 16, 38, 0, 91, 0, 0, 16, 7, 0, 76,
+ 4, 91, 0, 0,255,255, 0, 59, 0, 0, 7, 68, 6, 20, 16, 38, 0, 91, 0, 0, 16, 39, 0, 76, 4, 91, 0, 0, 16, 7, 0, 76,
+ 5,203, 0, 0,255,255, 0,193, 0, 0, 1,121, 6, 20, 16, 6, 0, 79, 0, 0,255,255, 0,113,255,227, 3,231, 4,123, 16, 6,
+ 0, 70, 0, 0,255,255, 0,113,255,227, 4, 90, 6, 20, 16, 6, 0, 71, 0, 0,255,255, 0,186, 0, 0, 7, 29, 4,123, 16, 6,
+ 0, 80, 0, 0, 0, 3, 0,121,255,255, 9,125, 5,213, 0, 13, 0, 22, 0, 31, 0, 0, 1, 32, 0, 17, 16, 0, 41, 1, 32, 0,
+ 17, 16, 0, 33, 1, 51, 32, 0, 17, 16, 0, 33, 35, 3, 17, 35, 32, 0, 17, 16, 0, 33, 6, 53, 1,178, 1,150,254,104,254, 80,
+253,140,254, 80,254,104, 1,150, 1,178, 1,159,244, 1, 53, 1, 31,254,225,254,203,244,202,244,254,203,254,225, 1, 31, 1, 53,
+ 5,213,254,151,254,128,254,126,254,150, 1,106, 1,130, 1,128, 1,105,250,209, 1, 24, 1, 46, 1, 44, 1, 23,251,119, 4,137,
+254,233,254,212,254,210,254,232, 0, 3, 0,201, 0, 0, 5,176, 5,213, 0, 17, 0, 26, 0, 35, 0,251,186, 0, 9, 0, 27, 0,
+ 3, 43,184, 0, 9, 16,186, 0, 14, 0, 23, 0, 3, 43,184, 0, 14, 16,186, 0, 31, 0, 5, 0, 3, 43,184, 0, 31, 16,184, 0,
+ 9, 16,184, 0, 0,208, 65, 5, 0,234, 0, 5, 0,250, 0, 5, 0, 2, 93, 65, 27, 0, 25, 0, 5, 0, 41, 0, 5, 0, 57, 0,
+ 5, 0, 73, 0, 5, 0, 89, 0, 5, 0,105, 0, 5, 0,121, 0, 5, 0,137, 0, 5, 0,153, 0, 5, 0,169, 0, 5, 0,185, 0,
+ 5, 0,201, 0, 5, 0,217, 0, 5, 0, 13, 93,184, 0, 9, 16,184, 0, 18,208, 65, 5, 0,234, 0, 23, 0,250, 0, 23, 0, 2,
+ 93, 65, 27, 0, 25, 0, 23, 0, 41, 0, 23, 0, 57, 0, 23, 0, 73, 0, 23, 0, 89, 0, 23, 0,105, 0, 23, 0,121, 0, 23, 0,
+137, 0, 23, 0,153, 0, 23, 0,169, 0, 23, 0,185, 0, 23, 0,201, 0, 23, 0,217, 0, 23, 0, 13, 93,184, 0, 31, 16,184, 0,
+ 37,220, 0,186, 0, 2, 0, 34, 0, 3, 43,184, 0, 2, 16,186, 0, 28, 0, 8, 0, 3, 43,184, 0, 28, 16,186, 0, 19, 0, 0,
+ 0, 3, 43,184, 0, 19, 16,186, 0, 10, 0, 18, 0, 3, 43,184, 0, 10, 16, 48, 49, 1, 21, 51, 32, 0, 17, 16, 0, 33, 35, 21,
+ 51, 32, 22, 21, 20, 6, 35, 3, 17, 51, 50, 54, 53, 52, 38, 35, 1, 33, 32, 0, 17, 16, 0, 41, 1, 1,147,244, 1, 53, 1, 31,
+254,225,254,203,244, 72, 1, 0,240,241,255, 72, 78,159,147,147,159,254,232, 1,159, 1,178, 1,150,254,104,254, 80,254, 97, 1,
+ 89,179, 1, 24, 1, 46, 1, 44, 1, 23,178,194,207,208,195, 2,158,253,232,129,140,138,129, 1,222,254,151,254,128,254,126,254,
+150, 0, 0, 0, 0, 5, 0,121,255,255, 9,125, 5,213, 0, 17, 0, 26, 0, 40, 0, 49, 0, 67, 0, 0, 1, 51, 32, 0, 17, 16,
+ 0, 33, 35, 53, 51, 32, 54, 53, 52, 38, 33, 35, 25, 1, 51, 50, 22, 21, 20, 6, 35, 19, 32, 0, 17, 16, 0, 41, 1, 32, 0, 17,
+ 16, 0, 33, 19, 35, 34, 38, 53, 52, 54, 59, 1, 53, 35, 32, 6, 21, 20, 22, 33, 51, 21, 35, 32, 0, 17, 16, 0, 33, 51, 5, 96,
+244, 1, 53, 1, 31,254,225,254,203,244, 72, 0,255,241,240,255, 0, 72, 78,159,147,147,159,135, 1,176, 1,152,254,106,254, 78,
+253,140,254, 78,254,106, 1,152, 1,176,213, 78,159,147,147,159, 78, 72,255, 0,240,241, 0,255, 72,244,254,203,254,225, 1, 31,
+ 1, 53,244, 5, 47,254,233,254,212,254,210,254,232,179,195,208,207,194,253, 98, 2, 24,129,138,140,129,254, 33, 1,106, 1,130,
+ 1,128, 1,105,254,151,254,128,254,126,254,150, 1,223,129,140,138,129,134,194,207,208,195,179, 1, 24, 1, 46, 1, 44, 1, 23,
+255,255, 0,115,255,227, 5, 39, 5,240, 16, 6, 1, 72, 0, 0, 0, 1, 0,100, 0,204, 6, 63, 4, 56, 0, 9, 0,129,180, 2,
+ 9, 6, 0, 10, 16,212,212,204, 50, 64, 9, 64, 2, 64, 9, 48, 2, 48, 9, 4, 93, 49, 64, 10, 2, 5, 9, 1, 0, 6, 5,156,
+ 6, 10, 0, 16,212,236, 17, 57, 57,204, 16,204, 48, 64, 12, 8, 9, 9, 0, 8, 7, 8, 7,156, 0, 9, 0, 7, 5, 16,252, 60,
+ 8, 6, 16, 60, 64, 12, 3, 2, 2, 1, 3, 4, 3, 4,156, 1, 2, 1, 7, 5, 16,252, 60, 8, 6, 16, 60,176, 16, 75, 83, 88,
+ 0,179, 3, 2, 8, 9, 16, 60, 16, 60,180, 8,156, 9, 9, 0, 7, 5, 16,236,180, 3,156, 2, 2, 1, 7, 5, 16,236, 89, 19,
+ 53, 1, 23, 7, 33, 21, 33, 23, 7,100, 1,137,120,233, 4,195,251, 61,233,120, 2, 85, 90, 1,137,120,233,170,233,120, 0, 0,
+ 0, 1, 1,163, 0, 0, 5, 15, 5,220, 0, 9, 0,129, 64, 10, 2, 5, 9, 1, 0, 6, 5,156, 6, 10, 16,212,236, 17, 57, 57,
+204, 16,204, 49, 0,180, 2, 9, 6, 0, 10, 16,212,212,204, 50, 64, 9, 79, 2, 79, 9, 63, 2, 63, 9, 4, 93, 48, 64, 12, 8,
+ 9, 9, 0, 8, 7, 8, 7,156, 0, 9, 0, 7, 4, 16,252, 60, 8, 6, 16, 60, 64, 12, 3, 2, 2, 1, 3, 4, 3, 4,156, 1,
+ 2, 1, 7, 4, 16,252, 60, 8, 6, 16, 60,176, 16, 75, 83, 88, 1,179, 3, 2, 8, 9, 16, 60, 16, 60,180, 8,156, 9, 9, 0,
+ 7, 4, 16,236,180, 3,156, 2, 2, 1, 7, 4, 16,236, 89, 1, 51, 1, 7, 39, 17, 35, 17, 7, 39, 3, 45, 90, 1,136,120,232,
+170,234,120, 5,220,254,118,120,234,251, 60, 4,196,234,120, 0, 0, 1, 0,117, 0,204, 6, 80, 4, 56, 0, 9, 0,129,180, 2,
+ 9, 0, 6, 10, 16,212,212,204, 50, 64, 9, 79, 2, 79, 9, 95, 2, 95, 9, 4, 93, 49, 64, 10, 9, 6, 2, 1, 0, 5, 6,156,
+ 5, 10, 0, 16,212,236, 17, 57, 57,204, 16,204, 48, 64, 12, 8, 9, 9, 0, 8, 7, 8, 7,156, 0, 9, 0, 7, 5, 16,252, 60,
+ 8, 6, 16, 60, 64, 12, 3, 2, 2, 1, 3, 4, 3, 4,156, 1, 2, 1, 7, 5, 16,252, 60, 8, 6, 16, 60,176, 16, 75, 83, 88,
+ 0,179, 3, 2, 8, 9, 16, 60, 16, 60,180, 8,156, 9, 9, 0, 7, 5, 16,236,180, 3,156, 2, 2, 1, 7, 5, 16,236, 89, 1,
+ 21, 1, 39, 55, 33, 53, 33, 39, 55, 6, 80,254,119,120,233,251, 61, 4,195,233,120, 2,175, 90,254,119,120,233,170,233,120, 0,
+ 0, 1, 1,163,255,249, 5, 15, 5,213, 0, 9, 0,129, 64, 10, 9, 6, 2, 1, 0, 5, 6,156, 5, 10, 16,212,236, 17, 57, 57,
+204, 16,204, 49, 0,180, 2, 9, 0, 6, 10, 16,212,212,204, 50, 64, 9, 64, 2, 64, 9, 80, 2, 80, 9, 4, 93, 48, 64, 12, 8,
+ 9, 9, 0, 8, 7, 8, 7,156, 0, 9, 0, 7, 4, 16,252, 60, 8, 6, 16, 60, 64, 12, 3, 2, 2, 1, 3, 4, 3, 4,156, 1,
+ 2, 1, 7, 4, 16,252, 60, 8, 6, 16, 60,176, 16, 75, 83, 88, 1,179, 3, 2, 8, 9, 16, 60, 16, 60,180, 8,156, 9, 9, 0,
+ 7, 4, 16,236,180, 3,156, 2, 2, 1, 7, 4, 16,236, 89, 5, 35, 1, 55, 23, 17, 51, 17, 55, 23, 3,135, 90,254,118,120,234,
+170,232,120, 7, 1,138,120,234, 4,196,251, 60,234,120, 0, 0, 0, 1, 0,100, 0,204, 6, 80, 4, 56, 0, 15, 0,218,182, 7,
+ 10, 9, 2, 15, 0, 16, 16,212,204, 50,212,204, 50, 64, 13, 80, 2, 80, 15, 95, 10, 95, 7, 79, 10, 79, 7, 6, 93, 49, 0, 64,
+ 15, 7, 2, 4, 10, 15, 0, 1, 8, 9, 4, 13, 4,156, 13, 16, 16,212,236, 17, 23, 57,204, 50, 16,204, 50, 48, 64, 12, 14, 15,
+ 15, 0, 14, 13, 14, 13,156, 0, 15, 0, 7, 5, 16,252, 60, 8, 6, 16, 60, 64, 12, 3, 2, 2, 1, 3, 4, 3, 4,156, 1, 2,
+ 1, 7, 5, 16,252, 60, 8, 6, 16, 60, 64, 12, 11, 10, 10, 9, 11, 12, 11, 12,156, 9, 9, 10, 7, 5, 16,252, 60, 8, 6, 16,
+ 60, 64, 12, 6, 7, 7, 8, 6, 5, 6, 5,156, 8, 7, 8, 7, 5, 16,252, 60, 8, 6, 16, 60,176, 16, 75, 83, 88, 0,183, 11,
+ 10, 6, 7, 3, 2, 14, 15, 16, 60, 16, 60, 16, 60, 16, 60,180, 14,156, 15, 15, 0, 7, 5, 16,236,180, 3,156, 2, 2, 1, 7,
+ 5, 16,236,180, 11,156, 10, 10, 9, 7, 5, 16,236,180, 6,156, 7, 7, 8, 7, 5, 16,236, 89, 19, 53, 1, 23, 7, 33, 39, 55,
+ 1, 21, 1, 39, 55, 33, 23, 7,100, 1,137,120,233, 3,188,233,120, 1,137,254,119,120,233,252, 68,233,120, 2, 85, 90, 1,137,
+120,233,233,120,254,119, 90,254,119,120,233,233,120, 0, 0, 0, 0, 1, 1,163,255,239, 5, 15, 5,220, 0, 15, 0,222, 64, 15,
+ 7, 2, 4, 10, 15, 0, 1, 8, 9, 4, 13, 4,156, 13, 16, 16,212,236, 17, 23, 57,204, 50, 16,204, 50, 49, 0,182, 7, 10, 9,
+ 2, 15, 0, 16, 16,212,204, 50,212,204, 50, 64, 17, 95, 2, 95, 15, 80, 10, 80, 7, 79, 2, 79, 15, 64, 10, 64, 7, 8, 93, 48,
+ 64, 12, 14, 15, 15, 0, 14, 13, 14, 13,156, 0, 15, 0, 7, 4, 16,252, 60, 8, 6, 16, 60, 64, 12, 3, 2, 2, 1, 3, 4, 3,
+ 4,156, 1, 2, 1, 7, 4, 16,252, 60, 8, 6, 16, 60, 64, 12, 11, 10, 10, 9, 11, 12, 11, 12,156, 9, 9, 10, 7, 4, 16,252,
+ 60, 8, 6, 16, 60, 64, 12, 6, 7, 7, 8, 6, 5, 6, 5,156, 8, 7, 8, 7, 4, 16,252, 60, 8, 6, 16, 60,176, 16, 75, 83,
+ 88, 1,183, 11, 10, 6, 7, 3, 2, 14, 15, 16, 60, 16, 60, 16, 60, 16, 60,180, 14,156, 15, 15, 0, 7, 4, 16,236,180, 3,156,
+ 2, 2, 1, 7, 4, 16,236,180, 11,156, 10, 10, 9, 7, 4, 16,236,180, 6,156, 7, 7, 8, 7, 4, 16,236, 89, 1, 51, 1, 7,
+ 39, 17, 55, 23, 1, 35, 1, 55, 23, 17, 7, 39, 3, 45, 90, 1,136,120,232,232,120,254,120, 90,254,118,120,234,234,120, 5,220,
+254,118,120,234,252, 67,234,120,254,118, 1,138,120,234, 3,189,234,120, 0, 0, 0, 1, 1, 32, 0, 52, 5,159, 4,179, 0, 9,
+ 0, 0, 1, 55, 33, 21, 33, 1, 7, 1, 17, 35, 1, 32, 63, 2, 44,254,182, 3, 94,120,252,162,169, 4,116, 63,169,252,162,120,
+ 3, 94,254,182, 0, 1, 1, 32, 0, 52, 5,159, 4,179, 0, 9, 0, 0, 1, 23, 17, 35, 17, 1, 39, 1, 33, 53, 5, 96, 63,169,
+252,162,120, 3, 94,254,182, 4,179, 63,253,212, 1, 74,252,162,120, 3, 94,169, 0, 1, 1, 32, 0, 52, 5,159, 4,179, 0, 9,
+ 0, 0, 37, 7, 33, 53, 33, 1, 55, 1, 17, 51, 5,159, 63,253,212, 1, 74,252,162,120, 3, 94,169,115, 63,169, 3, 94,120,252,
+162, 1, 74, 0, 0, 1, 1, 32, 0, 52, 5,159, 4,179, 0, 9, 0, 0, 37, 39, 17, 51, 17, 1, 23, 1, 33, 21, 1, 95, 63,169,
+ 3, 94,120,252,162, 1, 74, 52, 63, 2, 44,254,182, 3, 94,120,252,162,169, 0, 0, 1, 0,100, 0,204, 5, 63, 5, 3, 0, 11,
+ 0, 0, 1, 33, 23, 7, 1, 53, 1, 23, 7, 33, 17, 51, 5, 63,252, 61,233,120,254,119, 1,137,120,233, 3, 25,170, 2, 45,233,
+120, 1,137, 90, 1,137,120,233, 2, 44, 0, 0, 0, 1, 0,217, 2, 45, 5,219, 2,215, 0, 3, 0, 17,182, 0,156, 2, 4, 1,
+ 0, 4, 16,212,196, 49, 0, 16,212,236, 48, 19, 33, 21, 33,217, 5, 2,250,254, 2,215,170, 0, 0, 2, 0,217, 0, 0, 5,219,
+ 5, 4, 0, 11, 0, 15, 0, 0, 33, 35, 17, 33, 53, 33, 17, 51, 17, 33, 21, 33, 1, 53, 33, 21, 3,174,168,253,211, 2, 45,168,
+ 2, 45,253,211,253, 43, 5, 2, 1,131,170, 1,131,254,125,170, 2,215,170,170, 0, 2, 0,217, 0, 0, 5,219, 5,213, 0, 11,
+ 0, 15, 0, 87,186, 0, 5, 0, 6, 0, 3, 43,184, 0, 5, 16,184, 0, 0,208,184, 0, 6, 16,184, 0, 10,208,184, 0, 6, 16,
+184, 0, 12,208,184, 0, 5, 16,184, 0, 13,208, 0,184, 0, 5, 47,186, 0, 13, 0, 14, 0, 3, 43,184, 0, 13, 16,186, 0, 2,
+ 0, 3, 0, 3, 43,184, 0, 2, 16,184, 0, 3, 16,184, 0, 7,208,184, 0, 2, 16,184, 0, 9,208, 48, 49, 1, 17, 33, 21, 33,
+ 17, 35, 17, 33, 53, 33, 25, 1, 51, 21, 35, 3,174, 2, 45,253,211,168,253,211, 2, 45,168,168, 4,160,254, 5,170,254, 5, 1,
+251,170, 1,251, 1, 53,204, 0, 0, 1,254,137,255,227, 2,205, 5,240, 0, 3, 0, 43, 64, 19, 0, 15, 1, 2, 1, 2, 15, 3,
+ 0, 3, 66, 2,140, 0,145, 4, 1, 3, 4, 16,212,204, 49, 0, 16,228,228, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 5,237, 89,
+ 34, 1, 51, 1, 35, 2, 45,160,252, 92,160, 5,240,249,243, 0,255,255, 1,138,255,146, 4, 60, 6, 37, 16, 3, 0, 63, 1,138,
+ 0, 80, 0, 0,255,255, 0,190, 0,175, 4, 68, 4, 85, 16, 7, 0, 13, 0,129,254,101, 0, 0,255,255, 1, 68, 1, 71, 3,190,
+ 3,194, 16, 7, 0,114, 0,129,253,210, 0, 0, 0, 1, 0,219, 2, 72, 1,174, 3, 70, 0, 3, 0, 18,183, 2,131, 0, 4, 1,
+ 25, 0, 4, 16,212,236, 49, 0, 16,212,236, 48, 19, 51, 21, 35,219,211,211, 3, 70,254, 0, 0, 0, 1, 0, 61,255,215, 5, 25,
+ 6,125, 0, 10, 0, 42, 64, 24, 10, 9, 8, 7, 6, 5, 11, 2, 4, 2, 0, 11, 10, 9, 7, 6, 5, 4, 3, 0, 8, 1, 8, 11,
+ 16,212,204, 23, 57, 49, 0, 16,212,204,196, 17, 18, 23, 57, 48, 1, 51, 21, 35, 1, 35, 1, 7, 39, 37, 1, 4, 92,189,115,253,
+174, 66,254,193,125, 25, 1, 27, 1, 0, 6,125, 96,249,186, 3,115, 45, 80, 98,253, 59, 0, 0,255,255, 0, 61,255,215, 5, 25,
+ 7,208, 18, 34, 6, 95, 0, 0, 16, 3, 0,117, 0,115, 1,224,255,255, 0, 61,255,215, 5, 25, 7,191, 18, 34, 6, 95, 0, 0,
+ 16, 3, 5,206, 0,115, 1,224, 0, 2, 0,221, 0,221, 4,141, 3,238, 0, 11, 0, 37, 0, 0, 1, 46, 1, 35, 34, 6, 21, 20,
+ 22, 51, 50, 54, 1, 34, 38, 39, 14, 1, 35, 34, 38, 53, 52, 54, 51, 50, 22, 23, 62, 1, 51, 21, 34, 6, 7, 30, 1, 51, 3, 25,
+ 49,133, 85,102,127,118, 89, 82,134, 1,189, 73,149, 79, 70,157, 94,136,186,167,134, 95,153, 72, 68,158, 97, 43,133, 74, 49,134,
+ 67, 2,154, 88, 88,132,106,101,134,136,254,232,119,139,135,127,223,166,175,216,126,138,138,131,150,135,162, 88, 90, 0, 0, 0,
+ 0, 3, 0,221, 0,221, 5,207, 3,238, 0, 11, 0, 23, 0, 47, 0,255, 64, 29, 45, 27, 21, 9, 33, 3, 0, 36, 24, 4, 21, 15,
+ 39, 33, 21, 27, 15, 33, 48, 12, 0, 36, 24, 18, 6, 42, 18, 30, 48, 16,212,196,212,196, 17, 57, 57, 57, 57, 49, 0, 16,212,196,
+212,196, 16,192, 17, 18, 23, 57, 18, 57, 17, 18, 57, 48, 64,190, 5, 2, 5, 3, 5, 4, 0, 5, 0, 6, 0, 7, 5, 8, 5, 9,
+ 5, 10, 10, 16, 15, 17, 15, 18, 15, 19, 10, 20, 21, 2, 21, 3, 21, 4, 16, 5, 16, 6, 16, 7, 21, 8, 21, 9, 21, 10, 26, 14,
+ 26, 15, 26, 16, 31, 17, 31, 18, 31, 19, 26, 20, 26, 21, 26, 22, 36, 2, 36, 3, 36, 4, 32, 5, 32, 6, 32, 7, 36, 8, 36, 9,
+ 36, 10, 42, 14, 42, 15, 42, 16, 47, 17, 47, 18, 47, 19, 42, 20, 42, 21, 42, 22, 53, 2, 53, 3, 53, 4, 48, 5, 48, 6, 48, 7,
+ 53, 8, 53, 9, 53, 10, 58, 14, 58, 15, 58, 16, 63, 17, 63, 18, 63, 19, 58, 20, 58, 21, 58, 22, 69, 2, 69, 3, 69, 4, 64, 5,
+ 64, 6, 64, 7, 69, 8, 69, 9, 69, 10, 74, 14, 74, 15, 74, 16, 79, 17, 79, 18, 79, 19, 74, 20, 74, 21, 74, 22, 86,180, 31,176,
+ 32,176, 33,176, 34,176, 38,176, 39,176, 40,180, 41, 8, 93, 1, 93, 1, 30, 1, 51, 50, 54, 53, 52, 38, 35, 34, 6, 7, 46, 1,
+ 35, 34, 6, 21, 20, 22, 51, 50, 54, 23, 14, 1, 35, 34, 38, 53, 52, 54, 51, 50, 22, 23, 62, 1, 51, 50, 22, 21, 20, 6, 35, 34,
+ 38, 3,147, 49,134, 84,101,128,118, 89, 82,133,196, 49,133, 85,102,127,118, 89, 82,134,144, 70,157, 94,136,186,167,134, 95,153,
+ 72, 68,158, 97,134,188,167,134, 94,149, 2, 47, 88, 90,135,105,101,134,135, 55, 88, 88,132,106,101,134,136, 22,135,127,223,166,
+175,216,126,138,138,131,225,167,175,214,119, 0, 0, 6, 0,247, 0, 1, 7, 9, 6, 19, 0, 3, 0, 49, 0, 59, 0, 70, 0, 79,
+ 0, 89, 0, 0, 1, 33, 17, 33, 17, 21, 20, 6, 32, 38, 53, 52, 54, 59, 1, 17, 35, 34, 38, 53, 52, 54, 32, 22, 29, 1, 33, 53,
+ 52, 54, 51, 50, 22, 21, 20, 6, 43, 1, 17, 51, 50, 22, 21, 20, 6, 35, 34, 38, 61, 1, 1, 53, 52, 38, 35, 34, 6, 20, 22, 51,
+ 19, 35, 34, 6, 21, 20, 22, 51, 50, 54, 53, 1, 51, 50, 54, 52, 38, 34, 6, 21, 17, 21, 20, 22, 50, 54, 53, 52, 38, 35, 3,108,
+ 1, 40,254,216,185,254,252,184,184,127,170,170,127,184,184, 1, 4,185, 1, 40,185,130,131,183,183,128,170,170,128,183,183,131,
+130,185,254, 68, 98, 69, 68, 98, 98, 69,166,166, 69, 98, 98, 69, 68, 98, 2, 80,167, 68, 98, 97,138, 98, 98,138, 97, 98, 68, 2,
+118, 1, 40,254, 68,170,128,183,184,131,128,186, 1, 40,186,129,130,184,183,128,170,170,128,183,184,130,129,186,254,216,186,128,
+131,184,183,128,170, 2, 80,167, 69, 97, 97,138, 98,253,176, 98, 68, 69, 98, 98, 68, 2,247, 98,138, 97, 97, 69,253, 9,167, 68,
+ 98, 98, 69, 68, 98, 0, 0, 0, 0, 1, 0,217, 1, 31, 5,219, 3, 94, 0, 5, 0, 0, 1, 33, 17, 51, 17, 33, 5,219,250,254,
+168, 4, 90, 1, 31, 2, 63,254,107, 0, 0, 0, 0, 2, 0,172, 0, 0, 7, 84, 5,200, 0, 7, 0, 11, 0, 0, 19, 33, 1, 33,
+ 21, 33, 1, 33, 37, 33, 21, 33,172, 2, 66, 2,154, 1,204,253,188,253,102,254, 54, 3,244, 2,180,253, 76, 5,200,250,204,148,
+ 5, 52,148,148, 0, 1, 0,183,254,242, 2,123, 6, 18, 0, 5, 0, 0, 19, 1, 51, 9, 1, 35,183, 1, 26,170,254,230, 1, 26,
+170, 2,130,252,112, 3,144, 3,144, 0, 0, 0, 0, 1, 0,164,254,242, 2,104, 6, 18, 0, 5, 0, 0, 9, 1, 35, 9, 1, 51,
+ 2,104,254,230,170, 1, 26,254,230,170, 2,130,252,112, 3,144, 3,144, 0, 0, 0, 3, 0,152,255,236, 6,148, 5,232, 0, 13,
+ 0, 27, 0, 38, 0,219,186, 0, 14, 0, 6, 0, 3, 43,184, 0, 14, 16,186, 0, 35, 0, 29, 0, 3, 43,184, 0, 35, 16,186, 0,
+ 0, 0, 20, 0, 3, 43,184, 0, 0, 16, 65, 27, 0, 22, 0, 14, 0, 38, 0, 14, 0, 54, 0, 14, 0, 70, 0, 14, 0, 86, 0, 14,
+ 0,102, 0, 14, 0,118, 0, 14, 0,134, 0, 14, 0,150, 0, 14, 0,166, 0, 14, 0,182, 0, 14, 0,198, 0, 14, 0,214, 0, 14,
+ 0, 13, 93, 65, 5, 0,229, 0, 14, 0,245, 0, 14, 0, 2, 93, 65, 5, 0,234, 0, 20, 0,250, 0, 20, 0, 2, 93, 65, 27, 0,
+ 25, 0, 20, 0, 41, 0, 20, 0, 57, 0, 20, 0, 73, 0, 20, 0, 89, 0, 20, 0,105, 0, 20, 0,121, 0, 20, 0,137, 0, 20, 0,
+153, 0, 20, 0,169, 0, 20, 0,185, 0, 20, 0,201, 0, 20, 0,217, 0, 20, 0, 13, 93, 0,186, 0, 17, 0, 3, 0, 3, 43,184,
+ 0, 17, 16,186, 0, 10, 0, 24, 0, 3, 43,184, 0, 10, 16,186, 0, 36, 0, 37, 0, 3, 43,184, 0, 36, 16,184, 0, 28,208, 48,
+ 49, 1, 16, 0, 33, 32, 0, 17, 52, 18, 36, 51, 50, 4, 18, 5, 16, 0, 33, 32, 0, 17, 52, 2, 36, 35, 34, 4, 2, 1, 51, 17,
+ 7, 53, 37, 51, 17, 51, 21, 33, 6,148,254, 63,254,194,254,196,254, 63,206, 1,113,190,193, 1,113,205,250, 87, 1,143, 1, 28,
+ 1, 28, 1,143,182,254,184,173,173,254,184,182, 1,124,217,236, 1, 1,161,218,253,151, 2,234,254,193,254, 65, 1,191, 1, 63,
+198, 1,114,198,198,254,144,200,254,228,254,112, 1,144, 1, 28,179, 1, 71,177,177,254,185,253,255, 2,126, 43,152, 47,252,230,
+142, 0, 0, 0, 0, 3, 0,152,255,236, 6,148, 5,232, 0, 13, 0, 27, 0, 56, 1, 63,186, 0, 14, 0, 6, 0, 3, 43,184, 0,
+ 14, 16,186, 0, 51, 0, 38, 0, 3, 43,184, 0, 51, 16,186, 0, 0, 0, 20, 0, 3, 43,184, 0, 0, 16, 65, 27, 0, 22, 0, 14,
+ 0, 38, 0, 14, 0, 54, 0, 14, 0, 70, 0, 14, 0, 86, 0, 14, 0,102, 0, 14, 0,118, 0, 14, 0,134, 0, 14, 0,150, 0, 14,
+ 0,166, 0, 14, 0,182, 0, 14, 0,198, 0, 14, 0,214, 0, 14, 0, 13, 93, 65, 5, 0,229, 0, 14, 0,245, 0, 14, 0, 2, 93,
+ 65, 5, 0,234, 0, 20, 0,250, 0, 20, 0, 2, 93, 65, 27, 0, 25, 0, 20, 0, 41, 0, 20, 0, 57, 0, 20, 0, 73, 0, 20, 0,
+ 89, 0, 20, 0,105, 0, 20, 0,121, 0, 20, 0,137, 0, 20, 0,153, 0, 20, 0,169, 0, 20, 0,185, 0, 20, 0,201, 0, 20, 0,
+217, 0, 20, 0, 13, 93,184, 0, 51, 16,184, 0, 29,208,184, 0, 29, 47, 65, 5, 0,234, 0, 38, 0,250, 0, 38, 0, 2, 93, 65,
+ 27, 0, 25, 0, 38, 0, 41, 0, 38, 0, 57, 0, 38, 0, 73, 0, 38, 0, 89, 0, 38, 0,105, 0, 38, 0,121, 0, 38, 0,137, 0,
+ 38, 0,153, 0, 38, 0,169, 0, 38, 0,185, 0, 38, 0,201, 0, 38, 0,217, 0, 38, 0, 13, 93,186, 0, 44, 0, 6, 0, 0, 17,
+ 18, 57, 0,186, 0, 17, 0, 3, 0, 3, 43,184, 0, 17, 16,186, 0, 10, 0, 24, 0, 3, 43,184, 0, 10, 16,186, 0, 29, 0, 30,
+ 0, 3, 43,184, 0, 29, 16,186, 0, 48, 0, 41, 0, 3, 43,184, 0, 48, 16, 48, 49, 1, 16, 0, 33, 32, 0, 17, 52, 18, 36, 51,
+ 50, 4, 18, 5, 16, 0, 33, 32, 0, 17, 52, 2, 36, 35, 34, 4, 2, 1, 33, 21, 33, 53, 54, 36, 55, 62, 1, 53, 52, 38, 35, 34,
+ 6, 7, 53, 62, 1, 51, 50, 22, 21, 20, 6, 7, 14, 1, 6,148,254, 63,254,194,254,196,254, 63,206, 1,113,190,193, 1,113,205,
+250, 87, 1,143, 1, 28, 1, 28, 1,143,182,254,184,173,173,254,184,182, 2, 79, 1,180,253, 92, 82, 1, 6, 33, 62, 47, 95, 78,
+ 59,132,115, 97,145, 61,163,197, 48, 62, 17,178, 2,234,254,193,254, 65, 1,191, 1, 63,198, 1,114,198,198,254,144,200,254,228,
+254,112, 1,144, 1, 28,179, 1, 71,177,177,254,185,253,255,142,129, 77,241, 34, 63, 85, 40, 63, 78, 38, 58,171, 36, 31,151,125,
+ 58,105, 70, 18,167, 0, 0, 0, 0, 3, 0,152,255,236, 6,148, 5,232, 0, 13, 0, 27, 0, 68, 1,181,186, 0, 14, 0, 6, 0,
+ 3, 43,184, 0, 14, 16,186, 0, 66, 0, 53, 0, 3, 43,184, 0, 66, 16,186, 0, 0, 0, 20, 0, 3, 43,184, 0, 0, 16, 65, 27,
+ 0, 22, 0, 14, 0, 38, 0, 14, 0, 54, 0, 14, 0, 70, 0, 14, 0, 86, 0, 14, 0,102, 0, 14, 0,118, 0, 14, 0,134, 0, 14,
+ 0,150, 0, 14, 0,166, 0, 14, 0,182, 0, 14, 0,198, 0, 14, 0,214, 0, 14, 0, 13, 93, 65, 5, 0,229, 0, 14, 0,245, 0,
+ 14, 0, 2, 93, 65, 5, 0,234, 0, 20, 0,250, 0, 20, 0, 2, 93, 65, 27, 0, 25, 0, 20, 0, 41, 0, 20, 0, 57, 0, 20, 0,
+ 73, 0, 20, 0, 89, 0, 20, 0,105, 0, 20, 0,121, 0, 20, 0,137, 0, 20, 0,153, 0, 20, 0,169, 0, 20, 0,185, 0, 20, 0,
+201, 0, 20, 0,217, 0, 20, 0, 13, 93, 65, 5, 0,234, 0, 53, 0,250, 0, 53, 0, 2, 93, 65, 27, 0, 25, 0, 53, 0, 41, 0,
+ 53, 0, 57, 0, 53, 0, 73, 0, 53, 0, 89, 0, 53, 0,105, 0, 53, 0,121, 0, 53, 0,137, 0, 53, 0,153, 0, 53, 0,169, 0,
+ 53, 0,185, 0, 53, 0,201, 0, 53, 0,217, 0, 53, 0, 13, 93,186, 0, 28, 0, 53, 0, 66, 17, 18, 57,186, 0, 44, 0, 53, 0,
+ 66, 17, 18, 57,184, 0, 44, 47, 65, 5, 0,234, 0, 44, 0,250, 0, 44, 0, 2, 93, 65, 27, 0, 25, 0, 44, 0, 41, 0, 44, 0,
+ 57, 0, 44, 0, 73, 0, 44, 0, 89, 0, 44, 0,105, 0, 44, 0,121, 0, 44, 0,137, 0, 44, 0,153, 0, 44, 0,169, 0, 44, 0,
+185, 0, 44, 0,201, 0, 44, 0,217, 0, 44, 0, 13, 93,184, 0, 31,220,186, 0, 38, 0, 6, 0, 0, 17, 18, 57,186, 0, 59, 0,
+ 6, 0, 0, 17, 18, 57, 0,186, 0, 17, 0, 3, 0, 3, 43,184, 0, 17, 16,186, 0, 10, 0, 24, 0, 3, 43,184, 0, 10, 16,186,
+ 0, 41, 0, 34, 0, 3, 43,184, 0, 41, 16,186, 0, 63, 0, 56, 0, 3, 43,184, 0, 63, 16,186, 0, 50, 0, 47, 0, 3, 43,184,
+ 0, 50, 16,186, 0, 28, 0, 47, 0, 50, 17, 18, 57, 48, 49, 1, 16, 0, 33, 32, 0, 17, 52, 18, 36, 51, 50, 4, 18, 5, 16, 0,
+ 33, 32, 0, 17, 52, 2, 36, 35, 34, 4, 2, 5, 30, 1, 21, 20, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 43, 1,
+ 53, 51, 50, 54, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 21, 20, 6, 6,148,254, 63,254,194,254,196,254, 63,206, 1,
+113,190,193, 1,113,205,250, 87, 1,143, 1, 28, 1, 28, 1,143,182,254,184,173,173,254,184,182, 3,185, 13,118,216,195, 64,136,
+ 88, 91,125, 68,117,115,107, 99,140,145, 90, 88, 92, 91, 52,121,107, 95,136, 61,161,193,104, 2,234,254,193,254, 65, 1,191, 1,
+ 63,198, 1,114,198,198,254,144,200,254,228,254,112, 1,144, 1, 28,179, 1, 71,177,177,254,185,150, 3,129, 93,141,156, 23, 27,
+168, 48, 28, 79, 76, 71, 78,140, 60, 58, 60, 63, 21, 32,151, 24, 20,137,115, 81,114, 0, 0, 0, 0, 4, 0,152,255,236, 6,148,
+ 5,232, 0, 13, 0, 27, 0, 30, 0, 41, 0,243,186, 0, 14, 0, 6, 0, 3, 43,184, 0, 14, 16,186, 0, 32, 0, 28, 0, 3, 43,
+184, 0, 32, 16,186, 0, 0, 0, 20, 0, 3, 43,184, 0, 0, 16, 65, 27, 0, 22, 0, 14, 0, 38, 0, 14, 0, 54, 0, 14, 0, 70,
+ 0, 14, 0, 86, 0, 14, 0,102, 0, 14, 0,118, 0, 14, 0,134, 0, 14, 0,150, 0, 14, 0,166, 0, 14, 0,182, 0, 14, 0,198,
+ 0, 14, 0,214, 0, 14, 0, 13, 93, 65, 5, 0,229, 0, 14, 0,245, 0, 14, 0, 2, 93, 65, 5, 0,234, 0, 20, 0,250, 0, 20,
+ 0, 2, 93, 65, 27, 0, 25, 0, 20, 0, 41, 0, 20, 0, 57, 0, 20, 0, 73, 0, 20, 0, 89, 0, 20, 0,105, 0, 20, 0,121, 0,
+ 20, 0,137, 0, 20, 0,153, 0, 20, 0,169, 0, 20, 0,185, 0, 20, 0,201, 0, 20, 0,217, 0, 20, 0, 13, 93,184, 0, 32, 16,
+184, 0, 36,208,184, 0, 28, 16,184, 0, 38,208, 0,186, 0, 17, 0, 3, 0, 3, 43,184, 0, 17, 16,186, 0, 10, 0, 24, 0, 3,
+ 43,184, 0, 10, 16,186, 0, 34, 0, 35, 0, 3, 43,184, 0, 34, 16,184, 0, 29,208,184, 0, 35, 16,184, 0, 39,208, 48, 49, 1,
+ 16, 0, 33, 32, 0, 17, 52, 18, 36, 51, 50, 4, 18, 5, 16, 0, 33, 32, 0, 17, 52, 2, 36, 35, 34, 4, 2, 37, 1, 33, 3, 51,
+ 17, 51, 21, 35, 21, 35, 53, 33, 53, 6,148,254, 63,254,194,254,196,254, 63,206, 1,113,190,193, 1,113,205,250, 87, 1,143, 1,
+ 28, 1, 28, 1,143,182,254,184,173,173,254,184,182, 2,191,254,243, 1, 13, 24,206,141,141,182,254, 67, 2,234,254,193,254, 65,
+ 1,191, 1, 63,198, 1,114,198,198,254,144,200,254,228,254,112, 1,144, 1, 28,179, 1, 71,177,177,254,185, 79,254,130, 2, 72,
+253,184,141,211,211,142, 0, 0, 0, 3, 0,152,255,236, 6,148, 5,232, 0, 13, 0, 27, 0, 57, 1, 75,186, 0, 14, 0, 6, 0,
+ 3, 43,184, 0, 14, 16,186, 0, 31, 0, 28, 0, 3, 43,184, 0, 31, 16,186, 0, 38, 0, 51, 0, 3, 43,184, 0, 38, 16,186, 0,
+ 0, 0, 20, 0, 3, 43,184, 0, 0, 16, 65, 27, 0, 22, 0, 14, 0, 38, 0, 14, 0, 54, 0, 14, 0, 70, 0, 14, 0, 86, 0, 14,
+ 0,102, 0, 14, 0,118, 0, 14, 0,134, 0, 14, 0,150, 0, 14, 0,166, 0, 14, 0,182, 0, 14, 0,198, 0, 14, 0,214, 0, 14,
+ 0, 13, 93, 65, 5, 0,229, 0, 14, 0,245, 0, 14, 0, 2, 93, 65, 5, 0,234, 0, 20, 0,250, 0, 20, 0, 2, 93, 65, 27, 0,
+ 25, 0, 20, 0, 41, 0, 20, 0, 57, 0, 20, 0, 73, 0, 20, 0, 89, 0, 20, 0,105, 0, 20, 0,121, 0, 20, 0,137, 0, 20, 0,
+153, 0, 20, 0,169, 0, 20, 0,185, 0, 20, 0,201, 0, 20, 0,217, 0, 20, 0, 13, 93,186, 0, 45, 0, 6, 0, 0, 17, 18, 57,
+ 65, 5, 0,234, 0, 51, 0,250, 0, 51, 0, 2, 93, 65, 27, 0, 25, 0, 51, 0, 41, 0, 51, 0, 57, 0, 51, 0, 73, 0, 51, 0,
+ 89, 0, 51, 0,105, 0, 51, 0,121, 0, 51, 0,137, 0, 51, 0,153, 0, 51, 0,169, 0, 51, 0,185, 0, 51, 0,201, 0, 51, 0,
+217, 0, 51, 0, 13, 93, 0,186, 0, 17, 0, 3, 0, 3, 43,184, 0, 17, 16,186, 0, 10, 0, 24, 0, 3, 43,184, 0, 10, 16,186,
+ 0, 48, 0, 41, 0, 3, 43,184, 0, 48, 16,186, 0, 29, 0, 30, 0, 3, 43,184, 0, 29, 16,186, 0, 35, 0, 54, 0, 3, 43,184,
+ 0, 35, 16, 48, 49, 1, 16, 0, 33, 32, 0, 17, 52, 18, 36, 51, 50, 4, 18, 5, 16, 0, 33, 32, 0, 17, 52, 2, 36, 35, 34, 4,
+ 2, 1, 33, 21, 33, 21, 6, 54, 51, 50, 22, 21, 20, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 35, 34, 6, 7, 6,
+148,254, 63,254,194,254,196,254, 63,206, 1,113,190,193, 1,113,205,250, 87, 1,143, 1, 28, 1, 28, 1,143,182,254,184,173,173,
+254,184,182, 1,152, 2, 61,254,111, 3, 63, 31,176,207,213,190, 64,133, 88, 95,119, 68,104,118,118,104, 50,101, 89, 2,234,254,
+193,254, 65, 1,191, 1, 63,198, 1,114,198,198,254,144,200,254,228,254,112, 1,144, 1, 28,179, 1, 71,177,177,254,185, 1, 25,
+142,171, 1, 10,176,149,152,172, 20, 24,172, 47, 27, 97, 85, 86, 97, 20, 37, 0, 0, 4, 0,152,255,236, 6,148, 5,232, 0, 13,
+ 0, 27, 0, 39, 0, 64, 1,145,186, 0, 14, 0, 6, 0, 3, 43,184, 0, 14, 16,186, 0, 31, 0, 59, 0, 3, 43,184, 0, 31, 16,
+186, 0, 53, 0, 37, 0, 3, 43,184, 0, 53, 16,186, 0, 0, 0, 20, 0, 3, 43,184, 0, 0, 16, 65, 27, 0, 22, 0, 14, 0, 38,
+ 0, 14, 0, 54, 0, 14, 0, 70, 0, 14, 0, 86, 0, 14, 0,102, 0, 14, 0,118, 0, 14, 0,134, 0, 14, 0,150, 0, 14, 0,166,
+ 0, 14, 0,182, 0, 14, 0,198, 0, 14, 0,214, 0, 14, 0, 13, 93, 65, 5, 0,229, 0, 14, 0,245, 0, 14, 0, 2, 93, 65, 5,
+ 0,234, 0, 20, 0,250, 0, 20, 0, 2, 93, 65, 27, 0, 25, 0, 20, 0, 41, 0, 20, 0, 57, 0, 20, 0, 73, 0, 20, 0, 89, 0,
+ 20, 0,105, 0, 20, 0,121, 0, 20, 0,137, 0, 20, 0,153, 0, 20, 0,169, 0, 20, 0,185, 0, 20, 0,201, 0, 20, 0,217, 0,
+ 20, 0, 13, 93, 65, 27, 0, 22, 0, 31, 0, 38, 0, 31, 0, 54, 0, 31, 0, 70, 0, 31, 0, 86, 0, 31, 0,102, 0, 31, 0,118,
+ 0, 31, 0,134, 0, 31, 0,150, 0, 31, 0,166, 0, 31, 0,182, 0, 31, 0,198, 0, 31, 0,214, 0, 31, 0, 13, 93, 65, 5, 0,
+229, 0, 31, 0,245, 0, 31, 0, 2, 93, 65, 5, 0,234, 0, 37, 0,250, 0, 37, 0, 2, 93, 65, 27, 0, 25, 0, 37, 0, 41, 0,
+ 37, 0, 57, 0, 37, 0, 73, 0, 37, 0, 89, 0, 37, 0,105, 0, 37, 0,121, 0, 37, 0,137, 0, 37, 0,153, 0, 37, 0,169, 0,
+ 37, 0,185, 0, 37, 0,201, 0, 37, 0,217, 0, 37, 0, 13, 93,186, 0, 41, 0, 37, 0, 53, 17, 18, 57, 0,186, 0, 17, 0, 3,
+ 0, 3, 43,184, 0, 17, 16,186, 0, 10, 0, 24, 0, 3, 43,184, 0, 10, 16,186, 0, 34, 0, 56, 0, 3, 43,184, 0, 34, 16,186,
+ 0, 62, 0, 44, 0, 3, 43,184, 0, 62, 16,186, 0, 50, 0, 28, 0, 3, 43,184, 0, 50, 16, 48, 49, 1, 16, 0, 33, 32, 0, 17,
+ 52, 18, 36, 51, 50, 4, 18, 5, 16, 0, 33, 32, 0, 17, 52, 2, 36, 35, 34, 4, 2, 5, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52,
+ 38, 19, 21, 46, 1, 35, 34, 6, 7, 6, 54, 51, 50, 22, 21, 20, 6, 35, 34, 38, 53, 52, 18, 51, 50, 22, 6,148,254, 63,254,194,
+254,196,254, 63,206, 1,113,190,193, 1,113,205,250, 87, 1,143, 1, 28, 1, 28, 1,143,182,254,184,173,173,254,184,182, 2,161,
+ 78, 92, 92, 78, 78, 92, 92,212, 84, 97, 47,119,127, 5, 9,128, 78,160,186,194,160,185,192,234,200, 53,106, 2,234,254,193,254,
+ 65, 1,191, 1, 63,198, 1,114,198,198,254,144,200,254,228,254,112, 1,144, 1, 28,179, 1, 71,177,177,254,185,159, 98, 91, 90,
+ 98, 98, 90, 91, 98, 1,157,156, 35, 22,148, 80, 11, 61,177,148,145,179,253,231,218, 1, 11, 19, 0, 3, 0,152,255,236, 6,148,
+ 5,232, 0, 13, 0, 27, 0, 34, 0,235,184, 0, 35, 47,184, 0, 36, 47,184, 0, 0,220,184, 0, 35, 16,184, 0, 6,208,184, 0,
+ 6, 47,184, 0, 14,220, 65, 27, 0, 22, 0, 14, 0, 38, 0, 14, 0, 54, 0, 14, 0, 70, 0, 14, 0, 86, 0, 14, 0,102, 0, 14,
+ 0,118, 0, 14, 0,134, 0, 14, 0,150, 0, 14, 0,166, 0, 14, 0,182, 0, 14, 0,198, 0, 14, 0,214, 0, 14, 0, 13, 93, 65,
+ 5, 0,229, 0, 14, 0,245, 0, 14, 0, 2, 93,184, 0, 0, 16,184, 0, 20,220, 65, 5, 0,234, 0, 20, 0,250, 0, 20, 0, 2,
+ 93, 65, 27, 0, 25, 0, 20, 0, 41, 0, 20, 0, 57, 0, 20, 0, 73, 0, 20, 0, 89, 0, 20, 0,105, 0, 20, 0,121, 0, 20, 0,
+137, 0, 20, 0,153, 0, 20, 0,169, 0, 20, 0,185, 0, 20, 0,201, 0, 20, 0,217, 0, 20, 0, 13, 93,186, 0, 32, 0, 6, 0,
+ 0, 17, 18, 57,186, 0, 33, 0, 6, 0, 0, 17, 18, 57, 0,186, 0, 17, 0, 3, 0, 3, 43,184, 0, 17, 16,186, 0, 10, 0, 24,
+ 0, 3, 43,184, 0, 10, 16,186, 0, 29, 0, 33, 0, 3, 43,184, 0, 29, 16, 48, 49, 1, 16, 0, 33, 32, 0, 17, 52, 18, 36, 51,
+ 50, 4, 18, 5, 16, 0, 33, 32, 0, 17, 52, 2, 36, 35, 34, 4, 2, 1, 33, 21, 1, 35, 1, 33, 6,148,254, 63,254,194,254,196,
+254, 63,206, 1,113,190,193, 1,113,205,250, 87, 1,143, 1, 28, 1, 28, 1,143,182,254,184,173,173,254,184,182, 1,107, 2,171,
+254,148,193, 1, 81,254, 49, 2,234,254,193,254, 65, 1,191, 1, 63,198, 1,114,198,198,254,144,200,254,228,254,112, 1,144, 1,
+ 28,179, 1, 71,177,177,254,185, 1, 25, 75,252,163, 3, 26, 0, 0, 5, 0,152,255,236, 6,148, 5,232, 0, 13, 0, 27, 0, 39,
+ 0, 63, 0, 75, 2, 13,186, 0, 14, 0, 6, 0, 3, 43,184, 0, 14, 16,186, 0, 31, 0, 61, 0, 3, 43,184, 0, 31, 16,186, 0,
+ 49, 0, 70, 0, 3, 43,184, 0, 49, 16,186, 0, 0, 0, 20, 0, 3, 43,184, 0, 0, 16, 65, 27, 0, 22, 0, 14, 0, 38, 0, 14,
+ 0, 54, 0, 14, 0, 70, 0, 14, 0, 86, 0, 14, 0,102, 0, 14, 0,118, 0, 14, 0,134, 0, 14, 0,150, 0, 14, 0,166, 0, 14,
+ 0,182, 0, 14, 0,198, 0, 14, 0,214, 0, 14, 0, 13, 93, 65, 5, 0,229, 0, 14, 0,245, 0, 14, 0, 2, 93, 65, 5, 0,234,
+ 0, 20, 0,250, 0, 20, 0, 2, 93, 65, 27, 0, 25, 0, 20, 0, 41, 0, 20, 0, 57, 0, 20, 0, 73, 0, 20, 0, 89, 0, 20, 0,
+105, 0, 20, 0,121, 0, 20, 0,137, 0, 20, 0,153, 0, 20, 0,169, 0, 20, 0,185, 0, 20, 0,201, 0, 20, 0,217, 0, 20, 0,
+ 13, 93, 65, 27, 0, 22, 0, 31, 0, 38, 0, 31, 0, 54, 0, 31, 0, 70, 0, 31, 0, 86, 0, 31, 0,102, 0, 31, 0,118, 0, 31,
+ 0,134, 0, 31, 0,150, 0, 31, 0,166, 0, 31, 0,182, 0, 31, 0,198, 0, 31, 0,214, 0, 31, 0, 13, 93, 65, 5, 0,229, 0,
+ 31, 0,245, 0, 31, 0, 2, 93, 65, 5, 0,234, 0, 70, 0,250, 0, 70, 0, 2, 93, 65, 27, 0, 25, 0, 70, 0, 41, 0, 70, 0,
+ 57, 0, 70, 0, 73, 0, 70, 0, 89, 0, 70, 0,105, 0, 70, 0,121, 0, 70, 0,137, 0, 70, 0,153, 0, 70, 0,169, 0, 70, 0,
+185, 0, 70, 0,201, 0, 70, 0,217, 0, 70, 0, 13, 93,186, 0, 37, 0, 70, 0, 49, 17, 18, 57,184, 0, 37, 47, 65, 5, 0,234,
+ 0, 37, 0,250, 0, 37, 0, 2, 93, 65, 27, 0, 25, 0, 37, 0, 41, 0, 37, 0, 57, 0, 37, 0, 73, 0, 37, 0, 89, 0, 37, 0,
+105, 0, 37, 0,121, 0, 37, 0,137, 0, 37, 0,153, 0, 37, 0,169, 0, 37, 0,185, 0, 37, 0,201, 0, 37, 0,217, 0, 37, 0,
+ 13, 93,186, 0, 43, 0, 61, 0, 31, 17, 18, 57,184, 0, 43, 47,186, 0, 52, 0, 70, 0, 49, 17, 18, 57,184, 0, 37, 16,184, 0,
+ 55,220,184, 0, 43, 16,184, 0, 64,220, 0,186, 0, 17, 0, 3, 0, 3, 43,184, 0, 17, 16,186, 0, 10, 0, 24, 0, 3, 43,184,
+ 0, 10, 16,186, 0, 34, 0, 58, 0, 3, 43,184, 0, 34, 16,186, 0, 46, 0, 73, 0, 3, 43,184, 0, 46, 16,186, 0, 67, 0, 28,
+ 0, 3, 43,184, 0, 67, 16,186, 0, 52, 0, 28, 0, 67, 17, 18, 57, 48, 49, 1, 16, 0, 33, 32, 0, 17, 52, 18, 36, 51, 50, 4,
+ 18, 5, 16, 0, 33, 32, 0, 17, 52, 2, 36, 35, 34, 4, 2, 5, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 37, 46, 1, 53, 52,
+ 54, 51, 50, 22, 21, 20, 6, 7, 30, 1, 21, 20, 6, 35, 34, 38, 53, 52, 54, 55, 20, 22, 51, 50, 54, 53, 52, 38, 35, 34, 6, 6,
+148,254, 63,254,194,254,196,254, 63,206, 1,113,190,193, 1,113,205,250, 87, 1,143, 1, 28, 1, 28, 1,143,182,254,184,173,173,
+254,184,182, 2,175, 84, 95, 95, 84, 84, 95, 95,254,198, 4,106,183,157,157,182,105, 4, 15,118,190,173,173,190,118, 87, 81, 77,
+ 75, 82, 82, 75, 77, 81, 2,234,254,193,254, 65, 1,191, 1, 63,198, 1,114,198,198,254,144,200,254,228,254,112, 1,144, 1, 28,
+179, 1, 71,177,177,254,185,230, 80, 73, 73, 80, 81, 72, 73, 80, 73, 1,118, 83,116,136,136,116, 83,118, 1, 3,131, 92,138,151,
+151,138, 92,131,193, 61, 66, 66, 61, 62, 66, 66, 0, 4, 0,152,255,236, 6,148, 5,232, 0, 13, 0, 27, 0, 52, 0, 64, 1,145,
+186, 0, 14, 0, 6, 0, 3, 43,184, 0, 14, 16,186, 0, 62, 0, 41, 0, 3, 43,184, 0, 62, 16,186, 0, 0, 0, 20, 0, 3, 43,
+184, 0, 0, 16,186, 0, 47, 0, 56, 0, 3, 43,184, 0, 47, 16, 65, 27, 0, 22, 0, 14, 0, 38, 0, 14, 0, 54, 0, 14, 0, 70,
+ 0, 14, 0, 86, 0, 14, 0,102, 0, 14, 0,118, 0, 14, 0,134, 0, 14, 0,150, 0, 14, 0,166, 0, 14, 0,182, 0, 14, 0,198,
+ 0, 14, 0,214, 0, 14, 0, 13, 93, 65, 5, 0,229, 0, 14, 0,245, 0, 14, 0, 2, 93, 65, 5, 0,234, 0, 20, 0,250, 0, 20,
+ 0, 2, 93, 65, 27, 0, 25, 0, 20, 0, 41, 0, 20, 0, 57, 0, 20, 0, 73, 0, 20, 0, 89, 0, 20, 0,105, 0, 20, 0,121, 0,
+ 20, 0,137, 0, 20, 0,153, 0, 20, 0,169, 0, 20, 0,185, 0, 20, 0,201, 0, 20, 0,217, 0, 20, 0, 13, 93, 65, 27, 0, 22,
+ 0, 62, 0, 38, 0, 62, 0, 54, 0, 62, 0, 70, 0, 62, 0, 86, 0, 62, 0,102, 0, 62, 0,118, 0, 62, 0,134, 0, 62, 0,150,
+ 0, 62, 0,166, 0, 62, 0,182, 0, 62, 0,198, 0, 62, 0,214, 0, 62, 0, 13, 93, 65, 5, 0,229, 0, 62, 0,245, 0, 62, 0,
+ 2, 93,186, 0, 29, 0, 41, 0, 62, 17, 18, 57, 65, 5, 0,234, 0, 56, 0,250, 0, 56, 0, 2, 93, 65, 27, 0, 25, 0, 56, 0,
+ 41, 0, 56, 0, 57, 0, 56, 0, 73, 0, 56, 0, 89, 0, 56, 0,105, 0, 56, 0,121, 0, 56, 0,137, 0, 56, 0,153, 0, 56, 0,
+169, 0, 56, 0,185, 0, 56, 0,201, 0, 56, 0,217, 0, 56, 0, 13, 93, 0,186, 0, 17, 0, 3, 0, 3, 43,184, 0, 17, 16,186,
+ 0, 10, 0, 24, 0, 3, 43,184, 0, 10, 16,186, 0, 32, 0, 50, 0, 3, 43,184, 0, 32, 16,186, 0, 44, 0, 59, 0, 3, 43,184,
+ 0, 44, 16,186, 0, 53, 0, 38, 0, 3, 43,184, 0, 53, 16, 48, 49, 1, 16, 0, 33, 32, 0, 17, 52, 18, 36, 51, 50, 4, 18, 5,
+ 16, 0, 33, 32, 0, 17, 52, 2, 36, 35, 34, 4, 2, 1, 53, 30, 1, 51, 50, 54, 55, 54, 6, 35, 34, 38, 53, 52, 54, 51, 50, 22,
+ 21, 20, 2, 35, 34, 38, 19, 50, 54, 53, 52, 38, 35, 34, 6, 21, 20, 22, 6,148,254, 63,254,194,254,196,254, 63,206, 1,113,190,
+193, 1,113,205,250, 87, 1,143, 1, 28, 1, 28, 1,143,182,254,184,173,173,254,184,182, 1,144, 85, 97, 46,119,127, 5, 10,128,
+ 79,159,186,194,160,185,191,233,200, 53,107,217, 78, 91, 91, 78, 78, 92, 92, 2,234,254,193,254, 65, 1,191, 1, 63,198, 1,114,
+198,198,254,144,200,254,228,254,112, 1,144, 1, 28,179, 1, 71,177,177,254,185,253,139,156, 36, 21,147, 79, 13, 60,175,148,145,
+180,253,232,218,254,246, 19, 1,180, 98, 91, 91, 98, 98, 91, 91, 98, 0, 0, 0, 0, 5, 0,152,255,236, 6,148, 5,232, 0, 13,
+ 0, 27, 0, 38, 0, 50, 0, 62, 1,155,186, 0, 14, 0, 6, 0, 3, 43,184, 0, 14, 16,186, 0, 35, 0, 29, 0, 3, 43,184, 0,
+ 35, 16,186, 0, 42, 0, 60, 0, 3, 43,184, 0, 42, 16,186, 0, 54, 0, 48, 0, 3, 43,184, 0, 54, 16,186, 0, 0, 0, 20, 0,
+ 3, 43,184, 0, 0, 16, 65, 27, 0, 22, 0, 14, 0, 38, 0, 14, 0, 54, 0, 14, 0, 70, 0, 14, 0, 86, 0, 14, 0,102, 0, 14,
+ 0,118, 0, 14, 0,134, 0, 14, 0,150, 0, 14, 0,166, 0, 14, 0,182, 0, 14, 0,198, 0, 14, 0,214, 0, 14, 0, 13, 93, 65,
+ 5, 0,229, 0, 14, 0,245, 0, 14, 0, 2, 93, 65, 5, 0,234, 0, 20, 0,250, 0, 20, 0, 2, 93, 65, 27, 0, 25, 0, 20, 0,
+ 41, 0, 20, 0, 57, 0, 20, 0, 73, 0, 20, 0, 89, 0, 20, 0,105, 0, 20, 0,121, 0, 20, 0,137, 0, 20, 0,153, 0, 20, 0,
+169, 0, 20, 0,185, 0, 20, 0,201, 0, 20, 0,217, 0, 20, 0, 13, 93, 65, 5, 0,234, 0, 48, 0,250, 0, 48, 0, 2, 93, 65,
+ 27, 0, 25, 0, 48, 0, 41, 0, 48, 0, 57, 0, 48, 0, 73, 0, 48, 0, 89, 0, 48, 0,105, 0, 48, 0,121, 0, 48, 0,137, 0,
+ 48, 0,153, 0, 48, 0,169, 0, 48, 0,185, 0, 48, 0,201, 0, 48, 0,217, 0, 48, 0, 13, 93, 65, 5, 0,234, 0, 60, 0,250,
+ 0, 60, 0, 2, 93, 65, 27, 0, 25, 0, 60, 0, 41, 0, 60, 0, 57, 0, 60, 0, 73, 0, 60, 0, 89, 0, 60, 0,105, 0, 60, 0,
+121, 0, 60, 0,137, 0, 60, 0,153, 0, 60, 0,169, 0, 60, 0,185, 0, 60, 0,201, 0, 60, 0,217, 0, 60, 0, 13, 93, 0,186,
+ 0, 17, 0, 3, 0, 3, 43,184, 0, 17, 16,186, 0, 10, 0, 24, 0, 3, 43,184, 0, 10, 16,186, 0, 45, 0, 57, 0, 3, 43,184,
+ 0, 45, 16,186, 0, 36, 0, 37, 0, 3, 43,184, 0, 36, 16,186, 0, 51, 0, 39, 0, 3, 43,184, 0, 51, 16,184, 0, 36, 16,184,
+ 0, 28,208, 48, 49, 1, 16, 0, 33, 32, 0, 17, 52, 18, 36, 51, 50, 4, 18, 5, 16, 0, 33, 32, 0, 17, 52, 2, 36, 35, 34, 4,
+ 2, 19, 51, 17, 7, 53, 55, 51, 17, 51, 21, 33, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 39, 50, 22, 21, 20, 6, 35, 34,
+ 38, 53, 52, 54, 6,148,254, 63,254,194,254,196,254, 63,206, 1,113,190,193, 1,113,205,250, 87, 1,143, 1, 28, 1, 28, 1,143,
+182,254,184,173,173,254,184,182,205,158,172,188,117,159,254, 62, 3, 4, 64, 69, 69, 64, 63, 70, 70, 63,130,136,136,130,131,136,
+136, 2,234,254,193,254, 65, 1,191, 1, 63,198, 1,114,198,198,254,144,200,254,228,254,112, 1,144, 1, 28,179, 1, 71,177,177,
+254,185,254, 62, 2, 62, 39,137, 42,253, 54,128, 2,222,151,163,162,151,151,162,163,151,123,228,209,208,228,228,208,209,228, 0,
+ 0, 1, 0,170, 1,119, 6,130, 4, 99, 0, 5, 0, 11, 0,184, 0, 2, 47,184, 0, 5, 47, 48, 49, 19, 17, 37, 5, 17, 5,170,
+ 1,119, 4, 97,251,159, 2, 50, 1,117,188,188,254,139,187, 0, 0, 1, 0,170, 0, 0, 4,116, 5,217, 0, 19, 0, 31, 0,184,
+ 0, 5, 47,186, 0, 16, 0, 18, 0, 3, 43,184, 0, 16, 16,184, 0, 18, 16,184, 0, 13,208,184, 0, 13, 47, 48, 49, 1, 22, 21,
+ 20, 7, 3, 33, 3, 38, 53, 52, 55, 54, 39, 35, 53, 33, 23, 7, 22, 3,126,246, 8,238,254, 34,237, 9,246,127, 7,117, 1,218,
+ 1,119, 1, 4,224, 66,179, 32, 36,252, 89, 3,167, 38, 34,175, 66, 26,134, 89, 89, 1,135, 0, 0, 1, 0, 47, 0, 0, 5,170,
+ 6, 20, 0, 36, 0, 72, 64, 19, 38, 0, 7, 9, 5, 8, 12, 33, 24, 13, 30, 8, 17, 12, 33, 16, 20, 76, 37, 16,252, 60,196, 50,
+196,252, 60,196, 16, 60,252, 60,196,196,196, 49, 0, 64, 17, 9, 13, 17,169, 18, 2, 26,135, 0, 24,151, 6, 31, 18,188, 11, 15,
+ 47, 60,230, 50, 50,254, 60,238, 50, 16,238, 50, 50, 48, 1, 21, 35, 34, 6, 29, 1, 33, 21, 33, 17, 35, 17, 33, 17, 35, 17, 35,
+ 53, 51, 53, 52, 54, 59, 1, 21, 35, 34, 7, 6, 29, 1, 33, 53, 52, 54, 51, 5,170,176, 99, 77, 1, 47,254,209,185,254, 7,185,
+176,176,174,189,174,176, 99, 39, 38, 1,249,174,189, 6, 20,153, 80,104, 99,143,252, 47, 3,209,252, 47, 3,209,143, 78,187,171,
+153, 40, 40,104, 99, 78,187,171, 0, 2, 0, 47, 0, 0, 4, 74, 6, 20, 0, 21, 0, 25, 0, 67, 64, 17, 27, 70, 0, 23, 8, 22,
+ 15, 20, 4, 8, 8, 3, 22, 10, 6, 76, 26, 16,252, 60,196, 50,196,252, 60,196, 16,254, 60,236, 49, 0, 64, 18, 8, 3,169, 0,
+ 16,135, 14, 24,190, 22,177, 14,151, 9, 0,188, 5, 1, 47, 60,230, 50,238,254,238, 16,238, 16,238, 50, 48, 1, 17, 35, 17, 33,
+ 17, 35, 17, 35, 53, 51, 53, 52, 54, 59, 1, 21, 35, 34, 6, 29, 1, 1, 51, 21, 35, 4, 74,185,254, 7,185,176,176,173,179,185,
+176, 99, 77, 1,249,185,185, 4, 96,251,160, 3,209,252, 47, 3,209,143, 78,183,175,153, 80,104, 99, 1,178,233, 0, 1, 0, 47,
+ 0, 0, 4, 74, 6, 20, 0, 21, 0, 55, 64, 15, 23, 70, 1, 8, 4, 10, 12, 8, 8, 16, 4, 18, 14, 76, 22, 16,252, 60,196,196,
+252, 60,196, 16,254,236, 49, 0, 64, 13, 15, 11,169, 9, 4,135, 0,151, 17, 9,188, 13, 2, 47, 60,230, 50,254,238, 16,238, 50,
+ 48, 1, 33, 17, 35, 17, 33, 34, 6, 29, 1, 33, 21, 33, 17, 35, 17, 35, 53, 51, 53, 52, 54, 2, 74, 2, 0,185,254,183, 99, 77,
+ 1, 47,254,209,185,176,176,174, 6, 20,249,236, 5,123, 80,104, 99,143,252, 47, 3,209,143, 78,187,171, 0, 0, 0, 2, 0, 47,
+ 0, 0, 6,252, 6, 20, 0, 41, 0, 45, 0, 90, 64, 24, 47, 70, 23, 43, 8, 42, 16, 27, 21, 8, 26, 42, 9, 0, 31, 6, 8, 36,
+ 30, 9, 34, 38, 76, 46, 16,252, 60,196, 50,196,252, 60,196, 16,196, 50,252, 60,196, 16,252, 60,236, 49, 0, 64, 23, 27, 31, 35,
+169, 36, 17, 1,135, 0, 45,190, 42,177, 16, 0,151, 22, 7, 36,188, 25, 29, 33, 47, 60, 60,228, 50, 50,228, 50,244,236, 16,236,
+ 50, 16,236, 50, 50, 48, 1, 21, 35, 34, 7, 6, 29, 1, 33, 53, 52, 55, 54, 55, 54, 59, 1, 21, 35, 34, 6, 29, 1, 33, 17, 35,
+ 17, 33, 17, 35, 17, 33, 17, 35, 17, 35, 53, 51, 53, 52, 54, 51, 5, 51, 21, 35, 2,248,176, 99, 39, 38, 1,249, 87, 28, 39, 78,
+131,174,176, 99, 77, 2,178,185,254, 7,185,254, 7,185,176,176,174,189, 3,249,185,185, 6, 20,153, 40, 40,104, 99, 78,187, 85,
+ 28, 19, 39,153, 80,104, 99,251,160, 3,209,252, 47, 3,209,252, 47, 3,209,143, 78,187,171, 2,233, 0, 0, 0, 0, 1, 0, 47,
+ 0, 0, 6,252, 6, 20, 0, 38, 0, 78, 64, 22, 40, 70, 13, 8, 16, 22, 24, 20, 8, 16, 9, 0, 28, 6, 8, 33, 27, 9, 31, 35,
+ 76, 39, 16,252, 60,196, 50,196,252, 60,196, 16,196,252, 60,196, 16,252,236, 49, 0, 64, 18, 24, 28, 32,169, 33, 17, 2,135, 12,
+ 38,151, 21, 7, 33,188, 15, 26, 30, 47, 60, 60,228, 50, 50,244, 60,236, 50, 16,236, 50, 50, 48, 1, 21, 35, 34, 7, 6, 29, 1,
+ 33, 53, 52, 54, 51, 33, 17, 35, 17, 33, 34, 6, 29, 1, 33, 21, 33, 17, 35, 17, 33, 17, 35, 17, 35, 53, 51, 53, 52, 54, 51, 2,
+248,176, 99, 39, 38, 1,249,174,189, 2, 0,185,254,183, 99, 77, 1, 47,254,209,185,254, 7,185,176,176,174,189, 6, 20,153, 40,
+ 40,104, 99, 78,187,171,249,236, 5,123, 80,104, 99,143,252, 47, 3,209,252, 47, 3,209,143, 78,187,171, 0, 0, 0, 1, 0, 47,
+ 0, 0, 5, 76, 6, 20, 0, 45, 0, 0, 1, 53, 52, 39, 38, 43, 1, 34, 7, 6, 21, 17, 35, 17, 35, 53, 51, 53, 52, 55, 54, 59,
+ 1, 50, 23, 22, 29, 1, 33, 21, 33, 17, 20, 23, 22, 59, 1, 21, 35, 34, 39, 38, 53, 17, 35, 53, 3, 24, 36, 37,101, 34, 99, 39,
+ 38,185,176,176, 87, 87,189, 30,189, 87, 85, 1,123,254,133, 37, 38,115,189,189,213, 81, 81,135, 4, 96, 99,104, 40, 40, 40, 40,
+104,251, 61, 3,209,143, 78,187, 85, 86, 86, 83,189, 78,143,253,160,137, 39, 39,154, 80, 79,210, 2, 96,143, 0, 0, 1, 0,111,
+255,227, 6,178, 5,240, 0, 89, 0, 0, 1, 21, 38, 39, 38, 35, 34, 7, 6, 21, 20, 23, 22, 31, 1, 30, 1, 21, 20, 7, 6, 35,
+ 34, 39, 38, 39, 53, 22, 23, 22, 51, 50, 55, 54, 53, 52, 39, 38, 47, 1, 38, 39, 38, 53, 52, 55, 54, 51, 50, 23, 38, 53, 52, 55,
+ 54, 55, 50, 23, 22, 29, 1, 33, 21, 33, 17, 20, 23, 22, 59, 1, 21, 35, 34, 39, 38, 53, 17, 35, 53, 51, 53, 52, 39, 38, 7, 34,
+ 7, 6, 21, 20, 3, 81, 86, 73, 84, 70,117, 63, 59, 49, 49,148, 63,195,166,123,124,216, 96, 92, 97,108,102, 99, 99, 97,130, 70,
+ 70, 50, 45,177, 64,171, 76, 76,102,112,181, 72, 77, 5, 92, 91,162,140, 98, 94, 1,123,254,133, 37, 38,115,189,189,213, 81, 81,
+135,135, 48, 54, 68, 69, 54, 52, 4, 63,174, 43, 17, 20, 42, 39, 87, 64, 37, 36, 33, 14, 43,152,137,156, 91, 91, 17, 18, 35,190,
+ 53, 26, 27, 45, 44, 81, 75, 40, 35, 42, 15, 36, 74, 75,130,166, 78, 86, 11, 29, 31,135, 95, 93, 1, 96, 92,136, 76,143,253,160,
+137, 39, 39,154, 80, 79,210, 2, 96,143, 78, 65, 43, 50, 1, 49, 48, 64, 61, 0, 0, 1, 0,170,255,227, 8,227, 6, 20, 0, 74,
+ 0, 0, 1, 22, 21, 17, 35, 53, 14, 1, 35, 34, 38, 53, 17, 51, 17, 20, 22, 51, 50, 54, 53, 17, 52, 39, 33, 34, 39, 38, 55, 54,
+ 55, 54, 59, 1, 21, 35, 34, 21, 20, 51, 33, 39, 38, 55, 54, 59, 1, 21, 35, 38, 21, 20, 31, 1, 33, 3, 20, 23, 22, 51, 50, 54,
+ 53, 17, 51, 17, 35, 53, 14, 1, 35, 34, 38, 53, 17, 4, 79, 9,184, 67,177,117,193,200,184,124,124,149,173, 5,254, 83,149, 94,
+ 83, 3, 3, 87,115,118, 89, 89,131,131, 1,108, 23, 77, 32, 55,209,236,222, 96, 14, 59, 1,221, 1, 62, 62,124,149,173,184,184,
+ 67,177,117,193,200, 3,182, 37, 33,252,144,172,102, 99,240,231, 1,102,254,161,159,159,190,164, 1,145, 36, 28, 94, 83,145,131,
+ 66, 87,175,123,138, 56,186, 72,122,175, 1, 44, 39, 34,145,253, 97,160, 79, 79,190,164, 2,123,251,160,172,102, 99,240,231, 1,
+252, 0, 0, 0, 0, 1, 0,174,255,227, 8,227, 6, 20, 0, 58, 0, 0, 1, 33, 38, 21, 20, 31, 1, 22, 21, 17, 35, 53, 14, 1,
+ 35, 34, 38, 53, 17, 51, 17, 20, 22, 51, 50, 54, 53, 17, 52, 47, 1, 38, 55, 54, 51, 33, 17, 33, 21, 33, 17, 20, 22, 51, 50, 55,
+ 54, 53, 17, 51, 17, 35, 53, 14, 1, 35, 34, 38, 53, 5, 57,254,243, 96, 14, 77, 49,184, 67,177,117,193,200,184,124,124,149,173,
+ 16, 77, 77, 32, 55,209, 1,211, 2,242,253, 14,124,124,152, 83, 87,184,184, 67,177,117,193,200, 5,101, 1, 44, 39, 34,188,120,
+ 77,252,144,172,102, 99,240,231, 2,166,253, 97,159,159,190,164, 1,145, 63, 39,188,187, 71,122,254, 76,170,254, 11,159,159, 95,
+ 98,161, 1, 59,252,224,172,102, 99,240,231, 0, 0, 1, 0,174,254, 86, 8,227, 6, 20, 0, 53, 0, 0, 1, 33, 38, 21, 20, 31,
+ 1, 22, 21, 17, 35, 53, 14, 1, 35, 34, 38, 53, 17, 51, 17, 20, 22, 51, 50, 54, 53, 17, 52, 47, 1, 38, 55, 54, 51, 33, 17, 62,
+ 1, 51, 50, 22, 21, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 5, 57,254,243, 96, 14, 77, 49,184, 67,177,117,193,200,184,124,
+124,149,173, 16, 77, 77, 32, 55,209, 1,212, 66,179,117,193,198,184,124,124,149,172,185, 5,101, 1, 44, 39, 34,188,120, 77,252,
+144,172,102, 99,240,231, 2,166,253, 97,159,159,190,164, 1,145, 63, 39,188,187, 71,122,253,158,101,100,239,232,253, 92, 2,158,
+159,158,190,164,251,221, 0, 0, 0, 2, 0,174,254, 86, 8,227, 6, 20, 0, 53, 0, 60, 0, 0, 1, 33, 34, 39, 38, 55, 54, 55,
+ 54, 51, 33, 17, 33, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 35, 53, 14, 1, 35, 34, 38, 53, 17, 35, 17, 51, 21, 33, 17, 14, 1,
+ 35, 34, 38, 53, 17, 51, 17, 20, 22, 51, 50, 55, 54, 53, 25, 1, 33, 34, 21, 20, 51, 3,160,254,219,149, 94, 83, 3, 3, 87,115,
+118, 1,221, 1,153,124,124,149,173,184,184, 67,177,117,193,200,225,213,254,115, 67,177,117,193,200,184,124,124,149, 87, 86,254,
+219,131,131, 3,182, 94, 83,145,131, 66, 87,254, 76,253, 97,159,159,190,164, 2,123,251,160,172,102, 99,240,231, 1,252,251, 66,
+162, 2, 86,102, 99,240,231, 1,102,254,161,159,159, 95, 95,164, 2,123, 1, 5,123,138, 0, 0, 0, 1, 0,174,254, 86, 11,155,
+ 6, 20, 0, 72, 0, 0, 1, 33, 38, 21, 20, 31, 1, 22, 21, 17, 35, 53, 14, 1, 35, 34, 38, 53, 17, 51, 17, 20, 22, 51, 50, 54,
+ 53, 17, 52, 47, 1, 38, 55, 54, 51, 33, 17, 54, 55, 54, 51, 50, 22, 29, 1, 20, 23, 22, 51, 50, 54, 53, 17, 51, 17, 35, 53, 14,
+ 1, 35, 34, 39, 38, 61, 1, 52, 38, 35, 34, 6, 21, 17, 35, 5, 57,254,243, 96, 14, 77, 49,184, 67,177,117,193,200,184,124,124,
+149,173, 16, 77, 77, 32, 55,209, 1,212, 99, 37, 90,107,193,198, 62, 56,110,140,173,184,184, 67,177,108,175, 98,100,124,124,120,
+172,185, 5,101, 1, 44, 39, 34,188,120, 77,252,144,172,102, 99,240,231, 2,166,253, 97,159,159,190,164, 1,145, 63, 39,188,187,
+ 71,122,253,158,129, 22, 50,239,232,227,151, 88, 79,190,164, 2,123,251,160,172,102, 99,120,123,228,228,159,158,190,164,251,221,
+ 0, 3, 0, 30,255, 84, 8, 22, 7, 76, 0, 3, 0, 7, 0, 42, 0, 0, 9, 4, 21, 51, 53, 39, 53, 52, 54, 55, 54, 55, 54, 63,
+ 1, 54, 55, 54, 53, 52, 38, 35, 34, 6, 7, 21, 62, 1, 51, 50, 22, 21, 20, 6, 15, 1, 14, 1, 29, 1, 4, 26, 3,252,252, 4,
+252, 4, 3,150,203, 6, 6, 6, 8, 19, 23, 44, 88, 92, 34, 36,223,184,103,193, 94, 97,179, 79,108,131, 51, 57, 90, 90, 56, 7,
+ 76,252, 4,252, 4, 3,252,253,174,254,254,147,123, 52, 60, 21, 25, 26, 31, 43, 86, 90, 64, 69, 76,159,194, 56, 57,188, 67, 70,
+110, 89, 49, 94, 53, 89, 86,130,101,154, 0, 0, 0, 0, 0, 1, 0, 0, 60, 2, 0, 1, 9,254, 48, 0, 0, 11, 11,244, 0, 16,
+ 0, 36,255,211, 0, 16, 0, 37,255,183, 0, 16, 0, 42, 0, 75, 0, 16, 0, 45, 0,114, 0, 16, 0, 50, 0, 57, 0, 16, 0, 52,
+ 0, 75, 0, 16, 0, 55,255, 68, 0, 16, 0, 57,255,136, 0, 16, 0, 58,255,173, 0, 16, 0, 59,255,154, 0, 16, 0, 60,255, 13,
+ 0, 16, 0, 82, 0, 38, 0, 16, 0, 89,255,201, 0, 16, 0, 92,255,220, 0, 16, 0,130,255,211, 0, 16, 0,131,255,211, 0, 16,
+ 0,132,255,211, 0, 16, 0,133,255,211, 0, 16, 0,134,255,211, 0, 16, 0,148, 0, 57, 0, 16, 0,149, 0, 57, 0, 16, 0,150,
+ 0, 57, 0, 16, 0,151, 0, 57, 0, 16, 0,152, 0, 57, 0, 16, 0,159,255, 13, 0, 16, 0,180, 0, 38, 0, 16, 0,181, 0, 38,
+ 0, 16, 0,182, 0, 38, 0, 16, 0,183, 0, 38, 0, 16, 0,184, 0, 38, 0, 16, 0,191,255,220, 0, 16, 0,193,255,220, 0, 16,
+ 0,194,255,211, 0, 16, 0,196,255,211, 0, 16, 0,198,255,211, 0, 16, 0,224, 0, 75, 0, 16, 1, 38,255, 68, 0, 16, 1, 58,
+255, 13, 0, 36, 0, 16,255,211, 0, 36, 0, 17,255,220, 0, 36, 0, 29,255,220, 0, 36, 0, 36, 0, 57, 0, 36, 0, 38,255,220,
+ 0, 36, 0, 42,255,220, 0, 36, 0, 50,255,220, 0, 36, 0, 52,255,220, 0, 36, 0, 55,255, 97, 0, 36, 0, 57,255,125, 0, 36,
+ 0, 58,255,144, 0, 36, 0, 60,255, 97, 0, 36, 0, 70,255,220, 0, 36, 0, 71,255,220, 0, 36, 0, 72,255,220, 0, 36, 0, 73,
+255,183, 0, 36, 0, 82,255,220, 0, 36, 0, 84,255,220, 0, 36, 0, 87,255,220, 0, 36, 0, 89,255,136, 0, 36, 0, 90,255,173,
+ 0, 36, 0, 92,255,117, 0, 36, 0,109,255,183, 0, 36, 0,130, 0, 57, 0, 36, 0,131, 0, 57, 0, 36, 0,132, 0, 57, 0, 36,
+ 0,133, 0, 57, 0, 36, 0,134, 0, 57, 0, 36, 0,137,255,220, 0, 36, 0,148,255,220, 0, 36, 0,149,255,220, 0, 36, 0,150,
+255,220, 0, 36, 0,151,255,220, 0, 36, 0,152,255,220, 0, 36, 0,159,255, 97, 0, 36, 0,169,255,220, 0, 36, 0,170,255,220,
+ 0, 36, 0,171,255,220, 0, 36, 0,172,255,220, 0, 36, 0,173,255,220, 0, 36, 0,180,255,220, 0, 36, 0,181,255,220, 0, 36,
+ 0,182,255,220, 0, 36, 0,183,255,220, 0, 36, 0,184,255,220, 0, 36, 0,191,255,117, 0, 36, 0,193,255,117, 0, 36, 0,194,
+ 0, 57, 0, 36, 0,196, 0, 57, 0, 36, 0,198, 0, 57, 0, 36, 0,200,255,220, 0, 36, 0,201,255,220, 0, 36, 0,202,255,220,
+ 0, 36, 0,203,255,220, 0, 36, 0,204,255,220, 0, 36, 0,205,255,220, 0, 36, 0,206,255,220, 0, 36, 0,207,255,220, 0, 36,
+ 0,209,255,220, 0, 36, 0,211,255,220, 0, 36, 0,213,255,220, 0, 36, 0,215,255,220, 0, 36, 0,217,255,220, 0, 36, 0,219,
+255,220, 0, 36, 0,221,255,220, 0, 36, 0,222,255,220, 0, 36, 0,224,255,220, 0, 36, 0,226,255,220, 0, 36, 1, 14,255,220,
+ 0, 36, 1, 15,255,220, 0, 36, 1, 16,255,220, 0, 36, 1, 17,255,220, 0, 36, 1, 18,255,220, 0, 36, 1, 19,255,220, 0, 36,
+ 1, 36,255, 97, 0, 36, 1, 37,255,220, 0, 36, 1, 38,255, 97, 0, 36, 1, 39,255,220, 0, 36, 1, 54,255,144, 0, 36, 1, 55,
+255,173, 0, 36, 1, 56,255, 97, 0, 36, 1, 57,255,117, 0, 36, 1, 58,255, 97, 0, 36, 1,136,255,220, 0, 36, 1,172,255,220,
+ 0, 36, 1,173,255,220, 0, 36, 1,174,255,220, 0, 36, 1,175,255,220, 0, 36, 1,220,255, 97, 0, 36, 1,221,255,220, 0, 36,
+ 1,240,255,220, 0, 36, 1,243,255,220, 0, 36, 1,244,255, 97, 0, 36, 1,245,255,117, 0, 36, 4,252,255,144, 0, 36, 4,253,
+255,173, 0, 36, 4,254,255,144, 0, 36, 4,255,255,173, 0, 36, 5, 0,255,144, 0, 36, 5, 1,255,173, 0, 36, 5,106,255, 97,
+ 0, 36, 5,107,255,117, 0, 36, 5,145,254,248, 0, 36, 5,146,255, 3, 0, 36, 5,147, 0, 47, 0, 37, 0, 38,255,220, 0, 37,
+ 0, 42,255,220, 0, 37, 0, 50,255,220, 0, 37, 0, 54,255,220, 0, 37, 0, 57,255,193, 0, 37, 0, 58,255,183, 0, 37, 0, 60,
+255,144, 0, 37, 0,109,255,193, 0, 37, 0,125,255,220, 0, 37, 0,137,255,220, 0, 37, 0,148,255,220, 0, 37, 0,149,255,220,
+ 0, 37, 0,150,255,220, 0, 37, 0,151,255,220, 0, 37, 0,152,255,220, 0, 37, 0,159,255,144, 0, 37, 0,200,255,220, 0, 37,
+ 0,202,255,220, 0, 37, 0,204,255,220, 0, 37, 0,206,255,220, 0, 37, 0,222,255,220, 0, 37, 0,224,255,220, 0, 37, 0,226,
+255,220, 0, 37, 0,228,255,220, 0, 37, 1, 14,255,220, 0, 37, 1, 16,255,220, 0, 37, 1, 18,255,220, 0, 37, 1, 28,255,220,
+ 0, 37, 1, 30,255,220, 0, 37, 1, 32,255,220, 0, 37, 1, 34,255,220, 0, 37, 1, 54,255,183, 0, 37, 1, 56,255,144, 0, 37,
+ 1, 58,255,144, 0, 37, 1,172,255,220, 0, 37, 1,174,255,220, 0, 37, 1,218,255,220, 0, 37, 1,240,255,220, 0, 37, 4,252,
+255,183, 0, 37, 4,254,255,183, 0, 37, 5, 0,255,183, 0, 37, 5,106,255,144, 0, 37, 5,145,255,144, 0, 37, 5,146,255,144,
+ 0, 37, 5,147,255,173, 0, 38, 0, 60,255,220, 0, 38, 0,109,255,220, 0, 38, 0,125,255,220, 0, 38, 0,159,255,220, 0, 38,
+ 1, 56,255,220, 0, 38, 1, 58,255,220, 0, 38, 1,244,255,220, 0, 38, 5,106,255,220, 0, 38, 5,146, 0, 38, 0, 39, 0, 36,
+255,220, 0, 39, 0, 57,255,220, 0, 39, 0, 60,255,144, 0, 39, 0,109,255,220, 0, 39, 0,125,255,220, 0, 39, 0,130,255,220,
+ 0, 39, 0,131,255,220, 0, 39, 0,132,255,220, 0, 39, 0,133,255,220, 0, 39, 0,134,255,220, 0, 39, 0,159,255,144, 0, 39,
+ 0,194,255,220, 0, 39, 0,196,255,220, 0, 39, 0,198,255,220, 0, 39, 1, 56,255,144, 0, 39, 1, 58,255,144, 0, 39, 1,244,
+255,144, 0, 39, 5,106,255,144, 0, 39, 5,145,255,211, 0, 39, 5,146,255,201, 0, 39, 5,147,255, 68, 0, 41, 0, 17,254,183,
+ 0, 41, 0, 29,255, 97, 0, 41, 0, 36,255, 68, 0, 41, 0, 54,255,220, 0, 41, 0, 55,255,220, 0, 41, 0, 68,255, 68, 0, 41,
+ 0, 72,255,144, 0, 41, 0, 76,255,107, 0, 41, 0, 82,255,183, 0, 41, 0, 85,255,107, 0, 41, 0, 88,255,144, 0, 41, 0, 92,
+255, 68, 0, 41, 0,130,255, 68, 0, 41, 0,131,255, 68, 0, 41, 0,132,255, 68, 0, 41, 0,133,255, 68, 0, 41, 0,134,255, 68,
+ 0, 41, 0,162,255, 68, 0, 41, 0,163,255, 68, 0, 41, 0,164,255, 68, 0, 41, 0,165,255, 68, 0, 41, 0,166,255, 68, 0, 41,
+ 0,167,255, 68, 0, 41, 0,170,255,144, 0, 41, 0,171,255,144, 0, 41, 0,172,255,144, 0, 41, 0,173,255,144, 0, 41, 0,180,
+255,183, 0, 41, 0,181,255,183, 0, 41, 0,182,255,183, 0, 41, 0,183,255,183, 0, 41, 0,184,255,183, 0, 41, 0,187,255,144,
+ 0, 41, 0,188,255,144, 0, 41, 0,189,255,144, 0, 41, 0,190,255,144, 0, 41, 0,191,255, 68, 0, 41, 0,193,255, 68, 0, 41,
+ 0,194,255, 68, 0, 41, 0,195,255, 68, 0, 41, 0,196,255, 68, 0, 41, 0,197,255, 68, 0, 41, 0,198,255, 68, 0, 41, 0,199,
+255, 68, 0, 41, 0,213,255,144, 0, 41, 0,215,255,144, 0, 41, 0,217,255,144, 0, 41, 0,219,255,144, 0, 41, 0,221,255,144,
+ 0, 41, 0,241,255,107, 0, 41, 0,245,255,107, 0, 41, 1, 15,255,183, 0, 41, 1, 17,255,183, 0, 41, 1, 19,255,183, 0, 41,
+ 1, 23,255,107, 0, 41, 1, 25,255,107, 0, 41, 1, 27,255,107, 0, 41, 1, 28,255,220, 0, 41, 1, 30,255,220, 0, 41, 1, 32,
+255,220, 0, 41, 1, 34,255,220, 0, 41, 1, 36,255,220, 0, 41, 1, 38,255,220, 0, 41, 1, 40,255,220, 0, 41, 1, 43,255,144,
+ 0, 41, 1, 45,255,144, 0, 41, 1, 47,255,144, 0, 41, 1, 49,255,144, 0, 41, 1, 51,255,144, 0, 41, 1, 53,255,144, 0, 41,
+ 1, 57,255, 68, 0, 41, 1,173,255,183, 0, 41, 1,175,255,183, 0, 41, 1,218,255,220, 0, 41, 1,220,255,220, 0, 41, 1,241,
+255,183, 0, 41, 1,245,255, 68, 0, 41, 5,107,255, 68, 0, 41, 5,145,255,211, 0, 41, 5,147,254,136, 0, 42, 0, 55,255,183,
+ 0, 42, 0, 60,255,154, 0, 42, 0,109,255,220, 0, 42, 0,125,255,220, 0, 42, 0,159,255,154, 0, 42, 1, 38,255,183, 0, 42,
+ 1, 58,255,154, 0, 42, 5,145,255,211, 0, 42, 5,146,255,211, 0, 42, 5,147,255,201, 0, 43, 0, 17,255,220, 0, 43, 5,145,
+255,183, 0, 43, 5,146,255,193, 0, 43, 5,147,255,183, 0, 45, 0, 16,255,183, 0, 45, 0, 36,255,220, 0, 45, 0,109,255,220,
+ 0, 45, 0,125,255,220, 0, 45, 0,130,255,220, 0, 45, 0,131,255,220, 0, 45, 0,132,255,220, 0, 45, 0,133,255,220, 0, 45,
+ 0,134,255,220, 0, 45, 5,145,255,183, 0, 45, 5,146,255,193, 0, 45, 5,147,255,144, 0, 46, 0, 16,255, 41, 0, 46, 0, 36,
+255,220, 0, 46, 0, 38,255,144, 0, 46, 0, 50,255,144, 0, 46, 0, 55,255, 97, 0, 46, 0, 56,255,201, 0, 46, 0, 58,255,183,
+ 0, 46, 0, 60,255,183, 0, 46, 0, 68,255,220, 0, 46, 0, 72,255,154, 0, 46, 0, 82,255,154, 0, 46, 0, 88,255,154, 0, 46,
+ 0, 92,255,107, 0, 46, 0,109,255,125, 0, 46, 0,130,255,220, 0, 46, 0,131,255,220, 0, 46, 0,132,255,220, 0, 46, 0,133,
+255,220, 0, 46, 0,134,255,220, 0, 46, 0,137,255,144, 0, 46, 0,148,255,144, 0, 46, 0,149,255,144, 0, 46, 0,150,255,144,
+ 0, 46, 0,151,255,144, 0, 46, 0,152,255,144, 0, 46, 0,155,255,201, 0, 46, 0,156,255,201, 0, 46, 0,157,255,201, 0, 46,
+ 0,158,255,201, 0, 46, 0,159,255,183, 0, 46, 0,162,255,220, 0, 46, 0,163,255,220, 0, 46, 0,164,255,220, 0, 46, 0,165,
+255,220, 0, 46, 0,166,255,220, 0, 46, 0,167,255,220, 0, 46, 0,170,255,154, 0, 46, 0,171,255,154, 0, 46, 0,172,255,154,
+ 0, 46, 0,173,255,154, 0, 46, 0,180,255,154, 0, 46, 0,181,255,154, 0, 46, 0,182,255,154, 0, 46, 0,183,255,154, 0, 46,
+ 0,184,255,154, 0, 46, 0,187,255,154, 0, 46, 0,188,255,154, 0, 46, 0,189,255,154, 0, 46, 0,190,255,154, 0, 46, 0,191,
+255,107, 0, 46, 0,193,255,107, 0, 46, 0,200,255,144, 0, 46, 0,206,255,144, 0, 46, 0,221,255,154, 0, 46, 1, 38,255, 97,
+ 0, 46, 1, 48,255,201, 0, 46, 1, 49,255,154, 0, 46, 1, 58,255,183, 0, 46, 5,145,255,193, 0, 46, 5,146,255,193, 0, 47,
+ 0, 16,255,220, 0, 47, 0, 36, 0, 47, 0, 47, 0, 50,255,183, 0, 47, 0, 55,254,230, 0, 47, 0, 56,255,154, 0, 47, 0, 57,
+255, 31, 0, 47, 0, 58,255, 68, 0, 47, 0, 60,254,240, 0, 47, 0, 72,255,220, 0, 47, 0, 82,255,220, 0, 47, 0, 88,255,220,
+ 0, 47, 0, 92,255, 68, 0, 47, 0,130, 0, 47, 0, 47, 0,131, 0, 47, 0, 47, 0,132, 0, 47, 0, 47, 0,133, 0, 47, 0, 47,
+ 0,134, 0, 47, 0, 47, 0,148,255,183, 0, 47, 0,149,255,183, 0, 47, 0,150,255,183, 0, 47, 0,151,255,183, 0, 47, 0,152,
+255,183, 0, 47, 0,155,255,154, 0, 47, 0,156,255,154, 0, 47, 0,157,255,154, 0, 47, 0,158,255,154, 0, 47, 0,159,254,240,
+ 0, 47, 0,170,255,220, 0, 47, 0,171,255,220, 0, 47, 0,172,255,220, 0, 47, 0,173,255,220, 0, 47, 0,180,255,220, 0, 47,
+ 0,181,255,220, 0, 47, 0,182,255,220, 0, 47, 0,183,255,220, 0, 47, 0,184,255,220, 0, 47, 0,187,255,220, 0, 47, 0,188,
+255,220, 0, 47, 0,189,255,220, 0, 47, 0,190,255,220, 0, 47, 0,191,255, 68, 0, 47, 0,193,255, 68, 0, 47, 0,221,255,220,
+ 0, 47, 1, 38,254,230, 0, 47, 1, 48,255,154, 0, 47, 1, 49,255,220, 0, 47, 1, 58,254,240, 0, 47, 5,145,254, 97, 0, 47,
+ 5,146,253,230, 0, 50, 0, 16, 0, 57, 0, 50, 0, 17,255,173, 0, 50, 0, 29,255,220, 0, 50, 0, 36,255,220, 0, 50, 0, 57,
+255,220, 0, 50, 0, 59,255,125, 0, 50, 0, 60,255,144, 0, 50, 0,109,255,220, 0, 50, 0,130,255,220, 0, 50, 0,131,255,220,
+ 0, 50, 0,132,255,220, 0, 50, 0,133,255,220, 0, 50, 0,134,255,220, 0, 50, 0,159,255,144, 0, 50, 1, 58,255,144, 0, 50,
+ 5,145,255,211, 0, 50, 5,146,255,220, 0, 50, 5,147,255, 68, 0, 51, 0, 16,255,211, 0, 51, 0, 17,254,193, 0, 51, 0, 36,
+255,125, 0, 51, 0, 60,255,211, 0, 51, 0, 68,255,164, 0, 51, 0, 72,255,183, 0, 51, 0, 76,255,211, 0, 51, 0, 81,255,220,
+ 0, 51, 0, 82,255,183, 0, 51, 0, 85,255,220, 0, 51, 0, 86,255,220, 0, 51, 0, 88,255,220, 0, 51, 0,109,255,220, 0, 51,
+ 0,130,255,125, 0, 51, 0,131,255,125, 0, 51, 0,132,255,125, 0, 51, 0,133,255,125, 0, 51, 0,134,255,125, 0, 51, 0,159,
+255,211, 0, 51, 0,162,255,164, 0, 51, 0,163,255,164, 0, 51, 0,164,255,164, 0, 51, 0,165,255,164, 0, 51, 0,166,255,164,
+ 0, 51, 0,167,255,164, 0, 51, 0,170,255,183, 0, 51, 0,171,255,183, 0, 51, 0,172,255,183, 0, 51, 0,173,255,183, 0, 51,
+ 0,179,255,220, 0, 51, 0,180,255,183, 0, 51, 0,181,255,183, 0, 51, 0,182,255,183, 0, 51, 0,183,255,183, 0, 51, 0,184,
+255,183, 0, 51, 0,187,255,220, 0, 51, 0,188,255,220, 0, 51, 0,189,255,220, 0, 51, 0,190,255,220, 0, 51, 0,221,255,183,
+ 0, 51, 1, 10,255,220, 0, 51, 1, 23,255,220, 0, 51, 1, 27,255,220, 0, 51, 1, 33,255,220, 0, 51, 1, 35,255,220, 0, 51,
+ 1, 49,255,220, 0, 51, 1, 58,255,211, 0, 51, 5,145, 0, 38, 0, 51, 5,146, 0, 38, 0, 51, 5,147,254,183, 0, 52, 0, 16,
+ 0, 57, 0, 52, 5,145,255,211, 0, 52, 5,146,255,220, 0, 52, 5,147,255,125, 0, 53, 0, 16,255,173, 0, 53, 0, 17,255,183,
+ 0, 53, 0, 29,255,193, 0, 53, 0, 36,255,173, 0, 53, 0, 38,255,154, 0, 53, 0, 55,255,107, 0, 53, 0, 57,255,144, 0, 53,
+ 0, 58,255,173, 0, 53, 0, 60,255,125, 0, 53, 0, 68,255,211, 0, 53, 0, 72,255,164, 0, 53, 0, 82,255,164, 0, 53, 0, 88,
+255,164, 0, 53, 0, 92,255,144, 0, 53, 0,109,255,144, 0, 53, 0,125,255,220, 0, 53, 0,130,255,173, 0, 53, 0,131,255,173,
+ 0, 53, 0,132,255,173, 0, 53, 0,133,255,173, 0, 53, 0,134,255,173, 0, 53, 0,137,255,154, 0, 53, 0,159,255,125, 0, 53,
+ 0,162,255,211, 0, 53, 0,163,255,211, 0, 53, 0,164,255,211, 0, 53, 0,165,255,211, 0, 53, 0,166,255,211, 0, 53, 0,167,
+255,211, 0, 53, 0,170,255,164, 0, 53, 0,171,255,164, 0, 53, 0,172,255,164, 0, 53, 0,173,255,164, 0, 53, 0,180,255,164,
+ 0, 53, 0,181,255,164, 0, 53, 0,182,255,164, 0, 53, 0,183,255,164, 0, 53, 0,184,255,164, 0, 53, 0,187,255,164, 0, 53,
+ 0,188,255,164, 0, 53, 0,189,255,164, 0, 53, 0,190,255,164, 0, 53, 0,191,255,144, 0, 53, 0,193,255,144, 0, 53, 0,200,
+255,154, 0, 53, 0,206,255,154, 0, 53, 0,221,255,164, 0, 53, 1, 38,255,107, 0, 53, 1, 49,255,164, 0, 53, 1, 58,255,125,
+ 0, 53, 5,145,255,107, 0, 53, 5,146,255,125, 0, 53, 5,147,255,220, 0, 54, 0, 36, 0, 38, 0, 54, 0,130, 0, 38, 0, 54,
+ 0,131, 0, 38, 0, 54, 0,132, 0, 38, 0, 54, 0,133, 0, 38, 0, 54, 0,134, 0, 38, 0, 55, 0, 16,255, 68, 0, 55, 0, 17,
+255, 13, 0, 55, 0, 29,255, 31, 0, 55, 0, 36,255, 97, 0, 55, 0, 38,255,136, 0, 55, 0, 55,255,220, 0, 55, 0, 68,254,173,
+ 0, 55, 0, 70,254,164, 0, 55, 0, 72,254,164, 0, 55, 0, 76,255,193, 0, 55, 0, 82,254,164, 0, 55, 0, 85,254,211, 0, 55,
+ 0, 86,254,173, 0, 55, 0, 88,254,201, 0, 55, 0, 90,254,173, 0, 55, 0, 92,254,193, 0, 55, 0,109,255, 68, 0, 55, 0,125,
+255,144, 0, 55, 0,130,255, 97, 0, 55, 0,131,255, 97, 0, 55, 0,132,255, 97, 0, 55, 0,133,255, 97, 0, 55, 0,134,255, 97,
+ 0, 55, 0,137,255,136, 0, 55, 0,162,254,173, 0, 55, 0,163,254,173, 0, 55, 0,164,254,173, 0, 55, 0,165,254,173, 0, 55,
+ 0,166,254,173, 0, 55, 0,167,254,173, 0, 55, 0,169,254,164, 0, 55, 0,170,254,164, 0, 55, 0,171,254,164, 0, 55, 0,172,
+254,164, 0, 55, 0,173,254,164, 0, 55, 0,180,254,164, 0, 55, 0,181,254,164, 0, 55, 0,182,254,164, 0, 55, 0,183,254,164,
+ 0, 55, 0,184,254,164, 0, 55, 0,187,254,201, 0, 55, 0,188,254,201, 0, 55, 0,189,254,201, 0, 55, 0,190,254,201, 0, 55,
+ 0,191,254,193, 0, 55, 0,193,254,193, 0, 55, 0,200,255,136, 0, 55, 0,201,254,164, 0, 55, 0,206,255,136, 0, 55, 0,207,
+254,164, 0, 55, 0,221,254,164, 0, 55, 1, 23,254,211, 0, 55, 1, 27,254,211, 0, 55, 1, 33,254,173, 0, 55, 1, 35,254,173,
+ 0, 55, 1, 38,255,220, 0, 55, 1, 49,254,201, 0, 55, 5,146,255,211, 0, 55, 5,147,254,248, 0, 56, 0, 61,255,220, 0, 56,
+ 1, 63,255,220, 0, 57, 0, 16,255,136, 0, 57, 0, 17,254,248, 0, 57, 0, 29,255, 89, 0, 57, 0, 36,255,125, 0, 57, 0, 50,
+255,220, 0, 57, 0, 68,255, 97, 0, 57, 0, 72,255, 97, 0, 57, 0, 76,255,211, 0, 57, 0, 82,255, 97, 0, 57, 0, 88,255,117,
+ 0, 57, 0, 92,255,201, 0, 57, 0,109,255, 78, 0, 57, 0,125,255,144, 0, 57, 0,130,255,125, 0, 57, 0,131,255,125, 0, 57,
+ 0,132,255,125, 0, 57, 0,133,255,125, 0, 57, 0,134,255,125, 0, 57, 0,148,255,220, 0, 57, 0,149,255,220, 0, 57, 0,150,
+255,220, 0, 57, 0,151,255,220, 0, 57, 0,152,255,220, 0, 57, 0,162,255, 97, 0, 57, 0,163,255, 97, 0, 57, 0,164,255, 97,
+ 0, 57, 0,165,255, 97, 0, 57, 0,166,255, 97, 0, 57, 0,167,255, 97, 0, 57, 0,170,255, 97, 0, 57, 0,171,255, 97, 0, 57,
+ 0,172,255, 97, 0, 57, 0,173,255, 97, 0, 57, 0,180,255, 97, 0, 57, 0,181,255, 97, 0, 57, 0,182,255, 97, 0, 57, 0,183,
+255, 97, 0, 57, 0,184,255, 97, 0, 57, 0,187,255,117, 0, 57, 0,188,255,117, 0, 57, 0,189,255,117, 0, 57, 0,190,255,117,
+ 0, 57, 0,191,255,201, 0, 57, 0,193,255,201, 0, 57, 0,221,255, 97, 0, 57, 1, 49,255,117, 0, 57, 5,147,254,230, 0, 58,
+ 0, 16,255,173, 0, 58, 0, 17,255, 21, 0, 58, 0, 29,255,136, 0, 58, 0, 36,255,144, 0, 58, 0, 68,255,125, 0, 58, 0, 72,
+255,136, 0, 58, 0, 76,255,211, 0, 58, 0, 82,255,136, 0, 58, 0, 85,255,164, 0, 58, 0, 88,255,183, 0, 58, 0, 92,255,220,
+ 0, 58, 0,109,255,144, 0, 58, 0,125,255,220, 0, 58, 0,130,255,144, 0, 58, 0,131,255,144, 0, 58, 0,132,255,144, 0, 58,
+ 0,133,255,144, 0, 58, 0,134,255,144, 0, 58, 0,162,255,125, 0, 58, 0,163,255,125, 0, 58, 0,164,255,125, 0, 58, 0,165,
+255,125, 0, 58, 0,166,255,125, 0, 58, 0,167,255,125, 0, 58, 0,170,255,136, 0, 58, 0,171,255,136, 0, 58, 0,172,255,136,
+ 0, 58, 0,173,255,136, 0, 58, 0,180,255,136, 0, 58, 0,181,255,136, 0, 58, 0,182,255,136, 0, 58, 0,183,255,136, 0, 58,
+ 0,184,255,136, 0, 58, 0,187,255,183, 0, 58, 0,188,255,183, 0, 58, 0,189,255,183, 0, 58, 0,190,255,183, 0, 58, 0,191,
+255,220, 0, 58, 0,193,255,220, 0, 58, 0,221,255,136, 0, 58, 1, 23,255,164, 0, 58, 1, 27,255,164, 0, 58, 1, 49,255,183,
+ 0, 58, 5,145,255,220, 0, 58, 5,147,254,248, 0, 59, 0, 16,255,154, 0, 59, 0, 38,255,107, 0, 59, 0, 50,255,125, 0, 59,
+ 0, 55,255,220, 0, 59, 0, 72,255,164, 0, 59, 0,109,255,144, 0, 59, 0,137,255,107, 0, 59, 0,148,255,125, 0, 59, 0,149,
+255,125, 0, 59, 0,150,255,125, 0, 59, 0,151,255,125, 0, 59, 0,152,255,125, 0, 59, 0,170,255,164, 0, 59, 0,171,255,164,
+ 0, 59, 0,172,255,164, 0, 59, 0,173,255,164, 0, 59, 0,200,255,107, 0, 59, 0,206,255,107, 0, 59, 0,221,255,164, 0, 59,
+ 1, 38,255,220, 0, 59, 5,145,255, 97, 0, 59, 5,146,255,173, 0, 59, 5,147,255,211, 0, 60, 0, 16,255, 13, 0, 60, 0, 17,
+254, 97, 0, 60, 0, 29,254,240, 0, 60, 0, 36,255, 97, 0, 60, 0, 38,255,144, 0, 60, 0, 50,255,144, 0, 60, 0, 68,254,230,
+ 0, 60, 0, 72,254,240, 0, 60, 0, 76,255,183, 0, 60, 0, 82,254,240, 0, 60, 0, 88,255, 21, 0, 60, 0,109,255, 31, 0, 60,
+ 0,125,255,107, 0, 60, 0,130,255, 97, 0, 60, 0,131,255, 97, 0, 60, 0,132,255, 97, 0, 60, 0,133,255, 97, 0, 60, 0,134,
+255, 97, 0, 60, 0,137,255,144, 0, 60, 0,148,255,144, 0, 60, 0,149,255,144, 0, 60, 0,150,255,144, 0, 60, 0,151,255,144,
+ 0, 60, 0,152,255,144, 0, 60, 0,162,254,230, 0, 60, 0,163,254,230, 0, 60, 0,164,254,230, 0, 60, 0,165,254,230, 0, 60,
+ 0,166,254,230, 0, 60, 0,167,254,230, 0, 60, 0,170,254,240, 0, 60, 0,171,254,240, 0, 60, 0,172,254,240, 0, 60, 0,173,
+254,240, 0, 60, 0,180,254,240, 0, 60, 0,181,254,240, 0, 60, 0,182,254,240, 0, 60, 0,183,254,240, 0, 60, 0,184,254,240,
+ 0, 60, 0,187,255, 21, 0, 60, 0,188,255, 21, 0, 60, 0,189,255, 21, 0, 60, 0,190,255, 21, 0, 60, 0,200,255,144, 0, 60,
+ 0,206,255,144, 0, 60, 0,221,254,240, 0, 60, 1, 49,255, 21, 0, 60, 5,145,255,144, 0, 60, 5,146,255,220, 0, 60, 5,147,
+254,248, 0, 61, 0, 16,255,220, 0, 61, 5,145,255,220, 0, 61, 5,146,255,220, 0, 61, 5,147,255,220, 0, 72, 0, 91,255,220,
+ 0, 73, 0, 16,255,144, 0, 73, 0, 17,255,107, 0, 73, 0, 29,255,183, 0, 73, 0, 87,255,220, 0, 73, 0, 90,255,220, 0, 73,
+ 0, 92,255,220, 0, 73, 0,109,255,183, 0, 73, 0,125,255,220, 0, 73, 0,191,255,220, 0, 73, 0,193,255,220, 0, 73, 1, 39,
+255,220, 0, 73, 5,145, 0, 65, 0, 73, 5,147,255, 21, 0, 78, 0, 68,255,220, 0, 78, 0, 72,255,183, 0, 78, 0, 82,255,183,
+ 0, 78, 0, 88,255,193, 0, 78, 0, 92,255,183, 0, 78, 0,162,255,220, 0, 78, 0,163,255,220, 0, 78, 0,164,255,220, 0, 78,
+ 0,165,255,220, 0, 78, 0,166,255,220, 0, 78, 0,167,255,220, 0, 78, 0,170,255,183, 0, 78, 0,171,255,183, 0, 78, 0,172,
+255,183, 0, 78, 0,173,255,183, 0, 78, 0,180,255,183, 0, 78, 0,181,255,183, 0, 78, 0,182,255,183, 0, 78, 0,183,255,183,
+ 0, 78, 0,184,255,183, 0, 78, 0,187,255,193, 0, 78, 0,188,255,193, 0, 78, 0,189,255,193, 0, 78, 0,190,255,193, 0, 78,
+ 0,191,255,183, 0, 78, 0,193,255,183, 0, 78, 0,221,255,183, 0, 78, 1, 49,255,193, 0, 81, 5,145,255,107, 0, 81, 5,146,
+255,144, 0, 81, 5,147,255,164, 0, 82, 0, 16, 0, 38, 0, 82, 0, 17,255,220, 0, 82, 0, 91,255,193, 0, 82, 5,145,255,107,
+ 0, 82, 5,146,255,183, 0, 82, 5,147,255,125, 0, 85, 0, 16,255,125, 0, 85, 0, 17,255, 68, 0, 85, 0, 29,255,220, 0, 85,
+ 0, 70,255,211, 0, 85, 0, 71,255,220, 0, 85, 0, 72,255,211, 0, 85, 0, 74,255,220, 0, 85, 0, 75,255,220, 0, 85, 0, 80,
+255,220, 0, 85, 0, 81,255,220, 0, 85, 0, 82,255,211, 0, 85, 0, 84,255,220, 0, 85, 0, 85,255,220, 0, 85, 0, 91,255,201,
+ 0, 85, 0,109,255,183, 0, 85, 0,169,255,211, 0, 85, 0,170,255,211, 0, 85, 0,171,255,211, 0, 85, 0,172,255,211, 0, 85,
+ 0,173,255,211, 0, 85, 0,179,255,220, 0, 85, 0,180,255,211, 0, 85, 0,181,255,211, 0, 85, 0,182,255,211, 0, 85, 0,183,
+255,211, 0, 85, 0,184,255,211, 0, 85, 0,201,255,211, 0, 85, 0,207,255,211, 0, 85, 0,209, 0, 72, 0, 85, 0,221,255,211,
+ 0, 85, 0,225,255,220, 0, 85, 1, 10,255,220, 0, 85, 1, 23,255,220, 0, 85, 1, 27,255,220, 0, 85, 5,146, 0, 86, 0, 85,
+ 5,147,254,201, 0, 89, 0, 16,255,201, 0, 89, 0, 17,255, 97, 0, 89, 0, 29,255,144, 0, 89, 0,109,255,220, 0, 89, 0,125,
+255,220, 0, 89, 5,146,255,220, 0, 89, 5,147,254,240, 0, 90, 0, 17,255, 68, 0, 90, 0, 29,255,144, 0, 90, 0,109,255,220,
+ 0, 90, 0,125,255,220, 0, 90, 5,147,255, 41, 0, 91, 0, 70,255,220, 0, 91, 0, 72,255,193, 0, 91, 0, 82,255,193, 0, 91,
+ 0,169,255,220, 0, 91, 0,170,255,193, 0, 91, 0,171,255,193, 0, 91, 0,172,255,193, 0, 91, 0,173,255,193, 0, 91, 0,180,
+255,193, 0, 91, 0,181,255,193, 0, 91, 0,182,255,193, 0, 91, 0,183,255,193, 0, 91, 0,184,255,193, 0, 91, 0,201,255,220,
+ 0, 91, 0,207,255,220, 0, 91, 0,221,255,193, 0, 92, 0, 16,255,220, 0, 92, 0, 17,254,220, 0, 92, 0, 29,255,107, 0, 92,
+ 0,109,255,220, 0, 92, 0,125,255,220, 0, 92, 5,147,254,211, 0,109, 0, 37,255,220, 0,109, 0, 38,255,220, 0,109, 0, 39,
+255,220, 0,109, 0, 42,255,220, 0,109, 0, 45,255,220, 0,109, 0, 55,255,144, 0,109, 0, 57,255,144, 0,109, 0, 58,255,220,
+ 0,109, 0, 60,255,107, 0,109, 0, 89,255,220, 0,109, 0, 90,255,220, 0,109, 0, 92,255,220, 0,109, 0,136, 0,151, 0,109,
+ 0,137,255,220, 0,109, 0,159,255,107, 0,109, 0,191,255,220, 0,109, 0,193,255,220, 0,109, 0,200,255,220, 0,109, 0,206,
+255,220, 0,109, 0,208,255,220, 0,109, 0,224,255,220, 0,109, 1, 38,255,144, 0,109, 1, 58,255,107, 0,125, 0, 36,255,183,
+ 0,125, 0, 37,255,183, 0,125, 0, 38,255,220, 0,125, 0, 39,255,220, 0,125, 0, 45,255,220, 0,125, 0, 50,255,220, 0,125,
+ 0, 55,255, 68, 0,125, 0, 57,255, 78, 0,125, 0, 58,255,144, 0,125, 0, 59,255,144, 0,125, 0, 60,255, 31, 0,125, 0, 89,
+255,220, 0,125, 0, 90,255,220, 0,125, 0, 92,255,220, 0,125, 0,130,255,183, 0,125, 0,131,255,183, 0,125, 0,132,255,183,
+ 0,125, 0,133,255,183, 0,125, 0,134,255,183, 0,125, 0,137,255,220, 0,125, 0,148,255,220, 0,125, 0,149,255,220, 0,125,
+ 0,150,255,220, 0,125, 0,151,255,220, 0,125, 0,152,255,220, 0,125, 0,159,255, 31, 0,125, 0,191,255,220, 0,125, 0,193,
+255,220, 0,125, 0,200,255,220, 0,125, 0,206,255,220, 0,125, 0,208,255,220, 0,125, 1, 38,255, 68, 0,125, 1, 58,255, 31,
+ 0,130, 0, 16,255,211, 0,130, 0, 17,255,220, 0,130, 0, 29,255,220, 0,130, 0, 36, 0, 57, 0,130, 0, 38,255,220, 0,130,
+ 0, 42,255,220, 0,130, 0, 50,255,220, 0,130, 0, 52,255,220, 0,130, 0, 55,255, 97, 0,130, 0, 57,255,125, 0,130, 0, 58,
+255,144, 0,130, 0, 60,255, 97, 0,130, 0, 70,255,220, 0,130, 0, 71,255,220, 0,130, 0, 72,255,220, 0,130, 0, 73,255,183,
+ 0,130, 0, 82,255,220, 0,130, 0, 84,255,220, 0,130, 0, 87,255,220, 0,130, 0, 89,255,136, 0,130, 0, 90,255,173, 0,130,
+ 0, 92,255,117, 0,130, 0,109,255,183, 0,130, 0,130, 0, 57, 0,130, 0,131, 0, 57, 0,130, 0,132, 0, 57, 0,130, 0,133,
+ 0, 57, 0,130, 0,134, 0, 57, 0,130, 0,137,255,220, 0,130, 0,148,255,220, 0,130, 0,149,255,220, 0,130, 0,150,255,220,
+ 0,130, 0,151,255,220, 0,130, 0,152,255,220, 0,130, 0,159,255, 97, 0,130, 0,169,255,220, 0,130, 0,170,255,220, 0,130,
+ 0,171,255,220, 0,130, 0,172,255,220, 0,130, 0,173,255,220, 0,130, 0,180,255,220, 0,130, 0,181,255,220, 0,130, 0,182,
+255,220, 0,130, 0,183,255,220, 0,130, 0,184,255,220, 0,130, 0,191,255,117, 0,130, 0,193,255,117, 0,130, 0,194, 0, 57,
+ 0,130, 0,196, 0, 57, 0,130, 0,198, 0, 57, 0,130, 0,200,255,220, 0,130, 0,201,255,220, 0,130, 0,202,255,220, 0,130,
+ 0,204,255,220, 0,130, 0,205,255,220, 0,130, 0,206,255,220, 0,130, 0,207,255,220, 0,130, 0,209,255,220, 0,130, 0,213,
+255,220, 0,130, 0,215,255,220, 0,130, 0,217,255,220, 0,130, 0,219,255,220, 0,130, 0,221,255,220, 0,130, 0,222,255,220,
+ 0,130, 0,224,255,220, 0,130, 0,226,255,220, 0,130, 1, 14,255,220, 0,130, 1, 15,255,220, 0,130, 1, 16,255,220, 0,130,
+ 1, 17,255,220, 0,130, 1, 18,255,220, 0,130, 1, 19,255,220, 0,130, 1, 36,255, 97, 0,130, 1, 37,255,220, 0,130, 1, 38,
+255, 97, 0,130, 1, 39,255,220, 0,130, 1, 54,255,144, 0,130, 1, 55,255,173, 0,130, 1, 56,255, 97, 0,130, 1, 57,255,117,
+ 0,130, 1, 58,255, 97, 0,130, 1,240,255,220, 0,130, 1,241,255,220, 0,130, 4,252,255,144, 0,130, 4,255,255,173, 0,130,
+ 5, 0,255,144, 0,130, 5, 1,255,173, 0,130, 5,106,255, 97, 0,130, 5,107,255,117, 0,130, 5,145,254,248, 0,130, 5,146,
+255, 3, 0,130, 5,147, 0, 47, 0,131, 0, 16,255,211, 0,131, 0, 17,255,220, 0,131, 0, 29,255,220, 0,131, 0, 36, 0, 57,
+ 0,131, 0, 38,255,220, 0,131, 0, 42,255,220, 0,131, 0, 50,255,220, 0,131, 0, 52,255,220, 0,131, 0, 55,255, 97, 0,131,
+ 0, 57,255,125, 0,131, 0, 58,255,144, 0,131, 0, 60,255, 97, 0,131, 0, 70,255,220, 0,131, 0, 71,255,220, 0,131, 0, 72,
+255,220, 0,131, 0, 73,255,183, 0,131, 0, 82,255,220, 0,131, 0, 84,255,220, 0,131, 0, 87,255,220, 0,131, 0, 89,255,136,
+ 0,131, 0, 90,255,173, 0,131, 0, 92,255,117, 0,131, 0,109,255,183, 0,131, 0,130, 0, 57, 0,131, 0,131, 0, 57, 0,131,
+ 0,132, 0, 57, 0,131, 0,133, 0, 57, 0,131, 0,134, 0, 57, 0,131, 0,137,255,220, 0,131, 0,148,255,220, 0,131, 0,149,
+255,220, 0,131, 0,150,255,220, 0,131, 0,151,255,220, 0,131, 0,152,255,220, 0,131, 0,159,255, 97, 0,131, 0,169,255,220,
+ 0,131, 0,170,255,220, 0,131, 0,171,255,220, 0,131, 0,172,255,220, 0,131, 0,173,255,220, 0,131, 0,180,255,220, 0,131,
+ 0,181,255,220, 0,131, 0,182,255,220, 0,131, 0,183,255,220, 0,131, 0,184,255,220, 0,131, 0,191,255,117, 0,131, 0,193,
+255,117, 0,131, 0,194, 0, 57, 0,131, 0,196, 0, 57, 0,131, 0,198, 0, 57, 0,131, 0,200,255,220, 0,131, 0,201,255,220,
+ 0,131, 0,202,255,220, 0,131, 0,204,255,220, 0,131, 0,205,255,220, 0,131, 0,206,255,220, 0,131, 0,207,255,220, 0,131,
+ 0,209,255,220, 0,131, 0,213,255,220, 0,131, 0,215,255,220, 0,131, 0,217,255,220, 0,131, 0,219,255,220, 0,131, 0,221,
+255,220, 0,131, 0,222,255,220, 0,131, 0,224,255,220, 0,131, 0,226,255,220, 0,131, 1, 14,255,220, 0,131, 1, 15,255,220,
+ 0,131, 1, 16,255,220, 0,131, 1, 17,255,220, 0,131, 1, 18,255,220, 0,131, 1, 19,255,220, 0,131, 1, 36,255, 97, 0,131,
+ 1, 37,255,220, 0,131, 1, 38,255, 97, 0,131, 1, 39,255,220, 0,131, 1, 54,255,144, 0,131, 1, 55,255,173, 0,131, 1, 56,
+255, 97, 0,131, 1, 57,255,117, 0,131, 1, 58,255, 97, 0,131, 1,240,255,220, 0,131, 1,241,255,220, 0,131, 4,252,255,144,
+ 0,131, 4,254,255,144, 0,131, 4,255,255,173, 0,131, 5, 0,255,144, 0,131, 5, 1,255,173, 0,131, 5,106,255, 97, 0,131,
+ 5,107,255,117, 0,131, 5,145,254,248, 0,131, 5,146,255, 3, 0,131, 5,147, 0, 47, 0,132, 0, 16,255,211, 0,132, 0, 17,
+255,220, 0,132, 0, 29,255,220, 0,132, 0, 36, 0, 57, 0,132, 0, 38,255,220, 0,132, 0, 42,255,220, 0,132, 0, 50,255,220,
+ 0,132, 0, 52,255,220, 0,132, 0, 55,255, 97, 0,132, 0, 57,255,125, 0,132, 0, 58,255,144, 0,132, 0, 60,255, 97, 0,132,
+ 0, 70,255,220, 0,132, 0, 71,255,220, 0,132, 0, 72,255,220, 0,132, 0, 73,255,183, 0,132, 0, 82,255,220, 0,132, 0, 84,
+255,220, 0,132, 0, 87,255,220, 0,132, 0, 89,255,136, 0,132, 0, 90,255,173, 0,132, 0, 92,255,117, 0,132, 0,109,255,183,
+ 0,132, 0,130, 0, 57, 0,132, 0,131, 0, 57, 0,132, 0,132, 0, 57, 0,132, 0,133, 0, 57, 0,132, 0,134, 0, 57, 0,132,
+ 0,137,255,220, 0,132, 0,148,255,220, 0,132, 0,149,255,220, 0,132, 0,150,255,220, 0,132, 0,151,255,220, 0,132, 0,152,
+255,220, 0,132, 0,159,255, 97, 0,132, 0,169,255,220, 0,132, 0,170,255,220, 0,132, 0,171,255,220, 0,132, 0,172,255,220,
+ 0,132, 0,173,255,220, 0,132, 0,180,255,220, 0,132, 0,181,255,220, 0,132, 0,182,255,220, 0,132, 0,183,255,220, 0,132,
+ 0,184,255,220, 0,132, 0,191,255,117, 0,132, 0,193,255,117, 0,132, 0,194, 0, 57, 0,132, 0,196, 0, 57, 0,132, 0,198,
+ 0, 57, 0,132, 0,200,255,220, 0,132, 0,201,255,220, 0,132, 0,202,255,220, 0,132, 0,204,255,220, 0,132, 0,205,255,220,
+ 0,132, 0,206,255,220, 0,132, 0,207,255,220, 0,132, 0,209,255,220, 0,132, 0,213,255,220, 0,132, 0,215,255,220, 0,132,
+ 0,217,255,220, 0,132, 0,219,255,220, 0,132, 0,221,255,220, 0,132, 0,222,255,220, 0,132, 0,224,255,220, 0,132, 0,226,
+255,220, 0,132, 1, 14,255,220, 0,132, 1, 15,255,220, 0,132, 1, 16,255,220, 0,132, 1, 17,255,220, 0,132, 1, 18,255,220,
+ 0,132, 1, 19,255,220, 0,132, 1, 36,255, 97, 0,132, 1, 37,255,220, 0,132, 1, 38,255, 97, 0,132, 1, 39,255,220, 0,132,
+ 1, 54,255,144, 0,132, 1, 55,255,173, 0,132, 1, 56,255, 97, 0,132, 1, 57,255,117, 0,132, 1, 58,255, 97, 0,132, 1,240,
+255,220, 0,132, 1,241,255,220, 0,132, 4,252,255,144, 0,132, 4,254,255,144, 0,132, 4,255,255,173, 0,132, 5, 0,255,144,
+ 0,132, 5, 1,255,173, 0,132, 5,106,255, 97, 0,132, 5,107,255,117, 0,132, 5,145,254,248, 0,132, 5,146,255, 3, 0,132,
+ 5,147, 0, 47, 0,133, 0, 16,255,211, 0,133, 0, 17,255,220, 0,133, 0, 29,255,220, 0,133, 0, 36, 0, 57, 0,133, 0, 38,
+255,220, 0,133, 0, 42,255,220, 0,133, 0, 50,255,220, 0,133, 0, 52,255,220, 0,133, 0, 55,255, 97, 0,133, 0, 57,255,125,
+ 0,133, 0, 58,255,144, 0,133, 0, 60,255, 97, 0,133, 0, 70,255,220, 0,133, 0, 71,255,220, 0,133, 0, 72,255,220, 0,133,
+ 0, 73,255,183, 0,133, 0, 82,255,220, 0,133, 0, 84,255,220, 0,133, 0, 87,255,220, 0,133, 0, 89,255,136, 0,133, 0, 90,
+255,173, 0,133, 0, 92,255,117, 0,133, 0,109,255,183, 0,133, 0,130, 0, 57, 0,133, 0,131, 0, 57, 0,133, 0,132, 0, 57,
+ 0,133, 0,133, 0, 57, 0,133, 0,134, 0, 57, 0,133, 0,137,255,220, 0,133, 0,148,255,220, 0,133, 0,149,255,220, 0,133,
+ 0,150,255,220, 0,133, 0,151,255,220, 0,133, 0,152,255,220, 0,133, 0,159,255, 97, 0,133, 0,169,255,220, 0,133, 0,170,
+255,220, 0,133, 0,171,255,220, 0,133, 0,172,255,220, 0,133, 0,173,255,220, 0,133, 0,180,255,220, 0,133, 0,181,255,220,
+ 0,133, 0,182,255,220, 0,133, 0,183,255,220, 0,133, 0,184,255,220, 0,133, 0,191,255,117, 0,133, 0,193,255,117, 0,133,
+ 0,194, 0, 57, 0,133, 0,196, 0, 57, 0,133, 0,198, 0, 57, 0,133, 0,200,255,220, 0,133, 0,201,255,220, 0,133, 0,202,
+255,220, 0,133, 0,204,255,220, 0,133, 0,205,255,220, 0,133, 0,206,255,220, 0,133, 0,207,255,220, 0,133, 0,209,255,220,
+ 0,133, 0,213,255,220, 0,133, 0,215,255,220, 0,133, 0,217,255,220, 0,133, 0,219,255,220, 0,133, 0,221,255,220, 0,133,
+ 0,222,255,220, 0,133, 0,224,255,220, 0,133, 0,226,255,220, 0,133, 1, 14,255,220, 0,133, 1, 15,255,220, 0,133, 1, 16,
+255,220, 0,133, 1, 17,255,220, 0,133, 1, 18,255,220, 0,133, 1, 19,255,220, 0,133, 1, 36,255, 97, 0,133, 1, 37,255,220,
+ 0,133, 1, 38,255, 97, 0,133, 1, 39,255,220, 0,133, 1, 54,255,144, 0,133, 1, 55,255,173, 0,133, 1, 56,255, 97, 0,133,
+ 1, 57,255,117, 0,133, 1, 58,255, 97, 0,133, 1,240,255,220, 0,133, 4,252,255,144, 0,133, 4,254,255,144, 0,133, 4,255,
+255,173, 0,133, 5, 0,255,144, 0,133, 5, 1,255,173, 0,133, 5,106,255, 97, 0,133, 5,107,255,117, 0,133, 5,145,254,248,
+ 0,133, 5,146,255, 3, 0,133, 5,147, 0, 47, 0,134, 0, 16,255,211, 0,134, 0, 17,255,220, 0,134, 0, 29,255,220, 0,134,
+ 0, 36, 0, 57, 0,134, 0, 38,255,220, 0,134, 0, 42,255,220, 0,134, 0, 50,255,220, 0,134, 0, 52,255,220, 0,134, 0, 55,
+255, 97, 0,134, 0, 57,255,125, 0,134, 0, 58,255,144, 0,134, 0, 60,255, 97, 0,134, 0, 70,255,220, 0,134, 0, 71,255,220,
+ 0,134, 0, 72,255,220, 0,134, 0, 73,255,183, 0,134, 0, 82,255,220, 0,134, 0, 84,255,220, 0,134, 0, 87,255,220, 0,134,
+ 0, 89,255,136, 0,134, 0, 90,255,173, 0,134, 0, 92,255,117, 0,134, 0,109,255,183, 0,134, 0,130, 0, 57, 0,134, 0,131,
+ 0, 57, 0,134, 0,132, 0, 57, 0,134, 0,133, 0, 57, 0,134, 0,134, 0, 57, 0,134, 0,137,255,220, 0,134, 0,148,255,220,
+ 0,134, 0,149,255,220, 0,134, 0,150,255,220, 0,134, 0,151,255,220, 0,134, 0,152,255,220, 0,134, 0,159,255, 97, 0,134,
+ 0,169,255,220, 0,134, 0,170,255,220, 0,134, 0,171,255,220, 0,134, 0,172,255,220, 0,134, 0,173,255,220, 0,134, 0,180,
+255,220, 0,134, 0,181,255,220, 0,134, 0,182,255,220, 0,134, 0,183,255,220, 0,134, 0,184,255,220, 0,134, 0,191,255,117,
+ 0,134, 0,193,255,117, 0,134, 0,194, 0, 57, 0,134, 0,196, 0, 57, 0,134, 0,198, 0, 57, 0,134, 0,200,255,220, 0,134,
+ 0,201,255,220, 0,134, 0,202,255,220, 0,134, 0,204,255,220, 0,134, 0,205,255,220, 0,134, 0,206,255,220, 0,134, 0,207,
+255,220, 0,134, 0,209,255,220, 0,134, 0,213,255,220, 0,134, 0,215,255,220, 0,134, 0,217,255,220, 0,134, 0,219,255,220,
+ 0,134, 0,221,255,220, 0,134, 0,222,255,220, 0,134, 0,224,255,220, 0,134, 0,226,255,220, 0,134, 1, 14,255,220, 0,134,
+ 1, 15,255,220, 0,134, 1, 16,255,220, 0,134, 1, 17,255,220, 0,134, 1, 18,255,220, 0,134, 1, 19,255,220, 0,134, 1, 36,
+255, 97, 0,134, 1, 37,255,220, 0,134, 1, 38,255, 97, 0,134, 1, 39,255,220, 0,134, 1, 54,255,144, 0,134, 1, 55,255,173,
+ 0,134, 1, 56,255, 97, 0,134, 1, 57,255,117, 0,134, 1, 58,255, 97, 0,134, 1,240,255,220, 0,134, 1,241,255,220, 0,134,
+ 4,252,255,144, 0,134, 4,254,255,144, 0,134, 4,255,255,173, 0,134, 5, 0,255,144, 0,134, 5, 1,255,173, 0,134, 5,106,
+255, 97, 0,134, 5,107,255,117, 0,134, 5,145,254,248, 0,134, 5,146,255, 3, 0,134, 5,147, 0, 47, 0,136, 5,145,255,173,
+ 0,136, 5,146,255,164, 0,136, 5,147,255,144, 0,137, 0, 60,255,220, 0,137, 0,109,255,220, 0,137, 0,125,255,220, 0,137,
+ 0,159,255,220, 0,137, 1, 58,255,220, 0,137, 5,146, 0, 38, 0,146, 0, 36,255,220, 0,146, 0, 57,255,220, 0,146, 0, 60,
+255,144, 0,146, 0,109,255,220, 0,146, 0,125,255,220, 0,146, 0,130,255,220, 0,146, 0,131,255,220, 0,146, 0,132,255,220,
+ 0,146, 0,133,255,220, 0,146, 0,134,255,220, 0,146, 0,159,255,144, 0,146, 0,194,255,220, 0,146, 0,196,255,220, 0,146,
+ 0,198,255,220, 0,146, 1, 56,255,144, 0,146, 1, 58,255,144, 0,146, 1,244,255,144, 0,146, 5,106,255,144, 0,146, 5,145,
+255,211, 0,146, 5,146,255,201, 0,146, 5,147,255, 68, 0,148, 0, 16, 0, 57, 0,148, 0, 17,255,173, 0,148, 0, 29,255,220,
+ 0,148, 0, 36,255,220, 0,148, 0, 57,255,220, 0,148, 0, 59,255,125, 0,148, 0, 60,255,144, 0,148, 0,109,255,220, 0,148,
+ 0,130,255,220, 0,148, 0,131,255,220, 0,148, 0,132,255,220, 0,148, 0,133,255,220, 0,148, 0,134,255,220, 0,148, 0,159,
+255,144, 0,148, 1, 58,255,144, 0,148, 5,145,255,211, 0,148, 5,146,255,220, 0,148, 5,147,255, 68, 0,149, 0, 16, 0, 57,
+ 0,149, 0, 17,255,173, 0,149, 0, 29,255,220, 0,149, 0, 36,255,220, 0,149, 0, 57,255,220, 0,149, 0, 59,255,125, 0,149,
+ 0, 60,255,144, 0,149, 0,109,255,220, 0,149, 0,130,255,220, 0,149, 0,131,255,220, 0,149, 0,132,255,220, 0,149, 0,133,
+255,220, 0,149, 0,134,255,220, 0,149, 0,159,255,144, 0,149, 1, 58,255,144, 0,149, 5,145,255,211, 0,149, 5,146,255,220,
+ 0,149, 5,147,255, 68, 0,150, 0, 16, 0, 57, 0,150, 0, 17,255,173, 0,150, 0, 29,255,220, 0,150, 0, 36,255,220, 0,150,
+ 0, 57,255,220, 0,150, 0, 59,255,125, 0,150, 0, 60,255,144, 0,150, 0,109,255,220, 0,150, 0,130,255,220, 0,150, 0,131,
+255,220, 0,150, 0,132,255,220, 0,150, 0,133,255,220, 0,150, 0,134,255,220, 0,150, 0,159,255,144, 0,150, 1, 58,255,144,
+ 0,150, 5,145,255,211, 0,150, 5,146,255,220, 0,150, 5,147,255, 68, 0,151, 0, 16, 0, 57, 0,151, 0, 17,255,173, 0,151,
+ 0, 29,255,220, 0,151, 0, 36,255,220, 0,151, 0, 57,255,220, 0,151, 0, 59,255,125, 0,151, 0, 60,255,144, 0,151, 0,109,
+255,220, 0,151, 0,130,255,220, 0,151, 0,131,255,220, 0,151, 0,132,255,220, 0,151, 0,133,255,220, 0,151, 0,134,255,220,
+ 0,151, 0,159,255,144, 0,151, 1, 58,255,144, 0,151, 5,145,255,211, 0,151, 5,146,255,220, 0,151, 5,147,255, 68, 0,152,
+ 0, 16, 0, 57, 0,152, 0, 17,255,173, 0,152, 0, 29,255,220, 0,152, 0, 36,255,220, 0,152, 0, 57,255,220, 0,152, 0, 59,
+255,125, 0,152, 0, 60,255,144, 0,152, 0,109,255,220, 0,152, 0,130,255,220, 0,152, 0,131,255,220, 0,152, 0,132,255,220,
+ 0,152, 0,133,255,220, 0,152, 0,134,255,220, 0,152, 0,159,255,144, 0,152, 1, 58,255,144, 0,152, 5,145,255,211, 0,152,
+ 5,146,255,220, 0,152, 5,147,255, 68, 0,155, 0, 61,255,220, 0,155, 1, 63,255,220, 0,156, 0, 61,255,220, 0,156, 1, 63,
+255,220, 0,157, 0, 61,255,220, 0,157, 1, 63,255,220, 0,158, 0, 61,255,220, 0,158, 1, 63,255,220, 0,159, 0, 16,255, 13,
+ 0,159, 0, 17,254, 97, 0,159, 0, 29,254,240, 0,159, 0, 36,255, 97, 0,159, 0, 38,255,144, 0,159, 0, 50,255,144, 0,159,
+ 0, 68,254,230, 0,159, 0, 72,254,240, 0,159, 0, 76,255,183, 0,159, 0, 82,254,240, 0,159, 0, 88,255, 21, 0,159, 0,109,
+255, 31, 0,159, 0,125,255,107, 0,159, 0,130,255, 97, 0,159, 0,131,255, 97, 0,159, 0,132,255, 97, 0,159, 0,133,255, 97,
+ 0,159, 0,134,255, 97, 0,159, 0,137,255,144, 0,159, 0,148,255,144, 0,159, 0,149,255,144, 0,159, 0,150,255,144, 0,159,
+ 0,151,255,144, 0,159, 0,152,255,144, 0,159, 0,162,254,230, 0,159, 0,163,254,230, 0,159, 0,164,254,230, 0,159, 0,165,
+254,230, 0,159, 0,166,254,230, 0,159, 0,167,254,230, 0,159, 0,170,254,240, 0,159, 0,171,254,240, 0,159, 0,172,254,240,
+ 0,159, 0,173,254,240, 0,159, 0,180,254,240, 0,159, 0,181,254,240, 0,159, 0,182,254,240, 0,159, 0,183,254,240, 0,159,
+ 0,184,254,240, 0,159, 0,187,255, 21, 0,159, 0,188,255, 21, 0,159, 0,189,255, 21, 0,159, 0,190,255, 21, 0,159, 0,200,
+255,144, 0,159, 0,206,255,144, 0,159, 0,221,254,240, 0,159, 1, 49,255, 21, 0,159, 5,145,255,144, 0,159, 5,146,255,220,
+ 0,159, 5,147,254,248, 0,160, 0, 17,255,107, 0,160, 0, 29,255,183, 0,160, 5,145,255,220, 0,160, 5,147,255, 68, 0,161,
+ 0, 16, 0, 38, 0,161, 5,145,255,144, 0,161, 5,146,255,144, 0,161, 5,147,255,173, 0,170, 0, 91,255,220, 0,171, 0, 91,
+255,220, 0,172, 0, 91,255,220, 0,173, 0, 91,255,220, 0,178, 5,145,255,164, 0,178, 5,146,255,144, 0,178, 5,147,255,183,
+ 0,179, 5,145,255,107, 0,179, 5,146,255,144, 0,179, 5,147,255,164, 0,180, 0, 16, 0, 38, 0,180, 0, 17,255,220, 0,180,
+ 0, 91,255,193, 0,180, 5,145,255,107, 0,180, 5,146,255,183, 0,180, 5,147,255,125, 0,181, 0, 16, 0, 38, 0,181, 0, 17,
+255,220, 0,181, 0, 91,255,193, 0,181, 5,145,255,107, 0,181, 5,146,255,183, 0,181, 5,147,255,125, 0,182, 0, 16, 0, 38,
+ 0,182, 0, 17,255,220, 0,182, 0, 91,255,193, 0,182, 5,145,255,107, 0,182, 5,146,255,183, 0,182, 5,147,255,125, 0,183,
+ 0, 16, 0, 38, 0,183, 0, 17,255,220, 0,183, 0, 91,255,193, 0,183, 5,145,255,107, 0,183, 5,146,255,183, 0,183, 5,147,
+255,125, 0,184, 0, 16, 0, 38, 0,184, 0, 17,255,220, 0,184, 0, 91,255,193, 0,184, 5,145,255,107, 0,184, 5,146,255,183,
+ 0,184, 5,147,255,125, 0,191, 0, 16,255,220, 0,191, 0, 17,254,220, 0,191, 0, 29,255,107, 0,191, 0,109,255,220, 0,191,
+ 0,125,255,220, 0,191, 5,147,254,211, 0,193, 0, 16,255,220, 0,193, 0, 17,254,220, 0,193, 0, 29,255,107, 0,193, 0,109,
+255,220, 0,193, 0,125,255,220, 0,193, 5,147,254,211, 0,194, 0, 16,255,211, 0,194, 0, 17,255,220, 0,194, 0, 29,255,220,
+ 0,194, 0, 36, 0, 57, 0,194, 0, 38,255,220, 0,194, 0, 42,255,220, 0,194, 0, 50,255,220, 0,194, 0, 52,255,220, 0,194,
+ 0, 55,255, 97, 0,194, 0, 57,255,125, 0,194, 0, 58,255,144, 0,194, 0, 60,255, 97, 0,194, 0, 70,255,220, 0,194, 0, 71,
+255,220, 0,194, 0, 72,255,220, 0,194, 0, 73,255,183, 0,194, 0, 82,255,220, 0,194, 0, 84,255,220, 0,194, 0, 87,255,220,
+ 0,194, 0, 89,255,136, 0,194, 0, 90,255,173, 0,194, 0, 92,255,117, 0,194, 0,109,255,183, 0,194, 0,130, 0, 57, 0,194,
+ 0,131, 0, 57, 0,194, 0,132, 0, 57, 0,194, 0,133, 0, 57, 0,194, 0,134, 0, 57, 0,194, 0,148,255,220, 0,194, 0,149,
+255,220, 0,194, 0,150,255,220, 0,194, 0,151,255,220, 0,194, 0,152,255,220, 0,194, 0,159,255, 97, 0,194, 0,169,255,220,
+ 0,194, 0,170,255,220, 0,194, 0,171,255,220, 0,194, 0,172,255,220, 0,194, 0,173,255,220, 0,194, 0,180,255,220, 0,194,
+ 0,181,255,220, 0,194, 0,182,255,220, 0,194, 0,183,255,220, 0,194, 0,184,255,220, 0,194, 0,191,255,117, 0,194, 0,193,
+255,117, 0,194, 0,194, 0, 57, 0,194, 0,196, 0, 57, 0,194, 0,198, 0, 57, 0,194, 0,200,255,220, 0,194, 0,202,255,220,
+ 0,194, 0,204,255,220, 0,194, 0,205,255,220, 0,194, 0,206,255,220, 0,194, 0,209,255,220, 0,194, 0,211,255,220, 0,194,
+ 0,213,255,220, 0,194, 0,215,255,220, 0,194, 0,217,255,220, 0,194, 0,219,255,220, 0,194, 0,221,255,220, 0,194, 0,222,
+255,220, 0,194, 0,226,255,220, 0,194, 1, 14,255,220, 0,194, 1, 15,255,220, 0,194, 1, 16,255,220, 0,194, 1, 17,255,220,
+ 0,194, 1, 18,255,220, 0,194, 1, 19,255,220, 0,194, 1, 36,255, 97, 0,194, 1, 37,255,220, 0,194, 1, 38,255, 97, 0,194,
+ 1, 39,255,220, 0,194, 1, 54,255,144, 0,194, 1, 55,255,173, 0,194, 1, 56,255, 97, 0,194, 1, 57,255,117, 0,194, 1, 58,
+255, 97, 0,194, 1,240,255,220, 0,194, 1,241,255,220, 0,194, 4,252,255,144, 0,194, 4,254,255,144, 0,194, 4,255,255,173,
+ 0,194, 5, 0,255,144, 0,194, 5, 1,255,173, 0,194, 5,106,255, 97, 0,194, 5,107,255,117, 0,194, 5,145,254,248, 0,194,
+ 5,146,255, 2, 0,194, 5,147, 0, 47, 0,196, 0, 16,255,211, 0,196, 0, 17,255,220, 0,196, 0, 29,255,220, 0,196, 0, 36,
+ 0, 57, 0,196, 0, 38,255,220, 0,196, 0, 42,255,220, 0,196, 0, 50,255,220, 0,196, 0, 52,255,220, 0,196, 0, 55,255, 97,
+ 0,196, 0, 57,255,125, 0,196, 0, 58,255,144, 0,196, 0, 60,255, 97, 0,196, 0, 70,255,220, 0,196, 0, 71,255,220, 0,196,
+ 0, 72,255,220, 0,196, 0, 73,255,183, 0,196, 0, 82,255,220, 0,196, 0, 84,255,220, 0,196, 0, 87,255,220, 0,196, 0, 89,
+255,136, 0,196, 0, 90,255,173, 0,196, 0, 92,255,117, 0,196, 0,109,255,183, 0,196, 0,130, 0, 57, 0,196, 0,131, 0, 57,
+ 0,196, 0,132, 0, 57, 0,196, 0,133, 0, 57, 0,196, 0,134, 0, 57, 0,196, 0,148,255,220, 0,196, 0,149,255,220, 0,196,
+ 0,150,255,220, 0,196, 0,151,255,220, 0,196, 0,152,255,220, 0,196, 0,159,255, 97, 0,196, 0,169,255,220, 0,196, 0,170,
+255,220, 0,196, 0,171,255,220, 0,196, 0,172,255,220, 0,196, 0,173,255,220, 0,196, 0,180,255,220, 0,196, 0,181,255,220,
+ 0,196, 0,182,255,220, 0,196, 0,183,255,220, 0,196, 0,184,255,220, 0,196, 0,191,255,117, 0,196, 0,193,255,117, 0,196,
+ 0,194, 0, 57, 0,196, 0,196, 0, 57, 0,196, 0,198, 0, 57, 0,196, 0,200,255,220, 0,196, 0,202,255,220, 0,196, 0,204,
+255,220, 0,196, 0,205,255,220, 0,196, 0,206,255,220, 0,196, 0,209,255,220, 0,196, 0,211,255,220, 0,196, 0,213,255,220,
+ 0,196, 0,215,255,220, 0,196, 0,217,255,220, 0,196, 0,219,255,220, 0,196, 0,221,255,220, 0,196, 0,222,255,220, 0,196,
+ 0,226,255,220, 0,196, 1, 14,255,220, 0,196, 1, 15,255,220, 0,196, 1, 16,255,220, 0,196, 1, 17,255,220, 0,196, 1, 18,
+255,220, 0,196, 1, 19,255,220, 0,196, 1, 36,255, 97, 0,196, 1, 37,255,220, 0,196, 1, 38,255, 97, 0,196, 1, 39,255,220,
+ 0,196, 1, 54,255,144, 0,196, 1, 55,255,173, 0,196, 1, 56,255, 97, 0,196, 1, 57,255,117, 0,196, 1, 58,255, 97, 0,196,
+ 1,240,255,220, 0,196, 1,241,255,220, 0,196, 4,252,255,144, 0,196, 4,254,255,144, 0,196, 4,255,255,173, 0,196, 5, 0,
+255,144, 0,196, 5, 1,255,173, 0,196, 5,106,255, 97, 0,196, 5,107,255,117, 0,196, 5,145,254,248, 0,196, 5,146,255, 2,
+ 0,196, 5,147, 0, 47, 0,198, 0, 16,255,211, 0,198, 0, 17,255,220, 0,198, 0, 29,255,220, 0,198, 0, 36, 0, 57, 0,198,
+ 0, 38,255,220, 0,198, 0, 42,255,220, 0,198, 0, 50,255,220, 0,198, 0, 52,255,220, 0,198, 0, 55,255, 97, 0,198, 0, 57,
+255,125, 0,198, 0, 58,255,144, 0,198, 0, 60,255, 97, 0,198, 0, 70,255,220, 0,198, 0, 71,255,220, 0,198, 0, 72,255,220,
+ 0,198, 0, 73,255,183, 0,198, 0, 82,255,220, 0,198, 0, 84,255,220, 0,198, 0, 87,255,220, 0,198, 0, 89,255,136, 0,198,
+ 0, 90,255,173, 0,198, 0,109,255,183, 0,198, 0,130, 0, 57, 0,198, 0,131, 0, 57, 0,198, 0,132, 0, 57, 0,198, 0,133,
+ 0, 57, 0,198, 0,134, 0, 57, 0,198, 0,148,255,220, 0,198, 0,149,255,220, 0,198, 0,150,255,220, 0,198, 0,151,255,220,
+ 0,198, 0,152,255,220, 0,198, 0,159,255, 97, 0,198, 0,169,255,220, 0,198, 0,170,255,220, 0,198, 0,171,255,220, 0,198,
+ 0,172,255,220, 0,198, 0,173,255,220, 0,198, 0,180,255,220, 0,198, 0,181,255,220, 0,198, 0,182,255,220, 0,198, 0,183,
+255,220, 0,198, 0,184,255,220, 0,198, 0,194, 0, 57, 0,198, 0,196, 0, 57, 0,198, 0,198, 0, 57, 0,198, 0,200,255,220,
+ 0,198, 0,202,255,220, 0,198, 0,204,255,220, 0,198, 0,205,255,220, 0,198, 0,206,255,220, 0,198, 0,209,255,220, 0,198,
+ 0,211,255,220, 0,198, 0,213,255,220, 0,198, 0,215,255,220, 0,198, 0,217,255,220, 0,198, 0,219,255,220, 0,198, 0,221,
+255,220, 0,198, 0,222,255,220, 0,198, 0,226,255,220, 0,198, 1, 14,255,220, 0,198, 1, 15,255,220, 0,198, 1, 16,255,220,
+ 0,198, 1, 17,255,220, 0,198, 1, 19,255,220, 0,198, 1, 36,255, 97, 0,198, 1, 37,255,220, 0,198, 1, 38,255, 97, 0,198,
+ 1, 39,255,220, 0,198, 1, 54,255,144, 0,198, 1, 55,255,173, 0,198, 1, 56,255, 97, 0,198, 1, 58,255, 97, 0,198, 1,240,
+255,220, 0,198, 1,241,255,220, 0,198, 4,252,255,144, 0,198, 4,254,255,144, 0,198, 4,255,255,173, 0,198, 5, 0,255,144,
+ 0,198, 5, 1,255,173, 0,198, 5,106,255, 97, 0,198, 5,145,254,248, 0,198, 5,146,255, 2, 0,198, 5,147, 0, 47, 0,200,
+ 0, 60,255,220, 0,200, 0,109,255,220, 0,200, 0,125,255,220, 0,200, 0,159,255,220, 0,200, 1, 58,255,220, 0,200, 5,146,
+ 0, 38, 0,206, 0, 60,255,220, 0,206, 0,109,255,220, 0,206, 0,125,255,220, 0,206, 0,159,255,220, 0,206, 1, 58,255,220,
+ 0,206, 5,146, 0, 38, 0,208, 0, 36,255,220, 0,208, 0, 57,255,220, 0,208, 0, 60,255,144, 0,208, 0,109,255,220, 0,208,
+ 0,125,255,220, 0,208, 0,130,255,220, 0,208, 0,131,255,220, 0,208, 0,132,255,220, 0,208, 0,133,255,220, 0,208, 0,134,
+255,220, 0,208, 0,159,255,144, 0,208, 0,194,255,220, 0,208, 0,196,255,220, 0,208, 0,198,255,220, 0,208, 1, 56,255,144,
+ 0,208, 1, 58,255,144, 0,208, 1,244,255,144, 0,208, 5,106,255,144, 0,208, 5,145,255,211, 0,208, 5,146,255,201, 0,208,
+ 5,147,255, 68, 0,210, 0, 36,255,220, 0,210, 0, 57,255,220, 0,210, 0, 60,255,144, 0,210, 0,109,255,220, 0,210, 0,125,
+255,220, 0,210, 0,130,255,220, 0,210, 0,131,255,220, 0,210, 0,132,255,220, 0,210, 0,133,255,220, 0,210, 0,134,255,220,
+ 0,210, 0,159,255,144, 0,210, 1, 58,255,144, 0,210, 5,145,255,211, 0,210, 5,146,255,201, 0,210, 5,147,255, 68, 0,221,
+ 0, 91,255,220, 0,224, 0, 55,255,183, 0,224, 0, 60,255,154, 0,224, 0,109,255,220, 0,224, 0,125,255,220, 0,224, 0,159,
+255,154, 0,224, 1, 38,255,183, 0,224, 1, 58,255,154, 0,224, 5,145,255,211, 0,224, 5,146,255,211, 0,224, 5,147,255,201,
+ 0,251, 0, 16,255,220, 0,251, 0, 36, 0, 47, 0,251, 0, 50,255,183, 0,251, 0, 55,254,230, 0,251, 0, 56,255,154, 0,251,
+ 0, 57,255, 31, 0,251, 0, 58,255, 68, 0,251, 0, 60,254,240, 0,251, 0, 72,255,220, 0,251, 0, 82,255,220, 0,251, 0, 88,
+255,220, 0,251, 0, 92,255, 68, 0,251, 0,130, 0, 47, 0,251, 0,131, 0, 47, 0,251, 0,132, 0, 47, 0,251, 0,133, 0, 47,
+ 0,251, 0,134, 0, 47, 0,251, 0,148,255,183, 0,251, 0,149,255,183, 0,251, 0,150,255,183, 0,251, 0,151,255,183, 0,251,
+ 0,152,255,183, 0,251, 0,155,255,154, 0,251, 0,156,255,154, 0,251, 0,157,255,154, 0,251, 0,158,255,154, 0,251, 0,159,
+254,240, 0,251, 0,170,255,220, 0,251, 0,171,255,220, 0,251, 0,172,255,220, 0,251, 0,173,255,220, 0,251, 0,180,255,220,
+ 0,251, 0,181,255,220, 0,251, 0,182,255,220, 0,251, 0,183,255,220, 0,251, 0,184,255,220, 0,251, 0,187,255,220, 0,251,
+ 0,188,255,220, 0,251, 0,189,255,220, 0,251, 0,190,255,220, 0,251, 0,191,255, 68, 0,251, 0,193,255, 68, 0,251, 0,221,
+255,220, 0,251, 1, 38,254,230, 0,251, 1, 48,255,154, 0,251, 1, 49,255,220, 0,251, 1, 58,254,240, 0,251, 5,145,254, 97,
+ 0,251, 5,146,253,230, 0,255, 0, 16,255,220, 0,255, 0, 36, 0, 47, 0,255, 0, 50,255,183, 0,255, 0, 55,254,230, 0,255,
+ 0, 56,255,154, 0,255, 0, 57,255, 31, 0,255, 0, 58,255, 68, 0,255, 0, 60,254,240, 0,255, 0, 72,255,220, 0,255, 0, 82,
+255,220, 0,255, 0, 88,255,220, 0,255, 0, 92,255, 68, 0,255, 0,130, 0, 47, 0,255, 0,131, 0, 47, 0,255, 0,132, 0, 47,
+ 0,255, 0,133, 0, 47, 0,255, 0,134, 0, 47, 0,255, 0,148,255,183, 0,255, 0,149,255,183, 0,255, 0,150,255,183, 0,255,
+ 0,151,255,183, 0,255, 0,152,255,183, 0,255, 0,155,255,154, 0,255, 0,156,255,154, 0,255, 0,157,255,154, 0,255, 0,158,
+255,154, 0,255, 0,159,254,240, 0,255, 0,170,255,220, 0,255, 0,171,255,220, 0,255, 0,172,255,220, 0,255, 0,173,255,220,
+ 0,255, 0,180,255,220, 0,255, 0,181,255,220, 0,255, 0,182,255,220, 0,255, 0,183,255,220, 0,255, 0,184,255,220, 0,255,
+ 0,187,255,220, 0,255, 0,188,255,220, 0,255, 0,189,255,220, 0,255, 0,190,255,220, 0,255, 0,191,255, 68, 0,255, 0,193,
+255, 68, 0,255, 0,221,255,220, 0,255, 1, 38,254,230, 0,255, 1, 48,255,154, 0,255, 1, 49,255,220, 0,255, 1, 58,254,240,
+ 0,255, 5,145,254, 97, 0,255, 5,146,253,230, 1, 2, 0, 79,255, 63, 1, 10, 5,145,255,107, 1, 10, 5,146,255,144, 1, 10,
+ 5,147,255,164, 1, 22, 0, 16,255,173, 1, 22, 0, 17,255,183, 1, 22, 0, 29,255,193, 1, 22, 0, 36,255,173, 1, 22, 0, 38,
+255,154, 1, 22, 0, 55,255,107, 1, 22, 0, 57,255,144, 1, 22, 0, 58,255,173, 1, 22, 0, 60,255,125, 1, 22, 0, 68,255,211,
+ 1, 22, 0, 72,255,164, 1, 22, 0, 82,255,164, 1, 22, 0, 88,255,164, 1, 22, 0, 92,255,144, 1, 22, 0,109,255,144, 1, 22,
+ 0,125,255,220, 1, 22, 0,130,255,173, 1, 22, 0,131,255,173, 1, 22, 0,132,255,173, 1, 22, 0,133,255,173, 1, 22, 0,134,
+255,173, 1, 22, 0,137,255,154, 1, 22, 0,159,255,125, 1, 22, 0,162,255,211, 1, 22, 0,163,255,211, 1, 22, 0,164,255,211,
+ 1, 22, 0,165,255,211, 1, 22, 0,166,255,211, 1, 22, 0,167,255,211, 1, 22, 0,170,255,164, 1, 22, 0,171,255,164, 1, 22,
+ 0,172,255,164, 1, 22, 0,173,255,164, 1, 22, 0,180,255,164, 1, 22, 0,181,255,164, 1, 22, 0,182,255,164, 1, 22, 0,183,
+255,164, 1, 22, 0,184,255,164, 1, 22, 0,187,255,164, 1, 22, 0,188,255,164, 1, 22, 0,189,255,164, 1, 22, 0,190,255,164,
+ 1, 22, 0,191,255,144, 1, 22, 0,193,255,144, 1, 22, 0,200,255,154, 1, 22, 0,206,255,154, 1, 22, 0,221,255,164, 1, 22,
+ 1, 38,255,107, 1, 22, 1, 49,255,164, 1, 22, 1, 58,255,125, 1, 22, 5,145,255,107, 1, 22, 5,146,255,125, 1, 22, 5,147,
+255,220, 1, 23, 0, 16,255,125, 1, 23, 0, 17,255, 68, 1, 23, 0, 29,255,220, 1, 23, 0, 70,255,211, 1, 23, 0, 71,255,220,
+ 1, 23, 0, 72,255,211, 1, 23, 0, 74,255,220, 1, 23, 0, 75,255,220, 1, 23, 0, 80,255,220, 1, 23, 0, 81,255,220, 1, 23,
+ 0, 82,255,211, 1, 23, 0, 84,255,220, 1, 23, 0, 85,255,220, 1, 23, 0, 91,255,201, 1, 23, 0,109,255,183, 1, 23, 0,169,
+255,211, 1, 23, 0,170,255,211, 1, 23, 0,171,255,211, 1, 23, 0,172,255,211, 1, 23, 0,173,255,211, 1, 23, 0,179,255,220,
+ 1, 23, 0,180,255,211, 1, 23, 0,181,255,211, 1, 23, 0,182,255,211, 1, 23, 0,183,255,211, 1, 23, 0,184,255,211, 1, 23,
+ 0,201,255,211, 1, 23, 0,207,255,211, 1, 23, 0,209, 0, 72, 1, 23, 0,221,255,211, 1, 23, 0,225,255,220, 1, 23, 1, 10,
+255,220, 1, 23, 1, 23,255,220, 1, 23, 1, 27,255,220, 1, 23, 5,146, 0, 86, 1, 23, 5,147,254,201, 1, 26, 0, 16,255,173,
+ 1, 26, 0, 17,255,183, 1, 26, 0, 29,255,193, 1, 26, 0, 36,255,173, 1, 26, 0, 38,255,154, 1, 26, 0, 55,255,107, 1, 26,
+ 0, 57,255,144, 1, 26, 0, 58,255,173, 1, 26, 0, 60,255,125, 1, 26, 0, 68,255,211, 1, 26, 0, 72,255,164, 1, 26, 0, 82,
+255,164, 1, 26, 0, 88,255,164, 1, 26, 0, 92,255,144, 1, 26, 0,109,255,144, 1, 26, 0,125,255,220, 1, 26, 0,130,255,173,
+ 1, 26, 0,131,255,173, 1, 26, 0,132,255,173, 1, 26, 0,133,255,173, 1, 26, 0,134,255,173, 1, 26, 0,137,255,154, 1, 26,
+ 0,159,255,125, 1, 26, 0,162,255,211, 1, 26, 0,163,255,211, 1, 26, 0,164,255,211, 1, 26, 0,165,255,211, 1, 26, 0,166,
+255,211, 1, 26, 0,167,255,211, 1, 26, 0,170,255,164, 1, 26, 0,171,255,164, 1, 26, 0,172,255,164, 1, 26, 0,173,255,164,
+ 1, 26, 0,180,255,164, 1, 26, 0,181,255,164, 1, 26, 0,182,255,164, 1, 26, 0,183,255,164, 1, 26, 0,184,255,164, 1, 26,
+ 0,187,255,164, 1, 26, 0,188,255,164, 1, 26, 0,189,255,164, 1, 26, 0,190,255,164, 1, 26, 0,191,255,144, 1, 26, 0,193,
+255,144, 1, 26, 0,200,255,154, 1, 26, 0,206,255,154, 1, 26, 0,221,255,164, 1, 26, 1, 38,255,107, 1, 26, 1, 49,255,164,
+ 1, 26, 1, 58,255,125, 1, 26, 5,145,255,107, 1, 26, 5,146,255,125, 1, 26, 5,147,255,220, 1, 27, 0, 16,255,125, 1, 27,
+ 0, 17,255, 68, 1, 27, 0, 29,255,220, 1, 27, 0, 70,255,211, 1, 27, 0, 71,255,220, 1, 27, 0, 72,255,211, 1, 27, 0, 74,
+255,220, 1, 27, 0, 75,255,220, 1, 27, 0, 80,255,220, 1, 27, 0, 81,255,220, 1, 27, 0, 82,255,211, 1, 27, 0, 84,255,220,
+ 1, 27, 0, 85,255,220, 1, 27, 0, 91,255,201, 1, 27, 0,109,255,183, 1, 27, 0,169,255,211, 1, 27, 0,170,255,211, 1, 27,
+ 0,171,255,211, 1, 27, 0,172,255,211, 1, 27, 0,173,255,211, 1, 27, 0,179,255,220, 1, 27, 0,180,255,211, 1, 27, 0,181,
+255,211, 1, 27, 0,182,255,211, 1, 27, 0,183,255,211, 1, 27, 0,184,255,211, 1, 27, 0,201,255,211, 1, 27, 0,207,255,211,
+ 1, 27, 0,209,255,220, 1, 27, 0,221,255,211, 1, 27, 0,225,255,220, 1, 27, 1, 10,255,220, 1, 27, 1, 23,255,220, 1, 27,
+ 1, 27,255,220, 1, 27, 5,146, 0, 86, 1, 27, 5,147,254,201, 1, 32, 0, 36, 0, 38, 1, 32, 0,130, 0, 38, 1, 32, 0,131,
+ 0, 38, 1, 32, 0,132, 0, 38, 1, 32, 0,133, 0, 38, 1, 32, 0,134, 0, 38, 1, 34, 0, 36, 0, 38, 1, 34, 0,130, 0, 38,
+ 1, 34, 0,131, 0, 38, 1, 34, 0,132, 0, 38, 1, 34, 0,133, 0, 38, 1, 34, 0,134, 0, 38, 1, 38, 0, 16,255, 68, 1, 38,
+ 0, 17,255, 13, 1, 38, 0, 29,255, 31, 1, 38, 0, 36,255, 97, 1, 38, 0, 38,255,136, 1, 38, 0, 55,255,220, 1, 38, 0, 68,
+254,173, 1, 38, 0, 70,254,164, 1, 38, 0, 72,254,164, 1, 38, 0, 76,255,193, 1, 38, 0, 82,254,164, 1, 38, 0, 85,254,211,
+ 1, 38, 0, 86,254,173, 1, 38, 0, 88,254,201, 1, 38, 0, 90,254,173, 1, 38, 0, 92,254,193, 1, 38, 0,109,255, 68, 1, 38,
+ 0,125,255,144, 1, 38, 0,130,255, 97, 1, 38, 0,131,255, 97, 1, 38, 0,132,255, 97, 1, 38, 0,133,255, 97, 1, 38, 0,134,
+255, 97, 1, 38, 0,137,255,136, 1, 38, 0,162,254,173, 1, 38, 0,163,254,173, 1, 38, 0,164,254,173, 1, 38, 0,165,254,173,
+ 1, 38, 0,166,254,173, 1, 38, 0,167,254,173, 1, 38, 0,169,254,164, 1, 38, 0,170,254,164, 1, 38, 0,171,254,164, 1, 38,
+ 0,172,254,164, 1, 38, 0,173,254,164, 1, 38, 0,180,254,164, 1, 38, 0,181,254,164, 1, 38, 0,182,254,164, 1, 38, 0,183,
+254,164, 1, 38, 0,184,254,164, 1, 38, 0,187,254,201, 1, 38, 0,188,254,201, 1, 38, 0,189,254,201, 1, 38, 0,190,254,201,
+ 1, 38, 0,191,254,193, 1, 38, 0,193,254,193, 1, 38, 0,200,255,136, 1, 38, 0,201,254,164, 1, 38, 0,206,255,136, 1, 38,
+ 0,207,254,164, 1, 38, 0,221,254,164, 1, 38, 1, 23,254,211, 1, 38, 1, 27,254,211, 1, 38, 1, 33,254,173, 1, 38, 1, 35,
+254,173, 1, 38, 1, 38,255,220, 1, 38, 1, 49,254,201, 1, 38, 5,146,255,211, 1, 38, 5,147,254,248, 1, 48, 0, 61,255,220,
+ 1, 48, 1, 63,255,220, 1, 58, 0, 16,255, 13, 1, 58, 0, 17,254, 97, 1, 58, 0, 29,254,240, 1, 58, 0, 36,255, 97, 1, 58,
+ 0, 38,255,144, 1, 58, 0, 50,255,144, 1, 58, 0, 68,254,230, 1, 58, 0, 72,254,240, 1, 58, 0, 76,255,183, 1, 58, 0, 82,
+254,240, 1, 58, 0, 88,255, 21, 1, 58, 0,109,255, 31, 1, 58, 0,125,255,107, 1, 58, 0,130,255, 97, 1, 58, 0,131,255, 97,
+ 1, 58, 0,132,255, 97, 1, 58, 0,133,255, 97, 1, 58, 0,134,255, 97, 1, 58, 0,137,255,144, 1, 58, 0,148,255,144, 1, 58,
+ 0,149,255,144, 1, 58, 0,150,255,144, 1, 58, 0,151,255,144, 1, 58, 0,152,255,144, 1, 58, 0,162,254,230, 1, 58, 0,163,
+254,230, 1, 58, 0,164,254,230, 1, 58, 0,165,254,230, 1, 58, 0,166,254,230, 1, 58, 0,167,254,230, 1, 58, 0,170,254,240,
+ 1, 58, 0,171,254,240, 1, 58, 0,172,254,240, 1, 58, 0,173,254,240, 1, 58, 0,180,254,240, 1, 58, 0,181,254,240, 1, 58,
+ 0,182,254,240, 1, 58, 0,183,254,240, 1, 58, 0,184,254,240, 1, 58, 0,187,255, 21, 1, 58, 0,188,255, 21, 1, 58, 0,189,
+255, 21, 1, 58, 0,190,255, 21, 1, 58, 0,200,255,144, 1, 58, 0,206,255,144, 1, 58, 0,221,254,240, 1, 58, 1, 49,255, 21,
+ 1, 58, 5,145,255,144, 1, 58, 5,146,255,220, 1, 58, 5,147,254,248, 1, 63, 0, 16,255,220, 1, 63, 5,145,255,220, 1, 63,
+ 5,146,255,220, 1, 63, 5,147,255,220, 5,133, 0, 36,255,211, 5,133, 0, 37,255,183, 5,133, 0, 42, 0, 75, 5,133, 0, 45,
+ 0,114, 5,133, 0, 50, 0, 57, 5,133, 0, 52, 0, 75, 5,133, 0, 55,255, 68, 5,133, 0, 57,255,136, 5,133, 0, 58,255,173,
+ 5,133, 0, 59,255,154, 5,133, 0, 60,255, 13, 5,133, 0, 82, 0, 38, 5,133, 0, 89,255,201, 5,133, 0, 92,255,220, 5,133,
+ 0,130,255,211, 5,133, 0,131,255,211, 5,133, 0,132,255,211, 5,133, 0,133,255,211, 5,133, 0,134,255,211, 5,133, 0,148,
+ 0, 57, 5,133, 0,149, 0, 57, 5,133, 0,150, 0, 57, 5,133, 0,151, 0, 57, 5,133, 0,152, 0, 57, 5,133, 0,159,255, 13,
+ 5,133, 0,180, 0, 38, 5,133, 0,181, 0, 38, 5,133, 0,182, 0, 38, 5,133, 0,183, 0, 38, 5,133, 0,184, 0, 38, 5,133,
+ 0,191,255,220, 5,133, 0,193,255,220, 5,133, 0,224, 0, 75, 5,133, 1, 38,255, 68, 5,133, 1, 58,255, 13, 5,145, 0, 36,
+254,248, 5,145, 0, 37,255,193, 5,145, 0, 38,255,183, 5,145, 0, 39,255,193, 5,145, 0, 41,255,193, 5,145, 0, 42,255,183,
+ 5,145, 0, 43,255,193, 5,145, 0, 45,255,193, 5,145, 0, 46,255,193, 5,145, 0, 47,255,193, 5,145, 0, 50,255,183, 5,145,
+ 0, 51,255,193, 5,145, 0, 52,255,183, 5,145, 0, 53,255,193, 5,145, 0, 59,255,136, 5,145, 0, 61,255,220, 5,145, 0, 73,
+255,183, 5,145, 0, 81,255,144, 5,145, 0, 82,255,107, 5,145, 0, 85,255,144, 5,145, 0, 89,255,183, 5,145, 0, 90,255,183,
+ 5,145, 0, 92,255,183, 5,145, 0,130,254,248, 5,145, 0,131,254,248, 5,145, 0,132,254,248, 5,145, 0,133,254,248, 5,145,
+ 0,134,254,248, 5,145, 0,136,254,125, 5,145, 0,137,255,183, 5,145, 0,148,255,183, 5,145, 0,149,255,183, 5,145, 0,150,
+255,183, 5,145, 0,151,255,183, 5,145, 0,152,255,183, 5,145, 0,160,255,193, 5,145, 0,161,255,193, 5,145, 0,178,255,183,
+ 5,145, 0,179,255,144, 5,145, 0,180,255,107, 5,145, 0,181,255,107, 5,145, 0,182,255,107, 5,145, 0,183,255,107, 5,145,
+ 0,184,255,107, 5,145, 0,191,255,183, 5,145, 0,193,255,183, 5,145, 0,200,255,183, 5,145, 0,206,255,183, 5,145, 0,208,
+255,193, 5,145, 0,224,255,183, 5,145, 0,251,255,193, 5,145, 0,255,255,193, 5,145, 1, 10,255,144, 5,145, 1, 22,255,193,
+ 5,145, 1, 23,255,144, 5,145, 1, 26,255,193, 5,145, 1, 27,255,144, 5,145, 1, 63,255,220, 5,147, 0, 36, 0, 38, 5,147,
+ 0, 37,255,183, 5,147, 0, 38,255,144, 5,147, 0, 39,255,183, 5,147, 0, 41,255,183, 5,147, 0, 42,255,183, 5,147, 0, 43,
+255,183, 5,147, 0, 45, 0, 47, 5,147, 0, 46,255,183, 5,147, 0, 47,255,183, 5,147, 0, 50,255,144, 5,147, 0, 51,255,183,
+ 5,147, 0, 52,255,144, 5,147, 0, 53,255,183, 5,147, 0, 55,254,230, 5,147, 0, 57,254,136, 5,147, 0, 58,255, 3, 5,147,
+ 0, 59,255,183, 5,147, 0, 60,254,136, 5,147, 0, 73,255,220, 5,147, 0, 81,255,183, 5,147, 0, 82,255,183, 5,147, 0, 85,
+255,183, 5,147, 0, 89,255, 21, 5,147, 0, 90,255, 60, 5,147, 0, 92,255,144, 5,147, 0,130, 0, 38, 5,147, 0,131, 0, 38,
+ 5,147, 0,132, 0, 38, 5,147, 0,133, 0, 38, 5,147, 0,134, 0, 38, 5,147, 0,136, 0, 38, 5,147, 0,137,255,144, 5,147,
+ 0,148,255,144, 5,147, 0,149,255,144, 5,147, 0,150,255,144, 5,147, 0,151,255,144, 5,147, 0,152,255,144, 5,147, 0,159,
+254,136, 5,147, 0,160,255,183, 5,147, 0,161,255,183, 5,147, 0,178,255,183, 5,147, 0,179,255,183, 5,147, 0,180,255,183,
+ 5,147, 0,181,255,183, 5,147, 0,182,255,183, 5,147, 0,183,255,183, 5,147, 0,184,255,183, 5,147, 0,191,255,144, 5,147,
+ 0,193,255,144, 5,147, 0,200,255,144, 5,147, 0,206,255,144, 5,147, 0,208,255,183, 5,147, 0,224,255,183, 5,147, 0,251,
+255,183, 5,147, 0,255,255,183, 5,147, 1, 10,255,183, 5,147, 1, 22,255,183, 5,147, 1, 23,255,183, 5,147, 1, 26,255,183,
+ 5,147, 1, 27,255,183, 5,147, 1, 38,254,230, 5,147, 1, 58,254,136, 0, 0, 0, 0, 0, 61, 2,226, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0,152, 1, 50, 0, 1, 0, 0, 0, 0, 0, 1, 0, 11, 1,227, 0, 1, 0, 0, 0, 0, 0, 2, 0, 4, 1,249, 0, 1,
+ 0, 0, 0, 0, 0, 3, 0, 11, 2, 22, 0, 1, 0, 0, 0, 0, 0, 4, 0, 11, 2, 58, 0, 1, 0, 0, 0, 0, 0, 5, 0, 11,
+ 2, 94, 0, 1, 0, 0, 0, 0, 0, 6, 0, 10, 2,128, 0, 1, 0, 0, 0, 0, 0, 8, 0, 17, 2,175, 0, 1, 0, 0, 0, 0,
+ 0, 11, 0, 29, 2,253, 0, 1, 0, 0, 0, 0, 0, 13, 18,157, 40, 87, 0, 1, 0, 0, 0, 0, 0, 14, 0, 52, 59, 95, 0, 1,
+ 0, 0, 0, 0, 1, 0, 0, 24, 59,148, 0, 1, 0, 0, 0, 0, 1, 1, 0, 9, 60, 27, 0, 1, 0, 0, 0, 0, 1, 2, 0, 18,
+ 60, 76, 0, 1, 0, 0, 0, 0, 1, 3, 0, 9, 60,139, 0, 1, 0, 0, 0, 0, 1, 4, 0, 17, 60,167, 0, 1, 0, 0, 0, 0,
+ 1, 5, 0, 16, 61, 22, 0, 1, 0, 0, 0, 0, 1, 6, 0, 14, 61,125, 0, 1, 0, 0, 0, 0, 1, 7, 0, 7, 61,207, 0, 1,
+ 0, 0, 0, 0, 1, 8, 0, 18, 61,245, 0, 1, 0, 0, 0, 1, 1, 0, 0, 24, 59,173, 0, 1, 0, 0, 0, 1, 1, 1, 0, 9,
+ 60, 37, 0, 1, 0, 0, 0, 1, 1, 2, 0, 23, 60, 95, 0, 1, 0, 0, 0, 1, 1, 3, 0, 9, 60,149, 0, 1, 0, 0, 0, 1,
+ 1, 4, 0, 31, 60,185, 0, 1, 0, 0, 0, 1, 1, 5, 0, 18, 61, 39, 0, 1, 0, 0, 0, 1, 1, 6, 0, 15, 61,140, 0, 1,
+ 0, 0, 0, 1, 1, 7, 0, 21, 61,215, 0, 1, 0, 0, 0, 1, 1, 8, 0, 22, 62, 8, 0, 1, 0, 0, 0, 2, 1, 0, 0, 33,
+ 59,198, 0, 1, 0, 0, 0, 2, 1, 1, 0, 9, 60, 47, 0, 1, 0, 0, 0, 2, 1, 4, 0, 23, 60,217, 0, 1, 0, 0, 0, 2,
+ 1, 5, 0, 17, 61, 58, 0, 1, 0, 0, 0, 2, 1, 6, 0, 17, 61,156, 0, 1, 0, 0, 0, 2, 1, 8, 0, 16, 62, 31, 0, 1,
+ 0, 0, 0, 3, 1, 0, 0, 21, 59,232, 0, 1, 0, 0, 0, 3, 1, 1, 0, 8, 60, 57, 0, 1, 0, 0, 0, 3, 1, 4, 0, 17,
+ 60,241, 0, 1, 0, 0, 0, 3, 1, 5, 0, 19, 61, 76, 0, 1, 0, 0, 0, 3, 1, 6, 0, 13, 61,174, 0, 1, 0, 0, 0, 3,
+ 1, 8, 0, 18, 62, 48, 0, 1, 0, 0, 0, 4, 1, 0, 0, 28, 59,254, 0, 1, 0, 0, 0, 4, 1, 1, 0, 9, 60, 66, 0, 1,
+ 0, 0, 0, 4, 1, 2, 0, 19, 60,119, 0, 1, 0, 0, 0, 4, 1, 3, 0, 7, 60,159, 0, 1, 0, 0, 0, 4, 1, 4, 0, 18,
+ 61, 3, 0, 1, 0, 0, 0, 4, 1, 5, 0, 28, 61, 96, 0, 1, 0, 0, 0, 4, 1, 6, 0, 18, 61,188, 0, 1, 0, 0, 0, 4,
+ 1, 7, 0, 7, 61,237, 0, 1, 0, 0, 0, 4, 1, 8, 0, 17, 62, 67, 0, 3, 0, 1, 4, 9, 0, 0, 1, 48, 0, 0, 0, 3,
+ 0, 1, 4, 9, 0, 1, 0, 22, 1,203, 0, 3, 0, 1, 4, 9, 0, 2, 0, 8, 1,239, 0, 3, 0, 1, 4, 9, 0, 3, 0, 22,
+ 1,254, 0, 3, 0, 1, 4, 9, 0, 4, 0, 22, 2, 34, 0, 3, 0, 1, 4, 9, 0, 5, 0, 22, 2, 70, 0, 3, 0, 1, 4, 9,
+ 0, 6, 0, 20, 2,106, 0, 3, 0, 1, 4, 9, 0, 8, 0, 34, 2,139, 0, 3, 0, 1, 4, 9, 0, 11, 0, 58, 2,193, 0, 3,
+ 0, 1, 4, 9, 0, 13, 37, 58, 3, 27, 0, 3, 0, 1, 4, 9, 0, 14, 0,104, 58,245, 0, 67, 0,111, 0,112, 0,121, 0,114,
+ 0,105, 0,103, 0,104, 0,116, 0, 32, 0, 40, 0, 99, 0, 41, 0, 32, 0, 50, 0, 48, 0, 48, 0, 51, 0, 32, 0, 98, 0,121,
+ 0, 32, 0, 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,109, 0, 44, 0, 32, 0, 73, 0,110, 0, 99, 0, 46,
+ 0, 32, 0, 65, 0,108, 0,108, 0, 32, 0, 82, 0,105, 0,103, 0,104, 0,116, 0,115, 0, 32, 0, 82, 0,101, 0,115, 0,101,
+ 0,114, 0,118, 0,101, 0,100, 0, 46, 0, 10, 0, 67, 0,111, 0,112, 0,121, 0,114, 0,105, 0,103, 0,104, 0,116, 0, 32,
+ 0, 40, 0, 99, 0, 41, 0, 32, 0, 50, 0, 48, 0, 48, 0, 54, 0, 32, 0, 98, 0,121, 0, 32, 0, 84, 0, 97, 0,118, 0,109,
+ 0,106, 0,111, 0,110, 0,103, 0, 32, 0, 66, 0, 97, 0,104, 0, 46, 0, 32, 0, 65, 0,108, 0,108, 0, 32, 0, 82, 0,105,
+ 0,103, 0,104, 0,116, 0,115, 0, 32, 0, 82, 0,101, 0,115, 0,101, 0,114, 0,118, 0,101, 0,100, 0, 46, 0, 10, 0, 68,
+ 0,101, 0,106, 0, 97, 0, 86, 0,117, 0, 32, 0, 99, 0,104, 0, 97, 0,110, 0,103, 0,101, 0,115, 0, 32, 0, 97, 0,114,
+ 0,101, 0, 32, 0,105, 0,110, 0, 32, 0,112, 0,117, 0, 98, 0,108, 0,105, 0, 99, 0, 32, 0,100, 0,111, 0,109, 0, 97,
+ 0,105, 0,110, 0, 10, 0, 0, 67,111,112,121,114,105,103,104,116, 32, 40, 99, 41, 32, 50, 48, 48, 51, 32, 98,121, 32, 66,105,
+116,115,116,114,101, 97,109, 44, 32, 73,110, 99, 46, 32, 65,108,108, 32, 82,105,103,104,116,115, 32, 82,101,115,101,114,118,101,
+100, 46, 10, 67,111,112,121,114,105,103,104,116, 32, 40, 99, 41, 32, 50, 48, 48, 54, 32, 98,121, 32, 84, 97,118,109,106,111,110,
+103, 32, 66, 97,104, 46, 32, 65,108,108, 32, 82,105,103,104,116,115, 32, 82,101,115,101,114,118,101,100, 46, 10, 68,101,106, 97,
+ 86,117, 32, 99,104, 97,110,103,101,115, 32, 97,114,101, 32,105,110, 32,112,117, 98,108,105, 99, 32,100,111,109, 97,105,110, 10,
+ 0, 0, 68, 0,101, 0,106, 0, 97, 0, 86, 0,117, 0, 32, 0, 83, 0, 97, 0,110, 0,115, 0, 0, 68,101,106, 97, 86,117, 32,
+ 83, 97,110,115, 0, 0, 66, 0,111, 0,111, 0,107, 0, 0, 66,111,111,107, 0, 0, 68, 0,101, 0,106, 0, 97, 0, 86, 0,117,
+ 0, 32, 0, 83, 0, 97, 0,110, 0,115, 0, 0, 68,101,106, 97, 86,117, 32, 83, 97,110,115, 0, 0, 68, 0,101, 0,106, 0, 97,
+ 0, 86, 0,117, 0, 32, 0, 83, 0, 97, 0,110, 0,115, 0, 0, 68,101,106, 97, 86,117, 32, 83, 97,110,115, 0, 0, 86, 0,101,
+ 0,114, 0,115, 0,105, 0,111, 0,110, 0, 32, 0, 50, 0, 46, 0, 56, 0, 0, 86,101,114,115,105,111,110, 32, 50, 46, 56, 0,
+ 0, 68, 0,101, 0,106, 0, 97, 0, 86, 0,117, 0, 83, 0, 97, 0,110, 0,115, 0, 0, 68,101,106, 97, 86,117, 83, 97,110,115,
+ 0, 0, 68, 0,101, 0,106, 0, 97, 0, 86, 0,117, 0, 32, 0,102, 0,111, 0,110, 0,116, 0,115, 0, 32, 0,116, 0,101, 0,
+ 97, 0,109, 0, 0, 68,101,106, 97, 86,117, 32,102,111,110,116,115, 32,116,101, 97,109, 0, 0,104, 0,116, 0,116, 0,112, 0,
+ 58, 0, 47, 0, 47, 0,100, 0,101, 0,106, 0, 97, 0,118, 0,117, 0, 46, 0,115, 0,111, 0,117, 0,114, 0, 99, 0,101, 0,
+102, 0,111, 0,114, 0,103, 0,101, 0, 46, 0,110, 0,101, 0,116, 0, 0,104,116,116,112, 58, 47, 47,100,101,106, 97,118,117,
+ 46,115,111,117,114, 99,101,102,111,114,103,101, 46,110,101,116, 0, 0, 70, 0,111, 0,110, 0,116, 0,115, 0, 32, 0, 97, 0,
+114, 0,101, 0, 32, 0, 40, 0, 99, 0, 41, 0, 32, 0, 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,109, 0,
+ 32, 0, 40, 0,115, 0,101, 0,101, 0, 32, 0, 98, 0,101, 0,108, 0,111, 0,119, 0, 41, 0, 46, 0, 32, 0, 68, 0,101, 0,
+106, 0, 97, 0, 86, 0,117, 0, 32, 0, 99, 0,104, 0, 97, 0,110, 0,103, 0,101, 0,115, 0, 32, 0, 97, 0,114, 0,101, 0,
+ 32, 0,105, 0,110, 0, 32, 0,112, 0,117, 0, 98, 0,108, 0,105, 0, 99, 0, 32, 0,100, 0,111, 0,109, 0, 97, 0,105, 0,
+110, 0, 46, 0, 32, 0, 71, 0,108, 0,121, 0,112, 0,104, 0,115, 0, 32, 0,105, 0,109, 0,112, 0,111, 0,114, 0,116, 0,
+101, 0,100, 0, 32, 0,102, 0,114, 0,111, 0,109, 0, 32, 0, 65, 0,114, 0,101, 0,118, 0, 32, 0,102, 0,111, 0,110, 0,
+116, 0,115, 0, 32, 0, 97, 0,114, 0,101, 0, 32, 0, 40, 0, 99, 0, 41, 0, 32, 0, 84, 0, 97, 0,118, 0,109, 0,106, 0,
+117, 0,110, 0,103, 0, 32, 0, 66, 0, 97, 0,104, 0, 32, 0, 40, 0,115, 0,101, 0,101, 0, 32, 0, 98, 0,101, 0,108, 0,
+111, 0,119, 0, 41, 0, 10, 0, 10, 0, 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,109, 0, 32, 0, 86, 0,
+101, 0,114, 0, 97, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0,115, 0, 32, 0, 67, 0,111, 0,112, 0,121, 0,114, 0,105, 0,
+103, 0,104, 0,116, 0, 10, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0,
+ 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0,
+ 45, 0, 45, 0, 10, 0, 10, 0, 67, 0,111, 0,112, 0,121, 0,114, 0,105, 0,103, 0,104, 0,116, 0, 32, 0, 40, 0, 99, 0,
+ 41, 0, 32, 0, 50, 0, 48, 0, 48, 0, 51, 0, 32, 0, 98, 0,121, 0, 32, 0, 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,
+101, 0, 97, 0,109, 0, 44, 0, 32, 0, 73, 0,110, 0, 99, 0, 46, 0, 32, 0, 65, 0,108, 0,108, 0, 32, 0, 82, 0,105, 0,
+103, 0,104, 0,116, 0,115, 0, 32, 0, 82, 0,101, 0,115, 0,101, 0,114, 0,118, 0,101, 0,100, 0, 46, 0, 32, 0, 66, 0,
+105, 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,109, 0, 32, 0, 86, 0,101, 0,114, 0, 97, 0, 32, 0,105, 0,115, 0,
+ 10, 0, 97, 0, 32, 0,116, 0,114, 0, 97, 0,100, 0,101, 0,109, 0, 97, 0,114, 0,107, 0, 32, 0,111, 0,102, 0, 32, 0,
+ 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,109, 0, 44, 0, 32, 0, 73, 0,110, 0, 99, 0, 46, 0, 10, 0,
+ 10, 0, 80, 0,101, 0,114, 0,109, 0,105, 0,115, 0,115, 0,105, 0,111, 0,110, 0, 32, 0,105, 0,115, 0, 32, 0,104, 0,
+101, 0,114, 0,101, 0, 98, 0,121, 0, 32, 0,103, 0,114, 0, 97, 0,110, 0,116, 0,101, 0,100, 0, 44, 0, 32, 0,102, 0,
+114, 0,101, 0,101, 0, 32, 0,111, 0,102, 0, 32, 0, 99, 0,104, 0, 97, 0,114, 0,103, 0,101, 0, 44, 0, 32, 0,116, 0,
+111, 0, 32, 0, 97, 0,110, 0,121, 0, 32, 0,112, 0,101, 0,114, 0,115, 0,111, 0,110, 0, 32, 0,111, 0, 98, 0,116, 0,
+ 97, 0,105, 0,110, 0,105, 0,110, 0,103, 0, 32, 0, 97, 0, 32, 0, 99, 0,111, 0,112, 0,121, 0, 10, 0,111, 0,102, 0,
+ 32, 0,116, 0,104, 0,101, 0, 32, 0,102, 0,111, 0,110, 0,116, 0,115, 0, 32, 0, 97, 0, 99, 0, 99, 0,111, 0,109, 0,
+112, 0, 97, 0,110, 0,121, 0,105, 0,110, 0,103, 0, 32, 0,116, 0,104, 0,105, 0,115, 0, 32, 0,108, 0,105, 0, 99, 0,
+101, 0,110, 0,115, 0,101, 0, 32, 0, 40, 0, 34, 0, 70, 0,111, 0,110, 0,116, 0,115, 0, 34, 0, 41, 0, 32, 0, 97, 0,
+110, 0,100, 0, 32, 0, 97, 0,115, 0,115, 0,111, 0, 99, 0,105, 0, 97, 0,116, 0,101, 0,100, 0, 10, 0,100, 0,111, 0,
+ 99, 0,117, 0,109, 0,101, 0,110, 0,116, 0, 97, 0,116, 0,105, 0,111, 0,110, 0, 32, 0,102, 0,105, 0,108, 0,101, 0,
+115, 0, 32, 0, 40, 0,116, 0,104, 0,101, 0, 32, 0, 34, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,
+116, 0,119, 0, 97, 0,114, 0,101, 0, 34, 0, 41, 0, 44, 0, 32, 0,116, 0,111, 0, 32, 0,114, 0,101, 0,112, 0,114, 0,
+111, 0,100, 0,117, 0, 99, 0,101, 0, 32, 0, 97, 0,110, 0,100, 0, 32, 0,100, 0,105, 0,115, 0,116, 0,114, 0,105, 0,
+ 98, 0,117, 0,116, 0,101, 0, 32, 0,116, 0,104, 0,101, 0, 10, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,
+102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 44, 0, 32, 0,105, 0,110, 0, 99, 0,108, 0,117, 0,100, 0,105, 0,110, 0,
+103, 0, 32, 0,119, 0,105, 0,116, 0,104, 0,111, 0,117, 0,116, 0, 32, 0,108, 0,105, 0,109, 0,105, 0,116, 0, 97, 0,
+116, 0,105, 0,111, 0,110, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,114, 0,105, 0,103, 0,104, 0,116, 0,115, 0, 32, 0,
+116, 0,111, 0, 32, 0,117, 0,115, 0,101, 0, 44, 0, 32, 0, 99, 0,111, 0,112, 0,121, 0, 44, 0, 32, 0,109, 0,101, 0,
+114, 0,103, 0,101, 0, 44, 0, 10, 0,112, 0,117, 0, 98, 0,108, 0,105, 0,115, 0,104, 0, 44, 0, 32, 0,100, 0,105, 0,
+115, 0,116, 0,114, 0,105, 0, 98, 0,117, 0,116, 0,101, 0, 44, 0, 32, 0, 97, 0,110, 0,100, 0, 47, 0,111, 0,114, 0,
+ 32, 0,115, 0,101, 0,108, 0,108, 0, 32, 0, 99, 0,111, 0,112, 0,105, 0,101, 0,115, 0, 32, 0,111, 0,102, 0, 32, 0,
+116, 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,
+101, 0, 44, 0, 32, 0, 97, 0,110, 0,100, 0, 32, 0,116, 0,111, 0, 32, 0,112, 0,101, 0,114, 0,109, 0,105, 0,116, 0,
+ 10, 0,112, 0,101, 0,114, 0,115, 0,111, 0,110, 0,115, 0, 32, 0,116, 0,111, 0, 32, 0,119, 0,104, 0,111, 0,109, 0,
+ 32, 0,116, 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,
+114, 0,101, 0, 32, 0,105, 0,115, 0, 32, 0,102, 0,117, 0,114, 0,110, 0,105, 0,115, 0,104, 0,101, 0,100, 0, 32, 0,
+116, 0,111, 0, 32, 0,100, 0,111, 0, 32, 0,115, 0,111, 0, 44, 0, 32, 0,115, 0,117, 0, 98, 0,106, 0,101, 0, 99, 0,
+116, 0, 32, 0,116, 0,111, 0, 32, 0,116, 0,104, 0,101, 0, 10, 0,102, 0,111, 0,108, 0,108, 0,111, 0,119, 0,105, 0,
+110, 0,103, 0, 32, 0, 99, 0,111, 0,110, 0,100, 0,105, 0,116, 0,105, 0,111, 0,110, 0,115, 0, 58, 0, 10, 0, 10, 0,
+ 84, 0,104, 0,101, 0, 32, 0, 97, 0, 98, 0,111, 0,118, 0,101, 0, 32, 0, 99, 0,111, 0,112, 0,121, 0,114, 0,105, 0,
+103, 0,104, 0,116, 0, 32, 0, 97, 0,110, 0,100, 0, 32, 0,116, 0,114, 0, 97, 0,100, 0,101, 0,109, 0, 97, 0,114, 0,
+107, 0, 32, 0,110, 0,111, 0,116, 0,105, 0, 99, 0,101, 0,115, 0, 32, 0, 97, 0,110, 0,100, 0, 32, 0,116, 0,104, 0,
+105, 0,115, 0, 32, 0,112, 0,101, 0,114, 0,109, 0,105, 0,115, 0,115, 0,105, 0,111, 0,110, 0, 32, 0,110, 0,111, 0,
+116, 0,105, 0, 99, 0,101, 0, 32, 0,115, 0,104, 0, 97, 0,108, 0,108, 0, 10, 0, 98, 0,101, 0, 32, 0,105, 0,110, 0,
+ 99, 0,108, 0,117, 0,100, 0,101, 0,100, 0, 32, 0,105, 0,110, 0, 32, 0, 97, 0,108, 0,108, 0, 32, 0, 99, 0,111, 0,
+112, 0,105, 0,101, 0,115, 0, 32, 0,111, 0,102, 0, 32, 0,111, 0,110, 0,101, 0, 32, 0,111, 0,114, 0, 32, 0,109, 0,
+111, 0,114, 0,101, 0, 32, 0,111, 0,102, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0,
+ 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 32, 0,116, 0,121, 0,112, 0,101, 0,102, 0, 97, 0, 99, 0,
+101, 0,115, 0, 46, 0, 10, 0, 10, 0, 84, 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,
+102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 32, 0,109, 0, 97, 0,121, 0, 32, 0, 98, 0,101, 0, 32, 0,109, 0,111, 0,
+100, 0,105, 0,102, 0,105, 0,101, 0,100, 0, 44, 0, 32, 0, 97, 0,108, 0,116, 0,101, 0,114, 0,101, 0,100, 0, 44, 0,
+ 32, 0,111, 0,114, 0, 32, 0, 97, 0,100, 0,100, 0,101, 0,100, 0, 32, 0,116, 0,111, 0, 44, 0, 32, 0, 97, 0,110, 0,
+100, 0, 32, 0,105, 0,110, 0, 32, 0,112, 0, 97, 0,114, 0,116, 0,105, 0, 99, 0,117, 0,108, 0, 97, 0,114, 0, 10, 0,
+116, 0,104, 0,101, 0, 32, 0,100, 0,101, 0,115, 0,105, 0,103, 0,110, 0,115, 0, 32, 0,111, 0,102, 0, 32, 0,103, 0,
+108, 0,121, 0,112, 0,104, 0,115, 0, 32, 0,111, 0,114, 0, 32, 0, 99, 0,104, 0, 97, 0,114, 0, 97, 0, 99, 0,116, 0,
+101, 0,114, 0,115, 0, 32, 0,105, 0,110, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0,115, 0,
+ 32, 0,109, 0, 97, 0,121, 0, 32, 0, 98, 0,101, 0, 32, 0,109, 0,111, 0,100, 0,105, 0,102, 0,105, 0,101, 0,100, 0,
+ 32, 0, 97, 0,110, 0,100, 0, 10, 0, 97, 0,100, 0,100, 0,105, 0,116, 0,105, 0,111, 0,110, 0, 97, 0,108, 0, 32, 0,
+103, 0,108, 0,121, 0,112, 0,104, 0,115, 0, 32, 0,111, 0,114, 0, 32, 0, 99, 0,104, 0, 97, 0,114, 0, 97, 0, 99, 0,
+116, 0,101, 0,114, 0,115, 0, 32, 0,109, 0, 97, 0,121, 0, 32, 0, 98, 0,101, 0, 32, 0, 97, 0,100, 0,100, 0,101, 0,
+100, 0, 32, 0,116, 0,111, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0,115, 0, 44, 0, 32, 0,
+111, 0,110, 0,108, 0,121, 0, 32, 0,105, 0,102, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,102, 0,111, 0,110, 0,116, 0,
+115, 0, 10, 0, 97, 0,114, 0,101, 0, 32, 0,114, 0,101, 0,110, 0, 97, 0,109, 0,101, 0,100, 0, 32, 0,116, 0,111, 0,
+ 32, 0,110, 0, 97, 0,109, 0,101, 0,115, 0, 32, 0,110, 0,111, 0,116, 0, 32, 0, 99, 0,111, 0,110, 0,116, 0, 97, 0,
+105, 0,110, 0,105, 0,110, 0,103, 0, 32, 0,101, 0,105, 0,116, 0,104, 0,101, 0,114, 0, 32, 0,116, 0,104, 0,101, 0,
+ 32, 0,119, 0,111, 0,114, 0,100, 0,115, 0, 32, 0, 34, 0, 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,
+109, 0, 34, 0, 32, 0,111, 0,114, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,119, 0,111, 0,114, 0,100, 0, 10, 0, 34, 0,
+ 86, 0,101, 0,114, 0, 97, 0, 34, 0, 46, 0, 10, 0, 10, 0, 84, 0,104, 0,105, 0,115, 0, 32, 0, 76, 0,105, 0, 99, 0,
+101, 0,110, 0,115, 0,101, 0, 32, 0, 98, 0,101, 0, 99, 0,111, 0,109, 0,101, 0,115, 0, 32, 0,110, 0,117, 0,108, 0,
+108, 0, 32, 0, 97, 0,110, 0,100, 0, 32, 0,118, 0,111, 0,105, 0,100, 0, 32, 0,116, 0,111, 0, 32, 0,116, 0,104, 0,
+101, 0, 32, 0,101, 0,120, 0,116, 0,101, 0,110, 0,116, 0, 32, 0, 97, 0,112, 0,112, 0,108, 0,105, 0, 99, 0, 97, 0,
+ 98, 0,108, 0,101, 0, 32, 0,116, 0,111, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0,115, 0, 32, 0,111, 0,114, 0, 32, 0,
+ 70, 0,111, 0,110, 0,116, 0, 10, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 32, 0,116, 0,104, 0,
+ 97, 0,116, 0, 32, 0,104, 0, 97, 0,115, 0, 32, 0, 98, 0,101, 0,101, 0,110, 0, 32, 0,109, 0,111, 0,100, 0,105, 0,
+102, 0,105, 0,101, 0,100, 0, 32, 0, 97, 0,110, 0,100, 0, 32, 0,105, 0,115, 0, 32, 0,100, 0,105, 0,115, 0,116, 0,
+114, 0,105, 0, 98, 0,117, 0,116, 0,101, 0,100, 0, 32, 0,117, 0,110, 0,100, 0,101, 0,114, 0, 32, 0,116, 0,104, 0,
+101, 0, 32, 0, 34, 0, 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,109, 0, 10, 0, 86, 0,101, 0,114, 0,
+ 97, 0, 34, 0, 32, 0,110, 0, 97, 0,109, 0,101, 0,115, 0, 46, 0, 10, 0, 10, 0, 84, 0,104, 0,101, 0, 32, 0, 70, 0,
+111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 32, 0,109, 0, 97, 0,121, 0,
+ 32, 0, 98, 0,101, 0, 32, 0,115, 0,111, 0,108, 0,100, 0, 32, 0, 97, 0,115, 0, 32, 0,112, 0, 97, 0,114, 0,116, 0,
+ 32, 0,111, 0,102, 0, 32, 0, 97, 0, 32, 0,108, 0, 97, 0,114, 0,103, 0,101, 0,114, 0, 32, 0,115, 0,111, 0,102, 0,
+116, 0,119, 0, 97, 0,114, 0,101, 0, 32, 0,112, 0, 97, 0, 99, 0,107, 0, 97, 0,103, 0,101, 0, 32, 0, 98, 0,117, 0,
+116, 0, 32, 0,110, 0,111, 0, 10, 0, 99, 0,111, 0,112, 0,121, 0, 32, 0,111, 0,102, 0, 32, 0,111, 0,110, 0,101, 0,
+ 32, 0,111, 0,114, 0, 32, 0,109, 0,111, 0,114, 0,101, 0, 32, 0,111, 0,102, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,
+ 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 32, 0,116, 0,121, 0,
+112, 0,101, 0,102, 0, 97, 0, 99, 0,101, 0,115, 0, 32, 0,109, 0, 97, 0,121, 0, 32, 0, 98, 0,101, 0, 32, 0,115, 0,
+111, 0,108, 0,100, 0, 32, 0, 98, 0,121, 0, 32, 0,105, 0,116, 0,115, 0,101, 0,108, 0,102, 0, 46, 0, 10, 0, 10, 0,
+ 84, 0, 72, 0, 69, 0, 32, 0, 70, 0, 79, 0, 78, 0, 84, 0, 32, 0, 83, 0, 79, 0, 70, 0, 84, 0, 87, 0, 65, 0, 82, 0,
+ 69, 0, 32, 0, 73, 0, 83, 0, 32, 0, 80, 0, 82, 0, 79, 0, 86, 0, 73, 0, 68, 0, 69, 0, 68, 0, 32, 0, 34, 0, 65, 0,
+ 83, 0, 32, 0, 73, 0, 83, 0, 34, 0, 44, 0, 32, 0, 87, 0, 73, 0, 84, 0, 72, 0, 79, 0, 85, 0, 84, 0, 32, 0, 87, 0,
+ 65, 0, 82, 0, 82, 0, 65, 0, 78, 0, 84, 0, 89, 0, 32, 0, 79, 0, 70, 0, 32, 0, 65, 0, 78, 0, 89, 0, 32, 0, 75, 0,
+ 73, 0, 78, 0, 68, 0, 44, 0, 32, 0, 69, 0, 88, 0, 80, 0, 82, 0, 69, 0, 83, 0, 83, 0, 10, 0, 79, 0, 82, 0, 32, 0,
+ 73, 0, 77, 0, 80, 0, 76, 0, 73, 0, 69, 0, 68, 0, 44, 0, 32, 0, 73, 0, 78, 0, 67, 0, 76, 0, 85, 0, 68, 0, 73, 0,
+ 78, 0, 71, 0, 32, 0, 66, 0, 85, 0, 84, 0, 32, 0, 78, 0, 79, 0, 84, 0, 32, 0, 76, 0, 73, 0, 77, 0, 73, 0, 84, 0,
+ 69, 0, 68, 0, 32, 0, 84, 0, 79, 0, 32, 0, 65, 0, 78, 0, 89, 0, 32, 0, 87, 0, 65, 0, 82, 0, 82, 0, 65, 0, 78, 0,
+ 84, 0, 73, 0, 69, 0, 83, 0, 32, 0, 79, 0, 70, 0, 32, 0, 77, 0, 69, 0, 82, 0, 67, 0, 72, 0, 65, 0, 78, 0, 84, 0,
+ 65, 0, 66, 0, 73, 0, 76, 0, 73, 0, 84, 0, 89, 0, 44, 0, 10, 0, 70, 0, 73, 0, 84, 0, 78, 0, 69, 0, 83, 0, 83, 0,
+ 32, 0, 70, 0, 79, 0, 82, 0, 32, 0, 65, 0, 32, 0, 80, 0, 65, 0, 82, 0, 84, 0, 73, 0, 67, 0, 85, 0, 76, 0, 65, 0,
+ 82, 0, 32, 0, 80, 0, 85, 0, 82, 0, 80, 0, 79, 0, 83, 0, 69, 0, 32, 0, 65, 0, 78, 0, 68, 0, 32, 0, 78, 0, 79, 0,
+ 78, 0, 73, 0, 78, 0, 70, 0, 82, 0, 73, 0, 78, 0, 71, 0, 69, 0, 77, 0, 69, 0, 78, 0, 84, 0, 32, 0, 79, 0, 70, 0,
+ 32, 0, 67, 0, 79, 0, 80, 0, 89, 0, 82, 0, 73, 0, 71, 0, 72, 0, 84, 0, 44, 0, 32, 0, 80, 0, 65, 0, 84, 0, 69, 0,
+ 78, 0, 84, 0, 44, 0, 10, 0, 84, 0, 82, 0, 65, 0, 68, 0, 69, 0, 77, 0, 65, 0, 82, 0, 75, 0, 44, 0, 32, 0, 79, 0,
+ 82, 0, 32, 0, 79, 0, 84, 0, 72, 0, 69, 0, 82, 0, 32, 0, 82, 0, 73, 0, 71, 0, 72, 0, 84, 0, 46, 0, 32, 0, 73, 0,
+ 78, 0, 32, 0, 78, 0, 79, 0, 32, 0, 69, 0, 86, 0, 69, 0, 78, 0, 84, 0, 32, 0, 83, 0, 72, 0, 65, 0, 76, 0, 76, 0,
+ 32, 0, 66, 0, 73, 0, 84, 0, 83, 0, 84, 0, 82, 0, 69, 0, 65, 0, 77, 0, 32, 0, 79, 0, 82, 0, 32, 0, 84, 0, 72, 0,
+ 69, 0, 32, 0, 71, 0, 78, 0, 79, 0, 77, 0, 69, 0, 10, 0, 70, 0, 79, 0, 85, 0, 78, 0, 68, 0, 65, 0, 84, 0, 73, 0,
+ 79, 0, 78, 0, 32, 0, 66, 0, 69, 0, 32, 0, 76, 0, 73, 0, 65, 0, 66, 0, 76, 0, 69, 0, 32, 0, 70, 0, 79, 0, 82, 0,
+ 32, 0, 65, 0, 78, 0, 89, 0, 32, 0, 67, 0, 76, 0, 65, 0, 73, 0, 77, 0, 44, 0, 32, 0, 68, 0, 65, 0, 77, 0, 65, 0,
+ 71, 0, 69, 0, 83, 0, 32, 0, 79, 0, 82, 0, 32, 0, 79, 0, 84, 0, 72, 0, 69, 0, 82, 0, 32, 0, 76, 0, 73, 0, 65, 0,
+ 66, 0, 73, 0, 76, 0, 73, 0, 84, 0, 89, 0, 44, 0, 32, 0, 73, 0, 78, 0, 67, 0, 76, 0, 85, 0, 68, 0, 73, 0, 78, 0,
+ 71, 0, 10, 0, 65, 0, 78, 0, 89, 0, 32, 0, 71, 0, 69, 0, 78, 0, 69, 0, 82, 0, 65, 0, 76, 0, 44, 0, 32, 0, 83, 0,
+ 80, 0, 69, 0, 67, 0, 73, 0, 65, 0, 76, 0, 44, 0, 32, 0, 73, 0, 78, 0, 68, 0, 73, 0, 82, 0, 69, 0, 67, 0, 84, 0,
+ 44, 0, 32, 0, 73, 0, 78, 0, 67, 0, 73, 0, 68, 0, 69, 0, 78, 0, 84, 0, 65, 0, 76, 0, 44, 0, 32, 0, 79, 0, 82, 0,
+ 32, 0, 67, 0, 79, 0, 78, 0, 83, 0, 69, 0, 81, 0, 85, 0, 69, 0, 78, 0, 84, 0, 73, 0, 65, 0, 76, 0, 32, 0, 68, 0,
+ 65, 0, 77, 0, 65, 0, 71, 0, 69, 0, 83, 0, 44, 0, 10, 0, 87, 0, 72, 0, 69, 0, 84, 0, 72, 0, 69, 0, 82, 0, 32, 0,
+ 73, 0, 78, 0, 32, 0, 65, 0, 78, 0, 32, 0, 65, 0, 67, 0, 84, 0, 73, 0, 79, 0, 78, 0, 32, 0, 79, 0, 70, 0, 32, 0,
+ 67, 0, 79, 0, 78, 0, 84, 0, 82, 0, 65, 0, 67, 0, 84, 0, 44, 0, 32, 0, 84, 0, 79, 0, 82, 0, 84, 0, 32, 0, 79, 0,
+ 82, 0, 32, 0, 79, 0, 84, 0, 72, 0, 69, 0, 82, 0, 87, 0, 73, 0, 83, 0, 69, 0, 44, 0, 32, 0, 65, 0, 82, 0, 73, 0,
+ 83, 0, 73, 0, 78, 0, 71, 0, 32, 0, 70, 0, 82, 0, 79, 0, 77, 0, 44, 0, 32, 0, 79, 0, 85, 0, 84, 0, 32, 0, 79, 0,
+ 70, 0, 10, 0, 84, 0, 72, 0, 69, 0, 32, 0, 85, 0, 83, 0, 69, 0, 32, 0, 79, 0, 82, 0, 32, 0, 73, 0, 78, 0, 65, 0,
+ 66, 0, 73, 0, 76, 0, 73, 0, 84, 0, 89, 0, 32, 0, 84, 0, 79, 0, 32, 0, 85, 0, 83, 0, 69, 0, 32, 0, 84, 0, 72, 0,
+ 69, 0, 32, 0, 70, 0, 79, 0, 78, 0, 84, 0, 32, 0, 83, 0, 79, 0, 70, 0, 84, 0, 87, 0, 65, 0, 82, 0, 69, 0, 32, 0,
+ 79, 0, 82, 0, 32, 0, 70, 0, 82, 0, 79, 0, 77, 0, 32, 0, 79, 0, 84, 0, 72, 0, 69, 0, 82, 0, 32, 0, 68, 0, 69, 0,
+ 65, 0, 76, 0, 73, 0, 78, 0, 71, 0, 83, 0, 32, 0, 73, 0, 78, 0, 32, 0, 84, 0, 72, 0, 69, 0, 10, 0, 70, 0, 79, 0,
+ 78, 0, 84, 0, 32, 0, 83, 0, 79, 0, 70, 0, 84, 0, 87, 0, 65, 0, 82, 0, 69, 0, 46, 0, 10, 0, 10, 0, 69, 0,120, 0,
+ 99, 0,101, 0,112, 0,116, 0, 32, 0, 97, 0,115, 0, 32, 0, 99, 0,111, 0,110, 0,116, 0, 97, 0,105, 0,110, 0,101, 0,
+100, 0, 32, 0,105, 0,110, 0, 32, 0,116, 0,104, 0,105, 0,115, 0, 32, 0,110, 0,111, 0,116, 0,105, 0, 99, 0,101, 0,
+ 44, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,110, 0, 97, 0,109, 0,101, 0,115, 0, 32, 0,111, 0,102, 0, 32, 0, 71, 0,
+110, 0,111, 0,109, 0,101, 0, 44, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0, 71, 0,110, 0,111, 0,109, 0,101, 0, 10, 0,
+ 70, 0,111, 0,117, 0,110, 0,100, 0, 97, 0,116, 0,105, 0,111, 0,110, 0, 44, 0, 32, 0, 97, 0,110, 0,100, 0, 32, 0,
+ 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,109, 0, 32, 0, 73, 0,110, 0, 99, 0, 46, 0, 44, 0, 32, 0,
+115, 0,104, 0, 97, 0,108, 0,108, 0, 32, 0,110, 0,111, 0,116, 0, 32, 0, 98, 0,101, 0, 32, 0,117, 0,115, 0,101, 0,
+100, 0, 32, 0,105, 0,110, 0, 32, 0, 97, 0,100, 0,118, 0,101, 0,114, 0,116, 0,105, 0,115, 0,105, 0,110, 0,103, 0,
+ 32, 0,111, 0,114, 0, 10, 0,111, 0,116, 0,104, 0,101, 0,114, 0,119, 0,105, 0,115, 0,101, 0, 32, 0,116, 0,111, 0,
+ 32, 0,112, 0,114, 0,111, 0,109, 0,111, 0,116, 0,101, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,115, 0, 97, 0,108, 0,
+101, 0, 44, 0, 32, 0,117, 0,115, 0,101, 0, 32, 0,111, 0,114, 0, 32, 0,111, 0,116, 0,104, 0,101, 0,114, 0, 32, 0,
+100, 0,101, 0, 97, 0,108, 0,105, 0,110, 0,103, 0,115, 0, 32, 0,105, 0,110, 0, 32, 0,116, 0,104, 0,105, 0,115, 0,
+ 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 10, 0,119, 0,
+105, 0,116, 0,104, 0,111, 0,117, 0,116, 0, 32, 0,112, 0,114, 0,105, 0,111, 0,114, 0, 32, 0,119, 0,114, 0,105, 0,
+116, 0,116, 0,101, 0,110, 0, 32, 0, 97, 0,117, 0,116, 0,104, 0,111, 0,114, 0,105, 0,122, 0, 97, 0,116, 0,105, 0,
+111, 0,110, 0, 32, 0,102, 0,114, 0,111, 0,109, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0, 71, 0,110, 0,111, 0,109, 0,
+101, 0, 32, 0, 70, 0,111, 0,117, 0,110, 0,100, 0, 97, 0,116, 0,105, 0,111, 0,110, 0, 32, 0,111, 0,114, 0, 32, 0,
+ 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,109, 0, 10, 0, 73, 0,110, 0, 99, 0, 46, 0, 44, 0, 32, 0,
+114, 0,101, 0,115, 0,112, 0,101, 0, 99, 0,116, 0,105, 0,118, 0,101, 0,108, 0,121, 0, 46, 0, 32, 0, 70, 0,111, 0,
+114, 0, 32, 0,102, 0,117, 0,114, 0,116, 0,104, 0,101, 0,114, 0, 32, 0,105, 0,110, 0,102, 0,111, 0,114, 0,109, 0,
+ 97, 0,116, 0,105, 0,111, 0,110, 0, 44, 0, 32, 0, 99, 0,111, 0,110, 0,116, 0, 97, 0, 99, 0,116, 0, 58, 0, 32, 0,
+102, 0,111, 0,110, 0,116, 0,115, 0, 32, 0, 97, 0,116, 0, 32, 0,103, 0,110, 0,111, 0,109, 0,101, 0, 32, 0,100, 0,
+111, 0,116, 0, 10, 0,111, 0,114, 0,103, 0, 46, 0, 32, 0, 10, 0, 10, 0, 65, 0,114, 0,101, 0,118, 0, 32, 0, 70, 0,
+111, 0,110, 0,116, 0,115, 0, 32, 0, 67, 0,111, 0,112, 0,121, 0,114, 0,105, 0,103, 0,104, 0,116, 0, 10, 0, 45, 0,
+ 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0,
+ 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 10, 0, 10, 0, 67, 0,
+111, 0,112, 0,121, 0,114, 0,105, 0,103, 0,104, 0,116, 0, 32, 0, 40, 0, 99, 0, 41, 0, 32, 0, 50, 0, 48, 0, 48, 0,
+ 54, 0, 32, 0, 98, 0,121, 0, 32, 0, 84, 0, 97, 0,118, 0,109, 0,106, 0,111, 0,110, 0,103, 0, 32, 0, 66, 0, 97, 0,
+104, 0, 46, 0, 32, 0, 65, 0,108, 0,108, 0, 32, 0, 82, 0,105, 0,103, 0,104, 0,116, 0,115, 0, 32, 0, 82, 0,101, 0,
+115, 0,101, 0,114, 0,118, 0,101, 0,100, 0, 46, 0, 10, 0, 10, 0, 80, 0,101, 0,114, 0,109, 0,105, 0,115, 0,115, 0,
+105, 0,111, 0,110, 0, 32, 0,105, 0,115, 0, 32, 0,104, 0,101, 0,114, 0,101, 0, 98, 0,121, 0, 32, 0,103, 0,114, 0,
+ 97, 0,110, 0,116, 0,101, 0,100, 0, 44, 0, 32, 0,102, 0,114, 0,101, 0,101, 0, 32, 0,111, 0,102, 0, 32, 0, 99, 0,
+104, 0, 97, 0,114, 0,103, 0,101, 0, 44, 0, 32, 0,116, 0,111, 0, 32, 0, 97, 0,110, 0,121, 0, 32, 0,112, 0,101, 0,
+114, 0,115, 0,111, 0,110, 0, 32, 0,111, 0, 98, 0,116, 0, 97, 0,105, 0,110, 0,105, 0,110, 0,103, 0, 10, 0, 97, 0,
+ 32, 0, 99, 0,111, 0,112, 0,121, 0, 32, 0,111, 0,102, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,102, 0,111, 0,110, 0,
+116, 0,115, 0, 32, 0, 97, 0, 99, 0, 99, 0,111, 0,109, 0,112, 0, 97, 0,110, 0,121, 0,105, 0,110, 0,103, 0, 32, 0,
+116, 0,104, 0,105, 0,115, 0, 32, 0,108, 0,105, 0, 99, 0,101, 0,110, 0,115, 0,101, 0, 32, 0, 40, 0, 34, 0, 70, 0,
+111, 0,110, 0,116, 0,115, 0, 34, 0, 41, 0, 32, 0, 97, 0,110, 0,100, 0, 10, 0, 97, 0,115, 0,115, 0,111, 0, 99, 0,
+105, 0, 97, 0,116, 0,101, 0,100, 0, 32, 0,100, 0,111, 0, 99, 0,117, 0,109, 0,101, 0,110, 0,116, 0, 97, 0,116, 0,
+105, 0,111, 0,110, 0, 32, 0,102, 0,105, 0,108, 0,101, 0,115, 0, 32, 0, 40, 0,116, 0,104, 0,101, 0, 32, 0, 34, 0,
+ 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 34, 0, 41, 0, 44, 0,
+ 32, 0,116, 0,111, 0, 32, 0,114, 0,101, 0,112, 0,114, 0,111, 0,100, 0,117, 0, 99, 0,101, 0, 10, 0, 97, 0,110, 0,
+100, 0, 32, 0,100, 0,105, 0,115, 0,116, 0,114, 0,105, 0, 98, 0,117, 0,116, 0,101, 0, 32, 0,116, 0,104, 0,101, 0,
+ 32, 0,109, 0,111, 0,100, 0,105, 0,102, 0,105, 0, 99, 0, 97, 0,116, 0,105, 0,111, 0,110, 0,115, 0, 32, 0,116, 0,
+111, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0, 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,109, 0, 32, 0,
+ 86, 0,101, 0,114, 0, 97, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,
+114, 0,101, 0, 44, 0, 10, 0,105, 0,110, 0, 99, 0,108, 0,117, 0,100, 0,105, 0,110, 0,103, 0, 32, 0,119, 0,105, 0,
+116, 0,104, 0,111, 0,117, 0,116, 0, 32, 0,108, 0,105, 0,109, 0,105, 0,116, 0, 97, 0,116, 0,105, 0,111, 0,110, 0,
+ 32, 0,116, 0,104, 0,101, 0, 32, 0,114, 0,105, 0,103, 0,104, 0,116, 0,115, 0, 32, 0,116, 0,111, 0, 32, 0,117, 0,
+115, 0,101, 0, 44, 0, 32, 0, 99, 0,111, 0,112, 0,121, 0, 44, 0, 32, 0,109, 0,101, 0,114, 0,103, 0,101, 0, 44, 0,
+ 32, 0,112, 0,117, 0, 98, 0,108, 0,105, 0,115, 0,104, 0, 44, 0, 10, 0,100, 0,105, 0,115, 0,116, 0,114, 0,105, 0,
+ 98, 0,117, 0,116, 0,101, 0, 44, 0, 32, 0, 97, 0,110, 0,100, 0, 47, 0,111, 0,114, 0, 32, 0,115, 0,101, 0,108, 0,
+108, 0, 32, 0, 99, 0,111, 0,112, 0,105, 0,101, 0,115, 0, 32, 0,111, 0,102, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,
+ 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 44, 0, 32, 0, 97, 0,
+110, 0,100, 0, 32, 0,116, 0,111, 0, 32, 0,112, 0,101, 0,114, 0,109, 0,105, 0,116, 0, 10, 0,112, 0,101, 0,114, 0,
+115, 0,111, 0,110, 0,115, 0, 32, 0,116, 0,111, 0, 32, 0,119, 0,104, 0,111, 0,109, 0, 32, 0,116, 0,104, 0,101, 0,
+ 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 32, 0,105, 0,
+115, 0, 32, 0,102, 0,117, 0,114, 0,110, 0,105, 0,115, 0,104, 0,101, 0,100, 0, 32, 0,116, 0,111, 0, 32, 0,100, 0,
+111, 0, 32, 0,115, 0,111, 0, 44, 0, 32, 0,115, 0,117, 0, 98, 0,106, 0,101, 0, 99, 0,116, 0, 32, 0,116, 0,111, 0,
+ 10, 0,116, 0,104, 0,101, 0, 32, 0,102, 0,111, 0,108, 0,108, 0,111, 0,119, 0,105, 0,110, 0,103, 0, 32, 0, 99, 0,
+111, 0,110, 0,100, 0,105, 0,116, 0,105, 0,111, 0,110, 0,115, 0, 58, 0, 10, 0, 10, 0, 84, 0,104, 0,101, 0, 32, 0,
+ 97, 0, 98, 0,111, 0,118, 0,101, 0, 32, 0, 99, 0,111, 0,112, 0,121, 0,114, 0,105, 0,103, 0,104, 0,116, 0, 32, 0,
+ 97, 0,110, 0,100, 0, 32, 0,116, 0,114, 0, 97, 0,100, 0,101, 0,109, 0, 97, 0,114, 0,107, 0, 32, 0,110, 0,111, 0,
+116, 0,105, 0, 99, 0,101, 0,115, 0, 32, 0, 97, 0,110, 0,100, 0, 32, 0,116, 0,104, 0,105, 0,115, 0, 32, 0,112, 0,
+101, 0,114, 0,109, 0,105, 0,115, 0,115, 0,105, 0,111, 0,110, 0, 32, 0,110, 0,111, 0,116, 0,105, 0, 99, 0,101, 0,
+ 10, 0,115, 0,104, 0, 97, 0,108, 0,108, 0, 32, 0, 98, 0,101, 0, 32, 0,105, 0,110, 0, 99, 0,108, 0,117, 0,100, 0,
+101, 0,100, 0, 32, 0,105, 0,110, 0, 32, 0, 97, 0,108, 0,108, 0, 32, 0, 99, 0,111, 0,112, 0,105, 0,101, 0,115, 0,
+ 32, 0,111, 0,102, 0, 32, 0,111, 0,110, 0,101, 0, 32, 0,111, 0,114, 0, 32, 0,109, 0,111, 0,114, 0,101, 0, 32, 0,
+111, 0,102, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,
+119, 0, 97, 0,114, 0,101, 0, 10, 0,116, 0,121, 0,112, 0,101, 0,102, 0, 97, 0, 99, 0,101, 0,115, 0, 46, 0, 10, 0,
+ 10, 0, 84, 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,
+114, 0,101, 0, 32, 0,109, 0, 97, 0,121, 0, 32, 0, 98, 0,101, 0, 32, 0,109, 0,111, 0,100, 0,105, 0,102, 0,105, 0,
+101, 0,100, 0, 44, 0, 32, 0, 97, 0,108, 0,116, 0,101, 0,114, 0,101, 0,100, 0, 44, 0, 32, 0,111, 0,114, 0, 32, 0,
+ 97, 0,100, 0,100, 0,101, 0,100, 0, 32, 0,116, 0,111, 0, 44, 0, 32, 0, 97, 0,110, 0,100, 0, 32, 0,105, 0,110, 0,
+ 10, 0,112, 0, 97, 0,114, 0,116, 0,105, 0, 99, 0,117, 0,108, 0, 97, 0,114, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,
+100, 0,101, 0,115, 0,105, 0,103, 0,110, 0,115, 0, 32, 0,111, 0,102, 0, 32, 0,103, 0,108, 0,121, 0,112, 0,104, 0,
+115, 0, 32, 0,111, 0,114, 0, 32, 0, 99, 0,104, 0, 97, 0,114, 0, 97, 0, 99, 0,116, 0,101, 0,114, 0,115, 0, 32, 0,
+105, 0,110, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0,115, 0, 32, 0,109, 0, 97, 0,121, 0,
+ 32, 0, 98, 0,101, 0, 10, 0,109, 0,111, 0,100, 0,105, 0,102, 0,105, 0,101, 0,100, 0, 32, 0, 97, 0,110, 0,100, 0,
+ 32, 0, 97, 0,100, 0,100, 0,105, 0,116, 0,105, 0,111, 0,110, 0, 97, 0,108, 0, 32, 0,103, 0,108, 0,121, 0,112, 0,
+104, 0,115, 0, 32, 0,111, 0,114, 0, 32, 0, 99, 0,104, 0, 97, 0,114, 0, 97, 0, 99, 0,116, 0,101, 0,114, 0,115, 0,
+ 32, 0,109, 0, 97, 0,121, 0, 32, 0, 98, 0,101, 0, 32, 0, 97, 0,100, 0,100, 0,101, 0,100, 0, 32, 0,116, 0,111, 0,
+ 32, 0,116, 0,104, 0,101, 0, 10, 0, 70, 0,111, 0,110, 0,116, 0,115, 0, 44, 0, 32, 0,111, 0,110, 0,108, 0,121, 0,
+ 32, 0,105, 0,102, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,102, 0,111, 0,110, 0,116, 0,115, 0, 32, 0, 97, 0,114, 0,
+101, 0, 32, 0,114, 0,101, 0,110, 0, 97, 0,109, 0,101, 0,100, 0, 32, 0,116, 0,111, 0, 32, 0,110, 0, 97, 0,109, 0,
+101, 0,115, 0, 32, 0,110, 0,111, 0,116, 0, 32, 0, 99, 0,111, 0,110, 0,116, 0, 97, 0,105, 0,110, 0,105, 0,110, 0,
+103, 0, 32, 0,101, 0,105, 0,116, 0,104, 0,101, 0,114, 0, 10, 0,116, 0,104, 0,101, 0, 32, 0,119, 0,111, 0,114, 0,
+100, 0,115, 0, 32, 0, 34, 0, 84, 0, 97, 0,118, 0,109, 0,106, 0,111, 0,110, 0,103, 0, 32, 0, 66, 0, 97, 0,104, 0,
+ 34, 0, 32, 0,111, 0,114, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,119, 0,111, 0,114, 0,100, 0, 32, 0, 34, 0, 65, 0,
+114, 0,101, 0,118, 0, 34, 0, 46, 0, 10, 0, 10, 0, 84, 0,104, 0,105, 0,115, 0, 32, 0, 76, 0,105, 0, 99, 0,101, 0,
+110, 0,115, 0,101, 0, 32, 0, 98, 0,101, 0, 99, 0,111, 0,109, 0,101, 0,115, 0, 32, 0,110, 0,117, 0,108, 0,108, 0,
+ 32, 0, 97, 0,110, 0,100, 0, 32, 0,118, 0,111, 0,105, 0,100, 0, 32, 0,116, 0,111, 0, 32, 0,116, 0,104, 0,101, 0,
+ 32, 0,101, 0,120, 0,116, 0,101, 0,110, 0,116, 0, 32, 0, 97, 0,112, 0,112, 0,108, 0,105, 0, 99, 0, 97, 0, 98, 0,
+108, 0,101, 0, 32, 0,116, 0,111, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0,115, 0, 10, 0,111, 0,114, 0, 32, 0, 70, 0,
+111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 32, 0,116, 0,104, 0, 97, 0,
+116, 0, 32, 0,104, 0, 97, 0,115, 0, 32, 0, 98, 0,101, 0,101, 0,110, 0, 32, 0,109, 0,111, 0,100, 0,105, 0,102, 0,
+105, 0,101, 0,100, 0, 32, 0, 97, 0,110, 0,100, 0, 32, 0,105, 0,115, 0, 32, 0,100, 0,105, 0,115, 0,116, 0,114, 0,
+105, 0, 98, 0,117, 0,116, 0,101, 0,100, 0, 32, 0,117, 0,110, 0,100, 0,101, 0,114, 0, 32, 0,116, 0,104, 0,101, 0,
+ 32, 0, 10, 0, 34, 0, 84, 0, 97, 0,118, 0,109, 0,106, 0,111, 0,110, 0,103, 0, 32, 0, 66, 0, 97, 0,104, 0, 32, 0,
+ 65, 0,114, 0,101, 0,118, 0, 34, 0, 32, 0,110, 0, 97, 0,109, 0,101, 0,115, 0, 46, 0, 10, 0, 10, 0, 84, 0,104, 0,
+101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 32, 0,
+109, 0, 97, 0,121, 0, 32, 0, 98, 0,101, 0, 32, 0,115, 0,111, 0,108, 0,100, 0, 32, 0, 97, 0,115, 0, 32, 0,112, 0,
+ 97, 0,114, 0,116, 0, 32, 0,111, 0,102, 0, 32, 0, 97, 0, 32, 0,108, 0, 97, 0,114, 0,103, 0,101, 0,114, 0, 32, 0,
+115, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 32, 0,112, 0, 97, 0, 99, 0,107, 0, 97, 0,103, 0,101, 0,
+ 32, 0, 98, 0,117, 0,116, 0, 10, 0,110, 0,111, 0, 32, 0, 99, 0,111, 0,112, 0,121, 0, 32, 0,111, 0,102, 0, 32, 0,
+111, 0,110, 0,101, 0, 32, 0,111, 0,114, 0, 32, 0,109, 0,111, 0,114, 0,101, 0, 32, 0,111, 0,102, 0, 32, 0,116, 0,
+104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0,
+ 32, 0,116, 0,121, 0,112, 0,101, 0,102, 0, 97, 0, 99, 0,101, 0,115, 0, 32, 0,109, 0, 97, 0,121, 0, 32, 0, 98, 0,
+101, 0, 32, 0,115, 0,111, 0,108, 0,100, 0, 32, 0, 98, 0,121, 0, 10, 0,105, 0,116, 0,115, 0,101, 0,108, 0,102, 0,
+ 46, 0, 10, 0, 10, 0, 84, 0, 72, 0, 69, 0, 32, 0, 70, 0, 79, 0, 78, 0, 84, 0, 32, 0, 83, 0, 79, 0, 70, 0, 84, 0,
+ 87, 0, 65, 0, 82, 0, 69, 0, 32, 0, 73, 0, 83, 0, 32, 0, 80, 0, 82, 0, 79, 0, 86, 0, 73, 0, 68, 0, 69, 0, 68, 0,
+ 32, 0, 34, 0, 65, 0, 83, 0, 32, 0, 73, 0, 83, 0, 34, 0, 44, 0, 32, 0, 87, 0, 73, 0, 84, 0, 72, 0, 79, 0, 85, 0,
+ 84, 0, 32, 0, 87, 0, 65, 0, 82, 0, 82, 0, 65, 0, 78, 0, 84, 0, 89, 0, 32, 0, 79, 0, 70, 0, 32, 0, 65, 0, 78, 0,
+ 89, 0, 32, 0, 75, 0, 73, 0, 78, 0, 68, 0, 44, 0, 10, 0, 69, 0, 88, 0, 80, 0, 82, 0, 69, 0, 83, 0, 83, 0, 32, 0,
+ 79, 0, 82, 0, 32, 0, 73, 0, 77, 0, 80, 0, 76, 0, 73, 0, 69, 0, 68, 0, 44, 0, 32, 0, 73, 0, 78, 0, 67, 0, 76, 0,
+ 85, 0, 68, 0, 73, 0, 78, 0, 71, 0, 32, 0, 66, 0, 85, 0, 84, 0, 32, 0, 78, 0, 79, 0, 84, 0, 32, 0, 76, 0, 73, 0,
+ 77, 0, 73, 0, 84, 0, 69, 0, 68, 0, 32, 0, 84, 0, 79, 0, 32, 0, 65, 0, 78, 0, 89, 0, 32, 0, 87, 0, 65, 0, 82, 0,
+ 82, 0, 65, 0, 78, 0, 84, 0, 73, 0, 69, 0, 83, 0, 32, 0, 79, 0, 70, 0, 10, 0, 77, 0, 69, 0, 82, 0, 67, 0, 72, 0,
+ 65, 0, 78, 0, 84, 0, 65, 0, 66, 0, 73, 0, 76, 0, 73, 0, 84, 0, 89, 0, 44, 0, 32, 0, 70, 0, 73, 0, 84, 0, 78, 0,
+ 69, 0, 83, 0, 83, 0, 32, 0, 70, 0, 79, 0, 82, 0, 32, 0, 65, 0, 32, 0, 80, 0, 65, 0, 82, 0, 84, 0, 73, 0, 67, 0,
+ 85, 0, 76, 0, 65, 0, 82, 0, 32, 0, 80, 0, 85, 0, 82, 0, 80, 0, 79, 0, 83, 0, 69, 0, 32, 0, 65, 0, 78, 0, 68, 0,
+ 32, 0, 78, 0, 79, 0, 78, 0, 73, 0, 78, 0, 70, 0, 82, 0, 73, 0, 78, 0, 71, 0, 69, 0, 77, 0, 69, 0, 78, 0, 84, 0,
+ 10, 0, 79, 0, 70, 0, 32, 0, 67, 0, 79, 0, 80, 0, 89, 0, 82, 0, 73, 0, 71, 0, 72, 0, 84, 0, 44, 0, 32, 0, 80, 0,
+ 65, 0, 84, 0, 69, 0, 78, 0, 84, 0, 44, 0, 32, 0, 84, 0, 82, 0, 65, 0, 68, 0, 69, 0, 77, 0, 65, 0, 82, 0, 75, 0,
+ 44, 0, 32, 0, 79, 0, 82, 0, 32, 0, 79, 0, 84, 0, 72, 0, 69, 0, 82, 0, 32, 0, 82, 0, 73, 0, 71, 0, 72, 0, 84, 0,
+ 46, 0, 32, 0, 73, 0, 78, 0, 32, 0, 78, 0, 79, 0, 32, 0, 69, 0, 86, 0, 69, 0, 78, 0, 84, 0, 32, 0, 83, 0, 72, 0,
+ 65, 0, 76, 0, 76, 0, 10, 0, 84, 0, 65, 0, 86, 0, 77, 0, 74, 0, 79, 0, 78, 0, 71, 0, 32, 0, 66, 0, 65, 0, 72, 0,
+ 32, 0, 66, 0, 69, 0, 32, 0, 76, 0, 73, 0, 65, 0, 66, 0, 76, 0, 69, 0, 32, 0, 70, 0, 79, 0, 82, 0, 32, 0, 65, 0,
+ 78, 0, 89, 0, 32, 0, 67, 0, 76, 0, 65, 0, 73, 0, 77, 0, 44, 0, 32, 0, 68, 0, 65, 0, 77, 0, 65, 0, 71, 0, 69, 0,
+ 83, 0, 32, 0, 79, 0, 82, 0, 32, 0, 79, 0, 84, 0, 72, 0, 69, 0, 82, 0, 32, 0, 76, 0, 73, 0, 65, 0, 66, 0, 73, 0,
+ 76, 0, 73, 0, 84, 0, 89, 0, 44, 0, 10, 0, 73, 0, 78, 0, 67, 0, 76, 0, 85, 0, 68, 0, 73, 0, 78, 0, 71, 0, 32, 0,
+ 65, 0, 78, 0, 89, 0, 32, 0, 71, 0, 69, 0, 78, 0, 69, 0, 82, 0, 65, 0, 76, 0, 44, 0, 32, 0, 83, 0, 80, 0, 69, 0,
+ 67, 0, 73, 0, 65, 0, 76, 0, 44, 0, 32, 0, 73, 0, 78, 0, 68, 0, 73, 0, 82, 0, 69, 0, 67, 0, 84, 0, 44, 0, 32, 0,
+ 73, 0, 78, 0, 67, 0, 73, 0, 68, 0, 69, 0, 78, 0, 84, 0, 65, 0, 76, 0, 44, 0, 32, 0, 79, 0, 82, 0, 32, 0, 67, 0,
+ 79, 0, 78, 0, 83, 0, 69, 0, 81, 0, 85, 0, 69, 0, 78, 0, 84, 0, 73, 0, 65, 0, 76, 0, 10, 0, 68, 0, 65, 0, 77, 0,
+ 65, 0, 71, 0, 69, 0, 83, 0, 44, 0, 32, 0, 87, 0, 72, 0, 69, 0, 84, 0, 72, 0, 69, 0, 82, 0, 32, 0, 73, 0, 78, 0,
+ 32, 0, 65, 0, 78, 0, 32, 0, 65, 0, 67, 0, 84, 0, 73, 0, 79, 0, 78, 0, 32, 0, 79, 0, 70, 0, 32, 0, 67, 0, 79, 0,
+ 78, 0, 84, 0, 82, 0, 65, 0, 67, 0, 84, 0, 44, 0, 32, 0, 84, 0, 79, 0, 82, 0, 84, 0, 32, 0, 79, 0, 82, 0, 32, 0,
+ 79, 0, 84, 0, 72, 0, 69, 0, 82, 0, 87, 0, 73, 0, 83, 0, 69, 0, 44, 0, 32, 0, 65, 0, 82, 0, 73, 0, 83, 0, 73, 0,
+ 78, 0, 71, 0, 10, 0, 70, 0, 82, 0, 79, 0, 77, 0, 44, 0, 32, 0, 79, 0, 85, 0, 84, 0, 32, 0, 79, 0, 70, 0, 32, 0,
+ 84, 0, 72, 0, 69, 0, 32, 0, 85, 0, 83, 0, 69, 0, 32, 0, 79, 0, 82, 0, 32, 0, 73, 0, 78, 0, 65, 0, 66, 0, 73, 0,
+ 76, 0, 73, 0, 84, 0, 89, 0, 32, 0, 84, 0, 79, 0, 32, 0, 85, 0, 83, 0, 69, 0, 32, 0, 84, 0, 72, 0, 69, 0, 32, 0,
+ 70, 0, 79, 0, 78, 0, 84, 0, 32, 0, 83, 0, 79, 0, 70, 0, 84, 0, 87, 0, 65, 0, 82, 0, 69, 0, 32, 0, 79, 0, 82, 0,
+ 32, 0, 70, 0, 82, 0, 79, 0, 77, 0, 10, 0, 79, 0, 84, 0, 72, 0, 69, 0, 82, 0, 32, 0, 68, 0, 69, 0, 65, 0, 76, 0,
+ 73, 0, 78, 0, 71, 0, 83, 0, 32, 0, 73, 0, 78, 0, 32, 0, 84, 0, 72, 0, 69, 0, 32, 0, 70, 0, 79, 0, 78, 0, 84, 0,
+ 32, 0, 83, 0, 79, 0, 70, 0, 84, 0, 87, 0, 65, 0, 82, 0, 69, 0, 46, 0, 10, 0, 10, 0, 69, 0,120, 0, 99, 0,101, 0,
+112, 0,116, 0, 32, 0, 97, 0,115, 0, 32, 0, 99, 0,111, 0,110, 0,116, 0, 97, 0,105, 0,110, 0,101, 0,100, 0, 32, 0,
+105, 0,110, 0, 32, 0,116, 0,104, 0,105, 0,115, 0, 32, 0,110, 0,111, 0,116, 0,105, 0, 99, 0,101, 0, 44, 0, 32, 0,
+116, 0,104, 0,101, 0, 32, 0,110, 0, 97, 0,109, 0,101, 0, 32, 0,111, 0,102, 0, 32, 0, 84, 0, 97, 0,118, 0,109, 0,
+106, 0,111, 0,110, 0,103, 0, 32, 0, 66, 0, 97, 0,104, 0, 32, 0,115, 0,104, 0, 97, 0,108, 0,108, 0, 32, 0,110, 0,
+111, 0,116, 0, 10, 0, 98, 0,101, 0, 32, 0,117, 0,115, 0,101, 0,100, 0, 32, 0,105, 0,110, 0, 32, 0, 97, 0,100, 0,
+118, 0,101, 0,114, 0,116, 0,105, 0,115, 0,105, 0,110, 0,103, 0, 32, 0,111, 0,114, 0, 32, 0,111, 0,116, 0,104, 0,
+101, 0,114, 0,119, 0,105, 0,115, 0,101, 0, 32, 0,116, 0,111, 0, 32, 0,112, 0,114, 0,111, 0,109, 0,111, 0,116, 0,
+101, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,115, 0, 97, 0,108, 0,101, 0, 44, 0, 32, 0,117, 0,115, 0,101, 0, 32, 0,
+111, 0,114, 0, 32, 0,111, 0,116, 0,104, 0,101, 0,114, 0, 10, 0,100, 0,101, 0, 97, 0,108, 0,105, 0,110, 0,103, 0,
+115, 0, 32, 0,105, 0,110, 0, 32, 0,116, 0,104, 0,105, 0,115, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,
+111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 32, 0,119, 0,105, 0,116, 0,104, 0,111, 0,117, 0,116, 0, 32, 0,
+112, 0,114, 0,105, 0,111, 0,114, 0, 32, 0,119, 0,114, 0,105, 0,116, 0,116, 0,101, 0,110, 0, 32, 0, 97, 0,117, 0,
+116, 0,104, 0,111, 0,114, 0,105, 0,122, 0, 97, 0,116, 0,105, 0,111, 0,110, 0, 10, 0,102, 0,114, 0,111, 0,109, 0,
+ 32, 0, 84, 0, 97, 0,118, 0,109, 0,106, 0,111, 0,110, 0,103, 0, 32, 0, 66, 0, 97, 0,104, 0, 46, 0, 32, 0, 70, 0,
+111, 0,114, 0, 32, 0,102, 0,117, 0,114, 0,116, 0,104, 0,101, 0,114, 0, 32, 0,105, 0,110, 0,102, 0,111, 0,114, 0,
+109, 0, 97, 0,116, 0,105, 0,111, 0,110, 0, 44, 0, 32, 0, 99, 0,111, 0,110, 0,116, 0, 97, 0, 99, 0,116, 0, 58, 0,
+ 32, 0,116, 0, 97, 0,118, 0,109, 0,106, 0,111, 0,110, 0,103, 0, 32, 0, 64, 0, 32, 0,102, 0,114, 0,101, 0,101, 0,
+ 10, 0, 46, 0, 32, 0,102, 0,114, 0, 46, 0, 0, 70,111,110,116,115, 32, 97,114,101, 32, 40, 99, 41, 32, 66,105,116,115,116,
+114,101, 97,109, 32, 40,115,101,101, 32, 98,101,108,111,119, 41, 46, 32, 68,101,106, 97, 86,117, 32, 99,104, 97,110,103,101,115,
+ 32, 97,114,101, 32,105,110, 32,112,117, 98,108,105, 99, 32,100,111,109, 97,105,110, 46, 32, 71,108,121,112,104,115, 32,105,109,
+112,111,114,116,101,100, 32,102,114,111,109, 32, 65,114,101,118, 32,102,111,110,116,115, 32, 97,114,101, 32, 40, 99, 41, 32, 84,
+ 97,118,109,106,117,110,103, 32, 66, 97,104, 32, 40,115,101,101, 32, 98,101,108,111,119, 41, 10, 10, 66,105,116,115,116,114,101,
+ 97,109, 32, 86,101,114, 97, 32, 70,111,110,116,115, 32, 67,111,112,121,114,105,103,104,116, 10, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 10, 10, 67,111,112,121,114,105,103,104,
+116, 32, 40, 99, 41, 32, 50, 48, 48, 51, 32, 98,121, 32, 66,105,116,115,116,114,101, 97,109, 44, 32, 73,110, 99, 46, 32, 65,108,
+108, 32, 82,105,103,104,116,115, 32, 82,101,115,101,114,118,101,100, 46, 32, 66,105,116,115,116,114,101, 97,109, 32, 86,101,114,
+ 97, 32,105,115, 10, 97, 32,116,114, 97,100,101,109, 97,114,107, 32,111,102, 32, 66,105,116,115,116,114,101, 97,109, 44, 32, 73,
+110, 99, 46, 10, 10, 80,101,114,109,105,115,115,105,111,110, 32,105,115, 32,104,101,114,101, 98,121, 32,103,114, 97,110,116,101,
+100, 44, 32,102,114,101,101, 32,111,102, 32, 99,104, 97,114,103,101, 44, 32,116,111, 32, 97,110,121, 32,112,101,114,115,111,110,
+ 32,111, 98,116, 97,105,110,105,110,103, 32, 97, 32, 99,111,112,121, 10,111,102, 32,116,104,101, 32,102,111,110,116,115, 32, 97,
+ 99, 99,111,109,112, 97,110,121,105,110,103, 32,116,104,105,115, 32,108,105, 99,101,110,115,101, 32, 40, 34, 70,111,110,116,115,
+ 34, 41, 32, 97,110,100, 32, 97,115,115,111, 99,105, 97,116,101,100, 10,100,111, 99,117,109,101,110,116, 97,116,105,111,110, 32,
+102,105,108,101,115, 32, 40,116,104,101, 32, 34, 70,111,110,116, 32, 83,111,102,116,119, 97,114,101, 34, 41, 44, 32,116,111, 32,
+114,101,112,114,111,100,117, 99,101, 32, 97,110,100, 32,100,105,115,116,114,105, 98,117,116,101, 32,116,104,101, 10, 70,111,110,
+116, 32, 83,111,102,116,119, 97,114,101, 44, 32,105,110, 99,108,117,100,105,110,103, 32,119,105,116,104,111,117,116, 32,108,105,
+109,105,116, 97,116,105,111,110, 32,116,104,101, 32,114,105,103,104,116,115, 32,116,111, 32,117,115,101, 44, 32, 99,111,112,121,
+ 44, 32,109,101,114,103,101, 44, 10,112,117, 98,108,105,115,104, 44, 32,100,105,115,116,114,105, 98,117,116,101, 44, 32, 97,110,
+100, 47,111,114, 32,115,101,108,108, 32, 99,111,112,105,101,115, 32,111,102, 32,116,104,101, 32, 70,111,110,116, 32, 83,111,102,
+116,119, 97,114,101, 44, 32, 97,110,100, 32,116,111, 32,112,101,114,109,105,116, 10,112,101,114,115,111,110,115, 32,116,111, 32,
+119,104,111,109, 32,116,104,101, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,114,101, 32,105,115, 32,102,117,114,110,105,115,
+104,101,100, 32,116,111, 32,100,111, 32,115,111, 44, 32,115,117, 98,106,101, 99,116, 32,116,111, 32,116,104,101, 10,102,111,108,
+108,111,119,105,110,103, 32, 99,111,110,100,105,116,105,111,110,115, 58, 10, 10, 84,104,101, 32, 97, 98,111,118,101, 32, 99,111,
+112,121,114,105,103,104,116, 32, 97,110,100, 32,116,114, 97,100,101,109, 97,114,107, 32,110,111,116,105, 99,101,115, 32, 97,110,
+100, 32,116,104,105,115, 32,112,101,114,109,105,115,115,105,111,110, 32,110,111,116,105, 99,101, 32,115,104, 97,108,108, 10, 98,
+101, 32,105,110, 99,108,117,100,101,100, 32,105,110, 32, 97,108,108, 32, 99,111,112,105,101,115, 32,111,102, 32,111,110,101, 32,
+111,114, 32,109,111,114,101, 32,111,102, 32,116,104,101, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,114,101, 32,116,121,112,
+101,102, 97, 99,101,115, 46, 10, 10, 84,104,101, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,114,101, 32,109, 97,121, 32, 98,
+101, 32,109,111,100,105,102,105,101,100, 44, 32, 97,108,116,101,114,101,100, 44, 32,111,114, 32, 97,100,100,101,100, 32,116,111,
+ 44, 32, 97,110,100, 32,105,110, 32,112, 97,114,116,105, 99,117,108, 97,114, 10,116,104,101, 32,100,101,115,105,103,110,115, 32,
+111,102, 32,103,108,121,112,104,115, 32,111,114, 32, 99,104, 97,114, 97, 99,116,101,114,115, 32,105,110, 32,116,104,101, 32, 70,
+111,110,116,115, 32,109, 97,121, 32, 98,101, 32,109,111,100,105,102,105,101,100, 32, 97,110,100, 10, 97,100,100,105,116,105,111,
+110, 97,108, 32,103,108,121,112,104,115, 32,111,114, 32, 99,104, 97,114, 97, 99,116,101,114,115, 32,109, 97,121, 32, 98,101, 32,
+ 97,100,100,101,100, 32,116,111, 32,116,104,101, 32, 70,111,110,116,115, 44, 32,111,110,108,121, 32,105,102, 32,116,104,101, 32,
+102,111,110,116,115, 10, 97,114,101, 32,114,101,110, 97,109,101,100, 32,116,111, 32,110, 97,109,101,115, 32,110,111,116, 32, 99,
+111,110,116, 97,105,110,105,110,103, 32,101,105,116,104,101,114, 32,116,104,101, 32,119,111,114,100,115, 32, 34, 66,105,116,115,
+116,114,101, 97,109, 34, 32,111,114, 32,116,104,101, 32,119,111,114,100, 10, 34, 86,101,114, 97, 34, 46, 10, 10, 84,104,105,115,
+ 32, 76,105, 99,101,110,115,101, 32, 98,101, 99,111,109,101,115, 32,110,117,108,108, 32, 97,110,100, 32,118,111,105,100, 32,116,
+111, 32,116,104,101, 32,101,120,116,101,110,116, 32, 97,112,112,108,105, 99, 97, 98,108,101, 32,116,111, 32, 70,111,110,116,115,
+ 32,111,114, 32, 70,111,110,116, 10, 83,111,102,116,119, 97,114,101, 32,116,104, 97,116, 32,104, 97,115, 32, 98,101,101,110, 32,
+109,111,100,105,102,105,101,100, 32, 97,110,100, 32,105,115, 32,100,105,115,116,114,105, 98,117,116,101,100, 32,117,110,100,101,
+114, 32,116,104,101, 32, 34, 66,105,116,115,116,114,101, 97,109, 10, 86,101,114, 97, 34, 32,110, 97,109,101,115, 46, 10, 10, 84,
+104,101, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,114,101, 32,109, 97,121, 32, 98,101, 32,115,111,108,100, 32, 97,115, 32,
+112, 97,114,116, 32,111,102, 32, 97, 32,108, 97,114,103,101,114, 32,115,111,102,116,119, 97,114,101, 32,112, 97, 99,107, 97,103,
+101, 32, 98,117,116, 32,110,111, 10, 99,111,112,121, 32,111,102, 32,111,110,101, 32,111,114, 32,109,111,114,101, 32,111,102, 32,
+116,104,101, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,114,101, 32,116,121,112,101,102, 97, 99,101,115, 32,109, 97,121, 32,
+ 98,101, 32,115,111,108,100, 32, 98,121, 32,105,116,115,101,108,102, 46, 10, 10, 84, 72, 69, 32, 70, 79, 78, 84, 32, 83, 79, 70,
+ 84, 87, 65, 82, 69, 32, 73, 83, 32, 80, 82, 79, 86, 73, 68, 69, 68, 32, 34, 65, 83, 32, 73, 83, 34, 44, 32, 87, 73, 84, 72, 79,
+ 85, 84, 32, 87, 65, 82, 82, 65, 78, 84, 89, 32, 79, 70, 32, 65, 78, 89, 32, 75, 73, 78, 68, 44, 32, 69, 88, 80, 82, 69, 83, 83,
+ 10, 79, 82, 32, 73, 77, 80, 76, 73, 69, 68, 44, 32, 73, 78, 67, 76, 85, 68, 73, 78, 71, 32, 66, 85, 84, 32, 78, 79, 84, 32, 76,
+ 73, 77, 73, 84, 69, 68, 32, 84, 79, 32, 65, 78, 89, 32, 87, 65, 82, 82, 65, 78, 84, 73, 69, 83, 32, 79, 70, 32, 77, 69, 82, 67,
+ 72, 65, 78, 84, 65, 66, 73, 76, 73, 84, 89, 44, 10, 70, 73, 84, 78, 69, 83, 83, 32, 70, 79, 82, 32, 65, 32, 80, 65, 82, 84, 73,
+ 67, 85, 76, 65, 82, 32, 80, 85, 82, 80, 79, 83, 69, 32, 65, 78, 68, 32, 78, 79, 78, 73, 78, 70, 82, 73, 78, 71, 69, 77, 69, 78,
+ 84, 32, 79, 70, 32, 67, 79, 80, 89, 82, 73, 71, 72, 84, 44, 32, 80, 65, 84, 69, 78, 84, 44, 10, 84, 82, 65, 68, 69, 77, 65, 82,
+ 75, 44, 32, 79, 82, 32, 79, 84, 72, 69, 82, 32, 82, 73, 71, 72, 84, 46, 32, 73, 78, 32, 78, 79, 32, 69, 86, 69, 78, 84, 32, 83,
+ 72, 65, 76, 76, 32, 66, 73, 84, 83, 84, 82, 69, 65, 77, 32, 79, 82, 32, 84, 72, 69, 32, 71, 78, 79, 77, 69, 10, 70, 79, 85, 78,
+ 68, 65, 84, 73, 79, 78, 32, 66, 69, 32, 76, 73, 65, 66, 76, 69, 32, 70, 79, 82, 32, 65, 78, 89, 32, 67, 76, 65, 73, 77, 44, 32,
+ 68, 65, 77, 65, 71, 69, 83, 32, 79, 82, 32, 79, 84, 72, 69, 82, 32, 76, 73, 65, 66, 73, 76, 73, 84, 89, 44, 32, 73, 78, 67, 76,
+ 85, 68, 73, 78, 71, 10, 65, 78, 89, 32, 71, 69, 78, 69, 82, 65, 76, 44, 32, 83, 80, 69, 67, 73, 65, 76, 44, 32, 73, 78, 68, 73,
+ 82, 69, 67, 84, 44, 32, 73, 78, 67, 73, 68, 69, 78, 84, 65, 76, 44, 32, 79, 82, 32, 67, 79, 78, 83, 69, 81, 85, 69, 78, 84, 73,
+ 65, 76, 32, 68, 65, 77, 65, 71, 69, 83, 44, 10, 87, 72, 69, 84, 72, 69, 82, 32, 73, 78, 32, 65, 78, 32, 65, 67, 84, 73, 79, 78,
+ 32, 79, 70, 32, 67, 79, 78, 84, 82, 65, 67, 84, 44, 32, 84, 79, 82, 84, 32, 79, 82, 32, 79, 84, 72, 69, 82, 87, 73, 83, 69, 44,
+ 32, 65, 82, 73, 83, 73, 78, 71, 32, 70, 82, 79, 77, 44, 32, 79, 85, 84, 32, 79, 70, 10, 84, 72, 69, 32, 85, 83, 69, 32, 79, 82,
+ 32, 73, 78, 65, 66, 73, 76, 73, 84, 89, 32, 84, 79, 32, 85, 83, 69, 32, 84, 72, 69, 32, 70, 79, 78, 84, 32, 83, 79, 70, 84, 87,
+ 65, 82, 69, 32, 79, 82, 32, 70, 82, 79, 77, 32, 79, 84, 72, 69, 82, 32, 68, 69, 65, 76, 73, 78, 71, 83, 32, 73, 78, 32, 84, 72,
+ 69, 10, 70, 79, 78, 84, 32, 83, 79, 70, 84, 87, 65, 82, 69, 46, 10, 10, 69,120, 99,101,112,116, 32, 97,115, 32, 99,111,110,116,
+ 97,105,110,101,100, 32,105,110, 32,116,104,105,115, 32,110,111,116,105, 99,101, 44, 32,116,104,101, 32,110, 97,109,101,115, 32,
+111,102, 32, 71,110,111,109,101, 44, 32,116,104,101, 32, 71,110,111,109,101, 10, 70,111,117,110,100, 97,116,105,111,110, 44, 32,
+ 97,110,100, 32, 66,105,116,115,116,114,101, 97,109, 32, 73,110, 99, 46, 44, 32,115,104, 97,108,108, 32,110,111,116, 32, 98,101,
+ 32,117,115,101,100, 32,105,110, 32, 97,100,118,101,114,116,105,115,105,110,103, 32,111,114, 10,111,116,104,101,114,119,105,115,
+101, 32,116,111, 32,112,114,111,109,111,116,101, 32,116,104,101, 32,115, 97,108,101, 44, 32,117,115,101, 32,111,114, 32,111,116,
+104,101,114, 32,100,101, 97,108,105,110,103,115, 32,105,110, 32,116,104,105,115, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,
+114,101, 10,119,105,116,104,111,117,116, 32,112,114,105,111,114, 32,119,114,105,116,116,101,110, 32, 97,117,116,104,111,114,105,
+122, 97,116,105,111,110, 32,102,114,111,109, 32,116,104,101, 32, 71,110,111,109,101, 32, 70,111,117,110,100, 97,116,105,111,110,
+ 32,111,114, 32, 66,105,116,115,116,114,101, 97,109, 10, 73,110, 99, 46, 44, 32,114,101,115,112,101, 99,116,105,118,101,108,121,
+ 46, 32, 70,111,114, 32,102,117,114,116,104,101,114, 32,105,110,102,111,114,109, 97,116,105,111,110, 44, 32, 99,111,110,116, 97,
+ 99,116, 58, 32,102,111,110,116,115, 32, 97,116, 32,103,110,111,109,101, 32,100,111,116, 10,111,114,103, 46, 32, 10, 10, 65,114,
+101,118, 32, 70,111,110,116,115, 32, 67,111,112,121,114,105,103,104,116, 10, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 10, 10, 67,111,112,121,114,105,103,104,116, 32, 40, 99, 41,
+ 32, 50, 48, 48, 54, 32, 98,121, 32, 84, 97,118,109,106,111,110,103, 32, 66, 97,104, 46, 32, 65,108,108, 32, 82,105,103,104,116,
+115, 32, 82,101,115,101,114,118,101,100, 46, 10, 10, 80,101,114,109,105,115,115,105,111,110, 32,105,115, 32,104,101,114,101, 98,
+121, 32,103,114, 97,110,116,101,100, 44, 32,102,114,101,101, 32,111,102, 32, 99,104, 97,114,103,101, 44, 32,116,111, 32, 97,110,
+121, 32,112,101,114,115,111,110, 32,111, 98,116, 97,105,110,105,110,103, 10, 97, 32, 99,111,112,121, 32,111,102, 32,116,104,101,
+ 32,102,111,110,116,115, 32, 97, 99, 99,111,109,112, 97,110,121,105,110,103, 32,116,104,105,115, 32,108,105, 99,101,110,115,101,
+ 32, 40, 34, 70,111,110,116,115, 34, 41, 32, 97,110,100, 10, 97,115,115,111, 99,105, 97,116,101,100, 32,100,111, 99,117,109,101,
+110,116, 97,116,105,111,110, 32,102,105,108,101,115, 32, 40,116,104,101, 32, 34, 70,111,110,116, 32, 83,111,102,116,119, 97,114,
+101, 34, 41, 44, 32,116,111, 32,114,101,112,114,111,100,117, 99,101, 10, 97,110,100, 32,100,105,115,116,114,105, 98,117,116,101,
+ 32,116,104,101, 32,109,111,100,105,102,105, 99, 97,116,105,111,110,115, 32,116,111, 32,116,104,101, 32, 66,105,116,115,116,114,
+101, 97,109, 32, 86,101,114, 97, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,114,101, 44, 10,105,110, 99,108,117,100,105,110,
+103, 32,119,105,116,104,111,117,116, 32,108,105,109,105,116, 97,116,105,111,110, 32,116,104,101, 32,114,105,103,104,116,115, 32,
+116,111, 32,117,115,101, 44, 32, 99,111,112,121, 44, 32,109,101,114,103,101, 44, 32,112,117, 98,108,105,115,104, 44, 10,100,105,
+115,116,114,105, 98,117,116,101, 44, 32, 97,110,100, 47,111,114, 32,115,101,108,108, 32, 99,111,112,105,101,115, 32,111,102, 32,
+116,104,101, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,114,101, 44, 32, 97,110,100, 32,116,111, 32,112,101,114,109,105,116,
+ 10,112,101,114,115,111,110,115, 32,116,111, 32,119,104,111,109, 32,116,104,101, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,
+114,101, 32,105,115, 32,102,117,114,110,105,115,104,101,100, 32,116,111, 32,100,111, 32,115,111, 44, 32,115,117, 98,106,101, 99,
+116, 32,116,111, 10,116,104,101, 32,102,111,108,108,111,119,105,110,103, 32, 99,111,110,100,105,116,105,111,110,115, 58, 10, 10,
+ 84,104,101, 32, 97, 98,111,118,101, 32, 99,111,112,121,114,105,103,104,116, 32, 97,110,100, 32,116,114, 97,100,101,109, 97,114,
+107, 32,110,111,116,105, 99,101,115, 32, 97,110,100, 32,116,104,105,115, 32,112,101,114,109,105,115,115,105,111,110, 32,110,111,
+116,105, 99,101, 10,115,104, 97,108,108, 32, 98,101, 32,105,110, 99,108,117,100,101,100, 32,105,110, 32, 97,108,108, 32, 99,111,
+112,105,101,115, 32,111,102, 32,111,110,101, 32,111,114, 32,109,111,114,101, 32,111,102, 32,116,104,101, 32, 70,111,110,116, 32,
+ 83,111,102,116,119, 97,114,101, 10,116,121,112,101,102, 97, 99,101,115, 46, 10, 10, 84,104,101, 32, 70,111,110,116, 32, 83,111,
+102,116,119, 97,114,101, 32,109, 97,121, 32, 98,101, 32,109,111,100,105,102,105,101,100, 44, 32, 97,108,116,101,114,101,100, 44,
+ 32,111,114, 32, 97,100,100,101,100, 32,116,111, 44, 32, 97,110,100, 32,105,110, 10,112, 97,114,116,105, 99,117,108, 97,114, 32,
+116,104,101, 32,100,101,115,105,103,110,115, 32,111,102, 32,103,108,121,112,104,115, 32,111,114, 32, 99,104, 97,114, 97, 99,116,
+101,114,115, 32,105,110, 32,116,104,101, 32, 70,111,110,116,115, 32,109, 97,121, 32, 98,101, 10,109,111,100,105,102,105,101,100,
+ 32, 97,110,100, 32, 97,100,100,105,116,105,111,110, 97,108, 32,103,108,121,112,104,115, 32,111,114, 32, 99,104, 97,114, 97, 99,
+116,101,114,115, 32,109, 97,121, 32, 98,101, 32, 97,100,100,101,100, 32,116,111, 32,116,104,101, 10, 70,111,110,116,115, 44, 32,
+111,110,108,121, 32,105,102, 32,116,104,101, 32,102,111,110,116,115, 32, 97,114,101, 32,114,101,110, 97,109,101,100, 32,116,111,
+ 32,110, 97,109,101,115, 32,110,111,116, 32, 99,111,110,116, 97,105,110,105,110,103, 32,101,105,116,104,101,114, 10,116,104,101,
+ 32,119,111,114,100,115, 32, 34, 84, 97,118,109,106,111,110,103, 32, 66, 97,104, 34, 32,111,114, 32,116,104,101, 32,119,111,114,
+100, 32, 34, 65,114,101,118, 34, 46, 10, 10, 84,104,105,115, 32, 76,105, 99,101,110,115,101, 32, 98,101, 99,111,109,101,115, 32,
+110,117,108,108, 32, 97,110,100, 32,118,111,105,100, 32,116,111, 32,116,104,101, 32,101,120,116,101,110,116, 32, 97,112,112,108,
+105, 99, 97, 98,108,101, 32,116,111, 32, 70,111,110,116,115, 10,111,114, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,114,101,
+ 32,116,104, 97,116, 32,104, 97,115, 32, 98,101,101,110, 32,109,111,100,105,102,105,101,100, 32, 97,110,100, 32,105,115, 32,100,
+105,115,116,114,105, 98,117,116,101,100, 32,117,110,100,101,114, 32,116,104,101, 32, 10, 34, 84, 97,118,109,106,111,110,103, 32,
+ 66, 97,104, 32, 65,114,101,118, 34, 32,110, 97,109,101,115, 46, 10, 10, 84,104,101, 32, 70,111,110,116, 32, 83,111,102,116,119,
+ 97,114,101, 32,109, 97,121, 32, 98,101, 32,115,111,108,100, 32, 97,115, 32,112, 97,114,116, 32,111,102, 32, 97, 32,108, 97,114,
+103,101,114, 32,115,111,102,116,119, 97,114,101, 32,112, 97, 99,107, 97,103,101, 32, 98,117,116, 10,110,111, 32, 99,111,112,121,
+ 32,111,102, 32,111,110,101, 32,111,114, 32,109,111,114,101, 32,111,102, 32,116,104,101, 32, 70,111,110,116, 32, 83,111,102,116,
+119, 97,114,101, 32,116,121,112,101,102, 97, 99,101,115, 32,109, 97,121, 32, 98,101, 32,115,111,108,100, 32, 98,121, 10,105,116,
+115,101,108,102, 46, 10, 10, 84, 72, 69, 32, 70, 79, 78, 84, 32, 83, 79, 70, 84, 87, 65, 82, 69, 32, 73, 83, 32, 80, 82, 79, 86,
+ 73, 68, 69, 68, 32, 34, 65, 83, 32, 73, 83, 34, 44, 32, 87, 73, 84, 72, 79, 85, 84, 32, 87, 65, 82, 82, 65, 78, 84, 89, 32, 79,
+ 70, 32, 65, 78, 89, 32, 75, 73, 78, 68, 44, 10, 69, 88, 80, 82, 69, 83, 83, 32, 79, 82, 32, 73, 77, 80, 76, 73, 69, 68, 44, 32,
+ 73, 78, 67, 76, 85, 68, 73, 78, 71, 32, 66, 85, 84, 32, 78, 79, 84, 32, 76, 73, 77, 73, 84, 69, 68, 32, 84, 79, 32, 65, 78, 89,
+ 32, 87, 65, 82, 82, 65, 78, 84, 73, 69, 83, 32, 79, 70, 10, 77, 69, 82, 67, 72, 65, 78, 84, 65, 66, 73, 76, 73, 84, 89, 44, 32,
+ 70, 73, 84, 78, 69, 83, 83, 32, 70, 79, 82, 32, 65, 32, 80, 65, 82, 84, 73, 67, 85, 76, 65, 82, 32, 80, 85, 82, 80, 79, 83, 69,
+ 32, 65, 78, 68, 32, 78, 79, 78, 73, 78, 70, 82, 73, 78, 71, 69, 77, 69, 78, 84, 10, 79, 70, 32, 67, 79, 80, 89, 82, 73, 71, 72,
+ 84, 44, 32, 80, 65, 84, 69, 78, 84, 44, 32, 84, 82, 65, 68, 69, 77, 65, 82, 75, 44, 32, 79, 82, 32, 79, 84, 72, 69, 82, 32, 82,
+ 73, 71, 72, 84, 46, 32, 73, 78, 32, 78, 79, 32, 69, 86, 69, 78, 84, 32, 83, 72, 65, 76, 76, 10, 84, 65, 86, 77, 74, 79, 78, 71,
+ 32, 66, 65, 72, 32, 66, 69, 32, 76, 73, 65, 66, 76, 69, 32, 70, 79, 82, 32, 65, 78, 89, 32, 67, 76, 65, 73, 77, 44, 32, 68, 65,
+ 77, 65, 71, 69, 83, 32, 79, 82, 32, 79, 84, 72, 69, 82, 32, 76, 73, 65, 66, 73, 76, 73, 84, 89, 44, 10, 73, 78, 67, 76, 85, 68,
+ 73, 78, 71, 32, 65, 78, 89, 32, 71, 69, 78, 69, 82, 65, 76, 44, 32, 83, 80, 69, 67, 73, 65, 76, 44, 32, 73, 78, 68, 73, 82, 69,
+ 67, 84, 44, 32, 73, 78, 67, 73, 68, 69, 78, 84, 65, 76, 44, 32, 79, 82, 32, 67, 79, 78, 83, 69, 81, 85, 69, 78, 84, 73, 65, 76,
+ 10, 68, 65, 77, 65, 71, 69, 83, 44, 32, 87, 72, 69, 84, 72, 69, 82, 32, 73, 78, 32, 65, 78, 32, 65, 67, 84, 73, 79, 78, 32, 79,
+ 70, 32, 67, 79, 78, 84, 82, 65, 67, 84, 44, 32, 84, 79, 82, 84, 32, 79, 82, 32, 79, 84, 72, 69, 82, 87, 73, 83, 69, 44, 32, 65,
+ 82, 73, 83, 73, 78, 71, 10, 70, 82, 79, 77, 44, 32, 79, 85, 84, 32, 79, 70, 32, 84, 72, 69, 32, 85, 83, 69, 32, 79, 82, 32, 73,
+ 78, 65, 66, 73, 76, 73, 84, 89, 32, 84, 79, 32, 85, 83, 69, 32, 84, 72, 69, 32, 70, 79, 78, 84, 32, 83, 79, 70, 84, 87, 65, 82,
+ 69, 32, 79, 82, 32, 70, 82, 79, 77, 10, 79, 84, 72, 69, 82, 32, 68, 69, 65, 76, 73, 78, 71, 83, 32, 73, 78, 32, 84, 72, 69, 32,
+ 70, 79, 78, 84, 32, 83, 79, 70, 84, 87, 65, 82, 69, 46, 10, 10, 69,120, 99,101,112,116, 32, 97,115, 32, 99,111,110,116, 97,105,
+110,101,100, 32,105,110, 32,116,104,105,115, 32,110,111,116,105, 99,101, 44, 32,116,104,101, 32,110, 97,109,101, 32,111,102, 32,
+ 84, 97,118,109,106,111,110,103, 32, 66, 97,104, 32,115,104, 97,108,108, 32,110,111,116, 10, 98,101, 32,117,115,101,100, 32,105,
+110, 32, 97,100,118,101,114,116,105,115,105,110,103, 32,111,114, 32,111,116,104,101,114,119,105,115,101, 32,116,111, 32,112,114,
+111,109,111,116,101, 32,116,104,101, 32,115, 97,108,101, 44, 32,117,115,101, 32,111,114, 32,111,116,104,101,114, 10,100,101, 97,
+108,105,110,103,115, 32,105,110, 32,116,104,105,115, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,114,101, 32,119,105,116,104,
+111,117,116, 32,112,114,105,111,114, 32,119,114,105,116,116,101,110, 32, 97,117,116,104,111,114,105,122, 97,116,105,111,110, 10,
+102,114,111,109, 32, 84, 97,118,109,106,111,110,103, 32, 66, 97,104, 46, 32, 70,111,114, 32,102,117,114,116,104,101,114, 32,105,
+110,102,111,114,109, 97,116,105,111,110, 44, 32, 99,111,110,116, 97, 99,116, 58, 32,116, 97,118,109,106,111,110,103, 32, 64, 32,
+102,114,101,101, 10, 46, 32,102,114, 46, 0, 0,104, 0,116, 0,116, 0,112, 0, 58, 0, 47, 0, 47, 0,100, 0,101, 0,106, 0,
+ 97, 0,118, 0,117, 0, 46, 0,115, 0,111, 0,117, 0,114, 0, 99, 0,101, 0,102, 0,111, 0,114, 0,103, 0,101, 0, 46, 0,
+110, 0,101, 0,116, 0, 47, 0,119, 0,105, 0,107, 0,105, 0, 47, 0,105, 0,110, 0,100, 0,101, 0,120, 0, 46, 0,112, 0,
+104, 0,112, 0, 47, 0, 76, 0,105, 0, 99, 0,101, 0,110, 0,115, 0,101, 0, 0,104,116,116,112, 58, 47, 47,100,101,106, 97,
+118,117, 46,115,111,117,114, 99,101,102,111,114,103,101, 46,110,101,116, 47,119,105,107,105, 47,105,110,100,101,120, 46,112,104,
+112, 47, 76,105, 99,101,110,115,101, 0, 65,108,108, 32, 84,121,112,111,103,114, 97,112,104,105, 99, 32, 70,101, 97,116,117,114,
+101,115, 0, 70,111,110, 99,116,105,111,110,115, 32,116,121,112,111,103,114, 97,112,104,105,113,117,101,115, 0, 65,108,108,101,
+ 32,116,121,112,111,103,114, 97,102,105,115, 99,104,101,110, 32, 77,154,103,108,105, 99,104,107,101,105,116,101,110, 0, 70,117,
+110,122,105,111,110,105, 32, 84,105,112,111,103,114, 97,102,105, 99,104,101, 0, 65,108,108,101, 32,116,121,112,111,103,114, 97,
+102,105,115, 99,104,101, 32,107,101,110,109,101,114,107,101,110, 0, 76,105,103, 97,116,117,114,101,115, 0, 76,105,103, 97,116,
+117,114,101,115, 0, 76,105,103, 97,116,117,114,101,110, 0, 76,101,103, 97,116,117,114,101, 0, 76,105,103, 97,116,117,114,101,
+110, 0, 67,117,114,115,105,118,101, 32, 99,111,110,110,101, 99,116,105,111,110, 0, 67,111,110,110,101, 99,116,105,111,110, 32,
+100,101,115, 32, 67,117,114,115,105,118,101,115, 0, 67,117,114,115,105,101,118,101, 32,118,101,114, 98,105,110,100,105,110,103,
+ 0, 70,114, 97, 99,116,105,111,110,115, 0, 70,114, 97, 99,116,105,111,110,115, 0, 66,114,101,117,107,101,110, 0, 65,108,108,
+ 32, 84,121,112,101, 32, 70,101, 97,116,117,114,101,115, 0, 84,111,117,116,101,115, 32,102,111,110, 99,116,105,111,110,115, 32,
+116,121,112,111,103,114, 97,112,104,105,113,117,101,115, 0, 65,108,108,101, 32, 65,117,115,122,101,105, 99,104,110,117,110,103,
+115, 97,114,116,101,110, 0, 84,117,116,116,101, 32,108,101, 32, 70,117,110,122,105,111,110,105, 0, 65,108,108,101, 32,116,121,
+112,101,107,101,110,109,101,114,107,101,110, 0, 67,111,109,109,111,110, 32, 76,105,103, 97,116,117,114,101,115, 0, 76,105,103,
+ 97,116,117,114,101,115, 32, 85,115,117,101,108,108,101,115, 0, 78,111,114,109, 97,108,101, 32, 76,105,103, 97,116,117,114,101,
+110, 0, 76,101,103, 97,116,117,114,101, 32,112,105,157, 32, 67,111,109,117,110,105, 0, 71,101,109,101,101,110,115, 99,104, 97,
+112,112,101,108,105,106,107,101, 32, 76,105,103, 97,116,117,114,101,110, 0, 82, 97,114,101, 32, 76,105,103, 97,116,117,114,101,
+115, 0, 76,105,103, 97,116,117,114,101,115, 32, 82, 97,114,101,115, 0, 83,101,108,116,101,110,101, 32, 76,105,103, 97,116,117,
+114,101,110, 0, 76,101,103, 97,116,117,114,101, 32, 82, 97,114,101, 0, 90,101,108,100,122, 97,109,101, 32,108,105,103, 97,116,
+117,114,101,110, 0, 67,117,114,115,105,118,101, 0, 80,108,101,105,110,101,109,101,110,116, 32, 99,111,110,110,101, 99,116,142,
+101,115, 0, 67,117,114,115,105,101,102, 0, 68,105, 97,103,111,110, 97,108, 32, 70,114, 97, 99,116,105,111,110,115, 0, 70,114,
+ 97, 99,116,105,111,110,115, 32,101,110, 32, 68,105, 97,103,111,110, 97,108,101, 0, 68,105, 97,103,111,110, 97,108,101,114, 32,
+ 66,114,117, 99,104, 0, 70,114, 97,122,105,111,110,105, 32, 68,105, 97,103,111,110, 97,108,105, 0, 68,105, 97,103,111,110, 97,
+108,101, 32, 98,114,101,117,107,101,110, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,255,171, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,163, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8,
+ 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16, 0, 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24,
+ 0, 25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0, 31, 0, 32, 0, 33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38, 0, 39, 0, 40,
+ 0, 41, 0, 42, 0, 43, 0, 44, 0, 45, 0, 46, 0, 47, 0, 48, 0, 49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, 0, 56,
+ 0, 57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 64, 0, 65, 0, 66, 0, 67, 0, 68, 0, 69, 0, 70, 0, 71, 0, 72,
+ 0, 73, 0, 74, 0, 75, 0, 76, 0, 77, 0, 78, 0, 79, 0, 80, 0, 81, 0, 82, 0, 83, 0, 84, 0, 85, 0, 86, 0, 87, 0, 88,
+ 0, 89, 0, 90, 0, 91, 0, 92, 0, 93, 0, 94, 0, 95, 0, 96, 0, 97, 0,172, 0,163, 0,132, 0,133, 0,189, 0,150, 0,232,
+ 0,134, 0,142, 0,139, 0,157, 0,169, 0,164, 1, 2, 0,138, 0,218, 0,131, 0,147, 0,242, 0,243, 0,141, 0,151, 0,136,
+ 0,195, 0,222, 0,241, 0,158, 0,170, 0,245, 0,244, 0,246, 0,162, 0,173, 0,201, 0,199, 0,174, 0, 98, 0, 99, 0,144,
+ 0,100, 0,203, 0,101, 0,200, 0,202, 0,207, 0,204, 0,205, 0,206, 0,233, 0,102, 0,211, 0,208, 0,209, 0,175, 0,103,
+ 0,240, 0,145, 0,214, 0,212, 0,213, 0,104, 0,235, 0,237, 0,137, 0,106, 0,105, 0,107, 0,109, 0,108, 0,110, 0,160,
+ 0,111, 0,113, 0,112, 0,114, 0,115, 0,117, 0,116, 0,118, 0,119, 0,234, 0,120, 0,122, 0,121, 0,123, 0,125, 0,124,
+ 0,184, 0,161, 0,127, 0,126, 0,128, 0,129, 0,236, 0,238, 0,186, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 0,253,
+ 0,254, 1, 9, 1, 10, 1, 11, 1, 12, 0,255, 1, 0, 1, 13, 1, 14, 1, 15, 1, 1, 1, 16, 1, 17, 1, 18, 1, 19, 1, 20,
+ 1, 21, 1, 22, 1, 23, 1, 24, 1, 25, 1, 26, 1, 27, 0,248, 0,249, 1, 28, 1, 29, 1, 30, 1, 31, 1, 32, 1, 33, 1, 34,
+ 1, 35, 1, 36, 1, 37, 1, 38, 1, 39, 1, 40, 1, 41, 1, 42, 1, 43, 0,250, 0,215, 1, 44, 1, 45, 1, 46, 1, 47, 1, 48,
+ 1, 49, 1, 50, 1, 51, 1, 52, 1, 53, 1, 54, 1, 55, 1, 56, 1, 57, 1, 58, 0,226, 0,227, 1, 59, 1, 60, 1, 61, 1, 62,
+ 1, 63, 1, 64, 1, 65, 1, 66, 1, 67, 1, 68, 1, 69, 1, 70, 1, 71, 1, 72, 1, 73, 0,176, 0,177, 1, 74, 1, 75, 1, 76,
+ 1, 77, 1, 78, 1, 79, 1, 80, 1, 81, 1, 82, 1, 83, 0,251, 0,252, 0,228, 0,229, 1, 84, 1, 85, 1, 86, 1, 87, 1, 88,
+ 1, 89, 1, 90, 1, 91, 1, 92, 1, 93, 1, 94, 1, 95, 1, 96, 1, 97, 1, 98, 1, 99, 1,100, 1,101, 1,102, 1,103, 1,104,
+ 1,105, 0,187, 1,106, 1,107, 1,108, 1,109, 0,230, 0,231, 1,110, 1,111, 1,112, 1,113, 1,114, 1,115, 1,116, 1,117,
+ 1,118, 1,119, 1,120, 1,121, 1,122, 1,123, 1,124, 1,125, 1,126, 1,127, 1,128, 0,166, 1,129, 1,130, 1,131, 1,132,
+ 1,133, 1,134, 1,135, 1,136, 1,137, 1,138, 1,139, 1,140, 1,141, 1,142, 1,143, 1,144, 1,145, 1,146, 1,147, 1,148,
+ 1,149, 1,150, 1,151, 1,152, 1,153, 1,154, 1,155, 1,156, 1,157, 1,158, 1,159, 1,160, 1,161, 1,162, 1,163, 1,164,
+ 1,165, 1,166, 1,167, 1,168, 1,169, 1,170, 1,171, 1,172, 1,173, 1,174, 1,175, 1,176, 1,177, 1,178, 1,179, 1,180,
+ 1,181, 1,182, 1,183, 1,184, 1,185, 1,186, 1,187, 1,188, 1,189, 1,190, 1,191, 1,192, 1,193, 1,194, 1,195, 1,196,
+ 1,197, 1,198, 1,199, 1,200, 1,201, 1,202, 1,203, 1,204, 1,205, 1,206, 1,207, 1,208, 1,209, 1,210, 1,211, 1,212,
+ 1,213, 1,214, 1,215, 1,216, 1,217, 1,218, 1,219, 1,220, 1,221, 1,222, 1,223, 1,224, 1,225, 1,226, 1,227, 1,228,
+ 1,229, 1,230, 1,231, 1,232, 1,233, 1,234, 1,235, 1,236, 1,237, 1,238, 1,239, 1,240, 1,241, 1,242, 1,243, 1,244,
+ 1,245, 1,246, 1,247, 1,248, 1,249, 1,250, 1,251, 1,252, 1,253, 1,254, 1,255, 2, 0, 2, 1, 2, 2, 2, 3, 2, 4,
+ 2, 5, 2, 6, 2, 7, 2, 8, 2, 9, 2, 10, 2, 11, 2, 12, 2, 13, 2, 14, 2, 15, 2, 16, 2, 17, 2, 18, 2, 19, 2, 20,
+ 2, 21, 2, 22, 2, 23, 2, 24, 2, 25, 2, 26, 2, 27, 2, 28, 2, 29, 2, 30, 2, 31, 2, 32, 2, 33, 2, 34, 2, 35, 2, 36,
+ 2, 37, 2, 38, 2, 39, 2, 40, 2, 41, 2, 42, 2, 43, 2, 44, 2, 45, 2, 46, 2, 47, 2, 48, 2, 49, 2, 50, 2, 51, 2, 52,
+ 2, 53, 2, 54, 2, 55, 2, 56, 2, 57, 2, 58, 2, 59, 2, 60, 2, 61, 2, 62, 2, 63, 2, 64, 2, 65, 2, 66, 2, 67, 2, 68,
+ 2, 69, 2, 70, 2, 71, 2, 72, 2, 73, 2, 74, 0,216, 0,225, 2, 75, 2, 76, 2, 77, 2, 78, 2, 79, 2, 80, 2, 81, 2, 82,
+ 2, 83, 2, 84, 2, 85, 2, 86, 2, 87, 2, 88, 2, 89, 2, 90, 0,219, 0,220, 0,221, 0,224, 0,217, 0,223, 2, 91, 2, 92,
+ 2, 93, 2, 94, 2, 95, 2, 96, 2, 97, 2, 98, 2, 99, 2,100, 2,101, 2,102, 2,103, 2,104, 2,105, 2,106, 2,107, 2,108,
+ 2,109, 2,110, 2,111, 2,112, 2,113, 2,114, 2,115, 2,116, 2,117, 2,118, 2,119, 2,120, 2,121, 2,122, 2,123, 2,124,
+ 2,125, 2,126, 2,127, 2,128, 2,129, 2,130, 2,131, 2,132, 2,133, 2,134, 2,135, 2,136, 2,137, 2,138, 2,139, 2,140,
+ 2,141, 2,142, 2,143, 2,144, 2,145, 2,146, 2,147, 2,148, 2,149, 2,150, 2,151, 2,152, 2,153, 2,154, 2,155, 2,156,
+ 2,157, 2,158, 2,159, 2,160, 2,161, 2,162, 2,163, 2,164, 2,165, 2,166, 2,167, 2,168, 2,169, 2,170, 2,171, 2,172,
+ 2,173, 2,174, 2,175, 2,176, 2,177, 2,178, 2,179, 2,180, 2,181, 2,182, 2,183, 2,184, 2,185, 2,186, 2,187, 2,188,
+ 2,189, 2,190, 2,191, 2,192, 2,193, 2,194, 2,195, 2,196, 2,197, 2,198, 2,199, 2,200, 2,201, 2,202, 2,203, 2,204,
+ 2,205, 2,206, 2,207, 2,208, 2,209, 2,210, 2,211, 2,212, 2,213, 2,214, 2,215, 2,216, 2,217, 2,218, 2,219, 2,220,
+ 2,221, 2,222, 2,223, 2,224, 2,225, 2,226, 2,227, 2,228, 2,229, 2,230, 2,231, 2,232, 2,233, 2,234, 0,159, 2,235,
+ 2,236, 2,237, 2,238, 2,239, 2,240, 2,241, 2,242, 2,243, 2,244, 2,245, 2,246, 2,247, 2,248, 2,249, 2,250, 2,251,
+ 2,252, 2,253, 2,254, 2,255, 3, 0, 0,155, 3, 1, 3, 2, 3, 3, 3, 4, 3, 5, 3, 6, 3, 7, 3, 8, 3, 9, 3, 10,
+ 3, 11, 3, 12, 3, 13, 3, 14, 3, 15, 3, 16, 3, 17, 3, 18, 3, 19, 3, 20, 3, 21, 3, 22, 3, 23, 3, 24, 3, 25, 3, 26,
+ 3, 27, 3, 28, 3, 29, 3, 30, 3, 31, 3, 32, 3, 33, 3, 34, 3, 35, 3, 36, 3, 37, 3, 38, 3, 39, 3, 40, 3, 41, 3, 42,
+ 3, 43, 3, 44, 3, 45, 3, 46, 3, 47, 3, 48, 3, 49, 3, 50, 3, 51, 3, 52, 3, 53, 3, 54, 3, 55, 3, 56, 3, 57, 3, 58,
+ 3, 59, 3, 60, 3, 61, 3, 62, 3, 63, 3, 64, 3, 65, 3, 66, 3, 67, 3, 68, 3, 69, 3, 70, 3, 71, 3, 72, 3, 73, 3, 74,
+ 3, 75, 3, 76, 3, 77, 3, 78, 3, 79, 3, 80, 3, 81, 3, 82, 3, 83, 3, 84, 3, 85, 3, 86, 3, 87, 3, 88, 3, 89, 3, 90,
+ 3, 91, 3, 92, 3, 93, 3, 94, 3, 95, 3, 96, 3, 97, 3, 98, 3, 99, 3,100, 3,101, 3,102, 3,103, 3,104, 3,105, 3,106,
+ 3,107, 3,108, 3,109, 3,110, 3,111, 3,112, 3,113, 3,114, 3,115, 3,116, 3,117, 3,118, 3,119, 3,120, 3,121, 3,122,
+ 3,123, 3,124, 3,125, 3,126, 3,127, 3,128, 3,129, 3,130, 3,131, 3,132, 3,133, 3,134, 3,135, 3,136, 3,137, 3,138,
+ 3,139, 3,140, 3,141, 3,142, 3,143, 3,144, 3,145, 3,146, 3,147, 3,148, 3,149, 3,150, 3,151, 3,152, 3,153, 3,154,
+ 3,155, 3,156, 3,157, 3,158, 3,159, 3,160, 3,161, 3,162, 3,163, 3,164, 3,165, 3,166, 3,167, 3,168, 3,169, 3,170,
+ 3,171, 3,172, 3,173, 3,174, 3,175, 3,176, 3,177, 3,178, 3,179, 3,180, 3,181, 3,182, 3,183, 3,184, 3,185, 3,186,
+ 3,187, 3,188, 3,189, 3,190, 3,191, 3,192, 3,193, 3,194, 3,195, 3,196, 3,197, 3,198, 3,199, 3,200, 3,201, 3,202,
+ 3,203, 3,204, 3,205, 3,206, 3,207, 3,208, 3,209, 3,210, 3,211, 3,212, 3,213, 3,214, 3,215, 3,216, 3,217, 3,218,
+ 3,219, 3,220, 3,221, 3,222, 3,223, 3,224, 3,225, 3,226, 3,227, 3,228, 3,229, 3,230, 3,231, 3,232, 3,233, 3,234,
+ 3,235, 3,236, 3,237, 3,238, 3,239, 3,240, 3,241, 3,242, 3,243, 3,244, 3,245, 3,246, 3,247, 3,248, 3,249, 3,250,
+ 3,251, 3,252, 3,253, 3,254, 3,255, 4, 0, 4, 1, 4, 2, 4, 3, 4, 4, 4, 5, 4, 6, 4, 7, 4, 8, 4, 9, 4, 10,
+ 4, 11, 4, 12, 4, 13, 4, 14, 4, 15, 4, 16, 4, 17, 4, 18, 4, 19, 4, 20, 4, 21, 4, 22, 4, 23, 4, 24, 4, 25, 4, 26,
+ 4, 27, 4, 28, 4, 29, 4, 30, 4, 31, 4, 32, 4, 33, 4, 34, 4, 35, 4, 36, 4, 37, 4, 38, 4, 39, 4, 40, 4, 41, 4, 42,
+ 4, 43, 4, 44, 4, 45, 4, 46, 4, 47, 4, 48, 4, 49, 4, 50, 4, 51, 4, 52, 4, 53, 4, 54, 4, 55, 4, 56, 4, 57, 4, 58,
+ 4, 59, 4, 60, 4, 61, 4, 62, 4, 63, 4, 64, 4, 65, 4, 66, 4, 67, 4, 68, 4, 69, 4, 70, 4, 71, 4, 72, 4, 73, 4, 74,
+ 4, 75, 4, 76, 4, 77, 4, 78, 4, 79, 4, 80, 4, 81, 4, 82, 4, 83, 4, 84, 4, 85, 4, 86, 4, 87, 4, 88, 4, 89, 4, 90,
+ 4, 91, 4, 92, 4, 93, 4, 94, 4, 95, 4, 96, 4, 97, 4, 98, 4, 99, 4,100, 4,101, 4,102, 4,103, 4,104, 4,105, 4,106,
+ 4,107, 4,108, 4,109, 4,110, 4,111, 4,112, 4,113, 4,114, 4,115, 4,116, 4,117, 4,118, 4,119, 4,120, 4,121, 4,122,
+ 4,123, 4,124, 4,125, 4,126, 4,127, 4,128, 4,129, 4,130, 4,131, 4,132, 4,133, 4,134, 4,135, 4,136, 4,137, 4,138,
+ 4,139, 4,140, 4,141, 4,142, 4,143, 4,144, 4,145, 4,146, 4,147, 4,148, 4,149, 4,150, 4,151, 4,152, 4,153, 4,154,
+ 4,155, 4,156, 4,157, 4,158, 4,159, 4,160, 4,161, 4,162, 4,163, 4,164, 4,165, 4,166, 4,167, 4,168, 4,169, 4,170,
+ 4,171, 4,172, 4,173, 4,174, 4,175, 4,176, 4,177, 4,178, 4,179, 4,180, 4,181, 4,182, 4,183, 4,184, 4,185, 4,186,
+ 4,187, 4,188, 4,189, 4,190, 4,191, 4,192, 4,193, 4,194, 4,195, 4,196, 4,197, 4,198, 4,199, 4,200, 4,201, 4,202,
+ 4,203, 4,204, 4,205, 4,206, 4,207, 4,208, 4,209, 4,210, 4,211, 4,212, 4,213, 4,214, 4,215, 4,216, 4,217, 4,218,
+ 4,219, 4,220, 4,221, 4,222, 4,223, 4,224, 4,225, 4,226, 4,227, 4,228, 4,229, 4,230, 4,231, 4,232, 4,233, 4,234,
+ 4,235, 4,236, 4,237, 4,238, 4,239, 4,240, 4,241, 4,242, 4,243, 4,244, 4,245, 4,246, 4,247, 4,248, 4,249, 4,250,
+ 4,251, 4,252, 4,253, 4,254, 4,255, 5, 0, 5, 1, 5, 2, 5, 3, 5, 4, 5, 5, 5, 6, 5, 7, 5, 8, 5, 9, 5, 10,
+ 5, 11, 5, 12, 5, 13, 5, 14, 5, 15, 5, 16, 5, 17, 5, 18, 5, 19, 5, 20, 5, 21, 5, 22, 5, 23, 5, 24, 5, 25, 5, 26,
+ 5, 27, 5, 28, 5, 29, 5, 30, 5, 31, 5, 32, 5, 33, 5, 34, 5, 35, 5, 36, 5, 37, 5, 38, 5, 39, 5, 40, 5, 41, 5, 42,
+ 5, 43, 5, 44, 5, 45, 5, 46, 5, 47, 5, 48, 5, 49, 5, 50, 5, 51, 5, 52, 5, 53, 5, 54, 5, 55, 5, 56, 5, 57, 5, 58,
+ 5, 59, 5, 60, 5, 61, 5, 62, 5, 63, 5, 64, 5, 65, 5, 66, 5, 67, 5, 68, 5, 69, 5, 70, 5, 71, 5, 72, 5, 73, 5, 74,
+ 5, 75, 5, 76, 5, 77, 5, 78, 5, 79, 5, 80, 5, 81, 5, 82, 5, 83, 5, 84, 5, 85, 5, 86, 5, 87, 5, 88, 5, 89, 5, 90,
+ 5, 91, 5, 92, 5, 93, 5, 94, 5, 95, 5, 96, 5, 97, 5, 98, 5, 99, 5,100, 5,101, 5,102, 5,103, 5,104, 5,105, 5,106,
+ 5,107, 5,108, 5,109, 5,110, 5,111, 5,112, 5,113, 5,114, 5,115, 5,116, 5,117, 5,118, 5,119, 5,120, 5,121, 5,122,
+ 5,123, 5,124, 5,125, 5,126, 5,127, 5,128, 5,129, 5,130, 5,131, 5,132, 5,133, 5,134, 5,135, 5,136, 5,137, 5,138,
+ 5,139, 5,140, 5,141, 5,142, 5,143, 5,144, 5,145, 5,146, 5,147, 5,148, 5,149, 5,150, 5,151, 5,152, 5,153, 5,154,
+ 5,155, 5,156, 5,157, 5,158, 5,159, 5,160, 5,161, 5,162, 5,163, 5,164, 5,165, 5,166, 5,167, 5,168, 5,169, 0,178,
+ 0,179, 5,170, 5,171, 5,172, 0,182, 0,183, 0,196, 5,173, 0,180, 0,181, 0,197, 5,174, 0,130, 0,194, 0,135, 5,175,
+ 5,176, 5,177, 0,171, 5,178, 0,198, 5,179, 5,180, 5,181, 5,182, 5,183, 5,184, 5,185, 5,186, 0,190, 0,191, 5,187,
+ 5,188, 5,189, 5,190, 5,191, 5,192, 5,193, 5,194, 5,195, 0,188, 5,196, 5,197, 5,198, 5,199, 5,200, 5,201, 5,202,
+ 5,203, 5,204, 5,205, 5,206, 5,207, 5,208, 5,209, 5,210, 5,211, 5,212, 5,213, 5,214, 5,215, 5,216, 5,217, 5,218,
+ 5,219, 5,220, 5,221, 5,222, 5,223, 5,224, 5,225, 5,226, 5,227, 5,228, 5,229, 5,230, 5,231, 5,232, 5,233, 5,234,
+ 5,235, 5,236, 5,237, 5,238, 5,239, 5,240, 5,241, 5,242, 5,243, 5,244, 5,245, 5,246, 5,247, 5,248, 5,249, 5,250,
+ 5,251, 5,252, 5,253, 0,247, 5,254, 5,255, 6, 0, 6, 1, 6, 2, 6, 3, 6, 4, 6, 5, 6, 6, 6, 7, 6, 8, 6, 9,
+ 6, 10, 6, 11, 6, 12, 6, 13, 6, 14, 6, 15, 6, 16, 6, 17, 6, 18, 6, 19, 6, 20, 6, 21, 6, 22, 6, 23, 6, 24, 6, 25,
+ 6, 26, 6, 27, 6, 28, 6, 29, 6, 30, 6, 31, 6, 32, 0,140, 6, 33, 6, 34, 6, 35, 6, 36, 6, 37, 6, 38, 6, 39, 6, 40,
+ 6, 41, 6, 42, 6, 43, 6, 44, 6, 45, 6, 46, 6, 47, 6, 48, 6, 49, 6, 50, 6, 51, 6, 52, 6, 53, 6, 54, 6, 55, 6, 56,
+ 6, 57, 6, 58, 6, 59, 6, 60, 6, 61, 6, 62, 6, 63, 6, 64, 6, 65, 6, 66, 6, 67, 6, 68, 6, 69, 6, 70, 6, 71, 6, 72,
+ 6, 73, 6, 74, 6, 75, 6, 76, 6, 77, 6, 78, 6, 79, 6, 80, 6, 81, 6, 82, 6, 83, 6, 84, 6, 85, 6, 86, 6, 87, 6, 88,
+ 6, 89, 6, 90, 6, 91, 6, 92, 6, 93, 6, 94, 6, 95, 6, 96, 6, 97, 6, 98, 6, 99, 6,100, 6,101, 6,102, 0,239, 6,103,
+ 6,104, 0,188, 6,105, 6,106, 6,107, 0,195, 0,165, 6,108, 6,109, 6,110, 0,146, 6,111, 6,112, 6,113, 6,114, 6,115,
+ 6,116, 6,117, 6,118, 6,119, 6,120, 6,121, 6,122, 6,123, 6,124, 6,125, 6,126, 6,127, 6,128, 6,129, 0,192, 0,193,
+ 6,130, 6,131, 6,132, 6,133, 6,134, 6,135, 6,136, 6,137, 6,138, 6,139, 6,140, 6,141, 6,142, 6,143, 6,144, 6,145,
+ 6,146, 6,147, 6,148, 6,149, 6,150, 6,151, 6,152, 6,153, 6,154, 6,155, 6,156, 6,157, 6,158, 6,159, 6,160, 6,161,
+ 6,162, 6,163, 6,164, 6,165, 6,166, 6,167, 6,168, 6,169, 6,170, 6,171, 9,115,102,116,104,121,112,104,101,110, 7, 65,
+109, 97, 99,114,111,110, 7, 97,109, 97, 99,114,111,110, 6, 65, 98,114,101,118,101, 6, 97, 98,114,101,118,101, 7, 65,111,103,
+111,110,101,107, 7, 97,111,103,111,110,101,107, 11, 67, 99,105,114, 99,117,109,102,108,101,120, 11, 99, 99,105,114, 99,117,109,
+102,108,101,120, 10, 67,100,111,116, 97, 99, 99,101,110,116, 10, 99,100,111,116, 97, 99, 99,101,110,116, 6, 68, 99, 97,114,111,
+110, 6,100, 99, 97,114,111,110, 6, 68, 99,114,111, 97,116, 7, 69,109, 97, 99,114,111,110, 7,101,109, 97, 99,114,111,110, 6,
+ 69, 98,114,101,118,101, 6,101, 98,114,101,118,101, 10, 69,100,111,116, 97, 99, 99,101,110,116, 10,101,100,111,116, 97, 99, 99,
+101,110,116, 7, 69,111,103,111,110,101,107, 7,101,111,103,111,110,101,107, 6, 69, 99, 97,114,111,110, 6,101, 99, 97,114,111,
+110, 11, 71, 99,105,114, 99,117,109,102,108,101,120, 11,103, 99,105,114, 99,117,109,102,108,101,120, 10, 71,100,111,116, 97, 99,
+ 99,101,110,116, 10,103,100,111,116, 97, 99, 99,101,110,116, 12, 71, 99,111,109,109, 97, 97, 99, 99,101,110,116, 12,103, 99,111,
+109,109, 97, 97, 99, 99,101,110,116, 11, 72, 99,105,114, 99,117,109,102,108,101,120, 11,104, 99,105,114, 99,117,109,102,108,101,
+120, 4, 72, 98, 97,114, 4,104, 98, 97,114, 6, 73,116,105,108,100,101, 6,105,116,105,108,100,101, 7, 73,109, 97, 99,114,111,
+110, 7,105,109, 97, 99,114,111,110, 6, 73, 98,114,101,118,101, 6,105, 98,114,101,118,101, 7, 73,111,103,111,110,101,107, 7,
+105,111,103,111,110,101,107, 2, 73, 74, 2,105,106, 11, 74, 99,105,114, 99,117,109,102,108,101,120, 11,106, 99,105,114, 99,117,
+109,102,108,101,120, 12, 75, 99,111,109,109, 97, 97, 99, 99,101,110,116, 12,107, 99,111,109,109, 97, 97, 99, 99,101,110,116, 12,
+107,103,114,101,101,110,108, 97,110,100,105, 99, 6, 76, 97, 99,117,116,101, 6,108, 97, 99,117,116,101, 12, 76, 99,111,109,109,
+ 97, 97, 99, 99,101,110,116, 12,108, 99,111,109,109, 97, 97, 99, 99,101,110,116, 6, 76, 99, 97,114,111,110, 6,108, 99, 97,114,
+111,110, 4, 76,100,111,116, 4,108,100,111,116, 6, 78, 97, 99,117,116,101, 6,110, 97, 99,117,116,101, 12, 78, 99,111,109,109,
+ 97, 97, 99, 99,101,110,116, 12,110, 99,111,109,109, 97, 97, 99, 99,101,110,116, 6, 78, 99, 97,114,111,110, 6,110, 99, 97,114,
+111,110, 11,110, 97,112,111,115,116,114,111,112,104,101, 3, 69,110,103, 3,101,110,103, 7, 79,109, 97, 99,114,111,110, 7,111,
+109, 97, 99,114,111,110, 6, 79, 98,114,101,118,101, 6,111, 98,114,101,118,101, 13, 79,104,117,110,103, 97,114,117,109,108, 97,
+117,116, 13,111,104,117,110,103, 97,114,117,109,108, 97,117,116, 6, 82, 97, 99,117,116,101, 6,114, 97, 99,117,116,101, 12, 82,
+ 99,111,109,109, 97, 97, 99, 99,101,110,116, 12,114, 99,111,109,109, 97, 97, 99, 99,101,110,116, 6, 82, 99, 97,114,111,110, 6,
+114, 99, 97,114,111,110, 6, 83, 97, 99,117,116,101, 6,115, 97, 99,117,116,101, 11, 83, 99,105,114, 99,117,109,102,108,101,120,
+ 11,115, 99,105,114, 99,117,109,102,108,101,120, 12, 84, 99,111,109,109, 97, 97, 99, 99,101,110,116, 12,116, 99,111,109,109, 97,
+ 97, 99, 99,101,110,116, 6, 84, 99, 97,114,111,110, 6,116, 99, 97,114,111,110, 4, 84, 98, 97,114, 4,116, 98, 97,114, 6, 85,
+116,105,108,100,101, 6,117,116,105,108,100,101, 7, 85,109, 97, 99,114,111,110, 7,117,109, 97, 99,114,111,110, 6, 85, 98,114,
+101,118,101, 6,117, 98,114,101,118,101, 5, 85,114,105,110,103, 5,117,114,105,110,103, 13, 85,104,117,110,103, 97,114,117,109,
+108, 97,117,116, 13,117,104,117,110,103, 97,114,117,109,108, 97,117,116, 7, 85,111,103,111,110,101,107, 7,117,111,103,111,110,
+101,107, 11, 87, 99,105,114, 99,117,109,102,108,101,120, 11,119, 99,105,114, 99,117,109,102,108,101,120, 11, 89, 99,105,114, 99,
+117,109,102,108,101,120, 11,121, 99,105,114, 99,117,109,102,108,101,120, 6, 90, 97, 99,117,116,101, 6,122, 97, 99,117,116,101,
+ 10, 90,100,111,116, 97, 99, 99,101,110,116, 10,122,100,111,116, 97, 99, 99,101,110,116, 5,108,111,110,103,115, 7,117,110,105,
+ 48, 49, 56, 48, 7,117,110,105, 48, 49, 56, 49, 7,117,110,105, 48, 49, 56, 50, 7,117,110,105, 48, 49, 56, 51, 7,117,110,105,
+ 48, 49, 56, 52, 7,117,110,105, 48, 49, 56, 53, 7,117,110,105, 48, 49, 56, 54, 7,117,110,105, 48, 49, 56, 55, 7,117,110,105,
+ 48, 49, 56, 56, 7,117,110,105, 48, 49, 56, 57, 7,117,110,105, 48, 49, 56, 65, 7,117,110,105, 48, 49, 56, 66, 7,117,110,105,
+ 48, 49, 56, 67, 7,117,110,105, 48, 49, 56, 68, 7,117,110,105, 48, 49, 56, 69, 7,117,110,105, 48, 49, 56, 70, 7,117,110,105,
+ 48, 49, 57, 48, 7,117,110,105, 48, 49, 57, 49, 7,117,110,105, 48, 49, 57, 51, 7,117,110,105, 48, 49, 57, 52, 7,117,110,105,
+ 48, 49, 57, 53, 7,117,110,105, 48, 49, 57, 54, 7,117,110,105, 48, 49, 57, 55, 7,117,110,105, 48, 49, 57, 56, 7,117,110,105,
+ 48, 49, 57, 57, 7,117,110,105, 48, 49, 57, 65, 7,117,110,105, 48, 49, 57, 66, 7,117,110,105, 48, 49, 57, 67, 7,117,110,105,
+ 48, 49, 57, 68, 7,117,110,105, 48, 49, 57, 69, 7,117,110,105, 48, 49, 57, 70, 5, 79,104,111,114,110, 5,111,104,111,114,110,
+ 7,117,110,105, 48, 49, 65, 50, 7,117,110,105, 48, 49, 65, 51, 7,117,110,105, 48, 49, 65, 52, 7,117,110,105, 48, 49, 65, 53,
+ 7,117,110,105, 48, 49, 65, 54, 7,117,110,105, 48, 49, 65, 55, 7,117,110,105, 48, 49, 65, 56, 7,117,110,105, 48, 49, 65, 57,
+ 7,117,110,105, 48, 49, 65, 65, 7,117,110,105, 48, 49, 65, 66, 7,117,110,105, 48, 49, 65, 67, 7,117,110,105, 48, 49, 65, 68,
+ 7,117,110,105, 48, 49, 65, 69, 5, 85,104,111,114,110, 5,117,104,111,114,110, 7,117,110,105, 48, 49, 66, 49, 7,117,110,105,
+ 48, 49, 66, 50, 7,117,110,105, 48, 49, 66, 51, 7,117,110,105, 48, 49, 66, 52, 7,117,110,105, 48, 49, 66, 53, 7,117,110,105,
+ 48, 49, 66, 54, 7,117,110,105, 48, 49, 66, 55, 7,117,110,105, 48, 49, 66, 56, 7,117,110,105, 48, 49, 66, 57, 7,117,110,105,
+ 48, 49, 66, 65, 7,117,110,105, 48, 49, 66, 66, 7,117,110,105, 48, 49, 66, 67, 7,117,110,105, 48, 49, 66, 68, 7,117,110,105,
+ 48, 49, 66, 69, 7,117,110,105, 48, 49, 66, 70, 7,117,110,105, 48, 49, 67, 48, 7,117,110,105, 48, 49, 67, 49, 7,117,110,105,
+ 48, 49, 67, 50, 7,117,110,105, 48, 49, 67, 51, 7,117,110,105, 48, 49, 67, 52, 7,117,110,105, 48, 49, 67, 53, 7,117,110,105,
+ 48, 49, 67, 54, 7,117,110,105, 48, 49, 67, 55, 7,117,110,105, 48, 49, 67, 56, 7,117,110,105, 48, 49, 67, 57, 7,117,110,105,
+ 48, 49, 67, 65, 7,117,110,105, 48, 49, 67, 66, 7,117,110,105, 48, 49, 67, 67, 7,117,110,105, 48, 49, 67, 68, 7,117,110,105,
+ 48, 49, 67, 69, 7,117,110,105, 48, 49, 67, 70, 7,117,110,105, 48, 49, 68, 48, 7,117,110,105, 48, 49, 68, 49, 7,117,110,105,
+ 48, 49, 68, 50, 7,117,110,105, 48, 49, 68, 51, 7,117,110,105, 48, 49, 68, 52, 7,117,110,105, 48, 49, 68, 53, 7,117,110,105,
+ 48, 49, 68, 54, 7,117,110,105, 48, 49, 68, 55, 7,117,110,105, 48, 49, 68, 56, 7,117,110,105, 48, 49, 68, 57, 7,117,110,105,
+ 48, 49, 68, 65, 7,117,110,105, 48, 49, 68, 66, 7,117,110,105, 48, 49, 68, 67, 7,117,110,105, 48, 49, 68, 68, 7,117,110,105,
+ 48, 49, 68, 69, 7,117,110,105, 48, 49, 68, 70, 7,117,110,105, 48, 49, 69, 48, 7,117,110,105, 48, 49, 69, 49, 7,117,110,105,
+ 48, 49, 69, 50, 7,117,110,105, 48, 49, 69, 51, 7,117,110,105, 48, 49, 69, 52, 7,117,110,105, 48, 49, 69, 53, 6, 71, 99, 97,
+114,111,110, 6,103, 99, 97,114,111,110, 7,117,110,105, 48, 49, 69, 56, 7,117,110,105, 48, 49, 69, 57, 7,117,110,105, 48, 49,
+ 69, 65, 7,117,110,105, 48, 49, 69, 66, 7,117,110,105, 48, 49, 69, 67, 7,117,110,105, 48, 49, 69, 68, 7,117,110,105, 48, 49,
+ 69, 69, 7,117,110,105, 48, 49, 69, 70, 7,117,110,105, 48, 49, 70, 48, 7,117,110,105, 48, 49, 70, 49, 7,117,110,105, 48, 49,
+ 70, 50, 7,117,110,105, 48, 49, 70, 51, 7,117,110,105, 48, 49, 70, 52, 7,117,110,105, 48, 49, 70, 53, 7,117,110,105, 48, 49,
+ 70, 54, 7,117,110,105, 48, 49, 70, 55, 7,117,110,105, 48, 49, 70, 56, 7,117,110,105, 48, 49, 70, 57, 10, 65,114,105,110,103,
+ 97, 99,117,116,101, 10, 97,114,105,110,103, 97, 99,117,116,101, 7, 65, 69, 97, 99,117,116,101, 7, 97,101, 97, 99,117,116,101,
+ 11, 79,115,108, 97,115,104, 97, 99,117,116,101, 11,111,115,108, 97,115,104, 97, 99,117,116,101, 7,117,110,105, 48, 50, 48, 48,
+ 7,117,110,105, 48, 50, 48, 49, 7,117,110,105, 48, 50, 48, 50, 7,117,110,105, 48, 50, 48, 51, 7,117,110,105, 48, 50, 48, 52,
+ 7,117,110,105, 48, 50, 48, 53, 7,117,110,105, 48, 50, 48, 54, 7,117,110,105, 48, 50, 48, 55, 7,117,110,105, 48, 50, 48, 56,
+ 7,117,110,105, 48, 50, 48, 57, 7,117,110,105, 48, 50, 48, 65, 7,117,110,105, 48, 50, 48, 66, 7,117,110,105, 48, 50, 48, 67,
+ 7,117,110,105, 48, 50, 48, 68, 7,117,110,105, 48, 50, 48, 69, 7,117,110,105, 48, 50, 48, 70, 7,117,110,105, 48, 50, 49, 48,
+ 7,117,110,105, 48, 50, 49, 49, 7,117,110,105, 48, 50, 49, 50, 7,117,110,105, 48, 50, 49, 51, 7,117,110,105, 48, 50, 49, 52,
+ 7,117,110,105, 48, 50, 49, 53, 7,117,110,105, 48, 50, 49, 54, 7,117,110,105, 48, 50, 49, 55, 12, 83, 99,111,109,109, 97, 97,
+ 99, 99,101,110,116, 12,115, 99,111,109,109, 97, 97, 99, 99,101,110,116, 7,117,110,105, 48, 50, 49, 65, 7,117,110,105, 48, 50,
+ 49, 66, 7,117,110,105, 48, 50, 49, 67, 7,117,110,105, 48, 50, 49, 68, 7,117,110,105, 48, 50, 49, 69, 7,117,110,105, 48, 50,
+ 49, 70, 7,117,110,105, 48, 50, 50, 48, 7,117,110,105, 48, 50, 50, 49, 7,117,110,105, 48, 50, 50, 50, 7,117,110,105, 48, 50,
+ 50, 51, 7,117,110,105, 48, 50, 50, 52, 7,117,110,105, 48, 50, 50, 53, 7,117,110,105, 48, 50, 50, 54, 7,117,110,105, 48, 50,
+ 50, 55, 7,117,110,105, 48, 50, 50, 56, 7,117,110,105, 48, 50, 50, 57, 7,117,110,105, 48, 50, 50, 65, 7,117,110,105, 48, 50,
+ 50, 66, 7,117,110,105, 48, 50, 50, 67, 7,117,110,105, 48, 50, 50, 68, 7,117,110,105, 48, 50, 50, 69, 7,117,110,105, 48, 50,
+ 50, 70, 7,117,110,105, 48, 50, 51, 48, 7,117,110,105, 48, 50, 51, 49, 7,117,110,105, 48, 50, 51, 50, 7,117,110,105, 48, 50,
+ 51, 51, 7,117,110,105, 48, 50, 51, 52, 7,117,110,105, 48, 50, 51, 53, 7,117,110,105, 48, 50, 51, 54, 8,100,111,116,108,101,
+115,115,106, 7,117,110,105, 48, 50, 51, 56, 7,117,110,105, 48, 50, 51, 57, 7,117,110,105, 48, 50, 51, 65, 7,117,110,105, 48,
+ 50, 51, 66, 7,117,110,105, 48, 50, 51, 67, 7,117,110,105, 48, 50, 51, 68, 7,117,110,105, 48, 50, 51, 69, 7,117,110,105, 48,
+ 50, 51, 70, 7,117,110,105, 48, 50, 52, 48, 7,117,110,105, 48, 50, 52, 49, 7,117,110,105, 48, 50, 53, 57, 7,117,110,105, 48,
+ 50, 54, 50, 7,117,110,105, 48, 50, 55, 48, 7,117,110,105, 48, 50, 55, 53, 7,117,110,105, 48, 50, 57, 50, 7,117,110,105, 48,
+ 50, 66, 48, 7,117,110,105, 48, 50, 66, 49, 7,117,110,105, 48, 50, 66, 50, 7,117,110,105, 48, 50, 66, 51, 7,117,110,105, 48,
+ 50, 66, 52, 7,117,110,105, 48, 50, 66, 53, 7,117,110,105, 48, 50, 66, 54, 7,117,110,105, 48, 50, 66, 55, 7,117,110,105, 48,
+ 50, 66, 56, 7,117,110,105, 48, 50, 66, 57, 7,117,110,105, 48, 50, 66, 65, 7,117,110,105, 48, 50, 66, 66, 9, 97,102,105,105,
+ 53, 55, 57, 50, 57, 9, 97,102,105,105, 54, 52, 57, 51, 55, 7,117,110,105, 48, 50, 66, 69, 7,117,110,105, 48, 50, 66, 70, 7,
+117,110,105, 48, 50, 67, 48, 7,117,110,105, 48, 50, 67, 49, 7,117,110,105, 48, 50, 67, 50, 7,117,110,105, 48, 50, 67, 51, 7,
+117,110,105, 48, 50, 67, 52, 7,117,110,105, 48, 50, 67, 53, 7,117,110,105, 48, 50, 67, 56, 7,117,110,105, 48, 50, 67, 57, 7,
+117,110,105, 48, 50, 67, 65, 7,117,110,105, 48, 50, 67, 66, 7,117,110,105, 48, 50, 67, 67, 7,117,110,105, 48, 50, 67, 68, 7,
+117,110,105, 48, 50, 67, 69, 7,117,110,105, 48, 50, 67, 70, 7,117,110,105, 48, 50, 68, 48, 7,117,110,105, 48, 50, 68, 49, 7,
+117,110,105, 48, 50, 68, 50, 7,117,110,105, 48, 50, 68, 51, 7,117,110,105, 48, 50, 68, 52, 7,117,110,105, 48, 50, 68, 53, 7,
+117,110,105, 48, 50, 68, 54, 7,117,110,105, 48, 50, 68, 55, 7,117,110,105, 48, 50, 68, 69, 7,117,110,105, 48, 50, 68, 70, 7,
+117,110,105, 48, 50, 69, 48, 7,117,110,105, 48, 50, 69, 49, 7,117,110,105, 48, 50, 69, 50, 7,117,110,105, 48, 50, 69, 51, 7,
+117,110,105, 48, 50, 69, 52, 7,117,110,105, 48, 50, 69, 53, 7,117,110,105, 48, 50, 69, 54, 7,117,110,105, 48, 50, 69, 55, 7,
+117,110,105, 48, 50, 69, 56, 7,117,110,105, 48, 50, 69, 57, 7,117,110,105, 48, 50, 69, 67, 7,117,110,105, 48, 50, 69, 68, 7,
+117,110,105, 48, 50, 69, 69, 7,117,110,105, 48, 50, 70, 51, 7,117,110,105, 48, 50, 70, 55, 9,103,114, 97,118,101, 99,111,109,
+ 98, 9, 97, 99,117,116,101, 99,111,109, 98, 7,117,110,105, 48, 51, 48, 50, 9,116,105,108,100,101, 99,111,109, 98, 7,117,110,
+105, 48, 51, 48, 52, 7,117,110,105, 48, 51, 48, 53, 7,117,110,105, 48, 51, 48, 54, 7,117,110,105, 48, 51, 48, 55, 7,117,110,
+105, 48, 51, 48, 56, 13,104,111,111,107, 97, 98,111,118,101, 99,111,109, 98, 7,117,110,105, 48, 51, 48, 65, 7,117,110,105, 48,
+ 51, 48, 66, 7,117,110,105, 48, 51, 48, 67, 7,117,110,105, 48, 51, 48, 68, 7,117,110,105, 48, 51, 48, 69, 7,117,110,105, 48,
+ 51, 48, 70, 7,117,110,105, 48, 51, 49, 48, 7,117,110,105, 48, 51, 49, 49, 7,117,110,105, 48, 51, 49, 50, 7,117,110,105, 48,
+ 51, 49, 51, 7,117,110,105, 48, 51, 49, 52, 7,117,110,105, 48, 51, 49, 53, 7,117,110,105, 48, 51, 49, 54, 7,117,110,105, 48,
+ 51, 49, 55, 7,117,110,105, 48, 51, 49, 56, 7,117,110,105, 48, 51, 49, 57, 7,117,110,105, 48, 51, 49, 65, 7,117,110,105, 48,
+ 51, 49, 66, 7,117,110,105, 48, 51, 49, 67, 7,117,110,105, 48, 51, 49, 68, 7,117,110,105, 48, 51, 49, 69, 7,117,110,105, 48,
+ 51, 49, 70, 7,117,110,105, 48, 51, 50, 48, 7,117,110,105, 48, 51, 50, 49, 7,117,110,105, 48, 51, 50, 50, 12,100,111,116, 98,
+101,108,111,119, 99,111,109, 98, 7,117,110,105, 48, 51, 50, 52, 7,117,110,105, 48, 51, 50, 53, 7,117,110,105, 48, 51, 50, 54,
+ 7,117,110,105, 48, 51, 50, 55, 7,117,110,105, 48, 51, 50, 56, 7,117,110,105, 48, 51, 50, 57, 7,117,110,105, 48, 51, 50, 65,
+ 7,117,110,105, 48, 51, 50, 66, 7,117,110,105, 48, 51, 50, 67, 7,117,110,105, 48, 51, 50, 68, 7,117,110,105, 48, 51, 50, 69,
+ 7,117,110,105, 48, 51, 50, 70, 7,117,110,105, 48, 51, 51, 48, 7,117,110,105, 48, 51, 51, 49, 7,117,110,105, 48, 51, 51, 50,
+ 7,117,110,105, 48, 51, 51, 51, 7,117,110,105, 48, 51, 51, 52, 7,117,110,105, 48, 51, 51, 53, 7,117,110,105, 48, 51, 51, 54,
+ 7,117,110,105, 48, 51, 51, 55, 7,117,110,105, 48, 51, 51, 56, 7,117,110,105, 48, 51, 51, 57, 7,117,110,105, 48, 51, 51, 65,
+ 7,117,110,105, 48, 51, 51, 66, 7,117,110,105, 48, 51, 51, 67, 7,117,110,105, 48, 51, 51, 68, 7,117,110,105, 48, 51, 51, 69,
+ 7,117,110,105, 48, 51, 51, 70, 7,117,110,105, 48, 51, 52, 48, 7,117,110,105, 48, 51, 52, 49, 7,117,110,105, 48, 51, 52, 50,
+ 7,117,110,105, 48, 51, 52, 51, 7,117,110,105, 48, 51, 52, 52, 7,117,110,105, 48, 51, 52, 53, 7,117,110,105, 48, 51, 52, 54,
+ 7,117,110,105, 48, 51, 52, 55, 7,117,110,105, 48, 51, 52, 56, 7,117,110,105, 48, 51, 52, 57, 7,117,110,105, 48, 51, 52, 65,
+ 7,117,110,105, 48, 51, 52, 66, 7,117,110,105, 48, 51, 52, 67, 7,117,110,105, 48, 51, 52, 68, 7,117,110,105, 48, 51, 52, 69,
+ 7,117,110,105, 48, 51, 53, 49, 7,117,110,105, 48, 51, 53, 50, 7,117,110,105, 48, 51, 53, 51, 7,117,110,105, 48, 51, 53, 55,
+ 7,117,110,105, 48, 51, 53, 56, 7,117,110,105, 48, 51, 53, 67, 7,117,110,105, 48, 51, 53, 68, 7,117,110,105, 48, 51, 54, 48,
+ 7,117,110,105, 48, 51, 54, 49, 7,117,110,105, 48, 51, 54, 50, 7,117,110,105, 48, 51, 55, 52, 7,117,110,105, 48, 51, 55, 53,
+ 7,117,110,105, 48, 51, 55, 65, 7,117,110,105, 48, 51, 55, 69, 5,116,111,110,111,115, 13,100,105,101,114,101,115,105,115,116,
+111,110,111,115, 10, 65,108,112,104, 97,116,111,110,111,115, 9, 97,110,111,116,101,108,101,105, 97, 12, 69,112,115,105,108,111,
+110,116,111,110,111,115, 8, 69,116, 97,116,111,110,111,115, 9, 73,111,116, 97,116,111,110,111,115, 12, 79,109,105, 99,114,111,
+110,116,111,110,111,115, 12, 85,112,115,105,108,111,110,116,111,110,111,115, 10, 79,109,101,103, 97,116,111,110,111,115, 17,105,
+111,116, 97,100,105,101,114,101,115,105,115,116,111,110,111,115, 5, 65,108,112,104, 97, 4, 66,101,116, 97, 5, 71, 97,109,109,
+ 97, 7,117,110,105, 48, 51, 57, 52, 7, 69,112,115,105,108,111,110, 4, 90,101,116, 97, 3, 69,116, 97, 5, 84,104,101,116, 97,
+ 4, 73,111,116, 97, 5, 75, 97,112,112, 97, 6, 76, 97,109, 98,100, 97, 2, 77,117, 2, 78,117, 2, 88,105, 7, 79,109,105, 99,
+114,111,110, 2, 80,105, 3, 82,104,111, 5, 83,105,103,109, 97, 3, 84, 97,117, 7, 85,112,115,105,108,111,110, 3, 80,104,105,
+ 3, 67,104,105, 3, 80,115,105, 12, 73,111,116, 97,100,105,101,114,101,115,105,115, 15, 85,112,115,105,108,111,110,100,105,101,
+114,101,115,105,115, 10, 97,108,112,104, 97,116,111,110,111,115, 12,101,112,115,105,108,111,110,116,111,110,111,115, 8,101,116,
+ 97,116,111,110,111,115, 9,105,111,116, 97,116,111,110,111,115, 20,117,112,115,105,108,111,110,100,105,101,114,101,115,105,115,
+116,111,110,111,115, 5, 97,108,112,104, 97, 4, 98,101,116, 97, 5,103, 97,109,109, 97, 5,100,101,108,116, 97, 7,101,112,115,
+105,108,111,110, 4,122,101,116, 97, 3,101,116, 97, 5,116,104,101,116, 97, 4,105,111,116, 97, 5,107, 97,112,112, 97, 6,108,
+ 97,109, 98,100, 97, 7,117,110,105, 48, 51, 66, 67, 2,110,117, 2,120,105, 7,111,109,105, 99,114,111,110, 3,114,104,111, 6,
+115,105,103,109, 97, 49, 5,115,105,103,109, 97, 3,116, 97,117, 7,117,112,115,105,108,111,110, 3,112,104,105, 3, 99,104,105,
+ 3,112,115,105, 5,111,109,101,103, 97, 12,105,111,116, 97,100,105,101,114,101,115,105,115, 15,117,112,115,105,108,111,110,100,
+105,101,114,101,115,105,115, 12,111,109,105, 99,114,111,110,116,111,110,111,115, 12,117,112,115,105,108,111,110,116,111,110,111,
+115, 10,111,109,101,103, 97,116,111,110,111,115, 7,117,110,105, 48, 51, 68, 48, 6,116,104,101,116, 97, 49, 8, 85,112,115,105,
+108,111,110, 49, 7,117,110,105, 48, 51, 68, 51, 7,117,110,105, 48, 51, 68, 52, 4,112,104,105, 49, 6,111,109,101,103, 97, 49,
+ 7,117,110,105, 48, 51, 68, 55, 7,117,110,105, 48, 51, 68, 56, 7,117,110,105, 48, 51, 68, 57, 7,117,110,105, 48, 51, 68, 65,
+ 7,117,110,105, 48, 51, 68, 66, 7,117,110,105, 48, 51, 68, 67, 7,117,110,105, 48, 51, 68, 68, 7,117,110,105, 48, 51, 68, 69,
+ 7,117,110,105, 48, 51, 68, 70, 7,117,110,105, 48, 51, 69, 48, 7,117,110,105, 48, 51, 69, 49, 7,117,110,105, 48, 51, 69, 50,
+ 7,117,110,105, 48, 51, 69, 51, 7,117,110,105, 48, 51, 69, 52, 7,117,110,105, 48, 51, 69, 53, 7,117,110,105, 48, 51, 69, 54,
+ 7,117,110,105, 48, 51, 69, 55, 7,117,110,105, 48, 51, 69, 56, 7,117,110,105, 48, 51, 69, 57, 7,117,110,105, 48, 51, 69, 65,
+ 7,117,110,105, 48, 51, 69, 66, 7,117,110,105, 48, 51, 69, 67, 7,117,110,105, 48, 51, 69, 68, 7,117,110,105, 48, 51, 69, 69,
+ 7,117,110,105, 48, 51, 69, 70, 7,117,110,105, 48, 51, 70, 48, 7,117,110,105, 48, 51, 70, 49, 7,117,110,105, 48, 51, 70, 50,
+ 7,117,110,105, 48, 51, 70, 51, 7,117,110,105, 48, 51, 70, 52, 7,117,110,105, 48, 51, 70, 53, 7,117,110,105, 48, 51, 70, 54,
+ 7,117,110,105, 48, 51, 70, 55, 7,117,110,105, 48, 51, 70, 56, 7,117,110,105, 48, 51, 70, 57, 7,117,110,105, 48, 51, 70, 65,
+ 7,117,110,105, 48, 51, 70, 66, 7,117,110,105, 48, 51, 70, 67, 7,117,110,105, 48, 51, 70, 68, 7,117,110,105, 48, 51, 70, 69,
+ 7,117,110,105, 48, 51, 70, 70, 7,117,110,105, 48, 52, 48, 48, 9, 97,102,105,105, 49, 48, 48, 50, 51, 9, 97,102,105,105, 49,
+ 48, 48, 53, 49, 9, 97,102,105,105, 49, 48, 48, 53, 50, 9, 97,102,105,105, 49, 48, 48, 53, 51, 9, 97,102,105,105, 49, 48, 48,
+ 53, 52, 9, 97,102,105,105, 49, 48, 48, 53, 53, 9, 97,102,105,105, 49, 48, 48, 53, 54, 9, 97,102,105,105, 49, 48, 48, 53, 55,
+ 9, 97,102,105,105, 49, 48, 48, 53, 56, 9, 97,102,105,105, 49, 48, 48, 53, 57, 9, 97,102,105,105, 49, 48, 48, 54, 48, 9, 97,
+102,105,105, 49, 48, 48, 54, 49, 7,117,110,105, 48, 52, 48, 68, 9, 97,102,105,105, 49, 48, 48, 54, 50, 9, 97,102,105,105, 49,
+ 48, 49, 52, 53, 9, 97,102,105,105, 49, 48, 48, 49, 55, 9, 97,102,105,105, 49, 48, 48, 49, 56, 9, 97,102,105,105, 49, 48, 48,
+ 49, 57, 9, 97,102,105,105, 49, 48, 48, 50, 48, 9, 97,102,105,105, 49, 48, 48, 50, 49, 9, 97,102,105,105, 49, 48, 48, 50, 50,
+ 9, 97,102,105,105, 49, 48, 48, 50, 52, 9, 97,102,105,105, 49, 48, 48, 50, 53, 9, 97,102,105,105, 49, 48, 48, 50, 54, 9, 97,
+102,105,105, 49, 48, 48, 50, 55, 9, 97,102,105,105, 49, 48, 48, 50, 56, 9, 97,102,105,105, 49, 48, 48, 50, 57, 9, 97,102,105,
+105, 49, 48, 48, 51, 48, 9, 97,102,105,105, 49, 48, 48, 51, 49, 9, 97,102,105,105, 49, 48, 48, 51, 50, 9, 97,102,105,105, 49,
+ 48, 48, 51, 51, 9, 97,102,105,105, 49, 48, 48, 51, 52, 9, 97,102,105,105, 49, 48, 48, 51, 53, 9, 97,102,105,105, 49, 48, 48,
+ 51, 54, 9, 97,102,105,105, 49, 48, 48, 51, 55, 9, 97,102,105,105, 49, 48, 48, 51, 56, 9, 97,102,105,105, 49, 48, 48, 51, 57,
+ 9, 97,102,105,105, 49, 48, 48, 52, 48, 9, 97,102,105,105, 49, 48, 48, 52, 49, 9, 97,102,105,105, 49, 48, 48, 52, 50, 9, 97,
+102,105,105, 49, 48, 48, 52, 51, 9, 97,102,105,105, 49, 48, 48, 52, 52, 9, 97,102,105,105, 49, 48, 48, 52, 53, 9, 97,102,105,
+105, 49, 48, 48, 52, 54, 9, 97,102,105,105, 49, 48, 48, 52, 55, 9, 97,102,105,105, 49, 48, 48, 52, 56, 9, 97,102,105,105, 49,
+ 48, 48, 52, 57, 9, 97,102,105,105, 49, 48, 48, 54, 53, 9, 97,102,105,105, 49, 48, 48, 54, 54, 9, 97,102,105,105, 49, 48, 48,
+ 54, 55, 9, 97,102,105,105, 49, 48, 48, 54, 56, 9, 97,102,105,105, 49, 48, 48, 54, 57, 9, 97,102,105,105, 49, 48, 48, 55, 48,
+ 9, 97,102,105,105, 49, 48, 48, 55, 50, 9, 97,102,105,105, 49, 48, 48, 55, 51, 9, 97,102,105,105, 49, 48, 48, 55, 52, 9, 97,
+102,105,105, 49, 48, 48, 55, 53, 9, 97,102,105,105, 49, 48, 48, 55, 54, 9, 97,102,105,105, 49, 48, 48, 55, 55, 9, 97,102,105,
+105, 49, 48, 48, 55, 56, 9, 97,102,105,105, 49, 48, 48, 55, 57, 9, 97,102,105,105, 49, 48, 48, 56, 48, 9, 97,102,105,105, 49,
+ 48, 48, 56, 49, 9, 97,102,105,105, 49, 48, 48, 56, 50, 9, 97,102,105,105, 49, 48, 48, 56, 51, 9, 97,102,105,105, 49, 48, 48,
+ 56, 52, 9, 97,102,105,105, 49, 48, 48, 56, 53, 9, 97,102,105,105, 49, 48, 48, 56, 54, 9, 97,102,105,105, 49, 48, 48, 56, 55,
+ 9, 97,102,105,105, 49, 48, 48, 56, 56, 9, 97,102,105,105, 49, 48, 48, 56, 57, 9, 97,102,105,105, 49, 48, 48, 57, 48, 9, 97,
+102,105,105, 49, 48, 48, 57, 49, 9, 97,102,105,105, 49, 48, 48, 57, 50, 9, 97,102,105,105, 49, 48, 48, 57, 51, 9, 97,102,105,
+105, 49, 48, 48, 57, 52, 9, 97,102,105,105, 49, 48, 48, 57, 53, 9, 97,102,105,105, 49, 48, 48, 57, 54, 9, 97,102,105,105, 49,
+ 48, 48, 57, 55, 7,117,110,105, 48, 52, 53, 48, 9, 97,102,105,105, 49, 48, 48, 55, 49, 9, 97,102,105,105, 49, 48, 48, 57, 57,
+ 9, 97,102,105,105, 49, 48, 49, 48, 48, 9, 97,102,105,105, 49, 48, 49, 48, 49, 9, 97,102,105,105, 49, 48, 49, 48, 50, 9, 97,
+102,105,105, 49, 48, 49, 48, 51, 9, 97,102,105,105, 49, 48, 49, 48, 52, 9, 97,102,105,105, 49, 48, 49, 48, 53, 9, 97,102,105,
+105, 49, 48, 49, 48, 54, 9, 97,102,105,105, 49, 48, 49, 48, 55, 9, 97,102,105,105, 49, 48, 49, 48, 56, 9, 97,102,105,105, 49,
+ 48, 49, 48, 57, 7,117,110,105, 48, 52, 53, 68, 9, 97,102,105,105, 49, 48, 49, 49, 48, 9, 97,102,105,105, 49, 48, 49, 57, 51,
+ 7,117,110,105, 48, 52, 54, 48, 7,117,110,105, 48, 52, 54, 49, 9, 97,102,105,105, 49, 48, 49, 52, 54, 9, 97,102,105,105, 49,
+ 48, 49, 57, 52, 7,117,110,105, 48, 52, 54, 52, 7,117,110,105, 48, 52, 54, 53, 7,117,110,105, 48, 52, 54, 54, 7,117,110,105,
+ 48, 52, 54, 55, 7,117,110,105, 48, 52, 54, 56, 7,117,110,105, 48, 52, 54, 57, 7,117,110,105, 48, 52, 54, 65, 7,117,110,105,
+ 48, 52, 54, 66, 7,117,110,105, 48, 52, 54, 67, 7,117,110,105, 48, 52, 54, 68, 7,117,110,105, 48, 52, 54, 69, 7,117,110,105,
+ 48, 52, 54, 70, 7,117,110,105, 48, 52, 55, 48, 7,117,110,105, 48, 52, 55, 49, 9, 97,102,105,105, 49, 48, 49, 52, 55, 9, 97,
+102,105,105, 49, 48, 49, 57, 53, 9, 97,102,105,105, 49, 48, 49, 52, 56, 9, 97,102,105,105, 49, 48, 49, 57, 54, 7,117,110,105,
+ 48, 52, 55, 54, 7,117,110,105, 48, 52, 55, 55, 7,117,110,105, 48, 52, 55, 56, 7,117,110,105, 48, 52, 55, 57, 7,117,110,105,
+ 48, 52, 55, 65, 7,117,110,105, 48, 52, 55, 66, 7,117,110,105, 48, 52, 55, 67, 7,117,110,105, 48, 52, 55, 68, 7,117,110,105,
+ 48, 52, 55, 69, 7,117,110,105, 48, 52, 55, 70, 7,117,110,105, 48, 52, 56, 48, 7,117,110,105, 48, 52, 56, 49, 7,117,110,105,
+ 48, 52, 56, 50, 7,117,110,105, 48, 52, 56, 51, 7,117,110,105, 48, 52, 56, 52, 7,117,110,105, 48, 52, 56, 53, 7,117,110,105,
+ 48, 52, 56, 54, 7,117,110,105, 48, 52, 56, 56, 7,117,110,105, 48, 52, 56, 57, 7,117,110,105, 48, 52, 56, 65, 7,117,110,105,
+ 48, 52, 56, 66, 7,117,110,105, 48, 52, 56, 67, 7,117,110,105, 48, 52, 56, 68, 7,117,110,105, 48, 52, 56, 69, 7,117,110,105,
+ 48, 52, 56, 70, 9, 97,102,105,105, 49, 48, 48, 53, 48, 9, 97,102,105,105, 49, 48, 48, 57, 56, 7,117,110,105, 48, 52, 57, 50,
+ 7,117,110,105, 48, 52, 57, 51, 7,117,110,105, 48, 52, 57, 52, 7,117,110,105, 48, 52, 57, 53, 7,117,110,105, 48, 52, 57, 54,
+ 7,117,110,105, 48, 52, 57, 55, 7,117,110,105, 48, 52, 57, 56, 7,117,110,105, 48, 52, 57, 57, 7,117,110,105, 48, 52, 57, 65,
+ 7,117,110,105, 48, 52, 57, 66, 7,117,110,105, 48, 52, 57, 67, 7,117,110,105, 48, 52, 57, 68, 7,117,110,105, 48, 52, 57, 69,
+ 7,117,110,105, 48, 52, 57, 70, 7,117,110,105, 48, 52, 65, 48, 7,117,110,105, 48, 52, 65, 49, 7,117,110,105, 48, 52, 65, 50,
+ 7,117,110,105, 48, 52, 65, 51, 7,117,110,105, 48, 52, 65, 52, 7,117,110,105, 48, 52, 65, 53, 7,117,110,105, 48, 52, 65, 54,
+ 7,117,110,105, 48, 52, 65, 55, 7,117,110,105, 48, 52, 65, 56, 7,117,110,105, 48, 52, 65, 57, 7,117,110,105, 48, 52, 65, 65,
+ 7,117,110,105, 48, 52, 65, 66, 7,117,110,105, 48, 52, 65, 67, 7,117,110,105, 48, 52, 65, 68, 7,117,110,105, 48, 52, 65, 69,
+ 7,117,110,105, 48, 52, 65, 70, 7,117,110,105, 48, 52, 66, 48, 7,117,110,105, 48, 52, 66, 49, 7,117,110,105, 48, 52, 66, 50,
+ 7,117,110,105, 48, 52, 66, 51, 7,117,110,105, 48, 52, 66, 52, 7,117,110,105, 48, 52, 66, 53, 7,117,110,105, 48, 52, 66, 54,
+ 7,117,110,105, 48, 52, 66, 55, 7,117,110,105, 48, 52, 66, 56, 7,117,110,105, 48, 52, 66, 57, 7,117,110,105, 48, 52, 66, 65,
+ 7,117,110,105, 48, 52, 66, 66, 7,117,110,105, 48, 52, 66, 67, 7,117,110,105, 48, 52, 66, 68, 7,117,110,105, 48, 52, 66, 69,
+ 7,117,110,105, 48, 52, 66, 70, 7,117,110,105, 48, 52, 67, 48, 7,117,110,105, 48, 52, 67, 49, 7,117,110,105, 48, 52, 67, 50,
+ 7,117,110,105, 48, 52, 67, 51, 7,117,110,105, 48, 52, 67, 52, 7,117,110,105, 48, 52, 67, 53, 7,117,110,105, 48, 52, 67, 54,
+ 7,117,110,105, 48, 52, 67, 55, 7,117,110,105, 48, 52, 67, 56, 7,117,110,105, 48, 52, 67, 57, 7,117,110,105, 48, 52, 67, 65,
+ 7,117,110,105, 48, 52, 67, 66, 7,117,110,105, 48, 52, 67, 67, 7,117,110,105, 48, 52, 67, 68, 7,117,110,105, 48, 52, 67, 69,
+ 7,117,110,105, 48, 52, 68, 48, 7,117,110,105, 48, 52, 68, 49, 7,117,110,105, 48, 52, 68, 50, 7,117,110,105, 48, 52, 68, 51,
+ 7,117,110,105, 48, 52, 68, 52, 7,117,110,105, 48, 52, 68, 53, 7,117,110,105, 48, 52, 68, 54, 7,117,110,105, 48, 52, 68, 55,
+ 7,117,110,105, 48, 52, 68, 56, 9, 97,102,105,105, 49, 48, 56, 52, 54, 7,117,110,105, 48, 52, 68, 65, 7,117,110,105, 48, 52,
+ 68, 66, 7,117,110,105, 48, 52, 68, 67, 7,117,110,105, 48, 52, 68, 68, 7,117,110,105, 48, 52, 68, 69, 7,117,110,105, 48, 52,
+ 68, 70, 7,117,110,105, 48, 52, 69, 48, 7,117,110,105, 48, 52, 69, 49, 7,117,110,105, 48, 52, 69, 50, 7,117,110,105, 48, 52,
+ 69, 51, 7,117,110,105, 48, 52, 69, 52, 7,117,110,105, 48, 52, 69, 53, 7,117,110,105, 48, 52, 69, 54, 7,117,110,105, 48, 52,
+ 69, 55, 7,117,110,105, 48, 52, 69, 56, 7,117,110,105, 48, 52, 69, 57, 7,117,110,105, 48, 52, 69, 65, 7,117,110,105, 48, 52,
+ 69, 66, 7,117,110,105, 48, 52, 69, 67, 7,117,110,105, 48, 52, 69, 68, 7,117,110,105, 48, 52, 69, 69, 7,117,110,105, 48, 52,
+ 69, 70, 7,117,110,105, 48, 52, 70, 48, 7,117,110,105, 48, 52, 70, 49, 7,117,110,105, 48, 52, 70, 50, 7,117,110,105, 48, 52,
+ 70, 51, 7,117,110,105, 48, 52, 70, 52, 7,117,110,105, 48, 52, 70, 53, 7,117,110,105, 48, 52, 70, 54, 7,117,110,105, 48, 52,
+ 70, 55, 7,117,110,105, 48, 52, 70, 56, 7,117,110,105, 48, 52, 70, 57, 7,117,110,105, 48, 53, 48, 48, 7,117,110,105, 48, 53,
+ 48, 49, 7,117,110,105, 48, 53, 48, 50, 7,117,110,105, 48, 53, 48, 51, 7,117,110,105, 48, 53, 48, 52, 7,117,110,105, 48, 53,
+ 48, 53, 7,117,110,105, 48, 53, 48, 54, 7,117,110,105, 48, 53, 48, 55, 7,117,110,105, 48, 53, 48, 56, 7,117,110,105, 48, 53,
+ 48, 57, 7,117,110,105, 48, 53, 48, 65, 7,117,110,105, 48, 53, 48, 66, 7,117,110,105, 48, 53, 48, 67, 7,117,110,105, 48, 53,
+ 48, 68, 7,117,110,105, 48, 53, 48, 69, 7,117,110,105, 48, 53, 48, 70, 7,117,110,105, 48, 53, 51, 49, 7,117,110,105, 48, 53,
+ 51, 50, 7,117,110,105, 48, 53, 51, 51, 7,117,110,105, 48, 53, 51, 52, 7,117,110,105, 48, 53, 51, 53, 7,117,110,105, 48, 53,
+ 51, 54, 7,117,110,105, 48, 53, 51, 55, 7,117,110,105, 48, 53, 51, 56, 7,117,110,105, 48, 53, 51, 57, 7,117,110,105, 48, 53,
+ 51, 65, 7,117,110,105, 48, 53, 51, 66, 7,117,110,105, 48, 53, 51, 67, 7,117,110,105, 48, 53, 51, 68, 7,117,110,105, 48, 53,
+ 51, 69, 7,117,110,105, 48, 53, 51, 70, 7,117,110,105, 48, 53, 52, 48, 7,117,110,105, 48, 53, 52, 49, 7,117,110,105, 48, 53,
+ 52, 50, 7,117,110,105, 48, 53, 52, 51, 7,117,110,105, 48, 53, 52, 52, 7,117,110,105, 48, 53, 52, 53, 7,117,110,105, 48, 53,
+ 52, 54, 7,117,110,105, 48, 53, 52, 55, 7,117,110,105, 48, 53, 52, 56, 7,117,110,105, 48, 53, 52, 57, 7,117,110,105, 48, 53,
+ 52, 65, 7,117,110,105, 48, 53, 52, 66, 7,117,110,105, 48, 53, 52, 67, 7,117,110,105, 48, 53, 52, 68, 7,117,110,105, 48, 53,
+ 52, 69, 7,117,110,105, 48, 53, 52, 70, 7,117,110,105, 48, 53, 53, 48, 7,117,110,105, 48, 53, 53, 49, 7,117,110,105, 48, 53,
+ 53, 50, 7,117,110,105, 48, 53, 53, 51, 7,117,110,105, 48, 53, 53, 52, 7,117,110,105, 48, 53, 53, 53, 7,117,110,105, 48, 53,
+ 53, 54, 7,117,110,105, 48, 53, 53, 57, 7,117,110,105, 48, 53, 53, 65, 7,117,110,105, 48, 53, 53, 66, 7,117,110,105, 48, 53,
+ 53, 67, 7,117,110,105, 48, 53, 53, 68, 7,117,110,105, 48, 53, 53, 69, 7,117,110,105, 48, 53, 53, 70, 7,117,110,105, 48, 53,
+ 54, 49, 7,117,110,105, 48, 53, 54, 50, 7,117,110,105, 48, 53, 54, 51, 7,117,110,105, 48, 53, 54, 52, 7,117,110,105, 48, 53,
+ 54, 53, 7,117,110,105, 48, 53, 54, 54, 7,117,110,105, 48, 53, 54, 55, 7,117,110,105, 48, 53, 54, 56, 7,117,110,105, 48, 53,
+ 54, 57, 7,117,110,105, 48, 53, 54, 65, 7,117,110,105, 48, 53, 54, 66, 7,117,110,105, 48, 53, 54, 67, 7,117,110,105, 48, 53,
+ 54, 68, 7,117,110,105, 48, 53, 54, 69, 7,117,110,105, 48, 53, 54, 70, 7,117,110,105, 48, 53, 55, 48, 7,117,110,105, 48, 53,
+ 55, 49, 7,117,110,105, 48, 53, 55, 50, 7,117,110,105, 48, 53, 55, 51, 7,117,110,105, 48, 53, 55, 52, 7,117,110,105, 48, 53,
+ 55, 53, 7,117,110,105, 48, 53, 55, 54, 7,117,110,105, 48, 53, 55, 55, 7,117,110,105, 48, 53, 55, 56, 7,117,110,105, 48, 53,
+ 55, 57, 7,117,110,105, 48, 53, 55, 65, 7,117,110,105, 48, 53, 55, 66, 7,117,110,105, 48, 53, 55, 67, 7,117,110,105, 48, 53,
+ 55, 68, 7,117,110,105, 48, 53, 55, 69, 7,117,110,105, 48, 53, 55, 70, 7,117,110,105, 48, 53, 56, 48, 7,117,110,105, 48, 53,
+ 56, 49, 7,117,110,105, 48, 53, 56, 50, 7,117,110,105, 48, 53, 56, 51, 7,117,110,105, 48, 53, 56, 52, 7,117,110,105, 48, 53,
+ 56, 53, 7,117,110,105, 48, 53, 56, 54, 7,117,110,105, 48, 53, 56, 55, 7,117,110,105, 48, 53, 56, 57, 7,117,110,105, 48, 53,
+ 56, 65, 9, 97,102,105,105, 53, 55, 51, 56, 56, 7,117,110,105, 49, 69, 48, 48, 7,117,110,105, 49, 69, 48, 49, 7,117,110,105,
+ 49, 69, 48, 50, 7,117,110,105, 49, 69, 48, 51, 7,117,110,105, 49, 69, 48, 52, 7,117,110,105, 49, 69, 48, 53, 7,117,110,105,
+ 49, 69, 48, 54, 7,117,110,105, 49, 69, 48, 55, 7,117,110,105, 49, 69, 48, 56, 7,117,110,105, 49, 69, 48, 57, 7,117,110,105,
+ 49, 69, 48, 65, 7,117,110,105, 49, 69, 48, 66, 7,117,110,105, 49, 69, 48, 67, 7,117,110,105, 49, 69, 48, 68, 7,117,110,105,
+ 49, 69, 48, 69, 7,117,110,105, 49, 69, 48, 70, 7,117,110,105, 49, 69, 49, 48, 7,117,110,105, 49, 69, 49, 49, 7,117,110,105,
+ 49, 69, 49, 50, 7,117,110,105, 49, 69, 49, 51, 7,117,110,105, 49, 69, 49, 52, 7,117,110,105, 49, 69, 49, 53, 7,117,110,105,
+ 49, 69, 49, 54, 7,117,110,105, 49, 69, 49, 55, 7,117,110,105, 49, 69, 49, 56, 7,117,110,105, 49, 69, 49, 57, 7,117,110,105,
+ 49, 69, 49, 65, 7,117,110,105, 49, 69, 49, 66, 7,117,110,105, 49, 69, 49, 67, 7,117,110,105, 49, 69, 49, 68, 7,117,110,105,
+ 49, 69, 49, 69, 7,117,110,105, 49, 69, 49, 70, 7,117,110,105, 49, 69, 50, 48, 7,117,110,105, 49, 69, 50, 49, 7,117,110,105,
+ 49, 69, 50, 50, 7,117,110,105, 49, 69, 50, 51, 7,117,110,105, 49, 69, 50, 52, 7,117,110,105, 49, 69, 50, 53, 7,117,110,105,
+ 49, 69, 50, 54, 7,117,110,105, 49, 69, 50, 55, 7,117,110,105, 49, 69, 50, 56, 7,117,110,105, 49, 69, 50, 57, 7,117,110,105,
+ 49, 69, 50, 65, 7,117,110,105, 49, 69, 50, 66, 7,117,110,105, 49, 69, 50, 67, 7,117,110,105, 49, 69, 50, 68, 7,117,110,105,
+ 49, 69, 50, 69, 7,117,110,105, 49, 69, 50, 70, 7,117,110,105, 49, 69, 51, 48, 7,117,110,105, 49, 69, 51, 49, 7,117,110,105,
+ 49, 69, 51, 50, 7,117,110,105, 49, 69, 51, 51, 7,117,110,105, 49, 69, 51, 52, 7,117,110,105, 49, 69, 51, 53, 7,117,110,105,
+ 49, 69, 51, 54, 7,117,110,105, 49, 69, 51, 55, 7,117,110,105, 49, 69, 51, 56, 7,117,110,105, 49, 69, 51, 57, 7,117,110,105,
+ 49, 69, 51, 65, 7,117,110,105, 49, 69, 51, 66, 7,117,110,105, 49, 69, 51, 67, 7,117,110,105, 49, 69, 51, 68, 7,117,110,105,
+ 49, 69, 51, 69, 7,117,110,105, 49, 69, 51, 70, 7,117,110,105, 49, 69, 52, 48, 7,117,110,105, 49, 69, 52, 49, 7,117,110,105,
+ 49, 69, 52, 50, 7,117,110,105, 49, 69, 52, 51, 7,117,110,105, 49, 69, 52, 52, 7,117,110,105, 49, 69, 52, 53, 7,117,110,105,
+ 49, 69, 52, 54, 7,117,110,105, 49, 69, 52, 55, 7,117,110,105, 49, 69, 52, 56, 7,117,110,105, 49, 69, 52, 57, 7,117,110,105,
+ 49, 69, 52, 65, 7,117,110,105, 49, 69, 52, 66, 7,117,110,105, 49, 69, 52, 67, 7,117,110,105, 49, 69, 52, 68, 7,117,110,105,
+ 49, 69, 52, 69, 7,117,110,105, 49, 69, 52, 70, 7,117,110,105, 49, 69, 53, 48, 7,117,110,105, 49, 69, 53, 49, 7,117,110,105,
+ 49, 69, 53, 50, 7,117,110,105, 49, 69, 53, 51, 7,117,110,105, 49, 69, 53, 52, 7,117,110,105, 49, 69, 53, 53, 7,117,110,105,
+ 49, 69, 53, 54, 7,117,110,105, 49, 69, 53, 55, 7,117,110,105, 49, 69, 53, 56, 7,117,110,105, 49, 69, 53, 57, 7,117,110,105,
+ 49, 69, 53, 65, 7,117,110,105, 49, 69, 53, 66, 7,117,110,105, 49, 69, 53, 67, 7,117,110,105, 49, 69, 53, 68, 7,117,110,105,
+ 49, 69, 53, 69, 7,117,110,105, 49, 69, 53, 70, 7,117,110,105, 49, 69, 54, 48, 7,117,110,105, 49, 69, 54, 49, 7,117,110,105,
+ 49, 69, 54, 50, 7,117,110,105, 49, 69, 54, 51, 7,117,110,105, 49, 69, 54, 52, 7,117,110,105, 49, 69, 54, 53, 7,117,110,105,
+ 49, 69, 54, 54, 7,117,110,105, 49, 69, 54, 55, 7,117,110,105, 49, 69, 54, 56, 7,117,110,105, 49, 69, 54, 57, 7,117,110,105,
+ 49, 69, 54, 65, 7,117,110,105, 49, 69, 54, 66, 7,117,110,105, 49, 69, 54, 67, 7,117,110,105, 49, 69, 54, 68, 7,117,110,105,
+ 49, 69, 54, 69, 7,117,110,105, 49, 69, 54, 70, 7,117,110,105, 49, 69, 55, 48, 7,117,110,105, 49, 69, 55, 49, 7,117,110,105,
+ 49, 69, 55, 50, 7,117,110,105, 49, 69, 55, 51, 7,117,110,105, 49, 69, 55, 52, 7,117,110,105, 49, 69, 55, 53, 7,117,110,105,
+ 49, 69, 55, 54, 7,117,110,105, 49, 69, 55, 55, 7,117,110,105, 49, 69, 55, 56, 7,117,110,105, 49, 69, 55, 57, 7,117,110,105,
+ 49, 69, 55, 65, 7,117,110,105, 49, 69, 55, 66, 7,117,110,105, 49, 69, 55, 67, 7,117,110,105, 49, 69, 55, 68, 7,117,110,105,
+ 49, 69, 55, 69, 7,117,110,105, 49, 69, 55, 70, 6, 87,103,114, 97,118,101, 6,119,103,114, 97,118,101, 6, 87, 97, 99,117,116,
+101, 6,119, 97, 99,117,116,101, 9, 87,100,105,101,114,101,115,105,115, 9,119,100,105,101,114,101,115,105,115, 7,117,110,105,
+ 49, 69, 56, 54, 7,117,110,105, 49, 69, 56, 55, 7,117,110,105, 49, 69, 56, 56, 7,117,110,105, 49, 69, 56, 57, 7,117,110,105,
+ 49, 69, 56, 65, 7,117,110,105, 49, 69, 56, 66, 7,117,110,105, 49, 69, 56, 67, 7,117,110,105, 49, 69, 56, 68, 7,117,110,105,
+ 49, 69, 56, 69, 7,117,110,105, 49, 69, 56, 70, 7,117,110,105, 49, 69, 57, 48, 7,117,110,105, 49, 69, 57, 49, 7,117,110,105,
+ 49, 69, 57, 50, 7,117,110,105, 49, 69, 57, 51, 7,117,110,105, 49, 69, 57, 52, 7,117,110,105, 49, 69, 57, 53, 7,117,110,105,
+ 49, 69, 57, 54, 7,117,110,105, 49, 69, 57, 55, 7,117,110,105, 49, 69, 57, 56, 7,117,110,105, 49, 69, 57, 57, 7,117,110,105,
+ 49, 69, 57, 65, 7,117,110,105, 49, 69, 57, 66, 7,117,110,105, 49, 69, 65, 48, 7,117,110,105, 49, 69, 65, 49, 7,117,110,105,
+ 49, 69, 65, 50, 7,117,110,105, 49, 69, 65, 51, 7,117,110,105, 49, 69, 65, 52, 7,117,110,105, 49, 69, 65, 53, 7,117,110,105,
+ 49, 69, 65, 54, 7,117,110,105, 49, 69, 65, 55, 7,117,110,105, 49, 69, 65, 56, 7,117,110,105, 49, 69, 65, 57, 7,117,110,105,
+ 49, 69, 65, 65, 7,117,110,105, 49, 69, 65, 66, 7,117,110,105, 49, 69, 65, 67, 7,117,110,105, 49, 69, 65, 68, 7,117,110,105,
+ 49, 69, 65, 69, 7,117,110,105, 49, 69, 65, 70, 7,117,110,105, 49, 69, 66, 48, 7,117,110,105, 49, 69, 66, 49, 7,117,110,105,
+ 49, 69, 66, 50, 7,117,110,105, 49, 69, 66, 51, 7,117,110,105, 49, 69, 66, 52, 7,117,110,105, 49, 69, 66, 53, 7,117,110,105,
+ 49, 69, 66, 54, 7,117,110,105, 49, 69, 66, 55, 7,117,110,105, 49, 69, 66, 56, 7,117,110,105, 49, 69, 66, 57, 7,117,110,105,
+ 49, 69, 66, 65, 7,117,110,105, 49, 69, 66, 66, 7,117,110,105, 49, 69, 66, 67, 7,117,110,105, 49, 69, 66, 68, 7,117,110,105,
+ 49, 69, 66, 69, 7,117,110,105, 49, 69, 66, 70, 7,117,110,105, 49, 69, 67, 48, 7,117,110,105, 49, 69, 67, 49, 7,117,110,105,
+ 49, 69, 67, 50, 7,117,110,105, 49, 69, 67, 51, 7,117,110,105, 49, 69, 67, 52, 7,117,110,105, 49, 69, 67, 53, 7,117,110,105,
+ 49, 69, 67, 54, 7,117,110,105, 49, 69, 67, 55, 7,117,110,105, 49, 69, 67, 56, 7,117,110,105, 49, 69, 67, 57, 7,117,110,105,
+ 49, 69, 67, 65, 7,117,110,105, 49, 69, 67, 66, 7,117,110,105, 49, 69, 67, 67, 7,117,110,105, 49, 69, 67, 68, 7,117,110,105,
+ 49, 69, 67, 69, 7,117,110,105, 49, 69, 67, 70, 7,117,110,105, 49, 69, 68, 48, 7,117,110,105, 49, 69, 68, 49, 7,117,110,105,
+ 49, 69, 68, 50, 7,117,110,105, 49, 69, 68, 51, 7,117,110,105, 49, 69, 68, 52, 7,117,110,105, 49, 69, 68, 53, 7,117,110,105,
+ 49, 69, 68, 54, 7,117,110,105, 49, 69, 68, 55, 7,117,110,105, 49, 69, 68, 56, 7,117,110,105, 49, 69, 68, 57, 7,117,110,105,
+ 49, 69, 68, 65, 7,117,110,105, 49, 69, 68, 66, 7,117,110,105, 49, 69, 68, 67, 7,117,110,105, 49, 69, 68, 68, 7,117,110,105,
+ 49, 69, 68, 69, 7,117,110,105, 49, 69, 68, 70, 7,117,110,105, 49, 69, 69, 48, 7,117,110,105, 49, 69, 69, 49, 7,117,110,105,
+ 49, 69, 69, 50, 7,117,110,105, 49, 69, 69, 51, 7,117,110,105, 49, 69, 69, 52, 7,117,110,105, 49, 69, 69, 53, 7,117,110,105,
+ 49, 69, 69, 54, 7,117,110,105, 49, 69, 69, 55, 7,117,110,105, 49, 69, 69, 56, 7,117,110,105, 49, 69, 69, 57, 7,117,110,105,
+ 49, 69, 69, 65, 7,117,110,105, 49, 69, 69, 66, 7,117,110,105, 49, 69, 69, 67, 7,117,110,105, 49, 69, 69, 68, 7,117,110,105,
+ 49, 69, 69, 69, 7,117,110,105, 49, 69, 69, 70, 7,117,110,105, 49, 69, 70, 48, 7,117,110,105, 49, 69, 70, 49, 6, 89,103,114,
+ 97,118,101, 6,121,103,114, 97,118,101, 7,117,110,105, 49, 69, 70, 52, 7,117,110,105, 49, 69, 70, 53, 7,117,110,105, 49, 69,
+ 70, 54, 7,117,110,105, 49, 69, 70, 55, 7,117,110,105, 49, 69, 70, 56, 7,117,110,105, 49, 69, 70, 57, 7,117,110,105, 49, 70,
+ 66, 70, 7,117,110,105, 49, 70, 70, 68, 7,117,110,105, 49, 70, 70, 69, 7,117,110,105, 50, 48, 48, 48, 7,117,110,105, 50, 48,
+ 48, 49, 7,117,110,105, 50, 48, 48, 50, 7,117,110,105, 50, 48, 48, 51, 7,117,110,105, 50, 48, 48, 52, 7,117,110,105, 50, 48,
+ 48, 53, 7,117,110,105, 50, 48, 48, 54, 7,117,110,105, 50, 48, 48, 55, 7,117,110,105, 50, 48, 48, 56, 7,117,110,105, 50, 48,
+ 48, 57, 7,117,110,105, 50, 48, 48, 65, 7,117,110,105, 50, 48, 48, 66, 9, 97,102,105,105, 54, 49, 54, 54, 52, 7, 97,102,105,
+105, 51, 48, 49, 7, 97,102,105,105, 50, 57, 57, 7, 97,102,105,105, 51, 48, 48, 7,117,110,105, 50, 48, 49, 48, 7,117,110,105,
+ 50, 48, 49, 49, 10,102,105,103,117,114,101,100, 97,115,104, 9, 97,102,105,105, 48, 48, 50, 48, 56, 7,117,110,105, 50, 48, 49,
+ 54, 13,117,110,100,101,114,115, 99,111,114,101,100, 98,108, 13,113,117,111,116,101,114,101,118,101,114,115,101,100, 7,117,110,
+105, 50, 48, 49, 70, 7,117,110,105, 50, 48, 50, 51, 14,111,110,101,100,111,116,101,110,108,101, 97,100,101,114, 14,116,119,111,
+100,111,116,101,110,108,101, 97,100,101,114, 7,117,110,105, 50, 48, 50, 55, 7,117,110,105, 50, 48, 51, 49, 6,109,105,110,117,
+116,101, 6,115,101, 99,111,110,100, 7,117,110,105, 50, 48, 51, 52, 7,117,110,105, 50, 48, 51, 53, 7,117,110,105, 50, 48, 51,
+ 54, 7,117,110,105, 50, 48, 51, 55, 7,117,110,105, 50, 48, 51, 56, 7,117,110,105, 50, 48, 51, 66, 9,101,120, 99,108, 97,109,
+100, 98,108, 7,117,110,105, 50, 48, 51, 68, 7,117,110,105, 50, 48, 51, 69, 7,117,110,105, 50, 48, 51, 70, 7,117,110,105, 50,
+ 48, 52, 48, 7,117,110,105, 50, 48, 52, 49, 7,117,110,105, 50, 48, 52, 50, 7,117,110,105, 50, 48, 52, 51, 7,117,110,105, 50,
+ 48, 52, 53, 7,117,110,105, 50, 48, 52, 54, 7,117,110,105, 50, 48, 52, 55, 7,117,110,105, 50, 48, 52, 56, 7,117,110,105, 50,
+ 48, 52, 57, 7,117,110,105, 50, 48, 52, 65, 7,117,110,105, 50, 48, 52, 66, 7,117,110,105, 50, 48, 52, 67, 7,117,110,105, 50,
+ 48, 52, 68, 7,117,110,105, 50, 48, 52, 69, 7,117,110,105, 50, 48, 52, 70, 7,117,110,105, 50, 48, 53, 48, 7,117,110,105, 50,
+ 48, 53, 49, 7,117,110,105, 50, 48, 53, 50, 7,117,110,105, 50, 48, 53, 51, 7,117,110,105, 50, 48, 53, 52, 7,117,110,105, 50,
+ 48, 53, 53, 7,117,110,105, 50, 48, 53, 54, 7,117,110,105, 50, 48, 53, 55, 7,117,110,105, 50, 48, 53, 56, 7,117,110,105, 50,
+ 48, 53, 57, 7,117,110,105, 50, 48, 53, 65, 7,117,110,105, 50, 48, 53, 66, 7,117,110,105, 50, 48, 53, 67, 7,117,110,105, 50,
+ 48, 53, 68, 7,117,110,105, 50, 48, 53, 69, 7,117,110,105, 50, 48, 55, 48, 7,117,110,105, 50, 48, 55, 49, 7,117,110,105, 50,
+ 48, 55, 52, 7,117,110,105, 50, 48, 55, 53, 7,117,110,105, 50, 48, 55, 54, 7,117,110,105, 50, 48, 55, 55, 7,117,110,105, 50,
+ 48, 55, 56, 7,117,110,105, 50, 48, 55, 57, 7,117,110,105, 50, 48, 55, 65, 7,117,110,105, 50, 48, 55, 66, 7,117,110,105, 50,
+ 48, 55, 67, 7,117,110,105, 50, 48, 55, 68, 7,117,110,105, 50, 48, 55, 69, 7,117,110,105, 50, 48, 55, 70, 7,117,110,105, 50,
+ 48, 56, 48, 7,117,110,105, 50, 48, 56, 49, 7,117,110,105, 50, 48, 56, 50, 7,117,110,105, 50, 48, 56, 51, 7,117,110,105, 50,
+ 48, 56, 52, 7,117,110,105, 50, 48, 56, 53, 7,117,110,105, 50, 48, 56, 54, 7,117,110,105, 50, 48, 56, 55, 7,117,110,105, 50,
+ 48, 56, 56, 7,117,110,105, 50, 48, 56, 57, 7,117,110,105, 50, 48, 56, 65, 7,117,110,105, 50, 48, 56, 66, 7,117,110,105, 50,
+ 48, 56, 67, 7,117,110,105, 50, 48, 56, 68, 7,117,110,105, 50, 48, 56, 69, 7,117,110,105, 50, 48, 65, 48, 13, 99,111,108,111,
+110,109,111,110,101,116, 97,114,121, 7,117,110,105, 50, 48, 65, 50, 4,108,105,114, 97, 7,117,110,105, 50, 48, 65, 53, 7,117,
+110,105, 50, 48, 65, 54, 6,112,101,115,101,116, 97, 7,117,110,105, 50, 48, 65, 56, 7,117,110,105, 50, 48, 65, 57, 9, 97,102,
+105,105, 53, 55, 54, 51, 54, 4,100,111,110,103, 4, 69,117,114,111, 7,117,110,105, 50, 48, 65, 68, 7,117,110,105, 50, 48, 65,
+ 69, 7,117,110,105, 50, 48, 65, 70, 7,117,110,105, 50, 48, 66, 49, 7,117,110,105, 50, 48, 66, 52, 7,117,110,105, 50, 48, 66,
+ 53, 7,117,110,105, 50, 48, 68, 54, 7,117,110,105, 50, 48, 68, 55, 7,117,110,105, 50, 49, 48, 48, 7,117,110,105, 50, 49, 48,
+ 51, 7,117,110,105, 50, 49, 48, 52, 9, 97,102,105,105, 54, 49, 50, 52, 56, 7,117,110,105, 50, 49, 48, 54, 7,117,110,105, 50,
+ 49, 48, 57, 7,117,110,105, 50, 49, 48, 69, 7,117,110,105, 50, 49, 48, 70, 8, 73,102,114, 97,107,116,117,114, 9, 97,102,105,
+105, 54, 49, 50, 56, 57, 9, 97,102,105,105, 54, 49, 51, 53, 50, 7,117,110,105, 50, 49, 49, 55, 11,119,101,105,101,114,115,116,
+114, 97,115,115, 8, 82,102,114, 97,107,116,117,114, 7,117,110,105, 50, 49, 49, 68, 12,112,114,101,115, 99,114,105,112,116,105,
+111,110, 7,117,110,105, 50, 49, 50, 48, 7,117,110,105, 50, 49, 50, 49, 7,117,110,105, 50, 49, 50, 54, 7,117,110,105, 50, 49,
+ 50, 55, 7,117,110,105, 50, 49, 50, 65, 7,117,110,105, 50, 49, 50, 66, 9,101,115,116,105,109, 97,116,101,100, 7,117,110,105,
+ 50, 49, 51, 50, 7,117,110,105, 50, 49, 51, 52, 5, 97,108,101,112,104, 7,117,110,105, 50, 49, 51, 66, 7,117,110,105, 50, 49,
+ 52, 66, 8,111,110,101,116,104,105,114,100, 9,116,119,111,116,104,105,114,100,115, 7,117,110,105, 50, 49, 53, 53, 7,117,110,
+105, 50, 49, 53, 54, 7,117,110,105, 50, 49, 53, 55, 7,117,110,105, 50, 49, 53, 56, 7,117,110,105, 50, 49, 53, 57, 7,117,110,
+105, 50, 49, 53, 65, 9,111,110,101,101,105,103,104,116,104, 12,116,104,114,101,101,101,105,103,104,116,104,115, 11,102,105,118,
+101,101,105,103,104,116,104,115, 12,115,101,118,101,110,101,105,103,104,116,104,115, 7,117,110,105, 50, 49, 53, 70, 7,117,110,
+105, 50, 49, 54, 48, 7,117,110,105, 50, 49, 54, 49, 7,117,110,105, 50, 49, 54, 50, 7,117,110,105, 50, 49, 54, 51, 7,117,110,
+105, 50, 49, 54, 52, 7,117,110,105, 50, 49, 54, 53, 7,117,110,105, 50, 49, 54, 54, 7,117,110,105, 50, 49, 54, 55, 7,117,110,
+105, 50, 49, 54, 56, 7,117,110,105, 50, 49, 54, 57, 7,117,110,105, 50, 49, 54, 65, 7,117,110,105, 50, 49, 54, 66, 7,117,110,
+105, 50, 49, 54, 67, 7,117,110,105, 50, 49, 54, 68, 7,117,110,105, 50, 49, 54, 69, 7,117,110,105, 50, 49, 54, 70, 7,117,110,
+105, 50, 49, 55, 48, 7,117,110,105, 50, 49, 55, 49, 7,117,110,105, 50, 49, 55, 50, 7,117,110,105, 50, 49, 55, 51, 7,117,110,
+105, 50, 49, 55, 52, 7,117,110,105, 50, 49, 55, 53, 7,117,110,105, 50, 49, 55, 54, 7,117,110,105, 50, 49, 55, 55, 7,117,110,
+105, 50, 49, 55, 56, 7,117,110,105, 50, 49, 55, 57, 7,117,110,105, 50, 49, 55, 65, 7,117,110,105, 50, 49, 55, 66, 7,117,110,
+105, 50, 49, 55, 67, 7,117,110,105, 50, 49, 55, 68, 7,117,110,105, 50, 49, 55, 69, 7,117,110,105, 50, 49, 55, 70, 7,117,110,
+105, 50, 49, 56, 48, 7,117,110,105, 50, 49, 56, 49, 7,117,110,105, 50, 49, 56, 50, 7,117,110,105, 50, 49, 56, 51, 9, 97,114,
+114,111,119,108,101,102,116, 7, 97,114,114,111,119,117,112, 10, 97,114,114,111,119,114,105,103,104,116, 9, 97,114,114,111,119,
+100,111,119,110, 9, 97,114,114,111,119, 98,111,116,104, 9, 97,114,114,111,119,117,112,100,110, 7,117,110,105, 50, 49, 57, 54,
+ 7,117,110,105, 50, 49, 57, 55, 7,117,110,105, 50, 49, 57, 56, 7,117,110,105, 50, 49, 57, 57, 14, 99, 97,114,114,105, 97,103,
+101,114,101,116,117,114,110, 7,117,110,105, 50, 50, 49, 51, 7,117,110,105, 50, 50, 49, 52, 7,117,110,105, 50, 50, 49, 54, 12,
+ 97,115,116,101,114,105,115,107,109, 97,116,104, 7,117,110,105, 50, 50, 49, 56, 7,117,110,105, 50, 50, 49, 66, 7,117,110,105,
+ 50, 50, 49, 67, 12,112,114,111,112,111,114,116,105,111,110, 97,108, 7,117,110,105, 50, 51, 49, 56, 7,117,110,105, 50, 51, 49,
+ 57, 7,117,110,105, 50, 51, 50, 53, 9, 97,110,103,108,101,108,101,102,116, 10, 97,110,103,108,101,114,105,103,104,116, 7,117,
+110,105, 50, 52, 54, 48, 7,117,110,105, 50, 52, 54, 49, 7,117,110,105, 50, 52, 54, 50, 7,117,110,105, 50, 52, 54, 51, 7,117,
+110,105, 50, 52, 54, 52, 7,117,110,105, 50, 52, 54, 53, 7,117,110,105, 50, 52, 54, 54, 7,117,110,105, 50, 52, 54, 55, 7,117,
+110,105, 50, 52, 54, 56, 7,117,110,105, 50, 52, 54, 57, 7,117,110,105, 50, 54, 66, 48, 7,117,110,105, 50, 54, 66, 49, 7,117,
+110,105, 50, 56, 48, 48, 7,117,110,105, 70, 66, 48, 48, 7,117,110,105, 70, 66, 48, 51, 7,117,110,105, 70, 66, 48, 52, 7,117,
+110,105, 70, 66, 48, 53, 7,117,110,105, 70, 66, 48, 54, 7,117,110,105, 70, 66, 49, 51, 7,117,110,105, 70, 66, 49, 52, 7,117,
+110,105, 70, 66, 49, 53, 7,117,110,105, 70, 66, 49, 54, 7,117,110,105, 70, 66, 49, 55, 7,117,110,105, 70, 70, 70, 68, 9,100,
+108, 76,116, 99, 97,114,111,110, 8, 68,105,101,114,101,115,105,115, 5, 65, 99,117,116,101, 5, 84,105,108,100,101, 5, 71,114,
+ 97,118,101, 10, 67,105,114, 99,117,109,102,108,101,120, 5, 67, 97,114,111,110, 12,117,110,105, 48, 51, 49, 49, 46, 99, 97,115,
+101, 5, 66,114,101,118,101, 9, 68,111,116, 97, 99, 99,101,110,116, 12, 72,117,110,103, 97,114,117,109,108, 97,117,116, 11, 68,
+111,117, 98,108,101, 97, 99,117,116,101, 11,117,110,105, 48, 51, 48, 56, 48, 51, 48, 52, 11,117,110,105, 48, 51, 48, 52, 48, 51,
+ 48, 56, 11,117,110,105, 48, 51, 48, 55, 48, 51, 48, 52, 11,117,110,105, 48, 51, 48, 56, 48, 51, 48, 49, 11,117,110,105, 48, 51,
+ 48, 56, 48, 51, 48, 48, 11,117,110,105, 48, 51, 48, 52, 48, 51, 48, 49, 11,117,110,105, 48, 51, 48, 52, 48, 51, 48, 48, 11,117,
+110,105, 48, 51, 48, 51, 48, 51, 48, 52, 11,117,110,105, 48, 51, 48, 56, 48, 51, 48, 67, 11,117,110,105, 48, 51, 48, 51, 48, 51,
+ 48, 56, 11,117,110,105, 48, 51, 48, 67, 48, 51, 48, 55, 11,117,110,105, 48, 51, 48, 51, 48, 51, 48, 49, 11,117,110,105, 48, 51,
+ 48, 50, 48, 51, 48, 49, 11,117,110,105, 48, 51, 48, 50, 48, 51, 48, 48, 11,117,110,105, 48, 51, 48, 50, 48, 51, 48, 51, 11,117,
+110,105, 48, 51, 48, 54, 48, 51, 48, 51, 11,117,110,105, 48, 51, 48, 54, 48, 51, 48, 49, 11,117,110,105, 48, 51, 48, 54, 48, 51,
+ 48, 48, 11,117,110,105, 48, 51, 48, 54, 48, 51, 48, 57, 11,117,110,105, 48, 51, 48, 50, 48, 51, 48, 57, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 20,108, 0, 0, 0, 16, 0, 0, 0, 7, 0, 1, 0, 2, 0, 0, 0, 1,255,255,255,255,
+ 0, 1, 0, 3, 0, 0, 0, 0,255,255,255,254, 0, 1, 0, 2, 0, 0, 0, 1,255,255,255,255, 0, 1, 0, 3, 0, 0, 0, 0,
+255,255,255,254, 0, 1, 0, 4, 0, 0, 0, 2,255,255,255,255, 0, 1, 0, 5, 0, 0, 0, 0,255,255,255,253, 0, 1, 0, 4,
+ 0, 0, 0, 2,255,255,255,255, 0, 1, 0, 5, 0, 0, 0, 0,255,255,255,253, 0, 1, 0, 4, 0, 0, 0, 2,255,255,255,255,
+ 0, 1, 0, 5, 0, 0, 0, 0,255,255,255,253, 0, 2, 0, 2, 0, 0, 0, 4,255,255,255,255, 0, 2, 0, 0, 0, 0, 0, 0,
+255,255,255,251, 0, 11, 0, 2, 0, 0, 0, 8,255,255,255,255, 0, 11, 0, 0, 0, 0, 0, 0,255,255,255,247, 0, 0, 0, 0,
+255,255,255,255,255,255,255,255, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,176, 64, 0, 0, 1, 0, 0, 0, 4,
+ 0, 0, 0, 6, 0, 0, 0, 20, 0, 0, 0,242, 0, 0, 1, 34, 0, 0, 1, 98, 0, 4, 0, 6, 0, 10, 0, 48, 0, 3, 0, 12,
+ 2, 92, 2, 72, 0, 78, 2, 97, 2, 94, 0,120, 2,104, 2,100, 0,128, 2,110, 2,107, 0,138, 2,123, 2,113, 0,146, 2,138,
+ 2,129, 0,168, 2,140, 2,140, 0,188, 2,154, 2,142, 0,190, 4,123, 4,123, 0,216, 5,253, 5,252, 0,218,255,255,255,255,
+ 0, 0, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5,
+ 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5,
+ 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5,
+ 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5,
+ 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 4, 0, 5, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 1, 0, 2, 0, 3, 0, 3, 0, 4, 0, 3, 0, 5, 0, 4, 0, 6, 0, 6, 0, 7, 0, 6, 0, 5,
+ 0, 7, 0, 0, 0, 0,255,255,255,255, 0, 2,128, 0,255,255, 0, 0, 0, 1, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 1,
+255,255, 0, 2, 0, 0,255,255,255,255, 0, 3,128, 0,255,255, 0, 2, 0, 0, 0, 0, 0, 3,255,255, 0, 3, 0, 0,255,255,
+255,255, 0, 0, 0, 16, 0, 0, 0, 28, 0, 0, 0, 40, 0, 0, 0, 52, 0, 4, 0, 6, 0, 0, 0, 0,255,255, 0, 0, 0, 4,
+ 0, 6, 0, 0, 0, 0,255,255, 0, 0, 0, 4, 0, 6, 0, 0, 0, 0,255,255, 0, 0, 0, 4, 0, 6, 0, 0, 0, 0,255,255,
+ 0, 0, 0, 0, 0, 0, 4, 52, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 22, 0, 0, 0, 28, 0, 0, 0,160, 0, 0, 2,132,
+ 0, 0, 3, 38, 0, 0, 3,186, 0, 0, 4, 4, 0, 4, 0, 6, 0, 13, 0, 48, 0, 3, 0, 30, 0, 3, 0, 3, 0, 96, 0, 17,
+ 0, 17, 0, 98, 0, 41, 0, 41, 0,100, 0, 81, 0, 81, 0,102, 0,114, 0,114, 0,104, 2, 21, 2, 21, 0,106, 2, 73, 2, 73,
+ 0,108, 2, 76, 2, 75, 0,110, 2, 80, 2, 78, 0,114, 2, 83, 2, 82, 0,120, 2,112, 2,111, 0,124, 5,159, 5,159, 0,128,
+ 5,162, 5,162, 0,130,255,255,255,255, 0, 0, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13,
+ 0, 14, 0, 15, 0, 16, 0, 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0,
+ 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 3, 0, 4, 0, 7, 0, 8,
+ 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16, 0, 5, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 17,
+ 0, 0, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 18, 0, 0, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 19, 0, 0, 0, 3, 0, 4,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 2, 0, 0, 0, 20, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 5, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 6, 0, 22, 0, 22, 0, 22, 0, 22, 0, 22, 0, 22, 0, 22, 0, 22,
+ 0, 22, 0, 22, 0, 22, 0, 22, 0, 22, 0, 22, 0, 22, 0, 22, 0, 22, 0, 22, 0, 22, 0, 22, 0, 23, 0, 22, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 0, 24, 0, 25, 0, 25, 0, 25, 0, 25, 0, 25, 0, 25, 0, 25, 0, 25, 0, 25, 0, 25, 0, 25, 0, 25,
+ 0, 25, 0, 25, 0, 25, 0, 25, 0, 25, 0, 25, 0, 25, 0, 25, 0, 25, 0, 26, 0, 0, 0, 0, 0, 0, 0, 2,128, 0, 0, 0,
+ 0, 3,128, 0, 0, 0, 0, 5,128, 0, 0, 0, 0, 6,128, 0, 0, 0, 0, 7,128, 0, 0, 0, 0, 9,128, 0, 0, 0, 0, 0,
+160, 0, 0, 0, 0, 0,160, 0, 0, 2, 0, 0,160, 0, 0, 4, 0, 0,160, 0, 0, 6, 0, 0,160, 0, 0, 8, 0, 0,160, 0,
+ 0, 10, 0, 0,160, 0, 0, 12, 0, 0,160, 0, 0, 14, 0, 0,160, 0, 0, 16, 0, 0,160, 0, 0, 18, 0, 4,128, 0, 0, 0,
+ 0, 0,160, 0, 0, 20, 0, 0,160, 0, 0, 23, 0, 0,160, 0, 0, 25, 0, 8,128, 0, 0, 0, 0, 0, 96, 0, 0, 27, 0, 0,
+160, 0, 0, 29, 0, 10,128, 0, 0, 0, 0, 0, 96, 0, 0, 32, 0, 0,160, 0, 0, 34, 63,255,253,183,191,255,255,254, 63,255,
+253,183,128, 0, 0, 0, 63,255,253,184,128, 0, 0, 2, 63,255,253,184,128, 0, 0, 4, 63,255,253,185,128, 0, 0, 6, 63,255,
+253,186,128, 0, 0, 8, 63,255,253,186,128, 0, 0, 10, 63,255,253,187,128, 0, 0, 12, 63,255,253,161,128, 0, 0, 14, 63,255,
+253,162,128, 0, 0, 16, 0, 0, 0, 3, 0, 0, 0, 4,128, 0, 0, 5, 63,255,255,238,191,255,255,166, 63,255,255,200,191,255,
+254, 5, 63,255,250,124,191,255,250,125, 63,255,250,126, 63,255,250,127,191,255,250,128, 63,255,250,126,191,255,250,127, 63,255,
+250,128, 63,255,250,129,191,255,250,130, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0,
+ 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 0, 0, 10, 0, 0, 0, 11, 0, 0, 0, 12,
+ 0, 0, 0, 13, 0, 0, 0, 0, 0, 14, 0, 0, 0, 15, 0, 0, 0, 0, 0, 16, 0,118, 2, 53, 0,113, 2, 49, 2, 50, 0,106,
+ 2, 51, 2, 54, 0,122, 2, 52, 5,155, 6, 3, 1, 11, 5,160, 5,161, 5,163, 5,164, 0, 0, 0, 0, 0,144, 0, 0, 0, 2,
+ 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 28, 0, 0, 0, 62, 0, 0, 0, 98, 0, 0, 0,116, 0, 0, 0,124, 0, 0, 0,128,
+ 0, 4, 0, 6, 0, 2, 0, 12, 0, 1, 0, 0, 4, 86, 4, 86, 0, 30, 4,115, 4,115, 0, 32,255,255,255,255, 0, 0, 0, 4,
+ 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2,128, 0, 0, 0, 0, 0,160, 0, 0, 0, 63,255,251,141,191,255,251,171,
+ 0, 0, 0, 0, 4,120, 0, 0, 0, 0, 1, 48, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 10, 0, 0, 0, 28, 0, 0, 0, 94,
+ 0, 0, 0,174, 0, 0, 0,222, 0, 0, 1, 6, 0, 0, 1, 26, 0, 4, 0, 6, 0, 6, 0, 24, 0, 2, 0, 12, 4, 86, 4, 86,
+ 0, 54, 4, 92, 4, 92, 0, 56, 4, 94, 4, 94, 0, 58, 4,101, 4,101, 0, 60, 4,103, 4,103, 0, 62, 4,111, 4,111, 0, 64,
+255,255,255,255, 0, 0, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 4, 0, 5, 0, 1, 0, 6, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 2,128, 0, 0, 0, 0, 3,128, 0, 0, 0, 0, 0,160, 0, 0, 0, 0, 0,160, 0, 0, 2,
+ 0, 0,160, 0, 0, 4, 0, 0,160, 0, 0, 6, 0, 0,160, 0, 0, 8, 63,255,251,170,191,255,251,156, 63,255,251,166,191,255,
+251,158, 63,255,251,166,191,255,251,160, 63,255,251,159,191,255,251,162, 63,255,251,161,191,255,251,154, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 6,126, 6,127, 6,129, 6,125, 6,128, 0, 0, 4,228, 0, 0, 0, 2,
+ 0, 0, 0, 2, 0, 0, 0, 23, 0, 0, 0, 28, 0, 0, 0,162, 0, 0, 3, 84, 0, 0, 3,246, 0, 0, 4,122, 0, 0, 4,188,
+ 0, 4, 0, 6, 0, 13, 0, 48, 0, 3, 0, 30, 0, 18, 0, 18, 0, 96, 0, 36, 0, 36, 0, 98, 0, 41, 0, 40, 0,100, 0, 48,
+ 0, 47, 0,104, 0, 55, 0, 53, 0,108, 0, 59, 0, 59, 0,114, 0, 68, 0, 68, 0,116, 0, 70, 0, 70, 0,118, 0, 73, 0, 73,
+ 0,120, 0, 76, 0, 76, 0,122, 0, 79, 0, 79, 0,124, 0, 82, 0, 82, 0,126, 0, 88, 0, 86, 0,128,255,255,255,255, 0, 0,
+ 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16, 0, 17, 0, 18, 0, 19,
+ 0, 20, 0, 21, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 3, 0, 4,
+ 0, 0, 0, 5, 0, 6, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 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, 2, 0, 3, 0, 4, 0, 0, 0, 5, 0, 6, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 3, 0, 4, 0, 0, 0, 5,
+ 0, 6, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 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, 2, 0, 3, 0, 4, 0, 10, 0, 5, 0, 6, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 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, 2, 0, 3, 0, 4, 0, 0, 0, 5, 0, 6, 0, 7,
+ 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, 1, 0, 0, 0, 12,
+ 0, 2, 0, 3, 0, 4, 0, 0, 0, 5, 0, 6, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 13, 0, 1, 0, 0, 0, 0, 0, 2, 0, 3, 0, 4, 0, 0, 0, 5, 0, 6, 0, 7, 0, 0, 0, 0,
+ 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 14, 0, 0, 0, 2, 0, 3,
+ 0, 4, 0, 0, 0, 5, 0, 6, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 3, 0, 4, 0, 0, 0, 5, 0, 6, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8,
+ 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, 2, 0, 3, 0, 4, 0, 0,
+ 0, 5, 0, 16, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 2, 0, 3, 0, 4, 0, 0, 0, 5, 0, 6, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 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, 2, 0, 3, 0, 4, 0, 0, 0, 5, 0, 6,
+ 0, 7, 0, 0, 0, 0, 0, 18, 0, 8, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 2, 0, 3, 0, 4, 0, 0, 0, 5, 0, 6, 0, 20, 0, 21, 0, 22, 0, 0, 0, 8, 0, 0, 0, 0, 0, 23, 0, 23,
+ 0, 23, 0, 23, 0, 23, 0, 23, 0, 23, 0, 23, 0, 23, 0, 23, 0, 23, 0, 23, 0, 23, 0, 23, 0, 23, 0, 23, 0, 23, 0, 24,
+ 0, 25, 0, 23, 0, 23, 0, 23, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2,
+ 0, 3, 0, 4, 0, 0, 0, 5, 0, 6, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+128, 0, 0, 0, 0, 4,128, 0, 0, 0, 0, 5,128, 0, 0, 0, 0, 6,128, 0, 0, 0, 0, 8,128, 0, 0, 0, 0, 10,128, 0,
+ 0, 0, 0, 12,128, 0, 0, 0, 0, 14,128, 0, 0, 0, 0, 3,128, 0, 0, 0, 0, 0,160, 0, 0, 0, 0, 0,160, 0, 0, 3,
+ 0, 0,160, 0, 0, 5, 0, 7,128, 0, 0, 0, 0, 0,160, 0, 0, 7, 0, 9,128, 0, 0, 0, 0, 0,160, 0, 0, 10, 0, 11,
+128, 0, 0, 0, 0, 0,160, 0, 0, 13, 0, 0,160, 0, 0, 16, 0, 13,128, 0, 0, 0, 0, 0,160, 0, 0, 19, 0, 0,160, 0,
+ 0, 21, 0, 0, 96, 0, 0, 23, 0, 0,160, 0, 0, 25, 0, 0,160, 0, 0, 28, 0, 0,160, 0, 0, 31, 63,255,255,197, 63,255,
+255,221,191,255,255,217, 63,255,255,173,191,255,255,207, 63,255,255,213,191,255,255,208, 63,255,255,216, 63,255,255,224,191,255,
+255,210, 63,255,255,196, 63,255,255,249,191,255,255,200, 63,255,255,187, 63,255,255,252,191,255,255,201, 63,255,255,184, 63,255,
+255,255,191,255,255,204, 63,255,255,199,191,255,255,203, 63,255,255,198,191,255,255,205, 63,255,255,206,191,255,255,207, 63,255,
+255,205, 63,255,255,209,191,255,255,210, 63,255,255,205, 63,255,255,212,191,255,255,213, 63,255,255,200,191,255,255,202, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 5, 0, 0,
+ 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 11, 0, 0, 0, 12,
+ 6, 25, 5,241, 6, 14, 6, 15, 5,254, 6, 1, 6, 2, 6,119, 6,120, 6,118, 6,121, 6,122, 6,124, 0, 0, 0, 0, 0,220,
+ 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 28, 0, 0, 0, 62, 0, 0, 0,110, 0, 0, 0,152, 0, 0, 0,184,
+ 0, 0, 0,200, 0, 4, 0, 6, 0, 2, 0, 12, 0, 1, 0, 0, 0, 4, 0, 4, 0, 30, 0, 34, 0, 34, 0, 32,255,255,255,255,
+ 0, 0, 0, 4, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, 0, 0, 2,128, 0,
+ 0, 0, 0, 3,128, 0, 0, 0, 0, 0,160, 0, 0, 0, 0, 0,160, 0, 0, 2, 0, 0,160, 0, 0, 4, 0, 0,160, 0, 0, 6,
+ 63,255,255,252,191,255,255,253, 63,255,255,224,191,255,255,255, 0, 0, 0, 0,191,255,255,227, 63,255,255,228,191,255,255,229,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 5,169, 5,182, 5,181, 5,180, 0, 0, 6, 56, 0, 0, 0, 2,
+ 0, 0, 0, 8, 0, 0, 0, 14, 0, 0, 0, 28, 0, 0, 0, 84, 0, 0, 2,132, 0, 0, 3,182, 0, 0, 5, 46, 0, 0, 5,234,
+ 0, 4, 0, 6, 0, 3, 0, 12, 0, 1, 0, 6, 0, 18, 0, 18, 0, 36, 0, 27, 0, 20, 0, 38, 5,177, 5,177, 0, 54,255,255,
+255,255, 0, 0, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 2, 0, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 1, 0, 2, 0, 3,
+ 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 8, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13,
+ 0, 14, 0, 9, 0, 15, 0, 9, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 16,
+ 0, 22, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 24,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 25, 0, 4, 0, 26, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 27, 0, 4, 0, 28, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 29, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 2, 0, 3, 0, 31, 0, 32, 0, 0, 0, 6, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 3,
+ 0, 34, 0, 35, 0, 0, 0, 6, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5,
+ 0, 0, 0, 6, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 39, 0, 0, 0, 6,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 40, 0, 0, 0, 6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 42, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 43, 0, 6, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 45, 0, 6, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 1,
+ 0, 2, 0, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 3,
+ 0, 4, 0, 5, 0, 0, 0, 6, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5,
+ 0, 0, 0, 6, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,128, 0, 0, 0, 0, 5,128, 0, 0, 0, 0, 8,128, 0, 0, 0,
+ 0, 11,128, 0, 0, 0, 0, 14,128, 0, 0, 0, 0, 17,128, 0, 0, 0, 0, 4,128, 0, 0, 0, 0, 3,128, 0, 0, 0, 0, 0,
+ 96, 0, 0, 0, 0, 0,160, 0, 0, 2, 0, 0,160, 0, 0, 5, 0, 0,160, 0, 0, 8, 0, 0,160, 0, 0, 11, 0, 0,160, 0,
+ 0, 14, 0, 0,160, 0, 0, 17, 0, 0, 96, 0, 0, 20, 0, 0,160, 0, 0, 22, 0, 0,160, 0, 0, 25, 0, 0,160, 0, 0, 28,
+ 0, 0,160, 0, 0, 31, 0, 0,160, 0, 0, 34, 0, 0,160, 0, 0, 37, 0, 7,128, 0, 0, 0, 0, 6,128, 0, 0, 0, 0, 0,
+160, 0, 0, 40, 0, 0,160, 0, 0, 43, 0, 0,160, 0, 0, 46, 0, 0,160, 0, 0, 49, 0, 10,128, 0, 0, 0, 0, 9,128, 0,
+ 0, 0, 0, 0,160, 0, 0, 52, 0, 0,160, 0, 0, 55, 0, 0,160, 0, 0, 58, 0, 0,160, 0, 0, 61, 0, 0,160, 0, 0, 64,
+ 0, 0,160, 0, 0, 67, 0, 13,128, 0, 0, 0, 0, 12,128, 0, 0, 0, 0, 0,160, 0, 0, 70, 0, 0,160, 0, 0, 73, 0, 16,
+128, 0, 0, 0, 0, 15,128, 0, 0, 0, 0, 0,160, 0, 0, 76, 0, 0,160, 0, 0, 79, 0, 0,160, 0, 0, 82, 0, 0,160, 0,
+ 0, 85, 0, 19,128, 0, 0, 0, 0, 18,128, 0, 0, 0, 0, 0,160, 0, 0, 88, 0, 0,160, 0, 0, 91, 63,255,250, 79,191,255,
+255,237, 63,255,255,237, 63,255,250, 82,191,255,255,240, 63,255,255,239, 63,255,250, 85,191,255,255,243, 63,255,255,241, 63,255,
+250, 88,191,255,255,246, 63,255,255,243, 63,255,250, 91,191,255,255,249, 63,255,255,245, 63,255,250, 94,191,255,255,252, 63,255,
+255,246, 63,255,250, 97,191,255,255,255, 0, 0, 0, 2,128, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 5,128, 0, 0, 4, 0, 0,
+ 0, 3, 0, 0, 0, 8,128, 0, 0, 7, 0, 0, 0, 5, 0, 0, 0, 11,128, 0, 0, 10, 0, 0, 0, 7, 0, 0, 0, 14,128, 0,
+ 0, 13, 0, 0, 0, 9, 0, 0, 0, 17,128, 0, 0, 16, 0, 0, 0, 10, 0, 0, 0, 20,128, 0, 0, 19, 0, 0, 0, 18, 63,255,
+250,120,128, 0, 0, 21, 0, 0, 0, 19, 63,255,250,123,128, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 29,128, 0, 0, 27, 0, 0,
+ 0, 25, 0, 0, 0, 32,128, 0, 0, 30, 0, 0, 0, 29, 63,255,250,132,128, 0, 0, 32, 0, 0, 0, 31, 63,255,250,135,128, 0,
+ 0, 35, 0, 0, 0, 31, 63,255,250,138,128, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 44,128, 0, 0, 41, 0, 0, 0, 40, 0, 0,
+ 0, 47,128, 0, 0, 44, 0, 0, 0, 40, 0, 0, 0, 50,128, 0, 0, 47, 0, 0, 0, 46, 63,255,250,150,128, 0, 0, 49, 0, 0,
+ 0, 49, 0, 0, 0, 56,128, 0, 0, 52, 0, 0, 0, 51, 63,255,250,156,128, 0, 0, 54, 0, 0, 0, 52, 63,255,250,159,128, 0,
+ 0, 57, 0, 0, 0, 57, 0, 0, 0, 65,128, 0, 0, 60, 0, 0, 0, 58, 0, 0, 0, 68,128, 0, 0, 63, 0, 0, 0, 61, 63,255,
+250,168,128, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 74,128, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0,
+ 0, 0, 0, 8, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0,
+ 0, 13, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 18,
+ 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 23, 0, 0,
+ 0, 0, 0, 24, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0,
+ 0, 29, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 31, 6, 39, 0,127, 6, 27, 0,126, 6, 29, 6, 33, 6, 35, 6, 39, 0,127,
+ 6, 27, 0,126, 6, 29, 6, 33, 6, 35, 6, 28, 6, 30, 6, 28, 6, 30, 0,128, 6, 31, 6, 36, 0,128, 6, 31, 6, 36, 6, 32,
+ 6, 32, 6, 34, 6, 37, 6, 34, 6, 37, 6, 38, 6, 38, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 60, 0, 0, 1, 0, 0, 1, 0, 2, 0, 0, 0, 64, 0, 0, 1, 1, 0, 2, 0, 1, 0, 0, 0, 72,192, 0, 1, 2,
+ 0, 11, 0, 1, 0, 0, 0, 76,192, 0, 1, 3, 0, 0, 1, 4, 0, 2, 1, 5, 0, 4, 1, 6, 0, 2, 1, 7, 0, 2, 1, 8,
+ 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 6, 0, 97, 1,128, 0, 6, 0,198, 0, 3, 0, 3, 0, 10, 0, 5, 0, 4, 0, 11,
+ 0, 8, 0, 6, 0, 5, 0, 10, 0, 9, 0, 11, 0, 11, 0, 11, 17, 11, 0, 12, 0, 12, 31, 11, 0, 13, 0, 13, 0, 11, 0, 14,
+ 0, 14, 0, 4, 0, 15, 0, 15, 0, 7, 0, 16, 0, 16, 0, 4, 0, 18, 0, 17, 0, 7, 0, 28, 0, 19, 0, 3, 0, 29, 0, 29,
+ 0, 7, 0, 30, 0, 30, 0, 11, 0, 31, 0, 31, 18, 11, 0, 32, 0, 32, 0, 11, 0, 33, 0, 33, 30, 11, 0, 35, 0, 34, 0, 11,
+ 0, 62, 0, 62, 18, 11, 0, 63, 0, 63, 0, 11, 0, 64, 0, 64, 30, 11, 0, 67, 0, 65, 0, 11, 0, 94, 0, 94, 18, 11, 0, 95,
+ 0, 95, 0, 11, 0, 96, 0, 96, 30, 11, 0, 97, 0, 97, 0, 11, 0, 98, 0, 98, 0, 7, 0, 99, 0, 99, 0, 11, 0,103, 0,100,
+ 0, 5, 0,107, 0,104, 0, 11, 0,113, 0,109, 0, 11, 0,115, 0,114, 0, 5, 0,117, 0,116, 0, 3, 0,118, 0,118, 0, 11,
+ 0,122, 0,120, 0, 11, 0,123, 0,123, 0, 3, 0,129, 0,125, 0, 11, 0,153, 0,153, 0, 11, 0,185, 0,185, 0, 11, 2, 19,
+ 2, 18, 0, 11, 2, 40, 2, 27, 0, 11, 2, 56, 2, 43, 0, 11, 2, 68, 2, 62, 0, 11, 2, 71, 2, 70, 0, 11, 2,154, 2, 72,
+128, 11, 2,156, 2,155, 0, 11, 2,160, 2,157,128, 11, 2,162, 2,161, 0, 11, 2,166, 2,164, 0, 11, 2,168, 2,168, 0, 11,
+ 3, 19, 3, 19, 0, 11, 3,163, 3,160,128, 11, 3,165, 3,164, 0, 11, 4,122, 4,122, 0, 11, 4,123, 4,123, 0, 7, 5,116,
+ 5,114, 0, 11, 5,127, 5,117, 0, 10, 5,130, 5,128, 0, 11, 5,132, 5,131, 0, 10, 5,156, 5,133, 0, 11, 5,161, 5,157,
+ 0, 5, 5,165, 5,162, 0, 11, 5,166, 5,166, 17, 11, 5,167, 5,167, 31, 11, 5,176, 5,168, 0, 11, 5,177, 5,177, 0, 7,
+ 5,178, 5,178, 17, 11, 5,179, 5,179, 31, 11, 5,203, 5,180, 0, 11, 5,204, 5,204, 0, 3, 5,211, 5,206, 0, 3, 5,213,
+ 5,212, 0, 4, 5,214, 5,214, 0, 11, 5,215, 5,215, 17, 11, 5,216, 5,216, 31, 11, 5,227, 5,218, 0, 3, 5,229, 5,228,
+ 0, 4, 5,230, 5,230, 0, 11, 5,231, 5,231, 17, 11, 5,232, 5,232, 31, 11, 5,251, 5,233, 0, 5, 5,253, 5,252,128, 11,
+ 6, 3, 5,254, 0, 11, 6, 10, 6, 8, 0, 11, 6, 16, 6, 13, 0, 11, 6, 18, 6, 18, 0, 11, 6, 21, 6, 21, 0, 5, 6, 22,
+ 6, 22, 0, 11, 6, 39, 6, 25, 0, 11, 6, 86, 6, 76, 0, 11, 6, 87, 6, 87, 0, 4, 6, 88, 6, 88, 0, 5, 6,102, 6, 89,
+ 0, 11, 6,103, 6,103, 17, 11, 6,104, 6,104, 31, 11, 6,116, 6,105, 0, 11, 6,130, 6,130, 0, 1,255,255,255,255, 0, 0,
+};
+
diff --git a/source/blender/editors/datafiles/blenderbuttons.c b/source/blender/editors/datafiles/blenderbuttons.c
new file mode 100644
index 00000000000..c29137ab74c
--- /dev/null
+++ b/source/blender/editors/datafiles/blenderbuttons.c
@@ -0,0 +1,4103 @@
+/* DataToC output of file <blenderbuttons> */
+
+int datatoc_blenderbuttons_size= 131097;
+char datatoc_blenderbuttons[]= {
+137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 2, 88, 0, 0, 2, 0, 8,
+ 6, 0, 0, 0, 94,187, 18, 70, 0, 0, 1, 57,105, 67, 67, 80, 80,104,111,116,111,115,104,111,112, 32, 73, 67, 67, 32,112,114,
+111,102,105,108,101, 0, 0,120,218,173,145,177, 74,195, 80, 20,134,191, 27, 69,197,161, 86, 8,226,224,112, 39, 81, 80,108,213,
+193,140, 73, 91,138, 32, 88,171, 67,146,173, 73, 67,149,210, 36,220,220,170,125, 8, 71,183, 14, 46,238, 62,129,147,163,224,160,
+248, 4,190,129,226,212,193, 33, 72,112, 18,193,111,250,206,207,225,112,224, 7,163, 98,215,157,134, 81,134, 65,172, 85,187,233,
+ 72,215,243,229,236, 19, 51, 76, 1, 64, 39,204, 82,187,213, 58, 0,136,147, 56,226, 39, 2, 62, 95, 17, 0,207,155,118,221,105,
+240, 55,230,195, 84,105, 96, 2,108,119,163, 44, 4, 81, 1,250, 23, 58,213, 32,198,128, 25,244, 83, 13,226, 14, 48,213, 73,187,
+ 6,226, 1, 40,245,114,127, 1, 74, 65,238,111, 64, 73,185,158, 15,226, 3, 48,123,174,231,131, 49, 7,152, 65,238, 43,128,169,
+163, 75, 13, 80, 75,210,145, 58,235,157,106, 89,181, 44, 75,218,221, 36,136,228,241, 40,211,209, 32,147,251,113,152,168, 52, 81,
+ 29, 29,117,129,252, 63, 0, 22,243,197,118,211,145,107, 85,203,218, 91,231,159,113, 61, 95,230,246,126,132, 0,196,210, 99,145,
+ 21,132, 67,117,254,221,133,177,243,251, 92,220, 24, 47,195,225, 45, 76, 79,138,108,247, 10,110, 54, 96,225,186,200, 86,171, 80,
+222,130,251,241, 23,194,179, 79,254, 28, 9,179, 39, 0, 0, 0, 6, 98, 75, 71, 68, 0, 0, 0, 0, 0, 0,249, 67,187,127, 0,
+ 0, 0, 9,112, 72, 89,115, 0, 0, 13,215, 0, 0, 13,215, 1, 66, 40,155,120, 0, 0, 0, 7,116, 73, 77, 69, 7,217, 3, 11,
+ 22, 59, 45, 8,130,118, 25, 0, 0, 32, 0, 73, 68, 65, 84,120,218,236, 93,119,120, 84, 85,226, 61,247,181,201,180,132, 20,146,
+ 64, 40, 65,138, 72, 9, 93,138, 32, 29,130, 16, 84, 64, 84,196, 31,224,234,162,171,162,226,170, 65, 69,176,145,192, 42, 32,184,
+148,197, 93, 68, 41, 10, 22, 52, 40, 44, 69,138, 52, 33,184, 2, 34,132, 22, 4, 66, 73, 34,144, 76, 50,153,246,230,254,254,200,
+188,231,100,152,242, 6, 38, 8,120,207,247,205, 55, 51,111,222, 59,115,251, 61,247,220,251,238, 35,148, 82, 84, 23, 8, 33,105,
+148,210,125,140,147,113, 50, 78,198,201, 56, 25, 39,227,100,156,127, 38,112, 87,144,168, 17, 87,100,132, 16,234,121,245,184,222,
+ 57,171, 49,238, 52,130,156, 61, 60,156,147,111,144,112,246,184, 94, 57,149,248, 70,146,215, 59, 13, 35,149,158, 94,225,164,145,
+ 14,103,117,113, 70,186, 94, 70,178,140,250,201,247,201, 55, 72, 56,123, 92,111,156,190,229, 39, 18,188,254,202,228,213,166,167,
+159,112,210, 72,135,179,186, 56, 35,221, 95, 70,170,140, 6,201,251,136,245, 77,215, 51,132, 63, 90, 96, 0, 0,165,148,120,241,
+147,235,149,211, 59, 29, 20,254, 72,134, 53,130,216, 24,105, 78,159,244,140, 20, 38, 83, 74, 9, 33,100, 19,128, 30,145,140,123,
+ 36,242,221, 39,174, 17,225,173, 78,113, 21,201,114, 95,221,156,145,170, 75,190,156,145, 40,247,254,242,189, 26,243, 40, 82,225,
+140, 72, 93,170,142, 50,239,167,252, 92, 53,175, 47,103, 36,234,146, 47,103, 36,202,253,181,224,140, 68, 93,242,199, 25,137,114,
+ 31, 40,239,153,131,117,109,132,128,111,197,238,121, 61, 11,161,106,118,177,122,220, 8,156, 17,206,163,201, 30,206, 72,142,102,
+122, 70, 42,143,124,203, 78, 36, 70, 93,222,156,145, 42,155,126,194,121,213,249,228,143,243,106,195, 27, 32,156, 17,143,251,213,
+150,251,107,197, 25,225, 60,138, 72, 93,242,225,236, 25,225, 65, 64,207, 72,214, 37,111,206, 72,213, 37, 63,225,188,234,124,242,
+199,121,181,225, 13, 16,206,136,199, 61,130,142,104,196,121,111, 58, 7,171, 58,197, 85,117,136, 55,101,148, 20,233,142, 44,146,
+ 34,171,186,156,182, 72,185, 56,126,120, 55, 69,144,110, 99,164,195,233, 9, 31,169, 14, 33, 76, 41,157, 76, 8,153,116, 61, 87,
+104, 86,151, 88, 93,186,222,234,146,191,114,115,181,117,169,186, 6,207,222,156,145, 18, 66,126,226,126, 85,117,201,247,218, 72,
+212,165, 16,156,164, 58,226, 31,233,250,116, 61,130,187, 94, 2, 82, 13,235,123,104,117,184, 98,213, 24,239, 72,134,179,231,141,
+ 16,247,234, 8, 39, 33,100,114, 53,197,253, 70, 73, 83, 86,151, 88, 93,186,238,234,146, 79,153,236, 25, 41,103, 40,210, 3, 41,
+ 95,206, 72,174, 67,138,100, 25,173,238,184, 71,178, 46, 85, 71,222,223, 40, 8,219,193,170,174,209,241,141,192, 89, 29,220,213,
+ 20,247, 77,213, 49, 58,168,134,117, 93, 17, 15, 39,165,116, 50, 34, 56,229,168,196, 57,146, 97,173,206,105,194,234, 40,155,213,
+ 89,222, 35,185,206,163,154,226,126,163,228,123,196,195, 25,169,186,228, 39,207,175, 58,172,254,210, 47,210, 83,216,145, 44,155,
+213,201, 25, 9,238,234, 8,103,117,229,253,141, 4, 82,157,219, 52, 48, 48, 48, 48, 48, 48, 48, 48,252, 25,225,215,193, 74, 75,
+ 75,219,208,177, 99,199,166, 63,254,248,163,131, 82, 10, 66, 8, 8, 33,224, 56, 14,132, 16,184,221,238, 51,187,119,239,190,131,
+ 37, 31, 3, 3,131,166,145, 28, 33, 28,126, 95,146,224,174, 28,204,178,209, 29, 3, 3,195, 77,220,238,249,107,227, 90,183,110,
+157,247,227,143, 63,214,249,239,127,255, 11,131,193, 0,147,201, 4,147,201, 4,179,217, 12,147,201,132, 65,131, 6,157,221,178,
+101, 75,163,112,255,236,150, 91,110, 57,228,114,185,106,133,165, 0, 5,161, 48, 63, 63,191, 41,165, 84,246,247,123,237,218,181,
+ 15, 17, 66,234,134,217,216, 23, 23, 20, 20, 52,164,148,186,174, 21,103,199,142, 29,243,101, 89, 78, 12,135, 83,167,211,157,218,
+182,109, 91, 83, 86, 76,175, 13,238,184,227,142, 67, 78,167, 51,236,242, 89,167, 78,157,166,203,151, 47,247, 91, 62, 59,117,234,
+116,220,237,118, 39,104, 44, 67, 0, 0,142,227,142,239,220,185,179, 77, 32, 1,210,174, 93,187,176,203, 39,128,194,220,220,220,
+ 6,129,126,108,211,166,205, 33,158,231, 35,202,169,160,125,251,246, 98,237,218,181, 23, 0,184, 47,216,121,162, 40, 22, 95,184,
+112,161,225,198,141, 27, 93,172, 52, 50, 48, 48,220,232,240,235, 96,185,221,238,211,143, 63,254,184,105,207,158, 61,129, 28,172,
+243, 87,242,103,118,187,189,110,254,186,117, 16,146,147, 65,237,118,184,226,226, 64, 41,133,219,237, 6,159,151, 7,234,112, 0,
+ 14, 7, 92,109,218, 0, 0,156, 78, 39,218,183,111,159,148,154,154, 42, 2,144, 3,208,214, 26, 55,110, 28,162,163,163, 81, 81,
+ 81,129,138,138, 10,216,108, 54,216,108, 54,216,237,118,216,237,118, 56, 28, 14, 56, 28, 14, 56,157, 78,216,108, 54,236,217,179,
+ 39, 54, 53, 53, 85, 0, 16,168, 33,175,245,244,211, 79,195,108, 54,171,124,202,187,194,225,205,103,179,217,240,211, 79, 63, 5,
+229,148,101, 57,113,211,166, 77, 48,153, 76,112,187,221,144,101, 25,178, 44,195,237,118,195,237,118, 43,233,238,125, 62,210,211,
+211,107,177, 34,122,237, 96,183,219,235,110,121,251,109,240, 53,107,130, 58,157,112, 53,111,174,230,143,248,253,247,128,211, 9,
+234,116,194,217,175,159, 90,110,239,190,251,238,164,162,162,162,128,229,211,229,114, 37,109,122,225, 5,112,209,209,160, 21, 21,
+ 48, 14, 25, 2, 84,218, 55, 40,157, 57, 19,212,233, 4,117, 56, 96,206,204, 4,165, 20, 69, 69, 69,214,180,180,180,253,168, 92,
+167, 64, 3, 8,177, 90,235,215,175, 87,203, 12,165, 20,138, 22, 83,234, 41,207,243,234,235,135, 31,126,192,243,207, 63, 31, 84,
+220,243, 60, 95,107,244,232,209,112, 56, 28,106,221, 81, 62, 59,157, 78,181,188,187, 92, 46, 56,157, 78,216,237,118,156, 58,117,
+ 42,228,128, 65, 17, 87,245,234,213, 27, 48,125,250,116,228,228,228,224,150, 91,110,129, 36, 73,106,248,148,240, 62,251,236,179,
+177,158, 54,137, 9, 44, 6, 6,134,155, 83, 96,237,219,183,175, 55, 0, 12, 29, 58,116, 67, 90, 90, 90,211, 95,126,249,197,161,
+ 52,222,158, 87,237,135, 30,122, 40, 95,105,204, 41,165,103, 62,254,248, 99, 77, 83,134, 66,114, 50,242,227,227, 1, 0,151,114,
+115,149, 17, 59,162,219,182, 85,207,113,252,242, 11, 56,142, 67, 74, 74,138, 58,170, 15, 6,179,217,140,254,253,251, 67,167,211,
+161,125,251,246,144, 36, 9,162, 40, 6,124,105,129,209,104,196,235,175,191,174,184, 20, 48,233,163,240,183, 59, 59, 67, 79,128,
+255,252,244, 11,108,178, 27,130, 32, 64, 16, 4,205,156, 38,147, 9,159,126,250, 41, 36, 73,242,251, 90,191,126, 61,238,185,231,
+ 30, 72,146,132,248,248,120,252,153, 54,100,187, 94,192,215,172,137,211,237,218, 93, 94, 62, 7, 15,190,172,124, 38, 37, 37,105,
+ 42,159, 92,116, 52,206,222,117, 23, 0,160, 96,243,102,232,116, 58, 72,146,132,152, 55,223, 4, 21, 69,112,146, 4,199, 99,143,
+193, 98,177, 88, 71,143, 30,189,221,104, 52,174,253,237,183,223,130,114,202,178,140,157, 59,119, 66,146, 36, 68, 69, 69, 93,246,
+210,233,116,136,138,138,194,178,101,203,112,242,228, 73, 77,113,183, 90,173,120,251,237,183, 65, 8,169, 82,135, 2,125,214,224,
+200,113, 3, 7, 14,156, 91,183,110,221,126,211,167, 79, 55, 73,146,132, 57,115,230, 64, 16, 4, 12, 26, 52, 8,241,241,241, 88,
+187,118, 45, 36, 73,194, 11, 47,188,192, 10, 31, 3, 3,195,205, 47,176,188, 26,200, 58,175,190,250,106,141,197,139, 23, 35, 42,
+ 42, 10, 6,131, 1, 70,163, 17, 70,163,177,202,231, 87, 94,121, 69,214,250,135,212,110,175,218,249,112, 28, 56,142, 11,120, 76,
+ 75, 7,102,183,219, 49,124,248,112, 0, 8, 41,174,180,138, 33,155,205, 6, 65, 16,208,168,126, 34, 94, 29,222, 1, 93,121, 10,
+107, 49,128,162, 50,140,174, 45,224,127,117,111,197,236, 95,139,113,162,196, 2, 65,208,118, 51,166, 44,203, 1,197,149, 36, 73,
+248,248,227,143, 49,124,248,112, 72,146,116, 89,154, 48, 92, 27, 80,167, 51,172,242,169,137,179,162, 66,177,137, 84,113,165,211,
+233, 0,157, 14,156, 40,130, 72, 18, 44, 22,139,117,232,208,161,187, 12, 6,195,146,196,196,196,130, 80,162,136, 82,138,168,168,
+168,203, 4,150, 78,167, 83,197,213,242,229,203,177,120,241, 98,116,234,212, 73,115,153,151, 36, 9, 79, 61,245,212,101,191,173,
+ 92,185, 82, 21, 88,130, 32, 64,146,164, 80,226,138, 0,224, 68, 81,188,255, 31,255,248, 7,167,156,159,144,144, 0, 81, 20,145,
+150,150, 6,179,217,140,173, 91,183,170,245,130,129,129,129, 33, 8, 68, 0,109, 0, 36,162,114,198,160, 20, 64,172,215,239,133,
+158,247, 68,175,239,187,252,240,220,238, 57, 71,249, 93,249,110, 7,160,243,115,188, 24,128,193,243,178, 1,216, 6,160,165,215,
+255, 40,215,193,247,127, 5, 79, 99,216, 3,192, 70, 0, 61,189, 55,191,163,148,158,126,235,173,183, 76,126, 28,172, 42,211,134,
+148, 82,205, 83,134,114,124,188,234, 12,212,104,223,254,247,198,253,231,159,213,142, 75,236,218, 21,196,104, 4,222,121, 71, 19,
+167,221,110,199,249,243,231, 47, 27,121, 95,169,192, 34,132,192,233,116,194, 96,136,194,119,243,187,227,204, 49, 23,222,206, 57,
+137,149, 63, 28,135, 32, 8,200,184,173, 9,134,185,128,236,120, 61,198,186,100, 56,220,218,214,234,186, 92, 46,191, 78,128,242,
+ 34,132, 84,249,204,112,237,225,106,222, 92,115,249, 36, 47,191,172,137,211, 56,100, 8,206,108,217, 2, 73,146,144,208,175, 31,
+224,113,173,132, 93,187, 32, 73, 18,202,202,202,172, 15,116,236,248,253, 5,189,126,241,160, 65,131,142,175, 93,187,214, 24, 82,
+180, 81, 90, 69, 76,121,187, 86,222,226, 74, 20, 69, 56,125, 68, 99, 48,129, 21,168,126, 40,229, 53, 28, 7, 11, 0,220,110, 55,
+253,246,219,111, 49,103,206, 28, 36, 36, 36,160,127,255,254,168, 85,171, 22,150, 47, 95, 14, 74, 41,158,122,234, 41, 24, 12, 6,
+ 24, 12, 6, 86,230, 25, 24,254,164, 8,164, 65,124,208,125,194,132, 9, 29,178,179,179,167,116,233,210,101,217,182,109,219,150,
+ 18, 66,114,188,218,196, 12, 15, 87,142,215,247,219,125, 68,150, 8, 32,145, 16,146,163,156,239,253,221,235,120, 95, 0, 58,229,
+251,132, 9, 19, 90,102,103,103, 79,201,204,204,124, 57, 43, 43, 75,154, 48, 97, 66,171,236,236,236, 41,202,255,248, 11,135,183,
+131,229,119, 23,224,207, 63,255,188,183,111, 12,155, 55,111,190,161,115,231,206, 77,247,236,217,227, 45,186,106,223,126,251,237,
+249,148,210,144,119, 23, 42,107,186, 2,185, 2, 28,199,129,152, 76,128,201,164, 53, 99,224,116, 58, 33, 8, 2, 56,142,195,218,
+181,107, 97, 48, 24, 48,112,224,192,128, 2, 75,171, 43,166,211, 73, 16, 98, 57,252,223,244,221, 40,186, 80,174, 78, 9,174,203,
+ 63,137, 31,244,122,188,218,162, 53,204,150,124,148,216,236, 97, 57, 88, 58,157, 78,237,172, 36, 73,194,147, 79, 62, 9,187,221,
+ 14,142,227,212, 99, 30,225,202,122,156, 63,166,178,107, 42,159, 84,163,139,229,118,187,127,119,173, 36, 9,156, 36,129,120,242,
+185,172,172,204, 58,100,200,144, 93, 23,244,250,197,167, 78,157,250, 1,128, 94,171,192, 82, 68,149,194,237, 79, 92, 9,130, 0,
+135,195,161,121,160, 18,200, 73, 10, 87, 96,209,202, 6,197, 13,128, 54,104,208, 64,189, 38, 57, 57, 25,177,177,177,234,218, 54,
+189, 94, 15,131,193,192, 28, 44, 6,134, 63, 55,180, 60,137, 32, 42, 59, 59,123,138,183,128,241, 21, 52,222,194,201, 71, 68,121,
+139,180,150, 33,218,255, 28, 95,209,164,252, 47, 33, 36, 39, 43, 43, 43, 35, 68, 56, 10,125, 5,150,230,109,246,121,158,175, 51,
+127,254,252, 26, 95,126,249, 37,204,102, 51, 98, 99, 99, 17, 19, 19,131,216,216, 88, 12, 27, 54, 44,228, 84,161,219,237, 14, 56,
+237,194,243,124,165, 96, 51,155, 43, 59, 49,141, 29,152,195,225,128, 40,138,224, 56, 14, 79, 60,241,132,186, 46,234,106,166, 8,
+237,118, 59,120,142, 7,162,110, 1,197, 78, 85, 92,169, 47,157, 14,249,245, 91,131,156, 61, 13, 65,208, 54, 67,234,118,187,213,
+ 78, 79, 20, 69,188,246,218,107,120,247,221,119,171,220, 64, 32,138, 34,218,182,109,139,188,188, 60, 86,229,254, 0,132, 85, 62,
+ 5, 65,147, 88, 87,220, 38, 73,146,192,233,116, 32, 30,129, 85, 86, 86,102, 29, 49, 98,196,247, 37, 37, 37,139,155, 54,109,122,
+ 4,149,219, 24,104, 18,213,132, 16,149, 83,175,215, 7, 20, 87,130, 32,104,118,176,148,122,228,141,191,254,245,175, 85,222, 1,
+224,169,167,158,210, 90,143, 40, 0,136,162,136,190,125,251,162, 85,171, 86, 88,185,114, 37,220,110, 55,158,124,242, 73, 24, 12,
+ 6,204,156, 57, 19, 46,151, 11, 83,167, 78,101,133,143,129,225,207, 61,176, 13,165, 65,172,153,153,153, 47, 19, 66,114, 60, 78,
+210,254, 32, 66,202, 31,110,247, 17,105,133, 1,218,235, 12,127, 34,203,251,179,130, 9, 19, 38,180,244, 19,142, 93,151, 9, 44,
+ 47,245, 24,170, 3, 58, 61,118,236, 88,147,178, 71,150, 34, 12,120,158,215,116,119, 33,119,232, 16,204,158, 5,237,246, 3, 7,
+126, 23, 22,221,187,131,152, 76, 32, 70, 35,184, 85,171, 42, 59,174,216, 88,224,165,151, 66,166,154,211,233, 84, 5, 86,113,113,
+113, 68,214, 96, 57,157, 78,240,146,136, 29,102, 17, 84,228,171,136, 43, 81, 20,193, 9, 34,242, 19,111, 5, 17,254, 11, 65,214,
+118,211,147, 34,176,148, 23,199,113,120,246,217,103,213, 52,224, 56, 14, 93,187,118, 85,132, 44,171,113,127, 0,132, 45, 91, 96,
+206,200,208, 84, 62, 73,116, 52,240,239,127,135,228, 44,155, 51, 7,209,111,191, 13, 34,138, 16,118,236,128, 78,167,131,197, 98,
+177,222,211,182,237, 46, 75,108,236,226, 19, 39, 78,252, 0,128, 27, 62,124,120,141, 14, 29, 58,240, 26, 27, 35,191,211,130, 75,
+151, 46,173, 34,174, 4, 65,128,203,165,173,124, 6,115,176,252,185, 89, 26,132, 37,189,251,238,187,193,243, 60,106,212,168,129,
+232,232,104,245,238, 75,197,185,114,185, 92,112,185, 92,154,215, 49, 50, 48, 48,220,156,208,160, 65,108, 89, 89, 89,251,179,178,
+178, 84, 39,201,215,193, 10,128, 65, 30, 49,149,168,136, 51, 84,174,165,218, 21, 36, 44, 25,129,132,151,247,177,236,236,236, 41,
+126,194,161, 78, 75, 6,220,104,180, 83,167, 78, 77,189,183,105,224,121, 30,178, 44,159,249,249,231,159,175,106,131, 81,234, 53,
+ 93,225, 45,206, 20, 87,128,152, 76, 97, 47, 34, 86,166, 8,121,158, 87,197,203,162, 69,139, 96, 54,155, 49,102,204,152,171, 16,
+ 88, 60,190,146,242, 0, 73,184,204,193,226, 69, 17,191,214,168, 7, 78, 20, 33,200, 78, 77, 78, 70, 73, 73, 9, 36, 73,194,123,
+239,189,135, 87, 94,121, 69, 73, 83,213, 29,241, 22, 90, 12,127, 80, 37,247,114,123, 66,149, 79,158,231,161,105,175, 76,151, 11,
+144, 36,192, 51,149,103,177, 88,172, 35, 70,140,248,222, 18, 27,187,184,113,227,198,138,115,197, 25,141, 70,240, 60,175,201,193,
+226, 56,206,175,184, 82,234,129, 90, 78,121, 62, 44, 7, 75,146, 36,172, 90,181, 74,173, 43,222,206, 85,184, 2,203, 59,172,155,
+ 55,111,198,158, 61,123,240,196, 19, 79,192, 96, 48, 96,214,172, 89,112,185, 92,120,227,141, 55, 96, 48, 24, 42,167, 79, 25, 24,
+ 24, 24, 2, 35, 78, 17, 56, 30,145, 84,197, 89,162,148,102,120,139,160, 64, 83,133, 30,199,105,115,136,255, 90,229, 17,102,126,
+161, 56,105, 62,131,222, 28, 95,113, 38, 40,202,209,251,157,227,184, 58,243,230,205,171,177,121,243,102, 24,141, 70,117,163,209,
+ 17, 35, 70,200, 87,157, 68,138,192,242, 76,183,168,194,194,211,129,113, 94, 29,152,214, 69,175,138,131,229, 45,176, 38, 77,154,
+ 4, 65, 16,176, 96,193, 2, 0,192,223,255,254,247,176, 4,150,195,225, 0,117, 3,219,228,141, 72,153,211, 26,244, 67, 61,206,
+109,254, 5,162, 40,162, 86,199,126,112,119, 24,134, 98, 93, 12, 76,212,173,121,244,125,225,194, 5, 28, 56,112, 0,132, 16,188,
+254,250,235, 85,246, 0,242, 94,227, 3, 0,107,215,174, 5,254, 68,207,108,186,238, 4,150,134,242,169, 56, 73, 90, 56,137, 78,
+ 7,222, 35,174,134, 12, 25,178,171,164,164,100,241,137, 19, 39,118, 1, 32, 35, 71,142,172, 97, 52, 26,177,112,225, 66, 43, 0,
+113,197,138, 21, 6, 45,162,197,159,184,242, 39,176,100, 89, 14,171, 30,133, 26,140, 92,137,192, 34,132, 64,150,101,213,185,114,
+ 58,157,234,247,168,168, 40, 86,240, 24, 24,254,228,238,149,247,123, 0, 20,250,172,115, 34, 62, 78, 83,161, 63, 97,229, 61, 29,
+232,245,217,233,135,215,238, 51,117,232,123, 92,121, 47,206,202,202,250, 78,113,174,188,142, 87, 9, 71, 64, 7,139, 82,170,110,
+ 52,170,116, 34, 28,199, 65,150,229,243, 87,155,144,174, 54,109,224, 60,120, 16, 60,207, 67,234,217,179,114, 45,139,209, 8,110,
+229,202,223, 59,174, 73,147, 64, 77, 38,208, 1, 3,180,113,122,238,206,243, 22, 88, 23, 47, 94,132, 40,138,120,235,173,183,192,
+113, 28,166, 78,157,138, 58,117,234,224,204,153, 51, 88,189,122,181, 38, 78,206,205, 65, 63, 58, 30,250,177,209,224,158,104,140,
+150,131,199,226, 82,105, 3,236,181,155,208,172, 44, 15,113, 27, 38,193, 33,107,159,222,112, 58,157,234,222, 69,148, 82,213,189,
+ 82,166, 77,100, 89, 86, 55,117,156, 54,109, 26,216,147, 68,174, 61, 28,125,250,104, 46,159,238,158,218, 30, 8,111,120,246, 89,
+ 56, 70,143,134,197, 98,177, 62,208,165,203,214, 18,189,254,227,230,205,155,171,107,174,140, 70, 35,244,122, 61, 81,156, 44, 45,
+156,202, 77, 29,161,196,149,242, 89,107,249,244,222,134, 33, 18, 2, 75,105, 59,198,140, 25,131,218,181,107, 99,246,236,217, 85,
+156,171,151, 95,126, 25, 78,167, 19, 51,103,206,100,133,143,129,129, 33, 24,118,133,113,238,237, 94, 98,105,215, 21,242,238,186,
+218, 0,251,109,121,247,238,221,219, 59,208, 5,222,211,135, 74, 3, 74, 41, 61,179,103,207,158, 59,252, 52,174,105,148,210,125,
+222,199,100, 89,254,125, 81,183,201, 84,233, 12, 24,141, 85, 28, 28,106, 54,131, 51,155, 1, 63,119,252,249,227, 84, 4, 22,199,
+113, 85, 70,223,130, 32,224,210,165, 75, 16, 69, 17,179,103,207, 70, 76, 76, 12,108, 54, 27,180,132,211,225,112,128,231,121,148,
+159, 40,199,241,137,123, 17,101, 58,130,166,253,162, 17, 45, 30, 69,147, 45, 95,194,229,178, 3, 94, 83,134, 90, 56, 27, 54,108,
+136,241,227,199,171,139,147,125, 95,222,113,165,148,226,246,219,111, 15,201,121,181, 96,156, 85, 57,189,239,114, 13, 85, 62, 57,
+159, 60, 11, 22, 78,229,110,193, 50,147,233,227, 19,199,142,237, 2,192,141, 28, 57, 50,198,104, 52, 98,254,252,249, 86, 0,220,
+155,111,190,105,104,208,160, 1,175, 37,156, 60,207, 95, 38,174,194, 17, 88,129,234,145,239,246, 33,207, 60,243,204,101, 27,141,
+ 6, 18, 88,129,226,206,243, 60,106,214,172, 9,163,209, 8,151,203,165, 58, 87,122,189, 94,221, 29, 62,208, 96,130,149, 79,198,
+201, 56,255, 60,156,127,144, 24,171, 54,132,189,178, 84,153, 62,220,177, 99, 7,162,163,163, 81,163, 70,141,176,166, 14,157, 78,
+ 39, 18, 19, 19, 65, 41,133,144,157, 13,160,242,201,175,118, 81, 84, 31,249, 33,246,238, 13, 55,199,193, 82, 94, 14,135,195, 17,
+114, 26,198,106,181, 86, 89,128,174,136, 43,239,142,193, 98,177,168,155,135,106,129,194,169,184, 98, 68,166, 56,182,110,197,229,
+119, 19,134,177,147,187, 44,203, 72, 74, 74,170,178,134, 71,233, 4,253,116,212, 0,155, 34,188,230,112, 58,157,136,243, 60,194,
+ 73,204,204, 4, 8, 1, 37, 4, 54,143,211,232,114,185, 32,118,233, 2,202,243, 40,177, 90,225,112, 56,160,215,235,131,114, 22,
+ 23, 23, 91, 31,124,240,193,239, 41,165, 31, 13, 30, 60, 56, 15,149, 11, 44,169,201,100,210,241, 60, 79, 1,252, 6,128,158, 63,
+127,190,198,185,115,231,220, 46,151,171, 94,168,112,238,216,177, 3,199,142, 29, 67,187,118,237,212,199,215, 40, 47,229, 17, 76,
+ 87,226, 96,249,219,163,237, 74,119,114,247,106, 51, 80,163, 70, 13,232,116, 58,188,245,214, 91,144, 36, 9, 6, 67,229, 44,232,
+204,153, 51, 43,211, 58, 12, 62, 6, 6, 6,134, 27, 1, 97, 11, 44,101,250,240,199, 31,127,116, 40,141,167,214,141, 70, 37, 73,
+ 42,108,213,170, 85, 88, 15, 60,150, 36,233,226,137, 19, 39, 92, 65, 84,244,217,141, 27, 55,134,245,144, 90,158,231, 67,114,238,
+216,177, 35, 44, 78,142,227,130,114,138,162, 88,152,158,158, 30, 86,220,163,162,162,206,179, 34,122,237, 32,138, 98,225,160, 65,
+131,252,231,209,172, 89,129,174,185,136, 32,207,206, 19, 69,241, 88,203,150, 45,127, 49,153, 76,223, 38, 36, 36,252,182,101,203,
+150,132,118,237,218, 85,121,248,115,187,118,237,106,249,148, 37, 59, 2, 60,135,208,131,179, 47,190,248, 98,184,229,179, 48,196,
+104,244,236,217,179,103,195,173, 71,133, 33, 27, 24, 65, 56, 59,110,220,184,186, 90,235, 58,216,115, 8, 25, 24, 24,254,172, 2,
+ 43,216,244, 97, 40,228,231,231, 55,136,116, 4, 78,159, 62,221,244, 70,224,220,177, 99, 71, 3, 86,220,174,111, 84, 71, 30,237,
+216,177, 35, 45,210,156,185,185,185, 17, 47,159,187,119,239,110, 90, 29,105,250,217,103,159, 53,101, 37,139,129,129,225,207, 8,
+182, 31, 0, 3, 3, 3, 3, 3, 3, 3, 3, 19, 88, 12, 12, 12, 12, 12, 12, 12, 12,215, 55, 8, 0,191, 83, 24,225,220, 29, 64,
+ 8, 9,123, 26, 36, 20, 63,227,100,156,140,147,113, 50, 78,198,201, 56,111, 62,206, 80,220,215,241,221,137,225, 9,172,234,220,
+107,137,221,194,202, 56, 25, 39,227,100,156,140,147,113, 50,206, 63, 35,216, 20, 33, 3, 3, 3, 3, 3, 3, 3, 3, 19, 88, 55,
+ 7,136,214,231, 0, 49, 48, 48, 48, 48, 48, 48,220,112, 8,184, 77, 67,199,142, 29,243,101, 89, 14,107,223, 38, 81, 20, 11,181,
+222,234, 78, 8, 17, 82, 82, 82,134, 24, 12,134, 30,162, 40,118, 1, 0,167,211,185,221,106,181,110, 42, 40, 40,248,130, 82,122,
+ 69,251,225, 36, 39, 39, 55,224, 56,238, 33, 66,200,112, 0,160,148, 46,119,187,221, 75,206,157, 59,151,127,189, 8, 43, 73,146,
+ 38,222,121,231,157,119, 18, 66, 22, 82, 74,151, 68,144,251,130,191,227,148,210,184, 43,229,172, 95,191,126,172,203,229,234, 0,
+160,173,231,208,143,130, 32,236,254,245,215, 95, 47,178,234,115,115,224, 74,234, 58, 80,185,175,221,246,237,219, 27, 68,146, 83,
+167,211,157,218,182,109,155,223,173, 29, 58,117,234,116,200,229,114,213,141,100, 56, 59,117,234,148,239,114,185,194, 14,103, 84,
+ 84,212,169,173, 91,183, 54,141, 36,231,181, 14,103, 32,116,232,208,225,115, 74,105,186,167, 77, 89,179,123,247,238,161,172,150,
+ 48, 48, 68, 80, 96,201,178,156,184,105,211, 38,152, 76, 38,165,147,134, 44,203,234, 46,209,110,183, 91,125,134,158,178,195,117,
+255,254,253, 53, 53, 0,245,234,213,107,209,180,105,211,197, 79, 61,245, 84,189,193,131, 7,235,146,147,147, 65, 8,193,217,179,
+103, 27,231,228,228, 60, 48,123,246,236,151,235,213,171, 55,242,228,201,147, 63,107,225, 75, 76, 76, 52, 73,146,116, 47,165,116,
+100,235,214,173,239,120,225,133, 23, 72,215,174, 93, 33,203, 50, 54,108,216, 48, 97,250,244,233,153, 41, 41, 41,219, 8, 33,139,
+ 29, 14,199,151,133,133,133,101,127, 96,154,247, 30, 55,110,220, 3,127,251,219,223,106, 62,250,232,163,255, 7, 96, 73, 4,185,
+117, 17, 20,107, 66,237,218,181,199, 3,200,244,229,117,185, 92,246,148,148,148,236, 51,103,206, 76,191, 82, 33,204,112,253,192,
+187,174, 43,207,196,116,185, 92,106,221,150,101, 89,125,202,130, 98,188, 82, 74,209,183,111,223,196,112, 56,149,118, 67,225, 5,
+ 0,183,219,237,125, 13,210,211,211,107, 5,226,116,187,221,181, 20, 78,239,112, 41,124,190,235, 73,149,176,222,121,231,157, 1,
+195,233,114,185, 18,191,255,254,123,232,245,122,149,203, 55,140,222,188,202, 67,171,123,245,234, 85, 43, 92, 78,229,179, 63, 78,
+ 0,232,218,181,235, 53, 13,167,151,120, 75,114,185, 92,179, 8, 33, 58,158,231, 95,160,148,166,175, 94,189, 26,178, 44, 99,208,
+160, 65,233,157, 58,117,106, 44,203,242, 63,140, 70,163,219,102,179, 61,177,115,231, 78,182, 1, 50, 3,195,213, 8, 44, 0, 48,
+153, 76, 88,186,116,169,250,120, 12,223, 71,209,120,127, 78, 77, 77,213,244,135,181,107,215,110,215,160, 65,131, 53, 95,124,241,
+133, 33, 41, 41, 73, 61,238,112, 56, 16, 19, 19,131, 49, 99,198,232,250,246,237,219,120,228,200,145, 27,107,215,174,157,126,230,
+204,153, 61,193,248,234,212,169,243,120, 82, 82,210,155,227,199,143, 55,220,125,247,221,136,139,171,106,214,100,100,100, 96,224,
+192,129,228,216,177, 99, 93,151, 47, 95,222,245,163,143, 62,122,183, 78,157, 58,175,157, 62,125,122, 94,168,176,214,173, 91, 55,
+ 78,175,215,191,159,156,156,156,118,252,248,241,109, 58,157,238,197,138,138,138,167,106,215,174, 61,194, 98,177,156,180,217,108,
+ 79,254,250,235,175,199,195, 17, 45,241,241,241,127, 31, 59,118,108,124,105,105,169,156,155,155,123, 88, 57,174,215,235,159,239,
+220,185,115,199,239,190,251,110, 9,165,244,243, 43,113,174, 92, 46,215,238, 96,191,107,117,178, 90,180,104, 33,213,174, 93,123,
+ 13,128,142,131, 7, 15, 62, 49,121,242,100, 26, 27, 27, 27,205,113, 28, 41, 46, 46,190, 48,109,218, 52,233,211, 79, 63,157, 84,
+187,118,237,244, 22, 45, 90,164,255,252,243,207, 14, 86,149,110,108,152, 76, 38,124,242,201, 39, 85, 30,135,227,253,220, 65,223,
+199,229,196,199,199, 87, 11, 39,165, 52,232,212,185,193, 96,192,134, 13, 27, 46,123, 52, 86,160,151,217,108, 6, 33, 4,132, 16,
+ 66, 3,220,209,163,215,235,177,110,221, 58,245, 65,215,161, 56,141, 70, 35, 16, 98,121, 69,184,156,102,179, 57,100,122, 94, 97,
+ 56, 67, 46, 69,112,185, 92,179,166, 77,155, 54, 40, 58, 58, 26, 47,189,244,210,255, 82, 83, 83, 17, 19, 19,131,249,243,231, 35,
+ 46, 46, 14,178, 44,255,239,157,119,222, 33, 39, 79,158,196,204,153, 51,231, 2, 24,194,106, 12, 3,195, 85, 10, 44, 0, 85, 26,
+193, 96, 2,203, 31,124,239, 48,104,208,160, 65,148,217,108, 94,242,213, 87, 95, 25, 18, 18,126,127, 90,136,221,110, 71,105,105,
+ 41, 44, 22, 11, 74, 75, 75, 97, 50,153, 48,103,206, 28,195, 67, 15, 61,180,164, 65,131, 6,173,243,243,243,109,129, 56, 41,165,
+217, 63,253,244,147,232,114,185,160,211,249, 55,112, 56,142, 67,227,198,141,241,204, 51,207,160, 91,183,110,198, 7, 31,124, 48,
+ 27,192,188, 64,156, 94,194,228,195, 45, 91,182,116, 73, 74, 74,210,127,249,229,151,250, 57,115,230,228, 13, 28, 56,208, 50,106,
+212,168,218, 23, 47, 94,172,157,145,145,241, 53,128, 22, 90,226,238,193, 3,227,199,143,111, 17, 23, 23,199, 77,155, 54,237, 98,
+105,105,233, 7,158,227, 79,205,156, 57,115, 84,143, 30, 61,106, 62,250,232,163,110, 66,200, 23,254, 58,131, 32,119,108,232, 60,
+241, 20,194,117,182,252,113, 94,188,120,241,101, 0, 29, 23, 45, 90,180,175, 79,159, 62,245, 41,165,197, 0,206, 2, 64, 82, 82,
+146,126,250,244,233,198, 30, 61,122,252,248,196, 19, 79,116,244,156, 59, 89, 99, 56,175, 24,140,179,122, 57,221,110, 55, 68, 81,
+196,176, 97,195, 64, 8,169,242, 28, 67,165,158,111,217,178, 5,253,251,247,135, 40,138,120,244,209, 71, 53,115, 62,248,224,131,
+112,185, 92,151,113,174, 95,191,190,138,208,226, 56, 78, 51,167,242,140,208, 80, 47,173,156, 90, 69,203,245,194,217,171, 87, 47,
+236,220,185,243,170, 57,149,102,254,167,159,126, 66,235,214,173,177,120,241, 98,194,243, 60,118,238,220, 9,131,193,128,209,163,
+ 71, 35, 45, 45,141, 24, 12, 6, 28, 59,118, 12, 22,139,133,176,122,196, 56,171,139, 51, 4, 68, 0,109, 0, 36, 2,144, 1,148,
+ 2,136, 5, 96,247,244,113,197, 0, 12,158,151, 13,128, 5, 64, 77,207,181, 69,158,193,134,247, 99,202, 10, 81,245,161,208,183,
+123,184,149, 71,128,121, 59,202,118,159,126, 84,249,238,251, 94,133, 91,240, 8, 9,165, 51,239, 73, 41,221,228,149,128,154,196,
+149, 40,138,208,178,102,219,237,118,143,205,204,204, 76,242, 22, 87, 54,155,173,138,184,178, 88, 44, 40, 40, 40, 64,253,250,245,
+ 49,124,248,240,164, 69,139, 22,141, 5,240, 94,176, 68,231,121, 30, 63,252,240, 3,206,159, 63,143, 86,173, 90,225,150, 91,110,
+169,114,194,209,163, 71,241,205, 55,223,224,194,133, 11,104,223,190,189,146, 81,126,145,146,146,146, 16, 27, 27, 59,142,227,184,
+251, 59,117,234,148, 82, 88, 88, 72,206,158, 61,139,212,212,212,228, 47,190,248, 2,123,247,238, 53,231,230,230,194,225,112, 72,
+ 93,186,116,169,223,188,121,243, 19,162, 40,174, 58,119,238,220,187,193,214,121, 17, 66,248,186,117,235,190,252,248,227,143,235,
+ 10, 10, 10,220, 31,125,244,209,119,148,210,189,132,144,251, 95,121,229,149,199,210,211,211,107,238,217,179,167,116,215,174, 93,
+ 59,168,198,189, 51,252, 56, 87,130,111,131,108,177, 88,112,226,196,137,221, 37, 37, 37,156,231,124, 59,165,180, 86, 16,215,174,
+ 17,128,241,247,223,127,255, 97,143,184,250,213, 83,152, 1, 0,178, 44, 59, 75, 75, 75,203,122,244,232, 81,187,111,223,190, 7,
+215,173, 91, 55,190,110,221,186,139, 79,157, 58,117,148,141, 87,110, 92,184, 92, 46,136,162,136,111,191,253, 54,168,219,180,117,
+235, 86,213,113, 89,177, 98,133, 38,206,175,190,250, 42,164,131, 21, 70, 27,162,138, 7,223,135,174,207,157, 59, 23,227,198,141,
+171,114,204,227, 94, 81, 79,227, 74, 3,113, 6, 18, 66,183, 52,108,136,179,103,206, 84,225,228, 56,174,202,212,102, 48,206,143,
+ 62,250, 8, 25, 25, 25,200,201,201, 9,250,126,215, 93,119,105,138,187, 34,174, 28, 14,135, 26,198, 35, 71,142,248,229,253,231,
+ 63,255, 9, 45, 77, 9,207,243,227,151, 45, 91,246,211,133, 11, 23,132,220,220, 92,232,245,122, 24, 12, 6,245,253,236,217,179,
+176,219,237,248,244,211, 79, 93, 28,199, 61,207,106, 11, 67,164, 17, 72,131,248,160,251,132, 9, 19, 58,100,103,103, 79,233,210,
+165,203,178,109,219,182, 45, 37,132,228, 80, 74, 51,148,247, 9, 19, 38,180,204,206,206,158,146,153,153,249,114, 86, 86,214,126,
+ 66, 72, 14, 0,248,126,247,232,155, 12, 31,241,150,168,240,120,194, 84,229, 92,127,223,125,223,125,185, 5,175, 3,196,171, 33,
+ 82, 58, 83,205, 2,203,223,104,201, 23,209,209,209, 3, 6, 12, 24, 32, 5, 19, 87,165,165,165, 40, 45, 45,197,161, 67,135,144,
+150,150, 38, 69, 71, 71, 15, 8, 33,176, 42,149,133, 32, 32, 37, 37, 5, 69, 69, 69,216,183,111, 31, 82, 83, 83,225,116, 58,177,
+102,205, 26, 92,188,120, 81,109,216,237,118,123, 80,158,164,164,164,217, 15, 61,244,208,192,177, 99,199,242,255,253,239,127,209,
+172, 89, 51,220,114,203, 45,216,182,109, 27, 28, 14, 7,234,213,171,135, 46, 93,186, 96,197,138, 21,104,211,166, 13,247,215,191,
+254,181,230,254,253,251, 71,207,154, 53,171, 51,128,118, 65,168,219, 12, 29, 58,180,102,116,116, 52,198,141, 27, 71,237,118,251,
+ 12, 66, 72,218,176, 97,195, 38, 63,253,244,211, 9,249,249,249,142,199, 30,123,108,187,221,110,159, 31, 70,185, 12,232, 92,185,
+ 92, 46, 88, 44, 22,148,148,148,160,180,180, 84, 40, 41, 41,225,160, 97,141,150,219,237,190, 19, 0, 63,113,226, 68, 80, 74,127,
+243, 22, 87,118,187, 29, 22,139, 5, 22,139,197, 45,203,242,165,177, 99,199, 90,215,173, 91,199,123,174, 97, 2,235, 6,134, 82,
+215,135, 14, 29, 90,197, 29, 90,191,126, 61, 50, 50, 50, 46,155,230,211, 34, 8, 20,206, 7, 30,120, 64, 21, 70, 74,155,177,122,
+245,106, 77,142, 75, 32,145,225,207,193,226, 56,206,239,177, 80, 34, 67,225,244,247, 2,112, 25,167, 86, 33, 40, 8, 2,198,142,
+ 29, 11, 81, 20,241,220,115,207, 65, 20, 69,164,165,165, 65, 20, 69,116,234,212, 9,162, 40,162, 87,175, 94, 97,115,110,222,188,
+ 25,157, 59,119, 86,195,152,150,150,134,118,237,218, 65, 20, 69,116,235,214, 13,162, 40,162,127,255,254,154, 56,149, 5,237,105,
+105,105,120,226,137, 39,240,197, 23, 95, 96,209,162, 69,234,239,195,134, 13,195,208,161, 67, 97,177, 88,144,156,156, 44, 20, 20,
+ 20,236,239,208,161, 3, 91,248,206, 16,113,248,211, 32, 62,136,202,206,206,158,226, 35,140,170, 64,249,157, 16,146,147,149,149,
+149,225, 45,134,188,191,123,185, 76,222,226,173,165,183, 3,229, 45,158, 2,136, 50,223,240,123,159, 95, 88, 69, 96,121, 34,214,
+211, 95, 3, 41, 73,146,218,160, 5, 18, 90, 90, 80, 81, 81,209, 74,113,175, 42, 42, 42,170, 8, 42, 79,199,173,126,182,219,237,
+104,216,176, 33, 42, 42, 42, 90,133,169,132, 81,187,118,109, 56, 28, 14, 44, 88,176, 64, 21, 86, 10, 28, 14, 71,168, 76,174,221,
+187,119,111, 62, 63, 63, 31,167, 79,159,134,219,237,198,246,237,219, 33,138, 34,172, 86, 43,108, 54, 27, 86,172, 88, 1,158,231,
+113,244,232, 81,232,245,122,180,110,221,154,200,178, 28, 27, 34,104, 61,122,247,238, 13, 66, 8, 86,175, 94,125,156, 82,154,103,
+ 52, 26, 23, 78,153, 50, 37,206,102,179,185, 71,141, 26,117,252,183,223,126,123, 25,128, 75,175,215, 79,236,209,163, 71,215,117,
+235,214,125,236,114,185, 22,135, 91, 80,109, 54, 91,149,180, 44, 41, 41,193,165, 75,151,180, 94,222, 22, 0, 98, 98, 98,106, 2,
+ 56,163, 28, 44, 47, 47, 71,121,121, 57, 74, 74, 74, 80, 94, 94, 14,171,213,234, 48, 26,141, 58,175,107,254,195,154,136, 27, 95,
+ 96,173, 94,189,186,138,203, 36,138, 34, 54,108,216,112,153, 3,165,211,233,176,106,213, 42, 77,110,211,215, 95,127, 29,212,185,
+242,110, 99, 66,173,193,242, 22, 67, 31,124, 80, 57,195,254,204, 51,207,248,157, 54,244, 94,186,112,223,125,247,145, 80,225, 20,
+ 69, 17,105,111,114, 0,100,252,250,142, 65,109,215,124, 57,181,184, 66, 10,231,252,249,243, 53, 57, 88, 3, 7, 14,212,204,233,
+ 27,174,125,251,246,249,229,157, 59,119,110,200,244, 84, 22,180,199,196,196,168,211,130, 0,144,145,145,241,188,217,108,238, 86,
+ 81, 81,113, 79, 78, 78, 14, 46, 94,188,136,134, 13, 27, 34, 41, 41, 9, 59,119,238, 76,103, 53,134,161,154, 92,172,158, 65, 78,
+177,102,102,102,190, 76, 8,201, 81, 28, 41, 95,167,201,223,119, 63,255,163,136, 32,101,122,240,118, 31,241,166, 76, 29, 14, 10,
+114,173,221, 71, 80,249, 78, 17,238, 10,233, 96, 41,115,254,222, 13, 87, 32,129,165,101,244, 73, 41,229, 9, 33, 85, 4, 64, 32,
+ 7,203,233,116,162,184,184, 24,148, 82, 62,146,153, 24, 74, 96, 21, 23, 23,191,240,212, 83, 79,173,156, 49, 99, 70,204, 3, 15,
+ 60,128,239,191,255, 30,205,155, 55,135,205,102, 67, 66, 66, 2,142, 31, 63, 14,158,231,145,151,151,135,212,212, 84,152, 76, 38,
+188,246,218,107, 22,171,213,250, 90, 48, 94, 73,146,122,118,239,222, 29,185,185,185,184,112,225,194,122, 66, 72,227,199, 30,123,
+236,174,186,117,235,114,111,191,253,182,237,240,225,195,211, 0, 92, 52,155,205,239,125,244,209, 71,253,218,181,107,103, 26, 53,
+106, 20, 37,132, 44,163,148,202, 90,227, 87, 86, 86,118,153,184, 82,190,107, 28, 69,136,132, 16, 74, 8, 81,231, 64, 20,241,171,
+188, 74, 74, 74, 96,179,217,168,211,233,228, 42, 47,161, 34,107, 30,110,108, 40,157,247,240,225,195, 47,155, 46,147, 36, 9,107,
+214,172,193,208,161, 67,161,211,233, 32, 73,146, 50,213, 30,170, 44, 65, 20, 69,140, 24, 49, 66, 21, 4, 95,125,245,149, 95,113,
+165,184, 82, 90, 57,121,158,199,211, 79, 63, 13, 81, 20, 49,103,206, 28, 60,251,236,179,224, 56, 14,211,167, 79, 7,207,243,152,
+ 56,113,162,191,233,135,160,156,162, 40,226,104, 86,229,123,253,191, 91, 80, 52,167,242, 38,156,152, 26, 53, 42,207, 11, 49, 45,
+232,143,211,159,115, 37, 8, 2,122,246,236, 9, 81, 20, 53, 9, 43,127,225, 60,112,224,128,250,185, 83,167, 78,232,218,181, 43,
+ 68, 81, 68,191,126,253, 84, 94,173, 79,233,144,101, 25,243,231,207, 87,167, 5, 61,121,213,121,252,248,241,247,248, 59,191, 69,
+139, 22,172,194, 48,252, 17, 14,150, 45, 43, 43,107,127, 86, 86,150, 95,135,202,215, 73, 10,230, 52,121, 9,171, 93,240, 76, 13,
+102,102,102,190,140,202,181, 91,187, 52, 92,171,243,157, 34,244,119,190,175,131,245,122,160,209, 98, 48,129,165,172, 75, 8, 5,
+163,209,184,191,168,168,168, 83, 84, 84,148,218,241,251, 19, 39, 80,170,230, 0, 0, 32, 0, 73, 68, 65, 84, 87, 22,139, 5, 60,
+207,227,252,249,243, 48, 26,141,251, 35,153,137,161,166, 8, 79,157, 58,181,171,110,221,186,143,252,245,175,127, 29,111,183,219,
+ 91, 10,130, 32,217,108, 54,221,215, 95,127, 77,214,172, 89,131, 90,181,106,225,153,103,158,161, 22,139,197, 65, 8,177,139,162,
+120,188,172,172,108,222,241,227,199,131, 58, 77,141, 27, 55,190,213,100, 50, 97,235,214,173, 0,176, 3,192,195, 79, 60,241, 4,
+231,116, 58, 49,119,238,220,115, 0,182,198,198,198,126,188,124,249,242, 14,173, 91,183,214,173, 93,187,214,178,115,231,206,117,
+ 90,197,149,178,222,202, 59, 13,189,211,184,164,164, 68, 83,250,112, 28,247, 63, 74,233,200,242,242,242, 18,131,193,160, 47, 41,
+ 41,113,120, 59,140, 22,139, 5,101,101,101,144,101, 89, 56,119,238,220, 41, 0,205, 56,142,251, 31,107, 30,110, 14,129,181,106,
+213,170,128,110,147,226,110, 41, 3,170, 53,107,214,104,114,197, 86,174, 92,121,153, 43,230,235, 10,105,157, 38,163,148, 86, 89,
+115, 5, 64, 29, 0,114, 28,135,204,204, 76,232,245,122,188,245,214, 91,200,204,204, 84, 93,172,162,162, 34,162,133,179,209, 4,
+155,167,141,133,122,173,195,110,175, 12, 31,199,105, 22, 89,222,156,190, 47,239,184,135,217, 1, 85,225,136, 4, 39,128, 85,131,
+ 6, 13, 26, 20, 23, 23,135,209,163, 71,195,104, 52, 98,200,144, 33,168,168,168, 24, 6, 0,217,217,217,152, 48, 97, 2, 0, 96,
+210,164, 73,152, 60,121, 50,202,203,203,109,172,198, 48, 84,147,131,245,122,144, 83,226,188,215, 84,133,193,155,227,125,190,194,
+225, 43,138, 60,142,216,230, 80, 92,254,174, 13, 4, 65, 81,142,193, 42,116, 40,247, 74, 25, 81,106,112, 87, 54,110,220,184,177,
+253,189,247,222, 43,120,119,252,190, 66,203, 51,223,143,163, 71,143,186,202,202,202, 54,106, 25,129, 69,202,193,242,136,172, 53,
+ 0,212,222, 35, 33, 33, 97,137,197, 98, 25,152,148,148, 36,218,237,118, 92,186,116,233,232,145, 35, 71, 90,135, 83,120, 76, 38,
+147, 30, 0, 46, 94,188, 8, 0, 23, 1, 52,185,245,214, 91,145,155,155,139,223,126,251, 45, 7, 64,191,201,147, 39,119,236,220,
+185,179,184,108,217, 50,235,147, 79, 62,249,169,195,225,152,165, 53, 78,254, 28,193,178,178, 50, 92,186,116, 9,229,229,229,154,
+167, 8, 9, 33,219, 40,165,152, 50,101, 74,201,228,201,147, 27,148,148,148,148, 93,186,116, 73,246,118,198,202,203,203,137,209,
+104, 20,150, 46, 93, 26,173, 92,195,154,135,155, 67, 96, 93,233, 29,111,161, 28, 44,111,183, 74, 17, 90, 58,157, 14,203,151, 47,
+247, 93, 43, 21, 82,101, 41,174,213, 51,207, 60, 3,189, 94,143,247,222,123, 79,109,131,252,221,209, 76, 8,241,123,247,155,111,
+ 56, 27,191,108, 71,193,204, 88,136,162,136,196, 39, 11,171, 76,197,249,171, 42, 90,194,249,143,127,252, 35, 98, 83,132,106, 56,
+ 27, 55, 6, 0,204,159, 63, 31,195,135, 15,199,214,173, 91, 3, 78, 17,134, 10,103,110,110,238,253,237,218,181,107,228,114,185,
+246,180,106,213, 74, 56,123,246, 44,134, 14, 29,138,229,203,151,195,211,145, 33, 51, 51,179,202, 53, 22,139,133, 9, 44,134,136,
+187, 87, 26, 78, 43,244, 89, 63, 69,188,167,235,130,188,251,158, 15,175, 99,222,188,133, 0,156,126,254,175,208,143,168,242,253,
+ 15,239,115, 10, 47,115,176,180, 52,186,193,196,150, 22,129, 69, 8,153, 61,105,210,164,177,221,186,117,139,139,137,137, 65, 65,
+ 65,129, 95, 7, 43, 38, 38, 6, 14,135, 3, 27, 55,110, 44, 37,132,204, 14, 65,235,114, 58,157, 66, 82, 82, 18,138,138,138, 2,
+222,221,195,113, 28, 12, 6, 3, 44, 22, 11, 0,132,187, 57,166,189,180,180,212, 57, 98,196, 8,113,246,236,217,176, 90,173, 97,
+ 53, 48,132, 16,174,103,207,158, 18, 80,185,150, 9, 64, 89,157, 58,117, 26,233,245,122,228,231,231, 3,192,113, 0,189, 6, 12,
+ 24, 32, 20, 23, 23,211,177, 99,199,174,119,187,221,175, 80, 74, 67, 13,151,227, 1, 32, 58, 58,250, 12, 0,108,223,190,253, 23,
+127,235,218, 94,126,249,229,102,158,206, 43, 30, 1,238,164,242, 18,151,251, 83, 82, 82, 62, 92,180,104,209,232, 30, 61,122,108,
+111,211,166, 77,195, 11, 23, 46, 92,178, 88, 44,246,242,242,114, 74, 41, 21,140, 70,163,184,101,203,150,188,188,188,188, 12, 0,
+ 31,158, 58,117,106, 63,107, 34,110,124, 68, 82, 92,121, 11, 2, 95, 7,203,247, 61, 28, 78, 37,156,227,199,143,199,251,239,191,
+ 15, 74,169, 42,172, 56,142,195,148, 41, 83, 0, 0,175,188,242, 74,192,237, 99, 2,113, 22,204, 52, 32,229,217,139, 85,142, 1,
+ 0,241,132,239, 74,166, 8, 39, 77,154, 4, 81, 20,171, 76,225, 9,130,160, 10,170,112,166, 8,213,112, 22, 20, 84,138,192,196,
+ 68, 60,244,208, 67,232,215,175, 31,238,186,235, 46, 16, 66,170,240,106,157, 34,228, 56,238,157,169, 83,167, 10,122,189, 30,118,
+187, 29,229,229,229, 40, 46, 46, 70, 32, 7,203,106,181, 70,177,218,194,240, 7, 96,215, 53,230,189,234,255, 19,180, 52, 18, 87,
+186, 77,131,239,211,182,143, 29, 59, 86,146,146,146, 50,102,196,136, 17,203,230,204,153, 99,104,212,168, 17, 14, 30, 60,136, 11,
+ 23, 46,192,225,112, 64,146, 36,164,164,164,192, 98,177,224,179,207, 62, 43,183, 90,173, 99, 10, 10, 10, 74,130,113, 18, 66,222,
+ 24, 48, 96,192,164,137, 19, 39,242, 45, 90,180,192,133, 11, 23, 96,177, 88,212,198,133, 16,130,152,152, 24, 24,141, 70,236,219,
+183, 15, 59,118,236,144, 9, 33,111, 4,227,244,211,168,157, 60,126,252,184,123,214,172, 89,168,168,168,176,185, 92,174, 83, 26,
+ 68,149, 55,167,193,179,233, 31,202,202,202, 0,192, 86,191,126,253, 20, 79,154, 0,192,175,141, 27, 55,126,181, 81,163, 70,228,
+227,143, 63,166,110,183,123,157, 63,113,229, 27, 78, 74,169,205,115, 92,167,184, 99,190,107,218, 74, 74, 74, 32,203,178,206,251,
+252, 80,113,119, 58,157, 47,137,162,216,109,204,152, 49, 93, 6, 13, 26,244,211,200,145, 35, 43, 98, 99, 99, 19,120,158,183, 30,
+ 61,122,244,183,229,203,151, 71, 29, 57,114, 36, 3,192, 49,167,211,249,146, 22,206, 8,216,199,140,179, 26, 57,149,186, 30,108,
+223,166, 80,131,168, 64,156,163, 70,141, 82, 5,150,242, 82,156, 43, 95, 78, 63,187,177, 95, 22,119,101, 90,236,197, 23, 95,172,
+ 18,190, 87, 95,125, 53, 96,216,108, 54, 27,209,194,121, 97,126,237,170, 11,218, 3,136, 42,173,225,124,253,245,215,175,216,193,
+ 10, 22,206,222,189,123,195, 98,177, 64, 16, 4,172, 93,187, 54,216, 34,119, 45,101,169, 98,245,234,213,208,235,245,248,236,179,
+207, 92,201,201,201, 66,108,108,108, 64, 7,171,162,162, 34,138,213, 35,198, 89, 29,156, 55, 27,130, 10, 44,151,203,133,122,245,
+234,169,226,137,227, 56,101, 95, 25,240, 60, 15,142,227,192,243, 60,194,121,110,113, 65, 65,193,250,148,148,148, 17, 67,134, 12,
+249,207,232,209,163,205,205,154, 53, 19, 83, 83, 83, 97,181, 90,145,159,159,143,252,252,124,215,134, 13, 27, 74,173, 86,235, 35,
+ 5, 5, 5,235, 67,241,157, 62,125,250,221,148,148,148, 85, 15, 63,252,240,155,109,218,180, 25, 56,126,252,120, 52,108,216, 16,
+151, 46, 93, 66, 92, 92, 28,146,146,146,112,252,248,113,172, 88,177, 2,151, 46, 93,250, 6,192,196,130,130,130,188,112, 18,201,
+ 96, 48,204,152, 58,117,106,247,228,228,228,102,197,197,197,167, 36, 73,122, 57,220,132,118, 56, 28, 50, 0,190,168,168, 8, 0,
+172, 6,131,129, 0,192,145, 35, 71, 0,224,215,250,245,235,199, 0,192,250,245,235, 9,128,157, 97,210,199, 3,192,128, 1, 3,
+126,243,109,252,189,156, 43,205, 40, 44, 44, 44,107,220,184,113, 87,171,213,154,181,106,213,170,209, 1,238, 22,251,208, 96, 48,
+ 76, 56,114,228, 72, 25,171, 70, 55, 73, 99, 32, 8,208,233,116, 87, 36,174,130,113,126,246,217,103,126,157, 43, 95, 78,173,237,
+136,175, 8, 84,246,187, 10, 54, 80, 12,209, 81,248,141,115, 32, 78, 45,225, 84, 56,179,179,179, 33,138, 34,250,246,237, 91,101,
+ 81,251,149, 56, 88, 10,167,242, 4, 12,179,217, 12, 89,150, 49,112,224,192,171,226,165,148, 62,157,147,147,227,162,148, 26, 57,
+142,251,123, 65, 65,193,126,197, 85,244,231, 96, 49, 48, 48, 92,165,192, 18, 69,177, 80,235,179, 5, 21,232,116,186, 66,141, 34,
+107, 93,227,198,141,155, 47, 88,176,224, 73,179,217,220,203,106,181,166,121,132,204, 62,139,197,242,157, 32, 8,255, 44, 40, 40,
+ 40,213,250,191, 30,193, 52, 60, 37, 37,165,203,195, 15, 63,252,230, 29,119,220,209,233,177,199, 30,131, 32, 8,248,244,211, 79,
+113,250,244,233,157, 30, 97,181,253, 74, 18,233,216,177, 99, 37, 8,126,251,104,168, 6,172, 76, 20,197,121,221,186,117,123,108,
+219,182,109, 31, 80, 74,207,232,245,250,127,247,236,217,115,212,247,223,127,255, 31, 74,233, 73, 81, 20, 63,232,218,181,235,152,
+157, 59,119,126, 76, 41, 61, 17, 38,191, 45, 88,195,239,207,185, 10,133, 35, 71,142,148, 2,120,178,118,237,218,239,243, 60,223,
+ 85,150,229,182, 0,192,243,252,143,178, 44,111, 61,115,230,204, 65, 86,125,110, 30,184,221,110, 36, 38, 38, 86, 25, 52, 41, 83,
+111, 87, 42,174,220,110, 55,146,146,146,192,113,156,202,171,108, 16, 26,100, 90,144, 4, 19, 24,110,183, 27,209,209,209, 42,167,
+ 50,232, 11, 81, 63,168,221,110, 15,186, 6, 43, 92, 78,132, 88,219,116,133,156,208,194,105,183,219, 35, 22, 78, 0,200,205,205,
+ 45, 6,240,176,242,189,125,251,246,171, 14, 30, 60, 56, 40,144,131,197,192,192,112,149, 2,107,199,142, 29, 13,170,243,143, 61,
+ 29,120,150,231, 21, 17,120, 4, 84,239,148,148,148,140,109,219,182, 41, 83, 87, 83, 11, 10, 10,114,254,232,132,118, 58,157,147,
+ 9, 33,111, 83, 74,157, 0, 80, 81, 81,241, 10, 33,100,146,242,176,100,167,211, 57,145, 16,242,250,213, 60, 60,153, 82,106,140,
+116,184, 61, 66,138,137,169,155, 24,162, 40, 22, 14, 24, 48, 32, 49,220,235,130, 13,168, 68, 81, 44, 76, 79, 79, 15,155, 51, 42,
+ 42,234,124, 16,206,179,189,122,245,170,123, 5,225,188, 88,167, 78, 29,191,119,194, 72,146, 84,216,189,123,247,136,134,243, 74,
+ 57,131,165,103,117,132, 51,136,224,186, 63, 37, 37,101, 91, 66, 66, 66, 35,155,205, 38, 89,173, 86,201,219, 5, 52, 24, 12, 69,
+172,214, 48, 48, 92,133,192,186,145,225, 17, 84, 57,215, 91,184, 20,113,229,245,221, 21,236, 59, 3,195,181, 64,117, 12,166,170,
+131,115,235,214,173, 77, 35,205,185,125,251,246, 6,127, 86,206, 16,109,232, 29,172,102, 48, 48, 92, 29, 56,150, 4, 12, 12, 12,
+ 12, 12, 12, 12, 12,145, 5, 1,144,230,239,135,112,238, 14, 32,132,164,133,251,199,161,248, 25, 39,227,100,156,140,147,113, 50,
+ 78,198,121,243,113,134,226,190, 89,238, 78, 36, 90,247, 74,185, 34,114,118, 11, 43,227,100,156,140,147,113, 50, 78,198,201, 56,
+255,132, 96, 83,132, 12, 12, 12, 12, 12, 12, 12, 12, 76, 96, 49, 48, 48, 48, 48, 48, 48, 48, 48,129,197,192,192,192,192,192,192,
+192,192, 4, 22, 3, 3, 3, 3, 3, 3, 3, 3, 3, 19, 88, 12, 12, 12, 12, 12, 12, 12, 12,215, 13,170,245, 46, 66, 6, 6, 6,
+ 6, 6, 6, 6,134, 63, 35, 84, 7,139, 16,178,137, 16,178,137, 37, 9, 3, 3, 3, 3, 3, 3,195,181,196,205,168, 65, 4, 79,
+196, 40,174,226, 97,198, 12, 12, 12, 12, 12, 12, 12, 12, 87, 40,174,110, 74, 13, 66, 40,165, 32,132, 80, 74, 41, 97,217,204,192,
+192,192,192,192,192,112,173, 5,214,205,168, 65,216, 34,119, 6, 6, 6, 6, 6, 6, 6,134,106, 18, 88,175,179, 53, 88, 12, 12,
+ 12, 12, 12, 12, 12,127, 0,110, 74, 13,162,222, 69, 72, 8,233, 1, 0,148, 82, 38,178, 24, 24, 24, 24, 24, 24, 24,174,157, 24,
+185, 9, 53, 8,219,166,129,129,129,129,129,129,129,129, 33,194,168,214, 53, 88,132,144, 52,198,201, 56, 25, 39,227,100,156,140,
+147,113, 50, 78, 38,176, 24, 24, 24, 24, 24, 24, 24, 24, 24,152,192, 98, 96, 96, 96, 96, 96, 96, 96, 96, 2,139,129,129,129,129,
+129,129,129,129, 9, 44, 6, 6, 6, 6, 6, 6, 6, 6, 6, 38,176, 24, 24, 24, 24, 24, 24, 24, 24,254, 32, 16, 0,126,239, 4,
+160,148,238,211, 76,114, 5,119, 19,132,226,103,156,140,147,113, 50, 78,198,201, 56, 25,231,205,199, 25,138, 59, 28,253,113, 93,
+ 11, 44, 45,251, 96, 17,207,131,130,194, 38, 39, 36, 45,210, 9,197, 56, 25, 39,227,100,156,140,179,122, 56,175,164,173,247,199,
+ 73, 8, 33, 94,131,120, 0,160,158,142,147, 94, 79,225,188, 81,242,168, 58,210,179,186,243,136, 1, 16, 66, 36, 32,135,202,105,
+ 68, 66, 8,113, 3,112,211, 8,236, 76,234,201, 88, 46, 82,124, 12,213,160,188, 43,243,136,252, 62,160, 96,249,196,192,112, 19,
+215,247,136,181,245, 94,109, 7,175,112, 2,144, 1,200,132, 16, 92, 77, 91, 82, 29,125,146, 55, 39,128,106,139,251,149,182,163,
+213,145,158,213,153, 71, 12, 33, 4, 22, 33,132, 52,111,222, 92,236,218,181,235, 15,177,177,177, 77,188,127, 27, 60,120, 48, 0,
+ 64,150,101,249,155,111,190,137, 14,231,207,122,246,236, 41, 8,130,240, 85, 70, 70, 70, 15, 95, 62, 79, 47, 46,231,228,228, 68,
+ 95,207, 9, 54,108,216,176, 82,135,195,193,251, 30,151, 36, 73,254,236,179,207,162,111,134, 66, 65, 8, 17,154, 52,105, 50,204,
+104, 52, 26,148, 99,109,219,182,245,254,157,238,217,179,103,161, 22,174,215, 95,127,157, 91,180,104,209, 86,163,209,104,228, 56,
+ 14,130, 32, 64, 16, 4,148,149,149, 21, 13, 31, 62,188, 31, 0, 44, 89,159,191, 54,202,104, 72,128, 27,112,187, 41,168,155,162,
+188,162,172,120, 76,122,227,126,147, 38, 77,114,179,106,122,121, 61, 10, 53, 56,242, 3,215,198,141, 27, 93, 44,245, 52,215, 1,
+165, 77,186,242,139,171, 54,180, 3,100,224, 65,207,215, 10, 14, 40, 38, 64, 94, 2,240,217, 57,192, 90,229,228,107,216,185, 41,
+ 29,109,221,186,117,223, 75, 78, 78, 30, 83, 90, 90, 90,206,243, 60, 8, 33,180,101,203,150,151, 69,135, 16, 2,183,219,125,106,
+255,254,253, 29, 66,116,220, 98,253,250,245,167, 39, 38, 38,142, 42, 47, 47, 47, 39,132,128, 16, 66, 9, 33, 72, 75, 75, 83, 57,
+149,119,183,219,125,106,223,190,125, 29,174, 85, 56,255,200,184, 43, 92, 90,226,238,205, 89,183,110,221,233,201,201,201,163, 44,
+ 22, 75, 57,199,113, 42,103,203,150, 45,175, 56,156,145,226,100, 8, 67, 96, 53,106,212, 72, 74, 76, 76,220,156,154,154,218,120,
+193,130, 5,200,203,203, 67,179,102,205, 32,203, 50,220,110, 55, 40,165, 24, 54,108, 24, 31,110,167, 32,138,226,170, 58,117,234,
+220,177, 96,193, 2,228,228,228,224,246,219,111, 7, 33, 4,178, 44, 67,150,101, 60,253,244,211,252, 85, 54, 22, 38, 65, 16,158,
+214,233,116,119,186, 92,174,219, 60,194,231, 96, 69, 69,197, 22,151,203, 53,155, 82, 90,118,181, 9,230,112, 56,248,175,191,254,
+218,159,240, 10, 26,246, 78,157, 58, 29,114,185, 92,117,195,249, 47,157, 78,119,106,219,182,109, 77, 3,253,222,165, 75,151, 67,
+ 14,135, 35, 44,206,168,168,168, 83, 91,183,110,109, 26, 76, 92, 53,110,220,248,190,150, 45, 91,234, 63,253,244, 83,156, 62,125,
+ 26, 6,131, 1,110,183, 27,178, 44,195,233,116,226,222,123,239, 37,225,252,167,209,104, 52,110,219,182,173, 81,116,116, 52,202,
+202,202,112,225,194, 5, 60,240,192, 3,106,103, 31,165, 55, 36,204,204,154,216,216,233,116,225,183, 18, 43,206, 95,176, 98,222,
+220,185, 55,124,229,234,210,165,203, 6,187,221, 30,175,124, 23, 69,241,183,157, 59,119,246,190, 90, 94,171,213,122,140, 82, 26,
+171,177,111, 7, 0,240, 60,127, 17, 64,253, 16,245, 39, 21,192, 64, 65, 16, 26, 9,130,208,148, 82, 90,223,229,114, 37,121,202,
+226,121,158,231,127,117, 56, 28,135,236,118,251, 81, 0,223, 80, 74, 79,220,164,226,170, 62, 0, 87, 74, 74, 74,129,103, 52,127,
+213,156, 50,240, 32,165,180, 6, 0, 92,186,116,169,198,201,147, 39,107,125,253,245,215, 45,167, 76,153,210, 91, 87, 81, 49,205,
+ 14, 28, 8,118,125,211,166, 77,119,139,162,152,234,213, 14,157,200,203,203,139, 68,103,199,213,169, 83,231,189,187,238,186,235,
+225,121,243,230, 25,119,238,220,105,108,213,170, 21, 42, 59, 91,168,237, 61,165, 84, 45, 91,157, 59,119, 1,249,221,221,190, 44,
+249, 0, 8, 41, 41, 41, 51, 7, 12, 24, 48, 98,238,220,185,198,125,251,246, 25,155, 52,105,162,114,122,167,167,167, 83, 71,251,
+246, 29, 64, 0, 66, 61,211, 84,145, 10,103,117,196,189, 69,139, 22,248,249,231,159,131,198, 61, 61, 61,125,196,188,121,243,140,
+123,247,238, 53,222,122,235,173,126,227,174,196,191, 67,135,219,131, 22, 71,239,244,156, 63,127,190, 49, 55, 55,215,216,188,121,
+115,143, 72,131, 26,198, 48,226, 94, 29,156, 12, 90, 4, 22, 33,132,235,217,179,231, 55,245,235,215,111,177, 96,193, 2,194,243,
+ 60,114,115,115, 81, 92, 92,140, 58,117,234,192,108, 54, 67,175,215,135,255, 71,130,240,149, 71, 92,113, 60,207, 99,195,189,247,
+194, 10, 96,152,221, 14, 73,146,112,228,200,145,171,109, 20,187, 69, 71, 71, 47, 88,178,100, 73,108,151, 46, 93,184,147, 39, 79,
+ 34, 45, 45, 13, 69, 69, 69,237, 55,110,220,216,118,236,216,177,163, 8, 33,143, 81, 74,191,143,196,200,246,155,111,190,129,201,
+100,130,209,104,132,201,100,130,195,225, 8,122,157,219,237,174,181, 97,195, 6, 68, 71, 71, 67,150,101, 80, 74,171, 84, 96,223,
+138,231,114,185,208,183,111,223, 90, 65, 45, 9,151,171,214,230,205,155, 85, 1,228,205, 37,203, 50,116, 58, 29, 56,142, 83, 28,
+ 71, 56, 28, 14,244,232,209,163, 86,176, 17, 93,147, 38, 77,134, 41,226,138,231,121, 44, 91,182, 12,201,201,201, 72, 74, 74,130,
+217,108,134,209,104,188,146,188, 71,116,116, 52,190,250,234, 43,196,197,197,161, 65,131, 6, 16,132,223,139,158,236,114,163,220,
+106, 71,198, 45,139, 48,122,109, 39,196,155, 37,184, 92,242, 13, 95,185,236,118,123,252,158, 61,123,212,239,189,123,247, 54,183,
+107,215,238,167, 64,231,107, 21, 96,178, 44, 39,108,217,178, 5, 6,131, 65, 91,231, 46,203,232,216,177, 99, 66,136,114,157,158,
+144,144,176,164, 75,151, 46, 98, 98, 98, 34,111, 48, 24, 96, 50,153, 16, 27, 27, 11,189, 94, 15,183,219, 93,223,229,114,213,183,
+217,108,119,158, 63,127, 94,254,226,139, 47,222, 32,132, 60, 68, 41, 93,115,147,137,171, 91, 82, 82, 82,254, 1, 0, 5, 5, 5,
+ 47, 24, 12,134,227,145, 18, 89, 10,106,212,168,129, 26, 53,106, 32, 45, 45, 13, 67,135, 14,141,109,219,182,237,223, 27,216,108,
+143,231, 3,246,128, 74,128,227,234,238,223,191, 63,193,107,192,198,223,122,235,173,231,252, 25, 94,158, 54,224,212,209,163, 71,
+ 59,132,136, 43, 87,171, 86,173,119, 6, 12, 24,112,255,188,121,243,162, 1,224,223,255,254, 55, 6, 14, 28,136, 90,181,106,193,
+ 96, 48, 64,146, 36, 72,146, 4, 81, 20,213,119,175, 78,218,175,150,175, 85,171,214,180,129, 3, 7,222, 55,119,238,220,104, 0,
+248,232,163,143,144,158,158,142,132,132, 4, 68, 71, 71, 35, 42, 42, 10, 58,157,174, 10,183, 23, 39,213, 18,206,233,157, 59,163,
+ 55, 0,241,223,255, 70,108,108, 44, 82, 71,142,132, 94,146,192,239,218,133,152,152, 24,111, 78,205,113,207,205,205,197,185,115,
+231,252,198,157,231,121, 68, 69, 69, 85,218,143, 21, 21,129, 92, 33, 53,238, 10,231,162, 69,139,212,184,155,205,102, 63,113,231,
+ 66,185,139,124,173, 90,181,166,165,167,167,223, 55,127,254,124,149,179, 79,159, 62,136,143,143, 71,116,116, 52, 36, 73,130, 78,
+167,243,151, 71,215,132,147, 65,163,192, 82,214, 70,153, 76,166,206, 31,124,240, 1,120,158, 87, 59,200,168,168, 40,181,112,232,
+116,186,176,109,232,140,140,140, 30, 11, 22, 44, 80, 57,109, 62,231, 92,137,104,243,226,239,117,231,157,119, 46, 90,181,106, 85,
+148, 32, 8,184,116,233, 18, 54,111,222,140,216,216, 88, 24, 12, 6, 12, 27, 54,140,235,213,171, 87,124,175, 94,189,150, 16, 66,
+ 70, 83, 74,191,187,154, 68,163,148,170, 98,195,100, 50,193,100, 50,105,117,114,176,114,229, 74, 8,130, 80,165,224,122, 87,100,
+229,123, 98, 98,162, 86, 71, 10,219,182,109, 3,199,113,234,245,162, 40, 98,213,170, 85,120,254,249,231,113,238,220, 57,245, 55,
+ 13,225, 36, 70,163,209,160,136, 43,143, 3,168, 52, 54, 68, 16, 4,226, 57, 78,195, 89,100, 42, 8, 2, 46, 94,188,136,154, 53,
+107, 34, 46, 46, 14, 81, 81, 81, 85, 42,172,211,229, 70, 65, 81, 41,134,127,219, 6,101,214, 18,148,148, 18, 56,156,206,155,174,
+178,125,240,193, 7,146, 44,203,138,224, 86, 93, 65,143, 43,133,199, 31,127, 60, 94, 43,151,193, 96,192,154, 53,107,212,178,164,
+116, 2, 74,163,232,125,188,110,221,186, 90,202,209,171,203,151, 47,143, 90,186,116,169, 58,216,209,233,116, 48,153, 76,136,137,
+137, 65,108,108, 44,226,227,227,145,144,144,128,182,109,219,242,143, 62,250, 40,223,173, 91,183, 87, 1,220, 52, 2,139, 16, 18,
+ 99, 48, 24, 38, 46, 95,190, 92, 2,128,190,125,251, 78,180, 90,173,207, 2, 40,185, 90,145,197, 3,203, 8, 33, 15,122,242, 78,
+223,175, 95, 63,221, 63,255,249, 79,220,118,219,109, 24, 55,110, 92,252,187,211,166, 13, 6,176, 34, 88,155,227,141, 89,179,102,
+197, 42,101, 72, 25,172, 41,175,178,178, 50, 60,247,220,115, 33,219,100, 0, 92, 74, 74,202, 95,254,245,175,127,153,149,227,241,
+241,241,151,181, 69,190,239,129, 92, 82, 47, 87,232,145,249,243,231,171,156, 9, 9, 9,106, 27,167,188,126, 61,248, 19, 54, 44,
+158, 1, 83,124, 45,140,124, 97,106,216,225,236, 8,160, 35,199,193,221,186, 53, 12, 6, 3, 18,140, 70, 64,146,224,246,136, 43,
+ 45,225,244,229,228,121, 94,141, 39,165, 20, 21, 21, 21, 40, 45, 45,133, 44,203,176,219,237,104,223,190, 61, 8, 33,184,229,150,
+ 91, 2,185, 66,151,197,189,102,205,154,151,197,221,187,157,246, 30,104, 6,226, 76, 73, 73,121,228,131, 15, 62,240,155,158,130,
+ 32, 64,146, 36, 44, 90,180, 72,147,147, 29, 14,103,152,249,206,160,197,193, 82, 70, 38,121,121,121,216,189,123, 55, 68, 81, 68,
+ 82, 82, 18, 58,118,236,168, 88,211, 16, 4, 1, 28,199, 97,240,224,193,229,190, 23, 75,146, 84,248,217,103,159, 53,240, 52, 10,
+202, 29, 6, 28, 0,172, 95,191, 30,171,210,211, 97, 3,208, 48, 43, 11,173, 50, 50,112, 72,167, 3, 15, 32,169,168, 8, 60,207,
+251,229,244, 94,155,229,231, 78, 8,179,201,100,154,151,147,147, 19, 37,203, 50,138,138,138, 0, 0, 25, 25, 25,224,121, 30,191,
+252,242, 11, 38, 79,158,140, 47,190,248, 2,171, 87,175,214, 55,107,214,108, 30, 33,164, 29,165,212,226,197, 95,133,243,158,123,
+238,201,115,187,221,117,252, 37,152, 36, 73, 0,128,232,232,104,232,245,122,152,205,102,191,194,197,223,221, 21,178, 44, 99,200,
+144, 33, 32,132,128,231,121,117, 61,146,119,101, 83, 62,239,221,187, 87, 19,167,219,237, 70,183,110,221, 0, 0, 38,147, 9,102,
+179, 25,223,125,247,187,126,108,215,174, 29,236,118, 59, 18, 19, 19,177,111,223, 62, 77,156,103,206,156,193,146, 37, 75, 32, 73,
+ 18,226,226,226, 32,138,162,180,126,253,250,215,140, 70, 99, 12,207,243,136,139,139, 67, 70, 70,198, 44,101,253,156,219,237,150,
+ 87,173, 90, 21, 29,136, 83, 16, 4, 88,173, 86, 85, 96,197,197,197, 85,117,226,220, 46,156, 58,119, 17,105,173,108,232,221, 67,
+ 66,206,234, 50,236,216,224, 14, 25,206,171,197,181,224, 60,113,226, 4,142, 28, 57,162, 78,175, 42,211,225,223,175, 95, 18,119,
+ 52,111,151, 73,233, 56, 41,165,208,185, 46,161, 75, 43,178, 19,110,124,182,125, 63,125, 39, 84, 56, 5, 65,128, 44,203, 88,189,
+122, 53,142, 31, 63,142,245,235,215,163,162,162, 2, 53,107,214, 68,108,108, 44, 58,119,238,140, 71, 30,121,196,175,192,242,229,
+148,101,121, 9, 33,164,245,200,145, 35,201, 55,223,124,131,162,162, 34,148,150,150,194,225,112,192,225,112, 64, 20, 69,117, 64,
+145,146,146, 2,142,227,104, 69, 69,197,146,155, 33,143, 60,237,136, 0, 96,194,251,239,191,159,208,190,125,123, 0,192,251,239,
+191,159,240,200, 35,143, 76, 0,240, 42, 0,215,149,132,211, 0,212, 65,229,197,171, 81,249,194,235, 86, 43,121,115,229,202, 33,
+ 0, 70,125,249,229,151, 24, 49, 98, 4,222,153, 54,173,149,175,192,242,230,116,187,221,216,181,107, 23,118,238,220, 9,151,203,
+ 5, 89,150,213,119,239,207,202,123, 32, 49,232, 19, 78, 98,177, 88, 42,118,238,220,105, 94,184,112, 33,226,227,227,209,160, 65,
+ 3,213,101,242, 21, 3,202, 43, 84,220, 45, 22, 75,197,190,125,251,204, 75,150, 44, 65,124,124, 60,234,215,175, 15,163,209,168,
+114, 74,146,132, 61,223,173,194, 19,163,238, 65,225,209,159, 48,235,217, 7, 52,135,115,122,231,206,232, 12,192, 52,111, 30,202,
+154, 55, 71,195, 62,125, 32, 72, 18,108, 63,254, 88, 25,190,222,189, 65,117, 58,136,219,183,107,230,220,181,107, 23, 40,165, 72,
+ 77, 77,133,213,106, 69, 76, 76,140, 26,214,117,235,214,225,238,187,239,198,226,197,139,209,185,115,103, 77,113,223,187,119,175,
+ 26,247,122,245,234, 93, 22,119, 69,196, 52,108,216, 16, 23, 47, 94, 68,163, 70,141,130,114,150,149,149, 85,228,230,230,154, 23,
+ 47, 94,140,248,248,120,212,173, 91, 23, 70,163,177,138, 19,246,250,235,175, 87,225,104,221,186,245, 85,115,134,155,239,215, 0,
+183, 3,240,118, 30,236, 0,116, 94,239,133, 0,118,249, 57, 79, 57, 46, 2,104,227,249, 77, 6, 80, 10, 32,214, 15, 95, 32,158,
+ 34,143,195,154,232,115,190,239,255, 84, 21, 88,132, 16,165, 54,246, 4,240, 61, 0, 52,107,214, 12,197,197,197,136,138,138, 66,
+199,142, 29, 81, 88, 88,168, 90,135,110,183, 27,183,221,118, 27,222,126,251,109,112, 28, 7,167,211, 9, 74, 41,120,158,199,189,
+247,222,235,207,122,113, 3,192, 29,119,220,129,223, 60, 7, 90,101,100,160,110,221,186, 56,233,229,196,164,165,165, 97,210,164,
+ 73,234,180, 22,165, 20, 86,171, 21, 15, 62,248, 32, 31,196, 29,121,234,163,143, 62,138,145, 36, 9,103,206,156,129, 50,210,148,
+ 36, 9,199,142, 29,195,204,153, 51,241,200, 35,143,224,248,241,227,168, 95,191, 62, 38, 78,156,104,158, 56,113,226, 83, 0,178,
+130, 52,150,201,159,127,254,185, 90,168,236,118, 59, 74, 75, 75, 81, 90, 90,138,197,139, 23, 3, 64, 21, 7, 75,235,180,153,219,
+237,198,234,213,171,253,142, 14,125, 71, 12, 90, 71, 11,110,183, 27, 59,119,238, 84,197,153, 32, 8,170,251, 68, 8,193,254,253,
+251,193,113,156, 42, 12, 67,245, 61, 74,220,146,147,147, 97, 48, 24, 32,138,162,244,195, 15, 63, 76,174, 85,171,150,105,212,168,
+ 81, 40, 45, 45, 69, 74, 74, 10,250,247,239, 15,183,219, 13,135,195, 17,114,237,156, 32, 8, 32,132,160,102,205,154,136,137,137,
+241, 51,213, 41, 99,208,144,139, 0, 42,195,152, 49,192,132,255,204,186, 57, 70, 48, 78,167, 19, 21, 21, 21, 85,196,213,246, 77,
+159,198,237,248,254,155,184,220, 93,155, 42, 51,249,208,221,191,119,199, 48,180,108,251,240,111,169,173,110, 37, 63,236,205, 11,
+ 62,157,205,243, 60,198,143, 31,143,204,204, 76, 12, 31, 62, 28,235,215,175,199, 75, 47,189,132, 71, 30,121, 68,235, 8,217, 59,
+156,255,121,248,225,135,255,178,124,249,242, 91,199,143, 31,207, 41,117,210,104, 52,130, 16, 2,155,205, 6,171,213,138,138,138,
+ 10, 28, 60,120,208,253,232,163,143, 30,182,219,237,255,185,137, 6,155,143, 63,247,220,115,205, 31,122,232, 33,245,192, 67, 15,
+ 61,132,253,251,247, 55,159, 49, 99,198,227,253,250,245,123, 63, 92, 23,203, 0,212,173, 81,171,214, 12, 0, 48,156, 61,251,156,
+ 21, 56, 5, 0,111, 2,233, 50,112,247,218,181,107, 1, 0,245,235,215,135, 27,104, 78,128,143,120, 96,153, 11,248,214,159,131,
+229,114,185, 80, 81, 81,113,153,152,242,247, 30, 42,156,148, 82, 74, 8,113,243, 60,143,180,180, 52,164,167,167, 67,167,211,193,
+108, 54,171,237,188,111,155, 20,168,163,245,109,146,120,158, 71,147, 38, 77,208,167, 79, 31, 72,146, 4,147,201,164, 14, 72, 21,
+135,181,117,183,190, 88,182,248, 29, 60,156,222, 18,255,215, 61, 25,159,237, 45,210, 20,206, 59, 57, 14, 93, 37, 9,150,102,205,
+ 16, 29, 29, 13,206, 96, 0,241,154,202,162, 70, 35, 56, 31,135, 60, 88, 56,211,210,210,112,246,236, 89,228,231,231, 35, 63, 63,
+ 31, 28,199,161,107,215,174,208,233,116, 16, 4, 1,121,121,121,120,227,141, 55, 96,183,219, 67,113, 82, 0,110,142,227,208,164,
+ 73, 19,244,238,221, 27, 58,157, 14, 70,163,241,178,169, 65, 81, 20, 81, 90, 90,138,198,141, 27, 99,229,202,149,184,243,206, 59,
+ 67,114, 54,111,222, 28, 61,123,246, 84,103, 20,148,165, 58, 74,122,122,196,157,154, 14,222, 55, 37,105,225, 92,254,131, 13,175,
+255,247, 44,202,237,133,248,173,220, 93,101, 6,184, 94, 77, 61, 78, 44, 25, 88,221,238,177,170, 65, 40,165,155, 2,156,150, 72,
+ 8,201,241, 42, 27, 25,132,144, 28,239,247, 64,231,121, 62,118,159, 48, 97, 66,135,236,236,236, 41, 93,186,116, 89,182,109,219,
+182,165,129,248, 2,241, 76,152, 48,161,101,118,118,246, 20,239,243,253,252,207,229, 14, 86,101, 57, 38, 20, 94,187,187,215,169,
+ 83, 71,157,119, 54,155,205, 85, 58,105,151,203,133,255,252,231, 63, 72, 74, 74, 82,215,232, 36, 39, 39, 7,172, 36,138,219,113,
+159,103,173,210, 65, 73,194, 73, 0, 45, 60, 13,129,203,229,130,195,225,192,138, 21, 43, 16, 29, 29,173, 86,116,179,217, 28, 52,
+ 99,116, 58, 93,247, 59,238,184,131, 43, 45, 45, 85, 69,137, 40,138, 56,118,236, 24,222,125,247, 93, 60,244,208, 67,104,220,184,
+ 49,100, 89, 70, 73, 73, 9,122,246,236, 41, 24,141,198,238,193, 4,150,226, 76,127,254,249,231,234,212,165,210,120, 41, 80, 4,
+150,214,117, 48,138, 24, 26, 50,100, 8,120,158,247,235, 90,121, 55,104, 91,182,108,209,204,217,185,115,103, 24,141, 70, 53,189,
+190,253,246,247,246,185, 99,199,142,160,148, 34, 49, 49, 17,223,127,255,125,200, 70,183,109,219,182,112,187,221, 72, 74, 74,130,
+ 36, 73,100,253,250,245,175,121,196, 21, 17, 69, 17, 63,254,248, 35,246,239,223,143,196,196, 68,152, 76, 38, 77, 83,187,165,165,
+165, 69, 35, 70,140,112, 41,194, 15, 0, 74, 74, 74,206,252,222,185,219,139,239, 29,240,153, 79, 88, 28,197, 55, 67,175,237,112,
+ 56, 80, 94, 94,142,195,135, 15,195,106,181, 66,150,101, 28, 61,178, 79, 55,229,141,113,228,245,231,187, 2, 0, 94,155,125, 6,
+214,173,181,213,107,118,124,249, 87,115,175, 7, 22,125, 12, 32, 53, 24,183,213,106,133,195,225, 64,106,106, 42,114,115,115, 81,
+ 86, 86,134, 62,125,250, 92,230,144,106,116,117,236,132,144,222,131, 7, 15,222, 50,125,250,244,134, 45, 90,180, 32,101,101,101,
+ 40, 43, 43, 67,121,121, 57,148,207,251,246,237,163, 75,151, 46, 61, 94, 94, 94,222,139, 82,106,191, 73,166, 6, 7,246,235,215,
+175,255,219,111,191,125,217,111,111,191,253, 54, 14, 28, 56,208,127,237,218,181,249,183,222,122,235, 55, 90, 69, 86, 3, 64,231,
+ 18,197,151, 62,253,244, 83, 9, 0,122,247,238,253, 82, 3,167,243,249,124,192,222,162, 85,171,251,182,109,219, 86, 67, 25,152,
+213,168, 81, 3,148, 82,190,188,188,188,198, 29,119,220,113, 31, 2, 8, 44,167,211, 9,171,213,170,254,191,247, 20,161,247, 98,
+100,142,227, 96, 54,155,227,110,189,245, 86,155,103,224, 91,118,240,224, 65,127,107,240,220,149,119,141, 1,181,106,213,130, 40,
+138,208,235,245, 85,214,223,132,114, 49,252, 64,174,236, 71,168, 58,237,244,243,247,171,113,241,200, 15,144, 8,133, 91,118,194,
+237,114, 64,118, 58,192,195,141, 3, 71, 79,163, 69, 74,200, 54, 68, 13, 39, 55,123, 54,228,142, 29,209,104,208, 32,112,162, 8,
+199,142, 29,149,142,208,192,129,128, 78, 7,227,230,205, 90,195, 89, 37,238,185,185,185, 24, 55,110, 28,166, 78,157, 10,131,193,
+160, 14, 84, 15, 30, 60,136, 79, 62,249, 4,253,250,245,211, 28,119, 66, 42,167, 90,149, 52,156, 48, 97, 2, 10, 10, 10, 48, 99,
+198, 12,116,232,208, 1,162, 40,226,226,197,139,184,227,142, 59,112,238,220, 57, 77,156,148,186, 17, 31, 31, 15, 81, 20, 17, 21,
+ 21,117,217, 26, 49,165,223, 11, 39,143,188, 57,159,189, 55, 10, 31,110, 61, 8,192,141,115, 75,186, 87,233,143,166,124,114,228,
+154,212, 67, 47, 13, 66, 66,156,151,161,145, 79, 57, 79, 73,228,168,236,236,236, 41,190,215,135,226,243,254,221,231,122,187,143,
+ 40, 59, 23,114,138, 80, 17, 67,110,183, 27,102,179, 89, 93,111,229,219,145, 42,191,121,143,110, 66, 53,230,110,183, 91, 45, 0,
+188,159,209,248,129, 3, 7,112,224, 64,213,155,105, 62,248,224,131,160,156, 46,151,235,182,184,184, 56,156, 61,123,214,187,113,
+193,107, 19, 39,226,255, 70,141, 82,197,149, 78,167, 67,102,102, 38,238,186,235, 46,216,108,182,219, 52, 52,186,234,186, 51,183,
+219,173, 58,117, 58,157, 14,111,188,241, 6,246,239,223, 95,101, 97,187, 78,167,147, 53,100, 56,214,172, 89, 19,210,193,146, 36,
+ 73,117,241,180,112,238,217,179,231,178,181, 56, 74, 99,251,191,255,253, 79,237,108,181,186, 98,178, 44,195,104, 52, 18, 73,146,
+136,209,104,140, 25, 53,106, 84,149, 53, 62,146, 36, 65,175,215,171,233, 19, 10, 67,134, 12, 9,218, 58, 61, 62,248,182,126,184,
+ 73,225,114,185, 96,179,217,112,233,210, 37, 76,158, 60,217,115,116,226, 89, 0,232,216,247, 53, 60,254,112,167,122, 62, 54,179,
+ 82, 2, 67,182,148,241,241,241, 88,188,120, 49, 68, 81, 68, 78, 78, 14, 98, 98, 98, 48,116,232, 80,196,196,196,224,197, 23, 95,
+196, 3, 15, 60, 16,214,226, 84, 74,105, 9, 33,164,207,115,207, 61,183,101,218,180,105,245,234,215,175, 15,135,195, 1,187,221,
+ 14,135,195,129,163, 71,143, 98,217,178,101,167,202,203,203,251, 80, 74, 75,110, 18,113, 85,247,214, 91,111,253,235,226,197,139,
+225, 61, 0,240,110,151, 22, 47, 94,140,110,221,186,253, 53, 47, 47,239, 23, 0,249, 90,120, 79, 2,143,191, 51,117,106, 61,101,
+250,126,234,212,169,245,254, 62,126,252,227, 0,222, 59,176,119,239,199, 99,198,140,121,110,249,242,229, 85,174, 25, 51,102, 12,
+ 14,236,221,251,113,160,122,174,184,161, 60,207,227,217,103,159, 13, 21, 4, 17, 0,108, 54, 27,250,244,233, 19,112, 64,213,162,
+ 69, 11,200,178,172,184,213,151, 45,108,246,110,223, 53,182, 31,202,102,149,234,160,252,196,174, 53, 24,255,196,112, 64,118, 1,
+142, 50,192, 81, 14,234, 40, 7,181,151,129,232, 12,160,206,138,144, 3, 63, 37,156, 49, 49, 49,149, 2, 72,175, 7,188,250, 31,
+ 98, 52,130,120,156, 43, 45,225,244,141,251,137, 19, 39,240,228,147, 79,194,110,183, 99,232,208,161,168,168,168,128,205,102, 67,
+ 69, 69, 5, 26, 54,108, 8,171,213,170,197, 17, 84,182, 51, 80, 93,192,231,158,123, 14, 29, 58,116,192, 27,111,188,129, 23, 95,
+124, 17, 13, 27, 54,196,227,143, 63,142,101,203,150,161,101,203,150, 40, 47, 47, 15,201,169,244,157,102,179, 25,130, 32,168,109,
+176,119, 94, 41, 2, 43, 84,220,131,113,130, 84,110,135,229,155,239,147,255,175,249,245, 86,103,115,180,136, 44,175,243,114,149,
+ 49,105,102,102,230,203,132,144,156,204,204,204,151,179,178,178,246,107,225, 11,240,251, 42,207,251, 32,175, 99,185, 33, 5,150,
+119,133, 86, 70, 51, 74,102, 40, 2, 70, 17, 88, 57, 57, 57, 88,177, 98, 69, 21, 1, 21, 74, 96, 29,240,100,110,115,207, 40, 76,
+249,222,204,237, 70,143, 30, 61,208,186,117,235, 42,238, 85, 40,135,136, 82,138, 3, 7, 14, 96,203,150, 45,184,235,174,187, 80,
+ 94, 94, 14,167,221,142,103,127,250, 9, 45, 70,142,132,221, 51,165, 25, 21, 21,133,119,223,125, 87,115,135,163,196, 63, 42, 42,
+ 74,181,231, 69, 81, 68,219,182,109, 33, 8, 2,126,252,241, 71,124,253,245,215, 97,221, 82,231,118,187,113,223,125,247, 85, 17,
+ 67,190, 2, 75,169, 60,171, 86,173,210, 28,206, 30, 61,122,192,108, 54,171,233,246,197, 23, 95,168,191,119,239,222, 29,132, 16,
+ 36, 37, 37, 33, 39, 39, 71,115, 56, 21,241,196,243, 60,202,202,202,144,155,155, 11,157, 78,167,174,207,208,235,245,106,250, 48,
+ 4, 23, 88,229,229,229,176,219, 43,205,158, 99,199,142, 85,249,221,238,184,114, 19, 72, 41, 71, 22,139, 5, 27, 55,110,196, 39,
+159,124,162,142,144,189,197,118,152,163,200, 34, 66, 72,223, 23, 95,124,113,227,155,111,190, 89, 59, 33, 33, 1, 74,181, 76, 0,
+ 0, 32, 0, 73, 68, 65, 84, 1, 14,135, 3, 39, 78,156,192,194,133, 11,207,148,149,149,245,165,148, 22,221, 68, 89, 68,243,242,
+242,138, 19, 19, 19, 21,123, 62,198,110,183, 19,207,160,137, 2, 80,132,100, 25, 0,135, 22,247, 74, 4,122, 14,189,239,190,222,
+222, 11,205,159,123,238, 57,236,216,177,163,183,184, 98,197, 62, 39,176,145, 95,177, 34,109,198,140, 25,234, 57, 51,102,204,192,
+231, 43, 86,108,144,129,141,193,202,146,213,106, 85,219,176,221,187,119,107,110, 35,130, 13, 36,149, 37, 21,129,214, 92,133,179,
+100,129, 82, 74,211,210,210, 42,215, 20,122,218,178,219,238,188, 7,211,223,251, 0, 81, 28,197,189, 61,154, 32,201, 44,128, 24,
+227, 33,245,200, 4,137,245,152,180,147,219,132, 28,240, 82, 74, 81,231,133, 23, 16,111, 52,194,230,113,170,164, 33, 67, 0,157,
+ 14,134,181,107, 33,138, 34,172, 35, 71, 2,146, 4,227,194,208,219,244,121,199,253,200,145, 35,216,186,117, 43,154, 53,107,134,
+195,135, 15,171,251, 84,113, 28,167, 14,176,181,198,221, 83,118, 32, 73, 18,206,158, 61,139,140,140, 12, 72,146,132, 15, 63,252,
+ 16,155, 54,109,194,139, 47,190,136, 49, 99,198,160, 87,175, 94,151, 25, 10,254, 56, 91,182,108, 89, 37,143, 2,173,143, 10, 39,
+143,252,113, 42,198,209,149,228,251, 53,173,176,191,187, 69,254,166,204, 6,249,113,158,110, 71,229,218, 40, 91, 86, 86,214,254,
+172,172,172, 12, 66, 72, 78, 86, 86, 86, 70, 16, 7,107, 80, 8,135,107, 16, 42,215, 92, 5,111,163,189, 10, 27, 69,229, 26, 44,
+ 21,193,110,207, 52,155,205,248,203, 95,254,130,151, 94,122, 9, 9, 9, 9, 72, 77, 77,213, 84,160,131, 97,211,166, 77,216,180,
+105, 83,149, 99, 43, 87,174, 12,122,141, 36, 73, 7,147,147,147,219, 61,240,192, 3,184,120,241, 34, 10, 10, 10, 16, 19, 19,131,
+ 22,239,188,131,189,127,251, 27,218,204,155, 7,174,119,229,157,239, 81, 81, 81,200,203,203, 67, 84, 84,212,193, 80, 65, 85, 92,
+ 59,101,171, 3,197,142, 87,210,133, 42,126,102, 24,139, 50, 40,165, 88,181,106, 85,208,181, 87,222,119,177,104,229,220,190,125,
+251,101, 14,150,146,222,202,111,202,130,104,173, 48, 24, 12, 84, 17, 88, 70,163, 17,241,241,241, 85,132, 85, 56, 14,214,207,217,
+217,107,121,131, 33, 65, 20, 69, 72,162, 8, 65, 20,225,176, 88,138, 83,159,122,170, 31, 0, 44, 92,184,112,171,201,100, 82, 55,
+ 34, 21, 69, 17,229,229,229, 69,247,221,119,223, 13,239,108,217,237,118,117,237, 82,152,141, 72,200,115, 28, 14, 7, 36, 73,194,
+ 87, 95,125,133,219,111,191, 29,237,219,183, 87,243, 90,153,226,208, 58, 69,232,243,223,167, 9, 33, 3,102,205,154,181,105,250,
+244,233,177, 22,139, 5, 11, 23, 46, 44, 41, 45, 45, 29, 64, 41, 61,125, 51, 9, 96, 79,124,254,226,213, 70,125, 12,160,134,231,
+107, 9,128,135,195,189,123,176,121,171, 86, 15, 47,244,211,193, 47, 92,184, 16,135, 15, 31,126, 24,123,247,110,172, 7,204,123,
+233,165,151, 26,183,111,223,190, 30, 0,188,244,210, 75, 39,235, 1,243,130,149, 7,197,193, 10, 53,144,245, 55, 96,210, 50,179,
+ 16,232,206,193, 43,237,100, 21,145,209,123,216,104,156,255,245, 8, 90,152,127, 67,114,156, 25,238,178,243,144,250, 76,198,222,
+223,140,152, 57,111, 77, 88,241,208, 69, 69,129,120,220, 54, 73,146, 0,131, 1,188, 94,255,123, 56, 61,107,178,194,225, 20, 69,
+ 17, 7, 15, 30,132,209,104,132, 44,203,151,137, 41,173,179, 9,222,121,165,184, 75,211,167, 79,199, 11, 47,188,128, 15, 63,252,
+ 16,123,247,238, 69,155, 54,109,208,183,111, 95,156, 63,127, 30, 63,253,244, 19,108, 54,155,230,112,122,247, 23, 7, 14, 28,192,
+186,117,235,112,232,208, 33,156, 60,121,242,138,242,199,151,211,183,223, 95,180,238, 87,140,238,151,122,205,234,162, 63, 13, 18,
+ 4,185, 62,238, 17,148,245, 80,138, 32,242,253, 14, 32, 78, 57,150,153,153,249,178,214,235,188,191, 43, 14, 88, 16,225,117,185,
+192,162,148, 18,127, 98, 72, 73,116,239, 10,170,124, 86,220, 18,147,201,132,212,212, 84, 77,149,158,231,121,212,183, 88, 20,129,
+162, 58, 87, 10,134, 15, 31,142,180,180,180, 42,107,176, 66, 85,110,155,205,182,229,187,239,190,107, 51,100,200, 16, 46, 47, 47,
+ 15,146, 36, 85,222, 86,219,165, 11,218,204,155,135,125,227,199,163,199,177, 99,168,112, 58,149, 91,219,157,229,229,229, 91, 52,
+100,182,186, 48, 81, 17, 17,202, 66,126,165, 50, 79,158, 60,217,239,190, 45,193, 42, 94,160, 17,162,247,139,227, 56,205, 98,200,
+237,118,171, 29, 41,207,243,234,139, 16,162,142,118,195,117, 49, 20,219, 92,225,229, 56, 14, 53,106,212, 80, 43,163,178, 6, 64,
+171,192, 18, 12,134,132, 89,195,135, 55,118, 78,156,136,232,185,115,225,122,254,121,188,222,181,171,250,187,201,100, 50,110,219,
+182,173,145,193, 96, 0,165, 20,133,133,133,184,255,254,251,111,138, 93,199,101, 89, 86, 23,136, 71, 26,159,126,250, 41,142, 29,
+ 59, 6,135,195,129,183,222,122,171,138,184,242,126, 93,161,240, 56,218,174, 93, 59,247,128, 1, 3,176,125,251,118,232,245,122,
+ 39,165,244, 40,243, 36, 67,227,231,189,123, 87,152, 76,166, 7, 1,152, 47, 94,188,200,215,168, 81, 3, 70,163, 17, 86,171,245,
+ 18,239,185, 83, 48, 31,176, 27,156,206,169,247,223,127,255, 12, 0, 16,156,206,169,193,246,193,186, 26,129, 21,202,193,242,238,
+ 84,175,212,185,242,199, 41,138, 34, 4,158,199,178,233,175,162,133,185, 24,237,110, 49,161,162, 40, 31, 81, 49, 53, 65, 98, 27,
+ 96,230,188, 53, 56,144,255, 91, 88,156,220, 39,159, 64,174, 87, 15,226,131, 15,130, 68, 69, 65,159,147, 3, 73,146, 96,253,203,
+ 95, 64,116, 58, 24, 23, 44,184,162,112,150,151,151, 7,116,170,180, 58, 88,190,156,146, 36,161, 93,187,118,104,210,164, 9, 54,
+110,220,136,118,237,218,225,240,225,195, 56,124,248, 48,242,243,243,177,119,239, 94, 92,184,112, 65, 51,167,146, 71,159,124,242,
+ 9, 10, 11, 11, 33, 73, 18, 74, 74, 74,112,252,248,241,128,235,159,195,201,119, 5, 81,131, 42, 55,210,174,159,104,184,102, 2,
+203,159, 6,241,131, 34,159,181, 78,202,119,187,143,216,241,253,238,123, 62, 0,156, 7,192,135,184,206,247,123, 81, 86, 86,214,
+ 70,197,249,242,240,242,129,214, 95, 85,113,176,124,251,133,123,238,185,231,178, 94, 57, 42, 42, 10,247,220,115, 15,120,158, 71,
+108,108, 44,106,212,168,129,166, 77,155,134,220,100,211, 35,174,228, 17, 35, 70, 92,198,169,215,235,113,239,189,247, 98,233,210,
+165, 0, 0,223,117, 9, 95,125,245, 85,168, 41,152,217,127,249,203, 95, 70,247,233,211, 39, 54, 37, 37, 5,103,206,156, 81,239,
+116, 36,189,122,161,251,209,163,176,203, 50, 76, 38, 19,142, 30, 61,138,217,179,103,151, 57, 28,142,217,161, 50,219, 91, 96, 41,
+110, 13, 33, 68,237,176, 8, 33,244,192,129, 3, 97,183, 62, 90,196, 85,184, 80, 68,149,183,200,122,226,137, 39,212,239,225, 52,
+146,146, 36,209, 65,131, 6,169,207, 32,140,139,139, 67, 66, 66, 2,206,157, 59,167, 54, 26, 38,147, 73, 21, 87, 90, 4,150,168,
+211,193,245,218,107, 16, 26, 52,192,175,123,246,160, 97,124, 60,248,230,205,171,140, 16, 45, 22, 11,210,211,211, 33, 8, 2,230,
+206,157,123,197,194,224,122,131,114,247, 96,106,106,106, 68, 55,171,116, 56, 28,120,236,177,199,252,174,127, 84, 22, 61,187,221,
+110, 56,157, 78,173,119,144, 94,145,139,118,179, 35, 53, 53, 53, 96,253, 9,148, 62,202,150, 12, 60,240,230,175,191,254,218,170,
+ 70,141, 26,232,223,191, 63,190,254,242,203,175, 38,122,237, 27,102, 5, 78, 25,206,158,125,214,243,249,116,168,188, 80,238, 34,
+140,124, 62,146,203,220,171,171,157, 30, 34,164,242,206,229,111, 23,189,135, 22,166, 66,180,169, 31,133,173, 59,126, 66,167,122,
+ 20,212, 38, 93, 41, 43,204,102,115,101, 59,105, 50,169,119, 15, 18, 66, 64, 12, 6, 32,204,253, 25, 21, 78,165,126, 40,109,239,
+213, 58, 88, 74,220,149,116,124,244,209, 71,241,210, 75, 47,161,127,255,254, 56,124,248, 48, 54,111,222,140,188,188, 60,140, 27,
+ 55, 14, 45, 91,182, 68,122,122,186,166,112, 42,124, 95,124,241, 5, 46, 93,186,164, 14, 70, 43, 42, 42,240,218,107,175, 93, 81,
+220,189,243, 93, 21,148,107,135, 1, 0, 62, 92,123,226,122,171,142, 63,132,248, 30,238,245,213, 14,191,189,216,215, 95,127,237,
+247,153,122,131, 7, 15, 46,191,251,238,187,113,232,208, 33,152, 76, 38, 52,109,218, 20, 54,155, 45, 96,103,232,253,180,237, 47,
+191,252, 50, 32,231, 61,247,220,131,134, 13, 27, 86,113,174, 2,109,125,224,251, 4,111, 74,169,133, 16,242, 84,247,238,221, 63,
+ 88,191,126,189,190,101,203,150, 40, 46, 46,134,219,237,198,132, 9, 19,240,254,251,239,195,100, 50,225,248,241,227, 24, 52,104,
+144,213, 98,177, 60,229,189, 7,150, 63, 78,143,112,171, 34, 34,148,233,194, 42,114,186,168,136, 4, 25, 33,248,125,210,248,172,
+ 89,179, 48,127,235, 86,140,245,114,112,252,225,253,247,223,215,196, 73, 41,197, 59,239,188, 19, 49,206,157, 59,119, 46,244,201,
+159,217,233,233,233, 56,121,242,100,149,105,193, 96, 2,203,151, 83, 18, 4, 68,207,153,131, 83, 63,253,132, 70,183,221, 6,201,
+237, 6, 90,181,250,189, 16, 10, 2,234,212,169,131,183,222,122, 11, 53,107,214, 68, 82, 82,210,101,101,234, 90, 61,181, 62,146,
+156,162, 40,110,126,231,157,119,186,253,235, 95,255,226, 12, 6, 3,118,239,222,141,226,226,226,203,132,146, 42,148, 19, 6, 65,
+ 46, 94,229,201, 87,185, 44, 88, 56, 43, 42, 42, 48,123,246,108, 77,249, 62,127,254,252, 43,138,187,183, 83,162, 69,108,221,136,
+121, 20, 66, 92,197,156, 56,113,194,223,162,243,101,240,185,211,207, 31, 39, 1,246, 45, 93,186,180, 85,171, 86,173,148,186, 55,
+106,218,127,255,251,192,100,171,181, 2,168,220,124,212, 35,198, 66,134,147, 82, 74, 12, 6, 3,210,210,210,224,116, 58,195,114,
+177,188,207,245, 13,167,178,214,232,106, 6,122,254, 56, 57,142, 3,207,243, 56,186,237,107,100, 12,168,141,109, 59,243,176,254,
+148, 9,245,162, 10, 80,187,188, 16,238,194, 95,240,236,125,237, 48,115, 69,229,147, 14,246,238, 14,205, 73, 8,129,249,233,167,
+ 65,140, 70,232, 87,172,128, 40,138,176, 61,249,100,229, 26, 44, 79,219, 86,241,230,155,128, 78, 7,253,139, 47,106, 10,167,239,
+ 76,141,178, 28,196, 91, 92, 5,115,176, 2,197, 29,168,220, 54,225,194,133, 11,248,232,163,143,240,200, 35,143,224,252,249,243,
+ 56,126,252, 56, 14, 29, 58,132,101,203,150,105,238,227,124,243, 40, 51, 51, 19,207, 63,255, 60, 56,142, 67, 90, 90, 26, 38, 79,
+158,140, 46, 93,186,132,157, 71,190,249,238,139, 80,238, 85,117,212,205,155, 13, 97,219, 4, 28,199,161,102,205,154,234,230,154,
+222, 29,108,184,214,181,183,152, 49, 24, 12, 48, 24, 12, 85,182, 62,184,251,238,187, 67, 58, 88,158,198,103, 45, 33,100, 76,227,
+198,141,231,101,103,103,155,251,244,233,195, 39, 39, 39, 99,224,192,129, 56,113,226, 4, 86,173, 90,229,156, 49, 99, 70,185,197,
+ 98,121,156, 82,186, 65,107,163,228, 45, 34,252,236, 94, 79,155, 52,105,162,121,136, 39,138,226,175, 71,143, 30,109,240,238,187,
+239,114,101, 0,102,112,156,218, 8,113,158,207,222,248,238,187,239, 92, 58,157, 46,232, 29, 75, 58,157, 78,229, 44, 39, 4, 51,
+ 60,149,155,243,226, 14,151, 51, 16,188,167, 75,255,159,189,243, 14,143,162,248,255,248,123,118,175, 39,164, 64, 72,128, 36, 23,
+ 66, 2,132, 14, 73,104,130, 20, 21, 68, 65,138, 72, 81, 81, 17,148,162, 8, 95, 84,186, 72, 19, 65, 17, 84, 4, 5, 69,137,128,
+ 52, 11, 8, 34,189, 23, 41, 73, 40, 2, 9, 2, 9,164, 65, 10,169, 87,183,205,239,143,148, 95, 8, 41,119, 73, 20,196,121, 61,
+207, 61,151,219,221,188,119,118,103,118,246,189,159, 41, 91,252,156, 56, 82, 17,171,213,106,144,105,211,208,192,221, 29,106, 69,
+ 1,225, 56,160,224,101,170,133,235,207,159, 63,143,247,223,127, 31,106,181, 26, 63,255,252,243, 67,113,113, 25,141,198,183,111,
+222,188,185,190, 95,191,126,141,203,204, 67, 41,179,200, 92,133, 15,248, 13,145, 91,250, 20, 84, 94, 82, 86, 57,121, 17,127,232,
+208, 33,227,220,185,115,249,116,142,195,130, 98, 77,195,133,159,226,249,114,224,192, 1,217, 96, 48, 36, 84,229, 88,254, 67,209,
+ 44,115, 66, 66,130,135,209,104,196,149, 43, 87, 8,254,191, 63, 86,241,235,238,121,148, 50,149, 66, 73,252,129,109, 75,151, 46,
+125,122,248,240,225,181,154, 52,105, 82, 56,248, 68, 91,240, 65,193,204,238, 59, 29, 60,255, 91, 63,250,232,163, 87,126,248,225,
+ 7,109,225,245, 18, 23, 23, 87, 81, 52, 26,171, 87,175,182, 87,116, 19, 44,124,211, 67, 97,212,165, 50, 81,244,178,162,234,225,
+253, 70,225,203, 29,223,192,167,213,211, 24,220,247, 81, 28, 93,246, 10,134, 52,179, 64,216,244, 2, 90, 14, 94,139,136,105,249,
+209,155, 54,155,167, 57,116,239,209,187,187,131, 47, 24, 45,200,113, 28,224,226, 2, 82, 44,250, 66, 10,102,116,119,230,126, 86,
+104, 46,202, 58,110,103,207, 7,207,243, 8, 10, 10, 66,112,112, 48, 58,119,238,140,208,208, 80, 60,246,216, 99, 56,119,238, 28,
+206,157, 59,135,241,227,199, 59,253,202,177,226,121,244,228,147, 79,226,169,167,158,170,114, 30,149,204,119,198, 3, 98,176,188,
+189,189,161,213,106, 43,109,168, 74, 98,183,219,139,140,149,193, 96, 40, 10, 77, 59, 98,174,138, 85, 64,251, 9, 33,109,223,125,
+247,221, 55, 13, 6, 67,215,194,169, 24,116, 58, 93,140,197, 98, 57, 44, 8,194,114, 74,105,182,227, 15,101,228, 46, 67, 81,202,
+ 6,200,202,202,114,216, 96,201,178,220,227,127,255,251,223,126,155,205, 22,232,200,246, 6,131, 33,201,100, 50,245, 40,111, 27,
+ 81, 20,123, 76,152, 48,161, 90, 53,203, 72,251, 93,166,170,240,219,209,190, 93,106,141, 6,218,201,147,193, 9, 2, 8,199,129,
+150,136, 96,169,213,106,120,122,122, 98,235,214,173,240,242,242,122,104, 46,174,205,155, 55,203, 0,134,148,183,205, 35,173,200,
+ 73, 0, 45, 30, 25,252, 91,218,197,235, 52, 48, 52,132,196,255,177,117,148,119, 5, 15, 36,143,127,242,201, 39,123, 5, 65, 8,
+112, 36, 29, 90,173,246,166, 32, 8, 78,231,187,162, 40, 36, 37, 37, 5,139, 22, 45, 50,101,100,100, 28,255,143,212,137, 43,123,
+244,232,241,254,222,189,123, 85, 70,163,177, 74, 66,241,128, 93,107,179,125, 18, 22, 22, 54,121,250,244,233,158,125,251,246,133,
+209,104,132,135,135,135,211, 90, 9, 9, 9,163, 1,212,233,218,181,107,239,194, 73, 25, 11,235,223,226,111, 3, 40,252, 46, 24,
+127,163,200,178,124,225,214,173, 91,237,202,169,232,138, 30,198,170,203, 92, 21,206,195, 6, 0, 79, 12,122, 21, 79, 12,122,181,
+ 40, 93,251,126,236,142,200,164,221, 8,231,146, 96,251,250, 81, 16,247,194, 34,204, 85,168,201,113, 28, 12,235,214,221, 53,141,
+141,225,147, 79,238,126,248,120,251,109,167,210, 89,252, 65,180,186,250, 96,241, 60,143,244,244,116,196,198,198,226,246,237,219,
+ 48,155,205,184,116,233, 18,236,118, 59, 50, 51, 51, 81, 56,210,176, 50,233,172,206, 60,170,110, 77, 70, 21, 13,150, 70,163, 73,
+ 27, 52,104,144,119, 69,219, 56,233,246,229, 87, 95,125,181,220, 59,181,171,171,171, 67, 61,190, 11, 12,212,124, 0,243, 11,222,
+ 97, 5,171,213,234,244,163,183, 90,173, 78, 29, 52,104,144, 79, 5,199,153,133,252,233,246, 29,226,228,201,147,169, 0,154, 87,
+103,230,253, 29,154,165, 92,136,242,232,209,163,203,205,159, 26, 53,106,148,123, 30,236,217,217, 25, 83,142, 28,201, 55, 85, 45,
+ 90, 0,173, 90, 33,239,206,157,140,194, 41,100,115,115,115,211, 95,122,233, 37,169,120,179, 96,241,137, 72, 31,106, 40,174,135,
+181,172,231, 19, 29, 75, 3, 1, 32, 58, 54,223,100,233, 52,184, 94, 65,190,183,252,187,147,150,156,156,124,190, 69,139, 22,127,
+101,102,102,126, 74, 41, 77,252, 79,100, 7,165,103, 9, 33,115, 27, 54,108, 56, 26, 64, 89, 97,134, 13,142, 70,244,236,192,165,
+ 58, 86,235,216,217, 51,103, 62, 55,107,230,204,198, 10,224, 5, 64, 15,228, 55, 17, 58, 25, 65,236, 87,221,199, 43,203,114, 98,
+167, 78,157,156,254,159,138,214,151, 51,147, 56,126,128, 17, 56,227,188,230,223,145,206, 66,205, 86,173, 90,161, 77,155, 54, 69,
+223,133, 20, 95, 30, 26, 26, 10, 89,150, 19, 37, 73, 42, 87, 51, 44, 44, 12,205,154, 53, 43,115,134,246,146,125,174,238,247,177,
+ 23, 82,248,114,157,208,208, 15, 43,165,201, 40,229,254,249,119,134,254, 31,182, 62, 25, 76,147,105, 50, 77,166,249, 32,104,146,
+138, 66, 62,247,248,248,252,215,149, 85,167,102,177,132, 54,103,121,196, 52, 25, 85,140, 96, 49, 24, 12, 6,227,254, 83,104,152,
+ 30, 4, 77,194,178,131,193, 40,243,218, 40,181,169,193, 25,103, 74, 8,113,186,185,162, 34,125,166,201, 52,153, 38,211,100,154,
+ 76,147,105, 62,124,154, 21,105, 63, 44,145, 49,214, 68,200, 52,153, 38,211,100,154, 76,147,105, 50,205,251,174,249,176,193,134,
+ 14, 48, 24, 12, 6,131,193, 96, 48,131,197, 96, 48, 24, 12, 6,131,193, 12, 22,131,193, 96, 48, 24, 12, 6, 51, 88, 12, 6,131,
+193, 96, 48, 24, 12,102,176, 24, 12, 6,131,193, 96, 48, 30, 24,200,127,232, 29, 99, 12, 6,131,193, 96, 48, 24,255, 8, 44,130,
+197, 96, 48, 24, 12, 6,131, 81,205,168, 0,160,240,229,161, 0, 64, 41,101, 19,243, 50, 24, 12, 6,131,193,248, 71,120, 88, 61,
+136,138, 25, 43, 6,131,193, 96, 48, 24,247,147,135,209,131,112,165, 57, 72, 6,131,193, 96, 48, 24,140,127,138,135,209,131,112,
+ 15,179,123,100, 48, 24, 12, 6,131,241,224,243,208, 71,176, 88, 20,139,193, 96, 48, 24, 12,198, 63,205,195,232, 65,216, 52, 13,
+ 12, 6,131,193, 96, 48, 24,213,204,223, 58, 77, 3, 33,164, 37,211,100,154, 76,147,105, 50, 77,166,201, 52,153, 38, 51, 88, 12,
+ 6,131,193, 96, 48, 24, 12,102,176, 24, 12, 6,131,193, 96, 48,152,193, 98, 48, 24, 12, 6,131,193, 96, 6,139,193, 96, 48, 24,
+ 12, 6,131,193, 12, 22,131,193, 96, 48, 24, 12,198,125,130, 0, 40,117, 36, 0,165,244,130,195, 34,149, 24, 77, 80,145, 62,211,
+100,154, 76,147,105, 50, 77,166,201, 52, 31, 62,205,138,180,157,241, 31, 15,180,193,250, 59,231,193, 34,132,180,172,238, 19,197,
+ 52,153, 38,211,100,154, 76,147,105, 50,205,135, 79,243, 97,131, 53, 17, 50, 24, 12, 6,131,193, 96, 84, 51, 42,118, 10, 24, 12,
+199, 8, 15, 15, 55,232,116,186, 39, 14, 28, 56,160,185,116,233, 18, 78,157, 58, 69,215,173, 91, 39,218,108,182,125,145,145,145,
+ 22,118,134, 30, 14,218,180,105,211,131,231,249,119, 0, 64,150,229,197,103,207,158,221, 91,133,167,124, 18, 28, 28,252,134, 78,
+167,235,165, 86,171,235,201,178, 76,108, 54, 91,138,217,108,222,151,156,156,188,148, 82,170, 84, 66, 51,220,203,203,235,181,150,
+ 45, 91, 54,188,118,237, 90, 98, 66, 66,194, 6, 0,123, 1,244, 48, 26,141,207, 7, 7, 7,251, 95,184,112,225,106, 70, 70,198,
+ 42, 74,105,228,253, 74, 39,131,193, 12,150, 99, 23, 31,231,238,238,254,152, 90,173, 30,101,177, 88,218,232,245,250, 63, 57,142,
+ 91,149,158,158,190,139, 93,120, 15, 47,132, 16,190, 94,189,122,143,251,248,248, 76,200,201,201,233,224,233,233,121,230,206,157,
+ 59,159,221,184,113, 99, 47,165, 84,174,164, 38,231,226,226,210, 93,165, 82,141,180,219,237,225, 58,157,238,188,162, 40,223,230,
+230,230,238,185,159,101,169,115,231,206,231,101, 89,246, 43,111, 27,157, 78,167,222,191,127, 63,255,203, 47,191,208, 31,126,248,
+225,206,243,207, 63,239, 58, 98,196, 8, 85, 68, 68,196, 74, 0,147, 75,110,223,177, 99,199,120, 81, 20,189, 29,217,191, 90,173,
+ 78,251,227,143, 63, 2, 89,169,187,255,240, 60,255,206,136,133, 7, 59, 43, 20,136,152,214, 29, 5,230,165, 82,132,133,133,125,
+211,191,127,255, 65, 33, 33, 33, 42, 69, 81, 32,138, 34,108, 54, 91,227,168,168,168, 46,187,118,237, 10, 3,240,146,147,215,207,
+211, 83,167, 78, 93, 62,119,238,220,218,106,181,154,136,162,216,126,227,198,141, 79,142, 29, 59,246,252, 87, 95,125,213,106,232,
+208,161, 53, 10,151,207,154, 53,235, 73, 66,200, 20, 74,233,230,127, 58,157, 12, 6,163, 2,131,229,238,238,222,208, 96, 48,140,
+118,115,115,235,213,168, 81,163,164, 17, 35, 70,156, 22, 4,225, 47,158,231,233,154, 53,107,198,219,237,246, 79,252,252,252,246,
+216,108,182, 21, 25, 25, 25,177, 78, 86, 20, 13, 1,140, 0,240, 36, 0, 95, 0,183, 0,236, 2,176,154, 82,122,165, 50, 7,227,
+239,239,223,194, 96, 48,188,205,243,124, 59,147,201,228,231,226,226,146, 2,224,116,110,110,238,103,201,201,201,103, 43,163,105,
+ 52, 26,131, 0,140,209,104, 52,157, 37, 73, 10, 84,171,213, 55, 69, 81, 60, 38,203,242,138,196,196,196,171,149,209,236, 84,223,
+189, 55,117,117, 91, 32, 16,189,191,201, 38,107, 92,181,188,168,161,182, 68,217,156,253,254,169, 27,185, 91,238,119,161,240,245,
+245, 13,169, 91,183,238, 91,141, 26, 53,122,174,126,253,250,154, 97,195,134,105,186,117,235,134, 67,135, 14, 61,186,110,221,186,
+246, 26,141, 70,104,223,190,253,207, 73, 73, 73, 75,147,147,147, 29,202,119,157, 78, 23, 92,163, 70,141,215, 93, 92, 92,122, 53,
+105,210, 36,101,220,184,113,177, 81, 81, 81, 49,173, 90,181, 74, 88,177, 98,197, 91,177,177,177,139,124,124,124,118, 91,173,214,
+111,114,115,115,175,252,211,199,108,179,217,130,143, 30, 61, 10,141, 70, 83,234,122, 69, 81, 48,120,240, 96,104,181, 90,172, 88,
+177,130,156, 58,117,106,174,197, 98,153,185,124,249,114,175,136,136,136,103, 75, 51, 88,162, 40,122,255,241,199, 31, 80,171,213,
+247,232,201,178, 12, 81, 20, 33, 73, 18,108, 54, 27,122,245,234,229,205,170,163, 7, 3, 74,105, 93, 10, 96,231, 57, 43, 0,120,
+ 86, 69, 75,175,215,135, 60,251,236,179,170,244,244,116,168, 84, 42, 8,130,128, 91,183,110, 33, 56, 56,152,183,217,108,141,157,
+213,107,210,164,201,107, 11, 22, 44,240,222,177, 99,135,176,110,221, 58,123,143, 30, 61,212, 35, 70,140,112,235,214,173, 91, 39,
+127,127,127,238,187,239,190,179,237,221,187, 87, 28, 54,108,152,246,195, 15, 63,244,222,185,115,231, 32, 0,155,255,233,116, 50,
+ 24,140,114, 12,150,139,139,203, 14,173, 86, 27, 48,120,240,224,195, 51,103,206,252,194,203,203, 75, 4,128,245,235,215,251, 14,
+ 25, 50, 36,229,205, 55,223,140,207,202,202, 82,205,157, 59,183,229,218,181,107,127, 50, 24, 12,183, 45, 22,203, 19, 14, 24, 43,
+ 2,224, 77,142,227,198,180,107,215,110,135, 44,203, 87, 15, 28, 56,176,240,137, 39,158,232, 15,128,158, 57,115,230, 39, 66,200,
+119, 0, 62,119, 52,162, 65, 8,225, 27, 52,104, 48,195,207,207,111,194, 87, 95,125,165,107,208,160, 1, 92, 92, 92,144,155,155,
+107,188,114,229,138,255,132, 9, 19,250, 4, 7, 7,127,229,225,225, 49, 39, 50, 50, 82,116, 80,147,248,249,249,141,115,119,119,
+127,127,241,226,197,250,144,144, 16,226,234,234,138,164,164,164,230,167, 79,159,110,246,217,103,159,189,108, 52, 26, 63, 76, 76,
+ 76,116, 56,157,221, 9, 81, 89, 27,214,254,181,102,227,118, 93,191,250,122, 21,169,235,226, 2, 53,199, 65, 20, 4,117,162,201,
+212, 96,220, 27, 99,214,118,108, 92,231, 68,158, 58,181,207,197,139, 84,184, 31, 5, 34, 56, 56,248,188,155,155, 91,192,179,207,
+ 62,171, 30, 60,120, 48,130,131,131,139,214,189,244,210, 75,120,233,165,151, 52,215,174, 93,211,108,222,188,249,149,181,107,215,
+190,208,160, 65,131,132,184,184,184,150, 21,152,171,237, 6,131,161,254,232,209,163,207, 78,158, 60,249,176,155,155,155, 0, 32,
+249,252,249,243,242,176, 97,195,254, 26, 57,114,100, 98,110,110, 46,102,204,152, 81,127,221,186,117,155,116, 58, 93,170,205,102,
+123,242,159, 62,118,189, 94,143,171, 87,175,222, 99,132, 82, 83, 83,145,145,145, 1,139,197,130,172,172, 44, 20, 60,225, 91, 21,
+ 69, 1,199,113, 64,254,104,220,178, 34, 83,136,141,189,215,131,138,162, 8,139,197, 2, 65, 16, 96, 23, 4,168,180, 58,116,237,
+209,243, 47, 66,177, 61,215,106, 94, 26,125,252,248, 77, 86, 61,221, 31, 56,142,187,182,237,240,213, 32, 0, 2,128,152, 42,202,
+ 41, 0,112,248,240, 97,220,190,125, 27,105,105,105, 72, 75, 75,131,209,104, 68,101, 34,182, 49, 49, 49,203,195,194,194, 72,116,
+116,244, 14, 0,171, 55,110,220,216,239,206,157, 59,159, 79,154, 52,169,230,162, 69,139, 50, 39, 79,158, 60, 1,192,175, 27, 55,
+110,124,169,117,235,214,189,207,157, 59,183,236,126,164,147,193, 96,148,211,201,157, 82, 90, 47, 32, 32,224,230,154, 53,107,186,
+142, 25, 51,166,105, 70, 70,134, 26, 0,188,189,189,109, 0,144,149,149,165,122,253,245,215, 91,124,251,237,183, 93,245,122,125,
+162, 44,203,181, 75,209, 40,109,132,193, 88, 23, 23,151,167, 46, 94,188,248,113,195,134, 13,245,243,231,207, 63,232,234,234,138,
+101,203,150,237,247,247,247,247,136,141,141,253,208,213,213,181, 11,128, 9,101,164,235, 30,205,192,192,192,233,131, 6, 13,154,
+112,236,216, 49, 93,235,214,173,225,230,230, 6,158,231,225,233,233,137, 14, 29, 58,144,195,135, 15,235,250,244,233, 51, 54, 59,
+ 59,123,190,163,154, 70,163,113,194, 51,207, 60, 51, 43, 50, 50,210,208,169, 83, 39,162, 86,171,145,157,157, 13,141, 70,131, 71,
+ 30,121,132,108, 88,183,206,208, 54, 52,116,186,209,104,156,233,168,166,173, 81,237,237, 67,198, 76,238,182,253,247, 93,196,199,
+199, 7,182,185,115,145,221,162, 5,108, 83,166,160, 78,221,186,216,182, 99, 39,121,230,165, 55, 58,185,137, 62, 59, 28,213,172,
+134,167,245,187, 52,173, 86,107,112,104,104, 40,127,252,248,113,219,213,171, 87, 45, 37, 71,153, 82, 74,113,241,226, 69,243,239,
+191,255,110,242,242,242,130,221,110, 15,170, 72,147, 82, 90,183, 75,151, 46, 98, 68, 68, 68,167,209,163, 71,171,111,221,186,117,
+ 2, 64,108,205,154, 53, 19, 1, 36,165,166,166,198,189,240,194, 11,126,107,215,174,125,188,118,237,218,201,148, 82,239,251,113,
+236,133,134,170,228,167,112,185,175,175, 47,182,111,223,142, 62,125,250,160, 99,199,142, 31,245,235,215, 79,119,234,212, 41, 74,
+ 8,249,221,153,116, 42,138, 2,139,197, 2,139,197,130,196,196, 68, 44, 89,186, 12, 39,143, 31,195,198, 53,223,251,142,123, 99,
+236,235, 30, 46,110,199, 67, 59,117, 10,248,167,143,157,105, 22,173, 79,202, 55, 87,196, 76, 41,189, 81, 89,205,103,159,125,182,
+121, 96, 96,160,207,166, 63,107, 34, 83,211, 4,178,218, 3,138,214, 19,178, 87, 91,252,165,121, 10,190,190,190, 62,129,129,129,
+ 29,156,209,164,148,238,143,138,138, 26, 64, 41, 93, 69, 41,149, 41,165,191, 76,158, 60,249, 13, 66,200,150,201,147, 39,191, 69,
+ 41,253,165, 96,121,196,217,179,103, 7, 81, 74, 15,223,143,116,178,178,196, 52,255, 6,218, 1,232, 83,240,105, 15,160, 67,137,
+223,218, 18,219,245, 40,227,187, 79,137,223,237, 74,252, 95,187,106, 53, 88,132, 16, 90,248, 41, 22,193, 17, 87,172, 88,241,243,
+215, 95,127,189, 34, 45, 45,205, 39, 40, 40,104,226,163,143, 62,218,249,218,181,107, 46, 93,187,118,237,236,235,235,251,118, 84,
+ 84,148,207,192,129, 3,191,126,249,229,151,127, 36,132, 72, 14, 68,133,130, 56,142,123,243,248,241,227, 27,154, 52,105, 98, 75,
+ 73, 73,241,236,209,163, 71, 38, 0,132,135,135,231,101,101,101,213,240,246,246,150,183,110,221,250, 19, 33,228, 85, 66, 72,133,
+161,105, 63, 63,191,214,181,107,215,158, 48,127,254,124, 29,207,243,101, 69, 80,240,193, 7, 31,232,220,221,221, 95,245,247,247,
+111, 95,145,166,175,175,111,136,155,155,219,140, 79, 63,253, 84,111,181, 90, 33, 73, 18,188,189,189,225,226,226,130,140,244,116,
+164,222,188,137,172,228, 68, 76,159, 56,193,224,106, 48,140,243,243,243,107, 85,145,230,163, 13,220,158,113,245,109,218,101,252,
+132,137,176,142, 28, 9,179, 94, 15,243,219,111,195, 22, 25, 9,243,194,133,176,213,172, 9,235,147, 79, 98,226,196,119,160,245,
+ 9,238,248, 72, 64,141, 65,247,203,117,191,255,254,251,220,196,137, 19,117,219,183,111,215,119,235,214,205,190,122,245,234, 92,
+147,201,132,229,203,151,231,134,135,135, 91, 87,172, 88,161,239,216,177,163,235,227,143, 63,174,118, 48, 34, 32,174, 93,187,246,
+252,202,149, 43,231, 95,185,114, 69,221,168, 81,163,185,109,218,180,233,157,155,155,171,238,208,161, 67,159,128,128,128, 5, 81,
+ 81, 81, 53,159,126,250,233,121, 51,102,204, 88, 15, 64,196, 3, 2,207,243,224,121, 30, 26,141, 6,173, 90,181,194,198,141, 27,
+225,231,231,135,111,190,249,198,179, 78,157, 58, 46, 17, 17, 17,217, 89, 89, 89,159, 58,163,105,183,219, 97,179,217, 96, 54,155,
+241,199,233, 51,248,253,215, 45, 88,179,238, 7,188,242,218,235,153,146, 36,217,198,142,126,221,205, 77,239, 50,158, 61,255,221,
+ 31,242,251, 23, 18, 51, 64,243, 8, 33,118, 0,104,216,176,161,214,223,223,191,125,195,134, 13,181,142,234, 88, 44,150, 47,150,
+ 44, 89,226,199,233, 60,113,212,222, 27, 27,233, 92,236,241, 88,142,180,192,201,168, 99,108,132,167,159,126,218, 27,192,146,106,
+ 72,239,118, 74,233, 48, 74,233,214,202,252,255,223,157,206,240,240,240,206,225,225,225, 71,195,195,195,175, 23,124,119,174,234,
+ 49,175,152, 73, 30,251,238,125,237, 95, 95, 77, 35,230,239,222,215,254,181, 98, 38,121,140,149,220,127, 47,165,121,144, 82,240,
+ 38,132,108, 39,132,108,159, 54,109,218, 99, 0,188, 74,252,238, 84,124, 59, 0,218,210,190, 11, 63,197,150,123, 23, 24, 43,239,
+ 98,191,171, 5, 85,177,139,180,212,102, 14,163,209,104, 89,180,104,209, 30,147,201,116,224,243,207, 63,111, 55,113,226,196,151,
+252,252,252, 14, 15, 26, 52,232, 83,119,119,119,177,180,254, 37,229,240, 74,199,142, 29,127, 54, 26,141, 74, 82, 82,146, 70, 20,
+ 69,205,245,235,215,117,162, 40, 18,181, 90, 77, 45, 22,139,250,194,133, 11, 26, 81, 20,229, 22, 45, 90,108,186,112,225,194, 8,
+ 0, 83,202, 19, 52, 24, 12,163,191,254,250,107,125, 89,230, 74,150,101,228,229,229, 65,146, 36,204,153, 51, 71, 63,105,210,164,
+ 55, 0,156, 42, 79, 83,173, 86,191,177,124,249,114,189, 40,138, 69,253,103, 98, 99, 99,145,157,153, 9, 49, 47, 15, 66, 94, 14,
+164,188,108,168,204,238,152,240,210,139,250, 5,223,124, 59, 30,192,200,242, 52, 5,109,141,121,223,127,243, 45, 68, 81,132,125,
+195,134, 82,183, 17, 15, 30, 4,236,118,124,240,225, 66,242,206,232, 23,230, 0,248,241, 62,221, 96,192,243, 60, 94,125,245, 85,
+ 98,183,219,181,219,182,109,211,182,106,213, 74, 14, 13, 13,117,235,223,191, 63, 36, 73, 66,118,118, 54,244,122,189, 51,178,114,
+131, 6, 13,204, 95,127,253,245,207, 25, 25, 25,219, 62,250,232,163, 46, 75,151, 46, 29,229,237,237,189, 99,200,144, 33,211,221,
+220,220, 4,173, 86, 11, 73,146,220, 31,180,139, 95,163,209,192, 96, 48,192,223,223, 31, 3, 7, 14,196,210,165, 75,193,243,124,
+ 6,207,243,123,242,242,242, 22, 93,184,112, 33,206, 89,131,101,181, 90, 97,177, 88,112, 61,254, 6, 68, 81, 68,196,218,181, 56,
+118,240,192,123,148,210,185,235,215,124,239,178,124,229,202,254, 0,222, 97, 85,239, 63,203,224,193,131,121, 66,136,103,195,186,
+122, 19,225,168,249, 4,165, 53, 3, 2, 2, 94,146, 36,233,113,163,209, 88, 59, 33, 33, 33,221,223,223,127,175,221,110,255, 53,
+ 45, 45,205, 84, 65,164,146, 72,146,132,209,237,179, 48,182, 35, 7, 73,146,144,149,149,133,155, 55,111,226,207, 63,255,196,201,
+147,127, 86, 42,141,129,129,129,175, 24, 12,134, 39, 52, 26, 77,125, 74, 41,103, 50,153,110,218,237,246, 3, 73, 73, 73,223,210,
+ 74, 76,108,248,119,165,179, 24, 11, 6, 14, 28, 88,207,195,195, 3, 81, 81, 81,245,206,157, 59,183, 0,192,163, 85,186, 38,137,
+102,197,144, 55, 14,248,186,184,213, 65,106,236, 70,223, 29, 91,231,174, 0,208,136,149,224,127,245,131, 13,169, 96,147, 52, 74,
+233, 51, 5,134,108,251,130, 5, 11,158, 41,248,191,103,138,255,118, 96, 63,207,148, 98,240,182,151,182,188,218, 12, 22, 33,132,
+150,119,128,174,174,174,210,140, 25, 51, 78, 28, 58,116, 40,188,115,231,206,199,156, 52, 86,133,116,108,220,184,113,228,238,221,
+187,189,234,213,171,103, 83, 20,133,184,187,187, 75,110,110,110,114, 65,223, 22, 26, 23, 23,167,142,139,139,171,225,229,229, 37,
+ 3,232, 88,145,160, 90,173,238, 16, 20, 20, 84,230,141, 44, 47, 47, 15,185,185,185,176,217,108,168, 83,167, 14,225, 56,174,194,
+240,159, 74,165,234,212,168, 81, 35,146,155,155,139, 58,117,234,224,220,185,115,176,230,229, 65, 52,229, 66,202,201,133,156,151,
+ 13,154,147, 5, 83,118, 22,130,124,106, 19,158,231, 43,140,138, 73,188,193,232,235,234, 10,251,212,169, 16,254,250, 11,208,104,
+160,169, 95, 31, 16,242,187, 90, 9,241,241,128, 86, 11,110,228, 72, 52,122,237, 53, 72,208,249,222,199,130, 14,187,221, 14,179,
+217, 12,141, 70,131,231,158,123, 14,135, 14, 29, 18,218,181,107,167, 79, 76, 76,132,221,110, 7,199,113, 69,205,103, 14, 86,226,
+ 50,199,113, 20, 0,188,188,188,196, 69,139, 22,237,239,218,181,107,247, 30, 61,122,236,209,106,255, 63, 40, 96,179,217, 20, 0,
+244, 65,186,240,117, 58, 29,212,106, 53, 8, 33,168, 81,163, 6,114,115,115,113,249,242,229,250,149,209,146,101, 57,191,223, 85,
+ 65, 20, 75,150,101,252,113,250, 4,244, 6, 3, 58,116,233, 58, 93, 81, 20,131, 90,165, 2, 95,208,185,139,241,207,209,161, 67,
+135, 48, 13,149,230,191,225, 43, 4, 60, 53,208,223,164,119, 81,153, 6,238,176,119, 15,110,216, 97,192,252, 15,230,215, 8, 10,
+ 10,114,141,142,142,206,155, 63,127,190,223,153, 51,103, 0,224,135,242,244,146,146,146,182, 44, 92,184,176,102,247,238,221, 27,
+168,213,106,146,149,149,133,180,180, 52,164,166,166, 34, 33, 33,129,198,197,197, 93, 23, 69,241,103,103,210,216,166, 77,155, 47,
+135, 13, 27,246, 66,243,230,205,213,148, 82,136,162, 8,179,217,220,250,228,201,147,125,142, 30, 61,218, 9,192,171,206, 30,119,
+114,114,242, 47, 11, 23, 46,116,237,222,189,123, 99,181, 90,205, 85, 71, 58, 75, 80,207,205,205, 13,123,247,238,133,135,135, 7,
+ 0,212,171,106, 94,217, 69,193,215,197,221, 23,136,255, 20, 62,158, 1,176,139,130, 47, 43,193,255,254, 40, 86, 5, 38,235, 52,
+128, 62, 85, 53, 67,127,151,153,170, 84, 4,171,144,219,183,111,235,114,115,115, 85,148, 82, 78,150,101,149,162, 40, 68,167,211,
+ 57,219,148,211,108,208,160, 65, 63,245,234,213, 43,171, 32, 50, 32,122,121,121, 73,153,153,153,200,206,206,134, 36, 73,178,187,
+187,187,185,110,221,186,230,166, 77,155,230, 28, 56,112,160,194, 38, 66,139,197,226, 95, 90, 36,197,108, 54, 35, 47, 47,175,200,
+ 96,153,205,102,184,187,187,195,100, 50, 85,120,113, 11,130, 16, 96, 48, 24,144,150,150,134,244,244,116, 88,243,114, 32,228,230,
+ 65,202,203,129,148,147, 13, 37, 55, 27, 52, 47, 23,138, 34,163,166,183, 55,236,118,187,127, 69,154,102,155,172, 85, 3,176,252,
+252, 51,240,191,255,149,109,110, 14, 28,128, 75, 72, 8, 44, 22,225,190,205, 81, 86,252, 33, 88, 16, 4, 72,146, 4, 74, 41,181,
+219,237,176,219,237,197, 77,147,147,222, 34,223,144,157, 61,123,214, 61, 53, 53, 85, 79, 41,229,243,242,242,116, 38,147,137,171,
+ 93,187,182, 21, 0,149, 36, 73,126,208, 46,124, 73,146, 32, 8, 2, 4, 65,128,205,102,115,234,184, 75,110, 91, 56,114,176, 96,
+ 24, 60,236,162, 29,159, 45,253, 18, 91, 54,109,196,165, 75, 23,253,102,206,253, 0,162, 36, 65, 86, 88,191,226,127,138,214,173,
+ 91,247,228,121,254,179,142, 30,138,219, 4,127, 49,175,182, 86, 49,197, 46,127,203,116,206,104,176, 88, 45,130,239,130,165, 31,
+122, 81, 10,204,152, 49,227,246,144, 33, 67,106, 76,156, 56,177,197,208,161, 67,123, 52,111,222,252,199,139, 23, 47, 10,101, 84,
+226,154, 17, 35, 70,156,174, 89,179,102,208,218,181,107, 83, 83, 82, 82,106,137,162,104,176,219,237,130,221,110,191,110,183,219,
+143,139,162,120, 32, 57, 57, 57,218,153,180,186,186,186,182, 28, 58,116,168, 58, 51, 51,179,104,180, 95, 90, 90, 26,194,194,194,
+248,125,251,246, 53,171,204, 93,185,173,144, 0, 0, 32, 0, 73, 68, 65, 84,241, 95,186,116,105,169,159,159,223,225,109,219,182,
+ 61, 81,163, 70,141, 80,173, 86, 91, 71, 81, 20,217, 98,177,164, 90, 44,150,243,149, 73,103, 9, 82,162,162,162,234,185,187,187,
+ 35, 49, 49, 17, 0, 82,170,154,103, 90,181, 38, 49,245,202, 70,127, 31,143, 32, 92,187,244, 27,180,106, 77, 34, 43,201, 15,125,
+ 4,171, 93,241,136, 85, 57, 38,201, 50,117,234,212,233,132,144,237, 83,167, 78,157, 94, 78, 4, 75, 46,190, 93,177,237,109,213,
+110,176, 74,195,100, 50,169, 78,159, 62,237,117,251,246,237, 26, 62, 62, 62,166,102,205,154,101, 17, 66, 64, 41, 37, 57, 57, 57,
+ 46,169,169,169, 46,174,174,174,182,250,245,235,231, 56,184,191,191,254,247,191,255,245,155, 50,101,202,222, 23, 95,124, 49, 5,
+ 0, 50, 51, 51,113,251,246,109,100,100,100, 64, 16, 4, 36, 37, 37,145, 35, 71,142,212,217,183,111,223,227, 0,226, 43, 18, 52,
+ 24, 12,137,185,185,185,141, 60, 61, 61,139,204, 65,161,169, 42,254, 45, 8, 2,114,115,115,225,234,234, 90,225,197,173, 86,171,
+147,211,210,210,130,237, 54, 27,210, 18, 19,243,141, 85, 94, 46,228,156, 44,200, 57,217, 32,166, 92,104, 68, 17, 58,181, 26,185,
+119, 50,160,209,104,110, 87,164,233,162,227,237,118, 73,210,242,125,251, 2,164,236,114, 68, 59,117,194,157, 22, 45,160,223,254,
+179,120, 31, 11,122,169,191, 75,154, 5,103,140,198,157, 59,119,184,165, 75,151, 54,139,141,141,173,225,227,227,147,222,163, 71,
+143, 56, 66, 8,229, 56, 78, 73, 77, 77,173, 21, 27, 27,219,200,211,211,211,164, 86,171,211,238,167,145, 42,109,153,201,100,130,
+205,102,131,213,106, 69, 86, 86, 22, 84, 42, 21,186,118,237,122,192,102,179,253, 66, 8, 89,115,242,228,201,220,178, 52, 69, 81,
+188,231, 92,202,178, 92,100,178, 84,132,199, 47,155, 54, 97,217,202,101,248,249,231,109,116,200,160,129,228,208,225, 35, 80, 20,
+154,196,170,220,127, 6,158,231, 63, 60, 54,229, 57, 55, 34, 75,121, 89,251, 55,153,151, 37,104, 77,191,157,189,112,204,108,181,
+243, 13,130,131,154, 6,214,111,160,158, 57,107, 74,234,185,203,127,196,103,126,149, 89,247,221,119,223,173,223,168, 81,163, 58,
+113,113,113,193, 0, 46,151,166,233,230,230, 22, 48,124,248,240,151,179,178,178,212,223,126,251,237,186,132,132,132, 99,148,210,
+235, 37, 76, 88, 27, 66,200,135, 5,245,176, 15, 0, 25,192, 62, 74,233,250,242, 60, 59, 33, 4, 7, 15, 30,188,103,180,159, 44,
+203,149,118,229,201,201,201, 89, 29, 59,118,108, 25, 27, 27,187, 61, 51, 51,115,227, 61,245,151,139, 75,159, 22, 45, 90, 12, 58,
+117,234,212, 60, 74,233, 53,103,180, 57,142,155,242,231,159,127,126, 64, 41, 13, 32,132,220,228, 56,238,189,170,230,153, 64,133,
+ 55,118,108,153,189,220, 46,216,141, 90,141, 54, 65,160,194,155,172, 36, 63,244, 20,246,145, 66,113,227, 84,138, 49, 58,190, 96,
+193, 2,195,194,133, 11,177, 96,193,130, 63, 75,139, 96, 21, 26,173, 5, 11, 22,252, 89,184, 93,177,237, 15, 87,171,193, 42,205,
+ 57,202,178,172, 95,184,112, 97,167,230,205,155, 39,119,238,220, 57,217,104, 52, 90, 10,111, 16, 42,149, 74,244,241,241,201,150,
+ 36,201,122,251,246,237,218,135, 15, 31,110, 64, 41,117,164,243,231, 33, 55, 55, 55,205,153, 51,103,234,109,220,184,177,117, 76,
+ 76, 76, 72,159, 62,125,138,162, 3,137,137,137, 33,159,125,246,153,172,211,233,210,121,158,143, 4, 80, 97, 39, 31, 81, 20, 79,
+ 94,185,114,165, 97,135, 14, 29,136, 40,138,119,153,170,226,127,107,181, 90, 36, 38, 38, 82, 69, 81, 78, 59, 96, 48, 78,159,139,
+142, 14,110,209,164, 73,190,185,202,205,134,156,147, 13, 57, 59, 11,196,156, 7,141, 40,192,213, 69,129, 78,235,130, 63,243,159,
+200, 42,156, 45, 89, 37, 89,110,198,231,228, 52,170,191,104, 17, 52,158,158,128, 32, 20, 53, 11, 2, 40,106, 46,164, 41, 41, 56,
+115,226, 4, 84,138, 45,249,126, 26,141, 90,181,106, 33, 39, 39, 7, 54,155, 13,148, 82, 80, 74,139, 12,149, 86,171, 69, 65,127,
+ 41, 71, 67, 87, 30,253,251,247,127,180, 67,135, 14, 49,175,190,250,234,254,102,205,154,221, 40, 44,235, 46, 46, 46, 66,147, 38,
+ 77,146,109, 54, 91,222,245,235,215, 67,214,174, 93,219, 73, 81,148, 26,247,227,184, 75,154,161,194, 8, 94,161,185, 74, 75, 75,
+195,174, 93,187,112,252,248,113, 92,188,120,177,221,201,147, 39, 91,109,217,178,229,221,230,205,155,119,184,120,241,226,109, 71,
+ 13, 86,225,185,164,148,130,230,143,142,199,214, 95,127, 71,239, 62,221, 72,174, 41, 7,219,119,236, 6,165,180, 30,171, 79,255,
+ 49, 76,144,100,147,237,208, 6,243,171,151,116, 89,105,118,204,139,142,142, 60,210,167, 79,159,189,193, 13, 26,187, 3,128,221,
+ 70,107,186,104,188, 12, 42,149, 74, 11, 0, 1, 1, 1,225,148,210,207,145, 63, 18,233, 30, 6, 12, 24,208,177, 78,157, 58,173,
+119,238,220,121, 62, 33, 33,225,120, 73,115, 5, 0, 33, 33, 33,239, 93,184,112,225, 73,181, 90, 77,138, 85,254, 20, 64,169, 6,
+235,217,103,159,109,100, 52, 26,107,237,184,226,129, 28, 77, 48, 20, 46, 11,148,215, 65,246,108,141, 27,154,230,168, 91,247,114,
+173,198,141, 27,183,186,114,229,202,121,103, 14,158, 16, 98, 28, 50,100,200,207,171, 86,173, 10,233,213,171,151, 22,192, 61, 6,
+171,105,211,166,253,247,237,219,247,236,216,177, 99, 91, 17, 66, 6, 81, 74, 29,158, 3,240,244,233,211, 39, 0, 84,107, 39,244,
+ 49,243,232, 1, 0, 77, 88,209,253,207, 68,175,128, 98,125,176, 0,164, 33,255, 93,202,197,127, 23,206,117,105, 47,182,109, 90,
+177,168,149,189, 68,212,171,180,117,105,168,198, 65, 86,170,114,110,178, 7, 79,157, 58,213, 38, 60, 60,252, 90,161,185, 42,188,
+ 30, 11,255,112,117,117,181, 3,160, 49, 49, 49,205,100, 89, 62,238,192,254, 86, 71, 70, 70,238,248,242,203, 47, 63, 14, 8, 8,
+176,245,239,223,159,251,224,131, 15,182, 23, 70,177,150, 44, 89, 66,123,247,238,253, 91,108,108, 44,185,116,233,210,123, 0,158,
+173, 72,208, 98,177,172,124,243,205, 55, 7, 29, 57,114, 68,111,183,219,145,149,149,117, 87,244, 42, 55, 55, 23,146, 36,129,231,
+121,124,249,229,151, 54,147,201,244,101,133, 79, 71,130,240,237, 71, 31,125, 52, 96,253,234,239,244,188,104,135, 53, 43, 19, 74,
+ 78, 22, 56,179, 9, 42,193, 14,157, 90, 70,189, 70,174,200, 77,213, 96,217,174,131, 22, 81, 20, 87, 86, 24, 21,179,153,166,191,
+ 49,122,212, 79,123,246, 31,128,250,241,199, 33,238,220,121,239,147, 94,157, 58,176, 10, 2, 22,204,159, 71,137, 37,107,230,253,
+ 40,232,106,181,250,242,168, 81,163,234,140, 30, 61,186,102,203,150, 45, 33, 8, 2, 68, 81, 44,138,188,120,121,121, 1, 0, 18,
+ 18, 18, 16, 21, 21,149,205,243,124,133,209, 59, 89,150, 15,221,184,113,163,249,200,145, 35,175, 62,245,212, 83, 62,130, 32,168,
+ 50, 51, 51, 83, 10,158,140, 85,254,254,254, 6,173, 86, 75, 82, 83, 83,179,238,220,185,227,163, 40,202,241,251,113,236,162, 40,
+226,253,247,223, 71, 68,108, 44,134,135,132, 20,153, 77,155,205,150,223,156,103,183, 99,247,238,221, 56,124,248, 48,214,173, 91,
+151,241,220,115,207,121,188,248,226,139, 30,235,214,173, 27, 7,224,189,178,204,234,228,201,147,177,237,250,117,244, 45,165,175,
+ 32,165, 4, 73,201, 73, 16, 69, 17, 63,255,188, 39, 89,173, 82,123, 46,249,120,161, 97,210,244,233,132, 85,187,255, 12,138,162,
+204,238,188,120,203, 56,142,115, 17, 0, 44,143,142, 62,115, 28, 0, 12, 6,131,247,226,197,139,181, 0,176,232,227, 69,106, 74,
+169, 90,146, 36,216,237,118,204,155, 55, 79, 63,122,244,232, 50, 71, 27,253,248,227,143, 89,115,231,206,173,245,218,107,175,245,
+ 60,120,240,160,142, 16,178,167,224, 65, 44,163, 32, 82, 85, 27,192,137,218,181,107,215,221,180,105, 83,208,147, 79, 62,233, 90,
+ 81, 58,173, 86,235, 87, 43, 87,174,172,191,248,176, 27,118,152, 6, 34,129, 14, 1,173, 69, 81, 75,147,139,102, 53,110,162, 91,
+189,132,122,235,214,173, 91, 14,192,225, 81,122,132,144,166,207, 61,247,220,198, 85,171, 86, 5,142, 26, 53, 42,233,248,241,227,
+137,132,144,210,202,114,198,240,225,195,111, 70, 68, 68, 4, 41,138,178,149, 16,210,223, 25,147,197, 96, 84, 3,167,255,166,109,
+255, 54,202, 51, 88,227, 9, 33,205, 22, 45, 90,244,193,183,223,126,219, 97,250,244,233, 7, 59,118,236,152, 89,104,176,110,221,
+186, 85,235,200,145, 35,221,205,102,179, 36,203,242,184,210,230,196, 40,249,182,109, 74,233, 77, 66,200,103,157, 59,119,126, 97,
+205,154, 53,235, 92, 93, 93, 51,247,238,221, 91,203,215,215,247, 78,100,100,164, 59,199,113,185, 87,174, 92, 81,237,221,187,119,
+ 40,128,149,165, 93,192, 37, 53,147,146,146,206, 53,104,208,224,243,119,223,125,119,194,204,153, 51,245,133,115, 12,229,230,230,
+194,106,181, 66,173, 86,131,231,121,108,216,176,193,102,183,219,191, 75, 76, 76, 60,229,128,230,201,192,192,192, 85,159, 44,250,
+100,212, 91, 35, 94,209,114, 57, 89,176,220, 73, 7, 4, 27,116, 42, 14,198,240,154,176,100,242, 88,190,235,168, 61,205, 98,249,
+ 41, 33, 33,225, 72, 69,154,199,110,228,236,236,216,200,251,192,188, 57,179, 30,155,250,227,143,128, 44,131,188,242, 10,176,111,
+ 31,208,178, 37,148,228,100, 88, 5, 1, 51,166, 77, 1,111, 73, 61,118,242, 70,222, 47, 21,105, 86, 7, 37, 53,111,222,188,217,
+ 65,146,164, 97,115,231,206,157, 29, 28, 28,172, 30, 49, 98,132,103, 96, 96, 32, 20, 69,129, 70,163, 65, 82, 82, 18, 78,157, 58,
+149,115,231,206, 29,129, 82,250,126,114,114,242, 15, 21,105,202,178, 60,150, 16,210,236,157,119,222,153,247,193, 7, 31,168, 63,
+249,228,147, 19, 61,123,246,244, 83,171,213,154,214,173, 91,123, 31, 62,124,216,176,101,203,150, 39, 76, 38, 19, 40,165, 19, 28,
+ 41, 75,213,125,236, 26,141, 38,237,242,229,203,181, 23, 45, 90, 68,110,101,101, 97,182, 70, 3,161, 96, 0, 66, 97,228,110,214,
+172, 89,112,117,117,197,146, 37, 75,112,250,244,233, 37, 25, 25, 25,111, 47, 93,186,212,107,195,134, 13,131, 11, 13, 86,113, 77,
+189, 94,127,227,220,185,115,198, 21, 43, 86,112, 9,146,132, 79, 69,241,158,136,214,228, 25,239, 65,176, 11, 32,132, 71,212, 31,
+135,231, 63,218,253,137,185, 53, 61, 61, 13,138, 66,233, 63,153,239,255,101,205,179,103,207, 30, 2,112,168,156,167,235,194,135,
+ 57,164,167,167, 35, 61, 61, 29, 30, 30, 30,133,147, 38,151,170,105,177, 88,206, 79,153, 50, 37,122,197,138, 21, 61,143, 29, 59,
+246,220,161, 67,135,158,218,191,127,191, 53, 62, 62, 94, 18, 69,145,214,171, 87, 79,245,232,163,143,234,123,247,238,237,162,211,
+233,184, 25, 51,102,100,204,159, 63,223,171,192,128,149,170,169, 40, 10,175, 40, 10,222,238,146,131,201,143,169, 96,179,229, 63,
+ 80, 38, 39, 39,225,226,197,139, 56,126, 60, 6,132, 16,206,201,243,249,201,186,117,235, 26,104,181, 90,178,126,253,122,227,250,
+245,235,223,168,232,252,173, 89,179,166,254,250,245,235, 63, 39,132,244,161,148, 42,172, 44, 49, 77,134,147, 6,171,160, 98,185,
+ 4, 96, 0, 33,164,211,164, 73,147,230,248,251,251,103,200,178,172,217,182,109,219, 83, 57, 57, 57,181,100, 89,158, 69, 41, 61,
+234,100, 40,112, 21, 33, 4, 67,135, 14,157,230,239,239,255,219,159,127,254,249,216,115,207, 61,183,105,219,182,109,143,203,178,
+124,227,218,181,107,211, 1,124, 9,224, 43, 71, 53,227,227,227, 63,220,179,103, 15, 57,113,226,196,248,169, 83,167,234,124,124,
+124,136,167,167, 39, 44, 22, 11, 18, 18, 18,232,234,213,171,109,118,187,125,133,135,135,199, 28, 71, 53,107,213,170, 53,115,207,
+177, 99,218,243, 23, 47,188,244,191,231, 7,235,235,251, 25,225,198, 25,145,123, 39, 3, 71,143, 37,225,243,221, 71,172,233,118,
+251, 38,142,227, 28, 30, 74,239,127, 53,189,255,158,205,223,110, 57,124,240,224, 99,243, 22,124, 68,154,188,246, 26, 92, 26, 52,
+ 64,118,163, 70, 56,117,248, 48, 22,204,159, 71,121, 83,234, 49,233,234,237,103,238, 87,129, 40,120,199,224,247,129,129,129,155,
+174, 92,185, 50,122,250,244,233, 83,195,194,194,168,205,102,211,236,216,177,195,148,146,146,162, 40,138,242,177, 90,173, 94, 17,
+ 31, 31,111,115, 66,247, 18,128,103, 9, 33,157, 70,142, 28, 57,219,207,207, 47, 85,146, 36,213,228,201,147, 31,203,204,204,172,
+ 67, 41,157,237,108, 89,170, 78, 4, 65,120, 98,210,164, 73, 7, 0,212, 40,222, 28,122,215,197,162, 82,105,114,114,114,136,162,
+ 40,162,213,106, 77, 43,140,140,150,117, 29,137,162,248,216,204,153, 51, 15, 88,173,214,250,101,237, 87,163, 55,224,232,241, 19,
+ 24, 54,116,136,172,226,249, 15, 94, 28, 58, 68,123,252,143,147, 50,165,202, 86, 86, 61, 61,152, 80, 74, 81,240, 48, 64,203,217,
+ 38,129, 16,242,222,153, 51,103,244, 99,198,140, 9, 29, 54,108,152,219,227,143, 63,238, 90, 34,250,174,108,219,182,205,188,114,
+229,202,140, 67,135, 14, 69,142, 28, 57,178, 31,242,103,143, 47,149,228,228,228,157,203,150, 45,243,232,214,173, 91, 67, 89,150,
+145,158,158, 94,212, 7, 43, 49, 49, 17, 55,110,220,184, 41,203,242,111, 78, 30,206,255, 94,124,241,197, 95, 34, 34, 34, 2, 70,
+141, 26,149,180, 97,195,134,223, 0,148,214,167,214,117,224,192,129,125, 34, 34, 34, 2, 70,143, 30,157, 0,224, 29, 54,195, 59,
+131, 81, 5,131, 85,172,178, 56, 14,224, 9, 66,200, 51,132, 16, 47,171,213,186,134, 82,186,189, 10, 21,212, 42, 66,200,222,132,
+132,132,225, 0,252,190,248,226,139, 47, 0, 36, 2,184, 2,160, 95,105,253, 21, 28, 48, 5,115,253,253,253,183,204,158, 61,187,
+ 90,222, 69, 88,240, 74,157,137,190,190,190, 63,190,247,245,234, 41,138,162,180, 81, 68,161, 22,120, 85, 22,207,243,231, 68, 81,
+252, 40, 33, 33,193, 41, 67,176, 57, 63,157,125, 59,212,119,127,122,202,216, 97,243, 37,222, 16, 96,178, 73, 90, 23,173,202,174,
+161,214, 4,206,146, 61,251,100,124,238, 3,113, 99, 45, 48, 79,159, 55,108,216,112,245,169, 83,167,222, 5, 48, 38, 47, 47,111,
+165, 94,175,255,228,234,213,171,185, 85,200,251,227, 0,122, 20,148, 37, 31,179,217,188,177, 42,101,169,186,136,140,140,188, 30,
+ 30, 30, 30, 12,192, 80,214, 54, 60,207, 47,221,185,115,231,179, 61,123,246,180,218,108,182, 69, 61,123,246, 84, 69, 71, 71, 83,
+ 74,233,129,210,182, 63,121,242,100, 42,128,114, 71,118,133,118,234, 20, 16,177,102,205,241, 17,195,135,187, 45,255,108, 73,205,
+211,145, 81,242,119, 17, 17,185, 38,171,117, 41,171,158, 30, 12, 10, 3, 85,106,181, 26, 46, 46, 46,112,119,119, 71, 90, 90, 90,
+133,131, 60, 40,165,215, 8, 33, 3, 39, 77,154,212,105,210,164, 73, 79,249,249,249, 53,171, 95,191,190, 63,199,113, 92, 74, 74,
+ 74,122, 66, 66,194, 77, 65, 16, 14, 0,216, 9, 64, 19, 20, 20,116, 14,192,134,178,244, 46, 94,188,248,145,159,159,223,225, 95,
+126,249,229, 41,189, 94,223, 68,163,209,212, 20, 4,129, 51,155,205,153,118,187, 61, 70, 16,132,223,147,146,146,254,112,242,122,
+252,139, 16,242,180, 74,165,250,121,213,170, 85, 33, 41, 41, 41,245, 15, 29, 58,116,207, 36,199,225,225,225, 95, 71, 68, 68, 4,
+140, 29, 59,246,250,250,245,235, 7,177,230, 65, 6,195,129,186,163, 18,243,210, 57, 83, 49, 61, 84,161,206,192,192, 64,157,163,
+ 81, 27, 22, 58,126,248, 52, 91,182,108,233, 89,167, 78,157,193,227,199,143,215, 54,105,210, 4, 49, 49, 49, 88,190,124,185, 61,
+ 57, 57,121,243,133, 11, 23,178, 42,155,206,208, 78,157, 2, 92,245,250,241, 0,121, 6,160,219, 77, 86,235, 93,239, 34,100,121,
+116,127, 52,251,247,239,191, 69,167,211, 53,224, 56,142, 80, 74,105,225,171,147, 10, 71,128,218,237,246,184,253,251,247, 15,120,
+ 24,142,157, 16, 98,108,223,190,253,156,152,152,152,221, 57, 57, 57,247,116,114,215,233,116,125,194,194,194,134,158, 56,113, 98,
+118,201, 81,132,172, 44, 49, 77, 70, 21, 34, 88,140,187,162, 58,140,255, 40, 5, 38,170,104, 64, 67, 80, 80, 16,250,244,233, 83,
+101,221, 2, 51,245, 14,216,204,237, 15, 20, 91,183,110, 29,240, 95, 57, 86, 74,105, 2,202,153,164,212,102,179,253, 6,224, 55,
+ 86, 42, 24, 12,199, 97,179, 69, 51, 24, 12, 6,131,193, 96, 84, 51, 4, 64,203, 50,158,104, 28, 14,253, 17, 66, 90, 86,226,137,
+233, 2,211,100,154, 76,147,105, 50, 77,166,201, 52,255, 91,154,197,180,231,150,177, 42,169, 64,231,235,127,181,193, 98,125,176,
+152, 38,211,100,154, 76,147,105, 50, 77,166,121,191, 53, 75,232,143,250,183, 27, 44,214, 68,200, 96, 48, 24, 12, 6,131,193, 12,
+ 22,131,193, 96, 48, 24, 12,198,131,141, 67,163, 8,181, 90,109, 51, 0, 47, 3,168, 67, 8,185, 77, 41, 93, 99,183,219, 47,253,
+215, 78,150, 86,171,109, 70, 8,121,153, 82, 90, 7,192,109, 0,247,247, 60, 16, 66,230,204,206,159, 89,127,214,108, 80,252,157,
+237,189, 12, 6,131,193, 96, 48,170,110,176, 26, 4, 4, 60, 71, 56,124, 34, 74,138,167,167,167, 39,183,108,217, 50,174,111,223,
+190,216,182,109, 27,198,191,245,214, 27,254,254,190,138,154, 87,101,129,202,239,198,221, 76,250,201,145,157, 13, 28, 56, 48, 94,
+ 20,197, 50,223,223,197,243,124,218,150, 45, 91, 2,171,122, 80,126, 97, 67,226, 69, 81, 40,115, 63, 42,149, 58, 45, 57,122,179,
+ 67,251, 9, 8,240,123,142, 3,249, 68, 82, 20,207,154, 53,107,114, 95,124,241, 69,209,121, 24, 55,110,220, 27, 70,127,127, 69,
+173,226,178,168,130,119,227,110,222,252,233, 31,203,185, 98,230, 10, 0,230,204, 6,153, 69, 8, 30, 72,147, 85,144,214, 89,179,
+ 64, 1,102, 2, 25, 12, 6,131,241, 31, 54, 88,132,208,207,214,175,252,196, 51, 35, 35, 19, 27,182,238, 66,211,166, 77,113,241,
+226, 69, 52,109,218, 20,143,182,111,205,245,122,164, 13,199,115,168,253,254, 23,107, 63, 3,224,144,177, 16, 69,209,251,151, 95,
+126, 1, 33,164,104,194,190,194, 73,251,114,115,115, 49, 97,194, 4,239,234, 56, 40, 81, 20,188,175,159,254, 25, 42,158, 64,146,
+ 41, 4,137, 66,148, 20, 8, 50, 69,142, 89,194,227,125, 94,116,120, 63,132,146,207,190,251, 98,145,103, 86,118, 54,126,222,177,
+231,174,243,240,120,231,118,220,224,222,221, 57, 23,131,166,246,232, 41, 31, 57,124, 30,170,131,226,230,234, 46,147, 5, 60,112,
+ 6,166, 48,173,115,230,128, 0,249,211, 98,207,158, 13, 74, 89,196,141,193, 96, 48, 24,255, 53,131,101, 19,101,207, 58,181, 60,
+176,250,187,239, 48,121,234, 60, 52,105,210, 4,148, 82, 16, 66, 48,125,230, 92,124, 58,111, 42,134, 62,221, 21,162,164,120,150,
+165, 81,198,140,193,136,139,139,131,197, 98,185,235,211,162, 69, 11,135, 18,236,232,168, 5, 21, 79,240, 91, 84, 46, 4, 81,129,
+ 32, 21,124, 68, 5,143,181,116,115, 74, 83,148, 21, 79, 79,143, 26, 88,181,242, 43, 76,154,187,232,174,243, 48,101,250, 76, 44,
+ 95,248, 30, 38,142,125, 5, 54, 81,246,172, 76, 58,157,225, 97,210,156, 61, 27,100,206, 28, 66, 28,109,218,100,231,147,105, 50,
+ 77,166,201, 52, 31,110,205,135,210, 96, 17, 66,186, 1, 56, 88,112,210,138, 34, 35,162,221,138,230, 70, 47,124,181,248, 3, 80,
+112, 80, 64, 1, 5,160,138,136, 6,181, 93, 96, 49,155,157,222,161,162, 40, 16, 4, 1,162, 40,226,235,175,191, 70, 94, 94, 30,
+ 20, 69, 65,211,166, 77, 1, 0,225,225,225,197, 69, 19, 34, 35, 35,155, 84,164,233,221,178,127, 12, 1, 49, 22, 95, 54,107,209,
+183, 56, 22,117, 13,148, 2, 58,131, 11, 6, 13, 27, 13, 89,161, 16, 68,231,223, 79,106, 53,153, 81,167,134, 26,159,206,159, 9,
+ 78,173, 1, 7, 2,142, 35,224,136,130, 38,254, 53, 97,179, 88,254,241,140,155, 53, 27,180,100, 20,107,214,108, 80,204,250,119,
+ 21,192, 7,186,105,147,193, 96, 48, 24,127, 59,101,121,144,135,194, 96, 1, 56, 88,218, 65,217,173,102,248,215,212,160,110, 13,
+ 15, 72,146,140, 63,133,122,200, 53, 91, 33, 8, 34,110, 8, 2,174, 70,167,160, 83,167, 78, 24, 48, 96, 64,158,221,110,135, 70,
+163,201,217,186,117,171, 95, 69, 6, 75, 20, 69, 8,130, 0,147,201,132,117,235,214, 65,165, 82, 21,189, 56,181,240, 62, 75, 41,
+ 69,231,206,157,141, 14,101, 14,136,241,234,169,159,224,166,231, 33, 41, 20,146, 68, 33,201,128,164, 80,152,237, 10, 6,142,124,
+ 15,146,162, 64, 86, 20,216,133,138,239,227,119, 25,182, 90,237,208,127,218, 6, 0, 53,138,214,187,235, 40, 38,119,230,160,209,
+234,160,213,240,176, 89,204,255,124,206, 81, 74,103, 17,130,127, 91, 39,247, 89,179,168, 2, 16,146,223, 92, 88,204,100, 61,128,
+ 77,155, 12, 6,131,193,248, 71, 56,248, 48, 25,171,146, 6,171,200, 69, 82, 74, 15,253,191,193,178, 64, 18,101,136,146, 12, 73,
+148,144,157,103,193,199, 31,127, 12,157, 78, 7, 66, 72,145, 89, 82, 20,133, 19, 69, 17,189,123,247,246,172,104,135,178, 44, 23,
+ 69,176, 40,165,224,121, 30, 29, 58,116,184,103,187, 63,254,112,234,165,240,112,211,243,104,208, 99,218, 61,203, 79,254,244, 1,
+ 40,165,144,101, 10, 73,166,176, 75,114,149, 13, 91,104,183,193,176,217,197,252,238,218, 20,176,154,205,247, 39,247, 40,165, 69,
+198,228, 95, 21,185,162,116,214, 44,208, 57,115, 8,155, 38,132,193, 96, 48, 24,165,122,144,135,202, 96, 33, 63, 68, 87,228, 34,
+109, 22, 11, 68, 81,130, 36,201, 16,197,124, 99,100, 48, 24,208,181,107,215,194,251,123,209,247,174, 93,187, 32, 8, 66,133, 59,
+ 44,236,212, 46, 8, 2, 20, 69, 1,165, 20, 27, 54,108,128, 90,173, 46,250,104, 52, 26,167, 15, 68,146, 41,166, 77,121, 27, 26,
+ 53, 7, 53,207, 65,163,226,160, 86,241,144, 41, 5,165,128,162, 80,200, 10,133, 77,116, 44, 80, 82,158, 97, 3, 0,193, 38, 0,
+148,130,130,194, 98, 50,177, 43,131,193, 96, 48, 24,140,170,113,151, 7,121, 88, 12, 86,119, 66,200, 61,206,195,110, 49, 21, 68,
+175,100,136,146, 84,100,160, 22, 47, 94, 12,149, 74, 5,173, 86, 11,149, 74, 85,100,136, 28, 49, 88, 86,171, 21, 65, 65, 65,176,
+219,237,104,218,180, 41, 40,165,120,254,249,231,239,217,238,212,169, 83, 78, 29,136, 40, 83, 44,248,104,201, 61,203,143,110,158,
+135, 86,205, 26,160, 93, 35, 87, 88, 5, 5, 57,102,169,202,134, 13, 0,172,118, 17, 10,242, 39, 29,176,152,204,236,178, 96, 48,
+ 24, 12, 6,163,114,148,234, 65, 30, 10,131, 85, 16,146,187,199, 53, 90,205,102, 72,162, 84,100,178,236,118, 59, 20, 69,193, 91,
+111,189,117,143,208,190,125,251, 96,183,219,203,223,153, 74,149,246,250,235,175,223, 53, 69, 2,165, 20, 63,253,244, 19,116, 58,
+221, 93, 81, 44, 66,156, 51,177,162, 76, 49,251,189,119,161, 85,241, 80,171, 10, 13, 17, 7, 69, 1,182,253,182, 27,219,126,219,
+ 93,180, 45,207,171,211,170, 98,216, 0,192,110, 23, 0,154, 31,129, 51,229,229,178,203,195, 65, 8, 33,132, 77,207,192, 96, 48,
+ 24,140, 98, 62,160, 84, 15,242, 80, 24,172,178,176, 90, 76, 16,139,245,193, 18, 4, 1,146, 36,225,235,175,191,190,171, 57, 79,
+173, 86,131,227,184, 10, 35, 88,191,252,242,203, 93,147,123,134,135,135,155, 41,165, 24, 52,104, 80, 81,115,227,171,175,190,138,
+ 81,163, 70, 57,109,176, 36,153, 98,206,252,197, 69, 58,189,123,116, 65,255,167,187, 65, 41,184,149,167, 94,216,226, 82, 93,134,
+ 13, 0,236,182,252, 62, 88, 20,128, 57,151, 53, 17, 58, 74,209,244, 12,179,168,194,206, 6,131,193, 96, 48, 30, 86,202, 52, 88,
+106, 21,151,115,245,198, 45,247,218,174, 6, 72,138, 21,178,146,223,111, 74,150,101,140, 26, 53,170,104,187, 23, 94,120, 1, 47,
+191,252,114,169, 6,203,145,183,109, 43,138,130,163, 71,143,130, 16, 2,142,227,138, 62,229, 68, 64, 74,213, 52,217, 20, 28,219,
+ 52, 23, 10,165, 80, 40,160, 20, 12, 72,176, 73, 21, 7, 75, 74,211,172,200,176,233,220, 60,193, 19, 10, 66,128,171,137,183,161,
+226,185, 28,103,143,221, 89,254,173,154,179,103,131,206, 46, 49,165,132,179, 29,220,217,249,100,154, 76,147,105, 50,205,135, 91,
+243, 63, 99,176, 8, 37,239,172,216,254,199, 98, 81, 86,220, 11,151, 53,111,222, 28,130, 32, 96,231,206,157, 69,198,131,231,249,
+162, 38, 61, 71,250, 96,149, 32,161,107,215,174,229, 77,197,144,224,136, 8, 5, 77,104,251,216, 16, 99,121,235,157, 77, 88, 69,
+134,109,213,161, 63,255,255, 36,114, 92, 14, 71,200, 59,172, 56,149,113,254,105,225,120,203,187,167,103, 96, 48, 24, 12, 6,227,
+ 63,103,176,226, 19, 18, 54, 0,216, 80,124, 89,239,222,189, 83,251,247,239,111,144, 36, 9, 54,155, 13,130, 32,192,110,183, 67,
+ 16, 4,216,108, 54,232,245,122,167,102,220,116,100, 18, 81, 71, 72,187,176,181, 73,117,158, 20, 71, 12, 91,114,114,114, 19, 86,
+124,156,183, 90,249,239, 35,100, 70,139,193, 96, 48, 24,255, 81,131, 85, 26, 22,139,197, 23,128, 42, 41, 41,233,158,117,183,110,
+221, 2, 0,233, 97, 56, 41,213,109,216, 24,229, 27,173,127,227, 12,244, 12, 6,131,193, 96, 84,155,193, 58,120,240,160,244,176,
+152, 40,198, 3,100,180,152,185, 98, 48, 24, 12,198, 67, 6,155, 73,155,193, 96, 48, 24, 12, 6,163,154, 33, 0, 90,150,182,194,
+153,209, 1,132,144,150,206,238,184, 34,125,166,201, 52,153, 38,211,100,154, 76,147,105, 62,124,154, 21,105, 83, 74, 47, 16, 66,
+ 70, 81, 74,191,254, 87, 27,172,191,115,206, 71, 54,132,149,105, 50, 77,166,201, 52,153, 38,211,100,154,149,208,255,215, 27, 44,
+214, 68,200,184,111,132,143,142, 50,176,179,192, 96, 48, 24,140,135, 17,213,131,152,168,240,240,240,186,148,210, 48,142,227,106,
+ 82, 74,247, 70, 70, 70,222, 98, 89, 85,169, 39, 0, 21,165, 84,122, 16, 53,141, 67, 55,253,172, 83,242,158,244,237,127, 41,161,
+147, 70,223, 98,243,230, 65, 50,203, 49, 6,131,193, 96, 48,131, 85, 64,251,246,237, 3,101, 89,126, 17,192, 80, 0,231, 35, 35,
+ 35, 95,116, 86,227,145, 71, 30,209,139,162, 56, 6, 64,123,112,170,176,198,173,187,214, 11,235,208, 21,153,102, 5,123, 55,125,
+ 18,215,189,123,247,182, 7, 15, 30,180, 57,163,217,182,109,219,159, 41,165,189,202, 48, 9, 31,158, 57,115,102,190, 51,122,109,
+218,180,233,193,243,252, 59, 0, 32,203,242,226,179,103,207,238,125, 16, 51,212,219,219,219,213,221,221,253,189,134, 13, 27,246,
+120,241,197, 23,131, 59,119,238,156,145,156,156,124, 90, 20,197,133, 73, 73, 73,231, 43,171,233,233,233,249, 94,139, 22, 45,158,
+124,245,213, 87, 27,116,238,220, 57, 35, 41, 41,233,180, 36, 73,149,210,236, 56,241,100,125,106, 74,239,245,203,138, 55, 49,118,
+222,134,128,243,146,254, 69, 0,107,156, 54,226,163,127,169,203,169,120,213,233,229,253, 18, 1, 32, 48, 48,176,190, 40,138,221,
+ 20, 69,105,165, 82,169,206,243, 60,127, 40, 62, 62,254, 70, 85,206,231,191, 69,147,193, 96, 48, 24, 15,129,193,106,222,188,185,
+171, 70,163, 25,192,113,220,176, 54,237, 58,119,234, 55,232, 21, 34,114, 6,124,240,246, 11, 78, 71, 54,194,195,195,219,131,240,
+ 95,191, 60,126, 65,112, 64, 80, 83,232, 92, 60, 96,178, 3,183,179, 21,104,205, 50,140,173,175, 54,184,126,114, 67, 39, 0,251,
+157,209,165,148,246,218,180,227, 36, 82,178,100, 16,146,223,155,159,227,128, 60,171,130,233, 35, 30,157, 14,192, 41,131,197,113,
+220,180,145, 11, 15,181, 87, 40,240,221,212,174, 26, 0, 15,156,193,242,245,245,125,164, 99,199,142,107,222,126,251,237,186, 94,
+ 94, 94,112,117,117,133, 90,173,174,147,148,148,212,119,220,184,113, 79,251,249,249, 77, 73, 74, 74, 90,225,172,102,175, 94,189,
+214,189,251,238,187, 62,132, 16,168, 84, 42,104, 52,154, 58, 73, 73, 73,125,223,121,231, 29,167, 53, 9, 33, 92,139,199, 71,140,
+112,243,233, 10,142, 35,240,112,213, 35, 59,254,252,224,192,192,183, 54,199,199,199, 59,108,162, 67, 71,239,152, 73,161,155,164,
+ 72,132,180,124, 97,229,206, 59,135,231,222, 12, 9, 9, 33, 35, 70,140,184, 35,203,178, 69, 20, 69,239,136,136,136,113,190,190,
+190,148,227,184,131, 54,155,237,104,122,122,122, 94,121, 9,155, 83,240, 58,159, 53,107, 60,107,216,237,134, 71, 41,165, 93,155,
+ 52,105, 66, 70,142, 28,153, 33,138,162,197,106,181,250,172, 89,179,198,113,205, 98,212,174, 93,187,134, 86,171,237, 66, 41,237,
+ 86,165,116, 22, 99,112, 15,114,118,243, 94,218,166,178,235, 75, 28,190, 7, 0, 61,165,244,150, 3,219,250, 0,112,161,148,198,
+253,211,154,127, 7,126,126,126,217,148, 82,181, 51,255,163,209,104,106, 57, 83, 94, 25, 12, 6, 51, 88,229, 85,128, 36, 52, 52,
+180, 51, 33,228,165,192,160,134, 3, 6,190, 56,218, 16,216,168, 37,242, 20,119,196,165, 83, 68, 29,248, 1,132,144,159, 28,213,
+107,216,176,161,214,195,195,227,253,128,198,109,199,143,154, 56,155,187,112, 91,143, 67,113, 50, 84,156, 29, 60, 0,187, 57, 13,
+ 57, 41, 49,184, 29,123,208, 34,203,242,201,202, 28, 92, 82,166,132,195, 49,118,240, 92,190,185,226, 57, 2, 85,229,231, 15,175,
+ 75, 1,252,126,206, 2, 66, 72,189, 7, 45, 35,141, 70,227,147,125,251,246,221, 60, 97,194, 4,149,217,108,134,213,106, 5,165,
+ 20,122,189, 30,190,190,190,248,233,167,159, 84, 67,135, 14,253,216,223,223,255,108, 98, 98,226, 41, 71, 53,135, 15, 31,190,249,
+205, 55,223, 84,197,196,196, 64, 16, 4, 24, 12, 6,232,245,122,212,170, 85, 11, 17, 17, 17,170,215, 94,123,205, 33,205,166, 77,
+155,118,208,233,116,243,218,181,107,215,182, 97,176, 55,159, 94,171, 49, 0, 32, 32,168, 17,220,112,187,235,245, 20,159,180,176,
+176,176, 88,179,217, 60, 63, 54, 54,246,215,242,180, 90,190,177,195, 83, 5,242,246,138,183, 59,113, 42,158, 39, 99, 63, 61,218,
+123,253,175,135,150,117, 13,111,152, 9,192,180, 99,199, 14,107,239,222,189,237, 35, 71,142, 20, 98, 99, 99,185, 79, 63,253,180,
+245,254,253,251,251,249,251,251, 31, 73, 76, 76,252,161, 52,205, 57,179, 65,118,164,252,122, 89, 16, 37,255,154, 93, 69,219,211,
+254, 23,191,120,237,181, 81, 57,254,254,254, 98,129,166,173,119,239,222,246,209,163, 71,219,175, 93,187, 70, 22, 47, 94,220,114,
+207,158, 61,207, 24,141,198, 35, 9,249,111, 61, 40,147,176,161, 75,119,251,180,121, 94,211,167, 93,205, 99,111,141,125, 61,219,
+215,215, 87,170,108, 58, 75,208,168,138,235,139,195, 3,152, 75, 8, 89, 77, 41, 61, 81, 78, 61,208, 6,192, 96, 0,159,222, 39,
+205,114, 49, 24, 12,241, 86,171,213, 27, 0,244,122,125,154,197, 98, 9,116,224, 97,140, 44, 93,186, 20, 26,141, 6, 28,199, 65,
+150,101,200,178, 12, 69, 81, 64, 41, 45,250, 46, 28, 16, 52,117,234, 84,214,156,205, 96, 48,170,207, 96,133,133,133,253,210,123,
+224, 43, 61, 59,118,237, 9, 73, 83, 7, 49,169, 4, 9,113, 20, 42, 94, 2, 7, 5,113,167,183, 82,158,231,127, 40, 81,113, 93,
+ 40, 43, 2,230,225,225,121, 96,208,232,217,205,130, 90,116,193,246,139, 2, 20,217,142,244,203,191, 35,235,198, 41,152,110, 95,
+182,139,182,188,139,132,144,227, 90,173,246,211,243,231,207,155, 43,210, 44,141,252,119, 8, 82, 16, 74, 0, 5, 0, 40,192,145,
+210, 42,216, 10, 53, 57,142, 59,191,245,192, 69, 35, 81,187, 2,192, 53, 7, 42,237,106, 31, 93, 81,150,166,159,159, 95,239,113,
+227,198,109,236,211,167, 15,151,158,158, 14, 0,216,178,101, 11,206,156, 57, 3,163,209,136,201,147, 39, 35, 32, 32, 0,115,230,
+204,225,135, 15, 31,190, 0,192, 99,142,104,190,247,242,203, 27,251,140, 28,201,157, 57,115, 6,146, 36, 97,239,222,189,184,112,
+225, 2,234,213,171,135, 9, 19, 38, 32, 32, 32, 0, 51,102,204,224,199,140, 25, 83,174,102,219,182,109, 47, 6, 6, 6, 26, 95,
+126,249,101,174,111,223,190, 36, 53, 23, 24,179, 44, 38,191, 0,106,116, 24, 50,248, 57,238,233,143, 94,199,158, 61,123,154,173,
+ 94,189,122, 77,219,182,109,237,103,206,156,241,118,248,124, 18, 66,107,184,123,101, 0, 72, 5, 0,119,119,119, 87, 0,102, 0,
+230,144,144, 16,213,151, 95,126, 41,197,196,196, 92,235,213,171,215, 83, 0,126, 40, 75, 83,146,148,186,223, 78,239,137,145, 31,
+238,209,205,154,245,126, 42,199,169, 69, 0, 2, 0,120,122,122, 22,105, 6, 7, 7,171,150, 45, 91, 38,198,196,196,196, 21,104,
+110, 40, 47,157,162,218,171, 83,155, 71, 91, 8, 7, 19, 50, 90,102,175,191,122,252,205,103,117,123, 90, 4,213,202,171,108, 58,
+ 7,247, 32,103, 11,205,211,224, 30,196, 92, 65,148,203, 12,224,175,146,145,172,146,154,148,210, 59,132,144, 85, 0, 54, 16, 66,
+134,149,102,136, 8, 33,143, 0, 88, 7, 96, 0,165, 52,173,162,242, 89, 92, 83,167,211,105,236,118,187,103, 73,227,227,172,102,
+177,180,152, 35, 35, 35, 17, 30, 30,142,226,223,133, 15, 22, 5,219,120, 59,122, 29,241, 60,143,175,190,250, 10, 28,199, 65,163,
+209, 64,173, 86, 67,163,209,220,243,105,211,166, 13, 40,165, 32,132, 56,124,189, 19, 66,248,128,128,128,183, 85, 42,213,112,187,
+221,238,167,211,233, 82, 68, 81, 92,231,229,229,245,113,100,100,164,248, 32,212, 33, 76,147,105, 62, 8,154, 21,208, 14, 64,241,
+107,218, 14, 64, 91,240,119, 58,242, 27,170,188, 74, 44, 47,190, 93,225,119, 97, 61,227, 93,240,127,180,152,110, 26,128,211,213,
+106,176, 8, 33,148, 82, 74, 10,191,203, 56,153,110,137, 22, 79,228,197,121, 67,197, 41, 80,241, 4, 42, 30, 0, 8, 50, 18, 47,
+193,154,151,126, 60, 50, 50, 50,222,145,157,234,245,250,121,131,199,206,111, 38,123,181,195,111,231,236, 16,115, 18,144,120,232,
+ 19,106, 78,187,178,138,231,249,213,178, 44, 95,142,138,138, 18,171,122,112, 10, 5,228,226,198, 74, 1, 8, 42, 61, 45, 69,241,
+ 23, 70,167, 60, 40, 14,217,215,215,183,223,148, 41, 83,126, 8, 11, 11, 35,107,215,174, 69,203,150, 45,177,106,213, 42,122,229,
+202,149,207, 8, 33,159,197,199,199, 63,102, 50,153, 86,255,240,195, 15,232,216,177, 35, 60, 60, 60,218,132,135,135,171,203,171,
+216,125,125,125,251,173,121,235,173, 31, 90,117,238, 76, 22,247,232, 1,223,231,159,199,198, 67,135,104, 92, 92,220,103,132,144,
+207, 18, 18, 18, 30,179, 90,173,171,191,249,230, 27,180,109,219,182, 66, 77,158,231,253, 55,108,216,192,187,184,184,128,231,121,
+212,215, 3, 62,158, 26,124,188, 41, 6,105,217, 86, 76, 26,224, 11,149, 74,133, 30, 61,122,192,207,207, 79, 53,118,236,216,114,
+ 71,183, 94,248,178,119, 86,232,232, 29, 75,198, 44, 62, 54,133, 35, 28, 13,242, 81, 29,240,224,179, 46, 1,158, 42, 0, 30,222,
+222,222, 34, 0,216,237,246,236,223,126,251, 77,138,138,138,170, 21, 20, 20,228,229,204,121,141,142, 62,107,174, 89,211, 43,163,
+ 65,131, 6, 42, 0, 30, 94, 94, 94, 85,210,124,169,119,107,109,158,197,142,131,103,174, 63, 58,114,193,129,206, 13,124,221,206,
+245,111, 87,107, 31, 0,147,179,154,133,102,105,112, 15, 98,222,188,249,120, 26,168, 12, 72,185, 34,132,108, 17,114,182, 8, 33,
+ 71,130,120, 71, 28, 60, 97, 73,203,205,123,169,139, 19, 21,230, 41, 66,200, 48, 0,235, 74,154,172, 98, 70,104, 24,165,244,188,
+179,154,118,187,125,111,161,241,209,235,245,222,132,228, 27, 67,189, 94, 47, 90,173,214,167,157,209, 4,128,200,200, 72,132,133,
+133,213, 40,208,164,133,223, 5,134,213,105, 10, 95, 90,207,243, 60,194,194,194,208,183,111, 95,132,132,132, 32, 49, 49, 17, 7,
+ 15, 30,196,149, 43, 87,138, 34, 92,206, 64, 8,225, 3, 3, 3,247,247,236,217,179,249,248,241,227,245, 1, 1, 1,136,137,137,
+ 49,126,249,229,151,255, 59,122,244,104,159,240,240,240, 46,229, 93,139, 12,198,127, 1, 71, 60, 8, 0,111, 66,200,246, 98,117,
+203, 51,133,191,167, 78,157, 58,125,193,130, 5,127, 18, 66,182, 23, 95, 94,124,187,226,223, 5,251,220, 78, 41,125,102,218,180,
+105, 45, 22, 46, 92,248, 97,225,182,247, 37,130,165, 86,171, 95,184,176,243,179, 99,141, 5, 90,207,167, 69,159,130,186,140, 0,
+160,184,113,118, 39, 20, 69, 89,231,136, 78,104,104,104, 23, 99,147,142,175,251,134,116,196,142,179, 54,228, 94,221,133, 91, 39,
+150, 39, 40,146,125, 76,116,116,244,225,234, 56,168,176,176,176, 1, 53,107,215,131, 77,160, 5, 6,235,110,147,245,176, 16, 16,
+ 16,240,220,252,249,243, 35,130,131,131,201,230,205,155, 65, 41,197,143, 63,127, 11,148,161, 0, 0, 32, 0, 73, 68, 65, 84,254,
+ 72,175, 94,189, 58, 54, 37, 37,101,109,225,253, 56, 36, 36,100, 57,207,243, 6,142,227, 96, 52, 26, 53,231,206,157,243, 5,112,
+163, 44,205,141, 83,166,124,223, 38, 36, 4, 73,131, 7,227, 81, 73,194,183,107,214,208, 27,138,114,151,102,227,198,141,151,171,
+ 84, 42, 3,207,243, 8, 8, 8,208,156, 61,123,182, 76, 77, 0, 16, 69, 17,231,206,157,131, 74,165, 66,173, 90,181,240,209,203,
+254, 56,121,249, 14, 90, 5,249,192,146,153,136, 77,251,162, 17, 23, 23, 7, 79, 79, 79,199, 12,208,202,222,243,234, 55, 14,107,
+186,102,221,166,100, 29,205,188,144,145,145,225,149,145,145, 1,119,119,247,108, 89,150,197,143, 63,254, 88,125,245,234, 85, 15,
+189, 94, 15,157, 78, 7, 81, 20,157,114,214,146, 36,113,213,173, 89,211, 77,143,129,143, 55,215, 60,213,169, 49,142,158,189, 17,
+254,201, 79,113, 45, 19, 46, 29, 24, 81, 21, 77, 80, 25, 56,209, 37,234,158,229,254,195,189, 43,249, 84,122,162,192,100,237, 32,
+132,104, 10, 22,167, 22,124, 15, 43,175,169,175, 2,205,162,223, 54,155,173,120,148, 73, 93, 25,205,240,240,240, 66, 13,165,196,
+195, 91, 90, 97,228, 74,175,215,167, 57,170, 39,203, 50,180, 90, 45, 90,180,104,129,119,222,121, 7, 49, 49, 49, 56,122,244, 40,
+124,124,124,208,171, 87, 47,168, 84, 42, 36, 36, 36, 56,109,176,252,252,252,222,126,226,137, 39,154, 46, 93,186, 84, 31, 31, 31,
+143,152,152, 24,184,187,187, 99,222,188,121,134,169, 83,167, 6, 29, 59,118,108, 26,128,185,236, 22,203, 96, 56, 92,159, 60, 83,
+242, 55, 33,100,251,130, 5, 11,158, 41,205, 84,149, 98,230,238, 90,190,112,225,194, 15,139,253,206,172,206,180,114,197, 29,100,
+121, 27,138,162,248,136,103,109, 95,239, 81, 47,246,130,162, 0,146, 2, 72, 50,133,217,108,194,173,152,131,102, 65, 16,182, 84,
+180,179,230,205,155,187, 18, 94,179,226,213,113, 51,201,142,104, 27,172,119,226,145,114,124,217, 77, 21, 71,219, 87,179,185,138,
+152,249,241,183, 56,125,221, 94,208, 76,152, 31,201,146,149,252,191, 31, 6,124,125,125, 67,158,121,230,153,136,160,160, 32,178,
+105,211, 38,216,108, 54, 36, 36, 36,208,168,168,168,209, 73, 73, 73,107,139, 85,240,195,159,126,250,105, 3,207,243, 16, 69, 17,
+215,175, 95, 55,221,190,125, 59,161, 44,205,145, 93,186, 68,180,242,247, 71,226,139, 47, 66,206,206,198, 57,131,129,158,166,244,
+ 30,205, 1, 3, 6, 24, 52,154,252,251,239,181,107,215,202,212, 44, 81,176, 97,183,219,145,148,148,132,243, 81, 39, 97, 74, 56,
+129,141,107, 86, 98,205,154, 53,136,139,139,131, 74,165,130, 36, 57, 62, 78, 66, 50,167,218,130,125, 13,185,197,151,229,228,228,
+120, 68, 69, 69, 41,151, 47, 95,246, 40,188,113, 2,128,162, 40,149,182,214, 37, 53,139, 34,164,149,212, 52,232,212,120,172,109,
+ 16, 47, 42, 84, 83,229,116,202,185, 66,169,203,133, 59, 98, 21, 42,176, 19, 0, 52,197,250, 29,249, 84,214, 92,149, 48, 62,247,
+ 52,173, 85,150,200,200,200,194,136,213, 93, 88, 44,150, 64, 74,169, 75,100,100, 36, 28,233,127, 85, 44, 47,161,213,106,209,175,
+ 95, 63, 92,190,124, 25, 73, 73, 73,224,121, 30, 54,155, 13, 54,155, 13, 97, 97, 97,208,104, 52, 78,167, 95,167,211,189, 48,126,
+252,120,151,184,184, 56,100,100,100,128,227, 56, 72,146, 4, 89,150,241,218,107,175,185,232,245,250,161,236,150,201, 96,148,238,
+ 65, 8, 33,163, 8, 33,163, 74, 26,164,170, 26,180,210, 52,166, 77,155,214, 2,128,238,111,137, 96, 21,134,231,202, 50, 45,158,
+181,125, 35,166, 45, 88,165,250,229, 28,143,204,148, 88, 88, 83, 99, 97, 12,235,143,212,216, 99,160,178,240,235,197,139, 23, 77,
+ 14, 84, 54,111, 15,124,125,118,192,145,120, 29, 44,130, 21,105, 71, 63, 81, 8,149, 70,157, 60, 25,153, 91, 93,230,202,211,171,
+110,196,123, 31,125,171,250,245, 79, 53,238, 36,199, 34,102,235, 20,200,130,185,100,166,237,114, 50,227, 73,120,120,120,221, 70,
+245, 12,224, 52, 58,252, 65,136,207,224,193,131,249,205,155, 55,223,183,206,174,201,201,201,177,190,190,190, 31,216,237,246,153,
+ 28,199,225,214,173, 91,244,236,217,179,163, 18, 19, 19,215, 23,110, 99, 52, 26,159,108,223,190,253,103, 83,167, 78, 5, 33, 4,
+251,247,239,135,201,100, 58, 70, 41, 85,202,211,172,245,231,159, 51,187,153,205,216,226,229, 69, 87,202,242, 61,154, 61,123,246,
+252,108,226,196,137, 32,132,224,200,145, 35,229,106, 22, 39, 46,157,194,100, 3, 2,189, 56,120,122,122,226,224,193,131, 69,253,
+ 93,178, 68, 55,200,146, 22,190,106, 75,165,207,137,162, 40, 36, 43, 43,139,183, 88, 44,188, 40,138,156, 74,165,162,133, 55, 97,
+ 81, 20,149,234,210,148,101,185, 74,154, 37, 30, 92,170,150, 78, 49,187,116, 35,101, 79,171,142,102, 39,123,193,183,182, 42,230,
+170,208,248, 20,118, 64,215,233,116, 69, 70,197,153, 40, 83, 25, 17,172, 74,173, 47,205, 96,169,213,106, 52,106,212, 8, 39, 78,
+156,128,187,187, 59,106,212,168, 1,131,193, 0,157, 78, 7,119,119,119,104,181, 90,112, 28,231,148,201, 18, 4,193,223,223,223,
+ 31,127,253,245, 23,244,122,125,209, 71,171,213, 34, 36, 36, 4,102,179,217,151,221, 90, 25,140,210, 61, 72,105, 51,185, 87, 71,
+ 51, 94,105, 38,107,225,194,133, 31, 22,143,130, 85,171,193, 42,215,180,212,246,141,152,250,225, 42,213,230, 40, 14, 89, 41, 49,
+184,177,115,186, 36, 11,230, 52, 69, 17,235,101, 94, 59, 10, 69, 81,214, 58,120, 80,143,214, 13,106,133, 99,209, 2,172, 49, 63,
+193,158,117,125, 89,100,100,228,177,234, 52, 87,211, 23,126,171,250,249,156, 10,119,146, 99,113,237,183,169,178,100, 55,189, 30,
+ 21, 21,181,169,178,186, 29, 58,116,104,248, 72,219,208,175, 94,170, 35,116,236, 55, 56, 8, 90,131, 6, 83,174,169,158,184,120,
+ 60,254, 72,219,182,109, 71,159, 57,115,230,226,125, 52, 89, 11,235,214,173,171, 54, 26,141, 83,146,146,146, 94, 75, 78, 78,222,
+ 88, 44,202,212,123,224,192,129, 27,199,140, 25,195,185,187,187, 35, 35, 35, 3,179,102,205,178,240, 60, 63,197, 17,205,125, 94,
+ 94, 83, 78,203,242, 61,154,221,250,143,222, 56,229,127,175,112,106,181, 26,233,233,233,152, 51,103, 78,133,154, 84, 95,143, 60,
+255,233, 77,212, 48,168,161,211,232,145,112,204,132, 15, 7,228, 55, 21,105, 52, 26,156,201,105, 9,206, 61, 0, 6,141, 10, 81,
+137,153, 16,221, 46,146,240,209, 81,234,200,149, 97, 21,154, 4, 66,136,156,158,158,174,142,139,139,211,219,237,118, 46, 48, 48,
+208, 10,228, 55,241,101,102,102,106,180, 90, 45, 8, 33,130, 36, 73, 78,197, 46, 51, 51, 51, 85, 87,175, 94,215,137,162, 88,166,
+166, 32, 8, 85,142,135, 86, 53,157, 16,179, 75, 15,249, 9,233, 85, 53, 88, 9,132, 16, 99,225,223,213, 81, 94,173, 86,171,119,
+177,166, 65, 80,234,120,255,176, 50, 34, 88,149, 94, 95, 74,221, 4,173, 86,139,171, 87,175,194,219,219, 27,146, 36,193,213,213,
+ 21, 6,131, 1, 6,131, 1, 22,139, 5, 90,173, 22, 60,207,151,218,201,189, 44,180, 90,109, 98, 76, 76, 76, 35, 79, 79, 79, 40,
+138,114,151,201,138,139,139,131,171,171,107, 50,187,181, 50, 24, 78, 5, 60,182, 23, 55, 90,132,144,237, 83,167, 78,157, 94, 89,
+189,169, 83,167, 78,175,106, 84,172, 92,131, 85,216,169,172,100,231,178,176,176,176, 1, 30, 94,245, 34, 38,125,240,141,234,135,
+ 51, 28,178, 83, 46, 35,121,207, 12, 73, 22,204,195,213,106,245,137,155,199, 86,174,227, 56,206,114,246,236,217,163, 14,156, 20,
+ 46,188, 99,151, 86,188,166, 6, 40,181,192,154,116, 18, 42,149,234,179,234, 52, 87, 83, 23,172, 82,109,142, 86, 33, 51, 37, 6,
+ 55,126,159, 38,203,130,185,210,230,170,123,247,238,170,188,188,188, 9, 45, 92,229,247,222, 9, 16, 53,126, 90, 5,151,190,154,
+130,152, 0,119,180,232,104, 64, 96, 19,185,245,201, 93,182,227,225,225,225,139,109, 54,219,194,139, 23, 47, 10,247,163,176,221,
+186,117,107,158,191,191,255,175,201,201,201, 69, 35, 58,124,125,125,251, 13, 27, 54,108, 93,183,110,221,184,245,235,215,163,127,
+255,254,120,255,253,247,105,122,122,250, 91,201,201,201,215, 42,171, 57,112,252,234, 31, 6,247,121,132, 12,153,244, 41,102,190,
+254, 24,190, 93, 54,191, 66,205, 90,125,214,158, 52,250,246,225, 27,215,178, 96,236,144,206,249, 79, 10, 27, 47,227,202,237,252,
+128,167,168,168,144,141, 58,248,106, 68,107,112, 28,193,225, 51, 87,176,250,118, 75,146, 20,127,240, 2, 16,214,164,188,116,202,
+178, 76,190,255,254,123,247,212,212, 84, 46, 36, 36,228, 78,235,214,173, 77, 90,173, 86,177, 88, 44,178, 94,175,151, 92, 93, 93,
+ 21,171,213,170,189,113,227, 70,205,164,164, 36,190,176, 25,206, 17,246,236,217, 83,175, 73,147,102, 25,161,161,161,101,106, 38,
+ 39, 39,115,206,104,150, 70, 85,211, 89,102, 4, 75,168, 90, 4,139, 82,218,132, 16, 98,174,138, 9,250,187, 40,136,132, 1,128,
+169,172,169, 24,156,137, 96, 21,246,171,210,106,181, 56,126,252, 56,158,122,234, 41, 40,138, 2,157, 78, 87, 52, 45,201,169, 83,
+167,160,209,104,192,243,188, 83,105, 21, 4, 97,253,178,101,203,222, 93,184,112,161,107, 97, 51,164,139,139, 11,180, 90, 45, 22,
+ 47, 94,108,178, 88, 44, 27,217, 45,147,193,162, 87,165,123,144, 18,164,149,136, 94,217,139,253, 78, 67,254,187,149,159, 41,248,
+ 27,165,252,109, 47,101, 89,198,130, 5, 11, 14, 20,139, 92,165, 85,231,113,149, 25,193, 10, 13, 13,125,194,179,182,111,196,187,
+ 31,124,163, 90,115,146, 71, 86,202, 37,164, 31,120, 79, 82, 68,203,240,168,168,168,194,254, 86, 61, 28,221, 81,120,120,120,195,
+250, 77, 58,184,164,230, 42,160,138, 4, 41,251,122,234,153,211, 39, 83,171,122, 0,161,161,161, 79,120,122,213,141,152, 60,127,
+149,106,125,164, 10, 89,201,151,145,188,103, 70,149,204, 85,155, 54,109,122,232, 84,220,183,227,253,197, 90,207,212,150, 32, 83,
+ 96,237, 45, 53, 54, 68,159, 60, 42, 16,197,214,226, 17,125,143,150,157,181,120, 98,168,139,234,218,121, 97,202,153,189,120, 51,
+ 52, 52,116,120,116,116,244,206,251, 81, 56, 19, 19, 19,139,140,144,191,191,255,192, 17, 35, 70,124,223,189,123,119,178,115,231,
+ 78, 40,138,130, 69,139, 22,209,115,231,206,141, 47, 30,141,114, 86,115,224,248,213,223, 63,215,175, 39,153,177, 89,196, 29,179,
+ 11, 38,205,254,148,218,147,207, 87,168,217,220,168,105,254,213,123, 47, 1, 0,254,184,120, 11,251,206,101, 34, 41,221,140,145,
+237,129,139, 0, 84, 68, 68, 77,238, 22,102,174, 62,143,214,129, 53, 48,232,177,198,232,218,182, 49,190,248,254,119, 99,237, 94,
+ 31,214, 77,223, 53,189,204, 73, 42, 21, 69, 73,223,179,103,143,203,204,153, 51,243,234,213,171,167,202,203,203,227,138,247, 97,
+210,104, 52,168, 87,175,158,148,149,149, 37,236,217,179,167,129,162, 40,119,202,189, 24, 84,220,173,145, 31,238,241,215,114,138,
+117,192,128,129,180,118,237,218, 42,139,197, 82,170,102, 70, 70,134,176,127,255,254, 32, 69, 81,210, 43, 58,151,188,156,155,190,
+120,221, 97,207,193, 61, 90,171, 27,248,222,219,137,223,217,116,222,109,176,238,136, 48,190, 82, 27,246, 59, 34,236,105, 18,132,
+ 12, 17, 66,154, 8,201,244,192, 13,231,168,108, 7,244, 10, 34, 97,222,213, 21,193,210,104, 52, 72, 72, 72,192,190,125,251,208,
+190,125,123,184,185,185,193,100, 50,225,196,137, 19,184,117,235, 86, 81, 4,203, 25,110,222,188,185, 68,173, 86,247, 30, 55,110,
+ 92,147, 49, 99,198,184, 54,109,218, 20,241,241,241, 88,178,100,137,249,252,249,243,113,181,106,213, 90,192,110,175, 12,134, 67,
+156,254,183, 37, 88, 85,206, 83,221,164, 71, 6,205, 84, 69,252,161, 66,102,210,159,200, 62,242,126, 73,115,229, 72, 40,175,232,
+109,219,178, 44,183,105, 17,250, 8,174,221,150, 32,229,196, 3, 84,142,174,100,120,240,174, 55,120,115, 28,247,110,167, 65, 51,
+ 85,107, 78,171,144,157,124, 9,105, 7,102, 58,109,174, 74,209,156,122, 96,210,160, 90,144, 36,156,219,177, 17,159, 38,104, 76,
+215, 45,100, 74,116,116,212,247,148, 82, 26, 26, 26, 58, 52,241,138,184,164,195,211,122,247,231, 6, 62,143,129, 3, 36,215,137,
+175, 70, 76, 6,176,179, 44,205,106, 10,141,150,171,233,235,235, 27,210,172, 89,179,136,222,189,123,147, 45, 91,182, 32, 55, 55,
+ 23,153,153,153,248,227,143, 63,222, 76, 78, 78,254,190,178,154,245,154,247,141, 24,208,183, 39,153,249,163,140,216,147,155, 80,
+195,118, 19,182,148,147, 14,105, 94, 72, 16,206,190, 56,249,187, 80,157,222, 0,217,224,135,119,251,251,162,169, 55,129,197,252,
+255, 93,246,218,213,252, 11,121,200,194,209,232,186,248,117,247, 97,240,138, 25, 55, 83,173,137,233,251,254,223, 92,149,150,206,
+180,180,180,201, 26,141,166,235,136, 17, 35,158,239,210,165,139,219,168, 81,163, 82,221,221,221, 77, 90,173,150,175, 85,171,150,
+150, 82,170,221,189,123,183,239,173, 91,183,106, 2,216,144,150,150,118,184,172,116,206,154, 13,138,217,253,154, 94,186, 4,114,
+250,180,111,151,225,251,213, 67,187,116,233, 82, 99,212,168, 81,105,197, 53,101, 89,214,238,222,189,219,239,214,173, 91,158, 0,
+214,167,165,165, 29,169,232,124,158,219,144, 26,212,168, 87,226,251,203,239,228,190, 21,236,239,205, 63,219,163,133,186,102,141,
+252,247, 92, 59,155, 78,160,196, 60, 88,227, 63,109, 85, 94,153, 41,107, 30,172,251, 81, 62, 45, 22, 75,160,179, 81, 49, 71,210,
+ 25, 21, 21,101, 46, 57, 31, 86,121, 17,172,178, 52,181, 90, 45, 84, 42, 21,210,210,210,176,103,207,158,187,230,194,210,106,181,
+ 69,211, 56, 56,163, 73, 41,149, 9, 33,143,203,178,252,246,196,137, 19,135,155,205,102, 63, 23, 23,151, 20,187,221,190,174,102,
+205,154,229,206,131,117, 63,242,136,105, 50,205,251,169,249,176, 81, 94, 31, 44,195,209,200, 43,224,117,169,200, 61,249,177,211,
+230,170, 52,110,221,177, 34, 81, 47, 65,188, 19, 11, 0,103,171, 41,180,232,118, 36,234, 42,212,250, 12,100,255,241,145,172,136,
+150, 42,245,185, 42, 40, 56, 34, 36, 9,246, 67,235, 49,254,138, 62,131,112,124,251,168,168,211,183, 11,215, 71, 71, 71,111, 12,
+ 13, 13,221,191,107,141,233, 76,143,174, 82,237,243,113,191,130,227, 56,225,126,103,102, 65, 39,245,249, 63,254,248,227, 76,147,
+201,132, 59,119,238,208, 83,167, 78,141, 73, 74, 74, 90, 87, 85,205, 79,191, 27, 56,243, 74,108, 54, 12,185, 39,169,237,198,214,
+177,197, 71, 21,150, 71,214,111, 47, 61,218,252,181,157,157, 72,214,133,246, 46, 87, 86, 76,252, 53,195,215,211,247,141, 55, 72,
+189,122,245, 80,179,102, 77,120,121,121, 33, 47, 47, 15,215,206,252, 78, 45, 41, 41, 54,169, 70,248, 87,246,122,143,239, 73,219,
+215,239,168, 3,121, 79, 1, 28, 10, 15, 15, 63,126,240,224,193,167,142, 29, 59,214,239,241,199, 31, 79,237,212,169, 83, 94, 84,
+ 84, 84,253,184,184, 56, 31, 0,219,124,124,124,118, 86, 56,215, 16,165,116,214,255,143, 74, 59, 24, 30, 30,126,172, 64,179,111,
+143, 30, 61,210, 58,118,236,152, 23, 21, 21, 85, 63, 62, 62,222, 91,150,229, 95, 27, 54,108,184,235,224,193,131,146, 99,101,116,
+150, 2, 96,118,171, 39, 39, 45,186,156,229,186,228, 90,210,157, 33,173, 26,251, 17, 0,196,233,116,162,196, 60, 88,229,204,115,
+ 85,209,122, 7,136,252, 27,138,105,149, 53, 75, 70,194,194,194,194, 2, 11,205, 84,201,111, 39,174,121,180,110,221, 26,197, 71,
+ 58,114, 28,119,215,135,231,121,168, 84,170,202,212, 81, 50,128, 69, 5, 31, 6,131,241, 95, 55, 88, 42,149,106,146, 41,242,243,
+185,148, 82,111, 0, 83,163,162,162,118, 85,101, 71, 26,141,230, 88,212,238,111,178,180,126,151, 61,173, 9,135, 77, 28, 33,107,
+170,227, 0, 8, 33,147, 77,145,159,207, 5,224,165, 40,202,123,209,209,209,219,170,170, 41,203,242,226, 71,151,108, 5, 96, 32,
+178, 44,127,114, 54, 50,234,118,201,109,162,163,163,211,219,180,105,243,250, 59, 35,215, 20,189, 0,250, 65,200,208,194, 78,234,
+ 65, 65, 65, 83,110,222,188,121,215, 8,192,170,106, 26,234,182,155, 34,166, 71,143, 78, 74, 74,250,193,153,255,191,184,234,169,
+227,192, 83,199,129, 41, 75, 66, 66, 66, 6, 79,159, 62,125, 89,179,102,205, 12,181,107,215, 38, 39, 79,158,164,215,174, 93,147,
+ 76, 38,211, 39, 23, 46, 92,248,160, 82,119,236,124, 83,178,205,215,215,119,223,158, 61,123, 6,236,222,189,187,189,162, 40,167,
+ 20, 69,153,159,156,156,108,169,170,230,174, 93,187, 6,236,220,185,179, 61,165,244, 4,165,244,215,164,164, 36,107,101, 52,207,
+239, 94,244,127,236,157,103,120, 20, 85,195,134,159, 51,179,125, 55,189,145, 70, 9, 9,132, 16, 18, 32,155, 2,129, 64, 64,144,
+174,162,160, 84, 1, 41,138, 32, 8,250, 34,189,247, 94, 68,225,149,222, 4, 20, 16, 5,164, 72,111, 9,161, 67, 40,129, 4,210,
+123,207,110,182,204,156,239, 7,129, 15,120,129,108, 2, 42,226,185,175,107,174, 77,102,103,238, 61, 83,246,236, 51,103,206,204,
+148, 0, 24, 84,239,173,177, 19, 46, 20, 39,175,224,101,214,129,119,239,222,141,125,137,114,222,126,201,247,203, 99,231,159,176,
+139,190,180,179, 34,183, 95,176, 48, 0,209,225,195,135, 87,100, 22,254,225, 45, 74, 24, 12, 6,227, 69,149,203,159, 54, 0, 8,
+120,252,255,240,240,112,171,250,245,235,191, 19, 16, 16,160,126, 85,206, 63,163,156,111,130,211,195,195, 35,224,117,118,214,169,
+ 83,103,120, 88, 88, 88, 70,131, 6, 13,190, 3, 32, 97,219,253,245,115, 2,208,252, 9,206, 42,108, 27, 49, 39,115, 50,167, 5,
+254,129,127,166,255,175, 24, 36,127,101,152, 59,121,242,100, 17,128, 95, 88,172,253,243,121,188,147,250,235,232,140,141,141, 93,
+ 4, 96, 17,219, 82,175,245,193, 87,241,159,224, 76,103,107,150,193, 96,252, 27,224,216, 42, 96, 48, 24, 12, 6,131,193,120,181,
+ 16, 0, 1,207, 57,210,180,184,181,130, 16, 18, 80,137, 35,217, 43,204,201,156,204,201,156,204,201,156,204,249,239,114,150,231,
+166,148, 94, 33,132, 12,124,214,157,220,255, 81, 1,171,162, 87,219, 84, 72,206, 46, 97,101, 78,230,100, 78,230,100, 78,230,100,
+206,138,251,255,241, 1,139,157, 34,100, 48, 24, 12, 6,131,193,120,197, 72,216, 42, 96, 88,130,135,135,199,148, 70,141, 26, 13,
+140,142,142, 94,124,255,254,253, 74,221,125, 58, 36, 36,164,190, 90,173,158,100, 54,155,181,102,179, 89,161, 82,169, 98, 11, 11,
+ 11,191, 59,119,238,220,150,202,150, 43, 36, 36, 36, 88,173, 86, 79, 48,155,205, 13,202,156,215,242,242,242,150, 93,184,112,225,
+167,215,201,201, 96, 48, 24, 12, 22,176, 30,177,104, 44,113,149,149, 66, 50,120, 62, 77, 2,128, 26, 53,106, 84, 55,153, 76,205,
+ 69, 81, 12,148, 72, 36,151,121,158, 63,154,144,144,112,239,101, 10,240, 79,113,254, 83, 32,132, 84, 81,171,213,189, 9, 33,173,
+ 41,165,191,151,148,148,108,160,148,190,212, 35,137,170, 84,169,226,220,181,107,215,145,139, 23, 47, 70,191,126,253, 70, 57, 59,
+ 59, 47,205,204,204,172,208, 21,102, 77,155, 54, 29,172, 82,169, 38,125,254,249, 16, 85,112,112, 48, 81,171,213,184,121,243,102,
+208,130, 5,243, 23, 53,111,222,188,203,177, 99,199, 62,160,148, 86,232,241, 46, 17, 17, 17, 95,170, 84,170,177,195,135, 15, 87,
+ 52,108,216,144,200,100, 50, 92,188,120, 49,120,201,146, 37,203,155, 55,111,222,249,216,177, 99, 61,104, 5,207,129, 63,237, 84,
+ 42,149,184,114,229, 74,240,252,249,243, 43,229,212, 14, 58, 47,149,169,141, 18, 0, 48,150,200,204, 49, 43,130, 76,150,142, 99,
+213, 19,131,193, 96,188,129, 1,107,249,104, 50, 94, 14,124, 13, 25,200,228, 65,242,125, 43,127,115,188,239,235,235, 75,250,245,
+235,151, 35, 8,130,206,100, 50, 57,175, 93,187,118,136,187,187, 59,229, 56,238, 72,105,105,233,137,172,172,172, 34, 75, 62,212,
+201,201,201, 74, 46,151, 71, 80, 74,155,249,250,250,146,254,253,251,231,152, 76, 38,157, 94,175,119,217,184,113,227, 80,119,119,
+119,209, 98, 39, 33,100,242, 36,144,141, 27,237, 53,122,189,178, 41,165,180,249,171, 42,231, 63, 40, 84,201,149, 74,101, 39,169,
+ 84,250,137,163,163,163, 83,187,118,237, 46, 85,169, 82,229,122,122,122,122,157,189,123,247,238,177,177,177,201, 52,153, 76,171,
+245,122,253,110, 74,105,133,239, 56, 47,149, 74,171, 19, 66,144,156,156, 12,169, 84, 42,149,203,229, 53, 0, 92,181,116,254,176,
+176,176, 0,153, 76, 54,229,187, 85,155,149,102,222, 26,217,102, 17,217, 5,128,204,201, 23,147,102, 46,210,204,155, 62,174, 73,
+227,198,141,135, 3, 88, 80,145, 86, 38,149, 74, 53,118,235,214,173, 74, 23, 23, 23,136,162,136,194,194, 66,248,249,249, 97,218,
+180,105,234,153, 51,103,190, 21, 22, 22,246, 41,128,239, 42,235,164,148,194,104, 52,162, 94,189,122,152, 59,119,174,122,210,164,
+ 73, 21,114,106, 87,158,151,154,140, 55,194,140, 37,194, 40, 0, 32, 82,126,118,228,100,135,115, 38,227,141,224,242,198,105, 87,
+226,108,204, 64, 22,178, 24,127, 45,238,238,238,141,189,188,188,126,188,127,255,254, 25,158,231, 63, 78, 72, 72, 40,125, 5,245,
+147, 7,128, 26, 0,236,240,224,194,170, 92, 0,247, 40,125,112,224, 94, 25,156,106,181,104, 15,185,186, 23, 64, 3, 9, 0,112,
+220,101,106, 42,222,144, 21,123,120,207, 75, 57, 21,154,222,160, 66, 32, 1, 68,112,252, 21, 34, 20,175,201,184,118,120, 63,219,
+ 51, 24,175, 44, 96,109, 30, 77,236, 64, 49, 98, 96,183,129, 28,207,243,100,197,143, 43,219, 31,248,245,191,203,234, 54,108,151,
+ 11,160,120,207,158, 61,250,246,237,219, 27, 62,249,228, 19,227,205,155, 55,185,133, 11, 23,214,255,227,143, 63,222,241,244,244,
+ 60,158,148,148,244,220,187,124,175,156,160,185, 41,152, 74, 60, 39,124,162, 42,205,150, 15, 92, 50,112,224,224, 2,119,119,119,
+115,153,179,180,125,251,246,134, 65,131, 6, 25, 30,115,190,235,233,233,121,236, 69,206,201,147, 64,100, 57,234,125,145,245,137,
+204,213,183,219,169,254, 3,191, 40,112,119,119, 55,115, 28, 87, 84,217,114,254,147,176,182,182,158,163,209,104, 58, 6, 5, 5,
+197,126,249,229,151, 71,223,121,231,157, 76, 0, 88,187,118,173,231,236,217,179, 47, 3, 56,245,203, 47,191, 56, 47, 92,184,176,
+219,249,243,231,167, 90, 91, 91,255, 90, 88, 88,248, 31, 11, 43, 70,206,213,213,117, 76,155, 54,109, 70,245,232,209, 3,214,214,
+214,232,211,167, 15,244,122,253, 73,119,119,247,169,169,169,169,243, 45,105,205, 81, 40, 20, 99, 63,251,236, 51,133, 40,177,198,
+184,117,113,200, 41,122,144, 27,212,114, 14,159,183, 82,160, 75,151,174,234,153, 51,103,124, 83,145,128,165, 86,171, 39, 12, 31,
+ 62, 92,225,226,226, 2, 0, 40, 42, 42, 66, 81, 81, 17, 10, 11, 11, 81, 90, 90,138,119,222,121, 71,253,253,247,223, 79,168, 72,
+192,122,220,121,243,230, 77, 24, 12, 6,232,116, 58,232,245,122, 88, 91, 91,163,115,231,206,234,101,203,150, 89,236,116, 75,131,
+244,158, 81, 92, 56,242,179, 15,157, 0, 96,254,119,219, 22, 2,186,230,212,130,113,110,105,136, 0,192, 2,214,139,247, 79, 30,
+192, 59, 82,169,244, 29, 31, 31,159,160,184,184,184, 75, 38,147,233, 23, 0,187, 40,165,166,151,116, 71,186,185,185, 77, 74, 77,
+ 77,253,158, 82,186,229,223,178, 78,189,189,189,183,108,218,180,201, 97,207,158, 61, 29,166, 77,155,246, 62,128, 77, 47,177, 14,
+165, 0,194,202,254,189, 89, 22,172, 80, 22,180,124, 9, 33, 94, 0,206, 84,228,160,207,217, 63, 82, 35, 66,181, 46, 60,178, 77,
+120,215, 46,157,173,156, 29,108, 81, 92, 42,224, 86, 66, 90,213,253,123,126,142,112, 13,236,112, 70, 16, 74, 62,206,188,118,164,
+184,162,206,150,109,223, 9,111,249, 86, 43, 43, 91, 91, 59,100, 23,154,112, 39, 33,169,218,209, 3,187,154, 84, 9,236,112, 2,
+ 48,245, 79,191,188,191,132,125,235, 24, 21,193,162, 78,238, 4,160, 14,118,234,108, 0,105, 0,138,108,108,108,140, 0, 74, 0,
+228,250,250,250,230, 47, 95,190, 60,121,215,174, 93,127, 80, 74,223,122,124,190,167,175, 48, 16,133, 82,215, 79,123, 12,133, 66,
+ 38,202,198,124, 51, 34,199,221,221, 61,163, 28,231,161,242,156, 0, 96,163,210,133,119,142,180, 11,172,202, 45,255,236,242,193,
+254,161, 57,169, 49, 37,128, 80,108, 99,101,101,170, 76, 57, 95, 5,127,149,211, 96, 48,188,107,103,103,151,159,147,147,163, 49,
+153, 76,164, 64,103,146,222, 72,210,219,220,215,185,185,222, 72,210,219, 20,232, 76, 82,147,201, 68, 50, 50, 50, 52, 74,165, 50,
+191,180,180,244, 93, 75,203,233,230,230, 54, 97,230,204,153,163, 87,175, 94,205,133,132,132,192,218,218, 26,141, 27, 55,198,134,
+ 13, 27, 36, 19, 39, 78,156,236,230,230,246,181, 37,229,164,148,134,104,181, 90, 34, 2,200, 45, 50,227,240, 76, 45, 78,206, 13,
+ 65,137, 65, 68,126, 65, 17, 56,142,131, 68, 34, 33, 65, 65, 65,222,150, 46,187,217,108,110,208,176, 97, 67, 2, 0,133,133,133,
+101,225,234,193, 80, 84, 84, 12,153, 76, 14, 81, 20,101, 13, 27, 54,116,171,140,211, 96, 48,160, 70,141, 26,168, 94,189, 58, 10,
+ 11, 11, 81, 80, 80, 0,153, 76, 86, 33,167, 65, 45, 37, 20,212, 69,165, 84, 56,170,148, 10, 71, 10,234, 2, 0,150,140, 51,168,
+165,228,239,220, 63, 9, 33, 78, 60,207,127,239,227,227,115,158,231,249,255, 18, 66,170,188,140,147, 16,162, 37,132, 76, 86,171,
+213,191,213,173, 91,247,150, 70,163,217, 75, 8,153, 74, 8, 9,171,140,147, 16, 34, 87,171,213,123,102,204,152,177,225,194,133,
+ 11, 31, 28, 58,116,168,198,165, 75,151,222,155, 51,103,206, 90, 43, 43,171,253,132, 16,213,203,124, 55,189,188,188,190,139,138,
+138,210, 54,105,210,100, 57, 33, 68,241, 42,190,239,132, 16,158, 16, 82,159, 60,124,216,225,107, 82,135, 60,196,211,211,211,187,
+ 97,195,134,142, 60,207, 35, 34, 34, 2,130, 32, 52,121, 73,103, 24,128,116, 74,233, 9, 74,105, 22,165, 84, 40, 27,178, 41,165,
+ 39, 1, 36, 1, 8,175,136, 83,132,106,221,240, 47,255,211,250,171, 47, 6, 88,157,191, 39,224,191,251, 83,177,245, 68, 38,146,
+ 11, 21,104,253,238, 39, 54,145,237,122,180,226,121,245,186,138, 58,199,140, 30,221,186,127,159,158, 86, 87, 82, 56,108, 59,153,
+133, 19,177, 5, 40, 33,246,136,124,119,160, 93,221,144,118,109, 65,100, 43, 94,135,109,244,166, 59,255, 21, 45, 88,221,103,210,
+188,229,163,201,130,239,183,172, 28,197, 17, 66, 53, 14, 1,135,117,212,243,122,217,244,182,206,206,206,166,178, 31,161,252,223,
+126,251,205,124,254,252,121,135,154, 53,107, 58, 90,190,101, 64, 46, 93,186,168,115,114,241, 74,247,242,242,122, 37,206, 86,225,
+ 45,228,250, 82, 29, 46,221,184,210,100,247,202,102,225,246, 46,126,151, 92,234, 12,248, 3, 66,120,177,193,108,206,171, 84, 57,
+255, 1,240, 60,175,219,190,125,251,127, 15, 28, 56,224, 54,110,194,148,214, 83,254,123,212,197,166, 94, 55,123,147,104, 99,117,
+104,209,133,162,188, 43, 27,115,115,110,236,203,208, 54,168,247, 71,231,206,157, 83,231,205,155,247, 69,121, 78, 79, 79, 79,165,
+ 68, 34,169,221,161, 67,135,145, 31,127,252, 49, 18, 18, 18,240,213, 87, 95,233, 46, 94,188,152, 19, 28, 28,236, 48,119,238, 92,
+213,192,129, 3,113,250,244,233,177, 94, 94, 94,191,152, 76,166,196,164,164,164,231, 62,159, 79, 16, 4,133, 82,169,132,174,172,
+ 77,193,104,166, 0,196, 71, 45, 79, 28,205,131, 68, 34,129, 40,138,181, 8, 33,119, 45,105, 21, 51,155,205, 10,165, 82,137,226,
+226, 98, 20, 21, 21, 33, 57,179, 8,247,210,139, 81, 88, 92, 10,157,206,132,146, 98, 19,164,106, 71,152,205,233,126,132,144,180,
+138, 56, 5, 65,128, 78,167, 67,113,113, 49,116, 58, 29,116, 58, 29, 68, 81, 68, 65, 65, 1,164, 82, 41, 53, 24, 12,190, 0, 82,
+203,221, 54,114,149, 25,224,230,126,191,118,215,216,178,227,153,185, 86,208,139,217, 22,140,123, 48,239,223,214, 50,164,112,114,
+114,218,183,125,251,246, 58,181,106,213, 66,124,124,188,111,215,174, 93,131, 9, 33,225,148,210,146, 10,186,212, 28,199, 77,237,
+219,183,239,192,238,221,187,147,218,181,107, 67, 34,145,192,108, 54,123,196,197,197, 53,219,186,117,235, 8,137, 68,178, 70, 16,
+132,111, 44,189,115, 60, 33,132, 83, 40, 20,235, 86,172, 88,209, 52, 44, 44, 12,235,214,173,195,217,179,103,197,208,208, 80,174,
+119,239,222,168, 94,189,122,232,199, 31,127,188,137, 16,242, 65,217,131,150, 43,186,252,213,122,246,236,233,201,243, 60, 26, 55,
+110, 44, 59,121,242,100, 3, 0,103, 94,114,157,106, 60, 60, 60,246,183,104,209,162,254,193,131, 7, 47, 18, 66,218, 84,228, 78,
+249,238,238,238, 29,171, 84,169, 50,205,218,218,218,222,210,121,138,138,138, 74, 50, 50, 50,198, 36, 37, 37,237,176,112,150,176,
+192,192, 64,152,205,102,216,218,218,194,205,205,173,177,167,167,231, 23, 54, 54, 54,239, 20, 22, 22,126,147,152,152,120,174, 2,
+203,235, 14,128,163,148,198,149,253, 95, 29, 64,237,178,183,111, 83, 74, 19, 40,165,241,132, 16, 55, 66,136,167, 37,167, 11,157,
+106,181,104,223,164,101,251,240,136,176, 0,110,230,246, 4, 8,162, 8, 9, 4, 72,120, 17, 89,130, 20,132, 16, 84,243, 13,225,
+171, 92, 57, 23,234,228,215,170,125, 86,236,193, 61,150, 56,219,117,234,220,196,183,182, 47, 55,127,231,125,228, 37, 95, 17,210,
+ 99,255,200, 38, 28, 7,175, 6,173, 29,107,248, 54,228,125, 26,182,148,166, 37, 92,105,238,232,219,172, 69,246,205, 99,135, 89,
+108, 96, 84, 56, 96, 17, 66, 40,165,244,209,145,213,224,153,116,106,160, 95, 21,191, 45,155,214,164, 20,155, 28,174,100,103,103,
+ 59,102,103,103,195,198,198, 38, 95, 16, 4,211,156, 57,115,164,113,113,113,182, 74,165, 18, 10,133, 2, 38,147,169, 66,157,137,
+ 69, 81, 36,175,218,169, 81, 91,161,137, 54, 92, 22, 28,160,197,181,184,235,218,243,135,135, 5,156,190, 80,240,201,173, 91,119,
+ 42,237,252,167,208,186,117,235,212,218,218, 54,191, 45,253,195,244,159, 69, 67, 66,212, 84, 20, 40,225,120,205,208,197, 34, 9,
+173,235,185,202, 65,150,159,199,243,124,185,158,106,213,170, 77,106,209,162,197,112,137, 68, 34, 29, 48, 96, 0, 0, 96,216,176,
+ 97,133,209,209,209,129,233,233,233,153, 85,171, 86,117, 27, 57,114,228,165,237,219,183,171, 63,249,228, 19,137, 78,167,187, 32,
+149, 74,169,155,155,219,204,212,212,212,233,207,114,202,100,178,203,215,175, 95,111,106,227, 17, 0, 39,107, 14,109,198,158, 7,
+ 0, 88, 41, 41,114,179,210,112,231,254,101, 84,175, 94, 93, 85,173, 90,181, 31,221,220,220,196, 70,141, 26,205,243,244,244,156,
+185,109,219,182,231,254, 56,170, 84,170,107, 23, 47, 94, 12,174, 91,183, 46,138,138,138,144,152, 81,140,213,167, 9, 74,244, 42,
+ 0, 42,112,176,130,149,189,135, 66, 74,117, 91,194,194,194,184,198,141, 27,207,242,240,240, 88, 80,158,243,250,245,235,193,245,
+234,213,131,201,100, 66, 76, 76, 12,138,139,139, 97, 48, 24,144,155,155,139,248,248,120,120,123,123, 43, 69, 81,220,213,161, 67,
+ 7, 33, 59, 59,123, 82, 84, 84,212,146,231,133,183,125, 95,248, 24,155, 79, 58,178,210,160, 43,252, 9, 0, 28, 29, 61,115,127,
+157, 20,100,104, 62,169,168,220,113,251,190,240, 49, 98,232,223,182,171,246, 26, 59,118,108, 29, 7, 7, 7,124,250,233,167,152,
+ 60,121, 50, 38, 76,152,224,243,233,167,159,246, 3,176,180, 2, 63,178, 42, 87, 87,215,227,139, 23, 47,246,109,210,164, 9,246,
+236,217,131,205,155, 55,227,238,221,187,102, 47, 47, 47, 73, 88, 88, 24, 38, 78,156,136, 54,109,218,244, 29, 58,116,104,211,178,
+ 0,103, 73,232,232, 61, 97,194,132,142, 77,155, 54, 69,223,190,125, 75, 15, 31, 62,220, 27,192,161,131, 7, 15, 54, 63,118,236,
+216,198, 13, 27, 54,168,166, 79,159,222,122,196,136, 17, 3, 0,124, 95,137,229,239,212,172, 89, 51, 0, 64,211,166, 77, 49,103,
+206,156, 86, 47, 19,176, 8, 33,114, 7, 7,135,159,215,175, 95, 95,223,215,215, 23,189,122,245,106,240,225,135, 31,254, 76, 8,
+233, 68, 41, 53, 88,226,112,117,117,157,186,114,229, 74,111,149, 74,101,241,231, 26, 12, 6,251, 65,131, 6, 77, 1,176,195,194,
+ 58,185, 81, 64, 64, 0,142, 28, 57,130, 86,173, 90,161, 94,189,122,222,131, 6, 13,154,217,166, 77, 27,124,249,229,151, 7,221,
+221,221,189, 83, 82, 82,178, 45,252,248,106, 0,110,149, 45,127, 85, 0,222, 0, 78,151,189, 23, 66, 8, 1,165, 52,161,108, 26,
+223,178,214,172, 23,163,212,244,122,167, 83, 7,171,159, 79,101, 64, 16, 69,248,121, 40, 81,183,154, 13, 18, 50,244,184,151,156,
+ 13, 41, 49,194, 90,165, 64, 96,120, 7,187,156,244,132, 94, 0,202,239,143, 37, 87,247,122,239,157, 14,154, 29,167, 51,144,151,
+124,149, 38, 68,111, 61, 42,148,234, 62, 7,128,235,199, 55, 44,113,179, 87,182,172,221, 64,203,151, 68,188,107,119,100,103,122,
+ 47, 0, 44, 96,253,121, 7,118, 79,100,144, 55,182, 5,235, 33, 57,133,146, 82, 91,151,192,194,226,228,228, 71,227, 10, 10, 10,
+108,111,221,186,149, 17, 27, 27,107, 43,149, 74, 33, 8,194,195, 47,167, 88,217, 66,188,106,167, 92, 38, 71,125,223, 64, 62,230,
+242, 57, 89,108,108,172, 45,207,203,232,171, 40,231,235,206,149, 20,161,170, 73,228, 53, 74,153,228,209,166, 21,137, 76, 83, 64,
+ 92,171, 58, 32, 63,175,188,249,181, 90,173,180,101,203,150,195, 87,173, 90, 37, 77, 77, 77,133,157,157, 29, 76, 38, 19,206,159,
+ 63,159,156,158,158,158, 9, 0,137,137,137,169,158,158,158,169,130, 32,248,248,249,249, 97,208,160, 65,168, 83,167, 14, 25, 57,
+114,228, 8, 66,200,204,103, 93, 9, 88, 80, 80,240,237,252,249,243, 27, 78,158,177, 64,221, 51,140,160,184,196,128,162,162, 34,
+164, 36,220,130,194, 76, 49,125,250,116, 40,149, 74, 0,224,179,179,179,249,217,179,103,141,186,120,241,226, 91, 0,154, 63,175,
+172,121,121,121,203, 22, 45, 90,180,124,206,156, 57,106,157, 78, 7,157, 94,143, 66,157, 28,103, 23,132, 62, 56, 20, 31, 17,133,
+ 89,179,231, 32,160,186, 70,149,156,156,140,137, 19, 39,126,117,247,238,221,198, 0,222,123,145,115,238,220,185,203,231,207,159,
+175,182,178,178, 2,165, 20,162, 40, 34, 49, 49, 17, 0, 48,117,234, 52,148,253,192,241,169,169,169,252,140, 25,211,167, 41, 20,
+138,150, 0, 58, 61,167, 9,157, 2, 40, 37, 4,105, 30, 30, 53,189, 21, 10,110,172,135, 71,233,169, 35, 19,147, 54, 19,130,180,
+ 7,211,128,186,175,116,255,232,254, 58,121,184,193,128,101,169,169,241,183, 41, 5,197,196,191,239, 56,192,201,201,233,179,119,
+223,125, 23,179,102,205,194,238,221,187,191,113,112,112,152, 53,121,242,100,184,185,185, 13, 34,132, 44,171,192, 85,148,211, 23,
+ 46, 92,232,235,231,231,135,143, 63,254,216,112,240,224,193, 73, 0,118, 3,184,127,252,248,241,170,107,215,174,109,191,117,235,
+214, 41,139, 22, 45, 82, 46, 93,186,212,251,131, 15, 62,152, 11,224,179,242,164, 85,170, 84, 25,218,189,123,119,204,155, 55, 15,
+135, 15, 31,238, 65, 41,253,189,236,173,253,132,144, 46, 51,102,204,216, 51,110,220, 56, 44, 92,184,240,243,138, 6, 44, 66,136,
+198,207,207,239,155,182,109,219,226,248,241,227,136,136,136, 64,120,120,248, 80, 66,200,114, 74,105,118, 37,126, 52, 56,107,107,
+235,117,107,215,174,109, 82,163, 70, 13, 76,155, 54, 13, 95,127,253, 53, 86,173, 90,213,164, 87,175, 94,235, 8, 33,221, 45,185,
+122,214,198,198,198, 74,165, 82, 97,214,172, 89,244,254,253,251,229,126,151,221,220,220,236,198,143, 31, 79,108,108,108,108, 45,
+ 40, 35,239,225,225, 97,227,234,234,218,196,213,213, 21,139, 23, 47,134,139,139, 11, 70,140, 24, 1, 71, 71, 71, 20, 23, 23,163,
+115,231,206,210, 51,103,206,116, 5,176,220,194, 69,119, 0,240,176,197,171, 14,128,211,148,210,162,178,207,139,194,131, 83,131,
+ 9,120,208, 47,203,162, 86, 57,142, 82,127,123, 59, 91,164, 92, 78,135, 4,102,248, 85,179,198,185,184, 98, 24, 5, 10,149,198,
+ 10,197,133,121,104,224,227,140,130, 18, 79,128,138,254,150, 56,101, 60,105, 40, 87,168,144, 81,144,143,180,235,135,114, 76,162,
+113,104,222,157, 99, 73, 0,224,224, 19, 57,244, 74,212,222, 19,157,219, 69, 56,103,228, 86, 3,165, 66, 48,139, 65,140,138, 48,
+126,107,157, 0, 0, 32, 0, 73, 68, 65, 84, 80,161, 27,141,138,162, 72,114,114,114, 36, 58,157,142, 55,153, 76,220,227,105,211,
+100, 50, 85, 42,184,252, 25,206,199,249, 51,156,175, 43,181, 92,184, 84,158,199, 19,167,234, 8,168,222,138,100,165, 90, 50,127,
+ 76, 76,140,233,216,177, 99,155, 70,143, 30,141, 5, 11, 22,224,206,157, 59,144, 74,165,240,243,243,115,117,118,118,214, 0, 64,
+205,154, 53,109, 2, 2, 2, 92,120,158, 71, 92, 92, 28, 54,111,222,140, 73,147, 38,209,152,152,152,117,207,251,161, 56,127,254,
+252,175,165,165,165,123,230, 76, 31, 95, 82,154,117, 19,106, 33, 19,180, 32, 30,106, 94,135,190, 3,135,226,110,166,128, 11,241,
+133,184, 16, 95,136,148, 98, 5, 62, 31, 49,150,243,242,242, 10, 10, 13, 13,253,228,121,101,189,112,225,194, 79, 37, 37, 37,135,
+166, 76,153, 82,114,247,238, 93,232,116, 58, 0,128,209, 44,194,104,126,178, 24, 30, 30, 30,152, 53,107,150, 70,163,209,132,107,
+181,218,238, 47,114, 22, 23, 23, 31,154, 48, 97, 66, 73, 92, 92, 28,242,243,243,145,150,150, 6, 66, 8,250, 15, 30,137,187,153,
+226,163,114,102, 27,173, 49,252, 63, 19,185,170, 85,171, 54,111,216,176,225,251, 47, 90,175, 30, 30,158,222,126,126,222, 27,206,
+156, 57,211,211,219,219,123,224,195, 96, 69, 41, 40, 0, 84,175, 94,189,127, 76, 76, 76,239, 6, 13,252, 54,186,185,185,215,254,
+155,143, 34,155,125,244,209, 71,181, 69, 81,196,182,109,219,174, 82, 74,151,238,220,185, 51,166,180,180, 20,221,187,119,175, 1,
+160,181,133, 30,109,143, 30, 61, 6, 70, 68, 68, 96,216,176, 97,198,131, 7, 15, 54,161,148, 46,161,148,222,163, 15,184, 79, 41,
+ 93,126,228,200,145, 70, 67,135, 14, 45, 13, 13, 13, 69,159, 62,125,122, 19, 66,154,148,227,109,212,189,123,119, 95, 81, 20,177,
+121,243,230, 43,143,133,171,135,161,246,232,182,109,219,162, 12, 6, 3,122,246,236,233, 69, 8,105, 94,129,101,151, 41,149,202,
+141,211,166, 77,179, 77, 78, 78, 70,239,222,189, 75,111,220,184,129,137, 19, 39,170,108,109,109,119, 16, 66, 52, 21, 93,159, 74,
+165,114,217,242,229,203, 59, 6, 6, 6,226,179,207, 62, 51, 44, 95,190,252,171,193,131, 7, 27,180, 90, 45,190,253,246,219,142,
+114,185,124, 89, 69,124,105,105,105,249, 71,142, 28,241, 44,111, 72, 79, 79,183,232,214, 44, 53,106,212,176,173, 87,175, 94, 84,
+ 72, 72, 72, 98,253,250,245,107, 2,192,213,171, 87,179,182,109,219, 70, 29, 29, 29,177,111,223, 62,172, 92,185, 18, 77,155, 54,
+133,181,181,117,151, 10, 20,149,150, 13,120,236,245,233,247,159,158,174, 92,103,126,137, 25, 18,142,131,148,167,184,151,174,131,
+ 81,160,144, 73, 57, 72,121, 64,194, 81, 56, 90, 75, 33,149,242, 0, 33, 22, 57, 57, 66,144, 91,108,130,132, 39,144,202,165,132,
+ 23, 68,229,195,247,120,169,168,148,203,149,196,197, 86, 6,185,132,128, 35, 96, 48, 94, 93, 11, 86, 89,165, 35,100,101,101, 73,
+227,227,227,149, 6,131,129,171, 81,163,134, 30, 0,204,102, 51,151,155,155, 43,147,203,229, 32,132, 24,205,102,115,133, 14,185,
+115,114,114,165, 9,247,111,189, 82,231,179, 48,155,205, 92, 73, 73,174,252, 85, 58, 95, 71,110,220,184, 97,117, 59, 62, 69, 83,
+133,175, 27, 51,116,105, 76, 24, 5,164,132, 82,147, 66,119,227, 76, 86,198, 69, 25,108, 21,106, 79, 79,207,114,251,207,220,189,
+123,247,115,119,119,247,217,148, 82, 63, 74,233, 79, 11, 22, 44, 32, 75,150, 44,177, 27, 60,120,240, 85,119,119,247, 20, 95, 95,
+223,106, 11, 22, 44,176, 6,128, 13, 27, 54,136,123,247,238,237,164, 80, 40,110, 36, 36, 36,164,191,200,123,244,232,209,190,161,
+161,161,159,124,247,221,119, 83,204,102,179,194,217,217, 89,177,126,253,122, 36,231, 25, 48,110,253,255, 95, 89,168, 81,240, 24,
+214, 70,131,200,200,150,220,253,251,247,191, 2,176,234,121,206, 99,199,142,245, 8, 11, 11,251,244,219,111,191,157, 0,171,234,
+ 10, 69,157,126,178,150,163, 31,156,126,116,115, 80, 60,170, 16,243,243,243,145,155,155,139,206,157, 59,171, 55,110,220,248, 25,
+128,205,229, 57,151, 46, 93, 58, 65, 16, 4,153,179,179,179, 98,211,166, 77,136,207, 50,224,155,181,113, 40,212, 63, 40,167,149,
+ 66,130,161,173, 20,104,217,178, 37,159,146,146, 50, 10,192,207,207,242,121,122,122,250,248,249,249,109,216,180,105, 83,157, 69,
+139, 22,229,222,186,117,171,196,205,205,109,220, 83,147, 25,102,206,156,153,179,126,253,250, 90,189,123,247,222,232,230,230,214,
+ 43, 53, 53,245,198,223,177, 31,217,218,218, 78, 29, 52,104, 16,126,252,241, 71,228,230,230, 46, 43, 91,127,203, 54,109,218,180,
+182,127,255,254, 88,183,110,221, 84, 66,200, 1, 11, 90,177,222,238,214,173, 27,246,238,221,139, 63,254,248, 99, 10,165, 52,246,
+ 57,173,124,113,132,144,241,187,118,237,154,219,189,123,119,172, 94,189,186, 53,128,147, 47,240,182,108,211,166, 13,246,236,217,
+131,156,156,156,103,118, 60,206,207,207, 95,185,123,247,238,208, 54,109,218, 96,230,204,153,111, 1, 56,106, 65, 61,231,107,107,
+107,187, 98,241,226,197,218,192,192, 64,244,232,209, 67,111, 52, 26,223,251,234,171,175,182,111,217,178,197,106,221,186,117, 65,
+ 3, 6, 12, 56, 70, 8, 25, 76, 41,141,178,100, 93,242, 60, 63,121,233,210,165, 31, 71, 70, 70, 98,228,200,145,230,223,127,255,
+189, 43,165,244, 16, 33,228,206,168, 81,163,126,158, 55,111, 30, 63,111,222,188,143,121,158,207, 18, 4, 97,226,223,177,189, 69,
+ 81,156, 57,127,254,252, 58,254,254,254,208,235,245,184,115,231, 14,210,210,210,126,204,200,200, 56,116,229,202,149,233,169,169,
+169, 59, 93, 93, 93,251,142, 24, 49,194, 35, 56, 56, 88, 91,173, 90, 53, 59, 75, 90,208, 30,107,153,202, 4,112, 3, 64,104, 89,
+203, 21, 0,132, 0,184, 93,246,183, 29,128, 60,139, 10, 75,184,171,183,226,147,189,236,173,108,144, 43,202, 17,159,156, 13,149,
+ 70, 3,142,114, 48,235,114, 81,171,186, 11, 68, 10, 20,100, 37,131,227,136, 69,183,145, 49,137,244, 66, 66, 98,186,187,157, 70,
+137, 90,218, 14, 14, 23, 15,175, 94,101,231,211,108,136,132, 23,120,137,220,102,105,143,238, 31, 59,154, 5,138,162,220, 84, 16,
+158, 63, 7, 6,227, 85, 5, 44, 65, 16,200,186,117,235,108, 50, 50, 50, 56, 95, 95,223,156,250,245,235, 23,203,229,114, 81,167,
+211, 9, 74,165,210,172,209,104, 68,189, 94, 47,191,119,239,158,125,114,114, 50,255,240, 52,156, 37, 28, 61,122,220,213,167,118,
+ 96,198,171,116, 62,231, 8,210,172, 82, 73,132, 87,233,124,157, 16, 69, 81, 62,125,250,244, 70, 14, 14, 14,197,161,161,161,201,
+225, 62,206,187, 83,138,113, 98,193,194,255,246,246,175, 91,109,189, 45,159,155, 87, 44,167,210,164,164, 36,215,219,183,111,171,
+ 41,165,178,242,156, 41, 41, 41,137, 0, 18,221,220,220, 86, 70, 70, 70, 14,234,216,177, 35,142, 28, 57,226, 92, 92, 92,236,172,
+209, 60, 56,136,255,233,167,159,176,115,231,206, 37,105,105,105, 71, 44, 45,107, 84, 84,212, 42, 0,171, 26, 54,108,168,181,181,
+181, 61, 98, 99, 99,195, 37,230, 23, 63,186,178, 80, 38,225,208,228,235,104,100,231,230, 65,202, 17, 40,149, 74, 15, 66, 8,247,
+188,150,177,178, 31,249,239, 0,124, 23,218,174,255,187, 54,247,182,172,154,191, 96,129,226,225,145,105, 21,123, 25,242,242,242,
+144,153,153,137,172,172, 44, 72, 36, 18,232,245,122,191, 23, 30, 34, 63,230, 12, 12, 12,108,225,232,232,184, 75,173, 86,243, 52,
+171, 24,185, 69,198, 39, 78, 65,230,230,149, 66, 42,149, 66,163,209,248, 60,203,229,228,228,100, 37,147,201, 86,252,240,195, 15,
+190,214,214,214,252,128, 1, 3,108, 7, 12, 24,208, 24, 64,227,103, 77,175, 86,171,249,213,171, 87,251, 52,104,208, 96, 69,205,
+154, 53, 59,222,189,123,183,224, 47,108,185,226, 1,244,255,234,171,175,130,148, 74, 37,150, 46, 93, 26, 15,224,199,178,183,127,
+ 94,190,124,249,232,110,221,186,213, 30, 54,108, 88,221,113,227,198, 13, 37,132,124,251,162, 14,228, 50,153,172, 97,221,186,117,
+177, 99,199, 14,224,193,105,193, 23,177,227,212,169, 83,115, 59,118,236, 8,149, 74,165, 45,175,209,165,106,213,170,216,181,107,
+ 23, 0, 92,122,206, 52,151, 98, 99, 99,209,185,115,103,112, 28, 87,221,130,101,239,248,246,219,111,111,156, 57,115,166,196,218,
+218, 26,159,124,242,137,225,236,217,179,157, 41,165, 39, 8, 33,109,123,245,234,245,251,134, 13, 27, 52,199,142, 29,243,157, 62,
+125,250, 31, 60,207,207, 21, 4, 97,114, 57,206,222,211,166, 77,251,234,189,247,222,195,228,201,147,233,143, 63,254,216,143, 82,
+122,168,108, 31, 59, 72, 8,233,111,111,111,191,122,204,152, 49, 36, 63, 63,255, 43, 66, 72, 50,165,244,191,207,243, 21, 21, 21,
+ 21, 8,130, 80, 69,167,211, 89,212,103,203,210,233,125,124,124,222,246,247,247,199,174, 93,187,208,169, 83, 39, 28, 56,112, 0,
+ 18,137,100, 95, 82, 82,210, 49, 0,135, 0,192,205,205,205, 38, 46, 46,238,139,102,205,154,113,127,252,241,199,187, 0,214, 88,
+ 80,132, 4, 0,245, 0,252, 65, 41, 77, 42,187,112,178, 17, 30,220, 7,235, 6,165, 52,177,108, 58,127, 0,119, 45,170,235, 76,
+ 69,155, 14,237,217,222,188,245, 7,131,109,120,158, 64, 2, 25, 74, 10, 11, 0, 65,128, 79,245, 42, 8,173, 91, 5,151, 18,116,
+ 56,117, 96, 91,126, 73, 73,177, 69,183,151, 16, 76,197, 27, 14,253,190, 51, 34,164,117, 31, 27,133, 79, 93, 84,173, 50,188,254,
+213,168,253,191, 42,229, 50,242,254, 7, 93,109, 91,132,214,194,161,203, 5, 56,125,104, 71,158,174, 56,111, 3,139, 12,140, 74,
+ 5,172,103,117, 46, 19, 69, 49,235,192,129, 3,234,241,227,199, 23,185,185,185, 73,138,138,138,184,199,251, 48,201,100, 50,184,
+185,185,153,243,242,242,140, 7, 14, 28,240, 18, 69, 49,231,133,205,177,188, 34,237,251, 77, 75, 61, 5,162, 54,180,105,215, 73,
+244,244,172,241,210, 78, 0,208, 27, 20, 89,219,247,237,176,107, 30,218, 84, 90,197,169,202,179, 42,251, 10, 59,255, 65,164,222,
+190,125,219,105,250,244,233,151, 60, 60, 60,244, 0,224,168, 17,210,178,175,253,156,107, 85,163, 99,154, 84,161,128,179,179,115,
+169,149,149,149,121,207,158, 61,111, 81, 74,211, 44, 21,219,219,219,127, 51,104,208, 32,238,248,241,227,253,123,245,234, 69,188,
+188,188,112,225,194, 5,108,216,176,129,110,219,182,237,219,180,180,180, 74, 29,117, 43, 20,138,120,163,241,201, 91,223, 60,126,
+101, 97,110,110, 46,184,194, 44, 8,130, 96,182,244,238,238, 66,230,165,168, 82,149, 10,245,170,253,255, 89,156,220,220, 92,100,
+102,101, 61, 10, 88, 25, 25, 25,224,121, 94,111,105, 57,229,114,249, 61,131,193,240, 84, 57,197,199, 91, 74, 32,228,101,193,248,
+244,194,148,145,149,149, 85,228,225,225,241,253,210,165, 75,103, 78,153, 50,197,121,225,194,133,185,177,177,177,133, 28,199,233,
+159,250,158, 41,189,189,189,173,230,207,159,239,178,100,201,146, 92, 0,223,253,197,225,170, 83, 64, 64,192,202,246,237,219, 91,
+ 13, 30, 60, 24, 75,150, 44, 65, 90, 90,218, 4, 74,169,185,172,110, 16, 9, 33, 99,151, 47, 95,254,211,168, 81,163, 96, 52, 26,
+103,238,217,179,103, 28, 33,228, 11, 74,233,143,207,114, 58, 59, 59,123, 72, 36, 18,196,196,196, 20, 82, 74,239,150, 19,106,211,
+125,125,125, 51, 8, 33, 46,174,174,174, 94, 47,154,214,193,193,161,166,181,181, 53,146, 31,244, 11, 77,120,206,100,247, 83, 82,
+ 82,168, 92, 46, 39,110,110,110, 62,229, 45,191,157,157,221,151, 63,252,240,131,228,240,225,195,152, 56,113, 98,242,189,123,247,
+ 62, 41,187,141, 0, 40,165, 23, 9, 33,173, 91,180,104,177,118,212,168, 81,181,102,207,158, 77, 98, 99, 99, 7, 0,120, 97,192,
+170, 94,189,122,255,126,253,250, 97,233,210,165, 88,177, 98,197, 48, 74,233,207, 79, 45,243, 54, 66,136,189,131,131,195,252, 65,
+131, 6, 97,205,154, 53, 31, 1,120,110,192, 74, 75, 75, 27,247,209, 71, 31,141,206,205,205,157,107,201, 54,181,100,122, 15, 15,
+143, 14, 61,123,246,116,161,148, 98,201,146, 37,233, 75,151, 46, 45,201,207,207,255, 49, 53, 53,245,216, 83, 45,113,187,246,237,
+219,247,197,224,193,131,113,228,200,145, 5, 30, 30, 30, 52, 57, 57,121,109, 57,219, 52,141, 16, 82,147, 16, 82,135, 82,122,163,
+236, 42,193,164,167,246,187, 90,101,211, 38, 91,178, 76, 89,177,135,247,184,212,107,127,250, 98,212,145,183,188,234, 69, 72, 93,
+236,173,225, 81,219, 9, 14, 26, 25, 40,128, 43,247,116, 56,115,108,191, 41, 35,253,254, 25, 75,174, 32,124,232,116, 13,236,112,
+ 70,237,120,252,173,154,254,225, 18,175, 90,181,209,186, 73,125, 59, 71, 27, 41, 12, 38,138, 3, 23,243,113,250,216, 94, 83,102,
+ 70,210, 81,118, 5,225,159,203,155,214,193,189,220, 22,172,204,204,204,255,200,100,178,102,253,250,245,235, 22, 17, 17, 97, 61,
+112,224,192, 12, 27, 27,155, 98,185, 92,206, 59, 56, 56,200, 41,165,242,253,251,247,187,167,165,165,217, 3,216,146,153,153,121,
+236,169, 47,208, 19, 79,219, 30, 56,165,216,151, 16, 66, 60, 60,236,154, 73,182,124,214, 45, 34, 34, 66,243,178,206, 73,147, 64,
+ 39, 53,215,251,156,118, 37,227,179,243,246, 12,241,116,117,229,155,133,132, 75,173,212,154,178,144,224, 32, 23, 69,200, 42,226,
+124, 69, 63, 90,127,137,211, 96, 48,188,117,231,206,157, 15,123,245,234, 53, 82,171,213, 94, 27, 51,102,204, 89, 59, 59, 59, 83,
+217,145, 34, 12, 6,131,244,192,129, 3, 97, 73, 73, 73,254, 38,147,105, 62,128,173,150,150,243,218,181,107, 70, 0,195,221,221,
+221,127,203,200,200,248,165, 91,183,110, 88,179,102, 13, 78,157, 58,213, 58, 37, 37,229,116,101,151,253,244,233,211,185,109,219,
+182,213,221,184,113, 67,195,107,170,194,213, 94,134,182,227, 47,128,138, 20, 86, 74,138,226,194,124,152,114,114, 80, 82, 82,114,
+221, 82,103, 76, 76, 76, 90,211,166, 77,245,119,239,222, 85,212,172, 89,243, 65,184, 42, 11, 86,153,153,153,200,201,201, 65, 65,
+ 65, 1,149, 74,165, 49,150, 58,163,163,163,227,219,180,105, 35, 36, 36, 36,240, 60,239,140, 42,118, 50,180, 28,253, 96,118,123,
+ 53, 80, 88,144, 15, 93, 86, 22,116, 58,221,115,157,201,201,201,219, 60, 60, 60, 0, 96,230,132, 9, 19, 28,219,182,109, 27, 23,
+ 21, 21,213,230,241,207, 9, 14, 14,254,113,202,148, 41,109,167, 79,159,158,189,110,221,186,113, 41, 41, 41, 91,254,202,125,201,
+193,193,225,139, 61,123,246, 88, 25,141, 70, 44, 89,178, 4, 11, 22, 44, 88, 71, 41,221,249, 84,229,183,143,231,249, 21, 28,199,
+ 13, 26, 50,100, 8, 6, 13, 26,164, 14, 14, 14,254,226,177, 86,174, 39,156,201,201,201,147,131,130,130, 70,103,102,102, 90, 20,
+ 8,110,221,186, 53, 36, 40, 40,104, 84,102,102,230,194, 23, 45,187, 70,163,209, 8,130,128,248,248,248, 60, 74,105,193,115, 42,
+106,189,175,175,111,138, 32, 8, 30, 26,141,198,190,188,253, 51, 47, 47,111,174, 86,171, 29,155,145,145,113, 8,192,108, 74,169,
+254, 41,223,101, 66, 72,240,176, 97,195, 62,155, 57,115,230, 59,233,233,233,219,203,115,222,187,119,111,110,139, 22, 45,190,185,
+121,243,230, 70, 74,233,170,231,148,243,123, 66,136,113,227,198,141, 3,226,227,227,231,189,200,153,148,148,180, 23,192, 94, 75,
+183,239,243,166,127,106,187,143, 24, 58,116, 40,246,238,221,139,162,162,162,111,147,147,147, 23, 60,199, 21,229,229,229,245, 91,
+227,198,141, 59,204,157, 59, 87,214,190,125,251, 1, 0,214, 90,176,127,158, 5,208,168,172, 31,220, 77, 0, 15, 15,108,237,241,
+224,150, 13, 4,207,185, 58,243,121, 78, 74,117,125, 46, 28,223,177, 54,241,246,165, 48,109,100,103,187,252, 18, 79,200, 36, 28,
+138,114, 83,113,250,224,207,121, 41,201,119,206, 26,141,197,125, 42,226, 20,132,146,143, 47,157,216,177, 46, 45,225, 90,104, 73,
+147,246,118,121,133,213, 33,147, 16,228,101, 37,225,236,145, 93,185,169,137,241, 39, 77, 66,233,160,191,179,158,255,183, 56,255,
+ 85, 1,171,236,116,201, 81,173, 86,123,234,200,145, 35,109, 79,158, 60,249, 78,203,150, 45, 51,194,195,195,139,206,159, 63, 95,
+ 61, 62, 62,222, 5,192,110, 23, 23,151,125, 49, 49, 49, 22,221, 57,249, 85, 59,203,124,102,128, 76,154,252,185,211,220,164,203,
+ 89, 11, 82, 51,182,119,245,169,238, 69, 0,144,152,152, 11,213,227,227,227,157, 43, 90,206,127, 80,234,167, 0,126, 36,132,236,
+ 56,123,246,236,128,247,223,127,127, 80,203,150, 45,207, 82, 74,201,169, 83,167,180,247,238,221, 11, 19, 4, 97,149, 40,138,131,
+ 42,243,152,156,135,167, 92,100, 50, 25,245,245,245, 37, 42,149, 10, 10,133,226,250,203,150, 59, 47, 47,111,228,252,249,243,151,
+ 79,159,179,132,255,252,109, 91,100,101,103, 35, 59, 59, 27,185, 57, 57,144, 65,135,139,215,174, 10, 69, 69, 69, 35, 43,226, 52,
+ 26,141, 99,198,143, 31, 63,119,222,188,121,154,194,194,194, 71, 1, 43, 39, 39, 7, 58,157, 14, 71,142, 28, 41, 53, 26,141,227,
+ 42,226, 44, 40, 40,152, 48,119,238,220, 25, 67, 71,142,229, 6, 68, 72,145, 87,160, 67, 94, 94, 30,138, 10, 11,161, 32, 58, 68,
+ 93,189, 42, 24, 12,134,175, 95,228, 40, 11, 89, 52, 49, 49,113, 92, 97, 97,225,237,103,124, 70,218,144, 33, 67, 82, 79,157, 58,
+ 53, 53, 41, 41,105,243, 95,189, 15,229,228,228,204,105,212,168,209,236,204,204,204,120,163,209,248, 51,165,244,153,101, 16, 4,
+ 97, 4, 33,228,236,178,101,203,186, 56, 57, 57,185,164,165,165,205,127,193,126, 89,161, 64, 96,233,244,247,239,223,159,160,213,
+106,191,206,200,200,152, 95, 78, 96,251,178,108,186,133, 22,124,246, 62, 0,251,202,153,198,140, 7,183,168, 88,106,225,242,252,
+ 10,224, 87, 11,166, 91, 13, 96,245,223, 81,119,228,230,230,206,235,216,177,227,248,244,244,244,163,105,105,105,139, 95, 52,173,
+201,100,234, 51,104,208,160,241,174,174,174, 97, 25, 25, 25, 75, 44, 92, 7,102, 0, 39,202, 30,149,227, 13,224,225, 85,120,121,
+ 0, 18, 42,243,168,156,178, 59,180,127,224,228,215,170,253,193,237,139,123, 65, 16, 2, 1, 2, 78,202, 95,214,151, 20,111,176,
+180,229,234, 25,206,247,157,252, 90,181,207, 73, 79,232, 45, 10, 66, 32, 71, 32, 18,158,191, 82,170, 47, 94,147,113,237, 32,123,
+ 84, 14,163,114, 33,180, 34,207,194,117,119,119, 87, 73,165,210,247, 40,165,161,162, 40, 70,137,162,184, 51, 37, 37, 69,247, 50,
+ 9,247,213, 59, 9,249,178,151,170,138,149, 10,223, 91,169, 16,176,108,135,253,120,179, 89,220,241,178,229,252,167, 28, 49, 16,
+ 66, 52, 50,153,108,164, 40,138, 61, 68, 81,220, 36,138,226,252, 23,221, 91,200,210,114,214,170, 85,107,121,139, 22, 45,122,253,
+254,251,239, 43,239,221,187, 55,242, 85, 44,123, 68, 68,196,154,170, 85,171,190, 31, 25, 25,201, 43,149, 74,164,166,166, 34, 39,
+ 39, 7, 55,111,222, 52,103,103,103,207, 56,113,226,196,236, 74, 56,255, 43,151,203,223,233,212,169,147, 90, 38,147, 33, 39, 39,
+ 7,249,249,249,244,196,137, 19, 6,142,227, 70,159, 58,117,106,101, 5,215, 39,137,136,136,248,185,106,213,170,111,133,135,135,
+243, 50,153, 12,185,185,185,200,206,206,198,141, 27, 55,132,204,204,204,255,156, 57,115,230,123, 75,156, 62, 62, 62,242,184,184,
+184,103,246,137,209,106,181,210,231,133,127,118,148,204,156,204,201,156,255,182, 22, 44, 66,200, 64, 74,233,202, 55,182, 5,235,
+105,202, 66,202, 38,188,196,243,169,254,124, 39,165, 11, 55, 32, 13, 32,239, 78,158, 12,114, 63, 81,247,224,130,248,127, 9,101,
+ 97,106, 50,202,233, 35, 82, 81,110,223,190, 61,216,221,221,253,171, 23, 5,213,138,114,252,248,241,190, 65, 65, 65, 91,147,146,
+146,198,169, 84,170, 58,130, 32,152, 13, 6,195, 69,131,193, 48,246,236,217,179,231, 43,233, 28, 16, 20, 20,244,211,206,157, 59,
+135, 11,130,224,207,113, 92, 41,165, 52,134, 82, 58,245,212,169, 83,177,149,108, 33,236, 28, 20, 20,212, 57, 57, 57,249,107,133,
+ 66, 81, 91, 20, 69, 83,105,105,233, 57,131,193,240,159,179,103,207, 90,236,124, 94,184, 2, 30,220, 34,131, 29,239, 49, 24, 12,
+198,155,131,228,205, 93, 52, 74, 39, 78, 4,197, 68,182,145, 95,113, 24,126,165,156, 63,127,254,119, 0,191,191, 98,231,126, 0,
+251, 95,177,115, 7, 44,188, 35, 54,131,193, 96, 48, 24, 28, 91, 5, 12, 6,131,193, 96, 48, 24,175, 22, 2, 32,224, 89,111, 84,
+228,220, 42, 33, 36,160,162, 31,108, 65,223, 23,230,100, 78,230,100, 78,230,100, 78,230,124,195,156,143,185,167, 60,231,173,228,
+ 50,207, 63,186, 15, 22,249, 51,187, 39,177, 14,128,204,201,156,204,201,156,204,201,156,204,249,111,132,157, 34,100, 48, 24, 12,
+ 6,131,193, 96, 1,139,193, 96, 48, 24, 12, 6,131, 5, 44, 6,131,193, 96, 48, 24, 12, 22,176, 24, 12, 6,131,193, 96, 48, 24,
+ 44, 96, 49, 24, 12, 6,131,193, 96,188, 54,144,127,209, 77,206, 25, 12, 6,131,193, 96, 48,254, 18,158,104,193, 34,132,176,180,
+197, 96, 48, 24, 12, 6,227, 47,231, 77,203, 32,236, 20, 33,131,193, 96, 48, 24, 12, 6, 11, 88, 12, 6,131,193, 96, 48, 24,255,
+128,128,197, 78, 13, 50, 24, 12, 6,131,193,248, 59,120, 83, 51,200,195, 22,172,200,178, 5,140,100,155,154,193, 96, 48, 24, 12,
+198, 95,200, 27,153, 65,216, 85,132, 12, 6,131,193, 96, 48, 24,175, 24,214, 7,139,193, 96, 48, 24, 12, 6,227,159, 20,176, 8,
+ 33, 1,204,201,156,204,201,156,204,201,156,204,201,156, 44, 96, 49, 24, 12, 6,131,193, 96, 48, 88,192, 98, 48, 24, 12, 6,131,
+193, 96, 1,139,193, 96, 48, 24, 12, 6,131, 5, 44, 6,131,193, 96, 48, 24, 12, 6, 11, 88, 12, 6,131,193, 96, 48, 24,127, 19,
+ 4,192, 51,175, 4,160,148, 94,177, 88, 82,137,171, 9,202,243, 51, 39,115, 50, 39,115, 50, 39,115, 50,231,155,231, 44,207, 93,
+145,252,241, 90, 7,172, 63,243, 70,163,132,144,128, 87,189,162,152,147, 57,153,147, 57,153,147, 57,153,243,205,115,190,105, 72,
+216, 42, 96, 48,254,225,108, 39, 60,156,234,214, 0,161,174, 32,178,116, 28,185,116, 23, 19,169,248,210, 78,215,122,213, 96, 48,
+185, 64,165,202,194,129, 11,241, 47,237,100, 48, 24, 12, 22,176, 24, 12,198, 63, 6, 79,255, 90, 48,137, 83, 0,184, 2,134, 59,
+104, 22, 48, 15,192,181,151,114,186,248,215,130, 40, 78,132,140,243,128,177,244, 54, 90,212,157, 7, 32,150,173,108, 6,131,193,
+176,140,191,165,147,123,112,112,240,201,144,144,144, 9,145,145,145, 10,182, 9, 24,140,151,224, 74,160, 26, 38,211,219,165, 70,
+209,125,223,169, 28,231, 98,189, 80, 27,156,177, 13, 98,253, 53, 47,229,228,196, 86,122,163, 80,117,195,193, 98,151, 34,189,185,
+ 14, 68,225,229,156,101, 52,104,208,192, 54, 52, 52,116,151, 86,171,117,100, 27,143,193, 96,176,128,245,138,161,148, 54,112,113,
+113, 25,170,211,233,110, 4, 5, 5,117,248, 55,173,240,176,176,176, 63, 26, 55,110,156, 16, 30, 30,158, 16, 30, 30,126,170,188,
+241,111, 42,193,193,193, 13,154, 54,109,186,215,223,255,193,143,118,224,103, 59,157,131,250,239,247, 14,251, 98,159, 7,251, 90,
+ 86,128, 66,234, 2,240,205, 99,227, 75, 84,233,185,102,151,152, 27,197, 86,160,124, 51,100,139,174, 47,229, 20, 73,243, 11,113,
+122,245,233, 59,206, 46, 39,175,150, 90, 3,124,243,151,114,150, 33,145, 72, 6, 0,104,201,243,252, 16,182,241,254,221, 16, 66,
+252, 9, 33, 29, 8, 33,218, 87,232,156, 86,183,110,221, 56, 66,200,231,108, 13, 51,254, 49, 1,171,139, 55,105,220,195,155,252,
+222,173, 38,201,232,238, 77, 50,122,122,147,131, 93,106,147,166,149,253,224,159,126,250, 73,181,126,253,122,231,128,128,128,181,
+ 97, 97, 97, 7,195,194,194,124, 42,227, 9, 13, 13,221, 21, 28, 28,252,254,211,227,180, 90,109,151,167,198,157, 11, 13, 13, 77,
+ 11, 9, 9,185,106,137, 87,171,213, 94,214,106,181,153,193,193,193,151,159, 26,223, 37, 52, 52,116,215, 83, 97,225,253,167,199,
+ 61, 15,158,231, 61,118,239,222,237,252,219,111,191, 57, 75,165, 82,151,167,199,255,250,235,175, 79,140,175, 40, 33, 33, 33,125,
+ 67, 66, 66,254,120,124, 92, 80, 80, 80,159,167,199,149,179,236,127, 4, 5, 5,245,121,202,251, 71, 72, 72, 72,223, 87, 20, 50,
+131,228,114,249,239, 70,163,177,169, 70,163, 81, 3,128,196,164,178, 22,101,146, 46, 70, 42,105, 24,248,245, 1,103,246,213,180,
+128, 88,127, 25, 68,115, 19, 65,164, 78, 87,227,245,206,237, 58,118,145, 92,186,173,115, 50, 9,130, 61, 68, 52,195,209, 26,138,
+ 74, 57, 5, 67,184, 64, 69,151, 67, 23,164,206,145, 29,134,240,135,175, 72,157, 76,130,224, 0, 65,108, 90, 41,231,255,239, 87,
+ 82,158,231,191, 24, 56,112, 32, 71, 8,249,212,199,199, 71,254,111,218, 92,141,235, 19,247,183,130, 37,199, 66,234,145,198,175,
+ 48, 80,212,181,178,178, 58, 65, 8,169,245, 15, 11, 87, 13, 0,168, 41,165,191, 1,112, 33,132, 72, 94,129,115,246,148, 41, 83,
+190,188,124,249,178, 91,205,154, 53,199, 17, 66,120, 86, 73, 48, 94,251,128,245,145, 23, 25,235,230,234,241,203,216,133,155,154,
+254,247,232, 93,205,183,187,207,107, 70,142,154,209,216,205,214,121, 71, 79,111, 50,245,121,243,189,232, 10, 3,185, 92,142, 59,
+119,238, 96,233,210,165,202, 73,147, 38, 53,178,178,178, 58, 27, 22, 22, 54,231, 97,139,134,165, 78, 74,105, 35,153, 76,182, 60,
+ 44, 44,108,197, 99, 21,118, 35,165, 82,185, 44, 44, 44,108,213,195,211,144, 90,173,182, 70, 84, 84,148, 53, 33,196,197,146,114,
+134,134,134,186,198,196,196,168, 9, 33,174, 0, 16, 25, 25,169, 8, 13, 13,253,193,211,211,115, 41,128, 70, 0,224,227,227, 35,
+ 15, 11, 11, 91, 81,181,106,213,111, 9, 33,141, 44, 89,118,142,227, 96,103,103,135, 77,155, 54,129,227,184,199, 43, 7,216,217,
+217, 97,227,198,141, 32,132, 84,120,125,250,251,251,107, 66, 67, 67, 55,185,185,185,205, 17, 69, 49, 12, 0, 2, 3, 3,213,161,
+161,161, 27, 61, 61, 61,231, 62, 28,103,161, 51, 76,161, 80,204, 9, 13, 13,221, 24, 24, 24,168, 6, 0, 81, 20,195,164, 82,233,
+236,208,208,208, 77, 21,221, 70,205,155, 55, 31,220,168, 81,163,220,144,144,144,194,136,136,136,141, 60,207,239,157, 62,125,186,
+ 90,169, 84, 26,204,246,213, 53,218, 65,135,170,202,164,114, 51, 37, 92, 41, 21, 48, 69, 90, 40,179,247,249, 98,159,220,210,101,
+175, 44,255,120,103, 38,239, 12,130, 22, 55,239,233,148, 94,181,130,213, 46,126, 93,224,108, 39, 85,156,185, 94,108, 5, 9,137,
+ 4,167,113,170,148, 19,210, 22, 87,239,232, 84, 14,222,237, 84, 33,141,155, 1,234, 90,138,163, 23,139,173, 33,225, 43,231,252,
+255,247,223, 11, 15, 15,151,181,106,213, 10,238,238,238,156,141,141,205, 71,111,252, 54,122, 44, 92, 89, 41,228, 71,231, 79,249,
+ 50,200,213, 65,189,213,146,144,101,193,229,243,117, 93, 92, 92,246, 45, 91,182,172,161,181,181,245, 1, 75, 66,214,235,176, 62,
+203,194,149,140, 82, 26,245, 48,214, 3, 8,127, 73,231,236, 73,147, 38, 13, 25, 61,122, 52, 10, 11, 11,209,167, 79, 31,107, 0,
+ 51, 43,227,236,218,181, 43,223,181,107, 87,254, 95, 81,135,188,102,206,114,144, 3,104, 1,160, 3,128,183, 0,132,150,253, 29,
+ 82, 54,116, 0,208,234,169,215,144,135,109, 4,101,255,135, 61,199,209,225, 25,243,133, 60, 54,254,241,255,159,254,251,197, 1,
+139, 16, 66, 31,127,125, 98,103,243, 33,141,156,220, 60,190,156,181, 35, 90, 37,222,186,136,243,159,180,196,141, 97,239, 65,117,
+251, 34, 70, 13,253, 70,101, 99, 99,247,105, 87, 31,210,172, 50,107,235,214,173, 91,216,188,121, 51,156,156,156,200,170, 85,171,
+ 20, 31,126,248,225, 0, 27, 27,155, 91,193,193,193, 31, 89,234,224, 56, 78, 92,189,122,181,230,221,119,223,237,226,224,224, 16,
+ 29, 18, 18,226,197,113,156,184,110,221, 58, 77,183,110,221, 58, 27, 12,134,152,176,176, 48,159,243,231,207, 11,209,209,209,224,
+121,203, 14,106, 98, 98, 98,132,189,123,247, 62,108,113,241, 1, 16, 51,107,214,172, 46, 59,118,236,176,178,177,177,161, 33, 33,
+ 33, 94, 85,171, 86,141,158, 51,103,206, 71, 63,253,244,147,149,181,181, 53,181,176, 34,128, 94,175,135, 82,169,124, 34, 72, 61,
+ 28,175, 80, 40,158, 27,176, 94,208,106, 85,215,209,209,241,252,204,153, 51, 59,238,220,185, 83,101,109,109,141, 70,141, 26,213,
+177,179,179,187, 48,119,238,220, 78,187,118,237, 82, 89, 91, 91, 91,236,147,201,100,216,176, 97,131,186, 71,143, 30, 29, 20, 10,
+197,249, 70,141, 26,213,145,201,100,216,180,105,147,186, 71,143, 30,237,212,106,117, 76, 72, 72, 72, 93, 75,125,130, 32,140, 90,
+184,112,161,124,235,214,173,124,245,234,213, 91, 79,159, 62, 93,173,213,106, 9,165, 20, 84, 94,203,214, 44,161, 93,244,156,217,
+131, 55, 24,127,229, 64,210, 5,137,177,167,157,192,179, 86,172, 23,177,157,240, 32,198, 6, 0,241,142,185, 85,226,216, 32,162,
+167, 4, 25,191, 32,212,207, 74,114, 56,166,208,133,138,168, 6,193, 28,140,163,145,146, 10, 57,101,166, 64,112,212,231,192, 69,
+206, 49,188, 85, 79,201,253,251,247,225, 85, 55,146,223, 29, 13, 23, 74, 81, 3, 68, 8,170,144,243,201,253,106, 76,215,174, 93,
+ 53, 9, 9, 9, 8, 15, 15, 87, 43, 20,138,209,175,164, 21,239,180, 95, 53, 28,247,139,192, 9, 63,215,202,150,237,207,110,185,
+178, 82,200,143,108,218,240,163, 91, 96, 68,127,178,226,203,234,246,142, 86,178,173, 47,211,146, 85, 22,174,246,158, 61,123,214,
+225,237,183,223,198,164, 73,147,156,108,108,108, 14,188,238, 45, 89,143,135, 43, 66,136,170,236,244, 96, 10, 0,143,151,112,206,
+157, 52,105,210,144, 49, 99,198,224,204,153, 51,152, 51,103, 14,218,181,107, 7, 59, 59,187, 80, 75, 29,193,193,193, 33,205,155,
+ 55,223,220,188,121,243,212,196,196,196,130,123,247,238, 21, 68, 68, 68,164, 54,111,222,124,115,112,112,112,200,203, 44,114,217,
+192,120,241, 54,124,110, 6,121,140,250,163, 71,143, 14, 37,132,252, 58,122,244,232, 96, 0, 78,132,144, 95, 1, 56, 3,112, 46,
+251, 91,254,212,171,115, 89,104,122,248,190,227,179, 28, 15,135,167,230,115,126,108,252,227,159,241,244,223,229,183, 96, 17, 66,
+154, 3, 56,246,244, 4, 82, 17,227, 7,141,152,170,140, 95,187, 0,169, 27, 22,130,100, 37,131,207, 75, 67,233,177, 95, 96, 58,
+254, 11,122, 55, 14, 87,169, 64, 38, 86,102,165, 90, 89, 89, 65, 38,147,225,214,173, 91,184,126,253, 58,218,181,107, 39, 91,178,
+100,137,109, 64, 64,192,178, 38, 77,154,156, 9, 11, 11, 11,176, 96,195,160,118,237,218,232,214,173,155,124,216,176, 97, 53,229,
+114,249, 41, 74,169,196,203,203, 11, 31,126,248,161,108,212,168, 81,213,229,114,249, 9, 81, 20,101,106,181,218,226,240, 66, 8,
+129, 90,173, 6, 0,169,183,183,247,201,205,155, 55,215,104,210,164,137,100,255,254,253, 40, 44, 44,228,107,213,170,117,102,243,
+230,205,222,141, 27, 55,150,156, 56,113, 2, 58,157,206,226,128, 85, 92, 92,252,204,128, 85, 84, 84,244, 63,227, 45, 8, 87,125,
+107,214,172,121,124,203,150, 45, 30, 77,155, 54,229, 15, 31, 62,140,194,194, 66,120,122,122,158,216,178,101,139, 71,120,120, 56,
+127,234,212, 41, 20, 22, 22, 86, 40, 96,149,173, 63,233,200,145, 35, 61,120,158, 63, 46,147,201, 80,189,122,117,124,248,225,135,
+178, 17, 35, 70,120,200,100,178,163,150,158, 50, 20, 4, 65,238,236,236, 12, 91, 91, 91,244,239,223, 95, 93,167, 78, 29, 98, 54,
+155, 65, 41,133,220, 88,108, 36, 34,173, 77, 8,247, 62,225,121,163, 0,178,145, 80, 62, 66, 52, 75,100,172,218,121, 1, 54, 1,
+ 14,224, 73,203,123,169,165, 10,165,166,170,149,198,169, 14,144,115, 12, 53, 61, 20, 32,132, 83, 68,197, 22,105,192,147,150, 16,
+178, 29, 42,228, 20,208,242,110,114,169,194,168,170,167,113,247,168,134,172,172, 44, 84,245,242,131,158,115,150,159,186, 90,164,
+ 1,173,160,179, 12,173, 86,219,164,106,213,170,174, 53,106,212, 64, 86, 86, 22,106,213,170, 5, 43, 43, 43,187,134, 13, 27,182,
+172,244, 58, 56, 90, 67,129, 2,174, 17, 4,204, 4, 48, 14,224,166,128,100, 53,192,121,173,244,117, 11, 87,155, 55,254,232,238,
+232, 86, 7,184,210, 31, 85, 28,228, 88, 53,186,190,189,163,149,162, 82, 33,139, 16, 82,183, 74,149, 42,123,207,158, 61,235,168,
+ 84, 42, 17, 19, 19, 3,127,127,127, 44, 88,176,192,201,206,206,238,181, 13, 89, 79,133, 43,123, 74,169, 14,128, 8,160, 43, 42,
+113,213, 43,121,192,130,169, 83,167, 14, 30, 51,102, 12, 78,159, 62, 13, 15, 15, 15,100,100,100,160, 89,179,102,247,243,242,242,
+102, 91,210, 90,213,172, 89,179,111,237,237,237,127, 29, 48, 96, 64,199, 77,155, 54,217,236,220,185,147, 52,111,222,156, 84,171,
+ 86,205,102,192,128, 1, 29,237,237,237,127,109,214,172,217,183,150,182,106,149, 33, 1,160, 4,160,126, 56,220,185,115, 71,238,
+227,227, 35, 39,132, 40,203,194,165,130, 16,194,158,166, 82, 78, 6,121, 12,167, 89,179,102,205,160,148,118,156, 53,107,214,140,
+199,230,251,245, 5,206,199, 67, 19, 0,224,105, 7,165,180,227,227,175,143,207, 75, 41,237, 72, 41,237,248,248,252, 47,250,188,
+231, 6, 44, 0, 71, 40,165,205,255,167, 25,144, 32,192,181,102, 29,228, 29,216, 6, 21, 79,158, 24,184,187, 87, 80, 85, 41,129,
+153,210,186,149, 89,161, 86, 86, 86,143, 6,142,227,144,154,154, 10,158,231, 49, 97,194, 4,229,144, 33, 67,234, 73, 36,146,195,
+205,155, 55,159, 82, 94, 96, 1,128,168,168, 40,212,170, 85,139,140, 25, 51,198,186, 89,179,102, 18, 0,184,116,233, 18,124,124,
+124,200,180,105,211,172, 58,117,234, 68, 42, 18,176, 56,142,131, 82,169, 68,100,100, 36, 89,179,102,141, 70,161, 80,224,183,223,
+126, 67, 86, 86, 22,222,126,251,109,201,154, 53,107, 52, 74,165, 18, 71,143, 30, 69,126,126,126,133,130, 91,105,105, 41,158, 46,
+203,243, 90,182, 94, 68,147, 38, 77,190,115,117,117,157,179,126,253,122,133, 74,165,194,225,195,135,145,159,159,143,238,221,187,
+155, 55,110,220,168,180,177,177,193,169, 83,167,144,159,159, 95,169, 29,254,177,117,170, 10, 15, 15, 55, 1,192,133, 11, 23,224,
+235,235, 75,198,140, 25,163,178,177,177,153, 29, 17, 17,241,157, 5, 77,201, 40, 41, 41,129, 94,175,199,237,219,183,145,147,147,
+131,164,164, 36,136,162, 8,130,140, 66, 81, 38,221, 74, 68,225,125, 94,170, 80, 72, 56, 18, 11, 2, 63, 42, 17,101,100,242,100,
+ 86,249, 60,111, 39,146,149,214,130, 72, 26,156,190, 86,100,223,244,237, 30, 50,100,238, 5,168, 9, 32, 18,180, 8,243,148,252,
+114,170,196, 5,148, 4, 64, 69,124, 1, 11,118, 40, 66, 8,164, 6, 31, 80, 18,116, 32,198,236,208,180,205,103,178,164,164, 36,
+200,100, 50, 40, 20, 10, 4, 53,254, 64,178,249,136,201, 21, 64, 32,148,164,182, 69,206, 39, 67,251, 55,253,250,245, 83, 39, 39,
+ 39, 63,114,182,107,215, 78, 99,101,101, 53,166,210,225,138,183, 10,133, 89, 24,114,245,174,174,218,180,245,169,117,226,146,116,
+190,224,232, 23, 48, 8,245, 95, 54,100,121,121,121, 69,212,169, 83,231,154,183,183,119,248,203,132, 43,107,133,252,240,150,141,
+ 63,186, 59,184, 62, 8, 87, 16, 74, 0, 94, 5, 87, 23,123,172,154, 24,105,239,104,173,170, 80,200, 42, 11, 87,123,206,156, 57,
+227,168, 84, 42,113,238,220, 57,200,229,114, 40,149, 74, 4, 6, 6, 98,229,202,149, 78,246,246,246,175, 69,200, 34,132,216, 17,
+ 66, 90, 17, 66, 58, 19, 66,222,123, 44, 92,213, 0, 16, 73, 8,105, 9,160, 10,128, 19,148,210,203, 22, 58,195, 37, 18,201,207,
+ 13, 26, 52,184, 35,145, 72, 98,102,204,152, 49,104,212,168, 81, 88,188,120, 49, 34, 35, 35,239,126,243,205, 55,184,113,227,134,
+185,184,184,184, 43,165,116,111,121,190,148,148,148,113,222,222,222, 93,118,238,220,169,169, 94,189, 58, 87, 92, 92,140, 3, 7,
+ 14, 96,238,220,185, 40, 45, 45,133,167,167, 39,183,115,231, 78,141,183,183,119,151,148,148,148,113, 22,148,207,201,201,201,169,
+ 22, 30,156,206, 82, 0, 80, 1, 80, 39, 36, 36,104, 14, 31, 62,108,223,160, 65, 3, 59, 43, 43, 43,245,184,113,227,220,135, 13,
+ 27,214,177,188, 22,144,127, 25,207,204, 32,207, 9, 77,143,255,190,116,124, 94,232,121,248,222,179,194, 83,101, 11,249,162,207,
+123, 81,192,138, 36,132, 28,125,214, 68,198,112,179,214,203, 0, 0, 32, 0, 73, 68, 65, 84,156,116, 40, 32, 64,205, 19,168, 36,
+228,193, 43, 79,160, 34, 34, 36,185,233, 21,172,106,159, 12, 88,214,214,214,176,182,182,126, 34,104,233,116, 58, 20, 23, 23, 63,
+209, 71,233,121, 60, 60,229,103,111,111,143,194,194, 66,152,205,102, 60, 60, 29,230,224,224,128,210,210, 82, 16, 66,160,209,104,
+160,209,104, 42, 28,176, 0,224,244,233,211, 56,121,242, 36, 36, 18, 9, 28, 28, 30, 28,188,159, 59,119, 14,151, 47, 95,134, 92,
+ 46,135,163,163, 99,133,188, 6,131, 1, 74,165,242,127,250, 96, 25, 12, 6, 40, 20, 10,139, 79, 99,114, 28, 7,189, 94, 79,207,
+157, 59,135, 43, 87,174, 64,161, 80,192,217,217, 25, 50,153, 12,137,137,137,136,141,141,133, 92, 46,135,179,115,229,190,195, 54,
+ 54, 54,200,203,203,131, 40,138, 80,169, 84,143,198, 21, 21, 21,129,227, 56,139,182,207, 67, 46, 92,184,128,211,167, 79, 35, 62,
+ 62, 30,151, 46, 93,194,141, 27, 55,240,196, 83, 4,104, 89, 51,186, 73, 52, 81,128,227, 77, 60, 55, 9, 19, 89,149,243,204,106,
+168,190, 13, 56,201, 91,153,121, 38, 69, 86,145,220,166,138,207, 91, 64,214, 94,128,240,128,212, 14,141, 26,214,196,253, 52, 65,
+125, 35,169, 84, 9,163,208, 26,251,235,218, 89,228,148, 72, 90,102,228,153, 20,241,249,206,214,117, 3,180,200,200,200,128, 66,
+161,128, 66,161, 64,112,216, 91,184,147, 38,170,174, 38,232,212, 16,197, 86, 22, 57,255,191,245,170,166, 82,169, 12, 13, 10, 10,
+ 34,233,233,233, 80, 40, 20, 80, 42,149,104,220,184, 49, 56,142,171,167,213,106,125, 43,180,252,119,124,228,144, 89,133, 0,194,
+144,235,119, 75,220,118,157,212,213,122,231,157, 15,236, 23,109,207,244,189,158,160,175, 1,179,113, 24, 10, 77, 13, 43, 27,178,
+188,188,188,154,170,213,234,159,198,141, 27, 87, 67, 42,149,238,168, 89,179,102,147,202,120,212, 10,126,201,216, 97,221,221,237,
+ 31,134, 43,115, 49,192,171, 0, 94,253, 32,100, 85,113,194,180, 97,173,236, 85, 82,217,102, 75,157, 42,149,106,237,178,101,203,
+156, 30,134, 43,153, 76, 6,165, 82,249,104, 8, 10, 10,194,196,137, 19,157,236,237,237,215,252,205,225,202, 30, 64, 19, 0, 87,
+ 0,236, 4,112,248,177,112,229, 13, 96, 87, 89,171,213, 69, 74,233,125, 11,157,141,218,182,109,187,247,206,157, 59,109, 46, 94,
+188,232,154,150,150,230, 59,114,228, 72, 44, 90,180, 8,163, 70,141,218, 74, 41,109,176,109,219,182,198, 81, 81, 81,161,148,210,
+107, 22,214,161,159,244,236,217, 83,173, 82,169,160, 84, 42,177,126,253,122,124,246,217,103, 80, 40, 30, 92,203,161, 86,171,161,
+ 82,169,208,179,103, 79, 53, 33,164,159, 5,202,156,130,130, 2,171,206,157, 59, 87, 45,107,185,210, 24, 12, 6,171,172,172, 44,
+ 27,142,227,108,235,213,171,231, 50,113,226, 68,223,162,162,162,250,187,119,239,206, 0,144,197, 42,180,242, 51,200,211, 1,199,
+146,113,149,157,222,210,144, 85,161,128, 69, 41, 61, 10,160,217, 51, 38,184,114, 63,250, 40, 28,252,131,158,108,193,146, 16,168,
+173,109,112, 55, 57, 17, 82,144,235,149, 40,224, 19, 45, 88, 15,135,212,212, 84,124,243,205, 55, 37, 27, 54,108,184,106, 52, 26,
+ 91, 28, 61,122,116,130, 37, 45, 88, 46, 46, 46,184,127,255, 62,157, 59,119,110,225,190,125,251,204, 15,199, 37, 38, 38,210,241,
+227,199, 23,253,248,227,143,180,162,167, 8, 85, 42, 21,142, 30, 61, 74, 39, 76,152, 80,144,156,156, 76, 29, 28, 28,224,232,232,
+136, 67,135, 14,153, 71,143, 30, 93, 16, 23, 23, 71, 29, 28, 28,224,224,224, 80, 33,175, 32, 8, 80,169, 84, 79,204,195,113, 28,
+ 76, 38,211,255,140,127, 17,199,143, 31,255, 44, 63, 63,127,212,215, 95,127,173,187,118,237, 26,117,118,118,134,179,179, 51,214,
+174, 93, 43,233,211,167,143,238,210,165, 75,143,198, 85, 6, 39, 39, 39,220,184,113,131,206,156, 57, 83,119,240,224, 65, 41, 0,
+ 56, 59, 59,227,198,141, 27,116,234,212,169,186,188,188,188, 81,199,143, 31,255,204,146,109,157,147,147,131,172,172, 44, 36, 37,
+ 37, 33, 43, 43, 11,217,217,217, 16, 69, 17, 20, 46,214,156,209,244, 33,120,110,135, 96, 42, 45, 53, 73, 72,109,128,222, 21, 68,
+163, 97,226, 68,176, 59,135, 63, 11,185, 80, 5,160,141, 79, 92, 46,178,109,221,254, 35, 57, 41,136, 2, 76, 69,128,212, 30,144,
+218, 67,162,116, 68,219,150, 13,249, 53,251, 11,170,128, 32, 12,182,242,242,251,183, 72, 69, 23, 80, 49,252,224,121,189, 93,211,
+118, 67,229, 57, 57, 57,224, 56,238, 81,192, 82,107, 52,104,213,190, 39,183,250,128,190, 10, 68,218, 8, 42, 98,113,159, 25,153,
+ 76,246,101,191,126,253,100, 79, 59, 85, 42, 21,222,125,247, 93,133, 70,163, 25,101,241,178,199,250,203,144,161, 10,129, 40, 12,
+185,145,160,115,219,121, 74, 87,107,228,196,213,170,122,245,195,240,233, 59,206,170,153, 27, 50,253, 46,222, 41,169, 1,137,121,
+ 40,138, 76, 65, 88, 89,177,144, 85,179,102,205, 38,106,181,250,231,157, 59,119,170, 91,180,104,129,175,190,250, 74, 35,147,201,
+118,120,121,121, 85,248,138,105, 93,161, 48, 98,234,162,245, 25,151,182,182, 5,204,133,101,225,234,255,135,140,124, 17,227,151,
+ 29, 46, 48, 80,177,143,197, 78,157,110, 64,255,254,253,115,126,250,233,167,255, 9, 87, 74,165, 18,241,241,241,152, 54,109, 90,
+110,110,110,238,192,191,121, 47,173, 15,224, 18, 0, 61,128,166, 0,212,101, 87, 10,134,150,133, 45,129, 82,154, 65, 41, 77,179,
+ 84,200,243,252,136,229,203,151, 75,116, 58, 29, 6, 12, 24,128,196,196, 68,164,164,164, 96,236,216,177, 9,162, 40, 14, 40,115,
+ 94,166,148,222,180,212, 89, 92, 92,252,233,148, 41, 83,116,201,201,201, 8, 8, 8, 64, 70, 70, 6,218,183,111,143, 14, 29, 58,
+ 64,173, 86, 35, 48, 48, 16,137,137,137,152, 60,121,178,190,164,164,196,146,186, 78, 52,153, 76,215, 15, 31, 62,172,236,216,177,
+ 99,237,121,243,230,121, 29, 62,124,216,167,164,164,164, 70,105,105,169, 95,106,106,170,255,238,221,187,171,173, 92,185, 50, 49,
+ 33, 33, 33,154, 82, 42,176, 10,237,197, 25,228, 21,240,219,203,180, 84, 61,171, 5,204, 82,184, 50, 17,121,252,245,137,214, 43,
+130,169,235,182,175,213,203,171,215,134,173, 95, 3,168,149, 74,168, 20,114,168,236, 28,160, 23, 69,252, 16,159, 86, 82, 12, 58,
+249,101, 3,150, 40,138, 88,177, 98,133,126,218,180,105,249,169,169,169, 95, 28, 59,118,172,209,217,179,103,203,189, 74,129,227,
+ 56, 20, 20, 20, 96,219,182,109,186, 53,107,214,220, 45, 45, 45, 13,151, 74,165,102,131,193,128, 77,155, 54,233, 23, 47, 94,124,
+ 79,175,215, 55,149, 74,165,198,138,156,126,123, 24,176,164, 82,169,169,180,180, 52,124,235,214,173,119,126,253,245, 87,157,141,
+141, 13, 36, 18,137, 89,175,215,135,174, 95,191,254,214,150, 45, 91,116, 54, 54, 54, 21,242,138,162,248,204, 62, 88,130, 32, 60,
+ 58,114,178,148,232,232,232, 53, 38,147,169,249,230,205,155,147,215,172, 89,163,183,177,177, 1, 0, 8,130, 16,177,110,221,186,
+228,239,191,255,190,180, 34, 29,220, 1,192,104, 52, 66, 16, 4,172, 91,183,174,116,203,150, 45,201,162, 40, 70, 60, 28,183,122,
+245,106,253,250,245,235,147, 77, 38, 83,243,232,232,232, 53, 22,110,107, 67, 74, 74, 10, 82, 83, 83,113,233,210, 37, 67,108,108,
+ 44,205,202,202, 2,165, 20, 38,137, 70, 66, 57,114, 75,164,116, 59, 21, 4, 25, 79,241, 17, 1, 57, 70,120,222,200,170,156,231,
+ 80, 4, 53, 8, 81,221, 76,212, 91, 43,101, 38,130,180,159, 1,153,253,163,128, 5,169, 61,220, 61, 60, 17,125,163,196, 10, 4,
+114,232, 77,229, 39,236, 18,170, 1, 33,234,171, 9,212, 90, 34, 83,145,244,244,244, 71, 63,218, 15, 3,145,151,183, 63, 46,220,
+ 42,209,128, 64, 1, 17, 22,223, 74, 68, 20,197,118, 86, 86, 86,146,135,206,135, 62,133, 66,129,154, 53,107,242, 38,147,169,181,
+197,203,158, 46,186, 66, 48,127,122,243,158,222,109,231, 9,157,207,136,241,171, 85, 42, 46, 23, 72, 88,140,122,181, 92, 49,226,
+227,250,242,177,171,178,234, 70, 95, 47,169, 9, 78,232,143,186,197, 78,150,170,189,189,189,195, 85, 42,213,142,157, 59,119,170,
+ 53, 26, 13,238,220,185,131,250,245,235, 99,218,180,105,106,149, 74,245,179,151,151, 87, 68, 69, 54,211,169, 88,122,191,164, 72,
+104,241,159, 21,137,233,151,226,133, 7,193,138,123, 16,174, 50, 11, 40,250,143,255, 37, 63,183, 72,223,253,204, 69,211,209, 10,
+212,155,151,242,243,243, 59,141, 31, 63, 62, 39, 43, 43,235,137,112,117,239,222, 61,116,235,214, 45, 55, 43, 43,171, 13,165,244,
+250,223,188,151,106,240,160,243,186,111, 89,139, 85, 32,165,212, 12,160,168,178,161,162,110,221,186, 13,170, 87,175,142,239,190,
+251, 14, 63,252,240, 67,222,130, 5, 11, 64, 41, 69,237,218,181,109, 42,235,188,120,241,226, 94,157, 78,247, 77,239,222,189,117,
+ 27, 55,110, 20,250,244,233,131,144,144, 16,104,181, 90,244,238,221, 27, 63,252,240,131,185, 87,175, 94,122,189, 94, 63,234,226,
+197,139,123, 45,220, 70,165, 5, 5, 5, 23,127,251,237,183,203,203,151, 47, 79, 26, 62,124,120,209,192,129, 3,101, 51,102,204,
+200,218,182,109,219,197,227,199,143,255,174,215,235,163, 41,165,165,172, 50,123,180,206,158,155, 65, 30, 35,179, 44,232, 24,158,
+122,205, 44,231, 61, 75,231,125,230,223, 22, 76,247, 92,202,189,226,102, 91, 28, 61,211,211,155, 44,156,186,250,251,225,189, 2,
+235,170,106,120,213,133, 80,148,135,203,105,105, 88,151,154, 95, 98, 20,233,138,109,119,232,177,202, 6, 44,158,231,241,251,239,
+191, 11,155, 54,109, 50, 2, 88,157,159,159, 63,229,218,181,107,197, 21,168,188,185,126,253,250, 21,231,228,228,236, 74, 77, 77,
+253, 34, 46, 46,206, 16, 17, 17,193,245,232,209,163, 56, 59, 59,251, 55, 66,200,231,103,207,158, 45,109,218,180, 41, 42,242, 96,
+107, 66, 8,100, 50, 25, 8, 33,136,138,138, 74,240,247,247, 15, 57,115,230,204,194, 91,183,110,125, 64, 41,229,162,163,163,147,
+180, 90,109,216,169, 83,167,230,199,198,198,126, 40,138, 34,103,169,151,227,184,255,105,169, 34,132, 60, 10,117, 21,189,138, 48,
+ 58, 58,250,186,191,191,191,246,204,153, 51, 43, 6, 14, 28,216, 10,128,250,204,153, 51, 55, 2, 3, 3,131,206,156, 57,179,226,
+227,143, 63,110, 93,214, 92,109,113,192,122,239,189,247, 74,242,243,243, 15, 20, 22, 22, 14,186,124,249,114,137, 86,171,197,123,
+239,189, 87,146,151,151,119, 48, 47, 47,111, 80, 69,182, 17,165,116,246,137, 19, 39,166, 81, 74, 37, 42,149,106,239,197,139, 23,
+ 91,149,148,148,168, 41,165, 32,194,221, 2,206, 16,246,147, 64, 36, 28,149,240, 29, 64, 80, 11, 60, 38,200,228,106,214,116,254,
+ 60, 20,230, 66, 16,146,218,181,165,131, 98,241,178,213,210,190,157,106, 42, 3,252,170, 63, 8, 87, 50,123, 68, 95,207,195,196,
+ 5,219,196,153, 3,157, 18, 32,210, 36, 24,233,173,114,157, 54,124, 33, 74,197,204,126,109,228,138, 89,255, 29, 94,163, 73,135,
+175, 21,117, 3, 66, 31, 5,161,216,107,231,176,104,214, 23,226,204, 1,118, 9, 16,145, 10, 3,110, 86,224, 59,218,115,214,172,
+ 89, 59,251,246,237,171,169, 87,175,222, 35,103,124,124, 60,230,204,153,163,211,235,245,221, 45,253, 86, 66,234, 87, 95, 48, 83,
+231,141, 7,178,125,190, 28,250,169, 90,197,229, 0,119,231, 61, 8, 47, 82, 91, 52,172,231,132, 9,159,187, 74, 71,206,221,237,
+119, 98,113,205, 34,136,242, 58, 0, 82, 45, 58,218,228,184,159,103,204,152,161, 86,169, 84,184,117,235, 22, 30,158, 54,210,106,
+181, 88,180,104,145,122,200,144, 33, 59, 35, 35, 35, 93,142, 28, 57, 98,174, 72,200, 10,247, 35, 45,254,179, 60,238,240,156, 97,
+118, 85,234,215,113, 70, 86, 33,208,127,226,238,188,236, 34,125,207,138,132,171,199, 67, 22, 33,164,211,176, 97,195,118,175, 93,
+187,214,161,110,221,186, 72, 76, 76, 68,183,110,221,114,178,178,178,218,190, 6,225, 10, 0,138, 1,184, 3,184,133, 7,125,145,
+238, 16, 66,228,120,137,199,179, 93,191,126,253,226,189,123,247, 92, 63,249,228, 19, 20, 20, 20,216,125,244,209, 71,184,115,231,
+ 14,110,222,188,121,233,101, 10, 26, 21, 21,181,170, 81,163, 70,167,215,172, 89, 51,146,227,184, 38,165,165,165,206, 0,196,253,
+251,247,167, 9,130,112, 92,167,211, 45, 57,119,238,220,173, 10,110, 35, 10, 32,187,108,184,197, 42,173, 87, 66,244,223, 52,111,
+165,177,104,103,223,120,135, 78,239,226, 77,142,252,112, 38,106,130,145,210, 6, 0, 32,227,200,149, 34, 66,167,108,191, 67, 79,
+188, 32, 76,188,240,105,219,241,241,241, 88,188,120,113, 73, 81, 81,209,101,179,217, 60,248,236,217,179,113, 22, 4,148, 39,156,
+ 18,137,228, 76, 98, 98,226,134,115,231,206,253,252,248,184,164,164,164, 77, 81, 81, 81,219, 31, 27,151,216,162, 69, 11, 15, 66,
+ 72,182, 37,229, 36,132,164,189,251,238,187, 60,207,243,201, 0,112,237,218, 53, 35,128,207, 67, 66, 66,126,183,178,178,234, 3,
+ 0, 49, 49, 49, 38, 0, 95,132,134,134, 30,208,104, 52,125, 45, 89,118, 66, 8,120,158,127,102, 11, 22,128, 23,118,114,127,209,
+250, 44, 11, 60, 61, 66, 66, 66,250,170,213,234,158, 0,112,249,242,229, 18, 0, 61, 67, 66, 66,250,168,213,234, 94,150, 58,213,
+106,245,217,244,244,244, 13,209,209,209,107,159, 26,183,209,146, 86,171,167,157,209,209,209,203, 1, 44,127,248,127, 88, 88, 88,
+208,237,219,183,247,138,162,168,146,100,223, 45,185,240, 91,187, 12,237,160,195, 53, 5,142,106, 64,232,120, 51, 71,114, 46, 44,
+104,164,175,200,190, 84, 25,254,177, 78, 71,238, 62,178,201, 34, 31,119,229,200,129,157, 28,200,236, 45,119,107, 12,237,233, 42,
+ 15,106, 96,143,179,215,114,241,213,180,141,226,172, 65,206,119,155,248, 91, 37, 64,196,114, 8,165,153,229, 58,173, 76,247,161,
+ 55, 45,168, 93, 85, 49,114,228,251, 34,153,176,126,186,151, 82, 57, 77, 22, 28, 22,137,235, 87,163, 48,123,210, 32,113,246, 32,
+187,187, 77,234, 90, 39,130,112,223, 66,208,103, 90,186,236,209,209,209,167, 67, 66, 66,222, 91,187,118,237,206, 97,195,134,105,
+ 2, 3, 3, 17, 31, 31,143, 41, 83,166,232, 74, 74, 74, 62,184,112,225,194, 49,139,151,157, 18, 10, 80,136, 2,132,111, 38,125,
+107,208, 25, 4,162, 51, 82,162, 55,128,211,149,138,164,200, 32, 18,147, 73, 36, 30,206,234, 7, 45, 26,220,255, 30,248, 60,175,
+156, 28,199,229, 15, 27, 54,204,234,185,185, 86,161, 40,174,204,118,127, 20,178, 22,199, 28, 30,213, 95, 86,101,201,166,115,185,
+ 89, 5,250, 94,229,133,171, 23, 57, 31,134,172,190,125,251,238,158, 59,119,174,195,232,209,163,179, 51, 50, 50,218,149, 23,174,
+254,194,125,254, 18, 30,220,219,234, 44,165,244, 56, 33, 68,131, 7,247, 32,186, 90, 89,167, 32, 8, 11, 62,253,244,211,214, 51,
+102,204,144, 76,156, 56, 17,113,113,113,152, 58,117,170, 96, 54,155,231,190,236,119,243,204,153, 51, 55, 0,244,255,215,212, 33,
+175,169,243, 77,131, 84,164, 85,231, 85,109, 0,173, 86, 91,210,166, 77, 27,221,209,163, 71,139,245,122,253,208,243,231,207,255,
+246,111,217,249, 90,182,108,249, 7,207,243, 94,132, 16, 80, 74, 83, 15, 28, 56, 16, 14, 0, 45, 90,180,248, 67, 34,145,120,149,
+ 29,241,167, 30, 58,116, 40,252, 77,254,226, 5, 7, 7, 55, 0, 48, 93,175,215,119,189,118,237, 90,113,195, 47,246, 57, 17, 29,
+103, 67,120,222, 24,179,226,173, 68, 86,233,148,227,220,231, 35,135, 90, 17, 4,208,145,151,239,148,212, 24,191, 54,219,171, 99,
+235,198,210,117,219,143,137,179, 62,125, 20,174, 22,128,234,206,161,121, 66,169,197, 78, 37, 23, 12, 94, 50,242,194,237,146,106,
+ 95,173,200,245,110,221,177, 63,255,235,207, 43,196,217,131, 28, 30,134,171,249, 16,138,162, 44,118, 62, 70, 72, 72, 72, 99,153,
+ 76,182,179,123,247,238,154, 45, 91,182,148, 27,174,158,233, 60,229, 95, 21,102, 58, 9,132,150,223, 7,140,114,119, 96,194, 44,
+188,117, 45,241,117,216,238,225,126,164,154,202, 74,249, 83,177,209,244,181, 37, 45, 87,150, 56, 9, 33,245,237,236,236, 86,229,
+229,229,245,182,164,229,234,175, 92,118, 66,136, 19, 0,109,217,129, 60, 1,112,157, 82,122,247, 37,157,225, 60,207,143,240,241,
+241, 9,136,139,139,187, 38, 8,194, 66, 74,233,113, 22, 92, 88,192, 98, 1,171,140,136,136,136,147,162, 40, 30,144, 74,165,115,
+142, 28, 57, 82,202,118, 62,230,100,206, 74, 56, 31, 11, 89,231,110, 21,123,205,218,146, 91,245,203, 46,182, 73,229,133,171,114,
+157,101, 33, 43,234, 70, 73,245,217, 91, 11,170,142,248,192, 42,169,188,112,101,233,178,135,132,132, 52,150,203,229, 43, 75, 74,
+ 74, 62, 47, 47, 92, 61,211, 25,235, 47, 67,182,217, 29,148,248,131,210,231, 63,106,135,240, 37, 32,220, 53,100,208, 12,116,185,
+102,100,251, 18,115, 50, 39, 11, 88,127, 53,127,203, 93,143,143, 31, 63,222,132,173,122, 6,227, 37,105, 27,103,192, 62,159,243,
+ 80, 43,230, 7,251,170, 62,253,121,178,186, 4,148, 36, 67,164,223,190, 40, 92, 89,224, 60, 7,165,121,126,104,109,213,231, 59,
+ 38,169, 75, 0,164, 3,220,210, 23,133, 43, 75,137,142,142, 62, 13,192,191,210, 2,191,107, 70, 0, 9, 0,185,135,201, 47,184,
+ 67,246, 68, 80,224, 79, 60,122,100, 48, 24,140,215, 49, 96, 49, 24,140, 87, 24,178, 98,253, 99,144, 41, 29, 3,130, 26,144,154,
+ 18, 81, 96, 74, 71,219, 4,195, 75, 58,163,145,201,223, 3, 69, 45, 72, 76,119, 81,160,127, 57,231, 43,135,210, 7, 33,138,193,
+ 96, 48, 88,192, 98, 48, 24,127, 6,126,215,140,240, 67, 50,128,228,215,218,201, 96, 48, 24,255, 34, 8,128,128,103, 31, 31, 90,
+126,110,149, 16, 18, 80,209, 15,182,160,243, 38,115, 50, 39,115, 50, 39,115, 50, 39,115,190, 97,206,242,220,111, 74,223,174,191,
+165,147, 59,115, 50, 39,115, 50, 39,115, 50, 39,115, 50,231,155, 12,123,152, 46,131,193, 96, 48, 24, 12, 6, 11, 88, 12, 6,131,
+193, 96, 48, 24, 44, 96, 49, 24, 12, 6,131,193, 96,176,128,197, 96, 48, 24, 12, 6,131,193, 96, 1,139,193, 96, 48, 24, 12, 6,
+227,181,225, 79,189,138,144,193, 96, 48, 24, 12, 6,227,223, 8, 7, 0,132, 16,150,178, 24, 12, 6,131,193, 96,252,229,188,169,
+ 25,132,157, 34,100, 48, 24, 12, 6,131,193, 96, 1,139,193, 96, 48, 24, 12, 6,131, 5, 44, 6,131,193, 96, 48, 24,140,127,103,
+192, 34,132, 80,214, 23,139,193, 96, 48, 24, 12,198, 95,205,155,152, 65,216, 85,132, 12, 6,131,193, 96, 48, 24,175, 24,118,138,
+144,193, 96, 48, 24, 12, 6,227,159, 20,176, 8, 33, 1,204,201,156,204,201,156,204,201,156,204,201,156, 44, 96, 49, 24, 12, 6,
+131,193, 96, 48, 88,192, 98, 48, 24, 12, 6,131,193, 96, 1,139,193, 96, 48, 24, 12, 6,131, 5, 44, 6,131,193, 96, 48, 24, 12,
+ 6, 11, 88, 12, 6,131,193, 96, 48, 24,127, 19, 4,192, 51,175, 4,160,148, 94,177, 88, 82,137,171, 9,202,243, 51, 39,115, 50,
+ 39,115, 50, 39,115, 50,231,155,231, 44,207, 93,145,252,241, 90, 7,172, 63,243, 70,163,132,144,128, 87,189,162,152,147, 57,153,
+147, 57,153,147, 57,153,243,205,115,190,105,176, 83,132, 12, 6,131,193, 96, 48, 24,175, 24,201,155,182, 64,254,254, 93,101,249,
+ 82,250,142,189,189,205, 72, 80,138,220,188,194,249,182, 38,242,203,181,107,219,140,127,214,103, 18, 66, 8, 0,208, 55,244,185,
+ 67,132, 16,101,189,122,245, 66, 0,224,234,213,171,209,148, 82,253,203,174, 47,103,255,206, 35,172,109, 84,189,204, 38,129,234,
+117,165,107,210,175,238, 88,242, 42,203,236,236,236,175, 49, 40, 53,211, 0,241,109, 16,112,148,146, 35,146, 34, 97, 84,110,110,
+ 76,129,165, 14,247,102,163, 70,241, 50, 73, 63,193,104,154,157,114,108,206,106,247,200,201,142,130,185,120,150, 84, 33,143, 16,
+ 13,198, 57, 41,199,231,252,192,170,144,138, 99,227,223,198, 94, 37,179,230,211, 46,108,203, 98,107,131,193, 96,176,128, 85, 70,
+181,128, 30,118,165,196, 56,150,151,240,239, 81, 42, 90,165, 93,216,230,252, 58, 44,136, 75,189,247,106,218,217, 91, 15,173,215,
+200,175, 75,143, 15,218, 40, 3,235,249,202, 75,141,102,252,178,231,216,183, 91,127,217, 63,207,183,217,199, 59,243,114, 11,151,
+254, 31,123,215, 29, 31, 69,181,182,159, 51,179,125, 55,157,100, 55,217, 77, 0, 9, 36, 64, 18, 32, 84, 19, 66,145,222,155,160,
+162,136,160, 2, 74, 19,229, 74, 71,244,162,160,116, 68, 64,138,210, 81,144, 94, 2,210,123, 73,168, 9, 4, 8,164,215, 77, 79,
+182,100,203,204,249,254, 72,194,141, 24,200, 6,240,126,247,122,231,209,253,177, 51, 57,231,217,119, 78,125,230, 61, 45, 59,102,
+207,163,151, 44, 62,100, 51, 70, 4,116,243,112,146, 73, 9, 33,187, 41,165,246,170,194,105,154,191,125,130,128,188, 82, 22,135,
+ 1, 97, 0, 2,154,145,118,117,115,120, 21,156, 74, 0,222, 0,146,158,198, 87, 21, 20,218, 96, 95, 9, 35,253,130, 49,226,179,
+154, 8,137,103, 60,155,186,126,253,250,225, 1, 1, 1,234,113,227,198,137, 1, 96,241,226,197,141, 26, 52,104,144, 29, 31, 31,
+127,129, 82,154,253, 92,121, 21,212,127,234,172, 41, 31,205,236,215, 61, 2,249, 37, 54,124,191,254,215,121,154,144,129,108,214,
+237,221, 75, 94, 74,158,104, 91, 40,220,157,156,174,140,255,244, 75, 93,207,142, 45, 68, 5, 70, 59,118, 70, 94,124,107,239,207,
+243, 58,184,187,183,104,237, 72,218,232,194,255,241,170,239, 43,190,179, 7,246,239,139,239, 87,173, 27,167,141,152,154, 35,150,
+137, 86,133,133,181,119,243,241,173,131, 93, 59,183, 78, 0, 32, 8,172,154,149, 39,151,166, 1,110, 65, 3,154,133,238, 60,119,
+223,224,228, 21, 50, 96, 23, 88, 44,213,223,216,115,211, 81, 14,223, 70,225, 23, 68, 12,235,195,241, 92, 90,202,221, 11, 17,127,
+133,157, 42, 77,227, 78, 32, 88, 79, 40, 21, 83,208,239, 89,158,236, 42,206,137,123,248,162, 47, 80, 46,190, 65,238, 28,111,237,
+ 38,101,148,205,172,188,233,154, 72,162, 56, 90,144,120,163,240, 37,165, 45,171,212, 4,190, 35,151, 41, 63,169, 31,216,168, 65,
+ 66,194,131, 7,134,226,194,229,198,172,251, 27, 41,165,124, 77,184,252, 59, 79,123,131, 3, 63,141,183, 91, 24, 17, 37,223, 62,
+ 58,179,100,171, 80,122, 5, 8,248,139, 5,150, 87,208, 16, 21, 17,209,171,237,195, 95,245,152, 62,118,160,116,233,150, 51,240,
+110,246, 70,124,230,141, 95,235,255,127, 62,132, 79,232,160,218,132,224,214,164,209, 67,241,254, 27, 93, 73, 78,177, 29, 69, 38,
+ 14, 68, 12, 12,121,189,183,114,208,128, 30,202,111,151,173,255,224, 96,228,201, 15,124, 66, 7, 53,206,184,190, 43,185, 58, 78,
+239, 22,111, 31, 1, 72, 64,197, 53,229,236,114,194,138,204, 0,202,197, 17, 3,149,155,250,236,236,145,129,251,231,188, 31, 60,
+103, 67,100,210, 74, 0,181, 0,100, 85,217, 0, 50, 34,221,166, 53,139,189,116,181,164, 96, 24, 6, 5, 6, 27,222, 28, 57,137,
+171,162,161, 84,173,158, 28,218,255,189,222,117,223,146,117,216, 53,147, 16,114,203,145, 6, 82,165,105, 24, 44,149,187, 28,240,
+111,214,197, 45,225,230,177, 32, 39, 77,163, 15, 12,114,243, 67,154,152, 88, 90,211,134, 90,165, 82, 5,184,184,184,180,236,209,
+163,135, 98,202,148, 41,226,246,237,219, 63,254,251,168, 81,163,196,103,206,156,209,125,251,237,183, 3,117, 58,157,169,168,168,
+ 40,202, 96, 48,220,167,148,114,142,254,134,187,187,251,123,131,122,183, 71,159,183,198,130,130,193,228,169,179,112,248, 80,228,
+112, 0, 47, 69, 96,185,176,204,204, 81, 19,103,233,218,135, 53, 23, 45,216,157, 12, 59, 79,209, 49,184,169,168,244,141, 79,189,
+143,253,186,228, 91, 0, 99,170,227,224, 36,204, 63,123,119,123, 13,224, 44,176,217,173, 94,110,181,220, 54, 15, 30, 56, 64,108,
+231, 40,142, 29, 59, 14,222,198,255,228,136, 45,222,205,135,158, 3, 97,116, 21,101,134, 16,128, 33, 0, 1, 1,165,124, 90,202,
+149,205, 47, 44, 18, 8, 33,172, 66,211,176, 59, 67,249, 97, 0,192, 19,102,179, 41, 43,238, 72, 77,242, 4, 0, 52, 77, 95, 79,
+164, 60,247,167, 23, 38,150, 21,235, 51,110,236,168,251, 2,246,121,246, 8,215,180, 56,253, 67,199, 46, 97,193,238, 33, 63,254,
+ 94,234,210,162,231,120,164, 21, 96,240,222,221,187, 6,123,133, 12, 56,195,128, 46,206,186,189,247,120,117, 92,114,153, 76,189,
+127,255,126,175, 30, 61,122,185,169, 67, 6,236,225, 9, 50, 25,138, 76,194, 51,153,132,216, 51,237, 12,205, 4, 75,178,114,253,
+165,217,190,177,233,167, 89,134,213,217,121, 46, 35,245,238,133,112,199, 13,198,250,200, 99,231, 60,205, 54,138,239,126,216, 58,
+203, 88,152, 53, 43,241,142,103,146, 82,211,112,138, 49, 43,238, 96, 77,158, 93,225,219, 84, 43,226,205, 61,124,180,245, 94, 31,
+ 63,241,243,214, 93, 59,181, 23,215,243,211,144, 71, 41, 89,244,247, 19,103,172,129,173,123, 94,202, 72, 75,216,197,219, 68,135,
+ 13,250,216,172,231, 75,223,142, 34, 39,117,163,159,251,190,241,254,192,126,131,134,194,205,197, 9, 22,107,105,131,147,191, 31,
+ 90,177,118,197,252, 48, 66,200,168,154,136, 67,142,218,167,173,157, 55,182, 62,192, 99,248,132,185, 51, 8, 33,219,107, 42,210,
+ 4, 8, 16, 80, 67,129, 69, 88,251,236,176, 54,175,122,124, 50,110,164,116,204,242, 83, 72,190,114,216,244,178,196,149, 74, 29,
+172, 22, 73, 68,239, 50, 12,235, 70,192,200,121,142, 75, 41, 36,250,213, 52, 53,181,218,225,168,140,235,187,146,189, 67,251,183,
+ 90,246,227, 47,179,163,110,196,182, 31, 51,124,160,202, 87,167,101,108,118,138, 11, 81,183,184, 21,107,182, 21,229,229, 23, 93,
+ 32, 34,250,149, 35,226, 10, 0, 40,133,255,162,133,223,121,233,106,201, 80,104,180, 99,236,167,179,240,237,215, 95, 56,213, 86,
+203, 97,182,240, 88, 25,153,170, 15,202, 95, 24, 61,103, 96,240,156,125,231, 51,214,143,156, 27,117, 19,128,241,153, 2,213, 85,
+138,241,171,239, 65, 33, 23,193, 85, 41, 1, 75,152, 63,137,171, 85,159,135,246, 27,213,175,222,244,111, 54,222,221, 0, 64, 12,
+ 64, 10,224,153,105,224,228, 29,212, 81,233, 82,107, 75,207, 17, 95,185, 42, 93, 53,120,103,112,207,160,179, 71,127,251, 61, 37,
+ 37, 17,126,141, 35,204,118, 59,127,162,184, 40,255,123, 67, 86, 92, 76,117,207, 93,183,110,221,161,189,123,247, 86,125,254,249,
+231, 98,157, 78,135, 95,247,157,208,117,126,125, 98,215,180,172, 92,111, 0,208,105,106,101,126, 56,172,239,239,135, 15, 31, 78,
+ 75, 75, 75,115,153, 55,111, 94,196,174, 93,187,154, 2,216,230,104, 94, 83,202,195,206, 81,112, 60, 5, 79,121,228, 22, 91,158,
+ 75, 84, 60, 85, 64, 16,244,233,222,161,165,104,233,254, 20,220, 79, 47,203, 18,153,152, 69,139, 22,173, 68,199,119,145,246,213,
+138,162,118, 83,123, 53, 13, 14,124,213, 87,171,198,165,168,155,144,138,197,110,111, 13,234, 11,185, 66,129,109,191,238,226,179,
+178,210,199,101,158, 93,184,209, 49, 67, 25,221,154,149, 75,188,106, 57, 75,192, 18, 2, 86,196,128,101,128, 18, 51,135,119, 63,
+152,240, 66,117, 70,161, 13,246,101,169,109,184,179,182,241,240, 65,131,222,244, 25,250,214, 16,202,178, 12,118,236, 62,208,231,
+151,109, 27, 50,157,124, 2, 55,112, 68,188,209,148, 30,147,234, 80,190,240,156,215,254,157, 27, 80,203, 69, 2,134, 0,185,197,
+ 28, 18,178, 76,152, 48,118,244,115,121,169, 9, 33,110, 31,247,127,165,251,205, 77,157, 59, 4,214,118,174,127,243, 65,193,221,
+ 17,255,140,254,225,104,106,195, 87,231, 44,104, 4,163,185, 20, 99, 62,157,137,156,244,196,246, 71, 14,237,107, 95,171, 97,247,
+251,196, 82,244, 69, 78,194,165, 3, 79,227, 52,155,205, 5, 61,123,244,118,241,246, 86, 43,214,175, 91,211, 53,175,208,132,188,
+130, 98,232,243,138,144,147,155,143,140,172, 28,164,165,103, 32, 53, 37,141,207, 99,245,136,140, 60,196,244,237,219,151,171,169,
+237, 38, 43,143, 27,143, 74, 80, 39,176, 37, 60,212,190,104,213,109, 68,157, 27,167,183,255,234,228,221,120, 97, 73,230,157, 47,
+ 28,225,112, 86, 7,126,247,230,219, 35, 62,124,115,240, 64, 81,195,250,190, 76,166,190,128,158,191, 20,157,191,116,241,178, 59,
+109, 59,116,108,220,183,103, 23,247,209,239, 13,233, 16, 23,159,218,110,219,206, 61,139,156,188, 26,110, 46,209,199, 77,168,105,
+ 61, 80,106, 26,174,127,173,223,136,129, 33,109,186, 34, 62, 62, 30, 15, 98,163,208,177,115, 15,244,232, 61, 8,150, 82,243,208,
+141,235,150, 70, 3,248,177,202,248, 45, 90,136,221, 10,220, 20,127,104,139,181,129, 34,128,130, 82, 10,187,169, 80,162,210, 52,
+243,112,175,215,197, 10, 0, 5,110, 5, 38, 26, 29,109, 19,186, 78, 1, 2, 94,178,192, 98, 88,105,207, 73, 35,123, 73,167,174,
+186,136,228, 43,191,152, 50,175,255,234, 89,241, 55,223, 22,111,197,166, 70,111, 15,250, 99, 71, 90,253, 10, 3, 66, 90,136,221,
+116,248, 84,237,227, 51,250,157,247,199,179,117,124, 53, 76,137,217,110,207, 74, 79,165,145,251,183,125,236, 90,187,217,119,133,
+201, 55,214, 62,141,147,212,239, 41,165,241,135, 45,153,215,247,222, 5,240,166, 58,120,168,250,252,149,219,147,221,221, 92,134,
+216, 57, 59,138,139,141, 59, 10, 10,108, 11,179, 99,182,101, 87,106,148, 72,229, 55,186,167,217,233,238, 36,193,167,235,239,195,
+108,225, 64, 41,133,151,155, 20,243,127, 75,130,136, 37,250,224,130,133,139,191, 26,104, 29,245,235,121,203,142, 25,187,253,218,
+ 2, 23,214, 83, 74, 75,158,106, 39, 0,150, 1, 84, 10, 49, 84,114, 17,156, 21, 98,148,205,220,250,151,184,250,225,179,166,253,
+ 70,247,171, 55, 99,222,150,184,159,103,174,185,115, 1, 64,124,229,249, 78, 85,217,233,226, 19,242,182,187,151,110, 97,255, 81,
+115,157, 19,243, 25,136,237,128,167,182, 30,249, 98,206, 92, 23,185,148,129, 66, 76, 93,110,197, 61,122,123,236,216, 79,122, 43,
+181,141,122, 27,211,239, 94,127, 86, 30,153, 76, 38,217,176, 97,195,196,102,179,217,250,254,164,249,237, 18, 83,178,186,125,253,
+197,100, 89,109,157, 26, 28, 79,113,251, 94, 74,253, 57, 95, 47,242, 61,248,251,165,200, 33,221,155, 28,245,241,241,113, 51,153,
+ 76,124, 77,242,189,176,176,104,235,150,221,199,166, 44, 91,188, 0,137, 89, 6,108,217,182, 19, 28,199,111,124,182, 40,251, 35,
+231,156, 57,115,188, 67, 66, 66, 36, 49, 49, 49, 89,148, 82,211, 19,161, 93,244, 69, 86,216, 56, 30, 4,128,167,155, 12,110, 78,
+ 82,176, 12, 1, 67, 72,181,249, 14,194,143,232,223,163, 29,164, 98, 22, 9,137,201,104,213,188, 41,188,106,185, 35,238,193, 35,
+100,102,101,101, 49,132,121,175, 78,183,217,243,109,165,230,153,233,103, 22,172,127,150,157,132, 1, 60,157, 37,248,102,103, 34,
+ 20, 82, 17, 20, 82, 22, 10, 89,217,191, 4,196, 65, 65,250,103, 59, 85,222, 13, 63,107, 26,220,108,206, 7, 31,188,207,180, 13,
+111, 67, 89, 86,132,172, 66, 27, 97, 8,240,201,216, 49,152,240,241, 40, 77, 98, 82,234,180,149,171,215, 76,113,210, 52,154, 95,
+146,117,247,107, 71,242,168,150,179, 4,179,183, 36, 64, 33, 43,179, 51,244, 21, 39,135,219,135, 39, 57,181, 77,123, 29, 58,153,
+ 45, 14, 44, 62,104,190,242,224,254,245,111,175,222, 74,138,162,148,230,171, 67, 6,192, 98,167, 40, 49,217, 16,147,108, 7,111,
+ 22, 99, 64,143, 86,104,234,230, 25,176,108,227,201,117,132, 16, 77, 69,253,124,146, 51, 53,238, 98, 75,247, 22, 67, 92,168, 65,
+121,107,193,238, 68,207, 58, 26, 23,120,187, 59,195, 75, 91, 11,141, 26, 5,194, 93, 37,134,139,130,133, 66,202, 50, 29,122, 12,
+ 65,247,238, 61, 77, 28,111,207,174, 73,249, 36,148,140, 28,212,171,253, 70, 2, 72, 24, 86,146,238, 83,167,129, 95,235, 30, 31,
+200, 91,118, 29, 1,155,197,252,153,147,119,208,233,146,204,216, 83,213,113,186,121,105,223, 29,249,254, 40, 73, 61,141, 12, 39,
+ 78, 95,180, 79,159, 49,227,118, 97, 73,254,162,146,140, 7,177,199, 79, 28,245,118,117,247,152, 49,125,214,220,176, 78,225,161,
+108,151,222,111, 73, 34, 35,143, 14, 6, 48,161, 58, 59, 9, 33,140, 66,221, 96,100,131, 70, 77, 39,125, 52,235,199, 58,105,185,
+ 22,184,107, 3,112,235,122, 20, 34,119,124,127,163,180,164,112,217,209,131,191, 77,250,226,155,229, 77,122,247,127, 19, 7,246,
+108,159, 64, 8, 89, 67,203,240,152,211,163, 65,135, 46, 77,234,132,172,247,110,168,246,168,204,207, 83, 22,115,230, 47,135,185,
+ 36, 31,117,181,110,222,206,141,235, 39, 81,134,128,242,128, 94,159,105,241, 12,236, 48, 40,231,222,233, 83, 53,105,231,107, 10,
+129,243,127,147,179, 26,180, 2,224, 5, 64, 15,224,234, 19,215, 40,255,142, 42,174,115,202,187,224, 90, 0, 44,229, 78,139, 10,
+ 84, 92, 63,237,126, 69,252, 88, 0,141,203, 57, 57, 0, 87, 0,228, 87, 43,176,202,181, 6,169, 84,121,255,112,253,199, 55, 92,
+155,206, 75,227, 13,142, 38,253,161,107,168,211,122,104,206,196, 81, 67, 20, 62,161,131,245, 25,215,119, 58,252,182,171,240, 13,
+208,186,213,118, 57, 52,238,147,207, 93, 63,126,175,175,211,221, 20, 99,113,108,146,177, 8, 10, 10,119,191, 90,162,144,238, 94,
+ 92,246,175, 11,103,184,234,154, 20, 20,166,221,250,173, 42, 14,181,139, 71,172,239,171,239,231, 91,140,134, 47,115, 98,118, 68,
+150,207, 11,250,135,111,216,144,217, 0,144,122,113,199, 99,129,162, 14, 29,248,170, 76,230, 54, 71,219,242,157, 90, 0,154, 87,
+103, 95, 94,137, 21, 28, 87,214, 31, 51, 12,129,193,204, 65, 46, 97,114, 2,115, 23, 60, 22, 87,231,233,135,239,217,232,118, 73,
+101,113, 85,117,163, 8,228, 21,219,160,146,139,224, 36, 23,193, 73, 33, 2, 83,174,176, 8, 33,170,239, 39, 53,237,251,209,192,
+250, 51,230,111,190,183, 97,198,234,216, 11, 0,238, 81, 74, 11,158,197,233,162,105,212, 70,234,234,185,248,131,207,151,168,206,
+221, 51, 64,235, 33, 69, 72, 29, 23,184, 42,165, 72,203, 43,155,211,159,158,107,134,217,234,140, 1, 31,206,113, 57,188, 99,197,
+ 25,119,223,166, 27,243, 83,111,142,171,238,217,119, 29, 60,243,202,163,228,204,110,191,254,180, 80,150,103, 4,146,242,120,228,
+ 21, 91, 96, 97,221, 49,243,139,175,100, 83,167, 78,233,129,210,220,180, 6,117, 60, 50,106, 92, 49,137,113,209,142,221, 71,255,
+ 17,210,162, 61,115,234,228, 73,220,140, 58,187, 67,127,123, 79,141,134, 7,107,215,174,109, 95,190,124,185,235,210,165, 75, 59,
+184,187,187,167,228,231,231,199,150,167,165,175, 87,157,144,220,125,135, 78,186,180,105, 26, 38, 82,200,196,112,119,146,192,223,
+ 91,137, 59,215, 78, 89, 24,144,223, 29,176, 80,231,163,174, 5,142, 2,250,156, 60,116,239, 20, 14,169,152, 69, 70, 70, 38, 2,
+ 3,234,249,116,239,244,154, 15, 15,130,149,107,215,126, 12, 96,253, 51,243, 29, 12, 88,150, 64, 41, 19,225,198,209, 53,133,165,
+198, 34, 43, 41, 31, 34,228, 41,151,246,220, 77, 13, 79,222,137,220,187,153,201, 40,176,227,126,102, 41, 73,205, 53,128, 1,133,
+151,171, 8, 60, 39, 66, 81, 65, 54,217,186,109, 43,174, 71, 93, 98, 8, 97,222, 3,240,181, 67, 47, 81, 12, 32,151,178,144, 75,
+ 89, 40, 36, 44, 74, 74,203,180,179, 58,100,192,102, 10, 20,138, 88, 81, 73,198,141,157,211, 29,170,223, 74,183, 38,155,214, 44,
+192,209,179,209,237, 78,197,111,108,174, 9,110,178,170,118,200,219, 75, 1,192,106,231, 97, 44, 41,132,202,150,132,118,117,115,
+ 80, 75,201,225, 94,190, 22, 55, 83, 69,170,234,134,179,242,163,119, 20,105,130,250, 77,184,113,238,208,118, 81,199, 65, 40, 48,
+112, 72,146, 89,160,148,137,202, 63, 44,238,220,188,140,204, 34,254,156,179, 69,217, 47, 41,254,112,141, 92,164, 37, 89,177, 39,
+ 1,248,254,203, 67, 92,223, 51, 99,229,103,107,135, 76,252,190, 75,171,238,239,147,251, 87,127,255, 28,192,169,106, 61, 88,110,
+ 30,162,135, 89, 28, 18, 18, 31,241,173,219,132,137, 46,157, 59, 17,250,251,201, 11, 27, 55,111,217, 82,218,235,245,247,228,157,
+219, 54, 99, 83,114, 45, 88,190,235, 14,141,201,160, 68,170,170, 37,118,192, 99,197,120,213,111,245,211,134, 13, 91, 7, 7, 5,
+248, 33,171,192,134,244,124, 43,206, 68, 63,192,198, 53, 83, 11, 11,178, 31,142,132,165,196,192,131, 43, 60,126,116,223,222, 49,
+227,167, 34, 40, 36,180, 78, 73,186,193, 25,192, 31,231, 30,242,252,136,175,191,254,206, 67, 84, 73,147,169, 0, 0, 32, 0, 73,
+ 68, 65, 84,165, 82,253,233,119,244, 89,233, 48,148, 24, 32, 85,186, 64,233, 82, 11,118, 59, 7, 27, 71, 81, 92, 92, 44,157, 54,
+254,157, 15, 29,121,126, 1, 2,106,224,137,117, 68,135,120, 17, 66, 14, 80, 74,251, 0,232, 2, 64, 90,233, 26,132,144, 3,229,
+194,239, 15,215, 83,167, 78,157, 62,111,222,188,152,138,176, 21,247, 43,194, 62,235,126,165,248,181,166, 77,155, 22, 50,127,254,
+252,111,194,194,194,182, 95,184,112,225,145, 67, 2,171,242,195,144, 74,111,247,127, 26, 54,105,214,183, 37,120, 17,235,235,229,
+132, 87,234,250,193, 77, 57, 92,161,109,254,166, 94, 36, 98,153,159,151, 78,147, 39, 22, 72, 32, 98, 68,198,154,136, 43, 25,235,
+114,116,213,218,141, 78,109,154,188, 34, 91,180, 59, 53, 33, 53,175,212,194,219,109,140,217, 88, 34,201,207,188, 47, 46,202, 78,
+116,118,241,110,200,154,139,244, 51, 1, 84, 41,176,164, 82, 41,179,108,193,151, 65,167, 78,159,223,176,223,201,165,208, 39,244,
+157,197,172,204,186,177, 66, 88, 17,242, 37,163,105,118,111,160, 84,174,156,210,176, 73, 7, 31,109, 64,107,215,203,135, 55,196,
+ 59, 32,207,217, 41,211,231, 60, 22, 87, 54, 83, 30,190, 91,179,191,184,179,199,233, 69, 21,226,106,155,126,232,219,221,219, 7,
+104, 14,239,151,228, 85, 91,128, 96, 79, 27,246,193, 39, 18,194, 0, 12, 72,217, 60, 46,202,103, 19, 66,148,203, 63,105,214,103,
+236,235,254, 51,191,221,114,111,227,244,213, 49, 21,226,170,218,204, 43,102, 21,183, 93, 74, 77, 89,137,241,183,235,140,239,213,
+ 86, 84,199,219, 21, 10,169, 8, 5, 6, 59, 10,140, 28, 82,245,102, 60,204, 52,224,246, 67, 61, 56, 83, 17,222, 25,251, 79,230,
+231,239,198,119,115, 36,127, 14,158,136,238,250,221, 55,211,101,121, 6, 32,167,132, 67,122,158, 25,105, 57, 38,164,230,152,160,
+144, 0, 97, 93,223,146,157, 59,244,115,247, 6,117, 60,126,170,105,101,202,186,117,212,168, 14, 25,112, 57, 45, 67, 31, 86, 63,
+ 32, 8,204,161,189,141,106, 53, 29,162,205,189,185, 35,221, 81,142,195,135, 15,231,248,250,250,170, 87,173, 90,165, 95,188,120,
+113, 72,237,218,181, 27,165,164,164,236,243,244,244, 28,254,253,130, 89,199,190, 88,240,147,167,197, 90,234, 18, 28, 26,206,138,
+196, 4, 49, 87,142,149, 30,217,245, 99, 6, 45, 50,206,172,142, 91, 42,147,213,146,203,197,176,217,120,176, 44, 11, 95, 31, 53,
+108, 28, 69,137,193,128,129,189,187, 33,230,238,125,156,191, 20,101,231,108,246,229,213, 55, 28,128,136, 97,160,148,137, 80,106,
+ 44,178, 38, 93,218, 88,247, 37,181, 73,148,167, 20,209, 15,141, 48,150,218, 97,181,241,240,215, 72,145,151,157,140,117,223,111,
+196,205,107, 87,209,174,115, 31, 44, 88,185, 5,227, 63, 28,226,240,170, 79,134,144,114,113, 37,130, 92,202,162,212, 86,214, 36,
+ 44,155, 55,149, 13, 14,106,140,142,125,134, 57,236,210,114,118, 82,160,216,100,133,202,205, 7,209,199, 55, 42, 15, 30,191, 50,
+249,187,229, 63,125, 82, 90, 76,145,122,239, 34,194,220,115, 81,223,211,130, 43,201,206, 56,154, 92, 7, 1,254,245,192,136,246,
+ 56, 86,134, 98,247,237, 87, 55, 27,184,175,168,113,104, 63,119,255, 64,200, 36, 44,100, 18, 6, 82, 9,131,135,247, 98,240,203,
+230, 13,119,237,114,229,144,248, 91,123, 44, 47,154,208, 37,153,241, 57,114, 77,224,164, 7,215,142,198,182,237,247, 49,220,188,
+235, 52,169, 73,252,121,115,103,148,114,118,155,237,237,225, 99,148,125,123,190, 38, 10,107, 27,174,138,186,151,143,111,127, 62,
+201,157,139,220,156, 33,145,185, 42,116,225,163, 61, 28, 17, 87, 30,117, 66,215,110,218,252,235,224,122,181,189,241,251,149, 4,
+ 92,139, 47,128,139,179, 43, 68, 42, 31, 4,118, 24,225,122, 59,114,233, 0, 99, 78,201, 86,177, 88,254, 94,203, 54, 17,160,148,
+226,126,108,108,126, 65,129,211,159,218,102, 70,196,172,157, 53,243, 31,221,213, 94,154,202,111,238,240,175, 31,128, 94,253, 6,
+227,248,169, 29,120, 20,127, 31, 60,165,224, 41, 64, 41, 69,110,142, 62, 15, 12,243,179, 32, 9, 4,252, 85, 34,235, 89, 58,164,
+ 66, 56, 61, 41,136,158, 20, 90, 21,223, 43,194,205,155, 55,175,207, 19,222,183, 62, 79,241,202,253, 41, 92, 69,252,249,243,231,
+127, 83,233,239, 14,105, 29, 81, 57, 9,121,214,195,169,155,245, 15,147,138,157,246,253,176,240, 19, 38,187,208, 6,133,148,133,
+170,118, 61, 52, 24,249,137,242,237,118, 94, 72, 47,117,199,254, 3, 63, 21,219,168,253,176,163,226, 74,202, 56, 29, 89,180,226,
+ 39, 73,253,186, 90, 50,103, 91, 98,188,217, 86, 54, 77,194, 82,106, 22, 37,221,140, 84,166,198, 30, 55,195,110,219,196, 74,101,
+ 45, 64,121,245,179,248,234,120,187, 33,188, 67, 23,101,135, 14, 29,148, 71, 79,158,159,123,240,224,193,143, 81,190, 67,189, 79,
+139,132,227, 45,218,246, 10,210,250, 55, 81, 22, 91, 8,164, 98,198,209,220,230,190,251,102, 14,106,171,229, 48, 89,120,252,115,
+245,161,226, 14, 78,191,127, 83, 89, 92,105,124, 27,248, 74,100,170, 63, 12,245, 61, 13,105, 87,183,118,170,162,160, 40,151,124,
+ 18,210,119,220, 16,255,153,223,109,185,183,105,218,170,152,243, 0,226, 28, 17, 87, 0, 64,211,163, 77,174,181, 67, 58,236,219,
+176,112,230,161,109,203, 58, 50,160, 30,141, 2, 3, 68, 93,187,118,147, 53,107, 21, 46,211, 23, 82,220, 73,208,195, 92,146,143,
+206, 97,141, 16,185,123, 51,151,149,153,226,208, 28, 15,125,126,145,119, 29,157, 6, 9, 57, 60,146,245,101,194, 42, 85,111, 68,
+ 90,174, 9,249, 37, 22,180,170,167,129,193, 96,241,126,238,202, 68,201,129,139, 23, 47,134,189,218,190, 43, 94,127,123,116,208,
+129, 93,155,175,104,130, 7,125,150, 21,179,235, 87, 71,226,239,216,177,131,211,106,181,241, 89, 89, 89, 17, 11, 22, 44,208, 7,
+ 6, 6,250,205,153, 51,103,186, 86,171,245, 24,242,250,235, 41,125,122,247,222,242,209,167,179, 59,172,252,242,167, 87,192,176,
+ 89,224,237,135,244, 38,110, 46,213,199,154,170,227,118, 82,202, 60,196, 44, 3,134, 16,184, 57,171, 32,147,138,192,218,121,240,
+ 28, 7, 55, 23, 37, 98, 98,239, 34,251,206,249,209, 5,143,142,236, 0, 22, 86, 43, 88, 88, 22, 80,201, 69,143,203,137,186,233,
+235,137,168, 98, 50, 57, 0, 16,150,213,103,221,248,173,174, 3, 9,200,219, 57, 10,179,149, 67,169,149,131,152,165, 40, 46,204,
+198, 23,211, 38,225,181, 30, 3, 49,119,216,120, 20,154, 89, 92, 79,182,192,110,179, 17, 71,243, 37, 45,207,130,158,205, 61,144,
+ 83,108, 71,190,129,131, 68, 84, 86, 95, 14, 94,203, 69,188,161,102, 11,222,120,158,194,211,195, 21,202, 92,160,215,167,187,241,
+ 90,115, 95,156,220,187, 70,116,254,202, 45,252,243,219,239,161,238,255, 42,214,223,168, 15,153,139, 31,100,174, 50,216,104,205,
+182,229,163, 54,209,167,215, 79,239,238, 84,223,127,138, 74, 42,150,148,121, 25, 83, 30, 97,243,134, 31,211,236, 98,244,205,187,
+188,165,248,101, 53,254, 98,134,213,185,122,120, 65, 38,102, 64,237, 22, 67, 77,227,103,166,103, 53, 89, 48,119,202,240,179,151,
+ 6, 78,111,221,115,140,244,212,238,101,165,177, 87, 14,140, 53,100, 56,237,242,143,240,140, 2,224, 81, 77,167, 66, 92,125, 66,
+126, 92,189,126,203,155, 62,222,106,236, 62,126, 19, 27,214,253, 0, 93,112,119,196, 95, 59, 10,191, 22,253,225, 84,175, 19,196,
+206, 59, 70,170, 24,113,240,168,137, 51,250, 55,111, 25,142,139,231, 78, 32, 91,159,186,142,210,184, 63,173, 70,206,185,119,250,
+ 20,105,209, 66,237,246, 48,237,241, 28, 44,134,181,250,240, 60,162, 59, 91, 41, 30,197,223,199,205,107,151, 90,240,156,228,177,
+151,186,192,173,192, 68, 31, 8,115,176, 4,188,124, 84,167, 67,170,243, 58,213, 80,204, 29,168, 74,100, 61,121,159, 16,114, 96,
+234,212,169,211, 1,208,169, 83,167, 78,175,184,158, 55,111,158, 9, 64,181, 14, 1, 81,229,135,171, 42,128,186, 89,255, 48,169,
+ 72,185,111,195,242, 25,138,109, 87, 56, 44, 56, 28,141,208, 64, 13,196, 98, 22, 42,185, 55,142,199, 20,226,194,153,125, 37,209,
+ 81,151,205,172,152,155,237,136,184,146, 16,197,161,249, 75, 87, 21, 4, 5,248, 73, 87, 28,202,188, 97,182,241,132, 82, 34, 38,
+148,176,148,242, 46,105,177, 39, 26, 23,145,156, 48,154,230,200, 10, 56,194, 91,237, 20,137,217, 22, 16, 2,180,141,232, 32, 63,
+122,244,119,197,191, 58, 44,177,123,237,134, 45,148,119,146, 13,144,136, 24,168,221,164,112,116, 57,141,151,155, 20,243,118, 38,
+ 66, 44, 98,244, 29,156,126, 95, 92, 89, 92,121,251, 54,240,117,118,113, 1,207, 19, 16, 66,158, 39,131,149,139, 39,132,244,153,
+ 56, 36, 96,230,226,109, 15, 54, 79, 93, 25,115,206, 81,207, 85,101, 20, 38,223, 46, 0,240, 89,197,181,107,237, 16,183,171, 81,
+151,187,184,186,171, 23,180,127, 99,102,173,146, 66, 11,186,132,151,137,171,155,103,127,125,203,152,121, 55,210, 81,110,171,157,
+ 71, 82,150, 17, 9,153,198,199,222,171,212, 28, 19, 20, 82, 22,102, 11,247, 66,149,201,169,180,244,199,200, 67,123,123,218, 56,
+ 68, 52,110,209, 1,175,143,156,226,118,108,239,134,159, 52, 65,253,204, 89,177,251,246, 59,194,145,158,158,110,242,240,240,184,
+ 84, 84, 84,212,119,203,150, 45,249,173, 90,181, 98,221,220,220,242, 0,200,174, 95,187, 38, 59,180,243,231,172,162,162,162,241,
+ 86,171, 53,186,218,188,246, 10, 82,149,138,109,111, 82, 59, 59, 76, 19,210, 83,148, 95, 80, 54,154,146,152,154, 1,147,193, 8,
+ 27,199, 35, 61, 35, 27,165,165,102, 20, 22, 21,161, 93,235,186,223,159,182, 4,207,112,214, 52,156, 94,156, 21,119,224, 89, 30,
+ 44, 67, 41, 7,165, 76,244,175,114,194,115, 94,171, 86,175,134,135, 83,217,136, 16,203, 18,228,149,216,144,145,103,197,156,169,
+227, 29, 29, 98,167,118, 59, 69,169,149,131,217,202,161,208,198,193,203,183, 22,190, 91,249, 11, 18,245,102,236,141, 42,196,195,
+ 12, 35, 66,235, 59, 3,188, 99, 5,148,101,197,250,129,111,188,247,167,223,151, 43,157,204, 18, 86, 4,149,188, 76, 0,169, 27,
+247, 31, 77, 8, 83,196,138,197,165,233, 55,126,221,251,116, 11, 1,169, 84, 10, 95,111, 15, 88,109, 28,142, 92, 78, 66,239,206,
+173,241,106,235, 22, 32, 34, 9,162,138, 66, 33,115,113, 2,101, 9,236, 60,133,197, 86,179, 50,165,143,221,145,229, 29, 50, 96,
+202,141,139, 71,127,232,214,123, 16,242,115, 50,176,105,237,138, 34, 27,199,245,206,185,177, 43,243,101, 53,252, 78,154, 38, 94,
+ 74, 23,215,239, 90,132,119,133,169, 48, 19,250,180,132,189, 53,229, 48,100,221, 40, 0,176,202,110,181, 76,103, 24, 2, 98,183,
+192,144,241, 96, 15, 0, 30, 8,173, 54,190,202, 59,112,212,215, 75, 86, 13,245,243,243, 67,228,185, 59,152, 55, 99,204, 13,165,
+210,185,174,198,195,213,149, 15,108,134,132,219,191,195,163,110, 1, 92, 53, 1,186,222, 93, 70,234,122,244, 26,136,152,155,209,
+ 88,190,240,171,203, 6, 70,185,224,169, 89, 84, 54, 97,253,241,208,161,135,127,135,175,194,218,119,133,197,102, 71,235,182, 93,
+112, 35,234,242,152,252, 71,199, 38, 10,221,191,128,127,151,200,114, 48, 92,159, 23,252,157, 62, 40,155,171,229,229,168, 7,107,
+222,188,121, 49,243,230,205,171,210, 35, 86,173,192,122,150,184,250,121,217,116,197,150,203,118,220, 77, 44, 64,183,150, 62,200,
+ 72, 79,195,129,109,223,243,160,128, 84, 46,205,178,219,249,163,165, 12,102,228, 95,217, 93, 84,157,184, 18, 83,217,254,185, 11,
+150,222, 9,109, 28,192,174,140,204,190, 96,180,112,148,130,136, 8, 32,230, 41, 17,129,145,171,120,222,214, 16,156,135,163,174,
+ 38,106,231,105,121, 98, 0, 86,142,130,130,255, 67, 38,217,236, 60, 56, 30,224, 41, 80, 17,182,122, 1, 84,182,210, 75, 33, 97,
+115, 2,243,202,230, 92,237,172, 16, 87,126, 13,124,157,157, 93, 32,151,176,160,229, 97,107, 40,174, 20,139,199,134,244,249,228,
+205,128, 89, 75,126,185,191,101,242,138,219,231,188, 2,123,169, 69,114, 55, 15,109,232,176,242,222, 14, 0,199,155,210,175,111,
+ 61, 94, 19,238,114,193,181, 67,229, 29, 88, 55, 35, 62,106,118,215, 94,111,225,240,238, 77, 21,226,234,144,163, 60,158,238, 46,
+153, 81, 49,137,245,173,212, 13,137,153, 6,164,230,152,144, 85, 80,166,119,189, 92, 37, 72, 77, 73,130, 74, 37,117,184, 19,243,
+ 14, 25, 56,150, 18,140, 0,197,214,172,219,187,151,196,199, 31,182,144, 22,163,251, 28, 63,188,107,254,163,135,247,199,180,233,
+ 60, 4,161, 29, 95, 71,228,150, 5, 83, 1,236,119,148, 55, 47, 47,175,216,221,221,253,236,103,159,125,214,111,253,250,245,121,
+ 0, 68, 69, 69, 69,202,129, 3, 7,250,230,230,230, 78,162,148, 38, 57, 36, 38, 69,248,121,236,152,177, 29, 7,246,239, 75,108,
+ 68, 98,217,251,251, 37,145,141,227,200,252,127,188,193, 69, 93,187,194,216, 56,142,124, 48,184, 29,127,229,210,121,102,218,168,
+ 62,220,107,175, 6, 35,250,110,162,247,200,161,131,230, 2,120,250, 91, 20,229,211,222, 30, 57,177,172,140,240,252,227, 57, 87,
+ 30, 78, 98,140, 93,125, 23,170,199,243,134, 68,232, 18,234, 81,163, 54,194,198,241, 48, 91, 56,152, 45, 28,140, 22, 59, 78,221,
+206, 71,124,122, 9, 10,140, 54,148, 90,203,196,138,213,202, 3,112,172,209,170,188, 21,131,186,201,128, 77, 43,230, 77,103, 15,
+ 92,203,133,132,101,225,172,148,240,114,105,153, 32, 92,185,120,166, 40,176, 81, 99,116,234,241,182,236,217, 30, 44, 30,103,174,
+222,199,247, 59,111, 96,233,244, 33, 16, 49, 4,227,230,254,138,119,186, 55, 4,207, 83,100,220,143,130, 79,195, 87, 33,147,202,
+203,188,215, 86,222,145,186,211, 10,229, 43,107, 41,165,209,153,183,247,108,240,109,216,254,219, 71,215, 15,168,204,102, 43,111,
+ 21,169,250,233,111,236,143, 47, 15, 27, 4, 64, 2,160,148, 82,122,183,166,141,176,139,111,144, 59,207,217,135,212,246, 15,250,
+252,253,137, 95,169,149,174,158,248,109,227,114, 10, 49,179,173, 70, 25,197, 89, 25,148,205,233, 42,228,203,219, 31,194, 16,148,
+219,230,193,115, 86,182, 58,239,149, 95, 72,167, 73, 13, 27, 5,225, 82, 76, 42,190,157,245,209, 13,115,118,194, 8,139,179,251,
+ 72,107, 73,198,132,198, 33,161,208,104, 60,145,149,145,129, 14,125,187,163, 91,247, 30,136,185, 25,141,175,191,248,236, 50, 99,
+ 44,237,231,136,215, 22, 0,220, 27,182, 15,110, 18,218,114,100,253, 70, 77,161,207,205, 67,189,192, 38, 8, 12, 9, 29,233,222,
+176,253,186,252,184, 51, 49, 16, 32,224, 63, 7, 7, 1,244,126, 82, 8, 61, 41,146, 42,121,160,170,194,213,202, 28, 21,225,159,
+ 38,224, 42,207,201, 2,224,208,246, 71,162, 39, 21, 99,197,181,186, 89,255, 48,137, 88,177,239,167, 37,211, 20,155, 47,219,113,
+ 47,169, 16,221, 90,249, 32, 39, 39, 23, 71,118,174, 53, 16,198,222, 59,243,198,254, 40, 71, 83, 67,225, 27,160, 21,113,226,221,
+ 51,190,250, 42,178, 93,155,150,182, 85, 71, 50,206, 20,219,192,243, 34,145,152, 45,229, 69,132,165, 34,202, 80,177, 76,161, 20,
+121,189,210,218, 21, 15, 47,237, 85,169,131, 39, 27,245,181,238, 82,122,234,153,155,109,218, 43,189,248,114, 28, 69,101, 23, 21,
+ 5, 96,231, 40,104,197,178, 99,187, 99, 2,139, 33,192,166,227, 25,250,224,162,133,143,197,213,150,156, 50,113,229,226,236, 2,
+153,164,108, 34, 48,117,120, 45,216,191,196,213,130,177, 33,125, 63,121, 59, 96,214,178, 29,241, 91, 62, 91,126,251, 44,128,251,
+ 34,185,155,199, 79,235, 22,203,180,181,228, 96, 0, 20, 24, 56,188, 53,252,249, 94, 28,157, 52, 1,111,180,104,215,103,102,167,
+222, 67,112,232,183,159,184, 91,231,119,213, 72, 92, 1, 64,159, 78, 45,126,159,247,221, 50,223,207,166,207,150, 73,197, 20,197,
+ 38, 27,100, 18, 6,106, 87, 41, 60,148, 12,206, 70,238, 42,109, 23,164, 62,226, 8,151, 71,155,119,156,253,107,215,158, 55,109,
+198, 52,246,167,181,107,255,169,109,210,239,112,250,173,125,247,105,244,143, 54, 0,159,169, 67, 6, 61,208,249, 94, 93, 92, 59,
+184, 61,220, 60,117, 77, 60, 3,251, 57,229,220,219, 87,226,168,173,249,249,249, 41,117,235,214,125,176, 98,197,138, 70,227,198,
+141, 43, 29, 55,110,156,175,201,100,218,225,168,184, 2,128, 86, 45,154,134, 78, 24, 55, 90, 44, 21, 49, 16,139, 25,212,243,237,
+109,183,218,202,246,254,105,211,164,193,227, 18,246, 58,128,219,143,178, 49,245,251,227, 40, 40, 41,133, 72,196, 74,158,197,155,
+124,249, 41,251, 92, 17,252, 65, 92, 57,201, 69, 48,149,214,100,171, 33, 66,173,118, 30, 54, 59,143, 82, 43,135, 82,139, 29, 38,
+ 11, 15,147,133,127, 92,252, 89,134,192, 86, 86,222,107,236, 98,165, 20, 69,245, 26, 54, 68,253,146, 66, 40,229, 12, 20, 82, 49,
+ 20,210,178,119,158, 35,215,242,144,104, 41,168,150,131,231,121, 88,203,189, 82,165, 86, 14, 42, 89,217,251,156,197, 86,182, 42,
+ 55,237,238,169,173, 89,241, 87,222,244, 14,108,205,250, 6,134,163, 84,230,144,153,110,148,210,163,132,144, 46,132,144,206, 0,
+104,237,198,109,249,189,187,119,161, 79,239, 62,198,148,155, 7, 20,132,144,118,229, 85, 31,148,210,115,132,144,106,247,192,114,
+246,105, 28,193, 83,108, 34,128, 2,148,191,163,241,169,173,108,255, 90,223,134, 17,157,122,177,117,253, 3, 97,177,113,216,188,
+110, 41,189,116,114,215,100, 67,198,189,155, 53, 73, 75,109,157,134,200, 72, 73, 26,199, 67,244, 29,202,132, 21,104,217, 41,101,
+ 6, 39,239, 6,157, 21,238,126,207,244, 90,186,185, 53,119,110,210,170,163,111, 82,142, 21,135, 15, 31,134,177, 40,251, 43,139,
+165,216,136, 82,186,225,196,158, 31,223,123, 99,244,151,206,173, 91,182,128,155,139, 10,181,220, 92,112, 45,234, 2, 22,204,157,
+126,153, 49,150,246,211,235, 99, 29, 30,206,100, 40,243,207,190, 67, 70, 50,121,185,249, 88,242,205,231, 24, 51,249, 27,116,233,
+247, 46,115,255,238,141,127, 2,232, 47,244,233, 2,254, 93,158,171,167,120,178,244,149, 60, 79,127,186,174, 36,138,170,186, 38,
+229,215,150,167,112, 88,158, 16, 85,150, 39,238, 91,158,224,187,241, 66, 30, 44, 22,226,253,235, 23, 79,149,239,185,205,226, 81,
+ 90, 62,186,181,242, 65,182, 94,143,131, 91, 87, 24,108,188,121, 64,118, 13,196, 21, 0,136,108,232, 89,219,215,123,202,199,111,
+246, 35, 59,110,229, 70,167, 51, 74, 78, 38, 23, 49,172,168,132, 21,203,141, 76,137, 73,202,138, 40,203, 80,171,149,109,214,101,
+210,165,107, 54, 67,211,220,228,216, 25, 78,154,156,186, 46, 62,141,182, 21,101,220, 93, 90, 21, 47,199,217,145,149,147, 7, 31,
+119, 37,178, 10,108,176,113,180,138, 48, 20,132, 16, 40,101, 44,140,134, 34,240, 92,245, 83, 8,148,206,154, 3,193, 69, 11, 19,
+ 42,196,213,214,156,178, 97,193,202,226, 74, 46, 97,193, 16,226,176, 7,139, 16,162,248,110, 92, 80,159,207,134,150,137,171, 73,
+ 75,111,158, 3,112,159, 82,154,171, 13, 29, 6, 79,103, 9,198,126, 31, 11,149, 74, 2,119,165, 4,162,231, 56,200,200, 73, 19,
+240, 70,243,118,125,214,117, 25, 56,134,217,187,225, 59,251,221,155,231,135,214, 68, 92,113, 28, 71,108, 54, 27, 58,181,109,146,
+118, 45, 54,241,204,220, 47,102,181,111,221,229, 77, 89,187,134,222, 48, 90,236, 72, 75, 78,193,217, 35, 59, 74,125,220,197,167,
+ 27,212,241,200,176,217,108,213,118,224,249,126, 86, 99,105,129,217, 44, 18, 73, 84,131, 7,246, 34, 81,209,209, 91, 52,193, 3,
+118, 3, 36, 6,132, 15, 2, 65,255,102, 65,254,200, 7,133,165,212,100, 86,139,164, 53,158,152,156,148,148,116, 98,249,242,229,
+193, 98,177, 88, 19, 25, 25,201, 27, 12,134,223,106, 18,223,110,183, 83,134, 16, 18, 29, 95, 98,117,115, 18,147,122, 26,153, 72,
+161, 98, 96,178,208,199, 66,235,246,163,108,108, 59, 28,131,248,212, 2,104, 60,228,140,143, 59, 3,187,157,203,127,158, 6,133,
+101, 24, 40,101, 98,168,228, 44, 84, 50, 17, 20, 50, 17, 44, 54,199, 55, 10, 39,160, 9,103, 47, 94, 11,106,215, 40, 8,209, 15,
+ 13,184,147, 98,129,217,202,129,130,130,148,123, 25, 93, 21, 98,100,103, 36,129,167, 92, 82, 77,237, 19,177,162,146,238,253,254,
+ 60,161, 93,169,114,178, 73,101, 12, 84, 18, 73,181, 28, 54,142, 67,219, 22, 13,224,174,169,141,169, 11,119, 1, 0, 86,204,124,
+ 3,106, 23, 22,219,126,166,200,190,189,119,148, 58,120,192,183, 41,183, 79, 77, 77,189,121,252,141,206,109,188, 89,141, 60,223,
+129,106, 68, 6, 0,224, 1, 28,162,148,218,253, 26,133, 63,236,209,189,135,206,206,115, 25,148,210, 51,229,129,164, 0,218, 19,
+ 66,186,162,154,125,228,202, 26, 99,242, 83,244,213, 43, 94, 86, 59,197,241,243, 55, 90, 71,188, 26, 10,139,141,194, 80,106,197,
+181,232, 27,216,251,219,102,227,221,219, 87, 71, 24, 51,239, 57, 92,151,178, 82, 18,143,165, 38,222,239, 61,108,204,116, 89,243,
+176,206, 31,238,219,190,234, 13, 90,238,194, 34, 4,168,251,234,176, 43,222, 77, 6, 52, 20, 57,121, 51,176, 22, 80, 67,118,194,
+197,170,120, 10, 10,156,140,247, 98,175, 23, 60,202,180,184,137,220, 26, 64, 44,113,122,159,184,250,254,192,202,148,211,117,175,
+190,231,124,234,252, 37,196, 94, 63, 7,173,167, 10, 9, 15,239, 27, 99,111, 70,173, 53, 64,242, 13,213,199, 58,188,232,200, 43,
+168,163, 38,160, 97,147, 78,206,110, 94,216,181,109, 45, 10,243,115,151,156,136,220, 53,169,115,223,225,240,243, 15,234,228, 21,
+212, 81,163,143, 61,149, 5, 1, 2,254,255,112,181,154,235,151,193,249, 82, 33,122,122, 71,107,151,123,122,215,193,111, 31, 15,
+199,236,121,223,227, 86, 92, 18, 14,111,255,161, 92, 92,237,189,232,160,160,120,124,218,118,113,214,253,199,123, 89,141, 12,175,
+133,145,143,223, 41, 61,171,142, 60, 99,115, 58,128, 67,207,226, 4,128, 82, 67,209,219,147, 62,255,114,101,219, 87, 91,233,218,
+117,238,238,108,231,228,160, 79, 12,137, 80, 0, 94, 42,138, 71, 55,143, 21,232, 83,239,222,227, 77,249, 99,159,197, 73, 8,145,
+205, 30, 25,120,126,206,192,224, 57, 59,207, 91,118,156,230, 62,120,175,115,120, 3,141, 88,230, 84,222,125,145,178,255, 24, 2,
+169,148,173, 82, 93, 84,197, 57,127,108, 80,239,201, 67, 27,206, 94,190, 51,126,107,185,184,186, 71, 41,205,173, 8, 35, 97, 89,
+184,168, 36,112, 81, 74,224,174, 18, 87,203,249,167,206,207,187, 81,207,150, 21,226,106,163, 99,226,170, 10, 59,163, 6, 14, 28,
+ 24,250,209, 71, 31, 73, 63,251,176,207,233,211,151, 98, 31,254, 18,249,107,215,188,220, 34,111,142,227,160, 82, 73, 51,195, 27,
+121,254, 30, 80,199, 35,237,214,173, 91,252,241,227,199, 75, 57,142,187,246, 44, 78,186, 99, 7,231,217,100,192,174,168,235,183,
+134, 55,111, 22,140,149,223, 47,106,116,255, 97, 98,163,248, 71,201,208,233,116,208,233,116, 40,178, 43,241,240,242,109, 24,139,
+115,247, 39,198,238,181,214,244,217,199,142, 29,251, 90, 65, 65,129,100,229,202,149, 61, 59,116,232,176, 71,171,213,190, 54,122,
+244,232,139, 63,254,248,163,201,145,103,143,190, 30,179,243,167,141, 91,198,188,241,122,127,137,217,206,112, 87,239, 23,219,228,
+108, 41,241,247,117, 97, 47, 68, 39,240, 27, 14,222, 70,129,153,133,191,206,133,105,228, 3,114,237,194, 46,254,244,189,155,151,
+121, 17,153, 94, 19, 59, 31,139,206,146,178, 45, 59, 84,229,251, 77,169,100, 34, 88, 57,199,242, 8, 0,196, 86,229,152,137, 99,
+ 63,124, 20, 28,210, 98,236, 27,239,141,145,180, 14,168,139,171, 15,138,224,225, 36,134,183,187, 20, 57,250, 92, 68,237, 89,108,
+ 47, 72,189,181,150, 17, 99, 94, 77,211,179,242, 86, 12,234,198, 3,199,172, 92, 60,157, 61,114, 45, 15, 82, 25, 3,149, 84,198,
+ 43,149,108,181,118,230, 23, 20, 95, 92,184,124,109,216,187,111,245, 71,207,176,186, 56,123, 51, 13, 60, 45, 27,170,231,248, 50,
+111,157, 62,118,175,101,194, 91,245,206,143,238, 23,160, 46, 52,233, 27,204, 78,180, 94, 38,132, 48, 21, 59,135,255,169, 44, 81,
+122,132, 16,194, 2,104, 13,160, 43, 33,228, 44,165, 52,226, 9, 59,252, 0, 4, 3, 72, 40,127,129,225, 29,120,118, 98,181, 83,
+ 36,100,153,112,225,194,121,152,141, 69,136,143,127,128,223, 15,239,137, 42, 46,204,221, 32,183,211, 93,198,156,123, 37,142,214,
+ 35, 0, 48,241, 37,159, 45,156, 57,138,111,209,190,123,247, 94,131, 70, 74,167,124,189,206, 45, 62,254, 1,199,243,128,202,191,
+167, 84,231,175,106,204, 80, 43,205,189,187,207,146,124,109,255, 49,142, 97, 38, 87,197, 73,233, 41,187,147,119,195,181,231,207,
+159,254, 92,174,109,129, 70,189,167,247, 78,187,177,175,183,119, 80,119,120,214, 15, 71,250,141,189,184,121, 97,219,145,107, 28,
+ 55, 75,206, 33,165, 68, 31,103,168,137,157, 0,192,151,114,131,131,155, 71, 48, 38,179, 5, 49,215, 46,166, 20, 60, 58, 59,251,
+142,202,121,208,171,221,134,250,213,111,252, 42,147,114,239,214, 96, 0,223,215,132,243, 69, 32,112,254,111,114,254,221, 32,122,
+250, 27,172,184,244,234,205,123,178, 94,239,127,131,232,152, 4, 28,251,109, 85,141,196,213,191, 11,185,177,187,162, 0,180,212,
+132,188,217,239,210,213,232,121, 77,154,183,241,224,249,127, 45, 71,162, 60,207,222,188,122,206,144,155, 24,157,110, 55, 27, 62,
+203,188,249,107,181,251,183,140, 30, 80,175,195,156,247,203,118,104,159,178, 91, 23, 98,231,182,177,145, 98,137,158,128,160,252,
+127, 16, 66,192, 48,101,223,109,118,155, 35,203,171,188, 63, 25, 28, 56, 98,197,174,248,173,159, 44,185,121,182,194,115,245,135,
+ 78,215,104,133,139, 82, 2, 23,149, 24, 42, 23, 9,216, 26,166,133, 84, 44,255,176, 83,223,247, 29, 22, 87, 85, 65,175,215,223,
+ 32,132,220, 93,180,104, 81,171, 53,107,214,212,159, 60,121,114,210,218,175, 71,255, 4, 0, 71,142,148,141, 8,222,187,119, 15,
+ 43, 86,108, 55,151,150,150, 62, 48, 24, 12,151, 41,165,213,122,156, 56,177,120,218,198,181,171, 27,101,246,121,189,101, 29,255,
+134,112,243,110,136, 48, 93, 67, 20, 24,109,136, 73,201,195,195, 7,215,113,251,226,129, 91, 82, 94, 50,185, 38,246, 14, 25, 50,
+132, 85,171,213,109, 8, 33,225,205,155, 55,111,220,191,127,255,188,180,180,180,144,132,132, 4, 94, 34,145, 20,205,153, 51,231,
+218,156, 57,115,170, 29,123, 43,206,186, 51,205,201, 39, 36,114,201,210, 31,166,126,248,193,123,109,134, 12, 30, 32,182, 51,206,
+252,141, 4,179,125,233,206, 88, 18,226,175,102, 66,164, 70,114,241,212, 94, 62,246,198,229, 75, 28,143,111, 75, 50, 99,207, 62,
+111,185,205,200,183,160, 75, 51, 15,152, 74, 57,148,218, 40,172, 28, 30, 15,161, 57,130,242,243, 20,103, 42,116, 77, 86,199, 76,
+250,112,118, 72,171,136,183,218,245,124,135, 81,212,114,198,233, 3,235,105,194,245,200, 93, 34,194,127,105,200,190,159,240,226,
+ 13, 41, 10,235, 7, 52, 70,162,165, 0, 46, 50, 9,148,114, 22, 42,185,184,250,178,228, 81,216,227,196,137, 51,239,252,126,252,
+204, 87, 93, 94,139,240,152, 61,178, 63,118, 28, 60, 15, 39,133, 4,148,231,240,230,107,117, 6,222,217,214,173,151,159,151, 82,
+187,235,116,202,185,113, 75,111, 79, 51, 24,172, 15,170, 59,150,165,124, 7,255,139,132,144, 70, 0,250, 18, 66,236, 0, 20, 0,
+ 12, 40,219,155, 70, 1,224, 66,117,251,200,253,241, 25,233,136,176,176,214,155, 9,168, 20, 20,235,142,239,197, 33, 30,226,132,
+146,172, 91,250,231, 77, 55, 99,202,189, 12, 0,111, 59,251, 52,142,184,121,241,196,156,246, 61, 6,135,182,239, 61, 76,156,152,
+ 99, 3, 47,114,130,225,225, 57,107, 98,212, 47,183,236, 22,243,156,146,204,184,211,207,226, 50, 48,202, 5,215, 15, 44,104, 23,
+208,105, 66,155, 90,245,195,225, 94,167, 5, 0,160, 48, 53, 6, 41, 87,127, 59, 80,148, 46, 30, 70,233,173,231, 94,221, 39,146,
+203,135, 54,104,220, 28,113,177, 55, 96, 50, 22,255, 66, 41,229, 61,234,183,255,229, 97,220,205,207,181,254,161, 96,164,242,161,
+ 79, 19, 88, 2, 4, 8,120, 74,187,242,180, 61,253,212,205,250,135, 49, 84,188,143,231,237, 10,150, 21,153, 56,216,250,213, 84,
+ 92,253,187, 85, 51, 25, 50,132,213, 36, 72, 71,137, 68,162, 78,169,151,127,126, 29, 0,188, 91,189,247, 51,203,217,206,164, 95,
+223,182,241,105, 27, 24, 62,201,217, 63, 66,219,185, 67,104,173, 58,147,150,223,190, 3, 32,182,186, 77, 68, 29,244, 12, 73, 1,
+ 4, 0,112, 2,240,128, 82,154, 83, 57,188, 54,244,237,206, 44, 43, 86, 84, 12, 11,178, 0,120, 80,211,163, 75, 27,143, 59,154,
+158, 78,222, 13,219,179,172,232, 35,187,141, 91,111,200,190,123,236,133,211,147, 16,165, 84, 42, 13,243,246,246,214,206,156, 57,
+ 83,113,245,234, 85,209,225,195,135,205,197,197,197,105,197,197,197,103, 41,165,198,154,112,146,142, 29, 69,234, 92,247, 65, 96,
+105, 87, 15, 47,109, 39, 15, 79,111,207,188,156,140,188, 92,125,230, 9,194,115,199,178, 37,234,157,229,243,178,106, 92,150,198,
+141, 27,215,149, 16, 18, 72, 41,173, 67, 8,121,200, 48,204,131,210,210, 82,135, 61, 88,127, 72, 71,159,144,118, 42,133,116,218,
+187,195,222,110,221,175, 95, 95,230,226,141, 36,156, 62,113,136,187,114,225,212,149, 82,139,125,126, 73,198,237,179, 47, 82,230,
+ 53,205, 94, 79,164, 92,213,219, 52,136,196, 98,125,250,181, 63,158,251,231, 8,167,147,119,227,198, 32,152,206, 80,136,237,132,
+255,214,152, 17,119,237,101,213, 77,109,179, 55,250,115, 54,219,159, 38,180, 75,100,226,210,148,232,127,173, 34,124, 86,190,107,
+242, 92,223,225, 40,190, 10,239,216,203,163,206, 43,245, 17,115,108, 57, 14,253,131, 92,252,253, 90,118,244,103, 75,175,237,141,
+ 79, 51,223,174,124,106,129,163,118, 18, 66, 52, 0,122, 82, 74,127, 34,132,140, 4,112, 13, 64,204,179, 68,218,255,199,219, 60,
+ 33,132,168, 52,254,131, 84, 78,234,111, 35,122,189,227,113,242,192,207,197, 22,115,225, 63, 12, 25, 15,118, 62,205,214, 63,181,
+ 33,154, 38, 74, 21,108, 83, 61,234,181, 30,165,240,240, 83, 25,114, 18,243,243,147,162,150, 26,179, 52,203,170,155,167, 90,157,
+157,193,157, 71,166, 13, 31, 55,215,109,247,150,101,136,191,115,173, 89, 78,220,241, 7,158, 13, 59, 55,240,245,111,114,163, 93,
+191,143,112,120,211,215,246,248,115, 27, 92,171,106, 67, 5, 47,142,192, 41,224,233,111,131,127,217, 7, 64,200,127, 35, 39,202,
+ 28, 83, 94, 0,156, 94,182,157, 0, 36,255,109,233, 9,192, 77,161, 80,244,112,117,117,237,135,178, 73,198, 47,197, 78,247,214,
+111, 59,255, 39, 63,187,202, 59,184,157,119,189,150,187,213,175, 52,223,173,242, 14,110,247,119, 46,243,255, 14, 78,116,232, 32,
+210, 4,247,127,207, 51,184, 95,226, 27, 3, 59,196, 70,132,168, 59, 85, 87,199, 28, 44,159, 67, 0,140, 4, 48,228, 63, 61, 61,
+129, 14, 34,165,182, 89, 19,248,248, 40,158,187, 13,105,220, 88,162,244, 10, 82, 3, 29, 68, 47,203, 78,247,122,237, 38, 7, 68,
+188,155,233,230,223, 97,126,229,251,110,254,237,167,215,107, 59, 44,213,189, 94,187,201, 66,153, 23, 56,255,106,206,191,219, 71,
+ 36, 72,204, 42, 69, 39,197,191, 86, 25,188,108,110,235,127, 97,122, 20, 0,136,124,217,188, 47,115, 35,200,191, 2,229,158,170,
+179, 66,141,120, 73,229,232,212, 41, 59,128, 13, 0, 54, 84,158,103,245, 18,202,231,142,255,158,186,116,202, 14,224,214, 11,113,
+196,198, 90, 1,100,191,212,186,248,240,204, 66, 84,177,107,110,126,252,233,111, 0,124, 35,148, 94, 1, 2,106, 14, 70, 72, 2,
+ 1, 2, 4,252, 63,136,118, 94, 72, 5, 1, 2, 4,252,157, 65, 80,126,164, 76, 21, 13,160,195, 99,171,132,144,144,231,104, 96,
+111, 11,156, 2,167,192, 41,112, 10,156, 2,167,192,249,191,197, 89, 29,247,223,101,110, 23,169,230,224,250, 23, 35, 23, 38, 0,
+ 10,156, 2,167,192, 41,112, 10,156, 2,167,192,249, 63, 8, 97,136, 80,128,128,234, 27, 18, 53, 33, 68, 45,164,132, 0, 1, 2,
+ 4, 8,248,143, 21, 88,142,118, 86, 47,210,169, 9, 29,226, 95,146,111, 34, 66,200,167,238,238,238,151,234,213,171,151,237,234,
+234,122,137, 16,242, 25, 33, 68,252,188,156, 58,157,174,141, 86,171, 93,225,237,237,189, 74,171,213,134,255,133,182,107, 9, 33,
+218,231,140,251, 21, 33,120, 88,246, 33, 95, 9, 37, 65,128, 0, 1, 2, 4, 56,130,167,174, 34,108,215,174,221, 57,145, 72,164,
+ 19,137, 68,142,158, 99, 70,109, 54, 91,218,169, 83,167, 34,170,233,172, 38,149,127, 95, 66, 41,157,253, 34,225, 28,136,187,130,
+ 82, 58,237,121, 58,100, 0,160,148,166, 3,128,175,175,175, 63,207,243,237,197, 98,113, 67,155,205, 22,199, 48,204,153,212,212,
+212,135,255, 97, 2,136,109,220,184,254, 48,150,144,182, 0,220, 0, 20,216,121,122,193,203, 75,187,249,212, 41,199,246,200,169,
+ 16, 82, 0, 38,168, 84,170,193, 74,165,242,149,146,146,146, 71, 38,147,105,143, 84, 42,237,180,124,249,114, 93, 88, 88,152,179,
+ 94,175, 39, 12,195,168, 15, 28, 56,240,246,242,229,203,187, 16, 66,122, 83, 74,237, 53,181,153,227,184, 97,251,246,237, 11, 6,
+128, 94,189,122,141, 32,132, 92,162,148,242, 79,166,127, 21, 54, 18, 31, 31,159,112, 0,200,200,200,184, 64, 41,165, 90,173,182,
+173, 76, 38, 27, 1, 0,165,165,165, 63,167,167,167,159,127, 9,101, 73, 77, 8, 38, 85,108, 92,203, 48,228, 83,103,103,231,173,
+197,197,197,247, 43,254, 94,110,103,182,208,148, 8, 16, 32, 64,128, 0,135, 4, 22,195, 48,186,117,235,214,121, 41, 20, 10,144,
+242,195,246, 72,165, 67,247, 8, 33,143,175,109, 54, 27, 76, 38, 19,198,142, 29,107,175, 65,103,245, 89,215,174, 93,187,201,229,
+242, 63,108, 44,105, 54,155,197,132, 32,168,226,212,121,134, 33,147, 8, 33, 63, 56,210,137, 85,252,134,197, 82,202,136,197, 82,
+176, 44, 51,161, 89,179,102,161,122,189,254, 20,128,117,233,233,233,185, 14,112,252, 2,160, 15, 33, 4, 78, 78, 78, 87,253,253,
+253,115, 63,248,224, 3,239,206,157, 59,163,110,221,186,200,200,200,104,115,242,228,201, 17, 45, 91,182,204,204,204,204, 60, 65,
+ 41, 61,149,158,158,126,255, 5,197,145,151,135,135, 71, 79,137, 68, 34, 97, 24, 38, 63, 61, 61,253, 2,165, 52,179, 38,226, 42,
+ 36, 40, 96,209,168,209, 99, 26, 13, 28, 56,208, 71,161,116,150, 39, 39,199,167,175, 93,179,218,245,220,217,243,205, 8, 33,147,
+202,119,191,118,196, 75,181,255,139, 47,190,208, 70, 68, 68, 56,231,230,230,194,110,183,215,218,179,103,207,168,230,205,155, 59,
+235,116, 58,233,166, 77,155, 80, 82, 82, 2,142,227,220,253,253,253,221,135, 14, 29,106,217,180,105,211, 4, 0,139,107,250,220,
+ 60,207,179,229,255, 18,142,227,196, 0, 88, 66,200,156,234, 4,145, 78,167,107,213,191,127,255,249, 50,153, 12,219,182,109,219,
+ 1, 96, 57,128, 55,143, 29, 59, 22, 0, 0, 17, 17, 17,111, 2, 56,239,230,230,214,140, 16,124,202,243,101, 71, 39,213,164, 44,
+ 85,133,222,189,251,128, 16,178,194,219,219,251,124, 78, 78,142,142, 16,188,249, 60,194, 77,128, 0, 1, 2, 4,252, 15, 11, 44,
+ 0, 80, 40, 20,216,191,127, 63, 40,165, 96, 24, 6, 44,203,150, 31, 17,195, 32,170, 36, 4,102,187, 24, 37, 25, 55, 49,168,185,
+ 24,205,155, 55,255,131, 0,123, 90, 31, 94, 89,160, 77,156, 56, 17, 26,141,230, 15, 1,178,178,178,112,226,196,241, 42,227, 56,
+170, 55, 42, 95,204,157, 59,215, 53, 47, 47,175,247,250,245,235,187,248,248,248,124,153,145,145,113,182, 26,207, 85,159,138,137,
+255,221,186,117,107,245,227,143, 63,222, 41, 46, 46,182, 94,190,124,217,186,122,245,234,244,215, 94,123, 77, 59,120,240, 96,201,
+132, 9, 19,188, 31, 61,122,244,206,254,253,251,223,113,119,119,223,151,159,159,191,224,121, 50, 64,165, 82,133,244,239,223,191,
+203, 79, 63,253, 36, 85, 42,149,120,248,240, 97,173, 97,195,134,105, 8, 33,191, 60,121,148,206,211,208,184,113,253, 97, 31,142,
+ 26, 21, 56,230,163,113, 45,172, 86,139,241,102,244,169, 19, 34, 9,195,142, 29,251,190,107,110,110,150, 7,207,211, 97, 40,219,
+127,168, 58, 76,152, 57,115,166,143,191,191,127,237,173, 91,183,162,164,164, 4, 0,188,234,213,171,135,128,128, 0,238,244,233,
+211, 8, 12, 12,132,179,179, 51, 78,159, 62,141,139, 23, 47,162, 69,139, 22, 78, 18,137,228,245,103, 9, 44,157, 78,215, 68,167,
+211,205,210,128, 73,109, 7, 0, 0, 32, 0, 73, 68, 65, 84,148,103,118, 69,250,134,134,134, 98,226,196,137, 48,155,205,104,208,
+160, 65, 61,133, 66,113,254,244,233, 83,142,136,107,185,167,167, 39,198,140, 25,131,146,146,146, 33, 58,157, 46,129, 82, 42, 42,
+183, 23,148, 82,117, 64, 64,192,230,142, 29, 59, 54,216,183,111, 47,121,222,202, 65, 41,205, 38,132, 44,233,219,183,207,167, 0,
+ 65,167, 78,157,242, 38, 78,156,200,221,185,115,167,221,160, 65, 3, 91,223,187,119,255,165, 8, 55, 1, 2, 4, 8, 16,240, 63,
+ 36,176, 42, 60, 84,199,142, 29,131,197,242,231,163,230,220, 59, 52,199,228, 65,117, 48, 98,252, 70,108,127, 16,143, 38, 77,154,
+224,201, 21,137, 79, 28,210,154,205,178,236, 58,134, 33, 31, 18, 66, 16, 26,218, 60,123,209,162, 69, 85, 29,139, 98, 11, 13,109,
+158,205,178,140,154, 82, 10, 66,152,181, 60,207,101, 87,197,249,180, 14, 81, 42,149, 77, 2, 0, 31, 31,109,246,193,131, 7,109,
+131, 7, 15,198,194,133, 11,165, 83,166, 76,249, 66,167,211, 13, 79, 75, 75, 75,123,154,157,149,225,231,231,135,184,184, 56,204,
+152, 49, 35, 51, 43, 43,107, 93,102,102,102,220,150, 45, 91,234,212,171, 87,111,196,154, 53,107,234,133,135,135, 51, 61,122,244,
+192,129, 3, 7,154, 85, 97, 75,117, 75, 95,197, 0, 94,233,216,177, 99,231,157, 59,119, 74,139,138,138,144,148,148, 4,165, 82,
+137,217,179,103, 59,127,244,209, 71,237, 1,236,114,132,147, 37,164,109,191,254, 3, 52, 22,139,169,196, 98, 49, 23, 39, 36, 69,
+101,164,167,223, 41,104,224,223, 66,221,173,123,152, 71, 92,220,195,182, 79, 19, 88,149, 57,229,114,249,235,109,219,182,117,222,
+186,117, 43, 90,182,108, 9, 87, 87, 87,156, 60,121, 18,183,110,221, 66, 94, 94, 30, 67, 41,133,147,147, 19,230,207,159, 15, 63,
+ 63, 63, 20, 23, 23, 35, 49, 49,177,150, 88, 44,246,124,150,157, 60,207,247,218,184,113,163,198,211,211, 19,118,187, 29,148, 82,
+216,237,118,240, 60,143,140,140, 12,148,148,148, 64,165, 82,193,108, 54,227,204,153,211, 85,138,229,202,156,105,105,105,103,214,
+172, 89,115,166, 97,195,134,237,167, 76,153, 2,137, 68, 50,181,160,160, 0, 11, 23, 46,132, 82,169,196,220,185,115,189, 67, 67,
+ 67, 1,192,102,183,219, 43,202, 18,165, 20,223, 87, 22, 65,142,172,128,241,245,245, 61,150,157,173, 15,127,237,181,215,144,159,
+159,111,155, 61,123, 54, 66, 67, 67,209,160, 65, 0,170, 75,207,151, 5,129, 83,224, 20, 56, 5,206,255, 5,206,191,165,192, 34,
+132, 80, 74,203,134, 81,158,248,142,157, 59,119, 86, 25,241,189,197,177, 16,177,101,253,223,170, 85,171,144,151,151, 87,173,183,
+137,227,184, 79, 52, 26,141,105,234,212,169,157, 26, 52,104, 96, 27, 59,118,236,181,196,196,196,137,149,195,212,173, 91,119,217,
+ 15, 63,252,128, 7, 15, 30,228,204,159, 63,255, 68, 86, 86,214,244, 26,102,250, 44, 66,200, 10, 0, 72, 79, 79,207, 61,112,224,
+ 64,203,211,167, 79,127,182,100,201, 18,239,113,227,198, 73,199,143, 31,255, 33,128, 47,158, 18, 55,157, 16,178, 69,167,211,189,
+ 19, 17, 17,129, 1, 3, 6,228,182,109,219,214,122,229,202, 21,239, 75,151, 46,205, 90,177, 98, 5, 63,124,248,112,166, 93,187,
+118,208,235,245,248,237,183,223,248,228,228,100, 70, 38,147,153, 28,118,175, 17,210,137,101,217, 79, 25,134, 9, 13, 10, 10,186,
+ 59,122,244,232,219,121,121,121, 57,169,169,169, 48, 26,141,176, 90,173, 16,137, 68,144, 72, 36, 53,216, 63,131,184, 42,149, 10,
+201,197,243,123,142,164,167,198,230,100,100,221, 46,100, 64,153,244,244,168,194,192,192, 78, 30, 40,155,147, 85, 45,156,156,156,
+234,233,245,122,148,148,148,192,205,205, 13, 75,150, 44,129, 90,173,134,201,100, 66, 92, 92, 28,245,245,245, 37, 39, 79,158,132,
+ 78,167, 67,126,126, 62, 44, 22, 11,140, 70, 99,150,197, 98,121,230,243,139,197,226,125,195,135, 15,111,175, 86,171,149, 21, 30,
+ 44,158,231, 81,191,126,125,140, 27, 55, 14,219,183,111, 71,124,124, 60, 40,165, 54,157,206, 55,155, 97,136, 26, 0,101, 24,118,
+139,221,110,207,174, 34,159,168,175,175,239,220, 89,179,102,249,174, 94,189,250,149,137, 19, 39,130,227, 56,240, 60, 15,142,227,
+144,157,157,141,125,251,246,225,252,249,243,214,184,184,184,237, 46, 46,174, 49, 38,147, 41,170,180,180,244,145,163, 41,234,235,
+235, 43,231,121,254,131,128,128,128,158, 67,135, 14,181, 73, 36, 18,152, 76, 38, 24,141, 70,220,190,125,219,214,179,103,207,188,
+190,125,251,120, 28, 60,120,144, 82,138, 37,130,247, 74,128, 0, 1, 2,158, 15, 79,211, 32,127, 27, 15,214,211, 30,234,231,159,
+127, 6,165, 20, 44,203,130, 97,152,199, 67,132, 37,233, 60,222, 27,191, 25, 18,150, 71,100,100, 36,154, 53,107,230,208, 15,242,
+ 60,191, 60, 50, 50, 50, 44, 34, 34, 66,212,165, 75,151,230,117,234,212, 9, 77, 74, 74,186, 14, 0,117,234,212, 9,237,218,181,
+107,115,181, 90,141,101,203,150,153,121,158, 95,254,156,202,186,114,103,119,217,207,207,239,203,221,187,119,175, 30, 61,122, 52,
+124,124,124,154, 86, 19,119,116,247,238,221,155,125,254,249,231,152, 49, 99,134,117,221,186,117,246, 49, 99,198,136, 58,118,236,
+136, 77,155, 54, 49,247,238,221,195,186,117,235,248,221,187,119,103, 18, 66,216,238,221,187,107,106, 80,136, 58,104, 52,154, 95,
+118,236,216,193,183,106,213, 74,126,255,254,253, 70,147, 38, 77,210,100,100,100, 28,109,208,160, 65,174,209,104,132,221,110,135,
+193, 96, 0, 0,139,163,188, 12, 75,178, 82, 83, 31,169, 75,173, 5,230, 30, 29,195, 39,233, 19,115,224, 85,183, 63,126, 63,189,
+115,105, 82, 74, 60, 79, 24, 56, 52,212, 88, 82, 82,242,200,110,183,123, 0, 80, 31, 59,118, 12, 94, 94, 94, 40, 46, 46,134,213,
+106,133,201,100,178,186,187,187,203,114,115,115, 81, 90, 90,138,210,210, 82,184,184,184, 32, 58, 58, 58,207,110,183, 31,122, 22,
+111,114,114,242, 29, 0,221,158, 16,210, 50,134, 97,142,219,108, 54, 60,124,248, 16,119,239,222,237,156,152,152, 88, 90,158, 78,
+ 90, 0,176,219,237,233, 79,227, 76, 77, 77, 53,123,121,121,125,254,254,251,239, 79,212,104, 52, 33, 0,224,239,239,239, 50,105,
+210, 36, 44, 88,176, 0, 49, 49, 49,179,196, 98,241,165,180,180,180,210,154,150, 31,141, 70, 19,164, 80, 40, 38, 79,152, 48, 65,
+ 19, 20, 20,132,210,210, 50, 10,103,103,103, 24,141, 70,184,184,184, 32, 44, 44, 44,238,203, 47,191,180, 82,138, 81,148,210, 44,
+161,137, 20, 32, 64,128,128,151, 35,178,254, 86, 30,172,114, 97, 65, 8, 33,244,137, 7, 46,235,192, 25,230, 15,226,138,101, 89,
+ 12,106,201,162,184,129, 63, 24,166,108, 40,209,110,119,108, 17,153, 94,175,207,242,245,245,221, 19, 29, 29, 61,120,200,144, 33,
+ 56,113,226,196,199, 0, 62, 0, 0,150,101, 63, 30, 50,100, 8,162,163,163,113,247,238,221, 61,122,189,254,165,116, 92, 86,171,
+213,104,179,149,141, 70,202,229,114, 73,181,130,133, 97,172, 18, 73, 89,176,251,247,239, 15, 24, 63,126,252,128,238,221,187,143,
+236,221,187, 55,246,237,219,135,141, 27, 55,126, 13,224, 68, 68, 68,196,230,154,216,193,178,236,164,237,219,183,219, 35, 34, 34,
+156, 41,165, 8, 14, 14,118,158, 60,121,178,117,225,194,133,245,134, 15, 31,158,155,154,154,138,162,162, 34,100,102,102, 90,147,
+147,147,227, 29,229,181,115,252,137, 21, 43,126,208,141,250,160,191,102,231,129,245,243,126,219,117,179,233,219,111,102,198,106,
+117, 77,188,150,175, 60, 47,183,219,249,189,142,240,152,205,230,223, 14, 30, 60,248,102,157, 58,117,212,183,110,221,130,217,108,
+ 6,207,243,232,217,179, 39, 0,200, 42,194,197,197,197,153,141, 70, 99,118,108,108,108,113, 82, 82,146, 13,101,147,204, 29,169,
+ 64,143, 87, 7, 90,173,214,119,122,245,234, 5,142,227,208,163, 71, 15,220,184,113,227, 29, 0,235, 42,254,238,104, 89, 2, 48,
+ 13, 0,116, 58,157,135,171,171,235,190, 10,239,152, 70,163, 57, 31, 29, 29,109,243,245,245, 29, 42,145, 72,194, 76, 38,211,206,
+204,204,204, 51,213,113,106,181,218,240, 6, 13, 26,204, 92,184,112, 1,209,104,188,193,113, 54,216,237,118,100,103,231,160,164,
+164, 4, 65, 65, 65,240,243,243,195,252,249,243,193, 48,204,126, 65, 92, 9, 16, 32, 64,192,139,163, 42, 13,242,223, 14,230,201,
+ 7,172, 78, 92, 85,124,151,136, 88,120,214,114,135,103, 45, 15,184,187,187,131,227, 56, 56,170, 62, 25,134,217,180,117,235, 86,
+139,171,171, 43,250,246,237, 27,232,227,227, 19,225,227,227, 19,209,183,111,223, 64, 87, 87, 87,108,221,186,213,194, 48,204,166,
+151,164,138, 25,150,101,135, 69, 68, 68, 32, 43, 43, 11,143, 30, 61,186, 92,147,248, 41, 41, 41,197, 25, 25, 25,219, 13, 6, 3,
+ 68, 34, 17,204,102, 51, 0,156, 2, 80,227,179,212,120,158,111,213,170, 85, 43, 69,197, 92,181,132,132, 4, 56, 59, 59, 59,167,
+164,164,168,141, 70, 35, 44, 22, 11, 10, 10, 10,112,237,218, 53, 35,128,116, 71,121, 99, 98,238,239,137,186, 18, 21, 29,121,244,
+ 44,243,202, 43, 77,189,124,117,202, 34, 79, 47, 95,231, 67,145,183, 20,153, 25,185, 15, 99, 98,226, 29, 61, 12,119,249,238,221,
+187,115,163,163,163,239,250,250,250, 38,187,186,186, 82, 0,200,200,200,248,195,231,234,213,171,178,200,200, 72, 99, 82, 82,210,
+ 62,148, 45, 10,176, 59,144, 15, 95, 17,130,123,132,224, 30,203,178,139,154, 53,107,246,118,120,120, 56, 82, 82, 82, 16, 30, 30,
+142,224,224,224,183, 61, 61, 61,189,107,152,183,222,132, 16,109, 80, 80,144, 74,165, 82, 45, 29, 57,114, 36,236,118, 59,186,116,
+233, 2,131,193,176, 94,171,213,254,163,123,247,238, 31,255,248,227,143, 77, 53, 26,205, 39, 14,210, 14,125,235,173,183,136, 82,
+169,130,205,102,131, 84, 42,133, 74,229,132,122,245,234,161, 83,167, 78,160,148,162, 83,167, 78,252,154, 53,107,246, 41, 20,138,
+205, 66,179, 40, 64,128, 0, 1, 47, 79,100,253, 45, 61, 88, 79,233,192,192,113, 28, 8, 33,184, 84, 24, 2,179, 93,132,194,148,
+ 40, 12,105, 37,125, 44,180, 88,150, 5,203,178,176,217,108,112,244,216,157,228,228,228, 2, 31, 31,159, 95,207,159, 63,255,238,
+192,129, 3,113,228,200,145,209, 0, 48,112,224, 64,156, 63,127, 30, 15, 31, 62,252, 53, 35, 35,163,160,134,157,173, 39, 0,182,
+178, 71, 65,163,209,188, 82,187,118,237,143, 71,141, 26,213,166, 73,147, 38,216,178,101, 11, 0,156,112,216, 51, 84,230,149, 83,
+ 3, 40,121,226,217, 36, 0,156,121,158,175,209, 38,155, 12,195, 92, 61,113,226, 68,171,222,189,123, 59, 39, 37, 37, 33, 61, 61,
+ 29, 59,118,236,200,246,240,240,200,230,121, 30, 30, 30, 30,240,244,244,132,205,102, 83,196,197,197,121, 3,112,120,175, 45,142,
+ 74,215, 30, 61,114,121,117,235, 22, 61,153, 87,234,168, 10, 1, 11,185, 26,157,166, 18, 73, 68,171,106, 80,184,237,132,144,190,
+231,206,157,155,112,241,226,197, 65, 62, 62, 62,228,221,119,223, 69,207,158, 61, 33,149, 74, 97, 50,153,144,159,159,143,131, 7,
+ 15, 18,187,221, 30, 14, 0, 62, 62, 62,181,235,214,173,251, 51, 33, 36, 45, 33, 33,225,221,167,228,205,147, 91,116,140, 30, 48,
+ 96,192,157,140,140, 12,219,164, 73,147,176,104,209, 34,140, 24, 49, 66, 28, 27, 27,251, 1,128,127, 58,152,223, 95, 18,130, 79,
+ 65, 65, 82, 83, 82,238,253,176,114,101,169,143,143, 15,142, 29, 59,134,176,176, 48,212,175, 95,255,149,107,215,174,189,210,174,
+ 93, 59, 92,190,124, 25,185,185,185, 23,171,227,236,216,177,163,136,101,217,122, 90,173, 22,137,137,137,144,203,229,240,246,246,
+134,155,155, 27,188,188,188,176,104,209, 34, 44, 89,178,228,166, 72, 36, 90,151,150,150,246, 80,104, 14, 5, 8, 16, 32, 64,192,
+ 51, 5, 86,101,213,248,164, 23,235,240,225,195,160,148,194, 41,188, 37,166, 14,169,139, 97, 31,111,196,182,135,113,144,201,100,
+255, 34, 17,137,240,209, 71, 31,213,232,135,221,221,221,183,109,219,182,109, 96,219,182,109, 85, 93,186,116,169, 15, 0,114,185,
+220,182,109,219, 54,131,187,187,251,182, 26,138,171, 25,132, 96, 10, 40, 24,153, 84,122,204,163, 86,173,227,206,206,206, 45,186,
+119,239, 94,191, 71,143, 30,240,247,247,199,142, 29, 59,176, 99,199,142, 19, 25, 25, 25, 23, 28,229,173, 87,175, 30,238,220,185,
+ 51, 12,192,122, 0, 20,255,154,196,111, 7,208,214,207,207, 79, 94, 19, 59, 57,142, 91, 50,124,248,240,157, 51,102,204,200, 9,
+ 12, 12, 84,109,223,190, 61,255,216,177, 99,150, 94,189,122, 61,170,232,200, 77, 38, 19, 76, 38,147, 84,167,211, 53,168,137,192,
+138,137,137,201,238,209,189,179,215,202,213,231,235,155, 76,156,117,239,225, 99, 86,155, 69,101,186, 19,247, 48,179, 38, 54, 82,
+ 74,237,190,190,190, 99,120,158,247,178,219,237, 86, 47, 47, 47,201, 47,191,252, 2,185, 92, 14,134, 97, 16, 26, 26, 10,185, 92,
+110,209,106,181,133, 0,160, 86,171,109,139, 23, 47, 22,189,255,254,251,146,154,100,153,183,183, 55, 54,111,222, 12,131,193, 48,
+111,251,246,237,211, 62,250,232, 35, 4, 6, 6,118,212,106,181,139,210,211,211, 77,213,228,183,123,101,193, 70, 8,105, 40,145,
+ 72,238, 44, 95,190,220,114,238,220,185,221,145,145,145, 61, 71,140, 24, 33,143,136,136,192,133, 11, 23,176,118,237,218,203,174,
+174,174,203,170, 51,234,244,233,211,188,143,143,207,227, 97,112,179,217,140,132,132, 4,132,133,133, 97,221,186,117, 88,190,124,
+249,214,204,204, 76,193,107, 37, 64,128, 0, 1,127,145,231,234,239,228,197, 18, 85, 23, 96,251,246,237, 0,128, 15,190,143,131,
+197, 82, 54,143,105,213,170, 85,143,247,175,170, 24, 74, 60,115,230, 12, 80,131, 61,171, 98, 99, 99, 13,190,190,190,155,198,143,
+ 31, 63,247,234,213, 43,106, 0,136,138,138,202,206,204,204,156,153,154,154,106,168,129,184,114, 35, 4, 83,120,158,178,229, 34,
+173,235,164, 73,147,180,109,219,182,181,138,197, 98, 36, 39, 39,227,187,239,190,195,249,243,231,183,103,100,100,172,164, 14,184,
+217, 18, 19, 19, 47,167,164,164,180, 25, 55,110, 28,218,183,111,223,103,237,218,181,221, 42, 63, 91,104,104,232,134, 94,189,122,
+105,100, 50,153,200, 98,177,112,247,239,223,191,238, 96, 33, 58, 77, 8, 25, 58,101,202,148, 9,148,210,102,106,181, 58,185,117,
+235,214,177,109,219,182,205,117,113,113,129, 72, 36, 66,118,118, 54,140, 70, 35, 56,142,115,175, 73, 70,250,249,249, 69, 76,152,
+ 48,161,233,152, 49, 99, 96, 48, 24,176,113,227, 70,172, 92,185, 18,126,126,126, 17, 41, 41, 41,231,106,194,197,243,188,215,254,
+253,251, 43, 60,117, 56,126,252, 56,180, 90, 45, 92, 93, 93, 81, 84, 84,132,119,223,125, 87, 58,107,214, 44, 0,192,181,107,215,
+196, 10,133,162,186,231,206, 38,132, 44, 97, 24, 50, 9, 0,105,213,170,181,222,197,197,197,118,233,210,165,248,180,180,180, 67,
+254,254,254,175, 15, 31, 62,188,126,235,214,173, 37,247,239,223,111, 7,224, 72, 77, 11,114, 94, 94, 30,206,156, 57,115, 38, 35,
+ 35, 99,137, 90,173,222,246,229,151, 95,126,234,237,237,221, 44, 61, 61,253,146, 70,163,153, 27, 29, 29,109,115, 32,127,120, 31,
+ 31,159,148,163, 71,143,250, 13, 30, 60, 24, 82,169, 20,249,249,249,112,113,113,193,226,197,139,169,213,106,221, 35, 52,133, 2,
+ 4, 8, 16, 32,224,165, 8,172,221,187,119,131, 97, 24, 88,178, 45,248,104,202,118, 40,229, 44, 78,158, 60, 9, 15, 15,143, 63,
+204,203,170, 24, 50,124, 66,252, 60,243,180,237,188,188,188,115,233,233,105, 94,149, 54,150,244,146,201,228,231,170, 17, 84,207,
+228, 36,132,192,106,181, 34, 50, 50, 18,103,207,158,181, 62,120,240,224, 52, 33,100,127,122,122,250, 77, 71, 57, 11, 11, 11,191,
+ 29, 61,122,244,148,158, 61,123,182, 25, 54,108, 24,150, 47, 95, 46,185,115,231, 14, 40,165,104,222,188, 57,154, 52,105,162,179,
+217,108, 52, 38, 38,166,100,223,190,125,145,102,179,121,179,163,118, 82, 74,143, 1, 56, 70, 8,145,100,102,102,190, 82, 88, 88,
+216,153,231,121,231,236,236,108, 36, 38, 38, 34, 47, 47, 15, 69, 69, 69,176,219,237,121, 53,121,246,148,148,148,115,173, 90,181,
+ 2,195, 48, 48,153, 76, 72, 77, 77,133,221,110, 71,122,122,122,141,211,147, 97, 24,125,175, 94,189,188, 74, 75, 75,237,111,189,
+245,150, 72,175,215, 35, 48, 48, 16, 0, 80, 92, 92,140,195,135, 15,163, 97,195,134, 21,158, 51, 4, 5, 5, 85,203, 73, 41,157,
+ 77, 8,249,209,199,199,231,203,111,190,249, 38,240,210,165, 75,176,217,108,145, 0, 96,179,217, 34,163,162,162,234,183,104,209,
+ 2, 91,182,108,233, 94,149,192,170,204, 73, 41,205, 47, 23,108,159,130,130, 4, 53,110,156, 27, 24, 24,104, 21,139,197,181, 0,
+ 32, 59, 59, 59, 27,192, 20, 7,196,121, 72, 21,123,118,205,220,181,107,215,251, 23, 47, 94,108,247,233,167,159,146, 78,157, 58,
+ 1, 0, 12, 6, 3,167,215,235, 13,207,195,249,162, 16, 56, 5, 78,129, 83,224,252, 95,224,252,159, 18, 88,133,133,133,104,221,
+186, 53,108, 54, 27, 26, 55,182,161,168,168, 30,108, 54,219,227,201,191, 60,207,195,110,183,131,227, 56, 48, 12,227,240, 28,172,
+ 10,152,205,102,235,147,155,191,155,205,102,107, 13, 93,139, 5,132,144,239, 24,134, 76, 1, 5, 35,149, 74, 47,175, 92,185,114,
+ 35,128, 52, 74,233,229,234,134,155,170, 66,102,102,102, 14,128,201,181,107,215,110,126,242,228,201,113,131, 6, 13,170,223,183,
+111, 95, 36, 39, 39,195,110,183, 35, 62, 62,222,182,111,223,190,152,130,130,130, 31, 41,165,119,158, 39,225, 41,165, 86, 0,247,
+156,157,157,193,243,124,251,176,176, 48, 15,187,221,142,156,156, 28, 92,188,120, 49, 49, 39, 39,231,252,115,120,176, 48,122,244,
+104,148,148,148, 96,251,246,237, 56,114,228,200,115,121,176, 82, 83, 83, 27, 0,128, 86,171,205,114,113,113, 17,141, 28, 57, 18,
+ 54,155, 13, 70,163, 17, 69, 69, 69,200,205,205,181,124,242,201, 39, 82, 0,144, 74,165,182, 30, 61,122,136, 28,124,230,244,240,
+240,112, 87,185, 92,142, 51,103,206,240, 60,207, 31, 47, 23, 53,199,207,157, 59, 55,174, 89,179,102,140,167,167,103, 67, 7,185,
+190, 32,132,172,118,113,113,209, 54, 14, 10, 90, 74, 41,133,151,151,151,223,139, 86,136,172,172, 44, 61,128,121, 58,157,110,215,
+231,159,127,254, 97,155, 54,109,130,191,248,226, 11, 80, 90,230, 33, 21, 32, 64,128, 0, 1, 2, 94, 84, 96, 37,140, 25, 51,198,
+ 90,217, 51,244,132,151,227, 79,158, 35,158,231,211,106, 40, 50,178, 9, 33,139,203,135,142,240,188, 27, 54, 82, 74,231, 18, 66,
+126, 4,192,154, 75, 75, 95,218,178,249,228,228,228,107,132,144,145,155, 54,109,234,178, 99,199,142,201,111,190,249,166, 98,253,
+250,245,150,236,236,236, 69, 0,142, 80, 74,249, 23,253,141,226,226,226,123,132,144,140,184,184,184, 87,165, 82,169,130,227, 56,
+189, 94,175,143,165,148,150,212,132, 39, 37, 37,229,156, 86,171,197,158, 61,123,224,225,225,129,188,188, 60,135, 60, 88,213,188,
+161, 12,216,186,117,235,110,158,231,229, 79,228,125, 81,122,122,122, 3,160,108,146,251,225,195,135,127, 38,132,164, 57,104,231,
+246,177, 99,199,190,171,215,235,127, 75, 75, 75,203, 47, 23,116,249,190,190,190, 75,102,204,152, 49, 52, 39, 39,231,151, 26,228,
+123, 38, 33, 68,255,232,209,163,226,188,188, 60,103,142,227, 94, 90,197, 72, 75, 75,123, 0,224, 31, 58,157,174, 77,143, 30, 61,
+222,161,148,234,133,230, 66,128, 0, 1, 2, 4,188,176,192, 58,121,242,100,167,127,135, 1,229, 67, 71, 63, 84, 8,174, 23,224,
+201,249,139,236,163, 0,126, 39,132,156, 88,182,108, 89, 35,163,209,152, 72, 41, 53,188,228,223, 40, 6,112,244, 69,121,210,211,
+211,149,132,144, 25, 0,166, 3,248,134, 82,250,245, 11,138,140, 75, 0,158,185,117, 66, 70, 70, 70, 50,128,215, 28,229, 76, 77,
+ 77,221,133, 39,142, 0, 42,191,191, 7,192,158,231, 72, 59,206,207,207,111,246,164, 73,147,122, 0,216,255,178,243, 63, 45, 45,
+237, 50,128,203, 66, 83, 33, 64,128, 0, 1,255,239,104, 5,192,171,252,123,197, 75,175,215, 19,223, 45, 0,164,149,226, 84, 92,
+235, 1, 92,173,196, 81,249,126,117,113, 1, 32, 7,192, 77,212,100, 19,240,255,132, 20,163,148,102,255,167, 31, 53, 66, 41,229,
+ 12, 6, 67,204,203, 22, 87,127,129,157, 95, 83, 74,149, 47, 42,174,254,155,144,146,146, 18,157,150,150,246,207,180,180,180, 91,
+ 66,251, 35, 64,128, 0, 1,127, 95,113, 69, 8, 57, 64, 8, 57, 80, 46,136,188,170,248, 46,173, 8, 83,249,186,146, 48,243,170,
+226,254, 51,227, 18, 66, 14, 76,155, 54,237, 53, 0,225, 53, 49,152, 17,242, 76,128, 0, 1, 2, 4, 8, 16,240, 31, 14, 47, 66,
+200, 1, 74,105, 31, 74,105,159,114, 1,244, 52, 71, 67,159,202,255, 62, 11, 85,241, 84,252, 70,229,235,249,243,231,127, 3, 64,
+ 81, 19,131, 69,132,144,144,167, 24,232,240,234,128,167,113, 60,235,111,213,241, 11,156, 2,167,192, 41,112, 10,156, 2,167,192,
+249,247,227,124, 89,241, 95, 6,170, 18,107, 21, 66,174,242,245,212,169, 83,167,163, 6,195,131, 21,228,127,217, 7, 64,136,192,
+ 41,112, 10,156, 2,167,192, 41,112, 10,156, 2,231, 11,126,122,151, 73, 22,218,187,242,247,170,238, 61,235,123,117,113, 29, 8,
+235,176,205, 34, 8, 16, 32, 64,128, 0, 1, 2, 4,252,103, 67, 95,217,219, 84,238, 97,226,166, 78,157, 58,189,226, 94,185,151,
+169, 20,128,172, 10,111, 89,229,120,213,121,214, 28, 14,251, 44, 8, 2, 75,128, 67, 32,132,136, 0, 76,112,115,115, 27,226,230,
+230, 86, 55, 47, 47, 47,161,168,168,232, 55, 0,203, 41,165,182,231,225, 12,110, 64,186,112,118, 76,230,121,176,172, 8,139,238,
+ 60,164,145, 66, 74, 11, 16, 32, 64,128,128, 42,112, 21, 64,171, 74,162, 71, 15,224,214,188,121,243,242,231,205,155, 87,249,222,
+ 13, 0,205,202,195,233,171, 16, 74,150,242,107, 75, 21, 97, 44,142,132,253, 75, 4, 86, 80,109,242, 33,120,204, 0, 1, 5,193,
+ 55,177,201,116,109, 77,226, 55, 9, 36,175, 73, 25,209, 74, 10,202,154,109,220, 52,194,161,202, 61,154, 40,139, 8,185,152,157,
+ 71, 64,120, 11,111,255,232,214, 61,122,210,225, 78,187, 33,233, 42,162,204,122,158,167, 98,158,167, 91, 24,224,176,210,130, 75,
+ 23, 83,169,249,121,115,181,118,109,226, 70,120,244,148,136, 68, 45,173,118,123, 20,101,112, 56, 57,153, 22,252, 39,149,188, 33,
+ 65, 68, 34,242, 83, 44, 84,201,108, 93, 88,150,115,231,120, 54,223,104, 22, 31,183,165,152, 62,219, 17, 75, 29,222,188,149, 16,
+ 34, 6, 48, 65,165, 82,189,174, 84, 42, 95, 41, 41, 41,121,100, 50,153,118, 75,165,210,206,203,151, 47,247, 13, 11, 11,115,210,
+235,245,228,255,216, 59,239,168, 40,174,191,141, 63,119,182,194,178,244,190,244, 38, 34,162, 8,246,138, 6,107, 80, 99,212, 52,
+ 99,138,177,164, 89, 82, 94,211,140, 49, 38,198,196, 88, 98, 18, 19,163, 38,209, 88, 18, 27,198, 18, 59, 26, 75, 44, 96, 71, 84,
+ 80, 1, 97,233, 32,236,194,178,101,102,238,251, 7, 66,208, 8, 44,196, 52,127,247,115,206, 28,216,157,217,103,238,220,153,185,
+243,204,247, 54,142,227, 60,126,254,249,231, 49, 95,124,241, 69, 60, 33,228, 65, 74, 41,223,220, 52, 11, 60, 94, 79,219,254,124,
+119, 0, 8,138,255,234, 45, 66,200,238,230,142, 45,214, 62,148,180, 17, 4, 76,108,106, 59,137, 4, 75,207,102,180,108, 80,216,
+ 54,193,228, 43, 2,132,129, 34, 81,194, 97,253,185,171,108, 76, 44, 6,131,193,248,135, 76,214,157,156,176,114,187,191,157,102,
+ 25, 44, 66, 49,243, 66,250, 13, 39,136,102,180, 13, 15,121, 23, 64,179, 12,150, 66, 34, 89,118,242, 76,190, 39,168, 25,203, 22,
+188,176,210,100, 1,120,222, 12,145,183,128,231, 45,224,121, 51, 4,193, 2,145,175,198,204,133, 7, 0, 94,135,142, 29, 90, 45,
+ 3, 16,108,237, 62,100, 34,183,226,212,209,221,206,132, 47,199,143,223,127,244,124,150, 86,255,252,190, 19,218,146,200, 64,242,
+238,197, 44,252, 96,237, 3, 60, 32,128,120, 81,138,161,254, 26,247,145,211, 39, 61,210,101, 96,223,158,156,127, 64, 16,178,179,
+174,143,223,149,116, 88,236,213,205,227,120,182,182,104, 35, 33,216,154,149, 69,243,255,204, 73,112,119, 34,237, 29,236,108,191,
+146,201, 57, 59,153, 68,146, 94, 84, 86,241,113,126, 9,181,250, 2, 25, 29, 73,228,234, 96,249,177,190, 67,158,114,238,213,239,
+ 25,193, 86,165,214,229, 92, 75, 49,237,220, 58,191,255, 85,121,218,241,209,145,164,139, 53, 38,139, 16, 34, 37,132,108,155, 57,
+115,166, 87,207,158, 61,237, 75, 74, 74,192,243,188,203,166, 77,155, 38,117,234,212, 73,237,227,227,163, 88,181,106, 21,244,122,
+ 61, 4, 65,112, 14, 9, 9,113,126,244,209, 71,249,213,171, 87, 79, 6,176,160, 49,237,192, 64,162,180, 35,112,184,205, 96,137,
+168, 27,192,212,194, 67, 21,162,129,119,219, 32, 98, 1, 0,133, 9,250, 20, 45,109,114, 20,126, 65,192,196,211,201, 73,227,248,
+155, 39, 1,193, 12, 10, 11, 32,154, 1,106, 1, 21,205,128,104, 1,165,102,116,125,232, 59, 0,152,220,146,243, 67, 8, 30,216,
+183,239,164, 87, 65,126, 94,236,194,133,115, 94,139, 12, 34,187, 57, 9,214, 94,184,138,195,247, 98,176, 89, 6,131,241,207,243,
+192, 3, 15,172,208,235,245, 31,159, 56,113, 34,253, 94,105,122,121,121, 69,112, 28,151,213,146, 25, 69,234, 19, 19, 19, 51, 21,
+192,211,183, 62,126,127,234,212,169, 69,127, 54,109, 93,186,116,241,161,148,122,222, 42,251, 11,142, 31, 63,158,203,174,130,127,
+208, 96, 81, 64, 9, 42, 2, 71, 30, 2, 37,176,105,238,206, 40,133, 13,136, 4,176,232, 49, 60, 33, 30,110,174,222,128, 80, 9,
+ 8, 6,128,175, 2,132,154,165,184, 40, 11,224, 43,129,162, 95,192, 83,170,108,246, 81, 89,202,129,194,245, 24,208,205, 31, 78,
+246, 54,152,242, 88,164,235, 55,137,151,151, 44, 79,188,212, 23,192, 83, 77,253,220,215,151, 44,122, 99,210,240,231, 6,244, 79,
+ 32,129, 33, 81, 40, 45,202,193,137,147,191,221, 92,248,205,134,139,253,251,116,108, 51,114,196, 35, 78, 19, 39,189,214, 45,235,
+234,249,110, 7,246,111, 89,224,175, 33,139,179,181,244,205, 22, 69,199,188,229, 19, 7,196,199,207,254,234,155,239, 85,182,106,
+ 87, 84,148,102, 7, 61,249,196,136,104, 47, 23,146,144, 95,106, 93,196, 69,230,103, 59, 63, 62,225, 89,151, 81, 79,127,106,111,
+ 49,235,205,218, 43, 59, 47,218,217,242,220,163,143, 77, 41,255,126,217,187, 94, 87,205,165,243, 1,188,108,133,212,228,153, 51,
+103,122,133,132,132,248,175, 89,179, 6,122,189, 30, 0, 60,194,194,194, 16, 22, 22, 38, 28, 60,120, 16,225,225,225,176,183,183,
+199,129, 3, 7,112,236,216, 49,116,232,208, 65, 37,151,203, 71, 54,102,176,218,132,146,209, 15,245,237,248, 69,112,128,143,170,
+166,241,159, 8, 74, 69,232,245, 70,188, 48, 39, 5,101, 21,213, 24,242, 64, 76,171, 64, 31,251, 43, 28, 68, 80, 10,100,106, 11,
+132,136, 96,242, 88,218, 53,186,163,169,200, 84,135, 78,125,187,159, 73,249, 45,220, 92,184, 13,157,135,124,116, 25, 20, 71,127,
+119, 71,232,158,114,240,187,112,224,187, 22,221, 32,132, 16, 18, 25, 4, 33,251,183,143,225, 27, 51, 94,178,244,187,157,110,229,
+ 37,185, 79,108, 90,255,213, 67, 75,150,126,253, 99, 75, 77, 27,131,193,248,215, 49,208,201,201, 41,174,115,231,206, 3,239,149,
+201,146,201,100,182,130, 32,180,210,104, 52, 87, 90,106,178,166, 76,153,242, 34, 33,228,195,148,148, 20, 0, 64,108,108,236,135,
+177,177,177,119, 29,231,208,193,193,161, 50, 50, 50,242,253,207, 62,251,236,203,198, 52,167, 79,159,238,109,177, 88, 2, 79,157,
+ 58, 85,107,224, 2, 99, 98, 98, 2,239,182,173,157,157,157,208,165, 75,151,172,143, 63,254, 56,143, 93, 34,127,101, 4, 11,184,
+156,127,104,106,180,169,180, 10, 4,184,220,180,161,186,189,171,101,181, 69,248,244,251, 69, 79,205,110, 27,238,140, 10,157, 9,
+123, 14,101,194,194,155, 33,242, 60, 4,193, 2,225,214,223,129,221,220,208,157,159,132,197,235, 46,193,194,139,243, 26,211,252,
+ 67, 68, 3,226,211, 29,250, 60,242,131, 64,169,220,206,134,171, 8,241,119,117,127,237,201,104,110,202, 99,109, 97,168,230, 71,
+182, 9, 36, 7, 47,102,210,239, 26,211,108, 27,228,252,236, 11,227,199, 19, 81,213, 22,201,199,118, 96,242,255,189,157, 81, 92,
+ 82,246, 81, 86, 14, 78,109,221,247,107,128,191,167,235,204, 69,115,222,238, 16, 30, 61, 8,131, 56, 3,126, 61,124,232,105, 0,
+111, 54, 39,157,158,158, 68, 37, 26, 49,164, 75,231,142,239,175, 92,183, 77,197,233, 79, 3,217,171,225,228,212, 13, 75, 23,127,
+236, 49,108,196,232, 5, 0, 6, 88,163,105,167,180,196,247,122,224,105, 88,204,122,179,197,168, 51, 26,202, 82,205, 66, 85,161,
+153,147,113,210, 78,237,219, 20, 22, 20, 36,245,183,230, 28,217,217,217,141,234,222,189,187,122,245,234,213,136,141,141,133,147,
+147, 19,246,239,223,143,179,103,207,162,164,164,132,163,148, 66,173, 86, 99,238,220,185,240,243,243, 67, 69, 69, 5,178,178,178,
+156,101, 50,153, 75, 99,233, 84, 74,165, 99, 63,253,248, 99, 21,199, 1, 16,121,128,254,190,104,243, 11, 81, 89,105,128,147, 90,
+ 14,119, 23,219,186,239,121,139, 73,210,113,240,235,147, 0,236,104,236,216,207,102,208,139,109,131,200, 81, 80, 62,156, 10, 6,
+128,226,232,133,235,180,206,244,180, 15, 37,109, 98,123, 63, 51, 81, 34,193,210,166,174,207,187, 17, 25,132,193,157, 34,212,118,
+182,150,139,200, 73,154,140, 12, 65, 73, 61,219,141,195, 99, 79,188,168, 90,186,108,233, 16, 66,200, 20, 90,111, 18,206,191,162,
+123, 49,211,100,154,247,131,230,232,209,163, 37, 0,176,126,253,122,225,223,152, 78,169, 84,106,254,250,235,175, 61, 38, 77,154,
+180,203, 90,147,213,228,243,168,102,254,174, 43, 0,172, 54, 89,119,106,102,100,100,124,244,209, 71, 31,225,167,159,126, 2, 0,
+172, 89,179, 6,173, 90,181,186,235,111,207,158, 61,107,247,214, 91,111,125, 4,224,203,198, 52,207,159, 63, 31, 52,103,206, 28,
+252,248, 99,205,204,100, 63,252,240, 3, 34, 34, 34,238,170,121,250,244,105,201,219,111,191, 29, 4, 32,239,175, 62, 71,247,173,
+193, 34,132, 80, 74, 41,105, 98,251,107, 94,246,178,104, 88, 44, 0,112,173,185, 59, 75,205,160, 11, 58,132,203,250,239,221,244,
+101, 79, 27, 5,135,247, 22,190,154, 83, 82,162,139,147,112, 16, 1, 64, 16,193, 57,218, 43,146, 62,122, 57,218,175,172,188, 26,
+ 91, 15,230, 30, 78,189, 70,155, 21, 10, 61,119,133,238, 7,224, 93,247,128, 13, 38, 97, 99,223,222,187,242,199,143, 7, 70, 77,
+ 27,211, 30,137, 7, 50, 95, 70, 19,225, 12,181, 74, 46, 33,249, 27, 81, 38,156, 69,151, 46, 67,113,226,196,245,208, 51,199, 18,
+191, 93,183,110,149,240,212, 99, 35, 37,173, 98, 71,161,170, 36, 13, 89,191,205,129, 46,107, 47, 28, 84, 82,153,181,233,115,119,
+ 34,237,109,109,109, 95,244,247, 10, 72,152,254,230,116,105, 66,194,163, 54, 92,229,121,208,188,245, 16,205,122,136,149, 55,224,
+162,238, 12, 66,224,105,245, 91,146, 66,226,164, 86, 59,153,115, 47,172, 73, 51,235,175,153, 97,200, 23,104,149,150, 16,133,140,
+250,122,120, 65,194,241,142,214,232,216,218,218, 6, 21, 22, 22, 66,167,211,193,209,209, 17, 11, 23, 46,132,135,135, 7, 12, 6,
+ 3, 46, 93,186, 68,125,125,125, 73, 82, 82, 18,124,124,124, 80, 86, 86, 6,147,201,132,170,170,170, 2,147,201,212,104,161, 81,
+109,230,191,122,229,181, 87,122, 5,248,122, 74,106, 35, 88,162, 40, 34,186,109, 48,250,245,238,138, 61, 23, 78, 34,241,108, 58,
+ 68, 42,162,118,125,102, 78,113,165, 89, 20,126,176,186,240, 20,249,154, 72,232, 93, 12, 88, 75,162, 76,237,218, 17,149,160,199,
+ 27, 93, 34,237,159,122,243, 73,127,181, 90,201,161,218, 70, 64,181,201, 2, 93,218, 18,184,250,181,135,202,198,134,196,196, 24,
+164, 0, 44,172, 40, 97, 48,254, 72,199,142, 29, 59,169, 84,170,169, 0,250, 24,141, 70,123, 81, 20,209,171, 87, 47, 29,199,113,
+ 7,171,170,170, 22, 37, 39, 39,183,180,173, 76,237,179,138,222,203,244, 6, 4, 4,160,185, 38,171, 41,180, 90,173, 65,163,209,
+ 52,203,100,213,167,168,168, 72, 18, 30, 30, 14,131,193, 0, 81, 20, 81, 89, 89,137,196,196, 68, 84, 84, 84, 64, 20, 69,216,218,
+218, 98,209, 94, 35, 42, 47,172,198,234,111, 62, 69, 81, 81,145,196, 10, 77, 18, 17, 17,129,234,234,106,240, 60, 15,163,209,136,
+221,187,119,195,104, 52,194, 98,177, 64, 38,147, 97,206,150,155, 48,158, 95,141,239,150,125,130,162,162, 34,242, 87, 95, 43, 86,
+122,144,255,158,193,170, 61,176,191,227, 0, 5,145,159,249,205,247,107,147,222,124,249, 49,188, 52,246, 1,223, 89,159,109,238,
+123,225, 26, 93, 3, 0,109,130,201, 19, 79, 62, 24,230,231,100, 39,195,172,165,201, 0,161, 51,255,236,254,206, 94,163,233,237,
+ 90,145,255,219,124, 32,107,215, 91,227, 98, 16,234,235, 16, 26, 26, 74, 20, 25, 25,180,137, 1,195, 40, 94,122,231,115,240,150,
+ 69,150,215, 38, 61, 44,235,210,247, 41, 68,119,223, 41, 41,189,190, 19,201,155,198,225,187,205,191, 85,201,164,176, 25,219, 91,
+102,245,104,248,110,142, 36,166,107,215,110,187,150,126,179,220,198, 83, 19, 74,136,165, 8,168, 56, 8, 62,127, 55,140,134, 98,
+152, 12, 58,152, 69,123,148,103,239,135, 82, 65,173,190,177, 45, 38,177,228,102,241, 85, 91,137,120,147, 68,180,113,233,137,178,
+253,128,243,104,100,158, 62,114,242,122,161,214, 94, 16,165,165,214,232,232,245,250,107, 22,139,197, 21,128,251,190,125,251,224,
+238,238, 14,157, 78, 7,179,217, 12,131,193, 96,113,118,118, 86,148,148,148,192,104, 52,194,104, 52,194,193,193, 1,201,201,201,
+122,158,231, 27,157, 67, 48,237, 26,221, 17,171, 33,158,251, 21, 80,215,126, 39,145,192,149, 55,155, 78,246,235,209, 14, 41,103,
+ 46, 97,253,182,227,157, 4, 1, 37,181,235, 43, 41, 42, 50, 51,169,209,250,215, 83, 30, 84,248,189, 31, 67,109,227,247,150, 52,
+110,143, 12, 38, 29,149, 74,217,252,185,111, 61, 24,209, 39, 82, 80,146,234, 60, 16, 0, 42, 27, 41,140, 38, 1,142,222,161,160,
+ 38, 29, 53, 84, 87,151,159, 63, 15, 30, 12, 6,227, 15,209,170,194,194,194,197,206,206,206, 35,199,142, 29,107,219,167, 79, 31,
+142,227, 56, 44, 92,184, 16,249,249,249, 14, 3, 7, 14, 76, 88,181,106, 85,191,222,189,123,111,244,240,240,152,108, 77, 84,171,
+222, 51, 75, 6,160,214, 68,208,171, 87,175,242,131, 6, 13,194,213,171, 87,185, 91,198, 75, 4, 96,110,105,251,200,127,163,201,
+202,203,203, 67, 81, 81, 17,250, 15, 29,138, 69,115,231,162,119,239,222,136,143,143, 7, 0,236,221,187, 23, 93,212,199,225,146,
+208, 27, 23, 47, 90, 95,212,221,184,113, 3, 37, 37, 37, 24, 50,124, 56,150, 45, 89,130,152,152, 24,180,110,221, 26, 0,144,148,
+148,132,126, 94,233, 80,135,245, 67, 90, 90,218, 95,126,189,252,157, 30,228, 31,137, 96,253, 93,156, 75,167, 39, 34,131,201, 47,
+143, 61,216,121,240,208,126,145, 88,190,110,223,123,145,145,100, 67,141, 1, 81,206, 28,251, 96, 8, 82,175,150, 97,223,113,237,
+ 47,169,215,232,137,123,177, 79,158,135,159,167,171, 26,224, 20,168, 52,241,188,131, 3,172,190,241,206,101, 22,135, 61, 50,229,
+235,241, 83, 31,249,237,173, 41, 79, 68, 97,245,186,211, 88,240, 83,218,235,102, 51, 86,142,236,229,146, 13, 88,223, 22,205, 94,
+101,251,252,210,111,150,219,120,185,202, 9,178, 22, 65, 48,228, 64,168, 46,129,217,120, 19, 21,229, 55,145,147, 87,140,178, 42,
+ 41,178, 10,136, 33, 55,223,180,218, 90,221,242, 42,233,207, 91, 55,204,123,106,212,200,177,174, 87, 78,124,115,108,203,126,131,
+251, 99,253,127,169, 84,216, 5, 56, 29, 60,177,215,185,220, 32,253,214, 26,157,234,234,234,141,191,252,242,203,163, 1, 1, 1,
+238,231,206,157, 67,117,117, 53, 68, 81,196,224,193,131,129,122, 19, 96,166,165,165, 85, 27, 12,134,194, 11, 23, 46,232,179,179,
+179,171, 0, 44,110, 74,251, 86,131,245,186, 66,165, 77, 16, 25, 29, 25,238, 13, 8, 6,180, 9,243,130, 69, 64,223,139,215,233,
+231, 45, 62,201,212, 82, 19,193, 34,232,222, 54,136, 44, 6, 65,247,228,253, 11,195, 59,246,155,134,230, 68,176, 34, 67,201,128,
+168,112,205,210,133,115,222,116,118,113,247,147, 64, 48,128, 89, 13,222, 77, 0, 0, 32, 0, 73, 68, 65, 84,240, 21, 84, 44, 61,
+ 6,105,229, 21, 56,248, 62, 8,193,177, 59,150,126, 57,191, 82, 16,232,250,250,213,131, 12, 6,163,206, 80,188, 19, 30, 30, 62,
+234,243,207, 63, 87,157, 57,115, 6,149,149,149, 56,126,252, 56,230,205,155,135,145, 35, 71,194,215,215,151, 75, 76, 76,180,123,
+249,229,151, 71, 93,190,124,185, 8,192,172, 38, 30,192,110,174,174,174, 78,197,197,197, 90, 0,242, 91, 38,139,100,102,102, 34,
+ 41, 41,137,139,142,142,166,133,133,133,252,148, 41, 83,156,244,122,125,251,207, 62,251,236, 48,128,130,251, 37,146,181,113,227,
+ 70,156, 62,125, 26, 51,163,163, 49,205,219, 27,174,174,174, 56,120,240, 32, 40,165,176,179,179, 67,105,105, 41,126,252,241, 71,
+196,197,197, 89,157,158,159,127,254, 25, 39, 79,158,196,251, 29, 58,224,101, 27, 27, 56, 58, 58, 34, 41,169,166,195,190, 82,169,
+ 68, 78, 78, 14,246,239,223,143,222,189,123,179, 11,186,133, 88, 29,125,137, 35, 68, 74, 8, 60, 45, 22, 3,204, 60, 5, 33,240,
+142,140, 36,242, 22,185, 58, 14,239, 45,254,118, 27, 85, 74,204, 24, 63, 42,214, 27, 6,140,135, 1,227,199, 13, 15,215,168,148,
+ 82,124,182, 46,149, 74, 57,188,119, 47, 14,176, 93, 16,105,229,226, 96,243,238,131,113,109,145, 93, 96,192,181, 27, 21,187, 82,
+ 82,172, 31,183,233,218, 53,148,229,104,177, 72,111,226, 33,145, 72, 81,110,160,200,201,193,183,133,133, 48, 54, 55, 45, 18, 41,
+ 25,224,169, 9, 37,180, 32, 17,198,155,151, 80,121, 51, 7, 37, 37, 57,208,149,151,160,178, 74, 7,157,174, 10,121,185, 90,236,
+252, 77, 91,198, 87, 11,135,173,213,253,105,119,213, 91,167, 78, 29,190,116,226,216,110, 59, 7,247,246,206,145,129, 74,209,206,
+ 94, 99,127,240,120,170,163,182,176, 58,237,167,157, 85,214,230,229,226,141, 27, 55,150,157, 58,117, 42,205,215,215, 55,219,209,
+209,145, 18, 66,144,151,151,119,219,146,156,156,172,220,185,115,103, 85,118,118,246, 22, 0, 9,205, 29,162,161,125, 40,105,211,
+175, 91,171,217, 67,226,162, 0,193,128,132,184, 54,232,221, 41,104,118,251, 80,210,166,197,254,138,214, 84, 17, 30, 93,211, 47,
+252,232,234,158,227,142,172,236, 18,110,202,253,161,217, 58, 68,196,203,211, 30, 13,116,112,177, 53,113, 68,208,131,200, 28, 1,
+ 85, 40,225,124,159, 32,178,152,149, 36,187, 42, 64, 24,245,196, 99, 69,203,126,216,246,149,155,136, 69,172, 8, 97, 48,238,242,
+ 96,225,184,113, 99,198,140, 81,217,218,218,194,198,198, 6,171, 86,173,194,243,207, 63, 15,165,178,166,207,146, 74,165,130,173,
+173, 45,198,140, 25,163, 34,132, 60,107,133,100,105, 69, 69,133,122,196,136, 17,126, 0, 84, 0,236, 76, 38,147,186,184,184,216,
+129,227, 56,199,182,109,219,122,204,156, 57, 51, 92,175,215,183,223,186,117,107, 33,128,226,150,164,187,188,188, 28, 87,175, 94,
+197,142, 29, 59, 48,113,226,196, 74,158,231, 21,106,181,122,250,159,140,206,200, 60, 61, 61, 85, 26,141,198,149, 82,218,154, 82,
+202, 81, 74,253, 91,162, 37, 8, 2, 58,118,236,136,189,191,158,196,210,245, 71, 48,255,203,149,200,206,206, 70, 68, 68, 4, 68,
+177,229, 29,154, 59,117,234,132,253,251, 15, 97,245,150, 19,152,183,240, 43,228,228,228, 52,216, 38,139,209,204, 8, 86, 83,161,
+185,200, 32,210,206, 51, 74,185,252,237, 97, 33, 17,210,182,239,129, 72,109,177,233,187,173,221,222,252,232,235, 83,237,125,201,
+184,179, 57,180, 89,245,232,103, 51,232,197,182,193,100,253,153,212,136, 71,134,245,246,195,178,245,170, 55, 0,224,145,254,193,
+ 56,145, 90,132,227,231, 11,215, 95,184,214,178, 49,139,106,137, 8, 38,161, 28,197, 83,109, 66, 60, 39, 44,156, 49, 74,229,238,
+166,194,156,175,146, 33, 2,171,173,191,152, 1, 0,190, 0,202,127,143, 83,144,218,104,142,147, 32,162, 89,161, 76,142,208,221,
+249, 89,103, 30,117,229, 92,136,190,162, 24,249,218, 27,208, 85,232,225,228, 32,131,163, 74, 2,141,183, 7, 84,142,190, 16,165,
+ 69, 78,151,174,233, 59, 3,176,122,224,205, 10,139,252,133, 35, 71,246, 28,238, 17, 61,161,186, 77,144,140,151,202, 36, 54, 39,
+ 83, 51,149, 58,131,252,101,107, 53, 40,165, 60, 33, 36,225,208,161, 67,147,143, 30, 61, 58,194,219,219,155,140, 29, 59, 22,131,
+ 6, 13,130, 82,169,132,193, 96, 64, 89, 89, 25,182,111,223, 78,120,158,239, 14, 0,222,222,222,254,129,129,129,223, 17, 66,114,
+175, 95,191, 62,214,154,253, 40, 20,138,249,239, 78, 30, 34,227,205,122,204, 90,188, 29,239,190, 20,143,153, 47,197,201, 18, 38,
+230,206, 7, 48,176, 69, 39, 92,228, 33, 10,213,232,254,228,175, 53,189, 8, 9,186,159,220,245, 65, 56,112,218,106,137,216, 88,
+ 34,147, 72, 73,235, 54, 62, 70,153,144,187, 14,196,198,135, 74, 92,251, 0,234,112, 66,213, 81,248,226,179,119, 43,151, 47, 95,
+190,151,114,152,147,154, 73,211, 88,241,193, 96,220,157,202,202,202, 73,239,191,255,254,202,208,208, 80,219,168,168, 40, 44, 89,
+178, 4, 67,134, 12,169, 51, 87,237,218,181,195,141, 27, 55, 48,107,214,172,234,170,170,170,231,173, 40,155, 68, 66,200,197,164,
+164,164,136,132,132, 4,239,222,189,123,147, 54,109,218,200,148, 74,165,104, 52, 26,237,242,242,242,148,105,105,105, 72, 78, 78,
+190, 90, 93, 93,125,142, 82, 42,180, 36,221,179,102,205,170,116,115,115,179,155, 58,117, 42, 62,249,228,147,220, 95,127,253, 53,
+230,207,230,133,183,183,119, 16,199,113, 98,110,110,238,117, 31, 31, 31,239,156,156,156, 22, 53, 14,175, 13,150,159, 61,123, 22,
+135,210, 69, 40,236,156,145,153, 86,129,189, 63,111,193,152, 9, 19,193,243, 45,111,173,112,250,244,105,172,217,157, 6,175,160,
+ 8, 84,167,157,198,198,141, 27,241,252,243,207,255, 41,205,102, 30, 27,185,111,219, 96,213, 30,224,157, 43, 67, 67,137, 66, 97,
+196, 91, 3,187,249, 76, 27,245, 64,168,132,175,202,131, 40,138,144, 0,112,179,231,240,237, 55, 75,131,214,111,254, 37,169,157,
+191,100, 9, 76,226,172,115, 5,180,202,106, 87, 47,197, 7, 11,190, 63,242,240, 15,179,251, 72,159, 31, 29,225, 12, 0,114, 25,
+135,197,107, 47,240, 68,138, 15,154, 25,165,234, 41,149,113,107, 44,148,218, 82,129,102,251,120, 57,219, 61, 60, 32,214,231,161,
+ 1, 29,209,190,141, 63, 68,222,140,247,191, 76,196,250, 29,103,191, 76,187,222,120,183,255,219, 76, 90,144, 19, 78,106, 10, 94,
+227,164,248,128,212,179, 87,158,158,144,203,165,152,218,202,207, 70,129,102, 52,193,209, 85, 25,190,122,115,250,212,248,183, 95,
+ 26,230, 98,214,169,200,149,204, 50, 64,168,134,157,173, 26,106,175, 94,112,114, 8, 67,117, 69, 30,228,210, 20,149,167, 91,206,
+232,230, 24,172,205, 59,116,233, 47,141,109, 45,121,239,243,147,110,166, 42, 80,222,156,194, 85, 85, 19,186,113, 79, 69, 70, 51,
+ 47,116,139,175,175,239, 68, 81, 20,221,121,158, 55,187,187,187,203,127,250,233, 39,216,216,216,128,227, 56, 68, 71, 71,195,198,
+198,198,164,209,104,202, 1,192,195,195,195,178, 96,193, 2,233,184,113,227,172,138,102, 70, 6, 19,191, 17, 3,218,246,112,117,
+144, 96,229,230,163,216,178,247,226,150, 32, 31,187,225,207, 14,111,139,184,206, 62, 61, 34,131,137, 95,234, 53,122,163,249,119,
+168, 5,245,123, 17,182, 15, 37,109, 58, 13,120,231,174,189, 7, 27, 34,232, 20,196,203, 33, 20,132, 72, 64, 65,128,234, 92,240,
+ 57,171, 33, 9,126,153,110, 78,252,192,176,236,155,229, 31,165,102, 82, 22,181, 98, 48,154,224,204,153, 51,191,116,238,220,249,
+141,177, 99,199,206, 29, 59,118,172,226,233,167,159,150, 28, 59,118, 12,162, 40,162, 99,199,142, 88,190,124, 57,191,110,221, 58,
+139,209,104,156,126,230,204,153, 95,172, 44,155,140,132,144, 51,219,183,111,119,185,120,241,162,139, 76, 38,115, 19, 69,209,169,
+170,170,170,216,100, 50,149,148,149,149, 21, 2, 40,107,105,181,125,117,117,181,205,197,139, 23,143,155,205,102,205,212,169, 83,
+ 91,199,199,199,135,199,198,198,118, 78, 73, 73,105,113, 83, 21,142,227,228,162, 40, 26, 40,165,182,181,187,113,119,119,183, 43,
+ 42, 42,170,108,137,158, 68, 34, 65, 89, 89, 25,116,185, 25,168, 42, 46, 70,107, 73, 21, 58,184,184,195,222,222, 30, 22, 75,203,
+251,218,232,245,122, 40,249, 28, 92, 63,121, 29,197,197,153, 8, 11,234, 0, 59, 59, 59, 24,141,198,191,237,154,185,223,204,213,
+109, 6,235, 15, 15, 66,127, 50,222, 89,142, 79,158, 30, 29, 44, 15, 14,244,129,169, 40, 25,167, 51, 42,241,206,138,206,105, 18,
+185,189,241,165,167,250,119,232, 27,239,142, 62,113,157, 72, 96,192, 59, 47,206,157,251,213,196, 72, 63,242, 86,234, 13,250,165,
+ 53, 59, 62,127,133, 94,111, 19, 68,190, 79, 58,153,251,156,175,155, 1, 20, 20, 73,201,121, 56,155, 94,246,253,197,235,244,122,
+179, 46, 58, 57,183,234, 84,202, 57, 23,240, 6,228,103,252, 18,238,229, 21, 8, 80, 11, 44, 38, 3,142,157, 58,143,229, 63, 38,
+241, 39,207,102,254,223,197, 76,106,213,195, 54, 61,251,230,222,140,156,242,248,247, 39,117,198,224, 30,254, 79,127,180, 34,229,
+177,186,206, 42,148, 98, 80, 71,167,139, 99,250,218,171,108,165, 38,240, 80, 32,229, 74,249, 30,107,116,243,138,233, 41,111, 55,
+242,240,217,179,103,158,241,241,114,140, 31,220,201,214,205,221, 1,114,123,183, 64, 40,236, 92, 32,242,122, 84,149, 94, 6, 21,
+170, 65, 32, 6, 55, 39, 15,252,252,252,122, 78,157, 58,213,102,226,196,137,208,235,245, 88,185,114, 37,150, 44, 89, 2, 63, 63,
+191,158, 55,110,220, 56,220, 28, 45, 81, 20,221,183,110,221, 10,212,180,117,192,190,125,251,160,209,104,224,232,232, 8,157, 78,
+135,177, 99,199, 42,102,204,152, 1, 0, 56,117,234,148,204,214,214,182, 25, 55, 17, 70, 15,234, 17, 76, 32, 24,176, 97,231,133,
+ 18,216,224,153, 77,123, 46,245,120,118,104,176,235,224,174,222,100,251,193,235,163, 1,124,218,252,155, 83, 0, 68,195,109, 81,
+ 82, 52,179,247,224,122, 74,133,200, 96,114,117,221,158, 34,187, 81, 67, 98,108,229, 50,142,208,234, 28,136, 68, 78, 22, 45,249,
+ 86,111, 39,197,183, 96, 48, 24, 86,113,226,196,137, 21, 93,187,118,253,237,187,239,190,123,149,227,184, 30, 70,163,209, 29,128,
+184,123,247,238,124, 65, 16, 14, 25, 12,134,197,201,201,201, 87,154,249, 16,166, 0, 74,110, 45, 87,238,101,122,165, 82,233,143,
+ 21, 21, 21,179, 5, 65, 24,181,107,215,174,249, 35, 70,140,192,207, 63,255,252, 44,238, 62, 82,184,181,101,105, 69, 94, 94,222,
+117, 95, 95, 95,183,128,128, 0,183,202,202,202, 2,165, 82,233, 5, 32,163, 37,122, 74,165, 18,135, 14, 29,194,224,158,189,112,
+102,111, 22, 34, 60,253,208,119,204, 83, 72, 76, 74,130, 68, 34,105,233,113,227,208,161, 67,120,120, 72, 95,108,218,180, 9, 65,
+ 49, 81,120,233,165,151,176,123,247,110, 72,165,108, 54,189,191,196, 96, 17, 17, 51,246,252, 56, 71, 14,209,130, 13,107, 62,193,
+222,147, 85,166,180, 28,188,215, 58, 23, 95,110,128, 78, 44, 40,217,248, 92,151,131, 87, 63,124,246,233, 4, 85,191, 62,253,209,
+175,119, 95,105,219,232, 62,111,160,222,248, 27,132,144,168,198,198,202,160, 34,230, 46,219,152, 54,110,221,142,203, 4,188, 14,
+143, 13,235, 68,169,136,185,141, 70,190, 26,210,228, 13, 64,249,113,108,219,123, 20, 26,207, 92, 92,185,150,133, 77, 59,142,223,
+ 40,215, 85,253, 64, 8, 86, 95,204,108, 56, 42,114,167,102,137,206,244,226,160,151,183,125,241, 72,255,144,254,211, 30,111,143,
+ 45, 11, 30, 84, 92,211,150, 67, 16,120,244,111, 79, 65, 34, 20, 42, 17, 2,142,102, 72,233,178,109,185,137,122,147, 48,205,218,
+116,230, 21,211, 20, 0, 41,193,206,196,225, 66, 58, 6,143,232,229,241, 97,215, 24,193, 67, 95,144,130,188,236,116,220, 52,216,
+ 32,167,132, 0, 20, 87,173, 62,118, 0, 55,110,220, 56,220,169, 83, 39, 0,128,193, 96, 64, 78, 78, 14,120,158,135, 86,171, 61,
+220,220,252,228, 56,174,104,200,144, 33,238, 70,163,145,127,252,241,199,165,197,197,197, 8, 15, 15,175,137,194,233,116,248,229,
+151, 95,234,122,155, 92,184,112, 1,145,145,145, 86,167,211,221,201,118, 76,199, 72, 23, 92,184,156,141, 44,109,197,218,212,107,
+212, 28, 25, 76,214,158,189, 84, 48,185,123, 7, 15,184, 56, 40,198,220,205, 96, 53,164,217, 62,148,180, 1, 65,119,136,150,154,
+ 94,132, 4,221,219,135,146, 54,214,244, 28,188,155,166, 84,138,103,231,255,152, 57,125,253,193,162,132,255,123,174,151,125,143,
+110,131, 21, 16, 45, 84, 95,101,180, 92,184, 70,117, 45,209,252,179, 48, 77,166,249, 95,213, 60,118,236,216, 37, 0,207,253, 23,
+142,125,255,254,253, 83, 1, 32, 54, 54,118,221,166, 77,155,230,172, 92,185, 82,161, 86,171, 59,253, 25, 77,173, 86,123,249,214,
+118, 69, 26,141,166, 77, 73, 73,201,121, 95, 95, 95, 69,115, 52,101, 50, 89, 81,251,246,237,221, 31,122,232, 33,240, 60,143,244,
+244,116,100,101,101, 97,232,179,207,192,217,217, 25,199, 83, 83,145,158,158,142,119,223,125, 23, 70,163, 17,215,175, 95, 47,106,
+ 74, 83, 46,151,155,163,162,162,228,195,134, 13, 3,207,243,200,200,200,192,141, 27, 55,240,242,203, 47,195,209,209, 17,151, 46,
+ 93, 66, 70, 70, 6,102,204,152, 1,163,209,136,172,172, 44,243,223,113,142,254,103, 12, 22, 37, 16, 32, 90, 80,126,114, 38,190,
+222, 6,179, 69, 64,204,133, 28,154, 89,111,147,101, 29,252,200,142,179,231,211, 82, 83,142,247, 83,160,226, 28, 40,208,172,122,
+239,180, 44,154,223, 41, 66,170, 7,175,179, 71,209, 47,184,166,213, 85,166,181, 96,218, 25,193, 44,142,237,208,185,235, 90, 17,
+ 84, 46, 10,116, 61, 15,236,151, 82, 92,187,112, 29,169, 45, 9, 23,231,228, 80, 45,128,135, 2,125, 73,239,173,135, 50,231,142,
+ 27, 26, 17,245,252,168,182,168,170,212, 65, 70,171,113, 62, 95,129, 47,126, 46, 56, 89,162, 51,189,126,227, 6, 77,105, 73,198,
+ 95, 43,163, 21, 0,214, 69, 4, 74,169,206,112,225,237,135,251, 6, 4, 17,184,161,160,168, 28, 27,147,242,142,105, 75, 27,239,
+ 85,211, 64, 4, 11,147, 38, 77,130, 78,167,195,186,117,235,176,107,215,174, 22, 69,176,114,114,114,194, 0, 64,163,209, 20,216,
+219,219, 75,159,121,230,153,218,161, 26, 80, 81, 81,129,146,146, 18,211,212,169, 83, 21, 0,160, 80, 40, 44,131, 6, 13,178,250,
+ 53, 39, 44,192,209, 71, 10, 35, 18,247, 93, 6,164,248,241,214, 85,248,227,150, 3, 89,147,219,183,114, 65,152,191, 67, 72,172,
+134,216, 90, 51, 77, 14, 80, 51, 85,206,201,157,179,194,171,175,204, 0,165, 22, 28, 90,226, 28,222,235,249,178,137,104,225, 8,
+235,103,175, 80, 45,128,201,145, 65,100,197,148, 15,119,190,209, 49, 42,181,251,107,147,134,219, 83,194, 38, 70,103, 48,254, 23,
+ 72, 73, 73,169,136,142,142,126,166, 95,191,126,211,244,122,253,130,123,161, 73, 41,229,189,188,188,242,188,188,188,194,205,102,
+115,179,230, 50, 53,155,205, 47,127,241,197, 23,159, 91, 44, 22,247,218,239,140, 70, 35,214,172, 89, 3,179,217, 12,185, 92, 14,
+149, 74,133,140,140, 12, 72, 36,146, 34,158,231,155,108,119, 43,138,226,213, 47,191,252, 50,196,108, 54,215, 53,237,224,121, 30,
+171, 87,175,134,209,104,132, 82,169,132, 90,173, 70,122,122, 58,228,114,185, 89, 20,197,171,236,202,104,129,169,111,200,127, 68,
+250,147,241,160,120, 11, 20, 4, 28, 62,108,104, 98,231,186,237, 0,220, 57, 1,180, 53, 14,183, 93, 56,233,171,144, 72, 86, 2,
+ 64,181, 40,140,187,112,137,238,249, 55,189,217, 16, 66, 72,128, 47, 70,123,187,217, 45,126,109, 76,180,221, 39, 63,156,169,204,
+ 43,173, 28,151,157, 77,183,223,171,116,250,123,146, 32, 31,103,188,161, 84,192,137,231,145,154, 89,132,213, 55, 10,233,181,230,
+106,106, 52,154,170,128,128, 0,184,184,184,160,180,180, 20, 89, 89, 89,208,106,181,170,150,166,211,199,199,167, 43, 33,100,179,
+ 40,138, 54,119, 70,184,106, 77,152,183,183,183,191, 66,161,184,173,145,123, 99,154,109, 67,201,156,168, 80,231, 73, 23,174,150,
+175, 62,159, 46,212,153,160,200, 32,242,126, 76, 27,183, 23,206,165,151, 46, 59,123, 69,120,179, 57, 17,172, 59, 39,123,182,118,
+236, 43,171,174,207, 96,210, 79,164,152, 2,130,188, 11,215,232, 36, 22,201, 96,154, 76,147,105, 50, 77, 22,193,178,214, 89,255,
+101, 11,128,168,251, 69, 19,128, 52, 48, 16,173, 0, 40,254,229,233,124, 27, 64, 21,128,183,255,173,233,140,137,129,236,127,249,
+ 90, 98,154, 76,147,105, 50, 77,166,121,255, 47,172,218,163, 25, 33, 94,220,227, 70,149,127, 81, 58, 63, 4,240,225,191, 59, 4,
+ 79,217,212, 50, 12, 6,131,193,184,175,225, 88, 22, 48, 24, 12, 6,131,193, 96,220, 91, 8,128,168,187,173,104, 78,221, 42, 33,
+ 36,170,185, 59,110, 74,159,105, 50, 77,166,201, 52,153, 38,211,100,154,247,159,102, 83,218,247, 75,219, 46,242, 87, 78,165,198,
+ 26, 0, 50, 77,166,201, 52,153, 38,211,100,154, 76,243,127, 17, 86, 69,200, 96, 48, 24, 12, 6,131,193, 12, 22,131,193, 96, 48,
+ 24, 12, 6, 51, 88, 12, 6,131,193, 96, 48, 24,204, 96, 49, 24, 12, 6,131,193, 96, 48,152,193, 98, 48, 24, 12, 6,131,193,248,
+215,240,151,246, 34,100, 48, 24, 12, 6,131,193,248, 95,132, 3, 0, 66, 8,189,181,244, 97, 89,194, 96, 48, 24, 12, 6,227,239,
+226,126,245, 32,117, 83,229, 80, 74, 9, 33,132,162,102,240, 81, 6,131,193, 96, 48, 24,140,191,133,251,209,131,112,245, 29, 36,
+128, 56,118,154, 25, 12, 6,131,193, 96,252,157,220,143, 30,228,182, 8, 22, 59,197, 12, 6,131,193, 96, 48,254,110,238, 71, 15,
+194,122, 17, 50, 24, 12, 6,131,193, 96,220, 99, 88, 47, 66, 6,131,193, 96, 48, 24,140,123, 12,139, 96, 49, 24, 12, 6,131,193,
+ 96,252,151, 12, 22, 33, 36,138,105, 50, 77,166,201, 52,153, 38,211,100,154, 76,147, 25, 44, 6,131,193, 96, 48, 24, 12, 6, 51,
+ 88, 12, 6,131,193, 96, 48, 24,204, 96, 49, 24, 12, 6,131,193, 96, 48,131,197, 96, 48, 24, 12, 6,131,193, 96, 6,139,193, 96,
+ 48, 24, 12, 6,227, 31,130, 0,184,107, 79, 0, 74,233,121,171, 69, 90,208,155,160, 41,125,166,201, 52,153, 38,211,100,154, 76,
+147,105,222,127,154, 77,105, 55,199,127,252,171, 13,214, 95, 57,208, 40, 33, 36,234, 94,103, 20,211,100,154, 76,147,105, 50, 77,
+166,201, 52,239, 63,205,251, 13, 86, 69,200, 96, 48,254,215, 8, 99, 89,192, 96, 48,254,106,164,255,212,142, 9, 33, 92, 61,131,
+ 39, 2,160,244, 79,134,211,254, 10,205,127, 43, 4,224,218,204,154, 37, 85,230,229, 53,235, 28, 26,189,189,249,139, 51,103,242,
+180, 38,127, 24,140,255, 28,233,229,135,234,254,111,229,212,155,212,220, 14, 0, 0,122,229,230,175, 13,222,239, 97,142,189, 88,
+230, 49, 24, 13,144,156,156, 92, 21, 16, 16,128,118,237,218, 93,201,207,207,255,138, 82,186,140,229,202,191,200, 96,181,241,180,
+237, 28,224,235, 54,104, 71,114,246,123,141,109, 23, 27, 27, 43, 75, 72, 72, 88, 6, 96, 84,253,239,135, 14, 29,122,219,118, 50,
+153,172,164,172,172, 44,248,192,129, 3,124, 83,251,142,141,141,149, 37, 12, 29,250, 71,205, 97,195,254,160,153,237,226, 18,114,
+106,233, 82,190,222,151,132, 0,132, 2, 20, 0,194,195,195, 15,115, 28,231, 67, 8,105,200,200,213,253,207,113, 53,126, 78, 20,
+197,220,212,212,212,158, 77,165, 83,163,209,196, 3,120,213,138,236,156,175,213,106,247, 54,182,129,195,158, 61, 25,148, 82, 39,
+137, 68, 98,213,249, 17, 4, 1,242, 11, 23,110, 98,230,204, 64,118,233, 51,254,235,180,114,234,205, 13, 29, 58,180, 31,128,186,
+235,249,245,167,230,255, 97, 59,137, 68, 98, 76, 76, 76, 92, 77, 41,101, 47, 21, 12, 70, 3,236,217,179, 7, 19, 38, 76,192,185,
+115,231, 90,237,216,177, 99,145, 70,163,153,152,151,151, 55,136, 82, 90,204,114,231, 31, 54, 88,225, 26,251, 86, 30,174,174, 27,
+ 63,250,224,125, 0,120,175, 49, 35,228,237,237,189,204,207,207,111,208,130, 5, 11,176,109,219, 54, 4, 5, 5, 65, 46,151, 67,
+ 34,145, 64, 34,145,128,227, 56, 72, 36, 18, 76,157, 58,213,233, 86, 26,249,166,204,149,183,183,247, 50, 95, 63,191, 65,243,231,
+207,199,142, 29, 59, 16, 16, 16,112, 87,205,105,211,166, 57, 1,144, 1, 16,234, 4,228,242,218,183, 96,122,203, 52,249,156, 58,
+117,202,221,198,198,166,230,181,152, 82,136,162,120,219, 66, 41,173, 91, 4, 65, 64,175, 94, 86,191, 29,191,154,150,150,214,179,
+178,178,242, 54,141,218,125,212,254,127, 75,175, 81,131,101, 50,153, 92,147, 79, 28, 6, 49, 95, 3,132, 82, 80,206, 5, 80, 4,
+ 3,156,242,174,219,151,150,150, 98,224,192,129,174,236,178,103,220, 15,230, 42, 33, 33,225,129,176,176, 48,205,156, 57,115,144,
+145,145,129,240,240,112, 8,130, 0, 81, 20,111,251, 59,118,236, 88,197,168, 81,163, 8,203, 53, 6,227,118,252, 71, 44, 91, 68,
+ 5,203,248,154, 79, 78, 0,190,129, 78,167,195,115,207, 61,135, 45, 91,182,180,238,218,181,235,108, 0,147, 88, 78,253,131, 6,
+171,149,175,173, 70,165,176,219,186,244,235, 47,136, 69,151,239,212,208,118,132, 16,110,200,144, 33, 95,249,250,250,246, 95,176,
+ 96,129,157, 92, 46,199,165,113,227,112,179,186, 26,166, 79, 62,129,147,155, 27,194, 39, 78,132, 43,207,131, 63,115,198,170,125,
+215,215,156, 63,127,190,157, 92, 46, 71, 78, 78, 14, 76, 38, 19, 60, 60, 60, 96,107,107, 11,133, 66, 81,183, 88,169, 9, 27, 27,
+ 27,236,217,179, 7, 82,169,180,110,145, 72, 36,119,253,236,233,233,217,156,236,154,223,186,117,235,118,233,233,233,246,165,165,
+165,232,218,181,171,142, 16,114,174,118, 37,165,180,221,185,115,231,236,173, 21, 35,230,107,168,204,254, 26, 98,217, 70,192,233,
+ 97, 8, 14,143,162, 26,193,119,125,208,136, 34,123,129,103,220, 23,230,138, 12, 25, 50,164,111,104,104,168,247,156, 57,115,100,
+ 50,153, 12,167, 79,159, 70, 97, 97, 33, 92, 93, 93, 97,107,107, 11,153, 76, 6,137, 68, 2,153, 76,198, 50,140,193,104, 0, 42,
+ 88,198, 71,119,236, 94,247,121,229,158,197, 48, 58,198, 32,247,189,247,176,104,209, 34,180,106,213,170, 35,203,165,127,208, 96,
+ 69, 7, 58, 57, 42,168,124,235,138, 37, 11, 20, 48,235,157, 46,157, 60,130,182,131, 39,214,154,133,243,245, 76, 11, 1,192,201,
+100,178, 71,230,205,155,199,201,229,114, 0, 64, 71, 65,128,198,108, 70,121,100, 36,108,157,156,224,111, 54, 3,102, 51,140,183,
+214,255,225,130,176, 66, 83, 34,145, 64, 46,151, 67, 42,149, 66, 38,147, 65, 46,151, 55,110,176, 42, 43,239,218, 19,162,214, 68,
+237,217,179, 7, 22,139, 5,163, 70,141,186,171,217,106, 42,157,245,209,106,181,123, 53, 26,205, 57, 81, 20,123,138,162, 8, 66,
+200, 57,173, 86, 59,176,118,189, 70,163,137,111,223,190,253,171, 0,230, 91,165, 41,148, 66, 44, 93, 11,251,110,197,168,248,205,
+ 13,196, 46, 30, 2, 2,112,244,108, 22, 14,166,100,161,168,180, 2, 81,193,110,120,100, 96,212, 93, 13,214, 95,209, 11,132,105,
+ 50,205,191, 88,147,200,229,242,192, 57,115,230,144, 90, 3, 85, 27,161,174, 53, 86,181,255,215, 86,225,223,161,185,145,229, 39,
+211,100,154, 0,145,200,150,157, 73, 62, 58, 30, 0, 42, 46,110,194,148,199,187, 67,167, 75,199,164, 73, 51,144,155,155,139, 43,
+ 87,174,156,254, 59,211,121,223, 26, 44, 66, 8,165,148, 54, 43,140,238,235, 75,108,236,121,213,198, 47, 23,125,228, 96,111,175,
+114, 75,222,157,136,172,172,252, 70,127, 35,138, 34,253,229,151, 95,112,121,252,120,116,224,121,148,205,155, 7,162,209,160,237,
+240,225,144,155,205,168, 56,113, 2,114,181, 26, 10,181, 26, 13,181,129,106, 72, 51, 71,171,133, 84, 42,133, 90,173,134,157,157,
+ 29,148, 74,101,157,177,146,203,229,144,203,229, 86,107, 82, 74, 33,149, 74,113,254,252,121,100,101,101,193,201,201, 9, 71,142,
+ 28, 65,124,124,252,109,230, 74, 34,145,128, 16, 98,181,110,125,125, 65, 16,238,106,192,208, 68,213,224,237,103,208, 21,112,121,
+ 18,186, 99, 26,192,121, 12, 44,212, 9, 34, 21,145,124,169, 0, 95,207,122, 18, 0, 16, 51, 98, 22, 70,245,143,100, 17, 44,198,
+125,131, 32, 8,184,124,249, 50, 46, 94,188, 8,137, 68, 2, 7, 7, 7,216,217,217, 65, 38,147,213, 45, 28,199,177, 8, 22,131,
+209, 8,217,155,199, 79, 37,132,204,245,247,247,223,245,213,156, 57,161,241,241,241, 0,128,189,123,247,226,187, 39,158,192,123,
+192,227,139, 9,201,159, 76,233,187,127,117, 90, 90,226, 65,254, 19, 6,171,246,192,154,115,128,132, 16, 18,234,233,240,195,172,
+183, 95, 12, 12, 8, 14,241, 60,190,253, 39, 92,187,150,139,130,130,178,134, 12, 5, 37,132,136, 0,104, 96, 96, 32,202,170,171,
+161, 49,153, 32,209,104,160,118,117,133,244, 86,228, 74,102,103, 7,185, 90, 13,121, 3, 17,172,198, 52,171, 77, 38, 40, 20, 10,
+168,213,106,168,213,106, 40,149, 74,200,235,153, 43,107, 52,235,153, 54, 72,165, 82,156, 61,123, 22, 61,123,246,132,159,159, 31,
+126,252,241, 71, 12, 28, 56,240, 15, 81,172,230,154,171,187, 25,172,122,141,223,155,108,220,126, 27,138, 80,240,246,143,128, 83,
+ 61, 0, 51,117,128,145,122,215, 84, 9,242, 34, 62,221,116, 13,151,179,139, 33, 8, 98, 93, 53, 33,131,113, 31, 64, 9, 33, 52,
+ 34, 34,130,148,148,148, 64, 38,147,213,153,171,214,173, 91, 35, 55, 55,183,206, 92,213, 70,180, 24, 12,198,221,145, 72, 36,179,
+ 19, 19, 19, 67,109,108,108,240,225,135, 31,194,222,222, 30,199,102,207,198,183,114, 57,108, 1,124,101, 54,191, 10,224, 47, 53,
+ 88, 45,241, 32,255,169, 8, 86,115,241,241,241,249,168,107,207,174, 61,131,219,116, 82, 30,223,185, 9,233, 87,178, 80, 92, 92,
+ 14, 74, 97,104,172, 96, 4, 0,153, 76,134,170,247,223, 71, 89,187,118,136, 26, 57, 18, 82,179, 25, 21,199,142, 65,174, 86, 67,
+ 21, 19, 3, 98, 50, 65, 86, 80, 96,117, 97, 91,171,233,238,238, 14,185, 92, 14,165, 82, 9, 27, 27,155,154, 8, 86, 61,115,213,
+ 92,131, 85, 81, 81,129,235,215,175, 99,194,132, 9, 80,169, 84, 32,132,160,176,176, 16,254,254,254,144, 72, 36,200,205,205,197,
+254,253,251, 17, 20, 20, 4,133, 66,209,172,139,162, 94,227,246,118, 26,141,102, 23,165,180,221,169, 83,167,236, 99, 99, 99,209,
+172, 8, 22,145,195,136, 0, 8,240,133, 72,127, 55, 82,150,122,102,138, 82,214, 6,139,113,255,112,229,230,175,244,255,158, 94,
+ 0, 0,112,119,119,175, 51, 82, 33, 33, 33,183, 69,174,152,185, 98, 48,154,166, 85,171, 86, 29,124,124,124, 48,117,234, 84, 84,
+175, 93, 11, 61,128, 4, 0,137,102, 51, 0, 64, 13,188,201,114,233,111, 52, 88,126,126,126,147,162,163,163,159, 89,246,253,106,
+187,185, 51, 94,215,149,167,158,231,140,213, 38,187,106,139,197,116, 77, 91,250, 85, 99, 17,167, 97,195,134, 65, 34,145, 64,237,
+236, 12, 91, 71, 71,200,107, 35, 87, 42, 21,228,106, 53,136,201, 4,106, 50, 65,110,101,104,191,190,166,141,141, 13, 20, 10,197,
+ 93,141, 85,115, 13,214,205,155, 55,241,211, 79, 63,161,115,231,206, 80,169, 84,144, 72, 36,104,223,190, 61, 82, 83, 83, 17, 28,
+ 28, 12, 0, 72, 76, 76,196,195, 15, 63,140,244,244,116,180,105,211,198,174,185, 6, 75, 16, 4,236,217,179,199,158, 82,218,147,
+ 82,138,162,162,162, 22,157, 68, 65, 16, 80, 90, 90,138, 45, 91,182,160,160,160, 0,238,238,238,168,208, 57,162,182, 87,186, 40,
+254,222, 11,146,193,184, 95, 16, 69, 17,182,182,182, 72, 73, 73,193,163,143, 62, 10, 0,176, 88, 44,112,115,115, 67,112,112, 48,
+ 6, 13, 26,132,129, 3, 7,178,140, 98, 48, 26,123, 97,185,114, 37, 57, 43, 43, 43,124,198,140, 25,248,206,199, 7,246,246,246,
+120,101,230,204,227, 60,207,247, 99,185,115, 15, 12, 86,115, 66,115,126,126,126,195,188,188,188,102,175, 94,189,218, 86,171,213,
+194,167, 85,148,253,182, 13,235,141, 30,106,185, 33,183,236,230,132,179, 57,186,196,166, 52, 56,142, 67,235,105,211, 16,100, 54,
+163,228,232, 81, 40,212,106,168, 59,117, 2, 49,153,160,200,204,132, 92,173,134,196,214,182, 89, 7,194,113, 92, 77,149, 96,173,
+153,170, 87, 53, 88,107,182,238,214,224,245,110,152,205,102,199,248,248,120, 60,240,192, 3, 24, 57,114,100, 93, 85, 96,135, 14,
+ 29,176,110,221, 58,140, 24, 49, 2,103,206,156,129, 70,163, 65,235,214,173,209,186,117,107, 36, 37, 37, 53, 43,189,181,195, 50,
+ 12, 24, 48, 64, 71, 8, 57, 71, 41,109,119,242,228, 73,251,150,156, 68, 81, 20,177,101,203, 22, 60,246,216, 99,104,213,170, 21,
+142, 29, 59,134,233, 51, 62,132,163, 71, 0,120,206, 29, 0,101, 85,132,140,251, 14, 65, 16, 26,108,200, 94, 91, 38, 48, 24,140,
+ 38,239,163, 25,195,135, 15,143,253,240,195, 15, 91,191,242,202, 43, 0, 0,141, 70,211, 69,163,209,164,252, 93,227, 96,221,143,
+213,131,117, 6,203,154, 3,236,211,167,207,151,130, 32, 12, 85,169, 84, 78,207, 61,247,156,185,184,184, 24,155, 55,111,198,183,
+223,126, 91, 85,105,225, 78,151,151, 10,207,101,228,234,114,173, 53, 67, 54, 60, 15,152,205,144,223,106,115, 5,163, 17,212,108,
+134, 76,173,134, 84,165,106,246,129,112, 28,119,215,136,149, 82,161,128,236,214,120, 88,214,162, 80, 40,202, 15, 31, 62,236,158,
+147,147,115, 91,131,246,160,160, 32, 0,192,137, 19, 39,112,236,216, 49, 60,246,216, 99,144, 74,165,144,203,229, 56,123,246,172,
+190,185,166, 72, 16,132,186, 94,132, 26,141, 38,190,115,231,206,119,237, 61,104,141, 86, 78, 78, 14, 90,181,106, 5,163,209, 8,
+123,123,123, 20,231, 93,199,213, 43,233,168, 48,164,194,223, 93,133,194,194, 66, 40,149, 74, 86,154, 48,238, 43, 36, 18, 9,122,
+247,238,141,226,226, 98,184,185,185, 65,169, 84,162,188,188,252, 54,227,181, 98,197, 10,150, 81, 12,198, 93,240, 31,177,108,145,
+239,208, 47,199, 3,192,171,159,237,195,219,179, 23, 98,204,200,129,120,230,153,103,254,246,113,176,238,251, 54, 88, 13, 29, 88,
+ 92, 92,220, 24, 23, 23,151,209,207, 62,251,172,237,137, 19, 39,240,193, 7, 31, 72,247,236,217, 99, 62,121,242, 36, 47,138,226,
+155, 57, 57, 90,171, 75, 48, 66, 8, 56,142,131,126,251,118,232,188,188,224,208,177, 35,136,217, 92, 19,185,178,183, 71,165,143,
+ 15, 96, 52,194,177,188, 28,205,213,172, 29,146,161,254,176, 12,178, 91,195, 53,180,164,224,190,219,184, 87,147, 38, 77,194,178,
+101,203,208,173, 91, 55,132,133,133, 65, 42,149,130,227,184, 22,245, 34,172, 95,101,215,236,222,131,119,188,201,251,249,249, 33,
+ 37, 37, 5, 78, 78, 78,248,246,219,111,225,225,238,142, 73,195,195, 97, 50,153, 96,177, 88, 80, 89, 89, 9, 65, 16,112,159,206,
+ 28,196,248, 31, 68, 20,197,219,218, 92, 21, 23, 23,195,215,215,183,209,168, 22,131,193,168,247, 28,170, 63, 14, 86,199,238, 56,
+178,105, 30,214, 93,246, 71,238,236,217,255,200, 56, 88,247, 91, 4,171,201, 82,168, 71,143, 30,234,178,178,178, 79,159,122,234,
+ 41,219,202,202, 74, 20, 23, 23,163,184,184, 24,199,143, 31,223,111, 50,153, 58,229,228,228,172,104,196,248, 68, 53,100, 94, 92,
+ 60, 60,160,176,183, 7,169,215,123, 80,166, 82,213, 68,178, 76, 38,160, 1, 35,208,152,102,125,115, 85, 91, 69,104,149,185,178,
+179,187, 77,147,227,184,186, 97, 26,238,236, 49,232,231,231,135, 57,115,230, 96,248,240,225,183, 13,211, 96,109, 58, 53, 26, 77,
+ 60,165,180, 93,237, 3,226, 86, 35,247,120, 43,141,100, 84, 67, 6,107,240,224,193,216,182,109, 27, 94,123,237, 53,100,102,102,
+ 98,196,136, 17, 32,132,192,209,209, 17, 94, 94, 94,112,118,118,134,141,141,205, 31,210,218,144,230,159,129,105, 50,205,191, 75,
+179,126,131,118,181, 90,141,170,170,170, 38,205, 21, 33,100, 36,203, 79,166,201, 52,235,198,193,194,153,228,163, 56,248,253, 43,
+120, 49, 33, 8, 35, 2,211, 49, 99, 70,211,227, 96,253, 21,233,188,223,104,210,125, 84, 84, 84,188,219,186,117,107,249,197,139,
+ 23,145,145,145,129,203,151, 47, 67, 16,132,171, 57, 57, 57, 45, 46,164, 56,142,131,163,163, 35, 20, 10, 5,164,185,185, 53,109,
+164,212,106, 0,168,137, 92, 81, 10,210,204,234, 44,142,227, 32,149, 74,127, 31,243,234, 86,161,219, 82, 4, 65,168, 27,161,189,
+118,156,171,218,133,227,184,186,165, 5, 67, 52,188,122,252,248,113,251,172,172, 44, 80, 74,177,121,243,102,251,135, 31,126,248,
+213,150, 70,175, 10, 11, 11, 97, 54,155, 33,147,201, 48,120,240, 96,116,239,222, 29,122,189,190, 46, 90, 69, 8,129, 84, 42,101,
+189, 8, 25,247, 29,181,109,176,234,143,218,206, 34, 87, 12,134,245,100,111, 30, 63, 21,192, 84, 66,200,232,153, 51,103,126,247,
+194, 11, 47, 64, 20, 69, 36, 37, 37, 97,201, 27,111,224, 61, 65,120,124, 49, 33, 85,147, 41,157,202,114,235, 30, 26,172,174, 93,
+187, 6,232,116,186,101, 60,207,183, 23, 4, 65,113,240,224, 65, 84, 87, 87, 35, 53, 53,213, 32,138,226,230, 22,239, 80, 42,205,
+159, 60,121,178,175, 53,219,202,229,242,155,104, 98, 30,194,250,154,212, 10,179, 35,151,203,111, 26,189,189, 27,213, 20, 69, 49,
+183,254,220,130,181, 38,234, 46,209,159,250,133,125,174,149, 89, 48,191,107,215,174,127,248,174, 37,121,169, 80, 40,114, 18, 18,
+ 18,188,154,243, 27,185, 92,158,207, 46,123,198,127, 29,185, 92,110, 24, 59,118,172, 85, 61,119, 37, 18,137,105,195,134, 13,172,
+110,156,193,104, 0, 27,185,252,241, 23, 95,124, 17, 63,252,240, 3, 54, 47, 90,132,129, 57, 57, 88, 39,151,195, 86, 46,199, 87,
+102,243,120, 0,204, 96,221, 75,131, 85, 94, 94,254, 94,105,105,105,231,138,138, 10,254,234,213,171, 6, 66,136,192,113,156, 65,
+ 20,197,143, 4, 65, 88,222,210, 29,110,220,184, 49,252, 94, 31, 68,173, 38,177,162,202,211, 26, 82, 83, 83,123,254, 85, 25,254,
+103,218, 90,221,201,111, 71,143, 70,176, 75,152,241,191, 70,152, 99, 47,172, 95,223,107, 45,203, 9, 6,227,222,112,250,220,185,
+120, 0, 24, 60,120, 48, 12,175,190, 10, 0, 88,121,107, 28, 44,123, 96,217,191, 36,153,157, 0,184,223,250,191, 24,192, 37, 0,
+177, 0,108, 1, 24, 1,232, 1,184,213,219,190,228,214,186,218,245,191, 2,176,252,157, 9,110,208,144, 92,186,116,233,233,162,
+162, 34,123,147,201,228, 44, 8,130, 27,207,243,158,102,179, 57,136,231,249,101,148,181,148,254,199,161,128,248,103, 22,150,131,
+ 12, 6,131,193, 0,128,240,240,112,149,155,155,155, 42, 60, 60, 92,245, 14,165,183, 45,255,162,234, 65,119, 66,200, 54, 66,200,
+182, 55,223,124,179, 47,128,238,111,190,249,102,231, 91,159, 59, 2,112,171, 93, 79, 8,217, 6,192,245,142,245,209,127,119,130,
+239,183, 6, 11,180, 69,139,217, 92,251, 63,131,193, 96, 48, 24,140,127,235, 67,158,210,132,185,115,231,206, 1, 32,153, 59,119,
+238,156,122,159, 65, 41, 77,168,255,247,142,245,238,127,119, 90, 9,128,168, 6, 14,194,234,153,178, 91,210,155,160, 41,125,166,
+201, 52,153, 38,211,188,131,176, 59, 52, 55, 54,161,217, 88, 71,156,116,150,159, 76,147,105,254, 51,154, 77,105, 55,240,251, 7,
+ 9, 33,219, 40,165, 9,245,255,214, 55, 94,183, 52,183,213,255,255,142,245,219,255,110, 55,248,151, 45, 0,162,152, 38,211,100,
+154, 76,243, 95,166, 57,146,229, 39,211,100,154,255, 62,205, 38,150, 7,107, 44, 75,195,127, 27,250,191,222,119,127,103,122, 27,
+ 25,166, 97,195, 6,201,141,112, 91,123,165,157, 32, 7, 0, 99,165,196,236,119,217,160,195,168, 81,108,190, 21, 6,131,193, 96,
+ 48, 24,127, 59,132,144,109,111,188,241,198, 91,255,133,180, 74, 27, 50, 87, 69,177, 10, 87, 27,203,205, 48,158, 71,107, 0,176,
+ 81,224, 82, 81,172,125,186,251,134, 13, 37,247,218,100, 13, 27, 54, 76,173, 80, 40,100,235,215,175, 47,251, 55,102, 82,187, 80,
+226, 35, 88, 48, 20, 18, 12, 2, 0, 8,216, 41,145, 97,235,185, 12,154,219,204, 11,195,227, 86,212,176,240, 94,108,119,175,127,
+203,184, 63,208,104, 52,182, 0, 18,164, 82,233, 24,103,103,231,142, 37, 37, 37, 31,230,228,228,124,222,194,194, 76, 10, 96,178,
+147,147,211,104, 39, 39,167,192,210,210,210,235, 21, 21, 21, 27, 1, 44,166,148, 54,171, 71, 78,239, 14,100,186, 66, 46,123,182,
+218,108,249,248,240,105,250,109, 92, 44,113,229, 69,204,181,145, 75,123, 25, 77,252, 39,135,206,208,229,205,216, 83,195, 58, 0,
+ 0, 32, 0, 73, 68, 65, 84, 76, 27, 23, 21, 21,101, 35, 8, 2, 81, 42,149,162, 92, 46,167, 10,133,226,206,182,148,252,129, 3,
+ 7,238, 28,150, 37,253,159, 56, 47,241,241,241,107, 40,165,195,121,158,135, 68, 34, 57,184,127,255,254, 33,127, 86, 51, 46, 46,
+ 78, 9, 0, 7, 14, 28, 48,254,199, 30,146, 92, 80, 80,144,250,250,245,235,122, 90, 59, 43, 61,163, 73,186,117,235,150,105, 54,
+155, 27,109, 75, 36,151,203,139,126,251,237,183,192,251,240,240,139,107,171,254, 0, 20, 2,144,220,250,108,186,245,183,160,222,
+119, 5, 13,172,255,231, 13,214,141,112, 91,123, 27,203,205,176,194,252,212, 81,133,218,211, 35, 1,192, 67,211, 97,163,135, 87,
+228,134, 27,225, 78,230,174,145,163,213, 18, 91,178, 72,202,201,218, 87, 27,141,174, 50,153,172,196,196,243,103,165, 22, 50, 85,
+155,186,254, 70,115, 19, 65, 41,253,137, 16,226, 61,116,232,208, 93,162, 40,174,220,190,125,251,165, 22,221,180,113,113, 82,207,
+ 50,215,199, 57,153,116, 8, 64,163, 40, 5, 40,145,158,135,217,188,179,192,165,120, 53,253, 99, 65,219, 32,177,177,196,182,186,
+ 2,241, 16, 49,180, 85,144,103,151,169, 19, 71,186,118,238, 62,208,182,178,202,130, 95,247,111,235,180,124,205,214, 23,219, 6,
+147, 19, 2,193, 86, 91, 71,236, 73, 73,161,134, 38, 10,148,247, 9,193,180, 91,255, 47,164,148,190,251,103,182,179,226,183, 95,
+ 80, 74,223,188,199,133, 98, 91,103,103,231, 47,148, 74,165,157, 68, 34, 73,207,201,201,249,148, 82,122,170,185, 58,126,126,126,
+145, 60,207, 15,151,201,100,177, 22,139, 37, 69, 42,149,110,185,113,227, 70,234,159, 72,151,164, 77,155,208, 39, 37,132,244, 0,
+224, 4,224,166, 64,233,145,139, 23, 51,126,160,148,182,232,101, 32, 46, 46, 78,106,168,172,124, 92, 42,145, 12,166,148, 70,129,
+ 82, 2, 66,206,243, 60,191, 83,101,111,191,250,128,149,215, 82,247,238,221, 47, 91, 44,150,102,141, 85, 38,149, 74,139,124,124,
+124,194,215,175, 95,223,236,180,251,250,250, 62,236,227,227,243, 85,215,174, 93, 85, 29, 58,116,128, 92, 46,199, 39,159,124, 50,
+ 25,192,231,214, 24, 41, 59, 59,187, 81, 42,149, 42, 72,175,215, 95, 51, 24, 12,137, 10,133,162,223,226,197,139,125,186,117,235,
+102, 95, 84, 84, 68, 56,142,243,216,186,117,235, 19,159,127,254,121, 60, 33,228, 65, 74,169,117,249,208,129,116,109, 29,228,253,
+238, 75, 79,244,197,107,115,127,124,169,103, 59, 82,108,107, 39,255,106,100,207, 80,167,200, 16, 39,188,191,244,183,201, 0,172,
+ 54, 88,145,145,145,242,132,132,132, 85,132,144, 7, 9, 33, 13, 62,160, 57,142,211,199,197,197,249, 55,118,190,130,186, 58, 31,
+150, 74,164, 62, 13,173,231, 5, 62,247,250,177,178, 63, 61,116,139, 32, 8,131,150, 47, 95, 14,169, 84,138, 49, 99,198,244,137,
+141,141,181, 77, 73, 73, 49, 88, 87, 30,197,186, 2,120, 5, 0,167, 80, 40, 22, 28, 61,122,180, 40, 54, 54,118,187, 92, 46,143,
+187,181,254, 64, 74, 74,202,131,119,156, 83,242,103,122,124,199,197,197,189, 35,138,226, 68,133, 66,113,163,172,172,108, 92, 74,
+ 74,202,229, 63,155, 7,177,177,177,178,130,130,130,201,237,219,183,127,190, 83,167, 78, 94,169,169,169, 5, 62, 62, 62, 75, 60,
+ 61, 61, 23,167,164,164, 52,105,216, 59,116,232,224,205,113,220,147, 0, 30,191,245, 0,221, 64, 8, 89,157,146,146,114,237,127,
+193, 96,153,205,102,247,148, 25, 51, 0,137, 4,134,190,125, 65, 41,133,106,214, 44,160,184, 24,101,243,231,131,231,121, 12, 30,
+ 60,216,253, 62, 61,252, 19,255,181, 4,223,213, 96, 41,237, 4, 57,207,163,117,161,246,244,200, 46,131, 22, 59, 0,192,241,157,
+147, 71,186,120, 71,166, 42,237,132,116,133, 90,190,246,225,161,241,237, 71, 37,244, 33,190,222, 30,200,201, 43,244, 88,177,110,
+ 87,255,109, 59,147,214, 2,232, 97,101,212,234, 9,139,197, 18,192,113,220, 58,142,227,188, 23, 45, 90, 20,146,145,145, 49,110,
+221,186,117,195,134, 14, 29,122, 68, 20,197,239,182,111,223,254,155,181, 7,226,213, 97,120,132, 23,188,214, 12, 31, 49,196,255,
+193,254,238,138, 0, 47,119,136,162, 18,151,174, 89,252,246, 28, 58,213,127,199, 47,187,167,122, 70, 13,127,178,224,252,150, 11,
+ 77,105, 69,132,144, 71, 85, 74,249, 43,111,188,240,160,215,224, 65, 9,246, 46,190, 49, 82,144,154,201,162, 21, 14,192,136, 39,
+ 95,181, 27,254,196, 20,187,107, 23, 14,251,108,223,177,181,255,234,196, 3,121, 17, 33,100, 65,218, 85,250, 99, 67, 81, 37, 66,
+ 48, 77, 20, 41, 87, 83,232,147, 87,251,247,239, 63,192,198,198,230,182, 2,165,186,186, 90, 70, 8, 34, 69,145,222,122, 56,144,
+105,132,144, 47,173,137, 70,213,238,195,100, 50,114, 50,153, 2, 18, 9, 55, 57, 58, 58,186, 67, 81, 81,209, 1, 0,203,181, 90,
+109,201,159,185, 80, 84, 42,213,179,195,135, 15,159,179,114,229, 74,181,173,173, 45,180, 90,109,248,163,143, 62,218,158, 16,242,
+ 16,165,180,201,130, 87,163,209, 68, 3,120,200,205,205,237,225,113,227,198, 5, 60,240,192, 3, 8, 12, 12,132, 86,171,141, 79,
+ 74, 74,122, 51, 38, 38, 38,187,160,160, 96, 35,128, 68,173, 86,123,166, 57,230, 42, 42,178,213,252, 9, 19, 39, 69,140, 24, 49,
+194, 91,105, 99, 43,205,201,201, 44,250,230,235, 37,142, 18,194,181, 39,132,188,218, 92,147,213,165, 75,151, 8, 34,138,107,159,
+127,246,217,192,142,221,187, 75, 61,189,189, 81, 93, 94,142,140, 75,151,252, 78,158, 56, 17,191,101,239,222,105,177,177,177, 99,
+ 82, 82, 82,154,188,150, 76, 38,147,239,161, 15, 63,132,196,205, 13,212, 98, 1,223,166, 13, 68, 81,172,153, 71,239,240, 97,192,
+ 98, 1,181, 88, 96,233,223,191,110,126,202, 97,195,134,121, 20, 23, 23,203, 0, 52, 43,221,126,126,126,222, 97, 97, 97,203,223,
+124,243, 77,185,209,104,196,233,211,167,113,244,232, 81,177,168,168,104,126, 83,230,138, 16,178,117,230,204,153,154,158, 61,123,
+218,151,148,148,128,231,121,215,196,196,196, 9,177,177,177,246, 62, 62, 62,138, 85,171, 86,213,206, 16,224, 28, 18, 18,226,252,
+248,227,143,155, 86,173, 90, 53, 25,192, 2,171, 10, 26,130,217,143, 14,235, 15,131,133,131,197,194,187,123,187,219,255, 48,121,
+108, 31, 25,168, 9, 43,127, 62, 5, 11, 47,126,219, 28,115, 21, 28, 28,188, 50, 56, 56,184,239,220,185,115, 73, 70, 70,134,164,
+205,173,124,229,121, 30,130, 32, 64, 16,106,178,110,204,152, 49,234, 91,229, 92,131, 6, 75, 42,145,250, 28,222,116,193, 93,165,
+ 82,213,253,182,118, 50,246,202,202, 74, 12,122,170,107, 75,162, 85,126,148, 82,255, 59, 12, 22, 87,219, 54,195,100, 50,193,198,
+198,166,215, 3, 15, 60, 80,117,203, 84,151,237,218,181,235, 98, 35,146,207, 63,247,220,115, 83,212,106, 53, 22, 45, 90,212, 47,
+ 50, 50, 50, 78,169, 84,198,237,219,183, 15, 0,208,171, 87,175,184,206,157, 59,187,240, 60, 63,148, 16, 50,194,193,193,161,103,
+ 76, 76,204,225,232,232,232, 39,207,156, 57, 83,222,220,244,119,236,216,241,225,168,168,168,151,231,205,155,103,119,225,194, 5,
+231,247,223,127,127, 45,128, 14,127,166, 12,137,140,140,148, 87, 86, 86,174,121,239,189,247, 6,215, 78, 53, 38,138,162,231,175,
+191,254,250,254,107,175,189,214, 53, 54, 54,246,177,134, 76, 86,167, 78,157,218, 83, 74,103,132,132,132,196, 63,245,212, 83,146,
+ 30, 61,122, 64,175,215, 99,247,238,221,255,183,105,211,166,255,139,137,137, 57, 70, 41,125,255,244,233,211,135,238,213,195, 49,
+ 54, 54,246, 18, 0,191,218,184, 67, 74, 74, 74,235,127,197, 83,219,222, 30,232,219, 23, 21,121,121, 53,101,243,188,121, 53,101,
+205,156, 57, 44,196,247, 95, 48, 88, 77, 81, 85, 85, 21,253,230,228,177,224,184,154,145,204,195,130,253,241,209, 91, 19,200,150,
+109,187,172, 30,103,162,180,180,116,198,227,143, 63,238,189,101,203,150,231, 56,142,179, 41, 44, 44, 36, 85, 85, 85,182,211,166,
+ 77,243,213,233,116, 35, 18, 19, 19,123, 15, 27, 54,236, 28,165,244,147,173, 91,183, 38, 55,166,229, 30, 61, 50,212,195,205, 99,
+247,167,179, 39, 56, 71, 5,135,192,100,177, 32,167, 48, 23, 20, 74,120,121,168, 49,230,161,104,121,143,142,178,208,249, 95,236,
+219,229,213,126,104,255,252,179, 91, 27, 43,200, 32,161,120,253,248,137,212, 86, 28, 95, 66,136,204,161,129, 55, 99, 41, 66,219,
+197, 73,159, 15,142,114, 26, 50, 96,144,195,195, 79, 79,123, 29,192,143,141, 61,199,234, 61,208, 48,101,202,148,186,169,120,106,
+ 41, 40, 40,192,254,253,251,238,250, 27,107,253, 70,253, 15, 31,124,240,129, 99,105,105,233,131, 43, 86,172,136,247,246,246,158,
+149,151,151,215,236,194,135, 16, 98, 11, 96, 80,191,126,253,102,111,218,180, 73, 93, 59,122,189,167,167, 39, 22, 44, 88,224,247,
+232,163,143,126, 12, 96, 88, 19,230,234,187,177, 99,199,142,238,223,191, 63,194,195,195, 81, 82, 82,130, 99,199,142,153,150, 44,
+ 89,114,253,129, 7, 30, 8, 26, 61,122,180, 98,202,148, 41,254,153,153,153,175, 38, 38, 38,190,234,236,236,252,109, 89, 89,217,
+203,214,164,175, 77,155,208, 39,199,141, 31, 31, 49,233,249,151, 98,205,102, 99,213,217,148,131,251,165,114, 78,242,210,203,227,
+ 29, 75,203,138,220, 40, 21,159, 4,240,125, 51,204, 85,168,143,167,231,158,185, 31,127,236,228,226,238,142,252,252,124,220,200,
+201, 65,222,249,243, 32, 0,250,247,239,175,136,110,223, 62,100,225,210,165, 59, 59,117,234, 52,224,228,201,147, 23,155,210,148,
+184,185, 33, 55, 38, 6, 0, 80,158,146, 82, 27, 89,129,253,208,161,191,191,153,166,165,129,227, 56,120,120,120,180,100,250,165,
+218, 72,112,151,158, 61,123,202, 1,224,181,215, 94,211, 85, 86, 86,206, 35,132,252,148,155,155,171,109,226,167,147,223,121,231,
+ 29,239,144,144, 16,255, 53,107,214, 64,175,215, 3,128,123,112,112, 48,194,194,194,132,131, 7, 15, 34, 60, 60, 28,246,246,246,
+ 56,120,240, 32,142, 29, 59,134,152,152, 24,181, 92, 46, 31,105,141,193,234, 21, 77,134,116,236, 16,213, 53,192,207, 31, 7,142,
+158,128, 92, 33,115,122,225,169, 4,216,171,165,152,183, 98,187,152,157, 83,250,210,161, 51,116,165,149,215, 35,247,224,131, 15,
+ 46, 15, 12, 12,140,155, 59,119,174, 74, 46,151,227,220,185,115,200,207,207,135,187,187, 59,108,108,108, 32,147,201, 32,149, 74,
+155, 53, 85,150, 74,165,130, 86,171,133,249,214,224,138,130, 32, 64,167,211,193,203,171, 38,248, 56,107, 22,225,102,206,180,174,
+ 42,107,192,128, 1,175,123,120,120,204,240,240,240,144,212,255,222,104, 52,226,141, 55,222,128, 94,175,135,143,143, 15,124,124,
+124, 54,213,206,123, 90, 82, 82,130,254,253,251,207,221,179,103,207,236, 6,100, 29,189,189,189, 49,116,232, 80,152, 76,166,136,
+175,190,250,234,123, 74, 41,170,170,170,234, 54,240,240,240,200,236,213,171,151,164,103,207,158, 8, 9, 9,193,210,165, 75,251,
+110,216,176,161, 55,128,159,155,123, 45, 57, 58, 58, 62, 50,106,212, 40, 59,181, 90,141, 46, 93,186,192,100, 50,105,226,226,226,
+148, 45,169,138, 36,132, 72, 53, 26,141,167, 84, 42,253,108,242,228,201, 3,251,244,233,131,180,180, 52,236,220,185, 19,195,134,
+ 13, 67, 92, 92, 28,222,126,251,237, 65,239,190,251,238,100, 52, 48,171,133, 40,138,171, 55,110,220, 24,232,235,235, 11,137,164,
+ 38, 91, 29, 28, 28, 48,110,220, 56,140, 29, 59, 22, 59,118,236,232, 58,103,206,156,181,113,113,113, 1, 7,154, 81, 83,209,212,
+ 59, 75,202,173,251, 53, 54, 54,214,239,223,242,208, 54,117,235,134,178,188, 60,120,122,123, 3, 0,242,180, 90, 80, 74,235, 62,
+227, 86, 89,195,248,151, 26, 44, 99,165,196,108,163,192, 37, 15, 77,135,141,199,119, 78,174,171, 34,148, 82, 92,170,174,148,152,
+ 1, 64,160, 20, 21,122, 30,182, 74, 14,153,121, 58,156,191, 90,116,183, 2,255,182,174,150,253,251,247,223,170,211,233,194, 93,
+ 92, 92, 22,240, 60, 47,233,219,183,175,164,107,215,174,238, 89, 89, 89, 56,112,224, 0,100, 50, 25, 76, 38, 19,113,118,118, 86,
+142, 27, 55, 78, 99, 48, 24, 92,223,122,235, 45, 55, 0,125, 26,210, 36,163, 71, 75,188,101,146, 13,243,102, 63,238, 76, 36,151,
+113, 57,251, 38, 66,125,187,192,213,209, 15,185, 69,122,164,164,238,192,229,140,237, 8,245,245,199,132, 49, 97,142, 11,191, 46,
+222, 72, 98, 39, 70,209,148,165,150,134, 52, 1, 72, 36,170, 80, 98, 74,122, 88,148,184,245, 33, 18,239, 4, 66,108, 52,183,109,
+ 80, 89,146,137, 75,191,173,164,153,231,126,166,254,209, 79, 18, 0,146,134,142,157, 82, 90, 40,145, 72,150,115, 28, 25, 79, 8,
+ 65,135, 14, 49,133,243,231,207,191,219,155,154,165, 67,135,152, 66,137,132,243,168,153, 71,144, 91, 38,138, 66, 97, 35,233,172,
+191,191, 66, 66,200, 66,133, 66, 57, 13, 0,188,189, 53,133,219,183,111,183,140, 26, 53, 10,159,126,250,169, 98,250,244,233, 51,
+125,124,124,158,202,205,205,205,109,236, 28,213, 43, 20,163, 28, 28, 28, 38,182,106,213,106,216,236,217,179, 21,131, 6, 13,178,
+165,148, 66,167,211, 65,167,211,161,170,170, 10,118,118,118,144, 74,165, 94, 77,157,247,192,192,192,135,199,141, 27, 7,119,119,
+119, 28, 63,126, 28,211,167, 79,207, 42, 42, 42,250, 32, 47, 47, 47,101,237,218,181,173, 67, 66, 66,222, 94,186,116,105, 68,207,
+158, 61,185,161, 67,135, 98,235,214,173, 61,154,210,172, 59, 81,132,244,120,232,161, 17,238, 38,147,161,210,104, 52,148, 95,207,
+ 74,206,203,201,185,112, 51, 60,172,147,199,128,129,221, 92, 46, 93,186,218,163, 33,131,117,167,230,232,209,163, 37,156, 32,252,
+248,241,188,121, 78,156, 84, 10,139,197,130,128,128, 0,156, 59,119, 14, 21,101,101, 48,232,245,184,150,154, 10, 77, 80, 16, 38,
+143, 25,227,244,193,146, 37,107, 98, 99, 99, 59,214,127,235,190, 91, 58,169,197,114,103,181,213, 31,230,204,187,219,119,214,156,
+247, 59, 30, 66,153, 90,173, 22, 42,149, 10, 17, 17, 17,118,201,201,201, 71,115,114,114,180, 77,105,218,216,216,140,236,209,163,
+135,253,218,181,107, 17, 27, 27, 11, 39, 39, 39,236,223,191, 31,231,206,157,131,217,108,230,116, 58, 29,212,106, 53,230,206,157,
+ 11,127,127,127, 84, 84, 84, 32, 51, 51,211, 85, 38,147,185, 89,149, 78,130,103, 70,143,120, 8, 18,185, 29, 46,101,228,160, 79,
+215, 24,120,120,120,224,236,197, 12,100,231,150, 22, 16,130,167, 7,245, 80,206, 53, 24, 76,239,252,122,154,174,104, 72,147,212,
+ 56, 79, 78, 42,149, 62, 52,103,206, 28, 78, 46,151,215,229, 93,237,156,132,181,198,170,118,146,246,187,153,213,187,165,147,231,
+121,152,205,102,152,205,102,136,162,136,162,162, 34, 84, 84, 84,192,217,217,185,102,131,153, 0, 1, 33,180,129, 89,232,239,184,
+223,199,126,242,201, 39, 18,239,218, 7, 94, 61,114,114,114, 80, 94, 94, 14,123,123,123, 56, 57, 57,213, 69,220,138,139,139, 49,
+117,234,212,177, 0,102,223, 77, 83, 42,149,126,242,233,167,159, 14,107,221,186,181,215,179,207, 62, 11,169, 84, 58,168,164,164,
+ 4, 43, 87,174,132, 74,165,194,138, 21, 43, 16, 24, 24, 40, 17, 4, 1, 6,131,161,214, 8, 87, 42, 20,138,204,150, 92, 75,101,
+101,101, 63,108,219,182,173,123,183,110,221, 28, 1, 96,248,240,225,220,150, 45, 91,178,251,246,237,123, 67,167,211, 61, 89,191,
+186,176, 33,205,216,216, 88, 89,126,126,254, 43, 99,198,140,153, 18, 31, 31,239, 80, 82, 82, 2,165, 82,137,159,126,250, 9,203,
+151, 47,223,109,177, 88,102,109,220,184,241,189,111,190,249,166,255,240,225,195,241,205, 55,223,188,112,171, 89,132,120, 23, 77,
+111, 63, 63, 63,156, 61,123, 22,206,206,206,112,115,115, 67,121,121, 57,142, 29, 59,134, 19, 39, 78, 32, 34, 34, 2,132, 16,167,
+198,162,149,141,164,179,197,145,170,230, 12,103,116,175, 52, 75, 75, 75, 81, 94, 94, 14, 57,106, 6,111,188,121,243, 38, 0,212,
+125,110,105, 58, 9, 33, 82, 31, 31,159, 4, 71, 71,199,137, 0, 36,101,101,101, 43,108,109,109, 19, 51, 50, 50, 76,127,215,177,
+223,151, 6,139, 16, 82,123, 94,226, 40,165, 7,253, 46, 27,116, 69,177,246,233, 30, 94,145, 27, 92,188, 35, 83, 1, 64, 74,113,
+137,202,236,211,253,206, 25,116, 0, 96, 54, 83, 28,189, 84,134, 51, 87, 10,112,238, 74, 62,212, 54, 77,191,117, 27,141,198,126,
+ 59,119,238,196,134, 13, 27,230,127,254,249,231, 52, 59, 59, 27, 89, 89, 89,112,118,118, 70,159, 62,125, 80, 84, 84,132,147, 39,
+ 79, 34, 52, 52, 20,148, 82,248,249,249, 41, 0, 56, 54,166,233,121, 69, 28,243,212,132, 14, 65,110,142, 4, 91,143,238, 66,215,
+136, 17, 80, 41,165, 40, 42,171, 2, 71, 8, 50,174,239,133, 32,216,225, 76, 90, 54,186, 71,217,161,103, 23, 7,159,202,125,101,
+207, 2, 88,218,244, 19,203, 2,161,112, 47, 21, 10,247, 81,206,185, 35,145,120, 15, 39,101,229,213, 72,251,237, 91,154,119, 41,
+169,174,172, 53,155,116, 77, 74, 9,130, 48,213,211,211,211,240,198, 27,111,244, 11, 11, 11,179,188,248,226,139,167, 50, 51, 51,
+167,220, 97, 68, 62,251,242,203, 47,145,158,158, 94, 60,119,238,220,253, 5, 5, 5,111, 53,243,198,156, 65, 8,249, 2, 0,180,
+ 90,109,201,182,109,219, 58, 30, 60,120,240,213,133, 11, 23,122,189,244,210, 75,138,151, 95,126,121,124,205,163,162,201, 27, 45,
+ 58, 46, 46,110,231, 15, 63,252, 96,231,229,229, 69, 8, 33, 48,155,205, 40, 42, 42, 66, 81, 81, 17,202,203,203, 81, 89, 89, 9,
+189, 94, 15,142,227,154,108, 47,167, 82,169, 36, 21, 21, 21,184,121,243, 38, 58,119,238,140, 19, 39, 78, 4, 28, 57,114,100,249,
+215, 95,127, 45,142, 29, 59,150,196,197,197,145,226,226, 98,108,218,180, 73,204,207,207,231,108,108,108,244, 86,191, 29,115,112,
+ 82,169,108,229,191, 29, 73,220,169,205, 73, 45,206, 43, 56, 95,206,129,114, 90,109,114,121,112, 88, 95, 87,212,180,201,178,138,
+107,215,174, 61, 54,109,210,164, 96, 71,103,103,240, 60, 15, 55, 55, 55,228,228,228,160,170,170, 10, 85, 21, 21, 48,232,245,168,
+174,168, 64,218,190,125,232, 54,100, 8, 6,116,232,224,183,253,212,169,103, 0,124,211,152, 46,223,166, 77, 93,228,202, 49, 54,
+246,247,251, 33, 53,181,206, 88,201,122,244, 0, 81,169, 64,222,106,121,231, 24,173, 86,123, 38, 32, 32, 96,215,160, 65,131, 6,
+ 78,152, 48,129,203,207,207,223,226,229,229,213, 47, 63, 63, 63,173,177,223,169,213,234,224,226,226, 98,232,116, 58, 56, 57, 57,
+ 97,225,194,133,240,240,240,128,193, 96,192,201,147, 39,169,175,175, 47, 73, 74, 74,130,143,143, 15, 74, 75, 75, 97, 50,153, 80,
+ 85, 85, 85, 96, 50,153, 12,214, 93,152,240,241,244,242, 5, 71, 45,208, 22, 20, 99,248,144, 1,144,202,213,200,204, 41, 70,116,
+100,136,247, 19, 67,123,120, 75, 8,143,255,251,120,237, 11, 0, 86, 88, 97, 36,105,122,122, 58, 82,111,229,159,131,131, 3,236,
+236,236,106, 38,121,151,203,235,204,149, 84,106,125,128,190,118,114,244, 90,115, 85, 84, 84,132,140,172,203,216,148,180, 10,102,
+193,226,250, 93, 23,135,235, 33, 50,217,121,119, 61,153, 89,116,150,158,105,226,254, 89, 53,125,250,244,247,220,221,111,111, 10,
+227,231,231,135,137, 19, 39, 98,219,182,109, 72, 79, 79,191,173, 59,119,105,105,169, 8, 96, 85, 67,154,199,143, 31, 47,236,210,
+165,203, 35,175,188,242,202,222, 85,171, 86, 41,198,140, 25, 83, 87,157, 41, 8, 2,244,122, 61,246,237,219,135, 67,135, 14, 33,
+ 57, 57,185,204,108, 54,255, 44,145, 72,150, 28, 63,126, 60,173,185,215, 81,183,110,221,156,213,106,245,135, 47,188,240,130, 61,
+ 0, 84, 87, 87, 99,204,152, 49,182,143, 60,242, 8, 82, 82, 82, 34, 62,255,252,243,149, 0, 58, 55, 85, 29,200,113,220,250,164,
+164,164,248, 86,173, 90,213,188, 61, 90, 44, 56,114,228, 8, 38, 76,152, 80,170, 82,169,198,166,166,166, 86,250,248,248,188,183,
+109,219,182,254,209,209,209,104,215,174,157,103,113,113,177, 26, 64, 69, 3,231, 29,130, 32,212,157,159, 21, 43,126,191, 84,170,
+171,171,107,162, 59, 38, 19,233,220,185,115,224,137, 19, 39, 50,239, 65,164,234, 70,189,207, 55,254, 45, 15,237,170,213,171, 33,
+155, 62, 29,151,143, 28, 1,165, 20,110,145,145, 0,128,203,135, 14,213, 12,159,240,202, 43,205,210,243,241,241,113,161,148, 62,
+ 19, 31, 31,255,210,160, 65,131,220,188,189,189,225,234,234,138,115,231,206,117,219,181,107,215, 2, 31, 31,159,229,148,210,229,
+ 90,173,246, 47,203,131, 59, 61,200,125, 23,193,162,148,146, 91, 7, 73, 48,106,148,224,190, 97, 67,201,141,112, 39,179,210, 78,
+ 72, 7,128,234, 74,137,217,239,220,173, 97, 26,102,175, 5, 5,133, 32, 80, 80, 81,132, 72, 41, 4, 43,130,231,174, 14, 22,112,
+231,157,241,120,215,225, 24, 59, 54,153,236,219,183, 15, 7, 14, 28, 64,116,116, 52, 44, 22, 11, 28, 28, 28, 48,122,244,104, 36,
+ 38, 38, 66,165, 82,161,178,178,178, 73, 77,181, 11, 63,162, 75,187, 48,201,229,236,115,232,216,106, 36, 2,189,123, 34, 35,183,
+ 28,101, 58, 35, 74,202, 13, 8, 15,127, 29, 5,165, 6, 84, 84, 26,112,246,210, 26,248,122, 7,115,156,236,106,127,171, 12, 86,
+189, 39,132, 88,118,146,138,101, 39,233,190, 93,127,108,110,196, 27,173,107,226, 32,138,226,226,157, 59,119,118,235,217,179,167,
+ 52, 62, 62, 62, 38, 32, 32,160, 67, 86, 86,214,105, 0, 8, 8, 8,232,208,191,127,255, 24, 15, 15, 15,124,246,217,103,213,162,
+ 40, 46,110,225,219, 79,253,246, 90,199,253,252,252,102,109,222,188,249,235,137, 19, 39,194,219,219,187,189, 53, 26, 78, 78, 78,
+227, 87,174, 92,105,231,237,237, 77,120,158, 71,117,117, 53,242,243,243,113,243,230, 77,148,149,149, 33, 59, 59, 27,165,165,165,
+200,203,203,171,204,204,204,220,104,109,218,222,121,231, 29,240, 60,111,153, 48, 97,130,172,111,223,190, 88,181,106, 21,119,237,
+218, 53,124,243,205, 55,194,250,245,235,179, 56,142,147,142, 28, 57,210,191,121, 7, 76,138,115,114,174,185, 27,205,101,213,131,
+226,186, 79, 43,202, 44,134,123,224,112,236,253,117,227,103,217,153, 25,148,112,176,186,237,153, 82, 38, 27, 16,219,181,171, 44,
+ 63, 63, 31,161,161,161,200,205,205,197,149, 43, 87, 96, 50,153, 80, 89, 94, 14, 75, 69, 5,132,178, 50,208,138, 10,100,254,250,
+ 43,218,132,134, 42,118,158, 58,213,191, 41,131, 85, 91, 45,220, 80,212,138,227, 56, 16, 59, 59,192,206, 14,148,107,222,228, 10,
+ 26,141, 38,193,193,193,225,149,138,138,138, 93, 90,173,246, 99,179,217,252,202, 71, 31,125, 20,251,254,251,239,187, 78,159, 62,
+221,126,250,244,233,171, 3, 3, 3,187,101,102,102, 54, 88,181,163,215,235,175, 89, 44, 22, 23, 0, 30,123,247,238,133,187,187,
+ 59,116, 58, 29,204,102, 51, 12, 6,131,217,217,217, 89, 89, 82, 82, 2,163,209, 8,163,209, 8, 7, 7, 7,164,164,164,148,242,
+ 60,191,195,154, 52,218,218,216,184, 42,108, 28, 33,242,213,144,202,100,240,247, 11,132, 40, 24, 81, 86, 81,133,167, 31, 25,138,
+ 83,231, 82,177, 35,233, 56,111,177, 52,126,205,211,154, 66, 74, 36,132,208,240,240,112,220,188,121, 19, 18,137, 4,118,118,118,
+ 80,171,213,136,136,136,192,141, 27, 55, 90,108,176,234,155,171,125,191,109, 67,145, 62, 15,203,230,173,133,143,151, 31, 7,192,
+ 45, 55,255, 70,191,103, 95, 29,221, 41,168,167,203,188,235,135, 75, 27,108,215,182,123,247,238,121, 3, 6, 12,216,150,159,159,
+239, 86,239, 92,119,179, 88, 44,239,242, 60,143,204,204, 76, 92,188,120,241, 19, 74,105,210,239, 33,115, 73,238,158, 61,123, 26,
+ 53, 5,199,143, 31, 63, 21, 27, 27,251,236,232,209,163, 23, 4, 6, 6,122, 80, 74, 17, 29, 29,141,199, 31,127, 28,243,230,205,
+195,175,191,254,186, 65, 20,197,239, 28, 28, 28,142, 22, 21, 21, 73, 26,138, 60, 52, 70,231,206,157, 93,148, 74,229,193, 47,191,
+252, 50, 32, 36, 36,132,211,106,181,248,237,183,223,208,173, 91, 55, 16, 66, 16, 22, 22, 6,139,197,226,211,148,185,162,148,254,
+180,121,243,230,248,144,144, 16,164,165,165,225,208,161, 67,112,119,119,135,173,173, 45,134, 14, 29,234,242,211, 79, 63, 77,140,
+140,140,252, 92, 42,149,190, 59,100,200, 16, 8,130,128,228,228,228,252,235,215,175,235, 27, 59, 71,141,188,188,131, 82, 10,139,
+197,242, 9,199,113, 35, 59,117,234, 52,244,228,201,147,201,127,230,225,248,175,105,115, 5,192,223,223,191, 13,199,113, 47,186,
+184,184,160,172,164,228,182,200, 85,109,137, 81,251, 25, 0, 90,181,106,181,169,186,186,122,102, 99,157,135,124,125,125,163,108,
+109,109, 95, 74, 72, 72,120,244,193, 7, 31,148,152,205,102,108,219,182, 13, 95,124,241, 5, 6, 13, 26,132,176,176, 48,188,254,
+250,235, 14, 70,163,241,213, 93,187,118,189, 18, 25, 25,185, 71,167,211,189,251,103, 58, 36, 53,113,127,255,238, 65,238, 55,131,
+117,235,192,226,234,214,140, 26, 37,248, 1, 55,111, 21,226,174, 78, 78, 78, 11, 4, 65,232,131,119,223,133,189,212, 17,153, 25,
+ 87,160, 43, 19, 97, 49, 25, 33,138, 20, 84,108, 58, 79,108, 21, 2, 28,122, 83, 84,252, 74, 32, 35, 4, 67,134, 12,193,192,129,
+ 3,113,234,212, 41,172, 90,181, 10, 61,123,246, 68,121,121, 57, 42, 42, 42,160,215,235,107,219,130, 52,138,220,166,186,109,128,
+103,171,255,103,239,186,227,162,184,246,239,185, 51, 91,129,165,247,166,193, 94,158, 74, 21,187, 24,172,137, 37, 70, 77,177,198,
+ 94, 98, 98, 73, 98, 75, 98,108,209, 20, 77, 49,106,244,197,168,137,229,133,168,137, 37, 22,140,193,130,136, 84, 81, 16, 80, 65,
+ 41, 11, 2,210,151, 93,118,119,102,238,239, 15,202, 67,164, 44,198,252,158, 47,111,206,231,195,103,119,150,153, 51,183,204,204,
+ 61,115,238,247,222,139, 50,109, 79,152,203,229, 40, 44,173, 68, 81, 89, 37, 10,138,117, 56,242,235,235,168,212, 85,128,171,212,
+131, 55,112, 80, 57,143, 69,123,187, 65, 0,189,221,245,105, 22,162,177,178,204,164,145, 58,249,249,249, 15, 60, 60, 60,126,137,
+137,137, 25, 63, 97,194, 4,156, 63,127,126, 62,128,153,213, 15,216,249, 19, 38, 76, 64, 76, 76, 12,110,221,186,245, 75,126,126,
+254, 83, 25, 82,106, 48, 24, 42,140,213, 93, 84, 74,165, 82,102,202, 49, 12,195, 12,113,116,116, 36, 6,131, 1, 15, 31, 62, 68,
+ 65, 65, 1, 30, 62,124, 8,173, 86,139,242,242,114,112, 28, 7,163,209,136,200,200,200, 7, 60,207, 71,182, 36, 61, 73, 73, 73,
+237, 23, 47, 94, 60,115,240,224,193,171, 70,142, 28,137,227,199,143,227,199, 31,127,156, 3,224,112,223,190,125, 99, 90,154, 63,
+158,231,255,216,182,109,187,243,172, 25,163,157,127, 62,177,123,227,225, 35,215,123, 76,124, 53, 55,209,205,189,187,227,254,237,
+225,114,142,163, 39, 76, 38, 19,132,238,246,206,206,184,119,239, 30,162,162,162,160,211,233,106, 69,133,161,168, 8,198,194, 66,
+ 16,141, 6, 10,142,131, 46, 35, 3,109,187,119, 7, 1,186,152, 32,172, 27,237, 22,100, 89, 22,132, 16, 16,149,170, 74,100, 53,
+210,173,213,136,184,242,241,241,241,249, 97,215,174, 93,178, 37, 75,150, 4,180,105,211,230,219,156,156,156, 12, 79, 79,207, 23,
+ 62,255,252,243,139,235,214,173, 83, 76,154, 52,169,195,174, 93,187, 38, 54,229, 12,233,116,186,195, 39, 79,158,124,181,117,235,
+214, 78, 9, 9, 9,208,233,116, 16, 4, 1, 35, 70,140, 0, 0, 69,205,126,201,201,201,186,138,138,138,188,196,196,196,178,251,
+247,239, 27, 1,152,244, 18, 96, 97, 97,105, 39,145, 89, 64, 96, 36,176,182,182,133, 68,110, 1,129,147,128, 23, 0, 75,107, 7,
+ 92,137, 77, 70,210,125,118,206,237, 52,132,152,244,182, 83, 45, 88, 29, 28, 28,106,187, 4,107,186, 11,157,157,157, 81, 82, 82,
+242, 68, 2,171,180,180, 20, 37, 37, 37, 72, 77,191,133,188,178, 28,132, 30,138, 0,207,243,168,172,172,210,166,110,206, 30, 56,
+119,232,154, 42,104,188,255,123, 14, 62,228, 98, 65, 28,141,105, 66,100,165, 0, 72,169,233,218, 12, 14, 14,254,120,240,224,193,
+ 48, 24, 12,232,223,191, 63, 18, 18, 18, 70,216,216,216,172,111,233, 72,209,152,152,152, 95,187,118,237,122,170,172,172,172, 53,
+207,243,175,218,217,217, 45,227, 56,174,198,125, 59,193, 48,204,117,141, 70,115,188, 93,187,118,125,252,253,253,143, 68, 71, 71,
+ 79,111, 70,248,147,128,128,128,113,230,230,230,211, 52, 26,205, 33,165, 82,185,108,219,182,109,173,219,180,105,195,220,191,127,
+ 31, 28,199, 33, 35, 35, 67,136,138,138,170,240,247,247, 87,133,134,134,150, 51, 12,211,168,211,230,231,231, 39, 53, 26,141,255,
+ 58,118,236,216,144,182,109,219,226,226,197,139,216,180,105, 19,218,181,107,135, 61,123,246,160, 79,159, 62,240,242,242,130,173,
+173,237,130,210,210,210,192, 79, 62,249,100,152,175,175, 47,142, 30, 61,138,252,252,252, 29, 77, 77,217,192,113,141,135, 86, 85,
+ 84, 84,128, 82,138,231,159,127,126,250,146, 37, 75, 48,106,212,168,227,129,129,129,253, 35, 35, 35,239,152, 80,172,207,164, 83,
+ 85,219, 55,234,234,186,110,200,144, 33, 75,122,244,232,129,253,251,247, 67, 29, 24, 8,237,143, 63,194,102,228, 72, 80, 0,105,
+ 63,252, 0, 74, 41,108, 70, 87,133,194,122,141, 31,143,101,203,150, 13, 27, 59,118,172, 39, 0,255, 70, 56, 55, 78,153, 50,229,
+173,201,147, 39, 35, 54, 54, 22, 59,119,238, 68, 92, 92, 92,205, 4,162, 48, 26,141, 72, 74, 74, 66, 82, 82, 18, 92, 93, 93,241,
+226,139, 47,146,217,179,103, 15, 29, 49, 98,132, 3,128,126,127, 69, 62, 31,211, 32,127, 91, 7,235,209,135,184,189,181,181,117,
+244,182,109,219,236,122,246,236,201,114, 28,135,223,207,159,199, 59, 11,167, 99,248,200, 5,208, 85,202,193,233, 8,120,153,170,
+217,147,105,245, 44, 74, 47, 18, 8,170, 23,160,215,235, 49,251,160, 12, 54,228, 33,190,156,214, 19, 91,183,110,173,234,138,169,
+168, 64, 89, 89, 25,202,203,203, 81, 86,214,124,215, 91,121,177,202, 96, 48, 10,200,206,187,143,172,156, 27,176, 86,181, 2,101,
+ 60,241,160,176, 2, 4, 78, 48,106,147, 33, 84,223,152,149,218, 44,104, 42, 77, 20,199,212,244, 56, 73,131,190,212,228,125, 25,
+134,249,225,192,129, 3,163,182,108,217, 34, 31, 53,106, 84, 71, 87, 87,215,126, 0,240,202, 43,175,116,180,182,182,198,129, 3,
+ 7,244, 77, 61,192, 90,120,193, 50,174,174,174,147,251,245,235,135, 7, 15, 30, 32, 45, 45, 45,210,196, 52,158,141,143,143,159,
+234,233,233, 73, 50, 50, 50,144,149,149,133,194,194, 66, 88, 91, 91,195,206,206, 14, 46, 46, 46, 16, 4, 1, 90,173,214,249,230,
+205,155, 62, 0,206,154,154,166,188,188,188, 34, 0, 95, 85, 84, 84,172,146, 72, 36, 53,214,254,175,120,194, 5,168,111, 38,221,
+ 9,233,214,173,125, 87, 15, 15,219, 14,126,221,186, 57,122,184,223, 41,117,112,244,176,252,237,116,130, 89,222,131,162,228,155,
+ 55,111, 31,109, 73,145,105, 11, 11,161,190,126,189, 42,230,170,172, 12,186,242,114,112,197,197,112,237,208, 1,208,104,192,232,
+116,144,232,116,144, 10, 2,204,204,205, 97,202,219,150,228,210, 37,168, 70, 86, 77,223,162, 79, 74,170,114,172, 8,129,116,192,
+ 0, 16, 11, 11, 16,115,115, 48, 39, 79, 86, 9, 45, 75, 75, 96,119,179,189,100,112,115,115,179,119,113,113, 9,217,186,117,171,
+172,160,160, 0,137,137,137, 9,105,105,105,165, 14, 14, 14, 42,137, 68, 34, 36, 39, 39,255,145,156,156, 60,194,203,203, 11, 60,
+207,183,109,134,238,235,163, 71,143, 6,247,237,219,151,243,242,242, 50,207,207,207,247, 44, 42, 42, 34, 57,213,163,148,106, 16,
+ 21, 21,165,200,204,204,172,224,121,254, 24,170,230,193,106,244, 38,113,116,116,180,144,203,229,175,242, 60, 63,185,171, 23, 47,
+ 41, 44,211, 2,156, 30,233,247,210, 81,172, 49,128,114, 70,100,100,229, 64, 83, 41,224, 97, 97, 25,252,122,190,176, 85,207, 93,
+ 89,229,230,230,182, 82,173, 86,159,104,202,197, 26, 51,102, 12, 40,165,136,138,138,194,165, 75,151,112,233,210, 37,220,187,247,
+111,243,199,218,218, 26,161,161,161, 24, 52,104,144,233,221, 46, 21, 21,112,118,118,134,181,181, 53,142,134,253,128,239, 62, 63,
+ 88, 27,232, 94,231, 5, 9,230,230,230,216,240,206, 23, 22,211,223, 27,247, 33,128, 81,166,112, 7, 7, 7, 79,110,223,190,189,
+ 79, 96, 96, 32,238,221,187, 7,111,111,111,180,111,223,190,107,106,106,234, 12, 83,220,207,250, 72, 76, 76, 52,248,250,250, 58,
+ 57, 59, 59, 47,158, 58,117, 42, 56,142,195,176, 97,195,144,146,146,242,125,126,126,126,246,140, 25, 51, 90, 15, 28, 56, 16, 31,
+126,248,225, 43, 61,123,246, 92,215, 84,119, 89,191,126,253,222, 29, 63,126,252,123, 47,189,244,146,242,210,165, 75, 61,181, 90,
+ 45,235,225,225,193,220,185,115, 7, 60,207, 35, 60, 60,156, 59,123,246,108,182,193, 96,216,124,227,198,141, 94,229,229,229,199,
+226,226,226, 26,117, 46, 31, 60,120,240,214,209,163, 71,135,118,236,216, 17,167, 79,159,198,188,121,243, 78,171, 84,170, 46, 47,
+190,248,162,167,133,133, 5,226,227,227, 97, 48, 24,224,234,234,234,180,124,249,242, 17,195,134, 13,195,185,115,231,176,118,237,
+218, 83,206,206,206, 95, 55, 39,130, 37,213,177,145,117,193,178, 44,226,226,226,240,252,243,207, 99,217,178,101, 0,128,223,127,
+255,221,114,232,208,161, 81, 65, 65, 65, 46,205, 5,230, 55,230, 84, 61, 43,163, 8, 45, 45, 45, 39,239,217,179, 7,183,111,223,
+198,229,203,151, 81, 84, 84, 4,157, 78, 87,187,152,110, 73,113,113,213,116, 13,173, 91,163,235,202,149,248,246,229,151,145,147,
+147, 3,134, 97,236,155,120,198,191,186,114,229, 74,156, 58,117, 10,155, 54,109, 66,105,105,195,109,152,153,153, 25, 2, 2, 2,
+224,227,227,131,180,180, 52, 0,176,255,171,242,249,183,118,176, 26,131,181,181,245,103, 59,118,236,176,235,211,167, 15,171,209,
+104, 32, 8, 2,122,247,234,133,169,211,166,226,204,209,159,225,218,102, 16, 88,157, 25, 56, 75,243,230, 5,150,209, 10,232, 81,
+ 2, 77, 89, 25,148,213,193,164,215,179,116,160,148,194, 96, 48, 64,163,209,212,198,246,212, 4, 83, 55,235, 30, 25, 20,113, 73,
+119,121,143,210,242, 56, 68,198,252, 8,163, 94, 15,175,142, 43, 80,105,116,128,133,211, 12,104, 13,199, 97, 40,174,114,226,229,
+ 86, 65,120,240,160, 0, 32, 76,179, 22, 39,229, 76, 14, 3,130, 81,103,186,192,202,200,200, 40,118,117,117,253, 41, 60, 60,124,
+202,216,177, 99,113,230,204,153, 57, 0, 48,118,236, 88,132,135,135,227,238,221,187, 63,229,228,228, 20,183, 80, 72, 57,160,106,
+ 78,152, 90,215,203,217,217,217,171, 85,171, 86,243,103,207,158, 29,216,189,123,119,236,223,191, 31, 0,206,155,194, 87, 80, 80,
+240,207,165, 75,151, 14, 89,188,120,177, 11,195, 48, 36, 37, 37, 5,132, 16, 56, 57, 57,193,211,211, 19,118,118,118, 40, 46, 46,
+134,175,175,175,133,167,167,231, 40, 83, 5, 86,181,197,239, 1,160,164,230, 77,169,250, 83, 6,192,154, 82,250, 68,163, 90, 5,
+ 65,182,253,236,233,200,237, 1,190,195, 25,175,214, 22, 37,128,158, 92,139,202,182, 48,242,210,150, 53, 94,132, 36,220, 77, 77,
+245,162,130,128,242,162, 34, 24,202,202, 96, 44, 42, 2, 87, 88, 8,226,234, 10,137, 78, 7,182,178, 18,172, 94, 7,165,210, 28,
+ 37,121,121, 32,140, 9,215, 82,157, 6,161, 70, 92,177, 44, 91,235, 90, 17, 11,139, 90,135,139,101, 89,152, 50,117,145, 66,161,
+216,179,115,231, 78, 23, 87, 87, 87,124,241,197, 23,112,113,113,233, 24, 28, 28, 92,208,191,127,127, 51, 7, 7, 7,116,236,216,
+ 17,254,254,254,248,227,143, 63,192,178,236,221,102, 30,108, 28, 33,100,212,229,203,151,223,138,136,136,120,217,213,213,149, 76,
+153, 50, 5,195,135, 15,135, 66,161,128, 86,171, 69, 81, 81, 17, 78,158, 60, 73, 56,142,235, 83,253, 6,220,234,185,231,158,219,
+ 67, 8,201, 78, 79, 79,159, 82,159, 83, 46,151,239,153, 53,107, 86,208,168, 81,163, 8, 35,232,244,161,103,246, 73,120,158, 35,
+239,172,252,142, 15,187,116,129,225,121,142,140,123,125,169,240,219,249, 4,102,206, 91,159,241, 62,189, 94, 68, 98, 98,162,203,
+172, 89,179,214, 3, 56, 97,202,181, 36,145, 72,106,203,179, 62, 88,150,109,116,208,192, 99,206, 8,207,101,143,152,214,251,223,
+ 47, 76,188,193,222,221,197,147,169,113,174, 0,160,180,180, 20, 25, 25, 25, 48, 26,141,176,183,183,135,209,104, 52,105,125,182,
+ 53,107,214, 48,132,144,247, 26,218,211, 84, 0, 0, 32, 0, 73, 68, 65, 84, 39, 79,158,140,220,220, 92,172, 93,187, 22, 43, 87,
+174,196,248,241,227,177, 97,195,134,149,126,126,126,123, 76,153,255,169, 94, 55, 94,123, 27, 27,155,195,235,215,175,151, 89, 89,
+ 89, 33, 46, 46, 14, 93,186,116,193,231,159,127, 46, 73, 73, 73,105,221,169, 83, 39,220,186,117, 11,217,217,217,105,205,197, 34,
+201,229,242, 57, 11, 22, 44, 80,102,102,102, 98,220,184,113,202,180,180, 52,220,188,121, 19,148, 82,196,198,198,114, 71,143, 30,
+205,214,106,181, 3, 98, 98, 98, 30, 2,248,190,185, 23,186,254,253,251, 47,104,223,190, 61,126,255,253,119,204,159, 63,255,172,
+133,133,197,235,197,197,197, 51,244,122,253,231, 35, 71,142, 68,159, 62,125,144,156,156,140, 81,163, 70, 33, 32, 32, 0,231,207,
+159,199,178,101,203, 78, 91, 88, 88, 76,108,166, 28,238,132,133,133,117,245,247,247,175,237,221,144, 74,165,176,177,177, 65, 82,
+ 82, 18, 58,116,232,128,101,203,150, 97,203,150, 45, 88,178,100,137, 48,116,232, 80, 78,175,215,203,106,156,205, 39,196, 51, 49,
+138,176,188,188,156,230,228,228,192,202,202, 10, 33, 33, 33, 72, 58,117, 10,145,179,102,225,222,154, 53,160,148,194,113,253,122,
+ 4,190,255, 62,186,221,189, 11,181, 90,141,125,251,246,129, 97,152,218, 17,177,141,220,243, 40, 41, 41,129,183,183, 55,162,162,
+162,176,111,223, 62,124,241,197, 23,181,177,108, 82,169, 20, 65, 65, 65, 24, 58,116, 40, 82, 82, 82,176,115,231, 78, 88, 89, 89,
+ 65,196, 19, 8, 44, 74, 41,169,251, 89,175,123, 99,160,191,191, 63, 91, 94, 94, 14,157, 78,135, 7, 15, 30, 32, 61, 61, 29,102,
+102,102,200,206,203, 64,207,118,229,200, 37,122, 36,198,166,242,144, 72,174, 55,247, 80,212,235,245,136,140,140, 68,100,100, 36,
+132,142,155, 32, 8, 66, 77, 55, 69,173,123,149,155,155, 43,120,122,122,162,180,180,148,105,190,241,170, 60,123, 62, 60,126,216,
+148,177,207,203, 67,195,190,131,177,146, 67,185,206, 6, 26,157, 30,101, 90, 41,244,138,161, 32,228, 34, 24, 86,129, 62, 62,237,
+240,199,229, 84,157, 96, 52,132, 54,221,224, 64, 16, 12, 15, 41,227, 49,137, 8, 57, 71, 40,120, 93,195, 59,178, 44, 36,114, 21,
+180, 21,101, 2,165,166, 59, 48,182,182,182, 7, 15, 30, 60, 56,182,111,223,190, 22,131, 7, 15,110, 87,221,125,103, 60,120,240,
+160,198,214,214,246, 96, 11,197,213, 42, 66,176, 12, 20,140, 66, 46, 63,103,103,111,255,187,165,165,165,223,176, 97,195,218, 13,
+ 31, 62, 28,109,219,182, 69, 72, 72, 8, 66, 66, 66,206,231,228,228, 92, 49,241, 77,226, 58, 33,100, 66,122,122,250, 68, 87, 87,
+215,161, 61,122,244,112,105,211,166,141,210,218,218, 26, 44,203, 66,163,209,160,160,160,160,102,196, 85, 27, 83,211,250,220,115,
+207,193,213,213,245, 29,169, 84,186,190,222,155, 10, 7,224, 5, 87, 87, 87,139, 39,185,136, 19, 19, 19, 31, 12, 31, 22,236,180,
+253,219,240,246, 90, 45,111,248,245,212, 57,131, 81,111,161, 77, 74,190,219,162,217,236, 13,130,112, 54, 38, 58,122,120,191, 62,
+125, 20,247, 98, 98, 96, 44, 46, 6, 95, 84, 4,137,193, 0,137, 70, 3,182,178, 18, 68,171, 69, 43, 31,115, 64,112,198,181,180,
+108,206,192,243,231, 76, 22, 88,213,221,129, 53,141,127,141,192, 98,234, 8,172,154,238,175,166,224,236,236,108, 62, 98,196,136,
+ 32, 95, 95, 95, 80, 74,241,217,103,159,193, 96, 48,200, 13, 6, 3,140, 70, 35, 12, 6, 3,202,202,202,112,248,240, 97,252,240,
+195, 15, 17, 86, 86, 86, 63,154, 80,231,156,135,135,199, 92, 65, 16, 28, 57,142, 51, 56, 58, 58,202,126,250,233, 39, 40,149, 74,
+ 48, 12, 3, 31, 31, 31, 40,149, 74,189,155,155, 91, 9, 0, 56, 57, 57, 25,183,108,217, 34,153, 49, 99,134,172,145,183,127,159,
+183,222,122, 75, 90, 35, 26,221, 90,109,224, 12, 6,131, 0, 0,157,123, 12,248,119,183,216, 48,224,246,237,219,216,188,121, 51,
+ 52, 26, 13, 88,150,149,153,120,141, 34, 56, 56, 24, 67,135, 14,173,237, 14,116,114,114,130, 94,175, 7,199,113, 38,139, 43, 0,
+168,153, 68,116,205, 26,194, 96, 53,176, 39,208, 50, 29, 64,109,252, 84, 73, 73, 9, 50, 51, 51,113,255,254,253,218,238, 19,129,
+154,246,150, 29, 30, 30,222,223,203,203,203,205,195,195, 3,187,118,237,130, 86,171,189,251,203, 47,191,180,157, 50,101, 10, 90,
+183,110,237,192,243,124, 48,128,211, 45,185, 78, 57,142,155,178,112,225, 66, 11, 39, 39, 39,236,222,189, 27,199,142, 29,203,235,
+209,163,135,211,244,233,211,209,177, 99, 71, 36, 38, 38,226,171,175,190,122, 40, 8,194,171, 38,112,165, 93,187,118,205,217, 96,
+ 48, 32, 59, 59, 27,130, 32, 32, 57, 57, 25,217,217,217,194,133, 11, 23,178,117, 58, 93,141,184,106, 22, 94, 94, 94, 42, 63, 63,
+ 63,167,148,148, 20, 28, 58,116, 8, 70,163,113, 77, 98, 98,162,193,198,198,230,208,182,109,219, 86,182,105,211,198,118,192,128,
+ 1,232,211,167, 15, 40,165, 56,126,252, 56, 62,250,232,163,211,102,102,102,175, 39, 38, 38, 26,154,113,213, 95, 91,183,110,221,
+ 7,246,246,246,227, 38, 77,154,196,248,249,249, 33, 58, 58, 26, 60,207, 35, 56, 56,184, 86, 92,157, 57,115,230,167,211,167, 79,
+191, 4, 64,166, 82,169,236, 76,153, 86,130, 16,242, 2,128, 26,135,160,130, 82,250,219,179,214, 80,235,116, 58,164,164,164,192,
+217,217, 25, 29,251,246, 69,199,244,116,252, 81, 29,212, 62,104,233, 82,148,107, 52,216,179,103, 15, 98, 98, 98,192,178, 44,218,
+182,109,219,252,243,206, 96,192,157, 59,119, 80, 80, 80,128, 49, 99,198, 96,210,164, 73,248,244,211, 79, 97, 48, 24,176,106,213,
+ 42, 20, 22, 22, 98,215,174, 93, 72, 77, 77,133, 68, 34,129, 74,165,250,203,242,215,148, 6,249, 91, 59, 88, 53,194, 72, 16, 4,
+168,213,106, 68, 69, 69, 33, 45, 45, 13, 42,149, 10, 90, 78, 16,182, 94,141, 23, 24, 34, 85,115, 20, 17,132,151,174,106,174, 66,
+121,158, 71, 68, 68, 4,110,223,190, 13,235, 14,180, 38, 48, 17, 58,157, 14, 26,141,166,198,185,210, 38, 37, 37,229,150,148,148,
+216, 53,151,182, 7, 29,152,253,161,161,231, 22,249,251,116,109, 63,120,224, 71, 56,113,226, 67, 20,151,150, 66, 83, 41, 65,185,
+214, 0,141,142,194,205,178, 45, 2,123,248, 34,255,161, 30, 41, 55, 99,178,243,101,182, 77,190,137, 81,130,111, 38,140, 13, 94,
+252,193,187,179,157,187,116, 92,174,164,121,191,129,150,196, 82,212,204, 87, 73, 24,200, 85, 14,128, 68, 65,163,147, 10,202,255,
+ 72,208, 22, 80,130,111, 90, 32, 8, 52, 30, 30, 30, 63, 44, 92,184,112,125, 84,212, 53, 39, 0,136,142,142,206,203,205,205,125,
+ 63, 43, 43, 75, 99, 42, 15, 33,196,134, 16, 44, 19, 4,202, 86,139,180, 33,139, 23, 47,118,235,219,183,175, 65, 42,149, 34, 35,
+ 35, 3,159,126,250, 41,194,195,195, 15,229,228,228,108,111,201,172,206,148,210,120, 0,241,132,144,181, 9, 9, 9,131,131,131,
+131, 55,116,232,208,193,131,227, 56,148,148,148,160,168,168, 8,169,169,169,168,168,168,104,118,217,145,140,140,140,115,153,153,
+153,131,231,206,157,139,190,125,251, 78,219,187,119,239,107,117,109,224,238,221,187, 95, 29, 61,122,180,135,181,181,181, 76,171,
+213, 26,147,147,147, 47,182,232, 53,211,211,179,223,162, 69,139,122,204,153, 51, 7,229,229,229,216,183,111, 31,182,111,223, 14,
+ 79, 79,207,126,153,153,153,151, 91, 32, 0, 15, 30, 11, 13, 93,220,163, 83,167, 14,173,189,188,144,114,246, 44,100, 6, 3,164,
+ 28, 7,182,162, 2, 82, 99, 37,158,243,183,128, 76,233,128,156,123, 90, 28,186,121,243, 62,165,180,217, 9, 50, 13,193,193, 48,
+ 38, 39,131,101, 89,200,130,130,170, 98,173,204,205,193,252,250,235,191,133,213,234,213,160, 22, 22, 16,130,154, 15, 65,120,240,
+224, 65, 69,251,246,237, 99,111,221,186,229,215,169, 83, 39,172, 89,179, 6,153,153,153,160,148, 34, 47, 47, 79,151,151,151,167,
+ 46, 44, 44,204, 96, 24,230, 88,118,118,246, 30, 83,151, 34, 17, 4,193,241,248,241,227, 53,142, 34,126,255,253,119,184,185,185,
+193,218,218, 26,165,165,165,152, 50,101,138,252,131, 15, 62, 0, 0,196,198,198, 74,205,204,204, 26,119,117,141, 70,202, 48, 12,
+201,204,204, 52,152,155,155, 19, 59, 59, 59,137, 66,161, 64,101,101,101,173,208,186,125,251, 54, 78,156, 56,129,172,172, 44,216,
+217,217, 49,182,182,182,224,121,190,200,196,180,130,101,217,199, 2,218, 91, 42,174,234, 98,245,106, 42, 16, 16,210, 70,194, 94,
+207,206,205, 28,236,230,236,129, 7, 15, 30, 32, 35, 35, 3, 25, 25, 25,200,204,204, 68,251,246,237,145,126,255, 46,228, 50,233,
+117, 19,239,163,215,122,246,236, 9,173, 86,139,216,216, 88, 94, 42,149,190,150,144,144, 16,161,209,104,164, 61,122,244,192,253,
+251,247, 95,105,169,192, 98, 24,198,195,220,220, 28, 90,173, 22,199,143, 31, 47, 84,169, 84,157,227,226,226,198,167,166,166,126,
+234,233,233,105,121,255,254,253, 7, 6,131, 97, 68,116,116,116,170, 9,238,200,204,247,222,123,239,128, 32, 8,109,254,241,143,
+127,176,163, 71,143,182,112,119,119, 71, 84, 84, 84, 69,101,101,229, 39,166,138, 43, 0, 72, 79, 79, 47,191,116,233, 82, 94,215,
+174, 93,157, 92, 93, 93, 33,149, 74,215,185,185,185,125, 98, 97, 97,241,241,200,145, 35,109, 67, 66, 66,240,243,207, 63,195,194,
+194, 2,233,233,233, 57,201,201,201,223, 56, 57, 57,109, 55,197,193,139,138,138, 74, 7,240, 70, 96, 96,224,199, 95,126,249,229,
+ 50, 66,200,107,103,207,158,173,141,189,219,188,121, 51,206,156, 57,243,211,115,207, 61, 55, 43, 36, 36,100,122, 11,171,222,156,
+ 82,122,179,250,153,250,143, 58,191, 63, 43,177, 89, 70,189, 94, 15,123,123,123,228,231,231, 35, 47, 47, 15,173, 90,181, 66,255,
+254,253, 97, 52, 26,241,203,201,147,184, 84, 45,182, 28, 28, 28, 96,101,101,133,248,248,120, 80, 74,111, 53,217,249, 99, 48,212,
+246, 70,196,199,199,195,201,201, 9, 75,150, 44,129, 94,175,199, 79, 63,253,132,184,184, 56, 48, 12, 3, 71, 71, 71, 88, 90, 90,
+214,196,104,221,130,136,167, 39,176,170,215,204, 26,219,163, 71, 15, 73,106,106, 42, 82, 83,171,238,217,138,138, 10, 78,194,226,
+232,131,235,191,188,209,132, 0,232, 86,111,126,152,136,213,171, 87,247,158, 54,109, 26,220,221,221,177,243,154, 1,247, 51,120,
+ 24, 12, 6,228,228,228,224,202,149, 43,124,255,254,253, 89,142,227,202,121,158, 31,149,153,153,249, 58, 33, 36,183, 73,206,144,
+ 16,222,209,123,220,132,109, 59,254,249,199,180,105,211,108, 71,143,217,142,216,196, 27, 40,210, 56, 1, 0,220, 28, 44, 16,216,
+233, 61,228, 61,172,196,153, 83, 39,138,169, 80, 49,145,198, 29, 50, 54,197,153,148, 70,191,239,214,138, 92,152, 60,251,253,183,
+125,186,121, 13,125,103,238, 75,246, 29, 60,198, 40, 80, 28, 73, 21, 86,101,144, 91, 56,226, 86, 90,129,246,183, 8,245,195,130,
+ 18,238,119,194,227,171,164, 12,154,222, 20,103,125, 20, 22, 22, 94, 86,171,179, 29,235,204,218,238,168, 80, 40, 47, 55, 35,168,
+154,228,172,153, 78,225,244,233,211,184,116,233,146,225,246,237,219, 23, 8, 33,199,213,106,245,245, 39,229,164,148,150, 1, 56,
+ 98,105,105, 41,232,116,186, 15, 71,140, 24,209,158, 16,130, 59,119,238,224,252,249,243, 97, 5, 5, 5,159, 52,199, 89, 81, 81,
+177,224,237,183,223,254,102,240,224,193, 67,170, 71, 60,201, 83, 82, 82, 64, 41, 69, 64, 64, 0,250,244,233,211, 70,175,215, 11,
+ 87,175, 94, 45, 60,121,242,228, 33,157, 78,183,165, 37,233,204,204,204,188, 28, 16, 16, 80,213, 13,173,213, 34, 43, 43, 11, 28,
+199, 65,173, 86,183,168, 60, 67, 66, 66,248,192,192,192, 87,190,252,254,251, 63,222, 26, 55,206,182,215,232,209,200,142,136,128,
+ 94,173,134,156,231, 33,151, 41, 97,212, 56,161, 48, 91,135,239,110,222, 44,213,243,252,235,245, 27,135,134,210, 89, 53,167, 25,
+169, 29, 45, 72, 84,170,170,184,171, 58,163, 8,169, 74, 5, 70,165, 2, 35,147, 61,230, 96, 53,196,169,213,106, 39,206,158, 61,
+ 59,242,183,223,126,179,121,253,245,215, 49,122,244,232,248,210,210,210,225, 5, 5, 5, 38,245,109, 55,196,201, 48, 76,254, 11,
+ 47,188,224, 88, 89, 89,201,189,246,218,107,146,130,130, 2,116,236,216, 17, 0, 80, 86, 86,134, 83,167, 78,161, 83,167,170, 48,
+148,155, 55,111,162,107,215,174,141,114,198,199,199,255,188,119,239,222,185,227,199,143,151,241, 60,207, 87, 7,197, 19, 23, 23,
+ 23, 54, 42, 42, 74, 56,118,236, 24,180, 90, 45, 60, 60, 60,152, 86,173, 90,145,168,168, 40,225,238,221,187,145,132,144,149,166,
+212, 59,165,244, 17,113, 37,145, 72, 80, 81, 81, 97,146,184,106,234, 90,162,160,212, 81, 67,214,188,177,100, 66,224,185, 67,145,
+ 42, 11, 11,139,218,152,159,118,237,218, 65, 34,149, 96,247, 47, 91, 53, 37,101, 15,215, 54,199, 25, 20, 20,164,144, 74,165,163,
+125,124,124, 16, 29, 29, 13,189, 94,127,241,220,185,115,183,130,131,131,207,197,199,199,143,232,216,177, 35, 24,134,121, 33, 40,
+ 40,200, 34, 44, 44, 76, 99,106, 58, 41,165,105, 89, 89, 89,240,242,242,130,141,141,141,149,209,104,228,226,226,226,126,236,222,
+189,251,209,212,212, 84, 47,133, 66,113, 63, 58, 58,186,220,148,188,199,196,196,100, 2,232, 23, 20, 20, 36,185,113,227,198,253,
+254,253,251, 67, 46,151,163,125,251,246,170, 59,119,238,188,142, 38,166,142,168,207, 73, 41, 21,220,221,221,183, 93,187,118,109,
+173,143,143, 15, 94,123,237,181,231,163,163,163,159,247,246,246, 70,219,182,109, 17, 30, 30,142,176,176,176, 67,130, 32,188,149,
+147,147,163,107,234,133,175,177,188, 87, 7,173,207,244,243,243,123, 89, 34,145,192,210,210,146,205,206,206,102,207,158, 61, 11,
+ 74,233,155, 77, 13, 26,104,238, 89, 87, 31,166,196, 92,181,148,243, 73,238, 77,134, 97, 62,154, 58,117,234,215,115,230,204, 81,
+246,236,217, 19, 37, 37, 37,181,162,255,183,223,126,131, 32, 8,176,183,183,135,189,189, 61,110,223,190,141,163, 71,143,234,139,
+139,139,183, 41,149,202,207,155,226,156, 50,101,202, 35,156, 53,226,237,196,137, 19,181,131, 72,236,237,237,145,154,154,138, 35,
+ 71,142,232,138,139,139,183,114, 28,183,229,175,204,251,255,156,192, 42, 46, 46,126,119,197,138, 21, 3,103,204,152, 97,167,213,
+106, 89, 7, 7, 7,168,213,106,238,236,217,179, 69,229,229,229,239,182,228,100, 44,203, 14, 87,171,213,147, 22, 45, 90,180,182,
+125,251,246,118,111,188,241, 6, 22, 44,232, 4,189, 94, 15,133, 66, 1,153, 76,246,237,137, 19, 39,198,219,216,216,100, 31, 63,
+126, 60, 19,192, 38, 83,120,243,227, 15,223,113,241, 25, 51,244,235,175,183, 31,240, 13, 8,244,124,206,203, 75,209,207,211, 26,
+ 6, 35,143, 7,121, 15,113,225, 74, 82,101, 74, 98, 92, 22, 56,221,228, 7, 55,142, 39,153,194,121,163, 74, 48,189,221,163, 29,
+241,126,109,254,230, 69,253,123,182,237,245,230,107, 1,182,165, 66, 9, 61,122,236,118, 97, 90,102,249, 53, 9,139, 47,111,166,
+211,248, 39, 41,120,157, 78,103,168,223, 19,164,211,233, 12, 45,180, 85,139, 9, 33,159, 50, 12, 89, 6, 10, 70, 46,151, 71,110,
+223,190,125, 31,128,108, 74,105,164, 90,173,214, 62,173, 11,165,172,172,236, 23, 66, 72,236,157, 59,119, 22, 51, 12, 99,195,243,
+124,210,131, 7, 15,126,162,148, 54, 55, 75, 56,170, 39,187,124,201,195,195, 99,192,229,203,151, 55,141, 28, 57,178,219,139, 47,
+190,136,220,220, 92, 72, 36, 18,196,199,199,235, 79,158, 60, 25, 89, 92, 92,252, 17,165, 52,170,165,105,171,118,176, 48,119,238,
+ 92,148,149,149,225,208,161, 67, 56,115,230, 76,139, 29,172,154, 7,120, 96, 96,224,208,245,123,246, 28,124,161, 83,167, 86,157,
+218,182,149,181,238,218, 21,102,230,230, 40,121,248, 16,241,247,114,248, 31,147,147,211,181, 28, 55, 57, 38, 38,198,164,107,201,
+104, 52,194,214,214, 22,148, 82, 72,151, 47, 7, 8, 1, 37, 4,149,213,179,120,115, 28, 7,105,239,222,160, 44,139, 82,173, 22,
+ 6,131, 1, 74,165,178, 73,206,236,236,236,108, 79, 79,207,215,223,124,243,205,223,246,237,219,199, 4, 5, 5,245, 56,118,236,
+ 24,253, 51,117,156,149,149,213, 30, 0,220,220,220, 30, 88, 89, 89, 73,222,120,227, 13, 24,141, 70, 84, 84, 84,160,180,180, 20,
+ 15, 31, 62,212, 47, 90,180, 72, 14, 0,114,185,220, 56,124,248,240, 70,159, 31,106,181,122,133,167,167,231,233,175,191,254,122,
+249,140, 25, 51, 2,199,143, 31, 47,101, 89, 86,200,206,206,230, 14, 30, 60, 72, 58,116,232,192, 40, 20, 10, 18, 17, 17, 33,220,
+188,121,243, 42,165,244,147,236,236,108,147, 87, 26,168,113,213, 5, 65,168,157,191,170,169, 81,102, 45, 65,254,117, 26,239,213,
+199,230,179, 65, 19, 2,222, 91,191,244, 11, 11, 7, 71, 7,112, 28,135,180,140,187,248,254,232, 55,154,210,202,226, 79, 11,110,
+ 52,191, 6,167, 92, 46, 55,179,179,179, 83, 41,149, 74, 68, 69, 69, 1,192,161,234,134,233, 95,177,177,177, 35, 58,117,234, 4,
+ 27, 27, 27,179,252,252,252,246, 0,226, 90,144,196,187,106,181, 26, 70,163, 17,142,142,142,146,148,148,148, 86, 0,210, 18, 18,
+ 18, 42, 0,220,124,146, 60,135,133,133,113,253,250,245,187,125,227,198,141,128,231,158,123,142, 68, 70, 70,106,116, 58,221,193,
+150,242, 56, 59, 59,127,125,226,196,137,190,148,210, 33,190,190,190,104,221,186,117,141,107,143,139, 23, 47,134,100,103,103,207,
+126, 74,139, 59, 83, 66, 8,202,202,202,216,234, 50, 53,168, 84,170, 39,229,173,168,227, 92, 85, 60,107,141,116, 86, 86,214, 65,
+ 23, 23,151,115,171, 87,175, 94,209,190,125,251,153,179,103,207,102, 59,118,236,136,146,146, 18, 88, 89, 89,193,213,213, 21,217,
+217,217,216,183,111, 31,159,159,159,255, 3,203,178, 31,231,212, 31,161,210, 2, 78, 91, 91, 91,184,186,186, 34, 43, 43, 11,251,
+246,237,227,243,242,242,190,231,121,126, 99, 94, 94, 94, 30, 68,180, 76, 44,155,210,107, 84, 61, 77,195,103, 60,207, 15,172,113,
+181,138,139,139,223,109,110,125,187,198, 20,110, 80, 80,144,196,204,204,108, 82, 65, 65,193, 90, 15, 15, 15,187, 55,222,120, 3,
+171, 86,173, 66, 66, 66,130,249,216,177, 99,237, 36, 18, 9, 23, 18, 18, 82,218,210, 55,134,154,197,158, 33,145,141, 0, 21,186,
+ 1, 32, 96,216,102, 23,123, 54, 69,137,119,111, 75, 6,241, 20,179,170, 14,192,174,196,187, 52,236,207,190,217,212, 93,156,153,
+ 82, 52,187,176,115, 99,156, 13, 5,185, 63,233,219,210, 95,241, 6, 86,239,127,196,213,213,117,130, 92, 46,255,122,194,132, 9,
+ 22,123,247,238,213,229,229,229, 45, 2,112,168,169, 53, 3,155, 75,167,155,155, 91, 69,235,214,173, 97,103,103,135,194,194, 66,
+220,191,127, 31,106,181,218,252, 73,211, 89,119,177,103, 84, 47,246, 76, 77, 88,236,185, 62,103,175, 94,189,238, 25,141,198, 22,
+ 45,190, 42,149, 74, 31, 42, 20,138, 54, 53,231,104, 42,157,238,238,238, 19, 60, 60, 60,214,101,103,103,255,154,149,149,181,236,
+105,212,145,187,187,123, 47, 66,200, 81, 65, 16,148,245, 29,174, 26, 17,230,234,234,218, 74, 46,151, 63, 18,228,222, 24,167,167,
+167,103,127,165, 82,185, 98,210,164, 73, 61, 71,143, 30,205, 68, 70, 70,226,226,197,139,124,100,100,228, 53,163,209,184, 41, 51,
+ 51,243, 82, 75,210, 57, 97,194,132, 4,131,193,208,218,196,178,204, 39,132, 60,178,112,182,169,215,188,131, 15,241,179, 54,179,
+255, 80,111, 48,118,103, 8,168, 84, 42, 77, 40, 41,123,184,182, 33,113,213, 16,103,245,244, 12,191,216,218,218, 14, 46, 42, 42,
+186,193,113, 92, 80, 88, 88, 88,165,159,159,159,212,198,198,230,128,149,149,213, 11,165,165,165,151,251,246,237, 59, 98,245,234,
+213,130,169,117, 20, 24, 24,216,185, 77,155, 54, 81, 43, 86,172, 32,235,214,173, 67,102,102,166,223,213,171, 87,147,255,108,189,
+247,234,213,171, 53,203,178,123,120,158,111, 67, 8,217,123,245,234,213,143, 76, 17, 67,245, 57,187,118,237, 42, 43, 41, 41,153,
+239,225,225,241,150,179,179,179,211,131, 7, 15, 50, 50, 51, 51, 63,207,201,201,217,107,170,184, 50,165,142,252,252,252,138, 0,
+200, 1,192,148,120,171,255,239,103,221, 95,193,233,233,233,217,134,227,184,213, 62, 62, 62, 99,167, 79,159, 78,146,146,146, 16,
+ 26, 26,138,244,244,244, 99, 12,195,172,206,202,202,186,243, 52, 56,207,158, 61, 75,211,211,211,143, 72, 36,146,181,153,153,153,
+105,255, 95,121,255,159, 20, 88,127,213,197, 87, 35,180,138,138,138, 86,169, 84,170,219,161,161,161, 47, 60,107, 23,244, 95,205,
+ 73, 8,113,170,118,163,242,254,151,242, 78, 8,145, 40,149, 74,127,157, 78,119,139, 82, 90,250,148, 56, 87, 1, 88, 9,224, 99,
+ 74,233,134,255,181,107,233, 89,231,172, 22, 90,139, 40,165,168,172,172,252,178, 41, 97,245,119,202,251,224,193,131, 61,207,157,
+ 59,151, 89,255,217,167, 84, 42,109,116, 58, 93,113,216, 19,188,248,249,251,251,127,196,178,236, 4,142,227, 14,197,196,196,172,
+123, 22,243, 78, 8, 33,173, 91,183,150, 55, 53,201,173,120, 31, 61, 25,167,171,171,171, 47,128,229, 64,213, 50, 74,153,153,153,
+209, 79,139,147, 16,194, 3,248, 68,173, 86,199,255,127,231,253,239, 6,201,127,242,228,213, 15,150,189,104,193, 98,188,127, 55,
+152, 34,172,254,166,249,230, 0, 92,125,202,156, 27, 0,108, 16,111,235,103, 19,213,130,234,210,255, 90,190,235,139,171, 58,207,
+190,130, 39,229,140,142,142,254, 8,192, 71,207,248, 61, 78, 1, 84,138, 87,254,211, 71, 78, 78, 78, 44,128,241,207, 58,231,255,
+ 58, 24,177, 8, 68,136, 16, 33, 66,132, 8, 17, 34,158, 46, 8,128,110,141,188,125,152,108,253, 17, 66,186,181,244,196, 38,116,
+247,136,156, 34,167,200, 41,114,138,156, 34,167,200,249, 55,227,108,142,251,239,210,245,248, 31,141,193, 18, 57, 69, 78,145, 83,
+228, 20, 57, 69, 78,145, 83,228,252, 59, 66,236, 34, 20, 33, 66,132, 8, 17, 34, 68,136,120,202, 48, 57,200,189,123, 59,226,206,
+ 27, 49, 10, 44,134, 3, 0,120,156,102,165, 56,158,112,135,102, 63,233,201, 93, 92, 92, 58, 19, 66, 38, 51, 12, 51, 30,128, 32,
+ 8, 66, 8, 33,228, 71,181, 90,157,250,164,156,129,129,129,157, 57,142,123,149, 16,242, 18, 0, 80, 74,127,145, 72, 36,255,138,
+140,140, 52,105, 6, 90, 51, 51,179,123, 58,157,206, 17, 0,148, 74,101,190, 78,167,243, 66,245,172,227,227,199,143, 39, 5, 5,
+ 5, 4, 0, 46, 92,184, 80,179,214, 38,109,110,134,116,133, 66,113, 79,175,215, 63, 54, 84, 95, 42,149, 26,108,108,108,138,237,
+237,237,139, 29, 29, 29,139,100, 50,217,205,130,130,130, 11,241,241,241,209,148,210,220,150,228,123,224,192,129, 31, 40, 20,138,
+133,122,189,126,103, 88, 88,216, 7,127,245,133, 67, 8, 9,240,116,115,217,105, 52, 26,132,220,252,194,143, 40,165, 39, 90,114,
+124,187,118,237,228,238,238,238,164,254,208,234, 47,231, 16, 23,202,128, 89,188,163,249,249,181,154, 73,159,175, 84, 42,157,235,
+236,236, 60, 52, 43, 43, 43, 22,192, 42,113, 22, 98, 17, 34, 68,136, 16,241, 76, 8, 44, 63, 63, 98,166, 43,197, 96, 8, 24,213,
+193,203, 57,112,241,220,241,246,254,189,135,153, 87, 84, 24,232,197,243, 39, 2,190, 59,112,124,193, 63,218,144,107, 60,193,113,
+ 51,107,132,198,196,208, 70, 39,182,252,234, 29,201, 61,158,231, 29, 1, 64,128, 68,243, 69,136,227,157,128,128, 0,239,165, 75,
+151, 34, 48, 48, 16,130, 32,224,194,133, 11,139,191,248,226,139,197,174,174,174,209, 44,203,238,151,201,100, 63,167,165,165, 53,
+ 59,132, 63, 32, 32,192, 67, 16,132,241, 0, 94,233,213,171, 87,215,121,243,230,161,125,251,246,168,172,172, 68,100,100,228,210,
+253,251,247, 47,245,243,243, 75, 4,240, 19,195, 48, 63, 71, 69, 69,101, 53,198,165,211,233, 28,107,244, 18, 33,196,113,246,236,
+217, 26,163,209, 8,189, 94, 15,163,209, 8,149, 74,149,168,211,233,174,247,235,215, 47,218,210,210,242,202,201,147, 39,111, 3,
+224,187, 56,155,245,108,237,225, 48,252,183,232,140,143,234,115,234,245,122, 71, 93,100, 36,192,243,224,238,223,135,110,240, 96,
+ 84,175, 27, 39, 99, 71,140,112,226, 24,198,137,148,151,223,213,253,248,227,142, 78,157, 58,213,206, 99,210, 20,103, 61, 49, 65,
+230,206,157,187,116,249,242,229,210,137, 19, 39,190, 17, 20, 20,180,166,177,161,223,166,114, 54,115, 62, 69, 47,255, 30,167,142,
+ 31, 62,164, 4, 33, 24, 59,118,252, 30, 66,200, 44, 74,233, 47,245,247,245,241,241, 9,150,201,100, 31,113, 28, 23, 43,145, 72,
+ 62,136,140,140, 44,243,247,247, 63,236,224,224, 48, 92,175,215,195,215,215, 55, 34, 54, 54,118, 48, 0,236,152, 73,214,200,129,
+197,224, 65,118,206, 36,219,230,124, 71,151, 63, 97,250,102, 79,155, 54,237,243, 13, 27, 54,176,213,147,240, 13,233,210,165, 75,
+123, 66,136, 63,165, 84, 43,222,246, 34, 68,136, 16, 33,226, 63, 38,176, 58,183, 37,175,154, 43,100, 75,150,207,127,209,101,196,
+240,145,150,118, 30,190, 18, 16,182,202,145,177, 2, 25, 59,121,169,197,152,137,111, 91,164, 39,134,187,159,252,237,196,144, 31,
+143,158,207,233,220,150,108,185,117,151,254,171, 33, 62,158,231, 29,151,204,152, 7, 0,216,178,123,135, 69,114,114,178,183, 74,
+165,122,100, 89,144, 97,195,134, 97,200,144, 33,200,200,200,240, 63,124,248,176,255,158, 61,123, 62,245,240,240, 88,157,149,149,
+181,181,113, 17,232,183,206,221,221,125,241,210,165, 75,137,191,191, 63, 20, 10, 69,237,255, 44, 44, 44, 16, 28, 28,140,224,224,
+ 96,228,230,230,118, 13, 11, 11,235,122,224,192,129,181,126,126,126, 95,196,196,196,152,228,242,188,254,250,235,120,248,240, 33,
+ 30, 62,124,136,210,210,210, 28,141, 70,147,175,211,233,114,148, 74,101,234,160, 65,131,238, 0,224, 59,186, 89,118,112,116,176,
+ 63,188,113,253, 90,160,137,161,211,234, 62,125, 0, 0,218, 27,255,238,182, 54,167,148, 66, 38, 75,145,228,228,252, 90, 87, 92,
+153,202, 89, 45, 48,109,211,210,210, 4,153, 76,134, 78,157, 58, 73, 83, 82, 82,238, 5, 5, 5,125, 23, 22, 22,182,166,238,126,
+ 45,225,108, 6,254, 31,189,187, 64, 86,112, 55, 14,183,174,156,197, 24, 63, 15,101,236,205,148,213, 0, 30, 19, 88, 44,203, 46,
+255,237,183,223,188,175, 93,187,230,189,122,245,234,118,126,126,126,163, 1, 12, 58,125,250, 52,164, 82, 41,130,131,131,123, 7,
+ 5, 5,217,203,184,252, 81,163,219,147,165,243, 23,207, 37, 0,176,235,155, 93,111,110, 95, 64,182,205,223, 70,179, 90, 32,172,
+100, 44,203,126,177,111,223,190,105, 83,166, 76,193,253,251,247,113,249,242,101,168, 84, 42,172, 91,183,174,245,210,165, 75,215,
+ 0,120, 87,188,237, 69,136, 16, 33, 66,196,127, 76, 96,177, 20,239, 70, 94, 75,236,192,112, 15, 9,145, 90, 53,184, 15,195, 72,
+208,182,219, 64,201, 92,175,127,216,140, 24, 50,212,234,229,105,139,223, 5,240, 47, 83, 78,108,105,105,217, 8, 39,131,231,158,
+123, 14,239,188,243, 14,188,189,189,229, 83,167, 78,125, 31,192,214, 38,168, 22,135,132,132, 16,150,101,193,178,108,163, 59,185,
+184,184, 96,200,144, 33,112,113,113, 33,239,190,251,238, 98, 0, 13, 10, 44,165, 82,153, 79, 8,113, 4, 0, 59, 59, 59,236,216,
+177, 3, 70,163, 81,168,168,168,184, 81, 81, 81, 17,111, 48, 24,162, 20, 10,197,213,139, 23, 47,222, 1,128, 14, 30,102,110,230,
+114,243,227,187,118,108,133,177,236,129,109, 99,231,231,179, 30,215, 9,148,210, 18,198,204,236,190, 52, 61,253,176,172,164, 36,
+166,230,119, 83, 57, 1,160, 95,191,126, 54, 22, 22, 22, 23,182,111,223, 46,149,201,100,152, 53,107,150,133, 90,173,198,103,159,
+125, 54, 31,192,154, 39,225,108, 66,192, 88,247,239,227,159,252,245,166, 15, 45,125, 3,251,225,234,207,219, 81, 92,172, 65,121,
+ 89, 5,120,129, 42, 26, 58,134, 82, 90,120,231,206, 29,140, 24, 49, 2, 57, 57, 57, 3,118,238,220,185, 83, 16, 4,162,209,104,
+106, 23,106, 85,169, 84,183, 7,246, 9,146, 51,119,215, 62,241,133, 76, 8,113,180,178,178,250,233,204,153, 51, 1, 1, 1, 1,
+184,122,245, 42,238,222,189,139, 5, 11, 22,232, 23, 44, 88, 32,155, 58,117, 42, 89,178,100,201, 60, 66,200, 47,148,210, 8,241,
+214, 23, 33, 66,132, 8, 17,255, 17,129, 5,128,101,205,219, 17,253, 31, 47, 11,172,195, 64,194,186,142, 36, 68,233,246,200, 14,
+154,135,247,144, 28,177,143,222, 75, 56, 70, 91,121, 79, 38, 0,216,122,141,235,191, 23,151,100,217,130, 45,187,119, 56, 0,128,
+220,204, 30, 33, 33, 33, 24, 60,120, 48, 14,127,221, 21,229, 37, 85,203, 38,169,172, 93, 49,238,173, 68, 36, 39, 39, 35, 60, 60,
+188,102,161, 89,105, 99,156, 53,109, 43,162,163,145,223,183, 47,228,133,133, 48, 55, 55,135, 92, 46,127,100,135,148,148, 20, 92,
+188,120, 17,247,239,223, 71,219,182,109,171,142,105,132, 83,171,213, 62, 55,101,202,148,130,201,147, 39,155,237,221,187, 23,105,
+105,105, 46,145,145,145,101, 13, 21,144,247,115, 54,214, 50, 65,118,124,247,142, 47,164, 48,104,108,147,163,194,241,143, 17,115,
+ 26, 76,167,110,224,192, 90,231,202, 44, 48, 16,140,151,151,129,200,100,169,133,187,118, 13,245,245,245, 53,182,148,179,127,255,
+254, 43,121,158,127, 83, 16, 4,197,238,221,187,165, 14, 14, 14,204,150, 45, 91,140,103,207,158,229, 41,165,140, 76, 38,219,254,
+ 36,233,108, 10, 82,137,228,195,207, 87,191,107,105,206, 24, 17,251,219,143,200,186,159,129,235,183,179,141,255,186,156,196,235,
+141,220,220,134,202, 83, 34,145,188,181, 98,197, 10,159,221,187,119,187,206,156, 57, 19, 50,153,236,149,135, 15, 31,226,208,161,
+ 67, 48, 55, 55,199,142, 29, 59,240,220,115,207,201,121,158, 71,220,137,135,216,241,213, 54,128, 82,232,140,178,131, 75,246,113,
+ 89, 77,212,123, 93,113,213,181,117,235,214,199,255,248,227, 15, 39,119,119,119,132,133,133, 33, 55, 55, 23,174,174,174, 88,176,
+ 96,129,124,211,166, 77, 7, 74, 75, 75,199,110,216,176, 65,153,144,144,176,151, 16,210,129, 86,225,169,143,128, 17, 57, 69, 78,
+145, 83,228, 20, 57,255, 18, 4, 0,112, 4,144, 15, 32,170,222, 54,170,191,163,129,237,130,234, 54,223,190, 14, 87, 1,170, 98,
+168, 29, 1,240, 0,174, 1, 40,250, 75, 4, 22, 33,100, 32,128, 48, 0,107, 40,165, 31, 61,178,135, 96, 4,159,119,142,242,121,
+191, 83,198,214,159,176,174, 99, 72, 81,137, 14,183, 34,190,167, 57,201,127, 80, 84,199, 43, 25,244,101, 77,158,232,171, 35, 30,
+ 29,229,114,121,225,173, 91,183,240,251,239,191, 3, 0,142, 28, 57,130,242,146, 28,212,233, 58,196,231,159,127, 14,142,227,192,
+ 48, 12, 12, 6,211,214, 62,166,149, 85,113,210,122,189, 30,122,189, 30,164,103, 79, 72, 7, 12,192,157, 5, 11,112,238,220, 57,
+228,231,231, 67, 38,147, 65, 38,147,153,180, 32, 44,199,113, 36, 47, 47, 15, 58,157, 78,224, 26, 57,192,195,131, 40, 45, 57,243,
+195, 91,191,216, 96,105,169, 50,119,138, 62,251, 11,238,223,111, 60, 46,221,104, 52,254,219,165,107,219, 86, 11,137, 36, 86, 26,
+ 23,247,175,186,226,170, 37,156, 60,207,191,125,240,224, 65,139,162,162, 34,200,100, 50,124,242,201, 39,198, 75,151, 46,169, 57,
+142, 27, 16, 19, 19,243,240, 73,211,217, 20, 28, 28, 29, 79,191, 60,105,206,156,245, 51,134, 64,171,209,225,232,165, 68,252,158,
+144, 62, 1, 64, 4,165, 84,211,208, 49,145,145,145,121,129,129,129, 47, 47, 90,180,232,252,158, 61,123,204, 38, 77,154, 4,158,
+231,107,255, 42, 42, 42,240,199, 31,127,224,210,165, 75,136,137,185,158, 37,163,157,126,119, 49, 47,251,233,199, 51,166, 45,210,
+ 76, 8,113,245,242,242, 58, 25, 25, 25,233, 96,110,110,142,208,208, 80, 20, 23, 23, 99,254,252,249,181,206, 85,113,113,241,248,
+ 29, 59,118, 76,188,119,239,222,199,225,225,225,133,213, 47, 2, 28, 68,136, 16, 33, 66,196,127, 28, 77,106,144,127,195,145, 16,
+114,130, 82, 58, 18,192, 96, 0,242, 58,219, 32,132,156,168, 22,126,143,108, 47, 95,190,124,229,198,141, 27,111,214,108,215,236,
+179, 98,197,138,127,108,218,180,233,227,222,189,123, 31,186,114,229, 74,218, 95, 38,176, 0,132, 81, 74, 73, 51, 50, 6, 66, 81,
+ 20, 21,138,162,232,239,103, 82, 30, 23, 37,149, 37, 45, 62,185,167,167, 39, 18,147, 30, 19, 55,181,223, 77, 21, 88,232,219, 23,
+200,201, 1, 92, 93,171, 82,154,147, 3, 3,128,111, 87,172,128, 92, 46,175,237,138,170, 22, 38,205,210,233,245,122,146,159,159,
+ 79,117, 58, 93, 66,101,101, 37,215,192,197, 64,218, 57, 91,253,184,122,249,130, 86, 94,109,219,187, 70,158,252, 9,105,105,217,
+120,240,160,225,250, 81,169, 84,229, 70,163, 81, 85, 93,177,241,132, 97, 30,154,197,197,253, 12, 32,241, 73, 57, 9, 33,167, 39,
+ 77,154, 52, 50, 48, 48,144,116,238,220, 89,126,254,252,121,142,231,249, 71,196, 85, 75, 57,155,130,155,155,219,224, 23, 94,120,
+225,200,236,217,179, 49,102,248, 96, 76,236,223,149,102,229, 21,107, 1,156,111,106,145,230,106,145,117,195,207,207,111,226,248,
+241,227,191,106,211,166,141, 39, 0,120,123,123, 99,226,196,137,248,242,203, 47, 17, 26, 26,186, 23,192,238,152,152,152,184, 22,
+222,148,230,182,182,182,191,158, 63,127,222,193,220,220, 28,103,207,158, 69, 69, 69,197, 99,206,213,199, 31,127,172,188,119,239,
+222,150, 51,103,206,116, 6,192, 84, 47,211, 35, 66,132, 8, 17, 34,158, 13,152,160, 65,106,159,251, 39, 40,165, 35,235, 10,166,
+250, 66,171,230,123,205,126, 27, 55,110, 28, 89, 87,124, 1,192,166, 77,155, 62,174,179, 93,241, 87,100,170, 70, 96, 5, 17, 66,
+ 40,128, 32, 74,233,133, 39, 33, 50, 86,150, 61,209,140,165,114, 51,123,108,217,189,163,170,144, 36,143,198,101,153,236, 96,181,
+ 96,178, 84, 83, 28, 44,131,193, 32, 20, 21, 21,221,211,104, 52, 49, 73, 73, 73,143,137, 7,119,119,247,141,189,251,245,234,211,
+190, 71, 79,179,200,211, 71,112, 59,245, 62, 10, 10, 74, 0, 74,117, 13,241,217,217,217, 61,100,230,205, 83,153,231,228, 20, 51,
+130,144,221, 58, 33,225,213, 63,203, 25, 30, 30, 62, 45, 48, 48,208,247,202,149, 43,161, 86, 86, 86, 0, 64,235,138,171, 39,225,
+108, 64, 84,245,150, 72, 36,199, 24,134, 49, 27, 54,108, 24,222,122,235, 45,124,249,229,151, 28,149,153,141,219,113, 42,250,229,
+242, 74,253, 71,205,137,171, 26,196,196,196,132, 78,152, 48,161,107,124,124,188, 27,165,116,184,173,173,237, 22,163,209, 8, 65,
+ 16, 64, 41, 61,206,113, 92,170,191,191,255, 65, 71, 71,199,224,188,188,188,131, 49, 49, 49,139,154,185,201, 24,153, 76,182,247,
+220,185,115, 93,220,220,220, 16, 26, 26,138,138,138,138, 90,231,106,218,180,105,143, 56, 87, 87,174, 92, 41, 20,197,149, 8, 17,
+ 34, 68, 60,147, 48, 89,131,212,136,166,250, 34,171, 37,226, 12,128,118,249,242,229, 43, 9, 33, 39,170, 29, 46, 45, 0,245,211,
+206, 20, 83,157,224, 11,213,234, 49,236,209,156,152,222, 22, 25,244,165, 79,148,128,118, 3, 14,192,119,204, 5,164, 25,230,227,
+ 1, 51,183,190,147,100,154,192, 58,114,164,202,189,202,201,249,183,147, 85,237,102, 61,137,192, 42, 47, 47,191, 81, 88, 88,152,
+ 80, 82, 82,114, 21,128, 80,207,117,155,219,163, 71,143,105,187,246,238,183, 60,126,250,143,138,152,168,155,154, 7,121,197,168,
+ 48, 24, 13, 9, 25, 15,182, 55,196,231,228,228, 84, 68,129, 66,137,209,120, 78,126,227,198,207, 13, 56,121, 45,230,172,118,134,
+ 98, 1,156, 56,125,250,244,109,150,101,191,126, 26,156,117,197,149,189,189,253,175,251,247,239, 55, 59,124,248, 48,166, 79,159,
+142, 79, 63,253, 20,167, 79,159, 30,167, 86,171,207,149,233, 42,231, 82, 74, 31,152, 90,207, 95,206, 33, 46, 3, 29,126,118,149,
+ 72, 36,214,246,246,246,107, 39, 79,158, 12,142,227, 48,104,208, 32, 56, 58, 58, 30,146,201,100, 23,102,204,152, 49,122,243,230,
+205,230, 94, 94, 94,179,252,252,252, 92,154,161, 92,127,224,192,129, 17,222,222,222, 8, 15, 15, 71, 73, 73, 9, 92, 93, 93,241,
+230,155,111,202, 55,109,218,116,240,235,175,191,214,109,220,184, 81, 54,100,200,144, 45,103,206,156,241,169,168,168, 24, 42,138,
+ 43, 17, 34, 68,136,120,246,208,168, 6,105, 66,100, 61,225,121,106,142,147,110,220,184,241, 38,165,116,228,166, 77,155, 62, 6,
+ 96,246,151, 57, 88,213,202, 17, 0,130, 30,213, 87,229,166, 59, 88,186,166, 32,213, 53, 92, 0, 0, 32, 0, 73, 68, 65, 84, 5,
+214,219, 47,103,165, 8, 60,143, 47,151,178,144,155,217,163,221,128, 3,205,186, 82, 45,141,193,106, 64,173, 62,182,109,138,192,
+170,168,168,136,201,203,203,187,155,158,158,126,169,238, 36,162,158,158,158,163,156,157,157,215, 29, 56,112,192, 76,173, 86,195,
+163, 67, 55,171, 29, 63,255,171,210,217, 92,161,203, 44, 46,156,125, 61,171,252,104, 67,124, 74,165,242, 22,189,119, 47, 73,158,
+156,124,134, 0, 55,235, 9,161, 39,226,172, 65, 68, 68,196,180, 6, 4,219,159,226,116,115,115,235,237,224,224,240,235, 55,223,
+124, 99,174, 86,171, 33,147,201,160, 82,169,112,254,252,121,168,213,234,115, 45,189,200,182,207, 34,171,228, 2,222, 3, 15,166,
+175,103,118,229,171,239,125, 99,102,103,103,135,184,184, 56,116,233,210, 5,155, 55,111,150,167,164,164,116,238,212,169, 19, 82,
+ 83, 83,145,147,147,115, 43, 38, 38, 38,183,137,183,144,209,179,103,207,126,123,220,184,113,184,118,237, 26,114,114,114, 48,111,
+222, 60,253,155,111,190, 41,155, 58,117, 42, 41, 41, 41, 25,191,125,251,246,137,233,233,233,162,115, 37, 66,132, 8, 17,207, 56,
+ 26,211, 32, 77,224, 36,128, 23,235,187, 90,245,197, 87,141, 67, 85,119,187,254,254,213,255,215,253, 21,249,146, 84,159,140, 60,
+ 46,112, 32, 8,134,135,148,241,152, 68,132,156, 35, 20,124, 35,231,103, 89, 72,228, 42,104, 43,202, 4, 74, 31,117,123,234, 66,
+224,121,135,186,193,236, 44,203, 54, 26, 15,197,178, 44,172,173,173, 81, 86, 86, 6, 0,198,102,242,192, 27,199,141, 99,229, 47,
+189, 4,131,139, 11,168,193, 80,229, 98, 1,192,202,149,143,236, 40,147,201,106, 92,177, 38,187,181, 74, 75, 75,175,197,196,196,
+ 92,161,148,230, 1,192,192,129, 3,183,241, 60, 63,202,194,194,194,102,214,172, 89,134,130,130, 2, 28, 61,122, 20,223,127,255,
+189, 86, 99, 96, 99,139,245,220,204, 59,217,229,141,206,104, 95, 80, 80,240,187,231,173, 91,135,235,254,246,103, 57, 27,194,211,
+224,116,115,115,235,237,228,228, 84, 43,174, 20, 10, 5, 84, 42, 21,178,179,179, 33,145, 72, 90, 60, 73,231,193,249,196, 6, 20,
+239,204,121,123, 14,195, 48, 12,179,107,219, 63,205,108,204, 41,126,248,225, 7,132,132,132, 36,119,235,214,173,211,140, 25, 51,
+208,177, 99, 71, 36, 39, 39,227,139, 47,190, 80, 27, 12,134, 87,154,188,104, 37,146,105,235,214,173,163,106,181,154,220,189,123,
+183,214,185,218,184,113, 99,109,204, 85, 90, 90,154, 24,115, 37, 66,132, 8, 17,255, 29, 14,150, 41,241, 87, 5,213,226,233, 65,
+ 3,219,108, 29, 97, 85,127, 59,175,222, 54, 0,232,235,253, 63,254, 47, 19, 88, 13,102,152,224,155, 9, 99,131, 23,127,248,238,
+ 28,231,206, 29,151, 43,105,222, 41,208,146, 24,138,154,144, 27,194, 64,174,114, 0, 36, 10, 26,157, 84, 80,254, 71,130,182,128,
+ 18,124, 99,234,137, 59,119,238,140,220,220, 92, 20, 22, 22,214,254,198, 48, 12,236,236,236,160, 84, 42, 17, 29, 29,141,240,240,
+112, 35,128,117,205, 84,204,166,169, 83,167,174,152, 63,127, 62,211,115,250,116, 24, 46, 93,122,100,120, 24, 33, 4, 74,165, 18,
+102,102,102,200,206,206, 70, 74, 74,138, 64, 41,221,212, 20,231,157, 59,119,194, 41,165,249, 0, 16, 20, 20, 52,201,206,206,110,
+194,244,233,211,205,174, 93,187,134,245,235,215, 75, 66, 67, 67, 13, 81, 81, 81,156, 32, 8, 43,178,178,212,223, 53,151,215,164,
+164,164,168,186,219, 79,131,179, 62,158, 6,167,187,187,123, 47, 55, 55,183, 95,191,250,234, 43,243,220,220, 92, 40, 20, 10, 88,
+ 90, 90, 34, 35, 35, 3,235,214,173,211,112, 28,247,210,211,184,232,116, 58, 29, 14, 31, 62,156,211,166, 77,155,158,215,175, 95,
+ 31,180,108,217,178,109,173, 91,183,118,203,200,200,184,199,243,252,139, 81, 81, 81,247,155, 58,222,198,198, 38,208,209,209,145,
+ 68, 68, 68, 96,222,188,121,250,133, 11, 23,138,206,149, 8, 17, 34, 68,252,189,113,173,153,237,103, 14,141, 46,246,156,148, 70,
+191,191,147,146, 57,122,210,236, 85, 7,103,190,185, 34, 59,181,192,190,146, 56,143, 33, 68,225, 6,133,149, 43,172, 92,187, 33,
+ 61, 95,162,221,122, 88,157,117, 34, 82,251,179,182, 28, 99,147,210,232,247,245,108,191,110,117, 92,169,252, 45,187,119, 96,203,
+238, 29,224, 4,169,254,141, 55,222, 64, 65, 65, 1,210, 46, 79, 70,236,175, 3,209, 70,182, 29, 46,116, 39,242,243,243,241,237,
+183,223,210,208,208,208, 35, 70,163,209, 71,173, 86,127,211, 24, 39, 0,196,198,198,126,156,157,157,221,123,229,202,149,161,243,
+203,202,112,107,251,118,200,167, 78, 5,211,189, 59,204,205,205,225,224,224, 0,141, 70,131, 11, 23, 46,224,250,245,235,161,149,
+149,149,189, 99, 99, 99, 63,110,138,179, 70, 92,245,237,219, 87, 85, 92, 92,252,249,212,169, 83,205, 52, 26, 13, 10, 10, 10, 80,
+ 80, 80,128,200,200,200,243,122,189, 62, 32, 43, 43,171, 81,209, 82,151,147, 82,154, 89,243,253,105,113,214,197,211,226, 52, 55,
+ 55, 95,116,244,232, 81,115,134, 97,160, 80, 40, 96,109,109,141,204,204, 76,172, 93,187, 86,163,213,106, 95, 82,171,213, 38, 77,
+208, 89,151,243,245,237,180, 24, 4,159,239,252,106,167,176,253,139, 29,148,218, 13,132,153,181, 59,172,173,173,237,126,254,249,
+103, 33, 62, 62,254,156,155,155, 91,167,212,212,212,110,149,149,149, 1, 87,175, 94,189,223, 28,103, 65, 65,193,197,123,247,238,
+193,194,194, 2, 11, 23, 46,148,127,252,241,199, 7,191,254,250,107,221,199, 31,127,220,162,152,171,198,202,243,207, 64,228, 20,
+ 57, 69, 78,145, 83,228, 20,209,164,131, 5, 0, 55, 50,104, 58,128,183,123,180, 35,222,175,205,223,188,168,127,207,182,189,222,
+124, 45,192,182, 84, 40,161, 71,143,221, 46, 76,203, 44,191, 38, 97,241,229,205, 52,218,172,189,246,246,231,220,115,117,183,183,
+122,120, 4, 76,159, 62,125,253,210, 9,121,125,234,118, 29,238,255,105,255, 37, 66,200,170,156,156, 28,147,135,236,199,196,196,
+220, 4,240,146,175,175,111,191, 37, 75,150,172,123,217,211,211,127, 82, 80, 16,164, 82, 41,162,162,162,240,240,225,195,104, 0,
+ 31,196,198,198, 94,110, 73,225,148,150,150,126,216,177, 99, 71, 89, 82, 82, 18,238,220,185,131,148,148, 20,240, 60,127, 55, 43,
+ 43,107,220,147, 22,248,179,204,169,211,233, 62, 91,191,126,125,240,154, 53,107, 20,150,150,150,136,139,139,195,154, 53,107, 52,
+ 58,157,206,100,113,213, 16,230,255,147,110,248,114, 14,249, 62, 60,173,205,144, 46,238,189,183, 27,141, 70, 56, 57, 57,201,123,
+245,234,229, 10, 64, 29, 18, 18,194, 3, 72,107, 1,229, 7,222,222,222, 29,215,175, 95,223,110,218,180,105, 40, 46, 46, 22,157,
+ 43, 17, 34, 68,136, 16,241,223, 35,176,106,112,253, 14,141, 7, 48,181,123, 91, 50,232, 82,212,221, 89, 85,242, 21,187, 18,211,
+105,216,147,158, 56, 43, 43, 43, 10,192,144, 45,139,201, 35,243, 79,228,228,228, 12,127, 82,206,106, 1, 53,208,219,219,123,244,
+ 81,150,125, 23,105,105,224,121,254,179,248,248,248, 99, 45,225,233,213,171, 87,235,178,178,178,127, 26,141,198, 30, 60,207,203,
+ 47, 92,184, 0,157, 78,135,196,196, 68,173, 32, 8, 71,159, 36,109,255, 13,156,153,153,153, 49,110,110,110, 35, 9, 33, 39,150,
+ 45, 91,166, 88,187,118,237,159, 22, 87, 53, 88,180,147,230,238,247,243, 11, 99, 83, 82,120,163,209,200,114, 28, 7,158,231,101,
+ 79,194, 69, 41,189, 67, 8,233,185,120,241,226, 15,222,121,231,157, 69,155, 54,109,146,137, 49, 87, 34, 68,136, 16, 33,226,191,
+ 78, 96,213, 32,225, 46,253, 3,192, 31, 79, 51, 1,213, 93,135,142, 53,223,159, 6,103,181,160, 58,246,164,199,151,148,148,124,
+ 84, 88, 88,216,179,180,180,148, 75, 75, 75,211, 18, 66,120,134, 97,180,130, 32,108,228,121,254,187,191, 51,167, 90,173,142,112,
+117,117, 29,114,229,202,149,133, 21, 21, 21, 59,213,106,245,213,167, 85,215, 49, 49, 49,153,126,126,126,239,207,154, 53,107, 34,
+199,113,255,138,142,142,190,247,164, 92,148, 82, 61,128,247, 9, 33,191, 38, 36, 36,252,112,229,202,149, 92, 81, 92,137, 16, 33,
+ 66,132,136,255, 74,129,245, 87,160,126,215,225,179,128,228,228,228,105, 0,166,253, 47,114, 2, 64, 78, 78, 78,236, 95,193, 91,
+ 45,178,190, 6,240,245,211,226,163,148,198, 16, 66,186,160,106,148,136, 40,174, 68,136, 16, 33, 66,132, 40,176, 68,136,120, 74,
+ 34,139, 66, 92, 91, 80,132, 8, 17, 34, 68, 60, 67, 32, 0,186, 53,210,104,153,188, 82,246,147,140, 38,104,142, 95,228, 20, 57,
+ 69, 78,145, 83,228, 20, 57, 69,206,191, 31,103,115,220, 45,209, 31,207,180,192,106,201, 58,126, 45, 38, 39,164,219,211, 46, 40,
+145, 83,228, 20, 57, 69, 78,145, 83,228, 20, 57,255,126,156,127, 55, 48, 98, 17,136, 16, 33, 66,132, 8, 17, 34, 68, 60, 93,180,
+ 56, 6, 43, 48, 48,176, 29, 0, 68, 70, 70,222,121, 22, 50,224,227,227,115,161,109,219,182,173,110,223,190,109, 36,132,160,238,
+ 31, 0,200,229,242, 43, 87,174, 92,121, 67,172,234,255, 44, 44, 44, 44, 52, 44,203, 18,134, 97,192,178, 44,234,127, 54,244, 27,
+ 33,196, 41, 49, 49, 81,211, 24,167,155,223, 4, 79, 35,103, 92, 67,136,240, 29,229,153,153,132,173,249,164,255,164, 60,153,193,
+200, 12, 95, 10, 6,217, 34, 41, 85,124,164,190,121, 40, 75,172,133,134,209,173, 91,183,243, 61,123,246,236, 24, 23, 23,103,160,
+148,214,222, 63, 12,195,128, 16, 2, 65, 16,114,162,163,163,251,252,221,203,193,213,213,181, 31,128,205,213,131, 38,234, 34,133,
+ 16,242, 78,118,118,118,152,120,181,136, 16, 33,226,169, 9,172,158, 61,123,182,231,121,190, 63, 33,164, 31,165,180, 95,231,206,
+157,157, 42, 42, 42,224,231,231,151, 71, 8,185, 76, 41,189,204,178,236,165,107,215,174,221,110,142,171, 79,159, 62,209,122,189,
+190,115,139, 18, 40,145,148, 41,149,202,118, 97, 97, 97, 13, 54,180,206,206,206, 94,251,247,239,183, 75, 72, 72,128,133,133,197,
+ 35,127, 18,137, 4,189,122,245, 10,120, 86, 11,191,119,239,222, 6,158,231,165, 13,253,143,101, 89, 99, 68, 68,132,172, 25,177,
+123,143,227, 56,199,150,156, 83, 38,147,229, 71, 68, 68,152, 52,114,179,111,223,190, 42,142,227, 22,179, 44, 59, 80, 16,132, 46,
+213,233, 74,226, 56,238,130, 68, 34,249, 34, 60, 60,220,228,213,192, 89,150, 37, 5, 5, 5, 56,116,232, 16,186,249, 6,130, 82,
+192,187,107,251, 90, 33, 28, 25,155, 4,158,231, 17, 30,118, 26, 75,151, 46,133,175,175, 47, 52, 26, 13,219, 20,167,129, 19, 86,
+125,176, 96,114,208,134,173, 7,253,222, 95,248,186,106,195,214,131,190,239, 47,124,221,114,195,214,131, 62,239, 47,156,104,185,
+126,235,126,223, 85, 11, 39, 89,173,255,230,128, 30,192,252, 39,169,163,153, 93,186, 24, 25,142,107,240, 62, 17, 36, 18,238,187,
+164, 36,233,127,251, 67,128, 97, 24,247,157, 59,119, 90,159, 61,123, 22,102,102,102,181,247,143, 74,165,130,133,133, 5, 94,124,
+241, 69,254,105,157,203,207,207,239, 0,128, 49,213,155, 97, 49, 49, 49, 47, 62, 41, 23, 33,196, 66, 34,145, 44,148,203,229,253,
+ 57,142,235, 84,125,125, 39,235,116,186, 75, 28,199,109,165,148,106, 90,200,247,233,181,107,215, 58, 91, 90, 90,194, 96, 48,212,
+ 46, 12,207,178,108,199,192,192,192, 47, 0,244, 16,155, 12, 17, 34, 68,252,105,129,229,231,231,119, 20, 64,191,206,157, 59,155,
+ 13, 25, 50, 4,190,190,190,104,221,186, 53,148, 74, 37, 0,160,176,176,208, 41, 49, 49,113, 92, 92, 92,220,184,136,136, 8,248,
+249,249,105, 9, 33, 17,209,209,209,163, 27,227, 20, 4,193,227,244,233,211,112,112,112, 48, 41,113,130, 32, 96,196,136, 17,210,
+146,146, 18,115, 0, 13, 62, 44,115,115,115,133, 15, 63,252,176, 36, 60, 60,220,192, 48, 12, 40,165,132, 84,181,218, 4, 0, 56,
+142, 43,252, 79, 23,114,191,126,253,146, 0,184,213,228,137, 16,162, 14, 15, 15,239,194,243,188,244,218,181,107,141, 9,219,102,
+ 27,110,142,227, 28, 47, 95,190, 92, 91, 39,205,129,231,121,244,236,217,211, 36, 65,230,227,227, 51, 64,161, 80,252, 48,111,222,
+ 60,235, 62,125,250, 72, 60, 60, 60, 64, 8, 65,110,110,110,207, 43, 87,174,248,110,223,190,125,134,143,143,207,148,184,184,184,
+139, 38, 10, 44,236,219,183, 15,235,215,175,199,146,247, 63,197,155,211,199,131, 16, 2,133, 66,129,146,146, 18, 4,250,118,193,
+142,125,191,226,208,161, 67,208,106,181, 96, 89, 22, 94, 94, 94, 77,137, 83, 55,149,196, 54, 96,225,204,151,204, 63,219,190,207,
+124,225,204,151,240,249,142, 31,234,124,142,193,103, 59,246, 89,188, 53,115, 12,182,238,220, 19,216,187,119,111,183,136,136, 8,
+181, 41,117, 4, 0,148, 82,117,120,120,120, 23,134,227, 36,187, 82, 83,171,126,252,246, 91,224,193, 3,208,213,171, 1, 0,115,
+ 58,118,108,145, 3,220,189,123,247,203, 44,203,186,155, 80, 79,217, 9, 9, 9,253,254,132,240, 24, 12, 96,105,245,230,102, 74,
+233,185,102,238,179,236,185,115,231, 90,196,198,198, 54,230, 96,229,253, 9, 65,101, 79, 8,217, 10,192,140,101,217,119, 0, 12,
+ 15, 13, 13, 5,195, 48, 24, 58,116,104,144,159,159, 95, 71, 0, 27,205,205,205,169, 94,175,159, 23, 25, 25,153,103, 98, 30,251,
+ 89, 90, 90,254,243,192,129, 3, 54,189,123,247,102, 50, 51, 51,209,173, 91, 55, 20, 20, 20,248,133,133,133,249,204,153, 51,103,
+ 42, 33,100, 22,165,180, 37,171, 55,116,176,176,176,160, 83,167, 78, 37,117, 23,162,223,189,123, 55,124,181,218,182, 51, 91,183,
+ 46,172, 52, 24,202, 46,178,236, 42, 66,200,133,204,204,204, 28,177, 9, 17, 33, 66,196,147, 56, 88, 67, 47, 92,184, 0,163,209,
+ 8, 75, 75, 75,176,236,163,102,130,157,157, 29, 6, 12, 24,128,192,192, 64, 12, 30, 60, 24,201,201,201,102,159,124,242,201,243,
+205,157,208,220,220, 28, 17, 17, 17,224, 56, 14, 49, 49, 49, 40, 43, 43,195,232,209,163, 33,149, 74, 33,149, 74, 33,145, 72,106,
+ 63,157,157,157,161, 84, 42, 73, 73, 73, 73,163,124,214,214,214,109, 79,158, 60,201, 40, 20, 10,170, 82,169,232,133, 11, 23, 40,
+ 0, 90,213, 70, 62, 89, 4,127, 64, 64,128,179, 68, 34, 89,207,243,252, 88,158,231,229, 77,136, 6,163, 76, 38, 59,174,211,233,
+222,143,137,137,201,108,130,210,237,242,229,203, 86,181, 5, 59,116, 40,233,221,187,119, 73, 77,153,250,249,249, 61,178,115, 76,
+ 76,140,201,105, 85, 42,149, 8, 11, 11,131, 68, 34,129,109,255,254, 0, 0, 99,124, 60,164, 82, 41,208,181, 43, 0, 64,149,145,
+ 1,169, 84, 10, 23, 23, 23,147, 56,189,189,189, 7,183,106,213,234,224, 87, 95,125,101,198,178, 44, 82, 83, 83, 65, 8, 1,203,
+178,200,203,203, 67,191,126,253, 36,221,186,117,179, 95,177, 98,197, 97,111,111,239,215,227,227,227,207,153,224,146, 96,234,212,
+169,248,236,179,207,176,112,198,120,212,172,119,168,215,235,107,247,153, 55,117, 12,246,110,223,136, 15, 62,248, 0,167, 78,157,
+106,142,111, 67,231, 14,237,220,247,254,116, 6,125,123,245,196,222,159, 78,163, 79,175, 64,236, 13, 57,131,190,189, 2,241, 67,
+200, 25,244,239,221, 11, 63,132,156, 65,183,206, 29, 60, 30,222, 47,217,128,166,231,246,122,164,142,134, 13, 27, 70,122,247,238,
+ 93,210,141, 97,106, 4, 23,200,188,170, 37,157, 80, 45,176, 90, 10,150,101,221, 99, 99, 99,155, 21,184,190,190,190,127,246,190,
+ 94, 74, 41,237, 87, 45, 68, 0,160,201,250,185,113,227,198,243, 0,240,242,203, 47,159,239,214,173, 91,199, 91,183,110, 25,106,
+142,173,254,115,157, 56,113,226,189, 26,209, 69, 41,205,249,241,199, 31, 77,234, 50, 36,132,108, 62,126,252,248, 40,131,193,128,
+233,211,167,199,180,105,211, 70, 98,109,109,141,221,187,119,195,214,214, 22,122,189,254,218,231,159,127, 46,185,127,255, 62,190,
+249,230,155,157,117,220,173,166, 56, 7,245,239,223,127,223,201,147, 39, 21, 18,137, 4, 37, 37, 37,184,120,241, 34,108,108,108,
+ 96,102,102,134,113,227,198, 49, 3, 6, 12,176,123,254,249,231, 15, 16, 66,166, 81, 74, 77,158, 28, 89,171,213,210, 21, 43, 86,
+192,220,220,252, 17, 55, 92, 9,144,117, 87,175, 42, 54, 6, 5, 41, 86, 45, 90,180,244,219,111,191,237,229,225,225,177, 41, 43,
+ 43, 75, 45, 54, 35, 34, 68,136,104,169,192,130,133,133, 5,162,162,162, 64, 8,129,165,165, 37,172,172,172, 96,109,109,141,210,
+210, 82, 36, 38, 38,226,214,173, 91, 72, 79, 79, 7,195, 48,104,219,182, 45,106, 92,163, 58, 46,192,141, 6, 30,142, 96, 89, 22,
+247,238,221, 67,110,110, 46, 24,134,193,197,139, 23, 49,124,248,240, 71,196,149, 84,218,176,129, 83,159, 51, 44, 44,140,123,103,
+170,203,121,131, 94,227,192,113,250, 43, 97,148,206,243,245,245,189,224,228,228,228,225,237,237,205,215,116, 65, 53, 21,151, 85,
+159,147,101,217,141,243,231,207, 31, 55, 97,194, 4, 70, 34,145, 60,226, 0,233,245,122,232,245,122, 24,141, 70,104,181, 90,233,
+225,195,135, 95, 58,113,226,132, 57,128,151, 27, 75,167, 32, 8,143,228, 97,253,250,245,150, 28,199,225,171,175,190, 2, 0, 68,
+ 71, 71, 63,230,220,153,146,247,218, 74,148, 72, 80, 55,157, 53,101,200,213,219, 54,133, 51, 48, 48,208, 82, 46,151,127,191,101,
+203, 22,179,188,188, 60, 36, 36, 36,160, 71,143, 30, 88,181,106, 21, 52, 26, 13, 54,111,222,140, 59,119,238,192,201,201, 9, 43,
+ 87,174, 52,123,231,157,119,190, 15, 12, 12,236, 18, 25, 25, 89,214, 84, 58, 25,134,193,119,223,125, 7,142,227,192, 84,139,150,
+202,202, 74, 40, 20,138,250,233,193,234,213,171,107,247,105,140,211, 96, 48, 12, 91,177,104, 22,190,250,103, 8,186,182,115,198,
+137,208,171,232,217,173, 53, 78,157,191,134, 94,221,219,224,244,133,104,244,246,110,135,243, 87,111,226,237,249,147,240,238, 91,
+ 23,135, 53,149,247,250,101,190,118,237, 90, 75,158,231,113,106,217, 50,224,155,111, 64, 22, 46, 4,173,222,135, 48, 12,224,238,
+ 14,152,153,153, 92, 71,117,113,235,214, 45, 84, 86, 86, 62,246,187, 66,161, 64,231,206,157, 91,204, 73, 8,233,238,228,228,244,
+109,199,142, 29,187, 1,192,128, 1, 3,154,189,241, 27,185, 55,221,223,127,255,125,235,253,251,247, 67,161, 80,192,204,204, 12,
+230,230,230, 48, 55, 55,127,228,251,170, 85,171,248, 22, 92,159,242,228,228,100, 88, 90, 90, 98,215,174, 93, 18, 59, 59, 59,196,
+196,196, 64, 34,145, 96,242,228,201,232,222,189,187,196,204,204, 12, 23, 46, 92, 64,121,121,121,179,156,132, 16,149,133,133,197,
+183,199,143, 31, 87,240, 60,143,130,130, 2, 0,192,200,145, 35,193,178, 44,110,221,186,133,143, 62,250, 8, 63,255,252, 51,126,
+249,229, 23,165,159,159,223,183,132, 16, 95, 74,105,185, 9,229, 73, 43, 43, 43,169, 82,169,132, 82,169,132, 66,161,128, 66,161,
+128, 76, 38,131,142, 82,124,224,239,175,151,169, 84,124,143, 30, 61,218, 44, 88,176,128, 89,179,102,205, 32, 0, 63,154, 90,239,
+ 45,133,200, 41,114,254,175,113, 54,231,125, 0,168,251,130,170, 7, 80, 99,128, 20, 84,235, 15,251,122,191, 3, 64,205, 10, 49,
+142,141,108, 23, 0, 72, 4,208,165,250, 55, 30,192, 53, 0, 69, 79, 69, 96, 17, 66,104,157, 66, 35, 13, 20, 36, 74, 75, 75, 81,
+ 90, 90,138,204,204, 76,236,216,177,163,182,209,150, 72, 36, 96, 24,166, 54, 94,193, 20, 72,165, 82,100,102,102,194,219,219, 27,
+ 78, 78, 78,216,179,103, 15, 70,142, 28, 89,203, 87,243, 87, 87, 20, 53,133, 62,131, 38,118,126,169, 75,138,229,252, 77,161, 20,
+168,138,203,250,245,215, 95,237, 82, 83, 83,161, 84, 42, 97,102,102, 6, 51, 51, 51, 40,149, 74, 72,165,210,102,227,178, 4, 65,
+ 24, 53,126,252,120, 38, 52, 52, 20, 28,199, 65, 34,145, 64, 38,147, 65, 46,151,131,101, 89,200,100,178,218,191, 81,163, 70, 49,
+ 71,142, 28,121, 62, 40, 40, 72, 18, 22, 22,198, 53,114, 33, 34, 58, 58, 26,145,145,145,224,121, 30, 28,199,129,227, 56,104,181,
+ 90, 0,128,191,191,255, 35,251, 95,189,218,178,213,105,234, 58, 87, 18,137, 4,164,107, 87,112,213,206,149, 68, 34, 65,145,171,
+ 43, 0,192,193, 52, 67,111,209,244,233,211, 45, 21, 10, 5,110,220,184, 1,133, 66, 1,141, 70,131, 49, 99,198,160,188,188, 28,
+ 28,199, 65,161, 80,160,178,178, 18,206,206,206, 24, 60,120,176, 69,104,104,232, 34, 0,107,155,113,111, 48,115,230, 76,108,219,
+182, 13, 95,253,243, 39,188, 61,235,149,199,246,217,190,183,106,249,196, 53,107,214, 32, 44,172,233,120, 98, 65, 16,216, 62,254,
+157, 81, 90, 16, 0,169, 84,138,190,190,237,193,178, 44,250,248,117,128, 68, 34, 65,191,128,142, 96, 89, 22, 3, 3,187,160, 93,
+187,118, 16, 4,129,109,230, 97,209, 96, 29,233,245,122, 32,167,129,158,160,220, 92,160, 77,155, 39,121, 40, 97,217,178,101, 37,
+106,181,218,240,152,133,230,230, 38, 59,114,228,136,117, 75,140, 87, 66, 72,143,206,157, 59,159, 57,127,254,188,202,217,217, 25,
+ 28,199,193,104, 52, 66,163,209,224,149, 87, 94, 1,128,163, 45, 72, 91,246,250,245,235, 45, 26,112,176, 30,233, 54,164,148,154,
+220,101, 40,145, 72,150, 47, 91,182,108,248,152, 49, 99, 36,150,150,150,144, 74,165,144,203,229,144,203,229,144,201,100,184,119,
+239, 30,140, 70, 35, 66, 66, 66, 40,203,178,239,154,192,247,230, 15, 63,252, 96, 37,151,203,145,147,147, 3, 66, 8, 40,165,144,
+201,100, 72, 75, 75,195,151, 95,126,137,233,211,167, 35, 35, 35, 3,174,174,174, 88,178,100,137,106,211,166, 77,111, 2,216,104,
+ 74,131,161,215,235,125,205,204,204,160, 80, 40, 80, 35,180, 0, 32,214,220, 60, 49, 45, 45,173,167,139,139, 75,231, 86, 23, 47,
+238, 12, 10, 10,234,102,111,111, 31, 64, 8,217, 79,255,202,185,110, 68,136,248, 31, 64,115, 26,164, 70, 16, 17, 66, 78,212,217,
+111,100,205,246,242,229,203, 87,110,220,184,241, 38, 33,228, 68,221,223,107,246,171, 62,199,137,134,182,171,143,181, 95,177, 98,
+ 69,183, 77,155, 54,125,220,187,119,239, 67, 87,174, 92, 73,123,106, 2,171, 58,110,137, 54,145,177,199, 92,168,250, 48, 69, 96,
+213, 60,164, 43, 43, 43, 81, 80, 80,128,161, 67,135,194,204,204, 12, 12,195, 32, 51, 51, 19, 29, 58, 84, 53,142,241,241,241,248,
+240,195, 15,209,181,107, 87, 24, 12,134,102,211,116,230,196, 46,237,149,115,188, 86, 16,170, 30,252, 15, 30, 60,160, 27, 55,110,
+ 44, 15, 13, 13,213,255,251,212,181, 52,164,185,184, 44, 74,169, 68, 34,145,192,104, 52, 62, 50,202,141, 16,130, 65,131, 6,225,
+210,165, 75,181,191, 85, 59, 48, 76,117, 89, 54, 90, 8,213,142,215, 35,141,119, 13,106, 28, 44, 74, 41,116, 58, 29,140, 70,227,
+147, 85,102,181,243,199,213,219,110, 9, 24,134, 9,234,223,191,191, 36, 37, 37,165,182, 33, 52, 24, 12, 24, 56,112, 32, 24,134,
+ 65, 70, 70, 70,237,239,148, 82,248,248,248,200, 46, 93,186, 20,212,156,192, 98, 24, 6, 59,118,236,168,205,219, 55,223, 31,193,
+155,211, 95,174,117,114,190,249,254, 72,237,126,239,191,255,254, 99, 14, 86, 99,144,201,100,181,117,193,178, 44, 36, 18, 73,237,
+103,205,119, 83,219,191,198,234,136,110,216, 0,108,216, 80,229, 92, 1,168,208,104,170,196,113,223,190, 45, 22, 87,122,189, 30,
+106,181,218, 16, 31, 31,255,216, 64, 3,111,111,239,123,122,189,222,228,244, 18, 66,156,106,196, 21,165, 20, 47,190,248, 34, 22,
+ 45, 90,132,128,128, 0,148,149,149, 97,233,210,165, 40, 46, 46,254,162,123,247,238,159,220,184,113, 99, 21,165,116,123, 83,124,
+ 71,142, 28,121,172,139,191, 75,151, 46,231,123,245,234,213, 49, 54, 54,182,174,232,114, 13, 8, 8,184, 71, 41,109,114,116, 97,
+ 77, 64,123,247,238,221, 49,103,206, 28, 28, 62,124, 24,123,246,236, 65, 77,124,211,216,177, 99,241,210, 75, 47, 33, 63, 63, 31,
+206,206,206, 36, 59, 59,251,186,159,159, 95,147,129,239,114,185,124, 64,159, 62,125,152,178,178,178,218,231,144, 84, 42, 69, 90,
+ 90, 26, 54,111,222,140,137, 19, 39,162, 93,187,118,224,121, 30, 26,141, 6,131, 6, 13,146,108,221,186,117,128, 41, 2, 75, 34,
+145,188, 27, 28, 28,252, 49,128,174,117,159,133,132,144, 91,132,144, 85, 85,186, 58,247,214,168, 81,163,238, 5, 7, 7,251,180,
+105,211,198, 33, 33, 33,129,133,184,138,128, 8, 17,127,214, 13, 51, 89,131,212, 8,164,250, 66,107,227,198,141, 35,235,255, 86,
+ 87, 76, 53,244,189,238,177,155, 54,109,250,184, 14,119,197,211,200,215, 83, 91, 42,199, 84, 81,160,215,235, 17, 27, 27,139,246,
+237,219,195,204,204, 12, 18,137, 4,190,190,190,136,141,141, 69,151, 46, 93, 32, 8, 2, 86,174, 92,137,213,171, 87, 35, 36, 36,
+ 4,137,137,137, 18,103,103,231, 38, 57,119, 30, 46,123,196, 74,176,180,180,108, 19, 18, 18,242,167,226,178, 8, 33,181, 13,244,
+232,209,163,241,219,111,191, 65, 42,149,214,118,113,250,249,249,225,250,245,235, 38, 9, 1, 74,105,109,227, 93, 94, 94, 14,189,
+ 94, 15,142,227,224,232,232,136, 55,222,120, 3, 28,199,129,231,249,218,134,157,231,121,176, 44,139,158, 61,123, 82,134, 97,140,
+ 87,175, 94,109,114, 52,161, 33, 46,174, 42,109,255,248, 7, 56, 0, 22,247,239, 67, 42,149,162,216,173, 42,102,187, 85,121,121,
+163, 93,132,245,193,243,124, 23,119,119,119,164,164,164, 64,161, 80, 64, 46,151,163, 85,171, 86, 88,184,112, 33, 42, 42, 42,240,
+221,119,223,161,184,184, 24,114,185, 28, 82,169, 20,237,218,181,131, 94,175,239,210, 28, 47,203,178,152, 59,119, 46,190,255,254,
+123,236,216, 92,213, 5,248,237,150,170,207,186,211, 51, 48, 12,131, 13, 27, 54, 96,208,160, 65, 38,187,161, 75,151, 46, 53,107,
+236,255,135, 14, 29,210,154, 82,229,117,235,168,180,180, 20,122,189, 30, 60,207, 67,229,233,137,105,211,166, 85,213,207,171,175,
+130,231,121, 8, 83,167, 86,137, 4,115,115,147,235,168,174,192,106, 44, 61,148,210, 6,187, 14,155,192,208,229,203,151,171, 4,
+ 65,192,160, 65,131, 48,125,250,116,248,251,251, 99,235,214,173, 8, 15, 15,199, 63,255,249, 79, 28, 56,112, 0, 28,199,201,134,
+ 13, 27,182, 8,192,246,150,222,215, 44,203,186,239,220,185,211,250,151, 95,126,129, 74,165,130,141,141, 13,172,172,172, 96, 99,
+ 99,131,113,227,198, 53, 55,186,112,120,104,104, 40,108,109,109, 17, 29, 29, 13,185,188,202,181, 87,169, 84,118, 97, 97, 97,149,
+219,182,109, 43, 53, 51, 51,147,200,229,114,124,248,225,135,144,203,229,152, 57,115,102, 80, 80, 80,144, 34, 44, 44,172,193,130,
+224, 56,174,147,173,173, 45,114,115,115,107, 5,185, 74,165,194,135, 31,124,128, 41, 83,167,214,138, 43,185, 92,142,149, 43, 87,
+ 98,200,144, 33,168,172,172,236,100, 74, 94, 51, 51, 51, 99, 0, 12,105,110, 63, 65, 16, 72,117,125, 81, 0,130,216, 60,138, 16,
+241,255,234,118,157,168, 47,178,254, 12,215,242,229,203, 87, 2,160,203,151, 47, 95, 89,179,189,113,227, 70, 45,128, 63, 29, 95,
+249,212, 4,150, 41, 14, 86,255,254,253,149,219,182,109,131,139,139, 11,124,125,125,107, 29, 22, 63, 63, 63,108,221,186, 21,211,
+167, 79,199,169, 83,167,208,165, 75, 23, 12, 31, 62, 28, 3, 6, 12, 64,247,238,221,155,229,125,103,186,251,101,174,178,204,198,
+160,175,140,218,126,196, 48,189,180,180,244, 82,187,118,237, 92, 51, 50, 50,184,178,178,178,218,160, 97, 66, 8, 2, 2, 2, 32,
+145, 72,174, 69, 68, 68, 76, 52,197, 17, 26, 63,126, 60,126,249,229, 23,140, 29, 59, 22,103,207,158, 5, 0, 4, 4, 4, 32, 41,
+ 41, 9,230,230,230, 38, 59, 68, 53,141,119, 89, 89, 25,182,110,221,106,210, 49, 6,131, 1,193,193,193,205,158,160,166,187,150,
+175,183, 93, 87,220,152, 42,176,106,202, 73, 38,147,129, 97,152,218,174,156,242,242,114,148,148,148,212,118,149,214,252,153,218,
+ 53,204,178, 44,182,110,221, 10,163,209,136,121, 75,215,128,101, 37,152, 55,245, 37,176,108,149, 64,221,177,239, 87,240, 60,143,
+159,246,124,137,229,203,151,155,212, 53, 92,195,187,109,219, 54, 45,195, 48,143,185, 87, 12,195,180,200,193,171, 91, 71,219,182,
+109, 51,233,152,162,162, 34,140, 25, 51,198,228,147,212, 13,234,111,169, 0,107, 0,199,222,123,239,189, 25, 6,131,161,115,207,
+158, 61,205,102,207,158,141,204,204, 76,108,217,178, 69, 87, 84, 84,180,125,200,144, 33, 51, 84, 42,149,181, 70,163,209,164,167,
+167,127,254, 36,247,181, 32, 8,217,115,230,204,177,168,153, 35,171,102,100, 33,203,178, 38,141, 46,228,121, 30,187,118,237,170,
+237, 26,108,168,254,234, 94, 83,166,136,212,164,164, 36, 92,186,116, 9, 35, 70,140, 64, 69, 69, 5,140,122, 61, 22, 93,191,142,
+174,147, 38, 65, 47,147, 65, 16, 4, 40, 20, 10,108,222,188,249, 47,123,198,215, 17, 88, 34, 68,136,248,255,117,187, 70, 62, 77,
+174, 26, 7,107,227,198,141, 55, 55,110,220,248,152, 27,246,151, 10, 44,150,101, 81,119,200,114, 67,141,177,169, 49, 88,151, 47,
+ 95,214,157, 63,127, 94,149,149,149, 85,235, 16, 73, 36, 18,180,109,219, 22,132, 16,156, 58,117, 10,251,247,239,199,170, 85,171,
+ 32,145, 72, 96,101,101, 5, 31, 31, 31, 99, 78, 78,211,163,161,251, 12,120,181,237,255,177,119,222,225, 81, 84,251,255,127,159,
+153,217,158, 94, 73,150,132, 64, 8, 53,148, 84, 18,144, 18,145,142, 72, 17, 68, 68, 69, 65, 44,148, 43, 32, 2,126,239,189,128,
+138, 1, 1, 17, 68,154,168,168,160, 20,233, 8, 2,210, 33, 9, 73, 32,212,208, 18, 66, 72,239,109,179,117,102,206,239,143,100,
+115, 3,146,100, 3,168,252,116, 94,207,179,207,238,236,206,190,231,204,153,153, 51,239,249,156, 86,221, 6, 75, 0, 0, 47, 47,
+175,166, 91,183,110,173,175, 13, 86,131,227,217,152, 76, 38,200,100, 50,236,221,187, 23,253,250,245,195,177, 99,199,160,174,110,
+212,124,229,202, 21, 4, 5, 5,225,198,141, 27, 54,221,192,107, 71, 71, 12, 6, 3, 0, 32, 37, 37,197,214, 19,160,225,210,190,
+ 67, 7, 8,213,145, 43,142,227,238,137, 92,177, 44,139,219,213,233,110,111,131,150, 92, 46, 79,206,201,201, 9,243,244,244, 68,
+ 81, 81, 17, 20, 10,197, 61,230,140,227,184,154,200,150, 66,161,176,182,211, 74,110, 72,151, 97, 24, 76,153, 50, 5,155, 55,111,
+ 6, 0,188,253,234, 48,104, 52,106,152, 76, 38, 24, 12, 6,188,253,234, 80,172,254,110, 23, 24,134, 65,116,116, 52,250,245,235,
+103,115, 4,107,210,164, 73,117, 70,176,118,237,218,165,183, 53,159,173,199,200,218, 54,238,113, 30, 35, 91, 35, 88,182, 24, 44,
+ 66,200,155,237,219,183,159,161, 82,169,238,230,230,230,110,241,242,242,154,178,124,249,114,223, 59,119,238,192,209,209, 17, 7,
+ 14, 28, 80, 77,157, 58,245,157,179,103,207,142,161,148, 30,106, 40, 93, 29, 59,118, 60, 18, 17, 17,209,166,246, 48, 13,213,215,
+125,246,149, 43, 87, 30,101,128,209,195, 3, 6, 12, 24,236,232,232,136,215, 95,127, 29,114,185, 28, 35, 70,140,128,147,147, 83,
+209,186,117,235, 16, 22, 22, 86, 99,226,231,206,157,139, 59,119,238,128, 16,114,184,174,232, 85,245,249,121,173, 73,147, 38, 33,
+163, 71,143, 70, 73, 73, 9,178,178,178,224,232,232,136,192, 37, 75,112,241,157,119, 16,180,102, 13,152,222, 85, 53,157,181,206,
+207,107,117,233,249,248,248,132,139,162,248, 49,128,174,248, 95, 39, 29, 10, 32,134, 97,152,127,103,100,100,196, 63,160, 76,100,
+172,230,177,122, 93, 9, 9,137, 63, 49,130, 85,219,104,213,138, 66,213, 69,126,237,118, 89,117, 25,180,218,109,178, 0, 24, 31,
+ 71, 90,185, 90,133,251,253, 61, 0,111, 37, 37, 37, 5,116,232,208, 1,233,233,233, 40, 41, 41,121,160,128,157,157, 29,212,106,
+ 53,110,222,188, 9, 74,233,173,134,110, 48,181,163, 10,181,123, 12,126,240,193, 7,152, 61,123, 54,250,246,237,139,167, 26,217,
+182,229,215,221,107,202, 78, 29, 18,117,130, 72,179, 0, 32, 55, 55, 87,252,232,163,143,116, 7, 15, 30, 52,213,110, 40,111,173,
+206, 19, 4, 33,167,129, 3,200,151,149,149,113, 10,133, 2,132, 16,156, 62,125,186,102, 24,137, 43, 87,174, 64, 38,147, 33, 45,
+ 45, 13,114,185, 28,102,179, 25,168,170, 38,224, 27,115,243,110,132,195,182,253, 96,222,215,230,170,177,145,171,234,168,217,177,
+184,184,184,160, 62,125,250,112, 58,157,238,129, 6,203,106,174,148, 74, 37, 98, 99, 99, 77,122,189,190,193, 17,174, 89,150,197,
+178,101,203, 96, 54,155,107,134,105,176, 86,135, 89,199,194,122,251,213,161,216,177,241, 75,204,156, 57,211,230, 54, 88, 50,153,
+ 12, 95,127,253,181, 94, 38,147,213, 84, 51,214,110,127,101,109, 59,247, 48, 6,235,113, 29, 35, 47, 47, 47,119, 15, 15,143,229,
+ 46, 46, 46, 42,131,193,240,187,245,107,255, 94, 95,132,203,138,191,191,255,251, 73, 73, 73, 77,138,139,139,181,123,247,238,141,
+244,244,244,132, 82,169,196,176, 97,195, 42, 69, 81,100,150, 47, 95,174, 90,179,102,141,106,214,172, 89,171, 0,180,180,193,252,
+ 54, 93,179,102,141,211,137, 19, 39,238, 25,158, 96,204,152, 49,143, 52,192,104, 98, 98,226, 11,145,145,145,126,130, 32, 92,236,
+220,185, 51,119,231,206, 29, 60,251,236,179, 80,171,213, 53,199, 70,167,211, 89,219,165, 81,142,227,130, 26,154, 33,194,104, 52,
+158, 60,122,244,104,208,240,225,195,153, 27, 55,110, 64, 46,151, 87,245,238,237,218, 21, 65,107,214,224,210,244,233,232,149,154,
+ 10,131,197, 2,181, 90,141,253,251,247, 91, 42, 43, 43, 79,214, 99,216, 86,198,196,196,180, 87,169, 84, 48,155,205, 16, 69, 17,
+ 12,195, 16,150,101,187, 5, 6, 6, 46, 1,208,163,246,250, 90,173,182,245,228,201,147,155,242, 60, 47,100,102,102, 22, 73, 81,
+ 44, 9,137,199, 22, 77,106,168,160,206,191,207, 28,153,106, 45,231,163,106,110,229,103,171, 63,163,214,231,120, 0,225,247,173,
+107,253,221,116,223,187,245,247,164, 63, 52,130,197,178,236,240, 55,222,120, 99, 69,223,190,125,163,102,204,152, 1,123,123,123,
+100,103,103,215, 68,170, 20, 10, 5,124,125,125,161,215,235,113,226,196, 9,148,148,148, 28,103, 89,118, 74, 67, 27,180, 88, 44,
+ 53, 55,189,218, 61, 6,253,253,253,177,107,215,174,223, 25,130,186,134, 44,168,205,218, 29,186, 54,181,151,207,157, 59,231, 7,
+ 0, 31,126,248,225, 67,101,138, 76, 38,219,179,109,219,182,231,251,247,239,207, 88, 35,120,214,116,212, 30, 74,194,104, 52,226,
+251,239,191,167, 42,149,234, 72, 93, 61, 8,107,239,119,237, 8,214,227,186,121, 91, 44, 22,104,210,210,238,233,213,233, 83, 86,
+118,207,114, 59,209,246,102, 34,132,144,101,171, 87,175,158, 16, 18, 18,226,226,237,237,141,202,202, 74, 16, 66,224,225,225, 81,
+ 99, 96, 84, 42, 21,228,114, 57,146,147,147,113,232,208,161, 74, 74,233, 50, 91, 34, 88,239,190,251, 46,118,238,220,121,143,121,
+178,154, 43,235,112, 13,148, 82, 44, 94,188, 24,131, 7, 15,174, 55,114, 90,219,240,189,254,250,235,117, 70,176, 14, 31, 62,172,
+183,213,172,253, 17, 6,171,105,211,166,157, 34, 34, 34,246,174, 93,187,214,213,221,221, 29, 89, 89, 89,247,156,211, 77,155, 54,
+237,212,165, 75,151,189,107,215,174,117,245,240,240, 64,122,122,122,131,251,157,154,154,186,122,200,144, 33,243,134, 14, 29, 74,
+250,244,233, 3,181, 90,141,127,255,251,223,184,122,245,234,100, 0, 23,119,239,222,125,126,226,196,137,104,222,188,185,151,141,
+233,175, 25,104,180,118, 84, 90, 16,132,188, 71, 45, 96,120,158, 95,184, 98,197, 10, 78,163,209, 64,175,215, 35, 63, 63,255,158,
+ 42,193,202,202, 74,120,121,121, 97,242,228,201,228,243,207, 63, 95,140, 6,198,193,226,121,254,139,241,227,199,143,235,211,167,
+143,179, 86,171, 69,118,118, 54,228,213,213,130,228,233,167,209, 51, 37, 5, 38, 65,128, 70,163, 65,114,114, 50,214,175, 95,175,
+ 51,155,205, 15,172,147, 15, 8, 8, 80, 48, 12, 19, 32,151,203, 49,118,236,216,123,126,251,238,187,239, 16, 41, 8, 33,175,251,
+248, 20,136, 12, 99, 42,234,216,241, 4,195, 48,100,202,148, 41, 62, 61,122,244,104,127,249,242,229,212,130,130,130,179,210,109,
+ 81, 66,226, 79, 35,254, 47,250,239,227, 55, 88,241,241,241,183, 1, 12, 14, 9, 9,121,225,196,137, 19,139,166, 79,159,238,222,
+189,123,119, 20, 21, 21,193,207,207, 15,222,222,222, 72, 72, 72, 64, 82, 82, 82, 33,165,116,118, 66, 66,194, 79, 15,184, 89,255,
+110,182,109,189, 94,143,245,235,215, 99,234,222,189, 88,218,161, 3,138,238, 27, 7,169, 54,159,127,254,185, 53, 66, 84,175,214,
+238,131,252, 0, 0, 32, 0, 73, 68, 65, 84,230,253,109,176,130,131,131, 99,154, 53,107,230,157,158,158,206,215,142, 96, 89, 63,
+223,223, 6,235,126, 77,163,209,248,193,150, 45, 91,100, 63,252,240,195, 96, 81, 20,101,245,152, 80, 94,165, 82, 29, 50,153, 76,
+ 51,235,219,119, 74, 41,241,244,244, 68,243,230,205,161,215,235, 27,213,171,173,246,205,248, 65,251,110, 50,153,176,108,225, 66,
+ 44, 61,115, 6,147,186,118,173,215,136, 60,168, 93,209,253,154,113,113,113,229,193,193,193, 19,103,206,156,249,253,135, 31,126,
+168,246,240,240, 0,207,243,248,226,139, 47, 32,138, 34, 68, 81,172, 49, 87, 51,102,204,168,172,172,172,156,120,254,252,249,242,
+134,142, 17,203,178, 88,188,120, 49,120,158,175, 25,166,193, 58,208,168, 74,165,130,193, 96,192, 55,155,247,131, 97, 24,204,152,
+ 49,227,119, 85,211, 15,210,180,166,229,199, 31,127,212,223, 31,181,186,127,185, 14, 51,121,207, 49,178,183,183,135,159,159, 31,
+220,220,220, 30,219, 49,114,115,115,123,119,253,250,245,174,122,189, 30,201,201,201, 72, 78, 78, 6,195, 48,215,238,255, 93,167,
+211,225,210,165, 75,184,122,245, 42, 8, 33,215,234,203, 79, 74,233, 18, 66,200,166, 95,127,253,117,168, 82,169, 28,238,233,233,
+233,147,158,158,190,153, 82,186, 21, 0,222,126,251,109, 88, 44,150,134,170,246,107, 52, 47, 94,188, 88,231, 0,193,181,171, 15,
+173,215, 16,165, 52,251,220,185,115,221,108,185,222, 1,152,118,239,222, 13,123,123,123,236,220,185,147,119,113,113,225,230,207,
+159, 15,133, 66,129,121,243,230, 33, 61, 61,157,159, 48, 97, 2, 39,138, 34, 40,165,166,134, 52, 41,165, 21,132,144,201, 61,122,
+244, 88,255,203, 47,191,168, 90,183,110, 13,235, 64,196,115,230,204,193, 23, 95,124, 1,141, 70,131,107,215,174, 97,232,208,161,
+122,157, 78, 55,185,246, 24, 88,181, 53,121,158, 39,114,185,156,138,162,136,127,255,251,223,247, 12, 44,170,209,104,160, 6,176,
+ 32, 62, 94, 29, 29, 21,165,158, 50,111,222,208,106,131, 39, 92,190,124, 57,117,245,234,213, 49,148,210,227, 13,236,251,163, 86,
+133, 72,154,146,230, 63, 74,243,239, 70,131,245, 71,231,206,157,219, 18, 20, 20,116,112,225,194,133, 31,237,216,177,227,181,169,
+ 83,167, 18, 71, 71, 71,108,221,186,149, 22, 23, 23,255,160, 82,169, 62, 56,117,234, 84,137, 77, 27,227,184,235,135, 15, 31,238,
+ 60,125,250,116, 25, 59,115, 38,254,115,223, 36,191,247,147,156,156, 76,117, 58,157, 96, 48, 24,234,157, 83,236,113,183,193, 74,
+ 76, 76,204, 1, 48,246, 49,230,243,190, 79, 62,249,100,212,134, 13, 27, 56,181, 90,141,148,148, 20,220,176, 78,191, 82,183,121,
+195,103,159,125,198,155,205,230, 58,123, 50,168, 84,170, 59,167, 79,159,246,249,232,211, 79, 89, 35,195,224,243, 90,195, 21, 60,
+ 40,106,115,250,244,105,170, 80, 40, 74, 27, 74,236,249,243,231, 15,132,134,134,190, 52,101,202,148,111,134, 12, 25,162, 9, 11,
+ 11,147,251,249,249,129,227, 56,164,167,167,227,228,201,147,166, 3, 7, 14,232,141, 70,227,235,231,207,159, 63,100, 75, 6, 48,
+ 12,131,247,222,123, 15, 12,195,160, 77,203,102, 56,120, 34,254,158, 30,115,187, 15,158,130,151,167, 27, 58,116,232,128, 69,139,
+ 22, 97,216,176, 97, 13,233, 9,102,179,153,213,104, 52, 53, 99,149, 89,247,221, 90, 93,216,187,119,111,245,233,211,167,245, 38,
+147, 9, 44,203, 54, 20, 14,219,183,100,201,146,145, 63,252,240,131, 76,163,209, 60,182, 99,196,243,124,187,226,226, 98,232,116,
+ 58, 36, 36, 36,208, 47,191,252,178,160,180,180,116,110,237,223,139,138,138, 80, 94, 94,142,179,103,207,210,175,190,250,170,160,
+188,188,188,193,161,226, 41,165, 57, 0, 86, 87,191,238, 33, 55, 55,183,210,108, 54,107,178,179,179, 45,143,122,226, 90,171, 15,
+ 99, 99, 99,225,224,224, 0, 39, 39,167, 70, 85, 29, 82, 74,103, 28, 60,120, 80,142,234,169,114,242,243,243,207,202,100, 50,133,
+ 66,161, 64,102,102, 38, 68, 81,236,178,110,221,186,104, 0,102,142,227,166,218,168,121,136, 16,242, 90, 96, 96,224,154,121,243,
+230,217, 69, 69, 69,113, 90,173, 22,253,250,245,195,245,235,215,241,203, 47,191, 88, 86,173, 90, 85,169,211,233,222,162,148, 30,
+169,167, 60,162,148, 82,194,243,252, 61, 29, 55,172, 61,100,245,162,136, 15,130,131, 13,148,227, 76,243,230,205, 59, 14, 0, 89,
+ 89, 89,197,249,249,249,137,162, 40, 30,207,206,206,206,148,110, 33, 18, 18, 18,117,154,208,198, 52, 33,136,136,136,136, 16, 69,
+241,103, 65, 16,100,132,144, 17,137,137,137,167, 27,227,112, 35, 34, 34, 28,228,114,249, 97,189, 94, 31,104,203,246, 20, 10, 69,
+137,197, 98, 25, 28, 31, 31,127,161, 62,215,252,230,112,187,235, 26,149,200, 86, 26, 44,183,214,238,176, 12, 12, 9, 9,185, 51,
+104,208, 32, 85, 93,109,176,204,102,243,205,132,132,132,103,254, 44,119, 79, 8, 97,130,131,131,207,200,100,178,136,234,237,215,
+190, 89,212, 12,150,104, 93,174, 21,157, 74,191,126,253,122, 43, 74,169,185,142,252,244,148,201,100, 71, 13, 6,131,159, 45,105,
+ 82, 42,149,217, 70,163,177,127, 98, 98, 98,170, 45,251,222,189,123,119,103,158,231,255,165, 84, 42,159, 54, 26,141,237, 0, 64,
+173, 86, 39,235,245,250,163, 28,199, 45,175,203, 88, 63, 72,179,115,231,206, 58,150,101, 73,237, 33, 25, 30,244, 94,123,184,134,
+138,138, 10, 79,235, 36,223,247,107,246,232,209, 99,195,232,209,163, 7,190,242,202, 43,132,227,184,154,124,179, 30,107,107, 53,
+180,209,104,196,134, 13, 27,232,246,237,219,247, 31, 59,118,108, 92, 67,199,136,227,184, 8, 66, 72,205, 49,122,208,245,209,152,
+ 99,228,231,231, 23,100,103,103,183, 14, 85, 35, 11,167,148,150,150, 78,205,204,204,204,172,253,187, 90,173, 94, 7, 64,193, 48,
+204,239,126,127,152,243,147, 16, 50,177,109,219,182, 51,175, 93,187,182,172,174,177,175,108,213,236,212,169,211,145, 46, 93,186,
+180, 57,127,254,188,217,122, 13,213, 53,254,149, 45,154,161,161,161, 91, 0, 12,174, 94,255,112, 66, 66,194,208,135,125, 74, 38,
+132, 56,201,229,242, 73,106,181,186,167,193, 96,104, 91,253,208,113, 77,175,215,159, 48,155,205, 95, 82, 74, 75, 27,210,244,247,
+247, 63,123,242,228,201, 64,107,212,211, 58,122, 59,203,178,104,218,180,233,185,172,172,172, 30, 82,212, 65,210,148, 52,165, 8,
+214, 31,110,176,164, 19,229,159,171,105, 29,169,213,150, 70,189,127, 70, 58,187,118,237,170,229, 56,110,129,209,104,236, 95,223,
+ 40,237, 44,203, 10,106,181,250, 87,147,201,244,127,247, 79,246, 44, 29,119,233,252,124,152, 94,132,210, 49,146, 52, 37, 77,201,
+ 96,217, 2, 39,101,129,132, 45, 60,105,189,165,170,205,210, 56,233,200, 72, 60,202,249, 89,109,160,250, 74, 57, 40, 33, 33,241,
+184, 97,164, 44,144,144,144,144,144,144,144,144,120,188, 16, 0, 29,235,120, 34,108, 76,155,143,142, 15,241,196,121, 73,210,148,
+ 52, 37, 77, 73, 83,210,148, 52, 37,205,127,150,102, 67,218,127,151,170, 71,169, 13,150,164, 41,105, 74,154,146,166,164, 41,105,
+ 74,154,127,185,230,223, 13,169,138, 80, 66, 66, 66, 66, 66, 66, 66,226, 49, 35, 53,114,127, 8,180, 90,173, 26,192,179, 28,199,
+141,117,113,113, 9, 43, 44, 44, 92,144,145,145,241,197,223,116, 95, 91, 83, 74,199, 50, 12,243, 2, 0,136,162,184,149, 16,242,
+ 67, 86, 86,214,141, 71,213,142, 34,132,243, 2,198,203,128,105, 0, 96, 1,150,229, 0, 95, 31,163,148,255, 59,159, 63, 61,131,
+201, 44,133, 92,246,186,193,108, 89,116,234, 60,253, 38, 42,148,184,241, 34, 22,170,228, 92, 15,163,137,255,244,100, 18, 93,255,
+136, 79,150,246, 30, 30, 30,209, 12,195, 60, 77, 41, 37,148,210, 19,249,249,249,179, 40,165,101,210,213, 43, 33, 33, 33,241, 4,
+ 25, 44, 66, 8,219,190,125,192,203, 44, 33, 79, 1,112, 6, 80, 34, 80,122,250,234,213, 91, 63, 80, 74, 31,106,190,178,168,168,
+ 40, 78,175,211,141,225, 88,118, 32,165,180, 35, 40, 37, 32,228, 18,207,243, 7, 52, 14, 14, 27, 27,154,122, 6, 0, 70,141, 26,
+197,102,102,102, 94,231,121,222,163, 49,219,150,201,100, 57,103,206,156,105,243, 48,233,246,241,241, 25,209,180,105,211,213,145,
+145,145,154,224,224, 96,200,229,114,124,250,233,167, 83, 1,216,108,176, 72, 84, 20,215,164,216,109, 12, 35,227, 6, 1,180, 35,
+165, 0, 37,220, 37,152,205, 7,114, 93, 11, 54, 82, 27,246, 29, 0, 66, 66, 66,102, 18, 66,198, 86,247,160,218,112,238,220,185,
+207, 31,229,100,248,239, 27,108, 46,165,162,189, 72, 9, 42, 12, 50,243,207,199, 93, 47, 7, 7, 7,135,204,156, 57, 19,145,145,
+145, 16, 69, 17, 39, 78,156,152,182,108,217,178,105,222,222,222, 9, 44,203,110,148,203,229,219, 82, 83, 83, 31,234,198,237, 5,
+140,143,236,222,125,241,107, 51,102,176,149, 39, 78, 96,249, 55,223,124,138,178, 50, 0, 88,219, 72, 67, 65,186,116, 9, 26,238,
+232, 72, 6, 50, 4, 65, 20,148, 16,144, 11, 69,197, 56,144,144,112,254,103, 74,169,248,176,121, 18, 22, 22,182,157, 82,218,191,
+122, 59,191, 38, 36, 36,140,120,148, 60,238, 22, 76, 34,219,182,240,254,239,228,151,158,198,123, 11, 55, 79,238,222,137, 20,168,
+237,228,171,159,239, 30,224, 28,216,210, 25, 31,174,141,153, 10,224,161, 13, 22, 33, 68,227,225,225, 17,183,107,215,174,166, 17,
+ 17, 17, 28, 0, 36, 36, 36,140, 25, 60,120,112, 47, 66, 72, 56,165,180,252,175, 40,104,186,118,237,170,226,121,126, 34, 11, 60,
+ 67, 41,237, 80,157,214,203, 2,240, 27,199,113,235, 98, 98, 98, 12, 82,113, 44, 33, 33,241,143, 50, 88,132, 16,182, 99, 96,235,
+165, 19,223,124,171,221,240,225,195,189,213, 26, 7, 85,122,250,173,172,117,107, 86, 57,177,132,233, 76, 8,153,209, 88,147, 21,
+ 17, 17,209,142,136,226,143,111,191,254,122,243,176,110,221,184, 38,222,222, 48,148,150,226,214,181,107,190,241,103,207,246,217,
+117,248,240,180,208,208,208,177,137,137,137,151,235,211, 41, 40, 40,144,113,130,224,121,228,147, 79, 88,198,197, 5,148,231,193,
+183,107, 7, 81, 20, 65, 5, 1,220,233,211,128,197, 2, 42, 8, 48,247,174,154, 13, 68, 20, 69,244,239,223,223,231, 97, 50,203,
+215,215,215,187, 85,171, 86,235,231,204,153, 35, 55, 26,141, 56,127,254, 60,206,156, 57, 35,230,231,231, 47,181,217, 84, 4, 15,
+109,231, 5,175, 77, 67,135, 15,106, 54,184,175,135,194,207,203, 3,162,168,196,181, 84,139,239,161,147,231,250,254,178,255,224,
+187, 77, 58, 14,125, 57,247,210,174,122,247,189, 75,151, 46,253, 24,134,153,151,144,144, 0, 0, 8, 13, 13, 93, 16, 26, 26,186,
+160,161,237,219,217,217,229,233,116,186,241,137,137,137, 15,152,160, 89,212,204,159,250, 22, 68, 10,124,181,239,154, 60,121,213,
+174, 16, 71, 71,199,123, 38, 75,238,215,175, 31,250,246,237,139,244,244,244,176, 29, 59,118,132,173, 95,191,254, 83, 31, 31,159,
+121, 25, 25, 25, 43, 26,155,159, 50, 96,218,107, 51,102,176,118,105,105,176, 59,127, 30, 99,203,202,184, 69, 85,209, 44,155, 13,
+ 86,120,120,120,139,126,125,131, 55, 14, 27, 30,213,214,203, 43, 80, 46,147,185, 87, 79,220, 92,212, 42, 63,255,234, 48, 23, 23,
+188, 23, 17, 17,241, 82, 67,147, 8,215, 58, 55, 61,121,158, 95, 1, 64,206, 48,204, 12, 74,105,255, 3, 7, 14, 64, 16, 4, 12,
+ 30, 60,184,127,120,120,120, 11, 81, 20,151,218,217,217, 81,163,209,248,118, 92, 92, 92,163,230,235,227, 8, 62, 26,253, 92, 95,
+232, 45, 12, 44, 22,222,195,219,195,225,135,169,175,244,146,129,154,240,221,238,115,176,240,226, 55,143,114, 65,107,181,218, 5,
+223,127,255,189, 79,100,100,100,205,216, 96,193,193,193,236,146, 37, 75,180,211,166, 77, 91, 12,224,205, 70,152,203, 32,165, 82,
+185,160,164,164,100,212,149, 43, 87,116,157,222,222,233,193, 89,212, 14, 50,181,104,140, 91, 49, 32,179, 17,199, 40,140, 35,100,
+211,146,247,199,123,181,237,212,153, 81,121,184,131,220,201, 67,177,160,127,250,204,165,171, 61, 62, 95,181,113, 82,120,120,248,
+ 75,241,241,241, 9, 82,145, 44, 33, 33,241,143, 49, 88,237,219, 7,188, 60,254,141, 55,218,189,245,246,228, 80,179,217, 88,121,
+ 33,241,248, 17, 78,206,176,147,167,188,225, 84, 84,156,239, 78,169,248, 50,128, 13,141, 48, 87, 1, 77,155, 52, 57,180,112,209,
+ 34,103, 87, 15, 15,228,228,228,224,110, 70, 6,178, 47, 93, 2, 1,208,183,111, 95, 69, 80,231,206, 45,151,173, 93,123, 32, 60,
+ 60,188, 95,124,124,252,213,250,244, 88,142, 3,177,179, 67,102, 72, 8, 32,151,163, 52, 38,166,234,123,158,135,253,144, 33, 85,
+ 43,201,229, 48, 95,184, 0,134, 97,224,233,233,249,208,153, 69, 41,141,232,222,189,187, 28, 0,222,123,239,189,114,157, 78,183,
+152, 16,178, 37, 51, 51, 51,203,150,255,123, 4, 61, 31,224,233,238,121,112,201, 71, 19, 93, 58,250,183,132,201, 98, 65, 70, 94,
+ 38, 40,148,240,242,180,199,216, 97, 65,242,167,194,100, 1, 75, 87,254,246,171, 87,231, 33,125,115, 46,236,169,115,223, 89,150,
+ 93, 58,123,246,108,108,217,178, 5, 0,176,105,211, 38,180,110,221,186,193, 52,156, 57,115,198,243,253,247,223, 95, 13,224,129,
+ 17, 60,145, 86,205, 91,216,178,101, 0,156,156,156,234, 50,221,240,243,243,195,180,105,211, 16, 18, 18,162,120,249,229,151, 63,
+ 2,176,226, 97,242,180,242,196, 9,216,157, 63, 15,156, 56,209,232,255,134,134,134,250,182,111,239,118,116,233,146,255,186,239,
+217,123, 25, 75,150,124,131, 91,183,170,124, 84,203,150, 45,241,210,152, 81,178,141, 63,172,109, 63,107,214,220, 35, 93,186,116,
+121,230,236,217,179, 55, 27,210,228,121,126, 69,116,116,244, 96,123,123,123,204,158, 61, 59,201,223,223, 31,142,142,142, 88,187,
+118, 45, 92, 92, 92,192,243,124,210,162, 69,139,184,172,172, 44, 44, 95,190,124, 53,128,225,182,166,183, 71, 16, 25, 20, 22,220,
+ 49,210,207,183, 25,142,157, 57, 11,185, 66,230,252,206,171,207,194,193,158,195,226,175,247,137,233, 25, 69,147, 79, 38,209,239,
+234,125,224, 25,181,141, 13,210, 37,185, 36, 29, 80, 20, 81, 58, 87,180, 70,240, 80, 61, 72,102, 19,111,237,160,158, 61,123,178,
+213,231, 43,210,210,210, 96, 50,153,208,190,125,123,198,108, 54,247,108,196,117, 26,162, 80, 40,246,155,205,102,181,157,157,157,
+ 6,128,142,179,168, 29, 68, 57, 55,210, 76,197,171,157,102, 30, 50, 95, 92,220, 55,223, 22,115,213, 46,160,217,190,229, 11,254,
+207,142,205,191, 1, 29, 57,143,226, 92, 51,176,116, 15, 24, 71, 15, 60,253,222,100,174,115,112,144,118,246,255, 69,239,235,210,
+165,203,160,179,103,207, 38, 74,197,178,132,132,196,223,129, 6, 27,185,179,132, 60, 53,108,216,112, 15,147, 73,175, 51, 24,116,
+ 37,183,239, 36,100, 31, 57,178,254,210,245,171, 39,111,244,235,223,213,204,176,228,169,122, 12,201, 61, 61, 12, 70,141, 26,197,
+ 50,130,176,121,209,226,197,206,172, 92, 14,139,197, 2, 63, 63, 63, 24, 12, 6,148, 21, 23, 35, 39, 61, 29,167,247,238,133,174,
+160, 0, 83,198,142,117,150, 17,178, 41, 52, 52, 84, 86,159, 38, 40, 5,248,123,107,212, 24,134,185, 39,234, 98,253,238, 65,243,
+243, 61, 80,179, 14, 68, 81, 76,203,202,202,130, 70,163, 65,187,118,237,236, 8, 33,103, 50, 50, 50,178,108,209, 36,163, 70,177,
+ 50, 25,187,109,241, 71, 99, 92, 8,123, 29,215,211, 19,192,177, 74,184, 57,249,194,100, 6, 78, 37,254,130,111,182,253, 7, 25,
+153,113,152, 56,182,149,147, 90, 77,127, 38,161,111,214,185,239,102,179,185,121, 64, 64, 0, 58,118,236,136, 78,157, 58, 65, 16,
+ 4, 92,190,124, 25, 23, 47, 94,196,249,243,231,145,152,152,136,248,248,120,196,198,198,226,204,153, 51, 24, 53,229, 51,188, 53,
+101, 38, 42, 42, 42, 96, 50,153,124, 30,156, 78,166,114,252,127,190,199,225,171,102, 20, 20, 27,176,117,235, 86, 20, 21, 21, 97,
+243, 23,221,177,102,174, 55,214,204,245,198, 15,159,133,160,184,184, 16,177,177,177, 88,188,120, 49,116, 58, 29, 4, 65,224, 30,
+ 38, 63, 45,192,178,229,223,126, 43, 38,159, 56,129,100, 0,235, 9, 17, 45,192, 50,155,242,147, 16,226,230, 42,254,180,108,217,
+127,220, 89,230, 10, 92,157, 22,225,236,217,211,200,205,205, 69,110,110, 46,226,226,206,192,197,249, 43,112,220, 85,124,246,217,
+ 60, 87,103,103,254, 71, 66, 8, 99, 67, 58,229,201,201,201,208,235,245,248,233,167,159,184,232,232,104,196,197,197, 65,173, 86,
+ 99,220,184,113, 88,177, 98, 5,231,234,234,138,219,183,111,163,162,162,130, 52,234, 92, 34,120,109,212,240, 97, 96,229,118,184,
+118, 43, 3,189, 34, 67,224,233,233,137,171,105,197, 72,207, 44,202, 37, 4,227, 6, 60,165,204,233, 25, 76,198,215,165, 73,183,
+142, 20, 94, 26, 57, 32,120,192, 4,199, 9, 77,195, 39,118,174,222,167,234,116,180,231, 8,163,112,178,154,171,155, 55,111, 34,
+ 57, 57, 25,119,238,220,193,157, 59,119, 96,177, 88,234, 76,103,175, 94,189,222,137,140,140, 44, 14, 15, 15, 47,239,209,163,199,
+ 70,150,101,247, 47, 88,176, 64,163, 82,169, 76,188,139,159, 93,232,155,191,249,202,101, 10,158, 18,198, 72, 5,124, 40, 43,151,
+187, 4, 76, 61,160,168,111,223,187,118,237,170,146, 49,204,166, 21,209,255,182,179, 36,108, 7,188,155,194,211,127, 34,236, 93,
+ 34, 65, 75,244,224,147,146, 81,190,100, 37, 56,149,136,127,255,223, 44, 59, 34,138, 63, 4, 4, 4, 40, 30,230, 92,106,228,131,
+146,164, 41,105, 74,154, 79,160,230, 63, 46,130, 69, 24, 56,107, 52,106,121,204,233,157, 7,178, 50,174, 20,100,231, 94, 42,101,
+ 64,153,172,172,132, 82,255, 86, 79,187,161,170, 77,150, 77,164,166,166,190, 56,237,173,183,252,157,170, 34, 1,112,119,119, 71,
+ 70, 70, 6, 12, 6, 3, 42,203,202,160,175,168,128,177,172, 12, 87,143, 28, 65,183,129, 3,209, 63, 56,216,119,239,185,115,175,
+ 1, 88, 87,231, 77,154, 97,192,119,238,140,210,196, 68, 16,179, 25, 78,161,161, 53, 81, 43,227,149, 43, 85,198,202, 98,129,236,
+169,167, 64, 52, 26,144,121,243, 30, 58,179,178,178,178,146,252,252,252, 14, 14, 24, 48,160,223,196,137, 19,153,156,156,156, 93,
+ 94, 94, 94,189,115,114,114,146, 27,250,111,147, 27,226,216, 87, 39, 6,183,112,119, 34,216,115,230, 87, 68,182, 27, 14,141,146,
+ 67,126,113, 37, 24, 66,112,235,246, 97, 8,130, 29,146,146,211,209,173,163, 29,186, 71, 56, 54,213,253, 86,252, 58,234,169, 46,
+ 51, 24, 12,200,203,203,131,197, 98, 1,207,243, 24, 57,106, 20,190,219,176, 1, 58,157, 14, 6,131, 1, 38,147, 9,162, 88,213,
+252, 40, 39,207,128,184,115,251, 17,218,169,238, 40,215,135, 95, 9, 77,180, 90,109,229,119,123,214,226,208,161,170, 57,156,119,
+237,218, 5, 67,110, 10, 38,189, 88,213,244,104,217,119, 63, 97,217,103, 75, 97,182,136, 86,163,247,208,249,121, 19,248, 38, 85,
+ 20,103, 13,216,190,221,227,204,206,157, 98,236,158, 61,153,202,242,242,175,109,249,111,151, 46, 65,195, 39, 79,126,182,173, 90,
+165, 70, 70,250,231,104,215, 78,142, 25,211,220, 16,189,168, 0, 0, 48,117,178, 15,194,194,220, 80, 86,178, 13,238,158, 31,224,
+189, 25,195,253, 43, 42, 48, 6,192,198,122,159, 56, 24,102,198,198,141, 27,147,250,245,235,199,157, 59,119, 14, 74,165,178,102,
+162,112,181, 90,141,156,156, 28,152, 76, 38,108,217,178,133,103, 24,102, 70,227, 74, 36, 52,109,226,229, 3,134, 90,144,149, 91,
+128,161,131,250,129,147,219, 35, 45,163, 0, 65,129, 45,189, 95, 26,242,148, 55, 75,120,188,191,232,199,119, 0, 60, 48, 31,162,
+162,230,115,239,252,103,172,229,157, 54,205, 29,247, 30, 60,253,218, 30,134, 20,230,150, 94,253, 28, 55,206, 24,148,173, 58,190,
+216,214, 31,230, 35, 71,142,168,123,246,236, 9,189, 94,111,141,118, 98,227,198,141, 34,207,243,117,134, 9, 5, 65,152,245,253,
+247,223, 43,220,221,221, 49,101,202,148,190,227,199,143, 87,135,134,134, 18, 74, 41,168,162,149,147,192,209, 94, 60,248,179,172,
+ 73,216, 11, 57,219, 79,224,204, 99,157, 5,118, 45,128,140,122,162,129, 19, 23,127, 60,181, 9, 85,231, 65,222,123, 32,152,124,
+130,204,183,158,131, 88,110,128,121,193, 36,136, 84, 14,163,137,131,121,216, 36,200,253,219, 96,114, 72,184,247,242,115,241,111,
+ 0, 88, 41, 21,205, 18, 18, 18,247, 17, 14,192,218,222,186,160,250,193,210, 13,128, 53,146,238, 1,192,132,170,121, 95,173,220,
+191, 92,123,221,251,151,107,127, 46, 64,213,148, 89, 30, 0, 4, 0,103, 1, 20, 63, 84, 4,139, 16, 66,107, 69, 6,238, 29, 24,
+139,146,130,140,140,212, 34,163,185,216, 48, 32,170,219,180,103, 35,188,230,191,246,226, 59,115,157, 28, 84,234,244,180, 91,148,
+ 48, 40,180,117, 99, 74,153,172, 95,104,100,164, 44, 39, 39, 7, 78, 78, 78,200,204,204,196,141, 27, 55, 96, 48, 24,160, 43, 45,
+133,177,184, 24,124, 97, 33, 80, 88,136,180, 19, 39,208, 86,171, 85,176, 54, 76, 99, 33,138, 34, 8, 33, 96, 89,246,129, 81, 43,
+134,101, 65,236,237, 1,123,123,128,105,220,200, 20, 90,173,246,217,118,237,218, 29,211,106,181,179,170, 13,197,180,232,232,232,
+ 66, 74, 41,102,205,154,229,224,224,224,176,177,121,243,230,202,134,116,236, 93,249,225, 17,157, 90,177,215,211, 47, 34,172,245,
+243,104,238,221, 19,183, 50, 75,145, 95,106, 64, 78,145, 14,109,218,204,132,135,118, 34,156,188,222,194,133,107,119,161,245,242,
+103, 24,153,188,222,125,207,201,201,185,103,249,199, 77,155, 80, 89, 89,137, 86,173, 90,225,197, 23, 95,196,251,239,191,143,209,
+163, 71, 67,171,213,162,123, 75,224,245,151, 71, 34, 47,175, 81, 77,134,224,227,227, 83, 51, 65,155, 40,138,224,121, 30, 22,203,
+255, 76,149,201,100,178, 89,203,203,203,235, 61, 47, 47,175, 56,111,111,239, 4,111,111,239, 29,185, 90,237, 57,139,191,191,103,
+247,225,195, 73,224, 11, 47,176,119,237,236,200, 29, 63, 63, 59, 91,180, 28, 29,153, 1, 97, 97,221, 21, 37,197,223, 0,168, 50,
+123,175,191,230,129, 83,199, 59,224,244,201, 80, 76,153,220, 18, 12, 81,129, 48,114, 84,234,126, 67,251,192,142,114, 7, 7, 58,
+176, 62,205,176,176,176,237,162, 40, 94,238,208,161, 3,247,246,219,111, 67,169, 84,226,187,239,190,195,234,213,171,241,217,103,
+159,225,250,245,235,240,243,243,131,183,183, 55,154, 52,105,194,137,162,120, 57, 44, 44,108,187,173,251,175, 86,169,220, 20, 42,
+ 39,176,114, 59,112, 50, 25,154,249, 54, 7, 43,183, 67,113, 89, 37,198,189, 48, 4,151,110,102,227,227,213,123,120,139, 69,172,
+179,186,245,248,241,185,194,142,125,199, 44, 21, 21, 58,238,185, 65,125,244,111,189,246, 98, 43, 23, 85,203,111,224,211,167,115,
+139,102,222, 47,254, 55,122,133,105,194,219,239,154,191, 90,255, 53, 45, 47, 47, 71, 89, 89, 25,150, 47, 95,206,239,217,179, 39,
+ 75, 16,132,153,245, 24, 44, 5,203,178,160,148, 98,194,132, 9,154, 54,109,218, 16,158,231, 65, 41,133,194,172, 51, 51, 34,218,
+ 16,194,140, 32, 44,107, 22, 64, 54, 18,202,246, 16,121, 78, 94,111,244, 27,120, 38,176,115,103,182, 82,159, 6,123,199, 80, 20,
+126,250, 95,136, 57,197,160,121,101, 16, 56, 13,244,162, 10,101, 38, 25,138, 58,133, 32, 43, 41, 25,158, 26, 71,142, 35,164,143,
+116, 31,145,144,248,103, 81,175, 7,249, 31, 30,132,144,189,132,144,189,115,230,204,121, 26,128, 27, 33,100,111,181, 9,242,168,
+254,172,176,174, 83,199,178, 71,109,157,251,254, 91,251,179,251,156, 57,115,122, 19, 66,246,118,235,214,237,229,106, 35,247,248,
+ 35, 88,130, 32, 28,253,242,203, 85, 77,222, 24,255, 92,147,109,123,191,142,254,121,251,133,206, 47,141,206,185,162,109,218,201,
+ 99,227,170,211, 10,158,167,123,109,222,154, 40,118,114,107,210, 4,105,105,105,136,143,143,135,193, 96,128,209,104,132,209,104,
+132,185,184, 24,150,146, 18,144,242,114, 40,120, 30,134,244,116,180,236,212, 9, 4,104,111, 67,168,178,206,106, 65,150,101, 65,
+ 68, 17,196,206, 14,196,206,174, 81, 6, 75,171,213, 6, 7, 7, 7,127,191,110,221, 58,249,244,233,211,195,253,253,253,215,100,
+103,103,167,251,250,250, 14, 90,178,100,201,137,143, 62,250, 72, 57,118,236,216,214,235,214,173,123,169,174,136,131, 21,185,202,
+208,193,175, 73,107,148,235,187, 64,163, 80,160,168,204,136,226,114, 35, 10, 74, 12,216,190,107, 12,140,134, 74,240, 70, 19, 4,
+ 51, 15,251, 38,195,209,202,245,105,128,222, 12,172, 79, 51, 54, 54, 22,151, 47, 95,174,137, 96, 25, 12, 6, 12, 24, 48, 0,195,
+135, 15, 71, 90, 90, 26,206,157, 59, 7, 39, 39, 39,120,120,120, 96,235,214,173,184,120,241, 34, 66,173, 17,190, 70,192, 42,221,
+240,197,166,205, 48, 24, 12,160,140, 61,104,173,154,229,198, 68,176, 8, 33, 99,179,135, 13, 11,192,241,227, 24,216,172, 89,187,
+182,109,219,194, 96,248, 95,231,177,128,128, 0,223,140,140,140,219, 90,173,118, 51, 33,100, 93,102,102,230,133, 58,181, 32, 6,
+185,184,182, 71,214,221,232,106,109, 14, 4, 74,244,238,155, 4,179, 89,196,245,107, 3,160, 82, 42,193, 16, 37,120,190, 16,142,
+ 78, 77, 0,144,192, 6,206,163,254, 7, 14, 28,128,163,163, 99, 77,181, 32, 0, 60,251,236,179, 51,236,237,237,187, 27, 12,134,
+161,123,247,238, 69, 73, 73, 9,252,253,253,225,233,233,137,184,184,184,254,182,238,191,157,157,131, 43, 39,183,131,200,112,112,
+114,114, 1,167,176,131,200,115, 16, 68,192,193,201, 29,103,206, 93,195,213, 59,236,155, 55, 83,177,181,238, 52,130, 6, 12,188,
+ 20, 95,169,171,236, 48,244,185,126,174, 33,157, 59, 26,162,231,189,239,176,240,179, 53, 31,255,103,214, 91, 77, 50,203, 84,101,
+125,167,238,207,219,241,235,188,230, 75, 62, 91,174,202,203,203,179,152,141,134,253,162, 40, 78,173,175, 7, 33,165, 20,151, 46,
+ 93,130,131,131, 3, 82, 82, 82,224,230,230, 6, 65, 16,170, 30, 94,144, 87, 46,200,185,205,172,133,255,150,149,169, 86, 3,230,
+100,145,210,118,148, 19,229,100,254,124,134,206,157, 43,214,161,217, 65,161, 84, 66,167,163, 40, 63,189, 15, 98, 81, 37,104,137,
+ 30,168, 52, 65,167,103, 81, 94, 73, 80, 94, 41, 66,223, 57, 12,194,193, 88,184,148, 26, 64, 41,237, 36,221,110, 36, 36, 36,234,
+ 41,171,158, 37,132,236,141,142,142,126,182,190,223, 41,165,207, 2, 48,221,183, 12, 91, 62, 3,192,194,133, 11, 63,169,181, 92,
+249,135, 24,172,203, 87,111,109,237,216,177, 85,160,143,143, 75,235,208,142, 29, 61,124,154,222, 42,115,247,240,113,248,229,192,
+ 69,117, 94,110,241,181,203,151,111,238,104,140, 81,213, 23, 21, 33,235,194, 5,148, 21, 21, 65,175,211,193, 80, 94, 14,190,184,
+ 24,222,109,219,130, 86, 84,128,213,235,193, 25,141,144,139, 34,212, 26, 13,240,191, 25,238, 31,136, 76, 20,193, 29, 61, 10,251,
+225,195, 1,185, 28,166,171, 87,171,204,150,197, 2, 89,207,158, 32,118,118, 96,156,157, 65,246,237,171,250,222,193, 1,248,188,
+225,209, 12,180, 90,173,155,151,151,215,214, 47,190,248, 66, 94, 80, 80,128, 43, 87,174, 92, 76, 77, 77, 45,115,119,119,183,231,
+ 56, 78,188,118,237,218,209,107,215,174, 13,108,209,162, 5, 4, 65,104,217,144, 94, 69,137,189,217,108, 17,145,153,119, 7, 25,
+217,151,224,100,223, 12,148,241, 69,110, 81, 37, 8, 60, 97,209, 95,131, 88,221,150,204,168,207,128,206, 72,108,202, 80,179,217,
+ 12,179,217, 12,158,231, 97, 50,153,240,202, 43,175,224, 76, 76, 12, 54,237, 58,129,187,119,239,194,191,137, 26, 47,142, 30,137,
+160,160, 32, 88,123, 28,218, 98, 88,107,211,162,203, 82, 40, 20, 10,108,219,182, 13,154,170, 99,210,104,131,229,237,237, 29,221,
+174, 93,187,128,107, 58, 29,174, 36, 39,163,203,168, 81, 0,128, 83,167, 78,213,172,163,215,235,241,210, 75, 47, 41, 82, 83, 83,
+ 95, 77, 78, 78,126,213,219,219,123, 69,118,118,246,156,186, 52,247,237,139,193, 91,111, 93, 65,126,126, 85,100,119,243,166,255,
+249,167,180, 84, 51, 6, 12, 62, 0, 0,112,118,118,198,210,165,182,205,246, 32, 8, 2,214,174, 93, 91, 83, 45, 8, 0, 10,133,
+ 34,114,250,244,233, 67, 31,180,126, 96, 96,189,158, 13, 30, 30, 30,118, 10,133, 98,180, 32, 8, 47, 7,182, 16,184,162,114, 61,
+192,155,112, 59,237, 54, 74,116,102, 80,222,130,244,140,108,232,140, 34, 10,139,202, 17,218,101,208, 23, 38,254,204,255,105,181,
+218, 15,178,178,178, 30,248,240,114,107,255, 10,147,107,192,212,141, 57,249,155,103, 77,158,248,178,204,201,197,171, 98,253,202,
+ 79,156, 24,194, 96, 79,162,165, 56,176,165,155,203,208,200, 21, 21,111,190,251,239, 36,163,112,123, 58,210,127,185, 81, 29,238,
+174,151,162,162, 34, 24,141, 70,220,190,125, 27,106,181, 26, 50,153,172,218, 96, 89, 79,140,234,143, 22,209, 66, 57,194,112, 22,
+150,153,135,185,117, 95,236, 12, 3,220,206, 1, 86,238, 66,209,184,193,176,124, 52, 9, 2, 47, 71, 69,153, 8,211,224,201, 48,
+153, 69, 88, 88, 5,244,237, 58,160,248,195, 5, 48,218,171,129, 75,167,165, 59,136,132,132, 68,125, 15,234,123,103,207,158,253,
+129,141,171, 31, 6, 48,184, 49,198,205,186, 60,123,246,236, 15,172,219,138,142,142,214, 3,200,106,108, 90,109, 10,231,136,162,
+124,213,193, 3,113, 50, 70,198, 49, 45,252,236, 74, 1, 19,206,198,103,218, 89, 4,217,186, 70,230,204,197,148, 27, 55, 64, 69,
+ 17, 21, 37, 37, 48, 20, 21,193,146,151, 7, 75, 94, 30, 72,121, 57, 56,189, 30,156,193, 0,153,201, 0, 21,199,161, 52, 55, 23,
+132, 97,174, 52,152, 49,181, 26,239, 90, 35, 89, 44,203, 2,246,246, 85, 85,131, 26,205,255,170, 11,109,140, 96, 41,149,202,111,
+215,174, 93,235,229,237,237,141,175,191,254, 26, 94, 94, 94,109,158,121,230,153,130, 30, 61,122,228, 62,247,220,115, 9,239,191,
+255,254,192,176,176, 48, 20, 20, 20,128,101,217,148,134,244, 44,102,229,249,171, 41, 2,242, 11,206, 35, 46,241, 91,236,253,117,
+ 14,146,111, 95, 65,118,161, 14,118,158,227,193,217,247,168, 89, 87,225, 24,133,220,220, 2,128,212,191,239,247, 27, 33, 74, 41,
+ 46, 92,184,128,239,118,158,129, 54,240, 25,200,236, 60,112,233,210, 85, 28, 59,116, 16, 62, 62, 62, 13,154,161,255,190,193,230,
+ 62, 19, 82,138, 67, 91, 38, 34,239,230,183, 54, 27, 60, 27, 47,138,209,243,231,207, 71,233, 91,111, 1, 91,183, 66, 46,175,170,
+ 93,138,140,140, 68,120,120, 56, 62,252,240, 67, 68, 70, 70,130,101, 89,180,106,213, 10, 67,135, 14, 5, 33,100,116,157,251, 14,
+114, 65, 20, 10,209,178,229,255,188,237,119, 63,228,227, 92, 66, 31, 92,185, 56, 4, 59,119,103,215,124,223,172, 89, 51,228,228,
+164, 2,160, 87, 26, 72,227,175,131, 7, 15,198,222,189,123,161, 82,169,160,209,104, 48,124,248,112, 84, 86, 86, 62, 95,253, 68,
+ 3, 66, 8, 8, 33,152, 87,221,150,175,178,178,210, 88,159,166, 66,161,248,246,141, 55,222, 88,184,127,255,254,192, 37, 43,246,
+152, 14,253,122,208,114,224,224,111,252,123, 31,172, 55, 29, 59,121,222,114,228,212, 69,254,249, 49, 51,204,191, 28,185,196,191,
+ 57,117,177,105,201,146, 37,248,234,171,175,188,100, 50,217,199,245,233, 22,167,124, 81,145,124,243,242,202, 21,107, 54,176, 10,
+ 57, 85,222,201,183, 20,159, 74,214,103,217, 41,137,172,117, 19,106,247,175, 57, 31,221,206,206,185, 62, 7,233,191,220,180,177,
+112, 65, 97, 97, 33, 10, 10, 10,144,145,145,129,252,252,124, 20, 20, 20,128, 82, 10, 10, 79, 7,214,204,143, 6,203,236, 16, 44,
+ 70,163,133, 35,173, 1,154, 42,136,102,211,220,185, 16,235, 17,189, 92, 89, 86, 14,198, 64, 33,158, 79,131, 73, 84,161,212,196,
+161,196,200,162,220, 32,160,140,200, 81,206, 40, 81,212, 45, 10, 70,129, 69, 89,105, 25, 8, 33, 23,165, 91,136,132,132, 68,125,
+ 70,104,225,194,133,159,252, 81,218,214,207,209,209,209,151,107,109, 75,253, 40, 17,172,168, 90,245,158, 81,247,175,116,229,202,
+149,220, 1,253,159,241, 92,241,229,177,150,102,147,192,239,250,229,144,217, 98,182,215, 95,189,150,210,168, 6, 61,102, 81, 60,
+152,152,144, 48,160,123,183,110,202,180,115,231, 96, 41, 46,134, 80, 92, 12,153,217, 12, 78,167, 3, 99, 52,130,213,235,209, 44,
+ 88, 3, 80, 47,156, 77,201,226,205,130,112,184, 65,147, 97, 53, 88, 44, 91, 99,174, 24, 74,193,216,219, 87, 85, 13, 58, 56, 52,
+202, 92, 53,105,210, 68, 51,112,224,192,168,144,144, 16, 80, 74,177,120,241, 98,152,205,102,133,217,108,134,197, 98,129,217,108,
+ 70,121,121, 57,126,254,249,103,124,255,253,247, 49,142,142,142, 63, 52,108, 2,141, 7,143,156, 78,234,255,202,240,222,138, 67,
+199,214,195, 98,228, 81, 97,112,134,206, 96, 66,185, 94, 6,147,178, 31, 8, 57, 1,134, 85,162, 91,112, 0,142,158,186, 97, 16,
+ 45,230, 67,141,116,246, 48, 26,141,200,203,203, 71, 81,197,111, 64,105, 6,220,205,229,168,184,125, 11,193,175,188,218,160, 25,
+ 98, 24,104,190,254,232, 21,112, 28,135,159, 99, 42,192,113, 28,120,254,193, 99,158,178, 44, 11, 39, 39, 39, 84, 84, 84, 0,128,
+ 77, 46, 75,175,215, 99,211,166, 77,136,140,140, 68,175, 94,189,144,153,153,137,148,148, 20, 12, 26, 52,168,102,157,164,164, 36,
+156, 59,119, 14, 81, 81, 81,245,106,149,150,138,191, 22, 21,221, 28, 62,116,232, 80,121,108,108, 44, 40,165,104,221,218, 25,142,
+ 14,246, 32,140, 18,237,219,123, 0,184, 6, 66, 8,162,162,162, 96, 54,103,241, 58, 29,126,173, 79, 51, 33, 33, 97, 68,120,120,
+120, 11,158,231,147, 58,117,234,196,229,228,228, 96,228,200,145,216,188,121,179,245,137, 6,179,103,207,190, 55, 50, 89, 81, 81,
+175,193, 10, 13, 13, 13,158, 58,117,170,204, 90, 93,173,109,182,128, 55,155,205, 34, 0,180,235,220,243,127,227,199,245, 7,110,
+222,188,137,165, 75,151, 66,167,211,129,101, 89,121, 3,231, 61, 37,132,228,165, 19,187,237, 63,239,220, 59,126,200,179, 67, 57,
+139, 32,240, 29,253, 56,199,159,126,222,155,159,121,247,206, 42,220, 57,124,181,246,250, 13,232,153,178,179,179,237,213,106, 53,
+ 46, 94,188,104, 82,171,213,114, 47, 47, 47, 66, 41, 5,207,217,113, 34,131,235,160,244, 44, 17, 4, 57,203,114,163, 65,200, 9,
+194,178,245, 30,119, 1,248,237,230,149,171,189, 90, 53,109,205,148, 31,187,140,210,144, 30, 40,215, 1,186, 10, 2, 65,166,134,
+142, 83,162,162,101,107,148,187,121,129, 3,131,172,187,105, 22,158,210,195,210, 45, 68, 66,226, 31, 71,189, 30,228,254, 8, 86,
+215,174, 93,127,170, 29,101,178,126, 6, 96, 4, 80, 95,155,232,252,218,145,170,218,134,234, 65,219,185, 79,247,225, 12, 22,165,
+244, 56,234,169,138,243,245,245,237,254,238,187,239,118,126,243,205, 55, 81, 81, 81,129,239,190,251, 14,171, 86,173,130,175,175,
+111,247,187,119,239,158,178,117, 99,205,155, 55,255,113,247,161, 67,211, 58,183,109,219,186,121,243,230,184,118,243, 38,228,102,
+ 51, 56,158, 7, 91, 89, 9,153,197,136,230, 97,118,144,171,220,145,157, 86,137,159, 46, 95,190, 67, 41,173,119,224, 69, 11,195,
+192,212,191, 63,248,235,215,193,240, 60,228,189,123, 87,181,181,114,116, 4,179,107, 87,149,177, 18, 69, 96,238, 92, 80, 59, 59,
+136,207, 60,211, 96, 58,115,115,115, 43, 91,181,106,117, 46, 57, 57, 57,180,109,219,182,152, 63,127, 62,238,222,189, 11, 74, 41,
+242,242,242, 12,121,121,121, 89, 69, 69, 69,233, 12,195,236,206,204,204,252,214,150,145,194,115, 91, 51, 27, 15, 29, 58,252,110,
+ 88,112, 96,171, 62,189,230, 97,239,222,255,162,164,172, 12, 58, 35,135, 10,189, 25, 58, 3,133,214,161, 37, 34, 58,135, 32,191,
+208,132,235,151, 19, 51,243,229, 46,141, 26,116,146, 16,130,164,164, 36, 52,115, 5,174, 92, 75,128,187,177, 16,109,157,237, 17,
+210,189, 7, 82, 83, 83, 31, 24,245,250,157,201, 34, 0,207,243, 40, 43, 43, 67,183,182,109,145,155,155,139,194,194,194,123, 34,
+132,174,174,174,208,104, 52, 72, 72, 72,192,201,147, 39, 45, 12,195,252,215,134,228, 89, 76, 38, 83, 77, 85,229,225,195,135,209,
+187,119,111,244,236,217, 19,199,142, 29, 67, 66, 66, 2,206,157, 59, 7,134, 97,224,239,239,111, 29, 82,192, 82,151, 88,124,252,
+133,237,142,142,228,189,113,227,222, 9, 28, 59,118, 44,126,254,249, 39,188,254, 90, 27, 16, 70, 9, 66,148,120,110, 72, 59,124,
+248, 81, 2, 34, 34,162,224,238, 46,199,225, 95,200,149,199, 0, 0, 32, 0, 73, 68, 65, 84,195,151,211, 56,206,233,199,134,163,
+181,226,210, 69,139, 22,113, 42,149, 10, 38,147, 9, 21, 21, 21, 53,251,191,112,225, 66,204,153, 83, 85, 99, 57,119,238, 92,204,
+155, 55, 15, 6,131,161,222, 14, 14, 22,139,133, 50, 12, 67,238,222,189,107,214,104, 52,196,213,213,149, 83, 42,149, 48, 26,141,
+ 53, 70,235,230,205,155,216,187,119, 47, 50, 50, 50,224,234,234,202,184,184,184, 64, 16, 4,155,122,172, 20, 37,127,191,111, 55,
+193,224,238, 93, 35,252, 59,249,121, 43,138, 11,243,176,125,247,254,171,230,148,159,247,163,170, 90,208,166,217,220, 41,165,139,
+ 98, 99, 99, 63,166,148,114, 26,141,102,255,197,139, 23,251,232,116, 58, 13,165, 20, 68, 72, 45, 99, 76, 17, 63, 11,132, 99, 40,
+199, 14, 6, 65, 43,176,248,175, 92,161, 41,168,183,112,225,184,117, 31,108,220, 57,233,171, 53, 75,180,101,186, 82,232, 23,172,
+133, 57,241, 10,204, 10,123, 20,126, 20,141, 74,147, 8,125,113, 5, 28,190,250, 18,106, 47, 47, 28, 43, 79,201, 43, 45, 43,251,
+ 74,186,215, 72, 72,252,227,162, 82,245,122,144,218,230,200, 90,244, 1, 72,139,142,142, 46,168,213, 22, 43, 31, 64, 18,128,160,
+234,245,242,239,251, 95, 62,128,120, 0,225,181,116,242,107, 25,173,218,159, 77,247,173,147,244, 48,251, 69, 26,186,225, 90, 9,
+ 15, 15,175, 28, 61,122, 52,244,122, 61, 50, 50, 50,176,111,223, 62,100,101,101,105, 26,184,225,255,110,182,237,136,136,136, 0,
+ 23, 59,187,163, 83, 70,140,112, 81, 26,141,200,136,137,129, 57, 43, 11, 30, 45, 90, 64, 33,147,193,181,185, 55,202, 75, 13,248,
+234,242,229,178,212,178,178, 62,247, 15, 52, 90, 91, 51, 42, 42, 74,105, 54,155,243,119,239,222,205,150,148,148,128,225,121,176,
+195,135, 87, 69,173,156,156,192,110,216, 80, 85,165, 35, 8,192,178,101, 96,236,237,161,121,234, 41,244,154, 51, 7,137,137,137,
+154,250,210,217,180,105,211,166,126,126,126,113,191,252,242,139,115,102,102, 38,158,123,238,185,164,178,178,178, 1, 5, 5, 5,
+ 21, 54,154,157,223,105,122, 4, 61, 31,224,226,232,116,116,220,184,113, 46, 26,165,128,115, 87, 46,225, 78,177, 39, 76,102, 30,
+142,118, 10, 68,180, 85, 33,175,208,136, 95,247,239, 45, 49, 86, 22,245,187,127,160,209,218,154,161,161,161,149, 99,198,140,193,
+193,131, 7, 97, 50,153,170,123,247, 85,249,145,127,253,235, 95, 56,115,252, 24,202,211,110,161,107,143, 40, 12,124,101, 28, 94,
+127,253,117,196,198,198, 98,212,168, 81,184,114,229, 74,205,254,215,214,180, 78,149,195, 11, 12,242, 75, 21,194, 93, 93, 55,102,
+250,244,233, 36,251,194, 44,232, 43,114, 96, 52, 26, 33, 87,185, 35, 71, 24,133,253,251,247,211,194,194,194,237, 50,153,108,126,
+122,122,250,237,134,246,221,199,199,103,140,179,179,243,138, 62,125,250,168,170,163,132,184,120,241, 34, 40,165, 56,121,242, 36,
+ 0,192,207,207, 15,126,126,126,200,201,201, 65, 90, 90,154,222,108, 54,255, 43, 35, 35,227,199,186, 52,187,116,233,210,188,109,
+ 91,215,227,131, 7,143,112, 51,155, 45,232,251, 76, 57,120,190, 0,132,145,131,227, 60,113,242, 20, 65, 94,110, 17,206,196,196,
+ 20,223,186, 85,222, 47, 46, 46, 46,185,161,116,134,134,134,110, 25, 50,100,200, 96,149, 74,133,159,127,254,153,111,210,164, 9,
+231,236,236,140, 13, 27, 54,212,105,106, 41,165,117,158, 75, 90,173, 54,122,214,172, 89,111,141, 28, 57,146, 21, 4, 65, 40, 46,
+ 46, 22, 0, 16, 47, 47, 47, 54, 38, 38,198,178,123,247,110,232,245,122,248,248,248, 48,132, 16, 18, 31, 31, 47,166,164,164,196,
+ 17, 66, 62,200,200,200,184, 84, 87, 58,171,191,175, 26, 96,212,173,159,103,179,182, 1,235, 22,126, 56,215,253, 63, 31, 47, 44,
+ 77,185,120,229, 53, 20, 30,204,175,101,174,232,253, 17,172,186, 52,107, 93,167, 33,162, 40,238, 23, 69, 81,205,113, 92,203,184,
+184,184,188,208, 55,143,250, 11, 44, 29, 5,134, 38,243, 28,137,187,252,121,239,188,134, 52,195,195,195,195, 90, 54,111,182,239,
+157, 41, 83,236,202,242,203, 80,244,254,199, 40, 55,139, 40,124,111, 54,140, 60,133,219,143,235,193,169, 29,112, 76, 94,166,203,
+173, 40,253,221, 64,163, 13,165,243,161, 10, 61, 73, 83,210,148, 52,159, 72,205,191, 27, 54,205, 69, 88, 29,193,194, 91,111,189,
+133,242,242,114,252,244,211, 79,248,245,215, 95, 27, 29,193, 2,128,184,184,184, 91, 17, 17, 17,253, 62,222,176,225,199,193,109,
+219, 54,107,219,178,165,220, 53, 48, 16,106,141, 6, 37,133,133, 72, 74,203, 22,190,191,118,237,182,129,231, 95, 78, 76, 76,188,
+106, 67,196, 1, 60,207,195,201,201, 9,148,231, 33,155, 53, 11, 32, 4,148,101, 97,172,186,249, 65,164, 20,178,174, 93, 65, 89,
+ 22,165, 21, 54,249, 35,100,102,102,102,250,250,250,142,153, 60,121,242, 47,223,125,247, 29, 19, 21, 21,213,121,247,238,221,244,
+ 81, 50, 59, 63,233,231, 91, 94,193, 67,251,173, 88,177,106, 83, 72,120,132,111,243, 22, 45,148,221,125,157, 96,182, 8,200,205,
+ 43,196,241, 51, 87,141,215,175,156,207, 0,111,120, 57,247,210,158,122,247, 93, 46,151,167, 57, 59, 59, 55,159, 55,111, 30,120,
+158,135, 40,138,176, 88, 44,200,207,207,199,185,115,231, 16, 26,217, 21,237,198, 79, 64, 81, 81, 17,190,254,250,107,248,248,248,
+ 96,208,160, 65, 40, 41, 41,193,181,107,215,210, 30,164,249,225, 87, 66,147,218,203, 90,173, 54,120,252,248,241, 11,166,189, 80,
+222,227,189,241,227, 64, 41, 69,244,218,245,248, 97,231,247,167, 0,242, 65,118,118,246,249,134,246, 57, 32, 32, 64, 97, 52, 26,
+ 59, 83, 74,185,146,146,146,149,197,197,197, 99, 63,248,224, 3,175,207, 62,251, 12, 79, 61,245, 20, 50, 50, 50,144,154,154,138,
+182,109,219,162,180,180, 20,241,241,241, 66, 69, 69,197,122, 74,105,116, 78, 78, 78,189, 17,146,179,103,207,166,133,134,134, 62,
+157,155,179,250,199,183,223,234, 23, 96,177,132, 41, 28,157,122,128, 82, 30, 37,197,119, 65,232, 5,243,142,157,191,165,150,151,
+203, 95,180,117,170, 28,142,227,166,238,217,179, 7,168,158, 42, 39, 43, 43,235,178,181,106,249, 65, 17,172,134,200,202,202,154,
+227,235,235,123, 96,197,138, 21,179,199,143, 31, 31, 49,114,228, 72, 25,203,178, 98,102,102, 38,255,227,143, 63,146,214,173, 91,
+ 51, 74,165,146,196,196,196,136,151, 47, 95,142,165,148, 46,202,204,204, 60,105,227, 83, 31, 37,132,224,237,145, 45, 34,210,210,
+ 82, 10, 62,157,222,183,147,159,171,235,213,222, 35,252,187,148,149,141, 62,178,121,243,230,202, 7,153, 43, 27,175,211,115, 97,
+ 97, 97,253, 9, 33, 11,116, 58, 93, 37, 0,136, 10, 83, 57,163,103,182, 17,150, 53, 39,173,236,109, 83,243,128,248,248,248,132,
+240,240,240,193,179,102,206,218, 52,108,216, 11, 77,124, 95,123,137, 37, 23,174,193,172, 82, 64,121,253, 58, 24,123, 7,186,175,
+ 52, 53,183, 92,198,190, 24, 31, 31, 47,141,226, 46, 33, 33,241,183,193,230, 8,150, 86,171,173,244,243,243,131,171,171, 43,138,
+138,138,112,231,206,157,135,138, 96, 89,185,127,178,103, 66, 41,161, 54, 76,246,124, 95, 4,139, 51, 26,141,169, 22,139,165, 81,
+ 99, 84,200,100,178,252,216,216,216,230,182,164,179,105,211,166,163,124,124,124, 62,202,204,204,220,149,145,145, 49,235,113,184,
+123,235,100,207,224,228, 3, 65,197,142, 0, 8, 24,182,193,201,158,239,139, 96, 69,201,229,242, 47,204,102,115,243,251,215, 51,
+155,205, 40, 44, 44,132,209, 88, 85,109,172, 80, 40,224,230,230, 6,133, 66, 1,150,101,211, 4, 65,152, 98,157,139,208,150,167,
+144, 79,255, 37,171,156,254,250,120, 10, 0,139,191, 90, 71,110, 86, 82,215,111,191,165, 70, 91,246,253,246,237,219,173,236,237,
+237, 71, 18, 66,134, 3,104, 93, 81, 81, 97,252,207,127,254,115,225,216,177, 99,229,173, 90,181,234,219,175, 95, 63,114,245,234,
+ 85, 92,186,116,137, 22, 20, 20,236,224, 56,110,254,221,187,119, 83, 27,149,159,132, 48,221,186, 5,143,116,176, 39, 3, 68, 42,
+118,174,254,238,114, 69, 5,126,245,246,246,223,188,117,235, 86,225, 97,159,192,194,194,194,182, 87, 84, 84,244,191,126,253,250,
+ 67, 69,176,238,123, 80,233,161, 82,169,230,140, 29, 59,182,203,115,207, 61,199,196,197,197,225,196,137, 19, 66, 92, 92,220, 89,
+139,197,178,240,238,221,187, 39, 27,147,206,121,243,230,177, 37, 37, 37, 61, 69, 81, 28,218,162, 69,139, 32, 47, 47, 47,135,220,
+220,220,226,219,183,111,159,165,148,254,226,234,234, 26, 51,111,222,188,135,222,247,199,249, 68, 91,123,178,103, 78, 20, 59, 90,
+ 8,161,182, 76,246, 44, 69, 8, 36, 77, 73, 83,138, 96,253,237, 13, 86,117,134,254, 31,128, 15, 0,124, 66, 41, 93, 32,157, 40,
+255, 12,205, 79, 38,147, 34,150,169,106, 56,200,139, 48,243, 87,225, 62,247, 24,229,109,209,108,222,188,185,210, 98,177, 4, 1,
+104, 69, 8,113,162,148, 22, 91, 44,150, 67,121,121,121,121,222,222,222, 33, 0,172,173,198, 23,102,103,103,159,123, 18,243, 83,
+171,213,158, 49,153, 76, 45,141, 70,163, 92,175,215,203, 40,165, 53,109, 5,212,106,117, 65,101,101,165, 95, 99, 52,171,141,214,
+187,148, 82, 24,141,198,207,235, 50, 86,182,106, 78,158, 60,121,104,245, 58,254,132,144,107, 0,146, 43, 42, 42,142,110,216,176,
+ 65, 39,157,243,146,166,164, 41,105, 74, 6,235,175,129,107,204,202,213,166,106,129,148,109,255, 44, 62, 88, 73, 93, 31,246,191,
+105,105,105, 70, 0,177,213,175,123,168, 54, 84, 35,159,244,253,207,202,202,234,246, 56,245,170, 13,213,201,199,165,183,114,229,
+202, 93, 0,118, 73,103,170,132,132,132,196,147, 3, 35,101,129,132,132,132,132,132,132,132,196,227,133, 0,120,224, 16,215,141,
+ 9,253, 17, 66, 58, 54,118,195, 13,233, 75,154,146,166,164, 41,105, 74,154,146,166,164,249,247,211,108, 72,251,239, 82,245, 72,
+ 30,162,131,145,237,226, 82,253,180,164, 41,105, 74,154,146,166,164, 41,105, 74,154,255, 64,164, 42, 66, 9, 9, 9, 9, 9, 9,
+ 9, 9,201, 96, 73, 72, 72, 72, 72, 72, 72, 72, 72, 6, 75, 66, 66, 66, 66, 66, 66, 66, 66, 50, 88, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18,146,193,146,144,144,144,144,144,144,144,120, 98,248, 67,123, 17, 74, 72, 72, 72, 72, 72, 72, 72,252, 19,145, 34, 88, 18,
+ 18, 18, 18, 18, 18, 18, 18,127,132,193, 34,132,208,218,239, 18, 18, 18, 18, 18, 18, 18, 18,127, 6,127, 87, 15, 34, 69,176, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,131, 37, 33, 33, 33, 33, 33, 33, 33,241,255,135,193,138,170, 14,205, 69, 73, 89, 34, 33, 33, 33,
+ 33, 33, 33,241, 39,242,183,244, 32, 53,189, 8, 9, 33,148, 82, 74,164,227, 44, 33, 33, 33, 33, 33, 33,241,167,154,145,191,161,
+ 7,145,134,105,144,144,144,144,144,144,144,144,120,204,252,161,109,176, 8, 33, 29, 37, 77, 73, 83,210,148, 52, 37, 77, 73, 83,
+210,148, 52, 37,131, 37, 33, 33, 33, 33, 33, 33, 33, 33, 33, 25, 44, 9, 9, 9, 9, 9, 9, 9, 9,201, 96, 73, 72, 72, 72, 72,
+ 72, 72, 72, 72, 6, 75, 66, 66, 66, 66, 66, 66, 66, 66, 66, 50, 88, 18, 18, 18, 18, 18, 18, 18, 18,127, 17, 4,192, 3,123, 2,
+ 80, 74, 47,217, 44,242, 16,189, 9, 26,210,151, 52, 37, 77, 73, 83,210,148, 52, 37, 77, 73,243,239,167,217,144,118, 99,252,199,
+ 19,109,176,254,200,113,176, 8, 33, 29, 31,119, 70, 73,154,146,166,164, 41,105, 74,154,146,166,164,249,247,211,252,187, 33, 85,
+ 17, 74, 72, 72, 72, 72, 72, 72, 72, 72, 6,235,175,135, 16, 50,134, 16,178,139, 16, 18, 79, 8,217, 77, 8, 25,243, 8, 90,106,
+ 66,200,140, 90,122, 59, 9, 33,211, 8, 33, 74, 41,167,159,232,115,128,149,114,225, 47,205,127,226,227,227, 19, 16, 26, 26, 42,
+251,163,182, 17, 26, 26, 42,243,245,245,245,255, 35,183,241, 56,209,106,181,109, 2, 3, 3, 19,181, 90,109, 27,233, 12,145,144,
+248,235,225,234,250,161, 75,151, 46,215, 5, 65,240,105,140,152, 66,161,200, 56,115,230, 76,157, 23,119,120,120,248,117, 81, 20,
+127,167, 41,147,201, 68,139,197,242, 64,179, 39,147,201,242, 99, 99, 99,155, 63, 65, 5,251,215, 46, 46, 46,150, 85,171, 86,173,
+ 13, 14, 14, 14, 40, 46, 46,214,189,249,230,155,125, 8, 33,189, 41,165,227, 27,169, 21, 72, 8, 89, 31, 30, 30,190,107,234,212,
+169,219,219,180,105,227,160,215,235, 21, 91,182,108,105,178,122,245,234, 67,132,144,183, 40,165,201,210,105,250, 68,221,196,130,
+ 40,165,159,181,110,221, 58, 68,171,213, 38, 18, 66,166,101,102,102, 94,148,114,230, 79,203,127, 95, 0, 19,218,183,111,255, 98,
+219,182,109,189, 83, 83, 83, 77,222,222,222,191, 80, 74,167,231,228,228, 20, 60,142,109,248,248,248,184,136,162,248,153,167,167,
+231,144, 46, 93,186, 40, 82, 82, 82, 76, 90,173,118, 15,195, 48,211, 51, 50, 50,138,159, 84,115, 21, 17, 17,113,234,147, 79, 62,
+113,155, 51,103,206, 41,173, 86,219, 61, 43, 43,235,186,116,198, 72, 52, 68,243,230,205,157,202,203,203, 87, 49, 12, 19,164, 82,
+169,154, 56, 56, 56,192,222,222, 62, 87,169, 84, 94,112,114,114,122,123,231,206,157,165, 82, 46, 61,102,131, 69, 41,245,250,237,
+183,223,224,232,232, 8, 65, 16, 32,138, 34, 68, 81, 4,165,180,230,189, 54,102,179, 25,253,251,247,247,170,111, 99,148, 82,239,
+163, 71,143,194,193,193,225,158,255,117,237,218,149, 57,117,234, 20, 84, 42,213, 61,235,155, 76, 38,116,235,214,205,227, 9, 50,
+ 87,163,221,220,220, 76,119,238,164, 71, 24, 76,230,136,119,222,155,255,241,232, 33, 79, 59,198,196,196, 48,131, 7, 15,150, 17,
+ 66,198, 80, 74,127,180, 81, 75, 77, 8, 89,253,193, 7, 31, 44,149, 43,237, 61,182,238, 59,201,101,173,250, 33,163,115,160, 63,
+121,119,202,219,154, 41, 83,166, 36,180,107,215,110, 13, 33,164, 47,165,212, 40,157,170, 79,196,241,231,124,125,125,183, 68, 71,
+ 71,107,115,179,179,177,116,217,178, 46,162, 40,126,142,191,217, 12,240, 79,114,254,251,248,248,108,137,142,142,238,248,194, 11,
+ 47,128,101, 89, 24, 12, 6,197,246,237,219,135,127,252,241,199, 79,249,248,248,132, 60,170, 1, 10, 8, 8,112, 80, 42,149,241,
+209,209,209, 94, 35, 70,140, 0, 0, 84, 86, 86, 42,182,110,221, 58,242,147, 79, 62,121, 42, 32, 32, 32,248,214,173, 91,229,143,
+176, 15,140,155,155,219, 84, 0, 79,139,162,168, 4, 16, 87, 92, 92,252, 49,165,212,252, 40,233,118,113,113,217,184,100,201, 18,
+ 55,165, 82,137,111,191,253,214,237,133, 23, 94, 56,169,213,106,123, 72, 38, 75,162, 62, 60, 60, 60,198,149,149,149, 45,211,104,
+ 52,114,103,103,103,168,213,106,200,229,114, 40, 20, 10, 95, 23, 23, 23, 95,123,123,251,254, 47,189,244,210,180, 77,155, 54,109,
+144,114,235, 49, 26, 44, 0,208,104, 52,248,233,167,159,192,113, 28,228,114, 57,100, 50, 25,100, 50, 25, 20, 10, 5, 56,142,171,
+ 89,150,203,229,240,241,177, 61,216,181,123,247,110, 56, 57, 57,193,209,209, 17,237,219,183, 7, 0, 40,149, 74, 28, 62,124, 24,
+114,185,188, 70, 59, 44, 44,236, 79,207,144, 81,125, 72, 37, 0,108,253,188, 93,213,242,187, 85, 1,164,173,159,183,195,224,158,
+118,120,118,204,130,151, 42, 77,150,167,168, 72, 12,217, 69, 98,209,130,101,107,175, 6, 5,182, 37, 91,183,110, 13,118,119,119,
+127, 1,192,143, 54,110,234,157, 46, 93,186,236, 19, 24,149,231, 43,227, 94, 27,251, 26, 67,248,225,227,102,124,114, 58,233,122,
+201,250,192,144,205, 5, 5,153, 19, 86,172, 88,113,115,210,164, 73,111, 3, 88,102,107,250,107, 71, 9, 89,150, 45, 84,171,213,
+254,199,142, 29,227,159,128,155,163, 55,128, 5, 0,120, 0, 75, 41,165,215,107,253,214, 74, 46,151, 47, 48,155,205,197, 0, 62,
+166,148,102, 60,137, 23,139,143,143, 79,155,151, 95,126,217,173, 48, 63, 31, 75,151, 45,179,166, 61,132, 16,194, 82, 74,133, 63,
+ 51, 45,225,225,225, 45, 20, 10,197, 2, 0, 65, 70,163, 81, 91,125,189,102,137,162,184, 91,175,215,207, 79, 76, 76,212, 63,228,
+113,242, 1,208, 30, 85, 61,140, 31,248,156, 20, 29, 29,125,115,246,236,217,183,255,108, 77,173, 86,251,175,167,159,126,186,227,
+152, 49, 99,112,232,208, 33, 28, 61,122, 20, 65, 65, 65,232,219,183, 47,238,220,185,227,177,102,205,154, 49, 0, 86, 62, 74,190,
+ 26,141,198, 81,211,166, 77,243, 26, 49, 98, 4,246,236,217,131,163, 71,143,162, 91,183,110, 24, 52,104, 16,210,210,210,188, 54,
+108,216, 48, 10,192,250, 70,230,169, 18,192, 84, 0, 79,179, 44,219, 99,220,184,113,252,148, 41, 83,100, 12,195, 88, 62,255,252,
+115,143,245,235,215,143,118,119,119, 15, 41, 40, 40,168,120,216,116, 23, 23, 23,127,252,209, 71, 31,125,183,114,229, 74,135,148,
+148, 20,204,159, 63,223,125,242,228,201,199,181, 90,109, 47,201,100,213, 13,203,178,165,162, 40,202, 0,184, 82, 74,141, 13, 45,
+255,157,246,221,221,221,253,141,162,162,162,207,181, 90, 45, 60, 60, 60, 64, 72,213,229, 41,138, 34,116, 58, 29,244,122, 61,252,
+253,253,229,237,219,183,255,114,210,164, 73,178, 47,191,252,242, 43,233,140,105,100,121, 10,160, 23,165,244,120,173,194,160, 23,
+165,244,120,120,120,120,217,169, 83,167,184,189,123,247,130,101,217, 26, 35, 85,219, 84, 89, 63,203,100, 50,120,121,121,161, 79,
+159, 62,252,217,179,103, 29,235,218, 88,104,104,104,197,238,221,187,153,148,148, 20, 56, 58, 58,194,201,201, 9,222,222,222,232,
+218,181, 43, 98, 98, 98, 16, 27, 27,123,143,113,235,208,161, 3, 34, 34, 34,144,152,152,168,249,211,114,228,106,251, 74,180,191,
+170,169,163,160,188,112,245,234,213,175, 23,172, 59, 92,150, 87, 84,154,223,202, 89, 94, 57,166,123, 27,141,127, 83, 55,165, 87,
+100,247,207, 9, 33,249,148,210,112, 27, 11,221,157,223,127,255,253,142, 45,135,174,217,125,245,217,251, 19, 57,134,240,239,205,
+253,236,227,166,142, 44,223,132,229,117, 97, 3, 7, 58,118,232,208, 97,130,157,157,157, 64, 41, 29,102,107,242,195,194,194,202,
+126,253,245, 87,142,227, 56,244,233,211, 71,208,104, 52, 30,199,142, 29,251,203, 11, 6, 66,200,242,220,220,220, 9, 6,131, 1,
+ 97, 97, 97,229,133,133,133, 3, 40,165, 23, 8, 33, 29,134, 14, 29,122,120,235,214,173,246,231,206,157, 67,100,100,228,118, 74,
+233, 43, 79,210, 69,162,213,106,247, 0,232,205,178, 44, 70,143, 26,101,250,105,203, 22,133, 40,138, 85,206,128,210,248,236,236,
+236, 63, 53,130, 21, 26, 26,218, 70,165, 82, 29, 93,186,116,169, 67, 96, 96, 32,145,201,100,224,121, 30, 55,110,220,192,198,141,
+ 27, 13,103,207,158,205, 52, 24, 12, 97,137,137,137,150,135, 56, 78,253,143, 31, 63, 94, 25, 16, 16,240, 64,195,168,211,233,216,
+ 86,173, 90,249, 3,216,240,103,107, 54,109,218,180,169, 40,138,203,163,162,162,250,159, 56,113,226, 10,128,143, 40,165,239,110,
+220,184, 49,210,206,206, 14,207, 63,255,124,114,122,122,250, 35, 61,149,249,250,250,158,140,141,141, 13, 41, 47, 47, 71,239,222,
+189, 19, 57,142,251, 15,207,243, 31,109,219,182, 45,148, 97, 24,188,240,194, 11,231,238,222,189,219,163, 17,251, 30,168, 84, 42,
+ 55,252,248,227,143,246, 45, 91,182,108, 41,151,203,153,150, 45, 91,162,168,168, 8, 6,131, 1,158,158,158, 88,176, 96, 65,210,
+242,229,203,211,202,203,203, 71, 60,228,249,217,166, 75,151, 46,167, 62,252,240, 67,183,171, 87,175,162,117,235,214,200,207,207,
+ 71,106,106, 42, 86,172, 88,145, 91, 94, 94, 30,245, 87,153, 44, 66, 72, 14, 0, 7, 0,222,148,210,178,199,164,167,176, 46,203,
+100, 50, 40,149, 74, 40,149, 74,168,213,106,164,166,166,238, 98, 89,246, 77, 0, 54,157,251, 28,199,149, 9,130,192, 1,120, 26,
+ 64, 2,203,178, 37,245, 45, 83, 74,197, 39,160, 44,109,202, 48,204,167,148,210, 94, 0, 24, 66,200, 73, 79, 79,207,153,217,217,
+217,233,182,106, 52,109,218,212,181,160,160, 32,213,195,195, 67,230,233,233,105, 53,155, 8, 11, 11,131,193, 96,192,229,203,151,
+ 97, 45,227, 66, 67, 67,209,169, 83, 39, 75,105,105,169,255,156, 57,115,138,254,128,253,121,160, 7,249, 59, 24, 44, 6,192, 49,
+235, 78, 85,127,119,204,250,163, 32, 8,247,152,168,218,175,218, 70, 72, 38,147,129, 97,108,106, 47, 79, 76, 38, 83,141,185,114,
+116,116,132, 76, 86,213,126,148,231,249,223,105, 10,194,195, 7, 5, 92, 92, 92,118, 19, 66,158,121,204,249,149,146,159,159,111,
+ 30,210,163,181, 82, 86,150, 95,244,202, 83,173,156, 58, 5, 52, 13,244,244,105, 54, 66,167,211, 37, 2,200,105, 76,185,216,190,
+125,123,135,130,188,156,194,151,254,181, 56,122,230, 39,171, 23,134,183,106,234,208,163,109, 11,175,110,157,219, 53,119,183, 88,
+ 24,141, 70,211, 30,128,182,177,137,116,114,114,194,145, 35, 71,158,180,115,205, 89,175,215,163,168,168, 8,107,214,172,113,112,
+115,115, 59, 64, 8,121,105,232,208,161,191,109,219,182,205,190,180,180, 20,102,179, 25, 0, 12, 79,224,117,178,208,197,197,197,
+ 52,108,216, 48,252,184,121,179, 66, 20, 69, 29, 0, 29,128, 28, 66,200,244, 63, 59, 49, 74,165,242,221,143, 63,254,216, 33, 48,
+ 48,144, 20, 20, 20, 32, 43, 43, 11, 5, 5, 5,112,119,119,199,123,239,189,167,106,213,170,149, 86,169, 84,206,124,216,242,174,
+ 46, 35, 4, 0,118,118,118, 2, 26,223, 57,230,129,154, 60,207,147,200,200,200,105,157, 59,119,254,202, 22,205,204,204,204,204,
+236,236,236, 17, 39, 78,156, 24, 39, 8,194,107,153,153,153,251, 0, 44,223,189,123, 55,156,157,157,209,190,125,251,118, 62, 62,
+ 62, 1,143, 96,164,125,194,194,194, 66,188,189,189,177,117,235, 86, 48, 12,179,242,238,221,187, 39, 25,134, 89,185,103,207, 30,
+120,120,120,160, 93,187,118, 33, 90,173,214,166,112, 61, 33, 68,169, 84, 42, 55,220,188,121,179,237,144, 33, 67, 90,149,149,149,
+ 49, 90,173, 22,214, 99,150,158,158,142, 11, 23, 46, 96,252,248,241,158,130, 32,116,179,213, 76,245,234,213,235,238,200,145, 35,
+ 11,159,127,254,249,194, 17, 35, 70, 20, 14, 30, 60,248,236,183,223,126,235,102, 45, 71,231,204,153,131,148,148, 20, 56, 59, 59,
+227,181,215, 94,107,162, 86,171, 55, 62, 1,215, 80,182, 76, 38,171,116,113,113,113,124, 68, 29,133,245,197,113,156, 66,161, 80,
+ 40, 84, 42,149, 66,165, 82, 41,148, 74,165,226,111, 31, 17, 33, 68, 75, 8, 73,228, 56,110,128,179,179,179,163,171,171,171,189,
+175,175,111,159,150, 45, 91,198,191,246,218,107,126,182,234,232,245,250,245,106,181, 90,230,225, 81,213, 2,167, 95,191,126,216,
+184,113, 35, 70,143, 30, 45,246,235,215, 79, 28, 53,106, 20,154, 52,105, 2, 0, 72, 74, 74,130, 66,161,144,217,219,219,175,255,
+131,118,171, 78, 15,242,255, 59,220,125, 59,121, 79, 8, 95, 20,197,154,232,213,131, 76, 85,237,151,173, 8,130, 0, 47, 47, 47,
+104, 52, 26,104, 52,154,123,182,117,191,230,163,140,209,213,170, 85,171, 94, 26,141,166, 27, 33,100, 20,165,244,168,173,255, 27,
+245,110, 50,182, 30,174,243,231,189,239,190,251,110,255,152,152, 24, 99, 68,199,150,162, 42,235,110,145,198,197,163, 35,227,238,
+209,123,210,196, 55,227, 0,108,105, 76,129,163,215,235, 21, 45,188, 89,125,102,105,133,169,133,157,147,115,115, 7,181,166,133,
+135,147,171,179, 74,201,216, 53,245,244,182, 88, 44,165, 0,178, 27, 18,170, 93, 45,168, 82,169, 76,132, 16,206,217,217, 25, 78,
+ 78, 78,230,226,226,226,162,208,208, 80, 40, 20,138, 66,185, 92,110,115,117, 97,151, 46, 93,210, 4, 65,168,183,253,155, 92, 46,
+207,143,137,137,177,181, 3,194,252,160,160,160, 30,171, 86,173,114,111,221,186, 53,214,172, 89,227,176,109,219,182,117, 27, 55,
+110, 68, 73, 73, 9,110,223,190,141,215, 95,127,189, 28,141,168, 14,253,179,112,117,117, 61, 60,114,228, 72,172, 95,191,158, 82,
+ 74, 9, 0, 59,134, 97, 34, 28, 29, 29,111, 92,185,114,197,252, 23, 20,178,125,218,182,109, 75, 74, 75, 75, 65, 41, 5,203,178,
+247,188,102,206,156,169, 30, 63,126,252,172,110,221,186,189, 43,147,201,202,121,158,223, 86, 89, 89,185, 40, 41, 41,233,137,106,
+172,218,179,103,207,201,119,239,222, 29,232,231,231,247, 75, 99,254,151,153,153,185,205,250,153, 82,122, 41, 39,167,234,185, 70,
+173, 86, 3,128,234, 17,242, 85,229,228,228, 4, 0,184,123,247, 46, 0, 88, 59, 47, 92,204,202,202, 2, 0,216,219,219,131, 16,
+ 98,235, 54,166,110,221,186,213,193,219,219, 91,173,215,235,145,146,146,130,208,208, 80,148,151,151, 67,167,211,161,178,178, 18,
+102,179, 25,165,165,165,206,130, 32,152,108, 60, 23, 55,126,249,229,151, 62,237,218,181, 3,207,243,176, 88, 44,160,148,226,248,
+241,227,208,233,116,176, 88, 44,104,219,182, 45, 22, 46, 92,104,152, 52,105,146,106,203,150, 45,121,122,189,126,236, 95,125,172,
+ 89,150,133, 82,169, 4,199,113,217,205,154, 53, 3,195, 48,174,105,105,105, 15, 19, 89,247, 2,144,195,113,156, 66,169, 84, 66,
+165, 82,193,250,126,249,242,229,109,141,137, 94, 85,159, 63,180, 49,203,127,121, 68,132, 97, 62,229, 56, 78,225,230,230, 38,183,
+126,103, 54,155,229, 46, 46, 46,240,245,245,253, 12,192,112, 27,165, 58,187,187,187,131, 16, 2,185, 92,142, 55,222,120, 3,241,
+241,241,187,239,222,189,251, 70, 94, 94, 30, 42, 42, 42,190,114,116,116,124, 46, 47, 47, 15,130, 32, 32, 45, 45, 13, 65, 65, 65,
+157,255,224,221,251,157, 7,249, 91, 24, 44,171,115,172,229, 32,235, 52, 61,181, 77, 86,237,207, 54, 94,100,226,139, 47,190,248,
+192,238,237, 60,207,223,211,254,234, 81, 13,150, 82,169,196,160, 65,131, 84, 26,141,102,115,181,201,122,232,144, 99, 59,111, 85,
+ 51, 14,178,239,158,237,221,179,243,196,119,223,147,245,238,221,251,151,157, 59,119, 6,121,244,124,122,192,137,223, 54,123,174,
+157,189,231,151,159,126,250,169,194,214, 6,238,213,196,108,223,190,221,235,189, 41,111,203,163,162,162,118,142, 11,154,193,105,
+149,130,189,179, 66,206,218,177, 44,163,244,105,222,247,183,227, 39,114, 0,156,178,161,144,240, 58,124,248, 48,156,157,157, 1,
+ 64, 97, 50,153,224,236,236,140, 53,107,214,168, 28, 29, 29,225,232,232,136,110,221,186, 57,203,229,114, 14, 85,109,160,108, 49,
+194, 30,199,143, 31,135,157,157, 29,116, 58, 29,140, 70, 35,120,158, 7,165, 20, 28,199, 65,165, 82,161, 87,175, 94, 30,141, 40,
+200, 82, 9, 33,125,223,121,231,157, 67,171, 86,173,114, 15, 8, 8,192,252,249,243, 81, 88, 88,136,244,244,116,140, 29, 59,182,
+ 60, 53, 53,117, 64,237,182, 89, 79, 2,157, 58,117,170, 60,125,250, 52,246,239,223,143, 33, 67,134,144,221,187,119,155, 5, 65,
+144,103,100,100, 92,254,171,210, 36, 8,130,189, 66,161,128,197, 98, 1,199,113, 96, 89,182,230,157,101, 89, 52,109,218, 20,135,
+ 14, 29,226, 42, 43, 43,185,194,194, 66,205,215, 95,127,253, 86, 66, 66, 66, 19, 0,175,253,149,121,185,102,205, 26,223, 9, 19,
+ 38,100,112, 28, 71, 7, 14, 28,248,226,157, 59,119,134,120,123,123, 31, 59,114,228,200, 10, 0,173, 26,171,215,173, 91,183, 52,
+ 79, 79, 79,143,188,188, 60,252,240,195, 15,200,203,203,131,155,155, 91,108,104,104,232,189,133, 28,199,229,199,197,197, 53,248,
+ 32,224,227,227,115, 56, 59, 59, 27, 43, 87,174, 68,118,118, 54, 60, 60, 60,146, 66, 67, 67,225,225,225,129,188,188, 60,108,218,
+180, 9, 69, 69, 69,240,246,246, 62, 12,160,153, 13, 73,140,138,136,136,240, 43, 41, 41,129,147,147, 19, 42, 42, 42,144,144,144,
+128,192,192, 64,100,101,101,129, 97, 24, 56, 59, 59, 99,245,234,213,149,132, 16,155,170, 94,138,138,138,198,190,242,202, 43,199,
+246,236,217,211,196,203,203, 11,249,249,249,208,235,245,240,243,243,195,138, 21, 43,208,172, 89, 51, 28, 62,124,184, 72, 16,132,
+ 9,235,215,175,255,183, 94,175, 31,251, 87,183,193, 98, 24,166,166, 26,175,150, 41, 42,138,140,140,196,233,211,167,183, 52,198,
+ 20, 81, 74, 77,214,106, 65,149, 74, 85,243, 82, 42,149, 96, 24, 70,124,136,107,201,137, 16,210,217,122, 99,111,104,249,175,134,
+ 82,218,195,206,206, 78,126,255,247,197,197,197,242, 54,109,218,116,179, 85, 71,165, 82,185, 86, 63,144,160, 87,175, 94,200,203,
+203, 19,252,253,253, 95, 29, 53,106,148, 5, 0,222,124,243,205, 87,243,242,242,138, 44, 22, 11,203,113, 28,242,243,243,209,178,
+101, 75,215, 63,240,161,241,129, 30,228,255,123,131, 69, 41, 37,132, 16, 90,251,189,214,193,108, 48,114,101,253,205,150, 42, 66,
+ 81, 20,105, 29,189, 8,107,204,220,227, 52, 88,206,206,206, 24, 51,102,140, 38, 51, 51,115,157,173, 5,184,181,113,123,109,115,
+165,117,107,114,100,209, 39,243,189,110,237,255, 6, 95, 45, 95,204,199,197,197,237,246,242,242, 26, 6,160,220,203, 13,158, 57,
+133,216, 65, 41,221,220,136,147,137, 1,240,115,108,108,108, 76,255,254,253,227,110,223,190,237,156,122,243,102,140,131,190, 84,
+231,224,215,146,151,123,120, 62,171, 55, 91,184,231,159,127, 94, 9, 96,181, 13,122, 16, 69, 17,251,246,237,131,131,131, 3, 28,
+ 29, 29,225,236,236, 12,171,185,122, 88, 82, 82, 82,144,145,145, 1, 59, 59, 59,216,217,217,193,222,222, 30,246,246,246, 80, 40,
+ 20,214,104, 65, 99, 11,135,155,132,144,153,219,183,111,223,240,201, 39,159,160,164,164, 4,149,149,149,152, 59,119, 46, 82, 82,
+ 82,102, 82, 74, 47, 60, 73, 23, 71,231,206,157, 43, 99, 98, 98,112,234,212, 41,232,116, 58,172, 92,185, 18,222,222,222,131, 0,
+204,254, 43,211, 37, 8,130,156,101, 89, 48, 12, 3,134, 97,126, 23,193,178,154, 45,181, 90, 13,119,119,119,204,153, 51, 71, 62,
+116,232,208,129,127,101,154, 63,253,244,211,150,203,151, 47, 95,189, 97,195,134,131, 47,191,252,242,207,151, 46, 93,122,217,209,
+209,241,242,225,195,135, 23, 41,149,202,135,106,215, 98, 50,153, 60,146,146,146,254, 23, 34,157, 63, 31,130, 32, 64, 16,132,154,
+232, 78,101,101, 37,134, 12, 25, 98,211,131,128,197, 98,113, 59,112,224, 0, 0, 96,202,148, 41, 53, 15,153,181,245, 38, 78,156,
+136,193,131, 7,187,217,152, 68,173,139,139,139, 44, 61, 61, 29, 60,207, 35, 36, 36, 4,171, 87,175,198, 11, 47,188,128, 14, 29,
+ 58,160,188,188, 28, 87,174, 92,193,134, 13, 27, 92,228,114,249,243,182, 8,102,101,101, 93,215,106,181, 81,131, 6, 13, 58,185,
+ 99,199, 14,247,102,205,154,225,194,133, 11,200,206,206, 70,135, 14, 29,176,112,225, 66, 29,165,244,169,106, 83,181,235, 9,136,
+184,220, 99,132,212,106,245, 61,230,232, 97,224,121,222, 75,169, 84,230, 84, 87, 13, 66,169, 84, 34, 33, 33,161,209,209,171, 90,
+229,210,133,198, 44,255,149, 88,203, 97,139,197,242,187,239, 91,183,110,109,179,142,189,189, 61,177,222, 99, 45, 22, 11,178,179,
+179,133, 75,151, 46, 9, 33, 33, 33, 0, 0,111,111,111, 33, 54, 54, 86, 48, 26,141,172,245,126,237,228,228,244,135,152,204,250,
+ 60,200,223, 34,130, 5,224,196,125,239, 53,133,139,213,240,212, 21,185,178, 46,219,216, 6, 11, 28,199, 97,251,246,237, 53,237,
+176, 58,119,238, 92, 99,230,238,215,181,246,106,120, 24, 20, 10, 5,156,156,156,112,240,224, 65, 67, 82, 82,210,164,135,141, 92,
+105,221,154, 28, 89,186, 56,218,171,240,106, 12, 50,178,114,113,243,114,198, 17, 74,233, 38, 0,155, 0, 88, 27,197,219,108,174,
+ 2, 61,237, 58, 69,182,246,218,242,116,223, 1,218, 97,175,190,195, 76,154, 52, 41,226,213, 87, 95, 45,126,245,213, 87,223, 86,
+169, 84,129,130, 32, 20,255,118,252,120,250,243,207, 63,239, 90, 86, 86, 54,145, 82,170,183,161, 16,203,233,215,175,159, 15, 0,
+ 56, 56, 56,152,190,249,230, 27,133,179,179, 51, 94,122,233, 37, 67, 78, 78,142,170, 58, 63, 74,108,141, 94, 89,159,250, 39, 76,
+152,224,209, 64, 30,231, 55,242, 41,165,243,179,207, 62,187,114,243,230,205, 40, 44, 44, 68,101,101, 37,228,114, 57, 22, 47, 94,
+140,187,119,239, 46, 33,132, 92,121, 82, 10,179,160,160,160,202,184,184, 56, 92,188,120, 17, 70,163, 17,111,188,241, 6, 40,165,
+214, 58,237, 33,127,113,242, 72, 70, 70, 6,126,248,225, 7, 8,130,128,177, 99,199,162,121,243,230, 53, 6, 43, 39, 39, 7,223,
+124,243, 13, 4, 65,192,132, 9, 19,208,172, 89, 51, 88, 44, 22, 85, 84, 84, 20,247, 87,245, 40,157, 62,125,122,234,142, 29, 59,
+ 14,102,100,100,244, 91,180,104, 81,119, 66,136, 56,115,230,204,165, 78, 78, 78,143,212,251,178,184,180, 28,215,110,222, 1,207,
+243, 15,124,121,184,187, 54, 90,239, 70, 74, 58,120,190,202, 84,241, 2, 15,129,231,171,151, 45,112,115,109,148, 94,102, 81, 81,
+ 81,107,150,253,127,237,157,121, 92, 84, 85,255,199, 63,231,222,185,115,103, 31, 96, 8, 17, 68, 81,220, 23, 52, 89, 21,125,244,
+209, 52, 82,212,204,210, 39, 31, 75,109,251,169, 61, 46,143,230,146,102, 18, 21,104,174,105, 41, 60,105,101, 90,102,155,230,174,
+165, 86,138, 32, 66,106, 41, 34, 18,200, 42,187, 16, 12,179,221,153,243,251,131, 37, 52,209, 25,212, 28,237,190, 95, 47, 94, 51,
+115,239,240,153,115,207, 61,247,220,207,253,158,141,149,166,167,167,195,215,215, 23, 33, 33, 33,136,142,142, 70,113,113, 49, 4,
+ 65, 64,139, 22, 45,108, 22,139, 37,197,100, 50,253,104,175,104, 65, 65,129,190,125,251,246,134,231,158,123,142,190,247,222,123,
+ 68,171,213,226,210,165, 75,144, 72, 36,208,104, 52,250,212,212, 84,167,137, 2, 55,142, 92,201,100, 50,240, 60, 15,153, 76, 86,
+ 31,185, 34, 0,246, 2,112,200, 96, 83, 74, 77,173, 91,183,110,136, 92, 53, 55,122,117,183,184,155, 35, 19,187,116,233,242,147,
+ 90,173, 30,118,225,194,133,107,162, 88,227,199,143, 55,119,232,208, 33,222, 94, 29,141, 70,115,149,231,121,157,193, 96,192,137,
+ 19, 39,208,181,107, 87,105, 69, 69, 69, 20, 33,100,113,221,195,101, 84, 97, 97,161,180, 85,171, 86,245,191,139,138,138,138,171,
+173, 91,183,190, 91,217,118, 67, 15,242, 64, 24,172,186,209, 8, 13,175,215, 71,176,110,213, 60,104,111, 4,139, 16,130,170,170,
+ 42,168,213,106,212, 77,102,134, 70,163,177,254,212, 68,120, 59, 6, 75, 46,151,227,200,145, 35,134,184,184,184, 9,148,210,239,
+236,253,191,198,125,176, 60, 31,242,216,185,242,157, 90,115,117,230,216, 33,124,113,250, 74, 62, 97,108,255,109,110,154,122,180,
+ 80,249,123,122,184, 31, 88,181, 98,169, 38, 47,113, 31,182,199,173,162,103, 78,158,236,127,242,228,201,209,211,166, 77,115, 67,
+109,127,171,124, 0,241, 0,214,219, 99,174, 0, 32, 49, 49,177, 97,114,215,144,144,144, 74,173, 86, 11,181, 90,141,226,226, 98,
+169, 90,173,214, 53,103, 20,161, 61, 77, 42, 14,154,171,142, 35, 71,142, 60,248,213, 87, 95,169,174, 94,189,138,172,172, 44,204,
+155, 55, 15,239,191,255, 62,180, 90, 45,118,239,222,173, 30, 49, 98,196, 1, 66,200,160,123, 61,185,106,239,222,189,245, 73, 73,
+ 73,200,204,204,132, 32, 8, 24, 61,122,116, 99,115,117,207,177,217,108,116,214,172, 89,248,224,131, 15,192, 48, 12, 38, 78,156,
+136,202,202, 63, 6,104,233,116,186, 27,237, 99,235,174,247,123, 98,176, 36, 18, 9,253,225,135, 31, 86, 13, 28, 56, 16,185,185,
+185,143, 6, 5, 5,109,152, 60,121,114,254,237,234,186,185,104,240,112,247,246, 48, 26,141, 48, 26,141,240,246,246, 70, 85, 85,
+ 21,210,211,211, 97, 52, 26,225,217,194,213, 97,189,222, 61, 58,194,100, 50,193,104, 52,162, 69,139, 22,168,174,174, 70,102,102,
+ 38,140, 70, 35, 60, 60,220, 28,145,251,225,216,177, 99,190, 67,134, 12,233,114,238,220, 57,252,248,227,143, 48,153, 76,232,221,
+187, 55, 46, 94,188,136,190,125,251,162,178,178, 50, 49, 41, 41,233, 91, 7,174,163,214,225,225,225, 71, 62,253,244, 83,247,173,
+ 91,183,154, 38, 77,154,196, 71, 71, 71, 19, 66, 8,170,171,171,225,100, 93,134,254,100,176,146,147,147,191,228, 56,142, 2,104,
+ 86,180,169,158,156,156, 28,183,158, 61,123,150,203,100, 50, 62, 62, 62,126,123,115,163, 87,119,229,233,231,143, 27, 87, 79, 66,
+200,169, 58, 35,217,228,103, 71, 70, 38,118,238,220,121,158,151,151,215,224,128,128, 0,156, 63,127, 94, 42,147,201,240,204, 51,
+207,152, 35, 34, 34,204, 44,203,218, 61,224, 70, 46,151,167,106, 52,154,254, 70,163, 17, 38,147, 9,223,127,255, 61,220,220,220,
+254, 59, 98,196,136,105, 5, 5, 5,200,207,207,231,235,140, 43, 24,134,193,160, 65,131, 80,213, 69, 54,191, 0, 0, 29,173, 73,
+ 68, 65, 84, 86, 86,118,215,234,229,166, 60,200,131, 18,193,106,234,160,237,106, 30,116,196, 12, 25, 12,134,134,166, 38,141, 70,
+211, 96,204, 8, 33,127,210,180, 55, 42,118, 35, 82, 82, 82, 18, 50, 50, 50,214, 82, 74, 15, 52,231,255, 59,121,186,180, 11,108,
+163,233,152,159,184, 23, 23,206,156,194,231, 41, 87,242,171, 5,243,144,212, 2, 67,118, 83,134,236,166,209, 48, 79,117,119,111,
+ 15,247, 3, 43, 87, 44,213,148,158, 63,129,244,179,167,176, 55, 49,239,103, 35,165,151, 0,188,115, 39, 79,106,115,154,239,238,
+ 54,114,185,252, 63, 95,126,249,165,234,234,213,171,200,200,200,192,132, 9, 19, 42,178,178,178,102, 61,241,196, 19,171,247,237,
+219,231,170,211,233,112,240,224, 65,117,235,214,173,163, 0, 60,121, 15, 43, 71,189,213,106, 69,105,105, 41, 0,160, 95,191,126,
+ 78,101,174, 0,224,212,169, 83, 46, 35, 71,142,220, 11, 96,224,249,243,231, 97,179,217, 18,146,147,147, 27, 70,204,222,108,159,
+ 61,254, 77,175,215, 75,148, 74,165,208, 68,217,226, 28,141, 56, 52,214, 60,126,252,248,202,149, 43, 87,126, 59,103,206,156,140,
+219,212,188, 97, 4,107,196,136, 17,168, 49,152,145, 91, 88, 1, 65, 16,160, 55, 21,222, 86, 4,171, 86,207,132,236,130,114, 8,
+130, 5, 85, 6,135, 2,110,107,199,143, 31,255,212,241,227,199,203,186,116,233,162, 75, 74, 74, 66, 81, 81, 17, 44, 22, 11, 6,
+ 15, 30, 12,153, 76,118, 57, 38, 38, 70, 10, 96,173,157,101, 83, 57,116,232,208, 3,219,182,109,107, 25, 31, 31, 15,147,201,100,
+203,205,205,205,156, 61,123,182,230, 63,255,249,207, 67, 44,235,124,171, 55,213, 71,172, 82, 83, 83,235,141,213, 75,119,202, 8,
+213, 71,176,254, 78,108,222,188, 57,127,227,198,141,129, 62, 62, 62,239, 60,251,236,179, 3,189,189,189, 25,158,231,127, 98, 89,
+118, 46, 0,187,167,105, 80, 40, 20, 83,220,220,220,126, 97, 89,150,205,203,203,195,197,139, 23,193,178, 44, 40,165,124, 77, 77,
+ 13, 60, 61, 61, 81, 95,158,198,143, 31, 15, 31, 31, 31,107,106,106,234, 20,136,220, 57,131, 5, 0,111,190,249, 38,118,253,246,
+ 27, 70,250,249,221,244,123, 95,127,253,245,141, 42,132, 63,173,182,109,177, 88, 16, 19, 19,211,240,249,219,111,191,109, 48, 88,
+211,166, 77,187,230,255,119,236,216, 97,151,230,141,184,116,233, 82,184, 3, 55,213, 6,205,250, 62, 88, 23, 11, 43, 50,123,121,
+107,143,127,252,237,247,253, 50,203, 12,153,122,193, 28,113,189,185,178, 87,179,135,151,186,139,183,135,238,224,202,229, 75,181,
+245,209,176,109, 41, 5,149,196, 74,167, 59,120,243,191,229,177,115, 28,119, 37, 44, 44,204,167,174,114,187,101,179,224, 95,181,
+202,186,193, 96, 64, 66, 66, 2, 0,224,249,231,159,175,200,202,202, 26, 74, 41, 61, 79, 8, 73, 29, 62,124,248,193,189,123,247,
+214,135, 26,202,238,101, 58,129,218,145,174, 18,137, 4,157, 59,119,118,216, 92,253, 85,233, 44, 44, 44,156, 62,101,202,148,117,
+ 70,163,145, 53, 24, 12,211,237,221,119,171,116,126,254,249,231, 25, 29, 58,116,232,143,166,167, 77,176, 1, 72,188, 29,205,119,
+223,125, 23, 0, 58,221,142,102, 83, 17,172,207, 63,255, 28, 54,155, 13, 62,158, 46, 48, 26,141, 80,169, 84, 14,105, 94, 31,193,
+218,190,125, 59,108, 54, 27,218,120,185,193,104, 52, 94, 51,242,249, 86,154,148, 82, 35, 33,100,114, 88, 88,216, 39,111,189,245,
+214,111, 93,187,118,109, 29, 22, 22,230, 86, 86, 86, 86,244,243,207, 63,103,197,197,197,169, 5, 65,152,220, 84, 51,209,245,154,
+238,238,238,171, 54,111,222,236,115,254,252,121,228,229,229, 97,245,234,213,151,139,139,139,135, 75, 36, 18,217,218,181,107,143,
+ 70, 68, 68,120, 10,130, 96,116,134,242, 89, 79, 65, 65,193,158,186,251,140, 67,198,202,158,116, 38, 38, 38,126, 93,167,125,192,
+ 30,237,191,234,216,111,119,100,226,173,210,249,194, 11, 47,228, 1, 24,127, 59,233,220,191,127,255,229,167,159,126,122,169,191,
+191,255, 34,181, 90,141,180,180,180,134,105,145,234, 31,208, 9, 33, 24, 59,118, 44,166, 78,157,138, 67,135, 14, 45,253,215,191,
+254,117,249,110,231,231,223,198, 96,113, 28,151,157,145,145,209,118,243,230,205, 76, 5, 33,216, 66, 8, 88,150, 5, 33,164,161,
+ 99,109,253, 43, 0, 28, 57,114, 68,224,121, 62,235, 22, 55,255,236,147, 39, 79,182,217,184,113,163, 68,165, 82, 65, 46,151, 35,
+ 61, 61, 29, 18,137, 4,151, 47, 95,198,103,159,125,118, 77,167,221, 67,135, 14, 89, 21, 10,197, 61,155,213,251, 76,126,229,163,
+157,124, 20,222,234, 60, 67,113, 42,165, 55,188,128,175,239, 20,127, 35,148, 26,237,155, 43,151, 47,117,105,100,174, 42,140, 38,
+219, 99,231,138,170,239,120,225, 60,126,252,184,179, 46,244,250,214,192,129, 3,109, 0,220, 1,188, 65,107, 35,119,168, 51, 89,
+255,236,220,185,243, 12, 0, 10, 0,111,221,203,232,149,205,102,107,136,156, 58, 91,228,170, 49, 73, 73, 73,153, 0,134, 59,186,
+239, 86,140, 27, 55,238, 55, 0,191,221,201,180,222, 13,205,122,202,174, 86,226, 82,102, 94,221, 82, 94, 86, 88, 47, 95,249,163,
+255,148, 96, 65, 89,101,169,195, 17,172, 75,153,185,176,217,104,173,158, 53,175,182,147,187, 85,128, 96, 17, 80,114,213,177, 9,
+242, 41,165,231, 8, 33,125,231,207,159, 63, 3, 64,127,212,142, 62,204, 70,237,232,224,181,246,246,193,225, 56,174,255,154, 53,
+107,134, 51, 12,195, 36, 36, 36, 24,151, 47, 95,158, 83, 92, 92,252, 56,165, 52, 27, 0,188,189,189,255,185, 99,199,142,173,206,
+ 48, 37,195,117,188,120,159,106, 55,155,251,101,100,226,182,109,219,162,167, 77,155, 38, 9, 13, 13,157, 27, 28, 28,204,100,102,
+102,162,184,184, 24, 44,203,162, 83,167, 78, 8, 15, 15,135,175,175,175,109,223,190,125,203, 71,143, 30, 29, 45,218,165, 59,104,
+176,172, 86,235,144, 57,115,230, 28, 54, 26,141,118,245,197, 81, 40, 20,121,213,213,213, 67,110, 81,240,134,196,198,198, 30, 94,
+179,102, 77,219, 70, 21, 71,141,197, 98, 89, 52,109,218,180,183, 5, 65, 80, 92,167,153,107, 54,155, 7,253,149, 25,114,125,147,
+223,197,220,154,219,238, 39,162,226,225,151,147,176, 7,233,103,147,241,121, 74,193, 85,189,153,134,167, 22, 85,159,251, 59, 21,
+ 52, 74,105, 49,128, 89, 77,236,187, 4, 96,186, 19,164, 81, 73, 8,209, 59,179,177, 18,249, 3,158,231,139, 31, 29, 50,248,150,
+ 35, 4, 37, 18, 73,177,189,122, 67, 31, 25,116, 75, 61,142,227,138, 29, 44, 87, 70,212,118, 3,104,118, 87, 0,150,101,231,132,
+134,134,178,115,230,204, 41,220,183,111,223,247,229,229,229,179, 41,165,250,250,253,117,163, 6, 3,197, 82,225, 52,245,221,125,
+ 49, 50,113,253,250,245, 81,179,103,207,222,234,235,235,187,177,127,255,254,157, 59,116,232,160,209,104, 52,168,172,172,172, 42,
+ 43, 43, 75,219,181,107,215,243,147, 39, 79,206, 20,207,232, 29, 54, 88,137,137,137, 69, 0,186,223,201, 31,187,133,230,255,156,
+ 38, 87,206,119,211,215,155,173,198, 81,170, 38, 63,223,162, 15,214,149,146,223,103,188,245,241,222, 24,163,197,102, 19,108,116,
+ 74,106, 97, 85,170, 88,244,156,182, 98, 20,205,213,125, 66,124,124,124, 91,103,214,187,147,152, 76,166,153, 97, 97, 97,239, 90,
+173,214,149, 22,139,229,152,120,246, 69,238, 20,171, 86,173,202, 68,237, 82, 64, 24, 59,118, 44, 11, 0, 95,124,241,133,213, 9,
+147, 26, 12,192, 3, 64,253, 3,142, 7, 0, 19,106,103,246, 47, 6,144,116,223, 24,172,191, 43, 95,124,247,199, 13,246,122,227,
+116,171,207, 77,250,181,130,223,143, 1,232, 39,230,174,136,136, 72, 51,141,127, 54,128,199,197,156, 16,185,171,247, 63,231, 52,
+ 86,245,120, 16, 66,118, 83, 74, 71, 0, 64,253,251,198,219,156, 13, 70, 44, 82, 34, 34, 34, 34, 34, 34, 34, 34,119, 22, 2,192,
+191,137, 39, 38,187, 59, 96, 19, 66,252,155,241, 68,246,139,168, 41,106,138,154,162,166,168, 41,106,138,154,127, 47,205, 91,105,
+ 55,241,255, 17,183,136, 96,237,113, 58,131,117, 55, 39,166,251,171,135, 4,139,154,162,166,168, 41,106,138,154,162,166,168,121,
+127,106,222,130,251,206, 96,137,125,176, 68, 68, 68, 68, 68, 68, 68,156,157,154, 5, 11, 22, 44, 36,132,236, 6,128, 5, 11, 22,
+ 44,116,246, 4,139, 6, 75, 68, 68, 68, 68, 68, 68,196,217,137,143,137,137,209,199,196,196,212,119,104, 47, 70,109, 43,220, 8,
+252, 49,178,240,254, 54, 88, 11,134,248,245,243,110,237,253, 97, 69,105,233,105,155,169,106,234,146, 3,185,229,205,249, 97, 66,
+136,142,231,249,167,148, 74,229, 32, 74,169, 31,203,178, 23, 42, 43, 43,143, 88, 44,150, 47, 40,165,213, 98, 89, 18,185,215, 4,
+ 6, 6,246,224, 56,110, 54, 33, 36, 88, 16,132, 86, 28,199, 21, 16, 66,146, 76, 38,211,154, 83,167, 78,157, 22,115,232,193, 37,
+ 40, 40,232,107, 74,105,120, 93, 93,117,224,212,169, 83, 99,196, 92, 17, 17,185,167,152, 0,156,188,159, 18,236,176,193, 34,148,
+ 62,253,252,139, 19,189,175,230,164,121,127,178,109,127,167, 55,134,183, 13, 95,178, 55,203,161, 5,191, 20, 10,197, 83, 61,122,
+244, 88,177,110,221, 58, 93,187,118,237,136, 66,161, 64, 65, 65, 65,231, 51,103,206,140,138,140,140, 92,200,113,220,255, 89, 44,
+150,195,183,115, 96,132, 16, 23,119,141,100,118, 73,165,229,117,177, 92,138, 56,194,216,177, 99,217,156,156,156, 69, 58,157,110,
+230,252,249,243,101,126,126,126, 80,171,213, 40, 42, 42,106,125,241,226, 69,159,245,235,215, 15, 15, 11, 11,139,149, 74,165,145,
+ 71,143, 30, 21,196, 28,187,255, 9, 13, 13,109, 33, 8,194, 90, 66, 8,207,178,236, 92, 74,105,248,254,253,251, 97,181, 90, 17,
+ 17, 17, 17, 30, 26, 26,218,193,106,181, 46, 87, 42,149, 54,163,209, 56,181,110, 78, 63,145,251,156,144,144,144, 44,171,213,234,
+ 97,239,247,121,158,207,141,143,143,239, 44,230,156,200, 93, 49, 88, 44,197,129, 61, 95,109,159, 56,114, 64, 23, 50,241,241,128,
+ 14, 91,191, 77, 62, 50,231,209,246,143,174, 60,152, 97,215,146, 54, 74,165,114,218,148, 41, 83,162,162,162,162,228, 23, 46, 92,
+192,185,115,231, 32, 8, 2, 52, 26, 13,252,253,253,153, 61,123,246,180,156, 62,125,250,167, 60,207, 79, 49,153, 76, 59,155,123,
+ 96,158, 58, 54, 90, 35,151,140,147, 73, 36, 73, 70, 65,216,227,164, 23,247, 46,139,197,178,242,231,159,127,254,241,126, 41, 48,
+193,193,193,125, 37, 18,201, 66,158,231, 31,127, 80,205,197,229,203,151, 23,254,227, 31,255,152, 25, 25, 25, 41,203,204,204, 68,
+ 90, 90, 26, 10, 10, 10,208,174, 93, 59,180,107,215,142,172, 93,187, 86,190,110,221,186, 41,167, 79,159,102, 0,216,221, 15,128,
+ 16,194,120,121,121, 77, 26, 60,120,240,104,119,119,119,109, 65, 65, 65,101,124,124,252,238,188,188,188, 15, 41,165,205,202, 75,
+ 66, 8,227,225,225, 49, 33, 34, 34, 98,180,155,155,155, 91, 65, 65, 65,249,225,195,135,119, 23, 21, 21,125, 76, 41,181, 53, 55,
+ 15, 8, 33, 45, 81, 59,194, 88, 87,183,233,138,159,159,223,249,140,140,140,226, 59,168, 89,224,231,231,151,218, 28,205,190,125,
+251,122,155,205,230, 61, 0, 58, 54,245, 29, 74,105, 42,199,113, 17,246,152, 33, 65, 16,214,190,243,206, 59, 17, 26,141, 6,243,
+231,207, 63,237,235,235, 11,173, 86,139,184,184, 56,184,185,185,193,106,181,158, 94,177, 98, 5,201,201,201,193,154, 53,107, 54,
+ 0,120, 66,188,125,216,117,206,183, 0,112, 5, 48,137, 82, 90,218,104,187, 59,128,207, 1, 20, 83, 74,199,223,171,244, 89,173,
+ 86,143, 31,126,248, 1, 50,153,172,110,185, 37, 27, 40,165, 13,175,141, 49,155,205, 8, 15, 15,111, 41,158, 85, 17, 7, 2, 82,
+ 77,143, 34,124,117, 72,187,151,252,123, 7,188, 45,229, 37, 10,155,213, 2,155, 96,129,213, 98, 2, 75, 5,116,111,231,138,246,
+ 45,120, 84,253, 94,133, 79, 14,166,255, 94, 90,131, 1,209,123, 47,164,223,226, 98,243, 13, 14, 14, 62,113,244,232, 81,237,247,
+223,127,143, 11, 23, 46, 32, 58,186,118,137, 35,149, 74,133,125,251,246,213,175,232,141,199, 30,123,172, 36, 63, 63,191, 55,165,
+180,188, 25, 23,117,155, 1, 65, 62,199,191, 94, 49,192,173,199, 19, 95,102, 95, 41, 51,245,160,148, 58,221, 4,106,129,129,129,
+122,142,227,244, 38,147,233,169,251,193,100, 5, 7, 7,247,101, 89,118,135,197, 98, 81,170,213,106,247,163, 71,143, 26, 31,180,
+ 11, 34, 48, 48,176,135,171,171,235,209, 29, 59,118,200, 19, 18, 18, 80, 94, 94,142,162,162, 34,204,156, 57, 19, 27, 54,108, 64,
+143, 30, 61,160, 82,169,192,243, 60, 94,126,249,229, 26,189, 94, 31,158,152,152,152, 98,143, 17, 26, 48, 96,192, 71, 91,183,110,
+109,107,177, 88, 24,160,118,225,243,236,236,108,235,194,133, 11,115,146,147,147, 39, 59,106,178, 8, 33, 76, 88, 88,216,166,173,
+ 91,183,250,241, 60,207, 8,130, 0,155,205,134,139, 23, 47, 90, 23, 45, 90,116, 57, 57, 57,249,185,230,148,123, 66, 72, 47,165,
+ 82,217,229,229,151, 95, 46,125,252,241,199,205, 0,144,146,146, 66, 82, 82, 82, 92,124,125,125, 47, 47, 89,178,228, 76, 51, 52,
+123, 43,149,202, 78,211,167, 79, 47, 25, 62,124,184,192,243,188, 45, 33, 33,129, 61,123,246,172,139,159,159,223,111, 11, 23, 46,
+116,104, 52, 82, 64, 64,192,153,247,222,123,175,149,143,143,143,149, 16, 66,235,126,131, 18, 66, 40,195, 48, 20, 0, 82, 83, 83,
+185, 87, 94,121, 37, 59, 37, 37, 37,200,142,243,190, 99,252,248,241, 67,123,245,234,133, 46, 93,186,128,101, 89,164,165,165,225,
+210,165, 75,144,203,229,240,247,247,135, 66,161,192,206,157, 59,241,217,103,159, 29, 74, 78, 78, 30, 45,222, 62,236, 58,239, 63,
+ 0, 8, 2,112, 30,192, 48, 74,105,105,157,185,218, 15,160, 43,128, 19,148,210, 33,247,178, 14, 78, 72, 72,192,142, 29, 59, 32,
+149, 74,193,113, 28, 74, 75, 75,225,235,235, 11,137, 68, 2,142,227,192,113, 28,164, 82, 41,124,124,124,240,200, 35,143, 8, 73,
+ 73, 73, 90,241,204,138,220,118, 4,203,171,229, 67,243,158,124,114,136, 2, 86, 1, 48, 87, 3,102, 61,168,185, 26,212,164, 7,
+225, 21,160, 22, 3, 84,108, 41,254,239,145, 22,154,175,226, 11, 83, 94, 29,220,110, 76,204,225,204, 67, 77,233,105,181,218, 5,
+113,113,113,218,179,103,207, 34, 45, 45, 13,171, 87,175, 70, 84, 84, 20,164, 82, 41,202,203,203, 49,106,212, 40,196,199,199,195,
+100, 50,225,181,215, 94,115, 91,176, 96,193, 20, 0, 14, 47, 50,217, 82, 39,121,119,251, 39,107,221,116,138, 18, 60, 55, 42, 73,
+183,254,139,172,151, 0,108,112,198, 19, 48,111,222, 60,229,242,229,203,191,236,221,187,183, 83,155,172,224,224,224,190, 82,169,
+116,199,226,197,139, 85,139, 23, 47,182,222, 33,205,110, 12,195,124, 98, 50,153, 22,156, 62,125,250, 59,103, 56, 78,169, 84, 58,
+237,149, 87, 94,145,231,228,228,224,234,213,171, 13, 79,182,245,200,100, 50, 48, 12, 3,158,231,241,236,179,207,202, 55,109,218,
+ 52, 29,192,164, 91,233,122,121,121, 77,218,178,101, 75, 91,179,217,204, 84, 85, 85,129,231,121, 72,165, 82,244,236,217,147,157,
+ 59,119,174,207,172, 89,179, 94, 0, 16,235, 72, 90,117, 58,221,191,183,108,217,226,199,243, 60, 83, 80, 80,128,126,253,250, 33,
+ 33, 33, 1,161,161,161,236,188,121,243, 90, 79,159, 62,253, 57, 0, 31, 56, 26,101, 82, 42,149,221,142, 29, 59,150,219,170, 85,
+171,134,237,237,219,183,167,195,135, 15, 47, 59,127,254,124,167, 83,167, 78,149, 5, 5, 5,229, 58,160,233,173, 84, 42, 59, 31,
+ 60,120,240, 74, 84, 84,212,160, 13, 27, 54,140, 0,128,144,144,144, 61, 49, 49, 49, 71,138,139,139,187, 38, 36, 36,148,245,233,
+211, 39,223, 1,205, 14, 94, 94, 94, 85,211,166, 77, 83, 55,245,157,143, 62,250,168,140, 16,210,213, 30, 61,150,101,103,111,219,
+182,237, 76,121,121,185, 36, 57, 57, 25,114,185, 28, 10,133,162,225,245,202,149, 43, 48,153, 76,216,190,125,187,192, 48,204, 28,
+241,214, 97, 55,227, 0, 28, 0,208, 13,192, 62, 66,200, 51, 0, 62, 5,208, 5, 64, 58,128,123,190, 56,181,205,102, 3,199,113,
+144, 72, 36,216,179,103, 15, 98, 99, 99,241,205, 55,223,192,219,219,187,193, 96, 73, 36,146,250,114, 39,158, 81, 17,199, 12, 22,
+ 33,132, 82, 74, 73,253,107,253,206,130,130,162, 85, 31,199,126, 24,205,115, 12, 55, 36,172, 11,220,100, 2,136, 82, 7,233,192,
+ 5, 32,174,190, 0, 0, 90,150, 1,211,129, 5, 24,219,187,132,249,196, 76, 62,127,103, 84,231, 54,243,190, 77,171,106,162, 82,
+ 12,105,211,166, 13,126,252,241, 71,180,107,215, 14,139, 23, 47, 70,215,174, 93,161, 84, 42, 81, 88, 88,136,234,234,106,168, 84,
+ 42, 88,173, 86, 4, 4, 4,176,106,181,122,128,163, 6,139, 16,242,240,243,227, 66,131, 36,218, 46,232,247,216, 11, 56,184,126,
+160,234,227, 61, 5,175, 16, 66, 62,105,188, 56,170,179, 48,122,244,104, 20, 22, 22, 42,183,110,221,218,108,147, 21, 18, 18,178,
+203,106,181, 14,190,213,247,228,114,249,143,199,142, 29, 27,214, 92,115,181,105,211, 38,149,171,171,235, 29,169,100,234,204,213,
+247, 19, 39, 78,212,108,217,178,101,219,195, 15, 63,252,180, 51,152, 44, 66, 72, 31, 63, 63, 63,100,103,103,163,176,176, 16, 70,
+163, 17,133,133,181, 93, 12,115,115,115,225,227,227, 3, 55, 55, 55,248,248,248,160,115,231,206,132, 97,152, 96,123,116, 7, 14,
+ 28, 56, 2, 0,147,145,145,129,226,226, 98,104,181, 90,168,213,106,180,106,213, 10,131, 6, 13,146,180,111,223, 62,220, 81,131,
+ 21, 30, 30, 62, 90,169, 84, 50,217,217,217,200,204,204,132,209,104, 68,122,122, 58, 92, 93, 93,241,200, 35,143,112,126,126,126,
+195, 28, 53, 88, 0,186, 79,153, 50,165,184,177,185,170, 71,165, 82,145,110,221,186,149,107, 52,154, 0, 0,185,142,104,206,156,
+ 57,179, 40, 38, 38,166,255,161, 67,135,102,215,111, 60,116,232,208,127, 1,224,253,247,223, 63,230,226,226, 18, 0,192,161,133,
+213, 41,165,182, 23, 94,120,225, 18,207,243, 13,134,181,254, 61,207,243, 96, 24,198,197, 30,157,250, 14,237,254,254,254,152, 58,
+117, 42,190,249,230, 27,108,222,188,185, 97,255,147, 79, 62,137, 49, 99,198,160,170,170, 10,158,158,158,146,252,252,252, 95,131,
+130,130,156,162,227, 59, 33, 36, 16,192, 82, 0,102, 0,145,148, 82,167, 90,143,141, 82, 90, 68, 8, 9,111,100,178, 78, 0,144,
+213,153,171,112, 74,233, 61,239,203,102,181, 90,193,113, 28,114,114,114,176,113,227, 70,188,244,210, 75,232,217,179, 39, 42, 42,
+ 42, 26, 12, 22,199,113, 96, 24,113,225,147,187, 88,142,111,232, 65, 30,232, 8,150,172,127,118,108,230,113,166,231,216,145, 97,
+ 19,116, 90, 5,108,191,231, 67,250, 72, 36,206,150, 41,177, 38,246, 0, 0, 96,214, 83, 1,240, 31,250, 22,140, 31, 62,138,193,
+190, 38,254,195,159,229,255, 5, 16,117, 35, 61, 15, 15, 15,119, 65, 16,192, 48, 12, 84, 42, 21,116, 58, 29, 20, 10, 5, 74, 74,
+ 74, 48, 99,198, 12,236,223,191, 31, 38,147, 9, 82,169, 20,126,126,126, 48,155,205,126,142, 30,144,167,155,100,253,154, 21,209,
+ 46,165, 25,159, 33,249,194, 85, 40, 93,124,176,232,165, 64,215, 55, 54, 36, 47, 4,176,200, 25, 79, 66,247,238,221, 49, 99,198,
+ 12,229,186,117,235,154,101,178, 40,165, 75, 37, 18, 73,159, 57,115,230, 40,158,122,234,169, 63,237, 63,119,238, 28,166, 78,157,
+ 90,163,215,235,151, 53,199, 92,113, 28,183, 99,227,198,141, 42, 23, 23, 23,100,103,103,223, 49,115,181,118,237, 90, 77,251,246,
+237,193,113,156,252,163,143, 62,114, 10,147, 37, 8,130,143, 82,169, 68, 73, 73, 9,102,205,154,117, 77, 63,140,250,230,108, 0,
+ 72, 75, 75,131,143,143, 15, 12, 6,131,183, 61,186,238,238,238,174,148, 82,188,248,226,139,200,201,201,105,216,238,237,237,141,
+220,220, 92, 8,130,224,230,104, 90,117, 58,157,155,197, 98,193,128, 1, 3, 96, 48, 24,106,195, 5,227,198,129,227, 56, 20, 21,
+ 21,193, 98,177,232,154,145, 5,238,195,135, 15, 47,104,106,167, 90,173,182,232,116,186, 54,142, 38, 53, 34, 34, 34,127,253,250,
+245, 17,215,239, 56,121,242,100,132,139,139,203, 97,119,119,247, 78,205, 9, 62,200,100, 50,240, 60, 15,142,227, 80,255,190,254,
+143,101, 89,155,157,215, 79,248,254,253,251,161,213,106,145,152,152, 8,133, 66, 1, 0, 24, 49, 98,196, 28,181, 90,221,223, 96,
+ 48, 60,190,123,247,110, 92,189,122, 21,126,126,126,104,209,162, 5, 18, 19, 19,195,157,164,250,120, 27, 64,159,186,247,239, 54,
+122,239,108, 38,107, 2,128, 99,117,230,202, 4, 96,188, 51,152,171,198, 17,172,101,203,150, 65, 16, 4,196,199,199, 99,236,216,
+177, 32,132,128, 16, 2,173, 86,139,119,223,125, 87,116, 65, 34,205, 51, 88, 55,114,142,111,188, 65, 24,227,241,182, 27,198, 70,
+244,153,208,205, 71, 5, 99, 73, 6,120,181, 59,136,107, 91,172,137, 61,128,243, 89,101, 0,128, 53, 95,166,224,227, 87,195, 65,
+148, 58,120,213, 92,128,150,151,141,106,202, 96,149,150,150, 86,153,205,102, 55,133, 66,209,240, 84, 80, 82, 82,130,215, 95,127,
+ 29,219,183,111, 71,219,182,109, 33, 8, 2,120,158, 71,113,113, 49, 56,142,115,104,116,162, 68, 66, 30,139,156, 57,172,173,202,
+189, 19, 74, 83,222,168,221,168, 13,192, 75,227, 24,126,229, 39,191,252,155, 16,242, 46,165,212,233,230,203, 80,171,213,232,213,
+171, 23,254,253,239,127, 43,183,110,221,250, 1,110,210,113,247, 70, 36, 37, 37,157, 8, 14, 14, 30,181,106,213,170,111, 11, 10,
+ 10, 20,189,123,247,134, 90,173,134, 90,173, 70, 70, 70, 6,162,162,162, 12, 6,131,225,201,230, 68,199, 24,134,137,125,254,249,
+231, 85, 90,173, 22, 25, 25, 25,208,233,116,183,117,172,193,193,193,221, 88,150,253,126,237,218,181,154, 14, 29, 58, 32, 53, 53,
+ 21,129,129,129,104,217,178,165, 60, 38, 38,230,158,155, 44,169, 84,154, 87, 92, 92,220,190,117,235,214,216,180,105, 19, 24,134,
+ 65,126,126, 62, 22, 45, 90,132,152,152, 24,244,233,211, 7,106,181, 26,173, 91,183, 70,122,122, 58, 20, 10,197, 21,123,116,243,
+242,242,202, 1,120,236,219,183, 15, 37, 37, 37, 13,219,219,180,105,131,178,178, 50,152, 76,166, 50, 71,211,154,159,159, 95, 6,
+160,197,233,211,167,145,153,153,137, 97,195,134, 97,231,206,157, 8, 12, 12,132,213,106,133,197, 98, 41,107, 70, 22, 88, 89,150,
+189,217,242, 14, 4,128,163,102, 80,144, 72, 36,244, 38, 79,175,205,209,132,205,102,163, 77,153, 43,169, 84,138,155,253,230,141,
+162, 24,113,113,113, 13,205,130, 0,192,113, 92,159,217,179,103, 63,222,212, 67,145,147,208, 56, 74,231,148,131, 78, 8, 33, 30,
+ 0,182, 0,224,235, 34,109, 60,128,205,132,144, 97,141, 59,190,223, 75,131,197,178,108,195,103,149, 74,133, 94,189,122, 53, 24,
+ 44,189, 94, 15,142,227, 68,183,112,119, 77,248, 3, 23,189, 2,234, 22,123,110, 28,158,187,198, 92, 13, 11,154,208,213, 71,142,
+159, 83,126,129,196, 84, 6,106,172,188, 73, 13,101, 1,145,170,160, 85, 73, 90,221,228, 66, 59,157,149,149, 5, 87, 87, 87, 72,
+165, 82,200,100, 50,248,251,251,227,196,137, 19,232,212,169, 19,172, 86,107, 67, 69,249,235,175,191, 66, 16,132, 99, 14, 92,196,
+236, 67, 90,201,138,121, 11,163,212,200,219, 4, 87,141, 12,131,250,116, 0, 84,221,192,114, 50,172,122,109,164,155,231, 67, 46,
+239, 56,227, 73, 80,171,213,200,203,203,195,103,159,125,166, 55, 24, 12, 47, 54, 71, 35, 41, 41,233,132,213,106, 29,245,197, 23,
+ 95,212,100,101,101, 65, 46,151,227,226,197,139,245,230,106, 76,115,251,119,217,108,182, 41, 31,124,240, 65,245,238,221,187,161,
+ 86,171,161,209,104,110, 59,114, 53, 99,198, 12,117,199,142, 29,145,145,145, 1, 23, 23, 23,184,187,187,163,127,255,254, 88,183,
+110,157, 92,173, 86,111,123,248,225,135,239, 89,167, 87,155,205,150,152,158,158, 78, 93, 92, 92,208,185,115,103,244,232,209, 3,
+ 33, 33, 33, 0,128,250, 14,208,237,218,181, 3, 0, 92,186,116, 9,148,210, 83,246,232, 30, 59,118,108,119, 90, 90,154,213,203,
+203, 11, 61,123,246, 68, 64, 64, 0, 66, 67, 67,225,235,235,139,255,253,239,127,230,203,151, 47,239,119, 52,173,135, 15, 31,222,
+245,203, 47,191, 8, 94, 94, 94, 8, 12, 12,132, 76, 38, 67,143, 30, 61,224,229,229,133,184,184, 56,115, 86, 86,214,254,102,100,
+ 65,238,153, 51,103,216,166,118, 42, 20, 10, 13, 0, 71, 35, 15,249, 39, 79,158,100,194,194,194,254, 52,154, 55, 36, 36,100,143,
+ 66,161,112, 1,112,197,209,132, 18, 66,108, 60,207, 67, 46,151, 95, 99,174,120,158,135, 76, 38,131, 68, 34,177,119, 20,229,158,
+136,136, 8,236,222,189, 27,114,185, 28, 74,165, 18, 79, 60,241, 4, 12, 6,195,147, 0,176,116,233,210,134,155,109,100,100, 36,
+ 0, 64,175,215, 59,203, 0,143,185, 0,126, 5,240, 27,128,215,156,208, 92,181, 64,109,243, 96, 39,212, 54, 11,246,175,123,173,
+239,147,229,238, 4, 55,119, 72,165, 82,188,249,230,155,224, 56, 14, 45, 91,182,196,194,133, 11,177,120,241, 98, 68, 70, 70, 98,
+249,242,229,112,115,115, 19,155, 8,239,110, 57,185,198,131, 60, 80, 6,235,122, 76, 9,190, 75,158,122,172,247,132,174,173,100,
+ 56,157,242, 43,118,157, 44,184, 88, 82,114, 21,182,194, 95, 96, 43, 78,197,172,167, 2,208,173,173, 14,221,218,234, 48,235,169,
+ 0,216,138,126, 5, 45,207, 0,149,235, 80, 92, 69,154,108, 94, 40, 43, 43, 91, 19, 21, 21,117,213,205,205,173,161, 82,204,205,
+205, 69,247,238,221,175,169, 36, 89,150,197,235,175,191, 94, 82, 84, 84,180,201,110,147,162, 96,159, 91,246,218,211, 45,164, 50,
+ 13, 80,246, 35,180, 90, 53, 54,197,174, 0,140,249, 0,195, 99,228,144,135, 89,175, 22, 46,255, 36,132,116,116,182,147,144,157,
+157,141,200,200, 72,189, 94,175,191,173,142,238, 73, 73, 73, 39, 44, 22,203,168,184,184,184,154,189,123,247,226,237,183,223,190,
+ 45,115,213,200,184,141,222,188,121,115,117,118,118,246,109, 25, 44,142,227, 94, 17, 4, 65,179,122,245,106,219,208,161, 67,173,
+ 47,191,252,178,117,242,228,201,214, 49, 99,198, 88,135, 12, 25, 98,157, 50,101,138,213, 96, 48,200,212,106,245,219,247,234, 92,
+152,205,230,216,216,216, 88, 3,195, 48, 80,171,213,224,121, 30, 30, 30, 30, 13, 70,184,190,159,143,217,108,198,250,245,235,107,
+140, 70,227,251,246,232,150,148,148,108,158, 59,119,110,214,193,131, 7, 45, 21, 21, 21, 0,128,130,130, 2, 68, 71, 71,155, 55,
+108,216,144, 95, 94, 94,254,161,163,105,173,168,168,216, 50,127,254,252,203,123,247,238,181,176, 44,139,242,242,114,184,186,186,
+ 34, 58, 58,218, 28, 27, 27,155, 95, 89, 89,233,176,102,255,254,253, 51,114,115,115, 53, 70,163,145,222,224,252, 17,133, 66, 17,
+ 4,224,168, 35,154, 33, 33, 33, 25,217,217,217,218,183,222,122,235,167,161, 67,135,174,210,106,181,151,180, 90,237,165,161, 67,
+135,174,222,176, 97,195, 15,114,185, 60, 8,192,145,102, 68, 87,109,245,117,134, 92, 46,135, 76, 38,107,120, 64,147,201,100,224,
+ 56,206, 46,131,149,156,156, 60,142, 82,218, 83, 16, 4,161,103,207,158, 80, 42,149, 24, 51,102, 12,164, 82, 41, 0, 96,193,130,
+ 5,160,148,130, 82,218, 96,176,170,170,170,156,194, 96, 81, 74,127,162,148,134, 82, 74,253, 41,165,206, 56, 72,102,107, 35,115,
+ 21, 78, 41, 61, 7, 32,188,145,201,218,238, 12, 6,139,227, 56,116,237,218, 21,179,102,205,194,206,157, 59,145,149,149, 5, 65,
+ 16, 96,181, 90,193, 48, 12, 36, 18,137,104,176, 68, 28,166,161,137,176,241,107, 75, 87,213, 51,221,188, 36, 56,125,250, 60,190,
+ 61, 85,182,149, 97,216,157, 41,153,198,175,194,253,126,135,121,251,120,248,143,221,130,143, 95,173,237,130, 96, 43,250, 21,230,
+ 47,158, 1, 81, 62,132,244, 74, 37,244,230,242,253, 55, 41,200,167,116, 58,221,151,159,124,242,201,196, 73,147, 38,241, 54,155,
+ 13, 10,133, 2,179,103,207, 6,165,180,193, 92, 77,157, 58,181,186,168,168,104, 29,165, 52,195, 78,247,171,104,229,193,207,159,
+240,226, 34, 57,114, 98, 1, 70,138, 18,244, 70,175, 1,207,163, 40,235, 4, 80,125, 30, 32, 82,196, 46,123,193,125,212,228, 21,
+239, 1, 24,234, 44, 39, 32, 53, 53, 21, 75,150, 44,185,109,115,213,216, 16, 5, 7, 7,143,218,185,115,231,255, 12, 6,195,203,
+119, 80,115,244,178,101,203,118,180,104,209, 66,213, 92, 29,111,111,239, 23, 74, 74, 74,166,218,241,213,123,214,212,113,234,212,
+169,211,125,251,246,221,184,122,245,234, 23,103,206,156, 41, 87, 40, 20,208,106,181, 72, 75, 75, 67,155, 54,181, 93,143,106,106,
+106,240,234,171,175,214, 8,130,176, 53, 49, 49, 49,209,206, 74,220, 70, 8,121,126,202,148, 41,147, 58,117,234, 20, 65, 41,213,
+153,205,230,178,203,151, 47,239,175,172,172,108,214, 60, 88,117,154,207, 77,157, 58,117, 66,199,142, 29, 71, 91, 44, 22,157, 32,
+ 8,101, 57, 57, 57,123, 42, 43, 43, 55, 55, 71,243,167,159,126, 42,217,180,105,211,111,249,249,249, 93, 61, 61, 61, 43,221,221,
+221, 77,122,189,158,213,104, 52, 26,158,231,123, 3, 72, 4,112,193, 17,205,196,196,196,162,184,184,184,203,122,189,190, 83,108,
+108,236, 49, 87, 87,215, 35, 86,171,149,240, 60,239,166, 82,169, 6, 2,248, 9,192,165,230, 24,172,250, 7, 51,169, 84,218, 16,
+ 21,175,255, 12,192,230,128,214,138,101,203,150, 73,228,114, 57, 76, 38, 19,244,122, 61, 74, 75,107, 91,175,150, 46, 93,138, 87,
+ 95,125, 21, 0,176,100,201, 18, 68, 70, 70,162,166,166, 70, 38,222, 62,236,162, 12,192, 41, 0,227,234,251, 92, 53,234,248,190,
+ 21, 64,133,179, 24, 44,142,227, 48,105,210, 36, 12, 31, 62,252, 79,211, 52,136,157,220,239,250, 57,184,198,131, 60, 48,145,185,
+ 27,205,131,181, 96,104,219,255,243,113,225, 94,201,175, 20,118,242,125,179,230, 71, 70,130,190,250, 72,219,157,163, 59, 86, 63,
+210,173,165, 13,160, 2,136,182,246,102, 67,171,242, 65, 84, 45, 81,110,115,193,166,195,133,133,148, 97, 66,150,236,186, 88,122,
+ 19, 51,196,185,186,186,174,236,216,177,227,152,232,232,104,151, 46, 93,186, 64,169, 84,130, 82,138,179,103,207, 98,234,212,169,
+229,197,197,197,155, 74, 75, 75,223,160, 55,155,164,171, 17, 30,174,220,155, 27, 34,135,253,103,204,164,215,165,184, 48, 7,144,
+184, 0, 15, 13,193, 21, 50, 24, 45, 37,103, 0,211,149,218,109,156, 11,134, 77, 88, 90,190,255,112,210,191, 40,165,241,247, 58,
+243, 3, 3, 3,245,114,185,252,142,153,171,187, 77,112,112,112, 95,158,231,119, 24,141, 70,165, 74,165,122, 32,231,193,170, 59,
+ 47,156, 76, 38,139,146, 74,165, 47, 60,243,204, 51,138, 46, 93,186,192,215,215, 23, 69, 69, 69, 72, 75, 75, 67,108,108,172,193,
+102,179,125, 92, 86, 86,182,240,220,185,115,230, 7, 49, 15, 46, 94,188,232,213,190,125,251, 96,150,101,219,163,118,162,200, 43,
+ 0, 14, 54,199, 8,213,147,158,158,238,237,235,235, 27, 44,149, 74,253,234, 52,243, 1,124,215, 28,205,128,128,128, 51, 11, 22,
+ 44,104, 49, 96,192,128,106,150,101,169, 84, 42,165, 12,195, 64, 42,149, 82,137, 68, 66, 9, 33,244,211, 79, 63,213,174, 90,181,
+170,192,158,121,176,130,130,130,182,141, 24, 49, 98,164, 92, 46,199, 87, 95,125, 37,120,122,122, 74, 92, 93, 93,241,241,199, 31,
+ 55, 85,143,129, 82,170, 20,111,141,247,253,181,174,255,238,187,239,144,147,147,115,205,156, 87,141,141, 85,253,103, 66, 8,194,
+194,194,132,147, 39, 79,138,243, 96,137, 52,223, 96,221,136,101, 67,252,180, 21,160,159,247,106, 69,255, 17,228, 43,131,135,171,
+ 28, 12, 39, 67,165,129,224, 92,190, 1,199, 82, 43,115,173, 54,242,228,219, 7, 51,206,217, 25,117, 10,105,217,178,229, 92,155,
+205,214,141, 97, 24, 37,165,180,138, 97,152, 51, 5, 5, 5,209,148,210,243,142, 28,132,171,134, 61,235,166,146,184, 72,121,158,
+ 10,130, 21, 0, 11, 48, 4, 32, 12, 0,166,238,149, 5, 8,131,154, 26,179, 84,176,146,157, 69, 37, 37,211,238,117,230, 15, 24,
+ 48, 96, 87, 85, 85,213,125, 55,147,187, 76, 38, 91,200,178,236,227, 15,250, 50, 49,161,161,161, 1, 60,207,207,165,148, 6, 26,
+ 12, 6, 79,133, 66, 81, 68, 8, 73,169,174,174, 94,153,156,156,124, 82,172, 62,238, 29,119,122, 38,247,192,192, 64,119, 66,200,
+106, 74,169,146, 97,152, 87,108, 54,219,175, 62, 62, 62,216,177, 99,199, 13, 35, 88,162,193,122,176, 12,214,196,137, 19,177,235,
+183,223, 48,210,175,233,129,235, 95,127,253, 53,250,245,235, 39, 26, 44,145, 59,111,176,234, 76, 17,153, 59,168,237,147, 18, 66,
+158, 32, 12,237, 78, 0,222, 74,145,206, 16,250,157, 84,102,254, 96,201,174,252,154,235,190,239, 79, 41,253,229,142, 38, 88,212,
+ 20, 53,239,129, 38, 33,132,177,103,233, 25, 49, 63, 31, 12,205,192,192,192,237,213,213,213, 17,105,105,105, 77,105, 92, 99,176,
+196,252,188, 63, 53,251,245,235,119,126,213,170, 85,173, 59,118,236,200, 16, 66,192,178, 44, 8, 33, 96, 24, 6, 44,203, 54,188,
+ 2,192,145, 35, 71,132, 55,222,120, 35,235,167,159,126,234, 37,230,231,221,209,124,208,112,104, 45,194,186, 38,187, 47,235,254,
+ 68, 68,254, 54,220,206,186,126, 34,247, 31,201,201,201,227,188,189,189,227,221,221,221,219, 27,141, 70,105, 77, 77,141,180,241,
+195,168, 66,161, 40, 17,115,233,254, 71, 16,132, 65,115,230,204, 57, 98, 48, 24,124,111,245, 93,133, 66,145, 87, 93, 93, 61, 68,
+204, 53,145,187, 98,176, 68, 68, 68, 68,254, 46,228,231,231,135,137,185,240, 96, 83,215,124,220, 77,204, 9,145,187,129, 56, 44,
+ 66, 68, 68, 68, 68, 68, 68, 68, 68, 52, 88, 34, 34, 34, 34, 34, 34, 34, 34,162,193, 18, 17, 17, 17, 17, 17, 17, 17, 17, 13,150,
+136,136,136,136,136,136,136,136, 72,243,249,127, 79, 26,247,226, 57,216,252,127, 0, 0, 0, 0, 73, 69, 78, 68,174, 66, 96,130,
+ 0};
+
diff --git a/source/blender/editors/datafiles/bmonofont.ttf.c b/source/blender/editors/datafiles/bmonofont.ttf.c
new file mode 100644
index 00000000000..029ee607bc6
--- /dev/null
+++ b/source/blender/editors/datafiles/bmonofont.ttf.c
@@ -0,0 +1,9681 @@
+/* DataToC output of file <bmonofont_ttf> */
+
+int datatoc_bmonofont_ttf_size= 309588;
+char datatoc_bmonofont_ttf[]= {
+ 0, 1, 0, 0, 0, 18, 1, 0, 0, 4, 0, 32, 70, 70, 84, 77, 76,195, 13,197,
+ 0, 0, 1, 44, 0, 0, 0, 28, 71, 68, 69, 70,107,171,118, 72, 0, 0, 1, 72, 0, 0, 0,174, 71, 80, 79, 83, 85,176, 56, 58,
+ 0, 0, 1,248, 0, 0, 53,184, 71, 83, 85, 66, 11, 72,224,153, 0, 0, 55,176, 0, 0, 4,240, 79, 83, 47, 50,135,252,137,178,
+ 0, 0, 60,160, 0, 0, 0, 86, 99,109, 97,112,173,161, 29,196, 0, 0, 60,248, 0, 0, 20,198, 99,118,116, 32,233,151, 7, 12,
+ 0, 0, 81,192, 0, 0, 2, 48,102,112,103,109, 91, 2,107,223, 0, 0, 83,240, 0, 0, 0,172,103, 97,115,112, 0, 7, 0, 7,
+ 0, 0, 84,156, 0, 0, 0, 12,103,108,121,102, 94, 39,215, 74, 0, 0, 84,168, 0, 3,133, 48,104,101, 97,100,233, 47, 44,226,
+ 0, 3,217,216, 0, 0, 0, 54,104,104,101, 97, 8,183, 2, 7, 0, 3,218, 16, 0, 0, 0, 36,104,109,116,120,224, 90,223, 8,
+ 0, 3,218, 52, 0, 0, 23,172,108,111, 99, 97, 19,189,108,128, 0, 3,241,224, 0, 0, 47, 76,109, 97,120,112, 17,120, 9,216,
+ 0, 4, 33, 44, 0, 0, 0, 32,110, 97,109,101, 96,229,233,137, 0, 4, 33, 76, 0, 0, 33, 21,112,111,115,116,106, 10,163,233,
+ 0, 4, 66,100, 0, 0,111,212,112,114,101,112, 58,199,192, 7, 0, 4,178, 56, 0, 0, 7, 27, 0, 0, 0, 1, 0, 0, 0, 0,
+196, 21,105, 4, 0, 0, 0, 0,196, 86,210, 96, 0, 0, 0, 0,196, 86,210, 96, 0, 1, 0, 0, 0, 12, 0, 0, 0,166, 0, 0,
+ 0, 2, 0, 25, 0, 3, 2,123, 0, 1, 2,124, 2,141, 0, 3, 2,142, 2,142, 0, 1, 2,143, 2,149, 0, 3, 2,150, 2,151,
+ 0, 1, 2,152, 2,156, 0, 3, 2,157, 2,158, 0, 1, 2,159, 2,163, 0, 3, 2,164, 2,164, 0, 1, 2,165, 2,173, 0, 3,
+ 2,174, 2,180, 0, 1, 2,181, 2,186, 0, 3, 2,187, 2,187, 0, 1, 2,188, 2,188, 0, 3, 2,189, 4, 3, 0, 1, 4, 4,
+ 4, 15, 0, 3, 4, 16, 4,100, 0, 1, 4,101, 4,101, 0, 3, 4,102, 4,103, 0, 1, 4,104, 4,117, 0, 3, 4,118, 10,148,
+ 0, 1, 10,149, 10,150, 0, 2, 10,151, 11, 98, 0, 1, 11, 99, 11,106, 0, 2, 11,107, 11,209, 0, 1, 0, 4, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 10, 0,164, 0,236, 0, 6, 97,114, 97, 98, 0, 38, 99,121,114,108, 0, 52,100,102,108,116,
+ 0, 70,103,114,101,107, 0, 80,108, 97,111, 32, 0, 92,108, 97,116,110, 0,106, 0, 4, 0, 0, 0, 0,255,255, 0, 2, 0, 0,
+ 0, 3, 0, 10, 0, 1, 83, 82, 66, 32, 0, 10, 0, 0,255,255, 0, 1, 0, 1, 0, 4, 0, 0, 0, 0,255,255, 0, 0, 0, 4,
+ 0, 0, 0, 0,255,255, 0, 1, 0, 1, 0, 4, 0, 0, 0, 0,255,255, 0, 2, 0, 2, 0, 4, 0, 40, 0, 6, 73, 83, 77, 32,
+ 0, 40, 75, 83, 77, 32, 0, 40, 76, 83, 77, 32, 0, 40, 78, 83, 77, 32, 0, 40, 83, 75, 83, 32, 0, 40, 83, 83, 77, 32, 0, 40,
+ 0, 0,255,255, 0, 1, 0, 1, 0, 5,109, 97,114,107, 0, 32,109, 97,114,107, 0, 44,109, 97,114,107, 0, 52,109,107,109,107,
+ 0, 58,114,116, 98,100, 0, 66, 0, 0, 0, 4, 0, 2, 0, 3, 0, 4, 0, 5, 0, 0, 0, 2, 0, 6, 0, 7, 0, 0, 0, 1,
+ 0, 8, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 9, 0, 10, 0, 22, 0, 30, 0, 38, 0, 46, 0, 54, 0, 62, 0, 70,
+ 0, 80, 0, 88, 0, 96, 0, 6, 0, 1, 0, 1, 0, 82, 0, 6, 0, 1, 0, 1, 0,120, 0, 5, 0, 1, 0, 1, 0,192, 0, 4,
+ 0, 1, 0, 1, 1,154, 0, 5, 0, 1, 0, 1, 9,118, 0, 4, 0, 1, 0, 1, 10,152, 0, 4, 0, 0, 0, 2, 18,114, 27, 2,
+ 0, 1, 0, 0, 0, 1, 49,196, 0, 4, 0, 0, 0, 1, 49,236, 0, 1, 0, 8, 0, 1, 52, 84, 0, 1, 0, 28, 0, 22, 0, 1,
+ 0, 34, 0, 12, 0, 1, 0, 4, 0, 1, 2,112,253,228, 0, 1, 0, 1, 4, 14, 0, 1, 0, 1, 4, 9, 0, 1, 0, 0, 0, 6,
+ 0, 1, 2,104, 0, 0, 0, 1, 0, 38, 0, 30, 0, 1, 0, 48, 0, 12, 0, 2, 0, 6, 0, 12, 0, 1, 2, 99, 7, 34, 0, 1,
+ 2, 99, 6,224, 0, 1, 0, 2, 4, 10, 4, 13, 0, 1, 0, 3, 4, 7, 4, 8, 4, 11, 0, 3, 0, 0, 0, 14, 0, 0, 0, 20,
+ 0, 0, 0, 26, 0, 1, 2, 93, 4,106, 0, 1, 2, 93, 4,106, 0, 1, 2, 98, 4,106, 0, 1, 0,184, 0,174, 0, 1, 0,194,
+ 0, 12, 0, 8, 0, 18, 0, 36, 0, 54, 0, 72, 0, 90, 0,108, 0,126, 0,144, 0, 2, 0, 6, 0, 12, 0, 1, 3,224, 0, 80,
+ 0, 1, 3,124, 0, 72, 0, 2, 0, 6, 0, 12, 0, 1, 3, 48,255,224, 0, 1, 2,172,255,220, 0, 2, 0, 6, 0, 12, 0, 1,
+ 3,224, 0, 80, 0, 1, 3,124, 0, 72, 0, 2, 0, 6, 0, 12, 0, 1, 3, 60,255,136, 0, 1, 2, 80,255,132, 0, 2, 0, 6,
+ 0, 12, 0, 1, 3,168, 0, 44, 0, 1, 1, 32,253,220, 0, 2, 0, 6, 0, 12, 0, 1, 3, 84,255, 96, 0, 1, 1, 12,253,220,
+ 0, 2, 0, 6, 0, 12, 0, 1, 3,224, 0, 80, 0, 1, 3,124, 0, 72, 0, 2, 0, 6, 0, 12, 0, 1, 2, 12,255,164, 0, 1,
+ 3, 16, 0, 32, 0, 2, 0, 1, 11, 99, 11,106, 0, 0, 0, 1, 0, 3, 4, 6, 4, 9, 4, 14, 0, 3, 0, 0, 0, 14, 0, 0,
+ 0, 20, 0, 0, 0, 26, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 7,186, 7,110, 0, 1,
+ 7,196, 0, 12, 0,236, 1,218, 1,224, 1,230, 1,236, 1,242, 1,248, 1,254, 2, 4, 2, 10, 2, 16, 2, 22, 2, 28, 2, 34,
+ 2, 40, 2, 46, 2, 52, 2, 58, 2, 64, 2, 70, 2, 76, 2, 82, 2, 88, 2, 94, 2,100, 2,106, 2,112, 2,118, 2,124, 2,130,
+ 2,136, 2,142, 2,148, 2,154, 2,160, 2,166, 2,172, 2,178, 2,184, 2,190, 2,196, 2,202, 2,208, 2,214, 2,220, 2,226,
+ 2,232, 2,238, 2,244, 2,250, 3, 0, 3, 6, 3, 12, 3, 18, 3, 24, 3, 30, 3, 36, 3, 42, 3, 48, 3, 54, 3, 60, 3, 66,
+ 3, 72, 3, 78, 3, 84, 3, 90, 3, 96, 3,102, 3,108, 3,114, 3,120, 3,126, 3,132, 3,138, 3,144, 3,150, 3,156, 3,162,
+ 3,168, 3,174, 3,180, 3,186, 3,192, 3,198, 3,204, 3,210, 3,216, 3,222, 3,228, 3,234, 3,240, 3,246, 3,252, 4, 2,
+ 4, 8, 4, 14, 4, 20, 4, 26, 4, 32, 4, 38, 4, 44, 4, 50, 4, 56, 4, 62, 4, 68, 4, 74, 4, 80, 4, 86, 4, 92, 4, 98,
+ 4,104, 4,110, 4,116, 4,122, 4,128, 4,134, 4,140, 4,146, 4,152, 4,158, 4,164, 4,170, 4,176, 4,182, 4,188, 4,194,
+ 4,200, 4,206, 4,212, 4,218, 4,224, 4,230, 4,236, 4,242, 4,248, 4,254, 5, 4, 5, 10, 5, 16, 5, 22, 5, 28, 5, 34,
+ 5, 40, 5, 46, 5, 52, 5, 58, 5, 64, 5, 70, 5, 76, 5, 82, 5, 88, 5, 94, 5,100, 5,106, 5,112, 5,118, 5,124, 5,130,
+ 5,136, 5,142, 5,148, 5,154, 5,160, 5,166, 5,172, 5,178, 5,184, 5,190, 5,196, 5,202, 5,208, 5,214, 5,220, 5,226,
+ 5,232, 5,238, 5,244, 5,250, 6, 0, 6, 6, 6, 12, 6, 18, 6, 24, 6, 30, 6, 36, 6, 42, 6, 48, 6, 54, 6, 60, 6, 66,
+ 6, 72, 6, 78, 6, 84, 6, 90, 6, 96, 6,102, 6,108, 6,114, 6,120, 6,126, 6,132, 6,138, 6,144, 6,150, 6,156, 6,162,
+ 6,168, 6,174, 6,180, 6,186, 6,192, 6,198, 6,204, 6,210, 6,216, 6,222, 6,228, 6,234, 6,240, 6,246, 6,252, 7, 2,
+ 7, 8, 7, 14, 7, 20, 7, 26, 7, 32, 7, 38, 7, 44, 7, 50, 7, 56, 7, 62, 7, 68, 7, 74, 7, 80, 7, 86, 7, 92, 0, 1,
+ 2, 88, 0, 0, 0, 1, 2,100,253,223, 0, 1, 1,212, 2,124, 0, 1, 2,100,255,178, 0, 1, 2,104,254,136, 0, 1, 2, 48,
+255, 96, 0, 1, 2,116,255, 88, 0, 1, 2,116,255, 88, 0, 1, 1,252,253,204, 0, 1, 2, 12,253,208, 0, 1, 2, 60,253,183,
+ 0, 1, 2, 8,255,124, 0, 1, 2, 8,255,140, 0, 1, 2, 48,253,224, 0, 1, 2, 48,253,236, 0, 1, 2,104,254, 76, 0, 1,
+ 2,160,254,132, 0, 1, 3, 40,254,220, 0, 1, 3, 32,254,192, 0, 1, 1, 84,255,112, 0, 1, 1,108,255,120, 0, 1, 2,144,
+253,204, 0, 1, 2,136,253,208, 0, 1, 2, 96,255,120, 0, 1, 2, 60,255, 68, 0, 1, 2, 40,254, 68, 0, 1, 1,252,255,100,
+ 0, 1, 2, 20,254,124, 0, 1, 2,116,255, 88, 0, 1, 2, 76,254, 92, 0, 1, 2, 56,255, 40, 0, 1, 2, 80,253,220, 0, 1,
+ 2, 64,254,180, 0, 1, 2, 64,253,224, 0, 1, 2,116,255, 88, 0, 1, 2,116,255, 88, 0, 1, 2, 52,253,232, 0, 1, 2,120,
+253,208, 0, 1, 2,116,255, 88, 0, 1, 2, 96,253,224, 0, 1, 2,116,255, 88, 0, 1, 2,100,253,236, 0, 1, 2, 68,253,216,
+ 0, 1, 1,244,253,208, 0, 1, 2, 12,253,231, 0, 1, 2, 52,253,220, 0, 1, 2, 52,253,224, 0, 1, 2, 88,253,220, 0, 1,
+ 2, 72,253,224, 0, 1, 2, 46,253,228, 0, 1, 2, 69,253,223, 0, 1, 2, 17,253,227, 0, 1, 1,212,255, 68, 0, 1, 2, 53,
+255,106, 0, 1, 2, 84,255,106, 0, 1, 2, 8,254,110, 0, 1, 2, 96,255, 95, 0, 1, 2, 80,253,220, 0, 1, 2, 13,254,112,
+ 0, 1, 2, 13,254,112, 0, 1, 2,105,253,168, 0, 1, 2, 70,253,168, 0, 1, 2, 87,253,218, 0, 1, 2, 87,253,218, 0, 1,
+ 2,133,253,168, 0, 1, 2, 64,253,168, 0, 1, 2, 84,253,218, 0, 1, 2, 81,253,218, 0, 1, 2, 88,253,168, 0, 1, 2, 58,
+253,168, 0, 1, 2, 66,253,218, 0, 1, 2, 96,253,218, 0, 1, 2,130,255,106, 0, 1, 2, 76,255,106, 0, 1, 2, 91,255,155,
+ 0, 1, 2, 90,255,156, 0, 1, 2, 91,255,106, 0, 1, 2, 73,255,106, 0, 1, 2, 87,255,156, 0, 1, 2, 84,255,156, 0, 1,
+ 2, 76,255,106, 0, 1, 2, 52,255,106, 0, 1, 2, 75,255,156, 0, 1, 2, 93,255,156, 0, 1, 1,212,255, 76, 0, 1, 1,148,
+255, 64, 0, 1, 1,244,255,106, 0, 1, 2, 86,255,106, 0, 1, 1,224,255, 56, 0, 1, 1,136,255, 56, 0, 1, 1,244,255,106,
+ 0, 1, 2, 98,255,106, 0, 1, 2,116,253,168, 0, 1, 2, 92,253,168, 0, 1, 1,172,254, 12, 0, 1, 2, 88,254, 12, 0, 1,
+ 2, 84,253,168, 0, 1, 2, 72,253,168, 0, 1, 1,132,255, 6, 0, 1, 2, 88,255, 6, 0, 1, 2, 84,253,168, 0, 1, 2, 56,
+253,167, 0, 1, 1,184,253,228, 0, 1, 2, 88,254, 12, 0, 1, 2,104,253,168, 0, 1, 2,100,253,168, 0, 1, 1,196,253,228,
+ 0, 1, 2, 88,254, 12, 0, 1, 1,244,254, 12, 0, 1, 1,244,254, 12, 0, 1, 1,244,254, 12, 0, 1, 1,244,254, 12, 0, 1,
+ 2, 63,255,106, 0, 1, 1,198,255,106, 0, 1, 1, 44,255,106, 0, 1, 1, 44,255,106, 0, 1, 2, 84,255, 95, 0, 1, 1,238,
+255,106, 0, 1, 1, 44,255,106, 0, 1, 1, 44,255,106, 0, 1, 2, 84,255,100, 0, 1, 2, 84,255,100, 0, 1, 1,184,255,100,
+ 0, 1, 2, 16,255,100, 0, 1, 2, 76,254,112, 0, 1, 1,152,254,112, 0, 1, 2, 79,254,162, 0, 1, 2, 91,254,162, 0, 1,
+ 2,192, 0, 28, 0, 1, 2,100,253,216, 0, 1, 2,204,253,216, 0, 1, 2, 24,255,128, 0, 1, 2,100,255, 88, 0, 1, 2,100,
+255,120, 0, 1, 2,176,255, 88, 0, 1, 2,100,254,104, 0, 1, 2, 28,254,104, 0, 1, 2, 68,254,140, 0, 1, 2, 88,254,140,
+ 0, 1, 2, 44,255, 76, 0, 1, 2,108,255,132, 0, 1, 2,108,255,132, 0, 1, 2, 84,255,112, 0, 1, 2, 60,255,132, 0, 1,
+ 2, 88,255,124, 0, 1, 2,108,255,132, 0, 1, 2, 72,255,128, 0, 1, 2, 72,255,124, 0, 1, 2, 84,255,116, 0, 1, 2, 0,
+253,144, 0, 1, 2, 0,253,144, 0, 1, 2, 8,254,136, 0, 1, 2, 12,254,108, 0, 1, 2, 0,253,144, 0, 1, 2, 0,253,144,
+ 0, 1, 1, 60,255,132, 0, 1, 1, 84,255,112, 0, 1, 2, 0,253,144, 0, 1, 2, 0,253,144, 0, 1, 1,124,255,128, 0, 1,
+ 1, 68,255, 92, 0, 1, 2, 56,255, 92, 0, 1, 2, 56,255, 92, 0, 1, 2, 56,255, 92, 0, 1, 2, 56,255, 92, 0, 1, 1,188,
+253,192, 0, 1, 1,140,253,189, 0, 1, 1,188,253,192, 0, 1, 1,156,253,188, 0, 1, 1,152,254, 12, 0, 1, 1, 88,254, 16,
+ 0, 1, 1, 44,255,108, 0, 1, 1, 16,255,100, 0, 1, 1, 92,254, 28, 0, 1, 1, 9,254, 24, 0, 1, 1, 44,255,108, 0, 1,
+ 1, 44,255,108, 0, 1, 1,120,254, 20, 0, 1, 1, 68,254, 17, 0, 1, 1, 44,255,108, 0, 1, 1, 44,255,108, 0, 1, 1, 76,
+254, 16, 0, 1, 1, 32,254, 24, 0, 1, 1, 44,255,108, 0, 1, 1, 4,255,108, 0, 1, 0,240,255,108, 0, 1, 0,216,255,108,
+ 0, 1, 0,240,255,108, 0, 1, 0,208,255,112, 0, 1, 0,240,255,108, 0, 1, 0,208,255,104, 0, 1, 0,240,255,108, 0, 1,
+ 0,220,255,108, 0, 1, 1,122,253,215, 0, 1, 1,122,253,215, 0, 1, 1,224,255,147, 0, 1, 2, 94,255,141, 0, 1, 1,122,
+253,215, 0, 1, 1,122,253,215, 0, 1, 1,146,255,159, 0, 1, 2, 94,255,159, 0, 1, 2, 94,255, 45, 0, 1, 2,100,255, 15,
+ 0, 1, 1,158,255,117, 0, 1, 2,106,255,129, 0, 1, 1,224,254, 25, 0, 1, 1,224,253,185, 0, 1, 1, 56,255,141, 0, 1,
+ 2,106,255,129, 0, 1, 2, 58,255, 75, 0, 1, 1,218,255, 81, 0, 1, 0,216,255,129, 0, 1, 0,162,255, 93, 0, 1, 2, 88,
+254,109, 0, 1, 1,254,254, 97, 0, 1, 2,100,255,135, 0, 1, 2,106,255,117, 0, 1, 3, 18,255,117, 0, 1, 2,172,254,163,
+ 0, 1, 2, 70,255, 21, 0, 1, 2, 88,255, 39, 0, 1, 1,254,254, 85, 0, 1, 1,194,253,197, 0, 1, 2, 64,255,129, 0, 1,
+ 2, 76,255,123, 0, 1, 2, 82,255, 75, 0, 1, 2, 82,255,111, 0, 1, 1,176,255, 39, 0, 1, 2, 16,253,210, 0, 1, 2, 76,
+253,233, 0, 1, 2, 4,253,209, 0, 1, 2, 46,254,145, 0, 1, 2, 28,253,173, 0, 1, 1,146,253,188, 0, 1, 2, 58,254,139,
+ 0, 1, 2, 82,254,133, 0, 2, 0, 12, 3,223, 3,223, 0, 0, 3,227, 4, 3, 0, 1, 4, 33, 4, 50, 0, 34, 4, 52, 4, 55,
+ 0, 52, 4, 57, 4, 60, 0, 56, 10,151, 10,210, 0, 60, 10,213, 10,216, 0,120, 10,219, 10,222, 0,124, 10,238, 10,238, 0,128,
+ 10,245, 10,246, 0,129, 10,249, 11, 93, 0,131, 11, 95, 11, 98, 0,232, 0, 1, 0, 3, 4, 6, 4, 9, 4, 14, 0, 3, 0, 0,
+ 0, 14, 0, 0, 0, 20, 0, 0, 0, 26, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 0,184,
+ 0,174, 0, 1, 0,206, 0, 12, 0, 8, 0, 18, 0, 36, 0, 54, 0, 72, 0, 90, 0,108, 0,126, 0,144, 0, 2, 0, 6, 0, 12,
+ 0, 1, 3,156, 6,104, 0, 1, 0,147, 7, 53, 0, 2, 0, 6, 0, 12, 0, 1, 3,156, 6,104, 0, 1, 0, 91, 7, 25, 0, 2,
+ 0, 6, 0, 12, 0, 1, 3,156, 6,104, 0, 1, 0,155, 7,246, 0, 2, 0, 6, 0, 12, 0, 1, 3, 84, 6,108, 0, 1, 0, 43,
+ 7,250, 0, 2, 0, 6, 0, 12, 0, 1, 3,156, 6,104, 0, 1, 0,223, 5,221, 0, 2, 0, 6, 0, 12, 0, 1, 3,156, 6,104,
+ 0, 1, 0,223, 5,221, 0, 2, 0, 6, 0, 12, 0, 1, 3,156, 6,104, 0, 1, 0,223, 5,221, 0, 2, 0, 6, 0, 12, 0, 1,
+ 3, 92, 6,104, 0, 1, 0,159, 5,221, 0, 2, 0, 1, 11, 99, 11,106, 0, 0, 0, 1, 0, 9, 4, 4, 4, 5, 4, 7, 4, 8,
+ 4, 10, 4, 11, 4, 12, 4, 13, 4, 15, 0, 9, 0, 0, 0, 38, 0, 0, 0, 44, 0, 0, 0, 50, 0, 0, 0, 56, 0, 0, 0, 62,
+ 0, 0, 0, 68, 0, 0, 0, 74, 0, 0, 0, 80, 0, 0, 0, 86, 0, 1, 2, 93, 4,106, 0, 1, 2, 93, 4,106, 0, 1, 2, 93,
+ 4,106, 0, 1, 2, 93, 4,106, 0, 1, 2, 93, 4,106, 0, 1, 2, 98, 4,106, 0, 1, 2, 93, 4,106, 0, 1, 2, 93, 4,106,
+ 0, 1, 2,104, 4,176, 0, 1, 7,112, 7, 30, 0, 1, 7,134, 0, 12, 0,226, 1,198, 1,204, 1,210, 1,216, 1,222, 1,228,
+ 1,234, 1,240, 1,246, 1,252, 2, 2, 2, 8, 2, 14, 2, 20, 2, 26, 2, 32, 2, 38, 2, 44, 2, 50, 2, 56, 2, 62, 2, 68,
+ 2, 74, 2, 80, 2, 86, 2, 92, 2, 98, 2,104, 2,110, 2,116, 2,122, 2,128, 2,134, 2,140, 2,146, 2,152, 2,158, 2,164,
+ 2,170, 2,176, 2,182, 2,188, 2,194, 2,200, 2,206, 2,212, 2,218, 2,224, 2,230, 2,236, 2,242, 2,248, 2,254, 3, 4,
+ 3, 10, 3, 16, 3, 22, 3, 28, 3, 34, 3, 40, 3, 46, 3, 52, 3, 58, 3, 64, 3, 70, 3, 76, 3, 82, 3, 88, 3, 94, 3,100,
+ 3,106, 3,112, 3,118, 3,124, 3,130, 3,136, 3,142, 3,148, 3,154, 3,160, 3,166, 3,172, 3,178, 3,184, 3,190, 3,196,
+ 3,202, 3,208, 3,214, 3,220, 3,226, 3,232, 3,238, 3,244, 3,250, 4, 0, 4, 6, 4, 12, 4, 18, 4, 24, 4, 30, 4, 36,
+ 4, 42, 4, 48, 4, 54, 4, 60, 4, 66, 4, 72, 4, 78, 4, 84, 4, 90, 4, 96, 4,102, 4,108, 4,114, 4,120, 4,126, 4,132,
+ 4,138, 4,144, 4,150, 4,156, 4,162, 4,168, 4,174, 4,180, 4,186, 4,192, 4,198, 4,204, 4,210, 4,216, 4,222, 4,228,
+ 4,234, 4,240, 4,246, 4,252, 5, 2, 5, 8, 5, 14, 5, 20, 5, 26, 5, 32, 5, 38, 5, 44, 5, 50, 5, 56, 5, 62, 5, 68,
+ 5, 74, 5, 80, 5, 86, 5, 92, 5, 98, 5,104, 5,110, 5,116, 5,122, 5,128, 5,134, 5,140, 5,146, 5,152, 5,158, 5,164,
+ 5,170, 5,176, 5,182, 5,188, 5,194, 5,200, 5,206, 5,212, 5,218, 5,224, 5,230, 5,236, 5,242, 5,248, 5,254, 6, 4,
+ 6, 10, 6, 16, 6, 22, 6, 28, 6, 34, 6, 40, 6, 46, 6, 52, 6, 58, 6, 64, 6, 70, 6, 76, 6, 82, 6, 88, 6, 94, 6,100,
+ 6,106, 6,112, 6,118, 6,124, 6,130, 6,136, 6,142, 6,148, 6,154, 6,160, 6,166, 6,172, 6,178, 6,184, 6,190, 6,196,
+ 6,202, 6,208, 6,214, 6,220, 6,226, 6,232, 6,238, 6,244, 6,250, 7, 0, 7, 6, 7, 12, 0, 1, 2,152, 4,132, 0, 1,
+ 2,100, 8,116, 0, 1, 2,208, 5, 32, 0, 1, 1,204, 4,184, 0, 1, 2,104, 6,168, 0, 1, 2,100, 2,252, 0, 1, 2, 56,
+ 4,160, 0, 1, 2,124, 3,212, 0, 1, 2, 36, 4,160, 0, 1, 1,244, 4,124, 0, 1, 2, 4, 4, 96, 0, 1, 2, 4, 5, 72,
+ 0, 1, 1,208, 4, 76, 0, 1, 1,192, 5, 68, 0, 1, 2, 4, 2,252, 0, 1, 1,152, 4, 32, 0, 1, 2, 92, 3,240, 0, 1,
+ 1,220, 5,116, 0, 1, 1, 64, 3,184, 0, 1, 1, 52, 4, 72, 0, 1, 0,232, 6,184, 0, 1, 0,236, 6,212, 0, 1, 1,156,
+ 5, 40, 0, 1, 1,124, 5,244, 0, 1, 2, 88, 4, 84, 0, 1, 2,252, 5,132, 0, 1, 2,156, 5,248, 0, 1, 1,240, 5,204,
+ 0, 1, 3,144, 6,196, 0, 1, 2,152, 4, 40, 0, 1, 1,248, 4,108, 0, 1, 1,240, 3,240, 0, 1, 2,116, 3,188, 0, 1,
+ 2,172, 4, 60, 0, 1, 2,152, 4, 48, 0, 1, 2,124, 3,212, 0, 1, 2,188, 4,218, 0, 1, 2,111, 4,126, 0, 1, 1, 24,
+ 5,120, 0, 1, 1,174, 5,120, 0, 1, 3,234, 8, 52, 0, 1, 2, 95, 4, 96, 0, 1, 2,212, 4,196, 0, 1, 1,159, 3, 12,
+ 0, 1, 1,135, 4,144, 0, 1, 2,105, 3,232, 0, 1, 2, 70, 3,232, 0, 1, 2, 87, 3,232, 0, 1, 2, 87, 3,232, 0, 1,
+ 2,133, 3,232, 0, 1, 2, 64, 3,232, 0, 1, 2, 84, 3,232, 0, 1, 2, 84, 3,232, 0, 1, 2, 91, 3,232, 0, 1, 2, 58,
+ 3,232, 0, 1, 2, 66, 3,232, 0, 1, 2, 96, 3,232, 0, 1, 2,130, 4, 76, 0, 1, 2, 76, 4, 76, 0, 1, 2, 91, 5, 19,
+ 0, 1, 2, 90, 5, 20, 0, 1, 2, 91, 4,157, 0, 1, 2, 73, 4,175, 0, 1, 2, 87, 5, 20, 0, 1, 2, 84, 5, 20, 0, 1,
+ 2, 76, 4,226, 0, 1, 2, 52, 4,226, 0, 1, 2, 75, 5,170, 0, 1, 2, 93, 5,170, 0, 1, 1,144, 5,108, 0, 1, 1, 56,
+ 4,244, 0, 1, 1,244, 6, 64, 0, 1, 2, 94, 5,170, 0, 1, 1, 32, 5, 32, 0, 1, 1, 8, 4,228, 0, 1, 1,244, 6, 64,
+ 0, 1, 2, 98, 5,170, 0, 1, 1,210, 3,232, 0, 1, 1,186, 3,232, 0, 1, 1,172, 3,232, 0, 1, 2, 88, 3,232, 0, 1,
+ 1,178, 3,232, 0, 1, 1,166, 3,232, 0, 1, 1,132, 3,232, 0, 1, 2, 88, 3,232, 0, 1, 1,178, 3,232, 0, 1, 1,150,
+ 3,231, 0, 1, 1,184, 3,232, 0, 1, 2, 88, 3,232, 0, 1, 1,198, 3,232, 0, 1, 1,194, 3,232, 0, 1, 1,196, 3,232,
+ 0, 1, 2, 88, 3,232, 0, 1, 2,111, 4, 77, 0, 1, 2,188, 4,226, 0, 1, 2,170, 4,191, 0, 1, 2,152, 4,241, 0, 1,
+ 2, 33, 5, 84, 0, 1, 1,177, 5, 25, 0, 1, 1,255, 6, 14, 0, 1, 1,241, 6, 14, 0, 1, 1,140, 5,120, 0, 1, 0,243,
+ 5,120, 0, 1, 0,250, 6,164, 0, 1, 0,250, 6,164, 0, 1, 2, 84, 4,128, 0, 1, 2, 84, 4,128, 0, 1, 1,184, 4,128,
+ 0, 1, 2, 16, 4,128, 0, 1, 1,204, 3, 38, 0, 1, 1,148, 2,126, 0, 1, 2, 79, 3,232, 0, 1, 2, 91, 3,232, 0, 1,
+ 2,176, 4,184, 0, 1, 2, 12, 8,216, 0, 1, 2, 88, 8,224, 0, 1, 2,140, 5, 80, 0, 1, 2, 88, 5, 68, 0, 1, 1,128,
+ 4,216, 0, 1, 1, 28, 3,244, 0, 1, 2, 44, 5, 97, 0, 1, 2, 68, 5,102, 0, 1, 2, 92, 6,216, 0, 1, 2, 80, 6,232,
+ 0, 1, 2,104, 3, 60, 0, 1, 2, 16, 2,232, 0, 1, 2, 12, 3,200, 0, 1, 2, 92, 3,156, 0, 1, 2, 4, 4,200, 0, 1,
+ 2, 92, 4,216, 0, 1, 2, 92, 3,244, 0, 1, 2, 48, 4, 20, 0, 1, 2, 44, 4,196, 0, 1, 2, 48, 4,224, 0, 1, 2, 64,
+ 4,240, 0, 1, 2, 44, 5, 0, 0, 1, 2, 32, 5,100, 0, 1, 2, 32, 5, 96, 0, 1, 1,248, 4,128, 0, 1, 1,212, 4,124,
+ 0, 1, 1,116, 4, 76, 0, 1, 1, 96, 4, 48, 0, 1, 1,220, 4,164, 0, 1, 1,200, 4,176, 0, 1, 1, 48, 4,144, 0, 1,
+ 1,128, 4,132, 0, 1, 1,220, 5, 64, 0, 1, 1,216, 5, 92, 0, 1, 1, 32, 4,224, 0, 1, 1, 24, 4,220, 0, 1, 2, 12,
+ 4,172, 0, 1, 2, 4, 4,184, 0, 1, 2, 8, 5, 84, 0, 1, 2, 20, 5, 96, 0, 1, 2, 64, 3, 20, 0, 1, 1,180, 3, 16,
+ 0, 1, 1,148, 4, 76, 0, 1, 1, 56, 4,136, 0, 1, 2, 52, 4, 15, 0, 1, 1,206, 3,183, 0, 1, 2, 53, 3,222, 0, 1,
+ 1,243, 3,197, 0, 1, 1, 24, 5, 68, 0, 1, 0,180, 5, 56, 0, 1, 1, 48, 5, 72, 0, 1, 1, 12, 5, 60, 0, 1, 1, 68,
+ 3,140, 0, 1, 0,220, 3, 60, 0, 1, 1,200, 3,152, 0, 1, 1,120, 3,136, 0, 1, 1, 40, 4, 76, 0, 1, 0,208, 4, 88,
+ 0, 1, 1, 36, 4, 84, 0, 1, 0,212, 4,116, 0, 1, 0,240, 6,216, 0, 1, 0,192, 6,220, 0, 1, 0,232, 6,220, 0, 1,
+ 0,192, 6,228, 0, 1, 0,236, 6,244, 0, 1, 0,208, 6,228, 0, 1, 0,240, 6,232, 0, 1, 0,200, 6,224, 0, 1, 1,132,
+ 5, 48, 0, 1, 1,168, 4, 84, 0, 1, 1,196, 5, 76, 0, 1, 2,104, 4,132, 0, 1, 1,132, 6, 48, 0, 1, 1,216, 5,112,
+ 0, 1, 1,128, 6, 76, 0, 1, 2,104, 5, 60, 0, 1, 2,248, 5,112, 0, 1, 2,248, 4,248, 0, 1, 1,172, 5,184, 0, 1,
+ 2,108, 5, 36, 0, 1, 2,100, 5,172, 0, 1, 2, 96, 4,212, 0, 1, 1, 48, 5,156, 0, 1, 2,104, 5, 56, 0, 1, 2, 60,
+ 6, 8, 0, 1, 1,224, 6, 0, 0, 1, 1,247, 5,239, 0, 1, 2, 10, 6, 20, 0, 1, 2, 80, 6, 20, 0, 1, 1,200, 6, 16,
+ 0, 1, 2, 76, 6,100, 0, 1, 2,104, 6,188, 0, 1, 2,140, 3,216, 0, 1, 2,120, 3,132, 0, 1, 2, 56, 3,132, 0, 1,
+ 2, 84, 3,180, 0, 1, 1,228, 4,136, 0, 1, 1,135, 3, 82, 0, 1, 2, 32, 4,109, 0, 1, 2, 36, 4,118, 0, 1, 1,234,
+ 3,136, 0, 1, 2, 50, 3,122, 0, 1, 1,175, 4, 96, 0, 1, 1,238, 3, 28, 0, 1, 2,131, 3, 77, 0, 1, 2, 59, 3, 41,
+ 0, 1, 1,252, 3, 82, 0, 1, 1,166, 2, 68, 0, 1, 2, 5, 3,104, 0, 1, 1,112, 2, 95, 0, 1, 2, 41, 3, 73, 0, 1,
+ 2, 32, 3, 82, 0, 2, 0, 13, 3,223, 3,223, 0, 0, 3,225, 3,226, 0, 1, 3,228, 4, 3, 0, 3, 4, 36, 4, 36, 0, 35,
+ 4, 48, 4, 49, 0, 36, 4, 53, 4, 55, 0, 38, 4, 57, 4, 60, 0, 41, 10,151, 10,210, 0, 45, 10,213, 10,216, 0,105, 10,219,
+ 10,222, 0,109, 10,238, 10,238, 0,113, 10,241, 10,244, 0,114, 10,247, 11, 98, 0,118, 0, 1, 0, 9, 4, 4, 4, 5, 4, 7,
+ 4, 8, 4, 10, 4, 11, 4, 12, 4, 13, 4, 15, 0, 9, 0, 0, 0, 38, 0, 0, 0, 44, 0, 0, 0, 50, 0, 0, 0, 56, 0, 0,
+ 0, 62, 0, 0, 0, 68, 0, 0, 0, 74, 0, 0, 0, 80, 0, 0, 0, 86, 0, 1, 2, 93, 4,106, 0, 1, 2, 93, 4,106, 0, 1,
+ 2, 93, 4,106, 0, 1, 2, 93, 4,106, 0, 1, 2, 93, 4,106, 0, 1, 2, 98, 4,106, 0, 1, 2, 93, 4,106, 0, 1, 2, 93,
+ 4,106, 0, 1, 2,104, 4,176, 0, 1, 8,126, 7,246, 0, 1, 8,132, 0, 12, 0,253, 1,252, 2, 2, 2, 8, 2, 14, 2, 20,
+ 2, 26, 2, 32, 2, 38, 2, 44, 2, 50, 2, 56, 2, 62, 2, 68, 2, 74, 2, 80, 2, 86, 2, 92, 2, 98, 2,104, 2,110, 2,116,
+ 2,122, 2,128, 2,134, 2,140, 2,146, 2,152, 2,158, 2,164, 2,170, 2,176, 2,182, 2,188, 2,194, 2,200, 2,206, 2,212,
+ 2,218, 2,224, 2,230, 2,236, 2,242, 2,248, 2,254, 3, 4, 3, 10, 3, 16, 3, 22, 3, 28, 3, 34, 3, 40, 3, 46, 3, 52,
+ 3, 58, 3, 64, 3, 70, 3, 76, 3, 82, 3, 88, 3, 94, 3,100, 3,106, 3,112, 3,118, 3,124, 3,130, 3,136, 3,142, 3,148,
+ 3,154, 3,160, 3,166, 3,172, 3,178, 3,184, 3,190, 3,196, 3,202, 3,208, 3,214, 3,220, 3,226, 3,232, 3,238, 3,244,
+ 3,250, 4, 0, 4, 6, 4, 12, 4, 18, 4, 24, 4, 30, 4, 36, 4, 42, 4, 48, 4, 54, 4, 60, 4, 66, 4, 72, 4, 78, 4, 84,
+ 4, 90, 4, 96, 4,102, 4,108, 4,114, 4,120, 4,126, 4,132, 4,138, 4,144, 4,150, 4,156, 4,162, 4,168, 4,174, 4,180,
+ 4,186, 4,192, 4,198, 4,204, 4,210, 4,216, 4,222, 4,228, 4,234, 4,240, 4,246, 4,252, 5, 2, 5, 8, 5, 14, 5, 20,
+ 5, 26, 5, 32, 5, 38, 5, 44, 5, 50, 5, 56, 5, 62, 5, 68, 5, 74, 5, 80, 5, 86, 5, 92, 5, 98, 5,104, 5,110, 5,116,
+ 5,122, 5,128, 5,134, 5,140, 5,146, 5,152, 5,158, 5,164, 5,170, 5,176, 5,182, 5,188, 5,194, 5,200, 5,206, 5,212,
+ 5,218, 5,224, 5,230, 5,236, 5,242, 5,248, 5,254, 6, 4, 6, 10, 6, 16, 6, 22, 6, 28, 6, 34, 6, 40, 6, 46, 6, 52,
+ 6, 58, 6, 64, 6, 70, 6, 76, 6, 82, 6, 88, 6, 94, 6,100, 6,106, 6,112, 6,118, 6,124, 6,130, 6,136, 6,142, 6,148,
+ 6,154, 6,160, 6,166, 6,172, 6,178, 6,184, 6,190, 6,196, 6,202, 6,208, 6,214, 6,220, 6,226, 6,232, 6,238, 6,244,
+ 6,250, 7, 0, 7, 6, 7, 12, 7, 18, 7, 24, 7, 30, 7, 36, 7, 42, 7, 48, 7, 54, 7, 60, 7, 66, 7, 72, 7, 78, 7, 84,
+ 7, 90, 7, 96, 7,102, 7,108, 7,114, 7,120, 7,126, 7,132, 7,138, 7,144, 7,150, 7,156, 7,162, 7,168, 7,174, 7,180,
+ 7,186, 7,192, 7,198, 7,204, 7,210, 7,216, 7,222, 7,228, 0, 1, 4, 68, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,179,
+ 0, 0, 0, 1, 1,120, 0, 0, 0, 1, 2,122, 0, 0, 0, 1, 1, 79, 0, 0, 0, 1, 2,154, 0, 0, 0, 1, 3,226, 0, 0,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,154, 0, 0, 0, 1, 4, 68, 0, 0, 0, 1, 2,154, 0, 0, 0, 1, 4, 28, 0, 0, 0, 1,
+ 3,228, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 1, 42, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 4, 68, 0, 0, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 3,147, 0, 0, 0, 1, 4, 68, 0, 0,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,154, 0, 0, 0, 1, 3,198, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,208, 0, 0, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,118, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104,254, 86, 0, 1, 3,190, 0, 0, 0, 1, 2,104,
+ 0, 0, 0, 1, 1,185,254, 89, 0, 1, 4, 68, 0, 0, 0, 1, 3,120, 0, 0, 0, 1, 4, 27, 0, 0, 0, 1, 3,190, 0, 0,
+ 0, 1, 2,104, 0, 0, 0, 1, 1, 26,254, 86, 0, 1, 3,194,254, 86, 0, 1, 1,198, 0, 0, 0, 1, 2,104, 0, 0, 0, 1,
+ 3,120, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 3,115, 0, 0, 0, 1, 4, 68, 0, 0, 0, 1, 1, 26,
+254, 86, 0, 1, 2,104, 0, 0, 0, 1, 4, 68, 0, 0, 0, 1, 4, 68, 0, 0, 0, 1, 4, 68, 0, 0, 0, 1, 4, 68, 0, 0,
+ 0, 1, 4, 68, 0, 0, 0, 1, 4, 68, 0, 0, 0, 1, 2,122, 0, 0, 0, 1, 2,122, 0, 0, 0, 1, 2,122, 0, 0, 0, 1,
+ 2,122, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2, 54,
+ 0, 0, 0, 1, 3,228, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 1, 52, 0, 0, 0, 1, 2, 54, 0, 0, 0, 1, 3,198, 0, 0, 0, 1, 3,198,
+ 0, 0, 0, 1, 3,198, 0, 0, 0, 1, 3,198, 0, 0, 0, 1, 3,198, 0, 0, 0, 1, 3,198, 0, 0, 0, 1, 2,118, 0, 0,
+ 0, 1, 2,118, 0, 0, 0, 1, 2,118, 0, 0, 0, 1, 2,118, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 3,190, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 1, 26,254, 86, 0, 1, 1, 26,254, 86, 0, 1,
+ 1, 26,254, 86, 0, 1, 4, 68, 0, 0, 0, 1, 4, 68, 0, 0, 0, 1, 3,198, 0, 0, 0, 1, 2,179, 0, 0, 0, 1, 2,179,
+ 0, 0, 0, 1, 2,208, 0, 0, 0, 1, 2,179, 0, 0, 0, 1, 2,208, 0, 0, 0, 1, 2,179, 0, 0, 0, 1, 2,208, 0, 0,
+ 0, 1, 2, 54, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2, 54, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,122, 0, 0, 0, 1,
+ 2,118, 0, 0, 0, 1, 2,122, 0, 0, 0, 1, 2,118, 0, 0, 0, 1, 2,122, 0, 0, 0, 1, 2,118, 0, 0, 0, 1, 2,122,
+ 0, 0, 0, 1, 2,118, 0, 0, 0, 1, 2,154, 0, 0, 0, 1, 2,104,254, 86, 0, 1, 2,154, 0, 0, 0, 1, 2,104,254, 86,
+ 0, 1, 2,154, 0, 0, 0, 1, 2,104,254, 86, 0, 1, 2,104,254, 86, 0, 1, 3,226, 0, 0, 0, 1, 3,190, 0, 0, 0, 1,
+ 3,226, 0, 0, 0, 1, 3,190, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,154, 0, 0,
+ 0, 1, 1,185,254, 89, 0, 1, 4, 68, 0, 0, 0, 1, 2,154, 0, 0, 0, 1, 3,120, 0, 0, 0, 1, 2,154, 0, 0, 0, 1,
+ 3,120, 0, 0, 0, 1, 2,154, 0, 0, 0, 1, 3,120, 0, 0, 0, 1, 2,154, 0, 0, 0, 1, 3,120, 0, 0, 0, 1, 3,228,
+ 0, 0, 0, 1, 3,190, 0, 0, 0, 1, 3,228, 0, 0, 0, 1, 3,190, 0, 0, 0, 1, 4, 57, 0, 0, 0, 1, 2,104,254, 86,
+ 0, 1, 2,104,254, 86, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 4, 68, 0, 0, 0, 1, 1,198, 0, 0, 0, 1, 4, 68, 0, 0, 0, 1, 1,198,
+ 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 3,120, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 3,120, 0, 0, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 3,147, 0, 0,
+ 0, 1, 3,115, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 1, 26,254, 86, 0, 1, 2,104, 0, 0, 0, 1, 2,154, 0, 0, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,154, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,154, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104, 0, 0, 0, 1, 2, 10, 0, 0, 0, 1, 2,179, 0, 0, 0, 1, 2,208, 0, 0, 0, 1, 2, 54, 0, 0, 0, 1,
+ 2, 54, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104,254, 86, 0, 1, 2, 86, 0, 0, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,179, 0, 0, 0, 1, 1, 34,254, 86, 0, 1, 1,104,254, 86, 0, 1, 2,154, 0, 0, 0, 1, 2,104,254, 86,
+ 0, 1, 3,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 4, 68, 0, 0, 0, 1, 4, 68, 0, 0, 0, 1,
+ 3,120, 0, 0, 0, 1, 4, 8, 0, 0, 0, 1, 4, 28, 0, 0, 0, 1, 3,228, 0, 0, 0, 1, 3,190,254, 86, 0, 1, 2,104,
+ 0, 0, 0, 1, 1,249, 0, 0, 0, 1, 1,255, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 4, 88,254, 86, 0, 1, 1,210, 0, 0,
+ 0, 1, 1, 26,254, 86, 0, 1, 4,106,254,248, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 2,
+ 0, 22, 0, 36, 0, 61, 0, 0, 0, 68, 0, 93, 0, 26, 0,130, 0,135, 0, 52, 0,138, 0,152, 0, 58, 0,154, 0,167, 0, 73,
+ 0,170, 0,184, 0, 87, 0,186, 0,194, 0,102, 0,196, 0,197, 0,111, 0,200, 0,200, 0,113, 0,202, 0,217, 0,114, 0,220,
+ 0,227, 0,130, 0,229, 0,239, 0,138, 0,242, 0,243, 0,149, 0,246, 0,247, 0,151, 0,250, 0,252, 0,153, 0,255, 1, 6,
+ 0,156, 1, 9, 1, 19, 0,164, 1, 22, 1, 23, 0,175, 1, 26, 1, 31, 0,177, 1, 34, 1, 35, 0,183, 1, 38, 1, 51, 0,185,
+ 1, 54, 1,107, 0,199, 0, 1, 0, 1, 2,163, 0, 1, 0, 0, 0, 6, 0, 1, 2,124, 0, 0, 0, 1, 20,168, 20, 38, 0, 2,
+ 20,214, 0, 12, 1,127, 5,254, 6, 4, 6, 10, 6, 16, 6, 22, 6, 28, 6, 34, 6, 40, 6, 46, 6, 52, 6, 58, 6, 64, 6, 70,
+ 6, 76, 6, 82, 6, 88, 6, 94, 6,100, 6,106, 6,112, 6,118, 6,124, 6,130, 6,136, 6,142, 6,148, 6,154, 6,160, 6,166,
+ 6,172, 6,178, 6,184, 6,190, 6,196, 6,202, 6,208, 6,214, 6,220, 6,226, 6,232, 6,238, 6,244, 6,250, 7, 0, 7, 6,
+ 7, 12, 7, 18, 7, 24, 7, 30, 7, 36, 7, 42, 7, 48, 7, 54, 7, 60, 7, 66, 7, 72, 7, 78, 7, 84, 7, 90, 7, 96, 7,102,
+ 7,108, 7,114, 7,120, 7,126, 7,132, 7,138, 7,144, 0, 0, 7,150, 0, 0, 7,156, 7,162, 7,168, 7,174, 7,180, 7,186,
+ 7,192, 7,198, 7,204, 7,210, 7,216, 7,222, 7,228, 7,234, 7,240, 7,246, 7,252, 8, 2, 8, 8, 8, 14, 8, 20, 8, 26,
+ 8, 32, 8, 38, 8, 44, 8, 50, 8, 56, 8, 62, 8, 68, 8, 74, 8, 80, 8, 86, 8, 92, 0, 0, 8, 98, 0, 0, 8,104, 0, 0,
+ 8,110, 0, 0, 8,116, 0, 0, 8,122, 0, 0, 8,128, 8,134, 8,140, 8,146, 0, 0, 0, 0, 8,152, 0, 0, 8,158, 0, 0,
+ 8,164, 0, 0, 8,170, 0, 0, 8,176, 0, 0, 8,182, 0, 0, 8,188, 0, 0, 8,194, 8,200, 8,206, 0, 0, 8,212, 0, 0,
+ 8,218, 0, 0, 8,224, 0, 0, 8,230, 0, 0, 8,236, 0, 0, 8,242, 8,248, 8,254, 0, 0, 9, 4, 0, 0, 9, 10, 0, 0,
+ 9, 16, 0, 0, 9, 22, 0, 0, 9, 28, 9, 34, 9, 40, 9, 46, 9, 52, 0, 0, 9, 58, 0, 0, 9, 64, 0, 0, 9, 70, 0, 0,
+ 9, 76, 0, 0, 9, 82, 0, 0, 9, 88, 9, 94, 9,100, 9,106, 0, 0, 0, 0, 9,112, 0, 0, 9,118, 0, 0, 9,124, 0, 0,
+ 9,130, 0, 0, 9,136, 0, 0, 9,142, 0, 0, 9,148, 0, 0, 9,154, 0, 0, 9,160, 0, 0, 9,166, 0, 0, 9,172, 0, 0,
+ 9,178, 0, 0, 9,184, 0, 0, 9,190, 0, 0, 9,196, 9,202, 9,208, 0, 0, 9,214, 0, 0, 9,220, 0, 0, 9,226, 0, 0,
+ 9,232, 0, 0, 9,238, 9,244, 9,250, 0, 0, 10, 0, 0, 0, 10, 6, 0, 0, 10, 12, 0, 0, 10, 18, 10, 24, 0, 0, 10, 30,
+ 0, 0, 0, 0, 10, 36, 0, 0, 10, 42, 0, 0, 10, 48, 0, 0, 10, 54, 0, 0, 10, 60, 0, 0, 10, 66, 0, 0, 10, 72, 0, 0,
+ 10, 78, 0, 0, 10, 84, 10, 90, 10, 96, 10,102, 10,108, 0, 0, 10,114, 0, 0, 10,120, 0, 0, 10,126, 0, 0, 10,132, 0, 0,
+ 10,138, 0, 0, 10,144, 10,150, 0, 0, 10,156, 0, 0, 0, 0, 10,162, 0, 0, 10,168, 0, 0, 10,174, 0, 0, 10,180, 0, 0,
+ 10,186, 0, 0, 10,192, 0, 0, 10,198, 0, 0, 10,204, 10,210, 0, 0, 0, 0, 10,216, 0, 0, 10,222, 0, 0, 10,228, 10,234,
+ 10,240, 10,246, 10,252, 0, 0, 11, 2, 0, 0, 11, 8, 0, 0, 11, 14, 0, 0, 11, 20, 0, 0, 11, 26, 0, 0, 11, 32, 11, 38,
+ 0, 0, 0, 0, 11, 44, 11, 50, 11, 56, 0, 0, 11, 62, 0, 0, 11, 68, 11, 74, 0, 0, 11, 80, 0, 0, 11, 86, 11, 92, 0, 0,
+ 11, 98, 0, 0, 11,104, 11,110, 0, 0, 11,116, 0, 0, 0, 0, 11,122, 0, 0, 11,128, 11,134, 11,140, 11,146, 11,152, 11,158,
+ 11,164, 11,170, 11,176, 0, 0, 11,182, 0, 0, 11,188, 11,194, 0, 0, 11,200, 0, 0, 0, 0, 11,206, 0, 0, 11,212, 0, 0,
+ 11,218, 11,224, 11,230, 11,236, 11,242, 0, 0, 11,248, 0, 0, 11,254, 0, 0, 12, 4, 0, 0, 12, 10, 0, 0, 12, 16, 0, 0,
+ 12, 22, 12, 28, 12, 34, 12, 40, 12, 46, 0, 0, 12, 52, 0, 0, 12, 58, 12, 64, 0, 0, 12, 70, 0, 0, 0, 0, 12, 76, 12, 82,
+ 12, 88, 0, 0, 12, 94, 0, 0, 12,100, 0, 0, 12,106, 0, 0, 12,112, 12,118, 0, 0, 12,124, 0, 0, 0, 0, 12,130, 0, 0,
+ 12,136, 12,142, 0, 0, 12,148, 0, 0, 0, 0, 12,154, 0, 0, 12,160, 12,166, 12,172, 12,178, 12,184, 0, 0, 12,190, 0, 0,
+ 12,196, 0, 0, 12,202, 0, 0, 12,208, 0, 0, 12,214, 0, 0, 12,220, 0, 0, 12,226, 0, 0, 12,232, 0, 0, 12,238, 0, 0,
+ 12,244, 12,250, 0, 0, 13, 0, 0, 0, 0, 0, 13, 6, 0, 0, 13, 12, 0, 0, 13, 18, 0, 0, 13, 24, 0, 0, 13, 30, 0, 0,
+ 13, 36, 0, 0, 13, 42, 0, 0, 13, 48, 0, 0, 13, 54, 0, 0, 13, 60, 0, 0, 13, 66, 13, 72, 13, 78, 13, 84, 13, 90, 13, 96,
+ 13,102, 13,108, 13,114, 13,120, 13,126, 13,132, 13,138, 13,144, 13,150, 13,156, 13,162, 13,168, 13,174, 13,180, 13,186, 13,192,
+ 13,198, 13,204, 13,210, 13,216, 13,222, 13,228, 13,234, 13,240, 13,246, 13,252, 14, 2, 14, 8, 14, 14, 14, 20, 14, 26, 14, 32,
+ 14, 38, 14, 44, 14, 50, 14, 56, 14, 62, 14, 68, 14, 74, 14, 80, 14, 86, 14, 92, 14, 98, 14,104, 14,110, 14,116, 14,122, 14,128,
+ 14,134, 14,140, 14,146, 14,152, 14,158, 14,164, 14,170, 14,176, 14,182, 14,188, 14,194, 14,200, 14,206, 14,212, 14,218, 14,224,
+ 14,230, 14,236, 14,242, 14,248, 14,254, 15, 4, 15, 10, 15, 16, 15, 22, 15, 28, 15, 34, 15, 40, 15, 46, 15, 52, 15, 58, 15, 64,
+ 15, 70, 15, 76, 15, 82, 15, 88, 15, 94, 15,100, 15,106, 15,112, 15,118, 15,124, 15,130, 15,136, 15,142, 15,148, 15,154, 15,160,
+ 15,166, 15,172, 15,178, 15,184, 15,190, 15,196, 15,202, 15,208, 15,214, 15,220, 15,226, 15,232, 15,238, 15,244, 15,250, 16, 0,
+ 16, 6, 16, 12, 16, 18, 16, 24, 16, 30, 16, 36, 16, 42, 16, 48, 16, 54, 16, 60, 16, 66, 16, 72, 16, 78, 16, 84, 16, 90, 16, 96,
+ 16,102, 16,108, 16,114, 16,120, 16,126, 16,132, 16,138, 16,144, 16,150, 16,156, 16,162, 16,168, 16,174, 16,180, 16,186, 16,192,
+ 16,198, 16,204, 16,210, 16,216, 16,222, 16,228, 16,234, 16,240, 16,246, 16,252, 17, 2, 17, 8, 17, 14, 17, 20, 17, 26, 17, 32,
+ 17, 38, 17, 44, 17, 50, 17, 56, 17, 62, 17, 68, 17, 74, 17, 80, 17, 86, 17, 92, 17, 98, 17,104, 17,110, 17,116, 17,122, 17,128,
+ 17,134, 17,140, 17,146, 17,152, 17,158, 17,164, 17,170, 17,176, 17,182, 17,188, 17,194, 17,200, 17,206, 17,212, 17,218, 17,224,
+ 17,230, 17,236, 17,242, 17,248, 17,254, 18, 4, 18, 10, 18, 16, 18, 22, 18, 28, 18, 34, 18, 40, 18, 46, 18, 52, 18, 58, 18, 64,
+ 18, 70, 18, 76, 18, 82, 18, 88, 18, 94, 18,100, 18,106, 18,112, 18,118, 18,124, 18,130, 18,136, 18,142, 18,148, 18,154, 18,160,
+ 18,166, 18,172, 18,178, 18,184, 18,190, 18,196, 18,202, 18,208, 18,214, 18,220, 18,226, 18,232, 18,238, 18,244, 18,250, 19, 0,
+ 19, 6, 19, 12, 19, 18, 19, 24, 19, 30, 19, 36, 19, 42, 19, 48, 19, 54, 19, 60, 19, 66, 19, 72, 19, 78, 19, 84, 19, 90, 19, 96,
+ 19,102, 19,108, 19,114, 19,120, 19,126, 19,132, 19,138, 19,144, 19,150, 19,156, 19,162, 19,168, 19,174, 19,180, 19,186, 19,192,
+ 19,198, 19,204, 19,210, 19,216, 19,222, 19,228, 19,234, 19,240, 19,246, 19,252, 20, 2, 20, 8, 0, 0, 0, 0, 20, 14, 20, 20,
+ 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,179, 5,213,
+ 0, 1, 2,179, 0, 0, 0, 1, 2, 54, 5,213, 0, 1, 2, 54, 0, 0, 0, 1, 2,122, 5,213, 0, 1, 2,122, 0, 0, 0, 1,
+ 2,158, 5,213, 0, 1, 2,158, 0, 0, 0, 1, 2,154, 5,213, 0, 1, 2,154, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,154, 5,213, 0, 1, 2,154, 0, 0, 0, 1, 2,104, 5,213,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,154, 5,213, 0, 1, 2,154, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1,
+ 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2, 54, 5,213, 0, 1, 2, 54, 0, 0, 0, 1, 2,104, 5,213,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1,
+ 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,154, 5,213, 0, 1, 2,154, 0, 0, 0, 1, 2,104, 4, 96,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,104, 6, 20, 0, 1, 2,104, 0, 0, 0, 1, 2,179, 4, 96, 0, 1, 2,179, 0, 0, 0, 1,
+ 2,104, 6, 20, 0, 1, 2,104, 0, 0, 0, 1, 2,118, 4, 96, 0, 1, 2,118, 0, 0, 0, 1, 2,104, 6, 20, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86, 0, 1, 2,104, 6, 20, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104,254, 86, 0, 1, 2,154, 6, 20, 0, 1, 2,154, 0, 0, 0, 1, 2, 50, 6, 20, 0, 1, 2, 50, 0, 0, 0, 1,
+ 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86, 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86, 0, 1, 2,104, 4, 96,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 6, 20, 0, 1, 2,104, 0, 0, 0, 1,
+ 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86, 0, 1, 2,104, 4, 96,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,122, 5,213, 0, 1, 2,122, 0, 0, 0, 1, 2,179, 5,213, 0, 1, 2,122,
+ 0, 0, 0, 1, 2,122, 0, 0, 0, 1, 2,122, 0, 0, 0, 1, 2,122, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2, 54, 5,213, 0, 1, 2, 54, 0, 0, 0, 1, 2,104, 0, 0, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104,
+ 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104, 0, 0, 0, 1, 2, 54, 5,213, 0, 1, 2, 54, 0, 0, 0, 1, 2, 54, 5,213, 0, 1, 2, 54, 0, 0, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,179, 4, 96, 0, 1, 2,118, 0, 0, 0, 1, 2,118, 0, 0,
+ 0, 1, 2,118, 0, 0, 0, 1, 2,118, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104,254, 86, 0, 1, 2,104, 6, 20, 0, 1,
+ 2,104,254, 86, 0, 1, 2,104,254, 86, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104,
+ 5,213, 0, 1, 2,104, 4, 96, 0, 1, 2,179, 0, 0, 0, 1, 2,179, 0, 0, 0, 1, 2,179, 0, 0, 0, 1, 2,179, 0, 0,
+ 0, 1, 2,179, 0, 0, 0, 1, 2,179, 0, 0, 0, 1, 2,179, 0, 0, 0, 1, 2, 54, 0, 0, 0, 1, 2,104, 0, 0, 0, 1,
+ 2, 54, 5,213, 0, 1, 2, 54, 0, 0, 0, 1, 2,104, 6, 20, 0, 1, 2,104, 0, 0, 0, 1, 2,122, 0, 0, 0, 1, 2,118,
+ 0, 0, 0, 1, 2,122, 0, 0, 0, 1, 2,118, 0, 0, 0, 1, 2,122, 0, 0, 0, 1, 2,118, 0, 0, 0, 1, 2,122, 5,213,
+ 0, 1, 2,118, 4, 96, 0, 1, 2,122, 0, 0, 0, 1, 2,118, 0, 0, 0, 1, 2,154, 0, 0, 0, 1, 2,104,254, 86, 0, 1,
+ 2,154, 0, 0, 0, 1, 2,104,254, 86, 0, 1, 2,154, 0, 0, 0, 1, 2,104,254, 86, 0, 1, 2,154, 5,213, 0, 1, 2,104,
+254, 86, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 6, 20,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,154, 0, 0, 0, 1, 2,104,254, 86, 0, 1, 2,104, 5,213, 0, 1, 2,154, 6, 20, 0, 1, 2,154, 4, 96,
+ 0, 1, 2,154, 0, 0, 0, 1, 2,154, 0, 0, 0, 1, 2, 50, 0, 0, 0, 1, 2,154, 5,213, 0, 1, 2, 50, 6, 20, 0, 1,
+ 2,154, 0, 0, 0, 1, 2, 50, 0, 0, 0, 1, 2,154, 5,213, 0, 1, 2,154, 0, 0, 0, 1, 2, 50, 6, 20, 0, 1, 2, 50,
+ 0, 0, 0, 1, 2,154, 5,213, 0, 1, 2,154, 0, 0, 0, 1, 2, 50, 6, 20, 0, 1, 2, 50, 0, 0, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1,
+ 2,227, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104,254, 86, 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2, 54, 0, 0, 0, 1,
+ 2,104, 0, 0, 0, 1, 2, 54, 5,213, 0, 1, 2,104, 4, 96, 0, 1, 2, 54, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213,
+ 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 6, 20, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 6, 20, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1,
+ 2,104, 5,213, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104,
+254, 86, 0, 1, 2,104, 0, 0, 0, 1, 2,154, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,154, 0, 0, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,154, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 6, 20, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 6, 20, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104,
+ 6, 20, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 6, 20, 0, 1, 2,104, 0, 0,
+ 0, 1, 2, 10, 5,213, 0, 1, 2, 10, 0, 0, 0, 1, 2,179, 5,213, 0, 1, 2,179, 0, 0, 0, 1, 2,179, 4, 96, 0, 1,
+ 2,179, 0, 0, 0, 1, 2, 54, 5,213, 0, 1, 2, 54, 0, 0, 0, 1, 2, 54, 5,213, 0, 1, 2, 54, 0, 0, 0, 1, 2,104,
+ 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 6, 20, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86,
+ 0, 1, 2, 86, 5,213, 0, 1, 2, 86, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,179, 5,213, 0, 1,
+ 2,179, 0, 0, 0, 1, 3, 2, 5,213, 0, 1, 3, 2,254, 86, 0, 1, 2,104, 6, 20, 0, 1, 2,104,254, 86, 0, 1, 2,154,
+ 5,213, 0, 1, 2,154, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104,254, 86, 0, 1, 2,104, 6, 20, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,154, 6, 20, 0, 1, 2,154, 0, 0, 0, 1, 2, 50, 6, 20, 0, 1, 2, 50, 0, 0, 0, 1, 2,104,
+ 6, 20, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104,254, 86,
+ 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 1,249, 5,213, 0, 1,
+ 1,249, 0, 0, 0, 1, 1,255, 4, 96, 0, 1, 1,255, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104,
+ 4, 96, 0, 1, 2,104,254, 86, 0, 1, 2,236, 5,213, 0, 1, 2,236, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86,
+ 0, 1, 2, 54, 5,213, 0, 1, 2, 54,254, 86, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 5,213, 0, 1, 2,104, 0, 0, 0, 1, 2,104,
+ 4, 96, 0, 1, 2,104,254, 86, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,140, 6, 20, 0, 1, 2,140, 0, 0, 0, 1, 2, 41, 4, 96, 0, 1,
+ 2, 41, 0, 0, 0, 1, 2,179, 4, 96, 0, 1, 2,179, 0, 0, 0, 1, 2, 89, 6, 20, 0, 1, 2, 89, 0, 0, 0, 1, 2,104,
+ 6, 20, 0, 1, 2,104, 0, 0, 0, 1, 2,118, 4, 96, 0, 1, 2,118, 0, 0, 0, 1, 2,118, 4, 96, 0, 1, 2,118, 0, 0,
+ 0, 1, 1,154, 4, 96, 0, 1, 1,154, 0, 0, 0, 1, 2,118, 4, 96, 0, 1, 2,118, 0, 0, 0, 1, 2, 90, 4, 96, 0, 1,
+ 2, 90, 0, 0, 0, 1, 1,114, 4, 96, 0, 1, 1,114, 0, 0, 0, 1, 2,118, 4, 96, 0, 1, 2,118, 0, 0, 0, 1, 2,177,
+ 4, 96, 0, 1, 2,177,254, 86, 0, 1, 2, 62, 6, 20, 0, 1, 2, 62,254, 86, 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86,
+ 0, 1, 2,149, 4, 96, 0, 1, 2,149, 0, 0, 0, 1, 2,110, 4, 96, 0, 1, 2,110,254, 86, 0, 1, 2,104, 4, 96, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86, 0, 1, 2,111, 6, 20, 0, 1, 2,111, 0, 0, 0, 1, 2,111,
+ 6, 20, 0, 1, 2,111,254, 86, 0, 1, 2, 68, 4, 96, 0, 1, 2, 68, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0,
+ 0, 1, 2, 56, 6, 20, 0, 1, 2, 56, 0, 0, 0, 1, 2, 80, 6, 20, 0, 1, 2, 80, 0, 0, 0, 1, 2, 62, 6, 20, 0, 1,
+ 2, 62,254, 86, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86, 0, 1, 2,104,
+ 4, 96, 0, 1, 2,104,254, 86, 0, 1, 2,182, 4, 96, 0, 1, 2,182,254, 86, 0, 1, 1,252, 4,102, 0, 1, 2, 38,254, 86,
+ 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 6, 20, 0, 1, 2,104,254, 86, 0, 1, 2,104,
+ 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 6, 20, 0, 1, 2,104, 0, 0, 0, 1, 2, 54, 4, 96, 0, 1, 2, 54,254, 86,
+ 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86, 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86, 0, 1, 2, 99, 4, 96, 0, 1,
+ 2, 99, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2, 0, 4, 96, 0, 1, 2, 0, 0, 0, 0, 1, 2, 0,
+ 4, 96, 0, 1, 2, 0, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86, 0, 1, 2,115, 6, 20, 0, 1, 2,115,254, 86,
+ 0, 1, 2,115, 6, 20, 0, 1, 2,115,254, 86, 0, 1, 2,120, 4, 96, 0, 1, 2,120,254, 86, 0, 1, 2,115, 6, 20, 0, 1,
+ 2,115,254, 86, 0, 1, 2,164, 4, 96, 0, 1, 2,164,254, 86, 0, 1, 2,104, 6, 20, 0, 1, 2,104,254, 86, 0, 1, 2,104,
+ 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 6, 20, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2, 28, 4, 96, 0, 1, 2, 28,254, 86, 0, 1, 2,104,
+ 4, 96, 0, 1, 2,104,255,142, 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86, 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86,
+ 0, 1, 2, 36, 6, 20, 0, 1, 2, 36, 0, 0, 0, 1, 2,170, 6, 20, 0, 1, 2,170, 0, 0, 0, 1, 2, 36, 6, 20, 0, 1,
+ 2, 36, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2, 32, 4, 96, 0, 1, 2, 32, 0, 0, 0, 1, 2, 62,
+ 4, 96, 0, 1, 2, 62, 0, 0, 0, 1, 2, 26, 6, 20, 0, 1, 2, 26, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104, 4, 96, 0, 1, 2,104,254, 86, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 6, 20, 0, 1,
+ 2,104,254, 86, 0, 1, 2, 36, 6, 20, 0, 1, 2, 36, 0, 0, 0, 1, 2,170, 6, 20, 0, 1, 2,170, 0, 0, 0, 1, 2,104,
+ 5,224, 0, 1, 2,104, 2,156, 0, 1, 2, 82, 5,224, 0, 1, 2, 82, 2,156, 0, 1, 2, 69, 5,224, 0, 1, 2, 69, 2,156,
+ 0, 1, 2, 94, 5,224, 0, 1, 2, 94, 2,156, 0, 1, 2,114, 5,224, 0, 1, 2,114, 2,156, 0, 1, 2,144, 5,224, 0, 1,
+ 2,144, 2,156, 0, 1, 2,104, 5,224, 0, 1, 2,104, 2,156, 0, 1, 2,104, 5,224, 0, 1, 2,104, 2,156, 0, 1, 2,188,
+ 5,224, 0, 1, 2,188, 2,156, 0, 1, 2, 63, 5,224, 0, 1, 2, 63, 2,156, 0, 1, 2, 97, 5,224, 0, 1, 2, 97, 2,156,
+ 0, 1, 2,105, 5,224, 0, 1, 2,105, 2,156, 0, 1, 2,104, 5,224, 0, 1, 2,104, 2,156, 0, 1, 2,104, 5,224, 0, 1,
+ 2,104, 2,156, 0, 1, 2,104, 5,224, 0, 1, 2,104, 2,156, 0, 1, 2, 71, 5,224, 0, 1, 2, 71, 2,156, 0, 1, 2, 27,
+ 5,224, 0, 1, 2, 27, 2,156, 0, 1, 2,104, 5,224, 0, 1, 2,104, 2,156, 0, 1, 2,104, 5,224, 0, 1, 2,104, 2,156,
+ 0, 1, 2,104, 5,224, 0, 1, 2,104, 2,156, 0, 1, 2, 54, 5,213, 0, 1, 2, 92, 2,156, 0, 1, 2,104, 5,213, 0, 2,
+ 0, 21, 0, 36, 0, 61, 0, 0, 0, 68, 0, 93, 0, 26, 0,130, 0,152, 0, 52, 0,154, 0,184, 0, 75, 0,186, 0,194, 0,106,
+ 0,196, 0,200, 0,115, 0,202, 0,240, 0,120, 0,242, 0,243, 0,159, 0,246, 1,107, 0,161, 1,205, 1,205, 1, 23, 1,226,
+ 1,226, 1, 24, 1,238, 2, 5, 1, 25, 2, 7, 2, 11, 1, 49, 2, 13, 2, 52, 1, 54, 2, 54, 2, 58, 1, 94, 2, 60, 2, 64,
+ 1, 99, 4,172, 4,172, 1,104, 4,174, 4,192, 1,105, 5, 22, 5, 22, 1,124, 6,169, 6,169, 1,125, 11,209, 11,209, 1,126,
+ 0, 2, 0, 7, 2,124, 2,141, 0, 0, 2,143, 2,149, 0, 18, 2,152, 2,156, 0, 25, 2,159, 2,162, 0, 30, 2,165, 2,173,
+ 0, 34, 2,181, 2,186, 0, 43, 2,188, 2,188, 0, 49, 0, 50, 0, 0, 0,202, 0, 0, 0,208, 0, 0, 0,214, 0, 0, 0,220,
+ 0, 0, 0,226, 0, 0, 0,232, 0, 0, 0,238, 0, 0, 0,244, 0, 0, 0,250, 0, 0, 1, 0, 0, 0, 1, 6, 0, 0, 1, 12,
+ 0, 0, 1, 18, 0, 0, 1, 24, 0, 0, 1, 30, 0, 0, 1, 36, 0, 0, 1, 42, 0, 0, 1, 48, 0, 0, 1, 54, 0, 0, 1, 60,
+ 0, 0, 1, 66, 0, 1, 1, 72, 0, 1, 1, 78, 0, 1, 1, 84, 0, 1, 1, 90, 0, 1, 1, 96, 0, 1, 1,102, 0, 1, 1,108,
+ 0, 1, 1,114, 0, 1, 1,120, 0, 1, 1,126, 0, 1, 1,132, 0, 1, 1,138, 0, 1, 1,144, 0, 1, 1,150, 0, 1, 1,156,
+ 0, 1, 1,162, 0, 1, 1,168, 0, 1, 1,174, 0, 1, 1,180, 0, 1, 1,186, 0, 1, 1,192, 0, 1, 1,198, 0, 1, 1,204,
+ 0, 1, 1,210, 0, 1, 1,216, 0, 1, 1,222, 0, 0, 1,228, 0, 0, 1,234, 0, 0, 1,240, 0, 1, 2,104, 4, 96, 0, 1,
+ 2,104, 4, 96, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 4, 96, 0, 1, 2,104,
+ 4, 96, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 4, 96,
+ 0, 1, 2,104, 4, 96, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 4, 96, 0, 1,
+ 2,104, 4, 96, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 0, 0, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1,
+ 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104,
+ 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0,
+ 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 0, 0, 0, 1, 2,104, 4, 96, 0, 1, 2,104, 4, 96, 0, 1,
+ 2,104, 4, 96, 0, 1, 0, 8, 0, 4,251, 47, 0, 2, 0, 6, 2,124, 2,141, 0, 0, 2,143, 2,149, 0, 18, 2,152, 2,156,
+ 0, 25, 2,159, 2,173, 0, 30, 2,181, 2,186, 0, 45, 2,188, 2,188, 0, 51, 0, 1, 1,200, 1,190, 0, 2, 1,216, 0, 12,
+ 0, 27, 0,110, 0,116, 0,122, 0,128, 0,134, 0,140, 0,146, 0,152, 0,158, 0,164, 0,170, 0,176, 0,182, 0,188, 0,194,
+ 0,200, 0,206, 0,212, 0,218, 0,224, 0,230, 0,236, 0,242, 0,248, 0,254, 1, 4, 1, 10, 1, 16, 1, 22, 1, 28, 1, 34,
+ 1, 40, 1, 46, 1, 52, 1, 58, 1, 64, 1, 70, 1, 76, 1, 82, 1, 88, 1, 94, 1,100, 1,106, 1,112, 1,118, 1,124, 1,130,
+ 1,136, 1,142, 1,148, 1,154, 1,160, 1,166, 1,172, 0, 1, 4,209, 0, 0, 0, 1, 4,209, 4,160, 0, 1, 4,209, 0, 0,
+ 0, 1, 4,209, 4,160, 0, 1, 4,209, 0, 0, 0, 1, 4,209, 4,160, 0, 1, 4,209,254, 20, 0, 1, 4,209, 4,160, 0, 1,
+ 4,209, 0, 0, 0, 1, 4,209, 4,160, 0, 1, 4,209,254, 20, 0, 1, 4,209, 4,160, 0, 1, 4,209, 0, 0, 0, 1, 4,209,
+ 4,160, 0, 1, 4,209, 0, 0, 0, 1, 4,209, 4,160, 0, 1, 4,209, 0, 0, 0, 1, 4,209, 4,160, 0, 1, 4,209,254, 20,
+ 0, 1, 4,209, 4,160, 0, 1, 4,209, 0, 0, 0, 1, 4,209, 4,160, 0, 1, 4,209, 0, 0, 0, 1, 4,209, 4,160, 0, 1,
+ 4,209, 0, 0, 0, 1, 4,209, 4,160, 0, 1, 4,209, 0, 0, 0, 1, 4,210, 6, 16, 0, 1, 4,209, 0, 0, 0, 1, 4,209,
+ 4,160, 0, 1, 4,209, 0, 0, 0, 1, 4,210, 6, 16, 0, 1, 4,209, 0, 0, 0, 1, 4,209, 4,160, 0, 1, 4,209, 0, 0,
+ 0, 1, 4,210, 6, 16, 0, 1, 4,209, 0, 0, 0, 1, 4,209, 4,160, 0, 1, 4,209, 0, 0, 0, 1, 4,209, 6, 16, 0, 1,
+ 4,209, 0, 0, 0, 1, 4,209, 4,160, 0, 1, 4,209, 0, 0, 0, 1, 4,209, 4,160, 0, 1, 4,209, 0, 0, 0, 1, 4,209,
+ 4,160, 0, 1, 4,209, 0, 0, 0, 1, 4,209, 4,160, 0, 1, 4,209, 0, 0, 0, 1, 4,209, 4,160, 0, 1, 4,209, 0, 0,
+ 0, 1, 4,209, 4,160, 0, 1, 4,209, 0, 0, 0, 1, 4,209, 4,160, 0, 2, 0, 1, 4, 72, 4, 98, 0, 0, 0, 2, 0, 2,
+ 4,101, 4,101, 0, 0, 4,104, 4,117, 0, 1, 0, 15, 0, 1, 0, 62, 0, 1, 0, 68, 0, 1, 0, 74, 0, 1, 0, 80, 0, 1,
+ 0, 86, 0, 0, 0, 92, 0, 0, 0, 98, 0, 1, 0,104, 0, 0, 0,110, 0, 1, 0,116, 0, 1, 0,122, 0, 1, 0,128, 0, 1,
+ 0,134, 0, 1, 0,140, 0, 1, 0,146, 0, 1,255,247, 4,116, 0, 1, 4,209, 4,119, 0, 1, 4,209, 4,119, 0, 1, 4,209,
+ 4,119, 0, 1, 4,209, 4,119, 0, 1, 4,209, 0, 0, 0, 1, 4,209, 0, 0, 0, 1, 4,209, 4,116, 0, 1, 4,209, 0, 0,
+ 0, 1, 4,209, 4, 96, 0, 1, 4,209, 4,126, 0, 1, 4,209, 4,126, 0, 1, 4,209, 4, 96, 0, 1, 4,209, 4,126, 0, 1,
+ 4,209, 4, 96, 0, 1, 0, 8, 0, 4,251, 47, 0, 2, 0, 2, 4,101, 4,101, 0, 0, 4,104, 4,117, 0, 1, 0, 1, 0, 0,
+ 0, 10, 0,192, 1, 58, 0, 6, 97,114, 97, 98, 0, 38, 99,121,114,108, 0, 60,100,102,108,116, 0, 88,103,114,101,107, 0, 98,
+108, 97,111, 32, 0,110,108, 97,116,110, 0,120, 0, 4, 0, 0, 0, 0,255,255, 0, 6, 0, 2, 0, 3, 0, 4, 0, 5, 0, 8,
+ 0, 9, 0, 10, 0, 1, 83, 82, 66, 32, 0, 18, 0, 0,255,255, 0, 1, 0, 0, 0, 0,255,255, 0, 2, 0, 0, 0, 6, 0, 4,
+ 0, 0, 0, 0,255,255, 0, 0, 0, 4, 0, 0, 0, 0,255,255, 0, 1, 0, 0, 0, 4, 0, 0, 0, 0,255,255, 0, 0, 0, 40,
+ 0, 6, 73, 83, 77, 32, 0, 50, 75, 83, 77, 32, 0, 50, 76, 83, 77, 32, 0, 50, 78, 83, 77, 32, 0, 50, 83, 75, 83, 32, 0, 50,
+ 83, 83, 77, 32, 0, 50, 0, 0,255,255, 0, 2, 0, 0, 0, 1, 0, 0,255,255, 0, 3, 0, 0, 0, 1, 0, 7, 0, 10, 99, 99,
+109,112, 0, 62,100,108,105,103, 0, 68,102,105,110, 97, 0, 74,105,110,105,116, 0, 80,105,115,111,108, 0, 86,108,105,103, 97,
+ 0, 92,108,111, 99,108, 0, 98,108,111, 99,108, 0,104,109,101,100,105, 0,110,114,108,105,103, 0,116, 0, 0, 0, 1, 0, 1,
+ 0, 0, 0, 1, 0, 9, 0, 0, 0, 1, 0, 4, 0, 0, 0, 1, 0, 6, 0, 0, 0, 1, 0, 3, 0, 0, 0, 1, 0, 8, 0, 0,
+ 0, 1, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 1, 0, 7, 0, 11, 0, 24, 0, 32, 0, 40, 0, 48,
+ 0, 56, 0, 64, 0, 72, 0, 80, 0, 88, 0, 96, 0,104, 0, 1, 0, 0, 0, 1, 0, 88, 0, 6, 0, 0, 0, 1, 0, 92, 0, 1,
+ 0, 0, 0, 1, 0,228, 0, 1, 0, 9, 0, 1, 0,232, 0, 1, 0, 9, 0, 1, 0,236, 0, 1, 0, 9, 0, 1, 1,148, 0, 1,
+ 0, 9, 0, 1, 2, 46, 0, 4, 0, 9, 0, 1, 2,200, 0, 4, 0, 9, 0, 1, 2,230, 0, 4, 0, 0, 0, 1, 3, 36, 0, 1,
+ 0, 0, 0, 1, 3, 60, 0, 1, 0, 6, 10,197, 0, 1, 0, 1, 1, 12, 0, 2, 0, 20, 0, 28, 0, 36, 0, 36, 0, 4, 0, 0,
+ 0, 88, 0, 0, 0, 0, 0, 1, 0, 2, 0, 76, 0, 77, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 8, 0, 76, 0, 77, 0, 1,
+ 2,124, 2,145, 0, 2, 2,146, 2,149, 0, 3, 2,152, 2,156, 0, 3, 2,159, 2,175, 0, 3, 2,181, 2,184, 0, 3, 2,185,
+ 2,188, 0, 2, 2,191, 2,191, 0, 2, 0, 3, 0, 8, 0, 22, 0, 38, 0, 0, 0, 1, 0, 1, 0, 2, 0, 1, 0, 0, 0, 10,
+ 0, 0, 0, 1, 0, 2, 0, 3, 0, 2, 0, 1, 0, 0, 0, 10, 0, 0, 0, 1, 0, 3, 0, 3, 0, 3, 0, 2, 0, 1, 0, 0,
+ 0, 10, 0, 1, 0, 6, 7, 54, 0, 1, 0, 1, 3, 94, 0, 1, 0, 6, 6,149, 0, 1, 0, 1, 4, 50, 0, 2, 0,112, 0, 53,
+ 10,240, 10,242, 10,244, 10,246, 10,248, 10,252, 10,254, 11, 2, 11, 4, 11, 8, 11, 12, 11, 16, 11, 20, 11, 24, 11, 26, 11, 28,
+ 11, 30, 11, 32, 11, 36, 11, 40, 11, 44, 11, 48, 11, 52, 11, 56, 11, 60, 11, 64, 11, 68, 11, 72, 11, 76, 11, 80, 11, 84, 11, 88,
+ 11, 92, 11, 94, 11, 96, 10,172, 10,164, 10,152, 10,156, 10,168, 10,160, 10,188, 10,184, 10,192, 10,196, 10,202, 10,200, 10,176,
+ 10,204, 10,208, 10,212, 10,214, 10,220, 0, 2, 0, 10, 3,224, 3,248, 0, 0, 3,250, 4, 3, 0, 25, 4, 33, 4, 35, 0, 35,
+ 4, 38, 4, 40, 0, 38, 4, 43, 4, 44, 0, 41, 4, 46, 4, 48, 0, 43, 4, 50, 4, 50, 0, 46, 4, 52, 4, 54, 0, 47, 4, 56,
+ 4, 57, 0, 50, 4, 59, 4, 59, 0, 52, 0, 2, 0, 82, 0, 38, 10,250, 11, 0, 11, 6, 11, 10, 11, 14, 11, 18, 11, 22, 11, 34,
+ 11, 38, 11, 42, 11, 46, 11, 50, 11, 54, 11, 58, 11, 62, 11, 66, 11, 70, 11, 74, 11, 78, 11, 82, 11, 86, 11, 90, 11, 98, 10,174,
+ 10,166, 10,154, 10,158, 10,170, 10,162, 10,190, 10,186, 10,194, 10,198, 10,178, 10,206, 10,210, 10,216, 10,222, 0, 1, 0, 38,
+ 3,228, 3,230, 3,232, 3,233, 3,234, 3,235, 3,236, 3,241, 3,242, 3,243, 3,244, 3,245, 3,246, 3,247, 3,248, 3,250,
+ 3,251, 3,252, 3,253, 3,254, 3,255, 4, 0, 4, 3, 4, 33, 4, 34, 4, 35, 4, 38, 4, 39, 4, 40, 4, 43, 4, 44, 4, 46,
+ 4, 47, 4, 52, 4, 53, 4, 54, 4, 57, 4, 59, 0, 2, 0, 82, 0, 38, 10,249, 10,255, 11, 5, 11, 9, 11, 13, 11, 17, 11, 21,
+ 11, 33, 11, 37, 11, 41, 11, 45, 11, 49, 11, 53, 11, 57, 11, 61, 11, 65, 11, 69, 11, 73, 11, 77, 11, 81, 11, 85, 11, 89, 11, 97,
+ 10,173, 10,165, 10,153, 10,157, 10,169, 10,161, 10,189, 10,185, 10,193, 10,197, 10,177, 10,205, 10,209, 10,215, 10,221, 0, 1,
+ 0, 38, 3,228, 3,230, 3,232, 3,233, 3,234, 3,235, 3,236, 3,241, 3,242, 3,243, 3,244, 3,245, 3,246, 3,247, 3,248,
+ 3,250, 3,251, 3,252, 3,253, 3,254, 3,255, 4, 0, 4, 3, 4, 33, 4, 34, 4, 35, 4, 38, 4, 39, 4, 40, 4, 43, 4, 44,
+ 4, 46, 4, 47, 4, 52, 4, 53, 4, 54, 4, 57, 4, 59, 0, 1, 0, 30, 0, 2, 0, 10, 0, 20, 0, 1, 0, 4, 11,105, 0, 2,
+ 10,252, 0, 1, 0, 4, 11,106, 0, 2, 10,252, 0, 1, 0, 2, 11, 77, 11, 78, 0, 1, 0, 62, 0, 2, 0, 10, 0, 36, 0, 3,
+ 0, 8, 0, 14, 0, 20, 11,103, 0, 2, 10,246, 11,101, 0, 2, 10,242, 11, 99, 0, 2, 10,240, 0, 3, 0, 8, 0, 14, 0, 20,
+ 11,104, 0, 2, 10,246, 11,102, 0, 2, 10,242, 11,100, 0, 2, 10,240, 0, 1, 0, 2, 11, 77, 11, 78, 0, 1, 0, 26, 0, 1,
+ 0, 8, 0, 2, 0, 6, 0, 12, 10,150, 0, 2, 0, 79, 10,149, 0, 2, 0, 76, 0, 1, 0, 1, 0, 73, 0, 2, 0, 10, 0, 2,
+ 0,243, 1,226, 0, 1, 0, 2, 0, 76, 0, 77, 0, 1, 4,209, 1,144, 0, 5, 0, 0, 5, 51, 5,153, 0, 0, 1, 30, 5, 51,
+ 5,153, 0, 0, 3,215, 0,102, 2, 18, 0, 0, 2, 11, 6, 9, 3, 8, 4, 2, 2, 4,230, 0, 34,255,210, 0,249,251, 2, 0,
+ 0, 40, 0, 0, 0, 0, 80,102, 69,100, 0, 64, 0, 32,255,255, 6, 20,254, 20, 1,154, 7,109, 1,227, 96, 0, 0,223,255,223,
+ 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 44, 0, 0, 0, 4, 0, 0, 7,156, 0, 1, 0, 0, 0, 0, 18,188,
+ 0, 3, 0, 1, 0, 0, 0, 44, 0, 3, 0, 10, 0, 0, 7,156, 0, 4, 7,112, 0, 0, 1,216, 1, 0, 0, 7, 0,216, 0, 0,
+ 0,126, 1,185, 1,190, 1,195, 1,227, 1,240, 1,246, 1,249, 2, 27, 2, 33, 2, 65, 2, 69, 2,185, 2,193, 2,201, 2,205,
+ 2,211, 2,214, 2,222, 2,233, 2,243, 3, 63, 3, 67, 3, 88, 3, 97, 3,117, 3,122, 3,126, 3,138, 3,140, 3,161, 3,206,
+ 3,225, 4, 95, 4,155, 4,163, 4,179, 4,187, 4,196, 4,200, 4,204, 4,249, 6, 12, 6, 21, 6, 27, 6, 31, 6, 58, 6, 85,
+ 6, 90, 6,111, 6,116, 6,135, 6,146, 6,152, 6,161, 6,164, 6,169, 6,175, 6,181, 6,186, 6,190, 6,198, 6,204, 6,206,
+ 6,213, 6,249, 14,130, 14,132, 14,136, 14,138, 14,141, 14,151, 14,159, 14,163, 14,165, 14,167, 14,171, 14,185, 14,188, 14,205,
+ 16,252, 29, 2, 29, 9, 29, 20, 29, 23, 29, 31, 29, 46, 29, 60, 29, 91, 29,101, 29,120, 29,123, 29,133, 29,183, 29,191, 30, 19,
+ 30, 37, 30, 45, 30, 75, 30, 99, 30,119, 30,139, 30,143, 30,150, 30,155, 30,161, 30,177, 30,185, 30,189, 30,205, 30,229, 30,245,
+ 30,249, 31, 21, 31, 29, 31, 69, 31, 77, 31, 87, 31, 89, 31, 91, 31, 93, 31,125, 31,180, 31,196, 31,211, 31,219, 31,239, 31,244,
+ 31,254, 32, 10, 32, 21, 32, 35, 32, 38, 32, 49, 32, 58, 32, 62, 32, 73, 32, 95, 32,113, 32,142, 32,148, 32,166, 32,172, 32,177,
+ 32,181, 33, 2, 33, 14, 33, 22, 33, 34, 33, 38, 33, 43, 33, 95, 33,255, 34, 2, 34, 13, 34, 15, 34, 19, 34, 21, 34, 26, 34, 32,
+ 34, 45, 34, 61, 34,105, 34,139, 34,146, 34,161, 34,198, 34,205, 34,233, 34,239, 35, 6, 35, 21, 35, 25, 35, 33, 35, 40, 35, 43,
+ 35, 53, 35, 62, 35, 68, 35, 73, 35, 77, 35, 80, 35, 84, 35, 92, 35, 96, 35,101, 35,105, 35,112, 35,122, 35,125, 35,131, 35,139,
+ 35,149, 35,174, 35,207, 36, 35, 38, 47, 38,139, 38,156, 38,161, 38,177, 39, 4, 39, 9, 39, 39, 39, 75, 39, 77, 39, 82, 39, 86,
+ 39, 94, 39,117, 39,148, 39,175, 39,190, 39,224, 39,233, 41,235, 41,251, 42, 47, 43, 26, 44,119, 46, 24, 46, 46,246,197,251, 2,
+251,129,251,149,251,159,251,173,251,233,251,255,254,116,254,252,254,255,255,253,255,255, 0, 0, 0, 0, 0, 32, 0,160, 1,187,
+ 1,192, 1,205, 1,230, 1,244, 1,248, 1,252, 2, 30, 2, 36, 2, 69, 2, 80, 2,187, 2,198, 2,204, 2,208, 2,214, 2,216,
+ 2,224, 2,243, 3, 0, 3, 67, 3, 88, 3, 97, 3,116, 3,122, 3,126, 3,132, 3,140, 3,142, 3,163, 3,208, 3,240, 4,144,
+ 4,162, 4,170, 4,186, 4,192, 4,199, 4,203, 4,207, 6, 12, 6, 21, 6, 27, 6, 31, 6, 33, 6, 64, 6, 90, 6, 96, 6,116,
+ 6,121, 6,145, 6,152, 6,161, 6,164, 6,169, 6,175, 6,181, 6,186, 6,190, 6,198, 6,204, 6,206, 6,213, 6,240, 14,129,
+ 14,132, 14,135, 14,138, 14,141, 14,148, 14,153, 14,161, 14,165, 14,167, 14,170, 14,173, 14,187, 14,200, 16,208, 29, 2, 29, 8,
+ 29, 20, 29, 22, 29, 29, 29, 44, 29, 48, 29, 62, 29, 98, 29,119, 29,123, 29,133, 29,155, 29,185, 30, 0, 30, 24, 30, 40, 30, 48,
+ 30, 86, 30,104, 30,126, 30,142, 30,146, 30,155, 30,160, 30,176, 30,184, 30,188, 30,202, 30,228, 30,242, 30,248, 31, 0, 31, 24,
+ 31, 32, 31, 72, 31, 80, 31, 89, 31, 91, 31, 93, 31, 95, 31,128, 31,182, 31,198, 31,214, 31,221, 31,242, 31,246, 32, 0, 32, 16,
+ 32, 23, 32, 38, 32, 47, 32, 57, 32, 60, 32, 69, 32, 95, 32,112, 32,116, 32,144, 32,166, 32,172, 32,177, 32,180, 33, 2, 33, 14,
+ 33, 22, 33, 34, 33, 38, 33, 42, 33, 83, 33,144, 34, 2, 34, 5, 34, 15, 34, 17, 34, 21, 34, 23, 34, 29, 34, 39, 34, 56, 34, 65,
+ 34,109, 34,143, 34,149, 34,197, 34,205, 34,218, 34,239, 35, 0, 35, 8, 35, 24, 35, 28, 35, 37, 35, 43, 35, 53, 35, 55, 35, 65,
+ 35, 71, 35, 75, 35, 80, 35, 82, 35, 87, 35, 94, 35, 99, 35,104, 35,107, 35,115, 35,125, 35,128, 35,136, 35,149, 35,155, 35,206,
+ 36, 35, 37, 0, 38, 56, 38,144, 38,160, 38,176, 39, 1, 39, 6, 39, 12, 39, 41, 39, 77, 39, 79, 39, 86, 39, 88, 39, 97, 39,148,
+ 39,152, 39,177, 39,224, 39,232, 41,235, 41,250, 42, 47, 43, 18, 44,117, 46, 24, 46, 46,246,197,251, 1,251, 82,251,138,251,158,
+251,170,251,232,251,252,254,112,254,118,254,255,255,249,255,255, 0, 0,255,227,255,194,255,193,255,192,255,183,255,181,255,178,
+255,177,255,175,255,173,255,171,255,168,255,158,255,157,255,153,255,151,255,149,255,147,255,146,255,145,255,136,255,124,255,121,
+255,101,255, 93,255, 75,255, 71,255, 68,255, 63,255, 62,255, 61,255, 60,255, 59,255, 45,254,253,254,247,254,241,254,235,254,231,
+254,229,254,227,254,225,253,207,253,199,253,194,253,191,253,190,253,185,253,181,253,176,253,172,253,168,253,159,253,154,253,146,
+253,144,253,140,253,135,253,130,253,126,253,123,253,116,253,111,253,110,253,104,253, 78,245,199,245,198,245,196,245,195,245,193,
+245,187,245,186,245,185,245,184,245,183,245,181,245,180,245,179,245,168,243,166,231,161,231,156,231,146,231,145,231,140,231,128,
+231,127,231,126,231,120,231,103,231,101,231, 92,231, 71,231, 70,231, 6,231, 2,231, 0,230,254,230,244,230,240,230,234,230,232,
+230,230,230,226,230,222,230,208,230,202,230,200,230,188,230,166,230,154,230,152,230,146,230,144,230,142,230,140,230,138,230,137,
+230,136,230,135,230,134,230,132,230,131,230,130,230,128,230,127,230,125,230,124,230,123,230,118,230,117,230,115,230,107,230,100,
+230, 99,230, 93,230, 72,230, 56,230, 54,230, 53,230, 36,230, 31,230, 27,230, 25,229,205,229,194,229,187,229,176,229,173,229,170,
+229,131,229, 83,229, 81,229, 79,229, 78,229, 77,229, 76,229, 75,229, 73,229, 67,229, 57,229, 54,229, 51,229, 48,229, 46,229, 11,
+229, 5,228,249,228,244,228,228,228,227,228,225,228,223,228,220,228,218,228,209,228,208,228,206,228,204,228,203,228,201,228,200,
+228,198,228,197,228,195,228,193,228,192,228,190,228,188,228,186,228,182,228,173,228,168,228,137,228, 54,227, 90,227, 82,227, 78,
+227, 75,227, 61,226,238,226,237,226,235,226,234,226,233,226,232,226,229,226,228,226,226,226,196,226,193,226,192,226,159,226,152,
+224,151,224,137,224, 86,223,116,222, 26,220,122,220,101, 19,207, 15,148, 15, 69, 15, 61, 15, 53, 15, 43, 14,241, 14,223, 12,111,
+ 12,110, 12,108, 11,115, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 11, 32, 0, 0, 0, 0, 0, 0, 0,236, 0, 0, 0, 32, 0, 0, 0,126, 0, 0, 0, 3, 0, 0, 0,160,
+ 0, 0, 1,185, 0, 0, 0, 98, 0, 0, 1,187, 0, 0, 1,190, 0, 0, 1,124, 0, 0, 1,192, 0, 0, 1,195, 0, 0, 1,128,
+ 0, 0, 1,205, 0, 0, 1,227, 0, 0, 1,132, 0, 0, 1,230, 0, 0, 1,240, 0, 0, 1,155, 0, 0, 1,244, 0, 0, 1,246,
+ 0, 0, 1,166, 0, 0, 1,248, 0, 0, 1,249, 0, 0, 1,169, 0, 0, 1,252, 0, 0, 2, 27, 0, 0, 1,171, 0, 0, 2, 30,
+ 0, 0, 2, 33, 0, 0, 1,203, 0, 0, 2, 36, 0, 0, 2, 65, 0, 0, 1,207, 0, 0, 2, 69, 0, 0, 2, 69, 0, 0, 1,237,
+ 0, 0, 2, 80, 0, 0, 2,185, 0, 0, 1,238, 0, 0, 2,187, 0, 0, 2,193, 0, 0, 2, 88, 0, 0, 2,198, 0, 0, 2,201,
+ 0, 0, 2, 95, 0, 0, 2,204, 0, 0, 2,205, 0, 0, 2, 99, 0, 0, 2,208, 0, 0, 2,211, 0, 0, 2,101, 0, 0, 2,214,
+ 0, 0, 2,214, 0, 0, 2,105, 0, 0, 2,216, 0, 0, 2,222, 0, 0, 2,106, 0, 0, 2,224, 0, 0, 2,233, 0, 0, 2,113,
+ 0, 0, 2,243, 0, 0, 2,243, 0, 0, 2,123, 0, 0, 3, 0, 0, 0, 3, 63, 0, 0, 2,124, 0, 0, 3, 67, 0, 0, 3, 67,
+ 0, 0, 2,188, 0, 0, 3, 88, 0, 0, 3, 88, 0, 0, 2,189, 0, 0, 3, 97, 0, 0, 3, 97, 0, 0, 2,190, 0, 0, 3,116,
+ 0, 0, 3,117, 0, 0, 2,191, 0, 0, 3,122, 0, 0, 3,122, 0, 0, 2,193, 0, 0, 3,126, 0, 0, 3,126, 0, 0, 2,194,
+ 0, 0, 3,132, 0, 0, 3,138, 0, 0, 2,195, 0, 0, 3,140, 0, 0, 3,140, 0, 0, 2,202, 0, 0, 3,142, 0, 0, 3,161,
+ 0, 0, 2,203, 0, 0, 3,163, 0, 0, 3,206, 0, 0, 2,223, 0, 0, 3,208, 0, 0, 3,225, 0, 0, 3, 11, 0, 0, 3,240,
+ 0, 0, 4, 95, 0, 0, 3, 29, 0, 0, 4,144, 0, 0, 4,155, 0, 0, 3,141, 0, 0, 4,162, 0, 0, 4,163, 0, 0, 3,153,
+ 0, 0, 4,170, 0, 0, 4,179, 0, 0, 3,155, 0, 0, 4,186, 0, 0, 4,187, 0, 0, 3,165, 0, 0, 4,192, 0, 0, 4,196,
+ 0, 0, 3,167, 0, 0, 4,199, 0, 0, 4,200, 0, 0, 3,172, 0, 0, 4,203, 0, 0, 4,204, 0, 0, 3,174, 0, 0, 4,207,
+ 0, 0, 4,249, 0, 0, 3,176, 0, 0, 6, 12, 0, 0, 6, 12, 0, 0, 3,219, 0, 0, 6, 21, 0, 0, 6, 21, 0, 0, 3,220,
+ 0, 0, 6, 27, 0, 0, 6, 27, 0, 0, 3,221, 0, 0, 6, 31, 0, 0, 6, 31, 0, 0, 3,222, 0, 0, 6, 33, 0, 0, 6, 58,
+ 0, 0, 3,223, 0, 0, 6, 64, 0, 0, 6, 85, 0, 0, 3,249, 0, 0, 6, 90, 0, 0, 6, 90, 0, 0, 4, 15, 0, 0, 6, 96,
+ 0, 0, 6,111, 0, 0, 4, 16, 0, 0, 6,116, 0, 0, 6,116, 0, 0, 4, 32, 0, 0, 6,121, 0, 0, 6,135, 0, 0, 4, 33,
+ 0, 0, 6,145, 0, 0, 6,146, 0, 0, 4, 48, 0, 0, 6,152, 0, 0, 6,152, 0, 0, 4, 50, 0, 0, 6,161, 0, 0, 6,161,
+ 0, 0, 4, 51, 0, 0, 6,164, 0, 0, 6,164, 0, 0, 4, 52, 0, 0, 6,169, 0, 0, 6,169, 0, 0, 4, 53, 0, 0, 6,175,
+ 0, 0, 6,175, 0, 0, 4, 54, 0, 0, 6,181, 0, 0, 6,181, 0, 0, 4, 55, 0, 0, 6,186, 0, 0, 6,186, 0, 0, 4, 56,
+ 0, 0, 6,190, 0, 0, 6,190, 0, 0, 4, 57, 0, 0, 6,198, 0, 0, 6,198, 0, 0, 4, 58, 0, 0, 6,204, 0, 0, 6,204,
+ 0, 0, 4, 59, 0, 0, 6,206, 0, 0, 6,206, 0, 0, 4, 60, 0, 0, 6,213, 0, 0, 6,213, 0, 0, 4, 61, 0, 0, 6,240,
+ 0, 0, 6,249, 0, 0, 4, 62, 0, 0, 14,129, 0, 0, 14,130, 0, 0, 4, 72, 0, 0, 14,132, 0, 0, 14,132, 0, 0, 4, 74,
+ 0, 0, 14,135, 0, 0, 14,136, 0, 0, 4, 75, 0, 0, 14,138, 0, 0, 14,138, 0, 0, 4, 77, 0, 0, 14,141, 0, 0, 14,141,
+ 0, 0, 4, 78, 0, 0, 14,148, 0, 0, 14,151, 0, 0, 4, 79, 0, 0, 14,153, 0, 0, 14,159, 0, 0, 4, 83, 0, 0, 14,161,
+ 0, 0, 14,163, 0, 0, 4, 90, 0, 0, 14,165, 0, 0, 14,165, 0, 0, 4, 93, 0, 0, 14,167, 0, 0, 14,167, 0, 0, 4, 94,
+ 0, 0, 14,170, 0, 0, 14,171, 0, 0, 4, 95, 0, 0, 14,173, 0, 0, 14,185, 0, 0, 4, 97, 0, 0, 14,187, 0, 0, 14,188,
+ 0, 0, 4,110, 0, 0, 14,200, 0, 0, 14,205, 0, 0, 4,112, 0, 0, 16,208, 0, 0, 16,252, 0, 0, 4,118, 0, 0, 29, 2,
+ 0, 0, 29, 2, 0, 0, 4,163, 0, 0, 29, 8, 0, 0, 29, 9, 0, 0, 4,164, 0, 0, 29, 20, 0, 0, 29, 20, 0, 0, 4,166,
+ 0, 0, 29, 22, 0, 0, 29, 23, 0, 0, 4,167, 0, 0, 29, 29, 0, 0, 29, 31, 0, 0, 4,169, 0, 0, 29, 44, 0, 0, 29, 46,
+ 0, 0, 4,172, 0, 0, 29, 48, 0, 0, 29, 60, 0, 0, 4,175, 0, 0, 29, 62, 0, 0, 29, 91, 0, 0, 4,188, 0, 0, 29, 98,
+ 0, 0, 29,101, 0, 0, 4,218, 0, 0, 29,119, 0, 0, 29,120, 0, 0, 4,222, 0, 0, 29,123, 0, 0, 29,123, 0, 0, 4,224,
+ 0, 0, 29,133, 0, 0, 29,133, 0, 0, 4,225, 0, 0, 29,155, 0, 0, 29,183, 0, 0, 4,226, 0, 0, 29,185, 0, 0, 29,191,
+ 0, 0, 4,255, 0, 0, 30, 0, 0, 0, 30, 19, 0, 0, 5, 6, 0, 0, 30, 24, 0, 0, 30, 37, 0, 0, 5, 26, 0, 0, 30, 40,
+ 0, 0, 30, 45, 0, 0, 5, 40, 0, 0, 30, 48, 0, 0, 30, 75, 0, 0, 5, 46, 0, 0, 30, 86, 0, 0, 30, 99, 0, 0, 5, 74,
+ 0, 0, 30,104, 0, 0, 30,119, 0, 0, 5, 88, 0, 0, 30,126, 0, 0, 30,139, 0, 0, 5,104, 0, 0, 30,142, 0, 0, 30,143,
+ 0, 0, 5,118, 0, 0, 30,146, 0, 0, 30,150, 0, 0, 5,120, 0, 0, 30,155, 0, 0, 30,155, 0, 0, 5,125, 0, 0, 30,160,
+ 0, 0, 30,161, 0, 0, 5,126, 0, 0, 30,176, 0, 0, 30,177, 0, 0, 5,128, 0, 0, 30,184, 0, 0, 30,185, 0, 0, 5,130,
+ 0, 0, 30,188, 0, 0, 30,189, 0, 0, 5,132, 0, 0, 30,202, 0, 0, 30,205, 0, 0, 5,134, 0, 0, 30,228, 0, 0, 30,229,
+ 0, 0, 5,138, 0, 0, 30,242, 0, 0, 30,245, 0, 0, 5,140, 0, 0, 30,248, 0, 0, 30,249, 0, 0, 5,144, 0, 0, 31, 0,
+ 0, 0, 31, 21, 0, 0, 5,146, 0, 0, 31, 24, 0, 0, 31, 29, 0, 0, 5,168, 0, 0, 31, 32, 0, 0, 31, 69, 0, 0, 5,174,
+ 0, 0, 31, 72, 0, 0, 31, 77, 0, 0, 5,212, 0, 0, 31, 80, 0, 0, 31, 87, 0, 0, 5,218, 0, 0, 31, 89, 0, 0, 31, 89,
+ 0, 0, 5,226, 0, 0, 31, 91, 0, 0, 31, 91, 0, 0, 5,227, 0, 0, 31, 93, 0, 0, 31, 93, 0, 0, 5,228, 0, 0, 31, 95,
+ 0, 0, 31,125, 0, 0, 5,229, 0, 0, 31,128, 0, 0, 31,180, 0, 0, 6, 4, 0, 0, 31,182, 0, 0, 31,196, 0, 0, 6, 57,
+ 0, 0, 31,198, 0, 0, 31,211, 0, 0, 6, 72, 0, 0, 31,214, 0, 0, 31,219, 0, 0, 6, 86, 0, 0, 31,221, 0, 0, 31,239,
+ 0, 0, 6, 92, 0, 0, 31,242, 0, 0, 31,244, 0, 0, 6,111, 0, 0, 31,246, 0, 0, 31,254, 0, 0, 6,114, 0, 0, 32, 0,
+ 0, 0, 32, 10, 0, 0, 6,123, 0, 0, 32, 16, 0, 0, 32, 21, 0, 0, 6,134, 0, 0, 32, 23, 0, 0, 32, 35, 0, 0, 6,140,
+ 0, 0, 32, 38, 0, 0, 32, 38, 0, 0, 6,153, 0, 0, 32, 47, 0, 0, 32, 49, 0, 0, 6,154, 0, 0, 32, 57, 0, 0, 32, 58,
+ 0, 0, 6,157, 0, 0, 32, 60, 0, 0, 32, 62, 0, 0, 6,159, 0, 0, 32, 69, 0, 0, 32, 73, 0, 0, 6,162, 0, 0, 32, 95,
+ 0, 0, 32, 95, 0, 0, 6,167, 0, 0, 32,112, 0, 0, 32,113, 0, 0, 6,168, 0, 0, 32,116, 0, 0, 32,142, 0, 0, 6,170,
+ 0, 0, 32,144, 0, 0, 32,148, 0, 0, 6,197, 0, 0, 32,166, 0, 0, 32,166, 0, 0, 6,202, 0, 0, 32,172, 0, 0, 32,172,
+ 0, 0, 6,203, 0, 0, 32,177, 0, 0, 32,177, 0, 0, 6,204, 0, 0, 32,180, 0, 0, 32,181, 0, 0, 6,205, 0, 0, 33, 2,
+ 0, 0, 33, 2, 0, 0, 6,207, 0, 0, 33, 14, 0, 0, 33, 14, 0, 0, 6,208, 0, 0, 33, 22, 0, 0, 33, 22, 0, 0, 6,209,
+ 0, 0, 33, 34, 0, 0, 33, 34, 0, 0, 6,210, 0, 0, 33, 38, 0, 0, 33, 38, 0, 0, 6,211, 0, 0, 33, 42, 0, 0, 33, 43,
+ 0, 0, 6,212, 0, 0, 33, 83, 0, 0, 33, 95, 0, 0, 6,214, 0, 0, 33,144, 0, 0, 33,255, 0, 0, 6,227, 0, 0, 34, 2,
+ 0, 0, 34, 2, 0, 0, 7, 83, 0, 0, 34, 5, 0, 0, 34, 13, 0, 0, 7, 84, 0, 0, 34, 15, 0, 0, 34, 15, 0, 0, 7, 93,
+ 0, 0, 34, 17, 0, 0, 34, 19, 0, 0, 7, 94, 0, 0, 34, 21, 0, 0, 34, 21, 0, 0, 7, 97, 0, 0, 34, 23, 0, 0, 34, 26,
+ 0, 0, 7, 98, 0, 0, 34, 29, 0, 0, 34, 32, 0, 0, 7,102, 0, 0, 34, 39, 0, 0, 34, 45, 0, 0, 7,106, 0, 0, 34, 56,
+ 0, 0, 34, 61, 0, 0, 7,113, 0, 0, 34, 65, 0, 0, 34,105, 0, 0, 7,119, 0, 0, 34,109, 0, 0, 34,139, 0, 0, 7,160,
+ 0, 0, 34,143, 0, 0, 34,146, 0, 0, 7,191, 0, 0, 34,149, 0, 0, 34,161, 0, 0, 7,195, 0, 0, 34,197, 0, 0, 34,198,
+ 0, 0, 7,208, 0, 0, 34,205, 0, 0, 34,205, 0, 0, 7,210, 0, 0, 34,218, 0, 0, 34,233, 0, 0, 7,211, 0, 0, 34,239,
+ 0, 0, 34,239, 0, 0, 7,227, 0, 0, 35, 0, 0, 0, 35, 6, 0, 0, 7,228, 0, 0, 35, 8, 0, 0, 35, 21, 0, 0, 7,235,
+ 0, 0, 35, 24, 0, 0, 35, 25, 0, 0, 7,249, 0, 0, 35, 28, 0, 0, 35, 33, 0, 0, 7,251, 0, 0, 35, 37, 0, 0, 35, 40,
+ 0, 0, 8, 1, 0, 0, 35, 43, 0, 0, 35, 43, 0, 0, 8, 5, 0, 0, 35, 53, 0, 0, 35, 53, 0, 0, 8, 6, 0, 0, 35, 55,
+ 0, 0, 35, 62, 0, 0, 8, 7, 0, 0, 35, 65, 0, 0, 35, 68, 0, 0, 8, 15, 0, 0, 35, 71, 0, 0, 35, 73, 0, 0, 8, 19,
+ 0, 0, 35, 75, 0, 0, 35, 77, 0, 0, 8, 22, 0, 0, 35, 80, 0, 0, 35, 80, 0, 0, 8, 25, 0, 0, 35, 82, 0, 0, 35, 84,
+ 0, 0, 8, 26, 0, 0, 35, 87, 0, 0, 35, 92, 0, 0, 8, 29, 0, 0, 35, 94, 0, 0, 35, 96, 0, 0, 8, 35, 0, 0, 35, 99,
+ 0, 0, 35,101, 0, 0, 8, 38, 0, 0, 35,104, 0, 0, 35,105, 0, 0, 8, 41, 0, 0, 35,107, 0, 0, 35,112, 0, 0, 8, 43,
+ 0, 0, 35,115, 0, 0, 35,122, 0, 0, 8, 49, 0, 0, 35,125, 0, 0, 35,125, 0, 0, 8, 57, 0, 0, 35,128, 0, 0, 35,131,
+ 0, 0, 8, 58, 0, 0, 35,136, 0, 0, 35,139, 0, 0, 8, 62, 0, 0, 35,149, 0, 0, 35,149, 0, 0, 8, 66, 0, 0, 35,155,
+ 0, 0, 35,174, 0, 0, 8, 67, 0, 0, 35,206, 0, 0, 35,207, 0, 0, 8, 87, 0, 0, 36, 35, 0, 0, 36, 35, 0, 0, 8, 89,
+ 0, 0, 37, 0, 0, 0, 38, 47, 0, 0, 8, 90, 0, 0, 38, 56, 0, 0, 38,139, 0, 0, 9,138, 0, 0, 38,144, 0, 0, 38,156,
+ 0, 0, 9,222, 0, 0, 38,160, 0, 0, 38,161, 0, 0, 9,235, 0, 0, 38,176, 0, 0, 38,177, 0, 0, 9,237, 0, 0, 39, 1,
+ 0, 0, 39, 4, 0, 0, 9,239, 0, 0, 39, 6, 0, 0, 39, 9, 0, 0, 9,243, 0, 0, 39, 12, 0, 0, 39, 39, 0, 0, 9,247,
+ 0, 0, 39, 41, 0, 0, 39, 75, 0, 0, 10, 19, 0, 0, 39, 77, 0, 0, 39, 77, 0, 0, 10, 54, 0, 0, 39, 79, 0, 0, 39, 82,
+ 0, 0, 10, 55, 0, 0, 39, 86, 0, 0, 39, 86, 0, 0, 10, 59, 0, 0, 39, 88, 0, 0, 39, 94, 0, 0, 10, 60, 0, 0, 39, 97,
+ 0, 0, 39,117, 0, 0, 10, 67, 0, 0, 39,148, 0, 0, 39,148, 0, 0, 10, 88, 0, 0, 39,152, 0, 0, 39,175, 0, 0, 10, 89,
+ 0, 0, 39,177, 0, 0, 39,190, 0, 0, 10,113, 0, 0, 39,224, 0, 0, 39,224, 0, 0, 10,127, 0, 0, 39,232, 0, 0, 39,233,
+ 0, 0, 10,128, 0, 0, 41,235, 0, 0, 41,235, 0, 0, 10,130, 0, 0, 41,250, 0, 0, 41,251, 0, 0, 10,131, 0, 0, 42, 47,
+ 0, 0, 42, 47, 0, 0, 10,133, 0, 0, 43, 18, 0, 0, 43, 26, 0, 0, 10,134, 0, 0, 44,117, 0, 0, 44,119, 0, 0, 10,143,
+ 0, 0, 46, 24, 0, 0, 46, 24, 0, 0, 10,146, 0, 0, 46, 46, 0, 0, 46, 46, 0, 0, 10,147, 0, 0,246,197, 0, 0,246,197,
+ 0, 0, 10,148, 0, 0,251, 1, 0, 0,251, 2, 0, 0, 10,149, 0, 0,251, 82, 0, 0,251,129, 0, 0, 10,151, 0, 0,251,138,
+ 0, 0,251,149, 0, 0, 10,199, 0, 0,251,158, 0, 0,251,159, 0, 0, 10,211, 0, 0,251,170, 0, 0,251,173, 0, 0, 10,213,
+ 0, 0,251,232, 0, 0,251,233, 0, 0, 10,217, 0, 0,251,252, 0, 0,251,255, 0, 0, 10,219, 0, 0,254,112, 0, 0,254,116,
+ 0, 0, 10,223, 0, 0,254,118, 0, 0,254,252, 0, 0, 10,228, 0, 0,254,255, 0, 0,254,255, 0, 0, 11,107, 0, 0,255,249,
+ 0, 0,255,253, 0, 0, 11,108, 0, 1,214,112, 0, 1,214,163, 0, 0, 11,113, 0, 1,215,246, 0, 1,215,255, 0, 0, 11,165,
+ 0, 6, 2, 10, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0,
+ 0, 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, 1, 0, 0, 0, 0, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13,
+ 0, 14, 0, 15, 0, 16, 0, 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24, 0, 25, 0, 26, 0, 27, 0, 28, 0, 29,
+ 0, 30, 0, 31, 0, 32, 0, 33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38, 0, 39, 0, 40, 0, 41, 0, 42, 0, 43, 0, 44, 0, 45,
+ 0, 46, 0, 47, 0, 48, 0, 49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, 0, 56, 0, 57, 0, 58, 0, 59, 0, 60, 0, 61,
+ 0, 62, 0, 63, 0, 64, 0, 65, 0, 66, 0, 67, 0, 68, 0, 69, 0, 70, 0, 71, 0, 72, 0, 73, 0, 74, 0, 75, 0, 76, 0, 77,
+ 0, 78, 0, 79, 0, 80, 0, 81, 0, 82, 0, 83, 0, 84, 0, 85, 0, 86, 0, 87, 0, 88, 0, 89, 0, 90, 0, 91, 0, 92, 0, 93,
+ 0, 94, 0, 95, 0, 96, 0, 97, 0, 0, 0,134, 0,135, 0,137, 0,139, 0,147, 0,152, 0,158, 0,163, 0,162, 0,164, 0,166,
+ 0,165, 0,167, 0,169, 0,171, 0,170, 0,172, 0,173, 0,175, 0,174, 0,176, 0,177, 0,179, 0,181, 0,180, 0,182, 0,184,
+ 0,183, 0,188, 0,187, 0,189, 0,190, 6,149, 0,114, 0,100, 0,101, 0,105, 6,151, 0,120, 0,161, 0,112, 0,107, 6,210,
+ 0,118, 0,106, 7,150, 0,136, 0,154, 7,103, 0,115, 7,154, 7,155, 0,103, 0,119, 7, 83, 7, 94, 7, 93, 2,252, 7,110,
+ 0,108, 0,124, 2,229, 0,168, 0,186, 0,129, 0, 99, 0,110, 7,101, 1, 84, 7,126, 7, 85, 0,109, 0,125, 6,153, 0, 98,
+ 0,130, 0,133, 0,151, 1, 20, 1, 21, 6,137, 6,138, 6,145, 6,146, 6,141, 6,142, 0,185, 9, 36, 0,193, 1, 58, 0, 0,
+ 6,203, 6,157, 6,158, 10,149, 10,150, 6,150, 0,121, 6,143, 6,147, 6,155, 0,132, 0,140, 0,131, 0,141, 0,138, 0,143,
+ 0,144, 0,145, 0,142, 0,149, 0,150, 0, 0, 0,148, 0,156, 0,157, 0,155, 0,243, 2, 95, 2,110, 0,113, 2,106, 2,107,
+ 2,108, 0,122, 2,111, 2,109, 2, 96, 0, 0, 0,184, 0,203, 0,184, 0,203, 0,170, 1,145, 0,184, 0,102, 0, 0, 0,184,
+ 0,135, 2,127, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0,184, 0,195, 0,203, 0, 2, 0,203, 0,184, 0,184, 1,203, 1,137,
+ 1,186, 0,203, 0,166, 0,252, 0,203, 0,131, 0,242, 1, 10, 3,199, 1, 55, 0,131, 0,190, 0, 0, 0, 88, 4, 33, 0,203,
+ 0,143, 0,156, 0, 2, 0, 2, 0,143, 3,231, 0,117, 3,188, 0,211, 0,201, 0,219, 0,117, 3,231, 1, 57, 3,186, 0,203,
+ 1,211, 0, 33, 1,223, 0,184, 0,137, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 3,190, 0,137, 0,195, 3,190, 0,123, 3,190,
+ 3, 88, 1, 31, 1,109, 0,164, 1,174, 0, 0, 0,123, 0,184, 1,111, 0,127, 2,123, 0,184, 2, 82, 0,143, 0,205, 4,209,
+ 0, 0, 0,205, 0,135, 0,135, 0,147, 0,164, 0,111, 0,205, 0,203, 0,184, 0,131, 1,145, 0,221, 0,180, 0,139, 0,244,
+ 0,152, 2,233, 0, 90, 0,180, 0,186, 0,197, 4, 33, 0,254, 0, 14, 0, 2, 0, 2, 0, 2, 1,213, 0,246, 0,127, 2,170,
+ 2, 61, 2,102, 0,139, 0,197, 0,143, 0,154, 0,154, 1,131, 0,213, 0,115, 4, 0, 1, 10, 0,254, 0,225, 5,213, 2, 43,
+ 0,164, 0,180, 0,156, 0, 0, 0, 98, 0,156, 5,213, 5,152, 0,135, 2,127, 5,213, 5,213, 5,240, 0,164, 0, 0, 0, 29,
+ 6,184, 6, 20, 7, 35, 1,211, 0,184, 0,203, 0,166, 1,188, 1, 49, 2, 78, 0,211, 1, 10, 0,123, 0, 84, 3, 92, 3,113,
+ 3,219, 1,133, 4, 35, 4,119, 3,233, 0,143, 2, 0, 3, 96, 0,106, 0,207, 5,213, 6, 20, 0,143, 7, 35, 0,143, 6,102,
+ 1,121, 4, 96, 4, 96, 4, 96, 4,123, 0, 0, 0,123, 2,119, 4, 96, 1,170, 0,233, 6, 20, 7, 98, 3,248, 0,123, 2, 33,
+ 0,197, 0,156, 0,127, 2,123, 0, 0, 0,180, 2, 82, 5, 78, 5, 78, 4,209, 0,102, 0,156, 0,156, 0,102, 0,156, 0,143,
+ 0,102, 0,156, 0,143, 6, 16, 0,205, 3,250, 0,131, 0,145, 2,254, 1, 72, 4, 70, 3, 63, 0,143, 0,123, 4, 76, 0,152,
+ 0,162, 0, 0, 0, 39, 0,111, 0, 0, 0,111, 3, 53, 0,106, 0,111, 0,123, 5,141, 5,141, 5,141, 5,141, 0,170, 0,170,
+ 0, 45, 5,141, 3,150, 2,123, 0,246, 0,127, 2,170, 1, 51, 2, 61, 0,156, 2,102, 1,139, 0,143, 2,246, 0,205, 0,111,
+ 3, 68, 0, 55, 0,102, 0, 29, 5,238, 0,133, 1,180, 6, 20, 0, 0, 7,125, 0,115, 5,213, 0, 0, 20, 0,183, 7, 6, 5,
+ 4, 3, 2, 1, 0, 44, 32, 16,176, 2, 37, 73,100,176, 64, 81, 88, 32,200, 89, 33, 45, 44,176, 2, 37, 73,100,176, 64, 81, 88,
+ 32,200, 89, 33, 45, 44, 32, 16, 7, 32,176, 0, 80,176, 13,121, 32,184,255,255, 80, 88, 4, 27, 5, 89,176, 5, 28,176, 3, 37,
+ 8,176, 4, 37, 35,225, 32,176, 0, 80,176, 13,121, 32,184,255,255, 80, 88, 4, 27, 5, 89,176, 5, 28,176, 3, 37, 8,225, 45,
+ 44, 75, 80, 88, 32,184, 1, 23, 69, 68, 89, 33, 45, 44,176, 2, 37, 69, 96, 68, 45, 44, 75, 83, 88,176, 2, 37,176, 2, 37, 69,
+ 68, 89, 33, 33, 45, 44, 69, 68, 45, 44,176, 2, 37,176, 2, 37, 73,176, 5, 37,176, 5, 37, 73, 96,176, 32, 99,104, 32,138, 16,
+138, 35, 58,138, 16,101, 58, 45, 0, 0, 0, 2, 0, 8, 0, 2,255,255, 0, 3, 0, 2, 0,104,254,150, 4,104, 5,164, 0, 3,
+ 0, 7, 0, 31,188, 0, 4, 1, 20, 0, 0, 0, 6, 1, 20,182, 1, 8, 5,131, 2, 4, 0, 47,196,212,236, 49, 0, 16,212,236,
+212,236, 48, 19, 17, 33, 17, 37, 33, 17, 33,104, 4, 0,252,115, 3, 27,252,229,254,150, 7, 14,248,242,114, 6, 41, 0, 0, 0,
+ 0, 2, 2, 4, 0, 0, 2,207, 5,213, 0, 5, 0, 9, 0, 31, 64, 15, 3,135, 6,134, 0,136, 8, 4, 3, 7, 1, 3, 6, 0,
+ 10, 16,212, 60,236, 50, 57, 57, 49, 0, 47,228,252,236, 48, 1, 51, 17, 3, 35, 3, 17, 51, 21, 35, 2, 4,203, 21,161, 21,203,
+203, 5,213,253,113,254,155, 1,101,253,184,254, 0, 2, 1, 82, 3,170, 3,127, 5,213, 0, 3, 0, 7, 0, 29, 64, 14, 5, 1,
+137, 4, 0,136, 8, 0, 4, 2, 6, 4, 4, 8, 16,212,236,220,236, 49, 0, 16,244, 60,236, 50, 48, 1, 17, 35, 17, 35, 17, 35,
+ 17, 3,127,174,209,174, 5,213,253,213, 2, 43,253,213, 2, 43, 0, 2, 0, 2, 0, 0, 4,205, 5,190, 0, 27, 0, 31, 0, 74,
+ 64, 48, 28, 23, 7,140, 3, 0, 25, 5, 1, 30, 21, 9,140, 19, 15, 11, 17, 13, 31, 30, 29, 28, 27, 26, 24, 23, 22, 19, 18, 17,
+ 16, 15, 14, 13, 12, 10, 9, 8, 5, 4, 3, 2, 1, 0, 26, 6, 20, 32, 16,212,204, 23, 57, 49, 0, 47, 60,212, 60, 60,252, 60,
+ 60,212, 60, 60,196, 50,236, 50, 50, 48, 1, 3, 51, 19, 51, 3, 51, 21, 33, 3, 51, 21, 33, 3, 35, 19, 35, 3, 35, 19, 33, 53,
+ 33, 19, 33, 53, 33, 19, 1, 35, 3, 51, 2,172,104,245,105,160,105,244,254,231, 84,250,254,223,104,160,105,246,105,159,104,254,
+254, 1, 41, 84,254,246, 1, 47,104, 1, 8,245, 84,246, 5,190,254, 97, 1,159,254, 97,154,254,178,153,254, 98, 1,158,254, 98,
+ 1,158,153, 1, 78,154, 1,159,253,199,254,178, 0, 3, 0,190,254,211, 4, 90, 6, 20, 0, 6, 0, 13, 0, 47, 0,100, 64, 57,
+ 8, 40, 36, 0, 7, 41, 24, 4, 37, 20, 47, 16, 23, 19, 1, 37,139, 36,142, 31, 40,143, 30, 20,139, 19,142, 1,143, 14, 33, 30,
+ 16, 4, 6, 36, 8, 44, 5, 0, 11, 6, 27, 19, 5, 40, 32, 14, 3, 0, 7, 30, 23, 15, 3, 7, 48, 16,212, 23, 60,236, 23, 50,
+252, 60,236, 16,252,228,238, 49, 0, 47,198, 50,196,238,246,238, 16,238,198,246,238, 17, 18, 57, 17, 57, 17, 18, 23, 57, 17, 18,
+ 57, 48, 1, 17, 62, 1, 53, 52, 38, 39, 17, 14, 1, 21, 20, 22, 19, 35, 3, 46, 1, 39, 53, 30, 1, 23, 17, 46, 1, 53, 52, 54,
+ 55, 53, 51, 23, 30, 1, 23, 21, 46, 1, 39, 17, 30, 1, 21, 20, 6, 7, 2,180,110,124,112,222,104,117,109,212,100, 1,102,201,
+ 98,100,203, 99,200,202,211,191,100, 1, 79,162, 84, 85,161, 80,206,216,233,188, 2, 68,254, 78, 3,116,100, 93,103,209, 1,157,
+ 4,112, 94, 86,100,251,192, 1, 45, 5, 46, 41,180, 62, 66, 2, 1,202, 31,182,150,157,187, 14,235,235, 5, 30, 26,173, 43, 47,
+ 4,254, 81, 31,194,154,154,206, 9, 0, 0, 0, 0, 5, 0, 33, 0, 0, 4,176, 5,152, 0, 11, 0, 26, 0, 30, 0, 42, 0, 57,
+ 0, 86, 64, 47, 30, 55, 29, 40, 34, 28, 15, 27, 3, 9,146, 15, 34,146, 55,147, 40,146, 46,145, 15,147, 3,146, 24, 28, 27, 43,
+ 31, 30, 29, 6, 10, 21, 11, 0, 10, 12, 37, 10, 52, 11, 31, 10, 43, 12, 58, 16,196,212,236,252,236, 16,238,254,238, 57, 57, 17,
+ 18, 57, 57, 49, 0, 47,238,238,246,238,254,238, 16,238, 17, 57, 17, 57, 17, 18, 57, 18, 57, 48, 1, 20, 22, 51, 50, 54, 53, 52,
+ 38, 35, 34, 6, 7, 52, 54, 51, 50, 22, 23, 30, 1, 21, 20, 6, 35, 34, 38, 1, 39, 1, 23, 37, 20, 22, 51, 50, 54, 53, 52, 38,
+ 35, 34, 6, 7, 52, 54, 51, 50, 22, 23, 30, 1, 21, 20, 6, 35, 34, 38, 2,184,105, 78, 77,107,108, 76, 78,105,135,184,134, 64,
+115, 46, 46, 50,186,135,136,182,254, 72, 35, 4, 18, 41,252, 23,105, 79, 77,108,108, 77, 77,107,135,184,135, 64,117, 45, 45, 49,
+186,134,135,184, 1, 63, 78,106,107, 77, 77,108,106, 79,135,185, 48, 46, 47,116, 63,133,186,183, 1, 26, 96, 1,162, 96,229, 79,
+105,107, 77, 77,107,106, 78,135,185, 48, 45, 45,117, 65,134,185,184, 0, 0, 0, 0, 2, 0, 57,255,227, 4,197, 5,240, 0, 42,
+ 0, 55, 0,179, 64, 98, 17, 16, 2, 18, 15, 23, 12, 13, 12, 14, 23, 13, 13, 12, 45, 44, 2, 46, 43, 23, 0, 1, 0, 50, 51, 52,
+ 53, 54, 5, 49, 55, 23, 1, 1, 0, 66, 55, 12, 9, 6, 1, 5, 7, 15, 49, 13, 24, 0, 43, 3, 34, 7, 49,151, 18, 34, 33, 37,
+151, 30,150, 18,153, 7, 13, 0, 40, 1, 7, 6, 3, 33, 12, 8, 4, 55, 43, 33, 24, 40, 27, 15, 33, 4, 19, 8, 40, 18, 33, 27,
+ 8, 13, 16, 27, 46, 18, 21, 56, 16,220,236,196,252,196, 16,198,238, 16,238, 17, 57, 17, 18, 57, 17, 57, 57, 17, 18, 57, 18, 23,
+ 57, 17, 57, 49, 0, 47,198,228,246,238,214,206, 16,238, 17, 18, 23, 57, 17, 18, 57, 17, 23, 57, 48, 75, 83, 88, 7, 16, 14,237,
+ 17, 23, 57, 7, 16, 14,237, 17, 23, 57, 7, 16, 5,237, 7, 16, 5,237, 17, 23, 57, 89, 34, 9, 1, 62, 1, 53, 52, 47, 1, 51,
+ 21, 20, 6, 7, 23, 35, 39, 14, 1, 35, 34, 0, 53, 52, 54, 55, 46, 1, 53, 52, 54, 51, 50, 22, 23, 21, 46, 1, 35, 34, 6, 21,
+ 20, 22, 7, 14, 1, 21, 20, 22, 51, 50, 54, 55, 62, 1, 55, 2, 35, 1,160, 39, 38, 3, 1,164, 74, 75,170,213, 78, 83,186,106,
+216,254,230,138,139, 50, 48,199,173, 65,131, 70, 59,125, 69, 97,112, 58, 54, 92, 91,200,155, 42, 92, 44, 27, 35, 16, 3,139,253,
+209, 49,150,104, 32, 70, 7, 39,161,243, 88,229,109, 70, 68, 1, 13,204,137,234,100, 72,138, 71,150,174, 24, 23,183, 39, 37, 91,
+ 77, 59,129,207, 73,163, 92,151,199, 24, 23, 15, 23, 13, 0, 0, 0, 1, 2, 16, 3,170, 2,190, 5,213, 0, 3, 0, 18,183, 1,
+ 0,136, 4, 0, 4, 2, 4, 16,212,236, 49, 0, 16,244,196, 48, 1, 17, 35, 17, 2,190,174, 5,213,253,213, 2, 43, 0, 0, 0,
+ 0, 1, 1,170,254,242, 3,117, 6, 18, 0, 13, 0, 31, 64, 15, 6,156, 0,155, 14, 13, 7, 0, 3, 18, 6, 0, 24, 10, 14, 16,
+212,236, 50,236, 17, 57, 57, 49, 0, 16,252,236, 48, 1, 6, 2, 21, 20, 18, 23, 35, 38, 2, 53, 52, 18, 55, 3,117,133,131,131,
+133,160,151,148,148,151, 6, 18,228,254, 59,230,229,254, 58,230,238, 1,195,224,223, 1,196,236, 0, 1, 1, 92,254,242, 3, 39,
+ 6, 18, 0, 13, 0, 31, 64, 15, 7,156, 0,155, 14, 7, 1, 11, 8, 0, 24, 4, 18, 11, 14, 16,212,252,236, 50, 17, 57, 57, 49,
+ 0, 16,252,236, 48, 1, 51, 22, 18, 21, 20, 2, 7, 35, 54, 18, 53, 52, 2, 1, 92,160,151,148,148,151,160,133,131,131, 6, 18,
+236,254, 60,223,225,254, 60,236,232, 1,198,227,228, 1,198, 0, 0, 1, 0,166, 2, 74, 4, 43, 5,240, 0, 17, 0, 78, 64, 44,
+ 16, 13, 11, 0, 4, 12, 9, 7, 4, 2, 4, 8, 3,157, 5, 17, 12,157, 10, 1, 14,150, 18, 8, 12, 10, 3, 9, 6, 17, 3, 1,
+ 3, 2, 0, 25, 15, 4, 11, 9, 25, 13, 6, 18, 16,212, 60,236, 50,220, 60,236, 50, 23, 57, 17, 18, 23, 57, 49, 0, 16,244,212,
+ 60,236, 50,196,236, 50, 23, 57, 18, 23, 57, 48, 1, 13, 1, 7, 37, 17, 35, 17, 5, 39, 45, 1, 55, 5, 17, 51, 17, 37, 4, 43,
+254,154, 1,102, 57,254,176,115,254,176, 57, 1,102,254,154, 57, 1, 80,115, 1, 80, 4,223,194,195, 98,203,254,135, 1,121,203,
+ 98,195,194, 99,203, 1,121,254,135,203, 0, 0, 0, 1, 0, 88, 0,113, 4,121, 4,147, 0, 11, 0, 39, 64, 20, 0,161, 9, 1,
+160, 5,161, 7, 3, 12, 2, 26, 4, 0, 28, 8, 26, 10, 6, 12, 16,212, 60,236,252, 60,236, 49, 0, 16,212, 60,236,252, 60,236,
+ 48, 1, 17, 33, 21, 33, 17, 35, 17, 33, 53, 33, 17, 2,188, 1,189,254, 67,168,254, 68, 1,188, 4,147,254, 68,170,254, 68, 1,
+188,170, 1,188, 0, 1, 1,147,254,225, 2,242, 1, 47, 0, 5, 0, 24, 64, 11, 3,163, 0,162, 6, 3, 4, 1, 29, 0, 6, 16,
+212,236,212,204, 49, 0, 16,252,236, 48, 1, 51, 21, 3, 35, 19, 1,246,252,197,154, 99, 1, 47,207,254,129, 1,127, 0, 0, 0,
+ 0, 1, 1,100, 1,223, 3,109, 2,131, 0, 3, 0, 17,182, 0,160, 2, 4, 1, 0, 4, 16,212,196, 49, 0, 16,212,236, 48, 1,
+ 33, 21, 33, 1,100, 2, 9,253,247, 2,131,164, 0, 1, 1,233, 0, 0, 2,229, 1, 49, 0, 3, 0, 16,182, 0,162, 2, 1, 29,
+ 0, 4, 16,212,236, 49, 0, 47,236, 48, 1, 51, 17, 35, 1,233,252,252, 1, 49,254,207, 0, 0, 0, 1, 0,102,255, 66, 4, 55,
+ 5,213, 0, 3, 0, 24, 64, 11, 2, 0,136, 4, 1, 30, 0, 2, 30, 3, 4, 16,212,236,212,236, 49, 0, 16,244,196, 48, 1, 51,
+ 1, 35, 3,121,190,252,238,191, 5,213,249,109, 0, 3, 0,133,255,227, 4, 76, 5,240, 0, 11, 0, 23, 0, 35, 1, 10, 64, 26,
+ 3,165, 9, 18,151, 30, 12,151, 24,150, 30,153, 36, 21, 30, 27, 6, 33, 0, 27, 34, 15, 30, 33, 31, 36, 16,252,236,236,212,236,
+ 16,238, 49, 0, 16,228,244,236, 16,238,212,238, 48, 64,214, 47, 0, 47, 1, 47, 2, 47, 3, 47, 4, 47, 5, 47, 6, 47, 7, 47,
+ 8, 47, 9, 47, 10, 47, 11, 63, 0, 63, 1, 63, 2, 63, 3, 63, 4, 63, 5, 63, 6, 63, 7, 63, 8, 63, 9, 63, 10, 63, 11, 79,
+ 0, 79, 1, 79, 2, 79, 10, 79, 11, 95, 0, 95, 1, 95, 2, 95, 10, 95, 11,159, 0,159, 1,159, 2,159, 3,159, 4,159, 5,159,
+ 6,159, 7,159, 8,159, 9,159, 10,159, 11,175, 0,175, 1,175, 2,175, 3,175, 4,175, 5,175, 6,175, 7,175, 8,175, 9,175,
+ 10,175, 11,191, 0,191, 1,191, 2,191, 3,191, 4,191, 5,191, 6,191, 7,191, 8,191, 9,191, 10,191, 11, 70, 47, 0, 47, 1,
+ 47, 2, 47, 3, 47, 4, 47, 5, 47, 6, 47, 7, 47, 8, 47, 9, 47, 10, 47, 11, 95, 0, 95, 1, 95, 2, 95, 3, 95, 4, 95, 5,
+ 95, 6, 95, 7, 95, 8, 95, 9, 95, 10, 95, 11,191, 0,191, 1,191, 2,191, 3,191, 4,191, 5,191, 6,191, 7,191, 8,191, 9,
+191, 10,191, 11, 36, 93, 1, 93, 1, 52, 54, 51, 50, 22, 21, 20, 6, 35, 34, 38, 19, 34, 2, 17, 16, 18, 51, 50, 18, 17, 16, 2,
+ 39, 50, 18, 17, 16, 2, 35, 34, 2, 17, 16, 18, 1,227, 77, 54, 56, 80, 79, 57, 56, 75,133,141,139,139,141,142,139,139,142,239,
+245,245,239,239,244,244, 2,238, 55, 80, 80, 55, 56, 78, 76, 2,156,254,208,254,201,254,202,254,208, 1, 48, 1, 54, 1, 55, 1,
+ 48,160,254,120,254,129,254,130,254,120, 1,136, 1,126, 1,127, 1,136, 0, 0, 0, 1, 0,246, 0, 0, 4, 70, 5,213, 0, 10,
+ 0, 38, 64, 20, 3,151, 4, 2,151, 5,136, 7, 0,151, 9, 8, 35, 6, 30, 3, 0, 35, 1, 11, 16,212,236,196,252,236, 49, 0,
+ 47,236, 50,244,236,212,236, 48, 37, 33, 17, 5, 53, 37, 51, 17, 33, 21, 33, 1, 14, 1, 58,254,174, 1, 80,202, 1, 54,252,200,
+170, 4,117, 76,184, 74,250,213,170, 0, 0, 0, 0, 1, 0,152, 0, 0, 4, 35, 5,240, 0, 28, 0, 81, 64, 41, 0, 28, 37, 5,
+ 6, 5, 24, 25, 26, 3, 23, 27, 37, 6, 6, 5, 66, 16, 17,167, 13,151, 20,150, 4, 0,151, 2, 0, 16, 10, 2, 1, 10, 30, 23,
+ 34, 16, 3, 36, 29, 16,252,196,252,236,192,192, 17, 18, 57, 49, 0, 47,236, 50,244,236,244,204, 48, 75, 83, 88, 7, 16, 5,237,
+ 17, 23, 57, 7, 16, 5,237, 23, 50, 89, 34, 37, 33, 21, 33, 53, 54, 0, 55, 62, 1, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51,
+ 50, 4, 21, 20, 6, 7, 14, 1, 1,117, 2,174,252,117,187, 1, 24, 53,100, 70,147,128, 91,200,112,103,199, 97,219, 1, 11, 89,
+100, 56,213,170,170,170,197, 1, 46, 62,122,151, 79,125,142, 66, 67,204, 49, 50,233,189, 96,192,116, 65,230, 0, 0, 1, 0,137,
+255,227, 4, 55, 5,240, 0, 40, 0, 71, 64, 41, 0, 19,151, 21, 10,139, 9,166, 13,151, 6, 31,139, 32,166, 28,151, 35,150, 6,
+153, 21,169, 41, 22, 19, 0, 3, 20, 25, 30, 38, 16, 30, 3, 34, 31, 20, 9, 31, 41, 16,252,196,196,252,236,212,236, 17, 23, 57,
+ 49, 0, 16,236,228,244,236,244,236, 16,238,246,238, 16,238, 57, 48, 1, 30, 1, 21, 20, 4, 35, 34, 38, 39, 53, 30, 1, 51, 50,
+ 54, 53, 52, 38, 43, 1, 53, 51, 50, 54, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 4, 21, 20, 6, 3, 8,147,156,254,235,
+245,103,214,103,102,198, 98,166,178,178,152,154,154,139,156,145,134, 89,190,104,121,189, 73,218, 1, 5,137, 3, 31, 39,199,149,
+206,235, 38, 36,201, 53, 52,150,141,130,153,166,122,109,115,123, 40, 40,186, 32, 32,219,181,123,164, 0, 0, 0, 0, 2, 0,102,
+ 0, 0, 4,111, 5,213, 0, 2, 0, 13, 0, 66, 64, 31, 1, 13, 3, 13, 0, 3, 3, 13, 66, 0, 3, 11, 7,151, 5, 1, 3,136,
+ 9, 1, 12, 10, 0, 30, 8, 4, 6, 15, 12, 36, 14, 16,252,252,212, 60,236, 50, 17, 57, 49, 0, 47,228,212, 60,236, 50, 18, 57,
+ 48, 75, 83, 88, 7, 16, 4,201, 7, 16, 5,201, 89, 34, 9, 1, 33, 3, 51, 17, 51, 21, 35, 17, 35, 17, 33, 53, 2,223,254, 41,
+ 1,215, 33,234,199,199,201,253,135, 5, 29,252,235, 3,205,252, 51,164,254,156, 1,100,191, 0, 0, 1, 0,143,255,227, 4, 45,
+ 5,213, 0, 29, 0, 61, 64, 34, 4, 7, 29, 26,151, 7, 17,139, 16,142, 20,151, 13, 2,151, 0,136, 13,153, 7,170, 30, 3, 30,
+ 0, 23, 30, 1, 10, 34, 0, 16, 31, 30, 16,252,196,252,196,236, 16,238, 49, 0, 16,228,228,244,236, 16,238,246,238, 16,254,196,
+ 18, 57, 48, 19, 33, 21, 33, 17, 62, 1, 51, 50, 0, 21, 20, 0, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 35, 34, 6,
+ 7,207, 2,244,253,196, 43, 87, 44,232, 1, 16,254,227,247,119,197, 78, 92,186, 97,167,181,187,167, 81,154, 70, 5,213,170,254,
+145, 16, 15,254,238,234,236,254,240, 32, 32,205, 50, 49,176,162,160,178, 37, 37, 0, 2, 0,133,255,227, 4, 76, 5,240, 0, 24,
+ 0, 36, 0, 61, 64, 35, 7, 31, 25,151, 10, 31,151, 16, 10,171, 4, 1,139, 0,142, 4,151, 22,150, 16,153, 37, 34, 30, 0, 38,
+ 13, 34, 7, 6, 28, 1, 19, 31, 37, 16,252,236,236,252,228,236, 49, 0, 16,228,244,236,244,236, 16,229, 16,238, 16,238, 17, 57,
+ 48, 1, 21, 46, 1, 35, 34, 2, 17, 62, 1, 51, 50, 18, 21, 20, 2, 35, 32, 2, 17, 16, 0, 33, 50, 22, 1, 34, 6, 21, 20, 22,
+ 51, 50, 54, 53, 52, 38, 3,223, 63,142, 77,192,198, 48,170,110,216,237,244,221,254,252,242, 1, 35, 1, 20, 74,148,254,221,129,
+148,148,129,134,136,136, 5,180,186, 37, 39,254,223,254,231,100,107,254,247,243,242,254,246, 1,117, 1,145, 1,122, 1,141, 31,
+253,108,186,164,164,186,177,173,174,176, 0, 0, 0, 1, 0,139, 0, 0, 4, 55, 5,213, 0, 6, 0, 53, 64, 25, 5, 37, 2, 3,
+ 2, 3, 37, 4, 5, 4, 66, 5,151, 0,136, 3, 5, 3, 1, 4, 1, 34, 0, 31, 7, 16,252,236,196, 17, 57, 57, 49, 0, 47,244,
+236, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 5,237, 89, 34, 19, 33, 21, 1, 35, 1, 33,139, 3,172,253,234,211, 2, 8,253, 53,
+ 5,213, 86,250,129, 5, 43, 0, 0, 3, 0,131,255,227, 4, 78, 5,240, 0, 11, 0, 35, 0, 47, 0, 67, 64, 37, 24, 12, 0,151,
+ 39, 6,151, 30, 45,151, 18,150, 30,153, 39,169, 48, 24, 12, 36, 42, 30, 21, 36, 30, 15, 9, 30, 21, 27, 34, 3, 30, 15, 33, 31,
+ 48, 16,252,196,236,252,196,236, 16,238, 16,238, 17, 57, 57, 49, 0, 16,236,228,244,236, 16,238, 16,238, 57, 57, 48, 1, 34, 6,
+ 21, 20, 22, 51, 50, 54, 53, 52, 38, 37, 46, 1, 53, 52, 54, 51, 50, 22, 21, 20, 6, 7, 30, 1, 21, 20, 4, 35, 34, 36, 53, 52,
+ 54, 19, 20, 22, 51, 50, 54, 53, 52, 38, 35, 34, 6, 2,104,135,147,149,133,136,147,149,254,202,129,145,242,208,209,242,145,129,
+150,159,254,254,228,228,254,255,159, 77,128,121,122,128,127,123,121,128, 2,197,151,138,138,153,151,140,137,152, 84, 33,180,127,
+178,209,209,178,127,180, 33, 33,200,159,202,228,227,201,160,201, 1, 98,120,126,126,120,122,128,129, 0, 0, 0, 0, 2, 0,127,
+255,227, 4, 70, 5,240, 0, 11, 0, 36, 0, 59, 64, 34, 19, 6, 0,151, 22,171, 16, 13,139, 12,142, 16,151, 34, 6,151, 28,150,
+ 34,153, 37, 19, 6, 3, 1, 31, 34, 9, 30, 12, 38, 25, 31, 37, 16,252,228,236,252,236,236, 49, 0, 16,228,244,236, 16,238,246,
+238, 16,245,238, 17, 57, 48, 1, 50, 54, 53, 52, 38, 35, 34, 6, 21, 20, 22, 3, 53, 30, 1, 51, 50, 18, 17, 14, 1, 35, 34, 2,
+ 53, 52, 18, 51, 32, 18, 17, 16, 0, 33, 34, 38, 2, 84,129,147,147,129,134,136,135,225, 63,142, 77,192,197, 47,170,110,216,237,
+243,222, 1, 4,242,254,221,254,235, 73,148, 2,150,186,164,164,186,177,173,174,176,253,137,186, 37, 39, 1, 33, 1, 25,100,107,
+ 1, 10,244,241, 1, 9,254,138,254,111,254,135,254,115, 31, 0, 0, 2, 1,233, 0, 0, 2,229, 4, 39, 0, 3, 0, 7, 0, 27,
+ 64, 13, 2,162, 0,172, 4,162, 6, 5, 1, 29, 4, 0, 8, 16,212, 60,236, 50, 49, 0, 47,236,244,236, 48, 1, 51, 17, 35, 17,
+ 51, 17, 35, 1,233,252,252,252,252, 4, 39,254,209,254, 57,254,207, 0, 0, 0, 0, 2, 1,147,254,225, 2,242, 4, 39, 0, 5,
+ 0, 9, 0, 37, 64, 19, 8,162, 6, 3,163, 0,162, 6,172, 10, 3, 4, 0, 29, 1, 7, 29, 6, 10, 16,212,252,212,252,212,204,
+ 49, 0, 16,228,252,236, 16,238, 48, 1, 51, 21, 3, 35, 19, 3, 51, 17, 35, 1,246,252,197,154, 99, 13,252,252, 1, 47,207,254,
+129, 1,127, 3,199,254,209, 0, 0, 1, 0, 88, 0,141, 4,121, 4,119, 0, 6, 0, 33, 64, 18, 5, 4, 2, 1, 0, 5, 3,174,
+ 6,173, 7, 1, 2, 0, 40, 4, 39, 7, 16,252,236, 50, 57, 49, 0, 16,244,236, 23, 57, 48, 9, 2, 21, 1, 53, 1, 4,121,252,
+174, 3, 82,251,223, 4, 33, 3,193,254,192,254,195,183, 1,162,166, 1,162, 0, 0, 2, 0, 88, 1, 96, 4,121, 3,162, 0, 3,
+ 0, 7, 0, 27, 64, 12, 4,160, 6, 2,160, 0, 8, 5, 1, 4, 0, 8, 16,212, 60,196, 50, 49, 0, 16,212,236,212,236, 48, 19,
+ 33, 21, 33, 17, 33, 21, 33, 88, 4, 33,251,223, 4, 33,251,223, 2, 12,172, 2, 66,170, 0, 0, 0, 1, 0, 88, 0,141, 4,121,
+ 4,119, 0, 6, 0, 33, 64, 18, 6, 5, 3, 2, 0, 5, 4,174, 1,173, 7, 6, 2, 40, 4, 0, 39, 7, 16,252, 60,236, 57, 49,
+ 0, 16,244,236, 23, 57, 48, 19, 53, 1, 21, 1, 53, 1, 88, 4, 33,251,223, 3, 82, 3,193,182,254, 94,166,254, 94,183, 1, 61,
+ 0, 2, 0,244, 0, 0, 4, 16, 5,240, 0, 30, 0, 34, 0,123, 64, 66, 11, 10, 9, 8, 7, 5, 12, 6, 37, 25, 26, 25, 3, 4,
+ 2, 2, 5, 37, 26, 26, 25, 66, 29, 26, 5, 2, 4, 6, 25, 15, 0, 31, 16,139, 15,141, 12,151, 19,150, 31,134, 33, 6, 32, 25,
+ 22, 9, 5, 1, 0, 26, 32, 9, 0, 3, 1, 9, 41, 22, 15, 1, 32, 3, 31, 35, 16,212,236,196,212,212,236, 16,238, 17, 18, 57,
+ 17, 18, 57, 17, 18, 57, 18, 57, 49, 0, 47,238,246,254,244,238, 16,205, 17, 57, 57, 23, 57, 48, 75, 83, 88, 7, 16, 4,237, 17,
+ 23, 57, 7, 16, 4,237, 17, 23, 57, 89, 34, 1, 35, 53, 52, 54, 63, 1, 62, 1, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50,
+ 22, 21, 20, 6, 15, 1, 14, 1, 29, 1, 3, 51, 21, 35, 2,172,190, 61, 84, 90, 62, 47,131,109, 78,178, 98, 94,191,104,186,221,
+ 67, 94, 88, 69, 38,197,203,203, 1,145,154, 98,137, 82, 89, 59, 88, 49, 89,110, 69, 68,188, 57, 56,192,161, 76,131, 92, 86, 66,
+ 84, 61, 47,254,242,254, 0, 0, 0, 2, 0, 27,254,193, 4,154, 5,115, 0, 11, 0, 52, 0,112, 64, 49, 40, 43, 36, 26, 23, 3,
+ 14, 12, 9, 27, 52, 3,175, 23, 9,175, 12, 17, 39, 36,175, 43, 23, 30,175, 49, 43, 53, 39, 13, 6, 40, 12, 0, 6, 43, 20, 0,
+ 26, 13, 46, 12, 20, 33, 43, 12, 45, 46, 53, 16,220,236,252,196, 16,254, 60,196, 16,238, 17, 18, 57, 17, 18, 57, 49, 0, 16,196,
+212,252,196, 16,254,196,213,196,238, 16,238, 57, 57, 17, 18, 57, 17, 18, 57, 17, 18, 57, 48, 64, 13,128, 5,128, 6,128, 7,128,
+ 19,128, 20,128, 21, 6, 1, 93, 1, 52, 38, 35, 34, 6, 21, 20, 22, 51, 50, 54, 19, 35, 53, 14, 1, 35, 34, 38, 53, 52, 54, 51,
+ 50, 22, 23, 53, 52, 38, 35, 34, 0, 17, 16, 0, 33, 50, 54, 55, 23, 14, 1, 35, 32, 0, 17, 16, 0, 33, 50, 18, 21, 4, 14,128,
+107,107,129,129,107,107,128,140,144, 37,131, 82,161,211,211,161, 80,134, 36,176,145,246,254,221, 1, 74, 1, 18, 54,108, 57, 48,
+ 63,123, 58,254,155,254, 93, 1,120, 1, 60,209,250, 2, 33,129,155,155,129,130,155,155,254,232,111, 63, 68,242,188,188,242, 70,
+ 61, 63,156,190,254,129,254,185,254,183,254,122, 20, 21,135, 25, 24, 1,210, 1,140, 1,134, 1,206,254,246,224, 0, 2, 0, 37,
+ 0, 0, 4,172, 5,213, 0, 2, 0, 10, 0,152, 64, 65, 0, 37, 1, 0, 4, 5, 4, 2, 37, 5, 4, 7, 37, 5, 4, 6, 37, 5,
+ 5, 4, 9, 37, 3, 10, 8, 37, 3, 10, 1, 37, 10, 3, 10, 0, 37, 2, 0, 3, 3, 10, 66, 0, 3, 7,151, 1,176, 3,136, 9,
+ 5, 9, 8, 7, 6, 4, 3, 2, 1, 0, 9, 5, 47, 10, 11, 16,220,236, 23, 57, 49, 0, 47, 60,228,252,236, 18, 57, 48, 75, 83,
+ 88, 7, 16, 8,237, 7, 16, 5,237, 7, 5,237, 7, 5,237, 7, 16, 5,237, 7, 5,237, 7, 5,237, 7, 16, 8,237, 89, 34,178,
+ 7, 3, 1, 1, 93, 64, 26, 10, 0, 15, 0,143, 0,143, 0, 4, 3, 1, 11, 2, 4, 3, 12, 4, 9, 7, 6, 8,134, 1,137, 2,
+ 8, 93, 0, 93, 1, 3, 33, 1, 51, 1, 35, 3, 33, 3, 35, 2,104,213, 1,170,254,177,245, 1,201,209,110,253,245,108,209, 5,
+ 35,253, 4, 3,174,250, 43, 1,133,254,123, 0, 0, 3, 0,166, 0, 0, 4,113, 5,213, 0, 8, 0, 17, 0, 32, 0, 61, 64, 35,
+ 25, 0,151, 10, 9,151, 18,136, 1,151, 10,177, 31, 17, 11, 25, 31, 19, 8, 2, 5, 0, 14, 30, 22, 5, 50, 28, 49, 9, 0, 30,
+ 18, 48, 33, 16,252,236, 50,252,236,212,236, 17, 23, 57, 57, 57, 49, 0, 47,236,236,244,236, 16,238, 57, 48, 1, 17, 51, 50, 54,
+ 53, 52, 38, 35, 3, 17, 51, 50, 54, 53, 52, 38, 35, 37, 33, 50, 22, 21, 20, 6, 7, 30, 1, 21, 20, 4, 41, 1, 1,113,239,176,
+150,158,168,239,235,146,131,129,148,254, 74, 1,186,229,248,131,131,147,167,254,246,254,249,254, 70, 2,201,253,221,123,141,146,
+137, 2,102,254, 62,112,125,113,100,166,198,181,137,158, 20, 22,207,160,203,207, 0, 1, 0,139,255,227, 4, 49, 5,240, 0, 25,
+ 0, 46, 64, 26, 25,179, 0,178, 22,151, 3, 13,179, 12,178, 16,151, 9,150, 3,153, 26, 19, 50, 12, 0, 49, 6, 48, 26, 16,252,
+236, 50,236, 49, 0, 16,228,244,236,244,236, 16,238,246,238, 48, 37, 14, 1, 35, 32, 0, 17, 16, 0, 33, 50, 22, 23, 21, 46, 1,
+ 35, 34, 2, 17, 16, 18, 51, 50, 54, 55, 4, 49, 77,162, 91,254,225,254,195, 1, 63, 1, 29, 91,162, 77, 74,170, 86,197,196,196,
+197, 88,169, 73, 53, 41, 41, 1,150, 1,112, 1,110, 1,153, 41, 41,207, 61, 64,254,208,254,205,254,206,254,208, 64, 61, 0, 0,
+ 0, 2, 0,137, 0, 0, 4, 82, 5,213, 0, 8, 0, 17, 0, 40, 64, 21, 6,151, 9,136, 0,151, 15, 6, 0, 15, 9, 7, 3, 50,
+ 12, 49, 7, 30, 16, 48, 18, 16,252,236,252,236, 17, 57, 57, 57, 57, 49, 0, 47,236,244,236, 48, 37, 32, 54, 17, 16, 38, 33, 35,
+ 17, 19, 32, 0, 17, 16, 0, 41, 1, 17, 1,180, 0,255,202,201,255, 0, 96,100, 1, 86, 1, 68,254,188,254,170,254,209,166,251,
+ 1, 72, 1, 75,251,251,119, 5, 47,254,148,254,128,254,130,254,149, 5,213, 0, 0, 1, 0,197, 0, 0, 4, 78, 5,213, 0, 11,
+ 0, 41, 64, 22, 6,151, 4, 2,151, 0,136, 8,151, 4,177, 10, 1, 5, 9, 49, 7, 3, 30, 0, 51, 12, 16,252,236, 50,252,196,
+196, 49, 0, 47,236,236,244,236, 16,238, 48, 19, 33, 21, 33, 17, 33, 21, 33, 17, 33, 21, 33,197, 3,118,253, 84, 2,142,253,114,
+ 2,191,252,119, 5,213,170,254, 70,170,253,227,170, 0, 0, 0, 0, 1, 0,233, 0, 0, 4, 88, 5,213, 0, 9, 0, 36, 64, 19,
+ 6,151, 4, 2,151, 0,136, 4,177, 8, 5, 1, 49, 7, 3, 30, 0, 52, 10, 16,252,236, 50,252,196, 49, 0, 47,236,244,236, 16,
+238, 48, 19, 33, 21, 33, 17, 33, 21, 33, 17, 35,233, 3,111,253, 92, 2,101,253,155,203, 5,213,170,254, 72,170,253, 55, 0, 0,
+ 0, 1, 0,102,255,227, 4, 80, 5,240, 0, 29, 0, 60, 64, 33, 25, 26, 0, 22, 3, 26,151, 28, 22,151, 3, 13,179, 12,178, 16,
+151, 9,150, 3,153, 30, 27, 25, 30, 12, 0, 54, 19, 50, 6, 53, 30, 16,252,236,252,196,252,196, 49, 0, 16,228,244,236,244,236,
+ 16,254,212,238, 17, 18, 57, 17, 57, 48, 37, 14, 1, 35, 32, 0, 17, 16, 0, 33, 50, 22, 23, 21, 46, 1, 35, 34, 2, 17, 16, 18,
+ 51, 50, 54, 55, 17, 35, 53, 33, 4, 80, 81,203,118,254,228,254,196, 1, 64, 1, 29, 94,172, 80, 81,170, 95,197,197,191,198, 67,
+101, 41,217, 1,154,123, 75, 77, 1,151, 1,111, 1,110, 1,153, 53, 54,207, 77, 73,254,207,254,206,254,201,254,213, 31, 33, 1,
+145,166, 0, 0, 0, 1, 0,137, 0, 0, 4, 72, 5,213, 0, 11, 0, 38, 64, 20, 8,151, 2,177, 4, 0,136, 10, 6, 7, 3, 30,
+ 5, 49, 9, 1, 30, 0, 48, 12, 16,252,236, 50,252,236, 50, 49, 0, 47, 60,228, 50,252,236, 48, 19, 51, 17, 33, 17, 51, 17, 35,
+ 17, 33, 17, 35,137,203, 2, 41,203,203,253,215,203, 5,213,253,156, 2,100,250, 43, 2,199,253, 57, 0, 0, 0, 0, 1, 0,201,
+ 0, 0, 4, 6, 5,213, 0, 11, 0, 37, 64, 19, 10, 2,151, 0,136, 8, 4,151, 6, 5, 1, 55, 3, 30, 7, 0, 55, 9, 12, 16,
+212,236, 50,252,236, 50, 49, 0, 47,236, 50,244,236, 50, 48, 19, 33, 21, 33, 17, 33, 21, 33, 53, 33, 17, 33,201, 3, 61,254,199,
+ 1, 57,252,195, 1, 57,254,199, 5,213,170,251,127,170,170, 4,129, 0, 0, 0, 0, 1, 0,109,255,227, 3,188, 5,213, 0, 17,
+ 0, 44, 64, 23, 12, 7, 8, 1, 0,178, 4,151, 15, 8,151, 10,136, 15,153, 18, 9, 7, 30, 11, 0, 53, 18, 16,252,212,252,196,
+ 49, 0, 16,228,244,236, 16,238,246,206, 17, 57, 57, 48, 55, 53, 30, 1, 51, 50, 54, 53, 17, 33, 53, 33, 17, 16, 6, 35, 34, 38,
+109, 91,194,104,143,113,254,131, 2, 71,211,247, 96,190, 61,236, 81, 81,149,203, 3, 68,170,252, 18,254,230,234, 44, 0, 0, 0,
+ 0, 1, 0,137, 0, 0, 4,201, 5,213, 0, 11, 0,151, 64, 33, 8, 37, 9, 8, 5, 6, 5, 7, 37, 6, 5, 66, 8, 5, 2, 3,
+ 3, 0,180, 10, 6, 8, 5, 4, 3, 6, 1, 9, 1, 30, 0, 48, 12, 16,252,236, 50, 16,192, 23, 57, 49, 0, 47, 60,236, 50, 23,
+ 57, 48, 75, 83, 88, 7, 5,237, 7, 16, 8,237, 89, 34,178, 8, 4, 1, 1, 93, 64, 76, 7, 5, 22, 5, 23, 8, 38, 5, 38, 8,
+ 54, 2, 70, 2, 85, 2, 87, 8, 88, 9,100, 2,122, 5,121, 8,123, 9, 14, 2, 3, 1, 4, 7, 5, 0, 6, 2, 7, 22, 5, 23,
+ 8, 39, 5, 44, 6, 43, 7, 38, 8, 58, 3, 73, 3, 71, 6, 71, 7, 91, 3, 87, 5, 88, 6, 88, 7, 87, 8,107, 3,122, 3,120,
+ 7, 23, 93, 0, 93, 19, 51, 17, 1, 51, 9, 1, 35, 1, 7, 17, 35,137,203, 2,119,237,253,187, 2, 86,244,254, 25,154,203, 5,
+213,253,104, 2,152,253,158,252,141, 2,236,164,253,184, 0, 0, 0, 1, 0,215, 0, 0, 4,115, 5,213, 0, 5, 0, 24, 64, 12,
+ 2,151, 0,136, 4, 1, 30, 3, 49, 0, 52, 6, 16,252,236,236, 49, 0, 47,228,236, 48, 19, 51, 17, 33, 21, 33,215,203, 2,209,
+252,100, 5,213,250,213,170, 0, 0, 1, 0, 86, 0, 0, 4,121, 5,213, 0, 12, 0,133, 64, 44, 8, 2, 3, 2, 7, 3, 3, 2,
+ 10, 1, 2, 1, 9, 2, 2, 1, 66, 10, 7, 2, 3, 0, 8, 3, 0,180, 11, 5, 9, 8, 3, 2, 1, 5, 10, 6, 6, 4, 47, 10,
+ 6, 0, 48, 13, 16,252,236,252,236, 17, 23, 57, 49, 0, 47, 60,236, 50,196, 17, 23, 57, 48, 75, 83, 88, 7, 16, 5,201, 7, 16,
+ 4,201, 7, 16, 4,201, 7, 16, 5,201, 89, 34,178, 15, 10, 1, 0, 93, 64, 36, 5, 8, 10, 9, 23, 1, 24, 3, 23, 8, 24, 9,
+ 38, 1, 41, 3, 38, 8, 41, 9, 54, 1, 57, 3, 54, 8, 56, 9, 14, 15, 7, 15, 7, 15, 10, 3, 93, 1, 93, 19, 33, 9, 1, 33,
+ 17, 35, 17, 1, 35, 1, 17, 35, 86, 1, 14, 1, 2, 1, 4, 1, 15,187,254,246,153,254,245,186, 5,213,253, 8, 2,248,250, 43,
+ 5, 39,252,237, 3, 19,250,217, 0, 1, 0,139, 0, 0, 4, 70, 5,213, 0, 9, 0,109, 64, 28, 7, 1, 2, 1, 2, 6, 7, 6,
+ 66, 7, 2, 3, 0,180, 8, 5, 6, 1, 7, 2, 17, 4, 49, 7, 17, 0, 48, 10, 16,252,236,252,236, 17, 57, 57, 49, 0, 47, 60,
+236, 50, 57, 57, 48, 75, 83, 88, 7, 16, 4,201, 7, 16, 4,201, 89, 34,178, 23, 1, 1, 1, 93, 64, 38, 23, 2, 24, 7, 41, 2,
+ 38, 7, 56, 7, 87, 2,100, 2,106, 7,117, 2,122, 7, 10, 24, 6, 38, 1, 41, 6, 70, 1, 73, 6, 87, 1,103, 1,104, 6, 8,
+ 93, 0, 93, 19, 33, 1, 17, 51, 17, 33, 1, 17, 35,139, 1, 0, 1,248,195,255, 0,254, 8,195, 5,213,251, 51, 4,205,250, 43,
+ 4,205,251, 51, 0, 2, 0,117,255,227, 4, 92, 5,240, 0, 11, 0, 23, 0, 35, 64, 19, 9,151, 15, 3,151, 21,150, 15,153, 24,
+ 0, 50, 12, 54, 6, 50, 18, 53, 24, 16,252,236,252,236, 49, 0, 16,228,244,236, 16,238, 48, 1, 16, 2, 35, 34, 2, 17, 16, 18,
+ 51, 50, 18, 19, 16, 2, 35, 34, 2, 17, 16, 18, 51, 50, 18, 3,137,135,154,153,135,135,153,154,135,211,247,253,253,246,247,252,
+253,247, 2,233, 1, 73, 1, 26,254,230,254,183,254,184,254,230, 1, 25, 1, 73,254,122,254,128, 1,126, 1,136, 1,135, 1,128,
+254,128, 0, 0, 0, 2, 0,197, 0, 0, 4,117, 5,213, 0, 8, 0, 19, 0, 43, 64, 24, 1,151, 16, 0,151, 9,136, 18, 16, 10,
+ 8, 2, 4, 0, 5, 50, 13, 56, 17, 0, 30, 9, 51, 20, 16,252,236, 50,252,236, 17, 23, 57, 49, 0, 47,244,236,212,236, 48, 1,
+ 17, 51, 50, 54, 53, 52, 38, 35, 37, 33, 50, 4, 21, 20, 4, 43, 1, 17, 35, 1,143,234,140,157,156,141,254, 76, 1,180,250, 1,
+ 2,254,255,251,234,202, 5, 47,253,207,148,133,133,147,166,227,219,221,226,253,168, 0, 0, 0, 0, 2, 0,117,254,242, 4, 92,
+ 5,240, 0, 17, 0, 29, 0, 61, 64, 32, 0, 30, 16, 17, 15, 27,151, 3, 21,151, 9,150, 3,153, 17, 30, 17, 24, 16, 12, 15, 0,
+ 24, 18, 50, 12, 54, 24, 50, 6, 53, 30, 16,252,236,252,236, 17, 57, 57, 17, 57, 17, 57, 49, 0, 16,196,228,244,236, 16,238, 57,
+ 18, 57, 18, 57, 48, 5, 34, 6, 35, 34, 2, 17, 16, 18, 51, 50, 18, 17, 16, 2, 7, 23, 7, 19, 16, 2, 35, 34, 2, 17, 16, 18,
+ 51, 50, 18, 2,143, 7, 26, 8,250,247,247,252,253,247,137,139,200,151, 16,135,154,153,135,135,153,154,135, 27, 2, 1,128, 1,
+134, 1,135, 1,128,254,128,254,121,254,218,254,153, 72,190,100, 3,247, 1, 73, 1, 26,254,230,254,183,254,184,254,230, 1, 25,
+ 0, 2, 0,143, 0, 0, 4,209, 5,213, 0, 19, 0, 28, 0,106, 64, 56, 9, 8, 7, 3, 10, 6, 37, 3, 4, 3, 5, 37, 4, 4,
+ 3, 66, 6, 4, 0, 21, 3, 4, 21,151, 9, 20,151, 13,136, 11, 4, 5, 17, 22, 9, 6, 3, 10, 3, 17, 0, 28, 14, 3, 10, 25,
+ 50, 4, 17, 49, 20, 10, 30, 12, 48, 29, 16,252,236, 50,252,196,236, 17, 23, 57, 17, 57, 17, 23, 57, 17, 57, 49, 0, 47, 60,244,
+236,212,236, 18, 57, 18, 57, 18, 57, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 14,237, 17, 23, 57, 89, 34, 1, 30, 1, 23, 19, 35,
+ 3, 46, 1, 43, 1, 17, 35, 17, 33, 50, 4, 21, 20, 6, 1, 17, 51, 50, 54, 53, 52, 38, 35, 2,248, 78,110, 82,203,217,178, 77,
+123, 99,193,203, 1,160,246, 1, 6,161,253,208,221,145,142,151,144, 2,193, 20,111,166,254,104, 1,121,161, 93,253,137, 5,213,
+222,210,148,187, 2, 89,253,238,130,134,129,137, 0, 1, 0,139,255,227, 4, 74, 5,240, 0, 39, 0,132, 64, 61, 13, 12, 2, 14,
+ 11, 37, 30, 31, 30, 8, 9, 2, 7, 10, 37, 31, 31, 30, 66, 10, 11, 30, 31, 4, 1, 21,179, 20,167, 24,151, 17, 1,179, 0,167,
+ 4,151, 37,150, 17,153, 40, 30, 10, 11, 31, 27, 7, 0, 38, 27, 57, 14, 49, 20, 7, 57, 34, 48, 40, 16,252,236,196,252,236,228,
+ 17, 18, 57, 57, 57, 57, 49, 0, 16,228,244,236,244,236, 16,238,246,238, 17, 23, 57, 48, 75, 83, 88, 7, 16, 14,237, 17, 23, 57,
+ 7, 16, 14,237, 17, 23, 57, 89, 34,178, 8, 2, 1, 1, 93, 64, 10, 7, 0, 7, 1, 7, 2, 3, 7, 2, 1, 93, 0, 93, 1, 21,
+ 46, 1, 35, 34, 6, 21, 20, 22, 31, 1, 30, 1, 21, 20, 4, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 47, 1, 46, 1,
+ 53, 52, 36, 51, 50, 22, 3,244, 92,185, 94,143,166,109,149,106,210,192,254,248,252,105,212,107,115,205,104,153,170,117,145,108,
+208,188, 1, 13,223, 86,190, 5,162,205, 59, 60,133,113, 99,104, 35, 24, 49,210,181,213,224, 45, 45,215, 73, 68,137,123,112,118,
+ 32, 25, 47,190,160,200,241, 39, 0, 1, 0, 47, 0, 0, 4,162, 5,213, 0, 7, 0, 28, 64, 14, 6, 2,151, 0,136, 4, 1, 58,
+ 3, 30, 0, 58, 5, 8, 16,212,236,252,236, 49, 0, 47,244,236, 50, 48, 19, 33, 21, 33, 17, 35, 17, 33, 47, 4,115,254, 45,203,
+254, 43, 5,213,170,250,213, 5, 43, 0, 0, 0, 0, 1, 0,147,255,227, 4, 61, 5,213, 0, 29, 0, 41, 64, 23, 15, 3, 18, 0,
+ 4, 1, 9,151, 24,153, 16, 1,136, 30, 15, 30, 17, 49, 2, 30, 0, 48, 30, 16,252,236,252,236, 49, 0, 16,228, 50,244,236, 17,
+ 23, 57, 48, 19, 17, 51, 17, 20, 22, 23, 30, 1, 51, 50, 54, 55, 62, 1, 53, 17, 51, 17, 20, 6, 7, 14, 1, 35, 34, 38, 39, 46,
+ 1,147,203, 12, 15, 32,121, 86, 87,120, 33, 15, 12,202, 57, 70, 66,170,106,105,170, 67, 69, 58, 2, 61, 3,152,252, 12,109, 93,
+ 25, 59, 60, 60, 59, 25, 92,108, 3,246,252,104,229,193, 63, 59, 58, 58, 59, 62,197, 0, 0, 0, 0, 1, 0, 57, 0, 0, 4,152,
+ 5,213, 0, 6, 0, 76, 64, 41, 1, 37, 2, 3, 2, 0, 37, 6, 0, 3, 3, 2, 0, 37, 1, 0, 4, 5, 4, 6, 37, 5, 5, 4,
+ 66, 0, 5, 1,180, 3, 6, 4, 3, 1, 0, 5, 2, 47, 5, 48, 7, 16,252,236, 23, 57, 49, 0, 47,236, 50, 57, 48, 75, 83, 88,
+ 7, 16, 5,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,237, 89, 34, 37, 1, 51, 1, 35, 1, 51, 2,104, 1, 95,209,254, 75,
+245,254, 75,209,170, 5, 43,250, 43, 5,213, 0, 0, 1, 0, 0, 0, 0, 4,209, 5,213, 0, 12, 0,225, 64, 68, 5, 6, 5, 9,
+ 10, 9, 4, 10, 9, 3, 10, 11, 10, 2, 1, 2, 11, 11, 10, 6, 37, 7, 8, 7, 5, 37, 4, 5, 8, 8, 7, 2, 37, 3, 2, 12,
+ 0, 12, 1, 37, 0, 12, 66, 10, 5, 2, 3, 8, 3, 6, 0,180, 11, 8, 12, 11, 10, 9, 8, 6, 5, 4, 3, 2, 1, 11, 7, 0,
+ 47,204, 23, 57, 49, 0, 47, 60,252, 60,196, 17, 23, 57, 48, 75, 83, 88, 7, 5,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,
+237, 7, 16, 8,201, 7, 16, 5,201, 7, 5,201, 7, 16, 8,201, 89, 34,178, 24, 9, 1, 1, 93, 64, 94, 31, 3, 31, 4, 31, 10,
+ 47, 3, 47, 4, 43, 10, 63, 3, 63, 4, 56, 10, 90, 2, 90, 5, 11, 23, 11, 38, 2, 42, 3, 37, 4, 42, 5, 40, 8, 43, 9, 37,
+ 11, 38, 12, 53, 2, 58, 3, 53, 4, 58, 5, 59, 8, 58, 9, 52, 11, 54, 12, 84, 0, 84, 1, 90, 2, 88, 3, 87, 4, 86, 5, 91,
+ 6, 91, 7, 82, 8, 87, 9, 88, 11, 93, 12,103, 8,104, 12,121, 3,118, 4,121, 9,118, 11, 35, 93, 0, 93, 17, 51, 27, 1, 51,
+ 27, 1, 51, 3, 35, 11, 1, 35,197,143,170,211,172,143,197,223,191,203,202,191, 5,213,251, 68, 3, 34,252,220, 4,190,250, 43,
+ 3,119,252,137, 0, 1, 0, 18, 0, 0, 4,190, 5,213, 0, 11, 0,198, 64, 75, 9, 37, 10, 11, 10, 8, 37, 7, 8, 11, 11, 10,
+ 8, 37, 9, 8, 5, 6, 5, 7, 37, 6, 6, 5, 3, 37, 4, 5, 4, 2, 37, 1, 2, 5, 5, 4, 2, 37, 3, 2, 11, 0, 11, 1,
+ 37, 0, 0, 11, 66, 11, 8, 5, 2, 4, 3, 0,180, 9, 6, 11, 8, 7, 5, 2, 5, 0, 4, 59, 6, 47, 0, 59, 10, 48, 12, 16,
+252,228,252,228, 17, 23, 57, 49, 0, 47, 60,236, 50, 23, 57, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 8,237, 7, 16, 8,237, 7,
+ 16, 5,237, 7, 16, 5,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,237, 89, 34,178, 55, 2, 1, 0, 93, 64, 56, 13, 5, 4,
+ 11, 24, 5, 39, 1, 40, 3, 41, 5, 38, 11, 88, 11,120, 2,121, 5,119, 11, 11, 0, 2, 0, 2, 15, 8, 15, 8, 20, 2, 26, 8,
+ 33, 2, 37, 5, 43, 8, 37, 11, 53, 2, 85, 2, 89, 8, 88, 11,101, 2,115, 2, 16, 93, 1, 93, 19, 51, 9, 1, 51, 9, 1, 35,
+ 9, 1, 35, 1, 86,217, 1, 72, 1, 78,217,254, 65, 1,223,217,254,146,254,117,218, 1,244, 5,213,253,205, 2, 51,253, 66,252,
+233, 2,131,253,125, 3, 23, 0, 0, 1, 0, 37, 0, 0, 4,172, 5,213, 0, 8, 0, 89, 64, 46, 3, 37, 4, 5, 4, 2, 37, 1,
+ 2, 5, 5, 4, 2, 37, 3, 2, 8, 0, 8, 1, 37, 0, 0, 8, 66, 2, 3, 0,180, 6, 2, 7, 3, 5, 4, 1, 7, 0, 4, 60,
+ 5, 30, 0, 60, 7, 9, 16,212,236,252,236, 17, 18, 57, 17, 18, 57, 17, 57, 49, 0, 47,236, 50, 57, 48, 75, 83, 88, 7, 16, 5,
+237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,237, 89, 34, 19, 51, 9, 1, 51, 1, 17, 35, 17, 37,215, 1,108, 1,107,217,254,
+ 33,203, 5,213,253,109, 2,147,252,201,253, 98, 2,158, 0, 0, 0, 1, 0,156, 0, 0, 4,145, 5,213, 0, 9, 0, 69, 64, 28,
+ 8, 37, 2, 3, 2, 3, 37, 7, 8, 7, 66, 8,151, 0,136, 3,151, 5, 8, 3, 0, 1, 4, 47, 0, 6, 48, 10, 16,252,196,252,
+196, 17, 57, 57, 49, 0, 47,236,244,236, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 5,237, 89, 34,178, 8, 8, 1, 1, 93,178, 7,
+ 3, 1, 93, 19, 33, 21, 1, 33, 21, 33, 53, 1, 33,178, 3,201,252,244, 3, 34,252, 11, 2,247,253, 31, 5,213,154,251,111,170,
+154, 4,145, 0, 0, 1, 1,207,254,242, 3,119, 6, 20, 0, 7, 0, 30, 64, 15, 4,182, 6,183, 2,182, 0,181, 8, 5, 1, 3,
+ 61, 0, 8, 16,212,252,196, 50, 49, 0, 16,252,236,244,236, 48, 1, 33, 21, 35, 17, 51, 21, 33, 1,207, 1,168,240,240,254, 88,
+ 6, 20,143,249,252,143, 0, 0, 0, 1, 0,102,255, 66, 4, 55, 5,213, 0, 3, 0, 24, 64, 11, 1, 0,136, 4, 1, 30, 2, 0,
+ 30, 3, 4, 16,212,236,212,236, 49, 0, 16,244,196, 48, 9, 1, 35, 1, 1, 37, 3, 18,190,252,237, 5,213,249,109, 6,147, 0,
+ 0, 1, 1, 90,254,242, 3, 2, 6, 20, 0, 7, 0, 30, 64, 15, 3,182, 1,183, 5,182, 0,181, 8, 0, 61, 6, 2, 4, 8, 16,
+212,196, 50,236, 49, 0, 16,252,236,244,236, 48, 1, 17, 33, 53, 51, 17, 35, 53, 3, 2,254, 88,240,240, 6, 20,248,222,143, 6,
+ 4,143, 0, 0, 0, 1, 0, 72, 3,168, 4,137, 5,213, 0, 6, 0, 24, 64, 10, 3, 4, 1, 0,136, 7, 3, 1, 5, 7, 16,212,
+204, 57, 49, 0, 16,244,204, 50, 57, 48, 9, 1, 35, 9, 1, 35, 1, 2,193, 1,200,178,254,145,254,146,178, 1,200, 5,213,253,
+211, 1,139,254,117, 2, 45, 0, 0, 1, 0, 0,254, 29, 4,209,254,109, 0, 3, 0, 15,181, 0,184, 1, 4, 0, 2, 47,204, 49,
+ 0, 16,212,236, 48, 1, 21, 33, 53, 4,209,251, 47,254,109, 80, 80, 0, 0, 0, 0, 1, 1, 23, 4,238, 2,246, 6,102, 0, 3,
+ 0, 37, 64, 9, 1,186, 0,185, 4, 1, 60, 3, 4, 16,212,236, 49, 0, 16,244, 75,176, 9, 84, 75,176, 14, 84, 91, 88,185, 0,
+ 0, 0, 64, 56, 89,236, 48, 9, 1, 35, 1, 1,221, 1, 25,154,254,187, 6,102,254,136, 1,120, 0, 2, 0,133,255,227, 4, 35,
+ 4,123, 0, 11, 0, 41, 0,110, 64, 42, 10, 7, 0, 26, 32, 12, 24, 15, 7, 0,182, 24, 7,140, 18, 33,139, 32,191, 29,140, 36,
+190, 18,153, 24, 13, 1, 24, 4, 25, 14, 10, 6, 12, 68, 32, 4, 6, 21, 62, 42, 16,244,236,196,252,236, 50, 50, 17, 57, 57, 49,
+ 0, 47,196,228,244,252,244,236, 16,238, 16,238, 17, 57, 17, 57, 18, 57, 17, 18, 57, 48, 64, 29, 48, 31, 48, 32, 48, 33, 48, 34,
+160, 0,160, 1,160, 2,160, 10,160, 11,162, 22,160, 23,160, 24,160, 25,160, 26, 14, 93, 1, 35, 34, 6, 21, 20, 22, 51, 50, 54,
+ 55, 53, 55, 17, 35, 53, 14, 1, 35, 34, 38, 53, 52, 54, 59, 1, 53, 46, 1, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 23, 30, 1,
+ 2,190, 61,161,163,122,108,152,174, 1,185,185, 59,179,128,171,204,251,243,247, 1,134,147, 94,192, 91,102,187, 88,139,197, 61,
+ 38, 32, 2, 51,113,112,101,112,211,186, 41, 76,253,129,166,100, 95,193,162,187,194, 29,134,121, 54, 52,184, 39, 39, 82, 82, 50,
+147, 0, 0, 0, 0, 2, 0,193,255,227, 4, 88, 6, 20, 0, 11, 0, 28, 0, 48, 64, 26, 24, 12, 9, 3,140, 15, 9,140, 21,153,
+ 15,190, 27,155, 25, 0, 18, 18, 71, 24, 12, 6, 6, 26, 70, 29, 16,244,236, 50, 50,252,236, 49, 0, 47,236,228,244,236, 16,238,
+ 17, 57, 57, 48, 1, 52, 38, 35, 34, 6, 21, 20, 22, 51, 50, 54, 1, 62, 1, 51, 50, 18, 17, 16, 2, 35, 34, 38, 39, 21, 35, 17,
+ 51, 3,150,136,133,134,138,138,134,133,136,253,227, 44,155,102,202,232,233,203,100,153, 46,184,184, 2, 47,214,218,219,213,212,
+220,218, 2,120, 82, 88,254,201,254,239,254,235,254,197, 87, 83,141, 6, 20, 0, 0, 1, 0,195,255,227, 4, 37, 4,123, 0, 25,
+ 0, 47, 64, 26, 12,139, 13,192, 16, 0,139, 25,192, 22,140, 3, 16,140, 9,190, 3,153, 26, 19, 18, 12, 0, 6, 70, 26, 16,244,
+196, 50,236, 49, 0, 16,228,244,236, 16,254,244,238, 16,245,238, 48, 37, 14, 1, 35, 32, 0, 17, 16, 0, 33, 50, 22, 23, 21, 46,
+ 1, 35, 34, 6, 21, 20, 22, 51, 50, 54, 55, 4, 37, 74,157, 82,254,252,254,219, 1, 37, 1, 4, 81,154, 78, 73,147, 93,173,186,
+187,172, 96,152, 65, 57, 43, 43, 1, 56, 1, 20, 1, 20, 1, 56, 42, 44,193, 65, 58,224,208,207,225, 59, 62, 0, 0, 2, 0,123,
+255,227, 4, 18, 6, 20, 0, 16, 0, 28, 0, 48, 64, 26, 5, 0, 20, 26,140, 14, 20,140, 8,153, 14,190, 1,155, 3, 23, 4, 0,
+ 6, 2, 71, 17, 18, 11, 72, 29, 16,244,236,252,236, 50, 50, 49, 0, 47,236,228,244,236, 16,238, 17, 57, 57, 48, 1, 17, 51, 17,
+ 35, 53, 14, 1, 35, 34, 2, 17, 16, 18, 51, 50, 22, 1, 20, 22, 51, 50, 54, 53, 52, 38, 35, 34, 6, 3, 90,184,184, 46,153,100,
+203,233,234,202,101,154,254, 15,136,133,133,139,139,133,133,136, 3,209, 2, 67,249,236,141, 83, 87, 1, 59, 1, 21, 1, 17, 1,
+ 55, 87,254, 11,214,218,220,212,213,219,218, 0, 0, 2, 0,123,255,227, 4, 88, 4,123, 0, 21, 0, 28, 0, 69, 64, 38, 0, 22,
+ 3, 1, 10,139, 9,141, 6, 22,182, 1, 6,140, 13, 1,193, 25,140, 19,190, 13,153, 29, 3, 2, 28, 16, 9, 22, 6, 0, 73, 28,
+ 18, 16, 72, 29, 16,244,236,252,236,196, 17, 18, 57, 57, 49, 0, 16,228,244,236,228, 16,238, 16,238, 16,244,238, 18, 57, 17, 57,
+ 48, 1, 21, 33, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 32, 0, 17, 16, 0, 51, 50, 18, 7, 46, 1, 35, 34, 6, 7, 4, 88,
+252,227,191,174, 88,192,109,105,195, 91,254,251,254,218, 1, 32,240,214,247,184, 4,145,136,133,172, 16, 2, 94, 90, 6,183,200,
+ 56, 57,183, 43, 43, 1, 57, 1, 19, 1, 12, 1, 64,254,222,197,162,169,176,156, 0, 1, 0,195, 0, 0, 4, 39, 6, 20, 0, 19,
+ 0, 52, 64, 26, 5, 16, 1, 12, 8,182, 6, 1,140, 0,155, 14, 6,194, 10, 2, 19, 7, 0, 9, 5, 6, 13, 15, 11, 20, 16,212,
+ 60,196,252, 60,196, 50, 57, 57, 49, 0, 47,228, 50,252,236, 16,238, 50, 18, 57, 57, 48, 1, 21, 35, 34, 6, 29, 1, 33, 21, 33,
+ 17, 35, 17, 33, 53, 33, 53, 52, 54, 51, 4, 39,209, 99, 77, 1,129,254,127,184,254,213, 1, 43,169,179, 6, 20,153, 81,103, 99,
+143,252, 47, 3,209,143, 78,184,174, 0, 0, 0, 0, 2, 0,123,254, 72, 4, 18, 4,123, 0, 11, 0, 41, 0, 72, 64, 39, 25, 12,
+ 30, 27, 39, 9, 3, 18,139, 19, 22, 9,140, 30, 22,140, 15, 3,140, 36,190, 30, 15,195, 40,194, 42, 39, 25, 0, 6, 12, 71, 6,
+ 18, 18, 33, 72, 42, 16,244,196,236,252,236, 50, 50, 49, 0, 16,228,228,196,244,236, 16,238, 16,238, 16,213,238, 17, 18, 57, 57,
+ 17, 57, 57, 48, 1, 52, 38, 35, 34, 6, 21, 20, 22, 51, 50, 54, 19, 20, 2, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 61, 2, 14,
+ 1, 35, 34, 2, 17, 16, 18, 51, 50, 22, 23, 53, 51, 3, 90,135,129,135,142,143,136,127,135,184,238,231, 76,166, 83, 98,160, 67,
+149,136, 44,152,109,196,234,234,196,108,150, 47,184, 2, 57,207,215,215,207,207,217,218,254,221,252,254,252, 28, 27,182, 46, 44,
+162,176, 8,125, 94, 92, 1, 58, 1, 7, 1, 8, 1, 58, 86, 90,145, 0, 0, 0, 0, 1, 0,195, 0, 0, 4, 27, 6, 20, 0, 19,
+ 0, 44, 64, 24, 9, 14, 3, 0, 3, 1, 6,140, 17,190, 12,155, 10, 1, 2, 6, 0, 74, 13, 9, 6, 11, 70, 20, 16,244,236, 50,
+252,236, 49, 0, 47, 60,236,244,236, 17, 23, 57, 57, 48, 1, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 17, 62, 1, 51,
+ 50, 22, 4, 27,185,106,113,129,139,184,184, 49,168,115,171,169, 2,182,253, 74, 2,182,151,142,183,171,253,135, 6, 20,253,164,
+ 96, 99,225, 0, 0, 2, 0,178, 0, 0, 4, 68, 6, 20, 0, 9, 0, 13, 0, 46, 64, 25, 8,182, 0, 12,196, 10,155, 0,194, 6,
+ 2,182, 4, 3, 76, 11, 1, 6, 5, 76, 0, 75, 10, 7, 14, 16,212, 60,228,236,252, 60,236, 49, 0, 47,236, 50,228,252,236, 16,
+238, 48, 1, 33, 17, 33, 21, 33, 53, 33, 17, 33, 1, 51, 21, 35, 1, 0, 1,215, 1,109,252,110, 1,109,254,225, 1, 31,184,184,
+ 4, 96,252, 47,143,143, 3, 66, 2, 67,233, 0, 0, 2, 0,186,254, 86, 3, 16, 6, 20, 0, 13, 0, 17, 0, 56, 64, 29, 5, 0,
+ 1, 10,140, 8, 1,182, 3, 16,196, 14,155, 3,194, 8,195, 18, 11, 8, 2, 9, 2, 15, 4, 6, 14, 0, 18, 16,212, 60,236, 50,
+196,196, 18, 57, 57, 49, 0, 16,228,228,252,236, 16,238, 16,238, 17, 57, 57, 48, 5, 17, 33, 53, 33, 17, 20, 6, 43, 1, 53, 51,
+ 50, 54, 17, 51, 21, 35, 2, 88,254,195, 1,245,179,165,254,234, 90, 90,184,184, 20, 3,229,143,251,140,195,211,156,125, 6,165,
+233, 0, 0, 0, 0, 1, 0,236, 0, 0, 4,178, 6, 20, 0, 11, 0,197, 64, 58, 8, 23, 9, 8, 5, 6, 5, 7, 23, 6, 6, 5,
+ 9, 23, 3, 2, 8, 23, 7, 8, 3, 2, 5, 23, 6, 5, 2, 3, 2, 4, 23, 3, 3, 2, 66, 8, 5, 2, 3, 3,194, 0,155, 10,
+ 6, 8, 5, 4, 3, 6, 9, 1, 6, 6, 68, 0, 69, 12, 16,244,236,236, 50, 17, 23, 57, 49, 0, 47, 60,236,228, 23, 57, 48, 75,
+ 83, 88, 7, 16, 5,237, 7, 16, 8,237, 7, 8,237, 7, 4,237, 7, 16, 5,237, 7, 16, 8,237, 89, 34,178, 8, 7, 1, 1, 93,
+ 64, 82, 6, 2, 8, 8, 22, 2, 24, 5, 24, 8, 53, 2, 52, 5, 54, 8, 70, 2,102, 2,117, 2,118, 5, 12, 9, 3, 8, 8, 25,
+ 3, 23, 4, 24, 5, 25, 6, 26, 7, 24, 8, 40, 3, 39, 5, 40, 7, 59, 3, 59, 4, 55, 5, 57, 7, 55, 8, 74, 3, 73, 7, 89,
+ 6, 89, 7,107, 3,105, 4,105, 6,105, 7,121, 3,120, 5,121, 6,121, 7, 28, 93, 0, 93, 19, 51, 17, 1, 51, 9, 1, 35, 1,
+ 7, 17, 35,236,190, 1,227,224,254, 71, 1,254,225,254, 98,137,190, 6, 20,252,123, 1,209,254, 90,253, 70, 2, 66,129,254, 63,
+ 0, 1, 0,160, 0, 0, 4, 10, 6, 31, 0, 13, 0, 38, 64, 19, 9, 0, 3, 10,182, 12,197, 3,182, 5, 3, 6, 4, 0, 6, 11,
+ 76, 9, 14, 16,212,236,252,204, 57, 57, 49, 0, 47,236,252,236, 17, 57, 57, 48, 1, 20, 22, 59, 1, 21, 35, 34, 38, 53, 17, 33,
+ 53, 33, 2,127, 91, 89,215,233,165,181,254,217, 1,223, 1,150,124,126,156,212,194, 3,249,144, 0, 1, 0,109, 0, 0, 4,111,
+ 4,123, 0, 34, 0,163, 64, 39, 24, 18, 15, 9, 4, 7, 0, 29, 27, 6, 7, 21, 12,140, 32, 3,190, 27,194, 25, 16, 7, 0, 17,
+ 15, 8, 77, 6, 78, 17, 77, 15, 78, 28, 24, 77, 26, 69, 35, 16,244, 75,176, 12, 84, 75,176, 17, 84, 91, 88,185, 0, 26,255,192,
+ 56, 89,252, 60,252,236,252,236, 17, 18, 57, 49, 0, 47, 60, 60,228,244, 60,236, 50, 17, 57, 17, 57, 57, 17, 23, 57, 48, 64, 71,
+ 48, 4, 48, 5, 48, 6, 48, 7, 48, 8, 48, 9, 48, 10, 48, 11, 63, 22, 63, 23, 63, 24, 63, 25, 63, 26, 63, 27, 63, 28, 63, 29,
+ 63, 30,128, 3,128, 4,128, 5,128, 6,128, 7,128, 8,128, 9,128, 10,128, 11,143, 22,143, 23,143, 24,143, 25,143, 26,143, 27,
+143, 28,143, 29,143, 30, 35, 1, 93, 1, 62, 1, 51, 50, 22, 25, 1, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 52, 38, 35, 34,
+ 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 22, 2,164, 34,105, 74,135,111,168, 53, 70, 80, 59,168, 57, 74, 73, 57,167,167, 33,
+ 99, 63, 76,101, 3,238, 72, 69,209,254,223,253,119, 2,129,237,115,123,229,253,127, 2,129,240,112,123,229,253,127, 4, 96, 96,
+ 60, 63, 70, 0, 0, 1, 0,195, 0, 0, 4, 27, 4,123, 0, 19, 0, 44, 64, 24, 9, 14, 3, 0, 3, 1, 6,140, 17,190, 12,194,
+ 10, 1, 2, 6, 0, 74, 13, 9, 6, 11, 70, 20, 16,244,236, 50,252,236, 49, 0, 47, 60,228,244,236, 17, 23, 57, 57, 48, 1, 17,
+ 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 22, 4, 27,185,106,113,129,139,184,184, 49,168,115,171,169,
+ 2,182,253, 74, 2,182,151,142,183,171,253,135, 4, 96,168, 96, 99,225, 0, 0, 0, 2, 0,137,255,227, 4, 72, 4,123, 0, 11,
+ 0, 23, 0, 35, 64, 19, 6,140, 18, 0,140, 12,190, 18,153, 24, 9, 18, 15, 68, 3, 18, 21, 62, 24, 16,244,236,252,236, 49, 0,
+ 16,228,244,236, 16,238, 48, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 39, 50, 18, 17, 16, 2, 35, 34, 2, 17, 16, 18, 2,
+104,140,144,144,140,141,144,144,141,233,247,246,234,233,246,246, 3,223,218,214,213,219,219,213,214,218,156,254,210,254,226,254,
+225,254,211, 1, 45, 1, 31, 1, 30, 1, 46, 0, 0, 2, 0,190,254, 86, 4, 84, 4,123, 0, 16, 0, 28, 0, 51, 64, 28, 5, 0,
+ 20, 26,140, 14, 20,140, 8,190, 14,153, 1,195, 3,194, 29, 17, 18, 11, 71, 23, 4, 0, 6, 2, 70, 29, 16,244,236, 50, 50,252,
+236, 49, 0, 16,228,228,228,244,236, 16,238, 17, 57, 57, 48, 37, 17, 35, 17, 51, 21, 62, 1, 51, 50, 18, 17, 16, 2, 35, 34, 38,
+ 1, 52, 38, 35, 34, 6, 21, 20, 22, 51, 50, 54, 1,119,185,185, 46,153,100,203,231,232,202,102,153, 1,240,135,133,134,138,138,
+134,133,135,141,253,201, 6, 10,143, 83, 87,254,198,254,234,254,239,254,201, 87, 1,245,214,218,219,213,212,220,218, 0, 0, 0,
+ 0, 2, 0,137,254, 82, 4, 31, 4,119, 0, 11, 0, 28, 0, 51, 64, 28, 24, 12, 9, 3,140, 15, 9,140, 21,190, 15,153, 27,195,
+ 25,194, 29, 24, 12, 6, 6, 26, 71, 0, 18, 18, 62, 29, 16,244,236,252,236, 50, 50, 49, 0, 16,228,228,228,244,236, 16,238, 17,
+ 57, 57, 48, 1, 20, 22, 51, 50, 54, 53, 52, 38, 35, 34, 6, 1, 14, 1, 35, 34, 2, 17, 16, 18, 51, 50, 22, 23, 53, 51, 17, 35,
+ 1, 76,135,133,133,137,137,133,133,135, 2, 26, 45,153,101,201,233,232,202,100,153, 46,185,185, 2, 43,214,218,219,213,213,219,
+218,253,138, 83, 89, 1, 55, 1, 17, 1, 22, 1, 58, 87, 83,143,249,246, 0, 0, 0, 1, 1,106, 0, 0, 4,131, 4,123, 0, 17,
+ 0, 79, 64, 19, 6, 7, 11, 3, 0, 17, 3,151, 14,190, 9,194, 7, 10, 6, 6, 0, 8, 18, 16,212,196,236, 50, 49, 0, 47,228,
+244,236,212,204, 17, 57, 17, 57, 48, 64, 37, 16, 0, 16, 1, 16, 17, 32, 0, 32, 1, 32, 17, 48, 0, 48, 1, 51, 16, 48, 17, 64,
+ 0, 64, 1, 67, 16, 64, 17, 80, 0, 80, 1, 80, 16, 80, 17, 18, 93, 1, 46, 1, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51,
+ 50, 22, 23, 4,131, 59,122, 73,172,182,185,185, 46,191,131, 68,118, 54, 3,121, 46, 42,216,204,253,211, 4, 96,219,119,127, 34,
+ 36, 0, 0, 0, 0, 1, 0,213,255,227, 4, 6, 4,123, 0, 39, 0,117, 64, 64, 13, 12, 2, 14, 11, 23, 31, 30, 8, 9, 2, 7,
+ 10, 23, 30, 31, 30, 66, 29, 30, 24, 10, 11, 30, 31, 4, 21, 0,139, 1,192, 4, 20,139, 21,192, 24,140, 17, 4,140, 37,190, 17,
+153, 40, 29, 10, 11, 31, 27, 7, 0, 79, 27, 6, 14, 73, 7, 6, 20, 34, 69, 40, 16,244,196,236,252,236,228, 17, 18, 57, 57, 57,
+ 57, 49, 0, 16,228,244,236, 16,254,245,238, 16,245,238, 18, 23, 57, 17, 18, 57, 48, 75, 83, 88, 7, 16, 14,237, 17, 23, 57, 7,
+ 14,237, 17, 23, 57, 89, 34, 1, 21, 46, 1, 35, 34, 6, 21, 20, 22, 31, 1, 30, 1, 21, 20, 6, 35, 34, 38, 39, 53, 30, 1, 51,
+ 50, 54, 53, 52, 47, 2, 46, 1, 53, 52, 54, 51, 50, 22, 3,205, 79,160, 83,125,123, 92,183, 74,137,141,236,210, 83,182,106,103,
+188, 84,122,134,245, 8, 69,159,146,218,202, 90,166, 4, 57,180, 46, 46, 81, 83, 75, 74, 35, 14, 26,156,125,166,187, 35, 35,190,
+ 53, 53, 99, 89,128, 49, 2, 14, 31,147,127,161,175, 33, 0, 0, 0, 1, 0,131, 0, 0, 4, 8, 5,158, 0, 19, 0, 49, 64, 24,
+ 14, 5, 8, 15, 3,182, 0, 17, 1,194, 8,182, 10, 8, 11, 9, 2, 4, 0, 6, 16, 18, 14, 20, 16,212, 60,196,252, 60,196, 50,
+ 57, 57, 49, 0, 47,236,244, 60,196,236, 50, 17, 57, 57, 48, 1, 17, 33, 21, 33, 17, 20, 22, 59, 1, 21, 35, 34, 38, 53, 17, 33,
+ 53, 33, 17, 2,102, 1,162,254, 94, 94,117,207,225,207,170,254,213, 1, 43, 5,158,254,194,143,253,160,124, 98,147,166,203, 2,
+ 96,143, 1, 62, 0, 1, 0,195,255,227, 4, 27, 4, 94, 0, 19, 0, 44, 64, 24, 9, 14, 3, 0, 3, 1, 6,140, 17,153, 10, 1,
+194, 12, 13, 9, 6, 11, 74, 2, 6, 0, 70, 20, 16,244,236,252,236, 50, 49, 0, 47,228, 50,244,236, 17, 23, 57, 57, 48, 19, 17,
+ 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 35, 53, 14, 1, 35, 34, 38,195,184,107,112,130,138,185,185, 49,169,113,172,168, 1,
+168, 2,182,253, 74,151,142,183,171, 2,121,251,162,168, 97,100,225, 0, 0, 0, 0, 1, 0,100, 0, 0, 4,109, 4, 96, 0, 6,
+ 0,101, 64, 41, 3, 23, 4, 5, 4, 2, 23, 1, 2, 5, 5, 4, 2, 23, 3, 2, 6, 0, 6, 1, 23, 0, 0, 6, 66, 2, 3, 0,
+194, 5, 6, 5, 3, 2, 1, 5, 4, 73, 0, 69, 7, 16,244,236, 23, 57, 49, 0, 47,228, 50, 57, 48, 75, 83, 88, 7, 16, 5,237,
+ 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,237, 89, 34,178, 39, 2, 1, 0, 93, 64, 14, 7, 0, 7, 1, 8, 3, 8, 4, 4, 5,
+ 2, 37, 2, 2, 93, 1, 93, 19, 51, 9, 1, 51, 1, 35,100,191, 1, 69, 1, 70,191,254,114,237, 4, 96,252, 84, 3,172,251,160,
+ 0, 1, 0, 0, 0, 0, 4,209, 4, 96, 0, 12, 1, 17, 64, 69, 11, 2, 3, 2, 10, 9, 10, 3, 3, 2, 10, 11, 10, 4, 5, 4,
+ 9, 5, 5, 4, 6, 23, 7, 8, 7, 5, 23, 4, 5, 8, 8, 7, 2, 23, 3, 2, 12, 0, 12, 1, 23, 0, 12, 66, 10, 5, 2, 3,
+ 8, 3, 6, 0,194, 11, 8, 12, 11, 10, 9, 8, 6, 5, 4, 3, 2, 1, 11, 7, 0, 47,204, 23, 57, 49, 0, 47, 60,244, 60,196,
+ 17, 23, 57, 48, 75, 83, 88, 7, 5,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,237, 7, 16, 5,201, 7, 16, 8,201, 7, 16,
+ 8,201, 7, 16, 5,201, 89, 34,178, 15, 10, 1, 0, 93, 64,140, 11, 9, 4, 11, 31, 0, 31, 1, 29, 2, 26, 3, 28, 4, 25, 5,
+ 28, 9, 27, 10, 26, 11, 31, 12, 38, 0, 38, 1, 41, 2, 38, 5, 41, 6, 41, 7, 35, 8, 44, 12, 57, 2, 54, 5, 57, 6, 57, 7,
+ 51, 8, 60, 12, 69, 8, 73, 9, 70, 11, 74, 12, 86, 8, 88, 9, 87, 11, 89, 12,102, 2,105, 3,102, 4,105, 5,106, 9,101, 11,
+118, 2,122, 5,120, 8,124, 9,114, 11, 45, 15, 10, 25, 2, 31, 3, 31, 4, 25, 5, 31, 10, 31, 10, 43, 2, 43, 5, 62, 2, 62,
+ 5, 60, 10, 72, 10, 89, 10,106, 2,105, 5,104, 10,123, 2,127, 3,121, 4,127, 4,122, 5,124, 10,127, 10, 24, 93, 1, 93, 17,
+ 51, 27, 1, 51, 27, 1, 51, 1, 35, 11, 1, 35,182,195,160,157,162,195,182,254,250,176,179,178,176, 4, 96,252,119, 2, 66,253,
+190, 3,137,251,160, 2,102,253,154, 0, 0, 0, 0, 1, 0, 76, 0, 0, 4,133, 4, 96, 0, 11, 0,169, 64, 72, 5, 23, 6, 7,
+ 6, 4, 23, 3, 4, 7, 7, 6, 4, 23, 5, 4, 1, 2, 1, 3, 23, 2, 2, 1, 11, 23, 0, 1, 0, 10, 23, 9, 10, 1, 1, 0,
+ 10, 23, 11, 10, 7, 8, 7, 9, 23, 8, 8, 7, 66, 10, 7, 4, 1, 4, 8, 0,194, 5, 2, 10, 7, 4, 1, 4, 8, 0, 2, 73,
+ 8, 6, 69, 12, 16,244,196,252,196, 17, 23, 57, 49, 0, 47, 60,228, 50, 23, 57, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 8,237,
+ 7, 16, 8,237, 7, 16, 5,237, 7, 16, 5,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,237, 89, 34,178, 7, 10, 1, 0, 93,
+ 64, 30, 9, 1, 6, 7,102, 1,105, 7,118, 1,121, 7, 6, 7, 1, 7, 7, 6, 10, 21, 10, 58, 4, 52, 10, 90, 4, 86, 10, 8,
+ 93, 1, 93, 9, 2, 35, 9, 1, 35, 9, 1, 51, 9, 1, 4, 94,254,111, 1,184,213,254,184,254,185,213, 1,184,254,111,204, 1,
+ 41, 1, 39, 4, 96,253,232,253,184, 1,193,254, 63, 2, 72, 2, 24,254,107, 1,149, 0, 0, 0, 0, 1, 0,104,254, 86, 4,129,
+ 4, 96, 0, 18, 0,160, 64, 69, 13, 23, 14, 13, 2, 3, 2, 10, 11, 2, 9, 12, 23, 3, 3, 2, 17, 23, 18, 0, 18, 16, 23, 15,
+ 16, 0, 0, 18, 16, 23, 17, 16, 13, 14, 13, 15, 23, 14, 14, 13, 66, 16, 19, 13, 0, 14, 9,140, 7,195, 17, 14,194, 19, 17, 16,
+ 15, 13, 10, 7, 0, 7, 18, 8, 18, 73, 14, 69, 19, 16,244,236,196, 17, 23, 57, 49, 0, 16,228, 50,244,236, 17, 57, 57, 18, 57,
+ 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 8,237, 7, 16, 8,237, 7, 16, 5,237, 7, 16, 5,237, 17, 23, 57, 7, 16, 8,237, 89,
+ 34,178, 56, 18, 1, 1, 93, 64, 26, 4, 16,118, 16, 2, 8, 17, 8, 18, 25, 12, 25, 13, 38, 14, 38, 15, 56, 17, 73, 17, 73, 18,
+ 89, 13, 10, 93, 0, 93, 1, 6, 7, 2, 7, 14, 1, 43, 1, 53, 51, 50, 54, 55, 1, 51, 9, 1, 51, 3, 90, 46, 71, 99, 34, 46,
+138, 92,148,109, 81, 92, 71,254, 79,195, 1, 76, 1, 71,195, 1,104,117,191,254,248, 58, 78, 78,154, 94,196, 4, 78,252,148, 3,
+108, 0, 0, 0, 0, 1, 0,203, 0, 0, 4, 16, 4, 98, 0, 9, 0, 88, 64, 28, 3, 23, 7, 8, 7, 8, 23, 2, 3, 2, 66, 8,
+182, 0,194, 3,182, 5, 8, 3, 0, 4, 1, 73, 0, 6, 69, 10, 16,244,196,236, 50, 17, 57, 57, 49, 0, 47,236,244,236, 48, 75,
+ 83, 88, 7, 16, 5,237, 7, 16, 5,237, 89, 34,178, 56, 8, 1, 1, 93, 64, 21, 54, 3, 56, 8, 69, 3, 74, 8, 87, 3, 88, 8,
+101, 3,106, 8,117, 3,122, 8, 10, 93, 19, 33, 21, 1, 33, 21, 33, 53, 1, 33,227, 3, 45,253,125, 2,131,252,187, 2,131,253,
+149, 4, 98,168,252,220,150,170, 3, 37, 0, 0, 0, 1, 0,221,254,178, 3,244, 6, 20, 0, 36, 0,102, 64, 53, 25, 15, 21, 11,
+ 6, 37, 9, 26, 16, 21, 29, 11, 5, 32, 33, 3, 0, 11,182, 9, 0,182, 1,198, 9,199, 21,182, 19,181, 37, 12, 9, 10, 5, 36,
+ 22, 25, 0, 29, 10, 5, 19, 2, 20, 0, 32, 25, 61, 10, 15, 5, 37, 16,212, 60,196,252, 60,196, 50, 57, 57, 17, 18, 57, 17, 18,
+ 57, 57, 17, 18, 57, 57, 49, 0, 16,252,236,228,244,236, 16,238, 18, 23, 57, 18, 57, 17, 57, 57, 17, 18, 57, 17, 18, 57, 57, 48,
+ 5, 21, 35, 34, 38, 61, 1, 52, 38, 43, 1, 53, 51, 50, 54, 61, 1, 52, 54, 59, 1, 21, 35, 34, 6, 29, 1, 20, 6, 7, 30, 1,
+ 29, 1, 20, 22, 51, 3,244, 64,249,169,107,140, 62, 62,141,106,169,249, 64, 70,140, 85, 91,110,111, 90, 85,140,190,144,148,221,
+239,151,116,143,114,150,240,221,147,143, 87,142,248,157,142, 25, 27,142,156,248,143, 86, 0, 0, 0, 1, 2, 18,254, 29, 2,190,
+ 6, 29, 0, 3, 0, 18,183, 1, 0,181, 4, 0, 4, 2, 4, 16,212,236, 49, 0, 16,252,204, 48, 1, 17, 35, 17, 2,190,172, 6,
+ 29,248, 0, 8, 0, 0, 0, 0, 0, 1, 0,221,254,178, 3,244, 6, 20, 0, 36, 0,106, 64, 55, 31, 37, 27, 22, 12, 15, 8, 27,
+ 11, 21, 25, 15, 4, 5, 32, 3, 0, 25,182, 27, 0,182, 35,198, 27,199, 15,182, 17,181, 37, 28, 25, 26, 21, 15, 1, 4, 0, 8,
+ 26, 21, 35, 18, 4, 0, 26, 31, 21, 61, 16, 0, 11, 4, 37, 16,212, 60,196, 50,252, 60,196, 17, 18, 57, 57, 17, 18, 57, 17, 18,
+ 57, 57, 17, 18, 57, 57, 49, 0, 16,252,236,228,244,236, 16,238, 18, 23, 57, 17, 18, 57, 57, 17, 57, 17, 57, 57, 17, 18, 57, 48,
+ 23, 51, 50, 54, 61, 1, 52, 54, 55, 46, 1, 61, 1, 52, 38, 43, 1, 53, 51, 50, 22, 29, 1, 20, 22, 59, 1, 21, 35, 34, 6, 29,
+ 1, 20, 6, 43, 1,221, 68,141, 86, 90,111,110, 91, 86,141, 68, 62,249,168,107,141, 64, 64,141,107,168,249, 62,190, 88,141,248,
+156,142, 27, 25,142,157,248,141, 88,143,147,221,240,150,114,143,116,151,239,221,148, 0, 0, 0, 0, 1, 0, 88, 1,236, 4,121,
+ 3, 12, 0, 27, 0, 38, 64, 18, 1, 11, 4, 15, 0, 14, 4,160, 25, 18, 0,160, 11, 28, 0, 14, 39, 28, 16,252,196, 49, 0, 16,
+212,252, 60,212,236, 50, 18, 57, 17, 18, 57, 48, 1, 21, 14, 1, 35, 34, 39, 38, 39, 46, 1, 35, 34, 6, 7, 53, 62, 1, 51, 50,
+ 22, 23, 22, 23, 22, 51, 50, 54, 4,121, 75,143, 79, 90,113, 22, 11, 77,103, 51, 79,141, 73, 78,146, 83, 53,100, 74, 12, 21,116,
+ 93, 70,137, 3, 12,174, 59, 55, 51, 10, 4, 33, 24, 59, 63,174, 60, 54, 22, 31, 5, 10, 55, 61, 0, 2, 2, 4, 0, 0, 2,207,
+ 5,213, 0, 3, 0, 9, 0, 30, 64, 14, 6, 0,134, 1,136, 4, 7, 6, 8, 2, 3, 4, 0, 10, 16,212, 60,236, 50, 57, 57, 49,
+ 0, 47,244,252,204, 48, 1, 53, 51, 21, 3, 17, 19, 51, 19, 17, 2, 4,203,203, 21,161, 21, 4,215,254,254,251, 41, 2,143, 1,
+101,254,155,253,113, 0, 0, 0, 0, 2, 0,213,254,199, 4, 37, 5,152, 0, 26, 0, 33, 0, 78, 64, 42, 27, 8, 5, 4, 28, 0,
+139, 1,141, 28, 9,139, 8,141, 5,203, 12, 28,203, 22, 24, 21,190, 15, 12,153, 13, 34, 27, 21, 14, 7, 23, 12, 4, 8, 0, 31,
+ 30, 18, 69, 34, 16,244,236,212, 60,212, 60, 60,236, 50, 50, 49, 0, 16,196,228, 50,244, 60,196,236, 16,254,244,238, 16,245,238,
+ 17, 57, 17, 18, 57, 48, 1, 21, 46, 1, 39, 17, 62, 1, 55, 21, 14, 1, 7, 17, 35, 17, 38, 0, 53, 52, 0, 55, 17, 51, 17, 30,
+ 1, 1, 17, 14, 1, 21, 20, 22, 4, 37, 67,130, 63, 63,131, 66, 73,130, 57,103,225,254,252, 1, 7,222,103, 57,130,254,222,132,
+160,160, 4, 53,172, 40, 44, 4,252,154, 5, 45, 40,172, 31, 34, 3,254,226, 1, 30, 22, 1, 57,251,250, 1, 61, 19, 1, 31,254,
+225, 3, 34,252, 43, 3, 96, 12,236,184,184,235, 0, 1, 0,139, 0, 0, 4, 88, 5,240, 0, 27, 0, 62, 64, 32, 7, 22, 1, 18,
+ 10,182, 20, 8, 12, 1,139, 0,167, 4,151, 25,150, 16, 12,151, 14, 0, 13, 9, 11, 7, 30, 15, 19, 21, 17, 28, 16,212, 60,196,
+196,252, 60,196,212,196, 49, 0, 47,236, 50,244,236,244,236, 16,212, 60,238, 50, 18, 57, 57, 48, 1, 21, 46, 1, 35, 34, 6, 29,
+ 1, 33, 21, 33, 17, 33, 21, 33, 53, 51, 17, 35, 53, 51, 53, 52, 54, 51, 50, 22, 4, 68, 62,127, 67,134,127, 1,115,254,141, 2,
+ 25,252, 51,236,199,199,219,223, 65,137, 5,182,184, 44, 44,179,192,217,143,254, 47,170,170, 1,209,143,238,254,250, 29, 0, 0,
+ 0, 2, 0,205, 0,195, 4, 76, 4, 66, 0, 11, 0, 47, 0,129, 64, 26, 32, 22, 27, 23, 14, 40, 45, 13, 24, 30, 27, 9, 42, 12,
+ 45, 39, 33, 21, 15, 4, 3, 9,255, 31, 23, 27,184, 1, 0, 64, 39, 3,255, 41, 13, 45, 48, 31, 41, 36, 32, 13, 23, 18, 14, 33,
+ 39, 36, 6, 15, 21, 18, 42, 30, 24, 12, 4, 6, 0,120, 22, 14, 18,121, 6,120, 40, 32, 36, 48, 16,212,196, 50,236,252,196, 50,
+236, 17, 23, 57, 17, 57, 57, 17, 18, 57, 57, 17, 18, 57, 57, 17, 18, 57, 57, 49, 0, 16,212,196, 50,236,252,196, 50,236, 17, 23,
+ 57, 18, 57, 57, 17, 18, 57, 57, 17, 18, 57, 57, 17, 18, 57, 57, 48, 1, 52, 38, 35, 34, 6, 21, 20, 22, 51, 50, 54, 3, 55, 23,
+ 7, 30, 1, 21, 20, 6, 7, 23, 7, 39, 14, 1, 35, 34, 38, 39, 7, 39, 55, 46, 1, 53, 52, 54, 55, 39, 55, 23, 62, 1, 51, 50,
+ 22, 3,100,124, 91, 90,125,125, 90, 91,124, 24,166, 90,166, 30, 29, 30, 31,168, 94,166, 46, 91, 50, 48, 96, 48,164, 92,166, 31,
+ 29, 31, 31,168, 94,166, 46, 91, 51, 46, 94, 2,131, 90,123,123, 90, 92,125,126, 1,116,166, 93,166, 49, 93, 48, 50, 91, 45,166,
+ 94,167, 31, 30, 29, 28,163, 90,166, 51, 93, 46, 50, 93, 45,166, 95,168, 31, 30, 29, 0, 0, 0, 0, 1, 0, 37, 0, 0, 4,172,
+ 5,213, 0, 24, 0,127, 64, 68, 3, 37, 4, 9, 4, 2, 37, 1, 2, 9, 9, 4, 2, 37, 3, 2, 20, 0, 20, 1, 37, 0, 0, 20,
+ 66, 2, 7, 5, 16, 12,231, 18, 10, 23, 5,231, 21, 7, 3, 0,136, 14, 24, 1, 17, 2, 15, 8, 5, 3, 3, 6, 4, 60, 11, 6,
+101, 13, 9, 30, 22, 17,101, 0, 60, 19, 15, 25, 16,212, 60,236,236, 50,252, 60,236, 50,236, 18, 23, 57, 18, 57, 17, 57, 57, 49,
+ 0, 47,228, 50,212, 60,236, 50,212, 60,236, 50, 17, 18, 57, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 8,237, 7, 16, 8,237, 7,
+ 16, 5,237, 89, 34, 19, 51, 9, 1, 51, 1, 51, 21, 33, 7, 21, 33, 21, 33, 17, 35, 17, 33, 53, 33, 53, 39, 33, 53, 51, 37,215,
+ 1,108, 1,107,217,254,182,252,254,197, 86, 1,145,254,111,203,254,113, 1,143, 90,254,203,243, 5,213,253,109, 2,147,253,207,
+111,151, 35,111,253,244, 2, 12,111, 35,151,111, 0, 2, 2, 18,254,162, 2,190, 5,152, 0, 3, 0, 7, 0, 33,188, 0, 5, 1,
+ 7, 0, 4, 0, 0, 1, 7,183, 1, 8, 4, 0, 4, 6, 2, 8, 16,212, 60,236, 50, 49, 0, 16,212,236,212,236, 48, 1, 17, 35,
+ 17, 19, 17, 35, 17, 2,190,172,172,172, 5,152,253, 10, 2,246,252, 0,253, 10, 2,246, 0, 0, 0, 2, 0,199,255, 61, 4, 12,
+ 5,240, 0, 50, 0, 62, 0,106, 64, 60, 35, 36, 30, 57, 51, 11, 17, 36, 42, 4, 1, 27,143, 26,206, 30,207, 23, 1,143, 0,206,
+ 4,207, 48,150, 23, 63, 35, 7, 17, 60, 33, 42, 54, 11, 36, 57, 51, 4, 7, 33, 85, 20, 7, 85, 45, 20, 60, 85, 0, 38, 14, 45,
+ 26, 38, 54, 85, 39, 63, 16,212,236,228,196,212,228,236,196, 16,238, 16,238, 17, 23, 57, 18, 57, 17, 18, 57, 18, 57, 49, 0, 16,
+196,244,236,244,236, 16,238,246,238, 17, 23, 57, 57, 57, 17, 18, 57, 48, 1, 21, 46, 1, 35, 34, 6, 21, 20, 23, 22, 23, 30, 1,
+ 21, 20, 6, 7, 30, 1, 21, 20, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 47, 1, 46, 1, 53, 52, 54, 55, 46, 1, 53,
+ 52, 54, 51, 50, 22, 1, 14, 1, 21, 20, 22, 23, 62, 1, 53, 52, 38, 3,168, 83,143, 57, 97,107,205, 26, 14,212,130, 91, 93, 61,
+ 58,204,173, 73,155, 87, 87,148, 57,102,113,221, 24,214,128, 93, 91, 60, 59,200,167, 72,153,254,141, 62, 61,141,247, 62, 60,143,
+ 5,182,164, 39, 39, 80, 71, 90,115, 15, 8,119,154,101, 90,140, 53, 52,109, 64,142,168, 29, 29,164, 39, 39, 84, 76,102,123, 14,
+120,153,102, 91,143, 49, 44,112, 69,130,159, 29,253,213, 45, 90, 47, 76,135,133, 45, 90, 47, 76,136, 0, 0, 0, 0, 2, 1, 63,
+ 5, 70, 3,145, 6, 16, 0, 3, 0, 7, 0, 29, 64, 14, 6, 2,222, 4, 0,221, 8, 5, 97, 4, 1, 97, 0, 8, 16,212,252,212,
+236, 49, 0, 16,244, 60,236, 50, 48, 1, 51, 21, 35, 37, 51, 21, 35, 1, 63,203,203, 1,136,202,202, 6, 16,202,202,202, 0, 0,
+ 0, 3, 0, 0, 0,125, 4,209, 5, 78, 0, 25, 0, 49, 0, 73, 0, 68, 64, 39, 13,218, 14, 10,218, 17,220, 38,212, 62, 1,218,
+ 0, 4,218, 23,217, 26,212, 62,211, 50,209, 74, 7, 92, 20, 13, 0, 94, 44, 7, 56, 20, 32, 7, 56, 89, 68, 47,230,254,197, 16,
+254,229, 50, 16,238, 49, 0, 16,244,236,252,244,236,212,236, 16,254,253,238,214,238, 48, 1, 21, 46, 1, 35, 34, 6, 21, 20, 22,
+ 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 53, 52, 54, 51, 50, 22, 39, 34, 6, 7, 14, 1, 21, 20, 22, 23, 30, 1, 51, 50, 54, 55,
+ 62, 1, 53, 52, 38, 39, 46, 1, 39, 50, 22, 23, 30, 1, 21, 20, 6, 7, 14, 1, 35, 34, 38, 39, 46, 1, 53, 52, 54, 55, 62, 1,
+ 3, 96, 58,111, 58,117,135,140,130, 56,103, 50, 52,114, 61,180,207,208,179, 61,114,196,106,181, 75, 75, 77, 77, 75, 76,181,105,
+106,181, 76, 76, 75, 76, 75, 75,181,107,127,218, 90, 90, 92, 91, 91, 91,218,126,125,218, 91, 91, 91, 92, 90, 90,218, 4, 47,108,
+ 28, 27,149,128,132,142, 25, 26,104, 23, 22,200,172,173,202, 22,161, 74, 75, 75,184,106,104,183, 75, 76, 76, 76, 76, 76,181,105,
+106,184, 75, 75, 74,103, 90, 90, 91,220,126,125,218, 91, 91, 91, 91, 91, 91,218,125,126,220, 91, 90, 90, 0, 0, 0, 3, 1, 14,
+ 1,213, 3,193, 5,240, 0, 10, 0, 37, 0, 41, 0,100, 64, 54, 9, 6, 0, 25, 31, 11, 23, 14, 6, 0, 40,243, 38, 0,237, 23,
+ 38,241, 6,237, 12, 17, 32,239, 31,238, 28,237, 17,240, 35,150, 42, 38, 31, 20, 0, 23, 9, 3, 40, 39, 24, 13, 9,106, 11,107,
+ 31, 3,106, 20,105, 42, 16,252,236,196,252,236, 50, 50,192,192, 17, 18, 57, 57, 17, 18, 57, 49, 0, 16,244,228,252,244,236, 16,
+196,238,237,214,238, 16,238, 17, 18, 57, 18, 57, 17, 57, 17, 18, 57, 48, 1, 34, 6, 21, 20, 22, 51, 50, 54, 61, 1, 55, 17, 35,
+ 53, 14, 1, 35, 34, 38, 53, 52, 54, 59, 1, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 1, 33, 21, 33, 2,172,144,124,
+ 87, 72,105,131,143,143, 49,131, 82,129,150,187,172,182,119,117, 51,125, 67, 68,135, 63,184,172,253,107, 2,156,253,100, 4, 80,
+ 68, 78, 64, 77,143,115, 29, 61,254, 64,112, 65, 66,136,116,129,140, 4, 90, 92, 35, 33,127, 28, 28,172,253, 12,123, 0, 0, 0,
+ 0, 2, 0,119, 0,141, 4, 18, 4, 35, 0, 6, 0, 13, 0, 47, 64, 23, 9, 2, 11, 4,252, 7, 0,172, 14, 2, 12, 5, 9, 0,
+ 10, 7,118, 12, 3, 0,118, 5, 14, 16,212,252, 60,212,236, 50, 17, 57, 17, 18, 57, 49, 0, 16,244, 60,236, 50, 57, 57, 48, 1,
+ 21, 9, 1, 21, 1, 53, 1, 21, 9, 1, 21, 1, 53, 2, 76,254,211, 1, 45,254, 43, 3,155,254,211, 1, 45,254, 43, 4, 35,191,
+254,244,254,244,191, 1,162, 82, 1,162,191,254,244,254,244,191, 1,162, 82, 0, 0, 1, 0, 88, 1,115, 4,121, 3, 94, 0, 5,
+ 0, 24, 64, 11, 4,160, 2, 0, 6, 3, 28, 1, 0, 39, 6, 16,252,212,236, 49, 0, 16,212,196,236, 48, 19, 33, 17, 35, 17, 33,
+ 88, 4, 33,168,252,135, 3, 94,254, 21, 1, 63, 0, 1, 1,100, 1,223, 3,109, 2,131, 0, 3, 0, 17,182, 0,160, 2, 4, 1,
+ 0, 4, 16,212,196, 49, 0, 16,212,236, 48, 1, 33, 21, 33, 1,100, 2, 9,253,247, 2,131,164, 0, 4, 0, 0, 0,125, 4,209,
+ 5, 78, 0, 19, 0, 28, 0, 52, 0, 76, 0,133, 64, 73, 15, 14, 13, 3, 16, 12, 93, 9, 10, 9, 11, 93, 10, 10, 9, 66, 12, 10,
+ 6, 22, 9, 10, 22,215, 15, 20,215, 0, 17, 10,214, 65,212, 41, 0,213, 53,212, 41,211, 29,209, 77, 23, 20, 15, 12, 4, 0, 6,
+ 16, 9, 26, 3, 21, 16, 92, 18, 26, 92, 10, 3, 91, 71, 7, 35, 18, 88, 59, 7, 35, 89, 47, 47,230,254,229, 16,254,245,196,238,
+ 16,238, 50, 17, 18, 57, 17, 57, 57, 23, 57, 49, 0, 16,244,236,252,228, 16,254,237, 50, 16,238,214,238, 18, 57, 18, 57, 18, 57,
+ 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 4,237, 17, 23, 57, 89, 34, 1, 50, 22, 21, 20, 6, 7, 30, 1, 31, 1, 35, 39, 46, 1,
+ 43, 1, 17, 35, 17, 23, 35, 21, 51, 50, 54, 53, 52, 38, 3, 50, 22, 23, 30, 1, 21, 20, 6, 7, 14, 1, 35, 34, 38, 39, 46, 1,
+ 53, 52, 54, 55, 62, 1, 23, 34, 6, 7, 14, 1, 21, 20, 22, 23, 30, 1, 51, 50, 54, 55, 62, 1, 53, 52, 38, 39, 46, 1, 2, 88,
+147,144, 88, 80, 19, 58, 38,114,143,107, 49, 61, 45, 55,130,232,102,102, 90, 74, 74, 68,127,218, 90, 90, 92, 91, 91, 91,218,126,
+125,218, 91, 91, 91, 92, 90, 90,218,126,106,181, 75, 75, 77, 77, 75, 76,181,105,106,181, 76, 76, 75, 76, 75, 75,181, 4, 76, 98,
+101, 71, 93, 14, 5, 67, 59,186,174, 80, 42,254,216, 2,182, 84,232, 54, 63, 62, 53, 1, 86, 90, 90, 91,220,126,125,218, 91, 91,
+ 91, 91, 91, 91,218,125,126,220, 91, 90, 90,103, 74, 75, 75,184,106,104,183, 75, 76, 76, 76, 76, 76,181,105,106,184, 75, 75, 74,
+ 0, 1, 1, 61, 5, 98, 3,147, 5,246, 0, 3, 0, 17,182, 2,182, 0, 4, 1, 0, 4, 16,212,204, 49, 0, 16,212,236, 48, 1,
+ 33, 21, 33, 1, 61, 2, 86,253,170, 5,246,148, 0, 2, 1, 43, 3,117, 3,166, 5,240, 0, 14, 0, 26, 0, 32, 64, 17, 21,204,
+ 9,205, 15,204, 0,150, 27, 24, 83, 6, 84, 18, 83, 12, 27, 16,212,236,252,236, 49, 0, 16,244,236,252,236, 48, 1, 50, 22, 23,
+ 30, 1, 21, 20, 6, 35, 34, 38, 53, 52, 54, 23, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 2,104, 65,117, 44, 45, 47,186,134,
+135,180,184,133, 79,111,109, 79, 80,113,112, 5,240, 49, 46, 45,114, 66,132,183,180,135,134,186,129,111, 80, 80,108,110, 78, 79,
+112, 0, 0, 0, 0, 2, 0, 88, 0, 0, 4,121, 4,147, 0, 3, 0, 15, 0, 46, 64, 24, 9,227, 11, 7,160, 4,227, 13, 5, 0,
+160, 2, 6, 1, 26, 8, 4, 28, 12, 0, 26, 14, 10, 16, 16,212, 60,236, 50,252, 60,236, 50, 49, 0, 47,236,212, 60,236,252, 60,
+236, 48, 55, 33, 21, 33, 1, 17, 33, 21, 33, 17, 35, 17, 33, 53, 33, 17, 88, 4, 33,251,223, 2,100, 1,189,254, 67,168,254, 68,
+ 1,188,170,170, 4,147,254,183,170,254,180, 1, 76,170, 1, 73, 0, 1, 1, 66, 2,156, 3,125, 5,240, 0, 24, 0, 97, 64, 19,
+ 0, 87, 4, 5, 4, 22, 23, 2, 21, 24, 87, 5, 5, 4, 66, 5, 24, 14, 0, 65, 9, 1, 9, 0, 2, 0, 14, 1, 9, 0, 15, 0,
+ 2, 1, 10, 0, 11, 1, 9, 64, 14, 18,150, 25, 5, 0, 24, 14, 8,127, 1, 21, 14, 3, 25, 16,212,196,212,196,236, 17, 57, 57,
+ 57, 49, 0, 16,244,236,228,212,236, 16,238, 17, 57, 57, 48, 75, 83, 88, 7, 16, 4,237, 17, 23, 57, 7, 16, 5,237, 89, 34, 1,
+ 33, 21, 33, 53, 55, 62, 1, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 21, 20, 6, 7, 1,227, 1,154,253,197,231,101,
+ 81,100, 82, 49,113, 63, 65,121, 59,142,172, 74,119, 3, 14,114,110,226, 97,122, 51, 61, 76, 36, 36,125, 28, 28,133,107, 57,119,
+117, 0, 0, 0, 0, 1, 1, 70, 2,141, 3,156, 5,240, 0, 40, 0, 92, 65, 20, 0, 0, 0, 19, 1, 9, 0, 21, 0, 10, 1, 9,
+ 0, 9, 1, 11, 0, 21, 0, 13, 1, 9, 0, 6, 0, 31, 1, 9, 0, 32, 1, 11, 0, 6, 1, 10, 0, 28, 1, 9, 64, 19, 35,150,
+ 41, 22, 19, 13, 0, 3, 20, 25,127, 38, 16,127, 3, 31, 20, 9, 41, 16,212,196,196,212,236,212,236, 17, 23, 57, 57, 49, 0, 16,
+244,236,228,244,236, 16,238,198,246,238, 16,238, 57, 48, 1, 30, 1, 21, 20, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52,
+ 38, 43, 1, 53, 51, 50, 54, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 21, 20, 6, 2,219, 94, 99,190,177, 58,114, 59,
+ 69,113, 45,101,118,110,109, 66, 74, 93, 98, 96, 87, 44,112, 59, 69,117, 50,145,168, 88, 4, 96, 21,108, 80,124,134, 21, 20,121,
+ 27, 26, 81, 68, 74, 76,108, 63, 60, 56, 63, 24, 23,121, 17, 18,118, 99, 71, 93, 0, 1, 1,219, 4,238, 3,186, 6,102, 0, 3,
+ 0, 37, 64, 9, 2,186, 0,185, 4, 1, 60, 3, 4, 16,212,236, 49, 0, 16,244, 75,176, 9, 84, 75,176, 14, 84, 91, 88,185, 0,
+ 0, 0, 64, 56, 89,236, 48, 1, 51, 1, 35, 2,244,198,254,187,154, 6,102,254,136, 0, 0, 0, 0, 1, 0,195,254, 84, 4,158,
+ 4, 96, 0, 32, 0, 76, 64, 42, 19, 25, 31, 3, 22, 6, 3, 9, 12, 3, 1, 18, 6,140, 15,139, 28, 22,153, 0,195, 10, 1,194,
+ 33, 25, 11, 9, 32, 31, 2, 0, 18, 9, 6, 11, 74, 2, 6, 0, 70, 33, 16,244,236,252,236,196, 17, 18, 57, 57, 17, 18, 57, 49,
+ 0, 16,228, 50,228,244, 60,236,252,196, 17, 23, 57, 17, 18, 23, 57, 48, 19, 17, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 20,
+ 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 39, 14, 1, 35, 34, 38, 39, 17,195,184,120,111,127,129,185, 32, 33, 9, 29, 28, 38,
+ 68, 34, 62, 75, 12, 46,133, 89, 92,127, 44,254, 84, 6, 12,253, 72,142,151,170,166, 2,141,252,160, 59, 56, 10, 13,148, 23, 22,
+ 79, 79, 80, 78, 76, 80,253,213, 0, 1, 0,106,255, 59, 4, 6, 5,213, 0, 13, 0, 35, 64, 17, 4, 8, 0,136, 6, 2, 14, 0,
+ 7, 87, 5, 3, 87, 1, 49, 11, 14, 16,220,252,252,212,236, 57, 49, 0, 16,196, 50,244,196,204, 48, 1, 33, 17, 35, 17, 35, 17,
+ 35, 17, 46, 1, 53, 52, 36, 2, 70, 1,192,141,191,141,215,236, 1, 5, 5,213,249,102, 6, 31,249,225, 3, 78, 17,221,184,190,
+232, 0, 0, 0, 0, 1, 1,233, 2, 47, 2,229, 3, 96, 0, 3, 0, 21,185, 0, 2, 1, 1,181, 0, 4, 1, 29, 0, 4, 16,212,
+236, 49, 0, 16,212,236, 48, 1, 51, 17, 35, 1,233,252,252, 3, 96,254,207, 0,255,255, 1,139,254,117, 3, 41, 0, 0, 16, 6,
+ 2,163, 0, 0, 0, 1, 1, 88, 2,156, 3,147, 5,223, 0, 10, 0, 57, 65, 11, 0, 7, 0, 0, 1, 9, 0, 9, 0, 3, 1, 9,
+ 0, 4, 0, 9, 1, 10, 0, 2, 1, 9, 64, 13, 5,150, 11, 8, 97, 6, 87, 3,125, 0, 97, 1, 11, 16,212,236,236,252,236, 49,
+ 0, 16,244,236,228,212,236, 16,238, 50, 48, 1, 51, 17, 7, 53, 55, 51, 17, 51, 21, 33, 1,106,205,223,229,138,204,253,215, 3,
+ 10, 2, 99, 41,116, 39,253, 43,110, 0, 0, 0, 0, 3, 0,244, 1,213, 3,221, 5,240, 0, 11, 0, 23, 0, 27, 0, 51, 64, 28,
+ 26,243, 24,241, 6,237, 18,240, 0,237, 12,150, 28, 25, 15, 9, 24, 21, 3, 9,106, 15,107, 3,106, 21,105, 28, 16,252,236,252,
+236, 17, 18, 57, 17, 18, 57, 49, 0, 16,244,236,244,236,252,236, 48, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 39, 50, 22,
+ 21, 20, 6, 35, 34, 38, 53, 52, 54, 3, 33, 21, 33, 2,104,102,115,115,102,101,117,115,103,170,203,202,171,170,202,203,171, 2,
+164,253, 92, 5,123,156,139,139,154,157,136,139,156,117,224,188,187,223,223,187,188,224,252, 96,123, 0, 0, 0, 0, 2, 0,193,
+ 0,141, 4, 92, 4, 35, 0, 6, 0, 13, 0, 47, 64, 23, 12, 5, 10, 3,252, 7, 0,172, 14, 5, 8, 1, 12, 7, 1,118, 3, 0,
+ 8,118, 10, 7, 14, 16,212, 60,252,212, 60,236, 18, 57, 17, 18, 57, 49, 0, 16,244, 60,236, 50, 57, 57, 48, 9, 1, 21, 1, 53,
+ 9, 1, 37, 1, 21, 1, 53, 9, 1, 2,135, 1,213,254, 43, 1, 45,254,211,254, 58, 1,213,254, 43, 1, 45,254,211, 4, 35,254,
+ 94, 82,254, 94,191, 1, 12, 1, 12,191,254, 94, 82,254, 94,191, 1, 12, 1, 12,255,255, 0, 27,254,242, 4, 90, 6,123, 16, 39,
+ 6,170, 0,184,252, 86, 16, 39, 0,123,254,254, 0,156, 16, 6, 11,182, 0, 0,255,255, 0, 27,254,242, 4, 90, 6,123, 16, 39,
+ 0,123,254,254, 0,156, 16, 38, 11,182, 0, 0, 16, 7, 0,116, 0,201,252, 86,255,255, 0, 27,254,242, 4, 90, 6,140, 16, 39,
+ 6,170, 0,184,252, 86, 16, 39, 0,117,255, 29, 0,156, 16, 6, 11,182, 0, 0, 0, 2, 0,193,255,229, 3,221, 5,213, 0, 33,
+ 0, 37, 0,130, 64, 71, 11, 10, 9, 8, 7, 5, 12, 6, 37, 25, 26, 25, 3, 4, 2, 2, 5, 37, 26, 26, 25, 66, 33, 26, 5, 2,
+ 4, 6, 25, 0, 16,139, 15,141, 12, 0, 34,134, 36, 12,151, 19,153, 36,136, 38, 6, 35, 25, 22, 9, 31, 5, 0, 3, 29, 1, 26,
+ 35, 9, 41, 22, 15, 29, 3, 1, 15, 34, 30, 35, 38, 16,212,252,196,212,236, 16,214,238, 17, 57, 17, 18, 23, 57, 17, 18, 57, 18,
+ 57, 49, 0, 16,228,244,236, 16,254,205, 16,244,238, 18, 57, 57, 23, 57, 48, 75, 83, 88, 7, 16, 4,237, 17, 23, 57, 7, 16, 4,
+237, 17, 23, 57, 89, 34, 1, 51, 21, 20, 6, 15, 1, 14, 1, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 53, 52, 54, 63,
+ 1, 62, 1, 53, 52, 53, 54, 53, 19, 35, 53, 51, 2, 37,190, 61, 84, 90, 62, 47,131,109, 78,178, 98, 94,191,104,186,221, 67, 94,
+ 88, 67, 38, 2,196,202,202, 4, 68,154, 98,137, 82, 89, 59, 88, 49, 89,110, 69, 68,188, 57, 56,192,161, 76,131, 92, 86, 64, 84,
+ 63, 1, 4, 23, 19, 1, 14,254,255,255, 0, 37, 0, 0, 4,172, 7,107, 16, 38, 0, 36, 0, 0, 17, 7, 11,179, 0, 0, 1,117,
+ 0, 7, 64, 3, 79, 11, 1, 93, 49, 0, 0, 0,255,255, 0, 37, 0, 0, 4,172, 7,107, 16, 38, 0, 36, 0, 0, 17, 7, 11,177,
+ 0, 0, 1,117, 0, 7, 64, 3, 79, 11, 1, 93, 49, 0, 0, 0,255,255, 0, 37, 0, 0, 4,172, 7,109, 16, 38, 0, 36, 0, 0,
+ 17, 7, 11,180, 0, 0, 1,117, 0, 20,180, 5, 13, 17, 10, 7, 43, 64, 9, 32, 17, 47, 13, 0, 17, 15, 13, 4, 93, 49, 0, 0,
+255,255, 0, 37, 0, 0, 4,172, 7, 94, 16, 38, 0, 36, 0, 0, 17, 7, 11,178, 0, 0, 1,117, 0, 16,180, 5, 35, 20, 10, 7,
+ 43, 64, 5, 79, 35, 64, 20, 2, 93, 49, 0, 0,255,255, 0, 37, 0, 0, 4,172, 7, 78, 16, 38, 0, 36, 0, 0, 17, 7, 11,176,
+ 0, 0, 1,117, 0, 28,180, 5, 17, 14, 10, 7, 43, 64, 17,112, 14,127, 17, 48, 14, 63, 17, 32, 14, 47, 17, 0, 14, 15, 17, 8,
+ 93, 49, 0, 0, 0, 3, 0, 37, 0, 0, 4,172, 7,109, 0, 11, 0, 14, 0, 33, 0,193, 64, 87, 12, 37, 13, 12, 27, 28, 27, 14,
+ 37, 28, 27, 30, 37, 28, 27, 29, 37, 28, 28, 27, 32, 37, 15, 33, 31, 37, 15, 33, 13, 37, 33, 15, 33, 12, 37, 14, 12, 15, 15, 33,
+ 66, 12, 27, 15, 9, 30,151, 13, 3,200, 21, 9,144, 13,201, 32, 28, 29, 28, 24, 32, 33, 31, 13, 18, 6, 30, 14, 24, 12, 6, 27,
+ 0, 80, 24, 15, 6, 80, 18, 24, 75, 28, 47, 18, 75, 33, 34, 16,220,228,252,228, 16,238, 50, 16,238, 50, 17, 57, 17, 57, 57, 17,
+ 18, 57, 57, 17, 57, 17, 18, 57, 49, 0, 47, 60,230,230,214,238, 16,238, 18, 57, 57, 57, 48, 75, 83, 88, 7, 16, 8,237, 7, 16,
+ 5,237, 7, 5,237, 7, 5,237, 7, 16, 5,237, 7, 5,237, 7, 5,237, 7, 16, 8,237, 89, 34,178,128, 31, 1, 0, 93, 64, 20,
+133, 13,138, 14,138, 30,133, 31, 4,143, 12,143, 12,128, 13,128, 14,128, 30, 5, 93, 1, 93, 1, 52, 38, 35, 34, 6, 21, 20, 22,
+ 51, 50, 54, 7, 3, 33, 1, 46, 1, 53, 52, 54, 51, 50, 22, 21, 20, 6, 7, 1, 35, 3, 33, 3, 35, 3, 0, 89, 63, 64, 87, 88,
+ 63, 63, 89,152,213, 1,170,254,148, 58, 65,160,114,114,161, 64, 59, 1,172,209,110,253,245,108,209, 6, 90, 63, 89, 87, 65, 63,
+ 88, 88,252,253, 8, 3, 80, 33,121, 73,114,161,161,114, 73,118, 36,250,137, 1,133,254,123, 0, 0, 2, 0, 0, 0, 0, 4,156,
+ 5,213, 0, 15, 0, 19, 0,103, 64, 55, 13, 37, 15, 14, 12, 37, 15, 14, 17, 37, 14, 15, 14, 16, 37, 15, 15, 14, 66, 5,151, 3,
+ 11,151, 17, 16, 1,151, 0,136, 7,151, 17,176, 3,177, 13, 9, 17, 16, 15, 13, 12, 5, 14, 10, 0, 4, 8, 6, 2, 99, 18, 10,
+ 14, 47,212, 60,238, 50,214,196,196, 17, 18, 23, 57, 49, 0, 47, 60,238,238,238,244,238, 50, 16,238, 16,238, 48, 75, 83, 88, 7,
+ 16, 5,237, 7, 16, 5,237, 7, 5,237, 7, 5,237, 89, 34, 1, 21, 33, 17, 33, 21, 33, 17, 33, 21, 33, 17, 33, 3, 35, 1, 23,
+ 3, 33, 17, 4,137,254,174, 1, 51,254,205, 1,101,253,225,254,160,101,184, 1,154,120,202, 1, 53, 5,213,170,254, 70,170,253,
+227,170, 1,127,254,129, 5,213,170,252,252, 3, 4, 0, 0, 0,255,255, 0,139,254,117, 4, 49, 5,240, 16, 38, 2,163,100, 0,
+ 16, 6, 0, 38, 0, 0, 0, 0,255,255, 0,197, 0, 0, 4, 78, 7,107, 16, 38, 0, 40, 0, 0, 16, 7, 11,179, 0, 18, 1,117,
+255,255, 0,197, 0, 0, 4, 78, 7,107, 16, 38, 0, 40, 0, 0, 16, 7, 11,177, 0, 18, 1,117,255,255, 0,197, 0, 0, 4, 78,
+ 7,109, 16, 38, 0, 40, 0, 0, 16, 7, 11,180, 0, 18, 1,117,255,255, 0,197, 0, 0, 4, 78, 7, 78, 16, 38, 0, 40, 0, 0,
+ 16, 7, 11,176, 0, 18, 1,117,255,255, 0,201, 0, 0, 4, 6, 7,107, 16, 38, 0, 44, 0, 0, 16, 7, 11,179, 0, 0, 1,117,
+255,255, 0,201, 0, 0, 4, 6, 7,107, 16, 38, 0, 44, 0, 0, 16, 7, 11,177, 0, 0, 1,117,255,255, 0,201, 0, 0, 4, 6,
+ 7,109, 16, 38, 0, 44, 0, 0, 17, 7, 11,180, 0, 0, 1,117, 0, 11,180, 16, 32, 1, 0, 0, 16, 73, 99, 58, 49, 0, 0, 0,
+255,255, 0,201, 0, 0, 4, 6, 7, 78, 16, 38, 0, 44, 0, 0, 17, 7, 11,176, 0, 0, 1,117, 0, 8,180, 1, 18, 15, 0, 7,
+ 43, 49, 0, 0, 0, 2, 0, 8, 0, 0, 4, 78, 5,213, 0, 12, 0, 25, 0, 59, 64, 33, 23, 8,182, 10, 19,151, 0,136, 13,151,
+ 21, 10, 6, 19, 13, 6, 0, 4, 22, 20, 16, 50, 3, 49, 9, 48, 24, 20, 30, 11, 7, 48, 26, 16,252, 60,236, 50,236,252,236, 16,
+196, 23, 57, 49, 0, 47,198, 50,238,246,238, 16,238, 50, 48, 1, 32, 0, 17, 16, 0, 41, 1, 17, 35, 53, 51, 17, 1, 32, 54, 17,
+ 16, 38, 33, 35, 17, 33, 21, 33, 17, 1,180, 1, 86, 1, 68,254,187,254,171,254,209,125,125, 1, 47, 0,255,202,201,255, 0, 96,
+ 1, 8,254,248, 5,213,254,148,254,128,254,130,254,149, 2,197,149, 2,123,250,209,251, 1, 72, 1, 75,251,254, 43,149,253,225,
+255,255, 0,139, 0, 0, 4, 70, 7, 98, 16, 38, 0, 49, 0, 0, 17, 7, 11,178, 0, 0, 1,121, 0, 16,180, 4, 34, 19, 0, 7,
+ 43, 64, 5, 79, 34, 64, 19, 2, 93, 49, 0, 0,255,255, 0,117,255,227, 4, 92, 7,107, 16, 38, 0, 50, 0, 0, 17, 7, 11,179,
+ 0, 0, 1,117, 0, 7, 64, 3, 79, 24, 1, 93, 49, 0, 0, 0,255,255, 0,117,255,227, 4, 92, 7,107, 16, 38, 0, 50, 0, 0,
+ 17, 7, 11,177, 0, 0, 1,117, 0, 7, 64, 3, 79, 24, 1, 93, 49, 0, 0, 0,255,255, 0,117,255,227, 4, 92, 7,109, 16, 38,
+ 0, 50, 0, 0, 17, 7, 11,180, 0, 0, 1,117, 0, 20,180, 12, 26, 30, 18, 7, 43, 64, 9, 32, 30, 47, 26, 0, 30, 15, 26, 4,
+ 93, 49, 0, 0,255,255, 0,117,255,227, 4, 92, 7, 94, 16, 38, 0, 50, 0, 0, 17, 7, 11,178, 0, 0, 1,117, 0, 16,180, 12,
+ 48, 33, 18, 7, 43, 64, 5, 79, 48, 64, 33, 2, 93, 49, 0, 0,255,255, 0,117,255,227, 4, 92, 7, 78, 16, 38, 0, 50, 0, 0,
+ 17, 7, 11,176, 0, 0, 1,117, 0, 28,180, 12, 30, 27, 18, 7, 43, 64, 17,112, 27,127, 30, 48, 27, 63, 30, 32, 27, 47, 30, 0,
+ 27, 15, 30, 8, 93, 49, 0, 0, 0, 1, 0,150, 0,174, 4, 59, 4, 84, 0, 11, 0, 46, 64, 28, 10, 8, 7, 6, 4, 2, 1, 0,
+ 8, 11, 9, 5, 3, 12, 11, 10, 9, 8, 7, 5, 4, 3, 1, 9, 6, 2, 0, 12, 16,212, 60,204, 23, 57, 49, 0, 16,212, 60,204,
+ 50, 23, 57, 48, 19, 9, 1, 55, 9, 1, 23, 9, 1, 7, 9, 1,150, 1, 94,254,162,116, 1, 94, 1, 95,116,254,162, 1, 92,116,
+254,163,254,164, 1, 37, 1, 92, 1, 94,117,254,162, 1, 94,117,254,162,254,164,119, 1, 94,254,162, 0, 0, 0, 0, 3, 0, 8,
+255,186, 4,176, 6, 23, 0, 9, 0, 19, 0, 43, 0,107, 64, 58, 43, 41, 38, 11, 10, 9, 0, 4, 14, 29, 31, 32, 20, 14, 3, 42,
+ 38, 30, 3,151, 26, 14,151, 38,150, 26,153, 31, 31, 30, 44, 32, 35, 17, 42, 20, 23, 11, 10, 9, 0, 4, 6, 29, 35, 17, 41, 6,
+ 43, 6, 50, 23, 54, 17, 50, 35, 53, 44, 16,252,236,252,236,192, 18, 57, 17, 18, 57, 18, 23, 57, 17, 57, 57, 17, 18, 57, 17, 57,
+ 57, 49, 0, 47,228,244,236, 16,238,192, 16,192, 17, 18, 57, 57, 18, 57, 18, 23, 57, 17, 57, 57, 48, 1, 30, 1, 51, 50, 18, 17,
+ 52, 38, 39, 9, 1, 46, 1, 35, 34, 2, 17, 20, 22, 1, 22, 18, 21, 16, 2, 35, 34, 38, 39, 7, 39, 55, 38, 2, 53, 16, 18, 51,
+ 50, 22, 23, 55, 23, 1,115, 30,131, 84,154,135, 10, 10,253,221, 1,248, 25,115, 86,157,131, 5, 2,187, 41, 43,247,253,121,180,
+ 61,143,103,178, 32, 37,247,252,115,173, 57,139,100, 1, 47, 78, 90, 1, 25, 1, 73,110,136, 45,253,203, 2,207, 81, 85,254,220,
+254,134, 80,101, 2,230, 81,254,254,163,254,122,254,128, 81, 81,203, 70,252, 73, 1, 6,158, 1,135, 1,128, 82, 80,201, 74, 0,
+255,255, 0,147,255,227, 4, 61, 7,107, 16, 38, 0, 56, 0, 0, 17, 7, 11,179, 0, 0, 1,117, 0, 7, 64, 3, 79, 31, 1, 93,
+ 49, 0, 0, 0,255,255, 0,147,255,227, 4, 61, 7,107, 16, 38, 0, 56, 0, 0, 17, 7, 11,177, 0, 0, 1,117, 0, 7, 64, 3,
+ 79, 31, 1, 93, 49, 0, 0, 0,255,255, 0,147,255,227, 4, 61, 7,109, 16, 38, 0, 56, 0, 0, 17, 7, 11,180, 0, 0, 1,117,
+ 0, 20,180, 17, 32, 36, 1, 7, 43, 64, 9, 32, 36, 47, 32, 0, 36, 15, 32, 4, 93, 49, 0, 0,255,255, 0,147,255,227, 4, 61,
+ 7, 78, 16, 38, 0, 56, 0, 0, 17, 7, 11,176, 0, 0, 1,117, 0, 28,180, 17, 36, 33, 1, 7, 43, 64, 17,112, 33,127, 36, 48,
+ 33, 63, 36, 32, 33, 47, 36, 0, 33, 15, 36, 8, 93, 49, 0, 0,255,255, 0, 37, 0, 0, 4,172, 7,107, 16, 38, 0, 60, 0, 0,
+ 17, 7, 11,177, 0, 0, 1,117, 0, 7, 64, 3, 32, 9, 1, 93, 49, 0, 0, 0, 0, 2, 0,201, 0, 0, 4,141, 5,213, 0, 8,
+ 0, 21, 0, 52,181, 1,151, 18, 0,151, 11,184, 1, 8, 64, 19, 9,136, 20, 8, 2, 18, 12, 0, 5, 50, 15, 56, 19, 10, 0, 30,
+ 9, 51, 22, 16,252,236, 50, 50,252,236, 17, 57, 57, 57, 57, 49, 0, 47,244,252,236,212,236, 48, 1, 17, 51, 50, 54, 53, 52, 38,
+ 35, 1, 51, 17, 51, 32, 22, 21, 20, 6, 33, 35, 17, 35, 1,147,234,158,157,157,158,254, 76,202,254, 1, 4,248,248,254,252,254,
+202, 4, 33,253,243,132,131,131,131, 1,180,254,242,210,218,219,209,254,145, 0, 0, 1, 0,188,255,227, 4,125, 6, 20, 0, 47,
+ 0, 86, 64, 49, 45, 39, 33, 12, 4, 6, 13, 32, 0, 4, 42, 22,139, 23, 26,140, 19, 42,140, 3,155, 19,153, 46, 12, 9, 13, 29,
+ 32, 33, 39, 9, 1, 36, 39, 6, 6, 29, 6, 36, 16, 22, 45, 6, 16, 68, 0, 70, 48, 16,244,236,252,204, 16,198,238,212,238, 16,
+238, 17, 57, 57, 18, 57, 18, 57, 49, 0, 47,228,254,238, 16,254,213,238, 18, 23, 57, 23, 57, 48, 19, 52, 54, 51, 50, 22, 23, 14,
+ 1, 21, 20, 22, 31, 1, 30, 1, 21, 20, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 47, 1, 46, 1, 53, 52, 54, 55,
+ 46, 1, 35, 34, 6, 21, 17, 35,188,210,216,204,210, 2,155,168, 55, 67, 58,151,111,224,196, 69,135, 66, 76,133, 59,108,128, 65,
+120, 67, 92, 91,162,156, 2,121,113,121,114,187, 4,113,213,206,221,216, 14,124,100, 49, 77, 42, 37, 93,164,116,154,178, 25, 24,
+164, 31, 30, 97, 81, 71, 95, 74, 39, 56,133, 79,128,171, 35,107,114,131,139,251,147, 0, 0, 0,255,255, 0,133,255,227, 4, 35,
+ 6,102, 16, 38, 0, 68, 0, 0, 16, 6, 0, 67, 0, 0, 0, 0,255,255, 0,133,255,227, 4, 35, 6,102, 16, 38, 0, 68, 0, 0,
+ 16, 6, 0,118, 0, 0, 0, 0,255,255, 0,133,255,227, 4, 35, 6,102, 16, 38, 0, 68, 0, 0, 16, 6, 2, 95, 0, 0, 0, 0,
+255,255, 0,133,255,227, 4, 35, 6, 55, 16, 38, 0, 68, 0, 0, 16, 6, 2,110, 0, 0, 0, 0,255,255, 0,133,255,227, 4, 35,
+ 6, 16, 16, 38, 0, 68, 0, 0, 16, 6, 0,106, 0, 0, 0, 0,255,255, 0,133,255,227, 4, 35, 7, 6, 16, 38, 0, 68, 0, 0,
+ 16, 6, 2,108, 0, 0, 0, 0, 0, 3, 0, 41,255,227, 4,176, 4,123, 0, 10, 0, 19, 0, 67, 0,143, 64, 73, 61, 55, 15, 48,
+ 12, 18, 3, 54, 11, 37, 8, 0, 30, 67, 11, 1, 31,139, 30,141, 27, 8,140, 34, 55,139, 54,191, 15, 46, 11,182, 20, 1,193, 51,
+ 15,140, 64, 58,190, 40, 34,153, 68, 2, 5, 0, 24, 37, 61, 3, 47, 18, 46, 5, 21, 18, 77, 47, 0,117, 30, 11, 77, 20, 67, 5,
+ 77, 54, 43,115, 68, 16,244,196,236,252,236,196,252,196,236, 50, 18, 57, 17, 18, 23, 57, 17, 18, 57, 49, 0, 16,228, 50,244, 60,
+236, 50,244, 60,236, 50, 16,244,238, 16,254, 60,244,238, 17, 18, 57, 18, 57, 17, 57, 17, 18, 23, 57, 17, 18, 57, 48, 64, 9, 48,
+ 53, 48, 54, 48, 55, 48, 56, 4, 93, 1, 53, 35, 34, 6, 21, 20, 22, 51, 50, 54, 1, 53, 52, 38, 35, 34, 6, 29, 1, 5, 33, 14,
+ 1, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 39, 14, 1, 35, 34, 38, 53, 52, 54, 59, 1, 53, 52, 38, 35, 34, 6, 7,
+ 53, 62, 1, 51, 50, 22, 23, 62, 1, 51, 50, 22, 17, 2, 31, 49,169,120, 89, 83, 92, 74, 1,237, 77, 87, 87, 76, 1,235,254, 21,
+ 1, 1,101,112, 79,129, 50, 55,132, 71,110,149, 32, 39,133, 97,156,163,200,191,117, 99, 94, 56,132, 62, 77,132, 60, 91,124, 37,
+ 33,132, 89,174,145, 1,186, 72, 90,113, 89, 97,133, 1,143, 52,151,133,136,157, 43,143, 15, 35, 34,161,144, 51, 51,172, 41, 43,
+ 82, 78, 80, 80,172,164,171,179, 88,120,128, 43, 39,168, 35, 33, 63, 64, 61, 66,237,254,206, 0,255,255, 0,195,254,117, 4, 37,
+ 4,123, 16, 38, 2,163,104, 0, 16, 6, 0, 70, 0, 0, 0, 0,255,255, 0,123,255,227, 4, 88, 6,102, 16, 38, 0, 72, 0, 0,
+ 16, 6, 0, 67, 14, 0, 0, 0,255,255, 0,123,255,227, 4, 88, 6,102, 16, 38, 0, 72, 0, 0, 16, 6, 0,118, 14, 0, 0, 0,
+255,255, 0,123,255,227, 4, 88, 6,102, 16, 38, 0, 72, 0, 0, 16, 6, 2, 95, 14, 0, 0, 0,255,255, 0,123,255,227, 4, 88,
+ 6, 16, 16, 38, 0, 72, 0, 0, 17, 6, 0,106, 14, 0, 0, 7, 64, 3, 64, 29, 1, 93, 49, 0,255,255, 0,178, 0, 0, 4, 68,
+ 6,102, 16, 38, 0,243, 0, 0, 16, 6, 0, 67, 0, 0, 0, 0,255,255, 0,178, 0, 0, 4, 68, 6,102, 16, 38, 0,243, 0, 0,
+ 16, 6, 0,118, 0, 0, 0, 0,255,255, 0,178, 0, 0, 4, 68, 6,102, 16, 38, 0,243, 0, 0, 17, 6, 2, 95, 0, 0, 0, 9,
+ 64, 5, 64, 10, 48, 10, 2, 93, 49, 0, 0, 0,255,255, 0,178, 0, 0, 4, 68, 6, 16, 16, 38, 0,243, 0, 0, 17, 6, 0,106,
+ 24, 0, 0, 8,180, 3, 16, 13, 6, 7, 43, 49, 0, 2, 0,137,255,227, 4, 72, 6, 20, 0, 26, 0, 41, 0,139, 64, 79, 18, 23,
+ 19, 18, 1, 0, 13, 14, 15, 16, 4, 17, 23, 0, 1, 0, 22, 23, 23, 24, 23, 21, 23, 20, 21, 24, 24, 23, 66, 26, 25, 24, 21, 20,
+ 19, 6, 22, 15, 30, 18, 0, 22, 30,140, 12, 36,140, 6,153, 12, 22,155, 42, 18, 21, 24, 3, 39, 20, 19, 22, 3, 33, 9, 26, 25,
+ 3, 15, 0, 33, 39, 18, 3, 68, 33, 18, 9, 62, 42, 16,244,236,252,236, 17, 57, 57, 17, 57, 57, 17, 18, 23, 57, 17, 23, 57, 49,
+ 0, 16,236,204,244,236, 16,238, 18, 57, 57, 18, 57, 18, 23, 57, 48, 75, 83, 88, 7, 16, 8,237, 7, 16, 5,237, 7, 16, 5,237,
+ 23, 57, 7, 8,237, 89, 34, 1, 22, 18, 21, 16, 2, 35, 34, 2, 17, 16, 18, 51, 50, 22, 23, 46, 1, 39, 5, 39, 55, 39, 51, 23,
+ 37, 23, 3, 46, 1, 35, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 2,205,197,182,251,229,228,251,251,224, 34, 35, 15, 33, 72,
+ 38,254,233, 30,237,182,219,127, 1, 33, 33,174, 35, 82, 45,146,153,148,136,137,148, 58, 5, 47,212,254,132,200,254,244,254,216,
+ 1, 40, 1, 12, 1, 9, 1, 40, 2, 2, 45, 89, 44, 92, 98, 80,200,145, 94, 98,254, 23, 13, 13,210,199,196,212,212,196,110,203,
+255,255, 0,195, 0, 0, 4, 27, 6, 55, 16, 38, 0, 81, 0, 0, 16, 6, 2,110, 0, 0, 0, 0,255,255, 0,137,255,227, 4, 72,
+ 6,102, 16, 38, 0, 82, 0, 0, 16, 6, 0, 67, 0, 0, 0, 0,255,255, 0,137,255,227, 4, 72, 6,102, 16, 38, 0, 82, 0, 0,
+ 16, 6, 0,118, 0, 0, 0, 0,255,255, 0,137,255,227, 4, 72, 6,102, 16, 38, 0, 82, 0, 0, 17, 6, 2, 95, 0, 0, 0, 16,
+180, 15, 26, 30, 21, 7, 43, 64, 5, 15, 26, 0, 30, 2, 93, 49,255,255, 0,137,255,227, 4, 72, 6, 55, 16, 38, 0, 82, 0, 0,
+ 17, 6, 2,110, 0, 0, 0, 24,180, 15, 46, 32, 21, 7, 43, 64, 13, 48, 32, 63, 46, 32, 32, 47, 46, 16, 32, 31, 46, 6, 93, 49,
+255,255, 0,137,255,227, 4, 72, 6, 16, 16, 38, 0, 82, 0, 0, 17, 6, 0,106, 0, 0, 0, 24,180, 9, 30, 27, 3, 7, 43, 64,
+ 13,127, 30,112, 27, 95, 30, 80, 27, 79, 30, 64, 27, 6, 93, 49, 0, 3, 0, 88, 0,150, 4,121, 4,111, 0, 3, 0, 7, 0, 11,
+ 0, 39, 64, 19, 2,254, 0, 4,254, 6, 8,160, 0, 10, 12, 9, 5, 1,119, 8, 4, 0, 12, 16,212, 60,196,252, 60,196, 49, 0,
+ 16,212,196,252,212,236, 16,238, 48, 1, 51, 21, 35, 17, 51, 21, 35, 5, 33, 21, 33, 1,238,245,245,245,245,254,106, 4, 33,251,
+223, 1,139,245, 3,217,246,162,170, 0, 0, 0, 0, 3, 0, 47,255,160, 4,150, 4,188, 0, 9, 0, 19, 0, 43, 0,115, 64, 62,
+ 43, 44, 38, 31, 29, 26, 19, 10, 1, 0, 4, 13, 41, 38, 32, 20, 13, 4, 42, 38, 30, 26, 4,140, 38, 13,140, 26,190, 38,153, 44,
+ 43, 44, 42, 20, 23, 16, 32, 30, 35, 19, 10, 1, 0, 4, 7, 41, 23, 16, 29, 7, 31, 7, 18, 35, 68, 16, 18, 23, 62, 44, 16,244,
+236,252,236,192, 18, 57, 17, 18, 57, 18, 23, 57, 17, 57, 57, 17, 18, 57, 57, 17, 57, 49, 0, 16,228,244,236, 16,238, 16,192, 16,
+192, 17, 18, 57, 57, 18, 57, 18, 23, 57, 17, 57, 57, 17, 18, 57, 48, 9, 1, 30, 1, 51, 50, 54, 53, 52, 38, 39, 46, 1, 35, 34,
+ 6, 21, 20, 22, 23, 7, 46, 1, 53, 16, 18, 51, 50, 22, 23, 55, 23, 7, 30, 1, 21, 16, 2, 35, 34, 38, 39, 7, 39, 3,109,254,
+ 49, 36,101, 65,141,144, 12, 72, 35, 99, 67,139,149, 14, 14,139, 39, 41,246,233,100,158, 60,147, 93,164, 42, 44,246,234,103,157,
+ 57,160, 92, 3, 12,253,209, 47, 47,219,213, 52,111,175, 48, 46,214,202, 48,116, 71,160, 71,195,113, 1, 30, 1, 46, 55, 56,176,
+ 77,195, 66,193,122,254,225,254,211, 59, 60,186, 76, 0, 0, 0,255,255, 0,195,255,227, 4, 27, 6,102, 16, 38, 0, 88, 0, 0,
+ 16, 6, 0, 67, 0, 0, 0, 0,255,255, 0,195,255,227, 4, 27, 6,102, 16, 38, 0, 88, 0, 0, 16, 6, 0,118, 0, 0, 0, 0,
+255,255, 0,195,255,227, 4, 27, 6,102, 16, 38, 0, 88, 0, 0, 17, 6, 2, 95, 0, 0, 0, 16,180, 11, 22, 26, 1, 7, 43, 64,
+ 5, 15, 22, 0, 26, 2, 93, 49,255,255, 0,195,255,227, 4, 27, 6, 16, 16, 38, 0, 88, 0, 0, 17, 6, 0,106, 0, 0, 0, 24,
+180, 10, 26, 23, 2, 7, 43, 64, 13,127, 26,112, 23, 95, 26, 80, 23, 79, 26, 64, 23, 6, 93, 49,255,255, 0,104,254, 86, 4,129,
+ 6,102, 16, 38, 0, 92, 0, 0, 16, 6, 0,118, 0, 0, 0, 0, 0, 2, 0,190,254, 86, 4, 84, 6, 31, 0, 16, 0, 28, 0, 51,
+ 64, 28, 5, 0, 26, 20,140, 8, 26,140, 14,153, 8,190, 1,195, 3,197, 29, 17, 18, 11, 71, 23, 4, 0, 6, 2, 70, 29, 16,244,
+236, 50, 50,252,236, 49, 0, 16,236,228,228,244,236, 16,238, 17, 57, 57, 48, 37, 17, 35, 17, 51, 17, 62, 1, 51, 50, 18, 17, 16,
+ 2, 35, 34, 38, 1, 52, 38, 35, 34, 6, 21, 20, 22, 51, 50, 54, 1,119,185,185, 46,153,100,203,231,232,202,102,153, 1,240,135,
+133,134,138,138,134,133,135,141,253,201, 7,201,253,178, 83, 87,254,198,254,234,254,239,254,201, 87, 1,245,214,218,219,213,212,
+220,218, 0, 0,255,255, 0,104,254, 86, 4,129, 6, 16, 16, 38, 0, 92, 0, 0, 16, 6, 0,106, 0, 0, 0, 0,255,255, 0, 37,
+ 0, 0, 4,172, 7, 48, 16, 38, 11,189, 0, 0, 17, 6, 0, 36, 0, 0, 0, 20,180, 9, 2, 3, 14, 7, 43, 64, 9, 64, 3, 79,
+ 2, 32, 3, 47, 2, 4, 93, 49,255,255, 0,133,255,227, 4, 35, 5,246, 16, 38, 2,128, 0, 0, 16, 6, 0, 68, 0, 0, 0, 0,
+255,255, 0, 37, 0, 0, 4,172, 7,109, 16, 38, 11,184, 0, 0, 17, 6, 0, 36, 0, 0, 0, 24,180, 19, 8, 0, 24, 7, 43, 64,
+ 13, 95, 8, 80, 0, 79, 8, 64, 0, 47, 8, 32, 0, 6, 93, 49,255,255, 0,133,255,227, 4, 35, 6, 72, 16, 38, 2,130, 0, 0,
+ 16, 6, 0, 68, 0, 0, 0, 0,255,255, 0, 37,254,117, 4,224, 5,213, 16, 39, 2,109, 1,199, 0, 0, 16, 6, 0, 36, 0, 0,
+255,255, 0,133,254,117, 4,114, 4,123, 16, 39, 2,109, 1, 89, 0, 0, 16, 6, 0, 68, 0, 0,255,255, 0,139,255,227, 4, 49,
+ 7,107, 16, 38, 0, 38, 0, 0, 16, 7, 11,177, 0, 90, 1,117,255,255, 0,195,255,227, 4, 37, 6,102, 16, 38, 0, 70, 0, 0,
+ 16, 6, 0,118, 90, 0, 0, 0,255,255, 0,139,255,227, 4, 49, 7,116, 16, 39, 11,180, 0,126, 1,124, 16, 6, 0, 38, 0, 0,
+255,255, 0,195,255,227, 4, 37, 6,102, 16, 38, 2, 95, 90, 0, 16, 6, 0, 70, 0, 0, 0, 0,255,255, 0,139,255,227, 4, 49,
+ 7, 80, 16, 38, 11,185, 75, 0, 16, 6, 0, 38, 0, 0, 0, 0,255,255, 0,195,255,227, 4, 37, 6, 16, 16, 38, 2,131, 75, 0,
+ 16, 6, 0, 70, 0, 0, 0, 0,255,255, 0,139,255,227, 4, 49, 7,109, 16, 38, 0, 38, 0, 0, 16, 7, 11,181, 0, 90, 1,117,
+255,255, 0,195,255,227, 4, 37, 6,102, 16, 38, 0, 70, 0, 0, 16, 6, 2, 96, 90, 0, 0, 0,255,255, 0,137, 0, 0, 4, 82,
+ 7,103, 16, 38, 0, 39, 0, 0, 16, 7, 11,181,255,178, 1,111,255,255, 0,123,255,227, 5, 32, 6, 21, 16, 39, 11,175, 2, 58,
+255,175, 17, 6, 0, 71, 0, 0, 0, 13,185, 0, 0, 0, 64, 56, 64, 3,127, 0, 1, 93, 49, 0,255,255, 0, 8, 0, 0, 4, 78,
+ 5,213, 16, 6, 0,146, 0, 0, 0, 2, 0,123,255,227, 4,209, 6, 20, 0, 24, 0, 36, 0, 72, 64, 9, 13, 0, 34, 28, 7, 3,
+231, 9, 1,184, 1, 12, 64, 28, 34,140, 22, 28,140, 16,153, 22,190, 5,155, 11, 2, 31, 12, 4, 3, 0, 6, 8, 10, 6, 71, 25,
+ 18, 19, 72, 37, 16,244,236,252, 60,196,252, 23, 60,196, 49, 0, 47,236,228,244,236, 16,238,253, 60,238, 50, 17, 18, 57, 57, 48,
+ 1, 17, 33, 53, 33, 53, 51, 21, 51, 21, 35, 17, 35, 53, 14, 1, 35, 34, 2, 17, 16, 18, 51, 50, 22, 1, 20, 22, 51, 50, 54, 53,
+ 52, 38, 35, 34, 6, 3, 90,254,207, 1, 49,184,191,191,184, 46,153,100,203,233,234,202,101,154,254, 15,136,133,133,139,139,133,
+133,136, 3,209, 1, 53,121,149,149,121,250,250,141, 83, 87, 1, 59, 1, 21, 1, 17, 1, 55, 87,254, 11,214,218,220,212,213,219,
+218, 0, 0, 0,255,255, 0,197, 0, 0, 4, 78, 7, 48, 16, 38, 11,189, 18, 0, 16, 6, 0, 40, 0, 0, 0, 0,255,255, 0,123,
+255,227, 4, 88, 5,246, 16, 38, 2,128, 35, 0, 16, 6, 0, 72, 0, 0, 0, 0,255,255, 0,197, 0, 0, 4, 78, 7,109, 16, 38,
+ 11,184, 18, 0, 16, 6, 0, 40, 0, 0, 0, 0,255,255, 0,123,255,227, 4, 88, 6, 72, 16, 38, 2,130, 14, 0, 16, 6, 0, 72,
+ 0, 0, 0, 0,255,255, 0,197, 0, 0, 4, 78, 7, 80, 16, 38, 11,185, 18, 0, 16, 6, 0, 40, 0, 0, 0, 0,255,255, 0,123,
+255,227, 4, 88, 6, 16, 16, 38, 2,131, 14, 0, 16, 6, 0, 72, 0, 0, 0, 0,255,255, 0,197,254,117, 4, 78, 5,213, 16, 39,
+ 2,109, 1, 49, 0, 0, 16, 6, 0, 40, 0, 0,255,255, 0,123,254,117, 4, 88, 4,123, 16, 39, 2,109, 0,246, 0, 0, 16, 6,
+ 0, 72, 0, 0,255,255, 0,197, 0, 0, 4, 78, 7,103, 16, 38, 0, 40, 0, 0, 16, 7, 11,181, 0, 36, 1,111,255,255, 0,123,
+255,227, 4, 88, 6, 97, 16, 38, 0, 72, 0, 0, 16, 6, 2, 96, 35,251, 0, 0,255,255, 0,102,255,227, 4, 80, 7,109, 16, 39,
+ 11,180, 0, 0, 1,117, 16, 6, 0, 42, 0, 0,255,255, 0,123,254, 72, 4, 18, 6,102, 16, 38, 2, 95, 0, 0, 16, 6, 0, 74,
+ 0, 0, 0, 0,255,255, 0,102,255,227, 4, 80, 7,109, 16, 38, 11,184, 50, 0, 16, 6, 0, 42, 0, 0, 0, 0,255,255, 0,123,
+254, 72, 4, 18, 6, 72, 16, 38, 2,130, 0, 0, 16, 6, 0, 74, 0, 0, 0, 0,255,255, 0,102,255,227, 4, 80, 7, 80, 16, 38,
+ 11,185, 50, 0, 16, 6, 0, 42, 0, 0, 0, 0,255,255, 0,123,254, 72, 4, 18, 6, 16, 16, 38, 2,131, 0, 0, 16, 6, 0, 74,
+ 0, 0, 0, 0,255,255, 0,102,253,195, 4, 80, 5,240, 16, 39, 2,162, 0,128,255,225, 16, 6, 0, 42, 0, 0,255,255, 0,123,
+254, 72, 4, 18, 6, 78, 16, 39, 2,142, 0, 17, 1, 46, 16, 6, 0, 74, 0, 0,255,255, 0,137, 0, 0, 4, 72, 7,109, 16, 39,
+ 11,180, 0, 0, 1,117, 17, 6, 0, 43, 0, 0, 0, 20,180, 12, 2, 6, 7, 7, 43, 64, 9, 32, 6, 47, 2, 0, 6, 15, 2, 4,
+ 93, 49, 0, 0,255,255, 0,195, 0, 0, 4, 27, 7,109, 16, 39, 11,180, 0, 0, 1,117, 17, 6, 0, 75, 0, 0, 0, 24, 0, 75,
+176, 18, 81, 88,185, 0, 0, 0, 64, 56, 89, 64, 7,112, 0, 96, 0, 79, 0, 3, 93, 48, 0, 0, 0, 2, 0, 3, 0, 0, 4,206,
+ 5,213, 0, 19, 0, 23, 0, 63, 64, 33, 6, 2, 18,151, 9, 20, 17, 12,151, 21,177, 4, 0,136, 14, 10, 7, 12, 23, 4, 30, 9,
+ 5, 49, 18, 13, 20, 1, 30, 16, 0, 48, 24, 16,252, 60,236, 50, 50,204,252, 60,236, 50, 50,204, 49, 0, 47, 60,228, 50,252,236,
+220, 60, 60,236, 50, 50, 48, 19, 51, 21, 33, 53, 51, 21, 51, 21, 35, 17, 35, 17, 33, 17, 35, 17, 35, 53, 51, 23, 21, 33, 53,137,
+202, 2, 42,202,135,135,202,253,214,202,134,134,202, 2, 42, 5,213,224,224,224,164,251,175, 2,199,253, 57, 4, 81,164,164,224,
+224, 0, 0, 0, 0, 1, 0, 70, 0, 0, 4, 27, 6, 20, 0, 27, 0, 63, 64, 34, 9, 22, 3, 0, 3, 1, 18, 14,182, 21, 13, 6,
+140, 25,190, 16,155, 10, 1, 2, 6, 0, 74, 16, 19, 17, 21, 9, 6, 14, 16, 11, 70, 28, 16,244, 60,204,252, 50, 50,204, 16,252,
+236, 49, 0, 47, 60,236,244,236,220, 60,236, 50, 17, 23, 57, 57, 48, 1, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 35, 53,
+ 51, 53, 51, 21, 33, 21, 33, 17, 62, 1, 51, 50, 22, 4, 27,185,106,113,129,139,184,125,125,184, 1, 97,254,159, 49,168,115,171,
+169, 2,182,253, 74, 2,182,151,142,183,171,253,135, 4,246,164,122,122,164,254,194, 96, 99,225,255,255, 0,201, 0, 0, 4, 6,
+ 7, 94, 16, 39, 11,178, 0, 0, 1,117, 17, 6, 0, 44, 0, 0, 0, 24,180, 31, 24, 9, 30, 7, 43, 64, 13, 79, 24, 64, 9, 63,
+ 24, 48, 9, 47, 24, 32, 9, 6, 93, 49, 0, 0,255,255, 0,178, 0, 0, 4, 68, 6, 55, 16, 38, 2,110, 0, 0, 16, 6, 0,243,
+ 0, 0, 0, 0,255,255, 0,201, 0, 0, 4, 6, 7, 48, 16, 38, 11,189, 0, 0, 17, 6, 0, 44, 0, 0, 0, 16,180, 5, 2, 3,
+ 4, 7, 43, 64, 5, 79, 2, 64, 3, 2, 93, 49,255,255, 0,178, 0, 0, 4, 68, 5,246, 16, 38, 2,128, 0, 0, 16, 6, 0,243,
+ 0, 0, 0, 0,255,255, 0,201, 0, 0, 4, 6, 7,109, 16, 38, 11,184, 0, 0, 17, 6, 0, 44, 0, 0, 0, 16,180, 15, 8, 0,
+ 14, 7, 43, 64, 5, 79, 8, 64, 0, 2, 93, 49,255,255, 0,178, 0, 0, 4, 68, 6, 72, 16, 38, 2,130, 0, 0, 16, 6, 0,243,
+ 0, 0, 0, 0,255,255, 0,201,254,117, 4, 6, 5,213, 16, 38, 0, 44, 0, 0, 16, 6, 2,109, 70, 0, 0, 0,255,255, 0,178,
+254,117, 4, 68, 6, 20, 16, 38, 0, 76, 0, 0, 16, 6, 2,109, 80, 0, 0, 0,255,255, 0,201, 0, 0, 4, 6, 7, 80, 16, 38,
+ 11,185, 0, 0, 16, 6, 0, 44, 0, 0, 0, 0, 0, 1, 0,178, 0, 0, 4, 68, 4, 96, 0, 9, 0, 34, 64, 18, 8,182, 0,194,
+ 6, 2,182, 4, 3, 76, 1, 6, 5, 76, 0, 75, 7, 10, 16,212,228,236,252,236, 49, 0, 47,236, 50,244,236, 48, 1, 33, 17, 33,
+ 21, 33, 53, 33, 17, 33, 1, 0, 1,215, 1,109,252,110, 1,109,254,225, 4, 96,252, 47,143,143, 3, 66, 0, 0, 0, 2,255,255,
+255,230, 4,204, 5,216, 0, 20, 0, 32, 0, 61, 64, 31, 1, 0,178, 4,151, 17,153, 33, 10, 24, 32,151, 11, 21,136, 25, 29,151,
+ 27, 1, 11, 9, 12, 34, 26, 22, 24, 29, 21, 31, 33, 16,212,204, 50,220,204, 50, 16,212,204,196,196, 49, 0, 47,236, 50,244, 60,
+236, 50, 50, 16,244,236,244,204, 48, 37, 53, 30, 1, 51, 50, 55, 54, 53, 17, 33, 53, 33, 17, 16, 7, 6, 35, 34, 39, 38, 1, 33,
+ 21, 35, 17, 51, 21, 33, 53, 51, 17, 35, 2,140, 61,132, 71, 97, 39, 38,254,253, 1,141, 72, 72,168, 65, 65, 64,253, 45, 2, 93,
+228,228,253,163,228,228, 64,236, 81, 81, 74, 75,203, 3, 68,170,252, 18,254,230,117,117, 22, 22, 5,195,170,251,127,170,170, 4,
+129, 0, 0, 0, 0, 4,255,251,254, 75, 4,138, 6, 20, 0, 13, 0, 17, 0, 27, 0, 31, 0, 73, 64, 38, 10,140, 9,195, 32, 2,
+ 27,182, 18, 17, 31,196, 14, 28,155, 3, 18,194, 20, 24,182, 23, 10, 3, 14, 1, 6, 15, 4, 33, 21, 29, 19, 24, 18, 28, 26, 32,
+ 16,212, 60,196,204,220, 60,204, 16,220, 60,252, 60,196,196, 49, 0, 47,236, 50,228, 50,252, 60,236, 50, 16,238, 50, 16,244,236,
+ 48, 5, 17, 33, 53, 33, 17, 20, 6, 43, 1, 53, 51, 50, 54, 17, 51, 21, 35, 5, 33, 17, 33, 21, 33, 53, 33, 17, 35, 19, 51, 21,
+ 35, 3,210,254,195, 1,245,179,165,254,234, 90, 90,184,184,252,105, 1,130, 1, 44,253, 18, 1, 43,235,235,151,151, 31, 3,229,
+143,251,140,195,211,156,125, 6,165,233,192,252, 47,143,143, 3, 66, 2, 67,233,255,255, 0,109,255,227, 3,202, 7,109, 16, 39,
+ 11,180, 0, 48, 1,117, 16, 6, 0, 45, 0, 0,255,255, 0,186,254, 86, 3,168, 6,102, 16, 38, 2, 95, 0, 0, 16, 6, 1,226,
+ 0, 0, 0, 0,255,255, 0,137,253,224, 4,201, 5,213, 16, 38, 2,162,106,254, 16, 6, 0, 46, 0, 0, 0, 0,255,255, 0,236,
+253,224, 4,178, 6, 20, 16, 39, 2,162, 0,144,255,254, 16, 6, 0, 78, 0, 0, 0, 1, 0,236, 0, 0, 4,178, 4, 96, 0, 11,
+ 0,196, 64, 57, 8, 23, 9, 8, 5, 6, 5, 7, 23, 6, 6, 5, 9, 23, 3, 2, 8, 23, 7, 8, 3, 2, 5, 23, 6, 5, 2, 3,
+ 2, 4, 23, 3, 3, 2, 66, 8, 5, 2, 3, 3, 0,194, 10, 6, 8, 5, 4, 3, 6, 9, 1, 6, 6, 68, 0, 69, 12, 16,244,236,
+236, 50, 17, 23, 57, 49, 0, 47, 60,236, 50, 23, 57, 48, 75, 83, 88, 7, 16, 5,237, 7, 16, 8,237, 7, 8,237, 7, 4,237, 7,
+ 16, 5,237, 7, 16, 8,237, 89, 34,178, 8, 7, 1, 1, 93, 64, 82, 6, 2, 8, 8, 22, 2, 24, 5, 24, 8, 53, 2, 52, 5, 54,
+ 8, 70, 2,102, 2,117, 2,118, 5, 12, 9, 3, 8, 8, 25, 3, 23, 4, 24, 5, 25, 6, 26, 7, 24, 8, 40, 3, 39, 5, 40, 7,
+ 59, 3, 59, 4, 55, 5, 57, 7, 55, 8, 74, 3, 73, 7, 89, 6, 89, 7,107, 3,105, 4,105, 6,105, 7,121, 3,120, 5,121, 6,
+121, 7, 28, 93, 0, 93, 19, 51, 17, 1, 51, 9, 1, 35, 1, 7, 17, 35,236,190, 1,227,224,254, 71, 1,254,225,254, 98,137,190,
+ 4, 96,254, 47, 1,209,254, 90,253, 70, 2, 66,129,254, 63, 0,255,255, 0,200, 0, 0, 4,115, 7,108, 16, 39, 11,177,254,237,
+ 1,118, 17, 6, 0, 47, 0, 0, 0, 7, 64, 3, 32, 0, 1, 93, 49, 0, 0, 0,255,255, 0,160, 0, 0, 4, 10, 7,108, 16, 39,
+ 11,177,255,161, 1,118, 17, 6, 0, 79, 0, 0, 0, 24, 0, 75,176, 14, 81, 88,185, 0, 0, 0, 64, 56, 89, 64, 7,159, 0,143,
+ 0, 79, 0, 3, 93, 48, 0, 0,255,255, 0,215,253,224, 4,115, 5,213, 16, 38, 2,162,102,254, 16, 6, 0, 47, 0, 0, 0, 0,
+255,255, 0,160,253,224, 4, 10, 6, 31, 16, 38, 2,162,251,254, 16, 6, 0, 79, 0, 0, 0, 0,255,255, 0,215, 0, 0, 4,115,
+ 5,213, 16, 39, 11,175, 0,174,255,109, 16, 6, 0, 47, 0, 0,255,255, 0,160, 0, 0, 4,134, 6, 31, 16, 39, 11,175, 1,160,
+255,185, 16, 6, 0, 79, 0, 0,255,255, 0,215, 0, 0, 4,115, 5,213, 16, 39, 0,121, 1, 96, 0,134, 16, 6, 0, 47, 0, 0,
+255,255, 0,160, 0, 0, 4,188, 6, 31, 16, 39, 0,121, 1,215, 0,144, 16, 6, 0, 79, 0, 0, 0, 1,255,246, 0, 0, 4,115,
+ 5,213, 0, 13, 0, 55, 64, 30, 12, 11, 10, 4, 3, 2, 6, 0, 6,151, 0,136, 8, 3, 4, 7, 1, 11, 14, 0, 12, 5, 1, 30,
+ 7, 49, 9, 0, 52, 14, 16,252, 60,236,236, 50, 46, 17, 18, 57, 17, 18, 57, 57, 49, 0, 47,228,236, 17, 23, 57, 48, 19, 51, 17,
+ 37, 23, 1, 17, 33, 21, 33, 17, 7, 39, 55,215,203, 1, 59, 78,254,119, 2,209,252,100,145, 80,225, 5,213,253,152,219,111,254,
+238,253,227,170, 2, 59,106,110,158, 0, 0, 0, 0, 1, 0, 76, 0, 0, 4, 10, 6, 31, 0, 21, 0, 62, 64, 33, 20, 19, 18, 12,
+ 11, 10, 6, 9, 0, 3, 14,182, 16,197, 3,182, 5, 11, 12, 22, 15, 19, 3, 6, 20, 4, 17, 0, 6, 15, 13, 9, 22, 16,212, 60,
+204,252, 60,204, 50, 57, 57, 57, 17, 18, 57, 57, 49, 0, 47,236,252,236, 17, 57, 57, 23, 57, 48, 1, 20, 22, 59, 1, 21, 35, 34,
+ 38, 53, 17, 5, 39, 1, 17, 33, 53, 33, 17, 37, 23, 1, 2,127, 91, 89,215,233,165,181,254,213, 80, 1,123,254,217, 1,223, 1,
+ 59, 80,254,117, 1,150,124,126,156,212,194, 1, 36,209,111, 1, 8, 2, 47,144,253,190,219,110,254,237, 0, 0,255,255, 0,139,
+ 0, 0, 4, 70, 7,107, 16, 39, 11,177, 0, 33, 1,117, 16, 6, 0, 49, 0, 0,255,255, 0,195, 0, 0, 4, 27, 6,109, 16, 38,
+ 0,118, 20, 7, 16, 6, 0, 81, 0, 0, 0, 0,255,255, 0,139,253,224, 4, 70, 5,213, 16, 38, 2,162, 42,254, 16, 6, 0, 49,
+ 0, 0, 0, 0,255,255, 0,195,253,224, 4, 27, 4,123, 16, 38, 2,162, 48,254, 16, 6, 0, 81, 0, 0, 0, 0,255,255, 0,139,
+ 0, 0, 4, 70, 7,109, 16, 38, 0, 49, 0, 0, 16, 7, 11,181, 0, 42, 1,117,255,255, 0,195, 0, 0, 4, 27, 6,102, 16, 38,
+ 0, 81, 0, 0, 16, 6, 2, 96,244, 0, 0, 0,255,255, 0, 24, 0, 0, 4,150, 6, 20, 16, 38, 0, 81,123, 0, 16, 7, 2, 89,
+254, 73, 0, 0, 0, 1, 0,147,254, 86, 4, 61, 5,242, 0, 29, 0, 50, 64, 28, 24, 19, 13, 0, 4, 21, 16,151, 27,150, 22,136,
+ 21, 7,151, 6, 21, 7, 13, 30, 0, 49, 19, 23, 30, 22, 48, 30, 16,244,236, 50,252,236,196, 49, 0, 47,212,236, 16,228,244,236,
+ 17, 23, 57, 48, 1, 17, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 53, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51,
+ 50, 18, 4, 61, 89, 90,165,205,167, 90, 45, 44,116,124,141,152,202,202, 54,184,126,187,185, 3,231,252, 5,195,105,106,156, 62,
+ 62,146, 3,241,180,169,218,203,252, 87, 5,213,198,111,116,254,251, 0, 0, 0, 0, 1, 0,195,254, 86, 4, 27, 4,123, 0, 32,
+ 0, 50, 64, 28, 25, 20, 13, 0, 4, 22, 16,140, 29,190, 23,194, 22, 6,182, 7, 22, 7, 13, 6, 0, 74, 20, 24, 6, 23, 70, 33,
+ 16,244,236, 50,252,236,196, 49, 0, 47,212,236, 16,228,244,236, 17, 23, 57, 48, 1, 17, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54,
+ 53, 17, 52, 38, 35, 34, 7, 6, 21, 17, 35, 17, 51, 21, 54, 55, 54, 51, 50, 23, 22, 4, 27, 89, 90,165,205,185, 90, 45, 44,106,
+113,129, 70, 69,184,184, 49, 84, 84,115,171, 84, 85, 2,182,253, 54,195,105,106,156, 62, 62,126, 2,202,151,142, 91, 92,171,253,
+135, 4, 96,168, 96, 50, 49,113,112, 0, 0, 0,255,255, 0,117,255,227, 4, 92, 7, 48, 16, 38, 11,189, 0, 0, 17, 6, 0, 50,
+ 0, 0, 0, 20,180, 16, 2, 3, 22, 7, 43, 64, 9, 79, 2, 64, 3, 47, 2, 32, 3, 4, 93, 49,255,255, 0,137,255,227, 4, 72,
+ 5,246, 16, 38, 2,128, 0, 0, 17, 6, 0, 82, 0, 0, 0, 8,180, 19, 2, 3, 25, 7, 43, 49,255,255, 0,117,255,227, 4, 92,
+ 7,109, 16, 38, 11,184, 0, 0, 17, 6, 0, 50, 0, 0, 0, 16,180, 26, 8, 0, 32, 7, 43, 64, 5, 47, 8, 32, 0, 2, 93, 49,
+255,255, 0,137,255,227, 4, 72, 6, 72, 16, 38, 2,130, 0, 0, 17, 6, 0, 82, 0, 0, 0, 16,180, 29, 8, 0, 35, 7, 43, 64,
+ 5, 15, 8, 0, 0, 2, 93, 49,255,255, 0,117,255,227, 4, 92, 7,107, 16, 38, 11,186, 0, 0, 16, 6, 0, 50, 0, 0, 0, 0,
+255,255, 0,137,255,227, 4, 72, 6,102, 16, 38, 2,135, 0, 0, 16, 6, 0, 82, 0, 0, 0, 0, 0, 2, 0, 72, 0, 0, 4,193,
+ 5,213, 0, 16, 0, 25, 0, 59, 64, 31, 14,151, 12, 17, 10,151, 8,136, 23, 0,151, 12,177, 1, 23, 17, 8, 2, 20, 15, 11, 30,
+ 24, 9, 13, 0, 45, 20, 30, 5, 26, 16,220,236,252,196,196,212,236, 50, 18, 57, 57, 57, 57, 49, 0, 47,236,236, 50,244,236, 50,
+ 16,238, 48, 37, 21, 33, 32, 2, 17, 16, 18, 41, 1, 21, 33, 17, 33, 21, 33, 17, 1, 34, 6, 17, 16, 22, 59, 1, 17, 4,193,253,
+163,254,217,245,244, 1, 40, 2, 82,254,154, 1, 72,254,184,254,254,177,139,139,177, 61,170,170, 1, 77, 1,156, 1,161, 1, 75,
+170,254, 70,170,253,227, 4,129,230,254,164,254,166,229, 4,129, 0, 3, 0, 14,255,227, 4,186, 4,123, 0, 10, 0, 22, 0, 56,
+ 0,105, 64, 57, 50, 47, 9, 6, 0, 25, 31, 23, 38, 32, 11, 56, 23, 0, 32,139, 31,141, 11, 0,182, 23, 28, 11,140, 35, 23,193,
+ 17, 6,140, 53, 47,190, 41, 35,153, 57, 0, 3, 50, 38, 24, 9, 77, 14,117, 31, 3, 77, 23, 67, 20, 77, 44,115, 57, 16,244,236,
+252,236,196,252,236, 50, 57, 57, 17, 57, 49, 0, 16,228, 50,244, 60,236, 50,228, 16,238, 50, 16,238, 16,244,238, 17, 18, 57, 17,
+ 18, 57, 17, 18, 57, 17, 18, 57, 17, 57, 48, 1, 52, 54, 53, 52, 38, 35, 34, 6, 29, 1, 1, 50, 54, 53, 16, 38, 35, 34, 6, 17,
+ 16, 22, 1, 33, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 39, 14, 1, 35, 34, 2, 17, 16, 18, 51, 50, 22, 23, 62, 1,
+ 51, 50, 22, 17, 4, 23, 2, 80, 86, 87, 77,254,166,102, 82, 80,104,103, 80, 80, 3,172,254, 21, 99,112, 80,131, 47, 59,125, 74,
+ 98,147, 48, 52,128, 84,189,170,170,189, 89,128, 47, 37,130, 87,175,144, 2,145, 11, 38, 9,145,135,137,158, 43,253,234,168,239,
+ 1, 35,174,167,254,243,254,243,167, 1,135, 84,163,144, 53, 51,172, 43, 41, 67, 66, 68, 65, 1, 20, 1, 56, 1, 56, 1, 20, 62,
+ 65, 62, 65,237,254,206, 0, 0,255,255, 0,143, 0, 0, 4,209, 7,107, 16, 39, 11,177,255,181, 1,117, 16, 6, 0, 53, 0, 0,
+255,255, 1,106, 0, 0, 4,136, 6,109, 16, 39, 0,118, 0,206, 0, 7, 16, 6, 0, 85, 0, 0,255,255, 0,143,253,224, 4,209,
+ 5,213, 16, 38, 2,162,114,254, 16, 6, 0, 53, 0, 0, 0, 0,255,255, 1, 32,253,224, 4,131, 4,123, 16, 38, 2,162,136,254,
+ 16, 6, 0, 85, 0, 0, 0, 0,255,255, 0,143, 0, 0, 4,209, 7,103, 16, 38, 0, 53, 0, 0, 16, 7, 11,181,255,196, 1,111,
+255,255, 1,106, 0, 0, 4,131, 6,102, 16, 38, 0, 85, 0, 0, 16, 6, 2, 96, 90, 0, 0, 0,255,255, 0,139,255,227, 4, 74,
+ 7,107, 16, 39, 11,177, 0, 25, 1,117, 16, 6, 0, 54, 0, 0,255,255, 0,213,255,227, 4, 6, 6,109, 16, 38, 0,118, 26, 7,
+ 16, 6, 0, 86, 0, 0, 0, 0,255,255, 0,139,255,227, 4, 74, 7,109, 16, 39, 11,180, 0, 0, 1,117, 16, 6, 0, 54, 0, 0,
+255,255, 0,213,255,227, 4, 6, 6,102, 16, 38, 2, 95, 0, 0, 16, 6, 0, 86, 0, 0, 0, 0,255,255, 0,139,254,117, 4, 74,
+ 5,240, 16, 38, 2,163, 0, 0, 16, 6, 0, 54, 0, 0, 0, 0,255,255, 0,213,254,117, 4, 6, 4,123, 16, 38, 2,163, 0, 0,
+ 16, 6, 0, 86, 0, 0, 0, 0,255,255, 0,139,255,227, 4, 74, 7,109, 16, 38, 0, 54, 0, 0, 16, 7, 11,181, 0, 0, 1,117,
+255,255, 0,213,255,227, 4, 6, 6,102, 16, 38, 0, 86, 0, 0, 16, 6, 2, 96, 0, 0, 0, 0,255,255, 0, 47,254,117, 4,162,
+ 5,213, 16, 38, 2,163, 0, 0, 16, 6, 0, 55, 0, 0, 0, 0,255,255, 0,131,254,117, 4, 8, 5,158, 16, 38, 2,163,121, 0,
+ 16, 6, 0, 87, 0, 0, 0, 0,255,255, 0, 47, 0, 0, 4,162, 7,109, 16, 38, 0, 55, 0, 0, 17, 7, 11,181, 0, 6, 1,117,
+ 0, 8,180, 1, 13, 9, 0, 7, 43, 49, 0, 0,255,255, 0,131, 0, 0, 4, 8, 6,126, 16, 38, 0, 87, 0, 0, 16, 7, 11,175,
+ 1, 20, 0, 24, 0, 1, 0, 47, 0, 0, 4,162, 5,213, 0, 15, 0, 45, 64, 23, 4, 12,151, 7, 11, 3, 15,151, 0,136, 8, 1,
+ 58, 5, 7, 3, 30, 12, 0, 58, 10, 14, 16, 16,212, 60,236,204,252, 60,204,236, 49, 0, 47,244,236, 50,212, 60,236, 50, 48, 19,
+ 33, 21, 33, 17, 33, 21, 33, 17, 35, 17, 33, 53, 33, 17, 33, 47, 4,115,254, 45, 1, 9,254,247,203,254,247, 1, 9,254, 43, 5,
+213,170,253,192,170,253,191, 2, 65,170, 2, 64, 0, 1, 0,131, 0, 0, 4, 8, 5,158, 0, 27, 0, 66, 64, 33, 18, 9, 12, 5,
+ 21,182, 8, 20, 4, 24,182, 27, 1, 25,194, 12,182, 15, 12, 15, 13, 2, 6, 8, 4, 0, 6, 21, 25, 19, 23, 27, 28, 16,212, 60,
+ 60,196,196,252, 60, 60,196,196, 50, 57, 57, 49, 0, 47,236,244, 60,196,236, 50,212, 60,236, 50, 17, 57, 57, 48, 1, 17, 33, 21,
+ 33, 21, 51, 21, 35, 21, 20, 22, 59, 1, 21, 35, 34, 38, 61, 1, 35, 53, 51, 53, 33, 53, 33, 17, 2,102, 1,162,254, 94,229,229,
+ 94,117,207,225,207,170,229,229,254,213, 1, 43, 5,158,254,194,143,233,142,233,124, 98,147,166,203,233,142,233,143, 1, 62, 0,
+255,255, 0,147,255,227, 4, 61, 7, 94, 16, 39, 11,178, 0, 0, 1,117, 17, 6, 0, 56, 0, 0, 0, 16,180, 47, 24, 9, 31, 7,
+ 43, 64, 5, 79, 24, 64, 9, 2, 93, 49, 0, 0,255,255, 0,195,255,227, 4, 27, 6, 55, 16, 38, 2,110, 0, 0, 17, 6, 0, 88,
+ 0, 0, 0, 16,180, 39, 22, 8, 29, 7, 43, 64, 5, 47, 22, 32, 8, 2, 93, 49,255,255, 0,147,255,227, 4, 61, 7, 48, 16, 38,
+ 11,189, 0, 0, 17, 6, 0, 56, 0, 0, 0, 20,180, 21, 2, 3, 5, 7, 43, 64, 9, 79, 2, 64, 3, 47, 2, 32, 3, 4, 93, 49,
+255,255, 0,195,255,227, 4, 27, 5,246, 16, 38, 2,128, 0, 0, 17, 6, 0, 88, 0, 0, 0, 8,180, 15, 1, 0, 5, 7, 43, 49,
+255,255, 0,147,255,227, 4, 61, 7,109, 16, 38, 11,184, 0, 0, 17, 6, 0, 56, 0, 0, 0, 16,180, 31, 8, 0, 15, 7, 43, 64,
+ 5, 47, 8, 32, 0, 2, 93, 49,255,255, 0,195,255,227, 4, 27, 6, 72, 16, 38, 2,130, 0, 0, 17, 6, 0, 88, 0, 0, 0, 16,
+180, 25, 8, 0, 15, 7, 43, 64, 5, 15, 8, 0, 0, 2, 93, 49,255,255, 0,147,255,227, 4, 61, 8, 85, 16, 38, 0, 56, 0, 0,
+ 16, 7, 2,108, 0, 10, 1, 79,255,255, 0,195,255,227, 4, 27, 6,217, 16, 38, 0, 88, 0, 0, 16, 6, 2,108, 15,211, 0, 0,
+255,255, 0,147,255,227, 4, 61, 7,107, 16, 38, 11,186, 0, 0, 16, 6, 0, 56, 0, 0, 0, 0,255,255, 0,195,255,227, 4, 27,
+ 6,102, 16, 38, 2,135, 0, 0, 16, 6, 0, 88, 0, 0, 0, 0,255,255, 0,147,254,101, 4, 61, 5,213, 16, 38, 0, 56, 0, 0,
+ 16, 6, 2,109, 28,240, 0, 0,255,255, 0,195,254,117, 4,176, 4, 94, 16, 38, 0, 88, 0, 0, 16, 7, 2,109, 1,151, 0, 0,
+255,255, 0, 0, 0, 0, 4,209, 7,116, 16, 39, 11,180, 0, 0, 1,124, 17, 6, 0, 58, 0, 0, 0, 8,180, 14, 2, 6, 7, 7,
+ 43, 49, 0, 0,255,255, 0, 0, 0, 0, 4,209, 6,109, 16, 38, 2, 95, 0, 7, 17, 6, 0, 90, 0, 0, 0, 8,180, 14, 2, 6,
+ 7, 7, 43, 49,255,255, 0, 37, 0, 0, 4,172, 7,116, 16, 39, 11,180, 0, 0, 1,124, 17, 6, 0, 60, 0, 0, 0, 8,180, 11,
+ 2, 6, 7, 7, 43, 49, 0, 0,255,255, 0,104,254, 86, 4,129, 6,109, 16, 38, 2, 95, 12, 7, 16, 6, 0, 92, 0, 0, 0, 0,
+255,255, 0, 37, 0, 0, 4,172, 7, 78, 16, 38, 0, 60, 0, 0, 17, 7, 11,176, 0, 0, 1,117, 0, 8,180, 4, 15, 12, 0, 7,
+ 43, 49, 0, 0,255,255, 0,156, 0, 0, 4,145, 7,107, 16, 39, 11,177, 0, 27, 1,117, 16, 6, 0, 61, 0, 0,255,255, 0,203,
+ 0, 0, 4, 16, 6,109, 16, 38, 0,118, 86, 7, 16, 6, 0, 93, 0, 0, 0, 0,255,255, 0,156, 0, 0, 4,145, 7, 80, 16, 38,
+ 11,185, 50, 0, 16, 6, 0, 61, 0, 0, 0, 0,255,255, 0,203, 0, 0, 4, 16, 6, 16, 16, 38, 2,131, 0, 0, 16, 6, 0, 93,
+ 0, 0, 0, 0,255,255, 0,156, 0, 0, 4,145, 7,109, 16, 38, 0, 61, 0, 0, 16, 7, 11,181, 0, 0, 1,117,255,255, 0,203,
+ 0, 0, 4, 16, 6,102, 16, 38, 0, 93, 0, 0, 16, 6, 2, 96, 0, 0, 0, 0, 0, 1, 0,195, 0, 0, 4, 39, 6, 20, 0, 15,
+ 0, 44, 64, 22, 0, 7, 12, 4,182, 5, 12,140, 11,155, 5,194, 2, 13, 10, 11, 0, 6, 5, 3, 7, 16, 16,212, 60,196,252,196,
+ 57, 57, 49, 0, 47,228,252,236, 16,238, 18, 57, 57, 48, 1, 17, 35, 17, 33, 53, 33, 53, 52, 54, 59, 1, 21, 35, 34, 6, 2,166,
+184,254,213, 1, 43,169,179,221,209, 99, 77, 4,195,251, 61, 3,209,143, 78,184,174,153, 81, 0, 0, 2, 0, 70,255,227, 4, 88,
+ 6, 20, 0, 26, 0, 37, 0, 0, 1, 62, 1, 51, 50, 18, 17, 16, 2, 35, 34, 38, 39, 21, 35, 17, 35, 53, 51, 53, 51, 21, 51, 33,
+ 21, 33, 35, 0, 16, 38, 35, 34, 6, 21, 20, 22, 51, 50, 1,121, 44,155,102,202,232,233,203,100,153, 46,184,123,123,184, 2, 1,
+ 97,254,159, 2, 2, 29,136,133,134,138,138,134,133, 3,209, 82, 88,254,201,254,239,254,235,254,197, 87, 83,141, 4,246,164,122,
+122,164,252, 99, 1,172,218,219,213,212,220, 0, 0, 3, 0, 20, 0, 0, 4,165, 5,213, 0, 8, 0, 17, 0, 41, 0, 63, 64, 36,
+ 25, 0,151, 10, 9,151, 18,136, 1,151, 10,177, 31, 17, 11, 25, 31, 19, 8, 2, 7, 0, 14, 30, 22, 5, 50, 28, 9, 0, 30, 18,
+ 33, 36, 39, 43, 16,212,220,212, 57,236, 50,220,236,212,236, 17, 23, 57, 49, 0, 47,236,236,244,236, 16,238, 57, 48, 1, 17, 51,
+ 50, 54, 53, 52, 38, 35, 3, 17, 51, 50, 54, 53, 52, 38, 35, 37, 33, 50, 22, 21, 20, 6, 7, 30, 1, 21, 20, 4, 41, 1, 17, 34,
+ 6, 29, 1, 35, 53, 52, 54, 2, 28,120,176,150,158,168,120,116,146,131,129,148,254,194, 1, 66,229,248,131,131,147,167,254,246,
+254,249,254,190, 62,100,156,169, 2,201,253,221,123,141,146,137, 2,102,254, 62,112,125,113,100,166,198,181,137,158, 20, 22,207,
+160,203,207, 5, 47, 87,112, 49, 70,159,185, 0,255,255, 0,166, 0, 0, 4,113, 5,213, 16, 6, 3, 62, 0, 0, 0, 2, 0,193,
+255,227, 4, 88, 6, 20, 0, 18, 0, 29, 0, 0, 1, 62, 1, 51, 50, 18, 17, 16, 2, 35, 34, 38, 39, 21, 35, 17, 33, 21, 33, 0,
+ 16, 38, 35, 34, 6, 21, 20, 22, 51, 50, 1,121, 44,155,102,202,232,233,203,100,153, 46,184, 2,240,253,200, 2, 29,136,133,134,
+138,138,134,133, 3,209, 82, 88,254,201,254,239,254,235,254,197, 87, 83,141, 6, 20,184,251,253, 1,172,218,219,213,212,220, 0,
+ 0, 2, 0, 48, 0, 0, 4,161, 5,213, 0, 10, 0, 24, 0, 0, 1, 17, 51, 50, 55, 54, 53, 52, 39, 38, 35, 39, 51, 4, 23, 22,
+ 21, 20, 7, 6, 41, 1, 17, 39, 1, 1,161,239,176, 75, 75, 79, 79,168,239,235, 1,123,101, 53,133,133,254,249,254, 70,166, 1,
+113, 2,201,253,221, 62, 61,141,146, 68, 69,164, 15,191,100,161,203,103,104, 3,180,228, 1, 61, 0, 2, 0, 60,255,227, 4,148,
+ 6, 20, 0, 12, 0, 33, 0, 0, 0, 16, 38, 35, 34, 7, 6, 21, 20, 23, 22, 51, 50, 1, 62, 1, 51, 50, 23, 22, 17, 16, 7, 6,
+ 35, 34, 39, 38, 39, 21, 35, 17, 39, 1, 3,210,136,132,134, 70, 68, 68, 70,134,132,254,108, 44,154,102,202,116,116,116,116,204,
+100, 76, 76, 46,184,194, 1,122, 1, 89, 1,172,218,109,110,213,212,110,110, 3, 82, 82, 88,155,156,254,239,254,235,158,157, 43,
+ 44, 83,141, 3,180,228, 1,124, 0, 1, 0,139,255,227, 4, 49, 5,240, 0, 25, 0, 47, 64, 7, 19, 50, 6, 49, 0, 12, 26, 16,
+220, 60,244,236, 49, 0, 64, 18, 13,179, 12,178, 16,151, 9, 25,179, 0,178, 22,151, 3,150, 9,153, 26, 16,228,244,236,244,236,
+ 16,238,246,238, 48, 19, 62, 1, 51, 32, 0, 17, 16, 0, 33, 34, 38, 39, 53, 30, 1, 51, 50, 18, 17, 16, 2, 35, 34, 6, 7,139,
+ 77,162, 91, 1, 29, 1, 63,254,195,254,225, 91,162, 77, 73,169, 88,197,196,196,197, 86,170, 74, 5,158, 41, 41,254,103,254,146,
+254,144,254,106, 41, 41,207, 61, 64, 1, 48, 1, 50, 1, 51, 1, 48, 64, 61, 0, 0, 1, 0, 60,255,227, 4,149, 6,103, 0, 34,
+ 0, 0, 37, 14, 1, 35, 32, 0, 17, 16, 0, 33, 50, 23, 54, 55, 54, 59, 1, 21, 34, 7, 6, 29, 1, 46, 1, 35, 34, 2, 21, 16,
+ 18, 51, 50, 54, 55, 3,226, 77,162, 91,254,225,254,195, 1, 63, 1, 29, 90, 79, 23, 42, 90,165, 20, 84, 51, 44, 74,170, 86,197,
+196,196,197, 88,169, 73, 53, 41, 41, 1,150, 1,112, 1, 42, 1,153, 20, 51, 50,106,156, 62, 53,135, 70, 61, 64,254,208,239,254,
+206,254,208, 64, 61, 0, 0, 0, 0, 1, 0, 94,255,227, 4,115, 5,142, 0, 33, 0, 0, 37, 14, 1, 35, 32, 0, 16, 0, 33, 50,
+ 23, 54, 55, 54, 59, 1, 21, 34, 7, 6, 29, 1, 46, 1, 35, 34, 6, 21, 20, 22, 51, 50, 54, 55, 3,192, 74,157, 82,254,252,254,
+219, 1, 37, 1, 4, 70, 67, 19, 61, 90,165, 20, 90, 45, 44, 73,147, 93,173,186,187,172, 96,152, 65, 57, 43, 43, 1, 56, 2, 40,
+ 1, 56, 16,114, 71,106,156, 62, 62,126,148, 65, 58,224,208,207,225, 59, 62, 0,255,255, 0, 8, 0, 0, 4, 78, 5,213, 16, 6,
+ 0,146, 0, 0, 0, 2, 0, 8, 0, 0, 4,201, 5,213, 0, 18, 0, 27, 0, 0, 1, 51, 32, 0, 17, 16, 0, 33, 35, 17, 34, 7,
+ 6, 29, 1, 35, 53, 52, 54, 1, 32, 54, 17, 16, 38, 33, 35, 17, 1, 70,233, 1, 86, 1, 68,254,188,254,170,233, 54, 60, 48,156,
+192, 1, 99, 0,255,202,201,255, 0, 26, 5,213,254,148,254,128,254,130,254,149, 5, 47, 47, 38,114, 49, 70,181,163,250,209,251,
+ 1, 72, 1, 75,251,251,119, 0, 0, 2, 0,131, 0, 0, 4, 78, 5,213, 0, 8, 0, 22, 0, 0, 1, 35, 34, 6, 21, 20, 22, 59,
+ 1, 1, 53, 33, 17, 33, 32, 36, 53, 52, 55, 54, 37, 51, 17, 3,131,239,168,158,150,176,239,253, 69, 3,134,254, 70,254,249,254,
+246, 53,101, 1,123,235, 2,201,137,146,141,123, 4,137,166,250, 43,207,203,161,100,191, 15, 1,194, 0, 0, 0, 0, 2, 0,157,
+255,227, 4, 52, 6, 20, 0, 10, 0, 29, 0, 0, 0, 16, 22, 51, 50, 54, 53, 52, 38, 35, 34, 3, 53, 33, 17, 35, 53, 14, 1, 35,
+ 34, 2, 17, 16, 18, 51, 50, 22, 23, 17, 1, 95,136,133,134,138,138,134,133,163, 2,240,184, 46,153,100,203,233,232,202,102,155,
+ 44, 3, 5,254, 84,218,220,212,213,219, 1,125,184,249,236,141, 83, 87, 1, 59, 1, 21, 1, 17, 1, 55, 88, 82, 1,139, 0, 0,
+ 0, 2, 0,136,254, 61, 4, 71, 4,123, 0, 11, 0, 55, 0, 0, 37, 50, 54, 53, 52, 38, 35, 34, 6, 21, 20, 22, 5, 22, 23, 22,
+ 21, 20, 7, 6, 35, 34, 47, 1, 53, 22, 23, 22, 51, 50, 51, 55, 54, 63, 1, 54, 53, 52, 39, 38, 39, 38, 39, 38, 39, 38, 17, 16,
+ 18, 51, 50, 18, 17, 16, 7, 6, 2,104,140,144,144,140,141,144,144, 1,167, 19, 40, 62,118,119,197,102, 50,151, 66, 70, 75, 73,
+ 9, 10, 32, 73, 60, 39, 27, 13, 17, 41, 24,105,235,121,124,246,234,233,246,123, 31,127,218,214,213,219,219,213,214,218, 76, 9,
+ 40, 61, 92,136, 82, 82, 12, 36,173, 24, 15, 15, 1, 2, 43, 28, 24, 46, 33, 19, 24, 21, 13, 1, 3,148,151, 1, 30, 1, 31, 1,
+ 45,254,211,254,225,254,226,151, 38, 0, 0, 0, 0, 1, 0,197, 0, 0, 4, 78, 5,213, 0, 11, 0, 43, 64, 10, 8, 4, 30, 0,
+ 49, 11, 6, 3, 51, 12, 16,252,196,196,252,236, 50, 49, 0, 64, 12, 6,151, 8, 10,151, 0,136, 4,151, 8,177, 2, 47,236,236,
+244,236, 16,238, 48, 1, 17, 33, 53, 33, 17, 33, 53, 33, 17, 33, 53, 4, 78,252,119, 2,191,253,114, 2,142,253, 84, 5,213,250,
+ 43,170, 2, 29,170, 1,186,170, 0, 2, 0,117,255,227, 4, 92, 5,240, 0, 21, 0, 28, 0, 61, 64, 12, 3, 2, 28, 50, 16, 54,
+ 9, 22, 50, 0, 53, 29, 16,244,236,196,244,236, 57, 57, 49, 0, 64, 20, 0, 22, 3, 1, 10,179, 9, 6,151, 13,150, 29, 22,151,
+ 1, 25,151, 19,153, 29, 16,244,236,212,238, 16,244,244,212,238, 18, 57, 17, 57, 48, 19, 53, 33, 53, 52, 2, 35, 34, 6, 7, 53,
+ 62, 1, 51, 50, 18, 17, 16, 2, 35, 34, 2, 19, 20, 18, 51, 50, 18, 55,117, 3, 19,138,150, 86,170, 74, 77,162, 91,253,247,247,
+253,253,246,215,140,148,148,126, 9, 2,233, 83, 8,241, 1, 23, 64, 61,207, 41, 41,254,128,254,121,254,122,254,128, 1,126, 1,
+ 35,248,254,251, 0,255,254, 0, 0, 1, 0,137,255,227, 4, 55, 5,240, 0, 40, 0, 62, 64, 11, 20, 9, 31, 16, 50, 3, 25, 50,
+ 38, 48, 41, 16,252,236,212,236,212,196,196, 49, 0, 64, 22, 10,179, 9, 13,151, 6,150, 41, 0, 22,151, 19,177, 41, 31,179, 32,
+ 28,151, 35,153, 41, 16,244,236,212,236, 16,244,236, 57, 16,244,236,212,236, 48, 1, 46, 1, 53, 52, 36, 51, 50, 22, 23, 21, 46,
+ 1, 35, 34, 6, 21, 20, 22, 59, 1, 21, 35, 34, 6, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 36, 53, 52, 54, 1,184,131,
+137, 1, 5,218, 73,189,121,104,190, 89,134,145,156,139,154,154,152,178,178,166, 98,198,102,103,214,103,245,254,235,156, 3, 31,
+ 34,162,123,181,221, 32, 32,186, 40, 40,123,115,109,122,166,153,130,141,150, 52, 53,201, 36, 38,235,206,149,199, 0, 1, 0, 63,
+254, 86, 4,146, 5,213, 0, 19, 0, 0, 1, 33, 21, 33, 17, 33, 21, 33, 17, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 53, 1,124,
+ 3, 22,253,181, 2, 12,253,244, 89, 90,165,176,138, 90, 45, 44, 5,213,170,254, 72,170,253, 35,195,105,106,156, 62, 62,126, 0,
+ 0, 1, 0,195,254, 86, 4, 39, 6, 20, 0, 36, 0, 0, 1, 21, 43, 1, 34, 7, 6, 29, 1, 33, 21, 33, 17, 20, 7, 6, 43, 1,
+ 53, 51, 50, 55, 54, 53, 3, 33, 53, 33, 53, 52, 55, 54, 55, 54, 59, 2, 4, 39,209, 2, 97, 39, 38, 1,129,254,127, 81, 82,181,
+ 70, 49,105, 38, 38, 2,254,215, 1, 40, 87, 37, 60, 70, 97, 9, 3, 6, 20,153, 41, 40,103, 99,143,252, 27,214, 96, 96,156, 48,
+ 49,153, 3,229,143, 78,180, 92, 39, 21, 26, 0, 0, 1, 0, 52,255,227, 4,157, 6,103, 0, 40, 0, 0, 37, 14, 1, 35, 32, 0,
+ 17, 16, 0, 33, 50, 23, 22, 23, 54, 55, 54, 59, 1, 21, 34, 7, 6, 7, 21, 46, 1, 35, 34, 2, 17, 16, 18, 51, 50, 54, 55, 17,
+ 35, 53, 33, 4, 30, 82,202,118,254,228,254,196, 1, 64, 1, 28, 94, 86, 17, 17, 15, 21, 90,166, 19, 84, 51, 43, 1, 80,170, 96,
+196,198,192,198, 66,102, 40,216, 1,154,123, 75, 77, 1,151, 1,111, 1,110, 1,153, 26, 6, 6, 26, 25,106,156, 62, 54,134, 27,
+ 77, 73,254,207,254,206,254,201,254,213, 31, 33, 1,145,166, 0, 0, 2, 0, 28,254, 82, 4,182, 5, 73, 0, 13, 0, 21, 0, 0,
+ 1, 0, 17, 20, 33, 32, 53, 16, 9, 1, 51, 9, 1, 51, 1, 2, 17, 20, 51, 50, 53, 16, 2,218, 1, 68,254, 96,254, 72, 1, 38,
+254, 48,216, 1,116, 1,116,218,253,162,198,216,204, 2,138,254, 63,254,117,236,236, 1,111, 1,228, 2,184,253,213, 2, 43,252,
+166,254,211,254,188,138,138, 1, 69, 0, 0, 0, 0, 1, 0, 65, 0, 0, 4,144, 6, 20, 0, 38, 0, 0, 1, 17, 35, 20, 23, 22,
+ 55, 54, 55, 54, 53, 17, 51, 17, 20, 6, 35, 34, 39, 38, 53, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 17, 54, 55, 54, 51, 50,
+ 22, 2,243, 1, 34, 38, 55, 19, 54, 47,167,152,154,127, 74, 73, 95, 66, 71,125,166,166, 77, 17, 75, 85,118,152, 2,182,254,224,
+153, 49, 52, 4, 2, 73, 66,156, 1,155,254,101,228,225, 96, 96,214, 1, 32,151,142,183,171,253,135, 6, 20,253,164,134, 12, 49,
+225, 0, 0, 0, 0, 1, 0,201, 0, 0, 4, 58, 5,213, 0, 17, 0, 0, 1, 33, 53, 33, 21, 33, 17, 20, 23, 22, 59, 1, 23, 35,
+ 34, 39, 38, 53, 2, 2,254,199, 3, 61,254,199, 44, 45, 90,185, 1,217,170, 92, 89, 5, 43,170,170,252,122,127, 61, 62,171,106,
+102,198, 0, 0, 0, 1, 0,201, 0, 0, 4, 6, 5,213, 0, 21, 0, 0, 19, 33, 21, 33, 17, 51, 33, 21, 33, 35, 17, 33, 21, 33,
+ 53, 33, 17, 33, 53, 33, 17, 33,201, 3, 61,254,199, 2, 1, 9,254,247, 2, 1, 57,252,195, 1, 57,254,249, 1, 7,254,199, 5,
+213,170,253,192,170,254,105,170,170, 1,151,170, 2, 64, 0, 0, 0, 1, 0,110, 0, 0, 4,195, 5,213, 0, 25, 0, 0, 1, 54,
+ 55, 54, 51, 50, 31, 1, 7, 39, 38, 35, 34, 7, 6, 15, 1, 1, 35, 1, 7, 17, 35, 17, 51, 17, 2,135,161,105, 21, 20,126, 92,
+ 47,106, 33, 45, 60, 17, 19, 66,109,164, 2, 86,244,254, 25,154,203,203, 4,156,170, 12, 3, 99, 51,114, 37, 51, 4, 15,115,172,
+252,141, 2,236,164,253,184, 5,213,253,104, 0, 0, 1, 0,236, 0, 0, 4,178, 6, 20, 0, 23, 0, 0, 19, 53, 52, 55, 54, 59,
+ 1, 21, 35, 34, 7, 6, 21, 51, 17, 1, 51, 9, 1, 35, 1, 7, 17, 35,236, 89, 90,165,205,185, 90, 45, 44, 5, 1,227,224,254,
+ 71, 1,254,225,254, 98,137,190, 3,234,148,195,105,106,156, 62, 62,126,254, 17, 1,209,254, 90,253, 70, 2, 66,129,254, 63, 0,
+ 0, 1, 0,160, 0, 0, 4, 10, 6, 31, 0, 23, 0, 0, 1, 20, 22, 59, 1, 21, 35, 34, 38, 61, 1, 35, 53, 51, 17, 33, 53, 33,
+ 17, 59, 1, 21, 43, 1, 2,127, 91, 89,215,233,165,181,228,228,254,217, 1,223, 9,221,221, 9, 1,150,124,126,156,212,194,196,
+142, 2,167,144,252,201,142, 0, 0, 1, 0, 49, 0, 0, 4,109, 5,213, 0, 15, 0, 0, 1, 37, 23, 9, 1, 35, 9, 1, 35, 1,
+ 39, 5, 39, 1, 3, 51, 2, 67, 1, 92, 80,254,141, 1,241,191,254,191,254,182,191, 1,169, 34,254,150, 80, 1,129,174,191, 4,
+189,242,110,254,254,251,193, 2,192,253, 64, 3,145, 74,251,111, 1, 10, 1,124, 0, 1, 0,109,255,229, 4,111, 5,213, 0, 34,
+ 0, 0, 37, 14, 1, 35, 34, 38, 25, 1, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 35, 53,
+ 14, 1, 35, 34, 38, 2, 56, 34,105, 74,135,111,168, 53, 70, 80, 59,168, 57, 74, 73, 57,167,167, 33, 99, 63, 76,101,114, 72, 69,
+209, 1, 33, 3,254,252, 10,237,115,123,229, 3,246,252, 10,240,112,123,229, 3,246,250, 43, 96, 60, 63, 70, 0, 0, 1, 0, 29,
+254, 86, 4, 25, 5,213, 0, 18, 0, 0, 19, 51, 1, 17, 51, 17, 35, 1, 17, 20, 7, 6, 43, 1, 53, 50, 55, 54, 53,190,230, 1,
+198,175,230,254, 59, 81, 81,148, 27, 81, 40, 40, 5,213,251, 51, 4,205,250, 43, 4,205,251, 31,195,105,106,156, 62, 61,127, 0,
+ 0, 1, 0,195,254, 82, 4, 27, 4,123, 0, 19, 0, 0, 1, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51,
+ 50, 22, 4, 27,185,106,113,129,139,184,184, 49,168,115,171,169, 2,182,251,156, 4,100,151,142,183,171,253,135, 4, 96,168, 96,
+ 99,225, 0, 0, 0, 3, 0,117,255,227, 4, 92, 5,240, 0, 10, 0, 19, 0, 28, 0, 0, 1, 16, 2, 32, 2, 17, 16, 18, 51, 50,
+ 18, 3, 2, 39, 38, 35, 34, 7, 6, 3, 23, 22, 23, 22, 51, 50, 55, 54, 55, 4, 92,247,254, 6,246,247,252,253,247,212, 8, 58,
+ 68,154,153, 67, 59, 8, 1, 9, 57, 67,153,154, 68, 56, 9, 2,233,254,122,254,128, 1,126, 1,136, 1,135, 1,128,254,128,254,
+204, 1, 8,123,141,141,123,254,248,184,250,118,141,141,117,251,255,255, 0, 6,255,227, 4,167, 6, 21, 16, 39, 2,151, 1,121,
+ 1,164, 16, 6, 0, 50,145, 0,255,255, 0, 32,255,227, 4,178, 4,123, 16, 39, 2,151, 1,132, 0, 0, 16, 6, 0, 82,151, 0,
+ 0, 2, 0, 45,255,227, 4,164, 5,240, 0, 16, 0, 27, 0, 0, 19, 16, 37, 54, 51, 50, 23, 55, 51, 17, 35, 17, 7, 17, 6, 32,
+ 2, 1, 38, 35, 34, 2, 17, 16, 18, 51, 50, 55, 45, 1, 78, 53, 62,206,111,147,230,175,180,111,254, 56,221, 2,136, 61,138,138,
+121,121,138,138, 61, 2,233, 2,160, 89, 14,158,131,250, 43, 4,205,160,252,118,192, 1,126, 3, 94,141,254,230,254,183,254,184,
+254,230,141, 0, 0, 2, 0, 86,254, 82, 4,171, 4,123, 0, 19, 0, 32, 0, 0, 19, 16, 55, 54, 51, 50, 23, 21, 55, 51, 17, 35,
+ 17, 7, 17, 6, 35, 34, 39, 38, 55, 16, 23, 22, 51, 50, 55, 17, 38, 35, 34, 3, 6, 86,250, 80,101,210,111,126,231,176,181,110,
+211,234,111, 86,176,215, 19, 21,127, 65, 65,127,206, 40, 9, 2, 47, 1,180,115, 37,151, 43,110,250, 43, 4,205,157,253,248,151,
+188,146,254,254,117, 34, 3,109, 2,134,109,254,226, 66, 0, 0, 0, 2, 0, 56, 0, 0, 4,153, 5,213, 0, 23, 0, 33, 0, 0,
+ 1, 16, 5, 6, 43, 1, 17, 35, 17, 34, 7, 6, 29, 1, 35, 53, 52, 55, 54, 51, 33, 32, 19, 22, 1, 50, 55, 54, 53, 52, 38, 43,
+ 1, 17, 4,153,254,200, 86,110, 93,202, 54, 60, 48,156, 96, 96,126, 1, 39, 1,151, 82, 19,254, 4,211, 64, 22,156,141, 93, 4,
+ 23,254,164, 77, 22,253,168, 5, 47, 47, 38,114, 49, 70,181, 82, 81,254,220, 69,254,146,157, 56, 68,133,147,253,207, 0, 0, 0,
+ 0, 2, 0,190,254, 86, 4, 84, 5,152, 0, 14, 0, 42, 0, 0, 1, 16, 23, 22, 51, 50, 54, 53, 16, 39, 34, 35, 34, 3, 6, 17,
+ 54, 55, 50, 51, 50, 18, 17, 16, 2, 35, 34, 38, 39, 17, 35, 17, 16, 55, 54, 59, 1, 21, 35, 34, 7, 6, 21, 1,119,209, 29, 34,
+133,135,251, 9, 8,214, 46, 12, 91,194, 7, 7,203,231,232,202,102,153, 44,185,203, 63, 78,205,185,169, 9, 1, 2, 47,254,137,
+ 50, 7,218,214, 1,162, 14,254,239, 70, 1, 73,164, 6,254,198,254,234,254,239,254,201, 87, 83,253,201, 5,172, 1, 46, 79, 25,
+156,221, 14, 15, 0, 2, 0,143,254,248, 4,209, 5,213, 0, 22, 0, 31, 0, 0, 1, 22, 23, 22, 23, 19, 35, 3, 46, 1, 43, 1,
+ 17, 35, 17, 51, 17, 51, 50, 4, 21, 20, 6, 1, 17, 51, 50, 54, 53, 52, 38, 35, 2,248, 78, 55, 54, 83,203,217,178, 77,123, 99,
+193,203,203,213,246, 1, 6,161,253,208,221,145,142,151,144, 1,185, 20, 55, 55,167,254,104, 1,121,161, 93,254,145, 5,213,254,
+248,222,210,148,187, 2, 89,253,238,130,134,129,137, 0, 0, 0, 0, 1, 0,139,255,227, 4, 74, 5,240, 0, 39, 0, 0, 19, 62,
+ 1, 51, 50, 4, 21, 20, 6, 15, 1, 14, 1, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 36, 53, 52, 54, 63, 1, 62, 1, 53,
+ 52, 38, 35, 34, 6, 7,225,105,190, 86,223, 1, 13,188,208,108,145,117,170,153,104,205,115,107,212,105,252,254,248,192,210,106,
+149,109,166,143, 94,185, 92, 5,162, 39, 39,241,200,160,190, 47, 25, 32,118,112,123,137, 68, 73,215, 45, 45,224,213,181,210, 49,
+ 24, 35,104, 99,113,133, 60, 59, 0, 1, 0,213,255,227, 4, 6, 4,123, 0, 39, 0, 0, 1, 62, 1, 51, 50, 22, 21, 20, 6, 15,
+ 2, 6, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 53, 52, 54, 63, 1, 62, 1, 53, 52, 38, 35, 34, 6, 7, 1, 14, 80,
+166, 90,202,218,146,159, 69, 8,245,134,122, 84,188,103,106,182, 83,210,236,141,137, 74,183, 92,123,125, 83,160, 79, 4, 57, 33,
+ 33,175,161,127,147, 31, 14, 2, 49,128, 89, 99, 53, 53,190, 35, 35,187,166,125,156, 26, 14, 35, 74, 75, 83, 81, 46, 46, 0, 0,
+255,255, 0,120, 0, 0, 4,109, 5,213, 16, 6, 2,223, 0, 0, 0, 2, 0,118,254, 86, 4, 91, 6, 20, 0, 8, 0, 33, 0, 0,
+ 1, 38, 39, 38, 35, 34, 7, 6, 51, 5, 3, 20, 23, 22, 59, 1, 21, 35, 34, 39, 38, 53, 17, 35, 32, 53, 52, 33, 50, 23, 22, 23,
+ 51, 21, 2, 56, 7, 18, 33,110,124, 3, 3,119, 1,120, 2, 39, 37,100,176,174,195, 81, 87,190,254,242, 1, 47,181, 82, 53, 18,
+191, 5, 4, 45, 23, 48, 65, 51,154,251, 61,103, 41, 40,153, 86, 92,180, 4,174,210,216, 96, 64,111,155, 0, 0, 0, 1, 0,131,
+254, 86, 4, 8, 5,158, 0, 32, 0, 0, 1, 17, 33, 21, 33, 17, 20, 22, 59, 1, 29, 1, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54,
+ 61, 1, 35, 34, 38, 53, 17, 33, 53, 33, 17, 2,102, 1,162,254, 94, 94,117,207, 89, 90,165,205,185, 90, 45, 44, 40,207,170,254,
+213, 1, 43, 5,158,254,194,143,253,160,124, 98,147, 20,195,105,106,156, 62, 62,126, 20,166,203, 2, 96,143, 1, 62, 0, 0, 0,
+ 0, 1, 0, 47, 0, 0, 4,162, 5,213, 0, 16, 0, 0, 1, 38, 7, 6, 29, 1, 35, 53, 52, 54, 51, 33, 21, 33, 17, 35, 17, 1,
+197,131, 70, 49,156,192,214, 2,221,254, 45,203, 5, 47, 8, 55, 38,114, 49, 70,181,163,170,250,213, 5, 43, 0, 0, 1, 0,131,
+ 0, 0, 4, 8, 6, 20, 0, 29, 0, 0, 1, 33, 21, 33, 17, 20, 22, 59, 1, 21, 35, 34, 38, 53, 17, 33, 53, 33, 53, 52, 55, 54,
+ 59, 1, 21, 35, 34, 7, 6, 21, 2,102, 1,162,254, 94, 94,117,207,225,207,170,254,213, 1, 42, 89, 90,165,205,185, 90, 45, 44,
+ 4, 96,143,253,160,124, 98,147,166,203, 2, 96,143, 30,195,105,106,156, 62, 62,126, 0, 0, 0, 0, 1, 0, 47,254, 86, 4,162,
+ 5,213, 0, 21, 0, 0, 19, 33, 21, 33, 17, 29, 1, 20, 23, 22, 59, 1, 21, 35, 34, 39, 38, 61, 2, 17, 33, 47, 4,115,254, 45,
+ 44, 45, 90,185,223,165, 90, 89,254, 43, 5,213,170,251, 85,128, 20,126, 62, 62,156,106,105,195, 20,128, 4,171,255,255, 0, 9,
+255,227, 4,200, 6, 25, 16, 39, 2,151, 1,154, 1,168, 16, 7, 0, 56,255,118, 0, 0, 0, 0,255,255, 0, 39,255,227, 4,170,
+ 4,113, 16, 39, 2,151, 1,124, 0, 0, 16, 7, 0, 88,255,100, 0, 0, 0, 0, 0, 1, 0, 74, 0, 0, 4,135, 5,180, 0, 30,
+ 0, 0, 1, 21, 35, 22, 18, 21, 16, 0, 35, 34, 0, 17, 52, 18, 55, 35, 53, 33, 21, 6, 2, 21, 20, 18, 32, 18, 53, 52, 2, 39,
+ 53, 4,135,245,123,110,254,224,240,242,254,223,111,123,248, 1,207,120,134,180, 1, 52,179,134,120, 5,180,172,134,254,224,188,
+254,201,254,145, 1,110, 1, 56,188, 1, 33,133,172,172, 76,254,183,222,230,254,247, 1, 9,230,222, 1, 73, 76,172, 0, 0, 0,
+ 0, 1, 0,154, 0, 0, 4, 42, 5,213, 0, 24, 0, 0, 33, 34, 39, 38, 53, 17, 51, 17, 20, 23, 22, 51, 50, 18, 53, 52, 2, 39,
+ 51, 22, 18, 21, 16, 7, 6, 1,250,170, 92, 90,204, 44, 44, 90,154,180,134,120,218,122,110,144,147,106,102,198, 4, 63,251,208,
+126, 62, 62, 1, 9,230,222, 1, 73, 76,134,254,224,188,254,201,184,188, 0, 0, 0, 1, 0, 17, 0, 0, 4,192, 5,215, 0, 22,
+ 0, 0, 1, 3, 17, 35, 17, 1, 51, 1, 19, 54, 55, 54, 51, 50, 31, 1, 7, 39, 38, 35, 34, 7, 6, 3,107,246,183,254, 83,193,
+ 1, 72,199, 99,109, 46, 45, 80, 75, 25, 71, 10, 34, 40, 28, 31, 51, 4,116,254, 42,253, 98, 2,158, 3, 55,253,109, 1,145,200,
+ 42, 18, 57, 19,134, 9, 31, 16, 24, 0, 0, 0, 0, 1, 0, 24,254, 86, 4,201, 4,109, 0, 28, 0, 0, 5, 6, 7, 6, 43, 1,
+ 53, 51, 50, 54, 63, 1, 1, 51, 9, 1, 54, 55, 54, 51, 50, 31, 1, 7, 39, 38, 35, 34, 7, 2,110, 81, 71, 74,124,147,108, 76,
+ 84, 51, 33,254, 59,195, 1, 94, 1, 23, 50, 81, 43, 51, 49, 55, 48, 53, 28, 28, 22, 43, 16,104,203, 58, 61,154, 72,134, 84, 4,
+ 78,252,148, 2,187,126, 41, 22, 20, 17,147, 10, 11, 41, 0, 0, 0, 1, 0,156, 0, 0, 4,145, 5,213, 0, 18, 0, 0, 19, 33,
+ 21, 1, 51, 21, 33, 35, 1, 33, 21, 33, 53, 1, 35, 53, 33, 1, 33,178, 3,201,254,117,232,254,247, 80,254,240, 3, 34,252, 11,
+ 1, 19,180, 1, 34, 1,118,253, 31, 5,213,154,253,176,170,254,105,170,154, 1,167,170, 2, 64, 0, 1, 0,156, 0, 0, 4, 53,
+ 4, 98, 0, 18, 0, 0, 19, 33, 21, 1, 33, 21, 33, 35, 3, 33, 21, 33, 53, 19, 33, 53, 33, 1, 33,222, 3, 45,254,242, 1, 56,
+254,158, 89,242, 2,131,252,187,225,254,245, 1,142, 1, 31,253,149, 4, 98,168,254,174,164,254,210,150,170, 1, 26,164, 1,103,
+ 0, 1, 0, 26,255,228, 4,183, 5,213, 0, 31, 0, 0, 19, 20, 23, 22, 32, 55, 54, 53, 52, 39, 38, 43, 1, 53, 1, 33, 53, 33,
+ 21, 1, 50, 23, 22, 23, 22, 21, 20, 4, 33, 32, 36, 53,228,100, 99, 1,123,100,100, 92, 94,164,174, 1,114,253, 30, 3,202,254,
+136,104,130, 98, 86, 80,254,208,254,232,254,220,254,208, 1,179,143, 75, 75, 75, 75,143,134, 73, 74,166, 1,185,170,168,254, 71,
+ 56, 43,108,104,138,221,242,242,221, 0, 0, 0, 0, 1, 0, 26,255,228, 4,183, 5,213, 0, 31, 0, 0, 1, 51, 20, 4, 33, 32,
+ 36, 53, 52, 55, 54, 55, 54, 51, 1, 53, 33, 21, 33, 1, 21, 35, 34, 7, 6, 21, 20, 23, 22, 32, 55, 54, 3,238,200,254,208,254,
+220,254,232,254,208, 82, 85, 99,129,105,254,136, 3,200,253, 32, 1,114,174,166, 92, 92,100, 99, 1,123,100,100, 1,179,221,242,
+242,221,138,104,108, 43, 56, 1,185,168,170,254, 71,166, 74, 73,134,143, 75, 75, 75, 75, 0, 0, 0, 1, 0,125,254, 76, 4, 84,
+ 4, 96, 0, 32, 0, 0, 9, 1, 53, 33, 21, 33, 1, 21, 35, 34, 7, 6, 21, 20, 23, 22, 51, 50, 54, 55, 21, 6, 7, 6, 35, 32,
+ 36, 53, 52, 55, 54, 55, 54, 2,112,254,101, 3,106,253,101, 1,174,174,165, 93, 92,100, 99,190,109,200, 84,106,100, 99, 94,254,
+232,254,208, 81, 86, 98,128, 1,220, 1,220,168,147,254, 13,166, 74, 75,132,143, 75, 75, 50, 49,195, 37, 19, 18,242,221,138,104,
+109, 42, 56, 0, 0, 1, 0,152, 0, 0, 4, 35, 5,240, 0, 32, 0, 0, 19, 54, 51, 50, 4, 21, 20, 7, 6, 7, 51, 21, 35, 7,
+ 1, 33, 21, 33, 53, 1, 33, 53, 33, 54, 55, 54, 53, 52, 39, 38, 35, 34, 7,164,208,191,219, 1, 11, 45, 34, 66, 80,230, 56,254,
+187, 2,174,252,117, 1,126,254,229, 1,178,105, 30, 22,150, 57, 68,181,222, 5,141, 99,233,189, 96, 96, 74, 85,170, 63,254,168,
+170,170, 1,151,170,130, 84, 60, 62,185, 60, 22,133, 0, 0, 0, 0, 1, 0, 26,255,228, 4,182, 5,213, 0, 32, 0, 0, 37, 32,
+ 55, 54, 53, 52, 39, 38, 35, 33, 17, 33, 21, 33, 17, 33, 50, 23, 22, 23, 22, 21, 20, 4, 33, 32, 3, 38, 53, 51, 20, 23, 22, 2,
+104, 1, 60, 61, 13, 92, 94,164,254, 71, 3,156,253, 47, 1, 34,105,129, 99, 85, 80,254,208,254,232,254, 82,122, 44,202,158, 91,
+142,199, 43, 51,134, 73, 74, 3, 9,170,254, 73, 56, 43,108,101,141,221,242, 1, 0, 91,116,181, 71, 41, 0, 0, 0, 1, 0,125,
+254, 76, 4, 84, 4, 96, 0, 28, 0, 0, 1, 32, 55, 54, 53, 52, 39, 38, 35, 33, 17, 33, 21, 33, 17, 55, 54, 23, 22, 23, 22, 21,
+ 20, 4, 33, 34, 39, 53, 22, 2, 6, 1, 55, 63, 15, 92, 93,165,254,212, 2,240,253,200,168,103,131, 99, 85, 81,254,208,254,232,
+187,212,170,254,246,195, 45, 53,134, 73, 74, 3, 44,184,254, 51, 1, 1, 57, 43,108,104,138,221,242, 74,195, 99, 0, 1, 0,194,
+255,227, 4, 15, 5,158, 0, 32, 0, 0, 1, 52, 39, 38, 43, 1, 17, 35, 53, 51, 17, 51, 17, 51, 21, 35, 21, 22, 23, 22, 21, 20,
+ 7, 6, 33, 34, 39, 53, 22, 51, 50, 55, 54, 3, 77, 74, 89,173, 62,229,229,202,231,231,165,108,117,110,138,254,238,171,152,156,
+159,179, 99, 57, 1,183,114, 79, 95, 1, 15,164, 1, 20,254,236,164,125, 29,110,119,176,185,126,157, 70,172, 86,114, 65, 0, 0,
+ 0, 1, 2, 3, 0, 0, 2,206, 5,213, 0, 3, 0, 0, 1, 51, 17, 35, 2, 4,202,202, 5,213,250, 43, 0, 0,255,255, 1, 57,
+ 0, 0, 3,152, 5,213, 16, 39, 1,128,255, 54, 0, 0, 16, 7, 1,128, 0,202, 0, 0, 0, 0, 0, 1, 0,164, 0, 0, 4, 45,
+ 5,213, 0, 19, 0, 0, 1, 51, 17, 33, 21, 33, 21, 33, 21, 33, 17, 35, 17, 33, 53, 33, 53, 33, 53, 33, 2, 4,202, 1, 94,254,
+162, 1, 94,254,162,202,254,160, 1, 96,254,160, 1, 96, 5,213,254,108,168,240,170,254, 1, 1,255,170,240,168,255,255, 2, 3,
+ 0, 0, 2,206, 5,213, 16, 6, 0, 4,255, 0,255,255, 0, 37, 0, 0, 4,172, 7,109, 16, 38, 0, 36, 0, 0, 16, 7, 11,181,
+ 0, 0, 1,117,255,255, 0,133,255,227, 4, 35, 6,102, 16, 38, 0, 68, 0, 0, 16, 6, 2, 96, 0, 0, 0, 0,255,255, 0,201,
+ 0, 0, 4, 6, 7,109, 16, 38, 0, 44, 0, 0, 16, 7, 11,181, 0, 0, 1,117,255,255, 0,178, 0, 0, 4, 68, 6,102, 16, 38,
+ 0,243, 0, 0, 16, 6, 2, 96, 0, 0, 0, 0,255,255, 0,117,255,227, 4, 92, 7,109, 16, 38, 0, 50, 0, 0, 16, 7, 11,181,
+ 0, 0, 1,117,255,255, 0,137,255,227, 4, 72, 6,102, 16, 38, 0, 82, 0, 0, 16, 6, 2, 96, 0, 0, 0, 0,255,255, 0,147,
+255,227, 4, 61, 7,109, 16, 38, 0, 56, 0, 0, 17, 7, 11,181, 0, 0, 1,117, 0, 20,180, 17, 35, 31, 1, 7, 43, 64, 9, 32,
+ 31, 47, 35, 0, 31, 15, 35, 4, 93, 49, 0, 0,255,255, 0,195,255,227, 4, 27, 6,102, 16, 38, 0, 88, 0, 0, 16, 6, 2, 96,
+ 0, 0, 0, 0,255,255, 0,147,255,227, 4, 61, 7,160, 16, 39, 11,176, 0, 0, 0,249, 16, 38, 0, 56, 0, 0, 16, 7, 2, 98,
+ 0, 0, 1,170,255,255, 0,195,255,227, 4, 27, 7, 50, 16, 38, 2,132, 0, 0, 16, 38, 0, 88, 0, 0, 16, 7, 0,113, 0, 0,
+ 1, 60, 0, 0,255,255, 0,147,255,227, 4, 61, 7,249, 16, 39, 11,176, 0, 0, 0,249, 16, 38, 0, 56, 0, 0, 16, 7, 11,177,
+ 0, 0, 2, 3,255,255, 0,195,255,227, 4, 27, 7,162, 16, 38, 2,132, 0, 0, 16, 38, 0, 88, 0, 0, 16, 7, 2,125, 0, 0,
+ 1, 60, 0, 0,255,255, 0,147,255,227, 4, 61, 7,251, 16, 39, 11,176, 0, 0, 0,249, 16, 38, 0, 56, 0, 0, 16, 7, 11,181,
+ 0, 0, 2, 3,255,255, 0,195,255,227, 4, 27, 7,162, 16, 38, 2,132, 0, 0, 16, 38, 0, 88, 0, 0, 16, 7, 2,136, 0, 0,
+ 1, 60, 0, 0,255,255, 0,147,255,227, 4, 61, 7,249, 16, 39, 11,176, 0, 0, 0,249, 16, 38, 0, 56, 0, 0, 16, 7, 11,179,
+ 0, 0, 2, 3,255,255, 0,195,255,227, 4, 27, 7,162, 16, 39, 2,124, 0, 0, 1, 60, 16, 6, 0,190, 0, 0,255,255, 0,122,
+255,227, 4, 87, 4,123, 18, 6, 1,247, 0, 0,255,255, 0, 37, 0, 0, 4,172, 7,160, 16, 39, 11,176, 0, 0, 0,249, 16, 39,
+ 2, 98, 0, 0, 1,170, 16, 6, 0, 36, 0, 0,255,255, 0,133,255,227, 4, 35, 7, 50, 16, 39, 0,113, 0, 0, 1, 60, 16, 6,
+ 0,166, 0, 0,255,255, 0, 37, 0, 0, 4,172, 7,160, 16, 39, 2, 98, 0, 0, 1,170, 16, 38, 11,185, 0,132, 16, 6, 0, 36,
+ 0, 0, 0, 0,255,255, 0,133,255,227, 4, 35, 7, 50, 16, 39, 0,113, 0, 0, 1, 60, 18, 6, 1,210, 0, 0,255,255, 0, 0,
+ 0, 0, 4,156, 7, 48, 16, 39, 11,189, 0,170, 0, 0, 16, 6, 0,136, 0, 0,255,255, 0, 41,255,227, 4,176, 5,246, 16, 38,
+ 2,128, 0, 0, 16, 6, 0,168, 0, 0, 0, 0,255,255, 0,102,255,227, 4, 80, 7,109, 16, 39, 11,181, 0, 0, 1,117, 16, 6,
+ 0, 42, 0, 0,255,255, 0,123,254, 72, 4, 18, 6,102, 16, 38, 2, 96, 0, 0, 16, 6, 0, 74, 0, 0, 0, 0,255,255, 0,137,
+ 0, 0, 4,201, 7,109, 16, 39, 11,181, 0, 0, 1,117, 16, 6, 0, 46, 0, 0,255,255, 0,236, 0, 0, 4,178, 7,109, 16, 39,
+ 11,181, 0, 0, 1,117, 16, 6, 0, 78, 0, 0,255,255, 0,117,254,101, 4, 92, 5,240, 16, 38, 2,109, 28,240, 16, 6, 0, 50,
+ 0, 0, 0, 0,255,255, 0,137,254,101, 4, 72, 4,123, 16, 38, 2,109, 28,240, 16, 6, 0, 82, 0, 0, 0, 0,255,255, 0,117,
+254,101, 4, 92, 7, 48, 16, 38, 11,189, 0, 0, 16, 6, 1,159, 0, 0, 0, 0,255,255, 0,137,254,101, 4, 72, 5,246, 16, 38,
+ 2,128, 0, 0, 16, 6, 1,160, 0, 0, 0, 0,255,255, 0, 26,255,228, 4,183, 7,109, 16, 39, 11,181, 0, 0, 1,117, 16, 6,
+ 1,121, 0, 0,255,255, 0,125,254, 76, 4, 84, 6,102, 16, 38, 2, 96, 0, 0, 16, 6, 2, 48, 0, 0, 0, 0,255,255, 0,186,
+254, 86, 3,203, 6, 97, 16, 38, 2, 96, 35,251, 16, 6, 1,226, 0, 0, 0, 0,255,255, 0,102,255,227, 4, 80, 7,107, 16, 39,
+ 11,177, 0, 90, 1,117, 16, 6, 0, 42, 0, 0,255,255, 0,123,254, 72, 4, 18, 6,102, 16, 38, 0,118, 0, 0, 16, 6, 0, 74,
+ 0, 0, 0, 0, 0, 1, 0, 61,255,227, 4,148, 5,213, 0, 29, 0, 0, 37, 50, 55, 54, 25, 1, 51, 17, 16, 7, 6, 35, 34, 39,
+ 38, 17, 53, 33, 17, 35, 17, 51, 17, 33, 17, 51, 17, 16, 23, 22, 3,109, 54, 25, 33,182,104, 57,133,128, 72,134,254,213,182,182,
+ 1, 43,183, 82, 23,135, 79,102, 1, 14, 1, 39,254,192,254,139,140, 77, 83,153, 1, 98,150,253, 57, 5,213,253,156, 2,100,252,
+117,254,239,139, 39, 0, 0, 0,255,255, 0,139, 0, 0, 4, 70, 7,107, 16, 39, 11,179, 0, 0, 1,117, 16, 6, 0, 49, 0, 0,
+255,255, 0,195, 0, 0, 4, 27, 6,102, 16, 38, 0, 67, 0, 0, 16, 6, 0, 81, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 4,156,
+ 7,107, 16, 39, 11,177, 0,240, 1,117, 16, 6, 0,136, 0, 0,255,255, 0, 41,255,227, 4,176, 6,102, 16, 38, 0,118, 0, 0,
+ 16, 6, 0,168, 0, 0, 0, 0,255,255, 0, 8,255,186, 4,176, 7,107, 16, 39, 11,177, 0, 0, 1,117, 16, 6, 0,154, 0, 0,
+255,255, 0, 47,255,160, 4,150, 6,102, 16, 38, 0,118, 0, 0, 16, 6, 0,186, 0, 0, 0, 0,255,255, 0, 37, 0, 0, 4,172,
+ 7,107, 16, 38, 11,187, 0, 0, 16, 6, 0, 36, 0, 0, 0, 0,255,255, 0,133,255,227, 4, 35, 6,102, 16, 38, 2,139, 0, 0,
+ 16, 6, 0, 68, 0, 0, 0, 0,255,255, 0, 37, 0, 0, 4,172, 7,109, 16, 38, 11,183, 0, 0, 16, 6, 0, 36, 0, 0, 0, 0,
+255,255, 0,133,255,227, 4, 35, 6, 72, 16, 38, 2,141, 0, 0, 16, 6, 0, 68, 0, 0, 0, 0,255,255, 0,187, 0, 0, 4, 78,
+ 7,107, 16, 38, 11,187, 0, 0, 16, 6, 0, 40, 0, 0, 0, 0,255,255, 0,123,255,227, 4, 88, 6,102, 16, 38, 2,139, 14, 0,
+ 16, 6, 0, 72, 0, 0, 0, 0,255,255, 0,197, 0, 0, 4, 78, 7,109, 16, 38, 11,183, 0, 0, 16, 6, 0, 40, 0, 0, 0, 0,
+255,255, 0,123,255,227, 4, 88, 6, 72, 16, 38, 2,141, 14, 0, 16, 6, 0, 72, 0, 0, 0, 0,255,255, 0,187, 0, 0, 4, 6,
+ 7,107, 16, 38, 11,187, 0, 0, 16, 6, 0, 44, 0, 0, 0, 0,255,255, 0,178, 0, 0, 4, 68, 6,102, 16, 38, 2,139, 0, 0,
+ 16, 6, 0,243, 0, 0, 0, 0,255,255, 0,201, 0, 0, 4, 6, 7,109, 16, 38, 11,183, 0, 0, 16, 6, 0, 44, 0, 0, 0, 0,
+255,255, 0,178, 0, 0, 4, 68, 6, 72, 16, 38, 2,141, 0, 0, 16, 6, 0,243, 0, 0, 0, 0,255,255, 0,117,255,227, 4, 92,
+ 7,107, 16, 38, 11,187, 0, 0, 16, 6, 0, 50, 0, 0, 0, 0,255,255, 0,137,255,227, 4, 72, 6,102, 16, 38, 2,139, 0, 0,
+ 16, 6, 0, 82, 0, 0, 0, 0,255,255, 0,117,255,227, 4, 92, 7,109, 16, 38, 11,183, 0, 0, 16, 6, 0, 50, 0, 0, 0, 0,
+255,255, 0,137,255,227, 4, 72, 6, 72, 16, 38, 2,141, 0, 0, 16, 6, 0, 82, 0, 0, 0, 0,255,255, 0,137, 0, 0, 4,209,
+ 7,107, 16, 38, 11,187,206, 0, 16, 6, 0, 53, 0, 0, 0, 0,255,255, 1,104, 0, 0, 4,131, 6,102, 16, 39, 2,139, 0,150,
+ 0, 0, 16, 6, 0, 85, 0, 0,255,255, 0,143, 0, 0, 4,209, 7,109, 16, 38, 11,183,206, 0, 16, 6, 0, 53, 0, 0, 0, 0,
+255,255, 1,106, 0, 0, 4,131, 6, 72, 16, 39, 2,141, 0,150, 0, 0, 16, 6, 0, 85, 0, 0,255,255, 0,147,255,227, 4, 61,
+ 7,107, 16, 38, 11,187, 0, 0, 16, 6, 0, 56, 0, 0, 0, 0,255,255, 0,195,255,227, 4, 27, 6,102, 16, 38, 2,139, 0, 0,
+ 16, 6, 0, 88, 0, 0, 0, 0,255,255, 0,147,255,227, 4, 61, 7,109, 16, 38, 11,183, 0, 0, 16, 6, 0, 56, 0, 0, 0, 0,
+255,255, 0,195,255,227, 4, 27, 6, 72, 16, 38, 2,141, 0, 0, 16, 6, 0, 88, 0, 0, 0, 0,255,255, 0,139,253,226, 4, 74,
+ 5,240, 16, 38, 2,162, 0, 0, 16, 6, 0, 54, 0, 0, 0, 0,255,255, 0,213,253,226, 4, 6, 4,123, 16, 38, 2,162, 0, 0,
+ 16, 6, 0, 86, 0, 0, 0, 0,255,255, 0, 47,253,226, 4,162, 5,213, 16, 38, 2,162, 0, 0, 16, 6, 0, 55, 0, 0, 0, 0,
+255,255, 0,131,253,226, 4, 8, 5,158, 16, 38, 2,162, 89, 0, 16, 6, 0, 87, 0, 0, 0, 0,255,255, 0,137, 0, 0, 4, 72,
+ 7,109, 16, 39, 11,181, 0, 0, 1,117, 16, 6, 0, 43, 0, 0,255,255, 0,195, 0, 0, 4, 27, 7,109, 16, 39, 11,181, 0, 0,
+ 1,117, 16, 6, 0, 75, 0, 0, 0, 1, 0,147,254, 82, 4, 61, 5,242, 0, 19, 0, 0, 1, 17, 35, 17, 52, 38, 35, 34, 6, 21,
+ 17, 35, 17, 51, 21, 62, 1, 51, 50, 18, 4, 61,203,116,124,141,152,202,202, 54,184,126,187,185, 3,231,250,107, 5,159,180,169,
+218,203,252, 87, 5,213,198,111,116,254,251, 0, 0, 3, 0, 18,255,108, 4,159, 6, 20, 0, 6, 0, 40, 0, 49, 0, 0, 37, 22,
+ 55, 50, 55, 54, 34, 39, 20, 23, 54, 55, 54, 21, 16, 35, 34, 39, 6, 7, 35, 55, 38, 47, 1, 6, 7, 6, 39, 38, 39, 38, 17, 16,
+ 18, 51, 50, 22, 23, 17, 51, 0, 16, 22, 50, 54, 53, 52, 38, 34, 3,109, 12, 66,123, 3, 4,128,169, 13,114,104,164,250, 71, 48,
+ 30, 20,119, 68, 32, 38, 16, 28, 56, 77,100,163, 92, 93,187,161, 80,123, 35,184,253,153,108,212,111,111,212,144, 18, 1,155, 62,
+ 62,116, 35,244, 1, 2,218,254,199, 17, 79, 57,194, 13, 89, 37, 90, 53, 72, 1, 2,155,158, 1, 21, 1, 17, 1, 55, 87, 83, 2,
+ 67,252,241,254, 84,218,220,212,213,219, 0, 0, 0, 1, 0,156,254, 86, 4,146, 5,213, 0, 23, 0, 0, 19, 33, 21, 1, 33, 21,
+ 51, 21, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 61, 1, 33, 53, 1, 33,178, 3,201,252,244, 3, 34, 1, 89, 90,165,205,185, 90,
+ 45, 44,252,195, 2,247,253, 31, 5,213,154,251,111, 42,148,195,105,106,156, 62, 62,126, 20,154, 4,145, 0, 0, 0, 1, 0,203,
+254, 86, 4, 16, 4, 98, 0, 23, 0, 0, 19, 33, 21, 1, 33, 21, 35, 21, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 61, 1, 33, 53,
+ 1, 33,227, 3, 45,253,125, 2,131, 8, 89, 90,165,205,185, 90, 45, 44,253,124, 2,131,253,149, 4, 98,168,252,220,150, 20,195,
+105,106,156, 62, 62,126, 20,170, 3, 37, 0, 0,255,255, 0, 37, 0, 0, 4,172, 7, 80, 16, 38, 11,185, 0, 0, 16, 6, 0, 36,
+ 0, 0, 0, 0,255,255, 0,133,255,227, 4, 35, 6, 16, 16, 38, 2,131, 0, 0, 16, 6, 0, 68, 0, 0, 0, 0,255,255, 0,197,
+254,117, 4, 78, 5,213, 16, 38, 2,163, 50, 0, 16, 6, 0, 40, 0, 0, 0, 0,255,255, 0,123,254,117, 4, 88, 4,123, 16, 38,
+ 2,163, 50, 0, 16, 6, 0, 72, 0, 0, 0, 0,255,255, 0,117,255,227, 4, 92, 7,160, 16, 39, 11,176, 0, 0, 0,249, 16, 39,
+ 2, 98, 0, 0, 1,170, 16, 6, 0, 50, 0, 0,255,255, 0,137,255,227, 4, 72, 7, 50, 16, 39, 0,113, 0, 0, 1, 60, 16, 6,
+ 0,184, 0, 0,255,255, 0,117,255,227, 4, 92, 7,160, 16, 38, 0, 50, 0, 0, 16, 39, 11,178, 0, 0, 0,245, 16, 7, 2, 98,
+ 0, 0, 1,170,255,255, 0,137,255,227, 4, 72, 7, 50, 16, 39, 0,113, 0, 4, 1, 60, 16, 6, 0,183, 0, 0,255,255, 0,117,
+255,227, 4, 92, 7, 80, 16, 38, 11,185, 0, 0, 16, 6, 0, 50, 0, 0, 0, 0,255,255, 0,137,255,227, 4, 72, 6, 16, 16, 38,
+ 2,131, 0, 0, 16, 6, 0, 82, 0, 0, 0, 0,255,255, 0,117,255,227, 4, 92, 7,160, 16, 39, 2, 98, 0, 0, 1,170, 16, 38,
+ 11,185, 0,132, 16, 6, 0, 50, 0, 0, 0, 0,255,255, 0,137,255,227, 4, 72, 7, 50, 16, 39, 0,113, 0, 0, 1, 60, 16, 6,
+ 1,218, 0, 0,255,255, 0, 37, 0, 0, 4,172, 7, 48, 16, 38, 11,189, 0, 0, 16, 6, 0, 60, 0, 0, 0, 0,255,255, 0,104,
+254, 86, 4,129, 5,246, 16, 38, 2,128, 0, 0, 16, 6, 0, 92, 0, 0, 0, 0, 0, 2, 0,160,255,108, 4, 10, 6, 31, 0, 6,
+ 0, 29, 0, 0, 37, 22, 55, 50, 55, 54, 34, 3, 6, 7, 35, 55, 38, 39, 38, 53, 17, 33, 53, 33, 17, 20, 23, 54, 55, 54, 21, 16,
+ 35, 34, 2,216, 12, 66,123, 3, 4,128,144, 29, 20,119, 68, 19, 51, 39,254,217, 1,223, 13,114,104,164,250, 70,144, 18, 1,155,
+ 62,254,156, 79, 57,194, 5, 97, 74,184, 3,249,144,251,119,116, 35,244, 1, 2,218,254,199, 0, 0, 2, 0,106,255,108, 4,103,
+ 4,123, 0, 6, 0, 46, 0, 0, 37, 22, 55, 50, 55, 54, 34, 39, 20, 23, 54, 55, 54, 23, 20, 21, 16, 7, 34, 39, 6, 7, 35, 55,
+ 38, 39, 38, 61, 1, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 23, 22, 17, 3, 52, 12, 66,123, 3, 4,128,185,
+ 22,122,103,159, 5,250, 71, 49, 29, 20,119, 68, 19, 51, 39, 53, 90, 73, 57,167,167, 33, 99, 63,133, 57, 56,144, 18, 1,155, 62,
+ 62,114, 46,252, 2, 2,206, 6, 6,254,200, 1, 17, 79, 57,194, 5, 97, 74,184,235,237,115,123,229,253,127, 4, 96, 96, 60, 63,
+105,101,254,220, 0, 2, 0,131,255,108, 4, 8, 5,158, 0, 6, 0, 35, 0, 0, 37, 22, 55, 50, 55, 54, 34, 39, 20, 23, 54, 55,
+ 54, 21, 16, 35, 34, 39, 6, 7, 35, 55, 38, 39, 38, 53, 17, 33, 53, 33, 17, 51, 17, 33, 21, 33, 2,191, 12, 66,123, 3, 4,128,
+169, 13,114,104,164,250, 71, 48, 30, 20,119, 68, 19, 51, 39,254,213, 1, 43,184, 1,162,254, 94,144, 18, 1,155, 62, 62,116, 35,
+244, 1, 2,218,254,199, 17, 79, 57,194, 5, 97, 74,184, 2, 59,143, 1, 62,254,194,143, 0, 0, 0, 1, 0,186,254, 86, 3, 16,
+ 4, 96, 0, 13, 0, 44, 64, 22, 5, 0, 1, 10,140, 8, 1,182, 3,194, 8,195, 14, 11, 8, 2, 9, 2, 4, 6, 0, 14, 16,212,
+236,196,196, 18, 57, 57, 49, 0, 16,228,244,238, 16,238, 17, 57, 57, 48, 5, 17, 33, 53, 33, 17, 20, 6, 43, 1, 53, 51, 50, 54,
+ 2, 88,254,195, 1,245,179,165,254,234, 90, 90, 20, 3,229,143,251,140,195,211,156,125, 0, 0, 0, 3, 0,120,255,227, 4, 89,
+ 6, 20, 0, 8, 0, 19, 0, 49, 0, 0, 18, 16, 22, 50, 54, 53, 52, 38, 34, 0, 16, 38, 35, 34, 6, 21, 20, 22, 51, 50, 3, 62,
+ 1, 51, 50, 18, 17, 16, 2, 35, 34, 38, 39, 21, 35, 53, 14, 1, 35, 34, 2, 17, 16, 18, 51, 50, 22, 23, 17, 51,237, 81,160, 83,
+ 83,160, 2,166, 81, 80, 81, 82, 82, 81, 80,243, 26, 93, 61,122,139,140,122, 60, 92, 27,111, 27, 92, 60,122,140,141,121, 60, 93,
+ 26,111, 3, 5,254, 84,218,220,212,213,219,253,122, 1,172,218,219,213,212,220, 3, 82, 82, 88,254,201,254,239,254,235,254,197,
+ 87, 83,141,141, 83, 87, 1, 59, 1, 21, 1, 17, 1, 55, 87, 83, 2, 67, 0, 0, 0, 3, 0,120,254, 74, 4, 89, 4,123, 0, 8,
+ 0, 19, 0, 49, 0, 0, 0, 16, 38, 34, 6, 21, 20, 22, 50, 0, 16, 22, 51, 50, 54, 53, 52, 38, 35, 34, 19, 14, 1, 35, 34, 2,
+ 17, 16, 18, 51, 50, 22, 23, 53, 51, 21, 62, 1, 51, 50, 18, 17, 16, 2, 35, 34, 38, 39, 17, 35, 3,228, 81,160, 83, 83,160,253,
+ 90, 81, 80, 80, 83, 83, 80, 80,243, 26, 93, 61,121,140,140,122, 60, 92, 27,111, 27, 92, 60,122,140,141,121, 61, 92, 26,111, 1,
+ 89, 1,172,218,220,212,213,219, 2,134,254, 84,218,219,213,212,220,252,174, 82, 88, 1, 55, 1, 17, 1, 21, 1, 59, 87, 83,141,
+141, 83, 87,254,197,254,235,254,239,254,201, 87, 83,253,189, 0, 0, 3, 0, 8,255,186, 4,176, 6, 23, 0, 15, 0, 18, 0, 21,
+ 0, 0, 1, 51, 19, 1, 23, 9, 1, 35, 3, 33, 15, 1, 35, 7, 39, 55, 1, 33, 3, 39, 11, 1, 1,238,245, 96, 1, 9,100,254,
+193, 1, 59,209,110,254, 67,130, 56, 86, 49,103, 52, 1,230, 1, 27, 81, 43, 89,207, 5,213,254,199, 1,123, 74,254, 56,251,251,
+ 1,133,186,203, 70, 70, 74, 1,221, 1, 33,155, 1, 64,253, 25, 0, 2, 0, 8,255,186, 4,176, 6, 23, 0, 8, 0, 41, 0, 0,
+ 9, 1, 39, 38, 35, 34, 2, 17, 20, 1, 14, 1, 35, 32, 47, 1, 7, 39, 19, 38, 17, 16, 0, 33, 50, 23, 22, 23, 55, 23, 7, 21,
+ 38, 39, 1, 22, 23, 22, 51, 50, 54, 55, 1,112, 2, 52, 18, 85, 86,197,196, 2,211, 77,162, 91,254,225,158, 9,178,103,212, 81,
+ 1, 63, 1, 29, 91, 81, 59, 56, 70,100,127, 16, 17,253,139, 16, 21, 98,197, 88,169, 73, 2, 2, 3, 36, 6, 32,254,208,254,205,
+126,253,202, 41, 41,203, 11,255, 70, 1, 47,179, 1, 7, 1,110, 1,153, 20, 15, 26,100, 74,181, 73, 13, 12,252,126, 39, 32,152,
+ 64, 61, 0, 0, 0, 2, 0, 47,255,160, 4,150, 4,188, 0, 7, 0, 40, 0, 0, 9, 1, 38, 35, 34, 6, 21, 20, 1, 14, 1, 35,
+ 32, 47, 1, 7, 39, 19, 38, 53, 16, 0, 33, 50, 23, 22, 23, 55, 23, 7, 21, 38, 39, 1, 22, 23, 22, 51, 50, 54, 55, 1,149, 1,
+220, 62, 71,173,186, 2,160, 74,157, 82,254,252,146, 8,195, 92,216, 68, 1, 37, 1, 4, 81, 77, 40, 40, 95, 93,113, 34, 33,253,
+228, 13, 15, 94,172, 96,152, 65, 1,150, 2, 55, 18,224,208, 83,254, 93, 43, 43,156, 9,232, 76, 1, 2,132,189, 1, 20, 1, 56,
+ 21, 11, 17,114, 77,134,133, 30, 22,253,127, 21, 18,113, 59, 62, 0, 1, 0, 21, 0, 0, 4,188, 5,213, 0, 13, 0, 0, 1, 51,
+ 17, 33, 21, 33, 17, 33, 21, 33, 17, 33, 53, 33, 1, 32,203, 1, 7,254,249, 2,209,252,100,254,245, 1, 11, 5,213,253, 22,170,
+254,105,170, 2, 65,170, 0, 0, 0, 2, 0, 33,255,186, 4,201, 6, 23, 0, 2, 0, 18, 0, 0, 1, 19, 35, 3, 17, 33, 53, 33,
+ 55, 23, 7, 21, 35, 1, 17, 35, 17, 1, 39, 2,205,243,243,203,254, 45, 4, 8, 46,100, 39, 74,254,117,203,254,134,103, 3,208,
+ 1, 91,253,132, 2,124,170, 66, 74, 56,106,253,205,253, 8, 1,214,253,228, 70, 0, 1, 0,213,254, 16, 4, 25, 4,123, 0, 53,
+ 0, 0, 1, 21, 46, 1, 35, 34, 6, 21, 20, 22, 31, 1, 30, 1, 21, 20, 7, 6, 7, 31, 1, 22, 51, 21, 35, 34, 39, 38, 47, 1,
+ 38, 47, 1, 53, 54, 23, 22, 51, 50, 54, 53, 52, 47, 2, 38, 39, 38, 53, 52, 54, 51, 50, 22, 3,205, 79,160, 83,125,123, 92,183,
+ 74,137,141,118,104,176,152,147, 42, 76, 39, 84,114, 71, 89,237, 51,101, 50,123,122, 68, 62,122,134,245, 8, 69,161, 71, 73,218,
+202, 90,166, 4, 57,180, 46, 46, 81, 83, 75, 74, 35, 14, 26,156,125,166, 94, 82, 10,152,126, 36,154, 61, 38, 91,243, 53, 35, 16,
+190, 5, 96, 15, 99, 89,128, 49, 2, 14, 33, 71, 74,127,161,175, 33, 0, 0, 0, 0, 1, 0,203,254, 16, 4, 16, 4, 98, 0, 23,
+ 0, 0, 19, 33, 21, 1, 22, 23, 1, 23, 22, 59, 1, 21, 35, 34, 39, 38, 47, 1, 38, 35, 61, 1, 1, 33,227, 3, 45,253,106, 49,
+ 32, 1, 8,147, 42, 76, 52, 91, 84,114, 71, 89,237, 61, 90, 2,131,253,149, 4, 98,168,252,203, 17, 32,254,248,126, 36,154, 61,
+ 38, 91,243, 63,156, 14, 3, 37, 0, 1, 0, 55, 0, 0, 4,154, 5,213, 0, 26, 0, 0, 1, 34, 7, 6, 29, 1, 35, 53, 52, 54,
+ 51, 33, 50, 4, 21, 20, 4, 35, 17, 35, 17, 51, 50, 54, 16, 38, 35, 1,118, 54, 60, 48,156,192,126, 1, 39,250, 1, 2,254,255,
+251,202,202,140,157,156,141, 5, 47, 47, 38,114, 49, 70,181,163,227,219,221,226,253,168, 2,254,148, 1, 10,147, 0, 1, 0, 57,
+ 0, 0, 4,152, 5,213, 0, 6, 0, 0, 9, 1, 35, 1, 51, 1, 35, 2,105,254,161,209, 1,181,245, 1,181,209, 5, 43,250,213,
+ 5,213,250, 43, 0, 2, 0,154,255,227, 4, 56, 4,123, 0, 11, 0, 41, 0, 0, 1, 51, 50, 54, 53, 52, 38, 35, 34, 6, 29, 1,
+ 7, 17, 51, 21, 62, 1, 51, 50, 22, 21, 20, 6, 43, 1, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 39, 46, 1, 1,254,
+ 62,160,164,122,108,152,176,184,184, 60,178,128,172,204,252,242,248,136,146, 94,192, 92,102,188, 88,138,198, 60, 38, 32, 2, 43,
+113,112,101,112,211,186, 41, 76, 2,127,166,100, 95,193,162,187,194, 29,134,121, 54, 52,184, 39, 39, 82, 82, 50,147, 0, 0, 0,
+ 0, 2, 0,123,255,227, 4, 18, 4,123, 0, 16, 0, 28, 0, 48, 64, 26, 5, 0, 20, 26,140, 14, 20,140, 8,153, 14,190, 1,194,
+ 3, 23, 4, 0, 6, 2, 71, 17, 18, 11, 72, 29, 16,244,236,252,236, 50, 50, 49, 0, 47,236,228,244,236, 16,238, 17, 57, 57, 48,
+ 1, 53, 51, 17, 35, 53, 14, 1, 35, 34, 2, 17, 16, 18, 51, 50, 22, 1, 20, 22, 51, 50, 54, 53, 52, 38, 35, 34, 6, 3, 90,184,
+184, 46,153,100,203,233,234,202,101,154,254, 15,136,133,133,139,139,133,133,136, 3,209,141,251,162,141, 83, 87, 1, 59, 1, 21,
+ 1, 17, 1, 55, 87,254, 11,214,218,220,212,213,219,218, 0, 0, 0, 2, 0,192,255,225, 4, 87, 4,121, 0, 11, 0, 28, 0, 48,
+ 64, 26, 24, 12, 9, 3,140, 15, 9,140, 21,153, 15,190, 27,194, 25, 0, 18, 18, 71, 24, 12, 6, 6, 26, 70, 29, 16,244,236, 50,
+ 50,252,236, 49, 0, 47,236,228,244,236, 16,238, 17, 57, 57, 48, 1, 52, 38, 35, 34, 6, 21, 20, 22, 51, 50, 54, 1, 62, 1, 51,
+ 50, 18, 17, 16, 2, 35, 34, 38, 39, 21, 35, 17, 51, 3,149,136,133,133,139,139,133,133,136,253,227, 46,153,100,203,233,234,202,
+101,154, 44,184,184, 2, 45,214,218,220,212,213,219,218, 2,120, 83, 87,254,197,254,235,254,239,254,201, 87, 83,139, 4, 94, 0,
+ 0, 2, 0,193,255,227, 4, 88, 6, 20, 0, 11, 0, 36, 0, 57, 64, 31, 3,140, 12, 15, 9,140, 24, 21,153, 15,190, 25, 33,140,
+ 30,155, 25, 0, 18, 18, 71, 30, 33, 31, 24, 12, 6, 6, 26, 70, 37, 16,252,236, 50, 50,196, 57, 57,244,236, 49, 0, 47,252,236,
+ 16,228,244,196,236, 16,198,238, 48, 1, 52, 38, 35, 34, 6, 21, 20, 22, 51, 50, 54, 1, 62, 1, 51, 50, 18, 17, 16, 2, 35, 34,
+ 38, 39, 21, 35, 17, 52, 54, 59, 1, 21, 35, 34, 6, 21, 3,150,136,133,134,138,138,134,133,136,253,227, 44,155,102,202,232,233,
+203,100,153, 46,184,179,165,204,184, 90, 90, 2, 47,214,218,219,213,212,220,218, 2,120, 82, 88,254,201,254,239,254,235,254,197,
+ 87, 83,141, 4,126,195,211,156,125,125, 0, 0, 0, 1, 0,184,255,227, 4, 26, 4,123, 0, 25, 0, 48, 64, 6, 19, 18, 6, 0,
+ 12, 26, 16,220, 60,212,236, 49, 0, 64, 19, 0,139, 25,192, 22, 12,139, 13,192, 16,140, 9, 22,140, 3,190, 9,153, 26, 16,228,
+244,236, 16,254,244,238, 16,245,238, 48, 19, 62, 1, 51, 32, 0, 17, 16, 0, 33, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38,
+ 35, 34, 6, 7,184, 74,156, 82, 1, 4, 1, 38,254,218,254,252, 80,154, 78, 72,148, 92,174,186,188,172, 96,152, 64, 4, 37, 43,
+ 43,254,200,254,236,254,236,254,200, 42, 44,193, 65, 58,224,208,207,225, 59, 62, 0, 2, 0,195,255,115, 4, 58, 4,123, 0, 33,
+ 0, 41, 0, 0, 5, 52, 55, 38, 39, 38, 17, 16, 0, 33, 50, 22, 23, 21, 46, 1, 35, 34, 6, 21, 20, 23, 22, 23, 54, 51, 32, 21,
+ 20, 33, 34, 39, 6, 21, 19, 22, 51, 50, 53, 52, 35, 34, 1,180, 13, 57, 48,149, 1, 37, 1, 4, 81,154, 78, 73,147, 93,173,186,
+ 99, 7, 6, 85,195, 1, 45,254,178, 82, 71, 6, 43, 60, 74,146,132,101,141,104, 81, 35, 51,161, 1, 12, 1, 20, 1, 56, 42, 44,
+193, 65, 58,224,208,220, 99, 7, 7,176,246,189, 17, 57, 68, 1, 31, 19, 57, 75, 0, 2, 0,123,254, 86, 4, 56, 6, 20, 0, 8,
+ 0, 36, 0, 0, 0, 16, 22, 50, 54, 53, 52, 38, 34, 5, 17, 51, 17, 20, 23, 22, 59, 1, 21, 35, 34, 39, 38, 61, 1, 6, 7, 6,
+ 35, 34, 2, 17, 16, 18, 51, 50, 22, 1, 60,109,213,112,112,213, 1, 69,181, 35, 36, 72, 6, 56,132, 72, 71, 37, 61, 61, 80,180,
+207,208,179, 81,123, 3, 5,254, 84,218,220,212,213,219, 14, 2, 67,249,216,126, 62, 62,156,106,105,195,161, 83, 44, 43, 1, 59,
+ 1, 21, 1, 17, 1, 55, 87, 0, 0, 2, 0,123,255,227, 4, 55, 6, 20, 0, 10, 0, 38, 0, 0, 0, 16, 22, 51, 50, 54, 53, 52,
+ 38, 35, 34, 37, 53, 52, 55, 54, 59, 1, 21, 35, 34, 7, 6, 21, 17, 35, 53, 14, 1, 35, 34, 2, 17, 16, 18, 51, 50, 22, 23, 1,
+ 59,109,106,107,111,111,107,106, 1, 68, 71, 72,132, 56, 5, 72, 36, 35,183, 36,123, 80,180,206,207,179, 81,123, 35, 3, 5,254,
+ 84,218,220,212,213,219, 11,148,195,105,106,156, 62, 62,126,251,130,141, 83, 87, 1, 59, 1, 21, 1, 17, 1, 55, 87, 83, 0, 0,
+ 0, 2, 0,122,255,227, 4, 87, 4,123, 0, 21, 0, 28, 0, 0, 19, 52, 18, 51, 50, 0, 17, 16, 0, 33, 34, 38, 39, 53, 30, 1,
+ 51, 50, 54, 61, 1, 33, 55, 33, 46, 1, 35, 34, 6,122,247,214,240, 1, 32,254,218,254,251, 91,195,105,109,192, 88,174,191,252,
+227,184, 2, 94, 16,172,133,136,149, 2, 94,251, 1, 34,254,192,254,244,254,237,254,199, 43, 43,183, 57, 56,200,183, 6,143,156,
+176,170, 0, 0, 0, 2, 0,122,255,227, 4, 87, 4,123, 0, 21, 0, 28, 0, 63, 64, 12, 3, 2, 28, 18, 16, 73, 9, 22, 6, 0,
+ 72, 29, 16,244,236,196,244,236, 57, 57, 49, 0, 64, 22, 0, 22, 3, 1, 10,139, 9,141, 6,140, 13,190, 29, 22,182, 1,193, 25,
+140, 19,153, 29, 16,244,236,244,238, 16,244,244,244,238, 18, 57, 17, 57, 48, 19, 53, 33, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1,
+ 51, 32, 0, 17, 16, 0, 35, 34, 2, 55, 20, 22, 51, 50, 54, 55,122, 3, 29,191,174, 88,192,109,105,195, 91, 1, 5, 1, 38,254,
+224,240,214,247,184,149,136,133,172, 16, 2, 0, 90, 6,183,200, 56, 57,183, 43, 43,254,199,254,237,254,244,254,192, 1, 34,198,
+162,170,176,156, 0, 2, 0, 30,255,227, 4,179, 4,123, 0, 9, 0, 41, 0, 0, 37, 54, 53, 52, 39, 1, 22, 23, 22, 50, 3, 50,
+ 23, 55, 51, 21, 20, 22, 59, 1, 21, 35, 34, 38, 53, 7, 22, 21, 16, 2, 32, 39, 38, 39, 1, 38, 39, 38, 32, 7, 53, 54, 2, 66,
+ 76, 7,254, 43, 23, 25, 62,231,151,252,119,154,140, 57, 80, 33, 49,132,129,106, 23,226,254,148, 99, 71, 20, 2, 70, 15, 20, 58,
+254,194,147,154,214,138,207, 62, 56,254,156, 69, 35, 90, 3,252,232,117,148,153, 97,156,186,200, 81, 96,118,254,237,254,189,145,
+103,156, 1,187, 40, 34, 99,104,174, 86, 0, 0, 0, 1, 0,169,255,234, 4, 40, 4,123, 0, 48, 0, 57, 64, 31, 11,140, 12, 16,
+140, 7,190, 50, 27,182, 23, 50, 38,140, 37, 33,140, 42,153, 50, 24, 11, 38, 19, 18, 4, 29, 18, 46, 70, 49, 16,252,236,212,236,
+212,196,196, 49, 0, 16,244,236,212,236, 16,212,236, 16,244,236,212,236, 48, 1, 38, 39, 38, 53, 52, 54, 51, 50, 23, 22, 23, 21,
+ 38, 39, 38, 35, 34, 6, 21, 20, 23, 22, 59, 1, 21, 35, 34, 6, 21, 20, 23, 22, 51, 50, 55, 54, 55, 21, 6, 7, 6, 35, 34, 39,
+ 38, 53, 52, 54, 1,193,119, 65, 64,244,209, 81, 91, 92,105,104, 87, 86, 76,138,148, 72, 72,135,166,159,150,168, 90, 91,173, 99,
+ 91, 91, 77, 97, 90, 91, 86,254,139,138,148, 2, 95, 25, 65, 64, 94,134,158, 12, 12, 24,167, 27, 13, 12, 86, 74, 61, 43, 44,144,
+110, 81, 98, 53, 52, 18, 17, 34,173, 28, 14, 14, 91, 92,166,109,148, 0, 0, 0, 0, 1, 0,169,255,234, 4, 40, 4,123, 0, 40,
+ 0, 60, 64, 33, 32,139, 31,192, 28,140, 35,190, 41, 0, 20,182, 21, 41, 9,139, 10,192, 13,140, 6,153, 41, 25, 18, 38, 16, 18,
+ 3, 21, 32, 10, 41, 16,220,196,196,212,236,212,236, 49, 0, 16,244,252,252,236, 16,212,236, 57, 16,244,252,253,238, 48, 1, 30,
+ 1, 21, 20, 4, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 43, 1, 53, 51, 50, 54, 53, 52, 38, 35, 34, 6, 7, 53, 62,
+ 1, 51, 50, 22, 21, 20, 6, 3, 15,132,149,254,235,255, 85,182, 96, 76,182,100,173,181,169,150,158,165,136,144,149,138, 75,173,
+104,105,183, 80,210,244,130, 2, 95, 23,148,109,166,183, 28, 28,173, 34, 35,105, 98, 81,110,144, 87, 61, 74, 86, 25, 27,167, 24,
+ 24,158,134, 94,129, 0, 0, 0, 0, 1, 0, 56,255,234, 4,153, 4,123, 0, 66, 0, 0, 1, 22, 23, 22, 21, 20, 7, 6, 35, 34,
+ 38, 39, 53, 22, 23, 22, 51, 50, 55, 54, 53, 52, 39, 38, 43, 1, 53, 51, 50, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 7, 53, 54,
+ 55, 54, 51, 50, 23, 22, 23, 55, 51, 21, 20, 23, 22, 59, 1, 21, 35, 34, 39, 38, 53, 7, 53, 7, 6, 2, 5, 99, 56, 56,104,104,
+191, 64,136, 72, 57, 68, 68, 75,130, 67, 69, 64, 63,113,118,124,102, 54, 54, 56, 56,104, 56, 65, 65, 78, 79, 68, 69, 60,158, 91,
+ 75, 14,169,138, 29, 28, 79, 32, 48,131, 65, 61,211, 5, 49, 2, 95, 23, 74, 74,109,166, 92, 91, 28, 28,173, 34, 17, 18, 52, 53,
+ 98, 81, 55, 55,144, 44, 43, 61, 74, 43, 43, 12, 13, 27,167, 24, 12, 12, 79, 65,102,131,148,153, 49, 48,156, 96, 90,200,162, 1,
+ 6, 65, 0, 0, 0, 2, 0,176,255,213, 4, 34, 4,121, 0, 20, 0, 40, 0, 0, 1, 32, 17, 16, 33, 50, 55, 54, 53, 52, 39, 38,
+ 43, 1, 53, 51, 50, 55, 54, 52, 38, 37, 54, 51, 50, 22, 21, 20, 6, 7, 30, 1, 21, 20, 6, 35, 34, 39, 36, 17, 16, 2,158,254,
+173, 1, 83,118, 60, 59, 59, 33,139,136,136,139, 33, 59,121,254,177, 85,161,160,201,107, 98, 98,107,203,160,159, 85,254,237, 3,
+216,254, 94,254, 65, 59, 59, 76, 76, 54, 30,157, 30, 55,154,115,115, 46,173,148,103,142, 27, 28,142,103,148,174, 61,194, 1, 88,
+ 1,138, 0, 0, 0, 1, 0,186,254, 86, 4,113, 4, 94, 0, 21, 0, 0, 1, 21, 33, 17, 20, 6, 43, 1, 53, 51, 50, 54, 53, 17,
+ 33, 53, 33, 17, 33, 53, 33, 17, 4,113,254,159,179,165,254,234, 90, 90,254,129, 1,127,254,195, 1,245, 2,104,164,254, 40,195,
+211,156,125,125, 1,216,164, 1,103,143,254, 10, 0, 2, 0,123,254, 72, 4, 52, 6, 20, 0, 38, 0, 48, 0, 0, 1, 53, 52, 55,
+ 54, 59, 1, 21, 35, 34, 7, 6, 21, 17, 20, 7, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 61, 2, 14, 1, 35, 34, 2, 17, 52,
+ 18, 51, 19, 17, 35, 34, 6, 16, 22, 51, 50, 54, 2,237, 72, 72,134, 49, 26, 58, 29, 28,104,104,206, 62,134, 67, 79,130, 54,120,
+110, 35,123, 88,174,208,208,174,247,214,109,115,115,110,103,110, 4, 94, 32,195,105,106,156, 62, 62,126,251,202,251,131,130, 28,
+ 27,182, 46, 44,162,176, 8,125, 94, 92, 1, 58, 1, 7,233, 1, 60,253,219, 1,167,216,254, 98,217,218, 0, 0, 0, 2, 0,157,
+254, 72, 4, 52, 4, 94, 0, 9, 0, 36, 0, 0, 1, 17, 33, 34, 6, 16, 22, 51, 50, 54, 19, 20, 2, 35, 34, 38, 39, 53, 30, 1,
+ 51, 50, 54, 61, 2, 14, 1, 35, 34, 2, 17, 52, 55, 54, 51, 33, 3,124,254,248,135,142,143,136,127,135,184,238,231, 76,166, 83,
+ 98,160, 67,149,136, 44,152,109,196,234,117,113,200, 1,233, 2, 57, 1,167,216,254, 98,217,218,254,221,252,254,252, 28, 27,182,
+ 46, 44,162,176, 8,125, 94, 92, 1, 58, 1, 7,225,165,159, 0, 0, 1, 0,122, 0, 0, 4, 88, 4,152, 0, 32, 0, 0, 37, 17,
+ 35, 53, 33, 17, 6, 7, 6, 35, 34, 0, 17, 16, 0, 33, 50, 23, 22, 23, 21, 38, 39, 38, 35, 34, 7, 6, 16, 23, 22, 51, 50, 3,
+178,156, 1, 66, 72, 88, 78,202,252,254,214, 1, 44, 1, 6, 62,104,104,128,120,112, 86, 72,178,100, 98, 98,100,178,174,178, 1,
+ 26,140,253,240, 34, 20, 18, 1, 62, 1, 14, 1, 18, 1, 58, 18, 17, 75,172, 77, 27, 22,114,113,254,102,113,114, 0, 2, 0,102,
+254, 81, 4,107, 4, 94, 0, 18, 0, 27, 0, 0, 1, 0, 17, 20, 14, 2, 34, 46, 2, 53, 16, 9, 1, 51, 9, 1, 51, 0, 50, 54,
+ 53, 16, 3, 2, 17, 20, 2,226, 1, 28, 43, 93,159,220,158, 94, 43, 1, 32,254,114,218, 1, 46, 1, 36,216,253,135,227, 97,203,
+219, 2, 60,254, 84,254,179, 56, 86, 65, 34, 34, 65, 86, 56, 1, 84, 1,172, 2, 27,254,114, 1,142,250,150, 76, 69, 1, 34, 1,
+ 29,254,208,254,241, 69, 0, 0, 0, 2, 0,102, 0, 0, 4,106, 4, 94, 0, 12, 0, 20, 0, 0, 1, 22, 16, 33, 32, 53, 52, 55,
+ 1, 51, 9, 1, 51, 1, 6, 21, 20, 51, 50, 53, 52, 2,214,178,254,227,254,209,184,254,114,218, 1, 40, 1, 42,216,253,246,117,
+123,113, 2, 63,241,254,178,167,177,242, 2, 20,254,115, 1,141,253, 90,158, 59,104,104, 63, 0, 0, 1, 0,188,254, 82, 4, 21,
+ 4, 94, 0, 19, 0, 0, 19, 17, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 35, 17, 14, 1, 35, 34, 38,188,184,108,112,130,138,
+184,184, 50,168,114,172,168, 1,168, 2,182,253, 74,151,142,183,171, 2,121,249,244, 2, 86, 97,100,225, 0, 0, 0, 1, 0,195,
+ 0, 0, 4, 27, 6, 20, 0, 30, 0, 0, 1, 7, 62, 1, 51, 50, 22, 21, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 53, 52,
+ 55, 54, 59, 1, 21, 35, 34, 6, 21, 1,125, 2, 50,168,114,172,168,184,106,114,128,140,184, 90, 90,164,206,186, 90, 88, 3,194,
+ 10, 96, 99,225,228,253, 74, 2,182,151,142,183,171,253,135, 3,234,148,195,105,106,156,124,126, 0, 1, 0,195,254, 86, 4, 27,
+ 6, 20, 0, 40, 0, 0, 1, 7, 62, 1, 51, 50, 22, 21, 17, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 53, 17, 52, 38, 35, 34, 6,
+ 21, 17, 35, 17, 53, 52, 55, 54, 59, 1, 21, 35, 34, 6, 21, 1,125, 2, 49,169,114,171,169, 88, 91,165,204,184, 91, 45, 44,106,
+114,128,140,184, 90, 90,164,206,186, 90, 88, 3,194, 10, 96, 99,225,228,253, 54,195,105,106,156, 62, 62,126, 2,202,151,142,183,
+171,253,135, 3,234,148,195,105,106,156,124,126, 0, 2, 0,142, 0, 0, 4, 50, 6, 20, 0, 3, 0, 21, 0, 0, 1, 51, 21, 35,
+ 5, 33, 17, 33, 21, 33, 17, 33, 21, 33, 53, 33, 17, 33, 53, 33, 17, 33, 2, 12,184,184,254,226, 1,214, 1, 98,254,158, 1,110,
+252,110, 1,108,254,130, 1,126,254,226, 6, 20,233,205,254, 10,164,254,203,143,143, 1, 53,164, 1,105, 0, 0, 0, 1, 0,198,
+ 0, 0, 4, 10, 4, 94, 0, 14, 0, 0, 33, 35, 34, 39, 38, 53, 17, 33, 53, 33, 17, 20, 22, 59, 1, 4, 10,204,166, 90, 88,254,
+224, 1,216, 88, 90,186,106,102,198, 2, 59,141,253, 56,126,124, 0, 1, 0,160, 0, 0, 4, 50, 4, 94, 0, 11, 0, 0, 19, 33,
+ 21, 33, 17, 33, 21, 33, 53, 33, 17, 33,160, 3,146,254,146, 1,110,252,110, 1,108,254,148, 4, 94,141,252,190,143,143, 3, 66,
+ 0, 1, 0, 88, 0, 0, 4,121, 6, 31, 0, 38, 0, 0, 1, 20, 23, 22, 59, 1, 21, 35, 34, 38, 61, 1, 38, 35, 34, 6, 7, 53,
+ 62, 1, 51, 50, 23, 17, 33, 53, 33, 17, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 39, 2,146, 46, 72, 62,216,234,164,182, 46, 47,
+ 79,141, 73, 78,146, 83, 41, 38,254,218, 1,222,114, 92, 70,137, 74, 75,143, 79, 85,105, 1,150,147, 40, 63,156,212,194,198, 10,
+ 59, 63,174, 60, 54, 6, 2,137,144,252,167, 53, 61, 62,174, 59, 55, 45, 0, 0, 0, 2, 0,157, 0, 0, 4, 52, 6, 31, 0, 25,
+ 0, 32, 0, 0, 1, 20, 22, 59, 1, 21, 35, 34, 38, 61, 1, 35, 32, 53, 52, 51, 50, 23, 17, 33, 53, 33, 17, 51, 21, 35, 39, 38,
+ 35, 34, 21, 20, 51, 2,170, 91, 89,214,232,165,181, 62,254,233,246, 53, 42,254,217, 1,223,250,250,184, 23, 71, 78, 92, 1,150,
+124,126,156,212,194,220,189,246, 25, 1,131,144,252,243,160,160,132, 75, 57, 0, 0, 1, 0,160,254, 86, 4, 10, 6, 31, 0, 13,
+ 0, 0, 5, 20, 22, 59, 1, 21, 35, 34, 38, 53, 17, 33, 53, 33, 2,127, 91, 89,215,233,165,181,254,217, 1,223, 20,124,126,156,
+212,194, 5,163,144, 0, 0, 0, 0, 1, 0, 40,254, 76, 4,168, 6, 31, 0, 45, 0, 0, 1, 20, 22, 59, 1, 21, 35, 34, 38, 53,
+ 17, 35, 53, 33, 17, 33, 21, 1, 50, 23, 22, 23, 22, 21, 20, 6, 35, 34, 39, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 39, 38, 43,
+ 1, 53, 1, 33, 1,168, 72, 72,172,187,132,145,236, 1,128, 2,186,254,183, 84,103, 79, 69, 64,243,224, 75, 79, 80, 85, 67,160,
+ 87,152,160, 74, 74,132,140, 1, 88,253,236, 1,150,124,126,156,212,194, 3,249,144,254, 65,168,254, 36, 56, 43,108,104,138,221,
+242, 18, 19, 37,195, 49, 50,150,143,132, 75, 74,166, 1,243, 0, 0, 1, 0,104, 0, 0, 4,106, 4,123, 0, 33, 0, 0, 37, 14,
+ 1, 35, 34, 38, 25, 1, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 20, 22, 50, 54, 53, 17, 51, 17, 35, 53, 14, 1, 35, 34, 38,
+ 2, 50, 34,104, 74,136,110,168, 52, 70, 80, 60,168, 56,148, 56,168,168, 32,100, 62, 76,102,141, 72, 69,209, 1, 33, 2,137,253,
+127,237,115,123,229, 2,129,253,127,240,112,123,229, 2,129,251,160, 96, 60, 63, 70, 0, 0, 0, 0, 1, 0,104,254, 82, 4,106,
+ 4,123, 0, 33, 0, 0, 37, 14, 1, 35, 34, 38, 25, 1, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 20, 22, 50, 54, 53, 17, 51,
+ 17, 35, 17, 14, 1, 35, 34, 38, 2, 50, 34,104, 74,136,110,168, 52, 70, 80, 60,168, 56,148, 56,168,168, 32,100, 62, 76,102,141,
+ 72, 69,209, 1, 33, 2,137,253,127,237,115,123,229, 2,129,253,127,240,112,123,229, 2,129,249,215, 2, 41, 60, 63, 70, 0, 0,
+ 0, 1, 0,103,254, 86, 4,105, 4,123, 0, 43, 0, 0, 1, 62, 1, 51, 50, 22, 25, 1, 20, 6, 43, 1, 53, 51, 50, 54, 53, 17,
+ 52, 38, 35, 34, 6, 21, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 23, 22, 2,158, 34,105, 74,135,
+111,161,150,186,168, 83, 78, 53, 70, 80, 59,168, 57, 74, 73, 57,167,167, 33, 99, 63, 83, 44, 53, 3,238, 72, 69,209,254,223,253,
+ 99,194,212,156,124,126, 2,149,237,115,123,229,253,127, 2,129,240,112,123,229,253,127, 4, 94, 94, 64, 59, 35, 43, 0, 0, 0,
+ 0, 1, 0,178,254, 86, 4, 77, 4,123, 0, 31, 0, 0, 5, 20, 6, 43, 1, 53, 51, 50, 55, 54, 53, 17, 51, 21, 54, 55, 54, 51,
+ 50, 23, 22, 21, 17, 35, 17, 52, 38, 35, 34, 7, 6, 21, 1,234,123,136, 53, 2, 68, 28, 28,186, 49, 68, 67, 87,168, 86, 86,185,
+ 92, 94,111, 65, 64, 20,214,192,156, 48, 49,153, 4,114,172,101, 50, 50,119,120,232,253, 92, 2,158,159,158, 95, 95,164, 0, 0,
+ 0, 1, 0,136,254, 86, 4, 30, 4,123, 0, 32, 0, 0, 5, 17, 52, 39, 38, 35, 34, 7, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51,
+ 50, 23, 22, 21, 17, 20, 23, 22, 59, 1, 21, 35, 34, 39, 38, 2,232, 46, 47, 93,112, 64, 65,181,181, 50,134, 88,168, 86, 86, 29,
+ 29, 63, 4, 52,136, 60, 62, 20, 2,178,159, 79, 79, 95, 95,164,253,135, 4, 94,172,101,100,119,120,232,253, 72,153, 49, 48,156,
+ 96, 96, 0, 0, 0, 1, 0,144, 0, 0, 4, 65, 4,123, 0, 9, 0, 0, 19, 33, 1, 17, 51, 17, 33, 1, 17, 35,144, 1, 16, 1,
+221,196,254,240,254, 35,196, 4,123,252,121, 3,135,251,133, 3,135,252,121, 0, 0, 3, 0,137,255,227, 4, 72, 4,123, 0, 10,
+ 0, 19, 0, 28, 0, 0, 0, 32, 18, 17, 16, 2, 35, 34, 2, 17, 16, 37, 34, 7, 6, 7, 33, 38, 39, 38, 19, 33, 22, 23, 22, 51,
+ 50, 55, 54, 1,127, 1,210,247,246,234,233,246, 1,223,140, 72, 63, 8, 2, 55, 8, 63, 72,138,253,211, 14, 52, 72,140,141, 72,
+ 52, 4,123,254,210,254,226,254,225,254,211, 1, 45, 1, 31, 1, 30,146,109, 95,176,176, 95,109,253,224,132, 79,109,109, 79, 0,
+ 0, 2, 0, 69, 0, 0, 4,140, 4, 96, 0, 18, 0, 29, 0, 0, 1, 21, 33, 17, 33, 21, 33, 17, 33, 21, 33, 34, 39, 38, 17, 16,
+ 55, 54, 51, 23, 35, 34, 7, 6, 21, 20, 23, 22, 59, 1, 4,129,254,139, 1,100,254,156, 1,128,253,168,243,126,126,126,126,243,
+ 32, 23,151, 75, 75, 75, 75,151, 23, 4, 96,170,254,237,155,254,164,172,142,143, 1, 20, 1, 18,142,143,147,104,103,207,208,104,
+105, 0, 0, 0, 0, 2, 0,170,255,226, 4, 38, 4,123, 0, 22, 0, 46, 0, 0, 1, 52, 39, 38, 35, 34, 7, 6, 21, 16, 51, 50,
+ 55, 54, 61, 1, 51, 21, 20, 23, 22, 51, 50, 19, 20, 7, 6, 35, 34, 39, 38, 39, 6, 7, 6, 35, 34, 39, 38, 53, 16, 55, 18, 33,
+ 50, 23, 22, 3,128, 57, 80,145,131, 72, 74,124, 34, 41, 22,117, 23, 41, 32,125,166, 48, 55,137, 95, 67, 27, 16, 16, 27, 67, 95,
+118, 68, 56, 64,106, 1, 21,235,120, 90, 1,254,156,113,161,111,115,231,254,200, 79, 43,185,182,182,185, 43, 79, 1, 8,171,136,
+158,122, 50,101,101, 50,122,154,124,183, 0,255,173, 1, 32,237,176, 0, 0, 0, 0, 3, 0,137,254, 86, 4, 72, 6, 19, 0, 29,
+ 0, 38, 0, 47, 0, 0, 1, 35, 53, 33, 21, 35, 21, 22, 23, 22, 17, 16, 7, 6, 7, 21, 51, 21, 33, 53, 51, 53, 38, 39, 38, 17,
+ 16, 55, 54, 55, 23, 17, 54, 55, 54, 53, 52, 39, 38, 3, 17, 6, 7, 6, 21, 20, 23, 22, 2, 20,240, 2,152,240,161, 95,124,123,
+ 95,162,240,253,104,240,172,100,123,123,100,172,184, 69, 44, 72, 72, 44,253, 79, 49, 72, 72, 49, 5,111,164,164,252, 26,117,151,
+254,226,254,225,150,117, 26,240,165,165,237, 23,123,150, 1, 31, 1, 30,151,123, 23,168,252,194, 26, 66,110,213,214,109, 66,252,
+215, 3, 72, 24, 73,109,214,213,110, 73, 0, 0, 0, 1, 0,152,255,229, 3,177, 4, 94, 0, 17, 0, 0, 55, 30, 1, 51, 50, 54,
+ 53, 17, 51, 17, 35, 53, 14, 1, 35, 34, 38, 39,152, 59,122, 73,172,182,185,185, 46,191,131, 68,118, 54,231, 46, 42,216,204, 2,
+ 43,251,162,219,119,127, 34, 36, 0, 1, 0,152,255,229, 3,177, 6, 31, 0, 17, 0, 0, 55, 30, 1, 51, 50, 54, 53, 17, 51, 17,
+ 35, 53, 14, 1, 35, 34, 38, 39,152, 59,122, 73,172,182,185,185, 46,191,131, 68,118, 54,231, 46, 42,216,204, 3,236,249,225,219,
+119,127, 34, 36, 0, 1, 0,102,254, 86, 4,128, 4, 94, 0, 25, 0, 0, 5, 20, 22, 59, 1, 21, 35, 34, 38, 61, 1, 14, 1, 35,
+ 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 17, 51, 3,127, 89, 90, 78, 98,165,179, 46,191,131, 68,118, 54, 59,122, 73,172,182,185,
+ 20,125,125,156,211,195,239,119,127, 34, 36,188, 46, 42,216,204, 2, 43, 0, 0, 0, 1, 1,106,254, 86, 4,131, 4,123, 0, 17,
+ 0, 0, 1, 46, 1, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 22, 23, 4,131, 59,122, 73,172,182,185,185, 46,191,131,
+ 68,118, 54, 3,121, 46, 42,216,204,252, 41, 6, 8,217,119,127, 34, 36, 0, 0, 0, 1, 1,106,254, 86, 4,131, 4,123, 0, 27,
+ 0, 0, 5, 20, 23, 22, 59, 1, 21, 35, 34, 38, 53, 17, 51, 21, 62, 1, 51, 50, 22, 23, 21, 46, 1, 35, 34, 7, 6, 21, 2, 35,
+ 44, 44, 91,234,254,165,179,185, 46,191,131, 68,118, 54, 59,122, 73,172, 91, 91, 20,125, 63, 62,156,211,195, 4,114,217,119,127,
+ 34, 36,188, 46, 42,108,108,204, 0, 1, 0,160, 0, 0, 4, 50, 4,123, 0, 17, 0, 0, 1, 52, 55, 54, 59, 1, 21, 35, 34, 7,
+ 6, 21, 17, 33, 21, 33, 53, 33, 2, 8, 82, 82,180,210,188,106, 38, 36, 1,112,252,110, 1,104, 2,229,212, 98, 96,156, 48, 50,
+152,253,170,143,143, 0, 0, 0, 0, 1, 0,160, 0, 0, 4, 50, 4,123, 0, 16, 0, 0, 1, 17, 33, 21, 33, 53, 33, 17, 52, 38,
+ 43, 1, 53, 51, 50, 23, 22, 2,200, 1,106,252,110, 1,110, 72,108,186,208,180, 82, 82, 2,229,253,170,143,143, 2, 86,154, 96,
+156, 96, 98, 0, 0, 2, 0,122, 0, 0, 4, 87, 4, 94, 0, 22, 0, 33, 0, 0, 1, 22, 23, 22, 23, 19, 35, 3, 38, 39, 38, 43,
+ 1, 17, 35, 17, 33, 50, 23, 22, 21, 20, 6, 1, 17, 51, 50, 55, 54, 53, 52, 39, 38, 35, 2,212, 55, 53, 52, 53,174,195,162, 63,
+ 59, 59, 97,169,185, 1,132,217,108,107,112,253,245,198,119, 63, 64, 64, 63,119, 2, 13, 17, 54, 54, 94,254,206, 1, 31,113, 36,
+ 37,254, 39, 4, 94, 78, 77,166,105,140, 1,157,254,175, 43, 43, 83, 84, 42, 42, 0, 2, 0,122, 0, 0, 4, 87, 4, 94, 0, 22,
+ 0, 33, 0, 0, 1, 30, 1, 21, 20, 7, 6, 35, 33, 17, 51, 17, 51, 50, 55, 54, 55, 19, 51, 3, 6, 7, 6, 1, 51, 50, 55, 54,
+ 53, 52, 39, 38, 43, 1, 2,212,106,112,107,108,217,254,124,185,169, 97, 59, 59, 63,162,195,174, 53, 52, 53,254, 40,198,119, 63,
+ 64, 64, 63,119,198, 2, 83, 27,140,105,162, 81, 80, 4, 94,254, 41, 37, 36,113, 1, 29,254,208, 94, 54, 54,254, 55, 42, 42, 84,
+ 83, 43, 43, 0, 0, 1, 0,188,254, 86, 4, 20, 4,123, 0, 56, 0, 0, 1, 21, 46, 1, 35, 34, 7, 6, 21, 20, 23, 22, 31, 1,
+ 22, 23, 22, 21, 20, 7, 6, 35, 34, 39, 20, 23, 22, 59, 1, 21, 35, 34, 38, 61, 1, 22, 23, 22, 51, 50, 55, 54, 53, 52, 39, 38,
+ 47, 1, 38, 39, 38, 53, 52, 54, 51, 50, 22, 3,216, 78,167, 91,136, 68, 70, 50, 48,148, 64,196, 82, 82,122,124,216,104,106, 38,
+ 34,110,232,254,180,164,102,100, 98, 98,130, 70, 70, 50, 52,170, 64,172, 76, 76,224,206,102,181, 4, 63,174, 40, 40, 42, 42, 84,
+ 64, 37, 36, 33, 14, 42, 77, 76,137,157, 90, 91, 21,159, 55, 48,156,192,214,251, 53, 26, 27, 45, 44, 81, 75, 40, 40, 37, 15, 36,
+ 74, 75,130,158,172, 30, 0, 0, 0, 1, 0,125,254, 86, 4, 84, 6, 20, 0, 19, 0, 0, 5, 20, 6, 43, 1, 53, 51, 50, 54, 53,
+ 17, 52, 54, 59, 1, 21, 35, 34, 6, 21, 2,211,179,165,254,234, 90, 90,169,179,221,209, 99, 77, 20,195,211,156,125,125, 4,194,
+184,174,153, 81,103, 0, 0, 0, 0, 1, 0,125,254, 86, 4, 84, 6, 20, 0, 31, 0, 0, 1, 21, 33, 17, 20, 6, 43, 1, 53, 51,
+ 50, 54, 53, 17, 33, 53, 33, 17, 33, 53, 33, 53, 52, 54, 59, 1, 21, 35, 34, 6, 21, 17, 4, 52,254,159,179,165,254,234, 90, 90,
+254,129, 1,127,254,195, 1, 61,169,179,221,209, 99, 77, 2,104,164,254, 40,195,211,156,125,125, 1,216,164, 1,105,141, 80,184,
+174,153, 81,103,253,165, 0, 0, 0, 1, 0,125,254, 86, 4, 84, 4, 94, 0, 21, 0, 0, 1, 17, 20, 23, 22, 59, 1, 21, 35, 34,
+ 38, 53, 17, 52, 39, 38, 43, 1, 53, 51, 50, 22, 2,211, 39, 38, 99,209,221,179,169, 45, 45, 90,234,254,165,179, 2,200,252,223,
+103, 40, 41,153,174,184, 3, 12,124, 64, 62,156,211, 0, 0, 0, 0, 2, 0,118,254, 86, 4, 91, 6, 20, 0, 8, 0, 33, 0, 0,
+ 5, 35, 34, 21, 20, 51, 50, 55, 54, 55, 51, 21, 35, 6, 7, 6, 35, 32, 53, 52, 33, 51, 17, 52, 55, 54, 59, 1, 21, 35, 34, 7,
+ 6, 21, 2, 56,179,116,127,110, 33, 18,202,183,191, 18, 53, 82,181,254,209, 1, 14,190, 87, 81,195,174,176,100, 37, 39,154, 51,
+ 65, 48, 23,199,155,111, 64, 96,216,210, 4,174,180, 92, 86,153, 40, 41,103, 0, 0, 1, 0,166,254,194, 4, 43, 4, 96, 0, 19,
+ 0, 0, 1, 17, 33, 53, 33, 17, 52, 38, 43, 1, 53, 51, 50, 22, 21, 17, 33, 21, 33, 17, 2, 72,254, 94, 1,162, 94,117,207,225,
+207,170, 1, 43,254,213,254,194, 1, 62,143, 2, 96,124, 98,147,166,203,253,160,143,254,194, 0, 0, 1, 0,131,254, 87, 4, 8,
+ 5,158, 0, 19, 0, 0, 1, 17, 33, 21, 33, 17, 20, 22, 59, 1, 21, 35, 34, 38, 53, 17, 33, 53, 33, 17, 2,102, 1,162,254, 94,
+ 94,117,207,225,207,170,254,213, 1, 43, 5,158,254,194,143,251,247,124, 98,147,166,203, 4, 9,143, 1, 62, 0, 0, 2, 0, 0,
+255,227, 4,209, 4, 96, 0, 23, 0, 33, 0, 0, 17, 53, 51, 17, 51, 17, 33, 17, 51, 17, 51, 21, 35, 17, 35, 53, 6, 7, 6, 35,
+ 34, 38, 61, 1, 41, 1, 21, 20, 23, 22, 51, 50, 55, 54,142,184, 2, 58,184,153,153,184, 67, 89, 89,117,193,199, 2,241,253,199,
+ 62, 62,124,149, 87, 77, 1,196,164, 1,248,254, 8, 1,248,254, 8,164,254, 60,172,102, 50, 49,240,231, 10, 3,159, 80, 79, 95,
+ 85, 0, 0, 0, 0, 1, 0, 95,255,226, 4,114, 4, 96, 0, 35, 0, 0, 19, 53, 33, 21, 6, 7, 6, 21, 20, 22, 32, 55, 54, 53,
+ 52, 39, 38, 39, 53, 33, 21, 35, 22, 23, 22, 21, 20, 0, 32, 39, 38, 53, 52, 55, 54, 55, 95, 1,186,109, 63, 66,176, 1, 32, 88,
+ 88, 66, 71,100, 1,180,236,114, 56, 54,254,228,254, 62,142,142, 52, 53,119, 3,188,164,220, 69,105,111,135,159,194, 97, 98,158,
+146,100,111, 63,220,164,100,113,110,136,235,254,220,145,146,228,147,107,109,104, 0, 1, 0, 65, 0, 0, 4,119, 4, 96, 0, 32,
+ 0, 0, 1, 33, 22, 23, 22, 21, 20, 0, 43, 1, 34, 39, 38, 53, 17, 35, 53, 33, 17, 20, 23, 22, 63, 1, 50, 55, 54, 53, 52, 39,
+ 38, 39, 38, 2, 85, 1, 66,114, 56, 54,254,228,225, 70,181, 82, 81,155, 1, 83, 38, 40,103, 51,144, 88, 88, 66, 79, 92, 76, 3,
+218,100,113,110,136,235,254,220, 96, 96,214, 2, 59,143,253, 54,153, 49, 50, 2, 1, 97, 98,158,146,100,119, 55, 44, 0, 0, 0,
+ 0, 1, 0, 72, 0, 0, 4,138, 4, 96, 0, 6, 0, 0, 33, 35, 9, 1, 35, 1, 51, 4,138,196,254,162,254,162,194, 1,164,250,
+ 3,172,252, 84, 4, 96, 0, 0, 0, 1, 0, 15, 0, 0, 4,194, 4, 96, 0, 12, 0, 0, 33, 35, 11, 1, 35, 11, 1, 35, 19, 51,
+ 27, 1, 51, 4,194,148,184,183,173,184,184,147,235,173,193,194,173, 3,106,252,150, 3,106,252,150, 4, 96,252,106, 3,150, 0,
+ 0, 1, 0, 72, 0, 0, 4,138, 6, 10, 0, 15, 0, 0, 1, 62, 1, 59, 1, 21, 35, 34, 6, 15, 1, 1, 35, 9, 1, 35, 2, 52,
+ 78,148,124,146,108, 76, 84, 50, 34, 1,198,196,254,162,254,162,194, 4,200,200,122,154, 72,134, 84,251,178, 3,108,252,148, 0,
+ 0, 1, 0,102, 0, 0, 4,107, 4,125, 0, 8, 0, 0, 19, 51, 9, 1, 51, 1, 17, 35, 17,102,217, 1, 37, 1, 46,217,254, 93,
+203, 4,125,254, 56, 1,200,253,144,253,243, 2, 13, 0, 0, 0, 0, 1, 0,194,254, 86, 4, 15, 4, 96, 0, 20, 0, 0, 19, 33,
+ 21, 1, 33, 23, 20, 23, 22, 59, 1, 21, 35, 34, 38, 61, 1, 33, 53, 1, 33,213, 2,167,253,249, 2, 25, 1, 21, 21, 59, 27, 52,
+136,122,253,233, 2, 7,254, 12, 4, 96,168,252,219,167,153, 49, 48,156,192,214, 20,168, 3, 37, 0, 2, 0,167,255,145, 4, 42,
+ 4, 96, 0, 20, 0, 27, 0, 0, 33, 6, 21, 35, 52, 55, 33, 53, 1, 33, 53, 33, 21, 1, 51, 18, 51, 50, 23, 22, 33, 39, 51, 50,
+ 53, 52, 35, 6, 2,170, 3,153, 3,254,150, 2,180,253,101, 3,106,253, 76,175, 60,219,227, 1, 1,254,178, 20, 20,174, 70, 88,
+ 51, 60, 59, 52,168, 3, 37,147,168,252,219, 1, 32,246,189,147, 54, 91, 2, 0, 0, 1, 0,125,254, 76, 4, 84, 4, 96, 0, 32,
+ 0, 0, 1, 50, 23, 22, 23, 22, 21, 20, 4, 33, 34, 39, 38, 39, 53, 30, 1, 51, 50, 55, 54, 53, 52, 39, 38, 43, 1, 53, 1, 33,
+ 53, 33, 21, 2, 97,106,128, 98, 86, 81,254,208,254,232, 94, 99,100,106, 84,200,109,190, 99,100, 92, 93,165,174, 1,174,253,101,
+ 3,106, 1,220, 56, 42,109,104,138,221,242, 18, 19, 37,195, 49, 50, 75, 75,143,132, 75, 74,166, 1,243,147,168, 0, 2, 0,105,
+254, 76, 4,104, 4, 96, 0, 36, 0, 45, 0, 0, 1, 32, 55, 54, 5, 22, 23, 54, 53, 52, 39, 38, 43, 1, 53, 1, 33, 53, 33, 21,
+ 1, 50, 23, 22, 23, 22, 21, 20, 7, 22, 21, 35, 52, 39, 48, 7, 6, 55, 38, 35, 34, 7, 20, 51, 50, 55, 1,227,254,177, 2, 2,
+ 1, 42,246,158, 12, 92, 94,164,174, 1,174,253,101, 3,106,254,101,105,129,100, 84, 81, 39,100,153, 40, 20,151, 9,125,197,131,
+ 1,158,190, 99,254, 76,189,251, 5, 4, 59, 42, 49,133, 74, 74,166, 1,243,147,168,254, 36, 56, 43,108,103,139,113, 85,101,164,
+ 82, 56, 17,121,250, 42, 75, 47, 75, 0, 0, 0, 0, 1, 0,194, 0, 0, 4, 15, 6, 18, 0, 28, 0, 0, 1, 51, 50, 55, 54, 53,
+ 52, 39, 38, 35, 34, 7, 6, 7, 53, 54, 55, 54, 51, 32, 23, 22, 21, 20, 7, 6, 7, 17, 35, 1,190, 63,191, 87, 58, 58,102,176,
+ 80, 79, 78, 78, 76, 81, 81, 85, 1, 19,138,109,108,112,170,203, 3, 30,114, 76, 98,133, 65,114, 22, 21, 43,172, 35, 17, 18,157,
+125,186,170,115,119, 30,253,116, 0, 1, 0,194, 0, 0, 4, 15, 6, 18, 0, 28, 0, 0, 1, 17, 35, 17, 38, 39, 38, 53, 52, 55,
+ 54, 33, 50, 23, 22, 23, 21, 38, 39, 38, 35, 34, 7, 6, 7, 20, 23, 22, 51, 3, 18,202,170,112,108,110,137, 1, 19, 85, 81, 81,
+ 76, 78, 79, 78, 80,179, 99, 57, 1, 58, 86,192, 3, 30,252,226, 2,140, 30,119,115,170,186,125,157, 18, 17, 35,172, 43, 21, 22,
+114, 65,133, 98, 76,114, 0, 0, 0, 1, 0,194, 0, 0, 4, 15, 6, 18, 0, 28, 0, 0, 1, 17, 51, 17, 22, 23, 22, 21, 20, 7,
+ 6, 33, 34, 39, 38, 39, 53, 22, 23, 22, 51, 50, 55, 54, 55, 52, 39, 38, 35, 1,190,203,170,112,108,109,138,254,237, 85, 81, 81,
+ 76, 78, 78, 79, 80,179, 99, 57, 1, 58, 86,192, 2,244, 3, 30,253,116, 30,119,115,170,186,125,157, 18, 17, 35,172, 43, 21, 22,
+114, 65,133, 98, 76,114, 0, 0, 0, 1, 0,194,254, 74, 4, 15, 6, 18, 0, 35, 0, 0, 19, 52, 55, 54, 33, 50, 23, 22, 23, 21,
+ 38, 39, 38, 35, 34, 7, 6, 7, 17, 22, 23, 22, 51, 50, 55, 54, 55, 21, 6, 7, 6, 35, 32, 39, 38, 53,194,110,137, 1, 19, 85,
+ 81, 81, 76, 78, 79, 78, 80,179, 99, 57, 1, 1, 57, 99,179, 80, 78, 79, 78, 76, 81, 81, 85,254,237,137,110, 4, 62,186,125,157,
+ 18, 17, 35,172, 43, 21, 22,114, 65,133,251,224,133, 65,114, 22, 21, 43,172, 35, 17, 18,157,125,186, 0, 0, 0, 0, 3, 0, 95,
+ 0, 45, 4,115, 4, 66, 0, 12, 0, 26, 0, 40, 0, 0, 19, 52, 55, 54, 51, 50, 23, 22, 21, 20, 0, 32, 0, 55, 20, 23, 22, 32,
+ 54, 53, 52, 39, 38, 35, 34, 7, 6, 23, 52, 55, 54, 51, 50, 23, 22, 21, 20, 6, 34, 39, 38, 95,154,154,216,212,154,154,254,209,
+254, 79,254,204,181,101,100, 1, 26,198,100,101,138,141,100,101,227, 34, 33, 47, 46, 34, 33, 66, 94, 33, 34, 2, 53,212,156,157,
+157,156,212,216,254,208, 1, 48,217,141, 99, 99,198,141,138,102,102,102,102,137, 46, 34, 34, 34, 34, 46, 47, 66, 33, 33, 0, 0,
+ 0, 3, 0,209, 0, 0, 4, 0, 4,125, 0, 8, 0, 17, 0, 32, 0, 45, 64, 24, 25, 0,182, 10, 32, 9,182, 18,194, 1,182, 32,
+ 14, 18, 22, 5, 18, 28, 0, 9, 6, 18, 70, 33, 16,252,236, 50,212,236,212,236, 49, 0, 47,236,244,236, 16,212,236, 57, 48, 1,
+ 17, 51, 50, 54, 53, 52, 38, 35, 3, 17, 51, 50, 54, 53, 52, 38, 35, 37, 33, 50, 22, 21, 20, 6, 7, 30, 1, 21, 20, 6, 35, 33,
+ 1,155,221, 93, 95, 90, 94,225,210, 85, 84, 84, 86,254,101, 1,141,178,192, 98, 96,115,127,209,193,254, 99, 2, 18,254,152,105,
+ 63, 92,100, 1,194,254,232, 85, 63, 46, 86,169,148,136,105,125, 15, 25,156,117,154,168, 0, 0, 0, 2, 0,176,255,213, 4, 34,
+ 4,121, 0, 21, 0, 43, 0, 0, 1, 34, 7, 6, 20, 23, 22, 59, 1, 21, 35, 34, 7, 6, 21, 20, 23, 22, 51, 36, 17, 16, 39, 4,
+ 17, 16, 5, 6, 39, 34, 39, 38, 53, 52, 54, 55, 46, 1, 53, 52, 55, 54, 51, 50, 2, 50,115, 57, 64, 60, 32,138,137,137,138, 32,
+ 60, 64, 55,117, 1, 84,120, 1, 20,254,236, 86,147,173,100,100,106, 98, 98,106,100,100,173,150, 3,216, 54, 61,154, 55, 30,157,
+ 30, 54, 78, 74, 64, 54, 1, 1,190, 1,162,115,151,254,120,254,168,194, 62, 2, 87, 86,148,103,142, 28, 27,142,103,148, 87, 86,
+ 0, 1, 0, 54, 0, 0, 4,108, 6, 18, 0, 48, 0, 0, 37, 17, 35, 53, 33, 17, 6, 7, 6, 35, 34, 39, 38, 17, 16, 55, 54, 51,
+ 50, 23, 22, 23, 53, 52, 55, 54, 59, 1, 21, 35, 34, 7, 6, 29, 1, 35, 21, 38, 39, 38, 35, 34, 7, 6, 16, 23, 22, 51, 50, 2,
+206,116, 1, 30, 1,163, 58,152,212,123,125,127,124,219, 51, 72, 24, 13, 62, 60,136,190,129, 78, 30, 28, 2, 29,189, 63, 55,134,
+ 75, 74, 74, 75,134,130,178, 1, 26,140,253,240, 4, 50, 18,159,160, 1, 13, 1, 15,160,157, 18, 6, 5, 1,216, 94, 96,156, 48,
+ 51,151,148,106, 38, 66, 22,114,113,254,102,113,114, 0, 0, 0, 0, 1, 0,144, 0, 0, 4, 65, 4,123, 0, 11, 0, 0, 19, 51,
+ 17, 33, 17, 51, 17, 35, 17, 33, 17, 35,144,202, 2, 29,202,202,253,227,202, 4,123,254, 65, 1,191,251,133, 2, 18,253,238, 0,
+ 0, 3, 0,202,254, 86, 4, 7, 6, 20, 0, 3, 0, 20, 0, 29, 0, 0, 1, 51, 21, 35, 23, 17, 51, 21, 35, 6, 7, 6, 35, 32,
+ 53, 52, 33, 51, 17, 33, 53, 1, 35, 34, 23, 22, 51, 50, 55, 54, 2,154,184,184,184,180,190, 19, 53, 81,181,254,208, 1, 14,194,
+254,194, 1, 51,181,119, 3, 3,123,106, 38, 17, 6, 20,233,203,251,160,155,112, 63, 96,221,205, 3,209,143,251, 6, 51, 65, 48,
+ 23, 0, 0, 0, 0, 1, 0,119,254, 76, 4, 90, 4, 96, 0, 10, 0, 0, 1, 35, 17, 1, 35, 9, 1, 51, 1, 17, 51, 4, 90,186,
+253,220,236, 2, 82,253,150,240, 2, 56,186,254, 76, 3,151,254, 29, 2, 12, 2, 84,253,221, 2, 35, 0, 0, 0, 0, 1, 0,245,
+ 0, 0, 3,220, 4,123, 0, 5, 0, 0, 19, 51, 17, 33, 21, 33,245,202, 2, 29,253, 25, 4,123,252, 47,170, 0, 0, 2, 0, 35,
+254, 86, 4,124, 6, 18, 0, 29, 0, 41, 0, 0, 37, 6, 7, 6, 35, 34, 39, 38, 16, 55, 54, 51, 50, 23, 22, 23, 53, 52, 55, 54,
+ 59, 1, 21, 35, 34, 7, 6, 21, 17, 35, 0, 16, 23, 22, 50, 55, 54, 16, 39, 38, 34, 7, 2,187, 44, 66, 67, 93,174,110,109,109,
+110,174, 93, 67, 66, 44, 61, 61,136,190,127, 79, 29, 28,185,254, 41, 63, 63,219, 63, 63, 63, 63,219, 63,168,100, 48, 49,162,162,
+ 2, 16,162,162, 49, 48,100,198,214, 96, 96,156, 48, 49,153,249,218, 4,164,254,106,116,115,115,116, 1,150,116,115,115, 0, 0,
+ 0, 1, 0,194, 0, 0, 4, 15, 6, 18, 0, 36, 0, 0, 1, 51, 50, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 7, 53, 54, 55, 54,
+ 51, 32, 23, 22, 21, 20, 7, 6, 7, 21, 51, 21, 35, 17, 35, 17, 35, 53, 51, 1,190, 63,191, 87, 58, 58,102,176, 80, 79, 78, 78,
+ 76, 81, 81, 85, 1, 19,138,109,108,112,170,231,231,202,229,228, 3, 30,114, 76, 98,133, 65,114, 22, 21, 43,172, 35, 17, 18,157,
+125,186,170,115,119, 30,212,164,254,236, 1, 20,164, 0, 0, 0, 0, 1, 0,194, 0, 0, 4, 15, 6, 18, 0, 36, 0, 0, 1, 53,
+ 38, 39, 38, 53, 52, 55, 54, 33, 50, 23, 22, 23, 21, 38, 39, 38, 35, 34, 7, 6, 21, 20, 23, 22, 59, 1, 17, 51, 21, 35, 17, 35,
+ 17, 35, 53, 2, 72,170,112,108,110,137, 1, 19, 85, 81, 81, 76, 78, 79, 78, 80,176,102, 58, 58, 87,191, 62,229,229,202,231, 1,
+184,212, 30,119,115,170,186,125,157, 18, 17, 35,172, 43, 21, 22,114, 65,133, 98, 76,114,254,154,164,254,236, 1, 20,164, 0, 0,
+ 0, 3, 0, 29,255,227, 4,154, 6, 20, 0, 7, 0, 32, 0, 35, 0, 0, 18, 16, 22, 50, 54, 16, 38, 34, 5, 17, 51, 17, 33, 21,
+ 1, 33, 21, 33, 43, 1, 53, 6, 7, 6, 35, 34, 2, 16, 18, 51, 50, 23, 22, 23, 17, 1,168,100,175,101,101,175, 1, 20,110, 2,
+ 11,254, 97, 1,159,253,245, 16, 94, 33, 59, 56, 78,128,161,161,128, 78, 56, 58,144, 1,143, 2,250,254,106,231,231, 1,150,231,
+ 43, 2, 94,254, 76,168,252,219,147,168, 97, 51, 49, 1, 68, 2, 16, 1, 68, 49, 48, 77,252,251, 3, 5, 0, 0, 0, 2, 0, 27,
+254, 76, 4,180, 6, 20, 0, 13, 0, 67, 0, 0, 18, 16, 23, 22, 51, 50, 55, 54, 16, 39, 38, 35, 34, 7, 37, 19, 35, 53, 6, 7,
+ 6, 35, 34, 39, 38, 16, 55, 54, 51, 50, 23, 22, 23, 17, 51, 3, 33, 21, 3, 50, 23, 22, 23, 22, 21, 20, 6, 35, 34, 39, 38, 39,
+ 53, 30, 1, 51, 50, 55, 54, 53, 52, 39, 38, 43, 1, 53, 1, 33,141, 50, 50, 88, 87, 51, 50, 50, 51, 87, 88, 50, 1,180, 1,111,
+ 35, 53, 53, 74,122, 76, 77, 77, 76,122, 74, 53, 53, 35,111, 1, 2, 12,246, 63, 77, 59, 51, 49,182,168, 57, 59, 60, 64, 51,120,
+ 65,114, 59, 60, 55, 56, 99,104, 1, 2,254,113, 2,250,254,106,116,115,115,116, 1,150,116,115,115, 95,252, 51,168,100, 48, 49,
+162,162, 2, 16,162,162, 49, 48,100, 2, 94,254, 76,168,254, 36, 56, 42,109,104,138,221,242, 18, 19, 37,195, 49, 50, 75, 75,143,
+132, 75, 74,166, 1,243, 0, 0, 0, 4, 0, 54,255,145, 4,153, 6, 20, 0, 7, 0, 11, 0, 44, 0, 51, 0, 0, 18, 16, 22, 50,
+ 54, 16, 38, 34, 5, 19, 1, 33, 53, 33, 21, 1, 51, 18, 51, 50, 21, 22, 43, 1, 6, 21, 35, 52, 55, 39, 35, 53, 14, 1, 35, 34,
+ 2, 16, 18, 51, 50, 22, 23, 17, 51, 1, 51, 50, 53, 52, 35, 6,169,100,175,101,101,175, 1,127, 3, 1,141,254,115, 2, 9,254,
+ 97,105, 36,132,136, 1,200, 25, 2, 92, 1,216, 92, 35,106, 75,121,153,153,121, 75,106, 35,110, 1, 48, 12,104, 42, 53, 2,250,
+254,106,231,231, 1,150,231, 20,252,254, 3, 2,147,168,252,219, 1, 32,246,189, 51, 60, 83, 27, 1,168,100, 97, 1, 68, 2, 16,
+ 1, 68, 97,100, 2, 94,250,127, 54, 91, 2, 0, 0, 1, 0,153,255,227, 4, 56, 5,158, 0, 62, 0, 0, 1, 21, 46, 1, 35, 34,
+ 6, 21, 20, 22, 31, 1, 22, 23, 22, 21, 20, 6, 35, 34, 39, 38, 39, 21, 35, 34, 38, 53, 17, 35, 53, 51, 17, 51, 17, 51, 21, 35,
+ 17, 20, 22, 59, 1, 53, 30, 1, 51, 50, 54, 53, 52, 39, 38, 47, 1, 46, 1, 53, 52, 54, 51, 50, 22, 4, 20, 47,101, 54, 82, 82,
+ 59, 89, 37,119, 48, 50,148,130, 54, 58, 56, 62,113,128, 97, 81, 81,111,227,227, 45, 69,107, 62,118, 59, 78, 84, 31, 27,106, 38,
+103, 91,135,123, 61,108, 4, 63,174, 40, 40, 84, 84, 64, 73, 33, 14, 44, 75, 76,137,156,182, 17, 17, 33, 38,159,210, 2, 96,143,
+ 1, 62,254,194,143,253,160,137, 78, 77, 53, 53, 89, 81, 75, 40, 36, 41, 15, 36,149,130,158,172, 30, 0, 0, 0, 0, 2, 0,153,
+254, 86, 4, 52, 6, 20, 0, 37, 0, 46, 0, 0, 1, 17, 33, 53, 52, 55, 54, 59, 1, 21, 35, 34, 7, 6, 21, 19, 20, 7, 6, 43,
+ 1, 53, 51, 50, 55, 54, 61, 1, 35, 34, 39, 38, 53, 17, 35, 53, 51, 17, 1, 2, 17, 33, 17, 20, 23, 22, 51, 1,137, 1, 25, 65,
+ 60,147,130,132, 74, 28, 30, 2, 61, 61,136, 53, 37, 78, 29, 29,141,161, 59, 61,101,101, 1,165, 1,254,231, 28, 29, 85, 5,158,
+254,194, 78,182, 90, 86,153, 40, 41,103,251, 41,215, 95, 96,156, 48, 50,152, 20, 80, 77,212, 2, 96,143, 1, 62,250,252, 1, 23,
+ 2, 32,253,160,138, 38, 39, 0, 0, 3, 0,181,255,112, 4, 18, 5,158, 0, 46, 0, 54, 0, 64, 0, 0, 1, 17, 51, 21, 54, 51,
+ 50, 23, 22, 23, 21, 38, 39, 38, 35, 34, 7, 6, 16, 23, 22, 23, 54, 51, 50, 23, 20, 35, 34, 39, 6, 21, 7, 52, 55, 38, 39, 21,
+ 35, 34, 38, 53, 17, 35, 53, 51, 17, 1, 22, 51, 50, 53, 52, 35, 34, 7, 38, 53, 16, 55, 35, 17, 20, 22, 51, 1,117,228, 90,157,
+ 51, 49, 48, 46, 47, 47, 47, 48,108, 59, 59, 59, 4, 4, 50,118,179, 1,200, 49, 43, 3, 92, 7, 33, 28,114,128, 97, 81, 81, 1,
+254, 36, 45, 87, 79, 61,213, 77, 84,221, 45, 69, 5,158,254,194,130,157, 17, 18, 35,172, 43, 22, 21,113,114,254,102,114, 7, 7,
+176,246,189, 17, 57, 68, 3,104, 84, 34, 50,128,159,210, 2, 96,143, 1, 62,250,244, 19, 57, 75,105,157,248, 1, 7,155,253,160,
+137, 78, 0, 0, 0, 1, 0,135,254, 86, 4, 72, 6, 20, 0, 51, 0, 0, 1, 17, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 53, 17,
+ 52, 38, 35, 34, 6, 21, 17, 35, 17, 35, 17, 35, 17, 35, 53, 51, 53, 52, 54, 59, 1, 21, 35, 34, 6, 29, 1, 59, 2, 21, 54, 55,
+ 54, 51, 50, 23, 22, 4, 71, 49, 49,108,153,140, 63, 23, 23, 75, 74, 89,104,111,180,110,106,106,104,113,105,106, 59, 47,180, 2,
+109, 40, 53, 54, 70,116, 60, 59, 2,164,253, 72,214, 96, 96,156, 48, 49,153, 2,178,159,158,190,164,253,135, 3,209,252, 47, 3,
+209,143, 78,187,171,153, 80,104, 99,174,101, 50, 50,119,120, 0, 0, 2, 0,230,255,227, 3,235, 6, 20, 0, 37, 0, 55, 0, 0,
+ 1, 21, 38, 39, 38, 35, 34, 6, 21, 20, 23, 22, 31, 1, 22, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 39, 21, 35, 17, 51, 17, 54,
+ 55, 54, 51, 50, 23, 22, 1, 17, 22, 23, 22, 51, 50, 55, 54, 53, 52, 39, 38, 47, 1, 38, 39, 38, 3,190, 59, 62, 65, 66,103,102,
+ 36, 38,110, 47,149, 60, 62, 93, 91,163, 65, 76, 79, 68,138,138, 8, 75, 84,155, 76, 68, 67,253,235, 75, 69, 74, 73, 97, 53, 52,
+ 37, 34,133, 48,128, 57, 50, 4, 63,174, 41, 19, 20, 84, 84, 63, 38, 36, 33, 14, 44, 75, 76,137,155, 92, 91, 17, 21, 29, 38, 6,
+ 20,253, 58,138, 77, 86, 15, 15,254,183,253,206, 51, 23, 27, 45, 43, 82, 75, 40, 35, 42, 15, 36, 74, 65, 0, 0, 0, 2, 0,219,
+ 0, 0, 3,244, 6, 20, 0, 10, 0, 13, 0, 0, 19, 51, 17, 33, 21, 1, 33, 21, 33, 43, 1, 19, 17, 1,219,138, 2,143,253,249,
+ 2, 7,253,113, 20,118,138, 1,243, 6, 20,254, 76,168,252,219,147, 3,205,252,250, 3, 6, 0, 0, 2, 0,143,255,226, 4, 66,
+ 5, 32, 0, 12, 0, 25, 0, 0, 19, 51, 27, 1, 51, 27, 1, 51, 3, 35, 11, 1, 35, 3, 51, 27, 1, 51, 27, 1, 51, 3, 35, 11,
+ 1, 35,143,116,145,144,137,145,144,116,185,136,152,153,136,185,116,145,144,137,145,144,116,185,136,152,153,136, 2, 85,254, 23,
+ 1,233,254, 23, 1,233,253,141, 2, 2,253,254, 5, 61,254, 23, 1,233,254, 23, 1,233,253,141, 2, 2,253,254, 0, 2, 0,143,
+ 0,173, 4, 66, 5, 31, 0, 7, 0, 15, 0, 0, 19, 33, 17, 35, 17, 33, 17, 35, 17, 33, 17, 35, 17, 33, 17, 35,143, 3,179,143,
+253,107,143, 3,179,143,253,107,143, 2, 85,254, 88, 1, 5,254,251, 4,114,254, 88, 1, 5,254,251, 0, 0, 0, 0, 1, 0,178,
+254, 74, 4, 31, 6, 20, 0, 24, 0, 0, 5, 32, 25, 1, 52, 38, 43, 1, 53, 51, 50, 22, 21, 17, 16, 51, 50, 54, 53, 17, 51, 17,
+ 35, 17, 6, 2,132,254,219, 57, 79, 37, 53,136,122,186,112,129,138,138, 99, 29, 1,215, 2,196,153, 97,156,192,214,253, 66,254,
+195,190,164, 2,121,249,236, 2, 98,201, 0, 0, 0, 1, 0,197,254, 86, 4, 12, 6, 20, 0, 34, 0, 0, 1, 16, 51, 50, 54, 53,
+ 17, 51, 17, 6, 22, 59, 1, 21, 35, 34, 39, 38, 39, 53, 6, 35, 34, 25, 1, 52, 39, 38, 43, 1, 53, 51, 50, 22, 21, 1,190,148,
+ 90,103,111, 2, 48, 62, 30, 42,109, 47, 50, 1, 79,138,235, 23, 23, 63, 29, 42,109, 98, 1,192,254,195,190,164, 2,121,251,142,
+148,102,156, 92,103,231,172,201, 1,215, 2,196,153, 49, 48,156,192,214, 0, 0, 0, 1, 1, 65, 2,156, 3,144, 6, 4, 0, 19,
+ 0, 32, 64, 6, 0, 3, 14, 10, 11, 20, 16,212,220, 60, 47,204, 75, 49, 0, 64, 6, 6, 17, 12, 2, 11, 20, 16,212, 60,196,212,
+204, 48, 1, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 17, 62, 1, 51, 50, 22, 3,144,116, 78, 78, 94,108,117,117, 41,
+113, 74,121,125, 4, 23,254,133, 1,119, 89, 89,107, 92,254,158, 3,103,254,171, 56, 56,134, 0, 0, 1, 1, 65, 2,154, 3,144,
+ 6, 2, 0, 31, 0, 0, 1, 51, 62, 1, 51, 50, 22, 21, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 53, 52, 55, 54, 59, 1,
+ 21, 35, 34, 7, 6, 21, 1,181, 1, 41,113, 74,121,125,116, 78, 78, 94,108,117, 52, 51,114,160,147, 66, 24, 24, 4,172, 57, 56,
+134,130,254,134, 1,119, 89, 88,106, 92,254,158, 2, 49, 83,119, 54, 54, 87, 27, 28, 85, 0, 0, 0, 2, 1,230, 1,173, 2,235,
+ 6, 4, 0, 11, 0, 15, 0, 0, 1, 51, 17, 20, 6, 43, 1, 53, 51, 50, 54, 53, 17, 51, 21, 35, 2,119,116,103,114, 44, 31, 66,
+ 48,116,116, 5, 15,253,130,120,108, 88, 54, 86, 3,114,130, 0, 0, 1, 1,153, 2,156, 3, 56, 5, 31, 0, 17, 0, 0, 1, 46,
+ 1, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 22, 23, 3, 55, 19, 46, 28, 98,106,116,116, 37,117, 84, 12, 29, 18, 4,
+175, 10, 9,113,107,254,182, 2,115, 97, 57, 55, 2, 3, 0, 0, 0, 1, 1,153, 2,140, 3, 56, 5, 16, 0, 17, 0, 0, 1, 30,
+ 1, 51, 50, 54, 53, 17, 51, 17, 35, 53, 14, 1, 35, 34, 38, 39, 1,154, 19, 46, 28, 98,106,116,116, 37,117, 84, 12, 29, 18, 2,
+252, 10, 9,113,107, 1, 74,253,141, 97, 57, 55, 3, 2, 0, 0, 0, 1, 1, 81, 1,173, 3,128, 5, 16, 0, 31, 0, 0, 1, 30,
+ 1, 51, 50, 54, 53, 17, 51, 17, 29, 1, 20, 23, 22, 59, 1, 21, 35, 34, 39, 38, 61, 1, 35, 53, 14, 1, 35, 34, 38, 39, 1, 81,
+ 20, 46, 28, 98,105,117, 24, 24, 66, 31, 45,114, 51, 51, 1, 36,118, 83, 12, 29, 18, 2,252, 10, 9,113,107, 1, 74,253,213, 72,
+ 11, 86, 27, 27, 88, 54, 54,120, 11, 97, 57, 55, 3, 2, 0, 0, 0, 2, 1, 48, 2,156, 3,161, 5, 16, 0, 22, 0, 33, 0, 0,
+ 1, 30, 1, 21, 20, 7, 6, 43, 1, 17, 51, 17, 51, 50, 55, 54, 63, 1, 51, 7, 6, 7, 6, 1, 51, 50, 55, 54, 53, 52, 39, 38,
+ 43, 1, 2,172, 67, 71, 68, 68,137,244,117,106, 61, 37, 37, 40,102,123,110, 33, 33, 33,254,215,124, 75, 40, 40, 40, 40, 75,124,
+ 3,233, 15, 78, 59, 91, 45, 45, 2,115,254,247, 21, 20, 63,161,171, 53, 30, 30,255, 0, 23, 24, 47, 46, 24, 25, 0, 1, 0,143,
+ 2,156, 4, 66, 5, 16, 0, 12, 0, 0, 19, 51, 27, 1, 51, 27, 1, 51, 3, 35, 11, 1, 35,143,116,145,144,137,145,144,116,185,
+136,152,153,136, 5, 15,254, 23, 1,233,254, 23, 1,233,253,141, 2, 2,253,254, 0, 1, 1, 17, 1,173, 3,192, 5, 16, 0, 15,
+ 0, 0, 1, 14, 1, 43, 1, 53, 51, 50, 54, 63, 1, 1, 51, 27, 1, 51, 2,138, 49, 93, 79, 92, 68, 48, 53, 32, 21,254,226,123,
+220,221,123, 2, 98,112, 69, 87, 40, 75, 47, 2,105,254, 22, 1,234, 0, 0, 0,255,255, 1,236, 4,116, 2,235, 6,102, 16, 6,
+ 2,191, 0, 0,255,255, 1,207, 3,199, 3, 45, 6, 20, 16, 6, 6,141, 0, 0,255,255, 1,207, 3,199, 3, 45, 6, 20, 16, 6,
+ 6,142, 0, 0,255,255, 1,240, 4,194, 2,225, 6,193, 16, 6, 2,144, 0, 0, 0, 1, 1,223, 3,239, 2,242, 6, 20, 0, 16,
+ 0, 0, 1, 52, 53, 50, 54, 53, 52, 38, 35, 52, 53, 50, 23, 22, 20, 7, 6, 1,224, 64, 88, 88, 64,114, 80, 80, 80, 80, 3,239,
+ 61, 62, 88, 64, 63, 88, 61, 62, 80, 79,230, 80, 80, 0, 0, 0, 0, 1, 1,223, 3,239, 2,242, 6, 20, 0, 16, 0, 0, 1, 34,
+ 39, 38, 52, 55, 54, 51, 20, 21, 34, 6, 21, 20, 22, 51, 20, 2,242,116, 80, 78, 78, 80,116, 64, 88, 88, 64, 3,239, 80, 80,230,
+ 79, 80, 62, 61, 88, 63, 64, 88, 62, 0, 0, 0, 0, 1, 1, 94, 3,142, 3,115, 6,245, 0, 28, 0, 0, 1, 51, 50, 55, 54, 53,
+ 52, 39, 38, 35, 34, 7, 6, 7, 53, 54, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 7, 17, 35, 1,253, 40,121, 54, 36, 36, 62,113,
+ 51, 49, 50, 49, 48, 51, 51, 54,173, 87, 69, 68, 71,107,127, 5, 77, 64, 42, 55, 75, 36, 64, 12, 12, 24, 96, 20, 9, 10, 88, 70,
+104, 95, 64, 67, 17,254,147, 0, 0, 1, 1, 94, 3,142, 3,115, 6,245, 0, 28, 0, 0, 1, 17, 35, 17, 38, 39, 38, 53, 52, 55,
+ 54, 51, 50, 23, 22, 23, 21, 38, 39, 38, 35, 34, 7, 6, 21, 20, 23, 22, 51, 2,211,127,107, 71, 68, 70, 86,173, 54, 51, 51, 48,
+ 49, 50, 49, 51,113, 62, 36, 36, 54,121, 5, 77,254, 65, 1,109, 17, 67, 64, 95,104, 70, 88, 10, 9, 20, 96, 24, 12, 12, 64, 36,
+ 75, 55, 42, 64, 0, 1, 1, 41, 4,238, 3,168, 6,102, 0, 6, 0, 55, 64, 12, 4, 5, 2,186, 0,185, 7, 4, 2, 11, 6, 7,
+ 16,212,236, 57, 49, 0, 16,244,236, 50, 57, 48, 0, 75,176, 9, 84, 75,176, 14, 84, 91, 88,189, 0, 7,255,192, 0, 1, 0, 7,
+ 0, 7, 0, 64, 56, 17, 55, 56, 89, 1, 51, 19, 35, 39, 7, 35, 2, 31,147,246,139,181,180,139, 6,102,254,136,245,245, 0, 0,
+ 0, 1, 1, 41, 4,238, 3,168, 6,102, 0, 6, 0, 55, 64, 12, 3, 0,186, 4, 1,185, 7, 3, 5, 11, 1, 7, 16,212,236, 57,
+ 49, 0, 16,244, 60,236, 57, 48, 0, 75,176, 9, 84, 75,176, 14, 84, 91, 88,189, 0, 7,255,192, 0, 1, 0, 7, 0, 7, 0, 64,
+ 56, 17, 55, 56, 89, 1, 3, 51, 23, 55, 51, 3, 2, 31,246,139,180,181,139,246, 4,238, 1,120,245,245,254,136, 0, 1, 2, 36,
+ 3,231, 2,173, 6, 18, 0, 3, 0, 19, 64, 3, 0, 3, 4, 16,212,204, 49, 0, 64, 3, 3, 2, 4, 16,212,196, 48, 1, 17, 35,
+ 17, 2,172,136, 6, 18,253,213, 2, 43, 0, 0,255,255, 1, 61, 5, 98, 3,147, 5,246, 16, 6, 2,128, 0, 0, 0, 1, 2, 36,
+254,209, 2,173, 0,252, 0, 3, 0, 19, 64, 3, 0, 3, 4, 16,212,204, 49, 0, 64, 3, 3, 2, 4, 16,212,196, 48, 37, 17, 35,
+ 17, 2,172,136,252,253,213, 2, 43, 0, 0, 0,255,255, 1, 61,254,155, 3,148,255, 47, 16, 6, 2,173, 0, 0, 0, 2, 1,182,
+ 0, 0, 3, 27, 4, 35, 0, 2, 0, 5, 0, 0, 1, 3, 33, 3, 19, 33, 2,104,178, 1,101,179,179,254,155, 2,217, 1, 74,253,
+ 39,254,182, 0, 0, 1, 1,182, 2,216, 3, 27, 4, 35, 0, 2, 0, 0, 1, 3, 33, 2,104,178, 1,101, 2,217, 1, 74, 0, 0,
+255,255, 1,223, 1,254, 2,242, 4, 35, 16, 7, 2, 91, 0, 0,254, 15, 0, 0,255,255, 1,223, 1,254, 2,242, 4, 35, 16, 7,
+ 2, 92, 0, 0,254, 15, 0, 0, 0, 1, 0,193, 1,137, 3, 23, 3,223, 0, 11, 0, 0, 1, 53, 51, 21, 51, 21, 35, 21, 35, 53,
+ 35, 53, 1,162,148,225,225,148,225, 2,254,225,225,148,225,225,148, 0, 0, 0,255,255, 1, 47, 5, 41, 3,162, 6, 72, 16, 6,
+ 2,130, 0, 0,255,255, 2, 1, 5, 68, 2,206, 6, 16, 16, 6, 2,131, 0, 0, 0, 2, 1, 86, 4,225, 3,123, 7, 6, 0, 11,
+ 0, 23, 0, 87,178, 15,200, 9,184, 1, 4, 64, 12, 21,200, 3, 24, 12, 80, 0,123, 18, 80, 6, 24, 16,212,236,244,236, 49, 0,
+ 16,212,236,244,236, 48, 0, 75,176, 9, 84, 75,176, 12, 84, 91, 88,189, 0, 24,255,192, 0, 1, 0, 24, 0, 24, 0, 64, 56, 17,
+ 55, 56, 89, 1, 75,176, 9, 84, 88,189, 0, 24, 0, 64, 0, 1, 0, 24, 0, 24,255,192, 56, 17, 55, 56, 89, 1, 20, 6, 35, 34,
+ 38, 53, 52, 54, 51, 50, 22, 7, 52, 38, 35, 34, 6, 21, 20, 22, 51, 50, 54, 3,123,159,116,115,159,159,115,116,159,123, 88, 64,
+ 64, 87, 87, 64, 64, 88, 5,244,115,160,160,115,115,159,159,115, 63, 88, 87, 64, 65, 87, 88, 0, 0, 1, 1,164,254,117, 3, 25,
+ 0, 0, 0, 19, 0, 34,179, 11, 14, 10, 7,184, 1, 6, 64, 9, 14, 0, 1, 0, 10, 4,124, 17, 20, 16,212,236,196,212,204, 49,
+ 0, 47,212,252,196, 18, 57, 48, 33, 51, 14, 1, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 53, 52, 54, 2, 16,119, 45,
+ 43, 55, 54, 32, 62, 31, 38, 68, 30,122,115, 53, 61, 88, 31, 46, 46, 15, 15,133, 10, 10, 87, 93, 48,105, 0, 0, 0, 1, 1, 31,
+ 5, 29, 3,178, 6, 55, 0, 27, 0,187, 64, 33, 0, 18, 7, 14, 11, 4, 1, 18, 7, 15, 11, 4, 18,204, 25, 7, 4,204, 21, 11,
+ 28, 15, 1, 14, 0, 7, 21, 80, 22, 7, 80, 8, 28, 16,212,236,212,236, 17, 57, 57, 57, 57, 49, 0, 16,212, 60,252,212, 60,236,
+ 17, 18, 57, 17, 18, 57, 17, 18, 57, 17, 18, 57, 48, 0, 75,176, 9, 84, 75,176, 12, 84, 91, 88,189, 0, 28,255,192, 0, 1, 0,
+ 28, 0, 28, 0, 64, 56, 17, 55, 56, 89, 0, 75,176, 15, 84, 88,189, 0, 28, 0, 64, 0, 1, 0, 28, 0, 28,255,192, 56, 17, 55,
+ 56, 89, 64, 63, 9, 0, 12, 10, 12, 11, 12, 12, 11, 15, 11, 16, 15, 17, 15, 18, 15, 19, 15, 20, 15, 21, 15, 22, 15, 23, 9, 27,
+ 25, 0, 25, 1, 27, 10, 27, 11, 27, 12, 27, 13, 27, 14, 27, 15, 27, 16, 27, 17, 27, 18, 27, 19, 31, 20, 31, 21, 31, 22, 26, 23,
+ 25, 27, 31, 1, 93, 1, 39, 46, 1, 35, 34, 6, 7, 35, 62, 1, 51, 50, 22, 31, 1, 30, 1, 51, 50, 54, 55, 51, 14, 1, 35, 34,
+ 38, 2,100, 57, 21, 33, 14, 38, 36, 2,124, 1,102, 91, 39, 64, 37, 57, 21, 33, 13, 39, 36, 1,125, 1,102, 91, 39, 64, 5, 90,
+ 55, 20, 19, 74, 81,134,148, 28, 33, 55, 20, 19, 74, 81,134,148, 28, 0, 0, 0,255,255, 1, 88, 4,238, 4, 23, 6,102, 16, 6,
+ 2,135, 0, 0, 0, 1,254,161, 1,222, 3,115, 4, 8, 0, 15, 0, 0, 1, 37, 51, 21, 20, 23, 22, 59, 1, 21, 33, 34, 39, 38,
+ 53, 5,254,161, 2,107,184, 38, 38,105,250,254,241,175, 87, 82,253,150, 3,100,164,148,153, 49, 48,156, 96, 90,200,162, 0, 0,
+ 0, 2, 1, 37, 1,170, 3,172, 5, 15, 0, 13, 0, 21, 0, 0, 1, 22, 21, 20, 7, 4, 39, 38, 55, 3, 51, 23, 55, 51, 1, 6,
+ 23, 22, 51, 50, 53, 54, 2,181,178,242,254,246, 1, 1,182,250,136,191,184,136,254,188,139, 3, 1,135,128, 1, 3,220,249,180,
+129, 3, 3,135,192,241, 1, 47,224,224,254,138,174,152, 77, 77,140, 0, 0, 0, 0, 1, 1, 86, 2,156, 3,124, 6, 10, 0, 13,
+ 0, 0, 1, 20, 22, 59, 1, 21, 35, 34, 38, 53, 17, 35, 53, 33, 2,132, 56, 56,136,146,104,114,186, 1, 46, 3,127, 69, 71, 87,
+119,108, 2, 58, 81, 0, 0, 0, 0, 1, 1, 91, 2,156, 3,118, 5, 47, 0, 41, 0, 0, 1, 21, 46, 1, 35, 34, 6, 21, 20, 22,
+ 31, 1, 22, 23, 22, 21, 20, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 39, 38, 47, 1, 46, 1, 53, 52, 54, 51, 50, 22,
+ 3, 80, 49,106, 56, 87, 86, 62, 93, 40,125, 50, 52,155,137, 56,123, 68, 64,125, 61, 82, 88, 32, 28,111, 41,107, 96,141,130, 64,
+113, 5, 13, 97, 22, 22, 47, 47, 36, 41, 18, 8, 24, 42, 43, 77, 87,102, 20, 19,107, 30, 30, 50, 45, 42, 23, 20, 23, 8, 21, 83,
+ 73, 88, 97, 17, 0, 1, 1, 18, 2,156, 3,191, 5, 15, 0, 11, 0, 0, 1, 3, 1, 35, 39, 7, 35, 1, 3, 51, 23, 55, 3,177,
+255, 1, 13,137,206,205,137, 1, 18,250,136,188,187, 5, 15,254,207,254,190,246,246, 1, 72, 1, 43,223,223, 0, 0, 1, 1, 94,
+ 2,156, 3,115, 6, 2, 0, 28, 0, 0, 1, 17, 35, 17, 38, 39, 38, 53, 52, 55, 54, 51, 50, 23, 22, 23, 21, 38, 39, 38, 35, 34,
+ 7, 6, 21, 20, 23, 22, 51, 2,211,127,107, 71, 68, 70, 86,173, 54, 51, 51, 48, 49, 50, 49, 51,113, 62, 36, 36, 54,121, 4, 91,
+254, 65, 1,109, 17, 67, 64, 95,104, 70, 88, 10, 9, 20, 96, 24, 12, 12, 64, 36, 75, 55, 42, 64, 0, 1, 0,214, 0, 0, 3, 29,
+ 5, 88, 0, 5, 0, 0, 33, 17, 33, 53, 33, 17, 2,149,254, 65, 2, 71, 4,208,136,250,168, 0, 0, 1, 0,214, 0, 0, 3, 29,
+ 5, 88, 0, 7, 0, 0, 33, 17, 33, 53, 33, 17, 51, 17, 2,149,254, 65, 1,191,136, 3,156,136, 1, 52,250,168, 0, 1, 0,214,
+ 0, 0, 3, 29, 5, 88, 0, 7, 0, 0, 1, 17, 51, 17, 35, 17, 33, 53, 2,149,136,136,254, 65, 2,240, 2,104,250,168, 2,104,
+136, 0, 0, 0, 0, 1, 0,214, 0, 0, 3, 29, 5, 88, 0, 7, 0, 0, 1, 17, 51, 17, 35, 17, 33, 53, 2,149,136,136,254, 65,
+ 1,188, 3,156,250,168, 1, 52,136, 0, 0, 0, 0, 1, 0,214, 0, 0, 3, 29, 5, 88, 0, 5, 0, 0, 37, 17, 51, 17, 33, 53,
+ 2,149,136,253,185,136, 4,208,250,168,136, 0,255,255, 1,141,254, 10, 3, 68,255,193, 16, 6, 2,161, 0, 0,255,255, 1, 23,
+ 4,238, 2,246, 6,102, 16, 6, 0, 67, 0, 0,255,255, 1,219, 4,238, 3,186, 6,102, 16, 6, 0,118, 0, 0,255,255, 1, 41,
+ 4,238, 3,168, 6,102, 16, 6, 2, 95, 0, 0,255,255, 1, 31, 5, 29, 3,178, 6, 55, 16, 6, 2,110, 0, 0, 0, 1, 1, 61,
+ 5, 98, 3,147, 5,246, 0, 3, 0, 17,182, 2,182, 0, 4, 1, 0, 4, 16,212,204, 49, 0, 16,212,236, 48, 1, 33, 21, 33, 1,
+ 61, 2, 86,253,170, 5,246,148,255,255, 0, 0, 5,187, 4,209, 6, 11, 16, 6, 6,161, 0, 0, 0, 1, 1, 47, 5, 41, 3,162,
+ 6, 72, 0, 13, 0, 32,185, 0, 11, 1, 3, 64, 12, 4, 7, 0,185, 14, 7, 80, 8, 1, 80, 0, 14, 16,212,236,220,236, 49, 0,
+ 16,244, 60,212,236, 48, 1, 51, 30, 1, 51, 50, 54, 55, 51, 14, 1, 35, 34, 38, 1, 47,119, 11, 96, 87, 85, 96, 14,119, 11,158,
+145,144,158, 6, 72, 76, 74, 74, 76,143,144,144, 0, 1, 2, 1, 5, 68, 2,206, 6, 16, 0, 3, 0, 20, 64, 9, 2,222, 0,221,
+ 4, 1, 97, 0, 4, 16,212,236, 49, 0, 16,244,236, 48, 1, 51, 21, 35, 2, 1,205,205, 6, 16,204, 0, 0, 0,255,255, 1, 63,
+ 5, 70, 3,145, 6, 16, 16, 6, 0,106, 0, 0, 0, 1, 1,153, 4,242, 3, 56, 6,198, 0, 21, 0, 0, 1, 50, 23, 22, 21, 20,
+ 7, 6, 7, 21, 35, 53, 54, 55, 54, 53, 52, 35, 34, 7, 53, 54, 2, 74,230, 7, 1, 28, 50, 52,148, 67, 49, 22,120, 90, 64, 86,
+ 6,198,170, 5, 5, 64, 36, 67, 33, 88,108, 22, 48, 20, 53, 94, 32,131, 24, 0,255,255, 1, 86, 4,225, 3,123, 7, 6, 16, 6,
+ 2,108, 0, 0, 0, 2, 1, 88, 4,238, 4, 23, 6,102, 0, 3, 0, 7, 0, 37, 64, 17, 6, 2,186, 4, 0,185, 8, 0, 7, 3,
+ 4, 1, 5, 7, 1, 3, 8, 16,212,220,212,204, 17, 57, 17, 18, 57, 49, 0, 16,244, 60,236, 50, 48, 1, 51, 3, 35, 1, 51, 3,
+ 35, 2, 23,170,224,137, 2, 12,179,248,135, 6,102,254,136, 1,120,254,136, 0,255,255, 1, 41, 4,238, 3,168, 6,102, 16, 6,
+ 2, 96, 0, 0, 0, 1, 2, 34, 4,238, 2,170, 6,170, 0, 3, 0, 0, 1, 17, 35, 17, 2,170,136, 6,170,254, 68, 1,188, 0,
+255,255, 1, 86, 4,238, 3,118, 6,170, 16, 39, 2,137, 0,204, 0, 0, 16, 7, 2,137,255, 52, 0, 0, 0, 0, 0, 2, 0,210,
+ 4,238, 3,144, 6,102, 0, 3, 0, 7, 0, 0, 1, 19, 35, 3, 33, 19, 35, 3, 1,132,205,135,248, 2, 0,190,137,223, 6,102,
+254,136, 1,120,254,136, 1,120,255,255, 1, 47, 5, 41, 3,162, 6,220, 16, 39, 2,107, 0, 0, 0,204, 16, 6, 2,106, 0, 0,
+ 0, 1, 1, 47, 5, 41, 3,162, 6, 72, 0, 13, 0, 0, 1, 62, 1, 51, 50, 22, 23, 35, 46, 1, 35, 34, 6, 7, 1, 47, 11,158,
+144,145,158, 11,119, 14, 96, 85, 87, 96, 11, 5, 41,143,144,144,143, 76, 74, 74, 76, 0, 0, 0, 0, 1, 1,213, 3,199, 3, 34,
+ 5, 32, 0, 3, 0, 0, 1, 35, 19, 51, 2,196,239,187,146, 3,199, 1, 89, 0, 0, 1, 1,239, 4,194, 2,226, 6,193, 0, 8,
+ 0, 0, 1, 16, 35, 53, 22, 53, 35, 53, 51, 2,225,241,112,112,241, 5,195,254,255,123, 3,137,254, 0, 0, 0, 0, 1, 1,240,
+ 4,194, 2,225, 6,193, 0, 8, 0, 0, 1, 53, 51, 21, 35, 20, 51, 21, 34, 1,240,241,112,112,241, 5,195,254,254,134,123, 0,
+ 0, 1, 1,219, 4,238, 2,230, 6,102, 0, 3, 0, 0, 1, 51, 3, 35, 2, 32,198,113,154, 6,102,254,136, 0,255,255, 1,121,
+253,184, 3, 88,255, 48, 16, 7, 0, 67, 0, 98,248,202, 0, 0,255,255, 1,121,253,184, 3, 88,255, 48, 16, 7, 0,118,255,158,
+248,202, 0, 0, 0, 1, 1,156,253, 1, 2,212,254,235, 0, 7, 0, 0, 1, 53, 51, 17, 35, 53, 35, 53, 2, 76,136,136,176,254,
+ 58,177,254, 22,177,136, 0, 0, 0, 1, 1,204,253, 1, 3, 4,254,235, 0, 7, 0, 0, 1, 21, 35, 17, 51, 21, 51, 21, 2, 84,
+136,136,176,253,178,177, 1,234,177,136, 0, 0, 0, 1, 1,115, 5,134, 3, 94, 7,112, 0, 5, 0, 0, 1, 33, 53, 33, 17, 35,
+ 2,214,254,158, 1,234,136, 6,232,136,254, 22, 0, 1, 1,163, 2,252, 3, 46, 4,113, 0, 19, 0, 0, 1, 53, 30, 1, 51, 50,
+ 54, 53, 52, 38, 39, 51, 30, 1, 21, 20, 6, 35, 34, 38, 1,163, 61, 88, 31, 46, 46, 15, 15,133, 10, 10, 87, 93, 48,105, 3,104,
+119, 45, 43, 55, 54, 32, 62, 31, 38, 68, 30,122,115, 53, 0, 0, 0, 1, 1,250,254, 10, 2,214,255,193, 0, 12, 0, 0, 1, 21,
+ 34, 38, 52, 54, 51, 21, 34, 6, 21, 20, 22, 2,214, 93,127,127, 93, 51, 71, 71,254,108, 98,128,184,127, 98, 71, 50, 51, 71, 0,
+ 0, 1, 1, 98,253,178, 3, 76,254,235, 0, 7, 0, 0, 1, 51, 21, 33, 53, 51, 53, 51, 2,155,177,254, 22,177,136,254, 58,136,
+136,177, 0, 0, 0, 1, 1, 94,253,178, 3, 72,254,235, 0, 7, 0, 0, 1, 35, 53, 33, 21, 35, 21, 35, 2, 15,177, 1,234,177,
+136,254, 99,136,136,177, 0, 0, 0, 1, 1, 95,253, 1, 3, 73,254,235, 0, 11, 0, 0, 1, 35, 53, 51, 53, 51, 21, 51, 21, 35,
+ 21, 35, 2, 16,177,177,136,177,177,136,253,178,136,177,177,136,177, 0, 0, 0, 0, 1, 1,115,254, 99, 3, 94,254,235, 0, 3,
+ 0, 0, 1, 53, 33, 21, 1,116, 1,234,254, 99,136,136, 0, 0, 0, 1, 1,246,254, 86, 4, 27, 0,128, 0, 13, 0, 0, 37, 21,
+ 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 61, 1, 4, 27, 89, 90,165,205,185, 90, 45, 44,128,148,195,105,106,156, 62, 62,126,148,
+ 0, 1, 0,182,254, 86, 2,219, 0,128, 0, 13, 0, 0, 55, 51, 21, 20, 23, 22, 59, 1, 21, 35, 34, 39, 38, 53,182,185, 44, 45,
+ 90,185,205,165, 90, 89,128,148,126, 62, 62,156,106,105,195, 0, 0, 1, 2, 1,254, 99, 2,206,255, 47, 0, 3, 0, 19, 64, 8,
+ 2,222, 0, 4, 1, 97, 0, 4, 16,212,236, 49, 0, 16,212,236, 48, 5, 51, 21, 35, 2, 1,205,205,209,204, 0, 0, 2, 1, 63,
+254,100, 3,146,255, 46, 0, 3, 0, 7, 0, 28, 64, 13, 6, 2,222, 4, 0, 8, 5, 97, 4, 1, 97, 0, 8, 16,212,252,212,236,
+ 49, 0, 16,212, 60,236, 50, 48, 5, 51, 21, 35, 37, 51, 21, 35, 1, 64,202,202, 1,136,202,202,210,202,202,202, 0, 2, 1,141,
+254, 10, 3, 68,255,193, 0, 11, 0, 23, 0, 29,181, 12, 0, 18, 0, 6, 24, 16,212,204,204, 16,204, 49, 0,181, 15, 9, 21, 9,
+ 3, 24, 16,212,204,204, 16,204, 48, 1, 20, 6, 35, 34, 38, 53, 52, 54, 51, 50, 22, 7, 52, 38, 35, 34, 6, 21, 20, 22, 51, 50,
+ 54, 3, 68,127, 93, 92,127,127, 92, 93,127, 98, 71, 51, 51, 70, 70, 51, 51, 71,254,230, 92,128,128, 92, 92,127,127, 92, 50, 71,
+ 70, 51, 52, 70, 71, 0, 0, 0, 0, 1, 1,152,253,226, 2,229,255, 59, 0, 3, 0, 17, 64, 6, 0, 3, 4, 1, 3, 4, 16,212,
+204, 49, 0, 16,212,204, 48, 5, 51, 3, 35, 1,246,239,187,146,197,254,167, 0, 0, 1, 1,139,254,117, 3, 41, 0, 0, 0, 19,
+ 0, 56,179, 9, 6, 10, 13,186, 1, 6, 0, 6, 1, 5, 64, 9, 0, 9, 16, 19, 0, 16,124, 3, 20, 16,212,236,212,204, 16,196,
+ 49, 0, 47,246,254,197, 18, 57, 48, 1, 64, 13, 73, 1, 89, 1,105, 1,121, 1,137, 1,153, 1, 6, 93, 33, 30, 1, 21, 20, 6,
+ 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 39, 2,188, 56, 53,120,118, 45, 87, 44, 34, 75, 47, 58, 61, 44, 44, 62,105,
+ 48, 89, 91, 12, 12,131, 17, 15, 48, 46, 30, 87, 61, 0, 0, 0,255,255, 1,174,254,117, 3, 35, 0, 0, 16, 6, 2,109, 10, 0,
+ 0, 1, 2, 36,253,115, 2,173,255, 47, 0, 3, 0, 0, 5, 17, 35, 17, 2,172,136,209,254, 68, 1,188, 0, 0, 0, 1, 1, 85,
+253,229, 3,124,255, 47, 0, 7, 0, 0, 5, 17, 35, 53, 33, 21, 35, 17, 3,124,137,254,235,137,209,254,182,194,194, 1, 74, 0,
+ 0, 1, 0,206,254, 57, 4, 3,255, 88, 0, 20, 0, 0, 1, 6, 35, 34, 3, 52, 53, 51, 22, 51, 50, 55, 51, 22, 23, 50, 55, 51,
+ 2, 7, 34, 2,104, 59,116,218, 17,118, 13,103,102, 16,118, 11,105,102, 15,118, 15,220,116,254,139, 82, 1, 26, 2, 3,150,150,
+149, 1,150,254,226, 1, 0, 0, 0, 1, 1, 41,254, 27, 3,168,255,147, 0, 6, 0, 25, 64, 11, 3, 0,186, 4, 1, 7, 3, 5,
+ 11, 1, 7, 16,212,236, 57, 49, 0, 16,212, 60,236, 57, 48, 1, 3, 51, 23, 55, 51, 3, 2, 31,246,139,180,181,139,246,254, 27,
+ 1,120,245,245,254,136, 0, 0, 0, 1, 1, 41,254, 27, 3,168,255,147, 0, 6, 0, 25, 64, 11, 4, 5, 2,186, 0, 7, 4, 2,
+ 11, 6, 7, 16,212,236, 57, 49, 0, 16,212,236, 50, 57, 48, 5, 51, 19, 35, 39, 7, 35, 2, 31,147,246,139,181,180,139,109,254,
+136,245,245, 0, 0, 1, 1, 47,254, 25, 3,162,255, 56, 0, 13, 0, 32,185, 0, 11, 1, 3, 64, 12, 4, 7, 0,185, 14, 7, 80,
+ 8, 1, 80, 0, 14, 16,212,236,220,236, 49, 0, 16,244, 60,212,236, 48, 5, 51, 30, 1, 51, 50, 54, 55, 51, 14, 1, 35, 34, 38,
+ 1, 47,119, 11, 96, 87, 85, 96, 14,119, 11,158,145,144,158,200, 76, 74, 74, 76,143,144,144, 0, 0, 1, 1, 47,254, 27, 3,162,
+255, 58, 0, 13, 0, 0, 1, 35, 46, 1, 35, 34, 6, 7, 35, 62, 1, 51, 50, 22, 3,162,119, 11, 96, 87, 85, 96, 14,119, 11,158,
+145,144,158,254, 27, 76, 74, 74, 76,143,144,144, 0, 1, 1, 31,254, 27, 3,178,255, 53, 0, 27, 0,134, 64, 33, 0, 18, 7, 14,
+ 11, 4, 1, 18, 7, 15, 11, 4, 18,204, 25, 7, 4,204, 21, 11, 28, 15, 1, 14, 0, 7, 21, 80, 22, 7, 80, 8, 28, 16,212,236,
+212,236, 17, 57, 57, 57, 57, 49, 0, 16,212, 60,252,212, 60,236, 17, 18, 57, 17, 18, 57, 17, 18, 57, 17, 18, 57, 48, 64, 63, 9,
+ 0, 12, 10, 12, 11, 12, 12, 11, 15, 11, 16, 15, 17, 15, 18, 15, 19, 15, 20, 15, 21, 15, 22, 15, 23, 9, 27, 25, 0, 25, 1, 27,
+ 10, 27, 11, 27, 12, 27, 13, 27, 14, 27, 15, 27, 16, 27, 17, 27, 18, 27, 19, 31, 20, 31, 21, 31, 22, 26, 23, 25, 27, 31, 1, 93,
+ 1, 39, 46, 1, 35, 34, 6, 7, 35, 62, 1, 51, 50, 22, 31, 1, 30, 1, 51, 50, 54, 55, 51, 14, 1, 35, 34, 38, 2,100, 57, 21,
+ 33, 14, 38, 36, 2,124, 1,102, 91, 39, 64, 37, 57, 21, 33, 13, 39, 36, 1,125, 1,102, 91, 39, 64,254, 88, 55, 20, 19, 74, 81,
+134,148, 28, 33, 55, 20, 19, 74, 81,134,148, 28, 0, 1, 1, 61,254,155, 3,148,255, 47, 0, 3, 0, 17,182, 2,182, 0, 4, 1,
+ 0, 4, 16,212,204, 49, 0, 16,220,236, 48, 5, 33, 21, 33, 1, 62, 2, 86,253,170,209,148, 0,255,255, 0, 0,254, 29, 4,209,
+254,109, 16, 6, 0, 66, 0, 0,255,255, 0, 0,254, 29, 4,209,255, 93, 16, 6, 6,140, 0, 0,255,255, 0, 88, 1,236, 4,121,
+ 3, 12, 16, 6, 0, 97, 0, 0, 0, 1, 0,141, 1,196, 4, 38, 2,104, 0, 3, 0, 0, 1, 21, 33, 53, 4, 38,252,104, 2,104,
+164,164, 0, 0, 0, 1, 0, 0, 1,196, 4,209, 2,104, 0, 3, 0, 0, 17, 53, 33, 21, 4,209, 1,196,164,164, 0, 1, 0, 47,
+255,160, 4,150, 4,188, 0, 3, 0, 0, 23, 39, 1, 23,139, 92, 4, 10, 93, 96, 76, 4,208, 77, 0, 1, 0, 8,255,186, 4,176,
+ 6, 23, 0, 3, 0, 0, 23, 39, 1, 23,111,103, 4, 68,100, 70, 70, 6, 23, 74, 0, 1, 1,250,254, 10, 2,214,255,193, 0, 12,
+ 0, 0, 1, 50, 54, 53, 52, 38, 35, 53, 50, 22, 20, 6, 35, 1,250, 51, 71, 71, 51, 93,127,127, 93,254,108, 71, 51, 50, 71, 98,
+127,184,128, 0, 0, 1, 1, 85,254,128, 3,124,255,202, 0, 7, 0, 0, 1, 17, 51, 21, 33, 53, 51, 17, 1, 85,137, 1, 21,137,
+254,128, 1, 74,194,194,254,182, 0, 2, 1, 85,253, 9, 3,124,255, 47, 0, 3, 0, 7, 0, 0, 5, 17, 33, 17, 1, 17, 33, 17,
+ 3,124,253,217, 1,158,254,235,209,253,218, 2, 38,254, 98, 1, 22,254,234, 0, 0, 1, 0,206,254, 57, 4, 3,255, 88, 0, 20,
+ 0, 0, 5, 54, 51, 50, 19, 20, 21, 35, 38, 35, 34, 7, 35, 38, 39, 34, 7, 35, 18, 55, 50, 2,104, 60,116,218, 17,117, 14,104,
+101, 15,118, 12,105,102, 15,118, 15,220,116,250, 82,254,230, 2, 3,150,150,149, 1,150, 1, 30, 1, 0, 0, 0, 0, 1, 1,139,
+ 4,203, 3, 70, 6,135, 0, 11, 0, 0, 1, 7, 39, 55, 39, 55, 23, 55, 23, 7, 23, 7, 2,104,125, 96,125,125, 96,125,126, 96,
+125,125, 96, 5, 73,125, 96,125,125, 97,126,126, 97,125,125, 96, 0, 1, 1,219, 4,194, 2,246, 6,210, 0, 29, 0, 0, 1, 46,
+ 1, 53, 52, 54, 55, 21, 14, 1, 21, 20, 23, 22, 31, 1, 30, 1, 21, 20, 6, 7, 53, 62, 1, 53, 52, 39, 38, 39, 2, 24, 32, 28,
+146,136, 82, 74, 10, 11, 19, 54, 34, 28,148,134, 82, 72, 9, 11, 18, 5,199, 28, 48, 28, 80, 81, 2,110, 2, 27, 28, 10, 12, 15,
+ 14, 43, 28, 48, 28, 80, 81, 2,110, 2, 27, 28, 10, 12, 15, 14,255,255, 0, 0, 4,203, 4,209, 6, 11, 16, 38, 6,161, 0, 0,
+ 16, 7, 6,161, 0, 0,255, 16,255,255, 1,239, 4,194, 2,226, 6,193, 16, 6, 2,143, 0, 0,255,255, 4, 2, 5, 68, 4,207,
+ 6, 16, 16, 7, 2,107, 2, 1, 0, 0, 0, 0, 0, 1,255, 19, 5,240, 5,190, 7, 55, 0, 15, 0, 0, 0, 34, 5, 4, 7, 35,
+ 52, 37, 54, 50, 23, 4, 21, 35, 38, 37, 2,160,110,254,226,254,244,126,118, 1,252,228,233,229, 1,252,118,127,254,243, 6,174,
+ 25, 23,142,240, 60, 27, 27, 60,240,142, 23, 0, 0, 1, 1,236, 4,116, 2,235, 6,102, 0, 3, 0, 0, 1, 19, 51, 3, 1,236,
+ 65,190,110, 4,116, 1,242,254, 14, 0, 0, 0, 0, 1, 1,230,254, 86, 2,229, 0, 72, 0, 3, 0, 0, 37, 3, 35, 19, 2,229,
+ 65,190,110, 72,254, 14, 1,242, 0, 1, 2, 30,254, 86, 2,250,255,164, 0, 9, 0, 0, 1, 35, 34, 61, 1, 51, 21, 20, 59, 1,
+ 2,250,132, 88,149, 51, 20,254, 86,183,151,164,104, 0, 0, 0,255,255, 1,147,254,225, 2,242, 4, 39, 16, 6, 0, 30, 0, 0,
+255,255, 1,219, 4,238, 3,186, 6,102, 16, 6, 0,118, 0, 0,255,255, 1, 63, 5, 70, 3,186, 7,216, 16, 38, 0,106, 0, 0,
+ 16, 7, 2,195, 0, 0, 1,114,255,255, 0, 25, 0, 0, 4,172, 6,102, 16, 38, 2,206, 0, 0, 16, 7, 2,195,254, 62, 0, 0,
+255,255, 1,233, 2, 47, 2,229, 3, 96, 16, 6, 0,121, 0, 0,255,255,255, 31, 0, 0, 4, 78, 6,102, 16, 38, 2,210, 0, 0,
+ 16, 7, 2,195,253, 68, 0, 0,255,255,254,237, 0, 0, 4, 72, 6,102, 16, 38, 2,212, 0, 0, 16, 7, 2,195,253, 18, 0, 0,
+255,255,255, 31, 0, 0, 4, 6, 6,102, 16, 38, 2,214, 0, 0, 16, 7, 2,195,253, 68, 0, 0,255,255,255,181,255,227, 4, 92,
+ 6,102, 16, 38, 2,220, 0, 0, 16, 7, 2,195,253,218, 0, 0,255,255,254,112, 0, 0, 4,172, 6,102, 16, 38, 2,225, 0, 0,
+ 16, 7, 2,195,252,149, 0, 0,255,255,255,206, 0, 0, 4,135, 6,102, 16, 38, 2,229, 0, 0, 16, 7, 2,195,253,243, 0, 0,
+255,255, 1, 54, 0, 0, 3,207, 7,216, 16, 38, 2,245, 0, 0, 16, 6, 2,196, 0, 0, 0, 0,255,255, 0, 37, 0, 0, 4,172,
+ 5,213, 16, 6, 0, 36, 0, 0,255,255, 0,166, 0, 0, 4,113, 5,213, 16, 6, 0, 37, 0, 0,255,255, 0,215, 0, 0, 4,115,
+ 5,213, 16, 6, 3, 64, 0, 0, 0, 2, 0, 37, 0, 0, 4,172, 5,213, 0, 2, 0, 6, 0, 49,180, 3, 47, 4, 48, 7, 16,244,
+228, 49, 0,180, 5,180, 2,151, 4, 47,236,228, 48, 5, 64, 16, 1, 37, 5, 4, 0, 37, 3, 6, 3, 2, 37, 1, 37, 4, 5, 4,
+ 7, 16,236,236, 7, 16,236, 8,236, 37, 9, 1, 5, 33, 1, 51, 3,170,254,190,254,190, 3,134,251,121, 1,201,245,170, 4,121,
+251,135,170, 5,213, 0, 0, 0,255,255, 0,197, 0, 0, 4, 78, 5,213, 16, 6, 0, 40, 0, 0,255,255, 0,156, 0, 0, 4,145,
+ 5,213, 16, 6, 0, 61, 0, 0,255,255, 0,137, 0, 0, 4, 72, 5,213, 16, 6, 0, 43, 0, 0, 0, 3, 0,117,255,227, 4, 92,
+ 5,240, 0, 3, 0, 15, 0, 27, 0, 54, 64, 11, 3, 4, 50, 16, 54, 2, 10, 50, 22, 53, 28, 16,252,236,196,252,236,196,178,128,
+ 3, 1, 93, 49, 0, 64, 15, 7,151, 25,150, 28, 1,151, 2,177, 28, 13,151, 19,153, 28, 16,244,236, 16,244,236, 16,244,236, 48,
+ 1, 33, 53, 33, 23, 16, 2, 35, 34, 2, 17, 16, 18, 51, 50, 18, 19, 16, 2, 35, 34, 2, 17, 16, 18, 51, 50, 18, 3, 48,254,113,
+ 1,143, 89,135,154,153,135,135,153,154,135,211,247,253,253,246,247,252,253,247, 2,199,170,136, 1, 73, 1, 26,254,230,254,183,
+254,184,254,230, 1, 25, 1, 73,254,122,254,128, 1,126, 1,136, 1,135, 1,128,254,128, 0, 0,255,255, 0,201, 0, 0, 4, 6,
+ 5,213, 16, 6, 0, 44, 0, 0,255,255, 0,137, 0, 0, 4,201, 5,213, 16, 6, 0, 46, 0, 0, 0, 1, 0, 37, 0, 0, 4,172,
+ 5,213, 0, 6, 0, 48,180, 4, 47, 1, 48, 7, 16,244,228, 49, 0,179, 2,180, 5, 1, 47, 60,228, 48, 5, 64, 16, 6, 37, 2,
+ 1, 5, 37, 3, 4, 3, 6, 37, 0, 37, 1, 2, 1, 7, 16,236,236, 7, 16,236, 8,236, 51, 35, 1, 51, 1, 35, 1,246,209, 1,
+201,245, 1,201,209,254,141, 5,213,250, 43, 5, 35, 0, 0, 0,255,255, 0, 86, 0, 0, 4,121, 5,213, 16, 6, 0, 48, 0, 0,
+255,255, 0,139, 0, 0, 4, 70, 5,213, 16, 6, 0, 49, 0, 0, 0, 3, 0,137, 0, 0, 4, 72, 5,213, 0, 3, 0, 7, 0, 11,
+ 0, 40,183, 7, 8, 0, 49, 6, 11, 3, 12, 16,212, 60,196,244, 60,196, 49, 0, 64, 12, 2,151, 3,136, 10, 5,151, 6,177, 11,
+151, 10, 47,236,244,236, 16,244,236, 48, 1, 21, 33, 53, 1, 33, 53, 33, 19, 21, 33, 53, 4, 72,252, 65, 2,244,253,215, 2, 41,
+203,252, 65, 5,213,170,170,252,242,170,253, 57,170,170, 0, 0,255,255, 0,117,255,227, 4, 92, 5,240, 16, 6, 0, 50, 0, 0,
+255,255, 0,137, 0, 0, 4, 72, 5,213, 16, 6, 3, 76, 0, 0,255,255, 0,197, 0, 0, 4,117, 5,213, 16, 6, 0, 51, 0, 0,
+ 0, 1, 0,120, 0, 0, 4,109, 5,213, 0, 11, 0, 60,181, 2, 9, 49, 5, 8, 12, 16,212, 60,228, 50, 49, 0, 64, 9, 11, 7,
+151, 8,136, 1, 5,151, 4, 47,236, 50,244,236, 50, 48, 5, 64, 16, 0, 37, 6, 5, 11, 37, 6, 7, 6, 0, 37, 1, 37, 5, 6,
+ 5, 7, 16,236,236, 7, 16,236, 8,236, 9, 1, 33, 21, 33, 53, 9, 1, 53, 33, 21, 33, 3, 18,254, 57, 3, 34,252, 11, 1,198,
+254, 58, 3,245,252,222, 2,235,253,191,170,170, 2, 65, 2, 64,170,170, 0, 0,255,255, 0, 47, 0, 0, 4,162, 5,213, 16, 6,
+ 0, 55, 0, 0,255,255, 0, 37, 0, 0, 4,172, 5,213, 16, 6, 0, 60, 0, 0, 0, 3, 0,117, 0, 0, 4, 90, 5,213, 0, 29,
+ 0, 38, 0, 47, 0, 77, 64, 19, 34, 50, 5, 11, 28, 9, 38, 0, 30, 14, 27, 25, 44, 50, 20, 16, 40, 25, 48, 16,212, 60, 60,220,
+236, 16,196, 50,252, 60, 60,196, 50,220,236, 49, 0, 64, 20, 38, 40,151, 1, 24, 0, 26,151, 27,136, 13, 30, 39,151, 9, 16, 10,
+ 14,151, 13, 47,252, 60,220, 60,236, 50, 16,244,252, 60,220, 60,236, 50, 48, 1, 21, 22, 23, 22, 21, 20, 7, 6, 7, 21, 51, 21,
+ 33, 53, 51, 53, 38, 39, 38, 53, 52, 55, 54, 55, 53, 35, 53, 33, 21, 3, 54, 55, 54, 53, 52, 39, 38, 39, 3, 17, 6, 7, 6, 21,
+ 20, 23, 22, 2,205,176, 97,124,123, 97,177,147,254, 15,147,177, 97,123,123, 98,176,147, 1,241,147, 76, 43, 67, 67, 43, 76,203,
+ 76, 42, 68, 68, 42, 5, 43,118, 19, 91,115,235,235,115, 90, 19,116,170,170,116, 19, 90,115,235,235,115, 91, 19,118,170,170,252,
+163, 16, 42, 68,157,158, 68, 42, 16,253,201, 2, 55, 16, 42, 68,158,157, 68, 42,255,255, 0, 18, 0, 0, 4,190, 5,213, 16, 6,
+ 0, 59, 0, 0, 0, 1, 0,117, 0, 0, 4, 90, 5,213, 0, 31, 0, 57, 64, 15, 6, 30, 7, 14, 12, 0, 30, 17, 31, 25, 30, 24,
+ 19, 31, 32, 16,212, 60,212,236, 16,196,252, 60,196,212,236, 49, 0, 64, 13, 1, 30,151, 12, 19, 13, 17,151, 6, 31, 24,136, 16,
+ 47,228, 50, 50,252, 60,220, 60,236, 50, 48, 1, 17, 54, 55, 54, 25, 1, 51, 17, 16, 7, 6, 7, 21, 51, 21, 33, 53, 51, 53, 38,
+ 39, 38, 25, 1, 51, 17, 16, 23, 22, 23, 17, 2,205, 73, 46, 75,203,123, 98,176,147,254, 15,147,176, 98,123,203, 76, 45, 73, 5,
+213,252, 91, 34, 87,145, 1, 68, 1, 87,254,169,254,120,191,151, 32,214,170,170,214, 32,151,191, 1,136, 1, 87,254,169,254,188,
+145, 87, 34, 3,165, 0, 0, 0, 0, 1, 0, 74, 0, 0, 4,135, 5,180, 0, 31, 0, 64, 64, 23, 2, 30, 27, 14, 17,113, 21, 30,
+113, 27, 15,114, 21,111, 11,112, 0,114, 27,111, 5,108, 32, 16,244,236,228,244,236,228, 16,228, 16,228, 57, 17, 18, 57, 49, 0,
+ 64, 12, 24,248, 8,247, 30, 18, 14, 3, 1,249, 16, 0, 47, 60,238, 23, 50,246,238, 48, 51, 53, 51, 38, 2, 53, 16, 0, 51, 50,
+ 0, 17, 20, 2, 7, 51, 21, 33, 53, 54, 18, 53, 52, 2, 35, 34, 2, 21, 20, 18, 23, 21, 74,245,123,110, 1, 32,240,242, 1, 33,
+111,123,248,254, 49,120,134,180,154,154,179,134,120,172,134, 1, 32,188, 1, 55, 1,111,254,146,254,200,188,254,223,133,172,172,
+ 76, 1, 73,222,230, 1, 9,254,247,230,222,254,183, 76,172, 0,255,255, 0,201, 0, 0, 4, 6, 7, 78, 16, 39, 11,176, 0, 0,
+ 1,117, 16, 6, 2,214, 0, 0,255,255, 0, 37, 0, 0, 4,172, 7, 78, 16, 39, 11,176, 0, 0, 1,117, 16, 6, 2,225, 0, 0,
+255,255, 0, 70,255,230, 4,149, 6,102, 16, 38, 2,237, 0, 0, 16, 6, 2,195, 0, 0, 0, 0,255,255, 0,169,255,234, 4, 40,
+ 6,102, 16, 38, 2,241, 0, 0, 16, 6, 2,195, 0, 0, 0, 0,255,255, 0,195,254, 86, 4, 27, 6,102, 16, 38, 2,243, 0, 0,
+ 16, 6, 2,195, 0, 0, 0, 0,255,255, 1, 54, 0, 0, 3,207, 6,102, 16, 38, 2,245, 0, 0, 16, 6, 2,195, 0, 0, 0, 0,
+255,255, 0, 51,255,255, 4,105, 7,216, 16, 38, 3, 1, 0, 0, 16, 6, 2,196, 0, 0, 0, 0, 0, 2, 0, 70,255,230, 4,149,
+ 4,122, 0, 13, 0, 42, 0, 0, 1, 39, 38, 39, 38, 7, 6, 21, 20, 23, 22, 51, 50, 55, 18, 27, 1, 51, 3, 23, 22, 23, 22, 59,
+ 1, 21, 35, 34, 39, 38, 39, 6, 7, 6, 39, 38, 39, 38, 17, 16, 55, 54, 55, 2,254, 44, 45,177, 98, 61, 77, 74, 77, 85,133, 72,
+105, 59, 99,164,205, 40, 9, 35, 41, 32, 88,110, 94, 84, 41, 17, 46, 92, 45,143,198,114,118,126,143,161, 2, 9,231,236, 1, 1,
+111,137,183,220,105,107,213, 3, 42,254,189, 1, 37,253,161,219, 49, 41, 48,156, 84, 42, 88,109, 89, 42, 1, 2,150,156, 1, 20,
+ 1, 41,135,151, 3, 0, 0, 0, 0, 2, 0,151,254, 86, 4, 97, 6, 35, 0, 14, 0, 28, 0, 0, 37, 17, 35, 17, 16, 5, 4, 17,
+ 2, 7, 4, 19, 18, 5, 6, 3, 22, 23, 4, 17, 16, 5, 53, 4, 17, 52, 39, 36, 17, 1, 81,185, 1,205, 1,143, 1,171, 1, 22,
+ 2, 4,254, 26,130,171, 81,227, 1, 32,254, 48, 1,107,234,254,251, 69,254, 17, 6, 3, 1,231, 31, 27,254,154,254,236, 98, 54,
+254,209,254, 61, 23, 6, 1,113,141, 21, 25, 1, 39, 1, 26, 22,170, 6, 1, 48,189, 13, 15,254,224, 0, 0, 0, 0, 1, 0, 32,
+254, 86, 4,109, 4, 96, 0, 14, 0, 0, 19, 38, 43, 1, 53, 51, 50, 23, 9, 1, 51, 1, 17, 35, 17,220, 45, 94, 49, 70,194, 65,
+ 0,255, 1, 70,191,254, 91,190, 3, 68,126,158,176,253, 83, 3, 93,251,160,254, 86, 1,170, 0, 0, 2, 0,137,255,227, 4, 72,
+ 6, 34, 0, 11, 0, 52, 0, 0, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 37, 38, 39, 38, 53, 52, 54, 51, 50, 31, 1, 21,
+ 38, 39, 38, 15, 1, 6, 15, 1, 6, 21, 20, 23, 22, 23, 22, 23, 22, 23, 22, 17, 16, 2, 35, 34, 2, 17, 16, 55, 54, 2,104,140,
+144,144,140,141,144,144,254, 89, 19, 40, 62,237,197,102, 50,151, 66, 70, 85, 82, 32, 73, 60, 39, 27, 13, 17, 41, 24,105,235,121,
+124,246,234,233,246,123, 31, 3,223,218,214,213,219,219,213,214,218, 76, 9, 40, 61, 92,136,164, 12, 36,173, 24, 15, 17, 2, 1,
+ 2, 43, 28, 24, 46, 33, 19, 24, 21, 13, 1, 3,148,151,254,226,254,225,254,211, 1, 45, 1, 31, 1, 30,151, 38,255,255, 0,169,
+255,234, 4, 40, 4,123, 16, 6, 1,249, 0, 0, 0, 1, 0,152,254, 82, 4, 38, 6, 20, 0, 29, 0, 0, 37, 22, 23, 22, 21, 20,
+ 7, 6, 35, 52, 53, 22, 55, 54, 53, 52, 39, 38, 35, 32, 3, 2, 1, 33, 53, 33, 21, 0, 19, 18, 2,248,132, 79, 84, 74, 80,163,
+ 69, 42, 32, 32, 31, 58,253,181, 20, 17, 2, 76,253,236, 3,102,252,254, 46, 44,127, 1, 75, 79,120,115, 80, 87, 75, 76, 5, 44,
+ 35, 37, 53, 44, 42, 2, 51, 1,224, 1,101,185,185,254, 97,254, 90,254,105, 0, 0, 1, 0,195,254, 86, 4, 27, 4,123, 0, 19,
+ 0, 46, 64, 10, 2, 6, 0, 74, 13, 9, 6, 11, 70, 20, 16,244,236, 50,252,236, 49, 64, 15, 9, 14, 3, 0, 4, 10, 6,140, 17,
+190, 12,194, 1,195, 10, 0, 47,228,228,244,236, 17, 23, 57, 48, 1, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62,
+ 1, 51, 50, 22, 4, 27,185,106,113,129,139,184,184, 49,168,115,171,169, 2,182,251,160, 4, 96,151,142,183,171,253,135, 4, 96,
+168, 96, 99,225, 0, 3, 0,137,255,227, 4, 72, 5,220, 0, 8, 0, 17, 0, 29, 0, 57, 64, 11, 9, 0, 18, 21, 68, 10, 8, 18,
+ 27, 62, 30, 16,244,236, 50,252,236, 50, 49, 64, 14, 9,182, 0, 14,140, 24, 0, 4,140, 18,155, 24,153, 30, 0, 16,228,244,236,
+196, 16,236,182,239, 0,191, 0, 64, 0, 3, 93, 16,236, 48, 1, 38, 39, 38, 35, 34, 7, 6, 7, 5, 33, 22, 23, 22, 51, 50, 55,
+ 54, 1, 50, 18, 17, 16, 2, 35, 34, 2, 17, 16, 18, 3,131, 7, 63, 72,141,140, 72, 63, 7, 2, 53,253,203, 6, 64, 72,140,141,
+ 72, 64,254,235,233,247,246,234,233,246,246, 3, 60,226,135,153,153,135,226,184,224,137,154,154,137, 4, 56,254,119,254,141,254,
+138,254,121, 1,135, 1,118, 1,115, 1,137, 0, 0, 1, 1, 54, 0, 0, 3,207, 4, 96, 0, 15, 0, 29, 64, 6, 6, 0, 6, 15,
+ 13, 16, 16,212,204,252,204, 49, 64, 7, 13,182, 0,194, 6,182, 7, 0, 47,236,244,236, 48, 1, 17, 20, 23, 22, 59, 1, 21, 35,
+ 34, 39, 38, 39, 17, 35, 53, 2,196, 34, 36,108, 89,111,180, 82, 81, 1,210, 4, 96,253, 43,145, 46, 48,156, 96, 98,212, 2, 59,
+143, 0, 0, 0,255,255, 0,236, 0, 0, 4,178, 4, 96, 18, 6, 0,250, 0, 0, 0, 1, 0, 68, 0, 0, 4,134, 6, 21, 0, 13,
+ 0, 0, 9, 1, 35, 9, 1, 35, 1, 39, 38, 7, 35, 53, 23, 4, 2,130, 2, 4,195,254,198,254,126,195, 1,235, 74, 47,154, 49,
+ 70, 1, 18, 5,101,250,155, 3, 60,252,196, 4, 50,198,127, 1,158, 2, 7, 0,255,255, 0,195,254, 84, 4,158, 4, 96, 16, 6,
+ 0,119, 0, 0, 0, 1, 0,116, 0, 0, 4, 66, 4, 96, 0, 21, 0, 0, 33, 1, 51, 1, 54, 55, 54, 55, 54, 39, 38, 39, 51, 49,
+ 22, 23, 22, 21, 20, 7, 6, 7, 1,202,254,170,198, 1, 33,120,100, 76, 4, 2, 24, 28,106,186, 69, 46, 42,136,177,123, 4, 96,
+252, 84,124,172,129,112, 53,100,119,131, 89,124,114, 78,196,175,228,116, 0, 0, 0, 1, 0,161,254, 82, 4, 56, 6, 20, 0, 38,
+ 0, 0, 37, 22, 23, 22, 21, 20, 7, 6, 35, 52, 53, 22, 55, 54, 53, 52, 39, 38, 35, 32, 3, 52, 37, 36, 17, 52, 55, 35, 53, 33,
+ 21, 32, 17, 20, 5, 21, 4, 23, 18, 3, 17,132, 79, 84, 74, 80,163, 69, 42, 32, 32, 32, 57,253,146, 1, 1, 77,254,232,220,208,
+ 3, 21,253,139, 2, 16,253,199, 1, 2,127, 1, 75, 79,120,115, 80, 87, 75, 76, 5, 44, 35, 37, 53, 44, 42, 1,225,232,112, 36,
+ 1, 4,197, 82,185,185,254,221,191, 9,170, 38,220,254,191, 0,255,255, 0,137,255,227, 4, 72, 4,123, 16, 6, 0, 82, 0, 0,
+ 0, 1, 0, 80,255,217, 4,158, 4, 96, 0, 23, 0, 0, 19, 33, 21, 35, 17, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 53,
+ 17, 33, 17, 35, 17, 35, 80, 4, 49,141, 49, 55, 15, 44, 7, 35, 74, 37,113, 92,254, 84,180,143, 4, 96,184,253, 80, 72, 63, 5,
+ 1,133, 13, 12,131,176, 2,156,252, 88, 3,168, 0, 2, 0,190,254, 86, 4, 84, 4,124, 0, 16, 0, 28, 0, 46, 64, 10, 17, 18,
+ 4, 71, 23, 10, 6, 12, 70, 29, 16,244,236, 50,252,236, 49, 64, 14, 10, 20, 26,140, 7, 20,140, 0,190, 7,153, 11,195, 29, 0,
+ 16,228,228,244,236, 16,238, 17, 57, 48, 1, 54, 23, 22, 17, 16, 2, 35, 34, 38, 39, 17, 35, 17, 16, 55, 54, 1, 52, 38, 35, 34,
+ 6, 21, 20, 22, 51, 50, 54, 2,132,232,116,116,232,202,102,153, 44,185,110,131, 1,228,135,133,134,138,138,134,133,135, 4,123,
+ 1,158,157,254,234,254,239,254,201, 87, 83,253,201, 3,198, 1, 60,134,157,253,180,214,218,219,213,212,220,218, 0, 1, 0,195,
+254, 82, 4, 37, 4,123, 0, 36, 0, 0, 37, 22, 23, 22, 21, 20, 7, 6, 35, 52, 53, 22, 55, 54, 53, 52, 39, 38, 35, 32, 0, 16,
+ 0, 33, 50, 22, 23, 21, 46, 1, 35, 34, 6, 21, 20, 23, 22, 2,236,132, 79, 84, 74, 80,163, 69, 42, 32, 32, 31, 58,254,252,254,
+219, 1, 37, 1, 4, 81,154, 78, 73,147, 93,173,186, 93, 94,127, 1, 75, 79,120,115, 80, 87, 75, 76, 5, 44, 35, 37, 53, 44, 42,
+ 1, 56, 2, 40, 1, 56, 42, 44,193, 65, 58,224,208,209,110,111, 0, 2, 0,137,255,226, 4,107, 4, 96, 0, 13, 0, 29, 0, 50,
+ 64, 10, 29, 10, 18, 16, 68, 4, 18, 23, 62, 30, 16,244,236,244,236,196,179, 14, 27, 23, 16, 17, 18, 57, 57, 49, 64, 11, 7,140,
+ 20, 0, 14,182, 27,194, 20,153, 30, 0, 16,228,244,236, 50, 16,236, 48, 1, 34, 7, 6, 21, 20, 22, 51, 50, 54, 53, 52, 39, 38,
+ 55, 22, 17, 20, 7, 6, 39, 34, 2, 17, 16, 55, 54, 51, 33, 21, 2, 97,135, 70, 72,144,140,141,144,172, 60,221,206,151,114,215,
+233,246,123,115,241, 2, 3, 3,167, 80, 83,213,213,219,219,146,249,129, 45, 21,162,254,230,228,167,127, 1, 1, 45, 1, 31, 1,
+ 9,153,143,184, 0, 1, 0,159, 0, 0, 4, 50, 4, 94, 0, 17, 0, 33, 64, 7, 13, 3, 15, 6, 12, 10, 18, 16,212,204,252,196,
+204, 49, 0, 64, 8, 15, 11,140, 12,194, 3,182, 4, 47,236,244,236, 50, 48, 37, 22, 59, 1, 21, 35, 34, 39, 38, 53, 17, 33, 53,
+ 33, 21, 33, 17, 20, 2,230, 36,108, 89,111,180, 82, 82,254,152, 3,146,254,146,204, 48,156, 96, 98,212, 2, 18,182,182,253,227,
+145, 0, 0, 0, 0, 1, 0, 51,255,255, 4,105, 4, 96, 0, 30, 0, 0, 37, 50, 55, 54, 55, 54, 39, 38, 39, 51, 49, 22, 23, 22,
+ 21, 20, 7, 6, 37, 34, 39, 38, 53, 3, 35, 53, 33, 17, 20, 23, 22, 2,116,150, 90, 59, 15, 8, 30, 28,106,186, 70, 45, 42,128,
+133,254,250,180, 82, 82, 1,210, 1,143, 34, 35,156,179,118,187,102,128,119,131, 90,123,115,154,225,203,211, 1, 96, 98,212, 2,
+ 59,143,253, 43,145, 46, 48, 0, 0, 2, 0, 76,254, 86, 4,133, 4,104, 0, 10, 0, 41, 0, 79, 64, 13, 7, 18, 15, 19, 3, 6,
+ 30, 22, 39, 35, 18, 26, 42, 16,176, 10, 75, 81, 88,220, 27,212, 89,236,212,180, 48, 39,128, 39, 2, 93, 60,196,252, 60,212,180,
+ 48, 15,128, 15, 2, 93,236, 49, 64, 16, 3, 39,140, 22, 31, 0,140, 30, 11,190, 19, 22,153, 21,195, 42, 0, 16,236,228, 50,244,
+ 60,236, 50, 16,236, 50, 48, 1, 34, 21, 17, 50, 55, 54, 53, 52, 39, 38, 39, 50, 23, 22, 17, 16, 7, 6, 35, 17, 35, 17, 34, 39,
+ 38, 17, 16, 55, 54, 55, 21, 6, 7, 6, 21, 20, 23, 22, 51, 17, 16, 3, 5, 65, 92, 86, 77, 77, 71, 42,138,119,127,127,129,193,
+183,199,124,126,126,104,154, 65, 49, 76, 76, 78,101, 3,203,145,253, 82,104, 93,223,221, 99, 91,157,132,141,254,217,254,230,150,
+152,254,110, 1,145,153,155, 1, 20, 1, 44,132,109, 28,163, 26, 75,115,190,216,101,103, 2,175, 1, 46, 0, 0, 0, 1, 0, 89,
+254, 86, 4,120, 4, 96, 0, 23, 0, 0, 5, 3, 1, 35, 1, 3, 38, 43, 1, 53, 51, 32, 23, 19, 1, 51, 1, 19, 22, 59, 1, 21,
+ 35, 32, 2,238,142,254,247,191, 1,116,183, 47,156, 49, 70, 1, 0, 67,143, 1, 10,191,254,139,182, 47,157, 49, 70,254,255,250,
+ 1,122,253,214, 3, 9, 1,229,126,158,176,254,132, 2, 44,252,244,254, 30,126,158, 0, 0, 0, 0, 1, 0,131,254, 86, 4, 78,
+ 4, 96, 0, 27, 0, 0, 37, 54, 55, 54, 53, 17, 51, 17, 20, 7, 6, 7, 17, 35, 17, 38, 39, 38, 53, 17, 51, 17, 20, 23, 22, 23,
+ 17, 51, 2,196, 63, 62, 84,185,130,121,143,183,143,121,130,185, 84, 62, 63,183,140, 22, 64, 87,166, 2,129,253,120,216,145,135,
+ 1,254,111, 1,145, 1,135,145,216, 2,136,253,127,166, 87, 64, 22, 3,212, 0, 0, 1, 0, 70,255,227, 4,140, 4, 96, 0, 38,
+ 0, 0, 1, 18, 16, 7, 6, 35, 34, 38, 39, 14, 1, 35, 34, 39, 38, 16, 19, 51, 2, 17, 6, 23, 22, 55, 54, 55, 54, 17, 51, 16,
+ 23, 22, 23, 22, 55, 54, 39, 16, 3, 4, 9,131, 50, 75,186, 85,130, 21, 20,128, 88,186, 75, 50,131,190,126, 1, 18, 41, 64, 86,
+ 34, 25,170, 25, 34, 86, 64, 41, 18, 1,126, 4, 96,254,248,253,191,123,185,103, 76, 72,107,185,123, 2, 65, 1, 8,254,237,254,
+225,226, 62,145, 2, 2,111, 82, 1,121,254,135, 82,111, 2, 2,145, 62,226, 1, 31, 1, 19, 0,255,255, 1, 54, 0, 0, 3,207,
+ 6, 16, 16, 38, 2,245, 0, 0, 16, 6, 0,106, 0, 0, 0, 0,255,255, 0, 51,255,255, 4,105, 6, 16, 16, 38, 3, 1, 0, 0,
+ 16, 6, 0,106, 0, 0, 0, 0,255,255, 0,137,255,227, 4, 72, 6,102, 16, 38, 2,251, 0, 0, 16, 6, 2,195, 0, 0, 0, 0,
+255,255, 0, 51,255,255, 4,105, 6,102, 16, 38, 3, 1, 0, 0, 16, 6, 2,195, 0, 0, 0, 0,255,255, 0, 70,255,227, 4,140,
+ 6,102, 16, 38, 3, 5, 0, 0, 16, 6, 2,195, 0, 0, 0, 0, 0, 3, 0,149,255,232, 4, 67, 6, 36, 0, 9, 0, 25, 0, 35,
+ 0, 0, 1, 32, 55, 54, 39, 38, 7, 6, 7, 6, 5, 4, 3, 6, 37, 36, 39, 38, 3, 2, 55, 54, 51, 32, 19, 22, 5, 6, 39, 18,
+ 23, 22, 55, 54, 55, 54, 1, 93, 1, 12, 78,147, 26, 31,172,142, 73, 53, 1,237, 1,124,192,117,255, 0,254,237,116,102, 10, 9,
+128,134,210, 1, 77, 50, 27,254,142, 67,240, 6, 54, 82,165,175, 54, 87, 3,112, 65,123,137,161, 6, 5,165,122,253,250,254,137,
+225, 12, 15,198,178, 1,151, 1,127,202,212,254,130,205,255, 30, 10,254,253,105,161, 4, 4,152,245, 0, 0, 0, 0, 2, 0,114,
+255,233, 4, 83, 6, 36, 0, 9, 0, 36, 0, 0, 1, 54, 39, 38, 39, 38, 7, 6, 23, 22, 23, 4, 39, 38, 55, 18, 33, 50, 23, 22,
+ 3, 2, 7, 6, 35, 34, 39, 38, 19, 23, 18, 23, 22, 51, 50, 55, 54, 3,139, 4, 53, 74,103,172, 31, 26,147, 78,233,254,221,110,
+240, 29, 45, 1, 82,171,135,128, 9, 9,128,137,228,193,159,149, 13,195, 7, 78,114, 94,121,100, 80, 3,112,191,119,166, 4, 6,
+161,137,123, 65,170, 10, 75,164,251, 1,126,212,200,254,127,254,125,198,213,213,200, 1,235, 1,254, 83,106,156,157,126, 0, 0,
+ 0, 1, 0, 34, 0, 0, 4,185, 5,225, 0, 27, 0, 0, 1, 6, 3, 6, 21, 17, 35, 17, 52, 39, 2, 39, 38, 7, 53, 54, 23, 4,
+ 19, 18, 55, 54, 23, 22, 7, 6, 39, 38, 3,173,113, 79, 42,203, 42,100, 92,116,120, 76,151, 1, 15, 74,115,229,111, 64,122, 56,
+ 32,118, 86, 5, 17, 79,254,250,141,165,253,118, 2,138,180,126, 1, 42, 43, 52, 26,170, 24, 27, 48,254,114, 1,137, 53, 26, 49,
+ 95,148, 84, 24, 18, 0, 0, 0,255,255,254,112, 0, 0, 4,185, 6,102, 16, 38, 3, 13, 0, 0, 16, 7, 2,195,252,149, 0, 0,
+255,255, 0, 34, 0, 0, 4,185, 7, 78, 16, 38, 3, 13, 0, 0, 16, 7, 11,176, 0, 0, 1,117, 0, 3, 0,109,254, 86, 4,100,
+ 5,213, 0, 21, 0, 30, 0, 39, 0, 0, 1, 35, 17, 38, 39, 38, 17, 16, 55, 54, 55, 17, 51, 17, 22, 23, 22, 17, 16, 7, 6, 7,
+ 53, 54, 55, 54, 53, 52, 39, 38, 39, 3, 17, 6, 7, 6, 21, 20, 23, 22, 2,196,184,179,104,132,132, 93,190,184,178,105,133,133,
+ 94,189, 86, 53, 82, 82, 42, 97,184, 87, 52, 81, 81, 40,254, 86, 1,147, 24,121,150, 1, 31, 1, 14,167,118, 26, 1, 97,254,159,
+ 24,120,151,254,226,254,242,167,120, 25,165, 23, 71,110,213,188,135, 70, 25,252,189, 3, 67, 22, 73,109,214,185,138, 68, 0, 0,
+ 0, 2, 0, 57,255,255, 4,152, 4, 96, 0, 13, 0, 30, 0, 0, 1, 33, 6, 7, 2, 51, 50, 3, 51, 2, 55, 54, 3, 38, 55, 22,
+ 23, 18, 37, 38, 3, 2, 35, 32, 19, 54, 55, 35, 53, 33, 21, 3,146,253,176, 39, 3, 4, 84,177, 5,170, 3,175, 81, 1, 1,157,
+ 48, 6, 14,254,228,238, 39, 40,237,254,231, 11, 4, 48, 65, 4, 95, 3,168,144,253,254,171, 1,211,254, 43, 2, 1, 1, 84,253,
+144,145,247,253,223, 1, 1, 1, 51,254,204, 2, 32,239,153,184,184, 0, 0, 0, 0, 1, 0, 51,254, 91, 4,146, 4,103, 0, 47,
+ 0, 0, 5, 38, 39, 38, 55, 7, 2, 7, 6, 39, 38, 55, 54, 55, 54, 39, 38, 35, 34, 7, 53, 54, 23, 22, 23, 22, 7, 55, 18, 55,
+ 54, 23, 22, 7, 6, 7, 6, 23, 22, 51, 50, 55, 2, 7, 6, 39, 53, 4, 3,189,246, 33, 21, 24,189, 96,200,141, 3, 1, 61, 96,
+136, 91, 43, 26,142, 57, 91, 82,126,246, 33, 19, 42,189, 96,200,141, 3, 1, 61, 96,136, 91, 43, 26,142, 57, 91, 38,205,152,173,
+ 1, 55, 10, 32,240,156, 99,108,254,247,124, 89,145, 68, 84,132,124,203,169,104,108,224, 61, 17, 34,238,140,112,108, 1, 9,124,
+ 89,145, 68, 84,132,124,203,169,104,108,253,224,102, 77, 90,160,160, 0, 0, 0, 0, 2, 0,117,254, 86, 4, 92, 5,240, 0, 10,
+ 0, 27, 0, 0, 0, 16, 2, 35, 34, 2, 17, 16, 18, 51, 50, 1, 17, 38, 39, 38, 17, 16, 18, 51, 50, 18, 17, 16, 7, 6, 7, 17,
+ 3,137,135,154,153,135,135,153,154,255, 0,179, 95,123,247,252,253,247,124, 94,181, 1,160, 2,146, 1, 26,254,230,254,183,254,
+184,254,230,253,207, 1,150, 34,148,191, 1,136, 1,135, 1,128,254,128,254,121,254,124,194,149, 34,254,106, 0, 0, 2, 0,137,
+254, 86, 4, 72, 4,123, 0, 11, 0, 27, 0, 0, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 3, 17, 35, 17, 38, 39, 38, 17,
+ 16, 18, 32, 18, 17, 16, 7, 6, 2,104,140,144,144,140,141,144,144, 49,184,168, 96,123,246, 1,210,247,123, 95, 3,223,218,214,
+213,219,219,213,214,218,252, 10,254,109, 1,147, 26,119,150, 1, 31, 1, 30, 1, 46,254,210,254,226,254,225,150,118, 0, 0, 0,
+ 0, 1, 0,139,254, 82, 4, 76, 5,213, 0, 35, 0, 0, 1, 34, 7, 6, 17, 16, 18, 51, 50, 23, 22, 21, 20, 7, 6, 35, 52, 53,
+ 22, 55, 54, 53, 52, 39, 38, 35, 34, 39, 38, 17, 16, 55, 54, 41, 1, 21, 2,231,218, 77, 98,176,129,122, 89, 84, 74, 80,163, 69,
+ 42, 32, 32, 32, 57,234,159,123,159,139, 1, 50, 1,101, 5, 43,119,152,254,205,254,206,254,208, 84, 79,120,115, 80, 87, 75, 76,
+ 5, 44, 35, 37, 53, 44, 42,203,158, 1,157, 1,110,205,177,170, 0, 1, 0,155,254, 82, 4, 41, 4, 96, 0, 35, 0, 0, 1, 33,
+ 34, 7, 6, 21, 20, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 35, 52, 53, 22, 55, 54, 53, 52, 39, 38, 35, 34, 0, 17, 16, 55, 54,
+ 41, 1, 4, 41,254,155,193, 73, 93, 93, 95, 98,133, 78, 84, 74, 80,163, 69, 42, 32, 32, 32, 57,187,254,219,147,138, 1, 12, 1,
+101, 3,196, 85,108,212,209,110,111, 2, 2, 74, 79,120,115, 80, 87, 75, 76, 5, 44, 35, 37, 53, 44, 42, 1, 56, 1, 20, 1, 40,
+136,129, 0, 0,255,255, 0,233, 0, 0, 4, 88, 5,213, 18, 6, 0, 41, 0, 0, 0, 1, 0, 0,254, 86, 4, 6, 6, 20, 0, 35,
+ 0, 0, 33, 17, 52, 55, 54, 51, 50, 22, 23, 21, 46, 1, 35, 34, 7, 6, 21, 17, 33, 21, 33, 17, 20, 7, 6, 35, 34, 38, 39, 53,
+ 30, 1, 51, 50, 55, 54, 1,174,136, 96,169, 49, 99, 51, 36, 82, 44,120, 58, 75, 1, 65,254,191,139, 98,173, 57,102, 46, 49,100,
+ 48, 87, 64, 82, 4,130,160,142,100, 18, 18,164, 28, 29, 62, 81,111,254,201,143,253, 63,146,165,115, 21, 22,164, 31, 33, 75, 95,
+ 0, 1, 0, 96,255,252, 4,129, 5,213, 0, 23, 0, 0, 1, 3, 1, 3, 6, 23, 22, 55, 21, 34, 39, 38, 55, 19, 1, 19, 54, 39,
+ 38, 7, 53, 50, 23, 22, 1,227,110, 3, 12,234, 39, 27, 66,131,230, 81, 95, 19,154,253, 6,172, 39, 27, 66,131,230, 81, 95, 4,
+135,254, 91, 1,126,253, 44, 96, 42,108, 35,189, 70, 82,182, 1,218,254,145, 2,144, 96, 42,108, 35,189, 70, 82, 0, 1, 0,132,
+ 0, 0, 4, 77, 6, 19, 0, 7, 0, 0, 9, 1, 35, 19, 33, 1, 51, 3, 4, 77,254,231,184,226,253, 38, 1, 25,184,226, 3,112,
+252,144, 2,198, 3, 77,253, 93, 0, 1, 0, 33,254, 86, 4,154, 5,241, 0, 33, 0, 0, 1, 17, 35, 17, 6, 7, 53, 54, 5, 4,
+ 19, 18, 17, 16, 3, 35, 18, 17, 16, 39, 48, 7, 6, 21, 17, 35, 48, 17, 16, 63, 1, 38, 39, 38, 1,129,170, 98, 84,155, 1, 5,
+ 1, 66,215,192,224,225,238, 60,102, 90,203,208,112,140,157, 75, 5, 75,253,140, 2, 73, 10, 77,198,102, 5, 7,254,213,254,241,
+253,189,254, 55,254,179, 1, 76, 1,202, 1,243, 91, 79, 70,235,253,198, 2, 53, 1, 2,177, 96,182, 52, 25, 0, 0, 1, 0, 89,
+254,144, 4,120, 4,120, 0, 22, 0, 0, 1, 3, 35, 1, 38, 39, 1, 35, 1, 38, 39, 38, 35, 53, 32, 23, 22, 19, 18, 17, 35, 16,
+ 39, 3, 80,239,185, 1,100, 14, 50,254, 70,185, 2, 31, 98, 46,188,211, 1, 45,242,224,172,116,168, 96, 1, 52,254,204, 1,192,
+ 35, 77,253,208, 2,176,127, 33,132,164,216,200,254, 80,254,223,254,137, 1, 94,246, 0, 0, 0, 0, 1, 0, 52,255,242, 4,145,
+ 4,103, 0, 51, 0, 0, 1, 2, 7, 6, 35, 34, 53, 52, 1, 54, 53, 52, 39, 38, 35, 34, 7, 53, 54, 51, 50, 23, 4, 17, 20, 7,
+ 55, 18, 55, 54, 51, 50, 21, 20, 1, 6, 21, 20, 23, 22, 51, 50, 55, 21, 6, 35, 34, 39, 36, 17, 52, 55, 1,236, 96,200, 55, 34,
+ 55, 1, 36, 62, 14, 26,142, 57, 91, 64, 91, 26, 27, 1, 29, 29,189, 96,200, 55, 34, 55,254,220, 62, 14, 26,142, 57, 91, 64, 91,
+ 26, 27,254,227, 29, 1,153,254,247,124, 34, 79,154, 1, 9,138,122, 58, 54,104,108,224, 48, 4, 37,254,193, 91, 77,108, 1, 9,
+124, 34, 79,154,254,247,138,122, 58, 54,104,108,224, 48, 4, 37, 1, 63, 91, 77, 0, 2, 0,190,254, 86, 4, 84, 4,124, 0, 21,
+ 0, 32, 0, 0, 19, 16, 55, 54, 51, 54, 23, 22, 17, 16, 2, 35, 34, 38, 39, 18, 41, 1, 21, 33, 32, 17, 36, 16, 38, 35, 34, 6,
+ 21, 20, 22, 51, 50,190,110,129,215,232,116,116,232,202,102,153, 44, 5, 1, 28, 1,168,254,104,254, 22, 2,213,135,133,134,138,
+138,134,133, 2, 28, 1, 60,134,157, 1,158,157,254,234,254,239,254,201, 87, 83,254,115,170, 2,218, 41, 1,172,218,219,213,212,
+220, 0, 0, 0,255,255, 0,195,255,227, 4, 37, 4,123, 18, 6, 0, 70, 0, 0,255,255, 0,186,254, 86, 3, 16, 6, 20, 18, 6,
+ 0, 77, 0, 0, 0, 3, 0,117,255,227, 4, 92, 5,240, 0, 8, 0, 17, 0, 28, 0, 0, 1, 38, 39, 38, 35, 34, 7, 6, 7, 5,
+ 33, 18, 23, 22, 51, 50, 55, 54, 19, 16, 2, 32, 2, 17, 16, 18, 51, 50, 18, 3,134, 11, 53, 68,154,153, 67, 54, 11, 2, 62,253,
+191, 2, 66, 67,153,154, 68, 64,214,247,254, 6,246,247,252,253,247, 3,113,223,111,141,141,112,222,170,254,213,136,141,141,134,
+ 1, 79,254,122,254,128, 1,126, 1,136, 1,135, 1,128,254,128, 0, 1, 0,162,255,227, 4, 9, 4,123, 0, 33, 0, 0, 1, 38,
+ 39, 38, 35, 34, 7, 6, 7, 33, 21, 33, 22, 23, 22, 51, 50, 63, 1, 21, 7, 6, 35, 32, 39, 38, 16, 55, 54, 33, 50, 23, 22, 23,
+ 4, 9, 37, 37, 99,106,183,102, 95, 18, 2,165,253, 91, 18, 95,102,183,128, 77, 74, 79,104,107,254,244,156,157,157,156, 1, 12,
+101,110, 40, 39, 3,174, 13, 10, 26, 99, 92,169,144,169, 92, 99, 26, 25,167, 18, 22,156,156, 2, 40,156,156, 22, 8, 12, 0, 0,
+ 0, 1, 0,162,255,227, 4, 9, 4,123, 0, 34, 0, 0, 19, 48, 53, 54, 55, 54, 51, 32, 23, 22, 16, 7, 6, 33, 34, 47, 1, 53,
+ 23, 22, 51, 50, 55, 54, 55, 33, 53, 33, 38, 39, 38, 35, 34, 7, 6,162, 39, 40,110,101, 1, 12,156,157,157,156,254,244,107,104,
+ 79, 74, 77,128,183,102, 95, 18,253, 91, 2,165, 18, 95,102,183,106, 99, 37, 3,174,163, 12, 8, 22,156,156,253,216,156,156, 22,
+ 18,167, 25, 26, 99, 92,169,144,169, 92, 99, 26, 10, 0, 0, 0,255,255, 0,201, 0, 0, 4,141, 5,213, 18, 6, 0,160, 0, 0,
+255,255, 0,190,254, 86, 4, 84, 6, 31, 18, 6, 0,192, 0, 0,255,255, 0,139,255,227, 4, 49, 5,240, 18, 6, 0, 38, 0, 0,
+ 0, 1, 0, 86, 0, 0, 4,121, 5,213, 0, 12, 0, 0, 19, 33, 9, 1, 33, 17, 35, 17, 1, 35, 1, 17, 35, 86, 1, 14, 1, 2,
+ 1, 4, 1, 15,187,254,246,153,254,245,186, 5,213,254,123, 1,133,250, 43, 5, 39,254, 96, 1,160,250,217, 0, 0, 1, 0,127,
+254, 86, 4, 79, 4, 96, 0, 12, 0, 0, 19, 33, 27, 1, 33, 17, 35, 17, 3, 35, 3, 17, 35,127, 1, 27,204,206, 1, 27,185,226,
+153,227,185, 4, 96,254,123, 1,133,251,160, 3,178,254, 96, 1,160,250,164, 0, 0, 2, 0, 85,254, 86, 4, 84, 4,124, 0, 24,
+ 0, 35, 0, 0, 1, 21, 35, 53, 35, 53, 51, 17, 16, 55, 54, 51, 54, 23, 22, 17, 16, 2, 35, 34, 38, 39, 17, 33, 21, 18, 16, 38,
+ 35, 34, 6, 21, 20, 22, 51, 50, 1,119,185,105,105,110,131,213,232,116,116,232,202,102,153, 44, 1,225, 59,135,133,134,138,138,
+134,133,254,198,112,112,170, 2,172, 1, 62,132,157, 1,158,157,254,234,254,239,254,201, 87, 83,254,227,170, 2,147, 1,172,218,
+219,213,212,220, 0, 1, 0,139,255,227, 4, 49, 5,240, 0, 25, 0, 0, 55, 53, 30, 1, 51, 50, 18, 17, 16, 2, 35, 34, 6, 7,
+ 53, 62, 1, 51, 32, 0, 17, 16, 0, 33, 34, 38,139, 73,169, 88,197,196,196,197, 86,170, 74, 77,162, 91, 1, 29, 1, 63,254,195,
+254,225, 91,162, 53,207, 61, 64, 1, 48, 1, 50, 1, 51, 1, 48, 64, 61,207, 41, 41,254,103,254,146,254,144,254,106, 41, 0, 0,
+255,255, 0,139,255,227, 4, 49, 5,240, 18, 38, 3, 38, 0, 0, 16, 7, 0,121, 0,139, 0, 0,255,255, 0,139,255,227, 4, 49,
+ 5,240, 16, 39, 0,121,255, 99, 0, 0, 16, 6, 3, 42, 0, 0,255,255, 0,197, 0, 0, 4, 78, 7,107, 16, 39, 11,179, 0, 0,
+ 1,117, 16, 6, 3, 66, 0, 0,255,255, 0,197, 0, 0, 4, 78, 7, 78, 16, 39, 11,176, 0, 56, 1,117, 16, 6, 3, 66, 0, 0,
+ 0, 1,255,190,254, 42, 4,111, 5,215, 0, 47, 0, 0, 1, 23, 22, 51, 50, 54, 53, 17, 52, 38, 35, 34, 7, 6, 7, 6, 21, 17,
+ 35, 17, 35, 53, 33, 21, 33, 17, 54, 55, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 17, 16, 7, 6, 35, 34, 39, 52, 2, 61,
+ 78, 13, 12,143,113,106,113,106, 87, 46, 22, 69,203,246, 3,126,254, 67, 37, 48, 34, 14, 64,149, 26, 22,160, 88, 14, 11, 85,107,
+105,247, 83, 17,254,225, 17, 2,149,203, 1,160,151,142, 42, 21, 28, 92,171,254,111, 5, 45,170,170,253,243, 42, 24, 17, 9, 37,
+ 10, 2, 84, 13, 16,112,228,254, 70,254,232,119,117, 2, 2, 0,255,255, 0,215, 0, 0, 4,115, 7,107, 16, 39, 11,177, 0, 72,
+ 1,117, 16, 6, 3, 64, 0, 0, 0, 1, 0,139,255,227, 4, 49, 5,240, 0, 24, 0, 76, 64, 33, 0,151, 22,177, 25, 5,179, 6,
+178, 3,151, 8, 17,179, 16,178, 19,151, 14,150, 8,153, 25, 23, 0, 22, 50, 17, 6, 49, 11, 48, 25, 16,252,236, 50,252, 50,204,
+ 49, 0, 16,228,244,236,244,236, 16,238,246,238, 16,252,238,177, 22, 19, 73,177, 3, 0, 73, 80, 88,179, 22, 0, 64, 2, 23, 56,
+ 89, 48, 1, 22, 18, 51, 50, 55, 21, 6, 35, 32, 0, 17, 16, 0, 33, 50, 23, 21, 38, 35, 34, 2, 3, 33, 21, 1, 94, 4,192,189,
+188,150,154,176,254,225,254,195, 1, 63, 1, 29,176,154,152,190,190,163, 23, 2,115, 2,149,228,254,214,125,207, 82, 1,150, 1,
+111, 1,111, 1,153, 82,207,125,254,244,254,255,170, 0, 0, 0,255,255, 0,139,255,227, 4, 74, 5,240, 16, 6, 0, 54, 0, 0,
+255,255, 0,201, 0, 0, 4, 6, 5,213, 16, 6, 0, 44, 0, 0,255,255, 0,201, 0, 0, 4, 6, 7, 78, 16, 38, 3, 51, 0, 0,
+ 17, 7, 11,176, 0, 0, 1,117, 0, 8,180, 1, 18, 15, 0, 7, 43, 49, 0, 0,255,255, 0,109,255,227, 3,188, 5,213, 16, 6,
+ 0, 45, 0, 0, 0, 2,255,237, 0, 0, 4,199, 5,213, 0, 7, 0, 29, 0, 0, 37, 51, 50, 54, 16, 38, 43, 1, 25, 1, 51, 50,
+ 4, 16, 4, 43, 1, 17, 35, 21, 16, 2, 6, 35, 53, 50, 54, 18, 25, 1, 3, 33, 21, 90,125,121, 94, 21, 21,144, 1, 1,254,254,
+143,207,172, 24,202,236,138,118, 20,166,142, 1, 14,149, 2,254,253,168,226,254, 72,227, 5, 43,250,254,198,253,247,238,164,143,
+ 1,161, 1, 87, 1,170, 0, 0, 0, 2, 0, 34, 0, 0, 4,199, 5,213, 0, 8, 0, 28, 0, 0, 37, 51, 50, 54, 53, 52, 38, 43,
+ 1, 3, 17, 33, 17, 35, 17, 51, 17, 33, 17, 51, 17, 51, 50, 23, 22, 21, 20, 4, 35, 3, 33, 21, 90,125,120, 95, 21,186,254,117,
+186,186, 1,139,186, 21,179,119,103,254,254,143,166,142,130,140,149,253, 41, 2,199,253, 57, 5,213,253,156, 2,100,253,168,113,
+ 99,234,220,227, 0, 1,255,190, 0, 0, 4,111, 5,215, 0, 34, 0, 0, 1, 17, 54, 55, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23,
+ 22, 21, 17, 35, 17, 52, 38, 35, 34, 7, 6, 7, 6, 21, 17, 35, 17, 35, 53, 33, 21, 1,127, 37, 48, 34, 14, 64,149, 26, 22,160,
+ 88, 14, 11, 85,203,106,113,106, 87, 46, 22, 69,203,246, 3,126, 5, 45,253,243, 42, 24, 17, 9, 37, 10, 2, 84, 13, 16,112,228,
+254, 24, 1,206,151,142, 42, 21, 28, 92,171,254,111, 5, 45,170,170, 0, 0, 0,255,255, 0,137, 0, 0, 4,201, 7,107, 16, 39,
+ 11,177, 0, 27, 1,117, 16, 6, 3, 71, 0, 0,255,255, 0,139, 0, 0, 4, 70, 7,107, 16, 39, 11,179, 0, 0, 1,117, 16, 6,
+ 3, 69, 0, 0,255,255, 0,104, 0, 0, 4,129, 7,109, 16, 38, 11,184, 0, 0, 16, 6, 3, 80, 0, 0, 0, 0, 0, 1, 0,137,
+254,190, 4, 72, 5,213, 0, 11, 0, 0, 51, 17, 51, 17, 33, 17, 51, 17, 33, 17, 35, 17,137,203, 2, 41,203,254,118,171, 5,213,
+250,213, 5, 43,250, 43,254,190, 1, 66, 0, 0,255,255, 0, 37, 0, 0, 4,172, 5,213, 16, 6, 0, 36, 0, 0, 0, 2, 0,166,
+ 0, 0, 4,113, 5,213, 0, 8, 0, 23, 0, 50, 64, 28, 0,151, 12, 9,151, 22,136, 1,151, 12, 20, 20, 12, 8, 2, 4, 0, 23,
+ 5, 50, 16, 49, 10, 0, 30, 22, 48, 24, 16,252,236, 50,252,236,196, 17, 23, 57, 49, 0, 47,204,236,244,236, 16,236, 48, 1, 17,
+ 51, 50, 54, 53, 52, 38, 35, 1, 33, 17, 51, 4, 23, 22, 21, 20, 7, 6, 41, 1, 17, 33, 1,113,239,176,150,158,168, 1,204,253,
+ 69,235, 1,123,101, 53,133,133,254,249,254, 70, 3,134, 2,201,253,221,123,141,146,137, 2,102,254, 62, 15,191,100,161,203,103,
+104, 5,213, 0,255,255, 0,166, 0, 0, 4,113, 5,213, 16, 6, 0, 37, 0, 0, 0, 1, 0,215, 0, 0, 4,115, 5,213, 0, 5,
+ 0, 24,182, 2, 49, 4, 30, 1, 52, 6, 16,252,236,236, 49, 0,180, 3,151, 1,136, 5, 47,244,236, 48, 51, 17, 33, 21, 33, 17,
+215, 3,156,253, 47, 5,213,170,250,213, 0, 0, 0, 2, 0, 33,254,190, 4,176, 5,213, 0, 15, 0, 26, 0, 48, 64, 13, 4, 30,
+ 1, 16, 30, 15, 18, 30, 13, 5, 30, 8, 27, 16,212,236,220,236,212,236,220,236, 49, 0, 64, 11, 17,151, 14,136, 1, 26, 8,151,
+ 3, 7, 5, 47,204, 50,236, 50, 50,244,236, 48, 37, 51, 17, 35, 17, 33, 17, 35, 17, 51, 50, 19, 18, 25, 1, 33, 7, 33, 17, 20,
+ 3, 2, 6, 21, 20, 51, 33, 4, 55,121,170,252,197,170, 77, 48, 39, 30, 3, 84,203,254, 66, 28, 27, 11, 47, 1,209,170,254, 20,
+ 1, 66,254,190, 1,236, 1, 76, 1, 0, 1, 13, 1,210,170,254,215,224,254,225,254,225, 28, 8, 22, 0, 0, 0,255,255, 0,197,
+ 0, 0, 4, 78, 5,213, 16, 6, 0, 40, 0, 0, 0, 1, 0, 15, 0, 0, 4,194, 5,213, 0, 19, 0,120, 64, 11, 8, 5, 4, 3,
+ 6, 9, 1, 30, 12, 0, 20, 16,220, 60,252, 60,192, 23, 57, 49, 0, 64, 12, 66, 8, 5, 2, 3, 17, 3, 0,180, 15, 10, 6, 47,
+ 60, 60,236, 50, 50, 23, 57, 48, 75, 83, 88, 64, 9, 8, 37, 9, 8, 5, 7, 37, 6, 5, 7, 5,237, 16, 8,237, 89, 1, 64, 19,
+ 13, 0, 8, 14, 0, 7, 15, 0, 6, 16, 0, 5, 17, 0, 4, 18, 0, 3, 1, 16, 73, 58, 73, 58, 73, 58, 73, 58, 73, 58, 73, 58,
+ 0,183, 12, 9, 13, 8, 16, 5, 19, 2, 16, 60, 16, 60, 16, 60, 16, 60, 1, 51, 17, 1, 51, 9, 1, 35, 3, 7, 17, 35, 17, 39,
+ 3, 35, 9, 1, 51, 1, 2, 11,187, 1, 28,207,254,225, 1, 48,197,222, 89,187, 89,222,197, 1, 48,254,225,207, 1, 28, 5,213,
+253,173, 2, 83,253,166,252,133, 2,138,186,254, 48, 1,208,186,253,118, 3,123, 2, 90,253,173,255,255, 0,137,255,227, 4, 55,
+ 5,240, 16, 6, 0, 22, 0, 0, 0, 1, 0,139, 0, 0, 4, 70, 5,213, 0, 9, 0, 60, 64, 28, 8, 4, 3, 4, 3, 9, 8, 9,
+ 66, 8, 2, 3, 5,180, 7, 0, 9, 4, 3, 8, 17, 6, 49, 3, 17, 1, 48, 10, 16,252,236,252,236, 17, 57, 57, 49, 0, 47, 60,
+236, 50, 57, 57, 48, 75, 83, 88, 7, 16, 4,201, 7, 16, 4,201, 89, 34, 51, 17, 51, 17, 1, 33, 17, 35, 17, 1,139,195, 1,248,
+ 1, 0,195,254, 8, 5,213,251, 51, 4,205,250, 43, 4,205,251, 51, 0, 0, 0,255,255, 0,139, 0, 0, 4, 70, 7,109, 16, 38,
+ 11,184, 0, 0, 16, 6, 3, 69, 0, 0, 0, 0,255,255, 0,137, 0, 0, 4,201, 5,213, 16, 6, 0, 46, 0, 0, 0, 1, 0, 4,
+ 0, 0, 4, 70, 5,213, 0, 15, 0, 36, 64, 8, 15, 30, 12, 1, 30, 10, 6, 16, 16,212,220,236,212,236, 49, 0, 64, 9, 6,151,
+ 5, 0,151, 11,136, 14, 5, 47, 60,244,236, 16,236, 48, 1, 21, 16, 2, 6, 35, 53, 50, 54, 18, 25, 1, 33, 17, 35, 17, 1,227,
+ 23,203,253,138,118, 20, 3, 46,203, 5, 43,250,254,187,254, 2,238,164,143, 1,161, 1, 87, 1,170,250, 43, 5, 43, 0, 0, 0,
+255,255, 0, 86, 0, 0, 4,121, 5,213, 16, 6, 0, 48, 0, 0,255,255, 0,137, 0, 0, 4, 72, 5,213, 16, 6, 0, 43, 0, 0,
+255,255, 0,117,255,227, 4, 92, 5,240, 16, 6, 0, 50, 0, 0, 0, 1, 0,137, 0, 0, 4, 72, 5,213, 0, 7, 0, 30, 64, 9,
+ 4, 30, 1, 49, 5, 30, 0, 48, 8, 16,252,236,252,236, 49, 0,181, 4,151, 0,136, 6, 2, 47, 60,244,236, 48, 19, 33, 17, 35,
+ 17, 33, 17, 35,137, 3,191,203,253,215,203, 5,213,250, 43, 5, 43,250,213, 0,255,255, 0,197, 0, 0, 4,117, 5,213, 16, 6,
+ 0, 51, 0, 0,255,255, 0,139,255,227, 4, 49, 5,240, 16, 6, 0, 38, 0, 0,255,255, 0, 47, 0, 0, 4,162, 5,213, 16, 6,
+ 0, 55, 0, 0, 0, 1, 0,104, 0, 0, 4,129, 5,213, 0, 20, 0, 63, 64, 13, 66, 8,151, 7,153, 19, 16,136, 21, 20, 8, 16,
+ 21, 16,212,196,196, 49, 0, 16,228, 50,244,236, 48, 75, 83, 88, 64, 18, 18, 37, 0, 16, 15, 19, 37, 20, 20, 0, 18, 37, 15, 17,
+ 37, 16, 16, 15, 5, 7, 16,236, 16,236, 7, 16,236, 8, 16,236, 89, 1, 6, 7, 6, 7, 6, 43, 1, 53, 51, 50, 55, 54, 55, 54,
+ 55, 1, 51, 9, 1, 51, 2,229, 59, 69, 44, 76, 69, 92,148,109, 81, 46, 45, 34, 14, 15,254, 88,217, 1, 55, 1, 52,213, 1,169,
+158,111, 74, 43, 39,172, 47, 46, 77, 32, 42, 4, 53,252,194, 3, 62, 0, 0, 0, 0, 3, 0, 66, 0, 0, 4,143, 5,213, 0, 6,
+ 0, 24, 0, 31, 0,103, 64, 15, 28, 50, 12, 15, 31, 9, 30, 24, 4, 50, 21, 18, 1, 24, 32, 16,212, 60, 60,212,236, 16,252, 60,
+ 60,212,236, 49, 0, 64, 14, 31, 1,151, 9, 24, 7,136, 17, 25, 0,151, 15, 18, 17, 47,220, 60,236, 50, 16,244,220, 60,236, 50,
+ 48, 1,176, 13, 75, 84,176, 16, 75, 84, 91,176, 21, 75, 84, 91,176, 25, 75, 84, 91, 88,191, 0, 33, 0, 32,255,192, 0, 2, 0,
+ 0, 0, 32, 0, 32, 0, 64, 56, 18, 54, 23, 56, 89, 1, 17, 14, 1, 21, 20, 22, 19, 51, 21, 4, 18, 17, 16, 2, 5, 21, 35, 53,
+ 38, 2, 17, 16, 18, 37, 19, 62, 1, 53, 52, 38, 39, 2, 3,165, 73, 73,165,203, 1, 11,182,182,254,245,203,250,199,184, 1, 9,
+203,165, 73, 73,165, 1, 60, 3,123, 26,220,199,200,220, 4,127,122, 10,254,170,254,255,254,252,254,172, 10,152,152, 10, 1, 87,
+ 1, 1, 1, 4, 1, 83, 10,251,225, 26,220,200,199,220, 26, 0,255,255, 0, 18, 0, 0, 4,190, 5,213, 16, 6, 0, 59, 0, 0,
+ 0, 1, 0, 80,254,190, 4,149, 5,213, 0, 11, 0, 36, 64, 18, 6, 2,136, 10, 8, 4,151, 11, 11, 30, 8, 4, 30, 6, 3, 30,
+ 0, 12, 16,212,236,212,236,220,236, 49, 0, 47,236, 50,204,236, 50, 48, 51, 17, 51, 17, 33, 17, 51, 17, 51, 17, 35, 17, 80,203,
+ 2, 41,203,134,170, 5,213,250,213, 5, 43,250,213,254, 20, 1, 66, 0, 0, 0, 0, 1, 0,137, 0, 0, 4, 68, 5,213, 0, 19,
+ 0, 32, 64, 16, 17,151, 6, 1, 10,136, 13, 14, 9, 30, 11, 3, 30, 0, 48, 20, 16,252,236,212,236, 50, 49, 0, 47,236, 50,220,
+236, 48, 19, 17, 51, 17, 20, 22, 51, 50, 54, 55, 17, 51, 17, 35, 17, 14, 1, 35, 34, 38,137,203,110,109,117,122, 91,203,203,118,
+150,126,183,175, 3,212, 2, 1,254, 25,163, 80, 29, 69, 2,120,250, 43, 2,146, 58, 23,196, 0, 0, 1, 0,114, 0, 0, 4, 96,
+ 5,213, 0, 11, 0, 38, 64, 10, 11, 30, 10, 8, 30, 6, 3, 30, 1, 12, 16,212,236,220,236,220,236, 49, 0, 64, 8, 6, 11, 2,
+136, 8, 4,151, 1, 47,236, 50,252, 60, 60, 48, 41, 1, 17, 51, 17, 51, 17, 51, 17, 51, 17, 51, 4, 96,252, 18,186,224,186,224,
+186, 5,213,250,213, 5, 43,250,213, 5, 43, 0, 0, 1, 0, 60,254,190, 4,176, 5,213, 0, 15, 0, 47, 64, 13, 15, 30, 12, 11,
+ 30, 9, 7, 30, 5, 3, 30, 1, 16, 16,212,236,220,236,220,252,220,236, 49, 0, 64, 10, 6, 9, 2,136, 11, 8, 4,151, 14, 0,
+ 47,204,236, 50, 50,252, 60, 60, 48, 51, 17, 51, 17, 51, 17, 51, 17, 51, 17, 51, 17, 51, 17, 35, 17, 60,186,224,186,224,186,134,
+170, 5,213,250,213, 5, 43,250,213, 5, 43,250,213,254, 20, 1, 66, 0, 0, 0, 0, 2, 0, 32, 0, 0, 4,117, 5,213, 0, 8,
+ 0, 21, 0, 42, 64, 9, 4, 50, 18, 14, 0, 30, 9, 11, 22, 16,212,220,236, 50, 47,236, 49, 0, 64, 12, 14,151, 8,177, 22, 10,
+182, 13,136, 0,151, 9, 47,236,244,236, 16,244,236, 48, 37, 51, 50, 54, 53, 52, 38, 43, 1, 3, 17, 33, 53, 33, 17, 51, 50, 4,
+ 21, 20, 4, 35, 1,239,138,141,156,157,140,138,202,254,251, 1,207,138,251, 1, 1,254,254,250,166,147,133,133,148,253, 41, 5,
+ 43,170,253,168,226,221,219,227, 0, 3, 0, 65, 0, 0, 4,110, 5,213, 0, 3, 0, 13, 0, 24, 0, 44, 64, 11, 3, 30, 0, 9,
+ 50, 21, 17, 4, 30, 14, 25, 16,212,236, 50, 47,236,220,236, 49, 0, 64, 11, 17,151, 13,177, 4,151, 1, 15,136, 14, 0, 47, 60,
+228, 50,236,244,236, 48, 33, 17, 51, 17, 37, 51, 50, 55, 54, 53, 52, 38, 43, 1, 3, 17, 51, 17, 51, 50, 4, 21, 20, 4, 35, 3,
+163,203,252,157, 91,102, 78, 60,121,119, 91,202,202, 91,194, 1, 1,254,254,193, 5,213,250, 43,166, 74, 56,150,133,148,253, 41,
+ 5,213,253,168,226,221,219,227, 0, 2, 0,197, 0, 0, 4,117, 5,213, 0, 8, 0, 21, 0, 43, 64, 24, 8,151, 12, 0,151, 10,
+136, 9, 21, 13, 1, 7, 4, 0, 4, 50, 17, 56, 0, 12, 30, 10, 51, 22, 16,252,236, 50,252,236, 17, 23, 57, 49, 0, 47,228,236,
+212,236, 48, 37, 51, 50, 54, 53, 52, 38, 43, 1, 3, 17, 51, 17, 51, 50, 23, 22, 21, 20, 7, 6, 35, 1,143,234,141,156,157,140,
+234,202,202,234,251,128,129,129,129,250,166,147,133,133,148,253, 41, 5,213,253,168,113,113,221,219,113,114, 0, 0, 1, 0,139,
+255,227, 4, 49, 5,240, 0, 27, 0, 77, 64, 9, 11, 9, 12, 50, 25, 49, 19, 2, 29, 16,220, 60,244,236, 50,196, 49, 0, 64, 23,
+ 9,151, 12,177, 29, 3,179, 2,178, 5,151, 0, 18,179, 19,178, 16,151, 21,150, 0,153, 28, 16,228,244,236,244,236, 16,238,246,
+238, 16,252,238,177, 12, 16, 73,177, 5, 9, 73, 80, 88,179, 9, 12, 64, 2, 23, 56, 89, 48, 5, 34, 39, 53, 22, 51, 50, 55, 54,
+ 55, 33, 53, 33, 2, 39, 38, 35, 34, 7, 53, 54, 51, 32, 23, 22, 16, 7, 6, 1,213,176,154,150,188,189, 96, 95, 5,253,136, 2,
+115, 30, 63, 98,188,187,152,154,176, 1, 29,160,159,159,158, 29, 82,207,125,147,148,231,170, 1, 20, 97,152,125,207, 82,204,205,
+253, 34,203,203, 0, 2, 0, 60,255,227, 4,149, 5,240, 0, 11, 0, 30, 0, 64, 64, 36, 24, 23, 15, 14, 4, 16, 22, 3,151, 16,
+150, 9,151, 22,153, 28, 26,151, 12,177, 30,136, 28, 0, 30, 19, 28, 5, 30, 25, 13, 26, 12, 30, 28, 31, 16,212,236, 50,212, 50,
+236, 16,212,236, 49, 0, 47,228,252,238, 16,228,238,244,236, 17, 18, 23, 57, 48, 1, 16, 2, 35, 34, 2, 17, 16, 18, 51, 50, 18,
+ 1, 51, 26, 1, 51, 50, 18, 17, 16, 2, 35, 34, 2, 3, 35, 17, 35, 17, 51, 3,207, 95,107,107, 95, 95,107,107, 95,253, 56,111,
+ 10,187,202,202,198,198,202,203,186, 10,111,203,203, 2,233, 1, 73, 1, 26,254,230,254,183,254,184,254,230, 1, 25, 1,164, 1,
+ 67, 1,105,254,128,254,121,254,122,254,128, 1,106, 1, 77,253,102, 5,213, 0, 0, 2, 0, 76, 0, 0, 4,109, 5,213, 0, 8,
+ 0, 22, 0, 67, 64, 13, 10, 20, 0, 5, 20, 30, 17, 49, 0, 50, 13, 9, 23, 16,212,212,236,244,236, 50, 18, 17, 57, 49, 0, 64,
+ 11, 66, 10, 4,151, 21, 5,151, 17,136, 19, 9, 47, 60,244,236,212,236, 57, 48, 75, 83, 88,183, 21, 37, 10, 22, 37, 9, 9, 10,
+ 7, 16, 5,237, 16,237, 89, 1, 20, 22, 51, 33, 17, 33, 34, 6, 9, 1, 46, 1, 53, 52, 36, 51, 33, 17, 35, 17, 33, 1, 1,116,
+142,145, 1, 15,254,249,144,151,254,216, 1,113,108,178, 1, 6,246, 1,210,203,254,222,254,162, 4, 37,134,130, 2, 18,137,251,
+ 90, 2,154, 39,178,178,210,222,250, 43, 2,119,253,137, 0, 0,255,255, 0,133,255,227, 4, 35, 4,123, 16, 6, 0, 68, 0, 0,
+ 0, 2, 0,125,255,227, 4, 72, 6, 55, 0, 8, 0, 42, 0, 54, 64, 13, 34, 35, 0, 18, 14, 68, 4, 18, 9, 6, 20, 62, 43, 16,
+244,236,236,252,236,212,196, 49, 0, 64, 16, 7,140, 17, 34,182, 35, 30,182, 40, 2,140, 11,190, 17,153, 43, 16,228,244,236,220,
+236,212,236, 16,238, 48, 1, 16, 33, 32, 17, 20, 22, 51, 32, 1, 54, 51, 50, 18, 17, 16, 2, 35, 34, 2, 19, 54, 47, 1, 38, 52,
+ 55, 54, 55, 54, 55, 54, 37, 54, 55, 23, 6, 15, 1, 6, 7, 6, 7, 3,133,254,227,254,228,144,140, 1, 29,253,152,120,222,222,
+247,246,234,233,251, 5, 1, 1, 7, 5, 2, 20, 36, 91,167,128, 1, 28, 51, 35, 70, 35, 51,240, 98, 74,197, 21, 2, 47, 1,176,
+254, 80,213,219, 3,129,123,254,210,254,225,254,226,254,211, 1, 51, 1, 25, 45, 17,167,119, 82, 15,149, 73,185, 85, 65, 12, 2,
+ 16,142, 13, 5, 24, 10, 43,116,154, 0, 0, 0, 0, 3, 0,209, 0, 0, 4, 0, 4, 96, 0, 8, 0, 17, 0, 32, 0, 45, 64, 24,
+ 25, 0,182, 10, 32, 9,182, 18,194, 1,182, 32, 14, 18, 22, 5, 18, 28, 0, 9, 6, 18, 70, 33, 16,252,236, 50,212,236,212,236,
+ 49, 0, 47,236,244,236, 16,212,236, 57, 48, 1, 17, 51, 50, 54, 53, 52, 38, 35, 3, 17, 51, 50, 54, 53, 52, 38, 35, 37, 33, 50,
+ 22, 21, 20, 6, 7, 30, 1, 21, 20, 6, 35, 33, 1,137,239, 95,101, 85,107,243,228, 85, 84, 84, 86,254,101, 1,141,170,200, 95,
+ 99,133,109,209,193,254, 99, 2, 3,254,147,112, 80, 79, 94, 1,199,254,207, 85, 67, 67, 86,150,154,112,111,129, 14, 25,136,117,
+154,168, 0, 0, 0, 1, 1, 1, 0, 0, 3,241, 4, 96, 0, 5, 0, 22, 64, 10, 0,182, 3,194, 1, 4, 0, 6, 2, 6, 16,220,
+236,196, 49, 0, 47,252,236, 48, 1, 17, 35, 17, 33, 21, 1,185,184, 2,240, 3,202,252, 54, 4, 96,150, 0, 0, 0, 2, 0,105,
+254,226, 4,104, 4, 96, 0, 14, 0, 24, 0, 48, 64, 13, 4, 6, 2, 15, 6, 14, 17, 6, 12, 5, 6, 8, 25, 16,212,236,220,236,
+212,236,220,236, 49, 0, 64, 11, 16,182, 13,194, 1, 15, 8,182, 3, 7, 5, 47,204, 50,236, 50, 50,244,236, 48, 37, 51, 17, 35,
+ 17, 33, 17, 35, 17, 51, 50, 18, 53, 17, 33, 3, 17, 33, 17, 20, 7, 14, 1, 20, 51, 3,239,121,150,253, 45,150, 67, 55, 32, 2,
+236,185,254,132, 20, 8, 14, 34,150,254, 76, 1, 30,254,226, 1,180, 1,198,100, 1,160,252, 54, 3, 52,254,242,100,247,144, 33,
+ 26, 0, 0, 0,255,255, 0,123,255,227, 4, 88, 4,123, 16, 6, 0, 72, 0, 0, 0, 1, 0, 59, 0, 0, 4,151, 4, 96, 0, 19,
+ 0,120, 64, 11, 8, 5, 4, 3, 6, 9, 1, 30, 6, 0, 20, 16,220, 60,252, 60,192, 23, 57, 49, 0, 64, 12, 66, 8, 5, 2, 3,
+ 17, 3, 0,194, 15, 10, 6, 47, 60, 60,236, 50, 50, 23, 57, 48, 75, 83, 88, 64, 9, 8, 23, 9, 8, 5, 7, 23, 6, 5, 7, 5,
+237, 16, 8,237, 89, 1, 64, 19, 13, 0, 8, 14, 0, 7, 15, 0, 6, 16, 0, 5, 17, 0, 4, 18, 0, 3, 1, 16, 73, 58, 73, 58,
+ 73, 58, 73, 58, 73, 58, 73, 58, 0,183, 12, 9, 13, 8, 16, 5, 19, 2, 16, 60, 16, 60, 16, 60, 16, 60, 1, 51, 17, 1, 51, 3,
+ 1, 35, 3, 7, 17, 35, 17, 39, 3, 35, 1, 3, 51, 1, 2, 21,168, 0,255,199,239, 1, 3,179,191,104,168,104,191,179, 1, 3,
+239,199, 0,255, 4, 96,254, 80, 1,176,254,108,253, 52, 2, 16,177,254,161, 1, 95,177,253,240, 2,204, 1,148,254, 80, 0, 0,
+255,255, 0,169,255,234, 4, 40, 4,123, 16, 6, 1,250, 0, 0, 0, 1, 0,195, 0, 0, 4, 26, 4, 96, 0, 9, 0, 61, 64, 10,
+ 6, 0, 6, 8, 1, 5, 6, 2, 70, 10, 16,252,236, 50,212,236, 50, 49, 0, 64, 8, 66, 0, 5, 7, 3,194, 9, 2, 47, 60,236,
+ 50, 57, 57, 48, 75, 83, 88, 64, 10, 0, 23, 6, 5, 6, 5, 23, 1, 0, 1, 7, 0, 16,233, 7, 16,233, 89, 9, 1, 35, 17, 51,
+ 17, 1, 51, 17, 35, 3, 98,254, 25,184,184, 1,231,184,184, 3, 41,252,215, 4, 96,252,215, 3, 41,251,160, 0,255,255, 0,195,
+ 0, 0, 4, 26, 6, 72, 16, 38, 2,130, 0, 0, 16, 6, 3,101, 0, 0, 0, 0,255,255, 0,236, 0, 0, 4,178, 4, 96, 18, 6,
+ 0,250, 0, 0, 0, 1, 0, 30, 0, 0, 4, 26, 4, 96, 0, 17, 0, 34, 64, 8, 4, 6, 1, 5, 6, 17, 11, 18, 16,212,220,236,
+212,236, 49, 0, 64, 8, 5,182, 0,194, 12,182, 11, 2, 47, 60,236,244,236, 48, 1, 33, 17, 35, 17, 33, 21, 20, 2, 6, 43, 1,
+ 53, 51, 50, 54, 18, 53, 1, 9, 3, 17,184,254, 95, 27,151,186, 55, 35, 85, 94, 21, 4, 96,251,160, 3,202,245,189,254,209,233,
+150,118, 1, 24,174, 0, 0, 0, 0, 1, 0, 61, 0, 0, 4,155, 4, 96, 0, 12, 0, 78, 64, 21, 66, 10, 7, 2, 8, 3, 0,194,
+ 9, 6, 12, 3, 7, 6, 4, 13, 1, 10, 6, 0, 13, 16,220,236, 50, 16,220,236, 50, 49, 0, 47, 60,196,236, 50, 17, 23, 57, 48,
+ 75, 83, 88, 64, 16, 8, 23, 3, 7, 23, 3, 2, 3, 9, 23, 2, 10, 23, 2, 2, 1, 4, 7, 16,237, 16, 5,237, 4, 7, 16,237,
+ 16, 5,237, 89, 19, 51, 9, 1, 51, 17, 35, 17, 1, 35, 1, 17, 35, 61,184, 1,119, 1,119,184,184,254,229,184,254,229,184, 4,
+ 96,253, 77, 2,179,251,160, 2,229,254, 31, 1,225,253, 27, 0, 0, 1, 0,195, 0, 0, 4, 26, 4, 96, 0, 11, 0, 36, 64, 18,
+ 1,182, 6, 9, 4,194, 10, 2, 0, 8, 6, 9, 1, 5, 6, 3, 70, 12, 16,252,236, 50,212,236, 50, 49, 0, 47, 60,228, 50,212,
+236, 48, 1, 33, 17, 35, 17, 51, 17, 33, 17, 51, 17, 35, 3, 98,254, 25,184,184, 1,231,184,184, 2, 3,253,253, 4, 96,254, 57,
+ 1,199,251,160,255,255, 0,137,255,227, 4, 72, 4,123, 16, 6, 0, 82, 0, 0, 0, 1, 0,195, 0, 0, 4, 26, 4, 96, 0, 7,
+ 0, 28, 64, 14, 1,182, 4,194, 6, 2, 0, 6, 5, 1, 6, 3, 70, 8, 16,252,236,212,236, 49, 0, 47, 60,244,236, 48, 1, 33,
+ 17, 35, 17, 33, 17, 35, 3, 98,254, 25,184, 3, 87,184, 3,202,252, 54, 4, 96,251,160, 0, 0,255,255, 0,190,254, 86, 4, 84,
+ 4,123, 16, 6, 0, 83, 0, 0,255,255, 0,195,255,227, 4, 37, 4,123, 16, 6, 0, 70, 0, 0, 0, 1, 0,225, 0, 0, 4, 7,
+ 4, 96, 0, 7, 0, 28, 64, 13, 0, 3,182, 5,194, 1, 7, 1, 4, 3, 6, 1, 8, 16,220,252,204, 16,204, 49, 0, 47,252,252,
+ 60, 48, 1, 17, 35, 17, 33, 53, 33, 21, 2,208,184,254,201, 3, 38, 3,202,252, 54, 3,202,150,150, 0, 0, 0,255,255, 0,104,
+254, 86, 4,129, 4, 96, 16, 6, 0, 92, 0, 0, 0, 3, 0, 99,254, 86, 4,101, 6, 20, 0, 6, 0, 24, 0, 31, 0, 99, 64, 17,
+ 29, 18, 19, 13, 10, 22, 25, 16, 6, 13, 3, 18, 10, 7, 0, 13, 32, 16,212, 60, 60,212,236, 16,252, 60, 60, 73, 59,236, 49, 0,
+ 64, 17, 25, 0,140, 16, 13,190, 26, 6,140, 22, 7,153, 24,195, 14,155, 32, 16,236,236,244, 60,236, 50,244, 60,236, 50, 48, 1,
+176, 13, 75, 84,176, 16, 75, 84, 91, 88,191, 0, 33, 0, 32,255,192, 0, 2, 0, 0, 0, 32, 0, 32, 0, 64, 56, 18, 54, 23, 56,
+ 89, 1, 14, 1, 21, 20, 22, 23, 21, 38, 2, 17, 16, 18, 55, 17, 51, 17, 22, 18, 17, 16, 2, 7, 17, 35, 19, 17, 62, 1, 53, 52,
+ 38, 2, 8,120,106,106,120,220,201,199,222,184,222,199,201,220,184,184,120,106,106, 3,214, 25,153,245,245,162, 25,156, 22, 1,
+ 11, 1, 43, 1, 43, 1, 11, 22, 1,153,254,103, 22,254,245,254,213,254,213,254,245, 22,254,115, 5,128,252,169, 25,162,245,245,
+153, 0, 0, 0,255,255, 0, 76, 0, 0, 4,133, 4, 96, 16, 6, 0, 91, 0, 0, 0, 1, 0,124,254,226, 4, 94, 4, 96, 0, 11,
+ 0, 36, 64, 18, 9, 5,194, 2, 0, 8,182, 3, 3, 6, 0, 8, 6, 10, 7, 6, 5, 12, 16,220,236,212,236,220,236, 49, 0, 47,
+236, 50,204,236, 50, 48, 37, 17, 35, 17, 33, 17, 51, 17, 33, 17, 51, 17, 4, 94,150,252,180,184, 1,230,184,150,254, 76, 1, 30,
+ 4, 96,252, 54, 3,202,252, 54, 0, 1, 0,195, 0, 0, 4, 27, 4, 98, 0, 19, 0, 33, 64, 9, 14, 9, 6, 11, 3, 6, 0, 70,
+ 20, 16,252,236,212,236, 50, 49, 0,182, 17,182, 6, 10, 1,194, 13, 47,236, 50,220,236, 48, 19, 17, 51, 17, 20, 22, 51, 50, 54,
+ 55, 17, 51, 17, 35, 17, 14, 1, 35, 34, 38,195,184,107,110, 88,114, 69,184,184, 53,140,139,140,200, 2,243, 1,111,254,145,100,
+ 93, 20, 39, 1,245,251,158, 1,210, 21, 43,163, 0, 1, 0,125, 0, 0, 4, 85, 4, 96, 0, 11, 0, 36, 64, 18, 6, 11, 2,194,
+ 8, 4,182, 1, 11, 6, 10, 8, 6, 6, 3, 6, 1, 12, 16,220,236,220,236,220,236, 49, 0, 47,236, 50,252, 60,196, 48, 41, 1,
+ 17, 51, 17, 51, 17, 51, 17, 51, 17, 51, 4, 85,252, 40,168,240,168,240,168, 4, 96,252, 54, 3,202,252, 54, 3,202, 0, 0, 0,
+ 0, 1, 0, 80,254,226, 4,184, 4, 96, 0, 15, 0, 45, 64, 13, 0, 6, 13, 11, 6, 10, 8, 6, 6, 3, 6, 1, 16, 16,220,236,
+220,236,220,252,220,236, 49, 0, 64, 9, 6, 11, 2,194, 8, 4,182, 15, 1, 47,204,236, 50,252, 60,196, 48, 41, 1, 17, 51, 17,
+ 51, 17, 51, 17, 51, 17, 51, 17, 51, 17, 35, 4, 34,252, 46,168,240,168,240,168,144,150, 4, 96,252, 54, 3,202,252, 54, 3,202,
+252, 54,254, 76, 0, 2, 0, 30, 0, 0, 4,140, 4, 96, 0, 8, 0, 21, 0, 41, 64, 9, 4, 18, 18, 14, 0, 6, 9, 11, 22, 16,
+212,220,236, 50, 47,236, 49, 0, 64, 11, 8,182, 14, 22, 10,182, 13,194, 0,182, 9, 47,236,244,236, 16,212,236, 48, 37, 51, 50,
+ 54, 53, 52, 38, 43, 1, 3, 17, 35, 53, 33, 17, 33, 50, 22, 21, 20, 6, 35, 1,206,248,124,134,137,121,248,184,248, 1,176, 1,
+ 0,209,237,232,214,156, 88, 90, 90, 90,253,254, 3,202,150,254, 59,167,168,168,164, 0, 0, 0, 0, 3, 0,104, 0, 0, 4,105,
+ 4, 96, 0, 3, 0, 12, 0, 23, 0, 43, 64, 11, 3, 6, 0, 9, 18, 21, 16, 4, 6, 13, 24, 16,212,236, 50, 47,236,220,236, 49,
+ 0, 64, 10, 12,182, 16, 4,182, 1, 14,194, 13, 0, 47, 60,228, 50,236,212,236, 48, 33, 17, 51, 17, 37, 51, 50, 54, 53, 52, 38,
+ 43, 1, 3, 17, 51, 17, 51, 50, 22, 21, 20, 6, 35, 3,177,184,252,181, 83,124,134,137,121, 83,182,182, 91,209,237,232,214, 4,
+ 96,251,160,154, 89, 91, 91, 91,253,252, 4, 96,254, 59,167,168,168,164, 0, 0, 0, 2, 0,195, 0, 0, 4, 56, 4, 96, 0, 8,
+ 0, 19, 0, 42, 64, 23, 8,182, 12, 0,182, 10,194, 9, 19, 13, 1, 7, 4, 0, 4, 18, 16, 0, 12, 6, 10, 70, 20, 16,252,236,
+ 50,220,236, 17, 23, 57, 49, 0, 47,228,236,212,236, 48, 37, 51, 50, 54, 53, 52, 38, 43, 1, 3, 17, 51, 17, 33, 50, 22, 21, 20,
+ 6, 35, 1,123,248,129,128,129,128,248,184,184, 1, 0,208,237,231,214,153, 89, 90, 94, 88,253,254, 4, 96,254, 59,167,168,168,
+164, 0, 0, 0, 0, 1, 0,195,255,227, 4, 37, 4,123, 0, 31, 0, 75, 64, 8, 10, 11, 8, 18, 25, 19, 0, 32, 16,220, 60,212,
+236, 50,196, 49, 0, 64, 22, 19,139, 18,192, 15, 0,139, 1,192, 4,140, 29, 10,182, 8, 15,140, 22,190, 29,153, 32, 16,228,244,
+236,220,238, 16,254,244,238, 16,245,238,177, 10, 15, 73,177, 4, 8, 73, 80, 88,179, 10, 8, 64, 2, 23, 56, 89, 48, 55, 53, 30,
+ 1, 51, 50, 55, 54, 55, 33, 53, 33, 38, 39, 38, 35, 34, 6, 7, 53, 62, 1, 51, 32, 0, 17, 16, 7, 6, 33, 34, 38,195, 65,152,
+ 96,172, 94, 83, 9,253,226, 2, 25, 18, 69, 94,172, 93,147, 73, 78,154, 81, 1, 4, 1, 37,147,146,254,252, 82,157, 57,191, 62,
+ 59,113,100,176,144,137, 82,112, 58, 65,193, 44, 42,254,200,254,236,254,236,156,156, 43, 0, 0, 0, 2, 0, 78,255,227, 4,144,
+ 4,123, 0, 11, 0, 30, 0, 63, 64, 35, 24, 23, 15, 14, 4, 16, 22, 3,140, 16,190, 9,140, 22,153, 28, 26,182, 12, 30,194, 28,
+ 0, 6, 19, 28, 5, 6, 25, 13, 26, 12, 6, 28, 31, 16,220,236, 50,212, 50,236, 16,212,236, 49, 0, 47,228,220,238, 16,228,238,
+244,236, 17, 18, 23, 57, 48, 1, 52, 38, 35, 34, 6, 21, 20, 22, 55, 50, 54, 1, 51, 26, 1, 51, 50, 18, 17, 16, 2, 35, 34, 2,
+ 39, 35, 17, 35, 17, 51, 3,205,112, 76, 76,113,106, 85, 85,101,253, 57,142, 17,210,157,157,223,230,154,153,211, 16,142,184,184,
+ 2, 63,198,217,244,193,193,234, 1,250, 1, 1, 1, 0, 1, 1,254,220,254,211,254,210,254,231, 1, 20,237,254, 28, 4, 96, 0,
+ 0, 2, 0,168, 0, 0, 3,216, 4, 96, 0, 8, 0, 22, 0, 66, 64, 12, 10, 20, 0, 5, 20, 8, 17, 0, 18, 13, 9, 23, 16,220,
+212,236,212,236, 50, 18, 17, 57, 49, 0, 64, 11, 66, 10, 4,182, 21, 5,182, 17,194, 19, 9, 47, 60,244,236,212,236, 57, 48, 75,
+ 83, 88,183, 21, 23, 10, 22, 23, 9, 9, 10, 7, 16, 5,237, 16,237, 89, 1, 20, 22, 59, 1, 17, 35, 34, 6, 3, 1, 46, 1, 53,
+ 52, 54, 51, 33, 17, 35, 17, 35, 1, 1,147,114, 55,228,227, 56,114,235, 1, 16, 53,170,220,150, 1,141,184,193,254,254, 3, 19,
+ 97, 85, 1,109, 86,252,140, 1,223, 22,130,167,168,154,251,160, 1,199,254, 57,255,255, 0,123,255,227, 4, 88, 6,109, 16, 38,
+ 3, 98, 0, 0, 16, 6, 0, 67,226, 7, 0, 0,255,255, 0,123,255,227, 4, 88, 5,191, 16, 38, 3, 98, 0, 0, 16, 6, 0,106,
+ 35,175, 0, 0, 0, 1, 0, 35,254, 86, 4, 84, 6, 20, 0, 31, 0, 0, 19, 53, 51, 17, 51, 17, 33, 21, 33, 17, 62, 1, 51, 50,
+ 22, 21, 16, 2, 7, 53, 54, 18, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 35,190,184, 1,192,254, 64, 49,168,124,176,182,250,237,
+121,173,106,123,138,139,184, 3,209,143, 1,180,254, 76,143,254,115, 96, 99,230,223,254,180,254,142, 46,165, 25, 1, 24, 1, 22,
+152,141,183,171,254,251, 3,209,255,255, 1, 1, 0, 0, 4, 11, 6,109, 16, 38, 3, 96, 0, 0, 16, 6, 0,118, 81, 7, 0, 0,
+ 0, 1, 0,195,255,227, 4, 37, 4,123, 0, 31, 0, 76, 64, 32, 13,139, 14,192, 17, 0,139, 31,192, 28,140, 3, 22,182, 24, 17,
+140, 10,190, 3,153, 32, 22, 0, 21, 24, 18, 13, 0, 7, 70, 32, 16,244,196, 50,252, 50, 16,196, 49, 0, 16,228,244,236,220,238,
+ 16,254,244,238, 16,245,238,177, 22, 17, 73,177, 28, 24, 73, 80, 88,179, 22, 24, 64, 2, 23, 56, 89, 48, 37, 14, 1, 35, 32, 39,
+ 38, 17, 16, 0, 33, 50, 22, 23, 21, 46, 1, 35, 34, 7, 6, 7, 37, 21, 33, 22, 23, 22, 51, 50, 54, 55, 4, 37, 74,157, 82,254,
+252,146,147, 1, 37, 1, 4, 81,154, 78, 73,147, 93,173, 93, 69, 18, 2, 25,253,226, 9, 83, 94,172, 96,152, 65, 57, 43, 43,156,
+156, 1, 20, 1, 20, 1, 56, 42, 44,193, 65, 58,112, 83,137, 1,144,176,100,113, 59, 62, 0, 0,255,255, 0,213,255,227, 4, 6,
+ 4,123, 16, 6, 0, 86, 0, 0,255,255, 0,178, 0, 0, 4, 68, 6, 20, 16, 6, 0, 76, 0, 0,255,255, 0,178, 0, 0, 4, 68,
+ 6, 16, 16, 38, 0,243, 0, 0, 17, 6, 0,106, 24, 0, 0, 8,180, 3, 16, 13, 6, 7, 43, 49,255,255, 0,186,254, 86, 3, 16,
+ 6, 20, 16, 6, 0, 77, 0, 0, 0, 2, 0, 10, 0, 0, 4,203, 4, 96, 0, 5, 0, 30, 0, 0, 37, 50, 16, 43, 1, 17, 23, 35,
+ 17, 35, 21, 20, 2, 7, 6, 43, 1, 53, 51, 50, 54, 18, 53, 17, 33, 17, 51, 50, 22, 16, 6, 3, 55,208,208, 13, 21,189,229, 27,
+ 82, 67,188, 39, 35, 85, 94, 21, 2, 53, 21,159,237,232,153, 1,105,254,151,153, 3,202,245,189,254,209,128,105,150,118, 1, 24,
+174, 1,142,254, 59,167,254,176,164, 0, 0, 0, 0, 2, 0, 65, 0, 0, 4,158, 4, 96, 0, 6, 0, 24, 0, 0, 37, 50, 53, 52,
+ 43, 1, 25, 1, 51, 50, 22, 16, 6, 43, 1, 17, 33, 17, 35, 17, 51, 17, 33, 17, 51, 3, 10,208,208, 13, 21,159,237,232,164,189,
+254,148,168,168, 1,108,168,153,181,180,254,151, 2, 2,167,254,176,164, 2, 3,253,253, 4, 96,254, 57, 1,199, 0, 1, 0, 35,
+ 0, 0, 4, 57, 6, 20, 0, 27, 0, 0, 19, 53, 51, 17, 51, 17, 33, 21, 33, 17, 62, 1, 51, 50, 22, 21, 17, 35, 17, 52, 38, 35,
+ 34, 6, 21, 17, 35, 17, 35,190,184, 1,192,254, 64, 49,168,115,171,169,185,106,113,129,139,184, 3,209,143, 1,180,254, 76,143,
+254,115, 96, 99,225,228,254,190, 1, 66,151,142,183,171,254,251, 3,209, 0, 0,255,255, 0,236, 0, 0, 4,178, 6,109, 16, 38,
+ 3,103, 0, 0, 16, 6, 0,118, 48, 7, 0, 0,255,255, 0,195, 0, 0, 4, 26, 6,109, 16, 38, 3,101, 0, 0, 16, 6, 0, 67,
+ 64, 7, 0, 0,255,255, 0,104,254, 86, 4,129, 6, 72, 16, 38, 2,130, 0, 0, 16, 6, 3,112, 0, 0, 0, 0, 0, 1, 0,195,
+254,226, 4, 26, 4, 96, 0, 11, 0, 0, 51, 17, 51, 17, 33, 17, 51, 17, 33, 17, 35, 17,195,184, 1,231,184,254,160,151, 4, 96,
+252, 54, 3,202,251,160,254,226, 1, 30, 0, 0, 0, 1, 0,215, 0, 0, 4,115, 7, 7, 0, 7, 0, 28, 64, 14, 3, 5,151, 1,
+136, 7, 3, 4, 49, 6, 30, 1, 52, 8, 16,252,236,252,204, 49, 0, 47,244,236,204, 48, 51, 17, 33, 19, 51, 17, 33, 17,215, 2,
+242, 3,167,253, 47, 5,213, 1, 50,254, 36,250,213, 0, 0, 0, 0, 1, 1, 1, 0, 0, 3,242, 5,154, 0, 7, 0, 26, 64, 12,
+ 5, 0,182, 3,194, 1, 4, 7, 0, 6, 2, 8, 16,220,236,220,204, 49, 0, 47,252,236,204, 48, 1, 17, 35, 17, 33, 17, 51, 3,
+ 1,185,184, 2, 56,185, 1, 3,168,252, 88, 4, 96, 1, 58,254, 14, 0, 0, 0, 0, 1, 0, 85, 0, 0, 4,115, 5,213, 0, 13,
+ 0, 0, 19, 51, 17, 33, 21, 33, 17, 33, 21, 33, 17, 35, 17, 35, 85,130, 3,156,253, 47, 2, 35,253,221,203,130, 3,232, 1,237,
+170,254,189,170,252,194, 3, 62, 0, 1, 0,127, 0, 0, 3,241, 4, 96, 0, 13, 0, 0, 33, 17, 35, 53, 51, 17, 33, 21, 33, 17,
+ 33, 21, 33, 17, 1, 1,130,130, 2,240,253,200, 1,160,254, 96, 1,244,170, 1,194,184,254,246,170,254, 12, 0, 0, 1, 0,215,
+254,102, 4,115, 5,213, 0, 28, 0, 0, 1, 17, 35, 17, 33, 21, 33, 17, 33, 50, 23, 22, 21, 17, 16, 7, 6, 43, 1, 53, 51, 50,
+ 55, 54, 53, 17, 52, 38, 35, 1,162,203, 3,156,253, 47, 1, 55,186,113,111,104,102,228, 76, 62,134, 56, 55,124,124, 2,199,253,
+ 57, 5,213,170,254, 70,119,114,238,254,206,254,244,124,122,170, 75, 75,194, 1, 34,159,158, 0, 0, 1, 1, 1,254, 86, 4, 82,
+ 4, 96, 0, 29, 0, 0, 1, 17, 35, 17, 33, 21, 33, 17, 51, 32, 23, 22, 21, 17, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 53, 17,
+ 52, 39, 38, 35, 1,185,184, 2,240,253,200,250, 1, 5, 72, 82, 82, 81,181,193,172,110, 33, 38, 38, 49,134, 1,231,254, 25, 4,
+ 96,184,254,207, 71, 81,229,254,242,214, 96, 96,156, 48, 55,147, 1, 8,170, 32, 41, 0, 0, 0, 0, 1, 0, 15,254,190, 4,194,
+ 5,213, 0, 23, 0, 0, 51, 9, 1, 51, 1, 17, 51, 17, 1, 51, 1, 19, 51, 17, 35, 17, 35, 3, 7, 17, 35, 17, 39, 3, 15, 1,
+ 48,254,225,207, 1, 28,187, 1, 28,207,254,225,246, 58,170, 27,222, 89,187, 89,222, 3,123, 2, 90,253,173, 2, 83,253,173, 2,
+ 83,253,166,253, 47,254, 20, 1, 66, 2,138,186,254, 48, 1,208,186,253,118, 0, 0, 1, 0, 59,254,226, 4,174, 4, 96, 0, 23,
+ 0, 0, 51, 1, 3, 51, 1, 17, 51, 17, 1, 51, 3, 19, 51, 17, 35, 17, 35, 3, 7, 17, 35, 17, 39, 3, 59, 1, 3,239,199, 0,
+255,168, 0,255,199,239,205, 77,150, 52,191,104,168,104,191, 2,204, 1,148,254, 80, 1,176,254, 80, 1,176,254,108,253,202,254,
+ 76, 1, 30, 2, 16,177,254,161, 1, 95,177,253,240, 0, 0, 0,255,255, 0,137,254,117, 4, 55, 5,240, 16, 38, 2,163,183, 0,
+ 16, 6, 3, 68, 0, 0, 0, 0,255,255, 0,169,254,117, 4, 40, 4,123, 16, 38, 2,163,189, 0, 16, 6, 3,100, 0, 0, 0, 0,
+ 0, 1, 0,137,254,190, 4,201, 5,213, 0, 15, 0, 0, 37, 51, 17, 35, 17, 35, 1, 7, 17, 35, 17, 51, 17, 1, 51, 1, 4, 86,
+114,212, 31,254, 25,154,203,203, 2,119,237,253,187,170,254, 20, 1, 66, 2,236,164,253,184, 5,213,253,104, 2,152,253,158, 0,
+ 0, 1, 0,236,254,226, 4,178, 4, 96, 0, 15, 0, 0, 37, 51, 17, 35, 17, 35, 1, 7, 17, 35, 17, 51, 17, 1, 51, 1, 4, 44,
+134,196, 29,254, 98,137,190,190, 1,227,224,254, 71,184,254, 42, 1, 30, 2, 66,129,254, 63, 4, 96,254, 47, 1,209,254, 90, 0,
+ 0, 1, 0, 31,254,190, 4,179, 5,213, 0, 15, 0, 0, 37, 51, 17, 35, 17, 35, 17, 33, 17, 35, 17, 51, 17, 33, 17, 51, 3,222,
+213,213,203,253,215,203,203, 2, 41,203,170,254, 20, 1, 66, 2,199,253, 57, 5,213,253,156, 2,100, 0, 0, 0, 0, 1, 0, 98,
+254,226, 4,124, 4, 96, 0, 15, 0, 0, 37, 51, 17, 35, 17, 35, 17, 33, 17, 35, 17, 51, 17, 33, 17, 51, 3,185,195,195,184,254,
+ 25,184,184, 1,231,184,184,254, 42, 1, 30, 1,249,254, 7, 4, 96,254, 67, 1,189, 0, 0, 0,255,255, 0,139,254,117, 4, 49,
+ 5,240, 16, 38, 2,163,100, 0, 16, 6, 3, 78, 0, 0, 0, 0,255,255, 0,195,254,117, 4, 37, 4,123, 16, 38, 2,163,104, 0,
+ 16, 6, 3,110, 0, 0, 0, 0, 0, 1, 0, 47,254,190, 4,162, 5,213, 0, 11, 0, 0, 37, 51, 17, 35, 17, 35, 17, 33, 53, 33,
+ 21, 33, 2,207,213,213,203,254, 43, 4,115,254, 45,170,254, 20, 1, 66, 5, 43,170,170, 0, 0, 0, 1, 0,225,254,226, 4, 7,
+ 4, 96, 0, 11, 0, 0, 37, 51, 17, 35, 17, 35, 17, 33, 53, 33, 21, 33, 2,208,195,195,184,254,201, 3, 38,254,201,184,254, 42,
+ 1, 30, 3,174,178,178, 0, 0,255,255, 0, 37, 0, 0, 4,172, 5,213, 16, 6, 0, 60, 0, 0, 0, 1, 0, 92,254, 86, 4,116,
+ 4, 96, 0, 8, 0, 0, 19, 51, 9, 1, 51, 1, 17, 35, 17, 92,195, 1, 73, 1, 73,195,254, 84,192, 4, 96,252,148, 3,108,251,
+178,254, 68, 1,188, 0, 0, 0, 0, 1, 0, 37, 0, 0, 4,172, 5,213, 0, 16, 0, 0, 19, 51, 9, 1, 51, 1, 21, 33, 21, 33,
+ 17, 35, 17, 33, 53, 33, 53, 37,215, 1,108, 1,107,217,254, 33, 1, 10,254,246,203,254,248, 1, 8, 5,213,253,109, 2,147,252,
+201, 80,170,254, 92, 1,164,170, 80, 0, 0, 0, 0, 1, 0, 92,254, 86, 4,116, 4, 96, 0, 16, 0, 0, 19, 51, 9, 1, 51, 1,
+ 21, 51, 21, 35, 21, 35, 53, 35, 53, 51, 53, 92,195, 1, 73, 1, 73,195,254, 84,200,200,192,200,200, 4, 96,252,148, 3,108,251,
+178, 53,150,241,241,150, 53, 0, 0, 1, 0, 18,254,190, 4,191, 5,213, 0, 15, 0, 0, 37, 51, 17, 35, 17, 35, 9, 1, 35, 9,
+ 1, 51, 9, 1, 51, 1, 4, 88,102,212, 5,254,146,254,117,218, 1,244,254, 80,217, 1, 72, 1, 78,217,254, 65,170,254, 20, 1,
+ 66, 2,131,253,125, 3, 23, 2,190,253,205, 2, 51,253, 66, 0, 0, 1, 0, 76,254,226, 4,134, 4, 96, 0, 15, 0, 0, 37, 51,
+ 17, 35, 17, 35, 9, 1, 35, 9, 1, 51, 9, 1, 51, 1, 3,250,140,196, 18,254,184,254,185,213, 1,184,254,111,204, 1, 41, 1,
+ 39,207,254,111,184,254, 42, 1, 30, 1,193,254, 63, 2, 72, 2, 24,254,107, 1,149,253,232, 0, 0, 1, 0,140, 0, 0, 4, 71,
+ 5,215, 0, 28, 0, 0, 1, 17, 35, 17, 52, 38, 35, 34, 7, 6, 7, 6, 21, 17, 35, 17, 51, 17, 54, 63, 1, 54, 63, 1, 50, 23,
+ 22, 23, 22, 4, 71,203,106,113,106, 87, 46, 22, 69,203,203, 35, 50, 48, 64,149, 48,160, 88, 14, 11, 85, 1,244,254, 12, 1,218,
+151,142, 42, 21, 28, 92,171,254, 99, 5,215,253, 85, 39, 27, 26, 37, 10, 2, 84, 13, 16,112, 0,255,255, 0,195, 0, 0, 4, 27,
+ 6, 20, 16, 6, 0, 75, 0, 0,255,255, 0,201, 0, 0, 4, 6, 5,213, 16, 6, 0, 44, 0, 0,255,255, 0, 15, 0, 0, 4,194,
+ 7,109, 16, 38, 11,184, 0, 0, 16, 6, 3, 67, 0, 0, 0, 0,255,255, 0, 59, 0, 0, 4,151, 6, 72, 16, 38, 2,130, 0, 0,
+ 16, 6, 3, 99, 0, 0, 0, 0, 0, 1, 0,137,254,102, 4,184, 5,213, 0, 30, 0, 0, 1, 51, 50, 23, 22, 21, 17, 16, 7, 6,
+ 43, 1, 53, 51, 50, 55, 54, 53, 17, 52, 38, 43, 1, 7, 17, 35, 17, 51, 17, 1, 51, 2,115, 24,183,116,111,104,102,228, 76, 62,
+134, 56, 55,124,124,151,119,203,203, 2,119,237, 3,113,119,114,238,254,206,254,244,124,122,170, 75, 75,194, 1, 34,159,158,127,
+253,184, 5,213,253,104, 2,152, 0, 1, 0,236,254, 86, 4,109, 4, 96, 0, 31, 0, 0, 1, 51, 32, 23, 22, 21, 17, 20, 7, 6,
+ 43, 1, 53, 51, 50, 55, 54, 53, 17, 52, 39, 38, 43, 1, 7, 17, 35, 17, 51, 17, 1, 51, 2,106, 58, 1, 5, 72, 82, 82, 81,181,
+193,172,110, 33, 38, 38, 49,134,221, 39,190,190, 1,227,224, 2,119, 71, 81,229,254,242,214, 96, 96,156, 48, 55,147, 1, 8,170,
+ 32, 41, 38,254, 63, 4, 96,254, 47, 1,209, 0, 0, 1, 0,137,254,102, 4, 72, 5,213, 0, 21, 0, 0, 37, 16, 7, 6, 43, 1,
+ 53, 51, 50, 55, 54, 53, 17, 33, 17, 35, 17, 51, 17, 33, 17, 51, 4, 72,104,103,227, 76, 62,134, 56, 55,253,215,203,203, 2, 41,
+203,104,254,242,122,122,170, 75, 75,194, 2, 95,253, 57, 5,213,253,156, 2,100, 0, 1, 0,195,254, 86, 4, 26, 4, 96, 0, 21,
+ 0, 0, 5, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 53, 17, 33, 17, 35, 17, 51, 17, 33, 17, 51, 4, 26, 82, 81,181,193,172,110,
+ 33, 38,254, 25,184,184, 1,231,184, 20,214, 96, 96,156, 48, 55,147, 2, 13,254, 7, 4, 96,254, 67, 1,189, 0, 0, 1, 0,140,
+254,190, 4, 71, 5,215, 0, 32, 0, 0, 37, 17, 6, 15, 1, 6, 15, 1, 34, 39, 38, 39, 38, 53, 17, 51, 17, 20, 22, 51, 50, 55,
+ 54, 55, 54, 53, 17, 51, 17, 35, 17, 35, 17, 3,124, 35, 51, 47, 64,149, 48,160, 88, 14, 12, 84,203,106,113,106, 87, 46, 21, 70,
+203,203,213,170, 2, 36, 39, 27, 26, 37, 10, 2, 84, 13, 16,112,228, 1,209,254, 73,151,142, 42, 21, 28, 92,171, 1,122,250, 41,
+254,190, 1,236, 0, 1, 0,195,254,226, 4, 27, 4, 98, 0, 26, 0, 0, 37, 17, 6, 7, 54, 7, 6, 35, 34, 38, 53, 17, 51, 17,
+ 20, 22, 51, 50, 54, 61, 1, 51, 17, 35, 17, 35, 17, 3, 99, 27, 60, 3, 49, 84,115,171,169,185,106,113,129,139,184,184,195,184,
+ 1,126, 51, 36, 1, 28, 50,225,228, 1, 11,254,245,151,142,183,171,206,251,158,254,226, 1,214, 0, 1, 1,199, 0, 0, 2,127,
+ 6, 31, 0, 3, 0, 0, 1, 17, 35, 17, 2,127,184, 6, 31,249,225, 6, 31, 0,255,255, 0, 37, 0, 0, 4,172, 7,109, 16, 38,
+ 11,184, 0, 0, 17, 6, 3, 61, 0, 0, 0, 24,180, 19, 8, 0, 24, 7, 43, 64, 13, 95, 8, 80, 0, 79, 8, 64, 0, 47, 8, 32,
+ 0, 6, 93, 49,255,255, 0,133,255,227, 4, 35, 6, 72, 16, 38, 2,130, 0, 0, 16, 6, 3, 93, 0, 0, 0, 0,255,255, 0, 37,
+ 0, 0, 4,172, 7, 78, 16, 38, 3, 61, 0, 0, 17, 7, 11,176, 0, 0, 1,117, 0, 28,180, 5, 17, 14, 10, 7, 43, 64, 17,112,
+ 14,127, 17, 48, 14, 63, 17, 32, 14, 47, 17, 0, 14, 15, 17, 8, 93, 49, 0, 0,255,255, 0,133,255,227, 4, 35, 6, 16, 16, 38,
+ 0,106, 0, 0, 16, 6, 3, 93, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 4,156, 5,213, 16, 6, 0,136, 0, 0,255,255, 0, 41,
+255,227, 4,176, 4,123, 16, 6, 0,168, 0, 0,255,255, 0,197, 0, 0, 4, 78, 7,109, 16, 38, 11,184, 18, 0, 16, 6, 3, 66,
+ 0, 0, 0, 0,255,255, 0,123,255,227, 4, 88, 6, 72, 16, 38, 2,130, 14, 0, 16, 6, 3, 98, 0, 0, 0, 0,255,255, 0,117,
+255,227, 4, 92, 5,240, 18, 6, 1, 81, 0, 0,255,255, 0,122,255,227, 4, 87, 4,123, 18, 6, 1,247, 0, 0,255,255, 0,117,
+255,227, 4, 92, 7, 78, 16, 39, 11,176, 0, 0, 1,117, 16, 6, 3,185, 0, 0,255,255, 0,122,255,227, 4, 87, 6, 16, 16, 38,
+ 0,106, 0, 0, 16, 6, 3,186, 0, 0, 0, 0,255,255, 0, 15, 0, 0, 4,194, 7, 78, 16, 39, 11,176, 0, 0, 1,117, 16, 6,
+ 3, 67, 0, 0,255,255, 0, 59, 0, 0, 4,151, 6, 16, 16, 38, 0,106, 0, 0, 16, 6, 3, 99, 0, 0, 0, 0,255,255, 0,137,
+255,227, 4, 55, 7, 78, 16, 39, 11,176,255,239, 1,117, 16, 6, 3, 68, 0, 0,255,255, 0,169,255,234, 4, 40, 6, 16, 16, 38,
+ 0,106,241, 0, 16, 6, 3,100, 0, 0, 0, 0,255,255, 0, 26,255,228, 4,183, 5,213, 16, 6, 1,121, 0, 0,255,255, 0,125,
+254, 76, 4, 84, 4, 96, 16, 6, 2, 48, 0, 0,255,255, 0,139, 0, 0, 4, 70, 7, 48, 16, 38, 11,189, 0, 0, 16, 6, 3, 69,
+ 0, 0, 0, 0,255,255, 0,195, 0, 0, 4, 26, 5,246, 16, 38, 2,128, 0, 0, 16, 6, 3,101, 0, 0, 0, 0,255,255, 0,139,
+ 0, 0, 4, 70, 7, 78, 16, 39, 11,176, 0, 0, 1,117, 16, 6, 3, 69, 0, 0,255,255, 0,195, 0, 0, 4, 26, 6, 16, 16, 38,
+ 0,106, 0, 0, 16, 6, 3,101, 0, 0, 0, 0,255,255, 0,117,255,227, 4, 92, 7, 78, 16, 38, 3, 75, 0, 0, 17, 7, 11,176,
+ 0, 0, 1,117, 0, 28,180, 12, 30, 27, 18, 7, 43, 64, 17,112, 27,127, 30, 48, 27, 63, 30, 32, 27, 47, 30, 0, 27, 15, 30, 8,
+ 93, 49, 0, 0,255,255, 0,137,255,227, 4, 72, 6, 16, 16, 38, 3,107, 0, 0, 17, 6, 0,106, 0, 0, 0, 20,180, 15, 30, 27,
+ 21, 7, 43, 64, 9,127, 30,112, 27, 79, 30, 64, 27, 4, 93, 49,255,255, 0,117,255,227, 4, 92, 5,240, 16, 6, 3, 33, 0, 0,
+255,255, 0,137,255,227, 4, 72, 4,123, 16, 6, 2, 19, 0, 0,255,255, 0,117,255,227, 4, 92, 7, 78, 16, 39, 11,176, 0, 0,
+ 1,117, 16, 6, 3,201, 0, 0,255,255, 0,137,255,227, 4, 72, 6, 16, 16, 38, 0,106, 0, 0, 16, 6, 3,202, 0, 0, 0, 0,
+255,255, 0,139,255,227, 4, 49, 7, 78, 16, 39, 11,176,255,223, 1,117, 16, 6, 3, 90, 0, 0,255,255, 0,195,255,227, 4, 37,
+ 6, 16, 16, 38, 0,106,236, 0, 16, 6, 3,122, 0, 0, 0, 0,255,255, 0,104, 0, 0, 4,129, 7, 48, 16, 38, 11,189, 0, 0,
+ 16, 6, 3, 80, 0, 0, 0, 0,255,255, 0,104,254, 86, 4,129, 5,246, 16, 38, 2,128, 0, 0, 16, 6, 3,112, 0, 0, 0, 0,
+255,255, 0,104, 0, 0, 4,129, 7, 78, 16, 39, 11,176, 0, 0, 1,117, 16, 6, 3, 80, 0, 0,255,255, 0,104,254, 86, 4,129,
+ 6, 16, 16, 38, 0,106, 0, 0, 16, 6, 3,112, 0, 0, 0, 0,255,255, 0,104, 0, 0, 4,129, 7,107, 16, 38, 11,186, 0, 0,
+ 16, 6, 3, 80, 0, 0, 0, 0,255,255, 0,104,254, 86, 4,129, 6,102, 16, 38, 2,135, 0, 0, 16, 6, 3,112, 0, 0, 0, 0,
+255,255, 0,137, 0, 0, 4, 68, 7, 78, 16, 39, 11,176, 0, 0, 1,117, 16, 6, 3, 84, 0, 0,255,255, 0,195, 0, 0, 4, 27,
+ 6, 16, 16, 38, 0,106, 0, 0, 16, 6, 3,116, 0, 0, 0, 0, 0, 1, 0,215,254,190, 4,115, 5,213, 0, 9, 0, 0, 37, 51,
+ 17, 35, 17, 35, 17, 33, 21, 33, 1,162,213,213,203, 3,156,253, 47,170,254, 20, 1, 66, 5,213,170, 0, 0, 0, 0, 1, 1, 1,
+254,226, 3,241, 4, 96, 0, 9, 0, 0, 37, 51, 17, 35, 17, 35, 17, 33, 21, 33, 1,185,195,195,184, 2,240,253,200,184,254, 42,
+ 1, 30, 4, 96,184, 0, 0, 0,255,255, 0, 65, 0, 0, 4,110, 7, 78, 16, 39, 11,176, 0, 0, 1,117, 16, 6, 3, 88, 0, 0,
+255,255, 0,104, 0, 0, 4,105, 6, 16, 16, 38, 0,106, 0, 0, 16, 6, 3,120, 0, 0, 0, 0, 0, 1, 1,214, 0, 0, 2,251,
+ 1,236, 0, 5, 0, 0, 33, 35, 53, 19, 51, 3, 2,169,211,164,129, 82,172, 1, 64,254,192, 0, 0, 2, 1,100, 4,253, 3,109,
+ 6,241, 0, 10, 0, 27, 0, 0, 1, 51, 50, 55, 54, 53, 52, 39, 6, 7, 6, 23, 43, 1, 53, 51, 17, 51, 17, 54, 55, 54, 23, 22,
+ 21, 20, 7, 6, 2, 53, 55, 77, 23, 53, 30, 15, 57, 51, 23,175,112, 81,102, 36,104, 63, 70, 65, 64, 54, 5, 98, 13, 33, 21, 31,
+ 16, 4, 22, 20,169,101, 1,143,254,191, 73, 40, 24, 26, 25, 82, 91, 50, 42, 0, 0, 2, 1,214, 0, 0, 2,251, 5, 17, 0, 5,
+ 0, 9, 0, 0, 1, 35, 53, 19, 51, 11, 1, 51, 21, 35, 2,169,211,164,129, 82,211,211,211, 3, 37,172, 1, 64,254,192,253, 45,
+254, 0, 0, 0, 0, 2, 0,218, 0, 0, 3,247, 5,240, 0, 3, 0, 36, 0, 0, 37, 21, 35, 53, 55, 53, 52, 38, 39, 46, 1, 47,
+ 1, 46, 1, 53, 52, 54, 51, 50, 22, 23, 21, 46, 1, 35, 34, 6, 21, 20, 22, 31, 1, 30, 1, 29, 1, 3, 3,203, 6, 6, 6, 8,
+ 39, 47, 88, 90, 72,223,184,103,193, 94, 97,179, 79,108,131, 51, 57, 90, 90, 56,254,254,254,147,123, 52, 60, 21, 25, 53, 47, 86,
+ 86,137, 76,159,194, 56, 57,188, 67, 70,110, 89, 49, 94, 53, 89, 86,130,101,154, 0, 1, 1,178, 0, 85, 4, 45, 3,222, 0, 34,
+ 0, 0, 37, 53, 54, 55, 54, 55, 38, 39, 38, 53, 52, 55, 54, 55, 54, 51, 50, 23, 21, 38, 7, 6, 7, 6, 23, 20, 23, 22, 55, 54,
+ 55, 21, 6, 7, 6, 1,178, 47, 83, 68, 52,142, 51, 53, 21, 30,103, 99, 98,110, 90,100, 70, 51, 49, 96, 1,200, 57, 58, 72, 58,
+ 90,205,231, 85,176, 6, 25, 20, 33, 24, 76, 79, 84, 65, 75,118, 63, 61, 22,185, 31, 2, 1, 26, 48,112,115, 50, 14, 15, 19, 35,
+185, 60, 80, 90,255,255, 1, 0, 0, 0, 3,208, 7,131, 16, 38, 3,229, 0, 0, 16, 7, 4, 12, 0, 0, 1,194,255,255, 1,189,
+ 0, 0, 3, 20, 7,254, 16, 38, 3,229, 0, 0, 16, 7, 4, 13, 0, 0, 1,134,255,255, 0, 76,254, 12, 4, 51, 4,182, 16, 38,
+ 4, 1, 0, 0, 16, 7, 4, 13, 0, 99,254, 62,255,255, 1,189,254, 12, 3, 20, 6, 20, 16, 38, 3,229, 0, 0, 16, 6, 4, 14,
+ 0, 0, 0, 0,255,255, 0, 25,254,243, 4,209, 4, 92, 16, 38, 4, 2, 0, 0, 16, 7, 4, 13,255,114,253,228, 0, 1, 2, 12,
+ 0, 0, 2,196, 6, 20, 0, 3, 0, 0, 1, 51, 17, 35, 2, 12,184,184, 6, 20,249,236, 0, 0,255,255, 0, 69,254,200, 4,176,
+ 2, 27, 16, 39, 11,195, 2, 44,254,200, 16, 6, 4, 30, 0, 0,255,255, 0,222,255,198, 3,243, 4, 26, 16, 39, 11,196, 1,113,
+ 3,132, 16, 6, 4, 0, 0, 0,255,255, 0, 69,255,235, 4,176, 3, 32, 16, 39, 11,196, 1,184, 2,138, 16, 6, 4, 30, 0, 0,
+255,255, 0, 69,255,235, 4,176, 4, 26, 16, 39, 11,197, 1,164, 2,138, 16, 6, 4, 30, 0, 0,255,255, 0, 88,254, 11, 4,173,
+ 3,103, 16, 39, 11,195, 2,151, 0, 13, 16, 6, 3,235, 0, 0, 0, 1, 0, 88,254, 11, 4,173, 3,103, 0, 30, 0, 0, 19, 36,
+ 23, 4, 23, 21, 36, 7, 6, 21, 20, 23, 22, 5, 50, 55, 21, 6, 7, 4, 39, 38, 53, 16, 55, 54, 55, 38, 7, 6, 7, 88, 1, 20,
+195, 1, 36,196,254,218,215,224, 74,129, 1, 19,193,212,150,250,254,148,169,131,212, 96,137,101,159,135, 95, 3, 39, 64, 1, 1,
+ 53,154, 13,180,188,247,137, 94,163, 1,118,184, 98, 1, 2,196,152,222, 1, 2,223,101, 52, 3, 22, 19, 41, 0,255,255, 0, 88,
+254, 11, 4,173, 4,176, 16, 39, 11,195, 1,202, 4, 26, 16, 6, 3,235, 0, 0, 0, 1, 0,232,255,218, 3,232, 3,106, 0, 25,
+ 0, 0, 37, 54, 55, 54, 53, 52, 39, 38, 39, 51, 22, 23, 22, 21, 20, 7, 6, 5, 6, 35, 34, 39, 53, 22, 51, 50, 2, 84,174, 33,
+ 8, 60, 73,166,227,107, 72, 82, 32, 80,254,250, 46, 94,151,103,115,133, 82,151, 50,111, 27, 42, 91,103,120,179,108,131,152,105,
+ 99, 75,195, 40, 7, 38,184, 42,255,255, 0,232,255,218, 3,232, 4,200, 16, 39, 11,195, 2, 28, 4, 50, 16, 6, 3,237, 0, 0,
+ 0, 1,255,204,254, 8, 4, 68, 2, 34, 0, 17, 0, 0, 37, 54, 53, 52, 39, 51, 22, 21, 20, 7, 2, 5, 4, 5, 53, 32, 55, 36,
+ 3,133, 10, 53,184, 50, 8, 41,254,181,254,239,254, 21, 1,188,220, 0,255,154, 58, 72,126,136,118,132, 82, 62,254,181,173,143,
+ 9,184,128,146,255,255,255,204,254, 8, 4, 68, 3,182, 16, 39, 11,195, 3, 85, 3, 32, 16, 6, 3,239, 0, 0, 0, 1,255, 33,
+254, 20, 4,152, 2,238, 0, 63, 0, 0, 37, 6, 7, 6, 7, 6, 35, 34, 39, 38, 55, 54, 55, 51, 6, 23, 22, 23, 22, 51, 50, 55,
+ 54, 55, 54, 39, 52, 47, 1, 51, 23, 22, 23, 22, 23, 22, 55, 54, 53, 51, 6, 23, 22, 51, 50, 25, 1, 51, 17, 20, 7, 6, 7, 6,
+ 35, 34, 39, 38, 39, 6, 7, 6, 7, 6, 1,140, 9, 29, 38, 60, 71,114, 95,101,117, 18, 19, 61,164, 88, 6, 7, 33, 47, 47, 54,
+ 50, 34, 26, 24, 2, 16, 42,160, 18, 16, 22, 48, 40, 46, 46, 36,164, 4, 38, 31, 43,104,164, 62, 33, 85, 22, 78, 66, 24, 65, 25,
+ 31, 69, 51, 73, 48, 60,168, 94,121, 77, 92,100,115,213,232,130,225,137,172, 43, 59, 72, 50,122,109,165, 94, 92,234,156,145, 35,
+ 80, 3, 3,125,103,194,163,141,120, 1, 24, 1, 38,254,170,159,153, 82, 34, 9, 25, 67,126,109, 56, 40, 2, 2,255,255,255, 33,
+254, 20, 4,152, 4,176, 16, 39, 11,197, 1, 99, 3, 32, 16, 6, 3,241, 0, 0, 0, 2,255, 16,254, 20, 4,192, 2,143, 0, 12,
+ 0, 61, 0, 0, 37, 51, 50, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 7, 54, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 43, 1, 34,
+ 39, 38, 53, 20, 7, 6, 7, 6, 35, 34, 39, 38, 53, 52, 55, 51, 6, 21, 20, 23, 22, 55, 54, 55, 54, 53, 52, 39, 38, 39, 51, 20,
+ 23, 22, 2, 72,128,141, 73,106, 40, 36, 64, 71,103, 76,196, 75, 49,142,154,172, 90, 88,184,127,127,218, 37, 53, 44, 48, 46, 51,
+ 99, 77,130, 91,124,100,172,104, 60, 50, 61, 66, 37, 65, 9, 33, 13,170, 14, 10,184, 46, 68, 70, 45, 37, 33,109, 78, 6,128, 60,
+177, 82, 78,121,190,109, 75, 30, 26, 16,175,131,129, 43, 86, 90,127,203,188,172,204,156,145, 50, 41, 3, 4, 59,106,136,104, 62,
+212, 72, 15, 55, 40, 0, 0, 0,255,255,255, 16,254, 20, 4,192, 3, 77, 16, 39, 11,195, 1, 79, 2,183, 16, 6, 3,243, 0, 0,
+ 0, 2, 0, 10, 0, 0, 4,164, 6, 20, 0, 12, 0, 31, 0, 0, 37, 51, 50, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 19, 33, 35,
+ 53, 51, 17, 51, 17, 54, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 2, 44,129,140, 73,106, 40, 36, 63, 71,104, 75,136,253,251,224,
+224,184, 76, 49,142,154,171, 91, 87,184,126,184, 46, 68, 70, 45, 37, 33,109, 78,254,216,184, 5, 92,251, 14,128, 60,177, 82, 78,
+121,190,109, 75,255,255, 0, 10, 0, 0, 4,164, 6, 20, 16, 39, 11,195, 2, 89, 3, 22, 16, 6, 3,245, 0, 0, 0, 1, 0,122,
+254, 12, 4,183, 4, 42, 0, 42, 0, 0, 5, 22, 33, 50, 55, 21, 6, 35, 32, 39, 38, 53, 52, 55, 54, 55, 38, 39, 38, 53, 52, 55,
+ 54, 51, 21, 34, 7, 6, 21, 20, 23, 22, 51, 50, 55, 54, 55, 21, 4, 7, 6, 21, 20, 1, 88,119, 1, 83,193,212,150,250,254, 91,
+166, 98, 87,113, 77, 51, 47, 88,204,124,252,195,116, 93, 48, 45, 46, 40, 41,158,254,254,239,236,209,177,158,118,184, 99,188,111,
+201,177,101,131, 25, 4, 30, 56,130,208,127, 77,169, 65, 52,104, 75, 25, 24, 18, 69, 29,184, 26,149,131,185,117,255,255, 0,122,
+254, 12, 4,183, 5, 70, 16, 39, 11,195, 1,125, 4,176, 16, 6, 3,247, 0, 0, 0, 1,255,236, 0, 0, 4,229, 0,184, 0, 3,
+ 0, 0, 35, 53, 33, 21, 20, 4,249,184,184, 0,255,255,255,181,255,164, 4,140, 4,204, 16, 39, 11,195, 2,252, 4, 54, 16, 6,
+ 4, 51, 0, 0,255,255, 0, 31,254,124, 4,116, 5, 20, 16, 39, 11,196, 2, 83, 4,126, 16, 6, 4, 31, 0, 0, 0, 2, 0, 8,
+255,200, 4,159, 6, 20, 0, 33, 0, 61, 0, 0, 1, 21, 6, 7, 6, 21, 20, 23, 22, 23, 22, 21, 20, 7, 6, 35, 34, 39, 53, 22,
+ 51, 50, 55, 54, 53, 52, 39, 38, 39, 38, 55, 54, 55, 54, 1, 54, 25, 1, 51, 17, 16, 7, 6, 7, 6, 35, 6, 39, 38, 53, 52, 55,
+ 51, 6, 21, 22, 23, 22, 51, 50, 55, 54, 2,123, 74, 38, 80, 14, 12, 68,102, 88, 82, 78, 66, 56, 68, 45, 60, 57, 60, 78, 74, 18,
+ 32, 1, 2, 75, 85, 1,171, 52,184, 86,130, 67,155,184,173,163,217, 16,184, 14, 2,152,121, 87,127, 62,119, 4, 76, 82, 4, 14,
+ 30, 33, 28, 18, 16, 10, 15, 88,110, 42, 39, 11, 88, 10, 26, 26, 30, 38, 17, 16, 28, 47, 46, 81, 38, 43,252,209, 56, 1, 18, 3,
+177,252, 79,254,154, 92,136, 25, 55, 2, 57, 76,184, 75, 53, 58, 44, 93, 45, 35, 27, 52, 0, 0, 0, 1, 0, 66,254,200, 4, 75,
+ 6, 20, 0, 27, 0, 0, 37, 54, 25, 1, 51, 17, 16, 7, 6, 7, 6, 35, 34, 39, 38, 3, 38, 55, 51, 6, 21, 20, 23, 22, 51, 50,
+ 55, 54, 3,117, 30,184, 50,108,101,150,162, 99,119,242, 1, 1, 64,184, 65,166, 40, 73,105, 84, 99, 73, 57, 1, 40, 4,106,251,
+150,254,122, 71,156, 49, 72, 42, 86, 1, 3,138, 92,115,115,126, 66, 16, 34, 41, 0, 2, 0,130,254, 20, 4, 84, 2,243, 0, 17,
+ 0, 46, 0, 0, 1, 22, 51, 50, 55, 54, 53, 52, 39, 38, 39, 38, 35, 34, 7, 6, 21, 20, 7, 38, 7, 6, 21, 17, 35, 17, 52, 55,
+ 54, 51, 38, 53, 52, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 35, 6, 2, 88,122, 76, 44, 21, 53, 6, 21, 59, 40, 46, 59,
+ 27, 68,110, 50, 75, 25,200,120, 65, 90, 2,162, 77, 92, 77, 79,182, 28, 8, 98,120, 88,178, 1, 39, 42, 22, 57, 58, 24, 20, 88,
+ 17, 12, 27, 68, 68, 40,193, 28, 78, 26, 79,254, 20, 1,236,173,102, 55, 42, 40,148,132, 63, 36, 83,167, 45, 56,146, 65, 80, 2,
+255,255, 0, 54,254,181, 4,141, 3, 96, 16, 39, 11,195, 1,234, 2,202, 16, 6, 4, 56, 0, 0, 0, 2, 0,222,255,198, 3,243,
+ 2,222, 0, 15, 0, 31, 0, 0, 1, 34, 7, 6, 23, 22, 23, 22, 51, 50, 55, 54, 53, 52, 39, 38, 39, 50, 23, 22, 21, 6, 7, 6,
+ 35, 34, 39, 38, 53, 52, 55, 54, 2, 14, 66, 33, 26, 1, 1, 55, 57, 57, 91, 93, 75, 66,123,152,198,182,141, 1,147,165,132, 96,
+ 81,167, 37, 84, 2, 42, 87, 69,123, 82, 44, 44, 57, 46, 85, 77, 65,120,179,160,124,148,200, 75, 85, 35, 74,239,181, 78,185, 0,
+ 0, 2, 0, 76,254, 12, 4, 51, 2,134, 0, 11, 0, 38, 0, 0, 1, 34, 7, 6, 21, 20, 23, 22, 23, 52, 39, 38, 1, 16, 7, 6,
+ 7, 6, 33, 53, 32, 55, 54, 55, 38, 39, 38, 39, 38, 53, 52, 55, 54, 51, 50, 23, 22, 23, 22, 2,225, 63, 44, 24, 51, 47,192, 86,
+ 37, 1, 46,172, 45,186,190,254,106, 1,115,161,224, 49,118, 45,139, 51,116,211, 57, 62, 89, 72,131, 24, 17, 1,196, 57, 33, 36,
+ 55, 43, 40, 4,184, 59, 25,254,244,254,218,174, 46, 84, 86,184, 76,104,139, 3, 7, 24, 43, 98,137,217, 90, 24, 51, 91,142,102,
+ 0, 1, 0, 25,254,243, 4,209, 3, 28, 0, 53, 0, 0, 37, 6, 7, 6, 35, 34, 39, 36, 17, 52, 55, 51, 6, 23, 22, 23, 22, 51,
+ 50, 55, 54, 55, 54, 53, 52, 39, 38, 39, 38, 55, 54, 55, 54, 51, 50, 23, 22, 23, 35, 52, 39, 38, 7, 6, 7, 6, 21, 20, 23, 22,
+ 23, 22, 23, 22, 4,121,132,224,177, 93,129, 72,254,219, 63,184, 66, 1, 2,164, 75, 83,120,108,107, 65, 59, 27, 34,132, 98, 1,
+ 1, 94, 77, 96,143, 55, 50, 17,184, 19, 27, 39, 20, 24, 35,125, 91, 55, 31, 1, 1, 12,195, 48, 38, 26,104, 1, 5,117,113,131,
+ 99,147, 45, 20, 35, 35, 78, 71, 34, 46, 42, 51, 58, 44,131,150, 61, 50, 73, 66,137, 61, 25, 34, 4, 2, 20, 30, 57, 41, 44, 32,
+103, 58, 94, 77,255,255, 0, 25,254, 12, 4,209, 3, 28, 16, 39, 11,196, 1,114,254, 12, 16, 6, 4, 2, 0, 0, 0, 2, 1, 68,
+ 4,186, 3,140, 6,154, 0, 3, 0, 7, 0, 0, 1, 53, 37, 21, 1, 53, 37, 21, 1, 68, 2, 72,253,184, 2, 72, 5,170,110,130,
+110,254,142,110,130,110, 0, 0, 0, 2, 1, 68, 4,186, 3,140, 6,253, 0, 38, 0, 53, 0, 0, 1, 54, 55, 38, 39, 38, 53, 52,
+ 55, 54, 51, 50, 23, 22, 21, 20, 7, 22, 51, 22, 51, 21, 34, 47, 1, 6, 7, 6, 35, 34, 39, 38, 53, 51, 20, 23, 22, 51, 50, 55,
+ 54, 55, 54, 53, 52, 38, 35, 34, 7, 6, 21, 20, 23, 22, 2,116, 36, 22, 33, 23,108, 68, 29, 63, 73, 39, 56, 13, 19, 14, 19, 19,
+ 46, 20, 52, 26, 76, 84, 94,115, 55, 16, 90, 12, 36, 48, 56,158, 4, 2, 10, 34, 20, 24, 10, 18, 44, 20, 5,100, 36, 42, 7, 13,
+ 57, 94, 87, 52, 21, 39, 54, 79, 39, 38, 1, 1,110, 2, 5, 61, 78, 86,154, 41,113, 97, 26, 75,238, 7, 7, 21, 24, 34, 28, 9,
+ 13, 28, 37, 18, 8, 0, 0, 0, 0, 2, 1, 68,254, 22, 3,140,255,246, 0, 3, 0, 7, 0, 0, 1, 53, 37, 21, 37, 53, 37, 21,
+ 1, 68, 2, 72,253,184, 2, 72,254, 22,110,130,110,110,110,130,110, 0, 0, 0, 0, 1, 1, 68, 4,186, 3,140, 5,170, 0, 3,
+ 0, 0, 1, 53, 37, 21, 1, 68, 2, 72, 4,186,110,130,110, 0, 0, 2, 1, 68, 4,185, 3,140, 6,253, 0, 31, 0, 47, 0, 0,
+ 1, 38, 39, 38, 53, 52, 55, 54, 51, 50, 23, 22, 21, 20, 7, 22, 51, 22, 51, 21, 34, 39, 38, 39, 6, 7, 6, 35, 53, 50, 55, 54,
+ 55, 54, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 21, 20, 23, 22, 2,146, 9, 19,108, 68, 29, 63, 73, 39, 56, 15, 17, 18, 19, 19,
+ 34, 32, 31, 27, 43, 69,201,147,153,139, 22, 86, 4, 2, 10, 18, 16, 20, 24, 10, 18, 44, 20, 5,186, 2, 10, 56, 95, 87, 52, 21,
+ 39, 54, 79, 32, 45, 1, 1,110, 2, 2, 3, 61, 42,123,110,109, 18,112, 7, 7, 21, 24, 34, 14, 14, 9, 13, 28, 37, 18, 8, 0,
+ 0, 1, 1, 68,254,232, 3,140,255,216, 0, 3, 0, 0, 1, 53, 37, 21, 1, 68, 2, 72,254,232,110,130,110, 0, 0, 1, 1, 48,
+ 4,202, 3,161, 6,244, 0, 40, 0, 0, 1, 6, 7, 6, 7, 6, 39, 38, 53, 52, 55, 51, 6, 23, 22, 23, 22, 55, 54, 55, 54, 53,
+ 51, 20, 23, 22, 55, 54, 53, 52, 39, 51, 22, 7, 6, 7, 6, 7, 6, 39, 38, 2,120, 15, 33, 57, 69, 79, 41, 34, 16, 97, 12, 1,
+ 3, 22, 19, 50, 61, 4, 2, 96, 3, 14, 75, 71, 13,103, 15, 3, 3, 24, 38, 90, 71, 31, 27, 5,132, 77, 39, 68, 1, 2, 65, 50,
+111,109, 98,125, 56, 84, 34, 28, 23, 26,168, 82, 89, 36, 54,197, 2, 1,173,115, 57, 73,116,133, 54, 88, 11, 9, 33, 30, 0, 0,
+ 0, 2, 1, 86, 4,225, 3,122, 7, 6, 0, 9, 0, 19, 0, 0, 1, 52, 38, 34, 6, 21, 20, 22, 50, 62, 1, 20, 6, 35, 34, 38,
+ 52, 54, 51, 50, 3, 0, 88,128, 88, 88,128, 88,122,158,116,114,160,160,114,116, 5,244, 63, 88, 87, 64, 65, 87, 88,179,230,160,
+160,230,159, 0, 0, 1, 1, 0, 4,185, 3,208, 5,193, 0, 18, 0, 0, 1, 55, 22, 23, 22, 51, 50, 55, 54, 55, 21, 6, 7, 6,
+ 35, 34, 38, 39, 7, 1, 0,160,103, 67, 42, 54, 58, 42,107, 87, 90, 90, 66, 54, 34,152, 68,166, 5, 54,123, 83, 21, 13, 16, 41,
+ 76,125, 64, 29, 22, 34, 70,128,255,255, 1,189, 4,191, 3, 20, 6,120, 16, 6, 4, 32, 0,141,255,255, 1,189,254, 12, 3, 20,
+255,197, 16, 7, 4, 32, 0, 0,248,218, 0, 0, 0, 1, 1, 92, 4,238, 3,118, 6, 52, 0, 6, 0, 0, 1, 3, 51, 23, 55, 51,
+ 3, 2, 30,194,138,130,130,140,196, 4,238, 1, 70,195,195,254,186, 0, 0, 0, 0, 1, 1,250, 1,194, 2,214, 2,188, 0, 3,
+ 0, 0, 1, 51, 21, 35, 1,250,220,220, 2,188,250, 0, 0, 0, 0, 1, 1,150, 0, 0, 3, 60, 5, 20, 0, 9, 0, 0, 33, 35,
+ 16, 39, 2, 3, 51, 18, 19, 22, 3, 60,180, 38, 49,155,196,121, 73, 32, 1,169,220, 1, 33, 1,110,254,221,254,148,155, 0, 0,
+ 0, 1, 0,154, 0, 0, 4, 56, 5, 20, 0, 24, 0, 0, 1, 22, 23, 22, 17, 35, 16, 39, 2, 3, 51, 22, 23, 22, 51, 22, 55, 54,
+ 55, 51, 6, 7, 2, 35, 34, 1,237, 28, 23, 32,180, 38, 49,155,198, 67, 3, 82,180,122, 54, 32, 8,180, 8, 42, 98,244,111, 3,
+ 97,106,114,155,254, 22, 1,169,220, 1, 33, 1,110,155, 5,152, 2,149, 85, 80,121,109,254,250, 0, 1, 0,134, 0, 0, 4, 76,
+ 5, 20, 0, 37, 0, 0, 1, 22, 23, 22, 17, 35, 16, 39, 2, 3, 51, 22, 23, 22, 55, 54, 55, 54, 53, 51, 20, 23, 22, 23, 22, 55,
+ 54, 53, 51, 16, 7, 6, 35, 34, 39, 6, 7, 6, 1,228, 24, 16, 32,180, 38, 49,155,196, 47, 40, 19, 48, 72, 8, 6,180, 14, 21,
+ 47, 60, 14, 14,180, 40, 70,156,132, 33, 51, 52, 46, 3, 53, 87, 89,190,254, 57, 1,169,220, 1, 33, 1,110,114,124, 62, 8, 12,
+ 64, 50,166,222, 25, 37, 2, 2, 44, 42,202,254,207, 59,108, 62, 51, 12, 10, 0, 0, 1, 0,236,255,236, 3,228, 5, 32, 0, 42,
+ 0, 0, 1, 21, 6, 7, 6, 21, 20, 23, 22, 23, 21, 34, 7, 6, 21, 20, 23, 22, 23, 50, 55, 54, 55, 21, 6, 7, 6, 35, 34, 39,
+ 38, 53, 52, 55, 54, 55, 38, 39, 38, 39, 38, 55, 54, 3, 96,121,103,136, 92, 78, 78, 89,135,112, 48, 60, 74, 98, 88,126, 86, 72,
+124,101,101,150,112,100,108, 64, 88, 72, 44, 55, 1, 1,225,113, 5, 32,168, 17, 52, 67, 64, 35, 57, 48, 4,164, 76, 64,114, 82,
+ 60, 74, 1, 23, 33, 43,196, 37, 28, 23,125,112,165,134,128, 76, 24, 32, 48, 58, 63,150,128, 63, 0, 2, 0,202,255,236, 4, 8,
+ 5, 37, 0, 13, 0, 28, 0, 0, 0, 34, 7, 6, 7, 6, 23, 22, 32, 55, 54, 39, 38, 39, 3, 22, 19, 22, 21, 16, 7, 6, 32, 39,
+ 38, 17, 52, 55, 18, 2,171,133, 86, 79, 3, 5, 71, 41, 0,255, 40, 72, 4, 4, 78,154,191,135, 90, 86,104,254, 61,105, 84, 90,
+135, 4,104,212,192,174,199,115, 66, 66,115,199,174,192, 1,144, 1,254,161,235,179,254,203,117,144,144,117, 1, 53,179,235, 1,
+ 97, 0, 0, 0, 0, 1, 0,154, 0, 0, 4, 55, 5, 20, 0, 17, 0, 0, 1, 16, 19, 18, 19, 35, 2, 3, 2, 39, 6, 35, 34, 39,
+ 53, 22, 51, 50, 3,147, 37, 29, 98,196, 85, 31, 28, 2, 96,142,178,167,180,165,210, 5, 20,254,220,254,159,254,235,254,134, 1,
+ 68, 1, 75, 1, 42,145, 28, 50,180, 50, 0, 0, 0, 1, 0,126, 0, 0, 4, 82, 5, 20, 0, 18, 0, 0, 33, 38, 3, 2, 39, 51,
+ 18, 19, 22, 23, 54, 55, 18, 19, 51, 2, 3, 2, 7, 2, 14, 16, 98,160,126,196,154, 90, 48, 2, 2, 48, 90,154,196,164,120, 86,
+ 30,246, 1, 58, 1,254,230,254,202,254,197,168, 11, 11,168, 1, 59, 1, 54,254,211,254, 73,254,202,250, 0, 0, 0, 1, 0,126,
+ 0, 0, 4, 82, 5, 20, 0, 18, 0, 0, 1, 51, 22, 19, 18, 19, 35, 2, 3, 38, 39, 6, 7, 2, 3, 35, 54, 19, 18, 2, 14,180,
+ 30, 86,120,164,196,154, 90, 48, 2, 2, 48, 90,154,196,126,160, 98, 5, 20,250,254,202,254, 73,254,211, 1, 54, 1, 59,168, 11,
+ 11,168,254,197,254,202,230, 1,254, 1, 58, 0, 0, 2, 0,161, 0, 0, 4, 48, 5, 31, 0, 20, 0, 35, 0, 0, 1, 38, 39, 38,
+ 39, 38, 39, 38, 55, 54, 23, 22, 23, 22, 23, 22, 23, 18, 19, 35, 2, 3, 39, 38, 39, 38, 35, 34, 7, 6, 23, 22, 23, 22, 23, 22,
+ 2,252,205, 61,165, 66,103, 2, 4, 99,126,146,154, 92,128, 14, 10, 18, 36, 91,196, 92, 36, 7, 10, 34, 56,107, 78, 58, 58, 2,
+ 1, 59, 33, 77, 79, 2, 85, 3, 15, 41, 65,101,123,142, 98,126, 1, 1, 84,118,167,135,150,254,205,254,164, 1,156, 1,110, 87,
+108, 60, 97, 55, 54, 71, 57, 54, 31, 13, 14, 0, 0, 3, 0,200, 0, 0, 4, 10, 5, 20, 0, 3, 0, 7, 0, 11, 0, 0, 37, 51,
+ 21, 35, 1, 51, 21, 35, 37, 51, 1, 35, 3, 70,180,180,253,144,180,180, 2,148,160,253, 94,160,250,250, 5, 20,250,250,250,236,
+ 0, 1, 1, 54,255, 31, 3,155, 2,139, 0, 17, 0, 0, 5, 54, 55, 54, 55, 54, 53, 52, 39, 51, 22, 21, 20, 7, 6, 7, 6, 7,
+ 1, 54,168,113,107, 47, 25, 21,150, 24, 75, 79,165,106,188, 70, 5,113,109,143, 80, 79, 96, 96, 78,111,170,160,166,113, 72, 6,
+ 0, 1, 1,214, 3,254, 2,251, 5,213, 0, 5, 0, 0, 1, 51, 21, 3, 35, 19, 2, 40,211,164,129, 82, 5,213,152,254,193, 1,
+ 63, 0, 0, 0, 0, 1, 0,146, 0,206, 4, 64, 4, 76, 0, 9, 0, 0, 19, 33, 27, 1, 33, 5, 19, 37, 5, 19,146, 1,103,111,
+113, 1,103,254,221,112,254,219,254,221,111, 2,247, 1, 85,254,171,212,254,171,211,211, 1, 85, 0, 1, 0, 69,255,235, 4,176,
+ 2, 27, 0, 25, 0, 0, 1, 22, 21, 20, 7, 6, 5, 6, 39, 38, 53, 52, 55, 51, 6, 21, 20, 23, 22, 51, 50, 55, 54, 53, 52, 39,
+ 4,150, 26,166,152,254,233,223,154,157, 41,184, 43,117, 98,132,188,106,123, 25, 2, 27, 71,132,123,121,111, 1, 1, 57, 59,225,
+ 62,124,138, 48,108, 30, 25, 65, 76,106, 64, 71, 0, 2, 0, 31,254,124, 4,116, 3,217, 0, 15, 0, 56, 0, 0, 1, 54, 53, 52,
+ 39, 38, 7, 6, 7, 6, 7, 20, 23, 22, 51, 50, 1, 54, 55, 54, 17, 6, 35, 34, 39, 38, 53, 52, 55, 54, 55, 54, 51, 50, 23, 22,
+ 23, 22, 21, 20, 7, 6, 7, 6, 39, 38, 39, 38, 53, 52, 55, 51, 6, 7, 20, 23, 22, 3,129, 41, 66, 31, 44, 52, 40, 40, 1, 55,
+ 40, 42, 72,254, 91,212, 98,203, 63,122,133, 75, 98, 8, 23,150, 78, 76, 99, 57,103, 39, 33, 46, 57,165,187,233,206,138, 77, 82,
+183, 86, 2, 18, 86, 2, 25, 43, 77, 59, 51, 25, 1, 1, 42, 41, 51, 80, 38, 25,253, 59, 2,102,212, 1, 52, 75, 67, 87,129, 45,
+ 51,148, 69, 36, 50, 90,119,102,160,252,142,179,131,148, 1, 1,191,106,125,180,216,187,153, 72, 40,176, 0, 0, 0, 1, 1,189,
+ 5, 50, 3, 20, 6,235, 0, 24, 0, 0, 1, 55, 38, 39, 38, 55, 54, 55, 54, 23, 22, 23, 21, 38, 35, 34, 7, 6, 21, 20, 23, 22,
+ 55, 21, 5, 1,189, 78, 44, 16, 17, 1, 2, 54, 56, 94, 61, 53, 51, 63, 66, 17, 29, 94, 33,120,254,169, 5,150, 18, 20, 36, 37,
+ 45, 95, 44, 46, 1, 1, 32,100, 33, 18, 32, 26, 77, 27, 10, 29,102, 77, 0, 0,255,255, 0, 69,255,235, 4,176, 4,153, 16, 39,
+ 3,220, 0, 42,253,168, 16, 6, 4, 30, 0, 0,255,255, 0, 69,255,235, 4,176, 4, 26, 16, 39, 11,204, 2, 22, 3,132, 16, 6,
+ 4, 30, 0, 0,255,255, 0, 69,254, 12, 4,176, 2, 27, 16, 39, 11,204, 2, 16,255, 6, 16, 6, 4, 30, 0, 0,255,255, 0, 69,
+254, 12, 4,176, 3, 32, 16, 39, 11,208, 1,152,254, 12, 16, 38, 4, 30, 0, 0, 16, 7, 11,196, 1,184, 2,138,255,255, 0, 69,
+255,235, 4,176, 3,182, 16, 39, 11,203, 1,169, 3, 32, 16, 6, 4, 30, 0, 0,255,255, 0, 69,254, 12, 4,176, 2, 27, 16, 39,
+ 11,203, 1,158,255, 6, 16, 6, 4, 30, 0, 0,255,255, 0, 69,255,235, 4,176, 4, 26, 16, 39, 11,205, 1,164, 3,132, 16, 6,
+ 4, 30, 0, 0,255,255, 0, 69,254, 12, 4,176, 2, 27, 16, 39, 11,205, 1,158,255, 6, 16, 6, 4, 30, 0, 0,255,255, 0, 88,
+254, 11, 4,173, 5,176, 16, 39, 4, 13,255,174,255, 56, 16, 6, 3,235, 0, 0,255,255, 0, 88,254, 11, 4,173, 5,170, 16, 39,
+ 11,204, 1,194, 5, 20, 16, 6, 3,235, 0, 0,255,255, 0, 88,254, 11, 4,173, 3,103, 16, 39, 11,196, 2, 42, 0, 81, 16, 6,
+ 3,235, 0, 0,255,255, 0, 88,254, 11, 4,173, 3,103, 16, 39, 11,204, 2,203, 0,175, 16, 6, 3,235, 0, 0,255,255, 0, 88,
+254, 11, 4,173, 5,170, 16, 39, 11,197, 1, 84, 4, 26, 16, 6, 3,235, 0, 0,255,255, 0, 88,254, 11, 4,173, 3,103, 16, 39,
+ 11,203, 2,106, 0,150, 16, 6, 3,235, 0, 0,255,255, 0, 88,254, 11, 4,173, 3,103, 16, 39, 11,205, 2, 98, 0,175, 16, 6,
+ 3,235, 0, 0,255,255,255,204,254, 8, 4,208, 4,168, 16, 38, 3,239, 0, 0, 16, 7, 3,220, 1, 98,253,183,255,255,255,204,
+254, 8, 4,181, 4, 6, 16, 38, 3,239, 0, 0, 16, 7, 4, 15, 1, 62,253,210,255,255,255,204,254, 8, 4,101, 4,113, 16, 39,
+ 11,197, 2,213, 2,225, 16, 6, 3,239, 0, 0, 0, 2,255,181,255,164, 4,140, 3,120, 0, 14, 0, 57, 0, 0, 1, 54, 53, 52,
+ 39, 38, 7, 34, 6, 7, 20, 23, 22, 51, 50, 19, 6, 7, 6, 35, 34, 39, 38, 3, 38, 55, 51, 6, 21, 20, 23, 22, 51, 50, 55, 54,
+ 55, 54, 55, 6, 35, 34, 39, 38, 53, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 16, 3,163, 41, 66, 31, 44, 52, 80, 1, 55,
+ 38, 44, 72,157,105,167,178,165,163,114,244, 2, 2, 36,184, 36,120, 90,131,127, 84,188, 48, 65, 38, 63,122,133, 75, 98, 8, 23,
+150, 78, 76, 90, 66, 96, 46, 23, 1,184, 44, 76, 57, 53, 26, 2, 84, 50, 82, 36, 26,254,166, 84, 38, 40, 41, 88, 1, 21,138, 92,
+ 94,136,147, 45, 34, 22, 50, 28, 40,104, 76, 68, 86,130, 44, 52,148, 68, 36, 50, 72,102, 51,139,254,187, 0, 0,255,255,255,181,
+255,164, 4,140, 5,153, 16, 39, 11,197, 2,112, 4, 9, 16, 6, 4, 51, 0, 0, 0, 1, 0, 10,255,167, 5, 93, 6, 20, 0, 42,
+ 0, 0, 37, 50, 54, 55, 54, 53, 52, 47, 1, 38, 53, 52, 55, 54, 55, 1, 21, 1, 6, 21, 20, 31, 1, 22, 21, 20, 7, 6, 7, 6,
+ 35, 34, 39, 36, 17, 52, 55, 51, 6, 21, 20, 23, 22, 2, 38,162,218, 54, 52, 95,183, 62, 18, 46, 86, 2, 15,254,104, 71, 32,148,
+142,104, 82,164, 99,207,112,108,254,182, 63,184, 65,203, 79, 88,106, 60, 57, 85, 57,105,202, 68, 71, 84, 31, 79, 65, 1,142,209,
+254,194, 55, 46, 63, 35,162,155,111,157,117, 92, 78, 47, 32, 98, 1, 11,138, 92, 94,136,120, 72, 28, 0, 0, 0,255,255, 0, 10,
+255,167, 5, 97, 7, 56, 16, 39, 11,206, 2,170, 0, 0, 16, 6, 4, 53, 0, 0,255,255, 0, 66,254,200, 4,250, 7,196, 16, 39,
+ 4, 15, 1,132, 1,144, 16, 6, 3,253, 0, 0, 0, 1, 0, 54,254,181, 4,141, 2,176, 0, 29, 0, 0, 1, 20, 7, 6, 7, 6,
+ 35, 34, 39, 38, 17, 52, 55, 51, 6, 21, 20, 23, 22, 51, 50, 55, 54, 55, 54, 53, 52, 39, 51, 22, 4,141,100, 71,142,140,129,172,
+123,234, 53,184, 55,161, 57,129, 84, 63,157, 58, 34, 70,184, 72, 0,255,187,164,116, 60, 59, 63,120, 1, 18,174,142,174,142,180,
+ 67, 24, 20, 51,167, 98, 96,249,152,159, 0, 0, 0, 3, 0, 0,255,189, 4,147, 3,229, 0, 38, 0, 54, 0, 70, 0, 0, 40, 1,
+ 39, 38, 53, 52, 55, 51, 6, 21, 20, 23, 22, 51, 50, 55, 38, 39, 38, 53, 52, 55, 54, 23, 38, 39, 53, 22, 23, 4, 23, 22, 21, 20,
+ 7, 6, 35, 34, 39, 55, 54, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 21, 20, 23, 22, 37, 22, 21, 20, 7, 6, 7, 22, 51, 50, 55,
+ 54, 53, 52, 39, 38, 1,221,254,220, 67,118, 16,184, 14, 30, 45, 40, 59, 71, 45, 15, 18, 45, 48, 77, 44, 81,219,220, 1, 5, 59,
+ 14, 40, 74,175,131,154, 21, 36, 34, 39, 15, 22, 58, 65, 23, 22, 7, 21, 1, 71, 6, 98, 12, 17, 52, 49,126, 16, 7, 33, 29, 36,
+ 64,128, 75, 53, 58, 44, 43, 11, 16, 11,105, 69, 78, 64, 84, 83, 90, 9, 39, 14,185, 67,180,214,217, 52, 57,103, 61,113,108,228,
+ 27, 64, 72, 61, 46, 37, 52, 45, 43, 35, 30, 37,118,188, 37, 39,138,114, 14, 19, 46, 67, 30, 33, 60, 78, 69, 0,255,255, 0, 76,
+254, 12, 4, 51, 4, 72, 16, 39, 4, 15, 0,112,254, 20, 16, 6, 4, 1, 0, 0,255,255, 0, 25,254,243, 4,209, 3, 28, 16, 6,
+ 4, 2, 0, 0,255,255, 0, 25,254,243, 4,209, 4, 20, 16, 39, 4, 15,255, 40,253,224, 16, 6, 4, 2, 0, 0,255,255, 0,222,
+255,198, 3,243, 2,222, 16, 6, 4, 0, 0, 0,255,255, 1,250, 1,194, 2,214, 2,188, 16, 6, 4, 16, 0, 0,255,255, 1,150,
+ 0, 0, 3, 60, 5, 20, 16, 6, 4, 17, 0, 0,255,255, 0,154, 0, 0, 4, 56, 5, 20, 16, 6, 4, 18, 0, 0,255,255, 0,134,
+ 0, 0, 4, 76, 5, 20, 16, 6, 4, 19, 0, 0, 0, 1, 0,175, 0, 0, 4, 34, 5, 37, 0, 39, 0, 0, 1, 38, 53, 52, 55, 54,
+ 51, 50, 23, 21, 38, 7, 6, 7, 6, 21, 20, 23, 22, 55, 54, 55, 21, 6, 35, 34, 39, 22, 23, 22, 17, 35, 16, 39, 2, 3, 51, 22,
+ 23, 22, 2, 37, 4, 88, 92,108, 84, 88, 92, 68, 56, 30, 31, 25, 47, 48, 69,141,195, 61,141,146, 27, 23, 32,180, 37, 49,156,199,
+ 66, 3, 27, 4, 20, 15, 19,120, 58, 61, 25,156, 36, 2, 1, 33, 34, 21, 52, 21, 39, 2, 2, 17,180, 26, 81,106,114,155,254, 22,
+ 1,169,220, 1, 33, 1,110,155, 5, 56, 0, 0, 0, 2, 0,172,255,244, 4, 37, 5, 36, 0, 19, 0, 39, 0, 0, 1, 22, 51, 50,
+ 55, 54, 53, 52, 39, 38, 34, 7, 6, 21, 20, 23, 22, 51, 50, 55, 23, 6, 39, 38, 39, 38, 53, 16, 55, 18, 51, 50, 19, 22, 19, 22,
+ 7, 6, 7, 6, 2,194, 45, 50, 34, 18, 27, 87, 90,174, 91, 86, 27, 15, 37, 51, 44, 90, 40,145,160, 46, 53, 95,179,170,162,187,
+ 94, 1, 1, 53, 51,156,144, 1, 90,161, 74,107, 86,215,216,224,224,213,218, 60,133, 74,161,208,151, 2, 2,156,181,124, 1, 38,
+196, 1,118,254,138,187,254,209,141,164,157, 1, 2, 0, 0, 0, 0, 1, 1, 8, 0, 0, 3,200, 5, 32, 0, 32, 0, 0, 33, 18,
+ 55, 54, 55, 34, 39, 38, 53, 52, 55, 54, 55, 54, 23, 21, 38, 35, 34, 7, 6, 21, 20, 23, 22, 51, 50, 55, 21, 6, 7, 6, 7, 1,
+ 8, 66,110, 68,100, 78, 46,134, 98,112,140,121, 87, 86,116, 62, 48, 66, 55, 44,103,140, 96,225,111,134, 54, 0,255,181,111, 85,
+ 37,109,151,175, 96,109, 2, 2, 33,180, 51, 47, 65, 98, 77, 51, 41, 41,180, 73,152,183,225, 0,255,255, 0,126, 0, 0, 4, 82,
+ 5, 20, 16, 6, 4, 23, 0, 0,255,255, 0,126, 0, 0, 4, 82, 5, 20, 16, 6, 4, 24, 0, 0,255,255, 0,161, 0, 0, 4, 48,
+ 5, 31, 16, 6, 4, 25, 0, 0, 0, 3, 0, 62,255,235, 4,100, 4,123, 0, 7, 0, 15, 0, 42, 0, 62, 64, 13, 35, 6, 37, 10,
+ 2, 27, 20, 14, 6, 22, 6, 16, 43, 16,220,236,204,204,220, 60,204,204, 47,236, 49, 0, 64, 7, 0, 22, 4, 18,153, 37, 43, 16,
+ 60,244,204,220,204, 64, 9, 12, 25, 8, 40,140, 29, 33,190, 44, 16,252, 60,236,204,220,204, 48, 37, 38, 21, 20, 55, 54, 39, 38,
+ 3, 38, 21, 20, 55, 54, 39, 38, 19, 20, 35, 34, 53, 52, 55, 17, 6, 35, 34, 53, 52, 51, 50, 23, 54, 51, 32, 25, 1, 35, 17, 52,
+ 35, 34, 7, 1, 20, 63, 63, 66, 1, 1, 76, 63, 63, 66, 1, 1,162,198,230,244, 21, 21,202,202,145, 44, 76,189, 1,150,184,226,
+137, 87,244, 2, 66, 65, 1, 1, 63, 62, 3, 5, 2, 66, 65, 1, 1, 63, 62,252,195,205,201,202, 6, 1,112, 8,208,191, 81, 81,
+254,190,252,199, 3, 57,170,142, 0, 2, 0,108,255,221, 4,174, 4,141, 0, 3, 0, 44, 0, 0, 0, 34, 20, 50, 7, 34, 53, 52,
+ 55, 54, 55, 36, 19, 22, 5, 7, 4, 23, 22, 51, 50, 54, 51, 50, 23, 7, 38, 35, 34, 6, 35, 32, 39, 52, 37, 55, 54, 53, 52, 5,
+ 6, 7, 22, 23, 20, 1,130,128,128, 68,210,188,187,151, 1,229, 1, 2,254,152,182,254,227, 3, 5,231, 74,214, 80,158,138,134,
+105, 63, 51,204,107,254, 93, 1, 1,180,178,214,254,200, 75, 77, 63, 1, 3,111,128,148,228,137, 97, 98, 1, 2,254,169,237,117,
+ 59, 92, 83,102,142,213, 97,145,127,249,198,142, 58, 70,130,189, 3, 1, 55, 56, 85,216, 0, 0, 0, 3, 0,121,255,235, 4, 80,
+ 4,141, 0, 7, 0, 17, 0, 56, 0, 0, 1, 22, 51, 50, 55, 38, 39, 34, 19, 22, 39, 38, 35, 34, 23, 20, 21, 22, 37, 52, 55, 38,
+ 55, 54, 36, 23, 4, 18, 25, 1, 35, 17, 16, 38, 7, 14, 1, 23, 54, 55, 32, 7, 20, 35, 34, 39, 6, 23, 22, 23, 54, 51, 50, 21,
+ 20, 7, 4, 1, 89, 54, 5, 23, 48, 73, 1, 18,127, 54, 2, 3, 49, 54, 2, 1,254,174, 42, 44, 3, 6, 1, 11,229, 1, 33,191,
+184,127,169,177,155, 3, 42, 58, 1, 5, 1,250, 57, 20, 31, 3, 2, 20, 23,171,204,204,254,117, 2, 96, 20, 18, 17, 1,254, 16,
+ 1, 48, 39, 34, 1, 3, 47,220,127,128, 54, 79,211,217, 1, 1,254,224,254,214,253,191, 2, 65, 1, 1,183, 3, 3,184, 75, 18,
+ 1,165,165, 11, 37, 91, 57, 46,141,200,181, 1, 1, 0, 0, 0, 0, 2, 0,246,254, 24, 3,219, 4,140, 0, 25, 0, 33, 0, 0,
+ 19, 52, 54, 51, 32, 25, 1, 16, 6, 35, 34, 38, 39, 55, 22, 51, 50, 53, 17, 16, 35, 22, 21, 6, 39, 38, 19, 38, 23, 6, 55, 22,
+ 39, 54,247,162,221, 1,101,155,204,214,116, 13,189, 33,121,175,130, 2, 6,215,209,215, 67, 3, 2, 66, 66, 2, 1, 3,166,113,
+117,253,244,253,143,254,249,240,208,141, 10,209,243, 2,223, 1,104, 21, 33,207, 1, 1, 1, 9, 1, 65, 67, 3, 2, 66, 66, 0,
+ 0, 2, 0,124,255,255, 4, 85, 4,154, 0, 11, 0, 41, 0, 0, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 3, 50, 23, 22,
+ 25, 1, 7, 19, 52, 39, 20, 39, 38, 53, 52, 51, 50, 23, 16, 5, 6, 7, 6, 29, 1, 35, 53, 52, 55, 54, 2,110, 36, 28, 32, 32,
+ 37, 27, 32, 42,250,124,123,184, 1,101,200,217,218,244, 54,254,196,207, 76, 17,184, 30,106, 2, 96, 32, 32, 37, 27, 34, 30, 37,
+ 27, 2, 58,121,120,254,217,253,126, 1, 1, 41,142, 82,166, 1, 2,183,192,104, 1,149, 5, 4,134, 30,134, 75, 75,170, 62,220,
+ 0, 2, 0, 97,254, 25, 4,201, 4,131, 0, 11, 0, 57, 0, 0, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 3, 38, 53, 52,
+ 53, 54, 55, 54, 55, 36, 19, 22, 13, 1, 6, 23, 22, 51, 50, 55, 54, 51, 50, 21, 20, 19, 48, 7, 2, 17, 6, 33, 32, 53, 52, 45,
+ 1, 54, 53, 52, 5, 6, 7, 22, 23, 6, 1, 54, 36, 28, 32, 32, 37, 27, 32, 35,210, 2,229,118,202, 1,201, 2, 1,254,138,254,
+251,169, 5, 4,199,179, 93, 35,120,151,134,144,176, 46,254,164,254,127, 1, 62, 1, 1,229,254,226,114, 62, 62, 1, 36, 3,111,
+ 32, 32, 37, 27, 34, 30, 37, 27,254,236, 16,209, 2, 1,133,125, 64, 1, 2,254,188,214,126, 89, 57,112,101,183, 68,216,243,254,
+181, 81, 1, 99, 1, 70,211,248,226,108, 87, 78,110,169, 3, 1, 45, 55, 86,188, 0, 2, 0,114,255,238, 4, 92, 4,150, 0, 11,
+ 0, 44, 0, 0, 1, 50, 54, 53, 52, 38, 39, 38, 6, 21, 20, 22, 3, 20, 33, 32, 25, 1, 51, 17, 16, 37, 36, 17, 52, 53, 54, 55,
+ 38, 55, 18, 5, 22, 21, 20, 7, 6, 39, 22, 23, 22, 55, 21, 7, 6, 1,215, 36, 28, 33, 31, 37, 27, 32,130, 1, 47, 1, 64,184,
+254, 8,254, 15, 3,162,166, 1, 1, 1,108,180,192,126, 46, 2, 90, 65,144,141,147, 3,164, 32, 32, 36, 27, 1, 1, 33, 32, 36,
+ 28,253,140,174, 1,184, 2, 63,253,193,253,180, 1, 1, 1, 61, 2, 1,145, 81,109,234, 1, 46, 2, 1,176,186, 2, 1,117,189,
+ 71, 52, 12,161, 23, 24, 0, 0, 0, 2, 0,123,255,227, 4, 86, 4,124, 0, 7, 0, 28, 0, 44, 64, 9, 27, 6, 8, 6, 16, 2,
+ 21, 6, 14, 47,252,204,220,204, 47,236, 49, 0, 64, 12, 11,140, 24,190, 29, 0, 14, 4, 18,153, 28, 29, 16, 60,244,204,220,204,
+ 16,252,252, 48, 37, 34, 21, 20, 51, 50, 53, 52, 5, 17, 52, 5, 4, 21, 17, 36, 23, 22, 35, 34, 53, 17, 52, 36, 55, 54, 4, 21,
+ 17, 1,102, 64, 64, 64, 1,248,254,202,254,203, 1, 24, 1, 1,231,235, 1, 19,218,197, 1, 41,235, 64, 64, 64, 64,235, 3, 31,
+201, 3, 3,195,254, 80, 27,223,200,200, 2,142,199,121, 2, 2,120,204,252,199, 0, 2, 0,149,255,226, 4,111, 4,161, 0, 11,
+ 0, 42, 0, 0, 37, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 19, 34, 2, 35, 34, 7, 3, 32, 21, 20, 35, 34, 53, 17, 16, 51,
+ 50, 18, 51, 50, 18, 55, 50, 25, 1, 35, 17, 52, 35, 34, 2, 1,128, 36, 28, 32, 32, 37, 27, 32,228,122,119, 15, 54, 1, 1, 1,
+ 25,213,251,242,131, 94, 34, 36, 74,133,242,184, 55, 22,102,241, 32, 32, 37, 27, 34, 30, 37, 27, 1,250, 1, 38,225,254, 80,196,
+218,210, 2,150, 1, 87,254,224, 1, 31, 1,254,169,252,182, 3, 48,219,254,224, 0, 3, 0, 26,254, 20, 4, 62, 4,124, 0, 3,
+ 0, 7, 0, 35, 0, 0, 36, 34, 20, 50, 0, 34, 20, 50, 19, 50, 23, 22, 35, 34, 53, 17, 6, 35, 38, 53, 54, 55, 54, 23, 54, 51,
+ 32, 22, 21, 17, 35, 17, 52, 35, 34, 7, 2, 38,128,128,254,237,128,128,166,241, 2, 2,218,211, 33, 31,167, 1,179,145, 55,121,
+139, 1, 6,158,184,244,123, 94,220,128, 3,166,128,253,221,185,195,227, 2, 73, 7, 2,190,178, 1, 1,101,100,213,109,250,219,
+ 5, 37,163,139, 0, 2, 0,106,255,226, 4,104, 4,124, 0, 7, 0, 39, 0, 62, 64, 7, 6, 12, 2, 8, 36, 6, 15, 47,252, 60,
+204,220,204, 64, 7, 20, 6, 32, 24, 6, 26, 41, 16,220,236,220,236, 49, 0, 64, 6, 17,140, 34,153, 26, 41, 16, 60,244,236, 64,
+ 9, 4, 38, 0, 29,140, 22, 10,190, 41, 16,252, 60,236,204,220,204, 48, 1, 38, 23, 6, 55, 22, 39, 54, 5, 52, 51, 50, 21, 20,
+ 6, 21, 20, 51, 50, 53, 17, 52, 23, 4, 21, 17, 35, 17, 52, 7, 6, 21, 3, 2, 37, 36, 17, 16, 55, 34, 1, 54, 67, 3, 2, 66,
+ 67, 3, 2,254,244,202,216,254,170,178,252, 1, 0,164, 98, 82, 1, 1,254,172,254,176,216,214, 4, 18, 2, 66, 67, 3, 1, 65,
+ 67, 75,177,173,202,224,212,216,188, 2, 74,254, 1, 1,251,252,129, 3,127,106, 3, 3,101,253,183,254,173, 1, 1, 1,104, 1,
+ 48,154, 0, 0, 0, 2, 0, 75,255,227, 4, 84, 4,141, 0, 5, 0, 32, 0, 0, 0, 50, 52, 35, 34, 7, 3, 53, 51, 50, 54, 53,
+ 17, 36, 53, 52, 55, 54, 21, 17, 22, 55, 54, 53, 17, 51, 17, 16, 33, 34, 39, 6, 35, 1, 3,128, 64, 62, 2,184,122, 93, 85,254,
+232,226,238, 93,120,152,184,254,180,174, 84,114,217, 3,115,128, 64,252, 48,143,101,156, 1,103, 8,204,221, 1, 1,219,253,117,
+169, 1, 1,177, 3, 47,252,209,254,178,115,115, 0, 2, 0,124,255,238, 4, 84, 4,125, 0, 3, 0, 25, 0, 0, 0, 34, 20, 50,
+ 1, 52, 55, 38, 55, 54, 23, 22, 7, 6, 0, 21, 22, 37, 32, 25, 1, 51, 17, 16, 37, 36, 1,169,128,128,254,212,182,183, 1, 1,
+229,237, 1, 1,254,236, 1, 1, 37, 1, 60,184,254, 12,254, 29, 3,238,128,253,210,218,196, 38,182,196, 2, 2,188,151,254,209,
+168,204, 1, 1, 39, 2,180,253, 76,254, 66, 1, 1, 0, 0, 0, 0, 2, 0,124,255,238, 4, 84, 6, 20, 0, 3, 0, 25, 0, 0,
+ 0, 34, 20, 50, 1, 52, 55, 38, 55, 54, 23, 22, 7, 6, 0, 21, 22, 33, 32, 25, 1, 51, 17, 16, 37, 36, 1,169,128,128,254,212,
+182,183, 1, 1,229,237, 1, 1,254,236, 1, 1, 37, 1, 60,184,254, 12,254, 29, 3,238,128,253,210,218,196, 38,182,196, 2, 2,
+188,151,254,209,168,203, 1, 39, 4,104,251,152,254, 66, 1, 1, 0, 3, 0, 99,255,239, 4,246, 5, 27, 0, 11, 0, 23, 0, 74,
+ 0, 0, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 5, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 1, 43, 1, 38, 39, 6,
+ 35, 34, 39, 38, 53, 17, 52, 51, 50, 21, 6, 39, 16, 21, 20, 51, 50, 53, 17, 51, 17, 20, 55, 54, 53, 17, 38, 55, 52, 23, 22, 23,
+ 54, 53, 38, 39, 55, 22, 23, 22, 7, 19, 20, 7, 6, 3,132, 36, 28, 32, 32, 37, 27, 32,253,146, 36, 28, 32, 32, 38, 26, 32, 1,
+224, 2, 2, 99,103,101,133,126, 80, 76,210,216, 1,241,102,138,184,114,116,243, 1,208,179, 27, 30, 1, 74,119, 84, 1, 3,152,
+ 2, 92, 85, 3,250, 32, 32, 38, 26, 34, 30, 36, 28, 1, 32, 32, 37, 27, 34, 30, 37, 27,251,246, 1, 73, 74, 84, 79,154, 2, 98,
+223,197,199, 23,254,111, 59,132,132, 1, 52,254,203,139, 5, 5,130, 1,204, 8,168,209, 1, 1,152, 22, 80, 54, 65, 94,103, 91,
+195,111,254, 6,164, 80, 73, 0, 0, 2, 0, 99,255,239, 4, 98, 6, 20, 0, 36, 0, 48, 0, 0, 1, 20, 7, 6, 43, 2, 38, 39,
+ 6, 35, 34, 39, 38, 53, 17, 52, 51, 50, 21, 6, 39, 16, 21, 20, 51, 50, 53, 17, 51, 17, 20, 55, 54, 53, 17, 51, 1, 34, 6, 21,
+ 20, 22, 51, 50, 54, 53, 52, 38, 4, 98, 92, 85,123, 2, 2, 99,103,101,133,126, 80, 76,210,216, 1,241,102,138,184,114,116,184,
+252,212, 36, 28, 32, 32, 38, 26, 32, 1, 44,164, 80, 73, 1, 73, 74, 84, 79,154, 2, 98,223,197,199, 23,254,111, 59,132,132, 1,
+ 52,254,203,139, 5, 5,130, 4,232,253,229, 32, 32, 37, 27, 34, 30, 37, 27, 0, 0, 2, 0,101,255,238, 4,108, 4,126, 0, 11,
+ 0, 44, 0, 0, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 19, 50, 53, 17, 51, 17, 6, 55, 54, 53, 17, 51, 17, 16, 37, 38,
+ 39, 6, 35, 32, 17, 52, 55, 38, 55, 54, 23, 22, 7, 6, 0, 23, 20, 1, 98, 36, 28, 32, 32, 36, 28, 32, 48,110,184, 1,117,104,
+184,254,224,105,103,101,143,254,222,152,138, 2, 2,228,237, 1, 2,254,214, 2, 3,210, 32, 32, 37, 27, 34, 30, 37, 27,252,179,
+167, 1, 52,254,203,174, 5, 5,165, 3, 47,252,209,254,192, 3, 1, 73, 74, 1, 61,240,166, 37,158,249, 1, 1,219,143,254,170,
+144,167, 0, 0, 0, 2, 0,101,255,238, 4,108, 6, 20, 0, 11, 0, 44, 0, 0, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38,
+ 19, 50, 53, 17, 51, 17, 6, 55, 54, 53, 17, 51, 17, 16, 37, 38, 39, 6, 35, 32, 17, 52, 55, 38, 55, 54, 23, 22, 7, 6, 0, 23,
+ 20, 1, 98, 36, 28, 32, 32, 36, 28, 32, 48,110,184, 1,117,104,184,254,224,105,103,101,143,254,222,152,138, 2, 2,228,237, 1,
+ 2,254,214, 2, 3,210, 32, 32, 37, 27, 34, 30, 37, 27,252,179,167, 1, 52,254,203,175, 6, 5,165, 4,232,251, 24,254,192, 3,
+ 1, 73, 74, 1, 61,240,166, 37,158,249, 1, 1,219,143,254,170,144,167, 0, 0, 0, 1, 0, 16,255,227, 4, 96, 4, 96, 0, 23,
+ 0, 0, 1, 51, 17, 16, 51, 50, 25, 1, 51, 17, 16, 33, 34, 39, 6, 35, 34, 53, 52, 51, 50, 7, 50, 53, 1, 99,184,189,208,184,
+254,120,240, 41, 51,182,198,156,144, 2, 41, 4, 96,253, 44,254,237, 1, 19, 2,212,252,197,254,190, 56, 56,156,150,123,139, 0,
+ 0, 2, 0,114,255,238, 4, 92, 6, 20, 0, 11, 0, 44, 0, 0, 1, 50, 54, 53, 52, 38, 39, 38, 6, 21, 20, 22, 3, 20, 33, 32,
+ 25, 1, 51, 17, 16, 37, 36, 17, 52, 53, 54, 55, 38, 55, 18, 5, 22, 21, 20, 7, 6, 39, 22, 23, 22, 55, 21, 7, 6, 1,215, 36,
+ 28, 33, 31, 37, 27, 32,130, 1, 47, 1, 64,184,254, 8,254, 15, 3,162,166, 1, 1, 1,108,180,192,126, 46, 2, 90, 65,144,141,
+147, 3,164, 32, 32, 36, 27, 1, 1, 33, 32, 36, 28,253,140,174, 1,184, 3,218,252, 38,253,180, 1, 1, 1, 61, 2, 1,145, 81,
+109,234, 1, 46, 2, 1,176,186, 2, 1,117,189, 71, 52, 12,161, 23, 24, 0, 0, 0, 2, 0,100,255,238, 4,109, 4,140, 0, 11,
+ 0, 43, 0, 0, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 5, 38, 33, 32, 19, 18, 33, 32, 23, 7, 38, 7, 4, 23, 22, 5,
+ 4, 3, 2, 37, 36, 38, 55, 54, 23, 22, 21, 20, 7, 22, 55, 54, 1, 61, 36, 28, 32, 32, 36, 28, 32, 2, 87, 1,254,189,253,243,
+ 1, 1, 2, 21, 1, 54,184,116,177,211,254,169, 3, 5, 1,109, 1,225, 3, 2,254, 50,254,167,223, 1, 1,210,224, 22, 74,142,
+219, 1, 88, 32, 32, 36, 28, 32, 32, 36, 28, 16,232, 1, 56, 1, 36,220,123,188, 1, 2,138,158, 1, 1,254,144,254,154, 1, 1,
+178,123,204, 1, 1,209, 78, 20, 38, 1, 2, 0, 0, 2, 0, 96,255,238, 4,112, 4,141, 0, 11, 0, 46, 0, 0, 37, 34, 6, 21,
+ 20, 22, 51, 50, 54, 53, 52, 38, 1, 4, 25, 1, 20, 37, 38, 2, 39, 38, 7, 22, 7, 6, 39, 38, 55, 18, 33, 50, 18, 55, 54, 53,
+ 17, 16, 33, 34, 7, 6, 7, 39, 54, 55, 54, 1, 70, 37, 27, 32, 32, 36, 28, 32, 1, 8, 2, 2,254,244,232, 87,139, 68, 12,227,
+ 2, 2,207,250, 1, 1, 1, 78,232, 98,102, 80,254,198,229, 39, 26, 2,183, 6, 17, 71,248, 33, 31, 36, 28, 32, 32, 36, 27, 3,
+149, 1,254,137,253,212,250, 1, 1, 1,221, 2, 1, 84, 1,183,214, 1, 1,235, 1,137,254, 30, 2, 2,174, 1,168, 1, 24,114,
+ 74, 99, 20,111, 60,249, 0, 0, 0, 2, 0,111,255,228, 4, 98, 4,123, 0, 5, 0, 31, 0, 0, 1, 34, 20, 51, 50, 54, 1, 18,
+ 33, 32, 25, 1, 16, 37, 38, 36, 39, 52, 23, 50, 23, 22, 7, 22, 51, 32, 53, 17, 52, 33, 32, 7, 1, 80, 64, 64, 60, 8,254,244,
+ 41, 1,189, 1,244,254, 34,240,254,220, 1,229,217, 4, 1, 70, 25,127, 1, 30,254,204,254,233, 24, 1, 84,128,128, 1,206, 1,
+ 89,254,215,253,184,254,217, 2, 1,156,143,211, 1,215, 61, 73, 8,216, 1,196,204,213, 0, 0, 0, 3, 0, 97,255,238, 5, 35,
+ 5,156, 0, 11, 0, 50, 0, 58, 0, 0, 37, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 37, 17, 6, 33, 36, 55, 54, 33, 32, 23,
+ 54, 39, 38, 39, 55, 22, 23, 22, 7, 17, 20, 37, 38, 2, 39, 38, 7, 22, 7, 6, 39, 38, 55, 18, 33, 50, 18, 55, 54, 1, 32, 53,
+ 52, 33, 32, 21, 20, 1, 72, 38, 26, 32, 32, 36, 28, 32, 2, 74, 70,254,234,254, 10, 2, 2, 1,242, 1,142,114, 28, 2, 11, 99,
+158,128, 2, 2,178,254,244,232, 88,138, 68, 12,226, 2, 2,206,251, 1, 2, 1, 78,232, 98,102, 80,254,164, 1,116,254,140,254,
+182,248, 33, 31, 36, 28, 32, 32, 36, 27, 61, 1,153, 14, 1,252,233,154, 49, 18, 84,132,118,174,160,146,151,253,195,250, 1, 1,
+ 1,221, 2, 1, 84, 1,183,214, 1, 1,235, 1,137,254, 30, 2, 2, 2,209, 69,109, 77,100, 0, 0, 3, 0, 19,255,231, 4,189,
+ 4,154, 0, 6, 0, 13, 0, 54, 0, 0, 0, 34, 21, 6, 51, 50, 55, 36, 34, 21, 6, 51, 50, 55, 3, 36, 17, 16, 55, 38, 55, 54,
+ 23, 22, 7, 14, 1, 17, 20, 51, 54, 53, 17, 6, 43, 1, 38, 55, 54, 51, 50, 23, 54, 55, 54, 25, 1, 35, 17, 52, 35, 34, 7, 19,
+ 16, 1, 26,128, 1, 65, 63, 1, 1,145,128, 1, 65, 63, 1,238,254, 96,130,140, 1, 1,198,190, 1, 1,186,223,225, 20, 29, 2,
+185, 1, 1,166,162, 53, 64, 86,247,184, 67, 63, 47, 1, 4, 26, 64, 64, 64, 76, 64, 64, 64,252, 2, 1, 1, 69, 1, 62,169, 47,
+153,181, 1, 1,178,125,204,254,159,182, 1,181, 2, 8, 9, 6,183,169, 99, 98, 1, 4,254,186,252,169, 3, 87,157, 90,253,154,
+254,179, 0, 0, 0, 3, 0,119,255,238, 4,106, 4,141, 0, 11, 0, 37, 0, 45, 0, 0, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53,
+ 52, 38, 55, 36, 17, 16, 5, 4, 25, 1, 20, 37, 38, 39, 38, 55, 54, 23, 22, 21, 20, 7, 22, 51, 32, 53, 17, 6, 19, 52, 5, 4,
+ 7, 6, 5, 4, 1, 92, 36, 28, 32, 32, 37, 27, 32,244,254, 7, 1,249, 1,250,254, 10,202,170,134, 1, 1,220,237, 61, 65, 56,
+ 1, 41, 83, 85,254,196,254,192, 1, 1, 1, 66, 1, 60, 1, 83, 32, 32, 37, 27, 34, 30, 36, 28,208, 1, 1, 51, 1, 54, 1, 1,
+254,209,253,140,251, 2, 1, 72, 57,170,215, 1, 1,216, 71, 41, 35,175, 1, 36, 54, 1, 55,156, 1, 1,154,159, 1, 1, 0, 0,
+ 0, 2, 0, 84,255,238, 4,218, 4,216, 0, 11, 0, 54, 0, 0, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 1, 36, 39, 38,
+ 37, 36, 55, 54, 33, 50, 23, 22, 51, 50, 19, 23, 2, 7, 6, 39, 38, 35, 34, 23, 22, 5, 4, 3, 2, 37, 36, 39, 38, 55, 54, 23,
+ 22, 21, 20, 21, 6, 7, 22, 1, 50, 36, 28, 32, 32, 37, 27, 32, 1, 0, 1, 84, 1, 1,254,192,253,254, 3, 3, 1,158,136, 92,
+111, 69,104, 64,148, 77,243,135,113, 75, 85,210, 5, 5, 1, 80, 1,230, 1, 1,253,240,254,236,136,110, 1, 1,224,215, 1, 94,
+153, 1,139, 32, 32, 37, 27, 34, 30, 37, 27,254,249, 2,254,195, 43, 68,231,252, 89,108, 1, 4, 48,254,149, 1, 1,121, 80, 94,
+100, 54, 81,254,193,254,113, 2, 1,116, 94,125,223, 1, 1,214, 2, 1, 93, 70, 28, 0, 0, 0, 0, 2, 0, 48,255, 38, 4,169,
+ 4,161, 0, 3, 0, 36, 0, 0, 0, 34, 20, 50, 3, 39, 1, 0, 39, 38, 15, 1, 6, 39, 36, 3, 2, 33, 32, 7, 6, 39, 38, 53,
+ 34, 21, 20, 51, 50, 63, 1, 54, 23, 22, 21, 20, 1, 2, 42,128,128,202,129, 2, 43, 1, 24, 61, 25,120,165,130,215,254,226, 7,
+ 9, 1,136, 1, 15, 1, 1,211,212, 35,101,115, 90,140,175,104,224,254,225, 4, 13,128,251,153,134, 2, 78, 1, 41, 61, 25,137,
+187,147, 1, 1, 1,109, 1,144,206,216, 3, 4,205,205,195,100,157,196, 2, 5,189,157,254,207,255,255, 0, 90,255,229, 4,101,
+ 4,128, 16, 39, 4,101, 4,209,250,201, 16, 7, 4,101, 4,209,253,117, 0, 0, 0, 2,251,137, 5, 28,255,148, 7, 11, 0, 19,
+ 0, 26, 0, 0, 3, 2, 33, 32, 38, 55, 54, 23, 50, 7, 6, 7, 22, 51, 36, 53, 52, 39, 55, 22, 4, 52, 7, 34, 21, 6, 23,109,
+ 2,254, 5,254,182,195, 1, 1,229,241, 3, 1, 35, 33, 65, 1, 28, 86,138,168,253, 28, 66, 56, 1, 63, 6, 29,254,255,168,107,
+217, 1,216, 80, 36, 4, 1, 85, 46, 70,138,143,140,126, 1, 62, 61, 1, 0, 0, 0, 2, 0,157, 0, 0, 4, 33, 4,123, 0, 16,
+ 0, 22, 0, 0, 1, 32, 25, 1, 35, 17, 16, 35, 34, 7, 50, 21, 20, 35, 34, 53, 16, 18, 20, 51, 50, 52, 35, 2,106, 1,183,184,
+255,164, 61,218,229,225,166, 59, 67, 62, 4,123,254,106,253, 27, 2,203, 1, 25, 86,193,199,199, 1,174,254,137,110,110, 0, 0,
+255,255,252,197, 0, 0, 4, 33, 6,114, 16, 38, 4,102, 0, 0, 16, 7, 4,117,251, 47, 0, 0, 0, 1, 0, 83, 4,236, 4,126,
+ 7,105, 0, 17, 0, 0, 1, 20, 33, 21, 32, 17, 16, 33, 32, 17, 16, 33, 53, 32, 55, 52, 33, 32, 1, 18, 1, 36,254, 30, 2, 38,
+ 2, 4,254, 62, 1, 2, 2,254,186,254,152, 6, 37,187,126, 1, 63, 1, 62,254,194,254,193,126,187,197, 0, 0, 0, 1, 0, 83,
+ 4,230, 5, 19, 7,105, 0, 21, 0, 0, 1, 20, 33, 21, 32, 17, 16, 33, 32, 17, 20, 7, 51, 21, 33, 61, 1, 32, 55, 52, 33, 32,
+ 1, 17, 1, 37,254, 29, 2, 38, 2, 4, 62,212,253,169, 1, 1, 2,254,186,254,152, 6, 37,187,126, 1, 63, 1, 62,254,194,119,
+ 74,132, 6,126,187,197, 0, 0, 0, 2, 0, 83, 4,236, 4,126, 7,105, 0, 17, 0, 21, 0, 0, 1, 20, 33, 21, 32, 17, 16, 33,
+ 32, 17, 16, 33, 53, 32, 55, 52, 33, 32, 5, 21, 35, 53, 1, 18, 1, 36,254, 30, 2, 38, 2, 4,254, 62, 1, 2, 2,254,186,254,
+152, 1,222,238, 6, 37,187,126, 1, 63, 1, 62,254,194,254,193,126,187,197, 78,220,220, 0, 0, 0, 2, 0, 83, 4,230, 5, 19,
+ 7,105, 0, 21, 0, 25, 0, 0, 1, 20, 33, 21, 32, 17, 16, 33, 32, 17, 20, 7, 51, 21, 33, 61, 1, 32, 55, 52, 33, 32, 5, 21,
+ 35, 53, 1, 17, 1, 37,254, 29, 2, 38, 2, 4, 62,212,253,169, 1, 1, 2,254,186,254,152, 1,221,238, 6, 37,187,126, 1, 63,
+ 1, 62,254,194,119, 74,132, 6,126,187,197, 84,220,220, 0, 0, 0, 2, 1,207,253, 51, 3,135,255,178, 0, 4, 0, 21, 0, 0,
+ 4, 34, 20, 51, 54, 3, 54, 53, 52, 39, 6, 35, 34, 53, 52, 51, 50, 23, 22, 21, 20, 7, 2,191,130, 65, 65, 92,144, 5, 40, 68,
+179,170,101, 78, 91,204,188,129, 1,254,207,111, 91, 17, 16, 36,158,186, 78, 91,139,117,214, 0, 0, 2, 1,120,253,142, 3,153,
+255,175, 0, 5, 0, 26, 0, 0, 4, 34, 20, 51, 50, 53, 19, 34, 53, 52, 55, 38, 53, 52, 50, 21, 20, 6, 21, 20, 51, 50, 53, 17,
+ 51, 17, 20, 2, 5, 44, 23, 21,114,243, 62, 74,234,109,130,158,132,178, 44, 21,254, 87,146,115, 62, 10, 91,121,117, 63,123, 69,
+ 66, 88, 1, 70,254,186,195, 0, 0, 2, 0, 68, 5, 28, 4,141, 7, 11, 0, 20, 0, 27, 0, 0, 1, 22, 7, 39, 54, 53, 54, 37,
+ 34, 7, 22, 7, 6, 7, 6, 39, 38, 55, 54, 33, 32, 0, 52, 7, 34, 23, 20, 51, 4,140, 1,168,138, 86, 1,254,165, 65, 33, 46,
+ 10, 21,217,229, 1, 1,123,120, 1, 26, 2, 57,252,225, 60, 63, 1, 56, 6, 10, 95,143,138, 70, 46, 85, 1, 4, 68, 87,176, 1,
+ 1,217, 84, 95, 96,254,174,126, 1, 63, 61, 0, 0, 2,255,240,253,199, 4,225,255,177, 0, 7, 0, 26, 0, 0, 19, 50, 53, 52,
+ 35, 34, 21, 20, 5, 34, 2, 35, 22, 21, 20, 35, 34, 53, 16, 33, 50, 18, 51, 50, 55, 23, 6,176, 48, 48, 43, 2,201,218,172,184,
+ 92,196,184, 1, 76,222,222, 96, 93,166,134,191,254, 78, 48, 47, 46, 49,105, 1, 51, 32,114,191,167, 1, 67,254,208,198,114,240,
+ 0, 1, 2, 14, 4,241, 2,195, 6, 86, 0, 3, 0, 0, 1, 51, 17, 35, 2, 14,180,180, 6, 86,254,155, 0, 0, 0, 2, 0, 86,
+ 4,224, 4,123, 7, 33, 0, 7, 0, 27, 0, 0, 19, 22, 39, 54, 7, 34, 23, 6, 37, 20, 2, 41, 1, 53, 54, 53, 6, 55, 52, 23,
+ 22, 29, 1, 20, 7, 32, 54, 53,241, 42, 1, 1, 42, 44, 2, 2, 3,181,214,254,132,254, 85,144,183, 1,157,145, 71, 1,177,243,
+ 6,109, 1, 43, 43, 2, 41, 44,125,229,254,221,133, 46,112, 7,157,136, 1, 1,131,183, 92, 40,141,250, 0, 0, 0, 1, 0, 95,
+ 4,199, 5, 80, 6,243, 0, 52, 0, 0, 1, 34, 17, 16, 33, 50, 22, 55, 54, 55, 54, 51, 50, 21, 20, 7, 22, 55, 54, 55, 51, 6,
+ 7, 6, 33, 35, 53, 54, 53, 52, 35, 34, 7, 6, 39, 38, 39, 38, 35, 34, 21, 20, 59, 1, 38, 53, 52, 51, 22, 7, 6, 7, 6, 1,
+ 80,240, 1, 36, 50,126, 42, 38, 74, 72, 72,220,158,132, 66, 80, 4,154, 2,104, 40,254,226,196,208, 76, 24, 66, 68, 92,106, 36,
+ 62, 24,146,102, 62, 46, 96,104, 2, 2, 62, 52, 4,200, 1, 20, 1, 23,130, 1, 1, 65, 63,215,126, 61, 4, 13, 16,104,130, 92,
+ 36,133,107, 98, 56, 58, 59, 1, 1, 45, 70,144,161, 2, 95, 90, 1,107,102, 50, 41, 0, 0, 0, 0, 1, 1, 73, 4,224, 3,136,
+ 7, 30, 0, 11, 0, 0, 1, 53, 51, 53, 51, 21, 51, 21, 35, 21, 35, 53, 1, 74,216,142,216,216,142, 5,184,142,216,216,142,216,
+216, 0, 0, 0,255,255,255,240, 5, 23, 4,225, 7, 1, 16, 7, 4,111, 0, 0, 7, 80, 0, 0, 0, 2, 1,150, 4,246, 3, 59,
+ 6,114, 0, 7, 0, 12, 0, 0, 1, 52, 51, 50, 21, 20, 35, 34, 18, 20, 51, 50, 52, 1,150,212,208,212,208,132, 76, 84, 5,190,
+180,180,200, 1, 16,144,144, 0, 0, 1, 0,160, 0, 0, 4, 51, 4,122, 0, 21, 0, 0, 1, 2, 33, 32, 17, 52, 55, 51, 6, 21,
+ 16, 33, 32, 17, 52, 39, 36, 3, 51, 22, 23, 4, 4, 51, 1,254, 49,254, 61, 80,190, 85, 1, 15, 1, 17,189,254,220, 2,181, 1,
+126, 1,105, 1,239,254, 17, 1,201,105, 98, 99, 87,254,183, 1, 79,214, 74,102, 1, 20,161, 51,130, 0, 0, 0, 0, 2, 0,158,
+ 0, 0, 4, 52, 6, 22, 0, 18, 0, 26, 0, 0, 1, 16, 33, 32, 3, 18, 37, 53, 54, 39, 38, 53, 51, 20, 23, 22, 29, 1, 4, 3,
+ 18, 33, 4, 17, 16, 33, 32, 4, 52,254, 60,254, 49, 3, 3, 1,131, 1,163,141,181,126,161, 1,107,188, 1,254,239,254,241, 1,
+ 22, 1, 9, 2, 32,253,224, 2, 33, 1,171, 84,138,120, 28, 27,189, 89, 27, 57,185,144,118,254,119, 1,115, 3,254,149,254,107,
+ 0, 2, 0,110,254, 87, 4, 98, 4, 21, 0, 25, 0, 33, 0, 0, 37, 16, 33, 32, 17, 18, 37, 54, 55, 52, 35, 34, 23, 20, 23, 7,
+ 38, 53, 16, 33, 32, 3, 20, 7, 21, 4, 3, 16, 37, 32, 3, 16, 37, 4, 4, 97,254, 9,254, 4, 1, 2, 28,108, 2,213,183, 1,
+ 15,137, 46, 1, 95, 1,139, 1,122, 1, 45,179,254,190,254,182, 2, 1, 70, 1, 72, 43,254, 44, 1,212, 1,205, 5, 83,169,142,
+139, 46, 43, 82, 76,111, 1, 9,254,219,164, 84, 20,110,254,181, 1, 66, 1,254,189,254,192, 1, 1, 0, 0, 0, 0, 2, 0, 55,
+254, 87, 4,154, 4, 12, 0, 33, 0, 44, 0, 0, 23, 54, 55, 53, 0, 17, 16, 5, 50, 23, 51, 54, 51, 32, 17, 21, 16, 33, 32, 17,
+ 53, 52, 43, 1, 34, 17, 21, 16, 0, 23, 7, 38, 36, 7, 1, 53, 52, 43, 1, 34, 29, 1, 16, 51, 50,221, 40, 84,254,222, 1, 88,
+ 91, 80, 20, 60,170, 1,102,254,166,254,170, 73, 43,129, 2,121,104,202, 90,254,203,116, 2,212,149, 71,119,186,153,225, 44, 18,
+ 11, 1, 22, 1,200, 1,198, 1, 98, 98,254, 43, 20,254, 6, 2, 15,234, 93,254,196,109,254, 76,254,255,200, 1,167, 14, 86, 3,
+ 3,212,241,182,247,254,232, 0, 0, 1, 0,160,254, 87, 4, 51, 4, 22, 0, 26, 0, 0, 5, 2, 33, 32, 17, 52, 55, 51, 6, 21,
+ 16, 33, 32, 53, 17, 16, 32, 21, 20, 23, 7, 38, 53, 16, 5, 32, 19, 4, 51, 1,254, 73,254, 37,141,188,144, 1, 36, 1, 6,254,
+ 38, 62,176, 56, 1,150, 1,157, 1, 32,254,119, 1,146,143,106,115,133,254,251,241, 2,164, 1, 13,222,111,101, 1, 75,133, 1,
+114, 1,254,100, 0, 1, 0,158,254, 87, 4, 50, 4, 21, 0, 39, 0, 0, 5, 16, 33, 32, 3, 54, 55, 51, 6, 21, 16, 33, 32, 61,
+ 1, 52, 43, 1, 53, 51, 22, 55, 52, 35, 32, 7, 22, 23, 35, 38, 53, 16, 33, 32, 17, 20, 7, 21, 22, 17, 4, 50,254, 52,254, 58,
+ 2, 2,105,192,112, 1, 13, 1, 20,237, 73, 73,226, 1,225,254,252, 1, 1, 45,161, 60, 1,177, 1,158,229,237, 45,254,132, 1,
+152, 93,109,120, 82,254,246,223, 98,243,140, 1,240,243,202, 88,120, 82,126, 1, 88,254,123,209, 92, 20, 43,254,254, 0, 0, 0,
+ 0, 3, 0,158, 0, 0, 4, 50, 6, 20, 0, 17, 0, 24, 0, 32, 0, 0, 1, 2, 33, 32, 17, 16, 55, 53, 38, 55, 2, 33, 32, 17,
+ 6, 7, 21, 4, 3, 16, 5, 4, 19, 2, 32, 3, 52, 39, 34, 21, 6, 23, 54, 4, 50, 1,254, 53,254, 56,200,200, 1, 1, 1, 84,
+ 1, 87, 1, 92, 1, 70,185,254,235,254,245, 1, 1, 2, 32,205,190,168, 1,186,175, 1,248,254, 8, 1,249, 1, 73, 74, 20, 58,
+233, 1, 81,254,189,155, 85, 20, 45,254, 92, 1,112, 2, 1,254,144,254,152, 4, 33,212, 2,214,218, 1, 1, 0, 0, 2, 0, 55,
+ 0, 0, 4,154, 4, 11, 0, 26, 0, 37, 0, 0, 1, 21, 16, 7, 35, 54, 17, 53, 16, 43, 1, 34, 29, 1, 16, 33, 32, 17, 53, 16,
+ 33, 50, 23, 51, 54, 51, 32, 1, 17, 54, 35, 7, 38, 17, 21, 16, 51, 50, 4,154,239,162,212,132, 33, 83,254,203,254,135, 1,125,
+146, 71, 14, 74,116, 1, 65,253,170, 2, 70, 87,180,165,172, 2, 72, 67,254,162,167,174, 1, 66,117, 1, 25,182,220,254, 20, 2,
+ 7, 30, 1,230, 99, 99,253,121, 1,105,145, 1, 1,254,239,189,254,225, 0, 0, 0, 1, 0,159, 0, 0, 4, 51, 4, 21, 0, 17,
+ 0, 0, 1, 16, 7, 35, 18, 3, 16, 33, 32, 17, 16, 19, 35, 38, 19, 2, 33, 32, 4, 50,240,146,201, 1,254,252,254,230,198,148,
+238, 2, 2, 1,210, 1,195, 2, 35,254,165,200, 1, 4, 1, 31, 1, 99,254,160,254,230,254,244,207, 1, 90, 1,236, 0, 0, 0,
+ 0, 1, 0,158,254, 89, 4, 52, 4, 2, 0, 31, 0, 0, 5, 2, 33, 32, 17, 52, 55, 51, 6, 21, 16, 33, 32, 61, 1, 16, 43, 1,
+ 53, 51, 50, 53, 52, 33, 53, 32, 17, 22, 5, 21, 4, 19, 4, 52, 1,254, 67,254, 40,112,173, 98, 1, 29, 1, 2,238, 65, 65,228,
+254, 90, 2, 90, 1,254,245, 1, 26, 2, 30,254,119, 1,167,139,102,113,128,254,230,252, 50, 1, 16,152,198,230,154,254,128,208,
+ 49, 20, 49,254,216, 0, 0, 0, 0, 1, 0,160,254, 87, 4, 50, 4, 21, 0, 27, 0, 0, 1, 32, 17, 16, 0, 21, 35, 38, 36, 7,
+ 39, 54, 63, 1, 2, 17, 16, 33, 32, 17, 20, 6, 23, 7, 38, 54, 53, 16, 2,108,254,237, 2, 95,190, 36,254,179, 94, 77, 62,112,
+ 13,249, 1,204, 1,198,118, 20,159, 20, 92, 3,136,254,189,254, 89,254, 49,120,176, 79,104, 95, 91, 13, 14, 1, 5, 1,130, 1,
+203,254, 41,101,181,156, 1,157,168,117, 1, 71, 0, 2, 0,158, 0, 0, 4, 52, 6, 21, 0, 21, 0, 28, 0, 0, 1, 16, 33, 32,
+ 17, 16, 33, 50, 23, 51, 17, 52, 33, 6, 29, 1, 35, 53, 16, 33, 32, 17, 3, 16, 32, 17, 2, 33, 32, 4, 52,254, 69,254, 37, 1,
+203,196, 68, 20,254,228,232,187, 1,163, 1,203,188,253,226, 1, 1, 30, 1, 1, 1,239,254, 17, 2, 13, 2, 9,125, 1, 2,237,
+ 1,152, 62, 62, 1, 38,254,134,253, 84, 1,151,254,137,254,130, 0, 2, 0,158, 0, 0, 4, 51, 5,251, 0, 17, 0, 25, 0, 0,
+ 1, 18, 33, 32, 25, 1, 2, 41, 1, 21, 33, 34, 21, 17, 51, 54, 51, 4, 3, 16, 33, 32, 17, 16, 37, 4, 4, 50, 1,254, 50,254,
+ 58, 1, 1, 77, 1,206,254, 30,141, 35, 64,184, 1,205,185,254,234,254,239, 1, 17, 1, 22, 2, 36,253,220, 1,234, 2,182, 1,
+ 91,143,176,254,218,128, 1,254, 12, 1,103,254,133,254,132, 1, 1, 0, 0, 0, 0, 1, 0, 55, 0, 0, 4,154, 4, 11, 0, 35,
+ 0, 0, 1, 20, 7, 35, 54, 53, 17, 52, 7, 35, 34, 21, 17, 35, 17, 52, 43, 1, 34, 21, 17, 6, 23, 35, 38, 61, 1, 16, 33, 50,
+ 23, 51, 54, 51, 32, 17, 4,154,188,179,179,153, 75, 64,160, 66, 77,148, 2,203,194,199, 1,123,104, 73, 17, 70, 96, 1,128, 1,
+198,236,218,192,207, 1, 25,215, 1,207,254,235, 1, 21,207,228,254,252,214,192,225,236,102, 1,216,104,104,254, 38, 0, 0, 0,
+ 0, 1, 0,159, 0, 0, 4, 52, 6, 15, 0, 33, 0, 0, 1, 16, 33, 32, 19, 52, 55, 51, 6, 21, 16, 33, 32, 17, 16, 33, 35, 53,
+ 51, 50, 55, 52, 37, 36, 53, 51, 20, 23, 4, 17, 20, 7, 21, 22, 4, 52,254, 68,254, 39, 1,101,175, 91, 1, 31, 1, 0,254,236,
+ 63, 82,215, 1,254,233,254,220,172,239, 1, 87,186,232, 1,218,254, 38, 1,178,183, 90,126,147,254,223, 1, 73, 1, 74,135,200,
+149, 33, 54,176, 71, 41, 41,254,251,203, 61, 20,105, 0, 0, 0, 0, 1, 0,159,254, 89, 4, 51, 4, 50, 0, 23, 0, 0, 5, 2,
+ 33, 32, 3, 51, 6, 33, 32, 25, 1, 5, 21, 22, 21, 16, 5, 53, 32, 39, 18, 37, 53, 37, 4, 51, 1,254, 48,254, 62, 1,187, 1,
+ 1, 4, 1, 39,254, 77,221,253,241, 1,104, 1, 1,254,152, 3,148, 18,254,107, 1,111,227, 1, 11, 3,168, 52, 60, 89,238,254,
+206, 1,167,140, 1, 3, 75,130,129, 0, 0, 0, 0, 1, 0, 55, 0, 0, 4,154, 6, 21, 0, 41, 0, 0, 1, 21, 20, 7, 35, 54,
+ 61, 1, 16, 43, 1, 34, 21, 17, 35, 19, 54, 43, 1, 34, 17, 21, 20, 23, 35, 38, 17, 53, 52, 0, 37, 23, 4, 3, 51, 55, 50, 23,
+ 51, 54, 51, 32, 4,154,208,197,216,132, 88, 65,160, 1, 1, 74,124,103,230,210,210, 1, 90, 1,167, 25,254,150,218, 24, 86,165,
+ 72, 15, 73,160, 1, 58, 2, 84,142,244,210,184,219,193, 1, 42,167,254,195, 1, 61,167,254,219,165,252,184,210, 1, 24,103,251,
+ 2, 78,123,148, 82,254,159, 61, 98, 98, 0, 0, 0, 1, 0,159, 0, 0, 4, 51, 5,241, 0, 21, 0, 0, 1, 16, 33, 32, 25, 1,
+ 51, 17, 16, 33, 32, 17, 52, 36, 53, 52, 55, 23, 6, 21, 20, 4, 4, 51,254, 61,254, 47,182, 1, 27, 1, 9,254,241,206, 87,142,
+ 1, 50, 2, 3,253,253, 2, 3, 3,238,252, 18,254,142, 1,114,175,161,103,148,125,124, 56, 59, 67,188, 0, 0, 0, 2, 0, 45,
+254, 89, 4,164, 4,234, 0, 10, 0, 21, 0, 0, 19, 16, 37, 3, 51, 3, 4, 17, 2, 33, 32, 19, 16, 33, 32, 17, 16, 37, 19, 35,
+ 19, 4, 45, 1,250, 15,166, 15, 1,245, 2,253,202,253,193,188, 1,127, 1,134,254,193, 15,165, 14,254,194, 1, 34, 2,117, 82,
+ 1, 1,254,251, 78,253,133,253, 61, 2,201,253,195, 2, 61, 1,231,111,253,229, 2, 26,110, 0, 0, 1, 0, 55,254, 89, 4, 74,
+ 4, 12, 0, 41, 0, 0, 5, 2, 33, 32, 17, 52, 55, 51, 6, 21, 16, 33, 32, 53, 17, 52, 35, 6, 17, 7, 35, 39, 16, 39, 14, 1,
+ 35, 34, 39, 55, 22, 51, 50, 54, 51, 50, 23, 51, 54, 23, 36, 19, 4, 74, 2,254, 77,254, 31,145,179,138, 1, 39, 1, 3,130,132,
+ 10,133, 9,110, 62, 62, 62, 72, 83, 50, 62, 43, 51, 60, 76,103, 69, 20, 72,137, 1, 43, 1, 43,254,132, 1,164,159, 90,123,126,
+254,232,240, 2,234,191, 1,254,242,193,193, 1, 14, 1, 1,134, 95,181, 98, 99,184,184, 1, 1,254,179, 0, 0, 0, 2, 0, 55,
+254, 87, 4,157, 4, 11, 0, 45, 0, 56, 0, 0, 5, 16, 33, 35, 32, 17, 51, 20, 59, 1, 32, 61, 1, 52, 39, 35, 53, 51, 54, 61,
+ 1, 52, 43, 1, 34, 29, 1, 16, 33, 4, 17, 53, 16, 33, 50, 23, 51, 54, 51, 32, 17, 20, 7, 21, 22, 21, 1, 52, 43, 1, 34, 17,
+ 21, 16, 51, 50, 17, 4,157,254, 52, 56,254, 82,183,249, 47, 1, 22, 57, 80, 80, 54,100, 83, 59,254,190,254,142, 1,119,138, 67,
+ 17, 96,139, 1, 35,158,161,253,165, 94, 77,162,176,157, 61,254,148, 1,133,247,222,101,166, 2,151, 1,148,182,204,123,202,254,
+ 32, 1, 1,153,128, 1,154, 99, 99,254,109,251, 84, 20, 91,142, 2,171,167,254,250,120,254,215, 1, 5, 0, 0, 0, 1, 0,160,
+254, 87, 4, 49, 5,241, 0, 30, 0, 0, 37, 16, 33, 32, 17, 52, 55, 23, 6, 21, 16, 33, 32, 3, 19, 16, 5, 38, 21, 20, 23, 35,
+ 38, 53, 16, 33, 22, 23, 51, 19, 51, 4, 49,254, 84,254, 27,134,176,125, 1, 41, 1, 1, 1, 2,254,223,197, 82,179, 70, 1,113,
+142,124, 17, 1,173, 67,254, 20, 1,169,132,100, 1,121,113,254,232, 1, 94, 1, 40, 2, 30, 3, 3,164,182, 89,111,160, 1, 49,
+ 1,189, 2,153, 0, 1, 0, 55,254, 86, 4,154, 4, 12, 0, 43, 0, 0, 23, 54, 55, 53, 0, 17, 53, 16, 33, 22, 23, 51, 54, 55,
+ 4, 17, 21, 20, 15, 1, 54, 61, 1, 52, 43, 1, 34, 21, 17, 35, 17, 52, 43, 1, 34, 17, 21, 16, 0, 23, 39, 38, 36, 7,237, 57,
+ 65,254,208, 1, 95,131, 74, 16, 70,149, 1, 76,169,140,120,134,100, 58,160, 65, 76,151, 2,150, 69,203, 25,254,196,130,201, 83,
+ 2, 22, 1, 5, 1, 39, 80, 1,238, 1,103,103, 1, 1,254, 63, 70,244,177, 1,167,174,219,240,175,254,203, 1, 53,175,254,250,
+138,254,141,254,179,216, 1,142,112,122, 0, 0, 0, 1, 0,158,254, 89, 4, 50, 3,247, 0, 26, 0, 0, 5, 16, 33, 32, 17, 51,
+ 16, 5, 36, 61, 1, 35, 6, 35, 32, 17, 16, 37, 51, 4, 21, 16, 33, 32, 53, 17, 51, 4, 50,254, 70,254, 38,188, 1, 30, 1, 7,
+ 20, 88,175,254, 58, 1, 23,216,254,204, 1, 11, 1, 27,179, 47,254,136, 1,144,254,252, 1, 1,240,244, 98, 1,229, 1, 4,167,
+206,221,254,175,235, 2, 9, 0, 0, 2, 0, 55, 0, 0, 4, 52, 6, 20, 0, 31, 0, 39, 0, 0, 1, 16, 33, 32, 3, 16, 37, 22,
+ 23, 51, 17, 52, 35, 34, 29, 1, 35, 53, 52, 35, 34, 21, 35, 16, 51, 50, 23, 51, 54, 51, 32, 11, 1, 2, 33, 32, 19, 2, 33, 50,
+ 4, 52,254, 89,254, 18, 1, 1,198,193, 70, 20,142,141,157,160, 85,155,220,186, 63, 20, 58,172, 1, 46, 2,184, 1,254,233,254,
+247, 1, 1, 1, 56,232, 1,221,254, 35, 2, 13, 2, 8, 1, 1,129, 1, 33,213,210, 33, 35,208,226, 1,108,193,193,254,192,253,
+ 47, 1,133,254,133,254,132, 0, 0, 2, 0,158, 0, 0, 4, 52, 6, 20, 0, 19, 0, 29, 0, 0, 1, 22, 19, 2, 5, 35, 36, 19,
+ 16, 37, 36, 25, 1, 35, 19, 16, 33, 32, 19, 22, 39, 38, 35, 34, 21, 17, 51, 54, 5, 54, 3, 77,230, 1, 1,254,233,178, 1, 14,
+ 1,254,250,254,221,178, 2, 1,112, 1,127, 30, 1,164, 30,217,195, 30, 63, 1, 37, 56, 3,218,104,254,146,254,184,188,199, 1,
+ 65, 1,106, 1, 19,254,197,253,181, 4,190, 1, 86,254,199, 96, 77,191,214,254,228,128, 30,134, 0, 1, 0, 86,254, 89, 4,122,
+ 4, 37, 0, 35, 0, 0, 1, 20, 7, 21, 22, 21, 2, 33, 32, 17, 53, 16, 19, 23, 6, 3, 21, 18, 33, 32, 3, 54, 43, 1, 53, 51,
+ 50, 39, 54, 39, 38, 39, 51, 20, 23, 22, 4, 92,171,201, 2,253,247,253,231,209,145,164, 1, 1, 1, 92, 1, 88, 1, 1,183,184,
+176,164, 1, 1,161,143, 1,183,130,167, 2,133,153, 88, 20,123,191,254, 19, 2,195, 97, 1, 68, 1,100, 76,250,254,219,158,253,
+201, 1,130,218,136,184,119, 47, 46,173,125, 46, 56, 0, 0, 0, 0, 2, 0,158, 0, 0, 4, 52, 5,241, 0, 11, 0, 19, 0, 0,
+ 1, 18, 33, 32, 17, 16, 33, 50, 23, 51, 17, 51, 3, 16, 33, 32, 17, 16, 33, 32, 4, 51, 2,254, 47,254, 58, 1,198,215, 50, 20,
+178,186,254,234,254,246, 1, 9, 1, 23, 2, 5,253,251, 1,253, 2, 25,115, 2, 78,252, 22, 1,128,254,118,254,148, 0, 0, 0,
+ 0, 2, 0,160, 0, 0, 4,156, 6, 20, 0, 31, 0, 39, 0, 0, 19, 2, 33, 50, 23, 51, 54, 51, 50, 17, 35, 52, 35, 34, 29, 1,
+ 35, 53, 52, 35, 34, 21, 17, 51, 54, 55, 32, 17, 2, 5, 32, 17, 55, 18, 51, 36, 3, 18, 5, 32,161, 2, 1, 48,172, 58, 20, 63,
+186,218,153, 85,160,157,141,142, 20, 70,193, 1,193, 1,254, 43,254, 69,186, 1,252, 1, 34, 1, 1,254,249,254,233, 4,212, 1,
+ 64,193,193,254,148,226,208, 35, 33,210,213,254,223,129, 1,253,238,253,253, 1, 2, 15, 38,254, 92, 1, 1,114, 1,133, 1, 0,
+ 0, 2, 0,159,254, 89, 4, 52, 5,241, 0, 37, 0, 45, 0, 0, 5, 16, 33, 32, 19, 52, 55, 23, 6, 21, 20, 5, 32, 3, 52, 39,
+ 38, 39, 7, 32, 17, 16, 33, 23, 17, 51, 17, 22, 23, 51, 21, 35, 20, 15, 1, 22, 23, 22, 1, 20, 51, 22, 39, 54, 35, 38, 4, 52,
+254, 52,254, 54, 2, 81,143, 38, 1, 14, 1, 17, 1,176,113, 3, 89,254,203, 1, 65, 77,157, 94, 1,184,189, 82, 1, 1,172,141,
+253, 66,163,171, 1, 1,162,172, 20,254,109, 1,149,105, 94,105, 36, 73,250, 1, 1, 8,160, 99,111,102, 19, 1, 72, 1, 77, 9,
+ 1,180,254, 1, 59,105,162,105, 55, 72, 65,105, 97, 2, 66,201, 3,204,193, 1, 0, 2, 0,159, 0, 0, 4, 52, 5,241, 0, 11,
+ 0, 19, 0, 0, 1, 2, 33, 32, 25, 1, 51, 17, 51, 54, 51, 4, 3, 16, 33, 32, 17, 16, 33, 32, 4, 52, 1,254, 57,254, 51,171,
+ 41, 74,175, 1,200,187,254,242,254,238, 1, 20, 1, 12, 2, 13,253,243, 2, 13, 3,228,253,161,132, 1,253,248, 1,123,254,131,
+254,134, 0, 0, 0, 1, 0,159,254, 89, 4, 52, 4,215, 0, 31, 0, 0, 37, 16, 33, 32, 17, 52, 55, 23, 6, 21, 16, 5, 32, 17,
+ 54, 39, 38, 39, 53, 37, 53, 5, 53, 51, 17, 5, 21, 37, 21, 20, 23, 22, 4, 52,254, 46,254, 61,107,144, 64, 1, 8, 1, 22, 1,
+194,170, 1,254,185, 1, 71,146, 1, 80,254,176,215,190, 41,254, 48, 1,207,125,140, 89,105, 71,254,190, 1, 1, 66,173,157,171,
+135,160,120,180,128,232,254,243,127,177,134,125, 72,186,183, 0, 0, 1, 0,158, 0, 0, 4, 52, 6, 20, 0, 43, 0, 0, 1, 16,
+ 33, 32, 17, 53, 51, 21, 2, 33, 32, 39, 52, 39, 35, 53, 51, 50, 53, 54, 43, 1, 53, 51, 50, 55, 52, 37, 38, 53, 51, 20, 5, 22,
+ 21, 20, 7, 21, 22, 21, 20, 7, 21, 22, 4, 52,254, 55,254, 51,188, 1, 1, 12, 1, 21, 2,108,251,251,100, 1,101,251,249, 91,
+ 1,255, 0,233,166, 1, 20,233,144,154,148,158, 1,104,254,152, 1,160,101,101,254,236,212,174, 1,150,122,115,152,132, 85, 32,
+ 33,208,120, 26, 26,190,140, 47, 20, 54,137,126, 58, 20, 95, 0, 0, 1, 0,118,254, 89, 4, 51, 6, 20, 0, 61, 0, 0, 5, 2,
+ 33, 32, 17, 16, 19, 54, 3, 51, 18, 3, 6, 3, 18, 33, 50, 39, 52, 39, 35, 53, 51, 54, 53, 52, 43, 1, 53, 51, 50, 53, 52, 7,
+ 35, 53, 51, 50, 53, 38, 39, 38, 39, 51, 20, 23, 22, 23, 6, 7, 21, 22, 23, 6, 7, 21, 22, 23, 6, 7, 21, 22, 4, 51, 1,254,
+ 84,253,240, 55, 54,104,185, 84, 37, 49, 1, 1, 1, 84,251, 2,134,136,136,134,132,138,138,132,134,136,136,134, 1,185,145, 1,
+166,189,156, 1, 1,178,178, 1, 1,178,178, 1, 2,177,178,124,254,213, 1,216, 1, 43, 1, 13,227, 1, 63,254,249,254,229,225,
+254,169,254,179,160,198, 2,142, 1,134,164,138,156,132, 1,145,142, 82, 33, 34,178, 72, 54, 49,152,165, 34, 20, 40,159,187, 30,
+ 20, 38,183,146, 48, 20, 58, 0, 0, 2, 0,160,254,243, 4, 52, 4, 22, 0, 17, 0, 25, 0, 0, 23, 50, 55, 36, 17, 18, 37, 32,
+ 17, 16, 5, 22, 55, 21, 36, 39, 6, 7, 19, 16, 5, 36, 3, 18, 33, 32,201,149, 80,254,242, 3, 1,197, 1,204,254,231, 92,143,
+254,248,150,193,222,144, 1, 15, 1, 18, 1, 1,254,233,254,246, 60, 89,170, 1, 64, 2, 14, 1,253,241,254,192,170, 94, 5,209,
+ 69,194,193, 70, 3, 20,254,196, 85, 85, 1, 60, 1,127, 0, 0, 0, 1, 0,159,254, 87, 4, 52, 4, 21, 0, 29, 0, 0, 5, 2,
+ 5, 32, 17, 55, 23, 7, 18, 33, 32, 17, 53, 16, 5, 35, 53, 51, 32, 19, 39, 5, 21, 35, 17, 37, 16, 5, 4, 17, 4, 52, 1,254,
+ 48,254, 60, 31,180, 21, 1, 1, 10, 1, 14,254,194,114,114, 1, 30, 1, 2,254, 32,173, 3,108,254,236, 1, 20, 20,254,109, 2,
+ 1,149,111, 20, 91,254,249, 1, 7, 32, 1, 43, 1,160, 1,101, 74, 30,204, 1, 93, 29,254, 48,185,113,254,241, 0, 1, 0,159,
+254, 87, 4, 52, 6, 22, 0, 36, 0, 0, 5, 16, 33, 32, 17, 51, 16, 33, 32, 17, 53, 52, 33, 35, 53, 51, 36, 17, 6, 35, 4, 17,
+ 16, 5, 21, 32, 21, 20, 33, 50, 55, 17, 18, 5, 21, 4, 21, 4, 52,254, 52,254, 55,190, 1, 11, 1, 13,254,237,156,156, 1, 20,
+125,143,254, 53, 1,203,254,200, 1, 54,238,221, 1,254,203, 1, 53, 20,254,107, 1,149,254,248, 1, 8, 55,236,157, 11, 1,158,
+ 37, 3, 1,100, 1,133, 1,142,246,210,168,254,248,254,117,105, 20, 62,246, 0, 0, 3, 0,139, 0, 0, 4,124, 6, 21, 0, 23,
+ 0, 31, 0, 39, 0, 0, 1, 21, 16, 33, 32, 17, 16, 37, 33, 53, 33, 36, 17, 16, 33, 32, 17, 21, 51, 21, 35, 21, 51, 21, 37, 33,
+ 32, 21, 20, 33, 32, 53, 1, 20, 41, 1, 53, 52, 33, 32, 4, 10,254, 73,254, 56, 1,196, 1, 17,254,239,254, 60, 1,204, 1,179,
+114,114,114,254,228,254,239,254,250, 1, 14, 1, 9,253,233, 1, 6, 1, 17,254,247,254,242, 2, 5,182,254,177, 1, 79, 1,102,
+ 2,161, 1, 1,107, 1, 81,254,175,216,148,161,178, 30,206,201,211, 3, 99,214,216,195, 0, 0, 0, 2, 0, 55,254, 88, 4,154,
+ 4, 22, 0, 33, 0, 44, 0, 0, 1, 16, 33, 34, 39, 35, 21, 2, 33, 53, 50, 39, 17, 52, 35, 7, 38, 21, 17, 20, 51, 21, 36, 17,
+ 53, 16, 33, 50, 23, 51, 54, 51, 4, 17, 3, 17, 52, 43, 1, 34, 21, 17, 20, 51, 50, 4,154,254,205,126, 26, 15, 11,254,179,183,
+ 9, 77, 97,115,128,254,194, 1, 49,183, 68, 16, 62,182, 1, 51,189,136, 76, 73,167,118, 1,150,254,106,116,152,254,124,142,231,
+ 3, 9,178, 1, 1,189,254,193,217,148, 3, 1,120,240, 1,140,145,145, 1,254,117,254,174, 1,161,175,167,254,131,211, 0, 0,
+ 0, 1, 0,107,254, 89, 4,102, 4, 22, 0, 31, 0, 0, 33, 2, 33, 32, 3, 16, 37, 36, 53, 52, 35, 34, 7, 23, 7, 39, 16, 33,
+ 32, 17, 6, 5, 4, 17, 2, 33, 32, 19, 52, 39, 55, 22, 4,102, 1,253,245,254, 18, 1, 1, 71, 1, 68,152,181, 1, 5,165, 10,
+ 1, 96, 1, 85, 1,254,175,254,200, 1, 1, 54, 1, 73, 1, 64,154, 98,254, 89, 1,167, 1,115,114,103,127,188,159, 56, 21, 65,
+ 1, 58,254,168,212,131, 77,254,238,254,220, 1, 41,123, 54, 92,108, 0, 0, 0, 0, 1, 0,161,254, 89, 4, 52, 4, 40, 0, 27,
+ 0, 0, 19, 51, 17, 22, 33, 32, 17, 52, 37, 55, 4, 19, 16, 37, 35, 34, 39, 35, 21, 2, 37, 32, 17, 51, 2, 33, 32, 17,161,173,
+ 1, 1, 35, 1, 7,254,249,171, 1, 22, 1,254, 62, 2,185, 85, 20, 2, 1, 38, 1, 7,187, 1,254, 59,254, 51, 3,254,253,204,
+191, 1, 48,253,177, 63,226,254,245,254, 55, 1, 89,227,254,251, 1, 1, 4,254,112, 1,140, 0, 0, 2, 0,109,254, 87, 4, 99,
+ 4, 36, 0, 22, 0, 30, 0, 0, 19, 2, 33, 4, 17, 16, 5, 4, 21, 20, 23, 54, 61, 1, 51, 21, 2, 33, 32, 17, 52, 55, 36, 19,
+ 22, 5, 36, 53, 16, 33, 32,110, 1, 2, 0, 1,246,254,150,254,218,158,195,178, 1,254,140,254,170,239,254,100,191, 1, 1, 63,
+ 1, 59,254,197,254,192, 2,107, 1,185, 1,254, 72,254,235,169,117,158,181, 1, 1,140, 76, 76,254,230, 1, 56,231, 84, 87, 1,
+ 74,255, 38, 41,252, 1, 42, 0, 0, 1, 0,160,255,121, 4, 51, 4, 22, 0, 26, 0, 0, 5, 53, 52, 38, 35, 34, 7, 39, 54, 55,
+ 53, 38, 17, 16, 37, 4, 1, 39, 0, 37, 32, 3, 30, 1, 23, 22, 23, 2,239,116, 95,130, 67,130, 67,116,236, 1,228, 2,167,254,
+121,145, 1, 17,254, 96,254,220, 1, 3, 94,113,178,124,135, 1, 5,121,116, 74,102, 24, 30,173, 1, 73, 1,181, 1, 56,253, 5,
+ 61, 2, 92, 11,254,219,163,202, 98, 42,147, 0, 0, 3, 1, 35, 0, 50, 3,174, 3,227, 0, 3, 0, 7, 0, 11, 0, 0, 1, 51,
+ 21, 35, 5, 51, 21, 35, 5, 51, 21, 35, 1, 35,192,192, 1,209,186,186,254, 47,189,189, 3,227,176,189,174,232,174, 0, 0, 0,
+ 0, 2, 1,149, 2,245, 3, 60, 6, 20, 0, 15, 0, 23, 0, 0, 1, 50, 3, 16, 7, 34, 25, 1, 52, 59, 1, 21, 37, 34, 29, 1,
+ 23, 52, 35, 34, 7, 20, 51, 50, 2,108,208, 1,213,209,185,235,254,254, 70,237,124,112, 1,117,120, 5, 36,254,239,254,227, 1,
+ 1, 30, 1, 76,181, 82, 2, 81,158,194,180,186,201, 0, 0, 0, 0, 3, 0, 41,255,227, 4,176, 4,123, 0, 10, 0, 18, 0, 66,
+ 0, 0, 1, 21, 51, 50, 54, 53, 52, 38, 35, 34, 6, 1, 21, 20, 22, 50, 54, 61, 1, 37, 33, 62, 1, 53, 52, 38, 35, 34, 6, 7,
+ 53, 62, 1, 51, 50, 22, 23, 62, 1, 51, 50, 22, 21, 20, 6, 43, 1, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 39, 14,
+ 1, 35, 34, 38, 17, 2,186, 49,169,120, 89, 83, 92, 74,254, 19, 77,174, 76,254, 21, 1,235, 1, 1,101,112, 79,129, 50, 55,132,
+ 71,110,149, 32, 39,133, 97,156,163,200,191,117, 99, 94, 56,132, 62, 77,132, 60, 91,124, 37, 33,132, 89,174,145, 2,164, 72, 90,
+113, 89, 97,133,254,113, 52,151,133,136,157, 43,143, 15, 35, 34,161,144, 51, 51,172, 41, 43, 82, 78, 80, 80,172,164,171,179, 88,
+120,128, 43, 39,168, 35, 33, 63, 64, 61, 66,237, 1, 50, 0, 0, 0, 1, 0,169,255,234, 4, 40, 4,123, 0, 48, 0, 0, 1, 22,
+ 23, 22, 21, 20, 6, 35, 34, 39, 38, 39, 53, 22, 23, 22, 51, 50, 54, 53, 52, 39, 38, 43, 1, 53, 51, 50, 54, 53, 52, 39, 38, 35,
+ 34, 7, 6, 7, 53, 54, 55, 54, 51, 50, 23, 22, 21, 20, 6, 3, 16,119, 65, 64,244,209, 81, 91, 92,105,104, 87, 86, 76,138,148,
+ 72, 72,135,166,159,150,168, 90, 91,173, 99, 91, 91, 77, 97, 90, 91, 86,254,139,138,148, 2, 6, 25, 65, 64, 94,134,158, 12, 12,
+ 24,167, 27, 13, 12, 86, 74, 61, 43, 44,144,110, 81, 98, 53, 52, 18, 17, 34,173, 28, 14, 14, 91, 92,166,109,148, 0, 2, 0,178,
+254, 80, 4, 68, 4,100, 0, 9, 0, 13, 0, 0, 37, 33, 17, 33, 53, 33, 21, 33, 17, 33, 1, 35, 53, 51, 3,246,254, 41,254,147,
+ 3,146,254,147, 1, 31,254,225,184,184, 4, 3,209,143,143,252,190,253,189,233, 0, 3, 0, 14,255,227, 4,186, 4,123, 0, 10,
+ 0, 21, 0, 54, 0, 0, 19, 20, 6, 21, 20, 22, 51, 50, 54, 61, 1, 1, 34, 6, 21, 16, 22, 51, 50, 54, 16, 38, 1, 33, 53, 52,
+ 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 23, 62, 1, 51, 50, 18, 16, 2, 35, 34, 38, 39, 14, 1, 35, 34, 38, 17,177, 2, 80,
+ 86, 87, 77, 1, 90,102, 82, 80,104,103, 80, 80,252, 84, 1,235, 99,112, 80,131, 47, 59,125, 74, 98,147, 48, 52,128, 84,189,170,
+170,189, 89,128, 47, 37,130, 87,175,144, 1,205, 11, 38, 9,145,135,137,158, 43, 2, 22,168,239,254,221,174,167, 2, 26,167,254,
+121, 84,163,144, 53, 51,172, 43, 41, 67, 66, 68, 65,254,236,253,144,254,236, 62, 65, 62, 65,237, 1, 50, 0, 0, 0, 1, 0,137,
+ 2, 47, 4, 72, 4,123, 0, 12, 0, 0, 19, 16, 18, 32, 18, 17, 35, 52, 38, 35, 34, 6, 21,137,246, 1,210,247,195,144,141,140,
+144, 2, 47, 1, 30, 1, 46,254,210,254,226,214,218,218,214, 0, 0, 1, 0,136,255,227, 4, 71, 2, 47, 0, 12, 0, 0, 1, 16,
+ 2, 32, 2, 17, 51, 20, 22, 51, 50, 54, 53, 4, 71,246,254, 46,247,195,144,141,140,144, 2, 47,254,226,254,210, 1, 46, 1, 30,
+214,218,218,214, 0, 1, 0, 43, 0, 2, 4,166, 3, 91, 0, 19, 0, 0, 37, 33, 53, 33, 50, 54, 53, 52, 38, 35, 33, 53, 33, 21,
+ 35, 30, 1, 21, 20, 6, 2,225,253, 74, 2,182,151,142,183,171,253,135, 4, 94,168, 97,100,225, 2,184,108,112,130,138,184,184,
+ 50,168,114,172,168, 0, 0, 0, 0, 3, 0, 63,255,254, 4,146, 3, 87, 0, 3, 0, 7, 0, 27, 0, 0, 55, 53, 51, 21, 3, 53,
+ 51, 21, 1, 33, 53, 33, 50, 54, 53, 52, 38, 35, 33, 53, 33, 21, 35, 30, 1, 21, 20, 6, 63,142,142,142, 2,136,254, 26, 1,230,
+105,100,128,120,254, 69, 3, 15,118, 68, 70,158,122,204,204, 1,136,202,202,253,252,184,108,112,130,138,184,184, 50,168,114,172,
+168, 0, 0, 0, 0, 1, 0, 43, 0, 1, 4,166, 4, 3, 0, 34, 0, 0, 1, 30, 1, 21, 20, 6, 41, 1, 53, 33, 50, 54, 53, 52,
+ 38, 35, 33, 53, 33, 50, 54, 53, 52, 38, 35, 33, 53, 33, 21, 35, 30, 1, 21, 20, 6, 4, 25, 72, 69,209,254,223,253,119, 2,129,
+237,115,123,229,253,127, 2,129,240,112,123,229,253,127, 4, 96, 96, 60, 63, 70, 1,204, 34,105, 74,135,111,168, 53, 70, 80, 59,
+168, 57, 74, 73, 57,167,167, 33, 99, 63, 76,101, 0, 2, 0,252, 2,156, 3,214, 5,224, 0, 2, 0, 10, 0, 0, 1, 3, 33, 3,
+ 51, 1, 35, 39, 33, 7, 35, 2,104,134, 1, 12,210,154, 1, 32,132, 68,254,182, 68,132, 5,124,254, 85, 2, 15,252,188,218,218,
+ 0, 2, 0,245, 2,156, 3,220, 5,224, 0, 15, 0, 19, 0, 0, 1, 21, 35, 21, 51, 21, 35, 17, 51, 21, 33, 53, 35, 7, 35, 1,
+ 23, 3, 51, 17, 3,208,213,194,194,225,254,170,221, 64,116, 1, 2, 76,127,194, 5,224, 95,248, 95,254,209, 95,214,214, 3, 68,
+ 95,254, 80, 1,176, 0, 0, 0, 0, 3, 1, 55, 2,156, 3,154, 5,224, 0, 8, 0, 17, 0, 32, 0, 0, 1, 17, 51, 50, 54, 53,
+ 52, 38, 35, 3, 21, 51, 50, 54, 53, 52, 38, 35, 37, 33, 50, 22, 21, 20, 6, 7, 30, 1, 21, 20, 6, 35, 33, 1,182,151,111, 94,
+ 99,106,151,149, 91, 83, 81, 93,254,236, 1, 22,144,157, 83, 83, 93,105,167,166,254,234, 4, 43,254,206, 69, 79, 82, 76, 1, 88,
+252, 63, 70, 63, 56, 93,111,101, 77, 88, 12, 12,116, 89,114,116, 0, 2, 1, 55, 2,156, 3,154, 5,224, 0, 8, 0, 17, 0, 0,
+ 1, 50, 54, 53, 52, 38, 43, 1, 17, 19, 50, 22, 21, 20, 6, 43, 1, 17, 1,244,160,128,127,161, 61, 63,216,204,204,216,191, 2,
+249,141,183,186,140,253,118, 2,231,204,215,214,203, 3, 68, 0, 0, 1, 1, 76, 2,156, 3,134, 5,224, 0, 11, 0, 0, 1, 33,
+ 21, 33, 21, 33, 21, 33, 17, 33, 21, 33, 1, 76, 2, 46,254, 80, 1,156,254,100, 1,188,253,198, 5,224, 95,248, 95,254,209, 95,
+ 0, 1, 1, 76, 2,156, 3,134, 5,224, 0, 11, 0, 0, 1, 33, 21, 33, 21, 33, 21, 33, 17, 33, 21, 33, 3,134,253,210, 1,174,
+254,100, 1,156,254, 70, 2, 58, 5,224, 95,248, 95,254,209, 95, 0, 1, 1, 44, 2,140, 3,164, 5,239, 0, 28, 0, 0, 1, 14,
+ 1, 35, 34, 38, 16, 54, 51, 50, 22, 23, 21, 46, 1, 35, 34, 6, 21, 20, 22, 51, 50, 54, 55, 53, 35, 53, 33, 3,164, 52,126, 76,
+178,200,202,180, 60,108, 50, 52,106, 60,124,124,120,124, 42, 64, 26,136, 1, 2, 2,225, 42, 43,228, 1,154,229, 29, 31,116, 43,
+ 41,170,172,174,167, 17, 18,225, 93, 0, 0, 0, 0, 1, 1, 58, 2,156, 3,150, 5,224, 0, 11, 0, 0, 1, 51, 17, 33, 17, 51,
+ 17, 35, 17, 33, 17, 35, 1, 58,128, 1, 94,126,126,254,162,128, 5,224,254,169, 1, 87,252,188, 1,142,254,114, 0, 1, 1,100,
+ 2,156, 3,110, 5,224, 0, 11, 0, 0, 1, 33, 21, 35, 17, 51, 21, 33, 53, 51, 17, 35, 1,100, 2, 10,198,198,253,246,196,196,
+ 5,224, 95,253,122, 95, 95, 2,134, 0, 0, 0, 0, 1, 1, 94, 2,140, 3,115, 5,224, 0, 17, 0, 0, 1, 53, 30, 1, 51, 50,
+ 54, 53, 17, 35, 53, 33, 17, 20, 6, 35, 34, 38, 1, 94, 57,122, 66, 90, 71,240, 1,111,133,155, 61,119, 2,190,132, 45, 45, 83,
+114, 1,212, 95,253,205,158,131, 24, 0, 0, 0, 0, 1, 1, 18, 2,156, 3,192, 5,224, 0, 11, 0, 0, 1, 51, 17, 1, 51, 9,
+ 1, 35, 1, 7, 17, 35, 1, 18,128, 1,142,148,254,146, 1,122,154,254,204, 96,128, 5,224,254,140, 1,116,254,170,254, 18, 1,
+163, 92,254,185, 0, 1, 1, 69, 2,156, 3,140, 5,224, 0, 5, 0, 0, 1, 51, 17, 33, 21, 33, 1, 69,128, 1,199,253,185, 5,
+224,253, 27, 95, 0, 1, 1, 27, 2,156, 3,182, 5,224, 0, 12, 0, 0, 1, 51, 27, 1, 51, 17, 35, 17, 3, 35, 3, 17, 35, 1,
+ 27,170,163,164,170,117,168, 96,169,117, 5,224,254, 86, 1,170,252,188, 2,227,254, 71, 1,185,253, 29, 0, 0, 0, 1, 1, 60,
+ 2,156, 3,149, 5,224, 0, 9, 0, 0, 1, 51, 1, 17, 51, 17, 35, 1, 17, 35, 1, 60,161, 1, 61,123,161,254,194,122, 5,224,
+253, 80, 2,176,252,188, 2,176,253, 80, 0, 0, 0, 1, 1, 60, 2,156, 3,149, 5,224, 0, 9, 0, 0, 1, 35, 1, 17, 35, 17,
+ 51, 1, 17, 51, 3,149,161,254,194,122,161, 1, 61,123, 5,224,253, 80, 2,176,252,188, 2,176,253, 80, 0, 0, 0, 2, 1, 46,
+ 2,140, 3,163, 5,239, 0, 10, 0, 19, 0, 0, 0, 16, 38, 35, 34, 6, 21, 20, 22, 51, 50, 19, 20, 6, 32, 38, 16, 54, 32, 22,
+ 3, 30, 85, 97, 96, 85, 85, 96, 97,218,156,254,194,155,155, 1, 62,156, 3,133, 1,112,158,158,184,183,158, 1, 85,218,215,214,
+ 1,182,215,215, 0, 2, 1, 63, 2,156, 3,146, 5,224, 0, 8, 0, 18, 0, 0, 1, 17, 51, 50, 54, 53, 52, 38, 35, 37, 33, 50,
+ 22, 20, 6, 43, 1, 17, 35, 1,190,148, 88, 99, 98, 89,254,237, 1, 19,157,163,162,158,148,127, 5,131,254,198, 83, 74, 75, 82,
+ 93,127,246,127,254,176, 0, 0, 0, 2, 1, 17, 2,156, 3,192, 5,224, 0, 19, 0, 28, 0, 0, 1, 30, 1, 31, 1, 35, 39, 46,
+ 1, 43, 1, 17, 35, 17, 33, 50, 22, 21, 20, 6, 1, 17, 51, 50, 54, 53, 52, 38, 35, 2,150, 49, 69, 52,128,137,112, 49, 77, 62,
+122,128, 1, 6,155,165,101,254,159,139, 92, 89, 95, 91, 4, 39, 11, 63, 93,228,211, 90, 52,254,159, 3, 68,124,118, 83,104, 1,
+ 80,254,215, 73, 75, 72, 77, 0, 0, 1, 1, 2, 2,156, 3,207, 5,224, 0, 7, 0, 0, 1, 33, 21, 33, 17, 35, 17, 33, 1, 2,
+ 2,205,254,218,128,254,217, 5,224, 95,253, 27, 2,229, 0, 0, 0, 1, 1, 65, 2,140, 3,144, 5,224, 0, 29, 0, 0, 1, 17,
+ 51, 17, 20, 22, 23, 30, 1, 51, 50, 54, 55, 62, 1, 53, 17, 51, 17, 20, 6, 7, 14, 1, 35, 34, 38, 39, 46, 1, 1, 65,127, 8,
+ 10, 20, 76, 54, 55, 75, 21, 10, 7,128, 36, 44, 42,107, 67, 66,107, 42, 44, 36, 3,221, 2, 3,253,201, 61, 52, 14, 33, 33, 33,
+ 33, 14, 52, 60, 2, 56,253,253,128,108, 36, 33, 32, 32, 33, 35,110, 0, 0, 0, 0, 1, 0,228, 2,156, 3,237, 5,224, 0, 12,
+ 0, 0, 19, 51, 27, 1, 51, 27, 1, 51, 3, 35, 11, 1, 35,228,124, 90,107,133,109, 90,124,141,120,128,127,121, 5,224,253, 89,
+ 1,193,254, 62, 2,168,252,188, 1,241,254, 15, 0, 2, 1, 69, 2,140, 3,140, 5, 30, 0, 11, 0, 41, 0, 0, 1, 35, 34, 6,
+ 21, 20, 22, 51, 50, 54, 55, 53, 55, 17, 35, 53, 14, 1, 35, 34, 38, 53, 52, 54, 59, 1, 53, 46, 1, 35, 34, 6, 7, 53, 62, 1,
+ 51, 50, 22, 23, 30, 1, 2,171, 38,102,102, 77, 68, 95,110, 1,116,116, 38,112, 81,108,128,158,153,156, 1, 84, 93, 59,121, 58,
+ 65,118, 55, 88,124, 38, 24, 20, 3,215, 63, 63, 56, 63,118,104, 23, 43,254,154, 93, 56, 53,108, 91,104,109, 16, 75, 68, 30, 29,
+103, 21, 22, 46, 46, 28, 82, 0, 0, 2, 1, 69, 2,140, 3,140, 5, 30, 0, 11, 0, 41, 0, 0, 1, 51, 50, 54, 53, 52, 38, 35,
+ 34, 6, 7, 21, 7, 17, 51, 21, 62, 1, 51, 50, 22, 21, 20, 6, 43, 1, 21, 30, 1, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 39,
+ 46, 1, 2, 38, 38,102,102, 77, 68, 95,110, 1,116,116, 38,112, 81,108,128,158,153,156, 1, 84, 93, 59,121, 58, 65,118, 55, 88,
+124, 38, 24, 20, 3,211, 63, 63, 56, 63,118,104, 23, 43, 1,102, 93, 56, 53,108, 90,105,109, 16, 75, 68, 30, 29,103, 21, 22, 46,
+ 46, 28, 82, 0, 0, 2, 1, 71, 2,140, 3,138, 5, 30, 0, 16, 0, 26, 0, 0, 1, 53, 51, 17, 35, 53, 14, 1, 35, 34, 38, 53,
+ 52, 54, 51, 50, 22, 4, 20, 22, 51, 50, 54, 52, 38, 35, 34, 3, 22,116,116, 29, 96, 63,128,147,147,128, 63, 97,254,199, 86, 84,
+ 83, 88, 88, 83, 84, 4,191, 78,253,143, 79, 47, 48,176,155,153,174, 48,161,240,122,123,238,123, 0, 3, 0,251, 2,140, 3,214,
+ 5, 30, 0, 10, 0, 18, 0, 66, 0, 0, 1, 21, 51, 50, 54, 53, 52, 38, 35, 34, 6, 5, 21, 20, 22, 50, 54, 61, 1, 37, 33, 52,
+ 54, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 23, 62, 1, 51, 50, 22, 21, 20, 6, 43, 1, 21, 20, 22, 51, 50, 54, 55,
+ 21, 14, 1, 35, 34, 38, 39, 14, 1, 35, 34, 38, 53, 2,153, 31,107, 75, 56, 52, 58, 47,254,202, 48,110, 48,254,202, 1, 54, 1,
+ 64, 70, 50, 81, 32, 35, 83, 45, 69, 94, 20, 25, 84, 61, 98,103,126,121, 73, 62, 59, 35, 84, 39, 49, 83, 38, 57, 78, 24, 20, 84,
+ 56,109, 92, 4, 23, 41, 51, 63, 50, 54, 74,224, 29, 85, 74, 76, 88, 24, 80, 9, 19, 19, 90, 81, 28, 29, 96, 23, 24, 46, 43, 45,
+ 44, 96, 92, 96,100, 49, 67, 72, 24, 22, 94, 20, 18, 35, 36, 34, 37,132,172, 0, 0, 2, 1, 71, 2,140, 3,138, 6, 3, 0, 7,
+ 0, 24, 0, 0, 0, 52, 38, 34, 6, 20, 22, 50, 3, 62, 1, 51, 50, 22, 21, 20, 6, 35, 34, 38, 39, 21, 35, 17, 51, 3, 16, 86,
+168, 87, 87,168,255, 28, 97, 65,127,146,147,128, 63, 96, 29,116,116, 3, 93,240,122,123,238,123, 1,220, 46, 49,174,153,155,176,
+ 48, 47, 79, 3,103, 0, 0, 0, 0, 2, 1, 71, 2,140, 3,138, 6, 3, 0, 16, 0, 26, 0, 0, 1, 17, 51, 17, 35, 53, 14, 1,
+ 35, 34, 38, 53, 52, 54, 51, 50, 22, 4, 20, 22, 51, 50, 54, 52, 38, 35, 34, 3, 22,116,116, 29, 96, 63,128,147,147,128, 63, 97,
+254,199, 86, 84, 83, 88, 88, 83, 84, 4,191, 1, 68,252,153, 79, 47, 48,176,155,153,174, 48,161,240,122,123,238,123, 0, 0, 0,
+ 0, 2, 1, 49, 2,140, 3,160, 5, 30, 0, 21, 0, 28, 0, 0, 1, 21, 33, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38,
+ 53, 52, 54, 51, 50, 22, 7, 46, 1, 35, 34, 6, 7, 3,160,254, 10,120,110, 55,121, 69, 66,123, 57,165,185,181,152,134,156,116,
+ 2, 92, 85, 84,109, 10, 3,239, 50, 3,103,112, 31, 32,102, 24, 24,175,154,150,179,162,110, 90, 95, 99, 87, 0, 0, 2, 1, 49,
+ 2,140, 3,160, 5, 30, 0, 21, 0, 28, 0, 0, 1, 53, 33, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 21, 20, 6, 35,
+ 34, 38, 55, 30, 1, 51, 50, 54, 55, 1, 49, 1,246,120,110, 55,121, 69, 66,123, 57,165,185,181,152,134,156,116, 2, 92, 85, 84,
+109, 10, 3,187, 50, 3,103,112, 31, 32,102, 24, 24,175,154,150,179,162,110, 90, 95, 99, 87, 0, 0, 1, 1, 79, 2,144, 3,130,
+ 5, 30, 0, 40, 0, 0, 1, 46, 1, 53, 52, 54, 51, 50, 22, 23, 21, 46, 1, 35, 34, 6, 21, 20, 22, 59, 1, 21, 35, 34, 6, 21,
+ 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 53, 52, 54, 1,255, 75, 81,153,132, 51,115, 67, 66,109, 48, 87, 93, 91, 85,104,
+100, 94,106,114,109, 62,115, 48, 61,114, 54,160,174, 93, 3,240, 14, 72, 53, 75, 88, 13, 14, 93, 15, 14, 48, 42, 34, 48, 81, 62,
+ 45, 55, 59, 20, 19, 97, 16, 15,102, 93, 61, 83, 0, 1, 1, 79, 2,144, 3,130, 5, 30, 0, 40, 0, 0, 1, 30, 1, 21, 20, 6,
+ 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 43, 1, 53, 51, 50, 54, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22,
+ 21, 20, 6, 2,210, 75, 81,153,132, 51,115, 67, 66,109, 48, 87, 93, 91, 85,104,100, 94,106,114,109, 62,115, 48, 61,114, 54,160,
+174, 93, 3,190, 14, 72, 53, 75, 88, 13, 14, 93, 15, 14, 48, 42, 34, 48, 81, 62, 45, 55, 59, 20, 19, 97, 16, 15,102, 93, 61, 83,
+ 0, 2, 1, 71, 1,166, 3,138, 5, 30, 0, 9, 0, 39, 0, 0, 0, 52, 38, 35, 34, 6, 20, 22, 51, 50, 23, 20, 6, 35, 34, 38,
+ 39, 53, 30, 1, 51, 50, 54, 61, 2, 14, 1, 35, 34, 38, 53, 52, 54, 51, 50, 22, 23, 53, 51, 3, 22, 85, 81, 85, 90, 90, 86, 80,
+201,150,145, 48,105, 52, 62,100, 43, 93, 86, 28, 95, 69,124,147,147,124, 68, 94, 30,116, 3,103,232,120,120,232,122, 41,141,145,
+ 15, 15,102, 25, 25, 91, 98, 5, 70, 53, 51,175,148,147,176, 48, 50, 81, 0, 0, 0, 2, 1, 73, 1,170, 3,136, 5, 17, 0, 9,
+ 0, 13, 0, 0, 1, 33, 17, 35, 53, 33, 21, 35, 17, 51, 3, 35, 53, 51, 3, 87,254,216,230, 2, 63,230,181,181,115,115, 2,158,
+ 2, 35, 80, 80,254, 45,254,188,131, 0, 0, 0, 0, 1, 1, 56, 2,156, 3,153, 6, 3, 0, 11, 0, 0, 1, 51, 17, 1, 51, 5,
+ 1, 35, 1, 7, 21, 35, 1, 56,120, 1, 48,141,254,234, 1, 66,142,254,251, 86,120, 6, 3,254, 8, 1, 4,236,254,121, 1, 68,
+ 73,251, 0, 0, 0, 1, 1, 37, 2,156, 3,172, 5, 30, 0, 34, 0, 0, 1, 62, 1, 51, 50, 22, 21, 17, 35, 17, 52, 38, 35, 34,
+ 6, 21, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 22, 2,139, 21, 66, 47, 85, 70,106, 34, 44, 50,
+ 37,106, 36, 47, 46, 35,106,106, 20, 63, 39, 48, 64, 4,207, 41, 38,117,162,254,149, 1,103,133, 64, 69,128,254,153, 1,103,134,
+ 63, 69,128,254,153, 2,115, 54, 34, 35, 39, 0, 0, 1, 1, 91, 1,173, 3,118, 5, 30, 0, 31, 0, 0, 1, 17, 20, 7, 6, 43,
+ 1, 53, 51, 50, 55, 54, 53, 17, 52, 38, 35, 34, 7, 6, 21, 17, 35, 17, 51, 21, 54, 55, 54, 51, 50, 22, 3,118, 56, 57,104,129,
+117, 57, 28, 28, 67, 71, 82, 44, 43,116,116, 31, 53, 52, 73,108,106, 4, 33,254,112,109, 59, 60, 88, 35, 34, 71, 1,144, 84, 80,
+ 51, 52, 96,254,158, 2,115, 94, 54, 28, 27,126, 0, 2, 1, 58, 2,140, 3,151, 5, 30, 0, 11, 0, 22, 0, 0, 1, 34, 6, 21,
+ 20, 22, 51, 50, 54, 53, 52, 46, 1, 32, 22, 21, 20, 6, 35, 34, 38, 53, 52, 2,104, 88, 91, 91, 88, 89, 91, 91,236, 1, 38,156,
+155,148,147,155, 4,199,122,120,119,123,123,119,120,122, 87,169,160,161,168,168,161,160, 0, 0, 0, 1, 1, 88, 2,140, 3,121,
+ 5, 30, 0, 23, 0, 0, 1, 62, 1, 51, 50, 22, 16, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 52, 38, 35, 34, 6, 7, 1, 88,
+ 46, 99, 52,164,184,184,164, 51, 97, 49, 46, 92, 59,109,117,118,108, 61, 95, 41, 4,238, 24, 24,174,254,202,174, 23, 25,108, 36,
+ 33,126,232,126, 33, 35, 0, 0, 0, 1, 1, 58, 3,213, 3,151, 5, 30, 0, 12, 0, 0, 1, 52, 54, 32, 22, 21, 35, 52, 38, 35,
+ 34, 6, 21, 1, 58,155, 1, 38,156,123, 91, 89, 88, 91, 3,213,160,169,169,160,120,122,122,120, 0, 1, 1, 58, 2,140, 3,151,
+ 3,213, 0, 12, 0, 0, 1, 20, 6, 32, 38, 53, 51, 20, 22, 51, 50, 54, 53, 3,151,155,254,218,156,123, 91, 89, 88, 91, 3,213,
+160,169,169,160,120,122,122,120, 0, 2, 1, 71, 1,173, 3,138, 5, 30, 0, 16, 0, 24, 0, 0, 1, 17, 35, 17, 51, 21, 62, 1,
+ 51, 50, 22, 21, 20, 6, 35, 34, 38, 36, 52, 38, 34, 6, 20, 22, 50, 1,188,117,117, 29, 96, 63,128,146,146,128, 64, 96, 1, 56,
+ 85,168, 87, 87,168, 2,235,254,194, 3, 98, 80, 47, 48,176,155,153,174, 48,161,240,122,123,238,123, 0, 0, 0, 0, 1, 1, 77,
+ 2,156, 3,132, 5,193, 0, 19, 0, 0, 1, 21, 33, 21, 33, 17, 20, 22, 59, 1, 21, 35, 34, 38, 53, 17, 35, 53, 51, 53, 2,125,
+ 1, 7,254,249, 59, 74,130,141,131,107,188,188, 5,193,178, 80,254,172, 70, 55, 82, 93,114, 1, 84, 80,178, 0, 0, 1, 1, 91,
+ 2,140, 3,118, 5, 14, 0, 19, 0, 0, 1, 17, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 35, 53, 14, 1, 35, 34, 38, 1, 91,
+116, 67, 71, 82, 87,116,116, 31,107, 71,108,106, 3,137, 1,133,254,123, 84, 80,103, 96, 1, 98,253,142, 94, 54, 56,126, 0, 0,
+ 0, 1, 0,255, 2,157, 3,210, 4,125, 0, 19, 0, 0, 1, 33, 53, 33, 50, 54, 53, 52, 38, 35, 33, 53, 33, 21, 35, 30, 1, 21,
+ 20, 6, 2,180,254, 75, 1,181, 96, 89,115,108,254,113, 2,193,106, 61, 63,142, 2,157,103, 60, 63, 73, 77,104,104, 27, 95, 63,
+ 97, 94, 0, 0, 0, 1, 1, 37, 2,156, 3,172, 5, 30, 0, 34, 0, 0, 1, 14, 1, 35, 34, 38, 53, 17, 51, 17, 20, 22, 51, 50,
+ 54, 53, 17, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 35, 53, 14, 1, 35, 34, 38, 2, 70, 21, 66, 47, 85, 70,106, 34, 44, 50,
+ 37,106, 36, 47, 46, 35,106,106, 20, 63, 39, 48, 64, 2,235, 40, 39,117,162, 1,107,254,153,132, 65, 69,128, 1,103,254,153,134,
+ 63, 69,128, 1,103,253,141, 54, 34, 35, 39, 0, 0, 1, 1, 35, 2,156, 3,174, 5, 15, 0, 6, 0, 0, 1, 51, 27, 1, 51, 3,
+ 35, 1, 35,120,205,206,120,251,149, 5, 15,253,242, 2, 14,253,141, 0, 0, 0,255,255, 1, 72, 0, 0, 3,136, 3,103, 16, 7,
+ 6,169, 0, 0,253,100, 0, 0,255,255, 1,153, 0, 0, 3, 56, 2,131, 16, 7, 2, 81, 0, 0,253,100, 0, 0,255,255, 1, 91,
+255,240, 3,118, 2,114, 16, 7, 4,214, 0, 0,253,100, 0, 0,255,255, 1, 35, 0, 0, 3,174, 2,115, 16, 7, 4,217, 0, 0,
+253,100, 0, 0, 0, 2, 0,123,254, 72, 4, 18, 4,123, 0, 10, 0, 40, 0, 0, 37, 20, 22, 51, 50, 54, 16, 38, 35, 34, 6, 3,
+ 52, 18, 51, 50, 22, 23, 21, 46, 1, 35, 34, 6, 29, 2, 62, 1, 51, 50, 18, 17, 16, 2, 35, 34, 38, 39, 21, 35, 1, 51,135,129,
+135,142,143,136,127,135,184,238,231, 76,166, 83, 98,160, 67,149,136, 44,152,109,196,234,234,196,108,150, 47,184,138,207,215,215,
+ 1,158,217,218, 1, 35,252, 1, 4, 28, 27,182, 46, 44,162,176, 8,125, 94, 92,254,198,254,249,254,248,254,198, 86, 90,145, 0,
+255,255, 1, 58, 2,156, 3,150, 5,224, 16, 6, 4,179, 0, 0, 0, 1, 0,156, 0, 0, 4, 53, 4, 96, 0, 19, 0, 0, 1, 21,
+ 33, 17, 33, 21, 33, 53, 33, 17, 33, 53, 33, 17, 33, 53, 33, 21, 33, 17, 4, 53,254,143, 1,110,252,110, 1,108,254,144, 1,112,
+254,148, 3,146,254,146, 2,104,164,254,203,143,143, 1, 53,164, 1,105,143,143,254,151, 0, 0, 0, 1, 0,160,254, 86, 4, 10,
+ 6, 31, 0, 27, 0, 0, 1, 20, 22, 59, 1, 29, 2, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 61, 1, 35, 34, 38, 53, 17, 33, 53,
+ 33, 2,127, 91, 89,215, 89, 90,165,205,185, 90, 45, 44, 48,165,181,254,217, 1,223, 1,150,124,126, 28,128, 20,195,105,106,156,
+ 62, 62,126, 20,212,194, 3,249,144, 0, 0, 0, 0, 2, 1, 71, 2,140, 3,138, 5, 30, 0, 16, 0, 26, 0, 0, 1, 21, 35, 17,
+ 51, 21, 62, 1, 51, 50, 22, 21, 20, 6, 35, 34, 38, 36, 52, 38, 35, 34, 6, 20, 22, 51, 50, 1,187,116,116, 29, 96, 63,128,147,
+147,128, 63, 97, 1, 57, 86, 84, 83, 88, 88, 83, 84, 2,235, 78, 2,113, 79, 47, 48,176,155,153,174, 48,161,240,122,123,238,123,
+ 0, 1, 1, 88, 2,140, 3,121, 5, 30, 0, 24, 0, 0, 1, 14, 1, 35, 34, 38, 16, 54, 51, 50, 22, 23, 21, 46, 1, 35, 34, 6,
+ 21, 20, 22, 51, 50, 54, 55, 3,121, 46, 99, 52,164,184,184,164, 51, 97, 49, 46, 92, 59,109,117,118,108, 61, 95, 41, 2,188, 24,
+ 24,174, 1, 54,174, 23, 25,108, 36, 33,125,117,116,126, 33, 35, 0, 2, 1, 81, 2, 73, 3,128, 5, 28, 0, 7, 0, 43, 0, 0,
+ 1, 22, 51, 50, 53, 38, 35, 34, 7, 6, 21, 7, 52, 55, 38, 39, 38, 53, 52, 55, 54, 51, 50, 23, 22, 23, 21, 46, 1, 35, 34, 7,
+ 6, 20, 23, 22, 23, 54, 51, 50, 23, 20, 35, 34, 2,100, 38, 47, 92, 1, 82, 64, 53, 3, 97, 8, 36, 30, 94, 96, 94,165, 54, 51,
+ 51, 48, 50, 98, 51,113, 62, 62, 62, 4, 4, 53,124,188, 1,210, 52, 2,236, 11, 32, 42,154, 32, 38, 2, 58, 47, 20, 29, 90,150,
+153, 88, 88, 9, 11, 19, 96, 24, 24, 64, 63,230, 64, 4, 3, 98,138,106, 0, 0, 0, 2, 1, 58, 2,140, 3,151, 6, 3, 0, 26,
+ 0, 41, 0, 0, 1, 30, 1, 21, 20, 6, 35, 34, 38, 53, 52, 54, 51, 50, 22, 23, 46, 1, 39, 7, 39, 55, 39, 51, 23, 55, 23, 3,
+ 46, 1, 35, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 2,168,124,115,159,144,143,159,159,141, 21, 22, 10, 21, 46, 24,175, 19,
+149,115,138, 80,183, 20,109, 22, 52, 28, 92, 97, 94, 85, 86, 94, 37, 5,131,119,212,112,150,166,166,150,148,166, 1, 1, 25, 50,
+ 24, 51, 55, 44,112, 81, 53, 55,254,238, 7, 8,118,111,110,119,119,110, 61,114, 0, 1, 1, 79, 2,144, 3,130, 5, 30, 0, 40,
+ 0, 0, 1, 30, 1, 21, 20, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 43, 1, 53, 51, 50, 54, 53, 52, 38, 35, 34,
+ 6, 7, 53, 62, 1, 51, 50, 22, 21, 20, 6, 2,209, 84, 93,174,161, 53,115, 60, 47,115, 63,109,114,106, 95, 99,104, 85, 91, 94,
+ 87, 47,109, 66, 67,115, 50,133,153, 82, 3,240, 13, 83, 61, 93,102, 15, 16, 97, 19, 20, 59, 55, 45, 62, 81, 48, 34, 42, 48, 14,
+ 15, 93, 14, 13, 88, 75, 53, 72, 0, 1, 1, 87, 2,156, 3,122, 6, 3, 0, 19, 0, 0, 1, 21, 35, 34, 6, 29, 1, 51, 21, 35,
+ 17, 35, 17, 35, 53, 51, 53, 52, 54, 51, 3,122,132, 62, 49,243,243,116,188,188,107,113, 6, 3, 85, 46, 57, 56, 80,253,221, 2,
+ 35, 80, 44,103, 97, 0, 0, 0, 0, 1, 1, 98, 1,173, 3,111, 5, 15, 0, 23, 0, 0, 1, 53, 51, 17, 35, 53, 33, 17, 51, 21,
+ 35, 21, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 61, 1, 1,206,153,200, 1, 60,148,148, 57, 56,104,160,147, 57, 28, 29, 2,156,
+ 92, 1,199, 80,253,233, 92, 11,109, 59, 60, 88, 35, 35, 70, 11, 0, 2, 1, 71, 1,166, 3,138, 5, 13, 0, 10, 0, 36, 0, 0,
+ 1, 48, 53, 39, 34, 6, 20, 22, 51, 50, 54, 23, 20, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 61, 2, 14, 1, 35, 34, 38, 53,
+ 52, 54, 51, 33, 3, 22,166, 85, 90, 90, 86, 80, 85,116,150,145, 48,105, 52, 62,100, 43, 93, 86, 28, 95, 69,124,147,145,126, 1,
+ 52, 3,219,119,117,120,232,122,122,163,141,145, 15, 15,102, 25, 25, 91, 98, 5, 70, 53, 51,175,148,127,179, 0, 0, 1, 1, 91,
+ 1,171, 3,118, 5, 14, 0, 19, 0, 0, 1, 17, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 35, 17, 14, 1, 35, 34, 38, 1, 91,
+116, 67, 71, 82, 87,116,116, 31,107, 71,108,106, 3,137, 1,133,254,123, 84, 80,103, 96, 1, 98,252,157, 1, 79, 54, 56,126, 0,
+ 0, 2, 1, 67, 2,156, 3,142, 6, 3, 0, 3, 0, 21, 0, 0, 1, 51, 21, 35, 7, 33, 17, 51, 21, 35, 21, 51, 21, 33, 53, 51,
+ 53, 35, 53, 51, 53, 35, 2, 52,116,116,181, 1, 41,223,223,230,253,192,230,241,241,181, 6, 3,130,114,254,230, 92,173, 80, 80,
+173, 92,202, 0, 0, 1, 1, 97, 2,156, 3,112, 5, 15, 0, 13, 0, 0, 1, 35, 34, 38, 53, 17, 35, 53, 33, 17, 6, 22, 59, 1,
+ 3,112,129,104,113,181, 1, 41, 1, 57, 57,117, 2,156,117,110, 1, 64, 80,254,112, 70, 70, 0, 0, 1, 1, 73, 2,156, 3,136,
+ 5, 15, 0, 11, 0, 0, 1, 33, 21, 35, 17, 51, 21, 33, 53, 51, 17, 35, 1, 73, 2, 63,230,230,253,193,230,230, 5, 15, 80,254,
+ 45, 80, 80, 1,211, 0, 0, 0, 0, 1, 1, 71, 2,156, 3,138, 5, 15, 0, 19, 0, 0, 1, 21, 35, 21, 51, 21, 33, 53, 51, 53,
+ 35, 53, 51, 53, 35, 53, 33, 21, 35, 21, 3,138,232,230,253,193,230,232,232,230, 2, 63,230, 3,245, 92,173, 80, 80,173, 92,202,
+ 80, 80,202, 0, 0, 3, 1,100, 1,173, 3,109, 6, 3, 0, 3, 0, 18, 0, 28, 0, 0, 1, 51, 21, 35, 3, 34, 53, 52, 59, 1,
+ 17, 51, 17, 51, 21, 35, 6, 7, 6, 39, 48, 35, 34, 23, 22, 51, 50, 55, 54, 2,135,116,116,100,191,170,121,116,114,120, 12, 33,
+ 51, 21,114, 74, 1, 3, 77, 66, 24, 11, 6, 3,130,252, 44,124,115, 2,115,253,141, 87, 63, 35, 53,152, 29, 36, 27, 13, 0, 0,
+ 0, 1, 1, 85, 1,173, 3,124, 6, 10, 0, 13, 0, 0, 1, 20, 22, 59, 1, 21, 35, 34, 38, 53, 17, 35, 53, 33, 2,131, 57, 56,
+136,147,100,118,186, 1, 46, 2,145, 70, 70, 88,116,112, 3, 40, 81, 0, 0, 0, 0, 1, 1, 85, 1,173, 3,124, 6, 10, 0, 25,
+ 0, 0, 1, 20, 22, 59, 1, 21, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 61, 1, 35, 34, 38, 53, 17, 35, 53, 33, 2,131, 57, 56,
+136, 56, 57,104,129,116, 57, 29, 27, 30,104,114,186, 1, 46, 3,127, 69, 71, 98,109, 59, 60, 88, 35, 34, 71, 11,119,108, 2, 58,
+ 81, 0, 0, 0, 0, 1, 1,126, 2,156, 3, 83, 5, 30, 0, 5, 0, 0, 1, 51, 17, 33, 21, 33, 1,126,128, 1, 85,254, 43, 5,
+ 30,253,221, 95, 0, 1, 1, 37, 1,173, 3,171, 5, 30, 0, 48, 0, 0, 1, 62, 1, 51, 50, 23, 22, 21, 17, 21, 20, 7, 6, 43,
+ 1, 53, 51, 50, 55, 54, 61, 1, 49, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1,
+ 51, 50, 22, 2,138, 22, 66, 46, 86, 34, 35, 50, 51, 95,117,106, 51, 26, 25, 34, 44, 50, 37,106, 36, 47, 46, 36,105,105, 21, 62,
+ 40, 48, 64, 4,207, 41, 38, 58, 59,162,254,221, 83,109, 59, 60, 88, 35, 34, 71, 11, 1,103,133, 64, 69,128,254,153, 1,103,134,
+ 63, 69,128,254,153, 2,115, 54, 34, 35, 39, 0, 0, 1, 1, 37, 1,171, 3,172, 5, 30, 0, 34, 0, 0, 1, 14, 1, 35, 34, 38,
+ 53, 17, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 20, 22, 51, 50, 54, 53, 17, 51, 17, 35, 17, 14, 1, 35, 34, 38, 2, 70, 21,
+ 66, 47, 85, 70,106, 34, 44, 50, 37,106, 36, 47, 46, 35,106,106, 20, 63, 39, 48, 64, 2,235, 40, 39,117,162, 1,107,254,153,132,
+ 65, 69,128, 1,103,254,153,134, 63, 69,128, 1,103,252,141, 1, 54, 34, 35, 39, 0, 1, 1, 85, 1,173, 3,124, 5, 30, 0, 27,
+ 0, 0, 1, 20, 6, 43, 1, 53, 51, 50, 54, 53, 17, 51, 21, 62, 1, 51, 50, 22, 21, 17, 35, 17, 52, 38, 35, 34, 6, 21, 2, 24,
+ 77, 85, 33, 23, 49, 36, 88, 31, 84, 56, 91, 93, 86, 59, 59, 70, 81, 2,145,120,108, 88, 54, 86, 2,126, 97, 56, 56,134,129,254,
+133, 1,119, 89, 89,107, 92, 0, 0, 1, 1, 85, 1,173, 3,124, 5, 30, 0, 36, 0, 0, 1, 53, 17, 52, 39, 38, 35, 34, 7, 6,
+ 21, 17, 35, 17, 51, 21, 54, 55, 54, 51, 50, 23, 22, 21, 17, 29, 1, 20, 22, 59, 1, 21, 35, 34, 39, 38, 53, 2,185, 29, 30, 58,
+ 71, 40, 41, 87, 87, 31, 42, 43, 55, 91, 47, 47, 36, 49, 23, 33, 85, 38, 39, 2,156, 72, 1, 47, 89, 44, 45, 53, 54, 92,254,158,
+ 2,115, 97, 56, 28, 28, 66, 68,129,254,205, 72, 11, 86, 54, 88, 54, 54,120, 0, 0, 1, 1, 63, 2,156, 3,146, 5, 30, 0, 9,
+ 0, 0, 1, 51, 1, 17, 51, 17, 35, 1, 17, 35, 1, 63,171, 1, 45,123,171,254,211,123, 5, 30,254, 7, 1,249,253,126, 1,250,
+254, 6, 0, 0, 0, 3, 1, 58, 2,140, 3,151, 5, 30, 0, 14, 0, 23, 0, 32, 0, 0, 0, 32, 23, 22, 21, 20, 7, 6, 35, 34,
+ 39, 38, 53, 52, 55, 23, 34, 7, 6, 7, 33, 38, 39, 38, 19, 33, 22, 23, 22, 51, 50, 55, 54, 1,213, 1, 38, 78, 78, 78, 77,148,
+147, 77, 78, 78,224, 88, 45, 40, 5, 1,101, 5, 40, 45, 87,254,161, 9, 33, 45, 88, 89, 45, 33, 5, 30, 84, 85,160,161, 84, 84,
+ 84, 84,161,160, 85, 3, 61, 53, 99, 99, 53, 61,254,207, 74, 44, 61, 61, 44, 0, 0, 3, 1, 58, 1,174, 3,151, 6, 3, 0, 29,
+ 0, 38, 0, 47, 0, 0, 1, 35, 53, 33, 21, 35, 21, 22, 23, 22, 21, 20, 7, 6, 7, 21, 51, 21, 33, 53, 51, 53, 38, 39, 38, 53,
+ 52, 55, 54, 55, 23, 17, 54, 55, 54, 53, 52, 39, 38, 3, 17, 6, 7, 6, 21, 20, 23, 22, 2, 51,151, 1,162,151,102, 60, 78, 78,
+ 60,102,151,254, 94,151,108, 63, 78, 78, 63,108,116, 44, 27, 46, 46, 27,160, 50, 30, 46, 46, 30, 5,167, 92, 92,141, 15, 65, 85,
+160,161, 84, 65, 15,134, 92, 92,133, 13, 68, 84,161,160, 85, 68, 13, 93,254, 47, 14, 37, 62,119,120, 61, 37,254, 59, 1,214, 13,
+ 41, 61,120,119, 62, 41, 0, 0, 0, 1, 1, 91, 1,173, 3,118, 5, 30, 0, 60, 0, 0, 1, 21, 46, 1, 35, 34, 7, 6, 21, 20,
+ 23, 22, 31, 1, 22, 23, 22, 21, 20, 7, 6, 35, 34, 47, 1, 21, 20, 22, 59, 1, 21, 35, 34, 39, 38, 61, 3, 22, 23, 22, 51, 50,
+ 54, 53, 52, 39, 38, 47, 1, 46, 1, 53, 52, 55, 54, 51, 50, 23, 22, 3, 80, 49,106, 56, 87, 42, 44, 31, 31, 93, 40,123, 52, 52,
+ 77, 78,137, 56, 62, 13, 48, 66,147,160,114, 51, 52, 64, 62, 63, 61, 82, 88, 31, 33,107, 41,107, 96, 70, 71,130, 64, 57, 56, 4,
+253, 98, 23, 22, 23, 24, 47, 36, 21, 20, 18, 8, 24, 43, 42, 77, 87, 51, 51, 9, 3, 7, 86, 54, 88, 54, 54,120, 34, 49, 57, 29,
+ 15, 15, 50, 45, 42, 23, 22, 21, 8, 20, 84, 73, 88, 48, 48, 8, 8, 0, 0, 0, 0, 1, 1,120, 1,173, 3, 89, 6, 3, 0, 20,
+ 0, 0, 1, 2, 3, 52, 54, 59, 1, 21, 35, 34, 6, 21, 19, 20, 6, 43, 1, 53, 51, 50, 54, 2, 9, 1, 1,106,123,109,111, 62,
+ 49, 2,103,114, 44, 31, 66, 48, 2,145, 1, 93, 1, 77,101, 99, 85, 45, 58,253, 74,120,108, 88, 54, 0, 0, 0, 0, 1, 1, 77,
+ 1,173, 3,132, 5,193, 0, 33, 0, 0, 1, 21, 33, 21, 33, 17, 20, 23, 22, 59, 1, 21, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54,
+ 61, 1, 35, 34, 39, 38, 53, 17, 35, 53, 51, 53, 2,125, 1, 7,254,249, 30, 29, 74,130, 56, 56,104,130,117, 57, 28, 28, 25,131,
+ 53, 54,188,188, 5,193,178, 80,254,172, 70, 27, 28, 93,109, 59, 60, 88, 35, 34, 71, 11, 46, 47,114, 1, 84, 80,178, 0, 0, 0,
+ 0, 2, 0,208, 2,140, 4, 1, 5, 15, 0, 23, 0, 33, 0, 0, 19, 53, 51, 17, 51, 17, 33, 17, 51, 17, 51, 21, 35, 21, 35, 53,
+ 6, 7, 6, 35, 34, 38, 61, 1, 41, 1, 21, 20, 23, 22, 51, 50, 55, 54,208,109,116, 1,103,116,117,117,116, 42, 56, 55, 74,122,
+126, 1,219,254,153, 39, 39, 78, 94, 55, 49, 3,153, 92, 1, 26,254,230, 1, 26,254,230, 92,253, 96, 57, 28, 27,134,130, 5, 2,
+ 89, 44, 45, 54, 47, 0, 0, 0, 0, 1, 1, 32, 2,139, 3,177, 5, 15, 0, 29, 0, 0, 1, 53, 33, 21, 14, 1, 21, 20, 22, 50,
+ 54, 53, 52, 38, 39, 53, 33, 21, 35, 30, 1, 21, 20, 6, 32, 38, 53, 52, 54, 55, 1, 32, 1, 22, 68, 82,111,182,111, 87, 63, 1,
+ 19,149, 72, 69,178,254,228,179, 66, 75, 4,179, 92,123, 39,121, 75, 89,109,109, 89, 82,118, 35,123, 92, 56,125, 76,131,164,163,
+128, 82,121, 58, 0, 1, 1, 70, 2,156, 3,139, 5, 15, 0, 26, 0, 0, 1, 51, 49, 30, 1, 21, 20, 6, 43, 1, 34, 38, 53, 17,
+ 51, 17, 20, 22, 63, 1, 50, 54, 53, 52, 38, 39, 38, 2, 51,203, 72, 69,179,141, 45,114,102,116, 49, 65, 32, 91,110, 91, 58, 48,
+ 4,196, 56,125, 76,131,164,108,119, 1,144,254,112, 85, 56, 1, 1,109, 89, 81,123, 31, 24, 0, 0, 1, 1, 17, 2,156, 3,192,
+ 5, 15, 0, 6, 0, 0, 1, 35, 11, 1, 35, 1, 51, 3,192,123,221,220,123, 1, 9,157, 2,156, 2, 14,253,242, 2,115, 0, 0,
+ 0, 1, 1, 97, 2,156, 3,112, 5, 16, 0, 9, 0, 0, 1, 33, 21, 1, 33, 21, 33, 53, 1, 33, 1,112, 2, 0,254,107, 1,149,
+253,241, 1,149,254,122, 5, 16, 94,254, 62, 84, 95, 1,195, 0, 0, 1, 1, 94, 1,173, 3,115, 5, 15, 0, 22, 0, 0, 1, 33,
+ 21, 1, 33, 21, 35, 21, 20, 22, 59, 1, 21, 35, 34, 39, 38, 61, 1, 33, 53, 1, 33, 1,106, 1,157,254,185, 1, 71, 1, 36, 50,
+ 23, 33, 86, 38, 39,254,175, 1, 71,254,197, 5, 15, 94,254, 61, 82, 11, 86, 54, 88, 54, 54,120, 11, 94, 1,195, 0, 2, 1, 77,
+ 2, 94, 3,132, 5, 15, 0, 20, 0, 28, 0, 0, 1, 6, 21, 35, 52, 55, 35, 53, 1, 33, 53, 33, 21, 1, 51, 54, 51, 50, 21, 22,
+ 35, 39, 48, 51, 50, 53, 52, 35, 6, 2,146, 2, 97, 3,229, 1,180,254, 92, 2, 39,254, 76,110, 38,138,143, 1,210, 13, 13,109,
+ 44, 56, 2,156, 29, 33, 33, 29, 94, 1,195, 82, 94,254, 61,162,138,106, 82, 31, 51, 1, 0, 0, 0, 1, 1, 51, 1,168, 3,158,
+ 5, 15, 0, 28, 0, 0, 1, 50, 23, 30, 1, 21, 20, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 43, 1, 53, 1, 33,
+ 53, 33, 21, 2,100, 67, 80, 62,105,191,177, 59,125, 67, 53,126, 68,120,126,117,104,110, 1, 15,254, 92, 2, 39, 3,167, 32, 23,
+120, 77,124,135, 21, 20,109, 27, 28, 84, 80, 74, 83, 93, 1, 24, 82, 94, 0, 0, 0, 3, 1, 58, 2,140, 3,151, 5,228, 0, 6,
+ 0, 13, 0, 24, 0, 0, 1, 46, 1, 35, 34, 6, 7, 5, 33, 30, 1, 51, 50, 54, 0, 32, 22, 21, 20, 6, 35, 34, 38, 53, 52, 3,
+ 26, 4, 85, 89, 88, 85, 4, 1, 99,254,157, 3, 86, 88, 89, 86,254,190, 1, 38,156,155,148,147,155, 4,108,126,162,162,126,103,
+126,163,163, 2, 93,220,208,209,219,219,209,208,255,255, 0, 37,254, 10, 4,172, 5,213, 16, 38, 2,161, 0, 0, 16, 6, 0, 36,
+ 0, 0, 0, 0,255,255, 0,133,254, 10, 4, 35, 4,123, 16, 38, 2,161, 0, 0, 16, 6, 0, 68, 0, 0, 0, 0,255,255, 0,166,
+ 0, 0, 4,113, 7, 80, 16, 38, 11,185, 0, 0, 16, 6, 0, 37, 0, 0, 0, 0,255,255, 0,193,255,227, 4, 88, 6, 20, 16, 38,
+ 2,131, 50, 0, 16, 6, 0, 69, 0, 0, 0, 0,255,255, 0,166,254, 99, 4,113, 5,213, 16, 38, 2,159, 0, 0, 16, 6, 0, 37,
+ 0, 0, 0, 0,255,255, 0,193,254, 99, 4, 88, 6, 20, 16, 38, 2,159, 0, 0, 16, 6, 0, 69, 0, 0, 0, 0,255,255, 0,166,
+254,155, 4,113, 5,213, 16, 38, 2,173, 0, 0, 16, 6, 0, 37, 0, 0, 0, 0,255,255, 0,193,254,155, 4, 88, 6, 20, 16, 38,
+ 2,173, 0, 0, 16, 6, 0, 69, 0, 0, 0, 0,255,255, 0,139,254,117, 4, 49, 7,107, 16, 39, 11,177, 0, 90, 1,117, 16, 38,
+ 2,163,100, 0, 16, 6, 0, 38, 0, 0, 0, 0,255,255, 0,195,254,117, 4, 37, 6,102, 16, 38, 0,118, 90, 0, 16, 38, 2,163,
+104, 0, 16, 6, 0, 70, 0, 0,255,255, 0,137, 0, 0, 4, 82, 7, 80, 16, 38, 11,185,206, 0, 16, 6, 0, 39, 0, 0, 0, 0,
+255,255, 0,123,255,227, 4, 18, 6, 20, 16, 38, 2,131,206, 0, 16, 6, 0, 71, 0, 0, 0, 0,255,255, 0,137,254, 99, 4, 82,
+ 5,213, 16, 38, 2,159,206, 0, 16, 6, 0, 39, 0, 0, 0, 0,255,255, 0,123,254, 99, 4, 18, 6, 20, 16, 38, 2,159, 0, 0,
+ 16, 6, 0, 71, 0, 0, 0, 0,255,255, 0,137,254,155, 4, 82, 5,213, 16, 38, 2,173,206, 0, 16, 6, 0, 39, 0, 0, 0, 0,
+255,255, 0,123,254,155, 4, 18, 6, 20, 16, 38, 2,173, 0, 0, 16, 6, 0, 71, 0, 0, 0, 0,255,255, 0,125,254,117, 4, 82,
+ 5,213, 16, 39, 2,163,254,242, 0, 0, 18, 6, 0, 39, 0, 0,255,255, 0,123,254,117, 4, 18, 6, 20, 16, 38, 2,163,236, 0,
+ 18, 6, 0, 71, 0, 0, 0, 0,255,255, 0,137,254, 27, 4, 82, 5,213, 16, 38, 2,169,206, 0, 16, 6, 0, 39, 0, 0, 0, 0,
+255,255, 0,123,254, 27, 4, 18, 6, 20, 16, 38, 2,169, 0, 0, 16, 6, 0, 71, 0, 0, 0, 0,255,255, 0,197,254, 27, 4, 78,
+ 5,213, 16, 38, 2,169, 18, 0, 16, 6, 0, 40, 0, 0, 0, 0,255,255, 0,123,254, 27, 4, 88, 4,123, 16, 38, 2,169, 14, 0,
+ 16, 6, 0, 72, 0, 0, 0, 0,255,255, 0,197,254, 27, 4, 78, 5,213, 16, 38, 2,172, 18, 0, 16, 6, 0, 40, 0, 0, 0, 0,
+255,255, 0,123,254, 27, 4, 88, 4,123, 16, 38, 2,172, 14, 0, 16, 6, 0, 72, 0, 0, 0, 0,255,255, 0,197,254,117, 4, 78,
+ 7,109, 16, 38, 11,184, 18, 0, 16, 38, 0, 40, 0, 0, 16, 6, 2,163, 50, 0,255,255, 0,123,254,117, 4, 88, 6, 72, 16, 38,
+ 2,130, 14, 0, 16, 38, 0, 72, 0, 0, 16, 6, 2,163, 50, 0,255,255, 0,233, 0, 0, 4, 88, 7, 80, 16, 38, 11,185, 54, 0,
+ 16, 6, 0, 41, 0, 0, 0, 0,255,255, 0,195, 0, 0, 4, 39, 7, 80, 16, 38, 11,185, 0, 0, 16, 6, 0, 73, 0, 0, 0, 0,
+255,255, 0,102,255,227, 4, 80, 7, 48, 16, 38, 11,189, 50, 0, 16, 6, 0, 42, 0, 0, 0, 0,255,255, 0,123,254, 72, 4, 18,
+ 5,246, 16, 38, 2,128, 0, 0, 16, 6, 0, 74, 0, 0, 0, 0,255,255, 0,137, 0, 0, 4, 72, 7, 80, 16, 38, 11,185, 0, 0,
+ 16, 6, 0, 43, 0, 0, 0, 0,255,255, 0,195, 0, 0, 4, 27, 7, 80, 16, 38, 11,185, 0, 0, 16, 6, 0, 75, 0, 0, 0, 0,
+255,255, 0,137,254, 99, 4, 72, 5,213, 16, 38, 2,159, 0, 0, 16, 6, 0, 43, 0, 0, 0, 0,255,255, 0,195,254, 99, 4, 27,
+ 6, 20, 16, 38, 2,159, 0, 0, 16, 6, 0, 75, 0, 0, 0, 0,255,255, 0, 20,254,117, 4, 72, 5,213, 16, 39, 2,163,254,137,
+ 0, 0, 16, 6, 0, 43, 0, 0,255,255, 0, 55,254,117, 4, 27, 6, 20, 16, 39, 2,163,254,172, 0, 0, 16, 6, 0, 75, 0, 0,
+255,255, 0,137,254, 25, 4, 72, 5,213, 16, 38, 2,170, 0, 0, 16, 6, 0, 43, 0, 0, 0, 0,255,255, 0,195,254, 25, 4, 27,
+ 6, 20, 16, 38, 2,170, 0, 0, 16, 6, 0, 75, 0, 0, 0, 0,255,255, 0,201,254, 27, 4, 6, 5,213, 16, 38, 2,172, 0, 0,
+ 16, 6, 0, 44, 0, 0, 0, 0,255,255, 0,178,254, 27, 4, 68, 6, 20, 16, 38, 2,172, 0, 0, 16, 6, 0, 76, 0, 0, 0, 0,
+255,255, 0,137, 0, 0, 4,201, 7,107, 16, 39, 11,177, 0, 0, 1,117, 16, 6, 0, 46, 0, 0,255,255, 0,236, 0, 0, 4,178,
+ 7,107, 16, 39, 11,177,255, 37, 1,117, 16, 6, 0, 78, 0, 0,255,255, 0,137,254, 99, 4,201, 5,213, 16, 38, 2,159, 0, 0,
+ 16, 6, 0, 46, 0, 0, 0, 0,255,255, 0,236,254, 99, 4,178, 6, 20, 16, 38, 2,159, 50, 0, 16, 6, 0, 78, 0, 0, 0, 0,
+255,255, 0,137,254,155, 4,201, 5,213, 16, 38, 2,173, 0, 0, 16, 6, 0, 46, 0, 0, 0, 0,255,255, 0,236,254,155, 4,178,
+ 6, 20, 16, 38, 2,173, 50, 0, 16, 6, 0, 78, 0, 0, 0, 0,255,255, 0,215,254, 99, 4,115, 5,213, 16, 38, 2,159, 50, 0,
+ 16, 6, 0, 47, 0, 0, 0, 0,255,255, 0,160,254, 99, 4, 10, 6, 31, 16, 38, 2,159, 0, 0, 16, 6, 0, 79, 0, 0, 0, 0,
+255,255, 0,215,254, 99, 4,115, 7, 48, 16, 38, 11,189, 0, 0, 16, 6, 5, 52, 0, 0, 0, 0,255,255, 0,160,254, 99, 4, 10,
+ 7, 48, 16, 38, 11,189, 0, 0, 16, 6, 5, 53, 0, 0, 0, 0,255,255, 0,215,254,155, 4,115, 5,213, 16, 38, 2,173, 50, 0,
+ 16, 6, 0, 47, 0, 0, 0, 0,255,255, 0,160,254,155, 4, 10, 6, 31, 16, 38, 2,173, 0, 0, 16, 6, 0, 79, 0, 0, 0, 0,
+255,255, 0,215,254, 27, 4,115, 5,213, 16, 38, 2,169, 50, 0, 16, 6, 0, 47, 0, 0, 0, 0,255,255, 0,160,254, 27, 4, 10,
+ 6, 31, 16, 38, 2,169, 0, 0, 16, 6, 0, 79, 0, 0, 0, 0,255,255, 0, 86, 0, 0, 4,121, 7,107, 16, 39, 11,177, 0, 0,
+ 1,117, 16, 6, 0, 48, 0, 0,255,255, 0,109, 0, 0, 4,111, 6,102, 16, 38, 0,118, 0, 0, 16, 6, 0, 80, 0, 0, 0, 0,
+255,255, 0, 86, 0, 0, 4,121, 7, 80, 16, 38, 11,185, 0, 0, 16, 6, 0, 48, 0, 0, 0, 0,255,255, 0,109, 0, 0, 4,111,
+ 6, 16, 16, 38, 2,131, 0, 0, 18, 6, 0, 80, 0, 0, 0, 0,255,255, 0, 86,254, 99, 4,121, 5,213, 16, 38, 2,159, 0, 0,
+ 16, 6, 0, 48, 0, 0, 0, 0,255,255, 0,109,254, 99, 4,111, 4,123, 16, 38, 2,159, 0, 0, 16, 6, 0, 80, 0, 0, 0, 0,
+255,255, 0,139, 0, 0, 4, 70, 7, 80, 16, 38, 11,185, 0, 0, 16, 6, 0, 49, 0, 0, 0, 0,255,255, 0,195, 0, 0, 4, 27,
+ 6, 16, 16, 38, 2,131, 0, 0, 16, 6, 0, 81, 0, 0, 0, 0,255,255, 0,139,254, 99, 4, 70, 5,213, 16, 38, 2,159, 0, 0,
+ 16, 6, 0, 49, 0, 0, 0, 0,255,255, 0,195,254, 99, 4, 27, 4,123, 16, 38, 2,159, 0, 0, 16, 6, 0, 81, 0, 0, 0, 0,
+255,255, 0,139,254,155, 4, 70, 5,213, 16, 38, 2,173, 0, 0, 16, 6, 0, 49, 0, 0, 0, 0,255,255, 0,195,254,155, 4, 27,
+ 4,123, 16, 38, 2,173, 0, 0, 16, 6, 0, 81, 0, 0, 0, 0,255,255, 0,139,254, 27, 4, 70, 5,213, 16, 38, 2,169, 0, 0,
+ 16, 6, 0, 49, 0, 0, 0, 0,255,255, 0,195,254, 27, 4, 27, 4,123, 16, 38, 2,169, 0, 0, 16, 6, 0, 81, 0, 0, 0, 0,
+255,255, 0,197, 0, 0, 4,117, 7, 80, 16, 38, 11,185, 0, 0, 16, 6, 0, 51, 0, 0, 0, 0,255,255, 0,190,254, 86, 4, 84,
+ 6, 16, 16, 38, 2,131, 0, 0, 18, 6, 0, 83, 0, 0, 0, 0,255,255, 0,143, 0, 0, 4,209, 7, 80, 16, 38, 11,185,206, 0,
+ 16, 6, 0, 53, 0, 0, 0, 0,255,255, 1,106, 0, 0, 4,131, 6, 16, 16, 38, 2,131, 0, 0, 16, 6, 0, 85, 0, 0, 0, 0,
+255,255, 0,143,254, 99, 4,209, 5,213, 16, 38, 2,159,206, 0, 16, 6, 0, 53, 0, 0, 0, 0,255,255, 1,106,254, 99, 4,131,
+ 4,123, 16, 38, 2,159, 0, 0, 16, 6, 0, 85, 0, 0, 0, 0,255,255, 0,143,254, 99, 4,209, 7, 48, 16, 38, 11,189,206, 0,
+ 16, 6, 5, 78, 0, 0, 0, 0,255,255, 1, 61,254, 99, 4,131, 5,246, 16, 38, 2,128, 0, 0, 16, 6, 5, 79, 0, 0, 0, 0,
+255,255, 0,143,254,155, 4,209, 5,213, 16, 38, 2,173, 0, 0, 16, 6, 0, 53, 0, 0, 0, 0,255,255, 1, 61,254,155, 4,131,
+ 4,123, 16, 38, 2,173, 0, 0, 16, 6, 0, 85, 0, 0, 0, 0,255,255, 0,139,255,227, 4, 74, 7, 80, 16, 38, 11,185, 0, 0,
+ 16, 6, 0, 54, 0, 0, 0, 0,255,255, 0,213,255,227, 4, 6, 6, 16, 16, 38, 2,131, 0, 0, 18, 6, 0, 86, 0, 0, 0, 0,
+255,255, 0,139,254, 99, 4, 74, 5,240, 16, 38, 2,159, 0, 0, 16, 6, 0, 54, 0, 0, 0, 0,255,255, 0,213,254, 99, 4, 6,
+ 4,123, 16, 38, 2,159, 0, 0, 16, 6, 0, 86, 0, 0, 0, 0,255,255, 0,139,254, 99, 4, 74, 7, 80, 16, 38, 11,185, 0, 0,
+ 16, 38, 0, 54, 0, 0, 16, 6, 2,159, 0, 0,255,255, 0,213,254, 99, 4, 6, 6, 16, 16, 38, 2,131, 0, 0, 16, 38, 0, 86,
+ 0, 0, 16, 6, 2,159, 0, 0,255,255, 0, 47, 0, 0, 4,162, 7, 80, 16, 38, 11,185, 0, 0, 16, 6, 0, 55, 0, 0, 0, 0,
+255,255, 0,131, 0, 0, 4, 8, 7, 80, 16, 38, 11,185, 0, 0, 16, 6, 0, 87, 0, 0, 0, 0,255,255, 0, 47,254, 99, 4,162,
+ 5,213, 16, 38, 2,159, 0, 0, 16, 6, 0, 55, 0, 0, 0, 0,255,255, 0,131,254, 99, 4, 8, 5,158, 16, 38, 2,159, 0, 0,
+ 16, 6, 0, 87, 0, 0, 0, 0,255,255, 0, 47,254,155, 4,162, 5,213, 16, 38, 2,173, 0, 0, 16, 6, 0, 55, 0, 0, 0, 0,
+255,255, 0,131,254,155, 4, 8, 5,158, 16, 38, 2,173, 0, 0, 16, 6, 0, 87, 0, 0, 0, 0,255,255, 0, 47,254, 27, 4,162,
+ 5,213, 16, 38, 2,169, 0, 0, 16, 6, 0, 55, 0, 0, 0, 0,255,255, 0,131,254, 27, 4, 8, 5,158, 16, 38, 2,169, 0, 0,
+ 16, 6, 0, 87, 0, 0, 0, 0,255,255, 0,147,254,100, 4, 61, 5,213, 16, 38, 2,160, 0, 0, 16, 6, 0, 56, 0, 0, 0, 0,
+255,255, 0,195,254,100, 4, 27, 4, 94, 16, 38, 2,160, 0, 0, 16, 6, 0, 88, 0, 0, 0, 0,255,255, 0,147,254, 27, 4, 61,
+ 5,213, 16, 38, 2,172, 0, 0, 16, 6, 0, 56, 0, 0, 0, 0,255,255, 0,195,254, 27, 4, 27, 4, 94, 16, 38, 2,172, 0, 0,
+ 16, 6, 0, 88, 0, 0, 0, 0,255,255, 0,147,254, 27, 4, 61, 5,213, 16, 38, 2,169, 0, 0, 16, 6, 0, 56, 0, 0, 0, 0,
+255,255, 0,195,254, 27, 4, 27, 4, 94, 16, 38, 2,169, 0, 0, 16, 6, 0, 88, 0, 0, 0, 0,255,255, 0, 57,254, 99, 4,152,
+ 5,213, 16, 38, 2,159, 0, 0, 16, 6, 0, 57, 0, 0, 0, 0,255,255, 0,100,254, 99, 4,109, 4, 96, 16, 38, 2,159, 0, 0,
+ 16, 6, 0, 89, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 4,209, 7,114, 16, 39, 11,179, 0, 0, 1,124, 16, 6, 0, 58, 0, 0,
+255,255, 0, 0, 0, 0, 4,209, 6,109, 16, 38, 0, 67,192, 7, 16, 6, 0, 90, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 4,209,
+ 7,114, 16, 39, 11,177, 0, 0, 1,124, 16, 6, 0, 58, 0, 0,255,255, 0, 0, 0, 0, 4,209, 6,109, 16, 38, 0,118, 64, 7,
+ 16, 6, 0, 90, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 4,209, 7, 52, 16, 39, 0,106, 0, 0, 1, 36, 16, 6, 0, 58, 0, 0,
+255,255, 0, 0, 0, 0, 4,209, 5,191, 16, 38, 0,106, 0,175, 16, 6, 0, 90, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 4,209,
+ 7, 80, 16, 38, 11,185, 0, 0, 16, 6, 0, 58, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 4,209, 6, 16, 16, 38, 2,131, 0, 0,
+ 16, 6, 0, 90, 0, 0, 0, 0,255,255, 0, 0,254, 99, 4,209, 5,213, 16, 38, 2,159, 0, 0, 16, 6, 0, 58, 0, 0, 0, 0,
+255,255, 0, 0,254, 99, 4,209, 4, 96, 16, 38, 2,159, 0, 0, 16, 6, 0, 90, 0, 0, 0, 0,255,255, 0, 18, 0, 0, 4,190,
+ 7, 80, 16, 38, 11,185, 0, 0, 16, 6, 0, 59, 0, 0, 0, 0,255,255, 0, 76, 0, 0, 4,133, 6, 16, 16, 38, 2,131, 0, 0,
+ 16, 6, 0, 91, 0, 0, 0, 0,255,255, 0, 37, 0, 0, 4,172, 7, 80, 16, 38, 11,185, 0, 0, 16, 6, 0, 60, 0, 0, 0, 0,
+255,255, 0,104,254, 86, 4,129, 6, 16, 16, 38, 2,131, 0, 0, 16, 6, 0, 92, 0, 0, 0, 0,255,255, 0,156,254, 99, 4,145,
+ 5,213, 16, 38, 2,159, 50, 0, 18, 6, 0, 61, 0, 0, 0, 0,255,255, 0,203,254, 99, 4, 16, 4, 98, 16, 38, 2,159, 0, 0,
+ 18, 6, 0, 93, 0, 0, 0, 0,255,255, 0,156,254,155, 4,145, 5,213, 16, 38, 2,173, 50, 0, 16, 6, 0, 61, 0, 0, 0, 0,
+255,255, 0,203,254,155, 4, 16, 4, 98, 16, 38, 2,173, 0, 0, 16, 6, 0, 93, 0, 0, 0, 0,255,255, 0,195,254,155, 4, 27,
+ 6, 20, 16, 38, 2,173, 0, 0, 16, 6, 0, 75, 0, 0, 0, 0,255,255, 0,195, 0, 0, 4, 39, 7, 80, 16, 38, 11,185, 0, 0,
+ 16, 6, 1, 65, 0, 0, 0, 0,255,255, 0, 37,254, 99, 4,172, 5,213, 16, 38, 2,159, 0, 0, 16, 6, 0, 36, 0, 0, 0, 0,
+255,255, 0,133,254, 99, 4, 35, 4,123, 16, 38, 2,159, 0, 0, 16, 6, 0, 68, 0, 0, 0, 0,255,255, 0, 37, 0, 0, 4,172,
+ 7,249, 16, 38, 11,184, 0,128, 16, 38, 0, 36, 0, 0, 16, 7, 11,179, 0, 0, 2, 3, 0, 0,255,255, 0,133,255,227, 4, 35,
+ 7,162, 16, 39, 2,124, 0, 0, 1, 60, 18, 6, 0,197, 0, 0,255,255, 0,197,254, 99, 4, 78, 5,213, 16, 38, 2,159, 18, 0,
+ 16, 6, 0, 40, 0, 0, 0, 0,255,255, 0,123,254, 99, 4, 88, 4,123, 16, 38, 2,159, 14, 0, 16, 6, 0, 72, 0, 0, 0, 0,
+255,255, 0,197, 0, 0, 4, 78, 7, 94, 16, 39, 11,178, 0, 42, 1,117, 16, 6, 0, 40, 0, 0,255,255, 0,123,255,227, 4, 88,
+ 6, 55, 16, 38, 2,110, 0, 0, 16, 6, 0, 72, 0, 0, 0, 0,255,255, 0,201,254, 99, 4, 6, 5,213, 16, 38, 2,159, 0, 0,
+ 16, 6, 0, 44, 0, 0, 0, 0,255,255, 0,178,254, 99, 4, 68, 6, 20, 16, 38, 2,159, 0, 0, 16, 6, 0, 76, 0, 0, 0, 0,
+255,255, 0,117,254, 99, 4, 92, 5,240, 16, 38, 2,159, 0, 0, 16, 6, 0, 50, 0, 0, 0, 0,255,255, 0,137,254, 99, 4, 72,
+ 4,123, 16, 38, 2,159, 0, 0, 16, 6, 0, 82, 0, 0, 0, 0,255,255, 0,147,254, 99, 4, 61, 5,213, 16, 38, 2,159, 0, 0,
+ 16, 6, 0, 56, 0, 0, 0, 0,255,255, 0,195,254, 99, 4, 27, 4, 94, 16, 38, 2,159, 0, 0, 16, 6, 0, 88, 0, 0, 0, 0,
+255,255, 0, 37, 0, 0, 4,172, 7,114, 16, 39, 11,179, 0, 0, 1,124, 16, 6, 0, 60, 0, 0,255,255, 0,104,254, 86, 4,129,
+ 6,109, 16, 38, 0, 67,204, 7, 16, 6, 0, 92, 0, 0, 0, 0,255,255, 0, 37,254, 99, 4,172, 5,213, 16, 38, 2,159, 0, 0,
+ 16, 6, 0, 60, 0, 0, 0, 0,255,255, 0,104,254, 86, 4,129, 4, 96, 16, 39, 2,159, 0,250, 0, 0, 16, 6, 0, 92, 0, 0,
+255,255, 0, 37, 0, 0, 4,172, 7, 94, 16, 39, 11,178, 0, 0, 1,117, 16, 6, 0, 60, 0, 0,255,255, 0,104,254, 86, 4,129,
+ 6, 55, 16, 38, 2,110, 0, 0, 16, 6, 0, 92, 0, 0, 0, 0,255,255, 0, 70,255,230, 4,149, 6,114, 16, 38, 2,237, 0, 0,
+ 16, 6, 6, 66, 0, 0, 0, 0,255,255, 0, 70,255,230, 4,149, 6,114, 16, 38, 2,237, 0, 0, 16, 6, 6,122, 0, 0, 0, 0,
+255,255, 0, 70,255,230, 4,149, 6,114, 16, 38, 2,237, 0, 0, 16, 6, 6, 79, 0, 0, 0, 0,255,255, 0, 70,255,230, 4,149,
+ 6,114, 16, 38, 2,237, 0, 0, 16, 6, 6, 92, 0, 0, 0, 0,255,255, 0, 70,255,230, 4,149, 6,114, 16, 38, 2,237, 0, 0,
+ 16, 6, 6, 80, 0, 0, 0, 0,255,255, 0, 70,255,230, 4,149, 6,114, 16, 38, 2,237, 0, 0, 16, 6, 6, 93, 0, 0, 0, 0,
+255,255, 0, 70,255,230, 4,149, 7,209, 16, 38, 2,237, 0, 0, 16, 6, 6, 81, 0, 0, 0, 0,255,255, 0, 70,255,230, 4,149,
+ 7,209, 16, 38, 2,237, 0, 0, 16, 6, 6, 94, 0, 0, 0, 0,255,255, 0, 37, 0, 0, 4,172, 6,114, 16, 38, 2,206, 0, 0,
+ 16, 7, 6, 66,254,162, 0, 0,255,255, 0, 37, 0, 0, 4,172, 6,114, 16, 38, 2,206, 0, 0, 16, 7, 6,122,254,112, 0, 0,
+255,255,254,107, 0, 0, 4,172, 6,114, 16, 38, 2,206, 0, 0, 16, 7, 6, 79,253,118, 0, 0,255,255,254,107, 0, 0, 4,172,
+ 6,114, 16, 38, 2,206, 0, 0, 16, 7, 6, 92,253,118, 0, 0,255,255,255, 26, 0, 0, 4,172, 6,114, 16, 38, 2,206, 0, 0,
+ 16, 7, 6, 80,253,243, 0, 0,255,255,255, 6, 0, 0, 4,172, 6,114, 16, 38, 2,206, 0, 0, 16, 7, 6, 93,253,243, 0, 0,
+255,255,255,193, 0, 0, 4,172, 7,209, 16, 38, 2,206, 0, 0, 16, 7, 6, 81,254,162, 0, 0,255,255,255,143, 0, 0, 4,172,
+ 7,209, 16, 38, 2,206, 0, 0, 16, 7, 6, 94,254,112, 0, 0,255,255, 0,169,255,234, 4, 40, 6,114, 16, 38, 2,241, 0, 0,
+ 16, 6, 6, 66, 0, 0, 0, 0,255,255, 0,169,255,234, 4, 40, 6,114, 16, 38, 2,241, 0, 0, 16, 6, 6,122, 0, 0, 0, 0,
+255,255, 0,169,255,234, 4, 40, 6,114, 16, 38, 2,241, 0, 0, 16, 6, 6, 79, 0, 0, 0, 0,255,255, 0,169,255,234, 4, 40,
+ 6,114, 16, 38, 2,241, 0, 0, 16, 6, 6, 92, 0, 0, 0, 0,255,255, 0,169,255,234, 4, 40, 6,114, 16, 38, 2,241, 0, 0,
+ 16, 6, 6, 80, 0, 0, 0, 0,255,255, 0,169,255,234, 4, 40, 6,114, 16, 38, 2,241, 0, 0, 16, 6, 6, 93, 0, 0, 0, 0,
+255,255,255,126, 0, 0, 4, 78, 6,114, 16, 38, 2,210, 0, 0, 16, 7, 6, 66,253,143, 0, 0,255,255,255,126, 0, 0, 4, 78,
+ 6,114, 16, 38, 2,210, 0, 0, 16, 7, 6,122,253,143, 0, 0,255,255,253,138, 0, 0, 4, 78, 6,114, 16, 38, 2,210, 0, 0,
+ 16, 7, 6, 79,252,149, 0, 0,255,255,253,138, 0, 0, 4, 78, 6,114, 16, 38, 2,210, 0, 0, 16, 7, 6, 92,252,149, 0, 0,
+255,255,254, 7, 0, 0, 4, 78, 6,114, 16, 38, 2,210, 0, 0, 16, 7, 6, 80,252,224, 0, 0,255,255,253,243, 0, 0, 4, 78,
+ 6,114, 16, 38, 2,210, 0, 0, 16, 7, 6, 93,252,224, 0, 0,255,255, 0,195,254, 86, 4, 27, 6,114, 16, 38, 2,243, 0, 0,
+ 16, 6, 6, 66, 0, 0, 0, 0,255,255, 0,195,254, 86, 4, 27, 6,114, 16, 38, 2,243, 0, 0, 16, 6, 6,122, 0, 0, 0, 0,
+255,255, 0,195,254, 86, 4, 27, 6,114, 16, 38, 2,243, 0, 0, 16, 6, 6, 79, 0, 0, 0, 0,255,255, 0,195,254, 86, 4, 27,
+ 6,114, 16, 38, 2,243, 0, 0, 16, 6, 6, 92, 0, 0, 0, 0,255,255, 0,195,254, 86, 4, 30, 6,114, 16, 38, 2,243, 0, 0,
+ 16, 6, 6, 80, 0, 0, 0, 0,255,255, 0,195,254, 86, 4, 30, 6,114, 16, 38, 2,243, 0, 0, 16, 6, 6, 93, 0, 0, 0, 0,
+255,255, 0,195,254, 86, 4, 27, 7,209, 16, 38, 2,243, 0, 0, 16, 6, 6, 81, 0, 0, 0, 0,255,255, 0,195,254, 86, 4, 27,
+ 7,209, 16, 38, 2,243, 0, 0, 16, 6, 6, 94, 0, 0, 0, 0,255,255,255, 76, 0, 0, 4, 72, 6,114, 16, 38, 2,212, 0, 0,
+ 16, 7, 6, 66,253, 93, 0, 0,255,255,255, 76, 0, 0, 4, 72, 6,114, 16, 38, 2,212, 0, 0, 16, 7, 6,122,253, 93, 0, 0,
+255,255,253, 63, 0, 0, 4, 72, 6,114, 16, 38, 2,212, 0, 0, 16, 7, 6, 79,252, 74, 0, 0,255,255,253, 63, 0, 0, 4, 72,
+ 6,114, 16, 38, 2,212, 0, 0, 16, 7, 6, 92,252, 74, 0, 0,255,255,253,163, 0, 0, 4, 72, 6,114, 16, 38, 2,212, 0, 0,
+ 16, 7, 6, 80,252,124, 0, 0,255,255,253,143, 0, 0, 4, 72, 6,114, 16, 38, 2,212, 0, 0, 16, 7, 6, 93,252,124, 0, 0,
+255,255,254, 99, 0, 0, 4, 72, 7,209, 16, 38, 2,212, 0, 0, 16, 7, 6, 81,253, 68, 0, 0,255,255,254, 99, 0, 0, 4, 72,
+ 7,209, 16, 38, 2,212, 0, 0, 16, 7, 6, 94,253, 68, 0, 0,255,255, 1, 54, 0, 0, 3,207, 6,114, 16, 38, 2,245, 0, 0,
+ 16, 6, 6, 66, 0, 0, 0, 0,255,255, 1, 54, 0, 0, 3,207, 6,114, 16, 38, 2,245, 0, 0, 16, 6, 6,122, 0, 0, 0, 0,
+255,255, 0,245, 0, 0, 3,240, 6,114, 16, 38, 2,245, 0, 0, 16, 6, 6, 79, 0, 0, 0, 0,255,255, 0,245, 0, 0, 3,240,
+ 6,114, 16, 38, 2,245, 0, 0, 16, 6, 6, 92, 0, 0, 0, 0,255,255, 1, 39, 0, 0, 4, 30, 6,114, 16, 38, 2,245, 0, 0,
+ 16, 6, 6, 80, 0, 0, 0, 0,255,255, 1, 19, 0, 0, 4, 30, 6,114, 16, 38, 2,245, 0, 0, 16, 6, 6, 93, 0, 0, 0, 0,
+255,255, 1, 31, 0, 0, 3,207, 7,209, 16, 38, 2,245, 0, 0, 16, 6, 6, 81, 0, 0, 0, 0,255,255, 1, 31, 0, 0, 3,207,
+ 7,209, 16, 38, 2,245, 0, 0, 16, 6, 6, 94, 0, 0, 0, 0,255,255,255,126, 0, 0, 4, 6, 6,114, 16, 38, 2,214, 0, 0,
+ 16, 7, 6, 66,253,143, 0, 0,255,255,255,126, 0, 0, 4, 6, 6,114, 16, 38, 2,214, 0, 0, 16, 7, 6,122,253,143, 0, 0,
+255,255,253,163, 0, 0, 4, 6, 6,114, 16, 38, 2,214, 0, 0, 16, 7, 6, 79,252,174, 0, 0,255,255,253,163, 0, 0, 4, 6,
+ 6,114, 16, 38, 2,214, 0, 0, 16, 7, 6, 92,252,174, 0, 0,255,255,254, 7, 0, 0, 4, 6, 6,114, 16, 38, 2,214, 0, 0,
+ 16, 7, 6, 80,252,224, 0, 0,255,255,253,243, 0, 0, 4, 6, 6,114, 16, 38, 2,214, 0, 0, 16, 7, 6, 93,252,224, 0, 0,
+255,255,254,174, 0, 0, 4, 6, 7,209, 16, 38, 2,214, 0, 0, 16, 7, 6, 81,253,143, 0, 0,255,255,254,174, 0, 0, 4, 6,
+ 7,209, 16, 38, 2,214, 0, 0, 16, 7, 6, 94,253,143, 0, 0,255,255, 0,137,255,227, 4, 72, 6,114, 16, 38, 2,251, 0, 0,
+ 16, 6, 6, 66, 0, 0, 0, 0,255,255, 0,137,255,227, 4, 72, 6,114, 16, 38, 2,251, 0, 0, 16, 6, 6,122, 0, 0, 0, 0,
+255,255, 0,137,255,227, 4, 72, 6,114, 16, 38, 2,251, 0, 0, 16, 6, 6, 79, 0, 0, 0, 0,255,255, 0,137,255,227, 4, 72,
+ 6,114, 16, 38, 2,251, 0, 0, 16, 6, 6, 92, 0, 0, 0, 0,255,255, 0,137,255,227, 4, 72, 6,114, 16, 38, 2,251, 0, 0,
+ 16, 6, 6, 80, 0, 0, 0, 0,255,255, 0,137,255,227, 4, 72, 6,114, 16, 38, 2,251, 0, 0, 16, 6, 6, 93, 0, 0, 0, 0,
+255,255,255,201,255,227, 4, 92, 6,114, 16, 38, 2,220, 0, 0, 16, 7, 6, 66,253,218, 0, 0,255,255,255,126,255,227, 4, 92,
+ 6,114, 16, 38, 2,220, 0, 0, 16, 7, 6,122,253,143, 0, 0,255,255,253,138,255,227, 4, 92, 6,114, 16, 38, 2,220, 0, 0,
+ 16, 7, 6, 79,252,149, 0, 0,255,255,253,138,255,227, 4, 92, 6,114, 16, 38, 2,220, 0, 0, 16, 7, 6, 92,252,149, 0, 0,
+255,255,254,157,255,227, 4, 92, 6,114, 16, 38, 2,220, 0, 0, 16, 7, 6, 80,253,118, 0, 0,255,255,254,137,255,227, 4, 92,
+ 6,114, 16, 38, 2,220, 0, 0, 16, 7, 6, 93,253,118, 0, 0,255,255, 0, 51,255,255, 4,105, 6,114, 16, 38, 3, 1, 0, 0,
+ 16, 6, 6, 66, 0, 0, 0, 0,255,255, 0, 51,255,255, 4,105, 6,114, 16, 38, 3, 1, 0, 0, 16, 6, 6,122, 0, 0, 0, 0,
+255,255, 0, 51,255,255, 4,105, 6,114, 16, 38, 3, 1, 0, 0, 16, 6, 6, 79, 0, 0, 0, 0,255,255, 0, 51,255,255, 4,105,
+ 6,114, 16, 38, 3, 1, 0, 0, 16, 6, 6, 92, 0, 0, 0, 0,255,255, 0, 51,255,255, 4,105, 6,114, 16, 38, 3, 1, 0, 0,
+ 16, 6, 6, 80, 0, 0, 0, 0,255,255, 0, 51,255,255, 4,105, 6,114, 16, 38, 3, 1, 0, 0, 16, 6, 6, 93, 0, 0, 0, 0,
+255,255, 0, 51,255,255, 4,105, 7,209, 16, 38, 3, 1, 0, 0, 16, 6, 6, 81, 0, 0, 0, 0,255,255, 0, 51,255,255, 4,105,
+ 7,209, 16, 38, 3, 1, 0, 0, 16, 6, 6, 94, 0, 0, 0, 0,255,255,254,232, 0, 0, 4,172, 6,114, 16, 38, 2,225, 0, 0,
+ 16, 7, 6,122,252,249, 0, 0,255,255,253, 63, 0, 0, 4,172, 6,114, 16, 38, 2,225, 0, 0, 16, 7, 6, 92,252, 74, 0, 0,
+255,255,253, 68, 0, 0, 4,172, 6,114, 16, 38, 2,225, 0, 0, 16, 7, 6, 93,252, 49, 0, 0,255,255,254, 24, 0, 0, 4,172,
+ 7,209, 16, 38, 2,225, 0, 0, 16, 7, 6, 94,252,249, 0, 0,255,255, 0, 70,255,227, 4,140, 6,114, 16, 38, 3, 5, 0, 0,
+ 16, 6, 6, 66, 0, 0, 0, 0,255,255, 0, 70,255,227, 4,140, 6,114, 16, 38, 3, 5, 0, 0, 16, 6, 6,122, 0, 0, 0, 0,
+255,255, 0, 70,255,227, 4,140, 6,114, 16, 38, 3, 5, 0, 0, 16, 6, 6, 79, 0, 0, 0, 0,255,255, 0, 70,255,227, 4,140,
+ 6,114, 16, 38, 3, 5, 0, 0, 16, 6, 6, 92, 0, 0, 0, 0,255,255, 0, 70,255,227, 4,140, 6,114, 16, 38, 3, 5, 0, 0,
+ 16, 6, 6, 80, 0, 0, 0, 0,255,255, 0, 70,255,227, 4,140, 6,114, 16, 38, 3, 5, 0, 0, 16, 6, 6, 93, 0, 0, 0, 0,
+255,255, 0, 70,255,227, 4,140, 7,209, 16, 38, 3, 5, 0, 0, 16, 6, 6, 81, 0, 0, 0, 0,255,255, 0, 70,255,227, 4,140,
+ 7,209, 16, 38, 3, 5, 0, 0, 16, 6, 6, 94, 0, 0, 0, 0,255,255,255,201, 0, 0, 4,135, 6,114, 16, 38, 2,229, 0, 0,
+ 16, 7, 6, 66,253,218, 0, 0,255,255,255,101, 0, 0, 4,135, 6,114, 16, 38, 2,229, 0, 0, 16, 7, 6,122,253,118, 0, 0,
+255,255,253,138, 0, 0, 4,135, 6,114, 16, 38, 2,229, 0, 0, 16, 7, 6, 79,252,149, 0, 0,255,255,253,138, 0, 0, 4,135,
+ 6,114, 16, 38, 2,229, 0, 0, 16, 7, 6, 92,252,149, 0, 0,255,255,254,182, 0, 0, 4,135, 6,114, 16, 38, 2,229, 0, 0,
+ 16, 7, 6, 80,253,143, 0, 0,255,255,254,162, 0, 0, 4,135, 6,114, 16, 38, 2,229, 0, 0, 16, 7, 6, 93,253,143, 0, 0,
+255,255,254,249, 0, 0, 4,135, 7,209, 16, 38, 2,229, 0, 0, 16, 7, 6, 81,253,218, 0, 0,255,255,254,174, 0, 0, 4,135,
+ 7,209, 16, 38, 2,229, 0, 0, 16, 7, 6, 94,253,143, 0, 0,255,255, 0, 70,255,230, 4,149, 6,102, 16, 38, 2,237, 0, 0,
+ 16, 6, 0, 67, 0, 0, 0, 0,255,255, 0, 70,255,230, 4,149, 6,102, 16, 6, 2,232, 0, 0,255,255, 0,169,255,234, 4, 40,
+ 6,102, 16, 38, 2,241, 0, 0, 16, 6, 0, 67, 0, 0, 0, 0,255,255, 0,169,255,234, 4, 40, 6,102, 16, 6, 2,233, 0, 0,
+255,255, 0,195,254, 86, 4, 27, 6,102, 16, 38, 2,243, 0, 0, 16, 6, 0, 67, 0, 0, 0, 0,255,255, 0,195,254, 86, 4, 27,
+ 6,102, 16, 6, 2,234, 0, 0,255,255, 1, 23, 0, 0, 3,207, 6,102, 16, 38, 2,245, 0, 0, 16, 6, 0, 67, 0, 0, 0, 0,
+255,255, 1, 54, 0, 0, 3,207, 6,102, 16, 6, 2,235, 0, 0,255,255, 0,137,255,227, 4, 72, 6,102, 16, 38, 2,251, 0, 0,
+ 16, 6, 0, 67, 0, 0, 0, 0,255,255, 0,137,255,227, 4, 72, 6,102, 16, 6, 3, 8, 0, 0,255,255, 0, 51,255,255, 4,105,
+ 6,102, 16, 38, 3, 1, 0, 0, 16, 6, 0, 67, 0, 0, 0, 0,255,255, 0, 51,255,255, 4,105, 6,102, 16, 6, 3, 9, 0, 0,
+255,255, 0, 70,255,227, 4,140, 6,102, 16, 38, 3, 5, 0, 0, 16, 6, 0, 67, 0, 0, 0, 0,255,255, 0, 70,255,227, 4,140,
+ 6,102, 16, 6, 3, 10, 0, 0,255,255, 0, 70,254, 86, 4,149, 6,114, 16, 38, 5,146, 0, 0, 16, 6, 2,193,156, 0, 0, 0,
+255,255, 0, 70,254, 86, 4,149, 6,114, 16, 38, 5,147, 0, 0, 16, 6, 2,193,156, 0, 0, 0,255,255, 0, 70,254, 86, 4,149,
+ 6,114, 16, 38, 5,148, 0, 0, 16, 6, 2,193,156, 0, 0, 0,255,255, 0, 70,254, 86, 4,149, 6,114, 16, 38, 5,149, 0, 0,
+ 16, 6, 2,193,156, 0, 0, 0,255,255, 0, 70,254, 86, 4,149, 6,114, 16, 38, 2,193,156, 0, 16, 6, 5,150, 0, 0, 0, 0,
+255,255, 0, 70,254, 86, 4,149, 6,114, 16, 38, 2,193,156, 0, 16, 6, 5,151, 0, 0, 0, 0,255,255, 0, 70,254, 86, 4,149,
+ 7,209, 16, 38, 5,152, 0, 0, 16, 6, 2,193,156, 0, 0, 0,255,255, 0, 70,254, 86, 4,149, 7,209, 16, 38, 5,153, 0, 0,
+ 16, 6, 2,193,156, 0, 0, 0,255,255, 0, 37,254, 86, 4,172, 6,114, 16, 38, 5,154, 0, 0, 16, 6, 6, 65, 0, 0, 0, 0,
+255,255, 0, 37,254, 86, 4,172, 6,114, 16, 38, 5,155, 0, 0, 16, 6, 6, 65, 0, 0, 0, 0,255,255,254,107,254, 86, 4,172,
+ 6,114, 16, 38, 5,156, 0, 0, 16, 6, 6, 65, 0, 0, 0, 0,255,255,254,107,254, 86, 4,172, 6,114, 16, 38, 5,157, 0, 0,
+ 16, 6, 6, 65, 0, 0, 0, 0,255,255,255, 26,254, 86, 4,172, 6,114, 16, 38, 6, 65, 0, 0, 16, 6, 5,158, 0, 0, 0, 0,
+255,255,255, 6,254, 86, 4,172, 6,114, 16, 38, 6, 65, 0, 0, 16, 6, 5,159, 0, 0, 0, 0,255,255,255,193,254, 86, 4,172,
+ 7,209, 16, 38, 5,160, 0, 0, 16, 6, 6, 65, 0, 0, 0, 0,255,255,255,143,254, 86, 4,172, 7,209, 16, 38, 5,161, 0, 0,
+ 16, 6, 6, 65, 0, 0, 0, 0,255,255, 0,195,254, 86, 4, 27, 6,114, 16, 38, 5,174, 0, 0, 16, 7, 2,193,254,200, 0, 0,
+255,255, 0,195,254, 86, 4, 27, 6,114, 16, 38, 5,175, 0, 0, 16, 7, 2,193,254,200, 0, 0,255,255, 0,195,254, 86, 4, 27,
+ 6,114, 16, 38, 5,176, 0, 0, 16, 7, 2,193,254,200, 0, 0,255,255, 0,195,254, 86, 4, 27, 6,114, 16, 38, 5,177, 0, 0,
+ 16, 7, 2,193,254,200, 0, 0,255,255, 0,195,254, 86, 4, 30, 6,114, 16, 39, 2,193,254,200, 0, 0, 16, 6, 5,178, 0, 0,
+255,255, 0,195,254, 86, 4, 30, 6,114, 16, 39, 2,193,254,200, 0, 0, 16, 6, 5,179, 0, 0,255,255, 0,195,254, 86, 4, 27,
+ 7,209, 16, 38, 5,180, 0, 0, 16, 7, 2,193,254,200, 0, 0,255,255, 0,195,254, 86, 4, 27, 7,209, 16, 38, 5,181, 0, 0,
+ 16, 7, 2,193,254,200, 0, 0,255,255,255, 76,254, 86, 4, 72, 6,114, 16, 38, 5,182, 0, 0, 16, 6, 6, 65, 0, 0, 0, 0,
+255,255,255, 76,254, 86, 4, 72, 6,114, 16, 38, 5,183, 0, 0, 16, 6, 6, 65, 0, 0, 0, 0,255,255,253, 63,254, 86, 4, 72,
+ 6,114, 16, 38, 5,184, 0, 0, 16, 6, 6, 65, 0, 0, 0, 0,255,255,253, 63,254, 86, 4, 72, 6,114, 16, 38, 5,185, 0, 0,
+ 16, 6, 6, 65, 0, 0, 0, 0,255,255,253,163,254, 86, 4, 72, 6,114, 16, 38, 6, 65, 0, 0, 16, 6, 5,186, 0, 0, 0, 0,
+255,255,253,143,254, 86, 4, 72, 6,114, 16, 38, 6, 65, 0, 0, 16, 6, 5,187, 0, 0, 0, 0,255,255,254, 99,254, 86, 4, 72,
+ 7,209, 16, 38, 5,188, 0, 0, 16, 6, 6, 65, 0, 0, 0, 0,255,255,254, 99,254, 86, 4, 72, 7,209, 16, 38, 5,189, 0, 0,
+ 16, 6, 6, 65, 0, 0, 0, 0,255,255, 0, 70,254, 86, 4,140, 6,114, 16, 38, 5,230, 0, 0, 16, 6, 2,193, 0, 0, 0, 0,
+255,255, 0, 70,254, 86, 4,140, 6,114, 16, 38, 5,231, 0, 0, 16, 6, 2,193, 0, 0, 0, 0,255,255, 0, 70,254, 86, 4,140,
+ 6,114, 16, 38, 5,232, 0, 0, 16, 6, 2,193, 0, 0, 0, 0,255,255, 0, 70,254, 86, 4,140, 6,114, 16, 38, 5,233, 0, 0,
+ 16, 6, 2,193, 0, 0, 0, 0,255,255, 0, 70,254, 86, 4,140, 6,114, 16, 38, 2,193, 0, 0, 16, 6, 5,234, 0, 0, 0, 0,
+255,255, 0, 70,254, 86, 4,140, 6,114, 16, 38, 2,193, 0, 0, 16, 6, 5,235, 0, 0, 0, 0,255,255, 0, 70,254, 86, 4,140,
+ 7,209, 16, 38, 5,236, 0, 0, 16, 6, 2,193, 0, 0, 0, 0,255,255, 0, 70,254, 86, 4,140, 7,209, 16, 38, 5,237, 0, 0,
+ 16, 6, 2,193, 0, 0, 0, 0,255,255,255,201,254, 86, 4,135, 6,114, 16, 38, 5,238, 0, 0, 16, 6, 6, 65, 0, 0, 0, 0,
+255,255,255,101,254, 86, 4,135, 6,114, 16, 38, 5,239, 0, 0, 16, 6, 6, 65, 0, 0, 0, 0,255,255,253,138,254, 86, 4,135,
+ 6,114, 16, 38, 5,240, 0, 0, 16, 6, 6, 65, 0, 0, 0, 0,255,255,253,138,254, 86, 4,135, 6,114, 16, 38, 5,241, 0, 0,
+ 16, 6, 6, 65, 0, 0, 0, 0,255,255,254,182,254, 86, 4,135, 6,114, 16, 38, 6, 65, 0, 0, 16, 6, 5,242, 0, 0, 0, 0,
+255,255,254,162,254, 86, 4,135, 6,114, 16, 38, 6, 65, 0, 0, 16, 6, 5,243, 0, 0, 0, 0,255,255,254,249,254, 86, 4,135,
+ 7,209, 16, 38, 5,244, 0, 0, 16, 6, 6, 65, 0, 0, 0, 0,255,255,254,174,254, 86, 4,135, 7,209, 16, 38, 5,245, 0, 0,
+ 16, 6, 6, 65, 0, 0, 0, 0,255,255, 0, 70,255,230, 4,149, 6, 72, 16, 38, 2,130, 0, 0, 16, 6, 2,237, 0, 0, 0, 0,
+255,255, 0, 70,255,230, 4,149, 5,246, 16, 38, 2,128, 0, 0, 16, 6, 2,237, 0, 0, 0, 0,255,255, 0, 70,254, 86, 4,149,
+ 6,102, 16, 38, 5,246, 0, 0, 16, 6, 2,193,156, 0, 0, 0,255,255, 0, 70,254, 86, 4,149, 4,122, 16, 38, 2,237, 0, 0,
+ 16, 6, 2,193,156, 0, 0, 0,255,255, 0, 70,254, 86, 4,149, 6,102, 16, 38, 2,232, 0, 0, 16, 6, 2,193,156, 0, 0, 0,
+255,255, 0, 70,255,230, 4,149, 6, 55, 16, 38, 2,237, 0, 0, 16, 6, 6, 67, 0, 0, 0, 0,255,255, 0, 70,254, 86, 4,149,
+ 6, 55, 16, 38, 6, 57, 0, 0, 16, 6, 2,193,156, 0, 0, 0,255,255, 0, 37, 0, 0, 4,172, 7,109, 16, 38, 11,184, 0, 0,
+ 16, 6, 2,206, 0, 0, 0, 0,255,255, 0, 37, 0, 0, 4,172, 7, 48, 16, 38, 11,189, 0, 0, 16, 6, 2,206, 0, 0, 0, 0,
+255,255,255,135, 0, 0, 4,172, 6,102, 16, 38, 2,206, 0, 0, 16, 7, 6,110,254,112, 0, 0,255,255, 0, 25, 0, 0, 4,172,
+ 6,102, 16, 6, 2,197, 0, 0,255,255, 0, 37,254, 86, 4,172, 5,213, 16, 38, 2,206, 0, 0, 16, 6, 6, 65, 0, 0, 0, 0,
+255,255, 1,239, 4,194, 2,225, 6,114, 16, 6, 6, 66, 0, 0,255,255, 2, 30,254, 86, 2,250,255,164, 16, 6, 2,193, 0, 0,
+ 0, 1, 1,239, 4,194, 2,225, 6,114, 0, 8, 0, 0, 1, 16, 35, 53, 50, 53, 35, 53, 51, 2,225,241,142,142,241, 5,195,254,
+255,100,157,175,255,255, 1, 31, 5, 29, 3,178, 6, 55, 16, 6, 2,110, 0, 0,255,255, 1, 31, 5, 70, 3,178, 7,139, 16, 38,
+ 0,106, 0, 0, 16, 7, 6, 67, 0, 0, 1, 84,255,255, 0,195,254, 86, 4, 27, 6,102, 16, 38, 5,250, 0, 0, 16, 7, 2,193,
+254,200, 0, 0,255,255, 0,195,254, 86, 4, 27, 4,123, 16, 38, 2,243, 0, 0, 16, 7, 2,193,254,200, 0, 0,255,255, 0,195,
+254, 86, 4, 27, 6,102, 16, 38, 2,234, 0, 0, 16, 7, 2,193,254,200, 0, 0,255,255, 0,195,254, 86, 4, 27, 6, 55, 16, 38,
+ 2,243, 0, 0, 16, 6, 6, 67, 0, 0, 0, 0,255,255, 0,195,254, 86, 4, 27, 6, 55, 16, 38, 6, 72, 0, 0, 16, 7, 2,193,
+254,200, 0, 0,255,255,254,141, 0, 0, 4, 78, 6,102, 16, 38, 2,210, 0, 0, 16, 7, 6,110,253,118, 0, 0,255,255,255, 31,
+ 0, 0, 4, 78, 6,102, 16, 6, 2,199, 0, 0,255,255,254, 91, 0, 0, 4, 72, 6,102, 16, 38, 2,212, 0, 0, 16, 7, 6,110,
+253, 68, 0, 0,255,255,254,237, 0, 0, 4, 72, 6,102, 16, 6, 2,200, 0, 0,255,255, 0,137,254, 86, 4, 72, 5,213, 16, 38,
+ 2,212, 0, 0, 16, 6, 6, 65, 0, 0, 0, 0,255,255, 0,245, 4,194, 3,240, 6,114, 16, 39, 6, 66,255, 6, 0, 0, 16, 7,
+ 6,110, 0,250, 0, 0, 0, 0,255,255, 1, 39, 4,194, 4, 30, 6,114, 16, 39, 6, 66,255, 56, 0, 0, 16, 6, 6,121,100, 0,
+255,255, 1, 31, 4,194, 3,178, 7,209, 16, 38, 6, 66, 0, 0, 16, 7, 6, 67, 0, 0, 1,154,255,255, 1, 47, 0, 0, 3,207,
+ 6, 72, 16, 38, 2,130, 0, 0, 16, 6, 2,245, 0, 0, 0, 0,255,255, 1, 54, 0, 0, 3,207, 5,246, 16, 38, 2,128, 0, 0,
+ 16, 6, 2,245, 0, 0, 0, 0,255,255, 1, 23, 0, 0, 3,207, 7,216, 16, 38, 2,245, 0, 0, 16, 6, 6,108, 0, 0, 0, 0,
+255,255, 1, 54, 0, 0, 3,207, 7,216, 16, 6, 2,205, 0, 0,255,255, 1, 31, 0, 0, 3,207, 6, 55, 16, 38, 2,245, 0, 0,
+ 16, 6, 6, 67, 0, 0, 0, 0,255,255, 1, 31, 0, 0, 3,207, 7,139, 16, 38, 2,245, 0, 0, 16, 6, 6, 68, 0, 0, 0, 0,
+255,255, 0,201, 0, 0, 4, 6, 7,109, 16, 38, 11,184, 0, 0, 16, 6, 2,214, 0, 0, 0, 0,255,255, 0,201, 0, 0, 4, 6,
+ 7, 48, 16, 38, 11,189, 0, 0, 16, 6, 2,214, 0, 0, 0, 0,255,255,254,191, 0, 0, 4, 6, 6,102, 16, 38, 2,214, 0, 0,
+ 16, 7, 6,110,253,168, 0, 0,255,255,255, 31, 0, 0, 4, 6, 6,102, 16, 6, 2,201, 0, 0,255,255, 0,245, 4,194, 3,240,
+ 6,114, 16, 39, 6,122,255, 6, 0, 0, 16, 7, 6,110, 0,250, 0, 0, 0, 0,255,255, 1, 19, 4,194, 4, 30, 6,114, 16, 39,
+ 6,122,255, 36, 0, 0, 16, 6, 6,121,100, 0,255,255, 1, 31, 4,194, 3,178, 7,209, 16, 38, 6,122, 0, 0, 16, 7, 6, 67,
+ 0, 0, 1,154,255,255, 0, 51,255,255, 4,105, 6, 72, 16, 38, 2,130, 0, 0, 16, 6, 3, 1, 0, 0, 0, 0,255,255, 0, 51,
+255,255, 4,105, 5,246, 16, 38, 2,128, 0, 0, 16, 6, 3, 1, 0, 0, 0, 0,255,255, 0, 51,255,255, 4,105, 7,216, 16, 38,
+ 3, 1, 0, 0, 16, 6, 6,108, 0, 0, 0, 0,255,255, 0, 51,255,255, 4,105, 7,216, 16, 6, 2,236, 0, 0,255,255, 0,190,
+254, 86, 4, 84, 6,114, 16, 38, 2,253, 0, 0, 16, 6, 6, 66, 0, 0, 0, 0,255,255, 0,190,254, 86, 4, 84, 6,114, 16, 38,
+ 2,253, 0, 0, 16, 6, 6,122, 0, 0, 0, 0,255,255, 0, 51,255,255, 4,105, 6, 55, 16, 38, 3, 1, 0, 0, 16, 6, 6, 67,
+ 0, 0, 0, 0,255,255, 0, 51,255,255, 4,105, 7,139, 16, 38, 3, 1, 0, 0, 16, 6, 6, 68, 0, 0, 0, 0,255,255, 0, 37,
+ 0, 0, 4,172, 7,109, 16, 38, 11,184, 0, 0, 16, 6, 2,225, 0, 0, 0, 0,255,255, 0, 37, 0, 0, 4,172, 7, 48, 16, 38,
+ 11,189, 0, 0, 16, 6, 2,225, 0, 0, 0, 0,255,255,254, 91, 0, 0, 4,172, 6,102, 16, 38, 2,225, 0, 0, 16, 7, 6,110,
+253, 68, 0, 0,255,255,254,112, 0, 0, 4,172, 6,102, 16, 6, 2,203, 0, 0,255,255,255,126, 0, 0, 4,117, 6,114, 16, 38,
+ 2,222, 0, 0, 16, 7, 6,122,253,143, 0, 0,255,255, 1, 23, 5, 70, 3,145, 7,216, 16, 38, 0,106, 0, 0, 16, 7, 6,110,
+ 0, 0, 1,114,255,255, 1, 63, 5, 70, 3,186, 7,216, 16, 6, 2,196, 0, 0,255,255, 1, 23, 4,238, 2,246, 6,102, 16, 6,
+ 0, 67, 0, 0,255,255, 0, 70,254, 86, 4,140, 6,102, 16, 38, 6, 2, 0, 0, 16, 6, 2,193, 0, 0, 0, 0,255,255, 0, 70,
+254, 86, 4,140, 4, 96, 16, 38, 3, 5, 0, 0, 16, 6, 2,193, 0, 0, 0, 0,255,255, 0, 70,254, 86, 4,140, 6,102, 16, 38,
+ 3, 10, 0, 0, 16, 6, 2,193, 0, 0, 0, 0,255,255, 0, 70,255,227, 4,140, 6, 55, 16, 38, 3, 5, 0, 0, 16, 6, 6, 67,
+ 0, 0, 0, 0,255,255, 0, 70,254, 86, 4,140, 6, 55, 16, 38, 6,114, 0, 0, 16, 6, 2,193, 0, 0, 0, 0,255,255,254,166,
+255,227, 4, 92, 6,102, 16, 38, 2,220, 0, 0, 16, 7, 6,110,253,143, 0, 0,255,255,255,181,255,227, 4, 92, 6,102, 16, 6,
+ 2,202, 0, 0,255,255,254,166, 0, 0, 4,135, 6,102, 16, 38, 2,229, 0, 0, 16, 7, 6,110,253,143, 0, 0,255,255,255,206,
+ 0, 0, 4,135, 6,102, 16, 6, 2,204, 0, 0,255,255, 0, 74,254, 86, 4,135, 5,180, 16, 38, 2,229, 0, 0, 16, 6, 6, 65,
+ 0, 0, 0, 0,255,255, 1,219, 4,238, 3,186, 6,102, 16, 6, 0,118, 0, 0, 0, 1, 1,239, 4,194, 2,225, 6,114, 0, 8,
+ 0, 0, 1, 53, 51, 21, 35, 6, 51, 21, 34, 1,240,240,141, 1,143,241, 5,195,175,175,157,100, 0, 1, 1,100, 1,223, 3,109,
+ 2,131, 0, 3, 0, 17,182, 0,160, 2, 4, 1, 0, 4, 16,212,196, 49, 0, 16,212,236, 48, 1, 33, 21, 33, 1,100, 2, 9,253,
+247, 2,131,164,255,255, 1,100, 1,223, 3,109, 2,131, 16, 6, 6,134, 0, 0, 0, 1, 0, 0, 1,236, 4,209, 2,121, 0, 3,
+ 0, 16,182, 2,182, 0,253, 4, 1, 0, 47,198, 49, 0, 16,252,236, 48, 17, 33, 21, 33, 4,209,251, 47, 2,121,141, 0, 0, 0,
+ 0, 1, 0, 0, 1,236, 4,209, 2,121, 0, 3, 0, 16,182, 2,182, 0,253, 4, 1, 0, 47,198, 49, 0, 16,252,236, 48, 17, 33,
+ 21, 33, 4,209,251, 47, 2,121,141, 0, 0, 0, 0, 1, 0, 0, 1,236, 4,209, 2,121, 0, 3, 0, 15,181, 2,182, 0, 4, 1,
+ 0, 47,196, 49, 0, 16,212,236, 48, 17, 33, 21, 33, 4,209,251, 47, 2,121,141, 0, 1, 0, 0, 1,236, 4,209, 2,121, 0, 3,
+ 0, 15,181, 2,182, 0, 4, 1, 0, 47,196, 49, 0, 16,212,236, 48, 17, 33, 21, 33, 4,209,251, 47, 2,121,141,255,255, 0, 0,
+254, 29, 4,209,255, 93, 16, 38, 0, 66, 0, 0, 16, 7, 0, 66, 0, 0, 0,240, 0, 1, 1,207, 3,199, 3, 45, 6, 20, 0, 5,
+ 0, 24, 64, 11, 0,163, 3,181, 6, 3, 4, 0, 29, 1, 6, 16,212,252,212,204, 49, 0, 16,252,236, 48, 1, 35, 53, 19, 51, 3,
+ 2,203,252,196,154, 98, 3,199,207, 1,126,254,130, 0, 0, 0, 0, 1, 1,207, 3,199, 3, 45, 6, 20, 0, 5, 0, 24, 64, 11,
+ 3,163, 0,181, 6, 3, 4, 1, 29, 0, 6, 16,212,236,212,204, 49, 0, 16,252,236, 48, 1, 51, 21, 3, 35, 19, 2, 49,252,197,
+153, 98, 6, 20,206,254,129, 1,127, 0, 0, 0, 0, 1, 1,147,254,225, 2,242, 1, 47, 0, 5, 0, 26,178, 3,163, 0,184, 1,
+ 1,182, 6, 3, 4, 1, 29, 0, 6, 16,212,236,212,204, 49, 0, 16,252,236, 48, 1, 51, 21, 3, 35, 19, 1,246,252,197,154, 99,
+ 1, 47,207,254,129, 1,127, 0, 0, 1, 1,207, 3,199, 3, 45, 6, 20, 0, 5, 0, 0, 1, 21, 19, 35, 3, 53, 2,203, 98,153,
+197, 6, 20,206,254,129, 1,127,206, 0, 0, 0, 0, 2, 0,211, 3,199, 3,254, 6, 20, 0, 5, 0, 11, 0, 37, 64, 18, 6, 0,
+163, 9, 3,181, 12, 3, 4, 0, 29, 1, 7, 29, 6, 9, 10, 12, 16,212,204,212,236,212,252,212,204, 49, 0, 16,252, 60,236, 50,
+ 48, 1, 35, 53, 19, 51, 3, 5, 35, 53, 19, 51, 3, 3,156,252,196,154, 98,254, 53,254,199,153, 98, 3,199,207, 1,126,254,130,
+207,207, 1,126,254,130, 0, 0, 0, 2, 0,211, 3,199, 3,252, 6, 20, 0, 5, 0, 11, 0, 39, 64, 19, 9, 3,163, 6, 0,181,
+ 12, 9, 10, 6, 3, 4, 1, 29, 0, 6, 29, 7, 12, 16,212,236,212,236,212,204, 16,212,206, 49, 0, 16,252, 60,236, 50, 48, 1,
+ 51, 21, 3, 35, 19, 37, 51, 21, 3, 35, 19, 3, 0,252,197,153, 98,254, 53,252,196,154, 98, 6, 20,206,254,129, 1,127,206,206,
+254,129, 1,127, 0, 2, 0,211,254,225, 3,252, 1, 47, 0, 5, 0, 11, 0, 42,180, 9, 3,163, 6, 0,184, 1, 1, 64, 13, 12,
+ 9, 10, 6, 3, 4, 1, 29, 0, 6, 29, 7, 12, 16,212,236,212,236,212,204, 16,212,206, 49, 0, 16,252, 60,236, 50, 48, 1, 51,
+ 21, 3, 35, 19, 37, 51, 21, 3, 35, 19, 3, 0,252,197,153, 98,254, 53,252,196,154, 98, 1, 47,207,254,129, 1,127,207,207,254,
+129, 1,127, 0, 0, 2, 0,211, 3,199, 3,252, 6, 20, 0, 5, 0, 11, 0, 0, 1, 21, 19, 35, 3, 53, 33, 21, 19, 35, 3, 53,
+ 1,207, 98,153,197, 2,199, 98,154,196, 6, 20,206,254,129, 1,127,206,206,254,129, 1,127,206, 0, 1, 0,162,255, 59, 4, 47,
+ 5,213, 0, 11, 0, 39, 64, 20, 8, 4,203, 10, 2, 0,136, 6,202, 12, 3, 82, 5, 1, 81, 9, 82, 7, 0, 12, 16,212, 60,236,
+252, 60,236, 49, 0, 16,228,244,212, 60,236, 50, 48, 1, 51, 17, 33, 21, 33, 17, 35, 17, 33, 53, 33, 2, 16,177, 1,110,254,146,
+177,254,146, 1,110, 5,213,254, 92,153,251,163, 4, 93,153, 0, 0, 1, 0,162,255, 59, 4, 47, 5,213, 0, 19, 0, 60, 64, 31,
+ 18, 6,203, 0, 16, 8,203, 14, 10, 12, 4, 0, 2,202, 12,136, 20, 15, 0, 82, 17, 13, 1, 81, 9, 5, 82, 11, 7, 3, 20, 16,
+212, 60, 60,236, 50,252, 60, 60,236, 50, 49, 0, 16,228,244,196, 50, 16,212, 60,238, 50, 16,238, 50, 48, 37, 33, 17, 35, 17, 33,
+ 53, 33, 17, 33, 53, 33, 17, 51, 17, 33, 21, 33, 17, 33, 4, 47,254,146,177,254,146, 1,110,254,146, 1,110,177, 1,110,254,146,
+ 1,110,223,254, 92, 1,164,154, 2, 31,153, 1,164,254, 92,153,253,225, 0, 0, 0, 1, 1, 63, 1,209, 3,145, 4, 33, 0, 11,
+ 0, 18,183, 9,208, 3, 12, 6, 86, 0, 12, 16,212,236, 49, 0, 16,212,228, 48, 1, 52, 54, 51, 50, 22, 21, 20, 6, 35, 34, 38,
+ 1, 63,172,125,124,173,174,125,124,171, 2,250,124,171,172,123,124,173,171, 0, 0, 1, 1, 63, 1,129, 3,225, 4,113, 0, 2,
+ 0, 0, 1, 17, 1, 1, 63, 2,162, 1,129, 2,240,254,136, 0, 0, 3, 0, 80, 0, 0, 4,127, 1, 49, 0, 3, 0, 7, 0, 11,
+ 0, 35, 64, 17, 8, 4, 0,162, 10, 6, 2, 4, 29, 5, 8, 29, 9, 1, 29, 0, 12, 16,212,252,212,236,212,236, 49, 0, 47, 60,
+ 60,236, 50, 50, 48, 19, 51, 17, 35, 1, 51, 17, 35, 1, 51, 17, 35, 80,252,252, 3, 51,252,252,254,102,252,252, 1, 49,254,207,
+ 1, 49,254,207, 1, 49,254,207, 0, 7, 0, 0, 0, 0, 4,209, 5,152, 0, 3, 0, 15, 0, 27, 0, 39, 0, 51, 0, 63, 0, 75,
+ 0,116, 64, 14, 3, 2, 37, 31, 1, 49, 0, 61, 13,200, 19, 31,200, 49,184, 1, 2,181, 37,200, 43,145, 67, 19,184, 1, 2, 64,
+ 38, 55, 7,200, 73, 25, 3, 70, 2, 58, 52, 1, 40, 0, 28, 16, 58, 80, 70,122, 52, 80, 64, 10, 80, 22,122, 4, 80, 16, 34, 80,
+ 46,122, 16, 28, 80, 64, 40, 47,196,236,196,244,236, 16,238,246,238, 16,238,246,238, 17, 18, 57, 18, 57, 17, 18, 57, 17, 57, 49,
+ 0, 47, 60,238, 50,238, 50,246,238,254,238, 16,238, 50, 57, 18, 57, 17, 18, 57, 57, 48, 19, 39, 1, 23, 1, 20, 22, 51, 50, 54,
+ 53, 52, 38, 35, 34, 6, 7, 52, 54, 51, 50, 22, 21, 20, 6, 35, 34, 38, 19, 20, 22, 51, 50, 54, 53, 52, 38, 35, 34, 6, 7, 52,
+ 54, 51, 50, 22, 21, 20, 6, 35, 34, 38, 1, 20, 22, 51, 50, 54, 53, 52, 38, 35, 34, 6, 7, 52, 54, 51, 50, 22, 21, 20, 6, 35,
+ 34, 38, 72, 37, 4, 20, 39,252, 72, 95, 69, 68, 98, 99, 67, 69, 95,121,165,120,120,166,167,119,121,164, 76, 97, 69, 69, 97, 99,
+ 67, 69, 97,121,166,121,120,166,166,120,121,166, 3, 12, 97, 69, 70, 96, 98, 68, 69, 97,121,166,121,120,167,167,120,121,166, 2,
+ 55, 97, 1,159, 96,253, 74, 71, 97, 99, 69, 67, 99, 97, 69,121,165,166,120,121,168,166, 3,211, 69, 97, 97, 69, 67, 99, 97, 69,
+120,167,167,120,121,168,167,253, 34, 71, 97, 97, 71, 67, 99, 97, 69,120,166,166,120,121,168,167, 0, 7, 0, 0, 0, 0, 4,209,
+ 5,152, 0, 11, 0, 21, 0, 25, 0, 68, 0, 80, 0, 92, 0,104, 0, 0, 17, 52, 54, 51, 50, 22, 21, 20, 6, 35, 34, 38, 54, 20,
+ 22, 50, 54, 53, 52, 38, 35, 34, 3, 39, 1, 23, 1, 52, 54, 50, 23, 22, 23, 54, 55, 54, 51, 50, 23, 22, 23, 54, 55, 54, 51, 50,
+ 22, 21, 20, 6, 35, 34, 39, 38, 39, 6, 7, 6, 35, 34, 39, 38, 39, 6, 7, 6, 35, 34, 38, 55, 20, 22, 51, 50, 54, 53, 52, 38,
+ 35, 34, 6, 5, 20, 22, 51, 50, 54, 53, 52, 38, 35, 34, 6, 5, 20, 22, 51, 50, 54, 53, 52, 38, 35, 34, 6,166,121,120,166,166,
+120,121,166,121, 97,138, 97, 99, 67, 69,146, 37, 4, 20, 39,251,162,138,200, 69, 10, 9, 9, 10, 70,101,100, 69, 11, 8, 9, 10,
+ 70,101,100,139,139,100,101, 70, 10, 9, 8, 11, 69,100,101, 70, 10, 9, 9, 10, 70, 99,101,137,101, 79, 58, 56, 82, 82, 56, 58,
+ 79, 1,120, 81, 58, 58, 80, 82, 56, 58, 81, 1,122, 81, 58, 58, 80, 82, 56, 58, 81, 4,121,120,167,167,120,121,168,167,191,138,
+ 97, 97, 69, 67, 99,253, 24, 97, 1,159, 96,253, 74,121,165, 83, 12, 14, 14, 12, 83, 83, 12, 13, 13, 12, 83,166,120,121,168, 84,
+ 12, 13, 13, 12, 84, 84, 12, 14, 13, 13, 84,166,123, 71, 97, 99, 69, 67, 99, 97, 69, 71, 97, 97, 71, 67, 99, 97, 69, 71, 97, 97,
+ 71, 67, 99, 97, 0, 1, 1, 90, 0,141, 3, 47, 4, 35, 0, 6, 0, 26, 64, 12, 2, 4,252, 0,172, 7, 2, 3, 0,118, 5, 7,
+ 16,212,236, 50, 57, 49, 0, 16,244,236, 57, 48, 1, 21, 9, 1, 21, 1, 53, 3, 47,254,211, 1, 45,254, 43, 4, 35,191,254,244,
+254,244,191, 1,162, 82, 0, 0, 0, 1, 1,164, 0,141, 3,121, 4, 35, 0, 6, 0, 26, 64, 12, 5, 3,252, 0,172, 7, 5, 1,
+118, 3, 0, 7, 16,212, 60,236, 57, 49, 0, 16,244,236, 57, 48, 9, 1, 21, 1, 53, 9, 1, 1,164, 1,213,254, 43, 1, 45,254,
+211, 4, 35,254, 94, 82,254, 94,191, 1, 12, 1, 12, 0, 0, 0,255,255, 0,208, 0, 0, 4, 3, 5,213, 16, 39, 0, 4,254,204,
+ 0, 0, 16, 7, 0, 4, 1, 52, 0, 0, 0, 0, 0, 3, 0,244, 0, 0, 4, 16, 5,240, 0, 23, 0, 27, 0, 37, 0, 0, 1, 35,
+ 17, 6, 7, 6, 7, 53, 54, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 15, 1, 14, 1, 21, 3, 53, 51, 21, 3, 17, 55, 54, 55, 54,
+ 53, 52, 39, 38, 2,172,190, 31, 32, 89, 98, 94, 96, 95,104,186,111,110, 34, 33, 94, 88, 69, 38,197,203, 6, 45, 62, 23, 24, 66,
+ 37, 1,145, 3,173, 8, 12, 35, 68,188, 57, 28, 28, 96, 96,161, 76, 65, 66, 92, 86, 66, 84, 61,253,197,254,254, 5, 66,254, 82,
+ 45, 59, 44, 44, 49, 89, 55, 31,255,255, 0, 0, 5,187, 4,209, 6, 11, 16, 7, 0, 66, 0, 0, 7,158, 0, 0, 0, 1, 1,207,
+254,242, 3,119, 6, 20, 0, 11, 0, 0, 1, 33, 21, 35, 17, 51, 21, 35, 17, 51, 21, 33, 1,207, 1,168,240,240,240,240,254, 88,
+ 6, 20,143,253, 69,143,253, 70,143, 0, 0, 0, 0, 1, 1, 90,254,242, 3, 2, 6, 20, 0, 11, 0, 0, 1, 17, 33, 53, 51, 17,
+ 35, 53, 51, 17, 35, 53, 3, 2,254, 88,240,240,240,240, 6, 20,248,222,143, 2,186,143, 2,187,143, 0, 0, 0,255,255, 0, 33,
+ 0, 0, 4,177, 5,241, 16, 39, 11,188,254,188, 0, 0, 16, 7, 11,188, 1, 28, 0, 0, 0, 0,255,255, 0, 33, 0, 0, 4, 3,
+ 5,241, 16, 39, 11,188,254,188, 0, 0, 16, 7, 0, 4, 1, 52, 0, 0, 0, 0,255,255, 0,208, 0, 0, 4,177, 5,241, 16, 39,
+ 0, 4,254,204, 0, 0, 16, 7, 11,188, 1, 28, 0, 0, 0, 0, 0, 3, 1, 61, 2,141, 3,149, 5,240, 0, 12, 0, 28, 0, 44,
+ 0, 0, 0, 52, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 34, 19, 34, 7, 6, 21, 20, 23, 22, 51, 50, 55, 54, 53, 52, 39, 38, 39,
+ 50, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 53, 52, 55, 54, 2, 22, 24, 23, 34, 37, 23, 24, 24, 25, 70, 36, 87, 43, 44, 44, 43,
+ 87, 88, 43, 44, 44, 43, 88,149, 76, 76, 76, 76,149,150, 74, 75, 75, 76, 4, 32, 64, 23, 22, 22, 23, 32, 33, 20, 21, 1,161, 85,
+ 85,175,174, 85, 85, 85, 85,174,175, 85, 85, 89,110,109,215,214,110,109,109,110,214,215,109,110, 0, 2, 1, 72, 2,156, 3,136,
+ 6, 3, 0, 9, 0, 13, 0, 0, 1, 33, 17, 51, 21, 33, 53, 51, 17, 35, 19, 51, 21, 35, 1,122, 1, 40,230,253,192,230,180,180,
+116,116, 5, 15,253,221, 80, 80, 1,211, 1, 68,130, 0, 0, 0, 0, 2, 1, 12, 2,156, 3,141, 5,223, 0, 10, 0, 13, 0, 53,
+179, 11, 0, 12, 2,184, 1, 9,178, 8, 4, 6,186, 1, 10, 0, 0, 1, 21, 64, 11, 14, 12, 9, 11, 7, 87, 3, 5, 1, 9, 14,
+ 16,212,212, 60,196,236, 50, 17, 57, 49, 0, 16,244,244,212, 60,236, 50, 17, 57, 48, 1, 51, 17, 51, 21, 35, 21, 35, 53, 33, 53,
+ 9, 1, 33, 2,119,162,116,116,138,254,125, 1,131,254,238, 1, 18, 5,223,253,230,111,186,186,121, 1,147,254, 99, 0, 0, 0,
+ 0, 1, 1, 63, 2,141, 3,125, 5,223, 0, 33, 0, 0, 1, 33, 21, 33, 21, 62, 1, 51, 50, 23, 22, 21, 20, 7, 6, 35, 34, 38,
+ 39, 53, 22, 23, 22, 51, 50, 54, 53, 52, 38, 35, 34, 7, 6, 7, 1,102, 1,214,254,157, 26, 54, 28,144, 84, 84, 88, 89,153, 74,
+122, 48, 52, 63, 57, 60,104,112,116,103, 51, 47, 48, 44, 5,223, 95,204, 9, 8, 77, 76,131,132, 76, 76, 18, 18,114, 26, 15, 14,
+ 98, 91, 89,100, 10, 11, 20, 0, 0, 2, 1, 73, 2,141, 3,161, 5,240, 0, 29, 0, 41, 0, 0, 1, 21, 46, 1, 35, 34, 7, 6,
+ 21, 54, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 35, 34, 38, 53, 52, 54, 51, 50, 23, 22, 3, 34, 6, 20, 22, 51, 50, 55, 54, 52,
+ 39, 38, 3, 93, 39, 88, 48,119, 62, 61, 32, 50, 53, 68,135, 73, 74, 76, 76,137,161,150,180,171, 46, 46, 46,180, 80, 92, 92, 80,
+ 83, 42, 42, 42, 42, 5,207,104, 20, 22, 81, 81,158, 59, 28, 30, 74, 74,137,135, 75, 74,208,225,212,222, 9, 8,254,142,104,184,
+104, 50, 49,194, 49, 50, 0, 0, 0, 1, 1, 61, 2,156, 3,133, 5,223, 0, 6, 0, 0, 1, 33, 21, 1, 35, 1, 33, 1, 61, 2,
+ 72,254,180,131, 1, 67,254, 68, 5,223, 48,252,237, 2,228, 0, 0, 3, 1, 59, 2,140, 3,150, 5,238, 0, 14, 0, 46, 0, 61,
+ 0, 0, 1, 34, 7, 6, 20, 23, 22, 51, 50, 55, 54, 53, 52, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 51, 50, 23, 22, 21, 20, 7,
+ 6, 7, 22, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 53, 52, 55, 54, 55, 20, 23, 22, 51, 50, 55, 54, 53, 52, 38, 35, 34, 7, 6,
+ 2,104, 84, 45, 46, 46, 47, 82, 85, 45, 46, 46, 47,192, 80, 45, 45, 75, 75,129,130, 75, 75, 45, 45, 80, 93, 49, 50, 80, 80,142,
+141, 80, 80, 50, 49, 48, 39, 40, 75, 76, 40, 39, 78, 77, 75, 40, 39, 4, 41, 43, 42,154, 43, 43, 42, 43, 78, 77, 42, 43, 47, 18,
+ 50, 51, 71, 99, 59, 58, 58, 59, 99, 71, 51, 50, 18, 19, 56, 56, 89,113, 63, 64, 63, 64,112, 90, 56, 56,198, 67, 35, 36, 36, 35,
+ 67, 68, 72, 36, 36, 0, 0, 0, 0, 2, 1, 48, 2,141, 3,136, 5,240, 0, 15, 0, 46, 0, 0, 1, 50, 55, 54, 53, 52, 39, 38,
+ 35, 34, 7, 6, 21, 20, 23, 22, 3, 53, 30, 1, 51, 50, 55, 54, 53, 14, 1, 35, 34, 39, 38, 53, 52, 55, 54, 51, 50, 23, 22, 21,
+ 20, 7, 6, 35, 34, 39, 38, 2, 83, 80, 45, 46, 46, 45, 80, 83, 43, 42, 42, 42,140, 40, 88, 47,120, 61, 61, 29,106, 68,136, 72,
+ 73, 75, 76,137,162, 75, 75, 90, 91,172, 45, 46, 46, 4, 15, 52, 52, 93, 92, 52, 52, 50, 49, 97, 98, 50, 49,254,159,104, 20, 22,
+ 81, 80,158, 56, 60, 74, 75,137,135, 74, 74,104,105,225,211,111,111, 8, 9, 0, 0, 1, 1, 28, 2,219, 3,182, 5, 44, 0, 11,
+ 0, 0, 1, 21, 33, 21, 33, 21, 35, 53, 33, 53, 33, 53, 2,158, 1, 24,254,232,106,254,232, 1, 24, 5, 44,249, 95,249,249, 95,
+249, 0, 0, 0, 0, 1, 1, 28, 3,212, 3,182, 4, 51, 0, 3, 0, 0, 1, 33, 21, 33, 1, 28, 2,154,253,102, 4, 51, 95, 0,
+ 0, 2, 1, 28, 3, 97, 3,182, 4,165, 0, 3, 0, 7, 0, 0, 1, 33, 21, 33, 17, 33, 21, 33, 1, 28, 2,154,253,102, 2,154,
+253,102, 3,193, 96, 1, 68, 95, 0, 1, 1,216, 2, 5, 2,250, 6, 2, 0, 12, 0, 0, 1, 14, 1, 21, 20, 22, 23, 35, 46, 1,
+ 52, 54, 55, 2,250, 84, 84, 84, 84,102, 94, 94, 94, 94, 6, 2,127,254,129,128,254,129,133,253,250,253,132, 0, 0, 1, 1,216,
+ 2, 5, 2,249, 6, 2, 0, 13, 0, 0, 1, 51, 30, 1, 21, 20, 6, 7, 35, 62, 1, 53, 52, 38, 1,216,101, 95, 93, 93, 95,101,
+ 84, 83, 83, 6, 2,132,253,125,126,253,132,130,254,127,128,254, 0, 1, 1, 65, 2,156, 3,144, 5, 31, 0, 19, 0, 32, 64, 6,
+ 0, 3, 14, 10, 11, 20, 16,212,220, 60, 47,204, 75, 49, 0, 64, 6, 6, 17, 12, 2, 11, 20, 16,212, 60,196,212,204, 48, 1, 17,
+ 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 22, 3,144,116, 78, 78, 94,108,117,117, 41,113, 74,121,125,
+ 4, 23,254,133, 1,119, 89, 89,107, 92,254,158, 2,115, 97, 56, 56,134, 0, 0,255,255, 1, 61,255,241, 3,149, 3, 84, 16, 7,
+ 6,168, 0, 0,253,100, 0, 0,255,255, 1, 88, 0, 0, 3,147, 3, 67, 16, 7, 0,123, 0, 0,253,100, 0, 0,255,255, 1, 66,
+ 0, 0, 3,125, 3, 84, 16, 7, 0,116, 0, 0,253,100, 0, 0,255,255, 1, 70,255,241, 3,156, 3, 84, 16, 7, 0,117, 0, 0,
+253,100, 0, 0,255,255, 1, 12, 0, 0, 3,141, 3, 67, 16, 7, 6,170, 0, 0,253,100, 0, 0,255,255, 1, 63,255,241, 3,125,
+ 3, 67, 16, 7, 6,171, 0, 0,253,100, 0, 0,255,255, 1, 73,255,241, 3,161, 3, 84, 16, 7, 6,172, 0, 0,253,100, 0, 0,
+255,255, 1, 61, 0, 0, 3,133, 3, 67, 16, 7, 6,173, 0, 0,253,100, 0, 0,255,255, 1, 59,255,240, 3,150, 3, 82, 16, 7,
+ 6,174, 0, 0,253,100, 0, 0,255,255, 1, 48,255,241, 3,136, 3, 84, 16, 7, 6,175, 0, 0,253,100, 0, 0,255,255, 1, 28,
+ 0, 63, 3,182, 2,144, 16, 7, 6,176, 0, 0,253,100, 0, 0,255,255, 1, 28, 1, 56, 3,182, 1,151, 16, 7, 6,177, 0, 0,
+253,100, 0, 0,255,255, 1, 28, 0,197, 3,182, 2, 9, 16, 7, 6,178, 0, 0,253,100, 0, 0,255,255, 1,216,255,105, 2,250,
+ 3,102, 16, 7, 6,179, 0, 0,253,100, 0, 0,255,255, 1,216,255,105, 2,249, 3,102, 16, 7, 6,180, 0, 0,253,100, 0, 0,
+255,255, 1, 69,255,240, 3,140, 2,130, 16, 7, 4,193, 0, 0,253,100, 0, 0,255,255, 1, 49,255,240, 3,160, 2,130, 16, 7,
+ 4,199, 0, 0,253,100, 0, 0,255,255, 1, 58,255,240, 3,151, 2,130, 16, 7, 4,208, 0, 0,253,100, 0, 0,255,255, 1, 18,
+ 0, 0, 3,191, 2,115, 16, 7, 2,116, 0, 0,253,100, 0, 0,255,255, 1, 49,255,240, 3,160, 2,130, 16, 7, 4,200, 0, 0,
+253,100, 0, 0, 0, 5, 0, 0, 0, 0, 4,209, 5,213, 0, 2, 0, 6, 0, 34, 0, 38, 0, 41, 0, 0, 1, 39, 21, 19, 39, 35,
+ 21, 3, 33, 19, 51, 17, 51, 17, 51, 21, 35, 21, 51, 21, 35, 17, 33, 3, 35, 17, 35, 17, 35, 53, 51, 53, 35, 53, 51, 5, 23, 51,
+ 53, 3, 23, 53, 1,181, 79,183, 57,126,196, 1, 16,211,230,196,162,162,162,162,254,240,211,230,196,162,162,162,162, 2, 18, 57,
+126, 79, 79, 3,175,206,206,254,242,147,147, 3, 52,253,218, 2, 38,253,218,123,147,123,253,218, 2, 38,253,218, 2, 38,123,147,
+123,123,147,147,254,242,206,206, 0, 1, 0, 37,255,227, 4, 37, 5,240, 0, 51, 0,112, 64, 60, 13, 0,231, 49, 15, 38, 24,231,
+ 22, 31,179, 32,178, 28,151, 40, 22, 35, 7,179, 6,178, 10,151, 3,150, 35,153, 52, 51, 40, 39, 49, 41, 45, 24, 22, 16, 3, 19,
+ 15, 23, 14, 38, 0, 45, 25, 13, 23, 19, 14, 50, 39, 19, 30, 31, 6, 23, 45, 52, 16,212,196,196, 50,236,196, 50,196, 17, 18, 57,
+ 57, 18, 57, 57, 17, 18, 57, 17, 23, 57, 18, 57, 57, 17, 57, 57, 49, 0, 16,228,244,236,244,236, 16,198, 50,238,246,238, 16,238,
+ 50,213, 60,238, 50, 48, 19, 18, 0, 51, 50, 22, 23, 21, 46, 1, 35, 34, 6, 7, 33, 7, 33, 14, 1, 21, 20, 22, 23, 33, 7, 33,
+ 30, 1, 51, 50, 54, 55, 21, 14, 1, 35, 34, 0, 3, 35, 55, 51, 38, 39, 38, 53, 52, 55, 54, 55, 35, 55,211, 48, 1, 18,223, 84,
+147, 74, 66,159, 78,146,174, 24, 1,225, 49,254, 70, 2, 1, 1, 1, 1,105, 49,254,211, 23,174,147, 79,157, 67, 72,148, 85,226,
+254,237, 44,174, 49,117, 1, 1, 2, 2, 1, 1,166, 49, 3,180, 1, 27, 1, 33, 40, 42,207, 61, 68,208,204,108, 20, 45, 46, 15,
+ 38, 23,110,203,209, 67, 62,207, 42, 40, 1, 32, 1, 28,110, 12, 20, 45, 15, 18, 47, 19, 11,108, 0, 4, 0,106, 0, 0, 4,209,
+ 5,213, 0, 26, 0, 31, 0, 36, 0, 41, 0, 0, 19, 33, 32, 19, 51, 21, 35, 22, 7, 51, 21, 35, 6, 7, 6, 43, 1, 17, 35, 17,
+ 35, 53, 51, 53, 35, 53, 51, 55, 21, 33, 38, 35, 19, 33, 21, 51, 50, 55, 54, 39, 33, 21,197, 1,180, 1,130, 94,120, 95, 9, 8,
+ 94,114, 38, 97,126,225,234,202, 91, 91, 91, 91,202, 1,220, 77,165,253,254, 25,234,177,117, 7, 9,253,242, 5,213,254,247,116,
+ 58, 57,115,123, 70, 89,253,168, 3,114,115,115,116, 99, 99, 99,254, 67,116,231, 59, 56,115, 0, 0, 1, 0, 0,255,227, 4,209,
+ 5,240, 0, 54, 0, 0, 1, 54, 55, 54, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 4, 21, 20, 7, 51, 21, 35, 6, 15, 1,
+ 33, 21, 33, 6, 21, 20, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 36, 53, 52, 55, 35, 53, 51, 54, 55, 54, 55, 33, 53, 3, 63, 10,
+ 9, 55,166,143, 94,185, 92,105,190, 86,223, 1, 13, 21,156,233, 94,204, 39, 2, 58,252,167, 44,170,153,104,205,115,107,212,105,
+252,254,248, 18,157,217, 9, 9, 72,136,254, 69, 3,175, 7, 9, 52, 99,113,133, 60, 59,205, 39, 39,241,200, 75, 61,123, 91, 47,
+ 9,123, 57, 98,123,137, 68, 73,215, 45, 45,224,213, 78, 64,123, 11, 10, 79, 47,123, 0, 0, 0, 0, 2, 0,130,254,211, 4, 79,
+ 6, 20, 0, 33, 0, 44, 0, 0, 1, 21, 38, 39, 38, 35, 17, 50, 55, 54, 55, 21, 6, 7, 6, 7, 17, 35, 17, 38, 39, 38, 17, 53,
+ 16, 55, 54, 55, 53, 55, 21, 22, 23, 22, 1, 3, 6, 7, 6, 7, 6, 23, 22, 23, 22, 4, 79, 91, 84, 85,101,101, 85, 84, 91, 89,
+ 92, 89, 91,100,185,115,212,212,121,178,101, 93, 89, 92,254,138, 1, 91, 67,118, 15, 14, 14, 25,108, 67, 4,164,213,105, 45, 45,
+251,241, 45, 45,105,211, 72, 36, 34, 2,254,240, 1, 21, 23,117,214, 1, 57, 17, 1, 66,203,116, 23,230, 2,226, 2, 34, 35,251,
+163, 3,249, 23, 66,117,170,161,102,180,108, 67, 0, 2, 0,140,255,228, 4, 49, 5,240, 0, 23, 0, 32, 0, 0, 37, 22, 51, 50,
+ 54, 55, 21, 14, 1, 35, 32, 0, 17, 16, 0, 33, 50, 22, 23, 21, 46, 1, 34, 15, 1, 6, 7, 6, 17, 16, 23, 22, 23, 2, 1, 95,
+124,100,157, 84, 9,200,132,254,248,254,184, 1, 69, 1, 22,125,144, 61, 91,126,232,111,105, 8, 11,137,134, 12, 10,131, 55, 64,
+ 44,131, 5, 76, 1,168, 1, 93, 1,114, 1,149, 52, 30,130, 42, 58, 48, 78, 8, 14,178,254,175,254,204,190, 17, 11, 0, 0, 0,
+ 0, 1, 0, 84, 0, 0, 4, 72, 6, 20, 0, 26, 0, 0, 1, 3, 35, 19, 54, 55, 54, 53, 52, 38, 35, 34, 6, 7, 3, 35, 1, 51,
+ 3, 62, 1, 51, 50, 22, 21, 20, 6, 4, 51,135,184,135, 1, 2, 15, 93, 87,127,178, 33,123,184, 1, 47,184,116, 75,175, 98,139,
+154, 11, 2,182,253, 74, 2,183, 4, 10, 71, 39, 81, 87,186,168,253,135, 6, 20,253,164, 97, 98,145,130, 32, 94, 0, 4, 0, 10,
+ 0, 0, 4,199, 5,213, 0, 3, 0, 9, 0, 13, 0, 35, 0, 0, 0, 32, 16, 32, 19, 34, 16, 51, 50, 16, 3, 33, 21, 33, 1, 17,
+ 51, 19, 17, 52, 54, 51, 21, 34, 6, 21, 17, 35, 3, 17, 20, 6, 35, 53, 50, 54, 3,101, 1, 98,254,158,177, 50, 50, 51,228, 1,
+ 98,254,158,253, 32,245,204, 87,220, 85, 38,245,204, 87,220, 85, 38, 3, 12,253,234, 1,149,254,236, 1, 20,254, 9,148, 1, 49,
+ 4,164,251, 81, 3,126,131,174,184, 62, 59,251, 92, 4,175,252,130,131,174,184, 62, 0, 0, 0, 0, 2, 0, 0, 3,147, 4,102,
+ 5,213, 0, 7, 0, 20, 0,104, 64, 54, 15, 9, 10, 9, 14, 10, 10, 9, 17, 8, 9, 8, 16, 9, 9, 8, 66, 17, 14, 9, 3, 1,
+ 15, 18, 12, 3, 5, 1,215, 10, 8, 0,136, 21, 16, 15, 10, 9, 8, 5, 17, 13, 96, 11, 17, 96, 19, 0, 95, 2, 96, 4, 95, 6,
+ 47,252,254,236,213,238,214,238, 17, 23, 57, 49, 0, 16,244, 60, 60,236, 50,212, 60, 60,196, 17, 23, 57, 48, 75, 83, 88, 7, 16,
+ 5,201, 7, 16, 4,201, 7, 16, 4,201, 7, 16, 5,201, 89, 34, 1, 21, 35, 17, 35, 17, 35, 53, 33, 27, 1, 51, 17, 35, 17, 3,
+ 35, 3, 17, 35, 17, 1,182,162,114,162, 2,180,137,125,172,114,156, 55,166,113, 5,213, 94,254, 28, 1,228, 94,255, 0, 1, 0,
+253,190, 1,226,254,211, 1, 45,254, 30, 2, 66,255,255, 0, 74, 0, 0, 4,135, 5,180, 16, 6, 2,229, 0, 0,255,255, 0,137,
+ 0, 0, 4,201, 5,213, 16, 6, 0, 46, 0, 0,255,255, 0, 37, 0, 0, 4,172, 7,109, 16, 6, 0,135, 0, 0,255,255, 0, 27,
+254,227, 4,101, 6,123, 16, 39, 0,117, 0,201,252, 86, 16, 38, 11,182, 0, 0, 16, 7, 0,123,254,254, 0,156,255,255, 0, 27,
+254,227, 4,101, 6,140, 16, 39, 0,117, 0,201,252, 86, 16, 38, 11,182, 0, 0, 16, 7, 0,116,254,254, 0,156,255,255, 0, 27,
+254,227, 4, 90, 6,123, 16, 39, 6,171, 0,201,252, 86, 16, 38, 11,182, 0, 0, 16, 7, 0,123,254,254, 0,156,255,255, 0, 27,
+254,227, 4, 90, 6,140, 16, 39, 6,171, 0,201,252, 86, 16, 38, 11,182, 0, 0, 16, 7, 0,116,254,254, 0,156,255,255, 0, 27,
+254,227, 4, 90, 6,140, 16, 39, 6,171, 0,201,252, 86, 16, 38, 11,182, 0, 0, 16, 7, 0,117,254,254, 0,156,255,255, 0, 10,
+254,227, 4, 90, 6,123, 16, 39, 6,171, 0,201,252, 86, 16, 38, 11,182, 0, 0, 16, 7, 6,170,254,254, 0,156,255,255, 0, 27,
+254,227, 4,106, 6,123, 16, 39, 6,172, 0,201,252, 86, 16, 38, 11,182, 0, 0, 16, 7, 0,123,254,254, 0,156,255,255, 0, 27,
+254,227, 4,106, 6,123, 16, 39, 6,172, 0,201,252, 86, 16, 38, 11,182, 0, 0, 16, 7, 6,171,254,254, 0,156,255,255, 0, 27,
+254,226, 4, 95, 6,123, 16, 39, 6,174, 0,201,252, 86, 16, 38, 11,182, 0, 0, 16, 7, 0,123,254,254, 0,156,255,255, 0, 27,
+254,226, 4, 95, 6,140, 16, 39, 6,174, 0,201,252, 86, 16, 38, 11,182, 0, 0, 16, 7, 0,117,254,254, 0,156,255,255, 0, 27,
+254,226, 4, 95, 6,123, 16, 39, 6,174, 0,201,252, 86, 16, 38, 11,182, 0, 0, 16, 7, 6,171,254,254, 0,156,255,255, 0, 27,
+254,226, 4, 95, 6,123, 16, 39, 6,174, 0,201,252, 86, 16, 38, 11,182, 0, 0, 16, 7, 6,173,254,254, 0,156,255,255, 0, 27,
+ 1,248, 4, 90, 6,123, 16, 38, 11,182, 0, 0, 16, 7, 0,123,254,254, 0,156, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 9,
+ 0, 0, 19, 53, 1, 23, 7, 33, 21, 33, 23, 7, 66, 1, 35, 90,160, 3,112,252,144,160, 90, 2, 8, 82, 1, 35, 90,160,164,160,
+ 90, 0, 0, 0, 0, 1, 1, 28, 0, 0, 3,181, 4, 77, 0, 9, 0, 0, 9, 1, 7, 39, 17, 35, 17, 7, 39, 1, 2,146, 1, 34,
+ 90,160,164,160, 90, 1, 36, 4, 77,254,221, 90,160,252,144, 3,112,160, 90, 1, 35, 0, 0, 0, 0, 1, 0, 66, 0,229, 4,143,
+ 3,125, 0, 9, 0, 0, 9, 1, 39, 55, 33, 53, 33, 39, 55, 1, 4,143,254,221, 90,160,252,144, 3,112,160, 90, 1, 35, 2, 8,
+254,221, 90,160,164,160, 90,254,221, 0, 0, 0, 0, 1, 1, 28, 0, 0, 3,181, 4, 77, 0, 9, 0, 0, 33, 1, 55, 23, 17, 51,
+ 17, 55, 23, 1, 2, 64,254,220, 90,160,164,160, 90,254,222, 1, 35, 90,160, 3,112,252,144,160, 90,254,221, 0, 0, 1, 0, 66,
+ 0,229, 4,143, 3,125, 0, 15, 0, 0, 1, 33, 23, 7, 1, 53, 1, 23, 7, 33, 39, 55, 1, 21, 1, 39, 3,178,253,109,160, 90,
+254,221, 1, 35, 90,160, 2,147,160, 90, 1, 35,254,221, 90, 1,223,160, 90, 1, 35, 82, 1, 35, 90,160,160, 90,254,221, 82,254,
+221, 90, 0, 0, 0, 1, 1, 28, 0, 0, 3,181, 4, 77, 0, 15, 0, 0, 37, 55, 23, 1, 35, 1, 55, 23, 17, 7, 39, 1, 51, 1,
+ 7, 39, 2,186,160, 90,254,222, 82,254,220, 90,160,160, 90, 1, 36, 82, 1, 34, 90,160,221,160, 90,254,221, 1, 35, 90,160, 2,
+147,160, 90, 1, 35,254,221, 90,160, 0, 0, 0, 0, 1, 0,184, 0, 0, 4, 25, 3, 97, 0, 9, 0, 0, 19, 55, 33, 21, 35, 1,
+ 7, 1, 21, 35,184, 58, 1,156,227, 2,110,116,253,146,127, 3, 39, 58,127,253,146,116, 2,110,227, 0, 0, 0, 0, 1, 0,184,
+ 0, 0, 4, 25, 3, 97, 0, 9, 0, 0, 1, 17, 35, 53, 1, 39, 1, 35, 53, 33, 4, 25,127,253,146,116, 2,110,227, 1,156, 3,
+ 39,254,100,227,253,146,116, 2,110,127, 0, 0, 0, 1, 0,184, 0, 0, 4, 25, 3, 97, 0, 9, 0, 0, 41, 1, 53, 51, 1, 55,
+ 1, 53, 51, 17, 3,223,254,100,227,253,146,116, 2,110,127,127, 2,110,116,253,146,227,254,100, 0, 1, 0,184, 0, 0, 4, 25,
+ 3, 97, 0, 9, 0, 0, 55, 17, 51, 21, 1, 23, 1, 51, 21, 33,184,127, 2,110,116,253,146,227,254,100, 58, 1,156,227, 2,110,
+116,253,146,127, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 17, 0, 0, 1, 51, 21, 33, 7, 39, 55, 33, 23, 7, 1, 53, 1, 23,
+ 7, 33, 55, 23, 3,193,206,254,209,147,142, 99,254,125,160, 90,254,221, 1, 35, 90,160, 1,227,148,142, 2,131,164,250, 82,168,
+160, 90, 1, 35, 82, 1, 35, 90,160,250, 82, 0, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 17, 0, 0, 1, 35, 53, 33, 55, 23,
+ 7, 33, 39, 55, 1, 21, 1, 39, 55, 33, 7, 39, 1, 16,206, 1, 47,147,142, 99, 1,131,160, 90, 1, 35,254,221, 90,160,254, 29,
+148,142, 1,223,164,250, 82,168,160, 90,254,221, 82,254,221, 90,160,250, 82, 0, 0, 1, 0, 89, 1,139, 4,120, 3, 97, 0, 53,
+ 0, 0, 1, 22, 23, 22, 23, 22, 51, 50, 55, 54, 55, 54, 55, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 7, 38, 39, 38, 39,
+ 38, 35, 34, 7, 14, 1, 7, 6, 7, 6, 7, 6, 35, 34, 39, 38, 47, 1, 21, 35, 17, 55, 33, 21, 1, 36, 7,102, 18, 32, 25, 33,
+ 31, 26, 24, 26, 21, 13, 17, 43, 33, 51, 45, 54, 56, 43, 50, 34, 44, 24,106, 5, 33, 17, 33, 24, 33, 28, 28, 25, 51, 10, 14, 46,
+ 30, 54, 43, 56, 53, 46, 48, 36,109,127, 58, 1,156, 2,226, 12,119, 21, 18, 15, 15, 12, 29, 22, 39, 48, 55, 41, 27, 23, 23, 28,
+ 40, 54, 59, 67, 18, 43, 22, 19, 14, 14, 12, 58, 32, 44, 58, 39, 29, 24, 24, 25, 43,128,224, 1,156, 58,127, 0, 0, 1, 0, 89,
+ 1,139, 4,120, 3, 97, 0, 53, 0, 0, 1, 33, 53, 33, 23, 17, 35, 53, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 39, 46, 1, 39,
+ 38, 35, 34, 7, 6, 7, 6, 7, 39, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 51, 50, 55, 54, 55, 54,
+ 3,173,254,245, 1,156, 58,127,109, 36, 48, 46, 53, 56, 43, 54, 30, 46, 14, 10, 51, 25, 28, 28, 33, 24, 33, 17, 33, 5,106, 24,
+ 44, 34, 50, 43, 56, 54, 45, 51, 33, 43, 17, 13, 21, 26, 24, 26, 31, 33, 25, 32, 18,102, 2,226,127, 58,254,100,224,128, 43, 25,
+ 24, 24, 29, 39, 58, 44, 32, 58, 12, 14, 14, 19, 22, 43, 18, 67, 59, 54, 40, 28, 23, 23, 27, 41, 55, 48, 39, 22, 29, 12, 15, 15,
+ 18, 21,119, 0, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 17, 0, 0, 1, 33, 21, 33, 23, 7, 39, 35, 23, 7, 1, 53, 1, 23,
+ 7, 51, 55, 23, 2,105, 2, 38,253,218,160, 90,250,150,160, 90,254,221, 1, 35, 90,160,150,250, 90, 2,131,164,160, 90,250,160,
+ 90, 1, 35, 82, 1, 35, 90,160,250, 90, 0, 0, 0, 1, 1, 28, 0, 0, 3,181, 4, 77, 0, 17, 0, 0, 1, 7, 39, 55, 53, 7,
+ 39, 1, 51, 1, 7, 39, 21, 23, 7, 39, 17, 35, 2, 22,160, 90,250,160, 90, 1, 36, 82, 1, 34, 90,160,250, 90,160,164, 2, 38,
+160, 90,250,150,160, 90, 1, 35,254,221, 90,160,150,250, 90,160,253,218, 0, 0, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 17,
+ 0, 0, 1, 39, 55, 23, 51, 39, 55, 1, 21, 1, 39, 55, 35, 7, 39, 55, 33, 53, 2,104,160, 90,250,150,160, 90, 1, 35,254,221,
+ 90,160,150,250, 90,160,253,218, 2,131,160, 90,250,160, 90,254,221, 82,254,221, 90,160,250, 90,160,164, 0, 0, 0, 1, 1, 28,
+ 0, 0, 3,181, 4, 77, 0, 17, 0, 0, 1, 55, 23, 7, 21, 55, 23, 1, 35, 1, 55, 23, 53, 39, 55, 23, 17, 51, 2,186,160, 90,
+250,160, 90,254,222, 82,254,220, 90,160,250, 90,160,164, 2, 39,160, 90,250,150,160, 90,254,221, 1, 35, 90,160,150,250, 90,160,
+ 2, 38, 0, 0, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 14, 0, 0, 1, 23, 7, 39, 33, 23, 7, 1, 53, 1, 23, 7, 33, 55,
+ 23, 3,157,242, 90,250,253,228,160, 90,254,221, 1, 35, 90,160, 2, 28,250, 90, 2, 49,242, 90,250,160, 90, 1, 35, 82, 1, 35,
+ 90,160,250, 90, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 14, 0, 0, 1, 39, 55, 23, 33, 39, 55, 1, 21, 1, 39, 55, 33, 7,
+ 39, 1, 52,242, 90,250, 2, 28,160, 90, 1, 35,254,221, 90,160,253,228,250, 90, 2, 49,242, 90,250,160, 90,254,221, 82,254,221,
+ 90,160,250, 90, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 13, 0, 0, 1, 53, 51, 17, 35, 53, 33, 23, 7, 1, 53, 1, 23, 7,
+ 3,235,164,164,253, 52,160, 90,254,221, 1, 35, 90,160, 2,131,250,253,104,250,160, 90, 1, 35, 82, 1, 35, 90,160, 0, 0, 0,
+ 0, 1, 1, 28, 0, 0, 3,181, 4, 77, 0, 13, 0, 0, 37, 17, 7, 39, 1, 51, 1, 7, 39, 17, 51, 21, 33, 53, 2, 22,160, 90,
+ 1, 36, 82, 1, 34, 90,160,250,253,104,164, 2,204,160, 90, 1, 35,254,221, 90,160,253, 52,164,164, 0, 0, 0, 0, 1, 0, 66,
+ 0,229, 4,143, 3,125, 0, 13, 0, 0, 19, 33, 39, 55, 1, 21, 1, 39, 55, 33, 21, 35, 17, 51,230, 2,204,160, 90, 1, 35,254,
+221, 90,160,253, 52,164,164, 2,131,160, 90,254,221, 82,254,221, 90,160,250, 2,152, 0, 0, 0, 0, 1, 1, 28, 0, 0, 3,181,
+ 4, 77, 0, 13, 0, 0, 1, 17, 55, 23, 1, 35, 1, 55, 23, 17, 35, 53, 33, 21, 2,186,160, 90,254,222, 82,254,220, 90,160,250,
+ 2,152, 3,169,253, 52,160, 90,254,221, 1, 35, 90,160, 2,204,164,164, 0, 0, 0, 1, 1, 28, 0, 0, 3,181, 4, 77, 0, 19,
+ 0, 0, 37, 39, 55, 23, 17, 7, 39, 1, 51, 1, 7, 39, 17, 55, 23, 7, 51, 21, 33, 53, 2, 22,250, 90,160,160, 90, 1, 36, 82,
+ 1, 34, 90,160,160, 90,250,250,253,104,164,250, 90,160, 2, 24,160, 90, 1, 35,254,221, 90,160,253,232,160, 90,250,164,164, 0,
+ 0, 1, 0, 66, 0,229, 4,143, 4, 35, 0, 40, 0, 0, 1, 50, 55, 54, 55, 54, 55, 54, 53, 52, 39, 38, 39, 38, 39, 38, 35, 53,
+ 50, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 35, 33, 23, 7, 1, 53, 1, 23, 7, 3,100, 30, 26, 23, 19, 17, 10, 10,
+ 9, 10, 18, 16, 26, 23, 25, 62, 98, 45, 42, 22, 22, 21, 20, 44, 37, 58, 48, 31,253,147,160, 90,254,221, 1, 35, 90,160, 2,131,
+ 10, 9, 18, 17, 23, 24, 25, 27, 21, 23, 18, 16, 11, 10,164, 42, 43, 40, 53, 52, 60, 56, 53, 50, 46, 38, 26, 21,160, 90, 1, 35,
+ 82, 1, 35, 90,160, 0, 0, 0, 0, 1, 0, 66, 0,229, 4,143, 4, 35, 0, 41, 0, 0, 1, 33, 39, 55, 1, 21, 1, 39, 55, 33,
+ 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 51, 21, 34, 7, 6, 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 23, 22,
+ 1,109, 2, 69,160, 90, 1, 35,254,221, 90,160,253,147, 31, 48, 58, 37, 44, 20, 21, 22, 22, 42, 45, 49, 49, 62, 25, 23, 26, 16,
+ 18, 10, 9, 10, 10, 17, 19, 23, 26, 2,131,160, 90,254,221, 82,254,221, 90,160, 21, 26, 38, 46, 50, 53, 56, 60, 52, 53, 40, 43,
+ 21, 21,164, 10, 11, 16, 18, 23, 21, 27, 25, 24, 23, 17, 18, 9, 10, 0, 0, 0, 0, 2, 0, 66, 0,229, 4,143, 4, 35, 0, 36,
+ 0, 62, 0, 0, 1, 50, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 43, 1, 21, 35, 53, 33, 23, 7, 1, 53, 1, 23, 7,
+ 33, 53, 52, 55, 54, 55, 54, 55, 54, 23, 34, 7, 6, 7, 6, 7, 6, 29, 1, 51, 50, 55, 54, 55, 54, 55, 54, 53, 52, 39, 38, 39,
+ 38, 39, 38, 3,108, 62, 98, 45, 42, 22, 22, 21, 20, 44, 37, 58, 48, 31,151,164,254,206,160, 90,254,221, 1, 35, 90,160, 1, 50,
+ 21, 22, 41, 45, 48, 49, 57, 17, 26, 22, 18, 15, 12, 9,111, 30, 26, 23, 19, 17, 10, 10, 9, 10, 18, 16, 26, 23, 4, 35, 42, 43,
+ 40, 53, 52, 60, 56, 53, 50, 46, 38, 26, 21,213,213,160, 90, 1, 35, 82, 1, 35, 90,160,125, 59, 52, 55, 40, 43, 21, 20,163, 10,
+ 10, 17, 15, 27, 22, 26,125, 10, 9, 18, 17, 23, 24, 25, 27, 21, 23, 18, 16, 11, 10, 0, 0, 0, 0, 2, 0, 65, 0,229, 4,143,
+ 4, 35, 0, 37, 0, 63, 0, 0, 1, 22, 23, 22, 23, 22, 23, 22, 29, 1, 33, 39, 55, 1, 21, 1, 39, 55, 33, 21, 35, 53, 35, 34,
+ 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 23, 34, 7, 6, 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 23, 22, 59, 1,
+ 53, 52, 39, 38, 39, 38, 39, 38, 1,101, 57, 49, 48, 45, 41, 22, 21, 1, 50,160, 90, 1, 35,254,221, 90,160,254,206,164,151, 31,
+ 48, 58, 37, 44, 20, 21, 22, 22, 42, 45, 49, 49, 62, 25, 23, 26, 16, 18, 10, 9, 10, 10, 17, 19, 23, 26, 30,111, 9, 12, 15, 18,
+ 22, 26, 4, 35, 1, 20, 21, 43, 40, 55, 52, 59,125,160, 90,254,221, 82,254,221, 90,160,213,213, 21, 26, 38, 46, 50, 53, 56, 60,
+ 52, 53, 40, 43, 21, 21,164, 10, 11, 16, 18, 23, 21, 27, 25, 24, 23, 17, 18, 9, 10,125, 26, 22, 27, 15, 17, 10, 10, 0, 0, 0,
+ 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 88, 0, 0, 1, 51, 22, 23, 22, 23, 30, 1, 50, 54, 55, 54, 55, 54, 55, 54, 55, 54,
+ 51, 50, 23, 22, 23, 22, 23, 22, 23, 30, 1, 50, 54, 55, 54, 55, 54, 63, 1, 39, 55, 1, 21, 1, 39, 55, 35, 38, 7, 6, 7, 6,
+ 7, 6, 34, 39, 38, 39, 38, 39, 38, 39, 38, 39, 38, 34, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 34, 39, 38, 39, 38, 39, 38, 7,
+ 35, 23, 7, 1, 53, 1, 23, 1, 31, 8, 33, 24, 24, 25, 7, 16, 19, 16, 7, 7, 4, 11, 22, 23, 26, 27, 31, 33, 25, 30, 19, 22,
+ 11, 3, 7, 7, 17, 18, 17, 7, 30, 19, 23, 26, 15,160, 90, 1, 35,254,221, 90,160, 6, 12, 6, 9, 7, 27, 21, 27, 62, 27, 27,
+ 22, 25, 8, 3, 7, 7, 9, 8, 19, 8, 8, 7, 7, 3, 8, 26, 21, 28, 26, 62, 27, 24, 25, 7, 9, 6, 11, 7,160, 90,254,221,
+ 1, 35, 90, 2,131, 3, 16, 17, 34, 9, 11, 11, 9, 12, 12, 42, 33, 35, 16, 17, 17, 21, 30, 36, 39, 12, 12, 9, 11, 11, 9, 42,
+ 9, 12, 4, 3,160, 90,254,221, 82,254,221, 90,160, 1, 5, 5, 10, 37, 13, 17, 17, 18, 32, 39, 37, 12, 11, 10, 5, 6, 6, 5,
+ 10, 8, 15, 37, 39, 32, 18, 17, 17, 16, 34, 10, 5, 5, 1,160, 90, 1, 35, 82, 1, 35, 90, 0, 0, 1, 0, 66, 0,209, 4,143,
+ 3,145, 0, 23, 0, 0, 1, 33, 3, 39, 55, 35, 23, 7, 1, 53, 1, 23, 7, 33, 19, 23, 7, 51, 39, 55, 1, 21, 1, 39, 3,178,
+254,232, 60,140, 50,229,160, 90,254,221, 1, 35, 90,160, 1, 6, 60,140, 50,247,160, 90, 1, 35,254,221, 90, 1,223,254,242, 32,
+238,160, 90, 1, 35, 82, 1, 35, 90,160, 1, 14, 32,238,160, 90,254,221, 82,254,221, 90, 0, 0, 0, 1, 0,113, 0, 0, 4, 96,
+ 5,149, 0, 13, 0, 0, 37, 55, 23, 5, 39, 3, 55, 23, 19, 1, 19, 23, 3, 1, 3, 93,184, 74,254,177, 81,239,103,132,122,253,
+ 61,151,160, 90, 2,195,211,132,104,239, 13, 1, 80, 74,185, 2,212,254, 86, 3,125, 30,253,236, 1,170, 0, 0, 0, 1, 0,183,
+ 0, 0, 4, 26, 5,101, 0, 11, 0, 0, 1, 23, 7, 1, 53, 1, 23, 7, 33, 17, 35, 17, 1,148,160, 90,254,222, 1, 34, 90,160,
+ 2,134,164, 3,199,160, 90, 1, 35, 82, 1, 35, 90,160,251,149, 3,199, 0, 0, 0, 1, 0,183, 0, 0, 4, 26, 5,101, 0, 11,
+ 0, 0, 1, 33, 17, 35, 17, 33, 39, 55, 1, 21, 1, 39, 3, 60,254, 32,164, 2,132,160, 90, 1, 36,254,220, 90, 3,199,252, 57,
+ 4,107,160, 90,254,221, 82,254,221, 90, 0, 0, 0, 1, 0,183, 0, 0, 4, 26, 5,101, 0, 11, 0, 0, 1, 33, 17, 51, 17, 33,
+ 23, 7, 1, 53, 1, 23, 1,148, 1,226,164,253,122,160, 90,254,222, 1, 34, 90, 1,158, 3,199,251,149,160, 90, 1, 35, 82, 1,
+ 35, 90, 0, 0, 0, 1, 0,183, 0, 0, 4, 26, 5,101, 0, 11, 0, 0, 1, 39, 55, 1, 21, 1, 39, 55, 33, 17, 51, 17, 3, 60,
+160, 90, 1, 36,254,220, 90,160,253,124,164, 1,158,160, 90,254,221, 82,254,221, 90,160, 4,107,252, 57, 0, 0, 0, 1, 0,186,
+ 0, 0, 4, 23, 4, 82, 0, 11, 0, 0, 37, 17, 33, 53, 33, 17, 55, 23, 1, 35, 1, 55, 2,121,254, 65, 2, 99,160, 90,254,221,
+ 82,254,221, 90,221, 2,209,164,252,139,160, 90,254,221, 1, 35, 90, 0, 0, 0, 0, 1, 0, 63, 0, 0, 4,146, 3, 93, 0, 11,
+ 0, 0, 1, 33, 17, 51, 17, 33, 23, 7, 1, 53, 1, 23, 1, 28, 2,210,164,252,138,160, 90,254,222, 1, 34, 90, 1,158, 1,191,
+253,157,160, 90, 1, 35, 82, 1, 35, 90, 0, 0, 0, 1, 0, 81, 1, 88, 4,128, 3,229, 0, 41, 0, 0, 1, 55, 54, 55, 54, 55,
+ 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 23, 35, 52, 39, 38, 39, 38, 39, 38, 7, 6, 7, 6, 7, 6, 7, 6, 23, 21, 55, 23,
+ 1, 35, 1, 55, 1, 75, 1, 1, 36, 30, 60, 57, 74, 71, 84, 87, 68, 76, 55, 58, 32, 30, 1,152, 19, 19, 37, 35, 48, 40, 55, 57,
+ 41, 46, 37, 36, 20, 17, 2,160, 90,254,221, 82,254,221, 90, 2, 53, 24, 78, 83, 72, 59, 57, 30, 29, 29, 33, 54, 58, 73, 70, 84,
+ 55, 47, 48, 39, 36, 23, 19, 1, 1, 18, 20, 38, 36, 50, 40, 71, 23,160, 90,254,221, 1, 35, 90, 0, 1, 0, 81, 1, 88, 4,128,
+ 3,229, 0, 42, 0, 0, 1, 55, 23, 1, 35, 1, 55, 23, 53, 54, 39, 38, 39, 38, 39, 38, 39, 38, 7, 6, 7, 6, 7, 6, 21, 48,
+ 35, 54, 55, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 23, 3,134,160, 90,254,221, 82,254,221, 90,160, 2, 17, 20, 36,
+ 37, 46, 41, 57, 55, 40, 48, 35, 37, 19, 19,152, 1, 30, 32, 58, 55, 76, 68, 87, 84, 71, 74, 57, 60, 30, 36, 1, 2, 53,160, 90,
+254,221, 1, 35, 90,160, 23, 71, 40, 50, 36, 38, 20, 18, 1, 1, 19, 23, 36, 39, 48, 47, 55, 84, 70, 73, 58, 54, 33, 29, 29, 30,
+ 57, 59, 72, 83, 78, 0, 0, 0, 0, 2, 0, 50, 0, 0, 4,159, 4, 26, 0, 9, 0, 13, 0, 0, 19, 55, 33, 21, 35, 1, 7, 1,
+ 21, 35, 3, 53, 33, 21,184, 58, 1,156,227, 2,110,116,253,146,127,134, 4,108, 3, 39, 58,127,253,146,116, 2,110,227, 2, 63,
+ 80, 80, 0, 0, 0, 2, 0, 66, 0, 0, 4,143, 4,214, 0, 13, 0, 27, 0, 0, 19, 1, 23, 7, 33, 21, 33, 23, 7, 1, 17, 35,
+ 17, 51, 1, 17, 51, 17, 35, 17, 1, 39, 55, 33, 53, 33, 39, 55,230, 1, 35, 90,160, 2,204,253, 52,160, 90,254,221,164,164, 3,
+ 5,164,164,254,221, 90,160,253, 52, 2,204,160, 90, 3,179, 1, 35, 90,160,164,160, 90, 1, 35,254,221, 2,152,252,159, 1, 35,
+253,104, 1, 35,254,221, 90,160,164,160, 90, 0, 0, 1, 0, 88, 0, 0, 4,121, 3,249, 0, 54, 0, 0, 1, 23, 22, 23, 22, 21,
+ 20, 7, 6, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 23, 6, 7, 6, 21, 20, 22, 23, 22, 23, 22, 50,
+ 55, 54, 55, 62, 1, 53, 52, 39, 38, 47, 1, 21, 35, 17, 55, 33, 21, 3,149, 29, 74, 37, 37, 37, 39, 72, 68, 95, 83,108,104, 88,
+ 91, 72, 74, 37, 37, 37, 37, 74,119, 52, 24, 25, 50, 50, 45, 65, 56,144, 59, 62, 49, 49, 50, 25, 30, 45, 33,127, 58, 1,156, 3,
+122, 29, 74, 90, 91,103,104, 88, 92, 72, 67, 43, 37, 37, 39, 71, 75, 89, 91,101,103, 91, 87, 77,115, 50, 61, 62, 70, 68,123, 50,
+ 44, 30, 25, 25, 27, 47, 50,123, 68, 70, 62, 72, 39, 28,227, 1,156, 58,127, 0, 0, 1, 0, 88, 0, 0, 4,121, 3,249, 0, 54,
+ 0, 0, 1, 35, 53, 33, 23, 17, 35, 53, 7, 6, 7, 6, 21, 20, 22, 23, 22, 23, 22, 50, 55, 54, 55, 62, 1, 53, 52, 39, 38, 39,
+ 55, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 1, 60,227, 1,156, 58,127,
+ 33, 45, 30, 25, 50, 49, 49, 62, 59,144, 56, 65, 45, 50, 50, 25, 24, 52,119, 74, 37, 37, 37, 37, 74, 72, 91, 88,104,108, 83, 95,
+ 68, 72, 39, 38, 38, 38, 73, 3,122,127, 58,254,100,227, 28, 39, 72, 62, 70, 68,123, 50, 47, 27, 25, 25, 30, 44, 50,123, 68, 70,
+ 62, 61, 50,115, 77, 87, 91,103,101, 91, 89, 75, 71, 39, 37, 37, 43, 67, 72, 92, 88,104,103, 91, 91, 73, 0, 0, 0, 1, 0, 66,
+ 1,223, 4,143, 3,125, 0, 6, 0, 0, 19, 53, 1, 23, 7, 33, 21, 66, 1, 35, 90,160, 3,112, 1,223,123, 1, 35, 90,160,164,
+ 0, 1, 0, 66, 0,229, 4,143, 2,131, 0, 6, 0, 0, 19, 33, 21, 33, 23, 7, 1, 66, 4, 77,252,144,160, 90,254,221, 2,131,
+164,160, 90, 1, 35, 0, 0, 0, 0, 1, 2, 22, 0, 0, 3,181, 4, 77, 0, 6, 0, 0, 1, 51, 1, 7, 39, 17, 35, 2, 22,124,
+ 1, 34, 90,160,164, 4, 77,254,221, 90,160,252,144, 0, 0, 0, 0, 1, 1, 28, 0, 0, 2,187, 4, 77, 0, 6, 0, 0, 1, 17,
+ 35, 17, 7, 39, 1, 2,186,164,160, 90, 1, 36, 4, 77,251,179, 3,112,160, 90, 1, 35, 0, 0, 0, 1, 0, 66, 1,223, 4,143,
+ 3,125, 0, 6, 0, 0, 1, 33, 53, 33, 39, 55, 1, 4,143,251,179, 3,112,160, 90, 1, 35, 1,223,164,160, 90,254,221, 0, 0,
+ 0, 1, 0, 66, 0,229, 4,143, 2,131, 0, 6, 0, 0, 1, 21, 1, 39, 55, 33, 53, 4,143,254,221, 90,160,252,144, 2,131,123,
+254,221, 90,160,164, 0, 0, 0, 0, 1, 2, 22, 0, 0, 3,181, 4, 77, 0, 6, 0, 0, 33, 17, 51, 17, 55, 23, 1, 2, 22,164,
+160, 90,254,222, 4, 77,252,144,160, 90,254,221, 0, 1, 1, 71, 0, 0, 2,229, 4, 77, 0, 6, 0, 0, 33, 35, 1, 55, 23, 17,
+ 51, 2,229,123,254,221, 90,160,164, 1, 35, 90,160, 3,112, 0, 0, 2, 0, 66, 0, 0, 4,143, 4,124, 0, 9, 0, 19, 0, 0,
+ 9, 1, 39, 55, 33, 53, 33, 39, 55, 9, 1, 53, 1, 23, 7, 33, 21, 33, 23, 7, 4,143,254,221, 90,160,252,144, 3,112,160, 90,
+ 1, 35,251,179, 1, 35, 90,160, 3,112,252,144,160, 90, 3, 7,254,221, 90,160,164,160, 90,254,221,253,202, 82, 1, 35, 90,160,
+164,160, 90, 0, 0, 2, 0, 42, 0, 0, 4,167, 4, 77, 0, 9, 0, 19, 0, 0, 33, 1, 55, 23, 17, 51, 17, 55, 23, 9, 1, 51,
+ 1, 7, 39, 17, 35, 17, 7, 39, 3, 50,254,220, 90,160,164,160, 90,254,222,253,202, 82, 1, 34, 90,160,164,160, 90, 1, 35, 90,
+160, 3,112,252,144,160, 90,254,221, 4, 77,254,221, 90,160,252,144, 3,112,160, 90, 0, 0, 0, 0, 2, 0, 66, 0, 0, 4,143,
+ 4,124, 0, 9, 0, 19, 0, 0, 1, 21, 1, 39, 55, 33, 53, 33, 39, 55, 37, 1, 23, 7, 33, 21, 33, 23, 7, 1, 4,143,254,221,
+ 90,160,252,144, 3,112,160, 90,252,214, 1, 35, 90,160, 3,112,252,144,160, 90,254,221, 1,117, 82,254,221, 90,160,164,160, 90,
+193, 1, 35, 90,160,164,160, 90, 1, 35, 0, 0, 0, 1, 0, 66, 0, 0, 4,143, 4,124, 0, 17, 0, 0, 1, 39, 53, 1, 23, 7,
+ 33, 21, 33, 23, 7, 33, 21, 33, 23, 7, 1, 53, 1, 11,201, 1, 35, 90,160, 3,112,252,144,160,160, 3,112,252,144,160, 90,254,
+221, 2, 62,201, 82, 1, 35, 90,160,164,160,160,164,160, 90, 1, 35, 82, 0, 0, 0, 1, 0, 42, 0, 0, 4,167, 4, 77, 0, 17,
+ 0, 0, 1, 55, 51, 1, 7, 39, 17, 35, 17, 7, 39, 17, 35, 17, 7, 39, 1, 51, 2,104,202, 82, 1, 34, 90,160,164,160,160,164,
+160, 90, 1, 36, 82, 3,132,201,254,221, 90,160,252,144, 3,112,160,160,252,144, 3,112,160, 90, 1, 35, 0, 0, 0, 1, 0, 66,
+ 0, 0, 4,143, 4,124, 0, 17, 0, 0, 1, 23, 21, 1, 39, 55, 33, 53, 33, 39, 55, 33, 53, 33, 39, 55, 1, 21, 3,198,201,254,
+221, 90,160,252,144, 3,112,160,160,252,144, 3,112,160, 90, 1, 35, 2, 62,201, 82,254,221, 90,160,164,160,160,164,160, 90,254,
+221, 82, 0, 0, 0, 1, 0, 42, 0, 0, 4,167, 4, 77, 0, 17, 0, 0, 37, 7, 35, 1, 55, 23, 17, 51, 17, 55, 23, 17, 51, 17,
+ 55, 23, 1, 35, 2,104,200, 82,254,220, 90,160,164,160,160,164,160, 90,254,222, 82,201,201, 1, 35, 90,160, 3,112,252,144,160,
+160, 3,112,252,144,160, 90,254,221, 0, 0, 0, 0, 2, 0, 66, 0, 65, 4,143, 4, 33, 0, 6, 0, 13, 0, 0, 1, 21, 1, 39,
+ 55, 33, 61, 2, 1, 23, 7, 33, 21, 4,143,254,221, 90,160,252,144, 1, 35, 90,160, 3,112, 1,223,123,254,221, 90,160,164,164,
+123, 1, 35, 90,160,164, 0, 0, 0, 2, 0, 66, 0, 65, 4,143, 4, 33, 0, 6, 0, 13, 0, 0, 19, 33, 21, 33, 23, 7, 9, 1,
+ 33, 53, 33, 39, 55, 1, 66, 4, 77,252,144,160, 90,254,221, 4, 77,251,179, 3,112,160, 90, 1, 35, 1,223,164,160, 90, 1, 35,
+ 1, 31,164,160, 90,254,221, 0, 0, 2, 0, 66, 0,229, 4,143, 3,125, 0, 21, 0, 26, 0, 0, 1, 33, 55, 23, 7, 51, 21, 33,
+ 7, 33, 21, 33, 7, 39, 55, 35, 23, 7, 1, 53, 1, 23, 5, 33, 7, 23, 33, 1,113, 1,163, 86, 97, 54,250,254,210, 90, 1,136,
+254, 69, 86, 96, 54,227, 78, 90,254,221, 1, 35, 90, 1, 34,254, 62, 82, 82, 1,106, 2,213,168, 59,109, 82,164, 82,166, 58,108,
+ 78, 90, 1, 35, 82, 1, 35, 90,160, 82, 82, 0, 0, 3, 0, 66, 0,229, 4,143, 3,175, 0, 4, 0, 28, 0, 33, 0, 0, 1, 33,
+ 7, 23, 51, 55, 51, 39, 55, 1, 21, 1, 39, 55, 35, 7, 39, 55, 35, 23, 7, 1, 53, 1, 23, 7, 51, 55, 23, 3, 7, 33, 55, 39,
+ 2, 33,254,254, 82, 82,223,200,154, 78, 90, 1, 35,254,221, 90, 78,227, 31,140, 27,124, 78, 90,254,221, 1, 35, 90, 78,194, 46,
+140, 57, 35, 1, 33, 82, 82, 2,131, 82, 82,246, 78, 90,254,221, 82,254,221, 90, 78,158, 32,126, 78, 90, 1, 35, 82, 1, 35, 90,
+ 78,218, 32,254,244,164, 82, 82, 0, 2, 0, 66, 0,229, 4,143, 3,125, 0, 21, 0, 26, 0, 0, 1, 33, 7, 39, 55, 35, 53, 33,
+ 55, 33, 53, 33, 55, 23, 7, 51, 39, 55, 1, 21, 1, 39, 37, 33, 55, 39, 33, 3, 96,254, 93, 86, 97, 54,250, 1, 46, 90,254,120,
+ 1,187, 86, 96, 54,227, 78, 90, 1, 35,254,221, 90,254,222, 1,194, 82, 82,254,150, 1,141,168, 59,109, 82,164, 82,166, 58,108,
+ 78, 90,254,221, 82,254,221, 90,160, 82, 82, 0, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 14, 0, 0, 1, 7, 23, 33, 21, 33,
+ 23, 7, 1, 53, 1, 23, 7, 33, 21, 1, 31, 82, 82, 3,112,252,226, 78, 90,254,221, 1, 35, 90, 78, 3, 30, 2,131, 82, 82, 82,
+ 78, 90, 1, 35, 82, 1, 35, 90, 78, 82, 0, 0, 0, 1, 1, 28, 0, 0, 3,181, 4, 77, 0, 14, 0, 0, 1, 17, 35, 17, 7, 39,
+ 1, 51, 1, 7, 39, 17, 35, 19, 39, 2, 22, 82, 78, 90, 1, 36, 82, 1, 34, 90, 78, 82, 1, 83, 3,112,252,144, 3, 30, 78, 90,
+ 1, 35,254,221, 90, 78,252,226, 3,112, 82, 0, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 14, 0, 0, 1, 33, 53, 33, 39, 55,
+ 1, 21, 1, 39, 55, 33, 53, 33, 55, 3,178,252,144, 3, 30, 78, 90, 1, 35,254,221, 90, 78,252,226, 3,112, 82, 2,131, 82, 78,
+ 90,254,221, 82,254,221, 90, 78, 82, 82, 0, 0, 0, 1, 1, 28, 0, 0, 3,181, 4, 77, 0, 14, 0, 0, 37, 3, 51, 17, 55, 23,
+ 1, 35, 1, 55, 23, 17, 51, 17, 23, 2,187, 1, 82, 78, 90,254,222, 82,254,220, 90, 78, 82, 82,221, 3,112,252,226, 78, 90,254,
+221, 1, 35, 90, 78, 3, 30,252,144, 82, 0, 0, 0, 2, 0, 66, 0,229, 4,143, 3,125, 0, 5, 0, 21, 0, 0, 1, 33, 7, 23,
+ 33, 55, 47, 1, 55, 1, 21, 1, 39, 55, 33, 23, 7, 1, 53, 1, 23, 7, 3,178,253,109, 82, 82, 2,147, 82,164, 78, 90, 1, 35,
+254,221, 90, 78,254, 17, 78, 90,254,221, 1, 35, 90, 78, 2,131, 82, 82, 82,164, 78, 90,254,221, 82,254,221, 90, 78, 78, 90, 1,
+ 35, 82, 1, 35, 90, 78, 0, 0, 0, 2, 1, 28, 0, 0, 3,181, 4, 77, 0, 5, 0, 21, 0, 0, 1, 39, 7, 17, 23, 55, 19, 17,
+ 55, 23, 1, 35, 1, 55, 23, 17, 7, 39, 1, 51, 1, 7, 2,187, 83, 82, 82, 83, 81, 78, 90,254,222, 82,254,220, 90, 78, 78, 90,
+ 1, 36, 82, 1, 34, 90, 3,112, 82, 82,253,109, 82, 82, 2, 65,254, 17, 78, 90,254,221, 1, 35, 90, 78, 1,239, 78, 90, 1, 35,
+254,221, 90, 0, 0, 1, 0,155,255,198, 4, 54, 3, 97, 0, 14, 0, 0, 1, 35, 21, 1, 7, 1, 21, 35, 17, 55, 33, 21, 35, 1,
+ 7, 1,142,116, 2,110, 58,253,204,127, 58, 1,156,110, 2, 51, 58, 2,226,116,253,146, 58, 2, 53,112, 1,156, 58,127,253,204,
+ 58, 0, 0, 0, 0, 1, 0,155,255,198, 4, 54, 3, 97, 0, 14, 0, 0, 9, 1, 39, 1, 35, 53, 33, 23, 17, 35, 53, 1, 39, 1,
+ 53, 3, 67,253,146, 58, 2, 51,110, 1,156, 58,127,253,204, 58, 2,110, 2,226,253,146, 58, 2, 52,127, 58,254,100,112,253,203,
+ 58, 2,110,116, 0, 1, 0,155, 0, 0, 4, 54, 3,155, 0, 14, 0, 0, 37, 1, 55, 1, 53, 51, 17, 7, 33, 53, 51, 1, 55, 1,
+ 51, 3,183,253,146, 58, 2, 52,127, 58,254,100,112,253,203, 58, 2,110,116,243, 2,110, 58,253,205,110,254,100, 58,127, 2, 52,
+ 58,253,146, 0, 0, 1, 0,155, 0, 0, 4, 54, 3,155, 0, 14, 0, 0, 37, 1, 23, 1, 51, 21, 33, 39, 17, 51, 21, 1, 23, 1,
+ 21, 1,142, 2,110, 58,253,205,110,254,100, 58,127, 2, 52, 58,253,146,127, 2,110, 58,253,204,127, 58, 1,156,112, 2, 53, 58,
+253,146,116, 0, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 15, 0, 0, 1, 7, 1, 53, 1, 23, 33, 21, 33, 7, 33, 21, 33, 23,
+ 33, 21, 1,191, 90,254,221, 1, 35, 90, 2,208,252,222,119, 3,153,252,103,119, 3, 34, 1, 63, 90, 1, 35, 82, 1, 35, 90, 82,
+119, 82,119, 82, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 15, 0, 0, 1, 33, 53, 33, 55, 33, 53, 33, 39, 33, 53, 33, 55, 1,
+ 21, 1, 3, 18,253, 48, 3, 34,119,252,103, 3,153,119,252,222, 2,208, 90, 1, 35,254,221, 1, 63, 82,119, 82,119, 82, 90,254,
+221, 82,254,221, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 22, 0, 0, 1, 51, 23, 55, 23, 55, 23, 55, 51, 21, 7, 39, 7, 39,
+ 7, 39, 35, 23, 7, 1, 53, 1, 23, 1, 31,129, 58,151,150,150,150, 59, 33, 92,150,150,150,151, 91, 96,160, 90,254,221, 1, 35,
+ 90, 2,131, 67,173,173,173,173, 67,164,106,173,173,173,173,106,160, 90, 1, 35, 82, 1, 35, 90, 0, 1, 0, 66, 0,229, 4,143,
+ 3,125, 0, 22, 0, 0, 1, 39, 55, 1, 21, 1, 39, 55, 35, 7, 39, 7, 39, 7, 39, 53, 51, 23, 55, 23, 55, 23, 55, 3,178,160,
+ 90, 1, 35,254,221, 90,160, 96, 91,151,150,150,150, 92, 33, 59,150,150,150,151, 58, 2,131,160, 90,254,221, 82,254,221, 90,160,
+106,173,173,173,173,106,164, 67,173,173,173,173, 67, 0, 0, 0, 0, 1, 1, 28, 0, 0, 3,181, 4, 77, 0, 25, 0, 0, 37, 21,
+ 35, 53, 35, 53, 51, 53, 35, 53, 51, 53, 7, 39, 1, 51, 1, 7, 39, 21, 51, 21, 35, 21, 51, 21, 2,186,164,250,250,250,250,160,
+ 90, 1, 36, 82, 1, 34, 90,160,250,250,250,188,188,188,164,116,164,248,160, 90, 1, 35,254,221, 90,160,248,164,116,164, 0, 0,
+ 0, 1, 1, 28, 0, 0, 3,181, 4, 77, 0, 25, 0, 0, 1, 53, 51, 21, 51, 21, 35, 21, 51, 21, 35, 21, 55, 23, 1, 35, 1, 55,
+ 23, 53, 35, 53, 51, 53, 35, 53, 2, 22,164,250,250,250,250,160, 90,254,222, 82,254,220, 90,160,250,250,250, 3,144,189,189,164,
+116,164,247,160, 90,254,221, 1, 35, 90,160,247,164,116,164, 0, 0, 3, 0, 66, 0,229, 4,143, 3,125, 0, 9, 0, 13, 0, 17,
+ 0, 0, 1, 21, 33, 23, 7, 1, 53, 1, 23, 7, 5, 53, 51, 21, 51, 53, 51, 21, 2, 33,254,254,160, 90,254,221, 1, 35, 90,160,
+ 1,127,187,123,187, 2,131,164,160, 90, 1, 35, 82, 1, 35, 90,160,164,164,164,164,164, 0, 0, 0, 3, 1, 28, 0, 0, 3,181,
+ 4, 77, 0, 9, 0, 13, 0, 17, 0, 0, 1, 17, 7, 39, 1, 51, 1, 7, 39, 19, 7, 23, 35, 55, 19, 21, 35, 55, 2, 22,160, 90,
+ 1, 36, 82, 1, 34, 90,160, 1, 1, 1,165, 1,163,164, 1, 2,110, 1, 2,160, 90, 1, 35,254,221, 90,160,254,254,125,187,187,
+254,202,187,187, 0, 3, 0, 66, 0,229, 4,143, 3,125, 0, 9, 0, 13, 0, 17, 0, 0, 1, 33, 39, 55, 1, 21, 1, 39, 55, 33,
+ 43, 1, 53, 51, 5, 35, 53, 51, 2,176, 1, 2,160, 90, 1, 35,254,221, 90,160,254,254,125,187,187,254,202,187,187, 2,131,160,
+ 90,254,221, 82,254,221, 90,160,164,164,164, 0, 0, 3, 1, 28, 0, 0, 3,181, 4, 77, 0, 9, 0, 13, 0, 17, 0, 0, 1, 17,
+ 55, 23, 1, 35, 1, 55, 23, 17, 55, 39, 51, 21, 3, 39, 51, 21, 2,186,160, 90,254,222, 82,254,220, 90,160, 1, 1,164,163, 1,
+164, 1,223,254,254,160, 90,254,221, 1, 35, 90,160, 1, 2,125,187,187, 1, 54,187,187, 0, 0, 0, 1, 0, 66, 0,229, 4,143,
+ 3,125, 0, 13, 0, 0, 19, 1, 23, 7, 33, 21, 33, 23, 7, 1, 17, 35, 17, 51,230, 1, 35, 90,160, 2,204,253, 52,160, 90,254,
+221,164,164, 2, 90, 1, 35, 90,160,164,160, 90, 1, 35,254,221, 2,152, 0, 0, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 13,
+ 0, 0, 1, 17, 51, 17, 35, 17, 1, 39, 55, 33, 53, 33, 39, 55, 3,235,164,164,254,221, 90,160,253, 52, 2,204,160, 90, 2, 90,
+ 1, 35,253,104, 1, 35,254,221, 90,160,164,160, 90, 0, 0, 0, 0, 2, 0, 25, 0,188, 4,143, 3,166, 0, 6, 0, 13, 0, 0,
+ 1, 7, 23, 53, 33, 53, 33, 19, 9, 1, 21, 33, 17, 33, 1, 63,194,194, 3, 10,252,246, 79,254,139, 1,117, 3, 1,252,255, 2,
+244,195,195, 93,204,254, 37, 1,117, 1,117,201,254,168, 0, 0, 0, 2, 0,243, 0, 0, 3,222, 4,118, 0, 6, 0, 13, 0, 0,
+ 1, 51, 17, 51, 17, 51, 39, 1, 35, 17, 33, 17, 35, 1, 1,166, 92,204, 94,196, 1,118,202,254,168,200, 1,116, 3, 80,252,246,
+ 3, 10,194,254,239,252,255, 3, 1, 1,117, 0, 0, 2, 0, 66, 0,188, 4,185, 3,166, 0, 6, 0, 13, 0, 0, 1, 21, 33, 21,
+ 33, 21, 55, 1, 53, 33, 17, 33, 53, 1, 3,146,252,246, 3, 10,194,254,240,252,254, 3, 2, 1,116, 2,244, 93,204, 93,195,254,
+139,201, 1, 88,201,254,139, 0, 0, 2, 0,243, 0, 0, 3,222, 4,118, 0, 6, 0, 13, 0, 0, 1, 35, 17, 35, 17, 35, 23, 1,
+ 51, 17, 33, 17, 51, 1, 3, 44, 94,204, 92,194,254,140,200, 1, 88,202,254,138, 1, 38, 3, 10,252,246,194, 1, 17, 3, 1,252,
+255,254,139, 0, 0, 4, 0,243, 0, 0, 3,222, 4,118, 0, 6, 0, 10, 0, 14, 0, 21, 0, 0, 1, 17, 51, 39, 7, 51, 25, 1,
+ 21, 51, 53, 37, 33, 17, 33, 25, 1, 35, 9, 1, 35, 17, 2,206, 94,196,194, 92,204,254,238, 1, 88,254,168,200, 1,116, 1,118,
+202, 1,224, 1,112,194,194,254,144,254,242,140,140, 70,254,232, 1,154, 1,103, 1,117,254,139,254,153, 0, 0, 0, 2, 0,243,
+ 0, 0, 3,222, 4,118, 0, 10, 0, 21, 0, 0, 37, 17, 51, 39, 7, 51, 17, 35, 21, 33, 53, 37, 17, 35, 9, 1, 35, 17, 51, 17,
+ 33, 17, 2,206, 94,196,194, 92,200, 2, 94,254, 36,200, 1,116, 1,118,202,202,253, 22,210, 2,126,194,194,253,130,140,140, 70,
+ 1,233, 1,117,254,139,254, 23,254,232, 1, 24, 0, 3, 0,243, 0, 0, 3,222, 4,118, 0, 11, 0, 14, 0, 25, 0, 0, 1, 35,
+ 7, 51, 17, 35, 21, 33, 53, 35, 17, 51, 47, 1, 7, 3, 17, 35, 9, 1, 35, 17, 51, 17, 33, 17, 2,224,240, 74, 92,200, 2, 94,
+202, 94,124, 72, 71,101,200, 1,116, 1,118,202,202,253, 22, 3,154, 74,253,130,140,140, 2,126,123, 71, 71,253, 77, 1,233, 1,
+117,254,139,254, 23,254,232, 1, 24, 0, 0, 0, 0, 3, 0,243, 0, 0, 3,222, 4,118, 0, 6, 0, 13, 0, 24, 0, 0, 1, 7,
+ 51, 17, 35, 21, 33, 19, 17, 33, 53, 35, 17, 51, 1, 17, 35, 9, 1, 35, 17, 51, 17, 33, 17, 2, 70,160, 92,200, 1, 12, 70, 1,
+ 12,202, 94,254,144,200, 1,116, 1,118,202,202,253, 22, 3,239,159,253,130,140, 3,169,252, 87,140, 2,126,253,200, 1,233, 1,
+117,254,139,254, 23,254,232, 1, 24, 0, 0, 0, 0, 3, 0,243, 0, 0, 3,222, 4,118, 0, 6, 0, 12, 0, 23, 0, 0, 1, 51,
+ 39, 7, 51, 17, 51, 3, 51, 39, 7, 51, 55, 7, 35, 9, 1, 35, 23, 35, 17, 33, 17, 35, 2,206, 94,196,194, 92,204, 8,102,196,
+194,100, 94,172,200, 1,116, 1,118,202,202,202,254,168,200, 2,136,194,194,253,190, 3, 10,194,194, 94,173, 1,117,254,139,200,
+253,199, 2, 57, 0, 3, 0,243, 0, 0, 3,222, 4,118, 0, 10, 0, 16, 0, 31, 0, 0, 1, 17, 35, 21, 33, 53, 35, 17, 51, 39,
+ 7, 37, 51, 39, 7, 51, 55, 3, 35, 55, 35, 9, 1, 35, 23, 35, 17, 51, 17, 33, 17, 51, 2, 2,200, 2, 94,202, 94,196,194, 1,
+ 32,102,196,194,100, 94,172,200,200,200, 1,116, 1,118,202,202,202,202,253, 22,200, 2,136,254, 74,140,140, 1,182,194,194,200,
+194,194, 94,254,139,200, 1,117,254,139,200,254,223,254,232, 1, 24, 0, 0, 0, 0, 2, 0, 66, 0,188, 4,185, 3,166, 0, 10,
+ 0, 21, 0, 0, 1, 39, 35, 17, 51, 53, 33, 21, 55, 39, 21, 1, 21, 33, 17, 33, 21, 33, 53, 9, 1, 53, 1, 21, 1,140,140, 2,
+126,194,194,253,200,254,232, 1, 24, 1,234, 1,116,254,140, 2,151,201,253,162,201, 93,195,195, 93,254,238,201, 2,234,201,201,
+254,139,254,139,201, 0, 0, 0, 0, 2, 0, 69, 0, 0, 4,140, 4, 70, 0, 9, 0, 15, 0, 0, 1, 55, 33, 21, 35, 1, 7, 1,
+ 21, 35, 1, 21, 33, 17, 35, 17, 1, 42, 58, 1,156,227, 2,110,116,253,146,127, 3, 97,252, 4, 73, 3, 39, 58,127,253,146,116,
+ 2,110,227, 2,187, 73,252, 3, 4, 70, 0, 0, 0, 2, 0, 69, 0, 0, 4,140, 4, 70, 0, 9, 0, 15, 0, 0, 37, 33, 53, 51,
+ 1, 55, 1, 53, 51, 17, 19, 17, 33, 53, 33, 17, 3,108,254,100,228,253,146,116, 2,110,126,230,251,186, 3,252,229,127, 2,110,
+116,253,146,227,254,100, 3, 38,251,187, 73, 3,252, 0, 0, 0, 0, 2, 0,243, 0, 0, 3,222, 4,118, 0, 9, 0, 19, 0, 0,
+ 1, 17, 35, 23, 55, 35, 17, 51, 39, 7, 23, 35, 9, 1, 35, 17, 51, 9, 1, 51, 2, 2, 92,194,196, 94, 94,196,194, 22,200, 1,
+116, 1,118,202,202,254,138,254,140,200, 3, 80,253,214,194,194, 2, 42,194,194, 79, 1,117,254,139,254,116,254,139, 1,117, 0,
+ 0, 3, 0, 66, 0,229, 4,143, 3,125, 0, 30, 0, 39, 0, 48, 0, 0, 1, 6, 7, 6, 35, 34, 39, 38, 39, 35, 53, 51, 54, 55,
+ 54, 51, 50, 22, 23, 22, 23, 22, 23, 51, 39, 55, 1, 21, 1, 39, 55, 37, 38, 39, 38, 35, 34, 7, 6, 7, 5, 33, 22, 23, 22, 51,
+ 50, 55, 54, 2,197, 19, 52, 82,118,120, 78, 49, 18,107,107, 19, 50, 79,119, 57,103, 39, 32, 28, 6, 4,237,160, 90, 1, 35,254,
+221, 90,160,254,153, 11, 17, 48, 71, 68, 50, 18, 11, 1, 38,254,219, 12, 15, 43, 74, 68, 53, 17, 1,223, 64, 51, 80, 79, 50, 66,
+164, 66, 52, 82, 44, 40, 32, 58, 12, 14,160, 90,254,221, 82,254,221, 90,160,164, 20, 17, 49, 49, 17, 20,164, 19, 17, 47, 48, 16,
+ 0, 2, 0, 42, 0, 0, 4,167, 4, 77, 0, 9, 0, 19, 0, 0, 33, 35, 1, 55, 23, 17, 51, 17, 55, 23, 19, 1, 7, 39, 17, 35,
+ 17, 7, 39, 1, 1,160, 82,254,220, 90,160,164,160, 90,194, 1, 34, 90,160,164,160, 90, 1, 36, 1, 35, 90,160, 3,112,252,144,
+160, 90, 3, 42,254,221, 90,160,252,144, 3,112,160, 90, 1, 35, 0, 1, 0, 66,255, 1, 4,143, 5, 97, 0, 25, 0, 0, 1, 55,
+ 33, 53, 33, 39, 55, 33, 53, 33, 39, 55, 1, 21, 7, 23, 21, 7, 23, 21, 1, 39, 55, 33, 53, 33, 3, 18,160,252,144, 3,112,160,
+160,252,144, 3,112,160, 90, 1, 35,201,201,201,201,254,221, 90,160,252,144, 3,112, 1, 63,160,164,160,160,164,160, 90,254,221,
+ 82,201,201, 82,201,201, 82,254,221, 90,160,164, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 17, 0, 0, 1, 21, 35, 53, 33, 23,
+ 7, 1, 53, 1, 23, 7, 33, 53, 51, 21, 33, 21, 3, 30,164,254,165,160, 90,254,221, 1, 35, 90,160, 1, 91,164, 1,113, 1,223,
+250,250,160, 90, 1, 35, 82, 1, 35, 90,160,250,250,164, 0, 0, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 17, 0, 0, 1, 33,
+ 53, 33, 53, 51, 21, 33, 39, 55, 1, 21, 1, 39, 55, 33, 21, 35, 1,178,254,144, 1,112,164, 1, 92,160, 90, 1, 35,254,221, 90,
+160,254,164,164, 1,223,164,250,250,160, 90,254,221, 82,254,221, 90,160,250, 0, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 23,
+ 0, 0, 1, 35, 23, 7, 1, 53, 1, 23, 7, 51, 53, 51, 21, 51, 39, 55, 1, 21, 1, 39, 55, 35, 21, 35, 2, 22,247,160, 90,254,
+221, 1, 35, 90,160,247,164,248,160, 90, 1, 35,254,221, 90,160,248,164, 1,223,160, 90, 1, 35, 82, 1, 35, 90,160,250,250,160,
+ 90,254,221, 82,254,221, 90,160,250, 0, 0, 0, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 25, 0, 0, 1, 21, 35, 53, 35, 21,
+ 35, 53, 35, 23, 7, 1, 53, 1, 23, 7, 51, 53, 51, 21, 51, 53, 51, 21, 51, 21, 3,210,164,116,164,247,160, 90,254,221, 1, 35,
+ 90,160,247,164,116,164,189, 1,223,250,250,250,250,160, 90, 1, 35, 82, 1, 35, 90,160,250,250,250,250,164, 0, 0, 1, 0, 66,
+ 0,229, 4,143, 3,125, 0, 25, 0, 0, 19, 35, 53, 51, 53, 51, 21, 51, 53, 51, 21, 51, 39, 55, 1, 21, 1, 39, 55, 35, 21, 35,
+ 53, 35, 21, 35,254,188,188,164,116,164,248,160, 90, 1, 35,254,221, 90,160,248,164,116,164, 1,223,164,250,250,250,250,160, 90,
+254,221, 82,254,221, 90,160,250,250,250, 0, 0, 0, 1, 0, 66, 0,229, 4,143, 3,125, 0, 31, 0, 0, 1, 23, 7, 1, 53, 1,
+ 23, 7, 51, 53, 51, 21, 51, 53, 51, 21, 51, 39, 55, 1, 21, 1, 39, 55, 35, 21, 35, 53, 35, 21, 35, 53, 1, 31,160, 90,254,221,
+ 1, 35, 90,160,167,134, 56,134,168,160, 90, 1, 35,254,221, 90,160,168,134, 56,134, 1,223,160, 90, 1, 35, 82, 1, 35, 90,160,
+250,250,250,250,160, 90,254,221, 82,254,221, 90,160,250,250,250,250, 0, 0, 0, 0, 2, 0, 25, 0,188, 4,143, 3,166, 0, 2,
+ 0, 9, 0, 0, 1, 7, 23, 19, 33, 21, 33, 17, 9, 1, 1, 63,194,194, 79, 3, 1,252,255,254,139, 1,117, 2,244,195,195, 1,
+ 21,164,254,221, 1,117, 1,117, 0, 2, 0, 66, 0,188, 4,184, 3,166, 0, 2, 0, 9, 0, 0, 1, 17, 55, 37, 17, 9, 1, 17,
+ 33, 53, 3,146,194,254,239, 1,117,254,139,252,255, 2,244,254,122,195, 82, 1, 35,254,139,254,139, 1, 35,164, 0, 3, 0, 25,
+ 0,188, 4,184, 3,166, 0, 2, 0, 5, 0, 15, 0, 0, 1, 7, 23, 1, 17, 55, 5, 17, 9, 1, 17, 33, 17, 9, 1, 17, 1, 63,
+194,194, 2, 83,194,253, 58,254,139, 1,117, 1,181, 1,117,254,139, 2,244,195,195, 1,134,254,122,195, 82,254,221, 1,117, 1,
+117,254,221, 1, 35,254,139,254,139, 1, 35, 0, 0, 2, 0,190,255,231, 4, 23, 5, 45, 0, 29, 0, 41, 0, 58, 64, 14, 0, 39,
+ 33, 9, 27, 6, 39, 21, 6, 15, 33, 27, 15, 21,184, 1, 13, 64, 10, 42, 12, 36, 3, 0, 30, 18, 36, 24, 42, 16,212,204,220,204,
+ 57, 57, 17, 57, 49, 0, 16,228,204,220,204, 16,206, 16,206, 17, 18, 57, 17, 18, 57, 48, 1, 62, 1, 53, 52, 38, 35, 34, 6, 35,
+ 34, 38, 53, 52, 54, 51, 50, 18, 17, 16, 0, 35, 34, 38, 53, 52, 18, 51, 50, 22, 7, 52, 38, 35, 34, 2, 21, 20, 22, 51, 50, 18,
+ 3, 74, 15, 15, 73, 72, 55,144, 36, 36, 48,144,101,180,214,254,223,213,152,203,221,162,101,130, 11, 87, 79,109,141, 86, 80,109,
+141, 2,109, 87,163, 75,129,131,116, 44, 31, 62, 98,254,202,254,249,254,177,254, 70,216,163,198, 1, 1, 91,224,116,125,254,254,
+207,116,123, 1, 4, 0, 0, 0, 0, 3, 0, 73, 0, 98, 4,138, 4,163, 0, 33, 0, 48, 0, 63, 0, 0, 1, 23, 7, 22, 23, 22,
+ 21, 20, 7, 6, 7, 14, 1, 34, 39, 38, 39, 7, 39, 55, 38, 39, 38, 53, 52, 55, 54, 55, 62, 1, 50, 23, 22, 23, 6, 34, 7, 6,
+ 7, 14, 1, 21, 20, 23, 22, 23, 1, 38, 39, 23, 1, 22, 23, 22, 50, 55, 54, 55, 62, 1, 53, 52, 39, 38, 4, 38, 99,118, 45, 26,
+ 39, 39, 39, 79, 79,190,221, 95, 64, 56,118, 99,117, 45, 27, 39, 39, 39, 79, 79,190,221, 95, 65, 58,247,163, 71, 69, 58, 59, 57,
+ 28, 17, 26, 2, 40, 36, 40,175,253,216, 35, 38, 71,163, 70, 70, 58, 59, 57, 28, 16, 4,162, 99,118, 56, 64, 95,112,109, 95, 95,
+ 79, 78, 80, 40, 26, 45,118, 99,117, 58, 65, 95,109,112, 95, 95, 79, 79, 80, 40, 28, 45, 28, 30, 30, 57, 59,140, 83, 80, 70, 40,
+ 36, 2, 40, 26, 17,142,253,216, 25, 16, 30, 30, 30, 57, 59,140, 80, 83, 70, 39, 0, 2,255,250, 0, 0, 4,217, 5,143, 0, 3,
+ 0, 6, 0, 79, 64, 42, 4,105, 5, 4, 2, 3, 2, 6,105, 3, 3, 2, 5,105, 0, 1, 0, 4,105, 6, 4, 1, 1, 0, 66, 4,
+ 1, 5,249, 1,251, 0, 6, 5, 4, 2, 1, 5, 7, 3, 0, 7, 16,212,204, 17, 23, 57, 49, 0, 47,228,236, 17, 57, 48, 75, 83,
+ 88, 7, 16, 8,237, 7, 16, 5,237, 7, 16, 5,237, 7, 16, 8,237, 89, 34, 35, 1, 51, 9, 2, 33, 6, 2, 6,209, 2, 8,253,
+143,254,144, 2,225, 5,143,250,113, 4,195,251,233, 0, 0, 0, 0, 2,255,250, 0, 0, 4,217, 5,143, 0, 3, 0, 6, 0, 0,
+ 3, 33, 1, 35, 55, 1, 33, 6, 4,223,253,248,209,104, 1,113,253, 31, 5,143,250,113,204, 4, 23, 0, 0, 0, 0, 1, 0,129,
+ 0, 0, 4, 80, 5,184, 0, 26, 0, 0, 1, 22, 23, 30, 1, 51, 33, 21, 33, 34, 38, 2, 16, 18, 54, 51, 33, 21, 33, 34, 7, 6,
+ 7, 6, 7, 33, 21, 1, 48, 8, 34, 44,152, 90, 1,216,254, 40,136,232,134,134,232,136, 1,216,254, 40, 92, 74, 78, 42, 34, 8,
+ 3, 30, 2,135,102, 95,130,150,170,196, 1, 81, 1,142, 1, 81,196,170, 75, 77,128, 95,102,170, 0, 3, 0,129,255, 79, 4, 80,
+ 6,105, 0, 28, 0, 37, 0, 43, 0, 0, 37, 22, 51, 33, 21, 33, 34, 39, 7, 39, 55, 38, 39, 38, 16, 18, 54, 59, 1, 55, 23, 7,
+ 51, 21, 35, 3, 33, 21, 33, 19, 35, 34, 7, 6, 7, 6, 7, 33, 7, 35, 22, 23, 22, 23, 2, 76, 21, 23, 1,216,254, 40, 48, 44,
+ 58,163, 67,121, 69, 66,134,232,136,170, 54,163, 39,124,176,144, 1, 62,254,142, 18,118, 92, 74, 75, 45, 34, 8, 1, 46, 52,250,
+ 8, 34, 36, 58,174, 4,170, 12,189, 49,221, 99,172,169, 1,142, 1, 81,196,177, 50,127,170,254, 35,170, 2,135, 75, 75,130, 95,
+102,170,102, 95,108, 70, 0, 0, 0, 1, 0,130, 0,165, 4, 79, 4, 93, 0, 23, 0, 66, 0,176, 8, 47,176, 9, 51,176, 10, 51,
+177, 5, 4,237,177, 6, 4,237,177, 7, 4,237,176, 1,176, 5, 16,222,176, 2, 50,177, 0, 4,237,177, 23, 4,237,176, 18,176,
+ 0, 16,222,176, 19, 50,176, 20, 50,177, 15, 4,237,177, 16, 4,237,177, 17, 4,237, 1, 48, 49, 1, 21, 33, 22, 23, 22, 51, 33,
+ 21, 33, 34, 46, 1, 16, 62, 1, 51, 33, 21, 33, 34, 7, 6, 7, 4, 78,252,237, 22, 61, 99,133, 1,216,254, 40,136,230,134,134,
+230,136, 1,216,254, 40,133, 99, 61, 22, 2,214,170, 73, 57, 91,170,127,220, 1, 2,220,127,170, 91, 57, 73, 0, 0, 1, 0,129,
+ 0, 0, 4, 80, 5,184, 0, 26, 0, 0, 1, 38, 39, 46, 1, 35, 33, 53, 33, 50, 22, 18, 16, 2, 6, 35, 33, 53, 33, 50, 55, 54,
+ 55, 54, 55, 33, 53, 3,160, 8, 32, 44,152, 90,254, 40, 1,216,136,232,134,134,232,136,254, 40, 1,216, 92, 74, 76, 44, 32, 8,
+252,226, 3, 49,102, 95,130,150,170,196,254,175,254,114,254,175,196,170, 75, 77,128, 95,102,170, 0, 3, 0,129,255, 79, 4, 80,
+ 6,105, 0, 28, 0, 37, 0, 43, 0, 0, 1, 38, 35, 33, 53, 33, 50, 23, 55, 23, 7, 22, 23, 22, 16, 2, 6, 43, 1, 7, 39, 55,
+ 35, 53, 51, 19, 33, 53, 33, 3, 51, 50, 55, 54, 55, 54, 55, 33, 55, 51, 38, 39, 38, 39, 2,133, 21, 22,254, 40, 1,216, 47, 45,
+ 57,163, 67,121, 68, 68,134,232,136,171, 54,163, 39,123,174,146,254,192, 1,114, 18,120, 92, 74, 74, 46, 32, 8,254,211, 52,249,
+ 8, 32, 37, 58, 5, 10, 4,170, 12,189, 49,221, 99,172,169,254,114,254,175,196,177, 50,127,170, 1,221,170,253,121, 75, 75,130,
+ 95,102,170,102, 95,108, 70, 0, 0, 1, 0,130, 0,165, 4, 79, 4, 93, 0, 23, 0, 0, 19, 53, 33, 38, 39, 38, 35, 33, 53, 33,
+ 50, 30, 1, 16, 14, 1, 35, 33, 53, 33, 50, 55, 54, 55,131, 3, 19, 22, 62, 98,134,254, 40, 1,216,136,230,134,134,230,136,254,
+ 40, 1,216,134, 98, 62, 22, 2, 44,170, 73, 57, 91,170,127,220,254,254,220,127,170, 91, 57, 73, 0, 1, 0,152,254, 76, 4, 57,
+ 5,238, 0, 7, 0, 31,185, 0, 5, 1, 15, 64, 11, 1, 3, 0, 8, 4,128, 2, 6,128, 0, 8, 16,212,236,212,236, 49, 0, 16,
+196, 50,212,236, 48, 19, 17, 33, 17, 35, 17, 33, 17,152, 3,161,155,253,149,254, 76, 7,162,248, 94, 7, 30,248,226, 0, 0, 0,
+ 0, 1, 0,143,254, 76, 4, 61, 5,238, 0, 11, 0, 55,180, 11, 5, 12, 9, 0,191, 1, 15, 0, 2, 0, 9, 1, 15, 0, 7, 1,
+ 14, 0, 2, 1, 16, 64, 11, 12, 11, 10, 8, 5, 0, 5, 1, 6, 3, 12, 16,212, 60,196, 23, 57, 49, 0, 16,228,244,236, 16,238,
+ 17, 18, 57, 57, 48, 1, 33, 21, 33, 53, 9, 1, 53, 33, 21, 33, 1, 1, 76, 2,241,252, 82, 2, 37,253,219, 3,154,253, 35, 2,
+ 10,254,213,137, 92, 3,151, 3, 80, 95,140,252,221, 0, 0, 0, 0, 1, 0, 88, 2, 45, 4,121, 2,215, 0, 3, 0, 17,182, 0,
+160, 2, 4, 1, 0, 4, 16,212,196, 49, 0, 16,212,236, 48, 19, 33, 21, 33, 88, 4, 33,251,223, 2,215,170, 0, 0, 2, 0, 88,
+ 0, 0, 4,121, 4,147, 0, 3, 0, 15, 0, 0, 1, 33, 53, 33, 1, 17, 33, 53, 33, 17, 51, 17, 33, 21, 33, 17, 4,121,251,223,
+ 4, 33,253,155,254, 68, 1,188,168, 1,189,254, 67, 3,233,170,251,109, 1, 73,170, 1, 76,254,180,170,254,183, 0, 1, 0,102,
+255, 66, 4, 55, 5,213, 0, 3, 0, 24, 64, 11, 2, 0,136, 4, 1, 30, 0, 2, 30, 3, 4, 16,212,236,212,236, 49, 0, 16,244,
+196, 48, 1, 51, 1, 35, 3,121,190,252,238,191, 5,213,249,109,255,255, 0,166, 0,175, 4, 43, 4, 85, 16, 7, 0, 13, 0, 0,
+254,101, 0, 0,255,255, 1, 43, 1, 71, 3,166, 3,194, 16, 7, 0,114, 0, 0,253,210, 0, 0,255,255, 1, 63, 1,154, 3,145,
+ 3,234, 16, 6, 6,151, 0,201, 0, 1, 0, 59,255,217, 4,160, 6,160, 0, 10, 0, 47, 64, 26, 10, 3, 2, 1, 0, 5, 11, 5,
+ 4, 8, 6, 11, 10, 9, 8, 7, 4, 3, 2, 7, 5, 0, 11, 5, 1, 11, 16,212,196, 18, 57, 17, 23, 57, 49, 0, 16,212,196,192,
+192, 18, 23, 57, 48, 19, 39, 37, 19, 1, 51, 21, 35, 1, 35, 3,100, 41, 1, 35,219, 1,211,148, 47,254, 6,127,246, 2,221,125,
+ 98,253, 37, 5,191,131,249,188, 3, 57, 0, 0, 0, 2, 0,186, 0,250, 4, 23, 3,240, 0, 11, 0, 37, 0, 0, 1, 46, 1, 35,
+ 34, 6, 21, 20, 22, 51, 50, 54, 1, 34, 38, 39, 14, 1, 35, 34, 38, 53, 52, 54, 51, 50, 22, 23, 62, 1, 51, 21, 34, 6, 7, 30,
+ 1, 51, 2,170, 56, 92, 60, 72, 90, 82, 68, 68,106, 1,154, 80,128, 78, 66,132, 84,126,166,158,132, 94,136, 56, 46,148, 90, 56,
+104, 46, 56, 92, 58, 2,123,134, 99,133,106,109,129,118,254,253,100,131,124,107,214,165,173,206,115,129,117,127,140,117,124,136,
+100, 0, 0, 0, 0, 3, 0, 41, 0,250, 4,168, 3,240, 0, 11, 0, 23, 0, 47, 0, 55, 64, 28, 36, 24, 9, 21, 3,225, 39, 33,
+226, 15, 9,225, 45, 27,223, 48, 12, 0, 36, 24, 18, 6,100, 30, 18,100, 42, 48, 16,212,236,212,236, 17, 57, 57, 57, 57, 49, 0,
+ 16,252, 60,236, 50,252, 60,236, 50, 17, 57, 57, 48, 1, 30, 1, 51, 50, 54, 53, 52, 38, 35, 34, 6, 7, 46, 1, 35, 34, 6, 21,
+ 20, 22, 51, 50, 54, 19, 62, 1, 51, 50, 22, 21, 20, 6, 35, 34, 38, 39, 14, 1, 35, 34, 38, 53, 52, 54, 51, 50, 22, 2,182, 57,
+ 91, 61, 71, 91, 84, 70, 66,105,203, 56, 92, 61, 71, 91, 83, 68, 67,106,126, 47,147, 91,119,172,163,126, 83,128, 78, 65,132, 85,
+125,166,157,132, 94,136, 2,115,136,100,134,108,107,128,117,116,134, 99,133,106,109,129,118, 0,255,117,127,219,160,167,212,100,
+131,124,107,214,165,173,206,115, 0, 1, 0,125, 1, 31, 4, 84, 4,245, 0, 5, 0, 0, 1, 33, 17, 51, 17, 33, 4, 84,252, 42,
+170, 3, 44, 1, 31, 3,214,252,212, 0, 0, 0, 0, 1, 0,125, 1, 31, 4, 84, 4,245, 0, 5, 0, 0, 1, 33, 1, 51, 1, 33,
+ 4, 84,252, 42, 3, 24,170,253,112, 2,164, 1, 31, 3,214,252,212, 0, 0, 0, 0, 1, 0,164, 0, 0, 4, 44, 4,162, 0, 6,
+ 0, 0, 51, 1, 51, 1, 35, 9, 1,164, 1, 78,237, 1, 77,191,254,251,254,251, 4,162,251, 94, 3,172,252, 84, 0, 1, 0,164,
+ 0, 0, 4, 44, 4,162, 0, 6, 0, 0, 19, 51, 9, 1, 51, 1, 35,164,191, 1, 5, 1, 5,191,254,179,237, 4,162,252, 84, 3,
+172,251, 94, 0, 0, 1, 0,164, 0, 0, 4, 44, 4,162, 0, 36, 0, 0, 19, 52, 55, 54, 55, 54, 55, 54, 51, 50, 22, 23, 22, 23,
+ 22, 21, 17, 35, 17, 52, 39, 38, 39, 38, 39, 38, 35, 34, 7, 6, 7, 6, 7, 6, 21, 17, 35,164, 25, 26, 59, 57, 95, 85,105,106,
+170, 66, 57, 29, 24,172, 12, 10, 7, 29, 75, 71, 76, 86, 60, 83, 21, 13, 4, 12,173, 2, 68,230, 98,103, 58, 56, 32, 29, 58, 59,
+ 51,108, 92,238,253,188, 2,162, 93, 65, 57, 14, 57, 32, 30, 30, 41, 48, 33, 38,112, 48,253, 96, 0, 1, 0,164, 0, 0, 4, 44,
+ 4,162, 0, 36, 0, 0, 19, 17, 51, 17, 20, 23, 22, 23, 22, 23, 22, 51, 50, 55, 54, 55, 54, 55, 54, 53, 17, 51, 17, 20, 7, 6,
+ 7, 14, 1, 35, 34, 39, 38, 39, 38, 39, 38,164,173, 12, 4, 13, 21, 83, 60, 86, 76, 71, 75, 29, 7, 10, 12,172, 24, 29, 57, 66,
+170,106,105, 85, 95, 57, 59, 26, 25, 2, 94, 2, 68,253, 96, 48,112, 38, 33, 48, 41, 30, 30, 32, 57, 14, 57, 65, 93, 2,162,253,
+188,238, 92,108, 51, 59, 58, 29, 32, 56, 58,103, 98, 0, 0, 0, 0, 1, 0,129,254,136, 4, 80, 6,249, 0, 23, 0, 26, 64, 5,
+ 12, 13, 6, 1, 0, 47, 60,252, 60, 49, 0, 64, 6, 5,140, 10, 22,140, 17, 47,236, 47,236, 48, 5, 17, 52, 55, 54, 55, 54, 23,
+ 7, 38, 7, 6, 21, 17, 20, 7, 6, 7, 6, 39, 55, 22, 55, 54, 2, 12, 94, 65,145,134,142,106, 92, 78,120, 93, 65,145,134,142,
+106, 92, 78,119, 68, 6, 34,106,100, 69, 7, 6,113,113, 67, 3, 5,146,249,222,106,100, 69, 7, 6,113,113, 67, 3, 5, 0, 0,
+ 0, 2, 0, 63,254,124, 4,145, 7, 5, 0, 23, 0, 47, 0, 0, 5, 17, 52, 55, 54, 51, 50, 23, 7, 38, 7, 6, 21, 3, 20, 7,
+ 6, 35, 34, 39, 55, 22, 55, 54, 37, 19, 52, 55, 54, 51, 50, 23, 7, 38, 7, 6, 21, 17, 20, 7, 6, 35, 34, 39, 55, 22, 55, 54,
+ 2,228, 57, 67,109,106, 90, 67, 67, 58, 53, 1, 57, 67,109,106, 90, 67, 77, 48, 54,254, 80, 1, 57, 67,109,106, 90, 67, 67, 58,
+ 54, 57, 67,109,106, 90, 67, 77, 48, 53, 68, 6, 34, 98, 92,105, 57,127, 38, 10, 9,155,249,222, 98, 92,105, 57,127, 43, 15, 17,
+147, 6, 34, 98, 92,105, 57,127, 38, 10, 9,155,249,222, 98, 92,105, 57,127, 43, 15, 17, 0, 0, 0, 3, 0, 53,254,150, 4,157,
+ 6,235, 0, 23, 0, 47, 0, 71, 0, 0, 5, 17, 52, 55, 54, 55, 54, 23, 7, 38, 35, 34, 21, 17, 20, 7, 6, 7, 6, 39, 55, 22,
+ 51, 50, 37, 17, 52, 55, 54, 55, 54, 23, 7, 38, 35, 34, 21, 17, 20, 7, 6, 7, 6, 39, 55, 22, 51, 50, 37, 17, 52, 55, 54, 55,
+ 54, 23, 7, 38, 35, 34, 21, 17, 20, 7, 6, 7, 6, 39, 55, 22, 51, 50, 3, 82, 49, 45,113, 50, 74, 36, 34, 50, 27, 50, 45,113,
+ 50, 74, 36, 34, 50, 28,254,188, 49, 45,113, 50, 74, 36, 34, 50, 27, 50, 45,113, 50, 74, 36, 34, 50, 28,254,186, 50, 45,113, 50,
+ 74, 36, 34, 50, 28, 49, 45,113, 50, 74, 36, 34, 50, 27,127, 6, 93,109, 83, 74, 2, 1, 29,142, 14, 78,249,163,111, 81, 74, 2,
+ 1, 29,142, 14, 78, 6, 93,109, 83, 74, 2, 1, 29,142, 14, 78,249,163,111, 81, 74, 2, 1, 29,142, 14, 78, 6, 93,109, 83, 74,
+ 2, 1, 29,142, 14, 78,249,163,111, 81, 74, 2, 1, 29,142, 14,255,255, 0, 88, 2, 45, 4,121, 4,132, 16, 38, 7, 95, 0, 0,
+ 16, 7, 7,208, 0, 2, 1, 36, 0, 3, 0, 74, 0,134, 4,135, 4,132, 0, 3, 0, 7, 0, 11, 0, 0, 1, 51, 17, 35, 3, 51,
+ 17, 35, 1, 33, 21, 33, 3,139,252,252, 2,252,252,252,193, 2,234,253, 22, 4,132,254,207,254,100,254,207, 2, 81,170, 0, 0,
+255,255, 0, 87, 0,134, 4,125, 4,132, 16, 38, 7, 95, 0, 0, 16, 39, 7,208, 1,148, 1, 36, 16, 39, 7,208, 1,152,254, 87,
+ 16, 39, 7,208,254,111, 1, 36, 16, 7, 7,208,254,110,254, 87,255,255, 0, 88, 0,134, 4,121, 4,132, 16, 38, 7,117, 0, 0,
+ 16, 39, 7,208, 0, 2, 1, 36, 16, 7, 7,208, 0, 1,254, 87, 0, 1, 0, 88, 1,241, 4,121, 3, 18, 0, 27, 0, 0, 1, 21,
+ 14, 1, 35, 34, 39, 38, 39, 46, 1, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 23, 22, 23, 22, 51, 50, 54, 4,121, 75,143, 79, 90,
+113, 22, 11, 77,103, 51, 79,141, 73, 78,146, 83, 53,100, 75, 10, 22,116, 93, 70,137, 3, 18,175, 59, 55, 51, 10, 4, 34, 24, 59,
+ 64,174, 60, 55, 22, 32, 4, 11, 54, 60, 0, 0, 0, 1, 0, 88, 1,241, 4,121, 3, 18, 0, 27, 0, 0, 19, 30, 1, 51, 50, 55,
+ 54, 55, 62, 1, 51, 50, 22, 23, 21, 46, 1, 35, 34, 6, 7, 6, 7, 6, 35, 34, 38, 39, 88, 74,137, 70, 93,116, 22, 10, 75,100,
+ 53, 83,146, 78, 73,141, 79, 51,103, 77, 11, 22,113, 90, 79,143, 75, 3, 18, 63, 60, 54, 11, 4, 32, 22, 55, 60,174, 64, 59, 24,
+ 34, 4, 10, 51, 55, 59, 0, 0, 0, 1, 0, 88, 0,174, 4,121, 4, 71, 0, 31, 0, 0, 1, 38, 39, 38, 35, 34, 6, 7, 53, 62,
+ 1, 51, 50, 23, 22, 23, 19, 23, 3, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 39, 3, 39, 2, 24, 29, 23, 52, 51, 79,141, 73, 78,
+146, 83, 54, 49, 45, 29, 78,136, 83, 88, 73, 70,137, 74, 75,143, 79, 81,100, 83,136, 2, 80, 11, 5, 12, 59, 64,174, 60, 55, 11,
+ 11, 12, 1, 87, 31,254,145, 34, 60, 63,175, 59, 55, 41,254,148, 31, 0, 0, 0, 0, 2, 0, 88, 1, 49, 4,121, 3,162, 0, 3,
+ 0, 29, 0, 0, 19, 33, 21, 33, 5, 21, 14, 1, 35, 34, 47, 1, 46, 1, 35, 34, 6, 7, 53, 62, 1, 51, 50, 23, 51, 23, 22, 51,
+ 50, 54, 88, 4, 33,251,223, 4, 33, 75,143, 79, 90,113, 33, 83, 99, 49, 78,141, 74, 79,146, 82, 96,130, 1, 33,116, 93, 68,138,
+ 3,162,170,164,176, 59, 56, 51, 15, 36, 23, 60, 65,174, 62, 55, 55, 15, 55, 61, 0, 2, 0, 88, 1, 96, 4,121, 3,195, 0, 3,
+ 0, 31, 0, 0, 19, 33, 21, 33, 1, 21, 14, 1, 35, 34, 39, 38, 39, 46, 1, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 23, 22, 23,
+ 22, 51, 50, 54, 88, 4, 33,251,223, 4, 33, 75,143, 79, 90,113, 22, 11, 77,103, 51, 79,141, 73, 78,146, 83, 53,100, 75, 10, 22,
+116, 93, 70,137, 2, 12,172, 2, 99,175, 59, 55, 51, 10, 4, 34, 24, 59, 64,174, 60, 55, 22, 32, 4, 11, 54, 60, 0, 1, 0, 88,
+ 0, 98, 4,122, 4,213, 0, 39, 0, 0, 1, 3, 22, 55, 54, 55, 21, 6, 7, 6, 35, 34, 39, 7, 33, 21, 33, 7, 39, 55, 35, 53,
+ 33, 55, 38, 39, 38, 7, 6, 7, 53, 54, 55, 54, 55, 54, 31, 2, 19, 3,199,167,102, 89, 85, 69, 53,107, 73, 81, 37, 92,110, 2,
+ 42,253,120,152,114, 89,233, 1, 81,146, 77,111, 73, 70, 92, 60, 91, 69, 84, 70, 82,130, 13, 29,198, 4,113,254,224, 19, 36, 34,
+ 66,178, 50, 40, 26, 30,178,171,254,100,154,171,231, 37, 5, 4, 31, 40, 57,172, 76, 19, 22, 2, 3, 53, 5, 16, 1, 88, 0, 0,
+ 0, 3, 0, 88, 0,192, 4,121, 4,143, 0, 3, 0, 7, 0, 36, 0, 0, 19, 33, 21, 33, 21, 33, 21, 33, 1, 21, 14, 1, 35, 34,
+ 39, 38, 39, 46, 1, 35, 34, 6, 7, 53, 62, 1, 51, 50, 23, 22, 23, 22, 23, 22, 51, 50, 54, 88, 4, 33,251,223, 4, 33,251,223,
+ 4, 33, 75,143, 79, 90,113, 22, 11, 77,103, 51, 79,141, 73, 78,146, 83, 53, 50, 39, 86, 10, 22,116, 93, 70,137, 2,216,172,192,
+172, 3,207,175, 59, 55, 51, 10, 4, 34, 24, 59, 64,174, 60, 55, 11, 9, 34, 4, 11, 54, 60, 0, 0, 2, 0, 88, 0, 49, 4,121,
+ 4,143, 0, 19, 0, 48, 0, 0, 37, 35, 53, 33, 55, 33, 53, 33, 55, 23, 7, 51, 21, 33, 7, 33, 21, 33, 7, 39, 1, 21, 14, 1,
+ 35, 34, 39, 38, 39, 46, 1, 35, 34, 6, 7, 53, 62, 1, 51, 50, 23, 22, 23, 22, 23, 22, 51, 50, 54, 1, 81,249, 1,117,139,254,
+ 0, 2,123,104,113, 44,249,254,139,139, 2, 0,253,132,103,113, 3, 84, 75,143, 79, 90,113, 22, 11, 77,103, 51, 79,141, 73, 78,
+146, 83, 53, 50, 39, 86, 10, 22,116, 93, 70,137,192,172,192,172,143, 82, 61,172,192,172,143, 82, 4, 12,175, 59, 55, 51, 10, 4,
+ 34, 24, 59, 64,174, 60, 55, 11, 9, 34, 4, 11, 54, 60, 0, 0, 0, 1, 0, 88, 0, 0, 4,121, 5, 46, 0, 49, 0, 0, 37, 33,
+ 53, 33, 55, 33, 53, 33, 55, 38, 39, 46, 1, 35, 34, 6, 7, 53, 62, 1, 51, 50, 23, 22, 31, 1, 55, 23, 7, 22, 51, 50, 54, 55,
+ 21, 14, 1, 35, 34, 39, 7, 33, 21, 33, 7, 33, 21, 33, 7, 39, 1,104,254,240, 1, 77, 69,254,110, 1,208, 75, 9, 6, 77,103,
+ 51, 79,141, 73, 78,146, 83, 53, 50, 51, 74, 58, 86,155, 81, 11, 12, 70,137, 74, 75,143, 79, 31, 33, 56, 1,161,254, 33, 69, 2,
+ 36,253,159, 70,156,192,172,192,172,209, 4, 2, 34, 24, 59, 64,174, 60, 55, 11, 11, 32, 25,238, 56,225, 1, 60, 63,175, 59, 55,
+ 6,156,172,192,172,192, 55, 0, 0, 2, 0, 88, 1, 49, 4,121, 3,195, 0, 27, 0, 55, 0, 75, 64, 38, 29, 39, 32, 49, 48, 43,
+ 3, 53, 28, 1, 11, 4, 15, 25, 11,160, 18, 0, 25,160, 14, 4, 42, 32,160, 53, 39,160, 46, 28, 56, 49, 48, 28, 0, 42, 14, 56,
+ 16,212, 60,196, 50, 57, 57, 49, 0, 16,212, 60,236,212,236, 50,220, 60,252,212, 60,236, 18, 57, 17, 18, 57, 17, 18, 23, 57, 17,
+ 18, 57, 48, 1, 21, 14, 1, 35, 34, 39, 38, 39, 46, 1, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 23, 22, 23, 22, 51, 50, 54, 19,
+ 21, 14, 1, 35, 34, 39, 38, 39, 46, 1, 35, 34, 6, 7, 53, 62, 1, 51, 50, 23, 51, 22, 23, 22, 51, 50, 54, 4,121, 75,143, 79,
+ 90,113, 22, 11, 77,103, 51, 79,141, 73, 78,146, 83, 53,100, 75, 10, 22,116, 93, 70,137, 74, 75,143, 79, 90,113, 22, 11, 83, 99,
+ 49, 78,141, 74, 79,146, 82, 96,130, 1, 11, 22,116, 93, 68,138, 3,195,175, 59, 55, 51, 10, 4, 34, 24, 59, 64,174, 60, 55, 22,
+ 32, 4, 11, 54, 60,254,208,176, 59, 56, 51, 10, 5, 36, 23, 60, 65,174, 62, 55, 55, 5, 10, 55, 61, 0, 0, 0, 0, 1, 0, 88,
+ 0, 48, 4,121, 4,195, 0, 56, 0, 0, 1, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 23, 55, 38, 39, 38, 35, 34, 6, 7, 53, 62,
+ 1, 51, 50, 23, 22, 23, 19, 23, 3, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 39, 7, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 47,
+ 1, 3, 39, 1,221, 48, 48, 78,141, 74, 79,146, 82, 58, 71, 54, 55, 39, 52, 51, 79,141, 73, 78,146, 83, 53, 50, 48, 78, 93,138,
+ 97, 57, 49, 70,137, 74, 75,143, 79, 63, 74, 52,114, 91, 68,138, 75, 75,143, 79,100,103, 31, 98,138, 1,163, 11, 60, 65,174, 62,
+ 55, 20,178, 22, 9, 12, 59, 64,174, 60, 55, 11, 11, 33, 1, 55, 41,254,189, 15, 60, 63,175, 59, 55, 25,175, 53, 61, 64,176, 59,
+ 56, 51, 16,254,188, 41, 0, 0, 0, 3, 0, 88, 0,192, 4,121, 4,147, 0, 27, 0, 55, 0, 59, 0, 0, 1, 21, 14, 1, 35, 34,
+ 39, 38, 39, 46, 1, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 23, 22, 23, 22, 51, 50, 54, 19, 21, 14, 1, 35, 34, 39, 38, 39, 46,
+ 1, 35, 34, 6, 7, 53, 62, 1, 51, 50, 23, 51, 22, 23, 22, 51, 50, 54, 1, 33, 21, 33, 4,121, 75,143, 79, 90,113, 22, 11, 77,
+103, 51, 79,141, 73, 78,146, 83, 53,100, 75, 10, 22,116, 93, 70,137, 74, 75,143, 79, 90,113, 22, 11, 83, 99, 49, 78,141, 74, 79,
+146, 82, 96,130, 1, 11, 22,116, 93, 68,138,252, 42, 4, 33,251,223, 4,147,175, 59, 55, 51, 10, 4, 34, 24, 59, 64,174, 60, 55,
+ 22, 32, 4, 11, 54, 60,254,208,176, 59, 56, 51, 10, 5, 36, 23, 60, 65,174, 62, 55, 55, 5, 10, 55, 61,254,136,172, 0, 0, 0,
+ 0, 3, 0, 88, 0,149, 4,121, 4,147, 0, 27, 0, 55, 0, 83, 0, 0, 1, 21, 14, 1, 35, 34, 39, 38, 39, 46, 1, 35, 34, 6,
+ 7, 53, 62, 1, 51, 50, 23, 51, 22, 23, 22, 51, 50, 54, 19, 21, 14, 1, 35, 34, 39, 38, 39, 46, 1, 35, 34, 6, 7, 53, 62, 1,
+ 51, 50, 22, 23, 22, 23, 22, 51, 50, 54, 19, 21, 14, 1, 35, 34, 39, 38, 39, 46, 1, 35, 34, 6, 7, 53, 62, 1, 51, 50, 23, 51,
+ 22, 23, 22, 51, 50, 54, 4,121, 75,143, 79, 90,113, 22, 11, 83, 99, 49, 78,141, 74, 79,146, 82, 96,130, 1, 11, 22,116, 93, 68,
+138, 75, 75,143, 79, 90,113, 22, 11, 77,103, 51, 79,141, 73, 78,146, 83, 53,100, 75, 10, 22,116, 93, 70,137, 74, 75,143, 79, 90,
+113, 22, 11, 83, 99, 49, 78,141, 74, 79,146, 82, 96,130, 1, 11, 22,116, 93, 68,138, 1,184,176, 59, 56, 51, 10, 5, 36, 23, 60,
+ 65,174, 62, 55, 55, 5, 10, 55, 61, 3, 27,175, 59, 55, 51, 10, 4, 34, 24, 59, 64,174, 60, 55, 22, 32, 4, 11, 54, 60,254,208,
+176, 59, 56, 51, 10, 5, 36, 23, 60, 65,174, 62, 55, 55, 5, 10, 55, 61, 0, 0, 0, 3, 0, 88, 0,192, 4,121, 4,143, 0, 3,
+ 0, 7, 0, 36, 0, 0, 1, 21, 33, 53, 1, 21, 33, 53, 17, 30, 1, 51, 50, 55, 54, 55, 54, 55, 54, 51, 50, 22, 23, 21, 46, 1,
+ 35, 34, 6, 7, 6, 7, 6, 35, 34, 38, 39, 4,121,251,223, 4, 33,251,223, 74,137, 70, 93,116, 22, 10, 86, 39, 50, 53, 83,146,
+ 78, 73,141, 79, 51,103, 77, 11, 22,113, 90, 79,143, 75, 2,216,172,172,254,148,172,172, 3, 35, 63, 60, 54, 11, 4, 34, 9, 11,
+ 55, 60,174, 64, 59, 24, 34, 4, 10, 51, 55, 59, 0, 2, 0, 87, 0,221, 4,121, 4, 39, 0, 8, 0, 17, 0, 0, 0, 32, 37, 53,
+ 4, 23, 50, 37, 21, 0, 32, 5, 21, 36, 39, 34, 5, 53, 3, 49,254,112,254,182, 1, 90,184,185, 1, 86,253, 40, 1,144, 1, 73,
+254,167,184,185,254,169, 2,217,156,178,156, 7,163,178,254,182,156,178,156, 7,163,178, 0, 0, 0, 2, 0, 88, 0, 68, 4,122,
+ 4,190, 0, 29, 0, 59, 0, 0, 37, 22, 55, 54, 55, 54, 55, 33, 21, 35, 6, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 39, 35, 53,
+ 33, 22, 23, 22, 23, 22, 19, 6, 7, 6, 7, 6, 7, 33, 53, 51, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 51, 21, 33, 38,
+ 39, 38, 39, 38, 2,105, 49, 42, 43, 27, 21, 4, 1, 86,225, 9, 25, 27, 87, 74, 82, 78, 77, 82, 32, 25, 9,225, 1, 87, 4, 21,
+ 26, 44, 33, 58, 58, 33, 44, 26, 21, 4,254,169,225, 6, 28, 22, 92, 72, 83, 76, 80, 77, 37, 23, 11,225,254,170, 3, 22, 27, 43,
+ 42,223, 3, 37, 39, 72, 58, 94,168, 50, 58, 65, 60, 51, 51, 54, 71, 56, 52,168, 94, 58, 72, 39, 30, 3, 64, 4, 30, 39, 72, 63,
+ 89,168, 32, 76, 61, 64, 51, 51, 47, 78, 48, 60,168, 94, 58, 72, 39, 37, 0, 0, 0, 2, 0, 88, 1, 96, 4,122, 4,190, 0, 29,
+ 0, 33, 0, 0, 1, 6, 7, 6, 7, 6, 7, 33, 53, 51, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 51, 21, 33, 38, 39, 38,
+ 39, 38, 1, 33, 21, 33, 2,105, 58, 33, 44, 26, 21, 4,254,169,225, 6, 28, 22, 92, 72, 83, 76, 80, 77, 37, 23, 11,225,254,170,
+ 3, 22, 27, 43, 42,253,190, 4, 33,251,223, 4, 35, 4, 30, 39, 72, 63, 89,168, 32, 76, 61, 64, 51, 51, 47, 78, 48, 60,168, 94,
+ 58, 72, 39, 37,253,228,170, 0,255,255, 0, 88, 1, 96, 4,121, 5, 25, 16, 38, 0, 32, 0, 0, 16, 7, 7,208, 0, 2, 1,185,
+255,255, 0, 88,255,233, 4,121, 5, 25, 16, 38, 0, 32, 0, 0, 16, 39, 7,208, 0, 2, 1,185, 16, 39, 7,208, 0, 2, 1,185,
+ 16, 7, 7,208, 0, 1,253,186,255,255, 0, 88,255,236, 4,121, 5, 25, 16, 39, 7,208, 1,148,253,189, 16, 38, 0, 32, 0, 0,
+ 16, 7, 7,208,254,111, 1,185,255,255, 0, 87,255,236, 4,122, 5, 25, 16, 39, 7,208, 1,148, 1,185, 16, 38, 0, 32, 0, 0,
+ 16, 7, 7,208,254,110,253,189, 0, 4, 0, 74, 1, 46, 4,135, 3,213, 0, 3, 0, 7, 0, 11, 0, 15, 0, 0, 19, 51, 17, 35,
+ 17, 51, 17, 35, 5, 21, 33, 53, 1, 21, 33, 53, 74,236,236,236,236, 4, 61,252,251, 3, 5,252,251, 2, 62,254,240, 2,167,254,
+240,185,172,172, 1,150,170,170, 0, 4, 0, 74, 1, 46, 4,135, 3,213, 0, 3, 0, 7, 0, 11, 0, 15, 0, 0, 1, 17, 35, 17,
+ 19, 17, 35, 17, 1, 33, 21, 33, 17, 33, 21, 33, 4,135,236,236,236,252,175, 3, 5,252,251, 3, 5,252,251, 2, 62,254,240, 1,
+ 16, 1,151,254,240, 1, 16,254, 55,172, 2, 66,170, 0, 0, 0, 0, 2, 0, 88, 1, 96, 4,121, 3,162, 0, 9, 0, 27, 0, 0,
+ 1, 6, 21, 20, 23, 51, 54, 53, 38, 39, 23, 33, 21, 33, 53, 33, 38, 53, 52, 55, 33, 53, 33, 21, 33, 22, 21, 20, 2, 37, 52, 51,
+145, 52, 1, 52,141, 1, 56,251,223, 1, 62, 25, 27,254,192, 4, 33,254,201, 26, 2,250, 48, 73, 71, 48, 48, 71, 71, 50,240,170,
+170, 63, 56, 62, 59,168,168, 26, 95, 56, 0, 0, 0, 4, 0, 88, 1, 96, 4,121, 6, 21, 0, 3, 0, 7, 0, 17, 0, 32, 0, 0,
+ 19, 33, 21, 33, 17, 33, 21, 33, 1, 34, 6, 21, 20, 22, 50, 54, 52, 38, 39, 50, 22, 23, 30, 1, 21, 20, 6, 35, 34, 38, 53, 52,
+ 54, 88, 4, 33,251,223, 4, 33,251,223, 2, 17, 73,100,100,146,100,101, 72, 58,108, 39, 42, 42,169,122,123,164,168, 2, 12,172,
+ 2, 66,170, 2,172, 98, 70, 69, 96, 96,139, 98,113, 43, 40, 40,100, 58,115,161,158,118,118,163, 0, 3, 0, 88, 1, 96, 4,121,
+ 5, 75, 0, 3, 0, 7, 0, 17, 0, 0, 19, 33, 21, 33, 17, 33, 21, 33, 1, 50, 23, 21, 38, 39, 6, 7, 53, 54, 88, 4, 33,251,
+223, 4, 33,251,223, 2, 18,230,203,215,218,216,220,210, 2, 12,172, 2, 66,170, 2, 83,151,178,151, 9, 2,158,178,151, 0, 0,
+ 0, 3, 0, 88, 1, 96, 4,121, 6, 68, 0, 3, 0, 7, 0, 14, 0, 0, 19, 33, 21, 33, 17, 33, 21, 33, 55, 19, 51, 19, 35, 11,
+ 1, 88, 4, 33,251,223, 4, 33,251,223,214,234,162,233,143,171,166, 2, 12,172, 2, 66,170,242, 2, 90,253,166, 1,170,254, 86,
+ 0, 3, 0, 88, 1, 96, 4,121, 6, 68, 0, 3, 0, 7, 0, 14, 0, 0, 19, 33, 21, 33, 17, 33, 21, 33, 19, 51, 27, 1, 51, 3,
+ 35, 88, 4, 33,251,223, 4, 33,251,223,214,149,166,171,143,233,162, 2, 12,172, 2, 66,170, 3, 76,254, 86, 1,170,253,166, 0,
+ 0, 3, 0, 88, 1, 96, 4,121, 6,165, 0, 3, 0, 7, 0, 17, 0, 0, 19, 33, 21, 33, 17, 33, 21, 33, 19, 33, 27, 1, 33, 7,
+ 19, 39, 7, 19, 88, 4, 33,251,223, 4, 33,251,223,176, 1, 13, 84, 85, 1, 12,218, 85,220,219, 84, 2, 12,172, 2, 66,170, 2,
+173, 1, 0,255, 0,158,255, 0,159,159, 1, 0, 0, 4, 0, 88, 1, 96, 4,121, 6,176, 0, 3, 0, 7, 0, 10, 0, 14, 0, 0,
+ 19, 33, 21, 33, 17, 33, 21, 33, 1, 3, 33, 3, 51, 1, 33, 88, 4, 33,251,223, 4, 33,251,223, 2, 16,150, 1, 45,201,101, 1,
+ 4,253,147, 2, 12,172, 2, 66,170, 3, 21,254,122, 2, 40,253,105, 0, 0, 0, 0, 7, 0, 69, 1, 96, 4,140, 6, 29, 0, 3,
+ 0, 7, 0, 27, 0, 48, 0, 55, 0, 71, 0, 79, 0, 0, 19, 33, 21, 33, 17, 33, 21, 33, 1, 21, 35, 34, 6, 29, 1, 51, 21, 35,
+ 17, 35, 17, 35, 53, 51, 53, 52, 54, 51, 3, 21, 33, 30, 1, 51, 50, 54, 55, 21, 14, 1, 35, 34, 38, 53, 52, 54, 51, 50, 22, 7,
+ 46, 1, 35, 34, 6, 7, 39, 53, 51, 17, 35, 53, 14, 1, 35, 34, 38, 52, 54, 51, 50, 22, 6, 20, 22, 50, 54, 52, 38, 34, 88, 4,
+ 33,251,223, 4, 33,251,223, 4, 52, 64, 35, 28,109,109, 67, 63, 63, 63, 68,237,254,208, 4, 74, 66, 38, 71, 36, 36, 75, 38, 97,
+113,107, 91, 81, 95, 66, 1, 59, 49, 56, 66, 5,199, 67, 67, 21, 63, 45, 73, 92, 92, 73, 45, 63,204, 60,105, 60, 60,105, 2, 12,
+172, 2, 66,170, 3, 36, 55, 29, 37, 36, 51,254,160, 1, 96, 51, 28, 68, 61,254,170, 32, 68, 72, 19, 18, 62, 15, 16,112, 96, 99,
+116,105, 70, 54, 65, 63, 57,105,218,253,208, 61, 36, 35,116,190,117, 35,103,147, 83, 83,147, 83, 0, 3, 0, 88, 1, 96, 4,121,
+ 6, 20, 0, 3, 0, 7, 0, 42, 0, 0, 19, 33, 21, 33, 17, 33, 21, 33, 1, 62, 1, 51, 50, 22, 21, 17, 35, 17, 52, 38, 35, 34,
+ 6, 21, 17, 35, 17, 52, 38, 35, 34, 6, 21, 17, 35, 17, 51, 21, 62, 1, 51, 50, 22, 88, 4, 33,251,223, 4, 33,251,223, 2, 46,
+ 34, 93, 63, 84, 92, 89, 56, 56, 69, 81, 89, 55, 58, 68, 81, 89, 89, 31, 85, 59, 59, 82, 2, 12,172, 2, 66,170, 2,165, 61, 58,
+120,111,254,181, 1, 72, 79, 77, 93, 81,254,202, 1, 72, 80, 76, 94, 80,254,202, 2, 37, 85, 50, 48, 61, 0, 0, 0, 4, 0, 88,
+ 1, 96, 4,121, 6,218, 0, 3, 0, 7, 0, 11, 0, 44, 0, 0, 19, 33, 21, 33, 17, 33, 21, 33, 1, 51, 21, 35, 55, 35, 53, 52,
+ 54, 63, 1, 62, 1, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 21, 20, 6, 15, 1, 14, 1, 7, 14, 1, 21, 88, 4, 33,
+251,223, 4, 33,251,223, 1,195,102,102, 99, 96, 28, 45, 45, 29, 25, 65, 54, 40, 89, 49, 47, 97, 51, 92,112, 36, 45, 44, 24, 19,
+ 4, 3, 3, 2, 12,172, 2, 66,170, 1,105,127,200, 78, 50, 65, 43, 44, 27, 47, 24, 45, 55, 35, 33, 94, 28, 28, 97, 79, 38, 69,
+ 43, 43, 23, 27, 13, 10, 30, 26, 0, 1, 0, 88, 0, 37, 4,121, 4,221, 0, 19, 0, 60, 64, 32, 13, 12, 10, 3, 2, 4, 0,160,
+ 6, 12, 14, 10,160, 18, 6, 16, 8, 20, 18, 14, 13, 12, 8, 4, 3, 2, 8, 9, 5, 15, 0, 20, 16,212, 60,196, 50, 23, 57, 49,
+ 0, 16,212, 60,196, 50,252, 60,196, 16,254, 60,196, 57, 17, 18, 57, 48, 19, 33, 19, 23, 7, 51, 21, 33, 7, 33, 21, 33, 3, 39,
+ 55, 35, 53, 33, 55, 33, 88, 2,135,246,125,164,203,254,178,184, 2, 6,253,121,248,125,164,201, 1, 74,184,253,254, 3,162, 1,
+ 59,102,213,170,236,172,254,197,104,211,172,236, 0, 3, 0, 88, 0,192, 4,121, 4, 66, 0, 3, 0, 7, 0, 11, 0, 0, 19, 33,
+ 21, 33, 21, 33, 21, 33, 17, 33, 21, 33, 88, 4, 33,251,223, 4, 33,251,223, 4, 33,251,223, 2,216,172,192,172, 3,130,170, 0,
+ 0, 1, 0, 88, 0, 10, 4,121, 4,250, 0, 27, 0, 0, 37, 35, 53, 33, 55, 33, 53, 33, 55, 33, 53, 33, 55, 23, 7, 51, 21, 33,
+ 7, 33, 21, 33, 7, 33, 21, 33, 7, 39, 1, 71,239, 1, 61, 88,254,107, 1,229, 88,253,195, 2,139, 85,141, 55,235,254,200, 89,
+ 1,145,254, 32, 90, 2, 58,253,119, 83,141,192,172,192,172,192,170,184, 65,119,170,192,172,192,172,182, 64, 0, 0, 4, 0, 88,
+ 0, 0, 4,121, 4,238, 0, 3, 0, 7, 0, 11, 0, 15, 0, 0, 55, 33, 21, 33, 17, 33, 21, 33, 21, 33, 21, 33, 17, 33, 21, 33,
+ 88, 4, 33,251,223, 4, 33,251,223, 4, 33,251,223, 4, 33,251,223,172,172, 3,132,172,192,172, 3,130,170, 0, 0, 2, 0, 88,
+ 0, 0, 4,121, 4, 63, 0, 6, 0, 10, 0, 40, 64, 22, 6, 5, 3, 2, 0, 5, 1,229, 4,228, 7,160, 8, 6, 7, 4, 0, 40,
+ 9, 2, 39, 11, 16,252, 60,236, 50, 50, 57, 49, 0, 47,236,244,236, 23, 57, 48, 1, 21, 1, 53, 1, 21, 5, 1, 21, 33, 53, 4,
+121,251,223, 4, 33,252,223, 3, 33,251,223, 1,182,182, 1, 76,168, 1, 75,184,231,254, 10,170,170, 0, 0, 0, 0, 2, 0, 88,
+ 0, 0, 4,121, 4, 63, 0, 6, 0, 10, 0, 40, 64, 22, 5, 4, 2, 1, 0, 5, 6,229, 3,228, 7,160, 9, 1, 8, 4, 40, 7,
+ 2, 0, 39, 11, 16,252, 60, 60,236, 50, 57, 49, 0, 47,236,244,236, 23, 57, 48, 19, 45, 1, 53, 1, 21, 1, 21, 33, 21, 33, 88,
+ 3, 35,252,221, 4, 33,251,223, 4, 33,251,223, 1,182,234,231,184,254,181,168,254,180, 86,170, 0, 3, 0, 86,255, 84, 4,119,
+ 4,159, 0, 3, 0, 10, 0, 14, 0, 0, 51, 33, 21, 33, 1, 21, 1, 53, 1, 21, 5, 1, 21, 33, 53, 86, 4, 33,251,223, 4, 33,
+251,223, 4, 33,252,223, 3, 33,251,223,172, 2,194,182, 1, 76,168, 1, 75,184,231,254, 10,170,170, 0, 0, 0, 0, 3, 0, 86,
+255, 84, 4,119, 4,159, 0, 3, 0, 10, 0, 14, 0, 0, 51, 33, 21, 33, 17, 45, 1, 53, 1, 21, 1, 5, 21, 33, 53, 86, 4, 33,
+251,223, 3, 33,252,223, 4, 33,251,223, 4, 33,251,223,172, 2,194,234,231,184,254,181,168,254,180, 86,170,170, 0, 2, 0, 86,
+254,181, 4,119, 4,159, 0, 19, 0, 26, 0, 0, 5, 35, 53, 33, 55, 33, 53, 33, 55, 23, 7, 51, 21, 33, 7, 33, 21, 33, 7, 39,
+ 1, 21, 1, 53, 1, 21, 5, 1, 32,202, 1,112, 91,254, 53, 2,109,154,123, 42,201,254,149, 91, 1,198,253,148,153,121, 3,126,
+251,223, 4, 33,252,223,172,172, 96,170,161,117, 44,170, 96,172,159,118, 2,235,182, 1, 76,168, 1, 75,184,231, 0, 2, 0, 86,
+254,181, 4,119, 4,159, 0, 19, 0, 26, 0, 0, 5, 35, 53, 33, 55, 33, 53, 33, 55, 23, 7, 51, 21, 33, 7, 33, 21, 33, 7, 39,
+ 3, 45, 1, 53, 1, 21, 1, 1, 32,202, 1,112, 91,254, 53, 2,109,154,123, 42,201,254,149, 91, 1,198,253,148,153,121,163, 3,
+ 33,252,223, 4, 33,251,223,172,172, 96,170,161,117, 44,170, 96,172,159,118, 2,235,234,231,184,254,181,168,254,180, 0, 0, 0,
+ 0, 1, 0, 87, 0, 0, 4,121, 5, 4, 0, 27, 0, 0, 1, 38, 37, 53, 4, 55, 19, 23, 3, 54, 55, 21, 6, 15, 1, 22, 5, 21,
+ 36, 7, 3, 39, 19, 6, 7, 53, 54, 55, 2, 52,189,254,224, 1, 91,216,194,154,130,122,154,216,162, 98,190, 1, 31,254,165,216,
+193,154,129,124,152,219,160, 2,219, 18,136,178,170, 8, 1,127, 77,254,254, 41, 73,178,103, 35,194, 18,136,178,170, 8,254,129,
+ 77, 1, 2, 40, 74,178,104, 35, 0, 2, 0, 88,255,227, 4,121, 5, 32, 0, 15, 0, 18, 0, 0, 1, 37, 53, 37, 19, 23, 7, 37,
+ 21, 5, 3, 5, 21, 37, 3, 39, 19, 5, 23, 1,225,254,119, 2, 50,114,153, 75, 1, 47,254,146,100, 1,210,253,254,116,153,228,
+254,217,233, 1,148,155,166,222, 1,109, 48,241,120,182,138,254,187,174,183,203,254,139, 48, 2,221,111, 86, 0, 0, 2, 0, 88,
+255,227, 4,121, 5, 32, 0, 15, 0, 18, 0, 0, 1, 5, 21, 5, 3, 39, 55, 5, 53, 37, 19, 37, 53, 5, 19, 23, 3, 37, 39, 2,
+240, 1,137,253,206,114,153, 75,254,209, 1,110,100,254, 46, 2, 2,116,153,228, 1, 39,233, 3,111,155,166,222,254,147, 48,241,
+120,182,138, 1, 69,174,183,203, 1,117, 48,253, 35,111, 86, 0, 0, 2, 0, 88,255, 13, 4,121, 5, 8, 0, 2, 0, 26, 0, 0,
+ 1, 5, 23, 3, 33, 53, 33, 19, 37, 53, 37, 19, 23, 7, 37, 21, 5, 7, 5, 21, 37, 7, 33, 21, 33, 7, 39, 2, 88,255, 0,211,
+199,254,244, 1, 67, 95,254, 94, 2, 63,115,161, 77, 1, 27,254,164, 78, 1,170,254, 35, 78, 2, 43,253,158, 80,162, 2,234, 74,
+ 62,253,158,170, 1, 31,131,168,180, 1, 96, 53,237, 89,184,100,241,124,182,150,236,170,243, 53, 0, 2, 0, 88,255, 13, 4,121,
+ 5, 8, 0, 23, 0, 26, 0, 0, 1, 5, 21, 5, 7, 33, 21, 33, 7, 39, 55, 35, 53, 51, 55, 5, 53, 37, 55, 37, 53, 5, 19, 23,
+ 3, 55, 39, 2,224, 1,153,253,203, 78, 2,131,253, 69, 79,162, 62,179,235, 58,254,219, 1,102, 76,254, 78, 1,230,116,161,208,
+248,206, 3,116,128,168,177,241,170,243, 53,190,170,178, 92,182,104,236,125,184,152, 1, 97, 53,253,133, 72, 60, 0, 2, 0, 86,
+255,212, 4,119, 4, 63, 0, 28, 0, 35, 0, 0, 37, 21, 14, 1, 35, 34, 39, 38, 39, 46, 1, 35, 34, 6, 7, 53, 62, 1, 51, 50,
+ 23, 22, 23, 22, 23, 22, 51, 50, 54, 19, 21, 1, 53, 1, 21, 5, 4,119, 75,143, 79, 90,113, 22, 11, 77,103, 51, 79,141, 73, 78,
+146, 83, 53, 50, 39, 86, 10, 22,116, 93, 70,137, 74,251,223, 4, 33,252,223,245,175, 59, 55, 51, 10, 4, 34, 24, 59, 64,174, 60,
+ 55, 11, 9, 34, 4, 11, 54, 60, 1, 0,182, 1, 76,168, 1, 75,184,231, 0, 0, 0, 2, 0, 86,255,212, 4,119, 4, 63, 0, 33,
+ 0, 40, 0, 0, 37, 21, 6, 7, 6, 35, 34, 39, 38, 39, 38, 39, 38, 35, 34, 7, 6, 7, 53, 54, 55, 54, 51, 50, 23, 22, 23, 22,
+ 23, 22, 51, 50, 55, 54, 1, 45, 1, 53, 1, 21, 1, 4,119, 75, 72, 71, 79, 90,113, 22, 11, 77, 51, 52, 51, 79, 70, 71, 73, 78,
+ 73, 73, 83, 53, 50, 39, 86, 10, 22,116, 93, 70, 68, 69,252, 41, 3, 33,252,223, 4, 33,251,223,245,175, 59, 27, 28, 51, 10, 4,
+ 34, 12, 12, 29, 30, 64,174, 60, 28, 27, 11, 9, 34, 4, 11, 54, 30, 30, 1, 0,234,231,184,254,181,168,254,180, 0, 2, 0, 86,
+255, 13, 4,119, 5, 8, 0, 43, 0, 46, 0, 0, 37, 34, 6, 7, 53, 62, 1, 51, 50, 23, 55, 37, 53, 37, 19, 23, 7, 37, 21, 5,
+ 7, 5, 21, 37, 7, 22, 23, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 39, 38, 39, 38, 39, 3, 39, 1, 5, 23, 1,125, 81,141, 73,
+ 78,146, 83, 21, 21, 69,254, 94, 2, 65,115,161, 77, 1, 25,254,167, 80, 1,169,254, 35, 66, 24, 29,116, 93, 70,137, 74, 75,143,
+ 79, 90,113, 22, 11, 32, 28, 95,162, 1, 52,254,253,213, 79, 59, 64,174, 60, 55, 2,214,131,168,181, 1, 95, 53,236, 88,184, 99,
+242,124,182,150,207, 8, 15, 54, 60, 63,175, 59, 55, 51, 10, 4, 14, 11,254,223, 53, 3,169, 75, 62, 0, 0, 0, 0, 2, 0, 86,
+255, 13, 4,119, 5, 8, 0, 2, 0, 50, 0, 0, 1, 55, 39, 55, 5, 21, 5, 7, 22, 23, 22, 23, 22, 51, 50, 55, 54, 55, 21, 6,
+ 7, 6, 35, 34, 39, 38, 39, 38, 39, 3, 39, 19, 6, 7, 6, 7, 53, 54, 55, 54, 63, 1, 5, 53, 37, 55, 37, 53, 5, 19, 23, 2,
+131,244,202, 51, 1,151,253,205, 59, 24, 76, 10, 22,116, 93, 70, 68, 69, 74, 71, 76, 71, 79, 90,113, 22, 11, 80, 60,103,162, 85,
+ 31, 29, 71, 73, 78, 73, 53, 58, 34,254,216, 1,103, 78,254, 75, 1,232,116,161, 2, 89, 71, 59,152,127,168,177,184, 5, 31, 4,
+ 11, 54, 30, 30, 63,175, 56, 30, 28, 51, 10, 4, 36, 13,254,199, 53, 1, 3, 7, 12, 30, 64,174, 60, 28, 20, 5,106, 93,182,105,
+234,126,184,153, 1, 98, 53, 0, 0, 2, 0, 86,255, 74, 4,119, 4,211, 0, 6, 0, 13, 0, 0, 51, 45, 1, 53, 1, 21, 9, 1,
+ 21, 1, 53, 1, 21, 5, 86, 3, 33,252,223, 4, 33,251,223, 4, 33,251,223, 4, 33,252,223,234,231,184,254,181,168,254,180, 3,
+ 0,182, 1, 76,168, 1, 75,184,231, 0, 0, 0, 0, 2, 0, 86,255, 74, 4,119, 4,211, 0, 6, 0, 13, 0, 0, 33, 21, 1, 53,
+ 1, 21, 5, 1, 45, 1, 53, 1, 21, 1, 4,119,251,223, 4, 33,252,223,255, 0, 3, 33,252,223, 4, 33,251,223,182, 1, 76,168,
+ 1, 75,184,231, 1, 96,234,231,184,254,181,168,254,180, 0, 0, 0, 3, 0, 86,254,112, 4,119, 5,177, 0, 2, 0, 30, 0, 33,
+ 0, 0, 1, 5, 31, 1, 5, 21, 37, 7, 5, 21, 5, 3, 39, 55, 7, 53, 37, 19, 37, 53, 5, 55, 37, 53, 37, 19, 23, 7, 55, 21,
+ 5, 3, 37, 39, 2,132,254,210,252,163, 1,130,254, 78, 25, 1,203,253,155,109,162, 76,249, 1, 52, 80,254,124, 1,181, 24,254,
+ 51, 2,104,110,162, 76,245,254,206,250, 1, 44,250, 3,139, 87, 74, 47,113,182,136, 78,144,168,193,254,155, 48,248, 78,182, 90,
+ 1, 7,112,184,137, 79,145,168,193, 1,104, 50,249, 77,184, 88,252,207, 88, 72, 0, 3, 0, 86,254,112, 4,119, 5,177, 0, 27,
+ 0, 30, 0, 33, 0, 0, 1, 23, 3, 5, 21, 5, 7, 37, 21, 5, 7, 5, 21, 37, 3, 39, 19, 37, 53, 37, 55, 5, 53, 37, 55, 37,
+ 53, 5, 1, 55, 7, 1, 7, 55, 3, 44,162,126, 1, 39,254, 98, 29, 1,187,254, 10, 48, 2, 38,253,170,124,162,125,254,214, 1,
+162, 29,254, 65, 1,249, 48,253,215, 2, 89,254,255, 17,105, 1,204, 17,102, 5,177, 50,254,101, 92,168,130, 96,139,184,145,159,
+161,182,188,254,106, 48, 1,152, 94,168,131, 95,140,182,147,158,160,184,188,252,185, 56, 30, 2, 99, 55, 30, 0, 0, 1, 0, 86,
+255,211, 4,119, 5, 47, 0, 10, 0, 0, 1, 0, 5, 4, 1, 21, 0, 37, 53, 36, 1, 4,119,254,185,254, 92, 1,172, 1, 63,254,
+185,253, 38, 2,222, 1, 67, 4, 64,254,152, 87, 97,254,162,239, 1,197,150,166,148, 1,199, 0, 0, 1, 0, 88,255,211, 4,121,
+ 5, 47, 0, 10, 0, 0, 19, 53, 0, 5, 21, 4, 1, 53, 0, 37, 36, 88, 1, 67, 2,222,253, 38,254,185, 1, 63, 1,172,254, 92,
+ 4, 64,239,254, 57,148,166,150,254, 59,239, 1, 94, 97, 87, 0, 0, 2, 0, 86,255, 4, 4,119, 5,177, 0, 9, 0, 24, 0, 0,
+ 37, 38, 37, 53, 4, 23, 4, 23, 21, 38, 19, 0, 5, 4, 1, 21, 38, 37, 38, 37, 53, 36, 55, 36, 55, 2,164,224,254,146, 1,112,
+222, 1, 8,203,177,177,254,221,254,108, 1,148, 1, 35,183,254,228,247,254,169, 1, 97,237, 1, 28,183,155,154, 54,200, 56,131,
+156,220,252,207, 4,239,254,208, 79, 93,254,222,239,201,151,130, 57,166, 61,125,150,203, 0, 0, 0, 2, 0, 86,255, 4, 4,119,
+ 5,177, 0, 9, 0, 24, 0, 0, 37, 4, 7, 53, 54, 37, 54, 37, 21, 4, 1, 53, 22, 5, 22, 5, 21, 4, 7, 4, 7, 53, 0, 37,
+ 36, 2, 41,254,222,177,203, 1, 8,222, 1,112,254,146,253, 77,183, 1, 28,237, 1, 97,254,169,247,254,228,183, 1, 35, 1,148,
+254,108,155,200,207,252,220,156,131, 56,200, 54, 3,141,239,203,150,125, 61,166, 57,130,151,201,239, 1, 34, 93, 79, 0, 0, 0,
+ 0, 2, 0, 86,255,142, 4,119, 5,177, 0, 27, 0, 42, 0, 0, 37, 21, 14, 1, 35, 34, 39, 38, 39, 46, 1, 35, 34, 6, 7, 53,
+ 62, 1, 51, 50, 22, 23, 22, 23, 22, 51, 50, 54, 19, 0, 5, 4, 1, 21, 38, 37, 38, 37, 53, 36, 55, 36, 55, 4,119, 75,143, 79,
+ 90,113, 22, 11, 77,103, 51, 79,141, 73, 78,146, 83, 53,100, 75, 10, 22,116, 93, 70,137, 74,254,221,254,108, 1,148, 1, 35,183,
+254,228,247,254,169, 1, 97,237, 1, 28,183,175,175, 59, 55, 51, 10, 4, 34, 24, 59, 64,174, 60, 55, 22, 32, 4, 11, 54, 60, 4,
+ 82,254,208, 79, 93,254,222,239,201,151,130, 57,166, 61,125,150,203, 0, 0, 0, 0, 2, 0, 86,255,142, 4,119, 5,177, 0, 27,
+ 0, 42, 0, 0, 37, 21, 14, 1, 35, 34, 39, 38, 39, 46, 1, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 23, 22, 23, 22, 51, 50, 54,
+ 1, 53, 22, 5, 22, 5, 21, 4, 7, 4, 7, 53, 0, 37, 36, 4,119, 75,143, 79, 90,113, 22, 11, 77,103, 51, 79,141, 73, 78,146,
+ 83, 53,100, 75, 10, 22,116, 93, 70,137,252, 41,183, 1, 28,237, 1, 97,254,169,247,254,231,186, 1, 35, 1,148,254,108,175,175,
+ 59, 55, 51, 10, 4, 34, 24, 59, 64,174, 60, 55, 22, 32, 4, 11, 54, 60, 4, 82,239,203,150,125, 61,166, 57,130,148,204,239, 1,
+ 34, 93, 79, 0, 0, 2, 0, 86,255, 91, 4,119, 5,167, 0, 21, 0, 26, 0, 0, 1, 23, 3, 54, 55, 21, 6, 7, 3, 22, 23, 21,
+ 38, 37, 3, 39, 19, 38, 39, 53, 36, 55, 3, 55, 6, 7, 22, 3, 52,163,104,155,109,160,181, 85,233,193,178,254,214,160,162,166,
+192,233, 1, 71,246, 99, 32, 95,101, 84, 5,167, 50,254,170,119,153,239,176,110,254,235,119,212,239,247,157,253,244, 50, 2, 34,
+ 79, 48,166, 66,127,254,188,106, 37, 21, 19, 0, 0, 2, 0, 86,255, 91, 4,119, 5,167, 0, 21, 0, 26, 0, 0, 5, 39, 19, 6,
+ 7, 53, 54, 55, 19, 38, 39, 53, 22, 5, 19, 23, 3, 22, 23, 21, 4, 7, 19, 7, 54, 55, 38, 1,153,163,104,155,109,160,181, 85,
+233,193,178, 1, 42,160,162,166,192,233,254,185,246, 99, 32, 95,101, 84,165, 50, 1, 86,119,153,239,176,110, 1, 21,119,212,239,
+247,157, 2, 12, 50,253,222, 79, 48,166, 66,127, 1, 68,106, 37, 21, 19, 0, 0, 0, 1, 0, 88, 0,163, 4,121, 4, 95, 0, 20,
+ 0, 0, 37, 33, 34, 39, 38, 53, 52, 55, 54, 51, 33, 21, 33, 34, 6, 21, 20, 23, 22, 51, 33, 4,121,253,189,201,138,139,139,138,
+200, 2, 68,253,188,137,190, 95, 96,136, 2, 68,163,139,139,200,198,141,139,150,192,136,138, 94, 96, 0, 0, 0, 0, 1, 0, 88,
+ 0,163, 4,121, 4, 95, 0, 20, 0, 0, 55, 53, 33, 50, 55, 54, 53, 52, 38, 35, 33, 53, 33, 50, 23, 22, 21, 20, 7, 6, 35, 88,
+ 2, 68,136, 96, 95,190,137,253,188, 2, 68,200,138,139,139,138,201,163,150, 96, 94,138,136,192,150,139,141,198,200,139,139, 0,
+ 0, 2, 0, 88,255,196, 4,121, 5, 62, 0, 8, 0, 32, 0, 0, 1, 35, 34, 6, 21, 20, 23, 22, 23, 7, 38, 39, 38, 53, 52, 55,
+ 54, 59, 1, 55, 23, 7, 33, 21, 33, 3, 33, 21, 33, 34, 35, 7, 39, 2,127, 74,137,190, 95, 43, 51, 48, 84, 68,139,139,138,200,
+126, 75,161, 57, 1, 19,254,186,221, 2, 35,253,189, 10, 10, 75,162, 3,201,192,136,138, 94, 43, 24,144, 35, 69,139,200,198,141,
+139,223, 53,170,150,253,112,150,223, 53, 0, 0, 0, 2, 0, 88,255,196, 4,121, 5, 62, 0, 8, 0, 32, 0, 0, 1, 51, 50, 54,
+ 53, 52, 39, 38, 39, 55, 22, 23, 22, 21, 20, 7, 6, 43, 1, 7, 39, 55, 33, 53, 33, 19, 33, 53, 33, 50, 51, 55, 23, 2, 82, 74,
+137,190, 95, 43, 51, 48, 84, 68,139,139,138,200,126, 75,161, 57,254,237, 1, 70,221,253,221, 2, 67, 10, 10, 75,162, 1, 57,192,
+136,138, 94, 43, 24,144, 35, 69,139,200,198,141,139,223, 53,170,150, 2,144,150,223, 53, 0, 0, 0, 2, 0, 88, 0, 0, 4,121,
+ 5, 0, 0, 3, 0, 24, 0, 0, 37, 21, 33, 53, 37, 33, 34, 39, 38, 53, 52, 55, 54, 51, 33, 21, 33, 34, 6, 21, 20, 23, 22, 51,
+ 33, 4,121,251,223, 4, 33,253,189,201,138,139,139,138,200, 2, 68,253,188,137,190, 95, 96,136, 2, 68,170,170,170,154,139,139,
+200,198,141,139,150,192,136,138, 94, 96, 0, 0, 0, 2, 0, 88, 0, 0, 4,121, 5, 0, 0, 3, 0, 24, 0, 0, 37, 21, 33, 61,
+ 2, 33, 50, 55, 54, 53, 52, 38, 35, 33, 53, 33, 50, 23, 22, 21, 20, 7, 6, 35, 4,121,251,223, 2, 68,136, 96, 95,190,137,253,
+188, 2, 68,200,138,139,139,138,201,170,170,170,154,150, 96, 94,138,136,192,150,139,141,198,200,139,139, 0, 0, 0, 2, 0, 88,
+255, 44, 4,121, 5,214, 0, 29, 0, 38, 0, 0, 37, 33, 21, 33, 7, 39, 55, 35, 53, 33, 55, 38, 39, 38, 53, 52, 55, 54, 59, 1,
+ 55, 23, 7, 51, 21, 33, 3, 33, 21, 33, 19, 35, 34, 6, 21, 20, 23, 22, 23, 2, 36, 2, 85,253,114, 71,159, 54,227, 1, 27, 58,
+113, 89,139,139,138,200,178, 71,158, 53,226,254,236,220, 1,240,253,221, 94,127,137,190, 95, 61, 82,170,170,212, 53,159,170,172,
+ 32, 89,139,200,198,141,139,214, 53,161,150,253,112,150, 3, 38,192,136,136, 96, 61, 23, 0, 0, 0, 2, 0, 88,255, 44, 4,121,
+ 5,214, 0, 33, 0, 43, 0, 0, 1, 22, 23, 22, 21, 20, 7, 6, 43, 1, 7, 33, 21, 33, 7, 39, 55, 35, 53, 33, 55, 33, 53, 33,
+ 19, 38, 35, 33, 53, 33, 50, 23, 55, 23, 1, 51, 50, 55, 54, 53, 52, 39, 38, 39, 3,131, 57, 50,139,139,138,201, 68, 52, 2, 86,
+253,113, 70,159, 53,226, 1, 27, 51,254,178, 1,129,219, 12, 12,253,188, 2, 68, 38, 35, 73,158,254,188, 20,136, 96, 95, 95, 24,
+ 26, 4,199, 32, 50,141,198,200,139,139,154,170,212, 53,159,170,154,150, 2,143, 1,150, 5,219, 53,252, 57, 96, 94,138,136, 96,
+ 24, 18, 0, 0, 0, 1, 0, 88,255, 48, 4,121, 5, 0, 0, 33, 0, 0, 37, 21, 33, 7, 39, 55, 33, 53, 33, 55, 35, 34, 39, 38,
+ 53, 52, 55, 54, 51, 33, 21, 33, 34, 6, 21, 20, 23, 22, 51, 33, 21, 33, 23, 7, 4,121,254, 24,167,132, 82,254,160, 1,232,124,
+134,201,138,139,139,138,200, 2, 68,253,188,137,190, 95, 97,135, 2, 68,254,177, 65, 81,170,170,208,106,102,170,154,139,140,199,
+198,141,139,150,192,136,138, 94, 96,150, 53,101, 0, 1, 0, 88,255, 48, 4,121, 5, 0, 0, 34, 0, 0, 37, 21, 33, 7, 39, 55,
+ 33, 53, 33, 55, 6, 35, 33, 53, 33, 50, 55, 54, 53, 52, 38, 35, 33, 53, 33, 50, 23, 22, 21, 20, 7, 6, 7, 23, 7, 4,121,254,
+ 24,167,132, 82,254,160, 1,232,124, 16, 17,253,189, 2, 68,135, 97, 95,190,137,253,188, 2, 68,200,138,139,139, 93,122, 84, 81,
+170,170,208,106,102,170,155, 1,150, 96, 94,138,136,192,150,139,141,198,199,140, 94, 30, 68,101, 0, 1, 0, 88, 0,119, 4,121,
+ 4,139, 0, 7, 0, 49, 0,176, 6, 47,176, 7, 51,177, 4, 4,237,177, 5, 4,237,176, 2,176, 4, 16,222,176, 3, 50,177, 0,
+ 4,237,177, 1, 4,237, 1,176, 0, 47,176, 7, 51,177, 3, 4,237,177, 4, 4,237, 48, 49, 19, 33, 21, 33, 17, 33, 21, 33, 88,
+ 4, 33,252,137, 3,119,251,223, 4,139,170,253, 64,170, 0, 0, 0, 1, 0, 88, 0,119, 4,121, 4,139, 0, 7, 0, 49, 0,176,
+ 1, 47,176, 2, 51,177, 3, 4,237,177, 4, 4,237,176, 5,176, 3, 16,222,176, 6, 50,177, 0, 4,237,177, 7, 4,237, 1,176,
+ 4, 47,176, 5, 51,177, 0, 4,237,177, 1, 4,237, 48, 49, 1, 17, 33, 53, 33, 17, 33, 53, 4,121,251,223, 3,119,252,137, 4,
+139,251,236,170, 2,192,170, 0, 0, 2, 0, 88, 0, 14, 4,121, 4,244, 0, 3, 0, 11, 0, 72, 0,176, 2, 47,176, 3, 51,177,
+ 0, 4,237,177, 1, 4,237,176, 10,176, 0, 16,222,176, 11, 50,177, 8, 4,237,177, 9, 4,237,176, 6,176, 8, 16,222,176, 7,
+ 50,177, 4, 4,237,177, 5, 4,237, 1,176, 0, 47,176, 3, 51,176, 4, 51,176, 11, 51,177, 7, 4,237,177, 8, 4,237, 48, 49,
+ 55, 33, 21, 33, 17, 33, 21, 33, 17, 33, 21, 33, 88, 4, 33,251,223, 4, 33,252,137, 3,119,251,223,184,170, 4,230,170,253,152,
+170, 0, 0, 0, 0, 2, 0, 88, 0, 14, 4,121, 4,244, 0, 3, 0, 11, 0, 74, 0,176, 1, 47,176, 2, 51,177, 0, 4,237,177,
+ 3, 4,237,176, 5,176, 0, 16,222,176, 6, 50,177, 7, 4,237,177, 8, 4,237,176, 9,176, 7, 16,222,176, 10, 50,177, 4, 4,
+237,177, 11, 4,237, 1,176, 8, 47,176, 9, 51,177, 0, 4,237,177, 1, 4,237,177, 4, 4,237,177, 5, 4,237, 48, 49, 37, 21,
+ 33, 53, 1, 17, 33, 53, 33, 17, 33, 53, 4,121,251,223, 4, 33,251,223, 3,119,252,137,184,170,170, 4, 60,252, 68,170, 2,104,
+170, 0, 0, 0, 0, 3, 0, 79, 0,105, 4,130, 4,158, 0, 25, 0, 51, 0, 63, 0, 0, 0, 50, 22, 23, 22, 23, 22, 21, 20, 7,
+ 6, 7, 14, 1, 34, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 4, 34, 7, 6, 7, 14, 1, 21, 20, 22, 23, 22, 23, 22, 50, 55,
+ 54, 55, 62, 1, 53, 52, 38, 39, 38, 39, 7, 51, 17, 33, 21, 33, 17, 35, 17, 33, 53, 33, 1,250,221,190, 79, 79, 39, 39, 39, 39,
+ 79, 79,190,221,190, 79, 79, 39, 39, 39, 39, 79, 79, 1,126,163, 71, 69, 58, 59, 57, 57, 59, 58, 69, 71,163, 70, 70, 58, 59, 57,
+ 57, 59, 58, 70,222,140, 1, 20,254,236,140,254,237, 1, 19, 4,158, 80, 79, 79, 95, 95,112,109, 95, 95, 79, 78, 80, 80, 78, 79,
+ 95, 95,109,112, 95, 95, 79, 79, 61, 30, 30, 57, 59,140, 83, 80,140, 59, 57, 30, 30, 30, 30, 57, 59,140, 80, 83,140, 59, 57, 30,
+ 22,254,235,140,254,238, 1, 18,140, 0, 0, 0, 0, 3, 0, 79, 0,105, 4,130, 4,158, 0, 25, 0, 51, 0, 55, 0, 0, 0, 50,
+ 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 14, 1, 34, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 4, 34, 7, 6, 7, 14, 1, 21,
+ 20, 22, 23, 22, 23, 22, 50, 55, 54, 55, 62, 1, 53, 52, 38, 39, 38, 39, 19, 21, 33, 53, 1,250,221,190, 79, 79, 39, 39, 39, 39,
+ 79, 79,190,221,190, 79, 79, 39, 39, 39, 39, 79, 79, 1,126,163, 71, 69, 58, 59, 57, 57, 59, 58, 69, 71,163, 70, 70, 58, 59, 57,
+ 57, 59, 58, 70,194,253, 77, 4,158, 80, 79, 79, 95, 95,112,109, 95, 95, 79, 78, 80, 80, 78, 79, 95, 95,109,112, 95, 95, 79, 79,
+ 61, 30, 30, 57, 59,140, 83, 80,140, 59, 57, 30, 30, 30, 30, 57, 59,140, 80, 83,140, 59, 57, 30,254,213,140,140, 0, 3, 0, 79,
+ 0,105, 4,130, 4,158, 0, 25, 0, 51, 0, 63, 0, 0, 0, 50, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 14, 1, 34, 38, 39, 38,
+ 39, 38, 53, 52, 55, 54, 55, 54, 4, 34, 7, 6, 7, 14, 1, 21, 20, 22, 23, 22, 23, 22, 50, 55, 54, 55, 62, 1, 53, 52, 38, 39,
+ 38, 39, 5, 55, 23, 55, 23, 7, 23, 7, 39, 7, 39, 55, 1,250,221,190, 79, 79, 39, 39, 39, 39, 79, 79,190,221,190, 79, 79, 39,
+ 39, 39, 39, 79, 79, 1,126,163, 71, 69, 58, 59, 57, 57, 59, 58, 69, 71,163, 70, 70, 58, 59, 57, 57, 59, 58, 70,254, 66, 99,196,
+195, 99,195,194, 99,194,194, 99,194, 4,158, 80, 79, 79, 95, 95,112,109, 95, 95, 79, 78, 80, 80, 78, 79, 95, 95,109,112, 95, 95,
+ 79, 79, 61, 30, 30, 57, 59,140, 83, 80,140, 59, 57, 30, 30, 30, 30, 57, 59,140, 80, 83,140, 59, 57, 30,173, 99,196,195, 99,195,
+194, 99,194,194, 99,194, 0, 0, 0, 3, 0, 79, 0,105, 4,130, 4,158, 0, 25, 0, 51, 0, 55, 0, 0, 0, 50, 22, 23, 22, 23,
+ 22, 21, 20, 7, 6, 7, 14, 1, 34, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 4, 34, 7, 6, 7, 14, 1, 21, 20, 22, 23, 22,
+ 23, 22, 50, 55, 54, 55, 62, 1, 53, 52, 38, 39, 38, 39, 31, 1, 1, 39, 1,250,221,190, 79, 79, 39, 39, 39, 39, 79, 79,190,221,
+190, 79, 79, 39, 39, 39, 39, 79, 79, 1,126,163, 71, 69, 58, 59, 57, 57, 59, 58, 69, 71,163, 70, 70, 58, 59, 57, 57, 59, 58, 70,
+ 44, 99,254, 24, 99, 4,158, 80, 79, 79, 95, 95,112,109, 95, 95, 79, 78, 80, 80, 78, 79, 95, 95,109,112, 95, 95, 79, 79, 61, 30,
+ 30, 57, 59,140, 83, 80,140, 59, 57, 30, 30, 30, 30, 57, 59,140, 80, 83,140, 59, 57, 30, 75, 99,254, 24, 99, 0, 0, 3, 0, 79,
+ 0,105, 4,130, 4,158, 0, 3, 0, 29, 0, 55, 0, 0, 1, 51, 17, 35, 18, 50, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 14, 1,
+ 34, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 4, 34, 7, 6, 7, 14, 1, 21, 20, 22, 23, 22, 23, 22, 50, 55, 54, 55, 62, 1,
+ 53, 52, 38, 39, 38, 39, 1,233,252,252, 17,221,190, 79, 79, 39, 39, 39, 39, 79, 79,190,221,190, 79, 79, 39, 39, 39, 39, 79, 79,
+ 1,126,163, 71, 69, 58, 59, 57, 57, 59, 58, 69, 71,163, 70, 70, 58, 59, 57, 57, 59, 58, 70, 3, 16,254,207, 2,191, 80, 79, 79,
+ 95, 95,112,109, 95, 95, 79, 78, 80, 80, 78, 79, 95, 95,109,112, 95, 95, 79, 79, 61, 30, 30, 57, 59,140, 83, 80,140, 59, 57, 30,
+ 30, 30, 30, 57, 59,140, 80, 83,140, 59, 57, 30, 0, 4, 0, 79, 0,105, 4,130, 4,158, 0, 14, 0, 24, 0, 50, 0, 76, 0, 0,
+ 1, 50, 22, 23, 30, 1, 21, 20, 6, 35, 34, 38, 53, 52, 54, 22, 34, 6, 20, 22, 51, 50, 54, 53, 52, 2, 50, 22, 23, 22, 23, 22,
+ 21, 20, 7, 6, 7, 14, 1, 34, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 4, 34, 7, 6, 7, 14, 1, 21, 20, 22, 23, 22, 23,
+ 22, 50, 55, 54, 55, 62, 1, 53, 52, 38, 39, 38, 39, 2,104, 55, 98, 37, 38, 39,156,113,113,151,154,167,110, 78, 76, 56, 56, 79,
+244,221,190, 79, 79, 39, 39, 39, 39, 79, 79,190,221,190, 79, 79, 39, 39, 39, 39, 79, 79, 1,126,163, 71, 69, 58, 59, 57, 57, 59,
+ 58, 69, 71,163, 70, 70, 58, 59, 57, 57, 59, 58, 70, 3,143, 41, 39, 37, 96, 56,110,154,151,113,113,156,135, 77,112, 76, 77, 55,
+ 55, 1,228, 80, 79, 79, 95, 95,112,109, 95, 95, 79, 78, 80, 80, 78, 79, 95, 95,109,112, 95, 95, 79, 79, 61, 30, 30, 57, 59,140,
+ 83, 80,140, 59, 57, 30, 30, 30, 30, 57, 59,140, 80, 83,140, 59, 57, 30, 0, 0, 0, 7, 0, 79, 0,105, 4,130, 4,158, 0, 25,
+ 0, 33, 0, 39, 0, 47, 0, 55, 0, 61, 0, 69, 0, 0, 0, 50, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 14, 1, 34, 38, 39, 38,
+ 39, 38, 53, 52, 55, 54, 55, 54, 5, 17, 37, 38, 39, 38, 39, 38, 13, 2, 54, 53, 52, 3, 39, 17, 54, 55, 54, 55, 54, 5, 17, 7,
+ 22, 23, 22, 23, 22, 45, 2, 6, 21, 20, 19, 5, 17, 6, 7, 6, 7, 6, 1,250,221,190, 79, 79, 39, 39, 39, 39, 79, 79,190,221,
+190, 79, 79, 39, 39, 39, 39, 79, 79, 1,102, 0,255, 15, 18, 58, 70, 45, 1, 6,254,236, 1, 19, 28, 84,254, 49, 45, 70, 58, 17,
+254,158,254, 15, 17, 58, 69, 46,254,251, 1, 19,254,236, 27, 83, 0,255, 49, 46, 69, 58, 18, 4,158, 80, 79, 79, 95, 95,112,109,
+ 95, 95, 79, 78, 80, 80, 78, 79, 95, 95,109,112, 95, 95, 79, 79, 65,254,207,154, 19, 19, 57, 30, 19,238,150,150, 70, 80, 81,254,
+188,153,254,210, 7, 19, 30, 57, 18,131, 1, 46,153, 18, 18, 57, 30, 19,235,150,150, 69, 81, 80, 1, 68,154, 1, 49, 7, 19, 30,
+ 57, 19, 0, 0, 0, 4, 0, 79, 0,105, 4,130, 4,158, 0, 3, 0, 7, 0, 33, 0, 59, 0, 0, 1, 33, 21, 33, 17, 33, 21, 33,
+ 18, 50, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 14, 1, 34, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 4, 34, 7, 6, 7, 14,
+ 1, 21, 20, 22, 23, 22, 23, 22, 50, 55, 54, 55, 62, 1, 53, 52, 38, 39, 38, 39, 1, 43, 2,123,253,133, 2,123,253,133,207,221,
+190, 79, 79, 39, 39, 39, 39, 79, 79,190,221,190, 79, 79, 39, 39, 39, 39, 79, 79, 1,126,163, 71, 69, 58, 59, 57, 57, 59, 58, 69,
+ 71,163, 70, 70, 58, 59, 57, 57, 59, 58, 70, 2, 59,103, 1, 90,102, 1,214, 80, 79, 79, 95, 95,112,109, 95, 95, 79, 78, 80, 80,
+ 78, 79, 95, 95,109,112, 95, 95, 79, 79, 61, 30, 30, 57, 59,140, 83, 80,140, 59, 57, 30, 30, 30, 30, 57, 59,140, 80, 83,140, 59,
+ 57, 30, 0, 0, 0, 3, 0, 79, 0,105, 4,130, 4,158, 0, 25, 0, 51, 0, 55, 0, 0, 0, 50, 22, 23, 22, 23, 22, 21, 20, 7,
+ 6, 7, 14, 1, 34, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 4, 34, 7, 6, 7, 14, 1, 21, 20, 22, 23, 22, 23, 22, 50, 55,
+ 54, 55, 62, 1, 53, 52, 38, 39, 38, 39, 19, 33, 53, 33, 1,250,221,190, 79, 79, 39, 39, 39, 39, 79, 79,190,221,190, 79, 79, 39,
+ 39, 39, 39, 79, 79, 1,126,163, 71, 69, 58, 59, 57, 57, 59, 58, 69, 71,163, 70, 70, 58, 59, 57, 57, 59, 58, 70, 50,254,109, 1,
+147, 4,158, 80, 79, 79, 95, 95,112,109, 95, 95, 79, 78, 80, 80, 78, 79, 95, 95,109,112, 95, 95, 79, 79, 61, 30, 30, 57, 59,140,
+ 83, 80,140, 59, 57, 30, 30, 30, 30, 57, 59,140, 80, 83,140, 59, 57, 30,254, 73,140, 0, 0, 0, 0, 3, 0, 80, 0,105, 4,131,
+ 4,156, 0, 3, 0, 7, 0, 19, 0, 0, 37, 17, 33, 17, 3, 33, 17, 33, 1, 51, 17, 33, 21, 33, 17, 35, 17, 33, 53, 33, 3,244,
+252,232,140, 4, 51,251,205, 1,210,140, 1, 56,254,200,140,254,201, 1, 55,245, 3, 27,252,229, 3,167,251,205, 3,152,254,199,
+140,254,202, 1, 54,140, 0, 0, 0, 3, 0, 80, 0,105, 4,131, 4,156, 0, 3, 0, 7, 0, 11, 0, 0, 37, 17, 33, 17, 3, 33,
+ 17, 33, 1, 21, 33, 53, 3,244,252,232,140, 4, 51,251,205, 3,114,253, 77,245, 3, 27,252,229, 3,167,251,205, 2, 95,140,140,
+ 0, 3, 0, 80, 0,105, 4,131, 4,156, 0, 3, 0, 7, 0, 19, 0, 0, 37, 17, 33, 17, 3, 33, 17, 33, 19, 55, 9, 1, 23, 9,
+ 1, 7, 9, 1, 39, 1, 3,244,252,232,140, 4, 51,251,205,172, 99, 1, 11, 1, 12, 99,254,244, 1, 8, 99,254,248,254,246, 99,
+ 1, 10,245, 3, 27,252,229, 3,167,251,205, 3, 35, 99,254,245, 1, 12, 99,254,244,254,248, 99, 1, 8,254,247, 99, 1, 9, 0,
+ 0, 3, 0, 80, 0,105, 4,131, 4,156, 0, 3, 0, 7, 0, 11, 0, 0, 1, 51, 17, 35, 5, 17, 33, 17, 3, 33, 17, 33, 1,233,
+252,252, 2, 11,252,232,140, 4, 51,251,205, 3, 16,254,207,234, 3, 27,252,229, 3,167,251,205, 0, 1, 1,233, 2, 47, 2,229,
+ 3, 96, 0, 3, 0, 21,185, 0, 2, 1, 1,181, 0, 4, 1, 29, 0, 4, 16,212,236, 49, 0, 16,212,236, 48, 1, 51, 17, 35, 1,
+233,252,252, 3, 96,254,207, 0, 0, 1, 1, 8, 1,155, 3,201, 4, 55, 0, 9, 0, 0, 1, 33, 19, 23, 33, 7, 23, 39, 7, 19,
+ 1, 9, 1, 12, 84, 83, 1, 12,217, 84,218,218, 83, 3, 56, 0,255,255,158,255,158,158, 0,255, 0, 2, 0, 88, 1, 96, 4,121,
+ 3,195, 0, 3, 0, 31, 0, 0, 1, 21, 33, 53, 17, 30, 1, 51, 50, 55, 54, 55, 62, 1, 51, 50, 22, 23, 21, 46, 1, 35, 34, 6,
+ 7, 6, 7, 6, 35, 34, 38, 39, 4,121,251,223, 74,137, 70, 93,116, 22, 10, 75,100, 53, 83,146, 78, 73,141, 79, 51,103, 77, 11,
+ 22,113, 90, 79,143, 75, 2, 12,172,172, 1,183, 63, 60, 54, 11, 4, 32, 22, 55, 60,174, 64, 59, 24, 34, 4, 10, 51, 55, 59, 0,
+ 0, 3, 0, 88,254, 65, 4,121, 6, 21, 0, 6, 0, 13, 0, 17, 0, 0, 55, 53, 1, 21, 1, 53, 37, 19, 21, 1, 53, 1, 21, 5,
+ 1, 21, 33, 53, 88, 4, 33,251,223, 3, 35,254,251,223, 4, 33,252,223, 3, 33,251,223,202,182,254,180,168,254,181,184,231, 3,
+172,182, 1, 76,168, 1, 75,184,231,254, 10,170,170, 0, 0, 0, 0, 3, 0, 88,254, 65, 4,121, 6, 21, 0, 6, 0, 13, 0, 17,
+ 0, 0, 37, 13, 1, 21, 1, 53, 9, 1, 45, 1, 53, 1, 21, 1, 21, 33, 21, 33, 4,121,252,221, 3, 35,251,223, 4, 33,251,223,
+ 3, 33,252,223, 4, 33,251,223, 4, 33,251,223,202,234,231,184, 1, 75,168, 1, 76, 2, 12,234,231,184,254,181,168,254,180, 86,
+170, 0, 0, 0, 0, 2, 0, 86, 0, 0, 4,119, 4, 63, 0, 6, 0, 10, 0, 0, 1, 13, 1, 21, 1, 53, 1, 53, 33, 53, 33, 4,
+119,252,223, 3, 33,251,223, 4, 33,251,223, 4, 33, 2,137,234,231,184, 1, 75,168, 1, 76, 86,170, 0, 0, 0, 0, 2, 0, 88,
+ 0, 0, 4,121, 4, 63, 0, 6, 0, 10, 0, 0, 19, 53, 1, 21, 1, 53, 37, 1, 53, 33, 21, 88, 4, 33,251,223, 3, 35,252,221,
+ 4, 33, 2,137,182,254,180,168,254,181,184,231, 1,246,170,170, 0, 2, 0, 86,255, 4, 4,119, 5,177, 0, 9, 0, 24, 0, 0,
+ 1, 36, 55, 21, 6, 5, 6, 5, 53, 36, 1, 21, 38, 37, 38, 37, 53, 36, 55, 36, 55, 21, 0, 5, 4, 2,164, 1, 34,177,203,254,
+248,222,254,144, 1,110, 2,179,183,254,228,237,254,159, 1, 87,247, 1, 28,183,254,221,254,108, 1,148, 4, 26,200,207,252,220,
+156,131, 56,200, 54,252,115,239,203,150,125, 61,166, 57,130,151,201,239,254,222, 93, 79, 0, 0, 0, 2, 0, 86,255, 4, 4,119,
+ 5,177, 0, 9, 0, 24, 0, 0, 1, 22, 5, 21, 36, 39, 36, 39, 53, 22, 3, 0, 37, 36, 1, 53, 22, 5, 22, 5, 21, 4, 7, 4,
+ 7, 2, 41,224, 1,110,254,144,222,254,248,203,177,177, 1, 35, 1,148,254,108,254,221,183, 1, 28,247, 1, 87,254,159,237,254,
+228,183, 4, 26,154, 54,200, 56,131,156,220,252,207,251, 17, 1, 48, 79, 93, 1, 34,239,201,151,130, 57,166, 61,125,150,203, 0,
+ 0, 2, 0, 86,254,140, 4,119, 6, 41, 0, 37, 0, 42, 0, 0, 1, 23, 7, 54, 55, 21, 6, 7, 3, 22, 23, 21, 38, 39, 7, 23,
+ 4, 23, 21, 38, 37, 38, 39, 3, 39, 19, 38, 39, 53, 22, 23, 55, 38, 37, 53, 36, 63, 1, 3, 55, 6, 7, 22, 3,100,162, 77,106,
+ 84,129,152, 86,202,165,169,254, 51, 7, 1, 8,203,177,254,222, 31, 33,179,162,186,163,208,247,182, 51,210,254,242, 1, 97,237,
+ 52,109, 34, 99,106, 88, 6, 41, 51,245, 83, 93,239,135, 91,254,238,101,165,239,185,143,161, 4,156,220,252,207,200, 21, 20,253,
+200, 51, 2, 78, 64, 30,200, 37, 72,163, 90, 45,166, 61,125, 29,254,164,107, 36, 21, 20, 0, 0, 0, 2, 0, 86,254,140, 4,119,
+ 6, 41, 0, 36, 0, 40, 0, 0, 1, 23, 3, 22, 23, 21, 4, 15, 1, 54, 37, 21, 4, 15, 1, 3, 39, 19, 6, 7, 53, 54, 63, 1,
+ 6, 7, 53, 54, 37, 55, 36, 39, 53, 22, 5, 22, 31, 1, 7, 55, 38, 3, 37,162,165,154,187,255, 0,203, 68,209, 1, 62,254,146,
+224, 22,161,162, 87,119, 90,140,169, 78,231,156,204, 1, 2, 40,254,229,219,183, 1, 28, 43, 47,109, 5, 34, 15, 6, 41, 51,253,
+243, 51, 32,166, 43, 83,216,105, 48,200, 54,154, 15,254, 0, 51, 1, 22,104,105,252,152,121,247,135,172,239,203,106,127,101,229,
+239,203,150, 23, 20,220, 14, 8, 3, 0, 0, 0, 0, 2, 0, 88,255, 91, 4,121, 5,167, 0, 15, 0, 19, 0, 0, 1, 23, 7, 51,
+ 21, 33, 1, 33, 21, 33, 3, 39, 55, 35, 17, 33, 9, 1, 33, 17, 3, 80,158, 89,228,254,216,254,230, 2, 66,253,122,114,158, 89,
+228, 2,134,254,162, 1, 26,254,104, 5,167, 63,221,170,253, 64,170,254,228, 63,221, 4, 20,252,150, 2,192,253, 64, 0, 0, 0,
+ 0, 2, 0, 88,255, 91, 4,121, 5,167, 0, 15, 0, 19, 0, 0, 1, 23, 7, 51, 17, 33, 3, 39, 55, 35, 53, 33, 1, 33, 53, 33,
+ 23, 1, 33, 17, 3, 80,158, 89,228,253,122,114,158, 89,228, 1, 40, 1, 26,253,190, 2,134,115,254,230, 1,152, 5,167, 63,221,
+251,236,254,228, 63,221,170, 2,192,170,170,253, 64, 2,192, 0, 0, 1, 0, 88,255, 62, 4,121, 4,244, 0, 20, 0, 0, 19, 33,
+ 21, 33, 17, 33, 21, 33, 23, 7, 33, 21, 33, 7, 39, 55, 33, 53, 33, 55, 33, 88, 4, 33,252,137, 3,119,254,210, 32, 82, 1, 96,
+254, 24,167,132, 82,254,160, 1,232,103,253,177, 4,244,170,253,152,170, 26,102,170,208,106,102,170,128, 0, 0, 0, 1, 0, 88,
+255, 62, 4,121, 4,244, 0, 20, 0, 0, 37, 21, 33, 7, 39, 55, 33, 53, 33, 55, 33, 53, 33, 17, 33, 53, 33, 17, 33, 23, 7, 4,
+121,254, 24,167,132, 82,254,160, 1,232,103,253,177, 3,119,252,137, 4, 33,254,210, 32, 82,184,170,208,106,102,170,128,170, 2,
+104,170,252, 68, 26,102, 0, 0, 0, 1, 0, 86,254,237, 4,119, 4, 63, 0, 37, 0, 0, 37, 38, 39, 38, 35, 34, 6, 7, 53, 62,
+ 1, 51, 50, 22, 23, 55, 37, 53, 1, 21, 13, 1, 21, 37, 7, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 39, 3, 39, 2, 22, 29, 23,
+ 52, 51, 79,141, 73, 78,146, 83, 58, 90, 29, 48,253,236, 4, 33,252,223, 3, 33,254,120, 50, 88, 73, 70,137, 74, 75,143, 79, 81,
+100, 62,136, 51, 11, 5, 12, 59, 64,174, 60, 55, 22, 12,210,167,168, 1, 75,184,231,234,182,123,223, 34, 60, 63,175, 59, 55, 41,
+254,240, 31, 0, 0, 1, 0, 86,254,237, 4,119, 4, 63, 0, 38, 0, 0, 19, 45, 1, 53, 1, 21, 5, 23, 3, 22, 51, 50, 54, 55,
+ 21, 14, 1, 35, 34, 39, 3, 39, 19, 38, 39, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 23, 55, 5, 86, 3, 33,252,223, 4, 33,
+254, 63, 69, 62, 88, 73, 70,137, 74, 75,143, 79, 81,100, 62,136, 67, 29, 23, 52, 51, 79,141, 73, 78,146, 83, 58, 90, 29, 48,253,
+236, 1,182,234,231,184,254,181,168,141, 16,254,237, 34, 60, 63,175, 59, 55, 41,254,240, 31, 1, 39, 11, 5, 12, 59, 64,174, 60,
+ 55, 22, 12,212,167, 0, 0, 0, 0, 2, 0, 86,254, 75, 4,119, 5,177, 0, 31, 0, 46, 0, 0, 5, 38, 39, 38, 35, 34, 6, 7,
+ 53, 62, 1, 51, 50, 23, 22, 23, 19, 23, 3, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 39, 3, 39, 1, 0, 5, 4, 1, 21, 38, 37,
+ 38, 37, 53, 36, 55, 36, 55, 2, 22, 29, 23, 52, 51, 79,141, 73, 78,146, 83, 54, 49, 45, 29, 78,136, 83, 88, 73, 70,137, 74, 75,
+143, 79, 81,100, 83,136, 2,185,254,221,254,108, 1,148, 1, 35,183,254,228,247,254,169, 1, 97,237, 1, 28,183, 19, 11, 5, 12,
+ 59, 64,174, 60, 55, 11, 11, 12, 1, 87, 31,254,145, 34, 60, 63,175, 59, 55, 41,254,148, 31, 6, 88,254,208, 79, 93,254,222,239,
+201,151,130, 57,166, 61,125,150,203, 0, 0, 0, 0, 2, 0, 86,254, 75, 4,119, 5,177, 0, 31, 0, 46, 0, 0, 5, 38, 39, 38,
+ 35, 34, 6, 7, 53, 62, 1, 51, 50, 23, 22, 23, 19, 23, 3, 22, 51, 50, 54, 55, 21, 14, 1, 35, 34, 39, 3, 39, 1, 53, 22, 5,
+ 22, 5, 21, 4, 7, 4, 7, 53, 0, 37, 36, 2, 22, 29, 23, 52, 51, 79,141, 73, 78,146, 83, 54, 49, 45, 29, 78,136, 83, 88, 73,
+ 70,137, 74, 75,143, 79, 81,100, 83,136,254,152,183, 1, 28,237, 1, 97,254,169,247,254,231,186, 1, 35, 1,148,254,108, 19, 11,
+ 5, 12, 59, 64,174, 60, 55, 11, 11, 12, 1, 87, 31,254,145, 34, 60, 63,175, 59, 55, 41,254,148, 31, 6, 88,239,203,150,125, 61,
+166, 57,130,148,204,239, 1, 34, 93, 79, 0, 0,255,255, 0, 80, 1,234, 4,127, 3, 27, 16, 7, 6,153, 0, 0, 1,234, 0, 0,
+255,255, 0, 73, 0, 98, 4,138, 4,163, 16, 6, 7, 84, 0, 0, 0, 1, 0,114, 1, 76, 4, 82, 3,140, 0, 7, 0, 0, 1, 17,
+ 1, 53, 5, 17, 1, 21, 2,162,253,208, 1,176, 2, 48, 2,122,254,210, 1, 74,194,250, 1, 46,254,182,194, 0, 0, 2, 0,146,
+ 0, 0, 4, 63, 4,196, 0, 4, 0, 9, 0, 0, 51, 17, 9, 1, 17, 37, 33, 17, 9, 1,146, 1,214, 1,214,252,206, 2,184,254,
+164,254,164, 2,135, 2, 61,253,195,253,121,122, 1,213, 1,171,254, 85, 0, 0, 0, 1, 0,146, 3, 63, 4, 62, 5,248, 0, 5,
+ 0, 0, 9, 1, 35, 9, 1, 35, 2,104, 1,214,163,254,205,254,205,163, 5,248,253, 71, 1,199,254, 57, 0, 0, 0, 1, 0,146,
+254,242, 4, 62, 1,172, 0, 5, 0, 0, 9, 1, 51, 9, 1, 51, 2,104,254, 42,163, 1, 51, 1, 51,163,254,242, 2,186,254, 56,
+ 1,200, 0, 0, 0, 2, 0,146, 0, 0, 4, 62, 3,142, 0, 3, 0, 9, 0, 0, 19, 33, 21, 33, 5, 1, 35, 9, 1, 35,156, 3,
+153,252,103, 1,204, 1,214,163,254,205,254,205,163, 3,142,114, 99,253, 71, 1,199,254, 57, 0, 0, 3, 0,146, 0, 0, 4, 62,
+ 4,136, 0, 3, 0, 7, 0, 13, 0, 0, 19, 33, 21, 33, 21, 33, 21, 33, 5, 1, 35, 9, 1, 35,156, 3,153,252,103, 3,153,252,
+103, 1,204, 1,214,163,254,205,254,205,163, 4,136,114,136,114, 99,253, 71, 1,199,254, 57, 0, 0, 1, 1,207,254,242, 3,119,
+ 6, 20, 0, 5, 0, 0, 1, 33, 21, 35, 17, 35, 1,207, 1,168,240,184, 6, 20,143,249,109, 0, 0, 1, 1, 90,254,242, 3, 2,
+ 6, 20, 0, 5, 0, 0, 1, 17, 35, 17, 35, 53, 3, 2,184,240, 6, 20,248,222, 6,147,143, 0, 0, 1, 1,207,254,242, 3,119,
+ 6, 20, 0, 5, 0, 0, 1, 17, 51, 17, 51, 21, 1,207,184,240,254,242, 7, 34,249,109,143, 0, 0, 1, 1, 90,254,242, 3, 2,
+ 6, 20, 0, 5, 0, 0, 1, 33, 53, 51, 17, 51, 3, 2,254, 88,240,184,254,242,143, 6,147, 0, 0, 2, 2, 37, 0,150, 4,175,
+ 3, 67, 0, 3, 0, 7, 0, 0, 1, 33, 21, 33, 7, 51, 17, 35, 2,242, 1,189,254, 67,205,114,114, 3, 67,114, 91,254, 32, 0,
+ 0, 2, 0, 13, 0,150, 2,151, 3, 67, 0, 3, 0, 7, 0, 0, 19, 33, 21, 33, 5, 51, 17, 35, 13, 1,189,254, 67, 2, 24,114,
+114, 3, 67,114, 91,254, 32, 0, 0, 2, 2, 37, 2,209, 4,175, 5,126, 0, 3, 0, 7, 0, 0, 1, 33, 21, 33, 3, 51, 17, 35,
+ 2,242, 1,189,254, 67,205,114,114, 3, 67,114, 2,173,254, 32, 0, 2, 0, 13, 2,209, 2,151, 5,126, 0, 3, 0, 7, 0, 0,
+ 19, 33, 21, 33, 1, 51, 17, 35, 13, 1,189,254, 67, 2, 24,114,114, 3, 67,114, 2,173,254, 32, 0, 1, 0, 88, 1,115, 4,121,
+ 3, 94, 0, 5, 0, 0, 1, 21, 33, 17, 35, 17, 4,121,252,135,168, 3, 94,172,254,193, 1,235, 0, 2, 0, 97, 1, 2, 4,112,
+ 5, 18, 0, 7, 0, 15, 0, 0, 19, 36, 5, 2, 19, 4, 37, 18, 1, 18, 3, 4, 37, 2, 19, 36,231, 1,129, 1,129,137,137,254,
+127,254,127,137,254,241,184,184, 2, 7, 2, 8,184,184,253,248, 1,138,137,137, 1,128, 1,130,138,138,254,126,253,248, 1,244,
+ 2, 28,177,177,254, 12,253,229,177, 0, 0, 0,255,255, 0, 6, 1,176, 4,203, 4, 24, 16, 6, 9, 58, 0,156, 0, 2, 0, 6,
+ 1,176, 4,203, 4, 24, 0, 7, 0, 15, 0, 0, 19, 16, 37, 54, 32, 23, 4, 17, 37, 33, 38, 39, 38, 34, 7, 6, 6, 1, 49,152,
+ 1, 49,153, 1, 50,251,192, 3,187, 42,192,122,244,122,192, 1,176, 1, 96,176, 88, 88,176,254,160,114,197,111, 71, 71,110, 0,
+ 0, 2, 0,184, 1, 89, 4, 24, 4, 24, 0, 8, 0, 13, 0, 0, 0, 32, 23, 22, 23, 9, 1, 54, 55, 4, 34, 7, 9, 1, 1,210,
+ 1, 44,155, 74, 53,254, 80,254, 80, 53, 74, 1,173,248,133, 1, 2, 1, 0, 4, 24, 88, 42, 55,253,250, 2, 6, 55, 42, 35, 76,
+254,200, 1, 56, 0, 2, 0,166, 0,229, 4, 21, 4, 80, 0, 7, 0, 25, 0, 0, 0, 34, 6, 20, 22, 50, 54, 52, 3, 50, 23, 30,
+ 1, 21, 20, 6, 35, 34, 39, 7, 39, 55, 38, 53, 52, 54, 3, 4,196,138,135,199,140,238,158,105, 53, 54,216,157,127, 93,204, 81,
+205, 66,214, 3,201,137,199,135,137,195, 1, 18,111, 51,133, 78,152,214, 69,204, 81,204, 92,124,157,216, 0, 0, 0, 6, 0, 71,
+ 0,233, 4,138, 5, 43, 0, 3, 0, 45, 0, 55, 0, 65, 0, 74, 0, 84, 0, 0, 1, 51, 53, 35, 17, 21, 20, 6, 34, 38, 53, 52,
+ 54, 59, 1, 53, 35, 34, 38, 52, 54, 50, 22, 29, 1, 51, 53, 52, 54, 50, 22, 20, 6, 43, 1, 21, 51, 50, 22, 21, 20, 6, 34, 38,
+ 61, 1, 1, 53, 52, 38, 35, 34, 6, 20, 22, 51, 19, 35, 34, 6, 21, 20, 22, 50, 54, 53, 1, 51, 50, 54, 52, 38, 34, 6, 21, 17,
+ 21, 20, 22, 50, 54, 53, 52, 38, 35, 2, 1,207,207,130,183,129,129, 89,120,120, 89,129,129,183,130,207,130,184,128,128, 90,120,
+120, 90,128,128,184,130,254,201, 69, 49, 47, 69, 69, 48,117,117, 48, 69, 69, 96, 69, 1,159,118, 47, 69, 68, 97, 69, 69, 97, 68,
+ 69, 47, 2,162,208,254,200,119, 90,128,129, 92, 90,130,208,130,182,129,128, 90,119,119, 90,128,129,182,130,208,130, 90, 92,129,
+128, 90,119, 1,160,117, 48, 69, 69, 96, 69,254, 96, 69, 47, 49, 69, 69, 48, 2, 21, 69, 96, 69, 69, 48,253,235,117, 48, 69, 69,
+ 49, 47, 69, 0, 0, 1, 0, 88, 1,115, 4,121, 3, 94, 0, 5, 0, 0, 1, 33, 17, 51, 17, 33, 4,121,251,223,168, 3,121, 1,
+115, 1,235,254,193, 0, 0, 0, 0, 1, 1, 43, 2,209, 3,181, 5,126, 0, 5, 0, 0, 1, 33, 17, 35, 17, 33, 3,181,253,232,
+114, 2,138, 5, 12,253,197, 2,173, 0, 0, 0, 0, 1, 1, 28, 2,209, 3,166, 5,126, 0, 5, 0, 0, 1, 53, 33, 17, 35, 17,
+ 1, 28, 2,138,114, 5, 12,114,253, 83, 2, 59, 0, 1, 1, 43,255,142, 3,181, 2, 59, 0, 5, 0, 0, 33, 21, 33, 17, 51, 17,
+ 3,181,253,118,114,114, 2,173,253,197, 0, 0, 0, 1, 1, 28,255,142, 3,166, 2, 59, 0, 5, 0, 0, 41, 1, 17, 51, 17, 33,
+ 1, 28, 2, 24,114,253,118, 2, 59,253, 83, 0, 0, 1, 2, 0,254, 0, 4, 76, 6, 14, 0, 25, 0, 0, 1, 17, 52, 55, 26, 1,
+ 51, 50, 22, 21, 20, 6, 35, 34, 39, 38, 39, 46, 1, 35, 34, 3, 2, 21, 48, 17, 2, 1, 3, 12,190,202, 80,100, 64, 55, 42, 29,
+ 24, 15, 6, 9, 16,104, 17, 8,254, 0, 3,170, 36,129, 2, 3, 1,188, 84, 65, 54, 63, 19, 16, 38, 15, 72,253,149,254,211, 2,
+251,246, 0, 0, 0, 1, 0,124,254, 26, 2,200, 6, 40, 0, 25, 0, 0, 1, 17, 20, 7, 10, 1, 35, 34, 38, 53, 52, 54, 51, 50,
+ 23, 22, 23, 30, 1, 51, 50, 19, 18, 53, 48, 17, 2,199, 3, 12,190,202, 80,100, 64, 55, 42, 29, 24, 15, 6, 9, 16,104, 17, 8,
+ 6, 40,252, 86, 36,129,253,253,254, 68, 84, 65, 54, 63, 19, 16, 38, 15, 72, 2,107, 1, 45, 2, 4, 10, 0, 0, 0, 2, 0,104,
+ 0,233, 4,105, 4,201, 0, 7, 0, 11, 0, 0, 19, 33, 1, 33, 21, 33, 1, 35, 37, 33, 21, 33,104, 1, 92, 1,145, 1, 20,254,
+114,254,111,226, 2, 97, 1,160,254, 96, 4,201,252,222,190, 3, 34,190,190, 0, 0, 5, 0, 6, 1, 40, 4,203, 4, 73, 0, 4,
+ 0, 10, 0, 13, 0, 18, 0, 21, 0, 0, 9, 1, 33, 17, 33, 9, 1, 35, 3, 19, 51, 1, 23, 55, 33, 35, 17, 51, 27, 1, 39, 7,
+ 4,203,254, 81,252,234, 3, 22, 1, 5,254,211, 39,200,200, 39,254, 72,131,131,254,111, 57, 57,200,201,131,131, 2,185,254,111,
+ 3, 33,254,112, 1, 30,254,225,254,226, 2, 61,187,187,253,195, 1, 30,254,226,187,187, 0, 0, 0, 5, 0,125, 1, 40, 4, 84,
+ 4, 73, 0, 4, 0, 8, 0, 11, 0, 16, 0, 19, 0, 0, 1, 17, 35, 3, 19, 23, 33, 17, 33, 5, 23, 55, 33, 35, 17, 51, 27, 1,
+ 39, 7, 3,226,108,200,200,222,252, 41, 3,215,253,145,131,131,254,111,107,107,200,201,131,131, 1,154, 2, 61,254,225,254,226,
+114, 3, 33,114,187,187,253,195, 1, 30,254,226,187,187, 0, 0, 0, 43, 0, 50, 1,179, 4,159, 4, 34, 0, 11, 0, 23, 0, 35,
+ 0, 47, 0, 59, 0, 71, 0, 83, 0, 95, 0,107, 0,119, 0,131, 0,143, 0,155, 0,167, 0,179, 0,191, 0,203, 0,215, 0,227,
+ 0,239, 0,251, 1, 7, 1, 19, 1, 31, 1, 43, 1, 55, 1, 67, 1, 79, 1, 91, 1,103, 1,115, 1,127, 1,139, 1,151, 1,163,
+ 1,175, 1,187, 1,199, 1,211, 1,227, 1,239, 1,251, 2, 7, 0, 0, 19, 33, 50, 21, 17, 20, 35, 33, 34, 53, 17, 52, 23, 17,
+ 20, 51, 33, 50, 53, 17, 52, 35, 33, 34, 19, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59,
+ 1, 50, 55, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 7, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34,
+ 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21,
+ 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59,
+ 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 37, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34,
+ 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21,
+ 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59,
+ 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 39, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 7, 21, 20, 43, 1, 34,
+ 61, 1, 52, 59, 1, 50, 7, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 7, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 7, 21,
+ 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 7, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 7, 21, 20, 43, 1, 34, 61, 1, 52, 59,
+ 1, 50, 7, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 39, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34,
+ 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21,
+ 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59,
+ 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 23, 21, 20, 43, 1, 34,
+ 61, 1, 52, 59, 1, 50, 7, 50, 29, 1, 20, 43, 1, 34, 61, 1, 52, 34, 61, 1, 52, 51, 19, 21, 20, 43, 1, 34, 61, 1, 52, 59,
+ 1, 50, 23, 21, 20, 43, 1, 34, 61, 1, 52, 59, 1, 50, 5, 34, 61, 1, 52, 51, 33, 50, 29, 1, 20, 35,142, 3,181, 92, 92,252,
+ 75, 92, 61, 31, 3,181, 30, 30,252, 75, 31,108, 15, 31, 15, 15, 31, 15, 93, 15, 31, 15, 15, 31, 15,138, 15, 31, 16, 16, 31, 15,
+184, 16, 31, 15, 15, 31, 16, 92, 16, 30, 16, 16, 30, 16,184, 16, 30, 16, 16, 30, 16, 92, 15, 31, 16, 16, 31, 15, 92, 15, 31, 16,
+ 16, 31, 15, 92, 15, 31, 15, 15, 31, 15, 93, 16, 31, 15, 15, 31, 16,166, 16,105, 15, 15,105, 16,252,197, 15, 31, 15, 15, 31, 15,
+ 92, 15, 31, 15, 15, 31, 15, 93, 16, 31, 15, 15, 31, 16, 91, 15, 31, 15, 15, 31, 15, 93, 16, 31, 15, 15, 31, 16, 92, 16, 31, 15,
+ 15, 31, 16, 92, 15, 31, 16, 16, 31, 15, 92, 15, 31, 16, 16, 31, 15, 15, 15, 31, 16, 16, 31, 15, 92, 15, 31, 16, 16, 31, 15, 92,
+ 16, 31, 15, 15, 31, 16, 92, 16, 31, 15, 15, 31, 16, 92, 16, 30, 16, 16, 30, 16, 92, 16, 31, 15, 15, 31, 16, 93, 15, 31, 15, 15,
+ 31, 15, 92, 15, 31, 15, 15, 31, 15, 15, 15, 31, 15, 15, 31, 15, 92, 15, 31, 15, 15, 31, 15, 93, 16, 31, 15, 15, 31, 16, 92, 16,
+ 31, 15, 15, 31, 16, 92, 16, 31, 15, 15, 31, 16, 92, 16, 31, 15, 15, 31, 16, 92, 16, 30, 16, 16, 30, 16, 92, 15, 31, 16, 16, 31,
+ 15, 92, 15, 31, 15, 15, 31, 15,120, 16, 58, 15, 15, 58, 16, 16, 16, 16,102, 18, 30, 15, 62, 16, 31, 15, 15, 31, 16, 93, 16, 31,
+ 15, 15, 31, 16,253, 89, 15, 15, 1,173, 15, 15, 4, 34, 92,254, 73, 92, 92, 1,183, 92, 92,254, 73, 31, 31, 1,183, 31,254, 96,
+ 30, 16, 16, 30, 16, 15, 31, 16, 16, 31, 15, 76, 31, 15, 15, 31, 16, 16, 31, 15, 15, 31, 16, 16, 31, 15, 15, 31, 16, 16, 31, 15,
+ 15, 31, 16, 16, 31, 15, 15, 31, 16, 16, 31, 15, 15, 31, 16, 16, 31, 15, 15, 31, 16, 16, 31, 15, 15, 31, 16, 16, 31, 15, 15, 31,
+ 16, 76, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15,
+ 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 77, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15,
+ 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31, 15, 15, 31,
+ 15, 75, 31, 15, 15, 31, 16, 16, 31, 15, 15, 31, 16, 16, 31, 15, 15, 31, 16, 16, 31, 15, 15, 31, 16, 16, 31, 15, 15, 31, 16, 16,
+ 31, 15, 15, 31, 16, 16, 31, 15, 15, 31, 16, 16, 31, 15, 15, 31, 16, 16, 31, 15, 15, 31, 16, 16, 31, 15, 15, 31, 16, 92, 15,121,
+ 15, 15, 62, 14, 15, 30, 16,254,222, 31, 16, 16, 31, 15, 15, 31, 16, 16, 31, 15, 62, 16, 31, 15, 15, 31, 16, 0, 0, 5, 0, 6,
+ 1, 40, 4,203, 4, 73, 0, 4, 0, 10, 0, 13, 0, 18, 0, 21, 0, 0, 19, 1, 33, 17, 33, 9, 1, 51, 19, 3, 35, 41, 1, 23,
+ 37, 3, 19, 51, 17, 1, 33, 39, 6, 1,175, 3, 22,252,234,254,251, 1, 45, 39,200,200, 39, 1,184,254,250,131, 1, 14,200,200,
+ 57,254, 54, 1, 6,131, 2,185, 1,144,252,223, 1,145,254,225, 1, 30, 1, 31,187,187,254,225,254,226, 2, 61,253,195,187, 0,
+ 0, 1, 0, 72,255,211, 4,136, 2, 74, 0, 5, 0, 0, 5, 1, 55, 9, 1, 23, 2,104,253,224, 72, 1,216, 1,216, 72, 45, 2,
+ 45, 74,254, 28, 1,228, 74, 0, 0, 2, 1, 0,255, 52, 3,209, 6,161, 0, 3, 0, 7, 0, 0, 5, 33, 17, 33, 3, 17, 33, 17,
+ 1,114, 1,237,254, 19,114, 2,209, 90, 6,137,249, 5, 7,109,248,147, 0, 0, 0, 4, 0, 6,255, 52, 4,203, 6,161, 0, 3,
+ 0, 7, 0, 11, 0, 15, 0, 0, 23, 17, 33, 17, 37, 33, 17, 33, 53, 33, 53, 33, 53, 33, 17, 33, 6, 4,197,251,173, 3,225,252,
+ 31, 3,225,252, 31, 3,225,252, 31,204, 7,109,248,147,114, 1,186,172,236,170, 2,141, 0, 0, 0, 5, 0, 6,255, 52, 4,203,
+ 6,161, 0, 3, 0, 7, 0, 11, 0, 15, 0, 19, 0, 0, 1, 51, 21, 35, 17, 51, 21, 35, 1, 17, 33, 17, 37, 33, 17, 33, 53, 33,
+ 17, 33, 1,238,245,245,245,245,254, 24, 4,197,251,173, 3,225,252, 31, 3,225,252, 31, 4,111,246,254, 18,245,254,158, 7,109,
+248,147,114, 2,135,170, 3, 88, 0, 4, 0, 6,255, 52, 4,203, 6,161, 0, 3, 0, 8, 0, 12, 0, 17, 0, 0, 19, 9, 3, 33,
+ 17, 9, 2, 33, 17, 33, 9, 2, 17, 33,195, 1,165, 1,166,254, 90,254, 16, 3,225,254, 15,254, 16, 4, 83,251, 59, 4,197,251,
+173, 1,240, 1,241,252, 31, 2,220,254, 90, 1,166, 1,166,251, 36, 2,196,254, 16, 1,240,252,202, 7,109,252,173, 1,240,254,
+ 16, 2,225, 0,255,255, 0, 6,255, 52, 4,203, 6,161, 16, 38, 11,193, 0, 0, 16, 6, 8, 66, 0, 0, 0, 0, 0, 4, 0, 6,
+255, 52, 4,203, 6,161, 0, 13, 0, 24, 0, 28, 0, 39, 0, 0, 18, 16, 23, 22, 51, 50, 55, 54, 16, 39, 38, 35, 34, 7, 3, 33,
+ 17, 6, 7, 6, 35, 34, 39, 38, 39, 1, 33, 17, 33, 1, 54, 55, 54, 51, 50, 23, 22, 23, 17, 33,128,244,122,122,122,122,245,245,
+122,122,122,122,252, 3,225, 73,119,153,152,153,152,119, 72, 4, 83,251, 59, 4,197,251,173, 72,119,152,153,152,153,119, 73,252,
+ 31, 3,245,253,206,141, 71, 71,141, 2, 50,141, 71, 71,251, 36, 1,202, 95, 69, 88, 88, 69, 94,253,197, 7,109,253,168, 95, 68,
+ 88, 88, 69, 95, 1,231, 0, 0, 0, 3, 0, 6,254,162, 4,203, 7, 51, 0, 19, 0, 27, 0, 35, 0, 0, 18, 16, 37, 54, 55, 17,
+ 51, 17, 22, 23, 4, 16, 5, 6, 7, 17, 35, 17, 38, 39, 2, 16, 23, 22, 23, 17, 6, 7, 37, 17, 54, 55, 54, 16, 39, 38, 6, 1,
+ 49,114,115,152,114,115, 1, 50,254,206,115,114,152,115,114,183,244, 84, 84, 84, 84, 1, 64, 84, 84,245,245, 84, 1,124, 2,192,
+176, 66, 17, 1,244,254, 12, 17, 66,176,253, 64,176, 66, 17,254, 41, 1,215, 17, 66, 3, 41,253,206,141, 49, 15, 3,204, 15, 49,
+ 64,252, 52, 15, 49,141, 2, 50,141, 49, 0, 0,255,255, 0, 6, 0,116, 4,203, 5, 68, 16, 38, 11,193, 0, 0, 16, 7, 9, 37,
+ 0, 0, 0,200, 0, 3, 0, 6,255, 52, 4,203, 6,161, 0, 3, 0, 6, 0, 9, 0, 0, 23, 17, 33, 17, 37, 1, 33, 5, 1, 33,
+ 6, 4,197,251,173, 3, 89,252,167, 3,225,252,158, 3, 98,204, 7,109,248,147,198, 6, 53, 65,249,184, 0, 0, 0, 3, 0, 6,
+255, 52, 4,203, 6,161, 0, 3, 0, 6, 0, 9, 0, 0, 5, 33, 17, 33, 3, 17, 33, 7, 17, 33, 4,203,251, 59, 4,197,114,252,
+167,136, 3, 98,204, 7,109,249, 89, 6, 53, 65,249,184, 0, 0, 0, 4, 0, 6,255, 52, 4,203, 6,161, 0, 3, 0, 7, 0, 11,
+ 0, 14, 0, 0, 23, 17, 33, 17, 37, 33, 17, 1, 53, 1, 17, 33, 1, 17, 1, 6, 4,197,251,173, 3,225,252, 31, 3,225,252, 31,
+ 3,225,252,206,204, 7,109,248,147,114, 1, 88, 1,136,192, 1,136, 1, 97,251,133, 2,101,254,204, 0, 0, 0, 0, 4, 0, 6,
+255, 52, 4,203, 6,161, 0, 3, 0, 7, 0, 10, 0, 14, 0, 0, 23, 17, 33, 17, 37, 33, 17, 1, 25, 1, 9, 2, 17, 33, 6, 4,
+197,251,173, 3,225,252, 31, 3, 50,252,206, 3,225,252, 31,204, 7,109,248,147,114, 2,224,254,120, 3, 27,253,155, 1, 49, 1,
+233,254,120, 2,233, 0, 0, 0, 0, 3, 0, 6,255, 52, 4,203, 6,161, 0, 3, 0, 10, 0, 17, 0, 0, 23, 17, 33, 17, 37, 33,
+ 17, 33, 23, 7, 1, 53, 1, 23, 7, 33, 17, 33, 6, 4,197,251,173, 3,225,252,238,160, 90,254,235, 1, 21, 90,160, 3, 18,252,
+ 31,204, 7,109,248,147,114, 2,207,160, 90, 1, 21,110, 1, 21, 90,160, 3, 22, 0, 3, 0, 6,255, 52, 4,203, 6,161, 0, 3,
+ 0, 10, 0, 17, 0, 0, 5, 33, 17, 33, 3, 17, 1, 39, 55, 33, 17, 1, 17, 33, 17, 33, 39, 55, 4,203,251, 59, 4,197,114,254,
+235, 90,160,252,238, 3,225,252, 31, 3, 18,160, 90,204, 7,109,249, 5, 2,234,254,235, 90,160,253, 49, 3, 88, 3, 49,252,234,
+160, 90, 0, 0, 0, 3, 0, 6,255,196, 4,203, 5,213, 0, 8, 0, 30, 0, 39, 0, 0, 19, 16, 23, 22, 51, 50, 55, 1, 6, 1,
+ 6, 35, 34, 39, 36, 17, 16, 37, 39, 51, 23, 54, 51, 50, 23, 4, 17, 16, 5, 19, 35, 9, 1, 54, 17, 16, 39, 38, 35, 34,128,244,
+122,122, 61, 62,254,108,207, 2,150, 87, 87,153,152,254,207, 1, 21,115,191, 80, 89, 88,152,153, 1, 50,254,231,129,190,254,118,
+ 1,148,210,245,122,122, 62, 2,220,254,231,141, 71, 18, 3,106,140,252,178, 29, 88,176, 1, 96, 1, 79,176,250,174, 29, 88,176,
+254,160,254,175,176,254,233, 4,242,252,149,140, 1, 5, 1, 25,141, 71, 0, 0, 0, 3, 0, 37,254,162, 4,172, 7, 51, 0, 11,
+ 0, 14, 0, 17, 0, 0, 1, 17, 51, 17, 51, 1, 33, 17, 35, 17, 33, 1, 19, 17, 3, 33, 51, 3, 2, 28,152, 47, 1,201,254, 8,
+152,254, 9, 1,201, 46,246, 1,142,246,246, 5,213, 1, 94,254,162,250, 43,254,162, 1, 94, 5,213,250,213, 3,107,252,149, 3,
+107, 0, 0, 0, 0, 3, 0, 6,255, 52, 4,203, 6,161, 0, 4, 0, 8, 0, 14, 0, 0, 19, 17, 9, 1, 17, 55, 17, 33, 17, 19,
+ 17, 33, 17, 1, 35,120, 1,240, 1,241,114,251, 59,114, 3,225,254, 99,166, 6, 47,254,237,251,179, 4, 75, 1, 21,114,248,147,
+ 7,109,252,236,252, 25, 3,229,252,117, 0, 0, 0, 4, 0, 6,255, 52, 4,203, 6,161, 0, 2, 0, 6, 0, 11, 0, 17, 0, 0,
+ 37, 9, 2, 17, 33, 17, 37, 33, 53, 48, 33, 53, 1, 51, 1, 17, 33, 3,138,254,222,254,222,254,192, 4,197,251,173, 3,225,252,
+ 31, 1,130,221, 1,130,252, 31,170, 4,121,251,135,254,138, 7,109,248,147,114, 90, 91, 5,122,250,134, 5,212, 0, 3, 0, 6,
+255, 52, 4,203, 6,161, 0, 3, 0, 10, 0, 17, 0, 0, 19, 33, 17, 33, 37, 33, 17, 33, 1, 7, 39, 3, 17, 7, 39, 1, 33, 17,
+ 6, 4,197,251, 59, 2,180, 1,159,254, 71, 1, 20, 90,160,164,160, 90, 1, 20,254, 72, 6,161,248,147,114, 6,137,254,236, 90,
+160,250, 69, 5,187,160, 90, 1, 20,249,119, 0, 0, 3, 0, 37,254,162, 4,172, 7, 51, 0, 11, 0, 14, 0, 17, 0, 0, 33, 35,
+ 1, 33, 17, 51, 17, 33, 1, 35, 17, 35, 17, 35, 27, 1, 17, 19, 2, 28, 46,254, 55, 1,247,152, 1,248,254, 55, 47,152,246,246,
+152,246, 5,213, 1, 94,254,162,250, 43,254,162, 6,137,252,149, 3,107,252,149, 3,107, 0, 0, 0, 3, 0, 6,255, 52, 4,203,
+ 6,161, 0, 4, 0, 8, 0, 14, 0, 0, 23, 33, 17, 9, 2, 33, 17, 33, 9, 1, 51, 1, 17, 33,120, 3,225,254, 15,254, 16, 4,
+ 83,251, 59, 4,197,251,173, 1,158,166, 1,157,252, 31, 90, 1, 21, 4, 75,251,179,254,123, 7,109,251,167, 3,141,252,117, 3,
+229, 0, 0, 0, 0, 4, 0, 6,255, 52, 4,203, 6,161, 0, 2, 0, 6, 0, 12, 0, 16, 0, 0, 1, 33, 9, 1, 17, 33, 17, 37,
+ 33, 17, 1, 35, 1, 53, 33, 53, 33, 3,138,253,188, 1, 34,253,158, 4,197,251,173, 3,225,254,126,221,254,126, 3,225,252, 31,
+ 5, 43,251,135,254,130, 7,109,248,147,114, 5,212,250,134, 5,122, 91, 90, 0, 0, 3, 0, 6,255, 52, 4,203, 6,161, 0, 3,
+ 0, 10, 0, 17, 0, 0, 23, 17, 33, 17, 1, 17, 55, 23, 1, 33, 17, 41, 1, 17, 33, 1, 55, 23, 6, 4,197,253,239,160, 90,254,
+236, 1,185,253,189,254, 98, 1,184,254,236, 90,160,204, 7,109,248,147, 6,251,250, 69,160, 90,254,236, 6,137,249,119, 1, 20,
+ 90,160, 0, 0,255,255, 1, 0,255, 52, 3,209, 5,213, 16, 38, 11,192, 0, 0, 16, 6, 0, 10, 0, 0, 0, 0,255,255, 0, 6,
+255, 52, 4,203, 5,213, 16, 38, 11,191, 0, 0, 16, 6, 2,209, 0, 0, 0, 0,255,255, 0, 6,255, 52, 4,203, 5, 63, 16, 38,
+ 11,191, 0, 0, 16, 7, 9, 33, 0, 0, 0,200,255,255, 1, 0,255, 52, 3,209, 3,233, 16, 38, 11,192, 0, 0, 16, 6, 11,193,
+ 0, 0, 0, 0,255,255, 0, 6,255, 52, 4,203, 5, 68, 16, 38, 11,191, 0, 0, 16, 7, 9, 37, 0, 0, 0,200,255,255, 0, 6,
+255, 52, 4,203, 6,161, 16, 38, 0, 10, 0, 0, 16, 6, 8, 66, 0, 0, 0, 0,255,255,255,236, 0, 90, 4,229, 5, 94, 16, 39,
+ 9, 73, 0, 0, 0,200, 16, 6, 7,209, 0, 0,255,255, 0, 6,255, 52, 4,203, 6,161, 16, 38, 0, 29, 0, 0, 16, 6, 8, 66,
+ 0, 0, 0, 0,255,255, 1, 8, 1,155, 3,201, 5, 22, 16, 39, 11,194, 0, 0,255, 6, 16, 6, 7,209, 0, 0,255,255, 1, 63,
+ 1,212, 3,145, 5, 72, 16, 39, 11,194, 0, 0,255, 56, 16, 6, 11,193, 0, 0,255,255, 0, 6, 0,116, 4,203, 6,166, 16, 39,
+ 11,194, 0, 0, 0,150, 16, 7, 9, 37, 0, 0, 0,200, 0, 0,255,255, 0, 88, 1,236, 4,121, 5, 72, 16, 39, 11,194, 0, 0,
+255, 56, 16, 6, 0, 97, 0, 0,255,255, 0, 88, 0,141, 4,121, 5, 72, 16, 39, 11,194, 0, 0,255, 56, 16, 6, 0, 33, 0, 0,
+ 0, 3, 0, 37, 0, 0, 4,172, 5,213, 0, 10, 0, 32, 0, 42, 0, 0, 1, 33, 19, 22, 23, 22, 23, 22, 23, 22, 23, 37, 21, 6,
+ 7, 6, 7, 3, 35, 3, 6, 7, 6, 7, 53, 54, 55, 3, 33, 3, 54, 55, 54, 5, 27, 1, 38, 39, 38, 39, 38, 39, 38, 3,170,253,
+124,122, 42, 40, 50, 74, 11, 22, 69, 60, 1,105, 75, 72, 35, 38,186,245,217, 23, 22, 71, 73, 74, 69,194, 4,135,216, 11, 11, 69,
+253,162,151,124, 45, 50, 23, 10, 77, 51, 10, 5, 43,254, 79, 2, 9, 11, 31, 5, 10, 33, 13,114,174, 59, 27, 14, 7,253,159, 2,
+198, 6, 10, 29, 63,174, 57, 27, 2,121,253, 63, 5, 5, 30,112,253,230, 1,184, 13, 22, 10, 4, 33, 12, 2, 0, 0, 3, 0, 88,
+255,227, 4,121, 5,240, 0, 23, 0, 42, 0, 61, 0, 0, 0, 32, 23, 22, 19, 54, 55, 21, 6, 7, 2, 7, 6, 32, 39, 38, 3, 6,
+ 7, 53, 54, 55, 18, 55, 37, 34, 7, 6, 7, 54, 51, 50, 22, 23, 22, 23, 22, 51, 50, 55, 2, 39, 38, 1, 18, 23, 22, 51, 50, 55,
+ 54, 55, 6, 35, 34, 39, 38, 39, 46, 1, 35, 34, 1,121, 1,222,123,104, 15, 24, 24, 23, 23, 9,112,123,254, 34,122,105, 15, 23,
+ 24, 23, 23, 9,112, 1,105,141, 69, 53, 13, 27, 28, 53,100, 74, 11, 22,116, 93, 16, 17, 3, 66, 70,254, 90, 3, 67, 69,141,142,
+ 70, 52, 13, 22, 23, 90,113, 23, 10, 77,103, 51, 23, 5,240,196,167,254,208, 17, 20,174, 18, 15,254,176,180,196,196,168, 1, 49,
+ 17, 21,174, 18, 15, 1, 80,179, 36,152,115,206, 3, 22, 31, 5, 10, 55, 2, 1, 37,146,152,253,130,254,219,146,152,152,115,206,
+ 2, 51, 10, 4, 33, 24, 0, 0, 0, 1, 0, 88,254,162, 4,121, 7, 51, 0, 31, 0, 0, 1, 21, 14, 1, 35, 34, 39, 17, 35, 17,
+ 38, 39, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 23, 22, 23, 17, 51, 17, 22, 51, 50, 54, 4,121, 75,143, 79, 71, 85,152, 31, 25,
+ 52, 51, 79,141, 73, 78,146, 83, 53, 50, 19, 23,152, 94, 78, 70,137, 3,122,174, 59, 55, 32,252, 40, 4, 21, 11, 6, 12, 59, 63,
+174, 60, 54, 11, 4, 7, 3,207,251,243, 39, 61, 0, 2, 1, 0,254,225, 3,209, 4, 39, 0, 3, 0, 17, 0, 0, 1, 51, 17, 35,
+ 19, 51, 21, 7, 33, 21, 33, 7, 35, 55, 35, 53, 51, 55, 1,233,252,252, 13,252, 96, 1, 63,254,135, 43,154, 21,168,198, 48, 4,
+ 39,254,209,254, 55,207,186,114, 83, 83,114,186, 0, 3, 0, 6,255, 52, 4,203, 6,161, 0, 3, 0, 7, 0, 27, 0, 0, 23, 33,
+ 17, 33, 3, 17, 33, 17, 1, 33, 19, 23, 7, 51, 21, 33, 7, 33, 21, 33, 3, 39, 55, 35, 53, 33, 55, 33,120, 3,225,252, 31,114,
+ 4,197,251,247, 2, 5,197,100,131,162,254,245,147, 1,158,253,251,199,100,131,160, 1, 8,147,254,101, 90, 6,137,249, 5, 7,
+109,248,147, 4,110, 1, 59,102,213,170,236,172,254,197,104,211,172,236, 0, 0,255,255, 0, 6,255, 52, 4,203, 6,161, 16, 38,
+ 0, 34, 0, 0, 16, 6, 8, 66, 0, 0, 0, 0,255,255, 1, 54, 0, 0, 3,207, 4, 96, 16, 6, 2,245, 0, 0,255,255, 0,190,
+254, 86, 4, 84, 4,124, 16, 6, 2,253, 0, 0,255,255, 0, 70,255,227, 4,140, 4, 96, 16, 6, 3, 5, 0, 0,255,255, 0, 6,
+255, 52, 4,203, 4,122, 16, 38, 11,191, 0, 0, 16, 6, 2,237, 0, 0, 0, 0,255,255, 0,156,255, 52, 4, 53, 4,123, 16, 38,
+ 11,190, 0, 0, 16, 6, 3, 34, 0, 0, 0, 0,255,255, 1, 0,255, 52, 3,209, 4, 96, 16, 38, 11,192, 0, 0, 16, 6, 2,245,
+ 0, 0, 0, 0,255,255, 0, 6,255, 52, 4,203, 4, 96, 16, 38, 11,191, 0, 0, 16, 6, 3, 5, 0, 0, 0, 0,255,255, 0, 70,
+255,230, 4,149, 4,122, 16, 6, 2,237, 0, 0, 0, 1, 0, 26,254, 46, 4,183, 0,181, 0, 11, 0, 33,183, 6, 6, 10, 8, 5,
+ 6, 1, 3, 47,220,236, 47,220,236, 49, 0,183, 0,182, 6, 9, 2,182, 7, 4, 47, 60,236, 50,220,236, 48, 19, 17, 35, 53, 33,
+ 17, 33, 17, 33, 21, 35, 17,225,199, 1,111, 1,191, 1,111,199,254, 46, 1,218,173,254, 37, 1,219,173,254, 38, 0, 3, 0, 72,
+255,211, 4,136, 4, 58, 0, 5, 0, 17, 0, 48, 0, 0, 5, 1, 55, 9, 1, 23, 37, 35, 34, 6, 21, 20, 22, 51, 50, 54, 61, 1,
+ 55, 17, 35, 53, 14, 1, 35, 34, 38, 53, 52, 54, 59, 1, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 23, 22, 23, 30, 1, 2,
+104,253,224, 72, 1,216, 1,216, 72,254, 24, 35, 91, 93, 69, 62, 86, 99,105,105, 33,102, 72, 97,116,142,138,140, 76, 84, 53,109,
+ 52, 58,106, 50, 79, 56, 53, 37, 22, 18, 45, 2, 45, 74,254, 28, 1,228, 74,243, 63, 63, 56, 63,118,104, 23, 43,254,154, 93, 56,
+ 53,108, 91,104,109, 16, 75, 68, 30, 29,103, 21, 22, 23, 22, 47, 28, 82, 0, 0, 0, 6, 0, 6, 0,218, 4,203, 4, 58, 0, 3,
+ 0, 7, 0, 11, 0, 15, 0, 27, 0, 57, 0, 0, 1, 51, 53, 35, 23, 51, 53, 35, 5, 51, 53, 35, 1, 33, 53, 33, 1, 35, 34, 6,
+ 21, 20, 22, 51, 50, 54, 61, 1, 55, 17, 35, 53, 14, 1, 35, 34, 38, 53, 52, 54, 59, 1, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1,
+ 51, 50, 22, 23, 30, 1, 3, 97,115,115,170,115,115,254,172,115,115, 2, 20,251, 59, 4,197,252,183, 35, 91, 93, 69, 62, 86, 99,
+105,105, 33,102, 72, 97,116,142,138,140, 76, 84, 53,109, 52, 58,106, 50, 79,112, 34, 22, 18, 1,184,127,127,127,127,127,254,163,
+114, 1,167, 63, 63, 56, 63,118,104, 23, 43,254,154, 93, 56, 53,108, 91,104,109, 16, 75, 68, 30, 29,103, 21, 22, 46, 46, 28, 82,
+ 0, 6, 0, 6, 0,218, 4,203, 4, 58, 0, 3, 0, 7, 0, 19, 0, 49, 0, 61, 0, 91, 0, 0, 37, 53, 33, 21, 33, 53, 33, 21,
+ 3, 35, 34, 6, 21, 20, 22, 51, 50, 54, 61, 1, 55, 17, 35, 53, 14, 1, 35, 34, 38, 53, 52, 54, 59, 1, 53, 52, 38, 35, 34, 6,
+ 7, 53, 62, 1, 51, 50, 22, 23, 30, 1, 5, 35, 34, 6, 21, 20, 22, 51, 50, 54, 55, 53, 55, 17, 35, 53, 14, 1, 35, 34, 38, 53,
+ 52, 54, 59, 1, 53, 46, 1, 35, 34, 6, 7, 53, 62, 1, 51, 50, 22, 23, 30, 1, 2,155, 2, 48,251, 59, 2, 48,180, 35, 91, 93,
+ 69, 62, 86, 99,105,105, 33,102, 72, 97,116,142,138,140, 76, 84, 53,109, 52, 58,106, 50, 79,112, 34, 22, 18, 1,127, 34, 91, 93,
+ 69, 62, 86, 98, 1,105,105, 34,101, 73, 97,115,142,138,140, 1, 76, 83, 53,109, 52, 58,106, 50, 79,112, 34, 22, 18,218,114,114,
+114,114, 2, 25, 63, 63, 56, 63,118,104, 23, 43,254,154, 93, 56, 53,108, 91,104,109, 16, 75, 68, 30, 29,103, 21, 22, 46, 46, 28,
+ 82,125, 63, 63, 56, 63,118,104, 23, 43,254,154, 93, 56, 53,108, 91,104,109, 16, 75, 68, 30, 29,103, 21, 22, 46, 46, 28, 82, 0,
+ 0, 8, 0, 6, 1,107, 4,203, 4,138, 0, 30, 0, 42, 0, 46, 0, 50, 0, 54, 0, 58, 0, 62, 0, 66, 0, 0, 1, 17, 35, 53,
+ 14, 1, 35, 34, 38, 53, 52, 54, 59, 1, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51, 50, 23, 22, 23, 30, 1, 7, 35, 34, 6, 21,
+ 20, 22, 51, 50, 54, 61, 1, 1, 21, 37, 61, 1, 33, 21, 33, 17, 37, 21, 5, 45, 1, 21, 5, 21, 33, 21, 33, 21, 5, 21, 37, 3,
+113,105, 33,102, 72, 97,116,142,138,140, 76, 84, 53,109, 52, 58,106, 50, 79, 56, 53, 37, 22, 18,209, 35, 91, 93, 69, 62, 86, 99,
+ 1,202,254,212, 1, 44,254,212, 1, 44,254,212,253,147,254,212, 1, 44,254,212, 1, 44,254,212, 1, 44, 3, 30,254,154, 93, 56,
+ 53,108, 91,104,109, 16, 75, 68, 30, 29,103, 21, 22, 23, 22, 47, 28, 82,125, 63, 63, 56, 63,118,104, 23,254,241,121,140,121,188,
+114, 1, 68,140,121,140,121,140,121,140, 89,114, 74,140,121,140, 0, 7, 0, 82, 0, 56, 4,126, 4,207, 0, 52, 0, 60, 0, 68,
+ 0, 76, 0, 84, 0, 90, 0, 96, 0, 0, 37, 35, 53, 38, 39, 38, 39, 38, 39, 7, 39, 55, 38, 53, 52, 55, 53, 39, 55, 23, 54, 55,
+ 54, 55, 54, 55, 53, 51, 21, 22, 23, 22, 23, 22, 23, 55, 23, 7, 23, 22, 21, 20, 7, 21, 23, 7, 39, 6, 7, 6, 7, 6, 7, 53,
+ 54, 55, 54, 55, 54, 55, 39, 17, 21, 55, 38, 39, 38, 39, 38, 39, 6, 7, 6, 7, 6, 7, 23, 17, 53, 7, 22, 23, 22, 23, 22, 39,
+ 55, 39, 6, 21, 20, 37, 7, 23, 54, 53, 52, 2,154,100, 51, 47, 68, 57, 19, 15,177, 50,176, 28, 28,176, 50,177, 16, 18, 57, 68,
+ 47, 51,100, 52, 46, 69, 57, 18, 15,177, 50,176, 1, 28, 28,175, 50,176, 16, 18, 57, 69, 46, 52, 31, 29, 50, 42, 9, 7,168,168,
+ 7, 9, 42, 50, 29,131, 31, 28, 50, 42, 9, 8,168,168, 8, 9, 42, 50, 28,188,169,169, 16, 2, 42,169,169, 17, 56,203, 6, 20,
+ 29, 56, 19, 19,102, 87,102, 69, 79, 80, 68, 1,102, 87,103, 20, 19, 56, 29, 20, 6,203,203, 6, 20, 29, 56, 18, 20,102, 87,101,
+ 2, 68, 80, 79, 69, 1,101, 87,102, 20, 18, 56, 29, 20, 6,103, 5, 12, 21, 42, 9, 9, 97, 1,112,195, 97, 9, 9, 42, 21, 12,
+ 5, 5, 12, 21, 42, 9, 9, 97,254,144,195, 97, 9, 9, 42, 21, 12,179, 98, 97, 46, 52, 51,149, 97, 98, 45, 52, 53, 0, 0, 0,
+ 0, 4, 0, 70, 0, 94, 4,138, 4,162, 0, 15, 0, 30, 0, 39, 0, 48, 0, 0, 18, 52, 62, 2, 50, 30, 2, 20, 14, 2, 34, 46,
+ 1, 19, 51, 27, 1, 51, 38, 39, 46, 2, 34, 14, 1, 7, 6, 5, 35, 3, 54, 55, 62, 1, 55, 54, 1, 3, 35, 22, 23, 30, 1, 23,
+ 22, 70, 86,147,202,222,202,147, 86, 86,147,202,222,202,147, 28,240,192,193,239, 7, 24, 34,118,160,178,160,118, 34, 24, 3, 90,
+164,207, 56, 51, 80,118, 34, 25,254, 24,206,165, 7, 25, 34,118, 80, 51, 2, 17,222,202,147, 86, 86,147,202,222,202,147, 86, 86,
+147, 1,110,254,152, 1,104, 60, 56, 80,118, 68, 68,118, 80, 56,162,254,130, 8, 22, 34,118, 80, 57,254,193, 1,126, 63, 57, 80,
+118, 34, 22, 0, 0, 5, 0, 70, 0, 94, 4,138, 4,162, 0, 2, 0, 18, 0, 28, 0, 38, 0, 48, 0, 0, 1, 19, 33, 0, 52, 62,
+ 2, 50, 30, 2, 20, 14, 2, 34, 46, 1, 18, 20, 30, 1, 23, 22, 23, 1, 6, 7, 55, 33, 38, 39, 46, 1, 34, 6, 7, 6, 5, 1,
+ 54, 55, 62, 2, 52, 39, 38, 2,104,243,254, 26,254,209, 86,147,202,222,202,147, 86, 86,147,202,222,202,147, 25, 68,118, 80, 52,
+ 55,254,180, 4, 3, 57, 2,176, 17, 19, 59,160,178,160, 59, 19, 2,209,254,180, 55, 52, 80,118, 68, 34, 3, 1, 77, 1,199,254,
+253,222,202,147, 86, 86,147,202,222,202,147, 86, 86,147, 1,146,178,160,118, 34, 22, 8, 2,105, 8, 9, 99, 21, 19, 59, 68, 68,
+ 59, 19,103,253,151, 8, 22, 34,118,160,178, 80, 9, 0, 0, 0, 0, 3, 0, 70, 0, 94, 4,138, 4,162, 0, 2, 0, 9, 0, 37,
+ 0, 0, 1, 55, 39, 23, 1, 7, 1, 7, 3, 5, 1, 51, 20, 30, 2, 50, 62, 2, 52, 46, 2, 35, 53, 50, 30, 2, 20, 14, 2, 34,
+ 46, 2, 1, 5,145,174,205, 1,238, 86,254, 18,151, 70, 1,202,253,250,111, 68,118,160,178,160,118, 68, 68,118,160, 89,111,202,
+147, 86, 86,147,202,222,202,147, 86, 3, 83,146, 28,119,254, 18, 86, 1,238,151, 1,202, 70,254, 95, 89,160,118, 68, 68,118,160,
+178,160,118, 68,111, 86,147,202,222,202,147, 86, 86,147,202, 0, 0, 2, 0, 6,255, 52, 4,203, 6,161, 0, 3, 0, 7, 0, 0,
+ 23, 33, 17, 33, 3, 17, 33, 17,120, 3,225,252, 31,114, 4,197, 90, 6,137,249, 5, 7,109,248,147, 0, 0, 0, 0, 1, 1, 24,
+253,240, 3,184, 7,134, 0, 11, 0, 0, 1, 35, 53, 16, 19, 18, 19, 51, 0, 3, 2, 17, 1,219,195,160,186,166,160,254,252, 90,
+127,253,240,234, 3,151, 1,226, 2, 48, 1, 3,253,243,254,134,253,238,252,237, 0, 1, 1, 24,253,252, 1,219, 7,137, 0, 3,
+ 0, 0, 1, 51, 17, 35, 1, 24,195,195, 7,137,246,115, 0, 0, 0, 1, 1, 24,254, 20, 3,184, 7,137, 0, 11, 0, 0, 1, 21,
+ 16, 19, 18, 19, 35, 2, 3, 2, 17, 53, 1,219,127,147,203,160,208,144,160, 7,137,234,252,165,254, 87,254, 20,254,101, 1, 69,
+ 1,238, 2, 37, 3, 51,234, 0, 0, 1, 1, 25,253,240, 3,185, 7,134, 0, 11, 0, 0, 1, 53, 16, 3, 2, 1, 51, 18, 19, 18,
+ 17, 21, 2,246,127, 90,254,252,160,166,186,160,253,240,234, 3, 19, 2, 18, 1,122, 2, 13,254,253,253,208,254, 30,252,105,234,
+ 0, 1, 2,246,253,252, 3,185, 7,137, 0, 4, 0, 0, 1, 17, 35, 17, 48, 3,185,195, 7,137,246,115, 9,141, 0, 1, 1, 25,
+254, 20, 3,185, 7,137, 0, 11, 0, 0, 1, 51, 21, 16, 3, 2, 3, 35, 18, 19, 18, 17, 2,246,195,160,144,208,160,203,147,127,
+ 7,137,234,252,205,253,219,254, 18,254,187, 1,155, 1,236, 1,169, 3, 91, 0, 0, 1, 1, 24,253,252, 3,184, 7,109, 0, 5,
+ 0, 0, 1, 35, 17, 33, 21, 33, 1,219,195, 2,160,254, 35,253,252, 9,113,195, 0, 1, 1, 24,253,252, 1,219, 7,137, 0, 3,
+ 0, 0, 1, 51, 17, 35, 1, 24,195,195, 7,137,246,115, 0, 0, 0, 1, 1, 24,254, 20, 3,184, 7,137, 0, 5, 0, 0, 1, 17,
+ 33, 21, 33, 17, 1,219, 1,221,253, 96, 7,137,247, 78,195, 9,117, 0, 0, 0, 0, 1, 1, 24,253,252, 3,184, 7,109, 0, 5,
+ 0, 0, 1, 17, 33, 53, 33, 17, 2,245,254, 35, 2,160,253,252, 8,174,195,246,143, 0, 0, 0, 0, 1, 2,245,253,252, 3,184,
+ 7,122, 0, 3, 0, 0, 1, 51, 17, 35, 2,245,195,195, 7,122,246,130, 0, 0, 0, 1, 1, 24,254, 20, 3,184, 7,122, 0, 5,
+ 0, 0, 1, 51, 17, 33, 53, 33, 2,245,195,253, 96, 1,221, 7,122,246,154,195, 0, 1, 2, 12,253,234, 4,193, 7,109, 0, 13,
+ 0, 0, 1, 35, 17, 52, 55, 54, 51, 33, 21, 33, 34, 7, 6, 21, 2,198,186,111,121,186, 1, 19,254,231,101, 68, 57,253,234, 7,
+117,223,145,158,176,102, 87,153, 0, 1, 0, 17,253,252, 2,198, 7,134, 0, 24, 0, 0, 1, 22, 23, 22, 25, 1, 35, 17, 16, 39,
+ 38, 37, 39, 53, 51, 32, 55, 54, 25, 1, 51, 17, 16, 7, 6, 1,253, 58, 42,101,186,110, 75,254,251, 61, 61, 1, 3, 77,110,186,
+101, 40, 2,193, 32, 61,147,254, 67,253,232, 2, 12, 1,183, 95, 65, 4, 1,187, 69, 99, 1,179, 2, 12,253,232,254, 72,152, 60,
+ 0, 1, 2, 12,254, 20, 4,193, 7,134, 0, 13, 0, 0, 1, 17, 20, 23, 22, 51, 33, 21, 33, 34, 39, 38, 53, 17, 2,198, 57, 68,
+101, 1, 25,254,237,184,123,111, 7,134,248,148,154, 86,102,176,158,143,225, 7,100, 0, 0, 0, 0, 1, 2, 12,253,244, 2,198,
+ 7,140, 0, 3, 0, 0, 1, 35, 17, 51, 2,198,186,186,253,244, 9,152, 0, 0, 0, 1, 0, 16,253,234, 2,197, 7,109, 0, 13,
+ 0, 0, 1, 17, 52, 39, 38, 35, 33, 53, 33, 50, 23, 22, 21, 17, 2, 11, 57, 68,101,254,231, 1, 19,186,121,111,253,234, 7,125,
+153, 87,102,176,158,145,223,248,139, 0, 0, 0, 0, 1, 2, 11,253,252, 4,192, 7,134, 0, 24, 0, 0, 1, 38, 39, 38, 25, 1,
+ 51, 17, 16, 23, 22, 33, 51, 21, 7, 4, 7, 6, 25, 1, 35, 17, 16, 55, 54, 2,212, 60, 40,101,186,110, 77, 1, 3, 61, 61,254,
+251, 75,110,186,101, 42, 2,193, 33, 60,152, 1,184, 2, 24,253,244,254, 77, 99, 69,187, 1, 4, 65, 95,254, 73,253,244, 2, 24,
+ 1,189,147, 61, 0, 1, 0, 16,254, 20, 2,197, 7,134, 0, 13, 0, 0, 1, 51, 17, 20, 7, 6, 35, 33, 53, 33, 50, 55, 54, 53,
+ 2, 11,186,111,123,184,254,237, 1, 25,101, 68, 57, 7,134,248,156,225,143,158,176,102, 86,154, 0, 1, 2, 1,254, 0, 2,199,
+ 6, 40, 0, 3, 0, 0, 1, 17, 51, 17, 2, 1,198,254, 0, 8, 40,247,216, 0, 0, 2, 0, 25, 0,188, 4,143, 4,118, 0, 8,
+ 0, 17, 0, 0, 37, 9, 1, 21, 33, 17, 33, 17, 33, 1, 33, 53, 7, 23, 53, 33, 17, 35, 1,142,254,139, 1,117, 1,169, 1, 88,
+252,255, 1,239,253,194,194,194, 3, 10,204,188, 1,117, 1,117,201, 1,153,253, 15, 1, 18, 93,195,195, 93, 2,101, 0, 0, 0,
+ 0, 2, 0, 6, 0, 0, 4,203, 4,196, 0, 2, 0, 6, 0, 0, 1, 33, 9, 1, 33, 17, 33, 4,203,251, 59, 2, 98, 2, 99,251,
+ 59, 4,197, 2,160, 2, 36,251, 60, 1,248, 0, 0, 1, 0,150,254, 46, 4, 58, 0,181, 0, 7, 0, 28,183, 4, 6, 6, 9, 3,
+ 6, 1, 8, 16,220,236, 16,220,236, 49, 0,180, 0,182, 4, 6, 2, 47, 60,220,236, 48, 19, 17, 51, 17, 33, 17, 51, 17,150,168,
+ 2, 84,168,254, 46, 2,135,254, 37, 1,219,253,121, 0, 0, 0, 0, 1,255,236, 1,240, 4,229, 2,156, 0, 3, 0, 0, 3, 53,
+ 33, 21, 20, 4,249, 1,240,172,172, 0, 0, 0, 0, 1,255,236, 1,154, 4,229, 2,242, 0, 3, 0, 0, 3, 17, 33, 17, 20, 4,
+249, 1,154, 1, 88,254,168, 0, 0, 1, 2, 24,253,150, 2,184, 7,200, 0, 3, 0, 0, 1, 17, 51, 17, 2, 24,160,253,150, 10,
+ 50,245,206, 0, 0, 1, 1,200,253,150, 3, 8, 7,200, 0, 3, 0, 0, 1, 17, 33, 17, 1,200, 1, 64,253,150, 10, 50,245,206,
+ 0, 3,255,236, 1,240, 4,229, 2,156, 0, 3, 0, 7, 0, 11, 0, 0, 1, 53, 33, 21, 33, 53, 33, 21, 33, 53, 33, 21, 3,177,
+ 1, 52,252,239, 1, 41,252,239, 1, 52, 1,240,172,172,172,172,172,172, 0, 0, 0, 3,255,236, 1,154, 4,229, 2,242, 0, 3,
+ 0, 7, 0, 11, 0, 0, 1, 17, 33, 17, 33, 17, 33, 17, 33, 17, 33, 17, 3,177, 1, 52,252,239, 1, 41,252,239, 1, 52, 1,154,
+ 1, 88,254,168, 1, 88,254,168, 1, 88,254,168, 0, 3, 2, 24,253,150, 2,184, 7,200, 0, 3, 0, 7, 0, 11, 0, 0, 1, 17,
+ 51, 17, 3, 17, 51, 17, 3, 17, 51, 17, 2, 24,160,160,160,160,160,253,150, 3, 12,252,244, 3,192, 2,178,253, 78, 3,102, 3,
+ 12,252,244, 0, 0, 3, 1,200,253,150, 3, 8, 7,200, 0, 3, 0, 7, 0, 11, 0, 0, 1, 17, 33, 17, 1, 17, 33, 17, 1, 17,
+ 33, 17, 1,200, 1, 64,254,192, 1, 64,254,192, 1, 64,253,150, 3, 12,252,244, 3,192, 2,178,253, 78, 3,102, 3, 12,252,244,
+ 0, 4,255,235, 1,240, 4,229, 2,156, 0, 3, 0, 7, 0, 11, 0, 15, 0, 0, 3, 53, 51, 21, 51, 53, 51, 21, 51, 53, 51, 21,
+ 51, 53, 51, 21, 21,188,180,179,180,178,180,189, 1,240,172,172,172,172,172,172,172,172, 0, 0, 0, 4,255,236, 1,154, 4,230,
+ 2,242, 0, 3, 0, 7, 0, 11, 0, 15, 0, 0, 3, 17, 51, 17, 51, 17, 51, 17, 51, 17, 51, 17, 51, 17, 51, 17, 20,188,180,179,
+180,178,180,189, 1,154, 1, 88,254,168, 1, 88,254,168, 1, 88,254,168, 1, 88,254,168, 0, 0, 0, 4, 2, 24,253,150, 2,184,
+ 7,200, 0, 3, 0, 7, 0, 11, 0, 15, 0, 0, 1, 17, 51, 17, 3, 17, 51, 17, 3, 17, 51, 17, 3, 17, 51, 17, 2, 24,160,160,
+160,160,160,160,160, 5,150, 2, 50,253,206,248, 0, 2, 50,253,206, 5,115, 1,217,254, 39,253,115, 1,217,254, 39, 0, 0, 0,
+ 0, 4, 1,200,253,150, 3, 8, 7,200, 0, 3, 0, 7, 0, 11, 0, 15, 0, 0, 1, 17, 33, 17, 1, 17, 33, 17, 1, 17, 33, 17,
+ 1, 17, 33, 17, 1,200, 1, 64,254,192, 1, 64,254,192, 1, 64,254,192, 1, 64, 5,150, 2, 50,253,206,248, 0, 2, 50,253,206,
+ 5,115, 1,217,254, 39,253,115, 1,217,254, 39, 0, 1, 2, 24,253,150, 4,229, 2,156, 0, 5, 0, 0, 1, 17, 33, 21, 33, 17,
+ 2, 24, 2,205,253,211,253,150, 5, 6,172,251,166, 0, 0, 0, 0, 1, 2, 24,253,150, 4,229, 2,242, 0, 5, 0, 0, 1, 17,
+ 33, 17, 33, 17, 2, 24, 2,205,253,211,253,150, 5, 92,254,168,251,252, 0, 0, 0, 1, 1,200,253,150, 4,229, 2,156, 0, 5,
+ 0, 0, 1, 17, 33, 21, 33, 17, 1,200, 3, 29,254, 35,253,150, 5, 6,172,251,166, 0, 0, 0, 0, 1, 1,200,253,150, 4,229,
+ 2,242, 0, 5, 0, 0, 1, 17, 33, 17, 33, 17, 1,200, 3, 29,254, 35,253,150, 5, 92,254,168,251,252, 0, 0, 0, 1,255,236,
+253,150, 2,184, 2,156, 0, 5, 0, 0, 1, 17, 33, 53, 33, 17, 2, 24,253,212, 2,204,253,150, 4, 90,172,250,250, 0, 0, 0,
+ 0, 1,255,236,253,150, 2,184, 2,242, 0, 5, 0, 0, 1, 17, 33, 17, 33, 17, 2, 24,253,212, 2,204,253,150, 4, 4, 1, 88,
+250,164, 0, 0, 0, 1,255,236,253,150, 3, 8, 2,156, 0, 5, 0, 0, 1, 17, 33, 53, 33, 17, 1,200,254, 36, 3, 28,253,150,
+ 4, 90,172,250,250, 0, 0, 0, 0, 1,255,236,253,150, 3, 8, 2,242, 0, 5, 0, 0, 1, 17, 33, 17, 33, 17, 1,200,254, 36,
+ 3, 28,253,150, 4, 4, 1, 88,250,164, 0, 0, 0, 1, 2, 24, 1,240, 4,229, 7,200, 0, 5, 0, 0, 1, 17, 51, 17, 33, 21,
+ 2, 24,160, 2, 45, 1,240, 5,216,250,212,172, 0, 1, 2, 24, 1,154, 4,229, 7,200, 0, 5, 0, 0, 1, 17, 51, 17, 33, 17,
+ 2, 24,160, 2, 45, 1,154, 6, 46,251, 42,254,168, 0, 0, 0, 0, 1, 1,200, 1,240, 4,229, 7,200, 0, 5, 0, 0, 1, 17,
+ 33, 17, 33, 21, 1,200, 1, 64, 1,221, 1,240, 5,216,250,212,172, 0, 0, 0, 0, 1, 1,200, 1,154, 4,229, 7,200, 0, 5,
+ 0, 0, 1, 17, 33, 17, 33, 17, 1,200, 1, 64, 1,221, 1,154, 6, 46,251, 42,254,168, 0, 0, 0, 1,255,236, 1,240, 2,184,
+ 7,200, 0, 5, 0, 0, 3, 53, 33, 17, 51, 17, 20, 2, 44,160, 1,240,172, 5, 44,250, 40, 0, 0, 1,255,236, 1,154, 2,184,
+ 7,200, 0, 5, 0, 0, 3, 17, 33, 17, 51, 17, 20, 2, 44,160, 1,154, 1, 88, 4,214,249,210, 0, 1,255,236, 1,240, 3, 8,
+ 7,200, 0, 5, 0, 0, 3, 53, 33, 17, 33, 17, 20, 1,220, 1, 64, 1,240,172, 5, 44,250, 40, 0, 1,255,236, 1,154, 3, 8,
+ 7,200, 0, 5, 0, 0, 3, 17, 33, 17, 33, 17, 20, 1,220, 1, 64, 1,154, 1, 88, 4,214,249,210, 0, 0, 0, 0, 1, 2, 24,
+253,150, 4,229, 7,200, 0, 7, 0, 0, 1, 17, 51, 17, 33, 21, 33, 17, 2, 24,160, 2, 45,253,211,253,150, 10, 50,250,212,172,
+251,166, 0, 0, 0, 1, 2, 24,253,150, 4,229, 7,200, 0, 7, 0, 0, 1, 17, 51, 17, 33, 17, 33, 17, 2, 24,160, 2, 45,253,
+211,253,150, 10, 50,251, 42,254,168,251,252, 0, 0, 1, 1,200,253,150, 4,229, 7,200, 0, 9, 0, 0, 1, 17, 35, 17, 33, 17,
+ 33, 21, 33, 17, 2, 24, 80, 1, 64, 1,221,253,211,253,150, 4, 90, 5,216,250,212,172,251,166, 0, 1, 1,200,253,150, 4,229,
+ 7,200, 0, 9, 0, 0, 1, 17, 51, 17, 51, 17, 33, 21, 33, 17, 1,200, 80,160, 2, 45,254, 35,253,150, 5, 6, 5, 44,250,212,
+172,251,166, 0, 0, 1, 1,200,253,150, 4,229, 7,200, 0, 7, 0, 0, 1, 17, 33, 17, 33, 21, 33, 17, 1,200, 1, 64, 1,221,
+254, 35,253,150, 10, 50,250,212,172,251,166, 0, 0, 1, 1,200,253,150, 4,229, 7,200, 0, 9, 0, 0, 1, 17, 35, 17, 33, 17,
+ 33, 17, 33, 17, 2, 24, 80, 1, 64, 1,221,253,211,253,150, 4, 4, 6, 46,251, 42,254,168,251,252, 0, 0, 0, 0, 1, 1,200,
+253,150, 4,229, 7,200, 0, 9, 0, 0, 1, 17, 51, 17, 51, 17, 33, 17, 33, 17, 1,200, 80,160, 2, 45,254, 35,253,150, 5, 92,
+ 4,214,251, 42,254,168,251,252, 0, 1, 1,200,253,150, 4,229, 7,200, 0, 7, 0, 0, 1, 17, 33, 17, 33, 17, 33, 17, 1,200,
+ 1, 64, 1,221,254, 35,253,150, 10, 50,251, 42,254,168,251,252, 0, 1,255,236,253,150, 2,184, 7,200, 0, 7, 0, 0, 1, 17,
+ 33, 53, 33, 17, 51, 17, 2, 24,253,212, 2, 44,160,253,150, 4, 90,172, 5, 44,245,206, 0, 0, 0, 1,255,236,253,150, 2,184,
+ 7,200, 0, 7, 0, 0, 1, 17, 33, 17, 33, 17, 51, 17, 2, 24,253,212, 2, 44,160,253,150, 4, 4, 1, 88, 4,214,245,206, 0,
+ 0, 1,255,236,253,150, 3, 8, 7,200, 0, 9, 0, 0, 1, 17, 33, 53, 33, 17, 33, 17, 35, 17, 2, 24,253,212, 1,220, 1, 64,
+ 80,253,150, 4, 90,172, 5, 44,250, 40,251,166, 0, 1,255,236,253,150, 3, 8, 7,200, 0, 9, 0, 0, 1, 17, 33, 53, 33, 17,
+ 51, 17, 51, 17, 1,200,254, 36, 2, 44,160, 80,253,150, 4, 90,172, 5, 44,250,212,250,250, 0, 0, 1,255,236,253,150, 3, 8,
+ 7,200, 0, 7, 0, 0, 1, 17, 33, 53, 33, 17, 33, 17, 1,200,254, 36, 1,220, 1, 64,253,150, 4, 90,172, 5, 44,245,206, 0,
+ 0, 1,255,236,253,150, 3, 8, 7,200, 0, 9, 0, 0, 1, 17, 33, 17, 33, 17, 33, 17, 35, 17, 2, 24,253,212, 1,220, 1, 64,
+ 80,253,150, 4, 4, 1, 88, 4,214,249,210,251,252, 0, 0, 0, 0, 1,255,236,253,150, 3, 8, 7,200, 0, 9, 0, 0, 1, 17,
+ 33, 17, 33, 17, 51, 17, 51, 17, 1,200,254, 36, 2, 44,160, 80,253,150, 4, 4, 1, 88, 4,214,251, 42,250,164, 0, 1,255,236,
+253,150, 3, 8, 7,200, 0, 7, 0, 0, 1, 17, 33, 17, 33, 17, 33, 17, 1,200,254, 36, 1,220, 1, 64,253,150, 4, 4, 1, 88,
+ 4,214,245,206, 0, 1,255,236,253,150, 4,229, 2,156, 0, 7, 0, 0, 1, 17, 33, 53, 33, 21, 33, 17, 2, 24,253,212, 4,249,
+253,211,253,150, 4, 90,172,172,251,166, 0, 0, 0, 1,255,236,253,150, 4,229, 2,242, 0, 9, 0, 0, 1, 17, 33, 17, 33, 21,
+ 33, 21, 33, 17, 2, 24,253,212, 2,204, 2, 45,253,211,253,150, 4, 4, 1, 88, 86,172,251,166, 0, 1,255,236,253,150, 4,229,
+ 2,242, 0, 9, 0, 0, 1, 17, 33, 53, 33, 53, 33, 17, 33, 17, 2, 24,253,212, 2, 44, 2,205,253,211,253,150, 4, 90,172, 86,
+254,168,251,252, 0, 1,255,236,253,150, 4,229, 2,242, 0, 7, 0, 0, 1, 17, 33, 17, 33, 17, 33, 17, 2, 24,253,212, 4,249,
+253,211,253,150, 4, 4, 1, 88,254,168,251,252, 0, 1,255,236,253,150, 4,229, 2,156, 0, 7, 0, 0, 1, 17, 33, 53, 33, 21,
+ 33, 17, 1,200,254, 36, 4,249,254, 35,253,150, 4, 90,172,172,251,166, 0, 0, 0, 1,255,236,253,150, 4,229, 2,242, 0, 9,
+ 0, 0, 1, 17, 33, 17, 33, 21, 33, 21, 33, 17, 1,200,254, 36, 3, 28, 1,221,254, 35,253,150, 4, 4, 1, 88, 86,172,251,166,
+ 0, 1,255,236,253,150, 4,229, 2,242, 0, 9, 0, 0, 1, 17, 33, 53, 33, 53, 33, 17, 33, 17, 1,200,254, 36, 1,220, 3, 29,
+254, 35,253,150, 4, 90,172, 86,254,168,251,252, 0, 1,255,236,253,150, 4,229, 2,242, 0, 7, 0, 0, 1, 17, 33, 17, 33, 17,
+ 33, 17, 1,200,254, 36, 4,249,254, 35,253,150, 4, 4, 1, 88,254,168,251,252, 0, 1,255,236, 1,240, 4,229, 7,200, 0, 7,
+ 0, 0, 3, 53, 33, 17, 51, 17, 33, 21, 20, 2, 44,160, 2, 45, 1,240,172, 5, 44,250,212,172, 0, 1,255,236, 1,154, 4,229,
+ 7,200, 0, 9, 0, 0, 3, 17, 33, 17, 51, 17, 33, 21, 33, 21, 20, 2, 44,160, 2, 45,253,211, 1,154, 1, 88, 4,214,250,212,
+172, 86, 0, 0, 0, 1,255,236, 1,154, 4,229, 7,200, 0, 9, 0, 0, 3, 53, 33, 17, 51, 17, 33, 17, 33, 53, 20, 2, 44,160,
+ 2, 45,253, 51, 1,240,172, 5, 44,251, 42,254,168, 86, 0, 0, 0, 1,255,236, 1,154, 4,229, 7,200, 0, 7, 0, 0, 3, 17,
+ 33, 17, 51, 17, 33, 17, 20, 2, 44,160, 2, 45, 1,154, 1, 88, 4,214,251, 42,254,168, 0, 0, 0, 1,255,236, 1,240, 4,229,
+ 7,200, 0, 7, 0, 0, 3, 53, 33, 17, 33, 17, 33, 21, 20, 1,220, 1, 64, 1,221, 1,240,172, 5, 44,250,212,172, 0, 0, 0,
+ 0, 1,255,236, 1,154, 4,229, 7,200, 0, 9, 0, 0, 3, 17, 33, 17, 33, 17, 33, 21, 33, 21, 20, 1,220, 1, 64, 1,221,254,
+ 35, 1,154, 1, 88, 4,214,250,212,172, 86, 0, 0, 1,255,236, 1,154, 4,229, 7,200, 0, 9, 0, 0, 3, 53, 33, 17, 33, 17,
+ 33, 17, 33, 53, 20, 1,220, 1, 64, 1,221,252,227, 1,240,172, 5, 44,251, 42,254,168, 86, 0, 0, 1,255,236, 1,154, 4,229,
+ 7,200, 0, 7, 0, 0, 3, 17, 33, 17, 33, 17, 33, 17, 20, 1,220, 1, 64, 1,221, 1,154, 1, 88, 4,214,251, 42,254,168, 0,
+ 0, 1,255,236,253,150, 4,229, 7,200, 0, 11, 0, 0, 1, 17, 35, 17, 33, 53, 33, 17, 51, 17, 33, 21, 2,184,160,253,212, 2,
+ 44,160, 2, 45, 1,240,251,166, 4, 90,172, 5, 44,250,212,172, 0, 1,255,236,253,150, 4,229, 7,200, 0, 11, 0, 0, 1, 17,
+ 33, 17, 33, 17, 51, 17, 33, 21, 33, 17, 2, 24,253,212, 2, 44,160, 2, 45,253,211,253,150, 4, 4, 1, 88, 4,214,250,212,172,
+251,166, 0, 0, 0, 1,255,236,253,150, 4,229, 7,200, 0, 11, 0, 0, 1, 17, 33, 53, 33, 17, 51, 17, 33, 17, 33, 17, 2, 24,
+253,212, 2, 44,160, 2, 45,253,211,253,150, 4, 90,172, 5, 44,251, 42,254,168,251,252, 0, 0, 0, 1,255,236,253,150, 4,229,
+ 7,200, 0, 11, 0, 0, 1, 17, 33, 17, 33, 17, 51, 17, 33, 17, 33, 17, 2, 24,253,212, 2, 44,160, 2, 45,253,211,253,150, 4,
+ 4, 1, 88, 4,214,251, 42,254,168,251,252, 0, 0, 1,255,236,253,150, 4,229, 7,200, 0, 11, 0, 0, 1, 17, 33, 53, 33, 17,
+ 33, 17, 33, 21, 33, 17, 2, 24,253,212, 1,220, 1, 64, 1,221,253,211,253,150, 4, 90,172, 5, 44,250,212,172,251,166, 0, 0,
+ 0, 1,255,236,253,150, 4,229, 7,200, 0, 11, 0, 0, 1, 17, 33, 53, 33, 17, 51, 17, 33, 21, 33, 17, 1,200,254, 36, 2, 44,
+160, 2, 45,254, 35,253,150, 4, 90,172, 5, 44,250,212,172,251,166, 0, 0, 0, 0, 1,255,236,253,150, 4,229, 7,200, 0, 11,
+ 0, 0, 1, 17, 33, 53, 33, 17, 33, 17, 33, 21, 33, 17, 1,200,254, 36, 1,220, 1, 64, 1,221,254, 35,253,150, 4, 90,172, 5,
+ 44,250,212,172,251,166, 0, 0, 0, 1,255,236,253,150, 4,229, 7,200, 0, 13, 0, 0, 1, 17, 33, 17, 33, 17, 33, 17, 33, 21,
+ 33, 21, 35, 17, 2, 24,253,212, 1,220, 1, 64, 1,221,254, 35, 80,253,150, 4, 4, 1, 88, 4,214,250,212,172, 86,251,252, 0,
+ 0, 1,255,236,253,150, 4,229, 7,200, 0, 13, 0, 0, 1, 17, 35, 53, 33, 53, 33, 17, 33, 17, 33, 17, 33, 17, 2, 24, 80,254,
+ 36, 1,220, 1, 64, 1,221,253,211,253,150, 4, 4, 86,172, 5, 44,251, 42,254,168,251,252, 0, 0, 1,255,236,253,150, 4,229,
+ 7,200, 0, 13, 0, 0, 1, 17, 33, 17, 33, 17, 51, 17, 51, 21, 33, 21, 33, 17, 1,200,254, 36, 2, 44,160, 80, 1,221,254, 35,
+253,150, 4, 4, 1, 88, 4,214,251, 42, 86,172,251,166, 0, 0, 0, 1,255,236,253,150, 4,229, 7,200, 0, 13, 0, 0, 1, 17,
+ 33, 53, 33, 53, 51, 17, 51, 17, 33, 17, 33, 17, 1,200,254, 36, 1,220, 80,160, 2, 45,254, 35,253,150, 4, 90,172, 86, 4,214,
+251, 42,254,168,251,252, 0, 0, 0, 1,255,236,253,150, 4,229, 7,200, 0, 11, 0, 0, 1, 17, 33, 17, 33, 17, 33, 17, 33, 17,
+ 33, 17, 2, 24,253,212, 1,220, 1, 64, 1,221,253,211,253,150, 4, 4, 1, 88, 4,214,251, 42,254,168,251,252, 0, 1,255,236,
+253,150, 4,229, 7,200, 0, 11, 0, 0, 1, 17, 33, 17, 33, 17, 51, 17, 33, 17, 33, 17, 1,200,254, 36, 2, 44,160, 2, 45,254,
+ 35,253,150, 4, 4, 1, 88, 4,214,251, 42,254,168,251,252, 0, 0, 1,255,236,253,150, 4,229, 7,200, 0, 11, 0, 0, 1, 17,
+ 33, 17, 33, 17, 33, 17, 33, 21, 33, 17, 1,200,254, 36, 1,220, 1, 64, 1,221,254, 35,253,150, 4, 4, 1, 88, 4,214,250,212,
+172,251,166, 0, 0, 1,255,236,253,150, 4,229, 7,200, 0, 11, 0, 0, 1, 17, 33, 53, 33, 17, 33, 17, 33, 17, 33, 17, 1,200,
+254, 36, 1,220, 1, 64, 1,221,254, 35,253,150, 4, 90,172, 5, 44,251, 42,254,168,251,252, 0, 0, 1,255,236,253,150, 4,229,
+ 7,200, 0, 11, 0, 0, 1, 17, 33, 17, 33, 17, 33, 17, 33, 17, 33, 17, 1,200,254, 36, 1,220, 1, 64, 1,221,254, 35,253,150,
+ 4, 4, 1, 88, 4,214,251, 42,254,168,251,252, 0, 2,255,236, 1,240, 4,229, 2,156, 0, 3, 0, 7, 0, 0, 3, 53, 33, 21,
+ 51, 53, 33, 21, 20, 2, 44,160, 2, 45, 1,240,172,172,172,172, 0, 2,255,236, 1,154, 4,229, 2,242, 0, 3, 0, 7, 0, 0,
+ 1, 17, 33, 17, 33, 17, 33, 17, 2,184, 2, 45,251, 7, 2, 44, 1,154, 1, 88,254,168, 1, 88,254,168, 0, 0, 0, 2, 2, 24,
+253,150, 2,184, 7,200, 0, 3, 0, 7, 0, 0, 1, 17, 51, 17, 3, 17, 51, 17, 2, 24,160,160,160, 2,242, 4,214,251, 42,250,
+164, 4, 4,251,252, 0, 0, 0, 0, 2, 1,200,253,150, 3, 8, 7,200, 0, 3, 0, 7, 0, 0, 1, 17, 33, 17, 1, 17, 33, 17,
+ 1,200, 1, 64,254,192, 1, 64, 2,242, 4,214,251, 42,250,164, 4, 4,251,252, 0, 2,255,236, 1, 68, 4,229, 3, 72, 0, 3,
+ 0, 7, 0, 0, 3, 53, 33, 21, 1, 53, 33, 21, 20, 4,249,251, 7, 4,249, 2,156,172,172,254,168,172,172, 0, 0, 2, 1,120,
+253,150, 3, 88, 7,200, 0, 3, 0, 7, 0, 0, 1, 17, 51, 17, 51, 17, 51, 17, 1,120,160,160,160,253,150, 10, 50,245,206, 10,
+ 50,245,206, 0, 0, 1, 2, 24,253,150, 4,229, 3, 72, 0, 9, 0, 0, 1, 17, 33, 21, 33, 21, 33, 21, 33, 17, 2, 24, 2,205,
+253,211, 2, 45,253,211,253,150, 5,178,172,172,172,252, 82, 0, 0, 1, 1,120,253,150, 4,229, 2,156, 0, 9, 0, 0, 1, 17,
+ 33, 21, 33, 17, 35, 17, 35, 17, 1,120, 3,109,254,115,160,160,253,150, 5, 6,172,251,166, 4, 90,251,166, 0, 0, 2, 1,120,
+253,150, 4,229, 3, 72, 0, 5, 0, 11, 0, 0, 1, 17, 33, 21, 33, 17, 51, 17, 33, 21, 33, 17, 1,120, 3,109,253, 51,160, 2,
+ 45,254,115,253,150, 5,178,172,250,250, 4, 90,172,252, 82, 0, 0, 1,255,236,253,150, 2,184, 3, 72, 0, 9, 0, 0, 1, 17,
+ 33, 53, 33, 53, 33, 53, 33, 17, 2, 24,253,212, 2, 44,253,212, 2,204,253,150, 3,174,172,172,172,250, 78, 0, 0, 1,255,236,
+253,150, 3, 88, 2,156, 0, 9, 0, 0, 3, 53, 33, 17, 35, 17, 35, 17, 35, 17, 20, 3,108,160,160,160, 1,240,172,250,250, 4,
+ 90,251,166, 4, 90, 0, 0, 0, 0, 2,255,236,253,150, 3, 88, 3, 72, 0, 5, 0, 11, 0, 0, 1, 17, 33, 53, 33, 17, 33, 17,
+ 33, 53, 33, 17, 2,184,253, 52, 3,108,254, 32,254,116, 2, 44,253,150, 5, 6,172,250, 78, 3,174,172,251,166, 0, 1, 2, 24,
+ 1, 68, 4,229, 7,200, 0, 9, 0, 0, 1, 17, 51, 17, 33, 21, 33, 21, 33, 21, 2, 24,160, 2, 45,253,211, 2, 45, 1, 68, 6,
+132,251,128,172,172,172, 0, 0, 0, 1, 1,120, 1,240, 4,229, 7,200, 0, 9, 0, 0, 1, 17, 51, 17, 51, 17, 51, 17, 33, 21,
+ 1,120,160,160,160, 1,141, 1,240, 5,216,250,212, 5, 44,250,212,172, 0, 0, 0, 2, 1,120, 1, 68, 4,229, 7,200, 0, 5,
+ 0, 11, 0, 0, 1, 17, 51, 17, 33, 21, 1, 17, 51, 17, 33, 21, 2,184,160, 1,141,252,147,160, 2,205, 2,156, 5, 44,251,128,
+172,254,168, 6,132,250, 40,172, 0, 1,255,236, 1, 68, 2,184, 7,200, 0, 9, 0, 0, 3, 53, 33, 53, 33, 53, 33, 17, 51, 17,
+ 20, 2, 44,253,212, 2, 44,160, 1, 68,172,172,172, 4,128,249,124, 0, 0, 0, 0, 1,255,236, 1,240, 3, 88, 7,200, 0, 9,
+ 0, 0, 3, 53, 33, 17, 51, 17, 51, 17, 51, 17, 20, 1,140,160,160,160, 1,240,172, 5, 44,250,212, 5, 44,250, 40, 0, 0, 0,
+ 0, 2,255,236, 1, 68, 3, 88, 7,200, 0, 5, 0, 11, 0, 0, 3, 53, 33, 17, 51, 17, 1, 53, 33, 17, 51, 17, 20, 1,140,160,
+253,212, 2,204,160, 2,156,172, 4,128,250,212,254,168,172, 5,216,249,124, 0, 0, 1, 2, 24,253,150, 4,229, 7,200, 0, 11,
+ 0, 0, 1, 17, 51, 17, 33, 21, 33, 21, 33, 21, 33, 17, 2, 24,160, 2, 45,253,211, 2, 45,253,211,253,150, 10, 50,251,128,172,
+172,172,252, 82, 0, 2, 1,120,253,150, 4,229, 7,200, 0, 3, 0, 11, 0, 0, 1, 17, 51, 17, 51, 17, 51, 17, 33, 21, 33, 17,
+ 1,120,160,160,160, 1,141,254,115,253,150, 10, 50,245,206, 10, 50,250,212,172,251,166, 0, 0, 0, 3, 1,120,253,150, 4,229,
+ 7,200, 0, 5, 0, 9, 0, 15, 0, 0, 1, 17, 51, 17, 33, 21, 1, 17, 51, 17, 51, 17, 33, 21, 33, 17, 2,184,160, 1,141,252,
+147,160,160, 2, 45,254,115, 2,156, 5, 44,251,128,172,250,250, 10, 50,245,206, 4, 90,172,252, 82, 0, 0, 0, 0, 1,255,236,
+253,150, 2,184, 7,200, 0, 11, 0, 0, 1, 17, 33, 53, 33, 53, 33, 53, 33, 17, 51, 17, 2, 24,253,212, 2, 44,253,212, 2, 44,
+160,253,150, 3,174,172,172,172, 4,128,245,206, 0, 2,255,236,253,150, 3, 88, 7,200, 0, 7, 0, 11, 0, 0, 1, 17, 33, 53,
+ 33, 17, 51, 17, 51, 17, 51, 17, 1,120,254,116, 1,140,160,160,160,253,150, 4, 90,172, 5, 44,245,206, 10, 50,245,206, 0, 0,
+ 0, 3,255,236,253,150, 3, 88, 7,200, 0, 5, 0, 11, 0, 15, 0, 0, 3, 53, 33, 17, 51, 17, 3, 17, 33, 53, 33, 17, 51, 17,
+ 51, 17, 20, 1,140,160,160,254,116, 2, 44,160,160, 2,156,172, 4,128,250,212,250,250, 3,174,172,251,166, 10, 50,245,206, 0,
+ 0, 2,255,236,253,150, 4,229, 3, 72, 0, 7, 0, 11, 0, 0, 1, 17, 33, 53, 33, 21, 33, 17, 1, 53, 33, 21, 2, 24,253,212,
+ 4,249,253,211,253, 52, 4,249,253,150, 3,174,172,172,252, 82, 5, 6,172,172, 0, 1,255,236,253,150, 4,229, 2,156, 0, 11,
+ 0, 0, 3, 53, 33, 21, 33, 17, 35, 17, 35, 17, 35, 17, 20, 4,249,254,115,160,160,160, 1,240,172,172,251,166, 4, 90,251,166,
+ 4, 90, 0, 0, 0, 3,255,236,253,150, 4,229, 3, 72, 0, 3, 0, 9, 0, 15, 0, 0, 3, 53, 33, 21, 1, 17, 33, 53, 33, 17,
+ 51, 17, 33, 21, 33, 17, 20, 4,249,252,147,254,116, 2, 44,160, 2, 45,254,115, 2,156,172,172,250,250, 3,174,172,251,166, 4,
+ 90,172,252, 82, 0, 2,255,236, 1, 68, 4,229, 7,200, 0, 3, 0, 11, 0, 0, 3, 53, 33, 21, 1, 53, 33, 17, 51, 17, 33, 21,
+ 20, 4,249,251, 7, 2, 44,160, 2, 45, 1, 68,172,172, 1, 88,172, 4,128,251,128,172, 0, 0, 0, 1,255,236, 1,240, 4,229,
+ 7,200, 0, 11, 0, 0, 3, 53, 33, 17, 51, 17, 51, 17, 51, 17, 33, 21, 20, 1,140,160,160,160, 1,141, 1,240,172, 5, 44,250,
+212, 5, 44,250,212,172, 0, 0, 0, 3,255,236, 1, 68, 4,229, 7,200, 0, 3, 0, 9, 0, 15, 0, 0, 3, 53, 33, 21, 1, 53,
+ 33, 17, 51, 17, 51, 17, 51, 17, 33, 21, 20, 4,249,251, 7, 1,140,160,160,160, 1,141, 1, 68,172,172, 1, 88,172, 4,128,250,
+212, 5, 44,251,128,172, 0, 0, 0, 1,255,236,253,150, 4,229, 7,200, 0, 19, 0, 0, 1, 17, 33, 53, 33, 53, 33, 53, 33, 17,
+ 51, 17, 33, 21, 33, 21, 33, 21, 33, 17, 2, 24,253,212, 2, 44,253,212, 2, 44,160, 2, 45,253,211, 2, 45,253,211,253,150, 3,
+174,172,172,172, 4,128,251,128,172,172,172,252, 82, 0, 0, 0, 0, 1,255,236,253,150, 4,229, 7,200, 0, 19, 0, 0, 3, 53,
+ 33, 17, 51, 17, 51, 17, 51, 17, 33, 21, 33, 17, 35, 17, 35, 17, 35, 17, 20, 1,140,160,160,160, 1,141,254,115,160,160,160, 1,
+240,172, 5, 44,250,212, 5, 44,250,212,172,251,166, 4, 90,251,166, 4, 90, 0, 0, 4,255,236,253,150, 4,229, 7,200, 0, 5,
+ 0, 11, 0, 17, 0, 23, 0, 0, 1, 17, 33, 21, 33, 17, 33, 17, 33, 53, 33, 17, 1, 53, 33, 17, 51, 17, 51, 17, 51, 17, 33, 21,
+ 2,184, 2, 45,254,115,254, 32,254,116, 2, 44,253,212, 1,140,160,160,160, 1,141,253,150, 4, 90,172,252, 82, 3,174,172,251,
+166, 5, 6,172, 4,128,250,212, 5, 44,251,128,172, 0, 0, 0, 0, 1, 2, 24,253,150, 4,229, 2,156, 0, 12, 0, 0, 1, 17,
+ 52, 55, 54, 51, 33, 21, 33, 34, 6, 21, 17, 2, 24, 81, 91,168, 1,121,254,135, 89, 91,253,150, 3, 96,161,127,134,172,126,124,
+252,160, 0, 0, 0, 1,255,236,253,150, 2,184, 2,156, 0, 13, 0, 0, 1, 17, 52, 39, 38, 35, 33, 53, 33, 50, 23, 22, 21, 17,
+ 2, 24, 46, 45, 89,254,136, 1,120,168, 91, 81,253,150, 3, 96,126, 61, 63,172,134,120,168,252,160, 0, 0, 0, 0, 1,255,236,
+ 1,240, 2,184, 7,200, 0, 12, 0, 0, 3, 53, 33, 50, 54, 53, 17, 51, 17, 20, 7, 6, 35, 20, 1,120, 89, 91,160, 81, 91,168,
+ 1,240,172,126,124, 4, 50,251,206,168,120,134, 0, 1, 2, 24, 1,240, 4,229, 7,200, 0, 12, 0, 0, 1, 33, 34, 39, 38, 53,
+ 17, 51, 17, 20, 22, 51, 33, 4,229,254,135,168, 91, 81,160, 91, 89, 1,121, 1,240,134,120,168, 4, 50,251,206,124,126, 0, 0,
+ 0, 1,255,147,253,150, 5, 62, 7,200, 0, 3, 0, 0, 3, 1, 51, 1,109, 4,249,178,251, 7,253,150, 10, 50,245,206, 0, 0,
+ 0, 1,255,147,253,150, 5, 62, 7,200, 0, 3, 0, 0, 1, 35, 1, 51, 5, 62,178,251, 7,178,253,150, 10, 50, 0, 1,255,147,
+253,150, 5, 62, 7,200, 0, 11, 0, 0, 1, 35, 9, 1, 35, 9, 1, 51, 9, 1, 51, 1, 5, 62,178,253,220,253,221,178, 2,125,
+253,131,178, 2, 35, 2, 36,178,253,132,253,150, 4, 99,251,157, 5, 25, 5, 25,251,157, 4, 99,250,231, 0, 0, 0, 1,255,236,
+ 1,240, 2,124, 2,156, 0, 3, 0, 0, 3, 53, 33, 21, 20, 2,144, 1,240,172,172, 0, 0, 0, 0, 1, 2, 24, 2, 70, 2,184,
+ 7,200, 0, 3, 0, 0, 1, 17, 51, 17, 2, 24,160, 2, 70, 5,130,250,126, 0, 0, 1, 2,124, 1,240, 4,229, 2,156, 0, 3,
+ 0, 0, 1, 53, 33, 21, 2,124, 2,105, 1,240,172,172, 0, 0, 0, 1, 2, 24,253,150, 2,184, 2, 70, 0, 3, 0, 0, 1, 17,
+ 51, 17, 2, 24,160,253,150, 4,176,251, 80, 0, 0, 1,255,236, 1,154, 2,124, 2,242, 0, 3, 0, 0, 3, 17, 33, 17, 20, 2,
+144, 1,154, 1, 88,254,168, 0, 0, 1, 1,200, 2, 70, 3, 8, 7,200, 0, 3, 0, 0, 1, 17, 33, 17, 1,200, 1, 64, 2, 70,
+ 5,130,250,126, 0, 1, 2,124, 1,154, 4,229, 2,242, 0, 3, 0, 0, 1, 17, 33, 17, 2,124, 2,105, 1,154, 1, 88,254,168,
+ 0, 1, 1,200,253,150, 3, 8, 2, 70, 0, 3, 0, 0, 1, 17, 33, 17, 1,200, 1, 64,253,150, 4,176,251, 80, 0, 1,255,236,
+ 1,154, 4,229, 2,242, 0, 7, 0, 0, 3, 53, 33, 53, 33, 17, 33, 53, 20, 2,144, 2,105,253,151, 1,240,172, 86,254,168, 86,
+ 0, 1, 1,200,253,150, 3, 8, 7,200, 0, 7, 0, 0, 1, 17, 51, 17, 51, 17, 51, 17, 1,200, 80,160, 80,253,150, 4,176, 5,
+130,250,126,251, 80, 0, 0, 0, 0, 1,255,236, 1,154, 4,229, 2,242, 0, 7, 0, 0, 3, 17, 33, 21, 33, 21, 33, 21, 20, 2,
+144, 2,105,253,151, 1,154, 1, 88, 86,172, 86, 0, 1, 1,200,253,150, 3, 8, 7,200, 0, 7, 0, 0, 1, 17, 35, 17, 33, 17,
+ 35, 17, 2, 24, 80, 1, 64, 80,253,150, 4,176, 5,130,250,126,251, 80, 0, 0,255,255,255,236, 2, 20, 4,229, 6, 40, 16, 7,
+ 8,222, 0, 0, 4, 20, 0, 0, 0, 1,255,236,254, 0, 4,229,255, 5, 0, 3, 0, 0, 3, 17, 33, 17, 20, 4,249,254, 0, 1,
+ 5,254,251, 0, 0, 1,255,236,254, 0, 4,229, 0, 10, 0, 3, 0, 0, 3, 17, 33, 17, 20, 4,249,254, 0, 2, 10,253,246, 0,
+ 0, 1,255,236,254, 0, 4,229, 1, 15, 0, 3, 0, 0, 3, 17, 33, 17, 20, 4,249,254, 0, 3, 15,252,241, 0, 0, 1,255,236,
+254, 0, 4,229, 2, 20, 0, 3, 0, 0, 3, 17, 33, 17, 20, 4,249,254, 0, 4, 20,251,236, 0, 0, 1,255,236,254, 0, 4,229,
+ 3, 25, 0, 3, 0, 0, 3, 17, 33, 17, 20, 4,249,254, 0, 5, 25,250,231, 0, 0, 1,255,236,254, 0, 4,229, 4, 30, 0, 3,
+ 0, 0, 3, 17, 33, 17, 20, 4,249,254, 0, 6, 30,249,226, 0, 0, 1,255,236,254, 0, 4,229, 5, 35, 0, 3, 0, 0, 3, 17,
+ 33, 17, 20, 4,249,254, 0, 7, 35,248,221, 0, 0, 1,255,236,254, 0, 4,229, 6, 40, 0, 3, 0, 0, 3, 17, 33, 17, 20, 4,
+249,254, 0, 8, 40,247,216, 0, 0, 1,255,236,254, 0, 4, 70, 6, 40, 0, 3, 0, 0, 3, 17, 33, 17, 20, 4, 90,254, 0, 8,
+ 40,247,216, 0, 0, 1,255,236,254, 0, 3,167, 6, 40, 0, 3, 0, 0, 3, 17, 33, 17, 20, 3,186,254, 0, 8, 40,247,216, 0,
+ 0, 1,255,236,254, 0, 3, 8, 6, 40, 0, 3, 0, 0, 3, 17, 33, 17, 20, 3, 27,254, 0, 8, 40,247,216, 0, 0, 1,255,236,
+254, 0, 2,104, 6, 40, 0, 3, 0, 0, 3, 17, 33, 17, 20, 2,124,254, 0, 8, 40,247,216, 0, 0, 1,255,236,254, 0, 1,201,
+ 6, 40, 0, 3, 0, 0, 3, 17, 33, 17, 20, 1,221,254, 0, 8, 40,247,216, 0, 0, 1,255,236,254, 0, 1, 42, 6, 40, 0, 3,
+ 0, 0, 3, 17, 33, 17, 20, 1, 62,254, 0, 8, 40,247,216, 0, 0, 1,255,236,254, 0, 0,139, 6, 40, 0, 3, 0, 0, 3, 17,
+ 51, 17, 20,158,254, 0, 8, 40,247,216, 0, 0,255,255, 2,105,254, 0, 4,229, 6, 40, 16, 7, 8,230, 2,125, 0, 0, 0, 0,
+ 0, 12,255,236,254, 0, 4, 70, 6, 40, 0, 3, 0, 7, 0, 11, 0, 15, 0, 19, 0, 23, 0, 27, 0, 31, 0, 35, 0, 39, 0, 43,
+ 0, 47, 0, 0, 1, 17, 51, 17, 33, 17, 51, 17, 19, 17, 51, 17, 33, 17, 51, 17, 1, 17, 51, 17, 33, 17, 51, 17, 19, 17, 51, 17,
+ 33, 17, 51, 17, 1, 17, 51, 17, 33, 17, 51, 17, 19, 17, 51, 17, 33, 17, 51, 17, 3,166,160,252,228,159,159,159,252,229,158, 3,
+ 28,160,252,228,159,159,159,252,229,158, 3, 28,160,252,228,159,159,159,252,229,158,254, 0, 1, 5,254,251, 1, 5,254,251, 1,
+109, 1, 5,254,251, 1, 5,254,251, 1,110, 1, 5,254,251, 1, 5,254,251, 1,109, 1, 5,254,251, 1, 5,254,251, 1,110, 1,
+ 5,254,251, 1, 5,254,251, 1,109, 1, 5,254,251, 1, 5,254,251, 0, 0, 0, 0, 20,255,236,254, 0, 4,229, 6, 40, 0, 3,
+ 0, 7, 0, 11, 0, 15, 0, 19, 0, 23, 0, 27, 0, 31, 0, 39, 0, 47, 0, 55, 0, 63, 0, 71, 0, 79, 0, 87, 0, 95, 0,103,
+ 0,111, 0,119, 0,127, 0, 0, 23, 51, 17, 35, 25, 1, 35, 17, 19, 17, 51, 17, 3, 17, 35, 17, 19, 17, 51, 17, 3, 17, 35, 17,
+ 19, 17, 51, 17, 3, 17, 35, 17, 1, 59, 1, 17, 35, 25, 1, 35, 17, 59, 1, 17, 35, 25, 1, 35, 17, 59, 1, 17, 35, 25, 1, 35,
+ 17, 59, 1, 17, 35, 25, 1, 35, 1, 59, 1, 17, 35, 25, 1, 35, 17, 59, 1, 17, 35, 25, 1, 35, 17, 59, 1, 17, 35, 25, 1, 35,
+ 17, 59, 1, 17, 35, 25, 1, 35, 1, 59, 1, 17, 35, 25, 1, 35, 17, 59, 1, 17, 35, 25, 1, 35, 17, 59, 1, 17, 35, 25, 1, 35,
+ 17, 59, 1, 17, 35, 25, 1, 35,138,160,160,158,158,160,160,158,158,160,160,158,158,160,160,158, 1, 62,159,159,159,159,159,159,
+159,159,159,159,159,159,159,159,159,159, 1, 62,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, 1, 62,160,159,
+159,160,160,159,159,160,160,159,159,160,160,159,159,160,251,254,251, 1, 5, 1, 5,254,251, 1, 5, 1, 5,254,251, 1, 5, 1,
+ 5,254,251, 1, 5, 1, 5,254,251, 1, 5, 1, 5,254,251, 1, 5, 1, 5,254,251, 1, 5, 1, 5,254,251,249,226,254,251, 1,
+ 5, 1, 5, 1, 5,254,251, 1, 5, 1, 5, 1, 5,254,251, 1, 5, 1, 5, 1, 5,254,251, 1, 5, 1, 5,248,221,254,251, 1,
+ 5, 1, 5, 1, 5,254,251, 1, 5, 1, 5, 1, 5,254,251, 1, 5, 1, 5, 1, 5,254,251, 1, 5, 1, 5,248,221,254,251, 1,
+ 5, 1, 5, 1, 5,254,251, 1, 5, 1, 5, 1, 5,254,251, 1, 5, 1, 5, 1, 5,254,251, 1, 5, 1, 5, 0, 0, 7,255,236,
+254, 0, 4,229, 6, 40, 0, 25, 0, 29, 0, 33, 0, 37, 0, 41, 0, 45, 0, 49, 0, 0, 3, 17, 51, 17, 35, 17, 51, 17, 35, 17,
+ 51, 17, 33, 17, 51, 17, 33, 17, 35, 17, 35, 17, 33, 17, 35, 25, 1, 51, 17, 35, 1, 51, 17, 35, 1, 51, 17, 35, 1, 51, 17, 35,
+ 1, 51, 17, 35, 1, 51, 17, 35, 20,158,158,158,158,158, 1,222,159, 1,222,159,160,254, 35,159,159,159, 2,124,160,160,254,194,
+159,159,254,194,159,159, 2,124,160,160,254,194,159,159,254, 0, 1,109, 1, 5, 1,214, 1, 5, 1,214, 1, 5,254,251, 1, 5,
+247,216, 1, 5,254,251, 1, 5,254,251, 5,182, 1, 5,254,251, 1, 5,253,141, 1, 5,253,142, 1, 5,254,251, 1, 5,253,141,
+ 1, 5, 0, 0,255,255,255,236, 5, 35, 4,229, 6, 40, 16, 7, 8,219, 0, 0, 7, 35, 0, 0,255,255, 4, 69,254, 0, 4,228,
+ 6, 40, 16, 7, 8,233, 4, 90, 0, 0, 0, 0, 0, 1,255,236,254, 0, 2,104, 2, 20, 0, 3, 0, 0, 3, 17, 33, 17, 20, 2,
+124,254, 0, 4, 20,251,236, 0,255,255, 2,105,254, 0, 4,229, 2, 20, 16, 7, 8,240, 2,125, 0, 0, 0, 0,255,255,255,236,
+ 2, 20, 2,104, 6, 40, 16, 7, 8,240, 0, 0, 4, 20, 0, 0,255,255,255,236,254, 0, 4,229, 6, 40, 16, 38, 8,240, 0, 0,
+ 16, 38, 8,241, 0, 0, 16, 6, 8,242, 0, 0,255,255,255,236,254, 0, 4,229, 6, 40, 16, 38, 8,241, 0, 0, 16, 6, 8,242,
+ 0, 0, 0, 0,255,255,255,236,254, 0, 4,229, 6, 40, 16, 38, 8,240, 0, 0, 16, 38, 8,242, 0, 0, 16, 6, 8,247, 0, 0,
+255,255,255,236,254, 0, 4,229, 6, 40, 16, 38, 8,241, 0, 0, 16, 38, 8,242, 0, 0, 16, 6, 8,247, 0, 0,255,255, 2,105,
+ 2, 20, 4,229, 6, 40, 16, 7, 8,240, 2,125, 4, 20, 0, 0,255,255,255,236,254, 0, 4,229, 6, 40, 16, 38, 8,240, 0, 0,
+ 16, 6, 8,247, 0, 0, 0, 0,255,255,255,236,254, 0, 4,229, 6, 40, 16, 38, 8,240, 0, 0, 16, 38, 8,241, 0, 0, 16, 6,
+ 8,247, 0, 0, 0, 1, 0, 6,255,177, 4,203, 4,119, 0, 3, 0, 0, 23, 17, 33, 17, 6, 4,197, 78, 4,196,251, 60, 0, 0,
+ 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 3, 0, 7, 0, 0, 55, 33, 17, 33, 3, 17, 33, 17,120, 3,225,252, 31,114, 4,197,
+ 36, 3,224,251,174, 4,196,251, 60, 0, 0, 0, 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 11, 0, 23, 0, 0, 19, 20, 51, 33,
+ 50, 53, 17, 52, 35, 33, 34, 21, 3, 17, 16, 41, 1, 32, 25, 1, 16, 41, 1, 32,120,228, 2, 25,228,228,253,231,228,114, 1, 86,
+ 2, 25, 1, 86,254,170,253,231,254,170, 1, 8,228,228, 2, 24,228,228,253,232, 2, 24, 1, 86,254,170,253,232,254,170, 0, 0,
+255,255, 0, 6,255,177, 4,203, 4,119, 16, 38, 9, 4, 0, 0, 16, 6, 8,251, 0, 0, 0, 0, 0, 6, 0, 6,255,177, 4,203,
+ 4,119, 0, 3, 0, 7, 0, 11, 0, 15, 0, 19, 0, 23, 0, 0, 23, 17, 33, 17, 37, 33, 53, 33, 53, 33, 53, 33, 53, 33, 53, 33,
+ 53, 33, 53, 33, 53, 33, 53, 33, 6, 4,197,251,173, 3,225,252, 31, 3,225,252, 31, 3,225,252, 31, 3,225,252, 31, 3,225,252,
+ 31, 78, 4,196,251, 60,114,110,114,106,114,107,114,107,114,106, 0, 6, 0, 6,255,177, 4,203, 4,119, 0, 3, 0, 7, 0, 11,
+ 0, 15, 0, 19, 0, 23, 0, 0, 23, 17, 33, 17, 39, 51, 17, 35, 3, 51, 17, 35, 3, 51, 17, 35, 3, 51, 17, 35, 3, 51, 17, 35,
+ 6, 4,197,225,110,110,220,106,106,220,106,106,222,108,108,220,106,106, 78, 4,196,251, 60,114, 3,224,252, 32, 3,224,252, 32,
+ 3,224,252, 32, 3,224,252, 32, 3,224, 0, 0, 0, 26, 0, 6,255,177, 4,203, 4,119, 0, 3, 0, 7, 0, 11, 0, 15, 0, 19,
+ 0, 23, 0, 27, 0, 31, 0, 35, 0, 39, 0, 43, 0, 47, 0, 51, 0, 55, 0, 59, 0, 63, 0, 67, 0, 71, 0, 75, 0, 79, 0, 83,
+ 0, 87, 0, 91, 0, 95, 0, 99, 0,103, 0, 0, 19, 51, 53, 35, 17, 51, 53, 35, 17, 51, 53, 35, 17, 51, 53, 35, 17, 51, 53, 35,
+ 19, 51, 53, 35, 17, 51, 53, 35, 17, 51, 53, 35, 17, 51, 53, 35, 17, 51, 53, 35, 19, 51, 53, 35, 17, 51, 53, 35, 17, 51, 53, 35,
+ 17, 51, 53, 35, 17, 51, 53, 35, 19, 51, 53, 35, 17, 51, 53, 35, 17, 51, 53, 35, 17, 51, 53, 35, 17, 51, 53, 35, 19, 51, 53, 35,
+ 17, 51, 53, 35, 17, 51, 53, 35, 17, 51, 53, 35, 17, 51, 53, 35, 5, 17, 33, 17,120,106,106,106,106,106,106,106,106,106,106,220,
+108,108,108,108,108,108,108,108,108,108,222,106,106,106,106,106,106,106,106,106,106,220,106,106,106,106,106,106,106,106,106,106,
+220,110,110,110,110,110,110,110,110,110,110,252, 28, 4,197, 3,154,106,254,185,107,254,184,107,254,185,106,254,182,110, 3, 8,
+106,254,185,107,254,184,107,254,185,106,254,182,110, 3, 8,106,254,185,107,254,184,107,254,185,106,254,182,110, 3, 8,106,254,
+185,107,254,184,107,254,185,106,254,182,110, 3, 8,106,254,185,107,254,184,107,254,185,106,254,182,110,224, 4,196,251, 60, 0,
+ 0, 8, 0, 6,255,177, 4,203, 4,119, 0, 3, 0, 7, 0, 11, 0, 17, 0, 21, 0, 25, 0, 28, 0, 31, 0, 0, 23, 17, 33, 17,
+ 1, 21, 1, 51, 1, 21, 1, 55, 1, 21, 1, 51, 53, 1, 51, 1, 53, 1, 51, 1, 53, 1, 51, 23, 53, 1, 21, 51, 6, 4,197,251,
+173, 1, 52,138,254, 66, 2, 96,149,253, 11, 3,151, 74,252,108,161, 2,243,253,164,162, 1,186,254,208,162,142,252, 31,146, 78,
+ 4,196,251, 60, 2, 48,139,254,205, 2,245,150,253,160, 1, 3,224, 74,252,106, 76, 3,148,253, 14,151, 2, 91,254, 70,139, 1,
+ 47,142,142,252,178,146, 0, 0, 0, 8, 0, 6,255,177, 4,203, 4,119, 0, 3, 0, 7, 0, 11, 0, 17, 0, 21, 0, 25, 0, 28,
+ 0, 31, 0, 0, 23, 17, 33, 17, 37, 51, 1, 53, 1, 23, 1, 53, 1, 51, 1, 53, 35, 1, 53, 1, 35, 1, 53, 1, 35, 1, 53, 55,
+ 35, 1, 51, 53, 6, 4,197,253,208,138, 1, 52,253, 11,149, 2, 96,252, 31, 74, 3,151, 77,252,108, 2,243,151,253,164, 1,186,
+138,254,208,142,142, 3, 79,146, 78, 4,196,251, 60,114, 1, 51,139,254, 66, 1, 2, 96,150,253, 11, 3,150, 74,252,108,162, 2,
+242,253,165,161, 1,186,254,209,161,142,252, 32,146, 0, 0, 0, 0, 26, 0, 6,255,177, 4,203, 4,119, 0, 4, 0, 9, 0, 14,
+ 0, 19, 0, 23, 0, 28, 0, 33, 0, 37, 0, 41, 0, 45, 0, 50, 0, 55, 0, 59, 0, 63, 0, 67, 0, 71, 0, 75, 0, 80, 0, 84,
+ 0, 88, 0, 92, 0, 97, 0,102, 0,106, 0,111, 0,115, 0, 0, 37, 23, 51, 53, 39, 1, 23, 55, 39, 35, 17, 23, 55, 39, 7, 1,
+ 23, 55, 39, 35, 7, 23, 55, 39, 3, 23, 55, 39, 7, 1, 23, 55, 39, 35, 7, 23, 55, 39, 7, 23, 55, 39, 7, 23, 55, 39, 3, 51,
+ 55, 39, 7, 1, 23, 55, 53, 35, 7, 23, 55, 39, 7, 23, 55, 39, 7, 23, 55, 39, 7, 23, 55, 39, 7, 23, 55, 39, 1, 23, 55, 53,
+ 39, 7, 23, 55, 39, 7, 23, 55, 39, 7, 23, 55, 39, 7, 23, 51, 55, 39, 37, 23, 55, 53, 39, 7, 23, 55, 39, 7, 23, 51, 55, 39,
+ 5, 17, 33, 17, 3,235, 36, 74, 35,252, 66, 34, 76, 33, 77, 28, 76, 70, 34, 1, 15, 69, 76, 27, 85,189, 69, 76, 70,190, 35, 69,
+ 75, 29, 2, 65, 76, 69, 33, 85,183, 75, 76, 76,231, 75, 76, 76,231, 76, 75, 76,184, 74, 36, 75, 35, 3,116, 75, 34, 77,182, 75,
+ 69, 75,226, 76, 75, 75,232, 75, 76, 76,230, 75, 75, 76,224, 75, 69, 75, 2,193, 74, 29, 34,226, 75, 76, 75,232, 75, 76, 76,230,
+ 74, 76, 76,224, 36, 78, 30, 75, 2, 36, 69, 35, 29,231, 69, 75, 69,231, 30, 78, 36, 69,253, 2, 4,197, 72, 36, 76, 35, 3, 39,
+ 34, 76, 32,254,127, 29, 76, 69, 34, 1, 14, 69, 76, 26,189, 69, 76, 69,253,196, 34, 69, 75, 28, 2, 65, 76, 69, 33,183, 75, 75,
+ 76,232, 75, 75, 76,231, 76, 75, 76,253,195, 36, 75, 35, 3,116, 76, 34, 74,182, 76, 69, 76,226, 75, 75, 76,232, 75, 75, 75,230,
+ 76, 75, 75,224, 75, 69, 75, 1,137, 76, 29, 82, 34,226, 75, 76, 75,232, 75, 76, 74,230, 76, 76, 74,224, 36, 30, 75,237, 69, 34,
+ 82, 28,231, 69, 75, 69,231, 30, 36, 69,219, 4,196,251, 60, 0, 0, 1, 0,219, 0,135, 3,245, 3,161, 0, 3, 0, 0, 55, 17,
+ 33, 17,219, 3, 26,135, 3, 26,252,230, 0, 0, 0, 2, 0,219, 0,135, 3,245, 3,161, 0, 3, 0, 7, 0, 0, 37, 33, 17, 33,
+ 3, 17, 33, 17, 1, 77, 2, 54,253,202,114, 3, 26,249, 2, 54,253, 88, 3, 26,252,230, 0, 0, 0, 1, 0, 6, 0,240, 4,203,
+ 3, 56, 0, 3, 0, 0, 37, 33, 17, 33, 4,203,251, 59, 4,197,240, 2, 72, 0, 0, 2, 0, 6, 0,240, 4,203, 3, 56, 0, 3,
+ 0, 7, 0, 0, 1, 17, 33, 17, 5, 33, 17, 33, 4, 89,252, 31, 4, 83,251, 59, 4,197, 1, 98, 1,100,254,156,114, 2, 72, 0,
+ 0, 1, 1, 68,255,177, 3,141, 4,119, 0, 3, 0, 0, 5, 17, 33, 17, 1, 68, 2, 72, 78, 4,196,251, 60, 0, 0, 2, 1, 68,
+255,177, 3,141, 4,119, 0, 3, 0, 7, 0, 0, 37, 33, 17, 33, 3, 17, 33, 17, 1,182, 1,100,254,156,114, 2, 72, 36, 3,224,
+251,174, 4,196,251, 60, 0, 0, 0, 1, 0, 6, 0,240, 4,203, 3, 56, 0, 3, 0, 0, 37, 33, 1, 33, 3,151,252,111, 1, 52,
+ 3,145,240, 2, 72, 0, 0, 0, 0, 2, 0, 6, 0,240, 4,203, 3, 56, 0, 3, 0, 7, 0, 0, 1, 19, 33, 3, 5, 33, 1, 33,
+ 3, 97,188,253, 83,188, 2,227,252,111, 1, 52, 3,145, 1, 98, 1,100,254,156,114, 2, 72, 0, 0, 1, 0, 6,255,177, 4,203,
+ 4,119, 0, 2, 0, 0, 23, 9, 1, 6, 2, 98, 2, 99, 78, 4,196,251, 60, 0, 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 2,
+ 0, 5, 0, 0, 55, 33, 9, 3,177, 3,111,254, 72,253,158, 2, 98, 2, 99, 36, 3,110,252, 32, 4,196,251, 60, 0, 1, 0,219,
+ 0,135, 3,245, 3,161, 0, 2, 0, 0, 55, 9, 1,219, 1,141, 1,141,135, 3, 26,252,230, 0, 0, 2, 0,219, 0,135, 3,245,
+ 3,161, 0, 2, 0, 5, 0, 0, 37, 33, 3, 9, 2, 1,134, 1,196,226,254,115, 1,141, 1,141,249, 1,196,253,202, 3, 26,252,
+230, 0, 0, 0, 0, 1, 0, 6,255,177, 4,203, 4,119, 0, 2, 0, 0, 23, 17, 1, 6, 4,197, 78, 4,196,253,158, 0, 0, 0,
+ 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 2, 0, 5, 0, 0, 55, 9, 1, 3, 17, 1,120, 3,111,252,145,114, 4,197, 92, 1,
+184, 1,184,251,230, 4,196,253,158, 0, 0, 0, 0, 1, 0,219, 0,135, 3,245, 3,161, 0, 2, 0, 0, 55, 17, 1,219, 3, 26,
+135, 3, 26,254,115, 0, 0, 0, 0, 2, 0,219, 0,135, 3,245, 3,161, 0, 2, 0, 5, 0, 0, 1, 45, 1, 3, 17, 1, 1, 77,
+ 1,196,254, 60,114, 3, 26, 1, 50,226,226,253,145, 3, 26,254,115, 0, 0, 0, 0, 1, 0, 6, 0,135, 4,203, 3,161, 0, 2,
+ 0, 0, 55, 17, 1, 6, 4,197,135, 3, 26,254,115, 0, 0, 0, 0, 2, 0, 6, 0,135, 4,203, 3,161, 0, 2, 0, 5, 0, 0,
+ 19, 45, 1, 3, 17, 1,120, 3, 54,252,202,114, 4,197, 1, 50,226,226,253,145, 3, 26,254,115, 0, 1, 0, 6,255,177, 4,203,
+ 4,119, 0, 2, 0, 0, 5, 1, 33, 2,104,253,158, 4,197, 78, 4,196, 0, 0, 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 2,
+ 0, 5, 0, 0, 37, 1, 33, 9, 1, 33, 2,104, 1,149,252,215, 1,148,253,158, 4,197,205, 3, 40,251,189, 4,196, 0, 0, 0,
+ 0, 1, 0,219, 0,135, 3,245, 3,161, 0, 2, 0, 0, 37, 1, 33, 2,104,254,115, 3, 26,135, 3, 26, 0, 0, 0, 2, 0,219,
+ 0,135, 3,245, 3,161, 0, 2, 0, 5, 0, 0, 1, 19, 33, 19, 1, 33, 2,104,226,254, 60,226,254,115, 3, 26, 1,107, 1,196,
+253, 88, 3, 26, 0, 1, 0, 6,255,177, 4,203, 4,119, 0, 2, 0, 0, 19, 1, 17, 6, 4,197, 2, 20, 2, 98,251, 60, 0, 0,
+ 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 2, 0, 5, 0, 0, 19, 1, 17, 9, 1, 17,234, 3,111,251,173, 4,197, 2, 20,254,
+ 72, 3,112,254, 72, 2, 98,251, 60, 0, 0, 0, 0, 1, 0,219, 0,135, 3,245, 3,161, 0, 2, 0, 0, 19, 1, 17,219, 3, 26,
+ 2, 20, 1,141,252,230, 0, 0, 0, 2, 0,219, 0,135, 3,245, 3,161, 0, 2, 0, 5, 0, 0, 1, 5, 17, 5, 1, 17, 1,191,
+ 1,196,253, 88, 3, 26, 2, 20,226, 1,196,226, 1,141,252,230, 0, 1, 0, 6, 0,135, 4,203, 3,161, 0, 2, 0, 0, 19, 1,
+ 17, 6, 4,197, 2, 20, 1,141,252,230, 0, 0, 0, 2, 0, 6, 0,135, 4,203, 3,161, 0, 2, 0, 5, 0, 0, 1, 5, 17, 5,
+ 1, 17, 1, 35, 3, 54,251,173, 4,197, 2, 20,226, 1,196,226, 1,141,252,230, 0, 1, 0, 6,255,177, 4,203, 4,119, 0, 3,
+ 0, 0, 19, 9, 2, 6, 2, 98, 2, 99,253,157, 2, 20, 2, 98,253,158,253,158, 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 3,
+ 0, 7, 0, 0, 19, 9, 6,195, 1,165, 1,166,254, 90,253,158, 2, 98, 2, 99,253,157, 2, 20,254, 90, 1,166, 1,166,254, 90,
+ 2, 98,253,158,253,158, 0, 0, 0, 3, 0, 6,255,177, 4,203, 4,119, 0, 3, 0, 7, 0, 11, 0, 0, 19, 9, 10,250, 1,110,
+ 1,110,254,146,254, 54, 1,202, 1,203,254, 53,253,158, 2, 98, 2, 99,253,157, 2, 20, 1,110,254,146,254,146, 1,110,254, 54,
+ 1,202, 1,202,254, 54, 2, 98,253,158,253,158, 0, 3, 0, 6,255,172, 4,203, 4,124, 0, 13, 0, 27, 0, 41, 0, 0, 18, 16,
+ 55, 54, 51, 50, 23, 22, 16, 7, 6, 35, 34, 39, 0, 16, 23, 22, 51, 50, 55, 54, 16, 39, 38, 35, 34, 7, 0, 16, 37, 54, 51, 50,
+ 23, 4, 16, 5, 6, 35, 34, 39,220,198, 99, 99, 99, 99,199,199, 99, 99, 99, 99,254,222,244,122,122,122,122,245,245,122,122,122,
+122,254,146, 1, 49,152,153,152,153, 1, 50,254,206,153,152,153,152, 1, 47, 1,202,114, 57, 57,114,254, 54,114, 57, 57, 2,113,
+253,204,140, 71, 71,141, 2, 50,141, 71, 71,252,250, 2,192,176, 88, 88,176,253, 64,176, 88, 88, 0, 2, 0,117,254, 35, 4, 92,
+ 6,117, 0, 3, 0, 7, 0, 34, 64, 17, 2, 6, 0, 8, 4, 6, 8, 6, 4, 3, 2, 1, 0, 6, 5, 7, 8, 16,212,204, 23, 57,
+ 49, 0, 16,212,204, 17, 57, 18, 57, 48, 9, 7, 2,104,254,127, 1,129, 1,129,254,127, 1,244,254, 12,254, 13, 5,129,252,207,
+252,199, 3, 57, 4, 37,251,219,251,211, 4, 45, 0, 2, 0, 6,255,172, 4,203, 4,124, 0, 13, 0, 27, 0, 0, 18, 16, 23, 22,
+ 51, 50, 55, 54, 16, 39, 38, 35, 34, 7, 0, 16, 37, 54, 51, 50, 23, 4, 16, 5, 6, 35, 34, 39,128,244,122,122,122,122,245,245,
+122,122,122,122,254,146, 1, 49,152,153,152,153, 1, 50,254,206,153,152,153,152, 3, 46,253,204,140, 71, 71,141, 2, 50,141, 71,
+ 71,252,250, 2,192,176, 88, 88,176,253, 64,176, 88, 88, 0, 0, 0, 8, 0, 6,255,172, 4,203, 4,124, 0, 9, 0, 19, 0, 29,
+ 0, 39, 0, 47, 0, 55, 0, 63, 0, 71, 0, 0, 55, 22, 23, 22, 23, 7, 38, 39, 38, 39, 5, 54, 55, 54, 55, 23, 6, 7, 6, 7,
+ 19, 38, 39, 38, 39, 55, 22, 23, 22, 23, 37, 6, 7, 6, 7, 39, 54, 55, 54, 55, 19, 22, 50, 55, 23, 6, 34, 39, 1, 54, 52, 39,
+ 55, 22, 20, 7, 1, 38, 34, 7, 39, 54, 50, 23, 1, 6, 20, 23, 7, 38, 52, 55,212, 34, 46, 36, 44, 61, 55, 45, 58, 42, 2,237,
+ 44, 36, 41, 39,101, 49, 51, 45, 55, 99, 34, 46, 36, 44, 61, 55, 45, 58, 42,253, 19, 44, 36, 46, 34,101, 42, 58, 45, 55,185, 60,
+120, 60, 30, 75,150, 75, 2,114, 13, 13,119, 16, 16,254, 37, 60,120, 60, 30, 75,150, 75,253,143, 13, 13,119, 16, 16,250, 47, 38,
+ 30, 25,106, 32, 37, 48, 58, 69, 25, 30, 34, 51, 70, 65, 42, 37, 32, 3, 42, 47, 38, 30, 25,106, 32, 37, 48, 58, 69, 25, 30, 38,
+ 47, 71, 58, 48, 37, 32,252, 20, 17, 17,119, 21, 21, 1,219, 57,126, 57, 30, 71,158, 71, 2,114, 17, 17,119, 21, 21,254, 37, 57,
+126, 57, 30, 71,158, 71, 0, 0, 0, 6, 0, 6,255,172, 4,203, 4,124, 0, 13, 0, 23, 0, 27, 0, 37, 0, 47, 0, 51, 0, 0,
+ 54, 16, 37, 54, 51, 50, 23, 4, 16, 5, 6, 35, 34, 39, 19, 17, 22, 23, 22, 23, 17, 6, 7, 6, 7, 6, 16, 23, 1, 17, 22, 51,
+ 50, 55, 17, 38, 35, 34, 23, 17, 54, 55, 54, 55, 17, 38, 39, 38, 23, 17, 54, 16, 6, 1, 49,152,153,152,153, 1, 50,254,206,153,
+152,153,152, 29, 15, 17, 38, 38, 38, 38, 17,129, 98, 98, 1, 80, 27, 27, 26, 26, 26, 26, 27,193, 39, 39, 14, 14, 14, 14, 39,181,
+103,180, 2,192,176, 88, 88,176,253, 64,176, 88, 88, 3,163,252,218, 10, 9, 22, 15, 3,150, 15, 22, 9,113,122,254,156,122, 3,
+ 21,252, 46, 4, 3, 3,212, 3, 33,252,104, 15, 23, 8, 9, 3, 42, 9, 8, 23,139,253,156,124, 1,108, 0, 0, 0, 4, 0, 6,
+255,172, 4,203, 4,124, 0, 13, 0, 27, 0, 41, 0, 55, 0, 0, 0, 20, 23, 22, 51, 50, 55, 54, 52, 39, 38, 35, 34, 7, 2, 16,
+ 55, 54, 51, 50, 23, 22, 16, 7, 6, 35, 34, 39, 0, 16, 23, 22, 51, 50, 55, 54, 16, 39, 38, 35, 34, 7, 0, 16, 37, 54, 51, 50,
+ 23, 4, 16, 5, 6, 35, 34, 39, 1,226, 67, 34, 33, 34, 33, 68, 68, 33, 34, 33, 34,177,122, 61, 61, 61, 61,123,123, 61, 61, 61,
+ 61,254,146,244,122,122,122,122,245,245,122,122,122,122,254,146, 1, 49,152,153,152,153, 1, 50,254,206,153,152,153,152, 2, 97,
+154, 39, 20, 20, 39,154, 39, 20, 20,254,255, 1, 26, 70, 35, 35, 70,254,230, 70, 35, 35, 1,237,253,204,140, 71, 71,141, 2, 50,
+141, 71, 71,252,250, 2,192,176, 88, 88,176,253, 64,176, 88, 88, 0, 1, 0, 6,255,172, 4,203, 4,124, 0, 13, 0, 0, 54, 16,
+ 37, 54, 51, 50, 23, 4, 16, 5, 6, 35, 34, 39, 6, 1, 49,152,153,152,153, 1, 50,254,206,153,152,153,152,180, 2,192,176, 88,
+ 88,176,253, 64,176, 88, 88, 0, 0, 2, 0, 6,255,172, 4,203, 4,124, 0, 7, 0, 21, 0, 0, 37, 50, 55, 54, 16, 39, 38, 35,
+ 0, 16, 37, 54, 51, 50, 23, 4, 16, 5, 6, 35, 34, 39, 2,104,122,122,245,245,122,122,253,158, 1, 49,152,153,152,153, 1, 50,
+254,206,153,152,153,152, 39, 71,141, 2, 50,141, 71,252,179, 2,192,176, 88, 88,176,253, 64,176, 88, 88, 0, 0, 0, 2, 0, 6,
+255,172, 4,203, 4,124, 0, 7, 0, 21, 0, 0, 1, 34, 7, 6, 16, 23, 22, 51, 36, 16, 37, 54, 51, 50, 23, 4, 16, 5, 6, 35,
+ 34, 39, 2,104,122,122,244,244,122,122,253,158, 1, 49,152,153,152,153, 1, 50,254,206,153,152,153,152, 4, 1, 71,140,253,204,
+140, 71,141, 2,192,176, 88, 88,176,253, 64,176, 88, 88, 0, 0, 0, 2, 0, 6,255,172, 4,203, 4,124, 0, 8, 0, 22, 0, 0,
+ 1, 16, 39, 38, 35, 34, 7, 6, 17, 2, 16, 37, 54, 51, 50, 23, 4, 16, 5, 6, 35, 34, 39, 4, 81,245,122,122,122,122,244,122,
+ 1, 49,152,153,152,153, 1, 50,254,206,153,152,153,152, 2, 20, 1, 25,141, 71, 71,140,254,230,254,160, 2,192,176, 88, 88,176,
+253, 64,176, 88, 88, 0, 0, 0, 0, 2, 0, 6,255,172, 4,203, 4,124, 0, 8, 0, 22, 0, 0, 19, 16, 23, 22, 51, 50, 55, 54,
+ 17, 0, 16, 37, 54, 51, 50, 23, 4, 16, 5, 6, 35, 34, 39,128,244,122,122,122,122,245,251,181, 1, 49,152,153,152,153, 1, 50,
+254,206,153,152,153,152, 2, 20,254,230,140, 71, 71,141, 1, 25,254,160, 2,192,176, 88, 88,176,253, 64,176, 88, 88, 0, 0, 0,
+ 0, 2, 0, 6,255,172, 4,203, 4,124, 0, 12, 0, 26, 0, 0, 1, 34, 7, 6, 16, 23, 22, 51, 50, 55, 54, 17, 33, 0, 16, 37,
+ 54, 51, 50, 23, 4, 16, 5, 6, 35, 34, 39, 2,104,122,122,244,244,122,122,122,122,245,254, 23,253,158, 1, 49,152,153,152,153,
+ 1, 50,254,206,153,152,153,152, 4, 1, 71,140,253,204,140, 71, 71,141, 1, 25,254,160, 2,192,176, 88, 88,176,253, 64,176, 88,
+ 88, 0, 0, 0, 0, 2, 0, 6,255,172, 4,203, 4,124, 0, 5, 0, 19, 0, 0, 1, 34, 7, 6, 17, 33, 0, 16, 37, 54, 51, 50,
+ 23, 4, 16, 5, 6, 35, 34, 39, 2,104,122,122,244, 1,232,253,158, 1, 49,152,153,152,153, 1, 50,254,206,153,152,153,152, 4,
+ 1, 71,140,254,230,254,160, 2,192,176, 88, 88,176,253, 64,176, 88, 88, 0, 0, 0, 1, 1, 55,255,172, 3,154, 4,124, 0, 7,
+ 0, 0, 5, 34, 39, 36, 16, 37, 54, 51, 3,154,154,152,254,208, 1, 48,152,154, 84, 88,176, 2,192,176, 88, 0, 0, 1, 1, 55,
+255,172, 3,154, 4,124, 0, 7, 0, 0, 1, 50, 23, 4, 16, 5, 6, 35, 1, 56,150,154, 1, 50,254,206,154,150, 4,124, 88,176,
+253, 64,174, 90, 0, 2,255,236,255,236, 4,229, 6, 40, 0, 11, 0, 15, 0, 0, 1, 20, 22, 51, 50, 54, 53, 52, 38, 35, 34, 6,
+ 1, 17, 33, 17, 1, 63,171,124,125,174,173,124,125,172,254,173, 4,249, 2,250,126,171,173,124,123,172,171,252,118, 6, 60,249,
+196, 0, 0, 0, 0, 3,255,236,254, 0, 4,229, 6, 40, 0, 13, 0, 27, 0, 31, 0, 0, 54, 16, 55, 54, 51, 50, 23, 22, 16, 7,
+ 6, 35, 34, 39, 0, 16, 5, 22, 51, 50, 55, 36, 16, 37, 38, 35, 34, 7, 1, 17, 33, 17,128,244,122,122,122,122,245,245,122,122,
+122,122,254,146, 1, 49,152,153,152,153, 1, 50,254,206,153,152,153,152,254,181, 4,249,250, 2, 52,140, 71, 71,141,253,206,141,
+ 71, 71, 3, 6,253, 64,176, 88, 88,176, 2,192,176, 88, 88,249,220, 8, 40,247,216, 0, 0, 0, 0, 2,255,236, 2, 20, 4,229,
+ 6, 40, 0, 12, 0, 21, 0, 0, 3, 17, 33, 17, 35, 16, 37, 38, 35, 34, 7, 4, 17, 41, 1, 16, 55, 54, 51, 50, 23, 22, 20, 4,
+249, 26,254,206,153,152,153,152,254,207, 4, 75,252, 47,244,122,122,122,122,245, 2, 20, 4, 20,251,236, 1, 96,176, 88, 88,176,
+254,160, 1, 25,141, 71, 71,141, 0, 2,255,236,254, 0, 4,229, 2, 20, 0, 12, 0, 21, 0, 0, 3, 17, 51, 16, 5, 22, 51, 50,
+ 55, 36, 17, 51, 17, 1, 33, 16, 7, 6, 35, 34, 39, 38, 20, 26, 1, 49,152,153,152,153, 1, 50, 26,251,155, 3,209,245,122,122,
+122,122,244,254, 0, 4, 20,254,160,176, 88, 88,176, 1, 96,251,236, 4, 20,254,231,141, 71, 71,141, 0, 0, 0, 0, 1, 1, 55,
+ 2, 20, 3,154, 4,124, 0, 9, 0, 0, 1, 16, 37, 54, 51, 23, 34, 7, 6, 17, 1, 55, 1, 49,152,153, 1,123,121,244, 2, 20,
+ 1, 96,176, 88,123, 71,140,254,230, 0, 0, 0, 0, 1, 1, 55, 2, 20, 3,154, 4,124, 0, 9, 0, 0, 1, 50, 23, 4, 17, 35,
+ 16, 39, 38, 35, 1, 56,150,154, 1, 50,123,244,123,120, 4,124, 88,176,254,160, 1, 25,141, 71, 0, 1, 1, 55,255,172, 3,154,
+ 2, 20, 0, 9, 0, 0, 5, 53, 50, 55, 54, 17, 51, 16, 5, 6, 1, 56,120,123,244,123,254,206,154, 84,123, 71,141, 1, 25,254,
+160,174, 90, 0, 0, 1, 1, 55,255,172, 3,154, 2, 20, 0, 9, 0, 0, 5, 34, 39, 36, 17, 51, 16, 23, 22, 51, 3,153,153,152,
+254,207,123,244,121,123, 84, 88,176, 1, 96,254,230,140, 71, 0, 0, 1, 0, 6, 2, 20, 4,203, 4,124, 0, 17, 0, 0, 19, 16,
+ 37, 54, 51, 50, 23, 4, 17, 35, 16, 39, 38, 35, 34, 7, 6, 17, 6, 1, 49,152,153,152,153, 1, 50,122,245,122,122,122,122,244,
+ 2, 20, 1, 96,176, 88, 88,176,254,160, 1, 25,141, 71, 71,140,254,230, 0, 0, 0, 1, 0, 6,255,172, 4,203, 2, 20, 0, 18,
+ 0, 0, 19, 48, 51, 16, 23, 22, 51, 50, 55, 54, 17, 51, 16, 5, 6, 35, 34, 39, 36, 6,122,244,122,122,122,122,245,122,254,206,
+153,152,153,152,254,207, 2, 20,254,230,140, 71, 71,141, 1, 25,254,160,176, 88, 88,176, 0, 0, 0, 1, 0, 6,255,177, 4,203,
+ 4,119, 0, 2, 0, 0, 23, 1, 17, 6, 4,197, 78, 4,196,251, 60, 0, 0, 0, 0, 1, 0, 6,255,177, 4,203, 4,119, 0, 2,
+ 0, 0, 23, 17, 1, 6, 4,197, 78, 4,196,251, 60, 0, 0, 0, 0, 1, 0, 6,255,177, 4,203, 4,119, 0, 2, 0, 0, 23, 17,
+ 33, 6, 4,197, 78, 4,196, 0, 0, 1, 0, 6,255,177, 4,203, 4,119, 0, 2, 0, 0, 19, 33, 17, 6, 4,197, 4,118,251, 60,
+ 0, 2, 1, 63, 1,209, 3,145, 4, 33, 0, 11, 0, 23, 0, 0, 1, 20, 22, 51, 50, 54, 53, 52, 38, 35, 34, 6, 7, 52, 54, 51,
+ 50, 22, 21, 20, 6, 35, 34, 38, 1,122,137, 99,100,140,139, 99,100,138, 59,172,125,124,173,174,125,124,171, 2,250,101,137,139,
+ 99, 98,138,137, 99,124,171,172,123,124,173,171, 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 3, 0, 7, 0, 0, 37, 33, 17, 33,
+ 1, 17, 33, 17, 2,104, 1,240,254, 16,253,158, 4,197, 36, 3,224,251,174, 4,196,251, 60, 0, 0, 2, 0, 6,255,177, 4,203,
+ 4,119, 0, 3, 0, 7, 0, 0, 55, 33, 17, 33, 3, 17, 33, 17,120, 1,240,254, 16,114, 4,197, 36, 3,224,251,174, 4,196,251,
+ 60, 0, 0, 0, 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 2, 0, 6, 0, 0, 55, 33, 17, 1, 17, 33, 17,120, 3,224,251,174,
+ 4,197, 36, 3,224,251,174, 4,196,251, 60, 0, 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 2, 0, 6, 0, 0, 55, 1, 33, 3,
+ 17, 33, 17,120, 3,225,252, 31,114, 4,197, 36, 3,224,251,174, 4,196,251, 60, 0, 3, 0, 6,255,177, 4,203, 4,119, 0, 3,
+ 0, 7, 0, 11, 0, 0, 37, 33, 17, 33, 1, 33, 17, 33, 3, 17, 33, 17, 2,161, 1,183,254, 73,253,215, 1,183,254, 73,114, 4,
+197, 36, 3,224,252, 32, 3,224,251,174, 4,196,251, 60, 0, 0, 0, 3, 0, 6,255,177, 4,203, 4,119, 0, 11, 0, 14, 0, 17,
+ 0, 0, 1, 52, 54, 51, 50, 22, 21, 20, 6, 35, 34, 38, 1, 33, 9, 3, 1,226, 78, 56, 56, 78, 79, 56, 56, 77,254,207, 3,111,
+254, 72,253,158, 2, 98, 2, 99, 1,106, 56, 77, 77, 56, 55, 78, 77,254,242, 3,110,252, 32, 4,196,251, 60, 0, 0, 2, 0, 6,
+255,177, 4,203, 4,119, 0, 2, 0, 5, 0, 0, 37, 33, 9, 3, 2,104, 1,184,254, 72,253,158, 2, 98, 2, 99, 36, 3,110,252,
+ 32, 4,196,251, 60, 0, 0, 0, 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 2, 0, 5, 0, 0, 55, 33, 17, 9, 2,177, 1,183,
+253,158, 2, 98, 2, 99, 36, 3,110,252, 32, 4,196,251, 60, 0, 0, 2,255,236,255,146, 4,229, 4,150, 0, 13, 0, 27, 0, 0,
+ 18, 16, 5, 22, 51, 50, 55, 36, 16, 39, 38, 35, 34, 7, 0, 16, 37, 54, 51, 50, 23, 4, 16, 5, 6, 35, 34, 39,107, 0,255,126,
+128,127,128, 0,255,255,128,127,128,126,254,130, 1, 62,158,160,159,159, 1, 63,254,193,159,159,160,158, 3, 58,253,180,147, 73,
+ 73,147, 2, 76,147, 73, 73,252,216, 2,222,184, 91, 91,184,253, 34,184, 91, 91, 0, 3, 0, 6,255,177, 4,203, 4,119, 0, 3,
+ 0, 7, 0, 13, 0, 0, 23, 17, 33, 17, 1, 33, 17, 33, 17, 33, 17, 33, 17, 33, 6, 4,197,251,173, 1,183,254, 73, 3,224,254,
+ 73,253,215, 78, 4,196,251, 60, 2,154, 1,184,252, 32, 3,224,253,214, 0, 0, 0, 3, 0, 6,255,177, 4,203, 4,119, 0, 3,
+ 0, 7, 0, 13, 0, 0, 23, 17, 33, 17, 37, 33, 17, 33, 53, 33, 17, 33, 17, 33, 6, 4,197,251,173, 1,183,254, 73, 2, 41, 1,
+183,252, 32, 78, 4,196,251, 60,114, 1,182,114,253,216, 3,224, 0, 3, 0, 6,255,177, 4,203, 4,119, 0, 3, 0, 7, 0, 13,
+ 0, 0, 23, 17, 33, 17, 37, 33, 17, 33, 1, 33, 17, 33, 17, 33, 6, 4,197,253,214, 1,183,254, 73,253,215, 1,183, 2, 41,252,
+ 32, 78, 4,196,251, 60,114, 1,182,254, 74, 2, 40, 1,184, 0, 0, 3, 0, 6,255,177, 4,203, 4,119, 0, 3, 0, 7, 0, 13,
+ 0, 0, 23, 17, 33, 17, 1, 33, 17, 33, 1, 33, 17, 33, 17, 33, 6, 4,197,253,214, 1,183,254, 73,253,215, 3,224,253,215,254,
+ 73, 78, 4,196,251, 60, 2,154, 1,184,252, 32, 1,182, 2, 42, 0, 3, 0, 6,255,172, 4,203, 4,124, 0, 13, 0, 19, 0, 32,
+ 0, 0, 54, 16, 37, 54, 51, 50, 23, 4, 16, 5, 6, 35, 34, 39, 19, 6, 7, 6, 7, 33, 5, 22, 23, 22, 51, 50, 55, 54, 16, 39,
+ 38, 39, 17, 6, 1, 49,152,153,152,153, 1, 50,254,206,153,152,153,152,248, 94, 93,219, 22, 1,172,254, 84, 23,218,122,122,122,
+122,245,245, 94, 93,180, 2,192,176, 88, 88,176,253, 64,176, 88, 88, 3,249, 13, 54,126,240,114,238,126, 71, 71,141, 2, 50,141,
+ 54, 13,253,221, 0, 3, 0, 6,255,172, 4,203, 4,124, 0, 13, 0, 26, 0, 32, 0, 0, 54, 16, 37, 54, 51, 50, 23, 4, 16, 5,
+ 6, 35, 34, 39, 37, 54, 55, 54, 16, 39, 38, 35, 34, 7, 6, 7, 33, 5, 22, 23, 22, 23, 17, 6, 1, 49,152,153,152,153, 1, 50,
+254,206,153,152,153,152, 1,106, 93, 94,245,245,122,122,122,122,219, 22, 2, 30,253,226, 23,218, 93, 94,180, 2,192,176, 88, 88,
+176,253, 64,176, 88, 88, 39, 13, 54,141, 2, 50,141, 71, 71,126,240,114,238,126, 54, 13, 1,175, 0, 3, 0, 6,255,172, 4,203,
+ 4,124, 0, 13, 0, 26, 0, 32, 0, 0, 54, 16, 37, 54, 51, 50, 23, 4, 16, 5, 6, 35, 34, 39, 2, 16, 23, 22, 23, 17, 33, 38,
+ 39, 38, 35, 34, 7, 1, 54, 55, 54, 55, 33, 6, 1, 49,152,153,152,153, 1, 50,254,206,153,152,153,152,183,244, 93, 94, 2, 31,
+ 22,220,122,122,122,122, 1, 45, 93, 94,219, 23,254, 83,180, 2,192,176, 88, 88,176,253, 64,176, 88, 88, 3, 41,253,206,141, 54,
+ 13, 2, 33,240,126, 71, 71,252,113, 13, 54,126,238, 0, 0, 0, 0, 3, 0, 6,255,172, 4,203, 4,124, 0, 13, 0, 26, 0, 32,
+ 0, 0, 54, 16, 37, 54, 51, 50, 23, 4, 16, 5, 6, 35, 34, 39, 2, 16, 23, 22, 51, 50, 55, 54, 55, 33, 17, 6, 7, 1, 38, 39,
+ 38, 39, 17, 6, 1, 49,152,153,152,153, 1, 50,254,206,153,152,153,152,183,244,122,122,122,122,219, 23,253,225, 94, 93, 2,218,
+ 22,220, 94, 93,180, 2,192,176, 88, 88,176,253, 64,176, 88, 88, 3, 41,253,206,141, 71, 71,126,238, 2, 35, 13, 54,254,146,240,
+126, 54, 13,254, 79, 0, 0, 0, 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 2, 0, 5, 0, 0, 55, 1, 33, 3, 17, 33,120, 3,
+ 54,252,202,114, 4,197,206, 3, 54,251,174, 4,196, 0, 0, 0, 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 2, 0, 5, 0, 0,
+ 9, 1, 17, 37, 33, 17, 1, 35, 3, 54,251,173, 4,197, 4, 4,252,202, 3, 54,114,251, 60, 0, 0, 2, 0, 6,255,177, 4,203,
+ 4,119, 0, 2, 0, 5, 0, 0, 55, 33, 1, 3, 17, 1,120, 3, 54,252,202,114, 4,197, 36, 3, 54,252, 88, 4,196,251, 60, 0,
+ 0, 2, 0, 97, 0, 13, 4,111, 4, 27, 0, 3, 0, 7, 0, 0, 55, 33, 17, 33, 3, 17, 33, 17,211, 3, 42,252,214,114, 4, 14,
+127, 3, 42,252,100, 4, 14,251,242, 0, 0, 0, 0, 1, 0, 97, 0, 13, 4,111, 4, 27, 0, 3, 0, 0, 55, 17, 33, 17, 97, 4,
+ 14, 13, 4, 14,251,242, 0, 0, 0, 2, 0,175, 0, 91, 4, 33, 3,205, 0, 3, 0, 7, 0, 0, 37, 33, 17, 33, 3, 17, 33, 17,
+ 1, 33, 2,142,253,114,114, 3,114,205, 2,142,253, 0, 3,114,252,142, 0, 0, 0, 1, 0,175, 0, 91, 4, 33, 3,205, 0, 3,
+ 0, 0, 55, 17, 33, 17,175, 3,114, 91, 3,114,252,142, 0, 0, 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 2, 0, 5, 0, 0,
+ 37, 33, 17, 9, 1, 17, 1, 35, 3, 54,251,173, 4,197, 36, 3, 54,252, 88, 4,196,251, 60, 0, 0, 9, 0, 34, 0,164, 4,175,
+ 5, 49, 0, 7, 0, 12, 0, 19, 0, 34, 0, 42, 0, 50, 0, 58, 0, 65, 0, 73, 0, 0, 1, 51, 23, 17, 7, 35, 39, 17, 5, 23,
+ 21, 7, 39, 37, 23, 7, 35, 38, 39, 53, 5, 50, 31, 1, 20, 7, 6, 35, 34, 39, 38, 53, 52, 55, 54, 5, 33, 23, 21, 7, 33, 39,
+ 53, 37, 33, 23, 21, 7, 33, 39, 53, 7, 51, 22, 23, 21, 7, 39, 53, 37, 51, 23, 21, 7, 39, 53, 37, 51, 23, 17, 7, 35, 39, 17,
+ 2, 78, 60, 4, 4, 60, 5, 1,186, 46,194, 48,253,167,196, 47, 2,157, 35, 1,181,163, 69, 10,148, 55, 36,137, 76, 28,143, 52,
+253,228, 1, 8, 5, 5,254,248, 5, 3,122, 1, 14, 5, 5,254,242, 4, 56, 3,104, 89, 47,194,254, 54, 2, 46,192, 48, 1,165,
+ 60, 4, 4, 60, 5, 5, 49, 5,254,239, 4, 4, 1, 17,121, 49, 2,198, 49,186,199, 50,156, 43, 3,141,176, 75,147, 79, 17,130,
+ 49, 72,141, 80, 22,215, 5, 61, 5, 5, 61, 5, 5, 61, 5, 5, 61,218,102, 94, 2, 49,198, 3, 32, 46, 3,198, 49, 3, 92, 4,
+254,239, 5, 5, 1, 17, 0, 0, 0, 1, 0, 50, 0, 8, 4,159, 1,209, 0, 34, 0, 0, 1, 51, 50, 31, 1, 54, 51, 22, 21, 20,
+ 7, 22, 29, 1, 6, 35, 33, 53, 50, 55, 54, 59, 1, 39, 52, 63, 1, 23, 39, 52, 63, 1, 50, 23, 54, 3, 0, 13,134, 72, 12, 24,
+ 34, 83, 21, 63, 11, 49,251,209, 35, 82, 29, 32, 20, 7, 98, 24, 26, 3,125, 41, 30, 28, 74, 1,209,143, 53, 22, 17, 67, 30, 32,
+ 14, 44, 16, 63, 6,107, 24, 30, 67, 30, 2, 2, 7, 91, 55, 5, 27, 62, 0, 0, 0, 1, 0, 34, 0, 6, 4,175, 4, 45, 0, 63,
+ 0, 0, 1, 51, 23, 21, 51, 32, 19, 22, 29, 1, 35, 38, 39, 38, 43, 1, 34, 7, 21, 20, 7, 39, 38, 35, 17, 20, 15, 1, 34, 47,
+ 1, 53, 55, 51, 23, 21, 22, 59, 1, 50, 63, 1, 17, 34, 7, 6, 35, 39, 53, 55, 35, 38, 39, 35, 34, 15, 1, 35, 53, 54, 55, 54,
+ 51, 53, 2, 97, 41, 4, 2, 1, 56,199, 31, 1, 16, 14, 24, 41, 31,107, 79, 6, 24,107, 97, 75, 21, 65, 26, 2, 4, 31, 4, 7,
+ 45, 7, 39, 14, 4,150, 61, 12, 10, 5, 5, 3, 47,141, 47, 71, 24, 14, 2, 41,137,170,221, 4, 44, 4, 89,254,166, 61, 9, 6,
+ 11, 33, 17, 72, 36, 11, 1, 47, 43,254, 25, 72, 17, 1, 68, 20, 18, 5, 5, 8, 72, 41, 29, 1,225, 43, 41, 4, 9, 36, 46, 19,
+ 44, 12, 1,102,155,159, 89, 0, 0, 15, 0, 89,255,250, 4,120, 5,171, 0, 9, 0, 17, 0, 25, 0, 33, 0, 61, 0, 90, 0,133,
+ 0,177, 0,220, 1, 8, 1, 16, 1, 24, 1, 32, 1, 76, 1,120, 0, 0, 1, 22, 55, 51, 6, 7, 38, 39, 51, 22, 55, 38, 39, 54,
+ 55, 22, 23, 6, 5, 38, 39, 54, 55, 22, 23, 6, 3, 38, 39, 54, 55, 22, 23, 6, 39, 6, 21, 20, 22, 51, 50, 54, 53, 52, 39, 38,
+ 39, 22, 55, 54, 53, 52, 38, 35, 34, 6, 21, 20, 23, 22, 51, 6, 19, 54, 55, 50, 31, 1, 22, 20, 7, 6, 7, 22, 23, 22, 21, 20,
+ 4, 32, 36, 53, 52, 55, 54, 55, 38, 39, 38, 52, 55, 1, 23, 39, 38, 50, 15, 1, 55, 54, 51, 50, 21, 20, 15, 1, 23, 22, 21, 20,
+ 35, 34, 47, 1, 23, 22, 35, 34, 63, 1, 7, 6, 35, 34, 53, 52, 63, 1, 39, 38, 53, 52, 51, 50, 3, 23, 39, 38, 51, 50, 15, 1,
+ 55, 54, 51, 50, 21, 20, 15, 1, 23, 22, 21, 20, 35, 34, 47, 1, 23, 22, 35, 34, 63, 1, 7, 6, 35, 34, 53, 52, 63, 1, 39, 38,
+ 53, 52, 51, 50, 1, 23, 39, 38, 51, 50, 15, 1, 55, 54, 51, 50, 21, 20, 15, 1, 23, 22, 20, 35, 34, 47, 1, 23, 22, 35, 34, 63,
+ 1, 7, 6, 35, 34, 53, 52, 63, 1, 39, 38, 53, 52, 51, 48, 31, 1, 39, 38, 51, 50, 15, 1, 55, 54, 51, 50, 21, 20, 15, 1, 23,
+ 22, 21, 20, 35, 34, 47, 1, 23, 22, 35, 34, 63, 1, 7, 6, 35, 34, 53, 52, 63, 1, 39, 38, 53, 52, 51, 50, 1, 38, 53, 52, 51,
+ 50, 21, 20, 5, 38, 53, 54, 51, 50, 21, 20, 55, 38, 53, 52, 51, 50, 21, 20, 19, 23, 39, 38, 51, 50, 15, 1, 55, 54, 51, 50, 21,
+ 20, 15, 1, 23, 22, 21, 20, 35, 34, 47, 1, 23, 22, 35, 34, 63, 1, 7, 6, 35, 34, 53, 52, 63, 1, 39, 38, 53, 52, 51, 50, 1,
+ 23, 39, 38, 51, 50, 15, 1, 55, 54, 51, 50, 21, 20, 15, 1, 23, 22, 21, 20, 35, 34, 47, 1, 23, 22, 35, 34, 63, 1, 7, 6, 35,
+ 34, 53, 52, 63, 1, 39, 38, 53, 52, 51, 50, 2, 80, 79, 28, 25, 5,128,126, 9, 24, 41,185, 42, 1, 3, 43, 39, 3, 3,254,235,
+ 41, 3, 3, 43, 40, 3, 3, 64, 38, 2, 3, 39, 36, 2, 2,202,124,247,175,174,248,124,101,139, 63, 47, 65,125, 93, 92,138, 66,
+ 45, 55,144, 21, 26,147,132, 49, 2, 83, 76, 20, 24,111, 87,142,254,228,254,106,254,227,143, 92,118, 21, 19, 76, 76, 2,114, 37,
+ 6, 1, 28, 1, 6, 37, 4, 4, 14, 7, 44, 42, 7, 12, 6, 2, 35, 4, 1, 14, 14, 1, 5, 36, 2, 5, 13, 8, 41, 42, 8, 14,
+ 3,110, 36, 5, 1, 13, 16, 2, 6, 37, 4, 4, 13, 7, 43, 41, 8, 12, 6, 2, 36, 5, 1, 15, 13, 1, 4, 35, 2, 5, 14, 8,
+ 42, 43, 8, 15, 4,253, 28, 21, 3, 1, 9, 9, 1, 4, 22, 2, 2, 9, 4, 26, 24, 5, 8, 3, 1, 22, 4, 1, 9, 9, 1, 3,
+ 21, 1, 3, 8, 4, 25, 26, 4, 9, 63, 19, 4, 1, 8, 9, 1, 4, 19, 2, 3, 8, 5, 22, 22, 4, 7, 2, 3, 19, 3, 1, 8,
+ 8, 1, 4, 19, 3, 2, 7, 4, 22, 22, 5, 8, 3, 1,249, 39, 43, 38,254,180, 40, 1, 41, 38,251, 40, 43, 38,112, 23, 4, 1,
+ 9, 9, 1, 3, 21, 2, 2, 8, 3, 26, 25, 4, 8, 3, 1, 21, 2, 1, 8, 9, 1, 3, 22, 1, 3, 8, 6, 24, 25, 5, 9, 2,
+252,242, 37, 5, 1, 13, 14, 1, 5, 37, 4, 4, 13, 7, 43, 41, 8, 12, 4, 4, 36, 4, 1, 14, 13, 1, 4, 36, 4, 2, 14, 8,
+ 42, 43, 8, 15, 2, 3,132, 5, 42, 69, 5, 7, 67, 42, 90, 2, 42, 44, 3, 3, 41, 45, 4, 2, 41, 45, 3, 3, 42, 44,254, 18,
+ 2, 37, 38, 2, 2, 37, 38,158,102,147,145,208,208,145,147,102, 85, 32, 2, 53, 72,104,102,101,101,102,104, 72, 50, 30, 1,217,
+112, 24,117, 19, 94,232, 81, 24, 16, 28, 70,115,165,163,230,230,163,165,115, 75, 26, 15, 22, 81,232, 71,254,129, 31, 52, 13, 13,
+ 52, 31, 3, 16, 9, 3, 20, 19, 3, 9, 14, 2, 30, 50, 15, 15, 50, 30, 2, 14, 8, 4, 19, 20, 4, 8, 16, 1, 48, 31, 52, 14,
+ 14, 52, 31, 3, 16, 7, 3, 21, 19, 4, 9, 14, 2, 30, 50, 14, 14, 50, 30, 2, 14, 9, 4, 19, 21, 4, 6, 16, 1, 57, 17, 29,
+ 10, 10, 29, 17, 3, 10, 4, 2, 13, 10, 2, 14, 1, 17, 30, 7, 7, 30, 17, 1, 7, 7, 2, 10, 13, 2, 4, 10,251, 16, 28, 7,
+ 7, 28, 16, 2, 7, 6, 2, 9, 11, 2, 5, 8, 2, 15, 26, 8, 8, 26, 15, 2, 8, 5, 2, 11, 9, 2, 6, 7,253, 76, 2, 37,
+ 40, 39, 42,222, 2, 37, 41, 40, 42, 2, 2, 37, 41, 40, 42, 4,116, 17, 30, 8, 8, 30, 17, 2, 8, 7, 1, 11, 12, 2, 5, 9,
+ 1, 17, 28, 9, 9, 28, 17, 1, 9, 4, 3, 12, 11, 2, 6, 8,254, 49, 31, 52, 14, 14, 52, 31, 3, 16, 8, 3, 20, 19, 4, 9,
+ 14, 3, 29, 50, 14, 14, 50, 29, 3, 14, 9, 4, 19, 20, 4, 7, 16, 0, 0, 0, 0, 15, 0, 29, 0, 48, 4,180, 5,114, 0, 19,
+ 0, 33, 0, 50, 0, 67, 0, 84, 0,101, 0,118, 0,135, 0,152, 0,169, 0,186, 0,203, 0,220, 0,237, 0,254, 0, 0, 1, 22,
+ 7, 6, 15, 1, 6, 43, 1, 38, 39, 38, 53, 52, 63, 2, 54, 23, 22, 7, 6, 23, 22, 31, 1, 22, 63, 1, 54, 47, 1, 38, 7, 19,
+ 50, 23, 22, 29, 1, 20, 7, 6, 35, 34, 47, 1, 53, 52, 55, 54, 55, 50, 23, 22, 29, 1, 20, 7, 6, 35, 34, 47, 1, 53, 52, 55,
+ 54, 55, 50, 23, 22, 29, 1, 20, 7, 6, 35, 34, 39, 61, 1, 52, 55, 54, 55, 50, 23, 22, 29, 1, 20, 7, 6, 35, 34, 47, 1, 53,
+ 52, 55, 54, 19, 50, 23, 22, 29, 1, 20, 7, 6, 35, 34, 47, 1, 53, 52, 55, 54, 7, 50, 23, 22, 29, 1, 20, 7, 6, 35, 34, 39,
+ 61, 1, 52, 55, 54, 1, 50, 23, 22, 29, 1, 20, 7, 6, 35, 34, 47, 1, 53, 52, 55, 54, 55, 50, 23, 22, 29, 1, 20, 7, 6, 35,
+ 34, 39, 61, 1, 52, 55, 54, 55, 50, 23, 22, 29, 1, 20, 7, 6, 35, 34, 47, 1, 53, 52, 55, 54, 1, 50, 23, 22, 29, 1, 20, 7,
+ 6, 35, 34, 47, 1, 53, 52, 55, 54, 55, 50, 23, 22, 29, 1, 20, 7, 6, 35, 34, 47, 1, 53, 52, 55, 54, 55, 50, 23, 22, 29, 1,
+ 20, 7, 6, 35, 34, 47, 1, 53, 52, 55, 54, 55, 50, 23, 22, 29, 1, 20, 7, 6, 35, 34, 47, 1, 53, 52, 55, 54, 1,108, 61, 46,
+ 15, 37, 16, 71, 92, 17, 38, 29, 35, 45, 31, 9, 76,106, 46,196, 78, 26, 4, 10, 11, 48,100, 38, 75, 17, 24, 52,105,185, 21, 11,
+ 6, 20, 8, 10, 27, 9, 1, 19, 10,125, 22, 11, 5, 19, 8, 10, 27, 9, 1, 19, 10,103, 21, 11, 5, 19, 8, 10, 26, 11, 19, 10,
+115, 21, 11, 6, 20, 7, 11, 26, 10, 1, 19, 10, 2, 21, 12, 5, 20, 7, 11, 26, 10, 1, 20, 9,141, 22, 11, 5, 19, 8, 10, 27,
+ 10, 19, 10, 1, 38, 21, 11, 5, 19, 8, 10, 26, 11, 1, 20, 10,144, 22, 11, 5, 19, 8, 10, 27, 10, 19, 10,145, 21, 11, 6, 20,
+ 8, 10, 27, 9, 1, 19, 10,254, 2, 22, 11, 6, 20, 8, 10, 27, 9, 1, 19, 10,204, 21, 12, 5, 20, 7, 11, 26, 10, 1, 20, 9,
+217, 21, 11, 6, 20, 8, 10, 26, 10, 1, 19, 10,193, 21, 12, 5, 20, 7, 11, 26, 10, 1, 20, 9, 1,198, 72,131, 53, 45, 19, 86,
+ 5, 34, 42, 60, 67, 90, 43, 10, 93, 2, 9, 95, 95,102, 17, 12, 13, 56, 65, 37, 92,109, 36, 61, 70, 1, 14, 23, 9, 12, 4, 23,
+ 14, 5, 33, 10, 3, 23, 15, 6,234, 22, 9, 12, 5, 22, 14, 6, 34, 9, 4, 22, 15, 6,230, 23, 9, 11, 5, 22, 15, 5, 34, 9,
+ 4, 22, 15, 6,236, 23, 9, 11, 4, 23, 14, 5, 33, 9, 3, 24, 14, 6,253,197, 23, 9, 11, 5, 23, 14, 5, 33, 11, 2, 24, 14,
+ 6,194, 23, 9, 11, 4, 24, 14, 5, 34, 10, 3, 23, 14, 6, 1,131, 22, 9, 11, 6, 22, 14, 5, 33, 9, 4, 22, 16, 5,187, 23,
+ 9, 11, 5, 23, 14, 5, 34, 9, 3, 23, 15, 6,194, 24, 9, 11, 4, 23, 14, 6, 34, 10, 3, 23, 14, 7,252, 77, 22, 9, 11, 5,
+ 23, 14, 6, 34, 9, 4, 23, 14, 6,158, 22, 9, 11, 5, 22, 15, 6, 35, 9, 3, 23, 15, 5,172, 23, 9, 10, 5, 24, 13, 5, 33,
+ 10, 2, 24, 14, 6,151, 23, 9, 11, 4, 24, 13, 6, 34, 10, 2, 24, 14, 6, 0, 0, 1, 0, 58, 0, 15, 4,151, 4, 51, 0, 9,
+ 0, 0, 19, 33, 27, 1, 33, 5, 19, 37, 5, 19, 58, 1,170,132,133, 1,170,254,167,133,254,165,254,167,132, 2,158, 1,149,254,
+107,251,254,108,250,250, 1,148, 0, 2, 0, 58, 0, 20, 4,151, 4, 57, 0, 9, 0, 19, 0, 0, 19, 33, 27, 1, 33, 5, 19, 37,
+ 5, 19, 55, 3, 37, 5, 3, 37, 33, 11, 1, 33, 58, 1,170,132,133, 1,170,254,167,133,254,165,254,167,132, 48,100, 1, 9, 1,
+ 18,109, 1, 28,254,167,104,100,254,165, 2,164, 1,148,254,108,251,254,108,250,250, 1,148, 15,254,203,191,201, 1, 64,199, 1,
+ 56,254,200, 0, 0, 1, 0,200, 0, 5, 4, 9, 5,214, 0, 17, 0, 0, 1, 22, 23, 20, 7, 9, 1, 55, 19, 37, 55, 1, 38, 53,
+ 52, 55, 1, 54, 3,206, 57, 2, 9,253,125, 1,238, 86, 38,254, 55,224,253,221, 19, 65, 2,147, 11, 5,214, 2, 54, 36, 12,253,
+133,253,244,230,254, 56, 39, 94, 2, 52, 23, 23, 27, 63, 2,134, 10, 0, 0, 0, 0, 1, 0, 59,255,255, 4,150, 5,217, 0, 25,
+ 0, 0, 19, 33, 50, 21, 20, 7, 9, 1, 55, 19, 37, 55, 1, 38, 53, 52, 55, 1, 33, 17, 20, 35, 34, 53, 17, 52,122, 3,214, 60,
+ 26,253,229, 1,201, 83, 35,254, 78,216,254, 16, 14, 49, 1,199,253, 12, 68, 67, 5,217, 83, 34, 27,253,197,254, 27,213,254, 61,
+ 34,108, 2, 22, 15, 46, 27, 51, 1,223,250,252, 69, 68, 5, 91, 58, 0, 0, 0, 0, 3, 0, 43, 0, 7, 4,166, 4,129, 0, 13,
+ 0, 25, 0, 38, 0, 0, 1, 20, 0, 35, 34, 0, 53, 52, 18, 36, 51, 50, 4, 18, 5, 20, 0, 32, 0, 53, 52, 46, 1, 32, 14, 1,
+ 5, 20, 6, 35, 34, 38, 53, 52, 62, 1, 50, 30, 1, 4,165,254,177,238,237,254,177,154, 1, 19,143,144, 1, 20,153,251,191, 1,
+ 45, 1,173, 1, 46,138,248,254,252,248,138, 2,148, 84, 60, 58, 85, 39, 69, 71, 69, 39, 2, 68,238,254,178, 1, 78,238,149, 1,
+ 20,148,148,254,237,150,214,254,211, 1, 45,214,136,246,133,133,246,136, 60, 83, 83, 60, 38, 69, 36, 36, 69, 0, 0, 3, 0, 15,
+ 0, 5, 4,194, 5, 29, 0, 10, 0, 22, 0, 67, 0, 0, 0, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 37, 34, 6, 21, 20, 22, 51,
+ 50, 54, 53, 52, 38, 37, 22, 23, 22, 21, 20, 6, 35, 34, 38, 53, 52, 55, 54, 55, 54, 53, 52, 36, 32, 4, 21, 20, 23, 22, 23, 22,
+ 20, 6, 35, 34, 38, 52, 55, 54, 55, 38, 53, 52, 0, 51, 50, 0, 21, 20, 4, 11,113, 79, 79, 57, 56, 79,252,164, 56, 80, 80, 56,
+ 56, 79, 79, 3, 34, 19, 17, 70,140, 99, 99,139, 68, 62, 85, 93,255, 0,254,144,255, 0, 92, 96, 67, 68,139, 99, 98,141, 70, 14,
+ 14, 93, 1, 87,246,248, 1, 87, 1,177, 90, 65, 64, 90, 90, 64, 65, 90, 90, 65, 64, 91, 91, 64, 65, 90, 75, 15, 20, 80,114,113,
+160,160,113,114, 80, 71, 8,101,134,157,222,222,157,134,100, 3, 77, 80,228,160,160,228, 80, 15, 13,125,159,217, 1, 50,254,206,
+217,155, 0, 0, 0, 3, 0, 18,255,254, 4,191, 5,107, 0, 10, 0, 22, 0, 65, 0, 0, 1, 52, 38, 35, 34, 6, 21, 20, 22, 50,
+ 54, 37, 52, 38, 35, 34, 6, 21, 20, 22, 51, 50, 54, 1, 20, 0, 35, 34, 0, 53, 52, 55, 38, 39, 38, 52, 54, 51, 50, 22, 20, 7,
+ 6, 7, 6, 21, 20, 4, 32, 36, 53, 52, 39, 38, 39, 38, 52, 54, 51, 50, 22, 20, 7, 6, 7, 22, 4, 88, 80, 55, 57, 78, 78,113,
+ 79,253, 46, 78, 57, 55, 79, 79, 55, 57, 78, 3, 39,254,171,247,245,254,171, 93, 14, 14, 69,139, 97, 99,139, 68, 67, 95, 92, 0,
+255, 1,110, 0,255, 92, 85, 62, 68,139, 98, 99,138, 69, 17, 19, 88, 4, 70, 68, 98, 98, 68, 69, 97, 97, 69, 69, 97, 97, 69, 68,
+ 97, 97,254, 43,232,254,185, 1, 71,232,169,132, 14, 17, 85,242,171,171,242, 85, 83, 3,106,142,169,235,235,169,143,105, 9, 76,
+ 86,242,171,171,242, 86, 21, 16,130, 0, 0, 0, 0, 2, 0, 54, 0, 1, 4,155, 5,202, 0, 11, 0, 27, 0, 0, 1, 34, 6, 21,
+ 20, 22, 51, 50, 54, 53, 52, 38, 55, 22, 23, 22, 16, 0, 35, 34, 0, 16, 0, 51, 50, 23, 1, 23, 2, 63,143,201,201,143,142,201,
+199,190, 19, 18,152,254,206,217,215,254,206, 1, 47,218, 96, 84, 1, 14,154, 3, 99,200,144,142,201,201,142,144,200, 59, 16, 19,
+153,254, 80,254,207, 1, 49, 1,176, 1, 50, 29, 1,211, 89, 0, 0, 3, 0, 46, 0, 3, 4,163, 5,203, 0, 8, 0, 17, 0, 49,
+ 0, 0, 1, 34, 6, 20, 22, 50, 54, 52, 38, 0, 34, 6, 20, 22, 51, 50, 54, 52, 1, 22, 21, 20, 2, 35, 34, 2, 53, 52, 18, 51,
+ 50, 23, 22, 23, 55, 38, 53, 52, 18, 51, 50, 18, 21, 20, 2, 35, 34, 39, 38, 39, 1, 64, 75,106,106,150,106,105, 2, 79,151,105,
+105, 76, 75,105,253,247, 24,161,114,113,161,160,114,116, 80, 1, 1,138, 18,159,115,115,160,161,114,113, 81, 7, 7, 2,220,169,
+240,169,169,240,169, 2, 90,169,240,169,169,240,253,228, 84,100,181,254,255, 1, 1,181,183, 1, 1,128, 3, 2,137, 73, 85,183,
+ 1, 1,254,255,183,181,254,255,129, 11, 12, 0, 0, 14, 0, 20,255,255, 4,189, 4,200, 0, 23, 0, 41, 0, 53, 0, 65, 0, 77,
+ 0, 89, 0,100, 0,112, 0,123, 0,134, 0,145, 0,157, 0,169, 0,181, 0, 0, 1, 51, 4, 23, 22, 21, 6, 47, 1, 38, 55, 54,
+ 39, 33, 6, 23, 22, 15, 1, 6, 39, 52, 55, 54, 1, 53, 51, 21, 20, 23, 22, 21, 17, 33, 17, 52, 55, 54, 61, 1, 51, 21, 3, 20,
+ 22, 51, 50, 54, 53, 52, 38, 35, 34, 6, 5, 20, 6, 35, 34, 38, 53, 52, 54, 51, 50, 22, 39, 20, 6, 35, 34, 38, 53, 52, 54, 51,
+ 50, 22, 17, 20, 6, 35, 34, 38, 53, 52, 54, 51, 50, 22, 2, 22, 6, 7, 6, 38, 39, 38, 54, 55, 54, 19, 22, 6, 7, 6, 38, 39,
+ 38, 54, 55, 54, 22, 1, 30, 1, 14, 1, 39, 46, 1, 55, 62, 1, 4, 30, 1, 7, 14, 1, 39, 46, 1, 55, 54, 36, 54, 22, 23, 22,
+ 6, 7, 6, 38, 39, 38, 37, 54, 22, 23, 22, 6, 7, 6, 38, 39, 38, 54, 1, 62, 1, 23, 30, 1, 7, 14, 1, 39, 46, 1, 19, 62,
+ 1, 23, 30, 1, 7, 14, 1, 39, 46, 1, 2,102, 5, 1, 60,135,142, 20, 59,214, 46, 21, 61, 43,253,178, 44, 62, 21, 47,214, 59,
+ 20,142,135, 1,187, 75,127,121,252,129,122,126, 76, 90,124, 87, 88,123,123, 88, 88,123, 1, 73, 69, 49, 49, 69, 69, 49, 49, 69,
+ 84, 17, 12, 12, 18, 18, 12, 12, 17, 17, 12, 12, 18, 18, 12, 12, 17,109, 13, 3, 10, 10, 24, 7, 8, 4, 10, 10,226, 7, 3, 11,
+ 10, 23, 8, 7, 4, 10, 10, 24,254,249, 13, 10, 7, 22, 12, 11, 12, 4, 4, 22, 1, 59, 23, 11, 4, 4, 22, 11, 12, 11, 4, 4,
+254,201, 23, 22, 4, 3, 10, 12, 12, 22, 4, 4, 1, 82, 11, 22, 4, 4, 11, 12, 11, 23, 3, 4, 11,254,255, 7, 24, 10, 10, 4,
+ 8, 6, 25, 10, 10, 4,202, 8, 23, 10, 11, 3, 7, 7, 24, 10, 10, 4, 4,200, 14,127,135,139,133, 8,115, 22, 64,100, 6, 6,
+100, 64, 22,115, 8,133,139,135,125,254,189, 62,125, 61, 47, 78,234,254,110, 1,146,234, 78, 47, 61,125, 62,254, 64,137,192,192,
+137,136,193,193,135, 77,108,108, 77, 78,107,107,182, 18, 28, 28, 18, 19, 28, 28,253,233, 20, 27, 27, 20, 19, 28, 28, 1,235, 31,
+ 38, 11, 12, 6, 15, 17, 37, 12, 11,254, 73, 16, 37, 13, 10, 5, 17, 15, 37, 12, 10, 5, 1, 34, 7, 33, 36, 18, 5, 6, 35, 18,
+ 18, 18,160, 12, 34, 18, 18, 17, 6, 6, 33, 19, 18, 5, 12, 17, 18, 19, 34, 7, 4, 17, 18, 18,200, 6, 18, 18, 18, 33, 7, 6,
+ 18, 18, 18, 33,254,214, 15, 5, 10, 12, 38, 14, 17, 5, 10, 13, 37, 1,177, 16, 6, 11, 12, 37, 17, 15, 6, 12, 11, 38, 0, 0,
+ 0, 16, 0, 8, 0, 11, 4,201, 4,201, 0, 17, 0, 29, 0, 37, 0, 45, 0, 53, 0, 65, 0, 77, 0, 89, 0,100, 0,112, 0,124,
+ 0,136, 0,148, 0,166, 0,192, 0,218, 0, 0, 1, 53, 35, 21, 6, 7, 6, 21, 17, 33, 17, 52, 39, 38, 39, 53, 35, 21, 7, 50,
+ 22, 21, 20, 6, 35, 34, 38, 53, 52, 54, 22, 34, 6, 20, 22, 50, 54, 52, 38, 34, 6, 20, 22, 50, 54, 52, 2, 34, 6, 20, 22, 50,
+ 54, 52, 3, 14, 1, 23, 30, 1, 55, 62, 1, 39, 46, 1, 19, 14, 1, 23, 30, 1, 55, 62, 1, 39, 46, 1, 37, 6, 22, 23, 22, 54,
+ 55, 54, 38, 39, 38, 6, 5, 6, 22, 23, 22, 62, 1, 38, 39, 38, 6, 5, 30, 1, 55, 62, 1, 39, 46, 1, 7, 14, 1, 37, 30, 1,
+ 55, 62, 1, 39, 46, 1, 7, 14, 1, 3, 22, 54, 55, 54, 38, 39, 38, 6, 7, 6, 22, 19, 22, 54, 55, 54, 38, 39, 38, 6, 7, 6,
+ 22, 55, 53, 51, 21, 20, 23, 22, 21, 17, 33, 17, 52, 55, 54, 61, 1, 51, 21, 39, 6, 23, 22, 15, 1, 6, 39, 54, 55, 54, 37, 22,
+ 50, 55, 4, 23, 22, 23, 6, 47, 1, 38, 55, 54, 39, 55, 22, 7, 6, 31, 1, 22, 55, 38, 39, 38, 47, 1, 21, 35, 6, 7, 6, 7,
+ 22, 63, 1, 54, 39, 38, 55, 1,212, 26, 8,108,105, 3, 1,105,108, 4, 30,140, 89,122,123, 88, 87,124,123,137, 98, 69, 69, 98,
+ 69,100, 25, 17, 17, 25, 17, 17, 25, 17, 17, 25, 17,145, 10, 4, 7, 8, 24, 10, 10, 3, 7, 7, 24,185, 10, 4, 7, 7, 25, 10,
+ 10, 4, 8, 7, 24,254,236, 4, 12, 11, 12, 22, 4, 3, 10, 13, 11, 22, 1, 56, 4, 11, 11, 12, 22, 7, 11, 11, 12, 22,254,193,
+ 4, 22, 12, 12, 10, 3, 4, 22, 12, 11, 12, 1, 64, 3, 22, 12, 11, 11, 4, 3, 22, 12, 11, 11,241, 10, 24, 7, 8, 4, 10, 10,
+ 24, 8, 7, 4,205, 10, 24, 7, 8, 4, 10, 10, 25, 7, 7, 4, 46, 72,120,116,252,172,116,120, 72,184, 37, 63, 37, 53,200, 69,
+ 36, 7,132,133, 1, 54, 13, 26, 12, 1, 54,133,132, 7, 36, 68,201, 53, 37, 63, 37, 14, 45, 53, 33, 33,174, 49, 40, 5,127,167,
+255, 26, 29,255,167,126, 6, 40, 49,175, 32, 32, 53, 44, 3, 26, 52,116, 52, 40, 52,196,254,178, 1, 78,196, 52, 40, 52,116, 52,
+ 59,188,132,133,187,187,133,132,188,141,104,150,104,104,150,224, 26, 37, 26, 26, 37,254, 35, 26, 37, 26, 26, 37, 1,216, 11, 36,
+ 16, 14, 7, 11, 12, 37, 15, 14, 6,254, 95, 12, 36, 16, 15, 6, 12, 11, 36, 15, 16, 5,248, 18, 33, 6, 5, 16, 19, 17, 34, 5,
+ 6, 18,173, 17, 33, 6, 6, 17, 36, 33, 6, 6, 16, 47, 18, 17, 6, 6, 33, 17, 18, 18, 6, 6, 33,138, 18, 17, 5, 6, 33, 18,
+ 17, 18, 6, 5, 34,254,191, 12, 6, 15, 16, 36, 11, 11, 5, 16, 15, 36, 1,139, 11, 7, 14, 16, 36, 11, 12, 6, 15, 15, 37,234,
+ 58,127, 45, 44, 71,217,254,140, 1,116,217, 71, 44, 45,127, 58,186, 13, 88, 76, 15,134, 8,172,162, 82,113, 14, 1, 1, 14,113,
+ 82,162,172, 8,134, 15, 76, 88, 13, 23, 33, 91, 36, 31,110, 30,147,128, 91,105, 20, 1, 1, 20,105, 91,128,147, 30,110, 31, 36,
+ 91, 33, 0, 0, 0, 2, 0,111, 0, 4, 4, 98, 4, 8, 0, 7, 0, 11, 0, 0, 19, 33, 23, 17, 7, 33, 39, 17, 23, 17, 33, 17,
+116, 3,233, 4, 4,252, 23, 4, 75, 3, 90, 4, 7, 5,252, 7, 4, 4, 3,249, 71,252,149, 3,107, 0, 0, 0, 0, 3, 0, 99,
+255,253, 4,110, 4, 24, 0, 7, 0, 11, 0, 34, 0, 0, 19, 33, 23, 17, 7, 33, 39, 17, 23, 17, 33, 17, 7, 21, 6, 7, 2, 7,
+ 6, 35, 6, 35, 38, 43, 1, 53, 55, 50, 23, 51, 54, 55, 54, 55, 54,104, 4, 1, 5, 5,251,255, 5, 78, 3,110, 95, 53, 29,230,
+ 44, 4, 11, 83, 9, 71,144, 16,114,106, 51, 5, 35, 45, 69,109, 68, 4, 24, 4,251,239, 5, 5, 4, 17, 74,252,130, 3,126,111,
+ 4, 46, 40,254,201,227, 42, 33,182, 4, 52, 92,116, 82,126,131, 85, 0, 0, 0, 0, 3, 0,133, 0, 5, 4, 76, 3,218, 0, 7,
+ 0, 11, 0, 26, 0, 0, 19, 33, 23, 17, 7, 33, 39, 17, 23, 17, 33, 17, 5, 9, 1, 23, 9, 1, 21, 7, 1, 35, 1, 35, 39, 9,
+ 1,138, 3,189, 4, 4,252, 67, 4, 73, 3, 51,253, 90, 1, 13, 1, 12, 62,254,244, 1, 12, 60,254,242, 2,254,245, 3, 60, 1,
+ 12,254,244, 3,217, 4,252, 53, 5, 5, 3,203, 68,252,189, 3, 67, 88,254,245, 1, 11, 60,254,243,254,242, 1, 60, 1, 11,254,
+247, 59, 1, 14, 1, 13, 0, 0, 0, 1, 0,201, 0, 89, 4, 8, 5, 68, 0, 20, 0, 0, 1, 51, 1, 54, 1, 50, 55, 51, 23, 9,
+ 1, 21, 7, 1, 35, 1, 35, 39, 1, 0, 53, 1, 38, 5, 1, 60, 12, 1, 43, 4, 7, 4, 90,254,192, 1, 64, 92,254,193, 2,254,
+191, 3, 92, 1, 68,254,188, 5, 67,253,236, 9, 1,251, 16, 90,253,228,253,232, 3, 89, 2, 23,253,235, 92, 2, 24, 2, 21, 7,
+ 0, 8, 0, 28,255,252, 4,181, 5, 53, 0, 8, 0, 17, 0, 26, 0, 35, 0, 44, 0, 53, 0, 62, 0,126, 0, 0, 1, 51, 6, 43,
+ 1, 38, 61, 1, 52, 37, 51, 6, 43, 1, 38, 61, 1, 52, 37, 51, 6, 43, 1, 38, 61, 1, 52, 23, 51, 6, 43, 1, 38, 61, 1, 52,
+ 37, 51, 6, 43, 1, 38, 61, 1, 52, 23, 51, 6, 43, 1, 38, 61, 1, 52, 23, 51, 6, 43, 1, 38, 61, 1, 52, 37, 51, 23, 21, 51,
+ 32, 19, 22, 29, 1, 35, 38, 39, 38, 43, 1, 34, 7, 21, 20, 7, 39, 38, 35, 17, 20, 15, 1, 34, 47, 1, 53, 55, 51, 23, 21, 22,
+ 59, 1, 50, 63, 1, 17, 34, 7, 6, 35, 39, 53, 55, 35, 38, 39, 35, 34, 15, 1, 35, 53, 54, 55, 54, 51, 53, 1, 31, 2, 21, 64,
+ 4, 41, 1,163, 1, 20, 65, 4, 40, 1,123, 2, 21, 64, 5, 40,173, 2, 21, 64, 4, 41, 1,123, 3, 21, 65, 4, 41,206, 1, 19,
+ 65, 5, 40, 64, 2, 21, 65, 4, 40,254, 94, 41, 4, 1, 1, 52,196, 30, 1, 16, 13, 25, 39, 31,105, 79, 5, 23,106, 95, 74, 21,
+ 64, 26, 1, 4, 30, 4, 7, 44, 7, 38, 14, 4,147, 60, 12, 10, 5, 5, 3, 47,137, 47, 70, 23, 14, 2, 40,134,168,218, 4, 48,
+145, 7, 25, 1, 39,249,144, 5, 25, 2, 38,159,145, 6, 25, 2, 38,130,144, 5, 25, 2, 39,220,144, 5, 25, 2, 39, 74,144, 4,
+ 26, 2, 38,164,145, 6, 25, 1, 40,108, 4, 78,254,210, 53, 9, 5, 9, 29, 15, 62, 33, 9, 1, 41, 38,254, 86, 63, 15, 1, 60,
+ 17, 16, 4, 4, 7, 63, 36, 25, 1,165, 38, 36, 4, 8, 32, 39, 17, 38, 11, 1, 90,135,139, 78, 0, 9, 0, 78, 0, 6, 4,131,
+ 5,130, 0, 9, 0, 15, 0, 24, 0, 47, 0, 62, 0, 69, 0,113, 0,119, 0,134, 0, 0, 19, 6, 23, 33, 54, 55, 52, 35, 33, 6,
+ 19, 22, 23, 33, 54, 63, 1, 6, 7, 54, 55, 54, 39, 52, 35, 39, 6, 7, 51, 50, 21, 20, 7, 6, 7, 6, 7, 51, 50, 55, 54, 55,
+ 54, 55, 54, 53, 52, 35, 1, 51, 20, 6, 7, 20, 22, 23, 35, 38, 39, 38, 39, 38, 54, 3, 22, 37, 54, 55, 33, 22, 5, 54, 55, 50,
+ 23, 21, 20, 15, 1, 23, 20, 7, 33, 38, 61, 1, 55, 53, 36, 47, 1, 53, 54, 51, 22, 23, 38, 17, 52, 51, 33, 22, 21, 51, 50, 21,
+ 20, 7, 6, 7, 6, 43, 1, 39, 1, 22, 23, 33, 54, 55, 3, 6, 7, 6, 7, 35, 62, 1, 53, 52, 38, 53, 51, 30, 1,176, 1, 12,
+ 3, 42, 8, 2, 21,252,236, 19, 44, 4, 11, 2,199, 10, 6, 51, 6, 41, 61, 34, 22, 2, 23, 40, 1, 1, 38, 41, 48, 31, 57, 22,
+ 36, 5, 41, 27, 13, 76, 38, 21, 16, 84,254, 6, 6, 69, 1, 96, 3, 6, 13, 77, 23, 7, 2, 80,206,248, 1, 5, 24, 65,253, 91,
+ 26, 2, 77,178, 72, 13, 4,252, 89, 1, 11,254,142, 12, 3,254,223, 36, 2, 3, 13, 59,151,141, 38, 3, 24, 23, 38,101, 61, 24,
+ 79, 37, 47, 5, 12,253, 78, 4, 7, 2,255, 8, 3,253, 5, 13, 44, 8, 4, 2, 56, 40, 4, 7, 46, 2,143, 55, 76, 49, 82, 21,
+ 4,254,224, 24, 17, 21, 20,187,102,126, 1, 72, 56, 83, 16, 81, 27, 30, 44,122, 72, 37, 1, 57, 68, 54, 13, 29, 41,106, 71, 80,
+ 64, 2,246, 52,128, 82,106,100,166,137, 95, 42, 75,102,115,251, 68, 22, 20, 15,142, 73, 82, 23, 9, 9, 10, 15, 57, 33, 10, 14,
+ 7, 6, 15, 6, 2, 2, 79, 17, 12, 4, 10, 8, 19,238, 1, 28, 45, 2, 22, 93,145,144, 38, 21, 67, 4, 1, 43, 25, 17, 18, 24,
+ 1,213, 47, 26, 60, 85,103, 64, 65, 53, 79, 33, 43, 71, 0, 0, 0, 2, 0, 56, 0, 7, 4,153, 5,223, 0, 7, 0, 12, 0, 0,
+ 9, 1, 19, 7, 33, 39, 19, 9, 1, 3, 33, 3, 1, 2,110, 1,235, 63, 2,251,167, 4, 66, 1,241,254, 90, 57, 3,183, 54,254,
+ 92, 5,223,254,119,251,180, 3, 6, 4, 76, 1,134,254, 53,252, 95, 3,161, 1, 75, 0, 0, 0, 0, 1, 0, 47, 0, 2, 4,162,
+ 5,210, 0, 9, 0, 0, 9, 1, 19, 23, 7, 33, 39, 19, 0, 55, 2,108, 1,241, 66, 2, 2,251,149, 4, 68, 1,230, 16, 5,210,
+254,119,251,191, 3, 3, 6, 4, 68, 1,128, 6, 0, 1, 0, 38, 0, 7, 4,171, 4,196, 0, 66, 0, 0, 1, 39, 38, 53, 52, 55,
+ 54, 51, 50, 22, 54, 51, 50, 23, 22, 21, 20, 15, 1, 55, 54, 23, 22, 23, 22, 21, 20, 7, 14, 1, 22, 7, 6, 7, 6, 35, 34, 39,
+ 38, 47, 1, 18, 7, 35, 54, 3, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 54, 38, 39, 38, 53, 52, 55, 54, 55, 54, 23, 2, 82,165,
+ 56, 67, 28, 29, 67, 66, 67, 44, 71, 42, 10, 69,152,248,104, 93, 27, 26, 54, 6, 13,101, 59, 22, 8, 25, 44, 48, 25, 27, 81, 58,
+157, 31,110, 72,136, 30,157, 59, 80, 27, 25, 48, 43, 26, 9, 21, 59,101, 13, 6, 54, 26, 27, 92,105, 2,126,250, 84, 90, 87, 52,
+ 18, 88, 88, 92, 34, 31,103, 94,225, 82, 41, 32, 10, 22, 53, 54, 17, 17, 46, 39, 95, 69, 30, 22, 33, 10, 27, 83,226,254,190,241,
+241, 1, 66,226, 83, 27, 10, 33, 22, 30, 69, 95, 39, 46, 17, 16, 55, 53, 22, 10, 32, 41, 0, 0, 0, 2, 0, 47, 1,160, 4,162,
+ 4,116, 0, 57, 0, 62, 0, 0, 1, 22, 23, 20, 7, 6, 7, 22, 23, 51, 23, 7, 35, 6, 7, 34, 39, 52, 51, 22, 55, 50, 55, 38,
+ 39, 35, 34, 7, 22, 21, 6, 7, 36, 3, 52, 55, 22, 23, 21, 7, 20, 23, 50, 55, 18, 55, 22, 7, 20, 7, 54, 55, 50, 53, 54, 55,
+ 54, 38, 3, 6, 23, 53, 38, 3,251, 85, 15, 56,134, 15,195, 41, 21, 15, 36, 2, 13,116, 74, 19, 15, 12, 46, 59, 9,199, 5, 3,
+100, 51,102, 7,255,254, 44, 34, 51, 39, 6, 10, 86, 68, 10, 40,227,153, 4, 32, 71, 76, 47, 55, 59, 59, 44,103, 11,185, 24, 4,
+116, 4, 94, 70, 21, 29, 36, 22,221, 60, 10,142, 7, 76, 68, 38, 1, 63, 62,196, 88, 52, 82,200, 13, 2, 1, 33, 47, 8, 3, 35,
+ 19, 32, 73, 10, 63, 1,132, 16, 4,137, 32, 80, 63, 16, 31, 68, 33, 41, 77,254,230,118, 62, 2,147, 0, 0, 0, 0, 1, 0, 47,
+ 1, 14, 4,162, 4,122, 0, 50, 0, 0, 1, 33, 34, 38, 53, 52, 54, 55, 54, 55, 51, 55, 35, 38, 39, 38, 53, 52, 62, 1, 59, 1,
+ 55, 35, 34, 38, 53, 52, 54, 55, 54, 55, 33, 55, 33, 34, 38, 53, 52, 62, 1, 51, 33, 54, 55, 54, 51, 33, 50, 22, 21, 4,104,253,
+244, 33, 46, 21, 19, 14, 14, 41, 3,103, 36, 19, 24, 22, 39, 19,137, 1,196, 51, 48, 23, 19, 15, 17, 1, 1, 2,253,185, 33, 47,
+ 22, 38, 20, 2,106, 6, 13, 23, 33, 1, 29, 32, 47, 1, 14, 58, 40, 26, 47, 12, 9, 3, 11, 2, 24, 29, 41, 25, 47, 26, 10, 57,
+ 41, 24, 47, 13, 11, 2, 9, 57, 41, 26, 48, 24, 21, 16, 29, 58, 42, 0, 0, 0, 0, 1, 0, 47, 1, 14, 4,162, 4,122, 0, 50,
+ 0, 0, 19, 3, 52, 54, 51, 33, 50, 23, 22, 23, 33, 50, 30, 1, 21, 20, 6, 35, 33, 23, 33, 22, 23, 30, 1, 21, 20, 6, 43, 1,
+ 23, 51, 50, 30, 1, 21, 20, 7, 6, 7, 35, 23, 51, 22, 23, 30, 1, 21, 20, 6, 35,105, 57, 47, 32, 1, 29, 33, 23, 13, 6, 2,
+106, 20, 38, 22, 47, 33,253,185, 2, 1, 1, 17, 15, 19, 23, 48, 51,196, 1,137, 19, 39, 22, 24, 19, 36,103, 3, 41, 14, 14, 19,
+ 21, 46, 33, 1, 14, 3, 8, 42, 58, 29, 16, 21, 24, 48, 26, 41, 57, 9, 2, 11, 13, 47, 24, 41, 57, 10, 26, 47, 25, 41, 29, 24,
+ 2, 11, 3, 9, 12, 47, 26, 40, 58, 0, 0, 0, 0, 2, 0, 14, 1, 26, 4,195, 4, 33, 0, 33, 0, 67, 0, 0, 1, 19, 52, 38,
+ 35, 33, 34, 7, 33, 38, 21, 20, 51, 33, 7, 33, 34, 21, 20, 51, 33, 7, 35, 34, 21, 20, 59, 1, 7, 35, 34, 21, 20, 51, 7, 38,
+ 39, 54, 55, 51, 55, 35, 38, 39, 54, 55, 51, 55, 33, 34, 39, 54, 55, 33, 55, 33, 34, 39, 54, 51, 33, 54, 55, 33, 50, 22, 21, 3,
+ 4,101, 59, 39, 27,254,225, 43, 19,253,112, 67, 67, 2,111, 10,254,224, 67, 67, 0,255, 7,180, 67, 67,142, 16, 50, 67, 67, 23,
+ 75, 1, 1, 75, 60, 4,139, 76, 1, 1, 76,185, 2,255, 0, 75, 1, 1, 75, 1, 37, 3,253,147, 74, 1, 1, 74, 2,148, 26, 54,
+ 1, 48, 34, 50, 61, 1, 50, 2,129, 30, 41, 46, 2, 61, 60, 61, 61, 60, 64, 61, 58, 62, 61, 59, 24, 1, 84, 84, 1, 11, 1, 85,
+ 83, 1, 15, 85, 84, 1, 12, 85, 84, 56, 1, 51, 36,253, 81, 0, 0, 2, 0,140, 0, 0, 4, 69, 5,202, 0, 33, 0, 68, 0, 0,
+ 55, 5, 50, 54, 53, 17, 52, 39, 17, 54, 35, 34, 21, 17, 39, 17, 52, 35, 34, 21, 17, 39, 53, 52, 35, 34, 29, 1, 39, 53, 52, 35,
+ 34, 21, 39, 54, 55, 22, 23, 21, 23, 53, 54, 55, 22, 23, 21, 23, 17, 52, 55, 22, 23, 17, 23, 17, 54, 55, 22, 21, 17, 22, 23, 17,
+ 20, 6, 35, 37, 19,170, 3, 21, 36, 52, 58, 2, 74, 73, 76, 76, 72, 79, 75, 72, 76, 75, 73, 29, 1,104,103, 1, 14, 1,104,103,
+ 1, 18,105,103, 1, 15, 1,104,103, 68, 2, 62, 45,252,178, 1,115, 74, 49, 32, 1, 98, 54, 22, 3, 39, 83, 83,253, 2, 13, 1,
+ 99, 82, 82,254,196, 9,223, 83, 83,174, 18, 63, 83, 83, 28, 92, 1, 1, 92, 75, 4,172, 92, 1, 1, 92,228, 3, 1, 59, 92, 1,
+ 1, 92,254,150, 4, 2,253, 93, 1, 1, 93,252,212, 33, 65,254,138, 42, 62, 75, 2,155, 0, 0, 0, 2, 0, 14, 1, 26, 4,195,
+ 4, 33, 0, 33, 0, 68, 0, 0, 19, 33, 50, 53, 52, 43, 1, 39, 51, 50, 53, 52, 43, 1, 39, 33, 50, 53, 52, 35, 33, 39, 33, 50,
+ 53, 52, 7, 33, 38, 35, 33, 34, 6, 21, 1, 48, 33, 3, 52, 54, 51, 33, 22, 23, 33, 50, 23, 6, 35, 33, 23, 33, 22, 23, 6, 35,
+ 33, 23, 51, 22, 23, 6, 7, 35, 23, 51, 22, 23, 6,108, 2, 31, 67, 67, 50, 16,142, 67, 67,180, 7, 0,255, 67, 67,254,224, 10,
+ 2,111, 67, 67,253,112, 19, 43,254,225, 27, 39, 2,113,253,170, 61, 50, 34, 1, 48, 54, 26, 2,148, 74, 1, 1, 74,253,147, 3,
+ 1, 37, 75, 1, 1, 75,255, 0, 2,185, 76, 1, 1, 76,139, 4, 60, 75, 1, 1, 1, 50, 59, 61, 62, 58, 61, 64, 60, 61, 61, 60,
+ 61, 2, 46, 41, 30,253,103, 2,175, 36, 51, 1, 56, 84, 85, 12, 1, 84, 85, 15, 1, 83, 85, 1, 11, 1, 84, 84, 0, 2, 0,140,
+255,249, 4, 69, 5,194, 0, 33, 0, 67, 0, 0, 19, 20, 51, 50, 61, 1, 55, 21, 20, 51, 50, 61, 1, 55, 17, 20, 51, 50, 53, 17,
+ 55, 17, 20, 51, 50, 39, 17, 54, 53, 17, 52, 38, 35, 5, 39, 37, 50, 22, 21, 17, 6, 7, 17, 20, 7, 38, 39, 17, 7, 17, 6, 7,
+ 38, 53, 17, 7, 21, 6, 7, 38, 39, 53, 7, 21, 6, 7, 38, 39,170, 73, 75, 76, 72, 75, 79, 72, 76, 76, 73, 74, 2, 58, 52, 36,
+252,235, 30, 3, 78, 45, 62, 2, 68,103,104, 1, 15, 1,103,105, 18, 1,103,104, 1, 14, 1,103,104, 1, 2,179, 83, 83, 61, 20,
+174, 83, 83,221, 9,254,198, 83, 83, 1, 98, 13,253, 1, 83, 83, 3, 39, 23, 54, 1, 97, 33, 48, 74, 41, 75, 62, 42,254,138, 66,
+ 32,252,212, 92, 1, 1, 92, 2,252, 4,254,152, 93, 1, 1, 93, 1, 58, 2,228, 93, 1, 1, 93,171, 4, 74, 93, 1, 1, 93, 0,
+ 0, 29, 0, 12,255,254, 4,197, 4,191, 0, 79, 0,128, 0,136, 0,144, 0,159, 0,174, 0,181, 0,188, 0,205, 0,211, 0,218,
+ 0,222, 0,226, 0,230, 0,234, 0,238, 0,242, 0,246, 0,250, 0,254, 1, 2, 1, 17, 1, 29, 1, 33, 1, 37, 1, 41, 1, 45,
+ 1, 49, 1, 53, 0, 0, 1, 50, 23, 22, 29, 1, 20, 7, 23, 21, 20, 7, 51, 54, 53, 54, 59, 1, 50, 21, 22, 29, 1, 6, 35, 39,
+ 6, 7, 21, 23, 55, 22, 21, 20, 7, 20, 43, 1, 34, 47, 1, 6, 35, 34, 39, 6, 21, 6, 43, 1, 34, 53, 38, 53, 52, 55, 23, 55,
+ 53, 39, 7, 34, 39, 53, 52, 55, 54, 59, 1, 50, 31, 1, 53, 39, 55, 38, 53, 54, 55, 54, 1, 20, 23, 51, 53, 38, 53, 54, 59, 1,
+ 23, 7, 23, 21, 7, 21, 20, 23, 22, 29, 1, 23, 51, 55, 52, 55, 54, 53, 39, 55, 53, 39, 55, 22, 29, 1, 7, 23, 54, 61, 1, 52,
+ 39, 38, 43, 1, 32, 7, 6, 5, 22, 7, 6, 39, 34, 39, 52, 33, 22, 23, 6, 35, 34, 39, 38, 19, 51, 54, 51, 23, 54, 53, 38, 53,
+ 38, 35, 6, 7, 6, 21, 37, 6, 35, 6, 21, 23, 55, 22, 23, 53, 52, 39, 38, 53, 38, 5, 23, 21, 7, 38, 53, 52, 55, 22, 21, 20,
+ 7, 39, 53, 3, 22, 51, 54, 55, 38, 55, 6, 7, 6, 43, 1, 38, 39, 38, 39, 22, 55, 22, 23, 51, 53, 38, 5, 21, 50, 63, 1, 34,
+ 7, 5, 21, 23, 53, 55, 21, 55, 53, 7, 21, 23, 53, 51, 21, 55, 39, 7, 21, 55, 39, 7, 21, 51, 53, 51, 21, 51, 53, 7, 21, 23,
+ 53, 23, 21, 51, 53, 7, 21, 51, 53, 5, 39, 7, 21, 22, 21, 22, 51, 50, 55, 54, 55, 38, 53, 6, 37, 7, 22, 21, 20, 23, 50, 63,
+ 1, 38, 35, 7, 37, 7, 23, 53, 7, 21, 23, 53, 39, 21, 23, 53, 23, 21, 55, 53, 55, 21, 55, 53, 55, 21, 55, 53, 2,117,233,111,
+ 44, 77, 5, 19, 4,122, 34, 27, 6, 48, 54, 20, 48, 68,189, 47,178, 53, 73, 58, 50, 4, 39, 53,144, 58,131,134, 54,160, 38, 34,
+ 11, 42, 58, 68, 58,173,231, 83, 52, 6, 54, 3, 30, 25, 36, 46,101, 19, 9, 81, 26,201, 78,254,240, 53, 5, 23, 8, 10, 10, 14,
+ 10, 25, 15,117, 52, 77, 68, 97,149, 25, 20, 26, 10, 23, 19, 23, 4, 54,170, 98, 85, 29,254,254, 80, 15, 1, 25, 43, 10, 44, 72,
+ 59, 27, 1, 96,155, 4, 28, 73, 50, 51, 2,181, 4,214, 18, 78, 24, 53, 6, 15, 21, 40,189,253, 13, 13, 10, 40, 35, 73, 48,183,
+ 77,154, 19, 1,211, 10, 39, 29, 94, 53, 31, 37,204, 35,163,165, 33, 5, 25, 27, 21, 58, 88, 43,145, 9, 6, 34, 22, 7, 15, 19,
+ 5, 7, 1, 42, 11, 3, 19, 10, 18,254,236, 14,222, 20,227, 19,155, 21, 2, 54, 18, 3, 87, 24, 15, 19,125, 19, 87, 19, 58, 24,
+254,117, 87, 5, 52, 5, 10, 15, 53,118, 26, 14,142, 2, 84, 13,173, 38, 16, 9, 47, 4, 24, 72,254, 51, 3, 23, 19, 19, 86, 19,
+156, 20, 12, 19, 15, 20, 4,190,156, 88, 68, 57, 92, 83, 76, 5, 43, 38, 51, 49, 46,100, 43, 28, 19, 37, 6, 88, 33, 15, 81, 10,
+ 14, 36, 31, 50, 96, 96, 75, 80, 80, 80, 20, 71, 91, 54, 37, 35, 10, 10, 81, 15,121, 6, 45, 11, 22, 54, 91, 91, 51, 5, 71, 75,
+ 91,175,187, 79, 23,254,194, 96, 95, 65, 91, 45, 41, 15, 36,116, 55,136, 10, 76, 25, 45, 36, 20, 10, 21, 76, 54, 29, 61,152,127,
+ 15, 34, 17, 9, 28, 40,141, 20, 67, 74, 35,171, 82, 34,196, 48,169, 13, 58,130, 4,126, 71, 8, 66,123,126, 69,254,111,106, 4,
+ 6, 8, 60, 30, 52, 8, 83, 91, 16,191, 90, 30, 21, 8, 4, 15, 97, 11, 76, 21, 67, 53, 29, 11, 5,129, 41, 10, 46, 85, 37, 43,
+ 90, 38, 7, 41,131,254,205,162, 12,155, 55,101, 31,141, 60, 18, 73, 76, 65, 97, 77, 30,111, 75, 51, 51, 75, 64, 71, 54, 11, 36,
+ 4, 36, 4, 40, 8, 38, 12, 40, 4, 39, 39, 6, 38, 5, 49, 2, 47, 4, 45, 45, 45, 45, 50, 41, 4, 40, 11, 40, 45, 5, 40, 40,
+100, 4, 4, 16, 46, 39, 45, 84, 63, 24, 30, 24, 79, 75, 56, 84, 36, 12, 33, 84, 51, 15, 4,166, 40, 5, 45, 60, 40, 5, 40, 26,
+ 39, 6, 41, 20, 41, 5, 41, 3, 40, 4, 41, 8, 41, 6, 40, 0, 0, 1, 0, 9,255,251, 4,200, 5,211, 0, 38, 0, 0, 1, 50,
+ 23, 22, 21, 20, 7, 1, 7, 20, 23, 37, 50, 23, 21, 20, 35, 5, 34, 39, 38, 61, 1, 52, 55, 0, 55, 54, 53, 52, 39, 35, 5, 34,
+ 39, 53, 52, 55, 51, 2,244,116, 92, 42,101,253,232, 9, 79, 2,201, 64, 7, 85,253, 67,131, 88, 22,113, 1,249, 16, 9, 80, 9,
+253, 83, 46, 9, 80, 11, 5,211,141, 77, 79,138, 98,253,160, 62, 89, 26,209, 97, 3, 89,198,174, 53, 56, 24,138,108, 2, 55, 27,
+ 27, 22, 80, 32,204, 80, 30, 64, 12, 0, 0, 0, 0, 6, 0, 8, 0, 2, 4,201, 4,195, 0, 17, 0, 36, 0, 48, 0, 60, 0, 70,
+ 0, 88, 0, 0, 1, 32, 19, 22, 21, 16, 5, 6, 43, 1, 32, 3, 38, 61, 1, 16, 37, 54, 5, 38, 35, 34, 7, 6, 21, 16, 23, 22,
+ 51, 32, 19, 54, 61, 1, 16, 37, 38, 3, 35, 34, 39, 19, 22, 59, 1, 50, 55, 19, 6, 3, 6, 29, 1, 33, 53, 52, 55, 54, 55, 19,
+ 6, 37, 22, 23, 33, 38, 39, 38, 39, 19, 22, 5, 50, 23, 22, 21, 20, 7, 6, 43, 1, 34, 39, 38, 61, 1, 52, 55, 54, 2, 94, 1,
+ 55,215, 92,254,255,158,172, 26,254,203,213, 80, 1, 18,151, 1,184,135,135,244,191,103,227,145,181, 1, 21,190, 72,254,236, 4,
+244, 22,137,114,169, 39, 46, 6, 41, 37,173,115,234, 77,254,167,233, 14, 16,170, 5, 2, 13, 77, 2,254,166, 1, 25, 27, 35,170,
+102,254,155, 67, 45, 20, 55, 33, 37, 6, 65, 46, 17, 59, 32, 4,194,254,211,142,174,254,239,206,119, 1, 58,142,144, 23, 1, 19,
+210,107,139, 75,240,143,158,254,255,183,113, 1, 26,122,134, 13, 1, 24,182, 3,252, 43, 72, 1, 42, 25, 24,254,214, 71, 2,144,
+ 59, 77, 4, 13,234,178, 10, 10,254,214, 3,116,117,143, 47, 38, 40, 21, 1, 40, 65,247, 65, 30, 38, 58, 43, 26, 67, 30, 31, 4,
+ 59, 46, 23, 0, 0, 6, 0, 34, 0, 7, 4,175, 4, 47, 0, 9, 0, 19, 0, 29, 0, 56, 0, 80, 0,105, 0, 0, 1, 62, 1, 39,
+ 54, 55, 22, 6, 7, 38, 3, 38, 6, 7, 38, 39, 54, 22, 23, 6, 5, 20, 22, 23, 6, 7, 46, 1, 55, 22, 1, 6, 35, 34, 39, 38,
+ 39, 7, 6, 7, 6, 35, 34, 39, 22, 54, 55, 54, 39, 55, 22, 55, 23, 6, 23, 30, 1, 3, 22, 23, 22, 7, 51, 22, 23, 22, 29, 1,
+ 46, 1, 35, 6, 7, 39, 54, 39, 53, 54, 55, 54, 38, 1, 38, 53, 52, 55, 54, 23, 39, 38, 39, 54, 55, 14, 1, 23, 22, 31, 1, 6,
+ 23, 7, 38, 7, 38, 6, 2,220, 48, 55, 5, 26, 26, 9, 94, 60, 12, 5, 49,120, 44, 23, 15, 66,177, 53, 18,254,177, 64, 50, 2,
+ 11, 74, 86, 8, 30, 2,171, 77,118, 33, 35,117, 65, 1, 43, 85, 66, 68, 88, 91,102,185, 42, 59, 45, 49, 48, 41, 46, 46, 67, 44,
+157,183,115, 66, 35, 72, 2, 75, 85,139, 9,149, 80,130, 93, 49, 5, 50,129, 60, 48, 27,252,209, 3, 86, 81,137, 1, 31, 2, 12,
+196,125, 37, 39, 72,136, 1, 54, 8, 45, 84,125, 94,128, 1, 36, 29,107, 55, 10, 4, 82,151, 26, 27, 1,135, 27, 5, 31, 16, 20,
+ 50, 7, 39, 23,198, 55,102, 23, 27, 24, 33,157, 65, 4,254, 92, 59, 5, 25,121, 1, 63, 49, 33, 53, 48, 66, 69,116,132, 30, 34,
+ 33, 28,122,107, 81, 59, 4, 15, 48,154,113,117, 7, 48, 92,183, 7,111,130, 7,105, 29, 58, 19, 53, 22,111, 80,165,253, 90, 17,
+ 17,106,115, 88, 4, 1, 70, 97,192, 80, 74,194, 71,108, 27, 59, 24, 52, 26,101, 4, 1,106, 0, 0, 23, 0, 78,255,255, 4,131,
+ 5, 94, 0, 3, 0, 19, 0, 25, 0, 29, 0, 49, 0, 70, 0, 91, 0,113, 0,139, 0,149, 0,154, 0,159, 0,164, 0,169, 0,174,
+ 0,179, 0,184, 0,189, 0,194, 0,199, 0,204, 0,209, 0,252, 0, 0, 1, 6, 55, 38, 23, 38, 7, 6, 39, 55, 39, 54, 23, 22,
+ 23, 6, 7, 38, 39, 36, 1, 6, 7, 35, 38, 55, 3, 22, 39, 38, 19, 21, 6, 35, 34, 39, 53, 38, 55, 54, 55, 22, 23, 6, 7, 6,
+ 4, 7, 35, 38, 39, 21, 39, 53, 36, 39, 54, 55, 22, 23, 6, 7, 6, 4, 23, 22, 7, 39, 54, 39, 54, 3, 21, 39, 53, 36, 39, 54,
+ 55, 22, 23, 6, 23, 6, 4, 23, 6, 7, 39, 54, 53, 54, 7, 38, 39, 54, 55, 22, 23, 6, 21, 20, 4, 23, 6, 7, 38, 39, 54, 39,
+ 38, 39, 21, 39, 19, 21, 39, 53, 36, 55, 54, 55, 54, 23, 7, 23, 6, 39, 38, 7, 6, 4, 23, 6, 7, 38, 39, 54, 39, 54, 1, 20,
+ 30, 1, 51, 38, 55, 34, 14, 1, 5, 22, 23, 55, 38, 39, 22, 23, 55, 38, 39, 22, 23, 55, 38, 39, 22, 7, 55, 38, 39, 22, 7, 23,
+ 54, 39, 6, 7, 23, 54, 37, 23, 54, 55, 6, 7, 23, 54, 55, 6, 7, 23, 54, 55, 6, 31, 1, 38, 55, 6, 23, 55, 38, 55, 6, 23,
+ 55, 38, 39, 6, 23, 21, 39, 53, 38, 7, 34, 39, 54, 37, 22, 23, 22, 51, 53, 38, 39, 46, 1, 53, 52, 62, 1, 50, 30, 1, 21, 20,
+ 6, 7, 6, 7, 51, 20, 35, 21, 54, 55, 4, 23, 6, 35, 38, 3, 5, 16, 56, 9,112, 10, 43, 87, 68, 84, 99, 39, 72,188, 12, 2,
+130, 64,145, 1, 1,254,162, 88, 28, 14, 1, 79, 96, 61, 19, 32,220, 10, 24, 31, 3,161, 1, 4, 59, 42, 41, 56, 1, 2, 1, 32,
+ 2, 14, 24,107, 68,254,255, 4, 2,118, 47, 80,157, 3, 5, 1,146, 5, 4,107, 45, 74, 12, 1, 75, 68,254,176, 2, 4,104, 71,
+ 97,202, 13, 9, 2, 68, 1, 4,138, 96,150, 2,235,247, 5, 1,103, 66, 68,150, 1,234, 3, 4,160, 30, 54,166, 5, 2,172, 68,
+ 68, 68,254,159, 1, 12,188, 61, 51,100, 84, 68, 87, 44, 9, 3, 2,155, 6, 6,160, 58,103,242, 1, 11,254,149, 17, 30, 17, 28,
+ 28, 16, 31, 17, 1,151,106, 41, 25, 89,138,105, 35, 39, 87,116, 73, 16, 45, 57,119, 49, 1, 56, 36, 94, 2, 23, 56, 2, 59, 46,
+ 47, 55, 45,253, 73, 25, 41,106, 83, 41, 39, 35,105, 92, 18, 45, 16, 73, 77, 15, 57, 2, 49, 68, 59, 56, 23, 2, 37, 97, 55, 47,
+ 46, 7,216, 68, 61,117,246, 82, 78, 1, 66, 22, 82, 1, 1, 2, 2, 19, 21, 21, 38, 39, 37, 22, 21, 18, 3, 3, 1, 1, 81, 22,
+ 1, 66, 78, 82,246,113, 3,207, 32, 22, 18,100, 50, 10, 31, 14, 21, 23, 68, 13, 3,115, 57, 30, 16, 8, 18,253, 16, 31, 56, 67,
+ 32, 3, 91, 24, 34, 8,252,124, 52, 24, 52, 38, 27, 51, 44, 22, 12, 5, 20, 17, 39, 50, 94, 51,159, 82, 12, 84, 40, 66, 63, 29,
+ 18, 8, 23, 35, 39, 57, 67, 45, 13, 11, 18, 33, 21, 1,121,129, 12,126, 35, 90, 49, 20, 19, 6, 15, 29, 48, 62, 78, 63, 30, 25,
+ 36, 23, 37,151, 30, 89, 52, 28, 11, 7, 30, 41, 37, 70, 78, 63, 19, 13, 10, 29, 40, 28, 27,123, 11, 1,219,117, 8,115, 19,105,
+115, 4, 3, 60, 22, 21, 14, 32, 10, 51, 40, 38, 94, 84, 18, 15, 14, 25, 48, 29, 2, 53, 17, 29, 16, 60, 62, 15, 30, 55, 59, 44,
+ 35, 52, 20, 91, 58, 31, 79, 40,118, 65, 17,102, 71,135, 69, 7,116, 89,143, 66, 10,122, 94,126, 52, 23,106, 10, 35, 44, 59, 16,
+ 98, 31, 58, 91, 39,126, 17, 65,118, 64,126, 7, 69,135, 81,130, 10, 66,143, 97,107, 23, 52,126, 95,170,190, 6,178, 72, 35,152,
+ 84, 6, 50, 27, 1, 22, 1, 1, 10, 36, 20, 19, 36, 20, 20, 36, 19, 20, 36, 10, 1, 1, 1, 20, 27, 50, 6, 84,152, 34, 0, 0,
+ 0, 2, 0, 96,255,255, 4,113, 5,216, 0, 7, 0, 36, 0, 0, 1, 38, 39, 6, 7, 22, 23, 54, 7, 38, 39, 54, 55, 22, 23, 22,
+ 7, 51, 50, 55, 17, 38, 7, 35, 17, 20, 23, 33, 54, 53, 17, 35, 38, 7, 17, 22, 51, 2,214, 2,106,106, 1, 7,100,110,175,104,
+ 10, 2,177,177, 3, 4,119,143,158,152,150,160,143, 87,254,209, 86,147,159,150,152,158, 4,221,177, 2, 2,177,142,113, 90,114,
+101,184,243, 2, 2,243,194, 91, 99,254,247, 55, 1,254, 12,181,174,174,181, 1,244, 1, 55, 1, 9, 99, 0, 0, 0, 3, 0,121,
+255,254, 4, 88, 5,218, 0, 3, 0, 32, 0, 44, 0, 0, 1, 21, 51, 53, 39, 53, 51, 21, 51, 21, 35, 21, 51, 5, 21, 33, 17, 23,
+ 21, 39, 3, 35, 3, 39, 53, 23, 17, 33, 53, 33, 53, 35, 53, 19, 51, 17, 33, 53, 33, 53, 35, 21, 33, 21, 33, 1,252,202,182,170,
+126,126, 10, 1,148,254, 98,144,136, 2,176, 2,134,134,254,108, 1,150,118,164, 70, 1, 12,254,244, 70,254,244, 1, 12, 5, 65,
+ 60, 60, 51,102,102,162, 88, 1,175,253,232,139,156,133,254,238, 1,188,134,155,130, 1,113,176, 88,162,252,207, 1,187, 71, 99,
+ 99, 71, 0, 0, 0, 2, 0, 97, 0, 7, 4,112, 6, 2, 0, 7, 0, 32, 0, 0, 1, 17, 51, 50, 54, 52, 38, 35, 1, 17, 33, 50,
+ 22, 21, 20, 6, 43, 1, 21, 55, 51, 9, 1, 35, 39, 21, 35, 53, 7, 35, 9, 1, 51, 2,109,171, 96,104,104, 96,254,206, 1, 50,
+169,174,174,169,171,179,180,254,177, 1, 96,179,196,136,209,179, 1,104,254,182,181, 5,124,254, 59,118,217,118,252,188, 3,202,
+183,177,178,182,252,194,254,147,254,125,214,214,228,228, 1,138, 1,102, 0, 0, 0, 1, 0,204,255,251, 4, 5, 5,205, 0, 31,
+ 0, 0, 1, 51, 23, 21, 51, 23, 21, 7, 35, 21, 33, 23, 21, 7, 33, 17, 7, 35, 39, 17, 33, 39, 53, 55, 33, 53, 35, 39, 53, 55,
+ 51, 53, 2, 12,182, 6,175, 6, 6,175, 1, 54, 7, 7,254,202, 6,182, 6,254,204, 6, 6, 1, 52,174, 5, 5,174, 5,205, 5,
+154, 6,148, 6,112, 6,152, 5,252,134, 5, 5, 3,122, 5,152, 6,112, 6,148, 6,154, 0, 0, 0, 1, 0, 55, 0, 1, 4,154,
+ 4,100, 0, 43, 0, 0, 1, 33, 23, 21, 7, 35, 17, 33, 53, 55, 51, 23, 17, 7, 35, 39, 53, 33, 17, 51, 23, 21, 7, 33, 39, 53,
+ 55, 51, 17, 33, 21, 7, 35, 39, 17, 55, 51, 23, 21, 33, 17, 35, 39, 53, 1,196, 1, 73, 4, 4,120, 1,172, 5, 79, 5, 5, 79,
+ 5,254, 84,120, 4, 4,254,183, 4, 4,128,254, 83, 5, 86, 4, 4, 86, 5, 1,173,128, 4, 4,100, 5, 89, 4,254, 92,121, 5,
+ 5,254,183, 5, 5,118,254, 86, 4, 80, 4, 4, 80, 4, 1,170,118, 5, 5, 1, 73, 5, 5,121, 1,164, 4, 89, 0, 2, 0, 30,
+ 0, 3, 4,179, 5, 39, 0, 27, 0, 44, 0, 0, 1, 51, 50, 23, 35, 39, 32, 3, 6, 21, 16, 5, 22, 51, 55, 21, 6, 7, 6, 43,
+ 1, 32, 3, 38, 53, 16, 37, 54, 1, 51, 50, 23, 51, 21, 7, 22, 21, 39, 7, 35, 53, 55, 39, 53, 51, 2,109, 16,175,166, 4,189,
+254,240,165, 74, 1, 14,108,123,203,126,109, 64, 43, 22,254,221,188,104, 1, 52,136, 1,250, 2, 5, 49,165,133, 52,140,134, 2,
+ 52,136,168, 5, 39,129, 48,254,239,138,163,254,190,188, 62, 44, 5, 95, 22, 10, 1, 23,169,205, 1,118,210, 78,254,107,177, 3,
+110,165, 15,109,109, 3,177,110, 3, 0, 0, 0, 0, 4, 0, 8, 0, 0, 4,201, 4,193, 0, 22, 0, 79, 0, 98, 0,115, 0, 0,
+ 1, 22, 51, 50, 55, 22, 51, 50, 55, 53, 51, 23, 21, 20, 15, 1, 34, 39, 6, 35, 34, 39, 52, 23, 51, 22, 23, 50, 21, 3, 51, 54,
+ 17, 52, 39, 53, 22, 29, 1, 20, 7, 6, 7, 21, 22, 59, 1, 21, 6, 43, 1, 34, 7, 39, 35, 34, 39, 53, 51, 50, 55, 53, 39, 38,
+ 39, 38, 53, 52, 63, 1, 21, 6, 21, 16, 23, 53, 3, 53, 55, 50, 39, 21, 6, 7, 6, 21, 20, 23, 21, 35, 38, 39, 38, 53, 52, 55,
+ 54, 51, 52, 37, 22, 23, 22, 29, 1, 20, 7, 6, 7, 52, 55, 54, 61, 1, 16, 39, 1,220, 22, 52, 38, 26, 31, 35, 54, 17, 4, 2,
+ 56, 25, 36, 28, 27, 36, 66, 13,144, 2, 41, 27, 7, 8, 1,238, 90,181,182, 62, 38, 65,134, 21, 95, 59,105, 17, 56, 56,117, 45,
+111, 49, 98, 70, 71,102, 29, 81,162, 27, 95,239, 15, 3, 28,208, 77, 53,109,119, 2,128, 76, 31,218, 98, 29, 2, 4,107,106,143,
+135, 73, 25, 44, 75,242, 4,192, 61, 39, 39, 56, 5, 32, 4, 48, 22, 3, 35, 35, 82, 27,109, 52, 9, 4,252,218,185, 1, 43,158,
+168, 2,175,225, 29,220,180, 53, 18, 4, 33, 4, 27, 80, 80, 23, 4, 34, 3, 52, 92, 61,143,144,209,187, 25, 4,156,184,254,232,
+199, 2, 2,142, 18,138, 34, 5, 56, 81,165,195,189,174, 1, 60,189, 87, 84,218,166, 57, 3, 2, 25, 91,148,176, 38,172,148, 66,
+ 5, 6, 67,142,155, 2, 1, 40,198, 0, 0, 0, 0, 3, 0,103,255,249, 4,106, 5, 91, 0, 84, 0, 95, 0,103, 0, 0, 1, 50,
+ 23, 15, 1, 22, 23, 22, 21, 20, 7, 21, 35, 21, 50, 55, 54, 53, 52, 39, 55, 51, 22, 21, 16, 3, 38, 35, 34, 21, 20, 23, 22, 7,
+ 6, 35, 6, 39, 38, 39, 21, 6, 23, 20, 35, 34, 53, 54, 61, 1, 6, 21, 6, 39, 34, 39, 52, 54, 39, 52, 35, 34, 7, 2, 17, 52,
+ 55, 51, 23, 6, 21, 20, 23, 22, 23, 53, 35, 53, 38, 53, 52, 55, 47, 1, 54, 3, 20, 23, 51, 54, 53, 52, 39, 6, 7, 6, 37, 6,
+ 21, 20, 23, 54, 53, 52, 2,105, 61, 75, 17, 14,117, 47, 51,188,110,111,131,124,115, 20, 4,215,137,110, 73, 51,110, 30, 2, 12,
+ 39, 59, 6, 54, 87, 4, 78, 96,102, 73,141, 7, 58, 37, 13,141, 3, 43, 75,107,141,209, 5, 19,115,197, 58,111,109,188,219, 22,
+ 15, 80,189,124, 4, 64, 26, 82, 47, 37, 1, 83, 32, 60,133, 5, 91, 69, 14,114, 42, 74, 75, 78,183, 90, 69,110,118,145,182,162,
+105, 17,152,237,254,247,254,226,160, 41, 26,135, 37, 42, 54, 8, 38,219, 45,138, 67,108, 54, 55,106, 71,135, 86,176, 34, 2, 54,
+ 59,155, 30, 37,159, 1, 10, 1, 50,214,153, 17,112,160,231,150, 43, 16,110, 69, 85,187,175, 95,114, 17, 66,254, 40,134, 69, 97,
+128, 76,116, 23, 68, 58,149,106, 91,126, 94, 57,154,140, 0, 0, 0, 1, 0, 15, 0, 5, 4,194, 5, 34, 0, 50, 0, 0, 1, 50,
+ 23, 22, 21, 20, 7, 23, 7, 35, 39, 6, 35, 34, 39, 21, 3, 35, 38, 39, 54, 1, 54, 51, 22, 51, 50, 55, 39, 7, 35, 38, 39, 55,
+ 22, 21, 7, 22, 23, 53, 54, 61, 1, 52, 39, 38, 43, 1, 34, 7, 54, 2,171,190,169,120,100,156,113, 2,149,133,175,137,115,209,
+ 2,165, 3, 21, 1, 22, 19, 6, 91,127,154,121,174, 87, 5,151, 7,188,227,101,185, 23, 54,202,111, 96, 29, 79, 97,137, 5, 33,
+165,136,188,176,121,129,115,149, 96, 77, 3,254,107,123, 6, 22, 1,101, 26, 75, 91,174,101,102, 10,226, 12, 5,139,153, 12, 1,
+ 79,109, 31,222, 89, 60, 48,125, 0, 5, 0, 27, 0, 5, 4,182, 4,160, 0, 11, 0, 18, 0, 22, 0, 26, 0, 33, 0, 0, 19, 52,
+ 0, 51, 50, 0, 21, 20, 0, 35, 34, 0, 55, 20, 23, 1, 3, 6, 0, 19, 22, 23, 27, 1, 54, 55, 9, 1, 54, 53, 52, 0, 39, 17,
+ 27, 1, 89,244,245, 1, 89,254,167,245,244,254,167,120, 95, 1, 80, 2,154,254,237,136,139,151, 2, 75,161,134,254,217, 1, 92,
+ 89,254,236,166, 2, 81,245, 1, 90,254,166,245,244,254,169, 1, 87,244,180, 95, 1,139, 1, 98, 3,254,237,253,241,140, 4, 1,
+229,254, 25, 6,129, 1, 89,254,228, 88,193,196, 1, 19, 3,254,161, 0, 0, 0, 0, 4, 0, 14, 0, 5, 4,195, 4,186, 0, 18,
+ 0, 30, 0, 40, 0, 52, 0, 0, 1, 21, 30, 1, 51, 50, 54, 53, 52, 0, 35, 34, 0, 7, 62, 1, 51, 50, 22, 5, 20, 6, 35, 34,
+ 38, 53, 52, 54, 51, 50, 22, 5, 52, 38, 34, 6, 21, 20, 22, 50, 54, 37, 20, 0, 35, 34, 0, 53, 52, 0, 51, 50, 0, 2,105, 8,
+158,116,118,161,254,179,228,234,254,199, 16, 19,143,120,115,159, 1,113, 49, 31, 34, 48, 48, 34, 32, 48,253,205, 47, 66, 47, 47,
+ 66, 47, 3, 35,254,160,250,250,254,159, 1, 97,250,250, 1, 96, 2,105, 21,114,155,166,124,224, 1, 72,254,199,250,138,144,155,
+127, 33, 47, 47, 33, 34, 48, 48, 34, 34, 48, 48, 34, 33, 47, 48, 32,250,254,161, 1, 95,250,250, 1, 98,254,158, 0, 10, 0, 5,
+ 0,146, 4,204, 5, 57, 0, 14, 0, 62, 0, 68, 0, 74, 0, 80, 0, 86, 0, 92, 0, 98, 0,104, 0,110, 0, 0, 1, 20, 23, 22,
+ 50, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 5, 38, 55, 51, 54, 55, 39, 54, 55, 23, 54, 55, 53, 54, 23, 21, 22, 23, 55, 22, 23,
+ 7, 22, 23, 51, 22, 7, 35, 6, 7, 23, 6, 7, 39, 6, 7, 21, 6, 39, 53, 38, 39, 7, 38, 39, 55, 38, 39, 37, 54, 55, 39, 6,
+ 7, 5, 22, 23, 55, 38, 39, 1, 54, 55, 39, 6, 7, 37, 22, 23, 55, 38, 39, 1, 38, 39, 7, 22, 23, 37, 6, 7, 23, 54, 55, 5,
+ 6, 7, 23, 54, 55, 37, 38, 39, 7, 22, 23, 1,234, 38, 36,104, 37, 36, 37, 37, 51, 52, 36, 38,254, 49, 43, 43, 88, 21, 83, 65,
+ 11, 78, 64, 96,152, 61, 61,142,107, 62, 80, 13, 67, 82, 22, 88, 43, 43, 88, 15, 89, 67, 13, 80, 62,107,142, 61, 61,141,108, 63,
+ 76, 13, 63, 81, 21, 1,139, 26, 28, 9,111, 76, 1, 43, 32, 23,143, 78,110,254,249, 7, 17,159, 59, 18, 2, 80, 19, 5,214, 15,
+ 63,253,252, 16, 8,212, 17, 59, 2, 28, 6, 18,160, 64, 13,254,203, 26, 29, 10,110, 77,254,211, 22, 31,143, 78,110, 2,228, 51,
+ 37, 37, 37, 37, 51, 52, 37, 38, 38, 37,115, 61, 61,143, 96, 63, 74, 12, 62, 80, 23, 87, 44, 44, 87, 17, 87, 63, 11, 75, 63, 95,
+144, 61, 61,137,102, 63, 72, 8, 63, 80, 23, 87, 44, 44, 87, 18, 85, 63, 8, 72, 63, 94,145,234, 15, 8,210, 17, 60,133, 8, 15,
+155, 61, 16,254,161, 29, 21,133, 75,101, 43, 24, 26, 8, 99, 76,254,171, 24, 32, 13,109, 67,190, 29, 27,134, 80, 96,107, 14, 8,
+213, 24, 60,129, 7, 15,151, 60, 24, 0, 0, 0, 0, 5, 0, 33, 0,164, 4,176, 5, 52, 0, 15, 0, 30, 0, 40, 0, 48, 0, 56,
+ 0, 0, 19, 52, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 55, 20, 23, 22, 51, 50, 55, 54, 53, 52, 0, 35, 34, 7,
+ 6, 1, 38, 7, 35, 18, 37, 4, 19, 35, 38, 55, 38, 39, 54, 55, 22, 23, 6, 5, 38, 39, 54, 55, 22, 23, 6, 33,171,171,241,243,
+171,170,170,171,243,241,171,171,118,137,136,192,193,137,137,254,238,193,192,136,137, 1,211,164, 61, 54, 15, 1, 12, 1, 4, 15,
+ 53, 78, 39, 86, 3, 4, 91, 83, 4, 4,254, 46, 85, 4, 5, 91, 82, 5, 5, 2,234,243,171,172,172,171,243,241,171,170,170,171,
+241,191,137,138,138,137,191,195, 1, 16,136,136,254,222, 10,204, 1, 16, 14, 18,254,245,202,175, 4, 88, 91, 5, 7, 86, 91, 4,
+ 4, 88, 91, 5, 7, 86, 91, 0, 0, 5, 0, 33, 0,164, 4,176, 5, 52, 0, 15, 0, 30, 0, 40, 0, 48, 0, 56, 0, 0, 19, 52,
+ 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 55, 20, 23, 22, 51, 50, 55, 54, 53, 52, 0, 35, 34, 7, 6, 1, 22, 55,
+ 51, 2, 5, 36, 3, 51, 22, 1, 38, 39, 54, 55, 22, 23, 6, 5, 38, 39, 54, 55, 22, 23, 6, 33,171,171,241,243,171,170,170,171,
+243,241,171,171,118,137,136,192,193,137,137,254,238,193,192,136,137, 1,209,166, 61, 54, 15,254,243,254,253, 15, 51, 81, 1, 78,
+ 86, 3, 4, 91, 83, 4, 4,254, 46, 85, 4, 5, 91, 82, 5, 5, 2,234,243,171,172,172,171,243,241,171,170,170,171,241,191,137,
+138,138,137,191,195, 1, 16,136,136,254,119, 9,204,254,240, 14, 19, 1, 10,202, 1, 39, 4, 88, 91, 5, 7, 86, 91, 4, 4, 88,
+ 91, 5, 7, 86, 91, 0, 0, 0, 0, 4, 0, 33, 0,164, 4,176, 5, 52, 0, 15, 0, 25, 0, 33, 0, 41, 0, 0, 19, 52, 55, 54,
+ 51, 50, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 37, 35, 18, 5, 36, 19, 39, 6, 39, 6, 1, 38, 39, 6, 7, 22, 23, 54, 37, 38,
+ 39, 6, 7, 22, 23, 54, 33,171,171,241,243,171,170,170,171,243,241,171,171, 1, 52, 62, 18, 1, 59, 1, 68, 18, 64, 75,199,178,
+ 2, 6, 6, 99,110, 6, 5,103,107,254, 63, 5,100,110, 5, 4,104,107, 2,234,243,171,172,172,171,243,241,171,170,170,171,237,
+254,189, 22, 17, 1, 73, 2,248, 11, 10, 1,214,107, 8, 6,112,105, 7, 7,110,105, 8, 6,112,105, 7, 7, 0, 0, 10, 0, 33,
+ 0,164, 4,176, 5, 52, 0, 7, 0, 12, 0, 19, 0, 34, 0, 42, 0, 50, 0, 58, 0, 65, 0, 73, 0, 88, 0, 0, 1, 51, 23, 17,
+ 7, 35, 39, 17, 5, 23, 21, 7, 39, 37, 23, 7, 35, 38, 39, 53, 5, 50, 31, 1, 20, 7, 6, 35, 34, 39, 38, 53, 52, 55, 54, 5,
+ 33, 23, 21, 7, 33, 39, 53, 37, 33, 23, 21, 7, 33, 39, 53, 7, 51, 22, 23, 21, 7, 39, 53, 37, 51, 23, 21, 7, 39, 53, 37, 51,
+ 23, 17, 7, 35, 39, 17, 3, 6, 21, 20, 23, 22, 51, 50, 55, 54, 53, 39, 38, 35, 34, 2, 77, 61, 5, 5, 61, 4, 1,188, 44,194,
+ 47,253,165,197, 48, 3,156, 35, 1,182,168, 72, 10,153, 56, 38,141, 79, 29,148, 54,253,227, 1, 9, 5, 5,254,247, 4, 3,124,
+ 1, 14, 5, 5,254,242, 5, 55, 2,105, 89, 48,194,254, 54, 2, 46,193, 47, 1,164, 61, 5, 5, 61, 4, 29,101, 19, 54, 97, 25,
+ 38,105, 7, 49,114, 31, 5, 52, 5,254,238, 5, 5, 1, 18,122, 48, 2,199, 49,185,198, 50,156, 43, 3,142,176, 75,147, 78, 19,
+131, 50, 72,140, 81, 21,214, 5, 62, 5, 5, 62, 5, 5, 62, 5, 5, 62,219,102, 94, 2, 50,198, 3, 34, 47, 3,198, 49, 3, 93,
+ 5,254,238, 5, 5, 1, 18, 1,211, 56, 96, 49, 34, 89, 13, 52,102, 50,121, 0, 0, 2, 0,156, 0, 5, 4, 53, 5,198, 0, 23,
+ 0, 43, 0, 0, 1, 32, 1, 22, 21, 16, 5, 6, 43, 1, 34, 39, 53, 36, 55, 54, 17, 16, 37, 38, 39, 53, 52, 55, 23, 21, 4, 17,
+ 16, 5, 7, 21, 51, 50, 55, 54, 55, 54, 61, 1, 16, 1, 38, 35, 1, 59, 1,133, 1, 12,104,254,122,176,173, 48, 47, 79, 1, 16,
+123,153,254,183,134, 91,146, 40, 1,194,254,180, 42, 6, 84,156,229, 81, 28,254,171,161,155, 5,197,254,141,170,195,254,126,253,
+ 96, 14, 6, 78,174,199, 1, 8, 1,138,220, 79, 16, 3, 10, 14, 61, 3,194,254, 28,254,116,228, 24, 4, 82,150,240, 91, 92, 9,
+ 1, 56, 1, 1,100, 0, 0, 0, 0, 2, 0,149, 0, 7, 4, 60, 5,223, 0, 23, 0, 43, 0, 0, 37, 32, 1, 38, 53, 16, 1, 54,
+ 59, 1, 50, 23, 21, 4, 7, 6, 17, 16, 5, 22, 23, 21, 20, 7, 39, 53, 36, 17, 16, 37, 55, 53, 35, 34, 7, 6, 7, 6, 29, 1,
+ 16, 1, 22, 51, 3,154,254,118,254,238,104, 1,140,178,178, 48, 46, 80,254,236,126,154, 1, 78,136, 94,150, 40,254, 56, 1, 80,
+ 44, 6, 86,160,232, 82, 28, 1, 90,164,158, 7, 1,121,173,198, 1,136, 1, 1, 99, 15, 7, 79,177,203,254,245,254,112,225, 79,
+ 16, 4, 10, 14, 62, 3,197, 1,237, 1,145,232, 24, 3, 83,150,245, 92, 94, 9,254,194,254,252,102, 0, 0, 0, 0, 2, 0,189,
+255, 96, 4, 20, 5,171, 0, 49, 0, 66, 0, 0, 1, 22, 23, 22, 21, 20, 7, 6, 7, 21, 55, 21, 7, 23, 35, 53, 35, 53, 51, 39,
+ 38, 39, 38, 53, 52, 55, 54, 55, 38, 39, 38, 61, 1, 51, 21, 20, 23, 22, 23, 51, 54, 55, 54, 61, 1, 51, 21, 20, 7, 6, 7, 35,
+ 6, 7, 6, 21, 20, 23, 22, 51, 50, 55, 54, 53, 52, 39, 38, 3, 79, 38, 34,125,124,102,135,204,208, 1,122,191,191, 2,139,103,
+125,125, 34, 38, 38, 34,125,134, 85, 81,110, 36,109, 81, 85,134,125, 34,250, 36,110, 81, 85, 86, 86,123,120, 86, 86, 85, 81, 4,
+ 60, 25, 34,123,179,177,117, 94, 14,197, 2, 94, 1,191,192, 92,197, 13, 95,117,177,179,123, 34, 25, 23, 35,124,177, 8, 10,122,
+ 85, 79, 6, 6, 79, 85,122, 10, 8,177,124, 35, 89, 6, 79, 84,123,122, 81, 80, 80, 81,122,123, 84, 79, 0, 0, 0, 2, 0,145,
+255,155, 4, 64, 5, 62, 0, 14, 0, 41, 0, 0, 1, 52, 39, 38, 35, 34, 7, 6, 21, 20, 22, 51, 50, 55, 54, 5, 38, 53, 52, 55,
+ 54, 51, 50, 23, 22, 21, 20, 7, 6, 7, 21, 55, 21, 7, 23, 35, 39, 35, 53, 51, 39, 38, 3,173, 96, 95,132,135, 95, 95,190,135,
+132, 95, 96,253,111,139,138,138,197,194,138,138,137,113,147,223,228, 2,135, 2,209,209, 1,153, 3,107,135, 93, 94, 94, 93,135,
+134,178, 89, 89,193,129,195,197,136,137,137,136,197,195,129,104, 15,217, 1,103, 2,209,211,102,217, 14, 0, 0, 0, 2, 0,145,
+255,155, 4, 64, 5, 62, 0, 12, 0, 39, 0, 0, 1, 34, 7, 6, 16, 22, 51, 50, 55, 54, 16, 39, 38, 39, 55, 35, 53, 51, 55, 51,
+ 7, 23, 21, 39, 21, 22, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 53, 52, 55, 54, 2,106,135, 95, 95,190,135,132, 95, 96, 96, 95,
+200, 1,209,209, 2,135, 2,228,223,147,113,137,138,138,194,197,138,138,139,113, 2,165, 89, 88,254,242,186, 93, 93, 1, 14, 88,
+ 89,134,218,102,211,210, 1,104, 2,218, 15,104,129,195,196,136,137,137,136,196,195,129,106, 0, 0, 2, 0, 21, 0,154, 4,188,
+ 5, 48, 0, 13, 0, 39, 0, 0, 1, 38, 39, 38, 7, 6, 20, 23, 22, 51, 22, 55, 54, 38, 19, 6, 43, 1, 34, 39, 38, 53, 39, 52,
+ 55, 54, 23, 22, 23, 1, 37, 55, 33, 17, 7, 17, 1, 22, 23, 22, 2,162, 90,123,122, 91, 90, 90, 91,126,127, 92, 89, 8, 16,131,
+182, 1,185,130,129, 2,131,130,178,178, 87, 1, 26,254,222,109, 1,130,112,254,231, 78, 7, 6, 3, 35, 90, 4, 4, 88, 91,254,
+ 91, 89, 1, 90, 91,246,254, 80,128,128,129,183, 3,182,131,129, 7, 6, 81, 1, 16, 2,109,254,128,112, 1, 35,254,239, 84,178,
+177, 0, 0, 0, 0, 1, 0, 71, 0, 42, 4,138, 5,174, 0, 31, 0, 0, 1, 53, 50, 55, 54, 52, 39, 38, 35, 34, 7, 6, 29, 1,
+ 35, 52, 54, 51, 50, 23, 22, 21, 20, 7, 51, 17, 51, 17, 35, 17, 33, 53, 1,232,115, 80, 81, 80, 80,116,114, 81, 80,142,244,173,
+177,121,122,103,214,143,143,252, 76, 2, 31, 1, 81, 81,228, 81, 80, 80, 81,114, 2,174,246,123,123,174,159,116, 3,143,250,124,
+ 1,103,142, 0, 0, 1, 0,174, 0, 42, 4, 35, 5,174, 0, 34, 0, 0, 1, 35, 53, 51, 53, 51, 21, 51, 21, 35, 17, 54, 51, 50,
+ 23, 22, 21, 20, 6, 29, 1, 35, 52, 55, 54, 53, 52, 38, 35, 34, 7, 6, 21, 17, 35, 1, 18,100,100,143,168,168,105,144,167,113,
+113,132,143, 67, 66,146,105,103, 73, 73,143, 4,117,143,170,170,143,254,147,103,122,121,177, 85,216,114, 2,125,112,112, 68,116,
+160, 80, 81,115,254, 95, 0, 0, 0, 2, 0, 67, 0,133, 4,142, 5, 83, 0, 13, 0, 55, 0, 0, 1, 34, 7, 6, 21, 20, 22, 50,
+ 55, 54, 53, 52, 39, 38, 55, 22, 23, 22, 21, 20, 7, 6, 35, 34, 38, 53, 52, 55, 54, 55, 17, 35, 17, 35, 53, 51, 17, 35, 53, 51,
+ 17, 51, 17, 51, 17, 51, 17, 51, 21, 35, 17, 51, 21, 35, 17, 35, 2,104, 46, 32, 32, 64, 92, 32, 33, 32, 32, 16, 50, 40, 62, 62,
+ 63, 90, 87,126, 62, 39, 51,237,251,127,127,251,237,124,237,250,125,125,250,237, 1,203, 33, 32, 45, 47, 64, 32, 32, 47, 45, 32,
+ 33, 94, 15, 39, 63, 88, 89, 63, 63,126, 89, 88, 63, 40, 14, 1, 70,254,152,125, 2, 82,125,254,152, 1,104,254,152, 1,104,125,
+253,174,125, 1,104, 0, 0, 0, 0, 1, 0, 76, 0,133, 4,133, 5, 83, 0, 60, 0, 0, 1, 21, 35, 53, 35, 53, 51, 53, 38, 39,
+ 38, 39, 53, 7, 39, 55, 51, 23, 21, 39, 21, 51, 21, 35, 22, 23, 22, 23, 17, 7, 39, 55, 51, 23, 21, 39, 17, 54, 55, 54, 61, 1,
+ 51, 53, 7, 39, 55, 51, 23, 21, 39, 21, 49, 21, 20, 7, 6, 7, 21, 51, 21, 2,167,124,144,144,135,101,123, 1,118, 1,119,125,
+119,119, 2, 2, 1, 85, 65, 84,119, 1,120,124,120,120, 83, 64, 87, 1,119, 1,120,125,118,118,124,100,136,144, 1, 31,154,154,
+124,114, 18,101,123,177, 69,117,115,126,126,115,117, 69, 2,124, 86, 65, 16, 2, 75,116,114,127,127,114,116,253,182, 16, 64, 88,
+123, 1, 73,117,115,126,126,115,117, 73, 4,173,123,100, 19,114,124, 0, 0, 0, 0, 2, 0,215, 0, 42, 3,250, 5,174, 0, 18,
+ 0, 29, 0, 0, 19, 33, 32, 23, 22, 21, 20, 7, 6, 35, 33, 17, 33, 23, 21, 7, 33, 39, 17, 23, 17, 33, 50, 55, 54, 55, 52, 39,
+ 38, 35,223, 1,129, 1, 29, 95, 30,237, 56, 50,254,189, 2, 86, 8, 8,253, 41, 8,137, 1, 51,123, 68, 15, 8,153, 35, 77, 5,
+174,197, 72, 90,251, 87, 16,253,207, 7,123, 8, 8, 5,115,123,254, 63,122, 25, 75,155, 56, 16, 0, 1, 0, 24, 0, 1, 4,185,
+ 5, 33, 0, 32, 0, 0, 37, 16, 2, 35, 34, 2, 23, 35, 38, 53, 52, 54, 51, 32, 19, 22, 23, 54, 55, 18, 33, 50, 22, 21, 20, 7,
+ 35, 54, 2, 35, 34, 2, 17, 2, 59,205,122, 92, 41, 77, 97, 66,117,104, 1, 11, 95, 5, 4, 3, 5, 95, 1, 11,105,116, 66, 97,
+ 77, 40, 93,121,205, 2, 2, 13, 2,164,254,228,142,116,140,116,164,253, 91, 43, 35, 35, 43, 2,165,164,116,140,116,142, 1, 28,
+253, 92,253,243, 0, 2, 0, 53,255,248, 4,156, 4,196, 0, 8, 0, 46, 0, 0, 1, 34, 6, 20, 22, 50, 54, 52, 38, 39, 54, 55,
+ 62, 2, 51, 21, 34, 2, 7, 6, 7, 22, 23, 22, 21, 20, 6, 35, 34, 38, 53, 52, 55, 54, 55, 38, 39, 38, 2, 35, 53, 50, 30, 1,
+ 23, 22, 2,104,113,158,158,225,159,157,114,100, 58, 66, 74,124,141, 94,128,100, 16, 18, 35, 33,112,226,161,160,226,113, 32, 36,
+ 18, 16, 99,131, 93,141,143, 55, 65, 59, 2,186,170,241,169,169,241,170,123, 4, 50, 54,148,142, 88,255, 0, 89, 15, 13, 24, 34,
+122,172,172,242,242,172,172,122, 34, 25, 12, 15, 89, 1, 0, 88,142,148, 54, 50, 0, 2, 0, 27, 0, 12, 4,182, 4,206, 0, 19,
+ 0, 25, 0, 0, 1, 38, 39, 53, 4, 32, 37, 21, 6, 7, 17, 22, 23, 21, 36, 32, 5, 53, 54, 63, 1, 54, 23, 17, 6, 39, 1, 46,
+136,139, 1, 26, 2,106, 1, 23,143,135,135,143,254,233,253,150,254,230,139,136,124,189,189,189,189, 4, 25, 18, 42,120, 73, 73,
+122, 39, 19,252,168, 19, 38,124, 74, 74,120, 44, 17, 9, 21, 21, 3, 70, 21, 21, 0, 4, 0, 52, 0, 50, 4,157, 5, 15, 0, 8,
+ 0, 27, 0, 36, 0, 56, 0, 0, 0, 34, 6, 20, 22, 51, 50, 54, 52, 1, 44, 1, 39, 53, 22, 4, 39, 38, 53, 52, 54, 51, 50, 22,
+ 16, 7, 14, 1, 1, 50, 54, 52, 38, 34, 6, 20, 22, 19, 12, 1, 23, 21, 38, 36, 23, 22, 21, 20, 6, 35, 34, 38, 53, 52, 55, 62,
+ 1, 3,200,156,109,109, 78, 77,109,254,169,255, 0,254,213,125,207, 1,201, 9,108,168,121,122,169, 85, 60,202,254, 22, 77,110,
+110,154,110,109,234, 1, 1, 1, 43,125,207,254, 55, 9,108,168,121,122,169, 85, 60,201, 2,131,124,178,124,124,178,254, 44, 1,
+ 38, 40,117, 79, 31, 35,101,156,138,194,194,254,237, 97, 72, 71, 2,138,124,178,124,124,178,124, 2, 81, 2, 39, 40,115, 79, 30,
+ 35,101,156,139,194,194,139,137, 96, 73, 72, 0, 0, 2, 0, 61,255,253, 4,148, 5, 33, 0, 10, 0, 60, 0, 0, 0, 62, 1, 39,
+ 46, 1, 7, 14, 1, 23, 22, 19, 52, 54, 51, 50, 22, 21, 20, 2, 21, 22, 23, 50, 55, 23, 6, 35, 34, 38, 53, 52, 18, 53, 52, 38,
+ 35, 34, 6, 21, 20, 22, 23, 30, 1, 7, 6, 7, 6, 38, 39, 38, 53, 52, 55, 54, 55, 54, 23, 54, 38, 1, 68,132, 57, 25, 26,130,
+ 66, 66, 56, 26, 26,205,196,158,151,192,255, 3,118, 63, 87, 58,112, 98, 87,126,252,144,116,112,132, 41, 22, 32, 14, 34, 45,102,
+102,201, 41, 20, 24, 45,103,116,112, 21, 81, 1, 64, 51,131, 65, 65, 58, 26, 26,129, 65, 67, 2,106,141,177,194,155,165,254, 71,
+158,109, 3, 78, 63,105,106, 98,175, 1,166,171,118,145,136,114, 53,127, 54, 87,192, 71,101, 40, 40, 87,105, 48, 49, 53, 52,100,
+ 41, 45, 63, 1,195, 0, 0, 0, 0, 2, 0, 47,254,234, 4,162, 4,127, 0, 54, 0, 63, 0, 0, 1, 50, 22, 21, 62, 1, 51, 50,
+ 22, 29, 1, 62, 1, 51, 50, 22, 21, 16, 5, 20, 23, 35, 38, 39, 6, 7, 53, 54, 55, 39, 17, 54, 39, 14, 1, 7, 17, 35, 17, 52,
+ 38, 7, 38, 6, 7, 17, 35, 17, 52, 39, 51, 22, 23, 62, 1, 1, 17, 54, 19, 52, 38, 7, 34, 6, 1,193, 45, 83, 29,139, 53, 44,
+ 57, 34, 92, 48, 43, 70,254,244,103,118, 33, 52,117,124,135, 87, 6, 2, 34, 41, 94, 44,107, 22, 25, 29,127, 13,105,107,100, 83,
+ 26, 16,129, 1,242,182, 17, 33, 21, 21,101, 4,127,152, 98, 91,159,128,168,154, 95, 91,177,209,254,199,245, 72,148, 31,124, 78,
+ 5, 89, 21, 67,166, 2,142,242, 1, 1,166,153,253, 58, 2,194,246, 82, 1, 1,174,164,253, 72, 3, 66,146,146, 61,134, 71,144,
+253, 96,254, 83,191, 1, 3,148,110, 4,158, 0, 0, 2, 0, 85, 0,181, 4,124, 4,234, 0, 3, 0, 35, 0, 0, 19, 33, 21, 33,
+ 1, 33, 53, 51, 38, 53, 52, 54, 51, 50, 22, 21, 20, 7, 33, 21, 33, 53, 35, 54, 55, 54, 53, 52, 38, 34, 6, 21, 20, 23, 22, 23,
+ 85, 4, 39,251,217, 1,140,254,116,252, 48,183,132,132,184, 48, 1, 20,254, 90, 1, 13, 12, 61,121,173,121, 61, 11, 13, 1, 58,
+133, 1, 93,134, 90,115,162,227,227,162,115, 90,134,134, 11, 15, 74,106,107,149,149,107,106, 74, 15, 11, 0, 0, 0, 1, 0, 50,
+255,102, 4,159, 4,198, 0, 52, 0, 0, 37, 20, 22, 23, 51, 53, 51, 23, 7, 39, 53, 35, 34, 39, 38, 39, 3, 18, 39, 14, 1, 7,
+ 17, 35, 17, 16, 38, 7, 38, 6, 7, 17, 35, 17, 52, 39, 51, 22, 23, 62, 1, 51, 50, 22, 21, 62, 1, 51, 50, 22, 29, 1, 17, 3,
+ 89, 69, 59, 60, 2,136,136, 2, 60,135, 45, 30, 5, 14, 2, 33, 38, 89, 42,100, 21, 24, 27,120, 13, 99,102, 95, 79, 24, 15,122,
+ 46, 42, 79, 27,132, 50, 41, 55,226, 90,101, 1, 96,141,142, 3, 96, 98, 60, 96, 2,129, 1, 1, 1, 1,176,163,253, 15, 2,237,
+ 1, 5, 87, 1, 1,184,175,253, 30, 3,117,154,156, 65,143, 76,153,161,104, 96,169,136,178,164,253,251, 0, 0, 0, 1, 0, 56,
+ 0, 6, 4,153, 4,199, 0, 19, 0, 0, 1, 33, 53, 33, 21, 49, 21, 17, 35, 17, 7, 17, 35, 17, 1, 39, 1, 33, 53, 33, 3,213,
+254, 95, 2,100,114,192,114,253,149, 80, 2,107,254, 94, 2, 19, 4, 75,123, 85, 1,253,190, 1,199,209,253,190, 1,198,253, 95,
+ 87, 2,161,123, 0, 2, 0, 21, 0, 3, 4,188, 4,207, 0, 39, 0, 47, 0, 0, 1, 50, 18, 55, 54, 51, 50, 22, 21, 20, 6, 35,
+ 34, 39, 14, 1, 7, 35, 53, 55, 54, 19, 38, 2, 35, 34, 2, 23, 7, 52, 2, 39, 53, 50, 22, 23, 54, 55, 62, 1, 1, 22, 51, 50,
+ 55, 38, 39, 34, 2, 50, 88, 67, 20, 90,159,100,125,117,117,127,100, 36,103,113,138,126,100, 86, 41, 52, 48, 29,132, 5,129,116,
+108,120,132, 33, 38, 37, 34,100, 1, 25, 76,107,132, 7, 5,131,125, 4,206,253, 58, 3,181,155, 85,119,140,109,131,177, 3, 97,
+ 1, 3, 1, 52, 13, 2,136,254,115,170, 2,208, 1,151, 5, 79,182,226,165, 72, 75,123,252,215,119,162,129, 15, 0, 2, 0, 89,
+ 1, 64, 4,120, 3,174, 0, 32, 0, 65, 0, 0, 19, 54, 51, 50, 23, 22, 55, 54, 51, 50, 23, 22, 55, 54, 51, 50, 23, 7, 38, 7,
+ 6, 34, 39, 38, 7, 6, 35, 34, 39, 38, 6, 35, 39, 17, 54, 51, 50, 23, 22, 55, 54, 50, 23, 22, 55, 54, 51, 50, 23, 7, 38, 7,
+ 6, 35, 34, 39, 38, 7, 6, 35, 34, 39, 38, 6, 35, 39, 89,231, 82, 32, 9, 35,123, 61, 40, 39, 17, 37,123, 31, 29, 88, 78, 67,
+ 69,122, 62, 79, 18, 38,122, 62, 39, 40, 17, 35,243, 4, 38,231, 82, 31, 10, 35,123, 61, 79, 16, 38,123, 30, 29, 89, 78, 67, 69,
+122, 62, 39, 40, 19, 37,123, 61, 40, 39, 17, 35,243, 4, 38, 1,136,192, 28,101,101, 50, 50,101,101, 25,224, 36,201,108, 54, 54,
+107,100, 50, 51,100,201, 69, 1, 80,192, 28,100,100, 51, 51,100,100, 25,224, 36,202,108, 55, 54,107,100, 51, 52,101,202, 69, 0,
+ 0, 1, 0, 94, 0, 5, 4,115, 5, 35, 0, 28, 0, 0, 1, 7, 2, 3, 7, 0, 19, 33, 53, 33, 2, 1, 23, 18, 19, 51, 18, 19,
+ 55, 0, 3, 33, 7, 33, 18, 1, 39, 2, 3, 2,210,211, 28,243,145, 1, 13, 24,254,253, 1, 3, 25,254,244,145,243, 28,212, 27,
+244,144,254,244, 24, 1, 2, 1,254,253, 26, 1, 12,145,244, 27, 2, 76, 3,254,216,254,231, 2, 1, 51, 1, 16,151, 1, 15, 1,
+ 52, 3,254,232,254,216, 1, 40, 1, 24, 3,254,204,254,241,151,254,240,254,205, 2, 1, 25, 1, 40, 0, 0, 0, 0, 5, 0, 67,
+ 0, 5, 4,142, 4,128, 0, 15, 0, 32, 0, 36, 0, 84, 0,100, 0, 0, 1, 54, 55, 38, 39, 38, 34, 14, 1, 21, 20, 22, 23, 22,
+ 23, 33, 51, 33, 54, 55, 62, 1, 53, 52, 46, 1, 35, 34, 7, 6, 7, 22, 23, 1, 21, 33, 53, 1, 17, 38, 39, 46, 1, 53, 52, 62,
+ 1, 51, 50, 23, 53, 52, 54, 55, 54, 55, 53, 35, 53, 51, 53, 51, 21, 51, 21, 35, 21, 22, 23, 30, 1, 29, 1, 54, 51, 50, 30, 1,
+ 21, 20, 6, 7, 6, 7, 17, 1, 20, 30, 1, 51, 50, 62, 1, 53, 52, 46, 1, 35, 34, 14, 1, 2, 51, 1, 1, 27, 39, 56,120,112,
+ 65, 63, 57, 17, 17, 1, 7,108, 1, 6, 18, 17, 57, 62, 64,113, 60, 59, 57, 39, 26, 1, 1,254,168, 2, 68,253,125, 32, 29, 53,
+ 82, 84,151, 80, 61, 58, 28, 24, 10, 13, 83, 83, 80, 83, 83, 12, 10, 24, 28, 59, 60, 80,151, 84, 82, 52, 30, 32,254, 88, 19, 35,
+ 17, 19, 34, 19, 19, 34, 19, 17, 35, 19, 2,234, 3, 2, 33, 21, 32, 62,114, 62, 62,112, 30, 11, 6, 6, 11, 30,112, 62, 62,114,
+ 62, 32, 21, 33, 2, 3,254, 65,232,232,254,219, 1, 37, 10, 17, 41,150, 82, 83,151, 81, 24, 2, 27, 49, 13, 6, 3, 41, 54, 66,
+ 66, 54, 41, 3, 6, 13, 49, 27, 2, 24, 81,151, 83, 82,150, 41, 17, 10,254,219, 3,112, 20, 32, 20, 20, 32, 20, 18, 34, 18, 18,
+ 34, 0, 0, 0, 0, 8, 0, 86, 0, 0, 4,123, 4,122, 0, 72, 0, 78, 0, 82, 0,104, 0,124, 0,144, 0,165, 0,187, 0, 0,
+ 19, 38, 39, 52, 62, 1, 51, 50, 30, 1, 21, 6, 7, 19, 3, 34, 39, 52, 62, 1, 51, 50, 30, 1, 21, 6, 7, 27, 1, 38, 39, 52,
+ 62, 1, 51, 50, 30, 1, 21, 6, 7, 27, 1, 38, 53, 52, 62, 1, 51, 50, 30, 1, 21, 6, 7, 3, 19, 38, 53, 52, 62, 1, 51, 50,
+ 30, 1, 21, 6, 35, 3, 17, 33, 17, 5, 53, 7, 33, 39, 29, 2, 33, 53, 1, 23, 3, 54, 55, 62, 1, 53, 52, 46, 1, 35, 34, 14,
+ 1, 21, 20, 30, 1, 51, 50, 51, 19, 23, 3, 54, 55, 62, 1, 52, 46, 1, 35, 34, 14, 1, 20, 30, 1, 51, 50, 51, 1, 55, 19, 22,
+ 51, 50, 62, 1, 52, 46, 1, 35, 34, 14, 1, 20, 22, 23, 22, 23, 1, 51, 3, 50, 55, 62, 1, 53, 52, 46, 1, 35, 34, 14, 1, 21,
+ 20, 22, 23, 22, 23, 19, 55, 19, 22, 51, 50, 62, 1, 53, 52, 46, 1, 35, 34, 14, 1, 21, 20, 22, 23, 22, 23,169, 73, 9, 22, 41,
+ 22, 22, 41, 22, 3, 44,183, 40, 63, 14, 22, 41, 23, 22, 40, 23, 2, 35,144, 33, 51, 1, 23, 40, 21, 22, 41, 23, 3, 51, 29,142,
+ 36, 23, 41, 21, 23, 41, 22, 8, 66, 71,197, 33, 23, 40, 22, 23, 40, 22, 10, 75,123,253,109, 2,103,138,254,234,140, 2, 44,253,
+180, 59,177, 5, 5, 14, 16, 16, 27, 15, 14, 26, 17, 16, 27, 14, 6, 6,238,104,143, 4, 4, 13, 15, 15, 27, 14, 15, 27, 15, 15,
+ 27, 15, 5, 6, 1, 73, 88, 73, 4, 4, 14, 29, 14, 16, 27, 14, 14, 27, 16, 16, 13, 6, 6,254,238, 76, 36, 14, 12, 13, 16, 16,
+ 26, 15, 14, 28, 15, 15, 14, 11, 12,227, 80,127, 8, 9, 14, 27, 15, 16, 26, 14, 16, 26, 15, 15, 13, 3, 3, 3, 12, 2, 72, 22,
+ 39, 21, 21, 39, 22, 49, 16,254,124, 2, 26, 71, 21, 39, 21, 21, 39, 21, 35, 26,253,196, 2,115, 23, 37, 22, 39, 20, 20, 39, 22,
+ 41, 19,253,139, 2, 55, 36, 32, 21, 39, 21, 21, 39, 21, 65, 12,253,236, 1,138, 27, 32, 22, 39, 21, 21, 39, 22, 72,254,158,254,
+ 84, 1,172,221,172, 57, 46,161, 37,126,126, 1, 4, 32, 1,147, 2, 3, 8, 27, 14, 16, 26, 16, 16, 26, 16, 14, 27, 15,254,114,
+ 24, 2, 70, 2, 2, 8, 27, 29, 27, 15, 15, 27, 29, 27, 15,253,195, 20, 2, 41, 1, 15, 27, 29, 28, 14, 14, 28, 29, 27, 8, 3,
+ 2,253,188, 2,126, 8, 8, 26, 16, 14, 27, 15, 15, 27, 14, 16, 26, 8, 6, 2,253,151, 32, 1,119, 2, 16, 26, 16, 14, 28, 14,
+ 14, 28, 14, 16, 26, 8, 2, 1, 0, 5, 0,112, 0, 0, 4, 97, 5, 29, 0, 29, 0, 33, 0, 39, 0, 45, 0, 50, 0, 0, 1, 51,
+ 21, 51, 53, 51, 21, 35, 21, 7, 17, 23, 21, 51, 21, 33, 53, 51, 53, 55, 51, 17, 35, 39, 53, 35, 53, 51, 21, 51, 1, 53, 33, 21,
+ 1, 55, 53, 33, 21, 23, 17, 7, 21, 33, 53, 39, 53, 17, 55, 33, 17, 1,237,242,150,236,101, 80, 80,101,252, 15,101, 81, 1, 1,
+ 81,101,232,149, 2, 68,252,112, 2,225, 72,253, 62, 72, 64, 2,178, 65, 1,253,206, 5, 29,136,136,142,126,131,254, 0,130,125,
+143,143,125,133, 1,252,132,126,142,136,251,156, 48, 48, 3,109,114, 84, 84,114,253,199,101,112,112,101, 45, 1,221, 2,254, 33,
+ 0, 4, 0,222,255,248, 3,243, 4,197, 0, 55, 0, 67, 0, 81, 0, 94, 0, 0, 1, 38, 53, 52, 55, 54, 55, 38, 39, 38, 39, 53,
+ 54, 55, 54, 55, 54, 55, 38, 39, 38, 53, 52, 62, 1, 51, 50, 30, 1, 21, 20, 7, 6, 7, 22, 23, 22, 23, 22, 23, 21, 6, 7, 6,
+ 7, 22, 23, 22, 21, 20, 7, 6, 7, 19, 33, 27, 1, 53, 51, 53, 35, 53, 35, 21, 35, 21, 51, 21, 19, 54, 53, 52, 46, 1, 34, 14,
+ 1, 21, 20, 23, 3, 33, 0, 20, 30, 1, 50, 62, 1, 52, 46, 1, 35, 34, 6, 1,194, 25, 26, 6, 9, 49, 29, 34, 1, 1, 34, 35,
+ 64, 23, 24, 21, 14, 18, 37, 64, 35, 33, 64, 37, 17, 13, 22, 23, 24, 63, 36, 35, 1, 1, 35, 30, 48, 9, 7, 25, 26, 1, 2,231,
+252,237,222,220,141,141, 97,141,141,133, 49, 37, 63, 69, 63, 37, 52,182, 2, 21,254,153, 24, 44, 47, 45, 23, 24, 45, 22, 24, 43,
+ 1, 68, 44, 47, 49, 43, 14, 12, 31, 52, 59, 65, 3, 66, 60, 62, 34, 11, 9, 14, 24, 32, 34, 35, 62, 34, 34, 62, 35, 34, 32, 24,
+ 15, 8, 11, 34, 62, 60, 66, 3, 65, 59, 51, 32, 12, 14, 43, 49, 48, 44, 3, 3,254,188, 1, 75, 1, 18,102, 89,101,101, 89,102,
+254,238, 37, 60, 35, 64, 34, 34, 64, 35, 52, 45,254,233, 4, 47, 48, 43, 23, 23, 43, 48, 43, 23, 23, 0, 0, 0, 0, 4, 0,144,
+ 0, 6, 4, 65, 4,199, 0, 30, 0, 42, 0, 51, 0, 86, 0, 0, 1, 54, 38, 55, 22, 7, 0, 19, 33, 38, 53, 52, 36, 39, 6, 7,
+ 6, 7, 39, 7, 38, 39, 54, 39, 54, 55, 46, 1, 55, 22, 23, 7, 54, 59, 1, 6, 21, 20, 43, 1, 34, 39, 53, 3, 23, 20, 7, 35,
+ 34, 61, 1, 54, 19, 38, 39, 6, 22, 7, 6, 7, 22, 7, 22, 23, 55, 7, 54, 55, 54, 55, 22, 4, 23, 20, 23, 37, 2, 1, 50, 53,
+ 35, 54, 38, 39, 6, 22, 7, 2, 7, 11, 42, 73,125, 32, 1,142, 37,252,235, 10, 1, 71, 7, 73, 46, 37,128, 8, 35,113, 26, 74,
+ 12, 39, 59, 17, 10, 31, 84, 44,132, 31, 78, 4, 35, 56, 17, 6, 3, 5, 5, 58, 8, 23, 33,176, 29, 62, 35, 49, 20, 48, 36, 17,
+ 73, 20, 84, 78, 28,110, 23, 86, 66, 44,254,165, 2, 9, 2,199, 31,254,110, 1, 3, 32, 17, 63, 37, 35, 15, 4, 3, 20, 78, 97,
+106,105,254,249,253, 27, 45, 47,130,246, 52, 94, 2,116, 14, 18, 25, 38, 65,234,171, 89, 99, 26, 27,103, 21, 98,225, 51, 37, 29,
+ 39, 24, 12,254,187, 28, 43, 12, 25, 18, 40, 2, 40, 78, 31, 86, 56, 27, 79, 81,196,191, 62, 19, 58, 60, 8,117, 3,141,121,250,
+103, 42, 42, 1, 2,156, 1, 53, 1, 10,107, 60, 88, 62, 27, 0, 0, 4, 0,156, 0, 6, 4, 53, 4,104, 0, 13, 0, 29, 0, 80,
+ 0, 91, 0, 0, 0, 20, 30, 1, 51, 50, 62, 1, 52, 46, 1, 35, 34, 6, 55, 20, 30, 1, 51, 50, 62, 1, 53, 52, 46, 1, 35, 34,
+ 14, 1, 1, 21, 33, 53, 7, 38, 53, 52, 54, 55, 54, 55, 38, 39, 38, 53, 52, 54, 55, 54, 55, 38, 39, 38, 52, 62, 1, 51, 50, 30,
+ 1, 20, 7, 6, 7, 22, 23, 30, 1, 21, 20, 7, 6, 7, 22, 23, 30, 1, 21, 20, 7, 39, 38, 39, 46, 1, 35, 34, 6, 7, 6, 7,
+ 1,200, 43, 76, 41, 43, 76, 42, 43, 77, 41, 40, 76, 72, 12, 21, 11, 12, 21, 12, 12, 22, 11, 10, 22, 12, 1,196,252,227, 62, 9,
+124,110, 28, 30, 22, 16, 32, 64, 58, 20, 22, 20, 11, 17, 33, 58, 31, 30, 59, 33, 15, 13, 19, 20, 23, 56, 65, 31, 17, 22, 28, 29,
+110,125, 9, 69, 3, 48, 52,184, 96, 97,183, 51, 48, 3, 2,216, 84, 76, 42, 42, 76, 84, 77, 40, 40,202, 12, 20, 11, 11, 20, 12,
+ 11, 22, 12, 12, 22,252, 13, 1, 1, 1, 43, 43,120,220, 58, 16, 12, 21, 29, 56, 62, 62,113, 31, 11, 7, 15, 21, 30, 63, 57, 32,
+ 32, 57, 63, 30, 21, 15, 7, 11, 31,113, 62, 62, 56, 29, 21, 12, 16, 58,220,120, 43, 43, 99, 94, 85, 90, 98, 98, 90, 85, 94, 0,
+ 0, 8, 0,106,255,252, 4,103, 4, 37, 0, 15, 0, 32, 0, 36, 0, 84, 0,100, 0,104, 0,121, 0,138, 0, 0, 1, 52, 55, 38,
+ 39, 38, 34, 14, 1, 21, 20, 22, 23, 22, 23, 59, 2, 54, 55, 62, 1, 53, 52, 46, 1, 35, 34, 7, 6, 7, 22, 23, 1, 21, 33, 53,
+ 1, 17, 38, 39, 46, 1, 53, 52, 62, 1, 51, 50, 23, 53, 52, 54, 55, 54, 55, 53, 35, 53, 51, 53, 51, 21, 51, 21, 35, 21, 22, 23,
+ 30, 1, 29, 1, 54, 51, 50, 30, 1, 21, 20, 6, 7, 6, 7, 17, 1, 20, 30, 1, 51, 50, 62, 1, 53, 52, 46, 1, 35, 34, 14, 1,
+ 1, 21, 33, 53, 55, 35, 38, 39, 46, 1, 53, 52, 62, 1, 51, 50, 23, 22, 23, 6, 21, 51, 52, 39, 54, 55, 54, 51, 50, 30, 1, 21,
+ 20, 6, 7, 6, 7, 35, 2, 55, 2, 25, 36, 53,111,104, 60, 58, 53, 16, 16,244,100,243, 17, 16, 52, 58, 59,105, 56, 54, 53, 37,
+ 24, 1, 1,254,193, 2, 26,253,171, 29, 27, 49, 77, 78,141, 74, 57, 54, 25, 23, 9, 12, 77, 77, 74, 77, 77, 12, 9, 22, 26, 54,
+ 56, 74,141, 78, 77, 48, 28, 29,254,118, 18, 32, 16, 18, 32, 17, 17, 32, 18, 16, 32, 18, 1, 43,254, 48,146,199, 13, 12, 43, 47,
+ 48, 85, 45, 44, 44, 29, 21, 2,172, 2, 21, 29, 43, 44, 46, 84, 49, 47, 44, 12, 13,198, 2,172, 2, 3, 30, 20, 29, 57,106, 57,
+ 58,104, 28, 10, 6, 6, 10, 28,104, 58, 57,106, 57, 29, 20, 30, 3, 2,254, 97,215,215,254,240, 1, 16, 9, 16, 38,140, 76, 77,
+140, 75, 22, 1, 26, 45, 13, 5, 2, 39, 50, 61, 61, 50, 39, 2, 5, 13, 45, 26, 1, 22, 75,140, 77, 76,140, 38, 16, 9,254,240,
+ 3, 49, 18, 31, 17, 17, 31, 18, 17, 32, 16, 16, 32,253,169,142,142,147, 5, 8, 24, 86, 47, 47, 88, 47, 23, 17, 25, 2, 2, 2,
+ 2, 25, 17, 23, 47, 88, 47, 47, 86, 24, 8, 5, 0, 3, 0, 54, 0, 4, 4,155, 4,197, 0, 72, 0, 76, 0, 80, 0, 0, 19, 38,
+ 39, 52, 62, 1, 51, 50, 30, 1, 21, 6, 7, 19, 3, 34, 39, 52, 62, 1, 51, 50, 30, 1, 21, 6, 7, 27, 1, 38, 39, 52, 62, 1,
+ 51, 50, 30, 1, 21, 6, 7, 27, 1, 38, 53, 52, 62, 1, 51, 50, 30, 1, 21, 6, 7, 3, 19, 38, 53, 52, 62, 1, 51, 50, 30, 1,
+ 21, 6, 35, 3, 17, 33, 17, 5, 53, 33, 21, 5, 53, 33, 21,141, 77, 10, 24, 44, 23, 23, 44, 23, 4, 46,194, 42, 67, 15, 23, 44,
+ 25, 23, 43, 23, 2, 37,154, 35, 55, 1, 24, 43, 22, 23, 44, 24, 2, 55, 31,150, 37, 23, 44, 22, 25, 43, 24, 9, 70, 75,209, 35,
+ 24, 43, 23, 24, 43, 24, 11, 80,130,253, 68, 2,141,253,178, 2, 78,253,178, 3, 65, 1, 77, 23, 42, 22, 22, 42, 23, 52, 17,254,
+100, 2, 59, 75, 23, 41, 22, 22, 41, 23, 36, 28,253,160, 2,155, 24, 39, 23, 42, 21, 21, 42, 23, 44, 19,253,100, 2, 89, 38, 34,
+ 22, 42, 22, 22, 42, 22, 69, 13,253,204, 1,163, 27, 35, 23, 42, 22, 22, 42, 23, 76,254,136,254, 58, 1,198,165, 63, 63,242, 64,
+ 64, 0, 0, 0, 0, 4, 0,148, 0, 5, 4, 61, 4,197, 0, 3, 0, 7, 0, 37, 0, 41, 0, 0, 1, 53, 33, 21, 1, 53, 33, 21,
+ 19, 51, 21, 51, 53, 51, 21, 35, 21, 7, 17, 23, 21, 51, 21, 33, 53, 51, 53, 55, 51, 17, 35, 39, 53, 35, 53, 51, 21, 51, 1, 53,
+ 33, 21, 3,109,253,248, 2, 68,253,128,205,225,139,219, 94, 74, 74, 94,252, 87, 94, 75, 1, 1, 75, 94,215,139, 2, 26,252,178,
+ 3,178, 76, 76,252,230, 90, 90, 4, 44,125,125,131,117,122,254, 37,121,117,132,132,117,123, 1,216,123,117,131,125,251,235, 45,
+ 45, 0, 0, 0, 0, 2, 0,226, 0, 6, 3,239, 4,199, 0, 52, 0, 64, 0, 0, 1, 52, 55, 54, 55, 38, 39, 38, 39, 53, 54, 55,
+ 54, 55, 54, 55, 38, 39, 38, 53, 52, 62, 1, 51, 50, 30, 1, 21, 20, 7, 6, 7, 22, 23, 22, 23, 22, 23, 21, 6, 7, 6, 7, 22,
+ 23, 22, 21, 20, 7, 19, 33, 19, 38, 55, 53, 51, 53, 35, 53, 35, 21, 35, 21, 51, 21, 1,170, 26, 7, 9, 49, 29, 33, 1, 1, 33,
+ 35, 63, 23, 24, 21, 14, 18, 37, 63, 35, 33, 63, 37, 17, 13, 21, 22, 24, 62, 36, 34, 1, 1, 34, 30, 47, 9, 6, 26, 26,225,252,
+245,220, 21,238,140,140, 95,140,140, 1,168, 49, 43, 14, 12, 30, 52, 58, 65, 3, 65, 60, 61, 34, 11, 8, 15, 23, 32, 33, 35, 61,
+ 34, 34, 61, 35, 33, 32, 23, 16, 7, 11, 34, 61, 60, 65, 3, 65, 58, 51, 31, 12, 14, 43, 49, 47, 43,254,185, 1, 72, 43,228,101,
+ 88,101,101, 88,101, 0, 0, 0, 0, 4, 0,103, 0, 2, 4,106, 5, 32, 0, 34, 0, 46, 0, 55, 0, 61, 0, 0, 1, 54, 38, 55,
+ 30, 1, 7, 51, 20, 35, 0, 19, 33, 38, 53, 52, 0, 39, 6, 39, 6, 39, 55, 7, 38, 39, 54, 39, 54, 55, 54, 38, 55, 22, 23, 7,
+ 21, 22, 59, 1, 50, 53, 52, 55, 35, 34, 7, 3, 21, 20, 59, 1, 54, 53, 39, 34, 1, 23, 4, 19, 51, 2, 1,248, 54, 71, 74, 75,
+ 21, 38, 4, 2, 1,213, 39,252,175, 11, 1,110, 12, 61,108, 82, 93, 42, 94,100, 23, 87, 12, 42, 87, 9, 62, 33, 91, 49,148, 3,
+ 7, 18, 61, 37, 5, 84, 32,101, 25, 9, 62, 6, 54, 1,144, 46, 1, 72, 5, 67, 39, 4, 76, 34,139, 39, 71,128, 13, 1,254,215,
+252,225, 49, 50,140, 1, 0,104,152, 6,132, 4, 91, 70, 25, 72,229,184, 96, 91, 36, 37,111, 23,107,223, 14, 26, 43, 29, 42, 56,
+254,100, 21, 25, 13, 46, 30, 1,248, 78,235,253, 99, 2,232, 0, 0, 1, 0,118, 0, 5, 4, 91, 4,198, 0, 46, 0, 0, 55, 38,
+ 53, 52, 54, 55, 54, 55, 38, 39, 38, 53, 52, 54, 55, 54, 55, 38, 39, 38, 52, 62, 1, 51, 50, 30, 1, 20, 7, 6, 7, 22, 23, 30,
+ 1, 21, 20, 7, 6, 7, 22, 23, 30, 1, 21, 20, 7,127, 9,134,119, 31, 32, 24, 17, 34, 69, 62, 22, 24, 21, 13, 18, 35, 64, 33,
+ 33, 63, 37, 18, 13, 21, 22, 25, 61, 69, 33, 18, 24, 31, 31,119,135, 10, 6, 46, 47,130,238, 64, 17, 12, 24, 30, 61, 67, 68,122,
+ 34, 12, 8, 15, 24, 31, 69, 62, 34, 34, 62, 69, 31, 24, 16, 7, 12, 34,122, 68, 67, 61, 30, 24, 13, 16, 64,238,130, 47, 46, 0,
+ 0, 1, 0,128, 0,133, 4, 81, 5, 79, 0, 35, 0, 0, 1, 22, 23, 22, 23, 22, 29, 1, 20, 7, 6, 35, 34, 39, 35, 21, 20, 23,
+ 35, 53, 54, 53, 39, 35, 7, 6, 35, 34, 47, 1, 53, 52, 55, 0, 63, 1, 2,107, 77,177,195, 5, 32,133, 44, 52,127, 78, 34, 68,
+177, 70, 2, 32, 38, 70,105,153, 63, 7,154, 1, 2, 74, 2, 5, 79,137,227,228, 47, 70, 66, 33,137, 79, 18,182, 10,233,123, 5,
+124,234, 3, 73,109,172, 60, 38,150,167, 1, 61,136, 2, 0, 0, 0, 2, 0, 14, 0,133, 4,195, 5, 77, 0, 24, 0, 50, 0, 0,
+ 1, 50, 23, 22, 21, 50, 55, 54, 51, 50, 23, 22, 29, 1, 20, 7, 0, 7, 35, 1, 38, 53, 52, 55, 54, 3, 21, 20, 23, 1, 51, 1,
+ 54, 61, 1, 52, 39, 38, 35, 34, 3, 6, 21, 35, 52, 39, 38, 35, 34, 7, 6, 1, 61,179, 96, 23, 5, 10, 93,193,172,100, 31,182,
+254,142, 50, 5,254, 13, 99,164, 66,188,171, 1,134, 3, 1,216, 85,155, 59, 47,217, 71, 8, 5, 59, 83,156,143, 88, 30, 5, 77,
+226, 66, 20, 58,254,174, 64, 66, 10,213,189,254, 59, 55, 2,104,146,150,173,102, 37,254,208, 13,180,187,254, 35, 2, 62,133,124,
+ 31,142, 92, 23,254,144, 31, 21, 64,172,184,146, 57, 0, 0, 0, 0, 2, 0,145, 0,133, 4, 64, 5, 79, 0, 8, 0, 13, 0, 0,
+ 9, 1, 21, 0, 7, 38, 1, 38, 53, 9, 4, 2,105, 1,215,254, 67, 26, 12,254,110, 58, 1,213,254, 94, 1,165, 1,166,254,168,
+ 5, 79,253,158, 5,253,185, 28, 9, 2, 14, 71, 10, 2, 32,253,222,253,219, 2, 37, 1,189, 0, 0, 1, 0, 50, 0,133, 4,159,
+ 5, 79, 0, 55, 0, 0, 1, 50, 23, 22, 23, 20, 15, 1, 51, 54, 59, 1, 50, 23, 22, 21, 20, 7, 6, 7, 34, 39, 35, 21, 16, 23,
+ 21, 35, 39, 54, 17, 53, 35, 6, 35, 34, 39, 38, 53, 52, 55, 54, 59, 1, 50, 23, 51, 53, 38, 39, 38, 61, 1, 52, 55, 54, 2,106,
+176, 83, 10, 3, 99, 49, 2, 61, 69, 16,195, 79, 19,172, 32, 59,199, 83, 2, 67,171, 5, 70, 2, 82,202,157, 84, 20,202, 54, 42,
+ 8, 70, 64, 3, 69, 24, 49,176, 59, 5, 79,186, 43, 46, 96,132, 49, 23,166, 54, 50,168, 86, 10, 5,226, 8,254,230, 89, 5, 5,
+105, 1, 18, 2,228,166, 56, 47,192, 68, 10, 23, 2, 59, 56, 91, 66, 12,165, 86, 15, 0, 0, 0, 0, 3, 0,127, 0,134, 4, 82,
+ 5, 80, 0, 34, 0, 60, 0, 66, 0, 0, 1, 22, 1, 22, 29, 1, 20, 7, 6, 43, 1, 34, 39, 35, 21, 20, 23, 35, 53, 54, 53, 35,
+ 7, 6, 43, 1, 34, 39, 38, 53, 55, 53, 52, 55, 18, 55, 6, 1, 6, 21, 22, 23, 22, 59, 1, 50, 55, 51, 50, 23, 22, 59, 1, 50,
+ 55, 54, 61, 1, 52, 39, 38, 3, 51, 38, 39, 34, 7, 2,105,104, 1, 59, 70,148, 28, 40, 18,119, 81, 34, 68,177, 71, 34, 46, 70,
+ 87, 18,131, 67, 20, 2,169,239, 78,102,254,234, 66, 8,121, 18, 34, 13, 98, 79,150, 6, 26, 68, 85, 15,113, 53, 8,166,189,117,
+ 52, 11, 12, 5, 13, 5, 80,185,254,136,114,111, 2,172, 64, 13,179, 11,230,127, 5,124,239, 83, 96,143, 54, 52, 11, 2,164,175,
+ 1, 39, 60,164,254,183,107,110,153, 44, 7,179, 58,121,137, 33, 25, 25,145,170,236,252, 64, 19, 74, 68, 0, 0, 0, 1, 0, 11,
+ 0,133, 4,198, 5, 79, 0, 23, 0, 0, 1, 50, 23, 22, 23, 51, 54, 55, 54, 51, 50, 23, 22, 21, 20, 7, 1, 35, 1, 38, 53, 52,
+ 55, 54, 1, 59,167, 95, 35, 2, 2, 29, 75, 89,111,172,104, 26,171,254, 77, 5,254, 50,138,164, 69, 5, 79,193, 76, 41,133, 88,
+ 89,184, 68, 60,206,186,253,246, 2, 54,169,179,173,102, 37, 0, 0, 1, 0,145, 0,133, 4, 64, 5, 79, 0, 8, 0, 0, 9, 1,
+ 22, 21, 1, 38, 1, 52, 55, 2,105, 1,158, 57,254, 41, 10,254, 50, 92, 5, 79,253,231, 69, 11,253,159, 6, 2, 91, 11,114, 0,
+ 0, 3, 0, 49, 0,134, 4,160, 5, 86, 0, 50, 0, 96, 0,103, 0, 0, 1, 50, 23, 22, 21, 20, 15, 1, 54, 59, 1, 50, 23, 22,
+ 21, 20, 7, 6, 7, 34, 39, 35, 21, 16, 23, 21, 35, 39, 54, 17, 53, 35, 6, 35, 34, 39, 38, 53, 52, 55, 54, 59, 1, 50, 23, 38,
+ 39, 53, 52, 55, 54, 3, 20, 31, 1, 21, 38, 43, 1, 34, 15, 1, 20, 23, 22, 51, 50, 55, 54, 55, 51, 22, 23, 22, 51, 50, 55, 54,
+ 61, 1, 52, 47, 1, 35, 34, 7, 53, 54, 55, 54, 53, 52, 39, 38, 35, 34, 7, 19, 20, 7, 51, 53, 38, 53, 2,109,166, 86, 21, 94,
+ 18, 25, 50, 34,204, 76, 13,173, 28, 60,198, 84, 2, 67,172, 5, 70, 2, 82,203,157, 85, 21,203, 55, 42, 32, 50, 25, 81, 23,177,
+ 59,198,139, 10, 88, 97, 7,200, 50, 6,112, 50, 64,173, 94, 13, 18, 6, 30, 68, 74,130,138, 70, 10,208, 44, 5, 97, 88,106, 26,
+ 21,153, 45, 33,152, 68,216, 23, 50, 23, 5, 86,169, 57, 47,109,136, 19, 5,177, 46, 48,173, 82, 10, 6,227, 7,254,228, 90, 4,
+ 4,106, 1, 19, 3,230,167, 57, 47,194, 67, 10, 5, 92,145, 32,167, 86, 15,254,239,128,167, 10, 3, 8,175, 55,121, 77, 31,243,
+ 22, 53, 98,111,109,156, 38, 35, 5,183, 39, 3, 8, 3,112, 91, 63, 36,150, 71, 14,165,252,141, 23, 79, 3, 81, 18, 0, 0, 0,
+ 0, 4, 0, 46, 0, 7, 4,163, 4,198, 0, 14, 0, 29, 0, 44, 0, 72, 0, 0, 1, 51, 20, 6, 7, 20, 22, 23, 35, 38, 39, 38,
+ 39, 38, 54, 37, 51, 20, 6, 7, 20, 22, 23, 35, 38, 39, 38, 39, 38, 54, 5, 51, 20, 6, 7, 20, 22, 23, 35, 38, 39, 38, 39, 38,
+ 54, 19, 30, 1, 21, 20, 6, 4, 32, 36, 38, 53, 52, 54, 55, 51, 6, 7, 6, 20, 30, 1, 32, 62, 1, 52, 39, 38, 39, 1,126, 11,
+118, 1,165, 6, 11, 23,133, 39, 12, 4,138, 1, 5, 11,119, 2,167, 5, 11, 23,132, 40, 12, 3,138, 1, 24, 11,119, 1,166, 5,
+ 10, 23,133, 39, 13, 3,138, 36,136,155,150,254,239,254,217,254,239,150,154,136, 3,107, 61, 70,136,245, 1, 13,246,135, 70, 62,
+106, 4, 71, 51,126, 80,106, 98,164,135, 94, 42, 73,101,114,192, 78,192,123,160,152,249,204,145, 63,113,154,174, 74, 65,159,101,
+131,125,206,169,118, 54, 92,126,144,254,120, 40,143, 79, 78,143, 80, 80,143, 78, 79,143, 40, 33, 56, 63,136,124, 69, 69,124,136,
+ 63, 56, 33, 0, 0, 1, 1,114, 0, 33, 3, 95, 5,170, 0, 17, 0, 0, 1, 51, 23, 17, 20, 15, 1, 35, 34, 47, 1, 52, 63, 1,
+ 50, 23, 51, 17, 3, 21, 68, 6,185, 45, 33,200, 26, 4,199, 31, 93, 85, 4, 5,170, 7,251, 70,154, 43, 3,125, 29,123, 23, 4,
+ 60, 4,142, 0, 0, 1, 0,162, 0, 33, 4, 47, 5,170, 0, 29, 0, 0, 1, 51, 23, 21, 22, 23, 22, 21, 20, 7, 35, 39, 54, 53,
+ 52, 39, 38, 39, 17, 20, 7, 35, 34, 53, 52, 55, 51, 50, 23, 17, 2, 54, 82, 8, 25,163,227,115, 4, 28, 57,215, 87, 23,212, 53,
+229,200, 22, 91, 83, 5,170, 6, 37, 51, 59, 66,131,137, 91, 30, 47, 79, 66, 67, 39, 25,252, 18,144, 42,158,124, 21, 60, 4,144,
+ 0, 1, 0,106,255, 95, 4,103, 5,165, 0, 30, 0, 0, 1, 5, 23, 17, 20, 7, 35, 34, 61, 1, 52, 63, 1, 50, 23, 17, 37, 17,
+ 20, 15, 1, 35, 34, 61, 1, 52, 63, 1, 50, 23, 17, 1,217, 2,140, 2,181, 51,201,167, 37, 81, 77,253,251,142, 63, 25,203,160,
+ 41, 84, 75, 5,165,191, 4,251, 55,146, 40,155, 4,119, 20, 3, 55, 3,209,159,252, 23,129, 53, 7,146, 7,115, 32, 3, 63, 4,
+141, 0, 0, 0, 0, 2, 0, 17, 0,124, 4,192, 5, 79, 0, 24, 0, 28, 0, 0, 1, 23, 17, 20, 7, 34, 39, 52, 55, 50, 23, 51,
+ 17, 33, 17, 6, 7, 35, 34, 53, 52, 55, 50, 23, 17, 23, 21, 33, 53, 4,189, 3,214,192, 15,192, 89, 65, 3,253, 62, 7,199, 3,
+212,194, 82, 72, 73, 2,194, 5, 79, 3,251,243,176, 17,135,113, 12, 49, 2, 32,253,211,171, 29,145,103, 13, 52, 4, 2,170,128,
+128, 0, 0, 0, 0, 2, 1, 68, 0, 37, 3,141, 5,174, 0, 12, 0, 19, 0, 0, 1, 51, 23, 17, 51, 54, 51, 22, 23, 2, 5, 39,
+ 17, 19, 17, 36, 17, 54, 39, 34, 1, 73, 43, 4, 3,161,136,215, 18, 27,253,212, 2, 52, 1,139, 12,152,112, 5,174, 5,252,117,
+224, 3,242,254,111, 83, 2, 5,130,252, 16,254,177, 94, 1, 31,163, 8, 0, 0, 0, 2, 1,177, 0, 42, 3, 32, 5,175, 0, 13,
+ 0, 19, 0, 0, 1, 51, 23, 17, 37, 23, 17, 7, 35, 39, 17, 5, 35, 17, 19, 17, 51, 37, 17, 35, 1,182, 39, 6, 1, 59, 2, 4,
+ 38, 5,254,194, 2, 50, 1, 1, 13, 2, 5,175, 5,254, 73,152, 2,251,166, 5, 5, 1,202,151, 4, 72,253,188,254,147,135, 1,
+106, 0, 0, 0, 0, 2, 1, 55, 0, 42, 3,154, 5,175, 0, 40, 0, 44, 0, 0, 1, 51, 23, 17, 55, 23, 21, 6, 7, 17, 55, 21,
+ 6, 7, 17, 7, 35, 39, 17, 5, 17, 7, 35, 39, 17, 7, 53, 52, 55, 17, 35, 7, 53, 55, 17, 55, 51, 23, 21, 37, 17, 1, 17, 37,
+ 17, 2,246, 44, 5,112, 3, 3,112,115, 1,114, 5, 44, 4,254,240, 5, 39, 5,122,122, 2,120,122, 5, 39, 5, 1, 16,254,240,
+ 1, 16, 5,175, 5,254,225, 57, 2,133, 7, 56,254,160, 52,128, 4, 63,254,232, 4, 4, 1, 2,132,254,185, 4, 4, 1, 47, 57,
+134, 6, 57, 1,101, 53,131, 62, 1, 15, 3, 3,248,127, 1, 58,253,185,254,156,131, 1, 95, 0, 0, 1, 0, 96,255,254, 4,113,
+ 5, 28, 0, 69, 0, 0, 1, 35, 38, 7, 35, 34, 39, 53, 54, 53, 52, 39, 53, 54, 55, 51, 22, 59, 1, 53, 52, 39, 53, 54, 55, 51,
+ 22, 50, 55, 51, 22, 23, 21, 6, 29, 1, 51, 50, 55, 51, 22, 23, 21, 6, 21, 20, 23, 21, 6, 43, 1, 38, 7, 35, 17, 20, 23, 21,
+ 6, 7, 35, 38, 34, 7, 35, 38, 39, 53, 54, 53, 2, 42,148,159, 71, 49, 21, 9, 86, 86, 1, 28, 50, 73,158,147,115, 3, 25, 51,
+ 39,123, 39, 51, 25, 3,115,143,158, 73, 49, 28, 2, 86, 86, 9, 22, 48, 71,160,143,115, 3, 25, 51, 39,123, 39, 51, 25, 3,115,
+ 2,173, 1, 80, 31, 51, 43, 49, 61, 39, 51, 25, 3,115,153,159, 72, 49, 29, 2, 87, 87, 2, 29, 49, 72,159,153,115, 3, 25, 51,
+ 39, 61, 49, 43, 51, 31, 80, 1,254,136,159, 72, 50, 28, 2, 87, 87, 2, 28, 50, 72,159, 0, 0, 0, 6, 0, 46,255,240, 4,163,
+ 5, 15, 0, 6, 0, 13, 0, 20, 0, 27, 0, 59, 0, 71, 0, 0, 19, 6, 7, 22, 23, 55, 53, 5, 21, 23, 54, 55, 38, 39, 1, 38,
+ 39, 6, 7, 23, 51, 3, 35, 7, 22, 23, 54, 55, 3, 51, 55, 22, 23, 6, 7, 39, 35, 17, 23, 6, 7, 38, 39, 55, 17, 35, 7, 38,
+ 39, 54, 55, 23, 51, 53, 39, 54, 55, 22, 23, 15, 1, 21, 35, 21, 51, 17, 51, 17, 51, 53, 35, 53,206, 19, 42, 41, 20, 83, 2,144,
+ 82, 20, 41, 41, 20,254,181, 38, 42, 38, 39, 59, 40, 1, 40, 58, 39, 38, 41, 39, 6,200,182, 8,107,107, 8,182,200,110, 92, 92,
+ 91, 91,110,200,182, 9,107,107, 9,182,200,110, 91, 91, 92, 92,110, 96,102,102, 47,101,101, 3, 46, 40, 40, 38, 40, 59, 40, 1,
+ 40, 58, 40, 38, 40, 40, 1, 64, 20, 41, 41, 20, 83,252,200, 83, 20, 42, 42, 20, 2,152,110, 92, 93, 91, 91,111,254,132,182, 10,
+106,106, 10,182, 1,124,111, 91, 92, 92, 92,110,187,183, 10,106,106, 10,183,101,139, 40,254,176, 1, 80, 40,139, 0, 12, 0, 47,
+255,251, 4,162, 4, 78, 0, 20, 0, 35, 0, 46, 0, 54, 0, 67, 0, 77, 0,104, 0,119, 0,140, 0,151, 0,166, 0,175, 0, 0,
+ 1, 33, 50, 31, 1, 55, 51, 50, 21, 7, 33, 39, 53, 54, 55, 53, 38, 39, 38, 61, 1, 7, 51, 50, 23, 22, 21, 6, 7, 35, 38, 39,
+ 53, 54, 55, 54, 23, 21, 19, 7, 21, 51, 55, 7, 38, 47, 1, 5, 23, 55, 38, 43, 1, 34, 7, 5, 22, 31, 1, 21, 20, 7, 6, 43,
+ 1, 38, 39, 53, 31, 1, 51, 50, 63, 1, 52, 47, 1, 6, 37, 51, 50, 23, 22, 21, 7, 35, 39, 6, 15, 1, 23, 7, 35, 38, 39, 38,
+ 61, 1, 52, 63, 1, 35, 39, 53, 55, 23, 21, 23, 51, 21, 20, 7, 21, 22, 23, 19, 51, 23, 53, 39, 5, 51, 23, 21, 33, 50, 55, 51,
+ 23, 21, 6, 7, 6, 43, 1, 21, 7, 35, 38, 61, 1, 39, 23, 17, 7, 35, 34, 47, 1, 53, 52, 55, 5, 7, 23, 51, 53, 52, 59, 1,
+ 50, 63, 1, 33, 38, 61, 1, 5, 6, 7, 21, 20, 31, 1, 51, 53, 2, 20, 1, 45, 44, 22, 59, 75, 6, 4,132,254,247, 4, 14, 62,
+142, 12, 35, 87, 18, 85, 42, 23,134, 12, 3,229, 3,121, 12, 34,209,154, 17,154, 72, 21, 86, 13, 15,253,206,183,122, 47, 59, 21,
+ 64, 34, 2,191, 14,113, 4, 61, 17, 28,111, 9,137, 41,119,101, 41, 28, 1, 36, 73,173,253,197, 15, 7, 89, 39, 4, 4, 76,137,
+ 11, 3, 4, 5, 2, 17,132, 15, 65, 15, 2, 76, 4, 97, 14, 2, 88, 1,119,152, 2, 21, 72, 1,229, 4, 3, 1, 27, 32, 27, 2,
+ 4, 5,149, 19, 26,149, 3, 7,131, 62, 6, 4,227, 88, 37, 4, 67, 1,201, 73, 73, 4, 6,176, 16, 36, 80,254,204, 6,254, 67,
+ 47, 4, 68, 23,206, 4, 78, 54,103, 43, 5,229, 4, 4, 13, 32, 4,248, 15, 17, 3, 4, 10, 98, 37, 8,239, 13,131, 6, 2,215,
+ 6, 35, 18, 1,254,241, 11, 2,131, 9,150, 10, 3,230,106,213,110, 78,203, 13,208, 32, 15, 58, 51, 14, 8,242, 3, 11,212, 79,
+ 20, 43, 53,123, 98, 81,164, 60, 10, 4, 44,235, 26, 16, 30, 4, 21,229, 20, 23, 6, 21,100, 31, 45, 4, 4, 29, 4, 10, 2, 6,
+150, 8, 20,193, 1, 9, 6, 3,131,229, 4, 88, 25, 4, 1, 16,255, 22, 93, 3,220, 10, 3,136, 5,254,247, 3,102, 29, 9, 39,
+ 94, 9,131,130, 6, 22, 74,137, 1, 15, 6, 22, 74, 28, 7, 65, 33, 4,211, 0, 0, 4, 0, 60, 0, 10, 4,149, 4, 56, 0, 10,
+ 0, 31, 0, 50, 0, 69, 0, 0, 1, 51, 17, 7, 53, 55, 51, 17, 51, 21, 33, 5, 38, 53, 52, 63, 1, 39, 55, 23, 39, 7, 6, 23,
+ 22, 55, 33, 21, 33, 34, 39, 38, 37, 6, 7, 35, 21, 39, 55, 21, 51, 54, 55, 54, 39, 3, 55, 19, 22, 21, 20, 1, 22, 31, 1, 55,
+ 7, 39, 55, 39, 38, 7, 6, 7, 3, 39, 19, 54, 55, 54, 1,220,125,136,147, 93,125,254,158,254,129, 32, 28, 61, 45,171, 18, 45,
+ 72, 15, 27, 29, 87, 1, 40,254,159, 55, 42, 33, 4, 11, 62,128,121,154,154,144, 42, 19, 18, 49,147, 99,177, 27,253,189,123, 70,
+ 61, 46, 18,171, 44, 72, 28, 45, 46, 39,148,100,176, 29, 40, 35, 1, 89, 1, 43, 19, 71, 22,254,139, 67,134, 56, 57, 53, 55,106,
+ 26, 78,187, 26,125, 41, 37, 37, 6,116, 24, 20, 71,108, 7, 53,110,109, 51, 8, 40, 44, 72, 1, 1, 58,254,206, 48, 47, 40, 3,
+ 95, 1,107,105, 26,188, 78, 26,125, 33, 4, 7, 78,255, 0, 57, 1, 50, 48, 24, 20, 0, 0, 0, 0, 4, 0, 75, 0, 9, 4,134,
+ 4, 28, 0, 28, 0, 49, 0, 68, 0, 87, 0, 0, 1, 51, 21, 33, 53, 62, 1, 55, 62, 1, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1,
+ 51, 50, 22, 21, 20, 6, 7, 14, 1, 5, 38, 53, 52, 63, 1, 39, 55, 23, 39, 7, 6, 23, 22, 55, 33, 21, 33, 34, 39, 38, 37, 6,
+ 7, 35, 21, 39, 55, 21, 51, 54, 55, 54, 47, 1, 55, 19, 22, 21, 20, 1, 22, 31, 1, 55, 7, 39, 55, 39, 38, 7, 6, 15, 1, 39,
+ 19, 54, 55, 54, 2, 64,242,254,137, 46,146, 17, 35, 26, 53, 42, 34, 73, 63, 54, 79, 34, 91,109, 27, 34, 10, 99,253,229, 31, 27,
+ 60, 44,167, 17, 43, 71, 14, 26, 28, 85, 1, 32,254,168, 53, 41, 32, 3,240, 60,124,119,149,149,141, 41, 18, 17, 47,144, 97,173,
+ 26,253,203,121, 68, 60, 44, 17,167, 43, 71, 27, 44, 44, 38,145, 97,171, 28, 40, 33, 1, 62, 66, 60, 35,113, 15, 29, 39, 19, 28,
+ 37, 17, 27, 78, 18, 14, 71, 57, 27, 49, 32, 9, 77,232, 55, 56, 51, 53,104, 26, 76,183, 26,123, 39, 36, 36, 5,113, 24, 19, 69,
+104, 8, 51,107,106, 50, 8, 39, 43, 71,250, 56,254,214, 47, 46, 38, 3, 72, 1,103,104, 26,183, 76, 25,123, 32, 5, 6, 76,250,
+ 56, 1, 42, 47, 23, 19, 0, 0, 0, 4, 0, 68, 0, 10, 4,141, 4, 42, 0, 40, 0, 61, 0, 80, 0, 99, 0, 0, 1, 30, 1, 21,
+ 20, 6, 35, 34, 38, 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 43, 1, 53, 51, 50, 54, 53, 52, 38, 35, 34, 6, 7, 53, 62, 1, 51,
+ 50, 22, 21, 20, 6, 1, 38, 53, 52, 63, 1, 39, 55, 23, 39, 7, 6, 23, 22, 55, 33, 21, 33, 34, 39, 38, 37, 6, 7, 35, 21, 39,
+ 55, 21, 51, 54, 55, 54, 47, 1, 55, 19, 22, 21, 20, 1, 22, 31, 1, 55, 7, 39, 55, 39, 38, 7, 6, 15, 1, 39, 19, 54, 55, 54,
+ 2,246, 8, 68,124,113, 37, 78, 50, 52, 72, 39, 67, 66, 61, 57, 80, 83, 51, 52, 54, 52, 30, 69, 62, 54, 79, 35, 93,111, 60,253,
+107, 32, 28, 60, 45,170, 17, 44, 71, 15, 26, 29, 86, 1, 36,254,164, 54, 41, 34, 3,254, 61,126,120,152,152,142, 42, 18, 18, 48,
+146, 98,175, 27,253,196,122, 69, 60, 46, 18,169, 43, 71, 27, 45, 45, 38,147, 98,173, 28, 41, 34, 1,237, 1, 60, 43, 66, 73, 10,
+ 13, 78, 22, 13, 36, 37, 32, 36, 66, 28, 27, 28, 30, 10, 15, 71, 11, 9, 64, 54, 37, 54,254,161, 55, 57, 52, 54,105, 26, 77,185,
+ 26,124, 40, 36, 37, 6,115, 24, 20, 69,105, 8, 52,109,107, 51, 8, 40, 44, 71,254, 57,254,210, 48, 46, 39, 3, 83, 1,105,105,
+ 26,185, 77, 26,123, 33, 5, 6, 77,253, 56, 1, 47, 47, 23, 20, 0, 5, 0, 36, 0, 7, 4,173, 4,100, 0, 2, 0, 13, 0, 34,
+ 0, 53, 0, 72, 0, 0, 1, 7, 51, 3, 51, 17, 51, 21, 35, 21, 35, 53, 33, 53, 1, 38, 53, 52, 63, 1, 39, 55, 23, 39, 7, 6,
+ 23, 22, 55, 33, 21, 33, 34, 39, 38, 37, 6, 7, 35, 21, 39, 55, 21, 51, 54, 55, 54, 39, 3, 55, 19, 22, 21, 20, 1, 22, 31, 1,
+ 55, 7, 39, 55, 39, 38, 7, 6, 7, 3, 39, 19, 54, 55, 54, 2,129,175,175, 15,135, 92, 92,120,254,221,254,232, 34, 29, 64, 47,
+179, 18, 46, 75, 16, 28, 30, 91, 1, 53,254,143, 57, 43, 35, 4, 57, 65,133,128,159,159,151, 44, 20, 19, 51,154,103,185, 29,253,
+163,128, 74, 64, 48, 19,179, 46, 75, 29, 48, 48, 40,155,104,184, 29, 43, 36, 2,119,196, 1, 44,254,212, 72,109,109, 73,254,222,
+ 59, 60, 55, 57,111, 28, 81,196, 28,131, 43, 38, 39, 6,121, 25, 21, 74,112, 8, 55,115,113, 53, 8, 42, 47, 75, 1, 12, 60,254,
+193, 50, 50, 41, 3,133, 1,111,111, 28,196, 81, 27,131, 34, 4, 7, 82,254,245, 59, 1, 64, 50, 25, 21, 0, 0, 0, 4, 0, 62,
+ 0, 9, 4,147, 4, 51, 0, 29, 0, 50, 0, 69, 0, 88, 0, 0, 1, 33, 21, 35, 21, 50, 54, 51, 50, 22, 21, 20, 6, 35, 34, 38,
+ 39, 53, 30, 1, 51, 50, 54, 53, 52, 38, 35, 34, 6, 7, 1, 38, 53, 52, 63, 1, 39, 55, 23, 39, 7, 6, 23, 22, 55, 33, 21, 33,
+ 34, 39, 38, 37, 6, 7, 35, 21, 39, 55, 21, 51, 54, 55, 54, 39, 3, 55, 19, 22, 21, 20, 1, 22, 31, 1, 55, 7, 39, 55, 39, 38,
+ 7, 6, 15, 1, 39, 19, 54, 55, 54, 1,202, 1, 72,230, 4, 31, 17,101,118,121,110, 36, 76, 50, 55, 67, 39, 60, 67, 67, 60, 28,
+ 59, 50,254,149, 32, 27, 61, 45,171, 18, 45, 72, 14, 26, 29, 87, 1, 39,254,160, 55, 41, 34, 4, 9, 62,128,121,153,153,144, 42,
+ 18, 19, 49,147, 99,177, 26,253,191,123, 70, 61, 46, 19,170, 44, 72, 28, 45, 46, 38,149, 99,176, 28, 41, 34, 2,184, 69, 82, 5,
+ 85, 72, 72, 83, 10, 11, 83, 23, 13, 47, 40, 42, 46, 9, 18,254,200, 56, 57, 53, 54,106, 26, 78,187, 27,126, 40, 37, 37, 6,116,
+ 24, 20, 71,107, 8, 53,110,109, 51, 8, 40, 44, 72, 1, 0, 58,254,207, 48, 48, 39, 3, 92, 1,106,105, 26,187, 78, 25,125, 33,
+ 4, 7, 78,255, 57, 1, 49, 47, 24, 20, 0, 0, 0, 5, 0, 75, 0, 0, 4,134, 4, 18, 0, 9, 0, 34, 0, 55, 0, 74, 0, 93,
+ 0, 0, 1, 34, 6, 20, 22, 51, 50, 54, 52, 38, 55, 21, 46, 1, 35, 34, 6, 7, 6, 54, 51, 50, 22, 21, 20, 6, 35, 34, 38, 53,
+ 52, 54, 51, 50, 22, 1, 38, 53, 52, 63, 1, 39, 55, 23, 39, 7, 6, 23, 22, 55, 33, 21, 33, 34, 39, 38, 37, 6, 7, 35, 21, 39,
+ 55, 21, 51, 54, 55, 54, 47, 1, 55, 19, 22, 21, 20, 1, 22, 31, 1, 55, 7, 39, 55, 39, 38, 7, 6, 15, 1, 39, 19, 54, 55, 54,
+ 2, 93, 39, 48, 48, 39, 42, 47, 47,108, 43, 50, 24, 62, 65, 2, 5, 66, 40, 83, 96,100, 84, 94,100,121,103, 27, 55,253,157, 31,
+ 27, 60, 44,167, 17, 43, 71, 14, 26, 28, 85, 1, 32,254,168, 53, 41, 32, 3,240, 60,124,119,149,149,141, 41, 18, 17, 47,144, 97,
+173, 26,253,203,121, 68, 60, 44, 17,167, 43, 71, 27, 44, 44, 38,145, 97,171, 28, 40, 33, 1,219, 46, 84, 45, 45, 84, 46,192, 72,
+ 15, 10, 68, 38, 5, 29, 82, 69, 67, 83,117,107,102,123, 8,253,220, 55, 56, 51, 53,104, 26, 76,183, 26,123, 40, 35, 36, 5,113,
+ 24, 19, 69,105, 7, 52,108,106, 50, 8, 39, 43, 71,250, 56,254,214, 47, 46, 38, 3, 72, 1,104,103, 26,183, 76, 25,122, 32, 4,
+ 6, 76,250, 56, 1, 42, 46, 24, 19, 0, 0, 0, 0, 4, 0, 45, 0, 12, 4,164, 4, 88, 0, 6, 0, 27, 0, 46, 0, 65, 0, 0,
+ 1, 33, 21, 3, 35, 19, 33, 1, 38, 53, 52, 63, 1, 39, 55, 23, 39, 7, 6, 23, 22, 55, 33, 21, 33, 34, 39, 38, 37, 6, 7, 35,
+ 21, 39, 55, 21, 51, 54, 55, 54, 39, 3, 55, 19, 22, 21, 20, 1, 22, 31, 1, 55, 7, 39, 55, 39, 38, 7, 6, 7, 3, 39, 19, 54,
+ 55, 54, 1,178, 1,129,204,110,191,254,250,254,156, 33, 29, 63, 47,177, 18, 46, 74, 15, 27, 30, 89, 1, 48,254,149, 56, 43, 34,
+ 4, 40, 64,131,125,158,158,148, 44, 19, 18, 50,151,102,182, 28,253,172,127, 72, 63, 47, 19,175, 45, 74, 29, 46, 48, 39,153,102,
+180, 30, 42, 35, 2,192, 38,254, 75, 1,148,254, 28, 58, 59, 54, 56,110, 27, 80,193, 27,129, 42, 37, 39, 6,119, 25, 20, 73,110,
+ 8, 55,114,112, 53, 8, 41, 46, 74, 1, 8, 60,254,198, 50, 49, 40, 3,118, 1,109,109, 27,193, 81, 26,129, 34, 5, 7, 80,254,
+249, 59, 1, 58, 49, 25, 20, 0, 0, 3, 0, 45, 0, 0, 4,164, 4, 75, 0, 20, 0, 39, 0, 58, 0, 0, 55, 38, 53, 52, 63, 1,
+ 39, 55, 23, 39, 7, 6, 23, 22, 55, 33, 21, 33, 34, 39, 38, 37, 6, 7, 35, 21, 39, 55, 21, 51, 54, 55, 54, 39, 3, 55, 19, 22,
+ 21, 20, 1, 22, 31, 1, 55, 7, 39, 55, 39, 38, 7, 6, 7, 3, 39, 19, 54, 55, 54, 78, 33, 29, 63, 47,177, 18, 46, 74, 15, 27,
+ 30, 89, 1, 48,254,149, 56, 43, 34, 4, 40, 64,131,125,158,158,148, 44, 19, 18, 50,151,102,182, 28,253,172,127, 72, 63, 47, 19,
+175, 45, 74, 29, 46, 48, 39,153,102,180, 30, 42, 35,136, 58, 60, 54, 56,109, 27, 80,192, 27,129, 42, 38, 38, 6,119, 25, 20, 72,
+110, 7, 55,113,112, 53, 9, 41, 46, 74, 1, 8, 59,254,198, 49, 49, 41, 3,119, 1,110,108, 27,193, 80, 26,130, 33, 4, 7, 80,
+254,248, 59, 1, 59, 49, 25, 20, 0, 6, 0, 57,255,255, 4,152, 4, 57, 0, 16, 0, 26, 0, 39, 0, 57, 0, 72, 0, 82, 0, 0,
+ 1, 33, 50, 31, 1, 55, 51, 21, 6, 7, 33, 53, 54, 55, 3, 38, 35, 7, 50, 31, 1, 7, 38, 39, 54, 55, 54, 1, 22, 21, 23, 20,
+ 7, 6, 43, 1, 38, 39, 54, 55, 5, 22, 23, 39, 6, 15, 1, 23, 35, 3, 39, 54, 55, 54, 53, 39, 53, 51, 1, 51, 21, 33, 50, 55,
+ 51, 20, 3, 6, 43, 1, 21, 35, 47, 1, 23, 17, 7, 35, 34, 47, 1, 52, 55, 2, 24, 1, 36, 44, 25, 55, 74, 5,118, 12,254,255,
+ 73, 3,148, 26, 10, 77, 79, 32, 36,144,201, 20,112, 16, 37, 2,132,124, 2, 73, 11, 30, 94, 11,131, 18,151,253, 91,128, 1, 84,
+144, 3, 2, 4, 4,151, 6, 3, 60, 20, 75,171, 2, 34, 1, 1, 40, 25, 22, 2,150, 18, 24,153, 3,126, 71, 4, 4,217, 87, 36,
+ 3, 63, 4, 56, 63, 93, 41, 2,206, 16, 4, 40, 7, 1, 9, 19, 3, 69, 65,247,115, 15,194, 22, 35,254,192,208, 17, 30, 76, 44,
+ 6, 12,235, 17, 84, 20,216, 10, 48,248, 12, 31, 21, 1, 4, 24, 24, 96, 30, 9, 43, 2,254,252, 87, 20, 7,254,251, 17, 86,219,
+132, 4,254,255, 4, 96, 36, 36, 97, 0, 0, 0, 0, 7, 0, 46, 0, 7, 4,163, 4,124, 0, 19, 0, 37, 0, 50, 0, 60, 0, 74,
+ 0, 92, 0,101, 0, 0, 1, 51, 32, 19, 22, 29, 1, 16, 5, 6, 43, 1, 32, 3, 38, 61, 1, 16, 55, 54, 23, 21, 50, 31, 1, 21,
+ 6, 7, 21, 51, 54, 55, 35, 7, 38, 39, 38, 35, 5, 22, 51, 54, 55, 38, 35, 38, 35, 34, 7, 6, 7, 5, 21, 23, 51, 50, 55, 52,
+ 47, 1, 34, 5, 23, 6, 7, 20, 31, 1, 51, 52, 63, 1, 51, 23, 39, 5, 7, 22, 23, 51, 53, 55, 51, 50, 63, 1, 53, 35, 6, 43,
+ 1, 39, 53, 5, 6, 29, 1, 20, 31, 1, 51, 53, 2, 94, 21, 1, 45,185, 74,254,206,124,139, 3,254,183,176, 64,241,145,104, 29,
+ 39, 92, 20, 45,214, 7,101, 2, 64, 60, 14, 16, 19,254, 30,185, 6, 3,114, 50, 18, 22, 38, 72, 41, 59, 10, 1,232,117, 90, 74,
+ 20, 77, 31, 11,252,205, 61, 57, 8,106, 22, 2, 21,108, 7, 58,106, 1,128,103, 5, 98, 3, 4,131, 28, 46, 81, 2, 17, 26,241,
+ 4,254,105, 50, 81, 20,192, 4,124,254,233,133,157, 5,254,182,179, 58, 1, 42,127,125, 40, 1, 11,184,100,112, 2, 82,157, 2,
+ 17, 24, 2, 6,183, 33,104, 17, 9,220,106, 11,196, 96, 14, 93, 95, 23,169, 3,204,105, 36,120, 58, 45, 40, 94, 37, 17,177, 44,
+ 51, 19,189, 34,184,216,191, 2,180, 69, 5, 97,135, 2, 12, 5, 72, 77, 80, 30, 9, 69, 31, 3,222, 0, 0, 0, 0, 8, 0, 55,
+ 0, 4, 4,154, 4,103, 0, 15, 0, 32, 0, 47, 0, 58, 0, 66, 0, 82, 0, 96, 0,106, 0, 0, 1, 32, 19, 22, 21, 16, 5, 6,
+ 35, 32, 3, 38, 53, 16, 37, 54, 1, 16, 5, 22, 59, 1, 32, 19, 54, 53, 16, 37, 38, 35, 32, 3, 6, 1, 51, 50, 31, 1, 55, 21,
+ 6, 7, 35, 53, 55, 38, 47, 1, 35, 50, 31, 1, 7, 35, 38, 39, 54, 55, 54, 1, 22, 29, 1, 6, 43, 1, 39, 37, 51, 23, 7, 35,
+ 39, 35, 6, 7, 21, 38, 47, 1, 52, 55, 39, 5, 51, 21, 51, 50, 55, 21, 15, 1, 35, 7, 21, 35, 39, 37, 51, 23, 21, 7, 35, 34,
+ 47, 1, 54, 2,106, 1, 49,178, 77,254,227,123,157,254,199,174, 71, 1, 38,128,254,122, 1, 10,118,127, 36, 1, 14,172, 69,254,
+240,120,138,254,221,168, 69, 1,197,235, 40, 18, 43, 61, 82, 20,204, 58,110, 19, 20, 58, 68, 23, 33,115, 2,171, 13, 89, 21, 33,
+ 1,250,103, 16, 81, 75,117,253,162,207,109, 2, 2, 59, 2,125, 4, 9,117, 2, 65, 59, 2, 62, 5,245, 15, 18,130, 17,127, 4,
+ 5,101,254,231,225, 4, 4,184, 61, 29, 5, 1, 4,103,254,241,134,158,254,194,175, 67, 1, 23,121,165, 1, 63,176, 63,253,205,
+254,212,162, 66, 1, 3,124,147, 1, 42,168, 62,254,252,119, 1, 18, 52, 73, 32, 2,153, 26, 2, 39,191, 29, 9, 53, 64,194, 96,
+ 12,160, 19, 24,254,253,169, 25, 17, 98,199, 67,183, 2, 36,208, 16, 20, 9,205, 13, 21,106, 36,206, 72, 15, 4,219, 7, 5, 63,
+178,105, 4,207, 4, 77, 33, 37, 0, 5, 0, 46, 0, 7, 4,163, 4,124, 0, 7, 0, 23, 0, 31, 0, 55, 0, 72, 0, 0, 1, 22,
+ 23, 50, 55, 38, 39, 6, 1, 32, 19, 22, 21, 16, 5, 6, 35, 32, 3, 38, 53, 16, 37, 54, 1, 6, 7, 22, 51, 54, 55, 38, 5, 21,
+ 35, 6, 39, 46, 1, 55, 38, 54, 55, 50, 23, 54, 51, 30, 1, 7, 22, 6, 7, 6, 39, 35, 37, 16, 5, 22, 59, 1, 32, 19, 54, 53,
+ 16, 37, 38, 35, 32, 3, 6, 1, 4, 1,140,109, 74, 66,124,133, 1,101, 1, 54,180, 79,254,222,125,159,254,194,176, 73, 1, 43,
+129, 1,111,124, 66, 74,110,139, 2, 2,254,155, 2, 94,143,106, 97, 5, 3,121,103,119, 97, 97,121,103,120, 2, 4, 97,106,143,
+ 94, 2,253,229, 1, 14,119,130, 36, 1, 19,174, 70,254,236,121,141,254,216,170, 70, 2, 71,156, 2,155,148, 3, 2, 1,162,254,
+237,135,162,254,189,177, 68, 1, 28,123,167, 1, 67,180, 63,254, 96, 3,148,155, 2,156,146,205, 22,150, 6, 12,147, 66, 93,119,
+ 1,130,130, 1,119, 93, 66,147, 12, 6,150, 74,254,208,165, 67, 1, 7,125,150, 1, 46,171, 63,254,248,121, 0, 0, 2, 0, 80,
+ 0, 8, 4,129, 5, 37, 0, 24, 0, 46, 0, 0, 1, 50, 21, 6, 7, 23, 51, 50, 23, 7, 35, 23, 33, 22, 19, 55, 23, 6, 7, 38,
+ 3, 33, 34, 3, 52, 1, 6, 35, 34, 46, 1, 53, 52, 55, 54, 55, 23, 6, 7, 20, 30, 1, 50, 54, 55, 23, 6, 1,140,134, 1,112,
+ 21,241, 11, 14, 4,241, 11, 1,133, 11,123,117, 42, 4,240, 14,130,254, 95, 11, 74, 1,185, 99,108,108,198,109, 56, 28, 42, 35,
+ 22, 2, 73,133,145,132, 37, 60, 40, 5, 36,124,143, 1,202,128, 3, 88, 6,254,164, 35,123, 7, 78, 21, 1,119, 2,192,116,251,
+ 27, 55,109,197,110,108,100, 52, 41,190, 53, 58, 73,133, 73, 73, 66,147, 44, 0, 0, 3, 0, 60, 0, 5, 4,149, 4, 95, 0, 23,
+ 0, 27, 0, 31, 0, 0, 1, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 1, 17,
+ 33, 17, 37, 33, 17, 33, 1,255, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14,254, 62, 4, 87,
+252, 36, 3, 96,252,160, 2, 52, 31, 21, 23, 16, 14, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21,253,241, 4, 90,251,
+166,124, 3, 98, 0, 4, 0, 60, 0, 5, 4,149, 4, 95, 0, 23, 0, 47, 0, 51, 0, 55, 0, 0, 1, 52, 55, 54, 55, 54, 51, 50,
+ 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 1, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6,
+ 7, 6, 35, 34, 39, 38, 39, 38, 1, 17, 33, 17, 37, 33, 17, 33, 1, 23, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21,
+ 32, 31, 21, 23, 16, 14, 1,209, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14,253, 85, 4, 87,
+252, 36, 3, 96,252,160, 1, 72, 31, 21, 23, 15, 14, 14, 15, 23, 21, 31, 32, 21, 23, 15, 15, 15, 15, 23, 21, 1,244, 32, 21, 22,
+ 16, 14, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14, 14, 16, 23, 20,253, 9, 4, 90,251,166,124, 3, 98, 0, 0, 0, 0, 5, 0, 60,
+ 0, 5, 4,149, 4, 95, 0, 23, 0, 47, 0, 71, 0, 75, 0, 79, 0, 0, 1, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20,
+ 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 19, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38,
+ 39, 38, 19, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 1, 17, 33, 17, 37, 33,
+ 17, 33, 1, 23, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14,232, 14, 16, 23, 20, 32, 32, 21,
+ 22, 16, 14, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14,233, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14, 14, 16, 23, 20, 32, 32, 21, 22,
+ 16, 14,253, 85, 4, 87,252, 36, 3, 96,252,160, 1, 72, 31, 21, 23, 15, 14, 14, 15, 23, 21, 31, 32, 21, 23, 15, 15, 15, 15, 23,
+ 21, 1, 12, 31, 21, 23, 16, 14, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21, 1, 8, 32, 21, 22, 16, 14, 14, 15, 23,
+ 21, 32, 31, 21, 23, 16, 14, 14, 16, 23, 20,253, 9, 4, 90,251,166,124, 3, 98, 0, 6, 0, 60, 0, 1, 4,149, 4, 91, 0, 23,
+ 0, 47, 0, 71, 0, 95, 0, 99, 0,103, 0, 0, 1, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34,
+ 39, 38, 39, 38, 1, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 37, 52, 55, 54,
+ 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 1, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22,
+ 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 1, 17, 33, 17, 37, 33, 17, 33, 1, 23, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14,
+ 14, 15, 23, 21, 32, 31, 21, 23, 16, 14, 1,209, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14,
+254, 47, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14, 1,209, 14, 15, 23, 21, 32, 31, 21, 23,
+ 16, 14, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14,253, 85, 4, 87,252, 36, 3, 96,252,160, 3, 24, 32, 21, 23, 15, 15, 15, 15, 23,
+ 21, 32, 31, 21, 23, 15, 14, 14, 15, 23, 21,254, 75, 31, 21, 23, 16, 14, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21,
+ 32, 31, 21, 23, 16, 14, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21, 1,244, 32, 21, 23, 15, 15, 15, 15, 23, 21, 32,
+ 31, 21, 23, 15, 14, 14, 15, 23, 21,253, 8, 4, 90,251,166,124, 3, 98, 0, 0, 0, 7, 0, 60, 0, 5, 4,149, 4, 95, 0, 23,
+ 0, 47, 0, 71, 0, 95, 0,119, 0,123, 0,127, 0, 0, 1, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6,
+ 35, 34, 39, 38, 39, 38, 1, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 37, 52,
+ 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 1, 52, 55, 54, 55, 54, 51, 50, 23, 22,
+ 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 7, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6,
+ 35, 34, 39, 38, 39, 38, 1, 17, 33, 17, 37, 33, 17, 33, 1, 23, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21, 32, 31,
+ 21, 23, 16, 14, 1,209, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14,254, 47, 14, 16, 23, 20,
+ 32, 32, 21, 22, 16, 14, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14, 1,209, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14, 14, 16, 23, 20,
+ 32, 32, 21, 22, 16, 14,233, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14,254, 62, 4, 87,252,
+ 36, 3, 96,252,160, 3, 28, 32, 21, 22, 16, 14, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14, 14, 16, 23, 20,254, 76, 31, 21, 23, 15,
+ 14, 14, 15, 23, 21, 31, 32, 21, 23, 15, 15, 15, 15, 23, 21, 32, 31, 21, 23, 15, 14, 14, 15, 23, 21, 31, 32, 21, 23, 15, 15, 15,
+ 15, 23, 21, 1,244, 32, 21, 22, 16, 14, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14, 14, 16, 23, 20,200, 31, 21, 23, 16, 14, 14, 16,
+ 23, 20, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21,253,241, 4, 90,251,166,124, 3, 98, 0, 0, 0, 0, 8, 0, 60,255,252, 4,149,
+ 4, 86, 0, 23, 0, 47, 0, 71, 0, 95, 0,119, 0,143, 0,147, 0,151, 0, 0, 1, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22,
+ 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 37, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34,
+ 39, 38, 39, 38, 17, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 1, 52, 55, 54,
+ 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 37, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22,
+ 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 1, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34,
+ 39, 38, 39, 38, 1, 17, 33, 17, 37, 33, 17, 33, 2,231, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21, 32, 31, 21, 23,
+ 16, 14,254, 48, 14, 15, 24, 20, 32, 32, 20, 23, 16, 14, 14, 15, 24, 20, 32, 32, 20, 23, 16, 14, 14, 16, 23, 20, 32, 32, 21, 22,
+ 16, 14, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14, 1,209, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14, 14, 16, 23, 20, 32, 32, 21, 22,
+ 16, 14,254, 47, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14, 1,209, 14, 15, 23, 21, 32, 31,
+ 21, 23, 16, 14, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14,253, 85, 4, 87,252, 36, 3, 96,252,160, 2, 43, 32, 21, 22, 16, 14, 14,
+ 15, 23, 21, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21, 32, 32, 21, 22, 16, 14, 14, 15, 23,
+ 21, 1, 46, 32, 21, 22, 16, 14, 14, 15, 23, 21, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21,254, 0, 32, 21, 22, 16, 14, 14, 15, 23,
+ 21, 32, 31, 21, 23, 16, 14, 14, 16, 23, 20, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21, 32, 31, 21, 23, 16, 14, 14, 16, 23, 20, 2,
+ 64, 32, 21, 22, 16, 14, 14, 15, 23, 21, 32, 32, 21, 22, 16, 14, 14, 15, 23, 21,252,227, 4, 90,251,166,124, 3, 98, 0, 0, 0,
+ 0, 3, 0, 46, 0, 0, 4,163, 4,116, 0, 12, 0, 27, 0, 41, 0, 0, 1, 50, 4, 18, 16, 2, 4, 32, 36, 2, 16, 18, 36, 1,
+ 20, 30, 1, 32, 62, 1, 53, 52, 46, 1, 35, 34, 14, 1, 4, 52, 62, 1, 51, 50, 30, 1, 20, 14, 1, 35, 34, 38, 2,104,144, 1,
+ 16,154,150,254,240,254,217,254,240,150,153, 1, 16,254,152,133,240, 1, 7,240,133,137,240,128,127,242,135, 2,185, 26, 46, 25,
+ 24, 46, 26, 27, 45, 24, 25, 45, 4,116,147,254,238,254,214,254,242,151,151, 1, 14, 1, 42, 1, 18,147,253,198,132,240,132,132,
+240,132,131,243,130,130,243,156, 50, 46, 25, 25, 46, 50, 47, 24, 24, 0, 0, 0, 0, 4, 0, 46, 0, 5, 4,163, 4,121, 0, 12,
+ 0, 27, 0, 41, 0, 54, 0, 0, 1, 50, 4, 18, 16, 2, 4, 32, 36, 2, 16, 18, 36, 1, 20, 30, 1, 32, 62, 1, 53, 52, 46, 1,
+ 35, 34, 14, 1, 4, 52, 62, 1, 51, 50, 30, 1, 20, 14, 1, 35, 34, 38, 36, 50, 30, 1, 20, 14, 1, 35, 34, 46, 1, 52, 54, 2,
+104,144, 1, 16,154,150,254,240,254,217,254,240,150,153, 1, 16,254,152,133,240, 1, 7,240,133,137,240,128,127,242,135, 2,185,
+ 26, 46, 25, 24, 46, 26, 27, 45, 24, 25, 45,253,230, 49, 46, 26, 26, 45, 26, 24, 46, 26, 27, 4,121,147,254,238,254,214,254,242,
+151,151, 1, 14, 1, 42, 1, 18,147,253,198,132,240,132,132,240,132,131,243,130,130,243,156, 50, 46, 25, 25, 46, 50, 47, 24, 24,
+168, 24, 47, 50, 46, 25, 25, 46, 50, 47, 0, 0, 0, 2, 0, 46, 0, 0, 4,163, 4,116, 0, 12, 0, 26, 0, 0, 1, 50, 4, 18,
+ 16, 2, 4, 32, 36, 2, 16, 18, 36, 1, 50, 62, 1, 52, 46, 1, 35, 34, 14, 1, 20, 30, 1, 2,104,144, 1, 16,154,150,254,240,
+254,217,254,240,150,153, 1, 16, 1,178, 24, 45, 27, 26, 46, 24, 25, 46, 26, 27, 45, 4,116,147,254,238,254,214,254,242,151,151,
+ 1, 14, 1, 42, 1, 18,147,253,102, 24, 47, 50, 46, 25, 25, 46, 50, 47, 24, 0, 0, 3, 0, 46,255,246, 4,163, 4,106, 0, 12,
+ 0, 26, 0, 39, 0, 0, 1, 50, 4, 18, 16, 2, 4, 32, 36, 2, 16, 18, 36, 1, 50, 62, 1, 52, 46, 1, 35, 34, 14, 1, 20, 30,
+ 1, 36, 20, 30, 1, 51, 50, 62, 1, 52, 46, 1, 34, 6, 2,104,144, 1, 16,154,150,254,240,254,217,254,240,150,153, 1, 16, 1,
+178, 24, 45, 27, 26, 46, 24, 25, 46, 26, 27, 45,253,113, 26, 46, 24, 26, 45, 26, 26, 46, 49, 45, 4,106,147,254,238,254,214,254,
+242,151,151, 1, 14, 1, 42, 1, 18,147,253,102, 24, 47, 50, 46, 25, 25, 46, 50, 47, 24,121, 50, 46, 25, 25, 46, 50, 47, 24, 24,
+ 0, 1, 0, 82, 0, 7, 4,127, 0,150, 0, 3, 0, 0, 55, 33, 21, 33, 82, 4, 45,251,211,150,143, 0, 0, 0, 0, 2, 0, 82,
+ 0, 7, 4,127, 0,150, 0, 3, 0, 7, 0, 0, 55, 33, 21, 33, 37, 33, 21, 33, 82, 1,179,254, 77, 2,122, 1,179,254, 77,150,
+143,143,143, 0, 0, 2, 0,150,255,254, 4, 59, 4,187, 0, 9, 0, 26, 0, 0, 1, 54, 4, 55, 17, 6, 39, 38, 7, 47, 1, 35,
+ 39, 51, 21, 35, 21, 54, 23, 22, 55, 17, 6, 36, 7, 17, 35, 1, 37,135, 1,128,215,175,190,143,210, 16, 80, 61, 1,219, 61,205,
+176,204,188,231,254, 98,146, 78, 2, 27, 43,187, 35, 1,240, 33,102,129, 34, 2, 75, 43, 43, 21, 33,124,111, 53,253,155, 60,201,
+ 63,254, 49, 0, 0, 1, 0,115, 0, 5, 4, 94, 5, 30, 0, 16, 0, 0, 19, 35, 39, 51, 21, 35, 21, 54, 23, 22, 55, 17, 6, 36,
+ 7, 17, 35,182, 66, 1,236, 66,221,189,220,203,249,254, 66,157, 84, 4,240, 46, 46, 23, 35,133,120, 58,253,107, 65,217, 68,254,
+ 13, 0, 0, 0, 0, 1, 0, 39,255,255, 4,170, 4, 40, 0, 31, 0, 0, 1, 39, 7, 39, 55, 39, 55, 23, 55, 23, 7, 23, 55, 39,
+ 55, 23, 55, 23, 7, 22, 19, 39, 7, 31, 1, 7, 47, 1, 15, 1, 39, 55, 2, 37,237,132,140,132, 33, 98, 31,131,140,130,236,237,
+131,141,131, 31, 97, 32, 50, 24,214,236,126,227,131,192,128,126,192,131,225, 1,196,239,132,141,133, 31, 98, 31,132,142,132,239,
+238,133,142,133, 32, 98, 31, 80,254,230,220,240,127,193,132,228,127,127,228,132,193, 0, 0, 0, 0, 2, 0, 31, 0, 0, 4,178,
+ 4,211, 0, 15, 0, 82, 0, 0, 1, 20, 30, 1, 51, 50, 62, 1, 53, 52, 46, 1, 35, 34, 14, 1, 19, 21, 35, 6, 35, 34, 39, 53,
+ 35, 21, 35, 34, 38, 39, 38, 39, 7, 3, 23, 7, 48, 23, 22, 23, 22, 23, 17, 33, 53, 33, 53, 38, 39, 46, 1, 52, 62, 1, 51, 50,
+ 30, 1, 20, 6, 7, 6, 7, 21, 33, 21, 33, 17, 54, 55, 54, 55, 54, 55, 39, 55, 3, 39, 6, 7, 6, 7, 6, 1,252, 32, 58, 31,
+ 33, 57, 33, 34, 57, 32, 30, 58, 33,184, 6, 30, 32, 2, 3, 5, 6,137,251, 70, 13, 11, 71, 23,249, 70, 5, 59,107, 89, 95,254,
+207, 1, 49, 21, 21, 50, 55, 56,101, 53, 54,100, 58, 56, 49, 22, 22, 1, 41,254,215, 82, 76,107, 60, 2, 3, 71,250, 24, 71, 10,
+ 14, 69,126, 94, 3,255, 32, 58, 32, 32, 58, 32, 32, 59, 32, 32, 59,251,229, 1, 2, 1, 1, 1, 78, 71, 14, 13, 53, 1, 13,101,
+ 52, 5, 71, 40, 32, 6, 2, 76,105, 41, 7, 11, 28,101,110,102, 55, 55,102,110,101, 28, 11, 7, 41,105,253,182, 9, 27, 40, 71,
+ 3, 2, 52,101,254,243, 53, 13, 14, 71, 40, 29, 0, 4, 0,129, 0, 12, 4, 80, 4,109, 0, 4, 0, 9, 0, 57, 0, 89, 0, 0,
+ 37, 38, 39, 7, 22, 37, 23, 54, 55, 38, 1, 23, 54, 55, 51, 6, 7, 23, 22, 23, 14, 1, 7, 38, 47, 1, 6, 7, 39, 54, 55, 39,
+ 7, 22, 23, 7, 38, 39, 7, 6, 7, 34, 38, 39, 52, 63, 1, 38, 39, 51, 22, 23, 55, 1, 39, 9, 1, 7, 1, 21, 39, 1, 55, 9,
+ 1, 23, 1, 3, 38, 47, 1, 30, 1, 23, 55, 38, 39, 19, 23, 35, 23, 6, 7, 23, 62, 1, 55, 7, 6, 7, 4, 14, 36, 15, 7, 3,
+252,177, 6, 15, 37, 56, 2, 24,208, 56, 20, 69, 19, 70,117, 47, 1, 4, 45, 32, 54, 3,117, 78, 68, 29, 76, 50,183,182, 50, 76,
+ 29, 69, 78,117, 1, 47, 30, 56, 3, 48,117, 70, 19, 68, 21, 56,209,254,106, 24, 1,230, 1,231, 25,254, 85, 24, 1,189, 4,254,
+ 52,254, 53, 3, 1,191,239, 66, 37, 17, 31,121,133, 6, 92, 65,234, 27, 1,204, 64, 89, 7,132,121, 31, 16, 36, 70, 24, 10, 48,
+ 6, 61, 47, 6, 48, 10, 9, 1,159,228, 44, 45, 88, 55,136, 2, 48, 32, 25, 1, 3, 59,126, 42, 6, 50, 12, 37,218,218, 37, 12,
+ 50, 6, 42,126, 54, 8, 22, 27, 57, 2,136, 55, 88, 45, 44,228, 1,227,111,253,236, 2, 20,111,254, 3, 1, 27, 2, 16, 11,253,
+242, 2, 14, 11,253,244,254,243, 43, 70, 1, 57,100, 49, 12, 28, 41, 1, 12, 30,240, 40, 27, 12, 49,100, 57, 1, 67, 49, 0, 0,
+ 0, 5, 0,188,255,253, 4, 21, 5,236, 0, 3, 0, 22, 0, 42, 0, 67, 0, 84, 0, 0, 1, 22, 39, 38, 19, 21, 6, 35, 34, 39,
+ 53, 38, 55, 54, 55, 21, 6, 21, 6, 4, 7, 35, 38, 3, 36, 39, 38, 37, 21, 6, 21, 20, 4, 23, 6, 5, 39, 54, 39, 38, 39, 17,
+ 39, 19, 17, 39, 17, 36, 39, 54, 55, 54, 23, 7, 23, 6, 39, 38, 7, 6, 4, 23, 6, 5, 53, 36, 39, 54, 37, 39, 3, 46, 1, 53,
+ 52, 62, 1, 51, 50, 30, 1, 21, 20, 6, 7, 1,148, 68, 22, 36,250, 12, 28, 34, 4,182, 2, 6,158, 64, 4, 1, 70, 2, 14, 28,
+198,254,232, 6, 2, 1, 16,170, 2, 44, 2, 4,254,238, 2,188, 6, 2,194, 78, 78, 78,254,118, 4, 14,212, 70, 56,112, 94, 76,
+ 98, 50, 10, 4, 2,242, 6, 6,254,150, 1, 18, 2, 12,254,216, 78, 4, 22, 24, 24, 42, 22, 24, 42, 24, 24, 20, 4,181, 30, 43,
+ 11,251,148, 66, 29, 64, 48, 34, 65, 82, 25, 47, 24, 22, 48, 63,119, 65, 1,183, 37,111,100, 47, 68, 38, 51, 46, 89, 97, 81, 47,
+ 53, 35, 51, 36, 34,254,180, 19, 3, 1,254,129, 16, 1,117, 19,138,144, 5, 4, 73, 30, 25, 18, 39, 13, 64, 51, 47,117,138, 16,
+ 61, 32, 61, 35,110, 7, 1, 45, 11, 46, 24, 25, 46, 24, 24, 46, 25, 24, 46, 11, 0, 3, 0, 19, 0, 3, 4,190, 4,119, 0, 3,
+ 0, 7, 0, 51, 0, 0, 37, 11, 1, 22, 37, 11, 1, 22, 1, 51, 50, 29, 1, 20, 43, 1, 19, 6, 7, 14, 1, 35, 34, 46, 1, 55,
+ 19, 33, 19, 22, 14, 1, 34, 38, 39, 38, 39, 19, 35, 38, 61, 1, 52, 59, 1, 55, 23, 51, 55, 23, 51, 55, 4,128,207,207,207,254,
+ 68,207,207,207, 2,175,160, 42, 31,145,207, 2, 36, 35,130, 71, 70,129, 72, 2,204,253,250,205, 2, 72,129,141,130, 37, 35, 1,
+206,153, 24, 43,161, 40, 38,189, 97, 97,189, 39,196, 2,109,253,147, 57, 57, 2,109,253,147, 57, 2,249, 32, 18, 30,253,149, 51,
+ 46, 48, 53, 53, 95, 52, 2,105,253,151, 52, 95, 53, 53, 48, 46, 51, 2,107, 12, 22, 11, 35,116,116,242,242,116, 0, 2, 0, 22,
+ 0, 6, 4,187, 4,107, 0, 22, 0, 34, 0, 0, 1, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 38, 39, 46, 1, 7, 6,
+ 7, 39, 18, 1, 19, 35, 3, 35, 17, 35, 3, 35, 3, 35, 19, 1,214,138,118, 41, 37,151, 56, 27, 13, 32, 95, 94,168, 62, 25, 58,
+107,123,149, 90,172, 3,178, 71, 95, 63,215,103, 1,214, 64, 96, 72, 4, 44, 62, 6, 30,124, 58, 61, 43, 44,106, 44, 44, 60,134,
+ 54, 79, 47, 50,217, 51, 1, 51,254, 29,254, 60, 1, 98,254,158, 1, 98,254,158, 1,196, 0, 0, 0, 2, 0, 74,255,253, 4,135,
+ 5, 30, 0, 13, 0, 49, 0, 0, 0, 20, 30, 1, 51, 50, 62, 1, 52, 46, 1, 35, 34, 6, 19, 21, 51, 22, 54, 55, 20, 4, 7, 6,
+ 7, 35, 38, 55, 38, 36, 3, 30, 1, 55, 51, 53, 38, 39, 46, 1, 52, 62, 1, 50, 30, 1, 20, 6, 7, 6, 1,207, 44, 80, 42, 43,
+ 80, 44, 46, 78, 43, 41, 80,164, 5,133,198,151,254,100, 34, 47, 1, 37, 40, 2, 4,254, 77, 77,174,216,126, 6, 57, 53, 68, 76,
+ 77,137,145,139, 78, 77, 68, 50, 4, 41, 87, 78, 44, 44, 78, 87, 80, 42, 42,254,103,136, 1,168, 33,202,135,132,119,214,156,143,
+115,126, 1, 10, 1,215, 12,135, 6, 31, 38,136,151,138, 74, 74,138,151,136, 38, 28, 0, 0, 0, 0, 3, 0, 30, 0, 0, 4,179,
+ 4,211, 0, 63, 0, 71, 0, 79, 0, 0, 0, 50, 31, 1, 22, 23, 55, 22, 23, 7, 22, 23, 55, 22, 23, 7, 22, 20, 7, 23, 6, 7,
+ 39, 6, 7, 23, 6, 7, 39, 6, 15, 1, 6, 34, 47, 1, 38, 39, 7, 38, 39, 55, 38, 39, 7, 38, 39, 55, 38, 52, 55, 39, 54, 55,
+ 23, 54, 55, 39, 54, 55, 23, 54, 63, 1, 18, 32, 6, 16, 22, 32, 54, 16, 6, 20, 6, 34, 38, 52, 54, 50, 2, 69, 71, 35, 26, 57,
+ 54, 92, 62, 52, 50, 40, 28,112, 30, 13, 95, 4, 4, 95, 13, 30,112, 28, 40, 50, 52, 62, 92, 54, 57, 26, 35, 71, 35, 26, 58, 53,
+ 92, 62, 52, 50, 40, 28,112, 30, 13, 95, 4, 4, 95, 13, 30,112, 28, 40, 50, 52, 62, 92, 53, 58, 26,218,254,217,209,209, 1, 39,
+209,224, 78,109, 78, 78,109, 4,211, 4,128, 11, 25, 85, 37, 52,109, 43, 51, 13, 69, 74, 53, 30, 58, 29, 54, 74, 69, 13, 51, 43,
+109, 52, 37, 84, 24, 12,127, 5, 5,127, 12, 24, 84, 37, 52,109, 43, 51, 13, 69, 74, 54, 29, 58, 30, 53, 74, 69, 13, 51, 44,108,
+ 52, 37, 84, 24, 11,128,255, 0,210,254,217,208,208, 1, 39, 92,110, 77, 77,110, 77, 0, 0, 0, 0, 15, 0, 42, 0, 12, 4,167,
+ 5, 63, 0, 8, 0, 13, 0, 18, 0, 23, 0, 28, 0, 33, 0, 38, 0, 43, 0, 48, 0, 53, 0, 58, 0, 63, 0, 68, 0, 80, 0,145,
+ 0, 0, 0, 20, 30, 1, 51, 38, 55, 34, 6, 5, 22, 23, 55, 38, 39, 22, 23, 55, 38, 39, 22, 23, 55, 38, 39, 22, 7, 55, 38, 39,
+ 22, 7, 23, 54, 39, 6, 7, 23, 54, 37, 23, 54, 55, 6, 7, 23, 54, 55, 6, 7, 23, 54, 55, 6, 31, 1, 38, 55, 6, 23, 55, 38,
+ 55, 6, 23, 55, 38, 39, 6, 23, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 39, 53, 38, 39, 46, 1, 52, 62, 1, 51, 50, 30, 1,
+ 20, 6, 7, 6, 7, 51, 20, 35, 21, 22, 23, 22, 23, 54, 55, 4, 23, 6, 35, 38, 7, 22, 21, 20, 7, 6, 7, 3, 21, 6, 35, 34,
+ 39, 53, 3, 38, 39, 38, 53, 52, 55, 38, 7, 34, 39, 54, 37, 22, 23, 54, 55, 54, 2, 49, 15, 27, 16, 26, 26, 15, 28, 1,180, 97,
+ 36, 23, 79,127, 96, 32, 34, 78,105, 66, 14, 42, 52,108, 44, 1, 52, 34, 85, 2, 21, 52, 2, 55, 41, 44, 51, 40,252,224, 23, 36,
+ 97, 77, 35, 34, 31, 97, 84, 17, 42, 14, 66, 70, 13, 52, 1, 44, 61, 52, 52, 22, 3, 35, 89, 51, 44, 41, 6,253, 48, 66, 66, 48,
+ 47, 67, 66, 79, 3, 2, 16, 19, 19, 34, 18, 18, 33, 19, 18, 17, 1, 3, 1, 1, 45, 36, 3, 3, 70, 19, 1, 36, 70, 74,223, 70,
+ 49, 4, 46, 35, 45, 1, 10, 20, 22, 7, 2, 45, 35, 45, 2, 50, 77,223, 74, 70, 1, 36, 19, 71, 6, 8, 35, 5, 9, 30, 27, 16,
+ 56, 60, 15,103, 55, 42, 33, 50, 17, 85, 54, 29, 74, 37,110, 61, 17, 95, 67,127, 66, 7,110, 84,135, 62, 9,114, 89,119, 48, 23,
+100, 9, 34, 42, 55, 14, 93, 29, 54, 85, 36,117, 17, 61,110, 59,119, 7, 66,127, 76,122, 9, 62,135, 92,101, 23, 48,119, 90, 51,
+ 67, 46, 49, 66, 66, 49, 46, 67, 40, 78, 1, 2, 9, 34, 37, 34, 18, 18, 34, 37, 34, 9, 2, 1, 1, 77, 8, 35, 3, 3,112, 46,
+ 5, 80,143, 22, 22, 17, 18, 65, 46, 36, 7,253, 59, 81, 19, 25, 87, 2,185, 7, 36, 46, 65, 15, 15, 28, 23,142, 80, 5, 45,123,
+ 9, 8, 34, 0, 0, 15, 0, 82, 0, 11, 4,127, 4,199, 0, 15, 0, 26, 0, 38, 0, 46, 0, 70, 0, 82, 0,138, 0,150, 0,158,
+ 0,166, 0,178, 0,186, 0,194, 0,202, 0,214, 0, 0, 1, 50, 30, 1, 21, 20, 14, 1, 35, 34, 46, 1, 53, 52, 62, 1, 7, 38,
+ 39, 6, 7, 6, 22, 55, 54, 55, 38, 37, 6, 7, 22, 23, 22, 55, 54, 39, 38, 39, 6, 39, 22, 21, 20, 7, 54, 55, 38, 39, 38, 39,
+ 38, 39, 6, 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 23, 54, 55, 54, 55, 54, 53, 52, 55, 22, 23, 22, 23, 54, 55, 54, 39, 38, 7,
+ 6, 5, 55, 62, 1, 51, 50, 22, 23, 21, 54, 23, 22, 23, 22, 21, 20, 7, 6, 7, 51, 22, 23, 22, 21, 20, 7, 14, 1, 39, 35, 6,
+ 7, 6, 35, 34, 39, 38, 39, 6, 38, 39, 38, 53, 52, 55, 54, 55, 38, 39, 38, 53, 52, 55, 54, 55, 54, 5, 38, 39, 38, 35, 34, 7,
+ 6, 7, 22, 23, 54, 23, 6, 7, 22, 23, 22, 23, 38, 37, 6, 7, 54, 55, 54, 55, 38, 39, 38, 39, 38, 7, 6, 23, 22, 23, 54, 55,
+ 54, 7, 6, 7, 22, 23, 38, 53, 52, 23, 22, 23, 54, 55, 38, 39, 38, 23, 22, 23, 54, 55, 6, 7, 6, 7, 6, 7, 22, 23, 22, 51,
+ 50, 55, 54, 55, 38, 2,104, 16, 29, 16, 16, 29, 16, 16, 29, 16, 16, 29,183, 64, 57,104, 41, 44, 41, 82, 80,124, 12, 1,136, 5,
+ 11,124, 80, 82, 21, 21, 45, 42,103, 58, 62, 2, 2, 47, 42, 42, 89, 38, 40, 41, 40, 40, 39, 41, 38, 1, 1, 38, 41, 39, 41, 40,
+ 40, 41, 37, 3, 20, 12, 5, 64, 57,102, 43, 46, 21, 21, 84, 82,254, 34, 1, 28, 96, 51, 51, 96, 27,138, 92, 95, 26, 9, 28, 46,
+110, 1,112, 44, 27, 9, 26,183,140, 1, 27, 48, 48, 52, 52, 49, 47, 28,139,184, 25, 9, 26, 44,112,110, 44, 28, 9, 26, 93, 93,
+ 1,194, 22, 38, 38, 40, 41, 38, 38, 21, 69, 69, 69, 74, 48, 51, 28, 29, 27, 27, 4,254,217, 7, 5, 27, 28, 28, 28, 50, 87,121,
+ 81, 84, 20, 22, 46, 44,100, 57, 64, 5, 7, 46, 42, 42, 46, 1, 46, 5, 7, 49, 50, 28, 28, 29,174, 51, 48, 8, 4, 26, 28, 29,
+ 73, 68, 69, 21, 37, 38, 42, 42, 37, 38, 21, 70, 2,166, 15, 30, 17, 16, 28, 17, 17, 28, 16, 17, 30, 15,176, 43, 46, 83, 69, 70,
+ 69, 3, 3, 46, 73, 77, 77, 73, 46, 3, 3, 34, 35, 70, 69, 83, 46,136, 32, 33, 31, 32, 31, 32, 34, 59, 24, 23, 23, 21, 21, 23,
+ 23, 24, 45, 48, 46, 45, 25, 23, 23, 21, 21, 23, 23, 25, 45, 46, 48,217, 73, 77, 43, 46, 82, 69, 70, 36, 36, 4, 4, 8, 2,145,
+156,156,145, 2, 49, 1, 2, 46, 16, 22, 37, 50, 83, 95, 96, 81, 50, 37, 22, 16, 45, 4, 49,143, 79, 81, 81, 79,143, 50, 5, 45,
+ 16, 22, 36, 51, 81, 96, 95, 82, 51, 38, 21, 16, 46, 2, 1, 62,131, 71, 73, 73, 71,131, 26, 34, 34, 13, 21, 23, 15, 16, 17, 16,
+ 55, 52, 52, 55, 16, 17, 16, 15, 23, 35, 46, 4, 4, 36, 36, 70, 69, 82, 47, 43, 76,127, 31, 34, 32, 31, 32, 31, 33,174, 55, 53,
+ 20, 24, 14, 17, 16, 47, 24, 20, 53, 55, 17, 16, 17, 37, 34, 27,128, 73, 74, 74, 73,128, 27, 0, 0, 7, 0, 42,255,254, 4,167,
+ 5, 26, 0, 11, 0, 20, 0, 29, 0, 41, 0,112, 0,126, 0,140, 0, 0, 1, 20, 23, 54, 55, 38, 39, 54, 55, 38, 39, 6, 5, 52,
+ 38, 21, 6, 21, 22, 23, 54, 37, 6, 23, 54, 55, 46, 1, 39, 6, 5, 52, 39, 6, 7, 22, 23, 6, 7, 22, 23, 54, 3, 38, 7, 6,
+ 7, 38, 39, 54, 55, 22, 23, 54, 55, 38, 53, 52, 63, 1, 21, 22, 21, 20, 7, 30, 1, 23, 54, 55, 22, 23, 6, 7, 38, 39, 38, 7,
+ 22, 23, 22, 20, 7, 6, 7, 22, 23, 6, 35, 38, 39, 6, 7, 6, 7, 35, 38, 39, 53, 38, 39, 6, 7, 34, 39, 54, 55, 38, 39, 38,
+ 52, 55, 54, 6, 20, 30, 1, 51, 50, 62, 1, 52, 46, 1, 35, 34, 6, 55, 50, 30, 1, 20, 14, 1, 35, 34, 46, 1, 52, 62, 1, 2,
+154, 34, 48, 39, 45, 8, 3, 44, 32, 41, 42,255, 0, 35, 39, 7, 48, 19, 1,163, 6, 20, 53, 3, 3, 37, 1, 34,255, 0, 42, 37,
+ 37, 44, 3, 12, 41, 44, 44, 34,232, 71, 26, 28, 78, 89, 2, 2,160,148, 73, 39, 43, 34,144, 1,143, 34, 36, 40, 5, 74,147,161,
+ 1, 2, 89, 78, 28, 18, 79, 23, 17, 50, 49, 21, 28, 30, 44, 1, 12, 57, 44, 52, 61, 83, 22, 28, 28, 77, 58, 55, 44, 58, 12, 1,
+ 45, 30, 28, 20, 49, 50, 17, 45, 91,165, 91, 90,165, 91, 93,166, 87, 88,166,254, 73,139, 79, 77,139, 75, 76,139, 77, 78,140, 2,
+ 50,142,147, 13, 31, 89,123,149, 92, 25, 13, 98,179, 67, 87, 1, 68, 74,103, 65, 66, 99,112, 55, 76, 94, 66, 77, 1, 76, 48,148,
+ 98, 11, 27, 92,149,117, 93, 33, 13,147, 1, 64, 82, 37, 75, 2, 2,108,104, 2, 6,104, 22, 15, 79, 43,119,213, 1, 1,213,119,
+ 43, 79, 11, 23, 3,104, 6, 2,104,108, 2, 2, 75, 36, 80, 27, 30, 90,192, 88, 39, 31, 64, 68, 10, 48, 58, 41, 19, 30,119,119,
+ 30, 1, 18, 42, 59, 48, 10, 69, 65, 30, 38, 88,192, 90, 30,119,180,165, 91, 91,165,180,167, 91, 91, 71, 74,140,152,138, 77, 77,
+138,152,140, 74, 0, 4, 0, 34, 0, 2, 4,175, 4, 40, 0, 7, 0, 13, 0, 21, 0, 37, 0, 0, 1, 51, 1, 21, 33, 39, 35, 0,
+ 23, 1, 21, 33, 53, 0, 7, 50, 21, 2, 35, 34, 3, 54, 19, 50, 30, 1, 21, 20, 14, 1, 35, 34, 46, 1, 53, 52, 62, 1, 2,111,
+ 5, 2, 58,251,129, 6, 6, 2, 53, 16,254, 40, 3,183,254, 54, 14, 55, 37, 18, 16, 39, 18, 36, 14, 26, 15, 14, 27, 14, 14, 26,
+ 15, 15, 26, 4, 40,251,225, 6, 6, 4, 7,110,252,170, 12, 6, 3, 72,138, 48,254, 76, 1,186, 42,253,231, 14, 25, 15, 15, 25,
+ 14, 14, 25, 15, 15, 25, 14, 0, 0, 1, 0,136, 0, 8, 4, 73, 5, 34, 0, 19, 0, 0, 1, 51, 23, 21, 1, 20, 51, 4, 21, 23,
+ 1, 39, 53, 0, 53, 52, 35, 36, 47, 1, 4, 42, 12, 19,253,220, 80, 1, 82, 7,252,198, 12, 2, 54,104,254,193, 14, 6, 5, 34,
+ 19, 6,254, 38, 62, 73, 12, 62,253,170, 19, 6, 2, 12, 11, 62, 65, 15, 62, 0, 0, 1, 0,243, 0, 0, 3,223, 5,216, 0, 5,
+ 0, 0, 1, 33, 19, 3, 33, 3, 1,174, 1,117,188,188,254,139,187, 5,216,254,137,251,159, 4, 97, 0, 0, 0, 0, 1, 0,222,
+ 0, 0, 3,243, 4,193, 0, 19, 0, 0, 1, 22, 21, 20, 7, 3, 33, 3, 38, 53, 52, 55, 54, 39, 35, 53, 33, 23, 7, 22, 3, 43,
+200, 7,193,254,123,192, 8,200,104, 6, 95, 1,129, 1, 97, 1, 3,246, 54,145, 26, 29,253, 8, 2,248, 31, 27,142, 54, 21,109,
+ 72, 72, 1,109, 0, 3, 0, 46, 1,114, 4,163, 3,243, 0, 90, 0,121, 0,153, 0, 0, 1, 39, 35, 34, 39, 38, 7, 6, 21, 20,
+ 7, 6, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 51, 50, 31, 1, 22, 51, 50, 55, 54, 55,
+ 54, 55, 54, 39, 38, 39, 38, 39, 38, 47, 1, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 50, 22, 23, 22, 23, 22, 21, 20,
+ 7, 6, 7, 6, 7, 6, 23, 22, 31, 1, 33, 50, 23, 22, 23, 33, 23, 37, 22, 51, 50, 55, 54, 55, 54, 55, 54, 53, 52, 39, 38, 39,
+ 38, 39, 38, 35, 34, 7, 6, 7, 6, 7, 6, 21, 20, 23, 30, 1, 19, 38, 35, 34, 7, 6, 7, 6, 7, 6, 21, 20, 23, 22, 23, 22,
+ 23, 22, 51, 50, 55, 54, 55, 54, 55, 54, 53, 52, 39, 38, 39, 38, 2,203,151, 80,122, 20, 30, 2, 1, 7, 9, 18, 16, 25, 20, 30,
+ 25, 26, 25, 18, 15, 16, 13, 9, 9, 17, 17, 25, 20, 30, 24, 26, 44, 68, 64, 26, 9, 16, 13, 13, 2, 2, 3, 2, 9, 8, 16, 55,
+ 59, 43, 26, 18, 20, 10, 14, 9, 9, 18, 19, 22, 25, 50, 51, 18, 22, 9, 13, 9, 6, 9, 12, 2, 4, 24, 29, 77, 57, 1, 22,163,
+ 56, 71, 12,254, 41,149,253, 58, 14, 14, 17, 12, 14, 9, 12, 3, 4, 9, 7, 10, 13, 13, 17, 12, 14, 14, 15, 9, 9, 5, 4, 9,
+ 7, 21,214, 13, 16, 20, 8, 15, 9, 12, 3, 4, 9, 7, 10, 11, 15, 15, 14, 17, 11, 15, 9, 11, 3, 5, 10, 7, 10, 8, 1,114,
+145, 4, 6, 10, 5, 17, 12, 16, 23, 17, 15, 9, 8, 10, 10, 18, 14, 26, 20, 27, 26, 20, 23, 16, 16, 9, 8, 10, 18, 27, 2, 3,
+ 9, 11, 5, 5, 17, 16, 13, 14, 13, 48, 24, 17, 11, 17, 19, 21, 26, 21, 26, 20, 23, 17, 17, 7, 8, 21, 17, 21, 20, 25, 23, 24,
+ 21, 17, 8, 12, 5, 9, 15, 19, 76, 58, 22, 29, 53,146, 85, 6, 4, 5, 7, 9, 12, 12, 12, 9, 17, 12, 9, 12, 5, 6, 4, 5,
+ 7, 9, 12, 12, 12, 10, 16, 12, 20, 1,231, 7, 4, 5, 7, 11, 10, 12, 12, 11, 15, 12, 10, 9, 7, 6, 3, 5, 8, 10, 10, 12,
+ 13, 10, 15, 13, 10, 7, 0, 0, 0, 3, 0, 46, 1, 92, 4,163, 4, 11, 0, 25, 0,114, 0,140, 0, 0, 18, 50, 54, 55, 54, 55,
+ 54, 53, 52, 39, 38, 39, 46, 1, 34, 6, 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 1, 5, 6, 35, 34, 39, 37, 7, 14, 1, 21, 20,
+ 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 59, 1, 50, 55, 62, 1, 55,
+ 54, 52, 39, 46, 1, 39, 38, 43, 1, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 50, 23, 22, 23, 22, 23, 22, 21,
+ 20, 7, 6, 21, 20, 22, 31, 1, 37, 54, 51, 50, 23, 36, 34, 6, 7, 6, 7, 6, 21, 20, 23, 22, 23, 30, 1, 50, 54, 55, 54, 55,
+ 54, 53, 52, 39, 38, 39, 38,172, 35, 28, 12, 13, 6, 6, 6, 6, 13, 12, 28, 35, 28, 12, 13, 6, 6, 6, 6, 13, 12, 2, 64, 1,
+210, 33, 82, 60,165,254,237, 79,113, 60, 8, 5, 11, 10, 21, 17, 30, 24, 59, 25, 25, 21, 20, 12, 10, 10, 11, 21, 16, 30, 25, 29,
+ 51, 64, 77, 20, 28, 9, 9, 9, 9, 28, 20, 74, 67, 51, 29, 25, 30, 16, 21, 11, 10, 10, 12, 20, 21, 25, 25, 59, 24, 30, 17, 21,
+ 10, 11, 5, 8, 60,113, 79, 1, 19,165, 60, 82, 33,252, 45, 35, 28, 12, 13, 6, 6, 6, 6, 13, 12, 28, 35, 28, 12, 13, 6, 6,
+ 6, 6, 13, 12, 1,152, 10, 10, 11, 11, 12, 14, 14, 12, 11, 11, 9, 11, 11, 9, 11, 11, 12, 14, 14, 12, 11, 11, 10, 1, 18,190,
+ 47, 65,110, 33, 47, 10, 10, 6, 17, 12, 19, 26, 23, 22, 19, 16, 12, 10, 10, 10, 18, 15, 26, 23, 26, 26, 23, 22, 19, 16, 12, 10,
+ 25, 7, 20, 14, 16, 12, 15, 15, 19, 7, 25, 10, 12, 16, 19, 22, 23, 26, 26, 23, 26, 16, 17, 10, 10, 10, 12, 15, 20, 22, 23, 26,
+ 19, 12, 16, 6, 11, 11, 46, 33,109, 66, 48, 95, 11, 9, 11, 11, 12, 14, 14, 12, 11, 10, 10, 11, 11, 10, 10, 11, 12, 14, 14, 12,
+ 11, 11, 9, 0, 0, 3, 0, 58, 1, 63, 4,151, 3,178, 0, 89, 0,120, 0,151, 0, 0, 1, 51, 7, 33, 6, 7, 6, 35, 33, 7,
+ 6, 7, 6, 21, 20, 23, 22, 23, 22, 21, 20, 7, 6, 7, 14, 1, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 63, 1, 54,
+ 55, 54, 55, 54, 55, 54, 39, 38, 39, 38, 39, 38, 35, 34, 15, 1, 6, 35, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 62, 1, 55, 54,
+ 51, 50, 23, 22, 23, 22, 23, 22, 21, 20, 23, 22, 55, 54, 59, 1, 37, 6, 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 23, 22, 51, 50,
+ 54, 55, 54, 55, 54, 53, 52, 39, 38, 39, 38, 39, 38, 35, 34, 19, 54, 55, 54, 55, 54, 53, 52, 39, 38, 39, 38, 39, 38, 35, 34, 6,
+ 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 23, 22, 51, 50, 2,201,147,147, 1,205, 12, 69, 55,159,254,241, 57, 69, 34, 20, 14, 9,
+ 6, 8, 12, 9, 21, 18, 50, 49, 24, 22, 19, 19, 7, 8, 13, 8, 21, 18, 25, 43, 57, 54, 15, 8, 9, 2, 3, 2, 2, 13, 7, 21,
+ 5, 30, 62, 66, 43, 25, 24, 30, 19, 25, 16, 17, 9, 8, 12, 13, 35, 25, 25, 25, 29, 19, 25, 16, 17, 9, 6, 2, 4, 27, 17,122,
+ 79,254,111, 15, 10, 6, 11, 9, 4, 5, 9, 7, 16, 12, 16, 14, 29, 10, 11, 7, 8, 4, 4, 10, 5, 19, 11, 16, 14,180, 15, 10,
+ 6, 11, 9, 4, 5, 9, 10, 13, 12, 15, 15, 29, 10, 10, 7, 9, 4, 5, 9, 11, 13, 13, 14, 10, 3,178,142, 52, 28, 22, 57, 68,
+ 24, 14, 11, 3, 13, 8, 16, 23, 24, 18, 27, 19, 20, 17, 20, 7, 7, 17, 18, 21, 23, 21, 18, 29, 19, 20, 17, 10, 17, 23, 47, 13,
+ 13, 14, 15, 16, 6, 5, 10, 5, 7, 2, 27, 17, 10, 8, 9, 15, 16, 22, 22, 23, 24, 23, 22, 34, 10, 10, 8, 9, 15, 16, 22, 16,
+ 12, 19, 3, 10, 7, 4, 58, 6, 9, 6, 16, 14, 11, 14, 10, 12, 8, 6, 6, 4, 12, 10, 9, 12, 15, 13, 11, 10, 12, 8, 7, 5,
+ 4,254, 24, 6, 9, 5, 17, 13, 11, 15, 10, 11, 9, 8, 4, 3, 12, 9, 10, 12, 13, 12, 15, 9, 11, 9, 9, 3, 4, 0, 0, 0,
+ 0, 9, 0, 61, 1, 74, 4,148, 4, 3, 0, 90, 0,120, 0,150, 0,180, 0,210, 0,254, 1, 45, 1, 52, 1, 72, 0, 0, 1, 54,
+ 55, 38, 39, 38, 39, 38, 43, 1, 34, 39, 38, 39, 38, 39, 38, 52, 55, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 21, 20,
+ 7, 22, 31, 1, 55, 54, 51, 50, 23, 22, 21, 20, 7, 13, 1, 22, 21, 20, 7, 6, 35, 34, 47, 1, 7, 6, 7, 22, 21, 20, 7, 6,
+ 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 59, 1, 50, 55, 54, 6, 50, 55, 54, 55, 54, 55,
+ 54, 53, 52, 39, 38, 39, 38, 39, 38, 34, 7, 6, 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 23, 18, 50, 55, 54, 55, 54, 55, 54, 53,
+ 52, 39, 38, 39, 38, 39, 38, 34, 7, 6, 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 23, 18, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55,
+ 54, 55, 54, 55, 54, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 2, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55,
+ 54, 55, 54, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 5, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 53, 52, 39, 38,
+ 39, 38, 39, 38, 34, 7, 6, 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 23, 22, 59, 1, 50, 23, 22, 23, 22, 23, 55, 54, 7, 45, 1,
+ 38, 35, 34, 15, 1, 6, 7, 6, 7, 6, 7, 6, 43, 1, 34, 7, 6, 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 23, 22, 50, 55, 54,
+ 55, 54, 55, 54, 53, 52, 39, 38, 53, 52, 55, 54, 37, 23, 22, 51, 50, 55, 37, 38, 20, 7, 6, 7, 6, 34, 39, 38, 39, 38, 52, 55,
+ 54, 55, 54, 50, 23, 22, 23, 1,157, 8, 5, 5, 8, 6, 17, 56, 63, 46, 31, 31, 25, 28, 23, 13, 13, 13, 11, 27, 19, 32, 29, 33,
+ 32, 30, 29, 24, 27, 9, 13, 5, 33, 97, 61,240,155, 63, 94, 39, 6, 21,254,161, 1, 95, 21, 6, 41, 92, 63,155,240, 61, 97, 33,
+ 5, 13, 13, 23, 25, 28, 33, 29, 35, 27, 28, 23, 29, 9, 13, 13, 11, 25, 19, 34, 29, 33, 46, 56, 63, 16,191, 20, 7, 8, 7, 6,
+ 3, 2, 2, 3, 6, 7, 8, 7, 20, 7, 8, 7, 7, 2, 2, 2, 2, 7, 7, 8, 7, 20, 7, 8, 7, 6, 3, 2, 2, 3, 6, 7,
+ 8, 7, 20, 7, 8, 7, 7, 2, 2, 2, 2, 7, 7, 8, 34, 34, 15, 14, 12, 13, 6, 6, 6, 6, 13, 12, 14, 15, 34, 15, 14, 12,
+ 13, 6, 6, 6, 6, 13, 12, 14, 15, 34, 15, 14, 12, 13, 6, 6, 6, 6, 13, 12, 14, 15, 34, 15, 14, 12, 13, 6, 6, 6, 6, 13,
+ 12, 14, 1, 12, 26,102, 27, 15, 8, 11, 8, 4, 9, 9, 18, 14, 26, 22, 50, 22, 22, 18, 17, 10, 9, 9, 9, 18, 14, 26, 22, 25,
+ 46, 63, 69, 21, 12, 16, 5, 24, 19,130, 1, 83, 1,161, 29, 64, 54,149,252,102, 12, 12, 16, 14, 19, 71, 61, 46, 25, 22, 26, 14,
+ 18, 9, 9, 9, 10, 17, 18, 22, 22, 50, 22, 26, 14, 18, 9, 9, 4, 8, 11, 9, 1, 21,197,149, 54, 64, 29,254,136,149, 3, 5,
+ 6, 6, 15, 6, 6, 5, 3, 3, 5, 6, 6, 15, 6, 6, 5, 2,152, 6, 8, 10, 5, 4, 7, 22, 11, 9, 23, 19, 29, 26, 66, 26,
+ 23, 27, 18, 12, 11, 11, 11, 21, 25, 23, 32, 27, 20, 13, 6, 41, 25, 95, 62, 57, 9, 12, 21, 8,143,142, 8, 26, 8, 8, 57, 62,
+ 95, 25, 41, 7, 16, 16, 32, 27, 29, 20, 22, 9, 11, 11, 11, 19, 24, 25, 37, 23, 31, 28, 24, 24, 19, 13, 11, 22, 6,207, 2, 4,
+ 5, 5, 5, 3, 5, 5, 3, 5, 5, 5, 3, 3, 3, 3, 6, 4, 5, 3, 5, 5, 4, 4, 5, 5, 4, 1,137, 3, 3, 6, 4, 5,
+ 3, 5, 5, 4, 4, 5, 5, 4, 2, 2, 4, 5, 5, 5, 3, 5, 5, 3, 5, 5, 5, 3,254, 73, 5, 5, 10, 11, 12, 12, 15, 15,
+ 12, 12, 11, 9, 6, 5, 5, 6, 9, 11, 12, 12, 15, 15, 12, 12, 11, 10, 5, 1,134, 5, 6, 9, 11, 12, 12, 15, 15, 12, 12, 11,
+ 10, 5, 5, 5, 5, 10, 11, 12, 12, 15, 15, 12, 12, 11, 9, 6, 63, 10, 42, 5, 3, 4, 5, 10, 7, 16, 10, 16, 22, 20, 18, 17,
+ 13, 12, 8, 8, 10, 15, 13, 22, 20, 22, 22, 20, 18, 17, 13, 11, 9, 23, 7, 9, 12, 6, 17, 12,186,133,170, 32, 59,100, 46, 21,
+ 20, 11, 9, 7, 24, 8, 11, 13, 17, 19, 19, 22, 23, 19, 22, 13, 15, 10, 8, 8, 11, 13, 18, 18, 19, 23, 16, 9, 17, 7, 14, 1,
+ 1, 63, 80, 60, 33,154, 30, 15, 6, 7, 4, 3, 3, 4, 7, 6, 15, 6, 6, 4, 4, 4, 4, 6, 0, 3, 0, 52, 0, 71, 4,157,
+ 4,180, 0,110, 0,128, 0,146, 0, 0, 1, 6, 7, 6, 21, 20, 23, 22, 23, 22, 23, 22, 51, 50, 55, 54, 55, 54, 55, 54, 53, 52,
+ 39, 38, 39, 38, 39, 38, 35, 34, 7, 6, 7, 6, 7, 6, 21, 20, 23, 22, 23, 21, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 51,
+ 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 35, 34, 39, 46, 2, 53, 52, 55, 54, 55, 38, 53, 52, 55, 18, 51, 50,
+ 23, 22, 21, 20, 7, 6, 35, 34, 7, 6, 7, 6, 21, 20, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 23, 54, 55, 54, 55, 54, 55, 22,
+ 23, 22, 7, 6, 7, 6, 7, 6, 39, 38, 1, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 54, 55, 54, 53, 52, 1,122, 3, 1,
+ 7, 7, 8, 14, 15, 17, 81,107,100, 89, 87, 71, 74, 35, 35, 35, 34, 75, 69, 89, 88,101, 97, 91, 87, 71, 74, 35, 35, 35, 21, 32,
+ 78, 42, 41, 41, 39, 85, 79,103,103,113,113,104, 98, 84, 81, 43, 41, 41, 39, 85, 81,101,103,114,115,101, 30, 50, 26, 13, 10, 20,
+ 2, 78,133,123, 59, 5, 11, 26, 25, 6, 40, 31, 22, 50, 46, 12, 13, 16, 25, 39, 28, 13, 12, 55, 17, 30, 36, 18, 17, 2, 33, 5,
+ 13, 2, 7, 14, 20, 25, 27, 15, 20, 1, 47, 45, 16, 12, 15, 10, 22, 7, 21, 7, 42, 12, 21, 22, 1, 64, 4, 5, 17, 20, 21, 17,
+ 19, 13, 14, 8, 37, 37, 36, 72, 73, 86, 87, 99,103, 87, 83, 77, 70, 38, 37, 37, 36, 72, 73, 87, 87,103, 98, 88, 49, 46,111, 80,
+ 98,101,113,115,103, 96, 87, 80, 44, 43, 43, 41, 83, 81,102,100,118,111,103, 95, 87, 82, 42, 43, 43, 13, 48, 63, 35, 34, 32, 24,
+ 23, 12, 11,150,174, 1, 36, 6, 14, 41, 42, 50, 47, 31, 22, 91, 84, 71, 23, 16, 20, 22, 6, 33, 51, 30, 20, 40, 9, 24, 31, 45,
+ 41, 18, 28, 6, 15, 11, 35, 24, 37, 21, 23, 3, 5, 3, 3, 16, 12, 9, 36, 33, 39, 26, 28, 8, 7, 13, 40, 42, 48, 38, 0, 0,
+ 0, 6, 0, 37, 0, 63, 4,172, 4,201, 0, 15, 0, 28, 0, 44, 0, 74, 0,105, 0,137, 0, 0, 1, 38, 39, 38, 39, 55, 6, 21,
+ 20, 23, 22, 23, 22, 23, 22, 23, 19, 38, 39, 38, 34, 7, 6, 7, 19, 54, 51, 50, 23, 19, 23, 6, 7, 6, 7, 37, 54, 55, 54, 55,
+ 54, 55, 54, 53, 52, 38, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54,
+ 55, 54, 55, 19, 34, 7, 6, 7, 6, 7, 6, 21, 20, 23, 22, 23, 30, 1, 51, 50, 55, 54, 55, 54, 55, 54, 53, 52, 39, 38, 39, 38,
+ 39, 38, 39, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54,
+ 55, 54, 1, 36, 48, 24, 5, 3,223, 6, 14, 15, 26, 25, 36, 15, 6,182, 26, 34, 32, 78, 33, 33, 28, 53, 38, 41, 42, 38,102,224,
+ 2, 7, 24, 48,254,238, 10, 11, 36, 24, 27, 15, 14,211, 47, 19, 21, 16, 16, 9, 8, 8, 9, 16, 16, 21, 19, 47, 19, 20, 17, 17,
+ 8, 8, 8, 8, 17, 17, 20, 42,100, 93, 89, 74, 75, 36, 37, 37, 37, 74, 72,182,102,102, 92, 89, 74, 75, 36, 36, 36, 35, 76, 71,
+ 92, 90,104,116,106,101, 86, 84, 44, 43, 43, 40, 88, 82,105,105,117,115,107,100, 86, 84, 44, 42, 42, 40, 88, 81,105,106, 1,110,
+ 55, 60, 11, 12,189, 22, 26, 37, 34, 35, 27, 24, 16, 7, 1, 1, 59, 25, 15, 15, 15, 15, 25, 1, 34, 7, 7,254,136,189, 6, 17,
+ 60, 55, 98, 4, 4, 16, 24, 27, 35, 34, 37, 25, 88, 8, 9, 15, 18, 19, 21, 23, 22, 21, 19, 17, 16, 9, 8, 8, 9, 16, 17, 19,
+ 21, 22, 23, 21, 19, 18, 15, 9, 1,144, 38, 37, 74, 75, 89, 89,106,100, 91, 89, 74, 73, 77, 38, 37, 75, 74, 89, 89,102,106, 89,
+ 85, 79, 72, 39, 38, 75, 44, 42, 86, 83,104,103,121,114,106, 98, 89, 84, 43, 45, 45, 42, 85, 83,104,103,117,118,106, 98, 89, 83,
+ 45, 44, 0, 0, 0, 1, 0, 61, 0, 60, 4,148, 4, 91, 0, 45, 0, 0, 19, 53, 55, 39, 51, 23, 54, 55, 38, 3, 51, 23, 51, 21,
+ 35, 23, 51, 21, 35, 23, 51, 50, 23, 22, 20, 7, 6, 43, 1, 7, 51, 21, 35, 7, 51, 21, 35, 7, 35, 18, 55, 38, 39, 7, 35, 55,
+ 82, 27, 48, 75,110,109,215, 40,128, 92, 86,111, 64, 75,115, 70,114,198, 53, 36, 24, 24, 36, 53,198,114, 70,115, 75, 64,111, 86,
+ 92,128, 40,215,109,110, 75, 48, 2, 61, 30, 3,164,151, 10, 7,208, 1, 15,113, 60, 97, 60,149, 19, 13, 33, 13, 19,149, 60, 97,
+ 60,113, 1, 8,215, 8, 9,150,163, 0, 0, 0, 0, 5, 0, 63, 0,115, 4,146, 3,150, 0, 13, 0, 20, 0, 34, 0, 41, 0, 45,
+ 0, 0, 1, 37, 33, 5, 54, 55, 54, 55, 54, 50, 23, 22, 23, 22, 23, 5, 17, 5, 22, 21, 20, 13, 1, 33, 37, 6, 7, 6, 7, 6,
+ 34, 39, 38, 39, 38, 39, 37, 17, 37, 38, 53, 52, 1, 17, 33, 17, 2,223, 1, 79,252,117, 1, 79, 5, 6, 22, 28, 26, 63, 26, 33,
+ 17, 6, 36, 1, 71,254,185, 2,254,243,254,176, 3,139,254,176, 5, 5, 22, 28, 26, 63, 26, 28, 22, 5, 38,254,186, 1, 70, 2,
+254,111, 4, 83, 2,100,229,229, 7, 6, 21, 13, 11, 11, 15, 19, 7,129,221, 1,241,221, 13, 14, 15, 81,229,229, 6, 6, 21, 12,
+ 11, 11, 12, 21, 6,129,221,254, 15,220, 14, 15, 14,254, 96, 3, 35,252,221, 0, 0, 4, 1, 68, 0, 11, 3,141, 4,234, 0, 75,
+ 0,198, 0,217, 0,233, 0, 0, 1, 52, 55, 54, 63, 1, 54, 55, 50, 59, 1, 38, 39, 38, 39, 38, 53, 52, 55, 54, 51, 50, 23, 22,
+ 23, 22, 31, 1, 22, 23, 54, 55, 54, 55, 54, 55, 54, 53, 52, 39, 38, 55, 54, 51, 50, 23, 22, 23, 22, 15, 1, 6, 31, 1, 22, 21,
+ 20, 7, 23, 20, 7, 6, 21, 20, 23, 33, 53, 52, 39, 38, 39, 38, 55, 54, 39, 38, 1, 38, 35, 34, 15, 1, 6, 15, 1, 6, 15, 1,
+ 39, 38, 47, 1, 38, 39, 38, 39, 38, 35, 34, 7, 6, 21, 20, 23, 22, 31, 2, 22, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 39, 38,
+ 47, 1, 38, 39, 38, 35, 34, 7, 6, 7, 22, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 21, 20, 23, 22, 23, 22, 23, 22, 21, 20,
+ 7, 38, 39, 38, 39, 38, 63, 1, 54, 39, 38, 39, 6, 35, 34, 39, 38, 39, 38, 35, 34, 23, 22, 23, 22, 31, 1, 22, 21, 7, 33, 39,
+ 52, 55, 54, 47, 1, 54, 53, 52, 39, 38, 55, 19, 54, 39, 1, 7, 22, 23, 22, 23, 22, 23, 22, 51, 50, 55, 54, 53, 52, 39, 38, 39,
+ 38, 7, 6, 7, 22, 23, 22, 51, 50, 55, 54, 53, 52, 39, 38, 47, 1, 1, 68, 31, 18, 14, 43, 17, 31, 2, 2, 3, 21, 34, 25, 16,
+ 28, 19, 22, 30, 13, 14, 40, 14, 60, 62, 31, 12, 12, 15, 5, 4, 9, 4, 10, 4, 1, 5, 30, 22, 33, 45, 24, 11, 1, 9, 2, 7,
+ 1, 2, 2, 3, 1, 3, 17, 3, 1,254, 64, 4, 7, 31, 40, 1, 2, 24, 15, 2, 19, 3, 32, 28, 4, 4, 1, 8, 29, 4, 18, 44,
+ 20, 8, 35, 14, 37, 62, 22, 16, 14, 11, 14, 7, 6, 24, 11, 15, 78,112, 78, 77, 3, 16, 4, 4, 18, 15, 4, 3, 38, 95, 42, 6,
+ 35, 24, 16, 10, 5, 4, 3, 7, 40, 33, 10, 7, 38, 41, 17, 12, 1, 44, 19, 20, 44, 8, 2, 23,102, 38, 5, 6, 11, 1, 6, 2,
+ 6, 6, 12, 23, 33, 11, 13, 19, 14, 40, 8, 3, 2, 8, 6, 3, 8, 75, 1, 1, 1, 95, 1, 10, 11, 1, 1, 2, 7, 5, 1, 9,
+ 1, 2,254, 90, 14, 29, 48, 45, 14, 3, 1, 14, 8, 9, 3, 2, 10, 4, 5, 89,105, 12, 2, 68, 31, 12, 9, 13, 7, 3, 10, 6,
+ 9, 99, 2,112, 45, 41, 5, 26, 76, 30, 9, 38,103, 75, 29, 49, 30, 22, 23, 26, 4, 10, 21, 91,154, 78, 30, 17, 14, 51, 36, 26,
+ 13,110, 47, 5, 9, 9, 34, 33, 24, 48, 21, 15,123, 73,246, 23, 34, 18, 29, 72, 30, 35,102, 24,109, 15,116, 50, 62,149, 15, 27,
+ 44, 55, 72, 31, 66, 73, 46, 2, 59, 47, 56, 91, 24, 44,160, 23, 5, 13, 9, 11, 81, 31, 91,122, 41, 12, 10, 9, 5, 9, 25, 46,
+ 22, 41,209, 83, 57, 76, 10, 7, 15, 3, 1, 16, 5, 6, 42, 69, 31, 3, 25, 18, 8, 6, 9, 18, 32, 26, 15, 9, 39, 43, 40, 29,
+ 52, 37, 26, 2, 40, 52, 23, 13, 32, 14, 5, 4, 13, 7, 42, 88, 13, 8, 19, 18, 62, 12, 9, 9, 4, 21, 3, 4, 10, 55, 3, 28,
+ 65, 41, 18,175, 8, 9,130,150, 48, 39, 45, 53, 55, 48, 43, 73, 59, 45, 37, 1, 10, 14, 42,254,167, 17, 35, 37, 40, 48, 10, 10,
+ 14, 13, 7, 8, 17, 19, 7, 4, 93, 15, 16, 39, 53, 46, 7, 14, 9, 8, 15, 14, 9, 4, 85, 0, 0, 8, 0, 45, 0,149, 4,164,
+ 3,252, 0, 6, 0, 57, 0, 76, 0,112, 0,123, 0,127, 0,137, 0,141, 0, 0, 19, 22, 55, 54, 53, 52, 39, 5, 34, 39, 38, 35,
+ 34, 7, 6, 43, 1, 34, 39, 15, 1, 55, 38, 53, 52, 63, 1, 54, 55, 54, 55, 54, 55, 54, 51, 50, 23, 55, 54, 51, 50, 23, 22, 21,
+ 7, 23, 22, 51, 50, 55, 51, 22, 21, 20, 7, 35, 53, 6, 37, 54, 55, 54, 55, 19, 39, 38, 35, 34, 7, 6, 15, 1, 22, 21, 20, 7,
+ 54, 37, 34, 47, 1, 7, 20, 7, 54, 55, 22, 21, 20, 7, 6, 35, 34, 7, 22, 21, 20, 7, 50, 55, 54, 51, 50, 23, 22, 51, 50, 55,
+ 54, 53, 52, 39, 6, 55, 22, 21, 20, 7, 21, 51, 54, 53, 52, 39, 5, 54, 55, 15, 1, 6, 21, 20, 23, 22, 23, 54, 53, 52, 15, 1,
+ 55, 38,169, 19, 15, 11, 12, 2,116, 33, 77, 35, 20, 27,108, 53, 23, 71, 59, 26, 64,188, 92, 5, 10, 50, 20, 18, 66, 88, 45, 48,
+ 25, 25, 37, 45,109, 32, 42, 27, 21, 9,135,145, 32, 28, 39, 4,161, 63, 44,177, 78,253,171, 24, 21, 6, 3,239, 26, 12, 22, 63,
+168, 39, 24, 14, 33, 31, 28, 2,159, 38, 17,173, 82, 59, 45, 62, 11, 26, 60, 92, 45, 17, 24, 14, 82, 53, 45, 54, 28, 69, 33, 34,
+ 36, 98, 31, 36, 18, 54, 36, 33,113, 34, 44,253,162, 59, 10,116, 64, 80, 34, 22, 31, 16,251, 35, 67, 5, 1,127, 2, 28, 22, 22,
+ 22, 12,223, 10, 3, 11, 6, 42, 70, 83,192, 13, 23, 18, 34,165, 68, 24, 88, 64, 33, 19, 9, 37,122, 36, 40, 18, 21,156, 96, 21,
+ 21, 93,129,148,106, 77, 26,166, 26, 80, 20, 11, 1, 10, 21, 10,166, 38, 79, 47, 43, 28, 64, 25, 6,252, 12,112, 95,117, 60, 2,
+ 30, 10, 15, 13, 11, 28, 1, 28, 51, 30, 32, 9, 8, 9, 4, 26, 68, 77, 75, 90, 5, 21, 82,100, 89, 76, 54, 68,149, 95, 89,171,
+ 66, 73,139, 53, 19, 46, 33, 22, 14, 2, 33, 39, 39,107, 71, 28, 26, 0, 0, 0, 0, 7, 0, 87, 0,132, 4,122, 4,166, 0, 21,
+ 0, 27, 0, 34, 0, 41, 0, 51, 0, 83, 0, 90, 0, 0, 1, 54, 55, 54, 53, 52, 47, 1, 6, 35, 20, 7, 6, 35, 20, 7, 23, 22,
+ 51, 50, 55, 54, 1, 63, 1, 15, 2, 19, 55, 1, 19, 37, 1, 55, 5, 1, 22, 53, 52, 39, 1, 0, 54, 53, 52, 39, 1, 7, 1, 22,
+ 51, 1, 54, 55, 54, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 35, 34, 39, 38, 53, 52, 55, 54, 55,
+ 54, 23, 7, 1, 22, 51, 50, 39, 3,242, 7, 4, 5, 1, 48, 19, 24, 44, 44, 59, 18,192, 7, 6, 8, 12, 9,253, 40,124, 11,119,
+124, 11,107,215, 2, 6,149,253,228,253,251, 14, 1,105, 1,171, 53, 2,254, 46, 1, 85, 44, 5,254, 92, 92, 1,164, 14, 12,253,
+234, 10, 13, 12, 13, 11, 8, 11, 8, 6, 4, 5, 7, 8, 12, 11, 12, 12, 13, 12, 7, 11, 8, 5, 3, 4, 8, 8, 37,103, 1,210,
+ 9, 8, 46, 1, 1, 11, 6, 10, 13, 8, 4, 7,193, 18, 59, 44, 45, 22, 20, 48, 1, 5, 4, 2,106,123,119, 11,123,119, 1, 51,
+ 15,253,251,253,228,150, 2, 4,216, 17,254, 86, 1, 46, 8, 10, 1,210,253, 84, 44, 27, 12, 14, 1,165, 92,254, 91, 5, 2, 94,
+ 11, 9, 8, 4, 3, 6, 7, 11, 8, 11, 13, 12, 14, 10, 12, 8, 8, 4, 3, 6, 5, 13, 9, 11, 13, 11, 13,198, 11,254, 45, 1,
+ 53, 0, 0, 0, 0, 7, 0, 38, 0,224, 4,171, 2,196, 0, 19, 0, 25, 0, 32, 0, 39, 0, 45, 0, 69, 0, 76, 0, 0, 0, 52,
+ 39, 38, 39, 38, 47, 1, 20, 7, 22, 20, 7, 22, 21, 55, 54, 55, 54, 55, 5, 53, 39, 7, 21, 23, 3, 55, 33, 13, 1, 33, 39, 55,
+ 33, 54, 53, 52, 39, 33, 4, 52, 39, 33, 21, 33, 36, 52, 55, 54, 55, 62, 1, 50, 22, 23, 22, 23, 22, 20, 7, 6, 7, 14, 1, 34,
+ 38, 39, 38, 39, 23, 7, 33, 54, 53, 52, 39, 4, 3, 3, 2, 5, 3, 8,149, 15, 36, 36, 15,149, 8, 3, 5, 2,252,230, 67, 67,
+ 67,124,124, 2, 93, 1,170,254, 86,253,163,124,234, 1,236, 18, 25,253,226, 2, 86, 35,254, 27, 1,229,253,117, 3, 2, 5, 5,
+ 13, 14, 13, 5, 6, 2, 3, 3, 2, 6, 5, 13, 14, 13, 5, 5, 2,142, 57, 2, 30, 25, 18, 1,202, 17, 8, 7, 6, 5, 4, 90,
+ 23, 15, 40,102, 40, 14, 23, 89, 4, 5, 7, 7, 60,153, 80, 80,153, 80, 1, 0,142,242,241,142,213, 18, 16, 19, 18,225, 80, 17,
+114, 43, 28, 13, 12, 11, 10, 11, 11, 10, 11, 12, 13, 28, 13, 12, 10, 10, 12, 12, 10, 10, 12, 86, 72, 18, 20, 16, 18, 0, 0, 0,
+ 0, 7, 0, 87, 0,187, 4,122, 4,221, 0, 21, 0, 27, 0, 34, 0, 41, 0, 51, 0, 83, 0, 90, 0, 0, 1, 38, 39, 38, 35, 34,
+ 15, 1, 22, 21, 50, 23, 22, 21, 50, 23, 55, 54, 53, 52, 39, 38, 1, 39, 31, 2, 39, 7, 47, 1, 1, 37, 3, 1, 39, 23, 1, 54,
+ 53, 52, 7, 46, 1, 35, 34, 7, 1, 23, 1, 54, 53, 1, 38, 39, 38, 39, 38, 53, 52, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 23,
+ 22, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 39, 38, 55, 1, 54, 35, 34, 7, 1, 3,242, 7, 9, 12, 8, 6, 7,192, 18, 59, 44,
+ 44, 24, 19, 48, 1, 5, 4,253, 26,119, 11,124,119, 11,136,161, 14, 2, 5, 2, 28,149,253,250, 15, 12, 1,210, 2, 53, 30, 44,
+ 27, 12, 14,254, 92, 92, 1,164, 5,253,163, 12, 8, 8, 4, 3, 5, 8, 11, 7, 12, 13, 12, 12, 11, 12, 8, 7, 5, 4, 6, 8,
+ 11, 8, 11, 13, 12, 13, 15, 1,169, 1, 46, 8, 9,254, 46, 4, 86, 7, 5, 4, 1, 48, 20, 22, 45, 44, 58, 19,193, 7, 4, 8,
+ 13, 10,253,163, 11,119,123, 11,119,173,160,216, 2, 5,149,253,229,253,250,192,104, 1,211, 10, 8, 46, 1,111, 44, 5,254, 91,
+ 92, 1,165, 14, 12,253,232, 12, 13, 11, 13, 11, 9, 13, 5, 6, 3, 4, 8, 8, 12, 10, 14, 12, 13, 11, 8, 11, 7, 6, 3, 4,
+ 8, 9,220, 1,170, 54, 2,254, 46, 0, 0, 0, 0, 2, 0, 59, 1, 43, 4,150, 3, 93, 0, 35, 0, 67, 0, 0, 18, 52, 39, 22,
+ 37, 5, 21, 37, 46, 1, 39, 38, 34, 7, 6, 7, 6, 7, 6, 20, 23, 22, 23, 22, 23, 22, 50, 55, 62, 1, 55, 37, 21, 5, 36, 7,
+ 54, 20, 7, 54, 5, 37, 5, 6, 7, 6, 34, 39, 38, 39, 38, 39, 38, 52, 55, 54, 55, 54, 55, 54, 50, 23, 22, 23, 5, 37, 4, 39,
+ 98, 38,224, 1,162, 1,215,254, 73, 4, 11, 13, 10, 23, 10, 11, 8, 8, 4, 5, 5, 6, 6, 8, 11, 10, 23, 10, 13, 11, 4, 1,
+183,254, 41,254, 94,224,116, 17,131, 1,156, 1, 78,254,241, 17, 20, 20, 47, 20, 21, 16, 17, 9, 8, 8, 9, 17, 16, 21, 20, 47,
+ 20, 20, 17, 1, 15,254,178,254,100,131, 1,201,247, 73, 3, 87,210, 63, 21, 6, 12, 7, 4, 4, 5, 8, 6, 13, 10, 24, 10, 14,
+ 5, 8, 4, 5, 5, 6, 12, 6, 22, 64,209, 86, 2,249,105, 68, 2, 86,141, 18, 16, 9, 9, 9, 9, 16, 17, 20, 21, 47, 20, 20,
+ 18, 16, 9, 8, 8, 9, 16, 19,141, 86, 3, 0, 0, 1, 0, 37, 1, 17, 4,172, 3, 27, 0, 38, 0, 0, 1, 37, 21, 5, 36, 7,
+ 54, 52, 39, 22, 37, 5, 21, 37, 38, 39, 38, 39, 38, 34, 7, 6, 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 23, 22, 50, 55, 54, 55,
+ 54, 2,232, 1,196,254, 4,254, 64,203, 41, 41,203, 1,192, 1,252,254, 60, 5, 13, 11, 15, 14, 34, 14, 15, 11, 13, 5, 7, 7,
+ 5, 13, 11, 15, 14, 34, 14, 15, 11, 13, 1,247, 23, 27,226, 93, 2, 78,184, 79, 3, 93,226, 27, 24, 14, 12, 12, 6, 7, 7, 6,
+ 12, 12, 14, 15, 17, 16, 15, 14, 12, 12, 6, 7, 7, 6, 12, 12, 0, 1, 0,152, 0,192, 4, 57, 4,124, 0, 28, 0, 0, 1, 50,
+ 23, 22, 51, 50, 55, 18, 55, 54, 51, 50, 22, 21, 20, 7, 0, 1, 6, 35, 34, 39, 38, 39, 38, 53, 52, 55, 54, 1, 24, 34, 18, 35,
+ 15, 12, 12,245,210, 54,118, 28, 19, 29,254,174,254,224, 20, 62, 63, 12, 30, 40, 45, 61, 37, 2, 80, 56,106, 18, 1,138,243, 63,
+ 10, 8, 13, 35,254,106,254, 60, 32, 6, 13,121,134, 34, 36, 34, 22, 0, 0, 0, 0, 1, 0, 74, 0,114, 4,135, 4, 66, 0, 29,
+ 0, 0, 1, 50, 23, 22, 51, 50, 55, 18, 55, 54, 51, 50, 23, 22, 21, 20, 7, 0, 7, 6, 35, 34, 39, 38, 39, 38, 53, 52, 55, 54,
+ 1, 7, 34, 18, 34, 15, 12, 12,246,209, 89, 84,111, 22, 10, 20,253,205,107, 37,133, 44, 48, 20, 50, 63, 61, 86, 2,142, 56,106,
+ 18, 1,105,153, 65, 7, 2, 20, 15, 24,253,123,195, 67, 23, 11,123,156,117, 43, 28, 39, 0, 0, 0, 1, 0,129, 0,113, 4, 80,
+ 4, 63, 0, 11, 0, 0, 9, 1, 7, 9, 1, 39, 9, 1, 55, 9, 1, 23, 2,219, 1,115,115,254,141,254,141,115, 1,115,254,141,
+115, 1,115, 1,116,115, 2, 88,254,140,114, 1,115,254,141,114, 1,116, 1,115,115,254,141, 1,115,114, 0, 0, 0, 1, 0, 64,
+ 0,188, 4, 81, 4,207, 0, 11, 0, 0, 9, 1, 7, 9, 1, 39, 9, 1, 55, 9, 1, 23, 3, 53, 1, 28,237,254,228,254,229,237,
+ 1, 28,254,228,237, 1, 27, 1, 28,237, 2,197,254,229,237, 1, 27,254,229,237, 1, 27, 1, 27,237,254,229, 1, 28,237, 0, 0,
+ 0, 1, 0,131,255,236, 4, 78, 4,190, 0, 66, 0, 0, 1, 50, 23, 22, 23, 54, 51, 50, 23, 22, 21, 20, 7, 6, 7, 22, 23, 22,
+ 21, 20, 15, 1, 22, 21, 20, 7, 6, 35, 34, 39, 38, 39, 6, 3, 6, 35, 34, 39, 38, 53, 52, 55, 54, 55, 18, 55, 38, 39, 38, 53,
+ 52, 55, 54, 51, 50, 23, 54, 55, 54, 51, 50, 23, 22, 23, 54, 55, 54, 3,201, 8, 13, 14, 14, 24, 14, 12, 21, 13, 18,169,159, 66,
+116, 10, 25, 26, 3, 17, 22, 9, 21, 17, 97,104,140,180, 26, 62, 29, 4, 41, 9, 4, 22,166,185, 99, 33, 7, 15, 15, 13, 12, 19,
+ 7, 11, 14, 23, 26, 8, 44, 72,115,166, 19, 4,190, 13, 13, 22, 42, 22, 14, 17, 22, 19,183,220,161,194, 17, 9, 19, 20, 18, 10,
+ 16, 25, 13, 14, 21,125,169,182,254,208, 44, 34, 23, 50, 65, 25, 11, 34, 1, 3,216,236,127, 28, 9, 11, 21, 21, 23, 14, 9, 13,
+ 24,137,123,149,166, 20, 0, 0, 0, 1, 0, 51,255,253, 4,158, 5, 43, 0, 81, 0, 0, 1, 50, 23, 22, 23, 54, 23, 22, 23, 22,
+ 21, 20, 7, 6, 3, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 35, 34, 39, 6, 7, 6, 35, 34, 39, 38, 39, 6, 7, 6, 35, 6,
+ 39, 38, 39, 6, 35, 34, 39, 38, 53, 52, 55, 38, 39, 38, 53, 52, 55, 54, 55, 38, 39, 38, 53, 52, 55, 54, 51, 50, 23, 54, 55, 54,
+ 51, 50, 23, 22, 23, 54, 55, 54, 4, 0, 26, 23, 18, 7, 22, 9, 28, 13, 12, 14,211,206,130,129, 15, 26, 18, 32, 2, 12, 21, 28,
+ 32, 26, 7, 12, 31, 24, 20, 23, 78,106,201, 77, 15, 18, 17, 16, 13, 2, 17, 16, 22, 25, 32, 27, 8, 8, 16, 21,114,172,107, 87,
+ 19, 20, 14, 19, 23, 42, 1, 10, 20, 14, 38, 12, 92,132,202,218, 10, 5, 42, 26, 19, 51, 1, 5, 10, 12, 12, 18, 35, 14,192,254,
+239,179,142, 15, 22, 42, 23, 15, 2, 15, 30, 51, 21, 16, 9, 24, 24, 84,167,229,118, 22, 2, 33, 27, 12, 11, 26, 31, 15, 23, 40,
+ 2, 12, 21, 21, 18, 27,154,186,165,234, 53, 25, 22, 43, 28, 34, 12, 22, 44, 23,171,163,231,191, 10, 0, 0, 0, 0, 3, 0, 64,
+ 0, 5, 4,145, 4, 86, 0, 11, 0, 23, 0, 35, 0, 0, 1, 17, 33, 17, 33, 17, 33, 17, 33, 17, 33, 17, 37, 33, 17, 33, 17, 33,
+ 17, 33, 17, 33, 17, 33, 3, 33, 21, 33, 17, 35, 17, 33, 53, 33, 17, 51, 3, 11,254,187,254,197, 1, 59, 1, 69, 1, 59,255, 0,
+ 1, 74,254,182,254, 69,254,182, 1, 74, 1,187,148, 1, 74,254,182,147,254,182, 1, 74,147, 2,208, 1, 60,254,196,254,187,254,
+197, 1, 59, 1, 69, 59,254, 69,254,182, 1, 74, 1,187, 1, 75,254, 33,148,254,183, 1, 73,148, 1, 75, 0, 0, 0, 1, 0, 86,
+ 0, 7, 4,123, 4, 6, 0, 11, 0, 0, 1, 33, 17, 33, 17, 33, 17, 33, 17, 33, 17, 33, 2,247, 1,132,254,124,254,227,254,124,
+ 1,132, 1, 29, 2,143,254,238,254,139, 1,117, 1, 18, 1,118, 0, 2, 0, 57, 0, 6, 4,152, 4,102, 0, 11, 0, 15, 0, 0,
+ 1, 33, 21, 33, 17, 35, 17, 33, 53, 33, 17, 51, 3, 51, 53, 35, 2,194, 1,214,254, 42,180,254, 43, 1,213,180,179,178,178, 2,
+144,180,254, 42, 1,214,180, 1,214,253,119,178, 0, 2, 0, 48, 0, 0, 4,161, 4,114, 0, 3, 0, 15, 0, 0, 1, 33, 17, 33,
+ 37, 33, 17, 33, 17, 33, 17, 33, 17, 33, 17, 33, 1,209, 1, 47,254,209, 1, 48, 1,160,254, 96,254,207,254, 96, 1,160, 1, 49,
+ 1,161, 1, 47, 1,254,207,254, 96, 1,160, 1, 49, 1,160, 0, 0, 1, 0,155, 0, 3, 4, 41, 5, 30, 0, 11, 0, 0, 1, 33,
+ 21, 33, 17, 35, 17, 33, 53, 33, 17, 51, 2,203, 1, 94,254,162,210,254,162, 1, 94,210, 3,192,210,253, 22, 2,234,210, 1, 94,
+ 0, 2, 0,126, 0, 1, 4, 83, 5, 28, 0, 15, 0, 27, 0, 0, 1, 51, 23, 17, 33, 17, 33, 39, 17, 35, 39, 17, 33, 17, 33, 23,
+ 7, 17, 35, 17, 33, 21, 33, 17, 51, 17, 33, 53, 3, 76,131,131,254,250,254,188,131,131,132, 1, 7, 1, 68,131,175,193,254,250,
+ 1, 6,193, 1, 7, 4, 21,131,254,188,253,179,131, 1,202,131, 1, 68, 1, 7,132,218, 1, 6,254,250,193,253,179, 2, 77,193,
+ 0, 3, 0,144, 0, 4, 4, 65, 4,194, 0, 11, 0, 23, 0, 35, 0, 0, 1, 53, 33, 21, 35, 17, 51, 17, 33, 17, 51, 17, 39, 51,
+ 17, 35, 17, 33, 17, 35, 17, 51, 53, 33, 3, 51, 21, 35, 17, 35, 17, 35, 53, 51, 53, 51, 3, 6,254,197,245,245, 1, 59,245,175,
+245,245,254, 57,245,245, 1,199,140,245,245,175,245,245,175, 3,157,227,227,254,203,253,221, 2, 35, 1, 53, 65,254, 73,253,221,
+ 2, 35, 1,183,228,254,154,179,253,221, 2, 35,179,228, 0, 0, 0, 1, 0, 48, 0, 3, 4,161, 4,118, 0, 81, 0, 0, 1, 35,
+ 34, 7, 6, 7, 6, 7, 6, 21, 35, 17, 51, 20, 23, 22, 23, 22, 23, 22, 59, 1, 53, 52, 39, 38, 39, 38, 39, 38, 35, 53, 33, 21,
+ 34, 7, 6, 7, 14, 1, 29, 1, 51, 50, 55, 54, 55, 54, 55, 54, 53, 51, 17, 35, 52, 39, 38, 39, 38, 39, 38, 43, 1, 21, 20, 23,
+ 22, 23, 22, 23, 22, 51, 21, 33, 53, 50, 55, 54, 55, 62, 1, 53, 2, 47, 93, 76, 69, 68, 55, 51, 33, 28, 38, 38, 28, 31, 53, 52,
+ 71, 66, 79, 93, 28, 30, 54, 51, 72, 62, 83, 3,107, 83, 62, 72, 51, 56, 56, 93, 79, 66, 71, 52, 53, 31, 28, 38, 38, 28, 33, 51,
+ 53, 70, 69, 76, 93, 28, 30, 54, 51, 72, 62, 83,252,149, 83, 62, 72, 51, 56, 56, 2, 4, 29, 28, 56, 50, 73, 60, 85, 3,106, 84,
+ 60, 70, 54, 54, 30, 27, 93, 76, 69, 70, 54, 50, 33, 28, 38, 38, 28, 33, 50, 56,137, 76, 93, 27, 30, 54, 54, 70, 60, 84,252,150,
+ 85, 60, 73, 50, 55, 29, 29, 94, 76, 69, 70, 54, 50, 33, 28, 38, 38, 28, 33, 50, 56,137, 76, 0, 0, 8, 0, 71, 0, 2, 4,138,
+ 4,238, 0, 11, 0, 17, 0, 20, 0, 23, 0, 26, 0, 29, 0, 32, 0, 35, 0, 0, 1, 19, 33, 3, 19, 33, 11, 1, 33, 19, 3, 33,
+ 23, 7, 23, 33, 55, 47, 1, 7, 51, 31, 1, 55, 3, 7, 51, 5, 35, 23, 47, 1, 7, 19, 55, 35, 2,104,182, 1,108,182,182,254,
+148,182,182,254,149,182,182, 1,107, 48,135,135, 1, 13,135,135,135, 87,175,141, 88, 88, 88, 88,176,254,195,175, 87,228, 88, 88,
+ 88, 88,176, 4,238,254,196,254,198,254,197,254,197, 1, 59, 1, 59, 1, 58, 81,233,234,234,233,233,152, 81,152,152,254,198,153,
+ 81,152,233,153,153, 1, 59,152, 0, 1, 0, 31,255,236, 4,178, 4,127, 0, 67, 0, 0, 1, 53, 52, 39, 38, 53, 52, 55, 54, 50,
+ 23, 22, 21, 20, 7, 6, 29, 1, 51, 50, 55, 54, 51, 50, 23, 22, 20, 7, 6, 35, 34, 39, 38, 43, 1, 21, 20, 23, 22, 21, 20, 7,
+ 6, 34, 39, 38, 53, 52, 55, 54, 61, 1, 35, 34, 7, 6, 35, 34, 39, 38, 52, 55, 54, 51, 50, 23, 22, 51, 2, 67, 58, 33, 41, 42,
+ 91, 42, 41, 33, 58, 24,141, 92, 53, 89, 76, 36, 36, 36, 36, 76, 89, 53, 92,141, 24, 58, 33, 41, 42, 91, 42, 41, 33, 58, 24,141,
+ 92, 53, 89, 76, 36, 36, 36, 36, 76, 89, 53, 92,141, 2, 91, 24,141, 92, 53, 89, 76, 36, 36, 36, 36, 76, 89, 53, 92,141, 24, 58,
+ 33, 41, 42, 91, 42, 41, 33, 58, 25,141, 91, 53, 89, 76, 36, 37, 37, 36, 76, 89, 53, 91,141, 25, 58, 33, 41, 42, 91, 42, 41, 33,
+ 58, 0, 0, 0, 0, 1, 0, 28,255,239, 4,181, 4,137, 0,131, 0, 0, 1, 38, 39, 35, 6, 7, 6, 7, 14, 1, 35, 34, 38, 39,
+ 38, 39, 38, 52, 55, 54, 55, 62, 1, 51, 50, 22, 23, 22, 23, 22, 23, 51, 54, 55, 54, 55, 53, 38, 39, 38, 39, 46, 1, 53, 52, 54,
+ 55, 54, 55, 54, 50, 23, 22, 23, 30, 1, 21, 20, 6, 7, 6, 7, 6, 7, 21, 22, 23, 22, 23, 51, 54, 55, 54, 55, 62, 1, 51, 50,
+ 22, 23, 22, 23, 22, 20, 7, 6, 7, 14, 1, 35, 34, 38, 39, 38, 39, 38, 39, 35, 6, 7, 6, 7, 21, 22, 23, 22, 23, 30, 1, 21,
+ 20, 6, 7, 6, 7, 6, 34, 39, 38, 39, 46, 1, 53, 52, 54, 55, 54, 55, 54, 55, 53, 38, 2, 37, 12, 7,162, 1, 8, 15, 22, 25,
+ 62, 35, 34, 63, 24, 24, 14, 13, 13, 14, 24, 24, 63, 34, 35, 62, 25, 26, 11, 7, 2,162, 7, 12, 13, 16, 12, 15, 32, 23, 25, 26,
+ 26, 25, 25, 30, 30, 71, 30, 30, 25, 25, 26, 26, 25, 27, 28, 18, 9, 16, 13, 12, 7,162, 2, 7, 11, 26, 25, 62, 35, 34, 63, 24,
+ 24, 14, 13, 13, 14, 24, 24, 63, 34, 35, 62, 25, 22, 15, 8, 1,162, 7, 12, 13, 16, 9, 18, 28, 27, 25, 26, 26, 25, 25, 30, 30,
+ 71, 30, 30, 25, 25, 26, 26, 25, 23, 32, 15, 12, 16, 1,249, 13, 16, 12, 16, 32, 22, 26, 25, 25, 26, 24, 30, 31, 70, 30, 31, 24,
+ 25, 26, 26, 25, 26, 29, 17, 10, 16, 13, 12, 8,162, 2, 7, 15, 22, 25, 62, 35, 35, 62, 24, 24, 14, 13, 13, 14, 24, 24, 62, 35,
+ 35, 62, 25, 25, 12, 7, 2,162, 8, 12, 13, 16, 10, 17, 29, 26, 25, 26, 26, 25, 24, 31, 30, 70, 31, 30, 24, 26, 25, 25, 26, 22,
+ 32, 16, 12, 16, 13, 12, 8,161, 3, 7, 11, 26, 24, 63, 35, 34, 62, 25, 23, 14, 13, 13, 14, 23, 25, 62, 34, 35, 63, 24, 22, 15,
+ 8, 2,161, 8, 0, 1, 0, 26,255,237, 4,183, 4,138, 0,155, 0, 0, 1, 52, 39, 38, 39, 38, 39, 38, 39, 46, 1, 53, 52, 55,
+ 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 21, 50, 55, 54, 55, 54, 55,
+ 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 20, 7, 6, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 39, 38, 39, 38, 39, 38,
+ 35, 20, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55,
+ 54, 55, 54, 55, 54, 55, 54, 53, 34, 7, 6, 7, 6, 7, 6, 7, 14, 1, 35, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54,
+ 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 2, 66, 15, 18, 28, 10, 12, 19, 7, 31, 30, 15, 17, 29, 24, 44, 35, 44,
+ 43, 37, 41, 27, 29, 17, 15, 15, 17, 29, 7, 20, 6, 15, 32, 14, 15, 51, 33, 44, 25, 10, 9, 14, 8, 30, 38, 38, 42, 45, 35, 39,
+ 29, 28, 18, 16, 16, 18, 28, 29, 39, 35, 45, 42, 38, 38, 30, 8, 14, 9, 10, 31, 38, 36, 48, 15, 20, 26, 9, 13, 19, 7, 30, 16,
+ 15, 15, 17, 29, 27, 41, 36, 87, 36, 41, 27, 29, 17, 15, 15, 16, 30, 7, 19, 13, 9, 30, 16, 15, 48, 36, 39, 30, 10, 9, 14, 8,
+ 29, 76, 43, 44, 36, 38, 29, 26, 20, 17, 17, 18, 28, 29, 38, 36, 44, 47, 34, 38, 29, 8, 14, 4, 15, 31, 38, 36, 2, 98, 51, 34,
+ 41, 26, 11, 9, 14, 7, 29, 77, 42, 44, 37, 38, 29, 24, 22, 16, 16, 19, 27, 29, 38, 37, 44, 46, 34, 39, 29, 7, 14, 4, 16, 30,
+ 37, 37, 48, 15, 21, 25, 10, 12, 19, 8, 29, 16, 16, 16, 16, 29, 28, 41, 36, 87, 35, 41, 28, 29, 17, 15, 15, 16, 30, 8, 19, 12,
+ 10, 30, 16, 15, 52, 33, 44, 25, 10, 9, 14, 7, 30, 38, 38, 43, 44, 36, 39, 29, 27, 18, 16, 16, 18, 27, 29, 39, 36, 44, 43, 38,
+ 38, 30, 7, 14, 9, 10, 31, 38, 36, 49, 15, 16, 30, 11, 12, 18, 8, 30, 31, 15, 17, 29, 25, 44, 35, 44, 43, 36, 41, 28, 29, 16,
+ 16, 16, 16, 29, 8, 20, 6, 15, 31, 15, 15, 0, 0, 1, 0, 23,255,229, 4,186, 4,136, 1, 48, 0, 0, 1, 50, 23, 22, 23, 22,
+ 23, 22, 21, 20, 7, 6, 7, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 14, 1, 7, 6, 35, 34, 39, 38, 39, 38, 39,
+ 21, 51, 38, 39, 38, 39, 38, 53, 52, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 54, 55, 54, 51, 50,
+ 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 35, 34, 39, 38, 39, 22, 23, 22, 21, 20, 6, 7, 6, 7, 6, 35, 34, 39,
+ 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 35, 21, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7,
+ 6, 7, 6, 35, 34, 39, 38, 39, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 6,
+ 7, 6, 35, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 51, 50, 22, 23, 22, 23, 53, 35, 22, 23, 22, 23, 22, 21,
+ 20, 7, 6, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 6, 7, 6, 35, 34, 39, 38, 39, 38, 39, 38, 52,
+ 55, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 21, 20,
+ 7, 6, 7, 6, 7, 51, 53, 6, 7, 6, 7, 6, 35, 34, 39, 46, 1, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23,
+ 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 2,104, 23, 18, 21, 14, 15, 8, 8, 8, 8, 15, 8, 15, 19, 22, 23, 18, 20, 15, 15,
+ 8, 8, 8, 8, 31, 19, 19, 22, 23, 18, 19, 15, 11, 8,226, 13, 11, 15, 8, 9, 17, 15, 15, 20, 19, 22, 22, 19, 20, 15, 15, 8,
+ 9, 9, 6, 7, 15, 20, 19, 21, 25, 17, 19, 16, 14, 9, 8, 8, 9, 14, 17, 18, 20, 22, 21, 19, 20, 15, 7, 6, 9, 17, 15, 13,
+ 22, 19, 22, 19, 22, 20, 15, 15, 8, 9, 9, 8, 15, 11, 13,225, 7, 11, 13, 22, 18, 23, 22, 18, 20, 15, 15, 8, 8, 8, 8, 15,
+ 14, 21, 17, 23, 20, 21, 15, 9, 15, 8, 9, 9, 8, 15, 14, 21, 18, 45, 18, 21, 14, 15, 8, 9, 9, 8, 15, 9, 15, 18, 23, 23,
+ 17, 21, 14, 15, 8, 8, 8, 8, 15, 15, 20, 18, 22, 21, 40, 15, 11, 7,225, 13, 10, 17, 7, 8, 8, 8, 16, 16, 18, 20, 21, 23,
+ 19, 19, 15, 15, 9, 8, 8, 6, 8, 17, 18, 19, 22, 22, 19, 20, 15, 14, 9, 8, 8, 9, 14, 13, 22, 19, 22, 22, 19, 20, 15, 8,
+ 6, 8, 8, 9, 15, 14, 20, 19, 23, 21, 20, 19, 15, 16, 8, 8, 8, 9, 15, 10, 13,225, 8, 11, 15, 19, 18, 23, 22, 18, 20, 31,
+ 7, 9, 9, 7, 16, 14, 21, 17, 23, 23, 18, 15, 9, 16, 8, 8, 8, 8, 16, 14, 20, 18, 4,135, 8, 9, 14, 15, 20, 19, 23, 21,
+ 19, 20, 15, 7, 6, 8, 8, 9, 14, 15, 20, 19, 22, 24, 18, 19, 30, 9, 7, 7, 9, 15, 10, 13,224, 7, 11, 15, 19, 18, 23, 22,
+ 39, 15, 15, 9, 7, 7, 9, 15, 15, 20, 18, 23, 21, 20, 15, 8, 15, 8, 8, 8, 8, 15, 14, 21, 18, 22, 23, 19, 20, 14, 17, 7,
+ 7, 7, 9, 15, 9, 15, 19, 21, 20, 42, 14, 13, 10, 9, 9, 7, 16, 15, 20, 18, 23, 23, 17, 19, 16, 10, 8,225, 14, 10, 12, 11,
+ 8, 8, 9, 14, 16, 20, 19, 21, 22, 19, 20, 16, 14, 9, 8, 8, 6, 7, 14, 20, 19, 22, 22, 20, 19, 15, 15, 9, 8, 8, 9, 15,
+ 15, 19, 20, 22, 22, 19, 20, 14, 7, 6, 8, 8, 9, 14, 16, 20, 19, 22, 21, 19, 20, 16, 14, 9, 8, 17, 14, 10, 14,224, 7, 10,
+ 18, 17, 18, 23, 22, 19, 20, 14, 17, 7, 8, 8, 8, 16, 14, 20, 18, 23, 22, 19, 15, 9, 17, 7, 7, 7, 9, 15, 14, 20, 18, 46,
+ 18, 20, 15, 13, 10, 8, 8, 8, 15, 8, 15, 19, 22, 23, 18, 20, 14, 15, 9, 8, 8, 9, 15, 14, 20, 19, 22, 23, 18, 19, 15, 11,
+ 7,224, 13, 10, 15, 9, 7, 7, 9, 30, 19, 20, 22, 19, 22, 20, 15, 14, 9, 8, 8, 6, 7, 15, 20, 19, 21, 23, 19, 20, 15, 14,
+ 9, 8, 0, 0, 0, 1, 0, 43,255,231, 4,166, 4,106, 0, 31, 0, 0, 19, 50, 55, 54, 55, 54, 55, 54, 53, 20, 23, 22, 23, 22,
+ 23, 22, 51, 34, 7, 6, 7, 6, 7, 6, 21, 52, 39, 38, 39, 38, 39, 38, 43,115,105,100, 85, 83, 43, 42, 43, 39, 87, 80,105,104,
+116,116,104,105, 80, 87, 39, 43, 42, 43, 83, 85,100,105, 2, 41, 44, 41, 85, 82,104,101,120,117,104, 98, 88, 82, 44, 44, 44, 44,
+ 82, 89, 97,105,116,119,102,103, 83, 85, 41, 44, 0, 2, 0, 37,255,230, 4,172, 4,116, 0, 31, 0, 63, 0, 0, 19, 50, 23, 22,
+ 23, 22, 23, 22, 21, 52, 55, 54, 55, 54, 55, 54, 51, 34, 39, 38, 39, 38, 39, 38, 53, 20, 7, 6, 7, 6, 7, 6, 33, 50, 55, 54,
+ 55, 54, 55, 54, 53, 20, 23, 22, 23, 22, 23, 22, 51, 34, 7, 6, 7, 6, 7, 6, 21, 52, 39, 38, 39, 38, 39, 38,240, 76, 69, 65,
+ 56, 54, 29, 27, 28, 26, 58, 52, 68, 68, 77, 77, 68, 68, 52, 58, 26, 28, 27, 29, 54, 56, 65, 69,254,234,116,106,100, 86, 84, 44,
+ 42, 43, 40, 88, 81,106,104,118,118,104,106, 81, 88, 40, 43, 42, 44, 84, 86,100,106, 2, 45, 28, 28, 55, 54, 68, 67, 79, 77, 69,
+ 64, 58, 54, 29, 28, 29, 29, 54, 58, 63, 70, 76, 79, 67, 67, 54, 55, 28, 29, 45, 42, 85, 83,104,103,121,118,106, 98, 89, 83, 44,
+ 45, 44, 45, 82, 90, 98,106,118,121,103,104, 84, 85, 42, 44, 0, 0, 2, 0, 40,255,240, 4,169, 4, 56, 0, 9, 0, 19, 0, 0,
+ 19, 37, 27, 1, 5, 3, 19, 37, 5, 19, 1, 3, 33, 1, 3, 9, 1, 3, 1, 33, 41, 1,116,203,204, 1,116,245, 26,254,155,254,
+156, 26, 1, 74,135,254, 72, 1, 99,136, 1,100, 1,101,136, 1, 99,254, 72, 2,149, 93, 1, 70,254,186, 93,254,217,254,130,143,
+143, 1,126, 2,202,254, 93,254,253,254, 94, 1, 3,254,253, 1,162, 1, 3, 0, 0, 2, 0, 67,255,230, 4,142, 4, 53, 0, 9,
+ 0, 41, 0, 0, 1, 3, 33, 5, 3, 37, 5, 3, 37, 33, 3, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 35, 34,
+ 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 2,104,122,254,116, 1, 64,122, 1, 64, 1, 65,122, 1, 64,254,116,123,
+110,101, 95, 82, 80, 41, 40, 40, 38, 83, 78, 99,100,111,109,101, 95, 82, 80, 41, 40, 40, 38, 83, 77,100,100, 4, 48,254,135,233,
+254,136,233,233, 1,120,233, 1,125, 42, 40, 81, 79, 98, 98,114,108,101, 93, 84, 80, 41, 42, 42, 40, 81, 79, 98, 98,111,111,101,
+ 93, 84, 78, 43, 42, 0, 0, 0, 0, 2, 0, 40,255,230, 4,169, 4, 46, 0, 29, 0, 39, 0, 0, 0, 34, 7, 6, 7, 6, 7, 6,
+ 21, 20, 23, 22, 23, 22, 23, 22, 50, 55, 54, 55, 54, 55, 54, 53, 52, 39, 38, 39, 38, 39, 3, 19, 33, 1, 19, 9, 1, 19, 1, 33,
+ 2,152, 95, 41, 40, 34, 34, 17, 17, 17, 17, 34, 34, 40, 41, 95, 41, 40, 34, 34, 17, 17, 17, 17, 34, 34, 40, 89,136, 1,184,254,
+157,136,254,155,254,156,136,254,157, 1,184, 2,184, 17, 19, 31, 36, 40, 42, 47, 46, 42, 40, 35, 32, 19, 17, 17, 19, 32, 35, 40,
+ 42, 46, 47, 42, 40, 36, 31, 19, 1,135,254, 93,254,253,254, 94, 1, 3,254,253, 1,162, 1, 3, 0, 3, 0, 35,255,233, 4,174,
+ 4, 60, 0, 9, 0, 39, 0, 49, 0, 0, 19, 37, 27, 1, 5, 3, 19, 37, 5, 19, 0, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6,
+ 7, 6, 7, 6, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 19, 3, 33, 1, 3, 9, 1, 3, 1, 33, 35, 1,120,205,
+206, 1,120,248, 26,254,152,254,153, 26, 1, 29, 97, 41, 40, 35, 34, 17, 17, 17, 17, 34, 35, 40, 41, 97, 41, 40, 35, 34, 17, 17,
+ 17, 17, 34, 35, 40, 89,137,254, 68, 1,103,137, 1,103, 1,104,137, 1,103,254, 68, 2,149, 94, 1, 73,254,183, 94,254,214,254,
+127,144,144, 1,129, 1, 87, 17, 19, 32, 36, 40, 42, 48, 46, 43, 40, 36, 32, 19, 17, 17, 19, 32, 36, 40, 43, 46, 48, 42, 40, 36,
+ 32, 19, 1,139,254, 89,254,251,254, 90, 1, 5,254,251, 1,166, 1, 5, 0, 0, 0, 3, 0, 40,255,240, 4,169, 4, 56, 0, 9,
+ 0, 19, 0, 29, 0, 0, 1, 23, 51, 7, 23, 39, 7, 55, 39, 51, 19, 3, 33, 5, 3, 37, 5, 3, 37, 33, 3, 19, 33, 1, 19, 9,
+ 1, 19, 1, 33, 2,104, 69,219,177, 67,178,177, 67,177,219, 68,101,254,181, 1, 12,103, 1, 11, 1, 12,103, 1, 12,254,181,102,
+136, 1,184,254,157,136,254,155,254,156,136,254,157, 1,184, 3, 10,210,129,209,129,129,209,129, 1,105,254,198,194,254,198,195,
+195, 1, 58,194, 1,209,254, 93,254,253,254, 94, 1, 3,254,253, 1,162, 1, 3, 0, 3, 0, 61,255,252, 4,148, 4, 28, 0, 9,
+ 0, 19, 0, 29, 0, 0, 1, 23, 51, 7, 23, 39, 7, 55, 39, 51, 27, 1, 33, 5, 19, 37, 5, 19, 37, 33, 55, 7, 33, 23, 7, 55,
+ 23, 39, 55, 33, 2,104, 27, 84, 68, 26, 69, 68, 26, 68, 84, 26,131, 1,168,254,170,131,254,168,254,169,131,254,170, 1,168,130,
+ 78,255, 0,207, 80,207,208, 80,207,255, 0, 2, 73, 81, 50, 80, 49, 49, 80, 50, 2, 35,254,109,249,254,109,249,249, 1,147,249,
+172,243,150,243,150,150,243,150, 0, 6, 0, 40,255,246, 4,169, 4, 63, 0, 2, 0, 5, 0, 8, 0, 11, 0, 14, 0, 24, 0, 0,
+ 45, 1, 53, 37, 5, 55, 1, 3, 39, 37, 33, 7, 17, 3, 23, 17, 19, 33, 1, 19, 9, 1, 19, 1, 33, 1, 93, 1, 11,254, 80, 1,
+ 12,164, 1, 12,103,165, 1,177,254,181,102,101,101,136, 1,184,254,157,136,254,155,254,156,136,254,157, 1,184,114,194,173,140,
+194, 54,254,145, 1, 57, 54,140,140, 1,198,254,198,140, 2, 93,254, 94,254,253,254, 94, 1, 3,254,253, 1,162, 1, 3, 0, 0,
+ 0, 2, 0, 46, 0, 17, 4,163, 4, 5, 0, 13, 0, 23, 0, 0, 1, 5, 19, 47, 1, 5, 39, 19, 37, 33, 19, 23, 19, 33, 37, 3,
+ 33, 23, 3, 55, 23, 3, 55, 33, 4,162,254,196,121,114,235,254,226,114,121,254,196, 1,136,121,113,109, 1, 34,254, 0, 95,254,
+208,246, 94,247,246, 94,246,254,208, 2,108,231,254,140, 37,171,208, 37, 1,116,230, 1,117, 37,254,176,253,254,223,180,254,223,
+179,179, 1, 33,180, 0, 0, 0, 0, 1, 0, 54,255,254, 4,155, 4,130, 0, 17, 0, 0, 1, 17, 51, 17, 37, 23, 13, 1, 7, 37,
+ 17, 35, 17, 5, 39, 45, 1, 55, 1,237,247, 1, 58,124,254,198, 1, 58,124,254,198,247,254,198,124, 1, 57,254,199,124, 3, 23,
+ 1,107,254,148,182,214,181,182,214,181,254,149, 1,107,181,214,182,181,214, 0, 0, 2, 0, 87,255,255, 4,122, 4, 96, 0, 5,
+ 0, 23, 0, 0, 1, 7, 23, 51, 55, 39, 5, 37, 55, 5, 17, 23, 17, 37, 23, 13, 1, 7, 37, 17, 35, 17, 5, 39, 2, 14, 90, 90,
+180, 90, 90,254,242,254,163, 90, 1, 93,180, 1, 94, 90,254,162, 1, 94, 90,254,162,180,254,163, 90, 2,203,155,157,157,155,155,
+202,156,203, 1,148, 1,254,109,203,156,202,203,156,202,254,109, 1,147,202,156, 0, 1, 0, 48,255,253, 4,161, 4,111, 0, 23,
+ 0, 0, 9, 1, 7, 1, 17, 35, 17, 1, 39, 1, 33, 53, 33, 1, 55, 1, 17, 51, 17, 1, 23, 1, 33, 21, 2,197, 1, 80, 54,254,
+176, 77,254,176, 54, 1, 80,254, 36, 1,221,254,175, 54, 1, 80, 77, 1, 80, 54,254,175, 1,221, 2, 16,254,175, 54, 1, 82,254,
+ 35, 1,220,254,175, 54, 1, 81, 76, 1, 82, 54,254,175, 1,220,254, 36, 1, 81, 54,254,174, 76, 0, 1, 0, 36,255,240, 4,173,
+ 4,122, 0, 15, 0, 0, 1, 19, 9, 1, 13, 1, 9, 1, 11, 1, 9, 1, 45, 1, 9, 1, 2,104, 60, 1, 95,254,245, 1,181,254,
+ 75, 1, 11,254,161, 60, 59,254,161, 1, 10,254, 76, 1,180,254,246, 1, 95, 4,122,254, 75, 1, 11,254,161, 60, 59,254,160, 1,
+ 12,254, 74, 1,182,254,244, 1, 96, 59, 60, 1, 95,254,245, 0, 0, 9, 0, 26,255,233, 4,183, 4,134, 0, 2, 0, 5, 0, 8,
+ 0, 11, 0, 14, 0, 17, 0, 20, 0, 23, 0, 39, 0, 0, 1, 15, 1, 33, 39, 7, 1, 47, 1, 17, 55, 39, 1, 63, 1, 33, 23, 55,
+ 1, 31, 1, 17, 7, 23, 17, 19, 37, 3, 13, 1, 19, 37, 11, 1, 5, 19, 45, 1, 3, 5, 3,161,222, 91, 1,186,223,219, 1, 57,
+ 94,219, 91, 91,254,200,222, 90,254, 71,223,218,254,200, 94,218, 90, 90,122, 1, 39,125, 1, 42,254,214,125,254,217,122,121,254,
+217,125,254,214, 1, 42,125, 1, 39, 3,113, 94,220, 92, 92,254,200,222, 90,254, 71,223,218,254,200, 94,218, 90, 90, 1, 58,222,
+ 92, 1,187,223,220, 2, 79,254,214,125,254,216,122,121,254,217,125,254,214, 1, 42,125, 1, 39,121,122, 1, 40,125, 0, 0, 0,
+ 0, 1, 0, 50,255,228, 4,159, 5, 0, 0, 11, 0, 0, 1, 19, 37, 9, 1, 37, 11, 1, 5, 9, 1, 5, 2,104, 95, 1,216,254,
+135, 1,121,254, 40, 95, 94,254, 40, 1,122,254,134, 1,216, 4,255,254, 23,163,254,185,254,186,163,254, 21, 1,235,163, 1, 70,
+ 1, 71,163, 0, 0, 1, 0, 31,255,224, 4,178, 4,115, 0, 15, 0, 0, 1, 19, 37, 3, 13, 1, 19, 37, 11, 1, 5, 19, 45, 1,
+ 3, 5, 2,104, 86, 1, 72,207, 1,122,254,134,207,254,184, 86, 85,254,184,207,254,134, 1,122,207, 1, 72, 4,114,254,134,207,
+254,184, 86, 85,254,184,207,254,133, 1,123,207, 1, 72, 85, 86, 1, 72,207, 0, 0, 1, 0, 26,255,234, 4,183, 4,134, 0, 15,
+ 0, 0, 1, 19, 37, 3, 13, 1, 19, 37, 11, 1, 5, 19, 45, 1, 3, 5, 2,104,130, 1, 31,104, 1, 21,254,235,104,254,225,130,
+129,254,225,104,254,235, 1, 21,104, 1, 31, 4,134,254,235,104,254,225,130,130,254,225,104,254,235, 1, 21,104, 1, 31,130,130,
+ 1, 31,104, 0, 0, 1, 0, 36,255,221, 4,173, 4,104, 0, 23, 0, 0, 1, 19, 55, 3, 37, 7, 13, 1, 23, 37, 19, 39, 11, 1,
+ 7, 19, 5, 55, 45, 1, 39, 5, 3, 23, 2,104, 88,203, 53, 1, 10,180, 1, 1,254,255,180,254,246, 53,203, 88, 86,204, 54,254,
+245,179,255, 0, 1, 0,179, 1, 11, 54,204, 4,103,254,255,179,254,246, 53,203, 86, 87,204, 54,254,246,179,254,255, 1, 1,179,
+ 1, 10, 54,204, 87, 86,203, 53, 1, 10,179, 0, 0, 1, 0, 48, 0, 2, 4,161, 4,116, 0, 47, 0, 0, 1, 17, 51, 17, 19, 23,
+ 3, 55, 23, 7, 37, 23, 5, 33, 21, 33, 5, 7, 37, 23, 7, 39, 19, 7, 3, 17, 35, 17, 3, 39, 19, 7, 39, 55, 5, 39, 37, 33,
+ 53, 33, 37, 55, 5, 39, 55, 23, 3, 55, 2, 59, 91,130, 84,129,239, 65,240, 1, 58, 35,254,197, 1, 84,254,175, 1, 56, 35,254,
+198,240, 65,238,128, 84,130, 91,130, 84,129,239, 65,240,254,198, 35, 1, 57,254,174, 1, 84,254,197, 35, 1, 56,238, 65,238,128,
+ 84, 3, 32, 1, 84,254,174, 1, 56, 35,254,199,240, 65,240,130, 84,131, 91,129, 85,131,241, 64,238,254,200, 35, 1, 55,254,175,
+ 1, 83,254,199, 35, 1, 57,239, 64,239,129, 85,129, 91,131, 84,129,239, 65,239, 1, 56, 35, 0, 0, 1, 0, 49,255,240, 4,160,
+ 4,232, 0,159, 0, 0, 1, 53, 52, 39, 38, 53, 52, 55, 54, 50, 23, 22, 21, 20, 7, 6, 29, 1, 23, 22, 23, 55, 54, 55, 54, 55,
+ 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 35, 34, 35, 34, 15, 1, 22, 21, 20, 7, 23, 22, 51, 50, 55, 50, 51,
+ 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 47, 1, 6, 15, 1, 21, 20, 23, 22, 21, 20, 7, 6, 34, 39,
+ 38, 53, 52, 55, 54, 61, 1, 38, 39, 38, 39, 7, 6, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 51, 50, 51,
+ 22, 51, 50, 63, 1, 38, 53, 52, 55, 39, 38, 35, 34, 35, 34, 35, 34, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23,
+ 22, 31, 1, 54, 55, 54, 2, 63, 62, 36, 44, 46, 99, 46, 44, 36, 62, 13, 25, 20, 8, 93, 53, 32, 55, 49, 43, 18, 17, 58, 25, 16,
+ 4, 11, 72, 51, 62, 5, 5, 8, 9,107, 82, 10, 3, 4, 10, 83,107, 9, 8, 5, 5, 62, 51, 72, 11, 4, 16, 25, 58, 17, 18, 43,
+ 49, 55, 32, 55, 90, 12, 22, 20, 13, 62, 36, 44, 46, 99, 46, 44, 36, 63, 7, 7, 23, 19, 12, 90, 55, 32, 55, 49, 43, 18, 17, 58,
+ 25, 16, 4, 11, 72, 51, 62, 5, 5, 8, 9,108, 82, 10, 4, 3, 10, 82,107, 9, 8, 5, 5, 62, 51, 72, 11, 4, 16, 25, 58, 17,
+ 18, 43, 49, 55, 32, 57, 88, 9, 22, 23, 7, 2,248, 10,105, 98, 57, 64, 82, 39, 41, 41, 39, 82, 64, 57,100,103, 10, 5, 11, 19,
+ 5, 56,100, 60, 32, 28, 5, 20, 43, 28, 36, 18, 20, 59, 41, 29, 48, 5, 16, 16, 18, 16, 6, 49, 1, 30, 41, 58, 20, 18, 36, 29,
+ 42, 20, 5, 28, 32, 60,103, 52, 7, 21, 7, 5, 13,104, 99, 57, 64, 82, 40, 40, 40, 40, 82, 64, 57, 99,104, 13, 2, 3, 10, 18,
+ 7, 52,103, 60, 32, 28, 5, 20, 42, 29, 36, 18, 20, 58, 41, 30, 1, 48, 6, 16, 19, 16, 16, 5, 48, 29, 41, 59, 20, 18, 36, 28,
+ 43, 20, 5, 28, 32, 60,107, 48, 5, 20, 9, 3, 0, 2, 0, 55,255,238, 4,154, 4,217, 0, 29, 0,185, 0, 0, 0, 34, 7, 6,
+ 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 23, 22, 50, 55, 54, 55, 54, 55, 54, 53, 52, 39, 38, 39, 38, 47, 1, 53, 52, 39, 38, 53,
+ 52, 55, 54, 50, 23, 22, 21, 20, 7, 6, 29, 1, 23, 22, 23, 55, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7,
+ 6, 43, 1, 34, 35, 34, 15, 1, 22, 21, 20, 7, 23, 22, 51, 50, 59, 1, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39,
+ 38, 39, 38, 47, 1, 6, 15, 1, 21, 20, 23, 22, 21, 20, 7, 6, 34, 39, 38, 53, 52, 55, 54, 61, 1, 38, 39, 38, 39, 7, 6, 7,
+ 6, 7, 6, 35, 34, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 59, 1, 50, 51, 50, 63, 1, 38, 53, 52, 55, 39, 38, 35, 34, 43, 1,
+ 34, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 31, 1, 54, 55, 54, 2,122, 35, 13, 15, 11, 13, 5, 7, 7,
+ 5, 13, 11, 15, 13, 35, 13, 15, 11, 13, 5, 7, 7, 5, 13, 11, 15, 72, 61, 36, 44, 46, 97, 46, 44, 36, 62, 13, 25, 20, 8, 92,
+ 53, 31, 55, 48, 43, 18, 17, 57, 25, 16, 4, 12, 70, 51, 61, 10, 9, 8,107, 81, 10, 4, 4, 9, 83,106, 9, 8, 10, 61, 51, 70,
+ 12, 4, 16, 25, 57, 17, 18, 43, 48, 55, 31, 55, 89, 12, 22, 20, 13, 62, 36, 44, 46, 97, 46, 44, 36, 63, 8, 6, 24, 18, 12, 89,
+ 55, 31, 55, 48, 43, 18, 17, 57, 25, 16, 4, 11, 71, 51, 61, 10, 9, 8,107, 82, 9, 4, 4, 10, 81,107, 8, 9, 10, 61, 51, 71,
+ 11, 4, 16, 25, 57, 17, 18, 43, 48, 55, 31, 57, 87, 9, 21, 24, 6, 2,183, 7, 6, 12, 12, 14, 14, 17, 17, 14, 14, 12, 12, 6,
+ 7, 7, 6, 12, 12, 14, 14, 17, 17, 14, 14, 12, 12, 6, 62, 10,104, 96, 57, 64, 81, 39, 40, 40, 39, 81, 64, 57, 98,102, 10, 5,
+ 11, 19, 5, 55, 99, 60, 31, 29, 6, 19, 43, 28, 36, 18, 19, 58, 41, 29, 47, 6, 15, 16, 17, 17, 5, 48, 30, 40, 58, 19, 18, 36,
+ 28, 43, 19, 6, 29, 31, 60,102, 51, 7, 21, 7, 5, 12,103, 99, 56, 64, 81, 39, 40, 40, 39, 81, 64, 56, 99,103, 12, 3, 2, 11,
+ 17, 7, 51,102, 60, 31, 29, 6, 19, 43, 28, 36, 18, 19, 58, 40, 30, 47, 6, 16, 18, 16, 15, 6, 47, 29, 41, 58, 19, 18, 36, 28,
+ 43, 19, 6, 29, 31, 60,105, 48, 5, 20, 9, 3, 0, 1, 0, 43,255,235, 4,159, 4,223, 0,106, 0, 0, 1, 39, 38, 7, 6, 39,
+ 38, 39, 38, 55, 54, 55, 54, 23, 22, 23, 22, 31, 1, 53, 52, 39, 38, 53, 52, 55, 54, 50, 23, 22, 21, 20, 7, 6, 29, 1, 55, 54,
+ 55, 54, 55, 54, 23, 22, 23, 22, 7, 6, 7, 6, 39, 38, 15, 1, 23, 22, 55, 54, 23, 22, 23, 22, 7, 6, 7, 6, 39, 38, 39, 38,
+ 47, 1, 21, 20, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 53, 52, 55, 54, 61, 1, 7, 6, 7, 6, 7, 6, 39, 38, 39, 38, 55, 54,
+ 55, 54, 23, 22, 55, 2, 18, 38, 40,151, 90, 68, 76, 14, 23, 34, 35, 90, 58, 76, 71, 35, 58, 46, 39, 87, 52, 44, 67,138, 67, 44,
+ 52, 87, 39, 39, 65, 40, 67, 75, 59, 90, 34, 34, 23, 14, 76, 71, 87,144, 47, 39, 39, 39,152, 91, 67, 76, 14, 23, 34, 36, 88, 62,
+ 72, 72, 35, 58, 46, 39, 87, 52, 44, 67, 69, 72, 64, 44, 52, 87, 39, 42, 62, 38, 68, 76, 58, 90, 35, 35, 24, 15, 75, 71, 87,147,
+ 44, 2,102, 22, 23, 13, 8, 39, 44, 59, 91, 59, 59, 26, 17, 43, 42, 81,132, 27, 23, 45, 45,125, 75, 79, 87, 42, 65, 65, 42, 87,
+ 83, 71,117, 53, 45, 23, 23,136, 85, 38, 43, 17, 26, 59, 59, 91, 59, 44, 41, 10, 16, 26, 22, 23, 23, 13, 7, 39, 43, 59, 91, 60,
+ 62, 23, 16, 42, 42, 81,133, 27, 22, 45, 45,125, 75, 78, 87, 43, 64, 64, 45, 85, 83, 70,117, 53, 45, 22, 25,135, 83, 40, 43, 17,
+ 26, 59, 62, 89, 59, 43, 42, 10, 16, 26, 0, 0, 0, 4, 0, 33,255,229, 4,176, 4,189, 0, 14, 0,153, 0,177, 0,201, 0, 0,
+ 1, 54, 55, 54, 53, 52, 39, 38, 34, 7, 6, 21, 20, 23, 22, 19, 23, 22, 51, 50, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6,
+ 7, 6, 35, 34, 39, 38, 39, 38, 47, 1, 21, 20, 23, 22, 21, 20, 7, 6, 35, 34, 39, 38, 53, 52, 55, 54, 61, 1, 7, 6, 7, 6,
+ 7, 6, 35, 34, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 51, 50, 23, 22, 51, 50, 63, 1, 39, 38, 35, 34, 7, 6, 35, 34, 39, 38,
+ 39, 38, 53, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 31, 1, 53, 52, 39, 38, 53, 52, 55, 54, 50, 23, 22, 21, 20, 7, 6, 29,
+ 1, 55, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 35, 34, 7, 5, 6, 35, 34, 39, 38,
+ 35, 34, 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 51, 50, 55, 54, 55, 54, 37, 22, 23, 22, 23, 22, 51, 50, 55, 54, 55, 54, 53, 52,
+ 39, 38, 39, 38, 35, 34, 7, 6, 35, 34, 2,105, 23, 47, 31, 25, 41, 70, 41, 26, 31, 47,141, 15, 44, 85, 27, 31, 15, 14, 75, 58,
+ 77, 15, 10, 21, 36, 92, 16, 18, 47, 56, 69, 40, 53, 62, 15, 72, 54, 45, 69, 70, 74, 65, 45, 53, 72, 15, 59, 56, 41, 68, 55, 46,
+ 19, 17, 92, 35, 21, 9, 16, 76, 59, 75, 14, 15, 30, 27, 85, 44, 16, 16, 42, 85, 28, 31, 15, 14, 75, 59, 75, 17, 10, 22, 35, 92,
+ 17, 19, 46, 55, 70, 39, 53, 62, 15, 72, 53, 45, 68,141, 69, 45, 54, 72, 15, 60, 55, 42, 67, 56, 47, 18, 16, 92, 36, 21, 10, 15,
+ 77, 58, 75, 14, 15, 32, 27, 85, 43,254,211, 58, 54, 25, 24, 8, 8, 45, 50, 49, 6, 4, 11, 17, 52, 9, 10, 26, 36, 58, 21, 30,
+ 1,143, 60, 30, 21, 59, 36, 26, 10, 8, 52, 18, 11, 4, 6, 50, 50, 45, 8, 7, 25, 25, 54, 3, 12, 79, 59, 40, 65, 55, 20, 35,
+ 35, 20, 55, 65, 40, 59,254,247, 9, 26, 3, 1, 33, 42, 58, 35, 31, 46, 35, 59, 24, 4, 30, 38, 82,109, 33, 8, 16, 67, 99, 74,
+ 77, 85, 41, 63, 63, 44, 82, 77, 74, 99, 67, 16, 8, 31,111, 83, 37, 31, 5, 26, 57, 35, 46, 31, 35, 59, 41, 33, 1, 3, 26, 9,
+ 8, 25, 2, 1, 32, 41, 59, 35, 31, 45, 36, 58, 25, 5, 30, 39, 81,110, 33, 8, 16, 68, 99, 73, 77, 85, 42, 63, 63, 42, 85, 77,
+ 73, 99, 68, 16, 8, 32,111, 83, 37, 30, 5, 24, 59, 35, 46, 30, 36, 58, 42, 32, 1, 2, 25,102, 14, 3, 1, 28, 27, 31, 20, 16,
+ 27, 18, 29, 16, 3, 19, 32, 47, 68, 59, 59, 68, 47, 32, 19, 3, 16, 29, 18, 27, 16, 20, 31, 27, 28, 1, 3, 0, 0, 2, 0, 36,
+ 0, 0, 4,173, 4,105, 0, 29, 0,141, 0, 0, 0, 34, 7, 6, 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 23, 22, 50, 55, 54, 55,
+ 54, 55, 54, 53, 52, 39, 38, 39, 38, 39, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 35, 34,
+ 39, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 39, 38, 39, 6, 7, 6, 7, 6, 7, 6, 35, 34,
+ 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 6, 35, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 51, 50,
+ 23, 22, 23, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 2,160,111, 48, 48, 39,
+ 41, 19, 20, 20, 19, 41, 39, 48, 48,111, 48, 48, 39, 41, 19, 20, 20, 19, 41, 39, 48, 93, 48, 29, 43, 41, 42, 43, 37, 35, 32, 18,
+ 16, 16, 15, 35, 29, 43, 37, 48, 22, 21, 37, 26, 35, 14, 17, 17, 18, 31, 35, 38, 38, 46, 48, 37, 43, 29, 37, 13, 10, 4, 3, 11,
+ 18, 32, 35, 37, 39, 46, 48, 36, 44, 28, 35, 15, 16, 16, 19, 31, 29, 28, 18, 19, 48, 37, 45, 27, 35, 15, 16, 16, 18, 32, 35, 37,
+ 39, 46, 48, 36, 46, 32, 6, 5, 16, 16, 18, 32, 35, 37, 39, 45, 49, 36, 44, 28, 35, 15, 16, 16, 5, 3, 36, 20, 22, 37, 42, 47,
+ 48, 57, 54, 49, 47, 42, 37, 22, 20, 20, 22, 37, 42, 47, 49, 54, 57, 48, 47, 42, 37, 22, 15, 41, 12, 18, 18, 15, 34, 30, 42, 38,
+ 48, 45, 40, 37, 36, 29, 19, 17, 4, 18, 26, 36, 36, 41, 45, 48, 38, 42, 30, 33, 16, 16, 16, 20, 29, 38, 34, 27, 28, 29, 26, 42,
+ 30, 33, 16, 16, 16, 20, 29, 36, 36, 41, 45, 48, 38, 45, 27, 26, 17, 4, 17, 21, 28, 35, 37, 40, 45, 48, 38, 42, 30, 34, 15, 17,
+ 17, 19, 34, 11, 11, 40, 45, 48, 38, 42, 30, 34, 15, 16, 16, 19, 30, 36, 36, 40, 46, 47, 38, 11, 0, 6, 0, 22, 0, 3, 4,187,
+ 4,134, 0,110, 0,138, 0,163, 0,191, 0,216, 0,244, 0, 0, 37, 6, 7, 6, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 39, 38,
+ 53, 52, 55, 54, 55, 54, 55, 6, 35, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 38, 39, 38,
+ 53, 52, 55, 54, 55, 54, 55, 54, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 21,
+ 20, 7, 6, 7, 6, 7, 6, 35, 34, 39, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 39, 38, 2,
+ 50, 23, 22, 23, 55, 54, 53, 52, 39, 38, 39, 38, 39, 38, 34, 7, 6, 7, 6, 7, 6, 21, 20, 31, 1, 54, 55, 19, 38, 39, 38, 39,
+ 38, 39, 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 23, 22, 50, 55, 54, 55, 54, 55, 3, 38, 53, 52, 55, 54, 55, 39, 38, 39, 38, 35,
+ 34, 7, 6, 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 23, 22, 23, 5, 23, 22, 23, 22, 23, 22, 50, 55, 54, 55, 54, 55, 54, 53, 52,
+ 39, 38, 47, 1, 6, 7, 6, 7, 6, 63, 1, 54, 55, 54, 55, 54, 55, 54, 53, 52, 39, 38, 39, 38, 39, 38, 35, 34, 7, 6, 15, 1,
+ 22, 23, 22, 21, 20, 2,104, 3, 11, 13, 38, 29, 44, 38, 49, 47, 40, 38, 35, 33, 18, 17, 17, 15, 36, 26, 38, 22, 23, 49, 37, 45,
+ 29, 36, 15, 17, 17, 18, 33, 38, 36, 47, 39, 46, 41, 29, 50, 6, 5, 16, 16, 15, 36, 29, 45, 37, 99, 37, 45, 29, 36, 15, 16, 16,
+ 5, 6, 50, 29, 45, 42, 43, 43, 38, 36, 33, 18, 17, 17, 15, 36, 29, 45, 37, 49, 23, 22, 38, 26, 36, 15, 17, 17, 18, 33, 35, 38,
+ 40, 47, 49, 38, 44, 29, 38, 13, 11, 61,115, 48, 6, 6, 14, 7, 10, 9, 22, 20, 25, 24, 57, 24, 25, 20, 22, 9, 10, 7, 14, 6,
+ 6, 53, 28, 25, 53, 37, 24, 21, 82, 19, 12, 10, 10, 10, 21, 20, 25, 24, 57, 24, 26, 19, 19, 12,178, 3, 21, 17, 33, 95, 7, 5,
+ 28, 25, 28, 24, 25, 20, 19, 12, 11, 11, 9, 22, 20, 25, 17, 12, 1,186, 44, 12, 19, 19, 26, 24, 57, 24, 25, 20, 21, 10, 10, 10,
+ 12, 19, 82, 21, 24, 37, 53, 25,194,115, 12, 17, 25, 20, 22, 9, 11, 11, 12, 19, 20, 25, 24, 28, 25, 28, 5, 7, 95, 33, 17, 21,
+200, 29, 27, 35, 39, 30, 20, 17, 17, 16, 34, 31, 43, 39, 48, 47, 41, 38, 36, 27, 19, 4, 16, 20, 30, 37, 37, 41, 46, 50, 39, 43,
+ 31, 36, 14, 18, 18, 13, 42, 10, 11, 39, 49, 46, 42, 37, 37, 30, 20, 16, 16, 20, 30, 37, 37, 42, 46, 49, 39, 11, 10, 42, 13, 18,
+ 18, 16, 34, 31, 43, 39, 50, 46, 41, 37, 37, 30, 20, 16, 4, 19, 27, 36, 38, 41, 47, 48, 39, 43, 31, 34, 16, 17, 17, 20, 30, 39,
+ 35, 27, 2,142, 20, 3, 3, 76, 37, 16, 28, 26, 24, 21, 19, 11, 11, 11, 11, 19, 21, 24, 26, 28, 16, 37, 76, 3, 3,253,236, 5,
+ 11, 24, 37, 23, 35, 77, 19, 27, 25, 29, 28, 25, 24, 21, 19, 11, 11, 11, 11, 19, 19, 26, 1, 76, 17, 19, 58, 50, 40, 38, 54, 3,
+ 2, 10, 10, 11, 19, 19, 26, 23, 31, 28, 26, 23, 22, 19, 11, 7, 2,251, 95, 26, 19, 19, 11, 11, 11, 11, 19, 21, 24, 25, 28, 29,
+ 25, 27, 19, 77, 35, 23, 37, 24, 11,232, 14, 2, 7, 11, 19, 22, 23, 26, 28, 31, 23, 26, 19, 19, 11, 10, 10, 2, 3, 54, 38, 40,
+ 50, 58, 19, 0, 0, 10, 0, 22,255,237, 4,187, 4,148, 0, 45, 0, 91, 0,213, 1, 4, 1, 51, 1, 98, 1,145, 1,175, 1,221,
+ 2, 11, 0, 0, 1, 38, 39, 7, 6, 35, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 51, 50, 31, 1, 54, 55, 39,
+ 38, 35, 34, 6, 7, 6, 7, 6, 20, 23, 22, 23, 22, 23, 22, 51, 50, 55, 37, 6, 7, 23, 22, 51, 50, 55, 54, 55, 54, 55, 54, 52,
+ 39, 38, 39, 46, 1, 35, 34, 15, 1, 22, 23, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 35, 34, 39,
+ 37, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 52, 54, 55, 54, 55, 54, 50, 23, 22, 23, 30, 1, 21, 54, 55,
+ 54, 51, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 35, 22, 23,
+ 22, 21, 20, 7, 6, 7, 6, 7, 6, 35, 34, 39, 38, 39, 20, 6, 7, 6, 7, 6, 34, 39, 38, 39, 46, 1, 53, 6, 7, 6, 35, 34,
+ 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 1, 38, 39, 7, 6, 7,
+ 6, 7, 6, 7, 38, 39, 38, 39, 38, 39, 38, 39, 54, 55, 54, 55, 54, 63, 1, 38, 39, 7, 6, 7, 6, 7, 6, 21, 22, 23, 22, 23,
+ 30, 1, 51, 50, 55, 54, 55, 54, 55, 1, 22, 23, 55, 54, 55, 54, 55, 54, 53, 38, 39, 38, 39, 46, 1, 35, 34, 7, 6, 7, 6, 15,
+ 1, 22, 23, 55, 54, 55, 54, 55, 54, 55, 22, 23, 22, 23, 22, 23, 22, 23, 6, 7, 6, 7, 6, 7, 3, 6, 7, 23, 22, 23, 22, 23,
+ 22, 23, 6, 7, 6, 7, 6, 7, 6, 7, 38, 39, 38, 39, 38, 47, 1, 6, 7, 23, 22, 23, 22, 23, 22, 51, 50, 54, 55, 54, 55, 54,
+ 55, 52, 39, 38, 39, 38, 39, 1, 54, 55, 39, 38, 39, 38, 39, 38, 35, 34, 6, 7, 6, 7, 6, 7, 20, 23, 22, 23, 22, 31, 1, 54,
+ 55, 39, 38, 39, 38, 39, 38, 39, 54, 55, 54, 55, 54, 55, 54, 55, 22, 23, 22, 23, 22, 23, 4, 34, 7, 6, 7, 6, 7, 6, 21, 20,
+ 23, 22, 23, 22, 23, 22, 50, 55, 54, 55, 54, 55, 54, 53, 52, 39, 38, 39, 38, 39, 19, 6, 7, 23, 22, 21, 20, 7, 6, 7, 6, 7,
+ 6, 34, 39, 38, 39, 38, 39, 38, 53, 52, 63, 1, 38, 39, 7, 6, 21, 20, 23, 22, 23, 22, 23, 22, 50, 55, 54, 55, 54, 55, 54, 53,
+ 52, 39, 3, 22, 23, 55, 54, 53, 52, 39, 38, 39, 38, 39, 38, 34, 7, 6, 7, 6, 7, 6, 21, 20, 31, 1, 54, 55, 39, 38, 53, 52,
+ 55, 54, 55, 54, 55, 54, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 1,139, 4, 2,175, 13, 7, 7, 11, 9, 8, 6, 5, 3, 3, 5,
+ 6, 8, 9, 9, 9, 7, 13,175, 2, 4,158, 27, 16, 21, 40, 17, 15, 10, 7, 7, 10, 15, 17, 20, 20, 21, 16, 27, 2, 98, 2, 4,
+155, 27, 14, 23, 20, 20, 17, 15, 10, 7, 7, 10, 15, 17, 40, 23, 14, 27,155, 4, 2,172, 13, 5, 13, 7, 9, 8, 6, 5, 3, 3,
+ 5, 6, 9, 8, 11, 9, 5, 13,252,205, 28, 13, 13, 13, 12, 25, 25, 31, 31, 35, 33, 34, 31, 28, 26, 25, 25, 30, 31, 71, 31, 30,
+ 25, 25, 26, 30, 29, 34, 33, 35, 31, 31, 25, 22, 15, 13, 13, 11, 30, 42, 30, 29, 26, 27, 11, 13, 13, 13, 25, 21, 34, 32, 39, 29,
+ 11, 13, 13, 12, 25, 25, 31, 31, 35, 35, 32, 31, 28, 26, 25, 25, 30, 31, 71, 31, 30, 25, 25, 26, 31, 28, 33, 34, 34, 32, 31, 25,
+ 25, 12, 13, 13, 13, 27, 39, 32, 29, 26, 27, 12, 12, 12, 14, 25, 26, 29, 30, 1, 89, 15, 13,109, 8, 5, 5, 10, 9, 11, 10, 9,
+ 9, 7, 7, 4, 3, 1, 1, 4, 3, 7, 4, 11,138, 11, 8,141, 26, 10, 17, 7, 9, 1, 8, 7, 17, 16, 40, 22, 24, 19, 20, 16,
+ 11, 14, 1,121, 12, 7,139, 26, 10, 17, 7, 9, 1, 8, 7, 17, 16, 40, 22, 24, 19, 20, 17, 10, 14, 79, 15, 13,107, 8, 4, 8,
+ 8, 9, 11, 10, 9, 9, 7, 7, 4, 3, 1, 1, 4, 4, 6, 4, 11,119, 8, 11,138, 11, 4, 6, 4, 4, 1, 1, 3, 4, 7, 7,
+ 9, 9, 10, 11, 9, 8, 7, 5, 8,109, 13, 15, 81, 14, 11, 16, 20, 19, 24, 22, 40, 16, 17, 7, 8, 1, 9, 7, 17, 10, 26,254,
+ 28, 14, 14, 79, 14, 10, 17, 20, 19, 24, 22, 40, 16, 17, 7, 8, 1, 9, 7, 17, 10, 26,139, 8, 11,136, 11, 4, 7, 3, 4, 1,
+ 1, 3, 4, 7, 7, 9, 9, 10, 13, 7, 10, 6, 4, 8, 1, 26, 63, 27, 27, 23, 22, 12, 11, 11, 12, 22, 23, 27, 27, 63, 27, 27,
+ 23, 22, 12, 11, 11, 12, 22, 23, 27, 2, 17, 16, 21, 1, 3, 4, 7, 8, 8, 10, 19, 10, 8, 8, 7, 4, 3, 1, 21, 17, 16, 43,
+ 8, 9, 7, 17, 16, 20, 19, 47, 19, 20, 16, 17, 7, 9, 8, 76, 18, 16, 42, 8, 9, 7, 17, 16, 20, 19, 47, 19, 20, 16, 17, 7,
+ 9, 8, 42, 17, 17, 21, 1, 3, 4, 7, 8, 8, 10, 19, 10, 8, 8, 8, 3, 3, 1, 2, 3, 17, 17, 21, 2, 5, 3, 7, 8, 8,
+ 9, 11, 9, 9, 9, 8, 6, 5, 3, 2, 20, 17, 16, 43, 7, 15, 17, 17, 20, 18, 46, 20, 20, 16, 16, 8, 9, 7, 77, 18, 16, 43,
+ 7, 9, 8, 16, 16, 20, 20, 46, 18, 20, 17, 17, 15, 7, 42, 17, 17, 20, 2, 3, 5, 6, 8, 9, 9, 9, 11, 9, 8, 8, 9, 1,
+ 5, 2,221, 28, 32, 33, 33, 33, 33, 31, 25, 25, 12, 13, 13, 13, 27, 39, 63, 24, 24, 14, 13, 13, 14, 24, 24, 63, 39, 29, 11, 13,
+ 13, 12, 25, 22, 34, 31, 35, 28, 38, 31, 29, 13, 12, 26, 27, 28, 31, 35, 39, 27, 31, 25, 23, 15, 14, 29, 30, 34, 33, 33, 32, 31,
+ 25, 25, 13, 12, 12, 13, 28, 39, 63, 25, 23, 14, 13, 13, 14, 23, 25, 63, 39, 30, 11, 12, 12, 13, 25, 25, 31, 32, 33, 34, 33, 32,
+ 27, 14, 12, 26, 27, 29, 30, 36, 38, 28, 31, 24, 26, 12, 13,254,140, 9, 10,139, 10, 4, 6, 4, 4, 1, 1, 3, 4, 7, 7, 9,
+ 9, 10, 10, 9, 10, 6, 5, 8,109, 13, 14, 80, 15, 11, 15, 20, 19, 24, 22, 21, 19, 17, 16, 15, 7, 9, 15, 11, 25, 1,229, 13,
+ 15, 79, 15, 10, 16, 20, 19, 24, 22, 21, 19, 17, 16, 15, 7, 9, 16, 10, 25,139, 9, 11,136, 10, 4, 9, 2, 4, 1, 1, 3, 4,
+ 7, 7, 9, 9, 10, 13, 6, 10, 7, 4, 8,254,147, 14, 13,109, 8, 5, 6, 10, 9, 10, 10, 9, 9, 7, 7, 4, 3, 1, 1, 4,
+ 3, 7, 4, 10,139, 11, 8,142, 25, 11, 15, 9, 7, 15, 16, 17, 19, 21, 22, 24, 19, 20, 15, 11, 15, 1,121, 11, 9,139, 25, 10,
+ 16, 9, 7, 15, 16, 17, 19, 21, 22, 24, 19, 20, 16, 10, 15, 79, 15, 13,107, 8, 4, 8, 9, 9, 10, 10, 9, 9, 7, 7, 4, 3,
+ 1, 1, 4, 4, 7, 4, 10,163, 12, 12, 21, 24, 26, 28, 31, 31, 28, 27, 23, 21, 12, 12, 12, 12, 21, 23, 27, 28, 31, 31, 28, 26,
+ 24, 21, 12,254,147, 5, 1,175, 13, 7, 8, 10, 9, 8, 7, 4, 3, 3, 4, 7, 8, 9, 9, 9, 7, 13,175, 1, 5,158, 28, 15,
+ 22, 20, 19, 17, 15, 9, 9, 9, 9, 15, 17, 19, 20, 22, 15, 28, 2, 98, 1, 5,154, 29, 14, 23, 20, 19, 17, 15, 9, 9, 9, 9,
+ 15, 17, 19, 20, 23, 14, 29,154, 5, 1,172, 13, 6, 11, 8, 9, 8, 7, 3, 4, 4, 3, 7, 10, 7, 10, 9, 6, 13, 0, 0, 0,
+ 0, 4, 0, 37,255,223, 4,172, 4,106, 0, 29, 0, 60, 0, 92, 0,108, 0, 0, 0, 34, 7, 6, 7, 6, 7, 6, 21, 20, 23, 22,
+ 23, 22, 23, 22, 50, 55, 54, 55, 54, 55, 54, 53, 52, 39, 38, 39, 38, 47, 1, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6,
+ 7, 6, 35, 34, 39, 38, 39, 38, 39, 38, 52, 55, 54, 55, 54, 55, 54, 19, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7,
+ 6, 35, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 23, 3, 37, 19, 13, 1, 3, 37, 27, 1, 5, 3, 45, 1, 19,
+ 5, 2,150, 91, 39, 39, 33, 32, 16, 16, 16, 16, 32, 33, 39, 39, 91, 38, 40, 32, 33, 16, 16, 16, 16, 33, 32, 40, 84, 66, 51, 57,
+ 41, 43, 24, 23, 23, 23, 44, 43, 55, 54, 63, 65, 51, 58, 40, 43, 24, 23, 23, 23, 44, 43, 55, 54, 62,116,106,101, 86, 84, 44, 43,
+ 43, 40, 88, 82,105,105,117,115,107,100, 86, 84, 44, 42, 42, 40, 88, 81,105,106,116,117,254,223,122,254,222, 1, 34,122, 1, 33,
+117,118, 1, 33,122, 1, 34,254,222,122,254,223, 3, 4, 17, 18, 30, 35, 38, 40, 44, 45, 39, 39, 34, 30, 18, 17, 17, 18, 30, 34,
+ 39, 39, 45, 44, 40, 38, 35, 30, 18,101, 24, 25, 41, 42, 58, 54, 63, 59, 57, 55, 44, 43, 23, 24, 24, 25, 41, 42, 57, 55,122, 56,
+ 56, 44, 43, 23, 24, 1, 17, 44, 42, 85, 84,104,103,121,114,105, 99, 89, 84, 43, 44, 44, 42, 85, 83,105,103,116,118,106, 98, 90,
+ 82, 45, 44, 6,254,222,122,254,223,118,118,254,224,122,254,222, 1, 34,122, 1, 32,118,118, 1, 33,122, 0, 0, 0, 7, 0, 50,
+255,237, 4,159, 5, 57, 0, 8, 0,147, 0,156, 0,167, 0,178, 0,193, 0,208, 0, 0, 1, 17, 34, 7, 6, 21, 20, 23, 22, 19,
+ 23, 22, 51, 50, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 47, 1, 21, 20, 23, 22, 21, 20,
+ 7, 6, 35, 34, 39, 38, 53, 52, 55, 54, 61, 1, 7, 6, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 51, 50,
+ 23, 22, 51, 50, 63, 1, 39, 38, 35, 34, 7, 6, 35, 34, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 31, 1,
+ 53, 52, 39, 38, 53, 52, 55, 54, 50, 23, 22, 21, 20, 7, 6, 29, 1, 55, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7,
+ 6, 7, 6, 35, 34, 39, 38, 35, 34, 15, 1, 17, 50, 55, 54, 53, 52, 39, 38, 19, 37, 38, 39, 38, 35, 34, 7, 6, 7, 6, 1, 5,
+ 22, 23, 22, 51, 50, 55, 54, 55, 54, 19, 37, 6, 21, 20, 23, 22, 23, 22, 51, 50, 55, 54, 51, 50, 13, 1, 54, 53, 52, 39, 38, 39,
+ 38, 35, 34, 7, 6, 35, 34, 2,105, 34, 40, 25, 31, 45,137, 14, 43, 83, 25, 30, 15, 13, 73, 57, 75, 14, 9, 20, 35, 89, 16, 17,
+ 46, 54, 67, 38, 52, 60, 14, 70, 52, 44, 67, 68, 72, 63, 44, 52, 70, 15, 57, 54, 40, 66, 53, 45, 18, 17, 89, 34, 21, 9, 15, 75,
+ 56, 73, 14, 14, 30, 26, 83, 42, 15, 15, 41, 82, 27, 31, 14, 14, 73, 56, 74, 16, 9, 21, 34, 89, 17, 18, 45, 53, 68, 38, 51, 60,
+ 15, 70, 52, 44, 67,136, 67, 44, 52, 70, 14, 58, 54, 40, 65, 54, 46, 17, 16, 89, 35, 20, 9, 14, 75, 57, 73, 13, 15, 30, 27, 82,
+ 42,128, 34, 40, 24, 30, 45,141, 1, 54, 17, 50, 8, 10, 25, 35, 57, 20, 30,254,126,254,201, 17, 51, 8, 10, 25, 35, 57, 20, 29,
+ 59,254,201, 10, 4, 5, 48, 49, 43, 8, 8, 23, 24, 53, 1,128, 1, 54, 11, 4, 6, 48, 48, 44, 8, 7, 24, 24, 53, 3, 96, 1,
+129, 37, 23, 59, 71, 44, 65,254,222, 10, 28, 3, 1, 36, 46, 63, 39, 33, 51, 38, 64, 27, 5, 33, 42, 89,120, 36, 9, 18, 73,109,
+ 80, 84, 93, 45, 69, 69, 48, 90, 84, 80,109, 73, 18, 9, 34,122, 90, 41, 33, 5, 28, 63, 38, 51, 33, 39, 64, 45, 36, 1, 3, 28,
+ 10, 9, 28, 3, 1, 35, 44, 65, 39, 33, 50, 39, 63, 28, 5, 33, 42, 89,120, 36, 8, 17, 73,109, 81, 84, 92, 46, 69, 69, 46, 92,
+ 84, 81,109, 73, 17, 8, 35,121, 90, 41, 33, 5, 26, 65, 38, 50, 34, 39, 63, 46, 35, 1, 3, 28,214,254,126, 38, 22, 60, 71, 44,
+ 64, 1,137,193, 32, 18, 4, 22, 35, 51, 74,254,243,193, 32, 18, 3, 21, 35, 51, 74, 1, 13,193, 19, 30, 17, 22, 34, 30, 30, 1,
+ 4,220,193, 20, 29, 18, 21, 34, 30, 30, 1, 3, 0, 1, 0, 32, 0, 2, 4,177, 5, 87, 0, 65, 0, 0, 1, 39, 7, 39, 55, 39,
+ 55, 23, 53, 51, 21, 23, 53, 39, 55, 23, 53, 51, 21, 55, 23, 7, 21, 55, 53, 51, 21, 55, 23, 7, 23, 7, 39, 7, 23, 55, 23, 7,
+ 23, 7, 39, 21, 35, 53, 39, 21, 23, 7, 39, 21, 35, 53, 7, 39, 55, 53, 7, 21, 35, 53, 7, 39, 55, 39, 55, 23, 2, 1,207,168,
+ 52,116,169, 52,169,104,207,168, 52,116,103,116, 52,168,207,104,169, 52,169,116, 52,168,207,207,168, 52,116,169, 52,169,104,207,
+168, 52,116,103,116, 52,168,207,104,169, 52,169,116, 52,168, 2,173,126,102, 95, 70,104, 96,105,142,205,127,254,102, 95, 71,208,
+208, 71, 95,102,253,126,205,142,105, 96,104, 70, 95,102,126,127,102, 95, 70,104, 95,104,142,205,127,254,102, 95, 71,208,208, 71,
+ 95,102,254,127,205,142,104, 95,104, 70, 95,102, 0, 7, 0, 48,255,250, 4,161, 4,179, 0, 29, 0, 33, 0, 37, 0, 41, 0, 45,
+ 0, 49, 0, 53, 0, 0, 1, 51, 21, 55, 17, 55, 23, 7, 23, 7, 23, 7, 39, 17, 39, 21, 35, 53, 7, 17, 7, 39, 55, 39, 55, 39,
+ 55, 23, 17, 23, 7, 21, 23, 53, 55, 7, 21, 55, 5, 7, 23, 55, 37, 7, 23, 55, 5, 7, 21, 63, 1, 21, 23, 53, 2, 56, 97,236,
+214, 49,216,237,236,215, 49,214,236, 97,236,214, 49,215,236,237,216, 49,214,236,138,138,235,138,138,254, 91,139,138,138, 1, 76,
+137,138,138,254, 90,138,138, 97,138, 4,179,249,136,254,240,125, 84,125,136,136,123, 85,125,254,239,137,248,248,137, 1, 17,125,
+ 85,123,136,136,125, 84,125, 1, 16,136, 32,159, 80,159, 80, 80,159, 80, 85, 80, 79, 79, 80, 80, 79, 79, 83, 80,160, 80,160,160,
+ 80,160, 0, 0, 0, 1, 0, 25, 0, 5, 4,184, 4,192, 0, 65, 0, 0, 1, 51, 21, 55, 23, 7, 21, 55, 53, 51, 21, 55, 23, 7,
+ 23, 7, 39, 7, 23, 55, 23, 7, 23, 7, 39, 21, 35, 53, 39, 21, 23, 7, 39, 21, 35, 53, 7, 39, 55, 53, 7, 21, 35, 53, 7, 39,
+ 55, 39, 55, 23, 55, 39, 7, 39, 55, 39, 55, 23, 53, 51, 21, 23, 53, 39, 55, 23, 2, 57, 97,114, 81,195,218,162, 72, 49, 74,113,
+ 81,195,216,217,195, 81,114, 73, 49, 75,162,214,195, 81,114, 97,114, 81,195,216,162, 74, 49, 72,114, 81,195,217,215,195, 82,114,
+ 75, 49, 73,162,219,195, 81,114, 4,191, 84, 66,141,113,249,126,226,132, 42, 84, 43, 66,141,112,124,126,113,141, 65, 43, 84, 43,
+131,225,124,247,113,141, 66, 84, 82, 66,140,113,251,124,225,131, 43, 84, 42, 65,142,113,125,124,113,141, 66, 43, 84, 41,131,225,
+126,252,112,141, 66, 0, 0, 0, 0, 1, 0, 50,255,238, 4,159, 4,216, 0,135, 0, 0, 1, 22, 21, 20, 7, 6, 7, 6, 35, 34,
+ 39, 38, 39, 7, 23, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 53, 52, 55, 39, 21, 22,
+ 23, 30, 1, 20, 14, 1, 34, 46, 1, 52, 54, 55, 54, 55, 53, 7, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 53, 52, 55,
+ 54, 55, 54, 50, 23, 22, 23, 55, 39, 6, 7, 6, 35, 34, 46, 1, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 23, 53,
+ 38, 39, 46, 1, 52, 54, 55, 54, 51, 50, 30, 1, 20, 6, 7, 6, 7, 21, 55, 38, 53, 52, 55, 54, 55, 54, 51, 50, 23, 22, 4,137,
+ 22, 22, 22, 37, 39, 43, 44, 37, 15, 14,196,196, 14, 15, 37, 44, 43, 39, 37, 22, 22, 22, 23, 36, 39, 43, 41, 40, 38, 22, 21, 3,
+196, 17, 16, 37, 44, 44, 75, 87, 75, 44, 44, 37, 16, 17,196, 3, 21, 22, 38, 38, 43, 44, 38, 37, 22, 22, 22, 22, 37, 39, 86, 38,
+ 15, 14,196,196, 13, 16, 40, 41, 44, 75, 44, 22, 22, 37, 39, 43, 41, 40, 38, 22, 21, 3,196, 17, 16, 37, 44, 44, 37, 38, 43, 44,
+ 75, 44, 44, 37, 16, 17,196, 3, 21, 21, 39, 37, 44, 43, 39, 41, 3,157, 44, 37, 43, 39, 37, 22, 22, 22, 9, 12,113,113, 12, 9,
+ 22, 22, 22, 38, 38, 43, 42, 38, 38, 22, 22, 22, 21, 38, 37, 44, 18, 17,114,227, 6, 8, 22, 75, 88, 75, 44, 44, 75, 88, 75, 22,
+ 8, 6,227,114, 17, 18, 44, 37, 38, 21, 22, 22, 21, 38, 37, 44, 43, 38, 38, 22, 22, 22, 9, 12,113,113, 12, 9, 22, 44, 75, 88,
+ 37, 38, 21, 22, 22, 21, 38, 37, 44, 18, 17,114,227, 5, 9, 22, 75, 88, 75, 21, 22, 43, 75, 88, 75, 22, 9, 5,227,114, 17, 18,
+ 44, 37, 36, 23, 22, 22, 24, 0, 0, 9, 0, 41,255,235, 4,168, 4,106, 0, 7, 0, 11, 0, 15, 0, 19, 0, 23, 0, 46, 0, 69,
+ 0, 92, 0,115, 0, 0, 0, 20, 6, 34, 38, 52, 54, 50, 9, 1, 55, 9, 2, 55, 1, 37, 1, 39, 9, 2, 39, 1, 55, 38, 39, 38,
+ 39, 38, 53, 52, 55, 54, 55, 54, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 3, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 34,
+ 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 39, 6, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23,
+ 22, 5, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 2,218, 67, 93, 67, 67, 93, 1,
+ 64,254,220, 64, 1, 36,253,198,254,221, 64, 1, 35, 1,250,254,220, 64, 1, 36,254, 70,254,221, 64, 1, 35,139, 43, 11, 17, 3,
+ 1, 1, 3, 11, 17, 87, 17, 11, 3, 1, 1, 3, 17, 11, 44, 44, 11, 17, 3, 1, 1, 3, 11, 17, 87, 17, 11, 3, 1, 1, 3, 17,
+ 11,120, 45, 18, 28, 51, 22, 62, 52, 23, 49, 24, 37, 37, 24, 49, 23, 52, 62, 22, 51, 28, 18, 1,116, 45, 18, 28, 51, 22, 62, 52,
+ 23, 49, 24, 37, 37, 24, 49, 23, 52, 62, 22, 51, 28, 18, 2,102, 94, 67, 67, 94, 66,253,223, 1, 37, 64,254,219, 1,186, 1, 35,
+ 64,254,221,227,254,219, 64, 1, 37,253,198,254,221, 64, 1, 35,228, 45, 18, 28, 52, 21, 62, 52, 23, 49, 24, 37, 37, 24, 49, 23,
+ 52, 62, 21, 52, 28, 18,254,140, 45, 18, 28, 51, 22, 62, 52, 23, 49, 24, 37, 37, 24, 49, 23, 52, 62, 22, 51, 28, 18,209, 43, 12,
+ 17, 3, 1, 2, 2, 11, 18, 86, 17, 11, 3, 1, 1, 3, 17, 11, 43, 43, 11, 17, 3, 1, 1, 3, 11, 17, 86, 18, 11, 2, 2, 1,
+ 3, 17, 12, 0, 0, 9, 0, 33,255,227, 4,176, 4,114, 0, 7, 0, 11, 0, 15, 0, 19, 0, 23, 0, 43, 0, 63, 0, 83, 0,103,
+ 0, 0, 0, 20, 6, 34, 38, 52, 54, 50, 1, 55, 23, 7, 1, 55, 23, 7, 1, 23, 7, 39, 1, 23, 7, 39, 2, 20, 7, 6, 7, 6,
+ 34, 39, 38, 39, 38, 52, 55, 54, 55, 54, 50, 23, 22, 23, 18, 20, 7, 6, 7, 6, 34, 39, 38, 39, 38, 52, 55, 54, 55, 54, 50, 23,
+ 22, 23, 0, 50, 23, 22, 23, 22, 20, 7, 6, 7, 6, 34, 39, 38, 39, 38, 52, 55, 54, 55, 36, 50, 23, 22, 23, 22, 20, 7, 6, 7,
+ 6, 34, 39, 38, 39, 38, 52, 55, 54, 55, 3, 21,101,143,101,101,143,254, 4,227, 66,228, 2, 3,228, 65,227,253,187,228, 66,227,
+ 2,134,227, 65,228, 6, 14, 16, 30, 35, 85, 35, 30, 16, 14, 14, 16, 30, 35, 85, 35, 30, 16, 14, 14, 16, 30, 35, 85, 35, 30, 16,
+ 14, 14, 16, 30, 35, 85, 35, 30, 16,253,199, 86, 37, 42, 27, 31, 31, 27, 42, 37, 86, 38, 42, 27, 30, 30, 27, 42, 3, 75, 86, 38,
+ 42, 27, 30, 30, 27, 42, 38, 86, 37, 42, 27, 31, 31, 27, 42, 2,126,142,102,102,142,101,253,223,227, 65,227, 2,134,227, 65,227,
+ 1, 36,227, 65,227,253,252,227, 65,227, 2,132, 86, 37, 42, 27, 31, 31, 27, 42, 37, 86, 38, 42, 27, 30, 30, 27, 42,252,181, 86,
+ 38, 42, 27, 30, 30, 27, 42, 38, 86, 37, 42, 27, 31, 31, 27, 42, 1,204, 14, 16, 30, 35, 85, 35, 30, 16, 14, 14, 16, 30, 35, 85,
+ 35, 30, 16, 14, 14, 16, 30, 35, 85, 35, 30, 16, 14, 14, 16, 30, 35, 85, 35, 30, 16, 0, 0, 0, 0, 9, 0, 23,255,234, 4,186,
+ 4,141, 0, 12, 0, 25, 0, 38, 0, 51, 0, 64, 0, 77, 0, 89, 0, 97, 0,109, 0, 0, 1, 20, 7, 6, 43, 1, 37, 53, 37, 51,
+ 50, 23, 22, 5, 52, 55, 54, 59, 1, 5, 21, 5, 35, 34, 39, 38, 1, 22, 21, 20, 15, 2, 39, 63, 1, 54, 51, 50, 1, 38, 53, 52,
+ 63, 2, 23, 15, 1, 6, 35, 34, 3, 54, 51, 50, 31, 2, 7, 47, 1, 38, 53, 52, 1, 6, 35, 34, 47, 2, 55, 31, 1, 22, 21, 20,
+ 0, 50, 23, 22, 29, 1, 3, 35, 3, 53, 52, 55, 18, 20, 6, 34, 38, 52, 54, 50, 2, 34, 39, 38, 61, 1, 19, 51, 19, 21, 20, 7,
+ 4,185, 21, 22, 30, 8,254,193, 1, 63, 8, 29, 23, 21,251, 95, 21, 22, 30, 8, 1, 63,254,193, 8, 29, 23, 21, 3,244, 22, 20,
+ 6,252, 54,198, 5, 21, 32, 32,252,207, 22, 20, 6,252, 54,198, 5, 21, 32, 30, 24, 22, 32, 31, 22, 5,198, 54,252, 6, 20, 3,
+ 93, 23, 31, 32, 21, 5,198, 54,252, 6, 20,254, 39, 63, 23, 22, 38, 77, 38, 22,169, 67, 95, 67, 67, 95, 16, 63, 23, 22, 38, 77,
+ 38, 22, 2, 60, 32, 23, 22, 39, 76, 38, 22, 23, 31, 31, 23, 22, 38, 76, 39, 22, 23, 1,195, 22, 33, 30, 22, 5,198, 54,252, 5,
+ 22,252,162, 23, 32, 30, 22, 5,198, 54,252, 5, 22, 3, 94, 23, 22, 5,252, 54,198, 5, 21, 31, 33,252,207, 23, 22, 5,252, 54,
+198, 5, 21, 31, 32, 3,222, 23, 21, 31, 7,254,194, 1, 62, 7, 30, 22,253,245, 95, 67, 67, 95, 68,253, 60, 22, 21, 31, 7, 1,
+ 62,254,194, 7, 30, 22, 0, 0, 0, 1, 0, 34,255,233, 4,175, 4, 27, 0,108, 0, 0, 1, 50, 23, 22, 21, 20, 7, 3, 19, 54,
+ 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 7, 5, 37, 54, 51, 50, 23, 22, 20, 7, 6, 35, 34, 39, 37, 5, 22, 51, 22, 21, 20, 7,
+ 6, 35, 34, 39, 38, 39, 3, 19, 22, 21, 20, 7, 6, 34, 39, 38, 53, 52, 55, 19, 3, 6, 7, 6, 35, 34, 39, 38, 53, 52, 55, 50,
+ 55, 37, 5, 6, 35, 34, 39, 38, 52, 55, 54, 51, 50, 23, 5, 37, 38, 39, 38, 53, 52, 55, 54, 51, 22, 23, 22, 23, 19, 3, 38, 53,
+ 52, 55, 54, 2,104, 33, 35, 27, 4, 59,214, 15, 2, 39, 38, 49, 24, 22, 39, 8, 18,254,219, 1,104, 19, 9, 57, 26, 35, 35, 27,
+ 56, 5, 28,254,157, 1, 41, 21, 1, 39, 22, 24, 49, 33, 44, 8, 13,210, 59, 4, 27, 35, 65, 35, 27, 4, 59,210, 13, 8, 39, 38,
+ 49, 24, 22, 39, 1, 21, 1, 41,254,157, 28, 5, 56, 27, 35, 35, 26, 57, 9, 19, 1,104,254,219, 18, 8, 39, 22, 24, 49, 27, 50,
+ 2, 15,214, 59, 4, 27, 35, 4, 26, 32, 24, 52, 5, 21,254,181, 1, 16, 20, 1, 37, 22, 21, 46, 38, 33, 6, 12,194, 54, 3, 23,
+ 32, 61, 32, 25, 4, 54,196, 16, 37, 34, 46, 21, 22, 37, 7, 17, 1, 13,254,181, 21, 5, 51, 25, 32, 32, 25, 51, 9, 21, 1, 71,
+254,243, 17, 7, 37, 22, 21, 46, 53, 18, 16,196, 54, 4, 25, 32, 61, 32, 23, 3, 54,194, 12, 6, 37, 34, 46, 21, 22, 14, 23, 1,
+ 20,254,240, 1, 71, 21, 9, 52, 24, 32, 0, 0, 0, 2, 0, 36,255,245, 4,173, 4, 56, 0, 11, 0, 33, 0, 0, 19, 20, 0, 32,
+ 0, 53, 52, 46, 1, 34, 14, 1, 1, 6, 35, 34, 0, 53, 52, 18, 36, 51, 50, 23, 54, 51, 50, 4, 18, 21, 20, 0, 35, 34, 95, 1,
+ 28, 1,148, 1, 28,130,233,246,233,130, 2, 9, 18, 18,224,254,192,147, 1, 6,135, 18, 18, 18, 17,138, 1, 6,146,254,192,226,
+ 17, 2, 22,201,254,227, 1, 29,201,128,232,126,126,232,253, 97, 1, 1, 62,226,141, 1, 7,141, 1, 1,141,254,251,143,226,254,
+194, 0, 0, 0, 0, 2, 0, 69,255,193, 4,140, 4, 9, 0, 3, 0, 11, 0, 0, 37, 17, 33, 17, 23, 35, 17, 33, 21, 51, 17, 33,
+ 4, 14,252,112, 12, 69, 4, 2, 69,251,254, 63, 3,144,252,112, 57, 4, 2, 69,251,255, 0, 0, 0, 2, 0, 61, 0, 0, 4,148,
+ 4, 86, 0, 3, 0, 11, 0, 0, 37, 17, 33, 17, 37, 21, 33, 17, 51, 53, 33, 17, 4, 20,252, 99, 3,215,251,240, 69, 4, 16, 58,
+ 3,156,252,100, 12, 70, 4, 16, 70,251,240, 0, 0, 2, 0, 56,255,184, 4,153, 4, 25, 0, 3, 0, 9, 0, 0, 37, 17, 33, 17,
+ 7, 17, 33, 23, 17, 33, 4, 24,252, 91, 58, 4, 25, 70,251,252, 58, 3,164,252, 92, 59, 4, 25, 91,251,252, 0, 0, 2, 0, 48,
+ 0, 0, 4,161, 4,113, 0, 3, 0, 9, 0, 0, 37, 17, 33, 17, 5, 33, 17, 55, 33, 17, 4, 30,252, 78, 3,237,251,215, 93, 4,
+ 20, 60, 3,178,252, 78, 59, 4, 41, 71,251,237, 0, 4, 0, 43,255,250, 4,166, 4,116, 0, 3, 0, 7, 0, 11, 0, 15, 0, 0,
+ 19, 9, 14, 44, 1, 3, 1, 4,254,252, 1,111, 1, 4, 1, 3,254,253,253,196, 1, 4, 1, 4,254,252,254,252, 1, 4, 1, 4,
+254,252, 2, 57, 1, 3,254,253,254,252, 1, 4, 1, 2,254,254,254,251, 2, 59, 1, 5,254,251,254,253,254,146, 1, 4,254,252,
+254,252, 0, 0, 0, 1, 2, 27,255, 12, 2,182, 5,156, 0, 3, 0, 0, 1, 17, 35, 17, 2,182,155, 5,156,249,113, 6,143, 0,
+ 0, 1, 1,205,255, 10, 3, 4, 5,153, 0, 3, 0, 0, 1, 17, 33, 17, 3, 3,254,203, 5,153,249,114, 6,142, 0, 1, 1, 81,
+254,203, 3,128, 5,107, 0, 3, 0, 0, 1, 17, 33, 17, 3,127,253,211, 5,107,249, 96, 6,160, 0, 1, 1,221, 3,207, 2,244,
+ 5,217, 0, 6, 0, 0, 1, 33, 17, 55, 51, 7, 51, 2,244,254,233,125, 98, 62,118, 3,207, 1, 23,243,243, 0, 0, 1, 1,211,
+ 3,196, 2,254, 5,199, 0, 6, 0, 0, 1, 33, 17, 7, 35, 55, 35, 1,212, 1, 41,133,105, 67,126, 5,198,254,238,239,239, 0,
+255,255, 1, 0, 3,207, 3,209, 5,217, 16, 39, 10, 63, 0,221, 0, 0, 16, 7, 10, 63,255, 35, 0, 0, 0, 0,255,255, 0,246,
+ 3,196, 3,219, 5,199, 16, 39, 10, 64, 0,221, 0, 0, 16, 7, 10, 64,255, 35, 0, 0, 0, 0, 0, 2, 0,103,255, 93, 4,106,
+ 5,129, 0, 79, 0, 83, 0, 0, 1, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6, 35, 34, 7, 6, 7, 6, 7, 6,
+ 20, 23, 22, 23, 22, 23, 22, 51, 50, 55, 54, 55, 54, 55, 54, 53, 17, 35, 34, 39, 38, 53, 52, 54, 59, 1, 53, 55, 21, 33, 7, 35,
+ 17, 20, 7, 6, 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 37, 17, 35, 17, 1,185, 25, 21,
+ 22, 18, 17, 10, 8, 8, 10, 17, 18, 22, 21, 21, 23, 16, 15, 13, 14, 6, 7, 8, 8, 13, 16, 13, 19, 26, 52, 50, 59, 37, 45, 20,
+ 22,250,180,110, 96,212,174,250,114, 1, 21,114,163, 30, 35, 50, 54, 65, 64, 58, 86, 55, 58, 36, 41, 18, 19, 19, 21, 38, 31, 55,
+ 46, 1, 89,155, 1,113, 9, 10, 17, 16, 24, 22, 25, 24, 22, 24, 16, 17, 10, 9, 7, 6, 13, 13, 16, 16, 37, 17, 18, 11, 15, 5,
+ 7, 22, 27, 36, 46, 50, 55, 55, 1, 29,103, 91,149,154,189,163, 40,203,100,252,162, 86, 68, 81, 52, 57, 31, 30, 20, 21, 37, 42,
+ 44, 48, 52, 63, 40, 41, 45, 35, 23, 20,250, 1,230,254, 26, 0, 0, 2, 0,255,255,217, 3,210, 4,201, 0, 23, 0, 53, 0, 0,
+ 1, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 18, 50, 23, 22, 23, 22, 23, 22,
+ 21, 20, 7, 6, 7, 6, 7, 6, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 2,104,130, 99, 34, 36, 31, 15, 16,110,
+145,106,108,142,110, 16, 15, 31, 30, 40, 76,102,101, 42, 43, 36, 36, 18, 17, 17, 18, 36, 36, 43, 42,101, 42, 43, 36, 37, 17, 17,
+ 17, 17, 37, 36, 43, 4,201, 33, 11, 35, 31, 39, 40, 42,100, 82,106,168,168,106, 83, 99, 42, 40, 39, 31, 29, 17, 33,252,249, 18,
+ 20, 34, 37, 42, 44, 50, 48, 44, 43, 37, 34, 20, 17, 17, 20, 34, 37, 43, 44, 48, 50, 44, 42, 37, 34, 20, 0, 0, 0, 2, 0,190,
+255,227, 4, 19, 4,211, 0, 37, 0, 67, 0, 0, 1, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 50, 23, 22, 23, 22, 23, 22, 21,
+ 52, 55, 54, 55, 54, 55, 54, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 2, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6,
+ 7, 6, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 2,104, 99,216,110, 16, 15, 31, 30, 40, 37, 88, 37, 38, 31, 30,
+ 16, 16, 17, 16, 30, 31, 38, 38, 87, 37, 40, 30, 31, 15, 16,110,216,150,101, 42, 43, 36, 36, 18, 17, 17, 18, 36, 36, 43, 42,101,
+ 42, 43, 36, 37, 17, 17, 17, 17, 37, 36, 43, 2, 44,159,131, 68,106, 42, 40, 39, 31, 29, 17, 16, 16, 16, 30, 30, 40, 38, 44, 44,
+ 38, 40, 30, 30, 16, 16, 16, 17, 29, 31, 39, 40, 42,107, 67,131,255, 0, 17, 20, 34, 38, 42, 44, 49, 49, 44, 42, 37, 35, 19, 18,
+ 18, 19, 35, 37, 42, 44, 49, 49, 44, 42, 38, 34, 20, 0, 0, 0, 0, 1, 0, 46, 0,105, 4,163, 4, 15, 0, 37, 0, 0, 37, 38,
+ 37, 38, 53, 52, 55, 54, 55, 54, 55, 54, 50, 23, 22, 23, 22, 23, 22, 21, 52, 55, 54, 55, 54, 55, 54, 50, 23, 22, 23, 22, 23, 22,
+ 21, 20, 7, 4, 2,104,104,254,195,148, 21, 21, 42, 40, 52, 50,117, 50, 52, 41, 40, 22, 21, 22, 22, 40, 41, 52, 50,117, 50, 52,
+ 40, 42, 21, 21,148,254,195,105,194,197, 92,144, 61, 57, 55, 44, 42, 25, 23, 23, 24, 43, 42, 57, 54, 64, 64, 54, 57, 42, 43, 24,
+ 23, 23, 25, 42, 44, 55, 57, 61,146, 90,197, 0, 0, 1, 0,114,255,251, 4, 95, 5, 25, 0, 39, 0, 0, 1, 6, 3, 6, 35, 34,
+ 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 51, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 51, 50,
+ 23, 18, 4, 95,209,211,100,156, 65, 61, 59, 48, 45, 26, 25, 25, 24, 47, 46, 61, 58, 68, 68, 58, 61, 46, 47, 24, 25, 25, 26, 45,
+ 48, 59, 61, 65,158, 98,211, 2,138,120,254,148,170, 24, 23, 49, 46, 61, 56, 68, 67, 57, 60, 47, 46, 26, 24, 25, 24, 47, 48, 59,
+ 56, 69, 66, 58, 59, 47, 48, 24, 25,170,254,146, 0, 2, 0, 65, 0, 25, 4,144, 4,137, 0, 13, 0,105, 0, 0, 1, 54, 53, 52,
+ 39, 38, 35, 34, 7, 6, 21, 20, 23, 22, 23, 6, 7, 54, 51, 50, 23, 22, 21, 20, 7, 6, 21, 20, 51, 50, 55, 54, 51, 50, 21, 20,
+ 33, 34, 39, 38, 53, 16, 51, 50, 23, 54, 55, 38, 39, 38, 35, 34, 7, 6, 21, 20, 22, 21, 20, 7, 6, 35, 34, 39, 38, 53, 52, 55,
+ 54, 51, 50, 31, 1, 52, 55, 54, 51, 50, 23, 22, 21, 20, 7, 22, 51, 50, 55, 54, 53, 52, 39, 38, 53, 52, 55, 54, 51, 50, 23, 22,
+ 21, 20, 7, 6, 35, 34, 2,198, 8, 24, 19, 44, 24, 19, 15, 35, 60, 90, 17, 37, 76, 70,101, 48, 36,251,124, 85, 94, 14, 41, 44,
+ 51,255, 0,166,151,161,212, 83, 66, 63, 13, 82,187, 56, 60, 68, 51, 33, 35, 22, 29, 16, 26, 20, 12, 94, 76, 95, 85, 40, 61, 33,
+ 35, 63, 62, 40, 41, 13, 49, 70, 61, 34, 37, 17, 34, 17, 25, 46, 52, 34, 17,116, 78, 97, 53, 3,140, 38, 36, 52, 33, 27, 15, 12,
+ 22, 47, 28, 46,114, 60, 64, 54, 66, 50, 76,178, 95, 48, 62, 81, 35,107, 73,127,124,133,206, 1, 34,114,122, 55, 38,139, 41, 63,
+ 41, 44, 30, 31, 23, 19, 16, 23, 37, 20, 61, 94, 75, 61, 30, 46, 67, 25, 26, 50, 54, 70, 64, 49, 14, 27, 29, 25, 51, 15, 29, 17,
+ 46, 22, 33, 57, 27, 43, 99, 77, 51, 0, 0, 0, 0, 2, 0, 49, 1, 51, 4,160, 3,198, 0, 7, 0, 78, 0, 0, 1, 6, 7, 6,
+ 7, 54, 55, 54, 1, 32, 53, 52, 55, 38, 39, 38, 7, 22, 7, 6, 7, 22, 51, 50, 55, 22, 21, 20, 35, 34, 39, 35, 53, 51, 54, 55,
+ 54, 55, 38, 39, 38, 39, 38, 53, 52, 51, 6, 21, 20, 23, 22, 23, 50, 23, 22, 23, 38, 53, 52, 55, 54, 51, 50, 19, 22, 51, 50, 53,
+ 52, 39, 38, 53, 52, 51, 50, 21, 20, 7, 6, 1, 53, 51, 37, 53, 22, 64, 50, 54, 1,154,254,209, 96, 39, 44, 32, 32, 2, 61, 78,
+ 82, 21, 54, 35, 33, 6,118, 87, 16, 29, 31, 25, 82, 62, 52, 13, 29, 28, 50, 58, 79, 9,116, 53, 4, 49, 34, 34, 46, 25, 49, 38,
+ 88,176, 46, 20, 82, 79, 9, 9, 65, 53,200,143, 2,189, 11, 30, 41, 84, 24, 47, 49,254,165,206, 56, 54, 44, 23, 17, 1, 70, 65,
+ 83, 12, 58, 35, 24, 40, 61,139, 58,116, 65, 48, 2, 15, 14, 15, 11, 14, 57, 83, 24, 28, 31, 68, 32, 20, 16, 16, 39, 65, 35, 53,
+ 31, 24,254,215,125, 49, 24, 15, 14, 22, 49, 66,141, 79, 57, 0, 0, 1, 0,240,255,155, 3,225, 5,130, 0, 32, 0, 0, 5, 34,
+ 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 51, 21, 34, 7, 14, 1, 7, 6, 21, 20, 23, 22, 23, 22, 23, 22, 51, 3,
+225,151,138,131,112,109, 56, 56, 56, 52,113,108,135,138,151, 89, 84, 78,135, 33, 32, 32, 33, 67, 64, 82, 80, 93,101, 58, 54,112,
+108,135,134,152,153,137,128,116,109, 57, 58, 39, 54, 50,213,126,127,149,144,127,126,106,102, 55, 55, 0, 0, 0, 0, 1, 0,240,
+255,155, 3,225, 5,130, 0, 34, 0, 0, 23, 48, 53, 50, 55, 54, 55, 54, 55, 54, 53, 52, 39, 46, 1, 39, 38, 35, 48, 53, 50, 23,
+ 22, 23, 22, 23, 22, 21, 20, 7, 6, 7, 6, 7, 6,240, 93, 80, 82, 64, 67, 33, 32, 32, 33,135, 78, 84, 89,151,138,135,108,113,
+ 52, 56, 56, 56,109,112,131,138,101, 39, 54, 55,102,106,126,127,144,149,127,126,213, 50, 55, 38, 58, 57,109,116,127,138,153,152,
+133,136,108,111, 55, 58, 0, 0, 0, 1, 1,102,255,135, 3,107, 5, 82, 0, 12, 0, 0, 1, 6, 2, 16, 18, 23, 33, 38, 2, 53,
+ 52, 18, 55, 3,106,108,106,106,108,254,239,121,121,120,122, 5, 81,187,254,147,254,137,254,143,186,191, 1,113,182,181, 1,112,
+191, 0, 0, 0, 0, 1, 1,110,255,135, 3, 99, 5, 36, 0, 15, 0, 0, 1, 48, 33, 22, 18, 21, 20, 7, 6, 7, 33, 54, 55, 54,
+ 16, 2, 1,110, 1, 9,119,117, 59, 59,118,254,247,105, 52, 51,102, 5, 36,186,254,156,176,176,179,179,185,181,178,178, 1,108,
+ 1, 99, 0, 0, 0, 1, 1, 67,255,125, 3,142, 5, 85, 0, 5, 0, 0, 5, 35, 9, 1, 51, 1, 3,141,213,254,140, 1,116,213,
+254,138,130, 2,235, 2,236,253, 20, 0, 0, 0, 0, 1, 1, 68,255,125, 3,141, 5, 85, 0, 5, 0, 0, 5, 9, 1, 51, 9, 1,
+ 1, 68, 1,117,254,140,212, 1,116,254,140,130, 2,235, 2,236,253, 20,253, 21, 0, 1, 0,210,255, 86, 3,255, 5, 46, 0, 5,
+ 0, 0, 5, 33, 9, 1, 33, 1, 3,254,254,182,254, 31, 1,225, 1, 74,254, 22,169, 2,235, 2,236,253, 20, 0, 0, 1, 0,210,
+255, 86, 3,255, 5, 46, 0, 5, 0, 0, 23, 9, 1, 33, 9, 1,211, 1,234,254, 22, 1, 74, 1,225,254, 31,169, 2,235, 2,236,
+253, 20,253, 21, 0, 1, 0,205,255, 65, 4, 4, 5,209, 0, 5, 0, 0, 5, 33, 9, 1, 33, 1, 4, 3,254,109,254, 94, 1,162,
+ 1,147,254, 92,190, 3, 71, 3, 72,252,184, 0, 0, 1, 0,206,255, 66, 4, 3, 5,210, 0, 5, 0, 0, 23, 9, 1, 33, 9, 1,
+206, 1,163,254, 94, 1,146, 1,162,254, 94,190, 3, 72, 3, 72,252,184,252,184, 0, 1, 1,201,254,229, 3, 8, 5,118, 0, 7,
+ 0, 0, 33, 23, 7, 39, 17, 55, 23, 7, 2, 68,196, 87,232,232, 87,196,195, 87,231, 4,194,231, 87,195, 0, 0, 0, 1, 1,201,
+254,235, 3, 8, 5,124, 0, 7, 0, 0, 1, 39, 55, 23, 17, 7, 39, 55, 2,141,196, 87,232,232, 87,196, 4, 98,195, 87,231,251,
+ 62,231, 87,195, 0, 1, 1, 25,254,184, 3,184, 5, 94, 0, 36, 0, 0, 5, 21, 35, 34, 38, 61, 1, 52, 38, 43, 1, 53, 51, 50,
+ 54, 61, 1, 52, 54, 59, 1, 21, 35, 34, 6, 29, 1, 20, 6, 7, 30, 1, 29, 1, 20, 22, 51, 3,184,151,178,120, 77,101, 44, 44,
+102, 76,120,178,151, 49,100, 61, 65, 79, 79, 65, 61,100,198,130,133,199,215,136,105,128,104,134,216,199,132,129, 79,127,223,141,
+128, 23, 24,128,140,223,127, 79, 0, 1, 0,249,254,176, 3,216, 5,105, 0, 40, 0, 0, 23, 51, 50, 54, 61, 1, 52, 54, 55, 38,
+ 39, 38, 61, 1, 52, 38, 43, 1, 53, 51, 50, 23, 22, 29, 1, 20, 23, 22, 59, 1, 21, 35, 34, 6, 29, 1, 20, 7, 6, 43, 1,250,
+ 53,110, 67, 70, 86, 85, 36, 35, 67,110, 53,165,194, 66, 66, 42, 41,112, 47, 47,111, 84, 66, 66,194,165,204, 80,128,226,142,129,
+ 25, 22, 65, 65,143,225,129, 80,130, 68, 66,201,219,135, 52, 53,130,105,138,217,201, 68, 67, 0, 0, 1, 0, 83, 1, 47, 4,126,
+ 3,229, 0, 8, 0, 0, 9, 1, 35, 1, 33, 53, 33, 1, 51, 4,125,254,165,227, 1, 6,253, 15, 2,241,254,250,227, 2,138,254,
+165, 1, 6,170, 1, 6, 0, 0, 0, 1, 0,116, 0,146, 4, 93, 4,125, 0, 6, 0, 0, 9, 1, 55, 1, 27, 1, 37, 3, 16,253,
+100,148, 2, 94,186, 61,253,164, 1,138, 2, 93,149,253,100, 1, 14,253,164, 62, 0, 1, 0, 83, 1,162, 4,126, 4, 18, 0, 6,
+ 0, 0, 1, 5, 53, 5, 3, 9, 1, 3, 47,253, 37, 2,219, 48, 1,126,254,130, 2,168, 35,170, 35, 1, 5,254,201,254,201, 0,
+ 0, 1, 0,116, 0,193, 4, 93, 4,171, 0, 6, 0, 0, 9, 1, 39, 1, 45, 1, 3, 3,102,253,162,148, 2,156,254,241, 2, 92,
+ 61, 3, 93,253,100,149, 2, 93,186, 62,253,164, 0, 1, 0, 45, 1,161, 4,164, 3,225, 0, 8, 0, 0, 19, 33, 39, 4, 5, 4,
+ 5, 55, 33, 46, 2, 20,128, 1, 9, 1,216,254, 40,254,247,128,253,236, 2,239,242,192, 96, 96,192,242, 0, 0, 0, 1, 0, 73,
+ 1, 41, 4,136, 4, 61, 0, 50, 0, 0, 0, 20, 7, 6, 7, 1, 6, 7, 6, 34, 38, 39, 38, 39, 38, 53, 52, 55, 54, 63, 1, 33,
+ 34, 46, 1, 39, 38, 52, 55, 62, 2, 51, 33, 39, 38, 39, 38, 53, 52, 55, 54, 55, 62, 1, 50, 23, 22, 23, 1, 22, 4,136, 7, 9,
+ 12,254,212, 12, 18, 17, 39, 33, 13, 14, 7, 7, 7, 8, 13,139,253, 96, 19, 33, 27, 8, 6, 6, 8, 27, 33, 19, 2,160,139, 13,
+ 8, 7, 7, 7, 14, 13, 33, 39, 17, 18, 12, 1, 44, 14, 2,198, 38, 16, 18, 13,254,212, 12, 8, 7, 14, 13, 15, 16, 16, 19, 20,
+ 16, 18, 13,140, 14, 26, 18, 16, 38, 16, 18, 26, 15,139, 13, 18, 17, 19, 19, 16, 17, 14, 13, 15, 7, 9, 12,254,212, 14, 0, 0,
+ 0, 1, 0, 83, 1,182, 4,126, 4, 38, 0, 6, 0, 0, 1, 33, 53, 33, 17, 9, 1, 3, 70,253, 14, 2,242, 1, 55,254,201, 2,
+210, 56, 1, 27,254,201,254,201, 0, 1, 0, 45, 1,120, 4,164, 4, 20, 0, 6, 0, 0, 1, 33, 53, 33, 53, 9, 1, 3, 86,252,
+216, 3, 40, 1, 77,254,179, 2,114,168,250,254,178,254,178, 0, 0, 4, 0, 54, 1,117, 4,155, 4, 6, 0, 3, 0, 7, 0, 11,
+ 0, 18, 0, 0, 1, 35, 17, 51, 3, 35, 17, 51, 3, 35, 17, 51, 1, 33, 17, 33, 53, 9, 1, 1,233,180,180,240, 90, 90,150, 45,
+ 45, 2,239,254,211, 1, 45, 1, 73,254,183, 2, 40, 1, 44,254,212, 1, 44,254,212, 1, 44,254,212, 1, 44,178,254,184,254,183,
+ 0, 4, 0, 83, 1,156, 4,126, 4, 11, 0, 8, 0, 12, 0, 16, 0, 20, 0, 0, 1, 53, 22, 23, 6, 7, 53, 33, 17, 3, 35, 17,
+ 51, 3, 35, 17, 51, 3, 35, 17, 51, 3, 70,131,180,180,131,254,227, 57,171,171,228, 85, 85,142, 42, 42, 3,169, 98,218, 93, 94,
+218, 98, 1,171,254, 85, 1,171,254, 85, 1,171,254, 85, 1,171, 0, 1, 0, 83, 1,132, 4,126, 3,244, 0, 6, 0, 0, 1, 33,
+ 17, 33, 53, 9, 1, 3, 70,253, 14, 2,242, 1, 55,254,201, 2, 46, 1, 28,169,254,201,254,201, 0, 2, 0, 96, 1,116, 4,113,
+ 4, 24, 0, 2, 0, 6, 0, 0, 1, 33, 37, 23, 9, 2, 2, 12, 1,168,253,141,113,254,174, 4, 17,251,239, 2,198,203,203, 1,
+ 82,254,174,254,174, 0, 0, 0, 0, 2, 0,123, 1,164, 4, 86, 4, 36, 0, 2, 0, 6, 0, 0, 1, 7, 37, 33, 9, 2, 2, 16,
+192, 2, 83,254, 24,254,192, 3,219,252, 37, 2,228,193,193, 1, 64,254,192,254,192, 0, 0, 0, 0, 1, 0,123, 1, 31, 4, 86,
+ 4,189, 0, 3, 0, 0, 1, 3, 9, 1, 1,116,249, 3,219,252, 37, 2,238, 1,206,254, 50,254, 50, 0, 0, 0, 0, 1, 0, 54,
+ 1,140, 4,155, 4, 61, 0, 22, 0, 0, 19, 17, 20, 23, 22, 23, 22, 23, 22, 51, 33, 53, 9, 1, 53, 33, 34, 39, 38, 39, 38, 39,
+ 38, 54, 14, 13, 27, 26, 32, 32, 36, 2,104, 1, 73,254,183,253,152, 36, 32, 32, 26, 27, 13, 14, 2,213, 1,104, 36, 32, 32, 27,
+ 25, 15, 13,149,254,183,254,183,149, 13, 15, 25, 27, 32, 32, 0, 0, 1, 0, 54, 1,139, 4,155, 4, 60, 0, 22, 0, 0, 19, 52,
+ 55, 54, 55, 54, 55, 54, 51, 33, 53, 9, 1, 53, 33, 34, 7, 6, 7, 6, 7, 6, 21, 54, 14, 13, 27, 26, 32, 32, 36, 2,104, 1,
+ 73,254,183,253,152, 36, 32, 32, 26, 27, 13, 14, 2,243, 36, 32, 32, 27, 25, 15, 13,149,254,183,254,183,149, 13, 15, 25, 27, 32,
+ 32, 36, 0, 0, 0, 1, 1, 79, 1, 6, 3,130, 4,224, 0, 6, 0, 0, 1, 33, 17, 33, 17, 9, 1, 2,101,254,235, 1, 21, 1,
+ 28,254,228, 2, 18, 1,194, 1, 12,254, 19,254, 19, 0, 0, 0, 0, 1, 0, 54, 1,110, 4,155, 4, 0, 0, 8, 0, 0, 1, 53,
+ 22, 5, 4, 7, 53, 33, 17, 2,226,108, 1, 77,254,179,108,253, 84, 3,137,119,230, 99, 99,230,119, 1,164, 0, 0, 2, 0,101,
+ 1,107, 4,108, 4, 33, 0, 8, 0, 15, 0, 0, 1, 53, 33, 17, 33, 53, 51, 9, 1, 39, 21, 9, 1, 21, 33, 21, 2, 95,254, 6,
+ 1,250,178, 1, 91,254,165,121, 1, 34,254,222,254, 6, 1,107,169, 1,100,169,254,165,254,165,226,169, 1, 34, 1, 34,169,242,
+ 0, 2, 0,101, 1, 47, 4,108, 3,229, 0, 8, 0, 15, 0, 0, 1, 53, 33, 17, 33, 53, 51, 9, 1, 39, 21, 9, 1, 21, 33, 21,
+ 2, 95,254, 6, 1,250,178, 1, 91,254,165, 15, 1, 34,254,222,254, 7, 1, 47,169, 1,100,169,254,165,254,165,226,169, 1, 34,
+ 1, 34,169,242, 0, 2, 0, 53, 0,183, 4,156, 3,252, 0, 11, 0, 18, 0, 0, 27, 1, 33, 55, 51, 19, 21, 1, 35, 53, 55, 33,
+ 37, 7, 1, 3, 7, 33, 7, 54,205, 2, 85, 99, 71,153,253,249,106, 15,253,253, 2,182, 98, 1,202,122, 98,253,170,140, 1,239,
+ 1,100,169,254,147,143,254,184,142, 27,199,169, 1, 34, 1, 34,169,242, 0, 0, 0, 2, 0, 97, 0,214, 4,112, 3,171, 0, 11,
+ 0, 18, 0, 0, 19, 53, 33, 39, 53, 51, 1, 21, 3, 35, 39, 33, 1, 33, 23, 33, 23, 55, 37, 97, 1,220, 15, 99, 1,223,142, 65,
+ 91,253,216, 1,196,253,216,129, 2, 40, 90,113,254, 90, 2,157,123, 23,123,254,228,123,254,196,146, 1, 3,210,146,251,251, 0,
+ 0, 2, 0,125, 0,219, 4, 84, 4, 77, 0, 10, 0, 17, 0, 0, 37, 39, 33, 39, 17, 33, 53, 51, 1, 23, 1, 3, 21, 9, 1, 21,
+ 33, 17, 2,147, 59,254,113, 75, 1,202, 82, 1,110, 75,254,146, 97, 1, 50,254,206,254, 54,219,119,150, 1,238,119,254,146,150,
+254,146, 1, 73,119, 1, 50, 1, 50,119,254,138, 0, 2, 0, 84, 0,130, 4,125, 4, 62, 0, 10, 0, 17, 0, 0, 1, 51, 1, 7,
+ 1, 35, 53, 33, 17, 55, 33, 23, 33, 17, 33, 21, 9, 1, 2,150, 90, 1,140, 81,254,116, 90,254, 16, 81, 1,176, 48,254, 16, 1,
+240, 1, 76,254,180, 4, 62,254,115,162,254,115,129, 2, 24,163,228,254,106,129, 1, 76, 1, 75, 0, 2, 0, 50, 1, 78, 4,159,
+ 4,117, 0, 12, 0, 20, 0, 0, 19, 39, 33, 53, 51, 1, 23, 1, 35, 39, 53, 33, 39, 55, 7, 33, 21, 9, 1, 21, 33,163,112, 2,
+133, 83, 1,110, 37,254,146, 82, 38,253,160, 37,181, 85, 2, 97, 1, 50,254,206,253,159, 3, 7,247,119,254,146, 75,254,146, 74,
+ 44, 76,247,187,119, 1, 50, 1, 50,119, 0, 0, 0, 2, 0, 41, 0,253, 4,168, 4, 49, 0, 12, 0, 20, 0, 0, 19, 39, 55, 33,
+ 53, 55, 51, 1, 7, 1, 35, 53, 33, 55, 7, 33, 21, 9, 1, 21, 33,156,114, 38, 2,106, 38, 83, 1,116, 38,254,140, 83,253,112,
+184, 87, 2,108, 1, 54,254,202,253,148, 2,113,251, 77, 44, 76,254,140, 76,254,140,121,251,190,121, 1, 55, 1, 55,121, 0, 0,
+ 0, 1, 0,145, 0,189, 4, 64, 4,172, 0, 33, 0, 0, 19, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 21, 20, 7, 6,
+ 7, 6, 7, 6, 35, 34, 39, 38, 39, 38, 39, 33, 21, 9, 1, 21,145, 32, 54, 73, 89, 90,103, 98, 94, 85, 77, 73, 37, 38, 38, 34,
+ 76, 70, 92, 90,102, 99, 94, 85, 77, 51, 33, 1,231, 1,116,254,140, 3,167, 58, 54, 73, 38, 38, 38, 35, 76, 72, 90, 90,104, 99,
+ 92, 85, 77, 72, 39, 38, 38, 35, 76, 50, 60,129, 1,116, 1,116,128, 0, 0, 0, 0, 9, 0, 88, 1, 78, 4,121, 3, 22, 0, 3,
+ 0, 7, 0, 11, 0, 15, 0, 30, 0, 34, 0, 38, 0, 42, 0, 46, 0, 0, 1, 7, 51, 55, 35, 7, 51, 55, 35, 7, 51, 55, 35, 7,
+ 51, 55, 35, 53, 39, 33, 23, 33, 53, 22, 23, 6, 7, 53, 33, 7, 33, 1, 51, 39, 35, 23, 51, 39, 35, 23, 51, 39, 35, 23, 51, 39,
+ 35, 2, 8,114, 43,113,127,114, 42,114,128,114, 43,114,128,114, 43,114, 86,133, 1,128,133, 1, 22,123,139,139,123,254,234,133,
+254,128, 1,176, 42,113, 43, 29, 42,114, 42, 28, 43,114, 43, 29, 43,114, 43, 2, 21,171,171,171,171,171,171,171,171, 57,199,199,
+198,134, 92, 93,134,198,199, 1, 0,171,171,171,171,171,171,171, 0, 3, 0,116, 0,185, 4, 93, 4,162, 0, 12, 0, 16, 0, 20,
+ 0, 0, 1, 55, 6, 21, 20, 23, 38, 35, 34, 7, 55, 39, 55, 9, 1, 35, 1, 37, 53, 1, 21, 3,178,142, 6, 35,116,133, 54, 57,
+143,207, 46,254,119, 1, 90,230,254,166, 1, 21, 1, 89, 1,147,143, 57, 54,133,116, 34, 6,143,207, 46, 1, 42,254,168, 1, 88,
+ 47,230,254,167,229, 0, 0, 0, 0, 3, 0, 83, 1,209, 4,126, 3,107, 0, 8, 0, 12, 0, 16, 0, 0, 1, 53, 22, 23, 6, 7,
+ 53, 33, 53, 5, 33, 7, 33, 55, 39, 33, 23, 3,141,110,130,130,110,255, 0,254, 85, 1,170,142,254, 86,142,142, 1,170,142, 2,
+186,177,134, 71, 71,134,177, 56, 58,142,200,143,143, 0, 0, 0, 0, 3, 0,117, 0,129, 4, 92, 4,106, 0, 12, 0, 16, 0, 20,
+ 0, 0, 1, 39, 22, 51, 50, 55, 6, 21, 20, 23, 39, 7, 39, 9, 1, 21, 1, 3, 35, 1, 51, 3,131,142, 57, 53,133,116, 34, 5,
+142,207, 46,254,214, 1, 89,254,167, 47,230, 1, 89,230, 3,191,143, 6, 34,117,132, 54, 57,143,207, 46,254,120, 1, 88,230,254,
+168, 1, 21, 1, 88, 0, 0, 0, 0, 1, 0, 78, 0,185, 4,131, 4,238, 0, 50, 0, 0, 37, 38, 35, 34, 7, 54, 55, 54, 55, 1,
+ 38, 39, 38, 34, 7, 6, 7, 1, 54, 55, 54, 51, 50, 23, 22, 23, 38, 39, 38, 53, 52, 55, 54, 55, 1, 6, 7, 6, 21, 20, 23, 22,
+ 23, 1, 54, 55, 54, 55, 6, 21, 20, 4,130,125,144, 58, 60, 63, 77, 35, 21,254,246, 25, 31, 33, 68, 34, 32, 24,254,141, 31, 36,
+ 40, 42, 38, 42, 38, 29, 29, 15, 17, 17, 15, 29, 1,115, 28, 9, 12, 12, 13, 24, 1, 10, 3, 14, 32, 63, 6,186, 36, 6, 62, 34,
+ 14, 2, 1, 9, 26, 12, 13, 13, 13, 25, 1,115, 32, 14, 16, 16, 15, 31, 31, 37, 42, 38, 42, 40, 38, 30,254,140, 29, 27, 34, 33,
+ 35, 33, 30, 26,254,247, 20, 34, 79, 62, 62, 59,142, 0, 0, 0, 0, 1, 0, 42, 1,137, 4,167, 3, 69, 0, 47, 0, 0, 1, 6,
+ 7, 52, 55, 54, 55, 33, 34, 7, 6, 7, 6, 7, 6, 21, 33, 52, 55, 54, 55, 54, 55, 54, 51, 34, 39, 38, 39, 38, 39, 38, 53, 33,
+ 20, 23, 22, 23, 22, 23, 22, 51, 33, 38, 39, 38, 53, 22, 4,166,140,118, 28, 12, 11,254,184, 31, 27, 28, 22, 21, 12, 12,254, 53,
+ 13, 15, 26, 24, 36, 32, 37, 37, 32, 36, 24, 26, 15, 13, 1,203, 12, 12, 21, 22, 28, 27, 31, 1, 72, 11, 12, 28,118, 2,103, 77,
+144, 77, 69, 30, 14, 11, 12, 22, 20, 30, 27, 31, 37, 33, 35, 25, 24, 16, 14, 14, 16, 24, 26, 34, 33, 37, 31, 27, 30, 20, 22, 12,
+ 11, 14, 30, 69, 77,144, 0, 0, 0, 1, 0,117, 0,175, 4, 92, 4,151, 0, 50, 0, 0, 1, 6, 21, 20, 23, 38, 39, 38, 39, 7,
+ 6, 7, 6, 21, 20, 23, 22, 23, 1, 38, 39, 38, 53, 52, 55, 54, 55, 6, 7, 6, 35, 34, 39, 38, 39, 1, 22, 23, 22, 50, 55, 54,
+ 63, 1, 38, 39, 38, 39, 22, 51, 50, 4, 92, 34, 6, 58, 30, 13, 4,246, 25, 10, 11, 11, 12, 23,254,168, 28, 14, 15, 15, 14, 28,
+ 28, 35, 39, 36, 39, 36, 35, 28, 1, 89, 22, 30, 31, 64, 31, 28, 24,246, 20, 31, 73, 58, 56, 54,134, 4,151,115,133, 54, 58, 58,
+ 73, 32, 18,246, 27, 25, 31, 31, 31, 32, 29, 23,254,167, 27, 35, 38, 39, 35, 39, 34, 29, 29, 13, 15, 15, 14, 28, 1, 88, 22, 13,
+ 12, 12, 12, 23,247, 2, 13, 31, 58, 6, 0, 0, 0, 3, 0, 53, 1, 42, 4,156, 3,236, 0, 22, 0, 43, 0, 66, 0, 0, 1, 54,
+ 55, 6, 7, 6, 7, 6, 7, 6, 34, 39, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 36, 52, 55, 54, 55, 54, 55, 54, 50, 23, 4,
+ 5, 4, 7, 6, 34, 39, 38, 39, 38, 39, 37, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 55, 54, 50, 23, 22, 23, 22, 23, 22, 23,
+ 36, 3, 3,184,224,170, 91, 9, 16, 17, 20, 19, 47, 19, 21, 16, 16, 9, 8, 8, 9, 16, 16,253, 72, 11, 13, 20, 22, 27, 26, 61,
+ 27, 1, 8, 2,141,253, 97,246, 27, 61, 26, 31, 18, 22, 11, 2,194, 21, 16, 16, 9, 8, 8, 9, 16, 16, 21, 19, 47, 19, 20, 17,
+ 13, 12, 90,171,254,239, 2, 4, 73, 61, 88,194, 22, 15, 15, 10, 8, 8, 10, 15, 15, 22, 20, 24, 22, 20, 22, 15, 16,113, 62, 26,
+ 30, 19, 21, 12, 12, 11,100, 40, 42, 99, 10, 11, 14, 19, 24, 25,193, 9, 15, 16, 21, 21, 22, 23, 21, 21, 15, 16, 9, 8, 8, 9,
+ 16, 12, 24,194, 88, 74, 0, 0, 0, 2, 0, 29, 1,110, 4,180, 3,176, 0, 26, 0, 46, 0, 0, 19, 54, 55, 54, 55, 54, 55, 54,
+ 51, 50, 23, 22, 23, 22, 5, 4, 7, 14, 1, 35, 34, 39, 38, 39, 38, 39, 38, 37, 38, 39, 38, 53, 52, 55, 54, 55, 22, 23, 6, 7,
+ 38, 39, 38, 53, 52, 55, 54, 29, 53, 24, 26, 16, 32, 32, 35, 38, 43, 42, 49, 41,132, 1, 70,254,186,132, 45, 89, 41, 41, 32, 46,
+ 18, 23, 19, 23, 3, 69, 30, 15, 16, 16, 15, 30, 79,205,205, 79, 30, 15, 16, 16, 15, 2,143, 31, 47, 51, 16, 29, 15, 15, 15, 18,
+ 26, 83, 62, 62, 83, 28, 31, 15, 24, 20, 29, 38, 47, 31, 32, 35, 36, 41, 41, 37, 35, 31,195, 93, 93,195, 31, 35, 37, 41, 41, 36,
+ 35, 0, 0, 0, 0, 1, 0, 38, 1,190, 4,171, 3,166, 0,101, 0, 0, 0, 20, 6, 15, 1, 6, 7, 6, 34, 39, 38, 39, 46, 1,
+ 53, 52, 63, 1, 54, 53, 52, 39, 38, 39, 38, 39, 38, 43, 1, 34, 7, 6, 7, 6, 15, 1, 6, 7, 6, 7, 6, 35, 33, 34, 46, 2,
+ 52, 63, 1, 54, 52, 47, 1, 38, 52, 54, 55, 54, 55, 54, 51, 33, 50, 23, 22, 23, 22, 31, 1, 22, 23, 22, 23, 22, 59, 1, 50, 55,
+ 54, 55, 54, 55, 54, 53, 52, 47, 1, 38, 53, 52, 54, 55, 54, 55, 54, 50, 23, 22, 31, 1, 22, 4,171, 5, 5,195, 3, 7, 6, 13,
+ 6, 5, 5, 5, 5, 2, 22, 3, 3, 2, 5, 4, 6, 7, 6,229, 6, 6, 6, 5, 4, 3, 73, 4, 3, 4, 7, 5, 6,254, 14, 6,
+ 11, 10, 5, 2, 93, 3, 3, 93, 2, 5, 5, 5, 5, 6, 6, 1,242, 6, 5, 7, 4, 3, 4, 73, 3, 4, 5, 6, 6, 6,229, 6,
+ 7, 6, 4, 5, 2, 3, 3, 22, 2, 5, 5, 5, 5, 6, 13, 6, 7, 3,195, 5, 2,185, 14, 12, 5,195, 3, 4, 2, 2, 3, 4,
+ 5, 12, 7, 3, 9, 81, 9, 4, 5, 6, 6, 5, 4, 3, 3, 2, 4, 4, 4, 6,146, 9, 2, 4, 3, 3, 5, 10, 11, 15, 5,185,
+ 5, 16, 5,185, 5, 15, 11, 5, 4, 3, 3, 3, 2, 5, 2, 9,146, 6, 4, 4, 4, 2, 3, 3, 4, 5, 6, 6, 5, 4, 9, 81,
+ 9, 3, 7, 12, 5, 4, 3, 2, 2, 4, 3,195, 5, 0, 0, 0, 0, 1, 0, 37, 1,101, 4,171, 3,241, 0,103, 0, 0, 0, 20,
+ 7, 6, 7, 1, 6, 7, 6, 34, 39, 38, 39, 46, 1, 53, 52, 63, 1, 54, 53, 52, 39, 38, 39, 38, 39, 38, 43, 1, 34, 7, 6, 7,
+ 6, 15, 1, 6, 7, 6, 7, 6, 35, 33, 34, 46, 2, 52, 63, 1, 54, 52, 47, 1, 38, 52, 54, 55, 54, 55, 54, 51, 33, 50, 23, 22,
+ 23, 22, 31, 1, 22, 23, 22, 23, 22, 59, 1, 50, 55, 54, 55, 54, 55, 54, 53, 52, 47, 1, 38, 53, 52, 54, 55, 54, 55, 54, 50, 23,
+ 22, 23, 1, 22, 23, 4,171, 2, 3, 5,254,187, 4, 6, 6, 13, 6, 5, 5, 5, 5, 2, 71, 3, 3, 2, 5, 4, 7, 6, 6, 75,
+ 6, 6, 6, 4, 5, 3, 97, 4, 3, 5, 6, 5, 7,253,231, 7, 11, 10, 5, 3,117, 2, 2,126, 2, 5, 5, 5, 5, 6, 6, 2,
+ 26, 7, 5, 7, 4, 3, 4,105, 3, 5, 4, 6, 6, 6, 75, 6, 6, 7, 4, 5, 2, 3, 3, 71, 2, 5, 5, 5, 5, 6, 13, 6,
+ 6, 4, 1, 69, 5, 3, 2,178, 14, 6, 6, 5,254,220, 4, 3, 3, 3, 3, 4, 5, 11, 7, 6, 7,178, 6, 7, 5, 6, 7, 4,
+ 4, 3, 3, 2, 4, 4, 4, 6,195, 8, 3, 4, 3, 3, 5, 10, 11, 15, 5,234, 5, 16, 5,250, 5, 15, 11, 5, 4, 3, 3, 3,
+ 2, 5, 2, 9,211, 6, 4, 4, 4, 2, 3, 3, 4, 4, 7, 6, 5, 7, 6,178, 7, 6, 7, 11, 5, 4, 3, 3, 3, 3, 4,254,
+220, 5, 6, 0, 0, 3, 0, 50, 1, 12, 4,159, 3,178, 0, 19, 0, 31, 0, 43, 0, 0, 1, 6, 7, 6, 7, 35, 55, 54, 55, 54,
+ 55, 38, 39, 38, 47, 1, 51, 22, 23, 22, 1, 35, 54, 55, 54, 55, 33, 53, 33, 6, 7, 6, 3, 22, 23, 22, 23, 33, 53, 33, 38, 39,
+ 38, 39, 4,159,103, 63,106, 55, 82, 8, 61,121, 29, 54, 54, 29,121, 61, 8, 82, 54,107, 63,254, 86, 79, 14, 18, 23, 32,253,156,
+ 2,241, 83, 43, 13, 10, 10, 13, 43, 83,253, 15, 2,100, 32, 23, 18, 14, 2, 95, 56, 61,101,121, 17,139,117, 27, 39, 38, 28,117,
+138, 17,116,106, 60,254,117, 44, 42, 52, 52, 71,101,101, 29, 2,135, 29, 29,101,101, 71, 51, 53, 42, 43, 0, 0, 0, 3, 0,117,
+254, 35, 4, 92, 6,117, 0, 3, 0, 6, 0, 9, 0, 0, 9, 5, 33, 9, 1, 33, 2,104, 1,244,254, 12,254, 13, 1,243,254,152,
+ 2,209,254,151, 1,105,253, 47, 6,117,251,219,251,211, 4, 45, 3, 49,253, 8,252,142, 3, 0, 0, 1, 1,134,254,242, 3, 75,
+ 6, 18, 0, 5, 0, 0, 9, 1, 51, 9, 1, 35, 1,135, 1, 25,170,254,231, 1, 25,170, 2,130, 3,144,252,112,252,112, 0, 0,
+ 0, 1, 1,134,254,242, 3, 75, 6, 18, 0, 5, 0, 0, 9, 1, 35, 9, 1, 51, 3, 74,254,231,170, 1, 25,254,231,170, 2,130,
+252,112, 3,144, 3,144, 0, 0, 0, 1, 0,117,254, 35, 4, 92, 6,117, 0, 3, 0, 0, 9, 3, 2,104, 1,244,254, 12,254, 13,
+ 6,117,251,219,251,211, 4, 45, 0, 1, 0, 88, 0,113, 4,121, 4,147, 0, 19, 0, 0, 1, 17, 51, 17, 51, 21, 35, 17, 35, 17,
+ 35, 17, 35, 17, 35, 53, 51, 17, 51, 17, 2,220,168,245,245,168,232,168,244,244,168, 2,215, 1,188,254, 68,170,254, 68, 1,188,
+254, 68, 1,188,170, 1,188,254, 68, 0, 0, 0, 0, 1, 0, 88, 0,113, 4,121, 4,147, 0, 27, 0, 0, 19, 17, 51, 17, 51, 17,
+ 51, 17, 51, 17, 51, 17, 51, 21, 35, 17, 35, 17, 35, 17, 35, 17, 35, 17, 35, 17, 35, 53,202,168,162,168,162,168,115,115,168,162,
+168,162,168,114, 2,215, 1,188,254, 68, 1,188,254, 68, 1,188,254, 68,170,254, 68, 1,188,254, 68, 1,188,254, 68, 1,188,170,
+255,255, 0,150, 0,174, 4, 59, 4, 84, 16, 6, 0,153, 0, 0, 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 3, 0, 7, 0, 0,
+ 55, 33, 17, 33, 3, 17, 33, 17,120, 3,225,252, 31,114, 4,197, 36, 1,240,253,158, 4,196,251, 60, 0, 0, 0, 0, 2, 0, 6,
+255,177, 4,203, 4,119, 0, 3, 0, 7, 0, 0, 19, 33, 17, 33, 3, 17, 33, 17,120, 3,225,252, 31,114, 4,197, 2, 20, 1,240,
+251,174, 4,196,251, 60, 0, 0, 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 2, 0, 6, 0, 0, 55, 33, 1, 3, 17, 33, 17,120,
+ 3,225,252, 31,114, 4,197, 36, 3,224,251,174, 4,196,251, 60, 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 2, 0, 6, 0, 0,
+ 37, 17, 33, 3, 17, 33, 17, 4, 89,252, 31,114, 4,197, 36, 3,224,251,174, 4,196,251, 60, 0, 0, 2, 0, 6,255,177, 4,203,
+ 4,119, 0, 2, 0, 6, 0, 0, 37, 9, 5, 2,104, 1,203,254, 53,253,158, 2, 98, 2, 99,253,157, 74, 1,202, 1,202,254, 54,
+ 2, 98,253,158,253,158, 0, 0, 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 2, 0, 6, 0, 0, 19, 1, 17, 9, 3,158, 1,202,
+253,158, 2, 98, 2, 99,253,157, 2, 20,254, 54, 3,148,254, 54, 2, 98,253,158,253,158, 0, 0, 0, 2, 0, 6,255,177, 4,203,
+ 4,119, 0, 2, 0, 6, 0, 0, 19, 9, 1, 33, 9, 2,158, 1,202, 1,203,251,211, 2, 98, 2, 99,253,157, 2, 20,254, 54, 1,
+202, 2, 98,253,158,253,158, 0, 0, 2, 0, 6,255,177, 4,203, 4,119, 0, 2, 0, 6, 0, 0, 19, 33, 9, 4,158, 3,149,254,
+ 53,253,158, 2, 98, 2, 99,253,157, 2, 20, 1,202,254, 54, 2, 98,253,158,253,158, 0, 0, 0, 0, 12, 0, 6,255,177, 4,203,
+ 4,119, 0, 5, 0, 9, 0, 13, 0, 17, 0, 21, 0, 27, 0, 31, 0, 35, 0, 41, 0, 45, 0, 49, 0, 55, 0, 0, 37, 21, 35, 53,
+ 51, 53, 19, 21, 35, 53, 19, 21, 35, 53, 3, 21, 35, 53, 35, 21, 35, 53, 39, 21, 51, 21, 35, 53, 19, 21, 35, 53, 19, 21, 35, 53,
+ 1, 21, 35, 53, 35, 53, 35, 21, 35, 53, 35, 21, 35, 53, 35, 21, 35, 21, 35, 53, 4,203,205, 90,115,115,115,115,244,174,154,180,
+240, 86,200,114,114,114,114, 4,197,115, 90,154,174,154,180,154, 86,114,126,204,114, 90, 1, 72,174,174, 1, 78,179,179,253, 16,
+114,114,114,114, 90, 90,114,204, 1, 72,174,174, 1, 78,179,179, 1, 98,200, 86,114,114,114,114,114,114, 86,200, 0, 1, 0,137,
+ 0, 0, 4, 72, 5,213, 0, 7, 0, 0, 19, 51, 17, 33, 21, 33, 17, 35,137,203, 2,244,253, 12,203, 5,213,253,156,170,253, 57,
+ 0, 1, 0,195, 0, 0, 4, 26, 4, 96, 0, 7, 0, 0, 1, 17, 35, 17, 51, 17, 33, 21, 1,123,184,184, 2,159, 2, 3,253,253,
+ 4, 96,254, 57,150, 0, 0, 0, 0, 2, 0, 76,255,231, 4,133, 4,104, 0, 10, 0, 39, 0, 0, 1, 34, 21, 17, 50, 55, 54, 53,
+ 52, 39, 38, 39, 50, 23, 22, 17, 16, 7, 6, 35, 7, 34, 39, 38, 17, 16, 55, 54, 55, 21, 6, 7, 6, 21, 20, 23, 22, 51, 17, 16,
+ 3, 5, 65, 92, 86, 77, 77, 71, 42,138,119,127,127,129,193,183,199,124,126,126,104,154, 65, 49, 76, 76, 78,101, 3,203,145,253,
+ 82,104, 93,223,221, 99, 91,157,132,141,254,217,254,230,150,152, 1,153,155, 1, 20, 1, 44,132,109, 28,163, 26, 75,115,190,216,
+101,103, 2,175, 1, 46, 0, 0, 0, 3, 0,193,255,229, 3,221, 5,213, 0, 23, 0, 27, 0, 37, 0, 0, 1, 51, 17, 54, 55, 54,
+ 55, 21, 6, 7, 6, 35, 34, 39, 38, 53, 52, 55, 54, 63, 1, 62, 1, 53, 19, 21, 35, 53, 19, 17, 7, 6, 7, 6, 21, 20, 23, 22,
+ 2, 37,190, 31, 32, 89, 98, 94, 96, 95,104,186,111,110, 34, 33, 94, 88, 69, 38,197,203, 6, 45, 62, 23, 24, 66, 37, 4, 68,252,
+ 83, 8, 12, 35, 68,188, 57, 28, 28, 96, 96,161, 76, 65, 66, 92, 86, 66, 84, 61, 2, 59,254,254,250,190, 1,174, 45, 59, 44, 44,
+ 49, 89, 55, 31,255,255, 0,218, 0, 0, 3,247, 5,240, 16, 6, 3,222, 0, 0, 0, 2, 0,137,255,227, 4, 72, 6, 21, 0, 11,
+ 0, 37, 0, 0, 1, 34, 6, 21, 20, 22, 51, 50, 54, 53, 52, 38, 39, 54, 18, 17, 16, 2, 35, 34, 2, 17, 52, 54, 55, 46, 1, 53,
+ 52, 54, 51, 37, 21, 33, 34, 21, 20, 22, 2,104,140,144,144,140,141,144,144,141,232,248,246,234,233,246,123, 49, 80, 65,194,158,
+ 1,252,254, 40,188,114, 3,223,218,214,213,219,219,213,214,218,156, 1,254,209,254,226,254,225,254,211, 1, 45, 1, 31,229,216,
+ 42, 47,142, 49,124,148, 1,150,135, 73, 53, 0, 0, 2, 0, 35, 0, 0, 4, 55, 6, 20, 0, 3, 0, 25, 0, 78, 64, 42, 20, 9,
+ 22, 2, 18, 14,182, 10, 5,140, 4, 2,196, 0,155, 4,155, 10,194, 16, 12, 6, 25, 9, 4, 13, 0, 6, 1, 4, 15, 9, 6, 11,
+ 1, 74, 19, 69, 21, 17, 69, 26, 16,244, 60,228,236, 50,252, 60,196, 16,238, 50, 17, 18, 57, 57, 49, 0, 47, 60,230,236,254,238,
+ 16,238, 16,238, 50, 18, 57, 57, 57, 48, 1, 51, 21, 35, 39, 21, 35, 34, 6, 29, 1, 33, 17, 35, 17, 33, 17, 35, 17, 35, 53, 51,
+ 53, 52, 54, 51, 3,127,184,184,119,180, 99, 77, 2,147,184,254, 37,184,201,201,169,179, 6, 18,233,235,153, 81,103,101,251,162,
+ 3,209,252, 47, 3,209,143, 78,184,174, 0, 0, 0, 1, 0, 35, 0, 0, 4, 55, 6, 20, 0, 21, 0, 66, 64, 35, 16, 7, 18, 3,
+ 14, 10,182, 8, 3,140, 0,155, 8,194, 12, 1, 4, 21, 9, 7, 2, 6, 0, 9, 11, 7, 6, 0, 74, 15, 69, 17, 13, 69, 22, 16,
+244, 60,228,236,252, 60,196, 16,238, 17, 18, 57, 57, 49, 0, 47, 60,230,254,238, 16,238, 50, 18, 57, 57, 57, 48, 1, 17, 35, 17,
+ 33, 34, 6, 29, 1, 33, 21, 33, 17, 35, 17, 35, 53, 51, 53, 52, 54, 51, 4, 55,184,254,213, 99, 77, 1, 37,254,219,184,201,201,
+169,179, 6, 20,249,236, 5,123, 81,103,101,141,252, 47, 3,209,143, 78,184,174,255,255, 0, 69,254, 12, 4,176, 2, 27, 16, 38,
+ 4, 30, 0, 0, 16, 7, 11,204, 2, 30,255, 6,255,255, 0, 69,254, 12, 4,229, 2, 28, 16, 38, 11,198, 0, 0, 16, 7, 11,204,
+ 1,252,255, 6,255,255,255,236,254, 12, 2,188, 2, 88, 16, 38, 10,217, 0, 0, 16, 7, 11,204, 2, 12,255, 6,255,255,255,236,
+254, 12, 4,229, 2, 88, 16, 38, 10,218, 0, 0, 16, 7, 11,204, 2, 12,255, 6,255,255, 0, 69,254, 12, 4,176, 2, 27, 16, 38,
+ 4, 30, 0, 0, 16, 7, 11,203, 1,189,255, 6,255,255, 0, 69,254, 12, 4,229, 2, 28, 16, 38, 11,198, 0, 0, 16, 7, 11,203,
+ 1,120,255, 6,255,255,255,236,254, 12, 3, 28, 2, 88, 16, 38, 10,217, 0, 0, 16, 7, 11,203, 1,140,255, 6,255,255,255,236,
+254, 12, 4,229, 2, 88, 16, 38, 10,218, 0, 0, 16, 7, 11,203, 1,140,255, 6,255,255, 0, 69,254, 12, 4,176, 2, 27, 16, 38,
+ 4, 30, 0, 0, 16, 7, 11,205, 1,147,255, 6,255,255, 0, 69,254, 12, 4,229, 2, 28, 16, 38, 11,198, 0, 0, 16, 7, 11,205,
+ 1,114,255, 6,255,255,255,236,254, 12, 3, 10, 2, 88, 16, 38, 10,217, 0, 0, 16, 7, 11,205, 1,122,255, 6,255,255,255,236,
+254, 12, 4,229, 2, 88, 16, 38, 10,218, 0, 0, 16, 7, 11,205, 1,152,255, 6,255,255, 0, 69,255,235, 4,176, 3,189, 16, 38,
+ 4, 30, 0, 0, 16, 7, 11,204, 2, 55, 3, 39,255,255, 0, 69,255,236, 4,229, 3,195, 16, 38, 11,198, 0, 0, 16, 7, 11,204,
+ 2, 1, 3, 45,255,255,255,236, 0, 0, 2,188, 4,120, 16, 38, 10,217, 0, 0, 16, 7, 11,204, 2, 16, 3,226,255,255,255,236,
+ 0, 0, 4,229, 4,109, 16, 38, 10,218, 0, 0, 16, 7, 11,204, 2, 15, 3,215,255,255, 0, 69,255,235, 4,176, 4, 26, 16, 38,
+ 4, 30, 0, 0, 16, 7, 11,205, 1,147, 3,132,255,255, 0, 69,255,236, 4,229, 4, 26, 16, 39, 11,205, 1,129, 3,132, 16, 6,
+ 11,198, 0, 0,255,255,255,236, 0, 0, 3, 31, 4,121, 16, 38, 10,217, 0, 0, 16, 7, 11,205, 1,143, 3,227,255,255,255,236,
+ 0, 0, 4,229, 4,124, 16, 38, 10,218, 0, 0, 16, 7, 11,205, 1,140, 3,230,255,255, 0, 69,255,235, 4,176, 4, 87, 16, 38,
+ 4, 30, 0, 0, 16, 7, 3,220, 0, 76,253,102,255,255, 0, 69,255,236, 4,229, 4, 72, 16, 39, 3,220, 0, 52,253, 87, 16, 6,
+ 11,198, 0, 0,255,255,255,236, 0, 0, 3,184, 4,245, 16, 38, 10,217, 0, 0, 16, 7, 3,220, 0, 75,254, 4,255,255,255,236,
+ 0, 0, 4,229, 5, 4, 16, 38, 10,218, 0, 0, 16, 7, 3,220, 0, 93,254, 19,255,255,255,181,255,164, 4,140, 5,114, 16, 38,
+ 4, 51, 0, 0, 16, 7, 11,197, 2,116, 3,226,255,255,255,106,255,164, 4,229, 5, 6, 16, 39, 11,197, 2,132, 3,118, 16, 6,
+ 11,202, 0, 0,255,255,255,236, 0, 0, 3, 63, 6, 14, 16, 39, 11,197, 1, 44, 4,126, 16, 6, 11,199, 0, 0,255,255,255,236,
+ 0, 0, 4,229, 5, 16, 16, 39, 11,197, 1,150, 3,128, 16, 6, 11,200, 0, 0,255,255,255,181,255,164, 4,140, 5,126, 16, 38,
+ 4, 51, 0, 0, 16, 7, 11,205, 2,136, 4,232,255,255,255,106,255,164, 4,229, 5, 10, 16, 39, 11,205, 2,140, 4,116, 16, 6,
+ 11,202, 0, 0,255,255,255,236, 0, 0, 3, 63, 6, 14, 16, 39, 11,205, 1, 44, 5,120, 16, 6, 11,199, 0, 0,255,255,255,236,
+ 0, 0, 4,229, 5, 32, 16, 39, 11,205, 1,154, 4,138, 16, 6, 11,200, 0, 0,255,255, 0, 88,254, 11, 4,173, 3,103, 16, 38,
+ 3,235, 0, 0, 16, 7, 11,204, 2,123, 0,175,255,255, 0, 88,254, 11, 4,249, 3,103, 16, 38, 11, 16, 0, 0, 16, 7, 11,204,
+ 2, 47, 0,125,255,255,255,236,254, 62, 4, 92, 3, 47, 16, 39, 11,204, 1, 97,255, 56, 16, 6, 11, 17, 0, 0,255,255,255,236,
+254, 62, 4,252, 3, 47, 16, 39, 11,204, 2, 13,255, 56, 16, 6, 11, 18, 0, 0,255,255, 0, 88,254, 11, 4,173, 3,103, 16, 38,
+ 3,235, 0, 0, 16, 7, 11,196, 2,138, 0, 25,255,255, 0, 88,254, 11, 4,249, 3,103, 16, 38, 11, 16, 0, 0, 16, 7, 11,196,
+ 2, 38,255,231,255,255,255,236,255, 56, 4, 92, 3, 47, 16, 39, 11,196, 0,188,255, 56, 16, 6, 11, 17, 0, 0,255,255,255,236,
+255, 56, 4,252, 3, 47, 16, 39, 11,196, 1,144,255, 56, 16, 6, 11, 18, 0, 0,255,255, 0, 88,254, 11, 4,173, 3,103, 16, 38,
+ 3,235, 0, 0, 16, 7, 11,203, 2, 42, 0,150,255,255, 0, 88,254, 11, 4,249, 3,103, 16, 38, 11, 16, 0, 0, 16, 7, 11,203,
+ 1,197, 0, 66,255,255,255,236,254, 22, 4, 92, 3, 47, 16, 39, 11,203, 0,240,255, 16, 16, 6, 11, 17, 0, 0,255,255,255,236,
+254, 62, 4,252, 3, 47, 16, 39, 11,203, 1,144,255, 56, 16, 6, 11, 18, 0, 0,255,255, 0, 88,254, 11, 4,173, 3,103, 16, 38,
+ 3,235, 0, 0, 16, 7, 11,205, 2, 50, 0,175,255,255, 0, 88,254, 11, 4,249, 3,103, 16, 38, 11, 16, 0, 0, 16, 7, 11,205,
+ 1,197, 0, 94,255,255,255,236,254, 22, 4, 92, 3, 47, 16, 39, 11,205, 0,252,255, 16, 16, 6, 11, 17, 0, 0,255,255,255,236,
+254, 62, 4,252, 3, 47, 16, 39, 11,205, 1,144,255, 56, 16, 6, 11, 18, 0, 0,255,255,255,204,254, 8, 4, 97, 4, 55, 16, 38,
+ 3,239, 0, 0, 16, 7, 11,197, 2,208, 2,166,255,255,255, 96,254, 12, 4,229, 4, 68, 16, 39, 11,197, 2, 92, 2,180, 16, 6,
+ 11, 28, 0, 0,255,255,255,204,254, 8, 4,194, 4,155, 16, 39, 3,220, 1, 85,253,170, 16, 6, 3,239, 0, 0,255,255,255, 96,
+254, 12, 4,229, 4,132, 16, 39, 3,220, 0,233,253,147, 16, 6, 11, 28, 0, 0,255,255, 0, 10,255,167, 5, 93, 6, 20, 16, 6,
+ 4, 53, 0, 0, 0, 1,255,131,255,167, 5, 26, 6, 20, 0, 50, 0, 0, 37, 6, 7, 6, 7, 6, 35, 34, 39, 36, 17, 52, 55, 51,
+ 6, 21, 20, 23, 22, 51, 50, 54, 55, 54, 53, 52, 39, 3, 38, 53, 52, 55, 54, 55, 1, 21, 1, 6, 21, 20, 23, 1, 22, 59, 1, 21,
+ 35, 34, 39, 38, 39, 3,245, 25, 48, 81,128, 99,207,112,108,254,182, 63,184, 65,203, 79, 76,162,218, 54, 52, 41,182, 62, 18, 46,
+ 86, 2, 14,254,104, 70, 18, 1,100, 40, 40, 38, 42, 61, 35, 62, 20,182, 50, 40, 73, 61, 47, 32, 98, 1, 11,138, 92, 94,136,120,
+ 72, 28,106, 60, 57, 34, 49, 66, 1, 44,102, 37, 84, 31, 79, 65, 1,142,209,254,194, 55, 46, 78, 29,253,194, 63,184, 18, 30, 30,
+255,255,255,236, 0, 0, 4, 43, 6, 20, 16, 6, 11, 73, 0, 0,255,255,255,236, 0, 0, 4,230, 6, 20, 16, 6, 11, 74, 0, 0,
+255,255, 0, 10,255,167, 5, 99, 7, 71, 16, 38, 4, 53, 0, 0, 16, 7, 11,206, 2,172, 0, 14,255,255,255,131,255,167, 5, 26,
+ 7, 74, 16, 39, 11,206, 2, 84, 0, 18, 16, 6, 10,204, 0, 0,255,255,255,236, 0, 0, 4, 43, 7, 57, 16, 39, 11,207, 0,143,
+ 0, 0, 16, 6, 10,205, 0, 0,255,255,255,236, 0, 0, 4,230, 7, 57, 16, 39, 11,207, 0,156, 0, 0, 16, 6, 10,206, 0, 0,
+255,255, 0, 54,254,181, 4,141, 2,176, 16, 6, 4, 56, 0, 0, 0, 1,255,213,254, 12, 4,230, 2, 12, 0, 38, 0, 0, 1, 6,
+ 7, 6, 35, 34, 39, 38, 17, 52, 55, 51, 6, 21, 20, 23, 22, 51, 50, 55, 54, 55, 54, 53, 52, 39, 51, 22, 23, 22, 23, 22, 59, 1,
+ 21, 35, 34, 39, 6, 3,200, 71,142,140,129,172,123,234, 53,184, 55,161, 57,129, 84, 63,157, 58, 33,101,184, 17, 35, 34, 31, 35,
+ 86, 52, 94, 87, 14, 6,254,247,116, 60, 59, 63,120, 1, 18,174,142,174,142,180, 67, 24, 20, 51,167, 94,119,184,203, 51, 85, 84,
+ 56, 64,184, 48,173, 0, 0, 0,255,255, 0, 0,255,189, 4,147, 3,229, 16, 6, 4, 57, 0, 0, 0, 3, 0, 0,255,255, 4,242,
+ 3,229, 0, 38, 0, 54, 0, 68, 0, 0, 37, 51, 21, 33, 34, 39, 6, 7, 6, 39, 38, 53, 52, 55, 51, 6, 21, 20, 23, 22, 51, 50,
+ 55, 38, 39, 38, 53, 52, 55, 54, 23, 38, 39, 53, 22, 23, 22, 23, 22, 37, 54, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 21, 20, 23,
+ 22, 37, 22, 7, 6, 7, 22, 51, 50, 55, 54, 39, 38, 39, 38, 4,144, 98,254,136,190, 74,131,164,145, 68,118, 16,184, 14, 30, 45,
+ 40, 48,103, 58, 23, 18, 45, 48, 77, 44, 81,212,227,249, 71, 24,253,205, 36, 34, 39, 15, 22, 58, 65, 23, 22, 7, 21, 1, 71, 13,
+ 22, 25, 53, 28, 39,129, 13, 5, 5, 6, 20, 51,184,184, 52, 51, 1, 1, 37, 64,128, 75, 53, 58, 44, 43, 11, 16, 16, 67,102, 78,
+ 64, 84, 83, 90, 9, 39, 14,185, 65,182,200,231, 79, 29, 27, 64, 72, 61, 46, 37, 52, 45, 43, 35, 30, 37,118,188, 95, 85, 91, 49,
+ 21, 67, 31, 32, 34, 38, 95, 0,255,255,255,236,255,189, 3,227, 3,229, 16, 6, 11, 89, 0, 0, 0, 3,255,236, 0, 0, 4,242,
+ 3,229, 0, 28, 0, 44, 0, 58, 0, 0, 37, 38, 39, 38, 53, 52, 55, 54, 23, 38, 39, 53, 22, 23, 22, 23, 22, 7, 51, 21, 33, 34,
+ 39, 6, 43, 1, 53, 51, 50, 55, 54, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 21, 20, 23, 22, 37, 22, 7, 6, 7, 22, 51, 50, 55,
+ 54, 39, 38, 39, 38, 1, 92, 58, 23, 18, 45, 48, 77, 44, 81,212,227,249, 71, 24, 13,202,254, 32,190, 74,134,161,247,238, 70,226,
+ 36, 34, 39, 15, 22, 58, 65, 23, 22, 7, 21, 1, 71, 13, 22, 25, 53, 28, 39,129, 13, 5, 5, 6, 20, 51,200, 67,102, 78, 64, 84,
+ 83, 90, 9, 39, 14,185, 65,182,200,231, 79, 56,184, 52, 52,184, 85, 27, 64, 72, 61, 46, 37, 52, 45, 43, 35, 30, 37,118,188, 95,
+ 85, 91, 49, 21, 67, 31, 32, 34, 38, 95, 0, 0, 0, 1,255,236, 0, 0, 2,188, 2, 88, 0, 13, 0, 0, 37, 6, 33, 35, 53, 51,
+ 32, 55, 54, 61, 1, 51, 21, 20, 2, 96, 72,254,169,213,158, 1, 29, 44, 49,184, 86, 86,184, 44, 49,106,217,217,187, 0, 0, 0,
+ 0, 1,255,236, 0, 0, 4,229, 2, 88, 0, 20, 0, 0, 37, 6, 35, 33, 53, 33, 50, 55, 54, 61, 1, 51, 21, 20, 23, 22, 51, 33,
+ 21, 33, 34, 2, 94, 76,215,254,177, 1, 24,162, 44, 48,184, 50, 44,163, 1, 42,254,159,214, 86, 86,184, 44, 49,106,217,217,106,
+ 49, 44,184, 0,255,255, 0, 25,254,243, 4,209, 3, 28, 16, 6, 4, 2, 0, 0,255,255,255,123,254,240, 4,229, 2, 2, 16, 6,
+ 11, 94, 0, 0,255,255,255,236,254,212, 3, 23, 2, 88, 16, 39, 11,196, 1,135,254,212, 16, 6, 10,217, 0, 0,255,255,255,236,
+254,212, 4,229, 2, 88, 16, 39, 11,196, 1,147,254,212, 16, 6, 10,218, 0, 0,255,255, 1, 68, 4,186, 3,140, 6,154, 16, 6,
+ 4, 4, 0, 0,255,255,255,236, 0, 0, 4,229, 6,154, 16, 38, 4, 4, 0, 0, 16, 6, 3,249, 0, 0, 0, 0,255,255, 1, 68,
+ 4,186, 3,140, 6,253, 16, 6, 4, 5, 0, 0, 0, 1, 3, 34, 0, 0, 4,229, 1,107, 0, 13, 0, 0, 1, 20, 23, 22, 59, 1,
+ 21, 35, 34, 39, 38, 61, 1, 51, 3,218, 49, 44, 99, 75,130,142, 92, 87,184, 1, 76, 55, 49, 44,184, 92, 87,141, 43, 0, 0, 0,
+255,255, 1, 68,254, 22, 3,140,255,246, 16, 6, 4, 6, 0, 0,255,255, 1, 68, 4,186, 3,140, 5,170, 16, 6, 4, 7, 0, 0,
+255,255,255,236, 0, 0, 4,229, 5,170, 16, 38, 3,249, 0, 0, 16, 6, 4, 7, 0, 0, 0, 0,255,255, 1, 68, 4,185, 3,140,
+ 6,253, 16, 6, 4, 8, 0, 0,255,255,255,236, 0, 0, 4,229, 6,253, 16, 38, 3,249, 0, 0, 16, 6, 4, 8, 0, 0, 0, 0,
+255,255, 1, 68,254,232, 3,140,255,216, 16, 6, 4, 9, 0, 0,255,255,255,236,254,232, 4,229, 0,184, 16, 38, 3,249, 0, 0,
+ 16, 6, 4, 9, 0, 0, 0, 0,255,255, 1, 48, 4,202, 3,161, 6,244, 16, 6, 4, 10, 0, 0,255,255,255,236, 0, 0, 4,229,
+ 6,244, 16, 38, 3,249, 0, 0, 16, 6, 4, 10, 0, 0, 0, 0,255,255, 1, 86, 4,225, 3,122, 7, 6, 16, 6, 4, 11, 0, 0,
+255,255,255,236, 0, 0, 4,229, 7, 6, 16, 38, 4, 11, 0, 0, 16, 6, 3,249, 0, 0, 0, 0,255,255, 1,178, 0, 85, 4, 45,
+ 3,222, 16, 6, 3,223, 0, 0,255,255, 1, 0, 0, 0, 3,208, 7,131, 16, 38, 3,229, 0, 0, 16, 7, 4, 12, 0, 0, 1,194,
+255,255, 1, 0, 0, 0, 4,230, 7,131, 16, 39, 4, 12, 0, 0, 1,194, 16, 6, 10,252, 0, 0,255,255, 1,179, 0, 0, 3, 10,
+ 8, 58, 16, 38, 3,229, 0, 0, 16, 7, 4, 13,255,246, 1,194,255,255, 1,228, 0, 0, 4,230, 8, 58, 16, 39, 4, 13, 0, 39,
+ 1,194, 16, 6, 10,252, 0, 0,255,255, 0, 76,254, 12, 4, 51, 4,182, 16, 38, 4, 1, 0, 0, 16, 7, 4, 13, 0, 96,254, 62,
+255,255, 0, 90,254, 12, 4,229, 4,182, 16, 39, 4, 13, 0, 50,254, 62, 16, 6, 11, 92, 0, 0,255,255, 1,182,254, 12, 3, 13,
+ 6, 20, 16, 38, 3,229, 0, 0, 16, 6, 4, 14,249, 0, 0, 0,255,255, 2, 19,254, 12, 4,230, 6, 20, 16, 38, 4, 14, 86, 0,
+ 16, 6, 10,252, 0, 0, 0, 0,255,255, 0, 25,254,243, 4,209, 4, 87, 16, 38, 4, 2, 0, 0, 16, 7, 4, 13,255, 89,253,223,
+255,255,255,123,254,240, 4,229, 3, 96, 16, 39, 4, 13,254,228,252,232, 16, 6, 11, 94, 0, 0,255,255,255,236, 0, 0, 2,254,
+ 4,232, 16, 39, 4, 13,255,234,254,112, 16, 6, 10,217, 0, 0,255,255,255,236, 0, 0, 4,229, 4,232, 16, 39, 4, 13, 0, 0,
+254,112, 16, 6, 10,218, 0, 0,255,255, 2, 12, 0, 0, 2,196, 6, 20, 16, 6, 3,229, 0, 0, 0, 1, 2, 76, 0, 0, 4,230,
+ 6, 20, 0, 13, 0, 0, 1, 17, 51, 17, 20, 23, 22, 59, 1, 21, 33, 34, 39, 38, 2, 76,184, 50, 44,180,208,254,248,234, 80, 88,
+ 1,115, 4,161,251,107,106, 49, 44,184, 92,101,255,255, 0, 69,254,162, 4,176, 2, 27, 16, 38, 4, 30, 0, 0, 16, 7, 11,195,
+ 2, 27,254,162,255,255, 0, 69,254,162, 4,229, 2, 28, 16, 39, 11,195, 1,209,254,162, 16, 6, 11,198, 0, 0,255,255,255,236,
+254,212, 2,188, 2, 88, 16, 38, 10,217, 0, 0, 16, 7, 11,195, 1,248,254,212,255,255,255,236,254,212, 4,229, 2, 88, 16, 38,
+ 10,218, 0, 0, 16, 7, 11,195, 2, 20,254,212,255,255, 0,222,255,198, 3,243, 4, 26, 16, 38, 4, 0, 0, 0, 16, 7, 11,196,
+ 1,106, 3,132,255,255, 0,242, 0, 0, 4,229, 4, 26, 16, 39, 11,196, 1,198, 3,132, 16, 6, 11, 88, 0, 0,255,255, 0, 69,
+255,235, 4,176, 3, 32, 16, 38, 4, 30, 0, 0, 16, 7, 11,196, 1,191, 2,138,255,255, 0, 69,255,236, 4,229, 3, 32, 16, 39,
+ 11,196, 1,156, 2,138, 16, 6, 11,198, 0, 0,255,255,255,236, 0, 0, 3, 35, 3,232, 16, 39, 11,196, 1,147, 3, 82, 16, 6,
+ 10,217, 0, 0,255,255,255,236, 0, 0, 4,229, 3,232, 16, 39, 11,196, 1,147, 3, 82, 16, 6, 10,218, 0, 0,255,255, 0, 69,
+255,235, 4,176, 4, 26, 16, 38, 4, 30, 0, 0, 16, 7, 11,197, 1,186, 2,138,255,255, 0, 69,255,236, 4,229, 4, 26, 16, 39,
+ 11,197, 1,168, 2,138, 16, 6, 11,198, 0, 0,255,255,255,236, 0, 0, 3, 44, 4,226, 16, 38, 10,217, 0, 0, 16, 7, 11,197,
+ 1,156, 3, 82,255,255,255,236, 0, 0, 4,229, 4,188, 16, 38, 10,218, 0, 0, 16, 7, 11,197, 1,155, 3, 44,255,255, 0, 88,
+254, 11, 4,173, 3,103, 16, 38, 3,235, 0, 0, 16, 7, 11,195, 2,159, 0, 25,255,255, 0, 88,254, 11, 4,249, 3,103, 16, 39,
+ 11,195, 2,112,255,206, 16, 6, 11, 16, 0, 0,255,255,255,236,254,212, 4, 92, 3, 47, 16, 39, 11,195, 2, 13,254,212, 16, 6,
+ 11, 17, 0, 0,255,255,255,236,254,212, 4,252, 3, 47, 16, 39, 11,195, 2, 13,254,212, 16, 6, 11, 18, 0, 0,255,255, 0, 88,
+254, 11, 4,173, 3,103, 16, 6, 3,235, 0, 0, 0, 1, 0, 88,254, 11, 4,249, 3,103, 0, 46, 0, 0, 37, 51, 21, 35, 34, 39,
+ 38, 39, 38, 39, 6, 7, 6, 21, 20, 23, 22, 5, 50, 55, 21, 6, 7, 4, 39, 38, 53, 16, 55, 54, 55, 38, 7, 6, 7, 53, 36, 23,
+ 4, 23, 21, 6, 7, 23, 22, 23, 22, 4,209, 40, 49,129,123, 82, 61, 6, 73,114, 98,224, 74,129, 1, 19,193,212,150,250,254,148,
+169,131,212, 96,137,101,159,135, 95, 1, 20,195, 1, 36,196,109, 31, 29, 51, 72, 90,184,184,150,100,156, 15,178, 24, 80,183,252,
+138, 93,163, 1,118,184, 98, 1, 2,196,152,222, 1, 2,223,101, 52, 3, 22, 19, 41,184, 64, 1, 1, 53,154, 3, 10, 91,160, 95,
+119, 0, 0, 0, 0, 1,255,236, 0, 0, 4, 92, 3, 47, 0, 30, 0, 0, 1, 38, 39, 38, 39, 38, 7, 53, 54, 55, 50, 23, 4, 23,
+ 21, 6, 7, 6, 7, 6, 7, 6, 43, 1, 53, 51, 50, 55, 54, 55, 54, 3, 83, 83,103, 85,180, 82,161, 72, 75,162,172, 1, 2,220,
+ 76, 88,166, 74,145, 75,221,163,128,100,227,129,104,116, 94, 2, 29, 23, 23, 19, 16, 7, 6,184, 7, 1, 35, 52, 98,154, 24, 52,
+ 98, 66,129, 27, 80,184, 72, 58,106, 86, 0, 0, 0, 1,255,236, 0, 0, 4,252, 3, 47, 0, 41, 0, 0, 1, 4, 23, 21, 6, 7,
+ 22, 23, 22, 59, 1, 21, 35, 34, 39, 38, 39, 6, 7, 6, 7, 6, 43, 1, 53, 51, 50, 55, 54, 55, 54, 55, 38, 39, 38, 39, 38, 7,
+ 53, 54, 55, 50, 2,126, 1, 2,220, 65, 73, 50, 30,104, 54, 60, 80,151,124, 40, 59, 69, 41,145, 75,221,163,128,100,227,129,104,
+116, 94,101, 83,103, 85,180, 82,161, 72, 75,162, 3, 12, 52, 98,154, 20, 41, 78, 34,119,184,168, 54, 97, 46, 37,129, 27, 80,184,
+ 72, 58,106, 86, 35, 23, 23, 19, 16, 7, 6,184, 7, 1, 0, 0,255,255, 0, 88,254, 11, 4,173, 4,176, 16, 38, 3,235, 0, 0,
+ 16, 7, 11,195, 1,220, 4, 26,255,255, 0, 88,254, 11, 4,249, 4,176, 16, 39, 11,195, 1,216, 4, 26, 16, 6, 11, 16, 0, 0,
+255,255,255,236, 0, 0, 4, 92, 4, 76, 16, 39, 11,195, 2, 13, 3,182, 16, 6, 11, 17, 0, 0,255,255,255,236, 0, 0, 4,252,
+ 4, 76, 16, 39, 11,195, 2, 13, 3,182, 16, 6, 11, 18, 0, 0,255,255, 0,232,255,218, 3,232, 3,106, 16, 6, 3,237, 0, 0,
+ 0, 1, 0,232,255,218, 4,229, 3,106, 0, 32, 0, 0, 1, 52, 39, 38, 39, 35, 22, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39,
+ 21, 22, 51, 50, 55, 54, 55, 22, 59, 1, 53, 35, 34, 39, 38, 3,232, 82, 72,107,227,170, 69, 60, 8, 34,173, 34, 82,133,115,103,
+151, 94, 46,206, 94, 97,147, 83, 28, 99, 44, 82, 1,122,108,149,131,108,184,115,101, 93, 42, 27,115, 46, 9, 42,184, 38, 7, 31,
+130,130,184, 44, 82, 0, 0, 0,255,255, 0,232,255,218, 3,232, 4,176, 16, 38, 3,237, 0, 0, 16, 7, 11,195, 2, 12, 4, 26,
+255,255, 0,232,255,218, 4,229, 4,176, 16, 39, 11,195, 2, 21, 4, 26, 16, 6, 11, 24, 0, 0,255,255,255,204,254, 8, 4, 68,
+ 2, 34, 16, 6, 3,239, 0, 0, 0, 1,255, 96,254, 12, 4,229, 2, 38, 0, 24, 0, 0, 1, 51, 22, 23, 22, 23, 22, 59, 1, 21,
+ 35, 34, 39, 6, 5, 4, 33, 53, 32, 55, 36, 55, 54, 53, 52, 2,238,184, 30, 3, 10, 73, 42,101, 60,115,130, 50, 57,254,215,254,
+228,254, 32, 1,189,219, 0,255, 34, 10, 2, 38,112, 30,103, 77, 44,184, 62,253,158,151,184,128,149,197, 58, 72,126, 0, 0, 0,
+255,255,255,204,254, 8, 4, 68, 3,182, 16, 38, 3,239, 0, 0, 16, 7, 11,195, 3, 93, 3, 32,255,255,255, 96,254, 12, 4,229,
+ 3,182, 16, 39, 11,195, 2,239, 3, 32, 16, 6, 11, 28, 0, 0,255,255,255, 33,254, 20, 4,152, 2,238, 16, 6, 3,241, 0, 0,
+ 0, 1,254,213,254, 20, 4,229, 2,238, 0, 70, 0, 0, 5, 34, 39, 38, 39, 6, 7, 6, 7, 6, 39, 6, 7, 6, 7, 6, 35, 34,
+ 39, 38, 55, 54, 55, 51, 6, 23, 22, 23, 22, 51, 50, 55, 54, 55, 54, 39, 38, 47, 1, 51, 23, 22, 23, 22, 23, 22, 55, 54, 53, 51,
+ 6, 23, 22, 51, 50, 25, 1, 51, 17, 20, 23, 22, 59, 1, 21, 35, 34, 39, 6, 7, 6, 3, 52, 65, 25, 64, 26, 31, 69, 50, 74, 47,
+ 49, 8, 30, 37, 61, 71,113, 95,101,118, 18, 20, 60,164, 87, 5, 8, 33, 46, 48, 53, 50, 35, 26, 24, 2, 1, 16, 41,159, 18, 17,
+ 21, 49, 39, 47, 45, 37,164, 4, 37, 32, 42,105,164, 41, 44, 59, 8, 63,100, 60, 31, 71, 33, 29, 25, 67,126,109, 56, 40, 2, 2,
+ 80,168, 94,121, 77, 92,100,115,213,232,130,225,137,172, 43, 59, 72, 50,122,109,165, 94, 92,234,156,145, 35, 80, 3, 3,125,103,
+194,163,141,120, 1, 24, 1, 38,254,170,139, 41, 44,184, 96, 97, 19, 9, 0, 0, 0, 1,255,236,255,221, 4,148, 2,232, 0, 49,
+ 0, 0, 37, 34, 39, 38, 61, 1, 35, 21, 20, 7, 6, 43, 1, 21, 51, 50, 55, 54, 55, 22, 23, 22, 51, 50, 55, 54, 55, 22, 23, 22,
+ 51, 50, 55, 54, 55, 54, 53, 17, 35, 17, 16, 35, 34, 39, 38, 55, 35, 20, 7, 6, 1,230, 71, 21, 26,164, 70, 36, 76, 42, 70,101,
+ 59, 69, 21, 12, 44, 81, 50, 73, 51, 70, 31, 25, 65, 24, 66, 78, 22, 85, 33, 62,164,104, 43, 31, 38, 5,165, 37, 42,181, 84,100,
+ 79,156,192,118, 71, 35,184, 37, 44, 57, 63, 35, 64, 42, 56,109,126, 67, 25, 9, 34, 82,153,159, 1, 86,254,218,254,232,120,141,
+163,194,103,116, 0, 1,255,236,255,221, 4,230, 2,232, 0, 55, 0, 0, 1, 20, 23, 22, 51, 50, 25, 1, 51, 17, 20, 23, 22, 59,
+ 1, 21, 35, 34, 39, 6, 7, 6, 35, 34, 39, 38, 39, 6, 7, 6, 35, 34, 39, 38, 39, 6, 7, 6, 43, 1, 53, 51, 50, 55, 54, 61,
+ 1, 51, 21, 20, 23, 22, 50, 55, 54, 53, 2,209, 33, 29, 53,100,164, 42, 44, 34, 34, 64,101, 59, 54, 58, 22, 72, 79, 55, 42, 12,
+ 30, 70, 51, 53, 67, 37, 38, 24, 20, 70, 58, 68, 70, 42, 55, 31, 64,162, 26, 22, 96, 42, 37, 2, 82,166,138,120, 1, 24, 1, 38,
+254,170,139, 41, 44,184, 96, 88, 27, 10, 73, 54, 91,109, 56, 42, 54, 55, 53, 57, 44, 37,184, 35, 71,118,192,156, 79,100, 84,116,
+103,194, 0, 0,255,255,255, 33,254, 20, 4,152, 4,176, 16, 38, 3,241, 0, 0, 16, 7, 11,197, 1, 54, 3, 32,255,255,254,213,
+254, 20, 4,229, 4,176, 16, 39, 11,197, 0,236, 3, 32, 16, 6, 11, 32, 0, 0,255,255,255,236,255,221, 4,148, 4,176, 16, 39,
+ 11,197, 1,150, 3, 32, 16, 6, 11, 33, 0, 0,255,255,255,236,255,221, 4,230, 4,176, 16, 39, 11,197, 1, 82, 3, 32, 16, 6,
+ 11, 34, 0, 0,255,255,255, 16,254, 20, 4,192, 2,143, 16, 6, 3,243, 0, 0, 0, 2,254,197,254, 20, 4,229, 2,143, 0, 12,
+ 0, 71, 0, 0, 37, 51, 50, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 37, 20, 7, 22, 23, 22, 59, 1, 21, 35, 34, 47, 1, 6, 43,
+ 1, 34, 39, 38, 53, 20, 7, 6, 7, 6, 35, 34, 39, 38, 53, 52, 55, 51, 6, 21, 20, 23, 22, 55, 54, 55, 54, 53, 52, 39, 38, 39,
+ 51, 6, 23, 22, 23, 54, 55, 54, 51, 50, 23, 22, 1,253,129,140, 73,106, 40, 36, 63, 71,104, 75, 2, 61, 31, 16, 14, 46, 28, 39,
+ 59, 52,102, 28,172,136,218, 38, 52, 45, 47, 47, 51,102, 74,130, 90,125,101,172,104, 60, 50, 60, 67, 37, 64, 9, 33, 13,171, 1,
+ 14, 10, 40, 76, 49,146,150,171, 91, 87,184, 46, 68, 70, 45, 37, 33,109, 78, 78, 52, 71, 10, 13, 44,184, 94, 26,120, 30, 26, 16,
+175,131,129, 43, 86, 90,125,205,188,172,204,156,145, 50, 41, 3, 4, 59,103,139,104, 62,212, 72, 15, 55, 40, 50,128, 60,177, 82,
+ 78, 0, 0, 0, 0, 2,255,236, 0, 0, 4,193, 2,143, 0, 12, 0, 44, 0, 0, 37, 51, 50, 55, 54, 53, 52, 39, 38, 35, 34, 7,
+ 6, 3, 34, 39, 38, 39, 6, 43, 1, 53, 51, 50, 55, 54, 61, 1, 51, 21, 20, 22, 23, 54, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6,
+ 35, 2, 73,129,140, 73,106, 40, 36, 63, 71,104, 75, 82, 74, 78, 65, 39,102, 94,130, 75, 43, 37, 65,184, 18, 45, 76, 49,146,150,
+171, 91, 87,184,126,127,184, 46, 68, 70, 45, 37, 33,109, 78,254,216, 42, 35, 61,138,184, 44, 80,100,114, 78, 24, 80, 50,128, 60,
+177, 82, 78,121,190,109, 75, 0, 0, 2,255,236, 0, 0, 4,229, 2,143, 0, 12, 0, 54, 0, 0, 37, 51, 50, 55, 54, 53, 52, 39,
+ 38, 35, 34, 7, 6, 3, 34, 39, 38, 39, 6, 43, 1, 53, 51, 50, 55, 54, 61, 1, 51, 21, 20, 22, 23, 54, 55, 54, 51, 50, 23, 22,
+ 21, 20, 7, 22, 23, 22, 59, 1, 21, 35, 34, 47, 1, 6, 35, 1,253,129,140, 73,106, 40, 36, 63, 71,104, 75, 82, 74, 78, 65, 39,
+102, 68, 80, 26, 31, 42, 45,184, 18, 45, 76, 49,146,150,171, 91, 87, 31, 16, 14, 46, 28, 39, 59, 52,102, 28,172,136,184, 46, 68,
+ 70, 45, 37, 33,109, 78,254,216, 42, 35, 61,138,184, 46, 50,128,114, 78, 24, 80, 50,128, 60,177, 82, 78,121, 52, 71, 10, 13, 44,
+184, 94, 26,120,255,255,255, 16,254, 20, 4,192, 3, 52, 16, 38, 3,243, 0, 0, 16, 7, 11,195, 1, 79, 2,158,255,255,254,197,
+254, 20, 4,229, 3, 52, 16, 39, 11,195, 1, 4, 2,158, 16, 6, 11, 40, 0, 0,255,255,255,236, 0, 0, 4,193, 3,118, 16, 39,
+ 11,195, 1, 87, 2,224, 16, 6, 11, 41, 0, 0,255,255,255,236, 0, 0, 4,229, 3,104, 16, 39, 11,195, 1, 52, 2,210, 16, 6,
+ 11, 42, 0, 0,255,255, 0, 10, 0, 0, 4,164, 6, 20, 16, 6, 3,245, 0, 0, 0, 2, 0, 20, 0, 0, 4,229, 6, 20, 0, 12,
+ 0, 39, 0, 0, 37, 51, 50, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 37, 20, 7, 22, 59, 1, 21, 35, 34, 47, 1, 6, 35, 33, 35,
+ 53, 51, 17, 51, 17, 54, 55, 54, 51, 50, 23, 22, 2, 8,129,140, 73,106, 40, 36, 63, 71,104, 75, 2, 61, 42, 61, 37, 45, 58, 93,
+ 85, 28,125,149,253,251,178,178,184, 76, 49,146,150,171, 91, 87,184, 46, 68, 70, 45, 37, 33,109, 78, 78, 53, 70, 67,184, 79, 26,
+105,184, 5, 92,251, 14,128, 60,177, 82, 78, 0, 0, 2,255,236, 0, 0, 4,164, 6, 20, 0, 12, 0, 31, 0, 0, 37, 51, 50, 55,
+ 54, 53, 52, 39, 38, 35, 34, 7, 6, 19, 33, 35, 53, 51, 17, 51, 17, 54, 55, 54, 51, 50, 23, 22, 21, 20, 7, 6, 2, 44,129,140,
+ 73,106, 40, 36, 63, 71,104, 75,136,253,251,254,254,184, 76, 49,142,154,171, 91, 87,184,126,184, 46, 68, 70, 45, 37, 33,109, 78,
+254,216,184, 5, 92,251, 14,128, 60,177, 82, 78,121,190,109, 75, 0, 2,255,236, 0, 0, 4,229, 6, 20, 0, 12, 0, 39, 0, 0,
+ 37, 51, 50, 55, 54, 53, 52, 39, 38, 35, 34, 7, 6, 37, 20, 7, 22, 59, 1, 21, 35, 34, 47, 1, 6, 35, 33, 35, 53, 51, 17, 51,
+ 17, 54, 55, 54, 51, 50, 23, 22, 2, 8,129,140, 73,106, 40, 36, 63, 71,104, 75, 2, 61, 42, 61, 37, 45, 58, 93, 85, 28,125,149,
+253,251,218,218,184, 76, 49,146,150,171, 91, 87,184, 46, 68, 70, 45, 37, 33,109, 78, 78, 53, 70, 67,184, 79, 26,105,184, 5, 92,
+251, 14,128, 60,177, 82, 78, 0,255,255, 0, 10, 0, 0, 4,164, 6, 20, 16, 38, 3,245, 0, 0, 16, 7, 11,195, 2, 67, 3, 0,
+255,255, 0, 20, 0, 0, 4,229, 6, 20, 16, 39, 11,195, 2, 67, 3, 0, 16, 6, 11, 48, 0, 0,255,255,255,236, 0, 0, 4,164,
+ 6, 20, 16, 39, 11,195, 2, 67, 3, 0, 16, 6, 11, 49, 0, 0,255,255,255,236, 0, 0, 4,229, 6, 20, 16, 39, 11,195, 2, 67,
+ 3, 0, 16, 6, 11, 50, 0, 0,255,255, 0,122,254, 12, 4,183, 4, 42, 16, 6, 3,247, 0, 0, 0, 2, 0,148,254, 11, 4,244,
+ 3, 14, 0, 44, 0, 55, 0, 0, 51, 52, 55, 38, 39, 38, 53, 52, 55, 54, 55, 54, 50, 23, 22, 23, 22, 21, 20, 7, 6, 7, 22, 23,
+ 22, 59, 1, 21, 35, 32, 39, 6, 21, 20, 23, 22, 33, 50, 55, 21, 6, 7, 4, 39, 38, 0, 34, 7, 6, 21, 20, 23, 54, 55, 54, 39,
+148,187, 61, 38, 30, 13, 16,104, 89,238, 89,101, 19, 13, 69,118, 55, 68, 87, 95,148,224,208,254,183,248,154, 41,107, 1, 95,193,
+212,150,250,254, 82,157, 98, 1,169, 52, 30, 47, 70,134, 2, 1, 48,212,140, 50, 72, 57, 27, 31, 41, 55, 52, 45, 45, 51, 56, 38,
+ 34, 62, 56, 96, 19, 64, 37, 40,184,228,129,106,109, 61,158,118,184, 98, 1, 2,190,119, 3, 22, 7, 12, 32, 36, 65, 55, 46, 32,
+ 12, 0, 0, 0, 0, 1,255,236, 0, 0, 3,249, 4, 42, 0, 26, 0, 0, 55, 50, 55, 38, 39, 38, 53, 16, 55, 54, 51, 21, 34, 6,
+ 20, 23, 22, 51, 50, 55, 37, 21, 5, 4, 43, 1, 53, 61,161,202, 75, 52, 88,204,125,251,218,186, 62, 83, 70, 56, 73, 1, 32,254,
+ 92,254,162,178, 89,184, 93, 24, 59,100,140, 1, 8,125, 77,169,137,255, 52, 70, 33,129,184,197,164,184, 0, 0, 0, 2,255,236,
+ 0, 0, 4,229, 3, 14, 0, 36, 0, 47, 0, 0, 37, 6, 43, 1, 53, 51, 50, 55, 54, 55, 38, 39, 38, 53, 52, 55, 54, 55, 54, 50,
+ 23, 22, 23, 22, 21, 20, 7, 6, 7, 22, 23, 22, 59, 1, 21, 35, 34, 2, 34, 7, 6, 21, 20, 23, 54, 53, 52, 39, 2,104,194,202,
+240,218,107, 66, 59, 40, 97, 68, 30, 13, 16,104, 89,238, 89,102, 18, 13, 30, 77, 88, 31, 68, 61,112,219,241,202,168, 52, 30, 47,
+103,103, 47,185,185,184, 40, 36, 39, 85, 90, 39, 45, 31, 41, 55, 52, 45, 45, 51, 56, 41, 31, 45, 39, 98, 77, 31, 44, 40,184, 2,
+ 85, 7, 12, 32, 29, 95, 95, 29, 32, 12, 0, 0,255,255, 0,122,254, 12, 4,183, 5, 70, 16, 38, 3,247, 0, 0, 16, 7, 11,195,
+ 1,119, 4,176,255,255, 0,148,254, 11, 4,244, 4, 76, 16, 39, 11,195, 1,214, 3,182, 16, 6, 11, 56, 0, 0,255,255,255,236,
+ 0, 0, 3,249, 5, 70, 16, 39, 11,195, 1,119, 4,176, 16, 6, 11, 57, 0, 0,255,255,255,236, 0, 0, 4,229, 4, 76, 16, 39,
+ 11,195, 2, 27, 3,182, 16, 6, 11, 58, 0, 0,255,255,255,181,255,164, 4,140, 4,192, 16, 38, 4, 51, 0, 0, 16, 7, 11,195,
+ 2,240, 4, 42,255,255,255,106,255,164, 4,229, 4, 76, 16, 39, 11,195, 2,246, 3,182, 16, 6, 11,202, 0, 0,255,255,255,236,
+ 0, 0, 3, 63, 5, 20, 16, 39, 11,195, 1,169, 4,126, 16, 6, 11,199, 0, 0,255,255,255,236, 0, 0, 4,229, 4,126, 16, 39,
+ 11,195, 2, 34, 3,232, 16, 6, 11,200, 0, 0,255,255, 0, 31,254,124, 4,116, 5, 20, 16, 38, 4, 31, 0, 0, 16, 7, 11,196,
+ 2, 93, 4,126,255,255,255,237,254, 19, 4,229, 4, 1, 16, 39, 11,196, 2, 78, 3,107, 16, 6, 11,201, 0, 0,255,255,255,236,
+ 0, 0, 3, 63, 5, 20, 16, 38, 11,199, 0, 0, 16, 7, 11,196, 1, 44, 4,126,255,255,255,236, 0, 0, 4,229, 4,126, 16, 38,
+ 11,200, 0, 0, 16, 7, 11,196, 1,150, 3,232,255,255, 0, 8,255,200, 4,159, 6, 20, 16, 6, 3,252, 0, 0, 0, 2,255,161,
+255,200, 4,229, 6, 20, 0, 33, 0, 68, 0, 0, 1, 21, 6, 7, 6, 21, 20, 23, 22, 23, 22, 21, 20, 7, 6, 35, 34, 39, 53, 22,
+ 51, 50, 55, 54, 53, 52, 39, 38, 39, 38, 55, 54, 55, 54, 1, 35, 17, 16, 7, 6, 7, 6, 35, 34, 39, 38, 53, 52, 55, 35, 6, 21,
+ 20, 23, 22, 55, 54, 55, 54, 55, 22, 59, 1, 53, 35, 34, 39, 38, 53, 2, 20, 74, 38, 80, 14, 12, 68,102, 88, 82, 78, 66, 56, 68,
+ 45, 60, 57, 60, 78, 74, 18, 32, 1, 2, 75, 85, 2,130,184, 52, 74, 81, 98,117, 87,121,154, 14,184, 16,217,163,173,199,103, 79,
+ 91,113, 80,130, 75, 26, 44, 49, 4, 76, 82, 4, 14, 30, 33, 28, 18, 16, 10, 15, 88,110, 42, 39, 11, 88, 10, 26, 26, 30, 38, 17,
+ 16, 28, 47, 46, 81, 38, 43, 1,204,252, 79,254,249, 67, 95, 35, 38, 35, 45, 93, 44, 58, 53, 75,184, 76, 57, 2, 2, 53, 45, 78,
+123,184, 44, 49,106, 0, 0, 0, 0, 1,255,236, 0, 0, 4, 43, 6, 20, 0, 31, 0, 0, 41, 1, 53, 33, 50, 55, 54, 53, 52, 39,
+ 1, 38, 53, 52, 55, 54, 55, 1, 21, 5, 6, 7, 6, 21, 20, 23, 1, 22, 21, 20, 7, 6, 1,146,254, 90, 1,146,147, 46, 16, 54,
+254,202, 50, 10, 31,104, 2,233,253,173, 71, 21, 6, 31, 1, 19,102, 62, 95,184,104, 36, 36, 69, 66, 1,124, 61, 81, 30, 38,118,
+ 43, 1, 54,186,250, 30, 40, 11, 25, 32, 37,254,182,122,124,113,101,155, 0, 0, 0, 1,255,236, 0, 0, 4,230, 6, 20, 0, 41,
+ 0, 0, 41, 1, 53, 33, 50, 55, 54, 53, 52, 39, 1, 38, 53, 52, 55, 54, 55, 1, 21, 5, 6, 7, 6, 21, 20, 23, 1, 22, 23, 22,
+ 59, 1, 21, 35, 34, 39, 38, 47, 1, 6, 7, 6, 1,156,254, 80, 1,156,147, 47, 16, 54,254,202, 50, 10, 30,104, 2,234,253,172,
+ 70, 22, 6, 32, 2, 70, 22, 38, 44, 64, 88,132, 66, 58,102, 34, 96, 22, 16, 96,184,104, 36, 36, 69, 66, 1,124, 61, 81, 30, 38,
+118, 43, 1, 54,186,250, 30, 40, 11, 25, 32, 37,253, 63, 26, 14, 16,184, 24, 43, 41,120, 46, 27,155, 0, 0, 0,255,255, 0, 66,
+254,200, 4, 75, 6, 20, 16, 6, 3,253, 0, 0, 0, 1, 0, 9,254,200, 4,229, 6, 20, 0, 36, 0, 0, 1, 35, 17, 16, 7, 6,
+ 7, 6, 35, 34, 39, 38, 53, 52, 55, 35, 6, 23, 18, 23, 22, 51, 50, 55, 54, 55, 54, 55, 22, 59, 1, 53, 35, 34, 39, 38, 53, 4,
+ 18,184, 30, 69, 99, 84,105, 73, 40,166, 65,184, 64, 1, 1,242,119, 99,125, 94,129,104, 51, 15, 78, 56,130, 75, 43, 44, 49, 6,
+ 20,251,150,254,216, 57,131, 41, 34, 16, 66,126,115,115, 92,138,254,253, 86, 42, 34, 47,126, 63, 93, 51,184, 44, 49,106, 0, 0,
+ 0, 1,255,236, 0, 0, 3,233, 6, 20, 0, 13, 0, 0, 1, 20, 7, 6, 41, 1, 53, 33, 50, 55, 54, 53, 17, 51, 3,233, 87, 80,
+254,240,253,186, 2, 14,218, 44, 49,184, 1,115,178,101, 92,184, 44, 49,106, 4,149, 0, 0, 0, 0, 1,255,236, 0, 0, 4,229,
+ 6, 20, 0, 20, 0, 0, 37, 6, 41, 1, 53, 51, 50, 55, 54, 53, 17, 51, 17, 20, 23, 22, 59, 1, 21, 33, 32, 2,104, 76,254,240,
+254,224,234,218, 44, 48,184, 50, 44,218,233,254,223,254,244, 86, 86,184, 44, 49,106, 4,149,251,107,106, 49, 44,184, 0, 0, 0,
+255,255, 0,130,254, 20, 4, 84, 2,243, 16, 6, 3,254, 0, 0, 0, 2, 0, 71,254, 20, 4,229, 2,116, 0, 17, 0, 52, 0, 0,
+ 37, 22, 51, 50, 55, 54, 53, 52, 39, 38, 39, 38, 35, 34, 7, 6, 21, 20, 5, 6, 7, 6, 35, 34, 39, 38, 7, 6, 21, 17, 35, 17,
+ 52, 55, 54, 51, 38, 53, 52, 55, 54, 51, 50, 23, 22, 23, 30, 1, 59, 1, 21, 35, 34, 2, 12,122, 76, 44, 21, 53, 6, 21, 59, 40,
+ 46, 59, 27, 68, 1,192, 15, 13,133, 75,210,112, 35, 73, 25,200,120, 65, 73, 2,162, 77, 92, 72, 84,170, 40, 14, 82,102, 31, 86,
+173,168, 42, 22, 57, 58, 24, 20, 88, 17, 12, 27, 68, 68, 40,169, 14, 8, 80, 78, 25, 75, 26, 79,254,147, 1,109,173,102, 55, 42,
+ 40,148,132, 63, 36, 71,179, 64, 94,184, 0, 0, 0, 2,255,236,255,205, 3,166, 2,109, 0, 24, 0, 42, 0, 0, 37, 6, 7, 6,
+ 39, 6, 43, 1, 53, 51, 50, 55, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 37, 22, 51, 50, 55, 54, 53, 52, 39, 38, 39,
+ 38, 35, 34, 7, 6, 7, 6, 3,100, 96,140,212,112, 64,104,160,116, 52, 44, 43, 5, 20,135, 94, 93, 69, 69,189, 21, 4,253,240,
+ 62,159, 47, 19, 52, 5, 22, 58, 39, 39, 53, 41, 50, 15, 7, 52,101, 1, 2,100, 48,184, 36, 35, 49,181, 80, 56, 29, 79,171, 36,
+ 42,142, 77, 69, 18, 53, 69, 19, 18, 88, 17, 12, 27, 33, 97, 37, 0, 2,255,236,255,206, 4,229, 2,109, 0, 29, 0, 47, 0, 0,
+ 37, 6, 35, 34, 39, 6, 43, 1, 53, 51, 50, 55, 54, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 23, 22, 59, 1, 21, 35, 34, 37, 22,
+ 51, 50, 55, 54, 53, 52, 39, 38, 39, 38, 35, 34, 7, 6, 7, 6, 3,124, 97,139,214,110, 64,104,184,140, 52, 44, 43, 5, 20,135,
+ 94, 93, 72, 66,193, 17, 5, 51, 38,105,100,155,174,254, 18, 62,159, 47, 19, 52, 5, 22, 58, 39, 39, 53, 41, 46, 19, 7, 52,102,
+ 98, 48,184, 36, 35, 49,181, 80, 56, 29, 83,167, 49, 62, 47,184,199, 69, 18, 53, 69, 19, 18, 88, 17, 12, 27, 30,100, 37, 0, 0,
+255,255, 0, 54,254,181, 4,141, 3,132, 16, 38, 4, 56, 0, 0, 16, 7, 11,195, 1,211, 2,238,255,255,255,213,254, 12, 4,230,
+ 2,175, 16, 39, 11,195, 1,119, 2, 25, 16, 6, 10,212, 0, 0,255,255,255,236, 0, 0, 2,188, 3,232, 16, 38, 10,217, 0, 0,
+ 16, 7, 11,195, 2, 16, 3, 82,255,255,255,236, 0, 0, 4,229, 3,232, 16, 38, 10,218, 0, 0, 16, 7, 11,195, 2, 21, 3, 82,
+255,255, 0,222,255,198, 3,243, 2,222, 16, 6, 4, 0, 0, 0, 0, 2, 0,242, 0, 0, 4,229, 2,238, 0, 10, 0, 36, 0, 0,
+ 1, 38, 39, 38, 39, 6, 7, 6, 23, 30, 1, 19, 38, 39, 51, 22, 23, 22, 23, 22, 59, 1, 21, 35, 34, 39, 38, 39, 6, 35, 34, 39,
+ 38, 53, 52, 55, 54, 3, 5, 15, 13, 13, 12,120, 82,111, 2, 1,180,116, 4, 3,184, 1, 36, 21, 56, 31,112,113,168, 90, 73, 45,
+ 38,138,156, 56, 58,189,204,109, 1, 26, 42, 49, 50,101, 12, 67, 89, 62, 41, 50, 1,209, 39, 43,168,174,101, 79, 44,184, 51, 31,
+ 59, 73, 15, 48,154,173,127, 68, 0, 3,255,236,255,189, 3,227, 3,229, 0, 15, 0, 45, 0, 61, 0, 0, 1, 54, 55, 54, 53, 52,
+ 39, 38, 35, 34, 7, 6, 21, 20, 23, 22, 7, 50, 55, 38, 39, 38, 53, 52, 55, 54, 23, 38, 39, 53, 22, 23, 4, 23, 22, 21, 20, 7,
+ 6, 35, 34, 39, 6, 43, 1, 53, 1, 22, 21, 20, 7, 6, 7, 22, 51, 50, 55, 54, 53, 52, 39, 38, 1,186, 36, 34, 39, 15, 22, 58,
+ 65, 23, 22, 7, 21,249, 52, 78, 45, 15, 18, 45, 48, 77, 44, 81,219,220, 1, 5, 59, 14, 40, 74,175,131,154,120,146,175, 2,209,
+ 6, 98, 12, 17, 52, 49,126, 16, 7, 33, 29, 1, 13, 27, 64, 72, 61, 46, 37, 52, 45, 43, 35, 30, 37,118,136, 11,105, 69, 78, 64,
+ 84, 83, 90, 9, 39, 14,185, 67,180,214,217, 52, 57,103, 61,113,108, 41,184, 1, 68, 37, 39,138,114, 14, 19, 46, 67, 30, 33, 60,
+ 78, 69, 0, 0, 0, 3,255,236,254, 13, 4,229, 2,171, 0, 10, 0, 36, 0, 47, 0, 0, 37, 51, 50, 55, 54, 53, 52, 35, 34, 7,
+ 6, 7, 18, 55, 54, 51, 50, 23, 22, 21, 20, 7, 33, 21, 33, 22, 21, 20, 7, 6, 35, 34, 39, 38, 3, 33, 53, 5, 20, 23, 22, 51,
+ 50, 53, 52, 39, 38, 35, 1,228, 19, 42, 96,114, 84, 75, 74, 38,184, 9,129,108,129,138, 69, 46,163, 1,232,254, 24,163, 46, 69,
+138,129,108,129, 9,254,192, 1,248, 38, 74, 75, 84,114, 96, 42,184, 76, 90, 52,112,141, 72,117, 1, 10,126,107, 99, 67,114,111,
+108,184,108,111,114, 67, 99,107,128, 1, 8,184,184,117, 72,141,112, 52, 90, 76,255,255, 0, 76,254, 12, 4, 51, 2,134, 16, 6,
+ 4, 1, 0, 0, 0, 2, 0, 90,254, 12, 4,229, 2,135, 0, 11, 0, 44, 0, 0, 37, 52, 39, 38, 39, 38, 7, 6, 7, 6, 23, 22,
+ 5, 51, 21, 35, 39, 6, 7, 6, 7, 6, 33, 53, 32, 55, 54, 55, 38, 39, 38, 39, 38, 39, 38, 55, 54, 55, 54, 23, 22, 23, 22, 23,
+ 22, 3, 60, 16, 24, 46, 60, 60, 67, 13, 17, 64, 47, 1,115,246,194, 70, 25,129, 83,105,192,254,147, 1,105,132,168, 62,118, 45,
+139, 51,106, 10, 2, 10, 27,176, 59, 65, 87, 69,133, 22, 13,184, 76, 57, 80, 30, 41, 26, 29, 56, 75, 54, 40, 4,184, 1,156,129,
+ 83, 47, 86,184, 76, 95,148, 3, 7, 24, 43, 89,135, 31, 57,155, 75, 25, 1, 2, 49, 92,141, 83,255,255, 0, 25,254,243, 4,209,
+ 3, 28, 16, 6, 4, 2, 0, 0, 0, 1,255,123,254,240, 4,229, 2, 2, 0, 55, 0, 0, 37, 38, 39, 38, 39, 38, 53, 52, 55, 54,
+ 55, 54, 51, 50, 23, 22, 59, 1, 21, 35, 34, 39, 38, 35, 6, 7, 6, 21, 20, 23, 22, 21, 20, 7, 6, 7, 6, 35, 34, 39, 38, 39,
+ 38, 55, 51, 6, 21, 22, 23, 22, 51, 50, 55, 54, 55, 54, 3, 1, 2, 9, 24, 24, 44, 41, 77, 87, 29, 44,130, 46, 64, 34, 35, 35,
+127, 67, 64, 30, 34, 16, 20, 42, 53, 78,104,181,140, 76,121,147,228, 12, 6, 36,178, 26, 1,141, 69,113,130, 58,128, 20, 60, 51,
+ 44, 12, 36, 25, 46, 61, 78, 47, 91, 17, 6,138,192,184,172,165, 1, 16, 18, 32, 3, 69, 87, 60, 83, 83,111, 26, 20, 36, 56,198,
+ 92,138, 80,116,106, 26, 13, 17, 37, 15, 46, 0,255,255, 0, 25,254, 12, 4,209, 3, 28, 16, 38, 4, 2, 0, 0, 16, 7, 11,196,
+ 1, 89,254, 12,255,255,255,123,254, 12, 4,229, 2, 2, 16, 38, 11, 94, 0, 0, 16, 7, 11,196, 0,192,254, 12,255,255,255,236,
+254,212, 3, 18, 2, 88, 16, 39, 11,196, 1,130,254,212, 16, 6, 10,217, 0, 0,255,255,255,236,254,212, 4,229, 2, 88, 16, 39,
+ 11,196, 1,147,254,212, 16, 6, 10,218, 0, 0,255,255,255,150,255,236, 4, 30, 6,237, 16, 39, 4, 12,254,150, 1, 44, 16, 6,
+ 11,105, 0, 0,255,255,255, 64,255,236, 4,229, 6,237, 16, 39, 4, 12,254, 64, 1, 44, 16, 6, 11,106, 0, 0,255,255, 0, 83,
+255,236, 4, 30, 7,164, 16, 39, 4, 13,254,150, 1, 44, 16, 6, 11,105, 0, 0,255,255,255,224,255,236, 4,229, 7,164, 16, 39,
+ 4, 13,254, 35, 1, 44, 16, 6, 11,106, 0, 0,255,255, 0,133,254, 12, 4, 30, 6, 20, 16, 39, 4, 14,254,200, 0, 0, 16, 6,
+ 11,105, 0, 0,255,255, 0, 95,254, 12, 4,229, 6, 20, 16, 39, 4, 14,254,200, 0, 0, 16, 6, 11,106, 0, 0, 0, 1, 0,179,
+255,236, 4, 30, 6, 20, 0, 22, 0, 0, 1, 16, 7, 6, 7, 6, 35, 34, 39, 53, 22, 51, 50, 55, 1, 51, 1, 54, 55, 54, 53, 17,
+ 51, 4, 30,139, 55, 77,205,158,106, 75, 96, 85,113,136,254, 22,179, 1,170, 29, 20, 37,184, 3, 66,254,212,218, 85, 71,180, 32,
+184, 32,152, 4, 70,252, 65, 43, 55,137,184, 2,174, 0, 0, 0, 0, 1, 0, 95,255,236, 4,229, 6, 20, 0, 31, 0, 0, 1, 6,
+ 7, 6, 35, 34, 39, 53, 22, 51, 50, 55, 1, 51, 1, 54, 55, 54, 53, 17, 51, 17, 20, 23, 22, 59, 1, 21, 35, 34, 39, 38, 3, 63,
+ 59, 73,202,161,106, 75, 96, 85,113,136,254, 22,179, 1,170, 29, 20, 37,184, 34, 64, 80,105,129,175,102, 17, 1, 60, 91, 65,180,
+ 32,184, 32,152, 4, 70,252, 65, 43, 55,137,184, 2,174,252, 68,174, 84,158,184,243, 41, 0, 0, 0, 3, 0, 82,255, 84, 4,126,
+ 7, 24, 0, 5, 0, 38, 0, 42, 0, 0, 9, 1, 17, 9, 1, 17, 1, 53, 52, 55, 54, 63, 1, 54, 55, 54, 53, 52, 38, 35, 34, 6,
+ 7, 21, 62, 1, 51, 50, 22, 21, 20, 6, 15, 1, 6, 7, 6, 29, 1, 7, 21, 51, 53, 2,104, 2, 22,253,234,253,234, 2,117, 19,
+ 18, 70, 88, 94, 34, 33,221,186,104,191, 94, 98,178, 78,109,131, 47, 62, 90, 85, 29, 31, 7,203, 7, 24,254, 23,252, 14,254, 23,
+ 1,233, 3,242,252, 98,170, 61, 42, 40, 68, 86, 92, 66, 65, 76,161,192, 56, 57,188, 68, 69,110, 89, 49, 88, 59, 89, 84, 66, 69,
+ 98,154,147,254,254, 0, 0, 0,255,255, 0, 37, 0, 0, 4,172, 5,213, 16, 6, 0, 36, 0, 0,255,255, 0,166, 0, 0, 4,113,
+ 5,213, 16, 6, 0, 37, 0, 0,255,255, 0,139,255,227, 4, 49, 5,240, 16, 6, 0, 38, 0, 0,255,255, 0,137, 0, 0, 4, 82,
+ 5,213, 16, 6, 0, 39, 0, 0,255,255, 0,197, 0, 0, 4, 78, 5,213, 16, 6, 0, 40, 0, 0,255,255, 0,233, 0, 0, 4, 88,
+ 5,213, 16, 6, 0, 41, 0, 0,255,255, 0,102,255,227, 4, 80, 5,240, 16, 6, 0, 42, 0, 0,255,255, 0,137, 0, 0, 4, 72,
+ 5,213, 16, 6, 0, 43, 0, 0,255,255, 0,201, 0, 0, 4, 6, 5,213, 16, 6, 0, 44, 0, 0,255,255, 0,109,255,227, 3,188,
+ 5,213, 16, 6, 0, 45, 0, 0,255,255, 0,137, 0, 0, 4,201, 5,213, 16, 6, 0, 46, 0, 0,255,255, 0,215, 0, 0, 4,115,
+ 5,213, 16, 6, 0, 47, 0, 0,255,255, 0, 86, 0, 0, 4,121, 5,213, 16, 6, 0, 48, 0, 0,255,255, 0,139, 0, 0, 4, 70,
+ 5,213, 16, 6, 0, 49, 0, 0,255,255, 0,117,255,227, 4, 92, 5,240, 16, 6, 0, 50, 0, 0,255,255, 0,197, 0, 0, 4,117,
+ 5,213, 16, 6, 0, 51, 0, 0,255,255, 0,117,254,242, 4, 92, 5,240, 16, 6, 0, 52, 0, 0,255,255, 0,143, 0, 0, 4,209,
+ 5,213, 16, 6, 0, 53, 0, 0,255,255, 0,139,255,227, 4, 74, 5,240, 16, 6, 0, 54, 0, 0,255,255, 0, 47, 0, 0, 4,162,
+ 5,213, 16, 6, 0, 55, 0, 0,255,255, 0,147,255,227, 4, 61, 5,213, 16, 6, 0, 56, 0, 0,255,255, 0, 57, 0, 0, 4,152,
+ 5,213, 16, 6, 0, 57, 0, 0,255,255, 0, 0, 0, 0, 4,209, 5,213, 16, 6, 0, 58, 0, 0,255,255, 0, 18, 0, 0, 4,190,
+ 5,213, 16, 6, 0, 59, 0, 0,255,255, 0, 37, 0, 0, 4,172, 5,213, 16, 6, 0, 60, 0, 0,255,255, 0,156, 0, 0, 4,145,
+ 5,213, 16, 6, 0, 61, 0, 0,255,255, 0,133,255,227, 4, 35, 4,123, 16, 6, 0, 68, 0, 0,255,255, 0,193,255,227, 4, 88,
+ 6, 20, 16, 6, 0, 69, 0, 0,255,255, 0,195,255,227, 4, 37, 4,123, 16, 6, 0, 70, 0, 0,255,255, 0,123,255,227, 4, 18,
+ 6, 20, 16, 6, 0, 71, 0, 0,255,255, 0,123,255,227, 4, 88, 4,123, 16, 6, 0, 72, 0, 0,255,255, 0,195, 0, 0, 4, 39,
+ 6, 20, 16, 6, 0, 73, 0, 0,255,255, 0,123,254, 72, 4, 18, 4,123, 16, 6, 0, 74, 0, 0,255,255, 0,195, 0, 0, 4, 27,
+ 6, 20, 16, 6, 0, 75, 0, 0,255,255, 0,178, 0, 0, 4, 68, 6, 20, 16, 6, 0, 76, 0, 0,255,255, 0,186,254, 86, 3, 16,
+ 6, 20, 16, 6, 0, 77, 0, 0,255,255, 0,236, 0, 0, 4,178, 6, 20, 16, 6, 0, 78, 0, 0,255,255, 0,160, 0, 0, 4, 10,
+ 6, 31, 16, 6, 0, 79, 0, 0,255,255, 0,109, 0, 0, 4,111, 4,123, 16, 6, 0, 80, 0, 0,255,255, 0,195, 0, 0, 4, 27,
+ 4,123, 16, 6, 0, 81, 0, 0,255,255, 0,137,255,227, 4, 72, 4,123, 16, 6, 0, 82, 0, 0,255,255, 0,190,254, 86, 4, 84,
+ 4,123, 16, 6, 0, 83, 0, 0,255,255, 0,137,254, 82, 4, 31, 4,119, 16, 6, 0, 84, 0, 0,255,255, 1,106, 0, 0, 4,131,
+ 4,123, 16, 6, 0, 85, 0, 0,255,255, 0,213,255,227, 4, 6, 4,123, 16, 6, 0, 86, 0, 0,255,255, 0,131, 0, 0, 4, 8,
+ 5,158, 16, 6, 0, 87, 0, 0,255,255, 0,195,255,227, 4, 27, 4, 94, 16, 6, 0, 88, 0, 0,255,255, 0,100, 0, 0, 4,109,
+ 4, 96, 16, 6, 0, 89, 0, 0,255,255, 0, 0, 0, 0, 4,209, 4, 96, 16, 6, 0, 90, 0, 0,255,255, 0, 76, 0, 0, 4,133,
+ 4, 96, 16, 6, 0, 91, 0, 0,255,255, 0,104,254, 86, 4,129, 4, 96, 16, 6, 0, 92, 0, 0,255,255, 0,203, 0, 0, 4, 16,
+ 4, 98, 16, 6, 0, 93, 0, 0,255,255, 0,133,255,227, 4, 76, 5,240, 16, 6, 0, 19, 0, 0,255,255, 0,246, 0, 0, 4, 70,
+ 5,213, 16, 6, 0, 20, 0, 0,255,255, 0,152, 0, 0, 4, 35, 5,240, 16, 6, 0, 21, 0, 0,255,255, 0,137,255,227, 4, 55,
+ 5,240, 16, 6, 0, 22, 0, 0,255,255, 0,102, 0, 0, 4,111, 5,213, 16, 6, 0, 23, 0, 0,255,255, 0,143,255,227, 4, 45,
+ 5,213, 16, 6, 0, 24, 0, 0,255,255, 0,133,255,227, 4, 76, 5,240, 16, 6, 0, 25, 0, 0,255,255, 0,139, 0, 0, 4, 55,
+ 5,213, 16, 6, 0, 26, 0, 0,255,255, 0,131,255,227, 4, 78, 5,240, 16, 6, 0, 27, 0, 0,255,255, 0,127,255,227, 4, 70,
+ 5,240, 16, 6, 0, 28, 0, 0, 0, 1, 1,219, 4,238, 2,230, 6,102, 0, 3, 0, 17, 64, 6, 0, 3, 4, 1, 3, 4, 16,212,
+204, 49, 0, 16,212,204, 48, 1, 51, 3, 35, 2, 32,198,113,154, 6,102,254,136, 0, 2, 1, 63, 5, 14, 3,145, 5,217, 0, 3,
+ 0, 7, 0, 81, 64, 13, 4, 0,222, 6, 2, 8, 5, 97, 4, 1, 97, 0, 8, 16,212,252,212,236, 49, 0, 16,212, 60,236, 50, 48,
+ 0, 75,176, 14, 84, 88,189, 0, 8, 0, 64, 0, 1, 0, 8, 0, 8,255,192, 56, 17, 55, 56, 89, 1, 75,176, 14, 84, 75,176, 13,
+ 84, 91, 88,189, 0, 8,255,192, 0, 1, 0, 8, 0, 8, 0, 64, 56, 17, 55, 56, 89, 1, 51, 21, 35, 37, 51, 21, 35, 1, 63,203,
+203, 1,136,202,202, 5,217,203,203,203, 0, 0, 0, 1, 1,219, 4,238, 3, 90, 5,246, 0, 3, 0,107,181, 0, 2, 4, 1, 3,
+ 4, 16,212,196, 49, 0, 16,212,196, 48, 0, 75,176, 12, 84, 88,189, 0, 4,255,192, 0, 1, 0, 4, 0, 4, 0, 64, 56, 17, 55,
+ 56, 89, 0, 75,176, 14, 84, 88,189, 0, 4, 0, 64, 0, 1, 0, 4, 0, 4,255,192, 56, 17, 55, 56, 89, 64, 38, 15, 0, 15, 1,
+ 10, 2, 10, 3, 31, 0, 31, 1, 31, 2, 31, 3, 47, 0, 47, 1, 47, 2, 47, 3, 12, 15, 0, 15, 1, 31, 0, 31, 1, 47, 0, 47,
+ 1, 6, 93, 1, 93, 1, 51, 3, 35, 2,160,186,229,154, 5,246,254,248, 0, 0, 0, 1, 1, 31, 5, 14, 3,178, 5,233, 0, 29,
+ 0,209, 64, 30, 22, 16, 15, 3, 19, 12, 7, 1, 0, 3, 8, 4,204, 23, 12, 19,204, 27, 8, 30, 16, 1, 15, 0, 7, 22, 24, 7,
+ 9, 30, 16,212,196,212,196, 17, 57, 57, 57, 57, 49, 0, 16,212, 60,252,212, 60,236, 17, 23, 57, 17, 18, 23, 57, 48, 0, 75,176,
+ 14, 84, 75,176, 17, 84, 91, 88,189, 0, 30, 0, 64, 0, 1, 0, 30, 0, 30,255,192, 56, 17, 55, 56, 89, 64,116, 9, 0, 9, 1,
+ 15, 11, 15, 12, 15, 13, 13, 14, 15, 15, 15, 16, 15, 17, 15, 18, 15, 19, 15, 20, 15, 21, 15, 22, 15, 23, 15, 24, 11, 25, 26, 0,
+ 26, 1, 29, 11, 29, 12, 29, 13, 30, 14, 31, 15, 31, 16, 31, 17, 31, 18, 31, 19, 31, 20, 31, 21, 31, 22, 31, 23, 31, 24, 33, 15,
+ 1, 15, 2, 15, 3, 15, 4, 15, 5, 15, 11, 15, 12, 15, 13, 15, 21, 15, 22, 15, 23, 15, 24, 31, 1, 31, 2, 31, 3, 31, 4, 31,
+ 5, 31, 11, 31, 12, 31, 13, 31, 21, 31, 22, 31, 23, 31, 24, 24, 93, 1, 93, 1, 39, 46, 1, 35, 34, 6, 29, 1, 35, 52, 54, 51,
+ 50, 22, 31, 1, 30, 1, 51, 50, 54, 61, 1, 51, 14, 1, 35, 34, 38, 2,100, 57, 25, 31, 12, 35, 40,125,103, 85, 36, 61, 49, 57,
+ 22, 35, 15, 31, 40,125, 2,102, 84, 34, 60, 5, 57, 33, 14, 11, 50, 45, 6,101,118, 16, 27, 30, 13, 12, 51, 41, 6,100,119, 16,
+ 0, 1, 1,121, 4,238, 2,246, 5,246, 0, 3, 0,105,181, 0, 1, 4, 1, 3, 4, 16,212,196, 49, 0, 16,212,196, 48, 0, 75,
+176, 12, 84, 88,189, 0, 4,255,192, 0, 1, 0, 4, 0, 4, 0, 64, 56, 17, 55, 56, 89, 0, 75,176, 14, 84, 88,189, 0, 4, 0,
+ 64, 0, 1, 0, 4, 0, 4,255,192, 56, 17, 55, 56, 89, 1, 75,176, 14, 84, 88,189, 0, 4, 0, 64, 0, 1, 0, 4, 0, 4,255,
+192, 56, 17, 55, 56, 89, 64, 13, 15, 0, 15, 3, 31, 0, 31, 3, 47, 0, 47, 3, 6, 0, 93, 1, 19, 35, 3, 2, 49,197,154,227,
+ 5,246,254,248, 1, 8, 0, 0, 0, 1, 1, 55, 4,238, 3,154, 5,248, 0, 6, 0, 93, 64, 9, 4, 0, 5, 2, 7, 4, 2, 6,
+ 7, 16,212,196, 57, 49, 0, 16,212, 60,196, 57, 48, 0, 75,176, 12, 84, 88,189, 0, 7,255,192, 0, 1, 0, 7, 0, 7, 0, 64,
+ 56, 17, 55, 56, 89, 0, 75,176, 14, 84, 88,189, 0, 7, 0, 64, 0, 1, 0, 7, 0, 7,255,192, 56, 17, 55, 56, 89, 64, 19, 15,
+ 0, 15, 1, 12, 4, 31, 0, 31, 1, 28, 4, 47, 0, 47, 1, 44, 4, 9, 93, 1, 51, 19, 35, 39, 7, 35, 2, 10,189,211,140,166,
+165,140, 5,248,254,246,178,178, 0, 1, 1, 55, 4,238, 3,154, 5,248, 0, 6, 0,105, 64, 9, 3, 4, 1, 0, 7, 3, 5, 1,
+ 7, 16,212,196, 57, 49, 0, 16,212,196, 50, 57, 48, 0, 75,176, 14, 84, 88,189, 0, 7, 0, 64, 0, 1, 0, 7, 0, 7,255,192,
+ 56, 17, 55, 56, 89, 0, 75,176, 12, 84, 88,189, 0, 7,255,192, 0, 1, 0, 7, 0, 7, 0, 64, 56, 17, 55, 56, 89, 64, 31, 15,
+ 1, 15, 2, 10, 3, 15, 4, 15, 5, 31, 1, 31, 2, 26, 3, 31, 4, 31, 5, 47, 1, 47, 2, 42, 3, 47, 4, 47, 5, 15, 93, 1,
+ 3, 51, 23, 55, 51, 3, 2, 10,211,140,165,166,140,211, 4,238, 1, 10,178,178,254,246, 0, 0, 0, 1, 0, 27, 1,248, 4, 90,
+ 3,106, 0, 3, 0, 25, 64, 10, 1, 0, 3, 2, 4, 2, 0, 3, 1, 4, 16,212,196, 57, 57, 49, 0, 16,212,220,212,204, 48, 19,
+ 39, 1, 23, 51, 24, 4, 36, 27, 1,248,108, 1, 6,108, 0, 0, 0, 1, 1, 47, 6,123, 3,162, 7,109, 0, 12, 0, 0, 1, 62,
+ 1, 32, 22, 23, 35, 46, 1, 35, 34, 6, 7, 1, 47, 11,158, 1, 32,159, 11,119, 15, 97, 83, 82,100, 12, 6,123,120,122,123,119,
+ 56, 55, 57, 54, 0, 1, 1, 47, 6,123, 3,162, 7,109, 0, 13, 0, 31,178, 7, 0, 4,184, 1, 3, 64, 9, 11, 14, 7, 80, 8,
+ 1, 80, 0, 14, 16,212,236,212,236, 49, 0, 16,212,252,196, 50, 48, 1, 51, 30, 1, 51, 50, 54, 55, 51, 14, 1, 35, 34, 38, 1,
+ 47,119, 12,100, 82, 83, 97, 15,119, 11,159,144,144,158, 7,109, 54, 57, 55, 56,119,123,122, 0, 0, 1, 2, 1, 6,131, 2,206,
+ 7, 80, 0, 3, 0, 18,183, 0,222, 2, 4, 1, 97, 0, 4, 16,212,236, 49, 0, 16,212,236, 48, 1, 51, 21, 35, 2, 1,205,205,
+ 7, 80,205, 0, 0, 2, 1, 88, 6, 99, 4, 22, 7,107, 0, 3, 0, 7, 0, 25, 64, 10, 0, 4, 3, 7, 8, 1, 3, 5, 7, 8,
+ 16,212,204,212,204, 49, 0, 16,212, 60,204, 50, 48, 1, 51, 3, 35, 3, 51, 3, 35, 3, 92,186,229,154,122,186,229,154, 7,107,
+254,248, 1, 8,254,248, 0, 0, 0, 2, 0,187, 6, 99, 3,121, 7,107, 0, 3, 0, 7, 0, 0, 1, 19, 35, 3, 33, 19, 35, 3,
+ 1,117,197,154,229, 1,249,197,154,229, 7,107,254,248, 1, 8,254,248, 1, 8, 0, 2, 1,102, 0, 0, 3,149, 5,241, 0, 36,
+ 0, 40, 0, 0, 1, 35, 53, 52, 55, 54, 63, 1, 62, 1, 53, 52, 39, 38, 39, 38, 7, 6, 7, 53, 54, 55, 54, 23, 22, 23, 22, 21,
+ 20, 7, 6, 15, 1, 6, 7, 6, 21, 3, 51, 21, 35, 2,174,194, 19, 20, 55, 58, 41, 30, 42, 37, 62, 56, 39, 57, 64, 66, 57, 81,
+ 91,126, 67, 71, 21, 22, 61, 57, 46, 12, 12,199,203,203, 1,145,154, 98, 69, 66, 84, 89, 59, 88, 49, 73, 42, 37, 4, 2, 22, 35,
+ 68,217, 62, 23, 34, 6, 7, 89, 96,161, 76, 65, 66, 92, 86, 69, 39, 42, 61,254,195,254, 0, 0, 0, 1, 1, 61, 6,156, 3,147,
+ 7, 48, 0, 3, 0, 17,182, 2,182, 0, 4, 1, 0, 4, 16,212,204, 49, 0, 16,212,236, 48, 1, 33, 21, 33, 1, 61, 2, 86,253,
+170, 7, 48,148, 0, 1, 0,156,255, 52, 4, 53,255,166, 0, 3, 0, 0, 5, 33, 53, 33, 4, 53,252,103, 3,153,204,114, 0, 0,
+ 0, 1, 0, 6,255, 52, 4,203,255,166, 0, 3, 0, 0, 5, 33, 53, 33, 4,203,251, 59, 4,197,204,114, 0, 0, 0, 1, 1, 0,
+255, 52, 3,209,255,166, 0, 3, 0, 0, 5, 33, 53, 33, 3,209,253, 47, 2,209,204,114, 0, 0, 0, 2, 1, 94, 1,212, 3,115,
+ 3,233, 0, 11, 0, 19, 0, 0, 1, 50, 23, 30, 1, 21, 20, 6, 34, 38, 52, 54, 22, 34, 6, 20, 22, 50, 54, 52, 2,104,114, 76,
+ 38, 39,156,226,151,154,171,118, 85, 82,121, 86, 3,233, 80, 37, 96, 56,110,154,151,226,156,124, 84,121, 82, 84,118, 0, 0, 0,
+ 0, 2, 1, 63, 5, 70, 3,145, 6, 16, 0, 3, 0, 7, 0, 0, 1, 51, 21, 35, 37, 51, 21, 35, 1, 63,203,203, 1,136,202,202,
+ 6, 16,202,202,202, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,150, 0,150, 0, 3, 0, 0, 53, 51, 21, 35,150,150,150,150, 0, 0,
+ 0, 2, 0, 0, 0, 0, 1,144, 0,150, 0, 3, 0, 7, 0, 0, 55, 51, 21, 35, 39, 51, 21, 35,250,150,150,250,150,150,150,150,
+150,150, 0, 0, 0, 3, 0, 0, 0, 0, 1,144, 1,144, 0, 3, 0, 7, 0, 11, 0, 0, 19, 51, 21, 35, 23, 51, 21, 35, 39, 51,
+ 21, 35,125,150,150,125,150,150,250,150,150, 1,144,150,100,150,150,150, 0, 0, 0, 1, 0, 69,255,236, 4,229, 2, 28, 0, 38,
+ 0, 0, 5, 34, 39, 38, 53, 52, 55, 51, 6, 21, 20, 23, 22, 51, 50, 55, 54, 55, 54, 53, 52, 39, 51, 22, 21, 20, 23, 22, 59, 1,
+ 21, 35, 34, 39, 38, 39, 6, 7, 6, 2, 31,186,131,157, 41,184, 43,117, 98,127, 69,130, 87, 45, 55, 29,184, 19, 24, 19, 24, 33,
+ 75, 52, 47, 43, 20, 88, 96,116, 20, 56, 65,219, 62,124,138, 48,108, 30, 25, 55, 37, 53, 65, 56, 62, 55, 75, 90,100, 51, 40,184,
+ 44, 42, 79, 81, 47, 57, 0, 0, 0, 2,255,236, 0, 0, 3, 63, 3,217, 0, 15, 0, 48, 0, 0, 1, 54, 53, 52, 39, 38, 7, 6,
+ 7, 6, 7, 20, 23, 22, 51, 50, 1, 51, 50, 55, 54, 55, 54, 55, 6, 7, 6, 39, 38, 53, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23,
+ 22, 21, 20, 7, 6, 7, 6, 35, 33, 2, 86, 41, 66, 31, 44, 52, 40, 40, 1, 55, 40, 42, 72,253,174,241, 84,151, 79, 60, 31, 15,
+ 63, 97,130, 78, 98, 8, 23,150, 78, 76, 90, 66, 96, 46, 23, 78, 74,124,109,145,254,191, 2, 25, 43, 77, 59, 51, 25, 1, 1, 42,
+ 41, 51, 80, 38, 25,254,183, 23, 12, 93, 48, 50, 55, 2, 2, 69, 87,129, 52, 44,148, 69, 36, 50, 72,102, 51,140,208,143,136, 44,
+ 39, 0, 0, 0, 0, 2,255,236, 0, 0, 4,229, 3, 8, 0, 32, 0, 51, 0, 0, 1, 22, 23, 22, 21, 20, 7, 6, 7, 22, 59, 1,
+ 21, 33, 34, 39, 6, 35, 33, 53, 51, 50, 55, 38, 39, 38, 53, 52, 55, 54, 55, 54, 50, 6, 34, 7, 6, 7, 6, 21, 20, 23, 22, 23,
+ 54, 55, 54, 53, 52, 39, 38, 39, 2,200,183, 25, 8, 22, 28, 36, 38,148,225,254,197,136,186,184,136,254,196,226,146, 40, 30, 36,
+ 20, 8, 23,185, 30,128, 50, 28, 18, 56, 24, 10, 24, 30, 68, 64, 36, 24, 10, 24, 56, 2,250, 80,150, 50, 42, 73, 49, 67, 50, 17,
+184, 57, 57,184, 17, 40, 77, 46, 76, 44, 48,143, 87, 14,184, 10, 32, 53, 21, 29, 43, 53, 68, 22, 21, 69, 50, 46, 24, 26, 52, 33,
+ 0, 2,255,237,254, 19, 4,229, 2,228, 0, 46, 0, 64, 0, 0, 37, 38, 39, 38, 39, 38, 53, 52, 55, 54, 55, 54, 51, 50, 23, 22,
+ 23, 22, 23, 22, 59, 1, 21, 43, 1, 6, 7, 6, 7, 6, 39, 36, 39, 38, 53, 52, 55, 51, 6, 21, 20, 23, 22, 51, 50, 55, 54, 19,
+ 54, 39, 38, 39, 38, 35, 34, 7, 6, 7, 6, 21, 20, 23, 22, 23, 22, 3,140, 66, 46,121, 57,147, 6, 40,147, 41, 87,112, 56, 99,
+ 50, 20, 6, 26, 4, 88, 93, 48, 30, 76,104,142,151,164,254,211, 94, 69, 62,184, 62, 27, 58,195,108,117,158,123, 4, 22, 19, 47,
+ 34, 39, 34, 21, 53, 19, 10, 57, 76,100, 47, 10, 5, 13, 35, 43,109,185, 61, 26,165, 69, 19, 50, 88,145, 58,214, 1,184, 83,109,
+149, 74, 78, 1, 2,190,138,125,166, 96,107,155, 73, 61,130, 60, 81, 1,107,122, 87, 75, 35, 25, 10, 28, 57, 30, 25, 60, 44, 59,
+ 20, 9, 0, 0, 0, 2,255,106,255,164, 4,229, 3, 4, 0, 43, 0, 61, 0, 0, 37, 6, 7, 6, 7, 6, 39, 36, 3, 52, 55, 51,
+ 6, 21, 20, 23, 22, 51, 50, 55, 38, 39, 38, 53, 52, 55, 54, 55, 54, 51, 50, 23, 22, 23, 22, 21, 20, 7, 22, 59, 1, 21, 35, 34,
+ 39, 54, 53, 52, 39, 38, 39, 38, 35, 34, 7, 6, 7, 6, 21, 20, 23, 22, 3,115, 61,118,182,124,139,113,254,218, 2, 64,184, 66,
+170, 71,131,112,151, 34, 29, 82, 4, 22,188, 58, 52, 82, 81,139, 16, 4, 80, 9, 7,149,154,105,111,104, 5, 14, 52, 34, 40, 24,
+ 22, 61, 19, 6, 41, 49, 36, 33, 36, 56, 2, 2, 40,103, 1, 8,138, 92, 94,136,125, 69, 29, 58, 27, 44,124,108, 39, 28,155, 75,
+ 23, 50, 84,149, 37, 30,131,106, 1,184,223, 65,109, 20, 27, 71, 39, 25, 10, 25, 60, 19, 18, 43, 66, 78, 0, 0, 0, 3, 0, 0,
+255, 6, 1,144, 0,150, 0, 3, 0, 7, 0, 11, 0, 0, 23, 51, 53, 35, 55, 51, 53, 35, 7, 51, 53, 35,125,150,150,125,150,150,
+250,150,150,250,150,100,150,150,150, 0, 0, 0, 0, 2, 0, 0,255, 6, 0,150, 0,150, 0, 3, 0, 7, 0, 0, 21, 51, 21, 35,
+ 17, 51, 21, 35,150,150,150,150,100,150, 1,144,150, 0, 0, 0, 0, 4, 0, 0,255, 6, 1,144, 0,150, 0, 3, 0, 7, 0, 11,
+ 0, 15, 0, 0, 23, 51, 21, 35, 17, 51, 21, 35, 7, 51, 21, 35, 17, 51, 21, 35,250,150,150,150,150,250,150,150,150,150,100,150,
+ 1,144,150,100,150, 1,144,150, 0, 1, 0, 0, 4,116, 2,183, 7, 56, 0, 3, 0, 0, 9, 1, 53, 1, 2,183,253, 73, 2,183,
+ 6,134,253,238,178, 2, 18, 0, 0, 1, 0, 0, 4,243, 3,156, 7, 57, 0, 3, 0, 0, 9, 1, 53, 1, 3,156,252,100, 3,156,
+ 6,135,254,109,178, 1,147, 0, 0, 2, 0, 0, 0, 0, 1,182, 1,183, 0, 11, 0, 23, 0, 0, 37, 52, 39, 38, 34, 6, 21, 20,
+ 23, 22, 50, 62, 1, 20, 7, 6, 34, 39, 38, 52, 55, 54, 50, 23, 1, 60, 28, 28, 82, 56, 28, 28, 82, 56,122, 63, 64,184, 63, 64,
+ 64, 63,184, 64,220, 40, 28, 29, 56, 41, 42, 28, 27, 56,133,184, 64, 64, 64, 64,184, 64, 63, 63, 0, 1, 0,149,254, 86, 4, 60,
+ 5,213, 0, 19, 0, 68, 64, 33, 17, 1, 2, 1, 2, 16, 17, 16, 66, 17, 2, 3, 0,180, 19, 11,151, 10, 16, 19, 1, 17, 16, 3,
+ 17, 11, 4, 49, 17, 17, 0, 48, 20, 16,252,236,252,196,236, 50, 17, 57, 49, 0, 47, 60,212,236, 16,236, 50, 57, 57, 48, 75, 83,
+ 88, 7, 16, 4,201, 7, 16, 4,201, 89, 19, 51, 1, 17, 51, 17, 20, 7, 6, 43, 1, 53, 51, 50, 55, 54, 53, 1, 17, 35,149,185,
+ 2, 53,185, 89, 90,165,205,185, 90, 45, 44,253,203,185, 5,213,251,151, 4,105,250, 23,195,105,106,156, 62, 62,146, 4,105,251,
+151, 0, 0, 0, 0, 1, 0, 0, 0, 2, 64, 0, 9,134,133,154, 95, 15, 60,245, 0, 31, 8, 0, 0, 0, 0, 0,196, 90,209, 71,
+ 0, 0, 0, 0,196, 90,209, 71,251,137,253, 1, 5,190, 8, 85, 0, 0, 0, 8, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0,
+ 7,109,254, 29, 0, 0, 4,209,251,137,255, 20, 5,190, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,
+ 4,209, 0,104, 0, 0, 0, 0, 4,209, 0, 0, 4,209, 0, 0, 2, 4, 1, 82, 0, 2, 0,190, 0, 33, 0, 57, 2, 16, 1,170,
+ 1, 92, 0,166, 0, 88, 1,147, 1,100, 1,233, 0,102, 0,133, 0,246, 0,152, 0,137, 0,102, 0,143, 0,133, 0,139, 0,131,
+ 0,127, 1,233, 1,147, 0, 88, 0, 88, 0, 88, 0,244, 0, 27, 0, 37, 0,166, 0,139, 0,137, 0,197, 0,233, 0,102, 0,137,
+ 0,201, 0,109, 0,137, 0,215, 0, 86, 0,139, 0,117, 0,197, 0,117, 0,143, 0,139, 0, 47, 0,147, 0, 57, 0, 0, 0, 18,
+ 0, 37, 0,156, 1,207, 0,102, 1, 90, 0, 72, 0, 0, 1, 23, 0,133, 0,193, 0,195, 0,123, 0,123, 0,195, 0,123, 0,195,
+ 0,178, 0,186, 0,236, 0,160, 0,109, 0,195, 0,137, 0,190, 0,137, 1,106, 0,213, 0,131, 0,195, 0,100, 0, 0, 0, 76,
+ 0,104, 0,203, 0,221, 2, 18, 0,221, 0, 88, 0, 0, 2, 4, 0,213, 0,139, 0,205, 0, 37, 2, 18, 0,199, 1, 63, 0, 0,
+ 1, 14, 0,119, 0, 88, 1,100, 0, 0, 1, 61, 1, 43, 0, 88, 1, 66, 1, 70, 1,219, 0,195, 0,106, 1,233, 1,139, 1, 88,
+ 0,244, 0,193, 0, 27, 0, 27, 0, 27, 0,193, 0, 37, 0, 37, 0, 37, 0, 37, 0, 37, 0, 37, 0, 0, 0,139, 0,197, 0,197,
+ 0,197, 0,197, 0,201, 0,201, 0,201, 0,201, 0, 8, 0,139, 0,117, 0,117, 0,117, 0,117, 0,117, 0,150, 0, 8, 0,147,
+ 0,147, 0,147, 0,147, 0, 37, 0,201, 0,188, 0,133, 0,133, 0,133, 0,133, 0,133, 0,133, 0, 41, 0,195, 0,123, 0,123,
+ 0,123, 0,123, 0,178, 0,178, 0,178, 0,178, 0,137, 0,195, 0,137, 0,137, 0,137, 0,137, 0,137, 0, 88, 0, 47, 0,195,
+ 0,195, 0,195, 0,195, 0,104, 0,190, 0,104, 0, 37, 0,133, 0, 37, 0,133, 0, 37, 0,133, 0,139, 0,195, 0,139, 0,195,
+ 0,139, 0,195, 0,139, 0,195, 0,137, 0,123, 0, 8, 0,123, 0,197, 0,123, 0,197, 0,123, 0,197, 0,123, 0,197, 0,123,
+ 0,197, 0,123, 0,102, 0,123, 0,102, 0,123, 0,102, 0,123, 0,102, 0,123, 0,137, 0,195, 0, 3, 0, 70, 0,201, 0,178,
+ 0,201, 0,178, 0,201, 0,178, 0,201, 0,178, 0,201, 0,178,255,255,255,252, 0,109, 0,186, 0,137, 0,236, 0,236, 0,200,
+ 0,160, 0,215, 0,160, 0,215, 0,160, 0,215, 0,160,255,246, 0, 76, 0,139, 0,195, 0,139, 0,195, 0,139, 0,195, 0, 24,
+ 0,147, 0,195, 0,117, 0,137, 0,117, 0,137, 0,117, 0,137, 0, 72, 0, 14, 0,143, 1,106, 0,143, 1, 32, 0,143, 1,106,
+ 0,139, 0,213, 0,139, 0,213, 0,139, 0,213, 0,139, 0,213, 0, 47, 0,131, 0, 47, 0,131, 0, 47, 0,131, 0,147, 0,195,
+ 0,147, 0,195, 0,147, 0,195, 0,147, 0,195, 0,147, 0,195, 0,147, 0,195, 0, 0, 0, 0, 0, 37, 0,104, 0, 37, 0,156,
+ 0,203, 0,156, 0,203, 0,156, 0,203, 0,195, 0, 70, 0, 20, 0,166, 0,193, 0, 48, 0, 60, 0,139, 0, 60, 0, 94, 0, 8,
+ 0, 8, 0,131, 0,157, 0,136, 0,197, 0,117, 0,137, 0, 63, 0,195, 0, 52, 0, 28, 0, 65, 0,201, 0,201, 0,110, 0,236,
+ 0,160, 0, 49, 0,109, 0, 29, 0,195, 0,117, 0, 6, 0, 32, 0, 45, 0, 86, 0, 56, 0,190, 0,143, 0,139, 0,213, 0,120,
+ 0,118, 0,131, 0, 47, 0,131, 0, 47, 0, 9, 0, 39, 0, 74, 0,154, 0, 17, 0, 24, 0,156, 0,156, 0, 26, 0, 26, 0,125,
+ 0,152, 0, 26, 0,125, 0,194, 2, 3, 1, 57, 0,164, 2, 3, 0, 37, 0,133, 0,201, 0,178, 0,117, 0,137, 0,147, 0,195,
+ 0,147, 0,195, 0,147, 0,195, 0,147, 0,195, 0,147, 0,195, 0,122, 0, 37, 0,133, 0, 37, 0,133, 0, 0, 0, 41, 0,102,
+ 0,123, 0,137, 0,236, 0,117, 0,137, 0,117, 0,137, 0, 26, 0,125, 0,186, 0,102, 0,123, 0, 61, 0,139, 0,195, 0, 0,
+ 0, 41, 0, 8, 0, 47, 0, 37, 0,133, 0, 37, 0,133, 0,187, 0,123, 0,197, 0,123, 0,187, 0,178, 0,201, 0,178, 0,117,
+ 0,137, 0,117, 0,137, 0,137, 1,104, 0,143, 1,106, 0,147, 0,195, 0,147, 0,195, 0,139, 0,213, 0, 47, 0,131, 0,137,
+ 0,195, 0,147, 0, 18, 0,156, 0,203, 0, 37, 0,133, 0,197, 0,123, 0,117, 0,137, 0,117, 0,137, 0,117, 0,137, 0,117,
+ 0,137, 0, 37, 0,104, 0,160, 0,106, 0,131, 0,186, 0,120, 0,120, 0, 8, 0, 8, 0, 47, 0, 21, 0, 33, 0,213, 0,203,
+ 0, 55, 0, 57, 0,154, 0,123, 0,192, 0,193, 0,184, 0,195, 0,123, 0,123, 0,122, 0,122, 0, 30, 0,169, 0,169, 0, 56,
+ 0,176, 0,186, 0,123, 0,157, 0,122, 0,102, 0,102, 0,188, 0,195, 0,195, 0,142, 0,198, 0,160, 0, 88, 0,157, 0,160,
+ 0, 40, 0,104, 0,104, 0,103, 0,178, 0,136, 0,144, 0,137, 0, 69, 0,170, 0,137, 0,152, 0,152, 0,102, 1,106, 1,106,
+ 0,160, 0,160, 0,122, 0,122, 0,188, 0,125, 0,125, 0,125, 0,118, 0,166, 0,131, 0, 0, 0, 95, 0, 65, 0, 72, 0, 15,
+ 0, 72, 0,102, 0,194, 0,167, 0,125, 0,105, 0,194, 0,194, 0,194, 0,194, 0, 95, 0,209, 0,176, 0, 54, 0,144, 0,202,
+ 0,119, 0,245, 0, 35, 0,194, 0,194, 0, 29, 0, 27, 0, 54, 0,153, 0,153, 0,181, 0,135, 0,230, 0,219, 0,143, 0,143,
+ 0,178, 0,197, 1, 65, 1, 65, 1,230, 1,153, 1,153, 1, 81, 1, 48, 0,143, 1, 17, 1,236, 1,207, 1,207, 1,240, 1,223,
+ 1,223, 1, 94, 1, 94, 1, 41, 1, 41, 2, 36, 1, 61, 2, 36, 1, 61, 1,182, 1,182, 1,223, 1,223, 0,193, 1, 47, 2, 1,
+ 1, 86, 1,164, 1, 31, 1, 88,254,161, 1, 37, 1, 86, 1, 91, 1, 18, 1, 94, 0,214, 0,214, 0,214, 0,214, 0,214, 1,141,
+ 1, 23, 1,219, 1, 41, 1, 31, 1, 61, 0, 0, 1, 47, 2, 1, 1, 63, 1,153, 1, 86, 1, 88, 1, 41, 2, 34, 1, 86, 0,210,
+ 1, 47, 1, 47, 1,213, 1,239, 1,240, 1,219, 1,121, 1,121, 1,156, 1,204, 1,115, 1,163, 1,250, 1, 98, 1, 94, 1, 95,
+ 1,115, 1,246, 0,182, 2, 1, 1, 63, 1,141, 1,152, 1,139, 1,174, 2, 36, 1, 85, 0,206, 1, 41, 1, 41, 1, 47, 1, 47,
+ 1, 31, 1, 61, 0, 0, 0, 0, 0, 88, 0,141, 0, 0, 0, 47, 0, 8, 1,250, 1, 85, 1, 85, 0,206, 1,139, 1,219, 0, 0,
+ 1,239, 4, 2,255, 20, 1,236, 1,230, 2, 30, 1,147, 1,219, 1, 63, 0, 25, 1,233,255, 31,254,237,255, 31,255,181,254,112,
+255,206, 1, 54, 0, 37, 0,166, 0,215, 0, 37, 0,197, 0,156, 0,137, 0,117, 0,201, 0,137, 0, 37, 0, 86, 0,139, 0,137,
+ 0,117, 0,137, 0,197, 0,120, 0, 47, 0, 37, 0,117, 0, 18, 0,117, 0, 74, 0,201, 0, 37, 0, 70, 0,169, 0,195, 1, 54,
+ 0, 51, 0, 70, 0,151, 0, 32, 0,137, 0,169, 0,152, 0,195, 0,137, 1, 54, 0,236, 0, 68, 0,195, 0,116, 0,161, 0,137,
+ 0, 80, 0,190, 0,195, 0,137, 0,159, 0, 51, 0, 76, 0, 89, 0,131, 0, 70, 1, 54, 0, 51, 0,137, 0, 51, 0, 70, 0,149,
+ 0,114, 0, 34,254,112, 0, 34, 0,109, 0, 57, 0, 51, 0,117, 0,137, 0,139, 0,155, 0,233, 0, 0, 0, 96, 0,132, 0, 33,
+ 0, 89, 0, 52, 0,190, 0,195, 0,186, 0,117, 0,162, 0,162, 0,201, 0,190, 0,139, 0, 86, 0,127, 0, 85, 0,139, 0,139,
+ 0,139, 0,197, 0,197,255,190, 0,215, 0,139, 0,139, 0,201, 0,201, 0,109,255,237, 0, 34,255,190, 0,137, 0,139, 0,104,
+ 0,137, 0, 37, 0,166, 0,166, 0,215, 0, 33, 0,197, 0, 15, 0,137, 0,139, 0,139, 0,137, 0, 4, 0, 86, 0,137, 0,117,
+ 0,137, 0,197, 0,139, 0, 47, 0,104, 0, 66, 0, 18, 0, 80, 0,137, 0,114, 0, 60, 0, 32, 0, 65, 0,197, 0,139, 0, 60,
+ 0, 76, 0,133, 0,125, 0,209, 1, 1, 0,105, 0,123, 0, 59, 0,169, 0,195, 0,195, 0,236, 0, 30, 0, 61, 0,195, 0,137,
+ 0,195, 0,190, 0,195, 0,225, 0,104, 0, 99, 0, 76, 0,124, 0,195, 0,125, 0, 80, 0, 30, 0,104, 0,195, 0,195, 0, 78,
+ 0,168, 0,123, 0,123, 0, 35, 1, 1, 0,195, 0,213, 0,178, 0,178, 0,186, 0, 10, 0, 65, 0, 35, 0,236, 0,195, 0,104,
+ 0,195, 0,215, 1, 1, 0, 85, 0,127, 0,215, 1, 1, 0, 15, 0, 59, 0,137, 0,169, 0,137, 0,236, 0, 31, 0, 98, 0,139,
+ 0,195, 0, 47, 0,225, 0, 37, 0, 92, 0, 37, 0, 92, 0, 18, 0, 76, 0,140, 0,195, 0,201, 0, 15, 0, 59, 0,137, 0,236,
+ 0,137, 0,195, 0,140, 0,195, 1,199, 0, 37, 0,133, 0, 37, 0,133, 0, 0, 0, 41, 0,197, 0,123, 0,117, 0,122, 0,117,
+ 0,122, 0, 15, 0, 59, 0,137, 0,169, 0, 26, 0,125, 0,139, 0,195, 0,139, 0,195, 0,117, 0,137, 0,117, 0,137, 0,117,
+ 0,137, 0,139, 0,195, 0,104, 0,104, 0,104, 0,104, 0,104, 0,104, 0,137, 0,195, 0,215, 1, 1, 0, 65, 0,104, 1,214,
+ 1,100, 1,214, 0,218, 1,178, 1, 0, 1,189, 0, 76, 1,189, 0, 25, 2, 12, 0, 69, 0,222, 0, 69, 0, 69, 0, 88, 0, 88,
+ 0, 88, 0,232, 0,232,255,204,255,204,255, 34,255, 34,255, 16,255, 16, 0, 10, 0, 10, 0,122, 0,122,255,236,255,182, 0, 31,
+ 0, 8, 0, 66, 0,130, 0, 54, 0,222, 0, 76, 0, 25, 0, 25, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 48, 1, 86,
+ 1, 0, 1,189, 1,189, 1, 92, 1,250, 1,150, 0,154, 0,134, 0,236, 0,202, 0,154, 0,126, 0,126, 0,161, 0,200, 1, 54,
+ 1,214, 0,146, 0, 69, 0, 31, 1,189, 0, 69, 0, 69, 0, 69, 0, 69, 0, 69, 0, 69, 0, 69, 0, 69, 0, 88, 0, 88, 0, 88,
+ 0, 88, 0, 88, 0, 88, 0, 88,255,204,255,204,255,204,255,182,255,182, 0, 10, 0, 10, 0, 66, 0, 54, 0, 0, 0, 76, 0, 25,
+ 0, 25, 0,222, 1,250, 1,150, 0,154, 0,134, 0,175, 0,172, 1, 8, 0,126, 0,126, 0,161, 0, 62, 0,108, 0,121, 0,246,
+ 0,124, 0, 97, 0,114, 0,123, 0,149, 0, 26, 0,106, 0, 75, 0,124, 0,124, 0, 99, 0, 99, 0,101, 0,101, 0, 16, 0,114,
+ 0,100, 0, 96, 0,111, 0, 97, 0, 19, 0,119, 0, 84, 0, 48, 0, 90,251,138, 0,157,252,198, 0, 83, 0, 83, 0, 83, 0, 83,
+ 1,207, 1,120, 0, 68,255,240, 2, 14, 0, 86, 0, 95, 1, 73,255,240, 1,150, 0,160, 0,158, 0,110, 0, 55, 0,160, 0,158,
+ 0,158, 0, 55, 0,159, 0,158, 0,160, 0,158, 0,158, 0, 55, 0,159, 0,159, 0, 55, 0,159, 0, 45, 0, 55, 0, 55, 0,160,
+ 0, 55, 0,158, 0, 55, 0,158, 0, 86, 0,158, 0,160, 0,159, 0,159, 0,159, 0,158, 0,118, 0,160, 0,159, 0,159, 0,139,
+ 0, 55, 0,107, 0,161, 0,109, 0,160, 1, 35, 1,149, 0, 41, 0,169, 0,178, 0, 14, 0,137, 0,136, 0, 43, 0, 63, 0, 43,
+ 0,252, 0,245, 1, 55, 1, 55, 1, 76, 1, 76, 1, 44, 1, 58, 1,100, 1, 94, 1, 18, 1, 69, 1, 27, 1, 60, 1, 60, 1, 46,
+ 1, 63, 1, 17, 1, 2, 1, 65, 0,228, 1, 69, 1, 69, 1, 71, 0,251, 1, 71, 1, 71, 1, 49, 1, 49, 1, 79, 1, 79, 1, 71,
+ 1, 73, 1, 56, 1, 37, 1, 91, 1, 58, 1, 88, 1, 58, 1, 58, 1, 71, 1, 77, 1, 91, 0,255, 1, 37, 1, 35, 1, 72, 1,153,
+ 1, 91, 1, 35, 0,123, 1, 58, 0,156, 0,160, 1, 71, 1, 88, 1, 81, 1, 58, 1, 79, 1, 87, 1, 98, 1, 71, 1, 91, 1, 67,
+ 1, 97, 1, 73, 1, 71, 1,100, 1, 85, 1, 85, 1,126, 1, 37, 1, 37, 1, 85, 1, 85, 1, 63, 1, 58, 1, 58, 1, 91, 1,120,
+ 1, 77, 0,208, 1, 32, 1, 70, 1, 17, 1, 97, 1, 94, 1, 77, 1, 51, 1, 58, 0, 37, 0,133, 0,166, 0,193, 0,166, 0,193,
+ 0,166, 0,193, 0,139, 0,195, 0,137, 0,123, 0,137, 0,123, 0,137, 0,123, 0,125, 0,123, 0,137, 0,123, 0,197, 0,123,
+ 0,197, 0,123, 0,197, 0,123, 0,233, 0,195, 0,102, 0,123, 0,137, 0,195, 0,137, 0,195, 0, 20, 0, 55, 0,137, 0,195,
+ 0,201, 0,178, 0,137, 0,236, 0,137, 0,236, 0,137, 0,236, 0,215, 0,160, 0,215, 0,160, 0,215, 0,160, 0,215, 0,160,
+ 0, 86, 0,109, 0, 86, 0,109, 0, 86, 0,109, 0,139, 0,195, 0,139, 0,195, 0,139, 0,195, 0,139, 0,195, 0,197, 0,190,
+ 0,143, 1,106, 0,143, 1,106, 0,143, 1, 61, 0,143, 1, 61, 0,139, 0,213, 0,139, 0,213, 0,139, 0,213, 0, 47, 0,131,
+ 0, 47, 0,131, 0, 47, 0,131, 0, 47, 0,131, 0,147, 0,195, 0,147, 0,195, 0,147, 0,195, 0, 57, 0,100, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 76, 0, 37, 0,104, 0,156, 0,203, 0,156, 0,203,
+ 0,195, 0,195, 0, 37, 0,133, 0, 37, 0,133, 0,197, 0,123, 0,197, 0,123, 0,201, 0,178, 0,117, 0,137, 0,147, 0,195,
+ 0, 37, 0,104, 0, 37, 0,104, 0, 37, 0,104, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70, 0, 37, 0, 37,
+254,108,254,108,255, 27,255, 7,255,193,255,143, 0,169, 0,169, 0,169, 0,169, 0,169, 0,169,255,127,255,127,253,139,253,139,
+254, 8,253,244, 0,195, 0,195, 0,195, 0,195, 0,195, 0,195, 0,195, 0,195,255, 77,255, 77,253, 64,253, 64,253,164,253,144,
+254, 99,254, 99, 1, 54, 1, 54, 0,245, 0,245, 1, 39, 1, 19, 1, 31, 1, 31,255,127,255,127,253,164,253,164,254, 8,253,244,
+254,174,254,174, 0,137, 0,137, 0,137, 0,137, 0,137, 0,137,255,202,255,127,253,139,253,139,254,158,254,138, 0, 51, 0, 51,
+ 0, 51, 0, 51, 0, 51, 0, 51, 0, 51, 0, 51,254,233,253, 64,253, 69,254, 24, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70,
+ 0, 70, 0, 70,255,202,255,102,253,139,253,139,254,183,254,163,254,249,254,174, 0, 70, 0, 70, 0,169, 0,169, 0,195, 0,195,
+ 1, 23, 1, 54, 0,137, 0,137, 0, 51, 0, 51, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70,
+ 0, 37, 0, 37,254,108,254,108,255, 27,255, 7,255,193,255,143, 0,195, 0,195, 0,195, 0,195, 0,195, 0,195, 0,195, 0,195,
+255, 77,255, 77,253, 64,253, 64,253,164,253,144,254, 99,254, 99, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70,
+255,202,255,102,253,139,253,139,254,183,254,163,254,249,254,174, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70, 0, 37,
+ 0, 37,255,135, 0, 25, 0, 37, 1,239, 2, 30, 1,239, 1, 31, 1, 31, 0,195, 0,195, 0,195, 0,195, 0,195,254,141,255, 31,
+254, 91,254,237, 0,137, 0,245, 1, 39, 1, 31, 1, 47, 1, 54, 1, 23, 1, 54, 1, 31, 1, 31, 0,201, 0,201,254,191,255, 31,
+ 0,245, 1, 19, 1, 31, 0, 51, 0, 51, 0, 51, 0, 51, 0,190, 0,190, 0, 51, 0, 51, 0, 37, 0, 37,254, 91,254,112,255,127,
+ 1, 23, 1, 63, 1, 23, 0, 70, 0, 70, 0, 70, 0, 70, 0, 70,254,166,255,181,254,166,255,206, 0, 74, 1,219, 1,239, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,100, 1,100, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1,207, 1,207, 1,147, 1,207, 0,211, 0,211, 0,211, 0,211, 0,162, 0,162, 1, 63, 1, 63, 0, 80, 0, 0, 0, 0,
+ 0, 0, 1, 90, 1,164, 0,208, 0,244, 0, 0, 1,207, 1, 90, 0, 33, 0, 33, 0,208, 0, 0, 1, 61, 1, 72, 1, 12, 1, 63,
+ 1, 73, 1, 61, 1, 59, 1, 48, 1, 28, 1, 28, 1, 28, 1,216, 1,216, 1, 65, 1, 61, 1, 88, 1, 66, 1, 70, 1, 12, 1, 63,
+ 1, 73, 1, 61, 1, 59, 1, 48, 1, 28, 1, 28, 1, 28, 1,216, 1,216, 1, 69, 1, 49, 1, 58, 1, 18, 1, 49, 0, 0, 0, 37,
+ 0,106, 0, 0, 0,130, 0,140, 0, 84, 0, 10, 0, 0, 0, 74, 0,137, 0, 37, 0, 27, 0, 27, 0, 27, 0, 27, 0, 27, 0, 10,
+ 0, 27, 0, 27, 0, 27, 0, 27, 0, 27, 0, 27, 0, 27, 0, 66, 1, 28, 0, 66, 1, 28, 0, 66, 1, 28, 0,184, 0,184, 0,184,
+ 0,184, 0, 66, 0, 66, 0, 89, 0, 89, 0, 66, 1, 28, 0, 66, 1, 28, 0, 66, 0, 66, 0, 66, 1, 28, 0, 66, 1, 28, 1, 28,
+ 0, 66, 0, 66, 0, 66, 0, 65, 0, 66, 0, 66, 0,113, 0,183, 0,183, 0,183, 0,183, 0,186, 0, 63, 0, 81, 0, 81, 0, 50,
+ 0, 66, 0, 88, 0, 88, 0, 66, 0, 66, 2, 22, 1, 28, 0, 66, 0, 66, 2, 22, 1, 71, 0, 66, 0, 42, 0, 66, 0, 66, 0, 42,
+ 0, 66, 0, 42, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 1, 28, 0, 66, 1, 28, 0, 66, 1, 28, 0,155, 0,155, 0,155,
+ 0,155, 0, 66, 0, 66, 0, 66, 0, 66, 1, 28, 1, 28, 0, 66, 1, 28, 0, 66, 1, 28, 0, 66, 0, 66, 0, 25, 0,243, 0, 66,
+ 0,243, 0,243, 0,243, 0,243, 0,243, 0,243, 0,243, 0, 66, 0, 69, 0, 69, 0,243, 0, 66, 0, 42, 0, 66, 0, 66, 0, 66,
+ 0, 66, 0, 66, 0, 66, 0, 66, 0, 25, 0, 66, 0, 25, 0,190, 0, 73,255,250,255,250, 0,129, 0,129, 0,130, 0,129, 0,129,
+ 0,130, 0,152, 0,143, 0, 88, 0, 88, 0,102, 0,166, 1, 43, 1, 63, 0, 59, 0,186, 0, 41, 0,125, 0,125, 0,164, 0,164,
+ 0,164, 0,164, 0,129, 0, 63, 0, 53, 0, 88, 0, 74, 0, 87, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88,
+ 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 87, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 87, 0, 74, 0, 74,
+ 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 69, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88,
+ 0, 86, 0, 86, 0, 86, 0, 86, 0, 87, 0, 88, 0, 88, 0, 88, 0, 88, 0, 86, 0, 86, 0, 86, 0, 86, 0, 86, 0, 86, 0, 86,
+ 0, 86, 0, 86, 0, 88, 0, 86, 0, 86, 0, 86, 0, 86, 0, 86, 0, 86, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88,
+ 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 88, 0, 79, 0, 79, 0, 79, 0, 79, 0, 79, 0, 79, 0, 79, 0, 79, 0, 79,
+ 0, 80, 0, 80, 0, 80, 0, 80, 1,233, 1, 8, 0, 88, 0, 88, 0, 88, 0, 86, 0, 88, 0, 86, 0, 86, 0, 86, 0, 86, 0, 88,
+ 0, 88, 0, 88, 0, 88, 0, 86, 0, 86, 0, 86, 0, 86, 0, 80, 0, 73, 0,114, 0,146, 0,146, 0,146, 0,146, 0,146, 1,207,
+ 1, 90, 1,207, 1, 90, 2, 37, 0, 13, 2, 37, 0, 13, 0, 88, 0, 97, 0, 6, 0, 6, 0,184, 0,166, 0, 71, 0, 88, 1, 43,
+ 1, 28, 1, 43, 1, 28, 2, 0, 0,124, 0,104, 0, 6, 0,125, 0, 50, 0, 6, 0, 72, 1, 0, 0, 6, 0, 6, 0, 6, 0, 6,
+ 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 37, 0, 6, 0, 6, 0, 6, 0, 37, 0, 6,
+ 0, 6, 0, 6, 1, 0, 0, 6, 0, 6, 1, 0, 0, 6, 0, 6,255,236, 0, 6, 1, 8, 1, 63, 0, 6, 0, 88, 0, 88, 0, 37,
+ 0, 88, 0, 88, 1, 0, 0, 6, 0, 6, 1, 54, 0,190, 0, 70, 0, 6, 0,156, 1, 0, 0, 6, 0, 70, 0, 26, 0, 72, 0, 6,
+ 0, 6, 0, 6, 0, 82, 0, 70, 0, 70, 0, 70, 0, 6, 1, 24, 1, 24, 1, 24, 1, 25, 2,246, 1, 25, 1, 24, 1, 24, 1, 24,
+ 1, 24, 2,245, 1, 24, 2, 12, 0, 17, 2, 12, 2, 12, 0, 16, 2, 11, 0, 16, 2, 1, 0, 25, 0, 6, 0,150,255,236,255,236,
+ 2, 24, 1,200,255,236,255,236, 2, 24, 1,200,255,235,255,236, 2, 24, 1,200, 2, 24, 2, 24, 1,200, 1,200,255,236,255,236,
+255,236,255,236, 2, 24, 2, 24, 1,200, 1,200,255,236,255,236,255,236,255,236, 2, 24, 2, 24, 1,200, 1,200, 1,200, 1,200,
+ 1,200, 1,200,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,
+255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,
+255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236, 2, 24, 1,200,255,236, 1,120,
+ 2, 24, 1,120, 1,120,255,236,255,236,255,236, 2, 24, 1,120, 1,120,255,236,255,236,255,236, 2, 24, 1,120, 1,120,255,236,
+255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236, 2, 24,255,236,255,236, 2, 24,255,147,
+255,147,255,147,255,236, 2, 24, 2,124, 2, 24,255,236, 1,200, 2,124, 1,200,255,236, 1,200,255,236, 1,200,255,236,255,236,
+255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236, 2,105,255,236,
+255,236,255,236,255,236, 4, 69,255,236, 2,105,255,236,255,236,255,236,255,236,255,236, 2,105,255,236,255,236, 0, 6, 0, 6,
+ 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0,219, 0,219, 0, 6, 0, 6, 1, 68, 1, 68, 0, 6, 0, 6,
+ 0, 6, 0, 6, 0,219, 0,219, 0, 6, 0, 6, 0,219, 0,219, 0, 6, 0, 6, 0, 6, 0, 6, 0,219, 0,219, 0, 6, 0, 6,
+ 0,219, 0,219, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0,117, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6,
+ 0, 6, 0, 6, 0, 6, 0, 6, 1, 55, 1, 55,255,236,255,236,255,236,255,236, 1, 55, 1, 55, 1, 55, 1, 55, 0, 6, 0, 6,
+ 0, 6, 0, 6, 0, 6, 0, 6, 1, 63, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6,255,236, 0, 6, 0, 6,
+ 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 97, 0, 97, 0,175, 0,175, 0, 6, 0, 34, 0, 50,
+ 0, 34, 0, 89, 0, 29, 0, 58, 0, 58, 0,200, 0, 59, 0, 43, 0, 15, 0, 18, 0, 54, 0, 46, 0, 20, 0, 8, 0,111, 0, 99,
+ 0,133, 0,201, 0, 28, 0, 78, 0, 56, 0, 47, 0, 38, 0, 47, 0, 47, 0, 47, 0, 14, 0,140, 0, 14, 0,140, 0, 12, 0, 9,
+ 0, 8, 0, 34, 0, 78, 0, 96, 0,121, 0, 97, 0,204, 0, 55, 0, 30, 0, 8, 0,103, 0, 15, 0, 27, 0, 14, 0, 5, 0, 33,
+ 0, 33, 0, 33, 0, 33, 0,156, 0,149, 0,189, 0,145, 0,145, 0, 21, 0, 71, 0,174, 0, 67, 0, 76, 0,215, 0, 24, 0, 53,
+ 0, 27, 0, 52, 0, 61, 0, 47, 0, 85, 0, 50, 0, 56, 0, 21, 0, 89, 0, 94, 0, 67, 0, 86, 0,112, 0,222, 0,144, 0,156,
+ 0,106, 0, 54, 0,148, 0,226, 0,103, 0,118, 0,128, 0, 14, 0,145, 0, 50, 0,127, 0, 11, 0,145, 0, 49, 0, 46, 1,114,
+ 0,162, 0,106, 0, 17, 1, 68, 1,177, 1, 55, 0, 96, 0, 46, 0, 47, 0, 60, 0, 75, 0, 68, 0, 36, 0, 62, 0, 75, 0, 45,
+ 0, 45, 0, 57, 0, 46, 0, 55, 0, 46, 0, 80, 0, 60, 0, 60, 0, 60, 0, 60, 0, 60, 0, 60, 0, 46, 0, 46, 0, 46, 0, 46,
+ 0, 82, 0, 82, 0,150, 0,115, 0, 39, 0, 31, 0,129, 0,188, 0, 19, 0, 22, 0, 74, 0, 30, 0, 42, 0, 82, 0, 42, 0, 34,
+ 0,136, 0,243, 0,222, 0, 46, 0, 46, 0, 58, 0, 61, 0, 52, 0, 37, 0, 61, 0, 63, 1, 68, 0, 45, 0, 87, 0, 38, 0, 87,
+ 0, 59, 0, 37, 0,152, 0, 74, 0,129, 0, 64, 0,131, 0, 51, 0, 64, 0, 86, 0, 57, 0, 48, 0,155, 0,126, 0,144, 0, 48,
+ 0, 71, 0, 31, 0, 28, 0, 26, 0, 23, 0, 43, 0, 37, 0, 40, 0, 67, 0, 40, 0, 35, 0, 40, 0, 61, 0, 40, 0, 46, 0, 54,
+ 0, 87, 0, 48, 0, 36, 0, 26, 0, 50, 0, 31, 0, 26, 0, 36, 0, 48, 0, 49, 0, 55, 0, 43, 0, 33, 0, 36, 0, 22, 0, 22,
+ 0, 37, 0, 50, 0, 32, 0, 48, 0, 25, 0, 50, 0, 41, 0, 33, 0, 23, 0, 34, 0, 36, 0, 69, 0, 61, 0, 56, 0, 48, 0, 43,
+ 2, 27, 1,205, 1, 81, 1,221, 1,211, 1, 0, 0,246, 0,103, 0,255, 0,190, 0, 46, 0,114, 0, 65, 0, 49, 0,240, 0,240,
+ 1,102, 1,110, 1, 67, 1, 68, 0,210, 0,210, 0,205, 0,206, 1,201, 1,201, 1, 25, 0,249, 0, 83, 0,116, 0, 83, 0,116,
+ 0, 45, 0, 73, 0, 83, 0, 45, 0, 54, 0, 83, 0, 83, 0, 96, 0,123, 0,123, 0, 54, 0, 54, 1, 79, 0, 54, 0,101, 0,101,
+ 0, 53, 0, 97, 0,125, 0, 84, 0, 50, 0, 41, 0,145, 0, 88, 0,116, 0, 83, 0,117, 0, 78, 0, 42, 0,117, 0, 53, 0, 29,
+ 0, 38, 0, 37, 0, 50, 0,117, 1,134, 1,134, 0,117, 0, 88, 0, 88, 0,150, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6,
+ 0, 6, 0, 6, 0, 6, 0,137, 0,195, 0, 76, 0,193, 0,218, 0,137, 0, 35, 0, 35, 0, 69, 0, 69,255,236,255,236, 0, 69,
+ 0, 69,255,236,255,236, 0, 69, 0, 69,255,236,255,236, 0, 69, 0, 69,255,236,255,236, 0, 69, 0, 69,255,236,255,236, 0, 69,
+ 0, 69,255,236,255,236,255,182,255,106,255,236,255,236,255,182,255,106,255,236,255,236, 0, 88, 0, 88,255,236,255,236, 0, 88,
+ 0, 88,255,236,255,236, 0, 88, 0, 88,255,236,255,236, 0, 88, 0, 88,255,236,255,236,255,204,255, 96,255,204,255, 96, 0, 10,
+255,131,255,236,255,236, 0, 10,255,131,255,236,255,236, 0, 54,255,213, 0, 0, 0, 0,255,236,255,236,255,236,255,236, 0, 25,
+255,124,255,236,255,236, 1, 68,255,236, 1, 68, 3, 34, 1, 68, 1, 68,255,236, 1, 68,255,236, 1, 68,255,236, 1, 48,255,236,
+ 1, 86,255,236, 1,178, 1, 0, 1, 0, 1,179, 1,228, 0, 76, 0, 90, 1,182, 2, 19, 0, 25,255,124,255,236,255,236, 2, 12,
+ 2, 76, 0, 69, 0, 69,255,236,255,236, 0,222, 0,242, 0, 69, 0, 69,255,236,255,236, 0, 69, 0, 69,255,236,255,236, 0, 88,
+ 0, 88,255,236,255,236, 0, 88, 0, 88,255,236,255,236, 0, 88, 0, 88,255,236,255,236, 0,232, 0,232, 0,232, 0,232,255,204,
+255, 96,255,204,255, 96,255, 34,254,214,255,236,255,236,255, 34,254,214,255,236,255,236,255, 16,254,197,255,236,255,236,255, 16,
+254,197,255,236,255,236, 0, 10, 0, 20,255,236,255,236, 0, 10, 0, 20,255,236,255,236, 0,122, 0,148,255,236,255,236, 0,122,
+ 0,148,255,236,255,236,255,182,255,106,255,236,255,236, 0, 31,255,237,255,236,255,236, 0, 8,255,161,255,236,255,236, 0, 66,
+ 0, 9,255,236,255,236, 0,130, 0, 71,255,236,255,236, 0, 54,255,213,255,236,255,236, 0,222, 0,242,255,236,255,236, 0, 76,
+ 0, 90, 0, 25,255,124, 0, 25,255,124,255,236,255,236,255,150,255, 64, 0, 83,255,224, 0,133, 0, 95, 0,179, 0, 95, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 0, 37, 0,166, 0,139, 0,137, 0,197, 0,233, 0,102, 0,137, 0,201, 0,109, 0,137,
+ 0,215, 0, 86, 0,139, 0,117, 0,197, 0,117, 0,143, 0,139, 0, 47, 0,147, 0, 57, 0, 0, 0, 18, 0, 37, 0,156, 0,133,
+ 0,193, 0,195, 0,123, 0,123, 0,195, 0,123, 0,195, 0,178, 0,186, 0,236, 0,160, 0,109, 0,195, 0,137, 0,190, 0,137,
+ 1,106, 0,213, 0,131, 0,195, 0,100, 0, 0, 0, 76, 0,104, 0,203, 0,133, 0,246, 0,152, 0,137, 0,102, 0,143, 0,133,
+ 0,139, 0,131, 0,127, 1,219, 1, 63, 1,219, 1, 31, 1,121, 1, 55, 1, 55, 0, 27, 1, 47, 1, 47, 2, 1, 1, 88, 0,187,
+ 1,102, 1, 61, 0,156, 0, 6, 1, 0, 1, 94, 1, 63, 0, 0, 0, 0, 0, 0, 0, 69,255,236,255,236,255,237,255,106, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,149, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 76, 0, 0, 0, 76, 0, 0, 0, 76,
+ 0, 0, 0,152, 0, 0, 0,220, 0, 0, 1,152, 0, 0, 2,152, 0, 0, 3,160, 0, 0, 4,252, 0, 0, 5, 44, 0, 0, 5,132,
+ 0, 0, 5,220, 0, 0, 6,120, 0, 0, 6,208, 0, 0, 7, 12, 0, 0, 7, 56, 0, 0, 7,100, 0, 0, 7,152, 0, 0, 9, 32,
+ 0, 0, 9,120, 0, 0, 10, 40, 0, 0, 10,232, 0, 0, 11,100, 0, 0, 12, 0, 0, 0, 12,184, 0, 0, 13, 20, 0, 0, 13,232,
+ 0, 0, 14,156, 0, 0, 14,224, 0, 0, 15, 52, 0, 0, 15,128, 0, 0, 15,196, 0, 0, 16, 12, 0, 0, 16,244, 0, 0, 18, 8,
+ 0, 0, 18,216, 0, 0, 19,128, 0, 0, 20, 12, 0, 0, 20,128, 0, 0, 20,220, 0, 0, 21, 44, 0, 0, 21,208, 0, 0, 22, 40,
+ 0, 0, 22,128, 0, 0, 22,236, 0, 0, 23,188, 0, 0, 23,244, 0, 0, 24,180, 0, 0, 25, 80, 0, 0, 25,208, 0, 0, 26, 68,
+ 0, 0, 26,236, 0, 0, 27,184, 0, 0, 28,180, 0, 0, 28,248, 0, 0, 29,132, 0, 0, 29,248, 0, 0, 31, 16, 0, 0, 32, 20,
+ 0, 0, 32,156, 0, 0, 33, 16, 0, 0, 33, 84, 0, 0, 33,140, 0, 0, 33,208, 0, 0, 34, 20, 0, 0, 34, 64, 0, 0, 34,132,
+ 0, 0, 35,112, 0, 0, 36, 0, 0, 0, 36,136, 0, 0, 37, 24, 0, 0, 37,192, 0, 0, 38, 56, 0, 0, 39, 0, 0, 0, 39,112,
+ 0, 0, 39,216, 0, 0, 40, 80, 0, 0, 41, 76, 0, 0, 41,164, 0, 0, 42,176, 0, 0, 43, 32, 0, 0, 43,152, 0, 0, 44, 44,
+ 0, 0, 44,192, 0, 0, 45, 80, 0, 0, 46, 60, 0, 0, 46,176, 0, 0, 47, 32, 0, 0, 47,172, 0, 0, 48,248, 0, 0, 49,228,
+ 0, 0, 50,208, 0, 0, 51, 88, 0, 0, 52, 36, 0, 0, 52, 84, 0, 0, 53, 36, 0, 0, 53,164, 0, 0, 53,164, 0, 0, 53,244,
+ 0, 0, 54,184, 0, 0, 55, 76, 0, 0, 56,100, 0, 0, 57, 56, 0, 0, 57,132, 0, 0, 58,168, 0, 0, 58,236, 0, 0, 60, 8,
+ 0, 0, 60,236, 0, 0, 61, 96, 0, 0, 61,152, 0, 0, 61,196, 0, 0, 63, 44, 0, 0, 63, 88, 0, 0, 63,208, 0, 0, 64, 60,
+ 0, 0, 64,240, 0, 0, 65,192, 0, 0, 66, 4, 0, 0, 66,180, 0, 0, 67, 16, 0, 0, 67, 64, 0, 0, 67, 80, 0, 0, 67,184,
+ 0, 0, 68, 72, 0, 0, 68,192, 0, 0, 68,224, 0, 0, 69, 0, 0, 0, 69, 32, 0, 0, 70, 20, 0, 0, 70, 56, 0, 0, 70, 92,
+ 0, 0, 70,140, 0, 0, 70,184, 0, 0, 70,240, 0, 0, 72, 36, 0, 0, 72,220, 0, 0, 72,244, 0, 0, 73, 12, 0, 0, 73, 36,
+ 0, 0, 73, 60, 0, 0, 73, 84, 0, 0, 73,108, 0, 0, 73,132, 0, 0, 73,172, 0, 0, 73,208, 0, 0, 74,108, 0, 0, 74,152,
+ 0, 0, 74,188, 0, 0, 74,224, 0, 0, 75, 16, 0, 0, 75, 60, 0, 0, 75,116, 0, 0, 75,232, 0, 0, 76,236, 0, 0, 77, 16,
+ 0, 0, 77, 52, 0, 0, 77,100, 0, 0, 77,156, 0, 0, 77,192, 0, 0, 78, 64, 0, 0, 79, 36, 0, 0, 79, 60, 0, 0, 79, 84,
+ 0, 0, 79,108, 0, 0, 79,132, 0, 0, 79,156, 0, 0, 79,180, 0, 0, 81, 4, 0, 0, 81, 28, 0, 0, 81, 52, 0, 0, 81, 76,
+ 0, 0, 81,100, 0, 0, 81,132, 0, 0, 81,156, 0, 0, 81,180, 0, 0, 81,216, 0, 0, 81,248, 0, 0, 83, 12, 0, 0, 83, 36,
+ 0, 0, 83, 60, 0, 0, 83, 84, 0, 0, 83,124, 0, 0, 83,172, 0, 0, 83,220, 0, 0, 84, 56, 0, 0, 85, 60, 0, 0, 85, 84,
+ 0, 0, 85,108, 0, 0, 85,148, 0, 0, 85,196, 0, 0, 85,220, 0, 0, 86,112, 0, 0, 86,136, 0, 0, 86,180, 0, 0, 86,204,
+ 0, 0, 86,252, 0, 0, 87, 20, 0, 0, 87, 44, 0, 0, 87, 68, 0, 0, 87, 92, 0, 0, 87,116, 0, 0, 87,140, 0, 0, 87,164,
+ 0, 0, 87,188, 0, 0, 87,212, 0, 0, 87,236, 0, 0, 88, 4, 0, 0, 88, 28, 0, 0, 88, 68, 0, 0, 88, 84, 0, 0, 89, 16,
+ 0, 0, 89, 40, 0, 0, 89, 64, 0, 0, 89, 88, 0, 0, 89,112, 0, 0, 89,136, 0, 0, 89,160, 0, 0, 89,184, 0, 0, 89,208,
+ 0, 0, 89,232, 0, 0, 90, 0, 0, 0, 90, 24, 0, 0, 90, 48, 0, 0, 90, 72, 0, 0, 90, 96, 0, 0, 90,120, 0, 0, 90,144,
+ 0, 0, 90,168, 0, 0, 90,192, 0, 0, 90,240, 0, 0, 91, 36, 0, 0, 91,176, 0, 0, 92, 68, 0, 0, 92,120, 0, 0, 92,144,
+ 0, 0, 92,184, 0, 0, 92,208, 0, 0, 92,248, 0, 0, 93, 16, 0, 0, 93, 40, 0, 0, 93, 64, 0, 0, 93, 88, 0, 0, 93,168,
+ 0, 0, 94, 80, 0, 0, 95, 0, 0, 0, 95, 24, 0, 0, 95, 48, 0, 0, 95, 72, 0, 0, 95, 96, 0, 0, 96, 92, 0, 0, 96,128,
+ 0, 0, 96,180, 0, 0, 96,204, 0, 0, 96,228, 0, 0, 96,252, 0, 0, 97, 20, 0, 0, 97, 44, 0, 0, 97, 68, 0, 0, 97,184,
+ 0, 0, 98, 72, 0, 0, 98, 96, 0, 0, 98,120, 0, 0, 98,144, 0, 0, 98,168, 0, 0, 98,192, 0, 0, 98,216, 0, 0, 98,240,
+ 0, 0, 99,128, 0, 0,100, 24, 0, 0,100, 68, 0, 0,100,100, 0, 0,100,140, 0, 0,100,180, 0, 0,100,204, 0, 0,100,228,
+ 0, 0,101,124, 0, 0,102,148, 0, 0,102,172, 0, 0,102,196, 0, 0,102,220, 0, 0,102,244, 0, 0,103, 12, 0, 0,103, 36,
+ 0, 0,103, 60, 0, 0,103, 84, 0, 0,103,108, 0, 0,103,132, 0, 0,103,156, 0, 0,103,180, 0, 0,103,204, 0, 0,103,228,
+ 0, 0,103,252, 0, 0,104, 20, 0, 0,104, 56, 0, 0,104, 80, 0, 0,104,184, 0, 0,105, 76, 0, 0,105,120, 0, 0,105,160,
+ 0, 0,105,204, 0, 0,105,236, 0, 0,106, 20, 0, 0,106, 60, 0, 0,106, 84, 0, 0,106,108, 0, 0,106,132, 0, 0,106,156,
+ 0, 0,106,180, 0, 0,106,204, 0, 0,106,240, 0, 0,107, 16, 0, 0,107, 52, 0, 0,107, 76, 0, 0,107,112, 0, 0,107,136,
+ 0, 0,107,160, 0, 0,107,184, 0, 0,107,208, 0, 0,107,232, 0, 0,108, 0, 0, 0,108,100, 0, 0,108,216, 0, 0,109,152,
+ 0, 0,109,168, 0, 0,110, 12, 0, 0,110,100, 0, 0,110,212, 0, 0,111, 96, 0, 0,111,212, 0, 0,112, 64, 0, 0,112, 80,
+ 0, 0,112,180, 0, 0,113, 8, 0, 0,113,108, 0, 0,114, 24, 0, 0,114,116, 0, 0,115, 20, 0, 0,115,200, 0, 0,116, 12,
+ 0, 0,116,120, 0, 0,116,252, 0, 0,117, 88, 0, 0,117,208, 0, 0,118, 16, 0, 0,118, 92, 0, 0,118,184, 0, 0,119, 12,
+ 0, 0,119, 84, 0, 0,119,160, 0, 0,120, 8, 0, 0,120, 76, 0, 0,120,144, 0, 0,120,252, 0, 0,121, 20, 0, 0,121, 44,
+ 0, 0,121,144, 0, 0,121,252, 0, 0,122,108, 0, 0,122,240, 0, 0,123, 92, 0, 0,123,212, 0, 0,124, 76, 0, 0,124, 92,
+ 0, 0,124,200, 0, 0,125, 44, 0, 0,125,104, 0, 0,125,196, 0, 0,126, 8, 0, 0,126, 36, 0, 0,126, 64, 0, 0,126,172,
+ 0, 0,127, 0, 0, 0,127, 88, 0, 0,127,188, 0, 0,128, 4, 0, 0,128, 76, 0, 0,128,184, 0, 0,129, 36, 0, 0,129,144,
+ 0, 0,129,252, 0, 0,130,104, 0, 0,130,200, 0, 0,131, 44, 0, 0,131, 72, 0, 0,131,100, 0, 0,131,168, 0, 0,131,184,
+ 0, 0,131,208, 0, 0,131,232, 0, 0,132, 0, 0, 0,132, 24, 0, 0,132, 48, 0, 0,132, 72, 0, 0,132,120, 0, 0,132,144,
+ 0, 0,132,176, 0, 0,132,208, 0, 0,132,240, 0, 0,133, 16, 0, 0,133, 48, 0, 0,133, 80, 0, 0,133,112, 0, 0,133,136,
+ 0, 0,133,152, 0, 0,133,184, 0, 0,133,208, 0, 0,133,240, 0, 0,134, 8, 0, 0,134, 32, 0, 0,134, 56, 0, 0,134, 80,
+ 0, 0,134,104, 0, 0,134,128, 0, 0,134,152, 0, 0,134,176, 0, 0,134,200, 0, 0,134,224, 0, 0,134,248, 0, 0,135, 16,
+ 0, 0,135, 40, 0, 0,135, 64, 0, 0,135, 88, 0, 0,135,112, 0, 0,135,212, 0, 0,135,236, 0, 0,136, 4, 0, 0,136, 28,
+ 0, 0,136, 52, 0, 0,136, 76, 0, 0,136,100, 0, 0,136,124, 0, 0,136,148, 0, 0,136,172, 0, 0,136,196, 0, 0,136,220,
+ 0, 0,136,244, 0, 0,137, 12, 0, 0,137, 36, 0, 0,137, 60, 0, 0,137, 84, 0, 0,137,108, 0, 0,137,132, 0, 0,137,156,
+ 0, 0,137,180, 0, 0,137,204, 0, 0,137,228, 0, 0,137,252, 0, 0,138, 20, 0, 0,138, 44, 0, 0,138, 68, 0, 0,138, 92,
+ 0, 0,138,116, 0, 0,138,140, 0, 0,138,164, 0, 0,138,188, 0, 0,138,212, 0, 0,138,236, 0, 0,139, 4, 0, 0,139, 28,
+ 0, 0,139, 52, 0, 0,139,120, 0, 0,140, 24, 0, 0,140,104, 0, 0,140,184, 0, 0,140,208, 0, 0,140,232, 0, 0,141, 0,
+ 0, 0,141, 24, 0, 0,141, 56, 0, 0,141, 80, 0, 0,141,112, 0, 0,141,136, 0, 0,141,160, 0, 0,141,184, 0, 0,141,216,
+ 0, 0,141,240, 0, 0,142, 8, 0, 0,142, 32, 0, 0,142,132, 0, 0,143, 16, 0, 0,143,132, 0, 0,143,228, 0, 0,144,128,
+ 0, 0,145, 28, 0, 0,145,124, 0, 0,146, 16, 0, 0,146,156, 0, 0,146,212, 0, 0,147, 32, 0, 0,147,192, 0, 0,148, 20,
+ 0, 0,148,104, 0, 0,148,144, 0, 0,149, 12, 0, 0,149,156, 0, 0,150, 44, 0, 0,150,216, 0, 0,151, 96, 0, 0,151,224,
+ 0, 0,152, 84, 0, 0,152,204, 0, 0,153, 48, 0, 0,153,208, 0, 0,154, 88, 0, 0,155, 32, 0, 0,155,212, 0, 0,156,144,
+ 0, 0,157, 16, 0, 0,157, 88, 0, 0,157,232, 0, 0,158, 92, 0, 0,158,200, 0, 0,159, 52, 0, 0,159,132, 0, 0,159,200,
+ 0, 0,160, 36, 0, 0,160,152, 0, 0,160,232, 0, 0,161, 28, 0, 0,161, 76, 0, 0,161,192, 0, 0,162, 32, 0, 0,162, 84,
+ 0, 0,162,220, 0, 0,163, 68, 0, 0,163,172, 0, 0,164, 44, 0, 0,164,140, 0, 0,164,240, 0, 0,165, 32, 0, 0,165,140,
+ 0, 0,165,240, 0, 0,166,128, 0, 0,167, 24, 0, 0,167, 84, 0, 0,167,144, 0, 0,167,224, 0, 0,168, 32, 0, 0,168,116,
+ 0, 0,168,180, 0, 0,168,240, 0, 0,169, 96, 0, 0,169,208, 0, 0,170,116, 0, 0,170,180, 0, 0,171, 20, 0, 0,171, 92,
+ 0, 0,171,192, 0, 0,172, 4, 0, 0,172, 72, 0, 0,172,176, 0, 0,173, 32, 0, 0,173,140, 0, 0,173,180, 0, 0,173,236,
+ 0, 0,174, 44, 0, 0,174, 92, 0, 0,174,164, 0, 0,175, 0, 0, 0,175,104, 0, 0,175,248, 0, 0,176, 84, 0, 0,176,180,
+ 0, 0,177, 20, 0, 0,177,136, 0, 0,178, 12, 0, 0,178,164, 0, 0,179, 44, 0, 0,179,188, 0, 0,179,236, 0, 0,180, 80,
+ 0, 0,180,136, 0, 0,180,168, 0, 0,181, 44, 0, 0,181,156, 0, 0,182, 12, 0, 0,182,136, 0, 0,183, 84, 0, 0,183,248,
+ 0, 0,184,168, 0, 0,185, 52, 0, 0,185,240, 0, 0,186,124, 0, 0,187, 40, 0, 0,187,100, 0, 0,187,200, 0, 0,188, 8,
+ 0, 0,188, 88, 0, 0,188,192, 0, 0,189, 36, 0, 0,189,132, 0, 0,189,188, 0, 0,189,252, 0, 0,190, 60, 0, 0,190,156,
+ 0, 0,191, 8, 0, 0,191, 64, 0, 0,191,128, 0, 0,191,144, 0, 0,191,160, 0, 0,191,176, 0, 0,191,192, 0, 0,191,252,
+ 0, 0,192, 56, 0, 0,192,148, 0, 0,192,240, 0, 0,193, 76, 0, 0,193,168, 0, 0,193,216, 0, 0,193,232, 0, 0,194, 24,
+ 0, 0,194, 40, 0, 0,194, 80, 0, 0,194,108, 0, 0,194,128, 0, 0,194,148, 0, 0,194,192, 0, 0,194,208, 0, 0,194,224,
+ 0, 0,195,132, 0, 0,195,232, 0, 0,197, 0, 0, 0,197, 16, 0, 0,197, 76, 0, 0,197,160, 0, 0,197,212, 0, 0,198, 80,
+ 0, 0,198,136, 0, 0,198,228, 0, 0,199, 4, 0, 0,199, 40, 0, 0,199, 80, 0, 0,199,120, 0, 0,199,152, 0, 0,199,168,
+ 0, 0,199,184, 0, 0,199,200, 0, 0,199,216, 0, 0,199,232, 0, 0,200, 20, 0, 0,200, 36, 0, 0,200,120, 0, 0,200,168,
+ 0, 0,200,184, 0, 0,201, 0, 0, 0,201, 16, 0, 0,201, 96, 0, 0,201,112, 0, 0,201,140, 0, 0,201,168, 0, 0,201,212,
+ 0, 0,201,236, 0, 0,202, 36, 0, 0,202, 64, 0, 0,202,104, 0, 0,202,140, 0, 0,202,168, 0, 0,202,188, 0, 0,202,208,
+ 0, 0,202,244, 0, 0,203, 24, 0, 0,203, 56, 0, 0,203,124, 0, 0,203,172, 0, 0,203,208, 0, 0,203,244, 0, 0,204, 32,
+ 0, 0,204, 60, 0, 0,204,108, 0, 0,204,156, 0, 0,204,200, 0, 0,205, 8, 0, 0,205,116, 0, 0,205,160, 0, 0,206, 28,
+ 0, 0,206, 44, 0, 0,206, 72, 0, 0,206,108, 0, 0,206,180, 0, 0,206,244, 0, 0,207, 48, 0, 0,207,132, 0, 0,207,184,
+ 0, 0,208,152, 0, 0,208,196, 0, 0,208,212, 0, 0,208,228, 0, 0,208,244, 0, 0,209, 16, 0, 0,209, 40, 0, 0,209, 68,
+ 0, 0,209, 96, 0, 0,209,144, 0, 0,209,180, 0, 0,209,224, 0, 0,210, 40, 0, 0,210, 92, 0, 0,210,188, 0, 0,210,212,
+ 0, 0,210,228, 0, 0,210,248, 0, 0,211, 56, 0, 0,211, 88, 0, 0,211,116, 0, 0,211,156, 0, 0,211,172, 0, 0,211,188,
+ 0, 0,211,212, 0, 0,211,236, 0, 0,211,252, 0, 0,212, 20, 0, 0,212, 44, 0, 0,212, 68, 0, 0,212, 92, 0, 0,212,116,
+ 0, 0,212,140, 0, 0,212,164, 0, 0,212,180, 0, 0,212,196, 0, 0,212,212, 0, 0,213, 52, 0, 0,213, 68, 0, 0,213, 84,
+ 0, 0,213,100, 0, 0,214, 4, 0, 0,214, 20, 0, 0,214, 36, 0, 0,214,124, 0, 0,214,140, 0, 0,214,156, 0, 0,214,252,
+ 0, 0,215, 12, 0, 0,215, 28, 0, 0,215, 44, 0, 0,215,160, 0, 0,215,176, 0, 0,215,192, 0, 0,216,160, 0, 0,216,176,
+ 0, 0,217, 84, 0, 0,217,252, 0, 0,218, 20, 0, 0,218, 44, 0, 0,218, 68, 0, 0,218, 92, 0, 0,218,116, 0, 0,218,140,
+ 0, 0,218,164, 0, 0,219, 52, 0, 0,219,168, 0, 0,219,228, 0, 0,220,136, 0, 0,220,152, 0, 0,221, 0, 0, 0,221,112,
+ 0, 0,222, 24, 0, 0,222,112, 0, 0,222,128, 0, 0,222,192, 0, 0,222,208, 0, 0,223, 32, 0, 0,223,156, 0, 0,223,172,
+ 0, 0,223,248, 0, 0,224,136, 0, 0,224,252, 0, 0,225,144, 0, 0,225,240, 0, 0,226, 84, 0, 0,227, 40, 0, 0,227,132,
+ 0, 0,227,224, 0, 0,228,100, 0, 0,228,124, 0, 0,228,148, 0, 0,228,172, 0, 0,228,196, 0, 0,228,220, 0, 0,229,104,
+ 0, 0,229,236, 0, 0,230, 84, 0, 0,230,108, 0, 0,230,132, 0, 0,231, 12, 0, 0,231,128, 0, 0,232, 32, 0, 0,232,136,
+ 0, 0,232,236, 0, 0,233, 92, 0, 0,233,208, 0, 0,233,224, 0, 0,234, 76, 0, 0,234,168, 0, 0,234,212, 0, 0,235, 72,
+ 0, 0,235,164, 0, 0,236, 64, 0, 0,236,176, 0, 0,236,192, 0, 0,236,208, 0, 0,237, 60, 0, 0,237,172, 0, 0,238, 28,
+ 0, 0,238, 44, 0, 0,238, 60, 0, 0,238, 76, 0, 0,238,136, 0, 0,238,192, 0, 0,239, 48, 0, 0,239,140, 0, 0,239,164,
+ 0, 0,239,188, 0, 0,239,212, 0, 0,239,236, 0, 0,240,124, 0, 0,240,148, 0, 0,241, 60, 0, 0,241, 76, 0, 0,241, 92,
+ 0, 0,241,128, 0, 0,241,144, 0, 0,241,244, 0, 0,242, 80, 0, 0,242,192, 0, 0,242,216, 0, 0,242,240, 0, 0,243, 8,
+ 0, 0,243, 56, 0, 0,243, 72, 0, 0,243,208, 0, 0,243,224, 0, 0,244, 24, 0, 0,244,168, 0, 0,244,184, 0, 0,245,132,
+ 0, 0,245,148, 0, 0,246, 0, 0, 0,246, 24, 0, 0,246, 40, 0, 0,246,140, 0, 0,246,156, 0, 0,246,172, 0, 0,246,188,
+ 0, 0,247, 0, 0, 0,247, 16, 0, 0,247, 32, 0, 0,247, 48, 0, 0,247,192, 0, 0,248,156, 0, 0,248,172, 0, 0,249, 0,
+ 0, 0,249,100, 0, 0,249,184, 0, 0,250, 32, 0, 0,250,148, 0, 0,251, 20, 0, 0,251,136, 0, 0,252, 48, 0, 0,252,224,
+ 0, 0,253,124, 0, 0,253,140, 0, 0,254, 88, 0, 0,254,240, 0, 0,255, 40, 0, 0,255,176, 0, 0,255,192, 0, 1, 0,140,
+ 0, 1, 0,156, 0, 1, 1, 8, 0, 1, 1, 32, 0, 1, 1, 48, 0, 1, 1,148, 0, 1, 2, 28, 0, 1, 2,112, 0, 1, 2,128,
+ 0, 1, 2,196, 0, 1, 2,212, 0, 1, 2,228, 0, 1, 3, 40, 0, 1, 3, 56, 0, 1, 4, 16, 0, 1, 4, 32, 0, 1, 4,116,
+ 0, 1, 4,216, 0, 1, 5, 44, 0, 1, 5,144, 0, 1, 6, 4, 0, 1, 6,128, 0, 1, 6,240, 0, 1, 7,164, 0, 1, 8, 76,
+ 0, 1, 8,224, 0, 1, 8,248, 0, 1, 9, 16, 0, 1, 9,116, 0, 1, 9,140, 0, 1, 10, 68, 0, 1, 10, 84, 0, 1, 10,100,
+ 0, 1, 10,132, 0, 1, 10,148, 0, 1, 10,248, 0, 1, 11, 72, 0, 1, 11,160, 0, 1, 11,184, 0, 1, 11,208, 0, 1, 11,232,
+ 0, 1, 12, 24, 0, 1, 12, 92, 0, 1, 12,160, 0, 1, 12,212, 0, 1, 13, 8, 0, 1, 13,100, 0, 1, 13,196, 0, 1, 14, 32,
+ 0, 1, 14,124, 0, 1, 14,148, 0, 1, 14,172, 0, 1, 14,236, 0, 1, 15, 44, 0, 1, 15,104, 0, 1, 15,164, 0, 1, 15,188,
+ 0, 1, 15,212, 0, 1, 16, 4, 0, 1, 16, 52, 0, 1, 16, 68, 0, 1, 16,116, 0, 1, 16,184, 0, 1, 16,244, 0, 1, 17, 60,
+ 0, 1, 17,132, 0, 1, 17,228, 0, 1, 17,244, 0, 1, 18, 4, 0, 1, 18, 28, 0, 1, 18, 52, 0, 1, 18,148, 0, 1, 18,248,
+ 0, 1, 19, 64, 0, 1, 19,136, 0, 1, 19,240, 0, 1, 20, 68, 0, 1, 20, 96, 0, 1, 20,144, 0, 1, 20,168, 0, 1, 20,224,
+ 0, 1, 20,248, 0, 1, 21, 8, 0, 1, 21, 24, 0, 1, 21, 48, 0, 1, 21, 72, 0, 1, 21, 88, 0, 1, 21,104, 0, 1, 21,128,
+ 0, 1, 21,152, 0, 1, 21,176, 0, 1, 21,200, 0, 1, 21,224, 0, 1, 21,248, 0, 1, 22, 8, 0, 1, 22, 24, 0, 1, 22, 48,
+ 0, 1, 22, 72, 0, 1, 22, 96, 0, 1, 22,120, 0, 1, 22,176, 0, 1, 22,220, 0, 1, 22,236, 0, 1, 22,252, 0, 1, 23, 20,
+ 0, 1, 23, 44, 0, 1, 23, 68, 0, 1, 23, 92, 0, 1, 23,116, 0, 1, 23,140, 0, 1, 23,164, 0, 1, 23,188, 0, 1, 23,212,
+ 0, 1, 23,236, 0, 1, 24, 4, 0, 1, 24, 28, 0, 1, 24, 72, 0, 1, 24,116, 0, 1, 24,140, 0, 1, 24,164, 0, 1, 24,196,
+ 0, 1, 25, 32, 0, 1, 25, 80, 0, 1, 25,192, 0, 1, 26, 48, 0, 1, 26, 72, 0, 1, 26, 96, 0, 1, 26,120, 0, 1, 26,144,
+ 0, 1, 26,168, 0, 1, 26,196, 0, 1, 26,220, 0, 1, 26,244, 0, 1, 27, 12, 0, 1, 27, 36, 0, 1, 27, 60, 0, 1, 27,168,
+ 0, 1, 27,192, 0, 1, 28, 20, 0, 1, 28, 44, 0, 1, 28,112, 0, 1, 28,136, 0, 1, 29, 72, 0, 1, 29, 96, 0, 1, 30, 20,
+ 0, 1, 30, 44, 0, 1, 30,144, 0, 1, 30,168, 0, 1, 31, 40, 0, 1, 31, 64, 0, 1, 31, 88, 0, 1, 31,112, 0, 1, 31,136,
+ 0, 1, 32, 68, 0, 1, 32,160, 0, 1, 33, 44, 0, 1, 33, 68, 0, 1, 33,172, 0, 1, 34, 44, 0, 1, 34,208, 0, 1, 34,232,
+ 0, 1, 35, 20, 0, 1, 35,180, 0, 1, 35,224, 0, 1, 35,252, 0, 1, 36,140, 0, 1, 36,168, 0, 1, 37, 44, 0, 1, 37,112,
+ 0, 1, 37,180, 0, 1, 37,196, 0, 1, 37,216, 0, 1, 38, 0, 0, 1, 38, 28, 0, 1, 38, 76, 0, 1, 38,164, 0, 1, 39, 32,
+ 0, 1, 39,164, 0, 1, 40, 16, 0, 1, 40, 88, 0, 1, 40,168, 0, 1, 40,248, 0, 1, 41,120, 0, 1, 41,172, 0, 1, 41,236,
+ 0, 1, 42, 16, 0, 1, 42, 68, 0, 1, 42,152, 0, 1, 43, 72, 0, 1, 43,160, 0, 1, 43,184, 0, 1, 43,208, 0, 1, 43,232,
+ 0, 1, 44, 8, 0, 1, 44, 32, 0, 1, 44, 56, 0, 1, 44, 80, 0, 1, 44,104, 0, 1, 44,128, 0, 1, 44,152, 0, 1, 44,176,
+ 0, 1, 44,200, 0, 1, 44,224, 0, 1, 44,248, 0, 1, 45, 16, 0, 1, 45, 40, 0, 1, 45, 64, 0, 1, 45, 88, 0, 1, 46, 8,
+ 0, 1, 46, 32, 0, 1, 46,168, 0, 1, 46,192, 0, 1, 46,216, 0, 1, 47, 56, 0, 1, 48, 8, 0, 1, 48, 32, 0, 1, 48, 48,
+ 0, 1, 48, 72, 0, 1, 48, 88, 0, 1, 48,104, 0, 1, 48,120, 0, 1, 48,136, 0, 1, 48,152, 0, 1, 49, 24, 0, 1, 49,156,
+ 0, 1, 50, 4, 0, 1, 50, 20, 0, 1, 50, 36, 0, 1, 50, 52, 0, 1, 50,244, 0, 1, 51,132, 0, 1, 52, 60, 0, 1, 52,172,
+ 0, 1, 53, 44, 0, 1, 53,224, 0, 1, 54,116, 0, 1, 55, 0, 0, 1, 55,128, 0, 1, 55,240, 0, 1, 56,176, 0, 1, 57, 24,
+ 0, 1, 57,124, 0, 1, 57,220, 0, 1, 58,180, 0, 1, 59, 64, 0, 1, 59,208, 0, 1, 60, 96, 0, 1, 60,172, 0, 1, 61, 64,
+ 0, 1, 61,216, 0, 1, 62,116, 0, 1, 62,228, 0, 1, 63,164, 0, 1, 64, 80, 0, 1, 64,236, 0, 1, 65,164, 0, 1, 66, 36,
+ 0, 1, 66, 64, 0, 1, 66,160, 0, 1, 66,236, 0, 1, 67, 4, 0, 1, 67, 72, 0, 1, 67,148, 0, 1, 67,228, 0, 1, 68, 60,
+ 0, 1, 68,132, 0, 1, 68,212, 0, 1, 69, 56, 0, 1, 69,140, 0, 1, 69,168, 0, 1, 70, 8, 0, 1, 70,164, 0, 1, 70,208,
+ 0, 1, 70,228, 0, 1, 71, 20, 0, 1, 71,104, 0, 1, 71,204, 0, 1, 72, 72, 0, 1, 72,212, 0, 1, 73, 48, 0, 1, 73,172,
+ 0, 1, 74, 40, 0, 1, 74,160, 0, 1, 74,236, 0, 1, 75, 84, 0, 1, 75,184, 0, 1, 76, 28, 0, 1, 76,128, 0, 1, 76,236,
+ 0, 1, 77, 92, 0, 1, 77,184, 0, 1, 78, 56, 0, 1, 78,136, 0, 1, 78,228, 0, 1, 79,104, 0, 1, 80, 8, 0, 1, 80,112,
+ 0, 1, 80,248, 0, 1, 81, 84, 0, 1, 81,212, 0, 1, 82, 68, 0, 1, 82,188, 0, 1, 83, 12, 0, 1, 83,140, 0, 1, 84, 32,
+ 0, 1, 84,112, 0, 1, 84,220, 0, 1, 85, 92, 0, 1, 86, 20, 0, 1, 86,124, 0, 1, 86,232, 0, 1, 87, 96, 0, 1, 87,228,
+ 0, 1, 88,108, 0, 1, 88,224, 0, 1, 89, 68, 0, 1, 89,180, 0, 1, 90, 24, 0, 1, 90, 76, 0, 1, 90,156, 0, 1, 91, 92,
+ 0, 1, 91,232, 0, 1, 92, 32, 0, 1, 92,200, 0, 1, 92,252, 0, 1, 93, 48, 0, 1, 93,116, 0, 1, 93,208, 0, 1, 94, 56,
+ 0, 1, 94,108, 0, 1, 94,180, 0, 1, 95, 28, 0, 1, 95, 92, 0, 1, 95,140, 0, 1, 95,188, 0, 1, 96, 24, 0, 1, 96, 72,
+ 0, 1, 96,120, 0, 1, 96,184, 0, 1, 96,240, 0, 1, 97, 16, 0, 1, 97, 72, 0, 1, 97,120, 0, 1, 97,168, 0, 1, 97,240,
+ 0, 1, 98, 52, 0, 1, 98,148, 0, 1, 98,188, 0, 1, 99, 32, 0, 1, 99, 88, 0, 1, 99,212, 0, 1,100, 80, 0, 1,100,164,
+ 0, 1,101, 96, 0, 1,101,180, 0, 1,102, 12, 0, 1,102,104, 0, 1,102,196, 0, 1,103, 56, 0, 1,103,172, 0, 1,104, 32,
+ 0, 1,104, 88, 0, 1,104,144, 0, 1,104,248, 0, 1,105, 88, 0, 1,105,164, 0, 1,105,244, 0, 1,106, 36, 0, 1,106, 84,
+ 0, 1,106,168, 0, 1,106,232, 0, 1,107, 44, 0, 1,107,112, 0, 1,107,216, 0, 1,108, 0, 0, 1,108, 20, 0, 1,108, 40,
+ 0, 1,108, 60, 0, 1,108, 80, 0, 1,108,204, 0, 1,108,220, 0, 1,109, 36, 0, 1,109,120, 0, 1,109,204, 0, 1,110, 28,
+ 0, 1,110,160, 0, 1,111, 32, 0, 1,111,148, 0, 1,111,212, 0, 1,112, 28, 0, 1,112,136, 0, 1,112,204, 0, 1,113, 16,
+ 0, 1,113, 68, 0, 1,113,116, 0, 1,113,176, 0, 1,114, 12, 0, 1,114, 64, 0, 1,114,144, 0, 1,114,176, 0, 1,115, 56,
+ 0, 1,115,160, 0, 1,115,244, 0, 1,116, 96, 0, 1,116,144, 0, 1,117, 0, 0, 1,117,148, 0, 1,118, 64, 0, 1,118,136,
+ 0, 1,118,236, 0, 1,119, 84, 0, 1,119,176, 0, 1,120, 4, 0, 1,120, 44, 0, 1,120, 92, 0, 1,120,168, 0, 1,121, 4,
+ 0, 1,121, 96, 0, 1,121,184, 0, 1,121,208, 0, 1,121,232, 0, 1,122, 0, 0, 1,122, 24, 0, 1,122, 48, 0, 1,122, 72,
+ 0, 1,122, 96, 0, 1,122,120, 0, 1,122,152, 0, 1,122,180, 0, 1,122,204, 0, 1,122,228, 0, 1,122,252, 0, 1,123, 20,
+ 0, 1,123, 44, 0, 1,123, 68, 0, 1,123, 92, 0, 1,123,116, 0, 1,123,140, 0, 1,123,164, 0, 1,123,188, 0, 1,123,212,
+ 0, 1,123,236, 0, 1,124, 4, 0, 1,124, 32, 0, 1,124, 60, 0, 1,124, 84, 0, 1,124,108, 0, 1,124,132, 0, 1,124,156,
+ 0, 1,124,180, 0, 1,124,204, 0, 1,124,228, 0, 1,124,252, 0, 1,125, 20, 0, 1,125, 44, 0, 1,125, 68, 0, 1,125, 92,
+ 0, 1,125,116, 0, 1,125,140, 0, 1,125,164, 0, 1,125,188, 0, 1,125,212, 0, 1,125,236, 0, 1,126, 4, 0, 1,126, 28,
+ 0, 1,126, 52, 0, 1,126, 76, 0, 1,126,100, 0, 1,126,124, 0, 1,126,148, 0, 1,126,172, 0, 1,126,196, 0, 1,126,220,
+ 0, 1,126,244, 0, 1,127, 12, 0, 1,127, 36, 0, 1,127, 60, 0, 1,127, 84, 0, 1,127,108, 0, 1,127,132, 0, 1,127,156,
+ 0, 1,127,180, 0, 1,127,204, 0, 1,127,228, 0, 1,127,252, 0, 1,128, 20, 0, 1,128, 44, 0, 1,128, 68, 0, 1,128, 92,
+ 0, 1,128,116, 0, 1,128,140, 0, 1,128,164, 0, 1,128,188, 0, 1,128,212, 0, 1,128,236, 0, 1,129, 4, 0, 1,129, 28,
+ 0, 1,129, 52, 0, 1,129, 76, 0, 1,129,100, 0, 1,129,124, 0, 1,129,152, 0, 1,129,180, 0, 1,129,204, 0, 1,129,228,
+ 0, 1,129,252, 0, 1,130, 20, 0, 1,130, 44, 0, 1,130, 68, 0, 1,130, 92, 0, 1,130,116, 0, 1,130,140, 0, 1,130,164,
+ 0, 1,130,188, 0, 1,130,212, 0, 1,130,236, 0, 1,131, 4, 0, 1,131, 28, 0, 1,131, 52, 0, 1,131, 76, 0, 1,131,100,
+ 0, 1,131,124, 0, 1,131,148, 0, 1,131,172, 0, 1,131,196, 0, 1,131,220, 0, 1,131,244, 0, 1,132, 12, 0, 1,132, 36,
+ 0, 1,132, 60, 0, 1,132, 84, 0, 1,132,108, 0, 1,132,132, 0, 1,132,156, 0, 1,132,180, 0, 1,132,204, 0, 1,132,228,
+ 0, 1,132,252, 0, 1,133, 20, 0, 1,133, 44, 0, 1,133, 68, 0, 1,133,100, 0, 1,133,124, 0, 1,133,148, 0, 1,133,172,
+ 0, 1,133,196, 0, 1,133,220, 0, 1,133,244, 0, 1,134, 12, 0, 1,134, 36, 0, 1,134, 60, 0, 1,134, 84, 0, 1,134,108,
+ 0, 1,134,132, 0, 1,134,156, 0, 1,134,180, 0, 1,134,204, 0, 1,134,228, 0, 1,134,252, 0, 1,135, 20, 0, 1,135, 44,
+ 0, 1,135, 68, 0, 1,135, 92, 0, 1,135,116, 0, 1,135,140, 0, 1,135,164, 0, 1,135,188, 0, 1,135,212, 0, 1,135,236,
+ 0, 1,136, 4, 0, 1,136, 28, 0, 1,136, 52, 0, 1,136, 76, 0, 1,136,100, 0, 1,136,124, 0, 1,136,148, 0, 1,136,172,
+ 0, 1,136,196, 0, 1,136,220, 0, 1,136,244, 0, 1,137, 12, 0, 1,137, 36, 0, 1,137, 60, 0, 1,137, 84, 0, 1,137,108,
+ 0, 1,137,132, 0, 1,137,156, 0, 1,137,180, 0, 1,137,204, 0, 1,137,228, 0, 1,137,252, 0, 1,138, 20, 0, 1,138, 44,
+ 0, 1,138, 68, 0, 1,138, 92, 0, 1,138,116, 0, 1,138,140, 0, 1,138,164, 0, 1,138,188, 0, 1,138,212, 0, 1,138,236,
+ 0, 1,139, 4, 0, 1,139, 28, 0, 1,139, 52, 0, 1,139, 76, 0, 1,139,100, 0, 1,139,124, 0, 1,139,148, 0, 1,139,172,
+ 0, 1,139,196, 0, 1,139,220, 0, 1,139,244, 0, 1,140, 12, 0, 1,140, 36, 0, 1,140, 60, 0, 1,140, 84, 0, 1,140,108,
+ 0, 1,140,132, 0, 1,140,156, 0, 1,140,180, 0, 1,140,204, 0, 1,140,228, 0, 1,140,252, 0, 1,141, 20, 0, 1,141, 44,
+ 0, 1,141, 68, 0, 1,141, 92, 0, 1,141,116, 0, 1,141,140, 0, 1,141,164, 0, 1,141,188, 0, 1,141,212, 0, 1,141,236,
+ 0, 1,142, 4, 0, 1,142, 28, 0, 1,142, 52, 0, 1,142, 76, 0, 1,142,100, 0, 1,142,124, 0, 1,142,148, 0, 1,142,172,
+ 0, 1,142,196, 0, 1,142,220, 0, 1,142,244, 0, 1,143, 12, 0, 1,143, 36, 0, 1,143, 60, 0, 1,143, 84, 0, 1,143,108,
+ 0, 1,143,132, 0, 1,143,156, 0, 1,143,180, 0, 1,143,204, 0, 1,143,228, 0, 1,143,252, 0, 1,144, 20, 0, 1,144, 44,
+ 0, 1,144, 68, 0, 1,144, 92, 0, 1,144,116, 0, 1,144,132, 0, 1,144,156, 0, 1,144,172, 0, 1,144,196, 0, 1,144,212,
+ 0, 1,144,236, 0, 1,144,252, 0, 1,145, 20, 0, 1,145, 36, 0, 1,145, 60, 0, 1,145, 76, 0, 1,145,100, 0, 1,145,116,
+ 0, 1,145,140, 0, 1,145,164, 0, 1,145,188, 0, 1,145,212, 0, 1,145,236, 0, 1,146, 4, 0, 1,146, 28, 0, 1,146, 52,
+ 0, 1,146, 76, 0, 1,146,100, 0, 1,146,124, 0, 1,146,148, 0, 1,146,172, 0, 1,146,196, 0, 1,146,220, 0, 1,146,244,
+ 0, 1,147, 12, 0, 1,147, 36, 0, 1,147, 60, 0, 1,147, 84, 0, 1,147,108, 0, 1,147,132, 0, 1,147,156, 0, 1,147,180,
+ 0, 1,147,204, 0, 1,147,228, 0, 1,147,252, 0, 1,148, 20, 0, 1,148, 44, 0, 1,148, 68, 0, 1,148, 92, 0, 1,148,116,
+ 0, 1,148,140, 0, 1,148,164, 0, 1,148,188, 0, 1,148,212, 0, 1,148,236, 0, 1,149, 4, 0, 1,149, 28, 0, 1,149, 52,
+ 0, 1,149, 76, 0, 1,149,100, 0, 1,149,124, 0, 1,149,148, 0, 1,149,172, 0, 1,149,196, 0, 1,149,220, 0, 1,149,244,
+ 0, 1,150, 12, 0, 1,150, 36, 0, 1,150, 60, 0, 1,150, 84, 0, 1,150,108, 0, 1,150,132, 0, 1,150,156, 0, 1,150,180,
+ 0, 1,150,204, 0, 1,150,228, 0, 1,150,244, 0, 1,151, 12, 0, 1,151, 28, 0, 1,151, 44, 0, 1,151, 80, 0, 1,151, 96,
+ 0, 1,151,120, 0, 1,151,144, 0, 1,151,168, 0, 1,151,192, 0, 1,151,216, 0, 1,151,240, 0, 1,152, 8, 0, 1,152, 24,
+ 0, 1,152, 48, 0, 1,152, 64, 0, 1,152, 88, 0, 1,152,116, 0, 1,152,140, 0, 1,152,164, 0, 1,152,188, 0, 1,152,212,
+ 0, 1,152,236, 0, 1,152,252, 0, 1,153, 20, 0, 1,153, 44, 0, 1,153, 68, 0, 1,153, 92, 0, 1,153,116, 0, 1,153,132,
+ 0, 1,153,160, 0, 1,153,184, 0, 1,153,208, 0, 1,153,232, 0, 1,154, 0, 0, 1,154, 24, 0, 1,154, 40, 0, 1,154, 64,
+ 0, 1,154, 88, 0, 1,154,112, 0, 1,154,136, 0, 1,154,160, 0, 1,154,184, 0, 1,154,208, 0, 1,154,224, 0, 1,154,248,
+ 0, 1,155, 16, 0, 1,155, 32, 0, 1,155, 48, 0, 1,155, 72, 0, 1,155, 96, 0, 1,155,120, 0, 1,155,144, 0, 1,155,168,
+ 0, 1,155,192, 0, 1,155,208, 0, 1,155,232, 0, 1,155,248, 0, 1,156, 16, 0, 1,156, 32, 0, 1,156, 68, 0, 1,156, 68,
+ 0, 1,156, 68, 0, 1,156, 68, 0, 1,156, 68, 0, 1,156, 68, 0, 1,156, 68, 0, 1,156, 68, 0, 1,156, 68, 0, 1,156, 68,
+ 0, 1,156, 68, 0, 1,156, 68, 0, 1,156,112, 0, 1,156,128, 0, 1,156,172, 0, 1,156,216, 0, 1,157, 0, 0, 1,157, 40,
+ 0, 1,157, 64, 0, 1,157,124, 0, 1,157,184, 0, 1,157,244, 0, 1,158, 24, 0, 1,158,116, 0, 1,158,208, 0, 1,159, 48,
+ 0, 1,159,100, 0, 1,159,188, 0, 1,160, 64, 0, 1,160,128, 0, 1,160,156, 0, 1,160,244, 0, 1,160,244, 0, 1,162, 68,
+ 0, 1,163,112, 0, 1,163,180, 0, 1,163,252, 0, 1,164, 24, 0, 1,164,148, 0, 1,164,168, 0, 1,164,216, 0, 1,165, 8,
+ 0, 1,165, 36, 0, 1,165, 64, 0, 1,165, 92, 0, 1,165, 92, 0, 1,165,228, 0, 1,166, 28, 0, 1,166,140, 0, 1,166,244,
+ 0, 1,167,116, 0, 1,167,156, 0, 1,168, 84, 0, 1,168,224, 0, 1,169, 16, 0, 1,169, 44, 0, 1,169, 84, 0, 1,169,136,
+ 0, 1,169,188, 0, 1,170, 32, 0, 1,170, 52, 0, 1,170, 72, 0, 1,170, 92, 0, 1,170,112, 0, 1,170,132, 0, 1,170,152,
+ 0, 1,170,172, 0, 1,170,192, 0, 1,170,212, 0, 1,170,232, 0, 1,170,252, 0, 1,171, 16, 0, 1,171, 36, 0, 1,171, 56,
+ 0, 1,171, 76, 0, 1,171, 96, 0, 1,171,116, 0, 1,171,136, 0, 1,171,156, 0, 1,171,176, 0, 1,172, 52, 0, 1,173, 68,
+ 0, 1,173,196, 0, 1,174,100, 0, 1,174,248, 0, 1,175,108, 0, 1,175,200, 0, 1,176, 68, 0, 1,176,248, 0, 1,177, 8,
+ 0, 1,177, 24, 0, 1,177, 40, 0, 1,177, 72, 0, 1,177,104, 0, 1,177,136, 0, 1,177,168, 0, 1,177,200, 0, 1,177,232,
+ 0, 1,178, 8, 0, 1,178, 40, 0, 1,178, 72, 0, 1,178,104, 0, 1,178,136, 0, 1,178,168, 0, 1,178,192, 0, 1,178,240,
+ 0, 1,179, 36, 0, 1,179, 88, 0, 1,179,136, 0, 1,179,208, 0, 1,180, 24, 0, 1,180, 72, 0, 1,180,120, 0, 1,180,164,
+ 0, 1,180,208, 0, 1,181, 24, 0, 1,181, 96, 0, 1,182, 8, 0, 1,182,176, 0, 1,182,248, 0, 1,183, 64, 0, 1,183,136,
+ 0, 1,183,208, 0, 1,184, 16, 0, 1,184, 80, 0, 1,184,140, 0, 1,184,200, 0, 1,185, 4, 0, 1,185, 64, 0, 1,185,140,
+ 0, 1,186, 20, 0, 1,186,160, 0, 1,187,100, 0, 1,188, 44, 0, 1,189, 68, 0, 1,189,164, 0, 1,189,232, 0, 1,190, 32,
+ 0, 1,190, 88, 0, 1,190,144, 0, 1,190,200, 0, 1,191, 0, 0, 1,191, 56, 0, 1,191,196, 0, 1,192, 84, 0, 1,192,144,
+ 0, 1,192,248, 0, 1,193,160, 0, 1,194, 72, 0, 1,194,108, 0, 1,194,148, 0, 1,194,188, 0, 1,194,228, 0, 1,195, 12,
+ 0, 1,195, 52, 0, 1,195, 88, 0, 1,195,124, 0, 1,195,208, 0, 1,196, 36, 0, 1,196,120, 0, 1,196,192, 0, 1,197, 8,
+ 0, 1,197, 80, 0, 1,197,152, 0, 1,197,212, 0, 1,198, 20, 0, 1,198,120, 0, 1,198,244, 0, 1,199, 88, 0, 1,199,152,
+ 0, 1,199,216, 0, 1,200, 24, 0, 1,200, 88, 0, 1,200,180, 0, 1,201, 16, 0, 1,201, 80, 0, 1,201,144, 0, 1,201,208,
+ 0, 1,202, 16, 0, 1,202, 80, 0, 1,202,144, 0, 1,202,228, 0, 1,203, 60, 0, 1,203,140, 0, 1,203,220, 0, 1,204, 36,
+ 0, 1,204,112, 0, 1,204,184, 0, 1,205, 4, 0, 1,205, 64, 0, 1,205,124, 0, 1,205,188, 0, 1,205,248, 0, 1,206, 52,
+ 0, 1,206,112, 0, 1,206,200, 0, 1,207, 24, 0, 1,207,120, 0, 1,207,216, 0, 1,208, 48, 0, 1,208,160, 0, 1,208,244,
+ 0, 1,209, 56, 0, 1,209,124, 0, 1,209,204, 0, 1,210,108, 0, 1,210,188, 0, 1,211, 24, 0, 1,211, 92, 0, 1,211,160,
+ 0, 1,211,248, 0, 1,212, 72, 0, 1,212,152, 0, 1,213, 0, 0, 1,213, 52, 0, 1,213,104, 0, 1,213,184, 0, 1,214,116,
+ 0, 1,215, 64, 0, 1,215,188, 0, 1,215,232, 0, 1,216, 68, 0, 1,216,212, 0, 1,217,104, 0, 1,217,196, 0, 1,218, 84,
+ 0, 1,218,164, 0, 1,218,236, 0, 1,219, 92, 0, 1,219,136, 0, 1,219,200, 0, 1,219,252, 0, 1,220, 16, 0, 1,220, 36,
+ 0, 1,220, 52, 0, 1,220,152, 0, 1,221, 16, 0, 1,221,212, 0, 1,221,248, 0, 1,222, 32, 0, 1,222, 72, 0, 1,222,112,
+ 0, 1,222,228, 0, 1,223, 92, 0, 1,223,204, 0, 1,224,100, 0, 1,225, 60, 0, 1,225, 84, 0, 1,225,140, 0, 1,225,188,
+ 0, 1,225,220, 0, 1,226, 56, 0, 1,226,148, 0, 1,227, 0, 0, 1,227, 96, 0, 1,227,200, 0, 1,228, 76, 0, 1,228,196,
+ 0, 1,229, 92, 0, 1,229,244, 0, 1,230,232, 0, 1,231,148, 0, 1,232, 76, 0, 1,233, 64, 0, 1,233,184, 0, 1,234, 4,
+ 0, 1,234,192, 0, 1,235, 52, 0, 1,235, 76, 0, 1,235,116, 0, 1,235,148, 0, 1,235,180, 0, 1,235,244, 0, 1,236, 60,
+ 0, 1,236,152, 0, 1,237, 4, 0, 1,237, 76, 0, 1,237,140, 0, 1,237,204, 0, 1,238, 24, 0, 1,238, 96, 0, 1,239, 68,
+ 0, 1,239,200, 0, 1,240, 84, 0, 1,240,216, 0, 1,241, 12, 0, 1,241,104, 0, 1,241,168, 0, 1,242, 8, 0, 1,242,100,
+ 0, 1,242,168, 0, 1,242,232, 0, 1,243, 72, 0, 1,243,172, 0, 1,244, 20, 0, 1,244,104, 0, 1,244,188, 0, 1,245, 36,
+ 0, 1,245,136, 0, 1,246, 0, 0, 1,246,136, 0, 1,247, 40, 0, 1,247,212, 0, 1,248, 24, 0, 1,248, 92, 0, 1,248,224,
+ 0, 1,249,104, 0, 1,249,164, 0, 1,249,220, 0, 1,250, 68, 0, 1,250,172, 0, 1,251, 64, 0, 1,251,208, 0, 1,252, 56,
+ 0, 1,252,160, 0, 1,252,232, 0, 1,253, 44, 0, 1,253,152, 0, 1,254, 4, 0, 1,254, 88, 0, 1,254,168, 0, 1,255, 36,
+ 0, 1,255,176, 0, 2, 0, 24, 0, 2, 0,132, 0, 2, 0,220, 0, 2, 1, 52, 0, 2, 1,176, 0, 2, 2, 48, 0, 2, 2,248,
+ 0, 2, 3,168, 0, 2, 4,116, 0, 2, 5, 40, 0, 2, 5,216, 0, 2, 6,192, 0, 2, 7,176, 0, 2, 8,112, 0, 2, 9, 36,
+ 0, 2, 9,116, 0, 2, 9,172, 0, 2, 10, 12, 0, 2, 10, 68, 0, 2, 10,116, 0, 2, 10,164, 0, 2, 11, 12, 0, 2, 11, 92,
+ 0, 2, 11,176, 0, 2, 11,232, 0, 2, 12, 28, 0, 2, 12,132, 0, 2, 12,236, 0, 2, 13,132, 0, 2, 14, 24, 0, 2, 14,108,
+ 0, 2, 14,188, 0, 2, 15, 8, 0, 2, 15, 84, 0, 2, 15,208, 0, 2, 16, 84, 0, 2, 16,248, 0, 2, 17,152, 0, 2, 17,172,
+ 0, 2, 17,188, 0, 2, 17,232, 0, 2, 18, 32, 0, 2, 18, 72, 0, 2, 18,112, 0, 2, 18,164, 0, 2, 18,228, 0, 2, 19, 4,
+ 0, 2, 19, 36, 0, 2, 19, 68, 0, 2, 19,100, 0, 2, 19,140, 0, 2, 19,180, 0, 2, 19,220, 0, 2, 20, 4, 0, 2, 20, 36,
+ 0, 2, 20,120, 0, 2, 20,136, 0, 2, 20,204, 0, 2, 21, 16, 0, 2, 21,104, 0, 2, 22, 80, 0, 2, 22,116, 0, 2, 22,152,
+ 0, 2, 22,184, 0, 2, 22,216, 0, 2, 22,248, 0, 2, 23, 80, 0, 2, 23,168, 0, 2, 23,224, 0, 2, 24, 68, 0, 2, 24,156,
+ 0, 2, 29, 72, 0, 2, 29,172, 0, 2, 29,212, 0, 2, 30, 0, 0, 2, 30, 68, 0, 2, 30,148, 0, 2, 30,240, 0, 2, 31, 8,
+ 0, 2, 31,148, 0, 2, 32, 24, 0, 2, 32, 48, 0, 2, 32,104, 0, 2, 32,156, 0, 2, 32,232, 0, 2, 33, 52, 0, 2, 33,128,
+ 0, 2, 33,208, 0, 2, 34, 96, 0, 2, 34,176, 0, 2, 34,248, 0, 2, 35, 72, 0, 2, 35,152, 0, 2, 35,228, 0, 2, 36, 48,
+ 0, 2, 36,128, 0, 2, 36,208, 0, 2, 36,232, 0, 2, 37, 0, 0, 2, 37, 24, 0, 2, 37, 48, 0, 2, 37, 72, 0, 2, 37, 96,
+ 0, 2, 37,120, 0, 2, 37,144, 0, 2, 37,168, 0, 2, 37,192, 0, 2, 37,220, 0, 2, 37,244, 0, 2, 38, 12, 0, 2, 38,168,
+ 0, 2, 39,116, 0, 2, 39,216, 0, 2, 40, 24, 0, 2, 40,128, 0, 2, 40,152, 0, 2, 40,168, 0, 2, 40,184, 0, 2, 40,200,
+ 0, 2, 40,224, 0, 2, 40,248, 0, 2, 41, 16, 0, 2, 41, 40, 0, 2, 41, 56, 0, 2, 41,136, 0, 2, 42, 32, 0, 2, 42,204,
+ 0, 2, 43,204, 0, 2, 44,156, 0, 2, 45,204, 0, 2, 46,112, 0, 2, 47, 28, 0, 2, 47,156, 0, 2, 47,200, 0, 2, 48, 0,
+ 0, 2, 48, 28, 0, 2, 48, 84, 0, 2, 48,140, 0, 2, 48,168, 0, 2, 48,224, 0, 2, 49, 0, 0, 2, 49, 28, 0, 2, 49, 64,
+ 0, 2, 49,100, 0, 2, 49,128, 0, 2, 49,160, 0, 2, 49,212, 0, 2, 50, 44, 0, 2, 50,100, 0, 2, 50,128, 0, 2, 50,184,
+ 0, 2, 51, 16, 0, 2, 51, 68, 0, 2, 51, 96, 0, 2, 51,172, 0, 2, 51,216, 0, 2, 52, 28, 0, 2, 52, 56, 0, 2, 52, 84,
+ 0, 2, 52,112, 0, 2, 52,140, 0, 2, 52,192, 0, 2, 52,248, 0, 2, 53, 48, 0, 2, 53,108, 0, 2, 53,164, 0, 2, 53,228,
+ 0, 2, 54, 44, 0, 2, 54,120, 0, 2, 54,156, 0, 2, 54,192, 0, 2, 54,228, 0, 2, 55, 8, 0, 2, 55, 44, 0, 2, 55, 80,
+ 0, 2, 55,116, 0, 2, 55,152, 0, 2, 55,184, 0, 2, 55,220, 0, 2, 56, 0, 0, 2, 56, 36, 0, 2, 56, 68, 0, 2, 56,100,
+ 0, 2, 56,132, 0, 2, 56,168, 0, 2, 56,208, 0, 2, 56,248, 0, 2, 57, 36, 0, 2, 57, 80, 0, 2, 57,120, 0, 2, 57,168,
+ 0, 2, 57,212, 0, 2, 57,252, 0, 2, 58, 36, 0, 2, 58, 76, 0, 2, 58,120, 0, 2, 58,164, 0, 2, 58,204, 0, 2, 58,252,
+ 0, 2, 59, 40, 0, 2, 59, 80, 0, 2, 59,120, 0, 2, 59,164, 0, 2, 59,208, 0, 2, 59,248, 0, 2, 60, 32, 0, 2, 60, 76,
+ 0, 2, 60,120, 0, 2, 60,160, 0, 2, 60,196, 0, 2, 60,240, 0, 2, 61, 28, 0, 2, 61, 68, 0, 2, 61,108, 0, 2, 61,152,
+ 0, 2, 61,196, 0, 2, 61,236, 0, 2, 62, 28, 0, 2, 62, 80, 0, 2, 62,132, 0, 2, 62,184, 0, 2, 62,236, 0, 2, 63, 32,
+ 0, 2, 63, 84, 0, 2, 63,140, 0, 2, 63,196, 0, 2, 63,252, 0, 2, 64, 52, 0, 2, 64,104, 0, 2, 64,156, 0, 2, 64,208,
+ 0, 2, 65, 4, 0, 2, 65, 56, 0, 2, 65, 92, 0, 2, 65,136, 0, 2, 65,180, 0, 2, 65,224, 0, 2, 66, 8, 0, 2, 66, 48,
+ 0, 2, 66, 92, 0, 2, 66,136, 0, 2, 66,188, 0, 2, 66,232, 0, 2, 67, 20, 0, 2, 67, 72, 0, 2, 67,116, 0, 2, 67,160,
+ 0, 2, 67,212, 0, 2, 68, 0, 0, 2, 68, 44, 0, 2, 68, 96, 0, 2, 68,144, 0, 2, 68,196, 0, 2, 69, 8, 0, 2, 69, 56,
+ 0, 2, 69,108, 0, 2, 69,172, 0, 2, 69,224, 0, 2, 70, 16, 0, 2, 70, 80, 0, 2, 70,132, 0, 2, 70,180, 0, 2, 70,244,
+ 0, 2, 71, 60, 0, 2, 71,128, 0, 2, 71,220, 0, 2, 72, 16, 0, 2, 72, 72, 0, 2, 72,120, 0, 2, 72,172, 0, 2, 72,204,
+ 0, 2, 72,232, 0, 2, 73, 40, 0, 2, 73, 68, 0, 2, 73, 96, 0, 2, 73,124, 0, 2, 73,152, 0, 2, 73,180, 0, 2, 73,208,
+ 0, 2, 73,236, 0, 2, 74, 8, 0, 2, 74, 44, 0, 2, 74, 84, 0, 2, 74,120, 0, 2, 74,160, 0, 2, 74,180, 0, 2, 74,208,
+ 0, 2, 74,236, 0, 2, 75, 8, 0, 2, 75, 36, 0, 2, 75, 64, 0, 2, 75, 92, 0, 2, 75,120, 0, 2, 75,148, 0, 2, 75,176,
+ 0, 2, 75,204, 0, 2, 75,232, 0, 2, 76, 4, 0, 2, 76, 32, 0, 2, 76, 60, 0, 2, 76, 88, 0, 2, 76,108, 0, 2, 77, 32,
+ 0, 2, 78,168, 0, 2, 79, 80, 0, 2, 79,100, 0, 2, 79,120, 0, 2, 79,148, 0, 2, 79,168, 0, 2, 79,188, 0, 2, 79,216,
+ 0, 2, 79,240, 0, 2, 80, 12, 0, 2, 80, 40, 0, 2, 80, 60, 0, 2, 80, 84, 0, 2, 80,112, 0, 2, 80,140, 0, 2, 80,184,
+ 0, 2, 81, 12, 0, 2, 81, 36, 0, 2, 81,124, 0, 2, 81,216, 0, 2, 83, 12, 0, 2, 83,148, 0, 2, 84, 28, 0, 2, 85,188,
+ 0, 2, 85,216, 0, 2, 86, 4, 0, 2, 86, 32, 0, 2, 86, 76, 0, 2, 86,104, 0, 2, 86,148, 0, 2, 86,180, 0, 2, 86,228,
+ 0, 2, 87, 0, 0, 2, 87, 40, 0, 2, 87, 68, 0, 2, 87,112, 0, 2, 87,140, 0, 2, 87,184, 0, 2, 87,212, 0, 2, 88, 0,
+ 0, 2, 88, 28, 0, 2, 88, 68, 0, 2, 88, 96, 0, 2, 88,140, 0, 2, 88,168, 0, 2, 88,208, 0, 2, 88,236, 0, 2, 89, 24,
+ 0, 2, 89, 52, 0, 2, 89, 92, 0, 2, 89,120, 0, 2, 89,160, 0, 2, 89,192, 0, 2, 89,244, 0, 2, 90, 56, 0, 2, 90,196,
+ 0, 2, 91, 24, 0, 2, 91,124, 0, 2, 92,116, 0, 2, 93, 40, 0, 2, 93,220, 0, 2, 94, 20, 0, 2, 94,104, 0, 2, 94,188,
+ 0, 2, 95, 20, 0, 2, 95,108, 0, 2, 95,208, 0, 2, 96, 32, 0, 2, 96, 72, 0, 2, 96,112, 0, 2, 96,176, 0, 2, 97, 36,
+ 0, 2, 97,116, 0, 2, 97,200, 0, 2, 97,248, 0, 2, 98, 36, 0, 2, 98, 80, 0, 2, 98,124, 0, 2, 98,192, 0, 2, 99, 4,
+ 0, 2, 99, 32, 0, 2, 99, 60, 0, 2, 99, 84, 0, 2, 99,108, 0, 2, 99,184, 0, 2, 99,228, 0, 2,100, 16, 0, 2,100, 56,
+ 0, 2,100, 96, 0, 2,100,156, 0, 2,100,232, 0, 2,101, 20, 0, 2,101, 60, 0, 2,101,160, 0, 2,101,224, 0, 2,102, 28,
+ 0, 2,102, 92, 0, 2,102,156, 0, 2,103, 16, 0, 2,103,132, 0, 2,103,252, 0, 2,104,116, 0, 2,104,156, 0, 2,104,196,
+ 0, 2,104,236, 0, 2,105, 24, 0, 2,105, 52, 0, 2,105, 96, 0, 2,105,124, 0, 2,105,164, 0, 2,106,148, 0, 2,107, 0,
+ 0, 2,107,180, 0, 2,111,192, 0, 2,114,128, 0, 2,114,180, 0, 2,115, 16, 0, 2,115, 96, 0, 2,115,192, 0, 2,116, 72,
+ 0, 2,117, 16, 0, 2,117,216, 0, 2,118, 60, 0, 2,118,216, 0, 2,121, 12, 0, 2,123,176, 0, 2,123,232, 0, 2,124, 96,
+ 0, 2,124,212, 0, 2,125, 44, 0, 2,126,132, 0, 2,128, 28, 0, 2,128,100, 0, 2,128,152, 0, 2,129,100, 0, 2,130, 40,
+ 0, 2,130,192, 0, 2,131, 88, 0, 2,132, 28, 0, 2,132,228, 0, 2,133,168, 0, 2,134,108, 0, 2,137,220, 0, 2,138, 88,
+ 0, 2,139,112, 0, 2,140,196, 0, 2,143,236, 0, 2,144,104, 0, 2,144,240, 0, 2,145, 96, 0, 2,145,196, 0, 2,146, 72,
+ 0, 2,146,216, 0, 2,148, 24, 0, 2,149, 60, 0, 2,149,212, 0, 2,150, 96, 0, 2,151, 8, 0, 2,152,120, 0, 2,153, 52,
+ 0, 2,153,244, 0, 2,154,136, 0, 2,155,160, 0, 2,156, 52, 0, 2,156,200, 0, 2,157,136, 0, 2,158, 8, 0, 2,158,132,
+ 0, 2,159, 16, 0, 2,159,112, 0, 2,159,212, 0, 2,160,116, 0, 2,161, 32, 0, 2,161,132, 0, 2,161,240, 0, 2,162,128,
+ 0, 2,162,224, 0, 2,163,152, 0, 2,164, 84, 0, 2,165, 24, 0, 2,165,136, 0, 2,166, 40, 0, 2,166,112, 0, 2,167, 8,
+ 0, 2,167,204, 0, 2,168, 72, 0, 2,169,112, 0, 2,171,148, 0, 2,172, 44, 0, 2,173, 72, 0, 2,174, 92, 0, 2,175,108,
+ 0, 2,176,248, 0, 2,177,240, 0, 2,178,112, 0, 2,179, 52, 0, 2,179,252, 0, 2,180,140, 0, 2,180,252, 0, 2,181,156,
+ 0, 2,181,228, 0, 2,182,132, 0, 2,183, 72, 0, 2,183,156, 0, 2,183,204, 0, 2,184,236, 0, 2,185,208, 0, 2,186, 16,
+ 0, 2,186,108, 0, 2,186,208, 0, 2,187, 48, 0, 2,187,128, 0, 2,187,208, 0, 2,188,100, 0, 2,189, 36, 0, 2,190, 8,
+ 0, 2,192, 0, 0, 2,192,228, 0, 2,193,244, 0, 2,195, 28, 0, 2,196, 8, 0, 2,197, 24, 0, 2,198, 56, 0, 2,199, 20,
+ 0, 2,199,212, 0, 2,200,216, 0, 2,202, 8, 0, 2,203, 84, 0, 2,204, 72, 0, 2,204,224, 0, 2,205, 80, 0, 2,206, 8,
+ 0, 2,207, 0, 0, 2,208, 64, 0, 2,209,196, 0, 2,211,140, 0, 2,212, 32, 0, 2,212,216, 0, 2,213, 64, 0, 2,213,204,
+ 0, 2,213,232, 0, 2,214, 16, 0, 2,214,112, 0, 2,214,176, 0, 2,215, 36, 0, 2,216, 24, 0, 2,217, 76, 0, 2,218, 96,
+ 0, 2,219, 8, 0, 2,219,132, 0, 2,220, 36, 0, 2,221, 36, 0, 2,222,240, 0, 2,225,132, 0, 2,227, 48, 0, 2,227,180,
+ 0, 2,228, 0, 0, 2,228, 40, 0, 2,228,112, 0, 2,230, 52, 0, 2,231,208, 0, 2,233,140, 0, 2,237, 68, 0, 2,238,236,
+ 0, 2,240,144, 0, 2,241, 24, 0, 2,241,192, 0, 2,244,100, 0, 2,246, 0, 0, 2,247, 48, 0, 2,248, 44, 0, 2,249, 88,
+ 0, 2,250, 56, 0, 2,250,188, 0, 2,251, 32, 0, 2,251,132, 0, 2,251,200, 0, 2,252, 12, 0, 2,252,212, 0, 2,253,200,
+ 0, 2,254, 72, 0, 2,254,124, 0, 2,254,184, 0, 2,254,252, 0, 2,255, 44, 0, 2,255,140, 0, 2,255,252, 0, 3, 0,228,
+ 0, 3, 1,116, 0, 3, 2, 48, 0, 3, 3,176, 0, 3, 5,120, 0, 3, 8,208, 0, 3, 9, 56, 0, 3, 9,252, 0, 3, 10, 96,
+ 0, 3, 10,244, 0, 3, 11,132, 0, 3, 12, 64, 0, 3, 12,192, 0, 3, 13, 52, 0, 3, 13,172, 0, 3, 14, 20, 0, 3, 14, 96,
+ 0, 3, 14,192, 0, 3, 15, 36, 0, 3, 15,124, 0, 3, 16, 44, 0, 3, 16,112, 0, 3, 16,192, 0, 3, 17, 16, 0, 3, 17,120,
+ 0, 3, 18, 36, 0, 3, 19,216, 0, 3, 21,216, 0, 3, 23, 24, 0, 3, 25, 72, 0, 3, 26,228, 0, 3, 29,176, 0, 3, 35,172,
+ 0, 3, 37, 8, 0, 3, 39, 88, 0, 3, 40, 24, 0, 3, 40,208, 0, 3, 41,148, 0, 3, 43, 20, 0, 3, 44,144, 0, 3, 45,228,
+ 0, 3, 47, 52, 0, 3, 48,120, 0, 3, 48,240, 0, 3, 49, 36, 0, 3, 49, 88, 0, 3, 49,136, 0, 3, 49,184, 0, 3, 50, 16,
+ 0, 3, 50, 44, 0, 3, 50, 72, 0, 3, 50,100, 0, 3, 50,136, 0, 3, 50,172, 0, 3, 50,200, 0, 3, 50,228, 0, 3, 51,220,
+ 0, 3, 52,136, 0, 3, 53, 92, 0, 3, 53,216, 0, 3, 54, 88, 0, 3, 55,120, 0, 3, 56, 92, 0, 3, 56,200, 0, 3, 57, 52,
+ 0, 3, 57,112, 0, 3, 57,176, 0, 3, 57,216, 0, 3, 58, 0, 0, 3, 58, 40, 0, 3, 58, 80, 0, 3, 58,120, 0, 3, 58,160,
+ 0, 3, 58,200, 0, 3, 58,240, 0, 3, 59, 84, 0, 3, 59,196, 0, 3, 59,244, 0, 3, 60, 32, 0, 3, 60, 76, 0, 3, 60,120,
+ 0, 3, 60,168, 0, 3, 61, 76, 0, 3, 61,116, 0, 3, 61,156, 0, 3, 61,236, 0, 3, 62, 60, 0, 3, 62,100, 0, 3, 62,148,
+ 0, 3, 62,196, 0, 3, 62,232, 0, 3, 63, 60, 0, 3, 63,144, 0, 3, 63,188, 0, 3, 63,232, 0, 3, 64, 44, 0, 3, 64,112,
+ 0, 3, 64,192, 0, 3, 65, 12, 0, 3, 65, 88, 0, 3, 65,164, 0, 3, 65,248, 0, 3, 66, 76, 0, 3, 66,192, 0, 3, 67, 92,
+ 0, 3, 67,180, 0, 3, 67,252, 0, 3, 68, 84, 0, 3, 68,252, 0, 3, 69,148, 0, 3, 70, 56, 0, 3, 71, 20, 0, 3, 71,176,
+ 0, 3, 72,220, 0, 3, 74, 16, 0, 3, 74,168, 0, 3, 74,228, 0, 3, 75, 12, 0, 3, 75, 52, 0, 3, 75, 84, 0, 3, 75,152,
+ 0, 3, 75,236, 0, 3, 75,252, 0, 3, 76, 40, 0, 3, 76, 84, 0, 3, 76,124, 0, 3, 76,164, 0, 3, 76,212, 0, 3, 77, 4,
+ 0, 3, 77, 52, 0, 3, 77,100, 0, 3, 78, 8, 0, 3, 78, 44, 0, 3, 78, 84, 0, 3, 78,212, 0, 3, 79, 80, 0, 3, 79, 96,
+ 0, 3, 79,216, 0, 3, 80,120, 0, 3, 81, 0, 0, 3, 81, 24, 0, 3, 81, 48, 0, 3, 81, 72, 0, 3, 81, 96, 0, 3, 81,120,
+ 0, 3, 81,144, 0, 3, 81,168, 0, 3, 81,192, 0, 3, 81,216, 0, 3, 81,240, 0, 3, 82, 8, 0, 3, 82, 32, 0, 3, 82, 56,
+ 0, 3, 82, 80, 0, 3, 82,104, 0, 3, 82,128, 0, 3, 82,152, 0, 3, 82,176, 0, 3, 82,200, 0, 3, 82,224, 0, 3, 82,248,
+ 0, 3, 83, 16, 0, 3, 83, 40, 0, 3, 83, 64, 0, 3, 83, 88, 0, 3, 83,112, 0, 3, 83,136, 0, 3, 83,160, 0, 3, 83,184,
+ 0, 3, 83,208, 0, 3, 83,232, 0, 3, 84, 0, 0, 3, 84, 24, 0, 3, 84, 48, 0, 3, 84, 72, 0, 3, 84, 96, 0, 3, 84,120,
+ 0, 3, 84,144, 0, 3, 84,168, 0, 3, 84,192, 0, 3, 84,216, 0, 3, 84,240, 0, 3, 85, 8, 0, 3, 85, 32, 0, 3, 85, 56,
+ 0, 3, 85, 80, 0, 3, 85,104, 0, 3, 85,128, 0, 3, 85,152, 0, 3, 85,176, 0, 3, 85,200, 0, 3, 85,224, 0, 3, 85,240,
+ 0, 3, 86,140, 0, 3, 86,156, 0, 3, 86,172, 0, 3, 86,196, 0, 3, 86,220, 0, 3, 86,244, 0, 3, 87, 12, 0, 3, 87, 28,
+ 0, 3, 87,148, 0, 3, 87,164, 0, 3, 88,116, 0, 3, 88,132, 0, 3, 89, 56, 0, 3, 89,108, 0, 3, 89,176, 0, 3, 89,192,
+ 0, 3, 89,208, 0, 3, 89,232, 0, 3, 90, 0, 0, 3, 90, 16, 0, 3, 90, 40, 0, 3, 90, 56, 0, 3, 90,108, 0, 3, 90,124,
+ 0, 3, 90,140, 0, 3, 90,164, 0, 3, 90,180, 0, 3, 90,204, 0, 3, 90,220, 0, 3, 90,244, 0, 3, 91, 4, 0, 3, 91, 28,
+ 0, 3, 91, 44, 0, 3, 91, 68, 0, 3, 91, 84, 0, 3, 91,108, 0, 3, 91,132, 0, 3, 91,156, 0, 3, 91,180, 0, 3, 91,204,
+ 0, 3, 91,228, 0, 3, 91,252, 0, 3, 92, 20, 0, 3, 92, 44, 0, 3, 92, 68, 0, 3, 92, 92, 0, 3, 92,116, 0, 3, 92,132,
+ 0, 3, 92,184, 0, 3, 92,208, 0, 3, 92,232, 0, 3, 93, 0, 0, 3, 93, 24, 0, 3, 93, 48, 0, 3, 93, 72, 0, 3, 93, 96,
+ 0, 3, 93,120, 0, 3, 93,144, 0, 3, 93,168, 0, 3, 93,192, 0, 3, 93,216, 0, 3, 93,240, 0, 3, 94, 8, 0, 3, 94, 32,
+ 0, 3, 94, 56, 0, 3, 94, 80, 0, 3, 94,104, 0, 3, 94,120, 0, 3, 95, 16, 0, 3, 95,120, 0, 3, 95,252, 0, 3, 96, 20,
+ 0, 3, 96, 44, 0, 3, 96, 68, 0, 3, 96, 92, 0, 3, 96,108, 0, 3, 96,212, 0, 3, 96,236, 0, 3, 97, 4, 0, 3, 97, 20,
+ 0, 3, 97,108, 0, 3, 97,132, 0, 3, 97,156, 0, 3, 97,172, 0, 3, 98,128, 0, 3, 99, 16, 0, 3, 99,176, 0, 3, 99,200,
+ 0, 3, 99,224, 0, 3, 99,248, 0, 3,100, 16, 0, 3,100, 32, 0, 3,100,240, 0, 3,101,116, 0, 3,102, 16, 0, 3,102, 40,
+ 0, 3,102, 64, 0, 3,102, 88, 0, 3,102,112, 0, 3,102,128, 0, 3,102,248, 0, 3,103, 92, 0, 3,103,212, 0, 3,103,236,
+ 0, 3,104, 4, 0, 3,104, 28, 0, 3,104, 52, 0, 3,104, 68, 0, 3,104,240, 0, 3,105, 72, 0, 3,105,216, 0, 3,105,240,
+ 0, 3,106, 8, 0, 3,106, 32, 0, 3,106, 56, 0, 3,106, 80, 0, 3,106,104, 0, 3,106,128, 0, 3,106,152, 0, 3,106,176,
+ 0, 3,106,200, 0, 3,106,224, 0, 3,106,248, 0, 3,107, 8, 0, 3,107,212, 0, 3,108, 64, 0, 3,108,200, 0, 3,108,216,
+ 0, 3,109, 76, 0, 3,109,132, 0, 3,109,204, 0, 3,109,220, 0, 3,110,120, 0, 3,110,252, 0, 3,111,140, 0, 3,111,164,
+ 0, 3,111,188, 0, 3,111,212, 0, 3,111,236, 0, 3,111,252, 0, 3,112,116, 0, 3,113, 48, 0, 3,113,192, 0, 3,113,208,
+ 0, 3,114,100, 0, 3,114,116, 0, 3,115, 24, 0, 3,115, 48, 0, 3,115, 72, 0, 3,115, 96, 0, 3,115,120, 0, 3,115,144,
+ 0, 3,115,168, 0, 3,115,192, 0, 3,115,216, 0, 3,115,240, 0, 3,116, 8, 0, 3,116, 92, 0, 3,116,196, 0, 3,116,196,
+ 0, 3,116,196, 0, 3,116,196, 0, 3,116,196, 0, 3,116,196, 0, 3,117, 84, 0, 3,117,100, 0, 3,117,116, 0, 3,117,132,
+ 0, 3,117,148, 0, 3,117,164, 0, 3,117,180, 0, 3,117,196, 0, 3,117,212, 0, 3,117,228, 0, 3,117,244, 0, 3,118, 4,
+ 0, 3,118, 20, 0, 3,118, 36, 0, 3,118, 52, 0, 3,118, 68, 0, 3,118, 84, 0, 3,118,100, 0, 3,118,116, 0, 3,118,132,
+ 0, 3,118,148, 0, 3,118,164, 0, 3,118,180, 0, 3,118,196, 0, 3,118,212, 0, 3,118,228, 0, 3,118,244, 0, 3,119, 4,
+ 0, 3,119, 20, 0, 3,119, 36, 0, 3,119, 52, 0, 3,119, 68, 0, 3,119, 84, 0, 3,119,100, 0, 3,119,116, 0, 3,119,132,
+ 0, 3,119,148, 0, 3,119,164, 0, 3,119,180, 0, 3,119,196, 0, 3,119,212, 0, 3,119,228, 0, 3,119,244, 0, 3,120, 4,
+ 0, 3,120, 20, 0, 3,120, 36, 0, 3,120, 52, 0, 3,120, 68, 0, 3,120, 84, 0, 3,120,100, 0, 3,120,116, 0, 3,120,132,
+ 0, 3,120,148, 0, 3,120,164, 0, 3,120,180, 0, 3,120,196, 0, 3,120,212, 0, 3,120,228, 0, 3,120,244, 0, 3,121, 4,
+ 0, 3,121, 20, 0, 3,121, 36, 0, 3,121, 52, 0, 3,121, 96, 0, 3,121,216, 0, 3,122, 96, 0, 3,123,140, 0, 3,124, 20,
+ 0, 3,124,148, 0, 3,125, 36, 0, 3,125, 92, 0, 3,125,144, 0, 3,125,228, 0, 3,126, 16, 0, 3,126, 84, 0, 3,126,128,
+ 0, 3,127, 4, 0, 3,127, 48, 0, 3,127, 76, 0, 3,127,104, 0, 3,127,132, 0, 3,127,204, 0, 3,127,244, 0, 3,128, 12,
+ 0, 3,128, 48, 0, 3,128, 96, 0, 3,128,212, 0, 3,129,112, 0, 3,130, 12, 0, 3,130,208, 0, 3,131,136, 0, 3,131,184,
+ 0, 3,131,220, 0, 3,132, 20, 0, 3,132, 52, 0, 3,132, 84, 0, 3,132,164, 0, 3,133, 48, 0, 1, 0, 0, 11,210, 2, 12,
+ 0, 43, 0,107, 0, 6, 0, 2, 0, 16, 0, 64, 0, 8, 0, 0, 5, 87, 7, 27, 0, 5, 0, 4, 0, 0, 0, 22, 1, 14, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 95, 0,192, 0, 1, 0, 0, 0, 0, 0, 1, 0, 16, 1, 66, 0, 1, 0, 0, 0, 0, 0, 2, 0, 4,
+ 1, 93, 0, 1, 0, 0, 0, 0, 0, 3, 0, 16, 1,132, 0, 1, 0, 0, 0, 0, 0, 4, 0, 16, 1,183, 0, 1, 0, 0, 0, 0,
+ 0, 5, 0, 12, 1,226, 0, 1, 0, 0, 0, 0, 0, 6, 0, 14, 2, 13, 0, 1, 0, 0, 0, 0, 0, 8, 0, 17, 2, 64, 0, 1,
+ 0, 0, 0, 0, 0, 11, 0, 29, 2,142, 0, 1, 0, 0, 0, 0, 0, 13, 9,147, 21,212, 0, 1, 0, 0, 0, 0, 0, 14, 0, 52,
+ 31,210, 0, 3, 0, 1, 4, 9, 0, 0, 0,190, 0, 0, 0, 3, 0, 1, 4, 9, 0, 1, 0, 32, 1, 32, 0, 3, 0, 1, 4, 9,
+ 0, 2, 0, 8, 1, 83, 0, 3, 0, 1, 4, 9, 0, 3, 0, 32, 1, 98, 0, 3, 0, 1, 4, 9, 0, 4, 0, 32, 1,149, 0, 3,
+ 0, 1, 4, 9, 0, 5, 0, 24, 1,200, 0, 3, 0, 1, 4, 9, 0, 6, 0, 28, 1,239, 0, 3, 0, 1, 4, 9, 0, 8, 0, 34,
+ 2, 28, 0, 3, 0, 1, 4, 9, 0, 11, 0, 58, 2, 82, 0, 3, 0, 1, 4, 9, 0, 13, 19, 38, 2,172, 0, 3, 0, 1, 4, 9,
+ 0, 14, 0,104, 31,104, 0, 67, 0,111, 0,112, 0,121, 0,114, 0,105, 0,103, 0,104, 0,116, 0, 32, 0, 40, 0, 99, 0, 41,
+ 0, 32, 0, 50, 0, 48, 0, 48, 0, 51, 0, 32, 0, 98, 0,121, 0, 32, 0, 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,101,
+ 0, 97, 0,109, 0, 44, 0, 32, 0, 73, 0,110, 0, 99, 0, 46, 0, 32, 0, 65, 0,108, 0,108, 0, 32, 0, 82, 0,105, 0,103,
+ 0,104, 0,116, 0,115, 0, 32, 0, 82, 0,101, 0,115, 0,101, 0,114, 0,118, 0,101, 0,100, 0, 46, 0, 10, 0, 68, 0,101,
+ 0,106, 0, 97, 0, 86, 0,117, 0, 32, 0, 99, 0,104, 0, 97, 0,110, 0,103, 0,101, 0,115, 0, 32, 0, 97, 0,114, 0,101,
+ 0, 32, 0,105, 0,110, 0, 32, 0,112, 0,117, 0, 98, 0,108, 0,105, 0, 99, 0, 32, 0,100, 0,111, 0,109, 0, 97, 0,105,
+ 0,110, 0, 10, 0, 0, 67,111,112,121,114,105,103,104,116, 32, 40, 99, 41, 32, 50, 48, 48, 51, 32, 98,121, 32, 66,105,116,115,
+116,114,101, 97,109, 44, 32, 73,110, 99, 46, 32, 65,108,108, 32, 82,105,103,104,116,115, 32, 82,101,115,101,114,118,101,100, 46,
+ 10, 68,101,106, 97, 86,117, 32, 99,104, 97,110,103,101,115, 32, 97,114,101, 32,105,110, 32,112,117, 98,108,105, 99, 32,100,111,
+109, 97,105,110, 10, 0, 0, 68, 0,101, 0,106, 0, 97, 0, 86, 0,117, 0, 32, 0, 83, 0, 97, 0,110, 0,115, 0, 32, 0, 77,
+ 0,111, 0,110, 0,111, 0, 0, 68,101,106, 97, 86,117, 32, 83, 97,110,115, 32, 77,111,110,111, 0, 0, 66, 0,111, 0,111, 0,
+107, 0, 0, 66,111,111,107, 0, 0, 68, 0,101, 0,106, 0, 97, 0, 86, 0,117, 0, 32, 0, 83, 0, 97, 0,110, 0,115, 0, 32,
+ 0, 77, 0,111, 0,110, 0,111, 0, 0, 68,101,106, 97, 86,117, 32, 83, 97,110,115, 32, 77,111,110,111, 0, 0, 68, 0,101, 0,
+106, 0, 97, 0, 86, 0,117, 0, 32, 0, 83, 0, 97, 0,110, 0,115, 0, 32, 0, 77, 0,111, 0,110, 0,111, 0, 0, 68,101,106,
+ 97, 86,117, 32, 83, 97,110,115, 32, 77,111,110,111, 0, 0, 86, 0,101, 0,114, 0,115, 0,105, 0,111, 0,110, 0, 32, 0, 50,
+ 0, 46, 0, 50, 0, 53, 0, 0, 86,101,114,115,105,111,110, 32, 50, 46, 50, 53, 0, 0, 68, 0,101, 0,106, 0, 97, 0, 86, 0,
+117, 0, 83, 0, 97, 0,110, 0,115, 0, 77, 0,111, 0,110, 0,111, 0, 0, 68,101,106, 97, 86,117, 83, 97,110,115, 77,111,110,
+111, 0, 0, 68, 0,101, 0,106, 0, 97, 0, 86, 0,117, 0, 32, 0,102, 0,111, 0,110, 0,116, 0,115, 0, 32, 0,116, 0,101,
+ 0, 97, 0,109, 0, 0, 68,101,106, 97, 86,117, 32,102,111,110,116,115, 32,116,101, 97,109, 0, 0,104, 0,116, 0,116, 0,112,
+ 0, 58, 0, 47, 0, 47, 0,100, 0,101, 0,106, 0, 97, 0,118, 0,117, 0, 46, 0,115, 0,111, 0,117, 0,114, 0, 99, 0,101,
+ 0,102, 0,111, 0,114, 0,103, 0,101, 0, 46, 0,110, 0,101, 0,116, 0, 0,104,116,116,112, 58, 47, 47,100,101,106, 97,118,
+117, 46,115,111,117,114, 99,101,102,111,114,103,101, 46,110,101,116, 0, 0, 70, 0,111, 0,110, 0,116, 0,115, 0, 32, 0, 97,
+ 0,114, 0,101, 0, 32, 0, 40, 0, 99, 0, 41, 0, 32, 0, 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,109,
+ 0, 32, 0, 40, 0,115, 0,101, 0,101, 0, 32, 0, 98, 0,101, 0,108, 0,111, 0,119, 0, 41, 0, 46, 0, 32, 0, 68, 0,101,
+ 0,106, 0, 97, 0, 86, 0,117, 0, 32, 0, 99, 0,104, 0, 97, 0,110, 0,103, 0,101, 0,115, 0, 32, 0, 97, 0,114, 0,101,
+ 0, 32, 0,105, 0,110, 0, 32, 0,112, 0,117, 0, 98, 0,108, 0,105, 0, 99, 0, 32, 0,100, 0,111, 0,109, 0, 97, 0,105,
+ 0,110, 0, 46, 0, 10, 0, 10, 0, 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,109, 0, 32, 0, 86, 0,101,
+ 0,114, 0, 97, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0,115, 0, 32, 0, 67, 0,111, 0,112, 0,121, 0,114, 0,105, 0,103,
+ 0,104, 0,116, 0, 10, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45,
+ 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45, 0, 45,
+ 0, 45, 0, 10, 0, 10, 0, 67, 0,111, 0,112, 0,121, 0,114, 0,105, 0,103, 0,104, 0,116, 0, 32, 0, 40, 0, 99, 0, 41,
+ 0, 32, 0, 50, 0, 48, 0, 48, 0, 51, 0, 32, 0, 98, 0,121, 0, 32, 0, 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,101,
+ 0, 97, 0,109, 0, 44, 0, 32, 0, 73, 0,110, 0, 99, 0, 46, 0, 32, 0, 65, 0,108, 0,108, 0, 32, 0, 82, 0,105, 0,103,
+ 0,104, 0,116, 0,115, 0, 32, 0, 82, 0,101, 0,115, 0,101, 0,114, 0,118, 0,101, 0,100, 0, 46, 0, 32, 0, 66, 0,105,
+ 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,109, 0, 32, 0, 86, 0,101, 0,114, 0, 97, 0, 32, 0,105, 0,115, 0, 32,
+ 0, 97, 0, 32, 0,116, 0,114, 0, 97, 0,100, 0,101, 0,109, 0, 97, 0,114, 0,107, 0, 32, 0,111, 0,102, 0, 32, 0, 66,
+ 0,105, 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,109, 0, 44, 0, 32, 0, 73, 0,110, 0, 99, 0, 46, 0, 10, 0, 10,
+ 0, 80, 0,101, 0,114, 0,109, 0,105, 0,115, 0,115, 0,105, 0,111, 0,110, 0, 32, 0,105, 0,115, 0, 32, 0,104, 0,101,
+ 0,114, 0,101, 0, 98, 0,121, 0, 32, 0,103, 0,114, 0, 97, 0,110, 0,116, 0,101, 0,100, 0, 44, 0, 32, 0,102, 0,114,
+ 0,101, 0,101, 0, 32, 0,111, 0,102, 0, 32, 0, 99, 0,104, 0, 97, 0,114, 0,103, 0,101, 0, 44, 0, 32, 0,116, 0,111,
+ 0, 32, 0, 97, 0,110, 0,121, 0, 32, 0,112, 0,101, 0,114, 0,115, 0,111, 0,110, 0, 32, 0,111, 0, 98, 0,116, 0, 97,
+ 0,105, 0,110, 0,105, 0,110, 0,103, 0, 32, 0, 97, 0, 32, 0, 99, 0,111, 0,112, 0,121, 0, 32, 0,111, 0,102, 0, 32,
+ 0,116, 0,104, 0,101, 0, 32, 0,102, 0,111, 0,110, 0,116, 0,115, 0, 32, 0, 97, 0, 99, 0, 99, 0,111, 0,109, 0,112,
+ 0, 97, 0,110, 0,121, 0,105, 0,110, 0,103, 0, 32, 0,116, 0,104, 0,105, 0,115, 0, 32, 0,108, 0,105, 0, 99, 0,101,
+ 0,110, 0,115, 0,101, 0, 32, 0, 40, 0, 34, 0, 70, 0,111, 0,110, 0,116, 0,115, 0, 34, 0, 41, 0, 32, 0, 97, 0,110,
+ 0,100, 0, 32, 0, 97, 0,115, 0,115, 0,111, 0, 99, 0,105, 0, 97, 0,116, 0,101, 0,100, 0, 32, 0,100, 0,111, 0, 99,
+ 0,117, 0,109, 0,101, 0,110, 0,116, 0, 97, 0,116, 0,105, 0,111, 0,110, 0, 32, 0,102, 0,105, 0,108, 0,101, 0,115,
+ 0, 32, 0, 40, 0,116, 0,104, 0,101, 0, 32, 0, 34, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116,
+ 0,119, 0, 97, 0,114, 0,101, 0, 34, 0, 41, 0, 44, 0, 32, 0,116, 0,111, 0, 32, 0,114, 0,101, 0,112, 0,114, 0,111,
+ 0,100, 0,117, 0, 99, 0,101, 0, 32, 0, 97, 0,110, 0,100, 0, 32, 0,100, 0,105, 0,115, 0,116, 0,114, 0,105, 0, 98,
+ 0,117, 0,116, 0,101, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102,
+ 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 44, 0, 32, 0,105, 0,110, 0, 99, 0,108, 0,117, 0,100, 0,105, 0,110, 0,103,
+ 0, 32, 0,119, 0,105, 0,116, 0,104, 0,111, 0,117, 0,116, 0, 32, 0,108, 0,105, 0,109, 0,105, 0,116, 0, 97, 0,116,
+ 0,105, 0,111, 0,110, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,114, 0,105, 0,103, 0,104, 0,116, 0,115, 0, 32, 0,116,
+ 0,111, 0, 32, 0,117, 0,115, 0,101, 0, 44, 0, 32, 0, 99, 0,111, 0,112, 0,121, 0, 44, 0, 32, 0,109, 0,101, 0,114,
+ 0,103, 0,101, 0, 44, 0, 32, 0,112, 0,117, 0, 98, 0,108, 0,105, 0,115, 0,104, 0, 44, 0, 32, 0,100, 0,105, 0,115,
+ 0,116, 0,114, 0,105, 0, 98, 0,117, 0,116, 0,101, 0, 44, 0, 32, 0, 97, 0,110, 0,100, 0, 47, 0,111, 0,114, 0, 32,
+ 0,115, 0,101, 0,108, 0,108, 0, 32, 0, 99, 0,111, 0,112, 0,105, 0,101, 0,115, 0, 32, 0,111, 0,102, 0, 32, 0,116,
+ 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101,
+ 0, 44, 0, 32, 0, 97, 0,110, 0,100, 0, 32, 0,116, 0,111, 0, 32, 0,112, 0,101, 0,114, 0,109, 0,105, 0,116, 0, 32,
+ 0,112, 0,101, 0,114, 0,115, 0,111, 0,110, 0,115, 0, 32, 0,116, 0,111, 0, 32, 0,119, 0,104, 0,111, 0,109, 0, 32,
+ 0,116, 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114,
+ 0,101, 0, 32, 0,105, 0,115, 0, 32, 0,102, 0,117, 0,114, 0,110, 0,105, 0,115, 0,104, 0,101, 0,100, 0, 32, 0,116,
+ 0,111, 0, 32, 0,100, 0,111, 0, 32, 0,115, 0,111, 0, 44, 0, 32, 0,115, 0,117, 0, 98, 0,106, 0,101, 0, 99, 0,116,
+ 0, 32, 0,116, 0,111, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,102, 0,111, 0,108, 0,108, 0,111, 0,119, 0,105, 0,110,
+ 0,103, 0, 32, 0, 99, 0,111, 0,110, 0,100, 0,105, 0,116, 0,105, 0,111, 0,110, 0,115, 0, 58, 0, 10, 0, 10, 0, 84,
+ 0,104, 0,101, 0, 32, 0, 97, 0, 98, 0,111, 0,118, 0,101, 0, 32, 0, 99, 0,111, 0,112, 0,121, 0,114, 0,105, 0,103,
+ 0,104, 0,116, 0, 32, 0, 97, 0,110, 0,100, 0, 32, 0,116, 0,114, 0, 97, 0,100, 0,101, 0,109, 0, 97, 0,114, 0,107,
+ 0, 32, 0,110, 0,111, 0,116, 0,105, 0, 99, 0,101, 0,115, 0, 32, 0, 97, 0,110, 0,100, 0, 32, 0,116, 0,104, 0,105,
+ 0,115, 0, 32, 0,112, 0,101, 0,114, 0,109, 0,105, 0,115, 0,115, 0,105, 0,111, 0,110, 0, 32, 0,110, 0,111, 0,116,
+ 0,105, 0, 99, 0,101, 0, 32, 0,115, 0,104, 0, 97, 0,108, 0,108, 0, 32, 0, 98, 0,101, 0, 32, 0,105, 0,110, 0, 99,
+ 0,108, 0,117, 0,100, 0,101, 0,100, 0, 32, 0,105, 0,110, 0, 32, 0, 97, 0,108, 0,108, 0, 32, 0, 99, 0,111, 0,112,
+ 0,105, 0,101, 0,115, 0, 32, 0,111, 0,102, 0, 32, 0,111, 0,110, 0,101, 0, 32, 0,111, 0,114, 0, 32, 0,109, 0,111,
+ 0,114, 0,101, 0, 32, 0,111, 0,102, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83,
+ 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 32, 0,116, 0,121, 0,112, 0,101, 0,102, 0, 97, 0, 99, 0,101,
+ 0,115, 0, 46, 0, 10, 0, 10, 0, 84, 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102,
+ 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 32, 0,109, 0, 97, 0,121, 0, 32, 0, 98, 0,101, 0, 32, 0,109, 0,111, 0,100,
+ 0,105, 0,102, 0,105, 0,101, 0,100, 0, 44, 0, 32, 0, 97, 0,108, 0,116, 0,101, 0,114, 0,101, 0,100, 0, 44, 0, 32,
+ 0,111, 0,114, 0, 32, 0, 97, 0,100, 0,100, 0,101, 0,100, 0, 32, 0,116, 0,111, 0, 44, 0, 32, 0, 97, 0,110, 0,100,
+ 0, 32, 0,105, 0,110, 0, 32, 0,112, 0, 97, 0,114, 0,116, 0,105, 0, 99, 0,117, 0,108, 0, 97, 0,114, 0, 32, 0,116,
+ 0,104, 0,101, 0, 32, 0,100, 0,101, 0,115, 0,105, 0,103, 0,110, 0,115, 0, 32, 0,111, 0,102, 0, 32, 0,103, 0,108,
+ 0,121, 0,112, 0,104, 0,115, 0, 32, 0,111, 0,114, 0, 32, 0, 99, 0,104, 0, 97, 0,114, 0, 97, 0, 99, 0,116, 0,101,
+ 0,114, 0,115, 0, 32, 0,105, 0,110, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0,115, 0, 32,
+ 0,109, 0, 97, 0,121, 0, 32, 0, 98, 0,101, 0, 32, 0,109, 0,111, 0,100, 0,105, 0,102, 0,105, 0,101, 0,100, 0, 32,
+ 0, 97, 0,110, 0,100, 0, 32, 0, 97, 0,100, 0,100, 0,105, 0,116, 0,105, 0,111, 0,110, 0, 97, 0,108, 0, 32, 0,103,
+ 0,108, 0,121, 0,112, 0,104, 0,115, 0, 32, 0,111, 0,114, 0, 32, 0, 32, 0,111, 0,114, 0, 32, 0, 99, 0,104, 0, 97,
+ 0,114, 0, 97, 0, 99, 0,116, 0,101, 0,114, 0,115, 0, 32, 0,109, 0, 97, 0,121, 0, 32, 0, 98, 0,101, 0, 32, 0, 97,
+ 0,100, 0,100, 0,101, 0,100, 0, 32, 0,116, 0,111, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116,
+ 0,115, 0, 44, 0, 32, 0,111, 0,110, 0,108, 0,121, 0, 32, 0,105, 0,102, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,102,
+ 0,111, 0,110, 0,116, 0,115, 0, 32, 0, 97, 0,114, 0,101, 0, 32, 0,114, 0,101, 0,110, 0, 97, 0,109, 0,101, 0,100,
+ 0, 32, 0,116, 0,111, 0, 32, 0,110, 0, 97, 0,109, 0,101, 0,115, 0, 32, 0,110, 0,111, 0,116, 0, 32, 0, 99, 0,111,
+ 0,110, 0,116, 0, 97, 0,105, 0,110, 0,105, 0,110, 0,103, 0, 32, 0,101, 0,105, 0,116, 0,104, 0,101, 0,114, 0, 32,
+ 0,116, 0,104, 0,101, 0, 32, 0,119, 0,111, 0,114, 0,100, 0,115, 0, 32, 0, 34, 0, 66, 0,105, 0,116, 0,115, 0,116,
+ 0,114, 0,101, 0, 97, 0,109, 0, 34, 0, 32, 0,111, 0,114, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,119, 0,111, 0,114,
+ 0,100, 0, 32, 0, 34, 0, 86, 0,101, 0,114, 0, 97, 0, 34, 0, 46, 0, 10, 0, 10, 0, 84, 0,104, 0,105, 0,115, 0, 32,
+ 0, 76, 0,105, 0, 99, 0,101, 0,110, 0,115, 0,101, 0, 32, 0, 98, 0,101, 0, 99, 0,111, 0,109, 0,101, 0,115, 0, 32,
+ 0,110, 0,117, 0,108, 0,108, 0, 32, 0, 97, 0,110, 0,100, 0, 32, 0,118, 0,111, 0,105, 0,100, 0, 32, 0,116, 0,111,
+ 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,101, 0,120, 0,116, 0,101, 0,110, 0,116, 0, 32, 0, 97, 0,112, 0,112, 0,108,
+ 0,105, 0, 99, 0, 97, 0, 98, 0,108, 0,101, 0, 32, 0,116, 0,111, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0,115, 0, 32,
+ 0,111, 0,114, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101,
+ 0, 32, 0,116, 0,104, 0, 97, 0,116, 0, 32, 0,104, 0, 97, 0,115, 0, 32, 0, 98, 0,101, 0,101, 0,110, 0, 32, 0,109,
+ 0,111, 0,100, 0,105, 0,102, 0,105, 0,101, 0,100, 0, 32, 0, 97, 0,110, 0,100, 0, 32, 0,105, 0,115, 0, 32, 0,100,
+ 0,105, 0,115, 0,116, 0,114, 0,105, 0, 98, 0,117, 0,116, 0,101, 0,100, 0, 32, 0,117, 0,110, 0,100, 0,101, 0,114,
+ 0, 32, 0,116, 0,104, 0,101, 0, 32, 0, 34, 0, 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,109, 0, 32,
+ 0, 86, 0,101, 0,114, 0, 97, 0, 34, 0, 32, 0,110, 0, 97, 0,109, 0,101, 0,115, 0, 46, 0, 10, 0, 10, 0, 84, 0,104,
+ 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 32,
+ 0,109, 0, 97, 0,121, 0, 32, 0, 98, 0,101, 0, 32, 0,115, 0,111, 0,108, 0,100, 0, 32, 0, 97, 0,115, 0, 32, 0,112,
+ 0, 97, 0,114, 0,116, 0, 32, 0,111, 0,102, 0, 32, 0, 97, 0, 32, 0,108, 0, 97, 0,114, 0,103, 0,101, 0,114, 0, 32,
+ 0,115, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101, 0, 32, 0,112, 0, 97, 0, 99, 0,107, 0, 97, 0,103, 0,101,
+ 0, 32, 0, 98, 0,117, 0,116, 0, 32, 0,110, 0,111, 0, 32, 0, 99, 0,111, 0,112, 0,121, 0, 32, 0,111, 0,102, 0, 32,
+ 0,111, 0,110, 0,101, 0, 32, 0,111, 0,114, 0, 32, 0,109, 0,111, 0,114, 0,101, 0, 32, 0,111, 0,102, 0, 32, 0,116,
+ 0,104, 0,101, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114, 0,101,
+ 0, 32, 0,116, 0,121, 0,112, 0,101, 0,102, 0, 97, 0, 99, 0,101, 0,115, 0, 32, 0,109, 0, 97, 0,121, 0, 32, 0, 98,
+ 0,101, 0, 32, 0,115, 0,111, 0,108, 0,100, 0, 32, 0, 98, 0,121, 0, 32, 0,105, 0,116, 0,115, 0,101, 0,108, 0,102,
+ 0, 46, 0, 10, 0, 10, 0, 84, 0, 72, 0, 69, 0, 32, 0, 70, 0, 79, 0, 78, 0, 84, 0, 32, 0, 83, 0, 79, 0, 70, 0, 84,
+ 0, 87, 0, 65, 0, 82, 0, 69, 0, 32, 0, 73, 0, 83, 0, 32, 0, 80, 0, 82, 0, 79, 0, 86, 0, 73, 0, 68, 0, 69, 0, 68,
+ 0, 32, 0, 34, 0, 65, 0, 83, 0, 32, 0, 73, 0, 83, 0, 34, 0, 44, 0, 32, 0, 87, 0, 73, 0, 84, 0, 72, 0, 79, 0, 85,
+ 0, 84, 0, 32, 0, 87, 0, 65, 0, 82, 0, 82, 0, 65, 0, 78, 0, 84, 0, 89, 0, 32, 0, 79, 0, 70, 0, 32, 0, 65, 0, 78,
+ 0, 89, 0, 32, 0, 75, 0, 73, 0, 78, 0, 68, 0, 44, 0, 32, 0, 69, 0, 88, 0, 80, 0, 82, 0, 69, 0, 83, 0, 83, 0, 32,
+ 0, 79, 0, 82, 0, 32, 0, 73, 0, 77, 0, 80, 0, 76, 0, 73, 0, 69, 0, 68, 0, 44, 0, 32, 0, 73, 0, 78, 0, 67, 0, 76,
+ 0, 85, 0, 68, 0, 73, 0, 78, 0, 71, 0, 32, 0, 66, 0, 85, 0, 84, 0, 32, 0, 78, 0, 79, 0, 84, 0, 32, 0, 76, 0, 73,
+ 0, 77, 0, 73, 0, 84, 0, 69, 0, 68, 0, 32, 0, 84, 0, 79, 0, 32, 0, 65, 0, 78, 0, 89, 0, 32, 0, 87, 0, 65, 0, 82,
+ 0, 82, 0, 65, 0, 78, 0, 84, 0, 73, 0, 69, 0, 83, 0, 32, 0, 79, 0, 70, 0, 32, 0, 77, 0, 69, 0, 82, 0, 67, 0, 72,
+ 0, 65, 0, 78, 0, 84, 0, 65, 0, 66, 0, 73, 0, 76, 0, 73, 0, 84, 0, 89, 0, 44, 0, 32, 0, 70, 0, 73, 0, 84, 0, 78,
+ 0, 69, 0, 83, 0, 83, 0, 32, 0, 70, 0, 79, 0, 82, 0, 32, 0, 65, 0, 32, 0, 80, 0, 65, 0, 82, 0, 84, 0, 73, 0, 67,
+ 0, 85, 0, 76, 0, 65, 0, 82, 0, 32, 0, 80, 0, 85, 0, 82, 0, 80, 0, 79, 0, 83, 0, 69, 0, 32, 0, 65, 0, 78, 0, 68,
+ 0, 32, 0, 78, 0, 79, 0, 78, 0, 73, 0, 78, 0, 70, 0, 82, 0, 73, 0, 78, 0, 71, 0, 69, 0, 77, 0, 69, 0, 78, 0, 84,
+ 0, 32, 0, 79, 0, 70, 0, 32, 0, 67, 0, 79, 0, 80, 0, 89, 0, 82, 0, 73, 0, 71, 0, 72, 0, 84, 0, 44, 0, 32, 0, 80,
+ 0, 65, 0, 84, 0, 69, 0, 78, 0, 84, 0, 44, 0, 32, 0, 84, 0, 82, 0, 65, 0, 68, 0, 69, 0, 77, 0, 65, 0, 82, 0, 75,
+ 0, 44, 0, 32, 0, 79, 0, 82, 0, 32, 0, 79, 0, 84, 0, 72, 0, 69, 0, 82, 0, 32, 0, 82, 0, 73, 0, 71, 0, 72, 0, 84,
+ 0, 46, 0, 32, 0, 73, 0, 78, 0, 32, 0, 78, 0, 79, 0, 32, 0, 69, 0, 86, 0, 69, 0, 78, 0, 84, 0, 32, 0, 83, 0, 72,
+ 0, 65, 0, 76, 0, 76, 0, 32, 0, 66, 0, 73, 0, 84, 0, 83, 0, 84, 0, 82, 0, 69, 0, 65, 0, 77, 0, 32, 0, 79, 0, 82,
+ 0, 32, 0, 84, 0, 72, 0, 69, 0, 32, 0, 71, 0, 78, 0, 79, 0, 77, 0, 69, 0, 32, 0, 70, 0, 79, 0, 85, 0, 78, 0, 68,
+ 0, 65, 0, 84, 0, 73, 0, 79, 0, 78, 0, 32, 0, 66, 0, 69, 0, 32, 0, 76, 0, 73, 0, 65, 0, 66, 0, 76, 0, 69, 0, 32,
+ 0, 70, 0, 79, 0, 82, 0, 32, 0, 65, 0, 78, 0, 89, 0, 32, 0, 67, 0, 76, 0, 65, 0, 73, 0, 77, 0, 44, 0, 32, 0, 68,
+ 0, 65, 0, 77, 0, 65, 0, 71, 0, 69, 0, 83, 0, 32, 0, 79, 0, 82, 0, 32, 0, 79, 0, 84, 0, 72, 0, 69, 0, 82, 0, 32,
+ 0, 76, 0, 73, 0, 65, 0, 66, 0, 73, 0, 76, 0, 73, 0, 84, 0, 89, 0, 44, 0, 32, 0, 73, 0, 78, 0, 67, 0, 76, 0, 85,
+ 0, 68, 0, 73, 0, 78, 0, 71, 0, 32, 0, 65, 0, 78, 0, 89, 0, 32, 0, 71, 0, 69, 0, 78, 0, 69, 0, 82, 0, 65, 0, 76,
+ 0, 44, 0, 32, 0, 83, 0, 80, 0, 69, 0, 67, 0, 73, 0, 65, 0, 76, 0, 44, 0, 32, 0, 73, 0, 78, 0, 68, 0, 73, 0, 82,
+ 0, 69, 0, 67, 0, 84, 0, 44, 0, 32, 0, 73, 0, 78, 0, 67, 0, 73, 0, 68, 0, 69, 0, 78, 0, 84, 0, 65, 0, 76, 0, 44,
+ 0, 32, 0, 79, 0, 82, 0, 32, 0, 67, 0, 79, 0, 78, 0, 83, 0, 69, 0, 81, 0, 85, 0, 69, 0, 78, 0, 84, 0, 73, 0, 65,
+ 0, 76, 0, 32, 0, 68, 0, 65, 0, 77, 0, 65, 0, 71, 0, 69, 0, 83, 0, 44, 0, 32, 0, 87, 0, 72, 0, 69, 0, 84, 0, 72,
+ 0, 69, 0, 82, 0, 32, 0, 73, 0, 78, 0, 32, 0, 65, 0, 78, 0, 32, 0, 65, 0, 67, 0, 84, 0, 73, 0, 79, 0, 78, 0, 32,
+ 0, 79, 0, 70, 0, 32, 0, 67, 0, 79, 0, 78, 0, 84, 0, 82, 0, 65, 0, 67, 0, 84, 0, 44, 0, 32, 0, 84, 0, 79, 0, 82,
+ 0, 84, 0, 32, 0, 79, 0, 82, 0, 32, 0, 79, 0, 84, 0, 72, 0, 69, 0, 82, 0, 87, 0, 73, 0, 83, 0, 69, 0, 44, 0, 32,
+ 0, 65, 0, 82, 0, 73, 0, 83, 0, 73, 0, 78, 0, 71, 0, 32, 0, 70, 0, 82, 0, 79, 0, 77, 0, 44, 0, 32, 0, 79, 0, 85,
+ 0, 84, 0, 32, 0, 79, 0, 70, 0, 32, 0, 84, 0, 72, 0, 69, 0, 32, 0, 85, 0, 83, 0, 69, 0, 32, 0, 79, 0, 82, 0, 32,
+ 0, 73, 0, 78, 0, 65, 0, 66, 0, 73, 0, 76, 0, 73, 0, 84, 0, 89, 0, 32, 0, 84, 0, 79, 0, 32, 0, 85, 0, 83, 0, 69,
+ 0, 32, 0, 84, 0, 72, 0, 69, 0, 32, 0, 70, 0, 79, 0, 78, 0, 84, 0, 32, 0, 83, 0, 79, 0, 70, 0, 84, 0, 87, 0, 65,
+ 0, 82, 0, 69, 0, 32, 0, 79, 0, 82, 0, 32, 0, 70, 0, 82, 0, 79, 0, 77, 0, 32, 0, 79, 0, 84, 0, 72, 0, 69, 0, 82,
+ 0, 32, 0, 68, 0, 69, 0, 65, 0, 76, 0, 73, 0, 78, 0, 71, 0, 83, 0, 32, 0, 73, 0, 78, 0, 32, 0, 84, 0, 72, 0, 69,
+ 0, 32, 0, 70, 0, 79, 0, 78, 0, 84, 0, 32, 0, 83, 0, 79, 0, 70, 0, 84, 0, 87, 0, 65, 0, 82, 0, 69, 0, 46, 0, 10,
+ 0, 10, 0, 69, 0,120, 0, 99, 0,101, 0,112, 0,116, 0, 32, 0, 97, 0,115, 0, 32, 0, 99, 0,111, 0,110, 0,116, 0, 97,
+ 0,105, 0,110, 0,101, 0,100, 0, 32, 0,105, 0,110, 0, 32, 0,116, 0,104, 0,105, 0,115, 0, 32, 0,110, 0,111, 0,116,
+ 0,105, 0, 99, 0,101, 0, 44, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0,110, 0, 97, 0,109, 0,101, 0,115, 0, 32, 0,111,
+ 0,102, 0, 32, 0, 71, 0,110, 0,111, 0,109, 0,101, 0, 44, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0, 71, 0,110, 0,111,
+ 0,109, 0,101, 0, 32, 0, 70, 0,111, 0,117, 0,110, 0,100, 0, 97, 0,116, 0,105, 0,111, 0,110, 0, 44, 0, 32, 0, 97,
+ 0,110, 0,100, 0, 32, 0, 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,109, 0, 32, 0, 73, 0,110, 0, 99,
+ 0, 46, 0, 44, 0, 32, 0,115, 0,104, 0, 97, 0,108, 0,108, 0, 32, 0,110, 0,111, 0,116, 0, 32, 0, 98, 0,101, 0, 32,
+ 0,117, 0,115, 0,101, 0,100, 0, 32, 0,105, 0,110, 0, 32, 0, 97, 0,100, 0,118, 0,101, 0,114, 0,116, 0,105, 0,115,
+ 0,105, 0,110, 0,103, 0, 32, 0,111, 0,114, 0, 32, 0,111, 0,116, 0,104, 0,101, 0,114, 0,119, 0,105, 0,115, 0,101,
+ 0, 32, 0,116, 0,111, 0, 32, 0,112, 0,114, 0,111, 0,109, 0,111, 0,116, 0,101, 0, 32, 0,116, 0,104, 0,101, 0, 32,
+ 0,115, 0, 97, 0,108, 0,101, 0, 44, 0, 32, 0,117, 0,115, 0,101, 0, 32, 0,111, 0,114, 0, 32, 0,111, 0,116, 0,104,
+ 0,101, 0,114, 0, 32, 0,100, 0,101, 0, 97, 0,108, 0,105, 0,110, 0,103, 0,115, 0, 32, 0,105, 0,110, 0, 32, 0,116,
+ 0,104, 0,105, 0,115, 0, 32, 0, 70, 0,111, 0,110, 0,116, 0, 32, 0, 83, 0,111, 0,102, 0,116, 0,119, 0, 97, 0,114,
+ 0,101, 0, 32, 0,119, 0,105, 0,116, 0,104, 0,111, 0,117, 0,116, 0, 32, 0,112, 0,114, 0,105, 0,111, 0,114, 0, 32,
+ 0,119, 0,114, 0,105, 0,116, 0,116, 0,101, 0,110, 0, 32, 0, 97, 0,117, 0,116, 0,104, 0,111, 0,114, 0,105, 0,122,
+ 0, 97, 0,116, 0,105, 0,111, 0,110, 0, 32, 0,102, 0,114, 0,111, 0,109, 0, 32, 0,116, 0,104, 0,101, 0, 32, 0, 71,
+ 0,110, 0,111, 0,109, 0,101, 0, 32, 0, 70, 0,111, 0,117, 0,110, 0,100, 0, 97, 0,116, 0,105, 0,111, 0,110, 0, 32,
+ 0,111, 0,114, 0, 32, 0, 66, 0,105, 0,116, 0,115, 0,116, 0,114, 0,101, 0, 97, 0,109, 0, 32, 0, 73, 0,110, 0, 99,
+ 0, 46, 0, 44, 0, 32, 0,114, 0,101, 0,115, 0,112, 0,101, 0, 99, 0,116, 0,105, 0,118, 0,101, 0,108, 0,121, 0, 46,
+ 0, 32, 0, 70, 0,111, 0,114, 0, 32, 0,102, 0,117, 0,114, 0,116, 0,104, 0,101, 0,114, 0, 32, 0,105, 0,110, 0,102,
+ 0,111, 0,114, 0,109, 0, 97, 0,116, 0,105, 0,111, 0,110, 0, 44, 0, 32, 0, 99, 0,111, 0,110, 0,116, 0, 97, 0, 99,
+ 0,116, 0, 58, 0, 32, 0,102, 0,111, 0,110, 0,116, 0,115, 0, 32, 0, 97, 0,116, 0, 32, 0,103, 0,110, 0,111, 0,109,
+ 0,101, 0, 32, 0,100, 0,111, 0,116, 0, 32, 0,111, 0,114, 0,103, 0, 46, 0, 32, 0, 10, 0, 0, 70,111,110,116,115, 32,
+ 97,114,101, 32, 40, 99, 41, 32, 66,105,116,115,116,114,101, 97,109, 32, 40,115,101,101, 32, 98,101,108,111,119, 41, 46, 32, 68,
+101,106, 97, 86,117, 32, 99,104, 97,110,103,101,115, 32, 97,114,101, 32,105,110, 32,112,117, 98,108,105, 99, 32,100,111,109, 97,
+105,110, 46, 10, 10, 66,105,116,115,116,114,101, 97,109, 32, 86,101,114, 97, 32, 70,111,110,116,115, 32, 67,111,112,121,114,105,
+103,104,116, 10, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 10, 10, 67,111,112,121,114,105,103,104,116, 32, 40, 99, 41, 32, 50, 48, 48, 51, 32, 98,121, 32, 66,105,116,115,116,114,
+101, 97,109, 44, 32, 73,110, 99, 46, 32, 65,108,108, 32, 82,105,103,104,116,115, 32, 82,101,115,101,114,118,101,100, 46, 32, 66,
+105,116,115,116,114,101, 97,109, 32, 86,101,114, 97, 32,105,115, 32, 97, 32,116,114, 97,100,101,109, 97,114,107, 32,111,102, 32,
+ 66,105,116,115,116,114,101, 97,109, 44, 32, 73,110, 99, 46, 10, 10, 80,101,114,109,105,115,115,105,111,110, 32,105,115, 32,104,
+101,114,101, 98,121, 32,103,114, 97,110,116,101,100, 44, 32,102,114,101,101, 32,111,102, 32, 99,104, 97,114,103,101, 44, 32,116,
+111, 32, 97,110,121, 32,112,101,114,115,111,110, 32,111, 98,116, 97,105,110,105,110,103, 32, 97, 32, 99,111,112,121, 32,111,102,
+ 32,116,104,101, 32,102,111,110,116,115, 32, 97, 99, 99,111,109,112, 97,110,121,105,110,103, 32,116,104,105,115, 32,108,105, 99,
+101,110,115,101, 32, 40, 34, 70,111,110,116,115, 34, 41, 32, 97,110,100, 32, 97,115,115,111, 99,105, 97,116,101,100, 32,100,111,
+ 99,117,109,101,110,116, 97,116,105,111,110, 32,102,105,108,101,115, 32, 40,116,104,101, 32, 34, 70,111,110,116, 32, 83,111,102,
+116,119, 97,114,101, 34, 41, 44, 32,116,111, 32,114,101,112,114,111,100,117, 99,101, 32, 97,110,100, 32,100,105,115,116,114,105,
+ 98,117,116,101, 32,116,104,101, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,114,101, 44, 32,105,110, 99,108,117,100,105,110,
+103, 32,119,105,116,104,111,117,116, 32,108,105,109,105,116, 97,116,105,111,110, 32,116,104,101, 32,114,105,103,104,116,115, 32,
+116,111, 32,117,115,101, 44, 32, 99,111,112,121, 44, 32,109,101,114,103,101, 44, 32,112,117, 98,108,105,115,104, 44, 32,100,105,
+115,116,114,105, 98,117,116,101, 44, 32, 97,110,100, 47,111,114, 32,115,101,108,108, 32, 99,111,112,105,101,115, 32,111,102, 32,
+116,104,101, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,114,101, 44, 32, 97,110,100, 32,116,111, 32,112,101,114,109,105,116,
+ 32,112,101,114,115,111,110,115, 32,116,111, 32,119,104,111,109, 32,116,104,101, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,
+114,101, 32,105,115, 32,102,117,114,110,105,115,104,101,100, 32,116,111, 32,100,111, 32,115,111, 44, 32,115,117, 98,106,101, 99,
+116, 32,116,111, 32,116,104,101, 32,102,111,108,108,111,119,105,110,103, 32, 99,111,110,100,105,116,105,111,110,115, 58, 10, 10,
+ 84,104,101, 32, 97, 98,111,118,101, 32, 99,111,112,121,114,105,103,104,116, 32, 97,110,100, 32,116,114, 97,100,101,109, 97,114,
+107, 32,110,111,116,105, 99,101,115, 32, 97,110,100, 32,116,104,105,115, 32,112,101,114,109,105,115,115,105,111,110, 32,110,111,
+116,105, 99,101, 32,115,104, 97,108,108, 32, 98,101, 32,105,110, 99,108,117,100,101,100, 32,105,110, 32, 97,108,108, 32, 99,111,
+112,105,101,115, 32,111,102, 32,111,110,101, 32,111,114, 32,109,111,114,101, 32,111,102, 32,116,104,101, 32, 70,111,110,116, 32,
+ 83,111,102,116,119, 97,114,101, 32,116,121,112,101,102, 97, 99,101,115, 46, 10, 10, 84,104,101, 32, 70,111,110,116, 32, 83,111,
+102,116,119, 97,114,101, 32,109, 97,121, 32, 98,101, 32,109,111,100,105,102,105,101,100, 44, 32, 97,108,116,101,114,101,100, 44,
+ 32,111,114, 32, 97,100,100,101,100, 32,116,111, 44, 32, 97,110,100, 32,105,110, 32,112, 97,114,116,105, 99,117,108, 97,114, 32,
+116,104,101, 32,100,101,115,105,103,110,115, 32,111,102, 32,103,108,121,112,104,115, 32,111,114, 32, 99,104, 97,114, 97, 99,116,
+101,114,115, 32,105,110, 32,116,104,101, 32, 70,111,110,116,115, 32,109, 97,121, 32, 98,101, 32,109,111,100,105,102,105,101,100,
+ 32, 97,110,100, 32, 97,100,100,105,116,105,111,110, 97,108, 32,103,108,121,112,104,115, 32,111,114, 32, 32,111,114, 32, 99,104,
+ 97,114, 97, 99,116,101,114,115, 32,109, 97,121, 32, 98,101, 32, 97,100,100,101,100, 32,116,111, 32,116,104,101, 32, 70,111,110,
+116,115, 44, 32,111,110,108,121, 32,105,102, 32,116,104,101, 32,102,111,110,116,115, 32, 97,114,101, 32,114,101,110, 97,109,101,
+100, 32,116,111, 32,110, 97,109,101,115, 32,110,111,116, 32, 99,111,110,116, 97,105,110,105,110,103, 32,101,105,116,104,101,114,
+ 32,116,104,101, 32,119,111,114,100,115, 32, 34, 66,105,116,115,116,114,101, 97,109, 34, 32,111,114, 32,116,104,101, 32,119,111,
+114,100, 32, 34, 86,101,114, 97, 34, 46, 10, 10, 84,104,105,115, 32, 76,105, 99,101,110,115,101, 32, 98,101, 99,111,109,101,115,
+ 32,110,117,108,108, 32, 97,110,100, 32,118,111,105,100, 32,116,111, 32,116,104,101, 32,101,120,116,101,110,116, 32, 97,112,112,
+108,105, 99, 97, 98,108,101, 32,116,111, 32, 70,111,110,116,115, 32,111,114, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,114,
+101, 32,116,104, 97,116, 32,104, 97,115, 32, 98,101,101,110, 32,109,111,100,105,102,105,101,100, 32, 97,110,100, 32,105,115, 32,
+100,105,115,116,114,105, 98,117,116,101,100, 32,117,110,100,101,114, 32,116,104,101, 32, 34, 66,105,116,115,116,114,101, 97,109,
+ 32, 86,101,114, 97, 34, 32,110, 97,109,101,115, 46, 10, 10, 84,104,101, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,114,101,
+ 32,109, 97,121, 32, 98,101, 32,115,111,108,100, 32, 97,115, 32,112, 97,114,116, 32,111,102, 32, 97, 32,108, 97,114,103,101,114,
+ 32,115,111,102,116,119, 97,114,101, 32,112, 97, 99,107, 97,103,101, 32, 98,117,116, 32,110,111, 32, 99,111,112,121, 32,111,102,
+ 32,111,110,101, 32,111,114, 32,109,111,114,101, 32,111,102, 32,116,104,101, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,114,
+101, 32,116,121,112,101,102, 97, 99,101,115, 32,109, 97,121, 32, 98,101, 32,115,111,108,100, 32, 98,121, 32,105,116,115,101,108,
+102, 46, 10, 10, 84, 72, 69, 32, 70, 79, 78, 84, 32, 83, 79, 70, 84, 87, 65, 82, 69, 32, 73, 83, 32, 80, 82, 79, 86, 73, 68, 69,
+ 68, 32, 34, 65, 83, 32, 73, 83, 34, 44, 32, 87, 73, 84, 72, 79, 85, 84, 32, 87, 65, 82, 82, 65, 78, 84, 89, 32, 79, 70, 32, 65,
+ 78, 89, 32, 75, 73, 78, 68, 44, 32, 69, 88, 80, 82, 69, 83, 83, 32, 79, 82, 32, 73, 77, 80, 76, 73, 69, 68, 44, 32, 73, 78, 67,
+ 76, 85, 68, 73, 78, 71, 32, 66, 85, 84, 32, 78, 79, 84, 32, 76, 73, 77, 73, 84, 69, 68, 32, 84, 79, 32, 65, 78, 89, 32, 87, 65,
+ 82, 82, 65, 78, 84, 73, 69, 83, 32, 79, 70, 32, 77, 69, 82, 67, 72, 65, 78, 84, 65, 66, 73, 76, 73, 84, 89, 44, 32, 70, 73, 84,
+ 78, 69, 83, 83, 32, 70, 79, 82, 32, 65, 32, 80, 65, 82, 84, 73, 67, 85, 76, 65, 82, 32, 80, 85, 82, 80, 79, 83, 69, 32, 65, 78,
+ 68, 32, 78, 79, 78, 73, 78, 70, 82, 73, 78, 71, 69, 77, 69, 78, 84, 32, 79, 70, 32, 67, 79, 80, 89, 82, 73, 71, 72, 84, 44, 32,
+ 80, 65, 84, 69, 78, 84, 44, 32, 84, 82, 65, 68, 69, 77, 65, 82, 75, 44, 32, 79, 82, 32, 79, 84, 72, 69, 82, 32, 82, 73, 71, 72,
+ 84, 46, 32, 73, 78, 32, 78, 79, 32, 69, 86, 69, 78, 84, 32, 83, 72, 65, 76, 76, 32, 66, 73, 84, 83, 84, 82, 69, 65, 77, 32, 79,
+ 82, 32, 84, 72, 69, 32, 71, 78, 79, 77, 69, 32, 70, 79, 85, 78, 68, 65, 84, 73, 79, 78, 32, 66, 69, 32, 76, 73, 65, 66, 76, 69,
+ 32, 70, 79, 82, 32, 65, 78, 89, 32, 67, 76, 65, 73, 77, 44, 32, 68, 65, 77, 65, 71, 69, 83, 32, 79, 82, 32, 79, 84, 72, 69, 82,
+ 32, 76, 73, 65, 66, 73, 76, 73, 84, 89, 44, 32, 73, 78, 67, 76, 85, 68, 73, 78, 71, 32, 65, 78, 89, 32, 71, 69, 78, 69, 82, 65,
+ 76, 44, 32, 83, 80, 69, 67, 73, 65, 76, 44, 32, 73, 78, 68, 73, 82, 69, 67, 84, 44, 32, 73, 78, 67, 73, 68, 69, 78, 84, 65, 76,
+ 44, 32, 79, 82, 32, 67, 79, 78, 83, 69, 81, 85, 69, 78, 84, 73, 65, 76, 32, 68, 65, 77, 65, 71, 69, 83, 44, 32, 87, 72, 69, 84,
+ 72, 69, 82, 32, 73, 78, 32, 65, 78, 32, 65, 67, 84, 73, 79, 78, 32, 79, 70, 32, 67, 79, 78, 84, 82, 65, 67, 84, 44, 32, 84, 79,
+ 82, 84, 32, 79, 82, 32, 79, 84, 72, 69, 82, 87, 73, 83, 69, 44, 32, 65, 82, 73, 83, 73, 78, 71, 32, 70, 82, 79, 77, 44, 32, 79,
+ 85, 84, 32, 79, 70, 32, 84, 72, 69, 32, 85, 83, 69, 32, 79, 82, 32, 73, 78, 65, 66, 73, 76, 73, 84, 89, 32, 84, 79, 32, 85, 83,
+ 69, 32, 84, 72, 69, 32, 70, 79, 78, 84, 32, 83, 79, 70, 84, 87, 65, 82, 69, 32, 79, 82, 32, 70, 82, 79, 77, 32, 79, 84, 72, 69,
+ 82, 32, 68, 69, 65, 76, 73, 78, 71, 83, 32, 73, 78, 32, 84, 72, 69, 32, 70, 79, 78, 84, 32, 83, 79, 70, 84, 87, 65, 82, 69, 46,
+ 10, 10, 69,120, 99,101,112,116, 32, 97,115, 32, 99,111,110,116, 97,105,110,101,100, 32,105,110, 32,116,104,105,115, 32,110,111,
+116,105, 99,101, 44, 32,116,104,101, 32,110, 97,109,101,115, 32,111,102, 32, 71,110,111,109,101, 44, 32,116,104,101, 32, 71,110,
+111,109,101, 32, 70,111,117,110,100, 97,116,105,111,110, 44, 32, 97,110,100, 32, 66,105,116,115,116,114,101, 97,109, 32, 73,110,
+ 99, 46, 44, 32,115,104, 97,108,108, 32,110,111,116, 32, 98,101, 32,117,115,101,100, 32,105,110, 32, 97,100,118,101,114,116,105,
+115,105,110,103, 32,111,114, 32,111,116,104,101,114,119,105,115,101, 32,116,111, 32,112,114,111,109,111,116,101, 32,116,104,101,
+ 32,115, 97,108,101, 44, 32,117,115,101, 32,111,114, 32,111,116,104,101,114, 32,100,101, 97,108,105,110,103,115, 32,105,110, 32,
+116,104,105,115, 32, 70,111,110,116, 32, 83,111,102,116,119, 97,114,101, 32,119,105,116,104,111,117,116, 32,112,114,105,111,114,
+ 32,119,114,105,116,116,101,110, 32, 97,117,116,104,111,114,105,122, 97,116,105,111,110, 32,102,114,111,109, 32,116,104,101, 32,
+ 71,110,111,109,101, 32, 70,111,117,110,100, 97,116,105,111,110, 32,111,114, 32, 66,105,116,115,116,114,101, 97,109, 32, 73,110,
+ 99, 46, 44, 32,114,101,115,112,101, 99,116,105,118,101,108,121, 46, 32, 70,111,114, 32,102,117,114,116,104,101,114, 32,105,110,
+102,111,114,109, 97,116,105,111,110, 44, 32, 99,111,110,116, 97, 99,116, 58, 32,102,111,110,116,115, 32, 97,116, 32,103,110,111,
+109,101, 32,100,111,116, 32,111,114,103, 46, 32, 10, 0, 0,104, 0,116, 0,116, 0,112, 0, 58, 0, 47, 0, 47, 0,100, 0,101,
+ 0,106, 0, 97, 0,118, 0,117, 0, 46, 0,115, 0,111, 0,117, 0,114, 0, 99, 0,101, 0,102, 0,111, 0,114, 0,103, 0,101,
+ 0, 46, 0,110, 0,101, 0,116, 0, 47, 0,119, 0,105, 0,107, 0,105, 0, 47, 0,105, 0,110, 0,100, 0,101, 0,120, 0, 46,
+ 0,112, 0,104, 0,112, 0, 47, 0, 76, 0,105, 0, 99, 0,101, 0,110, 0,115, 0,101, 0, 0,104,116,116,112, 58, 47, 47,100,
+101,106, 97,118,117, 46,115,111,117,114, 99,101,102,111,114,103,101, 46,110,101,116, 47,119,105,107,105, 47,105,110,100,101,120,
+ 46,112,104,112, 47, 76,105, 99,101,110,115,101, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,255,126, 0, 90, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11,210, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6,
+ 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16, 0, 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22,
+ 0, 23, 0, 24, 0, 25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0, 31, 0, 32, 0, 33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38,
+ 0, 39, 0, 40, 0, 41, 0, 42, 0, 43, 0, 44, 0, 45, 0, 46, 0, 47, 0, 48, 0, 49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54,
+ 0, 55, 0, 56, 0, 57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 64, 0, 65, 0, 66, 0, 67, 0, 68, 0, 69, 0, 70,
+ 0, 71, 0, 72, 0, 73, 0, 74, 0, 75, 0, 76, 0, 77, 0, 78, 0, 79, 0, 80, 0, 81, 0, 82, 0, 83, 0, 84, 0, 85, 0, 86,
+ 0, 87, 0, 88, 0, 89, 0, 90, 0, 91, 0, 92, 0, 93, 0, 94, 0, 95, 0, 96, 0, 97, 0,172, 0,163, 0,132, 0,133, 0,189,
+ 0,150, 0,232, 0,134, 0,142, 0,139, 0,157, 0,169, 0,164, 1, 2, 0,138, 0,218, 0,131, 0,147, 0,242, 0,243, 0,141,
+ 0,151, 0,136, 0,195, 0,222, 0,241, 0,158, 0,170, 0,245, 0,244, 0,246, 0,162, 0,173, 0,201, 0,199, 0,174, 0, 98,
+ 0, 99, 0,144, 0,100, 0,203, 0,101, 0,200, 0,202, 0,207, 0,204, 0,205, 0,206, 0,233, 0,102, 0,211, 0,208, 0,209,
+ 0,175, 0,103, 0,240, 0,145, 0,214, 0,212, 0,213, 0,104, 0,235, 0,237, 0,137, 0,106, 0,105, 0,107, 0,109, 0,108,
+ 0,110, 0,160, 0,111, 0,113, 0,112, 0,114, 0,115, 0,117, 0,116, 0,118, 0,119, 0,234, 0,120, 0,122, 0,121, 0,123,
+ 0,125, 0,124, 0,184, 0,161, 0,127, 0,126, 0,128, 0,129, 0,236, 0,238, 0,186, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7,
+ 1, 8, 0,253, 0,254, 1, 9, 1, 10, 1, 11, 1, 12, 0,255, 1, 0, 1, 13, 1, 14, 1, 15, 1, 1, 1, 16, 1, 17, 1, 18,
+ 1, 19, 1, 20, 1, 21, 1, 22, 1, 23, 1, 24, 1, 25, 1, 26, 1, 27, 0,248, 0,249, 1, 28, 1, 29, 1, 30, 1, 31, 1, 32,
+ 1, 33, 1, 34, 1, 35, 1, 36, 1, 37, 1, 38, 1, 39, 1, 40, 1, 41, 1, 42, 1, 43, 0,250, 0,215, 1, 44, 1, 45, 1, 46,
+ 1, 47, 1, 48, 1, 49, 1, 50, 1, 51, 1, 52, 1, 53, 1, 54, 1, 55, 1, 56, 1, 57, 1, 58, 0,226, 0,227, 1, 59, 1, 60,
+ 1, 61, 1, 62, 1, 63, 1, 64, 1, 65, 1, 66, 1, 67, 1, 68, 1, 69, 1, 70, 1, 71, 1, 72, 1, 73, 0,176, 0,177, 1, 74,
+ 1, 75, 1, 76, 1, 77, 1, 78, 1, 79, 1, 80, 1, 81, 1, 82, 1, 83, 0,251, 0,252, 0,228, 0,229, 1, 84, 1, 85, 1, 86,
+ 1, 87, 1, 88, 1, 89, 1, 90, 1, 91, 1, 92, 1, 93, 1, 94, 1, 95, 1, 96, 1, 97, 1, 98, 1, 99, 1,100, 1,101, 1,102,
+ 1,103, 1,104, 1,105, 0,187, 1,106, 1,107, 1,108, 1,109, 0,230, 0,231, 1,110, 1,111, 1,112, 1,113, 1,114, 1,115,
+ 1,116, 1,117, 1,118, 1,119, 1,120, 1,121, 1,122, 1,123, 1,124, 1,125, 1,126, 1,127, 1,128, 0,166, 1,129, 1,130,
+ 1,131, 1,132, 1,133, 1,134, 1,135, 1,136, 1,137, 1,138, 1,139, 1,140, 1,141, 1,142, 1,143, 1,144, 1,145, 1,146,
+ 1,147, 1,148, 1,149, 1,150, 1,151, 1,152, 1,153, 1,154, 1,155, 1,156, 1,157, 1,158, 1,159, 1,160, 1,161, 1,162,
+ 1,163, 1,164, 1,165, 1,166, 1,167, 1,168, 1,169, 1,170, 1,171, 1,172, 1,173, 1,174, 1,175, 1,176, 1,177, 1,178,
+ 1,179, 1,180, 1,181, 1,182, 1,183, 1,184, 1,185, 1,186, 1,187, 1,188, 1,189, 1,190, 1,191, 1,192, 1,193, 1,194,
+ 1,195, 1,196, 1,197, 1,198, 1,199, 1,200, 1,201, 1,202, 1,203, 1,204, 1,205, 1,206, 1,207, 1,208, 1,209, 1,210,
+ 1,211, 1,212, 1,213, 1,214, 1,215, 1,216, 1,217, 1,218, 1,219, 1,220, 1,221, 1,222, 1,223, 1,224, 1,225, 1,226,
+ 1,227, 1,228, 1,229, 1,230, 1,231, 1,232, 1,233, 1,234, 1,235, 1,236, 1,237, 1,238, 1,239, 1,240, 1,241, 1,242,
+ 1,243, 1,244, 1,245, 1,246, 1,247, 1,248, 1,249, 1,250, 1,251, 1,252, 1,253, 1,254, 1,255, 2, 0, 2, 1, 2, 2,
+ 2, 3, 2, 4, 2, 5, 2, 6, 2, 7, 2, 8, 2, 9, 2, 10, 2, 11, 2, 12, 2, 13, 2, 14, 2, 15, 2, 16, 2, 17, 2, 18,
+ 2, 19, 2, 20, 2, 21, 2, 22, 2, 23, 2, 24, 2, 25, 2, 26, 2, 27, 2, 28, 2, 29, 2, 30, 2, 31, 2, 32, 2, 33, 2, 34,
+ 2, 35, 2, 36, 2, 37, 2, 38, 2, 39, 2, 40, 2, 41, 2, 42, 2, 43, 2, 44, 2, 45, 2, 46, 2, 47, 2, 48, 2, 49, 2, 50,
+ 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 2, 57, 2, 58, 2, 59, 2, 60, 2, 61, 2, 62, 2, 63, 2, 64, 2, 65, 2, 66,
+ 2, 67, 2, 68, 2, 69, 2, 70, 2, 71, 2, 72, 2, 73, 2, 74, 2, 75, 2, 76, 2, 77, 2, 78, 2, 79, 2, 80, 2, 81, 2, 82,
+ 2, 83, 2, 84, 2, 85, 2, 86, 2, 87, 2, 88, 2, 89, 2, 90, 2, 91, 2, 92, 2, 93, 2, 94, 2, 95, 2, 96, 2, 97, 2, 98,
+ 2, 99, 2,100, 2,101, 2,102, 2,103, 2,104, 2,105, 2,106, 2,107, 2,108, 2,109, 2,110, 2,111, 2,112, 2,113, 2,114,
+ 2,115, 2,116, 2,117, 2,118, 2,119, 2,120, 2,121, 2,122, 2,123, 2,124, 2,125, 2,126, 2,127, 2,128, 2,129, 2,130,
+ 2,131, 2,132, 2,133, 2,134, 2,135, 2,136, 2,137, 2,138, 0,216, 0,225, 2,139, 2,140, 2,141, 2,142, 2,143, 2,144,
+ 2,145, 2,146, 2,147, 0,219, 0,220, 0,221, 0,224, 0,217, 0,223, 2,148, 2,149, 2,150, 2,151, 2,152, 2,153, 2,154,
+ 2,155, 2,156, 2,157, 2,158, 2,159, 2,160, 2,161, 2,162, 2,163, 2,164, 2,165, 2,166, 2,167, 2,168, 2,169, 2,170,
+ 2,171, 2,172, 2,173, 2,174, 2,175, 2,176, 2,177, 2,178, 2,179, 2,180, 2,181, 2,182, 2,183, 2,184, 2,185, 2,186,
+ 2,187, 2,188, 2,189, 2,190, 2,191, 2,192, 2,193, 2,194, 2,195, 2,196, 2,197, 2,198, 2,199, 2,200, 2,201, 2,202,
+ 2,203, 2,204, 2,205, 2,206, 2,207, 2,208, 2,209, 2,210, 2,211, 2,212, 2,213, 2,214, 2,215, 2,216, 2,217, 2,218,
+ 2,219, 2,220, 2,221, 2,222, 2,223, 2,224, 2,225, 2,226, 2,227, 2,228, 2,229, 2,230, 2,231, 2,232, 2,233, 2,234,
+ 2,235, 2,236, 2,237, 2,238, 2,239, 2,240, 2,241, 2,242, 2,243, 2,244, 2,245, 2,246, 2,247, 2,248, 2,249, 2,250,
+ 2,251, 2,252, 2,253, 2,254, 2,255, 3, 0, 3, 1, 3, 2, 3, 3, 3, 4, 3, 5, 3, 6, 3, 7, 3, 8, 0,159, 3, 9,
+ 3, 10, 3, 11, 3, 12, 3, 13, 3, 14, 3, 15, 3, 16, 3, 17, 3, 18, 3, 19, 3, 20, 3, 21, 3, 22, 3, 23, 3, 24, 3, 25,
+ 3, 26, 3, 27, 3, 28, 3, 29, 3, 30, 0,155, 3, 31, 3, 32, 3, 33, 3, 34, 3, 35, 3, 36, 3, 37, 3, 38, 3, 39, 3, 40,
+ 3, 41, 3, 42, 3, 43, 3, 44, 3, 45, 3, 46, 3, 47, 3, 48, 3, 49, 3, 50, 3, 51, 3, 52, 3, 53, 3, 54, 3, 55, 3, 56,
+ 3, 57, 3, 58, 3, 59, 3, 60, 3, 61, 3, 62, 3, 63, 3, 64, 3, 65, 3, 66, 3, 67, 3, 68, 3, 69, 3, 70, 3, 71, 3, 72,
+ 3, 73, 3, 74, 3, 75, 3, 76, 3, 77, 3, 78, 3, 79, 3, 80, 3, 81, 3, 82, 3, 83, 3, 84, 3, 85, 3, 86, 3, 87, 3, 88,
+ 3, 89, 3, 90, 3, 91, 3, 92, 3, 93, 3, 94, 3, 95, 3, 96, 3, 97, 3, 98, 3, 99, 3,100, 3,101, 3,102, 3,103, 3,104,
+ 3,105, 3,106, 3,107, 3,108, 3,109, 3,110, 3,111, 3,112, 3,113, 3,114, 3,115, 3,116, 3,117, 3,118, 3,119, 3,120,
+ 3,121, 3,122, 3,123, 3,124, 3,125, 3,126, 3,127, 3,128, 3,129, 3,130, 3,131, 3,132, 3,133, 3,134, 3,135, 3,136,
+ 3,137, 3,138, 3,139, 3,140, 3,141, 3,142, 3,143, 3,144, 3,145, 3,146, 3,147, 3,148, 3,149, 3,150, 3,151, 3,152,
+ 3,153, 3,154, 3,155, 3,156, 3,157, 3,158, 3,159, 3,160, 3,161, 3,162, 3,163, 3,164, 3,165, 3,166, 3,167, 3,168,
+ 3,169, 3,170, 3,171, 3,172, 3,173, 3,174, 3,175, 3,176, 3,177, 3,178, 3,179, 3,180, 3,181, 3,182, 3,183, 3,184,
+ 3,185, 3,186, 3,187, 3,188, 3,189, 3,190, 3,191, 3,192, 3,193, 3,194, 3,195, 3,196, 3,197, 3,198, 3,199, 3,200,
+ 3,201, 3,202, 3,203, 3,204, 3,205, 3,206, 3,207, 3,208, 3,209, 3,210, 3,211, 3,212, 3,213, 3,214, 3,215, 3,216,
+ 3,217, 3,218, 3,219, 3,220, 3,221, 3,222, 3,223, 3,224, 3,225, 3,226, 3,227, 3,228, 3,229, 3,230, 3,231, 3,232,
+ 3,233, 3,234, 3,235, 3,236, 3,237, 3,238, 3,239, 3,240, 3,241, 3,242, 3,243, 3,244, 3,245, 3,246, 3,247, 3,248,
+ 3,249, 3,250, 3,251, 3,252, 3,253, 3,254, 3,255, 4, 0, 4, 1, 4, 2, 4, 3, 4, 4, 4, 5, 4, 6, 4, 7, 4, 8,
+ 4, 9, 4, 10, 4, 11, 4, 12, 4, 13, 4, 14, 4, 15, 4, 16, 4, 17, 4, 18, 4, 19, 4, 20, 4, 21, 4, 22, 4, 23, 4, 24,
+ 4, 25, 4, 26, 4, 27, 4, 28, 4, 29, 4, 30, 4, 31, 4, 32, 4, 33, 4, 34, 4, 35, 4, 36, 4, 37, 4, 38, 4, 39, 4, 40,
+ 4, 41, 4, 42, 4, 43, 4, 44, 4, 45, 4, 46, 4, 47, 4, 48, 4, 49, 4, 50, 4, 51, 4, 52, 4, 53, 4, 54, 4, 55, 4, 56,
+ 4, 57, 4, 58, 4, 59, 4, 60, 4, 61, 4, 62, 4, 63, 4, 64, 4, 65, 4, 66, 4, 67, 4, 68, 4, 69, 4, 70, 4, 71, 4, 72,
+ 4, 73, 4, 74, 4, 75, 4, 76, 4, 77, 4, 78, 4, 79, 4, 80, 4, 81, 4, 82, 4, 83, 4, 84, 4, 85, 4, 86, 4, 87, 4, 88,
+ 4, 89, 4, 90, 4, 91, 4, 92, 4, 93, 4, 94, 4, 95, 4, 96, 4, 97, 4, 98, 4, 99, 4,100, 4,101, 4,102, 4,103, 4,104,
+ 4,105, 4,106, 4,107, 4,108, 4,109, 4,110, 4,111, 4,112, 4,113, 4,114, 4,115, 4,116, 4,117, 4,118, 4,119, 4,120,
+ 4,121, 4,122, 4,123, 4,124, 4,125, 4,126, 4,127, 4,128, 4,129, 4,130, 4,131, 4,132, 4,133, 4,134, 4,135, 4,136,
+ 4,137, 4,138, 4,139, 4,140, 4,141, 4,142, 4,143, 4,144, 4,145, 4,146, 4,147, 4,148, 4,149, 4,150, 4,151, 4,152,
+ 4,153, 4,154, 4,155, 4,156, 4,157, 4,158, 4,159, 4,160, 4,161, 4,162, 4,163, 4,164, 4,165, 4,166, 4,167, 4,168,
+ 4,169, 4,170, 4,171, 4,172, 4,173, 4,174, 4,175, 4,176, 4,177, 4,178, 4,179, 4,180, 4,181, 4,182, 4,183, 4,184,
+ 4,185, 4,186, 4,187, 4,188, 4,189, 4,190, 4,191, 4,192, 4,193, 4,194, 4,195, 4,196, 4,197, 4,198, 4,199, 4,200,
+ 4,201, 4,202, 4,203, 4,204, 4,205, 4,206, 4,207, 4,208, 4,209, 4,210, 4,211, 4,212, 4,213, 4,214, 4,215, 4,216,
+ 4,217, 4,218, 4,219, 4,220, 4,221, 4,222, 4,223, 4,224, 4,225, 4,226, 4,227, 4,228, 4,229, 4,230, 4,231, 4,232,
+ 4,233, 4,234, 4,235, 4,236, 4,237, 4,238, 4,239, 4,240, 4,241, 4,242, 4,243, 4,244, 4,245, 4,246, 4,247, 4,248,
+ 4,249, 4,250, 4,251, 4,252, 4,253, 4,254, 4,255, 5, 0, 5, 1, 5, 2, 5, 3, 5, 4, 5, 5, 5, 6, 5, 7, 5, 8,
+ 5, 9, 5, 10, 5, 11, 5, 12, 5, 13, 5, 14, 5, 15, 5, 16, 5, 17, 5, 18, 5, 19, 5, 20, 5, 21, 5, 22, 5, 23, 5, 24,
+ 5, 25, 5, 26, 5, 27, 5, 28, 5, 29, 5, 30, 5, 31, 5, 32, 5, 33, 5, 34, 5, 35, 5, 36, 5, 37, 5, 38, 5, 39, 5, 40,
+ 5, 41, 5, 42, 5, 43, 5, 44, 5, 45, 5, 46, 5, 47, 5, 48, 5, 49, 5, 50, 5, 51, 5, 52, 5, 53, 5, 54, 5, 55, 5, 56,
+ 5, 57, 5, 58, 5, 59, 5, 60, 5, 61, 5, 62, 5, 63, 5, 64, 5, 65, 5, 66, 5, 67, 5, 68, 5, 69, 5, 70, 5, 71, 5, 72,
+ 5, 73, 5, 74, 5, 75, 5, 76, 5, 77, 5, 78, 5, 79, 5, 80, 5, 81, 5, 82, 5, 83, 5, 84, 5, 85, 5, 86, 5, 87, 5, 88,
+ 5, 89, 5, 90, 5, 91, 5, 92, 5, 93, 5, 94, 5, 95, 5, 96, 5, 97, 5, 98, 5, 99, 5,100, 5,101, 5,102, 5,103, 5,104,
+ 5,105, 5,106, 5,107, 5,108, 5,109, 5,110, 5,111, 5,112, 5,113, 5,114, 5,115, 5,116, 5,117, 5,118, 5,119, 5,120,
+ 5,121, 5,122, 5,123, 5,124, 5,125, 5,126, 5,127, 5,128, 5,129, 5,130, 5,131, 5,132, 5,133, 5,134, 5,135, 5,136,
+ 5,137, 5,138, 5,139, 5,140, 5,141, 5,142, 5,143, 5,144, 5,145, 5,146, 5,147, 5,148, 5,149, 5,150, 5,151, 5,152,
+ 5,153, 5,154, 5,155, 5,156, 5,157, 5,158, 5,159, 5,160, 5,161, 5,162, 5,163, 5,164, 5,165, 5,166, 5,167, 5,168,
+ 5,169, 5,170, 5,171, 5,172, 5,173, 5,174, 5,175, 5,176, 5,177, 5,178, 5,179, 5,180, 5,181, 5,182, 5,183, 5,184,
+ 5,185, 5,186, 5,187, 5,188, 5,189, 5,190, 5,191, 5,192, 5,193, 5,194, 5,195, 5,196, 5,197, 5,198, 5,199, 5,200,
+ 5,201, 5,202, 5,203, 5,204, 5,205, 5,206, 5,207, 5,208, 5,209, 5,210, 5,211, 5,212, 5,213, 5,214, 5,215, 5,216,
+ 5,217, 5,218, 5,219, 5,220, 5,221, 5,222, 5,223, 5,224, 5,225, 5,226, 5,227, 5,228, 5,229, 5,230, 5,231, 5,232,
+ 5,233, 5,234, 5,235, 5,236, 5,237, 5,238, 5,239, 5,240, 5,241, 5,242, 5,243, 5,244, 5,245, 5,246, 5,247, 5,248,
+ 5,249, 5,250, 5,251, 5,252, 5,253, 5,254, 5,255, 6, 0, 6, 1, 6, 2, 6, 3, 6, 4, 6, 5, 6, 6, 6, 7, 6, 8,
+ 6, 9, 6, 10, 6, 11, 6, 12, 6, 13, 6, 14, 6, 15, 6, 16, 6, 17, 6, 18, 6, 19, 6, 20, 6, 21, 6, 22, 6, 23, 6, 24,
+ 6, 25, 6, 26, 6, 27, 6, 28, 6, 29, 6, 30, 6, 31, 6, 32, 6, 33, 6, 34, 6, 35, 6, 36, 6, 37, 6, 38, 6, 39, 6, 40,
+ 6, 41, 6, 42, 6, 43, 6, 44, 6, 45, 6, 46, 6, 47, 6, 48, 6, 49, 6, 50, 6, 51, 6, 52, 6, 53, 6, 54, 6, 55, 6, 56,
+ 6, 57, 6, 58, 6, 59, 6, 60, 6, 61, 6, 62, 6, 63, 6, 64, 6, 65, 6, 66, 6, 67, 6, 68, 6, 69, 6, 70, 6, 71, 6, 72,
+ 6, 73, 6, 74, 6, 75, 6, 76, 6, 77, 6, 78, 6, 79, 6, 80, 6, 81, 6, 82, 6, 83, 6, 84, 6, 85, 6, 86, 6, 87, 6, 88,
+ 6, 89, 6, 90, 6, 91, 6, 92, 6, 93, 6, 94, 6, 95, 6, 96, 6, 97, 6, 98, 6, 99, 6,100, 6,101, 6,102, 6,103, 6,104,
+ 6,105, 6,106, 6,107, 6,108, 6,109, 6,110, 6,111, 6,112, 6,113, 6,114, 6,115, 6,116, 6,117, 6,118, 6,119, 6,120,
+ 6,121, 6,122, 6,123, 6,124, 6,125, 6,126, 6,127, 6,128, 6,129, 6,130, 6,131, 6,132, 6,133, 6,134, 6,135, 6,136,
+ 6,137, 6,138, 6,139, 6,140, 6,141, 6,142, 6,143, 6,144, 6,145, 6,146, 6,147, 6,148, 6,149, 6,150, 6,151, 6,152,
+ 6,153, 6,154, 6,155, 6,156, 6,157, 6,158, 6,159, 6,160, 6,161, 6,162, 6,163, 6,164, 6,165, 6,166, 6,167, 6,168,
+ 6,169, 6,170, 0,178, 0,179, 6,171, 6,172, 0,182, 0,183, 0,196, 6,173, 0,180, 0,181, 0,197, 6,174, 0,130, 0,194,
+ 0,135, 6,175, 0,171, 6,176, 0,198, 6,177, 0,190, 0,191, 6,178, 6,179, 6,180, 6,181, 6,182, 6,183, 6,184, 6,185,
+ 6,186, 6,187, 6,188, 6,189, 6,190, 6,191, 6,192, 6,193, 6,194, 6,195, 6,196, 6,197, 6,198, 6,199, 6,200, 6,201,
+ 6,202, 6,203, 6,204, 6,205, 6,206, 6,207, 6,208, 6,209, 6,210, 6,211, 6,212, 6,213, 6,214, 6,215, 6,216, 6,217,
+ 6,218, 6,219, 6,220, 6,221, 6,222, 6,223, 6,224, 6,225, 6,226, 6,227, 6,228, 0,140, 6,229, 6,230, 6,231, 6,232,
+ 6,233, 6,234, 6,235, 6,236, 6,237, 6,238, 6,239, 6,240, 6,241, 6,242, 6,243, 6,244, 6,245, 6,246, 6,247, 6,248,
+ 6,249, 6,250, 6,251, 6,252, 6,253, 6,254, 6,255, 7, 0, 7, 1, 7, 2, 7, 3, 7, 4, 7, 5, 7, 6, 7, 7, 7, 8,
+ 7, 9, 7, 10, 7, 11, 7, 12, 7, 13, 7, 14, 7, 15, 7, 16, 7, 17, 7, 18, 7, 19, 7, 20, 7, 21, 7, 22, 7, 23, 7, 24,
+ 7, 25, 7, 26, 7, 27, 7, 28, 7, 29, 7, 30, 7, 31, 7, 32, 7, 33, 7, 34, 7, 35, 7, 36, 7, 37, 7, 38, 7, 39, 7, 40,
+ 7, 41, 7, 42, 7, 43, 7, 44, 7, 45, 7, 46, 7, 47, 7, 48, 7, 49, 7, 50, 7, 51, 7, 52, 7, 53, 7, 54, 7, 55, 7, 56,
+ 7, 57, 7, 58, 7, 59, 7, 60, 7, 61, 7, 62, 7, 63, 7, 64, 7, 65, 7, 66, 7, 67, 7, 68, 7, 69, 7, 70, 7, 71, 7, 72,
+ 7, 73, 7, 74, 7, 75, 7, 76, 7, 77, 7, 78, 7, 79, 7, 80, 7, 81, 7, 82, 7, 83, 7, 84, 7, 85, 7, 86, 7, 87, 7, 88,
+ 7, 89, 7, 90, 7, 91, 7, 92, 7, 93, 7, 94, 7, 95, 7, 96, 7, 97, 7, 98, 7, 99, 7,100, 0,152, 7,101, 0,168, 7,102,
+ 7,103, 7,104, 7,105, 7,106, 7,107, 7,108, 0,154, 0,153, 0,239, 7,109, 7,110, 7,111, 7,112, 7,113, 0,165, 7,114,
+ 0,146, 7,115, 7,116, 7,117, 7,118, 7,119, 7,120, 0,156, 7,121, 7,122, 7,123, 7,124, 7,125, 7,126, 7,127, 7,128,
+ 7,129, 7,130, 7,131, 7,132, 7,133, 7,134, 7,135, 0,167, 7,136, 7,137, 7,138, 7,139, 7,140, 7,141, 7,142, 7,143,
+ 7,144, 7,145, 7,146, 7,147, 7,148, 7,149, 7,150, 7,151, 7,152, 7,153, 7,154, 7,155, 7,156, 7,157, 7,158, 0,143,
+ 7,159, 7,160, 7,161, 0,148, 0,149, 7,162, 7,163, 7,164, 7,165, 7,166, 7,167, 7,168, 7,169, 7,170, 7,171, 7,172,
+ 7,173, 7,174, 7,175, 7,176, 7,177, 7,178, 7,179, 7,180, 7,181, 7,182, 7,183, 7,184, 7,185, 7,186, 7,187, 7,188,
+ 7,189, 7,190, 7,191, 7,192, 7,193, 7,194, 7,195, 7,196, 7,197, 7,198, 7,199, 7,200, 7,201, 7,202, 7,203, 7,204,
+ 7,205, 7,206, 7,207, 7,208, 7,209, 7,210, 7,211, 7,212, 7,213, 7,214, 7,215, 7,216, 7,217, 7,218, 7,219, 7,220,
+ 7,221, 7,222, 7,223, 7,224, 7,225, 7,226, 7,227, 7,228, 7,229, 7,230, 7,231, 7,232, 7,233, 7,234, 7,235, 7,236,
+ 7,237, 7,238, 7,239, 7,240, 7,241, 7,242, 7,243, 7,244, 7,245, 7,246, 7,247, 7,248, 7,249, 7,250, 7,251, 7,252,
+ 7,253, 7,254, 7,255, 8, 0, 8, 1, 8, 2, 8, 3, 8, 4, 8, 5, 8, 6, 8, 7, 8, 8, 8, 9, 8, 10, 8, 11, 8, 12,
+ 8, 13, 8, 14, 8, 15, 8, 16, 8, 17, 8, 18, 8, 19, 8, 20, 8, 21, 8, 22, 8, 23, 8, 24, 8, 25, 8, 26, 8, 27, 8, 28,
+ 8, 29, 8, 30, 8, 31, 8, 32, 8, 33, 8, 34, 8, 35, 8, 36, 8, 37, 8, 38, 8, 39, 8, 40, 8, 41, 8, 42, 8, 43, 8, 44,
+ 8, 45, 8, 46, 8, 47, 8, 48, 8, 49, 8, 50, 8, 51, 8, 52, 8, 53, 8, 54, 8, 55, 8, 56, 8, 57, 8, 58, 8, 59, 8, 60,
+ 8, 61, 8, 62, 8, 63, 8, 64, 8, 65, 8, 66, 8, 67, 8, 68, 8, 69, 8, 70, 8, 71, 8, 72, 8, 73, 8, 74, 8, 75, 8, 76,
+ 8, 77, 8, 78, 8, 79, 8, 80, 8, 81, 8, 82, 8, 83, 8, 84, 8, 85, 8, 86, 8, 87, 8, 88, 8, 89, 8, 90, 8, 91, 8, 92,
+ 8, 93, 8, 94, 8, 95, 8, 96, 8, 97, 8, 98, 8, 99, 8,100, 8,101, 8,102, 8,103, 8,104, 8,105, 8,106, 8,107, 8,108,
+ 8,109, 8,110, 8,111, 8,112, 8,113, 8,114, 8,115, 8,116, 8,117, 8,118, 8,119, 8,120, 8,121, 8,122, 8,123, 8,124,
+ 8,125, 8,126, 8,127, 8,128, 8,129, 8,130, 8,131, 8,132, 8,133, 8,134, 8,135, 8,136, 8,137, 8,138, 8,139, 8,140,
+ 8,141, 8,142, 8,143, 8,144, 8,145, 8,146, 8,147, 8,148, 8,149, 8,150, 8,151, 8,152, 8,153, 8,154, 8,155, 8,156,
+ 8,157, 8,158, 8,159, 8,160, 8,161, 8,162, 8,163, 8,164, 8,165, 8,166, 8,167, 8,168, 8,169, 8,170, 8,171, 8,172,
+ 8,173, 8,174, 8,175, 8,176, 8,177, 8,178, 8,179, 8,180, 8,181, 8,182, 8,183, 8,184, 8,185, 8,186, 8,187, 8,188,
+ 8,189, 8,190, 8,191, 8,192, 8,193, 8,194, 8,195, 8,196, 8,197, 8,198, 8,199, 8,200, 8,201, 8,202, 8,203, 8,204,
+ 8,205, 8,206, 8,207, 8,208, 8,209, 8,210, 8,211, 8,212, 8,213, 8,214, 8,215, 8,216, 8,217, 8,218, 8,219, 8,220,
+ 8,221, 8,222, 8,223, 8,224, 8,225, 8,226, 8,227, 8,228, 8,229, 8,230, 8,231, 8,232, 8,233, 8,234, 8,235, 8,236,
+ 8,237, 8,238, 8,239, 8,240, 8,241, 8,242, 8,243, 8,244, 8,245, 8,246, 8,247, 8,248, 8,249, 8,250, 8,251, 8,252,
+ 8,253, 8,254, 8,255, 9, 0, 9, 1, 9, 2, 9, 3, 9, 4, 9, 5, 9, 6, 9, 7, 9, 8, 9, 9, 9, 10, 9, 11, 9, 12,
+ 9, 13, 9, 14, 9, 15, 9, 16, 9, 17, 9, 18, 9, 19, 9, 20, 9, 21, 9, 22, 9, 23, 9, 24, 9, 25, 9, 26, 9, 27, 9, 28,
+ 9, 29, 9, 30, 9, 31, 9, 32, 9, 33, 9, 34, 9, 35, 9, 36, 9, 37, 9, 38, 9, 39, 9, 40, 9, 41, 0,185, 9, 42, 9, 43,
+ 9, 44, 9, 45, 9, 46, 9, 47, 9, 48, 9, 49, 9, 50, 9, 51, 9, 52, 9, 53, 9, 54, 9, 55, 9, 56, 9, 57, 9, 58, 9, 59,
+ 9, 60, 9, 61, 9, 62, 9, 63, 9, 64, 9, 65, 9, 66, 9, 67, 9, 68, 9, 69, 9, 70, 9, 71, 9, 72, 9, 73, 9, 74, 9, 75,
+ 9, 76, 9, 77, 9, 78, 9, 79, 9, 80, 9, 81, 9, 82, 9, 83, 9, 84, 9, 85, 9, 86, 9, 87, 9, 88, 9, 89, 9, 90, 9, 91,
+ 9, 92, 9, 93, 9, 94, 9, 95, 9, 96, 9, 97, 9, 98, 9, 99, 9,100, 9,101, 9,102, 9,103, 9,104, 9,105, 9,106, 9,107,
+ 9,108, 9,109, 9,110, 9,111, 9,112, 9,113, 9,114, 9,115, 9,116, 9,117, 9,118, 9,119, 9,120, 9,121, 9,122, 9,123,
+ 9,124, 9,125, 9,126, 9,127, 9,128, 9,129, 9,130, 9,131, 9,132, 9,133, 9,134, 9,135, 9,136, 9,137, 9,138, 9,139,
+ 9,140, 9,141, 9,142, 9,143, 9,144, 9,145, 9,146, 9,147, 9,148, 9,149, 9,150, 9,151, 9,152, 9,153, 9,154, 9,155,
+ 9,156, 9,157, 9,158, 9,159, 9,160, 9,161, 9,162, 9,163, 9,164, 9,165, 9,166, 9,167, 9,168, 9,169, 9,170, 9,171,
+ 9,172, 9,173, 9,174, 9,175, 9,176, 9,177, 9,178, 9,179, 9,180, 9,181, 9,182, 9,183, 9,184, 9,185, 9,186, 9,187,
+ 9,188, 9,189, 9,190, 9,191, 9,192, 9,193, 9,194, 9,195, 9,196, 9,197, 9,198, 9,199, 9,200, 9,201, 9,202, 9,203,
+ 9,204, 9,205, 9,206, 9,207, 9,208, 9,209, 9,210, 9,211, 9,212, 9,213, 9,214, 9,215, 9,216, 9,217, 9,218, 9,219,
+ 9,220, 9,221, 9,222, 9,223, 9,224, 9,225, 9,226, 9,227, 9,228, 9,229, 9,230, 9,231, 9,232, 9,233, 9,234, 9,235,
+ 9,236, 9,237, 9,238, 9,239, 9,240, 9,241, 9,242, 9,243, 9,244, 9,245, 9,246, 9,247, 9,248, 9,249, 9,250, 9,251,
+ 9,252, 9,253, 9,254, 9,255, 10, 0, 10, 1, 10, 2, 10, 3, 10, 4, 10, 5, 10, 6, 10, 7, 10, 8, 10, 9, 10, 10, 10, 11,
+ 10, 12, 10, 13, 10, 14, 10, 15, 10, 16, 10, 17, 10, 18, 10, 19, 10, 20, 10, 21, 10, 22, 10, 23, 10, 24, 10, 25, 10, 26, 10, 27,
+ 10, 28, 10, 29, 10, 30, 10, 31, 10, 32, 10, 33, 10, 34, 10, 35, 10, 36, 10, 37, 10, 38, 10, 39, 10, 40, 10, 41, 10, 42, 10, 43,
+ 10, 44, 10, 45, 10, 46, 10, 47, 10, 48, 10, 49, 10, 50, 10, 51, 10, 52, 10, 53, 10, 54, 10, 55, 10, 56, 10, 57, 10, 58, 10, 59,
+ 10, 60, 10, 61, 10, 62, 10, 63, 10, 64, 10, 65, 10, 66, 10, 67, 10, 68, 10, 69, 10, 70, 10, 71, 10, 72, 10, 73, 10, 74, 10, 75,
+ 10, 76, 10, 77, 10, 78, 10, 79, 10, 80, 10, 81, 10, 82, 10, 83, 10, 84, 10, 85, 10, 86, 10, 87, 10, 88, 10, 89, 10, 90, 10, 91,
+ 10, 92, 10, 93, 10, 94, 10, 95, 10, 96, 10, 97, 10, 98, 10, 99, 10,100, 10,101, 10,102, 10,103, 10,104, 10,105, 10,106, 10,107,
+ 10,108, 10,109, 10,110, 10,111, 10,112, 10,113, 10,114, 10,115, 10,116, 10,117, 10,118, 10,119, 10,120, 10,121, 10,122, 10,123,
+ 10,124, 10,125, 10,126, 10,127, 10,128, 10,129, 10,130, 10,131, 10,132, 10,133, 10,134, 10,135, 10,136, 10,137, 10,138, 10,139,
+ 10,140, 10,141, 10,142, 10,143, 10,144, 10,145, 10,146, 10,147, 10,148, 10,149, 10,150, 10,151, 10,152, 10,153, 0,192, 0,193,
+ 10,154, 10,155, 10,156, 10,157, 10,158, 10,159, 10,160, 10,161, 10,162, 10,163, 10,164, 10,165, 10,166, 10,167, 10,168, 10,169,
+ 10,170, 10,171, 10,172, 10,173, 10,174, 10,175, 10,176, 10,177, 10,178, 10,179, 10,180, 10,181, 10,182, 10,183, 10,184, 10,185,
+ 10,186, 10,187, 10,188, 10,189, 10,190, 10,191, 10,192, 10,193, 10,194, 10,195, 10,196, 10,197, 10,198, 10,199, 10,200, 10,201,
+ 10,202, 10,203, 10,204, 10,205, 10,206, 10,207, 10,208, 10,209, 10,210, 10,211, 10,212, 10,213, 10,214, 10,215, 10,216, 10,217,
+ 10,218, 10,219, 10,220, 10,221, 10,222, 10,223, 10,224, 10,225, 10,226, 10,227, 10,228, 10,229, 10,230, 10,231, 10,232, 10,233,
+ 10,234, 10,235, 10,236, 10,237, 10,238, 10,239, 10,240, 10,241, 10,242, 10,243, 10,244, 10,245, 10,246, 10,247, 10,248, 10,249,
+ 10,250, 10,251, 10,252, 10,253, 10,254, 10,255, 11, 0, 11, 1, 11, 2, 11, 3, 11, 4, 11, 5, 11, 6, 11, 7, 11, 8, 11, 9,
+ 11, 10, 11, 11, 11, 12, 11, 13, 11, 14, 11, 15, 11, 16, 11, 17, 11, 18, 11, 19, 11, 20, 11, 21, 11, 22, 11, 23, 11, 24, 11, 25,
+ 11, 26, 11, 27, 11, 28, 11, 29, 11, 30, 11, 31, 11, 32, 11, 33, 11, 34, 11, 35, 11, 36, 11, 37, 11, 38, 11, 39, 11, 40, 11, 41,
+ 11, 42, 11, 43, 11, 44, 11, 45, 11, 46, 11, 47, 11, 48, 11, 49, 11, 50, 11, 51, 11, 52, 11, 53, 11, 54, 11, 55, 11, 56, 11, 57,
+ 11, 58, 11, 59, 11, 60, 11, 61, 11, 62, 11, 63, 11, 64, 11, 65, 11, 66, 11, 67, 11, 68, 11, 69, 11, 70, 11, 71, 11, 72, 11, 73,
+ 11, 74, 11, 75, 11, 76, 11, 77, 11, 78, 11, 79, 11, 80, 11, 81, 11, 82, 11, 83, 11, 84, 11, 85, 11, 86, 11, 87, 11, 88, 11, 89,
+ 11, 90, 11, 91, 11, 92, 11, 93, 11, 94, 11, 95, 11, 96, 11, 97, 11, 98, 11, 99, 11,100, 11,101, 11,102, 11,103, 11,104, 11,105,
+ 11,106, 11,107, 11,108, 11,109, 11,110, 11,111, 11,112, 11,113, 11,114, 11,115, 11,116, 11,117, 11,118, 11,119, 11,120, 11,121,
+ 11,122, 11,123, 11,124, 11,125, 11,126, 11,127, 11,128, 11,129, 11,130, 11,131, 11,132, 11,133, 11,134, 11,135, 11,136, 11,137,
+ 11,138, 11,139, 11,140, 11,141, 11,142, 11,143, 11,144, 11,145, 11,146, 11,147, 11,148, 11,149, 11,150, 11,151, 11,152, 11,153,
+ 11,154, 11,155, 11,156, 11,157, 11,158, 11,159, 11,160, 11,161, 11,162, 11,163, 11,164, 11,165, 11,166, 11,167, 11,168, 11,169,
+ 11,170, 11,171, 11,172, 11,173, 11,174, 11,175, 11,176, 11,177, 11,178, 11,179, 11,180, 11,181, 11,182, 11,183, 11,184, 11,185,
+ 11,186, 11,187, 11,188, 11,189, 11,190, 11,191, 11,192, 11,193, 11,194, 11,195, 11,196, 11,197, 11,198, 11,199, 11,200, 11,201,
+ 11,202, 11,203, 11,204, 11,205, 11,206, 11,207, 11,208, 11,209, 11,210, 11,211, 11,212, 9,115,102,116,104,121,112,104,101,110,
+ 7, 65,109, 97, 99,114,111,110, 7, 97,109, 97, 99,114,111,110, 6, 65, 98,114,101,118,101, 6, 97, 98,114,101,118,101, 7, 65,
+111,103,111,110,101,107, 7, 97,111,103,111,110,101,107, 11, 67, 99,105,114, 99,117,109,102,108,101,120, 11, 99, 99,105,114, 99,
+117,109,102,108,101,120, 10, 67,100,111,116, 97, 99, 99,101,110,116, 10, 99,100,111,116, 97, 99, 99,101,110,116, 6, 68, 99, 97,
+114,111,110, 6,100, 99, 97,114,111,110, 6, 68, 99,114,111, 97,116, 7, 69,109, 97, 99,114,111,110, 7,101,109, 97, 99,114,111,
+110, 6, 69, 98,114,101,118,101, 6,101, 98,114,101,118,101, 10, 69,100,111,116, 97, 99, 99,101,110,116, 10,101,100,111,116, 97,
+ 99, 99,101,110,116, 7, 69,111,103,111,110,101,107, 7,101,111,103,111,110,101,107, 6, 69, 99, 97,114,111,110, 6,101, 99, 97,
+114,111,110, 11, 71, 99,105,114, 99,117,109,102,108,101,120, 11,103, 99,105,114, 99,117,109,102,108,101,120, 10, 71,100,111,116,
+ 97, 99, 99,101,110,116, 10,103,100,111,116, 97, 99, 99,101,110,116, 12, 71, 99,111,109,109, 97, 97, 99, 99,101,110,116, 12,103,
+ 99,111,109,109, 97, 97, 99, 99,101,110,116, 11, 72, 99,105,114, 99,117,109,102,108,101,120, 11,104, 99,105,114, 99,117,109,102,
+108,101,120, 4, 72, 98, 97,114, 4,104, 98, 97,114, 6, 73,116,105,108,100,101, 6,105,116,105,108,100,101, 7, 73,109, 97, 99,
+114,111,110, 7,105,109, 97, 99,114,111,110, 6, 73, 98,114,101,118,101, 6,105, 98,114,101,118,101, 7, 73,111,103,111,110,101,
+107, 7,105,111,103,111,110,101,107, 2, 73, 74, 2,105,106, 11, 74, 99,105,114, 99,117,109,102,108,101,120, 11,106, 99,105,114,
+ 99,117,109,102,108,101,120, 12, 75, 99,111,109,109, 97, 97, 99, 99,101,110,116, 12,107, 99,111,109,109, 97, 97, 99, 99,101,110,
+116, 12,107,103,114,101,101,110,108, 97,110,100,105, 99, 6, 76, 97, 99,117,116,101, 6,108, 97, 99,117,116,101, 12, 76, 99,111,
+109,109, 97, 97, 99, 99,101,110,116, 12,108, 99,111,109,109, 97, 97, 99, 99,101,110,116, 6, 76, 99, 97,114,111,110, 6,108, 99,
+ 97,114,111,110, 4, 76,100,111,116, 4,108,100,111,116, 6, 78, 97, 99,117,116,101, 6,110, 97, 99,117,116,101, 12, 78, 99,111,
+109,109, 97, 97, 99, 99,101,110,116, 12,110, 99,111,109,109, 97, 97, 99, 99,101,110,116, 6, 78, 99, 97,114,111,110, 6,110, 99,
+ 97,114,111,110, 11,110, 97,112,111,115,116,114,111,112,104,101, 3, 69,110,103, 3,101,110,103, 7, 79,109, 97, 99,114,111,110,
+ 7,111,109, 97, 99,114,111,110, 6, 79, 98,114,101,118,101, 6,111, 98,114,101,118,101, 13, 79,104,117,110,103, 97,114,117,109,
+108, 97,117,116, 13,111,104,117,110,103, 97,114,117,109,108, 97,117,116, 6, 82, 97, 99,117,116,101, 6,114, 97, 99,117,116,101,
+ 12, 82, 99,111,109,109, 97, 97, 99, 99,101,110,116, 12,114, 99,111,109,109, 97, 97, 99, 99,101,110,116, 6, 82, 99, 97,114,111,
+110, 6,114, 99, 97,114,111,110, 6, 83, 97, 99,117,116,101, 6,115, 97, 99,117,116,101, 11, 83, 99,105,114, 99,117,109,102,108,
+101,120, 11,115, 99,105,114, 99,117,109,102,108,101,120, 12, 84, 99,111,109,109, 97, 97, 99, 99,101,110,116, 12,116, 99,111,109,
+109, 97, 97, 99, 99,101,110,116, 6, 84, 99, 97,114,111,110, 6,116, 99, 97,114,111,110, 4, 84, 98, 97,114, 4,116, 98, 97,114,
+ 6, 85,116,105,108,100,101, 6,117,116,105,108,100,101, 7, 85,109, 97, 99,114,111,110, 7,117,109, 97, 99,114,111,110, 6, 85,
+ 98,114,101,118,101, 6,117, 98,114,101,118,101, 5, 85,114,105,110,103, 5,117,114,105,110,103, 13, 85,104,117,110,103, 97,114,
+117,109,108, 97,117,116, 13,117,104,117,110,103, 97,114,117,109,108, 97,117,116, 7, 85,111,103,111,110,101,107, 7,117,111,103,
+111,110,101,107, 11, 87, 99,105,114, 99,117,109,102,108,101,120, 11,119, 99,105,114, 99,117,109,102,108,101,120, 11, 89, 99,105,
+114, 99,117,109,102,108,101,120, 11,121, 99,105,114, 99,117,109,102,108,101,120, 6, 90, 97, 99,117,116,101, 6,122, 97, 99,117,
+116,101, 10, 90,100,111,116, 97, 99, 99,101,110,116, 10,122,100,111,116, 97, 99, 99,101,110,116, 5,108,111,110,103,115, 7,117,
+110,105, 48, 49, 56, 48, 7,117,110,105, 48, 49, 56, 49, 7,117,110,105, 48, 49, 56, 50, 7,117,110,105, 48, 49, 56, 51, 7,117,
+110,105, 48, 49, 56, 52, 7,117,110,105, 48, 49, 56, 53, 7,117,110,105, 48, 49, 56, 54, 7,117,110,105, 48, 49, 56, 55, 7,117,
+110,105, 48, 49, 56, 56, 7,117,110,105, 48, 49, 56, 57, 7,117,110,105, 48, 49, 56, 65, 7,117,110,105, 48, 49, 56, 66, 7,117,
+110,105, 48, 49, 56, 67, 7,117,110,105, 48, 49, 56, 68, 7,117,110,105, 48, 49, 56, 69, 7,117,110,105, 48, 49, 56, 70, 7,117,
+110,105, 48, 49, 57, 48, 7,117,110,105, 48, 49, 57, 49, 7,117,110,105, 48, 49, 57, 51, 7,117,110,105, 48, 49, 57, 52, 7,117,
+110,105, 48, 49, 57, 53, 7,117,110,105, 48, 49, 57, 54, 7,117,110,105, 48, 49, 57, 55, 7,117,110,105, 48, 49, 57, 56, 7,117,
+110,105, 48, 49, 57, 57, 7,117,110,105, 48, 49, 57, 65, 7,117,110,105, 48, 49, 57, 66, 7,117,110,105, 48, 49, 57, 67, 7,117,
+110,105, 48, 49, 57, 68, 7,117,110,105, 48, 49, 57, 69, 7,117,110,105, 48, 49, 57, 70, 5, 79,104,111,114,110, 5,111,104,111,
+114,110, 7,117,110,105, 48, 49, 65, 50, 7,117,110,105, 48, 49, 65, 51, 7,117,110,105, 48, 49, 65, 52, 7,117,110,105, 48, 49,
+ 65, 53, 7,117,110,105, 48, 49, 65, 54, 7,117,110,105, 48, 49, 65, 55, 7,117,110,105, 48, 49, 65, 56, 7,117,110,105, 48, 49,
+ 65, 57, 7,117,110,105, 48, 49, 65, 65, 7,117,110,105, 48, 49, 65, 66, 7,117,110,105, 48, 49, 65, 67, 7,117,110,105, 48, 49,
+ 65, 68, 7,117,110,105, 48, 49, 65, 69, 5, 85,104,111,114,110, 5,117,104,111,114,110, 7,117,110,105, 48, 49, 66, 49, 7,117,
+110,105, 48, 49, 66, 50, 7,117,110,105, 48, 49, 66, 51, 7,117,110,105, 48, 49, 66, 52, 7,117,110,105, 48, 49, 66, 53, 7,117,
+110,105, 48, 49, 66, 54, 7,117,110,105, 48, 49, 66, 55, 7,117,110,105, 48, 49, 66, 56, 7,117,110,105, 48, 49, 66, 57, 7,117,
+110,105, 48, 49, 66, 66, 7,117,110,105, 48, 49, 66, 67, 7,117,110,105, 48, 49, 66, 68, 7,117,110,105, 48, 49, 66, 69, 7,117,
+110,105, 48, 49, 67, 48, 7,117,110,105, 48, 49, 67, 49, 7,117,110,105, 48, 49, 67, 50, 7,117,110,105, 48, 49, 67, 51, 7,117,
+110,105, 48, 49, 67, 68, 7,117,110,105, 48, 49, 67, 69, 7,117,110,105, 48, 49, 67, 70, 7,117,110,105, 48, 49, 68, 48, 7,117,
+110,105, 48, 49, 68, 49, 7,117,110,105, 48, 49, 68, 50, 7,117,110,105, 48, 49, 68, 51, 7,117,110,105, 48, 49, 68, 52, 7,117,
+110,105, 48, 49, 68, 53, 7,117,110,105, 48, 49, 68, 54, 7,117,110,105, 48, 49, 68, 55, 7,117,110,105, 48, 49, 68, 56, 7,117,
+110,105, 48, 49, 68, 57, 7,117,110,105, 48, 49, 68, 65, 7,117,110,105, 48, 49, 68, 66, 7,117,110,105, 48, 49, 68, 67, 7,117,
+110,105, 48, 49, 68, 68, 7,117,110,105, 48, 49, 68, 69, 7,117,110,105, 48, 49, 68, 70, 7,117,110,105, 48, 49, 69, 48, 7,117,
+110,105, 48, 49, 69, 49, 7,117,110,105, 48, 49, 69, 50, 7,117,110,105, 48, 49, 69, 51, 6, 71, 99, 97,114,111,110, 6,103, 99,
+ 97,114,111,110, 7,117,110,105, 48, 49, 69, 56, 7,117,110,105, 48, 49, 69, 57, 7,117,110,105, 48, 49, 69, 65, 7,117,110,105,
+ 48, 49, 69, 66, 7,117,110,105, 48, 49, 69, 67, 7,117,110,105, 48, 49, 69, 68, 7,117,110,105, 48, 49, 69, 69, 7,117,110,105,
+ 48, 49, 69, 70, 7,117,110,105, 48, 49, 70, 48, 7,117,110,105, 48, 49, 70, 52, 7,117,110,105, 48, 49, 70, 53, 7,117,110,105,
+ 48, 49, 70, 54, 7,117,110,105, 48, 49, 70, 56, 7,117,110,105, 48, 49, 70, 57, 7, 65, 69, 97, 99,117,116,101, 7, 97,101, 97,
+ 99,117,116,101, 11, 79,115,108, 97,115,104, 97, 99,117,116,101, 11,111,115,108, 97,115,104, 97, 99,117,116,101, 7,117,110,105,
+ 48, 50, 48, 48, 7,117,110,105, 48, 50, 48, 49, 7,117,110,105, 48, 50, 48, 50, 7,117,110,105, 48, 50, 48, 51, 7,117,110,105,
+ 48, 50, 48, 52, 7,117,110,105, 48, 50, 48, 53, 7,117,110,105, 48, 50, 48, 54, 7,117,110,105, 48, 50, 48, 55, 7,117,110,105,
+ 48, 50, 48, 56, 7,117,110,105, 48, 50, 48, 57, 7,117,110,105, 48, 50, 48, 65, 7,117,110,105, 48, 50, 48, 66, 7,117,110,105,
+ 48, 50, 48, 67, 7,117,110,105, 48, 50, 48, 68, 7,117,110,105, 48, 50, 48, 69, 7,117,110,105, 48, 50, 48, 70, 7,117,110,105,
+ 48, 50, 49, 48, 7,117,110,105, 48, 50, 49, 49, 7,117,110,105, 48, 50, 49, 50, 7,117,110,105, 48, 50, 49, 51, 7,117,110,105,
+ 48, 50, 49, 52, 7,117,110,105, 48, 50, 49, 53, 7,117,110,105, 48, 50, 49, 54, 7,117,110,105, 48, 50, 49, 55, 12, 83, 99,111,
+109,109, 97, 97, 99, 99,101,110,116, 12,115, 99,111,109,109, 97, 97, 99, 99,101,110,116, 7,117,110,105, 48, 50, 49, 65, 7,117,
+110,105, 48, 50, 49, 66, 7,117,110,105, 48, 50, 49, 69, 7,117,110,105, 48, 50, 49, 70, 7,117,110,105, 48, 50, 50, 48, 7,117,
+110,105, 48, 50, 50, 49, 7,117,110,105, 48, 50, 50, 52, 7,117,110,105, 48, 50, 50, 53, 7,117,110,105, 48, 50, 50, 54, 7,117,
+110,105, 48, 50, 50, 55, 7,117,110,105, 48, 50, 50, 56, 7,117,110,105, 48, 50, 50, 57, 7,117,110,105, 48, 50, 50, 65, 7,117,
+110,105, 48, 50, 50, 66, 7,117,110,105, 48, 50, 50, 67, 7,117,110,105, 48, 50, 50, 68, 7,117,110,105, 48, 50, 50, 69, 7,117,
+110,105, 48, 50, 50, 70, 7,117,110,105, 48, 50, 51, 48, 7,117,110,105, 48, 50, 51, 49, 7,117,110,105, 48, 50, 51, 50, 7,117,
+110,105, 48, 50, 51, 51, 7,117,110,105, 48, 50, 51, 52, 7,117,110,105, 48, 50, 51, 53, 7,117,110,105, 48, 50, 51, 54, 8,100,
+111,116,108,101,115,115,106, 7,117,110,105, 48, 50, 51, 56, 7,117,110,105, 48, 50, 51, 57, 7,117,110,105, 48, 50, 51, 65, 7,
+117,110,105, 48, 50, 51, 66, 7,117,110,105, 48, 50, 51, 67, 7,117,110,105, 48, 50, 51, 68, 7,117,110,105, 48, 50, 51, 69, 7,
+117,110,105, 48, 50, 51, 70, 7,117,110,105, 48, 50, 52, 48, 7,117,110,105, 48, 50, 52, 49, 7,117,110,105, 48, 50, 52, 53, 7,
+117,110,105, 48, 50, 53, 48, 7,117,110,105, 48, 50, 53, 49, 7,117,110,105, 48, 50, 53, 50, 7,117,110,105, 48, 50, 53, 51, 7,
+117,110,105, 48, 50, 53, 52, 7,117,110,105, 48, 50, 53, 53, 7,117,110,105, 48, 50, 53, 54, 7,117,110,105, 48, 50, 53, 55, 7,
+117,110,105, 48, 50, 53, 56, 7,117,110,105, 48, 50, 53, 57, 7,117,110,105, 48, 50, 53, 65, 7,117,110,105, 48, 50, 53, 66, 7,
+117,110,105, 48, 50, 53, 67, 7,117,110,105, 48, 50, 53, 68, 7,117,110,105, 48, 50, 53, 69, 7,117,110,105, 48, 50, 53, 70, 7,
+117,110,105, 48, 50, 54, 48, 7,117,110,105, 48, 50, 54, 49, 7,117,110,105, 48, 50, 54, 50, 7,117,110,105, 48, 50, 54, 51, 7,
+117,110,105, 48, 50, 54, 52, 7,117,110,105, 48, 50, 54, 53, 7,117,110,105, 48, 50, 54, 54, 7,117,110,105, 48, 50, 54, 55, 7,
+117,110,105, 48, 50, 54, 56, 7,117,110,105, 48, 50, 54, 57, 7,117,110,105, 48, 50, 54, 65, 7,117,110,105, 48, 50, 54, 66, 7,
+117,110,105, 48, 50, 54, 67, 7,117,110,105, 48, 50, 54, 68, 7,117,110,105, 48, 50, 54, 69, 7,117,110,105, 48, 50, 54, 70, 7,
+117,110,105, 48, 50, 55, 48, 7,117,110,105, 48, 50, 55, 49, 7,117,110,105, 48, 50, 55, 50, 7,117,110,105, 48, 50, 55, 51, 7,
+117,110,105, 48, 50, 55, 52, 7,117,110,105, 48, 50, 55, 53, 7,117,110,105, 48, 50, 55, 54, 7,117,110,105, 48, 50, 55, 55, 7,
+117,110,105, 48, 50, 55, 56, 7,117,110,105, 48, 50, 55, 57, 7,117,110,105, 48, 50, 55, 65, 7,117,110,105, 48, 50, 55, 66, 7,
+117,110,105, 48, 50, 55, 67, 7,117,110,105, 48, 50, 55, 68, 7,117,110,105, 48, 50, 55, 69, 7,117,110,105, 48, 50, 55, 70, 7,
+117,110,105, 48, 50, 56, 48, 7,117,110,105, 48, 50, 56, 49, 7,117,110,105, 48, 50, 56, 50, 7,117,110,105, 48, 50, 56, 51, 7,
+117,110,105, 48, 50, 56, 52, 7,117,110,105, 48, 50, 56, 53, 7,117,110,105, 48, 50, 56, 54, 7,117,110,105, 48, 50, 56, 55, 7,
+117,110,105, 48, 50, 56, 56, 7,117,110,105, 48, 50, 56, 57, 7,117,110,105, 48, 50, 56, 65, 7,117,110,105, 48, 50, 56, 66, 7,
+117,110,105, 48, 50, 56, 67, 7,117,110,105, 48, 50, 56, 68, 7,117,110,105, 48, 50, 56, 69, 7,117,110,105, 48, 50, 56, 70, 7,
+117,110,105, 48, 50, 57, 48, 7,117,110,105, 48, 50, 57, 49, 7,117,110,105, 48, 50, 57, 50, 7,117,110,105, 48, 50, 57, 51, 7,
+117,110,105, 48, 50, 57, 52, 7,117,110,105, 48, 50, 57, 53, 7,117,110,105, 48, 50, 57, 54, 7,117,110,105, 48, 50, 57, 55, 7,
+117,110,105, 48, 50, 57, 56, 7,117,110,105, 48, 50, 57, 57, 7,117,110,105, 48, 50, 57, 65, 7,117,110,105, 48, 50, 57, 66, 7,
+117,110,105, 48, 50, 57, 67, 7,117,110,105, 48, 50, 57, 68, 7,117,110,105, 48, 50, 57, 69, 7,117,110,105, 48, 50, 57, 70, 7,
+117,110,105, 48, 50, 65, 48, 7,117,110,105, 48, 50, 65, 49, 7,117,110,105, 48, 50, 65, 50, 7,117,110,105, 48, 50, 65, 51, 7,
+117,110,105, 48, 50, 65, 52, 7,117,110,105, 48, 50, 65, 53, 7,117,110,105, 48, 50, 65, 54, 7,117,110,105, 48, 50, 65, 55, 7,
+117,110,105, 48, 50, 65, 56, 7,117,110,105, 48, 50, 65, 57, 7,117,110,105, 48, 50, 65, 65, 7,117,110,105, 48, 50, 65, 66, 7,
+117,110,105, 48, 50, 65, 67, 7,117,110,105, 48, 50, 65, 68, 7,117,110,105, 48, 50, 65, 69, 7,117,110,105, 48, 50, 65, 70, 7,
+117,110,105, 48, 50, 66, 48, 7,117,110,105, 48, 50, 66, 49, 7,117,110,105, 48, 50, 66, 50, 7,117,110,105, 48, 50, 66, 51, 7,
+117,110,105, 48, 50, 66, 52, 7,117,110,105, 48, 50, 66, 53, 7,117,110,105, 48, 50, 66, 54, 7,117,110,105, 48, 50, 66, 55, 7,
+117,110,105, 48, 50, 66, 56, 7,117,110,105, 48, 50, 66, 57, 7,117,110,105, 48, 50, 66, 66, 7,117,110,105, 48, 50, 66, 67, 7,
+117,110,105, 48, 50, 66, 68, 7,117,110,105, 48, 50, 66, 69, 7,117,110,105, 48, 50, 66, 70, 7,117,110,105, 48, 50, 67, 48, 7,
+117,110,105, 48, 50, 67, 49, 7,117,110,105, 48, 50, 67, 56, 7,117,110,105, 48, 50, 67, 57, 7,117,110,105, 48, 50, 67, 67, 7,
+117,110,105, 48, 50, 67, 68, 7,117,110,105, 48, 50, 68, 48, 7,117,110,105, 48, 50, 68, 49, 7,117,110,105, 48, 50, 68, 50, 7,
+117,110,105, 48, 50, 68, 51, 7,117,110,105, 48, 50, 68, 54, 7,117,110,105, 48, 50, 68, 69, 7,117,110,105, 48, 50, 69, 48, 7,
+117,110,105, 48, 50, 69, 49, 7,117,110,105, 48, 50, 69, 50, 7,117,110,105, 48, 50, 69, 51, 7,117,110,105, 48, 50, 69, 52, 7,
+117,110,105, 48, 50, 69, 53, 7,117,110,105, 48, 50, 69, 54, 7,117,110,105, 48, 50, 69, 55, 7,117,110,105, 48, 50, 69, 56, 7,
+117,110,105, 48, 50, 69, 57, 7,117,110,105, 48, 50, 70, 51, 9,103,114, 97,118,101, 99,111,109, 98, 9, 97, 99,117,116,101, 99,
+111,109, 98, 7,117,110,105, 48, 51, 48, 50, 9,116,105,108,100,101, 99,111,109, 98, 7,117,110,105, 48, 51, 48, 52, 7,117,110,
+105, 48, 51, 48, 53, 7,117,110,105, 48, 51, 48, 54, 7,117,110,105, 48, 51, 48, 55, 7,117,110,105, 48, 51, 48, 56, 13,104,111,
+111,107, 97, 98,111,118,101, 99,111,109, 98, 7,117,110,105, 48, 51, 48, 65, 7,117,110,105, 48, 51, 48, 66, 7,117,110,105, 48,
+ 51, 48, 67, 7,117,110,105, 48, 51, 48, 68, 7,117,110,105, 48, 51, 48, 69, 7,117,110,105, 48, 51, 48, 70, 7,117,110,105, 48,
+ 51, 49, 48, 7,117,110,105, 48, 51, 49, 49, 7,117,110,105, 48, 51, 49, 50, 7,117,110,105, 48, 51, 49, 51, 7,117,110,105, 48,
+ 51, 49, 52, 7,117,110,105, 48, 51, 49, 53, 7,117,110,105, 48, 51, 49, 54, 7,117,110,105, 48, 51, 49, 55, 7,117,110,105, 48,
+ 51, 49, 56, 7,117,110,105, 48, 51, 49, 57, 7,117,110,105, 48, 51, 49, 65, 7,117,110,105, 48, 51, 49, 66, 7,117,110,105, 48,
+ 51, 49, 67, 7,117,110,105, 48, 51, 49, 68, 7,117,110,105, 48, 51, 49, 69, 7,117,110,105, 48, 51, 49, 70, 7,117,110,105, 48,
+ 51, 50, 48, 7,117,110,105, 48, 51, 50, 49, 7,117,110,105, 48, 51, 50, 50, 12,100,111,116, 98,101,108,111,119, 99,111,109, 98,
+ 7,117,110,105, 48, 51, 50, 52, 7,117,110,105, 48, 51, 50, 53, 7,117,110,105, 48, 51, 50, 54, 7,117,110,105, 48, 51, 50, 55,
+ 7,117,110,105, 48, 51, 50, 56, 7,117,110,105, 48, 51, 50, 57, 7,117,110,105, 48, 51, 50, 65, 7,117,110,105, 48, 51, 50, 66,
+ 7,117,110,105, 48, 51, 50, 67, 7,117,110,105, 48, 51, 50, 68, 7,117,110,105, 48, 51, 50, 69, 7,117,110,105, 48, 51, 50, 70,
+ 7,117,110,105, 48, 51, 51, 48, 7,117,110,105, 48, 51, 51, 49, 7,117,110,105, 48, 51, 51, 50, 7,117,110,105, 48, 51, 51, 51,
+ 7,117,110,105, 48, 51, 51, 52, 7,117,110,105, 48, 51, 51, 53, 7,117,110,105, 48, 51, 51, 54, 7,117,110,105, 48, 51, 51, 55,
+ 7,117,110,105, 48, 51, 51, 56, 7,117,110,105, 48, 51, 51, 57, 7,117,110,105, 48, 51, 51, 65, 7,117,110,105, 48, 51, 51, 66,
+ 7,117,110,105, 48, 51, 51, 67, 7,117,110,105, 48, 51, 51, 68, 7,117,110,105, 48, 51, 51, 69, 7,117,110,105, 48, 51, 51, 70,
+ 7,117,110,105, 48, 51, 52, 51, 7,117,110,105, 48, 51, 53, 56, 7,117,110,105, 48, 51, 54, 49, 7,117,110,105, 48, 51, 55, 52,
+ 7,117,110,105, 48, 51, 55, 53, 7,117,110,105, 48, 51, 55, 65, 7,117,110,105, 48, 51, 55, 69, 5,116,111,110,111,115, 13,100,
+105,101,114,101,115,105,115,116,111,110,111,115, 10, 65,108,112,104, 97,116,111,110,111,115, 9, 97,110,111,116,101,108,101,105,
+ 97, 12, 69,112,115,105,108,111,110,116,111,110,111,115, 8, 69,116, 97,116,111,110,111,115, 9, 73,111,116, 97,116,111,110,111,
+115, 12, 79,109,105, 99,114,111,110,116,111,110,111,115, 12, 85,112,115,105,108,111,110,116,111,110,111,115, 10, 79,109,101,103,
+ 97,116,111,110,111,115, 17,105,111,116, 97,100,105,101,114,101,115,105,115,116,111,110,111,115, 5, 65,108,112,104, 97, 4, 66,
+101,116, 97, 5, 71, 97,109,109, 97, 7,117,110,105, 48, 51, 57, 52, 7, 69,112,115,105,108,111,110, 4, 90,101,116, 97, 3, 69,
+116, 97, 5, 84,104,101,116, 97, 4, 73,111,116, 97, 5, 75, 97,112,112, 97, 6, 76, 97,109, 98,100, 97, 2, 77,117, 2, 78,117,
+ 2, 88,105, 7, 79,109,105, 99,114,111,110, 2, 80,105, 3, 82,104,111, 5, 83,105,103,109, 97, 3, 84, 97,117, 7, 85,112,115,
+105,108,111,110, 3, 80,104,105, 3, 67,104,105, 3, 80,115,105, 12, 73,111,116, 97,100,105,101,114,101,115,105,115, 15, 85,112,
+115,105,108,111,110,100,105,101,114,101,115,105,115, 10, 97,108,112,104, 97,116,111,110,111,115, 12,101,112,115,105,108,111,110,
+116,111,110,111,115, 8,101,116, 97,116,111,110,111,115, 9,105,111,116, 97,116,111,110,111,115, 20,117,112,115,105,108,111,110,
+100,105,101,114,101,115,105,115,116,111,110,111,115, 5, 97,108,112,104, 97, 4, 98,101,116, 97, 5,103, 97,109,109, 97, 5,100,
+101,108,116, 97, 7,101,112,115,105,108,111,110, 4,122,101,116, 97, 3,101,116, 97, 5,116,104,101,116, 97, 4,105,111,116, 97,
+ 5,107, 97,112,112, 97, 6,108, 97,109, 98,100, 97, 7,117,110,105, 48, 51, 66, 67, 2,110,117, 2,120,105, 7,111,109,105, 99,
+114,111,110, 3,114,104,111, 6,115,105,103,109, 97, 49, 5,115,105,103,109, 97, 3,116, 97,117, 7,117,112,115,105,108,111,110,
+ 3,112,104,105, 3, 99,104,105, 3,112,115,105, 5,111,109,101,103, 97, 12,105,111,116, 97,100,105,101,114,101,115,105,115, 15,
+117,112,115,105,108,111,110,100,105,101,114,101,115,105,115, 12,111,109,105, 99,114,111,110,116,111,110,111,115, 12,117,112,115,
+105,108,111,110,116,111,110,111,115, 10,111,109,101,103, 97,116,111,110,111,115, 7,117,110,105, 48, 51, 68, 48, 6,116,104,101,
+116, 97, 49, 8, 85,112,115,105,108,111,110, 49, 7,117,110,105, 48, 51, 68, 51, 7,117,110,105, 48, 51, 68, 52, 4,112,104,105,
+ 49, 6,111,109,101,103, 97, 49, 7,117,110,105, 48, 51, 68, 55, 7,117,110,105, 48, 51, 68, 56, 7,117,110,105, 48, 51, 68, 57,
+ 7,117,110,105, 48, 51, 68, 65, 7,117,110,105, 48, 51, 68, 66, 7,117,110,105, 48, 51, 68, 67, 7,117,110,105, 48, 51, 68, 68,
+ 7,117,110,105, 48, 51, 68, 69, 7,117,110,105, 48, 51, 68, 70, 7,117,110,105, 48, 51, 69, 48, 7,117,110,105, 48, 51, 69, 49,
+ 7,117,110,105, 48, 51, 70, 48, 7,117,110,105, 48, 51, 70, 49, 7,117,110,105, 48, 51, 70, 50, 7,117,110,105, 48, 51, 70, 51,
+ 7,117,110,105, 48, 51, 70, 52, 7,117,110,105, 48, 51, 70, 53, 7,117,110,105, 48, 51, 70, 54, 7,117,110,105, 48, 51, 70, 55,
+ 7,117,110,105, 48, 51, 70, 56, 7,117,110,105, 48, 51, 70, 57, 7,117,110,105, 48, 51, 70, 65, 7,117,110,105, 48, 51, 70, 66,
+ 7,117,110,105, 48, 51, 70, 67, 7,117,110,105, 48, 51, 70, 68, 7,117,110,105, 48, 51, 70, 69, 7,117,110,105, 48, 51, 70, 70,
+ 7,117,110,105, 48, 52, 48, 48, 7,117,110,105, 48, 52, 48, 49, 7,117,110,105, 48, 52, 48, 50, 7,117,110,105, 48, 52, 48, 51,
+ 7,117,110,105, 48, 52, 48, 52, 7,117,110,105, 48, 52, 48, 53, 7,117,110,105, 48, 52, 48, 54, 7,117,110,105, 48, 52, 48, 55,
+ 7,117,110,105, 48, 52, 48, 56, 7,117,110,105, 48, 52, 48, 57, 7,117,110,105, 48, 52, 48, 65, 7,117,110,105, 48, 52, 48, 66,
+ 7,117,110,105, 48, 52, 48, 67, 7,117,110,105, 48, 52, 48, 68, 7,117,110,105, 48, 52, 48, 69, 7,117,110,105, 48, 52, 48, 70,
+ 7,117,110,105, 48, 52, 49, 48, 7,117,110,105, 48, 52, 49, 49, 7,117,110,105, 48, 52, 49, 50, 7,117,110,105, 48, 52, 49, 51,
+ 7,117,110,105, 48, 52, 49, 52, 7,117,110,105, 48, 52, 49, 53, 7,117,110,105, 48, 52, 49, 54, 7,117,110,105, 48, 52, 49, 55,
+ 7,117,110,105, 48, 52, 49, 56, 7,117,110,105, 48, 52, 49, 57, 7,117,110,105, 48, 52, 49, 65, 7,117,110,105, 48, 52, 49, 66,
+ 7,117,110,105, 48, 52, 49, 67, 7,117,110,105, 48, 52, 49, 68, 7,117,110,105, 48, 52, 49, 69, 7,117,110,105, 48, 52, 49, 70,
+ 7,117,110,105, 48, 52, 50, 48, 7,117,110,105, 48, 52, 50, 49, 7,117,110,105, 48, 52, 50, 50, 7,117,110,105, 48, 52, 50, 51,
+ 7,117,110,105, 48, 52, 50, 52, 7,117,110,105, 48, 52, 50, 53, 7,117,110,105, 48, 52, 50, 54, 7,117,110,105, 48, 52, 50, 55,
+ 7,117,110,105, 48, 52, 50, 56, 7,117,110,105, 48, 52, 50, 57, 7,117,110,105, 48, 52, 50, 65, 7,117,110,105, 48, 52, 50, 66,
+ 7,117,110,105, 48, 52, 50, 67, 7,117,110,105, 48, 52, 50, 68, 7,117,110,105, 48, 52, 50, 69, 7,117,110,105, 48, 52, 50, 70,
+ 7,117,110,105, 48, 52, 51, 48, 7,117,110,105, 48, 52, 51, 49, 7,117,110,105, 48, 52, 51, 50, 7,117,110,105, 48, 52, 51, 51,
+ 7,117,110,105, 48, 52, 51, 52, 7,117,110,105, 48, 52, 51, 53, 7,117,110,105, 48, 52, 51, 54, 7,117,110,105, 48, 52, 51, 55,
+ 7,117,110,105, 48, 52, 51, 56, 7,117,110,105, 48, 52, 51, 57, 7,117,110,105, 48, 52, 51, 65, 7,117,110,105, 48, 52, 51, 66,
+ 7,117,110,105, 48, 52, 51, 67, 7,117,110,105, 48, 52, 51, 68, 7,117,110,105, 48, 52, 51, 69, 7,117,110,105, 48, 52, 51, 70,
+ 7,117,110,105, 48, 52, 52, 48, 7,117,110,105, 48, 52, 52, 49, 7,117,110,105, 48, 52, 52, 50, 7,117,110,105, 48, 52, 52, 51,
+ 7,117,110,105, 48, 52, 52, 52, 7,117,110,105, 48, 52, 52, 53, 7,117,110,105, 48, 52, 52, 54, 7,117,110,105, 48, 52, 52, 55,
+ 7,117,110,105, 48, 52, 52, 56, 7,117,110,105, 48, 52, 52, 57, 7,117,110,105, 48, 52, 52, 65, 7,117,110,105, 48, 52, 52, 66,
+ 7,117,110,105, 48, 52, 52, 67, 7,117,110,105, 48, 52, 52, 68, 7,117,110,105, 48, 52, 52, 69, 7,117,110,105, 48, 52, 52, 70,
+ 7,117,110,105, 48, 52, 53, 48, 7,117,110,105, 48, 52, 53, 49, 7,117,110,105, 48, 52, 53, 50, 7,117,110,105, 48, 52, 53, 51,
+ 7,117,110,105, 48, 52, 53, 52, 7,117,110,105, 48, 52, 53, 53, 7,117,110,105, 48, 52, 53, 54, 7,117,110,105, 48, 52, 53, 55,
+ 7,117,110,105, 48, 52, 53, 56, 7,117,110,105, 48, 52, 53, 57, 7,117,110,105, 48, 52, 53, 65, 7,117,110,105, 48, 52, 53, 66,
+ 7,117,110,105, 48, 52, 53, 67, 7,117,110,105, 48, 52, 53, 68, 7,117,110,105, 48, 52, 53, 69, 7,117,110,105, 48, 52, 53, 70,
+ 7,117,110,105, 48, 52, 57, 48, 7,117,110,105, 48, 52, 57, 49, 7,117,110,105, 48, 52, 57, 50, 7,117,110,105, 48, 52, 57, 51,
+ 7,117,110,105, 48, 52, 57, 52, 7,117,110,105, 48, 52, 57, 53, 7,117,110,105, 48, 52, 57, 54, 7,117,110,105, 48, 52, 57, 55,
+ 7,117,110,105, 48, 52, 57, 56, 7,117,110,105, 48, 52, 57, 57, 7,117,110,105, 48, 52, 57, 65, 7,117,110,105, 48, 52, 57, 66,
+ 7,117,110,105, 48, 52, 65, 50, 7,117,110,105, 48, 52, 65, 51, 7,117,110,105, 48, 52, 65, 65, 7,117,110,105, 48, 52, 65, 66,
+ 7,117,110,105, 48, 52, 65, 67, 7,117,110,105, 48, 52, 65, 68, 7,117,110,105, 48, 52, 65, 69, 7,117,110,105, 48, 52, 65, 70,
+ 7,117,110,105, 48, 52, 66, 48, 7,117,110,105, 48, 52, 66, 49, 7,117,110,105, 48, 52, 66, 50, 7,117,110,105, 48, 52, 66, 51,
+ 7,117,110,105, 48, 52, 66, 65, 7,117,110,105, 48, 52, 66, 66, 7,117,110,105, 48, 52, 67, 48, 7,117,110,105, 48, 52, 67, 49,
+ 7,117,110,105, 48, 52, 67, 50, 7,117,110,105, 48, 52, 67, 51, 7,117,110,105, 48, 52, 67, 52, 7,117,110,105, 48, 52, 67, 55,
+ 7,117,110,105, 48, 52, 67, 56, 7,117,110,105, 48, 52, 67, 66, 7,117,110,105, 48, 52, 67, 67, 7,117,110,105, 48, 52, 67, 70,
+ 7,117,110,105, 48, 52, 68, 48, 7,117,110,105, 48, 52, 68, 49, 7,117,110,105, 48, 52, 68, 50, 7,117,110,105, 48, 52, 68, 51,
+ 7,117,110,105, 48, 52, 68, 52, 7,117,110,105, 48, 52, 68, 53, 7,117,110,105, 48, 52, 68, 54, 7,117,110,105, 48, 52, 68, 55,
+ 7,117,110,105, 48, 52, 68, 56, 7,117,110,105, 48, 52, 68, 57, 7,117,110,105, 48, 52, 68, 65, 7,117,110,105, 48, 52, 68, 66,
+ 7,117,110,105, 48, 52, 68, 67, 7,117,110,105, 48, 52, 68, 68, 7,117,110,105, 48, 52, 68, 69, 7,117,110,105, 48, 52, 68, 70,
+ 7,117,110,105, 48, 52, 69, 48, 7,117,110,105, 48, 52, 69, 49, 7,117,110,105, 48, 52, 69, 50, 7,117,110,105, 48, 52, 69, 51,
+ 7,117,110,105, 48, 52, 69, 52, 7,117,110,105, 48, 52, 69, 53, 7,117,110,105, 48, 52, 69, 54, 7,117,110,105, 48, 52, 69, 55,
+ 7,117,110,105, 48, 52, 69, 56, 7,117,110,105, 48, 52, 69, 57, 7,117,110,105, 48, 52, 69, 65, 7,117,110,105, 48, 52, 69, 66,
+ 7,117,110,105, 48, 52, 69, 67, 7,117,110,105, 48, 52, 69, 68, 7,117,110,105, 48, 52, 69, 69, 7,117,110,105, 48, 52, 69, 70,
+ 7,117,110,105, 48, 52, 70, 48, 7,117,110,105, 48, 52, 70, 49, 7,117,110,105, 48, 52, 70, 50, 7,117,110,105, 48, 52, 70, 51,
+ 7,117,110,105, 48, 52, 70, 52, 7,117,110,105, 48, 52, 70, 53, 7,117,110,105, 48, 52, 70, 54, 7,117,110,105, 48, 52, 70, 55,
+ 7,117,110,105, 48, 52, 70, 56, 7,117,110,105, 48, 52, 70, 57, 7,117,110,105, 48, 54, 48, 67, 7,117,110,105, 48, 54, 49, 53,
+ 7,117,110,105, 48, 54, 49, 66, 7,117,110,105, 48, 54, 49, 70, 7,117,110,105, 48, 54, 50, 49, 7,117,110,105, 48, 54, 50, 50,
+ 7,117,110,105, 48, 54, 50, 51, 7,117,110,105, 48, 54, 50, 52, 7,117,110,105, 48, 54, 50, 53, 7,117,110,105, 48, 54, 50, 54,
+ 7,117,110,105, 48, 54, 50, 55, 7,117,110,105, 48, 54, 50, 56, 7,117,110,105, 48, 54, 50, 57, 7,117,110,105, 48, 54, 50, 65,
+ 7,117,110,105, 48, 54, 50, 66, 7,117,110,105, 48, 54, 50, 67, 7,117,110,105, 48, 54, 50, 68, 7,117,110,105, 48, 54, 50, 69,
+ 7,117,110,105, 48, 54, 50, 70, 7,117,110,105, 48, 54, 51, 48, 7,117,110,105, 48, 54, 51, 49, 7,117,110,105, 48, 54, 51, 50,
+ 7,117,110,105, 48, 54, 51, 51, 7,117,110,105, 48, 54, 51, 52, 7,117,110,105, 48, 54, 51, 53, 7,117,110,105, 48, 54, 51, 54,
+ 7,117,110,105, 48, 54, 51, 55, 7,117,110,105, 48, 54, 51, 56, 7,117,110,105, 48, 54, 51, 57, 7,117,110,105, 48, 54, 51, 65,
+ 7,117,110,105, 48, 54, 52, 48, 7,117,110,105, 48, 54, 52, 49, 7,117,110,105, 48, 54, 52, 50, 7,117,110,105, 48, 54, 52, 51,
+ 7,117,110,105, 48, 54, 52, 52, 7,117,110,105, 48, 54, 52, 53, 7,117,110,105, 48, 54, 52, 54, 7,117,110,105, 48, 54, 52, 55,
+ 7,117,110,105, 48, 54, 52, 56, 7,117,110,105, 48, 54, 52, 57, 7,117,110,105, 48, 54, 52, 65, 7,117,110,105, 48, 54, 52, 66,
+ 7,117,110,105, 48, 54, 52, 67, 7,117,110,105, 48, 54, 52, 68, 7,117,110,105, 48, 54, 52, 69, 7,117,110,105, 48, 54, 52, 70,
+ 7,117,110,105, 48, 54, 53, 48, 7,117,110,105, 48, 54, 53, 49, 7,117,110,105, 48, 54, 53, 50, 7,117,110,105, 48, 54, 53, 51,
+ 7,117,110,105, 48, 54, 53, 52, 7,117,110,105, 48, 54, 53, 53, 7,117,110,105, 48, 54, 53, 65, 7,117,110,105, 48, 54, 54, 48,
+ 7,117,110,105, 48, 54, 54, 49, 7,117,110,105, 48, 54, 54, 50, 7,117,110,105, 48, 54, 54, 51, 7,117,110,105, 48, 54, 54, 52,
+ 7,117,110,105, 48, 54, 54, 53, 7,117,110,105, 48, 54, 54, 54, 7,117,110,105, 48, 54, 54, 55, 7,117,110,105, 48, 54, 54, 56,
+ 7,117,110,105, 48, 54, 54, 57, 7,117,110,105, 48, 54, 54, 65, 7,117,110,105, 48, 54, 54, 66, 7,117,110,105, 48, 54, 54, 67,
+ 7,117,110,105, 48, 54, 54, 68, 7,117,110,105, 48, 54, 54, 69, 7,117,110,105, 48, 54, 54, 70, 7,117,110,105, 48, 54, 55, 52,
+ 7,117,110,105, 48, 54, 55, 57, 7,117,110,105, 48, 54, 55, 65, 7,117,110,105, 48, 54, 55, 66, 7,117,110,105, 48, 54, 55, 67,
+ 7,117,110,105, 48, 54, 55, 68, 7,117,110,105, 48, 54, 55, 69, 7,117,110,105, 48, 54, 55, 70, 7,117,110,105, 48, 54, 56, 48,
+ 7,117,110,105, 48, 54, 56, 49, 7,117,110,105, 48, 54, 56, 50, 7,117,110,105, 48, 54, 56, 51, 7,117,110,105, 48, 54, 56, 52,
+ 7,117,110,105, 48, 54, 56, 53, 7,117,110,105, 48, 54, 56, 54, 7,117,110,105, 48, 54, 56, 55, 7,117,110,105, 48, 54, 57, 49,
+ 7,117,110,105, 48, 54, 57, 50, 7,117,110,105, 48, 54, 57, 56, 7,117,110,105, 48, 54, 65, 49, 7,117,110,105, 48, 54, 65, 52,
+ 7,117,110,105, 48, 54, 65, 57, 7,117,110,105, 48, 54, 65, 70, 7,117,110,105, 48, 54, 66, 53, 7,117,110,105, 48, 54, 66, 65,
+ 7,117,110,105, 48, 54, 66, 69, 7,117,110,105, 48, 54, 67, 54, 7,117,110,105, 48, 54, 67, 67, 7,117,110,105, 48, 54, 67, 69,
+ 7,117,110,105, 48, 54, 68, 53, 7,117,110,105, 48, 54, 70, 48, 7,117,110,105, 48, 54, 70, 49, 7,117,110,105, 48, 54, 70, 50,
+ 7,117,110,105, 48, 54, 70, 51, 7,117,110,105, 48, 54, 70, 52, 7,117,110,105, 48, 54, 70, 53, 7,117,110,105, 48, 54, 70, 54,
+ 7,117,110,105, 48, 54, 70, 55, 7,117,110,105, 48, 54, 70, 56, 7,117,110,105, 48, 54, 70, 57, 7,117,110,105, 48, 69, 56, 49,
+ 7,117,110,105, 48, 69, 56, 50, 7,117,110,105, 48, 69, 56, 52, 7,117,110,105, 48, 69, 56, 55, 7,117,110,105, 48, 69, 56, 56,
+ 7,117,110,105, 48, 69, 56, 65, 7,117,110,105, 48, 69, 56, 68, 7,117,110,105, 48, 69, 57, 52, 7,117,110,105, 48, 69, 57, 53,
+ 7,117,110,105, 48, 69, 57, 54, 7,117,110,105, 48, 69, 57, 55, 7,117,110,105, 48, 69, 57, 57, 7,117,110,105, 48, 69, 57, 65,
+ 7,117,110,105, 48, 69, 57, 66, 7,117,110,105, 48, 69, 57, 67, 7,117,110,105, 48, 69, 57, 68, 7,117,110,105, 48, 69, 57, 69,
+ 7,117,110,105, 48, 69, 57, 70, 7,117,110,105, 48, 69, 65, 49, 7,117,110,105, 48, 69, 65, 50, 7,117,110,105, 48, 69, 65, 51,
+ 7,117,110,105, 48, 69, 65, 53, 7,117,110,105, 48, 69, 65, 55, 7,117,110,105, 48, 69, 65, 65, 7,117,110,105, 48, 69, 65, 66,
+ 7,117,110,105, 48, 69, 65, 68, 7,117,110,105, 48, 69, 65, 69, 7,117,110,105, 48, 69, 65, 70, 7,117,110,105, 48, 69, 66, 48,
+ 7,117,110,105, 48, 69, 66, 49, 7,117,110,105, 48, 69, 66, 50, 7,117,110,105, 48, 69, 66, 51, 7,117,110,105, 48, 69, 66, 52,
+ 7,117,110,105, 48, 69, 66, 53, 7,117,110,105, 48, 69, 66, 54, 7,117,110,105, 48, 69, 66, 55, 7,117,110,105, 48, 69, 66, 56,
+ 7,117,110,105, 48, 69, 66, 57, 7,117,110,105, 48, 69, 66, 66, 7,117,110,105, 48, 69, 66, 67, 7,117,110,105, 48, 69, 67, 56,
+ 7,117,110,105, 48, 69, 67, 57, 7,117,110,105, 48, 69, 67, 65, 7,117,110,105, 48, 69, 67, 66, 7,117,110,105, 48, 69, 67, 67,
+ 7,117,110,105, 48, 69, 67, 68, 7,117,110,105, 49, 48, 68, 48, 7,117,110,105, 49, 48, 68, 49, 7,117,110,105, 49, 48, 68, 50,
+ 7,117,110,105, 49, 48, 68, 51, 7,117,110,105, 49, 48, 68, 52, 7,117,110,105, 49, 48, 68, 53, 7,117,110,105, 49, 48, 68, 54,
+ 7,117,110,105, 49, 48, 68, 55, 7,117,110,105, 49, 48, 68, 56, 7,117,110,105, 49, 48, 68, 57, 7,117,110,105, 49, 48, 68, 65,
+ 7,117,110,105, 49, 48, 68, 66, 7,117,110,105, 49, 48, 68, 67, 7,117,110,105, 49, 48, 68, 68, 7,117,110,105, 49, 48, 68, 69,
+ 7,117,110,105, 49, 48, 68, 70, 7,117,110,105, 49, 48, 69, 48, 7,117,110,105, 49, 48, 69, 49, 7,117,110,105, 49, 48, 69, 50,
+ 7,117,110,105, 49, 48, 69, 51, 7,117,110,105, 49, 48, 69, 52, 7,117,110,105, 49, 48, 69, 53, 7,117,110,105, 49, 48, 69, 54,
+ 7,117,110,105, 49, 48, 69, 55, 7,117,110,105, 49, 48, 69, 56, 7,117,110,105, 49, 48, 69, 57, 7,117,110,105, 49, 48, 69, 65,
+ 7,117,110,105, 49, 48, 69, 66, 7,117,110,105, 49, 48, 69, 67, 7,117,110,105, 49, 48, 69, 68, 7,117,110,105, 49, 48, 69, 69,
+ 7,117,110,105, 49, 48, 69, 70, 7,117,110,105, 49, 48, 70, 48, 7,117,110,105, 49, 48, 70, 49, 7,117,110,105, 49, 48, 70, 50,
+ 7,117,110,105, 49, 48, 70, 51, 7,117,110,105, 49, 48, 70, 52, 7,117,110,105, 49, 48, 70, 53, 7,117,110,105, 49, 48, 70, 54,
+ 7,117,110,105, 49, 48, 70, 55, 7,117,110,105, 49, 48, 70, 56, 7,117,110,105, 49, 48, 70, 57, 7,117,110,105, 49, 48, 70, 65,
+ 7,117,110,105, 49, 48, 70, 66, 7,117,110,105, 49, 48, 70, 67, 7,117,110,105, 49, 68, 48, 50, 7,117,110,105, 49, 68, 48, 56,
+ 7,117,110,105, 49, 68, 48, 57, 7,117,110,105, 49, 68, 49, 52, 7,117,110,105, 49, 68, 49, 54, 7,117,110,105, 49, 68, 49, 55,
+ 7,117,110,105, 49, 68, 49, 68, 7,117,110,105, 49, 68, 49, 69, 7,117,110,105, 49, 68, 49, 70, 7,117,110,105, 49, 68, 50, 67,
+ 7,117,110,105, 49, 68, 50, 68, 7,117,110,105, 49, 68, 50, 69, 7,117,110,105, 49, 68, 51, 48, 7,117,110,105, 49, 68, 51, 49,
+ 7,117,110,105, 49, 68, 51, 50, 7,117,110,105, 49, 68, 51, 51, 7,117,110,105, 49, 68, 51, 52, 7,117,110,105, 49, 68, 51, 53,
+ 7,117,110,105, 49, 68, 51, 54, 7,117,110,105, 49, 68, 51, 55, 7,117,110,105, 49, 68, 51, 56, 7,117,110,105, 49, 68, 51, 57,
+ 7,117,110,105, 49, 68, 51, 65, 7,117,110,105, 49, 68, 51, 66, 7,117,110,105, 49, 68, 51, 67, 7,117,110,105, 49, 68, 51, 69,
+ 7,117,110,105, 49, 68, 51, 70, 7,117,110,105, 49, 68, 52, 48, 7,117,110,105, 49, 68, 52, 49, 7,117,110,105, 49, 68, 52, 50,
+ 7,117,110,105, 49, 68, 52, 51, 7,117,110,105, 49, 68, 52, 52, 7,117,110,105, 49, 68, 52, 53, 7,117,110,105, 49, 68, 52, 54,
+ 7,117,110,105, 49, 68, 52, 55, 7,117,110,105, 49, 68, 52, 56, 7,117,110,105, 49, 68, 52, 57, 7,117,110,105, 49, 68, 52, 65,
+ 7,117,110,105, 49, 68, 52, 66, 7,117,110,105, 49, 68, 52, 67, 7,117,110,105, 49, 68, 52, 68, 7,117,110,105, 49, 68, 52, 69,
+ 7,117,110,105, 49, 68, 52, 70, 7,117,110,105, 49, 68, 53, 48, 7,117,110,105, 49, 68, 53, 49, 7,117,110,105, 49, 68, 53, 50,
+ 7,117,110,105, 49, 68, 53, 51, 7,117,110,105, 49, 68, 53, 52, 7,117,110,105, 49, 68, 53, 53, 7,117,110,105, 49, 68, 53, 54,
+ 7,117,110,105, 49, 68, 53, 55, 7,117,110,105, 49, 68, 53, 56, 7,117,110,105, 49, 68, 53, 57, 7,117,110,105, 49, 68, 53, 65,
+ 7,117,110,105, 49, 68, 53, 66, 7,117,110,105, 49, 68, 54, 50, 7,117,110,105, 49, 68, 54, 51, 7,117,110,105, 49, 68, 54, 52,
+ 7,117,110,105, 49, 68, 54, 53, 7,117,110,105, 49, 68, 55, 55, 7,117,110,105, 49, 68, 55, 56, 7,117,110,105, 49, 68, 55, 66,
+ 7,117,110,105, 49, 68, 56, 53, 7,117,110,105, 49, 68, 57, 66, 7,117,110,105, 49, 68, 57, 67, 7,117,110,105, 49, 68, 57, 68,
+ 7,117,110,105, 49, 68, 57, 69, 7,117,110,105, 49, 68, 57, 70, 7,117,110,105, 49, 68, 65, 48, 7,117,110,105, 49, 68, 65, 49,
+ 7,117,110,105, 49, 68, 65, 50, 7,117,110,105, 49, 68, 65, 51, 7,117,110,105, 49, 68, 65, 52, 7,117,110,105, 49, 68, 65, 53,
+ 7,117,110,105, 49, 68, 65, 54, 7,117,110,105, 49, 68, 65, 55, 7,117,110,105, 49, 68, 65, 56, 7,117,110,105, 49, 68, 65, 57,
+ 7,117,110,105, 49, 68, 65, 65, 7,117,110,105, 49, 68, 65, 66, 7,117,110,105, 49, 68, 65, 67, 7,117,110,105, 49, 68, 65, 68,
+ 7,117,110,105, 49, 68, 65, 69, 7,117,110,105, 49, 68, 65, 70, 7,117,110,105, 49, 68, 66, 48, 7,117,110,105, 49, 68, 66, 49,
+ 7,117,110,105, 49, 68, 66, 50, 7,117,110,105, 49, 68, 66, 51, 7,117,110,105, 49, 68, 66, 52, 7,117,110,105, 49, 68, 66, 53,
+ 7,117,110,105, 49, 68, 66, 54, 7,117,110,105, 49, 68, 66, 55, 7,117,110,105, 49, 68, 66, 57, 7,117,110,105, 49, 68, 66, 65,
+ 7,117,110,105, 49, 68, 66, 66, 7,117,110,105, 49, 68, 66, 67, 7,117,110,105, 49, 68, 66, 68, 7,117,110,105, 49, 68, 66, 69,
+ 7,117,110,105, 49, 68, 66, 70, 7,117,110,105, 49, 69, 48, 48, 7,117,110,105, 49, 69, 48, 49, 7,117,110,105, 49, 69, 48, 50,
+ 7,117,110,105, 49, 69, 48, 51, 7,117,110,105, 49, 69, 48, 52, 7,117,110,105, 49, 69, 48, 53, 7,117,110,105, 49, 69, 48, 54,
+ 7,117,110,105, 49, 69, 48, 55, 7,117,110,105, 49, 69, 48, 56, 7,117,110,105, 49, 69, 48, 57, 7,117,110,105, 49, 69, 48, 65,
+ 7,117,110,105, 49, 69, 48, 66, 7,117,110,105, 49, 69, 48, 67, 7,117,110,105, 49, 69, 48, 68, 7,117,110,105, 49, 69, 48, 69,
+ 7,117,110,105, 49, 69, 48, 70, 7,117,110,105, 49, 69, 49, 48, 7,117,110,105, 49, 69, 49, 49, 7,117,110,105, 49, 69, 49, 50,
+ 7,117,110,105, 49, 69, 49, 51, 7,117,110,105, 49, 69, 49, 56, 7,117,110,105, 49, 69, 49, 57, 7,117,110,105, 49, 69, 49, 65,
+ 7,117,110,105, 49, 69, 49, 66, 7,117,110,105, 49, 69, 49, 67, 7,117,110,105, 49, 69, 49, 68, 7,117,110,105, 49, 69, 49, 69,
+ 7,117,110,105, 49, 69, 49, 70, 7,117,110,105, 49, 69, 50, 48, 7,117,110,105, 49, 69, 50, 49, 7,117,110,105, 49, 69, 50, 50,
+ 7,117,110,105, 49, 69, 50, 51, 7,117,110,105, 49, 69, 50, 52, 7,117,110,105, 49, 69, 50, 53, 7,117,110,105, 49, 69, 50, 56,
+ 7,117,110,105, 49, 69, 50, 57, 7,117,110,105, 49, 69, 50, 65, 7,117,110,105, 49, 69, 50, 66, 7,117,110,105, 49, 69, 50, 67,
+ 7,117,110,105, 49, 69, 50, 68, 7,117,110,105, 49, 69, 51, 48, 7,117,110,105, 49, 69, 51, 49, 7,117,110,105, 49, 69, 51, 50,
+ 7,117,110,105, 49, 69, 51, 51, 7,117,110,105, 49, 69, 51, 52, 7,117,110,105, 49, 69, 51, 53, 7,117,110,105, 49, 69, 51, 54,
+ 7,117,110,105, 49, 69, 51, 55, 7,117,110,105, 49, 69, 51, 56, 7,117,110,105, 49, 69, 51, 57, 7,117,110,105, 49, 69, 51, 65,
+ 7,117,110,105, 49, 69, 51, 66, 7,117,110,105, 49, 69, 51, 67, 7,117,110,105, 49, 69, 51, 68, 7,117,110,105, 49, 69, 51, 69,
+ 7,117,110,105, 49, 69, 51, 70, 7,117,110,105, 49, 69, 52, 48, 7,117,110,105, 49, 69, 52, 49, 7,117,110,105, 49, 69, 52, 50,
+ 7,117,110,105, 49, 69, 52, 51, 7,117,110,105, 49, 69, 52, 52, 7,117,110,105, 49, 69, 52, 53, 7,117,110,105, 49, 69, 52, 54,
+ 7,117,110,105, 49, 69, 52, 55, 7,117,110,105, 49, 69, 52, 56, 7,117,110,105, 49, 69, 52, 57, 7,117,110,105, 49, 69, 52, 65,
+ 7,117,110,105, 49, 69, 52, 66, 7,117,110,105, 49, 69, 53, 54, 7,117,110,105, 49, 69, 53, 55, 7,117,110,105, 49, 69, 53, 56,
+ 7,117,110,105, 49, 69, 53, 57, 7,117,110,105, 49, 69, 53, 65, 7,117,110,105, 49, 69, 53, 66, 7,117,110,105, 49, 69, 53, 67,
+ 7,117,110,105, 49, 69, 53, 68, 7,117,110,105, 49, 69, 53, 69, 7,117,110,105, 49, 69, 53, 70, 7,117,110,105, 49, 69, 54, 48,
+ 7,117,110,105, 49, 69, 54, 49, 7,117,110,105, 49, 69, 54, 50, 7,117,110,105, 49, 69, 54, 51, 7,117,110,105, 49, 69, 54, 56,
+ 7,117,110,105, 49, 69, 54, 57, 7,117,110,105, 49, 69, 54, 65, 7,117,110,105, 49, 69, 54, 66, 7,117,110,105, 49, 69, 54, 67,
+ 7,117,110,105, 49, 69, 54, 68, 7,117,110,105, 49, 69, 54, 69, 7,117,110,105, 49, 69, 54, 70, 7,117,110,105, 49, 69, 55, 48,
+ 7,117,110,105, 49, 69, 55, 49, 7,117,110,105, 49, 69, 55, 50, 7,117,110,105, 49, 69, 55, 51, 7,117,110,105, 49, 69, 55, 52,
+ 7,117,110,105, 49, 69, 55, 53, 7,117,110,105, 49, 69, 55, 54, 7,117,110,105, 49, 69, 55, 55, 7,117,110,105, 49, 69, 55, 69,
+ 7,117,110,105, 49, 69, 55, 70, 6, 87,103,114, 97,118,101, 6,119,103,114, 97,118,101, 6, 87, 97, 99,117,116,101, 6,119, 97,
+ 99,117,116,101, 9, 87,100,105,101,114,101,115,105,115, 9,119,100,105,101,114,101,115,105,115, 7,117,110,105, 49, 69, 56, 54,
+ 7,117,110,105, 49, 69, 56, 55, 7,117,110,105, 49, 69, 56, 56, 7,117,110,105, 49, 69, 56, 57, 7,117,110,105, 49, 69, 56, 65,
+ 7,117,110,105, 49, 69, 56, 66, 7,117,110,105, 49, 69, 56, 69, 7,117,110,105, 49, 69, 56, 70, 7,117,110,105, 49, 69, 57, 50,
+ 7,117,110,105, 49, 69, 57, 51, 7,117,110,105, 49, 69, 57, 52, 7,117,110,105, 49, 69, 57, 53, 7,117,110,105, 49, 69, 57, 54,
+ 7,117,110,105, 49, 69, 57, 66, 7,117,110,105, 49, 69, 65, 48, 7,117,110,105, 49, 69, 65, 49, 7,117,110,105, 49, 69, 66, 48,
+ 7,117,110,105, 49, 69, 66, 49, 7,117,110,105, 49, 69, 66, 56, 7,117,110,105, 49, 69, 66, 57, 7,117,110,105, 49, 69, 66, 67,
+ 7,117,110,105, 49, 69, 66, 68, 7,117,110,105, 49, 69, 67, 65, 7,117,110,105, 49, 69, 67, 66, 7,117,110,105, 49, 69, 67, 67,
+ 7,117,110,105, 49, 69, 67, 68, 7,117,110,105, 49, 69, 69, 52, 7,117,110,105, 49, 69, 69, 53, 6, 89,103,114, 97,118,101, 6,
+121,103,114, 97,118,101, 7,117,110,105, 49, 69, 70, 52, 7,117,110,105, 49, 69, 70, 53, 7,117,110,105, 49, 69, 70, 56, 7,117,
+110,105, 49, 69, 70, 57, 7,117,110,105, 49, 70, 48, 48, 7,117,110,105, 49, 70, 48, 49, 7,117,110,105, 49, 70, 48, 50, 7,117,
+110,105, 49, 70, 48, 51, 7,117,110,105, 49, 70, 48, 52, 7,117,110,105, 49, 70, 48, 53, 7,117,110,105, 49, 70, 48, 54, 7,117,
+110,105, 49, 70, 48, 55, 7,117,110,105, 49, 70, 48, 56, 7,117,110,105, 49, 70, 48, 57, 7,117,110,105, 49, 70, 48, 65, 7,117,
+110,105, 49, 70, 48, 66, 7,117,110,105, 49, 70, 48, 67, 7,117,110,105, 49, 70, 48, 68, 7,117,110,105, 49, 70, 48, 69, 7,117,
+110,105, 49, 70, 48, 70, 7,117,110,105, 49, 70, 49, 48, 7,117,110,105, 49, 70, 49, 49, 7,117,110,105, 49, 70, 49, 50, 7,117,
+110,105, 49, 70, 49, 51, 7,117,110,105, 49, 70, 49, 52, 7,117,110,105, 49, 70, 49, 53, 7,117,110,105, 49, 70, 49, 56, 7,117,
+110,105, 49, 70, 49, 57, 7,117,110,105, 49, 70, 49, 65, 7,117,110,105, 49, 70, 49, 66, 7,117,110,105, 49, 70, 49, 67, 7,117,
+110,105, 49, 70, 49, 68, 7,117,110,105, 49, 70, 50, 48, 7,117,110,105, 49, 70, 50, 49, 7,117,110,105, 49, 70, 50, 50, 7,117,
+110,105, 49, 70, 50, 51, 7,117,110,105, 49, 70, 50, 52, 7,117,110,105, 49, 70, 50, 53, 7,117,110,105, 49, 70, 50, 54, 7,117,
+110,105, 49, 70, 50, 55, 7,117,110,105, 49, 70, 50, 56, 7,117,110,105, 49, 70, 50, 57, 7,117,110,105, 49, 70, 50, 65, 7,117,
+110,105, 49, 70, 50, 66, 7,117,110,105, 49, 70, 50, 67, 7,117,110,105, 49, 70, 50, 68, 7,117,110,105, 49, 70, 50, 69, 7,117,
+110,105, 49, 70, 50, 70, 7,117,110,105, 49, 70, 51, 48, 7,117,110,105, 49, 70, 51, 49, 7,117,110,105, 49, 70, 51, 50, 7,117,
+110,105, 49, 70, 51, 51, 7,117,110,105, 49, 70, 51, 52, 7,117,110,105, 49, 70, 51, 53, 7,117,110,105, 49, 70, 51, 54, 7,117,
+110,105, 49, 70, 51, 55, 7,117,110,105, 49, 70, 51, 56, 7,117,110,105, 49, 70, 51, 57, 7,117,110,105, 49, 70, 51, 65, 7,117,
+110,105, 49, 70, 51, 66, 7,117,110,105, 49, 70, 51, 67, 7,117,110,105, 49, 70, 51, 68, 7,117,110,105, 49, 70, 51, 69, 7,117,
+110,105, 49, 70, 51, 70, 7,117,110,105, 49, 70, 52, 48, 7,117,110,105, 49, 70, 52, 49, 7,117,110,105, 49, 70, 52, 50, 7,117,
+110,105, 49, 70, 52, 51, 7,117,110,105, 49, 70, 52, 52, 7,117,110,105, 49, 70, 52, 53, 7,117,110,105, 49, 70, 52, 56, 7,117,
+110,105, 49, 70, 52, 57, 7,117,110,105, 49, 70, 52, 65, 7,117,110,105, 49, 70, 52, 66, 7,117,110,105, 49, 70, 52, 67, 7,117,
+110,105, 49, 70, 52, 68, 7,117,110,105, 49, 70, 53, 48, 7,117,110,105, 49, 70, 53, 49, 7,117,110,105, 49, 70, 53, 50, 7,117,
+110,105, 49, 70, 53, 51, 7,117,110,105, 49, 70, 53, 52, 7,117,110,105, 49, 70, 53, 53, 7,117,110,105, 49, 70, 53, 54, 7,117,
+110,105, 49, 70, 53, 55, 7,117,110,105, 49, 70, 53, 57, 7,117,110,105, 49, 70, 53, 66, 7,117,110,105, 49, 70, 53, 68, 7,117,
+110,105, 49, 70, 53, 70, 7,117,110,105, 49, 70, 54, 48, 7,117,110,105, 49, 70, 54, 49, 7,117,110,105, 49, 70, 54, 50, 7,117,
+110,105, 49, 70, 54, 51, 7,117,110,105, 49, 70, 54, 52, 7,117,110,105, 49, 70, 54, 53, 7,117,110,105, 49, 70, 54, 54, 7,117,
+110,105, 49, 70, 54, 55, 7,117,110,105, 49, 70, 54, 56, 7,117,110,105, 49, 70, 54, 57, 7,117,110,105, 49, 70, 54, 65, 7,117,
+110,105, 49, 70, 54, 66, 7,117,110,105, 49, 70, 54, 67, 7,117,110,105, 49, 70, 54, 68, 7,117,110,105, 49, 70, 54, 69, 7,117,
+110,105, 49, 70, 54, 70, 7,117,110,105, 49, 70, 55, 48, 7,117,110,105, 49, 70, 55, 49, 7,117,110,105, 49, 70, 55, 50, 7,117,
+110,105, 49, 70, 55, 51, 7,117,110,105, 49, 70, 55, 52, 7,117,110,105, 49, 70, 55, 53, 7,117,110,105, 49, 70, 55, 54, 7,117,
+110,105, 49, 70, 55, 55, 7,117,110,105, 49, 70, 55, 56, 7,117,110,105, 49, 70, 55, 57, 7,117,110,105, 49, 70, 55, 65, 7,117,
+110,105, 49, 70, 55, 66, 7,117,110,105, 49, 70, 55, 67, 7,117,110,105, 49, 70, 55, 68, 7,117,110,105, 49, 70, 56, 48, 7,117,
+110,105, 49, 70, 56, 49, 7,117,110,105, 49, 70, 56, 50, 7,117,110,105, 49, 70, 56, 51, 7,117,110,105, 49, 70, 56, 52, 7,117,
+110,105, 49, 70, 56, 53, 7,117,110,105, 49, 70, 56, 54, 7,117,110,105, 49, 70, 56, 55, 7,117,110,105, 49, 70, 56, 56, 7,117,
+110,105, 49, 70, 56, 57, 7,117,110,105, 49, 70, 56, 65, 7,117,110,105, 49, 70, 56, 66, 7,117,110,105, 49, 70, 56, 67, 7,117,
+110,105, 49, 70, 56, 68, 7,117,110,105, 49, 70, 56, 69, 7,117,110,105, 49, 70, 56, 70, 7,117,110,105, 49, 70, 57, 48, 7,117,
+110,105, 49, 70, 57, 49, 7,117,110,105, 49, 70, 57, 50, 7,117,110,105, 49, 70, 57, 51, 7,117,110,105, 49, 70, 57, 52, 7,117,
+110,105, 49, 70, 57, 53, 7,117,110,105, 49, 70, 57, 54, 7,117,110,105, 49, 70, 57, 55, 7,117,110,105, 49, 70, 57, 56, 7,117,
+110,105, 49, 70, 57, 57, 7,117,110,105, 49, 70, 57, 65, 7,117,110,105, 49, 70, 57, 66, 7,117,110,105, 49, 70, 57, 67, 7,117,
+110,105, 49, 70, 57, 68, 7,117,110,105, 49, 70, 57, 69, 7,117,110,105, 49, 70, 57, 70, 7,117,110,105, 49, 70, 65, 48, 7,117,
+110,105, 49, 70, 65, 49, 7,117,110,105, 49, 70, 65, 50, 7,117,110,105, 49, 70, 65, 51, 7,117,110,105, 49, 70, 65, 52, 7,117,
+110,105, 49, 70, 65, 53, 7,117,110,105, 49, 70, 65, 54, 7,117,110,105, 49, 70, 65, 55, 7,117,110,105, 49, 70, 65, 56, 7,117,
+110,105, 49, 70, 65, 57, 7,117,110,105, 49, 70, 65, 65, 7,117,110,105, 49, 70, 65, 66, 7,117,110,105, 49, 70, 65, 67, 7,117,
+110,105, 49, 70, 65, 68, 7,117,110,105, 49, 70, 65, 69, 7,117,110,105, 49, 70, 65, 70, 7,117,110,105, 49, 70, 66, 48, 7,117,
+110,105, 49, 70, 66, 49, 7,117,110,105, 49, 70, 66, 50, 7,117,110,105, 49, 70, 66, 51, 7,117,110,105, 49, 70, 66, 52, 7,117,
+110,105, 49, 70, 66, 54, 7,117,110,105, 49, 70, 66, 55, 7,117,110,105, 49, 70, 66, 56, 7,117,110,105, 49, 70, 66, 57, 7,117,
+110,105, 49, 70, 66, 65, 7,117,110,105, 49, 70, 66, 66, 7,117,110,105, 49, 70, 66, 67, 7,117,110,105, 49, 70, 66, 68, 7,117,
+110,105, 49, 70, 66, 69, 7,117,110,105, 49, 70, 66, 70, 7,117,110,105, 49, 70, 67, 48, 7,117,110,105, 49, 70, 67, 49, 7,117,
+110,105, 49, 70, 67, 50, 7,117,110,105, 49, 70, 67, 51, 7,117,110,105, 49, 70, 67, 52, 7,117,110,105, 49, 70, 67, 54, 7,117,
+110,105, 49, 70, 67, 55, 7,117,110,105, 49, 70, 67, 56, 7,117,110,105, 49, 70, 67, 57, 7,117,110,105, 49, 70, 67, 65, 7,117,
+110,105, 49, 70, 67, 66, 7,117,110,105, 49, 70, 67, 67, 7,117,110,105, 49, 70, 67, 68, 7,117,110,105, 49, 70, 67, 69, 7,117,
+110,105, 49, 70, 67, 70, 7,117,110,105, 49, 70, 68, 48, 7,117,110,105, 49, 70, 68, 49, 7,117,110,105, 49, 70, 68, 50, 7,117,
+110,105, 49, 70, 68, 51, 7,117,110,105, 49, 70, 68, 54, 7,117,110,105, 49, 70, 68, 55, 7,117,110,105, 49, 70, 68, 56, 7,117,
+110,105, 49, 70, 68, 57, 7,117,110,105, 49, 70, 68, 65, 7,117,110,105, 49, 70, 68, 66, 7,117,110,105, 49, 70, 68, 68, 7,117,
+110,105, 49, 70, 68, 69, 7,117,110,105, 49, 70, 68, 70, 7,117,110,105, 49, 70, 69, 48, 7,117,110,105, 49, 70, 69, 49, 7,117,
+110,105, 49, 70, 69, 50, 7,117,110,105, 49, 70, 69, 51, 7,117,110,105, 49, 70, 69, 52, 7,117,110,105, 49, 70, 69, 53, 7,117,
+110,105, 49, 70, 69, 54, 7,117,110,105, 49, 70, 69, 55, 7,117,110,105, 49, 70, 69, 56, 7,117,110,105, 49, 70, 69, 57, 7,117,
+110,105, 49, 70, 69, 65, 7,117,110,105, 49, 70, 69, 66, 7,117,110,105, 49, 70, 69, 67, 7,117,110,105, 49, 70, 69, 68, 7,117,
+110,105, 49, 70, 69, 69, 7,117,110,105, 49, 70, 69, 70, 7,117,110,105, 49, 70, 70, 50, 7,117,110,105, 49, 70, 70, 51, 7,117,
+110,105, 49, 70, 70, 52, 7,117,110,105, 49, 70, 70, 54, 7,117,110,105, 49, 70, 70, 55, 7,117,110,105, 49, 70, 70, 56, 7,117,
+110,105, 49, 70, 70, 57, 7,117,110,105, 49, 70, 70, 65, 7,117,110,105, 49, 70, 70, 66, 7,117,110,105, 49, 70, 70, 67, 7,117,
+110,105, 49, 70, 70, 68, 7,117,110,105, 49, 70, 70, 69, 7,117,110,105, 50, 48, 48, 48, 7,117,110,105, 50, 48, 48, 49, 7,117,
+110,105, 50, 48, 48, 50, 7,117,110,105, 50, 48, 48, 51, 7,117,110,105, 50, 48, 48, 52, 7,117,110,105, 50, 48, 48, 53, 7,117,
+110,105, 50, 48, 48, 54, 7,117,110,105, 50, 48, 48, 55, 7,117,110,105, 50, 48, 48, 56, 7,117,110,105, 50, 48, 48, 57, 7,117,
+110,105, 50, 48, 48, 65, 7,117,110,105, 50, 48, 49, 48, 7,117,110,105, 50, 48, 49, 49, 10,102,105,103,117,114,101,100, 97,115,
+104, 7,117,110,105, 50, 48, 49, 53, 13,117,110,100,101,114,115, 99,111,114,101,100, 98,108, 13,113,117,111,116,101,114,101,118,
+101,114,115,101,100, 7,117,110,105, 50, 48, 49, 70, 7,117,110,105, 50, 48, 50, 51, 7,117,110,105, 50, 48, 50, 70, 7,117,110,
+105, 50, 48, 51, 49, 9,101,120, 99,108, 97,109,100, 98,108, 7,117,110,105, 50, 48, 51, 68, 7,117,110,105, 50, 48, 51, 69, 7,
+117,110,105, 50, 48, 52, 53, 7,117,110,105, 50, 48, 52, 54, 7,117,110,105, 50, 48, 52, 55, 7,117,110,105, 50, 48, 52, 56, 7,
+117,110,105, 50, 48, 52, 57, 7,117,110,105, 50, 48, 53, 70, 7,117,110,105, 50, 48, 55, 48, 7,117,110,105, 50, 48, 55, 49, 7,
+117,110,105, 50, 48, 55, 52, 7,117,110,105, 50, 48, 55, 53, 7,117,110,105, 50, 48, 55, 54, 7,117,110,105, 50, 48, 55, 55, 7,
+117,110,105, 50, 48, 55, 56, 7,117,110,105, 50, 48, 55, 57, 7,117,110,105, 50, 48, 55, 65, 7,117,110,105, 50, 48, 55, 66, 7,
+117,110,105, 50, 48, 55, 67, 7,117,110,105, 50, 48, 55, 68, 7,117,110,105, 50, 48, 55, 69, 7,117,110,105, 50, 48, 55, 70, 7,
+117,110,105, 50, 48, 56, 48, 7,117,110,105, 50, 48, 56, 49, 7,117,110,105, 50, 48, 56, 50, 7,117,110,105, 50, 48, 56, 51, 7,
+117,110,105, 50, 48, 56, 52, 7,117,110,105, 50, 48, 56, 53, 7,117,110,105, 50, 48, 56, 54, 7,117,110,105, 50, 48, 56, 55, 7,
+117,110,105, 50, 48, 56, 56, 7,117,110,105, 50, 48, 56, 57, 7,117,110,105, 50, 48, 56, 65, 7,117,110,105, 50, 48, 56, 66, 7,
+117,110,105, 50, 48, 56, 67, 7,117,110,105, 50, 48, 56, 68, 7,117,110,105, 50, 48, 56, 69, 7,117,110,105, 50, 48, 57, 48, 7,
+117,110,105, 50, 48, 57, 49, 7,117,110,105, 50, 48, 57, 50, 7,117,110,105, 50, 48, 57, 51, 7,117,110,105, 50, 48, 57, 52, 7,
+117,110,105, 50, 48, 65, 54, 4, 69,117,114,111, 7,117,110,105, 50, 48, 66, 49, 7,117,110,105, 50, 48, 66, 52, 7,117,110,105,
+ 50, 48, 66, 53, 7,117,110,105, 50, 49, 48, 50, 7,117,110,105, 50, 49, 48, 69, 7,117,110,105, 50, 49, 49, 54, 7,117,110,105,
+ 50, 49, 50, 54, 7,117,110,105, 50, 49, 50, 65, 7,117,110,105, 50, 49, 50, 66, 8,111,110,101,116,104,105,114,100, 9,116,119,
+111,116,104,105,114,100,115, 7,117,110,105, 50, 49, 53, 53, 7,117,110,105, 50, 49, 53, 54, 7,117,110,105, 50, 49, 53, 55, 7,
+117,110,105, 50, 49, 53, 56, 7,117,110,105, 50, 49, 53, 57, 7,117,110,105, 50, 49, 53, 65, 9,111,110,101,101,105,103,104,116,
+104, 12,116,104,114,101,101,101,105,103,104,116,104,115, 11,102,105,118,101,101,105,103,104,116,104,115, 12,115,101,118,101,110,
+101,105,103,104,116,104,115, 7,117,110,105, 50, 49, 53, 70, 9, 97,114,114,111,119,108,101,102,116, 7, 97,114,114,111,119,117,
+112, 10, 97,114,114,111,119,114,105,103,104,116, 9, 97,114,114,111,119,100,111,119,110, 9, 97,114,114,111,119, 98,111,116,104,
+ 9, 97,114,114,111,119,117,112,100,110, 7,117,110,105, 50, 49, 57, 54, 7,117,110,105, 50, 49, 57, 55, 7,117,110,105, 50, 49,
+ 57, 56, 7,117,110,105, 50, 49, 57, 57, 7,117,110,105, 50, 49, 57, 65, 7,117,110,105, 50, 49, 57, 66, 7,117,110,105, 50, 49,
+ 57, 67, 7,117,110,105, 50, 49, 57, 68, 7,117,110,105, 50, 49, 57, 69, 7,117,110,105, 50, 49, 57, 70, 7,117,110,105, 50, 49,
+ 65, 48, 7,117,110,105, 50, 49, 65, 49, 7,117,110,105, 50, 49, 65, 50, 7,117,110,105, 50, 49, 65, 51, 7,117,110,105, 50, 49,
+ 65, 52, 7,117,110,105, 50, 49, 65, 53, 7,117,110,105, 50, 49, 65, 54, 7,117,110,105, 50, 49, 65, 55, 12, 97,114,114,111,119,
+117,112,100,110, 98,115,101, 7,117,110,105, 50, 49, 65, 57, 7,117,110,105, 50, 49, 65, 65, 7,117,110,105, 50, 49, 65, 66, 7,
+117,110,105, 50, 49, 65, 67, 7,117,110,105, 50, 49, 65, 68, 7,117,110,105, 50, 49, 65, 69, 7,117,110,105, 50, 49, 65, 70, 7,
+117,110,105, 50, 49, 66, 48, 7,117,110,105, 50, 49, 66, 49, 7,117,110,105, 50, 49, 66, 50, 7,117,110,105, 50, 49, 66, 51, 7,
+117,110,105, 50, 49, 66, 52, 14, 99, 97,114,114,105, 97,103,101,114,101,116,117,114,110, 7,117,110,105, 50, 49, 66, 54, 7,117,
+110,105, 50, 49, 66, 55, 7,117,110,105, 50, 49, 66, 56, 7,117,110,105, 50, 49, 66, 57, 7,117,110,105, 50, 49, 66, 65, 7,117,
+110,105, 50, 49, 66, 66, 7,117,110,105, 50, 49, 66, 67, 7,117,110,105, 50, 49, 66, 68, 7,117,110,105, 50, 49, 66, 69, 7,117,
+110,105, 50, 49, 66, 70, 7,117,110,105, 50, 49, 67, 48, 7,117,110,105, 50, 49, 67, 49, 7,117,110,105, 50, 49, 67, 50, 7,117,
+110,105, 50, 49, 67, 51, 7,117,110,105, 50, 49, 67, 52, 7,117,110,105, 50, 49, 67, 53, 7,117,110,105, 50, 49, 67, 54, 7,117,
+110,105, 50, 49, 67, 55, 7,117,110,105, 50, 49, 67, 56, 7,117,110,105, 50, 49, 67, 57, 7,117,110,105, 50, 49, 67, 65, 7,117,
+110,105, 50, 49, 67, 66, 7,117,110,105, 50, 49, 67, 67, 7,117,110,105, 50, 49, 67, 68, 7,117,110,105, 50, 49, 67, 69, 7,117,
+110,105, 50, 49, 67, 70, 12, 97,114,114,111,119,100, 98,108,108,101,102,116, 10, 97,114,114,111,119,100, 98,108,117,112, 13, 97,
+114,114,111,119,100, 98,108,114,105,103,104,116, 12, 97,114,114,111,119,100, 98,108,100,111,119,110, 12, 97,114,114,111,119,100,
+ 98,108, 98,111,116,104, 7,117,110,105, 50, 49, 68, 53, 7,117,110,105, 50, 49, 68, 54, 7,117,110,105, 50, 49, 68, 55, 7,117,
+110,105, 50, 49, 68, 56, 7,117,110,105, 50, 49, 68, 57, 7,117,110,105, 50, 49, 68, 65, 7,117,110,105, 50, 49, 68, 66, 7,117,
+110,105, 50, 49, 68, 67, 7,117,110,105, 50, 49, 68, 68, 7,117,110,105, 50, 49, 68, 69, 7,117,110,105, 50, 49, 68, 70, 7,117,
+110,105, 50, 49, 69, 48, 7,117,110,105, 50, 49, 69, 49, 7,117,110,105, 50, 49, 69, 50, 7,117,110,105, 50, 49, 69, 51, 7,117,
+110,105, 50, 49, 69, 52, 7,117,110,105, 50, 49, 69, 53, 7,117,110,105, 50, 49, 69, 54, 7,117,110,105, 50, 49, 69, 55, 7,117,
+110,105, 50, 49, 69, 56, 7,117,110,105, 50, 49, 69, 57, 7,117,110,105, 50, 49, 69, 65, 7,117,110,105, 50, 49, 69, 66, 7,117,
+110,105, 50, 49, 69, 67, 7,117,110,105, 50, 49, 69, 68, 7,117,110,105, 50, 49, 69, 69, 7,117,110,105, 50, 49, 69, 70, 7,117,
+110,105, 50, 49, 70, 48, 7,117,110,105, 50, 49, 70, 49, 7,117,110,105, 50, 49, 70, 50, 7,117,110,105, 50, 49, 70, 51, 7,117,
+110,105, 50, 49, 70, 52, 7,117,110,105, 50, 49, 70, 53, 7,117,110,105, 50, 49, 70, 54, 7,117,110,105, 50, 49, 70, 55, 7,117,
+110,105, 50, 49, 70, 56, 7,117,110,105, 50, 49, 70, 57, 7,117,110,105, 50, 49, 70, 65, 7,117,110,105, 50, 49, 70, 66, 7,117,
+110,105, 50, 49, 70, 67, 7,117,110,105, 50, 49, 70, 68, 7,117,110,105, 50, 49, 70, 69, 7,117,110,105, 50, 49, 70, 70, 8,101,
+109,112,116,121,115,101,116, 8,103,114, 97,100,105,101,110,116, 7,101,108,101,109,101,110,116, 10,110,111,116,101,108,101,109,
+101,110,116, 7,117,110,105, 50, 50, 48, 65, 8,115,117, 99,104,116,104, 97,116, 7,117,110,105, 50, 50, 48, 67, 7,117,110,105,
+ 50, 50, 48, 68, 7,117,110,105, 50, 50, 49, 51, 7,117,110,105, 50, 50, 49, 53, 12, 97,115,116,101,114,105,115,107,109, 97,116,
+104, 7,117,110,105, 50, 50, 49, 56, 7,117,110,105, 50, 50, 49, 57, 12,112,114,111,112,111,114,116,105,111,110, 97,108, 10,111,
+114,116,104,111,103,111,110, 97,108, 5, 97,110,103,108,101, 10,108,111,103,105, 99, 97,108, 97,110,100, 9,108,111,103,105, 99,
+ 97,108,111,114, 12,105,110,116,101,114,115,101, 99,116,105,111,110, 5,117,110,105,111,110, 7,117,110,105, 50, 50, 50, 67, 7,
+117,110,105, 50, 50, 50, 68, 7,117,110,105, 50, 50, 51, 56, 7,117,110,105, 50, 50, 51, 57, 7,117,110,105, 50, 50, 51, 65, 7,
+117,110,105, 50, 50, 51, 66, 7,115,105,109,105,108, 97,114, 7,117,110,105, 50, 50, 51, 68, 7,117,110,105, 50, 50, 52, 49, 7,
+117,110,105, 50, 50, 52, 50, 7,117,110,105, 50, 50, 52, 51, 7,117,110,105, 50, 50, 52, 52, 9, 99,111,110,103,114,117,101,110,
+116, 7,117,110,105, 50, 50, 52, 54, 7,117,110,105, 50, 50, 52, 55, 7,117,110,105, 50, 50, 52, 57, 7,117,110,105, 50, 50, 52,
+ 65, 7,117,110,105, 50, 50, 52, 66, 7,117,110,105, 50, 50, 52, 67, 7,117,110,105, 50, 50, 52, 68, 7,117,110,105, 50, 50, 52,
+ 69, 7,117,110,105, 50, 50, 52, 70, 7,117,110,105, 50, 50, 53, 48, 7,117,110,105, 50, 50, 53, 49, 7,117,110,105, 50, 50, 53,
+ 50, 7,117,110,105, 50, 50, 53, 51, 7,117,110,105, 50, 50, 53, 52, 7,117,110,105, 50, 50, 53, 53, 7,117,110,105, 50, 50, 53,
+ 54, 7,117,110,105, 50, 50, 53, 55, 7,117,110,105, 50, 50, 53, 56, 7,117,110,105, 50, 50, 53, 57, 7,117,110,105, 50, 50, 53,
+ 65, 7,117,110,105, 50, 50, 53, 66, 7,117,110,105, 50, 50, 53, 67, 7,117,110,105, 50, 50, 53, 68, 7,117,110,105, 50, 50, 53,
+ 69, 7,117,110,105, 50, 50, 53, 70, 11,101,113,117,105,118, 97,108,101,110, 99,101, 7,117,110,105, 50, 50, 54, 50, 7,117,110,
+105, 50, 50, 54, 51, 7,117,110,105, 50, 50, 54, 54, 7,117,110,105, 50, 50, 54, 55, 7,117,110,105, 50, 50, 54, 56, 7,117,110,
+105, 50, 50, 54, 57, 7,117,110,105, 50, 50, 54, 68, 7,117,110,105, 50, 50, 54, 69, 7,117,110,105, 50, 50, 54, 70, 7,117,110,
+105, 50, 50, 55, 48, 7,117,110,105, 50, 50, 55, 49, 7,117,110,105, 50, 50, 55, 50, 7,117,110,105, 50, 50, 55, 51, 7,117,110,
+105, 50, 50, 55, 52, 7,117,110,105, 50, 50, 55, 53, 7,117,110,105, 50, 50, 55, 54, 7,117,110,105, 50, 50, 55, 55, 7,117,110,
+105, 50, 50, 55, 56, 7,117,110,105, 50, 50, 55, 57, 7,117,110,105, 50, 50, 55, 65, 7,117,110,105, 50, 50, 55, 66, 7,117,110,
+105, 50, 50, 55, 67, 7,117,110,105, 50, 50, 55, 68, 7,117,110,105, 50, 50, 55, 69, 7,117,110,105, 50, 50, 55, 70, 7,117,110,
+105, 50, 50, 56, 48, 7,117,110,105, 50, 50, 56, 49, 12,112,114,111,112,101,114,115,117, 98,115,101,116, 14,112,114,111,112,101,
+114,115,117,112,101,114,115,101,116, 9,110,111,116,115,117, 98,115,101,116, 7,117,110,105, 50, 50, 56, 53, 12,114,101,102,108,
+101,120,115,117, 98,115,101,116, 14,114,101,102,108,101,120,115,117,112,101,114,115,101,116, 7,117,110,105, 50, 50, 56, 56, 7,
+117,110,105, 50, 50, 56, 57, 7,117,110,105, 50, 50, 56, 65, 7,117,110,105, 50, 50, 56, 66, 7,117,110,105, 50, 50, 56, 70, 7,
+117,110,105, 50, 50, 57, 48, 7,117,110,105, 50, 50, 57, 49, 7,117,110,105, 50, 50, 57, 50, 10, 99,105,114, 99,108,101,112,108,
+117,115, 7,117,110,105, 50, 50, 57, 54, 14, 99,105,114, 99,108,101,109,117,108,116,105,112,108,121, 7,117,110,105, 50, 50, 57,
+ 56, 7,117,110,105, 50, 50, 57, 57, 7,117,110,105, 50, 50, 57, 65, 7,117,110,105, 50, 50, 57, 66, 7,117,110,105, 50, 50, 57,
+ 67, 7,117,110,105, 50, 50, 57, 68, 7,117,110,105, 50, 50, 57, 69, 7,117,110,105, 50, 50, 57, 70, 7,117,110,105, 50, 50, 65,
+ 48, 7,117,110,105, 50, 50, 65, 49, 7,100,111,116,109, 97,116,104, 7,117,110,105, 50, 50, 67, 54, 7,117,110,105, 50, 50, 67,
+ 68, 7,117,110,105, 50, 50, 68, 65, 7,117,110,105, 50, 50, 68, 66, 7,117,110,105, 50, 50, 68, 67, 7,117,110,105, 50, 50, 68,
+ 68, 7,117,110,105, 50, 50, 68, 69, 7,117,110,105, 50, 50, 68, 70, 7,117,110,105, 50, 50, 69, 48, 7,117,110,105, 50, 50, 69,
+ 49, 7,117,110,105, 50, 50, 69, 50, 7,117,110,105, 50, 50, 69, 51, 7,117,110,105, 50, 50, 69, 52, 7,117,110,105, 50, 50, 69,
+ 53, 7,117,110,105, 50, 50, 69, 54, 7,117,110,105, 50, 50, 69, 55, 7,117,110,105, 50, 50, 69, 56, 7,117,110,105, 50, 50, 69,
+ 57, 7,117,110,105, 50, 50, 69, 70, 7,117,110,105, 50, 51, 48, 48, 7,117,110,105, 50, 51, 48, 49, 5,104,111,117,115,101, 7,
+117,110,105, 50, 51, 48, 51, 7,117,110,105, 50, 51, 48, 52, 7,117,110,105, 50, 51, 48, 53, 7,117,110,105, 50, 51, 48, 54, 7,
+117,110,105, 50, 51, 48, 56, 7,117,110,105, 50, 51, 48, 57, 7,117,110,105, 50, 51, 48, 65, 7,117,110,105, 50, 51, 48, 66, 7,
+117,110,105, 50, 51, 48, 67, 7,117,110,105, 50, 51, 48, 68, 7,117,110,105, 50, 51, 48, 69, 7,117,110,105, 50, 51, 48, 70, 13,
+114,101,118,108,111,103,105, 99, 97,108,110,111,116, 7,117,110,105, 50, 51, 49, 49, 7,117,110,105, 50, 51, 49, 50, 7,117,110,
+105, 50, 51, 49, 51, 7,117,110,105, 50, 51, 49, 52, 7,117,110,105, 50, 51, 49, 53, 7,117,110,105, 50, 51, 49, 56, 7,117,110,
+105, 50, 51, 49, 57, 7,117,110,105, 50, 51, 49, 67, 7,117,110,105, 50, 51, 49, 68, 7,117,110,105, 50, 51, 49, 69, 7,117,110,
+105, 50, 51, 49, 70, 10,105,110,116,101,103,114, 97,108,116,112, 10,105,110,116,101,103,114, 97,108, 98,116, 7,117,110,105, 50,
+ 51, 50, 53, 7,117,110,105, 50, 51, 50, 54, 7,117,110,105, 50, 51, 50, 55, 7,117,110,105, 50, 51, 50, 56, 7,117,110,105, 50,
+ 51, 50, 66, 7,117,110,105, 50, 51, 51, 53, 7,117,110,105, 50, 51, 51, 55, 7,117,110,105, 50, 51, 51, 56, 7,117,110,105, 50,
+ 51, 51, 57, 7,117,110,105, 50, 51, 51, 65, 7,117,110,105, 50, 51, 51, 66, 7,117,110,105, 50, 51, 51, 67, 7,117,110,105, 50,
+ 51, 51, 68, 7,117,110,105, 50, 51, 51, 69, 7,117,110,105, 50, 51, 52, 49, 7,117,110,105, 50, 51, 52, 50, 7,117,110,105, 50,
+ 51, 52, 51, 7,117,110,105, 50, 51, 52, 52, 7,117,110,105, 50, 51, 52, 55, 7,117,110,105, 50, 51, 52, 56, 7,117,110,105, 50,
+ 51, 52, 57, 7,117,110,105, 50, 51, 52, 66, 7,117,110,105, 50, 51, 52, 67, 7,117,110,105, 50, 51, 52, 68, 7,117,110,105, 50,
+ 51, 53, 48, 7,117,110,105, 50, 51, 53, 50, 7,117,110,105, 50, 51, 53, 51, 7,117,110,105, 50, 51, 53, 52, 7,117,110,105, 50,
+ 51, 53, 55, 7,117,110,105, 50, 51, 53, 56, 7,117,110,105, 50, 51, 53, 57, 7,117,110,105, 50, 51, 53, 65, 7,117,110,105, 50,
+ 51, 53, 66, 7,117,110,105, 50, 51, 53, 67, 7,117,110,105, 50, 51, 53, 69, 7,117,110,105, 50, 51, 53, 70, 7,117,110,105, 50,
+ 51, 54, 48, 7,117,110,105, 50, 51, 54, 51, 7,117,110,105, 50, 51, 54, 52, 7,117,110,105, 50, 51, 54, 53, 7,117,110,105, 50,
+ 51, 54, 56, 7,117,110,105, 50, 51, 54, 57, 7,117,110,105, 50, 51, 54, 66, 7,117,110,105, 50, 51, 54, 67, 7,117,110,105, 50,
+ 51, 54, 68, 7,117,110,105, 50, 51, 54, 69, 7,117,110,105, 50, 51, 54, 70, 7,117,110,105, 50, 51, 55, 48, 7,117,110,105, 50,
+ 51, 55, 51, 7,117,110,105, 50, 51, 55, 52, 7,117,110,105, 50, 51, 55, 53, 7,117,110,105, 50, 51, 55, 54, 7,117,110,105, 50,
+ 51, 55, 55, 7,117,110,105, 50, 51, 55, 56, 7,117,110,105, 50, 51, 55, 57, 7,117,110,105, 50, 51, 55, 65, 7,117,110,105, 50,
+ 51, 55, 68, 7,117,110,105, 50, 51, 56, 48, 7,117,110,105, 50, 51, 56, 49, 7,117,110,105, 50, 51, 56, 50, 7,117,110,105, 50,
+ 51, 56, 51, 7,117,110,105, 50, 51, 56, 56, 7,117,110,105, 50, 51, 56, 57, 7,117,110,105, 50, 51, 56, 65, 7,117,110,105, 50,
+ 51, 56, 66, 7,117,110,105, 50, 51, 57, 53, 7,117,110,105, 50, 51, 57, 66, 7,117,110,105, 50, 51, 57, 67, 7,117,110,105, 50,
+ 51, 57, 68, 7,117,110,105, 50, 51, 57, 69, 7,117,110,105, 50, 51, 57, 70, 7,117,110,105, 50, 51, 65, 48, 7,117,110,105, 50,
+ 51, 65, 49, 7,117,110,105, 50, 51, 65, 50, 7,117,110,105, 50, 51, 65, 51, 7,117,110,105, 50, 51, 65, 52, 7,117,110,105, 50,
+ 51, 65, 53, 7,117,110,105, 50, 51, 65, 54, 7,117,110,105, 50, 51, 65, 55, 7,117,110,105, 50, 51, 65, 56, 7,117,110,105, 50,
+ 51, 65, 57, 7,117,110,105, 50, 51, 65, 65, 7,117,110,105, 50, 51, 65, 66, 7,117,110,105, 50, 51, 65, 67, 7,117,110,105, 50,
+ 51, 65, 68, 7,117,110,105, 50, 51, 65, 69, 7,117,110,105, 50, 51, 67, 69, 7,117,110,105, 50, 51, 67, 70, 7,117,110,105, 50,
+ 52, 50, 51, 8, 83, 70, 49, 48, 48, 48, 48, 48, 7,117,110,105, 50, 53, 48, 49, 8, 83, 70, 49, 49, 48, 48, 48, 48, 7,117,110,
+105, 50, 53, 48, 51, 7,117,110,105, 50, 53, 48, 52, 7,117,110,105, 50, 53, 48, 53, 7,117,110,105, 50, 53, 48, 54, 7,117,110,
+105, 50, 53, 48, 55, 7,117,110,105, 50, 53, 48, 56, 7,117,110,105, 50, 53, 48, 57, 7,117,110,105, 50, 53, 48, 65, 7,117,110,
+105, 50, 53, 48, 66, 8, 83, 70, 48, 49, 48, 48, 48, 48, 7,117,110,105, 50, 53, 48, 68, 7,117,110,105, 50, 53, 48, 69, 7,117,
+110,105, 50, 53, 48, 70, 8, 83, 70, 48, 51, 48, 48, 48, 48, 7,117,110,105, 50, 53, 49, 49, 7,117,110,105, 50, 53, 49, 50, 7,
+117,110,105, 50, 53, 49, 51, 8, 83, 70, 48, 50, 48, 48, 48, 48, 7,117,110,105, 50, 53, 49, 53, 7,117,110,105, 50, 53, 49, 54,
+ 7,117,110,105, 50, 53, 49, 55, 8, 83, 70, 48, 52, 48, 48, 48, 48, 7,117,110,105, 50, 53, 49, 57, 7,117,110,105, 50, 53, 49,
+ 65, 7,117,110,105, 50, 53, 49, 66, 8, 83, 70, 48, 56, 48, 48, 48, 48, 7,117,110,105, 50, 53, 49, 68, 7,117,110,105, 50, 53,
+ 49, 69, 7,117,110,105, 50, 53, 49, 70, 7,117,110,105, 50, 53, 50, 48, 7,117,110,105, 50, 53, 50, 49, 7,117,110,105, 50, 53,
+ 50, 50, 7,117,110,105, 50, 53, 50, 51, 8, 83, 70, 48, 57, 48, 48, 48, 48, 7,117,110,105, 50, 53, 50, 53, 7,117,110,105, 50,
+ 53, 50, 54, 7,117,110,105, 50, 53, 50, 55, 7,117,110,105, 50, 53, 50, 56, 7,117,110,105, 50, 53, 50, 57, 7,117,110,105, 50,
+ 53, 50, 65, 7,117,110,105, 50, 53, 50, 66, 8, 83, 70, 48, 54, 48, 48, 48, 48, 7,117,110,105, 50, 53, 50, 68, 7,117,110,105,
+ 50, 53, 50, 69, 7,117,110,105, 50, 53, 50, 70, 7,117,110,105, 50, 53, 51, 48, 7,117,110,105, 50, 53, 51, 49, 7,117,110,105,
+ 50, 53, 51, 50, 7,117,110,105, 50, 53, 51, 51, 8, 83, 70, 48, 55, 48, 48, 48, 48, 7,117,110,105, 50, 53, 51, 53, 7,117,110,
+105, 50, 53, 51, 54, 7,117,110,105, 50, 53, 51, 55, 7,117,110,105, 50, 53, 51, 56, 7,117,110,105, 50, 53, 51, 57, 7,117,110,
+105, 50, 53, 51, 65, 7,117,110,105, 50, 53, 51, 66, 8, 83, 70, 48, 53, 48, 48, 48, 48, 7,117,110,105, 50, 53, 51, 68, 7,117,
+110,105, 50, 53, 51, 69, 7,117,110,105, 50, 53, 51, 70, 7,117,110,105, 50, 53, 52, 48, 7,117,110,105, 50, 53, 52, 49, 7,117,
+110,105, 50, 53, 52, 50, 7,117,110,105, 50, 53, 52, 51, 7,117,110,105, 50, 53, 52, 52, 7,117,110,105, 50, 53, 52, 53, 7,117,
+110,105, 50, 53, 52, 54, 7,117,110,105, 50, 53, 52, 55, 7,117,110,105, 50, 53, 52, 56, 7,117,110,105, 50, 53, 52, 57, 7,117,
+110,105, 50, 53, 52, 65, 7,117,110,105, 50, 53, 52, 66, 7,117,110,105, 50, 53, 52, 67, 7,117,110,105, 50, 53, 52, 68, 7,117,
+110,105, 50, 53, 52, 69, 7,117,110,105, 50, 53, 52, 70, 8, 83, 70, 52, 51, 48, 48, 48, 48, 8, 83, 70, 50, 52, 48, 48, 48, 48,
+ 8, 83, 70, 53, 49, 48, 48, 48, 48, 8, 83, 70, 53, 50, 48, 48, 48, 48, 8, 83, 70, 51, 57, 48, 48, 48, 48, 8, 83, 70, 50, 50,
+ 48, 48, 48, 48, 8, 83, 70, 50, 49, 48, 48, 48, 48, 8, 83, 70, 50, 53, 48, 48, 48, 48, 8, 83, 70, 53, 48, 48, 48, 48, 48, 8,
+ 83, 70, 52, 57, 48, 48, 48, 48, 8, 83, 70, 51, 56, 48, 48, 48, 48, 8, 83, 70, 50, 56, 48, 48, 48, 48, 8, 83, 70, 50, 55, 48,
+ 48, 48, 48, 8, 83, 70, 50, 54, 48, 48, 48, 48, 8, 83, 70, 51, 54, 48, 48, 48, 48, 8, 83, 70, 51, 55, 48, 48, 48, 48, 8, 83,
+ 70, 52, 50, 48, 48, 48, 48, 8, 83, 70, 49, 57, 48, 48, 48, 48, 8, 83, 70, 50, 48, 48, 48, 48, 48, 8, 83, 70, 50, 51, 48, 48,
+ 48, 48, 8, 83, 70, 52, 55, 48, 48, 48, 48, 8, 83, 70, 52, 56, 48, 48, 48, 48, 8, 83, 70, 52, 49, 48, 48, 48, 48, 8, 83, 70,
+ 52, 53, 48, 48, 48, 48, 8, 83, 70, 52, 54, 48, 48, 48, 48, 8, 83, 70, 52, 48, 48, 48, 48, 48, 8, 83, 70, 53, 52, 48, 48, 48,
+ 48, 8, 83, 70, 53, 51, 48, 48, 48, 48, 8, 83, 70, 52, 52, 48, 48, 48, 48, 7,117,110,105, 50, 53, 54, 68, 7,117,110,105, 50,
+ 53, 54, 69, 7,117,110,105, 50, 53, 54, 70, 7,117,110,105, 50, 53, 55, 48, 7,117,110,105, 50, 53, 55, 49, 7,117,110,105, 50,
+ 53, 55, 50, 7,117,110,105, 50, 53, 55, 51, 7,117,110,105, 50, 53, 55, 52, 7,117,110,105, 50, 53, 55, 53, 7,117,110,105, 50,
+ 53, 55, 54, 7,117,110,105, 50, 53, 55, 55, 7,117,110,105, 50, 53, 55, 56, 7,117,110,105, 50, 53, 55, 57, 7,117,110,105, 50,
+ 53, 55, 65, 7,117,110,105, 50, 53, 55, 66, 7,117,110,105, 50, 53, 55, 67, 7,117,110,105, 50, 53, 55, 68, 7,117,110,105, 50,
+ 53, 55, 69, 7,117,110,105, 50, 53, 55, 70, 7,117,112, 98,108,111, 99,107, 7,117,110,105, 50, 53, 56, 49, 7,117,110,105, 50,
+ 53, 56, 50, 7,117,110,105, 50, 53, 56, 51, 7,100,110, 98,108,111, 99,107, 7,117,110,105, 50, 53, 56, 53, 7,117,110,105, 50,
+ 53, 56, 54, 7,117,110,105, 50, 53, 56, 55, 5, 98,108,111, 99,107, 7,117,110,105, 50, 53, 56, 57, 7,117,110,105, 50, 53, 56,
+ 65, 7,117,110,105, 50, 53, 56, 66, 7,108,102, 98,108,111, 99,107, 7,117,110,105, 50, 53, 56, 68, 7,117,110,105, 50, 53, 56,
+ 69, 7,117,110,105, 50, 53, 56, 70, 7,114,116, 98,108,111, 99,107, 7,108,116,115,104, 97,100,101, 5,115,104, 97,100,101, 7,
+100,107,115,104, 97,100,101, 7,117,110,105, 50, 53, 57, 52, 7,117,110,105, 50, 53, 57, 53, 7,117,110,105, 50, 53, 57, 54, 7,
+117,110,105, 50, 53, 57, 55, 7,117,110,105, 50, 53, 57, 56, 7,117,110,105, 50, 53, 57, 57, 7,117,110,105, 50, 53, 57, 65, 7,
+117,110,105, 50, 53, 57, 66, 7,117,110,105, 50, 53, 57, 67, 7,117,110,105, 50, 53, 57, 68, 7,117,110,105, 50, 53, 57, 69, 7,
+117,110,105, 50, 53, 57, 70, 9,102,105,108,108,101,100, 98,111,120, 6, 72, 50, 50, 48, 55, 51, 7,117,110,105, 50, 53, 65, 50,
+ 7,117,110,105, 50, 53, 65, 51, 7,117,110,105, 50, 53, 65, 52, 7,117,110,105, 50, 53, 65, 53, 7,117,110,105, 50, 53, 65, 54,
+ 7,117,110,105, 50, 53, 65, 55, 7,117,110,105, 50, 53, 65, 56, 7,117,110,105, 50, 53, 65, 57, 6, 72, 49, 56, 53, 52, 51, 6,
+ 72, 49, 56, 53, 53, 49, 10,102,105,108,108,101,100,114,101, 99,116, 7,117,110,105, 50, 53, 65, 68, 7,117,110,105, 50, 53, 65,
+ 69, 7,117,110,105, 50, 53, 65, 70, 7,117,110,105, 50, 53, 66, 48, 7,117,110,105, 50, 53, 66, 49, 7,116,114,105, 97,103,117,
+112, 7,117,110,105, 50, 53, 66, 51, 7,117,110,105, 50, 53, 66, 52, 7,117,110,105, 50, 53, 66, 53, 7,117,110,105, 50, 53, 66,
+ 54, 7,117,110,105, 50, 53, 66, 55, 7,117,110,105, 50, 53, 66, 56, 7,117,110,105, 50, 53, 66, 57, 7,116,114,105, 97,103,114,
+116, 7,117,110,105, 50, 53, 66, 66, 7,116,114,105, 97,103,100,110, 7,117,110,105, 50, 53, 66, 68, 7,117,110,105, 50, 53, 66,
+ 69, 7,117,110,105, 50, 53, 66, 70, 7,117,110,105, 50, 53, 67, 48, 7,117,110,105, 50, 53, 67, 49, 7,117,110,105, 50, 53, 67,
+ 50, 7,117,110,105, 50, 53, 67, 51, 7,116,114,105, 97,103,108,102, 7,117,110,105, 50, 53, 67, 53, 7,117,110,105, 50, 53, 67,
+ 54, 7,117,110,105, 50, 53, 67, 55, 7,117,110,105, 50, 53, 67, 56, 7,117,110,105, 50, 53, 67, 57, 6, 99,105,114, 99,108,101,
+ 7,117,110,105, 50, 53, 67, 67, 7,117,110,105, 50, 53, 67, 68, 7,117,110,105, 50, 53, 67, 69, 6, 72, 49, 56, 53, 51, 51, 7,
+117,110,105, 50, 53, 68, 48, 7,117,110,105, 50, 53, 68, 49, 7,117,110,105, 50, 53, 68, 50, 7,117,110,105, 50, 53, 68, 51, 7,
+117,110,105, 50, 53, 68, 52, 7,117,110,105, 50, 53, 68, 53, 7,117,110,105, 50, 53, 68, 54, 7,117,110,105, 50, 53, 68, 55, 9,
+105,110,118, 98,117,108,108,101,116, 9,105,110,118, 99,105,114, 99,108,101, 7,117,110,105, 50, 53, 68, 65, 7,117,110,105, 50,
+ 53, 68, 66, 7,117,110,105, 50, 53, 68, 67, 7,117,110,105, 50, 53, 68, 68, 7,117,110,105, 50, 53, 68, 69, 7,117,110,105, 50,
+ 53, 68, 70, 7,117,110,105, 50, 53, 69, 48, 7,117,110,105, 50, 53, 69, 49, 7,117,110,105, 50, 53, 69, 50, 7,117,110,105, 50,
+ 53, 69, 51, 7,117,110,105, 50, 53, 69, 52, 7,117,110,105, 50, 53, 69, 53, 10,111,112,101,110, 98,117,108,108,101,116, 7,117,
+110,105, 50, 53, 69, 55, 7,117,110,105, 50, 53, 69, 56, 7,117,110,105, 50, 53, 69, 57, 7,117,110,105, 50, 53, 69, 65, 7,117,
+110,105, 50, 53, 69, 66, 7,117,110,105, 50, 53, 69, 67, 7,117,110,105, 50, 53, 69, 68, 7,117,110,105, 50, 53, 69, 69, 7,117,
+110,105, 50, 53, 69, 70, 7,117,110,105, 50, 53, 70, 48, 7,117,110,105, 50, 53, 70, 49, 7,117,110,105, 50, 53, 70, 50, 7,117,
+110,105, 50, 53, 70, 51, 7,117,110,105, 50, 53, 70, 52, 7,117,110,105, 50, 53, 70, 53, 7,117,110,105, 50, 53, 70, 54, 7,117,
+110,105, 50, 53, 70, 55, 7,117,110,105, 50, 53, 70, 56, 7,117,110,105, 50, 53, 70, 57, 7,117,110,105, 50, 53, 70, 65, 7,117,
+110,105, 50, 53, 70, 66, 7,117,110,105, 50, 53, 70, 67, 7,117,110,105, 50, 53, 70, 68, 7,117,110,105, 50, 53, 70, 69, 7,117,
+110,105, 50, 53, 70, 70, 7,117,110,105, 50, 54, 48, 48, 7,117,110,105, 50, 54, 48, 49, 7,117,110,105, 50, 54, 48, 50, 7,117,
+110,105, 50, 54, 48, 51, 7,117,110,105, 50, 54, 48, 52, 7,117,110,105, 50, 54, 48, 53, 7,117,110,105, 50, 54, 48, 54, 7,117,
+110,105, 50, 54, 48, 55, 7,117,110,105, 50, 54, 48, 56, 7,117,110,105, 50, 54, 48, 57, 7,117,110,105, 50, 54, 48, 65, 7,117,
+110,105, 50, 54, 48, 66, 7,117,110,105, 50, 54, 48, 67, 7,117,110,105, 50, 54, 48, 68, 7,117,110,105, 50, 54, 48, 69, 7,117,
+110,105, 50, 54, 48, 70, 7,117,110,105, 50, 54, 49, 48, 7,117,110,105, 50, 54, 49, 49, 7,117,110,105, 50, 54, 49, 50, 7,117,
+110,105, 50, 54, 49, 51, 7,117,110,105, 50, 54, 49, 52, 7,117,110,105, 50, 54, 49, 53, 7,117,110,105, 50, 54, 49, 54, 7,117,
+110,105, 50, 54, 49, 55, 7,117,110,105, 50, 54, 49, 56, 7,117,110,105, 50, 54, 49, 57, 7,117,110,105, 50, 54, 49, 65, 7,117,
+110,105, 50, 54, 49, 66, 7,117,110,105, 50, 54, 49, 67, 7,117,110,105, 50, 54, 49, 68, 7,117,110,105, 50, 54, 49, 69, 7,117,
+110,105, 50, 54, 49, 70, 7,117,110,105, 50, 54, 50, 48, 7,117,110,105, 50, 54, 50, 49, 7,117,110,105, 50, 54, 50, 50, 7,117,
+110,105, 50, 54, 50, 51, 7,117,110,105, 50, 54, 50, 52, 7,117,110,105, 50, 54, 50, 53, 7,117,110,105, 50, 54, 50, 54, 7,117,
+110,105, 50, 54, 50, 55, 7,117,110,105, 50, 54, 50, 56, 7,117,110,105, 50, 54, 50, 57, 7,117,110,105, 50, 54, 50, 65, 7,117,
+110,105, 50, 54, 50, 66, 7,117,110,105, 50, 54, 50, 67, 7,117,110,105, 50, 54, 50, 68, 7,117,110,105, 50, 54, 50, 69, 7,117,
+110,105, 50, 54, 50, 70, 7,117,110,105, 50, 54, 51, 56, 7,117,110,105, 50, 54, 51, 57, 9,115,109,105,108,101,102, 97, 99,101,
+ 12,105,110,118,115,109,105,108,101,102, 97, 99,101, 3,115,117,110, 7,117,110,105, 50, 54, 51, 68, 7,117,110,105, 50, 54, 51,
+ 69, 7,117,110,105, 50, 54, 51, 70, 6,102,101,109, 97,108,101, 7,117,110,105, 50, 54, 52, 49, 4,109, 97,108,101, 7,117,110,
+105, 50, 54, 52, 51, 7,117,110,105, 50, 54, 52, 52, 7,117,110,105, 50, 54, 52, 53, 7,117,110,105, 50, 54, 52, 54, 7,117,110,
+105, 50, 54, 52, 55, 7,117,110,105, 50, 54, 52, 56, 7,117,110,105, 50, 54, 52, 57, 7,117,110,105, 50, 54, 52, 65, 7,117,110,
+105, 50, 54, 52, 66, 7,117,110,105, 50, 54, 52, 67, 7,117,110,105, 50, 54, 52, 68, 7,117,110,105, 50, 54, 52, 69, 7,117,110,
+105, 50, 54, 52, 70, 7,117,110,105, 50, 54, 53, 48, 7,117,110,105, 50, 54, 53, 49, 7,117,110,105, 50, 54, 53, 50, 7,117,110,
+105, 50, 54, 53, 51, 7,117,110,105, 50, 54, 53, 52, 7,117,110,105, 50, 54, 53, 53, 7,117,110,105, 50, 54, 53, 54, 7,117,110,
+105, 50, 54, 53, 55, 7,117,110,105, 50, 54, 53, 56, 7,117,110,105, 50, 54, 53, 57, 7,117,110,105, 50, 54, 53, 65, 7,117,110,
+105, 50, 54, 53, 66, 7,117,110,105, 50, 54, 53, 67, 7,117,110,105, 50, 54, 53, 68, 7,117,110,105, 50, 54, 53, 69, 7,117,110,
+105, 50, 54, 53, 70, 5,115,112, 97,100,101, 7,117,110,105, 50, 54, 54, 49, 7,117,110,105, 50, 54, 54, 50, 4, 99,108,117, 98,
+ 7,117,110,105, 50, 54, 54, 52, 5,104,101, 97,114,116, 7,100,105, 97,109,111,110,100, 7,117,110,105, 50, 54, 54, 55, 7,117,
+110,105, 50, 54, 54, 56, 7,117,110,105, 50, 54, 54, 57, 11,109,117,115,105, 99, 97,108,110,111,116,101, 14,109,117,115,105, 99,
+ 97,108,110,111,116,101,100, 98,108, 7,117,110,105, 50, 54, 54, 67, 7,117,110,105, 50, 54, 54, 68, 7,117,110,105, 50, 54, 54,
+ 69, 7,117,110,105, 50, 54, 54, 70, 7,117,110,105, 50, 54, 55, 48, 7,117,110,105, 50, 54, 55, 49, 7,117,110,105, 50, 54, 55,
+ 50, 7,117,110,105, 50, 54, 55, 51, 7,117,110,105, 50, 54, 55, 52, 7,117,110,105, 50, 54, 55, 53, 7,117,110,105, 50, 54, 55,
+ 54, 7,117,110,105, 50, 54, 55, 55, 7,117,110,105, 50, 54, 55, 56, 7,117,110,105, 50, 54, 55, 57, 7,117,110,105, 50, 54, 55,
+ 65, 7,117,110,105, 50, 54, 55, 66, 7,117,110,105, 50, 54, 55, 67, 7,117,110,105, 50, 54, 55, 68, 7,117,110,105, 50, 54, 55,
+ 69, 7,117,110,105, 50, 54, 55, 70, 7,117,110,105, 50, 54, 56, 48, 7,117,110,105, 50, 54, 56, 49, 7,117,110,105, 50, 54, 56,
+ 50, 7,117,110,105, 50, 54, 56, 51, 7,117,110,105, 50, 54, 56, 52, 7,117,110,105, 50, 54, 56, 53, 7,117,110,105, 50, 54, 56,
+ 54, 7,117,110,105, 50, 54, 56, 55, 7,117,110,105, 50, 54, 56, 56, 7,117,110,105, 50, 54, 56, 57, 7,117,110,105, 50, 54, 56,
+ 65, 7,117,110,105, 50, 54, 56, 66, 7,117,110,105, 50, 54, 57, 48, 7,117,110,105, 50, 54, 57, 49, 7,117,110,105, 50, 54, 57,
+ 50, 7,117,110,105, 50, 54, 57, 51, 7,117,110,105, 50, 54, 57, 52, 7,117,110,105, 50, 54, 57, 53, 7,117,110,105, 50, 54, 57,
+ 54, 7,117,110,105, 50, 54, 57, 55, 7,117,110,105, 50, 54, 57, 56, 7,117,110,105, 50, 54, 57, 57, 7,117,110,105, 50, 54, 57,
+ 65, 7,117,110,105, 50, 54, 57, 66, 7,117,110,105, 50, 54, 57, 67, 7,117,110,105, 50, 54, 65, 48, 7,117,110,105, 50, 54, 65,
+ 49, 7,117,110,105, 50, 54, 66, 48, 7,117,110,105, 50, 54, 66, 49, 7,117,110,105, 50, 55, 48, 49, 7,117,110,105, 50, 55, 48,
+ 50, 7,117,110,105, 50, 55, 48, 51, 7,117,110,105, 50, 55, 48, 52, 7,117,110,105, 50, 55, 48, 54, 7,117,110,105, 50, 55, 48,
+ 55, 7,117,110,105, 50, 55, 48, 56, 7,117,110,105, 50, 55, 48, 57, 7,117,110,105, 50, 55, 48, 67, 7,117,110,105, 50, 55, 48,
+ 68, 7,117,110,105, 50, 55, 48, 69, 7,117,110,105, 50, 55, 48, 70, 7,117,110,105, 50, 55, 49, 48, 7,117,110,105, 50, 55, 49,
+ 49, 7,117,110,105, 50, 55, 49, 50, 7,117,110,105, 50, 55, 49, 51, 7,117,110,105, 50, 55, 49, 52, 7,117,110,105, 50, 55, 49,
+ 53, 7,117,110,105, 50, 55, 49, 54, 7,117,110,105, 50, 55, 49, 55, 7,117,110,105, 50, 55, 49, 56, 7,117,110,105, 50, 55, 49,
+ 57, 7,117,110,105, 50, 55, 49, 65, 7,117,110,105, 50, 55, 49, 66, 7,117,110,105, 50, 55, 49, 67, 7,117,110,105, 50, 55, 49,
+ 68, 7,117,110,105, 50, 55, 49, 69, 7,117,110,105, 50, 55, 49, 70, 7,117,110,105, 50, 55, 50, 48, 7,117,110,105, 50, 55, 50,
+ 49, 7,117,110,105, 50, 55, 50, 50, 7,117,110,105, 50, 55, 50, 51, 7,117,110,105, 50, 55, 50, 52, 7,117,110,105, 50, 55, 50,
+ 53, 7,117,110,105, 50, 55, 50, 54, 7,117,110,105, 50, 55, 50, 55, 7,117,110,105, 50, 55, 50, 57, 7,117,110,105, 50, 55, 50,
+ 65, 7,117,110,105, 50, 55, 50, 66, 7,117,110,105, 50, 55, 50, 67, 7,117,110,105, 50, 55, 50, 68, 7,117,110,105, 50, 55, 50,
+ 69, 7,117,110,105, 50, 55, 50, 70, 7,117,110,105, 50, 55, 51, 48, 7,117,110,105, 50, 55, 51, 49, 7,117,110,105, 50, 55, 51,
+ 50, 7,117,110,105, 50, 55, 51, 51, 7,117,110,105, 50, 55, 51, 52, 7,117,110,105, 50, 55, 51, 53, 7,117,110,105, 50, 55, 51,
+ 54, 7,117,110,105, 50, 55, 51, 55, 7,117,110,105, 50, 55, 51, 56, 7,117,110,105, 50, 55, 51, 57, 7,117,110,105, 50, 55, 51,
+ 65, 7,117,110,105, 50, 55, 51, 66, 7,117,110,105, 50, 55, 51, 67, 7,117,110,105, 50, 55, 51, 68, 7,117,110,105, 50, 55, 51,
+ 69, 7,117,110,105, 50, 55, 51, 70, 7,117,110,105, 50, 55, 52, 48, 7,117,110,105, 50, 55, 52, 49, 7,117,110,105, 50, 55, 52,
+ 50, 7,117,110,105, 50, 55, 52, 51, 7,117,110,105, 50, 55, 52, 52, 7,117,110,105, 50, 55, 52, 53, 7,117,110,105, 50, 55, 52,
+ 54, 7,117,110,105, 50, 55, 52, 55, 7,117,110,105, 50, 55, 52, 56, 7,117,110,105, 50, 55, 52, 57, 7,117,110,105, 50, 55, 52,
+ 65, 7,117,110,105, 50, 55, 52, 66, 7,117,110,105, 50, 55, 52, 68, 7,117,110,105, 50, 55, 52, 70, 7,117,110,105, 50, 55, 53,
+ 48, 7,117,110,105, 50, 55, 53, 49, 7,117,110,105, 50, 55, 53, 50, 7,117,110,105, 50, 55, 53, 54, 7,117,110,105, 50, 55, 53,
+ 56, 7,117,110,105, 50, 55, 53, 57, 7,117,110,105, 50, 55, 53, 65, 7,117,110,105, 50, 55, 53, 66, 7,117,110,105, 50, 55, 53,
+ 67, 7,117,110,105, 50, 55, 53, 68, 7,117,110,105, 50, 55, 53, 69, 7,117,110,105, 50, 55, 54, 49, 7,117,110,105, 50, 55, 54,
+ 50, 7,117,110,105, 50, 55, 54, 51, 7,117,110,105, 50, 55, 54, 52, 7,117,110,105, 50, 55, 54, 53, 7,117,110,105, 50, 55, 54,
+ 54, 7,117,110,105, 50, 55, 54, 55, 7,117,110,105, 50, 55, 54, 56, 7,117,110,105, 50, 55, 54, 57, 7,117,110,105, 50, 55, 54,
+ 65, 7,117,110,105, 50, 55, 54, 66, 7,117,110,105, 50, 55, 54, 67, 7,117,110,105, 50, 55, 54, 68, 7,117,110,105, 50, 55, 54,
+ 69, 7,117,110,105, 50, 55, 54, 70, 7,117,110,105, 50, 55, 55, 48, 7,117,110,105, 50, 55, 55, 49, 7,117,110,105, 50, 55, 55,
+ 50, 7,117,110,105, 50, 55, 55, 51, 7,117,110,105, 50, 55, 55, 52, 7,117,110,105, 50, 55, 55, 53, 7,117,110,105, 50, 55, 57,
+ 52, 7,117,110,105, 50, 55, 57, 56, 7,117,110,105, 50, 55, 57, 57, 7,117,110,105, 50, 55, 57, 65, 7,117,110,105, 50, 55, 57,
+ 66, 7,117,110,105, 50, 55, 57, 67, 7,117,110,105, 50, 55, 57, 68, 7,117,110,105, 50, 55, 57, 69, 7,117,110,105, 50, 55, 57,
+ 70, 7,117,110,105, 50, 55, 65, 48, 7,117,110,105, 50, 55, 65, 49, 7,117,110,105, 50, 55, 65, 50, 7,117,110,105, 50, 55, 65,
+ 51, 7,117,110,105, 50, 55, 65, 52, 7,117,110,105, 50, 55, 65, 53, 7,117,110,105, 50, 55, 65, 54, 7,117,110,105, 50, 55, 65,
+ 55, 7,117,110,105, 50, 55, 65, 56, 7,117,110,105, 50, 55, 65, 57, 7,117,110,105, 50, 55, 65, 65, 7,117,110,105, 50, 55, 65,
+ 66, 7,117,110,105, 50, 55, 65, 67, 7,117,110,105, 50, 55, 65, 68, 7,117,110,105, 50, 55, 65, 69, 7,117,110,105, 50, 55, 65,
+ 70, 7,117,110,105, 50, 55, 66, 49, 7,117,110,105, 50, 55, 66, 50, 7,117,110,105, 50, 55, 66, 51, 7,117,110,105, 50, 55, 66,
+ 52, 7,117,110,105, 50, 55, 66, 53, 7,117,110,105, 50, 55, 66, 54, 7,117,110,105, 50, 55, 66, 55, 7,117,110,105, 50, 55, 66,
+ 56, 7,117,110,105, 50, 55, 66, 57, 7,117,110,105, 50, 55, 66, 65, 7,117,110,105, 50, 55, 66, 66, 7,117,110,105, 50, 55, 66,
+ 67, 7,117,110,105, 50, 55, 66, 68, 7,117,110,105, 50, 55, 66, 69, 7,117,110,105, 50, 55, 69, 48, 7,117,110,105, 50, 55, 69,
+ 56, 7,117,110,105, 50, 55, 69, 57, 7,117,110,105, 50, 57, 69, 66, 7,117,110,105, 50, 57, 70, 65, 7,117,110,105, 50, 57, 70,
+ 66, 7,117,110,105, 50, 65, 50, 70, 7,117,110,105, 50, 66, 49, 50, 7,117,110,105, 50, 66, 49, 51, 7,117,110,105, 50, 66, 49,
+ 52, 7,117,110,105, 50, 66, 49, 53, 7,117,110,105, 50, 66, 49, 54, 7,117,110,105, 50, 66, 49, 55, 7,117,110,105, 50, 66, 49,
+ 56, 7,117,110,105, 50, 66, 49, 57, 7,117,110,105, 50, 66, 49, 65, 7,117,110,105, 50, 67, 55, 53, 7,117,110,105, 50, 67, 55,
+ 54, 7,117,110,105, 50, 67, 55, 55, 7,117,110,105, 50, 69, 49, 56, 7,117,110,105, 50, 69, 50, 69, 7,117,110,105, 70, 54, 67,
+ 53, 7,117,110,105, 70, 66, 53, 50, 7,117,110,105, 70, 66, 53, 51, 7,117,110,105, 70, 66, 53, 52, 7,117,110,105, 70, 66, 53,
+ 53, 7,117,110,105, 70, 66, 53, 54, 7,117,110,105, 70, 66, 53, 55, 7,117,110,105, 70, 66, 53, 56, 7,117,110,105, 70, 66, 53,
+ 57, 7,117,110,105, 70, 66, 53, 65, 7,117,110,105, 70, 66, 53, 66, 7,117,110,105, 70, 66, 53, 67, 7,117,110,105, 70, 66, 53,
+ 68, 7,117,110,105, 70, 66, 53, 69, 7,117,110,105, 70, 66, 53, 70, 7,117,110,105, 70, 66, 54, 48, 7,117,110,105, 70, 66, 54,
+ 49, 7,117,110,105, 70, 66, 54, 50, 7,117,110,105, 70, 66, 54, 51, 7,117,110,105, 70, 66, 54, 52, 7,117,110,105, 70, 66, 54,
+ 53, 7,117,110,105, 70, 66, 54, 54, 7,117,110,105, 70, 66, 54, 55, 7,117,110,105, 70, 66, 54, 56, 7,117,110,105, 70, 66, 54,
+ 57, 7,117,110,105, 70, 66, 54, 65, 7,117,110,105, 70, 66, 54, 66, 7,117,110,105, 70, 66, 54, 67, 7,117,110,105, 70, 66, 54,
+ 68, 7,117,110,105, 70, 66, 54, 69, 7,117,110,105, 70, 66, 54, 70, 7,117,110,105, 70, 66, 55, 48, 7,117,110,105, 70, 66, 55,
+ 49, 7,117,110,105, 70, 66, 55, 50, 7,117,110,105, 70, 66, 55, 51, 7,117,110,105, 70, 66, 55, 52, 7,117,110,105, 70, 66, 55,
+ 53, 7,117,110,105, 70, 66, 55, 54, 7,117,110,105, 70, 66, 55, 55, 7,117,110,105, 70, 66, 55, 56, 7,117,110,105, 70, 66, 55,
+ 57, 7,117,110,105, 70, 66, 55, 65, 7,117,110,105, 70, 66, 55, 66, 7,117,110,105, 70, 66, 55, 67, 7,117,110,105, 70, 66, 55,
+ 68, 7,117,110,105, 70, 66, 55, 69, 7,117,110,105, 70, 66, 55, 70, 7,117,110,105, 70, 66, 56, 48, 7,117,110,105, 70, 66, 56,
+ 49, 7,117,110,105, 70, 66, 56, 65, 7,117,110,105, 70, 66, 56, 66, 7,117,110,105, 70, 66, 56, 67, 7,117,110,105, 70, 66, 56,
+ 68, 7,117,110,105, 70, 66, 56, 69, 7,117,110,105, 70, 66, 56, 70, 7,117,110,105, 70, 66, 57, 48, 7,117,110,105, 70, 66, 57,
+ 49, 7,117,110,105, 70, 66, 57, 50, 7,117,110,105, 70, 66, 57, 51, 7,117,110,105, 70, 66, 57, 52, 7,117,110,105, 70, 66, 57,
+ 53, 7,117,110,105, 70, 66, 57, 69, 7,117,110,105, 70, 66, 57, 70, 7,117,110,105, 70, 66, 65, 65, 7,117,110,105, 70, 66, 65,
+ 66, 7,117,110,105, 70, 66, 65, 67, 7,117,110,105, 70, 66, 65, 68, 7,117,110,105, 70, 66, 69, 56, 7,117,110,105, 70, 66, 69,
+ 57, 7,117,110,105, 70, 66, 70, 67, 7,117,110,105, 70, 66, 70, 68, 7,117,110,105, 70, 66, 70, 69, 7,117,110,105, 70, 66, 70,
+ 70, 7,117,110,105, 70, 69, 55, 48, 7,117,110,105, 70, 69, 55, 49, 7,117,110,105, 70, 69, 55, 50, 7,117,110,105, 70, 69, 55,
+ 51, 7,117,110,105, 70, 69, 55, 52, 7,117,110,105, 70, 69, 55, 54, 7,117,110,105, 70, 69, 55, 55, 7,117,110,105, 70, 69, 55,
+ 56, 7,117,110,105, 70, 69, 55, 57, 7,117,110,105, 70, 69, 55, 65, 7,117,110,105, 70, 69, 55, 66, 7,117,110,105, 70, 69, 55,
+ 67, 7,117,110,105, 70, 69, 55, 68, 7,117,110,105, 70, 69, 55, 69, 7,117,110,105, 70, 69, 55, 70, 7,117,110,105, 70, 69, 56,
+ 48, 7,117,110,105, 70, 69, 56, 49, 7,117,110,105, 70, 69, 56, 50, 7,117,110,105, 70, 69, 56, 51, 7,117,110,105, 70, 69, 56,
+ 52, 7,117,110,105, 70, 69, 56, 53, 7,117,110,105, 70, 69, 56, 54, 7,117,110,105, 70, 69, 56, 55, 7,117,110,105, 70, 69, 56,
+ 56, 7,117,110,105, 70, 69, 56, 57, 7,117,110,105, 70, 69, 56, 65, 7,117,110,105, 70, 69, 56, 66, 7,117,110,105, 70, 69, 56,
+ 67, 7,117,110,105, 70, 69, 56, 68, 7,117,110,105, 70, 69, 56, 69, 7,117,110,105, 70, 69, 56, 70, 7,117,110,105, 70, 69, 57,
+ 48, 7,117,110,105, 70, 69, 57, 49, 7,117,110,105, 70, 69, 57, 50, 7,117,110,105, 70, 69, 57, 51, 7,117,110,105, 70, 69, 57,
+ 52, 7,117,110,105, 70, 69, 57, 53, 7,117,110,105, 70, 69, 57, 54, 7,117,110,105, 70, 69, 57, 55, 7,117,110,105, 70, 69, 57,
+ 56, 7,117,110,105, 70, 69, 57, 57, 7,117,110,105, 70, 69, 57, 65, 7,117,110,105, 70, 69, 57, 66, 7,117,110,105, 70, 69, 57,
+ 67, 7,117,110,105, 70, 69, 57, 68, 7,117,110,105, 70, 69, 57, 69, 7,117,110,105, 70, 69, 57, 70, 7,117,110,105, 70, 69, 65,
+ 48, 7,117,110,105, 70, 69, 65, 49, 7,117,110,105, 70, 69, 65, 50, 7,117,110,105, 70, 69, 65, 51, 7,117,110,105, 70, 69, 65,
+ 52, 7,117,110,105, 70, 69, 65, 53, 7,117,110,105, 70, 69, 65, 54, 7,117,110,105, 70, 69, 65, 55, 7,117,110,105, 70, 69, 65,
+ 56, 7,117,110,105, 70, 69, 65, 57, 7,117,110,105, 70, 69, 65, 65, 7,117,110,105, 70, 69, 65, 66, 7,117,110,105, 70, 69, 65,
+ 67, 7,117,110,105, 70, 69, 65, 68, 7,117,110,105, 70, 69, 65, 69, 7,117,110,105, 70, 69, 65, 70, 7,117,110,105, 70, 69, 66,
+ 48, 7,117,110,105, 70, 69, 66, 49, 7,117,110,105, 70, 69, 66, 50, 7,117,110,105, 70, 69, 66, 51, 7,117,110,105, 70, 69, 66,
+ 52, 7,117,110,105, 70, 69, 66, 53, 7,117,110,105, 70, 69, 66, 54, 7,117,110,105, 70, 69, 66, 55, 7,117,110,105, 70, 69, 66,
+ 56, 7,117,110,105, 70, 69, 66, 57, 7,117,110,105, 70, 69, 66, 65, 7,117,110,105, 70, 69, 66, 66, 7,117,110,105, 70, 69, 66,
+ 67, 7,117,110,105, 70, 69, 66, 68, 7,117,110,105, 70, 69, 66, 69, 7,117,110,105, 70, 69, 66, 70, 7,117,110,105, 70, 69, 67,
+ 48, 7,117,110,105, 70, 69, 67, 49, 7,117,110,105, 70, 69, 67, 50, 7,117,110,105, 70, 69, 67, 51, 7,117,110,105, 70, 69, 67,
+ 52, 7,117,110,105, 70, 69, 67, 53, 7,117,110,105, 70, 69, 67, 54, 7,117,110,105, 70, 69, 67, 55, 7,117,110,105, 70, 69, 67,
+ 56, 7,117,110,105, 70, 69, 67, 57, 7,117,110,105, 70, 69, 67, 65, 7,117,110,105, 70, 69, 67, 66, 7,117,110,105, 70, 69, 67,
+ 67, 7,117,110,105, 70, 69, 67, 68, 7,117,110,105, 70, 69, 67, 69, 7,117,110,105, 70, 69, 67, 70, 7,117,110,105, 70, 69, 68,
+ 48, 7,117,110,105, 70, 69, 68, 49, 7,117,110,105, 70, 69, 68, 50, 7,117,110,105, 70, 69, 68, 51, 7,117,110,105, 70, 69, 68,
+ 52, 7,117,110,105, 70, 69, 68, 53, 7,117,110,105, 70, 69, 68, 54, 7,117,110,105, 70, 69, 68, 55, 7,117,110,105, 70, 69, 68,
+ 56, 7,117,110,105, 70, 69, 68, 57, 7,117,110,105, 70, 69, 68, 65, 7,117,110,105, 70, 69, 68, 66, 7,117,110,105, 70, 69, 68,
+ 67, 7,117,110,105, 70, 69, 68, 68, 7,117,110,105, 70, 69, 68, 69, 7,117,110,105, 70, 69, 68, 70, 7,117,110,105, 70, 69, 69,
+ 48, 7,117,110,105, 70, 69, 69, 49, 7,117,110,105, 70, 69, 69, 50, 7,117,110,105, 70, 69, 69, 51, 7,117,110,105, 70, 69, 69,
+ 52, 7,117,110,105, 70, 69, 69, 53, 7,117,110,105, 70, 69, 69, 54, 7,117,110,105, 70, 69, 69, 55, 7,117,110,105, 70, 69, 69,
+ 56, 7,117,110,105, 70, 69, 69, 57, 7,117,110,105, 70, 69, 69, 65, 7,117,110,105, 70, 69, 69, 66, 7,117,110,105, 70, 69, 69,
+ 67, 7,117,110,105, 70, 69, 69, 68, 7,117,110,105, 70, 69, 69, 69, 7,117,110,105, 70, 69, 69, 70, 7,117,110,105, 70, 69, 70,
+ 48, 7,117,110,105, 70, 69, 70, 49, 7,117,110,105, 70, 69, 70, 50, 7,117,110,105, 70, 69, 70, 51, 7,117,110,105, 70, 69, 70,
+ 52, 7,117,110,105, 70, 69, 70, 53, 7,117,110,105, 70, 69, 70, 54, 7,117,110,105, 70, 69, 70, 55, 7,117,110,105, 70, 69, 70,
+ 56, 7,117,110,105, 70, 69, 70, 57, 7,117,110,105, 70, 69, 70, 65, 7,117,110,105, 70, 69, 70, 66, 7,117,110,105, 70, 69, 70,
+ 67, 7,117,110,105, 70, 69, 70, 70, 7,117,110,105, 70, 70, 70, 57, 7,117,110,105, 70, 70, 70, 65, 7,117,110,105, 70, 70, 70,
+ 66, 7,117,110,105, 70, 70, 70, 67, 7,117,110,105, 70, 70, 70, 68, 6,117, 49, 68, 54, 55, 48, 6,117, 49, 68, 54, 55, 49, 6,
+117, 49, 68, 54, 55, 50, 6,117, 49, 68, 54, 55, 51, 6,117, 49, 68, 54, 55, 52, 6,117, 49, 68, 54, 55, 53, 6,117, 49, 68, 54,
+ 55, 54, 6,117, 49, 68, 54, 55, 55, 6,117, 49, 68, 54, 55, 56, 6,117, 49, 68, 54, 55, 57, 6,117, 49, 68, 54, 55, 65, 6,117,
+ 49, 68, 54, 55, 66, 6,117, 49, 68, 54, 55, 67, 6,117, 49, 68, 54, 55, 68, 6,117, 49, 68, 54, 55, 69, 6,117, 49, 68, 54, 55,
+ 70, 6,117, 49, 68, 54, 56, 48, 6,117, 49, 68, 54, 56, 49, 6,117, 49, 68, 54, 56, 50, 6,117, 49, 68, 54, 56, 51, 6,117, 49,
+ 68, 54, 56, 52, 6,117, 49, 68, 54, 56, 53, 6,117, 49, 68, 54, 56, 54, 6,117, 49, 68, 54, 56, 55, 6,117, 49, 68, 54, 56, 56,
+ 6,117, 49, 68, 54, 56, 57, 6,117, 49, 68, 54, 56, 65, 6,117, 49, 68, 54, 56, 66, 6,117, 49, 68, 54, 56, 67, 6,117, 49, 68,
+ 54, 56, 68, 6,117, 49, 68, 54, 56, 69, 6,117, 49, 68, 54, 56, 70, 6,117, 49, 68, 54, 57, 48, 6,117, 49, 68, 54, 57, 49, 6,
+117, 49, 68, 54, 57, 50, 6,117, 49, 68, 54, 57, 51, 6,117, 49, 68, 54, 57, 52, 6,117, 49, 68, 54, 57, 53, 6,117, 49, 68, 54,
+ 57, 54, 6,117, 49, 68, 54, 57, 55, 6,117, 49, 68, 54, 57, 56, 6,117, 49, 68, 54, 57, 57, 6,117, 49, 68, 54, 57, 65, 6,117,
+ 49, 68, 54, 57, 66, 6,117, 49, 68, 54, 57, 67, 6,117, 49, 68, 54, 57, 68, 6,117, 49, 68, 54, 57, 69, 6,117, 49, 68, 54, 57,
+ 70, 6,117, 49, 68, 54, 65, 48, 6,117, 49, 68, 54, 65, 49, 6,117, 49, 68, 54, 65, 50, 6,117, 49, 68, 54, 65, 51, 6,117, 49,
+ 68, 55, 70, 54, 6,117, 49, 68, 55, 70, 55, 6,117, 49, 68, 55, 70, 56, 6,117, 49, 68, 55, 70, 57, 6,117, 49, 68, 55, 70, 65,
+ 6,117, 49, 68, 55, 70, 66, 6,117, 49, 68, 55, 70, 67, 6,117, 49, 68, 55, 70, 68, 6,117, 49, 68, 55, 70, 69, 6,117, 49, 68,
+ 55, 70, 70, 9,100,108, 76,116, 99, 97,114,111,110, 9, 68,105, 97,101,114,101,115,105,115, 5, 65, 99,117,116,101, 5, 84,105,
+108,100,101, 5, 71,114, 97,118,101, 10, 67,105,114, 99,117,109,102,108,101,120, 5, 67, 97,114,111,110, 13,102,114, 97, 99,116,
+105,111,110,115,108, 97,115,104, 12,117,110,105, 48, 51, 49, 49, 46, 99, 97,115,101, 12,117,110,105, 48, 51, 48, 54, 46, 99, 97,
+115,101, 12,117,110,105, 48, 51, 48, 55, 46, 99, 97,115,101, 12,117,110,105, 48, 51, 48, 66, 46, 99, 97,115,101, 12,117,110,105,
+ 48, 51, 48, 70, 46, 99, 97,115,101, 12,116,104,105,110,113,117,101,115,116,105,111,110, 12,117,110,105, 48, 51, 48, 52, 46, 99,
+ 97,115,101, 8,117,110,100,101,114, 98, 97,114, 13,117,110,100,101,114, 98, 97,114, 46,119,105,100,101, 14,117,110,100,101,114,
+ 98, 97,114, 46,115,109, 97,108,108, 3,106,111,116, 17,100,105, 97,101,114,101,115,105,115, 46,115,121,109, 98,111,108,115, 10,
+ 97,114, 97, 98,105, 99, 95,100,111,116, 12, 97,114, 97, 98,105, 99, 95, 50,100,111,116,115, 12, 97,114, 97, 98,105, 99, 95, 51,
+100,111,116,115, 12,117,110,105, 48, 54, 54, 69, 46,102,105,110, 97, 12,117,110,105, 48, 54, 65, 49, 46,105,110,105,116, 12,117,
+110,105, 48, 54, 65, 49, 46,109,101,100,105, 12,117,110,105, 48, 54, 54, 70, 46,102,105,110, 97, 12,117,110,105, 48, 54, 65, 49,
+ 46,102,105,110, 97, 14, 97,114, 97, 98,105, 99, 95, 51,100,111,116,115, 95, 97, 14, 97,114, 97, 98,105, 99, 95, 50,100,111,116,
+115, 95, 97, 12, 97,114, 97, 98,105, 99, 95, 52,100,111,116,115, 14, 97,114, 97, 98,105, 99, 95,103, 97,102, 95, 98, 97,114, 16,
+ 97,114, 97, 98,105, 99, 95,103, 97,102, 95, 98, 97,114, 95, 97, 11, 97,114, 97, 98,105, 99, 95,114,105,110,103, 7, 69,110,103,
+ 46, 97,108,116,185, 2,128, 1, 21,178,148, 93, 5, 65, 28, 1, 21, 0,150, 0, 3, 1, 21, 0,128, 0, 4, 1, 20, 0,254, 0,
+ 3, 1, 19, 0,254, 0, 3, 1, 18, 0, 18, 0, 3, 1, 17, 0,254, 0, 3, 1, 16, 0,254, 0, 3, 1, 15, 0,154, 0, 3, 1,
+ 14, 0,254, 0, 3, 1, 13,178,235, 71, 5, 65, 37, 1, 13, 0,125, 0, 3, 1, 12, 0, 37, 0, 3, 1, 11, 0, 50, 0, 3, 1,
+ 10, 0,150, 0, 3, 1, 9, 0,254, 0, 3, 1, 8, 0, 14, 0, 3, 1, 7, 0,254, 0, 3, 1, 6, 0, 37, 0, 3, 1, 5, 0,
+254, 0, 3, 1, 4, 0, 14, 0, 3, 1, 3, 0, 37, 0, 3, 1, 2, 0,254, 0, 3, 1, 1, 64, 89,254, 3,254,254, 3,253,125,
+ 3,252,254, 3,251,254, 3,250, 50, 3,249,187, 3,248,125, 3,247,246,140, 5,247,254, 3,247,192, 4,246,245, 89, 5,246,140,
+ 3,246,128, 4,245,244, 38, 5,245, 89, 3,245, 64, 4,244, 38, 3,243,242, 47, 5,243,250, 3,242, 47, 3,241,254, 3,240,254,
+ 3,239, 50, 3,238, 20, 3,237,150, 3,236,235, 71, 5,236,254, 3,236,184,255,209, 64,255, 4,235, 71, 3,234,233,100, 5,234,
+150, 3,233,100, 3,232,254, 3,231,230, 27, 5,231,254, 3,230, 27, 3,229,254, 3,228,107, 3,227,254, 3,226,187, 3,225,224,
+ 25, 5,225,250, 3,224, 25, 3,223,150, 3,222,254, 3,221,254, 3,220,219, 21, 5,220,254, 3,219, 21, 3,218,150, 3,217,216,
+ 21, 5,217,254, 3,216,141, 11, 5,216, 21, 3,215,125, 3,214, 58, 3,213,141, 11, 5,213, 58, 3,212,254, 3,211,210, 10, 5,
+211,254, 3,210, 10, 3,209,254, 3,208,254, 3,207,138, 17, 5,207, 28, 3,206, 22, 3,205,254, 3,204,150, 3,203,139, 37, 5,
+203,254, 3,202,254, 3,201,125, 3,200,254, 3,199,254, 3,198,254, 3,197,154, 13, 5,196,254, 3,195,254, 3,194,254, 3,193,
+254, 3,192,141, 11, 5,192, 20, 3,191, 12, 3,190,189,187, 5,190,254, 3,189,188, 93, 5,189,187, 3,189,128, 4,188,187, 37,
+ 5,188, 93, 3,188, 64, 4,187, 37, 3,186,254, 3,185,150, 3,184,143, 65, 5,183,254, 3,182,143, 65, 5,182,250, 3,181,154,
+ 13, 5,180,254, 3,179,100, 3,178,100, 3,177, 14, 3,176, 18, 3,175,254, 3,174,254, 64,253, 3,173,254, 3,172,254, 3,171,
+ 18, 3,170,254, 3,169,168, 14, 5,169, 50, 3,168, 14, 3,167,166, 17, 5,167, 40, 3,166, 17, 3,165,164, 45, 5,165,125, 3,
+164, 45, 3,163,254, 3,162,254, 3,161,254, 3,160,159, 25, 5,160,100, 3,159,158, 16, 5,159, 25, 3,158, 16, 3,157, 10, 3,
+156,254, 3,155,154, 13, 5,155,254, 3,154, 13, 3,153,152, 46, 5,153,254, 3,152, 46, 3,151,143, 65, 5,151,150, 3,150,149,
+187, 5,150,254, 3,149,148, 93, 5,149,187, 3,149,128, 4,148,144, 37, 5,148, 93, 3,148, 64, 4,147,254, 3,146,254, 3,145,
+144, 37, 5,145,187, 3,144, 37, 3,143,139, 37, 5,143, 65, 3,142,141, 11, 5,142, 20, 3,141, 11, 3,140,139, 37, 5,140,100,
+ 3,139,138, 17, 5,139, 37, 3,138, 17, 3,137,254, 3,136,254, 3,135,254, 3,134,133, 17, 5,134,254, 3,133, 17, 3,132,254,
+ 3,131,254, 3,130, 17, 66, 5,130, 83, 3,129,254, 3,128,120, 3,127,126,125, 5,127,254, 3,126,125, 3,125, 30, 3,124,254,
+ 3,123, 14, 3,122,254, 3,119,254, 3,118,254, 3,117,116, 12, 5,117, 15, 3,117,184, 1, 0, 64,218, 4,116, 12, 3,116,192,
+ 4,115, 18, 3,115, 64, 4,114,254, 3,113,254, 3,112,254, 3,111,110, 83, 5,111,150, 3,110,109, 40, 5,110, 83, 3,109, 40,
+ 3,108,254, 3,107, 50, 3,106,254, 3,105, 50, 3,104,250, 3,103,187, 3,102,254, 3,101,254, 3,100,254, 3, 99, 98, 30, 5,
+ 99,254, 3, 98, 0, 16, 5, 98, 30, 3, 97,254, 3, 96,254, 3, 95,254, 3, 94, 90, 11, 5, 94, 14, 3, 93,100, 3, 92,200, 3,
+ 91, 90, 11, 5, 91, 20, 3, 90, 11, 3, 89,254, 3, 88, 20, 3, 87,254, 3, 86,254, 3, 85, 27, 25, 5, 85, 50, 3, 84,254, 3,
+ 83,254, 3, 82,254, 3, 81,125, 3, 80,254, 3, 79, 20, 3, 78,254, 3, 77, 1, 45, 5, 77,254, 3, 76,187, 3, 75, 40, 3, 74,
+ 73, 24, 5, 74, 55, 3, 73, 67, 18, 5, 73, 24, 3, 72, 69, 24, 5, 72,254, 3, 71, 67, 18, 5, 71,100, 3, 70, 69, 24, 5, 70,
+187, 3, 69, 24, 3, 68, 67, 18, 5, 68, 55, 3, 67, 66, 17, 5, 67, 18, 3, 67,184, 2, 64, 64, 9, 4, 66, 65, 15, 5, 66, 17,
+ 3, 66,184, 2, 0, 64, 9, 4, 65, 64, 14, 5, 65, 15, 3, 65,184, 1,192, 64, 9, 4, 64, 63, 12, 5, 64, 14, 3, 64,184, 1,
+128, 64, 9, 4, 63, 12, 9, 5, 63, 12, 3, 63,184, 1, 64, 64,100, 4, 62,254, 3, 61, 1, 45, 5, 61,250, 3, 60,254, 3, 59,
+ 40, 3, 58,254, 3, 57, 17, 66, 5, 57,100, 3, 56, 49, 26, 5, 56, 75, 3, 55,254, 3, 54, 45, 20, 5, 54,254, 3, 53, 75, 3,
+ 52, 48, 26, 5, 52, 75, 3, 51, 48, 26, 5, 51,254, 3, 50, 17, 66, 5, 50,254, 3, 49, 45, 20, 5, 49, 26, 3, 48, 26, 3, 47,
+ 45, 20, 5, 47, 24, 3, 46, 9, 22, 5, 46,187, 3, 45, 44, 19, 5, 45, 20, 3, 45,184, 2,128, 64, 9, 4, 44, 16, 17, 5, 44,
+ 19, 3, 44,184, 2, 64, 64,150, 4, 43, 42, 37, 5, 43,254, 3, 42, 9, 22, 5, 42, 37, 3, 41, 2, 58, 5, 41,254, 3, 40,254,
+ 3, 39,254, 3, 38, 15, 3, 37, 22, 66, 5, 37, 69, 3, 36, 15, 3, 35,254, 3, 34, 15, 15, 5, 34,254, 3, 33, 32, 45, 5, 33,
+125, 3, 32, 45, 3, 31, 75, 3, 30, 17, 66, 5, 30,254, 3, 29,254, 3, 28, 27, 25, 5, 28,254, 3, 27, 0, 16, 5, 27, 25, 3,
+ 26,254, 3, 25,254, 3, 24,254, 3, 23, 22, 66, 5, 23, 70, 3, 22, 21, 45, 5, 22, 66, 3, 21, 20, 16, 5, 21, 45, 3, 20, 16,
+ 3, 19, 0, 16, 5, 19, 20, 3, 18, 17, 66, 5, 18,254, 3, 17, 1, 45, 5, 17, 66, 3, 16, 15, 15, 5, 16, 17, 3, 16,184, 2,
+ 0, 64, 9, 4, 15, 14, 12, 5, 15, 15, 3, 15,184, 1,192, 64, 9, 4, 14, 13, 10, 5, 14, 12, 3, 14,184, 1,128, 64, 9, 4,
+ 13, 12, 9, 5, 13, 10, 3, 13,184, 1, 64,180, 4, 12, 9, 3, 12,184, 1, 0, 64, 55, 4, 11,254, 3, 10, 9, 22, 5, 10,254,
+ 3, 9, 22, 3, 8, 16, 3, 7,254, 3, 6, 1, 45, 5, 6,254, 3, 5, 20, 3, 3, 2, 58, 5, 3,250, 3, 2, 1, 45, 5, 2,
+ 58, 3, 1, 0, 16, 5, 1, 45, 3, 0, 16, 3, 1,184, 1,100,133,141, 1, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 0, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 29, 0,
+ 0};
+
diff --git a/source/blender/editors/datafiles/preview.blend.c b/source/blender/editors/datafiles/preview.blend.c
new file mode 100644
index 00000000000..63731e97342
--- /dev/null
+++ b/source/blender/editors/datafiles/preview.blend.c
@@ -0,0 +1,13952 @@
+/* DataToC output of file <preview_blend> */
+
+int datatoc_preview_blend_size= 446288;
+char datatoc_preview_blend[]= {
+ 66, 76, 69, 78, 68, 69, 82, 95, 86, 50, 52, 55, 82, 69, 78, 68,
+ 0, 0, 0, 32,191,255,241,160, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 20,112,114,101,118,105,101,119, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 76, 79, 66, 0, 0, 0, 32,191,255,241,144, 0, 0, 0,165,
+ 0, 0, 0, 1, 32, 32, 32, 53, 0, 5, 0, 0, 0,245, 0, 15, 0, 1, 1, 0, 7, 31,229,144, 7,159,144, 32, 0, 0, 0, 0,
+ 0, 0, 0, 64, 0, 0, 83, 82, 0, 0, 0,120, 7, 31,229,144, 0, 0, 0,160, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 83, 82,115, 99,114,101,101,110, 0, 45, 83, 99,114,105,112,116,105,110,103, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 29,221,112, 7, 31,232, 48, 7, 31,232,112, 7, 31,235,176, 7, 31,235,240,
+ 13, 64,121,112, 7,159,144, 32, 0, 0, 3,231, 1,143, 4,174, 3,232, 3, 32, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 10,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 20, 7, 29,221,112, 0, 0, 0,161,
+ 0, 0, 0, 1, 7, 31,230, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 20,
+ 7, 31,230, 48, 0, 0, 0,161, 0, 0, 0, 1, 7, 31,230,112, 7, 29,221,112, 0, 0, 0, 0, 0, 0, 3, 32, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0, 20, 7, 31,230,112, 0, 0, 0,161, 0, 0, 0, 1, 7, 31,230,176, 7, 31,230, 48, 0, 0, 0, 0,
+ 3,232, 3, 32, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 20, 7, 31,230,176, 0, 0, 0,161, 0, 0, 0, 1, 7, 31,230,240,
+ 7, 31,230,112, 0, 0, 0, 0, 3,232, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 20, 7, 31,230,240, 0, 0, 0,161,
+ 0, 0, 0, 1, 7, 31,231, 48, 7, 31,230,176, 0, 0, 0, 0, 0, 0, 3, 6, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 20,
+ 7, 31,231, 48, 0, 0, 0,161, 0, 0, 0, 1, 7, 31,231,112, 7, 31,230,240, 0, 0, 0, 0, 3,232, 3, 6, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0, 20, 7, 31,231,112, 0, 0, 0,161, 0, 0, 0, 1, 7, 31,231,176, 7, 31,231, 48, 0, 0, 0, 0,
+ 3, 32, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 20, 7, 31,231,176, 0, 0, 0,161, 0, 0, 0, 1, 7, 31,231,240,
+ 7, 31,231,112, 0, 0, 0, 0, 3, 32, 3, 6, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 20, 7, 31,231,240, 0, 0, 0,161,
+ 0, 0, 0, 1, 7, 31,232, 48, 7, 31,231,176, 0, 0, 0, 0, 1,236, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 20,
+ 7, 31,232, 48, 0, 0, 0,161, 0, 0, 0, 1, 0, 0, 0, 0, 7, 31,231,240, 0, 0, 0, 0, 1,236, 3, 6, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0, 24, 7, 31,232,112, 0, 0, 0,162, 0, 0, 0, 1, 7, 31,232,176, 0, 0, 0, 0, 7, 31,230, 48,
+ 7, 31,230,112, 0, 1, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 7, 31,232,176, 0, 0, 0,162, 0, 0, 0, 1,
+ 7, 31,232,240, 7, 31,232,112, 7, 31,230, 48, 7, 31,230,240, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24,
+ 7, 31,232,240, 0, 0, 0,162, 0, 0, 0, 1, 7, 31,233, 48, 7, 31,232,176, 7, 31,230,112, 7, 31,231, 48, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 7, 31,233, 48, 0, 0, 0,162, 0, 0, 0, 1, 7, 31,233,112, 7, 31,232,240,
+ 7, 31,230,240, 7, 31,231, 48, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 7, 31,233,112, 0, 0, 0,162,
+ 0, 0, 0, 1, 7, 31,233,176, 7, 31,233, 48, 7, 31,230,176, 7, 31,231,112, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0, 24, 7, 31,233,176, 0, 0, 0,162, 0, 0, 0, 1, 7, 31,233,240, 7, 31,233,112, 7, 31,231, 48, 7, 31,231,176,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 7, 31,233,240, 0, 0, 0,162, 0, 0, 0, 1, 7, 31,234, 48,
+ 7, 31,233,176, 7, 31,231,112, 7, 31,231,176, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 7, 31,234, 48,
+ 0, 0, 0,162, 0, 0, 0, 1, 7, 31,234,112, 7, 31,233,240, 7, 31,230,176, 7, 31,231, 48, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0, 24, 7, 31,234,112, 0, 0, 0,162, 0, 0, 0, 1, 7, 31,234,176, 7, 31,234, 48, 7, 29,221,112,
+ 7, 31,230,240, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 7, 31,234,176, 0, 0, 0,162, 0, 0, 0, 1,
+ 7, 31,234,240, 7, 31,234,112, 7, 29,221,112, 7, 31,231,240, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24,
+ 7, 31,234,240, 0, 0, 0,162, 0, 0, 0, 1, 7, 31,235, 48, 7, 31,234,176, 7, 31,231,112, 7, 31,231,240, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 7, 31,235, 48, 0, 0, 0,162, 0, 0, 0, 1, 7, 31,235,112, 7, 31,234,240,
+ 7, 31,230,240, 7, 31,232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 7, 31,235,112, 0, 0, 0,162,
+ 0, 0, 0, 1, 7, 31,235,176, 7, 31,235, 48, 7, 31,231,176, 7, 31,232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0, 24, 7, 31,235,176, 0, 0, 0,162, 0, 0, 0, 1, 0, 0, 0, 0, 7, 31,235,112, 7, 31,231,240, 7, 31,232, 48,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,204, 7, 31,235,240, 0, 0, 0,164, 0, 0, 0, 1, 13, 64, 24,144,
+ 0, 0, 0, 0, 7, 31,230,240, 7, 31,230, 48, 7, 31,230,112, 7, 31,231, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,232,
+ 0, 0, 3, 7, 0, 0, 3, 32, 0, 0, 0, 0, 0, 0, 3,232, 0, 0, 3, 7, 0, 0, 3, 33, 0, 0, 0, 0, 0, 0, 3,232,
+ 0, 0, 3, 32, 0, 0, 3, 32, 0, 5, 0, 4, 0, 1, 7, 7, 3,233, 0, 1, 1, 0, 1, 0, 2,189, 0, 0, 0, 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, 7, 22,196, 96, 7, 22,196, 96,
+ 7, 31,236,240, 13, 64, 23,128, 68, 65, 84, 65, 0, 0, 0,228, 7, 31,236,240, 0, 0, 0,163, 0, 0, 0, 1, 7, 31,238, 0,
+ 0, 0, 0, 0, 79,117,116,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 7, 31,238, 0, 0, 0, 0,163, 0, 0, 0, 1, 7, 31,239, 16, 7, 31,236,240, 82,101,110,100,
+101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,
+101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 70, 0, 0,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 7, 31,239, 16, 0, 0, 0,163, 0, 0, 0, 1, 7, 31,240, 32, 7, 31,238, 0, 65,110,105,109, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,140, 0, 0, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 7, 31,240, 32, 0, 0, 0,163,
+ 0, 0, 0, 1, 7, 31,241, 48, 7, 31,239, 16, 70,111,114,109, 97,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,210, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 7, 31,241, 48, 0, 0, 0,163, 0, 0, 0, 1, 7, 31,242, 64,
+ 7, 31,240, 32, 80,114,101,118,105,101,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 7, 31,242, 64, 0, 0, 0,163, 0, 0, 0, 1, 7, 31,243, 80, 7, 31,241, 48, 76, 97,109,112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 70, 0, 0,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 7, 31,243, 80, 0, 0, 0,163, 0, 0, 0, 1, 7, 31,244, 96, 7, 31,242, 64, 83,104, 97,100,111,119, 32, 97,110,100, 32, 83,
+112,111,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,140, 0, 0, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 7, 31,244, 96, 0, 0, 0,163,
+ 0, 0, 0, 1, 7, 31,245,112, 7, 31,243, 80, 84,101,120,116,117,114,101, 32, 97,110,100, 32, 73,110,112,117,116, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,210, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 7, 31,245,112, 0, 0, 0,163, 0, 0, 0, 1, 7, 31,246,128,
+ 7, 31,244, 96, 77, 97,112, 32, 84,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, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3,210, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 31,244, 96,
+ 68, 65, 84, 65, 0, 0, 0,228, 7, 31,246,128, 0, 0, 0,163, 0, 0, 0, 1, 7, 31,247,144, 7, 31,245,112, 80,114,101,118,
+105,101,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,
+114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 7, 31,247,144, 0, 0, 0,163, 0, 0, 0, 1, 7, 31,248,160, 7, 31,246,128, 76,105,110,107,115, 32, 97,110,100, 32, 80,105,
+112,101,108,105,110,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 70, 0, 0, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 7, 31,248,160, 0, 0, 0,163,
+ 0, 0, 0, 1, 7, 31,249,176, 7, 31,247,144, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,140, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 7, 31,249,176, 0, 0, 0,163, 0, 0, 0, 1, 7, 31,250,192,
+ 7, 31,248,160, 82, 97,109,112,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,140, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 31,248,160,
+ 68, 65, 84, 65, 0, 0, 0,228, 7, 31,250,192, 0, 0, 0,163, 0, 0, 0, 1, 7, 31,251,208, 7, 31,249,176, 83,104, 97,100,
+101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,
+114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,210, 0, 0,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 31,251,208, 68, 65, 84, 65, 0, 0, 0,228,
+ 7, 31,251,208, 0, 0, 0,163, 0, 0, 0, 1, 7, 31,252,224, 7, 31,250,192, 77,105,114,114,111,114, 32, 84,114, 97,110,115,
+112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,210, 0, 0, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 7, 31,252,224, 0, 0, 0,163,
+ 0, 0, 0, 1, 7, 31,253,240, 7, 31,251,208, 84,101,120,116,117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 24, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 7, 31,253,240, 0, 0, 0,163, 0, 0, 0, 1, 7, 31,255, 0,
+ 7, 31,252,224, 77, 97,112, 32, 73,110,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 24, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 31,252,224,
+ 68, 65, 84, 65, 0, 0, 0,228, 7, 31,255, 0, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 0, 32, 7, 31,253,240, 77, 97,112, 32,
+ 84,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, 77, 97,116,101,
+114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 24, 0, 0,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 31,252,224, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 0, 32, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 1, 48, 7, 31,255, 0, 76,105,110,107, 32, 97,110,100, 32, 77, 97,116,
+101,114,105, 97,108,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 1, 48, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 2, 64, 13, 64, 0, 32, 77,101,115,104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 70, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 2, 64, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 3, 80,
+ 13, 64, 1, 48, 77,111,100,105,102,105,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,140, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 3, 80, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 4, 96, 13, 64, 2, 64, 83,104, 97,112,
+101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,
+105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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,140, 0, 0,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64, 2, 64, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 4, 96, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 5,112, 13, 64, 3, 80, 77,101,115,104, 32, 84,111,111,108,115, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,210, 0, 0, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 5,112, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 6,128, 13, 64, 4, 96, 77,101,115,104, 32, 84,111,111,108,115, 32, 49, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 24, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 6,128, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 7,144,
+ 13, 64, 5,112, 80,114,101,118,105,101,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 87,111,114,108,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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 7,144, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 8,160, 13, 64, 6,128, 87,111,114,108,
+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, 87,111,114,108,
+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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 70, 0, 0,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 8,160, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 9,176, 13, 64, 7,144, 77,105,115,116, 32, 47, 32, 83,116, 97,114,115,
+ 32, 47, 32, 80,104,121,115,105, 99,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87,111,114,108,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,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,140, 0, 0, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 9,176, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 10,192, 13, 64, 8,160, 65,109, 98, 32, 79, 99, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87,111,114,108,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, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,140, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 64, 8,160, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 10,192, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 11,208,
+ 13, 64, 9,176, 84,101,120,116,117,114,101, 32, 97,110,100, 32, 73,110,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 87,111,114,108,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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3,210, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 11,208, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 12,224, 13, 64, 10,192, 77, 97,112, 32,
+ 84,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, 87,111,114,108,
+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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,210, 0, 0,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64, 10,192, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 12,224, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 13,240, 13, 64, 11,208, 80,114,101,118,105,101,119, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,101,120,116,117,114,101, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 13,240, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 15, 0, 13, 64, 12,224, 84,101,120,116,117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,101,120,116,117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 70, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 15, 0, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 16, 16,
+ 13, 64, 13,240, 67,111,108,111,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,101,120,116,117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 70, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64, 13,240,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 16, 16, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 17, 32, 13, 64, 15, 0, 79, 98,106,101,
+ 99,116, 32, 97,110,100, 32, 76,105,110,107,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 98,106,101,
+ 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 17, 32, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 18, 48, 13, 64, 16, 16, 65,110,105,109, 32,115,101,116,116,105,110,103,
+115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 70, 0, 0, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 18, 48, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 19, 64, 13, 64, 17, 32, 68,114, 97,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,140, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 19, 64, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 20, 80,
+ 13, 64, 18, 48, 67,111,110,115,116,114, 97,105,110,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3,210, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 20, 80, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 21, 96, 13, 64, 19, 64, 67,108,111,117,
+100,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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,101,120,116,
+117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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,140, 0, 0,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 21, 96, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 22,112, 13, 64, 20, 80, 83,116,117, 99, 99,105, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,101,120,116,117,114,101, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,140, 0, 0, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 22,112, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 23,128, 13, 64, 21, 96, 87,111,111,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, 84,101,120,116,117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,140, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 23,128, 0, 0, 0,163, 0, 0, 0, 1, 0, 0, 0, 0,
+ 13, 64, 22,112, 82,101,110,100,101,114, 32, 76, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 31,236,240,
+ 68, 65, 84, 65, 0, 0, 0,204, 13, 64, 24,144, 0, 0, 0,164, 0, 0, 0, 1, 13, 64, 96, 96, 7, 31,235,240, 7, 31,231,112,
+ 7, 31,231,176, 7, 31,231, 48, 7, 31,230,176, 0, 0, 0, 0, 63,140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 65, 45, 68,171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191,128, 1, 80,191,128, 0, 0,
+128, 0, 0, 0,128, 0, 0, 0,188,163,215,226,128, 0, 0, 0, 0, 0, 3, 33, 0, 0, 3,232, 0, 0, 0, 0, 0, 0, 3, 5,
+ 0, 0, 3, 33, 0, 0, 3,232, 0, 0, 2,235, 0, 0, 3, 5, 0, 0, 3, 33, 0, 0, 3,232, 0, 0, 0, 0, 0, 0, 2,234,
+ 0, 7, 0, 6, 0, 2, 4, 4, 0,200, 2,235, 1, 0, 1, 0, 1, 76, 0, 4, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 64, 86, 32, 13, 64, 94,112, 7, 27,181,240, 7, 27,222,144, 13, 64, 25,144, 13, 64, 85, 16,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 25,144, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 26,160, 0, 0, 0, 0, 84,114, 97,110,
+115,102,111,114,109, 32, 80,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73,112,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, 33, 0,167,
+ 1, 62, 0,204, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 26,160, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 27,176, 13, 64, 25,144, 79,117,116,112,117,116, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64, 59,144, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 27,176, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 28,192, 13, 64, 26,160, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 24, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 28,192, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 29,208,
+ 13, 64, 27,176, 65,110,105,109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,254, 48, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 29,208, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 30,224, 13, 64, 28,192, 70,111,114,109,
+ 97,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,
+101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,253, 72,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 30,224, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 31,240, 13, 64, 29,208, 76,105,110,107, 32, 97,110,100, 32, 77, 97,116,
+101,114,105, 97,108,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 62, 0,204, 0, 0, 0, 1,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 31,240, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 33, 0, 13, 64, 30,224, 67, 97,109,101,114, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 24, 1, 62, 0,204, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 4, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 33, 0, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 34, 16,
+ 13, 64, 31,240, 80,114,101,118,105,101,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 34, 16, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 35, 32, 13, 64, 33, 0, 76, 97,109,112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 24,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 35, 32, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 36, 48, 13, 64, 34, 16, 83,104, 97,100,111,119, 32, 97,110,100, 32, 83,
+112,111,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254, 28, 1, 62, 0,224, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64, 85, 16, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 36, 48, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 37, 64, 13, 64, 35, 32, 84,101,120,116,117,114,101, 32, 97,110,100, 32, 73,110,112,117,116, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,253, 72, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 37, 64, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 38, 80,
+ 13, 64, 36, 48, 77, 97,112, 32, 84,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, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,253, 72, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64, 36, 48,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 38, 80, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 39, 96, 13, 64, 37, 64, 77,101,115,104,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,
+105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 24,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 39, 96, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 40,112, 13, 64, 38, 80, 77,111,100,105,102,105,101,114,115, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,253, 72, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 40,112, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 41,128, 13, 64, 39, 96, 83,104, 97,112,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,253, 72, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 64, 39, 96, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 41,128, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 42,144,
+ 13, 64, 40,112, 77,101,115,104, 32, 84,111,111,108,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,253, 72, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 42,144, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 43,160, 13, 64, 41,128, 77,101,115,104,
+ 32, 84,111,111,108,115, 32, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,
+105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 96,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 43,160, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 44,176, 13, 64, 42,144, 84,101,120,116,117,114,101, 32,102, 97, 99,101,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64, 44,176, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 44,176, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 45,192, 13, 64, 43,160, 85, 86, 32, 67, 97,108, 99,117,108, 97,116,105,111,110, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 45,192, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 46,208,
+ 13, 64, 44,176, 80, 97,105,110,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,254, 48, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 46,208, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 47,224, 13, 64, 45,192, 67,117,114,118,
+101, 32, 97,110,100, 32, 83,117,114,102, 97, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,
+105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 47,224, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 48,240, 13, 64, 46,208, 67,117,114,118,101, 32, 84,111,111,108,115, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 24, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 48,240, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 50, 0, 13, 64, 47,224, 67,117,114,118,101, 32, 84,111,111,108,115, 49, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,253, 72, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 50, 0, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 51, 16,
+ 13, 64, 48,240, 80,114,101,118,105,101,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 51, 16, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 52, 32, 13, 64, 50, 0, 76,105,110,107,
+115, 32, 97,110,100, 32, 80,105,112,101,108,105,110,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,
+114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 24,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 52, 32, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 53, 48, 13, 64, 51, 16, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254, 48, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 53, 48, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 54, 64, 13, 64, 52, 32, 82, 97,109,112,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254, 48, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 64, 52, 32, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 54, 64, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 55, 80,
+ 13, 64, 53, 48, 83,104, 97,100,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,253, 52, 1, 62, 0,224, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64, 55, 80,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 55, 80, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 56, 96, 13, 64, 54, 64, 77,105,114,114,
+111,114, 32, 84,114, 97,110,115,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,
+114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252,248,
+ 1, 62, 1, 28, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 56, 96, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 57,112, 13, 64, 55, 80, 84,101,120,116,117,114,101, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 16, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64, 57,112, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 57,112, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 58,128, 13, 64, 56, 96, 77, 97,112, 32, 73,110,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 16, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 58,128, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 59,144,
+ 13, 64, 57,112, 77, 97,112, 32, 84,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, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,252, 16, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64, 57,112,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 59,144, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 60,160, 13, 64, 58,128, 82,101,110,100,
+101,114, 32, 76, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,
+101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 60,160, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 61,176, 13, 64, 59,144, 80,114,101,118,105,101,119, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87,111,114,108,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,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254, 48, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 61,176, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 62,192, 13, 64, 60,160, 87,111,114,108,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, 87,111,114,108,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, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,253, 72, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 62,192, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 63,208,
+ 13, 64, 61,176, 77,105,115,116, 32, 47, 32, 83,116, 97,114,115, 32, 47, 32, 80,104,121,115,105, 99,115, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 87,111,114,108,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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 63,208, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 64,224, 13, 64, 62,192, 65,109, 98, 32,
+ 79, 99, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87,111,114,108,
+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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64, 62,192, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 64,224, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 65,240, 13, 64, 63,208, 84,101,120,116,117,114,101, 32, 97,110,100, 32,
+ 73,110,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87,111,114,108,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,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 24, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 65,240, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 67, 0, 13, 64, 64,224, 77, 97,112, 32, 84,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, 87,111,114,108,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, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 24, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 64, 64,224, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 67, 0, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 68, 16,
+ 13, 64, 65,240, 77,117,108,116,105,114,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,254, 48, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 68, 16, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 69, 32, 13, 64, 67, 0, 79, 98,106,101,
+ 99,116, 32, 97,110,100, 32, 76,105,110,107,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 98,106,101,
+ 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 69, 32, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 70, 48, 13, 64, 68, 16, 65,110,105,109, 32,115,101,116,116,105,110,103,
+115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 24, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 70, 48, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 71, 64, 13, 64, 69, 32, 68,114, 97,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254, 48, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 71, 64, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 72, 80,
+ 13, 64, 70, 48, 67,111,110,115,116,114, 97,105,110,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,253, 72, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 72, 80, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 73, 96, 13, 64, 71, 64, 66, 97,107,101,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,
+101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254, 48,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64, 28,192, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 73, 96, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 74,112, 13, 64, 72, 80, 83,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,253, 72, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64, 29,208, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 74,112, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 75,128, 13, 64, 73, 96, 80, 97,114,116,105, 99,108,101, 32, 83,121,115,116,101,109, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 97,114,116,105, 99,108,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 75,128, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 76,144,
+ 13, 64, 74,112, 80,104,121,115,105, 99,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 80, 97,114,116,105, 99,108,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,255, 24, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 76,144, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 77,160, 13, 64, 75,128, 86,105,115,117,
+ 97,108,105,122, 97,116,105,111,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 97,114,116,
+105, 99,108,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254, 48,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 77,160, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 78,176, 13, 64, 76,144, 69,120,116,114, 97,115, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 97,114,116,105, 99,108,101, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,253, 72, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 78,176, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 79,192, 13, 64, 77,160, 67,104,105,108,100,114,101,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 97,114,116,105, 99,108,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,253, 72, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 64, 77,160, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 79,192, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 80,208,
+ 13, 64, 78,176, 80,114,101,118,105,101,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,101,120,116,117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,254, 48, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 80,208, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 81,224, 13, 64, 79,192, 84,101,120,116,
+117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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,101,120,116,
+117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64, 81,224, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 82,240, 13, 64, 80,208, 67,111,108,111,114,115, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,101,120,116,117,114,101, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64, 80,208, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 82,240, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64, 84, 0, 13, 64, 81,224, 87,111,111,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, 84,101,120,116,117,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 24, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 84, 0, 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 85, 16,
+ 13, 64, 82,240, 83, 83, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,253, 72, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64, 55, 80,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 85, 16, 0, 0, 0,163, 0, 0, 0, 1, 0, 0, 0, 0, 13, 64, 84, 0, 83,107,121, 47,
+ 65,116,109,111,115,112,104,101,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254, 48,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,220,
+ 13, 64, 86, 32, 0, 0, 0,142, 0, 0, 0, 1, 7,159,132, 32, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 13, 64, 24,144,
+ 0, 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, 0, 0,193, 0, 0, 0,
+ 67,163, 0, 0,196, 48, 0, 0, 67,104, 0, 0,193, 0, 0, 0, 67,163, 0, 0,196,125,223, 92, 67,104, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,128, 0, 0, 66, 40, 0, 0, 69, 0, 0, 0, 67,225, 0, 0, 63, 0, 0, 0,
+ 63,154,225, 72, 0, 0, 0, 1, 0, 1, 0, 1, 0,200, 2,235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 4, 0, 1, 0, 0, 0, 4, 13, 64,160, 96,255,255, 0, 0, 0, 0, 0, 0, 1,150, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 3, 0, 0, 0, 68, 65, 84, 65, 0, 0, 3, 4, 7,159,132, 32, 0, 0, 0,137, 0, 0, 0, 1, 13, 64, 87, 48,
+ 13, 64, 86, 32, 0, 0, 0, 1, 63, 51, 51, 51, 13, 64, 24,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,127,198, 52,188,166, 29,146, 61, 22,153, 97, 0, 0, 0, 0, 61, 43,252, 13, 62,247, 11, 89,191, 95,248, 90, 0, 0, 0, 0,
+ 52, 67,176,196, 63, 96, 42,246, 62,247, 67, 44, 0, 0, 0, 0, 64, 78, 45, 74, 62,172, 87,201,194, 41,171, 79, 63,128, 0, 0,
+ 63,127,198, 53, 61, 43,251,248, 52, 80, 0, 0, 0, 0, 0, 0,188,166, 29,186, 62,247, 11,119, 63, 96, 43, 16, 0, 0, 0, 0,
+ 61, 22,153, 99,191, 95,248,117, 62,247, 67, 75, 0, 0, 0, 0,191,211,125,192,194, 21,161,185, 65,161,133, 59, 63,128, 0, 0,
+ 63,139,224,100,190, 96,221, 21,189, 22,154,236,189, 22,153, 97, 61, 60, 27,174, 64,167, 52,239, 63, 95,250,166, 63, 95,248, 90,
+ 52, 86, 9, 86, 65, 23,185, 41,190,247, 69,181,190,247, 67, 44, 64, 97,129,137, 64,105, 75, 27, 66, 41,152,145, 66, 41,171, 79,
+ 63,105,225, 95, 61, 39,247, 84,186,185, 46,176,184,146,196,144,186,245,126,178, 61, 54,117, 48, 61,165,157, 23, 52,153,160, 0,
+ 66,165, 56,225, 68,233,202,192,196,124, 94, 18,194, 71,254, 87,194,165, 77,102,196,233,177, 39, 68,124, 65,193, 66, 72, 0,101,
+ 63,140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 45, 68,171, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,191,128, 1, 80,191,128, 0, 0,128, 0, 0, 0,128, 0, 0, 0,188,163,215,226,128, 0, 0, 0,
+ 63,127,198, 52,188,166, 29,146, 61, 22,153, 97, 0, 0, 0, 0, 61, 43,252, 13, 62,247, 11, 89,191, 95,248, 90, 0, 0, 0, 0,
+ 52, 67,176,196, 63, 96, 42,246, 62,247, 67, 44, 0, 0, 0, 0, 64, 78, 45, 74, 62,172, 87,201,194, 41,171, 79, 63,128, 0, 0,
+ 63, 92, 99,141,191, 2, 35, 43,188, 46,238,188,188,148, 32, 94, 66, 25,240, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 7,159,156, 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, 2, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 2, 0, 1, 0, 0,255,226, 0, 0, 66, 12, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 58,124, 56, 68,
+ 60, 35,215, 10, 67,250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 68, 77,201, 64,111, 66,228,191,205, 97,230, 60,149,191,128,
+191, 77,109,116, 63,230,165,248, 0, 20, 0, 0, 0, 7, 0, 99, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,255,255, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 1, 88, 13, 64, 87, 48, 0, 0, 0,141, 0, 0, 0, 1, 13, 64, 88,176, 7,159,132, 32, 0, 0, 0, 2,
+ 63, 51, 51, 51, 13, 64, 24,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 67,122, 0, 0,189,204,204,205, 63,140,204,205, 63,128, 0, 0, 67,122, 0, 0,192,160, 0, 0, 64,160, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 2,235, 0, 0, 0, 16, 0, 0, 3,168, 0, 0, 0, 0, 0, 0, 0, 16,
+ 0, 0, 0, 16, 0, 0, 3,168, 0, 0, 0, 16, 0, 0, 2,235, 60, 35,215, 10, 60, 35,215, 10, 70,106, 96, 0, 68,122, 0, 0,
+ 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,159,184, 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, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0,
+ 0, 0, 0, 0, 0, 0, 79, 66, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 67,122, 0, 0,189,204,204,205, 63,140,204,205, 68, 65, 84, 65, 0, 0, 0,128, 13, 64, 88,176, 0, 0, 0,148, 0, 0, 0, 1,
+ 13, 64, 89, 96, 13, 64, 87, 48, 0, 0, 0, 9, 63, 51, 51, 51, 13, 64, 24,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 64,194,224, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61,204,204,205, 0, 0, 0, 5, 0, 0, 0, 17,
+ 0, 0, 2,225, 0, 0, 2,227, 0, 0, 0, 5, 0, 0, 0, 17, 0, 0, 2,207, 0, 0, 2,227, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 1, 8, 13, 64, 89, 96, 0, 0, 0,146, 0, 0, 0, 1, 13, 64, 90,144, 13, 64, 88,176, 0, 0, 0, 6,
+ 63, 51, 51, 51, 13, 64, 24,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,128, 0, 0,
+ 0, 0, 0, 0, 67,128, 0, 0,190,120, 0, 0, 63,159, 0, 0,190,242, 0, 0, 63,188,128, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 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,124,
+ 0, 0, 0, 0, 0, 0, 1,242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 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,
+ 0, 0, 1, 8, 13, 64, 90,144, 0, 0, 0,145, 0, 0, 0, 1, 13, 64, 91,192, 13, 64, 89, 96, 0, 0, 0, 3, 63, 51, 51, 51,
+ 13, 64, 24,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,182, 0, 0,195,209, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 67,182, 0, 0,195,190, 0, 0,181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0,
+ 0, 0, 1,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 1,124, 0, 0, 0, 0,
+ 0, 0, 1,124,195,190, 0, 0,195,190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 1, 0, 1,
+ 0, 1, 0, 1, 1,108, 1,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 3,142, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 0, 0, 0,176,
+ 13, 64, 91,192, 0, 0, 0,230, 0, 0, 0, 1, 13, 64, 92,160, 13, 64, 90,144, 0, 0, 0, 11, 63, 51, 51, 51, 13, 64, 24,144,
+192,128, 0, 0, 67,122, 0, 0,192,128, 0, 0, 67,127, 0, 0,192,128, 0, 0, 66, 72, 0, 0,192,128, 0, 0, 67,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, 1,124, 0, 0, 0, 0, 0, 0, 0, 16,
+ 0, 0, 0, 0, 0, 0, 1,124, 0, 0, 0, 16, 0, 0, 1,124, 63,128, 0, 0, 67,129,128, 0, 70,250, 0, 0, 67,129,128, 0,
+ 61,204,204,205, 65, 32, 0, 0, 0, 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, 68, 65, 84, 65,
+ 0, 0, 0,180, 13, 64, 92,160, 0, 0, 0,147, 0, 0, 0, 1, 13, 64, 93,128, 13, 64, 91,192, 0, 0, 0, 13, 63, 51, 51, 51,
+ 13, 64, 24,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 68,122, 0, 0, 0, 0, 0, 0, 68,122, 0, 0,192,160, 0, 0, 66,130, 0, 0, 0, 0, 0, 0, 67,182, 0, 0, 0, 0, 1,108,
+ 0, 0, 1,124, 0, 0, 0, 0, 0, 0, 1,124, 0, 0, 0,196, 0, 0, 1,108, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,196,
+ 0, 0, 1,108, 0, 0, 0, 16, 0, 0, 1,124, 0, 0, 0, 0, 0, 0, 0, 0, 68,122, 0, 0, 68,122, 0, 0, 61,204,204,205,
+ 66, 72, 0, 0, 0, 10, 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, 68, 65, 84, 65, 0, 0, 0,192, 13, 64, 93,128, 0, 0, 0,240, 0, 0, 0, 1, 13, 64, 94,112, 13, 64, 92,160,
+ 0, 0, 0, 12, 63, 51, 51, 51, 13, 64, 24,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 0, 0, 0,
+ 66, 2, 0, 0,196,122, 0, 0, 0, 0, 0, 0,191, 0, 0, 0, 66, 2, 0, 0,194,150, 0, 0, 64,160, 0, 0, 0, 0, 1,108,
+ 0, 0, 1,124, 0, 0, 0, 0, 0, 0, 2, 14, 0, 0, 0,128, 0, 0, 1,108, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,128,
+ 0, 0, 1,108, 0, 0, 0, 16, 0, 0, 2, 14, 0, 0, 0, 0, 0, 0, 0, 0, 70,250, 0, 0, 68,122, 0, 0, 60, 35,215, 10,
+ 66, 72, 0, 0, 0, 10, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1,200,
+ 13, 64, 94,112, 0, 0, 0,144, 0, 0, 0, 1, 0, 0, 0, 0, 13, 64, 93,128, 0, 0, 0, 5, 63, 51, 51, 51, 13, 64, 24,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,150, 83, 97,118,101, 32, 70,105,108,
+101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 85,115,101,114,115, 47,116,111,110, 47, 68,101,115,107,116,
+111,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, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+112,114,101,118,105,101,119, 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, 8, 0, 82, 0, 0, 0, 0, 1, 76, 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,255,255, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0,204, 13, 64, 96, 96,
+ 0, 0, 0,164, 0, 0, 0, 1, 13, 64,121,112, 13, 64, 24,144, 7, 31,231,240, 7, 31,232, 48, 7, 31,231,176, 7, 31,231,112,
+ 0, 0, 0, 0, 63,238, 38, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,140, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191,128, 1, 80,191,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,188,163,215,225,
+ 0, 0, 0, 0, 0, 0, 1,237, 0, 0, 3, 31, 0, 0, 0, 0, 0, 0, 3, 5, 0, 0, 1,237, 0, 0, 3, 31, 0, 0, 0, 0,
+ 0, 0, 0, 26, 0, 0, 1,237, 0, 0, 3, 31, 0, 0, 0, 27, 0, 0, 3, 5, 0, 9, 0, 8, 0, 1, 6, 6, 1, 51, 2,235,
+ 1, 0, 1, 0, 0,220, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64,111, 48,
+ 13, 64,119,128, 7, 23, 59,224, 7, 23, 59,224, 13, 64, 97, 96, 13, 64,110, 32, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 97, 96,
+ 0, 0, 0,163, 0, 0, 0, 1, 13, 64, 98,112, 0, 0, 0, 0, 84,114, 97,110,115,102,111,114,109, 32, 80,114,111,112,101,114,
+116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73,112,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, 33, 0,167, 1, 62, 0,204, 0, 0, 0, 0, 0,162, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 98,112, 0, 0, 0,163, 0, 0, 0, 1,
+ 13, 64, 99,128, 13, 64, 97, 96, 79,117,116,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64, 99,128, 0, 0, 0,163, 0, 0, 0, 1, 13, 64,100,144, 13, 64, 98,112,
+ 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 64, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,228, 13, 64,100,144, 0, 0, 0,163, 0, 0, 0, 1, 13, 64,101,160, 13, 64, 99,128, 65,110,105,109, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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,128, 0, 0, 1, 62, 0,204,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64,101,160,
+ 0, 0, 0,163, 0, 0, 0, 1, 13, 64,102,176, 13, 64,100,144, 70,111,114,109, 97,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,192, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64,102,176, 0, 0, 0,163, 0, 0, 0, 1,
+ 13, 64,103,192, 13, 64,101,160, 76,105,110,107, 32, 97,110,100, 32, 77, 97,116,101,114,105, 97,108,115, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64,103,192, 0, 0, 0,163, 0, 0, 0, 1, 13, 64,104,208, 13, 64,102,176,
+ 67, 97,109,101,114, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 69,100,105,116,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 64, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,228, 13, 64,104,208, 0, 0, 0,163, 0, 0, 0, 1, 13, 64,105,224, 13, 64,103,192, 80,114,101,118,105,101,119, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 62, 0,204,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64,105,224,
+ 0, 0, 0,163, 0, 0, 0, 1, 13, 64,106,240, 13, 64,104,208, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 24, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64,106,240, 0, 0, 0,163, 0, 0, 0, 1,
+ 13, 64,108, 0, 13, 64,105,224, 83,104, 97,100,111,119, 32, 97,110,100, 32, 83,112,111,116, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254, 48, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64,108, 0, 0, 0, 0,163, 0, 0, 0, 1, 13, 64,109, 16, 13, 64,106,240,
+ 84,101,120,116,117,114,101, 32, 97,110,100, 32, 73,110,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,253, 72, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,228, 13, 64,109, 16, 0, 0, 0,163, 0, 0, 0, 1, 13, 64,110, 32, 13, 64,108, 0, 77, 97,112, 32, 84,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, 76, 97,109,112, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,253, 72, 1, 62, 0,204,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64,108, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64,110, 32,
+ 0, 0, 0,163, 0, 0, 0, 1, 0, 0, 0, 0, 13, 64,109, 16, 84,114, 97,110,115,102,111,114,109, 32, 80,114,111,112,101,114,
+116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86,105,101,119, 51,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, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,228, 1, 62, 0,204, 0, 0, 0, 0, 0,162, 0, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 8, 13, 64,111, 48, 0, 0, 0,146, 0, 0, 0, 1,
+ 7,159,136, 32, 0, 0, 0, 0, 0, 0, 0, 6, 63, 51, 51, 51, 13, 64, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 67,128, 0, 0, 0, 0, 0, 0, 67,128, 0, 0,189,204, 0, 0, 63,140,192, 0,191,117,128, 0,
+ 63,250,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 51, 0, 0, 0, 0, 0, 0, 2,235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 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, 0, 0, 3, 4, 7,159,136, 32, 0, 0, 0,137, 0, 0, 0, 1, 13, 64,112, 96,
+ 13, 64,111, 48, 0, 0, 0, 1, 63, 51, 51, 51, 13, 64, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63, 64, 75, 54, 62,191,102,119,191, 11, 73, 11, 0, 0, 0, 0,191, 40,254,108, 62,217,202, 94,191, 30,124,246, 0, 0, 0, 0,
+180,186, 33,218, 63, 82,254,184, 63, 16,248,193, 0, 0, 0, 0, 62, 8,228, 73,192, 33,158, 72,193,210,148,125, 63,128, 0, 0,
+ 63, 64, 75, 68,191, 40,254,161, 54, 58,221,101, 0, 0, 0, 0, 62,191,103, 10, 62,217,202,178, 63, 82,255, 4, 0, 0, 0, 0,
+191, 11, 73, 20,191, 30,125, 78, 63, 16,248,219, 0, 0, 0, 0,193, 87,166, 3,193,114, 36, 19, 65,135,230,213, 63,128, 0, 0,
+ 63,178,226,132, 62,209, 88, 18, 63, 11, 74,121, 63, 11, 73, 11,191,157, 53,169, 62,238, 53, 87, 63, 30,126,150, 63, 30,124,246,
+181, 45, 39, 38, 63,102,198,153,191, 16,250, 62,191, 16,248,193, 62,126,177, 46,192, 48,197, 31, 65,210,109,176, 65,210,148,125,
+ 62,206,202,119,190,181,145,194,185, 84, 1, 62,183, 73, 79,188, 62,174,236, 32, 62,199, 10,100, 63, 64,245, 33, 55, 52,160, 0,
+ 68, 40, 79, 84, 68, 60,252,158,196, 84, 35, 68,194, 71,205,165,196, 40, 46, 68,196, 60,214,248, 68, 84, 1, 62, 66, 71,207,188,
+ 63,238, 38, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,191,128, 1, 80,191,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,188,163,215,225, 0, 0, 0, 0,
+ 63, 64, 75, 54, 62,191,102,119,191, 11, 73, 11, 0, 0, 0, 0,191, 40,254,108, 62,217,202, 94,191, 30,124,246, 0, 0, 0, 0,
+180,186, 33,218, 63, 82,254,184, 63, 16,248,193, 0, 0, 0, 0, 62, 8,228, 73,192, 33,158, 72,193,210,148,125, 63,128, 0, 0,
+ 63, 83,252, 84,190,223, 25,104, 62, 40, 52,115, 62,159,211,119, 65,198,183, 96, 65,198,183, 96, 0, 0, 0, 0, 0, 1, 0, 0,
+ 7,159,156, 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, 2, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 2, 0, 1, 0, 0,255,251, 0, 0, 66, 12, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 58,213,207,174,
+ 60, 35,215, 10, 67,250, 0, 0,188,218, 18,228,188, 23,180, 37,189, 22,146,163,190,122, 51,174,192, 58,244, 29, 54,224, 0, 0,
+ 63, 88,146, 56, 64, 71, 37,198, 0, 20, 0, 0, 0, 7, 0,115, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,255,255, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,220, 13, 64,112, 96, 0, 0, 0,142, 0, 0, 0, 1, 13, 64,113,112, 7,159,136, 32, 0, 0, 0, 4,
+ 0, 0, 0, 0, 13, 64, 96, 96, 0, 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, 0, 4, 0, 0, 0, 0, 68,160, 0, 0,196, 46, 0, 0, 67,100, 0, 0, 55,136,197,197, 68, 78,209,118,195,231,222, 40,
+ 67, 25,158,172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,128, 0, 0, 66, 40, 0, 0, 69, 0, 0, 0,
+ 67,225, 0, 0, 63, 0, 0, 0, 63,154,225, 72, 0, 0, 0, 1, 0, 1, 0, 1, 3,233, 2,235, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 0, 0,
+ 1,150, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 88, 13, 64,113,112, 0, 0, 0,141,
+ 0, 0, 0, 1, 13, 64,114,240, 13, 64,112, 96, 0, 0, 0, 2, 63, 51, 51, 51, 13, 64, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,122, 0, 0,189,204,204,205, 63,140,204,205,
+ 63,128, 0, 0, 67,122, 0, 0,192,160, 0, 0, 64,160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 2,235,
+ 0, 0, 0, 16, 0, 0, 3,168, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 3,168, 0, 0, 0, 16, 0, 0, 2,235,
+ 60, 35,215, 10, 60, 35,215, 10, 70,106, 96, 0, 68,122, 0, 0, 0, 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, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 7,159,184, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,122, 0, 0,189,204,204,205, 63,140,204,205, 68, 65, 84, 65,
+ 0, 0, 0,128, 13, 64,114,240, 0, 0, 0,148, 0, 0, 0, 1, 13, 64,115,160, 13, 64,113,112, 0, 0, 0, 9, 63, 51, 51, 51,
+ 13, 64, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64,194,224, 0, 0, 0, 0, 0, 0, 0, 62,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 61,204,204,205, 0, 0, 0, 5, 0, 0, 0, 17, 0, 0, 2,225, 0, 0, 2,227, 0, 0, 0, 5, 0, 0, 0, 17,
+ 0, 0, 2,207, 0, 0, 2,227, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 8, 13, 64,115,160, 0, 0, 0,145,
+ 0, 0, 0, 1, 13, 64,116,208, 13, 64,114,240, 0, 0, 0, 3, 63, 51, 51, 51, 13, 64, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,182, 0, 0,195,209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,182, 0, 0,
+195,190, 0, 0,181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 1,124, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 1,124, 0, 0, 0, 0, 0, 0, 1,124,195,190, 0, 0,195,190, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1,108, 1,124, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,142, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0,176, 13, 64,116,208, 0, 0, 0,230, 0, 0, 0, 1,
+ 13, 64,117,176, 13, 64,115,160, 0, 0, 0, 11, 63, 51, 51, 51, 13, 64, 96, 96,192,128, 0, 0, 67,122, 0, 0,192,128, 0, 0,
+ 67,127, 0, 0,192,128, 0, 0, 66, 72, 0, 0,192,128, 0, 0, 67,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, 1,124, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 1,124, 0, 0, 0, 16,
+ 0, 0, 1,124, 63,128, 0, 0, 67,129,128, 0, 70,250, 0, 0, 67,129,128, 0, 61,204,204,205, 65, 32, 0, 0, 0, 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, 68, 65, 84, 65, 0, 0, 0,180, 13, 64,117,176, 0, 0, 0,147,
+ 0, 0, 0, 1, 13, 64,118,144, 13, 64,116,208, 0, 0, 0, 13, 63, 51, 51, 51, 13, 64, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 68,122, 0, 0, 0, 0, 0, 0, 68,122, 0, 0,
+192,160, 0, 0, 66,130, 0, 0, 0, 0, 0, 0, 67,182, 0, 0, 0, 0, 1,108, 0, 0, 1,124, 0, 0, 0, 0, 0, 0, 1,124,
+ 0, 0, 0,196, 0, 0, 1,108, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,196, 0, 0, 1,108, 0, 0, 0, 16, 0, 0, 1,124,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68,122, 0, 0, 68,122, 0, 0, 61,204,204,205, 66, 72, 0, 0, 0, 10, 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, 68, 65, 84, 65, 0, 0, 0,192,
+ 13, 64,118,144, 0, 0, 0,240, 0, 0, 0, 1, 13, 64,119,128, 13, 64,117,176, 0, 0, 0, 12, 63, 51, 51, 51, 13, 64, 96, 96,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 0, 0, 0, 66, 2, 0, 0,196,122, 0, 0, 0, 0, 0, 0,
+191, 0, 0, 0, 66, 2, 0, 0,194,150, 0, 0, 64,160, 0, 0, 0, 0, 1,108, 0, 0, 1,124, 0, 0, 0, 0, 0, 0, 2, 14,
+ 0, 0, 0,128, 0, 0, 1,108, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,128, 0, 0, 1,108, 0, 0, 0, 16, 0, 0, 2, 14,
+ 0, 0, 0, 0, 0, 0, 0, 0, 70,250, 0, 0, 68,122, 0, 0, 60, 35,215, 10, 66, 72, 0, 0, 0, 10, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1,200, 13, 64,119,128, 0, 0, 0,144, 0, 0, 0, 1,
+ 0, 0, 0, 0, 13, 64,118,144, 0, 0, 0, 5, 63, 51, 51, 51, 13, 64, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 83, 97,118,101, 32, 70,105,108,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 47, 85,115,101,114,115, 47,116,111,110, 47, 68,101,115,107,116,111,112, 47, 0,114, 47,114,101,108,101, 97,115,
+101, 47,100, 97,116, 97,102,105,108,101,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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,112,114,101,118,105,101,119, 46, 98,108,101,110,
+100, 0, 0, 0, 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, 8, 0, 46, 0, 0, 0, 0, 1, 85, 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, 72, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0,204, 13, 64,121,112, 0, 0, 0,164, 0, 0, 0, 1, 0, 0, 0, 0,
+ 13, 64, 96, 96, 7, 29,221,112, 7, 31,230,240, 7, 31,232, 48, 7, 31,231,240, 0, 0, 0, 0, 63,157, 86,198, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 79, 65,252, 0, 0, 0, 0, 0, 0, 0, 0,189, 60, 82,166,188,131, 1,237,
+191,153,213,185,191,128, 0, 0,128, 0, 0, 0,128, 0, 0, 0,193, 65,194,239,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,235,
+ 0, 0, 0, 0, 0, 0, 3, 5, 0, 0, 0, 0, 0, 0, 1,235, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 1,235,
+ 0, 0, 0, 27, 0, 0, 3, 5, 0, 11, 0, 10, 0, 1, 1, 1, 1,236, 2,235, 1, 0, 1, 0, 2, 86, 0, 0, 0, 7, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,159,140, 32, 13, 64,145,160, 7, 27,196,112, 7, 27,196,112,
+ 13, 64,122,112, 13, 64,136, 64, 68, 65, 84, 65, 0, 0, 0,228, 13, 64,122,112, 0, 0, 0,163, 0, 0, 0, 1, 13, 64,123,128,
+ 0, 0, 0, 0, 84,114, 97,110,115,102,111,114,109, 32, 80,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 73,112,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, 33, 0,167, 1, 62, 0,204, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64,123,128, 0, 0, 0,163, 0, 0, 0, 1, 13, 64,124,144, 13, 64,122,112, 79,117,116,112,
+117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,
+101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64,124,144, 0, 0, 0,163, 0, 0, 0, 1, 13, 64,125,160, 13, 64,123,128, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64, 0, 0, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64,125,160, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64,126,176, 13, 64,124,144, 65,110,105,109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,128, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64,126,176, 0, 0, 0,163, 0, 0, 0, 1, 13, 64,127,192,
+ 13, 64,125,160, 70,111,114,109, 97,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3,192, 0, 0, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64,127,192, 0, 0, 0,163, 0, 0, 0, 1, 13, 64,128,208, 13, 64,126,176, 76,105,110,107,
+ 32, 97,110,100, 32, 77, 97,116,101,114,105, 97,108,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,
+105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64,128,208, 0, 0, 0,163, 0, 0, 0, 1, 13, 64,129,224, 13, 64,127,192, 67, 97,109,101,114, 97, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,100,105,116,105,110,103, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64, 0, 0, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64,129,224, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64,130,240, 13, 64,128,208, 80,114,101,118,105,101,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64,130,240, 0, 0, 0,163, 0, 0, 0, 1, 13, 64,132, 0,
+ 13, 64,129,224, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,255, 24, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64,132, 0, 0, 0, 0,163, 0, 0, 0, 1, 13, 64,133, 16, 13, 64,130,240, 83,104, 97,100,
+111,119, 32, 97,110,100, 32, 83,112,111,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254, 48,
+ 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228,
+ 13, 64,133, 16, 0, 0, 0,163, 0, 0, 0, 1, 13, 64,134, 32, 13, 64,132, 0, 84,101,120,116,117,114,101, 32, 97,110,100, 32,
+ 73,110,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,253, 72, 1, 62, 0,204, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,228, 13, 64,134, 32, 0, 0, 0,163,
+ 0, 0, 0, 1, 13, 64,135, 48, 13, 64,133, 16, 77, 97,112, 32, 84,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, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,253, 72, 1, 62, 0,204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 64,133, 16, 68, 65, 84, 65, 0, 0, 0,228, 13, 64,135, 48, 0, 0, 0,163, 0, 0, 0, 1, 13, 64,136, 64,
+ 13, 64,134, 32, 84,114, 97,110,115,102,111,114,109, 32, 80,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 86,105,101,119, 51,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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,228, 1, 62, 0,204, 0, 0, 0, 0, 0, 34, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,228, 13, 64,136, 64, 0, 0, 0,163, 0, 0, 0, 1, 0, 0, 0, 0, 13, 64,135, 48, 80,114,101,118,
+105,101,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86,105,101,119,
+ 51,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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 1,116,
+ 1,152, 1, 76, 0, 4, 0, 0, 2, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 3, 4,
+ 7,159,140, 32, 0, 0, 0,137, 0, 0, 0, 1, 13, 64,137, 80, 0, 0, 0, 0, 0, 0, 0, 1, 63, 51, 51, 51, 13, 64,121,112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 51,160, 0, 0,191,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 51,162, 33,104, 0, 0, 0, 0,
+ 60, 41,199, 78,191,230,129,210,193, 30,230,225, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,127,255,255, 0, 0, 0, 0, 0, 0, 0, 0,191,128, 0, 1, 51,160, 0, 0, 0, 0, 0, 0,
+188, 41,199, 79,193, 30,230,226, 63,230,129,216, 63,128, 0, 0, 63,157, 86,198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 61, 60, 82,166, 60,131, 2, 13, 63,153,213,185, 63,128, 0, 0,177,110,137,192, 63, 79, 65,252,179,194,218,164,179,162, 33,104,
+ 62,240, 79, 64,191,166, 74, 13,190, 50,105, 0, 65, 30,230,225, 63, 80, 67,132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 51,208, 0, 0, 63,158, 26, 71,179,128, 0, 0, 58, 96, 80, 64, 63, 81,241,110,190, 24, 70, 67,189,169, 29,122,
+189, 29,107, 44, 60,107,183,198, 62, 34,200, 16, 61,203, 63,156, 63,157, 86,198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63, 79, 65,252, 0, 0, 0, 0, 0, 0, 0, 0,189, 60, 82,166,188,131, 1,237,191,153,213,185,191,128, 0, 0,
+128, 0, 0, 0,128, 0, 0, 0,193, 65,194,239,128, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 51,160, 0, 0,191,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 51,162, 33,104, 0, 0, 0, 0,
+ 60, 41,199, 78,191,230,129,210,193, 30,230,225, 63,128, 0, 0, 63, 53, 4,244,191, 53, 4,243, 0, 0, 0, 0, 0, 0, 0, 0,
+ 65, 21,104,229, 63,128, 0, 0, 0, 0, 13,255, 0, 2, 0, 0, 7,159,156, 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, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 1, 0, 0,255,251, 0, 0,
+ 66, 12, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 59, 88,186,208, 60, 35,215, 10, 67,250, 0, 0,188,218, 18,228,188, 23,180, 37,
+189, 22,146,163, 64,198, 40, 85,192,173,239,178, 54,224, 0, 0, 63, 88,146, 56, 64, 71, 37,198, 0, 20, 0, 0, 0, 7, 0,207,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,255,255, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 8,
+ 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,220, 13, 64,137, 80, 0, 0, 0,142,
+ 0, 0, 0, 1, 13, 64,138, 96, 7,159,140, 32, 0, 0, 0, 4, 0, 0, 0, 0, 13, 64,121,112, 0, 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, 0, 4, 0, 0, 0, 0, 68,160, 0, 0,196, 46, 0, 0,
+ 67,100, 0, 0, 55,136,197,197, 68, 78,209,118,195,231,222, 40, 67, 25,158,172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 67,128, 0, 0, 66, 40, 0, 0, 69, 0, 0, 0, 67,225, 0, 0, 63, 0, 0, 0, 63,154,225, 72, 0, 0, 0, 1,
+ 0, 1, 0, 1, 3,233, 2,235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 2,
+ 0, 0, 0, 3, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 0, 0, 1,150, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 1, 88, 13, 64,138, 96, 0, 0, 0,141, 0, 0, 0, 1, 13, 64,139,224, 13, 64,137, 80, 0, 0, 0, 2,
+ 63, 51, 51, 51, 13, 64,121,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 67,122, 0, 0,189,204,204,205, 63,140,204,205, 63,128, 0, 0, 67,122, 0, 0,192,160, 0, 0, 64,160, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 2,235, 0, 0, 0, 16, 0, 0, 3,168, 0, 0, 0, 0, 0, 0, 0, 16,
+ 0, 0, 0, 16, 0, 0, 3,168, 0, 0, 0, 16, 0, 0, 2,235, 60, 35,215, 10, 60, 35,215, 10, 70,106, 96, 0, 68,122, 0, 0,
+ 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,159,184, 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, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0,
+ 0, 0, 0, 0, 0, 0, 79, 66, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 67,122, 0, 0,189,204,204,205, 63,140,204,205, 68, 65, 84, 65, 0, 0, 0,128, 13, 64,139,224, 0, 0, 0,148, 0, 0, 0, 1,
+ 13, 64,140,144, 13, 64,138, 96, 0, 0, 0, 9, 63, 51, 51, 51, 13, 64,121,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 64,194,224, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61,204,204,205, 0, 0, 0, 5, 0, 0, 0, 17,
+ 0, 0, 2,225, 0, 0, 2,227, 0, 0, 0, 5, 0, 0, 0, 17, 0, 0, 2,207, 0, 0, 2,227, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 1, 8, 13, 64,140,144, 0, 0, 0,146, 0, 0, 0, 1, 13, 64,141,192, 13, 64,139,224, 0, 0, 0, 6,
+ 63, 51, 51, 51, 13, 64,121,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,128, 0, 0,
+ 0, 0, 0, 0, 67,128, 0, 0,190,120, 0, 0, 63,159, 0, 0,190,242, 0, 0, 63,188,128, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 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,124,
+ 0, 0, 0, 0, 0, 0, 1,242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 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,
+ 0, 0, 1, 8, 13, 64,141,192, 0, 0, 0,145, 0, 0, 0, 1, 13, 64,142,240, 13, 64,140,144, 0, 0, 0, 3, 63, 51, 51, 51,
+ 13, 64,121,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,182, 0, 0,195,209, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 67,182, 0, 0,195,190, 0, 0,181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0,
+ 0, 0, 1,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 1,124, 0, 0, 0, 0,
+ 0, 0, 1,124,195,190, 0, 0,195,190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 1, 0, 1,
+ 0, 1, 0, 1, 1,108, 1,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 3,142, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 0, 0, 0,176,
+ 13, 64,142,240, 0, 0, 0,230, 0, 0, 0, 1, 13, 64,143,208, 13, 64,141,192, 0, 0, 0, 11, 63, 51, 51, 51, 13, 64,121,112,
+192,128, 0, 0, 67,122, 0, 0,192,128, 0, 0, 67,127, 0, 0,192,128, 0, 0, 66, 72, 0, 0,192,128, 0, 0, 67,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, 1,124, 0, 0, 0, 0, 0, 0, 0, 16,
+ 0, 0, 0, 0, 0, 0, 1,124, 0, 0, 0, 16, 0, 0, 1,124, 63,128, 0, 0, 67,129,128, 0, 70,250, 0, 0, 67,129,128, 0,
+ 61,204,204,205, 65, 32, 0, 0, 0, 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, 68, 65, 84, 65,
+ 0, 0, 0,180, 13, 64,143,208, 0, 0, 0,147, 0, 0, 0, 1, 13, 64,144,176, 13, 64,142,240, 0, 0, 0, 13, 63, 51, 51, 51,
+ 13, 64,121,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 68,122, 0, 0, 0, 0, 0, 0, 68,122, 0, 0,192,160, 0, 0, 66,130, 0, 0, 0, 0, 0, 0, 67,182, 0, 0, 0, 0, 1,108,
+ 0, 0, 1,124, 0, 0, 0, 0, 0, 0, 1,124, 0, 0, 0,196, 0, 0, 1,108, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,196,
+ 0, 0, 1,108, 0, 0, 0, 16, 0, 0, 1,124, 0, 0, 0, 0, 0, 0, 0, 0, 68,122, 0, 0, 68,122, 0, 0, 61,204,204,205,
+ 66, 72, 0, 0, 0, 10, 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, 68, 65, 84, 65, 0, 0, 0,192, 13, 64,144,176, 0, 0, 0,240, 0, 0, 0, 1, 13, 64,145,160, 13, 64,143,208,
+ 0, 0, 0, 12, 63, 51, 51, 51, 13, 64,121,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 0, 0, 0,
+ 66, 2, 0, 0,196,122, 0, 0, 0, 0, 0, 0,191, 0, 0, 0, 66, 2, 0, 0,194,150, 0, 0, 64,160, 0, 0, 0, 0, 1,108,
+ 0, 0, 1,124, 0, 0, 0, 0, 0, 0, 2, 14, 0, 0, 0,128, 0, 0, 1,108, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,128,
+ 0, 0, 1,108, 0, 0, 0, 16, 0, 0, 2, 14, 0, 0, 0, 0, 0, 0, 0, 0, 70,250, 0, 0, 68,122, 0, 0, 60, 35,215, 10,
+ 66, 72, 0, 0, 0, 10, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1,200,
+ 13, 64,145,160, 0, 0, 0,144, 0, 0, 0, 1, 0, 0, 0, 0, 13, 64,144,176, 0, 0, 0, 5, 63, 51, 51, 51, 13, 64,121,112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 83, 97,118,101, 32, 70,105,108,
+101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 85,115,101,114,115, 47,116,111,110, 47, 68,101,115,107,116,
+111,112, 47, 0,114, 47,114,101,108,101, 97,115,101, 47,100, 97,116, 97,102,105,108,101,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,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+112,114,101,118,105,101,119, 46, 98,108,101,110,100, 0, 0, 0, 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, 8, 0, 46, 0, 0, 0, 0, 1, 85, 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, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 0, 0, 5, 96, 7,159,144, 32,
+ 0, 0, 0,135, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67,112,114,101,118,105,101,
+119, 0, 0, 99,101,110,101, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,159,156, 32,
+ 13, 64,193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64,147,144, 13, 64,155, 16, 13, 64,147,144, 62, 18, 2, 17, 62,117,122,104,
+191,188,208, 62,188,211,197,192, 65, 59,229, 76, 64,184,106,208,188,211,197,192, 65, 59,229, 76, 64,184,106,208,188,211,197,192,
+ 65, 59,229, 76, 64,184,106,208, 0, 0, 0, 2, 62,214,245, 65, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 64,155, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64,155,176,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100, 0, 0, 0,100, 0, 0, 0, 1, 0, 0, 0, 0,
+ 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,128, 1,224, 0, 60, 0, 32, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 25, 0,141, 2, 88, 2, 88, 0, 2, 0, 2, 0, 0, 0, 24, 0, 4, 0, 0, 0, 0,
+ 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 32, 0, 0, 0, 0, 0, 64, 0, 0, 0, 5, 0, 25, 0, 10, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,158, 64, 13, 64,158, 64, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 63,128, 0, 0, 63,128, 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, 2,
+ 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 98, 97, 99,107, 98,117,102, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,116,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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 76,204,205,
+ 63, 76,204,205, 63, 76,204,205, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,128, 0, 0, 0, 0, 0, 6,
+ 0, 0, 0, 16, 63,128, 0, 0, 63,128, 0, 0, 2,173, 0, 95, 63,217,153,154, 0, 0,172, 68, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 7, 26, 32,144, 0, 1, 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, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,156,160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 68, 65, 84, 65, 0, 0, 0, 28, 13, 64,147,144, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,147,224,
+ 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 96, 0,227, 7,159,156, 32, 68, 65, 84, 65, 0, 0, 0, 28,
+ 13, 64,147,224, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,148, 48, 13, 64,147,144, 0, 0, 8, 0, 0, 0, 0, 2, 0, 0, 0, 0,
+ 46,224, 1,169, 7,159,248, 32, 68, 65, 84, 65, 0, 0, 0, 28, 13, 64,148, 48, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,148,128,
+ 13, 64,147,224, 0, 0, 0, 33, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1,122, 7,159,172, 32, 68, 65, 84, 65, 0, 0, 0, 28,
+ 13, 64,148,128, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,148,208, 13, 64,148, 48, 0, 0, 4, 14, 0, 0, 0, 1, 0, 0, 0, 0,
+ 1, 2, 1,220, 7,159,168, 32, 68, 65, 84, 65, 0, 0, 0, 28, 13, 64,148,208, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,149, 32,
+ 13, 64,148,128, 0, 0, 4, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 48, 1, 67, 7,159,244, 32, 68, 65, 84, 65, 0, 0, 0, 28,
+ 13, 64,149, 32, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,149,112, 13, 64,148,208, 0, 0, 0, 32, 0, 0, 0, 4, 0, 0, 16, 0,
+ 46,224, 1, 49, 7,159,208, 32, 68, 65, 84, 65, 0, 0, 0, 28, 13, 64,149,112, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,149,192,
+ 13, 64,149, 32, 0, 0, 0, 33, 0, 0, 0, 2, 0, 0, 0, 0, 1, 1, 1,122, 7,159,212, 32, 68, 65, 84, 65, 0, 0, 0, 28,
+ 13, 64,149,192, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,150, 16, 13, 64,149,112, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 20, 0,
+ 46,224, 0, 52, 7,159,204, 32, 68, 65, 84, 65, 0, 0, 0, 28, 13, 64,150, 16, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,150, 96,
+ 13, 64,149,192, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 20, 0, 46,224, 0, 47, 7,159,200, 32, 68, 65, 84, 65, 0, 0, 0, 28,
+ 13, 64,150, 96, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,150,176, 13, 64,150, 16, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 20, 0,
+ 46,224, 1, 85, 7,159,196, 32, 68, 65, 84, 65, 0, 0, 0, 28, 13, 64,150,176, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,151, 0,
+ 13, 64,150, 96, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 20, 0, 46,224, 0, 10, 7,159,192, 32, 68, 65, 84, 65, 0, 0, 0, 28,
+ 13, 64,151, 0, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,151, 80, 13, 64,150,176, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 20, 0,
+ 46,224, 1,113, 7,159,188, 32, 68, 65, 84, 65, 0, 0, 0, 28, 13, 64,151, 80, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,151,160,
+ 13, 64,151, 0, 0, 0, 0, 4, 0, 0, 0, 11, 0, 0, 0, 0, 1, 1, 1,147, 7,159,240, 32, 68, 65, 84, 65, 0, 0, 0, 28,
+ 13, 64,151,160, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,151,240, 13, 64,151, 80, 0, 0, 4, 14, 0, 0, 0, 3, 0, 0, 0, 0,
+ 1, 2, 1,220, 7,159,164, 32, 68, 65, 84, 65, 0, 0, 0, 28, 13, 64,151,240, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,152, 64,
+ 13, 64,151,160, 0, 0, 0, 64, 0, 0, 0, 1, 0, 0, 16, 0, 0,255, 2, 91, 7,159,232, 32, 68, 65, 84, 65, 0, 0, 0, 28,
+ 13, 64,152, 64, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,152,144, 13, 64,151,240, 0, 0, 0, 64, 0, 0, 0, 2, 0, 0, 0, 0,
+ 0,253, 1,180, 7,159,236, 32, 68, 65, 84, 65, 0, 0, 0, 28, 13, 64,152,144, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,152,224,
+ 13, 64,152, 64, 0, 0, 0, 32, 0, 0, 0, 15, 0, 0, 0, 0, 1, 0, 1,122, 7,159,252, 32, 68, 65, 84, 65, 0, 0, 0, 28,
+ 13, 64,152,224, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,153, 48, 13, 64,152,144, 0, 0, 0, 16, 0, 0, 0, 1, 0, 0, 0, 0,
+ 1, 1, 1,123, 7,159,228, 32, 68, 65, 84, 65, 0, 0, 0, 28, 13, 64,153, 48, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,153,128,
+ 13, 64,152,224, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 0, 1, 0, 1,123, 7,159,216, 32, 68, 65, 84, 65, 0, 0, 0, 28,
+ 13, 64,153,128, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,153,208, 13, 64,153, 48, 0, 0, 4, 28, 0, 0, 0, 4, 0, 0, 20, 0,
+ 46,224, 1,204, 7,159,176, 32, 68, 65, 84, 65, 0, 0, 0, 28, 13, 64,153,208, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,154, 32,
+ 13, 64,153,128, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 0, 1, 1, 1,122, 7,159,224, 32, 68, 65, 84, 65, 0, 0, 0, 28,
+ 13, 64,154, 32, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,154,112, 13, 64,153,208, 0, 0, 4, 28, 0, 0, 0, 5, 0, 0, 20, 0,
+ 46,224, 2,229, 7,159,184, 32, 68, 65, 84, 65, 0, 0, 0, 28, 13, 64,154,112, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,154,192,
+ 13, 64,154, 32, 0, 0, 0, 8, 0, 0, 0, 21, 0, 0, 0, 0, 0,204, 1,147, 7,159,220, 32, 68, 65, 84, 65, 0, 0, 0, 28,
+ 13, 64,154,192, 0, 0, 0,118, 0, 0, 0, 1, 13, 64,155, 16, 13, 64,154,112, 0, 0, 4, 28, 0, 0, 0, 6, 0, 0, 20, 0,
+ 46,224, 1, 9, 7,159,180, 32, 68, 65, 84, 65, 0, 0, 0, 28, 13, 64,155, 16, 0, 0, 0,118, 0, 0, 0, 1, 0, 0, 0, 0,
+ 13, 64,154,192, 0, 0, 13,223, 0, 0, 0, 3, 0, 0, 4, 0, 46,224, 0,227, 7,159,160, 32, 68, 65, 84, 65, 0, 0, 0, 40,
+ 13, 64,155, 96, 0, 0, 0,117, 0, 0, 0, 1, 1, 44, 0, 0, 0, 1, 0, 2, 0, 1, 0, 2, 0, 0, 0, 1, 1,244, 0,200,
+ 0,100, 0, 20, 0, 0, 39, 16, 61,204,204,205, 65,240, 0, 0, 64, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,188, 13, 64,155,176,
+ 0, 0, 0,132, 0, 0, 0, 1, 0, 1, 0, 1, 63, 76,204,205, 66,180, 0, 0, 0, 9, 0, 1, 63,128, 0, 0, 58,131, 18,111,
+ 0, 32, 0, 32, 0, 32, 0, 1, 63,128, 0, 0, 63,128, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 7, 0, 5, 0, 5,255,255, 0, 50, 0, 50, 0, 10, 0, 0, 0, 50, 0,100, 0, 10, 0, 0, 0, 50, 0, 50,
+ 0, 10, 0, 0, 0, 50, 0, 50, 0, 10, 0, 0, 0, 50, 0, 50, 0, 10, 0, 0, 0, 50, 0, 50, 0, 10, 0, 0, 0, 50, 0, 50,
+ 0, 10, 0, 0, 62,128, 0, 0, 0, 0, 0, 0, 56,209,183, 23, 61,204,204,205, 0, 0, 0, 0, 0, 0, 0, 50, 60, 35,215, 10,
+ 60, 35,215, 10, 63,166,102,102, 63,192, 0, 0, 66, 52, 0, 0, 63,122,225, 72, 61,204,204,205, 0, 3, 0, 1, 2, 0, 1, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 8, 13, 64,156,160, 0, 0, 1, 32, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 6, 0, 0, 67,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,191,127, 10, 78, 61,177, 44, 36,191,127, 10, 78, 61,177, 43,213,
+ 13, 64,157,208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0, 72, 13, 64,157,208, 0, 0, 1, 30, 0, 0, 0, 6, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 61,204,204,205, 63,121,188, 86, 0, 0, 0, 0, 62,153,153,154, 63, 75, 60, 96, 0, 0, 0, 0, 63, 51, 51, 51, 62, 83, 14,128,
+ 0, 0, 0, 0, 63,102,102,102, 60,200,117, 79, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0, 72, 13, 64,158, 64, 0, 0, 0,123, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 49, 32, 82,101,110,100,101,114,
+ 76, 97,121,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64,195,240,
+ 0, 15,255,255, 0, 0, 0, 0, 0, 0,127,255, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 73, 77, 0, 0, 1,128,
+ 13, 64,158,176, 0, 0, 0, 32, 0, 0, 0, 1, 7, 30,176,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 77, 73,109,
+ 97,103,101, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 53, 0, 0, 0, 0,
+ 85,110,116,105,116,108,101,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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 68,134,110,108, 0, 0, 1, 0, 1, 0, 0, 1,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 73, 77, 0, 0, 1,128, 7, 30,176,144, 0, 0, 0, 32, 0, 0, 0, 1,
+ 0, 0, 0, 0, 13, 64,158,176, 0, 0, 0, 0, 0, 0, 0, 0, 73, 77, 82,101,110,100,101,114, 32, 82,101,115,117,108,116, 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, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 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, 5, 0, 4,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 1, 0, 0, 1, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 67, 65, 0, 0, 0,132, 13, 64,160, 96, 0, 0, 0, 30, 0, 0, 0, 1, 13, 64,161, 16, 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, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 62, 76,204,205, 66, 96,148,117, 64,176, 0, 0, 66,112, 0, 0, 65,240, 0, 0,
+ 64,192, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 65, 0, 0, 0,132,
+ 13, 64,161, 16, 0, 0, 0, 30, 0, 0, 0, 1, 0, 0, 0, 0, 13, 64,160, 96, 0, 0, 0, 0, 0, 0, 0, 0, 67, 65, 67, 97,
+109,101,114, 97, 65,116,109,111, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 12, 62, 76,204,205, 66, 68,137,145, 64,176, 39, 76, 66,112, 69,210, 66, 12, 0, 0, 64,234, 14,161, 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, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 0, 0, 1,120, 13, 64,161,192, 0, 0, 0, 40,
+ 0, 0, 0, 1, 13, 64,165, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 76, 97,109,112, 46, 48, 48, 49, 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, 1, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 65,160, 0, 0, 66, 52, 0, 0, 62, 25,153,154, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 13, 64,163, 96, 0, 1, 0, 0, 63, 0, 0, 0, 66, 32, 0, 0, 66, 52, 0, 0, 63,128, 0, 0, 64, 64, 0, 0, 2, 0, 0, 3,
+ 0, 1, 0, 0, 0, 2, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 58,131, 18,111,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 65, 32, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 64, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,164,208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 1, 8, 13, 64,163, 96, 0, 0, 1, 32, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 2, 0, 1, 67,128, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0,191, 53, 4,243, 63, 53, 4,242,191, 53, 4,242, 63, 53, 4,243, 13, 64,164,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24,
+ 13, 64,164,144, 0, 0, 1, 30, 0, 0, 0, 2, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 32, 13, 64,164,208, 0, 0, 0, 19, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 0, 0, 1,120,
+ 13, 64,165, 32, 0, 0, 0, 40, 0, 0, 0, 1, 13, 64,168,128, 13, 64,161,192, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 76, 97,
+109,112, 46, 48, 48, 50, 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, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 65,160, 0, 0, 66,143,152,182, 62, 25,153,154, 63,128, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 13, 64,166,192, 0, 1, 0, 0, 63, 0, 0, 0, 66, 32, 0, 0, 66, 52, 0, 0, 63,128, 0, 0,
+ 64, 64, 0, 0, 2, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 58,131, 18,111, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 64, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,168, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 8, 13, 64,166,192, 0, 0, 1, 32, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 2, 0, 1, 67,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,191, 53, 4,243, 63, 53, 4,242,191, 53, 4,242, 63, 53, 4,243,
+ 13, 64,167,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0, 24, 13, 64,167,240, 0, 0, 1, 30, 0, 0, 0, 2, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 32, 13, 64,168, 48, 0, 0, 0, 19, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 76, 65, 0, 0, 1,120, 13, 64,168,128, 0, 0, 0, 40, 0, 0, 0, 1, 13, 64,171,144, 13, 64,165, 32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 76, 65, 83,112,111,116, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 8, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 12,204,205, 65,239,255,247, 66,150, 0, 0,
+ 62, 25,153,154, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 13, 64,170, 32, 0, 4, 0, 0, 63,128, 26, 46, 65,240, 4, 25,
+ 66, 52, 0, 0, 63,128, 0, 0, 64, 64, 0, 0, 11, 64, 0, 3, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 58,131, 18,111, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 64, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 1, 8, 13, 64,170, 32, 0, 0, 1, 32, 0, 0, 0, 1,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 2, 0, 1, 67,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,191, 53, 4,243, 63, 53, 4,242,
+191, 53, 4,242, 63, 53, 4,243, 13, 64,171, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 13, 64,171, 80, 0, 0, 1, 30, 0, 0, 0, 2, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 0, 0, 1,120, 13, 64,171,144,
+ 0, 0, 0, 40, 0, 0, 0, 1, 13, 64,174,160, 13, 64,168,128, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 83,112,111,116, 46, 48,
+ 48, 49, 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, 16, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,102,102,102, 65,239,255,247, 66,150, 0, 0, 62, 25,153,154, 63,128, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 13, 64,173, 48, 0, 1, 0, 0, 63,128, 26, 46, 65,240, 4, 25, 66, 52, 0, 0, 63,128, 0, 0, 64, 64, 0, 0,
+ 11, 64, 0, 3, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 58,131, 18,111, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 64, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 1, 8, 13, 64,173, 48, 0, 0, 1, 32, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 2, 0, 1,
+ 67,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,191, 53, 4,243, 63, 53, 4,242,191, 53, 4,242, 63, 53, 4,243, 13, 64,174, 96,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0, 24, 13, 64,174, 96, 0, 0, 1, 30, 0, 0, 0, 2, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 0, 0, 1,120, 13, 64,174,160, 0, 0, 0, 40, 0, 0, 0, 1, 13, 64,177,176,
+ 13, 64,171,144, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 83,112,111,116, 46, 48, 48, 51, 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, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 65,239,255,247, 66,150, 0, 0, 62, 25,153,154, 63,128, 0, 0, 63, 27,182,200, 63,128, 0, 0, 13, 64,176, 64, 0, 1, 0, 0,
+ 63,128, 26, 46, 65,240, 4, 25, 66, 52, 0, 0, 63,128, 0, 0, 64, 64, 0, 0, 11, 64, 0, 3, 0, 1, 0, 0, 0, 0, 0, 1,
+ 0, 1, 0, 1, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 58,131, 18,111, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 64, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 1, 8, 13, 64,176, 64,
+ 0, 0, 1, 32, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 2, 0, 1, 67,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+191, 53, 4,243, 63, 53, 4,242,191, 53, 4,242, 63, 53, 4,243, 13, 64,177,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 13, 64,177,112, 0, 0, 1, 30,
+ 0, 0, 0, 2, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65,
+ 0, 0, 1,120, 13, 64,177,176, 0, 0, 0, 40, 0, 0, 0, 1, 13, 64,180,192, 13, 64,174,160, 0, 0, 0, 0, 0, 0, 0, 0,
+ 76, 65, 83,112,111,116, 46, 48, 48, 52, 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, 16, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,204,204,205, 65,239,255,247, 66,150, 0, 0, 62, 25,153,154,
+ 63,128, 0, 0, 63, 27,182,200, 63,128, 0, 0, 13, 64,179, 80, 0, 1, 0, 0, 63,128, 26, 46, 65,240, 4, 25, 66, 52, 0, 0,
+ 63,128, 0, 0, 64, 64, 0, 0, 11, 64, 0, 3, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 58,131, 18,111, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 64, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 1, 8, 13, 64,179, 80, 0, 0, 1, 32, 0, 0, 0, 1, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 2, 0, 1, 67,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,191, 53, 4,243, 63, 53, 4,242,191, 53, 4,242,
+ 63, 53, 4,243, 13, 64,180,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 13, 64,180,128, 0, 0, 1, 30, 0, 0, 0, 2, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 0, 0, 1,120, 13, 64,180,192, 0, 0, 0, 40,
+ 0, 0, 0, 1, 13, 64,183,208, 13, 64,177,176, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 83,112,111,116, 46, 48, 48, 53, 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, 16, 8,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63, 83, 78, 80, 65,239,255,247, 66,150, 0, 0, 62, 25,153,154, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 13, 64,182, 96, 0, 4, 0, 0, 63,128, 26, 46, 65,240, 4, 25, 66, 52, 0, 0, 63,128, 0, 0, 64, 64, 0, 0, 11, 64, 0, 3,
+ 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 58,131, 18,111,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 64, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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,
+ 0, 0, 1, 8, 13, 64,182, 96, 0, 0, 1, 32, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 2, 0, 1, 67,128, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0,191, 53, 4,243, 63, 53, 4,242,191, 53, 4,242, 63, 53, 4,243, 13, 64,183,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24,
+ 13, 64,183,144, 0, 0, 1, 30, 0, 0, 0, 2, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 76, 65, 0, 0, 1,120, 13, 64,183,208, 0, 0, 0, 40, 0, 0, 0, 1, 13, 64,186,224, 13, 64,180,192,
+ 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 83,112,111,116, 46, 48, 48, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,179, 51, 51, 65,239,255,247,
+ 66, 72, 0, 0, 63, 8,156,171, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 13, 64,185,112, 0, 4, 0, 0, 65, 68,207, 78,
+ 65,240, 4, 25, 66, 52, 0, 0, 63,128, 0, 0, 64, 64, 0, 0, 2, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 58,131, 18,111, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 64, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 1, 8, 13, 64,185,112, 0, 0, 1, 32,
+ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 2, 0, 1, 67,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,191, 53, 4,243,
+ 63, 53, 4,242,191, 53, 4,242, 63, 53, 4,243, 13, 64,186,160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 13, 64,186,160, 0, 0, 1, 30, 0, 0, 0, 2,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 0, 0, 1,120,
+ 13, 64,186,224, 0, 0, 0, 40, 0, 0, 0, 1, 13, 64,189,240, 13, 64,183,208, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 83,112,
+111,116, 46, 48, 48, 55, 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, 16, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 65,239,255,247, 66,150, 0, 0, 62, 25,153,154, 63,128, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 13, 64,188,128, 0, 1, 0, 0, 63,128, 26, 46, 65,240, 4, 25, 66, 52, 0, 0, 63,128, 0, 0,
+ 64, 64, 0, 0, 11, 64, 0, 3, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 58,131, 18,111, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 64, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 1, 8, 13, 64,188,128, 0, 0, 1, 32, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 2, 0, 1, 67,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,191, 53, 4,243, 63, 53, 4,242,191, 53, 4,242, 63, 53, 4,243,
+ 13, 64,189,176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0, 24, 13, 64,189,176, 0, 0, 1, 30, 0, 0, 0, 2, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 0, 0, 1,120, 13, 64,189,240, 0, 0, 0, 40, 0, 0, 0, 1,
+ 0, 0, 0, 0, 13, 64,186,224, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 76, 97,109,112, 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, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,192, 0, 0, 65,160, 0, 0, 66, 52, 0, 0, 62, 25,153,154, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 13, 64,191,144,
+ 0, 1, 0, 0, 63, 0, 0, 0, 66, 32, 0, 0, 66, 52, 0, 0, 63,128, 0, 0, 64, 64, 0, 0, 2, 0, 0, 3, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 58,131, 18,111, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 64, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 0, 0, 1, 8,
+ 13, 64,191,144, 0, 0, 1, 32, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 2, 0, 1, 67,128, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0,191, 53, 4,243, 63, 53, 4,242,191, 53, 4,242, 63, 53, 4,243, 13, 64,192,192, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 13, 64,192,192,
+ 0, 0, 1, 30, 0, 0, 0, 2, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 87, 79, 0, 0, 1,100, 13, 64,193, 0, 0, 0, 0,116, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 87, 79, 87,111,114,108,100, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 79, 47,141, 62,209, 19, 64, 63, 14, 23, 73, 0, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 28,204,205, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 65,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 65, 32, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61, 76,204,205, 0, 0, 0, 5, 0, 0, 0, 0, 59,163,215, 10, 0, 0, 0, 0,
+ 62,128, 0, 0, 0, 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, 13, 64,194,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 32,
+ 13, 64,194,144, 0, 0, 0, 19, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 88, 0, 0, 0,120, 13, 64,194,224, 0, 0, 0, 28, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 88, 84,101,120,116, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 1,
+ 13, 64,195,128, 13, 64,195,128, 13, 64,195,128, 13, 64,195,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 7,159,150, 32,255,255,255,255, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24,
+ 13, 64,195,128, 0, 0, 0, 26, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64,195,192, 0, 0, 0, 0, 0, 0, 0, 0,
+ 70, 82, 69, 69, 68, 65, 84, 65, 0, 0, 0, 4, 13, 64,195,192, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 71, 82,
+ 0, 0, 0, 76, 13, 64,195,240, 0, 0, 0,232, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 71, 82, 79,118,101,114,114,105,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 64,196,112, 13, 64,198,176, 0, 15,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0, 24, 13, 64,196,112, 0, 0, 0,231, 0, 0, 0, 1, 13, 64,196,176, 0, 0, 0, 0, 7,159,208, 32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 13, 64,196,176, 0, 0, 0,231, 0, 0, 0, 1, 13, 64,196,240,
+ 13, 64,196,112, 7,159,204, 32, 7,162,150, 32, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 13, 64,196,240,
+ 0, 0, 0,231, 0, 0, 0, 1, 13, 64,197, 48, 13, 64,196,176, 7,159,200, 32, 7,157,170, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0, 24, 13, 64,197, 48, 0, 0, 0,231, 0, 0, 0, 1, 13, 64,197,112, 13, 64,196,240, 7,159,196, 32,
+ 7,157,174, 32, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 13, 64,197,112, 0, 0, 0,231, 0, 0, 0, 1,
+ 13, 64,197,176, 13, 64,197, 48, 7,159,192, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24,
+ 13, 64,197,176, 0, 0, 0,231, 0, 0, 0, 1, 13, 64,197,240, 13, 64,197,112, 7,159,188, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 13, 64,197,240, 0, 0, 0,231, 0, 0, 0, 1, 13, 64,198, 48, 13, 64,197,176,
+ 7,159,232, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 13, 64,198, 48, 0, 0, 0,231,
+ 0, 0, 0, 1, 13, 64,198,112, 13, 64,197,240, 7,159,176, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0, 24, 13, 64,198,112, 0, 0, 0,231, 0, 0, 0, 1, 13, 64,198,176, 13, 64,198, 48, 7,159,184, 32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 24, 13, 64,198,176, 0, 0, 0,231, 0, 0, 0, 1, 0, 0, 0, 0,
+ 13, 64,198,112, 7,159,180, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,156, 32,
+ 0, 0, 0,109, 0, 0, 0, 1, 7,159,160, 32, 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, 0, 1, 4, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 64,160, 96, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,188, 41,199, 78,193, 30,230,225, 63,230,129,216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,201, 15,218,128, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51,162, 33,105, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+191,128, 0, 0, 51,162, 33,105, 0, 0, 0, 0,188, 41,199, 78,193, 30,230,225, 63,230,129,216, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 48,136, 90, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+168, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+176,136, 90, 64, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 8, 0,
+ 0, 1, 0, 0, 0, 0, 0, 68, 0, 5, 0, 1, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205,
+ 61,204,204,205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,160, 32, 0, 0, 0,109, 0, 0, 0, 1,
+ 7,159,164, 32, 7,159,156, 32, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 67, 97,109,101,114, 97, 65,116,109,111, 0, 97,109,101,
+114, 97, 46, 48, 48, 49, 0, 0, 0, 1, 4, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,161, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+188, 41,199, 78,193, 30,230,225, 63,230,129,216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,244, 47,173,
+ 37,113,155,162, 37,170, 80, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 37,170, 80, 40,165,113,155,162,
+ 0, 0, 0, 0, 37,170, 80, 39,190,169, 64,157, 63,113,155,163, 0, 0, 0, 0, 37,113,155,165,191,113,155,163,190,169, 64,157,
+ 0, 0, 0, 0,188, 41,199, 78,193, 30,230,225, 63,230,129,216, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,154, 0, 0, 1, 25,127,255,254,
+ 0, 0, 0, 0, 37,171, 80, 41, 63,128, 0, 1, 51,128, 0, 1, 0, 0, 0, 0, 45,255,255,135,136,127,255,137, 63,128, 0, 0,
+ 0, 0, 0, 0, 48,128, 0, 0, 53,128, 0, 1, 52,128, 0, 2, 63,128, 0, 0, 63,128, 0, 0, 37,170, 80, 39, 37,113,155,166,
+ 0, 0, 0, 0,165,113,155,162, 63,113,155,164,190,169, 64,158, 0, 0, 0, 0,165,170, 80, 40, 62,169, 64,159, 63,113,155,162,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 13,223, 4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 5, 0, 1, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100,
+ 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 63,100, 41, 6, 63,128, 0, 0, 62,204,204,205, 63,100, 41, 6, 0, 0, 0, 0,
+ 61,117,194,143, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,164, 32, 0, 0, 0,109, 0, 0, 0, 1, 7,159,168, 32, 7,159,160, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 99,104,101, 99,107,101,114,115, 46, 48, 48, 49, 0, 46, 48, 48, 49, 0, 0, 0, 0, 0,
+ 0, 1, 4, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 23, 97,112, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,115, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,198,240, 55,142, 84, 52,192,188, 12,194,
+ 64, 71, 38, 28, 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,190, 36, 69,
+ 64,190, 36, 69, 64,190, 36, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0, 63, 73, 15,218,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,134,115, 83, 64,134,115, 82, 0, 0, 0, 0, 0, 0, 0, 0,192,134,115, 82,
+ 64,134,115, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,190, 36, 68, 0, 0, 0, 0, 55,142, 84, 52,
+192,188, 12,194, 64, 71, 38, 28, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 52, 85,230, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61,243,183,207,189,243,183,205, 37,162, 83,160, 0, 0, 0, 0, 50, 26, 90, 29,
+ 50, 26, 90, 31, 62, 44, 85,173, 0, 0, 0, 0,189,243,183,205,189,243,183,207, 50, 87,107, 24, 0, 0, 0, 0,190,247,176,158,
+190,246,108,212,190, 97,232, 64, 63,128, 0, 0, 0, 0, 4, 14, 4, 0, 0, 1, 0, 0, 0, 68, 0, 1, 0, 2, 0, 0, 0, 0,
+ 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56,
+ 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205, 61,204,204,205, 0, 0, 0, 0, 61,117,194,143, 0, 0, 0, 0,
+ 4, 0, 1, 1, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 29,237,208, 7, 29,244,128,
+ 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0, 4, 13, 64,198,240, 0, 0, 0, 0, 0, 0, 0, 1, 7,160, 4, 32, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,168, 32,
+ 0, 0, 0,109, 0, 0, 0, 1, 7,159,172, 32, 7,159,164, 32, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 99,104,101, 99,107,101,
+114,115, 46, 48, 48, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 22,250,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,109,208, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,199, 32, 55,142, 84, 52,192,188, 12,194, 64, 71, 38, 28, 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,190, 36, 69, 64,190, 36, 69, 64,190, 36, 68, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0, 63, 73, 15,218, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,134,115, 83,
+ 64,134,115, 82, 0, 0, 0, 0, 0, 0, 0, 0,192,134,115, 82, 64,134,115, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 64,190, 36, 68, 0, 0, 0, 0, 55,142, 84, 52,192,188, 12,194, 64, 71, 38, 28, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 52, 85,230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61,243,183,207,
+189,243,183,205, 37,162, 83,160, 0, 0, 0, 0, 50, 26, 90, 29, 50, 26, 90, 31, 62, 44, 85,173, 0, 0, 0, 0,189,243,183,205,
+189,243,183,207, 50, 87,107, 24, 0, 0, 0, 0,190,247,176,158,190,246,108,212,190, 97,232, 64, 63,128, 0, 0, 0, 0, 4, 14,
+ 4, 0, 0, 1, 0, 0, 0, 68, 0, 1, 0, 2, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205,
+ 61,204,204,205, 0, 0, 0, 0, 61,117,194,143, 0, 0, 0, 0, 4, 0, 1, 1, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 23, 89,240, 7, 22,192,224, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 64,199, 32, 0, 0, 0, 0, 0, 0, 0, 1,
+ 7,160, 0, 32, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,172, 32, 0, 0, 0,109, 0, 0, 0, 1, 7,159,176, 32, 7,159,168, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 99,104,101, 99,107,101,114,115, 46, 48, 48, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 4, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 28,254,192, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,120,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,199, 80, 60,102,131, 0, 64,164,112, 14,
+ 63,229,211, 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, 65, 34,159,178,
+ 65, 34,159,178, 65, 34,159,177, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0,178, 89,250,166,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 34,159,178,180, 10,120,151, 0, 0, 0, 0, 0, 0, 0, 0, 52, 10,120,151,
+ 65, 34,159,178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 34,159,177, 0, 0, 0, 0, 60,102,131, 0,
+ 64,164,112, 14, 63,229,211, 24, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 53, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61,201,126,231, 48,171,145,219, 30,247,120,240, 0, 0, 0, 0,164,217,209, 65,
+ 49,255, 57, 51, 61,201,126,232, 0, 0, 0, 0, 48,172, 66,235,189,201,126,231, 49,251,201, 70, 0, 0, 0, 0,187, 29,136, 18,
+191,189,200,203, 58, 9,139,180, 63,128, 0, 0, 0, 0, 0, 33, 0, 0, 0, 1, 0, 0, 0, 68, 0, 1, 0, 2, 0, 0, 0, 0,
+ 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56,
+ 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205, 61,204,204,205, 0, 0, 0, 0, 61,117,194,143, 0, 0, 0, 0,
+ 4, 0, 1, 1, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 27,180,176, 7, 22, 19,240,
+ 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0, 4, 13, 64,199, 80, 0, 0, 0, 0, 0, 0, 0, 1, 7,160, 4, 32, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,176, 32,
+ 0, 0, 0,109, 0, 0, 0, 1, 7,159,180, 32, 7,159,172, 32, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 76, 97,109,112, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 64,168,128, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 65,110, 57, 42, 64, 11,114,237, 64,121, 99,120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,103, 90, 85,190,186, 45,254, 63,128,209,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,255,247,136,
+ 63, 74, 39, 37, 62,182, 26,138, 0, 0, 0, 0,191, 44, 21,164, 61,194, 67, 28, 63, 59,248,176, 0, 0, 0, 0, 63, 11,203,251,
+191, 27, 45,217, 63, 20, 7, 47, 0, 0, 0, 0, 65,110, 57, 42, 64, 11,114,237, 64,121, 99,120, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+179, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 51,128, 0, 0, 63,128, 0, 0,178,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 41, 64, 0, 0, 53, 64, 0, 0,181, 64, 0, 0, 63,128, 0, 0, 62,255,247,138,
+191, 44, 21,164, 63, 11,203,251, 0, 0, 0, 0, 62,182, 26,141, 63, 59,248,176, 63, 20, 7, 45, 0, 0, 0, 0,191, 74, 39, 37,
+189,194, 67, 9, 63, 27, 45,217, 0, 0, 0, 0,193,142, 14,147, 64,234,125, 35,192, 0,119, 85, 63,128, 0, 0, 0, 0, 4, 28,
+ 16, 0, 0, 0, 0, 0, 0, 68, 0, 5, 0, 1, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205,
+ 61,204,204,205, 0, 0, 0, 0, 61,117,194,143, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,180, 32, 0, 0, 0,109, 0, 0, 0, 1,
+ 7,159,184, 32, 7,159,176, 32, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 76, 97,109,112, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,171,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+191,210, 76, 84,193, 71,162,178, 64,178,186,210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,103, 90, 85,
+190,186, 45,254, 63,128,209,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,255,247,136, 63, 74, 39, 37, 62,182, 26,138,
+ 0, 0, 0, 0,191, 44, 21,164, 61,194, 67, 28, 63, 59,248,176, 0, 0, 0, 0, 63, 11,203,251,191, 27, 45,217, 63, 20, 7, 47,
+ 0, 0, 0, 0,191,210, 76, 84,193, 71,162,178, 64,178,186,210, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 52,191,255,250,179,191,255,250,
+ 0, 0, 0, 0,178,255,255,248, 63,127,255,248, 51,255,255,248, 0, 0, 0, 0, 38,255,255,248,179,127,255,248, 63,128, 0, 0,
+ 0, 0, 0, 0,180,255,255,250,182,191,255,250, 53,127,255,244, 63,128, 0, 0, 62,255,247,136,191, 44, 21,164, 63, 11,203,251,
+ 0, 0, 0, 0, 62,182, 26,139, 63, 59,248,173, 63, 20, 7, 44, 0, 0, 0, 0,191, 74, 39, 36,189,194, 67, 17, 63, 27, 45,217,
+ 0, 0, 0, 0, 63,189,129,191,192,104,159,176,192, 53,194,132, 63,128, 0, 0, 0, 0, 4, 28, 16, 0, 0, 0, 0, 0, 0, 68,
+ 0, 5, 0, 1, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100,
+ 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205, 61,204,204,205, 0, 0, 0, 0,
+ 61,117,194,143, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,184, 32, 0, 0, 0,109, 0, 0, 0, 1, 7,159,188, 32, 7,159,180, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 76, 97,109,112, 46, 48, 48, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,183,208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,193, 16,188,238,193, 57,119,229,
+ 65,141,218, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 15, 79,202,191, 12,100,179, 63,234, 92,112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190, 96,197,171, 63, 83, 27,149, 63, 5,118, 10, 0, 0, 0, 0,191, 99,218,142,
+ 61, 75, 4,109,190,232, 3,179, 0, 0, 0, 0,190,204,142,233,191, 16, 64,104, 63, 57, 28,174, 0, 0, 0, 0,193, 16,188,238,
+193, 57,119,229, 65,141,218, 17, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,127,255,254,178,127,255,254, 52, 32, 0, 0, 0, 0, 0, 0,178,128, 0, 0,
+ 63,128, 0, 0, 51,192, 0, 2, 0, 0, 0, 0,179, 0, 0, 0, 38, 0, 0, 0, 63,128, 0, 1, 0, 0, 0, 0,181,127,255,255,
+182, 0, 0, 0, 54, 0, 0, 0, 63,128, 0, 0,190, 96,197,175,191, 99,218,143,190,204,142,235, 0, 0, 0, 0, 63, 5,118, 11,
+190,232, 3,179, 63, 57, 28,172, 0, 0, 0, 0,191, 83, 27,150,189, 75, 4,119, 63, 16, 64,105, 0, 0, 0, 0,193, 14,181,128,
+191, 61,177,214,193,128,133, 29, 63,128, 0, 0, 0, 0, 4, 28, 16, 0, 0, 0, 0, 0, 0, 68, 0, 5, 0, 1, 0, 0, 0, 0,
+ 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56,
+ 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205, 61,204,204,205, 0, 0, 0, 0, 61,117,194,143, 0, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66,
+ 0, 0, 3, 68, 7,159,188, 32, 0, 0, 0,109, 0, 0, 0, 1, 7,159,192, 32, 7,159,184, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 79, 66, 76, 97,109,112, 46, 48, 48, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,174,160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,104,147,176,193, 23, 84, 42, 64,171, 77,116, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,103, 90, 85,190,186, 45,254, 63,128,209,115, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62,255,247,136, 63, 74, 39, 37, 62,182, 26,138, 0, 0, 0, 0,191, 44, 21,164, 61,194, 67, 28, 63, 59,248,176,
+ 0, 0, 0, 0, 63, 11,203,251,191, 27, 45,217, 63, 20, 7, 47, 0, 0, 0, 0, 64,104,147,176,193, 23, 84, 42, 64,171, 77,116,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0,180, 31,255,255,167,159,255,254, 0, 0, 0, 0, 50,255,255,254, 63,127,255,254, 50,255,255,252,
+ 0, 0, 0, 0,178,255,255,254, 39,159,255,254, 63,127,255,254, 0, 0, 0, 0, 52,127,255,253,181,127,255,254, 52,255,255,253,
+ 63,128, 0, 0, 62,255,247,137,191, 44, 21,165, 63, 11,203,251, 0, 0, 0, 0, 62,182, 26,141, 63, 59,248,176, 63, 20, 7, 46,
+ 0, 0, 0, 0,191, 74, 39, 37,189,194, 67, 20, 63, 27, 45,217, 0, 0, 0, 0,192, 93, 99, 91,190, 80, 98,136,192,112,119,223,
+ 63,128, 0, 0, 0, 0, 0, 1, 16, 0, 0, 0, 0, 0, 0, 68, 0, 5, 0, 1, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10,
+ 63,128, 0, 0, 62,204,204,205, 61,204,204,205, 0, 0, 0, 0, 61,117,194,143, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 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, 64, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,192, 32,
+ 0, 0, 0,109, 0, 0, 0, 1, 7,159,196, 32, 7,159,188, 32, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 76, 97,109,112, 46, 48,
+ 48, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 64,177,176, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,192,251,147,249,193, 24, 0,206,192,104,131, 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, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,103, 90, 85,190,186, 45,254, 63,128,209,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,255,247,136,
+ 63, 74, 39, 37, 62,182, 26,138, 0, 0, 0, 0,191, 44, 21,164, 61,194, 67, 28, 63, 59,248,176, 0, 0, 0, 0, 63, 11,203,251,
+191, 27, 45,217, 63, 20, 7, 47, 0, 0, 0, 0,192,251,147,249,193, 24, 0,206,192,104,131, 67, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,127,255,254,
+ 50,255,255,254,166,127,255,254, 0, 0, 0, 0, 38,127,255,254, 63,128, 0, 0,179, 0, 0, 0, 0, 0, 0, 0,178,255,255,254,
+ 51, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,181,127,255,254,181,128, 0, 0, 41, 0, 0, 0, 63,128, 0, 0, 62,255,247,137,
+191, 44, 21,165, 63, 11,203,251, 0, 0, 0, 0, 62,182, 26,139, 63, 59,248,176, 63, 20, 7, 45, 0, 0, 0, 0,191, 74, 39, 36,
+189,194, 67, 19, 63, 27, 45,217, 0, 0, 0, 0, 64,176,142,147,191,170, 22, 97, 64,246, 28, 27, 63,128, 0, 0, 0, 0, 0, 1,
+ 16, 0, 0, 0, 0, 0, 0, 68, 0, 5, 0, 1, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205,
+ 61,204,204,205, 0, 0, 0, 0, 61,117,194,143, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,196, 32, 0, 0, 0,109, 0, 0, 0, 1,
+ 7,159,200, 32, 7,159,192, 32, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 76, 97,109,112, 46, 48, 48, 53, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,180,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 65, 54, 41,142,191,115,124, 24,192, 58,215,162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,103, 90, 85,
+190,186, 45,254, 63,128,209,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,255,247,136, 63, 74, 39, 37, 62,182, 26,138,
+ 0, 0, 0, 0,191, 44, 21,164, 61,194, 67, 28, 63, 59,248,176, 0, 0, 0, 0, 63, 11,203,251,191, 27, 45,217, 63, 20, 7, 47,
+ 0, 0, 0, 0, 65, 54, 41,142,191,115,124, 24,192, 58,215,162, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0,
+ 0, 0, 0, 0, 51,128, 0, 0, 63,128, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 53,128, 0, 0, 0, 0, 0, 0,181, 64, 0, 0, 63,128, 0, 0, 62,255,247,136,191, 44, 21,164, 63, 11,203,251,
+ 0, 0, 0, 0, 62,182, 26,139, 63, 59,248,175, 63, 20, 7, 46, 0, 0, 0, 0,191, 74, 39, 36,189,194, 67, 25, 63, 27, 45,217,
+ 0, 0, 0, 0,193, 49,192,139, 65, 36, 99, 40, 63,249,156, 89, 63,128, 0, 0, 0, 0, 0, 2, 20, 0, 0, 0, 0, 0, 0, 68,
+ 0, 5, 0, 1, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100,
+ 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205, 61,204,204,205, 0, 0, 0, 0,
+ 61,117,194,143, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,200, 32, 0, 0, 0,109, 0, 0, 0, 1, 7,159,204, 32, 7,159,196, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 76, 97,109,112, 46, 48, 48, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,183,208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,193, 19,239,220,193, 54,239,215,
+ 65, 60, 9, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191,103,251, 67,191, 24, 27,164, 64, 3,136, 37,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,197,143, 31, 63, 59,184,209, 63, 15, 80,138, 0, 0, 0, 0,191, 64, 66, 57,
+ 61,210,119,132,191, 38,249,118, 0, 0, 0, 0,191, 9, 43, 37,191, 44, 15, 35, 63, 2,212,114, 0, 0, 0, 0,193, 19,239,220,
+193, 54,239,215, 65, 60, 9, 42, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,180, 0, 0, 1, 52, 32, 0, 1, 0, 0, 0, 0, 38,128, 0, 1,
+ 63,128, 0, 0,179, 0, 0, 1, 0, 0, 0, 0,179, 0, 0, 1,179,128, 0, 0, 63,128, 0, 1, 0, 0, 0, 0, 53,128, 0, 0,
+170, 0, 0, 1, 42, 32, 0, 1, 63,128, 0, 0,190,197,143, 31,191, 64, 66, 56,191, 9, 43, 35, 0, 0, 0, 0, 63, 15, 80,139,
+191, 38,249,117, 63, 2,212,112, 0, 0, 0, 0,191, 59,184,208,189,210,119,142, 63, 44, 15, 35, 0, 0, 0, 0,193, 0,135,195,
+190,148,252,127,193, 48,180, 8, 63,128, 0, 0, 0, 0, 0, 2, 20, 0, 0, 0, 0, 0, 0, 68, 0, 5, 0, 1, 0, 0, 0, 0,
+ 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56,
+ 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205, 61,204,204,205, 0, 0, 0, 0, 61,117,194,143, 0, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66,
+ 0, 0, 3, 68, 7,159,204, 32, 0, 0, 0,109, 0, 0, 0, 1, 7,159,208, 32, 7,159,200, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 79, 66, 76, 97,109,112, 46, 48, 48, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,186,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,164, 99,104,193, 51,244,239, 64, 19,110,188, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,103, 90, 85,190,186, 45,254, 63,128,209,115, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62,255,247,136, 63, 74, 39, 37, 62,182, 26,138, 0, 0, 0, 0,191, 44, 21,164, 61,194, 67, 28, 63, 59,248,176,
+ 0, 0, 0, 0, 63, 11,203,251,191, 27, 45,217, 63, 20, 7, 47, 0, 0, 0, 0,192,164, 99,104,193, 51,244,239, 64, 19,110,188,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0,178,255,255,254, 51,128, 0, 1, 0, 0, 0, 0,167, 64, 0, 2, 63,128, 0, 0, 51, 0, 0, 1,
+ 0, 0, 0, 0,179,192, 0, 2, 51,128, 0, 1, 63,128, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 62,255,247,137,191, 44, 21,165, 63, 11,203,251, 0, 0, 0, 0, 62,182, 26,139, 63, 59,248,178, 63, 20, 7, 45,
+ 0, 0, 0, 0,191, 74, 39, 36,189,194, 67, 18, 63, 27, 45,217, 0, 0, 0, 0, 64, 91, 24, 96,192,108, 50,226, 63,219, 9,101,
+ 63,128, 0, 0, 0, 0, 0, 2, 20, 0, 0, 0, 0, 0, 0, 68, 0, 5, 0, 1, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10,
+ 63,128, 0, 0, 62,204,204,205, 61,204,204,205, 0, 0, 0, 0, 61,117,194,143, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 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, 64, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,208, 32,
+ 0, 0, 0,109, 0, 0, 0, 1, 7,159,212, 32, 7,159,204, 32, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 76, 97,109,112, 46, 48,
+ 48, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 64,189,240, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,188, 75,145,193,107,197, 44, 64, 81,147, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,201, 15,218, 37,128, 0, 0, 37,127,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 37,127,255,255,165,128, 0, 0, 0, 0, 0, 0, 37,127,255,255, 51,162, 33,105, 63,128, 0, 0, 0, 0, 0, 0, 37,128, 0, 0,
+191,128, 0, 0, 51,162, 33,105, 0, 0, 0, 0, 63,188, 75,145,193,107,197, 44, 64, 81,147, 5, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,127,255,254,
+ 53,107,197, 44,180, 81,147, 4, 0, 0, 0, 0, 37,127,255,253, 63,128, 0, 0, 48,136, 90, 64, 0, 0, 0, 0,165,127,255,254,
+155,107,197, 44, 63,128, 0, 0, 0, 0, 0, 0, 51,255,255,254,181,255,255,255, 52,127,255,254, 63,128, 0, 0, 63,128, 0, 0,
+178, 23, 25, 45,179, 75,199,107, 0, 0, 0, 0,165,128, 0, 1, 63,128, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0,177,108,127, 0,
+ 50, 29, 9,206, 63,128, 0, 0, 0, 0, 0, 0,191,189,159, 32,191,188,164, 47,192,153,188,150, 63,128, 0, 0, 0, 0, 0, 32,
+ 16, 0, 0, 0, 0, 0, 0, 68, 0, 5, 0, 1, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205,
+ 61,204,204,205, 0, 0, 0, 0, 61,117,194,143, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,212, 32, 0, 0, 0,109, 0, 0, 0, 1,
+ 7,159,216, 32, 7,159,208, 32, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 99,104,101, 99,107,101,114,115, 0, 0,108, 97,110,101,
+ 46, 48, 48, 51, 0, 0, 0, 0, 0, 1, 4, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 28,231, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,131, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 64,199,128,
+ 60,102,131, 0, 64,164,112, 14, 63,229,211, 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, 65, 34,159,178, 65, 34,159,178, 65, 34,159,177, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+128, 0, 0, 0,178, 89,250,166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 34,159,178,180, 10,120,151, 0, 0, 0, 0,
+ 0, 0, 0, 0, 52, 10,120,151, 65, 34,159,178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 34,159,177,
+ 0, 0, 0, 0, 60,102,131, 0, 64,164,112, 14, 63,229,211, 24, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61,201,126,231, 48,171,145,219, 30,247,120,240,
+ 0, 0, 0, 0,164,217,209, 65, 49,255, 57, 51, 61,201,126,232, 0, 0, 0, 0, 48,172, 66,235,189,201,126,231, 49,251,201, 70,
+ 0, 0, 0, 0,187, 29,136, 18,191,189,200,203, 58, 9,139,180, 63,128, 0, 0, 0, 0, 0, 33, 0, 0, 0, 1, 0, 0, 0, 68,
+ 0, 1, 0, 2, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100,
+ 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205, 61,204,204,205, 0, 0, 0, 0,
+ 61,117,194,143, 0, 0, 0, 0, 4, 0, 1, 1, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 26, 8, 80, 7, 26, 13,176, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 64,199,128, 0, 0, 0, 0, 0, 0, 0, 1, 7,160, 0, 32, 0, 0, 79, 66,
+ 0, 0, 3, 68, 7,159,216, 32, 0, 0, 0,109, 0, 0, 0, 1, 7,159,220, 32, 7,159,212, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 79, 66,112,114,101,118,105,101,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 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, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 26, 31,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 13, 65,154, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,199,176,189, 7, 82,100,191,103,204, 21, 63,230,165,241, 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,155, 39,153, 64,155, 39,153, 64,155, 39,153,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,201, 15,218, 37,192, 0, 0, 36,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 64,155, 39,153, 38, 27, 39,152,166,232,187,102, 0, 0, 0, 0, 38,232,187,102, 52,196,134,157, 64,155, 39,153,
+ 0, 0, 0, 0, 38, 27, 39,154,192,155, 39,153, 52,196,134,157, 0, 0, 0, 0,189, 7, 82,100,191,103,204, 21, 63,230,165,241,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,153, 34, 33,106, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,153, 34, 33,106, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,179,128, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 62, 83, 50, 25, 36,158,101,147, 35,211, 50, 27, 0, 0, 0, 0,164,158,101,147, 62, 83, 50, 25, 38,174, 59,158,
+ 0, 0, 0, 0,173,204, 94, 0,175, 96, 79,158, 62, 83, 50, 25, 0, 0, 0, 0, 59,153, 62,135,185,110, 94,217, 63,238, 71,118,
+ 63,128, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 68, 0, 1, 0, 2, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10,
+ 63,128, 0, 0, 62,204,204,205, 61,204,204,205, 0, 0, 0, 0, 61,117,194,143, 0, 0, 0, 0, 4, 0, 1, 1, 1, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 26, 19,192, 7, 26, 25,160, 0, 0, 0, 25, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 64,199,176,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,220, 32, 0, 0, 0,109, 0, 0, 0, 1,
+ 7,159,224, 32, 7,159,216, 32, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66,112,114,101,118,105,101,119, 46, 48, 48, 50, 0, 46, 48,
+ 48, 49, 0, 0, 0, 0, 0, 0, 0, 1, 4, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 65,104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,200, 16, 13, 64,200, 16, 13, 64,199,224,
+191,213,187,242, 63,134,145,194, 64, 35,100,254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 65, 28, 0,243, 65, 28, 0,246, 65, 28, 0,243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,135,110, 48,
+ 62, 59,169,180,191, 1,115,138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 6, 49,198,192,148,154,115,191,227,113, 3,
+ 0, 0, 0, 0, 64,106,250,159, 64, 91,207,189, 65, 5,170, 80, 0, 0, 0, 0,192, 86,151, 46,192,251, 94,125, 64,150,127,188,
+ 0, 0, 0, 0,191,213,187,242, 63,134,145,194, 64, 35,100,254, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 1,167, 0, 0, 1,179,128, 0, 1,
+ 0, 0, 0, 0,179, 0, 0, 1, 63,128, 0, 0, 51, 0, 0, 1, 0, 0, 0, 0,166,128, 0, 1, 51, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61,180,174,143, 61, 30, 48,160,189, 16,118,223,
+ 0, 0, 0, 0,188,153, 29,162, 61,179,248, 38, 61, 74,162,115, 0, 0, 0, 0, 61, 72, 21, 15,189, 19,250,160, 61,169, 57, 88,
+ 0, 0, 0, 0, 63, 50,107, 4,190,204, 46, 88, 63, 79,206,177, 63,128, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 68,
+ 0, 1, 0, 2, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100,
+ 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205, 61,204,204,205, 0, 0, 0, 0,
+ 61,117,194,143, 0, 0, 0, 0, 4, 0, 1, 1, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 64,199,224, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0, 68, 13, 64,200, 16, 0, 0, 0, 78, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 31,
+ 83,117, 98,115,117,114,102, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,224, 32,
+ 0, 0, 0,109, 0, 0, 0, 1, 7,159,228, 32, 7,159,220, 32, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66,112,114,101,118,105,101,
+119, 46, 48, 48, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 22,191, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,148,176, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,200,128,187,203,194, 16, 63, 45, 89,155, 63,230,153,244, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 72,135, 56, 63, 72,135, 56, 63, 72,135, 56, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 72,135, 56,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 72,135, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63, 72,135, 56, 0, 0, 0, 0,187,203,194, 16, 63, 45, 89,155, 63,230,153,244, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47,200,135, 57,
+178,200,135, 57, 63,128, 0, 1, 0, 0, 0, 0,176,192, 0, 0, 51,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,163,104,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 52, 33, 50, 51,206,250,252, 63,163,104,144, 0, 0, 0, 0,173,202,240, 60,
+191,163,104,144, 51,204, 63,183, 0, 0, 0, 0,187,173, 93,105,193, 88,176,172,186,118, 52, 95, 63,128, 0, 0, 0, 0, 0, 2,
+ 4, 0, 0, 0, 0, 0, 0, 68, 0, 1, 0, 2, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205,
+ 61,204,204,205, 0, 0, 0, 0, 61,117,194,143, 0, 0, 0, 0, 4, 0, 1, 1, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 32, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 29,251, 48, 7, 30, 0,144, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 64,200,128, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,228, 32, 0, 0, 0,109, 0, 0, 0, 1, 7,159,232, 32, 7,159,224, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 79, 66,112,114,101,118,105,101,119, 46, 48, 48, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 4, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 65,148,176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,200,176, 58, 10, 31, 0, 63,236, 94, 59,
+ 63,231, 84,236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,110,188, 91,
+ 63,110,188, 91, 63,110,188, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,201, 15,218,128, 0, 0, 0,128, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,110,188, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 51,151, 50, 90, 63,110,188, 91, 0, 0, 0, 0, 0, 0, 0, 0,191,110,188, 91, 51,151, 50, 90, 0, 0, 0, 0, 58, 10, 31, 0,
+ 63,236, 94, 59, 63,231, 84,236, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,127,255,254,179, 25, 53,226, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 1, 0, 0, 0, 0,174,128, 0, 1,
+179,255,255,254, 39,153, 53,226, 63,128, 0, 0, 63,137, 65,160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22,123, 29,164,
+ 63,137, 65,160, 40, 19, 46,157, 0, 0, 0, 0, 45, 14,127,248,176,150,195,159, 63,137, 65,161, 0, 0, 0, 0,188, 63, 80, 29,
+187,226, 95, 62, 65, 74, 19, 87, 63,128, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 68, 0, 1, 0, 2, 0, 0, 0, 0,
+ 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56,
+ 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205, 61,204,204,205, 0, 0, 0, 0, 61,117,194,143, 0, 0, 0, 0,
+ 4, 0, 1, 1, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 0, 0, 32, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0, 4, 13, 64,200,176, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,232, 32,
+ 0, 0, 0,109, 0, 0, 0, 1, 7,159,236, 32, 7,159,228, 32, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66,112,114,101,118,105,101,
+119, 46, 48, 48, 53, 0, 48, 48, 51, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 64,165, 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,189,195,155,128, 64,188,145, 20, 65, 88,220, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,134,180,221, 37,141,190, 48, 35, 57, 55,253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 35, 57, 55,253,165,141,190, 48, 0, 0, 0, 0, 37,112,128,219, 62,253,177, 52, 63, 94, 93, 94, 0, 0, 0, 0, 37, 22,133, 52,
+191, 94, 93, 94, 62,253,177, 52, 0, 0, 0, 0,189,195,155,128, 64,188,145, 20, 65, 88,220, 94, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 25,127,255,255,153,128, 0, 1, 0, 0, 0, 0,176, 0, 0, 0, 63,128, 0, 0, 10, 0, 0, 1, 0, 0, 0, 0,176, 0, 0, 5,
+ 51, 0, 0, 1, 63,128, 0, 1, 0, 0, 0, 0, 50, 0, 0, 0, 12, 0, 0, 0,140, 0, 0, 1, 63,128, 0, 0, 63,128, 0, 0,
+ 37,112,128,219, 37, 22,133, 53, 0, 0, 0, 0,174,231, 90, 80, 63, 94, 93, 94, 62,253,177, 52, 0, 0, 0, 0,172,239, 68, 0,
+190,253,177, 50, 63, 94, 93, 95, 0, 0, 0, 0, 61,174, 98,150,193,144,101, 85, 64,253,124,196, 63,128, 0, 0, 0, 0, 0, 64,
+ 16, 0, 0, 0, 0, 0, 0, 68, 0, 5, 0, 1, 0, 0, 0, 0, 79, 66, 0, 0, 0, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205,
+ 61,204,204,205, 0, 0, 0, 0, 61,117,194,143, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,236, 32, 0, 0, 0,109, 0, 0, 0, 1,
+ 7,159,240, 32, 7,159,232, 32, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66,112,114,101,118,105,101,119, 46, 48, 48, 54, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 65,169, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 64,200,224,
+190,252, 52, 94, 65,228,101,174, 65, 17,116,141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66, 30,239,235, 66, 30,239,236, 66, 30,239,235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 95,174,138,
+ 37,123,132, 98,165, 87, 56, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 30,239,235,168, 5,158,105,168, 28, 39,108,
+ 0, 0, 0, 0, 40, 77,129,212, 65,204, 15, 66, 65,243,186,158, 0, 0, 0, 0,165, 13, 89, 55,193,243,186,156, 65,204, 15, 65,
+ 0, 0, 0, 0,190,252, 52, 94, 65,228,101,174, 65, 17,116,141, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 25, 80, 0, 0, 25,120, 0, 2,
+ 0, 0, 0, 0, 24,216, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,153, 12, 0, 1,179, 0, 0, 1, 63,128, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 60,206, 43,101, 35, 5, 74, 25,159,183, 90,141,
+ 0, 0, 0, 0,162,202,143, 41, 60,158, 20,101, 60,132, 89,193, 0, 0, 0, 0, 34,173, 83,188,188,132, 89,192, 60,158, 20,103,
+ 0, 0, 0, 0, 60, 70,215, 11,191, 67, 43, 61, 63, 31,241,185, 63,128, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 68,
+ 0, 1, 0, 2, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100,
+ 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205, 61,204,204,205, 0, 0, 0, 0,
+ 61,117,194,143, 0, 0, 0, 0, 4, 0, 1, 1, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 64,200,224, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 79, 66,
+ 0, 0, 3, 68, 7,159,240, 32, 0, 0, 0,109, 0, 0, 0, 1, 7,159,244, 32, 7,159,236, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 79, 66,112,114,101,118,105,101,119, 99,117, 98,101, 0,117, 98,101, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 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, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 65,176,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,201, 16, 59, 88,253,128, 63,160,118,220, 64, 37, 15, 0, 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, 68, 88, 84, 64, 68, 88, 84, 64, 68, 88, 83,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,237,190, 1,190,217,230,108, 63, 52,151, 20, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 64, 8, 38, 67, 63,231,228,191, 63,162, 31,186, 0, 0, 0, 0,192, 13,118, 35, 63,220, 61, 2, 63,160, 44, 31,
+ 0, 0, 0, 0, 60,234, 52,166,191,227,223,102, 64, 31,229, 55, 0, 0, 0, 0, 59, 88,253,128, 63,160,118,220, 64, 37, 15, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0,178,155,255,255, 49, 64, 0, 2, 0, 0, 0, 0,178,211,255,254, 63,127,255,254,164,159, 0, 0,
+ 0, 0, 0, 0, 51, 2, 0, 1, 50,255,255,255, 63,128, 0, 1, 0, 0, 0, 0, 51,234, 0, 0,179,255,255,254, 37,175,128, 1,
+ 63,128, 0, 0, 62,103,115, 10,190,112,122,201, 59, 71, 17,255, 0, 0, 0, 0, 62, 9,205,116, 62, 8, 36,205, 62,135,232,136,
+ 0, 0, 0, 0,190, 69, 27, 1,190, 59, 50,224, 62, 65,176, 25, 0, 0, 0, 0,192, 16,176,110,192, 9, 71,158, 63,244, 90,115,
+ 63,128, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 68, 0, 1, 0, 2, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10,
+ 63,128, 0, 0, 62,204,204,205, 61,204,204,205, 0, 0, 0, 0, 61,117,194,143, 0, 0, 0, 0, 4, 0, 1, 1, 1, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 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, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 64,201, 16,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68, 7,159,244, 32, 0, 0, 0,109, 0, 0, 0, 1,
+ 7,159,248, 32, 7,159,240, 32, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66,112,114,101,118,105,101,119,104, 97,105,114, 0,108, 97,
+110,101, 0, 0, 0, 0, 0, 0, 0, 1, 4, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 65,141,144, 0, 0, 0, 0, 0, 0, 0, 0, 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, 65, 97,208, 13, 65, 97,208, 13, 64,201, 64,
+ 63,200, 92, 86, 63,227,205, 7,189, 9,199,149, 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, 47,126,234, 64, 47,126,234, 64, 47,126,236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 2, 80,225,
+191, 15,211, 5, 62, 18,219, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 18,254,224, 62,169,209, 23, 63,186,251, 27,
+ 0, 0, 0, 0,191,133,254, 71, 64, 17, 40,207, 63,144,194,229, 0, 0, 0, 0,191,137, 38, 78,191,192,162, 48, 64, 1,176,125,
+ 0, 0, 0, 0, 63,200, 92, 86, 63,227,205, 7,189, 9,199,149, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 1,179, 0, 0, 1,179,128, 0, 1,
+ 0, 0, 0, 0, 50,128, 0, 0, 63,128, 0, 1, 51,128, 0, 1, 0, 0, 0, 0,179,128, 0, 1,179, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 40, 12, 0, 2,180, 0, 0, 1,180, 44, 0, 1, 63,128, 0, 0, 62,156,100,244,190, 14,143,135,190, 17,235, 52,
+ 0, 0, 0, 0, 62, 70,239,175, 62, 26, 4,102, 62,137,251, 72, 0, 0, 0, 0,189, 52,172,174,190,154,112,211, 62, 76,243, 67,
+ 0, 0, 0, 0,191, 36, 56,149,192, 66, 98,139, 64, 68, 5,168, 63,128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 68,
+ 0, 1, 0, 2, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100,
+ 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205, 61,204,204,205, 0, 0, 0, 0,
+ 61,117,194,143, 0, 0, 0, 0, 4, 0, 1, 1, 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 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, 64,202, 32, 13, 64,202, 32,
+ 13, 64,201,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 64,201, 64, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,128, 13, 64,201,112, 0, 0, 0,111, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61,204,204,205, 62, 76,204,205, 60,163,215, 10, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 1, 64, 13, 64,202, 32, 0, 0, 1, 42,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 7,161, 74, 32, 12,117, 80, 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, 62,156,100,244,190, 14,143,134,190, 17,235, 52,
+ 0, 0, 0, 0, 61, 52,172,172, 62,154,112,211,190, 76,243, 69, 0, 0, 0, 0, 62, 70,239,176, 62, 26, 4,102, 62,137,251, 73,
+ 0, 0, 0, 0,191, 12,211,188,190,160,176,198, 63, 22,156, 56, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 2, 17,
+ 0, 0, 0,150, 0, 0, 0, 0, 0, 0, 0,150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 65, 97,144, 68, 65, 84, 65, 0, 0,114,216, 12,117, 80, 32, 0, 0, 1, 40, 0, 0, 0,150, 0, 0, 0, 0,192, 17,135, 20,
+192, 97,121, 36, 63,141, 32,112,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,
+191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,203,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 32, 96, 77, 62,160,201,185, 63, 6, 3,160,190,248, 34, 11, 60,185, 53,206,
+ 61,178,197,192, 63, 53,184,174,190,162,172,223, 62,224,136,109,191, 61,173,142, 60, 10, 96,180, 61,163,196,200, 63, 99,182, 78,
+ 60,180,242,165, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,150,112,248,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+192, 7, 46,111,192, 60, 26,143, 63,207,147, 28,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,
+190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,204,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,229,121, 6,191, 41, 50,108,191, 7,152,136,190,146,100,156,
+191, 25,141,146, 62,142, 92, 39, 63, 18,104,212,190,105,105,227, 62, 96,156,113,191, 69,226,137, 61, 17,247,147, 62, 44,172, 51,
+ 63, 54,125, 17, 61,169,195, 69, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 62,245, 63,144, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0,189,174,103,224,192, 17, 88, 60, 64, 76, 35,230,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,
+190,183,206,201,190, 61,137,200,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,205,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,155,160,101, 62,152, 87, 59,191, 84,199,118,
+ 62,183, 89, 86, 62,231,103,118,189,177, 47,110,191, 4, 8,155, 62,199, 60,100,189,177, 40,197, 62, 46, 14, 2, 62, 39, 96,102,
+ 61,242,119,101, 62,146,168,189, 62,221, 9, 55, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 61, 87, 36,135, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,192,131,102, 75, 63, 26,241,196, 64, 76,198,140,191, 55, 81,190,191, 71,243,107, 63, 42,237, 98,
+ 62,214,163,235,190,183,206,198,190, 61,137,206,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 64,206,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 39, 80, 49,190,218, 26,171,
+ 63, 16,118, 89,190,138, 72,130,190,122,255,169,191, 14,111,185, 63, 38,207, 21, 61,211,252, 73,191, 80,177,198,189,203,154, 43,
+ 61, 53,146,227, 63,115,180, 63, 59, 42,113,216, 58,144, 63,125, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 62,142, 95,175, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,189,226, 43, 64,191,220, 85,253, 64,101,104,225,191, 55, 81,190,191, 71,243,109,
+ 63, 42,237,100, 62,214,163,234,190,183,206,201,190, 61,137,200,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 64,207,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 45, 97,119,
+190,205, 47,119, 63, 19,117, 35, 62, 98,125,166, 62, 73,195,242, 62,243,228,124, 63, 11, 86,119, 62, 89,156, 70, 63, 88,232,230,
+190,204, 53,130, 62,128,120,250, 62, 20,194, 19, 62, 90, 15, 61, 62,200, 30, 92, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,253,129, 53, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,129,159,108, 63, 6,210, 8, 64,152,221, 35,191, 55, 81,190,
+191, 71,243,107, 63, 42,237,102, 62,214,163,235,190,183,206,200,190, 61,137,205,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 64,208,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+190,210,167, 41, 62,139,172,194, 63, 35,220,250,191, 22,182, 30, 61,136, 3,122,190,176,164,109,190,147,153, 30,188, 10,248,255,
+190,160, 90,234,190,205,241, 89, 63, 25,235,148, 62,146,172,206, 61, 52,195,137, 61,139,142, 99, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62, 77,227, 37, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,189,167,114,192,104, 59,217, 63,184,179,184,
+191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,209,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62,121, 45, 57, 63, 98,126,120,189,135,171, 60,190,200,174,139, 63, 21,142,220,191, 40, 70, 77, 62,150, 70,118,
+ 61, 92,245, 4,190,174,118,159, 63, 49,217,176, 60,104,167,120, 60,235,104,166, 63, 73,251,218, 62, 44, 25, 13, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,247, 2,217, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63, 30,112, 86,192, 82, 69,111,
+ 64, 51,191, 59,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,210,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,190,137,227, 49,191, 71,195,206,190, 96, 31, 70, 63, 5, 46,127,189,214, 51, 99,191, 67, 61,228,
+ 62, 2, 90,134,190,146,214,120, 62, 33,111, 34,190,187,229,136, 60,241,112, 27, 60,177,187, 0, 62,171,134, 4, 63, 29, 35,164,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 56,192,130, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,176,148,118,
+ 63, 1,200, 88, 64,146, 48, 89,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,
+191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,211,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190, 82,169, 42, 63, 57,214,102,191, 36,112, 55, 62, 9,205, 59, 63, 5,139,184,
+190, 43, 32,105,191, 37, 62,120, 63, 15,215,220, 63, 8, 2,180, 62,163,170,198, 63, 8,178,160, 62,184,164,185, 61, 63, 72, 68,
+ 61,112,104, 16, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,192,249, 97,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+191,168, 80,200,191,165,154, 8, 64, 80,248,229,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,
+190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,212,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 5,145, 56, 62,126, 77, 83,191, 63,133, 14, 62,167, 5,190,
+190, 96,212,123, 62,176,136,233,189, 80,193, 25, 62, 18, 49,147, 62, 25, 40,222,191, 10,204, 59, 62,104, 46,177, 62,150,106, 36,
+ 62,138, 61, 2, 62, 86,131, 4, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63, 19, 27, 39, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0,189,246,190, 0,192, 90,129,233, 64, 20,155,224,191, 55, 81,190,191, 71,243,107, 63, 42,237, 98, 62,214,163,235,
+190,183,206,198,190, 61,137,206,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,213,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 14, 77, 30, 62,154, 81,231,191, 22,220, 41,
+191, 0,189,104,190,160,167,214,190, 22, 60,140, 63, 74, 85, 37,191, 8,253, 32, 61, 23,146, 96,190,177, 30,196, 60,187, 25, 79,
+ 60,194,244,207, 62,253,234, 53, 62,234, 52,233, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63, 79, 21,218, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,190, 67,231,176,189, 11,105,144, 64,153,111,210,191, 55, 81,190,191, 71,243,109, 63, 42,237,100,
+ 62,214,163,234,190,183,206,201,190, 61,137,200,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 64,214,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,205,110, 74,191, 27,226,146,
+ 61,219, 95, 73, 63, 45, 3, 75,190,147,109,222, 63, 40,196,152,190,116,136, 36,190,190, 21,181,190,213, 38,211, 62,183,230,114,
+ 63, 24,217,206, 62, 25,222, 59, 61,134, 50, 0, 62, 63,161,139, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 62,127, 67,180, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,158,217, 58,192, 17,225,122, 64,120,158,213,191, 55, 81,190,191, 71,243,109,
+ 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 64,215,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 22, 95,176,
+190,210, 95,172,191, 46, 70,114, 62, 26, 71, 67, 61,234,164,188,191, 78,120,121,188,108,229,186,190, 72,225,144,190, 42,218,197,
+191,114,104, 83, 62, 73,213, 34, 61, 49,230,217, 61,187,117,217, 63, 42,253,143, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62, 95,144,226, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,127,205, 29,191,142,116,231, 64,100, 64,116,191, 55, 81,190,
+191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 64,216,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+189,132, 25,196,191, 41,167, 67,190,174,145,249, 63, 41,227,171, 62, 94,208, 84, 63, 50, 21, 98,191, 46,162,138,191, 56, 53,136,
+ 62,160, 44, 9,190,188, 42, 15, 62,145,124,109, 62,135, 84, 47, 62, 95, 56, 95, 62,111, 38,104, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62, 87,116,183, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 67,106,143, 62,236, 1,239, 64,105,139,230,
+191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,217,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62, 72, 62, 61, 62,176,226,147,191, 48,185, 67,191, 26,215,255,187,254,158,242,190,201,238, 89, 63, 39,166, 99,
+191, 3,238,102, 62, 10,229,206, 62,230, 53,165, 62,100,227, 37, 63, 54, 38,230, 61, 43, 4, 87, 60,190, 1,166, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61,126, 26,213, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191, 58, 63,114,191,102, 44,242,
+ 64,119,155,239,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,218,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 61,131,238,198,191, 58, 99, 49, 63, 26,180, 63,190,162, 92,201, 62,209,254,113, 63, 12, 67,151,
+ 62,197,138, 80,191, 72,116,197,190,182,129,117, 62, 76,137,180, 62,178,134,232, 62,113,134, 23, 62, 46,242,235, 62,122,121, 45,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,169, 12,248, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 62,175,173,244,
+ 61,141,194,136, 64,164,239, 0,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,201,190, 61,137,200,
+191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,219,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 28, 38,213, 60,166,248, 66,191, 67,199,227,190, 83,123,127,190,224,119,122,
+ 62,149, 46, 73, 62, 62, 43,135, 62,199,175, 30, 63, 2,224, 97, 62,250,198,180, 63, 48, 97,211, 61,130,134, 38, 61, 8, 53,167,
+ 62, 91, 40, 56, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,157,115, 93,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+192, 36,188,127,192, 42,192, 83, 63,202, 24, 20,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,
+190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,220,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190, 82,121, 10,190,216,142,233,191, 83,156, 94, 62,158, 73,222,
+ 63, 3,207,170,191, 39, 41, 63, 62,147,164, 2,191, 38,187, 36, 62,218, 1, 0,191, 32,119,145, 60,154,242,191, 62,130,165, 14,
+ 63, 49,236,127, 60,253, 44,163, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 62,130,194, 13, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63, 51,117,191,192, 44,247, 40, 64, 82, 59, 84,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,
+190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,221,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 71,176, 89,191, 18, 55,214,190,223, 82, 67,
+ 63, 50, 2,142, 61,202, 17,235, 62,199,118, 51, 63, 72,125,129,191, 36,250, 86, 61, 90, 99, 70, 63, 25, 38,125, 61,227, 50,218,
+ 61,110,152, 48, 62,104, 58,166, 63, 26,161,121, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 62, 35, 69, 21, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,192, 44,218, 23,190,159,112,131, 64, 80,196, 68,191, 55, 81,190,191, 71,243,109, 63, 42,237,100,
+ 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 64,222,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 39, 65, 62,190,203,203,175,
+191, 8, 58, 24,190,185,178,132, 63, 27,133, 48, 63, 35,150,166,189,174,164,195,189,209, 20,146,191, 3, 43,124, 63, 54,188,219,
+ 62, 53,126, 23, 63, 22,113, 93, 62, 42,104, 29, 61,140,168,166, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 62,222,122, 90, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191, 61,253,222,190, 43,216,212, 64,140,239,219,191, 55, 81,190,191, 71,243,109,
+ 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 64,223,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,251, 62, 59,
+ 62,132,207,154,191, 19,198,191,191, 25, 82,122,190,169,114,179,191, 46, 80,242,189,100, 92,161, 62,188,103,125,191, 23,234, 0,
+ 63, 22,140, 12, 62,252, 36, 24, 62,121,130,191, 61,198,245, 96, 62, 42,186, 98, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62, 89,205, 62, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,212,168,192,192, 30,175, 47, 64, 12,228, 94,191, 55, 81,190,
+191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 64,224,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 62, 6,136,242,191, 58,135,240, 61,233,198, 89, 63, 41,148, 57,190,189,188,151,190,189, 72,156, 63, 86, 14,184,190,165, 54,185,
+ 62, 49,220,131,189,189, 87, 60, 61,167,198,118, 62, 80,200, 92, 63, 10,210,157, 62, 48, 9,240, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61,181,132,186, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,190,238,184,114,191,230,206,237, 64, 85,122,208,
+191, 55, 81,190,191, 71,243,107, 63, 42,237, 98, 62,214,163,235,190,183,206,198,190, 61,137,206,191, 80, 38,157, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,225,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63, 30,165,128,190,249, 50,161,189, 86,213,180,191, 29, 10,178,191, 49,247,227,189, 7,139,215,189,154,249,222,
+191, 23, 77,153, 63, 14, 58,160, 61, 15, 47, 72, 62, 94,132,138, 62, 48,190,167, 62,136, 41,203, 62,176, 52,157, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,233,177, 38, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,104, 19, 67,191,254,122,179,
+ 64,123, 37,115,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,226,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 62,181,231, 69, 63, 51, 19, 36,191, 6, 5,126,190,170, 27,231,189, 35,253,128,189,151, 11,182,
+ 62,178,171, 74, 63, 49,231,127, 62,128,146,204, 62, 17,100, 88, 62,124,245,197, 61,130,108, 30, 61,229,152,201, 63, 19,193,242,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 79,156, 56, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,191,106,172,
+192, 42,225,110, 64,110,170, 2,191, 55, 81,190,191, 71,243,109, 63, 42,237, 98, 62,214,163,236,190,183,206,197,190, 61,137,201,
+191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,227,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 27,227, 49, 63, 26, 83, 17,191, 2,229, 27, 61,135, 48, 83, 62,134,244,199,
+190,151, 37, 55,189,237,195,210, 63, 17, 39,249, 61, 76, 1,154,191, 79,194, 75, 61,249, 99,240, 60,249, 88,190, 61,183, 20,174,
+ 63, 66, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,178, 40,150,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+192, 12, 3,121,190,252, 11, 63, 64, 89,136,146,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,
+190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,228,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 20, 59,104, 63, 17, 36, 30,190,252, 57,112, 62,162,101, 32,
+ 62,160, 6,139, 61, 80,160, 57, 61,245,243,109,190,224, 18, 41,188,227,154,182,190,139,196,238, 62,108, 28,173, 62,246,152,191,
+ 62, 61, 50,199, 61,210,254, 31, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63, 56,166, 20, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0,191,187,104,250,189,139, 86, 56, 64,131, 23,145,191, 55, 81,190,191, 71,243,107, 63, 42,237,100, 62,214,163,235,
+190,183,206,198,190, 61,137,203,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,229,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 19, 80,228,191, 16,138,118,191, 6,210,122,
+ 62,138, 14,139, 62,189, 65, 73,189,244, 89, 19, 62, 83, 5,205,190,107,159, 94, 62,255,199, 19,190, 48,124, 14, 62,208, 67, 15,
+ 62,190, 57,184, 61,219,154,119, 61,234,114,111, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 62,223, 51,203, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 62,161, 56, 52,191,207,221,255, 64,120,110,202,191, 55, 81,190,191, 71,243,109, 63, 42,237,100,
+ 62,214,163,234,190,183,206,201,190, 61,137,200,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 64,230,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 47,124,138, 63, 0,193, 12,
+ 62,176, 39,124,190,204, 3, 68, 61, 43,180,132,189,104,184, 66,191, 54,173, 69,189,116,239, 24,190, 53,183,191,190,198, 91,120,
+ 62,150, 33,123, 61,226, 30, 68, 62, 27,121,224, 62,227,154, 4, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63, 35, 22,117, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 41, 89, 63,192, 25,107,117, 63,222,245,174,191, 55, 81,190,191, 71,243,109,
+ 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 64,231,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,207,202, 66,
+ 63, 47, 32,211,191, 0,219,139,190,172,212,197, 63, 65, 68,195,190,217,152,105,190,214,218,159,190, 84,113, 85,190,158,108,194,
+ 61,235,217,229, 60,202,179, 82, 62,157,106,197, 63, 33,197,211, 61, 18,243, 9, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,102,162, 1, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,220,238, 94,191,150, 70, 91, 64, 72,192,203,191, 55, 81,190,
+191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 64,232,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63, 22, 95,176,190,210, 95,172,191, 46, 70,114, 62, 26, 71, 67, 61,234,164,188,191, 78,120,121,188,108,229,186,190, 72,225,144,
+190, 42,218,197,191,114,104, 83, 62, 77,183, 13, 62,182,153,158, 62,143, 59, 65, 62, 38,159, 52, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62, 95,144,226, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192,116,234, 61,188,238,101,224, 64, 56, 20,165,
+191, 55, 81,190,191, 71,243,107, 63, 42,237,100, 62,214,163,235,190,183,206,198,190, 61,137,203,191, 80, 38,157, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,233,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62, 6,136,242,191, 58,135,240, 61,233,198, 89, 63, 41,148, 57,190,189,188,151,190,189, 72,156, 63, 86, 14,184,
+190,165, 54,185, 62, 49,220,131,189,189, 87, 60, 60,242,255, 31, 63, 83,194,231, 62, 5, 56,189, 60, 85,188, 68, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61,181,132,186, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,189,240,209,128, 63, 95,183,178,
+ 64,176, 67, 5,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,201,190, 61,137,200,191, 80, 38,158,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,234,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,191, 86,114,107,191, 2,141,137, 61,105,140,227,190, 63,121, 70, 62,218,242,130,190,132,163,237,
+ 60, 16,235,219, 62,248,203, 85,191, 80,244, 79, 62,148, 0,103, 63, 85,189,153, 61,200,104,151, 60,142, 55,246, 61, 76, 57, 74,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 33,252, 31, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 25, 54,206,
+ 62,162,197,171, 64,121, 16, 6,191, 55, 81,190,191, 71,243,109, 63, 42,237, 98, 62,214,163,236,190,183,206,197,190, 61,137,201,
+191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,235,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,244,100,219,191, 91, 69,182,189,144,137, 60, 62, 59,126,161,190,200,228, 28,
+ 62,170, 49, 60,189,250,139,225, 62,111,143,244,191,100,103,252, 62, 79, 32,148, 62,163,246,104, 63, 16,201, 91, 61,136,104, 24,
+ 61, 66,230,227, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 41, 88,182,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+192, 61, 57, 29,191, 39, 53,236, 64, 55,221,173,191, 55, 81,190,191, 71,243,107, 63, 42,237,100, 62,214,163,235,190,183,206,198,
+190, 61,137,203,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,236,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190, 35, 43,167, 61,225,210,242, 63, 30, 58,197, 63, 67, 8,229,
+ 61,222,176,215, 63, 12, 15, 70, 62,165,195, 80, 61,227, 72,218,191, 87, 66,188, 62,195,213,145, 61,212,218, 39, 63, 25, 20,242,
+ 62,118, 70,122, 61,107,226,159, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63, 64, 74,173, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0,191, 40, 62,249, 63, 26,113, 16, 64,160,179, 50,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,
+190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,237,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,224, 29,190, 63, 4, 44,239, 63, 49,217,125,
+190,121, 25,107, 62,217,172,117,190,116, 98,242, 63, 42,162,148,190,199,178,142,191, 13,105, 54,190,163,107, 83, 63, 45,186, 64,
+ 62, 91,122,109, 61, 21,134, 32, 61,144,118, 21, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63, 73,107,113, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,191,138, 51, 90,192,110, 14,199, 63,203, 66, 18,191, 55, 81,190,191, 71,243,109, 63, 42,237,100,
+ 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 64,238,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 39, 78, 36,190,251, 50,128,
+190,189,185,139, 62,226, 4,175,190,153, 23,118,190,120,228, 67,191, 42,226, 50,191, 86,243,239,190,189, 42, 37,190,190, 1, 66,
+ 59,153,223,235, 59,243,174, 21, 63, 60,160,231, 62,128,135,251, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 62,105,245,167, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,186, 75, 44,191,204,205,170, 64, 61,169,132,191, 55, 81,190,191, 71,243,109,
+ 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 64,239,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,155,223,118,
+191, 3,196,249,190,163, 12,115,191, 60, 73,212, 62, 85,208, 59, 62,155, 11, 65,189,173, 17, 28,190,254, 16, 20, 63, 32,229,213,
+189, 28,221,216, 62, 52, 19, 79, 62,146, 52,229, 62,171,228,191, 62, 79,185,106, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 37,184, 45, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,219,119, 4,192, 28, 73,231, 64,128,117, 83,191, 55, 81,188,
+191, 71,243,109, 63, 42,237,100, 62,214,163,233,190,183,206,202,190, 61,137,201,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 64,240,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 62,254,109,168, 63, 4,146,210, 63, 23,131,232, 62,187,212, 66,190,158,109, 9, 62,216, 12, 71, 59,153, 20, 64, 62, 7, 2, 11,
+ 62, 91,134, 92,191, 33,128, 43, 62, 51, 75,186, 60,144,251,206, 61, 19, 49,198, 63, 69,114, 22, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,115,100,221, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,194, 59,172,192, 13, 29, 35, 64, 30,208, 13,
+191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,241,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62,155,223,118,191, 3,196,249,190,163, 12,115,191, 60, 73,212, 62, 85,208, 59, 62,155, 11, 65,189,173, 17, 28,
+190,254, 16, 20, 63, 32,229,213,189, 28,221,216, 61,227, 31, 97, 62,104,207,168, 62,237, 89, 38, 62, 74,238, 93, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 37,184, 45, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 82,190,197, 62,174,148,251,
+ 64, 91,189, 29,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,242,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,191, 10,132,170, 62,237, 61, 82,190,223,191,127, 63, 12,148, 11, 62, 92,142,236, 63, 32,199, 17,
+189,242,206,157, 63, 15,114,199,191, 33, 82, 91,190,167,247, 3, 62, 37, 10,210, 63, 65,152,124, 61,106,110, 28, 60,207,189,179,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,140, 23, 40, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,190,163,157,120,
+ 63, 33,219, 44, 64,167, 25,250,191, 55, 81,190,191, 71,243,107, 63, 42,237,102, 62,214,163,237,190,183,206,199,190, 61,137,206,
+191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,243,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 4,175,102,190, 50,200,160, 63, 77,214,248,190,110,194,226, 61,198, 10,138,
+ 62, 62,213,210, 61,253,163,141, 61,160,130,106,191,101,229,201, 62, 50,145,103, 63, 61,192, 52, 62, 23, 50, 16, 61, 1, 56, 40,
+ 61,162,254, 43, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 60,220, 81, 89,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63, 79, 63,131,191,203,225, 22, 64,133, 83,183,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,
+190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,244,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,194,155, 70,191, 3, 93, 82,191, 19,133, 23,191, 2,146,179,
+ 62,104,198,131, 63, 93,189, 15,190,209,226, 77,191, 21,122,159,190,234,192,169, 63, 35,128, 16, 62,167,188, 9, 61,138,167,141,
+ 61,185,163,186, 63, 3,152,147, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 59,236,249, 25, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62, 89,218, 20,192, 81, 21,169, 64, 38,226, 50,191, 55, 81,190,191, 71,243,107, 63, 42,237, 98, 62,214,163,235,
+190,183,206,198,190, 61,137,206,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,245,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 52,169,139, 62,156,163, 97,190,184,132, 26,
+ 63, 7, 25, 82, 62,151,117,127, 62,247,206,254, 63, 76,144, 27, 62,204, 57,150,188,246,181,184, 63, 19,222,196, 61, 18,237,175,
+ 61, 0, 0, 50, 62,208, 45,180, 63, 6,186, 72, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 62,186,195, 61, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,190,166, 91,192, 62,151,138,203, 64,159, 4,232,191, 55, 81,190,191, 71,243,109, 63, 42,237, 98,
+ 62,214,163,236,190,183,206,197,190, 61,137,201,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 64,246,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 7,240,212,191, 18, 2,213,
+191, 5, 90,228, 62,178, 92,221, 63, 16,236, 8, 62,151,216, 90, 62,128,193,155,188,245, 60, 56,190,160,129,118,191,113,157, 47,
+ 63, 40,117,114, 62, 37, 92,164, 61, 78,198, 72, 62, 5, 28, 6, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 62,226, 96,137, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,191,137,104,190,208,156,143, 64,116,245,234,191, 55, 81,190,191, 71,243,109,
+ 63, 42,237, 98, 62,214,163,236,190,183,206,197,190, 61,137,202,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 64,247,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 49,218,173,
+191, 23,109,113, 62, 55, 16, 32,190,188,117, 54, 62,208, 20, 25,191, 46,245,118,186,236,158, 72,191, 97, 10, 55, 62,183,128,140,
+190,146,230,177, 62,174,217,121, 62,188, 55, 45, 62, 25, 76, 41, 62, 16,146,138, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 48, 85, 96, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191, 78, 6,218,191, 2,247,240, 64,131,181, 2,191, 55, 81,190,
+191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 64,248,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+189,236, 25,179, 63, 27,158,127, 62,239,235,123, 63, 33,108, 59,190,103,198,244, 62,187,192,251,190,101, 39,179, 62,138,210,110,
+191, 54,168,145,190, 63, 20,208, 62,211,209,237, 62,129,168, 1, 62, 7,237,108, 62, 77, 30,188, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,109,210, 2, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,251,181,100, 63, 79, 67,160, 64,143,115, 83,
+191, 55, 81,190,191, 71,243,109, 63, 42,237, 98, 62,214,163,236,190,183,206,197,190, 61,137,201,191, 80, 38,157, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,249,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 61,237,243,122,190,169,234, 11,191, 55,226,211,191, 25,175,184, 63, 39,201, 24,190, 71, 23,204, 62,218, 61, 87,
+ 63, 39,211, 31,190,215,101,108,189,244,125, 35, 62,250, 56, 31, 62,248,208,174, 60, 79, 43, 50, 60, 79,186,252, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61,186,130, 83, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 16,143,166,192, 31, 40,219,
+ 63,240,165,188,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,250,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,191, 15,157,192,190,205, 51, 47,190,136, 40,152, 63, 44,122,128, 63, 92,144,194,190, 99, 36,235,
+190,206, 22,244, 62,220, 32,143, 63, 19,244,169,189,238,205,160, 61, 69,255, 93, 62,129,237,131, 63, 29,113,199, 61,169,188, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61,151,139,249, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 46, 16, 47,
+ 62, 17,135,234, 64,101,174,196,191, 55, 81,190,191, 71,243,107, 63, 42,237,100, 62,214,163,235,190,183,206,198,190, 61,137,203,
+191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,251,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,162,110,186,190,105,104,145, 62,239,168,247, 63, 74,235, 3,190,178, 77,140,
+ 63, 72, 49, 80, 62,112, 45,164, 63, 44,101, 43, 62,173,162, 95,190,104,215,180, 62,112,185,132, 63, 31,198, 76, 61,186,148, 82,
+ 61, 75,140,149, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61,120,174,161,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+192, 34, 76,221,191,220, 63,195, 64, 19, 92,101,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,
+190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,252,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 32, 89,101, 63, 82, 91,234, 60, 86, 78,243, 63, 12, 61, 22,
+190,178,120,249,191, 37, 19,203, 63, 24, 65,128, 63, 52,226,196,191, 0,214,219,190,210,228,203, 61,144, 5,191, 62,203,251, 27,
+ 62,232,217, 8, 61,156,169,185, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 62,113,165, 7, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0,191,208,209, 0,192, 57, 98,175, 63,244, 39,214,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,
+190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 64,253,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 6,136,242,191, 58,135,240, 61,233,198, 89,
+ 63, 41,148, 57,190,189,188,151,190,189, 72,156, 63, 86, 14,184,190,165, 54,185, 62, 49,220,131,189,189, 87, 60, 61,100,142, 40,
+ 62, 18, 81,206, 63, 34,238, 52, 62, 40,209,214, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 61,181,132,186, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,192, 19,146,156, 63, 38,169,132, 64,133,240,119,191, 55, 81,190,191, 71,243,109, 63, 42,237,100,
+ 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 64,254,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191,104,191,123,190,172, 12, 91,
+ 62,112, 97,100, 61,150, 67,240, 61,241,234,237,190, 65, 15,121, 62, 61, 2,224,190,233, 38,159,187,191, 62,118, 63, 29,119,107,
+ 62,202, 98,177, 63, 14,134,157, 60,213,140,246, 60,179,116, 97, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63, 69,173,159, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,211,209,100,192, 64, 57, 80, 64,100, 52,239,191, 55, 81,190,191, 71,243,109,
+ 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 64,255,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,157, 46,129,
+191, 47,142,239, 60,219,129, 7, 63, 40,203,124,189,122,175, 5, 62,139, 33,180, 61, 63, 8,162,191, 26,191, 75, 61,189,191, 52,
+190,100,188,125, 61,112,222,131, 60,161,149,150, 61,202,188,127, 63, 82,141,219, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 58, 78, 34, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 62,195, 40,204,192, 22, 66,169, 64, 88, 69, 56,191, 55, 81,190,
+191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 0,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63, 25, 69,168, 62,124,123, 76,191, 32,238,100, 62,220,140,234, 61,120,159, 84, 61,244,254,187, 63, 59,215,103,190, 71,235,244,
+191, 73,172, 9,190,165,228, 94, 62, 39,198,237, 61,180,166,232, 62,106, 45, 33, 63, 4,238, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,104,255,128, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,124, 41,179,192, 92, 52,215, 64, 56,194, 1,
+191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 1,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62,175,191,249, 63, 67,210, 72,190,255, 44, 91, 62, 97,232, 36,191, 70, 89,183,190,246, 37, 58, 61,211,174,112,
+189,119,174,231,191,119, 2,237, 62, 35,205,180, 59,158,119,225, 59, 89,185, 62, 62,150, 41, 58, 63, 50,212,186, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 32,102, 78, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 66,215, 78,189, 17,102, 16,
+ 64, 82, 64,251,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 2,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,190,158, 15, 40,191, 27, 48, 97,191, 41,181, 48,190,160, 19, 31,189,153, 23, 91,190,110,243,100,
+190,164,169,182,191,120,129, 97, 60, 90,101,145, 61,186, 53,193, 62, 31, 65, 94, 63, 45, 57,152, 61,248,240,117, 61, 61,128, 59,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61,137, 79,196, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,243,234,243,
+192, 50,199, 12, 64,118,173,246,191, 55, 81,192,191, 71,243,107, 63, 42,237, 98, 62,214,163,235,190,183,206,197,190, 61,137,205,
+191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 3,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,136,137,130,191,106, 7,101,190,155,249,249, 60,155,218,146,188,184,212,179,
+189,201,215, 68,191, 61,244, 40, 61, 70,234,114,191, 1,226,154, 63, 91,139,119, 61,207, 64,202, 60, 89,106, 46, 61, 13, 53, 30,
+ 63, 89,222,236, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 87, 40, 6,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+191, 54,176,174,191,187,173, 99, 64, 93, 31,209,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,
+190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 4,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 71,176, 89,191, 18, 55,214,190,223, 82, 67, 63, 50, 2,142,
+ 61,202, 17,235, 62,199,118, 51, 63, 72,125,129,191, 36,250, 86, 61, 90, 99, 70, 63, 25, 38,125, 62,129,144,101, 62, 91, 1,185,
+ 62,121, 67, 60, 62,148, 77, 32, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 62, 35, 69, 21, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0,192,100,131,238,191, 81,185,222, 64, 27, 50, 40,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,
+190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 5,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190, 35, 43,167, 61,225,210,242, 63, 30, 58,197,
+ 63, 67, 8,229, 61,222,176,215, 63, 12, 15, 70, 62,165,195, 80, 61,227, 72,218,191, 87, 66,188, 62,195,213,145, 60, 70,146,197,
+ 63, 44,125, 83, 62,156,124, 64, 60, 10,144,125, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63, 64, 74,173, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,190,248, 77,226,190,103,109, 12, 64,143,231,230,191, 55, 81,190,191, 71,243,107, 63, 42,237,100,
+ 62,214,163,235,190,183,206,199,190, 61,137,204,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 65, 6,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,251, 62, 59, 62,132,207,154,
+191, 19,198,191,191, 25, 82,122,190,169,114,179,191, 46, 80,242,189,100, 92,161, 62,188,103,125,191, 23,234, 0, 63, 22,140, 12,
+ 63, 3,173, 53, 62, 78,233,187, 61,187,225, 77, 62, 68,112,203, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 62, 89,205, 62, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 64, 10, 80,129,192, 74,130,253, 64,109,179,124,191, 55, 81,190,191, 71,243,109,
+ 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 65, 7,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 71,176, 89,
+191, 18, 55,214,190,223, 82, 67, 63, 50, 2,142, 61,202, 17,235, 62,199,118, 51, 63, 72,125,129,191, 36,250, 86, 61, 90, 99, 70,
+ 63, 25, 38,125, 60,202, 2,215, 59,181,116, 38, 60,204,167,240, 63,113,223,193, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62, 35, 69, 21, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 55, 37, 73,191,210, 44, 92, 64, 12, 20,134,191, 55, 81,190,
+191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 8,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63, 15, 7, 34,190, 46,194,135, 62,148, 82, 36,191, 66, 22,185, 63, 53,135,211,190,172, 29,111, 62,229, 68,200, 62,140,167,253,
+190, 99,223,181,190,176,226, 35, 61, 50,158,144, 62,230,247, 53, 62,236, 25,253, 61, 52,215,226, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,214,199,202, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,152,163, 4,192, 16,189,233, 64, 39, 29,148,
+191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 9,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,189,236, 25,179, 63, 27,158,127, 62,239,235,123, 63, 33,108, 59,190,103,198,244, 62,187,192,251,190,101, 39,179,
+ 62,138,210,110,191, 54,168,145,190, 63, 20,208, 61,250,136,113, 62, 71, 45,109, 62,222,240,248, 62,125,172,108, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,109,210, 2, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,213,219, 83,192, 77,221,119,
+ 64, 90,157, 98,191, 55, 81,192,191, 71,243,107, 63, 42,237, 98, 62,214,163,235,190,183,206,197,190, 61,137,205,191, 80, 38,158,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 10,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,191, 4,225, 56, 63, 35,172,239,191, 4, 44, 92,190,112,166, 88,190,176,149,229, 63, 6,184,233,
+191, 44,120, 91, 63, 20, 36,208, 63, 79, 84,165, 61, 89,145,190, 60,192,154,154, 60, 43,233,206, 62, 0, 13, 68, 63, 87, 72, 51,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 32,131, 34, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,106, 39,118,
+ 63,114, 29,130, 64,164,123,156,191, 55, 81,190,191, 71,243,107, 63, 42,237,102, 62,214,163,235,190,183,206,200,190, 61,137,205,
+191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 11,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 45, 97,119,190,205, 47,119, 63, 19,117, 35, 62, 98,125,166, 62, 73,195,242,
+ 62,243,228,124, 63, 11, 86,119, 62, 89,156, 70, 63, 88,232,230,190,204, 53,130, 63, 54, 27,149, 62,133, 38,243, 60, 53, 55,232,
+ 60,143,130, 91, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,253,129, 53,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+192,102, 71, 4,190,194,109,241, 64, 47, 39,108,191, 55, 81,192,191, 71,243,107, 63, 42,237,100, 62,214,163,233,190,183,206,198,
+190, 61,137,204,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 12,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,188,105,157,127, 62,184, 8,148,191, 7,109,181,191, 68,194,177,
+190,220, 77,163, 63,101,120, 58, 61, 25,105,241, 62, 86,197, 69,190,236, 78,214, 63, 46,136,126, 61, 22,203,152, 63, 61,161,132,
+ 62, 79,196, 67, 60,160, 22, 79, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63, 93,148,112, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,214,224, 12,192, 5,182,225, 64,136, 59,246,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,
+190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 13,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 24, 46,192,191, 43, 20, 41, 62,183,184,186,
+ 62,136,173, 42, 63, 50, 75, 75, 62,126, 83, 40, 63, 8,195,188, 62,238,211,234, 61,152, 36, 69, 62,145,106,235, 62,131, 28,211,
+ 60, 46,255, 24, 60,139,165, 11, 63, 55, 88,113, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63, 57,122, 93, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63, 92,158, 95,192, 67,243,117, 64, 70,154, 16,191, 55, 81,190,191, 71,243,109, 63, 42,237,100,
+ 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 65, 14,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 4,175,102,190, 50,200,160,
+ 63, 77,214,248,190,110,194,226, 61,198, 10,138, 62, 62,213,210, 61,253,163,141, 61,160,130,106,191,101,229,201, 62, 50,145,103,
+ 61,104, 55,112, 61, 9, 23, 14, 62,129, 82,208, 63, 40, 65,176, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 60,220, 81, 89, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 31,234, 87,192, 65,234,204, 63,172,200,110,191, 55, 81,190,191, 71,243,109,
+ 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 65, 15,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 99,180,162,
+ 62,145,169,127, 62,174, 95,114,189,223,121,169, 63, 73,190,173,190, 51, 72,118,190,162, 48,116,189,139, 98, 59, 62,191,245, 77,
+ 61,253,124, 75, 60, 48,252,197, 62, 62,176,163, 63, 72, 93,216, 60,166, 65, 94, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 12, 69, 81, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,189,122, 76,191,102,243,238, 64, 93,253,158,191, 55, 81,190,
+191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 16,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+189,218,139, 33,190,222, 81,160,190,151, 71, 75,191, 88, 33, 47,190,128,174,152,190,107,218, 43,190, 66, 96, 40,190,113, 29,219,
+190,184,240, 89, 62,204, 92,153, 62,135,159,101, 62,174,216,253, 62, 96, 99,217, 62, 50,171,104, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61,207, 27, 5, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63, 67, 75,227, 61, 78,124, 48, 64,171,150,200,
+191, 55, 81,190,191, 71,243,107, 63, 42,237,100, 62,214,163,235,190,183,206,198,190, 61,137,203,191, 80, 38,157, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 17,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,190,190, 19, 92, 62,147,203,188, 62, 2,242, 19, 63, 95,138,223, 60, 24, 50,144, 63, 64,174,148,191, 11,158,196,
+ 63, 64, 22,220,190, 19, 35, 98, 62, 44, 93,217, 63, 58,115,191, 60, 2,198,121, 59,167,102,254, 62,132,100,178, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62, 27,176,189, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 62,139, 37, 24, 63, 62,231, 4,
+ 64,179,205,174,191, 55, 81,188,191, 71,243,107, 63, 42,237,102, 62,214,163,235,190,183,206,200,190, 61,137,206,191, 80, 38,156,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 18,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 60,239,220, 87,191, 46,204,168, 61, 84, 95, 78,191, 58,105, 8, 63, 43,245,231, 62,151,254, 91,
+ 61,206,143, 77, 63, 42,139,177,190,196,107, 26,190,139,211,150, 63, 92, 23, 50, 61, 15, 27,169, 60, 83, 43, 8, 61,189, 83, 59,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 49,221,121, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,225,247, 32,
+192, 81,175, 37, 63,198,254,248,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,
+191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 19,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,130,132, 59,190,120,166,131,191,109,191, 15, 61,238,164,170,190, 78, 93, 20,
+189,231,164,245, 62, 16,254,254,190,234,189, 61,189,116,167,116, 63, 16,175, 67, 61, 2,132, 66, 61,189, 37,191, 63, 64, 5,173,
+ 62, 0,181, 91, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 2, 93,129,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 61,165,110,200, 62,239, 43,183, 64,169,243,129,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,
+190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 20,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 49,218,173,191, 23,109,113, 62, 55, 16, 32,190,188,117, 54,
+ 62,208, 20, 25,191, 46,245,118,186,236,158, 72,191, 97, 10, 55, 62,183,128,140,190,146,230,177, 63, 66,109, 62, 61,170,159,244,
+ 60,243,150, 79, 62, 2,136, 69, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63, 48, 85, 96, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0,191,243,158, 12,192,104,237,244, 63,155, 34,138,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,
+190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 21,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 49, 22,155, 62,165,232,223,191, 6,208,133,
+190,190,253, 93,190,194,234,190,191, 29, 89,239,191, 23,110,134,191, 30,217, 8,190,205,159,107,190,185, 94, 18, 60, 92,106,228,
+ 61, 35, 25, 23, 63, 93,111,136, 61,167,105,211, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 62,132,153,252, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63, 8, 74,118,192, 1,240, 0, 64,108,123, 28,191, 55, 81,190,191, 71,243,107, 63, 42,237,102,
+ 62,214,163,235,190,183,206,200,190, 61,137,205,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 65, 22,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,104,155,217,190, 29,164,215,
+190,179, 60,175, 62, 43,201,201, 61, 67, 60,100,189, 90, 42,171,191, 4, 85, 68, 62,130,249, 67,190,133,199,230, 63,107, 14,149,
+ 62,101,242,233, 61,181,120,181, 62, 43,136,231, 63, 4,241,245, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,108,179,252, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,231, 24, 26,191, 21,105, 44, 64, 98, 32,186,191, 55, 81,190,191, 71,243,107,
+ 63, 42,237,100, 62,214,163,235,190,183,206,198,190, 61,137,203,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 65, 23,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 49, 52,126,
+ 63, 43, 9,201,190, 96,234,166,190, 37,210,182, 61, 54, 58,206, 63, 63, 1,231,191, 34,173,133,190,170,154, 5, 63, 51,112, 93,
+191, 23, 61, 18, 62,138,189, 66, 62,210,103,114, 62, 62,128,117, 62, 7, 54, 35, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,126,132, 33, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191, 5, 52,141,192, 49,103, 10, 64, 37,154,230,191, 55, 81,190,
+191, 71,243,107, 63, 42,237, 98, 62,214,163,235,190,183,206,198,190, 61,137,206,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 24,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63, 32, 96, 77, 62,160,201,185, 63, 6, 3,160,190,248, 34, 11, 60,185, 53,206, 61,178,197,192, 63, 53,184,174,190,162,172,223,
+ 62,224,136,109,191, 61,173,142, 61,184, 47,132, 61,207,157,244, 62,225, 0,168, 62,189, 11,249, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,150,112,248, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,177, 45,136, 63, 99,253, 22, 64,155, 58, 8,
+191, 55, 81,190,191, 71,243,109, 63, 42,237, 98, 62,214,163,236,190,183,206,197,190, 61,137,202,191, 80, 38,157, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 25,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63, 55,202, 47,190, 89,235,249,190, 92, 18,127,191, 32,129,146,190, 8,212, 7,190,171, 50,167, 62,123,120, 97,
+189,249,152,232, 62,149, 18,140, 61, 13,111, 37, 63, 28,253,147, 62,184,184,231, 60, 58, 48, 48, 60,111, 78, 59, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 18, 61,115, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191, 57,255, 42,192, 65, 4,235,
+ 64, 19, 7, 77,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 26,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,189,133,218,208,189,176, 10,116, 63, 10,237,186, 63, 85, 61, 14,190, 38,219,182, 62,206,175,174,
+ 63, 10,240, 47,190,114,232, 31,190,207,162, 91,190,193, 85,173, 61,128,255,228, 61,172, 32, 76, 63, 5,152,147, 62,169,134,205,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 60,212, 38, 62, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,137, 68,184,
+ 61,226,177,204, 64,141,247,196,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,
+191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 27,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61,146,138,133,187, 8, 75,133, 62, 68,235, 28, 63,122,141,122, 63, 92,117,116,
+190,125,147, 7,190,147, 49, 87, 63, 41, 88, 9, 63, 2,255, 63, 61,126, 44, 71, 63, 0,166,107, 62,154, 29, 23, 61,165,214, 34,
+ 61,236,130, 42, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,103,170,241,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+192, 82,103, 22,191,201, 75, 73, 64, 0,247, 1,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,
+190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 28,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,168,120,231,191, 7,154,179, 63, 48,180, 41,190,187,232,239,
+191,104, 35, 9, 62,114, 8,222,190,177,143, 76,191, 28, 29,107, 62,234,112,210,190, 92,249, 9, 59,118,109, 73, 63, 4,155,168,
+ 62,243, 2, 73, 59,108,198,186, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 62,184, 4, 74, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0,191,246,241,194, 62,236,130, 87, 64,135,209, 50,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,
+190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 29,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,223,197,124,190,189,243, 32,190,140,213,199,
+191, 69,149, 13,190,199,235,221, 62,240, 79,159,190, 14,202,113,190, 60,168,186,190,220,145, 5, 62,148, 8, 42, 62,219, 99, 49,
+ 62,242, 73, 85, 61, 79, 14,127, 61, 67,141, 68, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 62,192,236,157, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,189,149,228,224,190,221, 13,233, 64,145,251,210,191, 55, 81,190,191, 71,243,107, 63, 42,237,100,
+ 62,214,163,235,190,183,206,199,190, 61,137,204,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 65, 30,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,190, 19, 92, 62,147,203,188,
+ 62, 2,242, 19, 63, 95,138,223, 60, 24, 50,144, 63, 64,174,148,191, 11,158,196, 63, 64, 22,220,190, 19, 35, 98, 62, 44, 93,217,
+ 63, 4,141,198, 62, 19, 71, 3, 61,174,186, 60, 62,129,146, 99, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 62, 27,176,189, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 62, 89,120, 0,190,120,169,164, 64,155, 78, 26,191, 55, 81,192,191, 71,243,109,
+ 63, 42,237, 98, 62,214,163,234,190,183,206,197,190, 61,137,202,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 65, 31,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 94,201,118,
+ 62,213,189,192, 62, 67, 27,142,190, 55, 93,214,190,131,154, 6,190,178, 48,133,190,192, 11,139,189,147,123, 39,191, 57,130, 29,
+190, 33,253, 46, 63, 24, 89,224, 61,198,174,189, 61,101,152, 2, 62,128,237,143, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,117,122, 59, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 26, 80, 92,189,239, 3,232, 64, 99,210,182,191, 55, 81,190,
+191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 32,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+190,153, 16,148,191, 33, 1,224, 62,168,253, 43, 63, 35, 36,254,191, 19,255,124,190,138, 97, 70, 62, 6,109,188,190,223, 58, 64,
+189,189,121,154, 62,170,126, 9, 62,126,248,115, 63, 12, 41, 84, 62, 4, 55,153, 61,152, 85, 62, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61,106,244, 74, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,190, 70,245, 80,192, 37,148,136, 64, 57,107, 41,
+191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 33,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62,249,246, 44, 62,140,102,200, 63, 10,199,154, 63, 32,102, 40,191, 19, 10, 78,190,250,238,224,190,111, 13, 0,
+ 61,187,232,243, 62, 99, 10,106, 62,221, 96,163, 61,239,237,208, 61,210, 34, 10, 62,181,101, 62, 62,218, 22,205, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 25,143, 35, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191, 25,172,253,191,249,234, 68,
+ 64, 73,217, 59,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 34,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 62,230,109,205,190,189, 47, 67,189,155,119,205,191, 79, 53,238,191, 88,144,223, 62,146,163, 88,
+190,208, 99, 63, 62,130,235,236,190, 17, 10, 72, 63, 15,223,124, 62, 64,172, 12, 62, 51, 24,160, 62,156, 49,145, 62,169,236, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 72,237,254, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 60, 63, 77,
+191,245, 70,192, 63,248,177,246,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,
+191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 35,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 16,162, 50,190,219,180, 33,190,177,166, 24,191, 29, 8,234,190, 48, 26, 24,
+190,115, 70,240, 63, 54,197, 0, 62, 75,201, 69,189, 10,174, 28, 63, 78,128, 81, 60,175,109,172, 62,214,135, 7, 63, 9, 12, 59,
+ 60,198,154,150, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,138, 50, 34,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,162,125, 6,192, 64,233, 63, 64, 86,167,147,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,
+190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 36,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 11,120,234,190,253, 35,200,190,233,152, 2,191, 0, 38, 0,
+191, 36, 3,214,190, 45,239, 3,191, 9,175,135,190, 42,130, 18, 63, 38,197,156,190,238, 37,181, 61,119, 49, 4, 60,224,251,119,
+ 62, 47, 5, 94, 63, 61,195,188, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 62,191,162, 89, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0,192, 27, 96,184,191,179, 23,251, 64, 38, 77,193,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,
+190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 37,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 32,231,177, 62,239, 89,150,190,188,156,128,
+191, 0, 45,225, 62,210,133,247, 63, 40,169, 51, 63, 26,184,146,190,223, 39,209,191, 15,238,182,190,146, 63, 75, 61,213,161,166,
+ 62,218,242,217, 62,191, 18, 39, 61,194, 74, 89, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 61,129,236, 81, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,191, 21, 0,185,192, 14,241,137, 64, 61, 27,206,191, 55, 81,190,191, 71,243,109, 63, 42,237,100,
+ 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 65, 38,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,213, 79,214, 63, 10, 19, 95,
+191, 56, 25, 60, 62, 10,193,193,190, 10,232,127,190, 93,126,162, 63, 7,169, 25,190,221,209, 38, 62,186,214, 52,191, 41, 63, 21,
+ 62, 27, 36, 58, 62, 28,151,245, 62,179, 23, 82, 62,177, 10,148, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63, 41,241, 98, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,189, 57, 80, 64,191,166, 80,193, 64,123,172,242,191, 55, 81,190,191, 71,243,109,
+ 63, 42,237,100, 62,214,163,234,190,183,206,201,190, 61,137,200,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 65, 39,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,232,174,160,
+ 61,164, 99, 64, 63, 12,108, 41,191, 50,126,106, 62,124,117, 66, 63, 82, 54,134, 62,191, 55, 38,190,197,232,121,189, 70,203,188,
+191, 51, 88, 26, 62,170,225,199, 62, 23, 67,114, 62, 33, 56,202, 62,184,224, 26, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61,138,213,216, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,190,219,106,202, 63,127,216, 17, 64,173,251,140,191, 55, 81,190,
+191, 71,243,110, 63, 42,237, 98, 62,214,163,235,190,183,206,198,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 40,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+190,213, 79,214, 63, 10, 19, 95,191, 56, 25, 60, 62, 10,193,193,190, 10,232,127,190, 93,126,162, 63, 7,169, 25,190,221,209, 38,
+ 62,186,214, 52,191, 41, 63, 21, 63, 79,203, 10, 62, 32, 14,104, 60, 44,238,252, 60,175,180, 55, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 41,241, 98, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 91, 39,111,191,150, 81, 64, 64, 15, 68, 89,
+191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 41,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,191, 0,212,130,191, 38,161, 15,190,123,203,131,191, 3, 48,207, 63, 64, 6,112,190, 34, 53,137,191, 6,202,175,
+ 62, 19,241, 66,190, 85,105,119, 61,146,246,149, 60, 25, 88, 25, 63, 25, 74, 85, 62,196,185,199, 59,249,179,210, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 90,223,198, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63, 40, 17,231,190,153, 44,141,
+ 64,161,123, 68,191, 55, 81,190,191, 71,243,107, 63, 42,237,102, 62,214,163,235,190,183,206,200,190, 61,137,205,191, 80, 38,157,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 42,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63, 68,219, 69, 62, 74, 75,190, 62,229,129,250,190,210, 78,198,188, 59, 63, 65, 62,214,173,173,
+ 62, 85,159, 18,189,185,160, 25,191, 46,193,169,190, 77, 21,177, 63, 32,133,202, 61, 36,163, 25, 60,225,136, 45, 62,156, 71,133,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61,141,208, 22, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,160, 95, 50,
+191,249,101, 34, 64,132, 96,176,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,
+191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 43,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,189,236, 25,179, 63, 27,158,127, 62,239,235,123, 63, 33,108, 59,190,103,198,244,
+ 62,187,192,251,190,101, 39,179, 62,138,210,110,191, 54,168,145,190, 63, 20,208, 62,138, 45, 62, 61, 30,142, 35, 61,128, 78,173,
+ 63, 32,246,170, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,109,210, 2,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+192, 6,133,111,191,225,152,167, 64, 32, 16, 84,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,
+190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 44,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,241, 57,184, 62,173,244,209, 61,188,195,202, 63, 79, 10,229,
+191, 34,223, 15,190, 40, 65,171, 61, 38,228,158, 63, 12,225,187,189, 13,196,198,191, 14,253,185, 61,217,107,245, 62,174,147,253,
+ 62,218,232,227, 62, 0, 80, 70, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 62,183,168, 8, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0,190,228, 99, 80,191, 51, 59, 44, 64,133, 75,221,191, 55, 81,192,191, 71,243,109, 63, 42,237, 98, 62,214,163,234,
+190,183,206,197,190, 61,137,202,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 45,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 23,191, 52, 62, 82,209,247, 62,204, 21, 34,
+ 63, 43, 58, 21, 61,139, 3, 1, 61,135,159, 52,189, 36,117, 30, 62,244,123,230, 62,185,104, 79, 63, 33, 73, 17, 62,213,208,117,
+ 62, 76,118,118, 62, 5,254, 32, 62,128,245, 65, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63, 4,246,179, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,192, 74,101, 85,191,105,185,166, 64, 36,141, 18,191, 55, 81,190,191, 71,243,109, 63, 42,237,100,
+ 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 65, 46,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 3,157,221, 62,215, 81, 67,
+ 63, 5, 46,135,191, 9,108,121,190, 16, 83, 37,190,130,244, 37, 62,216, 18,191, 63, 53, 44,221,189,162,136,153,190,252,138, 80,
+ 61,102,214,221, 63, 25, 22, 50, 62,157, 42,139, 61, 30,113,164, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63, 26,208,145, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,218,234,122,191,232,177, 50, 64, 42,174,108,191, 55, 81,190,191, 71,243,109,
+ 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 65, 47,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 59, 41, 98,
+ 61,252, 70,236,191, 25, 96, 77,190,154,195, 33,190,242,119, 31,190,204, 79,125,190, 18, 53, 23,190,214, 31,102,190,199,174,165,
+188,169,105, 48, 62, 8, 50,229, 62,148,251,227, 62,206, 65,133, 62, 49, 82, 75, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 5,230, 44, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,206,106,254, 62,150, 36,205, 64,137, 42, 96,191, 55, 81,190,
+191, 71,243,107, 63, 42,237,100, 62,214,163,235,190,183,206,198,190, 61,137,203,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 48,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63, 23,191, 52, 62, 82,209,247, 62,204, 21, 34, 63, 43, 58, 21, 61,139, 3, 1, 61,135,159, 52,189, 36,117, 30, 62,244,123,230,
+ 62,185,104, 79, 63, 33, 73, 17, 62,231, 15, 87, 62,207,237, 49, 61,141, 43,254, 61,150,225,226, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 4,246,179, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,167, 61,200,191,171, 5,119, 64,147,214, 86,
+191, 55, 81,190,191, 71,243,109, 63, 42,237, 98, 62,214,163,236,190,183,206,197,190, 61,137,201,191, 80, 38,157, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 49,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63, 70, 39,111,188,218,103, 91, 63, 30, 24, 44, 62, 12, 81, 28, 63, 16,129, 26, 61,162,153,215,191, 31,203, 11,
+ 63, 2,132,222,190,154, 4, 26, 62,100,112,202, 62,214, 36,216, 60,122, 85,172, 60,142,247, 44, 63, 12,140,132, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,115, 61, 48, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,251, 14,194,190,105,213, 44,
+ 64,109,188,165,191, 55, 81,190,191, 71,243,107, 63, 42,237,100, 62,214,163,235,190,183,206,198,190, 61,137,203,191, 80, 38,157,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 50,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,191, 3, 49,173, 63, 9,133,178, 63, 16, 18,104, 62,186, 16,159, 62,245,147,183, 62,111, 88,220,
+ 63, 2, 25,220,191, 77, 44, 80, 62,152,136, 76, 61,176,242,126, 62,155, 13,239, 62,234, 17, 40, 62, 13,128, 92, 61,208,130,226,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,208,147, 65, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 46, 47,102,
+ 63, 45,212, 64, 64,127, 35, 61,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,
+191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 51,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 48,164, 8,191, 38,100, 32,190,157,157,163, 61,167, 78, 10, 59, 54, 8, 4,
+190,147,155,139, 63, 50, 41, 11, 62,140,101, 27, 63,110,237,241, 59,179,188, 18, 62,165, 31, 74, 63, 37,208,207, 60,141,227, 74,
+ 60, 76, 28, 8, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62, 80, 24,129,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+191, 83,203, 10,192, 29, 15,133, 64, 42, 82,237,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,
+190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 52,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,232,194, 41, 63, 35,110,156,190, 75,200,233,191, 22,158,170,
+189,193,122, 83,189,149, 58,217,191, 18, 15, 80,189,145, 37, 66,189,219,184, 98,191, 86,185, 70, 61,239,150, 21, 62, 24,193,130,
+ 62,217, 71, 46, 62,158,114,141, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63, 75,231,122, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,102, 71, 47,191, 44, 13, 16, 64,156,187, 24,191, 55, 81,190,191, 71,243,109, 63, 42,237, 98, 62,214,163,236,
+190,183,206,197,190, 61,137,201,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 53,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190, 61, 40,120,191, 15,196,150,191, 54,219,159,
+ 62,191,195,234,190,122, 96,104,191, 74, 71,193,190, 56,230, 15, 61,203,156, 61, 61,177, 39,227,190,193,222, 25, 63, 13,206,178,
+ 60,237,101,144, 60,198,227, 16, 62,201, 30, 16, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 61,189,137, 74, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 62,252,210,140,191, 44, 58,216, 64,149,217, 98,191, 55, 81,192,191, 71,243,109, 63, 42,237, 98,
+ 62,214,163,234,190,183,206,197,190, 61,137,202,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 65, 54,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 38,152, 86,191, 17,225,169,
+189,140,217, 57,190,254,124, 67, 62, 17, 65, 13, 63, 15,204,229, 62,241,148,180,191, 73,210,175, 63, 21,161,182,188,169,222,186,
+ 63, 4,174,235, 61,156,216,125, 61,115,228,114, 62,176,239,124, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 61,165,104, 86, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 46,210,181,191,135, 4, 59, 64, 44, 99,164,191, 55, 81,190,191, 71,243,109,
+ 63, 42,237, 98, 62,214,163,236,190,183,206,197,190, 61,137,202,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 65, 55,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 45, 97,119,
+190,205, 47,119, 63, 19,117, 35, 62, 98,125,166, 62, 73,195,242, 62,243,228,124, 63, 11, 86,119, 62, 89,156, 70, 63, 88,232,230,
+190,204, 53,130, 61,201, 69,154, 63, 3,143, 74, 62,162, 10,155, 61,146, 21,186, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,253,129, 53, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 60, 64,235, 64, 63,147,210,203, 64,185, 32,205,191, 55, 81,190,
+191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,201,190, 61,137,200,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 56,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 62,136,137,130,191,106, 7,101,190,155,249,249, 60,155,218,146,188,184,212,179,189,201,215, 68,191, 61,244, 40, 61, 70,234,114,
+191, 1,226,154, 63, 91,139,119, 63,109,168,135, 61,112, 44, 87, 59,115, 72,106, 60, 24, 90,214, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 87, 40, 6, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 0,185,160,192, 38,235,197, 63,245,221,182,
+191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 57,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62,241, 54,241,190, 60, 75, 25,190,166, 31,137, 63, 76,162, 26, 62,180, 23,214,191, 22, 28,134, 62,184,125,189,
+ 63, 49,143,170, 62,208,100, 42, 63, 12,182,201, 61,103,123, 85, 62, 90, 65,230, 63, 29,215, 33, 61,233, 5,124, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 78, 6,233, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,247,118,132,192, 8, 66, 87,
+ 64, 20, 88, 93,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 58,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 62,157,149,183, 62,150,241,169, 63, 5, 72,210,191, 61, 98,196,191,103, 43, 94, 62, 13,249,141,
+190, 28, 40,108,189, 89,143,180, 62,180,169,159, 63,102,210, 50, 61,186,245, 15, 62,140,211,252, 62,252,184,237, 62, 15,107,164,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,126, 53,234, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,190, 2,252, 96,
+192, 63, 32,189, 64, 40,176,249,191, 55, 81,190,191, 71,243,107, 63, 42,237, 98, 62,214,163,235,190,183,206,198,190, 61,137,206,
+191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 59,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,185,185,227,190,133, 55, 69, 62,246,101, 76,191, 65, 32,146,190, 47,142, 11,
+191, 16,240,207, 60,250, 47,178, 62,135, 12,147,190,192,130,250, 63, 63,224,182, 61,141,251,109, 61,135, 15,209, 62,212,122,152,
+ 62,230, 66,150, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,201, 22,194,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+192, 60, 37,186,192, 19, 36,209, 63,212,102,200,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,
+190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 60,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,253,116,133, 63, 23,178,160,191, 32, 78,114, 61,221, 97, 57,
+189,236,244,191, 62,214, 56,206,191, 40,142, 77, 61,161, 48, 31, 63, 7, 95, 82,190, 62, 70,244, 59,141,146,144, 62,182,189, 24,
+ 63, 34, 24, 12, 59,183, 33,242, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63, 90, 4, 51, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,155,165, 62,191,200,188, 35, 64,140,201,156,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,
+190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 61,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,205,198, 68, 63, 99, 21, 50,190, 86,246, 18,
+189,178, 24,237, 62, 74,177,229,190,174, 94,233,189, 17,113, 14, 62,211,148,144,190, 80,182,157,191, 66,214, 18, 62,182,112, 54,
+ 61, 2,202,156, 61, 40,146, 65, 63, 18, 18, 24, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 62,124, 84,229, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63, 1, 48,150, 62,211, 14,133, 64,175,209,120,191, 55, 81,190,191, 71,243,107, 63, 42,237,102,
+ 62,214,163,235,190,183,206,200,190, 61,137,205,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 65, 62,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60,181, 0, 30, 63, 39, 21,183,
+191, 42, 28,174, 62,185,254,206, 61,180,101, 60, 62,162,164,224,191, 78, 22,169,190,146,164, 15, 62,188, 47, 66,191, 63,255,233,
+ 63, 76, 61, 26, 60,171,234,214, 60, 47,187,230, 62, 46,146,126, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63, 41,195,113, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 62, 98,144,196,191,112,190, 62, 64,138,224,153,191, 55, 81,190,191, 71,243,109,
+ 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 65, 63,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,148, 80,255,
+ 63, 5,138, 17, 62, 38, 16,171,191, 73, 50,107, 63, 32,126,214, 62,148, 14,143,191, 4, 31,183, 62,145,152, 70,189, 89, 32, 21,
+ 62,100,239, 63, 62,220,212, 51, 61,238, 96, 49, 61,205,246, 1, 62,180, 22, 64, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 76, 33,247, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 2,243, 80,191, 91, 84, 18, 64, 77, 0,110,191, 55, 81,190,
+191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 64,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+191, 69,146, 49,190, 69,123,236,191, 26,188,179,189, 47,182,207,191,105, 14, 96,190, 31,120, 55, 62, 18, 41,138,189,183, 73,210,
+189, 57, 99,105,190,137,155, 32, 62, 79,143,112, 62,220, 36, 13, 62,119,171,207, 62, 0,124,168, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,199,151,184, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 62, 34, 81,228,192, 39, 55,178, 64, 68, 36, 87,
+191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 65,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63, 3,148,230, 62,239, 68,224, 62,241, 64, 72,191, 11, 35, 71,191, 31,202,248, 62,182, 98, 68,191, 48,127, 18,
+189, 26,108,158,190,173, 93,145,191, 16,155,161, 61,244, 72,144, 61,173, 98,152, 62,154,243, 16, 62,252,162, 38, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,245,111, 69, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,132,206,226,191,254,157,153,
+ 64, 57, 78, 61,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 66,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 62,217, 64, 45,190,213, 24,151, 61,187,174, 94, 63, 76,136,102, 63, 32, 1, 27,189,162, 95,236,
+191, 29, 18,124,190,155, 78, 75,191, 43,134,124,190,184,202,174, 62, 35,138, 49, 62, 85,209,237, 62,186, 75,126, 62,137, 6,113,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 61, 76,100,111, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 62,237,163,228,
+192, 58, 20, 55, 64, 64,122, 9,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,
+191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 67,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,189, 55, 95, 82,190,181, 21, 43,191,101, 3,230, 62,137,248, 87, 62, 75,208, 4,
+ 59,115,115, 0,190, 95,196,100, 62, 83, 15,191,191, 81,222, 84, 62,169, 58, 36, 61,163,215,187, 61, 92,207, 90, 62,152,248,188,
+ 63, 17, 59,182, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,112,119,230,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+191,148, 59,202,191, 56,242,188, 64,113,111,189,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,
+190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 68,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61,192, 21,202, 63, 8, 22,216, 63, 66, 84,188, 62,186, 70,158,
+ 62, 98,211,240, 62,155, 7,124, 62,246,134, 10,190, 79, 16,110,189,252,197,248, 63, 39,188, 81, 62,169,204, 42, 62,154,195,204,
+ 62, 51,225,146, 62, 66,254,125, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63, 81, 26,123, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0,191,252,179, 34,191,184,102, 86, 64, 51,174,169,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,
+190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 69,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,144, 50,232,191, 50, 31,207,191, 40,203,179,
+189, 45, 99,214,190, 34,153,109,191, 10, 94,239,190,212,186,115,190, 19,234, 42,191, 97, 26, 72, 61, 99,105,122, 62, 21,210, 46,
+ 62,186, 32,250, 62,178,126,195, 62, 16,238, 85, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 60,124,240,131, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,192, 77,244, 1,190,163, 52, 51, 64, 62,234, 30,191, 55, 81,190,191, 71,243,109, 63, 42,237, 98,
+ 62,214,163,236,190,183,206,197,190, 61,137,202,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 65, 70,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,112, 41,126, 61,164,166, 56,
+ 61,240, 4, 91, 62,161,172, 15,190,191,126,106, 63, 64, 33,117, 62,184,227,130,190,244, 20, 92,189,180,168,210,191, 43, 25, 60,
+ 61,198,246, 89, 63, 46,130, 30, 62, 54,241,223, 61, 46, 41,221, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 62,107,196,190, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,122, 27,255,191,133,229,179, 64,149, 39, 66,191, 55, 81,190,191, 71,243,107,
+ 63, 42,237,102, 62,214,163,235,190,183,206,200,190, 61,137,205,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 65, 71,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 24, 46,192,
+191, 43, 20, 41, 62,183,184,186, 62,136,173, 42, 63, 50, 75, 75, 62,126, 83, 40, 63, 8,195,188, 62,238,211,234, 61,152, 36, 69,
+ 62,145,106,235, 62,239, 4,216, 61, 21,100,235, 61, 20, 73,174, 62,235,197, 83, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 57,122, 93, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,151, 66, 20,192, 62,139,208, 64, 5,118, 98,191, 55, 81,190,
+191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 72,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+190, 32,160,159,191, 52, 39,190,191, 9,138,142, 62,224, 13,138, 62,242,218,166, 63, 26, 71, 93, 62, 52, 22, 36, 62,124, 52,231,
+190,192, 91,165,191, 86,111,148, 61,120,101,212, 61,221, 26, 72, 63, 22, 82,158, 62,122, 14,241, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 22, 96,195, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,190, 46, 63,224,191,107,105,222, 64,132,191,198,
+191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,201,190, 61,137,200,191, 80, 38,158, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 73,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63, 55,202, 47,190, 89,235,249,190, 92, 18,127,191, 32,129,146,190, 8,212, 7,190,171, 50,167, 62,123,120, 97,
+189,249,152,232, 62,149, 18,140, 61, 13,111, 37, 62,204,238, 89, 62, 39, 90, 10, 62, 6,156,123, 62,156, 22, 98, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 18, 61,115, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,190,234,148,250,192, 97,179, 11,
+ 64, 3,215, 16,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 74,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,190,248,227,177,190,192,134,160, 62,184,159,155, 63, 51,157,105, 63, 54, 56, 2, 62,182,126, 88,
+187, 4,207,108, 62,198,216, 38,191, 73, 66,140, 61,248,126,139, 60,119, 26,251, 60,150,207, 34, 63, 20,176,170, 62,197,120,225,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,216,234,208, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,135,177,202,
+192, 86,220,150, 63,239, 9,144,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,
+191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 75,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 18,122,201,190,163, 68,155,191, 39, 36,236,190,194,182,221,190, 98, 47,217,
+190,230, 46, 97, 62,134,236,197, 60,187, 40,216,189,179, 92,111, 63, 54, 17, 71, 61, 5,169, 87, 61, 92,116,120, 63, 38,253,179,
+ 62,133,192,225, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 60,154, 58,100,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+192,108,105,213, 62,223,145,125, 64, 82,182,192,191, 55, 81,190,191, 71,243,107, 63, 42,237, 98, 62,214,163,235,190,183,206,198,
+190, 61,137,206,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 76,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190, 32,244,195,190,218,189,174, 62, 55, 11,163,191, 95, 75,157,
+190,243,155, 33,191, 90, 86,180, 62, 86,237, 57,190,126,198,226, 61,101, 34, 30,190,180,239, 93, 61,204, 82,206, 63, 89,113, 44,
+ 61, 23, 63, 63, 60,100, 33,220, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63, 50, 63, 6, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62,243, 23, 76,191,166,133, 46, 64,134,153, 78,191, 55, 81,192,191, 71,243,109, 63, 42,237, 98, 62,214,163,234,
+190,183,206,197,190, 61,137,202,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 77,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 49,218,173,191, 23,109,113, 62, 55, 16, 32,
+190,188,117, 54, 62,208, 20, 25,191, 46,245,118,186,236,158, 72,191, 97, 10, 55, 62,183,128,140,190,146,230,177, 62,190, 2,159,
+ 61,193,141, 29, 61,214, 93,214, 62,220, 2,164, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63, 48, 85, 96, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,190,214,192,130,192, 73, 57,182, 64, 23, 83,175,191, 55, 81,190,191, 71,243,109, 63, 42,237,100,
+ 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 65, 78,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 34,172,206, 62,187, 79, 64,
+ 62, 11,197,140, 63, 42,135,199, 61,148, 91,100, 60, 25, 75,123,189,232,126, 54,189,220,190,210, 62,186,158, 9,190,225, 62,182,
+ 61, 84,103,211, 61,115,194, 92, 62,253,216,148, 62,201, 34, 41, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 62,162,103, 38, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192,133, 4,122, 62,128,136,109, 64, 58, 58,136,191, 55, 81,190,191, 71,243,107,
+ 63, 42,237, 98, 62,214,163,235,190,183,206,198,190, 61,137,206,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 65, 79,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,137,206,147,
+ 63, 11,207,234, 62,225,144,195, 63, 40,225,162,190,148, 69, 24, 61,190,238, 50,191, 86, 31, 13, 63, 71,106,217, 62, 1, 60,247,
+ 62,136,250,162, 58,156, 80, 70, 63,108,100,142, 61,153, 72, 15, 58, 17, 35,116, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 60, 41,199,174, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 62, 12, 40,132,192, 1, 32,102, 64, 95,178,222,191, 55, 81,190,
+191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 80,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63, 95, 57,157, 62,214,148,238, 62,109,249, 87,189,204,220,227,189,221,118,238,191, 19,162,121,191, 48, 50,203,190, 80,232, 58,
+191, 8,100,141, 63, 19,142,229, 62, 88,196,223, 61,237, 94,134, 62, 97, 5,141, 62,231,195, 43, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 15, 11, 75, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63, 80,109,211,192, 20,210, 96, 64,103,253,246,
+191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 81,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62,133, 32, 88,190,189,201, 13, 63, 66, 43, 55, 62,239,254, 76, 62,179,163,254,188,171,181, 15, 60,196, 8,130,
+191, 14, 27,214,190,128, 32, 86,190,208, 27,190, 62, 53,196, 69, 61,135,184,136, 62, 35,250,240, 63, 24,153, 34, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,234, 93,224, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,147,142,240,190,166, 7, 43,
+ 64,130, 69, 61,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 82,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 62,249,246, 44, 62,140,102,200, 63, 10,199,154, 63, 32,102, 40,191, 19, 10, 78,190,250,238,224,
+190,111, 13, 0, 61,187,232,243, 62, 99, 10,106, 62,221, 96,163, 62,206,243, 56, 62,159,170,109, 62, 2,145,224, 62, 32, 50,211,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 25,143, 35, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191, 89,254, 2,
+192, 85,197,195, 63,254,197,176,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,
+191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 83,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,204,125,122, 63, 46, 10, 37,190, 26, 71, 69, 63, 24,168,130,190, 36,105,117,
+ 63, 32,220,144, 62,231,167, 11, 62,179,145,151,190, 36, 72, 33,191, 50, 67, 42, 61, 11, 3,111, 61, 76, 2,241, 63, 28,181,231,
+ 62,155,179,103, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,188,186,244,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+191,253, 46, 24, 61,214,126,200, 64,125, 1,248,191, 55, 81,190,191, 71,243,109, 63, 42,237, 98, 62,214,163,236,190,183,206,197,
+190, 61,137,202,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 84,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,181,218,171, 63, 80,100,162,190,175, 18, 86,190,157, 51,142,
+191, 4, 35, 18, 62,210,113,207, 63, 11,170, 0,190,165,126,134, 62, 59, 47,141,191, 62,163,104, 62,181,251, 18, 62,242,163,225,
+ 61,191, 98, 90, 61,158, 33,220, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,104, 76, 83, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0,192, 94, 18,115, 61, 49, 61,112, 64, 71,153, 90,191, 55, 81,190,191, 71,243,109, 63, 42,237, 98, 62,214,163,236,
+190,183,206,197,190, 61,137,202,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 85,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,112, 41,126, 61,164,166, 56, 61,240, 4, 91,
+ 62,161,172, 15,190,191,126,106, 63, 64, 33,117, 62,184,227,130,190,244, 20, 92,189,180,168,210,191, 43, 25, 60, 61,190,188,141,
+ 63, 68,157,118, 61,224,119,105, 60,239,129,112, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 62,107,196,190, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,191,141, 34, 38,192, 39,140,222, 64, 25, 55,182,191, 55, 81,190,191, 71,243,109, 63, 42,237,100,
+ 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 65, 86,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 85, 40,193,190,146, 79,120,
+190,203,249, 68, 62,131,217,207, 63, 22, 65,229, 63, 63,104,120,189,124,135,173,190,190,179,131, 62,171, 81,208, 63, 69,132,211,
+ 61,189, 6,122, 62, 23,195, 58, 62,254,114, 6, 62,134,106,189, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63, 20,102,179, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 63, 14,149,191,165,204, 64, 64, 24, 96, 12,191, 55, 81,190,191, 71,243,109,
+ 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 65, 87,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 30, 81, 54,
+ 62,223, 39,157, 63, 11, 30,214, 62,186, 51, 76, 62, 83,228,206, 61, 0,146,209, 63,121,106, 22,187, 6,124, 44,187, 71,233,128,
+ 62,173,190,218, 61, 83, 67, 14, 63, 4,186,192, 62,197,206, 39, 61, 50,159,178, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 60, 52, 19,208, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 22,180,183,192, 4,173,126, 64, 8,189,240,191, 55, 81,190,
+191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 88,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+191, 20, 59,104, 63, 17, 36, 30,190,252, 57,112, 62,162,101, 32, 62,160, 6,139, 61, 80,160, 57, 61,245,243,109,190,224, 18, 41,
+188,227,154,182,190,139,196,238, 61,131, 49,133, 62,167, 33,130, 63, 5,225,160, 61,177, 59,124, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 56,166, 20, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63, 97,160, 35,191,163,220,129, 64,141,248,194,
+191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 89,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 62,157,149,183, 62,150,241,169, 63, 5, 72,210,191, 61, 98,196,191,103, 43, 94, 62, 13,249,141,190, 28, 40,108,
+189, 89,143,180, 62,180,169,159, 63,102,210, 50, 62,206,174, 78, 61, 93,159, 68, 61,118, 84,160, 62,246,211, 54, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,126, 53,234, 0, 0, 0, 0,255,255,255,255,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,192, 18,223, 4,191,140,169,155,
+ 64, 57, 18,151,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 90,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63, 44, 63,186, 62,136,104,134, 63, 32,117, 44,190,147,227,178, 63, 90, 77,254,190,175,117, 0,
+ 62,167, 69,119, 61,138, 73,238, 62,189,211, 58,191, 37, 28,210, 62, 21, 96,245, 62,227,104, 35, 62,154, 62, 83, 61,222,164, 64,
+ 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,151, 27,130, 0, 0, 0, 0,
+255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191,179,193,100,
+192, 78,111,251, 63,228, 64,166,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,
+191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 91,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 4,101,129, 63, 0, 90,237,190,239,125,104, 63, 3, 31,131,190,212,160,200,
+ 63, 27,217,115,190, 6,189, 55,190, 22,223,131,190,223,241, 4,190, 0, 70, 4, 61, 35,242, 37, 61,171,214,204, 63, 46, 25,175,
+ 62, 72,177, 82, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62,202,249,184,
+ 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+191,124, 90, 93,191,212, 48,113, 64, 74,208, 56,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,190,183,206,200,
+190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 92,144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,189,236, 25,179, 63, 27,158,127, 62,239,235,123, 63, 33,108, 59,
+190,103,198,244, 62,187,192,251,190,101, 39,179, 62,138,210,110,191, 54,168,145,190, 63, 20,208, 62, 81,178,187, 62,108, 57,176,
+ 62,153,177, 93, 62,135, 88,108, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,109,210, 2, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0,192, 33,231,251,191, 59, 2,132, 64, 66,162, 78,191, 55, 81,190,191, 71,243,109, 63, 42,237,100, 62,214,163,234,
+190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 93,144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 24, 46,192,191, 43, 20, 41, 62,183,184,186,
+ 62,136,173, 42, 63, 50, 75, 75, 62,126, 83, 40, 63, 8,195,188, 62,238,211,234, 61,152, 36, 69, 62,145,106,235, 62, 30, 15,217,
+ 63, 4,209,227, 62,117,148,178, 61,178, 39,218, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63, 57,122, 93, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,138,185, 2,192, 41,128,191, 64, 97,193,139,191, 55, 81,190,191, 71,243,109, 63, 42,237,100,
+ 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 13, 65, 94,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,168,120,231,191, 7,154,179,
+ 63, 48,180, 41,190,187,232,239,191,104, 35, 9, 62,114, 8,222,190,177,143, 76,191, 28, 29,107, 62,234,112,210,190, 92,249, 9,
+ 61,250,196, 0, 61, 62,120, 79, 62, 31, 12,195, 63, 44,252,202, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0, 66,200, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 62,184, 4, 74, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,190,243, 63,242,191,159,176, 86, 64,111,150,245,191, 55, 81,190,191, 71,243,109,
+ 63, 42,237,100, 62,214,163,234,190,183,206,200,190, 61,137,199,191, 80, 38,158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 13, 65, 95,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 58, 26,166,
+ 62,159, 70, 1, 63, 2,111,113,190,173,187,235, 62,237, 51,116, 62,247, 53,130,190, 26,199,243,189,172, 88,235, 62,244,115,118,
+191, 5,147, 34, 62,158, 77,217, 62, 72,131, 43, 62, 68,208,119, 62,155, 8, 86, 0, 0, 0, 0, 0, 0, 0, 0, 66,200, 0, 0,
+ 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,110,152,253, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,191, 48,178,198, 62, 52, 39,138, 64,149,252, 39,191, 55, 81,190,
+191, 71,243,107, 63, 42,237,100, 62,214,163,235,190,183,206,198,190, 61,137,203,191, 80, 38,157, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66,200, 0, 0, 13, 65, 96,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+190,210,167, 41, 62,139,172,194, 63, 35,220,250,191, 22,182, 30, 61,136, 3,122,190,176,164,109,190,147,153, 30,188, 10,248,255,
+190,160, 90,234,190,205,241, 89, 63, 19, 71, 62, 62,107,215,111, 61,138, 71, 63, 62, 1,231,243, 0, 0, 0, 0, 0, 0, 0, 0,
+ 66,200, 0, 0, 66,200, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 62, 77,227, 37, 0, 0, 0, 0,255,255,255,255, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,203,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7,
+ 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,135, 60,124,223,255, 63, 2, 71,187,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 62, 15, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 84,231, 61,124,224, 31, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,203,
+ 61,197,143, 15, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 15, 63,187,172,165,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,151, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 85, 15, 62,124,224, 31, 63,245, 17,143, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 64,204,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 85, 7, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 61,255,
+ 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 15, 63,127,101,126, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,203, 61,197,143, 15, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,152, 62, 14, 62, 15, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,147,
+ 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 15, 62,124,224, 27, 63,245, 17,142, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,205,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,223, 63, 62,131,146, 57,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,191, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127,168, 61, 14, 61,239, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 23,
+ 61,124,223,251, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 3, 63,158, 2, 81,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 7, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,142, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23,
+ 62,124,224, 23, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,206,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 82, 7, 59,124,223,255, 62,131,146, 56, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84, 7, 60,124,223,255,
+ 63, 2, 71,186, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127, 8, 61, 14, 61,255, 63, 65,123,218, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,199, 61,124,224, 15, 63,127,101,123, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 20,171, 61,197,143, 15, 63,158, 2, 80, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,136, 62, 14, 62, 15,
+ 63,187,172,163, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 43, 62, 65,155,151, 63,216,177,182, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,255, 62,124,224, 31, 63,245, 17,139, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 64,207,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,223,127, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 85, 7, 60,124,223,191, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168,
+ 61, 14, 61,243, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 15, 61,124,223,251, 63,127,101,125,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 5, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,180, 62, 14, 62, 8, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59,
+ 62, 65,155,142, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 11, 62,124,224, 23, 63,245, 17,141,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,208,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 82, 7, 59,124,223,255,
+ 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84, 7, 60,124,223,223, 63, 2, 71,187, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,126,200, 61, 14, 61,247, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 84,135, 61,124,224, 7, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,107, 61,197,143, 11,
+ 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,104, 62, 14, 62, 11, 63,187,172,164, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,137,251, 62, 65,155,145, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 84,231, 62,124,224, 27, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 64,209,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 84, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7,
+ 60,124,223,255, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 61,255, 63, 65,123,220,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,231, 61,124,224, 15, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 20,235, 61,197,143, 15, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184,
+ 62, 14, 62, 11, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 75, 62, 65,155,147, 63,216,177,185,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 27, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,210,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,127, 62,131,146, 57, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,223, 63, 2, 71,186, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127,136, 61, 14, 61,247, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,223,251,
+ 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 5, 63,158, 2, 81, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 8, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 75, 62, 65,155,142, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 31, 62,124,224, 23,
+ 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,211,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7,
+ 59,124,223,255, 62,131,146, 59, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,224, 15, 63, 2, 71,188,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 62, 7, 63, 65,123,221, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 85, 71, 61,124,224, 23, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 43,
+ 61,197,143, 18, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,200, 62, 14, 62, 15, 63,187,172,165,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 91, 62, 65,155,152, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 85, 31, 62,124,224, 34, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 64,212,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,135, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 84,223, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,132, 61, 14, 62, 3,
+ 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,252, 61,124,224, 19, 63,127,101,127, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,207, 61,197,143, 15, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,169, 62, 14, 62, 13, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 50, 62, 65,155,147,
+ 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 7, 62,124,224, 31, 63,245, 17,142, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,213,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,143, 62,131,146, 56,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,223, 63, 2, 71,186, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127,200, 61, 14, 61,250, 63, 65,123,218, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7,
+ 61,124,224, 4, 63,127,101,124, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 11, 63,158, 2, 81,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 11, 63,187,172,163, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 43, 62, 65,155,146, 63,216,177,183, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,255,
+ 62,124,224, 26, 63,245, 17,140, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,214,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 87, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,199, 60,124,223,255,
+ 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 61,255, 63, 65,123,219, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 71, 61,124,223,255, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 21, 11, 61,197,143, 11, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,192, 62, 14, 62, 11,
+ 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 75, 62, 65,155,145, 63,216,177,184, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 25, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 64,215,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 85, 7, 60,124,223,191, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,200,
+ 61, 14, 61,239, 63, 65,123,221, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 39, 61,124,223,239, 63,127,101,127,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,142,255, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 3, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 75,
+ 62, 65,155,135, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 17, 63,245, 17,142,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,216,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 71, 59,124,223,239,
+ 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,199, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,120, 61, 14, 62, 2, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 84,247, 61,124,224, 17, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,203, 61,197,143, 15,
+ 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,165, 62, 14, 62, 13, 63,187,172,164, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 48, 62, 65,155,147, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 85, 7, 62,124,224, 28, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 64,217,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135,
+ 60,124,223,255, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 61,255, 63, 65,123,221,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 71, 61,124,224, 15, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 21, 43, 61,197,143, 7, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,200,
+ 62, 14, 62, 7, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 91, 62, 65,155,143, 63,216,177,186,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 31, 62,124,224, 23, 63,245, 17,143, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,218,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,135, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,231, 60,124,223,255, 63, 2, 71,186, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127,136, 61, 14, 62, 3, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,255, 61,124,224, 17,
+ 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,211, 61,197,143, 15, 63,158, 2, 81, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 13, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 53, 62, 65,155,148, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 10, 62,124,224, 29,
+ 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,219,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7,
+ 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,223,255, 63, 2, 71,187,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 61,255, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 85, 71, 61,124,223,255, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 43,
+ 61,197,143, 15, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,200, 62, 14, 62, 7, 63,187,172,164,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 83, 62, 65,155,143, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 85, 27, 62,124,224, 23, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 64,220,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 85, 7, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168, 61, 14, 62, 15,
+ 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 15, 63,127,101,127, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,219, 61,197,143, 23, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,168, 62, 14, 62, 11, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 67, 62, 65,155,147,
+ 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 19, 62,124,224, 27, 63,245, 17,143, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,221,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,127, 62,131,146, 57,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,191, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127,200, 61, 14, 61,239, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7,
+ 61,124,223,247, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,142,255, 63,158, 2, 81,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 5, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,138, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 15,
+ 62,124,224, 19, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,222,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 86, 7, 59,124,223,255, 62,131,146, 59, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,223,255,
+ 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 61,255, 63, 65,123,220, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 71, 61,124,224, 15, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 21, 11, 61,197,143, 7, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,200, 62, 14, 62, 11,
+ 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 83, 62, 65,155,143, 63,216,177,184, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 27, 62,124,224, 23, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 64,223,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 85, 71, 60,124,223,223, 63, 2, 71,189, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,200,
+ 61, 14, 61,247, 63, 65,123,221, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 23, 61,124,224, 7, 63,127,101,127,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 11, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,176, 62, 14, 62, 11, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59,
+ 62, 65,155,145, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 15, 62,124,224, 27, 63,245, 17,142,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,224,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,223,127,
+ 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,223, 63, 2, 71,187, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168, 61, 14, 61,247, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 85, 7, 61,124,224, 7, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,203, 61,197,143, 11,
+ 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 13, 63,187,172,165, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 43, 62, 65,155,145, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 85, 11, 62,124,224, 25, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 64,225,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 84,135, 59,124,224, 63, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,231,
+ 60,124,224, 55, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,152, 61, 14, 62, 17, 63, 65,123,219,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,255, 61,124,224, 30, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 20,203, 61,197,143, 24, 63,158, 2, 80, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,164,
+ 62, 14, 62, 18, 63,187,172,163, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 55, 62, 65,155,155, 63,216,177,183,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 9, 62,124,224, 36, 63,245, 17,140, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,226,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,191, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127,168, 61, 14, 61,239, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 23, 61,124,223,255,
+ 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,142,255, 63,158, 2, 81, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 7, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 67, 62, 65,155,139, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 15, 62,124,224, 19,
+ 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,227,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7,
+ 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,255, 63, 2, 71,186,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,200, 61, 14, 61,255, 63, 65,123,218, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 85, 39, 61,124,224, 15, 63,127,101,124, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 11,
+ 61,197,143, 15, 63,158, 2, 80, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,200, 62, 14, 62, 15, 63,187,172,163,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 91, 62, 65,155,151, 63,216,177,182, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 85, 31, 62,124,224, 31, 63,245, 17,139, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 64,228,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 85, 71, 60,124,223,255, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,200, 61, 14, 62, 7,
+ 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 23, 61,124,224, 23, 63,127,101,126, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 19, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,176, 62, 14, 62, 15, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,147,
+ 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 15, 62,124,224, 27, 63,245, 17,142, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,229,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,191, 62,131,146, 57,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,135, 60,124,223,247, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127, 72, 61, 14, 62, 0, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,231,
+ 61,124,224, 14, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,171, 61,197,143, 13, 63,158, 2, 81,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,152, 62, 14, 62, 13, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 27, 62, 65,155,147, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,251,
+ 62,124,224, 27, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,230,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 85, 7, 59,124,223,127, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 39, 60,124,223,223,
+ 63, 2, 71,186, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,184, 61, 14, 61,247, 63, 65,123,219, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 31, 61,124,223,255, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 20,243, 61,197,143, 3, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,188, 62, 14, 62, 7,
+ 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 67, 62, 65,155,141, 63,216,177,184, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 17, 62,124,224, 22, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 64,231,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 85, 7, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168,
+ 61, 14, 61,255, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 15, 63,127,101,126,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,219, 61,197,143, 7, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,176, 62, 14, 62, 11, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 67,
+ 62, 65,155,147, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 27, 63,245, 17,142,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,232,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 71, 59,124,223,255,
+ 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,199, 60,124,223,255, 63, 2, 71,188, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 62, 7, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 84,255, 61,124,224, 23, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,211, 61,197,143, 19,
+ 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,170, 62, 14, 62, 15, 63,187,172,164, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 56, 62, 65,155,147, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 85, 13, 62,124,224, 25, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 64,233,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 84, 7, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84, 7,
+ 60,124,224, 63, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127, 72, 61, 14, 62, 15, 63, 65,123,219,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,199, 61,124,224, 15, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 20,171, 61,197,143, 7, 63,158, 2, 80, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,152,
+ 62, 14, 62, 11, 63,187,172,163, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 27, 62, 65,155,147, 63,216,177,184,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,255, 62,124,224, 19, 63,245, 17,140, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,234,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255, 62,131,146, 59, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,128, 8, 61, 14, 61,255, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85,103, 61,124,223,255,
+ 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 75, 61,197,143, 7, 63,158, 2, 82, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,216, 62, 14, 62, 7, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 91, 62, 65,155,143, 63,216,177,186, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 31, 62,124,224, 23,
+ 63,245, 17,143, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,235,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7,
+ 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,224, 31, 63, 2, 71,187,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 62, 15, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 85, 71, 61,124,224, 23, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 43,
+ 61,197,143, 27, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,200, 62, 14, 62, 19, 63,187,172,165,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 91, 62, 65,155,155, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 85, 31, 62,124,224, 35, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 64,236,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 84,135, 60,124,223,191, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,104, 61, 14, 61,255,
+ 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,231, 61,124,224, 15, 63,127,101,126, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,187, 61,197,143, 7, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,152, 62, 14, 62, 11, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 35, 62, 65,155,143,
+ 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,255, 62,124,224, 23, 63,245, 17,141, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,237,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,255, 62,131,146, 59,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,255, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127,200, 61, 14, 61,255, 63, 65,123,221, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 71,
+ 61,124,224, 15, 63,127,101,128, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 11, 61,197,143, 15, 63,158, 2, 82,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,200, 62, 14, 62, 13, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 75, 62, 65,155,147, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23,
+ 62,124,224, 29, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,238,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 84, 7, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,224, 31,
+ 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 62, 7, 63, 65,123,219, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,231, 61,124,224, 23, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 20,203, 61,197,143, 19, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 13,
+ 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 75, 62, 65,155,149, 63,216,177,185, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 33, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 64,239,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,135, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 84,215, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,144,
+ 61, 14, 62, 7, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,251, 61,124,224, 15, 63,127,101,127,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,207, 61,197,143, 15, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,166, 62, 14, 62, 13, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 45,
+ 62, 65,155,147, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 8, 62,124,224, 27, 63,245, 17,142,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,240,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,222,255,
+ 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,223,191, 63, 2, 71,187, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,200, 61, 14, 61,239, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 85, 39, 61,124,223,255, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 11, 61,197,142,255,
+ 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,200, 62, 14, 62, 7, 63,187,172,164, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 91, 62, 65,155,139, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 85, 31, 62,124,224, 15, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 64,241,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 85, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7,
+ 60,124,223,255, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168, 61, 14, 62, 7, 63, 65,123,220,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 23, 61,124,224, 15, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 20,219, 61,197,143, 15, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,176,
+ 62, 14, 62, 13, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 51, 62, 65,155,145, 63,216,177,185,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 15, 62,124,224, 29, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,242,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,255, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127,200, 61, 14, 61,255, 63, 65,123,221, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 39, 61,124,224, 15,
+ 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 11, 61,197,143, 7, 63,158, 2, 82, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 11, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 75, 62, 65,155,143, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 23,
+ 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,243,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 82, 7,
+ 59,124,223,255, 62,131,146, 59, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 83,135, 60,124,223,191, 63, 2, 71,188,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,126,200, 61, 14, 61,239, 63, 65,123,221, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 84,135, 61,124,223,255, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20, 75,
+ 61,197,142,255, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127, 88, 62, 14, 61,255, 63,187,172,165,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,137,219, 62, 65,155,135, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 84,223, 62,124,224, 15, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 64,244,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 85, 7, 60,124,223,191, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168, 61, 14, 61,239,
+ 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 23, 61,124,223,255, 63,127,101,126, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,142,255, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,184, 62, 14, 62, 3, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 67, 62, 65,155,137,
+ 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 11, 62,124,224, 15, 63,245, 17,142, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,245,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,127, 62,131,146, 56,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,223, 63, 2, 71,186, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127,200, 61, 14, 61,251, 63, 65,123,218, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7,
+ 61,124,224, 3, 63,127,101,124, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 8, 63,158, 2, 80,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 10, 63,187,172,163, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 27, 62, 65,155,143, 63,216,177,183, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,247,
+ 62,124,224, 24, 63,245, 17,140, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,246,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 86, 7, 59,124,224,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,224, 63,
+ 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 62, 15, 63, 65,123,221, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 71, 61,124,224, 31, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 21, 11, 61,197,143, 27, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,216, 62, 14, 62, 23,
+ 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 91, 62, 65,155,157, 63,216,177,184, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 31, 62,124,224, 37, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 64,247,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 87, 7, 59,124,224, 15, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 85,135, 60,124,224, 19, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,232,
+ 61, 14, 62, 12, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 39, 61,124,224, 28, 63,127,101,125,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 11, 61,197,143, 25, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,200, 62, 14, 62, 19, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 91,
+ 62, 65,155,155, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 31, 62,124,224, 35, 63,245, 17,141,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,248,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,224, 63,
+ 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,255, 63, 2, 71,188, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168, 61, 14, 62, 3, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 85, 7, 61,124,224, 19, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,219, 61,197,143, 15,
+ 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 13, 63,187,172,164, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 51, 62, 65,155,148, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 85, 11, 62,124,224, 29, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 64,249,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 86, 7, 59,124,224, 33, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135,
+ 60,124,224, 29, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 62, 11, 63, 65,123,221,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 71, 61,124,224, 24, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 21, 43, 61,197,143, 24, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,200,
+ 62, 14, 62, 18, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 91, 62, 65,155,157, 63,216,177,184,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 31, 62,124,224, 37, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,250,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 71, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127,200, 61, 14, 61,255, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 23, 61,124,224, 15,
+ 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 15, 63,158, 2, 82, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 11, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 75, 62, 65,155,143, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 27, 62,124,224, 23,
+ 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,251,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 82, 7,
+ 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84, 7, 60,124,223,255, 63, 2, 71,187,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127, 8, 61, 14, 62, 7, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 84,167, 61,124,224, 15, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,139,
+ 61,197,143, 15, 63,158, 2, 80, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,136, 62, 14, 62, 11, 63,187,172,163,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 11, 62, 65,155,143, 63,216,177,183, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 84,247, 62,124,224, 23, 63,245, 17,140, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 64,252,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,135, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 84,215, 60,124,223,191, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,152, 61, 14, 61,255,
+ 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,255, 61,124,224, 15, 63,127,101,126, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,223, 61,197,143, 15, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,174, 62, 14, 62, 11, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 57, 62, 65,155,147,
+ 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 12, 62,124,224, 27, 63,245, 17,142, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,253,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255, 62,131,146, 58,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,255, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127,200, 61, 14, 61,255, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7,
+ 61,124,224, 15, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 15, 63,158, 2, 82,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 15, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 75, 62, 65,155,147, 63,216,177,186, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23,
+ 62,124,224, 31, 63,245, 17,143, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 64,254,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 86, 7, 59,124,223,191, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,224, 15,
+ 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 62, 7, 63, 65,123,221, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 71, 61,124,224, 23, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 21, 11, 61,197,143, 17, 63,158, 2, 83, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,200, 62, 14, 62, 14,
+ 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 91, 62, 65,155,146, 63,216,177,186, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 26, 63,245, 17,143, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 64,255,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 85,135, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,200,
+ 61, 14, 61,239, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 39, 61,124,223,255, 63,127,101,125,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 11, 61,197,143, 7, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 7, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 75,
+ 62, 65,155,139, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 31, 62,124,224, 19, 63,245, 17,141,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 0,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,223,127,
+ 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 71, 60,124,223,191, 63, 2, 71,187, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168, 61, 14, 61,239, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 85, 23, 61,124,223,255, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,251, 61,197,143, 3,
+ 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,192, 62, 14, 62, 6, 63,187,172,164, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 67, 62, 65,155,140, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 85, 19, 62,124,224, 21, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 65, 1,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 84, 7, 59,124,223,127, 62,131,146, 56, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7,
+ 60,124,223,223, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 61,247, 63, 65,123,219,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,231, 61,124,223,255, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 20,235, 61,197,143, 7, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184,
+ 62, 14, 62, 7, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 91, 62, 65,155,141, 63,216,177,184,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 31, 62,124,224, 23, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 2,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,255, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127,200, 61, 14, 62, 15, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 39, 61,124,224, 15,
+ 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 15, 63,158, 2, 81, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 11, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 75, 62, 65,155,143, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 23,
+ 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 3,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7,
+ 59,124,224,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,135, 60,124,224, 63, 63, 2, 71,187,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127, 72, 61, 14, 62, 47, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 84,231, 61,124,224, 63, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,203,
+ 61,197,143, 47, 63,158, 2, 80, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 27, 63,187,172,163,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 43, 62, 65,155,167, 63,216,177,183, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 84,255, 62,124,224, 51, 63,245, 17,139, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 65, 4,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,135, 59,124,224, 31, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 84,199, 60,124,224, 31, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,152, 61, 14, 62, 16,
+ 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 31, 63,127,101,126, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,215, 61,197,143, 22, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,172, 62, 14, 62, 17, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 53, 62, 65,155,151,
+ 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 9, 62,124,224, 32, 63,245, 17,141, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 5,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,223,255, 62,131,146, 58,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,199, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127,136, 61, 14, 61,255, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,247,
+ 61,124,223,255, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,219, 61,197,143, 15, 63,158, 2, 81,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 7, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,143, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 15,
+ 62,124,224, 23, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 6,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 84, 7, 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,135, 60,124,223,191,
+ 63, 2, 71,186, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,104, 61, 14, 61,239, 63, 65,123,219, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,231, 61,124,223,247, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 20,171, 61,197,143, 3, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,152, 62, 14, 62, 7,
+ 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 35, 62, 65,155,145, 63,216,177,183, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,255, 62,124,224, 26, 63,245, 17,140, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 7,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 85, 7, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,200,
+ 61, 14, 61,255, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 15, 63,127,101,126,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 7, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 7, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 75,
+ 62, 65,155,143, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 23, 63,245, 17,142,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 8,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,191, 59,124,222,255,
+ 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,229, 60,124,223,191, 63, 2, 71,187, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,154, 61, 14, 61,255, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 85, 7, 61,124,223,255, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,232, 61,197,143, 7,
+ 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,182, 62, 14, 62, 7, 63,187,172,165, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 65, 62, 65,155,139, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 85, 16, 62,124,224, 19, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 65, 9,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 84, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,199,
+ 60,124,224, 31, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168, 61, 14, 62, 7, 63, 65,123,220,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,247, 61,124,224, 15, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 20,219, 61,197,143, 15, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168,
+ 62, 14, 62, 13, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 51, 62, 65,155,147, 63,216,177,185,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 7, 62,124,224, 31, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 10,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,224,255, 62,131,146, 58, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,135, 60,124,224, 63, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127, 72, 61, 14, 62, 47, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,231, 61,124,224, 47,
+ 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,171, 61,197,143, 47, 63,158, 2, 80, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,152, 62, 14, 62, 27, 63,187,172,163, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 27, 62, 65,155,167, 63,216,177,183, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,247, 62,124,224, 49,
+ 63,245, 17,139, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 11,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7,
+ 59,124,223,255, 62,131,146, 56, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84, 7, 60,124,223,191, 63, 2, 71,186,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127, 8, 61, 14, 61,239, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 84,167, 61,124,223,255, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,107,
+ 61,197,143, 11, 63,158, 2, 80, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,104, 62, 14, 62, 9, 63,187,172,163,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,137,251, 62, 65,155,143, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 84,239, 62,124,224, 23, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 65, 12,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,255, 62,131,146, 56, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 84,135, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127, 72, 61, 14, 62, 15,
+ 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,231, 61,124,224, 15, 63,127,101,126, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,171, 61,197,143, 31, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,152, 62, 14, 62, 15, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 11, 62, 65,155,159,
+ 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,247, 62,124,224, 39, 63,245, 17,142, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 13,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,223,255, 62,131,146, 57,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,255, 63, 2, 71,186, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127,200, 61, 14, 61,255, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 39,
+ 61,124,223,255, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 7, 63,158, 2, 81,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,192, 62, 14, 62, 7, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 67, 62, 65,155,139, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 19,
+ 62,124,224, 19, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 14,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 84, 7, 59,124,223,127, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,191,
+ 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 61,239, 63, 65,123,219, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,223,247, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 20,235, 61,197,142,255, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 5,
+ 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,138, 63,216,177,184, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 19, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 15,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 84,135, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136,
+ 61, 14, 61,255, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,231, 61,124,224, 15, 63,127,101,126,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,203, 61,197,143, 7, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 11, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59,
+ 62, 65,155,147, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 27, 63,245, 17,142,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 16,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,135, 59,124,223,255,
+ 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,231, 60,124,224, 15, 63, 2, 71,187, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 62, 7, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 84,247, 61,124,224, 19, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,203, 61,197,143, 17,
+ 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,164, 62, 14, 62, 14, 63,187,172,164, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 51, 62, 65,155,148, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 85, 7, 62,124,224, 30, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 65, 17,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 83, 7, 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84, 71,
+ 60,124,223,191, 63, 2, 71,186, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127, 40, 61, 14, 61,223, 63, 65,123,218,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,199, 61,124,223,239, 63,127,101,124, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 20,155, 61,197,142,255, 63,158, 2, 80, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,128,
+ 62, 14, 61,255, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 11, 62, 65,155,131, 63,216,177,184,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,243, 62,124,224, 15, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 18,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,135, 60,124,223,191, 63, 2, 71,186, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127, 72, 61, 14, 61,239, 63, 65,123,218, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,199, 61,124,223,255,
+ 63,127,101,124, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,139, 61,197,142,247, 63,158, 2, 81, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,120, 62, 14, 61,255, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,137,251, 62, 65,155,131, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,239, 62,124,224, 11,
+ 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 19,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7,
+ 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,223,255, 63, 2, 71,187,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,200, 61, 14, 62, 15, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 85, 39, 61,124,224, 31, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 11,
+ 61,197,143, 23, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,200, 62, 14, 62, 15, 63,187,172,165,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 91, 62, 65,155,147, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 85, 39, 62,124,224, 27, 63,245, 17,143, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 65, 20,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,222,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 85,135, 60,124,223,191, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 61,239,
+ 63, 65,123,221, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85,103, 61,124,223,255, 63,127,101,127, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 43, 61,197,142,255, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,200, 62, 14, 62, 3, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 75, 62, 65,155,135,
+ 63,216,177,186, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 19, 63,245, 17,143, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 21,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255, 62,131,146, 59,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127,200, 61, 14, 62, 15, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 39,
+ 61,124,224, 15, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 11, 61,197,143, 15, 63,158, 2, 82,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,200, 62, 14, 62, 15, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 91, 62, 65,155,151, 63,216,177,186, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 31,
+ 62,124,224, 27, 63,245, 17,143, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 22,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 85, 7, 59,124,223,127, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,199, 60,124,223,191,
+ 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 61,231, 63, 65,123,219, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,215, 61,124,223,231, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 20,171, 61,197,142,247, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,152, 62, 14, 62, 1,
+ 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 27, 62, 65,155,135, 63,216,177,185, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,251, 62,124,224, 15, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 23,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 83, 7, 59,124,223,191, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 84,135, 60,124,223,239, 63, 2, 71,186, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,104,
+ 61, 14, 62, 3, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,231, 61,124,224, 15, 63,127,101,125,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,187, 61,197,143, 15, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,152, 62, 14, 62, 11, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 35,
+ 62, 65,155,145, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,255, 62,124,224, 25, 63,245, 17,141,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 24,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,224, 63,
+ 62,131,146, 56, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,224, 47, 63, 2, 71,186, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 62, 15, 63, 65,123,218, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 85, 7, 61,124,224, 29, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 24,
+ 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 17, 63,187,172,164, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,155, 63,216,177,183, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 85, 7, 62,124,224, 35, 63,245, 17,140, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 65, 25,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135,
+ 60,124,223,255, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 62, 7, 63, 65,123,221,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 71, 61,124,224, 23, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 21, 43, 61,197,143, 23, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,216,
+ 62, 14, 62, 15, 63,187,172,166, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 91, 62, 65,155,150, 63,216,177,186,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 31, 62,124,224, 30, 63,245, 17,143, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 26,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,224, 15, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127,200, 61, 14, 62, 11, 63, 65,123,221, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 23,
+ 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 19, 63,158, 2, 81, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 17, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 75, 62, 65,155,151, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 33,
+ 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 27,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7,
+ 59,124,223,191, 62,131,146, 59, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,224, 15, 63, 2, 71,188,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 62, 7, 63, 65,123,221, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 85, 39, 61,124,224, 19, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235,
+ 61,197,143, 17, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 14, 63,187,172,165,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 75, 62, 65,155,151, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 34, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 65, 28,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,103, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 84,191, 60,124,224, 63, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,144, 61, 14, 62, 15,
+ 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 3, 61,124,224, 15, 63,127,101,126, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,223, 61,197,143, 7, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,174, 62, 14, 62, 11, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 63, 62, 65,155,147,
+ 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 15, 62,124,224, 27, 63,245, 17,142, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 29,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,191, 62,131,146, 59,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,224, 3, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,128, 8, 61, 14, 62, 4, 63, 65,123,221, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 71,
+ 61,124,224, 18, 63,127,101,128, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 43, 61,197,143, 15, 63,158, 2, 82,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,200, 62, 14, 62, 14, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 91, 62, 65,155,149, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23,
+ 62,124,224, 26, 63,245, 17,143, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 30,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 84, 7, 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,199, 60,124,223,191,
+ 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 61,239, 63, 65,123,219, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,247, 61,124,223,247, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 20,203, 61,197,143, 3, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,160, 62, 14, 62, 7,
+ 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 51, 62, 65,155,145, 63,216,177,184, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 7, 62,124,224, 25, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 31,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 87, 7, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 85,199, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 40,
+ 61, 14, 62, 15, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 71, 61,124,224, 31, 63,127,101,126,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 27, 61,197,143, 31, 63,158, 2, 80, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,208, 62, 14, 62, 27, 63,187,172,163, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 91,
+ 62, 65,155,163, 63,216,177,183, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 27, 62,124,224, 43, 63,245, 17,140,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 32,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255,
+ 62,131,146, 59, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,223,255, 63, 2, 71,188, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 62, 7, 63, 65,123,221, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 85, 39, 61,124,224, 15, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 19,
+ 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 13, 63,187,172,164, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 75, 62, 65,155,147, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 85, 23, 62,124,224, 27, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 65, 33,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 86, 7, 59,124,223,127, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135,
+ 60,124,223,207, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 61,244, 63, 65,123,219,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 39, 61,124,223,254, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 21, 11, 61,197,143, 5, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184,
+ 62, 14, 62, 9, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 75, 62, 65,155,143, 63,216,177,185,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 25, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 34,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,241, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127,168, 61, 14, 61,253, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 23, 61,124,224, 11,
+ 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,219, 61,197,143, 13, 63,158, 2, 81, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,176, 62, 14, 62, 12, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 59, 62, 65,155,146, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 11, 62,124,224, 27,
+ 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 35,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,199,
+ 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,247, 60,124,223,255, 63, 2, 71,187,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,160, 61, 14, 61,255, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 85, 11, 61,124,223,255, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,231,
+ 61,197,143, 15, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,178, 62, 14, 62, 7, 63,187,172,165,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 61, 62, 65,155,143, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 85, 14, 62,124,224, 23, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 65, 36,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 85, 7, 60,124,223,191, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 61,239,
+ 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,223,239, 63,127,101,126, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,203, 61,197,142,255, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,184, 62, 14, 62, 3, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 75, 62, 65,155,137,
+ 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 17, 63,245, 17,141, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 37,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,135, 59,124,223,255, 62,131,146, 57,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,215, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127,140, 61, 14, 62, 15, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,251,
+ 61,124,224, 15, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,219, 61,197,143, 15, 63,158, 2, 82,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,178, 62, 14, 62, 15, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 61, 62, 65,155,147, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 15,
+ 62,124,224, 27, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 38,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 85, 7, 59,124,224, 13, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,224, 31,
+ 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168, 61, 14, 62, 9, 63, 65,123,220, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 23, 61,124,224, 22, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 20,235, 61,197,143, 16, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,176, 62, 14, 62, 14,
+ 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,148, 63,216,177,185, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 15, 62,124,224, 30, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 39,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,199, 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 84,231, 60,124,223,159, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,144,
+ 61, 14, 61,231, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,223,239, 63,127,101,126,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,217, 61,197,142,255, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,175, 62, 14, 62, 5, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 56,
+ 62, 65,155,140, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 11, 62,124,224, 21, 63,245, 17,142,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 40,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,224,255,
+ 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,224, 63, 63, 2, 71,188, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 72, 61, 14, 62, 31, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 85,103, 61,124,224, 47, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 75, 61,197,143, 39,
+ 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,248, 62, 14, 62, 27, 63,187,172,163, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138,139, 62, 65,155,163, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 85, 55, 62,124,224, 43, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 65, 41,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 85, 7, 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,199,
+ 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,152, 61, 14, 61,239, 63, 65,123,219,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 15, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 20,219, 61,197,143, 7, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,176,
+ 62, 14, 62, 11, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,139, 63,216,177,185,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 15, 62,124,224, 19, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 42,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,255, 62,131,146, 56, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84, 71, 60,124,223,191, 63, 2, 71,186, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127, 72, 61, 14, 61,239, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,231, 61,124,223,255,
+ 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,187, 61,197,142,255, 63,158, 2, 81, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,152, 62, 14, 62, 3, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 35, 62, 65,155,139, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,255, 62,124,224, 19,
+ 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 43,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7,
+ 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 71, 60,124,223,255, 63, 2, 71,186,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,200, 61, 14, 61,239, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 85, 23, 61,124,223,255, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,251,
+ 61,197,143, 7, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 7, 63,187,172,164,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 67, 62, 65,155,139, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 85, 19, 62,124,224, 19, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 65, 44,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,199, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 84,231, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,152, 61, 14, 62, 15,
+ 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 3, 61,124,224, 15, 63,127,101,126, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 15, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,180, 62, 14, 62, 11, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 63, 62, 65,155,147,
+ 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 15, 62,124,224, 27, 63,245, 17,141, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 45,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255, 62,131,146, 58,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 39, 60,124,224, 31, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127,168, 61, 14, 62, 15, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,255,
+ 61,124,224, 39, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,227, 61,197,143, 33, 63,158, 2, 82,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,176, 62, 14, 62, 24, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 67, 62, 65,155,162, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 17,
+ 62,124,224, 45, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 46,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 85, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,199, 60,124,223,255,
+ 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 61,255, 63, 65,123,219, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 15, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 20,219, 61,197,143, 7, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,176, 62, 14, 62, 11,
+ 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,143, 63,216,177,185, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 15, 62,124,224, 19, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 47,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,135, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 84,231, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,152,
+ 61, 14, 62, 7, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,255, 61,124,224, 15, 63,127,101,126,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,219, 61,197,143, 15, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 15, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 51,
+ 62, 65,155,147, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 9, 62,124,224, 27, 63,245, 17,142,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 48,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 82, 7, 59,124,223,223,
+ 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84, 7, 60,124,223,235, 63, 2, 71,187, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,126,200, 61, 14, 61,251, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 84,167, 61,124,224, 9, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,107, 61,197,143, 11,
+ 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,120, 62, 14, 62, 11, 63,187,172,164, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,137,251, 62, 65,155,145, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 84,239, 62,124,224, 28, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 65, 49,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 85, 7, 59,124,222,255, 62,131,146, 56, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 39,
+ 60,124,223,191, 63, 2, 71,186, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168, 61, 14, 61,239, 63, 65,123,219,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 23, 61,124,223,255, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 21, 3, 61,197,143, 7, 63,158, 2, 80, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,196,
+ 62, 14, 62, 7, 63,187,172,163, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 87, 62, 65,155,143, 63,216,177,183,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 29, 62,124,224, 23, 63,245, 17,140, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 50,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,191, 62,131,146, 57, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84, 7, 60,124,223,223, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127, 72, 61, 14, 61,251, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,199, 61,124,224, 11,
+ 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,155, 61,197,143, 13, 63,158, 2, 81, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,136, 62, 14, 62, 12, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 19, 62, 65,155,144, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,247, 62,124,224, 24,
+ 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 51,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7,
+ 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,224, 31, 63, 2, 71,188,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 62, 7, 63, 65,123,221, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 85, 71, 61,124,224, 15, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 11,
+ 61,197,143, 11, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,200, 62, 14, 62, 11, 63,187,172,164,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 91, 62, 65,155,143, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 85, 31, 62,124,224, 23, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 65, 52,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 85, 7, 60,124,223,239, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168, 61, 14, 62, 3,
+ 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 15, 63,127,101,127, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,219, 61,197,143, 17, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,168, 62, 14, 62, 13, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,149,
+ 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 29, 63,245, 17,142, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 53,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86,135, 59,124,223,255, 62,131,146, 57,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,103, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127,248, 61, 14, 61,255, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 55,
+ 61,124,224, 15, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 35, 61,197,143, 15, 63,158, 2, 80,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,220, 62, 14, 62, 15, 63,187,172,162, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138,107, 62, 65,155,151, 63,216,177,182, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 37,
+ 62,124,224, 31, 63,245, 17,139, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 54,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 86,135, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,103, 60,124,223,255,
+ 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,184, 61, 14, 62, 15, 63, 65,123,220, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 31, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 20,235, 61,197,143, 31, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,180, 62, 14, 62, 23,
+ 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 71, 62, 65,155,159, 63,216,177,184, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 18, 62,124,224, 43, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 55,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,222,255, 62,131,146, 56, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 85, 39, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168,
+ 61, 14, 62, 15, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 15, 61,124,224, 15, 63,127,101,125,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,243, 61,197,143, 15, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 11, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 83,
+ 62, 65,155,151, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 25, 62,124,224, 27, 63,245, 17,140,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 56,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,222,255,
+ 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,223,191, 63, 2, 71,188, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 61,239, 63, 65,123,221, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 85, 71, 61,124,223,255, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 75, 61,197,143, 7,
+ 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,216, 62, 14, 62, 7, 63,187,172,165, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138,107, 62, 65,155,143, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 85, 31, 62,124,224, 23, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 65, 57,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 85, 7, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7,
+ 60,124,224, 63, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168, 61, 14, 62, 15, 63, 65,123,220,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 31, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 20,219, 61,197,143, 23, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,176,
+ 62, 14, 62, 15, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 67, 62, 65,155,151, 63,216,177,185,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 19, 62,124,224, 31, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 58,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 71, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127,200, 61, 14, 61,255, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 23, 61,124,224, 15,
+ 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 15, 63,158, 2, 82, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,176, 62, 14, 62, 15, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 59, 62, 65,155,147, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 19, 62,124,224, 31,
+ 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 59,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7,
+ 59,124,223,143, 62,131,146, 56, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,223, 63, 2, 71,186,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,200, 61, 14, 61,251, 63, 65,123,218, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 85, 39, 61,124,224, 2, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235,
+ 61,197,143, 11, 63,158, 2, 80, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 11, 63,187,172,163,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 43, 62, 65,155,145, 63,216,177,183, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 85, 7, 62,124,224, 27, 63,245, 17,139, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 65, 60,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 85, 7, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168, 61, 14, 62, 15,
+ 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 23, 61,124,224, 15, 63,127,101,126, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 7, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,176, 62, 14, 62, 11, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 67, 62, 65,155,147,
+ 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 19, 62,124,224, 27, 63,245, 17,142, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 61,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,223,255, 62,131,146, 57,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,231, 60,124,223,191, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127,152, 61, 14, 61,239, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 15,
+ 61,124,223,255, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,142,255, 63,158, 2, 81,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 7, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 75, 62, 65,155,143, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 19,
+ 62,124,224, 23, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 62,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 84, 7, 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,135, 60,124,223,191,
+ 63, 2, 71,186, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127, 8, 61, 14, 61,239, 63, 65,123,218, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,199, 61,124,223,239, 63,127,101,124, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 20,139, 61,197,142,247, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,120, 62, 14, 61,251,
+ 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 11, 62, 65,155,131, 63,216,177,185, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,239, 62,124,224, 11, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 63,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 85, 39, 60,124,223,191, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,176,
+ 61, 14, 61,239, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 19, 61,124,223,239, 63,127,101,125,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,231, 61,197,142,255, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,179, 62, 14, 62, 5, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 65,
+ 62, 65,155,139, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 16, 62,124,224, 21, 63,245, 17,141,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 64,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,255,
+ 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,199, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,104, 61, 14, 61,255, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 84,239, 61,124,224, 15, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,203, 61,197,143, 11,
+ 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,164, 62, 14, 62, 11, 63,187,172,164, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 51, 62, 65,155,145, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 85, 11, 62,124,224, 25, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 65, 65,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 86, 7, 59,124,223,127, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7,
+ 60,124,223,207, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,200, 61, 14, 61,243, 63, 65,123,220,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 39, 61,124,223,251, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 20,235, 61,197,143, 3, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184,
+ 62, 14, 62, 7, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 75, 62, 65,155,141, 63,216,177,184,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 23, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 66,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,255, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127,168, 61, 14, 62, 7, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 15,
+ 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,219, 61,197,143, 15, 63,158, 2, 81, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 13, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 51, 62, 65,155,147, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 11, 62,124,224, 27,
+ 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 67,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7,
+ 59,124,223,127, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,223, 63, 2, 71,187,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,200, 61, 14, 61,247, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 85, 7, 61,124,223,255, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235,
+ 61,197,143, 3, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 6, 63,187,172,164,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 75, 62, 65,155,141, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 22, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 65, 68,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255, 62,131,146, 59, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 85, 71, 60,124,224, 13, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168, 61, 14, 62, 5,
+ 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 19, 63,127,101,126, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,227, 61,197,143, 17, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,176, 62, 14, 62, 14, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,149,
+ 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 13, 62,124,224, 31, 63,245, 17,142, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 69,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,151, 59,124,223,255, 62,131,146, 57,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,219, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127,140, 61, 14, 62, 7, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,249,
+ 61,124,224, 15, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,205, 61,197,143, 15, 63,158, 2, 82,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 15, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 51, 62, 65,155,147, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 10,
+ 62,124,224, 27, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 70,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 86, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,223,255,
+ 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 61,255, 63, 65,123,219, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 71, 61,124,224, 15, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 21, 11, 61,197,143, 15, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,200, 62, 14, 62, 7,
+ 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 91, 62, 65,155,143, 63,216,177,185, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 27, 62,124,224, 23, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 71,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,175, 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 84,224, 60,124,223,191, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,142,
+ 61, 14, 61,239, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 1, 61,124,223,239, 63,127,101,126,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,207, 61,197,142,255, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,164, 62, 14, 62, 3, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 42,
+ 62, 65,155,135, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 4, 62,124,224, 15, 63,245, 17,141,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 72,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255,
+ 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,224, 31, 63, 2, 71,187, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,200, 61, 14, 62, 7, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 85, 39, 61,124,224, 23, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 19,
+ 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 15, 63,187,172,165, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,147, 63,216,177,186, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 85, 23, 62,124,224, 31, 63,245, 17,143, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 65, 73,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 85, 7, 59,124,223,127, 62,131,146, 56, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 39,
+ 60,124,223,223, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,176, 61, 14, 61,239, 63, 65,123,219,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 19, 61,124,223,255, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 20,231, 61,197,143, 3, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,178,
+ 62, 14, 62, 9, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 63, 62, 65,155,143, 63,216,177,184,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 15, 62,124,224, 24, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 74,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,224, 31, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127,136, 61, 14, 62, 7, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 15,
+ 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 19, 63,158, 2, 82, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 15, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 75, 62, 65,155,151, 63,216,177,186, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 31,
+ 63,245, 17,143, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 75,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7,
+ 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,255, 63, 2, 71,187,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 62, 7, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 15, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,203,
+ 61,197,143, 15, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 15, 63,187,172,165,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 75, 62, 65,155,151, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 31, 63,245, 17,143, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 65, 76,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,255, 62,131,146, 56, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 84,135, 60,124,223,255, 63, 2, 71,186, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127, 72, 61, 14, 61,255,
+ 63, 65,123,217, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,231, 61,124,224, 15, 63,127,101,123, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,203, 61,197,143, 15, 63,158, 2, 80, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,168, 62, 14, 62, 11, 63,187,172,163, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,147,
+ 63,216,177,182, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 7, 62,124,224, 27, 63,245, 17,139, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 77,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 71, 59,124,223,255, 62,131,146, 56,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 39, 60,124,223,255, 63, 2, 71,186, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127,144, 61, 14, 62, 15, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,255,
+ 61,124,224, 31, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,223, 61,197,143, 31, 63,158, 2, 81,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,176, 62, 14, 62, 23, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 63, 62, 65,155,161, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 14,
+ 62,124,224, 43, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 78,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 84, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,135, 60,124,224, 15,
+ 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 62, 7, 63, 65,123,220, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,231, 61,124,224, 15, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 20,203, 61,197,143, 17, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 15,
+ 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,150, 63,216,177,185, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 30, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 79,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84, 7, 59,124,223,255, 62,131,146, 56, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 84,135, 60,124,223,255, 63, 2, 71,185, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127, 72,
+ 61, 14, 61,255, 63, 65,123,217, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,231, 61,124,223,255, 63,127,101,123,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,203, 61,197,143, 15, 63,158, 2, 80, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,152, 62, 14, 62, 7, 63,187,172,163, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 43,
+ 62, 65,155,143, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 84,255, 62,124,224, 23, 63,245, 17,141,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 80,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,223,127,
+ 62,131,146, 56, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,223, 63, 2, 71,187, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168, 61, 14, 61,247, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 85, 23, 61,124,223,255, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 3,
+ 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,176, 62, 14, 62, 7, 63,187,172,164, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,141, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 85, 15, 62,124,224, 23, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 65, 81,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7,
+ 60,124,223,191, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,200, 61, 14, 61,239, 63, 65,123,220,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 39, 61,124,223,255, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 20,235, 61,197,143, 3, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184,
+ 62, 14, 62, 5, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 75, 62, 65,155,139, 63,216,177,184,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 21, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 82,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255, 62,131,146, 59, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85,135, 60,124,223,255, 63, 2, 71,189, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127,200, 61, 14, 62, 1, 63, 65,123,221, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 23, 61,124,224, 16,
+ 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235, 61,197,143, 15, 63,158, 2, 82, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 13, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 67, 62, 65,155,147, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 15, 62,124,224, 30,
+ 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 83,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7,
+ 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,223, 63, 2, 71,187,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 61,255, 63, 65,123,219, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 7, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,203,
+ 61,197,143, 11, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 11, 63,187,172,165,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,145, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 29, 63,245, 17,143, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 65, 84,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,191, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 85,135, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,128, 8, 61, 14, 62, 11,
+ 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 39, 61,124,224, 19, 63,127,101,127, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 11, 61,197,143, 21, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,200, 62, 14, 62, 17, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 91, 62, 65,155,153,
+ 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 31, 62,124,224, 33, 63,245, 17,141, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 85,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7, 59,124,223,255, 62,131,146, 57,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 86, 7, 60,124,223,255, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,128, 8, 61, 14, 61,255, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 71,
+ 61,124,224, 15, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 21, 43, 61,197,143, 15, 63,158, 2, 81,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,216, 62, 14, 62, 11, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138,107, 62, 65,155,147, 63,216,177,183, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 39,
+ 62,124,224, 27, 63,245, 17,140, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 86,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 86, 7, 59,124,223,255, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,255,
+ 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,200, 61, 14, 62, 7, 63, 65,123,220, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 15, 63,127,101,127, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 20,203, 61,197,143, 15, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 13,
+ 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 43, 62, 65,155,147, 63,216,177,184, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 15, 62,124,224, 31, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 87,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,135, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 84,199, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136,
+ 61, 14, 61,255, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,255, 61,124,224, 15, 63,127,101,126,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,215, 61,197,143, 7, 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,174, 62, 14, 62, 11, 63,187,172,165, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 57,
+ 62, 65,155,143, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 13, 62,124,224, 23, 63,245, 17,142,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 88,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,135, 59,124,223,255,
+ 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,231, 60,124,223,255, 63, 2, 71,187, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,168, 61, 14, 62, 15, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 85, 15, 61,124,224, 31, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,211, 61,197,143, 23,
+ 63,158, 2, 82, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 15, 63,187,172,165, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 51, 62, 65,155,147, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 85, 11, 62,124,224, 27, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216,
+ 13, 65, 89,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0,186,145, 85, 7, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,247,
+ 60,124,223,191, 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,152, 61, 14, 61,239, 63, 65,123,219,
+ 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 11, 61,124,223,255, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0,188,227, 20,227, 61,197,142,255, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,180,
+ 62, 14, 62, 7, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 73, 62, 65,155,143, 63,216,177,184,
+ 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 20, 62,124,224, 23, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 90,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,135, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0,
+ 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,231, 60,124,223,255, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,
+188, 35,127,136, 61, 14, 61,255, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,255, 61,124,224, 15,
+ 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,211, 61,197,143, 15, 63,158, 2, 81, 66,122, 0, 0,
+ 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 15, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,
+189, 94,138, 55, 62, 65,155,147, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 12, 62,124,224, 27,
+ 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 91,144, 0, 0, 1, 37,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 86, 7,
+ 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,224, 63, 63, 2, 71,187,
+ 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,200, 61, 14, 62, 15, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0,
+ 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 31, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,235,
+ 61,197,143, 23, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,184, 62, 14, 62, 15, 63,187,172,164,
+ 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 75, 62, 65,155,151, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0,
+ 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 35, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 0,216, 13, 65, 92,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,135, 59,124,224, 15, 62,131,146, 58, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,
+187,145, 84,199, 60,124,223,251, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,152, 61, 14, 62, 8,
+ 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,224, 22, 63,127,101,126, 66, 72, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,219, 61,197,143, 17, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,
+189, 35,127,172, 62, 14, 62, 15, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 51, 62, 65,155,148,
+ 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 9, 62,124,224, 30, 63,245, 17,141, 66,200, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 93,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 85, 7, 59,124,223,255, 62,131,146, 58,
+ 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,191, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0,
+ 0, 0, 0, 0,188, 35,127,168, 61, 14, 61,255, 63, 65,123,220, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 23,
+ 61,124,224, 15, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,219, 61,197,143, 15, 63,158, 2, 81,
+ 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,176, 62, 14, 62, 11, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0,
+ 0, 0, 0, 0,189, 94,138, 67, 62, 65,155,147, 63,216,177,184, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 19,
+ 62,124,224, 27, 63,245, 17,141, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 94,144,
+ 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+186,145, 84, 7, 59,124,222,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 85, 7, 60,124,223,191,
+ 63, 2, 71,187, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,136, 61, 14, 61,239, 63, 65,123,219, 66, 22, 0, 0,
+ 63, 32, 0, 0, 0, 0, 0, 0,188,145, 85, 7, 61,124,223,239, 63,127,101,126, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+188,227, 20,203, 61,197,142,255, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,168, 62, 14, 62, 3,
+ 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 59, 62, 65,155,137, 63,216,177,184, 66,175, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 23, 62,124,224, 17, 63,245, 17,142, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 95,144, 0, 0, 1, 37, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 84,111, 59,124,223,255, 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0,
+ 0, 0, 0, 0,187,145, 84,173, 60,124,223,255, 63, 2, 71,188, 65,200, 0, 0, 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127,116,
+ 61, 14, 61,255, 63, 65,123,221, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,188,145, 84,245, 61,124,224, 15, 63,127,101,127,
+ 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,199, 61,197,143, 13, 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0,
+ 0, 0, 0, 0,189, 35,127,163, 62, 14, 62, 13, 63,187,172,164, 66,150, 0, 0, 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 47,
+ 62, 65,155,147, 63,216,177,185, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,189,145, 85, 6, 62,124,224, 28, 63,245, 17,142,
+ 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,216, 13, 65, 96,144, 0, 0, 1, 37, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,186,145, 82, 7, 59,124,223,127,
+ 62,131,146, 57, 65, 72, 0, 0, 63, 96, 0, 0, 0, 0, 0, 0,187,145, 84,135, 60,124,223,223, 63, 2, 71,186, 65,200, 0, 0,
+ 63, 64, 0, 0, 0, 0, 0, 0,188, 35,127, 8, 61, 14, 61,247, 63, 65,123,218, 66, 22, 0, 0, 63, 32, 0, 0, 0, 0, 0, 0,
+188,145, 84,199, 61,124,224, 7, 63,127,101,125, 66, 72, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,188,227, 20,139, 61,197,143, 7,
+ 63,158, 2, 81, 66,122, 0, 0, 62,192, 0, 0, 0, 0, 0, 0,189, 35,127,136, 62, 14, 62, 11, 63,187,172,164, 66,150, 0, 0,
+ 62,128, 0, 0, 0, 0, 0, 0,189, 94,138, 27, 62, 65,155,147, 63,216,177,183, 66,175, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
+189,145, 84,247, 62,124,224, 28, 63,245, 17,140, 66,200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 20,
+ 13, 65, 97,144, 0, 0, 0,112, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0, 76, 13, 65, 97,208, 0, 0, 0,102, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19,
+ 0, 0, 0, 23, 80, 97,114,116,105, 99,108,101, 83,121,115,116,101,109, 32, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 64,202, 32, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 1, 0, 2, 0, 0,
+ 0, 0, 79, 66, 0, 0, 3, 68, 7,159,248, 32, 0, 0, 0,109, 0, 0, 0, 1, 7,159,252, 32, 7,159,244, 32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 79, 66,112,114,101,118,105,101,119,108, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 97,109,112, 0, 1, 4, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 64,161,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,188,211,197,192, 65, 59,229, 76, 64,184,106,208,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 98,215,247, 63, 72, 11, 71, 63, 6,248,230, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63, 29, 14,212, 62,182,225,149,191, 52, 76, 84, 0, 0, 0, 0,191, 74, 40, 22, 62,139, 74,201,
+191, 12,198,228, 0, 0, 0, 0,187,157,213, 84, 63,100,190,151, 62,229,223,145, 0, 0, 0, 0,188,211,197,192, 65, 59,229, 76,
+ 64,184,106,208, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 51, 46, 0, 0,179, 63, 0, 0, 0, 0, 0, 0, 51, 2, 0, 0, 63,128, 0, 0,
+179, 0, 0, 0, 0, 0, 0, 0,179, 85, 0, 0,179, 0, 0, 1, 63,128, 0, 0, 0, 0, 0, 0,177,255,255,203, 40,122,144, 2,
+181, 0, 0, 0, 63,128, 0, 0, 63, 29, 14,213,191, 74, 40, 23,187,157,211,254, 0, 0, 0, 0,191, 52, 76, 83,191, 12,198,227,
+ 62,229,223,148, 0, 0, 0, 0,190,182,225,149,190,139, 74,202,191,100,190,152, 0, 0, 0, 0,192,158, 36,208,192,110,186,100,
+193,169, 43, 99, 63,128, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 5, 0, 1, 0, 0, 0, 0, 79, 66, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0,
+ 61, 35,215, 10, 63,128, 0, 0, 62,204,204,205, 61,204,204,205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
+ 1, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 1, 64, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 3, 68,
+ 7,159,252, 32, 0, 0, 0,109, 0, 0, 0, 1, 0, 0, 0, 0, 7,159,248, 32, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66,116,101,
+120,116,117,114,101, 0,114,101,118,105,101,119, 46, 48, 48, 53, 0, 0, 0, 0, 0, 1, 4, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 65,161,176,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 65, 98, 80,188,183, 16, 61,191,103,204, 21, 63,228,234, 48, 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,155, 39,153, 64,155, 39,153, 64,155, 39,153, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,201, 15,218, 37,192, 0, 0, 36,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 64,155, 39,153, 38, 27, 39,152,166,232,187,102, 0, 0, 0, 0, 38,232,187,102, 52,196,134,157, 64,155, 39,153, 0, 0, 0, 0,
+ 38, 27, 39,154,192,155, 39,153, 52,196,134,157, 0, 0, 0, 0,188,183, 16, 61,191,103,204, 21, 63,228,234, 48, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0,153, 34, 33,106, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+153, 34, 33,106, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,179,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 62, 83, 50, 25, 36,158,101,147, 35,211, 50, 27, 0, 0, 0, 0,164,158,101,147, 62, 83, 50, 25, 38,174, 59,158, 0, 0, 0, 0,
+173, 44, 24, 0,175, 94,165,224, 62, 83, 50, 25, 0, 0, 0, 0, 59, 33,251,236, 59, 40, 37,135, 63,238, 71,118, 63,128, 0, 0,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 68, 0, 1, 0, 2, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0,201,150,180, 56, 63,128, 0, 0, 61, 35,215, 10, 63,128, 0, 0,
+ 62,204,204,205, 61,204,204,205, 0, 0, 0, 0, 61,117,194,143, 0, 0, 0, 0, 4, 0, 1, 1, 1, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 65, 98, 80, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 77, 65, 0, 0, 2,108, 7,160, 0, 32, 0, 0, 0, 42, 0, 0, 0, 1, 7,160, 4, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 65, 99,104,101, 99,107,101,114,100, 97,114,107, 0, 0, 0, 97,116,101,114,
+105, 97, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 61,221, 1,116, 61,220,251,200, 61,220,251,200,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63, 0, 0, 0, 63, 89,153,154, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 76,204,205,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,160, 0, 0, 0, 0, 0, 0, 63,160, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 2, 0, 2, 0, 1, 0, 6, 63,128, 0, 0, 63,128, 0, 0, 0, 18, 0, 18,
+ 59,163,215, 10, 59,163,215, 10, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 64, 0, 3, 1, 64, 0, 3, 0, 1, 0, 4,
+ 0, 12, 0, 4, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64,128, 0, 0, 63, 0, 0, 0, 61,204,204,205, 63, 0, 0, 0,
+ 61,204,204,205, 61,204,204,205, 63,128, 0, 0, 8, 16, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 13, 65, 98,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63, 76,204,205, 63, 76,204,205, 63, 76,204,205, 61, 76,204,205, 61,204,204,205, 63,166,102,102, 63,128, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0,136, 13, 65, 98,128, 0, 0, 0, 33, 0, 0, 0, 1, 0, 16, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,103, 16, 0, 0, 0, 0, 0, 0, 0, 0, 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, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,192, 0, 1,
+ 63,192, 0, 1, 63,192, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,209,183, 23, 56,209,177,184,
+ 56,209,177,184, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 62, 76,204,205,
+ 0, 0, 0, 0, 0, 0, 77, 65, 0, 0, 2,108, 7,160, 4, 32, 0, 0, 0, 42, 0, 0, 0, 1, 7,160, 8, 32, 7,160, 0, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 77, 65, 99,104,101, 99,107,101,114,108,105,103,104,116, 0, 0, 0, 97,116,101,114,105, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 62,157, 65,188, 62,157, 61,178, 62,157, 61,178, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63, 0, 0, 0, 63, 89,153,154, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 76,204,205, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,160, 0, 0, 0, 0, 0, 0, 63,160, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 61,204,204,205, 0, 2, 0, 2, 0, 1, 0, 6, 63,128, 0, 0, 63,128, 0, 0, 0, 18, 0, 18, 59,163,215, 10,
+ 59,163,215, 10, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 64, 0, 3, 1, 64, 0, 3, 0, 1, 0, 4, 0, 12, 0, 4,
+ 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64,128, 0, 0, 63, 0, 0, 0, 61,204,204,205, 63, 0, 0, 0, 61,204,204,205,
+ 61,204,204,205, 63,128, 0, 0, 8, 16, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 13, 65, 99, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63, 76,204,205, 63, 76,204,205, 63, 76,204,205, 61, 76,204,205, 61,204,204,205, 63,166,102,102, 63,128, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0,136, 13, 65, 99, 48, 0, 0, 0, 33, 0, 0, 0, 1, 0, 16, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 65,103, 16, 0, 0, 0, 0, 0, 0, 0, 0, 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, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,209,183, 23, 56,209,177,184, 56,209,177,184,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 62, 76,204,205, 0, 0, 0, 0,
+ 0, 0, 77, 65, 0, 0, 2,108, 7,160, 8, 32, 0, 0, 0, 42, 0, 0, 0, 1, 7,160, 16, 32, 7,160, 4, 32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 77, 65,112,114,101,118,105,101,119, 0, 0, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 63,128, 0, 0, 63, 54,232, 61, 63, 23,161,184, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 62, 68,248,188, 63,128, 0, 0, 63, 76,204,205, 63, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,130,121,198, 63,160, 0, 0, 0, 0, 0, 0, 63,160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 61,204,204,205, 0, 2, 0, 2, 0, 50, 0, 6, 63,128, 0, 0, 63,128, 0, 0, 0, 18, 0, 18, 59,163,215, 10, 59,163,215, 10,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 17, 0, 3, 3, 17, 0, 3, 0, 1, 0, 4, 0, 12, 0, 4, 63, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 2,
+ 0, 0, 0, 0, 63, 0, 0, 0, 64,128, 0, 0, 63, 0, 0, 0, 61,204,204,205, 63, 0, 0, 0, 61,204,204,205, 61,204,204,205,
+ 63,128, 0, 0, 8, 16, 0, 1, 7,160, 12, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 13, 65, 99,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 65,100,144, 63, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63, 76,204,205,
+ 63, 76,204,205, 63, 76,204,205, 61, 76,204,205, 61,204,204,205, 63,166,102,102, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0,136, 13, 65, 99,224, 0, 0, 0, 33, 0, 0, 0, 1, 0, 16, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 13, 65,101,144, 0, 0, 0, 0, 0, 0, 0, 0, 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, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 62, 76,204,205, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 3, 8, 7,160, 12, 32, 0, 0, 0, 36, 0, 0, 0, 1, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 62,220, 40,245, 0, 0, 0, 0, 63,125,112,164, 63,128, 0, 0, 63, 24,214,106, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 1, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+ 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0,
+ 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+ 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0,
+ 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+ 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0,
+ 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+ 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 0, 0, 0, 32,
+ 13, 65,100,144, 0, 0, 0, 19, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 65, 0, 0, 2,108, 7,160, 16, 32, 0, 0, 0, 42, 0, 0, 0, 1,
+ 7,160, 24, 32, 7,160, 8, 32, 0, 0, 0, 0, 0, 0, 0, 0, 77, 65,116,101,120,116,117,114,101, 0,114,101,118,105,101,119,
+ 46, 48, 48, 49, 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, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63, 76,204,205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,160, 0, 0, 0, 0, 0, 0,
+ 63,160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61,204,204,205, 0, 2, 0, 2, 0, 50, 0, 6, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 18, 0, 18, 59,163,215, 10, 59,163,215, 10, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 71, 3, 1, 0, 67,
+ 0, 1, 0, 4, 0, 12, 0, 4, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 63, 0, 0, 0, 64,128, 0, 0, 63, 0, 0, 0, 61,204,204,205,
+ 63, 0, 0, 0, 61,204,204,205, 61,204,204,205, 63,128, 0, 0, 8, 1, 0,129, 7,160, 20, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 13, 65,100,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 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, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63, 76,204,205, 63, 76,204,205, 63, 76,204,205, 61, 76,204,205, 61,204,204,205, 63,166,102,102,
+ 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0,136, 13, 65,100,224, 0, 0, 0, 33, 0, 0, 0, 1,
+ 0, 1, 0,129, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,101,144, 0, 0, 0, 0, 0, 0, 0, 0, 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, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 63,128, 0, 0,
+ 62, 76,204,205, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 3, 8, 7,160, 20, 32, 0, 0, 0, 36, 0, 0, 0, 1, 0, 0, 0, 2,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,220, 40,245, 0, 0, 0, 0, 63,125,112,164,
+ 63,128, 0, 0, 63, 24,214,106, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 1, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0,
+ 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0,
+ 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0,
+ 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0,
+ 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0,
+ 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0,
+ 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0,
+ 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 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, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 77, 65, 0, 0, 2,108, 7,160, 24, 32, 0, 0, 0, 42, 0, 0, 0, 1, 0, 0, 0, 0, 7,160, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 77, 65,116,101,120,116,117,114,101, 46, 48, 48, 49, 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, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63, 76,204,205, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,160, 0, 0, 0, 0, 0, 0, 63,160, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 2, 0, 2, 0, 50, 0, 6, 63,128, 0, 0, 63,128, 0, 0, 0, 18, 0, 18, 59,163,215, 10,
+ 59,163,215, 10, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 3, 3, 1, 0, 3, 0, 1, 0, 4, 0, 12, 0, 4,
+ 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 3,
+ 0, 0, 0, 2, 0, 0, 0, 0, 63, 0, 0, 0, 64,128, 0, 0, 63, 0, 0, 0, 61,204,204,205, 63, 0, 0, 0, 61,204,204,205,
+ 61,204,204,205, 63,128, 0, 0, 0, 0, 0, 0, 7,160, 28, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63, 76,204,205, 63, 76,204,205, 63, 76,204,205, 61, 76,204,205, 61,204,204,205, 63,166,102,102, 63,128, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 3, 8, 7,160, 28, 32, 0, 0, 0, 36, 0, 0, 0, 1, 0, 0, 0, 2, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,220, 40,245, 0, 0, 0, 0, 63,125,112,164, 63,128, 0, 0,
+ 63, 24,214,106, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 1, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+ 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0,
+ 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+ 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0,
+ 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+ 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0,
+ 63, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0,
+ 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 69, 0, 0, 1, 4, 13, 65,101,144, 0, 0, 0, 38, 0, 0, 0, 1, 13, 65,103, 16, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 84, 69,112,114,101,118,105,101,119, 0,101,120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 62,128, 0, 0, 64,160, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 32, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 5, 0, 8, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 1, 0, 1,
+ 0, 3, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 60,204,204,205, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 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, 13, 65,102,192, 68, 65, 84, 65, 0, 0, 0, 32,
+ 13, 65,102,192, 0, 0, 0, 19, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 0, 0, 1, 4, 13, 65,103, 16, 0, 0, 0, 38, 0, 0, 0, 1,
+ 0, 0, 0, 0, 13, 65,101,144, 0, 0, 0, 0, 0, 0, 0, 0, 84, 69,102, 97,107,101,115,104, 97,100,111,119, 0, 0, 76,101,
+110,100, 0,101,120, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62,128, 0, 0, 64,160, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 64, 32, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 0, 40, 0, 5, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 1, 0, 1, 0, 3, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 60,204,204,205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 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, 77, 69, 0, 0, 1, 24, 13, 65,104, 64, 0, 0, 0, 52, 0, 0, 0, 1, 13, 65,109,208, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 77, 69, 67,117, 98,101, 46, 48, 48, 49, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 13, 65,105,128, 7,160,128, 32, 12,117,208, 32, 0, 0, 0, 0, 7,160, 32, 32, 7,160, 80, 32, 0, 0, 0, 0, 7,160,168, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,105,176, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 65,107, 16, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,108,112,
+ 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,249, 0, 0, 3,237, 0, 0, 1,244,
+ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 1, 61, 88,133,192,189, 85, 45,184,190, 24,181,196, 63, 35, 71,185, 62,235, 31,153,
+ 62,203,102,130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 4, 0, 1, 0, 1,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 65,105,128, 0, 0, 0, 0,
+ 0, 0, 0, 1, 7,160, 8, 32, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,105,176, 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,160, 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, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 47, 88, 7,160, 32, 32, 0, 0, 0, 58, 0, 0, 1,249, 62,131,144,140,
+ 60,200,163,119, 62, 85, 9,156, 92,125,170, 70, 21,228, 0,255, 0, 0, 0, 0,190, 26,222, 50, 60,200,163,119, 62, 85, 9,156,
+163,131,170, 70, 21,228, 0,255, 0, 0, 0, 0, 62,146,126, 61,188, 8, 37,223, 62, 47,183, 99, 76,247,194,191, 81,228, 2,255,
+ 0, 0, 0, 0,190, 56,185,147,188, 8, 37,223, 62, 47,183, 99,179, 9,194,191, 81,228, 2,255, 0, 0, 0, 0, 62,157,176,129,
+188,217, 91,211, 61,246,238,244, 84, 31,181,226, 61,191, 2,255, 0, 0, 0, 0,190, 79, 30, 28,188,217, 91,211, 61,246,238,244,
+171,225,181,226, 61,191, 2,255, 0, 0, 0, 0, 62, 94, 19,115,189,128,251,103, 62, 14, 32,150, 9,241,144,155, 62, 64, 2,255,
+ 0, 0, 0, 0,189,227,161, 26,189,128,251,103, 62, 14, 32,150,246, 15,144,155, 62, 64, 2,255, 0, 0, 0, 0, 62, 94, 19,115,
+189, 25,118,251, 62, 62,165, 20, 14,184,163,144, 87, 76, 2,255, 0, 0, 0, 0,189,227,161, 26,189, 25,118,251, 62, 62,165, 20,
+241, 72,163,144, 87, 76, 2,255, 0, 0, 0, 0, 62, 94, 19,115, 60, 34,107,232, 62, 92,128,116, 3, 3,131,121, 29,110, 0,255,
+ 0, 0, 0, 0,189,227,161, 26, 60, 34,107,232, 62, 92,128,116,252,253,131,121, 29,110, 0,255, 0, 0, 0, 0, 62, 56,193, 58,
+ 60,200,163,119, 62, 99,247, 77,171, 56,167,117, 36,206, 0,255, 0, 0, 0, 0,189,152,252,168, 60,200,163,119, 62, 99,247, 77,
+ 84,200,167,117, 36,206, 0,255, 0, 0, 0, 0, 62, 23, 42,109,188, 8, 37,223, 62, 73,215, 88,217,152,203,122,110, 56, 0,255,
+ 0, 0, 0, 0, 62, 0,197,229,188,217, 91,211, 62, 29, 14, 71,184,179,175, 93, 69, 66, 2,255, 0, 0, 0, 0,188,164, 23,249,
+188,217, 91,211, 62, 29, 14, 71, 71, 77,175, 93, 69, 66, 2,255, 0, 0, 0, 0, 61,182,231, 88, 61,121,154,159, 62, 32,201,179,
+151,181,255,104, 74, 51, 2,255, 0, 0, 0, 0, 60,134,121,207, 61,121,154,159, 62, 32,201,179,104, 75,255,104, 74, 51, 2,255,
+ 0, 0, 0, 0, 61,242,158, 25, 61,121,154,159, 62, 73,215, 88,171, 78,255,150, 95,246, 2,255, 0, 0, 0, 0,188, 80,194,110,
+ 61,121,154,159, 62, 73,215, 88, 84,178,255,150, 95,246, 2,255, 0, 0, 0, 0, 62, 41,211,138, 61,121,154,159, 62, 99,247, 77,
+133,152,254,153, 37, 98, 0,255, 0, 0, 0, 0,189,118, 66,143, 61,121,154,159, 62, 99,247, 77,122,104,254,153, 37, 98, 0,255,
+ 0, 0, 0, 0, 62, 56,193, 58, 61,206,232,154, 62, 99,247, 77,170, 24, 88, 13, 35, 89, 0,255, 0, 0, 0, 0,189,152,252,168,
+ 61,206,232,154, 62, 99,247, 77, 85,232, 88, 13, 35, 89, 0,255, 0, 0, 0, 0, 62, 23, 42,109, 62, 5, 79,173, 62, 73,215, 88,
+200,249, 65,221, 94,244, 2,255, 0, 0, 0, 0,189, 43,158, 31, 62, 5, 79,173, 62, 73,215, 88, 55, 7, 65,221, 94,244, 2,255,
+ 0, 0, 0, 0, 62, 0,197,229, 62, 27,180, 54, 62, 29, 14, 71,186, 51, 78, 86, 73, 78, 2,255, 0, 0, 0, 0,188,164, 23,249,
+ 62, 27,180, 54, 62, 29, 14, 71, 69,205, 78, 86, 73, 78, 2,255, 0, 0, 0, 0, 62, 94, 19,115, 62, 65, 6,111, 62, 14, 32,150,
+ 11, 2,107,152, 68,114, 2,255, 0, 0, 0, 0,189,227,161, 26, 62, 65, 6,111, 62, 14, 32,150,244,254,107,152, 68,114, 2,255,
+ 0, 0, 0, 0, 62, 94, 19,115, 62, 35, 43, 14, 62, 62,165, 20, 14,201, 91,180, 88, 14, 2,255, 0, 0, 0, 0,189,227,161, 26,
+ 62, 35, 43, 14, 62, 62,165, 20,241, 55, 91,180, 88, 14, 2,255, 0, 0, 0, 0, 62, 94, 19,115, 61,236,195,250, 62, 92,128,116,
+ 2,134,125, 29, 26,228, 0,255, 0, 0, 0, 0,189,227,161, 26, 61,236,195,250, 62, 92,128,116,253,122,125, 29, 26,228, 0,255,
+ 0, 0, 0, 0, 62,131,144,140, 61,206,232,154, 62, 85, 9,156, 93, 54, 85, 67, 20,154, 0,255, 0, 0, 0, 0,190, 26,222, 50,
+ 61,206,232,154, 62, 85, 9,156,162,202, 85, 67, 20,154, 0,255, 0, 0, 0, 0, 62,146,126, 61, 62, 5, 79,173, 62, 47,183, 99,
+ 76,241, 60,161, 82, 97, 2,255, 0, 0, 0, 0,190, 56,185,147, 62, 5, 79,173, 62, 47,183, 99,179, 15, 60,161, 82, 97, 2,255,
+ 0, 0, 0, 0, 62,157,176,129, 62, 27,180, 54, 61,246,238,244, 83,179, 71,157, 65, 45, 2,255, 0, 0, 0, 0,190, 79, 30, 28,
+ 62, 27,180, 54, 61,246,238,244,172, 77, 71,157, 65, 45, 2,255, 0, 0, 0, 0, 62,176, 89,157, 61,121,154,159, 61,232, 1, 67,
+111, 40,255,113, 63,117, 2,255, 0, 0, 0, 0,190,116,112, 84, 61,121,154,159, 61,232, 1, 67,144,216,255,113, 63,117, 2,255,
+ 0, 0, 0, 0, 62,161,107,237, 61,121,154,159, 62, 40, 64,139,100, 48,255,154, 79,167, 2,255, 0, 0, 0, 0,190, 86,148,244,
+ 61,121,154,159, 62, 40, 64,139,155,208,255,154, 79,167, 2,255, 0, 0, 0, 0, 62,139, 7,100, 61,121,154,159, 62, 81, 78, 48,
+126,117,254,181, 19,185, 0,255, 0, 0, 0, 0,190, 41,203,227, 61,121,154,159, 62, 81, 78, 48,129,139,254,181, 19,185, 0,255,
+ 0, 0, 0, 0, 62,140,229, 26, 61,121,154,159, 62, 88,197, 8,120,160,254,106, 42,198, 2,255, 0, 0, 0, 0,190, 45,135, 79,
+ 61,121,154,159, 62, 88,197, 8,135, 96,254,106, 42,198, 2,255, 0, 0, 0, 0, 62,133,110, 66, 61,214, 95,114, 62, 92,128,116,
+ 93,173, 74,126, 45, 93, 2,255, 0, 0, 0, 0,190, 30,153,158, 61,214, 95,114, 62, 92,128,116,162, 83, 74,126, 45, 93, 2,255,
+ 0, 0, 0, 0, 62, 94, 19,115, 61,251,177,170, 62,103,178,185, 11, 9,115, 31, 54,216, 2,255, 0, 0, 0, 0,189,227,161, 26,
+ 61,251,177,170, 62,103,178,185,244,247,115, 31, 54,216, 2,255, 0, 0, 0, 0, 62, 53, 5,206, 61,214, 95,114, 62,111, 41,145,
+181, 9, 80,184, 65, 43, 2,255, 0, 0, 0, 0,189,145,133,208, 61,214, 95,114, 62,111, 41,145, 74,247, 80,184, 65, 43, 2,255,
+ 0, 0, 0, 0, 62, 34, 92,178, 61,121,154,159, 62,111, 41,145,146,116,254, 57, 66, 43, 2,255, 0, 0, 0, 0,189, 88,103, 48,
+ 61,121,154,159, 62,111, 41,145,109,140,254, 57, 66, 43, 2,255, 0, 0, 0, 0, 62, 53, 5,206, 60,170,200, 22, 62,111, 41,145,
+182, 34,173,181, 64,115, 2,255, 0, 0, 0, 0,189,145,133,208, 60,170,200, 22, 62,111, 41,145, 73,222,173,181, 64,115, 2,255,
+ 0, 0, 0, 0, 62, 94, 19,115, 61,121,154,159, 62,114,228,253, 24, 74,255,139,125,171, 2,255, 0, 0, 0, 0,189,227,161, 26,
+ 61,121,154,159, 62,114,228,253,231,182,255,139,125,171, 2,255, 0, 0, 0, 0, 62, 94, 19,115, 59, 43,249,149, 62,103,178,185,
+ 10,218,140,140, 54, 45, 2,255, 0, 0, 0, 0,189,227,161, 26, 59, 43,249,149, 62,103,178,185,245, 38,140,140, 54, 45, 2,255,
+ 0, 0, 0, 0, 62,133,110, 66, 60,170,200, 22, 62, 92,128,116, 92,141,179,203, 44,210, 2,255, 0, 0, 0, 0,190, 30,153,158,
+ 60,170,200, 22, 62, 92,128,116,163,115,179,203, 44,210, 2,255, 0, 0, 0, 0, 61, 88,133,203, 62, 23,248,202, 62, 73,215, 88,
+ 0, 0,124, 43, 31, 17, 0,255, 0, 0, 0, 0, 61, 88,133,203, 61,229, 77, 34, 62,111, 41,145, 0, 0,249, 63,127,209, 0,255,
+ 0, 0, 0, 0, 61, 88,133,203,190,188,254,150, 62, 70, 27,236, 0, 0,251,204,127,237, 0,255, 0, 0, 0, 0, 61, 88,133,203,
+190, 78, 79,191, 62, 92,128,116, 0, 0,150, 33, 71,238, 2,255, 0, 0, 0, 0, 61, 88,133,203,190, 14,221,146, 62, 99,247, 77,
+ 0, 0,100, 28, 79,192, 0,255, 0, 0, 0, 0, 61, 88,133,203,190,211, 99, 30, 62, 62,165, 20, 0, 0,142,184, 59,147, 2,255,
+ 0, 0, 0, 0, 61, 88,133,203, 62, 12,198,133, 62, 6,169,190, 0, 0,103,143, 75, 57, 0,255, 0, 0, 0, 0, 61, 88,133,203,
+ 62, 91, 38, 99, 61,239,120, 28, 0, 0, 78,115,101, 34, 0,255, 0, 0, 0, 0, 61, 88,133,203, 62,187,243, 16,190,206,250,170,
+ 0, 0,110,190,191,212, 2,255, 0, 0, 0, 0, 61, 88,133,203, 62, 87,106,247,191, 11,224,178, 0, 0, 35,144,133, 12, 3,255,
+ 0, 0, 0, 0, 61, 88,133,203,188,157,165, 18,191, 9, 20, 33, 0, 0,214,194,134,213, 2,255, 0, 0, 0, 0, 61, 88,133,203,
+190,108, 43, 32,190,160, 83,227, 0, 0,134,154,215,113, 2,255, 0, 0, 0, 0, 62, 23, 42,109,190, 14,221,146, 61,232, 1, 67,
+113,144,198,122, 13, 79, 0,255, 0, 0, 0, 0,189, 43,158, 31,190, 14,221,146, 61,232, 1, 67,142,112,198,122, 13, 79, 0,255,
+ 0, 0, 0, 0, 62, 75,106, 87,190,131, 37,138, 61,239,120, 28,122,196, 31, 19, 18,152, 2,255, 0, 0, 0, 0,189,190, 78,225,
+190,131, 37,138, 61,239,120, 28,133, 60, 31, 19, 18,152, 2,255, 0, 0, 0, 0, 62, 94, 19,115,190,192,186, 2, 61,239,120, 28,
+125,167, 12,146, 20,226, 0,255, 0, 0, 0, 0,189,227,161, 26,190,192,186, 2, 61,239,120, 28,130, 89, 12,146, 20,226, 0,255,
+ 0, 0, 0, 0, 62,101,138, 75,190,239, 96,200, 61,202, 37,227,124,113,242,142, 26,196, 2,255, 0, 0, 0, 0,189,242,142,203,
+190,239, 96,200, 61,202, 37,227,131,143,242,142, 26,196, 2,255, 0, 0, 0, 0, 62, 82,225, 47,190,252,112,195, 61,194,175, 10,
+ 79,159,159, 44, 25,210, 2,255, 0, 0, 0, 0,189,205, 60,146,190,252,112,195, 61,194,175, 10,176, 97,159, 44, 25,210, 2,255,
+ 0, 0, 0, 0, 62, 11,248, 41,191, 1, 4,242, 61,224,138,107, 19,143,131, 13, 19,178, 2,255, 0, 0, 0, 0,188,253,170, 27,
+191, 1, 4,242, 61,224,138,107,236,113,131, 13, 19,178, 2,255, 0, 0, 0, 0, 61, 88,133,203,191, 2,226,168, 61,246,238,244,
+ 0, 0,130, 75, 24, 21, 2,255, 0, 0, 0, 0, 62,131,144,140,189,240,242, 18, 61,202, 37,227, 47,114,137,117, 8,232, 2,255,
+ 0, 0, 0, 0,190, 26,222, 50,189,240,242, 18, 61,202, 37,227,208,142,137,117, 8,232, 2,255, 0, 0, 0, 0, 62,178, 55, 83,
+189,143,233, 23, 61,209,156,187, 77, 25,154,198, 13,214, 2,255, 0, 0, 0, 0,190,120, 43,193,189,143,233, 23, 61,209,156,187,
+178,231,154,198, 13,214, 2,255, 0, 0, 0, 0, 62,224,222, 26, 60,140,236,182, 61,112, 21, 49,113,216,198,247, 12,255, 2,255,
+ 0, 0, 0, 0,190,170,188,167, 60,140,236,182, 61,112, 21, 49,142, 40,198,247, 12,255, 2,255, 0, 0, 0, 0, 62,232, 84,243,
+ 62, 23,248,202, 62, 2,238, 82,113,104, 51, 31, 30, 32, 2,255, 0, 0, 0, 0,190,178, 51,128, 62, 23,248,202, 62, 2,238, 82,
+142,152, 51, 31, 30, 32, 2,255, 0, 0, 0, 0, 62,196,224,112, 62, 50, 24,190, 62, 17,220, 2, 64,216,106,225, 27,121, 0,255,
+ 0, 0, 0, 0,190,142,190,253, 62, 50, 24,190, 62, 17,220, 2,191, 40,106,225, 27,121, 0,255, 0, 0, 0, 0, 62,144,160,134,
+ 62,106, 20, 20, 62, 47,183, 99, 75,137,101, 82, 20, 70, 0,255, 0, 0, 0, 0,190, 52,254, 39, 62,106, 20, 20, 62, 47,183, 99,
+180,119,101, 82, 20, 70, 0,255, 0, 0, 0, 0, 62, 79, 37,195, 62,154, 92, 67, 62, 70, 27,236, 38,241,119, 19, 26, 54, 2,255,
+ 0, 0, 0, 0,189,197,197,186, 62,154, 92, 67, 62, 70, 27,236,217, 15,119, 19, 26, 54, 2,255, 0, 0, 0, 0, 62, 0,197,229,
+ 62,145, 7,181, 62, 81, 78, 48,175, 21, 96, 54, 24, 12, 2,255, 0, 0, 0, 0,188,164, 23,249, 62,145, 7,181, 62, 81, 78, 48,
+ 80,235, 96, 54, 24, 12, 2,255, 0, 0, 0, 0, 61,167,249,168, 62, 53,212, 42, 62, 77,146,196,155,174, 76,128, 21,151, 0,255,
+ 0, 0, 0, 0, 60,194, 48,144, 62, 53,212, 42, 62, 77,146,196,100, 82, 76,128, 21,151, 0,255, 0, 0, 0, 0, 62, 4,129, 81,
+ 62, 16,129,241, 62, 88,197, 8, 25, 0,237, 4,124, 22, 0,255, 0, 0, 0, 0,188,193,243, 89, 62, 16,129,241, 62, 88,197, 8,
+231, 0,237, 4,124, 22, 0,255, 0, 0, 0, 0, 61,227,176,105, 61,184,132, 17, 62, 85, 9,156,255,160,232,126,125,209, 0,255,
+ 0, 0, 0, 0,187,178,169,214, 61,184,132, 17, 62, 85, 9,156, 0, 96,232,126,125,209, 0,255, 0, 0, 0, 0,189, 43,158, 31,
+188, 8, 37,223, 62, 73,215, 88, 38,104,203,122,110, 56, 0,255, 0, 0, 0, 0, 62,105, 69,184,189, 55, 82, 92, 62, 55, 46, 59,
+ 34,106,200,119,110, 16, 0,255, 0, 0, 0, 0,189,250, 5,163,189, 55, 82, 92, 62, 55, 46, 59,221,150,200,119,110, 16, 0,255,
+ 0, 0, 0, 0, 62,144,160,134,188,187,128,115, 62, 40, 64,139, 55,161,207, 60,104,115, 0,255, 0, 0, 0, 0,190, 52,254, 39,
+188,187,128,115, 62, 40, 64,139,200, 95,207, 60,104,115, 0,255, 0, 0, 0, 0, 62,176, 89,157, 61, 17, 26,205, 62, 29, 14, 71,
+ 58,181,226,123,109,214, 0,255, 0, 0, 0, 0,190,116,112, 84, 61, 17, 26,205, 62, 29, 14, 71,197, 75,226,123,109,214, 0,255,
+ 0, 0, 0, 0, 62,180, 21, 9, 61,177, 13, 57, 62, 29, 14, 71, 49,157,230, 61,115, 36, 0,255, 0, 0, 0, 0,190,123,231, 45,
+ 61,177, 13, 57, 62, 29, 14, 71,206, 99,230, 61,115, 36, 0,255, 0, 0, 0, 0, 62,170,192,123, 61,251,177,170, 62, 36,133, 31,
+ 39,206,234,175,119,196, 0,255, 0, 0, 0, 0,190,105, 62, 16, 61,251,177,170, 62, 36,133, 31,216, 50,234,175,119,196, 0,255,
+ 0, 0, 0, 0, 62,129,178,214, 62, 27,180, 54, 62, 62,165, 20, 24, 62,255, 85,125,173, 0,255, 0, 0, 0, 0,190, 23, 34,198,
+ 62, 27,180, 54, 62, 62,165, 20,231,194,255, 85,125,173, 0,255, 0, 0, 0, 0, 62, 45,142,246, 62, 42,161,230, 62, 81, 78, 48,
+ 31,251,247, 40,123,158, 0,255, 0, 0, 0, 0,189,130,152, 32, 62, 42,161,230, 62, 81, 78, 48,224, 5,247, 40,123,158, 0,255,
+ 0, 0, 0, 0, 61, 88,133,203,190,209,133,104, 62, 70, 27,236, 0, 0,210,148,119,170, 0,255, 0, 0, 0, 0, 61,212,194,185,
+190,198, 83, 36, 62, 70, 27,236, 19, 39,222, 65,121,248, 0,255, 0, 0, 0, 0, 58,240,196,191,190,198, 83, 36, 62, 70, 27,236,
+236,217,222, 65,121,248, 0,255, 0, 0, 0, 0, 61,220, 57,145,190,226, 80,207, 62, 58,233,167, 2,134,217,132,122, 12, 0,255,
+ 0, 0, 0, 0,186,236,241, 77,190,226, 80,207, 62, 58,233,167,253,122,217,132,122, 12, 0,255, 0, 0, 0, 0, 61,167,249,168,
+190,237,131, 19, 62, 51,114,207,252, 13,214,169,121, 18, 0,255, 0, 0, 0, 0, 60,194, 48,144,190,237,131, 19, 62, 51,114,207,
+ 3,243,214,169,121, 18, 0,255, 0, 0, 0, 0, 61, 88,133,203,190,239, 96,200, 62, 47,183, 99, 0, 0,219,150,122,180, 0,255,
+ 0, 0, 0, 0, 61, 88,133,203,190, 18,152,254, 62, 77,146,196, 0, 0, 97, 46, 83, 76, 0,255, 0, 0, 0, 0, 61, 88,133,203,
+189,240,242, 18, 62, 73,215, 88, 0, 0,104,197, 73,134, 0,255, 0, 0, 0, 0, 61,205, 75,225,189,248,104,235, 62, 73,215, 88,
+ 36, 52, 53, 2,110,187, 0,255, 0, 0, 0, 0, 59,179,158,179,189,248,104,235, 62, 73,215, 88,219,204, 53, 2,110,187, 0,255,
+ 0, 0, 0, 0, 61,227,176,105,190, 33,134,174, 62, 77,146,196, 95,187,212, 14, 72,182, 0,255, 0, 0, 0, 0,187,178,169,214,
+190, 33,134,174, 62, 77,146,196,160, 69,212, 14, 72,182, 0,255, 0, 0, 0, 0, 61,190, 94, 48,190, 63, 98, 15, 62, 73,215, 88,
+ 64,117,207,117, 99, 90, 0,255, 0, 0, 0, 0, 60, 81, 60,220,190, 63, 98, 15, 62, 73,215, 88,191,139,207,117, 99, 90, 0,255,
+ 0, 0, 0, 0, 62,116,119,252,189,151, 95,239, 62, 40, 64,139, 49,103,196,157,102, 13, 0,255, 0, 0, 0, 0,190, 8, 53, 22,
+189,151, 95,239, 62, 40, 64,139,206,153,196,157,102, 13, 0,255, 0, 0, 0, 0, 62,174,123,231,188,217, 91,211, 62, 17,220, 2,
+ 59,142,204,107,100,223, 2,255, 0, 0, 0, 0,190,112,180,232,188,217, 91,211, 62, 17,220, 2,196,114,204,107,100,223, 2,255,
+ 0, 0, 0, 0, 62,200,155,220, 61, 46,246, 45, 62, 6,169,190, 66,102,217, 11,102, 65, 0,255, 0, 0, 0, 0,190,146,122,105,
+ 61, 46,246, 45, 62, 6,169,190,189,154,217, 11,102, 65, 0,255, 0, 0, 0, 0, 62,204, 87, 72, 61,251,177,170, 62, 32,201,179,
+ 54, 87,228,142,112,151, 0,255, 0, 0, 0, 0,190,150, 53,213, 61,251,177,170, 62, 32,201,179,201,169,228,142,112,151, 0,255,
+ 0, 0, 0, 0, 62,191, 71, 78, 62, 16,129,241, 62, 66, 96,128, 42, 82,247, 97,120,125, 2,255, 0, 0, 0, 0,190,137, 37,219,
+ 62, 16,129,241, 62, 66, 96,128,213,174,247, 97,120,125, 2,255, 0, 0, 0, 0, 62,131,144,140, 62, 79,244, 31, 62, 99,247, 77,
+ 41,192,254,216,120,253, 0,255, 0, 0, 0, 0,190, 26,222, 50, 62, 79,244, 31, 62, 99,247, 77,214, 64,254,216,120,253, 0,255,
+ 0, 0, 0, 0, 62, 75,106, 87, 62,124,189, 48, 62,118,160,105, 28,217, 7, 53,124,126, 0,255, 0, 0, 0, 0,189,190, 78,225,
+ 62,124,189, 48, 62,118,160,105,227, 39, 7, 53,124,126, 0,255, 0, 0, 0, 0, 62, 23, 42,109, 62,113,138,236, 62,126, 23, 65,
+255,125, 5, 44,127,227, 0,255, 0, 0, 0, 0,189, 43,158, 31, 62,113,138,236, 62,126, 23, 65, 0,131, 5, 44,127,227, 0,255,
+ 0, 0, 0, 0, 61,205, 75,225, 62, 23,248,202, 62,122, 91,213,238,130, 2, 89,126,197, 0,255, 0, 0, 0, 0, 59,179,158,179,
+ 62, 23,248,202, 62,122, 91,213, 17,126, 2, 89,126,197, 0,255, 0, 0, 0, 0, 61,227,176,105,189,203,159,217, 62,107,110, 37,
+ 23,115,230, 27,123, 34, 0,255, 0, 0, 0, 0,187,178,169,214,189,203,159,217, 62,107,110, 37,232,141,230, 27,123, 34, 0,255,
+ 0, 0, 0, 0, 62, 26,229,218,190,133, 3, 64, 62, 58,233,167, 74,212, 14, 28,102,225, 2,255, 0, 0, 0, 0,189, 58,139,207,
+190,133, 3, 64, 62, 58,233,167,181, 44, 14, 28,102,225, 2,255, 0, 0, 0, 0, 62, 45,142,246,190,194,151,184, 62, 47,183, 99,
+ 72,235,252, 17,105, 31, 2,255, 0, 0, 0, 0,189,130,152, 32,190,194,151,184, 62, 47,183, 99,183, 21,252, 17,105, 31, 2,255,
+ 0, 0, 0, 0, 62, 53, 5,206,190,222,149, 99, 62, 36,133, 31, 66,179,225,197,104,249, 2,255, 0, 0, 0, 0,189,145,133,208,
+190,222,149, 99, 62, 36,133, 31,189, 77,225,197,104,249, 2,255, 0, 0, 0, 0, 62, 38, 24, 30,190,244,249,234, 62, 21,151,111,
+ 44, 62,183, 4, 95, 98, 2,255, 0, 0, 0, 0,189,103, 84,224,190,244,249,234, 62, 21,151,111,211,194,183, 4, 95, 98, 2,255,
+ 0, 0, 0, 0, 62, 4,129, 81,190,248,181, 86, 62, 21,151,111, 19,155,158, 52, 80, 54, 2,255, 0, 0, 0, 0,188,193,243, 89,
+190,248,181, 86, 62, 21,151,111,236,101,158, 52, 80, 54, 2,255, 0, 0, 0, 0, 61, 88,133,203,190,252,112,195, 62, 25, 82,219,
+ 0, 0,154,201, 78, 88, 2,255, 0, 0, 0, 0, 61, 88,133,203,188,247, 55, 52, 62, 66, 96,128, 0, 0,252, 2,127,239, 0,255,
+ 0, 0, 0, 0, 61, 88,133,203, 61, 61,227,222, 62, 85, 9,156, 0, 0,227,112,124,196, 0,255, 0, 0, 0, 0, 62, 82,225, 47,
+ 62, 46, 93, 82, 62, 73,215, 88, 21, 58,254,234,126, 56, 0,255, 0, 0, 0, 0,189,205, 60,146, 62, 46, 93, 82, 62, 73,215, 88,
+234,198,254,234,126, 56, 0,255, 0, 0, 0, 0, 62, 4,129, 81, 60, 94, 34,170, 62, 77,146,196,214, 37,232,110,118,163, 0,255,
+ 0, 0, 0, 0,188,193,243, 89, 60, 94, 34,170, 62, 77,146,196, 41,219,232,110,118,163, 0,255, 0, 0, 0, 0, 61,235, 39, 65,
+ 61, 61,227,222, 62, 81, 78, 48,232,150,230,127,123, 57, 0,255, 0, 0, 0, 0,188, 21, 11,173, 61, 61,227,222, 62, 81, 78, 48,
+ 23,106,230,127,123, 57, 0,255, 0, 0, 0, 0, 61,220, 57,145,190,190,220, 76, 62, 70, 27,236, 20,117,248,197,126, 36, 0,255,
+ 0, 0, 0, 0,186,236,241, 77,190,190,220, 76, 62, 70, 27,236,235,139,248,197,126, 36, 0,255, 0, 0, 0, 0, 61,182,231, 88,
+190,133, 3, 64, 62, 77,146,196, 19, 43, 0,128,126,141, 2,255, 0, 0, 0, 0, 60,134,121,207,190,133, 3, 64, 62, 77,146,196,
+236,213, 0,128,126,141, 2,255, 0, 0, 0, 0, 61, 88,133,203,190,133, 3, 64, 62, 77,146,196, 0, 0,255,122,127,254, 0,255,
+ 0, 0, 0, 0, 61, 88,133,203,190, 82, 11, 43, 62, 73,215, 88, 0, 0,184,121,106, 36, 0,255, 0, 0, 0, 0, 61,197,213, 8,
+190, 55,235, 55, 62, 92,128,116, 66,167,160,139, 53, 45, 2,255, 0, 0, 0, 0, 60, 21,134, 27,190, 55,235, 55, 62, 92,128,116,
+189, 89,160,139, 53, 45, 2,255, 0, 0, 0, 0, 61,235, 39, 65,190, 33,134,174, 62, 99,247, 77,118,133,224,215, 36,239, 2,255,
+ 0, 0, 0, 0,188, 21, 11,173,190, 33,134,174, 62, 99,247, 77,137,123,224,215, 36,239, 2,255, 0, 0, 0, 0, 61,212,194,185,
+189,233,123, 57, 62, 92,128,116, 81,167, 95,141, 24, 49, 2,255, 0, 0, 0, 0, 58,240,196,191,189,233,123, 57, 62, 92,128,116,
+174, 89, 95,141, 24, 49, 2,255, 0, 0, 0, 0, 61,145,149, 31,189,226, 4, 97, 62, 92,128,116,200,189,108,160, 39, 26, 2,255,
+ 0, 0, 0, 0, 61, 13,225, 89,189,226, 4, 97, 62, 92,128,116, 55, 67,108,160, 39, 26, 2,255, 0, 0, 0, 0, 61, 88,133,203,
+190, 22, 84,106, 62,114,228,253, 0, 0, 23, 42,125,225, 0,255, 0, 0, 0, 0, 61,153, 11,247,189,248,104,235, 62,107,110, 37,
+231,186, 78, 89, 98, 66, 2,255, 0, 0, 0, 0, 60,253,231, 82,189,248,104,235, 62,107,110, 37, 24, 70, 78, 89, 98, 66, 2,255,
+ 0, 0, 0, 0, 61,197,213, 8,189,255,223,195, 62,107,110, 37, 43, 88, 62,134,102,237, 2,255, 0, 0, 0, 0, 60, 21,134, 27,
+189,255,223,195, 62,107,110, 37,212,168, 62,134,102,237, 2,255, 0, 0, 0, 0, 61,212,194,185,190, 33,134,174, 62,114,228,253,
+ 46,247,233, 89,116,228, 2,255, 0, 0, 0, 0, 58,240,196,191,190, 33,134,174, 62,114,228,253,209, 9,233, 89,116,228, 2,255,
+ 0, 0, 0, 0, 61,182,231, 88,190, 44,184,243, 62,103,178,185, 31, 46,181,198, 99,128, 2,255, 0, 0, 0, 0, 60,134,121,207,
+190, 44,184,243, 62,103,178,185,224,210,181,198, 99,128, 2,255, 0, 0, 0, 0, 61, 88,133,203,190, 63, 98, 15, 62,103,178,185,
+ 0, 0,191,185,110,175, 2,255, 0, 0, 0, 0, 62, 49, 74, 98,190, 74,148, 83, 61,224,138,107,120, 23, 41, 34, 16, 99, 0,255,
+ 0, 0, 0, 0,189,138, 14,248,190, 74,148, 83, 61,224,138,107,135,233, 41, 34, 16, 99, 0,255, 0, 0, 0, 0, 62, 4,129, 81,
+190, 40,253,134, 62, 58,233,167, 80,251,250, 26, 98,241, 0,255, 0, 0, 0, 0,188,193,243, 89,190, 40,253,134, 62, 58,233,167,
+175, 5,250, 26, 98,241, 0,255, 0, 0, 0, 0, 62, 11,248, 41,190, 74,148, 83, 62, 58,233,167, 83,215, 16,153, 95, 71, 0,255,
+ 0, 0, 0, 0,188,253,170, 27,190, 74,148, 83, 62, 58,233,167,172, 41, 16,153, 95, 71, 0,255, 0, 0, 0, 0, 62, 38, 24, 30,
+190, 44,184,243, 61,224,138,107,122, 24, 35, 67, 15, 64, 0,255, 0, 0, 0, 0,189,103, 84,224,190, 44,184,243, 61,224,138,107,
+133,232, 35, 67, 15, 64, 0,255, 0, 0, 0, 0, 61, 88,133,203,190,235,165, 93, 62, 47,183, 99, 0, 0, 86,139, 94, 77, 0,255,
+ 0, 0, 0, 0, 61,153, 11,247,190,233,199,167, 62, 47,183, 99,206,144, 70,200, 94,125, 0,255, 0, 0, 0, 0, 60,253,231, 82,
+190,233,199,167, 62, 47,183, 99, 49,112, 70,200, 94,125, 0,255, 0, 0, 0, 0, 61,197,213, 8,190,222,149, 99, 62, 58,233,167,
+164,253, 17,109, 88, 75, 0,255, 0, 0, 0, 0, 60, 21,134, 27,190,222,149, 99, 62, 58,233,167, 91, 3, 17,109, 88, 75, 0,255,
+ 0, 0, 0, 0, 61,197,213, 8,190,203,236, 70, 62, 66, 96,128,225,141,168, 87, 88, 39, 0,255, 0, 0, 0, 0, 60, 21,134, 27,
+190,203,236, 70, 62, 66, 96,128, 30,115,168, 87, 88, 39, 0,255, 0, 0, 0, 0, 61, 88,133,203,190,213, 64,212, 62, 32,201,179,
+ 0, 0,159, 20, 83,153, 0,255, 0, 0, 0, 0, 61,197,213, 8,190,205,201,252, 62, 36,133, 31,230, 5,177,250, 98, 20, 0,255,
+ 0, 0, 0, 0, 60, 21,134, 27,190,205,201,252, 62, 36,133, 31, 25,251,177,250, 98, 20, 0,255, 0, 0, 0, 0, 61,197,213, 8,
+190,220,183,173, 62, 25, 82,219,152, 18, 24, 8, 70,188, 0,255, 0, 0, 0, 0, 60, 21,134, 27,190,220,183,173, 62, 25, 82,219,
+103,238, 24, 8, 70,188, 0,255, 0, 0, 0, 0, 61,153, 11,247,190,230, 12, 59, 62, 21,151,111,222, 26, 49,242,112,221, 0,255,
+ 0, 0, 0, 0, 60,253,231, 82,190,230, 12, 59, 62, 21,151,111, 33,230, 49,242,112,221, 0,255, 0, 0, 0, 0, 61, 88,133,203,
+190,231,233,241, 62, 21,151,111, 0, 0, 60, 18,113, 5, 0,255, 0, 0, 0, 0, 62, 8, 60,189, 61, 76,209,142, 62, 92,128,116,
+ 30, 4,244, 93,123,225, 0,255, 0, 0, 0, 0,188,223,206,186, 61, 76,209,142, 62, 92,128,116,225,252,244, 93,123,225, 0,255,
+ 0, 0, 0, 0, 62, 15,179,149, 60,170,200, 22, 62, 88,197, 8, 9, 71,251, 34,127,144, 0,255, 0, 0, 0, 0,189, 13,194,190,
+ 60,170,200, 22, 62, 88,197, 8,246,185,251, 34,127,144, 0,255, 0, 0, 0, 0, 62, 86,156,155, 62, 23,248,202, 62, 81, 78, 48,
+ 17, 81, 2, 74,126,204, 0,255, 0, 0, 0, 0,189,212,179,106, 62, 23,248,202, 62, 81, 78, 48,238,175, 2, 74,126,204, 0,255,
+ 0, 0, 0, 0, 62, 56,193, 58, 62, 20, 61, 94, 62, 88,197, 8, 25,218,253,177,125, 86, 2,255, 0, 0, 0, 0,189,152,252,168,
+ 62, 20, 61, 94, 62, 88,197, 8,230, 38,253,177,125, 86, 2,255, 0, 0, 0, 0, 62,127,170, 64, 62, 9, 11, 25, 62, 88,197, 8,
+ 21,182,240,210,125, 57, 2,255, 0, 0, 0, 0,190, 19,103, 90, 62, 9, 11, 25, 62, 88,197, 8,234, 74,240,210,125, 57, 2,255,
+ 0, 0, 0, 0, 62,161,107,237, 61,229, 77, 34, 62, 51,114,207, 28,143,237,249,123,117, 0,255, 0, 0, 0, 0,190, 86,148,244,
+ 61,229, 77, 34, 62, 51,114,207,227,113,237,249,123,117, 0,255, 0, 0, 0, 0, 62,167, 5, 15, 61,169,150, 97, 62, 47,183, 99,
+ 15,209,246,217,126,175, 0,255, 0, 0, 0, 0,190, 97,199, 56, 61,169,150, 97, 62, 47,183, 99,240, 47,246,217,126,175, 0,255,
+ 0, 0, 0, 0, 62,165, 39, 89, 61, 32, 8,125, 62, 43,251,247, 24,177,253,190,125,146, 0,255, 0, 0, 0, 0,190, 94, 11,204,
+ 61, 32, 8,125, 62, 43,251,247,231, 79,253,190,125,146, 0,255, 0, 0, 0, 0, 62,140,229, 26,187,152,222, 60, 62, 62,165, 20,
+ 33, 20, 2, 75,123,160, 0,255, 0, 0, 0, 0,190, 45,135, 79,187,152,222, 60, 62, 62,165, 20,222,236, 2, 75,123,160, 0,255,
+ 0, 0, 0, 0, 62,105, 69,184,188,187,128,115, 62, 73,215, 88, 26, 85,248,238,125, 14, 0,255, 0, 0, 0, 0,189,250, 5,163,
+188,187,128,115, 62, 73,215, 88,229,171,248,238,125, 14, 0,255, 0, 0, 0, 0, 62, 34, 92,178,186,133,194,226, 62, 92,128,116,
+ 7, 8,250,142,127,175, 0,255, 0, 0, 0, 0,189, 88,103, 48,186,133,194,226, 62, 92,128,116,248,248,250,142,127,175, 0,255,
+ 0, 0, 0, 0, 62, 11,248, 41, 61,177, 13, 57, 62, 92,128,116, 34,169,240, 2,122, 43, 0,255, 0, 0, 0, 0,188,253,170, 27,
+ 61,177, 13, 57, 62, 92,128,116,221, 87,240, 2,122, 43, 0,255, 0, 0, 0, 0, 62, 26,229,218, 61,251,177,170, 62, 92,128,116,
+ 27,126,239,108,123,231, 0,255, 0, 0, 0, 0,189, 58,139,207, 61,251,177,170, 62, 92,128,116,228,130,239,108,123,231, 0,255,
+ 0, 0, 0, 0, 62, 38, 24, 30, 61,236,195,250, 62, 81, 78, 48, 64,226,207, 13, 98,224, 0,255, 0, 0, 0, 0,189,103, 84,224,
+ 61,236,195,250, 62, 81, 78, 48,191, 30,207, 13, 98,224, 0,255, 0, 0, 0, 0, 62, 19,111, 1, 61,177, 13, 57, 62, 81, 78, 48,
+ 96, 29,229,169, 80, 81, 0,255, 0, 0, 0, 0,189, 28,176,110, 61,177, 13, 57, 62, 81, 78, 48,159,227,229,169, 80, 81, 0,255,
+ 0, 0, 0, 0, 62, 41,211,138, 59,205,106, 77, 62, 81, 78, 48, 55, 36, 71,122, 90,188, 0,255, 0, 0, 0, 0,189,118, 66,143,
+ 59,205,106, 77, 62, 81, 78, 48,200,220, 71,122, 90,188, 0,255, 0, 0, 0, 0, 62,105, 69,184,188, 67,220,161, 62, 66, 96,128,
+ 21, 76, 78, 90, 98,241, 0,255, 0, 0, 0, 0,189,250, 5,163,188, 67,220,161, 62, 66, 96,128,234,180, 78, 90, 98,241, 0,255,
+ 0, 0, 0, 0, 62,137, 41,174, 59, 43,249,149, 62, 55, 46, 59,245, 85, 69, 69,107, 25, 0,255, 0, 0, 0, 0,190, 38, 16,118,
+ 59, 43,249,149, 62, 55, 46, 59, 10,171, 69, 69,107, 25, 0,255, 0, 0, 0, 0, 62,157,176,129, 61, 61,227,222, 62, 40, 64,139,
+223,232, 29,211,120, 67, 0,255, 0, 0, 0, 0,190, 79, 30, 28, 61, 61,227,222, 62, 40, 64,139, 32, 24, 29,211,120, 67, 0,255,
+ 0, 0, 0, 0, 62,159,142, 55, 61,162, 31,137, 62, 40, 64,139,210,148,238,123,118, 95, 0,255, 0, 0, 0, 0,190, 82,217,136,
+ 61,162, 31,137, 62, 40, 64,139, 45,108,238,123,118, 95, 0,255, 0, 0, 0, 0, 62,153,245, 21, 61,214, 95,114, 62, 43,251,247,
+229,216,179,108, 99, 43, 0,255, 0, 0, 0, 0,190, 71,167, 67, 61,214, 95,114, 62, 43,251,247, 26, 40,179,108, 99, 43, 0,255,
+ 0, 0, 0, 0, 62,123,238,212, 62, 5, 79,173, 62, 77,146,196,237,202,158,179, 81, 35, 2,255, 0, 0, 0, 0,190, 15,171,238,
+ 62, 5, 79,173, 62, 77,146,196, 18, 54,158,179, 81, 35, 2,255, 0, 0, 0, 0, 62, 60,124,166, 62, 9, 11, 25, 62, 85, 9,156,
+ 39, 24,212,118,113,214, 2,255, 0, 0, 0, 0,189,160,115,129, 62, 9, 11, 25, 62, 85, 9,156,216,232,212,118,113,214, 2,255,
+ 0, 0, 0, 0, 62, 86,156,155, 62, 12,198,133, 62, 77,146,196, 1,213,193,189,111,208, 0,255, 0, 0, 0, 0,189,212,179,106,
+ 62, 12,198,133, 62, 77,146,196,254, 43,193,189,111,208, 0,255, 0, 0, 0, 0, 62, 23, 42,109, 60,230,126,216, 62, 77,146,196,
+ 84,226, 42,192, 85,187, 0,255, 0, 0, 0, 0,189, 43,158, 31, 60,230,126,216, 62, 77,146,196,171, 30, 42,192, 85,187, 0,255,
+ 0, 0, 0, 0, 62, 19,111, 1, 61, 91,191, 63, 62, 77,146,196,102,235, 2,196, 76, 11, 0,255, 0, 0, 0, 0,189, 28,176,110,
+ 61, 91,191, 63, 62, 77,146,196,153, 21, 2,196, 76, 11, 0,255, 0, 0, 0, 0, 61,212,194,185, 62, 38,230,122, 62, 10,101, 42,
+182,183,104,118,246, 5, 0,255, 0, 0, 0, 0, 58,240,196,191, 62, 38,230,122, 62, 10,101, 42, 73, 73,104,118,246, 5, 0,255,
+ 0, 0, 0, 0, 62, 19,111, 1, 62,131,247,186, 62, 14, 32,150,192,208, 66,221,167, 3, 2,255, 0, 0, 0, 0,189, 28,176,110,
+ 62,131,247,186, 62, 14, 32,150, 63, 48, 66,221,167, 3, 2,255, 0, 0, 0, 0, 62, 86,156,155, 62,137,144,220, 62, 2,238, 82,
+ 9, 59, 90, 89,165,208, 2,255, 0, 0, 0, 0,189,212,179,106, 62,137,144,220, 62, 2,238, 82,246,197, 90, 89,165,208, 2,255,
+ 0, 0, 0, 0, 62,142,194,208, 62, 83,175,139, 61,224,138,107, 37,165,114,104,212,176, 0,255, 0, 0, 0, 0,190, 49, 66,187,
+ 62, 83,175,139, 61,224,138,107,218, 91,114,104,212,176, 0,255, 0, 0, 0, 0, 62,189,105,152, 62, 35, 43, 14, 61,164,211,170,
+ 45, 67,116, 40,227, 1, 0,255, 0, 0, 0, 0,190,135, 72, 37, 62, 35, 43, 14, 61,164,211,170,210,189,116, 40,227, 1, 0,255,
+ 0, 0, 0, 0, 62,217,103, 66, 62, 12,198,133, 61,134,248, 73, 94,100, 79,237,223, 18, 0,255, 0, 0, 0, 0,190,163, 69,207,
+ 62, 12,198,133, 61,134,248, 73,161,156, 79,237,223, 18, 0,255, 0, 0, 0, 0, 62,211,206, 32, 60,200,163,119, 60,211,115,252,
+120,247,221,255,231,165, 0,255, 0, 0, 0, 0,190,157,172,173, 60,200,163,119, 60,211,115,252,135, 9,221,255,231,165, 0,255,
+ 0, 0, 0, 0, 62,170,192,123,189, 85, 45,188, 61, 52, 94,112, 76,155,154,106,242, 19, 0,255, 0, 0, 0, 0,190,105, 62, 16,
+189, 85, 45,188, 61, 52, 94,112,179,101,154,106,242, 19, 0,255, 0, 0, 0, 0, 62,131,144,140,189,196, 41, 0, 61,142,111, 33,
+ 56,204,142, 26, 13,138, 0,255, 0, 0, 0, 0,190, 26,222, 50,189,196, 41, 0, 61,142,111, 33,199, 52,142, 26, 13,138, 0,255,
+ 0, 0, 0, 0, 61, 88,133,203, 62,187,243, 16,188,105,242, 89, 0, 0,106,155, 70,214, 2,255, 0, 0, 0, 0, 61, 88,133,203,
+ 62,208,121,226,190, 62, 7,254, 0, 0,127,243, 3, 82, 2,255, 0, 0, 0, 0, 61, 88,133,203,190, 18,152,254,190,236,214, 11,
+ 0, 0,164, 54,166,204, 3,255, 0, 0, 0, 0, 61, 88,133,203,190,136,190,173,189,124,142,139, 0, 0,129,179,235, 65, 0,255,
+ 0, 0, 0, 0, 61, 88,133,203,191, 1,243,205, 61,134,248, 73, 0, 0,151,182,181,204, 2,255, 0, 0, 0, 0, 61, 88,133,203,
+190,218,217,247, 60, 56, 12,241, 0, 0,221,231,132,162, 2,255, 0, 0, 0, 0, 61, 88,133,203,190,162,222,161, 57,157, 21,147,
+ 0, 0,212, 16,135,201, 0,255, 0, 0, 0, 0, 61, 88,133,203,190,142, 87,207,188,146,212,141, 0, 0,147,245,187, 97, 0,255,
+ 0, 0, 0, 0, 62,230,119, 61, 61,106,172,239,189,253, 43,161,125,164,235,181, 13,156, 0,255, 0, 0, 0, 0,190,176, 85,202,
+ 61,106,172,239,189,253, 43,161,130, 92,235,181, 13,156, 0,255, 0, 0, 0, 0, 62,232, 84,243, 61,199,113,194,190, 47, 26, 78,
+126,174,238, 23,252, 66, 0,255, 0, 0, 0, 0,190,178, 51,128, 61,199,113,194,190, 47, 26, 78,129, 82,238, 23,252, 66, 0,255,
+ 0, 0, 0, 0, 62,211,206, 32, 61,147, 49,216,190,180,218,181, 81, 70, 13,148,158, 15, 1,255, 0, 0, 0, 0,190,157,172,173,
+ 61,147, 49,216,190,180,218,181,174,186, 13,148,158, 15, 1,255, 0, 0, 0, 0, 62,137, 41,174, 62, 27,180, 54,190,244, 76,226,
+ 58,123, 21,228,144, 70, 3,255, 0, 0, 0, 0,190, 38, 16,118, 62, 27,180, 54,190,244, 76,226,197,133, 21,228,144, 70, 3,255,
+ 0, 0, 0, 0, 62,202,121,146,189,151, 95,239,189,238, 61,240, 89, 76,164,139, 6,161, 2,255, 0, 0, 0, 0,190,148, 88, 31,
+189,151, 95,239,189,238, 61,240,166,180,164,139, 6,161, 2,255, 0, 0, 0, 0, 62,168,226,197,189,226, 4, 97,190,103, 21,163,
+ 38, 93,134, 34, 7,182, 0,255, 0, 0, 0, 0,190,101,130,164,189,226, 4, 97,190,103, 21,163,217,163,134, 34, 7,182, 0,255,
+ 0, 0, 0, 0, 62,180, 21, 9,189,100, 27,109,190,178,252,255, 43,106,170,219,170,222, 1,255, 0, 0, 0, 0,190,123,231, 45,
+189,100, 27,109,190,178,252,255,212,150,170,219,170,222, 1,255, 0, 0, 0, 0, 62, 86,156,155,188,217, 91,211,190,234,248, 85,
+ 55,168,213,109,148,229, 2,255, 0, 0, 0, 0,189,212,179,106,188,217, 91,211,190,234,248, 85,200, 88,213,109,148,229, 2,255,
+ 0, 0, 0, 0, 62, 38, 24, 30,190, 93, 61,112, 61, 37,112,191,120,197,255, 36,213,158, 0,255, 0, 0, 0, 0,189,103, 84,224,
+190, 93, 61,112, 61, 37,112,191,135, 59,255, 36,213,158, 0,255, 0, 0, 0, 0, 62, 11,248, 41,190,123, 24,209,188,236,102,176,
+ 84,188,181, 20,196, 24, 0,255, 0, 0, 0, 0,188,253,170, 27,190,123, 24,209,188,236,102,176,171, 68,181, 20,196, 24, 0,255,
+ 0, 0, 0, 0, 62, 64, 56, 19,190,196,117,110, 60,241, 79, 92, 79,131,254, 86,155,183, 2,255, 0, 0, 0, 0,189,167,234, 89,
+190,196,117,110, 60,241, 79, 92,176,125,254, 86,155,183, 2,255, 0, 0, 0, 0, 62, 45,142,246,190,146, 19, 59, 61, 7,149, 95,
+ 99, 5, 1, 8,174,231, 0,255, 0, 0, 0, 0,189,130,152, 32,190,146, 19, 59, 61, 7,149, 95,156,251, 1, 8,174,231, 0,255,
+ 0, 0, 0, 0, 62, 82,225, 47,190,244,249,234, 61, 22,131, 15, 62, 65,185,227,168,224, 2,255, 0, 0, 0, 0,189,205, 60,146,
+190,244,249,234, 61, 22,131, 15,193,191,185,227,168,224, 2,255, 0, 0, 0, 0, 61,242,158, 25,190,207,167,178, 60,181,152,155,
+ 16,133,232,208,131, 55, 0,255, 0, 0, 0, 0,188, 80,194,110,190,207,167,178, 60,181,152,155,239,123,232,208,131, 55, 0,255,
+ 0, 0, 0, 0, 61,227,176,105,190,155,103,201, 60,151,189, 58, 48, 7,224,163,141,149, 0,255, 0, 0, 0, 0,187,178,169,214,
+190,155,103,201, 60,151,189, 58,207,249,224,163,141,149, 0,255, 0, 0, 0, 0, 62, 4,129, 81,190,252,112,195, 61, 97, 39,129,
+ 12, 68,158,218,173,147, 0,255, 0, 0, 0, 0,188,193,243, 89,190,252,112,195, 61, 97, 39,129,243,188,158,218,173,147, 0,255,
+ 0, 0, 0, 0, 62, 30,161, 70,190, 59,166,163, 61, 82, 57,208,124,195,227,106,255,203, 0,255, 0, 0, 0, 0,189, 73,121,127,
+190, 59,166,163, 61, 82, 57,208,131, 61,227,106,255,203, 0,255, 0, 0, 0, 0, 62, 26,229,218,190, 33,134,174, 61,142,111, 33,
+120, 29,231,105, 36,193, 0,255, 0, 0, 0, 0,189, 58,139,207,190, 33,134,174, 61,142,111, 33,135,227,231,105, 36,193, 0,255,
+ 0, 0, 0, 0, 62, 23, 42,109,190, 7,102,186, 61,172, 74,130,101,160,182,164, 25,240, 0,255, 0, 0, 0, 0,189, 43,158, 31,
+190, 7,102,186, 61,172, 74,130,154, 96,182,164, 25,240, 0,255, 0, 0, 0, 0, 62, 26,229,218,190,111,230,140,189,148,171,206,
+ 84,120,159,221,253,198, 0,255, 0, 0, 0, 0,189, 58,139,207,190,111,230,140,189,148,171,206,171,136,159,221,253,198, 0,255,
+ 0, 0, 0, 0, 62, 67,243,127,190, 74,148, 83,190,139,205, 16, 67,255,151, 42,228, 73, 2,255, 0, 0, 0, 0,189,175, 97, 49,
+190, 74,148, 83,190,139,205, 16,188, 1,151, 42,228, 73, 2,255, 0, 0, 0, 0, 62, 90, 88, 7,189,248,104,235,190,205, 28,244,
+ 63,201,176, 25,179, 0, 3,255, 0, 0, 0, 0,189,220, 42, 66,189,248,104,235,190,205, 28,244,192, 55,176, 25,179, 0, 3,255,
+ 0, 0, 0, 0, 62,135, 75,248, 62,180,124, 55,190,167,202,187, 56, 34, 95,160,192, 17, 2,255, 0, 0, 0, 0,190, 34, 85, 10,
+ 62,180,124, 55,190,167,202,187,199,222, 95,160,192, 17, 2,255, 0, 0, 0, 0, 62,135, 75,248, 62,195,105,232,190, 58, 76,146,
+ 55, 54,115,120, 0,239, 2,255, 0, 0, 0, 0,190, 34, 85, 10, 62,195,105,232,190, 58, 76,146,200,202,115,120, 0,239, 2,255,
+ 0, 0, 0, 0, 62,135, 75,248, 62,176,192,203,189, 34,252,105, 63,239, 92,164, 60,238, 2,255, 0, 0, 0, 0,190, 34, 85, 10,
+ 62,176,192,203,189, 34,252,105,192, 17, 92,164, 60,238, 2,255, 0, 0, 0, 0, 62,137, 41,174, 62, 68,193,219, 61, 82, 57,208,
+ 49,123,102,255, 57,170, 0,255, 0, 0, 0, 0,190, 38, 16,118, 62, 68,193,219, 61, 82, 57,208,206,133,102,255, 57,170, 0,255,
+ 0, 0, 0, 0, 62,200,155,220, 62, 12,198,133, 59,248,172, 95, 98,142, 73,198, 35, 6, 0,255, 0, 0, 0, 0,190,146,122,105,
+ 62, 12,198,133, 59,248,172, 95,157,114, 73,198, 35, 6, 0,255, 0, 0, 0, 0, 62,178, 55, 83, 62, 35, 43, 14,188,146,212,141,
+ 61,129,106,254, 33,241, 0,255, 0, 0, 0, 0,190,120, 43,193, 62, 35, 43, 14,188,146,212,141,194,127,106,254, 33,241, 0,255,
+ 0, 0, 0, 0, 62,180, 21, 9, 62,141, 76, 72,189,253, 43,161, 76,234, 87,151, 52,221, 0,255, 0, 0, 0, 0,190,123,231, 45,
+ 62,141, 76, 72,189,253, 43,161,179, 22, 87,151, 52,221, 0,255, 0, 0, 0, 0, 62,217,103, 66, 62, 87,106,247,189,185,254, 7,
+101,187, 66, 28, 40,199, 2,255, 0, 0, 0, 0,190,163, 69,207, 62, 87,106,247,189,185,254, 7,154, 69, 66, 28, 40,199, 2,255,
+ 0, 0, 0, 0, 62,217,103, 66, 62,113,138,236,190, 80,177, 26,113,183, 58, 68,248,119, 2,255, 0, 0, 0, 0,190,163, 69,207,
+ 62,113,138,236,190, 80,177, 26,142, 73, 58, 68,248,119, 2,255, 0, 0, 0, 0, 62,180, 21, 9, 62,152,126,141,190,118, 3, 83,
+ 86,235, 93,238,253,205, 0,255, 0, 0, 0, 0,190,123,231, 45, 62,152,126,141,190,118, 3, 83,169, 21, 93,238,253,205, 0,255,
+ 0, 0, 0, 0, 62,180, 21, 9, 62,135,179, 38,190,182,184,107, 85,232, 70,154,192,157, 2,255, 0, 0, 0, 0,190,123,231, 45,
+ 62,135,179, 38,190,182,184,107,170, 24, 70,154,192,157, 2,255, 0, 0, 0, 0, 62,217,103, 66, 62, 76, 56,179,190,162, 49,153,
+110,166, 42,177,207,222, 2,255, 0, 0, 0, 0,190,163, 69,207, 62, 76, 56,179,190,162, 49,153,145, 90, 42,177,207,222, 2,255,
+ 0, 0, 0, 0, 62,174,123,231, 61,206,232,154,190,216, 79, 56, 75, 58, 1, 57,152,116, 3,255, 0, 0, 0, 0,190,112,180,232,
+ 61,206,232,154,190,216, 79, 56,180,198, 1, 57,152,116, 3,255, 0, 0, 0, 0, 62,142,194,208,189, 40,100,171,190,206,250,170,
+ 70, 73,187,147,173,200, 1,255, 0, 0, 0, 0,190, 49, 66,187,189, 40,100,171,190,206,250,170,185,183,187,147,173,200, 0,255,
+ 0, 0, 0, 0, 62,223, 0,100, 61,206,232,154,190,121,190,191,114,194, 41, 80, 38,207, 0,255, 0, 0, 0, 0,190,168,222,241,
+ 61,206,232,154,190,121,190,191,141, 62, 41, 80, 38,207, 0,255, 0, 0, 0, 0, 62,120, 51,104,190, 7,102,186,189,163,153,127,
+ 74,232,154,153, 22, 28, 0,255, 0, 0, 0, 0,190, 11,240,130,190, 7,102,186,189,163,153,127,181, 24,154,153, 22, 28, 0,255,
+ 0, 0, 0, 0, 62,129,178,214,190, 18,152,254,190,125,122, 44, 71, 89,151,115,237, 1, 0,255, 0, 0, 0, 0,190, 23, 34,198,
+190, 18,152,254,190,125,122, 44,184,167,151,115,237, 1, 0,255, 0, 0, 0, 0, 62,239,203,202, 62, 12,198,133,190,132, 86, 56,
+220, 72, 93,207, 79,106, 2,255, 0, 0, 0, 0,190,185,170, 88, 62, 12,198,133,190,132, 86, 56, 35,184, 93,207, 79,106, 2,255,
+ 0, 0, 0, 0, 62,211,206, 32,189,240,242, 18,190, 84,108,135, 15, 30,150, 34, 70, 84, 2,255, 0, 0, 0, 0,190,157,172,173,
+189,240,242, 18,190, 84,108,135,240,226,150, 34, 70, 84, 2,255, 0, 0, 0, 0, 63, 9,160, 38,189,203,159,217,190,154,186,192,
+ 67,164,166,138, 61,172, 0,255, 0, 0, 0, 0,190,221, 30,219,189,203,159,217,190,154,186,192,188, 92,166,138, 61,172, 0,255,
+ 0, 0, 0, 0, 63, 38,140,172,188,217, 91,211,190,178,252,255, 83,179,206,223, 83,114, 0,255, 0, 0, 0, 0,191, 11,123,244,
+188,217, 91,211,190,178,252,255,172, 77,206,223, 83,114, 0,255, 0, 0, 0, 0, 63, 46,242, 95, 61,199,113,194,190,177, 31, 73,
+ 92, 54, 12,232, 87,210, 2,255, 0, 0, 0, 0,191, 19,225,167, 61,199,113,194,190,177, 31, 73,163,202, 12,232, 87,210, 2,255,
+ 0, 0, 0, 0, 63, 32,243,138, 62, 61, 75, 3,190,177, 31, 73, 62,247, 83,221, 73, 97, 0,255, 0, 0, 0, 0,191, 5,226,209,
+ 62, 61, 75, 3,190,177, 31, 73,193, 9, 83,221, 73, 97, 0,255, 0, 0, 0, 0, 63, 7,194,112, 62, 46, 93, 82,190,150,255, 84,
+ 5,181,111, 80, 62,236, 0,255, 0, 0, 0, 0,190,217, 99,111, 62, 46, 93, 82,190,150,255, 84,250, 75,111, 80, 62,236, 0,255,
+ 0, 0, 0, 0, 63, 6,211,149, 62, 16,129,241,190,145,102, 50, 69,236,239,117,105,236, 0,255, 0, 0, 0, 0,190,215,133,185,
+ 62, 16,129,241,190,145,102, 50,186, 20,239,117,105,236, 0,255, 0, 0, 0, 0, 63, 27, 90,104, 62, 27,180, 54,190,169,168,113,
+ 24, 34,231,205,123, 89, 0,255, 0, 0, 0, 0,191, 0, 73,175, 62, 27,180, 54,190,169,168,113,231,222,231,205,123, 89, 0,255,
+ 0, 0, 0, 0, 63, 36,174,246, 61,169,150, 97,190,173, 99,221,223, 69,252, 16,123,173, 0,255, 0, 0, 0, 0,191, 9,158, 62,
+ 61,169,150, 97,190,173, 99,221, 32,187,252, 16,123,173, 0,255, 0, 0, 0, 0, 63, 30, 38,249,188,127,147, 98,190,173, 99,221,
+239,171, 39, 0,120,207, 0,255, 0, 0, 0, 0,191, 3, 22, 64,188,127,147, 98,190,173, 99,221, 16, 85, 39, 0,120,207, 0,255,
+ 0, 0, 0, 0, 63, 8,177, 75,189,143,233, 23,190,149, 33,158, 51, 9, 45, 56,108, 82, 0,255, 0, 0, 0, 0,190,219, 65, 37,
+189,143,233, 23,190,149, 33,158,204,247, 45, 56,108, 82, 0,255, 0, 0, 0, 0, 62,224,222, 26,189,173,196,120,190, 88, 39,243,
+ 38,147, 62,224,104,153, 2,255, 0, 0, 0, 0,190,170,188,167,189,173,196,120,190, 88, 39,243,217,109, 62,224,104,153, 2,255,
+ 0, 0, 0, 0, 62,247, 66,162, 61,236,195,250,190,128,154,204, 62,218,243,152,110,206, 2,255, 0, 0, 0, 0,190,193, 33, 48,
+ 61,236,195,250,190,128,154,204,193, 38,243,152,110,206, 2,255, 0, 0, 0, 0, 62,252,219,196, 61,184,132, 17,190,145,102, 50,
+ 87, 10,182, 73, 58, 19, 0,255, 0, 0, 0, 0,190,198,186, 82, 61,184,132, 17,190,145,102, 50,168,246,182, 73, 58, 19, 0,255,
+ 0, 0, 0, 0, 62,237,238, 21,189,128,251,103,190,125,122, 44, 15,232,121,106, 37, 64, 0,255, 0, 0, 0, 0,190,183,204,162,
+189,128,251,103,190,125,122, 44,240, 24,121,106, 37, 64, 0,255, 0, 0, 0, 0, 63, 9,160, 38,189, 85, 45,188,190,164, 15, 79,
+239,157,122, 89, 33,212, 0,255, 0, 0, 0, 0,190,221, 30,219,189, 85, 45,188,190,164, 15, 79, 16, 99,122, 89, 33,212, 0,255,
+ 0, 0, 0, 0, 63, 27, 90,104,188, 8, 37,223,190,182,184,107,158, 8, 81,202, 9,185, 0,255, 0, 0, 0, 0,191, 0, 73,175,
+188, 8, 37,223,190,182,184,107, 97,248, 81,202, 9,185, 0,255, 0, 0, 0, 0, 63, 32,243,138, 61,132, 68, 40,190,182,184,107,
+131, 60,239,145, 23, 95, 0,255, 0, 0, 0, 0,191, 5,226,209, 61,132, 68, 40,190,182,184,107,124,196,239,145, 23, 95, 0,255,
+ 0, 0, 0, 0, 63, 25,124,178, 61,236,195,250,190,180,218,181,228, 27,153, 22, 70,206, 0,255, 0, 0, 0, 0,190,252,215,242,
+ 61,236,195,250,190,180,218,181, 27,229,153, 22, 70,206, 0,255, 0, 0, 0, 0, 63, 7,194,112, 61,221,214, 74,190,162, 49,153,
+ 68, 65,168,253, 64,113, 0,255, 0, 0, 0, 0,190,217, 99,111, 61,221,214, 74,190,162, 49,153,187,191,168,253, 64,113, 0,255,
+ 0, 0, 0, 0, 62,228,153,135, 61,169,150, 97,190,125,122, 44, 86,113,222,190, 88, 87, 0,255, 0, 0, 0, 0,190,174,120, 20,
+ 61,169,150, 97,190,125,122, 44,169,143,222,190, 88, 87, 0,255, 0, 0, 0, 0, 62,226,187,209, 60,230,126,216,190,141,170,198,
+ 95,196,182,107, 42,100, 0,255, 0, 0, 0, 0,190,172,154, 93, 60,230,126,216,190,141,170,198,160, 60,182,107, 42,100, 0,255,
+ 0, 0, 0, 0, 62,208, 18,180,188, 8, 37,223,190,141,170,198,111, 42, 14, 21, 61,220, 0,255, 0, 0, 0, 0,190,153,241, 65,
+188, 8, 37,223,190,141,170,198,144,214, 14, 21, 61,220, 0,255, 0, 0, 0, 0, 62,223, 0,100,188, 67,220,161,190,141,170,198,
+ 79, 3, 91, 4, 43, 19, 2,255, 0, 0, 0, 0,190,168,222,241,188, 67,220,161,190,141,170,198,176,253, 91, 4, 43, 19, 2,255,
+ 0, 0, 0, 0, 62,228,153,135,189, 55, 82, 92,190,141,170,198,107,207,254,198, 68,250, 2,255, 0, 0, 0, 0,190,174,120, 20,
+189, 55, 82, 92,190,141,170,198,148, 49,254,198, 68,250, 2,255, 0, 0, 0, 0, 62,221, 34,174,189,115, 9, 29,190,141,170,198,
+ 82, 7, 64,225, 73,200, 0,255, 0, 0, 0, 0,190,167, 1, 59,189,115, 9, 29,190,141,170,198,173,249, 64,225, 73,200, 0,255,
+ 0, 0, 0, 0, 62,200,155,220,189, 85, 45,188,190, 58, 76,146,117, 38,207, 66,239, 47, 0,255, 0, 0, 0, 0,190,146,122,105,
+189, 85, 45,188,190, 58, 76,146,138,218,207, 66,239, 47, 0,255, 0, 0, 0, 0, 62,198,190, 38,189,128,251,103,190,106,209, 15,
+ 97,150, 18,139, 80,184, 0,255, 0, 0, 0, 0,190,144,156,179,189,128,251,103,190,106,209, 15,158,106, 18,139, 80,184, 0,255,
+ 0, 0, 0, 0, 62,198,190, 38,189, 10,137, 74,190,114, 71,231,116, 17,240, 66, 51,154, 0,255, 0, 0, 0, 0,190,144,156,179,
+189, 10,137, 74,190,114, 71,231,139,239,240, 66, 51,154, 0,255, 0, 0, 0, 0, 62,217,103, 66, 61, 46,246, 45,190,125,122, 44,
+113,112,204,245, 30, 39, 0,255, 0, 0, 0, 0,190,163, 69,207, 61, 46,246, 45,190,125,122, 44,142,144,204,245, 30, 39, 0,255,
+ 0, 0, 0, 0, 62,239,203,202, 61,121,154,159,190,139,205, 16, 90,105,185, 61, 56,146, 0,255, 0, 0, 0, 0,190,185,170, 88,
+ 61,121,154,159,190,139,205, 16,165,151,185, 61, 56,146, 0,255, 0, 0, 0, 0, 62,239,203,202, 61,106,172,239,190,152,221, 10,
+ 82,191,204,102, 82,230, 0,255, 0, 0, 0, 0,190,185,170, 88, 61,106,172,239,190,152,221, 10,173, 65,204,102, 82,230, 0,255,
+ 0, 0, 0, 0, 62,221, 34,174,189,115, 9, 29,190,152,221, 10, 29,246, 98, 64, 76, 94, 0,255, 0, 0, 0, 0,190,167, 1, 59,
+189,115, 9, 29,190,152,221, 10,226, 10, 98, 64, 76, 94, 0,255, 0, 0, 0, 0, 62,230,119, 61,189, 55, 82, 92,190,152,221, 10,
+ 77,150, 17,111,100, 75, 0,255, 0, 0, 0, 0,190,176, 85,202,189, 55, 82, 92,190,152,221, 10,178,106, 17,111,100, 75, 0,255,
+ 0, 0, 0, 0, 62,224,222, 26,188,127,147, 98,190,152,221, 10, 60,239, 60,190, 94,195, 0,255, 0, 0, 0, 0,190,170,188,167,
+188,127,147, 98,190,152,221, 10,195, 17, 60,190, 94,195, 0,255, 0, 0, 0, 0, 62,209,240,106,188, 8, 37,223,190,152,221, 10,
+ 83,199, 23,178, 93,209, 0,255, 0, 0, 0, 0,190,155,206,247,188, 8, 37,223,190,152,221, 10,172, 57, 23,178, 93,209, 0,255,
+ 0, 0, 0, 0, 62,228,153,135, 60,230,126,216,190,152,221, 10, 73, 98,200, 1, 88,170, 0,255, 0, 0, 0, 0,190,174,120, 20,
+ 60,230,126,216,190,152,221, 10,182,158,200, 1, 88,170, 0,255, 0, 0, 0, 0, 63, 9,160, 38, 61,206,232,154,190,175, 65,147,
+ 68, 23,223,166,103,112, 0,255, 0, 0, 0, 0,190,221, 30,219, 61,206,232,154,190,175, 65,147,187,233,223,166,103,112, 0,255,
+ 0, 0, 0, 0, 63, 27, 90,104, 61,221,214, 74,190,192, 12,249, 18,165,216,156,120, 89, 0,255, 0, 0, 0, 0,191, 0, 73,175,
+ 61,221,214, 74,190,192, 12,249,237, 91,216,156,120, 89, 0,255, 0, 0, 0, 0, 63, 35,192, 27, 61,121,154,159,190,193,234,175,
+185, 25,231, 29,103,157, 0,255, 0, 0, 0, 0,191, 8,175, 98, 61,121,154,159,190,193,234,175, 70,231,231, 29,103,157, 0,255,
+ 0, 0, 0, 0, 63, 30, 38,249,188, 67,220,161,190,192, 12,249,209, 43, 64, 0,100,119, 0,255, 0, 0, 0, 0,191, 3, 22, 64,
+188, 67,220,161,190,192, 12,249, 46,213, 64, 0,100,119, 0,255, 0, 0, 0, 0, 63, 10,143, 1,189, 85, 45,188,190,177, 31, 73,
+ 26, 52, 92,240, 84, 3, 0,255, 0, 0, 0, 0,190,222,252,145,189, 85, 45,188,190,177, 31, 73,229,204, 92,240, 84, 3, 0,255,
+ 0, 0, 0, 0, 62,237,238, 21,189,115, 9, 29,190,139,205, 16, 8, 58,111,116, 62,101, 0,255, 0, 0, 0, 0,190,183,204,162,
+189,115, 9, 29,190,139,205, 16,247,198,111,116, 62,101, 0,255, 0, 0, 0, 0, 62,254,185,122, 61,169,150, 97,190,158,118, 45,
+ 80,198,213,102, 89,175, 0,255, 0, 0, 0, 0,190,200,152, 8, 61,169,150, 97,190,158,118, 45,175, 58,213,102, 89,175, 0,255,
+ 0, 0, 0, 0, 62,239,203,202,186,133,194,226,190,154,186,192, 25,136, 0,130,125,108, 0,255, 0, 0, 0, 0,190,185,170, 88,
+186,133,194,226,190,154,186,192,230,120, 0,130,125,108, 0,255, 0, 0, 0, 0, 62,250,254, 14,188,187,128,115,190,156,152,119,
+ 27, 2, 30, 58,121,104, 0,255, 0, 0, 0, 0,190,196,220,156,188,187,128,115,190,156,152,119,228,254, 30, 58,121,104, 0,255,
+ 0, 0, 0, 0, 63, 4,245,223, 59,205,106, 77,190,164, 15, 79, 55,218,253,126,115, 35, 0,255, 0, 0, 0, 0,190,211,202, 76,
+ 59,205,106, 77,190,164, 15, 79,200, 38,253,126,115, 35, 0,255, 0, 0, 0, 0, 63, 0, 75,152, 60,230,126,216,190,160, 83,227,
+ 41,164,255,199,121, 8, 0,255, 0, 0, 0, 0,190,202,117,190, 60,230,126,216,190,160, 83,227,214, 92,255,199,121, 8, 0,255,
+ 0, 0, 0, 0, 63, 6,211,149, 61,106,172,239,190,165,237, 5, 39,237, 9,191,121, 55, 0,255, 0, 0, 0, 0,190,215,133,185,
+ 61,106,172,239,190,165,237, 5,216, 19, 9,191,121, 55, 0,255, 0, 0, 0, 0, 63, 11,125,220, 61, 17, 26,205,190,167,202,187,
+ 46,208,244, 41,118,137, 0,255, 0, 0, 0, 0,190,224,218, 71, 61, 17, 26,205,190,167,202,187,209, 48,244, 41,118,137, 0,255,
+ 0, 0, 0, 0, 63, 18, 5,218, 61, 61,227,222,190,169,168,113, 53, 70, 3, 84,116, 85, 2,255, 0, 0, 0, 0,190,237,234, 65,
+ 61, 61,227,222,190,169,168,113,202,186, 3, 84,116, 85, 2,255, 0, 0, 0, 0, 63, 15, 57, 73, 61,154,168,176,190,169,168,113,
+ 44, 99, 38, 36,113,212, 2,255, 0, 0, 0, 0,190,232, 81, 31, 61,154,168,176,190,169,168,113,211,157, 38, 36,113,212, 2,255,
+ 0, 0, 0, 0, 63, 7,194,112, 62, 27,180, 54,190,192, 12,249,198,249, 72, 3,166,222, 3,255, 0, 0, 0, 0,190,217, 99,111,
+ 62, 27,180, 54,190,192, 12,249, 57, 7, 72, 3,166,222, 3,255, 0, 0, 0, 0, 63, 34,209, 64, 62, 42,161,230,190,206,250,170,
+ 37,198, 68,123,154,174, 3,255, 0, 0, 0, 0,191, 7,192,135, 62, 42,161,230,190,206,250,170,218, 58, 68,123,154,174, 3,255,
+ 0, 0, 0, 0, 63, 48,208, 21, 61,177, 13, 57,190,195,200,102,121, 3, 17,201,218, 73, 3,255, 0, 0, 0, 0,191, 21,191, 93,
+ 61,177, 13, 57,190,195,200,102,134,253, 17,201,218, 73, 3,255, 0, 0, 0, 0, 63, 42, 72, 24,188,217, 91,211,190,203, 63, 62,
+ 82, 59,200, 75,175, 70, 3,255, 0, 0, 0, 0,191, 15, 55, 96,188,217, 91,211,190,203, 63, 62,173,197,200, 75,175, 70, 3,255,
+ 0, 0, 0, 0, 63, 9,160, 38,189,188,178, 40,190,193,234,175,249,134,165,184,165,129, 3,255, 0, 0, 0, 0,190,221, 30,219,
+189,188,178, 40,190,193,234,175, 6,122,165,184,165,129, 3,255, 0, 0, 0, 0, 62,215,137,140,189,226, 4, 97,190,154,186,192,
+249,126,163,122,167,205, 1,255, 0, 0, 0, 0,190,161,104, 25,189,226, 4, 97,190,154,186,192, 6,130,163,122,167,205, 1,255,
+ 0, 0, 0, 0, 62,232, 84,243, 62, 1,148, 65,190,167,202,187,193, 93, 65,224,165,229, 1,255, 0, 0, 0, 0,190,178, 51,128,
+ 62, 1,148, 65,190,167,202,187, 62,163, 65,224,165,229, 1,255, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,107, 16,
+ 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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,160, 80, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 47, 28, 7,160, 80, 32,
+ 0, 0, 0, 55, 0, 0, 3,237, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 34,
+ 0, 0, 0, 2, 0, 0, 0, 43, 0, 0, 0, 34, 0, 0, 0, 43, 0, 0, 0, 45, 0, 0, 0, 34, 0, 0, 0, 1, 0, 0, 0, 3,
+ 0, 0, 0, 34, 0, 0, 0, 1, 0, 0, 0, 46, 0, 0, 0, 34, 0, 0, 0, 44, 0, 0, 0, 46, 0, 0, 0, 34, 0, 0, 0, 3,
+ 0, 0, 0, 44, 0, 0, 0, 34, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 34, 0, 0, 0, 4, 0, 0, 0, 41, 0, 0, 0, 34,
+ 0, 0, 0, 41, 0, 0, 0, 43, 0, 0, 0, 34, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 34, 0, 0, 0, 42, 0, 0, 0, 44,
+ 0, 0, 0, 34, 0, 0, 0, 5, 0, 0, 0, 42, 0, 0, 0, 34, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 34, 0, 0, 0, 6,
+ 0, 0, 0, 8, 0, 0, 0, 34, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 34, 0, 0, 0, 7, 0, 0, 0, 9, 0, 0, 0, 34,
+ 0, 0, 0, 3, 0, 0, 0, 9, 0, 0, 0, 34, 0, 0, 0, 5, 0, 0, 0, 7, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 10,
+ 0, 0, 0, 34, 0, 0, 0, 8, 0, 0, 0, 10, 0, 0, 0, 34, 0, 0, 0, 9, 0, 0, 0, 11, 0, 0, 0, 34, 0, 0, 0, 1,
+ 0, 0, 0, 11, 0, 0, 0, 34, 0, 0, 0, 10, 0, 0, 0, 12, 0, 0, 0, 34, 0, 0, 0, 12, 0, 0, 0, 14, 0, 0, 0, 34,
+ 0, 0, 0, 8, 0, 0, 0, 14, 0, 0, 0, 34, 0, 0, 0, 11, 0, 0, 0, 13, 0, 0, 0, 34, 0, 0, 0, 14, 0, 0, 0, 15,
+ 0, 0, 0, 34, 0, 0, 0, 6, 0, 0, 0, 15, 0, 0, 0, 34, 0, 0, 0, 7, 0, 0, 0, 16, 0, 0, 0, 34, 0, 0, 0, 14,
+ 0, 0, 0, 19, 0, 0, 0, 34, 0, 0, 0, 17, 0, 0, 0, 19, 0, 0, 0, 34, 0, 0, 0, 15, 0, 0, 0, 17, 0, 0, 0, 34,
+ 0, 0, 0, 18, 0, 0, 0, 20, 0, 0, 0, 34, 0, 0, 0, 16, 0, 0, 0, 18, 0, 0, 0, 34, 0, 0, 0, 12, 0, 0, 0, 21,
+ 0, 0, 0, 34, 0, 0, 0, 19, 0, 0, 0, 21, 0, 0, 0, 34, 0, 0, 0, 20, 0, 0, 0, 22, 0, 0, 0, 34, 0, 0, 0, 13,
+ 0, 0, 0, 22, 0, 0, 0, 34, 0, 0, 0, 21, 0, 0, 0, 23, 0, 0, 0, 34, 0, 0, 0, 23, 0, 0, 0, 25, 0, 0, 0, 34,
+ 0, 0, 0, 19, 0, 0, 0, 25, 0, 0, 0, 34, 0, 0, 0, 24, 0, 0, 0, 26, 0, 0, 0, 34, 0, 0, 0, 22, 0, 0, 0, 24,
+ 0, 0, 0, 34, 0, 0, 0, 20, 0, 0, 0, 26, 0, 0, 0, 34, 0, 0, 0, 25, 0, 0, 0, 27, 0, 0, 0, 34, 0, 0, 0, 17,
+ 0, 0, 0, 27, 0, 0, 0, 34, 0, 0, 0, 26, 0, 0, 0, 28, 0, 0, 0, 34, 0, 0, 0, 18, 0, 0, 0, 28, 0, 0, 0, 34,
+ 0, 0, 0, 25, 0, 0, 0, 31, 0, 0, 0, 34, 0, 0, 0, 29, 0, 0, 0, 31, 0, 0, 0, 34, 0, 0, 0, 27, 0, 0, 0, 29,
+ 0, 0, 0, 34, 0, 0, 0, 30, 0, 0, 0, 32, 0, 0, 0, 34, 0, 0, 0, 26, 0, 0, 0, 32, 0, 0, 0, 34, 0, 0, 0, 28,
+ 0, 0, 0, 30, 0, 0, 0, 34, 0, 0, 0, 23, 0, 0, 0, 33, 0, 0, 0, 34, 0, 0, 0, 31, 0, 0, 0, 33, 0, 0, 0, 34,
+ 0, 0, 0, 32, 0, 0, 0, 34, 0, 0, 0, 34, 0, 0, 0, 24, 0, 0, 0, 34, 0, 0, 0, 34, 0, 0, 0, 33, 0, 0, 0, 35,
+ 0, 0, 0, 34, 0, 0, 0, 35, 0, 0, 0, 37, 0, 0, 0, 34, 0, 0, 0, 31, 0, 0, 0, 37, 0, 0, 0, 34, 0, 0, 0, 36,
+ 0, 0, 0, 38, 0, 0, 0, 34, 0, 0, 0, 34, 0, 0, 0, 36, 0, 0, 0, 34, 0, 0, 0, 32, 0, 0, 0, 38, 0, 0, 0, 34,
+ 0, 0, 0, 37, 0, 0, 0, 39, 0, 0, 0, 34, 0, 0, 0, 29, 0, 0, 0, 39, 0, 0, 0, 34, 0, 0, 0, 38, 0, 0, 0, 40,
+ 0, 0, 0, 34, 0, 0, 0, 30, 0, 0, 0, 40, 0, 0, 0, 34, 0, 0, 0, 37, 0, 0, 0, 43, 0, 0, 0, 34, 0, 0, 0, 39,
+ 0, 0, 0, 41, 0, 0, 0, 34, 0, 0, 0, 38, 0, 0, 0, 44, 0, 0, 0, 34, 0, 0, 0, 40, 0, 0, 0, 42, 0, 0, 0, 34,
+ 0, 0, 0, 35, 0, 0, 0, 45, 0, 0, 0, 34, 0, 0, 0, 36, 0, 0, 0, 46, 0, 0, 0, 34, 0, 0, 0, 35, 0, 0, 0, 49,
+ 0, 0, 0, 34, 0, 0, 0, 47, 0, 0, 0, 49, 0, 0, 0, 34, 0, 0, 0, 45, 0, 0, 0, 47, 0, 0, 0, 34, 0, 0, 0, 36,
+ 0, 0, 0, 50, 0, 0, 0, 34, 0, 0, 0, 46, 0, 0, 0, 48, 0, 0, 0, 34, 0, 0, 0, 48, 0, 0, 0, 50, 0, 0, 0, 34,
+ 0, 0, 0, 33, 0, 0, 0, 51, 0, 0, 0, 34, 0, 0, 0, 49, 0, 0, 0, 51, 0, 0, 0, 34, 0, 0, 0, 34, 0, 0, 0, 52,
+ 0, 0, 0, 34, 0, 0, 0, 50, 0, 0, 0, 52, 0, 0, 0, 34, 0, 0, 0, 23, 0, 0, 0, 53, 0, 0, 0, 34, 0, 0, 0, 51,
+ 0, 0, 0, 53, 0, 0, 0, 34, 0, 0, 0, 24, 0, 0, 0, 54, 0, 0, 0, 34, 0, 0, 0, 52, 0, 0, 0, 54, 0, 0, 0, 34,
+ 0, 0, 0, 21, 0, 0, 0, 55, 0, 0, 0, 34, 0, 0, 0, 53, 0, 0, 0, 55, 0, 0, 0, 34, 0, 0, 0, 22, 0, 0, 0, 56,
+ 0, 0, 0, 34, 0, 0, 0, 54, 0, 0, 0, 56, 0, 0, 0, 34, 0, 0, 0, 12, 0, 0, 0, 57, 0, 0, 0, 34, 0, 0, 0, 55,
+ 0, 0, 0, 57, 0, 0, 0, 34, 0, 0, 0, 13, 0, 0, 0, 58, 0, 0, 0, 34, 0, 0, 0, 56, 0, 0, 0, 58, 0, 0, 0, 34,
+ 0, 0, 0, 10, 0, 0, 0, 61, 0, 0, 0, 34, 0, 0, 0, 57, 0, 0, 0, 61, 0, 0, 0, 34, 0, 0, 0, 11, 0, 0, 0, 62,
+ 0, 0, 0, 34, 0, 0, 0, 58, 0, 0, 0, 62, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 34, 0, 0, 0, 61,
+ 0, 0, 0, 63, 0, 0, 0, 34, 0, 0, 0, 1, 0, 0, 0, 64, 0, 0, 0, 34, 0, 0, 0, 62, 0, 0, 0, 64, 0, 0, 0, 34,
+ 0, 0, 0, 47, 0, 0, 0, 63, 0, 0, 0, 34, 0, 0, 0, 48, 0, 0, 0, 64, 0, 0, 0, 34, 0, 0, 0, 59, 0, 0, 0, 63,
+ 0, 0, 0, 34, 0, 0, 0, 47, 0, 0, 0, 59, 0, 0, 0, 34, 0, 0, 0, 60, 0, 0, 0, 64, 0, 0, 0, 34, 0, 0, 0, 48,
+ 0, 0, 0, 60, 0, 0, 0, 34, 0, 0, 0, 59, 0, 0, 0, 61, 0, 0, 0, 34, 0, 0, 0, 60, 0, 0, 0, 62, 0, 0, 0, 34,
+ 0, 0, 0, 57, 0, 0, 0, 59, 0, 0, 0, 34, 0, 0, 0, 58, 0, 0, 0, 60, 0, 0, 0, 34, 0, 0, 0, 55, 0, 0, 0, 59,
+ 0, 0, 0, 34, 0, 0, 0, 56, 0, 0, 0, 60, 0, 0, 0, 34, 0, 0, 0, 53, 0, 0, 0, 59, 0, 0, 0, 34, 0, 0, 0, 54,
+ 0, 0, 0, 60, 0, 0, 0, 34, 0, 0, 0, 51, 0, 0, 0, 59, 0, 0, 0, 34, 0, 0, 0, 52, 0, 0, 0, 60, 0, 0, 0, 34,
+ 0, 0, 0, 49, 0, 0, 0, 59, 0, 0, 0, 34, 0, 0, 0, 50, 0, 0, 0, 60, 0, 0, 0, 34, 0, 0, 0, 87, 0, 0, 0,171,
+ 0, 0, 0, 34, 0, 0, 0,171, 0, 0, 0,173, 0, 0, 0, 34, 0, 0, 0, 89, 0, 0, 0,173, 0, 0, 0, 34, 0, 0, 0, 87,
+ 0, 0, 0, 89, 0, 0, 0, 34, 0, 0, 0,172, 0, 0, 0,173, 0, 0, 0, 34, 0, 0, 0, 88, 0, 0, 0,172, 0, 0, 0, 34,
+ 0, 0, 0, 88, 0, 0, 0, 89, 0, 0, 0, 34, 0, 0, 0, 85, 0, 0, 0,169, 0, 0, 0, 34, 0, 0, 0,169, 0, 0, 0,171,
+ 0, 0, 0, 34, 0, 0, 0, 85, 0, 0, 0, 87, 0, 0, 0, 34, 0, 0, 0,170, 0, 0, 0,172, 0, 0, 0, 34, 0, 0, 0, 86,
+ 0, 0, 0,170, 0, 0, 0, 34, 0, 0, 0, 86, 0, 0, 0, 88, 0, 0, 0, 34, 0, 0, 0, 83, 0, 0, 0,167, 0, 0, 0, 34,
+ 0, 0, 0,167, 0, 0, 0,169, 0, 0, 0, 34, 0, 0, 0, 83, 0, 0, 0, 85, 0, 0, 0, 34, 0, 0, 0,168, 0, 0, 0,170,
+ 0, 0, 0, 34, 0, 0, 0, 84, 0, 0, 0,168, 0, 0, 0, 34, 0, 0, 0, 84, 0, 0, 0, 86, 0, 0, 0, 34, 0, 0, 0, 81,
+ 0, 0, 0,165, 0, 0, 0, 34, 0, 0, 0,165, 0, 0, 0,167, 0, 0, 0, 34, 0, 0, 0, 81, 0, 0, 0, 83, 0, 0, 0, 34,
+ 0, 0, 0,166, 0, 0, 0,168, 0, 0, 0, 34, 0, 0, 0, 82, 0, 0, 0,166, 0, 0, 0, 34, 0, 0, 0, 82, 0, 0, 0, 84,
+ 0, 0, 0, 34, 0, 0, 0, 79, 0, 0, 0,163, 0, 0, 0, 34, 0, 0, 0,163, 0, 0, 0,165, 0, 0, 0, 34, 0, 0, 0, 79,
+ 0, 0, 0, 81, 0, 0, 0, 34, 0, 0, 0,164, 0, 0, 0,166, 0, 0, 0, 34, 0, 0, 0, 80, 0, 0, 0,164, 0, 0, 0, 34,
+ 0, 0, 0, 80, 0, 0, 0, 82, 0, 0, 0, 34, 0, 0, 0, 77, 0, 0, 0, 90, 0, 0, 0, 34, 0, 0, 0, 90, 0, 0, 0,143,
+ 0, 0, 0, 34, 0, 0, 0,143, 0, 0, 0,161, 0, 0, 0, 34, 0, 0, 0, 77, 0, 0, 0,161, 0, 0, 0, 34, 0, 0, 0, 91,
+ 0, 0, 0,144, 0, 0, 0, 34, 0, 0, 0, 78, 0, 0, 0, 91, 0, 0, 0, 34, 0, 0, 0, 78, 0, 0, 0,162, 0, 0, 0, 34,
+ 0, 0, 0,144, 0, 0, 0,162, 0, 0, 0, 34, 0, 0, 0, 90, 0, 0, 0, 92, 0, 0, 0, 34, 0, 0, 0, 92, 0, 0, 0,145,
+ 0, 0, 0, 34, 0, 0, 0,143, 0, 0, 0,145, 0, 0, 0, 34, 0, 0, 0, 93, 0, 0, 0,146, 0, 0, 0, 34, 0, 0, 0, 91,
+ 0, 0, 0, 93, 0, 0, 0, 34, 0, 0, 0,144, 0, 0, 0,146, 0, 0, 0, 34, 0, 0, 0, 92, 0, 0, 0, 94, 0, 0, 0, 34,
+ 0, 0, 0, 94, 0, 0, 0,147, 0, 0, 0, 34, 0, 0, 0,145, 0, 0, 0,147, 0, 0, 0, 34, 0, 0, 0, 95, 0, 0, 0,148,
+ 0, 0, 0, 34, 0, 0, 0, 93, 0, 0, 0, 95, 0, 0, 0, 34, 0, 0, 0,146, 0, 0, 0,148, 0, 0, 0, 34, 0, 0, 0, 94,
+ 0, 0, 0, 96, 0, 0, 0, 34, 0, 0, 0, 96, 0, 0, 0,149, 0, 0, 0, 34, 0, 0, 0,147, 0, 0, 0,149, 0, 0, 0, 34,
+ 0, 0, 0, 97, 0, 0, 0,150, 0, 0, 0, 34, 0, 0, 0, 95, 0, 0, 0, 97, 0, 0, 0, 34, 0, 0, 0,148, 0, 0, 0,150,
+ 0, 0, 0, 34, 0, 0, 0, 96, 0, 0, 0, 98, 0, 0, 0, 34, 0, 0, 0, 98, 0, 0, 0,151, 0, 0, 0, 34, 0, 0, 0,149,
+ 0, 0, 0,151, 0, 0, 0, 34, 0, 0, 0, 99, 0, 0, 0,152, 0, 0, 0, 34, 0, 0, 0, 97, 0, 0, 0, 99, 0, 0, 0, 34,
+ 0, 0, 0,150, 0, 0, 0,152, 0, 0, 0, 34, 0, 0, 0, 98, 0, 0, 0,100, 0, 0, 0, 34, 0, 0, 0,100, 0, 0, 0,153,
+ 0, 0, 0, 34, 0, 0, 0,151, 0, 0, 0,153, 0, 0, 0, 34, 0, 0, 0,101, 0, 0, 0,154, 0, 0, 0, 34, 0, 0, 0, 99,
+ 0, 0, 0,101, 0, 0, 0, 34, 0, 0, 0,152, 0, 0, 0,154, 0, 0, 0, 34, 0, 0, 0,100, 0, 0, 0,102, 0, 0, 0, 34,
+ 0, 0, 0,102, 0, 0, 0,155, 0, 0, 0, 34, 0, 0, 0,153, 0, 0, 0,155, 0, 0, 0, 34, 0, 0, 0,103, 0, 0, 0,156,
+ 0, 0, 0, 34, 0, 0, 0,101, 0, 0, 0,103, 0, 0, 0, 34, 0, 0, 0,154, 0, 0, 0,156, 0, 0, 0, 34, 0, 0, 0,102,
+ 0, 0, 0,104, 0, 0, 0, 34, 0, 0, 0,104, 0, 0, 0,157, 0, 0, 0, 34, 0, 0, 0,155, 0, 0, 0,157, 0, 0, 0, 34,
+ 0, 0, 0,105, 0, 0, 0,158, 0, 0, 0, 34, 0, 0, 0,103, 0, 0, 0,105, 0, 0, 0, 34, 0, 0, 0,156, 0, 0, 0,158,
+ 0, 0, 0, 34, 0, 0, 0,104, 0, 0, 0,106, 0, 0, 0, 34, 0, 0, 0,106, 0, 0, 0,159, 0, 0, 0, 34, 0, 0, 0,157,
+ 0, 0, 0,159, 0, 0, 0, 34, 0, 0, 0,107, 0, 0, 0,160, 0, 0, 0, 34, 0, 0, 0,105, 0, 0, 0,107, 0, 0, 0, 34,
+ 0, 0, 0,158, 0, 0, 0,160, 0, 0, 0, 34, 0, 0, 0, 65, 0, 0, 0,106, 0, 0, 0, 34, 0, 0, 0, 65, 0, 0, 0, 66,
+ 0, 0, 0, 34, 0, 0, 0, 66, 0, 0, 0,159, 0, 0, 0, 34, 0, 0, 0, 65, 0, 0, 0,107, 0, 0, 0, 34, 0, 0, 0, 66,
+ 0, 0, 0,160, 0, 0, 0, 34, 0, 0, 0,108, 0, 0, 0,125, 0, 0, 0, 34, 0, 0, 0,125, 0, 0, 0,157, 0, 0, 0, 34,
+ 0, 0, 0,108, 0, 0, 0,159, 0, 0, 0, 34, 0, 0, 0,126, 0, 0, 0,158, 0, 0, 0, 34, 0, 0, 0,109, 0, 0, 0,126,
+ 0, 0, 0, 34, 0, 0, 0,109, 0, 0, 0,160, 0, 0, 0, 34, 0, 0, 0,125, 0, 0, 0,176, 0, 0, 0, 34, 0, 0, 0,155,
+ 0, 0, 0,176, 0, 0, 0, 34, 0, 0, 0,156, 0, 0, 0,177, 0, 0, 0, 34, 0, 0, 0,126, 0, 0, 0,177, 0, 0, 0, 34,
+ 0, 0, 0,123, 0, 0, 0,153, 0, 0, 0, 34, 0, 0, 0,123, 0, 0, 0,176, 0, 0, 0, 34, 0, 0, 0,124, 0, 0, 0,154,
+ 0, 0, 0, 34, 0, 0, 0,124, 0, 0, 0,177, 0, 0, 0, 34, 0, 0, 0,121, 0, 0, 0,151, 0, 0, 0, 34, 0, 0, 0,121,
+ 0, 0, 0,123, 0, 0, 0, 34, 0, 0, 0,122, 0, 0, 0,152, 0, 0, 0, 34, 0, 0, 0,122, 0, 0, 0,124, 0, 0, 0, 34,
+ 0, 0, 0,119, 0, 0, 0,149, 0, 0, 0, 34, 0, 0, 0,119, 0, 0, 0,121, 0, 0, 0, 34, 0, 0, 0,120, 0, 0, 0,150,
+ 0, 0, 0, 34, 0, 0, 0,120, 0, 0, 0,122, 0, 0, 0, 34, 0, 0, 0,117, 0, 0, 0,147, 0, 0, 0, 34, 0, 0, 0,117,
+ 0, 0, 0,119, 0, 0, 0, 34, 0, 0, 0,118, 0, 0, 0,148, 0, 0, 0, 34, 0, 0, 0,118, 0, 0, 0,120, 0, 0, 0, 34,
+ 0, 0, 0,115, 0, 0, 0,145, 0, 0, 0, 34, 0, 0, 0,115, 0, 0, 0,117, 0, 0, 0, 34, 0, 0, 0,116, 0, 0, 0,146,
+ 0, 0, 0, 34, 0, 0, 0,116, 0, 0, 0,118, 0, 0, 0, 34, 0, 0, 0,113, 0, 0, 0,143, 0, 0, 0, 34, 0, 0, 0,113,
+ 0, 0, 0,115, 0, 0, 0, 34, 0, 0, 0,114, 0, 0, 0,144, 0, 0, 0, 34, 0, 0, 0,114, 0, 0, 0,116, 0, 0, 0, 34,
+ 0, 0, 0,112, 0, 0, 0,162, 0, 0, 0, 34, 0, 0, 0,112, 0, 0, 0,114, 0, 0, 0, 34, 0, 0, 0,174, 0, 0, 0,178,
+ 0, 0, 0, 34, 0, 0, 0,161, 0, 0, 0,174, 0, 0, 0, 34, 0, 0, 0,174, 0, 0, 0,179, 0, 0, 0, 34, 0, 0, 0,112,
+ 0, 0, 0,179, 0, 0, 0, 34, 0, 0, 0,162, 0, 0, 0,174, 0, 0, 0, 34, 0, 0, 0, 66, 0, 0, 0,110, 0, 0, 0, 34,
+ 0, 0, 0,108, 0, 0, 0,110, 0, 0, 0, 34, 0, 0, 0,109, 0, 0, 0,111, 0, 0, 0, 34, 0, 0, 0, 66, 0, 0, 0,111,
+ 0, 0, 0, 34, 0, 0, 0, 66, 0, 0, 0,175, 0, 0, 0, 34, 0, 0, 0,175, 0, 0, 0,180, 0, 0, 0, 34, 0, 0, 0,110,
+ 0, 0, 0,180, 0, 0, 0, 34, 0, 0, 0,111, 0, 0, 0,181, 0, 0, 0, 34, 0, 0, 0,175, 0, 0, 0,181, 0, 0, 0, 34,
+ 0, 0, 0,178, 0, 0, 0,180, 0, 0, 0, 34, 0, 0, 0,174, 0, 0, 0,175, 0, 0, 0, 32, 0, 0, 0,179, 0, 0, 0,181,
+ 0, 0, 0, 34, 0, 0, 0,132, 0, 0, 0,134, 0, 0, 0, 34, 0, 0, 0,134, 0, 0, 0,173, 0, 0, 0, 34, 0, 0, 0,132,
+ 0, 0, 0,171, 0, 0, 0, 34, 0, 0, 0,133, 0, 0, 0,134, 0, 0, 0, 34, 0, 0, 0,133, 0, 0, 0,172, 0, 0, 0, 34,
+ 0, 0, 0,130, 0, 0, 0,132, 0, 0, 0, 34, 0, 0, 0,130, 0, 0, 0,169, 0, 0, 0, 34, 0, 0, 0,131, 0, 0, 0,133,
+ 0, 0, 0, 34, 0, 0, 0,131, 0, 0, 0,170, 0, 0, 0, 34, 0, 0, 0,128, 0, 0, 0,130, 0, 0, 0, 34, 0, 0, 0,128,
+ 0, 0, 0,167, 0, 0, 0, 34, 0, 0, 0,129, 0, 0, 0,131, 0, 0, 0, 34, 0, 0, 0,129, 0, 0, 0,168, 0, 0, 0, 34,
+ 0, 0, 0,163, 0, 0, 0,184, 0, 0, 0, 34, 0, 0, 0,182, 0, 0, 0,184, 0, 0, 0, 34, 0, 0, 0,165, 0, 0, 0,182,
+ 0, 0, 0, 34, 0, 0, 0,183, 0, 0, 0,185, 0, 0, 0, 34, 0, 0, 0,164, 0, 0, 0,185, 0, 0, 0, 34, 0, 0, 0,166,
+ 0, 0, 0,183, 0, 0, 0, 34, 0, 0, 0,128, 0, 0, 0,182, 0, 0, 0, 34, 0, 0, 0,129, 0, 0, 0,183, 0, 0, 0, 34,
+ 0, 0, 0,141, 0, 0, 0,187, 0, 0, 0, 34, 0, 0, 0,186, 0, 0, 0,187, 0, 0, 0, 32, 0, 0, 0,184, 0, 0, 0,186,
+ 0, 0, 0, 34, 0, 0, 0,141, 0, 0, 0,184, 0, 0, 0, 34, 0, 0, 0,142, 0, 0, 0,187, 0, 0, 0, 34, 0, 0, 0,142,
+ 0, 0, 0,185, 0, 0, 0, 34, 0, 0, 0,185, 0, 0, 0,186, 0, 0, 0, 34, 0, 0, 0, 67, 0, 0, 0,186, 0, 0, 0, 32,
+ 0, 0, 0, 67, 0, 0, 0,182, 0, 0, 0, 34, 0, 0, 0, 67, 0, 0, 0,183, 0, 0, 0, 34, 0, 0, 0,127, 0, 0, 0,128,
+ 0, 0, 0, 34, 0, 0, 0, 67, 0, 0, 0,127, 0, 0, 0, 32, 0, 0, 0,127, 0, 0, 0,129, 0, 0, 0, 34, 0, 0, 0,139,
+ 0, 0, 0,190, 0, 0, 0, 34, 0, 0, 0,188, 0, 0, 0,190, 0, 0, 0, 34, 0, 0, 0,141, 0, 0, 0,188, 0, 0, 0, 34,
+ 0, 0, 0,139, 0, 0, 0,141, 0, 0, 0, 34, 0, 0, 0,189, 0, 0, 0,191, 0, 0, 0, 34, 0, 0, 0,140, 0, 0, 0,191,
+ 0, 0, 0, 34, 0, 0, 0,140, 0, 0, 0,142, 0, 0, 0, 34, 0, 0, 0,142, 0, 0, 0,189, 0, 0, 0, 34, 0, 0, 0,137,
+ 0, 0, 0,192, 0, 0, 0, 34, 0, 0, 0,190, 0, 0, 0,192, 0, 0, 0, 34, 0, 0, 0,137, 0, 0, 0,139, 0, 0, 0, 34,
+ 0, 0, 0,191, 0, 0, 0,193, 0, 0, 0, 34, 0, 0, 0,138, 0, 0, 0,193, 0, 0, 0, 34, 0, 0, 0,138, 0, 0, 0,140,
+ 0, 0, 0, 34, 0, 0, 0,136, 0, 0, 0,194, 0, 0, 0, 34, 0, 0, 0,192, 0, 0, 0,194, 0, 0, 0, 34, 0, 0, 0,136,
+ 0, 0, 0,137, 0, 0, 0, 34, 0, 0, 0,193, 0, 0, 0,195, 0, 0, 0, 34, 0, 0, 0,136, 0, 0, 0,195, 0, 0, 0, 34,
+ 0, 0, 0,136, 0, 0, 0,138, 0, 0, 0, 34, 0, 0, 0, 69, 0, 0, 0,135, 0, 0, 0, 34, 0, 0, 0, 69, 0, 0, 0,194,
+ 0, 0, 0, 34, 0, 0, 0,135, 0, 0, 0,136, 0, 0, 0, 34, 0, 0, 0, 69, 0, 0, 0,195, 0, 0, 0, 34, 0, 0, 0, 68,
+ 0, 0, 0,188, 0, 0, 0, 34, 0, 0, 0, 68, 0, 0, 0,187, 0, 0, 0, 34, 0, 0, 0, 68, 0, 0, 0,189, 0, 0, 0, 34,
+ 0, 0, 0,188, 0, 0, 0,203, 0, 0, 0, 34, 0, 0, 0,203, 0, 0, 0,205, 0, 0, 0, 34, 0, 0, 0, 68, 0, 0, 0,205,
+ 0, 0, 0, 34, 0, 0, 0,189, 0, 0, 0,204, 0, 0, 0, 34, 0, 0, 0,204, 0, 0, 0,205, 0, 0, 0, 34, 0, 0, 0, 69,
+ 0, 0, 0,196, 0, 0, 0, 34, 0, 0, 0,196, 0, 0, 0,197, 0, 0, 0, 34, 0, 0, 0,194, 0, 0, 0,197, 0, 0, 0, 34,
+ 0, 0, 0,196, 0, 0, 0,198, 0, 0, 0, 34, 0, 0, 0,195, 0, 0, 0,198, 0, 0, 0, 34, 0, 0, 0,197, 0, 0, 0,199,
+ 0, 0, 0, 34, 0, 0, 0,192, 0, 0, 0,199, 0, 0, 0, 34, 0, 0, 0,198, 0, 0, 0,200, 0, 0, 0, 34, 0, 0, 0,193,
+ 0, 0, 0,200, 0, 0, 0, 34, 0, 0, 0,199, 0, 0, 0,201, 0, 0, 0, 34, 0, 0, 0,190, 0, 0, 0,201, 0, 0, 0, 34,
+ 0, 0, 0,200, 0, 0, 0,202, 0, 0, 0, 34, 0, 0, 0,191, 0, 0, 0,202, 0, 0, 0, 34, 0, 0, 0,201, 0, 0, 0,203,
+ 0, 0, 0, 34, 0, 0, 0,202, 0, 0, 0,204, 0, 0, 0, 34, 0, 0, 0,196, 0, 0, 0,201, 0, 0, 0, 34, 0, 0, 0,196,
+ 0, 0, 0,202, 0, 0, 0, 34, 0, 0, 0,196, 0, 0, 0,205, 0, 0, 0, 34, 0, 0, 0,137, 0, 0, 0,161, 0, 0, 0, 34,
+ 0, 0, 0,136, 0, 0, 0,174, 0, 0, 0, 34, 0, 0, 0,138, 0, 0, 0,162, 0, 0, 0, 34, 0, 0, 0,139, 0, 0, 0,208,
+ 0, 0, 0, 34, 0, 0, 0,161, 0, 0, 0,208, 0, 0, 0, 34, 0, 0, 0,140, 0, 0, 0,209, 0, 0, 0, 34, 0, 0, 0,162,
+ 0, 0, 0,209, 0, 0, 0, 34, 0, 0, 0,141, 0, 0, 0,210, 0, 0, 0, 34, 0, 0, 0,208, 0, 0, 0,210, 0, 0, 0, 34,
+ 0, 0, 0,142, 0, 0, 0,211, 0, 0, 0, 34, 0, 0, 0,209, 0, 0, 0,211, 0, 0, 0, 34, 0, 0, 0,163, 0, 0, 0,210,
+ 0, 0, 0, 34, 0, 0, 0,164, 0, 0, 0,211, 0, 0, 0, 34, 0, 0, 0, 79, 0, 0, 0,206, 0, 0, 0, 34, 0, 0, 0,206,
+ 0, 0, 0,210, 0, 0, 0, 34, 0, 0, 0,207, 0, 0, 0,211, 0, 0, 0, 34, 0, 0, 0, 80, 0, 0, 0,207, 0, 0, 0, 34,
+ 0, 0, 0,206, 0, 0, 0,212, 0, 0, 0, 34, 0, 0, 0,208, 0, 0, 0,212, 0, 0, 0, 34, 0, 0, 0,209, 0, 0, 0,213,
+ 0, 0, 0, 34, 0, 0, 0,207, 0, 0, 0,213, 0, 0, 0, 34, 0, 0, 0, 77, 0, 0, 0,212, 0, 0, 0, 34, 0, 0, 0, 78,
+ 0, 0, 0,213, 0, 0, 0, 34, 0, 0, 0, 70, 0, 0, 0,127, 0, 0, 0, 34, 0, 0, 0, 70, 0, 0, 0,219, 0, 0, 0, 34,
+ 0, 0, 0,128, 0, 0, 0,219, 0, 0, 0, 34, 0, 0, 0,129, 0, 0, 0,220, 0, 0, 0, 34, 0, 0, 0, 70, 0, 0, 0,220,
+ 0, 0, 0, 34, 0, 0, 0,217, 0, 0, 0,219, 0, 0, 0, 34, 0, 0, 0,130, 0, 0, 0,217, 0, 0, 0, 34, 0, 0, 0,131,
+ 0, 0, 0,218, 0, 0, 0, 34, 0, 0, 0,218, 0, 0, 0,220, 0, 0, 0, 34, 0, 0, 0,215, 0, 0, 0,217, 0, 0, 0, 34,
+ 0, 0, 0,132, 0, 0, 0,215, 0, 0, 0, 34, 0, 0, 0,133, 0, 0, 0,216, 0, 0, 0, 34, 0, 0, 0,216, 0, 0, 0,218,
+ 0, 0, 0, 34, 0, 0, 0,214, 0, 0, 0,215, 0, 0, 0, 34, 0, 0, 0,134, 0, 0, 0,214, 0, 0, 0, 34, 0, 0, 0,214,
+ 0, 0, 0,216, 0, 0, 0, 34, 0, 0, 0,215, 0, 0, 0,226, 0, 0, 0, 34, 0, 0, 0,226, 0, 0, 0,228, 0, 0, 0, 34,
+ 0, 0, 0,214, 0, 0, 0,228, 0, 0, 0, 34, 0, 0, 0,216, 0, 0, 0,227, 0, 0, 0, 34, 0, 0, 0,227, 0, 0, 0,228,
+ 0, 0, 0, 34, 0, 0, 0,217, 0, 0, 0,224, 0, 0, 0, 34, 0, 0, 0,224, 0, 0, 0,226, 0, 0, 0, 34, 0, 0, 0,218,
+ 0, 0, 0,225, 0, 0, 0, 34, 0, 0, 0,225, 0, 0, 0,227, 0, 0, 0, 34, 0, 0, 0,219, 0, 0, 0,222, 0, 0, 0, 34,
+ 0, 0, 0,222, 0, 0, 0,224, 0, 0, 0, 34, 0, 0, 0,220, 0, 0, 0,223, 0, 0, 0, 34, 0, 0, 0,223, 0, 0, 0,225,
+ 0, 0, 0, 34, 0, 0, 0, 70, 0, 0, 0,221, 0, 0, 0, 34, 0, 0, 0,221, 0, 0, 0,222, 0, 0, 0, 34, 0, 0, 0,221,
+ 0, 0, 0,223, 0, 0, 0, 34, 0, 0, 0,221, 0, 0, 0,228, 0, 0, 0, 34, 0, 0, 0,222, 0, 0, 0,226, 0, 0, 0, 34,
+ 0, 0, 0,223, 0, 0, 0,227, 0, 0, 0, 34, 0, 0, 0,178, 0, 0, 0,231, 0, 0, 0, 34, 0, 0, 0,229, 0, 0, 0,231,
+ 0, 0, 0, 34, 0, 0, 0,180, 0, 0, 0,229, 0, 0, 0, 34, 0, 0, 0,179, 0, 0, 0,232, 0, 0, 0, 34, 0, 0, 0,181,
+ 0, 0, 0,230, 0, 0, 0, 34, 0, 0, 0,230, 0, 0, 0,232, 0, 0, 0, 34, 0, 0, 0,229, 0, 0, 0,251, 0, 0, 0, 34,
+ 0, 0, 0,110, 0, 0, 0,251, 0, 0, 0, 34, 0, 0, 0,111, 0, 0, 0,252, 0, 0, 0, 34, 0, 0, 0,230, 0, 0, 0,252,
+ 0, 0, 0, 34, 0, 0, 0,251, 0, 0, 0,253, 0, 0, 0, 34, 0, 0, 0,108, 0, 0, 0,253, 0, 0, 0, 34, 0, 0, 0,109,
+ 0, 0, 0,254, 0, 0, 0, 34, 0, 0, 0,252, 0, 0, 0,254, 0, 0, 0, 34, 0, 0, 0,231, 0, 0, 0,249, 0, 0, 0, 34,
+ 0, 0, 0,112, 0, 0, 0,250, 0, 0, 0, 34, 0, 0, 0,232, 0, 0, 0,250, 0, 0, 0, 34, 0, 0, 0,113, 0, 0, 0,247,
+ 0, 0, 0, 34, 0, 0, 0,247, 0, 0, 0,249, 0, 0, 0, 34, 0, 0, 0,114, 0, 0, 0,248, 0, 0, 0, 34, 0, 0, 0,248,
+ 0, 0, 0,250, 0, 0, 0, 34, 0, 0, 0,115, 0, 0, 0,245, 0, 0, 0, 34, 0, 0, 0,245, 0, 0, 0,247, 0, 0, 0, 34,
+ 0, 0, 0,116, 0, 0, 0,246, 0, 0, 0, 34, 0, 0, 0,246, 0, 0, 0,248, 0, 0, 0, 34, 0, 0, 0,117, 0, 0, 0,243,
+ 0, 0, 0, 34, 0, 0, 0,243, 0, 0, 0,245, 0, 0, 0, 34, 0, 0, 0,118, 0, 0, 0,244, 0, 0, 0, 34, 0, 0, 0,244,
+ 0, 0, 0,246, 0, 0, 0, 34, 0, 0, 0,119, 0, 0, 0,241, 0, 0, 0, 34, 0, 0, 0,241, 0, 0, 0,243, 0, 0, 0, 34,
+ 0, 0, 0,120, 0, 0, 0,242, 0, 0, 0, 34, 0, 0, 0,242, 0, 0, 0,244, 0, 0, 0, 34, 0, 0, 0,121, 0, 0, 0,239,
+ 0, 0, 0, 34, 0, 0, 0,239, 0, 0, 0,241, 0, 0, 0, 34, 0, 0, 0,122, 0, 0, 0,240, 0, 0, 0, 34, 0, 0, 0,240,
+ 0, 0, 0,242, 0, 0, 0, 34, 0, 0, 0,123, 0, 0, 0,237, 0, 0, 0, 34, 0, 0, 0,237, 0, 0, 0,239, 0, 0, 0, 34,
+ 0, 0, 0,124, 0, 0, 0,238, 0, 0, 0, 34, 0, 0, 0,238, 0, 0, 0,240, 0, 0, 0, 34, 0, 0, 0,176, 0, 0, 0,233,
+ 0, 0, 0, 34, 0, 0, 0,233, 0, 0, 0,237, 0, 0, 0, 34, 0, 0, 0,177, 0, 0, 0,234, 0, 0, 0, 34, 0, 0, 0,234,
+ 0, 0, 0,238, 0, 0, 0, 34, 0, 0, 0,125, 0, 0, 0,235, 0, 0, 0, 34, 0, 0, 0,233, 0, 0, 0,235, 0, 0, 0, 34,
+ 0, 0, 0,126, 0, 0, 0,236, 0, 0, 0, 34, 0, 0, 0,234, 0, 0, 0,236, 0, 0, 0, 34, 0, 0, 0,235, 0, 0, 0,253,
+ 0, 0, 0, 34, 0, 0, 0,236, 0, 0, 0,254, 0, 0, 0, 34, 0, 0, 0,253, 0, 0, 0,255, 0, 0, 0, 34, 0, 0, 0,255,
+ 0, 0, 1, 17, 0, 0, 0, 34, 0, 0, 0,235, 0, 0, 1, 17, 0, 0, 0, 34, 0, 0, 0,254, 0, 0, 1, 0, 0, 0, 0, 34,
+ 0, 0, 0,236, 0, 0, 1, 18, 0, 0, 0, 34, 0, 0, 1, 0, 0, 0, 1, 18, 0, 0, 0, 34, 0, 0, 1, 17, 0, 0, 1, 19,
+ 0, 0, 0, 34, 0, 0, 0,233, 0, 0, 1, 19, 0, 0, 0, 34, 0, 0, 0,234, 0, 0, 1, 20, 0, 0, 0, 34, 0, 0, 1, 18,
+ 0, 0, 1, 20, 0, 0, 0, 34, 0, 0, 1, 15, 0, 0, 1, 19, 0, 0, 0, 34, 0, 0, 0,237, 0, 0, 1, 15, 0, 0, 0, 34,
+ 0, 0, 0,238, 0, 0, 1, 16, 0, 0, 0, 34, 0, 0, 1, 16, 0, 0, 1, 20, 0, 0, 0, 34, 0, 0, 1, 13, 0, 0, 1, 15,
+ 0, 0, 0, 34, 0, 0, 0,239, 0, 0, 1, 13, 0, 0, 0, 34, 0, 0, 0,240, 0, 0, 1, 14, 0, 0, 0, 34, 0, 0, 1, 14,
+ 0, 0, 1, 16, 0, 0, 0, 34, 0, 0, 1, 11, 0, 0, 1, 13, 0, 0, 0, 34, 0, 0, 0,241, 0, 0, 1, 11, 0, 0, 0, 34,
+ 0, 0, 0,242, 0, 0, 1, 12, 0, 0, 0, 34, 0, 0, 1, 12, 0, 0, 1, 14, 0, 0, 0, 34, 0, 0, 1, 9, 0, 0, 1, 11,
+ 0, 0, 0, 34, 0, 0, 0,243, 0, 0, 1, 9, 0, 0, 0, 34, 0, 0, 0,244, 0, 0, 1, 10, 0, 0, 0, 34, 0, 0, 1, 10,
+ 0, 0, 1, 12, 0, 0, 0, 34, 0, 0, 1, 7, 0, 0, 1, 9, 0, 0, 0, 34, 0, 0, 0,245, 0, 0, 1, 7, 0, 0, 0, 34,
+ 0, 0, 0,246, 0, 0, 1, 8, 0, 0, 0, 34, 0, 0, 1, 8, 0, 0, 1, 10, 0, 0, 0, 34, 0, 0, 1, 5, 0, 0, 1, 7,
+ 0, 0, 0, 34, 0, 0, 0,247, 0, 0, 1, 5, 0, 0, 0, 34, 0, 0, 0,248, 0, 0, 1, 6, 0, 0, 0, 34, 0, 0, 1, 6,
+ 0, 0, 1, 8, 0, 0, 0, 34, 0, 0, 1, 3, 0, 0, 1, 5, 0, 0, 0, 34, 0, 0, 0,249, 0, 0, 1, 3, 0, 0, 0, 34,
+ 0, 0, 0,250, 0, 0, 1, 4, 0, 0, 0, 34, 0, 0, 1, 4, 0, 0, 1, 6, 0, 0, 0, 34, 0, 0, 1, 3, 0, 0, 1, 21,
+ 0, 0, 0, 34, 0, 0, 0,231, 0, 0, 1, 21, 0, 0, 0, 34, 0, 0, 0,232, 0, 0, 1, 22, 0, 0, 0, 34, 0, 0, 1, 4,
+ 0, 0, 1, 22, 0, 0, 0, 34, 0, 0, 0,251, 0, 0, 1, 1, 0, 0, 0, 34, 0, 0, 0,255, 0, 0, 1, 1, 0, 0, 0, 34,
+ 0, 0, 0,252, 0, 0, 1, 2, 0, 0, 0, 34, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 0, 34, 0, 0, 0,229, 0, 0, 1, 23,
+ 0, 0, 0, 34, 0, 0, 1, 1, 0, 0, 1, 23, 0, 0, 0, 34, 0, 0, 0,230, 0, 0, 1, 24, 0, 0, 0, 34, 0, 0, 1, 2,
+ 0, 0, 1, 24, 0, 0, 0, 34, 0, 0, 1, 21, 0, 0, 1, 23, 0, 0, 0, 34, 0, 0, 1, 22, 0, 0, 1, 24, 0, 0, 0, 34,
+ 0, 0, 0,106, 0, 0, 1, 25, 0, 0, 0, 34, 0, 0, 0, 71, 0, 0, 1, 25, 0, 0, 0, 38, 0, 0, 0, 65, 0, 0, 0, 71,
+ 0, 0, 0, 34, 0, 0, 0,107, 0, 0, 1, 26, 0, 0, 0, 34, 0, 0, 0, 71, 0, 0, 1, 26, 0, 0, 0, 38, 0, 0, 0,104,
+ 0, 0, 1, 27, 0, 0, 0, 34, 0, 0, 1, 25, 0, 0, 1, 27, 0, 0, 0, 34, 0, 0, 0,105, 0, 0, 1, 28, 0, 0, 0, 34,
+ 0, 0, 1, 26, 0, 0, 1, 28, 0, 0, 0, 34, 0, 0, 0,102, 0, 0, 1, 29, 0, 0, 0, 34, 0, 0, 1, 27, 0, 0, 1, 29,
+ 0, 0, 0, 34, 0, 0, 0,103, 0, 0, 1, 30, 0, 0, 0, 34, 0, 0, 1, 28, 0, 0, 1, 30, 0, 0, 0, 34, 0, 0, 0,100,
+ 0, 0, 1, 31, 0, 0, 0, 34, 0, 0, 1, 29, 0, 0, 1, 31, 0, 0, 0, 34, 0, 0, 0,101, 0, 0, 1, 32, 0, 0, 0, 34,
+ 0, 0, 1, 30, 0, 0, 1, 32, 0, 0, 0, 34, 0, 0, 0, 98, 0, 0, 1, 33, 0, 0, 0, 34, 0, 0, 1, 31, 0, 0, 1, 33,
+ 0, 0, 0, 38, 0, 0, 0, 99, 0, 0, 1, 34, 0, 0, 0, 34, 0, 0, 1, 32, 0, 0, 1, 34, 0, 0, 0, 38, 0, 0, 0, 96,
+ 0, 0, 1, 35, 0, 0, 0, 34, 0, 0, 1, 33, 0, 0, 1, 35, 0, 0, 0, 34, 0, 0, 0, 97, 0, 0, 1, 36, 0, 0, 0, 34,
+ 0, 0, 1, 34, 0, 0, 1, 36, 0, 0, 0, 34, 0, 0, 0, 94, 0, 0, 1, 37, 0, 0, 0, 34, 0, 0, 1, 35, 0, 0, 1, 37,
+ 0, 0, 0, 34, 0, 0, 0, 95, 0, 0, 1, 38, 0, 0, 0, 34, 0, 0, 1, 36, 0, 0, 1, 38, 0, 0, 0, 34, 0, 0, 0, 92,
+ 0, 0, 1, 39, 0, 0, 0, 34, 0, 0, 1, 37, 0, 0, 1, 39, 0, 0, 0, 34, 0, 0, 0, 93, 0, 0, 1, 40, 0, 0, 0, 34,
+ 0, 0, 1, 38, 0, 0, 1, 40, 0, 0, 0, 34, 0, 0, 0, 90, 0, 0, 1, 41, 0, 0, 0, 34, 0, 0, 1, 39, 0, 0, 1, 41,
+ 0, 0, 0, 34, 0, 0, 0, 91, 0, 0, 1, 42, 0, 0, 0, 34, 0, 0, 1, 40, 0, 0, 1, 42, 0, 0, 0, 34, 0, 0, 1, 49,
+ 0, 0, 1, 50, 0, 0, 0, 38, 0, 0, 1, 50, 0, 0, 1, 69, 0, 0, 0, 34, 0, 0, 1, 69, 0, 0, 1, 79, 0, 0, 0, 34,
+ 0, 0, 1, 49, 0, 0, 1, 79, 0, 0, 0, 34, 0, 0, 1, 50, 0, 0, 1, 70, 0, 0, 0, 34, 0, 0, 1, 49, 0, 0, 1, 80,
+ 0, 0, 0, 34, 0, 0, 1, 70, 0, 0, 1, 80, 0, 0, 0, 34, 0, 0, 1, 48, 0, 0, 1, 49, 0, 0, 0, 38, 0, 0, 1, 77,
+ 0, 0, 1, 79, 0, 0, 0, 34, 0, 0, 1, 48, 0, 0, 1, 77, 0, 0, 0, 34, 0, 0, 1, 48, 0, 0, 1, 78, 0, 0, 0, 34,
+ 0, 0, 1, 78, 0, 0, 1, 80, 0, 0, 0, 34, 0, 0, 1, 47, 0, 0, 1, 48, 0, 0, 0, 38, 0, 0, 1, 77, 0, 0, 1, 81,
+ 0, 0, 0, 34, 0, 0, 1, 47, 0, 0, 1, 81, 0, 0, 0, 34, 0, 0, 1, 47, 0, 0, 1, 82, 0, 0, 0, 34, 0, 0, 1, 78,
+ 0, 0, 1, 82, 0, 0, 0, 34, 0, 0, 0, 89, 0, 0, 1, 47, 0, 0, 0, 38, 0, 0, 0, 87, 0, 0, 1, 81, 0, 0, 0, 34,
+ 0, 0, 0, 88, 0, 0, 1, 82, 0, 0, 0, 34, 0, 0, 1, 75, 0, 0, 1, 81, 0, 0, 0, 34, 0, 0, 0, 85, 0, 0, 1, 75,
+ 0, 0, 0, 34, 0, 0, 0, 86, 0, 0, 1, 76, 0, 0, 0, 34, 0, 0, 1, 76, 0, 0, 1, 82, 0, 0, 0, 34, 0, 0, 1, 71,
+ 0, 0, 1, 75, 0, 0, 0, 34, 0, 0, 0, 83, 0, 0, 1, 71, 0, 0, 0, 34, 0, 0, 0, 84, 0, 0, 1, 72, 0, 0, 0, 34,
+ 0, 0, 1, 72, 0, 0, 1, 76, 0, 0, 0, 34, 0, 0, 1, 71, 0, 0, 1, 73, 0, 0, 0, 34, 0, 0, 0, 81, 0, 0, 1, 73,
+ 0, 0, 0, 34, 0, 0, 0, 82, 0, 0, 1, 74, 0, 0, 0, 34, 0, 0, 1, 72, 0, 0, 1, 74, 0, 0, 0, 34, 0, 0, 1, 71,
+ 0, 0, 1, 77, 0, 0, 0, 34, 0, 0, 1, 73, 0, 0, 1, 79, 0, 0, 0, 34, 0, 0, 1, 72, 0, 0, 1, 78, 0, 0, 0, 34,
+ 0, 0, 1, 74, 0, 0, 1, 80, 0, 0, 0, 34, 0, 0, 1, 67, 0, 0, 1, 73, 0, 0, 0, 34, 0, 0, 1, 67, 0, 0, 1, 69,
+ 0, 0, 0, 34, 0, 0, 1, 68, 0, 0, 1, 74, 0, 0, 0, 34, 0, 0, 1, 68, 0, 0, 1, 70, 0, 0, 0, 34, 0, 0, 0, 79,
+ 0, 0, 1, 67, 0, 0, 0, 34, 0, 0, 0, 80, 0, 0, 1, 68, 0, 0, 0, 34, 0, 0, 0,206, 0, 0, 1, 83, 0, 0, 0, 34,
+ 0, 0, 1, 83, 0, 0, 1, 85, 0, 0, 0, 34, 0, 0, 0,212, 0, 0, 1, 85, 0, 0, 0, 34, 0, 0, 1, 84, 0, 0, 1, 86,
+ 0, 0, 0, 34, 0, 0, 0,207, 0, 0, 1, 84, 0, 0, 0, 34, 0, 0, 0,213, 0, 0, 1, 86, 0, 0, 0, 34, 0, 0, 1, 67,
+ 0, 0, 1, 83, 0, 0, 0, 34, 0, 0, 1, 68, 0, 0, 1, 84, 0, 0, 0, 34, 0, 0, 1, 85, 0, 0, 1, 87, 0, 0, 0, 34,
+ 0, 0, 0, 77, 0, 0, 1, 87, 0, 0, 0, 34, 0, 0, 0, 78, 0, 0, 1, 88, 0, 0, 0, 34, 0, 0, 1, 86, 0, 0, 1, 88,
+ 0, 0, 0, 34, 0, 0, 1, 41, 0, 0, 1, 87, 0, 0, 0, 34, 0, 0, 1, 42, 0, 0, 1, 88, 0, 0, 0, 34, 0, 0, 0, 75,
+ 0, 0, 1, 65, 0, 0, 0, 34, 0, 0, 1, 65, 0, 0, 1, 93, 0, 0, 0, 34, 0, 0, 1, 45, 0, 0, 1, 93, 0, 0, 0, 39,
+ 0, 0, 0, 75, 0, 0, 1, 45, 0, 0, 0, 38, 0, 0, 1, 66, 0, 0, 1, 94, 0, 0, 0, 34, 0, 0, 0, 75, 0, 0, 1, 66,
+ 0, 0, 0, 34, 0, 0, 1, 45, 0, 0, 1, 94, 0, 0, 0, 39, 0, 0, 1, 91, 0, 0, 1, 93, 0, 0, 0, 34, 0, 0, 0, 76,
+ 0, 0, 1, 91, 0, 0, 0, 34, 0, 0, 0, 76, 0, 0, 1, 45, 0, 0, 0, 38, 0, 0, 1, 92, 0, 0, 1, 94, 0, 0, 0, 34,
+ 0, 0, 0, 76, 0, 0, 1, 92, 0, 0, 0, 34, 0, 0, 1, 89, 0, 0, 1, 91, 0, 0, 0, 34, 0, 0, 1, 46, 0, 0, 1, 89,
+ 0, 0, 0, 34, 0, 0, 0, 76, 0, 0, 1, 46, 0, 0, 0, 38, 0, 0, 1, 90, 0, 0, 1, 92, 0, 0, 0, 34, 0, 0, 1, 46,
+ 0, 0, 1, 90, 0, 0, 0, 34, 0, 0, 1, 69, 0, 0, 1, 89, 0, 0, 0, 34, 0, 0, 1, 46, 0, 0, 1, 50, 0, 0, 0, 38,
+ 0, 0, 1, 70, 0, 0, 1, 90, 0, 0, 0, 34, 0, 0, 1, 83, 0, 0, 1, 89, 0, 0, 0, 34, 0, 0, 1, 84, 0, 0, 1, 90,
+ 0, 0, 0, 34, 0, 0, 1, 39, 0, 0, 1, 59, 0, 0, 0, 34, 0, 0, 1, 51, 0, 0, 1, 59, 0, 0, 0, 34, 0, 0, 1, 37,
+ 0, 0, 1, 51, 0, 0, 0, 34, 0, 0, 1, 40, 0, 0, 1, 60, 0, 0, 0, 34, 0, 0, 1, 38, 0, 0, 1, 52, 0, 0, 0, 34,
+ 0, 0, 1, 52, 0, 0, 1, 60, 0, 0, 0, 34, 0, 0, 0, 74, 0, 0, 1, 57, 0, 0, 0, 39, 0, 0, 1, 57, 0, 0, 1, 65,
+ 0, 0, 0, 34, 0, 0, 0, 74, 0, 0, 0, 75, 0, 0, 0, 38, 0, 0, 1, 58, 0, 0, 1, 66, 0, 0, 0, 34, 0, 0, 0, 74,
+ 0, 0, 1, 58, 0, 0, 0, 39, 0, 0, 1, 43, 0, 0, 1, 99, 0, 0, 0, 34, 0, 0, 1, 97, 0, 0, 1, 99, 0, 0, 0, 34,
+ 0, 0, 1, 44, 0, 0, 1, 97, 0, 0, 0, 34, 0, 0, 1, 43, 0, 0, 1, 44, 0, 0, 0, 38, 0, 0, 1, 98, 0, 0, 1,100,
+ 0, 0, 0, 34, 0, 0, 1, 43, 0, 0, 1,100, 0, 0, 0, 34, 0, 0, 1, 44, 0, 0, 1, 98, 0, 0, 0, 34, 0, 0, 1, 95,
+ 0, 0, 1, 97, 0, 0, 0, 34, 0, 0, 0, 73, 0, 0, 1, 95, 0, 0, 0, 34, 0, 0, 0, 73, 0, 0, 1, 44, 0, 0, 0, 38,
+ 0, 0, 1, 96, 0, 0, 1, 98, 0, 0, 0, 34, 0, 0, 0, 73, 0, 0, 1, 96, 0, 0, 0, 34, 0, 0, 1, 57, 0, 0, 1, 95,
+ 0, 0, 0, 34, 0, 0, 0, 73, 0, 0, 0, 74, 0, 0, 0, 38, 0, 0, 1, 58, 0, 0, 1, 96, 0, 0, 0, 34, 0, 0, 1, 35,
+ 0, 0, 1,103, 0, 0, 0, 34, 0, 0, 1,103, 0, 0, 1,105, 0, 0, 0, 34, 0, 0, 1, 33, 0, 0, 1,105, 0, 0, 0, 34,
+ 0, 0, 1, 36, 0, 0, 1,104, 0, 0, 0, 34, 0, 0, 1, 34, 0, 0, 1,106, 0, 0, 0, 34, 0, 0, 1,104, 0, 0, 1,106,
+ 0, 0, 0, 34, 0, 0, 1,103, 0, 0, 1,109, 0, 0, 0, 34, 0, 0, 1,107, 0, 0, 1,109, 0, 0, 0, 34, 0, 0, 1,105,
+ 0, 0, 1,107, 0, 0, 0, 34, 0, 0, 1,104, 0, 0, 1,110, 0, 0, 0, 34, 0, 0, 1,106, 0, 0, 1,108, 0, 0, 0, 34,
+ 0, 0, 1,108, 0, 0, 1,110, 0, 0, 0, 34, 0, 0, 1,109, 0, 0, 1,111, 0, 0, 0, 34, 0, 0, 1,111, 0, 0, 1,113,
+ 0, 0, 0, 34, 0, 0, 1,107, 0, 0, 1,113, 0, 0, 0, 34, 0, 0, 1,110, 0, 0, 1,112, 0, 0, 0, 34, 0, 0, 1,108,
+ 0, 0, 1,114, 0, 0, 0, 34, 0, 0, 1,112, 0, 0, 1,114, 0, 0, 0, 34, 0, 0, 1,111, 0, 0, 1,117, 0, 0, 0, 34,
+ 0, 0, 1,115, 0, 0, 1,117, 0, 0, 0, 34, 0, 0, 1,113, 0, 0, 1,115, 0, 0, 0, 34, 0, 0, 1,112, 0, 0, 1,118,
+ 0, 0, 0, 34, 0, 0, 1,114, 0, 0, 1,116, 0, 0, 0, 34, 0, 0, 1,116, 0, 0, 1,118, 0, 0, 0, 34, 0, 0, 1, 55,
+ 0, 0, 1,119, 0, 0, 0, 39, 0, 0, 1,115, 0, 0, 1,119, 0, 0, 0, 34, 0, 0, 1, 55, 0, 0, 1,117, 0, 0, 0, 34,
+ 0, 0, 1,116, 0, 0, 1,120, 0, 0, 0, 34, 0, 0, 1, 56, 0, 0, 1,120, 0, 0, 0, 39, 0, 0, 1, 56, 0, 0, 1,118,
+ 0, 0, 0, 34, 0, 0, 1, 95, 0, 0, 1,115, 0, 0, 0, 34, 0, 0, 1, 57, 0, 0, 1,119, 0, 0, 0, 39, 0, 0, 1, 96,
+ 0, 0, 1,116, 0, 0, 0, 34, 0, 0, 1, 58, 0, 0, 1,120, 0, 0, 0, 39, 0, 0, 1, 97, 0, 0, 1,113, 0, 0, 0, 34,
+ 0, 0, 1, 98, 0, 0, 1,114, 0, 0, 0, 34, 0, 0, 1, 99, 0, 0, 1,107, 0, 0, 0, 34, 0, 0, 1,100, 0, 0, 1,108,
+ 0, 0, 0, 34, 0, 0, 1, 99, 0, 0, 1,101, 0, 0, 0, 34, 0, 0, 1,101, 0, 0, 1,105, 0, 0, 0, 34, 0, 0, 1,102,
+ 0, 0, 1,106, 0, 0, 0, 34, 0, 0, 1,100, 0, 0, 1,102, 0, 0, 0, 34, 0, 0, 1, 31, 0, 0, 1,101, 0, 0, 0, 34,
+ 0, 0, 1, 32, 0, 0, 1,102, 0, 0, 0, 34, 0, 0, 0, 72, 0, 0, 1,101, 0, 0, 0, 34, 0, 0, 0, 72, 0, 0, 1, 43,
+ 0, 0, 0, 38, 0, 0, 0, 72, 0, 0, 1,102, 0, 0, 0, 34, 0, 0, 1, 25, 0, 0, 1, 31, 0, 0, 0, 38, 0, 0, 1, 26,
+ 0, 0, 1, 32, 0, 0, 0, 38, 0, 0, 0, 72, 0, 0, 1, 25, 0, 0, 0, 34, 0, 0, 0, 72, 0, 0, 1, 26, 0, 0, 0, 34,
+ 0, 0, 0, 71, 0, 0, 0, 72, 0, 0, 0, 38, 0, 0, 1, 51, 0, 0, 1,103, 0, 0, 0, 34, 0, 0, 1, 52, 0, 0, 1,104,
+ 0, 0, 0, 34, 0, 0, 1, 51, 0, 0, 1, 53, 0, 0, 0, 34, 0, 0, 1, 53, 0, 0, 1,109, 0, 0, 0, 34, 0, 0, 1, 54,
+ 0, 0, 1,110, 0, 0, 0, 34, 0, 0, 1, 52, 0, 0, 1, 54, 0, 0, 0, 34, 0, 0, 1, 53, 0, 0, 1,123, 0, 0, 0, 34,
+ 0, 0, 1,111, 0, 0, 1,123, 0, 0, 0, 34, 0, 0, 1,112, 0, 0, 1,124, 0, 0, 0, 34, 0, 0, 1, 54, 0, 0, 1,124,
+ 0, 0, 0, 34, 0, 0, 1, 55, 0, 0, 1,123, 0, 0, 0, 34, 0, 0, 1, 56, 0, 0, 1,124, 0, 0, 0, 34, 0, 0, 1, 91,
+ 0, 0, 1,127, 0, 0, 0, 34, 0, 0, 1,125, 0, 0, 1,127, 0, 0, 0, 34, 0, 0, 1, 89, 0, 0, 1,125, 0, 0, 0, 34,
+ 0, 0, 1, 92, 0, 0, 1,128, 0, 0, 0, 34, 0, 0, 1, 90, 0, 0, 1,126, 0, 0, 0, 34, 0, 0, 1,126, 0, 0, 1,128,
+ 0, 0, 0, 34, 0, 0, 1, 59, 0, 0, 1,125, 0, 0, 0, 34, 0, 0, 1, 61, 0, 0, 1,127, 0, 0, 0, 34, 0, 0, 1, 59,
+ 0, 0, 1, 61, 0, 0, 0, 34, 0, 0, 1, 60, 0, 0, 1,126, 0, 0, 0, 34, 0, 0, 1, 60, 0, 0, 1, 62, 0, 0, 0, 34,
+ 0, 0, 1, 62, 0, 0, 1,128, 0, 0, 0, 34, 0, 0, 1, 41, 0, 0, 1,125, 0, 0, 0, 34, 0, 0, 1, 42, 0, 0, 1,126,
+ 0, 0, 0, 34, 0, 0, 1, 41, 0, 0, 1, 85, 0, 0, 0, 34, 0, 0, 1, 83, 0, 0, 1,125, 0, 0, 0, 34, 0, 0, 1, 42,
+ 0, 0, 1, 86, 0, 0, 0, 34, 0, 0, 1, 84, 0, 0, 1,126, 0, 0, 0, 34, 0, 0, 1, 55, 0, 0, 1, 63, 0, 0, 0, 34,
+ 0, 0, 1, 63, 0, 0, 1,121, 0, 0, 0, 39, 0, 0, 1,119, 0, 0, 1,121, 0, 0, 0, 34, 0, 0, 1, 64, 0, 0, 1,122,
+ 0, 0, 0, 39, 0, 0, 1, 56, 0, 0, 1, 64, 0, 0, 0, 34, 0, 0, 1,120, 0, 0, 1,122, 0, 0, 0, 34, 0, 0, 1, 65,
+ 0, 0, 1,121, 0, 0, 0, 34, 0, 0, 1, 66, 0, 0, 1,122, 0, 0, 0, 34, 0, 0, 1,121, 0, 0, 1,127, 0, 0, 0, 34,
+ 0, 0, 1, 61, 0, 0, 1, 63, 0, 0, 0, 34, 0, 0, 1,122, 0, 0, 1,128, 0, 0, 0, 34, 0, 0, 1, 62, 0, 0, 1, 64,
+ 0, 0, 0, 34, 0, 0, 1, 93, 0, 0, 1,121, 0, 0, 0, 39, 0, 0, 1, 94, 0, 0, 1,122, 0, 0, 0, 39, 0, 0, 1,129,
+ 0, 0, 1,141, 0, 0, 0, 34, 0, 0, 1,129, 0, 0, 1,155, 0, 0, 0, 34, 0, 0, 1,143, 0, 0, 1,155, 0, 0, 0, 34,
+ 0, 0, 1,141, 0, 0, 1,143, 0, 0, 0, 34, 0, 0, 1,130, 0, 0, 1,156, 0, 0, 0, 34, 0, 0, 1,130, 0, 0, 1,142,
+ 0, 0, 0, 34, 0, 0, 1,142, 0, 0, 1,144, 0, 0, 0, 34, 0, 0, 1,144, 0, 0, 1,156, 0, 0, 0, 34, 0, 0, 1,143,
+ 0, 0, 1,145, 0, 0, 0, 34, 0, 0, 1,139, 0, 0, 1,145, 0, 0, 0, 34, 0, 0, 1,139, 0, 0, 1,141, 0, 0, 0, 34,
+ 0, 0, 1,144, 0, 0, 1,146, 0, 0, 0, 34, 0, 0, 1,140, 0, 0, 1,142, 0, 0, 0, 34, 0, 0, 1,140, 0, 0, 1,146,
+ 0, 0, 0, 34, 0, 0, 1,145, 0, 0, 1,147, 0, 0, 0, 34, 0, 0, 1,137, 0, 0, 1,147, 0, 0, 0, 34, 0, 0, 1,137,
+ 0, 0, 1,139, 0, 0, 0, 34, 0, 0, 1,146, 0, 0, 1,148, 0, 0, 0, 34, 0, 0, 1,138, 0, 0, 1,140, 0, 0, 0, 34,
+ 0, 0, 1,138, 0, 0, 1,148, 0, 0, 0, 34, 0, 0, 1,147, 0, 0, 1,149, 0, 0, 0, 34, 0, 0, 1,135, 0, 0, 1,149,
+ 0, 0, 0, 34, 0, 0, 1,135, 0, 0, 1,137, 0, 0, 0, 34, 0, 0, 1,148, 0, 0, 1,150, 0, 0, 0, 34, 0, 0, 1,136,
+ 0, 0, 1,138, 0, 0, 0, 34, 0, 0, 1,136, 0, 0, 1,150, 0, 0, 0, 34, 0, 0, 1,149, 0, 0, 1,151, 0, 0, 0, 34,
+ 0, 0, 1,133, 0, 0, 1,151, 0, 0, 0, 34, 0, 0, 1,133, 0, 0, 1,135, 0, 0, 0, 34, 0, 0, 1,150, 0, 0, 1,152,
+ 0, 0, 0, 34, 0, 0, 1,134, 0, 0, 1,136, 0, 0, 0, 34, 0, 0, 1,134, 0, 0, 1,152, 0, 0, 0, 34, 0, 0, 1,151,
+ 0, 0, 1,153, 0, 0, 0, 34, 0, 0, 1,131, 0, 0, 1,153, 0, 0, 0, 34, 0, 0, 1,131, 0, 0, 1,133, 0, 0, 0, 34,
+ 0, 0, 1,152, 0, 0, 1,154, 0, 0, 0, 34, 0, 0, 1,132, 0, 0, 1,134, 0, 0, 0, 34, 0, 0, 1,132, 0, 0, 1,154,
+ 0, 0, 0, 34, 0, 0, 1,151, 0, 0, 1,161, 0, 0, 0, 34, 0, 0, 1,159, 0, 0, 1,161, 0, 0, 0, 34, 0, 0, 1,153,
+ 0, 0, 1,159, 0, 0, 0, 34, 0, 0, 1,160, 0, 0, 1,162, 0, 0, 0, 34, 0, 0, 1,152, 0, 0, 1,162, 0, 0, 0, 34,
+ 0, 0, 1,154, 0, 0, 1,160, 0, 0, 0, 34, 0, 0, 1,149, 0, 0, 1,163, 0, 0, 0, 34, 0, 0, 1,161, 0, 0, 1,163,
+ 0, 0, 0, 34, 0, 0, 1,162, 0, 0, 1,164, 0, 0, 0, 34, 0, 0, 1,150, 0, 0, 1,164, 0, 0, 0, 34, 0, 0, 1,147,
+ 0, 0, 1,165, 0, 0, 0, 34, 0, 0, 1,163, 0, 0, 1,165, 0, 0, 0, 34, 0, 0, 1,164, 0, 0, 1,166, 0, 0, 0, 34,
+ 0, 0, 1,148, 0, 0, 1,166, 0, 0, 0, 34, 0, 0, 1,145, 0, 0, 1,167, 0, 0, 0, 34, 0, 0, 1,165, 0, 0, 1,167,
+ 0, 0, 0, 34, 0, 0, 1,166, 0, 0, 1,168, 0, 0, 0, 34, 0, 0, 1,146, 0, 0, 1,168, 0, 0, 0, 34, 0, 0, 1,143,
+ 0, 0, 1,169, 0, 0, 0, 34, 0, 0, 1,167, 0, 0, 1,169, 0, 0, 0, 34, 0, 0, 1,168, 0, 0, 1,170, 0, 0, 0, 34,
+ 0, 0, 1,144, 0, 0, 1,170, 0, 0, 0, 34, 0, 0, 1,155, 0, 0, 1,157, 0, 0, 0, 34, 0, 0, 1,157, 0, 0, 1,169,
+ 0, 0, 0, 34, 0, 0, 1,156, 0, 0, 1,158, 0, 0, 0, 34, 0, 0, 1,158, 0, 0, 1,170, 0, 0, 0, 34, 0, 0, 1, 61,
+ 0, 0, 1,185, 0, 0, 0, 34, 0, 0, 1,183, 0, 0, 1,185, 0, 0, 0, 34, 0, 0, 1, 59, 0, 0, 1,183, 0, 0, 0, 34,
+ 0, 0, 1, 62, 0, 0, 1,186, 0, 0, 0, 34, 0, 0, 1, 60, 0, 0, 1,184, 0, 0, 0, 34, 0, 0, 1,184, 0, 0, 1,186,
+ 0, 0, 0, 34, 0, 0, 1, 61, 0, 0, 1,131, 0, 0, 0, 34, 0, 0, 1,153, 0, 0, 1,185, 0, 0, 0, 34, 0, 0, 1, 62,
+ 0, 0, 1,132, 0, 0, 0, 34, 0, 0, 1,154, 0, 0, 1,186, 0, 0, 0, 34, 0, 0, 1, 53, 0, 0, 1,183, 0, 0, 0, 34,
+ 0, 0, 1, 54, 0, 0, 1,184, 0, 0, 0, 34, 0, 0, 1,123, 0, 0, 1,171, 0, 0, 0, 34, 0, 0, 1,155, 0, 0, 1,171,
+ 0, 0, 0, 34, 0, 0, 1,123, 0, 0, 1,129, 0, 0, 0, 34, 0, 0, 1,156, 0, 0, 1,172, 0, 0, 0, 34, 0, 0, 1,124,
+ 0, 0, 1,172, 0, 0, 0, 34, 0, 0, 1,124, 0, 0, 1,130, 0, 0, 0, 34, 0, 0, 1,159, 0, 0, 1,181, 0, 0, 0, 34,
+ 0, 0, 1,181, 0, 0, 1,185, 0, 0, 0, 34, 0, 0, 1,160, 0, 0, 1,182, 0, 0, 0, 34, 0, 0, 1,182, 0, 0, 1,186,
+ 0, 0, 0, 34, 0, 0, 1,179, 0, 0, 1,187, 0, 0, 0, 34, 0, 0, 1,185, 0, 0, 1,187, 0, 0, 0, 34, 0, 0, 1,179,
+ 0, 0, 1,181, 0, 0, 0, 34, 0, 0, 1,186, 0, 0, 1,188, 0, 0, 0, 34, 0, 0, 1,180, 0, 0, 1,188, 0, 0, 0, 34,
+ 0, 0, 1,180, 0, 0, 1,182, 0, 0, 0, 34, 0, 0, 1,175, 0, 0, 1,187, 0, 0, 0, 34, 0, 0, 1,177, 0, 0, 1,179,
+ 0, 0, 0, 34, 0, 0, 1,175, 0, 0, 1,177, 0, 0, 0, 34, 0, 0, 1,176, 0, 0, 1,188, 0, 0, 0, 34, 0, 0, 1,176,
+ 0, 0, 1,178, 0, 0, 0, 34, 0, 0, 1,178, 0, 0, 1,180, 0, 0, 0, 34, 0, 0, 1,173, 0, 0, 1,189, 0, 0, 0, 34,
+ 0, 0, 1,187, 0, 0, 1,189, 0, 0, 0, 34, 0, 0, 1,173, 0, 0, 1,175, 0, 0, 0, 34, 0, 0, 1,188, 0, 0, 1,190,
+ 0, 0, 0, 34, 0, 0, 1,174, 0, 0, 1,190, 0, 0, 0, 34, 0, 0, 1,174, 0, 0, 1,176, 0, 0, 0, 34, 0, 0, 1,171,
+ 0, 0, 1,189, 0, 0, 0, 34, 0, 0, 1,173, 0, 0, 1,191, 0, 0, 0, 34, 0, 0, 1,171, 0, 0, 1,191, 0, 0, 0, 32,
+ 0, 0, 1,172, 0, 0, 1,190, 0, 0, 0, 34, 0, 0, 1,172, 0, 0, 1,192, 0, 0, 0, 32, 0, 0, 1,174, 0, 0, 1,192,
+ 0, 0, 0, 34, 0, 0, 1,157, 0, 0, 1,191, 0, 0, 0, 34, 0, 0, 1,158, 0, 0, 1,192, 0, 0, 0, 34, 0, 0, 1, 53,
+ 0, 0, 1,189, 0, 0, 0, 34, 0, 0, 1, 54, 0, 0, 1,190, 0, 0, 0, 34, 0, 0, 1,183, 0, 0, 1,187, 0, 0, 0, 34,
+ 0, 0, 1,184, 0, 0, 1,188, 0, 0, 0, 34, 0, 0, 1,191, 0, 0, 1,193, 0, 0, 0, 34, 0, 0, 1,193, 0, 0, 1,217,
+ 0, 0, 0, 34, 0, 0, 1,157, 0, 0, 1,217, 0, 0, 0, 34, 0, 0, 1,192, 0, 0, 1,194, 0, 0, 0, 34, 0, 0, 1,158,
+ 0, 0, 1,218, 0, 0, 0, 34, 0, 0, 1,194, 0, 0, 1,218, 0, 0, 0, 34, 0, 0, 1,173, 0, 0, 1,203, 0, 0, 0, 34,
+ 0, 0, 1,193, 0, 0, 1,203, 0, 0, 0, 34, 0, 0, 1,174, 0, 0, 1,204, 0, 0, 0, 34, 0, 0, 1,194, 0, 0, 1,204,
+ 0, 0, 0, 34, 0, 0, 1,175, 0, 0, 1,201, 0, 0, 0, 34, 0, 0, 1,201, 0, 0, 1,203, 0, 0, 0, 34, 0, 0, 1,176,
+ 0, 0, 1,202, 0, 0, 0, 34, 0, 0, 1,202, 0, 0, 1,204, 0, 0, 0, 34, 0, 0, 1,177, 0, 0, 1,199, 0, 0, 0, 34,
+ 0, 0, 1,199, 0, 0, 1,201, 0, 0, 0, 34, 0, 0, 1,178, 0, 0, 1,200, 0, 0, 0, 34, 0, 0, 1,200, 0, 0, 1,202,
+ 0, 0, 0, 34, 0, 0, 1,179, 0, 0, 1,197, 0, 0, 0, 34, 0, 0, 1,197, 0, 0, 1,199, 0, 0, 0, 34, 0, 0, 1,180,
+ 0, 0, 1,198, 0, 0, 0, 34, 0, 0, 1,198, 0, 0, 1,200, 0, 0, 0, 34, 0, 0, 1,181, 0, 0, 1,195, 0, 0, 0, 34,
+ 0, 0, 1,195, 0, 0, 1,197, 0, 0, 0, 34, 0, 0, 1,182, 0, 0, 1,196, 0, 0, 0, 34, 0, 0, 1,196, 0, 0, 1,198,
+ 0, 0, 0, 34, 0, 0, 1,159, 0, 0, 1,215, 0, 0, 0, 34, 0, 0, 1,195, 0, 0, 1,215, 0, 0, 0, 34, 0, 0, 1,160,
+ 0, 0, 1,216, 0, 0, 0, 34, 0, 0, 1,196, 0, 0, 1,216, 0, 0, 0, 34, 0, 0, 1,205, 0, 0, 1,217, 0, 0, 0, 34,
+ 0, 0, 1,169, 0, 0, 1,205, 0, 0, 0, 34, 0, 0, 1,170, 0, 0, 1,206, 0, 0, 0, 34, 0, 0, 1,206, 0, 0, 1,218,
+ 0, 0, 0, 34, 0, 0, 1,205, 0, 0, 1,207, 0, 0, 0, 34, 0, 0, 1,167, 0, 0, 1,207, 0, 0, 0, 34, 0, 0, 1,168,
+ 0, 0, 1,208, 0, 0, 0, 34, 0, 0, 1,206, 0, 0, 1,208, 0, 0, 0, 34, 0, 0, 1,207, 0, 0, 1,209, 0, 0, 0, 34,
+ 0, 0, 1,165, 0, 0, 1,209, 0, 0, 0, 34, 0, 0, 1,166, 0, 0, 1,210, 0, 0, 0, 34, 0, 0, 1,208, 0, 0, 1,210,
+ 0, 0, 0, 34, 0, 0, 1,209, 0, 0, 1,211, 0, 0, 0, 34, 0, 0, 1,163, 0, 0, 1,211, 0, 0, 0, 34, 0, 0, 1,164,
+ 0, 0, 1,212, 0, 0, 0, 34, 0, 0, 1,210, 0, 0, 1,212, 0, 0, 0, 34, 0, 0, 1,211, 0, 0, 1,213, 0, 0, 0, 34,
+ 0, 0, 1,161, 0, 0, 1,213, 0, 0, 0, 34, 0, 0, 1,162, 0, 0, 1,214, 0, 0, 0, 34, 0, 0, 1,212, 0, 0, 1,214,
+ 0, 0, 0, 34, 0, 0, 1,213, 0, 0, 1,215, 0, 0, 0, 34, 0, 0, 1,214, 0, 0, 1,216, 0, 0, 0, 34, 0, 0, 1,197,
+ 0, 0, 1,221, 0, 0, 0, 34, 0, 0, 1,219, 0, 0, 1,221, 0, 0, 0, 34, 0, 0, 1,199, 0, 0, 1,219, 0, 0, 0, 34,
+ 0, 0, 1,198, 0, 0, 1,222, 0, 0, 0, 34, 0, 0, 1,200, 0, 0, 1,220, 0, 0, 0, 34, 0, 0, 1,220, 0, 0, 1,222,
+ 0, 0, 0, 34, 0, 0, 1,221, 0, 0, 1,223, 0, 0, 0, 34, 0, 0, 1,223, 0, 0, 1,225, 0, 0, 0, 32, 0, 0, 1,219,
+ 0, 0, 1,225, 0, 0, 0, 34, 0, 0, 1,222, 0, 0, 1,224, 0, 0, 0, 34, 0, 0, 1,220, 0, 0, 1,226, 0, 0, 0, 34,
+ 0, 0, 1,224, 0, 0, 1,226, 0, 0, 0, 32, 0, 0, 1,223, 0, 0, 1,229, 0, 0, 0, 34, 0, 0, 1,227, 0, 0, 1,229,
+ 0, 0, 0, 34, 0, 0, 1,225, 0, 0, 1,227, 0, 0, 0, 34, 0, 0, 1,224, 0, 0, 1,230, 0, 0, 0, 34, 0, 0, 1,226,
+ 0, 0, 1,228, 0, 0, 0, 34, 0, 0, 1,228, 0, 0, 1,230, 0, 0, 0, 34, 0, 0, 1,229, 0, 0, 1,231, 0, 0, 0, 34,
+ 0, 0, 1,231, 0, 0, 1,233, 0, 0, 0, 34, 0, 0, 1,227, 0, 0, 1,233, 0, 0, 0, 34, 0, 0, 1,230, 0, 0, 1,232,
+ 0, 0, 0, 34, 0, 0, 1,228, 0, 0, 1,234, 0, 0, 0, 34, 0, 0, 1,232, 0, 0, 1,234, 0, 0, 0, 34, 0, 0, 1,217,
+ 0, 0, 1,227, 0, 0, 0, 34, 0, 0, 1,205, 0, 0, 1,233, 0, 0, 0, 34, 0, 0, 1,218, 0, 0, 1,228, 0, 0, 0, 34,
+ 0, 0, 1,206, 0, 0, 1,234, 0, 0, 0, 34, 0, 0, 1,193, 0, 0, 1,225, 0, 0, 0, 34, 0, 0, 1,194, 0, 0, 1,226,
+ 0, 0, 0, 34, 0, 0, 1,203, 0, 0, 1,219, 0, 0, 0, 34, 0, 0, 1,204, 0, 0, 1,220, 0, 0, 0, 34, 0, 0, 1,215,
+ 0, 0, 1,221, 0, 0, 0, 34, 0, 0, 1,216, 0, 0, 1,222, 0, 0, 0, 34, 0, 0, 1,213, 0, 0, 1,223, 0, 0, 0, 34,
+ 0, 0, 1,214, 0, 0, 1,224, 0, 0, 0, 34, 0, 0, 1,211, 0, 0, 1,229, 0, 0, 0, 34, 0, 0, 1,212, 0, 0, 1,230,
+ 0, 0, 0, 34, 0, 0, 1,209, 0, 0, 1,231, 0, 0, 0, 34, 0, 0, 1,210, 0, 0, 1,232, 0, 0, 0, 34, 0, 0, 1,207,
+ 0, 0, 1,233, 0, 0, 0, 34, 0, 0, 1,208, 0, 0, 1,234, 0, 0, 0, 34, 0, 0, 1,131, 0, 0, 1,245, 0, 0, 0, 34,
+ 0, 0, 1,243, 0, 0, 1,245, 0, 0, 0, 39, 0, 0, 1,133, 0, 0, 1,243, 0, 0, 0, 34, 0, 0, 1,132, 0, 0, 1,246,
+ 0, 0, 0, 34, 0, 0, 1,134, 0, 0, 1,244, 0, 0, 0, 34, 0, 0, 1,244, 0, 0, 1,246, 0, 0, 0, 39, 0, 0, 1,241,
+ 0, 0, 1,243, 0, 0, 0, 39, 0, 0, 1,135, 0, 0, 1,241, 0, 0, 0, 34, 0, 0, 1,136, 0, 0, 1,242, 0, 0, 0, 34,
+ 0, 0, 1,242, 0, 0, 1,244, 0, 0, 0, 39, 0, 0, 1,239, 0, 0, 1,241, 0, 0, 0, 39, 0, 0, 1,137, 0, 0, 1,239,
+ 0, 0, 0, 34, 0, 0, 1,138, 0, 0, 1,240, 0, 0, 0, 34, 0, 0, 1,240, 0, 0, 1,242, 0, 0, 0, 39, 0, 0, 1,237,
+ 0, 0, 1,239, 0, 0, 0, 39, 0, 0, 1,139, 0, 0, 1,237, 0, 0, 0, 34, 0, 0, 1,140, 0, 0, 1,238, 0, 0, 0, 34,
+ 0, 0, 1,238, 0, 0, 1,240, 0, 0, 0, 39, 0, 0, 1,235, 0, 0, 1,237, 0, 0, 0, 39, 0, 0, 1,141, 0, 0, 1,235,
+ 0, 0, 0, 34, 0, 0, 1,142, 0, 0, 1,236, 0, 0, 0, 34, 0, 0, 1,236, 0, 0, 1,238, 0, 0, 0, 39, 0, 0, 1,235,
+ 0, 0, 1,247, 0, 0, 0, 39, 0, 0, 1,129, 0, 0, 1,247, 0, 0, 0, 34, 0, 0, 1,130, 0, 0, 1,248, 0, 0, 0, 34,
+ 0, 0, 1,236, 0, 0, 1,248, 0, 0, 0, 39, 0, 0, 1,235, 0, 0, 1,243, 0, 0, 0, 34, 0, 0, 1,245, 0, 0, 1,247,
+ 0, 0, 0, 34, 0, 0, 1,236, 0, 0, 1,244, 0, 0, 0, 34, 0, 0, 1,246, 0, 0, 1,248, 0, 0, 0, 34, 0, 0, 1,237,
+ 0, 0, 1,241, 0, 0, 0, 34, 0, 0, 1,238, 0, 0, 1,242, 0, 0, 0, 34, 0, 0, 1, 55, 0, 0, 1,247, 0, 0, 0, 39,
+ 0, 0, 1, 56, 0, 0, 1,248, 0, 0, 0, 39, 0, 0, 1, 63, 0, 0, 1,245, 0, 0, 0, 39, 0, 0, 1, 64, 0, 0, 1,246,
+ 0, 0, 0, 39, 0, 0, 0, 14, 0, 0, 0,249, 0, 0, 0, 34, 0, 0, 0, 14, 0, 0, 0,178, 0, 0, 0, 34, 0, 0, 0, 14,
+ 0, 0, 0,113, 0, 0, 0, 34, 0, 0, 0, 14, 0, 0, 0,161, 0, 0, 0, 34, 0, 0, 0, 20, 0, 0, 0,112, 0, 0, 0, 34,
+ 0, 0, 0, 16, 0, 0, 0,112, 0, 0, 0, 34, 0, 0, 0, 9, 0, 0, 0,112, 0, 0, 0, 34, 0, 0, 0, 13, 0, 0, 0,112,
+ 0, 0, 0, 34, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,108,112, 0, 0, 1, 35, 0, 0, 0, 5, 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, 7,160,128, 32, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 86, 84,101,120, 0, 0, 0, 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,117,208, 32, 0, 0, 0, 6, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 67,111,108, 0, 0, 0, 0, 0, 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,160,168, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 39, 16, 7,160,128, 32, 0, 0, 0, 54, 0, 0, 1,244, 0, 0, 0, 45, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 43, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 46, 0, 0, 0, 44, 0, 0, 0, 1,
+ 0, 0, 0, 43, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 41, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 44,
+ 0, 0, 0, 42, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 7,
+ 0, 0, 0, 9, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 8, 0, 0, 0, 2,
+ 0, 0, 0, 1, 0, 0, 0, 9, 0, 0, 0, 11, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0, 12,
+ 0, 0, 0, 14, 0, 0, 0, 8, 0, 0, 0, 1, 0, 0, 0,112, 0, 0, 0, 13, 0, 0, 0, 11, 0, 0, 0, 9, 0, 0, 0, 1,
+ 0, 0, 0, 8, 0, 0, 0, 14, 0, 0, 0, 15, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 16, 0, 0, 0,112, 0, 0, 0, 9,
+ 0, 0, 0, 7, 0, 0, 0, 1, 0, 0, 0, 14, 0, 0, 0, 19, 0, 0, 0, 17, 0, 0, 0, 15, 0, 0, 0, 1, 0, 0, 0, 18,
+ 0, 0, 0, 20, 0, 0, 0,112, 0, 0, 0, 16, 0, 0, 0, 1, 0, 0, 0, 12, 0, 0, 0, 21, 0, 0, 0, 19, 0, 0, 0, 14,
+ 0, 0, 0, 1, 0, 0, 0, 20, 0, 0, 0, 22, 0, 0, 0, 13, 0, 0, 0,112, 0, 0, 0, 1, 0, 0, 0, 21, 0, 0, 0, 23,
+ 0, 0, 0, 25, 0, 0, 0, 19, 0, 0, 0, 1, 0, 0, 0, 26, 0, 0, 0, 24, 0, 0, 0, 22, 0, 0, 0, 20, 0, 0, 0, 1,
+ 0, 0, 0, 19, 0, 0, 0, 25, 0, 0, 0, 27, 0, 0, 0, 17, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0, 26, 0, 0, 0, 20,
+ 0, 0, 0, 18, 0, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 31, 0, 0, 0, 29, 0, 0, 0, 27, 0, 0, 0, 1, 0, 0, 0, 30,
+ 0, 0, 0, 32, 0, 0, 0, 26, 0, 0, 0, 28, 0, 0, 0, 1, 0, 0, 0, 23, 0, 0, 0, 33, 0, 0, 0, 31, 0, 0, 0, 25,
+ 0, 0, 0, 1, 0, 0, 0, 32, 0, 0, 0, 34, 0, 0, 0, 24, 0, 0, 0, 26, 0, 0, 0, 1, 0, 0, 0, 33, 0, 0, 0, 35,
+ 0, 0, 0, 37, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 38, 0, 0, 0, 36, 0, 0, 0, 34, 0, 0, 0, 32, 0, 0, 0, 1,
+ 0, 0, 0, 31, 0, 0, 0, 37, 0, 0, 0, 39, 0, 0, 0, 29, 0, 0, 0, 1, 0, 0, 0, 40, 0, 0, 0, 38, 0, 0, 0, 32,
+ 0, 0, 0, 30, 0, 0, 0, 1, 0, 0, 0, 37, 0, 0, 0, 43, 0, 0, 0, 41, 0, 0, 0, 39, 0, 0, 0, 1, 0, 0, 0, 42,
+ 0, 0, 0, 44, 0, 0, 0, 38, 0, 0, 0, 40, 0, 0, 0, 1, 0, 0, 0, 35, 0, 0, 0, 45, 0, 0, 0, 43, 0, 0, 0, 37,
+ 0, 0, 0, 1, 0, 0, 0, 44, 0, 0, 0, 46, 0, 0, 0, 36, 0, 0, 0, 38, 0, 0, 0, 1, 0, 0, 0, 45, 0, 0, 0, 35,
+ 0, 0, 0, 49, 0, 0, 0, 47, 0, 0, 0, 1, 0, 0, 0, 50, 0, 0, 0, 36, 0, 0, 0, 46, 0, 0, 0, 48, 0, 0, 0, 1,
+ 0, 0, 0, 35, 0, 0, 0, 33, 0, 0, 0, 51, 0, 0, 0, 49, 0, 0, 0, 1, 0, 0, 0, 52, 0, 0, 0, 34, 0, 0, 0, 36,
+ 0, 0, 0, 50, 0, 0, 0, 1, 0, 0, 0, 33, 0, 0, 0, 23, 0, 0, 0, 53, 0, 0, 0, 51, 0, 0, 0, 1, 0, 0, 0, 54,
+ 0, 0, 0, 24, 0, 0, 0, 34, 0, 0, 0, 52, 0, 0, 0, 1, 0, 0, 0, 23, 0, 0, 0, 21, 0, 0, 0, 55, 0, 0, 0, 53,
+ 0, 0, 0, 1, 0, 0, 0, 56, 0, 0, 0, 22, 0, 0, 0, 24, 0, 0, 0, 54, 0, 0, 0, 1, 0, 0, 0, 21, 0, 0, 0, 12,
+ 0, 0, 0, 57, 0, 0, 0, 55, 0, 0, 0, 1, 0, 0, 0, 58, 0, 0, 0, 13, 0, 0, 0, 22, 0, 0, 0, 56, 0, 0, 0, 1,
+ 0, 0, 0, 12, 0, 0, 0, 10, 0, 0, 0, 61, 0, 0, 0, 57, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0, 0, 11, 0, 0, 0, 13,
+ 0, 0, 0, 58, 0, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 61, 0, 0, 0, 1, 0, 0, 0, 64,
+ 0, 0, 0, 1, 0, 0, 0, 11, 0, 0, 0, 62, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 47, 0, 0, 0, 63,
+ 0, 0, 0, 1, 0, 0, 0, 48, 0, 0, 0, 46, 0, 0, 0, 1, 0, 0, 0, 64, 0, 0, 0, 1, 0, 0, 0, 59, 0, 0, 0, 63,
+ 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 48, 0, 0, 0, 64, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 61, 0, 0, 0, 63, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 64, 0, 0, 0, 62,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 59, 0, 0, 0, 57, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62,
+ 0, 0, 0, 58, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 59, 0, 0, 0, 55, 0, 0, 0, 57, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 58, 0, 0, 0, 56, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 59, 0, 0, 0, 53,
+ 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 56, 0, 0, 0, 54, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 59, 0, 0, 0, 51, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 54, 0, 0, 0, 52, 0, 0, 0, 60,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 59, 0, 0, 0, 49, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 52,
+ 0, 0, 0, 50, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 59, 0, 0, 0, 47, 0, 0, 0, 49, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 50, 0, 0, 0, 48, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 87, 0, 0, 0,171,
+ 0, 0, 0,173, 0, 0, 0, 89, 0, 0, 0, 1, 0, 0, 0,173, 0, 0, 0,172, 0, 0, 0, 88, 0, 0, 0, 89, 0, 0, 0, 1,
+ 0, 0, 0, 85, 0, 0, 0,169, 0, 0, 0,171, 0, 0, 0, 87, 0, 0, 0, 1, 0, 0, 0,172, 0, 0, 0,170, 0, 0, 0, 86,
+ 0, 0, 0, 88, 0, 0, 0, 1, 0, 0, 0, 83, 0, 0, 0,167, 0, 0, 0,169, 0, 0, 0, 85, 0, 0, 0, 1, 0, 0, 0,170,
+ 0, 0, 0,168, 0, 0, 0, 84, 0, 0, 0, 86, 0, 0, 0, 1, 0, 0, 0, 81, 0, 0, 0,165, 0, 0, 0,167, 0, 0, 0, 83,
+ 0, 0, 0, 1, 0, 0, 0,168, 0, 0, 0,166, 0, 0, 0, 82, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 79, 0, 0, 0,163,
+ 0, 0, 0,165, 0, 0, 0, 81, 0, 0, 0, 1, 0, 0, 0,166, 0, 0, 0,164, 0, 0, 0, 80, 0, 0, 0, 82, 0, 0, 0, 1,
+ 0, 0, 0, 77, 0, 0, 0, 90, 0, 0, 0,143, 0, 0, 0,161, 0, 0, 0, 1, 0, 0, 0,144, 0, 0, 0, 91, 0, 0, 0, 78,
+ 0, 0, 0,162, 0, 0, 0, 1, 0, 0, 0, 90, 0, 0, 0, 92, 0, 0, 0,145, 0, 0, 0,143, 0, 0, 0, 1, 0, 0, 0,146,
+ 0, 0, 0, 93, 0, 0, 0, 91, 0, 0, 0,144, 0, 0, 0, 1, 0, 0, 0, 92, 0, 0, 0, 94, 0, 0, 0,147, 0, 0, 0,145,
+ 0, 0, 0, 1, 0, 0, 0,148, 0, 0, 0, 95, 0, 0, 0, 93, 0, 0, 0,146, 0, 0, 0, 1, 0, 0, 0, 94, 0, 0, 0, 96,
+ 0, 0, 0,149, 0, 0, 0,147, 0, 0, 0, 1, 0, 0, 0,150, 0, 0, 0, 97, 0, 0, 0, 95, 0, 0, 0,148, 0, 0, 0, 1,
+ 0, 0, 0, 96, 0, 0, 0, 98, 0, 0, 0,151, 0, 0, 0,149, 0, 0, 0, 1, 0, 0, 0,152, 0, 0, 0, 99, 0, 0, 0, 97,
+ 0, 0, 0,150, 0, 0, 0, 1, 0, 0, 0, 98, 0, 0, 0,100, 0, 0, 0,153, 0, 0, 0,151, 0, 0, 0, 1, 0, 0, 0,154,
+ 0, 0, 0,101, 0, 0, 0, 99, 0, 0, 0,152, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0,102, 0, 0, 0,155, 0, 0, 0,153,
+ 0, 0, 0, 1, 0, 0, 0,156, 0, 0, 0,103, 0, 0, 0,101, 0, 0, 0,154, 0, 0, 0, 1, 0, 0, 0,102, 0, 0, 0,104,
+ 0, 0, 0,157, 0, 0, 0,155, 0, 0, 0, 1, 0, 0, 0,158, 0, 0, 0,105, 0, 0, 0,103, 0, 0, 0,156, 0, 0, 0, 1,
+ 0, 0, 0,104, 0, 0, 0,106, 0, 0, 0,159, 0, 0, 0,157, 0, 0, 0, 1, 0, 0, 0,160, 0, 0, 0,107, 0, 0, 0,105,
+ 0, 0, 0,158, 0, 0, 0, 1, 0, 0, 0,106, 0, 0, 0, 65, 0, 0, 0, 66, 0, 0, 0,159, 0, 0, 0, 1, 0, 0, 0, 66,
+ 0, 0, 0, 65, 0, 0, 0,107, 0, 0, 0,160, 0, 0, 0, 1, 0, 0, 0,108, 0, 0, 0,125, 0, 0, 0,157, 0, 0, 0,159,
+ 0, 0, 0, 1, 0, 0, 0,158, 0, 0, 0,126, 0, 0, 0,109, 0, 0, 0,160, 0, 0, 0, 1, 0, 0, 0,125, 0, 0, 0,176,
+ 0, 0, 0,155, 0, 0, 0,157, 0, 0, 0, 1, 0, 0, 0,156, 0, 0, 0,177, 0, 0, 0,126, 0, 0, 0,158, 0, 0, 0, 1,
+ 0, 0, 0,123, 0, 0, 0,153, 0, 0, 0,155, 0, 0, 0,176, 0, 0, 0, 1, 0, 0, 0,156, 0, 0, 0,154, 0, 0, 0,124,
+ 0, 0, 0,177, 0, 0, 0, 1, 0, 0, 0,121, 0, 0, 0,151, 0, 0, 0,153, 0, 0, 0,123, 0, 0, 0, 1, 0, 0, 0,154,
+ 0, 0, 0,152, 0, 0, 0,122, 0, 0, 0,124, 0, 0, 0, 1, 0, 0, 0,119, 0, 0, 0,149, 0, 0, 0,151, 0, 0, 0,121,
+ 0, 0, 0, 1, 0, 0, 0,152, 0, 0, 0,150, 0, 0, 0,120, 0, 0, 0,122, 0, 0, 0, 1, 0, 0, 0,117, 0, 0, 0,147,
+ 0, 0, 0,149, 0, 0, 0,119, 0, 0, 0, 1, 0, 0, 0,150, 0, 0, 0,148, 0, 0, 0,118, 0, 0, 0,120, 0, 0, 0, 1,
+ 0, 0, 0,115, 0, 0, 0,145, 0, 0, 0,147, 0, 0, 0,117, 0, 0, 0, 1, 0, 0, 0,148, 0, 0, 0,146, 0, 0, 0,116,
+ 0, 0, 0,118, 0, 0, 0, 1, 0, 0, 0,113, 0, 0, 0,143, 0, 0, 0,145, 0, 0, 0,115, 0, 0, 0, 1, 0, 0, 0,146,
+ 0, 0, 0,144, 0, 0, 0,114, 0, 0, 0,116, 0, 0, 0, 1, 0, 0, 0, 14, 0, 0, 0,161, 0, 0, 0,143, 0, 0, 0,113,
+ 0, 0, 0, 1, 0, 0, 0,144, 0, 0, 0,162, 0, 0, 0,112, 0, 0, 0,114, 0, 0, 0, 1, 0, 0, 0, 14, 0, 0, 0,178,
+ 0, 0, 0,174, 0, 0, 0,161, 0, 0, 0, 1, 0, 0, 0,174, 0, 0, 0,179, 0, 0, 0,112, 0, 0, 0,162, 0, 0, 0, 1,
+ 0, 0, 0,108, 0, 0, 0,159, 0, 0, 0, 66, 0, 0, 0,110, 0, 0, 0, 1, 0, 0, 0, 66, 0, 0, 0,160, 0, 0, 0,109,
+ 0, 0, 0,111, 0, 0, 0, 1, 0, 0, 0,110, 0, 0, 0, 66, 0, 0, 0,175, 0, 0, 0,180, 0, 0, 0, 1, 0, 0, 0,175,
+ 0, 0, 0, 66, 0, 0, 0,111, 0, 0, 0,181, 0, 0, 0, 1, 0, 0, 0,174, 0, 0, 0,178, 0, 0, 0,180, 0, 0, 0,175,
+ 0, 0, 0, 1, 0, 0, 0,181, 0, 0, 0,179, 0, 0, 0,174, 0, 0, 0,175, 0, 0, 0, 1, 0, 0, 0,132, 0, 0, 0,134,
+ 0, 0, 0,173, 0, 0, 0,171, 0, 0, 0, 1, 0, 0, 0,173, 0, 0, 0,134, 0, 0, 0,133, 0, 0, 0,172, 0, 0, 0, 1,
+ 0, 0, 0,130, 0, 0, 0,132, 0, 0, 0,171, 0, 0, 0,169, 0, 0, 0, 1, 0, 0, 0,172, 0, 0, 0,133, 0, 0, 0,131,
+ 0, 0, 0,170, 0, 0, 0, 1, 0, 0, 0,128, 0, 0, 0,130, 0, 0, 0,169, 0, 0, 0,167, 0, 0, 0, 1, 0, 0, 0,170,
+ 0, 0, 0,131, 0, 0, 0,129, 0, 0, 0,168, 0, 0, 0, 1, 0, 0, 0,163, 0, 0, 0,184, 0, 0, 0,182, 0, 0, 0,165,
+ 0, 0, 0, 1, 0, 0, 0,183, 0, 0, 0,185, 0, 0, 0,164, 0, 0, 0,166, 0, 0, 0, 1, 0, 0, 0,128, 0, 0, 0,167,
+ 0, 0, 0,165, 0, 0, 0,182, 0, 0, 0, 1, 0, 0, 0,166, 0, 0, 0,168, 0, 0, 0,129, 0, 0, 0,183, 0, 0, 0, 1,
+ 0, 0, 0,141, 0, 0, 0,187, 0, 0, 0,186, 0, 0, 0,184, 0, 0, 0, 1, 0, 0, 0,186, 0, 0, 0,187, 0, 0, 0,142,
+ 0, 0, 0,185, 0, 0, 0, 1, 0, 0, 0,182, 0, 0, 0,184, 0, 0, 0,186, 0, 0, 0, 67, 0, 0, 0, 1, 0, 0, 0,186,
+ 0, 0, 0,185, 0, 0, 0,183, 0, 0, 0, 67, 0, 0, 0, 1, 0, 0, 0,127, 0, 0, 0,128, 0, 0, 0,182, 0, 0, 0, 67,
+ 0, 0, 0, 1, 0, 0, 0,183, 0, 0, 0,129, 0, 0, 0,127, 0, 0, 0, 67, 0, 0, 0, 1, 0, 0, 0,139, 0, 0, 0,190,
+ 0, 0, 0,188, 0, 0, 0,141, 0, 0, 0, 1, 0, 0, 0,189, 0, 0, 0,191, 0, 0, 0,140, 0, 0, 0,142, 0, 0, 0, 1,
+ 0, 0, 0,137, 0, 0, 0,192, 0, 0, 0,190, 0, 0, 0,139, 0, 0, 0, 1, 0, 0, 0,191, 0, 0, 0,193, 0, 0, 0,138,
+ 0, 0, 0,140, 0, 0, 0, 1, 0, 0, 0,136, 0, 0, 0,194, 0, 0, 0,192, 0, 0, 0,137, 0, 0, 0, 1, 0, 0, 0,193,
+ 0, 0, 0,195, 0, 0, 0,136, 0, 0, 0,138, 0, 0, 0, 1, 0, 0, 0,135, 0, 0, 0, 69, 0, 0, 0,194, 0, 0, 0,136,
+ 0, 0, 0, 1, 0, 0, 0,195, 0, 0, 0, 69, 0, 0, 0,135, 0, 0, 0,136, 0, 0, 0, 1, 0, 0, 0,187, 0, 0, 0,141,
+ 0, 0, 0,188, 0, 0, 0, 68, 0, 0, 0, 1, 0, 0, 0,189, 0, 0, 0,142, 0, 0, 0,187, 0, 0, 0, 68, 0, 0, 0, 1,
+ 0, 0, 0, 68, 0, 0, 0,188, 0, 0, 0,203, 0, 0, 0,205, 0, 0, 0, 1, 0, 0, 0,204, 0, 0, 0,189, 0, 0, 0, 68,
+ 0, 0, 0,205, 0, 0, 0, 1, 0, 0, 0, 69, 0, 0, 0,196, 0, 0, 0,197, 0, 0, 0,194, 0, 0, 0, 1, 0, 0, 0,198,
+ 0, 0, 0,196, 0, 0, 0, 69, 0, 0, 0,195, 0, 0, 0, 1, 0, 0, 0,194, 0, 0, 0,197, 0, 0, 0,199, 0, 0, 0,192,
+ 0, 0, 0, 1, 0, 0, 0,200, 0, 0, 0,198, 0, 0, 0,195, 0, 0, 0,193, 0, 0, 0, 1, 0, 0, 0,192, 0, 0, 0,199,
+ 0, 0, 0,201, 0, 0, 0,190, 0, 0, 0, 1, 0, 0, 0,202, 0, 0, 0,200, 0, 0, 0,193, 0, 0, 0,191, 0, 0, 0, 1,
+ 0, 0, 0,190, 0, 0, 0,201, 0, 0, 0,203, 0, 0, 0,188, 0, 0, 0, 1, 0, 0, 0,204, 0, 0, 0,202, 0, 0, 0,191,
+ 0, 0, 0,189, 0, 0, 0, 1, 0, 0, 0,196, 0, 0, 0,201, 0, 0, 0,199, 0, 0, 0,197, 0, 0, 0, 1, 0, 0, 0,200,
+ 0, 0, 0,202, 0, 0, 0,196, 0, 0, 0,198, 0, 0, 0, 1, 0, 0, 0,196, 0, 0, 0,205, 0, 0, 0,203, 0, 0, 0,201,
+ 0, 0, 0, 1, 0, 0, 0,204, 0, 0, 0,205, 0, 0, 0,196, 0, 0, 0,202, 0, 0, 0, 1, 0, 0, 0,136, 0, 0, 0,137,
+ 0, 0, 0,161, 0, 0, 0,174, 0, 0, 0, 1, 0, 0, 0,162, 0, 0, 0,138, 0, 0, 0,136, 0, 0, 0,174, 0, 0, 0, 1,
+ 0, 0, 0,137, 0, 0, 0,139, 0, 0, 0,208, 0, 0, 0,161, 0, 0, 0, 1, 0, 0, 0,209, 0, 0, 0,140, 0, 0, 0,138,
+ 0, 0, 0,162, 0, 0, 0, 1, 0, 0, 0,139, 0, 0, 0,141, 0, 0, 0,210, 0, 0, 0,208, 0, 0, 0, 1, 0, 0, 0,211,
+ 0, 0, 0,142, 0, 0, 0,140, 0, 0, 0,209, 0, 0, 0, 1, 0, 0, 0,141, 0, 0, 0,184, 0, 0, 0,163, 0, 0, 0,210,
+ 0, 0, 0, 1, 0, 0, 0,164, 0, 0, 0,185, 0, 0, 0,142, 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 79, 0, 0, 0,206,
+ 0, 0, 0,210, 0, 0, 0,163, 0, 0, 0, 1, 0, 0, 0,211, 0, 0, 0,207, 0, 0, 0, 80, 0, 0, 0,164, 0, 0, 0, 1,
+ 0, 0, 0,206, 0, 0, 0,212, 0, 0, 0,208, 0, 0, 0,210, 0, 0, 0, 1, 0, 0, 0,209, 0, 0, 0,213, 0, 0, 0,207,
+ 0, 0, 0,211, 0, 0, 0, 1, 0, 0, 0, 77, 0, 0, 0,161, 0, 0, 0,208, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0,209,
+ 0, 0, 0,162, 0, 0, 0, 78, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0,128, 0, 0, 0,127, 0, 0, 0, 70, 0, 0, 0,219,
+ 0, 0, 0, 1, 0, 0, 0, 70, 0, 0, 0,127, 0, 0, 0,129, 0, 0, 0,220, 0, 0, 0, 1, 0, 0, 0,130, 0, 0, 0,128,
+ 0, 0, 0,219, 0, 0, 0,217, 0, 0, 0, 1, 0, 0, 0,220, 0, 0, 0,129, 0, 0, 0,131, 0, 0, 0,218, 0, 0, 0, 1,
+ 0, 0, 0,132, 0, 0, 0,130, 0, 0, 0,217, 0, 0, 0,215, 0, 0, 0, 1, 0, 0, 0,218, 0, 0, 0,131, 0, 0, 0,133,
+ 0, 0, 0,216, 0, 0, 0, 1, 0, 0, 0,134, 0, 0, 0,132, 0, 0, 0,215, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,216,
+ 0, 0, 0,133, 0, 0, 0,134, 0, 0, 0,214, 0, 0, 0, 1, 0, 0, 0,214, 0, 0, 0,215, 0, 0, 0,226, 0, 0, 0,228,
+ 0, 0, 0, 1, 0, 0, 0,227, 0, 0, 0,216, 0, 0, 0,214, 0, 0, 0,228, 0, 0, 0, 1, 0, 0, 0,215, 0, 0, 0,217,
+ 0, 0, 0,224, 0, 0, 0,226, 0, 0, 0, 1, 0, 0, 0,225, 0, 0, 0,218, 0, 0, 0,216, 0, 0, 0,227, 0, 0, 0, 1,
+ 0, 0, 0,217, 0, 0, 0,219, 0, 0, 0,222, 0, 0, 0,224, 0, 0, 0, 1, 0, 0, 0,223, 0, 0, 0,220, 0, 0, 0,218,
+ 0, 0, 0,225, 0, 0, 0, 1, 0, 0, 0,219, 0, 0, 0, 70, 0, 0, 0,221, 0, 0, 0,222, 0, 0, 0, 1, 0, 0, 0,221,
+ 0, 0, 0, 70, 0, 0, 0,220, 0, 0, 0,223, 0, 0, 0, 1, 0, 0, 0,221, 0, 0, 0,228, 0, 0, 0,226, 0, 0, 0,222,
+ 0, 0, 0, 1, 0, 0, 0,227, 0, 0, 0,228, 0, 0, 0,221, 0, 0, 0,223, 0, 0, 0, 1, 0, 0, 0,222, 0, 0, 0,226,
+ 0, 0, 0,224, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,225, 0, 0, 0,227, 0, 0, 0,223, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0,180, 0, 0, 0,178, 0, 0, 0,231, 0, 0, 0,229, 0, 0, 0, 1, 0, 0, 0,232, 0, 0, 0,179, 0, 0, 0,181,
+ 0, 0, 0,230, 0, 0, 0, 1, 0, 0, 0,110, 0, 0, 0,180, 0, 0, 0,229, 0, 0, 0,251, 0, 0, 0, 1, 0, 0, 0,230,
+ 0, 0, 0,181, 0, 0, 0,111, 0, 0, 0,252, 0, 0, 0, 1, 0, 0, 0,108, 0, 0, 0,110, 0, 0, 0,251, 0, 0, 0,253,
+ 0, 0, 0, 1, 0, 0, 0,252, 0, 0, 0,111, 0, 0, 0,109, 0, 0, 0,254, 0, 0, 0, 1, 0, 0, 0,178, 0, 0, 0, 14,
+ 0, 0, 0,249, 0, 0, 0,231, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0,112, 0, 0, 0,179, 0, 0, 0,232, 0, 0, 0, 1,
+ 0, 0, 0, 14, 0, 0, 0,113, 0, 0, 0,247, 0, 0, 0,249, 0, 0, 0, 1, 0, 0, 0,248, 0, 0, 0,114, 0, 0, 0,112,
+ 0, 0, 0,250, 0, 0, 0, 1, 0, 0, 0,113, 0, 0, 0,115, 0, 0, 0,245, 0, 0, 0,247, 0, 0, 0, 1, 0, 0, 0,246,
+ 0, 0, 0,116, 0, 0, 0,114, 0, 0, 0,248, 0, 0, 0, 1, 0, 0, 0,115, 0, 0, 0,117, 0, 0, 0,243, 0, 0, 0,245,
+ 0, 0, 0, 1, 0, 0, 0,244, 0, 0, 0,118, 0, 0, 0,116, 0, 0, 0,246, 0, 0, 0, 1, 0, 0, 0,117, 0, 0, 0,119,
+ 0, 0, 0,241, 0, 0, 0,243, 0, 0, 0, 1, 0, 0, 0,242, 0, 0, 0,120, 0, 0, 0,118, 0, 0, 0,244, 0, 0, 0, 1,
+ 0, 0, 0,119, 0, 0, 0,121, 0, 0, 0,239, 0, 0, 0,241, 0, 0, 0, 1, 0, 0, 0,240, 0, 0, 0,122, 0, 0, 0,120,
+ 0, 0, 0,242, 0, 0, 0, 1, 0, 0, 0,121, 0, 0, 0,123, 0, 0, 0,237, 0, 0, 0,239, 0, 0, 0, 1, 0, 0, 0,238,
+ 0, 0, 0,124, 0, 0, 0,122, 0, 0, 0,240, 0, 0, 0, 1, 0, 0, 0,123, 0, 0, 0,176, 0, 0, 0,233, 0, 0, 0,237,
+ 0, 0, 0, 1, 0, 0, 0,234, 0, 0, 0,177, 0, 0, 0,124, 0, 0, 0,238, 0, 0, 0, 1, 0, 0, 0,176, 0, 0, 0,125,
+ 0, 0, 0,235, 0, 0, 0,233, 0, 0, 0, 1, 0, 0, 0,236, 0, 0, 0,126, 0, 0, 0,177, 0, 0, 0,234, 0, 0, 0, 1,
+ 0, 0, 0,125, 0, 0, 0,108, 0, 0, 0,253, 0, 0, 0,235, 0, 0, 0, 1, 0, 0, 0,254, 0, 0, 0,109, 0, 0, 0,126,
+ 0, 0, 0,236, 0, 0, 0, 1, 0, 0, 0,235, 0, 0, 0,253, 0, 0, 0,255, 0, 0, 1, 17, 0, 0, 0, 1, 0, 0, 1, 0,
+ 0, 0, 0,254, 0, 0, 0,236, 0, 0, 1, 18, 0, 0, 0, 1, 0, 0, 0,233, 0, 0, 0,235, 0, 0, 1, 17, 0, 0, 1, 19,
+ 0, 0, 0, 1, 0, 0, 1, 18, 0, 0, 0,236, 0, 0, 0,234, 0, 0, 1, 20, 0, 0, 0, 1, 0, 0, 0,237, 0, 0, 0,233,
+ 0, 0, 1, 19, 0, 0, 1, 15, 0, 0, 0, 1, 0, 0, 1, 20, 0, 0, 0,234, 0, 0, 0,238, 0, 0, 1, 16, 0, 0, 0, 1,
+ 0, 0, 0,239, 0, 0, 0,237, 0, 0, 1, 15, 0, 0, 1, 13, 0, 0, 0, 1, 0, 0, 1, 16, 0, 0, 0,238, 0, 0, 0,240,
+ 0, 0, 1, 14, 0, 0, 0, 1, 0, 0, 0,241, 0, 0, 0,239, 0, 0, 1, 13, 0, 0, 1, 11, 0, 0, 0, 1, 0, 0, 1, 14,
+ 0, 0, 0,240, 0, 0, 0,242, 0, 0, 1, 12, 0, 0, 0, 1, 0, 0, 0,243, 0, 0, 0,241, 0, 0, 1, 11, 0, 0, 1, 9,
+ 0, 0, 0, 1, 0, 0, 1, 12, 0, 0, 0,242, 0, 0, 0,244, 0, 0, 1, 10, 0, 0, 0, 1, 0, 0, 0,245, 0, 0, 0,243,
+ 0, 0, 1, 9, 0, 0, 1, 7, 0, 0, 0, 1, 0, 0, 1, 10, 0, 0, 0,244, 0, 0, 0,246, 0, 0, 1, 8, 0, 0, 0, 1,
+ 0, 0, 0,247, 0, 0, 0,245, 0, 0, 1, 7, 0, 0, 1, 5, 0, 0, 0, 1, 0, 0, 1, 8, 0, 0, 0,246, 0, 0, 0,248,
+ 0, 0, 1, 6, 0, 0, 0, 1, 0, 0, 0,249, 0, 0, 0,247, 0, 0, 1, 5, 0, 0, 1, 3, 0, 0, 0, 1, 0, 0, 1, 6,
+ 0, 0, 0,248, 0, 0, 0,250, 0, 0, 1, 4, 0, 0, 0, 1, 0, 0, 0,231, 0, 0, 0,249, 0, 0, 1, 3, 0, 0, 1, 21,
+ 0, 0, 0, 1, 0, 0, 1, 4, 0, 0, 0,250, 0, 0, 0,232, 0, 0, 1, 22, 0, 0, 0, 1, 0, 0, 0,253, 0, 0, 0,251,
+ 0, 0, 1, 1, 0, 0, 0,255, 0, 0, 0, 1, 0, 0, 1, 2, 0, 0, 0,252, 0, 0, 0,254, 0, 0, 1, 0, 0, 0, 0, 1,
+ 0, 0, 0,251, 0, 0, 0,229, 0, 0, 1, 23, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 24, 0, 0, 0,230, 0, 0, 0,252,
+ 0, 0, 1, 2, 0, 0, 0, 1, 0, 0, 0,229, 0, 0, 0,231, 0, 0, 1, 21, 0, 0, 1, 23, 0, 0, 0, 1, 0, 0, 1, 22,
+ 0, 0, 0,232, 0, 0, 0,230, 0, 0, 1, 24, 0, 0, 0, 1, 0, 0, 0, 65, 0, 0, 0,106, 0, 0, 1, 25, 0, 0, 0, 71,
+ 0, 0, 0, 1, 0, 0, 1, 26, 0, 0, 0,107, 0, 0, 0, 65, 0, 0, 0, 71, 0, 0, 0, 1, 0, 0, 0,106, 0, 0, 0,104,
+ 0, 0, 1, 27, 0, 0, 1, 25, 0, 0, 0, 1, 0, 0, 1, 28, 0, 0, 0,105, 0, 0, 0,107, 0, 0, 1, 26, 0, 0, 0, 1,
+ 0, 0, 0,104, 0, 0, 0,102, 0, 0, 1, 29, 0, 0, 1, 27, 0, 0, 0, 1, 0, 0, 1, 30, 0, 0, 0,103, 0, 0, 0,105,
+ 0, 0, 1, 28, 0, 0, 0, 1, 0, 0, 0,102, 0, 0, 0,100, 0, 0, 1, 31, 0, 0, 1, 29, 0, 0, 0, 1, 0, 0, 1, 32,
+ 0, 0, 0,101, 0, 0, 0,103, 0, 0, 1, 30, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 98, 0, 0, 1, 33, 0, 0, 1, 31,
+ 0, 0, 0, 1, 0, 0, 1, 34, 0, 0, 0, 99, 0, 0, 0,101, 0, 0, 1, 32, 0, 0, 0, 1, 0, 0, 0, 98, 0, 0, 0, 96,
+ 0, 0, 1, 35, 0, 0, 1, 33, 0, 0, 0, 1, 0, 0, 1, 36, 0, 0, 0, 97, 0, 0, 0, 99, 0, 0, 1, 34, 0, 0, 0, 1,
+ 0, 0, 0, 96, 0, 0, 0, 94, 0, 0, 1, 37, 0, 0, 1, 35, 0, 0, 0, 1, 0, 0, 1, 38, 0, 0, 0, 95, 0, 0, 0, 97,
+ 0, 0, 1, 36, 0, 0, 0, 1, 0, 0, 0, 94, 0, 0, 0, 92, 0, 0, 1, 39, 0, 0, 1, 37, 0, 0, 0, 1, 0, 0, 1, 40,
+ 0, 0, 0, 93, 0, 0, 0, 95, 0, 0, 1, 38, 0, 0, 0, 1, 0, 0, 0, 92, 0, 0, 0, 90, 0, 0, 1, 41, 0, 0, 1, 39,
+ 0, 0, 0, 1, 0, 0, 1, 42, 0, 0, 0, 91, 0, 0, 0, 93, 0, 0, 1, 40, 0, 0, 0, 1, 0, 0, 1, 49, 0, 0, 1, 50,
+ 0, 0, 1, 69, 0, 0, 1, 79, 0, 0, 0, 1, 0, 0, 1, 70, 0, 0, 1, 50, 0, 0, 1, 49, 0, 0, 1, 80, 0, 0, 0, 1,
+ 0, 0, 1, 48, 0, 0, 1, 49, 0, 0, 1, 79, 0, 0, 1, 77, 0, 0, 0, 1, 0, 0, 1, 80, 0, 0, 1, 49, 0, 0, 1, 48,
+ 0, 0, 1, 78, 0, 0, 0, 1, 0, 0, 1, 47, 0, 0, 1, 48, 0, 0, 1, 77, 0, 0, 1, 81, 0, 0, 0, 1, 0, 0, 1, 78,
+ 0, 0, 1, 48, 0, 0, 1, 47, 0, 0, 1, 82, 0, 0, 0, 1, 0, 0, 0, 87, 0, 0, 0, 89, 0, 0, 1, 47, 0, 0, 1, 81,
+ 0, 0, 0, 1, 0, 0, 1, 47, 0, 0, 0, 89, 0, 0, 0, 88, 0, 0, 1, 82, 0, 0, 0, 1, 0, 0, 0, 85, 0, 0, 0, 87,
+ 0, 0, 1, 81, 0, 0, 1, 75, 0, 0, 0, 1, 0, 0, 1, 82, 0, 0, 0, 88, 0, 0, 0, 86, 0, 0, 1, 76, 0, 0, 0, 1,
+ 0, 0, 0, 83, 0, 0, 0, 85, 0, 0, 1, 75, 0, 0, 1, 71, 0, 0, 0, 1, 0, 0, 1, 76, 0, 0, 0, 86, 0, 0, 0, 84,
+ 0, 0, 1, 72, 0, 0, 0, 1, 0, 0, 0, 81, 0, 0, 0, 83, 0, 0, 1, 71, 0, 0, 1, 73, 0, 0, 0, 1, 0, 0, 1, 72,
+ 0, 0, 0, 84, 0, 0, 0, 82, 0, 0, 1, 74, 0, 0, 0, 1, 0, 0, 1, 71, 0, 0, 1, 77, 0, 0, 1, 79, 0, 0, 1, 73,
+ 0, 0, 0, 1, 0, 0, 1, 80, 0, 0, 1, 78, 0, 0, 1, 72, 0, 0, 1, 74, 0, 0, 0, 1, 0, 0, 1, 71, 0, 0, 1, 75,
+ 0, 0, 1, 81, 0, 0, 1, 77, 0, 0, 0, 1, 0, 0, 1, 82, 0, 0, 1, 76, 0, 0, 1, 72, 0, 0, 1, 78, 0, 0, 0, 1,
+ 0, 0, 1, 67, 0, 0, 1, 73, 0, 0, 1, 79, 0, 0, 1, 69, 0, 0, 0, 1, 0, 0, 1, 80, 0, 0, 1, 74, 0, 0, 1, 68,
+ 0, 0, 1, 70, 0, 0, 0, 1, 0, 0, 0, 79, 0, 0, 0, 81, 0, 0, 1, 73, 0, 0, 1, 67, 0, 0, 0, 1, 0, 0, 1, 74,
+ 0, 0, 0, 82, 0, 0, 0, 80, 0, 0, 1, 68, 0, 0, 0, 1, 0, 0, 0,206, 0, 0, 1, 83, 0, 0, 1, 85, 0, 0, 0,212,
+ 0, 0, 0, 1, 0, 0, 1, 86, 0, 0, 1, 84, 0, 0, 0,207, 0, 0, 0,213, 0, 0, 0, 1, 0, 0, 0, 79, 0, 0, 1, 67,
+ 0, 0, 1, 83, 0, 0, 0,206, 0, 0, 0, 1, 0, 0, 1, 84, 0, 0, 1, 68, 0, 0, 0, 80, 0, 0, 0,207, 0, 0, 0, 1,
+ 0, 0, 0, 77, 0, 0, 0,212, 0, 0, 1, 85, 0, 0, 1, 87, 0, 0, 0, 1, 0, 0, 1, 86, 0, 0, 0,213, 0, 0, 0, 78,
+ 0, 0, 1, 88, 0, 0, 0, 1, 0, 0, 0, 77, 0, 0, 1, 87, 0, 0, 1, 41, 0, 0, 0, 90, 0, 0, 0, 1, 0, 0, 1, 42,
+ 0, 0, 1, 88, 0, 0, 0, 78, 0, 0, 0, 91, 0, 0, 0, 1, 0, 0, 0, 75, 0, 0, 1, 65, 0, 0, 1, 93, 0, 0, 1, 45,
+ 0, 0, 0, 1, 0, 0, 1, 94, 0, 0, 1, 66, 0, 0, 0, 75, 0, 0, 1, 45, 0, 0, 0, 1, 0, 0, 1, 45, 0, 0, 1, 93,
+ 0, 0, 1, 91, 0, 0, 0, 76, 0, 0, 0, 1, 0, 0, 1, 92, 0, 0, 1, 94, 0, 0, 1, 45, 0, 0, 0, 76, 0, 0, 0, 1,
+ 0, 0, 0, 76, 0, 0, 1, 91, 0, 0, 1, 89, 0, 0, 1, 46, 0, 0, 0, 1, 0, 0, 1, 90, 0, 0, 1, 92, 0, 0, 0, 76,
+ 0, 0, 1, 46, 0, 0, 0, 1, 0, 0, 1, 46, 0, 0, 1, 89, 0, 0, 1, 69, 0, 0, 1, 50, 0, 0, 0, 1, 0, 0, 1, 70,
+ 0, 0, 1, 90, 0, 0, 1, 46, 0, 0, 1, 50, 0, 0, 0, 1, 0, 0, 1, 67, 0, 0, 1, 69, 0, 0, 1, 89, 0, 0, 1, 83,
+ 0, 0, 0, 1, 0, 0, 1, 90, 0, 0, 1, 70, 0, 0, 1, 68, 0, 0, 1, 84, 0, 0, 0, 1, 0, 0, 1, 37, 0, 0, 1, 39,
+ 0, 0, 1, 59, 0, 0, 1, 51, 0, 0, 0, 1, 0, 0, 1, 60, 0, 0, 1, 40, 0, 0, 1, 38, 0, 0, 1, 52, 0, 0, 0, 1,
+ 0, 0, 0, 74, 0, 0, 1, 57, 0, 0, 1, 65, 0, 0, 0, 75, 0, 0, 0, 1, 0, 0, 1, 66, 0, 0, 1, 58, 0, 0, 0, 74,
+ 0, 0, 0, 75, 0, 0, 0, 1, 0, 0, 1, 43, 0, 0, 1, 99, 0, 0, 1, 97, 0, 0, 1, 44, 0, 0, 0, 1, 0, 0, 1, 98,
+ 0, 0, 1,100, 0, 0, 1, 43, 0, 0, 1, 44, 0, 0, 0, 1, 0, 0, 1, 44, 0, 0, 1, 97, 0, 0, 1, 95, 0, 0, 0, 73,
+ 0, 0, 0, 1, 0, 0, 1, 96, 0, 0, 1, 98, 0, 0, 1, 44, 0, 0, 0, 73, 0, 0, 0, 1, 0, 0, 0, 73, 0, 0, 1, 95,
+ 0, 0, 1, 57, 0, 0, 0, 74, 0, 0, 0, 1, 0, 0, 1, 58, 0, 0, 1, 96, 0, 0, 0, 73, 0, 0, 0, 74, 0, 0, 0, 1,
+ 0, 0, 1, 33, 0, 0, 1, 35, 0, 0, 1,103, 0, 0, 1,105, 0, 0, 0, 1, 0, 0, 1,104, 0, 0, 1, 36, 0, 0, 1, 34,
+ 0, 0, 1,106, 0, 0, 0, 1, 0, 0, 1,105, 0, 0, 1,103, 0, 0, 1,109, 0, 0, 1,107, 0, 0, 0, 1, 0, 0, 1,110,
+ 0, 0, 1,104, 0, 0, 1,106, 0, 0, 1,108, 0, 0, 0, 1, 0, 0, 1,107, 0, 0, 1,109, 0, 0, 1,111, 0, 0, 1,113,
+ 0, 0, 0, 1, 0, 0, 1,112, 0, 0, 1,110, 0, 0, 1,108, 0, 0, 1,114, 0, 0, 0, 1, 0, 0, 1,113, 0, 0, 1,111,
+ 0, 0, 1,117, 0, 0, 1,115, 0, 0, 0, 1, 0, 0, 1,118, 0, 0, 1,112, 0, 0, 1,114, 0, 0, 1,116, 0, 0, 0, 1,
+ 0, 0, 1, 55, 0, 0, 1,119, 0, 0, 1,115, 0, 0, 1,117, 0, 0, 0, 1, 0, 0, 1,116, 0, 0, 1,120, 0, 0, 1, 56,
+ 0, 0, 1,118, 0, 0, 0, 1, 0, 0, 1, 57, 0, 0, 1, 95, 0, 0, 1,115, 0, 0, 1,119, 0, 0, 0, 1, 0, 0, 1,116,
+ 0, 0, 1, 96, 0, 0, 1, 58, 0, 0, 1,120, 0, 0, 0, 1, 0, 0, 1, 95, 0, 0, 1, 97, 0, 0, 1,113, 0, 0, 1,115,
+ 0, 0, 0, 1, 0, 0, 1,114, 0, 0, 1, 98, 0, 0, 1, 96, 0, 0, 1,116, 0, 0, 0, 1, 0, 0, 1, 97, 0, 0, 1, 99,
+ 0, 0, 1,107, 0, 0, 1,113, 0, 0, 0, 1, 0, 0, 1,108, 0, 0, 1,100, 0, 0, 1, 98, 0, 0, 1,114, 0, 0, 0, 1,
+ 0, 0, 1, 99, 0, 0, 1,101, 0, 0, 1,105, 0, 0, 1,107, 0, 0, 0, 1, 0, 0, 1,106, 0, 0, 1,102, 0, 0, 1,100,
+ 0, 0, 1,108, 0, 0, 0, 1, 0, 0, 1, 31, 0, 0, 1, 33, 0, 0, 1,105, 0, 0, 1,101, 0, 0, 0, 1, 0, 0, 1,106,
+ 0, 0, 1, 34, 0, 0, 1, 32, 0, 0, 1,102, 0, 0, 0, 1, 0, 0, 0, 72, 0, 0, 1,101, 0, 0, 1, 99, 0, 0, 1, 43,
+ 0, 0, 0, 1, 0, 0, 1,100, 0, 0, 1,102, 0, 0, 0, 72, 0, 0, 1, 43, 0, 0, 0, 1, 0, 0, 1, 25, 0, 0, 1, 27,
+ 0, 0, 1, 29, 0, 0, 1, 31, 0, 0, 0, 1, 0, 0, 1, 30, 0, 0, 1, 28, 0, 0, 1, 26, 0, 0, 1, 32, 0, 0, 0, 1,
+ 0, 0, 1, 25, 0, 0, 1, 31, 0, 0, 1,101, 0, 0, 0, 72, 0, 0, 0, 1, 0, 0, 1,102, 0, 0, 1, 32, 0, 0, 1, 26,
+ 0, 0, 0, 72, 0, 0, 0, 1, 0, 0, 0, 71, 0, 0, 1, 25, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 72,
+ 0, 0, 1, 26, 0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 35, 0, 0, 1, 37, 0, 0, 1, 51, 0, 0, 1,103,
+ 0, 0, 0, 1, 0, 0, 1, 52, 0, 0, 1, 38, 0, 0, 1, 36, 0, 0, 1,104, 0, 0, 0, 1, 0, 0, 1, 51, 0, 0, 1, 53,
+ 0, 0, 1,109, 0, 0, 1,103, 0, 0, 0, 1, 0, 0, 1,110, 0, 0, 1, 54, 0, 0, 1, 52, 0, 0, 1,104, 0, 0, 0, 1,
+ 0, 0, 1, 53, 0, 0, 1,123, 0, 0, 1,111, 0, 0, 1,109, 0, 0, 0, 1, 0, 0, 1,112, 0, 0, 1,124, 0, 0, 1, 54,
+ 0, 0, 1,110, 0, 0, 0, 1, 0, 0, 1, 55, 0, 0, 1,117, 0, 0, 1,111, 0, 0, 1,123, 0, 0, 0, 1, 0, 0, 1,112,
+ 0, 0, 1,118, 0, 0, 1, 56, 0, 0, 1,124, 0, 0, 0, 1, 0, 0, 1, 89, 0, 0, 1, 91, 0, 0, 1,127, 0, 0, 1,125,
+ 0, 0, 0, 1, 0, 0, 1,128, 0, 0, 1, 92, 0, 0, 1, 90, 0, 0, 1,126, 0, 0, 0, 1, 0, 0, 1, 59, 0, 0, 1,125,
+ 0, 0, 1,127, 0, 0, 1, 61, 0, 0, 0, 1, 0, 0, 1,128, 0, 0, 1,126, 0, 0, 1, 60, 0, 0, 1, 62, 0, 0, 0, 1,
+ 0, 0, 1, 39, 0, 0, 1, 41, 0, 0, 1,125, 0, 0, 1, 59, 0, 0, 0, 1, 0, 0, 1,126, 0, 0, 1, 42, 0, 0, 1, 40,
+ 0, 0, 1, 60, 0, 0, 0, 1, 0, 0, 1, 41, 0, 0, 1, 85, 0, 0, 1, 83, 0, 0, 1,125, 0, 0, 0, 1, 0, 0, 1, 84,
+ 0, 0, 1, 86, 0, 0, 1, 42, 0, 0, 1,126, 0, 0, 0, 1, 0, 0, 1, 83, 0, 0, 1, 89, 0, 0, 1,125, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 1,126, 0, 0, 1, 90, 0, 0, 1, 84, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 41, 0, 0, 1, 87,
+ 0, 0, 1, 85, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 86, 0, 0, 1, 88, 0, 0, 1, 42, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 1, 55, 0, 0, 1, 63, 0, 0, 1,121, 0, 0, 1,119, 0, 0, 0, 1, 0, 0, 1,122, 0, 0, 1, 64, 0, 0, 1, 56,
+ 0, 0, 1,120, 0, 0, 0, 1, 0, 0, 1, 57, 0, 0, 1,119, 0, 0, 1,121, 0, 0, 1, 65, 0, 0, 0, 1, 0, 0, 1,122,
+ 0, 0, 1,120, 0, 0, 1, 58, 0, 0, 1, 66, 0, 0, 0, 1, 0, 0, 1, 61, 0, 0, 1,127, 0, 0, 1,121, 0, 0, 1, 63,
+ 0, 0, 0, 1, 0, 0, 1,122, 0, 0, 1,128, 0, 0, 1, 62, 0, 0, 1, 64, 0, 0, 0, 1, 0, 0, 1, 91, 0, 0, 1, 93,
+ 0, 0, 1,121, 0, 0, 1,127, 0, 0, 0, 1, 0, 0, 1,122, 0, 0, 1, 94, 0, 0, 1, 92, 0, 0, 1,128, 0, 0, 0, 1,
+ 0, 0, 1, 65, 0, 0, 1,121, 0, 0, 1, 93, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 94, 0, 0, 1,122, 0, 0, 1, 66,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,141, 0, 0, 1,129, 0, 0, 1,155, 0, 0, 1,143, 0, 0, 0, 1, 0, 0, 1,156,
+ 0, 0, 1,130, 0, 0, 1,142, 0, 0, 1,144, 0, 0, 0, 1, 0, 0, 1,141, 0, 0, 1,143, 0, 0, 1,145, 0, 0, 1,139,
+ 0, 0, 0, 1, 0, 0, 1,146, 0, 0, 1,144, 0, 0, 1,142, 0, 0, 1,140, 0, 0, 0, 1, 0, 0, 1,139, 0, 0, 1,145,
+ 0, 0, 1,147, 0, 0, 1,137, 0, 0, 0, 1, 0, 0, 1,148, 0, 0, 1,146, 0, 0, 1,140, 0, 0, 1,138, 0, 0, 0, 1,
+ 0, 0, 1,137, 0, 0, 1,147, 0, 0, 1,149, 0, 0, 1,135, 0, 0, 0, 1, 0, 0, 1,150, 0, 0, 1,148, 0, 0, 1,138,
+ 0, 0, 1,136, 0, 0, 0, 1, 0, 0, 1,135, 0, 0, 1,149, 0, 0, 1,151, 0, 0, 1,133, 0, 0, 0, 1, 0, 0, 1,152,
+ 0, 0, 1,150, 0, 0, 1,136, 0, 0, 1,134, 0, 0, 0, 1, 0, 0, 1,133, 0, 0, 1,151, 0, 0, 1,153, 0, 0, 1,131,
+ 0, 0, 0, 1, 0, 0, 1,154, 0, 0, 1,152, 0, 0, 1,134, 0, 0, 1,132, 0, 0, 0, 1, 0, 0, 1,151, 0, 0, 1,161,
+ 0, 0, 1,159, 0, 0, 1,153, 0, 0, 0, 1, 0, 0, 1,160, 0, 0, 1,162, 0, 0, 1,152, 0, 0, 1,154, 0, 0, 0, 1,
+ 0, 0, 1,149, 0, 0, 1,163, 0, 0, 1,161, 0, 0, 1,151, 0, 0, 0, 1, 0, 0, 1,162, 0, 0, 1,164, 0, 0, 1,150,
+ 0, 0, 1,152, 0, 0, 0, 1, 0, 0, 1,147, 0, 0, 1,165, 0, 0, 1,163, 0, 0, 1,149, 0, 0, 0, 1, 0, 0, 1,164,
+ 0, 0, 1,166, 0, 0, 1,148, 0, 0, 1,150, 0, 0, 0, 1, 0, 0, 1,145, 0, 0, 1,167, 0, 0, 1,165, 0, 0, 1,147,
+ 0, 0, 0, 1, 0, 0, 1,166, 0, 0, 1,168, 0, 0, 1,146, 0, 0, 1,148, 0, 0, 0, 1, 0, 0, 1,143, 0, 0, 1,169,
+ 0, 0, 1,167, 0, 0, 1,145, 0, 0, 0, 1, 0, 0, 1,168, 0, 0, 1,170, 0, 0, 1,144, 0, 0, 1,146, 0, 0, 0, 1,
+ 0, 0, 1,143, 0, 0, 1,155, 0, 0, 1,157, 0, 0, 1,169, 0, 0, 0, 1, 0, 0, 1,158, 0, 0, 1,156, 0, 0, 1,144,
+ 0, 0, 1,170, 0, 0, 0, 1, 0, 0, 1, 59, 0, 0, 1, 61, 0, 0, 1,185, 0, 0, 1,183, 0, 0, 0, 1, 0, 0, 1,186,
+ 0, 0, 1, 62, 0, 0, 1, 60, 0, 0, 1,184, 0, 0, 0, 1, 0, 0, 1, 61, 0, 0, 1,131, 0, 0, 1,153, 0, 0, 1,185,
+ 0, 0, 0, 1, 0, 0, 1,154, 0, 0, 1,132, 0, 0, 1, 62, 0, 0, 1,186, 0, 0, 0, 1, 0, 0, 1, 51, 0, 0, 1, 59,
+ 0, 0, 1,183, 0, 0, 1, 53, 0, 0, 0, 1, 0, 0, 1,184, 0, 0, 1, 60, 0, 0, 1, 52, 0, 0, 1, 54, 0, 0, 0, 1,
+ 0, 0, 1,123, 0, 0, 1,171, 0, 0, 1,155, 0, 0, 1,129, 0, 0, 0, 1, 0, 0, 1,156, 0, 0, 1,172, 0, 0, 1,124,
+ 0, 0, 1,130, 0, 0, 0, 1, 0, 0, 1,153, 0, 0, 1,159, 0, 0, 1,181, 0, 0, 1,185, 0, 0, 0, 1, 0, 0, 1,182,
+ 0, 0, 1,160, 0, 0, 1,154, 0, 0, 1,186, 0, 0, 0, 1, 0, 0, 1,179, 0, 0, 1,187, 0, 0, 1,185, 0, 0, 1,181,
+ 0, 0, 0, 1, 0, 0, 1,186, 0, 0, 1,188, 0, 0, 1,180, 0, 0, 1,182, 0, 0, 0, 1, 0, 0, 1,175, 0, 0, 1,187,
+ 0, 0, 1,179, 0, 0, 1,177, 0, 0, 0, 1, 0, 0, 1,180, 0, 0, 1,188, 0, 0, 1,176, 0, 0, 1,178, 0, 0, 0, 1,
+ 0, 0, 1,173, 0, 0, 1,189, 0, 0, 1,187, 0, 0, 1,175, 0, 0, 0, 1, 0, 0, 1,188, 0, 0, 1,190, 0, 0, 1,174,
+ 0, 0, 1,176, 0, 0, 0, 1, 0, 0, 1,171, 0, 0, 1,189, 0, 0, 1,173, 0, 0, 1,191, 0, 0, 0, 1, 0, 0, 1,174,
+ 0, 0, 1,190, 0, 0, 1,172, 0, 0, 1,192, 0, 0, 0, 1, 0, 0, 1,155, 0, 0, 1,171, 0, 0, 1,191, 0, 0, 1,157,
+ 0, 0, 0, 1, 0, 0, 1,192, 0, 0, 1,172, 0, 0, 1,156, 0, 0, 1,158, 0, 0, 0, 1, 0, 0, 1, 53, 0, 0, 1,189,
+ 0, 0, 1,171, 0, 0, 1,123, 0, 0, 0, 1, 0, 0, 1,172, 0, 0, 1,190, 0, 0, 1, 54, 0, 0, 1,124, 0, 0, 0, 1,
+ 0, 0, 1, 53, 0, 0, 1,183, 0, 0, 1,187, 0, 0, 1,189, 0, 0, 0, 1, 0, 0, 1,188, 0, 0, 1,184, 0, 0, 1, 54,
+ 0, 0, 1,190, 0, 0, 0, 1, 0, 0, 1,183, 0, 0, 1,185, 0, 0, 1,187, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,188,
+ 0, 0, 1,186, 0, 0, 1,184, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,157, 0, 0, 1,191, 0, 0, 1,193, 0, 0, 1,217,
+ 0, 0, 0, 1, 0, 0, 1,194, 0, 0, 1,192, 0, 0, 1,158, 0, 0, 1,218, 0, 0, 0, 1, 0, 0, 1,191, 0, 0, 1,173,
+ 0, 0, 1,203, 0, 0, 1,193, 0, 0, 0, 1, 0, 0, 1,204, 0, 0, 1,174, 0, 0, 1,192, 0, 0, 1,194, 0, 0, 0, 1,
+ 0, 0, 1,173, 0, 0, 1,175, 0, 0, 1,201, 0, 0, 1,203, 0, 0, 0, 1, 0, 0, 1,202, 0, 0, 1,176, 0, 0, 1,174,
+ 0, 0, 1,204, 0, 0, 0, 1, 0, 0, 1,175, 0, 0, 1,177, 0, 0, 1,199, 0, 0, 1,201, 0, 0, 0, 1, 0, 0, 1,200,
+ 0, 0, 1,178, 0, 0, 1,176, 0, 0, 1,202, 0, 0, 0, 1, 0, 0, 1,177, 0, 0, 1,179, 0, 0, 1,197, 0, 0, 1,199,
+ 0, 0, 0, 1, 0, 0, 1,198, 0, 0, 1,180, 0, 0, 1,178, 0, 0, 1,200, 0, 0, 0, 1, 0, 0, 1,179, 0, 0, 1,181,
+ 0, 0, 1,195, 0, 0, 1,197, 0, 0, 0, 1, 0, 0, 1,196, 0, 0, 1,182, 0, 0, 1,180, 0, 0, 1,198, 0, 0, 0, 1,
+ 0, 0, 1,181, 0, 0, 1,159, 0, 0, 1,215, 0, 0, 1,195, 0, 0, 0, 1, 0, 0, 1,216, 0, 0, 1,160, 0, 0, 1,182,
+ 0, 0, 1,196, 0, 0, 0, 1, 0, 0, 1,169, 0, 0, 1,157, 0, 0, 1,217, 0, 0, 1,205, 0, 0, 0, 1, 0, 0, 1,218,
+ 0, 0, 1,158, 0, 0, 1,170, 0, 0, 1,206, 0, 0, 0, 1, 0, 0, 1,167, 0, 0, 1,169, 0, 0, 1,205, 0, 0, 1,207,
+ 0, 0, 0, 1, 0, 0, 1,206, 0, 0, 1,170, 0, 0, 1,168, 0, 0, 1,208, 0, 0, 0, 1, 0, 0, 1,165, 0, 0, 1,167,
+ 0, 0, 1,207, 0, 0, 1,209, 0, 0, 0, 1, 0, 0, 1,208, 0, 0, 1,168, 0, 0, 1,166, 0, 0, 1,210, 0, 0, 0, 1,
+ 0, 0, 1,163, 0, 0, 1,165, 0, 0, 1,209, 0, 0, 1,211, 0, 0, 0, 1, 0, 0, 1,210, 0, 0, 1,166, 0, 0, 1,164,
+ 0, 0, 1,212, 0, 0, 0, 1, 0, 0, 1,161, 0, 0, 1,163, 0, 0, 1,211, 0, 0, 1,213, 0, 0, 0, 1, 0, 0, 1,212,
+ 0, 0, 1,164, 0, 0, 1,162, 0, 0, 1,214, 0, 0, 0, 1, 0, 0, 1,159, 0, 0, 1,161, 0, 0, 1,213, 0, 0, 1,215,
+ 0, 0, 0, 1, 0, 0, 1,214, 0, 0, 1,162, 0, 0, 1,160, 0, 0, 1,216, 0, 0, 0, 1, 0, 0, 1,199, 0, 0, 1,197,
+ 0, 0, 1,221, 0, 0, 1,219, 0, 0, 0, 1, 0, 0, 1,222, 0, 0, 1,198, 0, 0, 1,200, 0, 0, 1,220, 0, 0, 0, 1,
+ 0, 0, 1,219, 0, 0, 1,221, 0, 0, 1,223, 0, 0, 1,225, 0, 0, 0, 1, 0, 0, 1,224, 0, 0, 1,222, 0, 0, 1,220,
+ 0, 0, 1,226, 0, 0, 0, 1, 0, 0, 1,225, 0, 0, 1,223, 0, 0, 1,229, 0, 0, 1,227, 0, 0, 0, 1, 0, 0, 1,230,
+ 0, 0, 1,224, 0, 0, 1,226, 0, 0, 1,228, 0, 0, 0, 1, 0, 0, 1,227, 0, 0, 1,229, 0, 0, 1,231, 0, 0, 1,233,
+ 0, 0, 0, 1, 0, 0, 1,232, 0, 0, 1,230, 0, 0, 1,228, 0, 0, 1,234, 0, 0, 0, 1, 0, 0, 1,205, 0, 0, 1,217,
+ 0, 0, 1,227, 0, 0, 1,233, 0, 0, 0, 1, 0, 0, 1,228, 0, 0, 1,218, 0, 0, 1,206, 0, 0, 1,234, 0, 0, 0, 1,
+ 0, 0, 1,193, 0, 0, 1,225, 0, 0, 1,227, 0, 0, 1,217, 0, 0, 0, 1, 0, 0, 1,228, 0, 0, 1,226, 0, 0, 1,194,
+ 0, 0, 1,218, 0, 0, 0, 1, 0, 0, 1,193, 0, 0, 1,203, 0, 0, 1,219, 0, 0, 1,225, 0, 0, 0, 1, 0, 0, 1,220,
+ 0, 0, 1,204, 0, 0, 1,194, 0, 0, 1,226, 0, 0, 0, 1, 0, 0, 1,199, 0, 0, 1,219, 0, 0, 1,203, 0, 0, 1,201,
+ 0, 0, 0, 1, 0, 0, 1,204, 0, 0, 1,220, 0, 0, 1,200, 0, 0, 1,202, 0, 0, 0, 1, 0, 0, 1,195, 0, 0, 1,215,
+ 0, 0, 1,221, 0, 0, 1,197, 0, 0, 0, 1, 0, 0, 1,222, 0, 0, 1,216, 0, 0, 1,196, 0, 0, 1,198, 0, 0, 0, 1,
+ 0, 0, 1,213, 0, 0, 1,223, 0, 0, 1,221, 0, 0, 1,215, 0, 0, 0, 1, 0, 0, 1,222, 0, 0, 1,224, 0, 0, 1,214,
+ 0, 0, 1,216, 0, 0, 0, 1, 0, 0, 1,211, 0, 0, 1,229, 0, 0, 1,223, 0, 0, 1,213, 0, 0, 0, 1, 0, 0, 1,224,
+ 0, 0, 1,230, 0, 0, 1,212, 0, 0, 1,214, 0, 0, 0, 1, 0, 0, 1,209, 0, 0, 1,231, 0, 0, 1,229, 0, 0, 1,211,
+ 0, 0, 0, 1, 0, 0, 1,230, 0, 0, 1,232, 0, 0, 1,210, 0, 0, 1,212, 0, 0, 0, 1, 0, 0, 1,207, 0, 0, 1,233,
+ 0, 0, 1,231, 0, 0, 1,209, 0, 0, 0, 1, 0, 0, 1,232, 0, 0, 1,234, 0, 0, 1,208, 0, 0, 1,210, 0, 0, 0, 1,
+ 0, 0, 1,205, 0, 0, 1,233, 0, 0, 1,207, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,208, 0, 0, 1,234, 0, 0, 1,206,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,133, 0, 0, 1,131, 0, 0, 1,245, 0, 0, 1,243, 0, 0, 0, 1, 0, 0, 1,246,
+ 0, 0, 1,132, 0, 0, 1,134, 0, 0, 1,244, 0, 0, 0, 1, 0, 0, 1,135, 0, 0, 1,133, 0, 0, 1,243, 0, 0, 1,241,
+ 0, 0, 0, 1, 0, 0, 1,244, 0, 0, 1,134, 0, 0, 1,136, 0, 0, 1,242, 0, 0, 0, 1, 0, 0, 1,137, 0, 0, 1,135,
+ 0, 0, 1,241, 0, 0, 1,239, 0, 0, 0, 1, 0, 0, 1,242, 0, 0, 1,136, 0, 0, 1,138, 0, 0, 1,240, 0, 0, 0, 1,
+ 0, 0, 1,139, 0, 0, 1,137, 0, 0, 1,239, 0, 0, 1,237, 0, 0, 0, 1, 0, 0, 1,240, 0, 0, 1,138, 0, 0, 1,140,
+ 0, 0, 1,238, 0, 0, 0, 1, 0, 0, 1,141, 0, 0, 1,139, 0, 0, 1,237, 0, 0, 1,235, 0, 0, 0, 1, 0, 0, 1,238,
+ 0, 0, 1,140, 0, 0, 1,142, 0, 0, 1,236, 0, 0, 0, 1, 0, 0, 1,129, 0, 0, 1,141, 0, 0, 1,235, 0, 0, 1,247,
+ 0, 0, 0, 1, 0, 0, 1,236, 0, 0, 1,142, 0, 0, 1,130, 0, 0, 1,248, 0, 0, 0, 1, 0, 0, 1,235, 0, 0, 1,243,
+ 0, 0, 1,245, 0, 0, 1,247, 0, 0, 0, 1, 0, 0, 1,246, 0, 0, 1,244, 0, 0, 1,236, 0, 0, 1,248, 0, 0, 0, 1,
+ 0, 0, 1,235, 0, 0, 1,237, 0, 0, 1,241, 0, 0, 1,243, 0, 0, 0, 1, 0, 0, 1,242, 0, 0, 1,238, 0, 0, 1,236,
+ 0, 0, 1,244, 0, 0, 0, 1, 0, 0, 1,237, 0, 0, 1,239, 0, 0, 1,241, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,242,
+ 0, 0, 1,240, 0, 0, 1,238, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 55, 0, 0, 1,123, 0, 0, 1,129, 0, 0, 1,247,
+ 0, 0, 0, 1, 0, 0, 1,130, 0, 0, 1,124, 0, 0, 1, 56, 0, 0, 1,248, 0, 0, 0, 1, 0, 0, 1, 55, 0, 0, 1,247,
+ 0, 0, 1,245, 0, 0, 1, 63, 0, 0, 0, 1, 0, 0, 1,246, 0, 0, 1,248, 0, 0, 1, 56, 0, 0, 1, 64, 0, 0, 0, 1,
+ 0, 0, 1, 61, 0, 0, 1, 63, 0, 0, 1,245, 0, 0, 1,131, 0, 0, 0, 1, 0, 0, 1,246, 0, 0, 1, 64, 0, 0, 1, 62,
+ 0, 0, 1,132, 0, 0, 0, 1, 68, 65, 84, 65, 0, 0, 85,240, 12,117,208, 32, 0, 0, 0, 65, 0, 0, 1,244, 63, 28,112, 3,
+ 62,236,178,185, 63, 27,124,224, 62,232, 65,235, 63, 30, 63,144, 62,226,195,233, 63, 32,152,118, 62,236,167, 37, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0,240, 62,209,232, 2, 62,226, 21,222, 62,215,109,102, 62,231,147,222, 62,213,135, 28, 62,236, 4,172,
+ 62,205, 54, 56, 62,235,249, 22, 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 32,152,118, 62,236,167, 37, 63, 30, 63,144,
+ 62,226,195,233, 63, 33,235,108, 62,220,235,197, 63, 37,151,209, 62,236,161, 89, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240,
+ 62,202,144, 76, 62,220, 61,186, 62,209,232, 2, 62,226, 21,222, 62,205, 54, 56, 62,235,249, 22, 62,195, 55,128, 62,235,243, 70,
+ 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 30, 63,144, 62,226,195,233, 63, 25, 55, 20, 62,223, 35, 1, 63, 25,178,200,
+ 62,214,233, 77, 63, 33,235,108, 62,220,235,197, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 62,219, 1,146, 62,214, 59, 66,
+ 62,219,248,248, 62,222,116,246, 62,209,232, 2, 62,226, 21,222, 62,202,144, 76, 62,220, 61,186, 13, 64,158,176, 61, 0, 0, 5,
+ 0, 0, 0,240, 63, 27,124,224, 62,232, 65,235, 63, 24,252, 87, 62,230,111, 93, 63, 25, 55, 20, 62,223, 35, 1, 63, 30, 63,144,
+ 62,226,195,233, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 62,219,248,248, 62,222,116,246, 62,220,110,118, 62,229,193, 78,
+ 62,215,109,102, 62,231,147,222, 62,209,232, 2, 62,226, 21,222, 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 24,252, 87,
+ 62,230,111, 93, 63, 22,195, 22, 62,232, 90,195, 63, 20, 91,191, 62,227, 18,193, 63, 25, 55, 20, 62,223, 35, 1, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0,240, 62,229,175,162, 62,226,100,178, 62,224,224,248, 62,231,172,182, 62,220,110,118, 62,229,193, 78,
+ 62,219,248,248, 62,222,116,246, 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 25, 55, 20, 62,223, 35, 1, 63, 20, 91,191,
+ 62,227, 18,193, 63, 17,165,187, 62,221, 6,225, 63, 25,178,200, 62,214,233, 77, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240,
+ 62,235, 27,170, 62,220, 88,214, 62,229,175,162, 62,226,100,178, 62,219,248,248, 62,222,116,246, 62,219, 1,146, 62,214, 59, 66,
+ 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 20, 91,191, 62,227, 18,193, 63, 18, 18,164, 62,236,201,173, 63, 13,231,157,
+ 62,236,161, 89, 63, 17,165,187, 62,221, 6,225, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 62,242,151,232, 62,235,243, 70,
+ 62,234, 65,216, 62,236, 27,158, 62,229,175,162, 62,226,100,178, 62,235, 27,170, 62,220, 88,214, 13, 64,158,176, 61, 0, 0, 5,
+ 0, 0, 0,240, 63, 22,195, 22, 62,232, 90,195, 63, 21,202, 11, 62,236,189, 1, 63, 18, 18,164, 62,236,201,173, 63, 20, 91,191,
+ 62,227, 18,193, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 62,234, 65,216, 62,236, 27,158, 62,226,211, 12, 62,236, 14,246,
+ 62,224,224,248, 62,231,172,182, 62,229,175,162, 62,226,100,178, 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 21,202, 11,
+ 62,236,189, 1, 63, 22,202,215, 62,241,124,237, 63, 20,105,125, 62,246, 71, 1, 63, 18, 18,164, 62,236,201,173, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0,240, 62,229,148, 42, 62,245,152,246, 62,224,209,112, 62,240,206,226, 62,226,211, 12, 62,236, 14,246,
+ 62,234, 65,216, 62,236, 27,158, 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 18, 18,164, 62,236,201,173, 63, 20,105,125,
+ 62,246, 71, 1, 63, 17,173, 44, 62,252,149,231, 63, 13,231,157, 62,236,161, 89, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240,
+ 62,235, 12,206, 62,251,231,218, 62,229,148, 42, 62,245,152,246, 62,234, 65,216, 62,236, 27,158, 62,242,151,232, 62,235,243, 70,
+ 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 20,105,125, 62,246, 71, 1, 63, 25, 59, 37, 62,250, 73, 49, 63, 25,178,108,
+ 63, 1,108,218, 63, 17,173, 44, 62,252,149,231, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 62,219, 2, 76, 63, 1, 21,213,
+ 62,219,240,216, 62,249,155, 38, 62,229,148, 42, 62,245,152,246, 62,235, 12,206, 62,251,231,218, 13, 64,158,176, 61, 0, 0, 5,
+ 0, 0, 0,240, 63, 22,202,215, 62,241,124,237, 63, 25, 1,195, 62,243,102,169, 63, 25, 59, 37, 62,250, 73, 49, 63, 20,105,125,
+ 62,246, 71, 1, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 62,219,240,216, 62,249,155, 38, 62,220, 99,156, 62,242,184,154,
+ 62,224,209,112, 62,240,206,226, 62,229,148, 42, 62,245,152,246, 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 25, 1,195,
+ 62,243,102,169, 63, 27,125,176, 62,241,145,149, 63, 30, 74,167, 62,246,153, 3, 63, 25, 59, 37, 62,250, 73, 49, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0,240, 62,209,209,212, 62,245,234,246, 62,215,107,192, 62,240,227,138, 62,220, 99,156, 62,242,184,154,
+ 62,219,240,216, 62,249,155, 38, 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 25, 59, 37, 62,250, 73, 49, 63, 30, 74,167,
+ 62,246,153, 3, 63, 33,230,204, 62,252,232,107, 63, 25,178,108, 63, 1,108,218, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240,
+ 62,202,153,132, 62,252, 58, 94, 62,209,209,212, 62,245,234,246, 62,219,240,216, 62,249,155, 38, 62,219, 2, 76, 63, 1, 21,213,
+ 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 30, 74,167, 62,246,153, 3, 63, 32,152,118, 62,236,167, 37, 63, 37,151,209,
+ 62,236,161, 89, 63, 33,230,204, 62,252,232,107, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 62,195, 55,128, 62,235,243, 70,
+ 62,205, 54, 56, 62,235,249, 22, 62,209,209,212, 62,245,234,246, 62,202,153,132, 62,252, 58, 94, 13, 64,158,176, 61, 0, 0, 5,
+ 0, 0, 0,240, 63, 27,125,176, 62,241,145,149, 63, 28,112, 3, 62,236,178,185, 63, 32,152,118, 62,236,167, 37, 63, 30, 74,167,
+ 62,246,153, 3, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 62,205, 54, 56, 62,235,249, 22, 62,213,135, 28, 62,236, 4,172,
+ 62,215,107,192, 62,240,227,138, 62,209,209,212, 62,245,234,246, 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 28,112, 3,
+ 62,236,178,185, 63, 27,125,176, 62,241,145,149, 63, 27, 39, 42, 62,241, 1, 57, 63, 27,249,140, 62,236,186,115, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0,240, 62,216, 24,206, 62,240, 83, 46, 62,215,107,192, 62,240,227,138, 62,213,135, 28, 62,236, 4,172,
+ 62,214,116, 8, 62,236, 12,102, 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 27,125,176, 62,241,145,149, 63, 25, 1,195,
+ 62,243,102,169, 63, 24,248, 6, 62,242, 91,185, 63, 27, 39, 42, 62,241, 1, 57, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240,
+ 62,220,119, 22, 62,241,173,174, 62,220, 99,156, 62,242,184,154, 62,215,107,192, 62,240,227,138, 62,216, 24,206, 62,240, 83, 46,
+ 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 25, 1,195, 62,243,102,169, 63, 22,202,215, 62,241,124,237, 63, 23, 38,157,
+ 62,240,173,225, 63, 24,248, 6, 62,242, 91,185, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 62,224, 25,234, 62,239,255,214,
+ 62,224,209,112, 62,240,206,226, 62,220, 99,156, 62,242,184,154, 62,220,119, 22, 62,241,173,174, 13, 64,158,176, 61, 0, 0, 5,
+ 0, 0, 0,240, 63, 22,202,215, 62,241,124,237, 63, 21,202, 11, 62,236,189, 1, 63, 22, 89, 13, 62,236,196,247, 63, 23, 38,157,
+ 62,240,173,225, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 62,225,181, 8, 62,236, 22,234, 62,226,211, 12, 62,236, 14,246,
+ 62,224,209,112, 62,240,206,226, 62,224, 25,234, 62,239,255,214, 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 21,202, 11,
+ 62,236,189, 1, 63, 22,195, 22, 62,232, 90,195, 63, 23, 33, 88, 62,233, 47, 69, 63, 22, 89, 13, 62,236,196,247, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0,240, 62,224, 36,112, 62,232,129, 58, 62,224,224,248, 62,231,172,182, 62,226,211, 12, 62,236, 14,246,
+ 62,225,181, 8, 62,236, 22,234, 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 22,195, 22, 62,232, 90,195, 63, 24,252, 87,
+ 62,230,111, 93, 63, 24,243,100, 62,231,123, 5, 63, 23, 33, 88, 62,233, 47, 69, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240,
+ 62,220,128, 90, 62,230,204,248, 62,220,110,118, 62,229,193, 78, 62,224,224,248, 62,231,172,182, 62,224, 36,112, 62,232,129, 58,
+ 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 24,252, 87, 62,230,111, 93, 63, 27,124,224, 62,232, 65,235, 63, 27, 37,169,
+ 62,232,211, 35, 63, 24,243,100, 62,231,123, 5, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 62,216, 27,206, 62,232, 37, 22,
+ 62,215,109,102, 62,231,147,222, 62,220,110,118, 62,229,193, 78, 62,220,128, 90, 62,230,204,248, 13, 64,158,176, 61, 0, 0, 5,
+ 0, 0, 0,240, 63, 27,124,224, 62,232, 65,235, 63, 28,112, 3, 62,236,178,185, 63, 27,249,140, 62,236,186,115, 63, 27, 37,169,
+ 62,232,211, 35, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 62,214,116, 8, 62,236, 12,102, 62,213,135, 28, 62,236, 4,172,
+ 62,215,109,102, 62,231,147,222, 62,216, 27,206, 62,232, 37, 22, 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,240, 63, 24,242,138,
+ 62,236,194, 21, 63, 27, 37,169, 62,232,211, 35, 63, 27,249,140, 62,236,186,115, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0,112, 62,214,116, 8, 62,236, 12,102, 62,216, 27,206, 62,232, 37, 22, 62,220,130, 16, 62,236, 20, 6,
+ 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,112, 63, 24,243,100, 62,231,123, 5, 63, 27, 37,169,
+ 62,232,211, 35, 63, 24,242,138, 62,236,194, 21, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,112,
+ 62,220,130, 16, 62,236, 20, 6, 62,216, 27,206, 62,232, 37, 22, 62,220,128, 90, 62,230,204,248, 63,128, 0, 0, 63,128, 0, 0,
+ 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,112, 63, 24,242,138, 62,236,194, 21, 63, 23, 33, 88, 62,233, 47, 69, 63, 24,243,100,
+ 62,231,123, 5, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,112, 62,220,128, 90, 62,230,204,248,
+ 62,224, 36,112, 62,232,129, 58, 62,220,130, 16, 62,236, 20, 6, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 61, 0, 0, 5,
+ 0, 0, 0,112, 63, 24,242,138, 62,236,194, 21, 63, 22, 89, 13, 62,236,196,247, 63, 23, 33, 88, 62,233, 47, 69, 63,128, 0, 0,
+ 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,112, 62,224, 36,112, 62,232,129, 58, 62,225,181, 8, 62,236, 22,234,
+ 62,220,130, 16, 62,236, 20, 6, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,112, 63, 24,242,138,
+ 62,236,194, 21, 63, 23, 38,157, 62,240,173,225, 63, 22, 89, 13, 62,236,196,247, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0,112, 62,225,181, 8, 62,236, 22,234, 62,224, 25,234, 62,239,255,214, 62,220,130, 16, 62,236, 20, 6,
+ 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,112, 63, 24,242,138, 62,236,194, 21, 63, 24,248, 6,
+ 62,242, 91,185, 63, 23, 38,157, 62,240,173,225, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,112,
+ 62,224, 25,234, 62,239,255,214, 62,220,119, 22, 62,241,173,174, 62,220,130, 16, 62,236, 20, 6, 63,128, 0, 0, 63,128, 0, 0,
+ 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,112, 63, 24,242,138, 62,236,194, 21, 63, 27, 39, 42, 62,241, 1, 57, 63, 24,248, 6,
+ 62,242, 91,185, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,112, 62,220,119, 22, 62,241,173,174,
+ 62,216, 24,206, 62,240, 83, 46, 62,220,130, 16, 62,236, 20, 6, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 61, 0, 0, 5,
+ 0, 0, 0,112, 63, 24,242,138, 62,236,194, 21, 63, 27,249,140, 62,236,186,115, 63, 27, 39, 42, 62,241, 1, 57, 63,128, 0, 0,
+ 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,112, 62,216, 24,206, 62,240, 83, 46, 62,214,116, 8, 62,236, 12,102,
+ 62,220,130, 16, 62,236, 20, 6, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 61, 0, 0, 5, 0, 0, 0,112, 63, 16,254,174,
+ 62, 34, 45, 94, 63, 13,190, 79, 62, 46,193,160, 63, 3,199,220, 62, 24,219, 89, 63, 3,199,219, 61,229, 28, 18, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 16, 63, 3,199,220, 62, 24,219, 89, 62,243,150, 14, 62, 47, 79,204, 62,236,248,140, 62, 34,202,182,
+ 63, 3,199,219, 61,229, 28, 18, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 64, 63, 21,152,184, 62, 53, 47,182, 63, 16,104,250,
+ 62, 55,113, 16, 63, 13,190, 79, 62, 46,193,160, 63, 16,254,174, 62, 34, 45, 94, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,128,
+ 62,243,150, 14, 62, 47, 79,204, 62,238, 68,200, 62, 56, 62, 76, 62,227,207,183, 62, 54, 75,250, 62,236,248,140, 62, 34,202,182,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,128, 63, 22, 57,137, 62, 61, 93, 81, 63, 16,186,206, 62, 72,129, 85, 63, 16,104,250,
+ 62, 55,113, 16, 63, 21,152,184, 62, 53, 47,182, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,238, 68,200, 62, 56, 62, 76,
+ 62,237,187,192, 62, 73,118,194, 62,226,152,122, 62, 62,166,190, 62,227,207,183, 62, 54, 75,250, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 22,249,250, 62, 88,251,160, 63, 16, 32,222, 62, 93,106, 34, 63, 16,186,206, 62, 72,129, 85, 63, 22, 57,137,
+ 62, 61, 93, 81, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,237,187,192, 62, 73,118,194, 62,239, 19, 21, 62, 94,110,121,
+ 62,225, 83, 90, 62, 90,153, 21, 62,226,152,122, 62, 62,166,190, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 25, 81, 20,
+ 62,132, 56, 17, 63, 15,243,206, 62,136,207,182, 63, 16, 32,222, 62, 93,106, 34, 63, 22,249,250, 62, 88,251,160, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,239, 19, 21, 62, 94,110,121, 62,239,193, 92, 62,137, 61,113, 62,221, 42, 54, 62,133, 25,209,
+ 62,225, 83, 90, 62, 90,153, 21, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 27,239,111, 62,166, 77,159, 63, 37, 94, 91,
+ 62,187,120,107, 63, 30, 21, 66, 62,200,139,178, 63, 12,237,158, 62,187,241, 38, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,211,125,139, 62,200,171,170, 62,197, 28,156, 62,187,130,166, 62,216, 21,115, 62,166,177, 14, 62,245,175, 15, 62,188, 14,188,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 37, 94, 91, 62,187,120,107, 63, 43, 57, 87, 62,206, 58,222, 63, 39,163, 24,
+ 62,216, 95,174, 63, 30, 21, 66, 62,200,139,178, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,191,194, 98, 62,216, 94, 42,
+ 62,184,207,130, 62,206, 27, 42, 62,197, 28,156, 62,187,130,166, 62,211,125,139, 62,200,171,170, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 43, 57, 87, 62,206, 58,222, 63, 50,229, 38, 62,226, 32,169, 63, 43, 79,177, 62,231,194,202, 63, 39,163, 24,
+ 62,216, 95,174, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,183,201, 60, 62,231,218, 82, 62,168, 39,196, 62,226, 11,206,
+ 62,184,207,130, 62,206, 27, 42, 62,191,194, 98, 62,216, 94, 42, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 50,229, 38,
+ 62,226, 32,169, 63, 48,134, 62, 62,249,107, 37, 63, 43,190,154, 62,249, 0,192, 63, 43, 79,177, 62,231,194,202, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,182,190,138, 62,249, 49, 35, 62,172,229,172, 62,249,127,116, 62,168, 39,196, 62,226, 11,206,
+ 62,183,201, 60, 62,231,218, 82, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 48,134, 62, 62,249,107, 37, 63, 46, 88,238,
+ 63, 2,223,146, 63, 40,207,123, 62,254,175,218, 63, 43,190,154, 62,249, 0,192, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,188,184, 2, 62,255, 0,140, 62,177, 87,173, 63, 3, 9,102, 62,172,229,172, 62,249,127,116, 62,182,190,138, 62,249, 49, 35,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 46, 88,238, 63, 2,223,146, 63, 34,158,220, 63, 10, 23,175, 63, 30, 77,126,
+ 63, 5, 88,156, 63, 40,207,123, 62,254,175,218, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,210, 65, 89, 63, 5,158, 56,
+ 62,201,109,124, 63, 10,121, 72, 62,177, 87,173, 63, 3, 9,102, 62,188,184, 2, 62,255, 0,140, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 34,158,220, 63, 10, 23,175, 63, 26,105, 28, 63, 11,194,242, 63, 25,120,244, 63, 7,242, 78, 63, 30, 77,126,
+ 63, 5, 88,156, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,220, 39, 0, 63, 8, 58,252, 62,218, 73,220, 63, 12, 31,169,
+ 62,201,109,124, 63, 10,121, 72, 62,210, 65, 89, 63, 5,158, 56, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 26,105, 28,
+ 63, 11,194,242, 63, 22,244,173, 63, 11,215,236, 63, 22, 47,202, 63, 8, 60,156, 63, 25,120,244, 63, 7,242, 78, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,226,221, 11, 63, 8,125, 90, 62,225, 89,220, 63, 12, 42, 77, 62,218, 73,220, 63, 12, 31,169,
+ 62,220, 39, 0, 63, 8, 58,252, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 22,244,173, 63, 11,215,236, 63, 11,169, 67,
+ 63, 11,197, 18, 63, 12,252,106, 63, 3,173,180, 63, 22, 47,202, 63, 8, 60,156, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,245,114, 35, 63, 3,196,233, 62,248, 72, 55, 63, 11,232, 91, 62,225, 89,220, 63, 12, 42, 77, 62,226,221, 11, 63, 8,125, 90,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 11,169, 67, 63, 11,197, 18, 63, 3,232,148, 63, 11, 17,164, 63, 3,220,162,
+ 63, 0, 88, 45, 63, 12,252,106, 63, 3,173,180, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 3,220,162, 63, 0, 88, 45,
+ 63, 3,232,148, 63, 11, 17,164, 62,248, 72, 55, 63, 11,232, 91, 62,245,114, 35, 63, 3,196,233, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 17, 59,103, 62,255,195,120, 63, 22, 81,240, 63, 1, 70,114, 63, 22, 47,202, 63, 8, 60,156, 63, 12,252,106,
+ 63, 3,173,180, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,226,221, 11, 63, 8,125, 90, 62,226,128,106, 63, 1,111,198,
+ 62,236,213,209, 62,255,250, 4, 62,245,114, 35, 63, 3,196,233, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 22, 81,240,
+ 63, 1, 70,114, 63, 25,182,151, 63, 1, 9,130, 63, 25,120,244, 63, 7,242, 78, 63, 22, 47,202, 63, 8, 60,156, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,220, 39, 0, 63, 8, 58,252, 62,219,150,213, 63, 1, 55, 50, 62,226,128,106, 63, 1,111,198,
+ 62,226,221, 11, 63, 8,125, 90, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 30, 49, 96, 62,254,229,121, 63, 30, 77,126,
+ 63, 5, 88,156, 63, 25,120,244, 63, 7,242, 78, 63, 25,182,151, 63, 1, 9,130, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,220, 39, 0, 63, 8, 58,252, 62,210, 65, 89, 63, 5,158, 56, 62,210,116,176, 62,255, 62,227, 62,219,150,213, 63, 1, 55, 50,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 37,113, 25, 62,247,157, 35, 63, 40,207,123, 62,254,175,218, 63, 30, 77,126,
+ 63, 5, 88,156, 63, 30, 49, 96, 62,254,229,121, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,210, 65, 89, 63, 5,158, 56,
+ 62,188,184, 2, 62,255, 0,140, 62,195,165,189, 62,247,232,139, 62,210,116,176, 62,255, 62,227, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 39, 62, 92, 62,240, 75,121, 63, 43,190,154, 62,249, 0,192, 63, 40,207,123, 62,254,175,218, 63, 37,113, 25,
+ 62,247,157, 35, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,188,184, 2, 62,255, 0,140, 62,182,190,138, 62,249, 49, 35,
+ 62,192, 10,222, 62,240,128,163, 62,195,165,189, 62,247,232,139, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 38,149,140,
+ 62,229, 95, 38, 63, 43, 79,177, 62,231,194,202, 63, 43,190,154, 62,249, 0,192, 63, 39, 62, 92, 62,240, 75,121, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,182,190,138, 62,249, 49, 35, 62,183,201, 60, 62,231,218, 82, 62,193,140,168, 62,229,129, 94,
+ 62,192, 10,222, 62,240,128,163, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 33,120, 14, 62,214,238,166, 63, 39,163, 24,
+ 62,216, 95,174, 63, 43, 79,177, 62,231,194,202, 63, 38,149,140, 62,229, 95, 38, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,183,201, 60, 62,231,218, 82, 62,191,194, 98, 62,216, 94, 42, 62,204, 75,168, 62,215, 7, 62, 62,193,140,168, 62,229,129, 94,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 27,178,165, 62,208, 17,128, 63, 30, 21, 66, 62,200,139,178, 63, 39,163, 24,
+ 62,216, 95,174, 63, 33,120, 14, 62,214,238,166, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,191,194, 98, 62,216, 94, 42,
+ 62,211,125,139, 62,200,171,170, 62,216, 24, 6, 62,208, 57,128, 62,204, 75,168, 62,215, 7, 62, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 17, 97, 15, 62,214, 34,220, 63, 12,237,158, 62,187,241, 38, 63, 30, 21, 66, 62,200,139,178, 63, 27,178,165,
+ 62,208, 17,128, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,211,125,139, 62,200,171,170, 62,245,175, 15, 62,188, 14,188,
+ 62,236,200,217, 62,214, 49,134, 62,216, 24, 6, 62,208, 57,128, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 17, 97, 15,
+ 62,214, 34,220, 63, 14,244,149, 62,221, 42, 4, 63, 3,230,147, 62,208, 47, 78, 63, 12,237,158, 62,187,241, 38, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 63, 3,230,147, 62,208, 47, 78, 62,241,144,141, 62,221, 52,244, 62,236,200,217, 62,214, 49,134,
+ 62,245,175, 15, 62,188, 14,188, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 17, 59,103, 62,255,195,120, 63, 12,252,106,
+ 63, 3,173,180, 63, 3,220,162, 63, 0, 88, 45, 63, 13, 25, 71, 62,243,163,116, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 63, 3,220,162, 63, 0, 88, 45, 62,245,114, 35, 63, 3,196,233, 62,236,213,209, 62,255,250, 4, 62,245, 45, 0, 62,243,185,206,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 13, 25, 71, 62,243,163,116, 63, 3,220,162, 63, 0, 88, 45, 63, 3,220,215,
+ 62,231,189,148, 63, 13, 2, 64, 62,230,215, 52, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 3,220,215, 62,231,189,148,
+ 63, 3,220,162, 63, 0, 88, 45, 62,245, 45, 0, 62,243,185,206, 62,245,100,219, 62,230,230,184, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 3,230,147, 62,208, 47, 78, 63, 14,244,149, 62,221, 42, 4, 63, 13, 2, 64, 62,230,215, 52, 63, 3,220,215,
+ 62,231,189,148, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,245,100,219, 62,230,230,184, 62,241,144,141, 62,221, 52,244,
+ 63, 3,230,147, 62,208, 47, 78, 63, 3,220,215, 62,231,189,148, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 7, 61,250,
+ 62, 54, 31,148, 63, 3,202,193, 62, 49,174,214, 63, 3,199,220, 62, 24,219, 89, 63, 13,190, 79, 62, 46,193,160, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 63, 3,199,220, 62, 24,219, 89, 63, 3,202,193, 62, 49,174,214, 63, 0, 87,175, 62, 54, 90,251,
+ 62,243,150, 14, 62, 47, 79,204, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 9,214, 68, 62, 66,237,246, 63, 7, 61,250,
+ 62, 54, 31,148, 63, 13,190, 79, 62, 46,193,160, 63, 16,104,250, 62, 55,113, 16, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,243,150, 14, 62, 47, 79,204, 63, 0, 87,175, 62, 54, 90,251, 62,251,137,104, 62, 67, 92,179, 62,238, 68,200, 62, 56, 62, 76,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 8,221,237, 62, 91, 90,218, 63, 9,214, 68, 62, 66,237,246, 63, 16,104,250,
+ 62, 55,113, 16, 63, 16,186,206, 62, 72,129, 85, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,238, 68,200, 62, 56, 62, 76,
+ 62,251,137,104, 62, 67, 92,179, 62,253,153, 39, 62, 91,195, 27, 62,237,187,192, 62, 73,118,194, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 15,243,206, 62,136,207,182, 63, 8, 32, 77, 62,139, 39, 10, 63, 9,117, 22, 62, 97,203,146, 63, 16, 32,222,
+ 62, 93,106, 34, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,252,110,192, 62, 98, 68, 79, 62,255, 89,219, 62,139, 79,116,
+ 62,239,193, 92, 62,137, 61,113, 62,239, 19, 21, 62, 94,110,121, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 8,221,237,
+ 62, 91, 90,218, 63, 16,186,206, 62, 72,129, 85, 63, 16, 32,222, 62, 93,106, 34, 63, 9,117, 22, 62, 97,203,146, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,239, 19, 21, 62, 94,110,121, 62,237,187,192, 62, 73,118,194, 62,253,153, 39, 62, 91,195, 27,
+ 62,252,110,192, 62, 98, 68, 79, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 9,125,119, 62,158,112, 7, 63, 3,233, 70,
+ 62,154, 27, 88, 63, 3,229,235, 62,139,108, 97, 63, 8, 32, 77, 62,139, 39, 10, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 63, 3,229,235, 62,139,108, 97, 63, 3,233, 70, 62,154, 27, 88, 62,252,179,165, 62,158,140,163, 62,255, 89,219, 62,139, 79,116,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 9,117, 22, 62, 97,203,146, 63, 8, 32, 77, 62,139, 39, 10, 63, 3,229,235,
+ 62,139,108, 97, 63, 3,215,246, 62,101, 56,143, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 3,229,235, 62,139,108, 97,
+ 62,255, 89,219, 62,139, 79,116, 62,252,110,192, 62, 98, 68, 79, 63, 3,215,246, 62,101, 56,143, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 3,210,147, 62, 86, 95,221, 63, 8,221,237, 62, 91, 90,218, 63, 9,117, 22, 62, 97,203,146, 63, 3,215,246,
+ 62,101, 56,143, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,252,110,192, 62, 98, 68, 79, 62,253,153, 39, 62, 91,195, 27,
+ 63, 3,210,147, 62, 86, 95,221, 63, 3,215,246, 62,101, 56,143, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 12, 54, 5,
+ 62,167,183,188, 63, 9, 61,250, 62,168,214,252, 63, 8,143,152, 62,163,107, 45, 63, 9,125,119, 62,158,112, 7, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,254,136,100, 62,163,123, 38, 62,253, 39,110, 62,168,224,103, 62,247, 68, 98, 62,167,206,146,
+ 62,252,179,165, 62,158,140,163, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 10,196,135, 62,178,208, 52, 63, 8,233, 25,
+ 62,175,110,116, 63, 9, 61,250, 62,168,214,252, 63, 12, 54, 5, 62,167,183,188, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,253, 39,110, 62,168,224,103, 62,253,195,102, 62,175,102,184, 62,250, 14, 98, 62,178,202,149, 62,247, 68, 98, 62,167,206,146,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 4, 17, 69, 62,182,176,105, 63, 6,138, 69, 62,177,180, 80, 63, 8,233, 25,
+ 62,175,110,116, 63, 10,196,135, 62,178,208, 52, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,253,195,102, 62,175,102,184,
+ 63, 1, 49, 14, 62,177,150, 62, 63, 4, 17, 69, 62,182,176,105, 62,250, 14, 98, 62,178,202,149, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 3,124,209, 62,177, 0, 70, 63, 3,232, 11, 62,174, 4,140, 63, 6,138, 69, 62,177,180, 80, 63, 4, 17, 69,
+ 62,182,176,105, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 1, 49, 14, 62,177,150, 62, 63, 3,232, 11, 62,174, 4,140,
+ 63, 3,124,209, 62,177, 0, 70, 63, 4, 17, 69, 62,182,176,105, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 3,233, 70,
+ 62,154, 27, 88, 63, 9,125,119, 62,158,112, 7, 63, 8,143,152, 62,163,107, 45, 63, 3,232,212, 62,158,152, 58, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,254,136,100, 62,163,123, 38, 62,252,179,165, 62,158,140,163, 63, 3,233, 70, 62,154, 27, 88,
+ 63, 3,232,212, 62,158,152, 58, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 3,232,212, 62,158,152, 58, 63, 8,143,152,
+ 62,163,107, 45, 63, 7, 91,121, 62,166, 51,134, 63, 3,231,205, 62,162,149, 58, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 63, 0,116, 44, 62,166, 56,255, 62,254,136,100, 62,163,123, 38, 63, 3,232,212, 62,158,152, 58, 63, 3,231,205, 62,162,149, 58,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 3,232, 11, 62,174, 4,140, 63, 3,233,214, 62,170,154,198, 63, 6,110,233,
+ 62,174,152, 94, 63, 6,138, 69, 62,177,180, 80, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 1, 82,228, 62,174,140, 95,
+ 63, 3,233,214, 62,170,154,198, 63, 3,232, 11, 62,174, 4,140, 63, 1, 49, 14, 62,177,150, 62, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 6,138, 69, 62,177,180, 80, 63, 6,110,233, 62,174,152, 94, 63, 7,236, 59, 62,173,123, 19, 63, 8,233, 25,
+ 62,175,110,116, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,255,185,217, 62,173,116, 92, 63, 1, 82,228, 62,174,140, 95,
+ 63, 1, 49, 14, 62,177,150, 62, 62,253,195,102, 62,175,102,184, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 8,233, 25,
+ 62,175,110,116, 63, 7,236, 59, 62,173,123, 19, 63, 7,249, 85, 62,169, 52, 92, 63, 9, 61,250, 62,168,214,252, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,255,169,160, 62,169, 57, 6, 62,255,185,217, 62,173,116, 92, 62,253,195,102, 62,175,102,184,
+ 62,253, 39,110, 62,168,224,103, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 9, 61,250, 62,168,214,252, 63, 7,249, 85,
+ 62,169, 52, 92, 63, 7, 91,121, 62,166, 51,134, 63, 8,143,152, 62,163,107, 45, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 63, 0,116, 44, 62,166, 56,255, 62,255,169,160, 62,169, 57, 6, 62,253, 39,110, 62,168,224,103, 62,254,136,100, 62,163,123, 38,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 3,233,214, 62,170,154,198, 63, 7,249, 85, 62,169, 52, 92, 63, 7,236, 59,
+ 62,173,123, 19, 63, 6,110,233, 62,174,152, 94, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,255,185,217, 62,173,116, 92,
+ 62,255,169,160, 62,169, 57, 6, 63, 3,233,214, 62,170,154,198, 63, 1, 82,228, 62,174,140, 95, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 3,233,214, 62,170,154,198, 63, 3,231,205, 62,162,149, 58, 63, 7, 91,121, 62,166, 51,134, 63, 7,249, 85,
+ 62,169, 52, 92, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 0,116, 44, 62,166, 56,255, 63, 3,231,205, 62,162,149, 58,
+ 63, 3,233,214, 62,170,154,198, 62,255,169,160, 62,169, 57, 6, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 4, 17, 69,
+ 62,182,176,105, 63, 10,196,135, 62,178,208, 52, 63, 12,237,158, 62,187,241, 38, 63, 3,230,147, 62,208, 47, 78, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,245,175, 15, 62,188, 14,188, 62,250, 14, 98, 62,178,202,149, 63, 4, 17, 69, 62,182,176,105,
+ 63, 3,230,147, 62,208, 47, 78, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 10,196,135, 62,178,208, 52, 63, 12, 54, 5,
+ 62,167,183,188, 63, 16, 0,112, 62,164,246,254, 63, 12,237,158, 62,187,241, 38, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,239,187,207, 62,165, 42, 19, 62,247, 68, 98, 62,167,206,146, 62,250, 14, 98, 62,178,202,149, 62,245,175, 15, 62,188, 14,188,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 12, 54, 5, 62,167,183,188, 63, 9,125,119, 62,158,112, 7, 63, 15,250, 44,
+ 62,154, 0,109, 63, 16, 0,112, 62,164,246,254, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,239,205, 56, 62,154, 71, 8,
+ 62,252,179,165, 62,158,140,163, 62,247, 68, 98, 62,167,206,146, 62,239,187,207, 62,165, 42, 19, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 9,125,119, 62,158,112, 7, 63, 8, 32, 77, 62,139, 39, 10, 63, 15,243,206, 62,136,207,182, 63, 15,250, 44,
+ 62,154, 0,109, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,239,193, 92, 62,137, 61,113, 62,255, 89,219, 62,139, 79,116,
+ 62,252,179,165, 62,158,140,163, 62,239,205, 56, 62,154, 71, 8, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 25, 81, 20,
+ 62,132, 56, 17, 63, 27, 46,208, 62,148, 35,149, 63, 15,250, 44, 62,154, 0,109, 63, 15,243,206, 62,136,207,182, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,239,205, 56, 62,154, 71, 8, 62,217,166,238, 62,148,221,229, 62,221, 42, 54, 62,133, 25,209,
+ 62,239,193, 92, 62,137, 61,113, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 27, 46,208, 62,148, 35,149, 63, 27,177, 36,
+ 62,156,151,158, 63, 16, 0,112, 62,164,246,254, 63, 15,250, 44, 62,154, 0,109, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,239,187,207, 62,165, 42, 19, 62,216,160, 0, 62,157, 44,127, 62,217,166,238, 62,148,221,229, 62,239,205, 56, 62,154, 71, 8,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 27,239,111, 62,166, 77,159, 63, 12,237,158, 62,187,241, 38, 63, 16, 0,112,
+ 62,164,246,254, 63, 27,177, 36, 62,156,151,158, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,239,187,207, 62,165, 42, 19,
+ 62,245,175, 15, 62,188, 14,188, 62,216, 21,115, 62,166,177, 14, 62,216,160, 0, 62,157, 44,127, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 8,221,237, 62, 91, 90,218, 63, 3,210,147, 62, 86, 95,221, 63, 3,211,129, 62, 83,168,248, 63, 8, 33,170,
+ 62, 86,149,254, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 3,211,129, 62, 83,168,248, 63, 3,210,147, 62, 86, 95,221,
+ 62,253,153, 39, 62, 91,195, 27, 62,255, 14, 8, 62, 86,232, 58, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 9,214, 68,
+ 62, 66,237,246, 63, 8,221,237, 62, 91, 90,218, 63, 8, 33,170, 62, 86,149,254, 63, 8,180, 20, 62, 69, 29, 94, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,255, 14, 8, 62, 86,232, 58, 62,253,153, 39, 62, 91,195, 27, 62,251,137,104, 62, 67, 92,179,
+ 62,253,210, 19, 62, 69,114, 55, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 7, 61,250, 62, 54, 31,148, 63, 9,214, 68,
+ 62, 66,237,246, 63, 8,180, 20, 62, 69, 29, 94, 63, 6, 82,168, 62, 57, 43, 80, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,253,210, 19, 62, 69,114, 55, 62,251,137,104, 62, 67, 92,179, 63, 0, 87,175, 62, 54, 90,251, 63, 1, 68, 48, 62, 57, 84,166,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 3,202,193, 62, 49,174,214, 63, 7, 61,250, 62, 54, 31,148, 63, 6, 82,168,
+ 62, 57, 43, 80, 63, 3,202,205, 62, 54, 22, 8, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 1, 68, 48, 62, 57, 84,166,
+ 63, 0, 87,175, 62, 54, 90,251, 63, 3,202,193, 62, 49,174,214, 63, 3,202,205, 62, 54, 22, 8, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 3,202,205, 62, 54, 22, 8, 63, 6, 82,168, 62, 57, 43, 80, 63, 5, 24,246, 62, 66,150, 26, 63, 3,205,213,
+ 62, 64,232,220, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 2,131, 29, 62, 66,172, 22, 63, 1, 68, 48, 62, 57, 84,166,
+ 63, 3,202,205, 62, 54, 22, 8, 63, 3,205,213, 62, 64,232,220, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 6, 82,168,
+ 62, 57, 43, 80, 63, 8,180, 20, 62, 69, 29, 94, 63, 6, 83, 39, 62, 70,114,191, 63, 5, 24,246, 62, 66,150, 26, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 63, 1, 75,185, 62, 70,160,222, 62,253,210, 19, 62, 69,114, 55, 63, 1, 68, 48, 62, 57, 84,166,
+ 63, 2,131, 29, 62, 66,172, 22, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 8,180, 20, 62, 69, 29, 94, 63, 8, 33,170,
+ 62, 86,149,254, 63, 6,111, 4, 62, 76,172, 40, 63, 6, 83, 39, 62, 70,114,191, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 63, 1, 51,157, 62, 76,218,158, 62,255, 14, 8, 62, 86,232, 58, 62,253,210, 19, 62, 69,114, 55, 63, 1, 75,185, 62, 70,160,222,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 8, 33,170, 62, 86,149,254, 63, 3,211,129, 62, 83,168,248, 63, 3,208,234,
+ 62, 75, 43,146, 63, 6,111, 4, 62, 76,172, 40, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 3,208,234, 62, 75, 43,146,
+ 63, 3,211,129, 62, 83,168,248, 62,255, 14, 8, 62, 86,232, 58, 63, 1, 51,157, 62, 76,218,158, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 3,208,234, 62, 75, 43,146, 63, 3,205,213, 62, 64,232,220, 63, 5, 24,246, 62, 66,150, 26, 63, 6,111, 4,
+ 62, 76,172, 40, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 2,131, 29, 62, 66,172, 22, 63, 3,205,213, 62, 64,232,220,
+ 63, 3,208,234, 62, 75, 43,146, 63, 1, 51,157, 62, 76,218,158, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 6,111, 4,
+ 62, 76,172, 40, 63, 5, 24,246, 62, 66,150, 26, 63, 6, 83, 39, 62, 70,114,191, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 63, 1, 75,185, 62, 70,160,222, 63, 2,131, 29, 62, 66,172, 22, 63, 1, 51,157, 62, 76,218,158,
+ 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 13, 2, 64, 62,230,215, 52, 63, 14,244,149,
+ 62,221, 42, 4, 63, 16,216, 4, 62,224, 24,160, 63, 15,200,120, 62,231,255, 84, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,237,193,119, 62,224, 38,190, 62,241,144,141, 62,221, 52,244, 62,245,100,219, 62,230,230,184, 62,239,211, 21, 62,232, 18,185,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 13, 25, 71, 62,243,163,116, 63, 13, 2, 64, 62,230,215, 52, 63, 15,200,120,
+ 62,231,255, 84, 63, 16,171,184, 62,241,133, 40, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,239,211, 21, 62,232, 18,185,
+ 62,245,100,219, 62,230,230,184, 62,245, 45, 0, 62,243,185,206, 62,237,252,218, 62,241,160, 62, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 17, 59,103, 62,255,195,120, 63, 13, 25, 71, 62,243,163,116, 63, 16,171,184, 62,241,133, 40, 63, 19, 44, 55,
+ 62,250, 21, 86, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,237,252,218, 62,241,160, 62, 62,245, 45, 0, 62,243,185,206,
+ 62,236,213,209, 62,255,250, 4, 62,232,228,153, 62,250, 67,154, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 14,244,149,
+ 62,221, 42, 4, 63, 17, 97, 15, 62,214, 34,220, 63, 19, 53,217, 62,218,211, 16, 63, 16,216, 4, 62,224, 24,160, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,233, 14, 8, 62,218,226, 66, 62,236,200,217, 62,214, 49,134, 62,241,144,141, 62,221, 52,244,
+ 62,237,193,119, 62,224, 38,190, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 17, 97, 15, 62,214, 34,220, 63, 27,178,165,
+ 62,208, 17,128, 63, 26,198,205, 62,214,184,124, 63, 19, 53,217, 62,218,211, 16, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,217,214,216, 62,214,224,218, 62,216, 24, 6, 62,208, 57,128, 62,236,200,217, 62,214, 49,134, 62,233, 14, 8, 62,218,226, 66,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 27,178,165, 62,208, 17,128, 63, 33,120, 14, 62,214,238,166, 63, 31,136,156,
+ 62,219,138,194, 63, 26,198,205, 62,214,184,124, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,208, 30,254, 62,219,177,204,
+ 62,204, 75,168, 62,215, 7, 62, 62,216, 24, 6, 62,208, 57,128, 62,217,214,216, 62,214,224,218, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 33,120, 14, 62,214,238,166, 63, 38,149,140, 62,229, 95, 38, 63, 36, 9, 79, 62,229,224, 94, 63, 31,136,156,
+ 62,219,138,194, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,198,192,148, 62,230, 11,182, 62,193,140,168, 62,229,129, 94,
+ 62,204, 75,168, 62,215, 7, 62, 62,208, 30,254, 62,219,177,204, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 38,149,140,
+ 62,229, 95, 38, 63, 39, 62, 92, 62,240, 75,121, 63, 36, 49, 14, 62,239, 88,253, 63, 36, 9, 79, 62,229,224, 94, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,198, 71, 97, 62,239,149,192, 62,192, 10,222, 62,240,128,163, 62,193,140,168, 62,229,129, 94,
+ 62,198,192,148, 62,230, 11,182, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 39, 62, 92, 62,240, 75,121, 63, 37,113, 25,
+ 62,247,157, 35, 63, 35, 33,243, 62,245,143, 80, 63, 36, 49, 14, 62,239, 88,253, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,200, 99, 87, 62,245,217,172, 62,195,165,189, 62,247,232,139, 62,192, 10,222, 62,240,128,163, 62,198, 71, 97, 62,239,149,192,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 37,113, 25, 62,247,157, 35, 63, 30, 49, 96, 62,254,229,121, 63, 29, 49,223,
+ 62,250,140,199, 63, 35, 33,243, 62,245,143, 80, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,212,124,147, 62,250,215,146,
+ 62,210,116,176, 62,255, 62,227, 62,195,165,189, 62,247,232,139, 62,200, 99, 87, 62,245,217,172, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 30, 49, 96, 62,254,229,121, 63, 25,182,151, 63, 1, 9,130, 63, 25,181, 50, 62,253,111,118, 63, 29, 49,223,
+ 62,250,140,199, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,219,151, 52, 62,253,186, 68, 62,219,150,213, 63, 1, 55, 50,
+ 62,210,116,176, 62,255, 62,227, 62,212,124,147, 62,250,215,146, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 25,182,151,
+ 63, 1, 9,130, 63, 22, 81,240, 63, 1, 70,114, 63, 22,188,241, 62,253,149, 28, 63, 25,181, 50, 62,253,111,118, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,225,163,212, 62,253,215, 91, 62,226,128,106, 63, 1,111,198, 62,219,150,213, 63, 1, 55, 50,
+ 62,219,151, 52, 62,253,186, 68, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 22, 81,240, 63, 1, 70,114, 63, 17, 59,103,
+ 62,255,195,120, 63, 19, 44, 55, 62,250, 21, 86, 63, 22,188,241, 62,253,149, 28, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,232,228,153, 62,250, 67,154, 62,236,213,209, 62,255,250, 4, 62,226,128,106, 63, 1,111,198, 62,225,163,212, 62,253,215, 91,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 22,188,241, 62,253,149, 28, 63, 19, 44, 55, 62,250, 21, 86, 63, 20,165, 9,
+ 62,247, 99,248, 63, 23, 0, 20, 62,251, 57, 6, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,229,232,232, 62,247,142, 74,
+ 62,232,228,153, 62,250, 67,154, 62,225,163,212, 62,253,215, 91, 62,225, 26,145, 62,251,116,114, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 25,181, 50, 62,253,111,118, 63, 22,188,241, 62,253,149, 28, 63, 23, 0, 20, 62,251, 57, 6, 63, 25,144,130,
+ 62,251, 7,128, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,225, 26,145, 62,251,116,114, 62,225,163,212, 62,253,215, 91,
+ 62,219,151, 52, 62,253,186, 68, 62,219,225,177, 62,251, 75, 67, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 29, 49,223,
+ 62,250,140,199, 63, 25,181, 50, 62,253,111,118, 63, 25,144,130, 62,251, 7,128, 63, 28,195, 80, 62,248,166, 55, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,219,225,177, 62,251, 75, 67, 62,219,151, 52, 62,253,186, 68, 62,212,124,147, 62,250,215,146,
+ 62,213, 95,233, 62,248,237, 20, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 35, 33,243, 62,245,143, 80, 63, 29, 49,223,
+ 62,250,140,199, 63, 28,195, 80, 62,248,166, 55, 63, 33,164, 22, 62,243, 75,102, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,213, 95,233, 62,248,237, 20, 62,212,124,147, 62,250,215,146, 62,200, 99, 87, 62,245,217,172, 62,203,114, 65, 62,243,143,159,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 36, 49, 14, 62,239, 88,253, 63, 35, 33,243, 62,245,143, 80, 63, 33,164, 22,
+ 62,243, 75,102, 63, 34,160, 30, 62,238, 47,169, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,203,114, 65, 62,243,143,159,
+ 62,200, 99, 87, 62,245,217,172, 62,198, 71, 97, 62,239,149,192, 62,201,128,188, 62,238,110,126, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 36, 9, 79, 62,229,224, 94, 63, 36, 49, 14, 62,239, 88,253, 63, 34,160, 30, 62,238, 47,169, 63, 34,144,131,
+ 62,231, 87,253, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,201,128,188, 62,238,110,126, 62,198, 71, 97, 62,239,149,192,
+ 62,198,192,148, 62,230, 11,182, 62,201,190,141, 62,231,140,124, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 31,136,156,
+ 62,219,138,194, 63, 36, 9, 79, 62,229,224, 94, 63, 34,144,131, 62,231, 87,253, 63, 30,208, 21, 62,221,182,174, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,201,190,141, 62,231,140,124, 62,198,192,148, 62,230, 11,182, 62,208, 30,254, 62,219,177,204,
+ 62,209,133,168, 62,221,221, 51, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 26,198,205, 62,214,184,124, 63, 31,136,156,
+ 62,219,138,194, 63, 30,208, 21, 62,221,182,174, 63, 26,218,128, 62,217,206, 68, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,209,133,168, 62,221,221, 51, 62,208, 30,254, 62,219,177,204, 62,217,214,216, 62,214,224,218, 62,217,157, 11, 62,217,243, 64,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 19, 53,217, 62,218,211, 16, 63, 26,198,205, 62,214,184,124, 63, 26,218,128,
+ 62,217,206, 68, 63, 20, 53,103, 62,221, 84,236, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,217,157, 11, 62,217,243, 64,
+ 62,217,214,216, 62,214,224,218, 62,233, 14, 8, 62,218,226, 66, 62,231, 5, 68, 62,221,101,234, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 16,216, 4, 62,224, 24,160, 63, 19, 53,217, 62,218,211, 16, 63, 20, 53,103, 62,221, 84,236, 63, 18, 87, 81,
+ 62,226,175, 33, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,231, 5, 68, 62,221,101,234, 62,233, 14, 8, 62,218,226, 66,
+ 62,237,193,119, 62,224, 38,190, 62,234,187,180, 62,226,190,249, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 19, 44, 55,
+ 62,250, 21, 86, 63, 16,171,184, 62,241,133, 40, 63, 18, 68, 98, 62,240,197,150, 63, 20,165, 9, 62,247, 99,248, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,234,197, 35, 62,240,226,215, 62,237,252,218, 62,241,160, 62, 62,232,228,153, 62,250, 67,154,
+ 62,229,232,232, 62,247,142, 74, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 16,171,184, 62,241,133, 40, 63, 15,200,120,
+ 62,231,255, 84, 63, 18, 4,161, 62,232,184,138, 63, 18, 68, 98, 62,240,197,150, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,235, 85,154, 62,232,206, 92, 62,239,211, 21, 62,232, 18,185, 62,237,252,218, 62,241,160, 62, 62,234,197, 35, 62,240,226,215,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 15,200,120, 62,231,255, 84, 63, 16,216, 4, 62,224, 24,160, 63, 18, 87, 81,
+ 62,226,175, 33, 63, 18, 4,161, 62,232,184,138, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,234,187,180, 62,226,190,249,
+ 62,237,193,119, 62,224, 38,190, 62,239,211, 21, 62,232, 18,185, 62,235, 85,154, 62,232,206, 92, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 3,232,148, 63, 11, 17,164, 63, 11,169, 67, 63, 11,197, 18, 63, 13,120,216, 63, 23, 81,160, 63, 4, 15,147,
+ 63, 23,248,227, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,245, 27, 64, 63, 23,166,100, 62,248, 72, 55, 63, 11,232, 91,
+ 63, 3,232,148, 63, 11, 17,164, 63, 4, 15,147, 63, 23,248,227, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 11,169, 67,
+ 63, 11,197, 18, 63, 22,244,173, 63, 11,215,236, 63, 23,233, 94, 63, 16, 60,186, 63, 13,120,216, 63, 23, 81,160, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,223,130,109, 63, 16,165,118, 62,225, 89,220, 63, 12, 42, 77, 62,248, 72, 55, 63, 11,232, 91,
+ 62,245, 27, 64, 63, 23,166,100, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 22,244,173, 63, 11,215,236, 63, 26,105, 28,
+ 63, 11,194,242, 63, 28, 56,220, 63, 14,250, 66, 63, 23,233, 94, 63, 16, 60,186, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,214,161,157, 63, 15,110,219, 62,218, 73,220, 63, 12, 31,169, 62,225, 89,220, 63, 12, 42, 77, 62,223,130,109, 63, 16,165,118,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 26,105, 28, 63, 11,194,242, 63, 34,158,220, 63, 10, 23,175, 63, 39, 44,109,
+ 63, 19,221,107, 63, 28, 56,220, 63, 14,250, 66, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,192, 26,156, 63, 20,139, 31,
+ 62,201,109,124, 63, 10,121, 72, 62,218, 73,220, 63, 12, 31,169, 62,214,161,157, 63, 15,110,219, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 34,158,220, 63, 10, 23,175, 63, 46, 88,238, 63, 2,223,146, 63, 56, 80,242, 63, 6,244, 44, 63, 39, 44,109,
+ 63, 19,221,107, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 64, 62,156,208, 61, 63, 7, 16,204, 62,177, 87,173, 63, 3, 9,102,
+ 62,201,109,124, 63, 10,121, 72, 62,192, 26,156, 63, 20,139, 31, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 16, 63, 46, 88,238,
+ 63, 2,223,146, 63, 48,134, 62, 62,249,107, 37, 63, 54,173,195, 62,252,106,239, 63, 56, 80,242, 63, 6,244, 44, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0,128, 62,160, 36,202, 62,252, 51, 94, 62,172,229,172, 62,249,127,116, 62,177, 87,173, 63, 3, 9,102,
+ 62,156,208, 61, 63, 7, 16,204, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,128, 63, 48,134, 62, 62,249,107, 37, 63, 50,229, 38,
+ 62,226, 32,169, 63, 53, 88,154, 62,221,146,240, 63, 54,173,195, 62,252,106,239, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 64,
+ 62,162,172,128, 62,221,169, 17, 62,168, 39,196, 62,226, 11,206, 62,172,229,172, 62,249,127,116, 62,160, 36,202, 62,252, 51, 94,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 16, 63, 50,229, 38, 62,226, 32,169, 63, 43, 57, 87, 62,206, 58,222, 63, 49,117,240,
+ 62,198,138,164, 63, 53, 88,154, 62,221,146,240, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,128, 62,172,137,147, 62,198, 19,148,
+ 62,184,207,130, 62,206, 27, 42, 62,168, 39,196, 62,226, 11,206, 62,162,172,128, 62,221,169, 17, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0,128, 63, 43, 57, 87, 62,206, 58,222, 63, 37, 94, 91, 62,187,120,107, 63, 41,160,156, 62,182,175, 56, 63, 49,117,240,
+ 62,198,138,164, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,188,212,202, 62,182,163,245, 62,197, 28,156, 62,187,130,166,
+ 62,184,207,130, 62,206, 27, 42, 62,172,137,147, 62,198, 19,148, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 48,252,165,
+ 62, 85, 33,133, 63, 48, 54,112, 62, 96, 19, 20, 63, 46, 36,172, 62,129, 7,208, 63, 42, 17,240, 62, 97, 84,129, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,181, 71, 76, 62,131,200,204, 62,175,121,117, 62,106,185,183, 62,172, 24,217, 62, 92,237, 21,
+ 62,187, 81,138, 62,103, 40, 59, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 48, 89,204, 62, 4,194,134, 63, 48,252,165,
+ 62, 85, 33,133, 63, 42, 17,240, 62, 97, 84,129, 63, 37,125,160, 62, 46,211, 50, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 16,
+ 62,187, 81,138, 62,103, 40, 59, 62,172, 24,217, 62, 92,237, 21, 62,172,197, 94, 62, 4,200,109, 62,195,121, 25, 62, 48,253, 46,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 64, 63, 20, 44, 11, 61,163, 26, 20, 63, 48, 89,204, 62, 4,194,134, 63, 37,125,160,
+ 62, 46,211, 50, 63, 24, 92, 40, 62, 21,184,214, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 32, 62,195,121, 25, 62, 48,253, 46,
+ 62,172,197, 94, 62, 4,200,109, 62,230,122,140, 61,161,248,202, 62,222, 13,216, 62, 22,116,222, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 32, 63, 16,254,174, 62, 34, 45, 94, 63, 3,199,219, 61,229, 28, 18, 63, 20, 44, 11, 61,163, 26, 20, 63, 24, 92, 40,
+ 62, 21,184,214, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 16, 62,230,122,140, 61,161,248,202, 63, 3,199,219, 61,229, 28, 18,
+ 62,236,248,140, 62, 34,202,182, 62,222, 13,216, 62, 22,116,222, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 64, 63, 21,152,184,
+ 62, 53, 47,182, 63, 16,254,174, 62, 34, 45, 94, 63, 24, 92, 40, 62, 21,184,214, 63, 25, 52,209, 62, 51,140, 76, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 32, 62,222, 13,216, 62, 22,116,222, 62,236,248,140, 62, 34,202,182, 62,227,207,183, 62, 54, 75,250,
+ 62,220,137,229, 62, 52,228,185, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 32, 63, 22, 57,137, 62, 61, 93, 81, 63, 21,152,184,
+ 62, 53, 47,182, 63, 25, 52,209, 62, 51,140, 76, 63, 30,166,193, 62, 73,168,114, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,220,137,229, 62, 52,228,185, 62,227,207,183, 62, 54, 75,250, 62,226,152,122, 62, 62,166,190, 62,209,198, 54, 62, 75,240, 18,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 22,249,250, 62, 88,251,160, 63, 22, 57,137, 62, 61, 93, 81, 63, 30,166,193,
+ 62, 73,168,114, 63, 36, 0, 75, 62,116, 47,229, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,209,198, 54, 62, 75,240, 18,
+ 62,226,152,122, 62, 62,166,190, 62,225, 83, 90, 62, 90,153, 21, 62,199,231,211, 62,119,237,216, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 30,166,193, 62, 73,168,114, 63, 37,125,160, 62, 46,211, 50, 63, 42, 17,240, 62, 97, 84,129, 63, 36, 0, 75,
+ 62,116, 47,229, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,187, 81,138, 62,103, 40, 59, 62,195,121, 25, 62, 48,253, 46,
+ 62,209,198, 54, 62, 75,240, 18, 62,199,231,211, 62,119,237,216, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 30,166,193,
+ 62, 73,168,114, 63, 25, 52,209, 62, 51,140, 76, 63, 24, 92, 40, 62, 21,184,214, 63, 37,125,160, 62, 46,211, 50, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,222, 13,216, 62, 22,116,222, 62,220,137,229, 62, 52,228,185, 62,209,198, 54, 62, 75,240, 18,
+ 62,195,121, 25, 62, 48,253, 46, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 36,163, 37, 62,140,168,191, 63, 36, 0, 75,
+ 62,116, 47,229, 63, 42, 17,240, 62, 97, 84,129, 63, 46, 36,172, 62,129, 7,208, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,187, 81,138, 62,103, 40, 59, 62,199,231,211, 62,119,237,216, 62,199, 64, 6, 62,142, 6,105, 62,181, 71, 76, 62,131,200,204,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 25, 81, 20, 62,132, 56, 17, 63, 22,249,250, 62, 88,251,160, 63, 36, 0, 75,
+ 62,116, 47,229, 63, 36,163, 37, 62,140,168,191, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,199,231,211, 62,119,237,216,
+ 62,225, 83, 90, 62, 90,153, 21, 62,221, 42, 54, 62,133, 25,209, 62,199, 64, 6, 62,142, 6,105, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 27, 46,208, 62,148, 35,149, 63, 36, 60, 91, 62,150,222,221, 63, 33,170,222, 62,158,126, 74, 63, 27,177, 36,
+ 62,156,151,158, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,204,234, 72, 62,159, 63, 56, 62,199,245,150, 62,152, 15, 85,
+ 62,217,166,238, 62,148,221,229, 62,216,160, 0, 62,157, 44,127, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 25, 81, 20,
+ 62,132, 56, 17, 63, 36,163, 37, 62,140,168,191, 63, 36, 60, 91, 62,150,222,221, 63, 27, 46,208, 62,148, 35,149, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,199,245,150, 62,152, 15, 85, 62,199, 64, 6, 62,142, 6,105, 62,221, 42, 54, 62,133, 25,209,
+ 62,217,166,238, 62,148,221,229, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 27,239,111, 62,166, 77,159, 63, 27,177, 36,
+ 62,156,151,158, 63, 33,170,222, 62,158,126, 74, 63, 31,212,102, 62,164,192,144, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,204,234, 72, 62,159, 63, 56, 62,216,160, 0, 62,157, 44,127, 62,216, 21,115, 62,166,177, 14, 62,208,119, 17, 62,165, 65,201,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 27,239,111, 62,166, 77,159, 63, 31,212,102, 62,164,192,144, 63, 41,160,156,
+ 62,182,175, 56, 63, 37, 94, 91, 62,187,120,107, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,188,212,202, 62,182,163,245,
+ 62,208,119, 17, 62,165, 65,201, 62,216, 21,115, 62,166,177, 14, 62,197, 28,156, 62,187,130,166, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 62,194,119,104, 63, 82,189,164, 62,212, 73, 23, 63, 90,239,152, 62,205,192,100, 63, 97,238, 46, 62,185, 56, 38,
+ 63, 91,154, 72, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 62,141, 94,228, 63,100,234, 86, 62,150, 66, 84, 63, 94,154,114,
+ 62,173, 86,230, 63, 98, 66, 79, 62,162,143, 20, 63,106,173, 44, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 63, 87,122, 72,
+ 62, 62, 8,216, 63, 84,106,202, 62,113,185,137, 63, 72, 77,226, 62,121, 21,204, 63, 71,225,158, 62, 68, 34,113, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 16, 62,137, 32,132, 62,121, 65,181, 62,107,179,168, 62,103,127,139, 62,114,147,210, 62, 61,116,212,
+ 62,142,125,248, 62, 80, 4, 30, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 64, 63, 71,225,158, 62, 68, 34,113, 63, 72, 77,226,
+ 62,121, 21,204, 63, 51, 7, 8, 62,130,186, 5, 63, 49,166, 3, 62, 96, 57,232, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,172,197, 18, 62,133,112, 41, 62,137, 32,132, 62,121, 65,181, 62,142,125,248, 62, 80, 4, 30, 62,174,228,121, 62,109, 79, 52,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 49,166, 3, 62, 96, 57,232, 63, 51, 7, 8, 62,130,186, 5, 63, 46, 36,172,
+ 62,129, 7,208, 63, 48, 54,112, 62, 96, 19, 20, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,181, 71, 76, 62,131,200,204,
+ 62,172,197, 18, 62,133,112, 41, 62,174,228,121, 62,109, 79, 52, 62,175,121,117, 62,106,185,183, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 36,163, 37, 62,140,168,191, 63, 46, 36,172, 62,129, 7,208, 63, 51, 7, 8, 62,130,186, 5, 63, 36, 60, 91,
+ 62,150,222,221, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,172,197, 18, 62,133,112, 41, 62,181, 71, 76, 62,131,200,204,
+ 62,199, 64, 6, 62,142, 6,105, 62,199,245,150, 62,152, 15, 85, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 53, 88,154,
+ 62,221,146,240, 63, 49,117,240, 62,198,138,164, 63, 69, 19,224, 62,190, 68, 24, 63, 74, 64, 53, 62,224, 31,171, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 16, 62,134, 78,250, 62,186,213,148, 62,172,137,147, 62,198, 19,148, 62,162,172,128, 62,221,169, 17,
+ 62,114,112,184, 62,220,169,248, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 64, 62,214, 74, 54, 63, 70, 55, 20, 62,233,130, 48,
+ 63, 83, 69,188, 62,212, 73, 23, 63, 90,239,152, 62,194,119,104, 63, 82,189,164, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240,
+ 62,150, 66, 84, 63, 94,154,114, 62,153, 1, 66, 63, 81,149,245, 62,185, 56, 38, 63, 83,110,102, 62,173, 86,230, 63, 98, 66, 79,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 63, 66,242,106, 63, 25, 94,202, 63, 70,100,190, 63, 15,234,222, 63, 77,189, 90,
+ 63, 17, 88,233, 63, 74,206, 8, 63, 27,118, 88, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 96, 32, 22, 63, 16, 60, 66,
+ 62,125, 87, 86, 63, 15, 5,174, 62,132,187, 78, 63, 24, 44,180, 62,108, 79, 26, 63, 26, 1,124, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 74,206, 8, 63, 27,118, 88, 63, 77,189, 90, 63, 17, 88,233, 63, 85,139, 72, 63, 19, 51,103, 63, 85,119,220,
+ 63, 31, 71, 77, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 64,199, 64, 63, 18, 40, 26, 62, 96, 32, 22, 63, 16, 60, 66,
+ 62,108, 79, 26, 63, 26, 1,124, 62, 67,191, 44, 63, 30, 89, 90, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 85,119,220,
+ 63, 31, 71, 77, 63, 85,139, 72, 63, 19, 51,103, 63,100,213,228, 63, 20,156, 72, 63, 96, 82, 18, 63, 34,133,128, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0,128, 62, 1, 50,226, 63, 20, 68,184, 62, 64,199, 64, 63, 18, 40, 26, 62, 67,191, 44, 63, 30, 89, 90,
+ 62, 24,204,194, 63, 34,186, 32, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,128, 63, 56, 80,242, 63, 6,244, 44, 63, 54,173,195,
+ 62,252,106,239, 63, 60,205,115, 62,253,150,213, 63, 64, 14,166, 63, 4, 80, 81, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 16,
+ 62,147, 85,190, 62,252,176, 91, 62,160, 36,202, 62,252, 51, 94, 62,156,208, 61, 63, 7, 16,204, 62,140,121,160, 63, 3,197, 74,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 64, 63, 64, 14,166, 63, 4, 80, 81, 63, 60,205,115, 62,253,150,213, 63, 73,103, 68,
+ 63, 0,248,233, 63, 75, 12,248, 63, 8,206, 64, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,115, 59,144, 62,255,143,102,
+ 62,147, 85,190, 62,252,176, 91, 62,140,121,160, 63, 3,197, 74, 62,107,135, 78, 63, 7,182, 88, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 75, 12,248, 63, 8,206, 64, 63, 73,103, 68, 63, 0,248,233, 63, 82,151,239, 63, 3,223, 86, 63, 82,227,181,
+ 63, 11,102,189, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 77, 17, 82, 63, 2, 98,162, 62,115, 59,144, 62,255,143,102,
+ 62,107,135, 78, 63, 7,182, 88, 62, 75, 98,202, 63, 10, 43,108, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 82,227,181,
+ 63, 11,102,189, 63, 82,151,239, 63, 3,223, 86, 63, 91,224, 92, 63, 5,144,239, 63, 90,148,161, 63, 13, 95,146, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62, 38, 40,178, 63, 3,230, 14, 62, 77, 17, 82, 63, 2, 98,162, 62, 75, 98,202, 63, 10, 43,108,
+ 62, 43,162, 10, 63, 12, 50, 8, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,103, 89,120, 63, 2, 76,105, 63,103,179,170,
+ 63, 12,105,142, 63, 90,148,161, 63, 13, 95,146, 63, 91,224, 92, 63, 5,144,239, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62, 43,162, 10, 63, 12, 50, 8, 61,231, 41,168, 63, 11, 83,158, 61,234,128,116, 63, 0, 39,200, 62, 38, 40,178, 63, 3,230, 14,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,100,213,228, 63, 20,156, 72, 63, 85,139, 72, 63, 19, 51,103, 63, 90,148,161,
+ 63, 13, 95,146, 63,103,179,170, 63, 12,105,142, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 43,162, 10, 63, 12, 50, 8,
+ 62, 64,199, 64, 63, 18, 40, 26, 62, 1, 50,226, 63, 20, 68,184, 61,231, 41,168, 63, 11, 83,158, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 85,139, 72, 63, 19, 51,103, 63, 77,189, 90, 63, 17, 88,233, 63, 82,227,181, 63, 11,102,189, 63, 90,148,161,
+ 63, 13, 95,146, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 75, 98,202, 63, 10, 43,108, 62, 96, 32, 22, 63, 16, 60, 66,
+ 62, 64,199, 64, 63, 18, 40, 26, 62, 43,162, 10, 63, 12, 50, 8, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 77,189, 90,
+ 63, 17, 88,233, 63, 70,100,190, 63, 15,234,222, 63, 75, 12,248, 63, 8,206, 64, 63, 82,227,181, 63, 11,102,189, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,107,135, 78, 63, 7,182, 88, 62,125, 87, 86, 63, 15, 5,174, 62, 96, 32, 22, 63, 16, 60, 66,
+ 62, 75, 98,202, 63, 10, 43,108, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 70,100,190, 63, 15,234,222, 63, 60,235, 82,
+ 63, 12, 12, 27, 63, 64, 14,166, 63, 4, 80, 81, 63, 75, 12,248, 63, 8,206, 64, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,140,121,160, 63, 3,197, 74, 62,145,230, 78, 63, 11,225,148, 62,125, 87, 86, 63, 15, 5,174, 62,107,135, 78, 63, 7,182, 88,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 57,118, 31, 63, 12, 79,230, 63, 56, 80,242, 63, 6,244, 44, 63, 64, 14,166,
+ 63, 4, 80, 81, 63, 60,235, 82, 63, 12, 12, 27, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 32, 62,140,121,160, 63, 3,197, 74,
+ 62,156,208, 61, 63, 7, 16,204, 62,152,199, 0, 63, 12,133, 13, 62,145,230, 78, 63, 11,225,148, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 32, 63, 57,240,195, 63, 23,138, 10, 63, 60,235, 82, 63, 12, 12, 27, 63, 70,100,190, 63, 15,234,222, 63, 66,242,106,
+ 63, 25, 94,202, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,125, 87, 86, 63, 15, 5,174, 62,145,230, 78, 63, 11,225,148,
+ 62,150, 7,247, 63, 23, 12, 96, 62,132,187, 78, 63, 24, 44,180, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 13,120,216,
+ 63, 23, 81,160, 63, 23,233, 94, 63, 16, 60,186, 63, 28, 56,220, 63, 14,250, 66, 63, 39, 44,109, 63, 19,221,107, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,214,161,157, 63, 15,110,219, 62,223,130,109, 63, 16,165,118, 62,245, 27, 64, 63, 23,166,100,
+ 62,192, 26,156, 63, 20,139, 31, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 56, 29,176, 63, 20,206, 88, 63, 57,118, 31,
+ 63, 12, 79,230, 63, 60,235, 82, 63, 12, 12, 27, 63, 57,240,195, 63, 23,138, 10, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,145,230, 78, 63, 11,225,148, 62,152,199, 0, 63, 12,133, 13, 62,153,211,239, 63, 20,159,220, 62,150, 7,247, 63, 23, 12, 96,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 54,148, 48, 63, 22,206,220, 63, 56, 29,176, 63, 20,206, 88, 63, 57,240,195,
+ 63, 23,138, 10, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,150, 7,247, 63, 23, 12, 96,
+ 62,153,211,239, 63, 20,159,220, 62,156,106,108, 63, 22,154,146, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 54,173,195, 62,252,106,239, 63, 53, 88,154, 62,221,146,240, 63, 74, 64, 53, 62,224, 31,171, 63, 60,205,115,
+ 62,253,150,213, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 32, 62,114,112,184, 62,220,169,248, 62,162,172,128, 62,221,169, 17,
+ 62,160, 36,202, 62,252, 51, 94, 62,147, 85,190, 62,252,176, 91, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 32, 63, 74, 64, 53,
+ 62,224, 31,171, 63, 81,106,217, 62,232,214, 14, 63, 73,103, 68, 63, 0,248,233, 63, 60,205,115, 62,253,150,213, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,115, 59,144, 62,255,143,102, 62, 84, 93, 88, 62,228,105, 50, 62,114,112,184, 62,220,169,248,
+ 62,147, 85,190, 62,252,176, 91, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 81,106,217, 62,232,214, 14, 63, 93,154,106,
+ 62,233, 26,226, 63, 82,151,239, 63, 3,223, 86, 63, 73,103, 68, 63, 0,248,233, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62, 77, 17, 82, 63, 2, 98,162, 62, 33, 1,128, 62,226,210, 70, 62, 84, 93, 88, 62,228,105, 50, 62,115, 59,144, 62,255,143,102,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,103, 89,120, 63, 2, 76,105, 63, 91,224, 92, 63, 5,144,239, 63, 82,151,239,
+ 63, 3,223, 86, 63, 93,154,106, 62,233, 26,226, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 77, 17, 82, 63, 2, 98,162,
+ 62, 38, 40,178, 63, 3,230, 14, 61,234,128,116, 63, 0, 39,200, 62, 33, 1,128, 62,226,210, 70, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 51, 7, 8, 62,130,186, 5, 63, 72, 77,226, 62,121, 21,204, 63, 73,254,154, 62,140, 82,178, 63, 56,188, 90,
+ 62,159,207,103, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,130,249,249, 62,137,175,246, 62,137, 32,132, 62,121, 65,181,
+ 62,172,197, 18, 62,133,112, 41, 62,161, 5,192, 62,159, 40,228, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 69, 19,224,
+ 62,190, 68, 24, 63, 56,188, 90, 62,159,207,103, 63, 73,254,154, 62,140, 82,178, 63, 77,217,216, 62,157,228, 7, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0,128, 62,130,249,249, 62,137,175,246, 62,161, 5,192, 62,159, 40,228, 62,134, 78,250, 62,186,213,148,
+ 62,111,118,154, 62,152,108,120, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,128, 63, 49,117,240, 62,198,138,164, 63, 41,160,156,
+ 62,182,175, 56, 63, 56,188, 90, 62,159,207,103, 63, 69, 19,224, 62,190, 68, 24, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62,161, 5,192, 62,159, 40,228, 62,188,212,202, 62,182,163,245, 62,172,137,147, 62,198, 19,148, 62,134, 78,250, 62,186,213,148,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 41,160,156, 62,182,175, 56, 63, 33,170,222, 62,158,126, 74, 63, 36, 60, 91,
+ 62,150,222,221, 63, 56,188, 90, 62,159,207,103, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,199,245,150, 62,152, 15, 85,
+ 62,204,234, 72, 62,159, 63, 56, 62,188,212,202, 62,182,163,245, 62,161, 5,192, 62,159, 40,228, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 36, 60, 91, 62,150,222,221, 63, 51, 7, 8, 62,130,186, 5, 63, 56,188, 90, 62,159,207,103, 63,128, 0, 0,
+ 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,161, 5,192, 62,159, 40,228, 62,172,197, 18, 62,133,112, 41,
+ 62,199,245,150, 62,152, 15, 85, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 41,160,156,
+ 62,182,175, 56, 63, 31,212,102, 62,164,192,144, 63, 33,170,222, 62,158,126, 74, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,204,234, 72, 62,159, 63, 56, 62,208,119, 17, 62,165, 65,201, 62,188,212,202, 62,182,163,245,
+ 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,245, 44,226, 63, 96,140,129, 62,227,135, 42,
+ 63,101, 2, 58, 62,219,168,136, 63, 95,236, 30, 62,238, 30,135, 63, 90, 41,200, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240,
+ 62,137,240,216, 63, 93,226, 90, 62,122,103,110, 63, 92,255,236, 62,120, 84, 74, 63, 83, 32,104, 62,138,193, 32, 63, 83, 3, 16,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 62,233,130, 48, 63, 83, 69,188, 62,238, 30,135, 63, 90, 41,200, 62,219,168,136,
+ 63, 95,236, 30, 62,212, 73, 23, 63, 90,239,152, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 62,137,240,216, 63, 93,226, 90,
+ 62,138,193, 32, 63, 83, 3, 16, 62,153, 1, 66, 63, 81,149,245, 62,150, 66, 84, 63, 94,154,114, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0,240, 63, 77,217,216, 62,157,228, 7, 63, 73,254,154, 62,140, 82,178, 63, 90, 61, 33, 62,124,207,195, 63, 90,225,160,
+ 62,137,121,110, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 16, 62, 81,207, 98, 62,110, 1,109, 62,130,249,249, 62,137,175,246,
+ 62,111,118,154, 62,152,108,120, 62, 74,125,166, 62,130, 30,252, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 64, 63, 72, 77,226,
+ 62,121, 21,204, 63, 84,106,202, 62,113,185,137, 63, 90, 61, 33, 62,124,207,195, 63, 73,254,154, 62,140, 82,178, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62, 81,207, 98, 62,110, 1,109, 62,107,179,168, 62,103,127,139, 62,137, 32,132, 62,121, 65,181,
+ 62,130,249,249, 62,137,175,246, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,212, 73, 23, 63, 90,239,152, 62,219,168,136,
+ 63, 95,236, 30, 62,205,192,100, 63, 97,238, 46, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,112,
+ 62,141, 94,228, 63,100,234, 86, 62,137,240,216, 63, 93,226, 90, 62,150, 66, 84, 63, 94,154,114, 63,128, 0, 0, 63,128, 0, 0,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,112, 63,109,178, 31, 62,228, 68,224, 63,102,178, 46, 62,232,184,100, 63,101,251,100,
+ 62,227,198,238, 63,107,173, 94, 62,225,130,168, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 61,249,209, 68, 62,219,134, 70,
+ 61,242,216,120, 62,225, 40,124, 61,177, 27, 28, 62,219,240, 42, 61,196,131, 76, 62,216, 97,196, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63,109,178, 31, 62,228, 68,224, 63,107,173, 94, 62,225,130,168, 63,114,102,144, 62,220, 23,198, 63,116, 76, 41,
+ 62,222,153,139, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 61,120,163, 56, 62,208,252, 58, 61,196,131, 76, 62,216, 97,196,
+ 61,177, 27, 28, 62,219,240, 42, 61, 73,183,128, 62,213,108, 84, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,116, 76, 41,
+ 62,222,153,139, 63,114,102,144, 62,220, 23,198, 63,117, 87, 84, 62,211,255,221, 63,119,115,183, 62,215, 49,140, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 61, 55, 29,144, 62,194,183,207, 61,120,163, 56, 62,208,252, 58, 61, 73,183,128, 62,213,108, 84,
+ 60,231,111,224, 62,198,142,100, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,119,115,183, 62,215, 49,140, 63,117, 87, 84,
+ 62,211,255,221, 63,118, 20,150, 62,196,110, 60, 63,122, 12, 49, 62,197, 8,246, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 61,103,197, 96, 62,170,206, 15, 61, 55, 29,144, 62,194,183,207, 60,231,111,224, 62,198,142,100, 61, 16, 54,240, 62,167, 4,120,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,122, 12, 49, 62,197, 8,246, 63,118, 20,150, 62,196,110, 60, 63,108,155, 17,
+ 62,178,201,130, 63,110,190, 84, 62,172, 77,223, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 61,246,252,148, 62,160,116,164,
+ 61,103,197, 96, 62,170,206, 15, 61, 16, 54,240, 62,167, 4,120, 61,246, 66, 8, 62,152,161, 28, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63,110,190, 84, 62,172, 77,223, 63,108,155, 17, 62,178,201,130, 63, 92,180, 21, 62,173, 95,202, 63, 90, 5,151,
+ 62,167, 61,138, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 54,216,144, 62,163, 76, 35, 61,246,252,148, 62,160,116,164,
+ 61,246, 66, 8, 62,152,161, 28, 62, 66,251,194, 62,158,102,163, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,108,155, 17,
+ 62,178,201,130, 63,109,132,198, 62,186,157,182, 63, 97, 32, 68, 62,178, 12,192, 63, 92,180, 21, 62,173, 95,202, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62, 36,185, 48, 62,166, 7, 16, 61,221, 91, 40, 62,167,194, 4, 61,246,252,148, 62,160,116,164,
+ 62, 54,216,144, 62,163, 76, 35, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,118, 20,150, 62,196,110, 60, 63,115,225, 84,
+ 62,198, 85,208, 63,109,132,198, 62,186,157,182, 63,108,155, 17, 62,178,201,130, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 61,221, 91, 40, 62,167,194, 4, 61,134,221,244, 62,175,164,121, 61,103,197, 96, 62,170,206, 15, 61,246,252,148, 62,160,116,164,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,117, 87, 84, 62,211,255,221, 63,116, 48,222, 62,209, 8,169, 63,115,225, 84,
+ 62,198, 85,208, 63,118, 20,150, 62,196,110, 60, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 61,134,221,244, 62,175,164,121,
+ 61, 93,108,160, 62,190,207, 17, 61, 55, 29,144, 62,194,183,207, 61,103,197, 96, 62,170,206, 15, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63,114,102,144, 62,220, 23,198, 63,113,151,174, 62,214,229, 26, 63,116, 48,222, 62,209, 8,169, 63,117, 87, 84,
+ 62,211,255,221, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 61, 93,108,160, 62,190,207, 17, 61,135,155, 12, 62,201, 39,166,
+ 61,120,163, 56, 62,208,252, 58, 61, 55, 29,144, 62,194,183,207, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,107,173, 94,
+ 62,225,130,168, 63,107,239,228, 62,218, 59, 62, 63,113,151,174, 62,214,229, 26, 63,114,102,144, 62,220, 23,198, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 61,135,155, 12, 62,201, 39,166, 61,195, 47,128, 62,207, 11, 6, 61,196,131, 76, 62,216, 97,196,
+ 61,120,163, 56, 62,208,252, 58, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,107,173, 94, 62,225,130,168, 63,101,251,100,
+ 62,227,198,238, 63,102,205, 71, 62,219, 94,132, 63,107,239,228, 62,218, 59, 62, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 61,244,157,192, 62,209,137,157, 61,249,209, 68, 62,219,134, 70, 61,196,131, 76, 62,216, 97,196, 61,195, 47,128, 62,207, 11, 6,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 69, 19,224, 62,190, 68, 24, 63, 77,217,216, 62,157,228, 7, 63, 85, 35,236,
+ 62,181,201,164, 63, 78, 92, 56, 62,188,114,177, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 32, 62, 80, 91,122, 62,174, 18, 72,
+ 62,111,118,154, 62,152,108,120, 62,134, 78,250, 62,186,213,148, 62,104,163,162, 62,182,180,150, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 32, 63, 77,217,216, 62,157,228, 7, 63, 90, 5,151, 62,167, 61,138, 63, 92,180, 21, 62,173, 95,202, 63, 85, 35,236,
+ 62,181,201,164, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 16, 62, 54,216,144, 62,163, 76, 35, 62, 66,251,194, 62,158,102,163,
+ 62,111,118,154, 62,152,108,120, 62, 80, 91,122, 62,174, 18, 72, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 64, 63, 74, 64, 53,
+ 62,224, 31,171, 63, 69, 19,224, 62,190, 68, 24, 63, 78, 92, 56, 62,188,114,177, 63, 81,106,217, 62,232,214, 14, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62,104,163,162, 62,182,180,150, 62,134, 78,250, 62,186,213,148, 62,114,112,184, 62,220,169,248,
+ 62, 84, 93, 88, 62,228,105, 50, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 93,154,106, 62,233, 26,226, 63, 94,229,196,
+ 62,224,195,128, 63,101,251,100, 62,227,198,238, 63,102,178, 46, 62,232,184,100, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 61,249,209, 68, 62,219,134, 70, 62, 28,187,108, 62,217, 86, 48, 62, 33, 1,128, 62,226,210, 70, 61,242,216,120, 62,225, 40,124,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 92,180, 21, 62,173, 95,202, 63, 97, 32, 68, 62,178, 12,192, 63, 94,215, 9,
+ 62,186, 54, 4, 63, 85, 35,236, 62,181,201,164, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 41,122, 60, 62,175, 58, 16,
+ 62, 36,185, 48, 62,166, 7, 16, 62, 54,216,144, 62,163, 76, 35, 62, 80, 91,122, 62,174, 18, 72, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 95, 78,230, 62,189,233, 4, 63, 86,188, 32, 62,190, 62, 44, 63, 85, 35,236, 62,181,201,164, 63, 94,215, 9,
+ 62,186, 54, 4, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 80, 91,122, 62,174, 18, 72, 62, 71,118, 78, 62,182, 49, 27,
+ 62, 37,225, 52, 62,179, 12, 40, 62, 41,122, 60, 62,175, 58, 16, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 92,166, 70,
+ 62,197,166, 0, 63, 86,188, 32, 62,190, 62, 44, 63, 95, 78,230, 62,189,233, 4, 63, 95, 13,226, 62,194,152, 37, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62, 37,225, 52, 62,179, 12, 40, 62, 71,118, 78, 62,182, 49, 27, 62, 45,143,142, 62,188, 37,237,
+ 62, 36,230,106, 62,184, 27,222, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 95, 90,248, 62,207,122,100, 63, 90,249,108,
+ 62,212,199, 58, 63, 86,188, 32, 62,190, 62, 44, 63, 92,166, 70, 62,197,166, 0, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62, 71,118, 78, 62,182, 49, 27, 62, 48, 56,110, 62,205, 43,230, 62, 30,250,174, 62,198, 12, 26, 62, 45,143,142, 62,188, 37,237,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 94,229,196, 62,224,195,128, 63, 90,249,108, 62,212,199, 58, 63, 95, 90,248,
+ 62,207,122,100, 63, 98,104, 92, 62,215,136,197, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 30,250,174, 62,198, 12, 26,
+ 62, 48, 56,110, 62,205, 43,230, 62, 28,187,108, 62,217, 86, 48, 62, 15, 59,212, 62,206, 50,224, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63,101,251,100, 62,227,198,238, 63, 94,229,196, 62,224,195,128, 63, 98,104, 92, 62,215,136,197, 63,102,205, 71,
+ 62,219, 94,132, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 15, 59,212, 62,206, 50,224, 62, 28,187,108, 62,217, 86, 48,
+ 61,249,209, 68, 62,219,134, 70, 61,244,157,192, 62,209,137,157, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 81,106,217,
+ 62,232,214, 14, 63, 90,249,108, 62,212,199, 58, 63, 94,229,196, 62,224,195,128, 63, 93,154,106, 62,233, 26,226, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62, 28,187,108, 62,217, 86, 48, 62, 48, 56,110, 62,205, 43,230, 62, 84, 93, 88, 62,228,105, 50,
+ 62, 33, 1,128, 62,226,210, 70, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 81,106,217, 62,232,214, 14, 63, 78, 92, 56,
+ 62,188,114,177, 63, 86,188, 32, 62,190, 62, 44, 63, 90,249,108, 62,212,199, 58, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62, 71,118, 78, 62,182, 49, 27, 62,104,163,162, 62,182,180,150, 62, 84, 93, 88, 62,228,105, 50, 62, 48, 56,110, 62,205, 43,230,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 78, 92, 56, 62,188,114,177, 63, 85, 35,236, 62,181,201,164, 63, 86,188, 32,
+ 62,190, 62, 44, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 71,118, 78, 62,182, 49, 27,
+ 62, 80, 91,122, 62,174, 18, 72, 62,104,163,162, 62,182,180,150, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63,102,205, 71, 62,219, 94,132, 63, 98,104, 92, 62,215,136,197, 63,100,109,182, 62,210,255,149, 63,104, 86, 54,
+ 62,214,241,209, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 7,107,160, 62,200,103, 34, 62, 15, 59,212, 62,206, 50,224,
+ 61,244,157,192, 62,209,137,157, 61,232, 2, 8, 62,203,214, 20, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 98,104, 92,
+ 62,215,136,197, 63, 95, 90,248, 62,207,122,100, 63, 97,206,112, 62,204,202, 10, 63,100,109,182, 62,210,255,149, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62, 21, 68, 64, 62,194, 55,107, 62, 30,250,174, 62,198, 12, 26, 62, 15, 59,212, 62,206, 50,224,
+ 62, 7,107,160, 62,200,103, 34, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 95, 90,248, 62,207,122,100, 63, 92,166, 70,
+ 62,197,166, 0, 63, 94,241, 82, 62,198,103, 40, 63, 97,206,112, 62,204,202, 10, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62, 35,225, 20, 62,188, 50, 39, 62, 45,143,142, 62,188, 37,237, 62, 30,250,174, 62,198, 12, 26, 62, 21, 68, 64, 62,194, 55,107,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 92,166, 70, 62,197,166, 0, 63, 95, 13,226, 62,194,152, 37, 63, 97, 1,118,
+ 62,195,226, 47, 63, 94,241, 82, 62,198,103, 40, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 28, 43, 12, 62,184,177,186,
+ 62, 36,230,106, 62,184, 27,222, 62, 45,143,142, 62,188, 37,237, 62, 35,225, 20, 62,188, 50, 39, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 95, 13,226, 62,194,152, 37, 63, 95, 78,230, 62,189,233, 4, 63, 97,113, 51, 62,189,151, 92, 63, 97, 1,118,
+ 62,195,226, 47, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 29, 67,104, 62,177,199, 58, 62, 37,225, 52, 62,179, 12, 40,
+ 62, 36,230,106, 62,184, 27,222, 62, 28, 43, 12, 62,184,177,186, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 95, 78,230,
+ 62,189,233, 4, 63, 94,215, 9, 62,186, 54, 4, 63, 96, 69, 96, 62,187,133,152, 63, 97,113, 51, 62,189,151, 92, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62, 35, 14,140, 62,176, 19, 33, 62, 41,122, 60, 62,175, 58, 16, 62, 37,225, 52, 62,179, 12, 40,
+ 62, 29, 67,104, 62,177,199, 58, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 94,215, 9, 62,186, 54, 4, 63, 97, 32, 68,
+ 62,178, 12,192, 63, 98, 91,112, 62,182,128,149, 63, 96, 69, 96, 62,187,133,152, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62, 29,107,228, 62,169,230, 95, 62, 36,185, 48, 62,166, 7, 16, 62, 41,122, 60, 62,175, 58, 16, 62, 35, 14,140, 62,176, 19, 33,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,107,239,228, 62,218, 59, 62, 63,102,205, 71, 62,219, 94,132, 63,104, 86, 54,
+ 62,214,241,209, 63,109, 27, 34, 62,214,254,155, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 61,232, 2, 8, 62,203,214, 20,
+ 61,244,157,192, 62,209,137,157, 61,195, 47,128, 62,207, 11, 6, 61,184,174, 36, 62,202,130,216, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63,113,151,174, 62,214,229, 26, 63,107,239,228, 62,218, 59, 62, 63,109, 27, 34, 62,214,254,155, 63,113,134, 69,
+ 62,212, 82,156, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 61,184,174, 36, 62,202,130,216, 61,195, 47,128, 62,207, 11, 6,
+ 61,135,155, 12, 62,201, 39,166, 61,138,114, 60, 62,197, 61, 28, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,116, 48,222,
+ 62,209, 8,169, 63,113,151,174, 62,214,229, 26, 63,113,134, 69, 62,212, 82,156, 63,114,143, 42, 62,207,168, 24, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 61,138,114, 60, 62,197, 61, 28, 61,135,155, 12, 62,201, 39,166, 61, 93,108,160, 62,190,207, 17,
+ 61,132, 85,184, 62,189,211, 22, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,115,225, 84, 62,198, 85,208, 63,116, 48,222,
+ 62,209, 8,169, 63,114,143, 42, 62,207,168, 24, 63,114,125,203, 62,200,114, 96, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 61,132, 85,184, 62,189,211, 22, 61, 93,108,160, 62,190,207, 17, 61,134,221,244, 62,175,164,121, 61,145,152, 16, 62,179,214, 84,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,109,132,198, 62,186,157,182, 63,115,225, 84, 62,198, 85,208, 63,114,125,203,
+ 62,200,114, 96, 63,109,192,177, 62,190,240,152, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 61,145,152, 16, 62,179,214, 84,
+ 61,134,221,244, 62,175,164,121, 61,221, 91, 40, 62,167,194, 4, 61,208,226, 64, 62,172, 58,232, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 97, 32, 68, 62,178, 12,192, 63,109,132,198, 62,186,157,182, 63,109,192,177, 62,190,240,152, 63, 98, 91,112,
+ 62,182,128,149, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 61,208,226, 64, 62,172, 58,232, 61,221, 91, 40, 62,167,194, 4,
+ 62, 36,185, 48, 62,166, 7, 16, 62, 29,107,228, 62,169,230, 95, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 97, 1,118,
+ 62,195,226, 47, 63, 97,113, 51, 62,189,151, 92, 63,102,139,215, 62,193,109, 15, 63,100, 47, 54, 62,198,115,186, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62, 5,169, 92, 62,179,115,168, 62, 29, 67,104, 62,177,199, 58, 62, 28, 43, 12, 62,184,177,186,
+ 62, 13, 97, 50, 62,186, 42, 50, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,100, 47, 54, 62,198,115,186, 63,102,139,215,
+ 62,193,109, 15, 63,105,241,174, 62,200, 8,204, 63,103,233, 71, 62,204, 42,178, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 61,229,171,228, 62,185, 42, 41, 62, 5,169, 92, 62,179,115,168, 62, 13, 97, 50, 62,186, 42, 50, 61,243,248, 92, 62,191, 22, 96,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,103,233, 71, 62,204, 42,178, 63,105,241,174, 62,200, 8,204, 63,108, 37, 51,
+ 62,205, 3,249, 63,106,212, 56, 62,208,238, 96, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 61,202, 99,120, 62,190, 49,192,
+ 61,229,171,228, 62,185, 42, 41, 61,243,248, 92, 62,191, 22, 96, 61,211,209,160, 62,195,159,108, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63,106,212, 56, 62,208,238, 96, 63,108, 37, 51, 62,205, 3,249, 63,110, 73, 56, 62,206,119,186, 63,109,191, 46,
+ 62,210, 64, 92, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 61,179,234,244, 62,190,219,240, 61,202, 99,120, 62,190, 49,192,
+ 61,211,209,160, 62,195,159,108, 61,181,129,196, 62,196, 14,204, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,109, 27, 34,
+ 62,214,254,155, 63,104, 86, 54, 62,214,241,209, 63,106,212, 56, 62,208,238, 96, 63,109,191, 46, 62,210, 64, 92, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 61,211,209,160, 62,195,159,108, 61,232, 2, 8, 62,203,214, 20, 61,184,174, 36, 62,202,130,216,
+ 61,181,129,196, 62,196, 14,204, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,100,109,182, 62,210,255,149, 63,103,233, 71,
+ 62,204, 42,178, 63,106,212, 56, 62,208,238, 96, 63,104, 86, 54, 62,214,241,209, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 61,211,209,160, 62,195,159,108, 61,243,248, 92, 62,191, 22, 96, 62, 7,107,160, 62,200,103, 34, 61,232, 2, 8, 62,203,214, 20,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,100,109,182, 62,210,255,149, 63, 97,206,112, 62,204,202, 10, 63,100, 47, 54,
+ 62,198,115,186, 63,103,233, 71, 62,204, 42,178, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 13, 97, 50, 62,186, 42, 50,
+ 62, 21, 68, 64, 62,194, 55,107, 62, 7,107,160, 62,200,103, 34, 61,243,248, 92, 62,191, 22, 96, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63, 97, 1,118, 62,195,226, 47, 63,100, 47, 54, 62,198,115,186, 63, 97,206,112, 62,204,202, 10, 63, 94,241, 82,
+ 62,198,103, 40, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62, 21, 68, 64, 62,194, 55,107, 62, 13, 97, 50, 62,186, 42, 50,
+ 62, 28, 43, 12, 62,184,177,186, 62, 35,225, 20, 62,188, 50, 39, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63, 96, 69, 96,
+ 62,187,133,152, 63, 98, 91,112, 62,182,128,149, 63,102,139,215, 62,193,109, 15, 63, 97,113, 51, 62,189,151, 92, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 62, 5,169, 92, 62,179,115,168, 62, 29,107,228, 62,169,230, 95, 62, 35, 14,140, 62,176, 19, 33,
+ 62, 29, 67,104, 62,177,199, 58, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,109,192,177, 62,190,240,152, 63,105,241,174,
+ 62,200, 8,204, 63,102,139,215, 62,193,109, 15, 63, 98, 91,112, 62,182,128,149, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 62, 5,169, 92, 62,179,115,168, 61,229,171,228, 62,185, 42, 41, 61,208,226, 64, 62,172, 58,232, 62, 29,107,228, 62,169,230, 95,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,114,125,203, 62,200,114, 96, 63,108, 37, 51, 62,205, 3,249, 63,105,241,174,
+ 62,200, 8,204, 63,109,192,177, 62,190,240,152, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 61,229,171,228, 62,185, 42, 41,
+ 61,202, 99,120, 62,190, 49,192, 61,145,152, 16, 62,179,214, 84, 61,208,226, 64, 62,172, 58,232, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63,114,143, 42, 62,207,168, 24, 63,110, 73, 56, 62,206,119,186, 63,108, 37, 51, 62,205, 3,249, 63,114,125,203,
+ 62,200,114, 96, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 61,202, 99,120, 62,190, 49,192, 61,179,234,244, 62,190,219,240,
+ 61,132, 85,184, 62,189,211, 22, 61,145,152, 16, 62,179,214, 84, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,113,134, 69,
+ 62,212, 82,156, 63,109,191, 46, 62,210, 64, 92, 63,110, 73, 56, 62,206,119,186, 63,114,143, 42, 62,207,168, 24, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 61,179,234,244, 62,190,219,240, 61,181,129,196, 62,196, 14,204, 61,138,114, 60, 62,197, 61, 28,
+ 61,132, 85,184, 62,189,211, 22, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,109, 27, 34, 62,214,254,155, 63,109,191, 46,
+ 62,210, 64, 92, 63,113,134, 69, 62,212, 82,156, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 61,138,114, 60, 62,197, 61, 28, 61,181,129,196, 62,196, 14,204, 61,184,174, 36, 62,202,130,216, 63,128, 0, 0, 63,128, 0, 0,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,110,190, 84, 62,172, 77,223, 63, 90, 5,151, 62,167, 61,138, 63, 96, 25, 22,
+ 62,149,248,246, 63,122,176,162, 62,161,215,145, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,128, 62, 54,234, 64, 62,140,219,146,
+ 62, 66,251,194, 62,158,102,163, 61,246, 66, 8, 62,152,161, 28, 61,189,241,172, 62,132,107, 13, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0, 0, 63,122, 12, 49, 62,197, 8,246, 63,110,190, 84, 62,172, 77,223, 63,122,176,162, 62,161,215,145, 63,126,255,188,
+ 62,198,248,115, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 64, 61,189,241,172, 62,132,107, 13, 61,246, 66, 8, 62,152,161, 28,
+ 61, 16, 54,240, 62,167, 4,120, 58,163, 8, 0, 62,162, 69, 39, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,128, 63,119,115,183,
+ 62,215, 49,140, 63,122, 12, 49, 62,197, 8,246, 63,126,255,188, 62,198,248,115, 63,122, 6, 47, 62,216,157,248, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0, 0, 58,163, 8, 0, 62,162, 69, 39, 61, 16, 54,240, 62,167, 4,120, 60,231,111,224, 62,198,142,100,
+ 60, 14,248,224, 62,198,141, 70, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 16, 63,116, 76, 41, 62,222,153,139, 63,119,115,183,
+ 62,215, 49,140, 63,122, 6, 47, 62,216,157,248, 63,119, 98,134, 62,225, 37,204, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0,
+ 60, 14,248,224, 62,198,141, 70, 60,231,111,224, 62,198,142,100, 61, 73,183,128, 62,213,108, 84, 60,229,210, 80, 62,218,239, 32,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 63,109,178, 31, 62,228, 68,224, 63,116, 76, 41, 62,222,153,139, 63,119, 98,134,
+ 62,225, 37,204, 63,115,185, 46, 62,234,157, 90, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,128, 60,229,210, 80, 62,218,239, 32,
+ 61, 73,183,128, 62,213,108, 84, 61,177, 27, 28, 62,219,240, 42, 61,122,103, 56, 62,230, 10, 30, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0,128, 63,102,178, 46, 62,232,184,100, 63,109,178, 31, 62,228, 68,224, 63,115,185, 46, 62,234,157, 90, 63,106,134,244,
+ 62,246, 64,234, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 64, 61,122,103, 56, 62,230, 10, 30, 61,177, 27, 28, 62,219,240, 42,
+ 61,242,216,120, 62,225, 40,124, 61,209,222,212, 62,240,123,238, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 16, 63, 5,188,235,
+ 63, 98, 74,252, 62,248,111,200, 63,112,105,197, 62,231, 49, 0, 63,107,190,118, 62,255, 57,150, 63, 96, 14, 53, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0,240, 62, 95, 99, 80, 63, 94,194,149, 62, 62, 8, 58, 63, 89,154, 10, 62, 92, 24, 40, 63, 74, 82, 14,
+ 62,112, 11,112, 63, 78,133,157, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 63, 5,188,235, 63, 98, 74,252, 63, 12,139,136,
+ 63,101,233,138, 63, 6, 45,116, 63,113,245,112, 62,248,111,200, 63,112,105,197, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240,
+ 62, 36,219, 68, 63, 81,186,249, 62, 65,254, 28, 63, 70, 55, 20, 62, 92, 24, 40, 63, 74, 82, 14, 62, 62, 8, 58, 63, 89,154, 10,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 63, 12,139,136, 63,101,233,138, 63, 12,130, 5, 63,108,216,149, 63, 6, 45,116,
+ 63,113,245,112, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,112, 62, 36,219, 68, 63, 81,186,249,
+ 62, 42, 1, 76, 63, 73,178, 39, 62, 65,254, 28, 63, 70, 55, 20, 63,128, 0, 0, 63,128, 0, 0, 13, 64,158,176, 1, 0, 0, 5,
+ 0, 0, 0,112, 63,103, 89,120, 63, 2, 76,105, 63, 93,154,106, 62,233, 26,226, 63,102,178, 46, 62,232,184,100, 63,106,134,244,
+ 62,246, 64,234, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 61,242,216,120, 62,225, 40,124, 62, 33, 1,128, 62,226,210, 70,
+ 61,234,128,116, 63, 0, 39,200, 61,209,222,212, 62,240,123,238, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 0, 62,245, 44,226,
+ 63, 96,140,129, 62,255, 57,150, 63, 96, 14, 53, 62,231, 49, 0, 63,107,190,118, 62,227,135, 42, 63,101, 2, 58, 13, 64,158,176,
+ 1, 0, 0, 5, 0, 0, 0,240, 62, 95, 99, 80, 63, 94,194,149, 62,112, 11,112, 63, 78,133,157, 62,120, 84, 74, 63, 83, 32,104,
+ 62,122,103,110, 63, 92,255,236, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0,240, 63, 77,217,216, 62,157,228, 7, 63, 90,225,160,
+ 62,137,121,110, 63, 96, 25, 22, 62,149,248,246, 63, 90, 5,151, 62,167, 61,138, 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 16,
+ 62, 54,234, 64, 62,140,219,146, 62, 74,125,166, 62,130, 30,252, 62,111,118,154, 62,152,108,120, 62, 66,251,194, 62,158,102,163,
+ 13, 64,158,176, 1, 0, 0, 5, 0, 0, 0, 64, 68, 65, 84, 65, 0, 0, 31, 64, 7,160,168, 32, 0, 0, 0, 59, 0, 0, 7,208,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 0, 0, 77, 69, 0, 0, 1, 24, 13, 65,109,208, 0, 0, 0, 52, 0, 0, 0, 1, 13, 65,115, 96, 13, 65,104, 64, 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, 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, 13, 65,111, 16,
+ 7,160,234, 32, 7,160,242, 32, 0, 0, 0, 0, 7,160,200, 32, 7,160,218, 32, 0, 0, 0, 0, 7,161, 0, 32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,111, 64, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0,
+ 13, 65,112,160, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,114, 0, 0, 0, 0, 3,
+ 0, 0, 0, 5, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,188, 0, 0, 1, 53, 0, 0, 0, 76, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 63, 76,204,213, 63, 76,204,255,182,104, 0, 0, 63,128, 0, 30, 63,128, 0,140, 63,127,255,214,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 65,111, 16, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,111, 64, 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,160,200, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 17,160, 7,160,200, 32, 0, 0, 0, 58, 0, 0, 0,188, 63,230,102,133, 63,179, 51,208,
+ 63,127,255,146,165,127, 0, 0, 90,129, 2,255, 0, 0, 0, 0, 63,230,102,133, 63, 25,154,206, 63,127,255,146,165,127, 0, 0,
+ 90,129, 2,255, 0, 0, 0, 0, 63,179, 51, 81, 63,179, 51,210, 63,127,255,148, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,
+ 63,128, 0, 28, 63,179, 51,212, 63,127,255,152, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63, 25,153,207, 63,179, 51,214,
+ 63,127,255,154, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 62, 76,205,152, 63,179, 51,216, 63,127,255,156, 0, 0, 0, 0,
+127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 63,128, 0,158, 63,127,255,148, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,
+ 63,128, 0, 27, 63,128, 0,160, 63,127,255,150, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63, 25,153,204, 63,128, 0,162,
+ 63,127,255,154, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63,128, 0,163, 63,127,255,156, 0, 0, 0, 0,
+127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 63, 25,154,209, 63,127,255,148, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,
+ 63,128, 0, 27, 63, 25,154,213, 63,127,255,150, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63, 25,153,204, 63, 25,154,217,
+ 63,127,255,154, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63, 25,154,221, 63,127,255,156, 0, 0, 0, 0,
+127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 62, 76,209,160, 63,127,255,148, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,
+ 63,128, 0, 27, 62, 76,209,176, 63,127,255,150, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63, 25,153,204, 62, 76,209,188,
+ 63,127,255,152, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 62, 76,205,140, 62, 76,209,204, 63,127,255,154, 0, 0, 0, 0,
+127,255, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63,230,103, 8, 63,127,255,148, 0, 0,165,127, 90,129, 0,255, 0, 0, 0, 0,
+ 63, 25,153,204, 63,230,103, 10, 63,127,255,146, 0, 0,165,127, 90,129, 0,255, 0, 0, 0, 0, 63,128, 0, 27, 63,230,103, 10,
+ 63,127,255,142, 0, 0,165,127, 90,129, 0,255, 0, 0, 0, 0, 63,179, 51, 80, 63,230,103, 12, 63,127,255,140, 0, 0,165,127,
+ 90,129, 0,255, 0, 0, 0, 0,190, 76,205,152, 63,230,103, 12, 63,127,255,140, 0, 0,165,127, 90,129, 0,255, 0, 0, 0, 0,
+190, 76,205,152, 62, 76,209,160, 63,127,255,148, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,190, 76,205,152, 63, 25,154,209,
+ 63,127,255,148, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,190, 76,205,152, 63,128, 0,158, 63,127,255,148, 0, 0, 0, 0,
+127,255, 2,255, 0, 0, 0, 0,190, 76,205,144, 63,179, 51,210, 63,127,255,148, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,
+ 63,230,102,131, 63,230,103, 7, 63,127,255,148, 0, 0,165,127, 90,129, 0,255, 0, 0, 0, 0, 63,230,102,131, 63,128, 0,160,
+ 63,127,255,142,165,127, 0, 0, 90,129, 2,255, 0, 0, 0, 0, 63,230,102,127, 62, 76,208, 28, 63,127,255,148,165,127, 0, 0,
+ 90,129, 2,255, 0, 0, 0, 0,190, 76,205,146,190, 76,208, 72, 63,127,255,148, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,
+ 62, 76,205,150,190, 76,208, 24, 63,127,255,156, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63, 25,153,207,190, 76,208, 40,
+ 63,127,255,154, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,128, 0, 28,190, 76,208, 56, 63,127,255,152, 0, 0, 0, 0,
+127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 81,190, 76,208, 72, 63,127,255,148, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,
+ 63,230,102,133,190, 76,208, 88, 63,127,255,146, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,230,102,133,190, 76,208, 88,
+191,128, 0, 4, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 81,190, 76,208, 72,191,128, 0, 3, 0, 0, 0, 0,
+127,255, 2,255, 0, 0, 0, 0, 63,128, 0, 28,190, 76,208, 56,191,128, 0, 1, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,
+ 63, 25,153,207,190, 76,208, 40,191,128, 0, 0, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 62, 76,205,150,190, 76,208, 24,
+191,127,255,254, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,190, 76,205,146,190, 76,208, 72,191,128, 0, 3, 0, 0, 0, 0,
+127,255, 2,255, 0, 0, 0, 0, 63,230,102,127, 62, 76,208, 28,191, 25,153,155,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0,
+ 63,230,102,131,190, 76,201,136,191, 25,153,159,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,127, 62, 76,208, 28,
+190, 76,204,193,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131,190, 76,201,136,190, 76,204,209,128, 1, 0, 0,
+ 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,127, 62, 76,208, 28, 62, 76,204,219,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0,
+ 63,230,102,131,190, 76,201,136, 62, 76,204,203,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,127, 62, 76,208, 28,
+ 63, 25,153,159,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131,190, 76,201,136, 63, 25,153,155,128, 1, 0, 0,
+ 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,127, 62, 76,208, 28,191,128, 0, 3,165,127, 0, 0, 90,129, 2,255, 0, 0, 0, 0,
+ 63,230,102,131, 63,128, 0,160,191,128, 0, 6,165,127, 0, 0, 90,129, 2,255, 0, 0, 0, 0, 63,230,102,131, 63,230,103, 7,
+191,128, 0, 3, 0, 0,165,127, 90,129, 0,255, 0, 0, 0, 0, 63,230,102,135, 63, 25,154,207, 63, 25,153,151,128, 1, 0, 0,
+ 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131, 63,128, 0,156, 63, 25,153,151,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0,
+ 63,230,102,131, 63,179, 51,212, 63, 25,153,155,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131, 63,230,103, 7,
+ 63, 25,153,159,165,127,165,127, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,135, 63, 25,154,207, 62, 76,204,171,128, 1, 0, 0,
+ 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131, 63,128, 0,160, 62, 76,204,187,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0,
+ 63,230,102,131, 63,179, 51,212, 62, 76,204,203,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131, 63,230,103, 7,
+ 62, 76,204,219,165,127,165,127, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,135, 63, 25,154,207,190, 76,204,241,128, 1, 0, 0,
+ 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131, 63,128, 0,160,190, 76,204,225,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0,
+ 63,230,102,131, 63,179, 51,212,190, 76,204,209,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131, 63,230,103, 7,
+190, 76,204,193,165,127,165,127, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,135, 63, 25,154,207,191, 25,153,167,128, 1, 0, 0,
+ 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131, 63,128, 0,160,191, 25,153,163,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0,
+ 63,230,102,131, 63,179, 51,212,191, 25,153,159,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131, 63,230,103, 7,
+191, 25,153,155,165,127,165,127, 0, 0, 2,255, 0, 0, 0, 0,190, 76,205,144, 63,179, 51,210,191,128, 0, 3, 0, 0, 0, 0,
+127,255, 2,255, 0, 0, 0, 0,190, 76,205,152, 63,128, 0,158,191,128, 0, 3, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,
+190, 76,205,152, 63, 25,154,209,191,128, 0, 3, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,190, 76,205,152, 62, 76,209,160,
+191,128, 0, 3, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,190, 76,205,152, 63,230,103, 12,191, 25,153,168, 0, 0,128, 1,
+ 0, 0, 2,255, 0, 0, 0, 0,190, 76,205,152, 63,230,103, 12,190, 76,204,244, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0,
+190, 76,205,152, 63,230,103, 12, 62, 76,204,168, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0,190, 76,205,144, 63,230,103, 12,
+ 63, 25,153,150, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0,190, 76,205,152, 63,230,103, 12,191,128, 0, 7, 0, 0,165,127,
+ 90,129, 0,255, 0, 0, 0, 0, 63,179, 51, 80, 63,230,103, 12,191,128, 0, 7, 0, 0,165,127, 90,129, 0,255, 0, 0, 0, 0,
+ 63,128, 0, 27, 63,230,103, 10,191,128, 0, 6, 0, 0,165,127, 90,129, 0,255, 0, 0, 0, 0, 63, 25,153,204, 63,230,103, 10,
+191,128, 0, 4, 0, 0,165,127, 90,129, 0,255, 0, 0, 0, 0, 62, 76,205,140, 63,230,103, 8,191,128, 0, 3, 0, 0,165,127,
+ 90,129, 0,255, 0, 0, 0, 0, 63,179, 51, 81, 63,230,103, 12, 63, 25,153,150, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0,
+ 63,128, 0, 28, 63,230,103, 10, 63, 25,153,150, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 63, 25,153,207, 63,230,103, 10,
+ 63, 25,153,154, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 62, 76,205,152, 63,230,103, 8, 63, 25,153,158, 0, 0,128, 1,
+ 0, 0, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 63,230,103, 12, 62, 76,204,168, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0,
+ 63,128, 0, 27, 63,230,103, 10, 62, 76,204,184, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 63, 25,153,204, 63,230,103, 10,
+ 62, 76,204,200, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63,230,103, 8, 62, 76,204,216, 0, 0,128, 1,
+ 0, 0, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 63,230,103, 12,190, 76,204,244, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0,
+ 63,128, 0, 27, 63,230,103, 10,190, 76,204,228, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 63, 25,153,204, 63,230,103, 10,
+190, 76,204,212, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63,230,103, 8,190, 76,204,196, 0, 0,128, 1,
+ 0, 0, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 63,230,103, 12,191, 25,153,168, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0,
+ 63,128, 0, 27, 63,230,103, 10,191, 25,153,164, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 63, 25,153,204, 63,230,103, 10,
+191, 25,153,160, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63,230,103, 8,191, 25,153,156, 0, 0,128, 1,
+ 0, 0, 2,255, 0, 0, 0, 0, 62, 76,205,140, 62, 76,209,204,191,127,255,255, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,
+ 63, 25,153,204, 62, 76,209,188,191,128, 0, 1, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,128, 0, 27, 62, 76,209,176,
+191,128, 0, 2, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 62, 76,209,160,191,128, 0, 3, 0, 0, 0, 0,
+127,255, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63, 25,154,221,191,127,255,254, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,
+ 63, 25,153,204, 63, 25,154,217,191,128, 0, 0, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,128, 0, 27, 63, 25,154,213,
+191,128, 0, 2, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 63, 25,154,209,191,128, 0, 3, 0, 0, 0, 0,
+127,255, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63,128, 0,163,191,127,255,254, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,
+ 63, 25,153,204, 63,128, 0,162,191,128, 0, 0, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,128, 0, 27, 63,128, 0,160,
+191,128, 0, 2, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 63,128, 0,158,191,128, 0, 3, 0, 0, 0, 0,
+127,255, 2,255, 0, 0, 0, 0, 62, 76,205,152, 63,179, 51,216,191,127,255,254, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,
+ 63, 25,153,207, 63,179, 51,214,191,128, 0, 0, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,128, 0, 28, 63,179, 51,212,
+191,128, 0, 1, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 81, 63,179, 51,210,191,128, 0, 3, 0, 0, 0, 0,
+127,255, 2,255, 0, 0, 0, 0, 63,230,102,133, 63, 25,154,206,191,128, 0, 4,165,127, 0, 0, 90,129, 2,255, 0, 0, 0, 0,
+ 63,230,102,133, 63,179, 51,208,191,128, 0, 4,165,127, 0, 0, 90,129, 2,255, 0, 0, 0, 0,190, 76,205,128, 62, 76,201,116,
+191,128, 0, 5,127,255, 0, 0, 0, 0, 16,255, 0, 0, 0, 0,190, 76,205,136, 63,127,255, 48,191,128, 0, 5,127,255, 0, 0,
+ 0, 0, 16,255, 0, 0, 0, 0,190, 76,205,112,190, 76,208, 64,191, 25,153,156,127,255, 0, 0, 0, 0, 16,255, 0, 0, 0, 0,
+190, 76,205,112, 62, 76,201, 84,191, 25,153,160,127,255, 0, 0, 0, 0, 18,255, 0, 0, 0, 0,190, 76,205,120, 63, 25,152,190,
+191, 25,153,164,127,255, 0, 0, 0, 0, 18,255, 0, 0, 0, 0,190, 76,205,152, 63,127,255, 46,191, 25,153,168,127,255, 0, 0,
+ 0, 0, 18,255, 0, 0, 0, 0,190, 76,205,112,190, 76,208, 64,190, 76,204,195,127,255, 0, 0, 0, 0, 16,255, 0, 0, 0, 0,
+190, 76,205,112, 62, 76,201, 84,190, 76,204,211,127,255, 0, 0, 0, 0, 18,255, 0, 0, 0, 0,190, 76,205,120, 63, 25,152,190,
+190, 76,204,227,127,255, 0, 0, 0, 0, 18,255, 0, 0, 0, 0,190, 76,205,152, 63,127,255, 46,190, 76,204,243,127,255, 0, 0,
+ 0, 0, 18,255, 0, 0, 0, 0,190, 76,205,112,190, 76,208, 64, 62, 76,204,221,127,255, 0, 0, 0, 0, 16,255, 0, 0, 0, 0,
+190, 76,205,112, 62, 76,201, 84, 62, 76,204,205,127,255, 0, 0, 0, 0, 18,255, 0, 0, 0, 0,190, 76,205,120, 63, 25,152,190,
+ 62, 76,204,189,127,255, 0, 0, 0, 0, 18,255, 0, 0, 0, 0,190, 76,205,152, 63,127,255, 46, 62, 76,204,173,127,255, 0, 0,
+ 0, 0, 18,255, 0, 0, 0, 0,190, 76,205,112,190, 76,208, 64, 63, 25,153,160,127,255, 0, 0, 0, 0, 16,255, 0, 0, 0, 0,
+190, 76,205,112, 62, 76,201, 84, 63, 25,153,156,127,255, 0, 0, 0, 0, 18,255, 0, 0, 0, 0,190, 76,205,120, 63, 25,152,198,
+ 63, 25,153,152,127,255, 0, 0, 0, 0, 18,255, 0, 0, 0, 0,190, 76,205,152, 63,127,255, 46, 63, 25,153,152,127,255, 0, 0,
+ 0, 0, 18,255, 0, 0, 0, 0,190, 76,205,112,190, 76,208, 64,191,128, 0, 4,231, 94,231, 94,132,215, 16,255, 0, 0, 0, 0,
+190, 76,205,120, 63, 25,152,190,191,128, 0, 7,127,255, 0, 0, 0, 0, 16,255, 0, 0, 0, 0,190, 76,205, 96, 63,179, 50,251,
+191,128, 0, 4,127,255, 0, 0, 0, 0, 16,255, 0, 0, 0, 0,190, 76,205,128, 63,230,102, 48, 63, 25,153,156,127,255, 0, 0,
+ 0, 0, 18,255, 0, 0, 0, 0,190, 76,205, 96, 63,179, 50,251, 63, 25,153,160,127,255, 0, 0, 0, 0, 18,255, 0, 0, 0, 0,
+190, 76,205,128, 63,230,102, 48, 62, 76,204,205,127,255, 0, 0, 0, 0, 18,255, 0, 0, 0, 0,190, 76,205, 96, 63,179, 50,251,
+ 62, 76,204,221,127,255, 0, 0, 0, 0, 18,255, 0, 0, 0, 0,190, 76,205,128, 63,230,102, 48,190, 76,204,211,127,255, 0, 0,
+ 0, 0, 18,255, 0, 0, 0, 0,190, 76,205, 96, 63,179, 50,251,190, 76,204,195,127,255, 0, 0, 0, 0, 18,255, 0, 0, 0, 0,
+190, 76,205,128, 63,230,102, 48,191, 25,153,160,127,255, 0, 0, 0, 0, 18,255, 0, 0, 0, 0,190, 76,205, 96, 63,179, 50,251,
+191, 25,153,156,127,255, 0, 0, 0, 0, 18,255, 0, 0, 0, 0,190, 76,205,144, 63,230,103, 10,191,128, 0, 5,243,161,111, 93,
+194, 34, 16,255, 0, 0, 0, 0,190, 76,205,144, 63,230,103, 10, 63,127,255,148,243,161,111, 93, 61,222, 16,255, 0, 0, 0, 0,
+190, 76,205, 96, 63,179, 50,251, 63,127,255,150,127,255, 0, 0, 0, 0, 16,255, 0, 0, 0, 0,190, 76,205,120, 63, 25,152,190,
+ 63,127,255,144,127,255, 0, 0, 0, 0, 16,255, 0, 0, 0, 0,190, 76,205,112,190, 76,208, 64, 63,127,255,150,231, 94,231, 94,
+123, 41, 16,255, 0, 0, 0, 0,190, 76,205,136, 63,127,255, 48, 63,127,255,148,127,255, 0, 0, 0, 0, 16,255, 0, 0, 0, 0,
+190, 76,205,128, 62, 76,201,116, 63,127,255,148,127,255, 0, 0, 0, 0, 16,255, 0, 0, 0, 0, 63,179, 51, 36,190, 76,208, 56,
+191, 25,153,157, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,127,255,222,190, 76,208, 80,191, 25,153,161, 0, 0,127,255,
+ 0, 0, 3,255, 0, 0, 0, 0, 63, 25,153,116,190, 76,208, 80,191, 25,153,165, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0,
+ 62, 76,204, 44,190, 76,208,104,191, 25,153,169, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,179, 51, 36,190, 76,208, 56,
+190, 76,204,198, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,127,255,222,190, 76,208, 80,190, 76,204,214, 0, 0,127,255,
+ 0, 0, 3,255, 0, 0, 0, 0, 63, 25,153,116,190, 76,208, 80,190, 76,204,230, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0,
+ 62, 76,204, 44,190, 76,208,104,190, 76,204,246, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,179, 51, 36,190, 76,208, 56,
+ 62, 76,204,218, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,127,255,222,190, 76,208, 80, 62, 76,204,202, 0, 0,127,255,
+ 0, 0, 3,255, 0, 0, 0, 0, 63, 25,153,116,190, 76,208, 80, 62, 76,204,186, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0,
+ 62, 76,204, 44,190, 76,208,104, 62, 76,204,170, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,179, 51, 34,190, 76,208, 56,
+ 63, 25,153,159, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,127,255,220,190, 76,208, 80, 63, 25,153,155, 0, 0,127,255,
+ 0, 0, 3,255, 0, 0, 0, 0, 63, 25,153,114,190, 76,208, 80, 63, 25,153,151, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0,
+ 62, 76,204, 36,190, 76,208,104, 63, 25,153,151, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,179, 51, 36,190, 76,208, 56,
+191,128, 0, 4, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,127,255,222,190, 76,208, 80,191,128, 0, 5, 0, 0,127,255,
+ 0, 0, 3,255, 0, 0, 0, 0, 63, 25,153,116,190, 76,208, 80,191,128, 0, 7, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0,
+ 62, 76,204, 44,190, 76,208,104,191,128, 0, 8, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,230,102,136,190, 76,208, 88,
+191,128, 0, 8, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,230,102,135,190, 76,208, 88, 63, 25,153,151, 0, 0,127,255,
+ 0, 0, 3,255, 0, 0, 0, 0, 63,230,102,136,190, 76,208, 88, 62, 76,204,170, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0,
+ 63,230,102,136,190, 76,208, 88,190, 76,204,246, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,230,102,136,190, 76,208, 88,
+191, 25,153,169, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,112,190, 76,208, 64,191, 25,153,156, 0, 0,127,255,
+ 0, 0, 1,255, 0, 0, 0, 0,190, 76,205,112,190, 76,208, 64,190, 76,204,195, 0, 0,127,255, 0, 0, 1,255, 0, 0, 0, 0,
+190, 76,205,112,190, 76,208, 64, 62, 76,204,221, 0, 0,127,255, 0, 0, 1,255, 0, 0, 0, 0,190, 76,205,112,190, 76,208, 64,
+ 63, 25,153,160, 0, 0,127,255, 0, 0, 1,255, 0, 0, 0, 0,190, 76,205,112,190, 76,208, 64,191,128, 0, 4, 0, 0,127,255,
+ 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,112,190, 76,208, 64, 63,127,255,150, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0,
+ 63,230,102,136,190, 76,208, 88, 63,127,255,142, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 62, 76,204, 44,190, 76,208,104,
+ 63,127,255,142, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63, 25,153,116,190, 76,208, 80, 63,127,255,144, 0, 0,127,255,
+ 0, 0, 3,255, 0, 0, 0, 0, 63,127,255,222,190, 76,208, 80, 63,127,255,148, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0,
+ 63,179, 51, 36,190, 76,208, 56, 63,127,255,150, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 44,
+ 13, 65,112,160, 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,160,218, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 0, 0, 14,124,
+ 7,160,218, 32, 0, 0, 0, 55, 0, 0, 1, 53, 0, 0, 0, 21, 0, 0, 0, 82, 0, 0, 0, 34, 0, 0, 0, 20, 0, 0, 0, 83,
+ 0, 0, 0, 34, 0, 0, 0, 19, 0, 0, 0, 84, 0, 0, 0, 34, 0, 0, 0, 18, 0, 0, 0, 85, 0, 0, 0, 34, 0, 0, 0, 22,
+ 0, 0, 0, 76, 0, 0, 0, 34, 0, 0, 0, 1, 0, 0, 0, 53, 0, 0, 0, 34, 0, 0, 0, 28, 0, 0, 0, 54, 0, 0, 0, 34,
+ 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 34, 0, 0, 0, 27, 0, 0, 0, 56, 0, 0, 0, 34, 0, 0, 0, 29, 0, 0, 0, 48,
+ 0, 0, 0, 34, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 34, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 34, 0, 0, 0, 2,
+ 0, 0, 0, 3, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 34, 0, 0, 0, 5, 0, 0, 0, 9, 0, 0, 0, 34,
+ 0, 0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 34, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 34, 0, 0, 0, 7, 0, 0, 0, 8,
+ 0, 0, 0, 34, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0, 34, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 34, 0, 0, 0, 2,
+ 0, 0, 0, 6, 0, 0, 0, 34, 0, 0, 0, 9, 0, 0, 0, 13, 0, 0, 0, 34, 0, 0, 0, 12, 0, 0, 0, 13, 0, 0, 0, 34,
+ 0, 0, 0, 8, 0, 0, 0, 12, 0, 0, 0, 34, 0, 0, 0, 11, 0, 0, 0, 12, 0, 0, 0, 34, 0, 0, 0, 7, 0, 0, 0, 11,
+ 0, 0, 0, 34, 0, 0, 0, 10, 0, 0, 0, 11, 0, 0, 0, 34, 0, 0, 0, 6, 0, 0, 0, 10, 0, 0, 0, 34, 0, 0, 0, 1,
+ 0, 0, 0, 10, 0, 0, 0, 34, 0, 0, 0, 13, 0, 0, 0, 17, 0, 0, 0, 34, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 34,
+ 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 34, 0, 0, 0, 15, 0, 0, 0, 16, 0, 0, 0, 34, 0, 0, 0, 11, 0, 0, 0, 15,
+ 0, 0, 0, 34, 0, 0, 0, 14, 0, 0, 0, 15, 0, 0, 0, 34, 0, 0, 0, 10, 0, 0, 0, 14, 0, 0, 0, 34, 0, 0, 0, 19,
+ 0, 0, 0, 20, 0, 0, 0, 34, 0, 0, 0, 2, 0, 0, 0, 21, 0, 0, 0, 34, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 34,
+ 0, 0, 0, 4, 0, 0, 0, 19, 0, 0, 0, 34, 0, 0, 0, 5, 0, 0, 0, 18, 0, 0, 0, 34, 0, 0, 0, 22, 0, 0, 0, 26,
+ 0, 0, 0, 34, 0, 0, 0, 24, 0, 0, 0, 25, 0, 0, 0, 34, 0, 0, 0, 18, 0, 0, 0, 22, 0, 0, 0, 34, 0, 0, 0, 17,
+ 0, 0, 0, 23, 0, 0, 0, 34, 0, 0, 0, 13, 0, 0, 0, 24, 0, 0, 0, 34, 0, 0, 0, 9, 0, 0, 0, 25, 0, 0, 0, 34,
+ 0, 0, 0, 5, 0, 0, 0, 26, 0, 0, 0, 34, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 28,
+ 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 34, 0, 0, 0, 1, 0, 0, 0, 29, 0, 0, 0, 34, 0, 0, 0, 21,
+ 0, 0, 0, 27, 0, 0, 0, 34, 0, 0, 0, 14, 0, 0, 0, 29, 0, 0, 0, 34, 0, 0, 0, 6, 0, 0, 0, 28, 0, 0, 0, 34,
+ 0, 0, 0, 30, 0, 0, 0, 31, 0, 0, 0, 34, 0, 0, 0, 34, 0, 0, 0, 35, 0, 0, 0, 34, 0, 0, 0, 32, 0, 0, 0, 33,
+ 0, 0, 0, 34, 0, 0, 0, 29, 0, 0, 0, 35, 0, 0, 0, 34, 0, 0, 0, 23, 0, 0, 0, 30, 0, 0, 0, 34, 0, 0, 0, 14,
+ 0, 0, 0, 34, 0, 0, 0, 34, 0, 0, 0, 15, 0, 0, 0, 33, 0, 0, 0, 34, 0, 0, 0, 16, 0, 0, 0, 32, 0, 0, 0, 34,
+ 0, 0, 0, 17, 0, 0, 0, 31, 0, 0, 0, 34, 0, 0, 0, 40, 0, 0, 0, 98, 0, 0, 0, 34, 0, 0, 0, 39, 0, 0, 0, 99,
+ 0, 0, 0, 34, 0, 0, 0, 38, 0, 0, 0,100, 0, 0, 0, 34, 0, 0, 0, 37, 0, 0, 0,101, 0, 0, 0, 34, 0, 0, 0, 41,
+ 0, 0, 0, 72, 0, 0, 0, 34, 0, 0, 0, 36, 0, 0, 0, 50, 0, 0, 0, 34, 0, 0, 0, 38, 0, 0, 0, 39, 0, 0, 0, 34,
+ 0, 0, 0, 36, 0, 0, 0, 37, 0, 0, 0, 34, 0, 0, 0, 40, 0, 0, 0, 41, 0, 0, 0, 34, 0, 0, 0, 51, 0, 0, 0,109,
+ 0, 0, 0, 34, 0, 0, 0, 50, 0, 0, 0,101, 0, 0, 0, 34, 0, 0, 0, 68, 0, 0, 0, 94, 0, 0, 0, 34, 0, 0, 0, 64,
+ 0, 0, 0, 90, 0, 0, 0, 34, 0, 0, 0, 60, 0, 0, 0, 86, 0, 0, 0, 34, 0, 0, 0, 56, 0, 0, 0, 82, 0, 0, 0, 34,
+ 0, 0, 0, 52, 0, 0, 0, 78, 0, 0, 0, 34, 0, 0, 0, 50, 0, 0, 0,114, 0, 0, 0, 34, 0, 0, 0, 65, 0, 0, 0,114,
+ 0, 0, 0, 34, 0, 0, 0, 67, 0, 0, 0,115, 0, 0, 0, 34, 0, 0, 0, 52, 0, 0, 0,115, 0, 0, 0, 34, 0, 0, 0, 51,
+ 0, 0, 0,115, 0, 0, 0, 34, 0, 0, 0, 51, 0, 0, 0,114, 0, 0, 0, 34, 0, 0, 0, 42, 0, 0, 0, 50, 0, 0, 0, 34,
+ 0, 0, 0, 43, 0, 0, 0, 45, 0, 0, 0, 34, 0, 0, 0, 42, 0, 0, 0, 43, 0, 0, 0, 34, 0, 0, 0, 42, 0, 0, 0, 44,
+ 0, 0, 0, 34, 0, 0, 0, 44, 0, 0, 0, 45, 0, 0, 0, 34, 0, 0, 0, 44, 0, 0, 0, 46, 0, 0, 0, 34, 0, 0, 0, 47,
+ 0, 0, 0, 49, 0, 0, 0, 34, 0, 0, 0, 46, 0, 0, 0, 47, 0, 0, 0, 34, 0, 0, 0, 46, 0, 0, 0, 48, 0, 0, 0, 34,
+ 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 34, 0, 0, 0, 55, 0, 0, 0, 56, 0, 0, 0, 34, 0, 0, 0, 54, 0, 0, 0, 55,
+ 0, 0, 0, 34, 0, 0, 0, 53, 0, 0, 0, 54, 0, 0, 0, 34, 0, 0, 0, 56, 0, 0, 0, 60, 0, 0, 0, 34, 0, 0, 0, 59,
+ 0, 0, 0, 60, 0, 0, 0, 34, 0, 0, 0, 55, 0, 0, 0, 59, 0, 0, 0, 34, 0, 0, 0, 58, 0, 0, 0, 59, 0, 0, 0, 34,
+ 0, 0, 0, 54, 0, 0, 0, 58, 0, 0, 0, 34, 0, 0, 0, 57, 0, 0, 0, 58, 0, 0, 0, 34, 0, 0, 0, 53, 0, 0, 0, 57,
+ 0, 0, 0, 34, 0, 0, 0, 60, 0, 0, 0, 64, 0, 0, 0, 34, 0, 0, 0, 63, 0, 0, 0, 64, 0, 0, 0, 34, 0, 0, 0, 59,
+ 0, 0, 0, 63, 0, 0, 0, 34, 0, 0, 0, 62, 0, 0, 0, 63, 0, 0, 0, 34, 0, 0, 0, 58, 0, 0, 0, 62, 0, 0, 0, 34,
+ 0, 0, 0, 61, 0, 0, 0, 62, 0, 0, 0, 34, 0, 0, 0, 57, 0, 0, 0, 61, 0, 0, 0, 34, 0, 0, 0, 64, 0, 0, 0, 68,
+ 0, 0, 0, 34, 0, 0, 0, 67, 0, 0, 0, 68, 0, 0, 0, 34, 0, 0, 0, 63, 0, 0, 0, 67, 0, 0, 0, 34, 0, 0, 0, 66,
+ 0, 0, 0, 67, 0, 0, 0, 34, 0, 0, 0, 62, 0, 0, 0, 66, 0, 0, 0, 34, 0, 0, 0, 65, 0, 0, 0, 66, 0, 0, 0, 34,
+ 0, 0, 0, 61, 0, 0, 0, 65, 0, 0, 0, 34, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 34, 0, 0, 0, 51, 0, 0, 0, 66,
+ 0, 0, 0, 34, 0, 0, 0, 48, 0, 0, 0, 53, 0, 0, 0, 34, 0, 0, 0, 46, 0, 0, 0, 57, 0, 0, 0, 34, 0, 0, 0, 44,
+ 0, 0, 0, 61, 0, 0, 0, 34, 0, 0, 0, 42, 0, 0, 0, 65, 0, 0, 0, 34, 0, 0, 0, 69, 0, 0, 0,110, 0, 0, 0, 34,
+ 0, 0, 0, 70, 0, 0, 0,106, 0, 0, 0, 34, 0, 0, 0, 71, 0, 0, 0,102, 0, 0, 0, 34, 0, 0, 0, 72, 0, 0, 0, 98,
+ 0, 0, 0, 34, 0, 0, 0, 73, 0, 0, 0, 97, 0, 0, 0, 34, 0, 0, 0, 74, 0, 0, 0, 93, 0, 0, 0, 34, 0, 0, 0, 75,
+ 0, 0, 0, 89, 0, 0, 0, 34, 0, 0, 0, 76, 0, 0, 0, 85, 0, 0, 0, 34, 0, 0, 0, 77, 0, 0, 0, 81, 0, 0, 0, 34,
+ 0, 0, 0, 70, 0, 0, 0, 71, 0, 0, 0, 34, 0, 0, 0, 73, 0, 0, 0, 77, 0, 0, 0, 34, 0, 0, 0, 74, 0, 0, 0, 75,
+ 0, 0, 0, 34, 0, 0, 0, 69, 0, 0, 0, 77, 0, 0, 0, 34, 0, 0, 0, 81, 0, 0, 0,110, 0, 0, 0, 34, 0, 0, 0, 80,
+ 0, 0, 0,111, 0, 0, 0, 34, 0, 0, 0, 79, 0, 0, 0,112, 0, 0, 0, 34, 0, 0, 0, 78, 0, 0, 0,113, 0, 0, 0, 34,
+ 0, 0, 0, 79, 0, 0, 0, 80, 0, 0, 0, 34, 0, 0, 0, 84, 0, 0, 0, 85, 0, 0, 0, 34, 0, 0, 0, 83, 0, 0, 0, 84,
+ 0, 0, 0, 34, 0, 0, 0, 82, 0, 0, 0, 83, 0, 0, 0, 34, 0, 0, 0, 85, 0, 0, 0, 89, 0, 0, 0, 34, 0, 0, 0, 88,
+ 0, 0, 0, 89, 0, 0, 0, 34, 0, 0, 0, 84, 0, 0, 0, 88, 0, 0, 0, 34, 0, 0, 0, 87, 0, 0, 0, 88, 0, 0, 0, 34,
+ 0, 0, 0, 83, 0, 0, 0, 87, 0, 0, 0, 34, 0, 0, 0, 86, 0, 0, 0, 87, 0, 0, 0, 34, 0, 0, 0, 82, 0, 0, 0, 86,
+ 0, 0, 0, 34, 0, 0, 0, 89, 0, 0, 0, 93, 0, 0, 0, 34, 0, 0, 0, 92, 0, 0, 0, 93, 0, 0, 0, 34, 0, 0, 0, 88,
+ 0, 0, 0, 92, 0, 0, 0, 34, 0, 0, 0, 91, 0, 0, 0, 92, 0, 0, 0, 34, 0, 0, 0, 87, 0, 0, 0, 91, 0, 0, 0, 34,
+ 0, 0, 0, 90, 0, 0, 0, 91, 0, 0, 0, 34, 0, 0, 0, 86, 0, 0, 0, 90, 0, 0, 0, 34, 0, 0, 0, 93, 0, 0, 0, 97,
+ 0, 0, 0, 34, 0, 0, 0, 96, 0, 0, 0, 97, 0, 0, 0, 34, 0, 0, 0, 92, 0, 0, 0, 96, 0, 0, 0, 34, 0, 0, 0, 95,
+ 0, 0, 0, 96, 0, 0, 0, 34, 0, 0, 0, 91, 0, 0, 0, 95, 0, 0, 0, 34, 0, 0, 0, 94, 0, 0, 0, 95, 0, 0, 0, 34,
+ 0, 0, 0, 90, 0, 0, 0, 94, 0, 0, 0, 34, 0, 0, 0, 81, 0, 0, 0, 97, 0, 0, 0, 34, 0, 0, 0, 80, 0, 0, 0, 96,
+ 0, 0, 0, 34, 0, 0, 0, 79, 0, 0, 0, 95, 0, 0, 0, 34, 0, 0, 0, 78, 0, 0, 0, 94, 0, 0, 0, 34, 0, 0, 0,101,
+ 0, 0, 0,105, 0, 0, 0, 34, 0, 0, 0,100, 0, 0, 0,101, 0, 0, 0, 34, 0, 0, 0,100, 0, 0, 0,104, 0, 0, 0, 34,
+ 0, 0, 0, 99, 0, 0, 0,100, 0, 0, 0, 34, 0, 0, 0, 99, 0, 0, 0,103, 0, 0, 0, 34, 0, 0, 0, 98, 0, 0, 0, 99,
+ 0, 0, 0, 34, 0, 0, 0, 98, 0, 0, 0,102, 0, 0, 0, 34, 0, 0, 0,105, 0, 0, 0,114, 0, 0, 0, 34, 0, 0, 0,105,
+ 0, 0, 0,109, 0, 0, 0, 34, 0, 0, 0,104, 0, 0, 0,105, 0, 0, 0, 34, 0, 0, 0,104, 0, 0, 0,108, 0, 0, 0, 34,
+ 0, 0, 0,103, 0, 0, 0,104, 0, 0, 0, 34, 0, 0, 0,103, 0, 0, 0,107, 0, 0, 0, 34, 0, 0, 0,102, 0, 0, 0,103,
+ 0, 0, 0, 34, 0, 0, 0,102, 0, 0, 0,106, 0, 0, 0, 34, 0, 0, 0,109, 0, 0, 0,113, 0, 0, 0, 34, 0, 0, 0,108,
+ 0, 0, 0,109, 0, 0, 0, 34, 0, 0, 0,108, 0, 0, 0,112, 0, 0, 0, 34, 0, 0, 0,107, 0, 0, 0,108, 0, 0, 0, 34,
+ 0, 0, 0,107, 0, 0, 0,111, 0, 0, 0, 34, 0, 0, 0,106, 0, 0, 0,107, 0, 0, 0, 34, 0, 0, 0,106, 0, 0, 0,110,
+ 0, 0, 0, 34, 0, 0, 0,113, 0, 0, 0,115, 0, 0, 0, 34, 0, 0, 0,112, 0, 0, 0,113, 0, 0, 0, 34, 0, 0, 0,111,
+ 0, 0, 0,112, 0, 0, 0, 34, 0, 0, 0,110, 0, 0, 0,111, 0, 0, 0, 34, 0, 0, 0,121, 0, 0, 0,144, 0, 0, 0, 50,
+ 0, 0, 0,125, 0, 0, 0,142, 0, 0, 0, 50, 0, 0, 0,129, 0, 0, 0,140, 0, 0, 0, 50, 0, 0, 0,133, 0, 0, 0,138,
+ 0, 0, 0, 50, 0, 0, 0,120, 0, 0, 0,135, 0, 0, 0, 50, 0, 0, 0,118, 0, 0, 0,134, 0, 0, 0,178, 0, 0, 0,121,
+ 0, 0, 0,125, 0, 0, 0, 50, 0, 0, 0,120, 0, 0, 0,121, 0, 0, 0, 50, 0, 0, 0,120, 0, 0, 0,124, 0, 0, 0, 50,
+ 0, 0, 0,120, 0, 0, 0,119, 0, 0, 0, 50, 0, 0, 0,119, 0, 0, 0,123, 0, 0, 0, 50, 0, 0, 0,118, 0, 0, 0,119,
+ 0, 0, 0, 50, 0, 0, 0,118, 0, 0, 0,122, 0, 0, 0, 50, 0, 0, 0,125, 0, 0, 0,129, 0, 0, 0, 50, 0, 0, 0,124,
+ 0, 0, 0,125, 0, 0, 0, 50, 0, 0, 0,124, 0, 0, 0,128, 0, 0, 0, 50, 0, 0, 0,123, 0, 0, 0,124, 0, 0, 0, 50,
+ 0, 0, 0,123, 0, 0, 0,127, 0, 0, 0, 50, 0, 0, 0,122, 0, 0, 0,123, 0, 0, 0, 50, 0, 0, 0,122, 0, 0, 0,126,
+ 0, 0, 0,178, 0, 0, 0,129, 0, 0, 0,133, 0, 0, 0, 50, 0, 0, 0,128, 0, 0, 0,129, 0, 0, 0, 50, 0, 0, 0,128,
+ 0, 0, 0,132, 0, 0, 0, 50, 0, 0, 0,127, 0, 0, 0,128, 0, 0, 0, 50, 0, 0, 0,127, 0, 0, 0,131, 0, 0, 0, 50,
+ 0, 0, 0,126, 0, 0, 0,127, 0, 0, 0, 50, 0, 0, 0,126, 0, 0, 0,130, 0, 0, 0, 50, 0, 0, 0,132, 0, 0, 0,133,
+ 0, 0, 0, 50, 0, 0, 0,131, 0, 0, 0,132, 0, 0, 0, 50, 0, 0, 0,130, 0, 0, 0,131, 0, 0, 0, 50, 0, 0, 0,137,
+ 0, 0, 0,138, 0, 0, 0, 50, 0, 0, 0,138, 0, 0, 0,140, 0, 0, 0, 50, 0, 0, 0,139, 0, 0, 0,140, 0, 0, 0, 50,
+ 0, 0, 0,137, 0, 0, 0,139, 0, 0, 0, 50, 0, 0, 0,140, 0, 0, 0,142, 0, 0, 0, 50, 0, 0, 0,141, 0, 0, 0,142,
+ 0, 0, 0, 50, 0, 0, 0,142, 0, 0, 0,144, 0, 0, 0, 50, 0, 0, 0,143, 0, 0, 0,144, 0, 0, 0, 50, 0, 0, 0,141,
+ 0, 0, 0,143, 0, 0, 0, 50, 0, 0, 0,136, 0, 0, 0,144, 0, 0, 0, 50, 0, 0, 0,117, 0, 0, 0,135, 0, 0, 0,178,
+ 0, 0, 0,116, 0, 0, 0,135, 0, 0, 0, 50, 0, 0, 0,116, 0, 0, 0,134, 0, 0, 0,178, 0, 0, 0,119, 0, 0, 0,116,
+ 0, 0, 0, 50, 0, 0, 0,117, 0, 0, 0,121, 0, 0, 0, 50, 0, 0, 0,117, 0, 0, 0,136, 0, 0, 0, 50, 0, 0, 0,136,
+ 0, 0, 0,145, 0, 0, 0,178, 0, 0, 0,146, 0, 0, 0,147, 0, 0, 0,178, 0, 0, 0,147, 0, 0, 0,150, 0, 0, 0, 50,
+ 0, 0, 0,149, 0, 0, 0,151, 0, 0, 0,178, 0, 0, 0,148, 0, 0, 0,151, 0, 0, 0, 50, 0, 0, 0,148, 0, 0, 0,150,
+ 0, 0, 0,178, 0, 0, 0,138, 0, 0, 0,147, 0, 0, 0, 50, 0, 0, 0,130, 0, 0, 0,149, 0, 0, 0,178, 0, 0, 0,131,
+ 0, 0, 0,151, 0, 0, 0, 50, 0, 0, 0,132, 0, 0, 0,148, 0, 0, 0, 50, 0, 0, 0,133, 0, 0, 0,150, 0, 0, 0, 50,
+ 0, 0, 0,155, 0, 0, 0,171, 0, 0, 0, 35, 0, 0, 0,154, 0, 0, 0,170, 0, 0, 0, 35, 0, 0, 0,153, 0, 0, 0,169,
+ 0, 0, 0, 35, 0, 0, 0,152, 0, 0, 0,168, 0, 0, 0, 35, 0, 0, 0,155, 0, 0, 0,159, 0, 0, 0, 35, 0, 0, 0,154,
+ 0, 0, 0,155, 0, 0, 0, 35, 0, 0, 0,154, 0, 0, 0,158, 0, 0, 0, 35, 0, 0, 0,153, 0, 0, 0,154, 0, 0, 0, 35,
+ 0, 0, 0,153, 0, 0, 0,157, 0, 0, 0, 35, 0, 0, 0,152, 0, 0, 0,153, 0, 0, 0, 35, 0, 0, 0,152, 0, 0, 0,156,
+ 0, 0, 0, 35, 0, 0, 0,159, 0, 0, 0,163, 0, 0, 0, 35, 0, 0, 0,158, 0, 0, 0,159, 0, 0, 0, 35, 0, 0, 0,158,
+ 0, 0, 0,162, 0, 0, 0, 35, 0, 0, 0,157, 0, 0, 0,158, 0, 0, 0, 35, 0, 0, 0,157, 0, 0, 0,161, 0, 0, 0, 35,
+ 0, 0, 0,156, 0, 0, 0,157, 0, 0, 0, 35, 0, 0, 0,156, 0, 0, 0,160, 0, 0, 0, 35, 0, 0, 0,163, 0, 0, 0,167,
+ 0, 0, 0, 35, 0, 0, 0,162, 0, 0, 0,163, 0, 0, 0, 35, 0, 0, 0,162, 0, 0, 0,166, 0, 0, 0, 35, 0, 0, 0,161,
+ 0, 0, 0,162, 0, 0, 0, 35, 0, 0, 0,161, 0, 0, 0,165, 0, 0, 0, 35, 0, 0, 0,160, 0, 0, 0,161, 0, 0, 0, 35,
+ 0, 0, 0,160, 0, 0, 0,164, 0, 0, 0, 35, 0, 0, 0,166, 0, 0, 0,167, 0, 0, 0, 35, 0, 0, 0,165, 0, 0, 0,166,
+ 0, 0, 0, 35, 0, 0, 0,164, 0, 0, 0,165, 0, 0, 0, 35, 0, 0, 0,169, 0, 0, 0,170, 0, 0, 0, 35, 0, 0, 0,174,
+ 0, 0, 0,175, 0, 0, 0, 35, 0, 0, 0,172, 0, 0, 0,176, 0, 0, 0, 35, 0, 0, 0,168, 0, 0, 0,172, 0, 0, 0, 35,
+ 0, 0, 0,164, 0, 0, 0,173, 0, 0, 0, 35, 0, 0, 0,160, 0, 0, 0,174, 0, 0, 0, 35, 0, 0, 0,156, 0, 0, 0,175,
+ 0, 0, 0, 35, 0, 0, 0,152, 0, 0, 0,176, 0, 0, 0, 35, 0, 0, 0,177, 0, 0, 0,181, 0, 0, 0, 35, 0, 0, 0,177,
+ 0, 0, 0,178, 0, 0, 0,163, 0, 0, 0,178, 0, 0, 0,179, 0, 0, 0, 35, 0, 0, 0,179, 0, 0, 0,180, 0, 0, 0,163,
+ 0, 0, 0,171, 0, 0, 0,181, 0, 0, 0, 35, 0, 0, 0,167, 0, 0, 0,180, 0, 0, 0, 35, 0, 0, 0,163, 0, 0, 0,179,
+ 0, 0, 0, 35, 0, 0, 0,159, 0, 0, 0,178, 0, 0, 0, 35, 0, 0, 0,155, 0, 0, 0,177, 0, 0, 0, 35, 0, 0, 0,182,
+ 0, 0, 0,184, 0, 0, 0, 35, 0, 0, 0,183, 0, 0, 0,187, 0, 0, 0, 35, 0, 0, 0,185, 0, 0, 0,186, 0, 0, 0, 35,
+ 0, 0, 0,180, 0, 0, 0,182, 0, 0, 0, 35, 0, 0, 0,173, 0, 0, 0,183, 0, 0, 0, 35, 0, 0, 0,164, 0, 0, 0,187,
+ 0, 0, 0, 35, 0, 0, 0,165, 0, 0, 0,186, 0, 0, 0, 35, 0, 0, 0,166, 0, 0, 0,185, 0, 0, 0, 35, 0, 0, 0,167,
+ 0, 0, 0,184, 0, 0, 0, 35, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,114, 0, 0, 0, 1, 35, 0, 0, 0, 5, 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, 7,160,234, 32, 0, 0, 0, 5, 0, 0, 0, 20,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 86, 84,101,120, 0, 0, 0, 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,160,242, 32, 0, 0, 0, 6, 0, 0, 0, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,111,108, 0, 0, 0, 0, 0, 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,161, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 5,240, 7,160,234, 32, 0, 0, 0, 54, 0, 0, 0, 76, 0, 0, 0, 18,
+ 0, 0, 0, 22, 0, 0, 0, 26, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 19, 0, 0, 0, 4, 0, 0, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 5,
+ 0, 0, 0, 9, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 25, 0, 0, 0, 24, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 12,
+ 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 6, 0, 0, 0, 10, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 12,
+ 0, 0, 0, 13, 0, 0, 0, 17, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 11, 0, 0, 0, 15, 0, 0, 0, 14,
+ 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 23, 0, 0, 0, 30, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 16,
+ 0, 0, 0, 32, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 0, 0, 0, 29, 0, 0, 0, 14, 0, 0, 0, 0,
+ 0, 0, 0, 42, 0, 0, 0, 65, 0, 0, 0,114, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 44, 0, 0, 0, 42,
+ 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 57, 0, 0, 0, 61, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 49,
+ 0, 0, 0, 48, 0, 0, 0, 46, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 1, 0, 0, 0, 53, 0, 0, 0, 48,
+ 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 56,
+ 0, 0, 0, 60, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 54, 0, 0, 0, 58, 0, 0, 0, 57, 0, 0, 0, 0,
+ 0, 0, 0, 58, 0, 0, 0, 59, 0, 0, 0, 63, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 0, 0, 0, 68,
+ 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 62, 0, 0, 0, 66, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0,115,
+ 0, 0, 0, 51, 0, 0, 0, 66, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 22, 0, 0, 0, 76, 0, 0, 0, 85,
+ 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 19, 0, 0, 0, 84, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 21,
+ 0, 0, 0, 82, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 85, 0, 0, 0, 89, 0, 0, 0, 88, 0, 0, 0, 0,
+ 0, 0, 0, 82, 0, 0, 0, 83, 0, 0, 0, 87, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 75, 0, 0, 0, 74,
+ 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 87, 0, 0, 0, 88, 0, 0, 0, 92, 0, 0, 0, 91, 0, 0, 0, 0, 0, 0, 0, 60,
+ 0, 0, 0, 86, 0, 0, 0, 90, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 92, 0, 0, 0, 93, 0, 0, 0, 97, 0, 0, 0, 96,
+ 0, 0, 0, 0, 0, 0, 0, 90, 0, 0, 0, 91, 0, 0, 0, 95, 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 97, 0, 0, 0, 73,
+ 0, 0, 0, 77, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, 0, 96, 0, 0, 0, 80, 0, 0, 0, 79, 0, 0, 0, 0,
+ 0, 0, 0, 78, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 36, 0, 0, 0, 50,
+ 0, 0, 0,101, 0, 0, 0, 0, 0, 0, 0,100, 0, 0, 0, 99, 0, 0, 0, 39, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 98,
+ 0, 0, 0, 72, 0, 0, 0, 41, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0,104, 0, 0, 0,100, 0, 0, 0,101,
+ 0, 0, 0, 0, 0, 0, 0,103, 0, 0, 0,102, 0, 0, 0, 98, 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0,109,
+ 0, 0, 0,105, 0, 0, 0,114, 0, 0, 0, 0, 0, 0, 0,108, 0, 0, 0,107, 0, 0, 0,103, 0, 0, 0,104, 0, 0, 0, 0,
+ 0, 0, 0,106, 0, 0, 0, 70, 0, 0, 0, 71, 0, 0, 0,102, 0, 0, 0, 0, 0, 0, 0,113, 0, 0, 0,112, 0, 0, 0,108,
+ 0, 0, 0,109, 0, 0, 0, 0, 0, 0, 0,111, 0, 0, 0,110, 0, 0, 0,106, 0, 0, 0,107, 0, 0, 0, 0, 0, 0, 0,113,
+ 0, 0, 0,115, 0, 0, 0, 52, 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 80, 0, 0, 0,111, 0, 0, 0,112,
+ 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 77, 0, 0, 0, 69, 0, 0, 0,110, 0, 0, 0, 0, 0, 0, 0,116, 0, 0, 0,135,
+ 0, 0, 0,120, 0, 0, 0,119, 0, 0, 0, 16, 0, 0, 0,125, 0, 0, 0,124, 0, 0, 0,120, 0, 0, 0,121, 0, 0, 0, 16,
+ 0, 0, 0,123, 0, 0, 0,122, 0, 0, 0,118, 0, 0, 0,119, 0, 0, 0, 16, 0, 0, 0,128, 0, 0, 0,127, 0, 0, 0,123,
+ 0, 0, 0,124, 0, 0, 0, 16, 0, 0, 0,133, 0, 0, 0,132, 0, 0, 0,128, 0, 0, 0,129, 0, 0, 0, 16, 0, 0, 0,131,
+ 0, 0, 0,130, 0, 0, 0,126, 0, 0, 0,127, 0, 0, 0, 16, 0, 0, 0,148, 0, 0, 0,151, 0, 0, 0,131, 0, 0, 0,132,
+ 0, 0, 0, 16, 0, 0, 0,147, 0, 0, 0,150, 0, 0, 0,133, 0, 0, 0,138, 0, 0, 0, 16, 0, 0, 0,137, 0, 0, 0,138,
+ 0, 0, 0,140, 0, 0, 0,139, 0, 0, 0, 16, 0, 0, 0,140, 0, 0, 0,129, 0, 0, 0,125, 0, 0, 0,142, 0, 0, 0, 16,
+ 0, 0, 0,141, 0, 0, 0,142, 0, 0, 0,144, 0, 0, 0,143, 0, 0, 0, 16, 0, 0, 0,144, 0, 0, 0,121, 0, 0, 0,117,
+ 0, 0, 0,136, 0, 0, 0, 16, 0, 0, 0,171, 0, 0, 0,181, 0, 0, 0,177, 0, 0, 0,155, 0, 0, 0, 2, 0, 0, 0,154,
+ 0, 0, 0,153, 0, 0, 0,169, 0, 0, 0,170, 0, 0, 0, 2, 0, 0, 0,152, 0, 0, 0,176, 0, 0, 0,172, 0, 0, 0,168,
+ 0, 0, 0, 2, 0, 0, 0,159, 0, 0, 0,158, 0, 0, 0,154, 0, 0, 0,155, 0, 0, 0, 2, 0, 0, 0,157, 0, 0, 0,156,
+ 0, 0, 0,152, 0, 0, 0,153, 0, 0, 0, 2, 0, 0, 0,179, 0, 0, 0,163, 0, 0, 0,159, 0, 0, 0,178, 0, 0, 0, 2,
+ 0, 0, 0,162, 0, 0, 0,161, 0, 0, 0,157, 0, 0, 0,158, 0, 0, 0, 2, 0, 0, 0,160, 0, 0, 0,174, 0, 0, 0,175,
+ 0, 0, 0,156, 0, 0, 0, 2, 0, 0, 0,167, 0, 0, 0,166, 0, 0, 0,162, 0, 0, 0,163, 0, 0, 0, 2, 0, 0, 0,165,
+ 0, 0, 0,164, 0, 0, 0,160, 0, 0, 0,161, 0, 0, 0, 2, 0, 0, 0,182, 0, 0, 0,184, 0, 0, 0,167, 0, 0, 0,180,
+ 0, 0, 0, 2, 0, 0, 0,185, 0, 0, 0,186, 0, 0, 0,165, 0, 0, 0,166, 0, 0, 0, 2, 0, 0, 0,187, 0, 0, 0,183,
+ 0, 0, 0,173, 0, 0, 0,164, 0, 0, 0, 2, 68, 65, 84, 65, 0, 0, 13, 16, 7,160,242, 32, 0, 0, 0, 65, 0, 0, 0, 76,
+ 63, 27,168,250, 59, 93,211, 96, 62,203,162, 84, 59, 93,211, 96, 62,203,162, 84, 59, 93,211, 96, 63, 27,168,251, 59, 93,211, 96,
+ 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63,131,172, 21, 59, 93,211, 96, 63, 81,128,146, 59, 93,211, 96, 63, 81,128,149,
+ 59, 93,211, 96, 63,131,172, 22, 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63,158,151,227, 59, 93,211, 96,
+ 63,185,131,174, 59, 93,211, 96, 63,185,131,174, 59, 93,211, 96, 63,158,151,225, 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1,
+ 0, 0, 0, 0, 63, 81,128,149, 59, 93,211, 96, 63, 27,168,251, 59, 93,211, 96, 63, 27,168,246, 59, 93,211, 96, 63, 81,128,142,
+ 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63,158,151,227, 59, 93,211, 96, 63,131,172, 22, 59, 93,211, 96,
+ 63,131,172, 24, 59, 93,211, 96, 63,158,151,226, 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63, 27,168,246,
+ 59, 93,211, 96, 62,203,162, 86, 59, 93,211, 96, 62,203,162, 85, 59, 93,211, 96, 63, 27,168,247, 59, 93,211, 96, 0, 0, 0, 0,
+ 61, 0, 0, 1, 0, 0, 0, 0, 63,131,172, 24, 59, 93,211, 96, 63, 81,128,142, 59, 93,211, 96, 63, 81,128,144, 59, 93,211, 96,
+ 63,131,172, 21, 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63,185,131,174, 59, 93,211, 96, 63,158,151,226,
+ 59, 93,211, 96, 63,158,151,226, 59, 93,211, 96, 63,185,131,176, 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0,
+ 63, 81,128,144, 59, 93,211, 96, 63, 27,168,247, 59, 93,211, 96, 63, 27,168,247, 59, 93,211, 96, 63, 81,128,144, 59, 93,211, 96,
+ 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63,158,151,226, 59, 93,211, 96, 63,131,172, 21, 59, 93,211, 96, 63,131,172, 22,
+ 59, 93,211, 96, 63,158,151,224, 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63, 27,168,247, 59, 93,211, 96,
+ 62,203,162, 85, 59, 93,211, 96, 62,203,162, 86, 59, 93,211, 96, 63, 27,168,248, 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1,
+ 0, 0, 0, 0, 63,131,172, 22, 59, 93,211, 96, 63, 81,128,144, 59, 93,211, 96, 63, 81,128,144, 59, 93,211, 96, 63,131,172, 22,
+ 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63,158,151,226, 59, 93,211, 96, 63,185,131,176, 59, 93,211, 96,
+ 63,185,131,174, 59, 93,211, 96, 63,158,151,224, 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63,140,131, 99,
+ 63, 41, 47, 76, 63,114,244, 44, 63, 79, 65,236, 63,114,244, 44, 63, 79, 65,236, 63,140,131, 99, 63, 41, 47, 76, 0, 0, 0, 0,
+ 60, 0, 0, 1, 0, 0, 0, 0, 63,159,140,161, 63, 3, 28,210, 63,140,131, 99, 63, 41, 47, 76, 63,140,131, 99, 63, 41, 47, 76,
+ 63,159,140,161, 63, 3, 28,210, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,140,131, 99, 63, 41, 47, 76, 63,114,244, 44,
+ 63, 79, 65,236, 63,114,244, 44, 63, 79, 65,236, 63,140,131, 99, 63, 41, 47, 76, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,
+ 63,159,140,161, 63, 3, 28,210, 63,140,131, 99, 63, 41, 47, 76, 63,140,131, 99, 63, 41, 47, 76, 63,159,140,161, 63, 3, 28,210,
+ 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,140,131, 99, 63, 41, 47, 72, 63,114,244, 44, 63, 79, 65,236, 63,114,244, 44,
+ 63, 79, 65,236, 63,140,131, 99, 63, 41, 47, 76, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 76,225,174, 63,117, 84,102,
+ 63, 38,207, 52, 63,141,179,111, 63, 38,207, 52, 63,141,179,111, 63, 76,225,174, 63,117, 84,102, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0, 63, 38,207, 52, 63,141,179,111, 63, 0,188,188, 63,160,188,173, 63, 0,188,188, 63,160,188,173, 63, 38,207, 52,
+ 63,141,179,111, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,114,244, 44, 63, 79, 65,236, 63, 76,225,174, 63,117, 84,102,
+ 63, 76,225,172, 63,117, 84,102, 63,114,244, 44, 63, 79, 65,236, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 76,225,172,
+ 63,117, 84,102, 63, 38,207, 52, 63,141,179,111, 63, 38,207, 52, 63,141,179,111, 63, 76,225,172, 63,117, 84,102, 0, 0, 0, 0,
+ 60, 0, 0, 1, 0, 0, 0, 0, 63, 38,207, 52, 63,141,179,111, 63, 0,188,188, 63,160,188,173, 63, 0,188,188, 63,160,188,173,
+ 63, 38,207, 52, 63,141,179,111, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,114,244, 44, 63, 79, 65,236, 63, 76,225,172,
+ 63,117, 84,102, 63, 76,225,172, 63,117, 84,102, 63,114,244, 44, 63, 79, 65,236, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,
+ 63, 38,207, 56, 63,141,179,111, 63, 76,225,172, 63,117, 84,102, 63, 76,225,172, 63,117, 84,102, 63, 38,207, 52, 63,141,179,111,
+ 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,189,188,105, 96, 63, 41, 47,120,190,118,127, 56, 63, 3, 28,220,190,118,127, 56,
+ 63, 3, 28,220,189,188,105, 96, 63, 41, 47,120, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62, 82, 95, 26, 63,117, 84,102,
+ 61,104, 84,200, 63, 79, 65,244, 61,104, 84,200, 63, 79, 65,242, 62, 82, 95, 26, 63,117, 84,102, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0, 63, 0,188,190, 63,160,188,171, 62,181, 84,122, 63,141,179,113, 62,181, 84,122, 63,141,179,113, 63, 0,188,188,
+ 63,160,188,173, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 61,104, 84,200, 63, 79, 65,242,189,188,105, 96, 63, 41, 47,120,
+189,188,105,128, 63, 41, 47,120, 61,104, 84,160, 63, 79, 65,242, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62,181, 84,122,
+ 63,141,179,113, 62, 82, 95, 26, 63,117, 84,102, 62, 82, 95, 26, 63,117, 84,102, 62,181, 84,122, 63,141,179,113, 0, 0, 0, 0,
+ 60, 0, 0, 1, 0, 0, 0, 0,189,188,105,128, 63, 41, 47,120,190,118,127, 64, 63, 3, 28,216,190,118,127, 64, 63, 3, 28,216,
+189,188,105,128, 63, 41, 47,120, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62, 82, 95, 26, 63,117, 84,102, 61,104, 84,160,
+ 63, 79, 65,242, 61,104, 84,160, 63, 79, 65,242, 62, 82, 95, 26, 63,117, 84,102, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,
+ 63, 0,188,188, 63,160,188,173, 62,181, 84,122, 63,141,179,113, 62,181, 84,122, 63,141,179,113, 63, 0,188,188, 63,160,188,173,
+ 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 61,104, 84,160, 63, 79, 65,242,189,188,105,128, 63, 41, 47,120,189,188,105,128,
+ 63, 41, 47,120, 61,104, 84,160, 63, 79, 65,242, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62,181, 84,122, 63,141,179,113,
+ 62, 82, 95, 26, 63,117, 84,102, 62, 82, 95, 26, 63,117, 84,102, 62,181, 84,122, 63,141,179,113, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0,189,188,105,128, 63, 41, 47,120,190,118,127, 64, 63, 3, 28,216,190,118,127, 64, 63, 3, 28,216,189,188,105,128,
+ 63, 41, 47,120, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62, 82, 95, 26, 63,117, 84,102, 61,104, 84,160, 63, 79, 65,242,
+ 61,104, 84,160, 63, 79, 65,242, 62, 82, 95, 26, 63,117, 84,102, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62,181, 84,122,
+ 63,141,179,113, 63, 0,188,188, 63,160,188,173, 63, 0,188,188, 63,160,188,173, 62,181, 84,122, 63,141,179,113, 0, 0, 0, 0,
+ 60, 0, 0, 1, 0, 0, 0, 0, 63,140,131,180, 62,186, 19,116, 63,159,140,244, 63, 3, 28, 50, 63,140,131, 99, 63, 41, 47, 76,
+ 63,114,244, 42, 63, 3, 28,244, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 76,225,174, 62,186, 21, 0, 63, 38,207, 51,
+ 62, 91,224, 24, 63, 76,226,112, 61,135, 38, 64, 63,114,244,240, 62, 91,221, 4, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,
+ 63, 0,188,185, 61,135, 44, 96, 62,181, 84, 61,189,169,104,176, 63, 0,189, 93,190,109, 1, 80, 63, 38,207,248,189,169,109,144,
+ 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 76,225,174, 63, 41, 47,116, 63, 38,207, 52, 63, 3, 28,248, 63, 76,225,174,
+ 62,186, 21, 0, 63,114,244, 42, 63, 3, 28,244, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 0,188,185, 62,186, 21, 0,
+ 62,181, 84,122, 62, 91,224, 32, 63, 0,188,185, 61,135, 44, 96, 63, 38,207, 51, 62, 91,224, 24, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0, 63, 76,225,172, 63,117, 84,102, 63, 38,207, 52, 63, 79, 65,236, 63, 76,225,174, 63, 41, 47,116, 63,114,244, 44,
+ 63, 79, 65,236, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 0,188,188, 63, 41, 47,120, 62,181, 84,122, 63, 3, 28,248,
+ 63, 0,188,185, 62,186, 21, 0, 63, 38,207, 52, 63, 3, 28,248, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62, 82, 95, 14,
+ 62,186, 21, 0, 61,104, 82,144, 62, 91,223,128, 62, 82, 94,138, 61,135, 43, 48, 62,181, 84,122, 62, 91,224, 32, 0, 0, 0, 0,
+ 60, 0, 0, 1, 0, 0, 0, 0, 63, 0,188,190, 63,117, 84,102, 62,181, 84,127, 63, 79, 65,242, 63, 0,188,188, 63, 41, 47,120,
+ 63, 38,207, 52, 63, 79, 65,236, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62, 82, 95, 26, 63, 41, 47,120, 61,104, 84,160,
+ 63, 3, 29, 0, 62, 82, 95, 14, 62,186, 21, 0, 62,181, 84,122, 63, 3, 28,248, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,
+ 63, 0,188,190, 63,117, 84,102, 63, 38,207, 56, 63,141,179,111, 63, 0,188,188, 63,160,188,173, 62,181, 84,122, 63,141,179,113,
+ 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62, 82, 95, 26, 63,117, 84,102, 61,104, 84,160, 63, 79, 65,242, 62, 82, 95, 26,
+ 63, 41, 47,120, 62,181, 84,127, 63, 79, 65,242, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,189,188,105,128, 63, 41, 47,120,
+190,118,127, 64, 63, 3, 28,216,189,188,106,128, 62,186, 20,176, 61,104, 84,160, 63, 3, 29, 0, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0, 63, 38,207, 56, 63,141,179,111, 63, 76,225,172, 63,117, 84,102, 63, 76,225,172, 63,117, 84,102, 63, 38,207, 52,
+ 63,141,179,111, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,114,244, 44, 63, 79, 65,236, 63, 76,225,172, 63,117, 84,102,
+ 63, 76,225,172, 63,117, 84,102, 63,114,244, 44, 63, 79, 65,236, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 38,207, 52,
+ 63,141,179,111, 63, 0,188,188, 63,160,188,173, 63, 0,188,188, 63,160,188,173, 63, 38,207, 52, 63,141,179,111, 0, 0, 0, 0,
+ 60, 0, 0, 1, 0, 0, 0, 0, 63, 76,225,172, 63,117, 84,102, 63, 38,207, 52, 63,141,179,111, 63, 38,207, 52, 63,141,179,111,
+ 63, 76,225,172, 63,117, 84,102, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,114,244, 44, 63, 79, 65,236, 63, 76,225,174,
+ 63,117, 84,102, 63, 76,225,172, 63,117, 84,102, 63,114,244, 44, 63, 79, 65,236, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,
+ 63, 38,207, 52, 63,141,179,111, 63, 0,188,188, 63,160,188,173, 63, 0,188,188, 63,160,188,173, 63, 38,207, 52, 63,141,179,111,
+ 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 76,225,174, 63,117, 84,102, 63, 38,207, 52, 63,141,179,111, 63, 38,207, 52,
+ 63,141,179,111, 63, 76,225,174, 63,117, 84,102, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,140,131, 99, 63, 41, 47, 72,
+ 63,114,244, 44, 63, 79, 65,236, 63,114,244, 44, 63, 79, 65,236, 63,140,131, 99, 63, 41, 47, 76, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0, 63,159,140,161, 63, 3, 28,210, 63,140,131, 99, 63, 41, 47, 76, 63,140,131, 99, 63, 41, 47, 76, 63,159,140,161,
+ 63, 3, 28,210, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,140,131, 99, 63, 41, 47, 76, 63,114,244, 44, 63, 79, 65,236,
+ 63,114,244, 44, 63, 79, 65,236, 63,140,131, 99, 63, 41, 47, 76, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,159,140,161,
+ 63, 3, 28,210, 63,140,131, 99, 63, 41, 47, 76, 63,140,131, 99, 63, 41, 47, 76, 63,159,140,161, 63, 3, 28,210, 0, 0, 0, 0,
+ 60, 0, 0, 1, 0, 0, 0, 0, 63,140,131, 99, 63, 41, 47, 76, 63,114,244, 44, 63, 79, 65,236, 63,114,244, 44, 63, 79, 65,236,
+ 63,140,131, 99, 63, 41, 47, 76, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62,181, 84,122, 63,141,179,113, 63, 0,188,188,
+ 63,160,188,173, 63, 0,188,188, 63,160,188,173, 62,181, 84,122, 63,141,179,113, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,
+ 62, 82, 95, 26, 63,117, 84,102, 61,104, 84,160, 63, 79, 65,242, 61,104, 84,160, 63, 79, 65,242, 62, 82, 95, 26, 63,117, 84,102,
+ 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,189,188,105,128, 63, 41, 47,120,190,118,127, 64, 63, 3, 28,216,190,118,127, 64,
+ 63, 3, 28,216,189,188,105,128, 63, 41, 47,120, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62,181, 84,122, 63,141,179,113,
+ 62, 82, 95, 26, 63,117, 84,102, 62, 82, 95, 26, 63,117, 84,102, 62,181, 84,122, 63,141,179,113, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0, 61,104, 84,160, 63, 79, 65,242,189,188,105,128, 63, 41, 47,120,189,188,105,128, 63, 41, 47,120, 61,104, 84,160,
+ 63, 79, 65,242, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 0,188,188, 63,160,188,173, 62,181, 84,122, 63,141,179,113,
+ 62,181, 84,122, 63,141,179,113, 63, 0,188,188, 63,160,188,173, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62, 82, 95, 26,
+ 63,117, 84,102, 61,104, 84,160, 63, 79, 65,242, 61,104, 84,160, 63, 79, 65,242, 62, 82, 95, 26, 63,117, 84,102, 0, 0, 0, 0,
+ 60, 0, 0, 1, 0, 0, 0, 0,189,188,105,128, 63, 41, 47,120,190,118,127, 64, 63, 3, 28,216,190,118,127, 64, 63, 3, 28,216,
+189,188,105,128, 63, 41, 47,120, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62,181, 84,122, 63,141,179,113, 62, 82, 95, 26,
+ 63,117, 84,102, 62, 82, 95, 26, 63,117, 84,102, 62,181, 84,122, 63,141,179,113, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,
+ 61,104, 84,200, 63, 79, 65,242,189,188,105, 96, 63, 41, 47,120,189,188,105,128, 63, 41, 47,120, 61,104, 84,160, 63, 79, 65,242,
+ 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 0,188,190, 63,160,188,171, 62,181, 84,122, 63,141,179,113, 62,181, 84,122,
+ 63,141,179,113, 63, 0,188,188, 63,160,188,173, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62, 82, 95, 26, 63,117, 84,102,
+ 61,104, 84,200, 63, 79, 65,244, 61,104, 84,200, 63, 79, 65,242, 62, 82, 95, 26, 63,117, 84,102, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0,189,188,105, 96, 63, 41, 47,120,190,118,127, 56, 63, 3, 28,220,190,118,127, 56, 63, 3, 28,220,189,188,105, 96,
+ 63, 41, 47,120, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 4,192, 7,161, 0, 32, 0, 0, 0, 59,
+ 0, 0, 1, 48,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255, 0, 0, 77, 69, 0, 0, 1, 24, 13, 65,115, 96, 0, 0, 0, 52, 0, 0, 0, 1, 13, 65,120,240, 13, 65,109,208,
+ 0, 0, 0, 0, 0, 0, 0, 0, 77, 69, 80,108, 97,110,101, 46, 48, 48, 49, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 13, 65,116,160, 7,161, 40, 32, 7,161, 46, 32, 0, 0, 0, 0, 7,161, 6, 32, 7,161, 24, 32, 0, 0, 0, 0, 7,161, 60, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,116,208, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 65,118, 48, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,119,144,
+ 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,182, 0, 0, 1, 45, 0, 0, 0, 74,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 63, 76,204,213, 63, 76,204,255,182,104, 0, 0, 63,128, 0, 30, 63,128, 0,140,
+ 63,127,255,214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 4, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 65,116,160, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,116,208, 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,161, 6, 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, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 17, 16, 7,161, 6, 32, 0, 0, 0, 58, 0, 0, 0,182, 63,230,102,133,
+ 63,179, 51,208,191,128, 0, 4,165,127, 0, 0, 90,129, 2,255, 0, 0, 0, 0, 63,230,102,133, 63, 25,154,206,191,128, 0, 4,
+165,127, 0, 0, 90,129, 2,255, 0, 0, 0, 0, 63,179, 51, 81, 63,179, 51,210,191,128, 0, 3, 0, 0, 0, 0,127,255, 2,255,
+ 0, 0, 0, 0, 63,128, 0, 28, 63,179, 51,212,191,128, 0, 1, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63, 25,153,207,
+ 63,179, 51,214,191,128, 0, 0, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 62, 76,205,152, 63,179, 51,216,191,127,255,254,
+ 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 63,128, 0,158,191,128, 0, 3, 0, 0, 0, 0,127,255, 2,255,
+ 0, 0, 0, 0, 63,128, 0, 27, 63,128, 0,160,191,128, 0, 2, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63, 25,153,204,
+ 63,128, 0,162,191,128, 0, 0, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63,128, 0,163,191,127,255,254,
+ 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 63, 25,154,209,191,128, 0, 3, 0, 0, 0, 0,127,255, 2,255,
+ 0, 0, 0, 0, 63,128, 0, 27, 63, 25,154,213,191,128, 0, 2, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63, 25,153,204,
+ 63, 25,154,217,191,128, 0, 0, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63, 25,154,221,191,127,255,254,
+ 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 62, 76,209,160,191,128, 0, 3, 0, 0, 0, 0,127,255, 2,255,
+ 0, 0, 0, 0, 63,128, 0, 27, 62, 76,209,176,191,128, 0, 2, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63, 25,153,204,
+ 62, 76,209,188,191,128, 0, 1, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 62, 76,205,140, 62, 76,209,204,191,127,255,255,
+ 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63,230,103, 8,191, 25,153,156, 0, 0,128, 1, 0, 0, 2,255,
+ 0, 0, 0, 0, 63, 25,153,204, 63,230,103, 10,191, 25,153,160, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 63,128, 0, 27,
+ 63,230,103, 10,191, 25,153,164, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 63,230,103, 12,191, 25,153,168,
+ 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63,230,103, 8,190, 76,204,196, 0, 0,128, 1, 0, 0, 2,255,
+ 0, 0, 0, 0, 63, 25,153,204, 63,230,103, 10,190, 76,204,212, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 63,128, 0, 27,
+ 63,230,103, 10,190, 76,204,228, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 63,230,103, 12,190, 76,204,244,
+ 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63,230,103, 8, 62, 76,204,216, 0, 0,128, 1, 0, 0, 2,255,
+ 0, 0, 0, 0, 63, 25,153,204, 63,230,103, 10, 62, 76,204,200, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 63,128, 0, 27,
+ 63,230,103, 10, 62, 76,204,184, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 63,230,103, 12, 62, 76,204,168,
+ 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 62, 76,205,152, 63,230,103, 8, 63, 25,153,158, 0, 0,128, 1, 0, 0, 2,255,
+ 0, 0, 0, 0, 63, 25,153,207, 63,230,103, 10, 63, 25,153,154, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 63,128, 0, 28,
+ 63,230,103, 10, 63, 25,153,150, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 63,179, 51, 81, 63,230,103, 12, 63, 25,153,150,
+ 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63,230,103, 8,191,128, 0, 3, 0, 0,165,127, 90,129, 0,255,
+ 0, 0, 0, 0, 63, 25,153,204, 63,230,103, 10,191,128, 0, 4, 0, 0,165,127, 90,129, 0,255, 0, 0, 0, 0, 63,128, 0, 27,
+ 63,230,103, 10,191,128, 0, 6, 0, 0,165,127, 90,129, 0,255, 0, 0, 0, 0, 63,179, 51, 80, 63,230,103, 12,191,128, 0, 7,
+ 0, 0,165,127, 90,129, 0,255, 0, 0, 0, 0,190, 76,205,144, 63,230,103, 12, 63, 25,153,150, 0, 0,128, 1, 0, 0, 2,255,
+ 0, 0, 0, 0,190, 76,205,152, 63,230,103, 12, 62, 76,204,168, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0,190, 76,205,152,
+ 63,230,103, 12,190, 76,204,244, 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0,190, 76,205,152, 63,230,103, 12,191, 25,153,168,
+ 0, 0,128, 1, 0, 0, 2,255, 0, 0, 0, 0,190, 76,205,152, 62, 76,209,160,191,128, 0, 3, 0, 0, 0, 0,127,255, 2,255,
+ 0, 0, 0, 0,190, 76,205,152, 63, 25,154,209,191,128, 0, 3, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,190, 76,205,152,
+ 63,128, 0,158,191,128, 0, 3, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,190, 76,205,144, 63,179, 51,210,191,128, 0, 3,
+ 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,230,102,131, 63,230,103, 7,191, 25,153,155,165,127,165,127, 0, 0, 2,255,
+ 0, 0, 0, 0, 63,230,102,131, 63,179, 51,212,191, 25,153,159,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131,
+ 63,128, 0,160,191, 25,153,163,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,135, 63, 25,154,207,191, 25,153,167,
+128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131, 63,230,103, 7,190, 76,204,193,165,127,165,127, 0, 0, 2,255,
+ 0, 0, 0, 0, 63,230,102,131, 63,179, 51,212,190, 76,204,209,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131,
+ 63,128, 0,160,190, 76,204,225,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,135, 63, 25,154,207,190, 76,204,241,
+128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131, 63,230,103, 7, 62, 76,204,219,165,127,165,127, 0, 0, 2,255,
+ 0, 0, 0, 0, 63,230,102,131, 63,179, 51,212, 62, 76,204,203,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131,
+ 63,128, 0,160, 62, 76,204,187,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,135, 63, 25,154,207, 62, 76,204,171,
+128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131, 63,230,103, 7, 63, 25,153,159,165,127,165,127, 0, 0, 2,255,
+ 0, 0, 0, 0, 63,230,102,131, 63,179, 51,212, 63, 25,153,155,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131,
+ 63,128, 0,156, 63, 25,153,151,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,135, 63, 25,154,207, 63, 25,153,151,
+128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131, 63,230,103, 7,191,128, 0, 3,128, 1, 0, 0, 0, 0, 2,255,
+ 0, 0, 0, 0, 63,230,102,131, 63,128, 0,160,191,128, 0, 6,165,127, 0, 0, 90,129, 2,255, 0, 0, 0, 0, 63,230,102,127,
+ 62, 76,208, 28,191,128, 0, 3,165,127, 0, 0, 90,129, 2,255, 0, 0, 0, 0, 63,230,102,131,190, 76,201,136, 63, 25,153,155,
+128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,127, 62, 76,208, 28, 63, 25,153,159,128, 1, 0, 0, 0, 0, 2,255,
+ 0, 0, 0, 0, 63,230,102,131,190, 76,201,136, 62, 76,204,203,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,127,
+ 62, 76,208, 28, 62, 76,204,219,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,131,190, 76,201,136,190, 76,204,209,
+128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,127, 62, 76,208, 28,190, 76,204,193,128, 1, 0, 0, 0, 0, 2,255,
+ 0, 0, 0, 0, 63,230,102,131,190, 76,201,136,191, 25,153,159,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,127,
+ 62, 76,208, 28,191, 25,153,155,128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 62, 76,205,150,190, 76,208, 24,191,127,255,254,
+ 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63, 25,153,207,190, 76,208, 40,191,128, 0, 0, 0, 0, 0, 0,127,255, 2,255,
+ 0, 0, 0, 0, 63,128, 0, 28,190, 76,208, 56,191,128, 0, 1, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 81,
+190, 76,208, 72,191,128, 0, 3, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,230,102,133,190, 76,208, 88,191,128, 0, 4,
+128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0, 63,230,102,133,190, 76,208, 88, 63,127,255,146,128, 1, 0, 0, 0, 0, 2,255,
+ 0, 0, 0, 0, 63,179, 51, 81,190, 76,208, 72, 63,127,255,148, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,128, 0, 28,
+190, 76,208, 56, 63,127,255,152, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63, 25,153,207,190, 76,208, 40, 63,127,255,154,
+ 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 62, 76,205,150,190, 76,208, 24, 63,127,255,156, 0, 0, 0, 0,127,255, 2,255,
+ 0, 0, 0, 0, 63,230,102,127, 62, 76,208, 28, 63,127,255,148,165,127, 0, 0, 90,129, 2,255, 0, 0, 0, 0, 63,230,102,131,
+ 63,128, 0,160, 63,127,255,142,165,127, 0, 0, 90,129, 2,255, 0, 0, 0, 0, 63,230,102,131, 63,230,103, 7, 63,127,255,148,
+128, 1, 0, 0, 0, 0, 2,255, 0, 0, 0, 0,190, 76,205,144, 63,179, 51,210, 63,127,255,148, 0, 0, 0, 0,127,255, 2,255,
+ 0, 0, 0, 0,190, 76,205,152, 63,128, 0,158, 63,127,255,148, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,190, 76,205,152,
+ 63, 25,154,209, 63,127,255,148, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,190, 76,205,152, 62, 76,209,160, 63,127,255,148,
+ 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 63,230,103, 12, 63,127,255,140, 0, 0,165,127, 90,129, 2,255,
+ 0, 0, 0, 0, 63,128, 0, 27, 63,230,103, 10, 63,127,255,142, 0, 0,165,127, 90,129, 2,255, 0, 0, 0, 0, 63, 25,153,204,
+ 63,230,103, 10, 63,127,255,146, 0, 0,165,127, 90,129, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63,230,103, 8, 63,127,255,148,
+ 0, 0,165,127, 90,129, 2,255, 0, 0, 0, 0, 62, 76,205,140, 62, 76,209,204, 63,127,255,154, 0, 0, 0, 0,127,255, 2,255,
+ 0, 0, 0, 0, 63, 25,153,204, 62, 76,209,188, 63,127,255,152, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,128, 0, 27,
+ 62, 76,209,176, 63,127,255,150, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 62, 76,209,160, 63,127,255,148,
+ 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63, 25,154,221, 63,127,255,156, 0, 0, 0, 0,127,255, 2,255,
+ 0, 0, 0, 0, 63, 25,153,204, 63, 25,154,217, 63,127,255,154, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,128, 0, 27,
+ 63, 25,154,213, 63,127,255,150, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 63, 25,154,209, 63,127,255,148,
+ 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 62, 76,205,140, 63,128, 0,163, 63,127,255,156, 0, 0, 0, 0,127,255, 2,255,
+ 0, 0, 0, 0, 63, 25,153,204, 63,128, 0,162, 63,127,255,154, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,128, 0, 27,
+ 63,128, 0,160, 63,127,255,150, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 80, 63,128, 0,158, 63,127,255,148,
+ 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 62, 76,205,152, 63,179, 51,216, 63,127,255,156, 0, 0, 0, 0,127,255, 2,255,
+ 0, 0, 0, 0, 63, 25,153,207, 63,179, 51,214, 63,127,255,154, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,128, 0, 28,
+ 63,179, 51,212, 63,127,255,152, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,179, 51, 81, 63,179, 51,210, 63,127,255,148,
+ 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 63,230,102,133, 63, 25,154,206, 63,127,255,146,165,127, 0, 0, 90,129, 2,255,
+ 0, 0, 0, 0, 63,230,102,133, 63,179, 51,208, 63,127,255,146,165,127, 0, 0, 90,129, 2,255, 0, 0, 0, 0,190, 76,205,144,
+ 62, 76,201,140, 63,127,255,148,127,255, 0, 0, 0, 0, 1,255, 0, 0, 0, 0,190, 76,205,136, 63,127,255, 52, 63,127,255,148,
+127,255, 0, 0, 0, 0, 1,255, 0, 0, 0, 0,190, 76,205,128,190, 76,208, 48, 63,127,255,150,127,255, 0, 0, 0, 0, 3,255,
+ 0, 0, 0, 0,190, 76,205,120, 63, 25,152,194, 63,127,255,144,127,255, 0, 0, 0, 0, 1,255, 0, 0, 0, 0,190, 76,205, 80,
+ 63,179, 50,254, 63,127,255,150,127,255, 0, 0, 0, 0, 1,255, 0, 0, 0, 0,190, 76,205,128, 63,230,103, 12, 63,127,255,148,
+127,255, 0, 0, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,128, 63,230,103, 12,191,128, 0, 5,127,255, 0, 0, 0, 0, 3,255,
+ 0, 0, 0, 0,190, 76,205, 80, 63,179, 50,254,191, 25,153,156,127,255, 0, 0, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,112,
+ 63,230,102, 50,191, 25,153,160,127,255, 0, 0, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205, 80, 63,179, 50,254,190, 76,204,195,
+127,255, 0, 0, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,112, 63,230,102, 50,190, 76,204,211,127,255, 0, 0, 0, 0, 3,255,
+ 0, 0, 0, 0,190, 76,205, 80, 63,179, 50,254, 62, 76,204,221,127,255, 0, 0, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,112,
+ 63,230,102, 50, 62, 76,204,205,127,255, 0, 0, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205, 80, 63,179, 50,254, 63, 25,153,160,
+127,255, 0, 0, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,112, 63,230,102, 50, 63, 25,153,156,127,255, 0, 0, 0, 0, 3,255,
+ 0, 0, 0, 0,190, 76,205, 80, 63,179, 50,254,191,128, 0, 4,127,255, 0, 0, 0, 0, 1,255, 0, 0, 0, 0,190, 76,205,120,
+ 63, 25,152,194,191,128, 0, 7,127,255, 0, 0, 0, 0, 1,255, 0, 0, 0, 0,190, 76,205,128,190, 76,208, 48,191,128, 0, 4,
+127,255, 0, 0, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,152, 63,127,255, 52, 63, 25,153,152,127,255, 0, 0, 0, 0, 3,255,
+ 0, 0, 0, 0,190, 76,205,120, 63, 25,152,202, 63, 25,153,152,127,255, 0, 0, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,128,
+ 62, 76,201,108, 63, 25,153,156,127,255, 0, 0, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,128,190, 76,208, 48, 63, 25,153,160,
+127,255, 0, 0, 0, 0, 1,255, 0, 0, 0, 0,190, 76,205,152, 63,127,255, 52, 62, 76,204,173,127,255, 0, 0, 0, 0, 3,255,
+ 0, 0, 0, 0,190, 76,205,120, 63, 25,152,194, 62, 76,204,189,127,255, 0, 0, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,128,
+ 62, 76,201,108, 62, 76,204,205,127,255, 0, 0, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,128,190, 76,208, 48, 62, 76,204,221,
+127,255, 0, 0, 0, 0, 1,255, 0, 0, 0, 0,190, 76,205,152, 63,127,255, 52,190, 76,204,243,127,255, 0, 0, 0, 0, 3,255,
+ 0, 0, 0, 0,190, 76,205,120, 63, 25,152,194,190, 76,204,227,127,255, 0, 0, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,128,
+ 62, 76,201,108,190, 76,204,211,127,255, 0, 0, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,128,190, 76,208, 48,190, 76,204,195,
+127,255, 0, 0, 0, 0, 1,255, 0, 0, 0, 0,190, 76,205,152, 63,127,255, 52,191, 25,153,168,127,255, 0, 0, 0, 0, 3,255,
+ 0, 0, 0, 0,190, 76,205,120, 63, 25,152,194,191, 25,153,164,127,255, 0, 0, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,128,
+ 62, 76,201,108,191, 25,153,160,127,255, 0, 0, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,128,190, 76,208, 48,191, 25,153,156,
+127,255, 0, 0, 0, 0, 1,255, 0, 0, 0, 0,190, 76,205,136, 63,127,255, 52,191,128, 0, 5,127,255, 0, 0, 0, 0, 1,255,
+ 0, 0, 0, 0,190, 76,205,144, 62, 76,201,140,191,128, 0, 5,127,255, 0, 0, 0, 0, 1,255, 0, 0, 0, 0, 63,179, 51, 36,
+190, 76,208, 56, 63,127,255,150, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,127,255,222,190, 76,208, 80, 63,127,255,148,
+ 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63, 25,153,116,190, 76,208, 80, 63,127,255,144, 0, 0,127,255, 0, 0, 3,255,
+ 0, 0, 0, 0, 62, 76,204, 44,190, 76,208,104, 63,127,255,142, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0,190, 76,205,112,
+190, 76,208, 64, 63,127,255,150,231, 94,231, 94,123, 41, 1,255, 0, 0, 0, 0,190, 76,205,112,190, 76,208, 64,191,128, 0, 4,
+231, 94,231, 94,132,215, 1,255, 0, 0, 0, 0,190, 76,205,112,190, 76,208, 64, 63, 25,153,160, 0, 0,127,255, 0, 0, 1,255,
+ 0, 0, 0, 0,190, 76,205,112,190, 76,208, 64, 62, 76,204,221, 0, 0,127,255, 0, 0, 1,255, 0, 0, 0, 0,190, 76,205,112,
+190, 76,208, 64,190, 76,204,195, 0, 0,127,255, 0, 0, 1,255, 0, 0, 0, 0,190, 76,205,112,190, 76,208, 64,191, 25,153,156,
+ 0, 0,127,255, 0, 0, 1,255, 0, 0, 0, 0, 63,230,102,136,190, 76,208, 88,191, 25,153,169, 0, 0,127,255, 0, 0, 3,255,
+ 0, 0, 0, 0, 63,230,102,136,190, 76,208, 88,190, 76,204,246, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,230,102,136,
+190, 76,208, 88, 62, 76,204,170, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,230,102,135,190, 76,208, 88, 63, 25,153,151,
+ 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 62, 76,204, 44,190, 76,208,104,191,128, 0, 8, 0, 0,127,255, 0, 0, 3,255,
+ 0, 0, 0, 0, 63, 25,153,116,190, 76,208, 80,191,128, 0, 7, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,127,255,222,
+190, 76,208, 80,191,128, 0, 5, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,179, 51, 36,190, 76,208, 56,191,128, 0, 4,
+ 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 62, 76,204, 36,190, 76,208,104, 63, 25,153,151, 0, 0,127,255, 0, 0, 3,255,
+ 0, 0, 0, 0, 63, 25,153,114,190, 76,208, 80, 63, 25,153,151, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,127,255,220,
+190, 76,208, 80, 63, 25,153,155, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,179, 51, 34,190, 76,208, 56, 63, 25,153,159,
+ 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 62, 76,204, 44,190, 76,208,104, 62, 76,204,170, 0, 0,127,255, 0, 0, 3,255,
+ 0, 0, 0, 0, 63, 25,153,116,190, 76,208, 80, 62, 76,204,186, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,127,255,222,
+190, 76,208, 80, 62, 76,204,202, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,179, 51, 36,190, 76,208, 56, 62, 76,204,218,
+ 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 62, 76,204, 44,190, 76,208,104,190, 76,204,246, 0, 0,127,255, 0, 0, 3,255,
+ 0, 0, 0, 0, 63, 25,153,116,190, 76,208, 80,190, 76,204,230, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,127,255,222,
+190, 76,208, 80,190, 76,204,214, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,179, 51, 36,190, 76,208, 56,190, 76,204,198,
+ 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 62, 76,204, 44,190, 76,208,104,191, 25,153,169, 0, 0,127,255, 0, 0, 3,255,
+ 0, 0, 0, 0, 63, 25,153,116,190, 76,208, 80,191, 25,153,165, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,127,255,222,
+190, 76,208, 80,191, 25,153,161, 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 63,179, 51, 36,190, 76,208, 56,191, 25,153,157,
+ 0, 0,127,255, 0, 0, 3,255, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,118, 48, 0, 0, 1, 35, 0, 0, 0, 5,
+ 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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,161, 24, 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, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 14, 28, 7,161, 24, 32, 0, 0, 0, 55, 0, 0, 1, 45,
+ 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 34, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 34, 0, 0, 0, 2, 0, 0, 0, 3,
+ 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 34, 0, 0, 0, 5, 0, 0, 0, 9, 0, 0, 0, 34, 0, 0, 0, 8,
+ 0, 0, 0, 9, 0, 0, 0, 34, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 34, 0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 34,
+ 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0, 34, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 34, 0, 0, 0, 2, 0, 0, 0, 6,
+ 0, 0, 0, 34, 0, 0, 0, 9, 0, 0, 0, 13, 0, 0, 0, 34, 0, 0, 0, 12, 0, 0, 0, 13, 0, 0, 0, 34, 0, 0, 0, 8,
+ 0, 0, 0, 12, 0, 0, 0, 34, 0, 0, 0, 11, 0, 0, 0, 12, 0, 0, 0, 34, 0, 0, 0, 7, 0, 0, 0, 11, 0, 0, 0, 34,
+ 0, 0, 0, 10, 0, 0, 0, 11, 0, 0, 0, 34, 0, 0, 0, 6, 0, 0, 0, 10, 0, 0, 0, 34, 0, 0, 0, 1, 0, 0, 0, 10,
+ 0, 0, 0, 34, 0, 0, 0, 13, 0, 0, 0, 17, 0, 0, 0, 34, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 34, 0, 0, 0, 12,
+ 0, 0, 0, 16, 0, 0, 0, 34, 0, 0, 0, 15, 0, 0, 0, 16, 0, 0, 0, 34, 0, 0, 0, 11, 0, 0, 0, 15, 0, 0, 0, 34,
+ 0, 0, 0, 14, 0, 0, 0, 15, 0, 0, 0, 34, 0, 0, 0, 10, 0, 0, 0, 14, 0, 0, 0, 34, 0, 0, 0, 21, 0, 0, 0, 37,
+ 0, 0, 0, 34, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 34, 0, 0, 0, 19, 0, 0, 0, 35, 0, 0, 0, 34, 0, 0, 0, 18,
+ 0, 0, 0, 34, 0, 0, 0, 34, 0, 0, 0, 21, 0, 0, 0, 25, 0, 0, 0, 34, 0, 0, 0, 20, 0, 0, 0, 21, 0, 0, 0, 34,
+ 0, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 34, 0, 0, 0, 19, 0, 0, 0, 20, 0, 0, 0, 34, 0, 0, 0, 19, 0, 0, 0, 23,
+ 0, 0, 0, 34, 0, 0, 0, 18, 0, 0, 0, 19, 0, 0, 0, 34, 0, 0, 0, 18, 0, 0, 0, 22, 0, 0, 0, 34, 0, 0, 0, 25,
+ 0, 0, 0, 29, 0, 0, 0, 34, 0, 0, 0, 24, 0, 0, 0, 25, 0, 0, 0, 34, 0, 0, 0, 24, 0, 0, 0, 28, 0, 0, 0, 34,
+ 0, 0, 0, 23, 0, 0, 0, 24, 0, 0, 0, 34, 0, 0, 0, 23, 0, 0, 0, 27, 0, 0, 0, 34, 0, 0, 0, 22, 0, 0, 0, 23,
+ 0, 0, 0, 34, 0, 0, 0, 22, 0, 0, 0, 26, 0, 0, 0, 34, 0, 0, 0, 29, 0, 0, 0, 33, 0, 0, 0, 34, 0, 0, 0, 28,
+ 0, 0, 0, 29, 0, 0, 0, 34, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 34, 0, 0, 0, 27, 0, 0, 0, 28, 0, 0, 0, 34,
+ 0, 0, 0, 27, 0, 0, 0, 31, 0, 0, 0, 34, 0, 0, 0, 26, 0, 0, 0, 27, 0, 0, 0, 34, 0, 0, 0, 26, 0, 0, 0, 30,
+ 0, 0, 0, 34, 0, 0, 0, 32, 0, 0, 0, 33, 0, 0, 0, 34, 0, 0, 0, 31, 0, 0, 0, 32, 0, 0, 0, 34, 0, 0, 0, 30,
+ 0, 0, 0, 31, 0, 0, 0, 34, 0, 0, 0, 34, 0, 0, 0, 35, 0, 0, 0, 34, 0, 0, 0, 36, 0, 0, 0, 37, 0, 0, 0, 34,
+ 0, 0, 0, 2, 0, 0, 0, 37, 0, 0, 0, 34, 0, 0, 0, 3, 0, 0, 0, 36, 0, 0, 0, 34, 0, 0, 0, 4, 0, 0, 0, 35,
+ 0, 0, 0, 34, 0, 0, 0, 5, 0, 0, 0, 34, 0, 0, 0, 34, 0, 0, 0, 38, 0, 0, 0, 39, 0, 0, 0, 34, 0, 0, 0, 40,
+ 0, 0, 0, 41, 0, 0, 0, 34, 0, 0, 0, 42, 0, 0, 0, 43, 0, 0, 0, 34, 0, 0, 0, 44, 0, 0, 0, 45, 0, 0, 0, 34,
+ 0, 0, 0, 30, 0, 0, 0, 38, 0, 0, 0, 34, 0, 0, 0, 26, 0, 0, 0, 39, 0, 0, 0, 34, 0, 0, 0, 22, 0, 0, 0, 40,
+ 0, 0, 0, 34, 0, 0, 0, 18, 0, 0, 0, 41, 0, 0, 0, 34, 0, 0, 0, 17, 0, 0, 0, 42, 0, 0, 0, 34, 0, 0, 0, 13,
+ 0, 0, 0, 43, 0, 0, 0, 34, 0, 0, 0, 9, 0, 0, 0, 44, 0, 0, 0, 34, 0, 0, 0, 5, 0, 0, 0, 45, 0, 0, 0, 34,
+ 0, 0, 0, 49, 0, 0, 0, 72, 0, 0, 0, 34, 0, 0, 0, 53, 0, 0, 0, 70, 0, 0, 0, 34, 0, 0, 0, 57, 0, 0, 0, 68,
+ 0, 0, 0, 34, 0, 0, 0, 61, 0, 0, 0, 66, 0, 0, 0, 34, 0, 0, 0, 48, 0, 0, 0, 63, 0, 0, 0, 34, 0, 0, 0, 46,
+ 0, 0, 0, 62, 0, 0, 0, 34, 0, 0, 0, 49, 0, 0, 0, 53, 0, 0, 0, 34, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 34,
+ 0, 0, 0, 48, 0, 0, 0, 52, 0, 0, 0, 34, 0, 0, 0, 47, 0, 0, 0, 48, 0, 0, 0, 34, 0, 0, 0, 47, 0, 0, 0, 51,
+ 0, 0, 0, 34, 0, 0, 0, 46, 0, 0, 0, 47, 0, 0, 0, 34, 0, 0, 0, 46, 0, 0, 0, 50, 0, 0, 0, 34, 0, 0, 0, 53,
+ 0, 0, 0, 57, 0, 0, 0, 34, 0, 0, 0, 52, 0, 0, 0, 53, 0, 0, 0, 34, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 34,
+ 0, 0, 0, 51, 0, 0, 0, 52, 0, 0, 0, 34, 0, 0, 0, 51, 0, 0, 0, 55, 0, 0, 0, 34, 0, 0, 0, 50, 0, 0, 0, 51,
+ 0, 0, 0, 34, 0, 0, 0, 50, 0, 0, 0, 54, 0, 0, 0, 34, 0, 0, 0, 57, 0, 0, 0, 61, 0, 0, 0, 34, 0, 0, 0, 56,
+ 0, 0, 0, 57, 0, 0, 0, 34, 0, 0, 0, 56, 0, 0, 0, 60, 0, 0, 0, 34, 0, 0, 0, 55, 0, 0, 0, 56, 0, 0, 0, 34,
+ 0, 0, 0, 55, 0, 0, 0, 59, 0, 0, 0, 34, 0, 0, 0, 54, 0, 0, 0, 55, 0, 0, 0, 34, 0, 0, 0, 54, 0, 0, 0, 58,
+ 0, 0, 0, 34, 0, 0, 0, 60, 0, 0, 0, 61, 0, 0, 0, 34, 0, 0, 0, 59, 0, 0, 0, 60, 0, 0, 0, 34, 0, 0, 0, 58,
+ 0, 0, 0, 59, 0, 0, 0, 34, 0, 0, 0, 65, 0, 0, 0, 66, 0, 0, 0, 34, 0, 0, 0, 66, 0, 0, 0, 68, 0, 0, 0, 34,
+ 0, 0, 0, 67, 0, 0, 0, 68, 0, 0, 0, 34, 0, 0, 0, 68, 0, 0, 0, 70, 0, 0, 0, 34, 0, 0, 0, 69, 0, 0, 0, 70,
+ 0, 0, 0, 34, 0, 0, 0, 67, 0, 0, 0, 69, 0, 0, 0, 34, 0, 0, 0, 70, 0, 0, 0, 72, 0, 0, 0, 34, 0, 0, 0, 71,
+ 0, 0, 0, 72, 0, 0, 0, 34, 0, 0, 0, 64, 0, 0, 0, 72, 0, 0, 0, 34, 0, 0, 0, 1, 0, 0, 0, 63, 0, 0, 0, 34,
+ 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 47,
+ 0, 0, 0, 34, 0, 0, 0, 1, 0, 0, 0, 49, 0, 0, 0, 34, 0, 0, 0, 1, 0, 0, 0, 64, 0, 0, 0, 34, 0, 0, 0, 33,
+ 0, 0, 0, 58, 0, 0, 0, 34, 0, 0, 0, 29, 0, 0, 0, 54, 0, 0, 0, 34, 0, 0, 0, 25, 0, 0, 0, 50, 0, 0, 0, 34,
+ 0, 0, 0, 21, 0, 0, 0, 46, 0, 0, 0, 34, 0, 0, 0, 14, 0, 0, 0, 64, 0, 0, 0, 34, 0, 0, 0, 6, 0, 0, 0, 63,
+ 0, 0, 0, 34, 0, 0, 0, 75, 0, 0, 0, 76, 0, 0, 0, 34, 0, 0, 0, 73, 0, 0, 0, 74, 0, 0, 0, 34, 0, 0, 0, 71,
+ 0, 0, 0, 77, 0, 0, 0, 34, 0, 0, 0, 64, 0, 0, 0, 77, 0, 0, 0, 34, 0, 0, 0, 14, 0, 0, 0, 76, 0, 0, 0, 34,
+ 0, 0, 0, 15, 0, 0, 0, 75, 0, 0, 0, 34, 0, 0, 0, 16, 0, 0, 0, 74, 0, 0, 0, 34, 0, 0, 0, 17, 0, 0, 0, 73,
+ 0, 0, 0, 34, 0, 0, 0, 82, 0, 0, 0, 94, 0, 0, 0, 34, 0, 0, 0, 81, 0, 0, 0, 95, 0, 0, 0, 34, 0, 0, 0, 80,
+ 0, 0, 0, 96, 0, 0, 0, 34, 0, 0, 0, 79, 0, 0, 0, 97, 0, 0, 0, 34, 0, 0, 0, 78, 0, 0, 0, 83, 0, 0, 0, 34,
+ 0, 0, 0, 81, 0, 0, 0, 82, 0, 0, 0, 34, 0, 0, 0, 79, 0, 0, 0, 80, 0, 0, 0, 34, 0, 0, 0, 84, 0, 0, 0,105,
+ 0, 0, 0, 34, 0, 0, 0, 83, 0, 0, 0, 97, 0, 0, 0, 34, 0, 0, 0, 83, 0, 0, 0,110, 0, 0, 0, 34, 0, 0, 0, 85,
+ 0, 0, 0,111, 0, 0, 0, 34, 0, 0, 0, 84, 0, 0, 0,111, 0, 0, 0, 34, 0, 0, 0, 84, 0, 0, 0,110, 0, 0, 0, 34,
+ 0, 0, 0, 86, 0, 0, 0,106, 0, 0, 0, 34, 0, 0, 0, 87, 0, 0, 0,102, 0, 0, 0, 34, 0, 0, 0, 88, 0, 0, 0, 98,
+ 0, 0, 0, 34, 0, 0, 0, 89, 0, 0, 0, 94, 0, 0, 0, 34, 0, 0, 0, 86, 0, 0, 0, 87, 0, 0, 0, 34, 0, 0, 0, 88,
+ 0, 0, 0, 89, 0, 0, 0, 34, 0, 0, 0, 93, 0, 0, 0,106, 0, 0, 0, 34, 0, 0, 0, 92, 0, 0, 0,107, 0, 0, 0, 34,
+ 0, 0, 0, 91, 0, 0, 0,108, 0, 0, 0, 34, 0, 0, 0, 90, 0, 0, 0,109, 0, 0, 0, 34, 0, 0, 0, 90, 0, 0, 0, 91,
+ 0, 0, 0, 34, 0, 0, 0, 92, 0, 0, 0, 93, 0, 0, 0, 34, 0, 0, 0, 97, 0, 0, 0,101, 0, 0, 0, 34, 0, 0, 0, 96,
+ 0, 0, 0, 97, 0, 0, 0, 34, 0, 0, 0, 96, 0, 0, 0,100, 0, 0, 0, 34, 0, 0, 0, 95, 0, 0, 0, 96, 0, 0, 0, 34,
+ 0, 0, 0, 95, 0, 0, 0, 99, 0, 0, 0, 34, 0, 0, 0, 94, 0, 0, 0, 95, 0, 0, 0, 34, 0, 0, 0, 94, 0, 0, 0, 98,
+ 0, 0, 0, 34, 0, 0, 0,101, 0, 0, 0,110, 0, 0, 0, 34, 0, 0, 0,101, 0, 0, 0,105, 0, 0, 0, 34, 0, 0, 0,100,
+ 0, 0, 0,101, 0, 0, 0, 34, 0, 0, 0,100, 0, 0, 0,104, 0, 0, 0, 34, 0, 0, 0, 99, 0, 0, 0,100, 0, 0, 0, 34,
+ 0, 0, 0, 99, 0, 0, 0,103, 0, 0, 0, 34, 0, 0, 0, 98, 0, 0, 0, 99, 0, 0, 0, 34, 0, 0, 0, 98, 0, 0, 0,102,
+ 0, 0, 0, 34, 0, 0, 0,105, 0, 0, 0,109, 0, 0, 0, 34, 0, 0, 0,104, 0, 0, 0,105, 0, 0, 0, 34, 0, 0, 0,104,
+ 0, 0, 0,108, 0, 0, 0, 34, 0, 0, 0,103, 0, 0, 0,104, 0, 0, 0, 34, 0, 0, 0,103, 0, 0, 0,107, 0, 0, 0, 34,
+ 0, 0, 0,102, 0, 0, 0,103, 0, 0, 0, 34, 0, 0, 0,102, 0, 0, 0,106, 0, 0, 0, 34, 0, 0, 0,109, 0, 0, 0,111,
+ 0, 0, 0, 34, 0, 0, 0,108, 0, 0, 0,109, 0, 0, 0, 34, 0, 0, 0,107, 0, 0, 0,108, 0, 0, 0, 34, 0, 0, 0,106,
+ 0, 0, 0,107, 0, 0, 0, 34, 0, 0, 0, 65, 0, 0, 0, 78, 0, 0, 0, 34, 0, 0, 0, 66, 0, 0, 0, 83, 0, 0, 0, 34,
+ 0, 0, 0, 58, 0, 0, 0, 85, 0, 0, 0, 34, 0, 0, 0, 59, 0, 0, 0,111, 0, 0, 0, 34, 0, 0, 0, 60, 0, 0, 0, 84,
+ 0, 0, 0, 34, 0, 0, 0, 61, 0, 0, 0,110, 0, 0, 0, 34, 0, 0, 0, 30, 0, 0, 0, 93, 0, 0, 0, 34, 0, 0, 0, 31,
+ 0, 0, 0, 92, 0, 0, 0, 34, 0, 0, 0, 32, 0, 0, 0, 91, 0, 0, 0, 34, 0, 0, 0, 33, 0, 0, 0, 90, 0, 0, 0, 34,
+ 0, 0, 0,113, 0, 0, 0,130, 0, 0, 0, 35, 0, 0, 0,115, 0, 0, 0,131, 0, 0, 0, 35, 0, 0, 0,112, 0, 0, 0,132,
+ 0, 0, 0, 35, 0, 0, 0,114, 0, 0, 0,133, 0, 0, 0, 35, 0, 0, 0,116, 0, 0, 0,125, 0, 0, 0, 35, 0, 0, 0,117,
+ 0, 0, 0,126, 0, 0, 0, 35, 0, 0, 0,113, 0, 0, 0,115, 0, 0, 0, 35, 0, 0, 0,112, 0, 0, 0,115, 0, 0, 0,163,
+ 0, 0, 0,112, 0, 0, 0,114, 0, 0, 0, 35, 0, 0, 0,113, 0, 0, 0,116, 0, 0, 0,163, 0, 0, 0,116, 0, 0, 0,117,
+ 0, 0, 0, 35, 0, 0, 0,118, 0, 0, 0,127, 0, 0, 0, 35, 0, 0, 0,118, 0, 0, 0,120, 0, 0, 0, 35, 0, 0, 0,127,
+ 0, 0, 0,146, 0, 0, 0,163, 0, 0, 0,142, 0, 0, 0,146, 0, 0, 0, 35, 0, 0, 0,144, 0, 0, 0,147, 0, 0, 0, 35,
+ 0, 0, 0,129, 0, 0, 0,147, 0, 0, 0, 35, 0, 0, 0,128, 0, 0, 0,147, 0, 0, 0,163, 0, 0, 0,128, 0, 0, 0,146,
+ 0, 0, 0, 35, 0, 0, 0,119, 0, 0, 0,127, 0, 0, 0, 35, 0, 0, 0,119, 0, 0, 0,120, 0, 0, 0, 35, 0, 0, 0,119,
+ 0, 0, 0,121, 0, 0, 0, 35, 0, 0, 0,122, 0, 0, 0,124, 0, 0, 0, 35, 0, 0, 0,121, 0, 0, 0,122, 0, 0, 0, 35,
+ 0, 0, 0,121, 0, 0, 0,123, 0, 0, 0, 35, 0, 0, 0,123, 0, 0, 0,124, 0, 0, 0, 35, 0, 0, 0,123, 0, 0, 0,125,
+ 0, 0, 0, 35, 0, 0, 0,125, 0, 0, 0,126, 0, 0, 0, 35, 0, 0, 0,132, 0, 0, 0,133, 0, 0, 0, 35, 0, 0, 0,131,
+ 0, 0, 0,132, 0, 0, 0, 35, 0, 0, 0,130, 0, 0, 0,131, 0, 0, 0, 35, 0, 0, 0,133, 0, 0, 0,137, 0, 0, 0,163,
+ 0, 0, 0,136, 0, 0, 0,137, 0, 0, 0, 35, 0, 0, 0,132, 0, 0, 0,136, 0, 0, 0, 35, 0, 0, 0,135, 0, 0, 0,136,
+ 0, 0, 0, 35, 0, 0, 0,131, 0, 0, 0,135, 0, 0, 0, 35, 0, 0, 0,134, 0, 0, 0,135, 0, 0, 0, 35, 0, 0, 0,130,
+ 0, 0, 0,134, 0, 0, 0, 35, 0, 0, 0,137, 0, 0, 0,141, 0, 0, 0, 35, 0, 0, 0,140, 0, 0, 0,141, 0, 0, 0, 35,
+ 0, 0, 0,136, 0, 0, 0,140, 0, 0, 0, 35, 0, 0, 0,139, 0, 0, 0,140, 0, 0, 0, 35, 0, 0, 0,135, 0, 0, 0,139,
+ 0, 0, 0, 35, 0, 0, 0,138, 0, 0, 0,139, 0, 0, 0, 35, 0, 0, 0,134, 0, 0, 0,138, 0, 0, 0, 35, 0, 0, 0,141,
+ 0, 0, 0,145, 0, 0, 0,163, 0, 0, 0,144, 0, 0, 0,145, 0, 0, 0, 35, 0, 0, 0,140, 0, 0, 0,144, 0, 0, 0, 35,
+ 0, 0, 0,143, 0, 0, 0,144, 0, 0, 0, 35, 0, 0, 0,139, 0, 0, 0,143, 0, 0, 0, 35, 0, 0, 0,142, 0, 0, 0,143,
+ 0, 0, 0, 35, 0, 0, 0,138, 0, 0, 0,142, 0, 0, 0, 35, 0, 0, 0,129, 0, 0, 0,145, 0, 0, 0, 35, 0, 0, 0,128,
+ 0, 0, 0,143, 0, 0, 0, 35, 0, 0, 0,125, 0, 0, 0,130, 0, 0, 0, 35, 0, 0, 0,123, 0, 0, 0,134, 0, 0, 0, 35,
+ 0, 0, 0,121, 0, 0, 0,138, 0, 0, 0, 35, 0, 0, 0,119, 0, 0, 0,142, 0, 0, 0, 35, 0, 0, 0,151, 0, 0, 0,166,
+ 0, 0, 0, 35, 0, 0, 0,150, 0, 0, 0,167, 0, 0, 0, 35, 0, 0, 0,149, 0, 0, 0,168, 0, 0, 0, 35, 0, 0, 0,148,
+ 0, 0, 0,169, 0, 0, 0, 35, 0, 0, 0,152, 0, 0, 0,154, 0, 0, 0,163, 0, 0, 0,148, 0, 0, 0,149, 0, 0, 0, 35,
+ 0, 0, 0,150, 0, 0, 0,151, 0, 0, 0, 35, 0, 0, 0,157, 0, 0, 0,178, 0, 0, 0, 35, 0, 0, 0,156, 0, 0, 0,174,
+ 0, 0, 0, 35, 0, 0, 0,155, 0, 0, 0,170, 0, 0, 0, 35, 0, 0, 0,154, 0, 0, 0,166, 0, 0, 0, 35, 0, 0, 0,154,
+ 0, 0, 0,155, 0, 0, 0, 35, 0, 0, 0,155, 0, 0, 0,156, 0, 0, 0,163, 0, 0, 0,156, 0, 0, 0,157, 0, 0, 0, 35,
+ 0, 0, 0,153, 0, 0, 0,157, 0, 0, 0,163, 0, 0, 0,158, 0, 0, 0,181, 0, 0, 0, 35, 0, 0, 0,159, 0, 0, 0,177,
+ 0, 0, 0, 35, 0, 0, 0,160, 0, 0, 0,173, 0, 0, 0, 35, 0, 0, 0,161, 0, 0, 0,169, 0, 0, 0, 35, 0, 0, 0,158,
+ 0, 0, 0,159, 0, 0, 0, 35, 0, 0, 0,160, 0, 0, 0,161, 0, 0, 0, 35, 0, 0, 0,162, 0, 0, 0,163, 0, 0, 0, 35,
+ 0, 0, 0,164, 0, 0, 0,165, 0, 0, 0, 35, 0, 0, 0,168, 0, 0, 0,169, 0, 0, 0, 35, 0, 0, 0,167, 0, 0, 0,168,
+ 0, 0, 0, 35, 0, 0, 0,166, 0, 0, 0,167, 0, 0, 0, 35, 0, 0, 0,169, 0, 0, 0,173, 0, 0, 0, 35, 0, 0, 0,172,
+ 0, 0, 0,173, 0, 0, 0, 35, 0, 0, 0,168, 0, 0, 0,172, 0, 0, 0, 35, 0, 0, 0,171, 0, 0, 0,172, 0, 0, 0, 35,
+ 0, 0, 0,167, 0, 0, 0,171, 0, 0, 0, 35, 0, 0, 0,170, 0, 0, 0,171, 0, 0, 0, 35, 0, 0, 0,166, 0, 0, 0,170,
+ 0, 0, 0, 35, 0, 0, 0,173, 0, 0, 0,177, 0, 0, 0, 35, 0, 0, 0,176, 0, 0, 0,177, 0, 0, 0, 35, 0, 0, 0,172,
+ 0, 0, 0,176, 0, 0, 0, 35, 0, 0, 0,175, 0, 0, 0,176, 0, 0, 0, 35, 0, 0, 0,171, 0, 0, 0,175, 0, 0, 0, 35,
+ 0, 0, 0,174, 0, 0, 0,175, 0, 0, 0, 35, 0, 0, 0,170, 0, 0, 0,174, 0, 0, 0, 35, 0, 0, 0,177, 0, 0, 0,181,
+ 0, 0, 0, 35, 0, 0, 0,180, 0, 0, 0,181, 0, 0, 0, 35, 0, 0, 0,176, 0, 0, 0,180, 0, 0, 0, 35, 0, 0, 0,179,
+ 0, 0, 0,180, 0, 0, 0, 35, 0, 0, 0,175, 0, 0, 0,179, 0, 0, 0, 35, 0, 0, 0,178, 0, 0, 0,179, 0, 0, 0, 35,
+ 0, 0, 0,174, 0, 0, 0,178, 0, 0, 0, 35, 0, 0, 0,165, 0, 0, 0,181, 0, 0, 0, 35, 0, 0, 0,164, 0, 0, 0,180,
+ 0, 0, 0, 35, 0, 0, 0,163, 0, 0, 0,179, 0, 0, 0, 35, 0, 0, 0,162, 0, 0, 0,178, 0, 0, 0, 35, 68, 65, 84, 65,
+ 0, 0, 1, 44, 13, 65,119,144, 0, 0, 1, 35, 0, 0, 0, 5, 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, 7,161, 40, 32, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 85, 86, 84,101,120, 0, 0, 0, 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,161, 46, 32, 0, 0, 0, 6, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 67,111,108, 0, 0, 0, 0, 0, 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,161, 60, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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,
+ 0, 0, 5,200, 7,161, 40, 32, 0, 0, 0, 54, 0, 0, 0, 74, 0, 0, 0, 35, 0, 0, 0, 34, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 36, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 45,
+ 0, 0, 0, 44, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 7, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 13,
+ 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 11, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 13,
+ 0, 0, 0, 43, 0, 0, 0, 42, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 15,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0, 14, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 17,
+ 0, 0, 0, 73, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 75, 0, 0, 0, 76, 0, 0, 0, 14, 0, 0, 0, 15, 0, 0, 0, 0,
+ 0, 0, 0, 21, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 18, 0, 0, 0, 34,
+ 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 25, 0, 0, 0, 21, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 24,
+ 0, 0, 0, 23, 0, 0, 0, 19, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 40, 0, 0, 0, 41, 0, 0, 0, 18,
+ 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 28, 0, 0, 0, 24, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 26,
+ 0, 0, 0, 22, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 58, 0, 0, 0, 33, 0, 0, 0, 29, 0, 0, 0, 54, 0, 0, 0, 0,
+ 0, 0, 0, 32, 0, 0, 0, 31, 0, 0, 0, 27, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 38, 0, 0, 0, 39,
+ 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 90, 0, 0, 0, 91, 0, 0, 0, 32, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 92,
+ 0, 0, 0, 93, 0, 0, 0, 30, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 48, 0, 0, 0, 63, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 51,
+ 0, 0, 0, 47, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 56, 0, 0, 0, 52, 0, 0, 0, 53, 0, 0, 0, 0,
+ 0, 0, 0, 55, 0, 0, 0, 54, 0, 0, 0, 50, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 59, 0, 0, 0, 55,
+ 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0,110, 0, 0, 0, 84, 0, 0, 0, 60, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0,111,
+ 0, 0, 0, 85, 0, 0, 0, 58, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, 83, 0, 0, 0, 66, 0, 0, 0, 65,
+ 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 61, 0, 0, 0, 57, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 68,
+ 0, 0, 0, 70, 0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 53, 0, 0, 0, 49, 0, 0, 0, 72, 0, 0, 0, 0,
+ 0, 0, 0, 71, 0, 0, 0, 72, 0, 0, 0, 64, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 79, 0, 0, 0, 97,
+ 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, 0, 94, 0, 0, 0, 82, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0,110,
+ 0, 0, 0,101, 0, 0, 0, 97, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0,100, 0, 0, 0, 99, 0, 0, 0, 95, 0, 0, 0, 96,
+ 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 88, 0, 0, 0, 89, 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0,104,
+ 0, 0, 0,100, 0, 0, 0,101, 0, 0, 0, 0, 0, 0, 0,103, 0, 0, 0,102, 0, 0, 0, 98, 0, 0, 0, 99, 0, 0, 0, 0,
+ 0, 0, 0,111, 0, 0, 0,109, 0, 0, 0,105, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0,108, 0, 0, 0,107, 0, 0, 0,103,
+ 0, 0, 0,104, 0, 0, 0, 0, 0, 0, 0,106, 0, 0, 0, 86, 0, 0, 0, 87, 0, 0, 0,102, 0, 0, 0, 0, 0, 0, 0, 90,
+ 0, 0, 0, 91, 0, 0, 0,108, 0, 0, 0,109, 0, 0, 0, 0, 0, 0, 0, 92, 0, 0, 0, 93, 0, 0, 0,106, 0, 0, 0,107,
+ 0, 0, 0, 0, 0, 0, 0,120, 0, 0, 0,119, 0, 0, 0,127, 0, 0, 0,118, 0, 0, 0, 2, 0, 0, 0,121, 0, 0, 0,138,
+ 0, 0, 0,142, 0, 0, 0,119, 0, 0, 0, 2, 0, 0, 0,124, 0, 0, 0,123, 0, 0, 0,121, 0, 0, 0,122, 0, 0, 0, 2,
+ 0, 0, 0,125, 0, 0, 0,130, 0, 0, 0,134, 0, 0, 0,123, 0, 0, 0, 2, 0, 0, 0,117, 0, 0, 0,116, 0, 0, 0,125,
+ 0, 0, 0,126, 0, 0, 0, 2, 0, 0, 0,112, 0, 0, 0,114, 0, 0, 0,133, 0, 0, 0,132, 0, 0, 0, 2, 0, 0, 0,113,
+ 0, 0, 0,115, 0, 0, 0,131, 0, 0, 0,130, 0, 0, 0, 2, 0, 0, 0,131, 0, 0, 0,132, 0, 0, 0,136, 0, 0, 0,135,
+ 0, 0, 0, 2, 0, 0, 0,136, 0, 0, 0,137, 0, 0, 0,141, 0, 0, 0,140, 0, 0, 0, 2, 0, 0, 0,134, 0, 0, 0,135,
+ 0, 0, 0,139, 0, 0, 0,138, 0, 0, 0, 2, 0, 0, 0,139, 0, 0, 0,140, 0, 0, 0,144, 0, 0, 0,143, 0, 0, 0, 2,
+ 0, 0, 0,129, 0, 0, 0,147, 0, 0, 0,144, 0, 0, 0,145, 0, 0, 0, 2, 0, 0, 0,142, 0, 0, 0,143, 0, 0, 0,128,
+ 0, 0, 0,146, 0, 0, 0, 2, 0, 0, 0,149, 0, 0, 0,148, 0, 0, 0,169, 0, 0, 0,168, 0, 0, 0, 2, 0, 0, 0,151,
+ 0, 0, 0,150, 0, 0, 0,167, 0, 0, 0,166, 0, 0, 0, 2, 0, 0, 0,169, 0, 0, 0,161, 0, 0, 0,160, 0, 0, 0,173,
+ 0, 0, 0, 2, 0, 0, 0,167, 0, 0, 0,168, 0, 0, 0,172, 0, 0, 0,171, 0, 0, 0, 2, 0, 0, 0,154, 0, 0, 0,166,
+ 0, 0, 0,170, 0, 0, 0,155, 0, 0, 0, 2, 0, 0, 0,172, 0, 0, 0,173, 0, 0, 0,177, 0, 0, 0,176, 0, 0, 0, 2,
+ 0, 0, 0,170, 0, 0, 0,171, 0, 0, 0,175, 0, 0, 0,174, 0, 0, 0, 2, 0, 0, 0,177, 0, 0, 0,159, 0, 0, 0,158,
+ 0, 0, 0,181, 0, 0, 0, 2, 0, 0, 0,175, 0, 0, 0,176, 0, 0, 0,180, 0, 0, 0,179, 0, 0, 0, 2, 0, 0, 0,156,
+ 0, 0, 0,174, 0, 0, 0,178, 0, 0, 0,157, 0, 0, 0, 2, 0, 0, 0,180, 0, 0, 0,181, 0, 0, 0,165, 0, 0, 0,164,
+ 0, 0, 0, 2, 0, 0, 0,178, 0, 0, 0,179, 0, 0, 0,163, 0, 0, 0,162, 0, 0, 0, 2, 68, 65, 84, 65, 0, 0, 12,184,
+ 7,161, 46, 32, 0, 0, 0, 65, 0, 0, 0, 74, 61,104, 84,160, 63, 79, 65,242,189,188,105,128, 63, 41, 47,120, 61,104, 84,160,
+ 63, 3, 29, 0, 62, 82, 95, 26, 63, 41, 47,120, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62,181, 84,122, 63,141,179,113,
+ 62, 82, 95, 26, 63,117, 84,102, 62,181, 84,127, 63, 79, 65,242, 63, 0,188,190, 63,117, 84,102, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0, 61,104, 84,160, 63, 3, 29, 0,189,188,106,128, 62,186, 20,176, 61,104, 82,144, 62, 91,223,128, 62, 82, 95, 14,
+ 62,186, 21, 0, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62,181, 84,127, 63, 79, 65,242, 62, 82, 95, 26, 63, 41, 47,120,
+ 62,181, 84,122, 63, 3, 28,248, 63, 0,188,188, 63, 41, 47,120, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 38,207, 56,
+ 63,141,179,111, 63, 0,188,190, 63,117, 84,102, 63, 38,207, 52, 63, 79, 65,236, 63, 76,225,172, 63,117, 84,102, 0, 0, 0, 0,
+ 60, 0, 0, 1, 0, 0, 0, 0, 62,181, 84,122, 63, 3, 28,248, 62, 82, 95, 14, 62,186, 21, 0, 62,181, 84,122, 62, 91,224, 32,
+ 63, 0,188,185, 62,186, 21, 0, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 38,207, 52, 63, 79, 65,236, 63, 0,188,188,
+ 63, 41, 47,120, 63, 38,207, 52, 63, 3, 28,248, 63, 76,225,174, 63, 41, 47,116, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,
+ 62,181, 84,122, 62, 91,224, 32, 62, 82, 94,138, 61,135, 43, 48, 62,181, 84, 61,189,169,104,176, 63, 0,188,185, 61,135, 44, 96,
+ 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 38,207, 52, 63, 3, 28,248, 63, 0,188,185, 62,186, 21, 0, 63, 38,207, 51,
+ 62, 91,224, 24, 63, 76,225,174, 62,186, 21, 0, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,114,244, 44, 63, 79, 65,236,
+ 63, 76,225,174, 63, 41, 47,116, 63,114,244, 42, 63, 3, 28,244, 63,140,131, 99, 63, 41, 47, 76, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0, 63, 38,207, 51, 62, 91,224, 24, 63, 0,188,185, 61,135, 44, 96, 63, 38,207,248,189,169,109,144, 63, 76,226,112,
+ 61,135, 38, 64, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,114,244,240, 62, 91,221, 4, 63,140,131,180, 62,186, 19,116,
+ 63,114,244, 42, 63, 3, 28,244, 63, 76,225,174, 62,186, 21, 0, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62,181, 84,122,
+ 63,141,179,113, 62, 82, 95, 26, 63,117, 84,102, 62, 82, 95, 26, 63,117, 84,102, 62,181, 84,122, 63,141,179,113, 0, 0, 0, 0,
+ 60, 0, 0, 1, 0, 0, 0, 0, 61,104, 84,160, 63, 79, 65,242,189,188,105,128, 63, 41, 47,120,189,188,105,128, 63, 41, 47,120,
+ 61,104, 84,160, 63, 79, 65,242, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 0,188,188, 63,160,188,173, 62,181, 84,122,
+ 63,141,179,113, 62,181, 84,122, 63,141,179,113, 63, 0,188,188, 63,160,188,173, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,
+ 62, 82, 95, 26, 63,117, 84,102, 61,104, 84,160, 63, 79, 65,242, 61,104, 84,160, 63, 79, 65,242, 62, 82, 95, 26, 63,117, 84,102,
+ 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,189,188,105,128, 63, 41, 47,120,190,118,127, 64, 63, 3, 28,216,190,118,127, 64,
+ 63, 3, 28,216,189,188,105,128, 63, 41, 47,120, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62,181, 84,122, 63,141,179,113,
+ 62, 82, 95, 26, 63,117, 84,102, 62, 82, 95, 26, 63,117, 84,102, 62,181, 84,122, 63,141,179,113, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0, 61,104, 84,160, 63, 79, 65,242,189,188,105,128, 63, 41, 47,120,189,188,105,128, 63, 41, 47,120, 61,104, 84,160,
+ 63, 79, 65,242, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 0,188,188, 63,160,188,173, 62,181, 84,122, 63,141,179,113,
+ 62,181, 84,122, 63,141,179,113, 63, 0,188,188, 63,160,188,173, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62, 82, 95, 26,
+ 63,117, 84,102, 61,104, 84,200, 63, 79, 65,242, 61,104, 84,160, 63, 79, 65,242, 62, 82, 95, 26, 63,117, 84,102, 0, 0, 0, 0,
+ 60, 0, 0, 1, 0, 0, 0, 0,189,188,105, 96, 63, 41, 47,120,190,118,127, 56, 63, 3, 28,220,190,118,127, 64, 63, 3, 28,216,
+189,188,105,128, 63, 41, 47,120, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62,181, 84,122, 63,141,179,113, 62, 82, 95, 26,
+ 63,117, 84,102, 62, 82, 95, 26, 63,117, 84,102, 62,181, 84,122, 63,141,179,113, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,
+ 61,104, 84,200, 63, 79, 65,244,189,188,105, 96, 63, 41, 47,120,189,188,105, 96, 63, 41, 47,120, 61,104, 84,200, 63, 79, 65,242,
+ 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,114,244, 44, 63, 79, 65,236, 63, 76,225,172, 63,117, 84,102, 63, 76,225,172,
+ 63,117, 84,102, 63,114,244, 44, 63, 79, 65,236, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 0,188,188, 63,160,188,173,
+ 63, 38,207, 56, 63,141,179,111, 63, 38,207, 52, 63,141,179,111, 63, 0,188,188, 63,160,188,173, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0, 63, 76,225,172, 63,117, 84,102, 63, 38,207, 52, 63,141,179,111, 63, 38,207, 52, 63,141,179,111, 63, 76,225,172,
+ 63,117, 84,102, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,114,244, 44, 63, 79, 65,236, 63, 76,225,172, 63,117, 84,102,
+ 63, 76,225,172, 63,117, 84,102, 63,114,244, 44, 63, 79, 65,236, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 38,207, 52,
+ 63,141,179,111, 63, 0,188,188, 63,160,188,173, 63, 0,188,188, 63,160,188,173, 63, 38,207, 52, 63,141,179,111, 0, 0, 0, 0,
+ 60, 0, 0, 1, 0, 0, 0, 0, 63, 76,225,174, 63,117, 84,102, 63, 38,207, 52, 63,141,179,111, 63, 38,207, 52, 63,141,179,111,
+ 63, 76,225,172, 63,117, 84,102, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,114,244, 44, 63, 79, 65,236, 63, 76,225,174,
+ 63,117, 84,102, 63, 76,225,174, 63,117, 84,102, 63,114,244, 44, 63, 79, 65,236, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,
+ 63, 38,207, 52, 63,141,179,111, 63, 0,188,190, 63,160,188,171, 63, 0,188,188, 63,160,188,173, 63, 38,207, 52, 63,141,179,111,
+ 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,159,140,162, 63, 3, 28,210, 63,140,131, 99, 63, 41, 47, 72, 63,140,131, 99,
+ 63, 41, 47, 76, 63,159,140,161, 63, 3, 28,210, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,140,131, 99, 63, 41, 47, 76,
+ 63,114,244, 44, 63, 79, 65,236, 63,114,244, 44, 63, 79, 65,236, 63,140,131, 99, 63, 41, 47, 76, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0, 63,159,140,161, 63, 3, 28,210, 63,140,131, 99, 63, 41, 47, 76, 63,140,131, 99, 63, 41, 47, 76, 63,159,140,161,
+ 63, 3, 28,210, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,140,131, 99, 63, 41, 47, 76, 63,114,244, 44, 63, 79, 65,236,
+ 63,114,244, 44, 63, 79, 65,236, 63,140,131, 99, 63, 41, 47, 76, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,159,140,161,
+ 63, 3, 28,210, 63,140,131, 99, 63, 41, 47, 76, 63,140,131, 99, 63, 41, 47, 76, 63,159,140,244, 63, 3, 28, 50, 0, 0, 0, 0,
+ 60, 0, 0, 1, 0, 0, 0, 0, 63,131,172, 22, 59, 93,211, 96, 63,158,151,226, 59, 93,211, 96, 63,158,151,224, 59, 93,211, 96,
+ 63,131,172, 22, 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63, 81,128,144, 59, 93,211, 96, 63, 27,168,247,
+ 59, 93,211, 96, 63, 27,168,248, 59, 93,211, 96, 63, 81,128,144, 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0,
+ 63,185,131,176, 59, 93,211, 96, 63,158,151,226, 59, 93,211, 96, 63,158,151,224, 59, 93,211, 96, 63,185,131,174, 59, 93,211, 96,
+ 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63,131,172, 21, 59, 93,211, 96, 63, 81,128,144, 59, 93,211, 96, 63, 81,128,144,
+ 59, 93,211, 96, 63,131,172, 22, 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63, 27,168,247, 59, 93,211, 96,
+ 62,203,162, 85, 59, 93,211, 96, 62,203,162, 85, 59, 93,211, 96, 63, 27,168,247, 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1,
+ 0, 0, 0, 0, 63,158,151,226, 59, 93,211, 96, 63,131,172, 24, 59, 93,211, 96, 63,131,172, 21, 59, 93,211, 96, 63,158,151,226,
+ 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63, 81,128,142, 59, 93,211, 96, 63, 27,168,246, 59, 93,211, 96,
+ 63, 27,168,247, 59, 93,211, 96, 63, 81,128,144, 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63,185,131,174,
+ 59, 93,211, 96, 63,158,151,227, 59, 93,211, 96, 63,158,151,226, 59, 93,211, 96, 63,185,131,174, 59, 93,211, 96, 0, 0, 0, 0,
+ 61, 0, 0, 1, 0, 0, 0, 0, 63,131,172, 22, 59, 93,211, 96, 63, 81,128,149, 59, 93,211, 96, 63, 81,128,142, 59, 93,211, 96,
+ 63,131,172, 24, 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63, 27,168,251, 59, 93,211, 96, 62,203,162, 84,
+ 59, 93,211, 96, 62,203,162, 86, 59, 93,211, 96, 63, 27,168,246, 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0,
+ 63,158,151,225, 59, 93,211, 96, 63,131,172, 21, 59, 93,211, 96, 63,131,172, 22, 59, 93,211, 96, 63,158,151,227, 59, 93,211, 96,
+ 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63, 81,128,146, 59, 93,211, 96, 63, 27,168,250, 59, 93,211, 96, 63, 27,168,251,
+ 59, 93,211, 96, 63, 81,128,149, 59, 93,211, 96, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63,159,140,161, 63, 3, 28,210,
+ 63,140,131, 99, 63, 41, 47, 76, 63,140,131, 99, 63, 41, 47, 76, 63,159,140,244, 63, 3, 28, 50, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0, 63,140,131, 99, 63, 41, 47, 76, 63,114,244, 44, 63, 79, 65,236, 63,114,244, 44, 63, 79, 65,236, 63,140,131, 99,
+ 63, 41, 47, 76, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,159,140,161, 63, 3, 28,210, 63,140,131, 99, 63, 41, 47, 76,
+ 63,140,131, 99, 63, 41, 47, 76, 63,159,140,161, 63, 3, 28,210, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63,140,131, 99,
+ 63, 41, 47, 76, 63,114,244, 44, 63, 79, 65,236, 63,114,244, 44, 63, 79, 65,236, 63,140,131, 99, 63, 41, 47, 76, 0, 0, 0, 0,
+ 60, 0, 0, 1, 0, 0, 0, 0, 63,159,140,162, 63, 3, 28,210, 63,140,131, 99, 63, 41, 47, 72, 63,140,131, 99, 63, 41, 47, 76,
+ 63,159,140,161, 63, 3, 28,210, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 38,207, 52, 63,141,179,111, 63, 0,188,190,
+ 63,160,188,171, 63, 0,188,188, 63,160,188,173, 63, 38,207, 52, 63,141,179,111, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,
+ 63,114,244, 44, 63, 79, 65,236, 63, 76,225,174, 63,117, 84,102, 63, 76,225,174, 63,117, 84,102, 63,114,244, 44, 63, 79, 65,236,
+ 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 76,225,174, 63,117, 84,102, 63, 38,207, 52, 63,141,179,111, 63, 38,207, 52,
+ 63,141,179,111, 63, 76,225,172, 63,117, 84,102, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 38,207, 52, 63,141,179,111,
+ 63, 0,188,188, 63,160,188,173, 63, 0,188,188, 63,160,188,173, 63, 38,207, 52, 63,141,179,111, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0, 63,114,244, 44, 63, 79, 65,236, 63, 76,225,172, 63,117, 84,102, 63, 76,225,172, 63,117, 84,102, 63,114,244, 44,
+ 63, 79, 65,236, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 76,225,172, 63,117, 84,102, 63, 38,207, 52, 63,141,179,111,
+ 63, 38,207, 52, 63,141,179,111, 63, 76,225,172, 63,117, 84,102, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 63, 0,188,188,
+ 63,160,188,173, 63, 38,207, 56, 63,141,179,111, 63, 38,207, 52, 63,141,179,111, 63, 0,188,188, 63,160,188,173, 0, 0, 0, 0,
+ 60, 0, 0, 1, 0, 0, 0, 0, 63,114,244, 44, 63, 79, 65,236, 63, 76,225,172, 63,117, 84,102, 63, 76,225,172, 63,117, 84,102,
+ 63,114,244, 44, 63, 79, 65,236, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 61,104, 84,200, 63, 79, 65,244,189,188,105, 96,
+ 63, 41, 47,120,189,188,105, 96, 63, 41, 47,120, 61,104, 84,200, 63, 79, 65,242, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,
+ 62,181, 84,122, 63,141,179,113, 62, 82, 95, 26, 63,117, 84,102, 62, 82, 95, 26, 63,117, 84,102, 62,181, 84,122, 63,141,179,113,
+ 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,189,188,105, 96, 63, 41, 47,120,190,118,127, 56, 63, 3, 28,220,190,118,127, 64,
+ 63, 3, 28,216,189,188,105,128, 63, 41, 47,120, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62, 82, 95, 26, 63,117, 84,102,
+ 61,104, 84,200, 63, 79, 65,242, 61,104, 84,160, 63, 79, 65,242, 62, 82, 95, 26, 63,117, 84,102, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0, 63, 0,188,188, 63,160,188,173, 62,181, 84,122, 63,141,179,113, 62,181, 84,122, 63,141,179,113, 63, 0,188,188,
+ 63,160,188,173, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 61,104, 84,160, 63, 79, 65,242,189,188,105,128, 63, 41, 47,120,
+189,188,105,128, 63, 41, 47,120, 61,104, 84,160, 63, 79, 65,242, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62,181, 84,122,
+ 63,141,179,113, 62, 82, 95, 26, 63,117, 84,102, 62, 82, 95, 26, 63,117, 84,102, 62,181, 84,122, 63,141,179,113, 0, 0, 0, 0,
+ 60, 0, 0, 1, 0, 0, 0, 0,189,188,105,128, 63, 41, 47,120,190,118,127, 64, 63, 3, 28,216,190,118,127, 64, 63, 3, 28,216,
+189,188,105,128, 63, 41, 47,120, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62, 82, 95, 26, 63,117, 84,102, 61,104, 84,160,
+ 63, 79, 65,242, 61,104, 84,160, 63, 79, 65,242, 62, 82, 95, 26, 63,117, 84,102, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0,
+ 63, 0,188,188, 63,160,188,173, 62,181, 84,122, 63,141,179,113, 62,181, 84,122, 63,141,179,113, 63, 0,188,188, 63,160,188,173,
+ 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 61,104, 84,160, 63, 79, 65,242,189,188,105,128, 63, 41, 47,120,189,188,105,128,
+ 63, 41, 47,120, 61,104, 84,160, 63, 79, 65,242, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 62,181, 84,122, 63,141,179,113,
+ 62, 82, 95, 26, 63,117, 84,102, 62, 82, 95, 26, 63,117, 84,102, 62,181, 84,122, 63,141,179,113, 0, 0, 0, 0, 60, 0, 0, 1,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 4,160, 7,161, 60, 32, 0, 0, 0, 59, 0, 0, 1, 40,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 77, 69, 0, 0, 1, 24,
+ 13, 65,120,240, 0, 0, 0, 52, 0, 0, 0, 1, 13, 65,131, 64, 13, 65,115, 96, 0, 0, 0, 0, 0, 0, 0, 0, 77, 69, 80,108,
+ 97,110,101, 46, 48, 48, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 13, 65,122, 48, 13, 65,128, 48, 13, 65,129, 0,
+ 0, 0, 0, 0, 7,161, 66, 32, 13, 65,125, 32, 0, 0, 0, 0, 13, 65,130,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 13, 65,122, 96, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,123,192, 0, 0, 0, 1,
+ 0, 0, 0, 5, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,126,208, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 80,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 32, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 76,205, 4, 55, 39,197,172, 63, 76,204,214, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 5, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 65,122, 48, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 1, 44, 13, 65,122, 96, 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,161, 66, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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,
+ 0, 0, 2, 40, 7,161, 66, 32, 0, 0, 0, 58, 0, 0, 0, 23,191, 76,205, 4, 0, 0, 0, 0,190,204,204,208, 0, 0,128, 1,
+ 0, 0, 3, 1, 0, 0, 0, 0,190,204,205, 55, 0, 0, 0, 0,190,204,204,216, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0,
+182, 70, 0, 0, 52,128, 0, 0,190,204,204,224, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0,191, 76,205, 4, 0, 0, 0, 0,
+ 52, 96, 0, 0, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0,190,204,205, 55, 0, 0, 0, 0,179, 0, 0, 0, 0, 0,128, 1,
+ 0, 0, 3, 1, 0, 0, 0, 0,182, 70, 0, 0, 52,128, 0, 0,180,144, 0, 0, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0,
+191, 76,205, 4, 0, 0, 0, 0, 62,204,204,213, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0,190,204,205, 55, 0, 0, 0, 0,
+ 62,204,204,205, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0,182, 70, 0, 0, 52,128, 0, 0, 62,204,204,197, 0, 0,128, 1,
+ 0, 0, 3, 1, 0, 0, 0, 0,190,204,205, 47, 0, 0, 0, 0, 63, 76,204,206, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0,
+182, 62, 0, 0, 52,128, 0, 0, 63, 76,204,206, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0,191, 76,205, 4, 0, 0, 0, 0,
+191, 76,204,208, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0,190,204,205, 55, 0, 0, 0, 0,191, 76,204,212, 0, 0,128, 1,
+ 0, 0, 3, 1, 0, 0, 0, 0,182, 70, 0, 0, 52,128, 0, 0,191, 76,204,214, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0,
+ 62,204,205, 47,180,128, 0, 0,191, 76,204,206, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0, 63, 76,205, 4, 0, 0, 0, 0,
+ 63, 76,204,210, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0, 62,204,205, 53,180,128, 0, 0, 63, 76,204,214, 0, 0,128, 1,
+ 0, 0, 3, 1, 0, 0, 0, 0, 63, 76,205, 0, 0, 0, 0, 0, 62,204,204,213, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0,
+ 62,204,205, 47,180,128, 0, 0, 62,204,204,221, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0, 63, 76,205, 0, 0, 0, 0, 0,
+ 52, 96, 0, 0, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0, 62,204,205, 47,180,128, 0, 0, 52,240, 0, 0, 0, 0,128, 1,
+ 0, 0, 3, 1, 0, 0, 0, 0, 63, 76,205, 0, 0, 0, 0, 0,190,204,204,208, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0,
+ 62,204,205, 47,180,128, 0, 0,190,204,204,200, 0, 0,128, 1, 0, 0, 3, 1, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 44,
+ 13, 65,123,192, 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 65,125, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 0, 0, 1,128,
+ 13, 65,125, 32, 0, 0, 0, 55, 0, 0, 0, 32, 0, 0, 0, 2, 0, 0, 0, 22, 0, 0, 0, 35, 0, 0, 0, 5, 0, 0, 0, 20,
+ 0, 0, 0, 35, 0, 0, 0, 8, 0, 0, 0, 18, 0, 0, 0, 35, 0, 0, 0, 14, 0, 0, 0, 13, 0, 0, 0, 35, 0, 0, 0, 2,
+ 0, 0, 0, 13, 0, 0, 0, 35, 0, 0, 0, 1, 0, 0, 0, 12, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 35,
+ 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 35, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 35, 0, 0, 0, 4, 0, 0, 0, 1,
+ 0, 0, 0, 35, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 5, 0, 0, 0, 8, 0, 0, 0, 35, 0, 0, 0, 5,
+ 0, 0, 0, 4, 0, 0, 0, 35, 0, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 35, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 35,
+ 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 35, 0, 0, 0, 8, 0, 0, 0, 10, 0, 0, 0, 35, 0, 0, 0, 8, 0, 0, 0, 7,
+ 0, 0, 0, 35, 0, 0, 0, 7, 0, 0, 0, 9, 0, 0, 0, 35, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 35, 0, 0, 0, 9,
+ 0, 0, 0, 10, 0, 0, 0, 35, 0, 0, 0, 11, 0, 0, 0, 12, 0, 0, 0, 35, 0, 0, 0, 15, 0, 0, 0, 16, 0, 0, 0, 35,
+ 0, 0, 0, 16, 0, 0, 0, 18, 0, 0, 0, 35, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 35, 0, 0, 0, 15, 0, 0, 0, 17,
+ 0, 0, 0, 35, 0, 0, 0, 18, 0, 0, 0, 20, 0, 0, 0, 35, 0, 0, 0, 19, 0, 0, 0, 20, 0, 0, 0, 35, 0, 0, 0, 20,
+ 0, 0, 0, 22, 0, 0, 0, 35, 0, 0, 0, 21, 0, 0, 0, 22, 0, 0, 0, 35, 0, 0, 0, 19, 0, 0, 0, 21, 0, 0, 0, 35,
+ 0, 0, 0, 14, 0, 0, 0, 22, 0, 0, 0, 35, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,126,208, 0, 0, 1, 35, 0, 0, 0, 5,
+ 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, 13, 65,128, 48, 0, 0, 0, 5,
+ 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 86, 84,101,120, 0, 0, 0, 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, 65,129, 0, 0, 0, 0, 6, 0, 0, 0, 64,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,111,108, 0, 0, 0, 0, 0, 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, 65,130,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0,160, 13, 65,128, 48, 0, 0, 0, 54, 0, 0, 0, 8,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 12, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 1,
+ 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 10,
+ 0, 0, 0, 9, 0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0, 16, 0, 0, 0, 18, 0, 0, 0, 17,
+ 0, 0, 0, 2, 0, 0, 0, 18, 0, 0, 0, 8, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 2, 0, 0, 0, 22, 0, 0, 0, 21,
+ 0, 0, 0, 19, 0, 0, 0, 20, 0, 0, 0, 2, 0, 0, 0, 22, 0, 0, 0, 2, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 2,
+ 68, 65, 84, 65, 0, 0, 1, 96, 13, 65,129, 0, 0, 0, 0, 65, 0, 0, 0, 8, 62,137,192, 12, 63,125,226,162, 61,246,108,144,
+ 63,125,226,162, 61,246,108,144, 63,125,226,162, 62,137,192, 12, 63,125,226,162, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0,
+ 62,213,228,252, 63,125,226,162, 62,137,192, 12, 63,125,226,162, 62,137,192, 12, 63,125,226,162, 62,213,228,252, 63,125,226,162,
+ 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 62,137,192, 12, 63,125,226,162, 61,246,108,144, 63,125,226,162, 61,246,108,144,
+ 63,125,226,162, 62,137,192, 12, 63,125,226,162, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 62,213,229, 0, 63,125,226,162,
+ 62,137,192, 18, 63,125,226,162, 62,137,192, 12, 63,125,226,162, 62,213,228,252, 63,125,226,162, 0, 0, 0, 0, 61, 0, 0, 1,
+ 0, 0, 0, 0, 63, 55, 23,154, 63,125,226,162, 63, 17, 5, 34, 63,125,226,162, 63, 17, 5, 30, 63,125,226,162, 63, 55, 23,152,
+ 63,125,226,162, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63, 17, 5, 30, 63,125,226,162, 62,213,228,252, 63,125,226,162,
+ 62,213,228,252, 63,125,226,162, 63, 17, 5, 30, 63,125,226,162, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63, 17, 5, 30,
+ 63,125,226,162, 63, 55, 23,152, 63,125,226,162, 63, 55, 23,152, 63,125,226,162, 63, 17, 5, 30, 63,125,226,162, 0, 0, 0, 0,
+ 61, 0, 0, 1, 0, 0, 0, 0, 63, 17, 5, 30, 63,125,226,162, 62,213,228,252, 63,125,226,162, 62,213,228,252, 63,125,226,162,
+ 63, 17, 5, 30, 63,125,226,162, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,128, 13, 65,130,144,
+ 0, 0, 0, 59, 0, 0, 0, 32,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255, 0, 0, 77, 69, 0, 0, 1, 24, 13, 65,131, 64, 0, 0, 0, 52, 0, 0, 0, 1, 13, 65,141,144,
+ 13, 65,120,240,192,139, 5, 8, 0, 0, 0, 0, 77, 69, 80,108, 97,110,101, 46, 48, 48, 51, 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, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 65,132,128, 13, 65,138,128, 13, 65,139, 80, 0, 0, 0, 0, 7,161, 70, 32, 13, 65,135,112, 0, 0, 0, 0,
+ 13, 65,140,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,132,176, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 20,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,134, 16, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0,
+ 13, 65,137, 32, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 32,
+ 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 76,205, 2,
+ 55, 39,197,172, 63, 76,204,214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 5,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 65,132,128,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,132,176, 0, 0, 1, 35, 0, 0, 0, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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,161, 70, 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, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 2, 40, 7,161, 70, 32, 0, 0, 0, 58, 0, 0, 0, 23,
+ 62,204,205, 47,180,128, 0, 0,190,204,204,200, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0, 63, 76,205, 0, 0, 0, 0, 0,
+190,204,204,208, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0, 62,204,205, 47,180,128, 0, 0, 52,240, 0, 0, 0, 0,128, 1,
+ 0, 0, 2, 0, 0, 0, 0, 0, 63, 76,205, 0, 0, 0, 0, 0, 52, 96, 0, 0, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0,
+ 62,204,205, 47,180,128, 0, 0, 62,204,204,221, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0, 63, 76,205, 0, 0, 0, 0, 0,
+ 62,204,204,213, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0, 62,204,205, 53,180,128, 0, 0, 63, 76,204,214, 0, 0,128, 1,
+ 0, 0, 2, 0, 0, 0, 0, 0, 62,204,205, 47,180,128, 0, 0,191, 76,204,206, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0,
+ 63, 76,205, 0, 0, 0, 0, 0,191, 76,204,208, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0,182, 70, 0, 0, 52,128, 0, 0,
+191, 76,204,214, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0,190,204,205, 55, 0, 0, 0, 0,191, 76,204,212, 0, 0,128, 1,
+ 0, 0, 2, 0, 0, 0, 0, 0,182, 62, 0, 0, 52,128, 0, 0, 63, 76,204,206, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0,
+190,204,205, 47, 0, 0, 0, 0, 63, 76,204,206, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0,191, 76,205, 4, 0, 0, 0, 0,
+ 63, 76,204,210, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0,182, 70, 0, 0, 52,128, 0, 0, 62,204,204,197, 0, 0,128, 1,
+ 0, 0, 2, 0, 0, 0, 0, 0,190,204,205, 55, 0, 0, 0, 0, 62,204,204,205, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0,
+191, 76,205, 4, 0, 0, 0, 0, 62,204,204,213, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0,182, 70, 0, 0, 52,128, 0, 0,
+180,144, 0, 0, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0,190,204,205, 55, 0, 0, 0, 0,179, 0, 0, 0, 0, 0,128, 1,
+ 0, 0, 2, 0, 0, 0, 0, 0,191, 76,205, 4, 0, 0, 0, 0, 52, 96, 0, 0, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0,
+182, 70, 0, 0, 52,128, 0, 0,190,204,204,224, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0,190,204,205, 55, 0, 0, 0, 0,
+190,204,204,216, 0, 0,128, 1, 0, 0, 2, 0, 0, 0, 0, 0,191, 76,205, 4, 0, 0, 0, 0,190,204,204,208, 0, 0,128, 1,
+ 0, 0, 2, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,134, 16, 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 65,135,112, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 1,128, 13, 65,135,112, 0, 0, 0, 55, 0, 0, 0, 32, 0, 0, 0, 1,
+ 0, 0, 0, 8, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 34,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 34, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 34, 0, 0, 0, 2, 0, 0, 0, 3,
+ 0, 0, 0, 34, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 34, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 34, 0, 0, 0, 4,
+ 0, 0, 0, 6, 0, 0, 0, 34, 0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 34, 0, 0, 0, 9, 0, 0, 0, 10, 0, 0, 0, 34,
+ 0, 0, 0, 12, 0, 0, 0, 13, 0, 0, 0, 34, 0, 0, 0, 13, 0, 0, 0, 16, 0, 0, 0, 34, 0, 0, 0, 15, 0, 0, 0, 16,
+ 0, 0, 0, 34, 0, 0, 0, 12, 0, 0, 0, 15, 0, 0, 0, 34, 0, 0, 0, 14, 0, 0, 0, 15, 0, 0, 0, 34, 0, 0, 0, 11,
+ 0, 0, 0, 14, 0, 0, 0, 34, 0, 0, 0, 18, 0, 0, 0, 19, 0, 0, 0, 34, 0, 0, 0, 15, 0, 0, 0, 18, 0, 0, 0, 34,
+ 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 34, 0, 0, 0, 14, 0, 0, 0, 17, 0, 0, 0, 34, 0, 0, 0, 19, 0, 0, 0, 22,
+ 0, 0, 0, 34, 0, 0, 0, 21, 0, 0, 0, 22, 0, 0, 0, 34, 0, 0, 0, 18, 0, 0, 0, 21, 0, 0, 0, 34, 0, 0, 0, 20,
+ 0, 0, 0, 21, 0, 0, 0, 34, 0, 0, 0, 17, 0, 0, 0, 20, 0, 0, 0, 34, 0, 0, 0, 10, 0, 0, 0, 21, 0, 0, 0, 34,
+ 0, 0, 0, 9, 0, 0, 0, 20, 0, 0, 0, 34, 0, 0, 0, 6, 0, 0, 0, 11, 0, 0, 0, 34, 0, 0, 0, 4, 0, 0, 0, 14,
+ 0, 0, 0, 34, 0, 0, 0, 2, 0, 0, 0, 17, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 34, 68, 65, 84, 65,
+ 0, 0, 1, 44, 13, 65,137, 32, 0, 0, 1, 35, 0, 0, 0, 5, 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, 13, 65,138,128, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 85, 86, 84,101,120, 0, 0, 0, 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, 65,139, 80, 0, 0, 0, 6, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 67,111,108, 0, 0, 0, 0, 0, 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, 65,140,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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,
+ 0, 0, 0,160, 13, 65,138,128, 0, 0, 0, 54, 0, 0, 0, 8, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 8,
+ 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 11, 0, 0, 0, 14, 0, 0, 0, 4, 0, 0, 0, 0,
+ 0, 0, 0, 12, 0, 0, 0, 13, 0, 0, 0, 16, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 15, 0, 0, 0, 18,
+ 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 19, 0, 0, 0, 22, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 20,
+ 0, 0, 0, 21, 0, 0, 0, 10, 0, 0, 0, 9, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 96, 13, 65,139, 80, 0, 0, 0, 65,
+ 0, 0, 0, 8, 63, 55, 23,152, 63,125,226,162, 63, 17, 5, 30, 63,125,226,162, 63, 17, 5, 30, 63,125,226,162, 63, 55, 23,152,
+ 63,125,226,162, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 62,213,228,252, 63,125,226,162, 63, 17, 5, 30, 63,125,226,162,
+ 63, 17, 5, 30, 63,125,226,162, 62,213,228,252, 63,125,226,162, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 63, 55, 23,152,
+ 63,125,226,162, 63, 17, 5, 30, 63,125,226,162, 63, 17, 5, 30, 63,125,226,162, 63, 55, 23,152, 63,125,226,162, 0, 0, 0, 0,
+ 61, 0, 0, 1, 0, 0, 0, 0, 63, 17, 5, 34, 63,125,226,162, 62,213,229, 0, 63,125,226,162, 62,213,228,252, 63,125,226,162,
+ 63, 17, 5, 30, 63,125,226,162, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 62,137,192, 18, 63,125,226,162, 61,246,108,144,
+ 63,125,226,162, 61,246,108,144, 63,125,226,162, 62,137,192, 12, 63,125,226,162, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0,
+ 62,213,228,252, 63,125,226,162, 62,137,192, 12, 63,125,226,162, 62,137,192, 12, 63,125,226,162, 62,213,228,252, 63,125,226,162,
+ 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 62,137,192, 12, 63,125,226,162, 61,246,108,144, 63,125,226,162, 61,246,108,144,
+ 63,125,226,162, 62,137,192, 12, 63,125,226,162, 0, 0, 0, 0, 61, 0, 0, 1, 0, 0, 0, 0, 62,213,228,252, 63,125,226,162,
+ 62,137,192, 12, 63,125,226,162, 62,137,192, 12, 63,125,226,162, 62,213,228,252, 63,125,226,162, 0, 0, 0, 0, 61, 0, 0, 1,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0,128, 13, 65,140,224, 0, 0, 0, 59, 0, 0, 0, 32,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 77, 69, 0, 0, 1, 24,
+ 13, 65,141,144, 0, 0, 0, 52, 0, 0, 0, 1, 13, 65,148,176, 13, 65,131, 64, 0, 0, 0, 0, 0, 0, 0, 0, 77, 69, 80,108,
+ 97,110,101, 46, 48, 48, 52, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,142,208, 13, 65,148, 16, 13, 65,148, 80,
+ 0, 0, 0, 0, 13, 65,144, 96, 13, 65,146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 13, 65,143, 0, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,144,240, 0, 0, 0, 1,
+ 0, 0, 0, 5, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,146,176, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 64,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+179,128, 0, 0, 52, 64, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 2, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 65,142,208, 0, 0, 0, 0, 0, 0, 0, 1, 7,160, 8, 32, 68, 65, 84, 65,
+ 0, 0, 1, 44, 13, 65,143, 0, 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 65,144, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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,
+ 0, 0, 0, 96, 13, 65,144, 96, 0, 0, 0, 58, 0, 0, 0, 4, 63,128, 0, 0, 63,127,255,255, 0, 0, 0, 0, 0, 0, 0, 0,
+127,255, 3,255, 0, 0, 0, 0, 63,128, 0, 0,191,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,255, 3,255, 0, 0, 0, 0,
+191,128, 0, 1,191,127,255,253, 0, 0, 0, 0, 0, 0, 0, 0,127,255, 3,255, 0, 0, 0, 0,191,127,255,250, 63,128, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 0,127,255, 3,255, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,144,240, 0, 0, 1, 35,
+ 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 65,146, 80,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 48, 13, 65,146, 80, 0, 0, 0, 55,
+ 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 35, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 35, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 35, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,146,176,
+ 0, 0, 1, 35, 0, 0, 0, 5, 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, 86, 84,101,120, 0, 0, 0, 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, 65,148, 16, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 86, 84,101,
+120, 0, 0, 0, 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, 65,148, 80,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 20, 13, 65,148, 16,
+ 0, 0, 0, 54, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 68, 65, 84, 65,
+ 0, 0, 0, 44, 13, 65,148, 80, 0, 0, 0, 65, 0, 0, 0, 1, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 60, 0, 0, 1, 0, 0, 0, 0, 0, 0, 77, 69,
+ 0, 0, 1, 24, 13, 65,148,176, 0, 0, 0, 52, 0, 0, 0, 1, 13, 65,154, 64, 13, 65,141,144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 77, 69,112,114,101,118,105,101,119, 0, 0, 0, 0,112,104,101,114,101, 0, 0, 0, 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, 13, 65,149,240, 12,118,208, 32,
+ 12,119, 64, 32, 0, 0, 0, 0, 12,118, 48, 32, 12,118,112, 32, 0, 0, 0, 0, 12,120, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 65,150, 32, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,151,128,
+ 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,152,224, 0, 0, 0, 3, 0, 0, 0, 5,
+ 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,130, 0, 0, 7,128, 0, 0, 5, 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, 64,186,224,117, 64,187, 13, 91, 64,186,240,160, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 65,149,240, 0, 0, 0, 0, 0, 0, 0, 1, 7,160, 8, 32,
+ 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,150, 32, 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,118, 48, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 60, 48, 12,118, 48, 32, 0, 0, 0, 58, 0, 0, 2,130,191,141,136, 28, 62,244,243, 12,192,183, 86,198,
+231,212, 10,117,130,191, 3,255, 0, 0, 0, 0,192,131,102,240, 64,119,183, 30,191,199,169,109,166, 58, 84,158,221,230, 3,255,
+ 0, 0, 0, 0, 63,239,108,119, 64,156, 85,213,192, 40, 58,188, 40,228,106,207,198,137, 3,255, 0, 0, 0, 0, 64,146,135, 95,
+191, 14, 54, 63,192,102,194,241,100, 27,243,219,177, 45, 3,255, 0, 0, 0, 0, 62,141, 84,239,192,157,220, 16,192, 73, 2, 14,
+ 6, 8,148, 39,187, 86, 3,255, 0, 0, 0, 0,192,162,239,132,192, 12,165,206,191,240, 45,150,144,175,207,245,214,251, 3,255,
+ 0, 0, 0, 0,190,141, 84,239, 64,157,220, 16, 64, 73, 2, 14,249,248,107,217, 68,170, 3,255, 0, 0, 0, 0, 64,162,239,132,
+ 64, 12,165,206, 63,240, 45,150,111, 81, 48, 11, 41, 5, 3,255, 0, 0, 0, 0, 64,131,102,240,192,119,183, 30, 63,199,169,109,
+ 89,198,171, 98, 34, 26, 3,255, 0, 0, 0, 0,191,239,108,119,192,156, 85,213, 64, 40, 58,188,215, 28,149, 49, 57,119, 3,255,
+ 0, 0, 0, 0,192,146,135, 95, 63, 14, 54, 63, 64,102,194,241,155,229, 12, 37, 78,211, 3,255, 0, 0, 0, 0, 63,141,136, 28,
+190,244,243, 12, 64,183, 86,198, 24, 44,245,139,125, 65, 3,255, 0, 0, 0, 0,192, 68, 17,114, 64, 35,153,226,192,137, 26,154,
+189, 6, 55,226,162, 85, 3,255, 0, 0, 0, 0, 62,230, 40,155, 64, 73,199,239,192,157, 52,176, 9,211, 68,237,148,153, 3,255,
+ 0, 0, 0, 0,191,168, 55,124, 64,164,177,224,192, 29,144, 58,227, 69,112,132,202, 46, 3,255, 0, 0, 0, 0,192,105, 35, 94,
+191,129, 88,230,192,143, 14,195,176, 93,233,233,158, 68, 3,255, 0, 0, 0, 0,192,173, 2, 37, 63,123,187,137,192, 1, 68, 56,
+137,206, 21,127,211,216, 3,255, 0, 0, 0, 0, 64, 2,168,234,189, 57,158,231,192,175,149, 65, 44,162,255, 3,136, 11, 3,255,
+ 0, 0, 0, 0, 64,114,159, 19, 64, 34,226,254,192,106,133,196, 82,225, 55,164,175,228, 3,255, 0, 0, 0, 0,190,249,176,105,
+192, 39,148, 21,192,166,214,217,245, 87,198,194,142, 5, 3,255, 0, 0, 0, 0, 64, 54,163,227,192, 78,121, 86,192,125,202, 22,
+ 62, 99,185,120,169, 79, 3,255, 0, 0, 0, 0,192, 53, 40,241,192,134, 31,200,192, 60,188,229,194, 30,164, 94,191,136, 3,255,
+ 0, 0, 0, 0,192,181,230, 96,191,119, 24, 33, 63,130, 26,174,131,186,234,231, 22, 56, 3,255, 0, 0, 0, 0,192,163, 93,103,
+ 64, 38,128,136, 63,153,235, 83,144,100, 56,224, 26, 74, 3,255, 0, 0, 0, 0,192, 36,219,238, 64,165,151,132, 63,109,226,165,
+199,176,113, 33, 20, 80, 3,255, 0, 0, 0, 0, 63,111,237, 24, 64,184,174,118, 62,154, 34,212, 20,125,126, 44, 6,148, 3,255,
+ 0, 0, 0, 0, 64,130,244,163, 64,133, 58,157,190,226, 95,125, 89,119, 91, 5,246, 86, 3,255, 0, 0, 0, 0, 64,181,230, 96,
+ 63,119, 24, 33,191,130, 26,174,124, 70, 21, 25,233,200, 3,255, 0, 0, 0, 0, 64,163, 93,103,192, 38,128,136,191,153,235, 83,
+111,156,199, 32,229,182, 3,255, 0, 0, 0, 0, 64, 36,219,238,192,165,151,132,191,109,226,165, 56, 80,142,223,235,176, 3,255,
+ 0, 0, 0, 0,191,111,237, 24,192,184,174,118,190,154, 34,212,235,131,129,212,249,108, 3,255, 0, 0, 0, 0,192,130,244,163,
+192,133, 58,157, 62,226, 95,125,166,137,164,251, 9,170, 3,255, 0, 0, 0, 0,192, 54,163,227, 64, 78,121, 86, 64,125,202, 22,
+193,157, 70,136, 86,177, 3,255, 0, 0, 0, 0, 64, 53, 40,241, 64,134, 31,200, 64, 60,188,229, 61,226, 91,162, 64,120, 3,255,
+ 0, 0, 0, 0, 64,173, 2, 37,191,123,187,137, 64, 1, 68, 56,118, 50,234,129, 44, 40, 3,255, 0, 0, 0, 0, 63,168, 55,124,
+192,164,177,224, 64, 29,144, 58, 28,187,143,124, 53,210, 3,255, 0, 0, 0, 0,192,114,159, 19,192, 34,226,254, 64,106,133,196,
+173, 31,200, 92, 80, 28, 3,255, 0, 0, 0, 0,192, 2,168,234, 61, 57,158,231, 64,175,149, 65,211, 94, 0,253,119,245, 3,255,
+ 0, 0, 0, 0, 62,249,176,105, 64, 39,148, 21, 64,166,214,217, 10,169, 57, 62,113,251, 3,255, 0, 0, 0, 0, 64,105, 35, 94,
+ 63,129, 88,230, 64,143, 14,195, 79,163, 22, 23, 97,188, 3,255, 0, 0, 0, 0, 64, 68, 17,114,192, 35,153,226, 64,137, 26,154,
+ 66,250,200, 30, 93,171, 3,255, 0, 0, 0, 0,190,230, 40,155,192, 73,199,239, 64,157, 52,176,246, 45,187, 19,107,103, 3,255,
+ 0, 0, 0, 0,192, 10,178, 37, 63,201,231,138,192,166,143,149,209,129, 33,140,141,145, 3,255, 0, 0, 0, 0,192,110,132, 3,
+ 64, 85,203,243,192, 66,107,151,174, 16, 73,158,190,209, 3,255, 0, 0, 0, 0,190,174,161,116, 63,241,152, 81,192,177, 2,110,
+247,217, 40, 15,134,182, 3,255, 0, 0, 0, 0, 63,154, 91,138, 64,133,179,218,192,122,222,209, 27, 0, 92, 30,171, 86, 3,255,
+ 0, 0, 0, 0,192, 52, 82, 7, 64,149,252, 82,192, 5,202, 64,193, 39,101,227,210,181, 3,255, 0, 0, 0, 0, 62,148, 12,179,
+ 64,166,221,251,192, 41, 87,188, 7,192,113,224,198, 21, 3,255, 0, 0, 0, 0,192, 29,246,216,190,141,156, 17,192,169,167,209,
+203, 47,250,160,139,137, 3,255, 0, 0, 0, 0,192,145, 72, 99,191,213,114, 79,192, 83, 35,183,156, 26,219, 3,185, 12, 3,255,
+ 0, 0, 0, 0,192,158, 58,115, 64, 33,120,129,191,238, 41,198,148,126, 56,116,215,137, 3,255, 0, 0, 0, 0,192,174,158,118,
+191, 33,148,103,192, 1,156,140,136,218,240,198,211,203, 3,255, 0, 0, 0, 0, 62,249, 14, 55, 62,102,133, 95,192,186,143,210,
+ 9, 56, 5, 40,128,113, 3,255, 0, 0, 0, 0, 64, 92, 61,220,190,159,230, 56,192,151, 61, 6, 76, 94,248,242,153,135, 3,255,
+ 0, 0, 0, 0, 64, 60, 86, 7, 64,119, 48, 60,192, 81, 88, 93, 63,119, 85,124,184,246, 3,255, 0, 0, 0, 0, 64,139, 55,252,
+ 63,132, 95, 62,192,113,216,225, 95,118, 21, 54,173,107, 3,255, 0, 0, 0, 0,191, 84, 6, 18,191,142, 96,251,192,182, 4, 76,
+237,158,233, 20,131,109, 3,255, 0, 0, 0, 0,189,225, 74,109,192,123, 54, 51,192,138,246, 34,253,241,169, 39,162, 1, 3,255,
+ 0, 0, 0, 0, 64,119, 66,153,191,251,154,127,192,123,220,161, 85, 59,214, 59,170, 34, 3,255, 0, 0, 0, 0, 63,208, 59,201,
+192,135,182,241,192,108,101,212, 34,103,162,133,175,160, 3,255, 0, 0, 0, 0,191,169,246,161,192,151,196,235,192, 74,149,170,
+228, 95,151,253,186,184, 3,255, 0, 0, 0, 0,192,131,198, 33,192, 84,137,218,192, 32,134, 37,164,247,184, 77,201,167, 3,255,
+ 0, 0, 0, 0,192,179, 61,176,191,210,110,138,190,228,220, 24,133,210,219,130,244,238, 3,255, 0, 0, 0, 0,192,170,182, 73,
+190, 90, 16,136, 64, 25,194, 90,139,224,252, 8, 53,174, 3,255, 0, 0, 0, 0,192,153, 55, 75, 64, 87, 78, 4,190, 62, 54, 12,
+151,200, 74, 29,250,179, 3,255, 0, 0, 0, 0,192,161, 19,235, 63,210, 12,207, 64, 31,242,210,146, 50, 34,244, 55,182, 3,255,
+ 0, 0, 0, 0,192, 94, 75, 60, 64,150,115,189,190,167,211,186,179, 98,102, 49,247,183, 3,255, 0, 0, 0, 0,191,189,191,186,
+ 64,168, 32, 63, 64, 7,100,213,224,161,114,191, 47, 61, 3,255, 0, 0, 0, 0, 63,186,205,242, 64,177, 65,141,191,154,219,127,
+ 32, 82,120,177,228, 61, 3,255, 0, 0, 0, 0, 62,175,245, 99, 64,178, 12, 97, 63,228,253,255, 6,247,121, 65, 40, 98, 3,255,
+ 0, 0, 0, 0, 64, 70, 92,226, 64,150,131, 8,191,204, 77,182, 66,193,103, 37,220, 32, 3,255, 0, 0, 0, 0, 64,152,194,200,
+ 64, 83,155,180, 63, 62,217,154,104,207, 71,101, 17, 87, 3,255, 0, 0, 0, 0, 64,170,182, 73, 62, 90, 16,136,192, 25,194, 90,
+116, 32, 3,248,202, 82, 3,255, 0, 0, 0, 0, 64,179, 61,176, 63,210,110,138, 62,228,220, 24,122, 46, 36,126, 11, 18, 3,255,
+ 0, 0, 0, 0, 64,161, 19,235,191,210, 12,207,192, 31,242,210,109,206,221, 12,200, 74, 3,255, 0, 0, 0, 0, 64,153, 55, 75,
+192, 87, 78, 4, 62, 62, 54, 12,104, 56,181,227, 5, 77, 3,255, 0, 0, 0, 0, 63,189,191,186,192,168, 32, 63,192, 7,100,213,
+ 31, 95,141, 65,208,195, 3,255, 0, 0, 0, 0, 64, 94, 75, 60,192,150,115,189, 62,167,211,186, 76,158,153,207, 8, 73, 3,255,
+ 0, 0, 0, 0,190,175,245, 99,192,178, 12, 97,191,228,253,255,249, 9,134,191,215,158, 3,255, 0, 0, 0, 0,191,186,205,242,
+192,177, 65,141, 63,154,219,127,223,174,135, 79, 27,195, 3,255, 0, 0, 0, 0,192,152,194,200,192, 83,155,180,191, 62,217,154,
+151, 49,184,155,238,169, 3,255, 0, 0, 0, 0,192, 70, 92,226,192,150,131, 8, 63,204, 77,182,189, 63,152,219, 35,224, 3,255,
+ 0, 0, 0, 0,191,208, 59,201, 64,135,182,241, 64,108,101,212,221,153, 93,123, 80, 96, 3,255, 0, 0, 0, 0,192,119, 66,153,
+ 63,251,154,127, 64,123,220,161,170,197, 41,197, 85,222, 3,255, 0, 0, 0, 0, 63,169,246,161, 64,151,196,235, 64, 74,149,170,
+ 27,161,104, 3, 69, 72, 3,255, 0, 0, 0, 0, 64,131,198, 33, 64, 84,137,218, 64, 32,134, 37, 91, 9, 71,179, 54, 89, 3,255,
+ 0, 0, 0, 0, 64,174,158,118, 63, 33,148,103, 64, 1,156,140,119, 38, 15, 58, 44, 53, 3,255, 0, 0, 0, 0, 64,158, 58,115,
+192, 33,120,129, 63,238, 41,198,107,130,199,140, 40,119, 3,255, 0, 0, 0, 0, 64, 52, 82, 7,192,149,252, 82, 64, 5,202, 64,
+ 62,217,154, 29, 45, 75, 3,255, 0, 0, 0, 0,190,148, 12,179,192,166,221,251, 64, 41, 87,188,248, 64,142, 32, 57,235, 3,255,
+ 0, 0, 0, 0,192, 60, 86, 7,192,119, 48, 60, 64, 81, 88, 93,192,137,170,132, 71, 10, 3,255, 0, 0, 0, 0,192,139, 55,252,
+191,132, 95, 62, 64,113,216,225,160,138,234,202, 82,149, 3,255, 0, 0, 0, 0,192, 92, 61,220, 62,159,230, 56, 64,151, 61, 6,
+179,162, 7, 14,102,121, 3,255, 0, 0, 0, 0,190,249, 14, 55,190,102,133, 95, 64,186,143,210,246,200,250,216,127,143, 3,255,
+ 0, 0, 0, 0, 61,225, 74,109, 64,123, 54, 51, 64,138,246, 34, 2, 15, 86,217, 93,255, 3,255, 0, 0, 0, 0, 63, 84, 6, 18,
+ 63,142, 96,251, 64,182, 4, 76, 18, 98, 22,236,124,147, 3,255, 0, 0, 0, 0, 64,145, 72, 99, 63,213,114, 79, 64, 83, 35,183,
+ 99,230, 36,253, 70,244, 3,255, 0, 0, 0, 0, 64, 29,246,216, 62,141,156, 17, 64,169,167,209, 52,209, 5, 96,116,119, 3,255,
+ 0, 0, 0, 0, 64,110,132, 3,192, 85,203,243, 64, 66,107,151, 81,240,182, 98, 65, 47, 3,255, 0, 0, 0, 0, 64, 10,178, 37,
+191,201,231,138, 64,166,143,149, 46,127,222,116,114,111, 3,255, 0, 0, 0, 0,191,154, 91,138,192,133,179,218, 64,122,222,209,
+229, 0,163,226, 84,170, 3,255, 0, 0, 0, 0, 62,174,161,116,191,241,152, 81, 64,177, 2,110, 8, 39,215,241,121, 74, 3,255,
+ 0, 0, 0, 0,192, 19, 76, 36, 64,129,151, 25,192, 98,254,212,206,231, 88, 97,177,131, 3,255, 0, 0, 0, 0,191,175,232, 93,
+ 64, 64, 23,177,192,154,186, 69,225,227, 66,235,151, 34, 3,255, 0, 0, 0, 0,190,232,190,208, 64,139,160, 93,192,120, 33,191,
+244,183, 94,205,170,192, 3,255, 0, 0, 0, 0,192,142,126,210, 63,238, 49, 43,192, 84, 30,112,158,187, 39, 95,182,183, 3,255,
+ 0, 0, 0, 0,192, 97,165,138, 63, 80, 9, 92,192,147, 74, 20,177,183, 17,233,156, 86, 3,255, 0, 0, 0, 0,192,152, 61, 98,
+188,106, 63, 87,192, 90, 97, 6,152,127, 0,251,180,183, 3,255, 0, 0, 0, 0, 64, 14,173,200, 64, 63,183,155,192,144, 75,192,
+ 48,206, 64, 45,156,152, 3,255, 0, 0, 0, 0, 63,167,162, 95, 63,209, 29,144,192,174,245, 25, 29,250, 36, 75,136,250, 3,255,
+ 0, 0, 0, 0, 64, 68, 62,211, 63,168, 56, 51,192,153,245, 13, 65,241, 29,192,150,106, 3,255, 0, 0, 0, 0, 64, 36,182, 33,
+191,220, 38, 34,192,159, 5,150, 54,233,217,211,146,223, 3,255, 0, 0, 0, 0, 63, 81, 34, 16,191,179, 64,129,192,180, 5,162,
+ 18,242,224, 93,133,111, 3,255, 0, 0, 0, 0, 63,159, 56,212,192, 68,166,172,192,154,108,212, 27,176,190, 32,149,208, 3,255,
+ 0, 0, 0, 0,191,223, 76,204,192,101, 32,170,192,137, 83, 65,216,199,178,195,161,198, 3,255, 0, 0, 0, 0,192, 10,249,249,
+191,244, 52, 62,192,162,236, 25,208, 9,213, 0,145,102, 3,255, 0, 0, 0, 0,192, 89,207, 42,192, 47, 6,251,192,121,165, 27,
+182,209,196, 18,169,198, 3,255, 0, 0, 0, 0,192,176,215,137, 63,241, 62, 25,190,219,254,179,134,179, 39,232,247, 78, 3,255,
+ 0, 0, 0, 0,192,186,150, 28, 60, 28, 16,150,191, 7, 9,191,128,118, 1,131,245, 77, 3,255, 0, 0, 0, 0,192,181,132, 34,
+ 63, 92, 60, 99, 63,149, 81,217,131,181, 18,238, 23,252, 3,255, 0, 0, 0, 0,190, 74,242,175, 64,183,173,164,191,145,105,227,
+250,117,125,160,232, 31, 3,255, 0, 0, 0, 0,192, 2,227,219, 64,173,164, 96,191, 78, 71,200,212,164,119, 52,238,226, 3,255,
+ 0, 0, 0, 0,191, 92,140,181, 64,184, 38, 75, 63, 37,148,176,236,224,125,237, 12,159, 3,255, 0, 0, 0, 0, 64,159,104, 75,
+ 63,236, 56,212,192, 29,126,240,108,211, 41,166,203, 9, 3,255, 0, 0, 0, 0, 64,132,159,215, 64, 97,184, 84,192, 10, 44, 30,
+ 91,176, 76, 19,209, 56, 3,255, 0, 0, 0, 0, 64,164,122, 95, 64, 44,143,199,191, 68, 78, 53,112, 17, 59, 17,237,185, 3,255,
+ 0, 0, 0, 0, 64, 54,176,255,192,141, 84,243,192, 36,176,237, 63,192,160, 9,200, 63, 3,255, 0, 0, 0, 0, 64,133,229, 93,
+192, 68, 21,217,192, 45,226,157, 90,249,187,187,197, 78, 3,255, 0, 0, 0, 0, 64,129, 56,203,192,130,211, 21,191,143,115,187,
+ 87,252,166,194,229,252, 3,255, 0, 0, 0, 0,192,104,239,189,192,140,142, 82,191,168,178,178,177,134,158,245,227,155, 3,255,
+ 0, 0, 0, 0,191,253,141, 50,192,167,155, 52,191,218,181,170,211,125,141,166,219,155, 3,255, 0, 0, 0, 0,192, 41, 58,164,
+192,167, 34,172, 61,151,232,206,197,232,141,243, 0, 26, 3,255, 0, 0, 0, 0,192,133,229, 93, 64, 68, 21,217, 64, 45,226,157,
+165, 7, 68, 69, 58,178, 3,255, 0, 0, 0, 0,192,129, 56,203, 64,130,211, 21, 63,143,115,187,168, 4, 89, 62, 26, 4, 3,255,
+ 0, 0, 0, 0,192, 54,176,255, 64,141, 84,243, 64, 36,176,237,192, 64, 95,247, 55,193, 3,255, 0, 0, 0, 0, 63,253,141, 50,
+ 64,167,155, 52, 63,218,181,170, 44,131,114, 90, 36,101, 3,255, 0, 0, 0, 0, 64, 41, 58,164, 64,167, 34,172,189,151,232,206,
+ 58, 24,114, 13,255,230, 3,255, 0, 0, 0, 0, 64,104,239,189, 64,140,142, 82, 63,168,178,178, 78,122, 97, 11, 28,101, 3,255,
+ 0, 0, 0, 0, 64,186,150, 28,188, 28, 16,150, 63, 7, 9,191,127,138,254,125, 10,179, 3,255, 0, 0, 0, 0, 64,181,132, 34,
+191, 92, 60, 99,191,149, 81,217,124, 75,237, 18,232, 4, 3,255, 0, 0, 0, 0, 64,176,215,137,191,241, 62, 25, 62,219,254,179,
+121, 77,216, 24, 8,178, 3,255, 0, 0, 0, 0, 64, 2,227,219,192,173,164, 96, 63, 78, 71,200, 43, 92,136,204, 17, 30, 3,255,
+ 0, 0, 0, 0, 63, 92,140,181,192,184, 38, 75,191, 37,148,176, 19, 32,130, 19,243, 97, 3,255, 0, 0, 0, 0, 62, 74,242,175,
+192,183,173,164, 63,145,105,227, 5,139,130, 96, 23,225, 3,255, 0, 0, 0, 0,192,132,159,215,192, 97,184, 84, 64, 10, 44, 30,
+164, 80,179,237, 46,200, 3,255, 0, 0, 0, 0,192,164,122, 95,192, 44,143,199, 63, 68, 78, 53,143,239,196,239, 18, 71, 3,255,
+ 0, 0, 0, 0,192,159,104, 75,191,236, 56,212, 64, 29,126,240,147, 45,214, 90, 52,247, 3,255, 0, 0, 0, 0,191,159, 56,212,
+ 64, 68,166,172, 64,154,108,212,228, 80, 65,224,106, 48, 3,255, 0, 0, 0, 0,192, 36,182, 33, 63,220, 38, 34, 64,159, 5,150,
+201, 23, 38, 45,109, 33, 3,255, 0, 0, 0, 0,191, 81, 34, 16, 63,179, 64,129, 64,180, 5,162,237, 14, 31,163,122,145, 3,255,
+ 0, 0, 0, 0, 64, 89,207, 42, 64, 47, 6,251, 64,121,165, 27, 73, 47, 59,238, 86, 58, 3,255, 0, 0, 0, 0, 63,223, 76,208,
+ 64,101, 32,170, 64,137, 83, 65, 39, 57, 77, 61, 94, 58, 3,255, 0, 0, 0, 0, 64, 10,249,249, 63,244, 52, 62, 64,162,236, 25,
+ 47,247, 43, 0,110,154, 3,255, 0, 0, 0, 0, 64,142,126,210,191,238, 49, 43, 64, 84, 30,112, 97, 69,216,161, 73, 73, 3,255,
+ 0, 0, 0, 0, 64,152, 61, 98, 60,106, 63, 87, 64, 90, 97, 6,103,129,255, 5, 75, 73, 3,255, 0, 0, 0, 0, 64, 97,165,138,
+191, 80, 9, 92, 64,147, 74, 20, 78, 73,238, 23, 99,170, 3,255, 0, 0, 0, 0, 62,232,190,208,192,139,160, 93, 64,120, 33,191,
+ 11, 73,161, 51, 85, 64, 3,255, 0, 0, 0, 0, 64, 19, 76, 36,192,129,151, 25, 64, 98,254,212, 49, 25,167,159, 78,125, 3,255,
+ 0, 0, 0, 0, 63,175,232, 93,192, 64, 23,177, 64,154,186, 69, 30, 29,189, 21,104,222, 3,255, 0, 0, 0, 0,192, 68, 62,211,
+191,168, 56, 51, 64,153,245, 13,190, 15,226, 64,105,150, 3,255, 0, 0, 0, 0,192, 14,173,200,192, 63,183,155, 64,144, 75,192,
+207, 50,191,211, 99,104, 3,255, 0, 0, 0, 0,191,167,162, 95,191,209, 29,144, 64,174,245, 25,226, 6,219,181,119, 6, 3,255,
+ 0, 0, 0, 0,191,211,156,158, 63,132,228,185,192,176,207,190,220,164, 21,231,134,244, 3,255, 0, 0, 0, 0,192, 41, 76, 0,
+ 64, 5,199,190,192,153,157, 83,198,146, 45, 75,150,246, 3,255, 0, 0, 0, 0,192,125, 83,204, 64,105, 55,169,192, 20,162,244,
+169, 72, 79,246,206, 82, 3,255, 0, 0, 0, 0,192, 91,215,178, 64, 62,235,222,192,108,254,190,180,215, 65, 87,175,155, 3,255,
+ 0, 0, 0, 0,191, 59, 63,242, 63,152,237,210,192,182, 21,251,239,125, 25, 26,131,149, 3,255, 0, 0, 0, 0, 61, 94,230, 86,
+ 64, 35, 30,198,192,169, 15,233, 0,238, 55, 52,140,135, 3,255, 0, 0, 0, 0, 63,199, 4,220, 64,146,145, 7,192, 83,186,104,
+ 34,109,100,137,184,168, 3,255, 0, 0, 0, 0, 63, 86,120, 9, 64,109, 91,149,192,142,242, 79, 18,133, 81, 64,158,218, 3,255,
+ 0, 0, 0, 0,192, 95,243,103, 64,138, 91,221,191,236, 15,186,178,170, 93,219,216, 25, 3,255, 0, 0, 0, 0,192, 5,206, 46,
+ 64,159, 41,121,192, 19, 91,154,209,230,108, 96,205,226, 3,255, 0, 0, 0, 0, 63,139,200,169, 64,163, 78,198,192, 42,146,201,
+ 24,247,111, 59,197,206, 3,255, 0, 0, 0, 0,191, 4,128,187, 64,167,181,206,192, 37, 92, 74,245, 57,114, 96,199,145, 3,255,
+ 0, 0, 0, 0,191,231, 16,151, 61,209,166,160,192,178, 95,167,217,136, 2,196,133,245, 3,255, 0, 0, 0, 0,192, 69,200,163,
+191, 38,143,178,192,158, 48,148,188,243,242, 11,147,223, 3,255, 0, 0, 0, 0,192,155,192, 43,191,250, 6,151,192, 39, 82,170,
+149, 79,212,247,199,231, 3,255, 0, 0, 0, 0,192,132,118,233,191,173,111,217,192,123,122, 67,165,100,226, 58,170,165, 3,255,
+ 0, 0, 0, 0,192,146, 85,238, 64, 78,205,178,191,221, 54, 70,156,183, 71,134,218,120, 3,255, 0, 0, 0, 0,192,167,137, 76,
+ 63,227, 31,111,191,251, 57,158,141,234, 39, 54,213, 59, 3,255, 0, 0, 0, 0,192,170,143, 39,191,183, 15,167,191,252, 85,251,
+139,217,223,169,213, 13, 3,255, 0, 0, 0, 0,192,175,214, 8, 62, 53,124,177,192, 2,241,206,136, 23, 3, 89,211, 92, 3,255,
+ 0, 0, 0, 0,190,160,160, 77, 62,182, 20, 9,192,186,232,108,248, 8, 7,241,128,128, 3,255, 0, 0, 0, 0, 63,163,144, 33,
+ 61,186,144,151,192,183, 47, 50, 27, 97, 2, 19,130,252, 3,255, 0, 0, 0, 0, 64,129,179,222,190,224,147,234,192,134,180, 38,
+ 89, 83,246, 64,164,218, 3,255, 0, 0, 0, 0, 64, 49,138,114,190, 57, 97,246,192,165, 76, 57, 60,250,251,247,143,138, 3,255,
+ 0, 0, 0, 0, 64, 27,158,249, 64,141,118,197,192, 62,196, 58, 52, 90, 97, 70,191, 90, 3,255, 0, 0, 0, 0, 64, 89,244, 98,
+ 64, 79,120, 8,192, 96,128, 65, 74, 8, 71, 39,179,151, 3,255, 0, 0, 0, 0, 64,144,100, 13, 62,118,214,200,192,110,205, 64,
+ 98,182, 4, 37,174,161, 3,255, 0, 0, 0, 0, 64,131,202, 42, 63,231,161, 60,192,112,245,142, 90, 10, 38,255,173,209, 3,255,
+ 0, 0, 0, 0,191,122, 51,149,190,163,151, 52,192,184,157, 15,234,118,250, 36,129,248, 3,255, 0, 0, 0, 0,191, 42,113, 5,
+191,241,112, 31,192,176,119, 15,241, 93,215, 84,135,135, 3,255, 0, 0, 0, 0, 61,172, 55, 60,192,143, 64, 22,192,113,246,164,
+ 2, 27,157,132,174, 71, 3,255, 0, 0, 0, 0,190,154,173,167,192, 83,224,111,192,154,169,198,249,136,183, 89,150,211, 3,255,
+ 0, 0, 0, 0, 64,136,133,151,191,162,249, 9,192,115,219,106, 93,175,229, 47,173, 3, 3,255, 0, 0, 0, 0, 64, 89,124,110,
+192, 40, 6,135,192,127,195,223, 74,120,199, 31,168,208, 3,255, 0, 0, 0, 0, 63,117,248,244,192,148, 90,109,192, 93, 0,123,
+ 20, 8,154, 66,180,249, 3,255, 0, 0, 0, 0, 64, 17, 0,162,192,113,196, 63,192,119,239, 52, 49, 10,173, 64,171,144, 3,255,
+ 0, 0, 0, 0,191, 7,217,162,192,156,117, 21,192, 75,238,222,245,139,149, 20,186,108, 3,255, 0, 0, 0, 0,192, 6,144,171,
+192,144,158,112,192, 69,241,198,210,156,157, 55,188,115, 3,255, 0, 0, 0, 0,192,148,238,110,192, 50,109,115,192, 13,197,187,
+153,170,195,231,208, 17, 3,255, 0, 0, 0, 0,192, 96,252, 79,192,115, 40,140,192, 48,165,116,178,226,173, 98,195,236, 3,255,
+ 0, 0, 0, 0,192,172,228,100,191,248,128,217,191,150, 93, 8,138, 91,213, 53,229, 86, 3,255, 0, 0, 0, 0,192,182,171, 82,
+191,168,250,216, 62,147, 15, 15,131,122,226,250, 5,203, 3,255, 0, 0, 0, 0,192,160, 73,215, 62, 49,165,124, 64, 66, 85,232,
+147, 33, 4, 84, 67, 42, 3,255, 0, 0, 0, 0,192,178, 89,171,191, 24,115,192, 63,221,116, 78,134,129,243, 64, 38, 50, 3,255,
+ 0, 0, 0, 0,192,143,206, 51, 64,105,250,133,191, 97,251,119,158, 85, 80, 53,235,193, 3,255, 0, 0, 0, 0,192,160, 32, 62,
+ 64, 65, 38,163, 63, 3,117,164,146,236, 66, 24, 10,193, 3,255, 0, 0, 0, 0,192,155,108,216, 63,141,255, 59, 64, 69,117,189,
+150, 61, 23,119, 68, 42, 3,255, 0, 0, 0, 0,192,164, 27, 85, 64, 9, 78,244, 63,239,193, 87,144, 33, 46,128, 41, 73, 3,255,
+ 0, 0, 0, 0,192,117, 35,134, 64,138,152, 39,191,116, 86, 73,171,230, 94, 2,234, 73, 3,255, 0, 0, 0, 0,192, 67,220, 35,
+ 64,159,218, 6, 62,155,103,242,188,240,108,215, 6, 55, 3,255, 0, 0, 0, 0,191, 99, 79,130, 64,164,182,215, 64, 42, 4, 10,
+237,118,112, 50, 58,190, 3,255, 0, 0, 0, 0,192, 3, 86,161, 64,168,205, 14, 63,197, 55, 60,211,148,115, 31, 33,255, 3,255,
+ 0, 0, 0, 0, 63,215,101,229, 64,168,141, 84,191,248, 90, 16, 37, 11,114,148,212,159, 3,255, 0, 0, 0, 0, 63,155, 52, 99,
+ 64,183, 17,198,190,235,199,232, 26,159,124,192,245,120, 3,255, 0, 0, 0, 0, 61, 10,179,105, 64,169,185, 25, 64, 31,119,120,
+ 0, 77,115,101, 55, 96, 3,255, 0, 0, 0, 0, 63, 37,198,143, 64,183,120,123, 63,135,108,160, 13,240,125, 8, 23,144, 3,255,
+ 0, 0, 0, 0, 64, 32,174,180, 64,155, 13, 65,192, 8,167,238, 53,247,105,245,208,163, 3,255, 0, 0, 0, 0, 64,104,199, 69,
+ 64,143,135,177,191,132, 12, 41, 79, 10, 98, 10,233, 31, 3,255, 0, 0, 0, 0, 64,159,134,121, 64, 49,245, 49, 63,169,166,210,
+109, 27, 59,242, 29,190, 3,255, 0, 0, 0, 0, 64,143,133, 52, 64,113,200,119, 62, 29,206,186, 98, 20, 82, 39, 3,190, 3,255,
+ 0, 0, 0, 0, 64,160, 73,215,190, 49,165,124,192, 66, 85,232,108,223,251,172,188,214, 3,255, 0, 0, 0, 0, 64,178, 89,171,
+ 63, 24,115,192,191,221,116, 78,121,127, 12,192,217,206, 3,255, 0, 0, 0, 0, 64,172,228,100, 63,248,128,217, 63,150, 93, 8,
+117,165, 42,203, 26,170, 3,255, 0, 0, 0, 0, 64,182,171, 82, 63,168,250,216,190,147, 15, 15,124,134, 29, 6,250, 53, 3,255,
+ 0, 0, 0, 0, 64,155,108,216,191,141,255, 59,192, 69,117,189,105,195,232,137,187,214, 3,255, 0, 0, 0, 0, 64,164, 27, 85,
+192, 9, 78,244,191,239,193, 87,111,223,209,128,214,183, 3,255, 0, 0, 0, 0, 64,143,206, 51,192,105,250,133, 63, 97,251,119,
+ 97,171,175,203, 20, 63, 3,255, 0, 0, 0, 0, 64,160, 32, 62,192, 65, 38,163,191, 3,117,164,109, 20,189,232,245, 63, 3,255,
+ 0, 0, 0, 0, 63, 99, 79,130,192,164,182,215,192, 42, 4, 10, 18,138,143,206,197, 66, 3,255, 0, 0, 0, 0, 64, 3, 86,161,
+192,168,205, 14,191,197, 55, 60, 44,108,140,225,222, 1, 3,255, 0, 0, 0, 0, 64,117, 35,134,192,138,152, 39, 63,116, 86, 73,
+ 84, 26,161,254, 21,183, 3,255, 0, 0, 0, 0, 64, 67,220, 35,192,159,218, 6,190,155,103,242, 67, 16,147, 41,249,201, 3,255,
+ 0, 0, 0, 0,189, 10,179,105,192,169,185, 25,192, 31,119,120,255,179,140,155,200,160, 3,255, 0, 0, 0, 0,191, 37,198,143,
+192,183,120,123,191,135,108,160,242, 16,130,248,232,112, 3,255, 0, 0, 0, 0,191,215,101,229,192,168,141, 84, 63,248, 90, 16,
+218,245,141,108, 43, 97, 3,255, 0, 0, 0, 0,191,155, 52, 99,192,183, 17,198, 62,235,199,232,229, 97,131, 64, 10,136, 3,255,
+ 0, 0, 0, 0,192,159,134,121,192, 49,245, 49,191,169,166,210,146,229,196, 14,226, 66, 3,255, 0, 0, 0, 0,192,143,133, 52,
+192,113,200,119,190, 29,206,186,157,236,173,217,252, 66, 3,255, 0, 0, 0, 0,192, 32,174,180,192,155, 13, 65, 64, 8,167,238,
+202, 9,150, 11, 47, 93, 3,255, 0, 0, 0, 0,192,104,199, 69,192,143,135,177, 63,132, 12, 41,176,246,157,246, 22,225, 3,255,
+ 0, 0, 0, 0,191,117,248,244, 64,148, 90,109, 64, 93, 0,123,235,248,101,190, 75, 7, 3,255, 0, 0, 0, 0,192, 17, 0,162,
+ 64,113,196, 63, 64,119,239, 52,206,246, 82,192, 84,112, 3,255, 0, 0, 0, 0,192,136,133,151, 63,162,249, 9, 64,115,219,106,
+162, 81, 26,209, 82,253, 3,255, 0, 0, 0, 0,192, 89,124,110, 64, 40, 6,135, 64,127,195,223,181,136, 56,225, 87, 48, 3,255,
+ 0, 0, 0, 0, 63, 7,217,162, 64,156,117, 21, 64, 75,238,222, 10,117,106,236, 69,148, 3,255, 0, 0, 0, 0, 64, 6,144,171,
+ 64,144,158,112, 64, 69,241,198, 45,100, 98,201, 67,141, 3,255, 0, 0, 0, 0, 64,148,238,110, 64, 50,109,115, 64, 13,197,187,
+102, 86, 60, 25, 47,239, 3,255, 0, 0, 0, 0, 64, 96,252, 79, 64,115, 40,140, 64, 48,165,116, 77, 30, 82,158, 60, 20, 3,255,
+ 0, 0, 0, 0, 64,170,143, 39, 63,183, 15,167, 63,252, 85,251,116, 39, 32, 87, 42,243, 3,255, 0, 0, 0, 0, 64,175,214, 8,
+190, 53,124,177, 64, 2,241,206,119,233,252,167, 44,164, 3,255, 0, 0, 0, 0, 64,146, 85,238,192, 78,205,178, 63,221, 54, 70,
+ 99, 73,184,122, 37,136, 3,255, 0, 0, 0, 0, 64,167,137, 76,191,227, 31,111, 63,251, 57,158,114, 22,216,202, 42,197, 3,255,
+ 0, 0, 0, 0, 64, 95,243,103,192,138, 91,221, 63,236, 15,186, 77, 86,162, 37, 39,231, 3,255, 0, 0, 0, 0, 64, 5,206, 46,
+192,159, 41,121, 64, 19, 91,154, 46, 26,147,160, 50, 30, 3,255, 0, 0, 0, 0,191,139,200,169,192,163, 78,198, 64, 42,146,201,
+231, 9,144,197, 58, 50, 3,255, 0, 0, 0, 0, 63, 4,128,187,192,167,181,206, 64, 37, 92, 74, 10,199,141,160, 56,111, 3,255,
+ 0, 0, 0, 0,192, 27,158,249,192,141,118,197, 64, 62,196, 58,203,166,158,186, 64,166, 3,255, 0, 0, 0, 0,192, 89,244, 98,
+192, 79,120, 8, 64, 96,128, 65,181,248,184,217, 76,105, 3,255, 0, 0, 0, 0,192,144,100, 13,190,118,214,200, 64,110,205, 64,
+157, 74,251,219, 81, 95, 3,255, 0, 0, 0, 0,192,131,202, 42,191,231,161, 60, 64,112,245,142,165,246,217, 1, 82, 47, 3,255,
+ 0, 0, 0, 0,192,129,179,222, 62,224,147,234, 64,134,180, 38,166,173, 9,192, 91, 38, 3,255, 0, 0, 0, 0,192, 49,138,114,
+ 62, 57, 97,246, 64,165, 76, 57,195, 6, 4, 9,112,118, 3,255, 0, 0, 0, 0, 62,160,160, 77,190,182, 20, 9, 64,186,232,108,
+ 7,248,248, 15,127,128, 3,255, 0, 0, 0, 0,191,163,144, 33,189,186,144,151, 64,183, 47, 50,228,159,253,237,125, 4, 3,255,
+ 0, 0, 0, 0,189,172, 55, 60, 64,143, 64, 22, 64,113,246,164,253,229, 98,124, 81,185, 3,255, 0, 0, 0, 0, 62,154,173,167,
+ 64, 83,224,111, 64,154,169,198, 6,120, 72,167,105, 45, 3,255, 0, 0, 0, 0, 63,122, 51,149, 62,163,151, 52, 64,184,157, 15,
+ 21,138, 5,220,126, 8, 3,255, 0, 0, 0, 0, 63, 42,113, 5, 63,241,112, 31, 64,176,119, 15, 14,163, 40,172,120,121, 3,255,
+ 0, 0, 0, 0, 64,155,192, 43, 63,250, 6,151, 64, 39, 82,170,106,177, 43, 9, 56, 25, 3,255, 0, 0, 0, 0, 64,132,118,233,
+ 63,173,111,217, 64,123,122, 67, 90,156, 29,198, 85, 91, 3,255, 0, 0, 0, 0, 63,231, 16,151,189,209,166,160, 64,178, 95,167,
+ 38,120,253, 60,122, 11, 3,255, 0, 0, 0, 0, 64, 69,200,163, 63, 38,143,178, 64,158, 48,148, 67, 13, 13,245,108, 33, 3,255,
+ 0, 0, 0, 0, 64,125, 83,204,192,105, 55,169, 64, 20,162,244, 86,184,176, 10, 49,174, 3,255, 0, 0, 0, 0, 64, 91,215,178,
+192, 62,235,222, 64,108,254,190, 75, 41,190,169, 80,101, 3,255, 0, 0, 0, 0, 63,211,156,158,191,132,228,185, 64,176,207,190,
+ 35, 92,234, 25,121, 12, 3,255, 0, 0, 0, 0, 64, 41, 76, 0,192, 5,199,190, 64,153,157, 83, 57,110,210,181,105, 10, 3,255,
+ 0, 0, 0, 0,191,199, 4,220,192,146,145, 7, 64, 83,186,104,221,147,155,119, 71, 88, 3,255, 0, 0, 0, 0,191, 86,120, 9,
+192,109, 91,149, 64,142,242, 79,237,123,174,192, 97, 38, 3,255, 0, 0, 0, 0, 63, 59, 63,242,191,152,237,210, 64,182, 21,251,
+ 16,131,230,230,124,107, 3,255, 0, 0, 0, 0,189, 94,230, 86,192, 35, 30,198, 64,169, 15,233,255, 18,200,204,115,121, 3,255,
+ 0, 0, 0, 0,192, 46, 27,208, 64, 86,104,124,192,126, 52, 85,197,137, 72,226,168,134, 3,255, 0, 0, 0, 0,191,234,168, 82,
+ 64,149, 62, 87,192, 67, 12,118,217, 5,101,188,188,210, 3,255, 0, 0, 0, 0,192, 16, 10,186, 64, 52,106,249,192,147,253,210,
+206,182, 62,131,155,198, 3,255, 0, 0, 0, 0,190,240, 33, 93, 64, 71,199,191,192,158, 47,142,245,214, 69, 40,148,199, 3,255,
+ 0, 0, 0, 0,187, 71, 46, 19, 64,115,240,194,192,142,166,175,254,240, 82,161,158, 66, 3,255, 0, 0, 0, 0,191,101,194,188,
+ 64,154, 84, 17,192, 77,193,240,235, 76,104,214,185,142, 3,255, 0, 0, 0, 0,192,115,246,246, 64, 15, 86,183,192,118,168, 51,
+172,249, 47,229,171, 45, 3,255, 0, 0, 0, 0,192,160, 1,101, 63,184,146, 47,192, 45, 38,153,146,225, 30, 96,196,102, 3,255,
+ 0, 0, 0, 0,192, 85,229,215, 63,218,178,166,192,144, 55,183,182, 38, 37,133,158,110, 3,255, 0, 0, 0, 0,192,104,178,151,
+189,205,107,245,192,147, 60,175,175,178,253,205,156, 91, 3,255, 0, 0, 0, 0,192,136, 81,192,191, 4,239, 55,192,127,222, 24,
+163,130,245,158,168, 35, 3,255, 0, 0, 0, 0,192,164,241, 70, 62,251,218,102,192, 48, 82,143,143,222, 11,210,195,110, 3,255,
+ 0, 0, 0, 0, 63,173,230,209, 64, 71,135,231,192,152,234, 27, 29,148, 67, 4,151, 11, 3,255, 0, 0, 0, 0, 64, 67,103,158,
+ 64, 51,206, 82,192,132,168, 39, 66,203, 60, 63,164,242, 3,255, 0, 0, 0, 0, 63,100,131,136, 64, 27, 95, 16,192,168,115, 4,
+ 20,122, 53,138,141,143, 3,255, 0, 0, 0, 0, 63,217,154, 77, 63, 78, 69,185,192,177,196,221, 38, 53, 17,236,135, 42, 3,255,
+ 0, 0, 0, 0, 64, 37,195,107, 63, 36,213, 4,192,167, 33, 20, 55,151, 14,194,141,168, 3,255, 0, 0, 0, 0, 64, 94,139,103,
+ 63,250,146,153,192,137,141, 72, 75, 19, 43,156,161,245, 3,255, 0, 0, 0, 0, 64, 21,195,231,191,101, 58,236,192,169,178,218,
+ 49,247,236, 31,139,218, 3,255, 0, 0, 0, 0, 64, 48, 32,142,192, 32,140,155,192,145, 1,195, 59, 3,200,178,156,204, 3,255,
+ 0, 0, 0, 0, 63,185,155, 70,191, 59,202, 12,192,180, 86,163, 32,149,239, 73,133, 91, 3,255, 0, 0, 0, 0, 62, 43, 97, 29,
+192, 2,118,144,192,175,231,125, 4,106,210,160,136,103, 3,255, 0, 0, 0, 0, 62,196,116, 97,192, 56,176, 10,192,162,239,120,
+ 8,164,194, 20,144, 81, 3,255, 0, 0, 0, 0, 64, 5, 2,185,192, 76,105,217,192,142,173,135, 45,218,187, 79,158, 56, 3,255,
+ 0, 0, 0, 0,191,144,243,163,192, 73, 41,252,192,154, 66,148,230,134,188, 73,150,107, 3,255, 0, 0, 0, 0,192, 20,133,147,
+192,124, 55,234,192,107, 3,176,204,110,170,196,175,164, 3,255, 0, 0, 0, 0,192, 60,186, 42,191,189,128,219,192,155, 43, 23,
+191, 41,222,189,150,199, 3,255, 0, 0, 0, 0,191,172,164, 52,192, 18,240,106,192,167, 58,141,226, 76,204,213,142,128, 3,255,
+ 0, 0, 0, 0,192,100,171, 12,191,243, 33,249,192,135,221,106,178,248,214,143,162,143, 3,255, 0, 0, 0, 0,192, 74, 78,195,
+192, 96,206,241,192, 94, 88, 98,188, 4,179, 34,179,129, 3,255, 0, 0, 0, 0,192,177,110, 41, 63,186, 30, 81,191,158,249,105,
+134,160, 30,165,229, 86, 3,255, 0, 0, 0, 0,192,172,138, 45, 64, 17,149,114, 62,200,203,127,137,251, 48,171, 9, 56, 3,255,
+ 0, 0, 0, 0,192,182, 94, 10, 63, 1, 5, 48,191,165, 81, 86,131,156, 12, 24,228, 94, 3,255, 0, 0, 0, 0,192,186,224,117,
+190,247,234, 37, 62,126, 56,147,128,132,246,101, 6, 46, 3,255, 0, 0, 0, 0,192,184, 78,204,189, 89,193, 19, 63,141,163,187,
+130, 22,254,208, 22,241, 3,255, 0, 0, 0, 0,192,174,232,105, 63,224,187,151, 63,153,183,156,136,137, 38,137, 25, 3, 3,255,
+ 0, 0, 0, 0,191, 68,118, 42, 64,176,173,101,191,233,132,114,238, 57,120,142,216,217, 3,255, 0, 0, 0, 0, 62,191,172, 81,
+ 64,186,208, 67,190,216,163,195, 7, 75,127,131,247,159, 3,255, 0, 0, 0, 0,191,218, 2,113, 64,171,151,172,191,212, 25,114,
+219,243,117,116,220, 30, 3,255, 0, 0, 0, 0,192, 21,244,251, 64,172, 12, 28, 61,128,151, 13,205,229,117,196, 1,226, 3,255,
+ 0, 0, 0, 0,191,223, 39, 51, 64,177, 94,248, 63, 76,122,104,217,155,121, 3, 16, 65, 3,255, 0, 0, 0, 0, 61, 28,208, 72,
+ 64,187, 13, 91, 62,245,215, 64, 0,187,127,168, 9, 66, 3,255, 0, 0, 0, 0, 64,142, 93, 45, 64, 14,137, 70,192, 70,202,147,
+ 96,241, 49,173,188,202, 3,255, 0, 0, 0, 0, 64,173, 23,106, 63,182,131,157,191,225,176,175,118, 7, 32, 20,218, 72, 3,255,
+ 0, 0, 0, 0, 64,128,203, 78, 64, 69, 14,124,192, 61, 0, 55, 88,168, 66, 80,191,199, 3,255, 0, 0, 0, 0, 64,133,175,133,
+ 64,121,149, 28,191,168,212, 51, 92, 4, 84, 86,227,170, 3,255, 0, 0, 0, 0, 64,149,211, 8, 64, 94,166, 84,191, 29, 24, 68,
+101,221, 76, 30,241,113, 3,255, 0, 0, 0, 0, 64,175,169, 31, 63,237,176,138,191,103,168, 15,119,152, 40,128,235, 11, 3,255,
+ 0, 0, 0, 0, 64, 57, 78,122,192,120, 12,224,192, 84, 56, 7, 64, 62,171,247,183,239, 3,255, 0, 0, 0, 0, 64, 48, 74, 0,
+192,155,165,245,191,227, 87,208, 61, 38,150, 68,217,192, 3,255, 0, 0, 0, 0, 64,100,108, 85,192, 76, 47,115,192, 88,224,149,
+ 77,102,185, 90,182,131, 3,255, 0, 0, 0, 0, 64,150,191,173,192, 55,233,227,191,254,101,198,102,121,192, 79,213, 73, 3,255,
+ 0, 0, 0, 0, 64,148, 97,119,192, 89, 33,200,191,150,225, 24,101, 7,182, 44,229, 20, 3,255, 0, 0, 0, 0, 64, 86,171, 75,
+192,150, 83, 36,191,133, 36, 22, 72,220,153,131,232, 32, 3,255, 0, 0, 0, 0,192, 81,251,116,192,139, 80,115,192, 10,124, 57,
+185, 81,160, 53,208,254, 3,255, 0, 0, 0, 0,192,122,239, 70,192,138,220, 53,190,227, 86,113,171, 68,160,132,246,195, 3,255,
+ 0, 0, 0, 0,192, 28, 50, 14,192,153, 4,245,192, 23, 39,141,201,187,151,215,205, 33, 3,255, 0, 0, 0, 0,191,189,123, 34,
+192,178,168,203,191,130,106,149,222,209,134, 63,234,158, 3,255, 0, 0, 0, 0,191,232,127,176,192,178,107,177,189,236,189, 47,
+216, 65,134,100,252, 66, 3,255, 0, 0, 0, 0,192, 90,168, 53,192,152, 83,169, 62,133,201,227,181, 29,152, 77, 4,136, 3,255,
+ 0, 0, 0, 0,192,150,191,173, 64, 55,233,227, 63,254,101,198,153,135, 63,177, 42,183, 3,255, 0, 0, 0, 0,192,100,108, 85,
+ 64, 76, 47,115, 64, 88,224,149,178,154, 70,166, 73,125, 3,255, 0, 0, 0, 0,192,148, 97,119, 64, 89, 33,200, 63,150,225, 24,
+154,249, 73,212, 26,236, 3,255, 0, 0, 0, 0,192, 86,171, 75, 64,150, 83, 36, 63,133, 36, 22,183, 36,102,125, 23,224, 3,255,
+ 0, 0, 0, 0,192, 48, 74, 0, 64,155,165,245, 63,227, 87,208,194,218,105,188, 38, 64, 3,255, 0, 0, 0, 0,192, 57, 78,122,
+ 64,120, 12,224, 64, 84, 56, 7,191,194, 84, 9, 72, 17, 3,255, 0, 0, 0, 0, 63,189,123, 34, 64,178,168,203, 63,130,106,149,
+ 33, 47,121,193, 21, 98, 3,255, 0, 0, 0, 0, 64, 28, 50, 14, 64,153, 4,245, 64, 23, 39,141, 54, 69,104, 41, 50,223, 3,255,
+ 0, 0, 0, 0, 63,232,127,176, 64,178,107,177, 61,236,189, 47, 39,191,121,156, 3,190, 3,255, 0, 0, 0, 0, 64, 90,168, 53,
+ 64,152, 83,169,190,133,201,227, 74,227,103,179,251,120, 3,255, 0, 0, 0, 0, 64,122,239, 70, 64,138,220, 53, 62,227, 86,113,
+ 84,188, 95,124, 9, 61, 3,255, 0, 0, 0, 0, 64, 81,251,116, 64,139, 80,115, 64, 10,124, 57, 70,175, 95,203, 47, 2, 3,255,
+ 0, 0, 0, 0, 64,186,224,117, 62,247,234, 37,190,126, 56,147,127,124, 9,155,249,210, 3,255, 0, 0, 0, 0, 64,182, 94, 10,
+191, 1, 5, 48, 63,165, 81, 86,124,100,243,232, 27,162, 3,255, 0, 0, 0, 0, 64,184, 78,204, 61, 89,193, 19,191,141,163,187,
+125,234, 1, 48,233, 15, 3,255, 0, 0, 0, 0, 64,174,232,105,191,224,187,151,191,153,183,156,119,119,217,119,230,253, 3,255,
+ 0, 0, 0, 0, 64,172,138, 45,192, 17,149,114,190,200,203,127,118, 5,207, 85,246,200, 3,255, 0, 0, 0, 0, 64,177,110, 41,
+191,186, 30, 81, 63,158,249,105,121, 96,225, 91, 26,170, 3,255, 0, 0, 0, 0, 64, 21,244,251,192,172, 12, 28,189,128,151, 13,
+ 50, 27,138, 60,254, 30, 3,255, 0, 0, 0, 0, 63,218, 2,113,192,171,151,172, 63,212, 25,114, 36, 13,138,140, 35,226, 3,255,
+ 0, 0, 0, 0, 63,223, 39, 51,192,177, 94,248,191, 76,122,104, 38,101,134,253,239,191, 3,255, 0, 0, 0, 0,189, 28,208, 72,
+192,187, 13, 91,190,245,215, 64,255, 69,128, 88,246,190, 3,255, 0, 0, 0, 0,190,191,172, 81,192,186,208, 67, 62,216,163,195,
+248,181,128,125, 8, 97, 3,255, 0, 0, 0, 0, 63, 68,118, 42,192,176,173,101, 63,233,132,114, 17,199,135,114, 39, 39, 3,255,
+ 0, 0, 0, 0,192,133,175,133,192,121,149, 28, 63,168,212, 51,163,252,171,170, 28, 86, 3,255, 0, 0, 0, 0,192,128,203, 78,
+192, 69, 14,124, 64, 61, 0, 55,167, 88,189,176, 64, 57, 3,255, 0, 0, 0, 0,192,175,169, 31,191,237,176,138, 63,103,168, 15,
+136,104,215,128, 20,245, 3,255, 0, 0, 0, 0,192,149,211, 8,192, 94,166, 84, 63, 29, 24, 68,154, 35,179,226, 14,143, 3,255,
+ 0, 0, 0, 0,192,173, 23,106,191,182,131,157, 63,225,176,175,137,249,223,236, 37,184, 3,255, 0, 0, 0, 0,192,142, 93, 45,
+192, 14,137, 70, 64, 70,202,147,159, 15,206, 83, 67, 54, 3,255, 0, 0, 0, 0,192, 5, 2,185, 64, 76,105,217, 64,142,173,135,
+210, 38, 68,177, 97,200, 3,255, 0, 0, 0, 0,190,196,116, 97, 64, 56,176, 10, 64,162,239,120,247, 92, 61,236,111,175, 3,255,
+ 0, 0, 0, 0,192, 48, 32,142, 64, 32,140,155, 64,145, 1,195,196,253, 55, 78, 99, 52, 3,255, 0, 0, 0, 0,192, 21,195,231,
+ 63,101, 58,236, 64,169,178,218,206, 9, 19,225,116, 38, 3,255, 0, 0, 0, 0,191,185,155, 70, 63, 59,202, 12, 64,180, 86,163,
+223,107, 16,183,122,165, 3,255, 0, 0, 0, 0,190, 43, 97, 29, 64, 2,118,144, 64,175,231,125,251,150, 45, 96,119,153, 3,255,
+ 0, 0, 0, 0, 64, 74, 78,195, 64, 96,206,241, 64, 94, 88, 98, 67,252, 76,222, 76,127, 3,255, 0, 0, 0, 0, 64,100,171, 12,
+ 63,243, 33,249, 64,135,221,106, 77, 8, 41,113, 93,113, 3,255, 0, 0, 0, 0, 64, 20,133,147, 64,124, 55,234, 64,107, 3,176,
+ 51,146, 85, 60, 80, 92, 3,255, 0, 0, 0, 0, 63,144,243,164, 64, 73, 41,252, 64,154, 66,148, 25,122, 67,183,105,149, 3,255,
+ 0, 0, 0, 0, 63,172,164, 52, 64, 18,240,106, 64,167, 58,141, 29,180, 51, 43,113,128, 3,255, 0, 0, 0, 0, 64, 60,186, 42,
+ 63,189,128,219, 64,155, 43, 23, 64,215, 33, 67,105, 57, 3,255, 0, 0, 0, 0, 64,160, 1,101,191,184,146, 47, 64, 45, 38,153,
+109, 31,225,160, 59,154, 3,255, 0, 0, 0, 0, 64,115,246,246,192, 15, 86,183, 64,118,168, 51, 83, 7,208, 27, 84,211, 3,255,
+ 0, 0, 0, 0, 64,164,241, 70,190,251,218,102, 64, 48, 82,143,112, 34,244, 46, 60,146, 3,255, 0, 0, 0, 0, 64,136, 81,192,
+ 63, 4,239, 55, 64,127,222, 24, 92,126, 10, 98, 87,221, 3,255, 0, 0, 0, 0, 64,104,178,151, 61,205,107,245, 64,147, 60,175,
+ 80, 78, 2, 51, 99,165, 3,255, 0, 0, 0, 0, 64, 85,229,215,191,218,178,166, 64,144, 55,183, 73,218,218,123, 97,146, 3,255,
+ 0, 0, 0, 0, 63,101,194,188,192,154, 84, 17, 64, 77,193,240, 20,180,151, 42, 70,114, 3,255, 0, 0, 0, 0, 59, 71, 46, 19,
+192,115,240,194, 64,142,166,175, 1, 16,173, 95, 97,190, 3,255, 0, 0, 0, 0, 63,234,168, 82,192,149, 62, 87, 64, 67, 12,118,
+ 38,251,154, 68, 67, 46, 3,255, 0, 0, 0, 0, 64, 46, 27,208,192, 86,104,124, 64,126, 52, 85, 58,119,183, 30, 87,122, 3,255,
+ 0, 0, 0, 0, 64, 16, 10,186,192, 52,106,249, 64,147,253,210, 49, 74,193,125,100, 58, 3,255, 0, 0, 0, 0, 62,240, 33, 93,
+192, 71,199,191, 64,158, 47,142, 10, 42,186,216,107, 57, 3,255, 0, 0, 0, 0,192, 94,139,103,191,250,146,153, 64,137,141, 72,
+180,237,212,100, 94, 11, 3,255, 0, 0, 0, 0,192, 37,195,107,191, 36,213, 4, 64,167, 33, 20,200,105,241, 62,114, 88, 3,255,
+ 0, 0, 0, 0,192, 67,103,158,192, 51,206, 82, 64,132,168, 39,189, 53,195,193, 91, 14, 3,255, 0, 0, 0, 0,191,173,230,209,
+192, 71,135,231, 64,152,234, 27,226,108,188,252,104,245, 3,255, 0, 0, 0, 0,191,217,154, 77,191, 78, 69,185, 64,177,196,221,
+217,203,238, 20,120,214, 3,255, 0, 0, 0, 0,191,100,131,136,192, 27, 95, 16, 64,168,115, 4,235,134,202,118,114,113, 3,255,
+ 0, 0, 0, 0,192, 37,220,139, 64,141,135,245,192, 54,173,114,199, 45, 96, 95,193,211, 3,255, 0, 0, 0, 0,192, 84,119,204,
+ 64,130, 73, 93,192, 38,107,212,183, 58, 88,223,199,137, 3,255, 0, 0, 0, 0,192, 67, 76,208, 64,111,120, 62,192, 85, 89, 14,
+189, 80, 81,196,183,140, 3,255, 0, 0, 0, 0,191,238,147, 68, 64,100,230,166,192,136, 9,234,215,216, 78,130,163, 59, 3,255,
+ 0, 0, 0, 0,191,109,149, 30, 64,111, 18, 40,192,141,100,171,235, 37, 81,201,159,199, 3,255, 0, 0, 0, 0,191,178,237,144,
+ 64,136,136, 25,192,113, 1,121,225,117, 92,189,173, 62, 3,255, 0, 0, 0, 0, 63, 66, 82,214, 64,152,115,128,192, 85, 25,164,
+ 16,241,104, 27,183,126, 3,255, 0, 0, 0, 0,189,171,155,119, 64,155, 40,138,192, 83, 96,113,254,128,105,196,183,238, 3,255,
+ 0, 0, 0, 0, 62,194,138, 67, 64,138, 97,177,192,124,158, 75, 8,112, 94,134,170, 29, 3,255, 0, 0, 0, 0,191, 94,106,158,
+ 64, 30,106,167,192,167,240,254,236,229, 53,187,141,105, 3,255, 0, 0, 0, 0,191,229,114, 22, 64, 20, 96,193,192,162,167,253,
+217, 22, 50, 93,144,244, 3,255, 0, 0, 0, 0,191,162,210, 45, 63,224,211,233,192,174, 67,184,228, 69, 37,245,136,244, 3,255,
+ 0, 0, 0, 0,192,152, 61, 37, 64, 14, 9,230,192, 39,179,137,152, 85, 48,183,198,226, 3,255, 0, 0, 0, 0,192,140,187,232,
+ 64, 62, 96, 6,192, 30,247,107,160, 7, 65, 68,202, 11, 3,255, 0, 0, 0, 0,192,132,134,116, 64, 40,130, 40,192, 77,207,237,
+165,139, 57,149,186, 30, 3,255, 0, 0, 0, 0,192,129,129, 12, 63,173,129,231,192,128,125,159,167, 62, 29, 15,168,123, 3,255,
+ 0, 0, 0, 0,192,134,112,254, 62,207,146,126,192,130, 19,159,164, 15, 9,119,167,117, 3,255, 0, 0, 0, 0,192,149,121,189,
+ 63,111,192,142,192, 90, 95, 76,154, 95, 20,107,180,236, 3,255, 0, 0, 0, 0,192,162, 65, 12,191,149, 84, 11,192, 44,202,172,
+145, 60,230, 47,197, 75, 3,255, 0, 0, 0, 0,192,165,120, 74,190,167, 78, 95,192, 48, 51,139,143, 54,248,140,195,244, 3,255,
+ 0, 0, 0, 0,192,150,161, 61,191, 89,221,107,192, 89,113,118,153, 40,237, 79,182, 35, 3,255, 0, 0, 0, 0,192, 66, 56, 52,
+ 62,139, 40,206,192,160,116, 21,190, 13, 6, 19,146,121, 3,255, 0, 0, 0, 0,192, 56,120,245, 63,154,213,118,192,158,227, 81,
+193, 81, 26, 47,147,133, 3,255, 0, 0, 0, 0,192, 22,104,220, 63, 40,221,204,192,170,137,115,205, 16, 14, 89,139,117, 3,255,
+ 0, 0, 0, 0, 64, 39,143,145, 64, 94, 49,190,192,124, 27,165, 56,238, 75,252,170, 43, 3,255, 0, 0, 0, 0, 64, 6,168,130,
+ 64,130,132,190,192,105, 96, 12, 45,226, 89, 91,176,173, 3,255, 0, 0, 0, 0, 63,222,169, 76, 64,104,107,205,192,136,142,150,
+ 38, 23, 79,105,163, 33, 3,255, 0, 0, 0, 0, 63,229,207,137, 64, 22, 63, 30,192,161,235,207, 39,198, 50,227,145,127, 3,255,
+ 0, 0, 0, 0, 64, 14, 11,239, 63,191,114,175,192,166,208,254, 48,133, 33, 81,142, 87, 3,255, 0, 0, 0, 0, 64, 43,222,239,
+ 64, 11,226,212,192,151, 71,227, 58, 33, 47,140,152, 91, 3,255, 0, 0, 0, 0, 64,124,245, 0, 62,187, 32, 27,192,138, 6, 57,
+ 86,138, 7,176,162, 2, 3,255, 0, 0, 0, 0, 64,112, 75, 42, 63,152, 42,228,192,139, 44, 25, 82, 0, 25,159,161, 31, 3,255,
+ 0, 0, 0, 0, 64, 82,218,178, 63, 1,247,178,192,154,129,211, 72, 35, 11, 4,150,217, 3,255, 0, 0, 0, 0, 63,104,203,208,
+ 63,113, 6,146,192,183, 5,108, 19,132, 20,150,131, 49, 3,255, 0, 0, 0, 0, 62,251, 68, 26, 63,228, 38,111,192,178, 48,114,
+ 10,139, 38,158,134,109, 3,255, 0, 0, 0, 0, 61,149, 78,163, 63,137, 25, 65,192,184,102,234, 1, 54, 23, 52,130, 34, 3,255,
+ 0, 0, 0, 0, 64, 80,140, 98,191,238,205,169,192,144, 69, 83, 71, 70,215,145,157,173, 3,255, 0, 0, 0, 0, 64,109, 39,177,
+191,147,213,155,192,140,143,238, 81, 57,230,247,160, 77, 3,255, 0, 0, 0, 0, 64, 66,225,100,191,131,191,146,192,157, 18,152,
+ 66,178,233,128,149, 25, 3,255, 0, 0, 0, 0, 63,220, 24,190,191,202,163,163,192,171,244,160, 37, 99,220,199,138,196, 3,255,
+ 0, 0, 0, 0, 63,133,219,227,192, 17, 47,172,192,169,160, 93, 23,126,206,164,140, 68, 3,255, 0, 0, 0, 0, 63,247,202, 46,
+192, 27,140, 23,192,158,252,116, 41,217,203, 77,147, 32, 3,255, 0, 0, 0, 0, 63, 68,220, 36,192,132,143, 24,192,130,105, 20,
+ 16,163,165, 66,167, 72, 3,255, 0, 0, 0, 0, 63,185,255, 60,192,108,244,215,192,138, 7,129, 31,113,175, 11,161,251, 3,255,
+ 0, 0, 0, 0, 63, 19, 18,220,192, 98,186,168,192,148,136, 66, 12,155,178,121,154,241, 3,255, 0, 0, 0, 0,187,172,119,131,
+191,162,209,182,192,183, 73,170,255,209,228,144,130,251, 3,255, 0, 0, 0, 0, 63, 40,230,165,191, 24,111,246,192,185,150, 50,
+ 14, 19,243, 18,129,113, 3,255, 0, 0, 0, 0,190, 50, 45,123,190,230, 16,213,192,186,240,160,251,231,246,124,128,109, 3,255,
+ 0, 0, 0, 0,191,199, 22,221,192,134,211, 71,192,113,161, 37,222, 98,163,255,173,157, 3,255, 0, 0, 0, 0,191, 58,131,171,
+192,140,178, 57,192,115,174,214,240,105,159,201,173, 11, 3,255, 0, 0, 0, 0,191,112,119,228,192,115, 46, 49,192,139,222,186,
+235,152,172,221,160,217, 3,255, 0, 0, 0, 0,191,254, 75,122,192, 50, 36, 18,192,152, 70, 84,211,253,195, 46,152, 87, 3,255,
+ 0, 0, 0, 0,192, 52,239,190,192, 22,186,193,192,145,240,166,194,167,204, 3,156,108, 3,255, 0, 0, 0, 0,192, 39, 23, 51,
+192, 76,245, 14,192,132,248,105,199, 29,186,137,164,200, 3,255, 0, 0, 0, 0,192,140,137,202,192, 33,234, 4,192, 60,117,152,
+159,215,200,216,192, 6, 3,255, 0, 0, 0, 0,192,115,176, 68,192, 68, 49, 85,192, 79,173, 65,172,178,189, 81,185, 81, 3,255,
+ 0, 0, 0, 0,192,128,173,131,192, 14,170, 50,192,105, 71,247,168, 30,207, 64,176,189, 3,255, 0, 0, 0, 0,192, 22, 80,230,
+191,141,155, 50,192,168, 95,108,205, 3,232, 6,141, 19, 3,255, 0, 0, 0, 0,191,194,113, 96,191,195,184,166,192,174,160, 31,
+222,205,222,245,136,227, 3,255, 0, 0, 0, 0,191,213,244,249,191, 52, 33, 10,192,178, 94,248,219,172,241, 3,134, 48, 3,255,
+ 0, 0, 0, 0,192,167, 26, 30, 64, 42, 11, 62,190,159,163,199,142, 45, 58, 26,248,236, 3,255, 0, 0, 0, 0,192,157,242, 15,
+ 64, 63, 35,177,191,132,230,242,148,115, 65,134,233, 39, 3,255, 0, 0, 0, 0,192,169,163, 58, 64, 14,207,184,191,148, 92, 43,
+140,122, 48,250,230,193, 3,255, 0, 0, 0, 0,192,184, 83,241, 63,117,241, 33,190,248, 69,204,130, 32, 20,245,246, 22, 3,255,
+ 0, 0, 0, 0,192,186,178, 88, 62,226, 33,180, 62,165,211, 69,128,153, 10, 65, 6,196, 3,255, 0, 0, 0, 0,192,181,194,100,
+ 63,178, 37,227, 62,191, 51, 65,131,199, 29,217, 7,201, 3,255, 0, 0, 0, 0,192,168, 68,140, 63, 57,100,162, 64, 31, 41, 90,
+141, 91, 15,195, 54,175, 3,255, 0, 0, 0, 0,192,173,114,185, 63,162, 11,147, 63,237,131,136,137,204, 27,106, 40,187, 3,255,
+ 0, 0, 0, 0,192,178, 82, 90, 62,168, 0,181, 63,231, 64,125,134,136, 7, 78, 39,175, 3,255, 0, 0, 0, 0,192,185, 52,235,
+191, 83,185,191,190,252,176, 39,129,201,237,211,244,241, 3,255, 0, 0, 0, 0,192,182,222, 95,190,161, 32,178,191,165, 92, 48,
+131, 90,248,208,227,211, 3,255, 0, 0, 0, 0,192,179,119, 52,191,147,204,223,191,160,141,116,133,169,230,113,228,103, 3,255,
+ 0, 0, 0, 0, 63, 35, 88,109, 64,182,186,129,191,152, 8,207, 14, 5,124,127,229,202, 3,255, 0, 0, 0, 0, 63, 99, 54,226,
+ 64,174,134,172,191,250, 98, 96, 19,180,118,244,213, 14, 3,255, 0, 0, 0, 0, 61, 60,195,150, 64,177,121, 46,191,245, 6,174,
+ 1, 84,120,249,214, 55, 3,255, 0, 0, 0, 0,191,145,160,228, 64,181, 59,121,191,123,252,246,231, 63,123,214,235, 42, 3,255,
+ 0, 0, 0, 0,191,188,166, 29, 64,181,120,167,189,165,224, 4,224, 81,123,253,253,203, 3,255, 0, 0, 0, 0,191, 9,186, 26,
+ 64,186,142,104,190,126, 74,128,243,158,127, 69,250, 88, 3,255, 0, 0, 0, 0,191, 19,205,179, 64,175,145, 33, 63,253,151,102,
+243,125,119,171, 43,167, 3,255, 0, 0, 0, 0,190,134,114,163, 64,183, 94, 81, 63,157,210, 73,250, 40,124,240, 27, 49, 3,255,
+ 0, 0, 0, 0,191,151,217,253, 64,178, 89, 90, 63,178,246,210,230, 89,121,146, 30,187, 3,255, 0, 0, 0, 0,192, 50,200,107,
+ 64,164, 21, 4,191, 18,252,143,194,229,111,189,243, 58, 3,255, 0, 0, 0, 0,192, 29,140,219, 64,163,216,164,191,187,160,163,
+202, 2,111,148,224, 27, 3,255, 0, 0, 0, 0,192, 76, 63, 8, 64,152, 92,149,191,157, 6,201,185,254,103,184,229, 25, 3,255,
+ 0, 0, 0, 0, 64,167, 31,102, 63,133,113, 18,192, 29,150,122,113,214, 22,149,202, 5, 3,255, 0, 0, 0, 0, 64,157, 48,115,
+ 63, 33,183, 74,192, 72,172, 21,107, 50, 13,106,187, 91, 3,255, 0, 0, 0, 0, 64,151, 48,250, 63,186,157,117,192, 74, 37,236,
+103, 41, 31,126,187, 23, 3,255, 0, 0, 0, 0, 64,148, 31,118, 64, 46, 99,144,192, 21,237, 95,101,101, 59,141,205,115, 3,255,
+ 0, 0, 0, 0, 64,150,177, 40, 64, 73,250,101,191,189,252,104,103, 13, 68,113,223, 39, 3,255, 0, 0, 0, 0, 64,164, 67, 59,
+ 64, 19,116,106,191,209,145, 96,111,204, 50,223,219,255, 3,255, 0, 0, 0, 0, 64,168, 99, 9, 64, 32,173,184, 63, 27, 16,129,
+114,228, 54,189, 13,164, 3,255, 0, 0, 0, 0, 64,174, 1,225, 64, 12,167, 65,190, 38, 1,199,118,149, 48, 17,252,195, 3,255,
+ 0, 0, 0, 0, 64,160,156,172, 64, 66,121, 23,188, 53,253,220,109,155, 66, 25, 0, 0, 3,255, 0, 0, 0, 0, 64,106,184,230,
+ 64,133, 83,117,191,243, 95, 76, 79,202, 90,251,214, 77, 3,255, 0, 0, 0, 0, 64,101,166,116, 64,111,107, 67,192, 47,233, 69,
+ 78, 23, 81,219,196, 34, 3,255, 0, 0, 0, 0, 64, 68, 20,109, 64,139, 9,202,192, 29,255,124, 66,138, 95, 22,202, 6, 3,255,
+ 0, 0, 0, 0, 64, 12,138, 46,192,156,168,195,192, 23,240, 99, 47,172,149, 54,203,252, 3,255, 0, 0, 0, 0, 63,201,189,110,
+192,154, 28, 48,192, 60,148,180, 34, 2,150,195,191,147, 3,255, 0, 0, 0, 0, 64, 17, 55, 21,192,140, 67,125,192, 75, 8,118,
+ 49, 61,160, 50,186,221, 3,255, 0, 0, 0, 0, 64,100,126, 85,192,114,211,103,192, 43,176,187, 78, 60,172,241,198, 2, 3,255,
+ 0, 0, 0, 0, 64,133,112, 29,192,104, 45,168,191,249, 44, 95, 90,154,176, 96,213, 48, 3,255, 0, 0, 0, 0, 64, 95,193,192,
+192,138, 5,221,191,239,219, 42, 76,181,162, 61,214,177, 3,255, 0, 0, 0, 0, 64,134, 21, 28,192,130,231,185, 62,133,210,175,
+ 91,128,166,182, 6, 33, 3,255, 0, 0, 0, 0, 64,115,101,128,192,142,100,106,190,205,174,214, 83, 32,159, 12,247,127, 3,255,
+ 0, 0, 0, 0, 64,142,250,187,192,113,123,178,190,242,120, 90, 97, 99,173,142,245,244, 3,255, 0, 0, 0, 0, 64,149, 83,115,
+192, 24,118, 25,192, 41, 5, 96,101,195,204, 61,198, 36, 3,255, 0, 0, 0, 0, 64,130, 97,236,192, 34,248,181,192, 87,132, 49,
+ 89, 17,200,184,182,144, 3,255, 0, 0, 0, 0, 64,144,103,186,191,234, 9, 91,192, 80,226,150, 98,152,216,121,184,152, 3,255,
+ 0, 0, 0, 0,192,136, 74,208,192,121,117,231,191,133,193, 32,162,248,171, 42,232,249, 3,255, 0, 0, 0, 0,192,144, 84, 31,
+192, 87, 19, 24,191,211, 65, 53,157, 74,182,248,219,224, 3,255, 0, 0, 0, 0,192,123, 90, 7,192,121,238,107,191,247,227,115,
+170, 22,171, 1,213,218, 3,255, 0, 0, 0, 0,192, 54,112,161,192,156, 77, 94,191,196,107,207,193,198,149, 23,223, 32, 3,255,
+ 0, 0, 0, 0,192, 22, 41, 24,192,169,197, 1,191, 84, 68,191,204, 45,140,105,237,172, 3,255, 0, 0, 0, 0,192, 75,243, 73,
+192,156, 16, 86,191, 33,150,180,186,216,149, 63,241,194, 3,255, 0, 0, 0, 0,192, 19,246,140,192,166, 60,148, 63,182, 70, 11,
+205,164,142,159, 31,127, 3,255, 0, 0, 0, 0,192, 58, 21, 17,192,160,209,224, 63, 88,100,103,192,202,146, 72, 18,171, 3,255,
+ 0, 0, 0, 0,192, 4,252,151,192,174, 89, 71, 63, 38, 93,215,210,148,137, 55, 14,122, 3,255, 0, 0, 0, 0,191,150,176, 53,
+192,174,252,238,191,226,172, 37,230,114,136,199,217, 20, 3,255, 0, 0, 0, 0,191,214,105,225,192,161,177,211,192, 29,229,160,
+219,197,145,175,202, 38, 3,255, 0, 0, 0, 0,191, 88,213, 62,192,167, 70,193,192, 32,217,212,237,221,141,232,200,230, 3,255,
+ 0, 0, 0, 0,192,130, 97,236, 64, 34,248,181, 64, 87,132, 49,166,239, 55, 72, 73,112, 3,255, 0, 0, 0, 0,192,144,103,186,
+ 63,234, 9, 91, 64, 80,226,150,157,104, 39,135, 71,104, 3,255, 0, 0, 0, 0,192,149, 83,115, 64, 24,118, 25, 64, 41, 5, 96,
+154, 61, 51,195, 57,220, 3,255, 0, 0, 0, 0,192,133,112, 29, 64,104, 45,168, 63,249, 44, 95,165,102, 79,160, 42,208, 3,255,
+ 0, 0, 0, 0,192, 95,193,192, 64,138, 5,221, 63,239,219, 42,179, 75, 93,195, 41, 79, 3,255, 0, 0, 0, 0,192,100,126, 85,
+ 64,114,211,103, 64, 43,176,187,177,196, 83, 15, 57,254, 3,255, 0, 0, 0, 0,191,201,189,110, 64,154, 28, 48, 64, 60,148,180,
+221,254,105, 61, 64,109, 3,255, 0, 0, 0, 0,192, 17, 55, 21, 64,140, 67,125, 64, 75, 8,118,206,195, 95,206, 69, 35, 3,255,
+ 0, 0, 0, 0,192, 12,138, 46, 64,156,168,195, 64, 23,240, 99,208, 84,106,202, 52, 4, 3,255, 0, 0, 0, 0,192,115,101,128,
+ 64,142,100,106, 62,205,174,214,172,224, 96,244, 8,129, 3,255, 0, 0, 0, 0,192,142,250,187, 64,113,123,178, 62,242,120, 90,
+158,157, 82,114, 10, 12, 3,255, 0, 0, 0, 0,192,134, 21, 28, 64,130,231,185,190,133,210,175,164,128, 89, 74,249,223, 3,255,
+ 0, 0, 0, 0, 63,214,105,225, 64,161,177,211, 64, 29,229,160, 36, 59,110, 81, 53,218, 3,255, 0, 0, 0, 0, 63, 88,213, 62,
+ 64,167, 70,193, 64, 32,217,212, 18, 35,114, 24, 55, 26, 3,255, 0, 0, 0, 0, 63,150,176, 53, 64,174,252,238, 63,226,172, 37,
+ 25,142,119, 57, 38,236, 3,255, 0, 0, 0, 0, 64, 22, 41, 24, 64,169,197, 1, 63, 84, 68,191, 51,211,115,151, 18, 84, 3,255,
+ 0, 0, 0, 0, 64, 75,243, 73, 64,156, 16, 86, 63, 33,150,180, 69, 40,106,193, 14, 62, 3,255, 0, 0, 0, 0, 64, 54,112,161,
+ 64,156, 77, 94, 63,196,107,208, 62, 58,106,233, 32,224, 3,255, 0, 0, 0, 0, 64,144, 84, 31, 64, 87, 19, 24, 63,211, 65, 53,
+ 98,182, 73, 8, 36, 32, 3,255, 0, 0, 0, 0, 64,123, 90, 7, 64,121,238,107, 63,247,227,115, 85,234, 84,255, 42, 38, 3,255,
+ 0, 0, 0, 0, 64,136, 74,208, 64,121,117,231, 63,133,193, 32, 93, 8, 84,214, 23, 7, 3,255, 0, 0, 0, 0, 64, 58, 21, 17,
+ 64,160,209,224,191, 88,100,103, 63, 54,109,184,237, 85, 3,255, 0, 0, 0, 0, 64, 4,252,151, 64,174, 89, 71,191, 38, 93,215,
+ 45,108,118,201,241,134, 3,255, 0, 0, 0, 0, 64, 19,246,140, 64,166, 60,148,191,182, 70, 11, 50, 92,113, 97,224,129, 3,255,
+ 0, 0, 0, 0, 64,182,222, 95, 62,161, 32,178, 63,165, 92, 48,124,166, 7, 48, 28, 45, 3,255, 0, 0, 0, 0, 64,179,119, 52,
+ 63,147,204,223, 63,160,141,116,122, 87, 25,143, 27,153, 3,255, 0, 0, 0, 0, 64,185, 52,235, 63, 83,185,191, 62,252,176, 39,
+126, 55, 18, 45, 11, 15, 3,255, 0, 0, 0, 0, 64,186,178, 88,190,226, 33,180,190,165,211, 69,127,103,245,191,249, 60, 3,255,
+ 0, 0, 0, 0, 64,181,194,100,191,178, 37,227,190,191, 51, 65,124, 57,226, 39,248, 55, 3,255, 0, 0, 0, 0, 64,184, 83,241,
+191,117,241, 33, 62,248, 69,204,125,224,235, 11, 9,234, 3,255, 0, 0, 0, 0, 64,157,242, 15,192, 63, 35,177, 63,132,230,242,
+107,141,190,122, 22,217, 3,255, 0, 0, 0, 0, 64,169,163, 58,192, 14,207,184, 63,148, 92, 43,115,134,207, 6, 25, 63, 3,255,
+ 0, 0, 0, 0, 64,167, 26, 30,192, 42, 11, 62, 62,159,163,199,113,211,197,230, 7, 20, 3,255, 0, 0, 0, 0, 64,173,114,185,
+191,162, 11,147,191,237,131,136,118, 52,228,150,215, 69, 3,255, 0, 0, 0, 0, 64,178, 82, 90,190,168, 0,181,191,231, 64,125,
+121,120,248,178,216, 81, 3,255, 0, 0, 0, 0, 64,168, 68,140,191, 57,100,162,192, 31, 41, 90,114,165,240, 61,201, 81, 3,255,
+ 0, 0, 0, 0, 64, 29,140,219,192,163,216,164, 63,187,160,163, 53,254,144,108, 31,229, 3,255, 0, 0, 0, 0, 64, 76, 63, 8,
+192,152, 92,149, 63,157, 6,201, 70, 2,152, 72, 26,231, 3,255, 0, 0, 0, 0, 64, 50,200,107,192,164, 21, 4, 63, 18,252,143,
+ 61, 27,144, 67, 12,198, 3,255, 0, 0, 0, 0, 63,188,166, 29,192,181,120,167, 61,165,224, 4, 31,175,132, 3, 2, 53, 3,255,
+ 0, 0, 0, 0, 63, 9,186, 26,192,186,142,104, 62,126, 74,128, 12, 98,128,187, 5,168, 3,255, 0, 0, 0, 0, 63,145,160,228,
+192,181, 59,121, 63,123,252,246, 24,193,132, 42, 20,214, 3,255, 0, 0, 0, 0,191, 99, 54,226,192,174,134,172, 63,250, 98, 96,
+236, 76,137, 12, 42,242, 3,255, 0, 0, 0, 0,189, 60,195,150,192,177,121, 46, 63,245, 6,174,254,172,135, 7, 41,201, 3,255,
+ 0, 0, 0, 0,191, 35, 88,109,192,182,186,129, 63,152, 8,207,241,251,131,129, 26, 54, 3,255, 0, 0, 0, 0, 62,134,114,163,
+192,183, 94, 81,191,157,210, 73, 5,216,131, 16,228,207, 3,255, 0, 0, 0, 0, 63,151,217,253,192,178, 89, 90,191,178,246,210,
+ 25,167,134,110,225, 69, 3,255, 0, 0, 0, 0, 63, 19,205,179,192,175,145, 33,191,253,151,102, 12,131,136, 85,212, 89, 3,255,
+ 0, 0, 0, 0,192,101,166,116,192,111,107, 67, 64, 47,233, 69,177,233,174, 37, 59,222, 3,255, 0, 0, 0, 0,192, 68, 20,109,
+192,139, 9,202, 64, 29,255,124,189,118,160,234, 53,250, 3,255, 0, 0, 0, 0,192,106,184,230,192,133, 83,117, 63,243, 95, 76,
+176, 54,165, 5, 41,179, 3,255, 0, 0, 0, 0,192,150,177, 40,192, 73,250,101, 63,189,252,104,152,243,187,143, 32,217, 3,255,
+ 0, 0, 0, 0,192,164, 67, 59,192, 19,116,106, 63,209,145, 96,144, 52,205, 33, 36, 1, 3,255, 0, 0, 0, 0,192,148, 31,118,
+192, 46, 99,144, 64, 21,237, 95,154,155,196,115, 50,141, 3,255, 0, 0, 0, 0,192,157, 48,115,191, 33,183, 74, 64, 72,172, 21,
+148,206,242,150, 68,165, 3,255, 0, 0, 0, 0,192,151, 48,250,191,186,157,117, 64, 74, 37,236,152,215,224,130, 68,233, 3,255,
+ 0, 0, 0, 0,192,167, 31,102,191,133,113, 18, 64, 29,150,122,142, 42,233,107, 53,251, 3,255, 0, 0, 0, 0,192,174, 1,225,
+192, 12,167, 65, 62, 38, 1,199,137,107,207,239, 3, 61, 3,255, 0, 0, 0, 0,192,160,156,172,192, 66,121, 23, 60, 53,253,220,
+146,101,189,231, 0, 0, 3,255, 0, 0, 0, 0,192,168, 99, 9,192, 32,173,184,191, 27, 16,129,141, 28,201, 67,242, 92, 3,255,
+ 0, 0, 0, 0,191, 19, 18,220, 64, 98,186,168, 64,148,136, 66,243,101, 77,135,101, 15, 3,255, 0, 0, 0, 0,191, 68,220, 36,
+ 64,132,143, 24, 64,130,105, 20,239, 93, 90,190, 88,184, 3,255, 0, 0, 0, 0,191,185,255, 60, 64,108,244,215, 64,138, 7,129,
+224,143, 80,245, 94, 5, 3,255, 0, 0, 0, 0,191,247,202, 46, 64, 27,140, 23, 64,158,252,116,214, 39, 52,179,108,224, 3,255,
+ 0, 0, 0, 0,191,220, 24,190, 63,202,163,163, 64,171,244,160,218,157, 35, 57,117, 60, 3,255, 0, 0, 0, 0,191,133,219,227,
+ 64, 17, 47,172, 64,169,160, 93,232,130, 49, 92,115,188, 3,255, 0, 0, 0, 0, 62, 50, 45,123, 62,230, 16,213, 64,186,240,160,
+ 4, 25, 9,132,127,147, 3,255, 0, 0, 0, 0, 59,172,119,131, 63,162,209,182, 64,183, 73,170, 0, 47, 27,112,125, 5, 3,255,
+ 0, 0, 0, 0,191, 40,230,165, 63, 24,111,246, 64,185,150, 50,241,237, 12,238,126,143, 3,255, 0, 0, 0, 0,192, 66,225,100,
+ 63,131,191,146, 64,157, 18,152,189, 78, 22,128,106,231, 3,255, 0, 0, 0, 0,192, 80,140, 98, 63,238,205,169, 64,144, 69, 83,
+184,186, 40,111, 98, 83, 3,255, 0, 0, 0, 0,192,109, 39,177, 63,147,213,154, 64,140,143,239,174,199, 25, 9, 95,179, 3,255,
+ 0, 0, 0, 0, 64,128,173,131, 64, 14,170, 50, 64,105, 71,247, 87,226, 48,192, 79, 67, 3,255, 0, 0, 0, 0, 64,140,137,202,
+ 64, 33,234, 4, 64, 60,117,152, 96, 41, 55, 40, 63,250, 3,255, 0, 0, 0, 0, 64,115,176, 68, 64, 68, 49, 85, 64, 79,173, 65,
+ 83, 78, 66,175, 70,175, 3,255, 0, 0, 0, 0, 64, 39, 23, 51, 64, 76,245, 14, 64,132,248,105, 56,227, 69,119, 91, 56, 3,255,
+ 0, 0, 0, 0, 63,254, 75,122, 64, 50, 36, 17, 64,152, 70, 83, 44, 3, 60,210,103,169, 3,255, 0, 0, 0, 0, 64, 52,239,190,
+ 64, 22,186,193, 64,145,240,166, 61, 89, 51,253, 99,148, 3,255, 0, 0, 0, 0, 63,213,244,249, 63, 52, 33, 10, 64,178, 94,248,
+ 36, 84, 14,253,121,208, 3,255, 0, 0, 0, 0, 64, 22, 80,230, 63,141,155, 50, 64,168, 95,108, 50,253, 23,250,114,237, 3,255,
+ 0, 0, 0, 0, 63,194,113, 96, 63,195,184,166, 64,174,160, 31, 33, 51, 33, 11,119, 29, 3,255, 0, 0, 0, 0, 63,112,119,228,
+ 64,115, 46, 49, 64,139,222,186, 20,104, 83, 35, 95, 40, 3,255, 0, 0, 0, 0, 63,199, 22,221, 64,134,211, 71, 64,113,161, 37,
+ 33,158, 92, 1, 82, 99, 3,255, 0, 0, 0, 0, 63, 58,131,170, 64,140,178, 58, 64,115,174,213, 15,151, 96, 55, 82,245, 3,255,
+ 0, 0, 0, 0, 64,132,134,116,192, 40,130, 40, 64, 77,207,237, 90,117,198,107, 69,226, 3,255, 0, 0, 0, 0, 64,140,187,232,
+192, 62, 96, 6, 64, 30,247,107, 95,249,190,188, 53,245, 3,255, 0, 0, 0, 0, 64,152, 61, 37,192, 14, 9,230, 64, 39,179,137,
+103,171,207, 73, 57, 30, 3,255, 0, 0, 0, 0, 64,149,121,189,191,111,192,142, 64, 90, 95, 76,101,161,235,149, 75, 20, 3,255,
+ 0, 0, 0, 0, 64,134,112,254,190,207,146,126, 64,130, 19,159, 91,241,246,137, 88,139, 3,255, 0, 0, 0, 0, 64,129,129, 12,
+191,173,129,231, 64,128,125,159, 88,194,226,241, 87,133, 3,255, 0, 0, 0, 0, 64, 22,104,220,191, 40,221,204, 64,170,137,115,
+ 50,240,241,167,116,139, 3,255, 0, 0, 0, 0, 64, 56,120,245,191,154,213,118, 64,158,227, 81, 62,175,229,209,108,123, 3,255,
+ 0, 0, 0, 0, 64, 66, 56, 52,190,139, 40,206, 64,160,116, 21, 65,243,249,237,109,135, 3,255, 0, 0, 0, 0, 64,150,161, 61,
+ 63, 89,221,107, 64, 89,113,118,102,216, 18,177, 73,221, 3,255, 0, 0, 0, 0, 64,165,120, 74, 62,167, 78, 95, 64, 48, 51,139,
+112,202, 7,116, 60, 12, 3,255, 0, 0, 0, 0, 64,162, 65, 12, 63,149, 84, 11, 64, 44,202,172,110,196, 25,209, 58,181, 3,255,
+ 0, 0, 0, 0,190,194,138, 67,192,138, 97,177, 64,124,158, 75,247,144,161,122, 85,227, 3,255, 0, 0, 0, 0,191, 66, 82,214,
+192,152,115,128, 64, 85, 25,164,239, 15,151,229, 72,130, 3,255, 0, 0, 0, 0, 61,171,155,119,192,155, 40,138, 64, 83, 96,113,
+ 1,128,150, 60, 72, 18, 3,255, 0, 0, 0, 0, 63,178,237,144,192,136,136, 25, 64,113, 1,121, 30,139,163, 67, 82,194, 3,255,
+ 0, 0, 0, 0, 63,238,147, 68,192,100,230,166, 64,136, 9,234, 40, 40,177,126, 92,197, 3,255, 0, 0, 0, 0, 63,109,149, 30,
+192,111, 18, 40, 64,141,100,171, 20,219,174, 55, 96, 57, 3,255, 0, 0, 0, 0, 63,162,210, 45,191,224,211,233, 64,174, 67,184,
+ 27,187,218, 11,119, 12, 3,255, 0, 0, 0, 0, 63, 94,106,158,192, 30,106,167, 64,167,240,254, 19, 27,202, 69,114,151, 3,255,
+ 0, 0, 0, 0, 63,229,114, 22,192, 20, 96,193, 64,162,167,253, 38,234,205,163,111, 12, 3,255, 0, 0, 0, 0, 64, 67, 76,208,
+192,111,120, 62, 64, 85, 89, 14, 66,176,174, 60, 72,116, 3,255, 0, 0, 0, 0, 64, 37,220,139,192,141,135,245, 64, 54,173,114,
+ 56,211,159,161, 62, 45, 3,255, 0, 0, 0, 0, 64, 84,119,204,192,130, 73, 93, 64, 38,107,212, 72,198,167, 33, 56,119, 3,255,
+ 0, 0, 0, 0,192, 82,218,178,191, 1,247,178, 64,154,129,211,183,221,244,252,105, 39, 3,255, 0, 0, 0, 0,192,124,245, 0,
+190,187, 32, 27, 64,138, 6, 57,169,118,248, 80, 93,254, 3,255, 0, 0, 0, 0,192,112, 75, 42,191,152, 42,228, 64,139, 44, 25,
+174, 0,230, 97, 94,225, 3,255, 0, 0, 0, 0,192, 43,222,239,192, 11,226,212, 64,151, 71,227,197,223,208,116,103,165, 3,255,
+ 0, 0, 0, 0,191,229,207,137,192, 22, 63, 30, 64,161,235,207,216, 58,205, 29,110,129, 3,255, 0, 0, 0, 0,192, 14, 11,239,
+191,191,114,175, 64,166,208,254,207,123,222,175,113,169, 3,255, 0, 0, 0, 0,189,149, 78,163,191,137, 25, 65, 64,184,102,234,
+254,202,232,204,125,222, 3,255, 0, 0, 0, 0,191,104,203,208,191,113, 6,146, 64,183, 5,108,236,124,235,106,124,207, 3,255,
+ 0, 0, 0, 0,190,251, 68, 26,191,228, 38,111, 64,178, 48,114,245,117,217, 98,121,147, 3,255, 0, 0, 0, 0,191,222,169, 76,
+192,104,107,205, 64,136,142,150,217,233,176,151, 92,223, 3,255, 0, 0, 0, 0,192, 39,143,145,192, 94, 49,190, 64,124, 27,165,
+199, 18,180, 4, 85,213, 3,255, 0, 0, 0, 0,192, 6,168,130,192,130,132,190, 64,105, 96, 12,210, 30,166,165, 79, 83, 3,255,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,151,128, 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,118,112, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 90, 0, 12,118,112, 32, 0, 0, 0, 55, 0, 0, 7,128, 0, 0, 0, 0, 0, 0, 0,162,
+ 0, 0, 0, 35, 0, 0, 0, 42, 0, 0, 0,162, 0, 0, 0, 35, 0, 0, 0, 12, 0, 0, 0,163, 0, 0, 0, 35, 0, 0, 0, 42,
+ 0, 0, 0,163, 0, 0, 0, 35, 0, 0, 0, 1, 0, 0, 0,164, 0, 0, 0, 35, 0, 0, 0, 43, 0, 0, 0,164, 0, 0, 0, 35,
+ 0, 0, 0, 12, 0, 0, 0,165, 0, 0, 0, 35, 0, 0, 0, 43, 0, 0, 0,165, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0,166,
+ 0, 0, 0, 35, 0, 0, 0, 44, 0, 0, 0,166, 0, 0, 0, 35, 0, 0, 0, 13, 0, 0, 0,167, 0, 0, 0, 35, 0, 0, 0, 44,
+ 0, 0, 0,167, 0, 0, 0, 35, 0, 0, 0, 2, 0, 0, 0,168, 0, 0, 0, 35, 0, 0, 0, 45, 0, 0, 0,168, 0, 0, 0, 35,
+ 0, 0, 0, 13, 0, 0, 0,169, 0, 0, 0, 35, 0, 0, 0, 45, 0, 0, 0,169, 0, 0, 0, 35, 0, 0, 0, 1, 0, 0, 0,170,
+ 0, 0, 0, 35, 0, 0, 0, 46, 0, 0, 0,170, 0, 0, 0, 35, 0, 0, 0, 14, 0, 0, 0,171, 0, 0, 0, 35, 0, 0, 0, 46,
+ 0, 0, 0,171, 0, 0, 0, 35, 0, 0, 0, 2, 0, 0, 0,172, 0, 0, 0, 35, 0, 0, 0, 47, 0, 0, 0,172, 0, 0, 0, 35,
+ 0, 0, 0, 14, 0, 0, 0,173, 0, 0, 0, 35, 0, 0, 0, 47, 0, 0, 0,173, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0,174,
+ 0, 0, 0, 35, 0, 0, 0, 48, 0, 0, 0,174, 0, 0, 0, 35, 0, 0, 0, 15, 0, 0, 0,175, 0, 0, 0, 35, 0, 0, 0, 48,
+ 0, 0, 0,175, 0, 0, 0, 35, 0, 0, 0, 5, 0, 0, 0,176, 0, 0, 0, 35, 0, 0, 0, 49, 0, 0, 0,176, 0, 0, 0, 35,
+ 0, 0, 0, 15, 0, 0, 0,177, 0, 0, 0, 35, 0, 0, 0, 49, 0, 0, 0,177, 0, 0, 0, 35, 0, 0, 0, 1, 0, 0, 0,178,
+ 0, 0, 0, 35, 0, 0, 0, 50, 0, 0, 0,178, 0, 0, 0, 35, 0, 0, 0, 16, 0, 0, 0,179, 0, 0, 0, 35, 0, 0, 0, 50,
+ 0, 0, 0,179, 0, 0, 0, 35, 0, 0, 0, 5, 0, 0, 0,180, 0, 0, 0, 35, 0, 0, 0, 51, 0, 0, 0,180, 0, 0, 0, 35,
+ 0, 0, 0, 16, 0, 0, 0,181, 0, 0, 0, 35, 0, 0, 0, 51, 0, 0, 0,181, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0,182,
+ 0, 0, 0, 35, 0, 0, 0, 52, 0, 0, 0,182, 0, 0, 0, 35, 0, 0, 0, 17, 0, 0, 0,183, 0, 0, 0, 35, 0, 0, 0, 52,
+ 0, 0, 0,183, 0, 0, 0, 35, 0, 0, 0, 3, 0, 0, 0,184, 0, 0, 0, 35, 0, 0, 0, 53, 0, 0, 0,184, 0, 0, 0, 35,
+ 0, 0, 0, 17, 0, 0, 0,185, 0, 0, 0, 35, 0, 0, 0, 53, 0, 0, 0,185, 0, 0, 0, 35, 0, 0, 0, 2, 0, 0, 0,186,
+ 0, 0, 0, 35, 0, 0, 0, 54, 0, 0, 0,186, 0, 0, 0, 35, 0, 0, 0, 18, 0, 0, 0,187, 0, 0, 0, 35, 0, 0, 0, 54,
+ 0, 0, 0,187, 0, 0, 0, 35, 0, 0, 0, 3, 0, 0, 0,188, 0, 0, 0, 35, 0, 0, 0, 55, 0, 0, 0,188, 0, 0, 0, 35,
+ 0, 0, 0, 18, 0, 0, 0,189, 0, 0, 0, 35, 0, 0, 0, 55, 0, 0, 0,189, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0,190,
+ 0, 0, 0, 35, 0, 0, 0, 56, 0, 0, 0,190, 0, 0, 0, 35, 0, 0, 0, 19, 0, 0, 0,191, 0, 0, 0, 35, 0, 0, 0, 56,
+ 0, 0, 0,191, 0, 0, 0, 35, 0, 0, 0, 4, 0, 0, 0,192, 0, 0, 0, 35, 0, 0, 0, 57, 0, 0, 0,192, 0, 0, 0, 35,
+ 0, 0, 0, 19, 0, 0, 0,193, 0, 0, 0, 35, 0, 0, 0, 57, 0, 0, 0,193, 0, 0, 0, 35, 0, 0, 0, 3, 0, 0, 0,194,
+ 0, 0, 0, 35, 0, 0, 0, 58, 0, 0, 0,194, 0, 0, 0, 35, 0, 0, 0, 20, 0, 0, 0,195, 0, 0, 0, 35, 0, 0, 0, 58,
+ 0, 0, 0,195, 0, 0, 0, 35, 0, 0, 0, 4, 0, 0, 0,196, 0, 0, 0, 35, 0, 0, 0, 59, 0, 0, 0,196, 0, 0, 0, 35,
+ 0, 0, 0, 20, 0, 0, 0,197, 0, 0, 0, 35, 0, 0, 0, 59, 0, 0, 0,197, 0, 0, 0, 35, 0, 0, 0, 4, 0, 0, 0,198,
+ 0, 0, 0, 35, 0, 0, 0, 60, 0, 0, 0,198, 0, 0, 0, 35, 0, 0, 0, 21, 0, 0, 0,199, 0, 0, 0, 35, 0, 0, 0, 60,
+ 0, 0, 0,199, 0, 0, 0, 35, 0, 0, 0, 5, 0, 0, 0,200, 0, 0, 0, 35, 0, 0, 0, 61, 0, 0, 0,200, 0, 0, 0, 35,
+ 0, 0, 0, 21, 0, 0, 0,201, 0, 0, 0, 35, 0, 0, 0, 61, 0, 0, 0,201, 0, 0, 0, 35, 0, 0, 0, 5, 0, 0, 0,202,
+ 0, 0, 0, 35, 0, 0, 0, 62, 0, 0, 0,202, 0, 0, 0, 35, 0, 0, 0, 22, 0, 0, 0,203, 0, 0, 0, 35, 0, 0, 0, 62,
+ 0, 0, 0,203, 0, 0, 0, 35, 0, 0, 0, 10, 0, 0, 0,204, 0, 0, 0, 35, 0, 0, 0, 63, 0, 0, 0,204, 0, 0, 0, 35,
+ 0, 0, 0, 22, 0, 0, 0,205, 0, 0, 0, 35, 0, 0, 0, 63, 0, 0, 0,205, 0, 0, 0, 35, 0, 0, 0, 1, 0, 0, 0,206,
+ 0, 0, 0, 35, 0, 0, 0, 64, 0, 0, 0,206, 0, 0, 0, 35, 0, 0, 0, 23, 0, 0, 0,207, 0, 0, 0, 35, 0, 0, 0, 64,
+ 0, 0, 0,207, 0, 0, 0, 35, 0, 0, 0, 10, 0, 0, 0,208, 0, 0, 0, 35, 0, 0, 0, 65, 0, 0, 0,208, 0, 0, 0, 35,
+ 0, 0, 0, 23, 0, 0, 0,209, 0, 0, 0, 35, 0, 0, 0, 65, 0, 0, 0,209, 0, 0, 0, 35, 0, 0, 0, 1, 0, 0, 0,210,
+ 0, 0, 0, 35, 0, 0, 0, 66, 0, 0, 0,210, 0, 0, 0, 35, 0, 0, 0, 24, 0, 0, 0,211, 0, 0, 0, 35, 0, 0, 0, 66,
+ 0, 0, 0,211, 0, 0, 0, 35, 0, 0, 0, 6, 0, 0, 0,212, 0, 0, 0, 35, 0, 0, 0, 67, 0, 0, 0,212, 0, 0, 0, 35,
+ 0, 0, 0, 24, 0, 0, 0,213, 0, 0, 0, 35, 0, 0, 0, 67, 0, 0, 0,213, 0, 0, 0, 35, 0, 0, 0, 2, 0, 0, 0,214,
+ 0, 0, 0, 35, 0, 0, 0, 68, 0, 0, 0,214, 0, 0, 0, 35, 0, 0, 0, 25, 0, 0, 0,215, 0, 0, 0, 35, 0, 0, 0, 68,
+ 0, 0, 0,215, 0, 0, 0, 35, 0, 0, 0, 6, 0, 0, 0,216, 0, 0, 0, 35, 0, 0, 0, 69, 0, 0, 0,216, 0, 0, 0, 35,
+ 0, 0, 0, 25, 0, 0, 0,217, 0, 0, 0, 35, 0, 0, 0, 69, 0, 0, 0,217, 0, 0, 0, 35, 0, 0, 0, 2, 0, 0, 0,218,
+ 0, 0, 0, 35, 0, 0, 0, 70, 0, 0, 0,218, 0, 0, 0, 35, 0, 0, 0, 26, 0, 0, 0,219, 0, 0, 0, 35, 0, 0, 0, 70,
+ 0, 0, 0,219, 0, 0, 0, 35, 0, 0, 0, 7, 0, 0, 0,220, 0, 0, 0, 35, 0, 0, 0, 71, 0, 0, 0,220, 0, 0, 0, 35,
+ 0, 0, 0, 26, 0, 0, 0,221, 0, 0, 0, 35, 0, 0, 0, 71, 0, 0, 0,221, 0, 0, 0, 35, 0, 0, 0, 3, 0, 0, 0,222,
+ 0, 0, 0, 35, 0, 0, 0, 72, 0, 0, 0,222, 0, 0, 0, 35, 0, 0, 0, 27, 0, 0, 0,223, 0, 0, 0, 35, 0, 0, 0, 72,
+ 0, 0, 0,223, 0, 0, 0, 35, 0, 0, 0, 7, 0, 0, 0,224, 0, 0, 0, 35, 0, 0, 0, 73, 0, 0, 0,224, 0, 0, 0, 35,
+ 0, 0, 0, 27, 0, 0, 0,225, 0, 0, 0, 35, 0, 0, 0, 73, 0, 0, 0,225, 0, 0, 0, 35, 0, 0, 0, 3, 0, 0, 0,226,
+ 0, 0, 0, 35, 0, 0, 0, 74, 0, 0, 0,226, 0, 0, 0, 35, 0, 0, 0, 28, 0, 0, 0,227, 0, 0, 0, 35, 0, 0, 0, 74,
+ 0, 0, 0,227, 0, 0, 0, 35, 0, 0, 0, 8, 0, 0, 0,228, 0, 0, 0, 35, 0, 0, 0, 75, 0, 0, 0,228, 0, 0, 0, 35,
+ 0, 0, 0, 28, 0, 0, 0,229, 0, 0, 0, 35, 0, 0, 0, 75, 0, 0, 0,229, 0, 0, 0, 35, 0, 0, 0, 4, 0, 0, 0,230,
+ 0, 0, 0, 35, 0, 0, 0, 76, 0, 0, 0,230, 0, 0, 0, 35, 0, 0, 0, 29, 0, 0, 0,231, 0, 0, 0, 35, 0, 0, 0, 76,
+ 0, 0, 0,231, 0, 0, 0, 35, 0, 0, 0, 8, 0, 0, 0,232, 0, 0, 0, 35, 0, 0, 0, 77, 0, 0, 0,232, 0, 0, 0, 35,
+ 0, 0, 0, 29, 0, 0, 0,233, 0, 0, 0, 35, 0, 0, 0, 77, 0, 0, 0,233, 0, 0, 0, 35, 0, 0, 0, 4, 0, 0, 0,234,
+ 0, 0, 0, 35, 0, 0, 0, 78, 0, 0, 0,234, 0, 0, 0, 35, 0, 0, 0, 30, 0, 0, 0,235, 0, 0, 0, 35, 0, 0, 0, 78,
+ 0, 0, 0,235, 0, 0, 0, 35, 0, 0, 0, 9, 0, 0, 0,236, 0, 0, 0, 35, 0, 0, 0, 79, 0, 0, 0,236, 0, 0, 0, 35,
+ 0, 0, 0, 30, 0, 0, 0,237, 0, 0, 0, 35, 0, 0, 0, 79, 0, 0, 0,237, 0, 0, 0, 35, 0, 0, 0, 5, 0, 0, 0,238,
+ 0, 0, 0, 35, 0, 0, 0, 80, 0, 0, 0,238, 0, 0, 0, 35, 0, 0, 0, 31, 0, 0, 0,239, 0, 0, 0, 35, 0, 0, 0, 80,
+ 0, 0, 0,239, 0, 0, 0, 35, 0, 0, 0, 9, 0, 0, 0,240, 0, 0, 0, 35, 0, 0, 0, 81, 0, 0, 0,240, 0, 0, 0, 35,
+ 0, 0, 0, 31, 0, 0, 0,241, 0, 0, 0, 35, 0, 0, 0, 81, 0, 0, 0,241, 0, 0, 0, 35, 0, 0, 0, 6, 0, 0, 0,242,
+ 0, 0, 0, 35, 0, 0, 0, 82, 0, 0, 0,242, 0, 0, 0, 35, 0, 0, 0, 32, 0, 0, 0,243, 0, 0, 0, 35, 0, 0, 0, 82,
+ 0, 0, 0,243, 0, 0, 0, 35, 0, 0, 0, 10, 0, 0, 0,244, 0, 0, 0, 35, 0, 0, 0, 83, 0, 0, 0,244, 0, 0, 0, 35,
+ 0, 0, 0, 32, 0, 0, 0,245, 0, 0, 0, 35, 0, 0, 0, 83, 0, 0, 0,245, 0, 0, 0, 35, 0, 0, 0, 6, 0, 0, 0,246,
+ 0, 0, 0, 35, 0, 0, 0, 84, 0, 0, 0,246, 0, 0, 0, 35, 0, 0, 0, 33, 0, 0, 0,247, 0, 0, 0, 35, 0, 0, 0, 84,
+ 0, 0, 0,247, 0, 0, 0, 35, 0, 0, 0, 7, 0, 0, 0,248, 0, 0, 0, 35, 0, 0, 0, 85, 0, 0, 0,248, 0, 0, 0, 35,
+ 0, 0, 0, 33, 0, 0, 0,249, 0, 0, 0, 35, 0, 0, 0, 85, 0, 0, 0,249, 0, 0, 0, 35, 0, 0, 0, 7, 0, 0, 0,250,
+ 0, 0, 0, 35, 0, 0, 0, 86, 0, 0, 0,250, 0, 0, 0, 35, 0, 0, 0, 34, 0, 0, 0,251, 0, 0, 0, 35, 0, 0, 0, 86,
+ 0, 0, 0,251, 0, 0, 0, 35, 0, 0, 0, 8, 0, 0, 0,252, 0, 0, 0, 35, 0, 0, 0, 87, 0, 0, 0,252, 0, 0, 0, 35,
+ 0, 0, 0, 34, 0, 0, 0,253, 0, 0, 0, 35, 0, 0, 0, 87, 0, 0, 0,253, 0, 0, 0, 35, 0, 0, 0, 8, 0, 0, 0,254,
+ 0, 0, 0, 35, 0, 0, 0, 88, 0, 0, 0,254, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0,255, 0, 0, 0, 35, 0, 0, 0, 88,
+ 0, 0, 0,255, 0, 0, 0, 35, 0, 0, 0, 9, 0, 0, 1, 0, 0, 0, 0, 35, 0, 0, 0, 89, 0, 0, 1, 0, 0, 0, 0, 35,
+ 0, 0, 0, 35, 0, 0, 1, 1, 0, 0, 0, 35, 0, 0, 0, 89, 0, 0, 1, 1, 0, 0, 0, 35, 0, 0, 0, 9, 0, 0, 1, 2,
+ 0, 0, 0, 35, 0, 0, 0, 90, 0, 0, 1, 2, 0, 0, 0, 35, 0, 0, 0, 36, 0, 0, 1, 3, 0, 0, 0, 35, 0, 0, 0, 90,
+ 0, 0, 1, 3, 0, 0, 0, 35, 0, 0, 0, 10, 0, 0, 1, 4, 0, 0, 0, 35, 0, 0, 0, 91, 0, 0, 1, 4, 0, 0, 0, 35,
+ 0, 0, 0, 36, 0, 0, 1, 5, 0, 0, 0, 35, 0, 0, 0, 91, 0, 0, 1, 5, 0, 0, 0, 35, 0, 0, 0, 10, 0, 0, 1, 6,
+ 0, 0, 0, 35, 0, 0, 0, 92, 0, 0, 1, 6, 0, 0, 0, 35, 0, 0, 0, 37, 0, 0, 1, 7, 0, 0, 0, 35, 0, 0, 0, 92,
+ 0, 0, 1, 7, 0, 0, 0, 35, 0, 0, 0, 11, 0, 0, 1, 8, 0, 0, 0, 35, 0, 0, 0, 93, 0, 0, 1, 8, 0, 0, 0, 35,
+ 0, 0, 0, 37, 0, 0, 1, 9, 0, 0, 0, 35, 0, 0, 0, 93, 0, 0, 1, 9, 0, 0, 0, 35, 0, 0, 0, 6, 0, 0, 1, 10,
+ 0, 0, 0, 35, 0, 0, 0, 94, 0, 0, 1, 10, 0, 0, 0, 35, 0, 0, 0, 38, 0, 0, 1, 11, 0, 0, 0, 35, 0, 0, 0, 94,
+ 0, 0, 1, 11, 0, 0, 0, 35, 0, 0, 0, 11, 0, 0, 1, 12, 0, 0, 0, 35, 0, 0, 0, 95, 0, 0, 1, 12, 0, 0, 0, 35,
+ 0, 0, 0, 38, 0, 0, 1, 13, 0, 0, 0, 35, 0, 0, 0, 95, 0, 0, 1, 13, 0, 0, 0, 35, 0, 0, 0, 7, 0, 0, 1, 14,
+ 0, 0, 0, 35, 0, 0, 0, 96, 0, 0, 1, 14, 0, 0, 0, 35, 0, 0, 0, 39, 0, 0, 1, 15, 0, 0, 0, 35, 0, 0, 0, 96,
+ 0, 0, 1, 15, 0, 0, 0, 35, 0, 0, 0, 11, 0, 0, 1, 16, 0, 0, 0, 35, 0, 0, 0, 97, 0, 0, 1, 16, 0, 0, 0, 35,
+ 0, 0, 0, 39, 0, 0, 1, 17, 0, 0, 0, 35, 0, 0, 0, 97, 0, 0, 1, 17, 0, 0, 0, 35, 0, 0, 0, 8, 0, 0, 1, 18,
+ 0, 0, 0, 35, 0, 0, 0, 98, 0, 0, 1, 18, 0, 0, 0, 35, 0, 0, 0, 40, 0, 0, 1, 19, 0, 0, 0, 35, 0, 0, 0, 98,
+ 0, 0, 1, 19, 0, 0, 0, 35, 0, 0, 0, 11, 0, 0, 1, 20, 0, 0, 0, 35, 0, 0, 0, 99, 0, 0, 1, 20, 0, 0, 0, 35,
+ 0, 0, 0, 40, 0, 0, 1, 21, 0, 0, 0, 35, 0, 0, 0, 99, 0, 0, 1, 21, 0, 0, 0, 35, 0, 0, 0, 9, 0, 0, 1, 22,
+ 0, 0, 0, 35, 0, 0, 0,100, 0, 0, 1, 22, 0, 0, 0, 35, 0, 0, 0, 41, 0, 0, 1, 23, 0, 0, 0, 35, 0, 0, 0,100,
+ 0, 0, 1, 23, 0, 0, 0, 35, 0, 0, 0, 11, 0, 0, 1, 24, 0, 0, 0, 35, 0, 0, 0,101, 0, 0, 1, 24, 0, 0, 0, 35,
+ 0, 0, 0, 41, 0, 0, 1, 25, 0, 0, 0, 35, 0, 0, 0,101, 0, 0, 1, 25, 0, 0, 0, 35, 0, 0, 0, 12, 0, 0, 1, 26,
+ 0, 0, 0, 35, 0, 0, 0,102, 0, 0, 1, 26, 0, 0, 0, 35, 0, 0, 0, 14, 0, 0, 1, 27, 0, 0, 0, 35, 0, 0, 0,102,
+ 0, 0, 1, 27, 0, 0, 0, 35, 0, 0, 0, 12, 0, 0, 1, 28, 0, 0, 0, 35, 0, 0, 0,103, 0, 0, 1, 28, 0, 0, 0, 35,
+ 0, 0, 0, 13, 0, 0, 1, 29, 0, 0, 0, 35, 0, 0, 0,103, 0, 0, 1, 29, 0, 0, 0, 35, 0, 0, 0, 13, 0, 0, 1, 30,
+ 0, 0, 0, 35, 0, 0, 0,104, 0, 0, 1, 30, 0, 0, 0, 35, 0, 0, 0, 14, 0, 0, 1, 31, 0, 0, 0, 35, 0, 0, 0,104,
+ 0, 0, 1, 31, 0, 0, 0, 35, 0, 0, 0, 12, 0, 0, 1, 32, 0, 0, 0, 35, 0, 0, 0,105, 0, 0, 1, 32, 0, 0, 0, 35,
+ 0, 0, 0, 16, 0, 0, 1, 33, 0, 0, 0, 35, 0, 0, 0,105, 0, 0, 1, 33, 0, 0, 0, 35, 0, 0, 0, 12, 0, 0, 1, 34,
+ 0, 0, 0, 35, 0, 0, 0,106, 0, 0, 1, 34, 0, 0, 0, 35, 0, 0, 0, 15, 0, 0, 1, 35, 0, 0, 0, 35, 0, 0, 0,106,
+ 0, 0, 1, 35, 0, 0, 0, 35, 0, 0, 0, 15, 0, 0, 1, 36, 0, 0, 0, 35, 0, 0, 0,107, 0, 0, 1, 36, 0, 0, 0, 35,
+ 0, 0, 0, 16, 0, 0, 1, 37, 0, 0, 0, 35, 0, 0, 0,107, 0, 0, 1, 37, 0, 0, 0, 35, 0, 0, 0, 13, 0, 0, 1, 38,
+ 0, 0, 0, 35, 0, 0, 0,108, 0, 0, 1, 38, 0, 0, 0, 35, 0, 0, 0, 18, 0, 0, 1, 39, 0, 0, 0, 35, 0, 0, 0,108,
+ 0, 0, 1, 39, 0, 0, 0, 35, 0, 0, 0, 13, 0, 0, 1, 40, 0, 0, 0, 35, 0, 0, 0,109, 0, 0, 1, 40, 0, 0, 0, 35,
+ 0, 0, 0, 17, 0, 0, 1, 41, 0, 0, 0, 35, 0, 0, 0,109, 0, 0, 1, 41, 0, 0, 0, 35, 0, 0, 0, 17, 0, 0, 1, 42,
+ 0, 0, 0, 35, 0, 0, 0,110, 0, 0, 1, 42, 0, 0, 0, 35, 0, 0, 0, 18, 0, 0, 1, 43, 0, 0, 0, 35, 0, 0, 0,110,
+ 0, 0, 1, 43, 0, 0, 0, 35, 0, 0, 0, 17, 0, 0, 1, 44, 0, 0, 0, 35, 0, 0, 0,111, 0, 0, 1, 44, 0, 0, 0, 35,
+ 0, 0, 0, 20, 0, 0, 1, 45, 0, 0, 0, 35, 0, 0, 0,111, 0, 0, 1, 45, 0, 0, 0, 35, 0, 0, 0, 17, 0, 0, 1, 46,
+ 0, 0, 0, 35, 0, 0, 0,112, 0, 0, 1, 46, 0, 0, 0, 35, 0, 0, 0, 19, 0, 0, 1, 47, 0, 0, 0, 35, 0, 0, 0,112,
+ 0, 0, 1, 47, 0, 0, 0, 35, 0, 0, 0, 19, 0, 0, 1, 48, 0, 0, 0, 35, 0, 0, 0,113, 0, 0, 1, 48, 0, 0, 0, 35,
+ 0, 0, 0, 20, 0, 0, 1, 49, 0, 0, 0, 35, 0, 0, 0,113, 0, 0, 1, 49, 0, 0, 0, 35, 0, 0, 0, 19, 0, 0, 1, 50,
+ 0, 0, 0, 35, 0, 0, 0,114, 0, 0, 1, 50, 0, 0, 0, 35, 0, 0, 0, 21, 0, 0, 1, 51, 0, 0, 0, 35, 0, 0, 0,114,
+ 0, 0, 1, 51, 0, 0, 0, 35, 0, 0, 0, 15, 0, 0, 1, 52, 0, 0, 0, 35, 0, 0, 0,115, 0, 0, 1, 52, 0, 0, 0, 35,
+ 0, 0, 0, 19, 0, 0, 1, 53, 0, 0, 0, 35, 0, 0, 0,115, 0, 0, 1, 53, 0, 0, 0, 35, 0, 0, 0, 15, 0, 0, 1, 54,
+ 0, 0, 0, 35, 0, 0, 0,116, 0, 0, 1, 54, 0, 0, 0, 35, 0, 0, 0, 21, 0, 0, 1, 55, 0, 0, 0, 35, 0, 0, 0,116,
+ 0, 0, 1, 55, 0, 0, 0, 35, 0, 0, 0, 16, 0, 0, 1, 56, 0, 0, 0, 35, 0, 0, 0,117, 0, 0, 1, 56, 0, 0, 0, 35,
+ 0, 0, 0, 23, 0, 0, 1, 57, 0, 0, 0, 35, 0, 0, 0,117, 0, 0, 1, 57, 0, 0, 0, 35, 0, 0, 0, 16, 0, 0, 1, 58,
+ 0, 0, 0, 35, 0, 0, 0,118, 0, 0, 1, 58, 0, 0, 0, 35, 0, 0, 0, 22, 0, 0, 1, 59, 0, 0, 0, 35, 0, 0, 0,118,
+ 0, 0, 1, 59, 0, 0, 0, 35, 0, 0, 0, 22, 0, 0, 1, 60, 0, 0, 0, 35, 0, 0, 0,119, 0, 0, 1, 60, 0, 0, 0, 35,
+ 0, 0, 0, 23, 0, 0, 1, 61, 0, 0, 0, 35, 0, 0, 0,119, 0, 0, 1, 61, 0, 0, 0, 35, 0, 0, 0, 14, 0, 0, 1, 62,
+ 0, 0, 0, 35, 0, 0, 0,120, 0, 0, 1, 62, 0, 0, 0, 35, 0, 0, 0, 25, 0, 0, 1, 63, 0, 0, 0, 35, 0, 0, 0,120,
+ 0, 0, 1, 63, 0, 0, 0, 35, 0, 0, 0, 14, 0, 0, 1, 64, 0, 0, 0, 35, 0, 0, 0,121, 0, 0, 1, 64, 0, 0, 0, 35,
+ 0, 0, 0, 24, 0, 0, 1, 65, 0, 0, 0, 35, 0, 0, 0,121, 0, 0, 1, 65, 0, 0, 0, 35, 0, 0, 0, 24, 0, 0, 1, 66,
+ 0, 0, 0, 35, 0, 0, 0,122, 0, 0, 1, 66, 0, 0, 0, 35, 0, 0, 0, 25, 0, 0, 1, 67, 0, 0, 0, 35, 0, 0, 0,122,
+ 0, 0, 1, 67, 0, 0, 0, 35, 0, 0, 0, 18, 0, 0, 1, 68, 0, 0, 0, 35, 0, 0, 0,123, 0, 0, 1, 68, 0, 0, 0, 35,
+ 0, 0, 0, 27, 0, 0, 1, 69, 0, 0, 0, 35, 0, 0, 0,123, 0, 0, 1, 69, 0, 0, 0, 35, 0, 0, 0, 18, 0, 0, 1, 70,
+ 0, 0, 0, 35, 0, 0, 0,124, 0, 0, 1, 70, 0, 0, 0, 35, 0, 0, 0, 26, 0, 0, 1, 71, 0, 0, 0, 35, 0, 0, 0,124,
+ 0, 0, 1, 71, 0, 0, 0, 35, 0, 0, 0, 26, 0, 0, 1, 72, 0, 0, 0, 35, 0, 0, 0,125, 0, 0, 1, 72, 0, 0, 0, 35,
+ 0, 0, 0, 27, 0, 0, 1, 73, 0, 0, 0, 35, 0, 0, 0,125, 0, 0, 1, 73, 0, 0, 0, 35, 0, 0, 0, 20, 0, 0, 1, 74,
+ 0, 0, 0, 35, 0, 0, 0,126, 0, 0, 1, 74, 0, 0, 0, 35, 0, 0, 0, 29, 0, 0, 1, 75, 0, 0, 0, 35, 0, 0, 0,126,
+ 0, 0, 1, 75, 0, 0, 0, 35, 0, 0, 0, 20, 0, 0, 1, 76, 0, 0, 0, 35, 0, 0, 0,127, 0, 0, 1, 76, 0, 0, 0, 35,
+ 0, 0, 0, 28, 0, 0, 1, 77, 0, 0, 0, 35, 0, 0, 0,127, 0, 0, 1, 77, 0, 0, 0, 35, 0, 0, 0, 28, 0, 0, 1, 78,
+ 0, 0, 0, 35, 0, 0, 0,128, 0, 0, 1, 78, 0, 0, 0, 35, 0, 0, 0, 29, 0, 0, 1, 79, 0, 0, 0, 35, 0, 0, 0,128,
+ 0, 0, 1, 79, 0, 0, 0, 35, 0, 0, 0, 21, 0, 0, 1, 80, 0, 0, 0, 35, 0, 0, 0,129, 0, 0, 1, 80, 0, 0, 0, 35,
+ 0, 0, 0, 31, 0, 0, 1, 81, 0, 0, 0, 35, 0, 0, 0,129, 0, 0, 1, 81, 0, 0, 0, 35, 0, 0, 0, 21, 0, 0, 1, 82,
+ 0, 0, 0, 35, 0, 0, 0,130, 0, 0, 1, 82, 0, 0, 0, 35, 0, 0, 0, 30, 0, 0, 1, 83, 0, 0, 0, 35, 0, 0, 0,130,
+ 0, 0, 1, 83, 0, 0, 0, 35, 0, 0, 0, 30, 0, 0, 1, 84, 0, 0, 0, 35, 0, 0, 0,131, 0, 0, 1, 84, 0, 0, 0, 35,
+ 0, 0, 0, 31, 0, 0, 1, 85, 0, 0, 0, 35, 0, 0, 0,131, 0, 0, 1, 85, 0, 0, 0, 35, 0, 0, 0, 23, 0, 0, 1, 86,
+ 0, 0, 0, 35, 0, 0, 0,132, 0, 0, 1, 86, 0, 0, 0, 35, 0, 0, 0, 32, 0, 0, 1, 87, 0, 0, 0, 35, 0, 0, 0,132,
+ 0, 0, 1, 87, 0, 0, 0, 35, 0, 0, 0, 23, 0, 0, 1, 88, 0, 0, 0, 35, 0, 0, 0,133, 0, 0, 1, 88, 0, 0, 0, 35,
+ 0, 0, 0, 24, 0, 0, 1, 89, 0, 0, 0, 35, 0, 0, 0,133, 0, 0, 1, 89, 0, 0, 0, 35, 0, 0, 0, 24, 0, 0, 1, 90,
+ 0, 0, 0, 35, 0, 0, 0,134, 0, 0, 1, 90, 0, 0, 0, 35, 0, 0, 0, 32, 0, 0, 1, 91, 0, 0, 0, 35, 0, 0, 0,134,
+ 0, 0, 1, 91, 0, 0, 0, 35, 0, 0, 0, 25, 0, 0, 1, 92, 0, 0, 0, 35, 0, 0, 0,135, 0, 0, 1, 92, 0, 0, 0, 35,
+ 0, 0, 0, 33, 0, 0, 1, 93, 0, 0, 0, 35, 0, 0, 0,135, 0, 0, 1, 93, 0, 0, 0, 35, 0, 0, 0, 25, 0, 0, 1, 94,
+ 0, 0, 0, 35, 0, 0, 0,136, 0, 0, 1, 94, 0, 0, 0, 35, 0, 0, 0, 26, 0, 0, 1, 95, 0, 0, 0, 35, 0, 0, 0,136,
+ 0, 0, 1, 95, 0, 0, 0, 35, 0, 0, 0, 26, 0, 0, 1, 96, 0, 0, 0, 35, 0, 0, 0,137, 0, 0, 1, 96, 0, 0, 0, 35,
+ 0, 0, 0, 33, 0, 0, 1, 97, 0, 0, 0, 35, 0, 0, 0,137, 0, 0, 1, 97, 0, 0, 0, 35, 0, 0, 0, 27, 0, 0, 1, 98,
+ 0, 0, 0, 35, 0, 0, 0,138, 0, 0, 1, 98, 0, 0, 0, 35, 0, 0, 0, 34, 0, 0, 1, 99, 0, 0, 0, 35, 0, 0, 0,138,
+ 0, 0, 1, 99, 0, 0, 0, 35, 0, 0, 0, 27, 0, 0, 1,100, 0, 0, 0, 35, 0, 0, 0,139, 0, 0, 1,100, 0, 0, 0, 35,
+ 0, 0, 0, 28, 0, 0, 1,101, 0, 0, 0, 35, 0, 0, 0,139, 0, 0, 1,101, 0, 0, 0, 35, 0, 0, 0, 28, 0, 0, 1,102,
+ 0, 0, 0, 35, 0, 0, 0,140, 0, 0, 1,102, 0, 0, 0, 35, 0, 0, 0, 34, 0, 0, 1,103, 0, 0, 0, 35, 0, 0, 0,140,
+ 0, 0, 1,103, 0, 0, 0, 35, 0, 0, 0, 29, 0, 0, 1,104, 0, 0, 0, 35, 0, 0, 0,141, 0, 0, 1,104, 0, 0, 0, 35,
+ 0, 0, 0, 35, 0, 0, 1,105, 0, 0, 0, 35, 0, 0, 0,141, 0, 0, 1,105, 0, 0, 0, 35, 0, 0, 0, 29, 0, 0, 1,106,
+ 0, 0, 0, 35, 0, 0, 0,142, 0, 0, 1,106, 0, 0, 0, 35, 0, 0, 0, 30, 0, 0, 1,107, 0, 0, 0, 35, 0, 0, 0,142,
+ 0, 0, 1,107, 0, 0, 0, 35, 0, 0, 0, 30, 0, 0, 1,108, 0, 0, 0, 35, 0, 0, 0,143, 0, 0, 1,108, 0, 0, 0, 35,
+ 0, 0, 0, 35, 0, 0, 1,109, 0, 0, 0, 35, 0, 0, 0,143, 0, 0, 1,109, 0, 0, 0, 35, 0, 0, 0, 31, 0, 0, 1,110,
+ 0, 0, 0, 35, 0, 0, 0,144, 0, 0, 1,110, 0, 0, 0, 35, 0, 0, 0, 36, 0, 0, 1,111, 0, 0, 0, 35, 0, 0, 0,144,
+ 0, 0, 1,111, 0, 0, 0, 35, 0, 0, 0, 22, 0, 0, 1,112, 0, 0, 0, 35, 0, 0, 0,145, 0, 0, 1,112, 0, 0, 0, 35,
+ 0, 0, 0, 31, 0, 0, 1,113, 0, 0, 0, 35, 0, 0, 0,145, 0, 0, 1,113, 0, 0, 0, 35, 0, 0, 0, 22, 0, 0, 1,114,
+ 0, 0, 0, 35, 0, 0, 0,146, 0, 0, 1,114, 0, 0, 0, 35, 0, 0, 0, 36, 0, 0, 1,115, 0, 0, 0, 35, 0, 0, 0,146,
+ 0, 0, 1,115, 0, 0, 0, 35, 0, 0, 0, 32, 0, 0, 1,116, 0, 0, 0, 35, 0, 0, 0,147, 0, 0, 1,116, 0, 0, 0, 35,
+ 0, 0, 0, 38, 0, 0, 1,117, 0, 0, 0, 35, 0, 0, 0,147, 0, 0, 1,117, 0, 0, 0, 35, 0, 0, 0, 32, 0, 0, 1,118,
+ 0, 0, 0, 35, 0, 0, 0,148, 0, 0, 1,118, 0, 0, 0, 35, 0, 0, 0, 37, 0, 0, 1,119, 0, 0, 0, 35, 0, 0, 0,148,
+ 0, 0, 1,119, 0, 0, 0, 35, 0, 0, 0, 37, 0, 0, 1,120, 0, 0, 0, 35, 0, 0, 0,149, 0, 0, 1,120, 0, 0, 0, 35,
+ 0, 0, 0, 38, 0, 0, 1,121, 0, 0, 0, 35, 0, 0, 0,149, 0, 0, 1,121, 0, 0, 0, 35, 0, 0, 0, 33, 0, 0, 1,122,
+ 0, 0, 0, 35, 0, 0, 0,150, 0, 0, 1,122, 0, 0, 0, 35, 0, 0, 0, 39, 0, 0, 1,123, 0, 0, 0, 35, 0, 0, 0,150,
+ 0, 0, 1,123, 0, 0, 0, 35, 0, 0, 0, 33, 0, 0, 1,124, 0, 0, 0, 35, 0, 0, 0,151, 0, 0, 1,124, 0, 0, 0, 35,
+ 0, 0, 0, 38, 0, 0, 1,125, 0, 0, 0, 35, 0, 0, 0,151, 0, 0, 1,125, 0, 0, 0, 35, 0, 0, 0, 38, 0, 0, 1,126,
+ 0, 0, 0, 35, 0, 0, 0,152, 0, 0, 1,126, 0, 0, 0, 35, 0, 0, 0, 39, 0, 0, 1,127, 0, 0, 0, 35, 0, 0, 0,152,
+ 0, 0, 1,127, 0, 0, 0, 35, 0, 0, 0, 34, 0, 0, 1,128, 0, 0, 0, 35, 0, 0, 0,153, 0, 0, 1,128, 0, 0, 0, 35,
+ 0, 0, 0, 40, 0, 0, 1,129, 0, 0, 0, 35, 0, 0, 0,153, 0, 0, 1,129, 0, 0, 0, 35, 0, 0, 0, 34, 0, 0, 1,130,
+ 0, 0, 0, 35, 0, 0, 0,154, 0, 0, 1,130, 0, 0, 0, 35, 0, 0, 0, 39, 0, 0, 1,131, 0, 0, 0, 35, 0, 0, 0,154,
+ 0, 0, 1,131, 0, 0, 0, 35, 0, 0, 0, 39, 0, 0, 1,132, 0, 0, 0, 35, 0, 0, 0,155, 0, 0, 1,132, 0, 0, 0, 35,
+ 0, 0, 0, 40, 0, 0, 1,133, 0, 0, 0, 35, 0, 0, 0,155, 0, 0, 1,133, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 1,134,
+ 0, 0, 0, 35, 0, 0, 0,156, 0, 0, 1,134, 0, 0, 0, 35, 0, 0, 0, 41, 0, 0, 1,135, 0, 0, 0, 35, 0, 0, 0,156,
+ 0, 0, 1,135, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 1,136, 0, 0, 0, 35, 0, 0, 0,157, 0, 0, 1,136, 0, 0, 0, 35,
+ 0, 0, 0, 40, 0, 0, 1,137, 0, 0, 0, 35, 0, 0, 0,157, 0, 0, 1,137, 0, 0, 0, 35, 0, 0, 0, 40, 0, 0, 1,138,
+ 0, 0, 0, 35, 0, 0, 0,158, 0, 0, 1,138, 0, 0, 0, 35, 0, 0, 0, 41, 0, 0, 1,139, 0, 0, 0, 35, 0, 0, 0,158,
+ 0, 0, 1,139, 0, 0, 0, 35, 0, 0, 0, 36, 0, 0, 1,140, 0, 0, 0, 35, 0, 0, 0,159, 0, 0, 1,140, 0, 0, 0, 35,
+ 0, 0, 0, 37, 0, 0, 1,141, 0, 0, 0, 35, 0, 0, 0,159, 0, 0, 1,141, 0, 0, 0, 35, 0, 0, 0, 36, 0, 0, 1,142,
+ 0, 0, 0, 35, 0, 0, 0,160, 0, 0, 1,142, 0, 0, 0, 35, 0, 0, 0, 41, 0, 0, 1,143, 0, 0, 0, 35, 0, 0, 0,160,
+ 0, 0, 1,143, 0, 0, 0, 35, 0, 0, 0, 37, 0, 0, 1,144, 0, 0, 0, 35, 0, 0, 0,161, 0, 0, 1,144, 0, 0, 0, 35,
+ 0, 0, 0, 41, 0, 0, 1,145, 0, 0, 0, 35, 0, 0, 0,161, 0, 0, 1,145, 0, 0, 0, 35, 0, 0, 0, 46, 0, 0, 1,146,
+ 0, 0, 0, 35, 0, 0, 0,102, 0, 0, 1,146, 0, 0, 0, 35, 0, 0, 0, 43, 0, 0, 1,147, 0, 0, 0, 33, 0, 0, 0, 46,
+ 0, 0, 1,147, 0, 0, 0, 33, 0, 0, 0, 43, 0, 0, 1,148, 0, 0, 0, 35, 0, 0, 0,102, 0, 0, 1,148, 0, 0, 0, 35,
+ 0, 0, 0,102, 0, 0, 1,149, 0, 0, 0, 35, 0, 0, 0,103, 0, 0, 1,149, 0, 0, 0, 35, 0, 0, 0,103, 0, 0, 1,150,
+ 0, 0, 0, 35, 0, 0, 0,104, 0, 0, 1,150, 0, 0, 0, 35, 0, 0, 0,102, 0, 0, 1,151, 0, 0, 0, 35, 0, 0, 0,104,
+ 0, 0, 1,151, 0, 0, 0, 35, 0, 0, 0, 45, 0, 0, 1,152, 0, 0, 0, 33, 0, 0, 0, 47, 0, 0, 1,152, 0, 0, 0, 33,
+ 0, 0, 0, 47, 0, 0, 1,153, 0, 0, 0, 35, 0, 0, 0,104, 0, 0, 1,153, 0, 0, 0, 35, 0, 0, 0, 45, 0, 0, 1,154,
+ 0, 0, 0, 35, 0, 0, 0,104, 0, 0, 1,154, 0, 0, 0, 35, 0, 0, 0, 44, 0, 0, 1,155, 0, 0, 0, 35, 0, 0, 0,103,
+ 0, 0, 1,155, 0, 0, 0, 35, 0, 0, 0, 42, 0, 0, 1,156, 0, 0, 0, 35, 0, 0, 0,103, 0, 0, 1,156, 0, 0, 0, 35,
+ 0, 0, 0, 42, 0, 0, 1,157, 0, 0, 0, 33, 0, 0, 0, 44, 0, 0, 1,157, 0, 0, 0, 33, 0, 0, 0, 50, 0, 0, 1,158,
+ 0, 0, 0, 35, 0, 0, 0,105, 0, 0, 1,158, 0, 0, 0, 35, 0, 0, 0, 43, 0, 0, 1,159, 0, 0, 0, 33, 0, 0, 0, 50,
+ 0, 0, 1,159, 0, 0, 0, 33, 0, 0, 0, 43, 0, 0, 1,160, 0, 0, 0, 35, 0, 0, 0,105, 0, 0, 1,160, 0, 0, 0, 35,
+ 0, 0, 0,105, 0, 0, 1,161, 0, 0, 0, 35, 0, 0, 0,106, 0, 0, 1,161, 0, 0, 0, 35, 0, 0, 0,106, 0, 0, 1,162,
+ 0, 0, 0, 35, 0, 0, 0,107, 0, 0, 1,162, 0, 0, 0, 35, 0, 0, 0,105, 0, 0, 1,163, 0, 0, 0, 35, 0, 0, 0,107,
+ 0, 0, 1,163, 0, 0, 0, 35, 0, 0, 0, 49, 0, 0, 1,164, 0, 0, 0, 33, 0, 0, 0, 51, 0, 0, 1,164, 0, 0, 0, 33,
+ 0, 0, 0, 51, 0, 0, 1,165, 0, 0, 0, 35, 0, 0, 0,107, 0, 0, 1,165, 0, 0, 0, 35, 0, 0, 0, 49, 0, 0, 1,166,
+ 0, 0, 0, 35, 0, 0, 0,107, 0, 0, 1,166, 0, 0, 0, 35, 0, 0, 0, 48, 0, 0, 1,167, 0, 0, 0, 35, 0, 0, 0,106,
+ 0, 0, 1,167, 0, 0, 0, 35, 0, 0, 0, 42, 0, 0, 1,168, 0, 0, 0, 35, 0, 0, 0,106, 0, 0, 1,168, 0, 0, 0, 35,
+ 0, 0, 0, 42, 0, 0, 1,169, 0, 0, 0, 33, 0, 0, 0, 48, 0, 0, 1,169, 0, 0, 0, 33, 0, 0, 0, 54, 0, 0, 1,170,
+ 0, 0, 0, 35, 0, 0, 0,108, 0, 0, 1,170, 0, 0, 0, 35, 0, 0, 0, 45, 0, 0, 1,171, 0, 0, 0, 33, 0, 0, 0, 54,
+ 0, 0, 1,171, 0, 0, 0, 33, 0, 0, 0, 45, 0, 0, 1,172, 0, 0, 0, 35, 0, 0, 0,108, 0, 0, 1,172, 0, 0, 0, 35,
+ 0, 0, 0,108, 0, 0, 1,173, 0, 0, 0, 35, 0, 0, 0,109, 0, 0, 1,173, 0, 0, 0, 35, 0, 0, 0,109, 0, 0, 1,174,
+ 0, 0, 0, 35, 0, 0, 0,110, 0, 0, 1,174, 0, 0, 0, 35, 0, 0, 0,108, 0, 0, 1,175, 0, 0, 0, 35, 0, 0, 0,110,
+ 0, 0, 1,175, 0, 0, 0, 35, 0, 0, 0, 53, 0, 0, 1,176, 0, 0, 0, 33, 0, 0, 0, 55, 0, 0, 1,176, 0, 0, 0, 33,
+ 0, 0, 0, 55, 0, 0, 1,177, 0, 0, 0, 35, 0, 0, 0,110, 0, 0, 1,177, 0, 0, 0, 35, 0, 0, 0, 53, 0, 0, 1,178,
+ 0, 0, 0, 35, 0, 0, 0,110, 0, 0, 1,178, 0, 0, 0, 35, 0, 0, 0, 52, 0, 0, 1,179, 0, 0, 0, 35, 0, 0, 0,109,
+ 0, 0, 1,179, 0, 0, 0, 35, 0, 0, 0, 44, 0, 0, 1,180, 0, 0, 0, 35, 0, 0, 0,109, 0, 0, 1,180, 0, 0, 0, 35,
+ 0, 0, 0, 44, 0, 0, 1,181, 0, 0, 0, 33, 0, 0, 0, 52, 0, 0, 1,181, 0, 0, 0, 33, 0, 0, 0, 58, 0, 0, 1,182,
+ 0, 0, 0, 35, 0, 0, 0,111, 0, 0, 1,182, 0, 0, 0, 35, 0, 0, 0, 53, 0, 0, 1,183, 0, 0, 0, 33, 0, 0, 0, 58,
+ 0, 0, 1,183, 0, 0, 0, 33, 0, 0, 0, 53, 0, 0, 1,184, 0, 0, 0, 35, 0, 0, 0,111, 0, 0, 1,184, 0, 0, 0, 35,
+ 0, 0, 0,111, 0, 0, 1,185, 0, 0, 0, 35, 0, 0, 0,112, 0, 0, 1,185, 0, 0, 0, 35, 0, 0, 0,112, 0, 0, 1,186,
+ 0, 0, 0, 35, 0, 0, 0,113, 0, 0, 1,186, 0, 0, 0, 35, 0, 0, 0,111, 0, 0, 1,187, 0, 0, 0, 35, 0, 0, 0,113,
+ 0, 0, 1,187, 0, 0, 0, 35, 0, 0, 0, 57, 0, 0, 1,188, 0, 0, 0, 33, 0, 0, 0, 59, 0, 0, 1,188, 0, 0, 0, 33,
+ 0, 0, 0, 59, 0, 0, 1,189, 0, 0, 0, 35, 0, 0, 0,113, 0, 0, 1,189, 0, 0, 0, 35, 0, 0, 0, 57, 0, 0, 1,190,
+ 0, 0, 0, 35, 0, 0, 0,113, 0, 0, 1,190, 0, 0, 0, 35, 0, 0, 0, 56, 0, 0, 1,191, 0, 0, 0, 35, 0, 0, 0,112,
+ 0, 0, 1,191, 0, 0, 0, 35, 0, 0, 0, 52, 0, 0, 1,192, 0, 0, 0, 35, 0, 0, 0,112, 0, 0, 1,192, 0, 0, 0, 35,
+ 0, 0, 0, 52, 0, 0, 1,193, 0, 0, 0, 33, 0, 0, 0, 56, 0, 0, 1,193, 0, 0, 0, 33, 0, 0, 0, 60, 0, 0, 1,194,
+ 0, 0, 0, 35, 0, 0, 0,114, 0, 0, 1,194, 0, 0, 0, 35, 0, 0, 0, 57, 0, 0, 1,195, 0, 0, 0, 33, 0, 0, 0, 60,
+ 0, 0, 1,195, 0, 0, 0, 33, 0, 0, 0, 57, 0, 0, 1,196, 0, 0, 0, 35, 0, 0, 0,114, 0, 0, 1,196, 0, 0, 0, 35,
+ 0, 0, 0,114, 0, 0, 1,197, 0, 0, 0, 35, 0, 0, 0,115, 0, 0, 1,197, 0, 0, 0, 35, 0, 0, 0,115, 0, 0, 1,198,
+ 0, 0, 0, 35, 0, 0, 0,116, 0, 0, 1,198, 0, 0, 0, 35, 0, 0, 0,114, 0, 0, 1,199, 0, 0, 0, 35, 0, 0, 0,116,
+ 0, 0, 1,199, 0, 0, 0, 35, 0, 0, 0, 49, 0, 0, 1,200, 0, 0, 0, 33, 0, 0, 0, 61, 0, 0, 1,200, 0, 0, 0, 33,
+ 0, 0, 0, 61, 0, 0, 1,201, 0, 0, 0, 35, 0, 0, 0,116, 0, 0, 1,201, 0, 0, 0, 35, 0, 0, 0, 49, 0, 0, 1,202,
+ 0, 0, 0, 35, 0, 0, 0,116, 0, 0, 1,202, 0, 0, 0, 35, 0, 0, 0, 48, 0, 0, 1,203, 0, 0, 0, 35, 0, 0, 0,115,
+ 0, 0, 1,203, 0, 0, 0, 35, 0, 0, 0, 56, 0, 0, 1,204, 0, 0, 0, 35, 0, 0, 0,115, 0, 0, 1,204, 0, 0, 0, 35,
+ 0, 0, 0, 48, 0, 0, 1,205, 0, 0, 0, 33, 0, 0, 0, 56, 0, 0, 1,205, 0, 0, 0, 33, 0, 0, 0, 64, 0, 0, 1,206,
+ 0, 0, 0, 35, 0, 0, 0,117, 0, 0, 1,206, 0, 0, 0, 35, 0, 0, 0, 50, 0, 0, 1,207, 0, 0, 0, 33, 0, 0, 0, 64,
+ 0, 0, 1,207, 0, 0, 0, 33, 0, 0, 0, 50, 0, 0, 1,208, 0, 0, 0, 35, 0, 0, 0,117, 0, 0, 1,208, 0, 0, 0, 35,
+ 0, 0, 0,117, 0, 0, 1,209, 0, 0, 0, 35, 0, 0, 0,118, 0, 0, 1,209, 0, 0, 0, 35, 0, 0, 0,118, 0, 0, 1,210,
+ 0, 0, 0, 35, 0, 0, 0,119, 0, 0, 1,210, 0, 0, 0, 35, 0, 0, 0,117, 0, 0, 1,211, 0, 0, 0, 35, 0, 0, 0,119,
+ 0, 0, 1,211, 0, 0, 0, 35, 0, 0, 0, 63, 0, 0, 1,212, 0, 0, 0, 33, 0, 0, 0, 65, 0, 0, 1,212, 0, 0, 0, 33,
+ 0, 0, 0, 65, 0, 0, 1,213, 0, 0, 0, 35, 0, 0, 0,119, 0, 0, 1,213, 0, 0, 0, 35, 0, 0, 0, 63, 0, 0, 1,214,
+ 0, 0, 0, 35, 0, 0, 0,119, 0, 0, 1,214, 0, 0, 0, 35, 0, 0, 0, 62, 0, 0, 1,215, 0, 0, 0, 35, 0, 0, 0,118,
+ 0, 0, 1,215, 0, 0, 0, 35, 0, 0, 0, 51, 0, 0, 1,216, 0, 0, 0, 35, 0, 0, 0,118, 0, 0, 1,216, 0, 0, 0, 35,
+ 0, 0, 0, 51, 0, 0, 1,217, 0, 0, 0, 33, 0, 0, 0, 62, 0, 0, 1,217, 0, 0, 0, 33, 0, 0, 0, 68, 0, 0, 1,218,
+ 0, 0, 0, 35, 0, 0, 0,120, 0, 0, 1,218, 0, 0, 0, 35, 0, 0, 0, 47, 0, 0, 1,219, 0, 0, 0, 33, 0, 0, 0, 68,
+ 0, 0, 1,219, 0, 0, 0, 33, 0, 0, 0, 47, 0, 0, 1,220, 0, 0, 0, 35, 0, 0, 0,120, 0, 0, 1,220, 0, 0, 0, 35,
+ 0, 0, 0,120, 0, 0, 1,221, 0, 0, 0, 35, 0, 0, 0,121, 0, 0, 1,221, 0, 0, 0, 35, 0, 0, 0,121, 0, 0, 1,222,
+ 0, 0, 0, 35, 0, 0, 0,122, 0, 0, 1,222, 0, 0, 0, 35, 0, 0, 0,120, 0, 0, 1,223, 0, 0, 0, 35, 0, 0, 0,122,
+ 0, 0, 1,223, 0, 0, 0, 35, 0, 0, 0, 67, 0, 0, 1,224, 0, 0, 0, 33, 0, 0, 0, 69, 0, 0, 1,224, 0, 0, 0, 33,
+ 0, 0, 0, 69, 0, 0, 1,225, 0, 0, 0, 35, 0, 0, 0,122, 0, 0, 1,225, 0, 0, 0, 35, 0, 0, 0, 67, 0, 0, 1,226,
+ 0, 0, 0, 35, 0, 0, 0,122, 0, 0, 1,226, 0, 0, 0, 35, 0, 0, 0, 66, 0, 0, 1,227, 0, 0, 0, 35, 0, 0, 0,121,
+ 0, 0, 1,227, 0, 0, 0, 35, 0, 0, 0, 46, 0, 0, 1,228, 0, 0, 0, 35, 0, 0, 0,121, 0, 0, 1,228, 0, 0, 0, 35,
+ 0, 0, 0, 46, 0, 0, 1,229, 0, 0, 0, 33, 0, 0, 0, 66, 0, 0, 1,229, 0, 0, 0, 33, 0, 0, 0, 72, 0, 0, 1,230,
+ 0, 0, 0, 35, 0, 0, 0,123, 0, 0, 1,230, 0, 0, 0, 35, 0, 0, 0, 55, 0, 0, 1,231, 0, 0, 0, 33, 0, 0, 0, 72,
+ 0, 0, 1,231, 0, 0, 0, 33, 0, 0, 0, 55, 0, 0, 1,232, 0, 0, 0, 35, 0, 0, 0,123, 0, 0, 1,232, 0, 0, 0, 35,
+ 0, 0, 0,123, 0, 0, 1,233, 0, 0, 0, 35, 0, 0, 0,124, 0, 0, 1,233, 0, 0, 0, 35, 0, 0, 0,124, 0, 0, 1,234,
+ 0, 0, 0, 35, 0, 0, 0,125, 0, 0, 1,234, 0, 0, 0, 35, 0, 0, 0,123, 0, 0, 1,235, 0, 0, 0, 35, 0, 0, 0,125,
+ 0, 0, 1,235, 0, 0, 0, 35, 0, 0, 0, 71, 0, 0, 1,236, 0, 0, 0, 33, 0, 0, 0, 73, 0, 0, 1,236, 0, 0, 0, 33,
+ 0, 0, 0, 73, 0, 0, 1,237, 0, 0, 0, 35, 0, 0, 0,125, 0, 0, 1,237, 0, 0, 0, 35, 0, 0, 0, 71, 0, 0, 1,238,
+ 0, 0, 0, 35, 0, 0, 0,125, 0, 0, 1,238, 0, 0, 0, 35, 0, 0, 0, 70, 0, 0, 1,239, 0, 0, 0, 35, 0, 0, 0,124,
+ 0, 0, 1,239, 0, 0, 0, 35, 0, 0, 0, 54, 0, 0, 1,240, 0, 0, 0, 35, 0, 0, 0,124, 0, 0, 1,240, 0, 0, 0, 35,
+ 0, 0, 0, 54, 0, 0, 1,241, 0, 0, 0, 33, 0, 0, 0, 70, 0, 0, 1,241, 0, 0, 0, 33, 0, 0, 0, 76, 0, 0, 1,242,
+ 0, 0, 0, 35, 0, 0, 0,126, 0, 0, 1,242, 0, 0, 0, 35, 0, 0, 0, 59, 0, 0, 1,243, 0, 0, 0, 33, 0, 0, 0, 76,
+ 0, 0, 1,243, 0, 0, 0, 33, 0, 0, 0, 59, 0, 0, 1,244, 0, 0, 0, 35, 0, 0, 0,126, 0, 0, 1,244, 0, 0, 0, 35,
+ 0, 0, 0,126, 0, 0, 1,245, 0, 0, 0, 35, 0, 0, 0,127, 0, 0, 1,245, 0, 0, 0, 35, 0, 0, 0,127, 0, 0, 1,246,
+ 0, 0, 0, 35, 0, 0, 0,128, 0, 0, 1,246, 0, 0, 0, 35, 0, 0, 0,126, 0, 0, 1,247, 0, 0, 0, 35, 0, 0, 0,128,
+ 0, 0, 1,247, 0, 0, 0, 35, 0, 0, 0, 75, 0, 0, 1,248, 0, 0, 0, 33, 0, 0, 0, 77, 0, 0, 1,248, 0, 0, 0, 33,
+ 0, 0, 0, 77, 0, 0, 1,249, 0, 0, 0, 35, 0, 0, 0,128, 0, 0, 1,249, 0, 0, 0, 35, 0, 0, 0, 75, 0, 0, 1,250,
+ 0, 0, 0, 35, 0, 0, 0,128, 0, 0, 1,250, 0, 0, 0, 35, 0, 0, 0, 74, 0, 0, 1,251, 0, 0, 0, 35, 0, 0, 0,127,
+ 0, 0, 1,251, 0, 0, 0, 35, 0, 0, 0, 58, 0, 0, 1,252, 0, 0, 0, 35, 0, 0, 0,127, 0, 0, 1,252, 0, 0, 0, 35,
+ 0, 0, 0, 58, 0, 0, 1,253, 0, 0, 0, 33, 0, 0, 0, 74, 0, 0, 1,253, 0, 0, 0, 33, 0, 0, 0, 80, 0, 0, 1,254,
+ 0, 0, 0, 35, 0, 0, 0,129, 0, 0, 1,254, 0, 0, 0, 35, 0, 0, 0, 61, 0, 0, 1,255, 0, 0, 0, 33, 0, 0, 0, 80,
+ 0, 0, 1,255, 0, 0, 0, 33, 0, 0, 0, 61, 0, 0, 2, 0, 0, 0, 0, 35, 0, 0, 0,129, 0, 0, 2, 0, 0, 0, 0, 35,
+ 0, 0, 0,129, 0, 0, 2, 1, 0, 0, 0, 35, 0, 0, 0,130, 0, 0, 2, 1, 0, 0, 0, 35, 0, 0, 0,130, 0, 0, 2, 2,
+ 0, 0, 0, 35, 0, 0, 0,131, 0, 0, 2, 2, 0, 0, 0, 35, 0, 0, 0,129, 0, 0, 2, 3, 0, 0, 0, 35, 0, 0, 0,131,
+ 0, 0, 2, 3, 0, 0, 0, 35, 0, 0, 0, 79, 0, 0, 2, 4, 0, 0, 0, 33, 0, 0, 0, 81, 0, 0, 2, 4, 0, 0, 0, 33,
+ 0, 0, 0, 81, 0, 0, 2, 5, 0, 0, 0, 35, 0, 0, 0,131, 0, 0, 2, 5, 0, 0, 0, 35, 0, 0, 0, 79, 0, 0, 2, 6,
+ 0, 0, 0, 35, 0, 0, 0,131, 0, 0, 2, 6, 0, 0, 0, 35, 0, 0, 0, 78, 0, 0, 2, 7, 0, 0, 0, 35, 0, 0, 0,130,
+ 0, 0, 2, 7, 0, 0, 0, 35, 0, 0, 0, 60, 0, 0, 2, 8, 0, 0, 0, 35, 0, 0, 0,130, 0, 0, 2, 8, 0, 0, 0, 35,
+ 0, 0, 0, 60, 0, 0, 2, 9, 0, 0, 0, 33, 0, 0, 0, 78, 0, 0, 2, 9, 0, 0, 0, 33, 0, 0, 0, 83, 0, 0, 2, 10,
+ 0, 0, 0, 35, 0, 0, 0,132, 0, 0, 2, 10, 0, 0, 0, 35, 0, 0, 0, 65, 0, 0, 2, 11, 0, 0, 0, 33, 0, 0, 0, 83,
+ 0, 0, 2, 11, 0, 0, 0, 33, 0, 0, 0, 65, 0, 0, 2, 12, 0, 0, 0, 35, 0, 0, 0,132, 0, 0, 2, 12, 0, 0, 0, 35,
+ 0, 0, 0,132, 0, 0, 2, 13, 0, 0, 0, 35, 0, 0, 0,133, 0, 0, 2, 13, 0, 0, 0, 35, 0, 0, 0,133, 0, 0, 2, 14,
+ 0, 0, 0, 35, 0, 0, 0,134, 0, 0, 2, 14, 0, 0, 0, 35, 0, 0, 0,132, 0, 0, 2, 15, 0, 0, 0, 35, 0, 0, 0,134,
+ 0, 0, 2, 15, 0, 0, 0, 35, 0, 0, 0, 67, 0, 0, 2, 16, 0, 0, 0, 33, 0, 0, 0, 82, 0, 0, 2, 16, 0, 0, 0, 33,
+ 0, 0, 0, 82, 0, 0, 2, 17, 0, 0, 0, 35, 0, 0, 0,134, 0, 0, 2, 17, 0, 0, 0, 35, 0, 0, 0, 67, 0, 0, 2, 18,
+ 0, 0, 0, 35, 0, 0, 0,134, 0, 0, 2, 18, 0, 0, 0, 35, 0, 0, 0, 66, 0, 0, 2, 19, 0, 0, 0, 35, 0, 0, 0,133,
+ 0, 0, 2, 19, 0, 0, 0, 35, 0, 0, 0, 64, 0, 0, 2, 20, 0, 0, 0, 35, 0, 0, 0,133, 0, 0, 2, 20, 0, 0, 0, 35,
+ 0, 0, 0, 64, 0, 0, 2, 21, 0, 0, 0, 33, 0, 0, 0, 66, 0, 0, 2, 21, 0, 0, 0, 33, 0, 0, 0, 84, 0, 0, 2, 22,
+ 0, 0, 0, 35, 0, 0, 0,135, 0, 0, 2, 22, 0, 0, 0, 35, 0, 0, 0, 69, 0, 0, 2, 23, 0, 0, 0, 33, 0, 0, 0, 84,
+ 0, 0, 2, 23, 0, 0, 0, 33, 0, 0, 0, 69, 0, 0, 2, 24, 0, 0, 0, 35, 0, 0, 0,135, 0, 0, 2, 24, 0, 0, 0, 35,
+ 0, 0, 0,135, 0, 0, 2, 25, 0, 0, 0, 35, 0, 0, 0,136, 0, 0, 2, 25, 0, 0, 0, 35, 0, 0, 0,136, 0, 0, 2, 26,
+ 0, 0, 0, 35, 0, 0, 0,137, 0, 0, 2, 26, 0, 0, 0, 35, 0, 0, 0,135, 0, 0, 2, 27, 0, 0, 0, 35, 0, 0, 0,137,
+ 0, 0, 2, 27, 0, 0, 0, 35, 0, 0, 0, 71, 0, 0, 2, 28, 0, 0, 0, 33, 0, 0, 0, 85, 0, 0, 2, 28, 0, 0, 0, 33,
+ 0, 0, 0, 85, 0, 0, 2, 29, 0, 0, 0, 35, 0, 0, 0,137, 0, 0, 2, 29, 0, 0, 0, 35, 0, 0, 0, 71, 0, 0, 2, 30,
+ 0, 0, 0, 35, 0, 0, 0,137, 0, 0, 2, 30, 0, 0, 0, 35, 0, 0, 0, 70, 0, 0, 2, 31, 0, 0, 0, 35, 0, 0, 0,136,
+ 0, 0, 2, 31, 0, 0, 0, 35, 0, 0, 0, 68, 0, 0, 2, 32, 0, 0, 0, 35, 0, 0, 0,136, 0, 0, 2, 32, 0, 0, 0, 35,
+ 0, 0, 0, 68, 0, 0, 2, 33, 0, 0, 0, 33, 0, 0, 0, 70, 0, 0, 2, 33, 0, 0, 0, 33, 0, 0, 0, 86, 0, 0, 2, 34,
+ 0, 0, 0, 35, 0, 0, 0,138, 0, 0, 2, 34, 0, 0, 0, 35, 0, 0, 0, 73, 0, 0, 2, 35, 0, 0, 0, 33, 0, 0, 0, 86,
+ 0, 0, 2, 35, 0, 0, 0, 33, 0, 0, 0, 73, 0, 0, 2, 36, 0, 0, 0, 35, 0, 0, 0,138, 0, 0, 2, 36, 0, 0, 0, 35,
+ 0, 0, 0,138, 0, 0, 2, 37, 0, 0, 0, 35, 0, 0, 0,139, 0, 0, 2, 37, 0, 0, 0, 35, 0, 0, 0,139, 0, 0, 2, 38,
+ 0, 0, 0, 35, 0, 0, 0,140, 0, 0, 2, 38, 0, 0, 0, 35, 0, 0, 0,138, 0, 0, 2, 39, 0, 0, 0, 35, 0, 0, 0,140,
+ 0, 0, 2, 39, 0, 0, 0, 35, 0, 0, 0, 75, 0, 0, 2, 40, 0, 0, 0, 33, 0, 0, 0, 87, 0, 0, 2, 40, 0, 0, 0, 33,
+ 0, 0, 0, 87, 0, 0, 2, 41, 0, 0, 0, 35, 0, 0, 0,140, 0, 0, 2, 41, 0, 0, 0, 35, 0, 0, 0, 75, 0, 0, 2, 42,
+ 0, 0, 0, 35, 0, 0, 0,140, 0, 0, 2, 42, 0, 0, 0, 35, 0, 0, 0, 74, 0, 0, 2, 43, 0, 0, 0, 35, 0, 0, 0,139,
+ 0, 0, 2, 43, 0, 0, 0, 35, 0, 0, 0, 72, 0, 0, 2, 44, 0, 0, 0, 35, 0, 0, 0,139, 0, 0, 2, 44, 0, 0, 0, 35,
+ 0, 0, 0, 72, 0, 0, 2, 45, 0, 0, 0, 33, 0, 0, 0, 74, 0, 0, 2, 45, 0, 0, 0, 33, 0, 0, 0, 88, 0, 0, 2, 46,
+ 0, 0, 0, 35, 0, 0, 0,141, 0, 0, 2, 46, 0, 0, 0, 35, 0, 0, 0, 77, 0, 0, 2, 47, 0, 0, 0, 33, 0, 0, 0, 88,
+ 0, 0, 2, 47, 0, 0, 0, 33, 0, 0, 0, 77, 0, 0, 2, 48, 0, 0, 0, 35, 0, 0, 0,141, 0, 0, 2, 48, 0, 0, 0, 35,
+ 0, 0, 0,141, 0, 0, 2, 49, 0, 0, 0, 35, 0, 0, 0,142, 0, 0, 2, 49, 0, 0, 0, 35, 0, 0, 0,142, 0, 0, 2, 50,
+ 0, 0, 0, 35, 0, 0, 0,143, 0, 0, 2, 50, 0, 0, 0, 35, 0, 0, 0,141, 0, 0, 2, 51, 0, 0, 0, 35, 0, 0, 0,143,
+ 0, 0, 2, 51, 0, 0, 0, 35, 0, 0, 0, 79, 0, 0, 2, 52, 0, 0, 0, 33, 0, 0, 0, 89, 0, 0, 2, 52, 0, 0, 0, 33,
+ 0, 0, 0, 89, 0, 0, 2, 53, 0, 0, 0, 35, 0, 0, 0,143, 0, 0, 2, 53, 0, 0, 0, 35, 0, 0, 0, 79, 0, 0, 2, 54,
+ 0, 0, 0, 35, 0, 0, 0,143, 0, 0, 2, 54, 0, 0, 0, 35, 0, 0, 0, 78, 0, 0, 2, 55, 0, 0, 0, 35, 0, 0, 0,142,
+ 0, 0, 2, 55, 0, 0, 0, 35, 0, 0, 0, 76, 0, 0, 2, 56, 0, 0, 0, 35, 0, 0, 0,142, 0, 0, 2, 56, 0, 0, 0, 35,
+ 0, 0, 0, 76, 0, 0, 2, 57, 0, 0, 0, 33, 0, 0, 0, 78, 0, 0, 2, 57, 0, 0, 0, 33, 0, 0, 0, 90, 0, 0, 2, 58,
+ 0, 0, 0, 35, 0, 0, 0,144, 0, 0, 2, 58, 0, 0, 0, 35, 0, 0, 0, 81, 0, 0, 2, 59, 0, 0, 0, 33, 0, 0, 0, 90,
+ 0, 0, 2, 59, 0, 0, 0, 33, 0, 0, 0, 81, 0, 0, 2, 60, 0, 0, 0, 35, 0, 0, 0,144, 0, 0, 2, 60, 0, 0, 0, 35,
+ 0, 0, 0,144, 0, 0, 2, 61, 0, 0, 0, 35, 0, 0, 0,145, 0, 0, 2, 61, 0, 0, 0, 35, 0, 0, 0,145, 0, 0, 2, 62,
+ 0, 0, 0, 35, 0, 0, 0,146, 0, 0, 2, 62, 0, 0, 0, 35, 0, 0, 0,144, 0, 0, 2, 63, 0, 0, 0, 35, 0, 0, 0,146,
+ 0, 0, 2, 63, 0, 0, 0, 35, 0, 0, 0, 63, 0, 0, 2, 64, 0, 0, 0, 33, 0, 0, 0, 91, 0, 0, 2, 64, 0, 0, 0, 33,
+ 0, 0, 0, 91, 0, 0, 2, 65, 0, 0, 0, 35, 0, 0, 0,146, 0, 0, 2, 65, 0, 0, 0, 35, 0, 0, 0, 63, 0, 0, 2, 66,
+ 0, 0, 0, 35, 0, 0, 0,146, 0, 0, 2, 66, 0, 0, 0, 35, 0, 0, 0, 62, 0, 0, 2, 67, 0, 0, 0, 35, 0, 0, 0,145,
+ 0, 0, 2, 67, 0, 0, 0, 35, 0, 0, 0, 80, 0, 0, 2, 68, 0, 0, 0, 35, 0, 0, 0,145, 0, 0, 2, 68, 0, 0, 0, 35,
+ 0, 0, 0, 62, 0, 0, 2, 69, 0, 0, 0, 33, 0, 0, 0, 80, 0, 0, 2, 69, 0, 0, 0, 33, 0, 0, 0, 94, 0, 0, 2, 70,
+ 0, 0, 0, 35, 0, 0, 0,147, 0, 0, 2, 70, 0, 0, 0, 35, 0, 0, 0, 82, 0, 0, 2, 71, 0, 0, 0, 33, 0, 0, 0, 94,
+ 0, 0, 2, 71, 0, 0, 0, 33, 0, 0, 0, 82, 0, 0, 2, 72, 0, 0, 0, 35, 0, 0, 0,147, 0, 0, 2, 72, 0, 0, 0, 35,
+ 0, 0, 0,147, 0, 0, 2, 73, 0, 0, 0, 35, 0, 0, 0,148, 0, 0, 2, 73, 0, 0, 0, 35, 0, 0, 0,148, 0, 0, 2, 74,
+ 0, 0, 0, 35, 0, 0, 0,149, 0, 0, 2, 74, 0, 0, 0, 35, 0, 0, 0,147, 0, 0, 2, 75, 0, 0, 0, 35, 0, 0, 0,149,
+ 0, 0, 2, 75, 0, 0, 0, 35, 0, 0, 0, 93, 0, 0, 2, 76, 0, 0, 0, 33, 0, 0, 0, 95, 0, 0, 2, 76, 0, 0, 0, 33,
+ 0, 0, 0, 95, 0, 0, 2, 77, 0, 0, 0, 35, 0, 0, 0,149, 0, 0, 2, 77, 0, 0, 0, 35, 0, 0, 0, 93, 0, 0, 2, 78,
+ 0, 0, 0, 35, 0, 0, 0,149, 0, 0, 2, 78, 0, 0, 0, 35, 0, 0, 0, 92, 0, 0, 2, 79, 0, 0, 0, 35, 0, 0, 0,148,
+ 0, 0, 2, 79, 0, 0, 0, 35, 0, 0, 0, 83, 0, 0, 2, 80, 0, 0, 0, 35, 0, 0, 0,148, 0, 0, 2, 80, 0, 0, 0, 35,
+ 0, 0, 0, 83, 0, 0, 2, 81, 0, 0, 0, 33, 0, 0, 0, 92, 0, 0, 2, 81, 0, 0, 0, 33, 0, 0, 0, 96, 0, 0, 2, 82,
+ 0, 0, 0, 35, 0, 0, 0,150, 0, 0, 2, 82, 0, 0, 0, 35, 0, 0, 0, 85, 0, 0, 2, 83, 0, 0, 0, 33, 0, 0, 0, 96,
+ 0, 0, 2, 83, 0, 0, 0, 33, 0, 0, 0, 85, 0, 0, 2, 84, 0, 0, 0, 35, 0, 0, 0,150, 0, 0, 2, 84, 0, 0, 0, 35,
+ 0, 0, 0,150, 0, 0, 2, 85, 0, 0, 0, 35, 0, 0, 0,151, 0, 0, 2, 85, 0, 0, 0, 35, 0, 0, 0,151, 0, 0, 2, 86,
+ 0, 0, 0, 35, 0, 0, 0,152, 0, 0, 2, 86, 0, 0, 0, 35, 0, 0, 0,150, 0, 0, 2, 87, 0, 0, 0, 35, 0, 0, 0,152,
+ 0, 0, 2, 87, 0, 0, 0, 35, 0, 0, 0, 95, 0, 0, 2, 88, 0, 0, 0, 33, 0, 0, 0, 97, 0, 0, 2, 88, 0, 0, 0, 33,
+ 0, 0, 0, 97, 0, 0, 2, 89, 0, 0, 0, 35, 0, 0, 0,152, 0, 0, 2, 89, 0, 0, 0, 35, 0, 0, 0, 95, 0, 0, 2, 90,
+ 0, 0, 0, 35, 0, 0, 0,152, 0, 0, 2, 90, 0, 0, 0, 35, 0, 0, 0, 94, 0, 0, 2, 91, 0, 0, 0, 35, 0, 0, 0,151,
+ 0, 0, 2, 91, 0, 0, 0, 35, 0, 0, 0, 84, 0, 0, 2, 92, 0, 0, 0, 35, 0, 0, 0,151, 0, 0, 2, 92, 0, 0, 0, 35,
+ 0, 0, 0, 84, 0, 0, 2, 93, 0, 0, 0, 33, 0, 0, 0, 94, 0, 0, 2, 93, 0, 0, 0, 33, 0, 0, 0, 98, 0, 0, 2, 94,
+ 0, 0, 0, 35, 0, 0, 0,153, 0, 0, 2, 94, 0, 0, 0, 35, 0, 0, 0, 87, 0, 0, 2, 95, 0, 0, 0, 33, 0, 0, 0, 98,
+ 0, 0, 2, 95, 0, 0, 0, 33, 0, 0, 0, 87, 0, 0, 2, 96, 0, 0, 0, 35, 0, 0, 0,153, 0, 0, 2, 96, 0, 0, 0, 35,
+ 0, 0, 0,153, 0, 0, 2, 97, 0, 0, 0, 35, 0, 0, 0,154, 0, 0, 2, 97, 0, 0, 0, 35, 0, 0, 0,154, 0, 0, 2, 98,
+ 0, 0, 0, 35, 0, 0, 0,155, 0, 0, 2, 98, 0, 0, 0, 35, 0, 0, 0,153, 0, 0, 2, 99, 0, 0, 0, 35, 0, 0, 0,155,
+ 0, 0, 2, 99, 0, 0, 0, 35, 0, 0, 0, 97, 0, 0, 2,100, 0, 0, 0, 33, 0, 0, 0, 99, 0, 0, 2,100, 0, 0, 0, 33,
+ 0, 0, 0, 99, 0, 0, 2,101, 0, 0, 0, 35, 0, 0, 0,155, 0, 0, 2,101, 0, 0, 0, 35, 0, 0, 0, 97, 0, 0, 2,102,
+ 0, 0, 0, 35, 0, 0, 0,155, 0, 0, 2,102, 0, 0, 0, 35, 0, 0, 0, 96, 0, 0, 2,103, 0, 0, 0, 35, 0, 0, 0,154,
+ 0, 0, 2,103, 0, 0, 0, 35, 0, 0, 0, 86, 0, 0, 2,104, 0, 0, 0, 35, 0, 0, 0,154, 0, 0, 2,104, 0, 0, 0, 35,
+ 0, 0, 0, 86, 0, 0, 2,105, 0, 0, 0, 33, 0, 0, 0, 96, 0, 0, 2,105, 0, 0, 0, 33, 0, 0, 0,100, 0, 0, 2,106,
+ 0, 0, 0, 35, 0, 0, 0,156, 0, 0, 2,106, 0, 0, 0, 35, 0, 0, 0, 89, 0, 0, 2,107, 0, 0, 0, 33, 0, 0, 0,100,
+ 0, 0, 2,107, 0, 0, 0, 33, 0, 0, 0, 89, 0, 0, 2,108, 0, 0, 0, 35, 0, 0, 0,156, 0, 0, 2,108, 0, 0, 0, 35,
+ 0, 0, 0,156, 0, 0, 2,109, 0, 0, 0, 35, 0, 0, 0,157, 0, 0, 2,109, 0, 0, 0, 35, 0, 0, 0,157, 0, 0, 2,110,
+ 0, 0, 0, 35, 0, 0, 0,158, 0, 0, 2,110, 0, 0, 0, 35, 0, 0, 0,156, 0, 0, 2,111, 0, 0, 0, 35, 0, 0, 0,158,
+ 0, 0, 2,111, 0, 0, 0, 35, 0, 0, 0, 99, 0, 0, 2,112, 0, 0, 0, 33, 0, 0, 0,101, 0, 0, 2,112, 0, 0, 0, 33,
+ 0, 0, 0,101, 0, 0, 2,113, 0, 0, 0, 35, 0, 0, 0,158, 0, 0, 2,113, 0, 0, 0, 35, 0, 0, 0, 99, 0, 0, 2,114,
+ 0, 0, 0, 35, 0, 0, 0,158, 0, 0, 2,114, 0, 0, 0, 35, 0, 0, 0, 98, 0, 0, 2,115, 0, 0, 0, 35, 0, 0, 0,157,
+ 0, 0, 2,115, 0, 0, 0, 35, 0, 0, 0, 88, 0, 0, 2,116, 0, 0, 0, 35, 0, 0, 0,157, 0, 0, 2,116, 0, 0, 0, 35,
+ 0, 0, 0, 88, 0, 0, 2,117, 0, 0, 0, 33, 0, 0, 0, 98, 0, 0, 2,117, 0, 0, 0, 33, 0, 0, 0, 92, 0, 0, 2,118,
+ 0, 0, 0, 35, 0, 0, 0,159, 0, 0, 2,118, 0, 0, 0, 35, 0, 0, 0, 91, 0, 0, 2,119, 0, 0, 0, 33, 0, 0, 0, 92,
+ 0, 0, 2,119, 0, 0, 0, 33, 0, 0, 0, 91, 0, 0, 2,120, 0, 0, 0, 35, 0, 0, 0,159, 0, 0, 2,120, 0, 0, 0, 35,
+ 0, 0, 0,159, 0, 0, 2,121, 0, 0, 0, 35, 0, 0, 0,160, 0, 0, 2,121, 0, 0, 0, 35, 0, 0, 0,160, 0, 0, 2,122,
+ 0, 0, 0, 35, 0, 0, 0,161, 0, 0, 2,122, 0, 0, 0, 35, 0, 0, 0,159, 0, 0, 2,123, 0, 0, 0, 35, 0, 0, 0,161,
+ 0, 0, 2,123, 0, 0, 0, 35, 0, 0, 0, 93, 0, 0, 2,124, 0, 0, 0, 33, 0, 0, 0,101, 0, 0, 2,124, 0, 0, 0, 33,
+ 0, 0, 0, 93, 0, 0, 2,125, 0, 0, 0, 35, 0, 0, 0,161, 0, 0, 2,125, 0, 0, 0, 35, 0, 0, 0,101, 0, 0, 2,126,
+ 0, 0, 0, 35, 0, 0, 0,161, 0, 0, 2,126, 0, 0, 0, 35, 0, 0, 0,100, 0, 0, 2,127, 0, 0, 0, 35, 0, 0, 0,160,
+ 0, 0, 2,127, 0, 0, 0, 35, 0, 0, 0, 90, 0, 0, 2,128, 0, 0, 0, 35, 0, 0, 0,160, 0, 0, 2,128, 0, 0, 0, 35,
+ 0, 0, 0, 90, 0, 0, 2,129, 0, 0, 0, 33, 0, 0, 0,100, 0, 0, 2,129, 0, 0, 0, 33, 0, 0, 1, 27, 0, 0, 1,146,
+ 0, 0, 0, 35, 0, 0, 0,171, 0, 0, 1,146, 0, 0, 0, 35, 0, 0, 0,171, 0, 0, 1, 27, 0, 0, 0, 35, 0, 0, 1,146,
+ 0, 0, 1,147, 0, 0, 0, 35, 0, 0, 1,146, 0, 0, 1,148, 0, 0, 0, 35, 0, 0, 1,147, 0, 0, 1,148, 0, 0, 0, 35,
+ 0, 0, 0,165, 0, 0, 1, 26, 0, 0, 0, 35, 0, 0, 0,165, 0, 0, 1,148, 0, 0, 0, 35, 0, 0, 1, 26, 0, 0, 1,148,
+ 0, 0, 0, 35, 0, 0, 0,164, 0, 0, 1,147, 0, 0, 0, 35, 0, 0, 0,164, 0, 0, 0,170, 0, 0, 0, 35, 0, 0, 0,170,
+ 0, 0, 1,147, 0, 0, 0, 35, 0, 0, 1, 26, 0, 0, 1,149, 0, 0, 0, 35, 0, 0, 1, 28, 0, 0, 1,149, 0, 0, 0, 35,
+ 0, 0, 1, 26, 0, 0, 1, 28, 0, 0, 0, 35, 0, 0, 1,149, 0, 0, 1,150, 0, 0, 0, 35, 0, 0, 1,149, 0, 0, 1,151,
+ 0, 0, 0, 35, 0, 0, 1,150, 0, 0, 1,151, 0, 0, 0, 35, 0, 0, 1, 27, 0, 0, 1, 31, 0, 0, 0, 35, 0, 0, 1, 31,
+ 0, 0, 1,151, 0, 0, 0, 35, 0, 0, 1, 27, 0, 0, 1,151, 0, 0, 0, 35, 0, 0, 1, 30, 0, 0, 1,150, 0, 0, 0, 35,
+ 0, 0, 1, 29, 0, 0, 1, 30, 0, 0, 0, 35, 0, 0, 1, 29, 0, 0, 1,150, 0, 0, 0, 35, 0, 0, 0,168, 0, 0, 1,152,
+ 0, 0, 0, 35, 0, 0, 0,172, 0, 0, 1,152, 0, 0, 0, 35, 0, 0, 0,168, 0, 0, 0,172, 0, 0, 0, 35, 0, 0, 1,152,
+ 0, 0, 1,153, 0, 0, 0, 35, 0, 0, 1,152, 0, 0, 1,154, 0, 0, 0, 35, 0, 0, 1,153, 0, 0, 1,154, 0, 0, 0, 35,
+ 0, 0, 0,169, 0, 0, 1, 30, 0, 0, 0, 35, 0, 0, 1, 30, 0, 0, 1,154, 0, 0, 0, 35, 0, 0, 0,169, 0, 0, 1,154,
+ 0, 0, 0, 35, 0, 0, 1, 31, 0, 0, 1,153, 0, 0, 0, 35, 0, 0, 0,173, 0, 0, 1, 31, 0, 0, 0, 35, 0, 0, 0,173,
+ 0, 0, 1,153, 0, 0, 0, 35, 0, 0, 0,167, 0, 0, 1,155, 0, 0, 0, 35, 0, 0, 1, 29, 0, 0, 1,155, 0, 0, 0, 35,
+ 0, 0, 0,167, 0, 0, 1, 29, 0, 0, 0, 35, 0, 0, 1,155, 0, 0, 1,156, 0, 0, 0, 35, 0, 0, 1,155, 0, 0, 1,157,
+ 0, 0, 0, 35, 0, 0, 1,156, 0, 0, 1,157, 0, 0, 0, 35, 0, 0, 0,162, 0, 0, 0,166, 0, 0, 0, 35, 0, 0, 0,162,
+ 0, 0, 1,157, 0, 0, 0, 35, 0, 0, 0,166, 0, 0, 1,157, 0, 0, 0, 35, 0, 0, 0,163, 0, 0, 1,156, 0, 0, 0, 35,
+ 0, 0, 0,163, 0, 0, 1, 28, 0, 0, 0, 35, 0, 0, 1, 28, 0, 0, 1,156, 0, 0, 0, 35, 0, 0, 1, 33, 0, 0, 1,158,
+ 0, 0, 0, 35, 0, 0, 0,179, 0, 0, 1, 33, 0, 0, 0, 35, 0, 0, 0,179, 0, 0, 1,158, 0, 0, 0, 35, 0, 0, 1,158,
+ 0, 0, 1,159, 0, 0, 0, 35, 0, 0, 1,159, 0, 0, 1,160, 0, 0, 0, 35, 0, 0, 1,158, 0, 0, 1,160, 0, 0, 0, 35,
+ 0, 0, 0,165, 0, 0, 1, 32, 0, 0, 0, 35, 0, 0, 1, 32, 0, 0, 1,160, 0, 0, 0, 35, 0, 0, 0,165, 0, 0, 1,160,
+ 0, 0, 0, 35, 0, 0, 0,164, 0, 0, 1,159, 0, 0, 0, 35, 0, 0, 0,178, 0, 0, 1,159, 0, 0, 0, 35, 0, 0, 0,164,
+ 0, 0, 0,178, 0, 0, 0, 35, 0, 0, 1, 32, 0, 0, 1,161, 0, 0, 0, 35, 0, 0, 1, 32, 0, 0, 1, 34, 0, 0, 0, 35,
+ 0, 0, 1, 34, 0, 0, 1,161, 0, 0, 0, 35, 0, 0, 1,161, 0, 0, 1,162, 0, 0, 0, 35, 0, 0, 1,162, 0, 0, 1,163,
+ 0, 0, 0, 35, 0, 0, 1,161, 0, 0, 1,163, 0, 0, 0, 35, 0, 0, 1, 33, 0, 0, 1, 37, 0, 0, 0, 35, 0, 0, 1, 33,
+ 0, 0, 1,163, 0, 0, 0, 35, 0, 0, 1, 37, 0, 0, 1,163, 0, 0, 0, 35, 0, 0, 1, 36, 0, 0, 1,162, 0, 0, 0, 35,
+ 0, 0, 1, 35, 0, 0, 1,162, 0, 0, 0, 35, 0, 0, 1, 35, 0, 0, 1, 36, 0, 0, 0, 35, 0, 0, 0,176, 0, 0, 1,164,
+ 0, 0, 0, 35, 0, 0, 0,176, 0, 0, 0,180, 0, 0, 0, 35, 0, 0, 0,180, 0, 0, 1,164, 0, 0, 0, 35, 0, 0, 1,164,
+ 0, 0, 1,165, 0, 0, 0, 35, 0, 0, 1,165, 0, 0, 1,166, 0, 0, 0, 35, 0, 0, 1,164, 0, 0, 1,166, 0, 0, 0, 35,
+ 0, 0, 0,177, 0, 0, 1, 36, 0, 0, 0, 35, 0, 0, 0,177, 0, 0, 1,166, 0, 0, 0, 35, 0, 0, 1, 36, 0, 0, 1,166,
+ 0, 0, 0, 35, 0, 0, 1, 37, 0, 0, 1,165, 0, 0, 0, 35, 0, 0, 0,181, 0, 0, 1,165, 0, 0, 0, 35, 0, 0, 0,181,
+ 0, 0, 1, 37, 0, 0, 0, 35, 0, 0, 0,175, 0, 0, 1,167, 0, 0, 0, 35, 0, 0, 0,175, 0, 0, 1, 35, 0, 0, 0, 35,
+ 0, 0, 1, 35, 0, 0, 1,167, 0, 0, 0, 35, 0, 0, 1,167, 0, 0, 1,168, 0, 0, 0, 35, 0, 0, 1,168, 0, 0, 1,169,
+ 0, 0, 0, 35, 0, 0, 1,167, 0, 0, 1,169, 0, 0, 0, 35, 0, 0, 0,162, 0, 0, 0,174, 0, 0, 0, 35, 0, 0, 0,174,
+ 0, 0, 1,169, 0, 0, 0, 35, 0, 0, 0,162, 0, 0, 1,169, 0, 0, 0, 35, 0, 0, 0,163, 0, 0, 1,168, 0, 0, 0, 35,
+ 0, 0, 1, 34, 0, 0, 1,168, 0, 0, 0, 35, 0, 0, 0,163, 0, 0, 1, 34, 0, 0, 0, 35, 0, 0, 1, 39, 0, 0, 1,170,
+ 0, 0, 0, 35, 0, 0, 0,187, 0, 0, 1,170, 0, 0, 0, 35, 0, 0, 0,187, 0, 0, 1, 39, 0, 0, 0, 35, 0, 0, 1,170,
+ 0, 0, 1,171, 0, 0, 0, 35, 0, 0, 1,170, 0, 0, 1,172, 0, 0, 0, 35, 0, 0, 1,171, 0, 0, 1,172, 0, 0, 0, 35,
+ 0, 0, 0,169, 0, 0, 1, 38, 0, 0, 0, 35, 0, 0, 0,169, 0, 0, 1,172, 0, 0, 0, 35, 0, 0, 1, 38, 0, 0, 1,172,
+ 0, 0, 0, 35, 0, 0, 0,168, 0, 0, 1,171, 0, 0, 0, 35, 0, 0, 0,168, 0, 0, 0,186, 0, 0, 0, 35, 0, 0, 0,186,
+ 0, 0, 1,171, 0, 0, 0, 35, 0, 0, 1, 38, 0, 0, 1,173, 0, 0, 0, 35, 0, 0, 1, 40, 0, 0, 1,173, 0, 0, 0, 35,
+ 0, 0, 1, 38, 0, 0, 1, 40, 0, 0, 0, 35, 0, 0, 1,173, 0, 0, 1,174, 0, 0, 0, 35, 0, 0, 1,173, 0, 0, 1,175,
+ 0, 0, 0, 35, 0, 0, 1,174, 0, 0, 1,175, 0, 0, 0, 35, 0, 0, 1, 39, 0, 0, 1, 43, 0, 0, 0, 35, 0, 0, 1, 43,
+ 0, 0, 1,175, 0, 0, 0, 35, 0, 0, 1, 39, 0, 0, 1,175, 0, 0, 0, 35, 0, 0, 1, 42, 0, 0, 1,174, 0, 0, 0, 35,
+ 0, 0, 1, 41, 0, 0, 1, 42, 0, 0, 0, 35, 0, 0, 1, 41, 0, 0, 1,174, 0, 0, 0, 35, 0, 0, 0,184, 0, 0, 1,176,
+ 0, 0, 0, 35, 0, 0, 0,188, 0, 0, 1,176, 0, 0, 0, 35, 0, 0, 0,184, 0, 0, 0,188, 0, 0, 0, 35, 0, 0, 1,176,
+ 0, 0, 1,177, 0, 0, 0, 35, 0, 0, 1,176, 0, 0, 1,178, 0, 0, 0, 35, 0, 0, 1,177, 0, 0, 1,178, 0, 0, 0, 35,
+ 0, 0, 0,185, 0, 0, 1, 42, 0, 0, 0, 35, 0, 0, 1, 42, 0, 0, 1,178, 0, 0, 0, 35, 0, 0, 0,185, 0, 0, 1,178,
+ 0, 0, 0, 35, 0, 0, 1, 43, 0, 0, 1,177, 0, 0, 0, 35, 0, 0, 0,189, 0, 0, 1, 43, 0, 0, 0, 35, 0, 0, 0,189,
+ 0, 0, 1,177, 0, 0, 0, 35, 0, 0, 0,183, 0, 0, 1,179, 0, 0, 0, 35, 0, 0, 1, 41, 0, 0, 1,179, 0, 0, 0, 35,
+ 0, 0, 0,183, 0, 0, 1, 41, 0, 0, 0, 35, 0, 0, 1,179, 0, 0, 1,180, 0, 0, 0, 35, 0, 0, 1,179, 0, 0, 1,181,
+ 0, 0, 0, 35, 0, 0, 1,180, 0, 0, 1,181, 0, 0, 0, 35, 0, 0, 0,166, 0, 0, 0,182, 0, 0, 0, 35, 0, 0, 0,166,
+ 0, 0, 1,181, 0, 0, 0, 35, 0, 0, 0,182, 0, 0, 1,181, 0, 0, 0, 35, 0, 0, 0,167, 0, 0, 1,180, 0, 0, 0, 35,
+ 0, 0, 0,167, 0, 0, 1, 40, 0, 0, 0, 35, 0, 0, 1, 40, 0, 0, 1,180, 0, 0, 0, 35, 0, 0, 1, 45, 0, 0, 1,182,
+ 0, 0, 0, 35, 0, 0, 0,195, 0, 0, 1,182, 0, 0, 0, 35, 0, 0, 0,195, 0, 0, 1, 45, 0, 0, 0, 35, 0, 0, 1,182,
+ 0, 0, 1,183, 0, 0, 0, 35, 0, 0, 1,182, 0, 0, 1,184, 0, 0, 0, 35, 0, 0, 1,183, 0, 0, 1,184, 0, 0, 0, 35,
+ 0, 0, 0,185, 0, 0, 1, 44, 0, 0, 0, 35, 0, 0, 0,185, 0, 0, 1,184, 0, 0, 0, 35, 0, 0, 1, 44, 0, 0, 1,184,
+ 0, 0, 0, 35, 0, 0, 0,184, 0, 0, 1,183, 0, 0, 0, 35, 0, 0, 0,184, 0, 0, 0,194, 0, 0, 0, 35, 0, 0, 0,194,
+ 0, 0, 1,183, 0, 0, 0, 35, 0, 0, 1, 44, 0, 0, 1,185, 0, 0, 0, 35, 0, 0, 1, 46, 0, 0, 1,185, 0, 0, 0, 35,
+ 0, 0, 1, 44, 0, 0, 1, 46, 0, 0, 0, 35, 0, 0, 1,185, 0, 0, 1,186, 0, 0, 0, 35, 0, 0, 1,185, 0, 0, 1,187,
+ 0, 0, 0, 35, 0, 0, 1,186, 0, 0, 1,187, 0, 0, 0, 35, 0, 0, 1, 45, 0, 0, 1, 49, 0, 0, 0, 35, 0, 0, 1, 49,
+ 0, 0, 1,187, 0, 0, 0, 35, 0, 0, 1, 45, 0, 0, 1,187, 0, 0, 0, 35, 0, 0, 1, 48, 0, 0, 1,186, 0, 0, 0, 35,
+ 0, 0, 1, 47, 0, 0, 1, 48, 0, 0, 0, 35, 0, 0, 1, 47, 0, 0, 1,186, 0, 0, 0, 35, 0, 0, 0,192, 0, 0, 1,188,
+ 0, 0, 0, 35, 0, 0, 0,196, 0, 0, 1,188, 0, 0, 0, 35, 0, 0, 0,192, 0, 0, 0,196, 0, 0, 0, 35, 0, 0, 1,188,
+ 0, 0, 1,189, 0, 0, 0, 35, 0, 0, 1,188, 0, 0, 1,190, 0, 0, 0, 35, 0, 0, 1,189, 0, 0, 1,190, 0, 0, 0, 35,
+ 0, 0, 0,193, 0, 0, 1, 48, 0, 0, 0, 35, 0, 0, 1, 48, 0, 0, 1,190, 0, 0, 0, 35, 0, 0, 0,193, 0, 0, 1,190,
+ 0, 0, 0, 35, 0, 0, 1, 49, 0, 0, 1,189, 0, 0, 0, 35, 0, 0, 0,197, 0, 0, 1, 49, 0, 0, 0, 35, 0, 0, 0,197,
+ 0, 0, 1,189, 0, 0, 0, 35, 0, 0, 0,191, 0, 0, 1,191, 0, 0, 0, 35, 0, 0, 1, 47, 0, 0, 1,191, 0, 0, 0, 35,
+ 0, 0, 0,191, 0, 0, 1, 47, 0, 0, 0, 35, 0, 0, 1,191, 0, 0, 1,192, 0, 0, 0, 35, 0, 0, 1,191, 0, 0, 1,193,
+ 0, 0, 0, 35, 0, 0, 1,192, 0, 0, 1,193, 0, 0, 0, 35, 0, 0, 0,182, 0, 0, 0,190, 0, 0, 0, 35, 0, 0, 0,182,
+ 0, 0, 1,193, 0, 0, 0, 35, 0, 0, 0,190, 0, 0, 1,193, 0, 0, 0, 35, 0, 0, 0,183, 0, 0, 1,192, 0, 0, 0, 35,
+ 0, 0, 0,183, 0, 0, 1, 46, 0, 0, 0, 35, 0, 0, 1, 46, 0, 0, 1,192, 0, 0, 0, 35, 0, 0, 1, 51, 0, 0, 1,194,
+ 0, 0, 0, 35, 0, 0, 0,199, 0, 0, 1,194, 0, 0, 0, 35, 0, 0, 0,199, 0, 0, 1, 51, 0, 0, 0, 35, 0, 0, 1,194,
+ 0, 0, 1,195, 0, 0, 0, 35, 0, 0, 1,194, 0, 0, 1,196, 0, 0, 0, 35, 0, 0, 1,195, 0, 0, 1,196, 0, 0, 0, 35,
+ 0, 0, 0,193, 0, 0, 1, 50, 0, 0, 0, 35, 0, 0, 0,193, 0, 0, 1,196, 0, 0, 0, 35, 0, 0, 1, 50, 0, 0, 1,196,
+ 0, 0, 0, 35, 0, 0, 0,192, 0, 0, 1,195, 0, 0, 0, 35, 0, 0, 0,192, 0, 0, 0,198, 0, 0, 0, 35, 0, 0, 0,198,
+ 0, 0, 1,195, 0, 0, 0, 35, 0, 0, 1, 50, 0, 0, 1,197, 0, 0, 0, 35, 0, 0, 1, 53, 0, 0, 1,197, 0, 0, 0, 35,
+ 0, 0, 1, 50, 0, 0, 1, 53, 0, 0, 0, 35, 0, 0, 1,197, 0, 0, 1,198, 0, 0, 0, 35, 0, 0, 1,197, 0, 0, 1,199,
+ 0, 0, 0, 35, 0, 0, 1,198, 0, 0, 1,199, 0, 0, 0, 35, 0, 0, 1, 51, 0, 0, 1, 55, 0, 0, 0, 35, 0, 0, 1, 55,
+ 0, 0, 1,199, 0, 0, 0, 35, 0, 0, 1, 51, 0, 0, 1,199, 0, 0, 0, 35, 0, 0, 1, 54, 0, 0, 1,198, 0, 0, 0, 35,
+ 0, 0, 1, 52, 0, 0, 1, 54, 0, 0, 0, 35, 0, 0, 1, 52, 0, 0, 1,198, 0, 0, 0, 35, 0, 0, 0,176, 0, 0, 1,200,
+ 0, 0, 0, 35, 0, 0, 0,200, 0, 0, 1,200, 0, 0, 0, 35, 0, 0, 0,176, 0, 0, 0,200, 0, 0, 0, 35, 0, 0, 1,200,
+ 0, 0, 1,201, 0, 0, 0, 35, 0, 0, 1,200, 0, 0, 1,202, 0, 0, 0, 35, 0, 0, 1,201, 0, 0, 1,202, 0, 0, 0, 35,
+ 0, 0, 0,177, 0, 0, 1, 54, 0, 0, 0, 35, 0, 0, 1, 54, 0, 0, 1,202, 0, 0, 0, 35, 0, 0, 0,177, 0, 0, 1,202,
+ 0, 0, 0, 35, 0, 0, 1, 55, 0, 0, 1,201, 0, 0, 0, 35, 0, 0, 0,201, 0, 0, 1, 55, 0, 0, 0, 35, 0, 0, 0,201,
+ 0, 0, 1,201, 0, 0, 0, 35, 0, 0, 0,175, 0, 0, 1,203, 0, 0, 0, 35, 0, 0, 1, 52, 0, 0, 1,203, 0, 0, 0, 35,
+ 0, 0, 0,175, 0, 0, 1, 52, 0, 0, 0, 35, 0, 0, 1,203, 0, 0, 1,204, 0, 0, 0, 35, 0, 0, 1,203, 0, 0, 1,205,
+ 0, 0, 0, 35, 0, 0, 1,204, 0, 0, 1,205, 0, 0, 0, 35, 0, 0, 0,174, 0, 0, 0,190, 0, 0, 0, 35, 0, 0, 0,190,
+ 0, 0, 1,205, 0, 0, 0, 35, 0, 0, 0,174, 0, 0, 1,205, 0, 0, 0, 35, 0, 0, 0,191, 0, 0, 1,204, 0, 0, 0, 35,
+ 0, 0, 0,191, 0, 0, 1, 53, 0, 0, 0, 35, 0, 0, 1, 53, 0, 0, 1,204, 0, 0, 0, 35, 0, 0, 1, 57, 0, 0, 1,206,
+ 0, 0, 0, 35, 0, 0, 0,207, 0, 0, 1, 57, 0, 0, 0, 35, 0, 0, 0,207, 0, 0, 1,206, 0, 0, 0, 35, 0, 0, 1,206,
+ 0, 0, 1,207, 0, 0, 0, 35, 0, 0, 1,207, 0, 0, 1,208, 0, 0, 0, 35, 0, 0, 1,206, 0, 0, 1,208, 0, 0, 0, 35,
+ 0, 0, 0,179, 0, 0, 1, 56, 0, 0, 0, 35, 0, 0, 1, 56, 0, 0, 1,208, 0, 0, 0, 35, 0, 0, 0,179, 0, 0, 1,208,
+ 0, 0, 0, 35, 0, 0, 0,178, 0, 0, 1,207, 0, 0, 0, 35, 0, 0, 0,206, 0, 0, 1,207, 0, 0, 0, 35, 0, 0, 0,178,
+ 0, 0, 0,206, 0, 0, 0, 35, 0, 0, 1, 56, 0, 0, 1,209, 0, 0, 0, 35, 0, 0, 1, 56, 0, 0, 1, 58, 0, 0, 0, 35,
+ 0, 0, 1, 58, 0, 0, 1,209, 0, 0, 0, 35, 0, 0, 1,209, 0, 0, 1,210, 0, 0, 0, 35, 0, 0, 1,210, 0, 0, 1,211,
+ 0, 0, 0, 35, 0, 0, 1,209, 0, 0, 1,211, 0, 0, 0, 35, 0, 0, 1, 57, 0, 0, 1, 61, 0, 0, 0, 35, 0, 0, 1, 57,
+ 0, 0, 1,211, 0, 0, 0, 35, 0, 0, 1, 61, 0, 0, 1,211, 0, 0, 0, 35, 0, 0, 1, 60, 0, 0, 1,210, 0, 0, 0, 35,
+ 0, 0, 1, 59, 0, 0, 1,210, 0, 0, 0, 35, 0, 0, 1, 59, 0, 0, 1, 60, 0, 0, 0, 35, 0, 0, 0,204, 0, 0, 1,212,
+ 0, 0, 0, 35, 0, 0, 0,204, 0, 0, 0,208, 0, 0, 0, 35, 0, 0, 0,208, 0, 0, 1,212, 0, 0, 0, 35, 0, 0, 1,212,
+ 0, 0, 1,213, 0, 0, 0, 35, 0, 0, 1,213, 0, 0, 1,214, 0, 0, 0, 35, 0, 0, 1,212, 0, 0, 1,214, 0, 0, 0, 35,
+ 0, 0, 0,205, 0, 0, 1, 60, 0, 0, 0, 35, 0, 0, 0,205, 0, 0, 1,214, 0, 0, 0, 35, 0, 0, 1, 60, 0, 0, 1,214,
+ 0, 0, 0, 35, 0, 0, 1, 61, 0, 0, 1,213, 0, 0, 0, 35, 0, 0, 0,209, 0, 0, 1,213, 0, 0, 0, 35, 0, 0, 0,209,
+ 0, 0, 1, 61, 0, 0, 0, 35, 0, 0, 0,203, 0, 0, 1,215, 0, 0, 0, 35, 0, 0, 0,203, 0, 0, 1, 59, 0, 0, 0, 35,
+ 0, 0, 1, 59, 0, 0, 1,215, 0, 0, 0, 35, 0, 0, 1,215, 0, 0, 1,216, 0, 0, 0, 35, 0, 0, 1,216, 0, 0, 1,217,
+ 0, 0, 0, 35, 0, 0, 1,215, 0, 0, 1,217, 0, 0, 0, 35, 0, 0, 0,180, 0, 0, 0,202, 0, 0, 0, 35, 0, 0, 0,202,
+ 0, 0, 1,217, 0, 0, 0, 35, 0, 0, 0,180, 0, 0, 1,217, 0, 0, 0, 35, 0, 0, 0,181, 0, 0, 1,216, 0, 0, 0, 35,
+ 0, 0, 1, 58, 0, 0, 1,216, 0, 0, 0, 35, 0, 0, 0,181, 0, 0, 1, 58, 0, 0, 0, 35, 0, 0, 1, 63, 0, 0, 1,218,
+ 0, 0, 0, 35, 0, 0, 0,215, 0, 0, 1, 63, 0, 0, 0, 35, 0, 0, 0,215, 0, 0, 1,218, 0, 0, 0, 35, 0, 0, 1,218,
+ 0, 0, 1,219, 0, 0, 0, 35, 0, 0, 1,219, 0, 0, 1,220, 0, 0, 0, 35, 0, 0, 1,218, 0, 0, 1,220, 0, 0, 0, 35,
+ 0, 0, 0,173, 0, 0, 1, 62, 0, 0, 0, 35, 0, 0, 1, 62, 0, 0, 1,220, 0, 0, 0, 35, 0, 0, 0,173, 0, 0, 1,220,
+ 0, 0, 0, 35, 0, 0, 0,172, 0, 0, 1,219, 0, 0, 0, 35, 0, 0, 0,214, 0, 0, 1,219, 0, 0, 0, 35, 0, 0, 0,172,
+ 0, 0, 0,214, 0, 0, 0, 35, 0, 0, 1, 62, 0, 0, 1,221, 0, 0, 0, 35, 0, 0, 1, 62, 0, 0, 1, 64, 0, 0, 0, 35,
+ 0, 0, 1, 64, 0, 0, 1,221, 0, 0, 0, 35, 0, 0, 1,221, 0, 0, 1,222, 0, 0, 0, 35, 0, 0, 1,222, 0, 0, 1,223,
+ 0, 0, 0, 35, 0, 0, 1,221, 0, 0, 1,223, 0, 0, 0, 35, 0, 0, 1, 63, 0, 0, 1, 67, 0, 0, 0, 35, 0, 0, 1, 63,
+ 0, 0, 1,223, 0, 0, 0, 35, 0, 0, 1, 67, 0, 0, 1,223, 0, 0, 0, 35, 0, 0, 1, 66, 0, 0, 1,222, 0, 0, 0, 35,
+ 0, 0, 1, 65, 0, 0, 1,222, 0, 0, 0, 35, 0, 0, 1, 65, 0, 0, 1, 66, 0, 0, 0, 35, 0, 0, 0,212, 0, 0, 1,224,
+ 0, 0, 0, 35, 0, 0, 0,212, 0, 0, 0,216, 0, 0, 0, 35, 0, 0, 0,216, 0, 0, 1,224, 0, 0, 0, 35, 0, 0, 1,224,
+ 0, 0, 1,225, 0, 0, 0, 35, 0, 0, 1,225, 0, 0, 1,226, 0, 0, 0, 35, 0, 0, 1,224, 0, 0, 1,226, 0, 0, 0, 35,
+ 0, 0, 0,213, 0, 0, 1, 66, 0, 0, 0, 35, 0, 0, 0,213, 0, 0, 1,226, 0, 0, 0, 35, 0, 0, 1, 66, 0, 0, 1,226,
+ 0, 0, 0, 35, 0, 0, 1, 67, 0, 0, 1,225, 0, 0, 0, 35, 0, 0, 0,217, 0, 0, 1,225, 0, 0, 0, 35, 0, 0, 0,217,
+ 0, 0, 1, 67, 0, 0, 0, 35, 0, 0, 0,211, 0, 0, 1,227, 0, 0, 0, 35, 0, 0, 0,211, 0, 0, 1, 65, 0, 0, 0, 35,
+ 0, 0, 1, 65, 0, 0, 1,227, 0, 0, 0, 35, 0, 0, 1,227, 0, 0, 1,228, 0, 0, 0, 35, 0, 0, 1,228, 0, 0, 1,229,
+ 0, 0, 0, 35, 0, 0, 1,227, 0, 0, 1,229, 0, 0, 0, 35, 0, 0, 0,170, 0, 0, 0,210, 0, 0, 0, 35, 0, 0, 0,210,
+ 0, 0, 1,229, 0, 0, 0, 35, 0, 0, 0,170, 0, 0, 1,229, 0, 0, 0, 35, 0, 0, 0,171, 0, 0, 1,228, 0, 0, 0, 35,
+ 0, 0, 1, 64, 0, 0, 1,228, 0, 0, 0, 35, 0, 0, 0,171, 0, 0, 1, 64, 0, 0, 0, 35, 0, 0, 1, 69, 0, 0, 1,230,
+ 0, 0, 0, 35, 0, 0, 0,223, 0, 0, 1, 69, 0, 0, 0, 35, 0, 0, 0,223, 0, 0, 1,230, 0, 0, 0, 35, 0, 0, 1,230,
+ 0, 0, 1,231, 0, 0, 0, 35, 0, 0, 1,231, 0, 0, 1,232, 0, 0, 0, 35, 0, 0, 1,230, 0, 0, 1,232, 0, 0, 0, 35,
+ 0, 0, 0,189, 0, 0, 1, 68, 0, 0, 0, 35, 0, 0, 1, 68, 0, 0, 1,232, 0, 0, 0, 35, 0, 0, 0,189, 0, 0, 1,232,
+ 0, 0, 0, 35, 0, 0, 0,188, 0, 0, 1,231, 0, 0, 0, 35, 0, 0, 0,222, 0, 0, 1,231, 0, 0, 0, 35, 0, 0, 0,188,
+ 0, 0, 0,222, 0, 0, 0, 35, 0, 0, 1, 68, 0, 0, 1,233, 0, 0, 0, 35, 0, 0, 1, 68, 0, 0, 1, 70, 0, 0, 0, 35,
+ 0, 0, 1, 70, 0, 0, 1,233, 0, 0, 0, 35, 0, 0, 1,233, 0, 0, 1,234, 0, 0, 0, 35, 0, 0, 1,234, 0, 0, 1,235,
+ 0, 0, 0, 35, 0, 0, 1,233, 0, 0, 1,235, 0, 0, 0, 35, 0, 0, 1, 69, 0, 0, 1, 73, 0, 0, 0, 35, 0, 0, 1, 69,
+ 0, 0, 1,235, 0, 0, 0, 35, 0, 0, 1, 73, 0, 0, 1,235, 0, 0, 0, 35, 0, 0, 1, 72, 0, 0, 1,234, 0, 0, 0, 35,
+ 0, 0, 1, 71, 0, 0, 1,234, 0, 0, 0, 35, 0, 0, 1, 71, 0, 0, 1, 72, 0, 0, 0, 35, 0, 0, 0,220, 0, 0, 1,236,
+ 0, 0, 0, 35, 0, 0, 0,220, 0, 0, 0,224, 0, 0, 0, 35, 0, 0, 0,224, 0, 0, 1,236, 0, 0, 0, 35, 0, 0, 1,236,
+ 0, 0, 1,237, 0, 0, 0, 35, 0, 0, 1,237, 0, 0, 1,238, 0, 0, 0, 35, 0, 0, 1,236, 0, 0, 1,238, 0, 0, 0, 35,
+ 0, 0, 0,221, 0, 0, 1, 72, 0, 0, 0, 35, 0, 0, 0,221, 0, 0, 1,238, 0, 0, 0, 35, 0, 0, 1, 72, 0, 0, 1,238,
+ 0, 0, 0, 35, 0, 0, 1, 73, 0, 0, 1,237, 0, 0, 0, 35, 0, 0, 0,225, 0, 0, 1,237, 0, 0, 0, 35, 0, 0, 0,225,
+ 0, 0, 1, 73, 0, 0, 0, 35, 0, 0, 0,219, 0, 0, 1,239, 0, 0, 0, 35, 0, 0, 0,219, 0, 0, 1, 71, 0, 0, 0, 35,
+ 0, 0, 1, 71, 0, 0, 1,239, 0, 0, 0, 35, 0, 0, 1,239, 0, 0, 1,240, 0, 0, 0, 35, 0, 0, 1,240, 0, 0, 1,241,
+ 0, 0, 0, 35, 0, 0, 1,239, 0, 0, 1,241, 0, 0, 0, 35, 0, 0, 0,186, 0, 0, 0,218, 0, 0, 0, 35, 0, 0, 0,218,
+ 0, 0, 1,241, 0, 0, 0, 35, 0, 0, 0,186, 0, 0, 1,241, 0, 0, 0, 35, 0, 0, 0,187, 0, 0, 1,240, 0, 0, 0, 35,
+ 0, 0, 1, 70, 0, 0, 1,240, 0, 0, 0, 35, 0, 0, 0,187, 0, 0, 1, 70, 0, 0, 0, 35, 0, 0, 1, 75, 0, 0, 1,242,
+ 0, 0, 0, 35, 0, 0, 0,231, 0, 0, 1, 75, 0, 0, 0, 35, 0, 0, 0,231, 0, 0, 1,242, 0, 0, 0, 35, 0, 0, 1,242,
+ 0, 0, 1,243, 0, 0, 0, 35, 0, 0, 1,243, 0, 0, 1,244, 0, 0, 0, 35, 0, 0, 1,242, 0, 0, 1,244, 0, 0, 0, 35,
+ 0, 0, 0,197, 0, 0, 1, 74, 0, 0, 0, 35, 0, 0, 1, 74, 0, 0, 1,244, 0, 0, 0, 35, 0, 0, 0,197, 0, 0, 1,244,
+ 0, 0, 0, 35, 0, 0, 0,196, 0, 0, 1,243, 0, 0, 0, 35, 0, 0, 0,230, 0, 0, 1,243, 0, 0, 0, 35, 0, 0, 0,196,
+ 0, 0, 0,230, 0, 0, 0, 35, 0, 0, 1, 74, 0, 0, 1,245, 0, 0, 0, 35, 0, 0, 1, 74, 0, 0, 1, 76, 0, 0, 0, 35,
+ 0, 0, 1, 76, 0, 0, 1,245, 0, 0, 0, 35, 0, 0, 1,245, 0, 0, 1,246, 0, 0, 0, 35, 0, 0, 1,246, 0, 0, 1,247,
+ 0, 0, 0, 35, 0, 0, 1,245, 0, 0, 1,247, 0, 0, 0, 35, 0, 0, 1, 75, 0, 0, 1, 79, 0, 0, 0, 35, 0, 0, 1, 75,
+ 0, 0, 1,247, 0, 0, 0, 35, 0, 0, 1, 79, 0, 0, 1,247, 0, 0, 0, 35, 0, 0, 1, 78, 0, 0, 1,246, 0, 0, 0, 35,
+ 0, 0, 1, 77, 0, 0, 1,246, 0, 0, 0, 35, 0, 0, 1, 77, 0, 0, 1, 78, 0, 0, 0, 35, 0, 0, 0,228, 0, 0, 1,248,
+ 0, 0, 0, 35, 0, 0, 0,228, 0, 0, 0,232, 0, 0, 0, 35, 0, 0, 0,232, 0, 0, 1,248, 0, 0, 0, 35, 0, 0, 1,248,
+ 0, 0, 1,249, 0, 0, 0, 35, 0, 0, 1,249, 0, 0, 1,250, 0, 0, 0, 35, 0, 0, 1,248, 0, 0, 1,250, 0, 0, 0, 35,
+ 0, 0, 0,229, 0, 0, 1, 78, 0, 0, 0, 35, 0, 0, 0,229, 0, 0, 1,250, 0, 0, 0, 35, 0, 0, 1, 78, 0, 0, 1,250,
+ 0, 0, 0, 35, 0, 0, 1, 79, 0, 0, 1,249, 0, 0, 0, 35, 0, 0, 0,233, 0, 0, 1,249, 0, 0, 0, 35, 0, 0, 0,233,
+ 0, 0, 1, 79, 0, 0, 0, 35, 0, 0, 0,227, 0, 0, 1,251, 0, 0, 0, 35, 0, 0, 0,227, 0, 0, 1, 77, 0, 0, 0, 35,
+ 0, 0, 1, 77, 0, 0, 1,251, 0, 0, 0, 35, 0, 0, 1,251, 0, 0, 1,252, 0, 0, 0, 35, 0, 0, 1,252, 0, 0, 1,253,
+ 0, 0, 0, 35, 0, 0, 1,251, 0, 0, 1,253, 0, 0, 0, 35, 0, 0, 0,194, 0, 0, 0,226, 0, 0, 0, 35, 0, 0, 0,226,
+ 0, 0, 1,253, 0, 0, 0, 35, 0, 0, 0,194, 0, 0, 1,253, 0, 0, 0, 35, 0, 0, 0,195, 0, 0, 1,252, 0, 0, 0, 35,
+ 0, 0, 1, 76, 0, 0, 1,252, 0, 0, 0, 35, 0, 0, 0,195, 0, 0, 1, 76, 0, 0, 0, 35, 0, 0, 1, 81, 0, 0, 1,254,
+ 0, 0, 0, 35, 0, 0, 0,239, 0, 0, 1, 81, 0, 0, 0, 35, 0, 0, 0,239, 0, 0, 1,254, 0, 0, 0, 35, 0, 0, 1,254,
+ 0, 0, 1,255, 0, 0, 0, 35, 0, 0, 1,255, 0, 0, 2, 0, 0, 0, 0, 35, 0, 0, 1,254, 0, 0, 2, 0, 0, 0, 0, 35,
+ 0, 0, 0,201, 0, 0, 1, 80, 0, 0, 0, 35, 0, 0, 1, 80, 0, 0, 2, 0, 0, 0, 0, 35, 0, 0, 0,201, 0, 0, 2, 0,
+ 0, 0, 0, 35, 0, 0, 0,200, 0, 0, 1,255, 0, 0, 0, 35, 0, 0, 0,238, 0, 0, 1,255, 0, 0, 0, 35, 0, 0, 0,200,
+ 0, 0, 0,238, 0, 0, 0, 35, 0, 0, 1, 80, 0, 0, 2, 1, 0, 0, 0, 35, 0, 0, 1, 80, 0, 0, 1, 82, 0, 0, 0, 35,
+ 0, 0, 1, 82, 0, 0, 2, 1, 0, 0, 0, 35, 0, 0, 2, 1, 0, 0, 2, 2, 0, 0, 0, 35, 0, 0, 2, 2, 0, 0, 2, 3,
+ 0, 0, 0, 35, 0, 0, 2, 1, 0, 0, 2, 3, 0, 0, 0, 35, 0, 0, 1, 81, 0, 0, 1, 85, 0, 0, 0, 35, 0, 0, 1, 81,
+ 0, 0, 2, 3, 0, 0, 0, 35, 0, 0, 1, 85, 0, 0, 2, 3, 0, 0, 0, 35, 0, 0, 1, 84, 0, 0, 2, 2, 0, 0, 0, 35,
+ 0, 0, 1, 83, 0, 0, 2, 2, 0, 0, 0, 35, 0, 0, 1, 83, 0, 0, 1, 84, 0, 0, 0, 35, 0, 0, 0,236, 0, 0, 2, 4,
+ 0, 0, 0, 35, 0, 0, 0,236, 0, 0, 0,240, 0, 0, 0, 35, 0, 0, 0,240, 0, 0, 2, 4, 0, 0, 0, 35, 0, 0, 2, 4,
+ 0, 0, 2, 5, 0, 0, 0, 35, 0, 0, 2, 5, 0, 0, 2, 6, 0, 0, 0, 35, 0, 0, 2, 4, 0, 0, 2, 6, 0, 0, 0, 35,
+ 0, 0, 0,237, 0, 0, 1, 84, 0, 0, 0, 35, 0, 0, 0,237, 0, 0, 2, 6, 0, 0, 0, 35, 0, 0, 1, 84, 0, 0, 2, 6,
+ 0, 0, 0, 35, 0, 0, 1, 85, 0, 0, 2, 5, 0, 0, 0, 35, 0, 0, 0,241, 0, 0, 2, 5, 0, 0, 0, 35, 0, 0, 0,241,
+ 0, 0, 1, 85, 0, 0, 0, 35, 0, 0, 0,235, 0, 0, 2, 7, 0, 0, 0, 35, 0, 0, 0,235, 0, 0, 1, 83, 0, 0, 0, 35,
+ 0, 0, 1, 83, 0, 0, 2, 7, 0, 0, 0, 35, 0, 0, 2, 7, 0, 0, 2, 8, 0, 0, 0, 35, 0, 0, 2, 8, 0, 0, 2, 9,
+ 0, 0, 0, 35, 0, 0, 2, 7, 0, 0, 2, 9, 0, 0, 0, 35, 0, 0, 0,198, 0, 0, 0,234, 0, 0, 0, 35, 0, 0, 0,234,
+ 0, 0, 2, 9, 0, 0, 0, 35, 0, 0, 0,198, 0, 0, 2, 9, 0, 0, 0, 35, 0, 0, 0,199, 0, 0, 2, 8, 0, 0, 0, 35,
+ 0, 0, 1, 82, 0, 0, 2, 8, 0, 0, 0, 35, 0, 0, 0,199, 0, 0, 1, 82, 0, 0, 0, 35, 0, 0, 1, 87, 0, 0, 2, 10,
+ 0, 0, 0, 35, 0, 0, 0,245, 0, 0, 2, 10, 0, 0, 0, 35, 0, 0, 0,245, 0, 0, 1, 87, 0, 0, 0, 35, 0, 0, 2, 10,
+ 0, 0, 2, 11, 0, 0, 0, 35, 0, 0, 2, 10, 0, 0, 2, 12, 0, 0, 0, 35, 0, 0, 2, 11, 0, 0, 2, 12, 0, 0, 0, 35,
+ 0, 0, 0,209, 0, 0, 1, 86, 0, 0, 0, 35, 0, 0, 0,209, 0, 0, 2, 12, 0, 0, 0, 35, 0, 0, 1, 86, 0, 0, 2, 12,
+ 0, 0, 0, 35, 0, 0, 0,208, 0, 0, 2, 11, 0, 0, 0, 35, 0, 0, 0,208, 0, 0, 0,244, 0, 0, 0, 35, 0, 0, 0,244,
+ 0, 0, 2, 11, 0, 0, 0, 35, 0, 0, 1, 86, 0, 0, 2, 13, 0, 0, 0, 35, 0, 0, 1, 88, 0, 0, 2, 13, 0, 0, 0, 35,
+ 0, 0, 1, 86, 0, 0, 1, 88, 0, 0, 0, 35, 0, 0, 2, 13, 0, 0, 2, 14, 0, 0, 0, 35, 0, 0, 2, 13, 0, 0, 2, 15,
+ 0, 0, 0, 35, 0, 0, 2, 14, 0, 0, 2, 15, 0, 0, 0, 35, 0, 0, 1, 87, 0, 0, 1, 91, 0, 0, 0, 35, 0, 0, 1, 91,
+ 0, 0, 2, 15, 0, 0, 0, 35, 0, 0, 1, 87, 0, 0, 2, 15, 0, 0, 0, 35, 0, 0, 1, 90, 0, 0, 2, 14, 0, 0, 0, 35,
+ 0, 0, 1, 89, 0, 0, 1, 90, 0, 0, 0, 35, 0, 0, 1, 89, 0, 0, 2, 14, 0, 0, 0, 35, 0, 0, 0,212, 0, 0, 2, 16,
+ 0, 0, 0, 35, 0, 0, 0,242, 0, 0, 2, 16, 0, 0, 0, 35, 0, 0, 0,212, 0, 0, 0,242, 0, 0, 0, 35, 0, 0, 2, 16,
+ 0, 0, 2, 17, 0, 0, 0, 35, 0, 0, 2, 16, 0, 0, 2, 18, 0, 0, 0, 35, 0, 0, 2, 17, 0, 0, 2, 18, 0, 0, 0, 35,
+ 0, 0, 0,213, 0, 0, 1, 90, 0, 0, 0, 35, 0, 0, 1, 90, 0, 0, 2, 18, 0, 0, 0, 35, 0, 0, 0,213, 0, 0, 2, 18,
+ 0, 0, 0, 35, 0, 0, 1, 91, 0, 0, 2, 17, 0, 0, 0, 35, 0, 0, 0,243, 0, 0, 1, 91, 0, 0, 0, 35, 0, 0, 0,243,
+ 0, 0, 2, 17, 0, 0, 0, 35, 0, 0, 0,211, 0, 0, 2, 19, 0, 0, 0, 35, 0, 0, 1, 89, 0, 0, 2, 19, 0, 0, 0, 35,
+ 0, 0, 0,211, 0, 0, 1, 89, 0, 0, 0, 35, 0, 0, 2, 19, 0, 0, 2, 20, 0, 0, 0, 35, 0, 0, 2, 19, 0, 0, 2, 21,
+ 0, 0, 0, 35, 0, 0, 2, 20, 0, 0, 2, 21, 0, 0, 0, 35, 0, 0, 0,206, 0, 0, 0,210, 0, 0, 0, 35, 0, 0, 0,206,
+ 0, 0, 2, 21, 0, 0, 0, 35, 0, 0, 0,210, 0, 0, 2, 21, 0, 0, 0, 35, 0, 0, 0,207, 0, 0, 2, 20, 0, 0, 0, 35,
+ 0, 0, 0,207, 0, 0, 1, 88, 0, 0, 0, 35, 0, 0, 1, 88, 0, 0, 2, 20, 0, 0, 0, 35, 0, 0, 1, 93, 0, 0, 2, 22,
+ 0, 0, 0, 35, 0, 0, 0,247, 0, 0, 2, 22, 0, 0, 0, 35, 0, 0, 0,247, 0, 0, 1, 93, 0, 0, 0, 35, 0, 0, 2, 22,
+ 0, 0, 2, 23, 0, 0, 0, 35, 0, 0, 2, 22, 0, 0, 2, 24, 0, 0, 0, 35, 0, 0, 2, 23, 0, 0, 2, 24, 0, 0, 0, 35,
+ 0, 0, 0,217, 0, 0, 1, 92, 0, 0, 0, 35, 0, 0, 0,217, 0, 0, 2, 24, 0, 0, 0, 35, 0, 0, 1, 92, 0, 0, 2, 24,
+ 0, 0, 0, 35, 0, 0, 0,216, 0, 0, 2, 23, 0, 0, 0, 35, 0, 0, 0,216, 0, 0, 0,246, 0, 0, 0, 35, 0, 0, 0,246,
+ 0, 0, 2, 23, 0, 0, 0, 35, 0, 0, 1, 92, 0, 0, 2, 25, 0, 0, 0, 35, 0, 0, 1, 94, 0, 0, 2, 25, 0, 0, 0, 35,
+ 0, 0, 1, 92, 0, 0, 1, 94, 0, 0, 0, 35, 0, 0, 2, 25, 0, 0, 2, 26, 0, 0, 0, 35, 0, 0, 2, 25, 0, 0, 2, 27,
+ 0, 0, 0, 35, 0, 0, 2, 26, 0, 0, 2, 27, 0, 0, 0, 35, 0, 0, 1, 93, 0, 0, 1, 97, 0, 0, 0, 35, 0, 0, 1, 97,
+ 0, 0, 2, 27, 0, 0, 0, 35, 0, 0, 1, 93, 0, 0, 2, 27, 0, 0, 0, 35, 0, 0, 1, 96, 0, 0, 2, 26, 0, 0, 0, 35,
+ 0, 0, 1, 95, 0, 0, 1, 96, 0, 0, 0, 35, 0, 0, 1, 95, 0, 0, 2, 26, 0, 0, 0, 35, 0, 0, 0,220, 0, 0, 2, 28,
+ 0, 0, 0, 35, 0, 0, 0,248, 0, 0, 2, 28, 0, 0, 0, 35, 0, 0, 0,220, 0, 0, 0,248, 0, 0, 0, 35, 0, 0, 2, 28,
+ 0, 0, 2, 29, 0, 0, 0, 35, 0, 0, 2, 28, 0, 0, 2, 30, 0, 0, 0, 35, 0, 0, 2, 29, 0, 0, 2, 30, 0, 0, 0, 35,
+ 0, 0, 0,221, 0, 0, 1, 96, 0, 0, 0, 35, 0, 0, 1, 96, 0, 0, 2, 30, 0, 0, 0, 35, 0, 0, 0,221, 0, 0, 2, 30,
+ 0, 0, 0, 35, 0, 0, 1, 97, 0, 0, 2, 29, 0, 0, 0, 35, 0, 0, 0,249, 0, 0, 1, 97, 0, 0, 0, 35, 0, 0, 0,249,
+ 0, 0, 2, 29, 0, 0, 0, 35, 0, 0, 0,219, 0, 0, 2, 31, 0, 0, 0, 35, 0, 0, 1, 95, 0, 0, 2, 31, 0, 0, 0, 35,
+ 0, 0, 0,219, 0, 0, 1, 95, 0, 0, 0, 35, 0, 0, 2, 31, 0, 0, 2, 32, 0, 0, 0, 35, 0, 0, 2, 31, 0, 0, 2, 33,
+ 0, 0, 0, 35, 0, 0, 2, 32, 0, 0, 2, 33, 0, 0, 0, 35, 0, 0, 0,214, 0, 0, 0,218, 0, 0, 0, 35, 0, 0, 0,214,
+ 0, 0, 2, 33, 0, 0, 0, 35, 0, 0, 0,218, 0, 0, 2, 33, 0, 0, 0, 35, 0, 0, 0,215, 0, 0, 2, 32, 0, 0, 0, 35,
+ 0, 0, 0,215, 0, 0, 1, 94, 0, 0, 0, 35, 0, 0, 1, 94, 0, 0, 2, 32, 0, 0, 0, 35, 0, 0, 1, 99, 0, 0, 2, 34,
+ 0, 0, 0, 35, 0, 0, 0,251, 0, 0, 2, 34, 0, 0, 0, 35, 0, 0, 0,251, 0, 0, 1, 99, 0, 0, 0, 35, 0, 0, 2, 34,
+ 0, 0, 2, 35, 0, 0, 0, 35, 0, 0, 2, 34, 0, 0, 2, 36, 0, 0, 0, 35, 0, 0, 2, 35, 0, 0, 2, 36, 0, 0, 0, 35,
+ 0, 0, 0,225, 0, 0, 1, 98, 0, 0, 0, 35, 0, 0, 0,225, 0, 0, 2, 36, 0, 0, 0, 35, 0, 0, 1, 98, 0, 0, 2, 36,
+ 0, 0, 0, 35, 0, 0, 0,224, 0, 0, 2, 35, 0, 0, 0, 35, 0, 0, 0,224, 0, 0, 0,250, 0, 0, 0, 35, 0, 0, 0,250,
+ 0, 0, 2, 35, 0, 0, 0, 35, 0, 0, 1, 98, 0, 0, 2, 37, 0, 0, 0, 35, 0, 0, 1,100, 0, 0, 2, 37, 0, 0, 0, 35,
+ 0, 0, 1, 98, 0, 0, 1,100, 0, 0, 0, 35, 0, 0, 2, 37, 0, 0, 2, 38, 0, 0, 0, 35, 0, 0, 2, 37, 0, 0, 2, 39,
+ 0, 0, 0, 35, 0, 0, 2, 38, 0, 0, 2, 39, 0, 0, 0, 35, 0, 0, 1, 99, 0, 0, 1,103, 0, 0, 0, 35, 0, 0, 1,103,
+ 0, 0, 2, 39, 0, 0, 0, 35, 0, 0, 1, 99, 0, 0, 2, 39, 0, 0, 0, 35, 0, 0, 1,102, 0, 0, 2, 38, 0, 0, 0, 35,
+ 0, 0, 1,101, 0, 0, 1,102, 0, 0, 0, 35, 0, 0, 1,101, 0, 0, 2, 38, 0, 0, 0, 35, 0, 0, 0,228, 0, 0, 2, 40,
+ 0, 0, 0, 35, 0, 0, 0,252, 0, 0, 2, 40, 0, 0, 0, 35, 0, 0, 0,228, 0, 0, 0,252, 0, 0, 0, 35, 0, 0, 2, 40,
+ 0, 0, 2, 41, 0, 0, 0, 35, 0, 0, 2, 40, 0, 0, 2, 42, 0, 0, 0, 35, 0, 0, 2, 41, 0, 0, 2, 42, 0, 0, 0, 35,
+ 0, 0, 0,229, 0, 0, 1,102, 0, 0, 0, 35, 0, 0, 1,102, 0, 0, 2, 42, 0, 0, 0, 35, 0, 0, 0,229, 0, 0, 2, 42,
+ 0, 0, 0, 35, 0, 0, 1,103, 0, 0, 2, 41, 0, 0, 0, 35, 0, 0, 0,253, 0, 0, 1,103, 0, 0, 0, 35, 0, 0, 0,253,
+ 0, 0, 2, 41, 0, 0, 0, 35, 0, 0, 0,227, 0, 0, 2, 43, 0, 0, 0, 35, 0, 0, 1,101, 0, 0, 2, 43, 0, 0, 0, 35,
+ 0, 0, 0,227, 0, 0, 1,101, 0, 0, 0, 35, 0, 0, 2, 43, 0, 0, 2, 44, 0, 0, 0, 35, 0, 0, 2, 43, 0, 0, 2, 45,
+ 0, 0, 0, 35, 0, 0, 2, 44, 0, 0, 2, 45, 0, 0, 0, 35, 0, 0, 0,222, 0, 0, 0,226, 0, 0, 0, 35, 0, 0, 0,222,
+ 0, 0, 2, 45, 0, 0, 0, 35, 0, 0, 0,226, 0, 0, 2, 45, 0, 0, 0, 35, 0, 0, 0,223, 0, 0, 2, 44, 0, 0, 0, 35,
+ 0, 0, 0,223, 0, 0, 1,100, 0, 0, 0, 35, 0, 0, 1,100, 0, 0, 2, 44, 0, 0, 0, 35, 0, 0, 1,105, 0, 0, 2, 46,
+ 0, 0, 0, 35, 0, 0, 0,255, 0, 0, 2, 46, 0, 0, 0, 35, 0, 0, 0,255, 0, 0, 1,105, 0, 0, 0, 35, 0, 0, 2, 46,
+ 0, 0, 2, 47, 0, 0, 0, 35, 0, 0, 2, 46, 0, 0, 2, 48, 0, 0, 0, 35, 0, 0, 2, 47, 0, 0, 2, 48, 0, 0, 0, 35,
+ 0, 0, 0,233, 0, 0, 1,104, 0, 0, 0, 35, 0, 0, 0,233, 0, 0, 2, 48, 0, 0, 0, 35, 0, 0, 1,104, 0, 0, 2, 48,
+ 0, 0, 0, 35, 0, 0, 0,232, 0, 0, 2, 47, 0, 0, 0, 35, 0, 0, 0,232, 0, 0, 0,254, 0, 0, 0, 35, 0, 0, 0,254,
+ 0, 0, 2, 47, 0, 0, 0, 35, 0, 0, 1,104, 0, 0, 2, 49, 0, 0, 0, 35, 0, 0, 1,106, 0, 0, 2, 49, 0, 0, 0, 35,
+ 0, 0, 1,104, 0, 0, 1,106, 0, 0, 0, 35, 0, 0, 2, 49, 0, 0, 2, 50, 0, 0, 0, 35, 0, 0, 2, 49, 0, 0, 2, 51,
+ 0, 0, 0, 35, 0, 0, 2, 50, 0, 0, 2, 51, 0, 0, 0, 35, 0, 0, 1,105, 0, 0, 1,109, 0, 0, 0, 35, 0, 0, 1,109,
+ 0, 0, 2, 51, 0, 0, 0, 35, 0, 0, 1,105, 0, 0, 2, 51, 0, 0, 0, 35, 0, 0, 1,108, 0, 0, 2, 50, 0, 0, 0, 35,
+ 0, 0, 1,107, 0, 0, 1,108, 0, 0, 0, 35, 0, 0, 1,107, 0, 0, 2, 50, 0, 0, 0, 35, 0, 0, 0,236, 0, 0, 2, 52,
+ 0, 0, 0, 35, 0, 0, 1, 0, 0, 0, 2, 52, 0, 0, 0, 35, 0, 0, 0,236, 0, 0, 1, 0, 0, 0, 0, 35, 0, 0, 2, 52,
+ 0, 0, 2, 53, 0, 0, 0, 35, 0, 0, 2, 52, 0, 0, 2, 54, 0, 0, 0, 35, 0, 0, 2, 53, 0, 0, 2, 54, 0, 0, 0, 35,
+ 0, 0, 0,237, 0, 0, 1,108, 0, 0, 0, 35, 0, 0, 1,108, 0, 0, 2, 54, 0, 0, 0, 35, 0, 0, 0,237, 0, 0, 2, 54,
+ 0, 0, 0, 35, 0, 0, 1,109, 0, 0, 2, 53, 0, 0, 0, 35, 0, 0, 1, 1, 0, 0, 1,109, 0, 0, 0, 35, 0, 0, 1, 1,
+ 0, 0, 2, 53, 0, 0, 0, 35, 0, 0, 0,235, 0, 0, 2, 55, 0, 0, 0, 35, 0, 0, 1,107, 0, 0, 2, 55, 0, 0, 0, 35,
+ 0, 0, 0,235, 0, 0, 1,107, 0, 0, 0, 35, 0, 0, 2, 55, 0, 0, 2, 56, 0, 0, 0, 35, 0, 0, 2, 55, 0, 0, 2, 57,
+ 0, 0, 0, 35, 0, 0, 2, 56, 0, 0, 2, 57, 0, 0, 0, 35, 0, 0, 0,230, 0, 0, 0,234, 0, 0, 0, 35, 0, 0, 0,230,
+ 0, 0, 2, 57, 0, 0, 0, 35, 0, 0, 0,234, 0, 0, 2, 57, 0, 0, 0, 35, 0, 0, 0,231, 0, 0, 2, 56, 0, 0, 0, 35,
+ 0, 0, 0,231, 0, 0, 1,106, 0, 0, 0, 35, 0, 0, 1,106, 0, 0, 2, 56, 0, 0, 0, 35, 0, 0, 1,111, 0, 0, 2, 58,
+ 0, 0, 0, 35, 0, 0, 1, 3, 0, 0, 2, 58, 0, 0, 0, 35, 0, 0, 1, 3, 0, 0, 1,111, 0, 0, 0, 35, 0, 0, 2, 58,
+ 0, 0, 2, 59, 0, 0, 0, 35, 0, 0, 2, 58, 0, 0, 2, 60, 0, 0, 0, 35, 0, 0, 2, 59, 0, 0, 2, 60, 0, 0, 0, 35,
+ 0, 0, 0,241, 0, 0, 1,110, 0, 0, 0, 35, 0, 0, 0,241, 0, 0, 2, 60, 0, 0, 0, 35, 0, 0, 1,110, 0, 0, 2, 60,
+ 0, 0, 0, 35, 0, 0, 0,240, 0, 0, 2, 59, 0, 0, 0, 35, 0, 0, 0,240, 0, 0, 1, 2, 0, 0, 0, 35, 0, 0, 1, 2,
+ 0, 0, 2, 59, 0, 0, 0, 35, 0, 0, 1,110, 0, 0, 2, 61, 0, 0, 0, 35, 0, 0, 1,113, 0, 0, 2, 61, 0, 0, 0, 35,
+ 0, 0, 1,110, 0, 0, 1,113, 0, 0, 0, 35, 0, 0, 2, 61, 0, 0, 2, 62, 0, 0, 0, 35, 0, 0, 2, 61, 0, 0, 2, 63,
+ 0, 0, 0, 35, 0, 0, 2, 62, 0, 0, 2, 63, 0, 0, 0, 35, 0, 0, 1,111, 0, 0, 1,115, 0, 0, 0, 35, 0, 0, 1,115,
+ 0, 0, 2, 63, 0, 0, 0, 35, 0, 0, 1,111, 0, 0, 2, 63, 0, 0, 0, 35, 0, 0, 1,114, 0, 0, 2, 62, 0, 0, 0, 35,
+ 0, 0, 1,112, 0, 0, 1,114, 0, 0, 0, 35, 0, 0, 1,112, 0, 0, 2, 62, 0, 0, 0, 35, 0, 0, 0,204, 0, 0, 2, 64,
+ 0, 0, 0, 35, 0, 0, 1, 4, 0, 0, 2, 64, 0, 0, 0, 35, 0, 0, 0,204, 0, 0, 1, 4, 0, 0, 0, 35, 0, 0, 2, 64,
+ 0, 0, 2, 65, 0, 0, 0, 35, 0, 0, 2, 64, 0, 0, 2, 66, 0, 0, 0, 35, 0, 0, 2, 65, 0, 0, 2, 66, 0, 0, 0, 35,
+ 0, 0, 0,205, 0, 0, 1,114, 0, 0, 0, 35, 0, 0, 1,114, 0, 0, 2, 66, 0, 0, 0, 35, 0, 0, 0,205, 0, 0, 2, 66,
+ 0, 0, 0, 35, 0, 0, 1,115, 0, 0, 2, 65, 0, 0, 0, 35, 0, 0, 1, 5, 0, 0, 1,115, 0, 0, 0, 35, 0, 0, 1, 5,
+ 0, 0, 2, 65, 0, 0, 0, 35, 0, 0, 0,203, 0, 0, 2, 67, 0, 0, 0, 35, 0, 0, 1,112, 0, 0, 2, 67, 0, 0, 0, 35,
+ 0, 0, 0,203, 0, 0, 1,112, 0, 0, 0, 35, 0, 0, 2, 67, 0, 0, 2, 68, 0, 0, 0, 35, 0, 0, 2, 67, 0, 0, 2, 69,
+ 0, 0, 0, 35, 0, 0, 2, 68, 0, 0, 2, 69, 0, 0, 0, 35, 0, 0, 0,202, 0, 0, 0,238, 0, 0, 0, 35, 0, 0, 0,238,
+ 0, 0, 2, 69, 0, 0, 0, 35, 0, 0, 0,202, 0, 0, 2, 69, 0, 0, 0, 35, 0, 0, 0,239, 0, 0, 2, 68, 0, 0, 0, 35,
+ 0, 0, 0,239, 0, 0, 1,113, 0, 0, 0, 35, 0, 0, 1,113, 0, 0, 2, 68, 0, 0, 0, 35, 0, 0, 1,117, 0, 0, 2, 70,
+ 0, 0, 0, 35, 0, 0, 1, 11, 0, 0, 1,117, 0, 0, 0, 35, 0, 0, 1, 11, 0, 0, 2, 70, 0, 0, 0, 35, 0, 0, 2, 70,
+ 0, 0, 2, 71, 0, 0, 0, 35, 0, 0, 2, 71, 0, 0, 2, 72, 0, 0, 0, 35, 0, 0, 2, 70, 0, 0, 2, 72, 0, 0, 0, 35,
+ 0, 0, 0,243, 0, 0, 1,116, 0, 0, 0, 35, 0, 0, 1,116, 0, 0, 2, 72, 0, 0, 0, 35, 0, 0, 0,243, 0, 0, 2, 72,
+ 0, 0, 0, 35, 0, 0, 0,242, 0, 0, 2, 71, 0, 0, 0, 35, 0, 0, 1, 10, 0, 0, 2, 71, 0, 0, 0, 35, 0, 0, 0,242,
+ 0, 0, 1, 10, 0, 0, 0, 35, 0, 0, 1,116, 0, 0, 2, 73, 0, 0, 0, 35, 0, 0, 1,116, 0, 0, 1,118, 0, 0, 0, 35,
+ 0, 0, 1,118, 0, 0, 2, 73, 0, 0, 0, 35, 0, 0, 2, 73, 0, 0, 2, 74, 0, 0, 0, 35, 0, 0, 2, 74, 0, 0, 2, 75,
+ 0, 0, 0, 35, 0, 0, 2, 73, 0, 0, 2, 75, 0, 0, 0, 35, 0, 0, 1,117, 0, 0, 1,121, 0, 0, 0, 35, 0, 0, 1,117,
+ 0, 0, 2, 75, 0, 0, 0, 35, 0, 0, 1,121, 0, 0, 2, 75, 0, 0, 0, 35, 0, 0, 1,120, 0, 0, 2, 74, 0, 0, 0, 35,
+ 0, 0, 1,119, 0, 0, 2, 74, 0, 0, 0, 35, 0, 0, 1,119, 0, 0, 1,120, 0, 0, 0, 35, 0, 0, 1, 8, 0, 0, 2, 76,
+ 0, 0, 0, 35, 0, 0, 1, 8, 0, 0, 1, 12, 0, 0, 0, 35, 0, 0, 1, 12, 0, 0, 2, 76, 0, 0, 0, 35, 0, 0, 2, 76,
+ 0, 0, 2, 77, 0, 0, 0, 35, 0, 0, 2, 77, 0, 0, 2, 78, 0, 0, 0, 35, 0, 0, 2, 76, 0, 0, 2, 78, 0, 0, 0, 35,
+ 0, 0, 1, 9, 0, 0, 1,120, 0, 0, 0, 35, 0, 0, 1, 9, 0, 0, 2, 78, 0, 0, 0, 35, 0, 0, 1,120, 0, 0, 2, 78,
+ 0, 0, 0, 35, 0, 0, 1,121, 0, 0, 2, 77, 0, 0, 0, 35, 0, 0, 1, 13, 0, 0, 2, 77, 0, 0, 0, 35, 0, 0, 1, 13,
+ 0, 0, 1,121, 0, 0, 0, 35, 0, 0, 1, 7, 0, 0, 2, 79, 0, 0, 0, 35, 0, 0, 1, 7, 0, 0, 1,119, 0, 0, 0, 35,
+ 0, 0, 1,119, 0, 0, 2, 79, 0, 0, 0, 35, 0, 0, 2, 79, 0, 0, 2, 80, 0, 0, 0, 35, 0, 0, 2, 80, 0, 0, 2, 81,
+ 0, 0, 0, 35, 0, 0, 2, 79, 0, 0, 2, 81, 0, 0, 0, 35, 0, 0, 0,244, 0, 0, 1, 6, 0, 0, 0, 35, 0, 0, 1, 6,
+ 0, 0, 2, 81, 0, 0, 0, 35, 0, 0, 0,244, 0, 0, 2, 81, 0, 0, 0, 35, 0, 0, 0,245, 0, 0, 2, 80, 0, 0, 0, 35,
+ 0, 0, 1,118, 0, 0, 2, 80, 0, 0, 0, 35, 0, 0, 0,245, 0, 0, 1,118, 0, 0, 0, 35, 0, 0, 1,123, 0, 0, 2, 82,
+ 0, 0, 0, 35, 0, 0, 1, 15, 0, 0, 1,123, 0, 0, 0, 35, 0, 0, 1, 15, 0, 0, 2, 82, 0, 0, 0, 35, 0, 0, 2, 82,
+ 0, 0, 2, 83, 0, 0, 0, 35, 0, 0, 2, 83, 0, 0, 2, 84, 0, 0, 0, 35, 0, 0, 2, 82, 0, 0, 2, 84, 0, 0, 0, 35,
+ 0, 0, 0,249, 0, 0, 1,122, 0, 0, 0, 35, 0, 0, 1,122, 0, 0, 2, 84, 0, 0, 0, 35, 0, 0, 0,249, 0, 0, 2, 84,
+ 0, 0, 0, 35, 0, 0, 0,248, 0, 0, 2, 83, 0, 0, 0, 35, 0, 0, 1, 14, 0, 0, 2, 83, 0, 0, 0, 35, 0, 0, 0,248,
+ 0, 0, 1, 14, 0, 0, 0, 35, 0, 0, 1,122, 0, 0, 2, 85, 0, 0, 0, 35, 0, 0, 1,122, 0, 0, 1,124, 0, 0, 0, 35,
+ 0, 0, 1,124, 0, 0, 2, 85, 0, 0, 0, 35, 0, 0, 2, 85, 0, 0, 2, 86, 0, 0, 0, 35, 0, 0, 2, 86, 0, 0, 2, 87,
+ 0, 0, 0, 35, 0, 0, 2, 85, 0, 0, 2, 87, 0, 0, 0, 35, 0, 0, 1,123, 0, 0, 1,127, 0, 0, 0, 35, 0, 0, 1,123,
+ 0, 0, 2, 87, 0, 0, 0, 35, 0, 0, 1,127, 0, 0, 2, 87, 0, 0, 0, 35, 0, 0, 1,126, 0, 0, 2, 86, 0, 0, 0, 35,
+ 0, 0, 1,125, 0, 0, 2, 86, 0, 0, 0, 35, 0, 0, 1,125, 0, 0, 1,126, 0, 0, 0, 35, 0, 0, 1, 12, 0, 0, 2, 88,
+ 0, 0, 0, 35, 0, 0, 1, 12, 0, 0, 1, 16, 0, 0, 0, 35, 0, 0, 1, 16, 0, 0, 2, 88, 0, 0, 0, 35, 0, 0, 2, 88,
+ 0, 0, 2, 89, 0, 0, 0, 35, 0, 0, 2, 89, 0, 0, 2, 90, 0, 0, 0, 35, 0, 0, 2, 88, 0, 0, 2, 90, 0, 0, 0, 35,
+ 0, 0, 1, 13, 0, 0, 1,126, 0, 0, 0, 35, 0, 0, 1, 13, 0, 0, 2, 90, 0, 0, 0, 35, 0, 0, 1,126, 0, 0, 2, 90,
+ 0, 0, 0, 35, 0, 0, 1,127, 0, 0, 2, 89, 0, 0, 0, 35, 0, 0, 1, 17, 0, 0, 2, 89, 0, 0, 0, 35, 0, 0, 1, 17,
+ 0, 0, 1,127, 0, 0, 0, 35, 0, 0, 1, 11, 0, 0, 2, 91, 0, 0, 0, 35, 0, 0, 1, 11, 0, 0, 1,125, 0, 0, 0, 35,
+ 0, 0, 1,125, 0, 0, 2, 91, 0, 0, 0, 35, 0, 0, 2, 91, 0, 0, 2, 92, 0, 0, 0, 35, 0, 0, 2, 92, 0, 0, 2, 93,
+ 0, 0, 0, 35, 0, 0, 2, 91, 0, 0, 2, 93, 0, 0, 0, 35, 0, 0, 0,246, 0, 0, 1, 10, 0, 0, 0, 35, 0, 0, 1, 10,
+ 0, 0, 2, 93, 0, 0, 0, 35, 0, 0, 0,246, 0, 0, 2, 93, 0, 0, 0, 35, 0, 0, 0,247, 0, 0, 2, 92, 0, 0, 0, 35,
+ 0, 0, 1,124, 0, 0, 2, 92, 0, 0, 0, 35, 0, 0, 0,247, 0, 0, 1,124, 0, 0, 0, 35, 0, 0, 1,129, 0, 0, 2, 94,
+ 0, 0, 0, 35, 0, 0, 1, 19, 0, 0, 1,129, 0, 0, 0, 35, 0, 0, 1, 19, 0, 0, 2, 94, 0, 0, 0, 35, 0, 0, 2, 94,
+ 0, 0, 2, 95, 0, 0, 0, 35, 0, 0, 2, 95, 0, 0, 2, 96, 0, 0, 0, 35, 0, 0, 2, 94, 0, 0, 2, 96, 0, 0, 0, 35,
+ 0, 0, 0,253, 0, 0, 1,128, 0, 0, 0, 35, 0, 0, 1,128, 0, 0, 2, 96, 0, 0, 0, 35, 0, 0, 0,253, 0, 0, 2, 96,
+ 0, 0, 0, 35, 0, 0, 0,252, 0, 0, 2, 95, 0, 0, 0, 35, 0, 0, 1, 18, 0, 0, 2, 95, 0, 0, 0, 35, 0, 0, 0,252,
+ 0, 0, 1, 18, 0, 0, 0, 35, 0, 0, 1,128, 0, 0, 2, 97, 0, 0, 0, 35, 0, 0, 1,128, 0, 0, 1,130, 0, 0, 0, 35,
+ 0, 0, 1,130, 0, 0, 2, 97, 0, 0, 0, 35, 0, 0, 2, 97, 0, 0, 2, 98, 0, 0, 0, 35, 0, 0, 2, 98, 0, 0, 2, 99,
+ 0, 0, 0, 35, 0, 0, 2, 97, 0, 0, 2, 99, 0, 0, 0, 35, 0, 0, 1,129, 0, 0, 1,133, 0, 0, 0, 35, 0, 0, 1,129,
+ 0, 0, 2, 99, 0, 0, 0, 35, 0, 0, 1,133, 0, 0, 2, 99, 0, 0, 0, 35, 0, 0, 1,132, 0, 0, 2, 98, 0, 0, 0, 35,
+ 0, 0, 1,131, 0, 0, 2, 98, 0, 0, 0, 35, 0, 0, 1,131, 0, 0, 1,132, 0, 0, 0, 35, 0, 0, 1, 16, 0, 0, 2,100,
+ 0, 0, 0, 35, 0, 0, 1, 16, 0, 0, 1, 20, 0, 0, 0, 35, 0, 0, 1, 20, 0, 0, 2,100, 0, 0, 0, 35, 0, 0, 2,100,
+ 0, 0, 2,101, 0, 0, 0, 35, 0, 0, 2,101, 0, 0, 2,102, 0, 0, 0, 35, 0, 0, 2,100, 0, 0, 2,102, 0, 0, 0, 35,
+ 0, 0, 1, 17, 0, 0, 1,132, 0, 0, 0, 35, 0, 0, 1, 17, 0, 0, 2,102, 0, 0, 0, 35, 0, 0, 1,132, 0, 0, 2,102,
+ 0, 0, 0, 35, 0, 0, 1,133, 0, 0, 2,101, 0, 0, 0, 35, 0, 0, 1, 21, 0, 0, 2,101, 0, 0, 0, 35, 0, 0, 1, 21,
+ 0, 0, 1,133, 0, 0, 0, 35, 0, 0, 1, 15, 0, 0, 2,103, 0, 0, 0, 35, 0, 0, 1, 15, 0, 0, 1,131, 0, 0, 0, 35,
+ 0, 0, 1,131, 0, 0, 2,103, 0, 0, 0, 35, 0, 0, 2,103, 0, 0, 2,104, 0, 0, 0, 35, 0, 0, 2,104, 0, 0, 2,105,
+ 0, 0, 0, 35, 0, 0, 2,103, 0, 0, 2,105, 0, 0, 0, 35, 0, 0, 0,250, 0, 0, 1, 14, 0, 0, 0, 35, 0, 0, 1, 14,
+ 0, 0, 2,105, 0, 0, 0, 35, 0, 0, 0,250, 0, 0, 2,105, 0, 0, 0, 35, 0, 0, 0,251, 0, 0, 2,104, 0, 0, 0, 35,
+ 0, 0, 1,130, 0, 0, 2,104, 0, 0, 0, 35, 0, 0, 0,251, 0, 0, 1,130, 0, 0, 0, 35, 0, 0, 1,135, 0, 0, 2,106,
+ 0, 0, 0, 35, 0, 0, 1, 23, 0, 0, 1,135, 0, 0, 0, 35, 0, 0, 1, 23, 0, 0, 2,106, 0, 0, 0, 35, 0, 0, 2,106,
+ 0, 0, 2,107, 0, 0, 0, 35, 0, 0, 2,107, 0, 0, 2,108, 0, 0, 0, 35, 0, 0, 2,106, 0, 0, 2,108, 0, 0, 0, 35,
+ 0, 0, 1, 1, 0, 0, 1,134, 0, 0, 0, 35, 0, 0, 1,134, 0, 0, 2,108, 0, 0, 0, 35, 0, 0, 1, 1, 0, 0, 2,108,
+ 0, 0, 0, 35, 0, 0, 1, 0, 0, 0, 2,107, 0, 0, 0, 35, 0, 0, 1, 22, 0, 0, 2,107, 0, 0, 0, 35, 0, 0, 1, 0,
+ 0, 0, 1, 22, 0, 0, 0, 35, 0, 0, 1,134, 0, 0, 2,109, 0, 0, 0, 35, 0, 0, 1,134, 0, 0, 1,136, 0, 0, 0, 35,
+ 0, 0, 1,136, 0, 0, 2,109, 0, 0, 0, 35, 0, 0, 2,109, 0, 0, 2,110, 0, 0, 0, 35, 0, 0, 2,110, 0, 0, 2,111,
+ 0, 0, 0, 35, 0, 0, 2,109, 0, 0, 2,111, 0, 0, 0, 35, 0, 0, 1,135, 0, 0, 1,139, 0, 0, 0, 35, 0, 0, 1,135,
+ 0, 0, 2,111, 0, 0, 0, 35, 0, 0, 1,139, 0, 0, 2,111, 0, 0, 0, 35, 0, 0, 1,138, 0, 0, 2,110, 0, 0, 0, 35,
+ 0, 0, 1,137, 0, 0, 2,110, 0, 0, 0, 35, 0, 0, 1,137, 0, 0, 1,138, 0, 0, 0, 35, 0, 0, 1, 20, 0, 0, 2,112,
+ 0, 0, 0, 35, 0, 0, 1, 20, 0, 0, 1, 24, 0, 0, 0, 35, 0, 0, 1, 24, 0, 0, 2,112, 0, 0, 0, 35, 0, 0, 2,112,
+ 0, 0, 2,113, 0, 0, 0, 35, 0, 0, 2,113, 0, 0, 2,114, 0, 0, 0, 35, 0, 0, 2,112, 0, 0, 2,114, 0, 0, 0, 35,
+ 0, 0, 1, 21, 0, 0, 1,138, 0, 0, 0, 35, 0, 0, 1, 21, 0, 0, 2,114, 0, 0, 0, 35, 0, 0, 1,138, 0, 0, 2,114,
+ 0, 0, 0, 35, 0, 0, 1,139, 0, 0, 2,113, 0, 0, 0, 35, 0, 0, 1, 25, 0, 0, 2,113, 0, 0, 0, 35, 0, 0, 1, 25,
+ 0, 0, 1,139, 0, 0, 0, 35, 0, 0, 1, 19, 0, 0, 2,115, 0, 0, 0, 35, 0, 0, 1, 19, 0, 0, 1,137, 0, 0, 0, 35,
+ 0, 0, 1,137, 0, 0, 2,115, 0, 0, 0, 35, 0, 0, 2,115, 0, 0, 2,116, 0, 0, 0, 35, 0, 0, 2,116, 0, 0, 2,117,
+ 0, 0, 0, 35, 0, 0, 2,115, 0, 0, 2,117, 0, 0, 0, 35, 0, 0, 0,254, 0, 0, 1, 18, 0, 0, 0, 35, 0, 0, 1, 18,
+ 0, 0, 2,117, 0, 0, 0, 35, 0, 0, 0,254, 0, 0, 2,117, 0, 0, 0, 35, 0, 0, 0,255, 0, 0, 2,116, 0, 0, 0, 35,
+ 0, 0, 1,136, 0, 0, 2,116, 0, 0, 0, 35, 0, 0, 0,255, 0, 0, 1,136, 0, 0, 0, 35, 0, 0, 1,141, 0, 0, 2,118,
+ 0, 0, 0, 35, 0, 0, 1, 7, 0, 0, 1,141, 0, 0, 0, 35, 0, 0, 1, 7, 0, 0, 2,118, 0, 0, 0, 35, 0, 0, 2,118,
+ 0, 0, 2,119, 0, 0, 0, 35, 0, 0, 2,119, 0, 0, 2,120, 0, 0, 0, 35, 0, 0, 2,118, 0, 0, 2,120, 0, 0, 0, 35,
+ 0, 0, 1, 5, 0, 0, 1,140, 0, 0, 0, 35, 0, 0, 1,140, 0, 0, 2,120, 0, 0, 0, 35, 0, 0, 1, 5, 0, 0, 2,120,
+ 0, 0, 0, 35, 0, 0, 1, 4, 0, 0, 2,119, 0, 0, 0, 35, 0, 0, 1, 6, 0, 0, 2,119, 0, 0, 0, 35, 0, 0, 1, 4,
+ 0, 0, 1, 6, 0, 0, 0, 35, 0, 0, 1,140, 0, 0, 2,121, 0, 0, 0, 35, 0, 0, 1,140, 0, 0, 1,142, 0, 0, 0, 35,
+ 0, 0, 1,142, 0, 0, 2,121, 0, 0, 0, 35, 0, 0, 2,121, 0, 0, 2,122, 0, 0, 0, 35, 0, 0, 2,122, 0, 0, 2,123,
+ 0, 0, 0, 35, 0, 0, 2,121, 0, 0, 2,123, 0, 0, 0, 35, 0, 0, 1,141, 0, 0, 1,144, 0, 0, 0, 35, 0, 0, 1,141,
+ 0, 0, 2,123, 0, 0, 0, 35, 0, 0, 1,144, 0, 0, 2,123, 0, 0, 0, 35, 0, 0, 1,145, 0, 0, 2,122, 0, 0, 0, 35,
+ 0, 0, 1,143, 0, 0, 2,122, 0, 0, 0, 35, 0, 0, 1,143, 0, 0, 1,145, 0, 0, 0, 35, 0, 0, 1, 24, 0, 0, 2,124,
+ 0, 0, 0, 35, 0, 0, 1, 8, 0, 0, 1, 24, 0, 0, 0, 35, 0, 0, 1, 8, 0, 0, 2,124, 0, 0, 0, 35, 0, 0, 2,124,
+ 0, 0, 2,125, 0, 0, 0, 35, 0, 0, 2,125, 0, 0, 2,126, 0, 0, 0, 35, 0, 0, 2,124, 0, 0, 2,126, 0, 0, 0, 35,
+ 0, 0, 1, 25, 0, 0, 1,145, 0, 0, 0, 35, 0, 0, 1, 25, 0, 0, 2,126, 0, 0, 0, 35, 0, 0, 1,145, 0, 0, 2,126,
+ 0, 0, 0, 35, 0, 0, 1,144, 0, 0, 2,125, 0, 0, 0, 35, 0, 0, 1, 9, 0, 0, 2,125, 0, 0, 0, 35, 0, 0, 1, 9,
+ 0, 0, 1,144, 0, 0, 0, 35, 0, 0, 1, 23, 0, 0, 2,127, 0, 0, 0, 35, 0, 0, 1, 23, 0, 0, 1,143, 0, 0, 0, 35,
+ 0, 0, 1,143, 0, 0, 2,127, 0, 0, 0, 35, 0, 0, 2,127, 0, 0, 2,128, 0, 0, 0, 35, 0, 0, 2,128, 0, 0, 2,129,
+ 0, 0, 0, 35, 0, 0, 2,127, 0, 0, 2,129, 0, 0, 0, 35, 0, 0, 1, 2, 0, 0, 1, 22, 0, 0, 0, 35, 0, 0, 1, 22,
+ 0, 0, 2,129, 0, 0, 0, 35, 0, 0, 1, 2, 0, 0, 2,129, 0, 0, 0, 35, 0, 0, 1, 3, 0, 0, 2,128, 0, 0, 0, 35,
+ 0, 0, 1,142, 0, 0, 2,128, 0, 0, 0, 35, 0, 0, 1, 3, 0, 0, 1,142, 0, 0, 0, 35, 68, 65, 84, 65, 0, 0, 1, 44,
+ 13, 65,152,224, 0, 0, 1, 35, 0, 0, 0, 5, 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, 12,118,208, 32, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 85, 86, 84,101,120, 0, 0, 0, 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,119, 64, 32, 0, 0, 0, 6, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,111,108, 0,
+ 0, 0, 0, 0, 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,120, 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,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 0, 0,100, 0,
+ 12,118,208, 32, 0, 0, 0, 54, 0, 0, 5, 0, 0, 0, 1, 27, 0, 0, 0,102, 0, 0, 1,146, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,146, 0, 0, 0,171, 0, 0, 1, 27, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 14, 0, 0, 1, 27, 0, 0, 0,171,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,171, 0, 0, 1,146, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,147,
+ 0, 0, 0, 46, 0, 0, 1,146, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,146, 0, 0, 1,148, 0, 0, 1,147, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 43, 0, 0, 1,147, 0, 0, 1,148, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,148, 0, 0, 1,146,
+ 0, 0, 0,102, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 26, 0, 0, 0, 12, 0, 0, 0,165, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,165, 0, 0, 1,148, 0, 0, 1, 26, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,102, 0, 0, 1, 26, 0, 0, 1,148,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,148, 0, 0, 0,165, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,147,
+ 0, 0, 0, 43, 0, 0, 0,164, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,164, 0, 0, 0,170, 0, 0, 1,147, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 46, 0, 0, 1,147, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,170, 0, 0, 0,164,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 26, 0, 0, 0,102, 0, 0, 1,149, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,149, 0, 0, 1, 28, 0, 0, 1, 26, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 12, 0, 0, 1, 26, 0, 0, 1, 28,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 28, 0, 0, 1,149, 0, 0, 0,103, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,150,
+ 0, 0, 0,103, 0, 0, 1,149, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,149, 0, 0, 1,151, 0, 0, 1,150, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,104, 0, 0, 1,150, 0, 0, 1,151, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,151, 0, 0, 1,149,
+ 0, 0, 0,102, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 27, 0, 0, 0, 14, 0, 0, 1, 31, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 31, 0, 0, 1,151, 0, 0, 1, 27, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,102, 0, 0, 1, 27, 0, 0, 1,151,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,151, 0, 0, 1, 31, 0, 0, 0,104, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,150,
+ 0, 0, 0,104, 0, 0, 1, 30, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 30, 0, 0, 1, 29, 0, 0, 1,150, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,103, 0, 0, 1,150, 0, 0, 1, 29, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 29, 0, 0, 1, 30,
+ 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,168, 0, 0, 0, 45, 0, 0, 1,152, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,152, 0, 0, 0,172, 0, 0, 0,168, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,168, 0, 0, 0,172,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,172, 0, 0, 1,152, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,153,
+ 0, 0, 0, 47, 0, 0, 1,152, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,152, 0, 0, 1,154, 0, 0, 1,153, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,104, 0, 0, 1,153, 0, 0, 1,154, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,154, 0, 0, 1,152,
+ 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,169, 0, 0, 0, 13, 0, 0, 1, 30, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 30, 0, 0, 1,154, 0, 0, 0,169, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 45, 0, 0, 0,169, 0, 0, 1,154,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,154, 0, 0, 1, 30, 0, 0, 0,104, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,153,
+ 0, 0, 0,104, 0, 0, 1, 31, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 31, 0, 0, 0,173, 0, 0, 1,153, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 47, 0, 0, 1,153, 0, 0, 0,173, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,173, 0, 0, 1, 31,
+ 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,167, 0, 0, 0, 44, 0, 0, 1,155, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,155, 0, 0, 1, 29, 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 13, 0, 0, 0,167, 0, 0, 1, 29,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 29, 0, 0, 1,155, 0, 0, 0,103, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,156,
+ 0, 0, 0,103, 0, 0, 1,155, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,155, 0, 0, 1,157, 0, 0, 1,156, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 42, 0, 0, 1,156, 0, 0, 1,157, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,157, 0, 0, 1,155,
+ 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,162, 0, 0, 1,157, 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 44, 0, 0, 0,166, 0, 0, 1,157,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,157, 0, 0, 0,162, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,156,
+ 0, 0, 0, 42, 0, 0, 0,163, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,163, 0, 0, 1, 28, 0, 0, 1,156, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,103, 0, 0, 1,156, 0, 0, 1, 28, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 28, 0, 0, 0,163,
+ 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,158, 0, 0, 0,105, 0, 0, 1, 33, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 33, 0, 0, 0,179, 0, 0, 1,158, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 50, 0, 0, 1,158, 0, 0, 0,179,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,179, 0, 0, 1, 33, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,158,
+ 0, 0, 0, 50, 0, 0, 1,159, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,159, 0, 0, 1,160, 0, 0, 1,158, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,105, 0, 0, 1,158, 0, 0, 1,160, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,160, 0, 0, 1,159,
+ 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,165, 0, 0, 0, 12, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 32, 0, 0, 1,160, 0, 0, 0,165, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 43, 0, 0, 0,165, 0, 0, 1,160,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,160, 0, 0, 1, 32, 0, 0, 0,105, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,164,
+ 0, 0, 0, 43, 0, 0, 1,159, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,159, 0, 0, 0,178, 0, 0, 0,164, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0,164, 0, 0, 0,178, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,178, 0, 0, 1,159,
+ 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,161, 0, 0, 0,105, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 32, 0, 0, 1, 34, 0, 0, 1,161, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,106, 0, 0, 1,161, 0, 0, 1, 34,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 34, 0, 0, 1, 32, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,161,
+ 0, 0, 0,106, 0, 0, 1,162, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,162, 0, 0, 1,163, 0, 0, 1,161, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,105, 0, 0, 1,161, 0, 0, 1,163, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,163, 0, 0, 1,162,
+ 0, 0, 0,107, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 37, 0, 0, 0, 16, 0, 0, 1, 33, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 33, 0, 0, 1,163, 0, 0, 1, 37, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,107, 0, 0, 1, 37, 0, 0, 1,163,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,163, 0, 0, 1, 33, 0, 0, 0,105, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 36,
+ 0, 0, 0,107, 0, 0, 1,162, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,162, 0, 0, 1, 35, 0, 0, 1, 36, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 15, 0, 0, 1, 36, 0, 0, 1, 35, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 35, 0, 0, 1,162,
+ 0, 0, 0,106, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,164, 0, 0, 0, 49, 0, 0, 0,176, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,176, 0, 0, 0,180, 0, 0, 1,164, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 51, 0, 0, 1,164, 0, 0, 0,180,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,180, 0, 0, 0,176, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,164,
+ 0, 0, 0, 51, 0, 0, 1,165, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,165, 0, 0, 1,166, 0, 0, 1,164, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 49, 0, 0, 1,164, 0, 0, 1,166, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,166, 0, 0, 1,165,
+ 0, 0, 0,107, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 36, 0, 0, 0, 15, 0, 0, 0,177, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,177, 0, 0, 1,166, 0, 0, 1, 36, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,107, 0, 0, 1, 36, 0, 0, 1,166,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,166, 0, 0, 0,177, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 37,
+ 0, 0, 0,107, 0, 0, 1,165, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,165, 0, 0, 0,181, 0, 0, 1, 37, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 16, 0, 0, 1, 37, 0, 0, 0,181, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,181, 0, 0, 1,165,
+ 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,167, 0, 0, 0, 48, 0, 0, 0,175, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,175, 0, 0, 1, 35, 0, 0, 1,167, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,106, 0, 0, 1,167, 0, 0, 1, 35,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 35, 0, 0, 0,175, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,167,
+ 0, 0, 0,106, 0, 0, 1,168, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,168, 0, 0, 1,169, 0, 0, 1,167, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 48, 0, 0, 1,167, 0, 0, 1,169, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,169, 0, 0, 1,168,
+ 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0,174, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,174, 0, 0, 1,169, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 42, 0, 0, 0,162, 0, 0, 1,169,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,169, 0, 0, 0,174, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,163,
+ 0, 0, 0, 42, 0, 0, 1,168, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,168, 0, 0, 1, 34, 0, 0, 0,163, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 12, 0, 0, 0,163, 0, 0, 1, 34, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 34, 0, 0, 1,168,
+ 0, 0, 0,106, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 39, 0, 0, 0,108, 0, 0, 1,170, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,170, 0, 0, 0,187, 0, 0, 1, 39, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 18, 0, 0, 1, 39, 0, 0, 0,187,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,187, 0, 0, 1,170, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,171,
+ 0, 0, 0, 54, 0, 0, 1,170, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,170, 0, 0, 1,172, 0, 0, 1,171, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 45, 0, 0, 1,171, 0, 0, 1,172, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,172, 0, 0, 1,170,
+ 0, 0, 0,108, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 38, 0, 0, 0, 13, 0, 0, 0,169, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,169, 0, 0, 1,172, 0, 0, 1, 38, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,108, 0, 0, 1, 38, 0, 0, 1,172,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,172, 0, 0, 0,169, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,171,
+ 0, 0, 0, 45, 0, 0, 0,168, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,168, 0, 0, 0,186, 0, 0, 1,171, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 54, 0, 0, 1,171, 0, 0, 0,186, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,186, 0, 0, 0,168,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 38, 0, 0, 0,108, 0, 0, 1,173, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,173, 0, 0, 1, 40, 0, 0, 1, 38, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 13, 0, 0, 1, 38, 0, 0, 1, 40,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 40, 0, 0, 1,173, 0, 0, 0,109, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,174,
+ 0, 0, 0,109, 0, 0, 1,173, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,173, 0, 0, 1,175, 0, 0, 1,174, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,110, 0, 0, 1,174, 0, 0, 1,175, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,175, 0, 0, 1,173,
+ 0, 0, 0,108, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 39, 0, 0, 0, 18, 0, 0, 1, 43, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 43, 0, 0, 1,175, 0, 0, 1, 39, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,108, 0, 0, 1, 39, 0, 0, 1,175,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,175, 0, 0, 1, 43, 0, 0, 0,110, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,174,
+ 0, 0, 0,110, 0, 0, 1, 42, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 42, 0, 0, 1, 41, 0, 0, 1,174, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,109, 0, 0, 1,174, 0, 0, 1, 41, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 41, 0, 0, 1, 42,
+ 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,184, 0, 0, 0, 53, 0, 0, 1,176, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,176, 0, 0, 0,188, 0, 0, 0,184, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0,184, 0, 0, 0,188,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,188, 0, 0, 1,176, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,177,
+ 0, 0, 0, 55, 0, 0, 1,176, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,176, 0, 0, 1,178, 0, 0, 1,177, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,110, 0, 0, 1,177, 0, 0, 1,178, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,178, 0, 0, 1,176,
+ 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,185, 0, 0, 0, 17, 0, 0, 1, 42, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 42, 0, 0, 1,178, 0, 0, 0,185, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 53, 0, 0, 0,185, 0, 0, 1,178,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,178, 0, 0, 1, 42, 0, 0, 0,110, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,177,
+ 0, 0, 0,110, 0, 0, 1, 43, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 43, 0, 0, 0,189, 0, 0, 1,177, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 55, 0, 0, 1,177, 0, 0, 0,189, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,189, 0, 0, 1, 43,
+ 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,183, 0, 0, 0, 52, 0, 0, 1,179, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,179, 0, 0, 1, 41, 0, 0, 0,183, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 17, 0, 0, 0,183, 0, 0, 1, 41,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 41, 0, 0, 1,179, 0, 0, 0,109, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,180,
+ 0, 0, 0,109, 0, 0, 1,179, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,179, 0, 0, 1,181, 0, 0, 1,180, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 44, 0, 0, 1,180, 0, 0, 1,181, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,181, 0, 0, 1,179,
+ 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,182, 0, 0, 0, 0, 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,166, 0, 0, 1,181, 0, 0, 0,182, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 52, 0, 0, 0,182, 0, 0, 1,181,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,181, 0, 0, 0,166, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,180,
+ 0, 0, 0, 44, 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,167, 0, 0, 1, 40, 0, 0, 1,180, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,109, 0, 0, 1,180, 0, 0, 1, 40, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 40, 0, 0, 0,167,
+ 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 45, 0, 0, 0,111, 0, 0, 1,182, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,182, 0, 0, 0,195, 0, 0, 1, 45, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 1, 45, 0, 0, 0,195,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,195, 0, 0, 1,182, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,183,
+ 0, 0, 0, 58, 0, 0, 1,182, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,182, 0, 0, 1,184, 0, 0, 1,183, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 53, 0, 0, 1,183, 0, 0, 1,184, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,184, 0, 0, 1,182,
+ 0, 0, 0,111, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 44, 0, 0, 0, 17, 0, 0, 0,185, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,185, 0, 0, 1,184, 0, 0, 1, 44, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,111, 0, 0, 1, 44, 0, 0, 1,184,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,184, 0, 0, 0,185, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,183,
+ 0, 0, 0, 53, 0, 0, 0,184, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,184, 0, 0, 0,194, 0, 0, 1,183, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 58, 0, 0, 1,183, 0, 0, 0,194, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,194, 0, 0, 0,184,
+ 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 44, 0, 0, 0,111, 0, 0, 1,185, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,185, 0, 0, 1, 46, 0, 0, 1, 44, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 17, 0, 0, 1, 44, 0, 0, 1, 46,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 46, 0, 0, 1,185, 0, 0, 0,112, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,186,
+ 0, 0, 0,112, 0, 0, 1,185, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,185, 0, 0, 1,187, 0, 0, 1,186, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,113, 0, 0, 1,186, 0, 0, 1,187, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,187, 0, 0, 1,185,
+ 0, 0, 0,111, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 45, 0, 0, 0, 20, 0, 0, 1, 49, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 49, 0, 0, 1,187, 0, 0, 1, 45, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,111, 0, 0, 1, 45, 0, 0, 1,187,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,187, 0, 0, 1, 49, 0, 0, 0,113, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,186,
+ 0, 0, 0,113, 0, 0, 1, 48, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 48, 0, 0, 1, 47, 0, 0, 1,186, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,112, 0, 0, 1,186, 0, 0, 1, 47, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 47, 0, 0, 1, 48,
+ 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,192, 0, 0, 0, 57, 0, 0, 1,188, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,188, 0, 0, 0,196, 0, 0, 0,192, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0,192, 0, 0, 0,196,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,196, 0, 0, 1,188, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,189,
+ 0, 0, 0, 59, 0, 0, 1,188, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,188, 0, 0, 1,190, 0, 0, 1,189, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,113, 0, 0, 1,189, 0, 0, 1,190, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,190, 0, 0, 1,188,
+ 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,193, 0, 0, 0, 19, 0, 0, 1, 48, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 48, 0, 0, 1,190, 0, 0, 0,193, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 57, 0, 0, 0,193, 0, 0, 1,190,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,190, 0, 0, 1, 48, 0, 0, 0,113, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,189,
+ 0, 0, 0,113, 0, 0, 1, 49, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 49, 0, 0, 0,197, 0, 0, 1,189, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 59, 0, 0, 1,189, 0, 0, 0,197, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,197, 0, 0, 1, 49,
+ 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,191, 0, 0, 0, 56, 0, 0, 1,191, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,191, 0, 0, 1, 47, 0, 0, 0,191, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 19, 0, 0, 0,191, 0, 0, 1, 47,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 47, 0, 0, 1,191, 0, 0, 0,112, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,192,
+ 0, 0, 0,112, 0, 0, 1,191, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,191, 0, 0, 1,193, 0, 0, 1,192, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 52, 0, 0, 1,192, 0, 0, 1,193, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,193, 0, 0, 1,191,
+ 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,190, 0, 0, 0, 0, 0, 0, 0,182, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,182, 0, 0, 1,193, 0, 0, 0,190, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 56, 0, 0, 0,190, 0, 0, 1,193,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,193, 0, 0, 0,182, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,192,
+ 0, 0, 0, 52, 0, 0, 0,183, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,183, 0, 0, 1, 46, 0, 0, 1,192, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,112, 0, 0, 1,192, 0, 0, 1, 46, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 46, 0, 0, 0,183,
+ 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 51, 0, 0, 0,114, 0, 0, 1,194, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,194, 0, 0, 0,199, 0, 0, 1, 51, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 21, 0, 0, 1, 51, 0, 0, 0,199,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,199, 0, 0, 1,194, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,195,
+ 0, 0, 0, 60, 0, 0, 1,194, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,194, 0, 0, 1,196, 0, 0, 1,195, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 57, 0, 0, 1,195, 0, 0, 1,196, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,196, 0, 0, 1,194,
+ 0, 0, 0,114, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 50, 0, 0, 0, 19, 0, 0, 0,193, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,193, 0, 0, 1,196, 0, 0, 1, 50, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,114, 0, 0, 1, 50, 0, 0, 1,196,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,196, 0, 0, 0,193, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,195,
+ 0, 0, 0, 57, 0, 0, 0,192, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,192, 0, 0, 0,198, 0, 0, 1,195, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 1,195, 0, 0, 0,198, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,198, 0, 0, 0,192,
+ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 50, 0, 0, 0,114, 0, 0, 1,197, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,197, 0, 0, 1, 53, 0, 0, 1, 50, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 19, 0, 0, 1, 50, 0, 0, 1, 53,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 53, 0, 0, 1,197, 0, 0, 0,115, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,198,
+ 0, 0, 0,115, 0, 0, 1,197, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,197, 0, 0, 1,199, 0, 0, 1,198, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,116, 0, 0, 1,198, 0, 0, 1,199, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,199, 0, 0, 1,197,
+ 0, 0, 0,114, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 51, 0, 0, 0, 21, 0, 0, 1, 55, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 55, 0, 0, 1,199, 0, 0, 1, 51, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,114, 0, 0, 1, 51, 0, 0, 1,199,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,199, 0, 0, 1, 55, 0, 0, 0,116, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,198,
+ 0, 0, 0,116, 0, 0, 1, 54, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 54, 0, 0, 1, 52, 0, 0, 1,198, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,115, 0, 0, 1,198, 0, 0, 1, 52, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 52, 0, 0, 1, 54,
+ 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,176, 0, 0, 0, 49, 0, 0, 1,200, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,200, 0, 0, 0,200, 0, 0, 0,176, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0,176, 0, 0, 0,200,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,200, 0, 0, 1,200, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,201,
+ 0, 0, 0, 61, 0, 0, 1,200, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,200, 0, 0, 1,202, 0, 0, 1,201, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,116, 0, 0, 1,201, 0, 0, 1,202, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,202, 0, 0, 1,200,
+ 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,177, 0, 0, 0, 15, 0, 0, 1, 54, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 54, 0, 0, 1,202, 0, 0, 0,177, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 49, 0, 0, 0,177, 0, 0, 1,202,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,202, 0, 0, 1, 54, 0, 0, 0,116, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,201,
+ 0, 0, 0,116, 0, 0, 1, 55, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 55, 0, 0, 0,201, 0, 0, 1,201, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 61, 0, 0, 1,201, 0, 0, 0,201, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,201, 0, 0, 1, 55,
+ 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,175, 0, 0, 0, 48, 0, 0, 1,203, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,203, 0, 0, 1, 52, 0, 0, 0,175, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 15, 0, 0, 0,175, 0, 0, 1, 52,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 52, 0, 0, 1,203, 0, 0, 0,115, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,204,
+ 0, 0, 0,115, 0, 0, 1,203, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,203, 0, 0, 1,205, 0, 0, 1,204, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 56, 0, 0, 1,204, 0, 0, 1,205, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,205, 0, 0, 1,203,
+ 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,174, 0, 0, 0, 0, 0, 0, 0,190, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,190, 0, 0, 1,205, 0, 0, 0,174, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 48, 0, 0, 0,174, 0, 0, 1,205,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,205, 0, 0, 0,190, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,204,
+ 0, 0, 0, 56, 0, 0, 0,191, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,191, 0, 0, 1, 53, 0, 0, 1,204, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,115, 0, 0, 1,204, 0, 0, 1, 53, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 53, 0, 0, 0,191,
+ 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,206, 0, 0, 0,117, 0, 0, 1, 57, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 57, 0, 0, 0,207, 0, 0, 1,206, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 64, 0, 0, 1,206, 0, 0, 0,207,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,207, 0, 0, 1, 57, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,206,
+ 0, 0, 0, 64, 0, 0, 1,207, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,207, 0, 0, 1,208, 0, 0, 1,206, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,117, 0, 0, 1,206, 0, 0, 1,208, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,208, 0, 0, 1,207,
+ 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,179, 0, 0, 0, 16, 0, 0, 1, 56, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 56, 0, 0, 1,208, 0, 0, 0,179, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 50, 0, 0, 0,179, 0, 0, 1,208,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,208, 0, 0, 1, 56, 0, 0, 0,117, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,178,
+ 0, 0, 0, 50, 0, 0, 1,207, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,207, 0, 0, 0,206, 0, 0, 0,178, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0,178, 0, 0, 0,206, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,206, 0, 0, 1,207,
+ 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,209, 0, 0, 0,117, 0, 0, 1, 56, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 56, 0, 0, 1, 58, 0, 0, 1,209, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,118, 0, 0, 1,209, 0, 0, 1, 58,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 58, 0, 0, 1, 56, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,209,
+ 0, 0, 0,118, 0, 0, 1,210, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,210, 0, 0, 1,211, 0, 0, 1,209, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,117, 0, 0, 1,209, 0, 0, 1,211, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,211, 0, 0, 1,210,
+ 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 61, 0, 0, 0, 23, 0, 0, 1, 57, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 57, 0, 0, 1,211, 0, 0, 1, 61, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,119, 0, 0, 1, 61, 0, 0, 1,211,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,211, 0, 0, 1, 57, 0, 0, 0,117, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 60,
+ 0, 0, 0,119, 0, 0, 1,210, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,210, 0, 0, 1, 59, 0, 0, 1, 60, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 22, 0, 0, 1, 60, 0, 0, 1, 59, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 59, 0, 0, 1,210,
+ 0, 0, 0,118, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,212, 0, 0, 0, 63, 0, 0, 0,204, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,204, 0, 0, 0,208, 0, 0, 1,212, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 65, 0, 0, 1,212, 0, 0, 0,208,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,208, 0, 0, 0,204, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,212,
+ 0, 0, 0, 65, 0, 0, 1,213, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,213, 0, 0, 1,214, 0, 0, 1,212, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 63, 0, 0, 1,212, 0, 0, 1,214, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,214, 0, 0, 1,213,
+ 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 60, 0, 0, 0, 22, 0, 0, 0,205, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,205, 0, 0, 1,214, 0, 0, 1, 60, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,119, 0, 0, 1, 60, 0, 0, 1,214,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,214, 0, 0, 0,205, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 61,
+ 0, 0, 0,119, 0, 0, 1,213, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,213, 0, 0, 0,209, 0, 0, 1, 61, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 23, 0, 0, 1, 61, 0, 0, 0,209, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,209, 0, 0, 1,213,
+ 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,215, 0, 0, 0, 62, 0, 0, 0,203, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,203, 0, 0, 1, 59, 0, 0, 1,215, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,118, 0, 0, 1,215, 0, 0, 1, 59,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 59, 0, 0, 0,203, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,215,
+ 0, 0, 0,118, 0, 0, 1,216, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,216, 0, 0, 1,217, 0, 0, 1,215, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 62, 0, 0, 1,215, 0, 0, 1,217, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,217, 0, 0, 1,216,
+ 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,180, 0, 0, 0, 5, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,202, 0, 0, 1,217, 0, 0, 0,180, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 51, 0, 0, 0,180, 0, 0, 1,217,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,217, 0, 0, 0,202, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,181,
+ 0, 0, 0, 51, 0, 0, 1,216, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,216, 0, 0, 1, 58, 0, 0, 0,181, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 16, 0, 0, 0,181, 0, 0, 1, 58, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 58, 0, 0, 1,216,
+ 0, 0, 0,118, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,218, 0, 0, 0,120, 0, 0, 1, 63, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 63, 0, 0, 0,215, 0, 0, 1,218, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 68, 0, 0, 1,218, 0, 0, 0,215,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,215, 0, 0, 1, 63, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,218,
+ 0, 0, 0, 68, 0, 0, 1,219, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,219, 0, 0, 1,220, 0, 0, 1,218, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,120, 0, 0, 1,218, 0, 0, 1,220, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,220, 0, 0, 1,219,
+ 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,173, 0, 0, 0, 14, 0, 0, 1, 62, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 62, 0, 0, 1,220, 0, 0, 0,173, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 47, 0, 0, 0,173, 0, 0, 1,220,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,220, 0, 0, 1, 62, 0, 0, 0,120, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,172,
+ 0, 0, 0, 47, 0, 0, 1,219, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,219, 0, 0, 0,214, 0, 0, 0,172, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,172, 0, 0, 0,214, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,214, 0, 0, 1,219,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,221, 0, 0, 0,120, 0, 0, 1, 62, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 62, 0, 0, 1, 64, 0, 0, 1,221, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,121, 0, 0, 1,221, 0, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 64, 0, 0, 1, 62, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,221,
+ 0, 0, 0,121, 0, 0, 1,222, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,222, 0, 0, 1,223, 0, 0, 1,221, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,120, 0, 0, 1,221, 0, 0, 1,223, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,223, 0, 0, 1,222,
+ 0, 0, 0,122, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 67, 0, 0, 0, 25, 0, 0, 1, 63, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 63, 0, 0, 1,223, 0, 0, 1, 67, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,122, 0, 0, 1, 67, 0, 0, 1,223,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,223, 0, 0, 1, 63, 0, 0, 0,120, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 66,
+ 0, 0, 0,122, 0, 0, 1,222, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,222, 0, 0, 1, 65, 0, 0, 1, 66, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 24, 0, 0, 1, 66, 0, 0, 1, 65, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 65, 0, 0, 1,222,
+ 0, 0, 0,121, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,224, 0, 0, 0, 67, 0, 0, 0,212, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,212, 0, 0, 0,216, 0, 0, 1,224, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 69, 0, 0, 1,224, 0, 0, 0,216,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,216, 0, 0, 0,212, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,224,
+ 0, 0, 0, 69, 0, 0, 1,225, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,225, 0, 0, 1,226, 0, 0, 1,224, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 67, 0, 0, 1,224, 0, 0, 1,226, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,226, 0, 0, 1,225,
+ 0, 0, 0,122, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 66, 0, 0, 0, 24, 0, 0, 0,213, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,213, 0, 0, 1,226, 0, 0, 1, 66, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,122, 0, 0, 1, 66, 0, 0, 1,226,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,226, 0, 0, 0,213, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 67,
+ 0, 0, 0,122, 0, 0, 1,225, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,225, 0, 0, 0,217, 0, 0, 1, 67, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 25, 0, 0, 1, 67, 0, 0, 0,217, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,217, 0, 0, 1,225,
+ 0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,227, 0, 0, 0, 66, 0, 0, 0,211, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,211, 0, 0, 1, 65, 0, 0, 1,227, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,121, 0, 0, 1,227, 0, 0, 1, 65,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 65, 0, 0, 0,211, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,227,
+ 0, 0, 0,121, 0, 0, 1,228, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,228, 0, 0, 1,229, 0, 0, 1,227, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 66, 0, 0, 1,227, 0, 0, 1,229, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,229, 0, 0, 1,228,
+ 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,170, 0, 0, 0, 1, 0, 0, 0,210, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,210, 0, 0, 1,229, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 46, 0, 0, 0,170, 0, 0, 1,229,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,229, 0, 0, 0,210, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,171,
+ 0, 0, 0, 46, 0, 0, 1,228, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,228, 0, 0, 1, 64, 0, 0, 0,171, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 14, 0, 0, 0,171, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 64, 0, 0, 1,228,
+ 0, 0, 0,121, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,230, 0, 0, 0,123, 0, 0, 1, 69, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 69, 0, 0, 0,223, 0, 0, 1,230, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 72, 0, 0, 1,230, 0, 0, 0,223,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,223, 0, 0, 1, 69, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,230,
+ 0, 0, 0, 72, 0, 0, 1,231, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,231, 0, 0, 1,232, 0, 0, 1,230, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,123, 0, 0, 1,230, 0, 0, 1,232, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,232, 0, 0, 1,231,
+ 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,189, 0, 0, 0, 18, 0, 0, 1, 68, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 68, 0, 0, 1,232, 0, 0, 0,189, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 55, 0, 0, 0,189, 0, 0, 1,232,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,232, 0, 0, 1, 68, 0, 0, 0,123, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,188,
+ 0, 0, 0, 55, 0, 0, 1,231, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,231, 0, 0, 0,222, 0, 0, 0,188, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0,188, 0, 0, 0,222, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,222, 0, 0, 1,231,
+ 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,233, 0, 0, 0,123, 0, 0, 1, 68, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 68, 0, 0, 1, 70, 0, 0, 1,233, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,124, 0, 0, 1,233, 0, 0, 1, 70,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 70, 0, 0, 1, 68, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,233,
+ 0, 0, 0,124, 0, 0, 1,234, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,234, 0, 0, 1,235, 0, 0, 1,233, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,123, 0, 0, 1,233, 0, 0, 1,235, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,235, 0, 0, 1,234,
+ 0, 0, 0,125, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 73, 0, 0, 0, 27, 0, 0, 1, 69, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 69, 0, 0, 1,235, 0, 0, 1, 73, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,125, 0, 0, 1, 73, 0, 0, 1,235,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,235, 0, 0, 1, 69, 0, 0, 0,123, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 72,
+ 0, 0, 0,125, 0, 0, 1,234, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,234, 0, 0, 1, 71, 0, 0, 1, 72, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 26, 0, 0, 1, 72, 0, 0, 1, 71, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 71, 0, 0, 1,234,
+ 0, 0, 0,124, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,236, 0, 0, 0, 71, 0, 0, 0,220, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,220, 0, 0, 0,224, 0, 0, 1,236, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 73, 0, 0, 1,236, 0, 0, 0,224,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,224, 0, 0, 0,220, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,236,
+ 0, 0, 0, 73, 0, 0, 1,237, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,237, 0, 0, 1,238, 0, 0, 1,236, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 71, 0, 0, 1,236, 0, 0, 1,238, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,238, 0, 0, 1,237,
+ 0, 0, 0,125, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 72, 0, 0, 0, 26, 0, 0, 0,221, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,221, 0, 0, 1,238, 0, 0, 1, 72, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,125, 0, 0, 1, 72, 0, 0, 1,238,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,238, 0, 0, 0,221, 0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 73,
+ 0, 0, 0,125, 0, 0, 1,237, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,237, 0, 0, 0,225, 0, 0, 1, 73, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 27, 0, 0, 1, 73, 0, 0, 0,225, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,225, 0, 0, 1,237,
+ 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,239, 0, 0, 0, 70, 0, 0, 0,219, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,219, 0, 0, 1, 71, 0, 0, 1,239, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,124, 0, 0, 1,239, 0, 0, 1, 71,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 71, 0, 0, 0,219, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,239,
+ 0, 0, 0,124, 0, 0, 1,240, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,240, 0, 0, 1,241, 0, 0, 1,239, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 70, 0, 0, 1,239, 0, 0, 1,241, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,241, 0, 0, 1,240,
+ 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,186, 0, 0, 0, 2, 0, 0, 0,218, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,218, 0, 0, 1,241, 0, 0, 0,186, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 54, 0, 0, 0,186, 0, 0, 1,241,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,241, 0, 0, 0,218, 0, 0, 0, 70, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,187,
+ 0, 0, 0, 54, 0, 0, 1,240, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,240, 0, 0, 1, 70, 0, 0, 0,187, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 18, 0, 0, 0,187, 0, 0, 1, 70, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 70, 0, 0, 1,240,
+ 0, 0, 0,124, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,242, 0, 0, 0,126, 0, 0, 1, 75, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 75, 0, 0, 0,231, 0, 0, 1,242, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 76, 0, 0, 1,242, 0, 0, 0,231,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,231, 0, 0, 1, 75, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,242,
+ 0, 0, 0, 76, 0, 0, 1,243, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,243, 0, 0, 1,244, 0, 0, 1,242, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,126, 0, 0, 1,242, 0, 0, 1,244, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,244, 0, 0, 1,243,
+ 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,197, 0, 0, 0, 20, 0, 0, 1, 74, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 74, 0, 0, 1,244, 0, 0, 0,197, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 59, 0, 0, 0,197, 0, 0, 1,244,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,244, 0, 0, 1, 74, 0, 0, 0,126, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,196,
+ 0, 0, 0, 59, 0, 0, 1,243, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,243, 0, 0, 0,230, 0, 0, 0,196, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0,196, 0, 0, 0,230, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,230, 0, 0, 1,243,
+ 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,245, 0, 0, 0,126, 0, 0, 1, 74, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 74, 0, 0, 1, 76, 0, 0, 1,245, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,127, 0, 0, 1,245, 0, 0, 1, 76,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 76, 0, 0, 1, 74, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,245,
+ 0, 0, 0,127, 0, 0, 1,246, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,246, 0, 0, 1,247, 0, 0, 1,245, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,126, 0, 0, 1,245, 0, 0, 1,247, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,247, 0, 0, 1,246,
+ 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 79, 0, 0, 0, 29, 0, 0, 1, 75, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 75, 0, 0, 1,247, 0, 0, 1, 79, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,128, 0, 0, 1, 79, 0, 0, 1,247,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,247, 0, 0, 1, 75, 0, 0, 0,126, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 78,
+ 0, 0, 0,128, 0, 0, 1,246, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,246, 0, 0, 1, 77, 0, 0, 1, 78, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 28, 0, 0, 1, 78, 0, 0, 1, 77, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 77, 0, 0, 1,246,
+ 0, 0, 0,127, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,248, 0, 0, 0, 75, 0, 0, 0,228, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,228, 0, 0, 0,232, 0, 0, 1,248, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 77, 0, 0, 1,248, 0, 0, 0,232,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,232, 0, 0, 0,228, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,248,
+ 0, 0, 0, 77, 0, 0, 1,249, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,249, 0, 0, 1,250, 0, 0, 1,248, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 75, 0, 0, 1,248, 0, 0, 1,250, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,250, 0, 0, 1,249,
+ 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 78, 0, 0, 0, 28, 0, 0, 0,229, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,229, 0, 0, 1,250, 0, 0, 1, 78, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,128, 0, 0, 1, 78, 0, 0, 1,250,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,250, 0, 0, 0,229, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 79,
+ 0, 0, 0,128, 0, 0, 1,249, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,249, 0, 0, 0,233, 0, 0, 1, 79, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 29, 0, 0, 1, 79, 0, 0, 0,233, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,233, 0, 0, 1,249,
+ 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,251, 0, 0, 0, 74, 0, 0, 0,227, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,227, 0, 0, 1, 77, 0, 0, 1,251, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,127, 0, 0, 1,251, 0, 0, 1, 77,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 77, 0, 0, 0,227, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,251,
+ 0, 0, 0,127, 0, 0, 1,252, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,252, 0, 0, 1,253, 0, 0, 1,251, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 74, 0, 0, 1,251, 0, 0, 1,253, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,253, 0, 0, 1,252,
+ 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,194, 0, 0, 0, 3, 0, 0, 0,226, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,226, 0, 0, 1,253, 0, 0, 0,194, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 58, 0, 0, 0,194, 0, 0, 1,253,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,253, 0, 0, 0,226, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,195,
+ 0, 0, 0, 58, 0, 0, 1,252, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,252, 0, 0, 1, 76, 0, 0, 0,195, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0,195, 0, 0, 1, 76, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 76, 0, 0, 1,252,
+ 0, 0, 0,127, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,254, 0, 0, 0,129, 0, 0, 1, 81, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 81, 0, 0, 0,239, 0, 0, 1,254, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 80, 0, 0, 1,254, 0, 0, 0,239,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,239, 0, 0, 1, 81, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,254,
+ 0, 0, 0, 80, 0, 0, 1,255, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,255, 0, 0, 2, 0, 0, 0, 1,254, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,129, 0, 0, 1,254, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 0, 0, 1,255,
+ 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,201, 0, 0, 0, 21, 0, 0, 1, 80, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 80, 0, 0, 2, 0, 0, 0, 0,201, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 61, 0, 0, 0,201, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 0, 0, 1, 80, 0, 0, 0,129, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,200,
+ 0, 0, 0, 61, 0, 0, 1,255, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,255, 0, 0, 0,238, 0, 0, 0,200, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0,200, 0, 0, 0,238, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,238, 0, 0, 1,255,
+ 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 1, 0, 0, 0,129, 0, 0, 1, 80, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 80, 0, 0, 1, 82, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,130, 0, 0, 2, 1, 0, 0, 1, 82,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 82, 0, 0, 1, 80, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 1,
+ 0, 0, 0,130, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 2, 0, 0, 2, 3, 0, 0, 2, 1, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,129, 0, 0, 2, 1, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 3, 0, 0, 2, 2,
+ 0, 0, 0,131, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 85, 0, 0, 0, 31, 0, 0, 1, 81, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 81, 0, 0, 2, 3, 0, 0, 1, 85, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,131, 0, 0, 1, 85, 0, 0, 2, 3,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 3, 0, 0, 1, 81, 0, 0, 0,129, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 84,
+ 0, 0, 0,131, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 2, 0, 0, 1, 83, 0, 0, 1, 84, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 30, 0, 0, 1, 84, 0, 0, 1, 83, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 83, 0, 0, 2, 2,
+ 0, 0, 0,130, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 4, 0, 0, 0, 79, 0, 0, 0,236, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,236, 0, 0, 0,240, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 81, 0, 0, 2, 4, 0, 0, 0,240,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,240, 0, 0, 0,236, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 4,
+ 0, 0, 0, 81, 0, 0, 2, 5, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 5, 0, 0, 2, 6, 0, 0, 2, 4, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 79, 0, 0, 2, 4, 0, 0, 2, 6, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 6, 0, 0, 2, 5,
+ 0, 0, 0,131, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 84, 0, 0, 0, 30, 0, 0, 0,237, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,237, 0, 0, 2, 6, 0, 0, 1, 84, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,131, 0, 0, 1, 84, 0, 0, 2, 6,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 6, 0, 0, 0,237, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 85,
+ 0, 0, 0,131, 0, 0, 2, 5, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 5, 0, 0, 0,241, 0, 0, 1, 85, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 31, 0, 0, 1, 85, 0, 0, 0,241, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,241, 0, 0, 2, 5,
+ 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 7, 0, 0, 0, 78, 0, 0, 0,235, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,235, 0, 0, 1, 83, 0, 0, 2, 7, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,130, 0, 0, 2, 7, 0, 0, 1, 83,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 83, 0, 0, 0,235, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 7,
+ 0, 0, 0,130, 0, 0, 2, 8, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 8, 0, 0, 2, 9, 0, 0, 2, 7, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 78, 0, 0, 2, 7, 0, 0, 2, 9, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 9, 0, 0, 2, 8,
+ 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,198, 0, 0, 0, 4, 0, 0, 0,234, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,234, 0, 0, 2, 9, 0, 0, 0,198, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0,198, 0, 0, 2, 9,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 9, 0, 0, 0,234, 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,199,
+ 0, 0, 0, 60, 0, 0, 2, 8, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 8, 0, 0, 1, 82, 0, 0, 0,199, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 21, 0, 0, 0,199, 0, 0, 1, 82, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 82, 0, 0, 2, 8,
+ 0, 0, 0,130, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 87, 0, 0, 0,132, 0, 0, 2, 10, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 10, 0, 0, 0,245, 0, 0, 1, 87, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 32, 0, 0, 1, 87, 0, 0, 0,245,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,245, 0, 0, 2, 10, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 11,
+ 0, 0, 0, 83, 0, 0, 2, 10, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 10, 0, 0, 2, 12, 0, 0, 2, 11, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 65, 0, 0, 2, 11, 0, 0, 2, 12, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 12, 0, 0, 2, 10,
+ 0, 0, 0,132, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 86, 0, 0, 0, 23, 0, 0, 0,209, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,209, 0, 0, 2, 12, 0, 0, 1, 86, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,132, 0, 0, 1, 86, 0, 0, 2, 12,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 12, 0, 0, 0,209, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 11,
+ 0, 0, 0, 65, 0, 0, 0,208, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,208, 0, 0, 0,244, 0, 0, 2, 11, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 83, 0, 0, 2, 11, 0, 0, 0,244, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,244, 0, 0, 0,208,
+ 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 86, 0, 0, 0,132, 0, 0, 2, 13, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 13, 0, 0, 1, 88, 0, 0, 1, 86, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 23, 0, 0, 1, 86, 0, 0, 1, 88,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 88, 0, 0, 2, 13, 0, 0, 0,133, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 14,
+ 0, 0, 0,133, 0, 0, 2, 13, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 13, 0, 0, 2, 15, 0, 0, 2, 14, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,134, 0, 0, 2, 14, 0, 0, 2, 15, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 15, 0, 0, 2, 13,
+ 0, 0, 0,132, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 87, 0, 0, 0, 32, 0, 0, 1, 91, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 91, 0, 0, 2, 15, 0, 0, 1, 87, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,132, 0, 0, 1, 87, 0, 0, 2, 15,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 15, 0, 0, 1, 91, 0, 0, 0,134, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 14,
+ 0, 0, 0,134, 0, 0, 1, 90, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 90, 0, 0, 1, 89, 0, 0, 2, 14, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,133, 0, 0, 2, 14, 0, 0, 1, 89, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 89, 0, 0, 1, 90,
+ 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,212, 0, 0, 0, 67, 0, 0, 2, 16, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 16, 0, 0, 0,242, 0, 0, 0,212, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0,212, 0, 0, 0,242,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,242, 0, 0, 2, 16, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 17,
+ 0, 0, 0, 82, 0, 0, 2, 16, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 16, 0, 0, 2, 18, 0, 0, 2, 17, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,134, 0, 0, 2, 17, 0, 0, 2, 18, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 18, 0, 0, 2, 16,
+ 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,213, 0, 0, 0, 24, 0, 0, 1, 90, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 90, 0, 0, 2, 18, 0, 0, 0,213, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 67, 0, 0, 0,213, 0, 0, 2, 18,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 18, 0, 0, 1, 90, 0, 0, 0,134, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 17,
+ 0, 0, 0,134, 0, 0, 1, 91, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 91, 0, 0, 0,243, 0, 0, 2, 17, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 82, 0, 0, 2, 17, 0, 0, 0,243, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,243, 0, 0, 1, 91,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,211, 0, 0, 0, 66, 0, 0, 2, 19, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 19, 0, 0, 1, 89, 0, 0, 0,211, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 24, 0, 0, 0,211, 0, 0, 1, 89,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 89, 0, 0, 2, 19, 0, 0, 0,133, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 20,
+ 0, 0, 0,133, 0, 0, 2, 19, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 19, 0, 0, 2, 21, 0, 0, 2, 20, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 64, 0, 0, 2, 20, 0, 0, 2, 21, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 21, 0, 0, 2, 19,
+ 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,210, 0, 0, 0, 1, 0, 0, 0,206, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,206, 0, 0, 2, 21, 0, 0, 0,210, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 66, 0, 0, 0,210, 0, 0, 2, 21,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 21, 0, 0, 0,206, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 20,
+ 0, 0, 0, 64, 0, 0, 0,207, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,207, 0, 0, 1, 88, 0, 0, 2, 20, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,133, 0, 0, 2, 20, 0, 0, 1, 88, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 88, 0, 0, 0,207,
+ 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 93, 0, 0, 0,135, 0, 0, 2, 22, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 22, 0, 0, 0,247, 0, 0, 1, 93, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 33, 0, 0, 1, 93, 0, 0, 0,247,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,247, 0, 0, 2, 22, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 23,
+ 0, 0, 0, 84, 0, 0, 2, 22, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 22, 0, 0, 2, 24, 0, 0, 2, 23, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 69, 0, 0, 2, 23, 0, 0, 2, 24, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 24, 0, 0, 2, 22,
+ 0, 0, 0,135, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 92, 0, 0, 0, 25, 0, 0, 0,217, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,217, 0, 0, 2, 24, 0, 0, 1, 92, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,135, 0, 0, 1, 92, 0, 0, 2, 24,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 24, 0, 0, 0,217, 0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 23,
+ 0, 0, 0, 69, 0, 0, 0,216, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,216, 0, 0, 0,246, 0, 0, 2, 23, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 84, 0, 0, 2, 23, 0, 0, 0,246, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,246, 0, 0, 0,216,
+ 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 92, 0, 0, 0,135, 0, 0, 2, 25, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 25, 0, 0, 1, 94, 0, 0, 1, 92, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 25, 0, 0, 1, 92, 0, 0, 1, 94,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 94, 0, 0, 2, 25, 0, 0, 0,136, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 26,
+ 0, 0, 0,136, 0, 0, 2, 25, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 25, 0, 0, 2, 27, 0, 0, 2, 26, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,137, 0, 0, 2, 26, 0, 0, 2, 27, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 27, 0, 0, 2, 25,
+ 0, 0, 0,135, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 93, 0, 0, 0, 33, 0, 0, 1, 97, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 97, 0, 0, 2, 27, 0, 0, 1, 93, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,135, 0, 0, 1, 93, 0, 0, 2, 27,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 27, 0, 0, 1, 97, 0, 0, 0,137, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 26,
+ 0, 0, 0,137, 0, 0, 1, 96, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 96, 0, 0, 1, 95, 0, 0, 2, 26, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,136, 0, 0, 2, 26, 0, 0, 1, 95, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 95, 0, 0, 1, 96,
+ 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,220, 0, 0, 0, 71, 0, 0, 2, 28, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 28, 0, 0, 0,248, 0, 0, 0,220, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0,220, 0, 0, 0,248,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,248, 0, 0, 2, 28, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 29,
+ 0, 0, 0, 85, 0, 0, 2, 28, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 28, 0, 0, 2, 30, 0, 0, 2, 29, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,137, 0, 0, 2, 29, 0, 0, 2, 30, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 30, 0, 0, 2, 28,
+ 0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,221, 0, 0, 0, 26, 0, 0, 1, 96, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 96, 0, 0, 2, 30, 0, 0, 0,221, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 71, 0, 0, 0,221, 0, 0, 2, 30,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 30, 0, 0, 1, 96, 0, 0, 0,137, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 29,
+ 0, 0, 0,137, 0, 0, 1, 97, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 97, 0, 0, 0,249, 0, 0, 2, 29, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 85, 0, 0, 2, 29, 0, 0, 0,249, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,249, 0, 0, 1, 97,
+ 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,219, 0, 0, 0, 70, 0, 0, 2, 31, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 31, 0, 0, 1, 95, 0, 0, 0,219, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 26, 0, 0, 0,219, 0, 0, 1, 95,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 95, 0, 0, 2, 31, 0, 0, 0,136, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 32,
+ 0, 0, 0,136, 0, 0, 2, 31, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 31, 0, 0, 2, 33, 0, 0, 2, 32, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 68, 0, 0, 2, 32, 0, 0, 2, 33, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 33, 0, 0, 2, 31,
+ 0, 0, 0, 70, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,218, 0, 0, 0, 2, 0, 0, 0,214, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,214, 0, 0, 2, 33, 0, 0, 0,218, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 70, 0, 0, 0,218, 0, 0, 2, 33,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 33, 0, 0, 0,214, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 32,
+ 0, 0, 0, 68, 0, 0, 0,215, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,215, 0, 0, 1, 94, 0, 0, 2, 32, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,136, 0, 0, 2, 32, 0, 0, 1, 94, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 94, 0, 0, 0,215,
+ 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 99, 0, 0, 0,138, 0, 0, 2, 34, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 34, 0, 0, 0,251, 0, 0, 1, 99, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 34, 0, 0, 1, 99, 0, 0, 0,251,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,251, 0, 0, 2, 34, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 35,
+ 0, 0, 0, 86, 0, 0, 2, 34, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 34, 0, 0, 2, 36, 0, 0, 2, 35, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 73, 0, 0, 2, 35, 0, 0, 2, 36, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 36, 0, 0, 2, 34,
+ 0, 0, 0,138, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 98, 0, 0, 0, 27, 0, 0, 0,225, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,225, 0, 0, 2, 36, 0, 0, 1, 98, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,138, 0, 0, 1, 98, 0, 0, 2, 36,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 36, 0, 0, 0,225, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 35,
+ 0, 0, 0, 73, 0, 0, 0,224, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,224, 0, 0, 0,250, 0, 0, 2, 35, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 86, 0, 0, 2, 35, 0, 0, 0,250, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,250, 0, 0, 0,224,
+ 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 98, 0, 0, 0,138, 0, 0, 2, 37, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 37, 0, 0, 1,100, 0, 0, 1, 98, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 27, 0, 0, 1, 98, 0, 0, 1,100,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,100, 0, 0, 2, 37, 0, 0, 0,139, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 38,
+ 0, 0, 0,139, 0, 0, 2, 37, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 37, 0, 0, 2, 39, 0, 0, 2, 38, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,140, 0, 0, 2, 38, 0, 0, 2, 39, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 39, 0, 0, 2, 37,
+ 0, 0, 0,138, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 99, 0, 0, 0, 34, 0, 0, 1,103, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,103, 0, 0, 2, 39, 0, 0, 1, 99, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,138, 0, 0, 1, 99, 0, 0, 2, 39,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 39, 0, 0, 1,103, 0, 0, 0,140, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 38,
+ 0, 0, 0,140, 0, 0, 1,102, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,102, 0, 0, 1,101, 0, 0, 2, 38, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,139, 0, 0, 2, 38, 0, 0, 1,101, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,101, 0, 0, 1,102,
+ 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,228, 0, 0, 0, 75, 0, 0, 2, 40, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 40, 0, 0, 0,252, 0, 0, 0,228, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,228, 0, 0, 0,252,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,252, 0, 0, 2, 40, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 41,
+ 0, 0, 0, 87, 0, 0, 2, 40, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 40, 0, 0, 2, 42, 0, 0, 2, 41, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,140, 0, 0, 2, 41, 0, 0, 2, 42, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 42, 0, 0, 2, 40,
+ 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,229, 0, 0, 0, 28, 0, 0, 1,102, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,102, 0, 0, 2, 42, 0, 0, 0,229, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 75, 0, 0, 0,229, 0, 0, 2, 42,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 42, 0, 0, 1,102, 0, 0, 0,140, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 41,
+ 0, 0, 0,140, 0, 0, 1,103, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,103, 0, 0, 0,253, 0, 0, 2, 41, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 87, 0, 0, 2, 41, 0, 0, 0,253, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,253, 0, 0, 1,103,
+ 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,227, 0, 0, 0, 74, 0, 0, 2, 43, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 43, 0, 0, 1,101, 0, 0, 0,227, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 28, 0, 0, 0,227, 0, 0, 1,101,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,101, 0, 0, 2, 43, 0, 0, 0,139, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 44,
+ 0, 0, 0,139, 0, 0, 2, 43, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 43, 0, 0, 2, 45, 0, 0, 2, 44, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 72, 0, 0, 2, 44, 0, 0, 2, 45, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 45, 0, 0, 2, 43,
+ 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,226, 0, 0, 0, 3, 0, 0, 0,222, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,222, 0, 0, 2, 45, 0, 0, 0,226, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 74, 0, 0, 0,226, 0, 0, 2, 45,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 45, 0, 0, 0,222, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 44,
+ 0, 0, 0, 72, 0, 0, 0,223, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,223, 0, 0, 1,100, 0, 0, 2, 44, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,139, 0, 0, 2, 44, 0, 0, 1,100, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,100, 0, 0, 0,223,
+ 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,105, 0, 0, 0,141, 0, 0, 2, 46, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 46, 0, 0, 0,255, 0, 0, 1,105, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 35, 0, 0, 1,105, 0, 0, 0,255,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,255, 0, 0, 2, 46, 0, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 47,
+ 0, 0, 0, 88, 0, 0, 2, 46, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 46, 0, 0, 2, 48, 0, 0, 2, 47, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 77, 0, 0, 2, 47, 0, 0, 2, 48, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 48, 0, 0, 2, 46,
+ 0, 0, 0,141, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,104, 0, 0, 0, 29, 0, 0, 0,233, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,233, 0, 0, 2, 48, 0, 0, 1,104, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,141, 0, 0, 1,104, 0, 0, 2, 48,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 48, 0, 0, 0,233, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 47,
+ 0, 0, 0, 77, 0, 0, 0,232, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,232, 0, 0, 0,254, 0, 0, 2, 47, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 88, 0, 0, 2, 47, 0, 0, 0,254, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,254, 0, 0, 0,232,
+ 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,104, 0, 0, 0,141, 0, 0, 2, 49, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 49, 0, 0, 1,106, 0, 0, 1,104, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 29, 0, 0, 1,104, 0, 0, 1,106,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,106, 0, 0, 2, 49, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 50,
+ 0, 0, 0,142, 0, 0, 2, 49, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 49, 0, 0, 2, 51, 0, 0, 2, 50, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,143, 0, 0, 2, 50, 0, 0, 2, 51, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 51, 0, 0, 2, 49,
+ 0, 0, 0,141, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,105, 0, 0, 0, 35, 0, 0, 1,109, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,109, 0, 0, 2, 51, 0, 0, 1,105, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,141, 0, 0, 1,105, 0, 0, 2, 51,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 51, 0, 0, 1,109, 0, 0, 0,143, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 50,
+ 0, 0, 0,143, 0, 0, 1,108, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,108, 0, 0, 1,107, 0, 0, 2, 50, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,142, 0, 0, 2, 50, 0, 0, 1,107, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,107, 0, 0, 1,108,
+ 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,236, 0, 0, 0, 79, 0, 0, 2, 52, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 52, 0, 0, 1, 0, 0, 0, 0,236, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 9, 0, 0, 0,236, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 0, 0, 0, 2, 52, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 53,
+ 0, 0, 0, 89, 0, 0, 2, 52, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 52, 0, 0, 2, 54, 0, 0, 2, 53, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,143, 0, 0, 2, 53, 0, 0, 2, 54, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 54, 0, 0, 2, 52,
+ 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,237, 0, 0, 0, 30, 0, 0, 1,108, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,108, 0, 0, 2, 54, 0, 0, 0,237, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 79, 0, 0, 0,237, 0, 0, 2, 54,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 54, 0, 0, 1,108, 0, 0, 0,143, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 53,
+ 0, 0, 0,143, 0, 0, 1,109, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,109, 0, 0, 1, 1, 0, 0, 2, 53, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 89, 0, 0, 2, 53, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 1, 0, 0, 1,109,
+ 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,235, 0, 0, 0, 78, 0, 0, 2, 55, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 55, 0, 0, 1,107, 0, 0, 0,235, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 30, 0, 0, 0,235, 0, 0, 1,107,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,107, 0, 0, 2, 55, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 56,
+ 0, 0, 0,142, 0, 0, 2, 55, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 55, 0, 0, 2, 57, 0, 0, 2, 56, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 76, 0, 0, 2, 56, 0, 0, 2, 57, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 57, 0, 0, 2, 55,
+ 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,234, 0, 0, 0, 4, 0, 0, 0,230, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,230, 0, 0, 2, 57, 0, 0, 0,234, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 78, 0, 0, 0,234, 0, 0, 2, 57,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 57, 0, 0, 0,230, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 56,
+ 0, 0, 0, 76, 0, 0, 0,231, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,231, 0, 0, 1,106, 0, 0, 2, 56, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,142, 0, 0, 2, 56, 0, 0, 1,106, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,106, 0, 0, 0,231,
+ 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,111, 0, 0, 0,144, 0, 0, 2, 58, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 58, 0, 0, 1, 3, 0, 0, 1,111, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 36, 0, 0, 1,111, 0, 0, 1, 3,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 3, 0, 0, 2, 58, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 59,
+ 0, 0, 0, 90, 0, 0, 2, 58, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 58, 0, 0, 2, 60, 0, 0, 2, 59, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 81, 0, 0, 2, 59, 0, 0, 2, 60, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 60, 0, 0, 2, 58,
+ 0, 0, 0,144, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,110, 0, 0, 0, 31, 0, 0, 0,241, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,241, 0, 0, 2, 60, 0, 0, 1,110, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,144, 0, 0, 1,110, 0, 0, 2, 60,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 60, 0, 0, 0,241, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 59,
+ 0, 0, 0, 81, 0, 0, 0,240, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,240, 0, 0, 1, 2, 0, 0, 2, 59, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 90, 0, 0, 2, 59, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 2, 0, 0, 0,240,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,110, 0, 0, 0,144, 0, 0, 2, 61, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 61, 0, 0, 1,113, 0, 0, 1,110, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 31, 0, 0, 1,110, 0, 0, 1,113,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,113, 0, 0, 2, 61, 0, 0, 0,145, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 62,
+ 0, 0, 0,145, 0, 0, 2, 61, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 61, 0, 0, 2, 63, 0, 0, 2, 62, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,146, 0, 0, 2, 62, 0, 0, 2, 63, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 63, 0, 0, 2, 61,
+ 0, 0, 0,144, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,111, 0, 0, 0, 36, 0, 0, 1,115, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,115, 0, 0, 2, 63, 0, 0, 1,111, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,144, 0, 0, 1,111, 0, 0, 2, 63,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 63, 0, 0, 1,115, 0, 0, 0,146, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 62,
+ 0, 0, 0,146, 0, 0, 1,114, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,114, 0, 0, 1,112, 0, 0, 2, 62, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,145, 0, 0, 2, 62, 0, 0, 1,112, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,112, 0, 0, 1,114,
+ 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,204, 0, 0, 0, 63, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 64, 0, 0, 1, 4, 0, 0, 0,204, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 10, 0, 0, 0,204, 0, 0, 1, 4,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 4, 0, 0, 2, 64, 0, 0, 0, 91, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 65,
+ 0, 0, 0, 91, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 64, 0, 0, 2, 66, 0, 0, 2, 65, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,146, 0, 0, 2, 65, 0, 0, 2, 66, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 66, 0, 0, 2, 64,
+ 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,205, 0, 0, 0, 22, 0, 0, 1,114, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,114, 0, 0, 2, 66, 0, 0, 0,205, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 63, 0, 0, 0,205, 0, 0, 2, 66,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 66, 0, 0, 1,114, 0, 0, 0,146, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 65,
+ 0, 0, 0,146, 0, 0, 1,115, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,115, 0, 0, 1, 5, 0, 0, 2, 65, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 91, 0, 0, 2, 65, 0, 0, 1, 5, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 5, 0, 0, 1,115,
+ 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,203, 0, 0, 0, 62, 0, 0, 2, 67, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 2, 67, 0, 0, 1,112, 0, 0, 0,203, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 22, 0, 0, 0,203, 0, 0, 1,112,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,112, 0, 0, 2, 67, 0, 0, 0,145, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 68,
+ 0, 0, 0,145, 0, 0, 2, 67, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 67, 0, 0, 2, 69, 0, 0, 2, 68, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 80, 0, 0, 2, 68, 0, 0, 2, 69, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 69, 0, 0, 2, 67,
+ 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,202, 0, 0, 0, 5, 0, 0, 0,238, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0,238, 0, 0, 2, 69, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 62, 0, 0, 0,202, 0, 0, 2, 69,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 69, 0, 0, 0,238, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 68,
+ 0, 0, 0, 80, 0, 0, 0,239, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,239, 0, 0, 1,113, 0, 0, 2, 68, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,145, 0, 0, 2, 68, 0, 0, 1,113, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,113, 0, 0, 0,239,
+ 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 70, 0, 0, 0,147, 0, 0, 1,117, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,117, 0, 0, 1, 11, 0, 0, 2, 70, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 94, 0, 0, 2, 70, 0, 0, 1, 11,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 11, 0, 0, 1,117, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 70,
+ 0, 0, 0, 94, 0, 0, 2, 71, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 71, 0, 0, 2, 72, 0, 0, 2, 70, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,147, 0, 0, 2, 70, 0, 0, 2, 72, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 72, 0, 0, 2, 71,
+ 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,243, 0, 0, 0, 32, 0, 0, 1,116, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,116, 0, 0, 2, 72, 0, 0, 0,243, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 82, 0, 0, 0,243, 0, 0, 2, 72,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 72, 0, 0, 1,116, 0, 0, 0,147, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,242,
+ 0, 0, 0, 82, 0, 0, 2, 71, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 71, 0, 0, 1, 10, 0, 0, 0,242, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0,242, 0, 0, 1, 10, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 10, 0, 0, 2, 71,
+ 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 73, 0, 0, 0,147, 0, 0, 1,116, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,116, 0, 0, 1,118, 0, 0, 2, 73, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,148, 0, 0, 2, 73, 0, 0, 1,118,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,118, 0, 0, 1,116, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 73,
+ 0, 0, 0,148, 0, 0, 2, 74, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 74, 0, 0, 2, 75, 0, 0, 2, 73, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,147, 0, 0, 2, 73, 0, 0, 2, 75, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 75, 0, 0, 2, 74,
+ 0, 0, 0,149, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,121, 0, 0, 0, 38, 0, 0, 1,117, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,117, 0, 0, 2, 75, 0, 0, 1,121, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,149, 0, 0, 1,121, 0, 0, 2, 75,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 75, 0, 0, 1,117, 0, 0, 0,147, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,120,
+ 0, 0, 0,149, 0, 0, 2, 74, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 74, 0, 0, 1,119, 0, 0, 1,120, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 37, 0, 0, 1,120, 0, 0, 1,119, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,119, 0, 0, 2, 74,
+ 0, 0, 0,148, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 76, 0, 0, 0, 93, 0, 0, 1, 8, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 8, 0, 0, 1, 12, 0, 0, 2, 76, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 95, 0, 0, 2, 76, 0, 0, 1, 12,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 12, 0, 0, 1, 8, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 76,
+ 0, 0, 0, 95, 0, 0, 2, 77, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 77, 0, 0, 2, 78, 0, 0, 2, 76, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 93, 0, 0, 2, 76, 0, 0, 2, 78, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 78, 0, 0, 2, 77,
+ 0, 0, 0,149, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,120, 0, 0, 0, 37, 0, 0, 1, 9, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 9, 0, 0, 2, 78, 0, 0, 1,120, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,149, 0, 0, 1,120, 0, 0, 2, 78,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 78, 0, 0, 1, 9, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,121,
+ 0, 0, 0,149, 0, 0, 2, 77, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 77, 0, 0, 1, 13, 0, 0, 1,121, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 38, 0, 0, 1,121, 0, 0, 1, 13, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 13, 0, 0, 2, 77,
+ 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 79, 0, 0, 0, 92, 0, 0, 1, 7, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 7, 0, 0, 1,119, 0, 0, 2, 79, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,148, 0, 0, 2, 79, 0, 0, 1,119,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,119, 0, 0, 1, 7, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 79,
+ 0, 0, 0,148, 0, 0, 2, 80, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 80, 0, 0, 2, 81, 0, 0, 2, 79, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 92, 0, 0, 2, 79, 0, 0, 2, 81, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 81, 0, 0, 2, 80,
+ 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,244, 0, 0, 0, 10, 0, 0, 1, 6, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 6, 0, 0, 2, 81, 0, 0, 0,244, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 83, 0, 0, 0,244, 0, 0, 2, 81,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 81, 0, 0, 1, 6, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,245,
+ 0, 0, 0, 83, 0, 0, 2, 80, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 80, 0, 0, 1,118, 0, 0, 0,245, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 32, 0, 0, 0,245, 0, 0, 1,118, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,118, 0, 0, 2, 80,
+ 0, 0, 0,148, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 82, 0, 0, 0,150, 0, 0, 1,123, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,123, 0, 0, 1, 15, 0, 0, 2, 82, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 96, 0, 0, 2, 82, 0, 0, 1, 15,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 15, 0, 0, 1,123, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 82,
+ 0, 0, 0, 96, 0, 0, 2, 83, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 83, 0, 0, 2, 84, 0, 0, 2, 82, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,150, 0, 0, 2, 82, 0, 0, 2, 84, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 84, 0, 0, 2, 83,
+ 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,249, 0, 0, 0, 33, 0, 0, 1,122, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,122, 0, 0, 2, 84, 0, 0, 0,249, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 85, 0, 0, 0,249, 0, 0, 2, 84,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 84, 0, 0, 1,122, 0, 0, 0,150, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,248,
+ 0, 0, 0, 85, 0, 0, 2, 83, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 83, 0, 0, 1, 14, 0, 0, 0,248, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0,248, 0, 0, 1, 14, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 14, 0, 0, 2, 83,
+ 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 85, 0, 0, 0,150, 0, 0, 1,122, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,122, 0, 0, 1,124, 0, 0, 2, 85, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,151, 0, 0, 2, 85, 0, 0, 1,124,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,124, 0, 0, 1,122, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 85,
+ 0, 0, 0,151, 0, 0, 2, 86, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 86, 0, 0, 2, 87, 0, 0, 2, 85, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,150, 0, 0, 2, 85, 0, 0, 2, 87, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 87, 0, 0, 2, 86,
+ 0, 0, 0,152, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,127, 0, 0, 0, 39, 0, 0, 1,123, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,123, 0, 0, 2, 87, 0, 0, 1,127, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,152, 0, 0, 1,127, 0, 0, 2, 87,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 87, 0, 0, 1,123, 0, 0, 0,150, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,126,
+ 0, 0, 0,152, 0, 0, 2, 86, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 86, 0, 0, 1,125, 0, 0, 1,126, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 38, 0, 0, 1,126, 0, 0, 1,125, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,125, 0, 0, 2, 86,
+ 0, 0, 0,151, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 88, 0, 0, 0, 95, 0, 0, 1, 12, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 12, 0, 0, 1, 16, 0, 0, 2, 88, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 97, 0, 0, 2, 88, 0, 0, 1, 16,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 16, 0, 0, 1, 12, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 88,
+ 0, 0, 0, 97, 0, 0, 2, 89, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 89, 0, 0, 2, 90, 0, 0, 2, 88, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 95, 0, 0, 2, 88, 0, 0, 2, 90, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 90, 0, 0, 2, 89,
+ 0, 0, 0,152, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,126, 0, 0, 0, 38, 0, 0, 1, 13, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 13, 0, 0, 2, 90, 0, 0, 1,126, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,152, 0, 0, 1,126, 0, 0, 2, 90,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 90, 0, 0, 1, 13, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,127,
+ 0, 0, 0,152, 0, 0, 2, 89, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 89, 0, 0, 1, 17, 0, 0, 1,127, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 39, 0, 0, 1,127, 0, 0, 1, 17, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 17, 0, 0, 2, 89,
+ 0, 0, 0, 97, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 91, 0, 0, 0, 94, 0, 0, 1, 11, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 11, 0, 0, 1,125, 0, 0, 2, 91, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,151, 0, 0, 2, 91, 0, 0, 1,125,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,125, 0, 0, 1, 11, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 91,
+ 0, 0, 0,151, 0, 0, 2, 92, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 92, 0, 0, 2, 93, 0, 0, 2, 91, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 94, 0, 0, 2, 91, 0, 0, 2, 93, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 93, 0, 0, 2, 92,
+ 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,246, 0, 0, 0, 6, 0, 0, 1, 10, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 10, 0, 0, 2, 93, 0, 0, 0,246, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 84, 0, 0, 0,246, 0, 0, 2, 93,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 93, 0, 0, 1, 10, 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,247,
+ 0, 0, 0, 84, 0, 0, 2, 92, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 92, 0, 0, 1,124, 0, 0, 0,247, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 33, 0, 0, 0,247, 0, 0, 1,124, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,124, 0, 0, 2, 92,
+ 0, 0, 0,151, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 94, 0, 0, 0,153, 0, 0, 1,129, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,129, 0, 0, 1, 19, 0, 0, 2, 94, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 98, 0, 0, 2, 94, 0, 0, 1, 19,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 19, 0, 0, 1,129, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 94,
+ 0, 0, 0, 98, 0, 0, 2, 95, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 95, 0, 0, 2, 96, 0, 0, 2, 94, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,153, 0, 0, 2, 94, 0, 0, 2, 96, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 96, 0, 0, 2, 95,
+ 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,253, 0, 0, 0, 34, 0, 0, 1,128, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,128, 0, 0, 2, 96, 0, 0, 0,253, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 87, 0, 0, 0,253, 0, 0, 2, 96,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 96, 0, 0, 1,128, 0, 0, 0,153, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,252,
+ 0, 0, 0, 87, 0, 0, 2, 95, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 95, 0, 0, 1, 18, 0, 0, 0,252, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,252, 0, 0, 1, 18, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 18, 0, 0, 2, 95,
+ 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 97, 0, 0, 0,153, 0, 0, 1,128, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,128, 0, 0, 1,130, 0, 0, 2, 97, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,154, 0, 0, 2, 97, 0, 0, 1,130,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,130, 0, 0, 1,128, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 97,
+ 0, 0, 0,154, 0, 0, 2, 98, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 98, 0, 0, 2, 99, 0, 0, 2, 97, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,153, 0, 0, 2, 97, 0, 0, 2, 99, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 99, 0, 0, 2, 98,
+ 0, 0, 0,155, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,133, 0, 0, 0, 40, 0, 0, 1,129, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,129, 0, 0, 2, 99, 0, 0, 1,133, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,155, 0, 0, 1,133, 0, 0, 2, 99,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 99, 0, 0, 1,129, 0, 0, 0,153, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,132,
+ 0, 0, 0,155, 0, 0, 2, 98, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 98, 0, 0, 1,131, 0, 0, 1,132, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 39, 0, 0, 1,132, 0, 0, 1,131, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,131, 0, 0, 2, 98,
+ 0, 0, 0,154, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,100, 0, 0, 0, 97, 0, 0, 1, 16, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 16, 0, 0, 1, 20, 0, 0, 2,100, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 99, 0, 0, 2,100, 0, 0, 1, 20,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 20, 0, 0, 1, 16, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,100,
+ 0, 0, 0, 99, 0, 0, 2,101, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,101, 0, 0, 2,102, 0, 0, 2,100, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 97, 0, 0, 2,100, 0, 0, 2,102, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,102, 0, 0, 2,101,
+ 0, 0, 0,155, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,132, 0, 0, 0, 39, 0, 0, 1, 17, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 17, 0, 0, 2,102, 0, 0, 1,132, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,155, 0, 0, 1,132, 0, 0, 2,102,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,102, 0, 0, 1, 17, 0, 0, 0, 97, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,133,
+ 0, 0, 0,155, 0, 0, 2,101, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,101, 0, 0, 1, 21, 0, 0, 1,133, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 40, 0, 0, 1,133, 0, 0, 1, 21, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 21, 0, 0, 2,101,
+ 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,103, 0, 0, 0, 96, 0, 0, 1, 15, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 15, 0, 0, 1,131, 0, 0, 2,103, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,154, 0, 0, 2,103, 0, 0, 1,131,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,131, 0, 0, 1, 15, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,103,
+ 0, 0, 0,154, 0, 0, 2,104, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,104, 0, 0, 2,105, 0, 0, 2,103, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 96, 0, 0, 2,103, 0, 0, 2,105, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,105, 0, 0, 2,104,
+ 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,250, 0, 0, 0, 7, 0, 0, 1, 14, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 14, 0, 0, 2,105, 0, 0, 0,250, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 86, 0, 0, 0,250, 0, 0, 2,105,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,105, 0, 0, 1, 14, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,251,
+ 0, 0, 0, 86, 0, 0, 2,104, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,104, 0, 0, 1,130, 0, 0, 0,251, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 34, 0, 0, 0,251, 0, 0, 1,130, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,130, 0, 0, 2,104,
+ 0, 0, 0,154, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,106, 0, 0, 0,156, 0, 0, 1,135, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,135, 0, 0, 1, 23, 0, 0, 2,106, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,100, 0, 0, 2,106, 0, 0, 1, 23,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 23, 0, 0, 1,135, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,106,
+ 0, 0, 0,100, 0, 0, 2,107, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,107, 0, 0, 2,108, 0, 0, 2,106, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,156, 0, 0, 2,106, 0, 0, 2,108, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,108, 0, 0, 2,107,
+ 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 1, 0, 0, 0, 35, 0, 0, 1,134, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,134, 0, 0, 2,108, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 89, 0, 0, 1, 1, 0, 0, 2,108,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,108, 0, 0, 1,134, 0, 0, 0,156, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 0,
+ 0, 0, 0, 89, 0, 0, 2,107, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,107, 0, 0, 1, 22, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 9, 0, 0, 1, 0, 0, 0, 1, 22, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 22, 0, 0, 2,107,
+ 0, 0, 0,100, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,109, 0, 0, 0,156, 0, 0, 1,134, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,134, 0, 0, 1,136, 0, 0, 2,109, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,157, 0, 0, 2,109, 0, 0, 1,136,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,136, 0, 0, 1,134, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,109,
+ 0, 0, 0,157, 0, 0, 2,110, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,110, 0, 0, 2,111, 0, 0, 2,109, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,156, 0, 0, 2,109, 0, 0, 2,111, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,111, 0, 0, 2,110,
+ 0, 0, 0,158, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,139, 0, 0, 0, 41, 0, 0, 1,135, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,135, 0, 0, 2,111, 0, 0, 1,139, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,158, 0, 0, 1,139, 0, 0, 2,111,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,111, 0, 0, 1,135, 0, 0, 0,156, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,138,
+ 0, 0, 0,158, 0, 0, 2,110, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,110, 0, 0, 1,137, 0, 0, 1,138, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 40, 0, 0, 1,138, 0, 0, 1,137, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,137, 0, 0, 2,110,
+ 0, 0, 0,157, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,112, 0, 0, 0, 99, 0, 0, 1, 20, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 20, 0, 0, 1, 24, 0, 0, 2,112, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,101, 0, 0, 2,112, 0, 0, 1, 24,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 24, 0, 0, 1, 20, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,112,
+ 0, 0, 0,101, 0, 0, 2,113, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,113, 0, 0, 2,114, 0, 0, 2,112, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 99, 0, 0, 2,112, 0, 0, 2,114, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,114, 0, 0, 2,113,
+ 0, 0, 0,158, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,138, 0, 0, 0, 40, 0, 0, 1, 21, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 21, 0, 0, 2,114, 0, 0, 1,138, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,158, 0, 0, 1,138, 0, 0, 2,114,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,114, 0, 0, 1, 21, 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,139,
+ 0, 0, 0,158, 0, 0, 2,113, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,113, 0, 0, 1, 25, 0, 0, 1,139, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 41, 0, 0, 1,139, 0, 0, 1, 25, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 25, 0, 0, 2,113,
+ 0, 0, 0,101, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,115, 0, 0, 0, 98, 0, 0, 1, 19, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 19, 0, 0, 1,137, 0, 0, 2,115, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,157, 0, 0, 2,115, 0, 0, 1,137,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,137, 0, 0, 1, 19, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,115,
+ 0, 0, 0,157, 0, 0, 2,116, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,116, 0, 0, 2,117, 0, 0, 2,115, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 98, 0, 0, 2,115, 0, 0, 2,117, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,117, 0, 0, 2,116,
+ 0, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,254, 0, 0, 0, 8, 0, 0, 1, 18, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 18, 0, 0, 2,117, 0, 0, 0,254, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 88, 0, 0, 0,254, 0, 0, 2,117,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,117, 0, 0, 1, 18, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,255,
+ 0, 0, 0, 88, 0, 0, 2,116, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,116, 0, 0, 1,136, 0, 0, 0,255, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 35, 0, 0, 0,255, 0, 0, 1,136, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,136, 0, 0, 2,116,
+ 0, 0, 0,157, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,118, 0, 0, 0,159, 0, 0, 1,141, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,141, 0, 0, 1, 7, 0, 0, 2,118, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 92, 0, 0, 2,118, 0, 0, 1, 7,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 7, 0, 0, 1,141, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,118,
+ 0, 0, 0, 92, 0, 0, 2,119, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,119, 0, 0, 2,120, 0, 0, 2,118, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,159, 0, 0, 2,118, 0, 0, 2,120, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,120, 0, 0, 2,119,
+ 0, 0, 0, 91, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 5, 0, 0, 0, 36, 0, 0, 1,140, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,140, 0, 0, 2,120, 0, 0, 1, 5, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 91, 0, 0, 1, 5, 0, 0, 2,120,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,120, 0, 0, 1,140, 0, 0, 0,159, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 4,
+ 0, 0, 0, 91, 0, 0, 2,119, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,119, 0, 0, 1, 6, 0, 0, 1, 4, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 10, 0, 0, 1, 4, 0, 0, 1, 6, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 6, 0, 0, 2,119,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,121, 0, 0, 0,159, 0, 0, 1,140, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,140, 0, 0, 1,142, 0, 0, 2,121, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,160, 0, 0, 2,121, 0, 0, 1,142,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,142, 0, 0, 1,140, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,121,
+ 0, 0, 0,160, 0, 0, 2,122, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,122, 0, 0, 2,123, 0, 0, 2,121, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,159, 0, 0, 2,121, 0, 0, 2,123, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,123, 0, 0, 2,122,
+ 0, 0, 0,161, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,144, 0, 0, 0, 37, 0, 0, 1,141, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1,141, 0, 0, 2,123, 0, 0, 1,144, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,161, 0, 0, 1,144, 0, 0, 2,123,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,123, 0, 0, 1,141, 0, 0, 0,159, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,145,
+ 0, 0, 0,161, 0, 0, 2,122, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,122, 0, 0, 1,143, 0, 0, 1,145, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 41, 0, 0, 1,145, 0, 0, 1,143, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,143, 0, 0, 2,122,
+ 0, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,124, 0, 0, 0,101, 0, 0, 1, 24, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 24, 0, 0, 1, 8, 0, 0, 2,124, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 93, 0, 0, 2,124, 0, 0, 1, 8,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 8, 0, 0, 1, 24, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,124,
+ 0, 0, 0, 93, 0, 0, 2,125, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,125, 0, 0, 2,126, 0, 0, 2,124, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,101, 0, 0, 2,124, 0, 0, 2,126, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,126, 0, 0, 2,125,
+ 0, 0, 0,161, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,145, 0, 0, 0, 41, 0, 0, 1, 25, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 25, 0, 0, 2,126, 0, 0, 1,145, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,161, 0, 0, 1,145, 0, 0, 2,126,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,126, 0, 0, 1, 25, 0, 0, 0,101, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,144,
+ 0, 0, 0,161, 0, 0, 2,125, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,125, 0, 0, 1, 9, 0, 0, 1,144, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 37, 0, 0, 1,144, 0, 0, 1, 9, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 9, 0, 0, 2,125,
+ 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,127, 0, 0, 0,100, 0, 0, 1, 23, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 23, 0, 0, 1,143, 0, 0, 2,127, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,160, 0, 0, 2,127, 0, 0, 1,143,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,143, 0, 0, 1, 23, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,127,
+ 0, 0, 0,160, 0, 0, 2,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,128, 0, 0, 2,129, 0, 0, 2,127, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0,100, 0, 0, 2,127, 0, 0, 2,129, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,129, 0, 0, 2,128,
+ 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 2, 0, 0, 0, 9, 0, 0, 1, 22, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 1, 22, 0, 0, 2,129, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 90, 0, 0, 1, 2, 0, 0, 2,129,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,129, 0, 0, 1, 22, 0, 0, 0,100, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 3,
+ 0, 0, 0, 90, 0, 0, 2,128, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2,128, 0, 0, 1,142, 0, 0, 1, 3, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 36, 0, 0, 1, 3, 0, 0, 1,142, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1,142, 0, 0, 2,128,
+ 0, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, 3, 68, 65, 84, 65, 0, 0,220, 0, 12,119, 64, 32, 0, 0, 0, 65, 0, 0, 5, 0,
+ 63,110,222,166, 63, 55,205, 9, 63,105,132,212, 63, 65,236,201, 63,103,153,218, 63, 54,155,119, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,103,153,218, 63, 54,155,119, 63,108,148,118, 63, 44,160,211, 63,110,222,166,
+ 63, 55,205, 9, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 36, 63, 45, 28, 36,
+ 63,110,222,166, 63, 55,205, 9, 63,108,148,118, 63, 44,160,211, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,108,148,118, 63, 44,160,211, 63,103,153,218, 63, 54,155,119, 63,102, 17, 87, 63, 43, 52,229, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 96, 81, 56, 63, 52, 55,170, 63,102, 17, 87, 63, 43, 52,229,
+ 63,103,153,218, 63, 54,155,119, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,103,153,218,
+ 63, 54,155,119, 63, 97, 75, 9, 63, 63,233, 92, 63, 96, 81, 56, 63, 52, 55,170, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,138, 63, 60, 86, 49, 63, 96, 81, 56, 63, 52, 55,170, 63, 97, 75, 9, 63, 63,233, 92,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 97, 75, 9, 63, 63,233, 92, 63,103,153,218,
+ 63, 54,155,119, 63,105,132,212, 63, 65,236,201, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 98,167,103, 63, 75, 39,168, 63, 89,153,138, 63, 82,228, 39, 63, 89,153,139, 63, 71,153,255, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,139, 63, 71,153,255, 63, 97, 75, 9, 63, 63,233, 92, 63, 98,167,103,
+ 63, 75, 39,168, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,105,132,212, 63, 65,236,201,
+ 63, 98,167,103, 63, 75, 39,168, 63, 97, 75, 9, 63, 63,233, 92, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 97, 75, 9, 63, 63,233, 92, 63, 89,153,139, 63, 71,153,255, 63, 89,153,138, 63, 60, 86, 49, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 96, 81, 56, 63, 52, 55,170, 63, 89,153,138, 63, 60, 86, 49,
+ 63, 89,153,139, 63, 49, 12, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,139,
+ 63, 49, 12, 79, 63, 95,182,205, 63, 40,228,222, 63, 96, 81, 56, 63, 52, 55,170, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,102, 17, 87, 63, 43, 52,229, 63, 96, 81, 56, 63, 52, 55,170, 63, 95,182,205, 63, 40,228,222,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 95,182,205, 63, 40,228,222, 63, 89,153,139,
+ 63, 49, 12, 79, 63, 89,153,139, 63, 37,200, 45, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 98,167,103, 63, 75, 39,168, 63,105,132,212, 63, 65,236,201, 63,109, 83,168, 63, 78, 83,207, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,109, 83,168, 63, 78, 83,207, 63,101, 85,135, 63, 88, 64,148, 63, 98,167,103,
+ 63, 75, 39,168, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,138, 63, 82,228, 39,
+ 63, 98,167,103, 63, 75, 39,168, 63,101, 85,135, 63, 88, 64,148, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,101, 85,135, 63, 88, 64,148, 63,109, 83,168, 63, 78, 83,207, 63,115, 51, 36, 63, 90, 56, 22, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,121, 18,162, 63, 78, 83,207, 63,115, 51, 36, 63, 90, 56, 22,
+ 63,109, 83,168, 63, 78, 83,207, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,109, 83,168,
+ 63, 78, 83,207, 63,115, 51, 36, 63, 67, 23,115, 63,121, 18,162, 63, 78, 83,207, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,124,225,116, 63, 65,236,202, 63,121, 18,162, 63, 78, 83,207, 63,115, 51, 36, 63, 67, 23,115,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 36, 63, 67, 23,115, 63,109, 83,168,
+ 63, 78, 83,207, 63,105,132,212, 63, 65,236,201, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,110,222,166, 63, 55,205, 9, 63,115, 51, 36, 63, 45, 28, 36, 63,119,135,163, 63, 55,205, 11, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,119,135,163, 63, 55,205, 11, 63,115, 51, 36, 63, 67, 23,115, 63,110,222,166,
+ 63, 55,205, 9, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,105,132,212, 63, 65,236,201,
+ 63,110,222,166, 63, 55,205, 9, 63,115, 51, 36, 63, 67, 23,115, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,115, 51, 36, 63, 67, 23,115, 63,119,135,163, 63, 55,205, 11, 63,124,225,116, 63, 65,236,202, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,121, 18,162, 63, 78, 83,207, 63,124,225,116, 63, 65,236,202,
+ 63,129,223,113, 63, 75, 39,170, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,129,223,113,
+ 63, 75, 39,170, 63,128,136, 98, 63, 88, 64,148, 63,121, 18,162, 63, 78, 83,207, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 36, 63, 90, 56, 22, 63,121, 18,162, 63, 78, 83,207, 63,128,136, 98, 63, 88, 64,148,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 59,136, 98, 95, 63, 88, 64,148, 60,111,184,160,
+ 63, 75, 39,170, 61, 76,203,243, 63, 82,228, 41, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 61, 76,203,243, 63, 49, 12, 82, 61, 76,203,246, 63, 60, 86, 53, 60,194,162, 31, 63, 52, 55,172, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 60,194,162, 31, 63, 52, 55,172, 60,213,239,111, 63, 40,228,223, 61, 76,203,243,
+ 63, 49, 12, 82, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,203,246, 63, 37,200, 48,
+ 61, 76,203,243, 63, 49, 12, 82, 60,213,239,111, 63, 40,228,223, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 60,213,239,111, 63, 40,228,223, 60,194,162, 31, 63, 52, 55,172, 58,169,226,120, 63, 43, 52,230, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,126,204,111, 63, 54,155,121, 63,128, 42,121, 63, 43, 52,230,
+ 63,131, 10,136, 63, 52, 55,172, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,131, 10,136,
+ 63, 52, 55,172, 63,130,141,160, 63, 63,233, 95, 63,126,204,111, 63, 54,155,121, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,124,225,116, 63, 65,236,202, 63,126,204,111, 63, 54,155,121, 63,130,141,160, 63, 63,233, 95,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 60,163,104, 11, 63, 63,233, 95, 60,194,162, 31,
+ 63, 52, 55,172, 61, 76,203,246, 63, 60, 86, 53, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 61, 76,203,244, 63, 71,154, 2, 61, 76,203,243, 63, 82,228, 41, 60,111,184,160, 63, 75, 39,170, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 60,111,184,160, 63, 75, 39,170, 60,163,104, 11, 63, 63,233, 95, 61, 76,203,244,
+ 63, 71,154, 2, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,203,246, 63, 60, 86, 53,
+ 61, 76,203,244, 63, 71,154, 2, 60,163,104, 11, 63, 63,233, 95, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,130,141,160, 63, 63,233, 95, 63,129,223,113, 63, 75, 39,170, 63,124,225,116, 63, 65,236,202, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,126,204,111, 63, 54,155,121, 63,124,225,116, 63, 65,236,202,
+ 63,119,135,163, 63, 55,205, 11, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,119,135,163,
+ 63, 55,205, 11, 63,121,209,210, 63, 44,160,212, 63,126,204,111, 63, 54,155,121, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,128, 42,121, 63, 43, 52,230, 63,126,204,111, 63, 54,155,121, 63,121,209,210, 63, 44,160,212,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,121,209,210, 63, 44,160,212, 63,119,135,163,
+ 63, 55,205, 11, 63,115, 51, 36, 63, 45, 28, 36, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,134,102, 95, 63, 94, 46, 79, 63,134,102, 95, 63,105,114, 22, 63,124,205, 52, 63, 99, 26, 58, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,124,205, 52, 63, 99, 26, 58, 63,128,136, 98, 63, 88, 64,148, 63,134,102, 95,
+ 63, 94, 46, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,203,243, 63, 82,228, 41,
+ 61, 76,203,234, 63, 94, 46, 79, 59,136, 98, 95, 63, 88, 64,148, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,128,136, 98, 63, 88, 64,148, 63,124,205, 52, 63, 99, 26, 58, 63,115, 51, 36, 63, 90, 56, 22, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,105,153, 21, 63, 99, 26, 58, 63,115, 51, 36, 63, 90, 56, 22,
+ 63,124,205, 52, 63, 99, 26, 58, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,124,205, 52,
+ 63, 99, 26, 58, 63,115, 51, 32, 63,109,154,212, 63,105,153, 21, 63, 99, 26, 58, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,138, 63,105,114, 19, 63,105,153, 21, 63, 99, 26, 58, 63,115, 51, 32, 63,109,154,212,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 32, 63,109,154,212, 63,124,205, 52,
+ 63, 99, 26, 58, 63,134,102, 95, 63,105,114, 22, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,134,102, 95, 63,116,187,242, 63, 59,153, 3, 63,128, 0, 0, 63, 89,153,136, 63,116,187,242, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,136, 63,116,187,242, 63,115, 51, 32, 63,109,154,212, 63,134,102, 95,
+ 63,116,187,242, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,134,102, 95, 63,105,114, 22,
+ 63,134,102, 95, 63,116,187,242, 63,115, 51, 32, 63,109,154,212, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,115, 51, 32, 63,109,154,212, 63, 89,153,136, 63,116,187,242, 63, 89,153,138, 63,105,114, 19, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,105,153, 21, 63, 99, 26, 58, 63, 89,153,138, 63,105,114, 19,
+ 63, 89,153,138, 63, 94, 46, 77, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,138,
+ 63, 94, 46, 77, 63,101, 85,135, 63, 88, 64,148, 63,105,153, 21, 63, 99, 26, 58, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 36, 63, 90, 56, 22, 63,105,153, 21, 63, 99, 26, 58, 63,101, 85,135, 63, 88, 64,148,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,101, 85,135, 63, 88, 64,148, 63, 89,153,138,
+ 63, 94, 46, 77, 63, 89,153,138, 63, 82,228, 39, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 75,153, 67, 63, 54,155,113, 63, 73,174, 74, 63, 65,236,193, 63, 68, 84,124, 63, 55,204,255, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 68, 84,124, 63, 55,204,255, 63, 70,158,169, 63, 44,160,200, 63, 75,153, 67,
+ 63, 54,155,113, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 77, 33,196, 63, 43, 52,221,
+ 63, 75,153, 67, 63, 54,155,113, 63, 70,158,169, 63, 44,160,200, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 70,158,169, 63, 44,160,200, 63, 68, 84,124, 63, 55,204,255, 63, 64, 0, 0, 63, 45, 28, 24, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 75,153, 67, 63, 54,155,113, 63, 77, 33,196, 63, 43, 52,221,
+ 63, 82,225,225, 63, 52, 55,165, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 82,225,225,
+ 63, 52, 55,165, 63, 81,232, 16, 63, 63,233, 89, 63, 75,153, 67, 63, 54,155,113, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 73,174, 74, 63, 65,236,193, 63, 75,153, 67, 63, 54,155,113, 63, 81,232, 16, 63, 63,233, 89,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 81,232, 16, 63, 63,233, 89, 63, 82,225,225,
+ 63, 52, 55,165, 63, 89,153,138, 63, 60, 86, 49, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 89,153,139, 63, 71,153,255, 63, 89,153,138, 63, 82,228, 39, 63, 80,139,179, 63, 75, 39,164, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 80,139,179, 63, 75, 39,164, 63, 81,232, 16, 63, 63,233, 89, 63, 89,153,139,
+ 63, 71,153,255, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,138, 63, 60, 86, 49,
+ 63, 89,153,139, 63, 71,153,255, 63, 81,232, 16, 63, 63,233, 89, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 81,232, 16, 63, 63,233, 89, 63, 80,139,179, 63, 75, 39,164, 63, 73,174, 74, 63, 65,236,193, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,139, 63, 49, 12, 79, 63, 89,153,138, 63, 60, 86, 49,
+ 63, 82,225,225, 63, 52, 55,165, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 82,225,225,
+ 63, 52, 55,165, 63, 83,124, 75, 63, 40,228,217, 63, 89,153,139, 63, 49, 12, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,139, 63, 37,200, 45, 63, 89,153,139, 63, 49, 12, 79, 63, 83,124, 75, 63, 40,228,217,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 83,124, 75, 63, 40,228,217, 63, 82,225,225,
+ 63, 52, 55,165, 63, 77, 33,196, 63, 43, 52,221, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 69,223,120, 63, 78, 83,198, 63, 73,174, 74, 63, 65,236,193, 63, 80,139,179, 63, 75, 39,164, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 80,139,179, 63, 75, 39,164, 63, 77,221,148, 63, 88, 64,140, 63, 69,223,120,
+ 63, 78, 83,198, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 63, 90, 56, 12,
+ 63, 69,223,120, 63, 78, 83,198, 63, 77,221,148, 63, 88, 64,140, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 77,221,148, 63, 88, 64,140, 63, 80,139,179, 63, 75, 39,164, 63, 89,153,138, 63, 82,228, 39, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 69,223,120, 63, 78, 83,198, 63, 64, 0, 0, 63, 90, 56, 12,
+ 63, 58, 32,136, 63, 78, 83,198, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 58, 32,136,
+ 63, 78, 83,198, 63, 64, 0, 0, 63, 67, 23,106, 63, 69,223,120, 63, 78, 83,198, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 73,174, 74, 63, 65,236,193, 63, 69,223,120, 63, 78, 83,198, 63, 64, 0, 0, 63, 67, 23,106,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 63, 67, 23,106, 63, 58, 32,136,
+ 63, 78, 83,198, 63, 54, 81,182, 63, 65,236,193, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 59,171,132, 63, 55,204,255, 63, 64, 0, 0, 63, 45, 28, 24, 63, 68, 84,124, 63, 55,204,255, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 68, 84,124, 63, 55,204,255, 63, 64, 0, 0, 63, 67, 23,106, 63, 59,171,132,
+ 63, 55,204,255, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 54, 81,182, 63, 65,236,193,
+ 63, 59,171,132, 63, 55,204,255, 63, 64, 0, 0, 63, 67, 23,106, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 64, 0, 0, 63, 67, 23,106, 63, 68, 84,124, 63, 55,204,255, 63, 73,174, 74, 63, 65,236,193, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 47,116, 77, 63, 75, 39,164, 63, 54, 81,182, 63, 65,236,193,
+ 63, 58, 32,136, 63, 78, 83,198, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 58, 32,136,
+ 63, 78, 83,198, 63, 50, 34,108, 63, 88, 64,140, 63, 47,116, 77, 63, 75, 39,164, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,118, 63, 82,228, 38, 63, 47,116, 77, 63, 75, 39,164, 63, 50, 34,108, 63, 88, 64,140,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 50, 34,108, 63, 88, 64,140, 63, 58, 32,136,
+ 63, 78, 83,198, 63, 64, 0, 0, 63, 90, 56, 12, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 45, 30, 31, 63, 52, 55,165, 63, 38,102,117, 63, 60, 86, 50, 63, 38,102,117, 63, 49, 12, 78, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,117, 63, 49, 12, 78, 63, 44,131,181, 63, 40,228,216, 63, 45, 30, 31,
+ 63, 52, 55,165, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 50,222, 60, 63, 43, 52,221,
+ 63, 45, 30, 31, 63, 52, 55,165, 63, 44,131,181, 63, 40,228,216, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 44,131,181, 63, 40,228,216, 63, 38,102,117, 63, 49, 12, 78, 63, 38,102,117, 63, 37,200, 45, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 45, 30, 31, 63, 52, 55,165, 63, 50,222, 60, 63, 43, 52,221,
+ 63, 52,102,189, 63, 54,155,113, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 52,102,189,
+ 63, 54,155,113, 63, 46, 23,240, 63, 63,233, 89, 63, 45, 30, 31, 63, 52, 55,165, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,117, 63, 60, 86, 50, 63, 45, 30, 31, 63, 52, 55,165, 63, 46, 23,240, 63, 63,233, 89,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 46, 23,240, 63, 63,233, 89, 63, 52,102,189,
+ 63, 54,155,113, 63, 54, 81,182, 63, 65,236,193, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 47,116, 77, 63, 75, 39,164, 63, 38,102,118, 63, 82,228, 38, 63, 38,102,117, 63, 71,153,255, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,117, 63, 71,153,255, 63, 46, 23,240, 63, 63,233, 89, 63, 47,116, 77,
+ 63, 75, 39,164, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 54, 81,182, 63, 65,236,193,
+ 63, 47,116, 77, 63, 75, 39,164, 63, 46, 23,240, 63, 63,233, 89, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 46, 23,240, 63, 63,233, 89, 63, 38,102,117, 63, 71,153,255, 63, 38,102,117, 63, 60, 86, 50, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 59,171,132, 63, 55,204,255, 63, 54, 81,182, 63, 65,236,193,
+ 63, 52,102,189, 63, 54,155,113, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 52,102,189,
+ 63, 54,155,113, 63, 57, 97, 87, 63, 44,160,200, 63, 59,171,132, 63, 55,204,255, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 63, 45, 28, 24, 63, 59,171,132, 63, 55,204,255, 63, 57, 97, 87, 63, 44,160,200,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 57, 97, 87, 63, 44,160,200, 63, 52,102,189,
+ 63, 54,155,113, 63, 50,222, 60, 63, 43, 52,221, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 54,101,250, 63, 99, 26, 51, 63, 38,102,118, 63,105,114, 19, 63, 38,102,118, 63, 94, 46, 77, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,118, 63, 94, 46, 77, 63, 50, 34,108, 63, 88, 64,140, 63, 54,101,250,
+ 63, 99, 26, 51, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 63, 90, 56, 12,
+ 63, 54,101,250, 63, 99, 26, 51, 63, 50, 34,108, 63, 88, 64,140, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 50, 34,108, 63, 88, 64,140, 63, 38,102,118, 63, 94, 46, 77, 63, 38,102,118, 63, 82,228, 38, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 54,101,250, 63, 99, 26, 51, 63, 64, 0, 0, 63, 90, 56, 12,
+ 63, 73,154, 6, 63, 99, 26, 51, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 73,154, 6,
+ 63, 99, 26, 51, 63, 64, 0, 0, 63,109,154,206, 63, 54,101,250, 63, 99, 26, 51, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,118, 63,105,114, 19, 63, 54,101,250, 63, 99, 26, 51, 63, 64, 0, 0, 63,109,154,206,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 63,109,154,206, 63, 73,154, 6,
+ 63, 99, 26, 51, 63, 89,153,138, 63,105,114, 19, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 89,153,136, 63,116,187,242, 63, 59,153, 3, 63,128, 0, 0, 63, 38,102,120, 63,116,187,242, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,120, 63,116,187,242, 63, 64, 0, 0, 63,109,154,206, 63, 89,153,136,
+ 63,116,187,242, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,138, 63,105,114, 19,
+ 63, 89,153,136, 63,116,187,242, 63, 64, 0, 0, 63,109,154,206, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 64, 0, 0, 63,109,154,206, 63, 38,102,120, 63,116,187,242, 63, 38,102,118, 63,105,114, 19, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,138, 63, 94, 46, 77, 63, 89,153,138, 63,105,114, 19,
+ 63, 73,154, 6, 63, 99, 26, 51, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 73,154, 6,
+ 63, 99, 26, 51, 63, 77,221,148, 63, 88, 64,140, 63, 89,153,138, 63, 94, 46, 77, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,138, 63, 82,228, 39, 63, 89,153,138, 63, 94, 46, 77, 63, 77,221,148, 63, 88, 64,140,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 77,221,148, 63, 88, 64,140, 63, 73,154, 6,
+ 63, 99, 26, 51, 63, 64, 0, 0, 63, 90, 56, 12, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62, 8, 71,167, 63, 55,205, 7, 61,229,192,170, 63, 65,236,200, 61,214,104,203, 63, 54,155,120, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,214,104,203, 63, 54,155,120, 61,254, 61,201, 63, 44,160,207, 62, 8, 71,167,
+ 63, 55,205, 7, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,173, 63, 45, 28, 27,
+ 62, 8, 71,167, 63, 55,205, 7, 61,254, 61,201, 63, 44,160,207, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 61,254, 61,201, 63, 44,160,207, 61,214,104,203, 63, 54,155,120, 61,202, 36,175, 63, 43, 52,228, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,156, 35,145, 63, 52, 55,172, 61,202, 36,175, 63, 43, 52,228,
+ 61,214,104,203, 63, 54,155,120, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,214,104,203,
+ 63, 54,155,120, 61,163,242, 32, 63, 63,233, 96, 61,156, 35,145, 63, 52, 55,172, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,203,246, 63, 60, 86, 53, 61,156, 35,145, 63, 52, 55,172, 61,163,242, 32, 63, 63,233, 96,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,163,242, 32, 63, 63,233, 96, 61,214,104,203,
+ 63, 54,155,120, 61,229,192,170, 63, 65,236,200, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 61,174,213, 17, 63, 75, 39,171, 61, 76,203,243, 63, 82,228, 41, 61, 76,203,244, 63, 71,154, 2, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,203,244, 63, 71,154, 2, 61,163,242, 32, 63, 63,233, 96, 61,174,213, 17,
+ 63, 75, 39,171, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,229,192,170, 63, 65,236,200,
+ 61,174,213, 17, 63, 75, 39,171, 61,163,242, 32, 63, 63,233, 96, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 61,163,242, 32, 63, 63,233, 96, 61, 76,203,244, 63, 71,154, 2, 61, 76,203,246, 63, 60, 86, 53, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,156, 35,145, 63, 52, 55,172, 61, 76,203,246, 63, 60, 86, 53,
+ 61, 76,203,243, 63, 49, 12, 82, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,203,243,
+ 63, 49, 12, 82, 61,151, 80, 53, 63, 40,228,223, 61,156, 35,145, 63, 52, 55,172, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 61,202, 36,175, 63, 43, 52,228, 61,156, 35,145, 63, 52, 55,172, 61,151, 80, 53, 63, 40,228,223,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,151, 80, 53, 63, 40,228,223, 61, 76,203,243,
+ 63, 49, 12, 82, 61, 76,203,246, 63, 37,200, 48, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 61,174,213, 17, 63, 75, 39,171, 61,229,192,170, 63, 65,236,200, 62, 2, 27,169, 63, 78, 83,204, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 2, 27,169, 63, 78, 83,204, 61,196, 70, 23, 63, 88, 64,147, 61,174,213, 17,
+ 63, 75, 39,171, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,203,243, 63, 82,228, 41,
+ 61,174,213, 17, 63, 75, 39,171, 61,196, 70, 23, 63, 88, 64,147, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 61,196, 70, 23, 63, 88, 64,147, 62, 2, 27,169, 63, 78, 83,204, 62, 25,153,160, 63, 90, 56, 14, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 49, 23,162, 63, 78, 83,195, 62, 25,153,160, 63, 90, 56, 14,
+ 62, 2, 27,169, 63, 78, 83,204, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 2, 27,169,
+ 63, 78, 83,204, 62, 25,153,172, 63, 67, 23,108, 62, 49, 23,162, 63, 78, 83,195, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62, 64, 82,240, 63, 65,236,183, 62, 49, 23,162, 63, 78, 83,195, 62, 25,153,172, 63, 67, 23,108,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,172, 63, 67, 23,108, 62, 2, 27,169,
+ 63, 78, 83,204, 61,229,192,170, 63, 65,236,200, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62, 8, 71,167, 63, 55,205, 7, 62, 25,153,173, 63, 45, 28, 27, 62, 42,235,173, 63, 55,204,254, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 42,235,173, 63, 55,204,254, 62, 25,153,172, 63, 67, 23,108, 62, 8, 71,167,
+ 63, 55,205, 7, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,229,192,170, 63, 65,236,200,
+ 62, 8, 71,167, 63, 55,205, 7, 62, 25,153,172, 63, 67, 23,108, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62, 25,153,172, 63, 67, 23,108, 62, 42,235,173, 63, 55,204,254, 62, 64, 82,240, 63, 65,236,183, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 49, 23,162, 63, 78, 83,195, 62, 64, 82,240, 63, 65,236,183,
+ 62, 91,200,166, 63, 75, 39,147, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 91,200,166,
+ 63, 75, 39,147, 62, 81, 16, 34, 63, 88, 64,131, 62, 49, 23,162, 63, 78, 83,195, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,160, 63, 90, 56, 14, 62, 49, 23,162, 63, 78, 83,195, 62, 81, 16, 34, 63, 88, 64,131,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 81, 16, 34, 63, 88, 64,131, 62, 91,200,166,
+ 63, 75, 39,147, 62,128, 0, 0, 63, 82,228, 13, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,128, 0, 0, 63, 49, 12, 47, 62,128, 0, 0, 63, 60, 86, 19, 62,101, 33, 92, 63, 52, 55,146, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,101, 33, 92, 63, 52, 55,146, 62,103,139, 14, 63, 40,228,199, 62,128, 0, 0,
+ 63, 49, 12, 47, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 63, 37,200, 23,
+ 62,128, 0, 0, 63, 49, 12, 47, 62,103,139, 14, 63, 40,228,199, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,103,139, 14, 63, 40,228,199, 62,101, 33, 92, 63, 52, 55,146, 62, 78, 32,230, 63, 43, 52,211, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 71,254,223, 63, 54,155,102, 62, 78, 32,230, 63, 43, 52,211,
+ 62,101, 33, 92, 63, 52, 55,146, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,101, 33, 92,
+ 63, 52, 55,146, 62, 97, 58, 23, 63, 63,233, 69, 62, 71,254,223, 63, 54,155,102, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62, 64, 82,240, 63, 65,236,183, 62, 71,254,223, 63, 54,155,102, 62, 97, 58, 23, 63, 63,233, 69,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 97, 58, 23, 63, 63,233, 69, 62,101, 33, 92,
+ 63, 52, 55,146, 62,128, 0, 0, 63, 60, 86, 19, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,128, 0, 0, 63, 71,153,228, 62,128, 0, 0, 63, 82,228, 13, 62, 91,200,166, 63, 75, 39,147, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 91,200,166, 63, 75, 39,147, 62, 97, 58, 23, 63, 63,233, 69, 62,128, 0, 0,
+ 63, 71,153,228, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 63, 60, 86, 19,
+ 62,128, 0, 0, 63, 71,153,228, 62, 97, 58, 23, 63, 63,233, 69, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62, 97, 58, 23, 63, 63,233, 69, 62, 91,200,166, 63, 75, 39,147, 62, 64, 82,240, 63, 65,236,183, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 71,254,223, 63, 54,155,102, 62, 64, 82,240, 63, 65,236,183,
+ 62, 42,235,173, 63, 55,204,254, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 42,235,173,
+ 63, 55,204,254, 62, 52, 20,105, 63, 44,160,198, 62, 71,254,223, 63, 54,155,102, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62, 78, 32,230, 63, 43, 52,211, 62, 71,254,223, 63, 54,155,102, 62, 52, 20,105, 63, 44,160,198,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 52, 20,105, 63, 44,160,198, 62, 42,235,173,
+ 63, 55,204,254, 62, 25,153,173, 63, 45, 28, 27, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,128, 0, 0, 63, 94, 46, 58, 62,128, 0, 0, 63,105,114, 8, 62, 64, 1,230, 63, 99, 26, 49, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 64, 1,230, 63, 99, 26, 49, 62, 81, 16, 34, 63, 88, 64,131, 62,128, 0, 0,
+ 63, 94, 46, 58, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 63, 82,228, 13,
+ 62,128, 0, 0, 63, 94, 46, 58, 62, 81, 16, 34, 63, 88, 64,131, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62, 81, 16, 34, 63, 88, 64,131, 62, 64, 1,230, 63, 99, 26, 49, 62, 25,153,160, 63, 90, 56, 14, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,230, 98,164, 63, 99, 26, 58, 62, 25,153,160, 63, 90, 56, 14,
+ 62, 64, 1,230, 63, 99, 26, 49, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 64, 1,230,
+ 63, 99, 26, 49, 62, 25,153,159, 63,109,154,210, 61,230, 98,164, 63, 99, 26, 58, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,203,237, 63,105,114, 22, 61,230, 98,164, 63, 99, 26, 58, 62, 25,153,159, 63,109,154,210,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,159, 63,109,154,210, 62, 64, 1,230,
+ 63, 99, 26, 49, 62,128, 0, 0, 63,105,114, 8, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,128, 0, 0, 63,116,187,232, 63, 59,153, 3, 63,128, 0, 0, 63,134,102, 95, 63,116,187,242, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,203,210, 63,116,187,242, 62, 25,153,159, 63,109,154,210, 62,128, 0, 0,
+ 63,116,187,232, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 63,105,114, 8,
+ 62,128, 0, 0, 63,116,187,232, 62, 25,153,159, 63,109,154,210, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62, 25,153,159, 63,109,154,210, 61, 76,203,210, 63,116,187,242, 61, 76,203,237, 63,105,114, 22, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,230, 98,164, 63, 99, 26, 58, 61, 76,203,237, 63,105,114, 22,
+ 61, 76,203,234, 63, 94, 46, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,203,234,
+ 63, 94, 46, 79, 61,196, 70, 23, 63, 88, 64,147, 61,230, 98,164, 63, 99, 26, 58, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,160, 63, 90, 56, 14, 61,230, 98,164, 63, 99, 26, 58, 61,196, 70, 23, 63, 88, 64,147,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,196, 70, 23, 63, 88, 64,147, 61, 76,203,234,
+ 63, 94, 46, 79, 61, 76,203,243, 63, 82,228, 41, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,170,138, 42, 63, 55,204,254, 62,159,214,136, 63, 65,236,183, 62,156, 0,145, 63, 54,155,102, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,156, 0,145, 63, 54,155,102, 62,165,245,204, 63, 44,160,198, 62,170,138, 42,
+ 63, 55,204,254, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 42, 63, 45, 28, 28,
+ 62,170,138, 42, 63, 55,204,254, 62,165,245,204, 63, 44,160,198, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,165,245,204, 63, 44,160,198, 62,156, 0,145, 63, 54,155,102, 62,152,239,141, 63, 43, 52,211, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,141,111, 82, 63, 52, 55,146, 62,152,239,141, 63, 43, 52,211,
+ 62,156, 0,145, 63, 54,155,102, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,156, 0,145,
+ 63, 54,155,102, 62,143, 98,245, 63, 63,233, 68, 62,141,111, 82, 63, 52, 55,146, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 63, 60, 86, 19, 62,141,111, 82, 63, 52, 55,146, 62,143, 98,245, 63, 63,233, 68,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,143, 98,245, 63, 63,233, 68, 62,156, 0,145,
+ 63, 54,155,102, 62,159,214,136, 63, 65,236,183, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,146, 27,173, 63, 75, 39,147, 62,128, 0, 0, 63, 82,228, 13, 62,128, 0, 0, 63, 71,153,228, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 63, 71,153,228, 62,143, 98,245, 63, 63,233, 68, 62,146, 27,173,
+ 63, 75, 39,147, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,159,214,136, 63, 65,236,183,
+ 62,146, 27,173, 63, 75, 39,147, 62,143, 98,245, 63, 63,233, 68, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,143, 98,245, 63, 63,233, 68, 62,128, 0, 0, 63, 71,153,228, 62,128, 0, 0, 63, 60, 86, 19, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,141,111, 82, 63, 52, 55,146, 62,128, 0, 0, 63, 60, 86, 19,
+ 62,128, 0, 0, 63, 49, 12, 47, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0,
+ 63, 49, 12, 47, 62,140, 58,121, 63, 40,228,199, 62,141,111, 82, 63, 52, 55,146, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,152,239,141, 63, 43, 52,211, 62,141,111, 82, 63, 52, 55,146, 62,140, 58,121, 63, 40,228,199,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,140, 58,121, 63, 40,228,199, 62,128, 0, 0,
+ 63, 49, 12, 47, 62,128, 0, 0, 63, 37,200, 23, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,146, 27,173, 63, 75, 39,147, 62,159,214,136, 63, 65,236,183, 62,167,116, 47, 63, 78, 83,195, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,167,116, 47, 63, 78, 83,195, 62,151,119,239, 63, 88, 64,131, 62,146, 27,173,
+ 63, 75, 39,147, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 63, 82,228, 13,
+ 62,146, 27,173, 63, 75, 39,147, 62,151,119,239, 63, 88, 64,131, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,151,119,239, 63, 88, 64,131, 62,167,116, 47, 63, 78, 83,195, 62,179, 51, 49, 63, 90, 56, 14, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,190,242, 44, 63, 78, 83,205, 62,179, 51, 49, 63, 90, 56, 14,
+ 62,167,116, 47, 63, 78, 83,195, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,167,116, 47,
+ 63, 78, 83,195, 62,179, 51, 42, 63, 67, 23,108, 62,190,242, 44, 63, 78, 83,205, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,198,143,214, 63, 65,236,200, 62,190,242, 44, 63, 78, 83,205, 62,179, 51, 42, 63, 67, 23,108,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 42, 63, 67, 23,108, 62,167,116, 47,
+ 63, 78, 83,195, 62,159,214,136, 63, 65,236,183, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,170,138, 42, 63, 55,204,254, 62,179, 51, 42, 63, 45, 28, 28, 62,187,220, 45, 63, 55,205, 7, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,187,220, 45, 63, 55,205, 7, 62,179, 51, 42, 63, 67, 23,108, 62,170,138, 42,
+ 63, 55,204,254, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,159,214,136, 63, 65,236,183,
+ 62,170,138, 42, 63, 55,204,254, 62,179, 51, 42, 63, 67, 23,108, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,179, 51, 42, 63, 67, 23,108, 62,187,220, 45, 63, 55,205, 7, 62,198,143,214, 63, 65,236,200, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,190,242, 44, 63, 78, 83,205, 62,198,143,214, 63, 65,236,200,
+ 62,212, 74,188, 63, 75, 39,171, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,212, 74,188,
+ 63, 75, 39,171, 62,206,238,122, 63, 88, 64,147, 62,190,242, 44, 63, 78, 83,205, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 49, 63, 90, 56, 14, 62,190,242, 44, 63, 78, 83,205, 62,206,238,122, 63, 88, 64,147,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,206,238,122, 63, 88, 64,147, 62,212, 74,188,
+ 63, 75, 39,171, 62,230,102,130, 63, 82,228, 41, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,230,102,130, 63, 49, 12, 82, 62,230,102,129, 63, 60, 86, 53, 62,216,247, 28, 63, 52, 55,172, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,216,247, 28, 63, 52, 55,172, 62,218, 43,243, 63, 40,228,223, 62,230,102,130,
+ 63, 49, 12, 82, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102,129, 63, 37,200, 48,
+ 62,230,102,130, 63, 49, 12, 82, 62,218, 43,243, 63, 40,228,223, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,218, 43,243, 63, 40,228,223, 62,216,247, 28, 63, 52, 55,172, 62,205,118,212, 63, 43, 52,228, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,202,101,206, 63, 54,155,120, 62,205,118,212, 63, 43, 52,228,
+ 62,216,247, 28, 63, 52, 55,172, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,216,247, 28,
+ 63, 52, 55,172, 62,215, 3,120, 63, 63,233, 95, 62,202,101,206, 63, 54,155,120, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,198,143,214, 63, 65,236,200, 62,202,101,206, 63, 54,155,120, 62,215, 3,120, 63, 63,233, 95,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,215, 3,120, 63, 63,233, 95, 62,216,247, 28,
+ 63, 52, 55,172, 62,230,102,129, 63, 60, 86, 53, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,230,102,130, 63, 71,154, 1, 62,230,102,130, 63, 82,228, 41, 62,212, 74,188, 63, 75, 39,171, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,212, 74,188, 63, 75, 39,171, 62,215, 3,120, 63, 63,233, 95, 62,230,102,130,
+ 63, 71,154, 1, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102,129, 63, 60, 86, 53,
+ 62,230,102,130, 63, 71,154, 1, 62,215, 3,120, 63, 63,233, 95, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,215, 3,120, 63, 63,233, 95, 62,212, 74,188, 63, 75, 39,171, 62,198,143,214, 63, 65,236,200, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,202,101,206, 63, 54,155,120, 62,198,143,214, 63, 65,236,200,
+ 62,187,220, 45, 63, 55,205, 7, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,187,220, 45,
+ 63, 55,205, 7, 62,192,112,142, 63, 44,160,207, 62,202,101,206, 63, 54,155,120, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,205,118,212, 63, 43, 52,228, 62,202,101,206, 63, 54,155,120, 62,192,112,142, 63, 44,160,207,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,192,112,142, 63, 44,160,207, 62,187,220, 45,
+ 63, 55,205, 7, 62,179, 51, 42, 63, 45, 28, 28, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,230,102,131, 63, 94, 46, 79, 62,230,102,131, 63,105,114, 22, 62,198,103, 87, 63, 99, 26, 58, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,198,103, 87, 63, 99, 26, 58, 62,206,238,122, 63, 88, 64,147, 62,230,102,131,
+ 63, 94, 46, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102,130, 63, 82,228, 41,
+ 62,230,102,131, 63, 94, 46, 79, 62,206,238,122, 63, 88, 64,147, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,206,238,122, 63, 88, 64,147, 62,198,103, 87, 63, 99, 26, 58, 62,179, 51, 49, 63, 90, 56, 14, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,159,255, 14, 63, 99, 26, 49, 62,179, 51, 49, 63, 90, 56, 14,
+ 62,198,103, 87, 63, 99, 26, 58, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,198,103, 87,
+ 63, 99, 26, 58, 62,179, 51, 49, 63,109,154,210, 62,159,255, 14, 63, 99, 26, 49, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 63,105,114, 8, 62,159,255, 14, 63, 99, 26, 49, 62,179, 51, 49, 63,109,154,210,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 49, 63,109,154,210, 62,198,103, 87,
+ 63, 99, 26, 58, 62,230,102,131, 63,105,114, 22, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,230,102,134, 63,116,187,242, 63, 59,153, 3, 63,128, 0, 0, 62,128, 0, 0, 63,116,187,232, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 63,116,187,232, 62,179, 51, 49, 63,109,154,210, 62,230,102,134,
+ 63,116,187,242, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102,131, 63,105,114, 22,
+ 62,230,102,134, 63,116,187,242, 62,179, 51, 49, 63,109,154,210, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,179, 51, 49, 63,109,154,210, 62,128, 0, 0, 63,116,187,232, 62,128, 0, 0, 63,105,114, 8, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,159,255, 14, 63, 99, 26, 49, 62,128, 0, 0, 63,105,114, 8,
+ 62,128, 0, 0, 63, 94, 46, 58, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0,
+ 63, 94, 46, 58, 62,151,119,239, 63, 88, 64,131, 62,159,255, 14, 63, 99, 26, 49, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 49, 63, 90, 56, 14, 62,159,255, 14, 63, 99, 26, 49, 62,151,119,239, 63, 88, 64,131,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,151,119,239, 63, 88, 64,131, 62,128, 0, 0,
+ 63, 94, 46, 58, 62,128, 0, 0, 63, 82,228, 13, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 8,120, 93, 63, 55,205, 11, 63, 3, 30,140, 63, 65,236,201, 63, 1, 51,145, 63, 54,155,121, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 1, 51,145, 63, 54,155,121, 63, 6, 46, 46, 63, 44,160,211, 63, 8,120, 93,
+ 63, 55,205, 11, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,220, 63, 45, 28, 35,
+ 63, 8,120, 93, 63, 55,205, 11, 63, 6, 46, 46, 63, 44,160,211, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 6, 46, 46, 63, 44,160,211, 63, 1, 51,145, 63, 54,155,121, 62,255, 86, 30, 63, 43, 52,230, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,243,213,222, 63, 52, 55,172, 62,255, 86, 30, 63, 43, 52,230,
+ 63, 1, 51,145, 63, 54,155,121, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 1, 51,145,
+ 63, 54,155,121, 62,245,201,128, 63, 63,233, 94, 62,243,213,222, 63, 52, 55,172, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102,129, 63, 60, 86, 53, 62,243,213,222, 63, 52, 55,172, 62,245,201,128, 63, 63,233, 94,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,245,201,128, 63, 63,233, 94, 63, 1, 51,145,
+ 63, 54,155,121, 63, 3, 30,140, 63, 65,236,201, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,248,130, 59, 63, 75, 39,169, 62,230,102,130, 63, 82,228, 41, 62,230,102,130, 63, 71,154, 1, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102,130, 63, 71,154, 1, 62,245,201,128, 63, 63,233, 94, 62,248,130, 59,
+ 63, 75, 39,169, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 3, 30,140, 63, 65,236,201,
+ 62,248,130, 59, 63, 75, 39,169, 62,245,201,128, 63, 63,233, 94, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,245,201,128, 63, 63,233, 94, 62,230,102,130, 63, 71,154, 1, 62,230,102,129, 63, 60, 86, 53, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,243,213,222, 63, 52, 55,172, 62,230,102,129, 63, 60, 86, 53,
+ 62,230,102,130, 63, 49, 12, 82, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102,130,
+ 63, 49, 12, 82, 62,242,161, 9, 63, 40,228,223, 62,243,213,222, 63, 52, 55,172, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,255, 86, 30, 63, 43, 52,230, 62,243,213,222, 63, 52, 55,172, 62,242,161, 9, 63, 40,228,223,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,242,161, 9, 63, 40,228,223, 62,230,102,130,
+ 63, 49, 12, 82, 62,230,102,129, 63, 37,200, 48, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,248,130, 59, 63, 75, 39,169, 63, 3, 30,140, 63, 65,236,201, 63, 6,237, 94, 63, 78, 83,207, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 6,237, 94, 63, 78, 83,207, 62,253,222,118, 63, 88, 64,148, 62,248,130, 59,
+ 63, 75, 39,169, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102,130, 63, 82,228, 41,
+ 62,248,130, 59, 63, 75, 39,169, 62,253,222,118, 63, 88, 64,148, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,253,222,118, 63, 88, 64,148, 63, 6,237, 94, 63, 78, 83,207, 63, 12,204,220, 63, 90, 56, 22, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 18,172, 88, 63, 78, 83,207, 63, 12,204,220, 63, 90, 56, 22,
+ 63, 6,237, 94, 63, 78, 83,207, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 6,237, 94,
+ 63, 78, 83,207, 63, 12,204,220, 63, 67, 23,115, 63, 18,172, 88, 63, 78, 83,207, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 22,123, 44, 63, 65,236,201, 63, 18,172, 88, 63, 78, 83,207, 63, 12,204,220, 63, 67, 23,115,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,220, 63, 67, 23,115, 63, 6,237, 94,
+ 63, 78, 83,207, 63, 3, 30,140, 63, 65,236,201, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 8,120, 93, 63, 55,205, 11, 63, 12,204,220, 63, 45, 28, 35, 63, 17, 33, 91, 63, 55,205, 9, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 17, 33, 91, 63, 55,205, 9, 63, 12,204,220, 63, 67, 23,115, 63, 8,120, 93,
+ 63, 55,205, 11, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 3, 30,140, 63, 65,236,201,
+ 63, 8,120, 93, 63, 55,205, 11, 63, 12,204,220, 63, 67, 23,115, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 12,204,220, 63, 67, 23,115, 63, 17, 33, 91, 63, 55,205, 9, 63, 22,123, 44, 63, 65,236,201, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 18,172, 88, 63, 78, 83,207, 63, 22,123, 44, 63, 65,236,201,
+ 63, 29, 88,153, 63, 75, 39,167, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 29, 88,153,
+ 63, 75, 39,167, 63, 26,170,121, 63, 88, 64,147, 63, 18,172, 88, 63, 78, 83,207, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,220, 63, 90, 56, 22, 63, 18,172, 88, 63, 78, 83,207, 63, 26,170,121, 63, 88, 64,147,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 26,170,121, 63, 88, 64,147, 63, 29, 88,153,
+ 63, 75, 39,167, 63, 38,102,118, 63, 82,228, 38, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 38,102,117, 63, 49, 12, 78, 63, 38,102,117, 63, 60, 86, 50, 63, 31,174,200, 63, 52, 55,169, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 31,174,200, 63, 52, 55,169, 63, 32, 73, 51, 63, 40,228,221, 63, 38,102,117,
+ 63, 49, 12, 78, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,117, 63, 37,200, 45,
+ 63, 38,102,117, 63, 49, 12, 78, 63, 32, 73, 51, 63, 40,228,221, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 32, 73, 51, 63, 40,228,221, 63, 31,174,200, 63, 52, 55,169, 63, 25,238,169, 63, 43, 52,229, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 24,102, 39, 63, 54,155,119, 63, 25,238,169, 63, 43, 52,229,
+ 63, 31,174,200, 63, 52, 55,169, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 31,174,200,
+ 63, 52, 55,169, 63, 30,180,246, 63, 63,233, 92, 63, 24,102, 39, 63, 54,155,119, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 22,123, 44, 63, 65,236,201, 63, 24,102, 39, 63, 54,155,119, 63, 30,180,246, 63, 63,233, 92,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 30,180,246, 63, 63,233, 92, 63, 31,174,200,
+ 63, 52, 55,169, 63, 38,102,117, 63, 60, 86, 50, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 38,102,117, 63, 71,153,255, 63, 38,102,118, 63, 82,228, 38, 63, 29, 88,153, 63, 75, 39,167, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 29, 88,153, 63, 75, 39,167, 63, 30,180,246, 63, 63,233, 92, 63, 38,102,117,
+ 63, 71,153,255, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,117, 63, 60, 86, 50,
+ 63, 38,102,117, 63, 71,153,255, 63, 30,180,246, 63, 63,233, 92, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 30,180,246, 63, 63,233, 92, 63, 29, 88,153, 63, 75, 39,167, 63, 22,123, 44, 63, 65,236,201, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 24,102, 39, 63, 54,155,119, 63, 22,123, 44, 63, 65,236,201,
+ 63, 17, 33, 91, 63, 55,205, 9, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 17, 33, 91,
+ 63, 55,205, 9, 63, 19,107,138, 63, 44,160,211, 63, 24,102, 39, 63, 54,155,119, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 25,238,169, 63, 43, 52,229, 63, 24,102, 39, 63, 54,155,119, 63, 19,107,138, 63, 44,160,211,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 19,107,138, 63, 44,160,211, 63, 17, 33, 91,
+ 63, 55,205, 9, 63, 12,204,220, 63, 45, 28, 35, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 38,102,118, 63, 94, 46, 77, 63, 38,102,118, 63,105,114, 19, 63, 22,102,235, 63, 99, 26, 59, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 22,102,235, 63, 99, 26, 59, 63, 26,170,121, 63, 88, 64,147, 63, 38,102,118,
+ 63, 94, 46, 77, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,118, 63, 82,228, 38,
+ 63, 38,102,118, 63, 94, 46, 77, 63, 26,170,121, 63, 88, 64,147, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 26,170,121, 63, 88, 64,147, 63, 22,102,235, 63, 99, 26, 59, 63, 12,204,220, 63, 90, 56, 22, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 3, 50,204, 63, 99, 26, 58, 63, 12,204,220, 63, 90, 56, 22,
+ 63, 22,102,235, 63, 99, 26, 59, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 22,102,235,
+ 63, 99, 26, 59, 63, 12,204,224, 63,109,154,212, 63, 3, 50,204, 63, 99, 26, 58, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102,131, 63,105,114, 22, 63, 3, 50,204, 63, 99, 26, 58, 63, 12,204,224, 63,109,154,212,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,224, 63,109,154,212, 63, 22,102,235,
+ 63, 99, 26, 59, 63, 38,102,118, 63,105,114, 19, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 38,102,120, 63,116,187,242, 63, 59,153, 3, 63,128, 0, 0, 62,230,102,134, 63,116,187,242, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102,134, 63,116,187,242, 63, 12,204,224, 63,109,154,212, 63, 38,102,120,
+ 63,116,187,242, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,118, 63,105,114, 19,
+ 63, 38,102,120, 63,116,187,242, 63, 12,204,224, 63,109,154,212, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 12,204,224, 63,109,154,212, 62,230,102,134, 63,116,187,242, 62,230,102,131, 63,105,114, 22, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 3, 50,204, 63, 99, 26, 58, 62,230,102,131, 63,105,114, 22,
+ 62,230,102,131, 63, 94, 46, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102,131,
+ 63, 94, 46, 79, 62,253,222,118, 63, 88, 64,148, 63, 3, 50,204, 63, 99, 26, 58, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,220, 63, 90, 56, 22, 63, 3, 50,204, 63, 99, 26, 58, 62,253,222,118, 63, 88, 64,148,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,253,222,118, 63, 88, 64,148, 62,230,102,131,
+ 63, 94, 46, 79, 62,230,102,130, 63, 82,228, 41, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 76,233,213, 63, 21, 48, 35, 63, 70,235,176, 63, 22,209,226, 63, 73,234, 80, 63, 11,111,146, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 73,234, 80, 63, 11,111,146, 63, 79,200, 1, 63, 9,152, 94, 63, 76,233,213,
+ 63, 21, 48, 35, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 82,215, 19, 63, 19, 29,252,
+ 63, 76,233,213, 63, 21, 48, 35, 63, 79,200, 1, 63, 9,152, 94, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 79,200, 1, 63, 9,152, 94, 63, 73,234, 80, 63, 11,111,146, 63, 76,204,193, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 76,233,213, 63, 21, 48, 35, 63, 82,215, 19, 63, 19, 29,252,
+ 63, 80, 41,220, 63, 31, 60,105, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 80, 41,220,
+ 63, 31, 60,105, 63, 73,219,164, 63, 33, 23,173, 63, 76,233,213, 63, 21, 48, 35, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 70,235,176, 63, 22,209,226, 63, 76,233,213, 63, 21, 48, 35, 63, 73,219,164, 63, 33, 23,173,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 73,219,164, 63, 33, 23,173, 63, 80, 41,220,
+ 63, 31, 60,105, 63, 77, 33,196, 63, 43, 52,221, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 70,158,169, 63, 44,160,200, 63, 64, 0, 0, 63, 45, 28, 24, 63, 67,171, 5, 63, 34, 17,216, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 67,171, 5, 63, 34, 17,216, 63, 73,219,164, 63, 33, 23,173, 63, 70,158,169,
+ 63, 44,160,200, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 77, 33,196, 63, 43, 52,221,
+ 63, 70,158,169, 63, 44,160,200, 63, 73,219,164, 63, 33, 23,173, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 73,219,164, 63, 33, 23,173, 63, 67,171, 5, 63, 34, 17,216, 63, 70,235,176, 63, 22,209,226, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 83,124, 75, 63, 40,228,217, 63, 77, 33,196, 63, 43, 52,221,
+ 63, 80, 41,220, 63, 31, 60,105, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 80, 41,220,
+ 63, 31, 60,105, 63, 86, 20,218, 63, 28,140,143, 63, 83,124, 75, 63, 40,228,217, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,139, 63, 37,200, 45, 63, 83,124, 75, 63, 40,228,217, 63, 86, 20,218, 63, 28,140,143,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 86, 20,218, 63, 28,140,143, 63, 80, 41,220,
+ 63, 31, 60,105, 63, 82,215, 19, 63, 19, 29,252, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 64, 0, 0, 63, 23, 32,182, 63, 70,235,176, 63, 22,209,226, 63, 67,171, 5, 63, 34, 17,216, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 67,171, 5, 63, 34, 17,216, 63, 60, 84,251, 63, 34, 17,216, 63, 64, 0, 0,
+ 63, 23, 32,182, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 57, 20, 80, 63, 22,209,226,
+ 63, 64, 0, 0, 63, 23, 32,182, 63, 60, 84,251, 63, 34, 17,216, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 60, 84,251, 63, 34, 17,216, 63, 67,171, 5, 63, 34, 17,216, 63, 64, 0, 0, 63, 45, 28, 24, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 63, 23, 32,182, 63, 57, 20, 80, 63, 22,209,226,
+ 63, 60,156,169, 63, 11,116, 96, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 60,156,169,
+ 63, 11,116, 96, 63, 67, 99, 87, 63, 11,116, 96, 63, 64, 0, 0, 63, 23, 32,182, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 70,235,176, 63, 22,209,226, 63, 64, 0, 0, 63, 23, 32,182, 63, 67, 99, 87, 63, 11,116, 96,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 67, 99, 87, 63, 11,116, 96, 63, 60,156,169,
+ 63, 11,116, 96, 63, 64, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 70,102, 96, 63, 0, 1,244, 63, 76,204,193, 63, 0, 0, 0, 63, 73,234, 80, 63, 11,111,146, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 73,234, 80, 63, 11,111,146, 63, 67, 99, 87, 63, 11,116, 96, 63, 70,102, 96,
+ 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 63, 0, 0, 0,
+ 63, 70,102, 96, 63, 0, 1,244, 63, 67, 99, 87, 63, 11,116, 96, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 67, 99, 87, 63, 11,116, 96, 63, 73,234, 80, 63, 11,111,146, 63, 70,235,176, 63, 22,209,226, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 57,153,160, 63, 0, 1,244, 63, 64, 0, 0, 63, 0, 0, 0,
+ 63, 60,156,169, 63, 11,116, 96, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 60,156,169,
+ 63, 11,116, 96, 63, 54, 21,176, 63, 11,111,146, 63, 57,153,160, 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 51, 51, 63, 63, 0, 0, 0, 63, 57,153,160, 63, 0, 1,244, 63, 54, 21,176, 63, 11,111,146,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 54, 21,176, 63, 11,111,146, 63, 60,156,169,
+ 63, 11,116, 96, 63, 57, 20, 80, 63, 22,209,226, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 64, 0, 0, 62,217, 58, 93, 63, 57, 61,144, 62,217,196, 19, 63, 60,123, 85, 62,198,230,253, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 60,123, 85, 62,198,230,253, 63, 67,132,171, 62,198,230,253, 63, 64, 0, 0,
+ 62,217, 58, 93, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 70,194,112, 62,217,196, 19,
+ 63, 64, 0, 0, 62,217, 58, 93, 63, 67,132,171, 62,198,230,253, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 67,132,171, 62,198,230,253, 63, 60,123, 85, 62,198,230,253, 63, 64, 0, 0, 62,180,111,211, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 62,217, 58, 93, 63, 70,194,112, 62,217,196, 19,
+ 63, 67, 84,125, 62,236,211, 42, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 67, 84,125,
+ 62,236,211, 42, 63, 60,171,131, 62,236,211, 42, 63, 64, 0, 0, 62,217, 58, 93, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 57, 61,144, 62,217,196, 19, 63, 64, 0, 0, 62,217, 58, 93, 63, 60,171,131, 62,236,211, 42,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 60,171,131, 62,236,211, 42, 63, 67, 84,125,
+ 62,236,211, 42, 63, 64, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 57,153,160, 63, 0, 1,244, 63, 51, 51, 63, 63, 0, 0, 0, 63, 54, 46,128, 62,236,207, 75, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 54, 46,128, 62,236,207, 75, 63, 60,171,131, 62,236,211, 42, 63, 57,153,160,
+ 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 63, 0, 0, 0,
+ 63, 57,153,160, 63, 0, 1,244, 63, 60,171,131, 62,236,211, 42, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 60,171,131, 62,236,211, 42, 63, 54, 46,128, 62,236,207, 75, 63, 57, 61,144, 62,217,196, 19, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 70,102, 96, 63, 0, 1,244, 63, 64, 0, 0, 63, 0, 0, 0,
+ 63, 67, 84,125, 62,236,211, 42, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 67, 84,125,
+ 62,236,211, 42, 63, 73,209,128, 62,236,207, 75, 63, 70,102, 96, 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 76,204,193, 63, 0, 0, 0, 63, 70,102, 96, 63, 0, 1,244, 63, 73,209,128, 62,236,207, 75,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 73,209,128, 62,236,207, 75, 63, 67, 84,125,
+ 62,236,211, 42, 63, 70,194,112, 62,217,196, 19, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 51, 22, 43, 63, 21, 48, 35, 63, 45, 40,237, 63, 19, 29,252, 63, 48, 55,255, 63, 9,152, 94, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 48, 55,255, 63, 9,152, 94, 63, 54, 21,176, 63, 11,111,146, 63, 51, 22, 43,
+ 63, 21, 48, 35, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 57, 20, 80, 63, 22,209,226,
+ 63, 51, 22, 43, 63, 21, 48, 35, 63, 54, 21,176, 63, 11,111,146, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 54, 21,176, 63, 11,111,146, 63, 48, 55,255, 63, 9,152, 94, 63, 51, 51, 63, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 51, 22, 43, 63, 21, 48, 35, 63, 57, 20, 80, 63, 22,209,226,
+ 63, 54, 36, 91, 63, 33, 23,173, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 54, 36, 91,
+ 63, 33, 23,173, 63, 47,214, 36, 63, 31, 60,105, 63, 51, 22, 43, 63, 21, 48, 35, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 45, 40,237, 63, 19, 29,252, 63, 51, 22, 43, 63, 21, 48, 35, 63, 47,214, 36, 63, 31, 60,105,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 47,214, 36, 63, 31, 60,105, 63, 54, 36, 91,
+ 63, 33, 23,173, 63, 50,222, 60, 63, 43, 52,221, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 44,131,181, 63, 40,228,216, 63, 38,102,117, 63, 37,200, 45, 63, 41,235, 38, 63, 28,140,141, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 41,235, 38, 63, 28,140,141, 63, 47,214, 36, 63, 31, 60,105, 63, 44,131,181,
+ 63, 40,228,216, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 50,222, 60, 63, 43, 52,221,
+ 63, 44,131,181, 63, 40,228,216, 63, 47,214, 36, 63, 31, 60,105, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 47,214, 36, 63, 31, 60,105, 63, 41,235, 38, 63, 28,140,141, 63, 45, 40,237, 63, 19, 29,252, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 57, 97, 87, 63, 44,160,200, 63, 50,222, 60, 63, 43, 52,221,
+ 63, 54, 36, 91, 63, 33, 23,173, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 54, 36, 91,
+ 63, 33, 23,173, 63, 60, 84,251, 63, 34, 17,216, 63, 57, 97, 87, 63, 44,160,200, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 63, 45, 28, 24, 63, 57, 97, 87, 63, 44,160,200, 63, 60, 84,251, 63, 34, 17,216,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 60, 84,251, 63, 34, 17,216, 63, 54, 36, 91,
+ 63, 33, 23,173, 63, 57, 20, 80, 63, 22,209,226, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,128, 14,134, 63, 21, 48, 39, 63,122, 30,227, 63, 22,209,233, 63,125, 29,138, 63, 11,111,150, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,125, 29,138, 63, 11,111,150, 63,129,125,159, 63, 9,152, 94, 63,128, 14,134,
+ 63, 21, 48, 39, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 60,193, 73,174, 63, 19, 29,253,
+ 57,232, 92,209, 63, 21, 48, 39, 60, 62,207,114, 63, 9,152, 94, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,129,125,159, 63, 9,152, 94, 63,125, 29,138, 63, 11,111,150, 63,128, 0, 0, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 57,232, 92,209, 63, 21, 48, 39, 60,193, 73,174, 63, 19, 29,253,
+ 60, 87, 67,214, 63, 31, 60,110, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,129,174,136,
+ 63, 31, 60,110, 63,125, 14,213, 63, 33, 23,180, 63,128, 14,134, 63, 21, 48, 39, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,122, 30,227, 63, 22,209,233, 63,128, 14,134, 63, 21, 48, 39, 63,125, 14,213, 63, 33, 23,180,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,125, 14,213, 63, 33, 23,180, 63,129,174,136,
+ 63, 31, 60,110, 63,128, 42,121, 63, 43, 52,230, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,121,209,210, 63, 44,160,212, 63,115, 51, 36, 63, 45, 28, 36, 63,118,222, 49, 63, 34, 17,226, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,118,222, 49, 63, 34, 17,226, 63,125, 14,213, 63, 33, 23,180, 63,121,209,210,
+ 63, 44,160,212, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,128, 42,121, 63, 43, 52,230,
+ 63,121,209,210, 63, 44,160,212, 63,125, 14,213, 63, 33, 23,180, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,125, 14,213, 63, 33, 23,180, 63,118,222, 49, 63, 34, 17,226, 63,122, 30,227, 63, 22,209,233, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 60,213,239,111, 63, 40,228,223, 58,169,226,120, 63, 43, 52,230,
+ 60, 87, 67,214, 63, 31, 60,110, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 60, 87, 67,214,
+ 63, 31, 60,110, 61, 20,129, 13, 63, 28,140,143, 60,213,239,111, 63, 40,228,223, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,203,246, 63, 37,200, 48, 60,213,239,111, 63, 40,228,223, 61, 20,129, 13, 63, 28,140,143,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 20,129, 13, 63, 28,140,143, 60, 87, 67,214,
+ 63, 31, 60,110, 60,193, 73,174, 63, 19, 29,253, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,115, 51, 44, 63, 23, 32,188, 63,122, 30,227, 63, 22,209,233, 63,118,222, 49, 63, 34, 17,226, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,118,222, 49, 63, 34, 17,226, 63,111,136, 31, 63, 34, 17,225, 63,115, 51, 44,
+ 63, 23, 32,188, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,108, 71,116, 63, 22,209,232,
+ 63,115, 51, 44, 63, 23, 32,188, 63,111,136, 31, 63, 34, 17,225, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,111,136, 31, 63, 34, 17,225, 63,118,222, 49, 63, 34, 17,226, 63,115, 51, 36, 63, 45, 28, 36, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 44, 63, 23, 32,188, 63,108, 71,116, 63, 22,209,232,
+ 63,111,207,213, 63, 11,116,100, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,111,207,213,
+ 63, 11,116,100, 63,118,150,138, 63, 11,116,101, 63,115, 51, 44, 63, 23, 32,188, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,122, 30,227, 63, 22,209,233, 63,115, 51, 44, 63, 23, 32,188, 63,118,150,138, 63, 11,116,101,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,118,150,138, 63, 11,116,101, 63,111,207,213,
+ 63, 11,116,100, 63,115, 51, 51, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,121,153,154, 63, 0, 1,244, 63,128, 0, 0, 63, 0, 0, 0, 63,125, 29,138, 63, 11,111,150, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,125, 29,138, 63, 11,111,150, 63,118,150,138, 63, 11,116,101, 63,121,153,154,
+ 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 51, 63, 0, 0, 0,
+ 63,121,153,154, 63, 0, 1,244, 63,118,150,138, 63, 11,116,101, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,118,150,138, 63, 11,116,101, 63,125, 29,138, 63, 11,111,150, 63,122, 30,227, 63, 22,209,233, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,108,204,205, 63, 0, 1,244, 63,115, 51, 51, 63, 0, 0, 0,
+ 63,111,207,213, 63, 11,116,100, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,111,207,213,
+ 63, 11,116,100, 63,105, 72,213, 63, 11,111,149, 63,108,204,205, 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,102,102,101, 63, 0, 0, 0, 63,108,204,205, 63, 0, 1,244, 63,105, 72,213, 63, 11,111,149,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,105, 72,213, 63, 11,111,149, 63,111,207,213,
+ 63, 11,116,100, 63,108, 71,116, 63, 22,209,232, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,115, 51, 58, 62,217, 58, 73, 63,108,112,192, 62,217,196, 4, 63,111,174,139, 62,198,230,223, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,111,174,139, 62,198,230,223, 63,118,183,239, 62,198,230,227, 63,115, 51, 58,
+ 62,217, 58, 73, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,121,245,179, 62,217,196, 6,
+ 63,115, 51, 58, 62,217, 58, 73, 63,118,183,239, 62,198,230,227, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,118,183,239, 62,198,230,227, 63,111,174,139, 62,198,230,223, 63,115, 51, 65, 62,180,111,160, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 58, 62,217, 58, 73, 63,121,245,179, 62,217,196, 6,
+ 63,118,135,185, 62,236,211, 30, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,118,135,185,
+ 62,236,211, 30, 63,111,222,180, 62,236,211, 30, 63,115, 51, 58, 62,217, 58, 73, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,108,112,192, 62,217,196, 4, 63,115, 51, 58, 62,217, 58, 73, 63,111,222,180, 62,236,211, 30,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,111,222,180, 62,236,211, 30, 63,118,135,185,
+ 62,236,211, 30, 63,115, 51, 51, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,108,204,205, 63, 0, 1,244, 63,102,102,101, 63, 0, 0, 0, 63,105, 97,170, 62,236,207, 65, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,105, 97,170, 62,236,207, 65, 63,111,222,180, 62,236,211, 30, 63,108,204,205,
+ 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 51, 63, 0, 0, 0,
+ 63,108,204,205, 63, 0, 1,244, 63,111,222,180, 62,236,211, 30, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,111,222,180, 62,236,211, 30, 63,105, 97,170, 62,236,207, 65, 63,108,112,192, 62,217,196, 4, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,121,153,154, 63, 0, 1,244, 63,115, 51, 51, 63, 0, 0, 0,
+ 63,118,135,185, 62,236,211, 30, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,118,135,185,
+ 62,236,211, 30, 63,125, 4,194, 62,236,207, 67, 63,121,153,154, 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,128, 0, 0, 63, 0, 0, 0, 63,121,153,154, 63, 0, 1,244, 63,125, 4,194, 62,236,207, 67,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,125, 4,194, 62,236,207, 67, 63,118,135,185,
+ 62,236,211, 30, 63,121,245,179, 62,217,196, 6, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,102, 73, 76, 63, 21, 48, 38, 63, 96, 92, 11, 63, 19, 29,253, 63, 99,107, 33, 63, 9,152, 94, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 99,107, 33, 63, 9,152, 94, 63,105, 72,213, 63, 11,111,149, 63,102, 73, 76,
+ 63, 21, 48, 38, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,108, 71,116, 63, 22,209,232,
+ 63,102, 73, 76, 63, 21, 48, 38, 63,105, 72,213, 63, 11,111,149, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,105, 72,213, 63, 11,111,149, 63, 99,107, 33, 63, 9,152, 94, 63,102,102,101, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,102, 73, 76, 63, 21, 48, 38, 63,108, 71,116, 63, 22,209,232,
+ 63,105, 87,124, 63, 33, 23,180, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,105, 87,124,
+ 63, 33, 23,180, 63, 99, 9, 65, 63, 31, 60,109, 63,102, 73, 76, 63, 21, 48, 38, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 96, 92, 11, 63, 19, 29,253, 63,102, 73, 76, 63, 21, 48, 38, 63, 99, 9, 65, 63, 31, 60,109,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 99, 9, 65, 63, 31, 60,109, 63,105, 87,124,
+ 63, 33, 23,180, 63,102, 17, 87, 63, 43, 52,229, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 95,182,205, 63, 40,228,222, 63, 89,153,139, 63, 37,200, 45, 63, 93, 30, 63, 63, 28,140,143, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 93, 30, 63, 63, 28,140,143, 63, 99, 9, 65, 63, 31, 60,109, 63, 95,182,205,
+ 63, 40,228,222, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,102, 17, 87, 63, 43, 52,229,
+ 63, 95,182,205, 63, 40,228,222, 63, 99, 9, 65, 63, 31, 60,109, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 99, 9, 65, 63, 31, 60,109, 63, 93, 30, 63, 63, 28,140,143, 63, 96, 92, 11, 63, 19, 29,253, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,108,148,118, 63, 44,160,211, 63,102, 17, 87, 63, 43, 52,229,
+ 63,105, 87,124, 63, 33, 23,180, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,105, 87,124,
+ 63, 33, 23,180, 63,111,136, 31, 63, 34, 17,225, 63,108,148,118, 63, 44,160,211, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 36, 63, 45, 28, 36, 63,108,148,118, 63, 44,160,211, 63,111,136, 31, 63, 34, 17,225,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,111,136, 31, 63, 34, 17,225, 63,105, 87,124,
+ 63, 33, 23,180, 63,108, 71,116, 63, 22,209,232, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62, 77, 65, 65, 63, 21, 48, 32, 62, 53, 72,152, 63, 22,209,229, 62, 65, 67, 47, 63, 11,111,147, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 65, 67, 47, 63, 11,111,147, 62, 88,185,255, 63, 9,152, 90, 62, 77, 65, 65,
+ 63, 21, 48, 32, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,100,246, 64, 63, 19, 29,246,
+ 62, 77, 65, 65, 63, 21, 48, 32, 62, 88,185,255, 63, 9,152, 90, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62, 88,185,255, 63, 9,152, 90, 62, 65, 67, 47, 63, 11,111,147, 62, 76,204,254, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 77, 65, 65, 63, 21, 48, 32, 62,100,246, 64, 63, 19, 29,246,
+ 62, 90, 65, 89, 63, 31, 60, 94, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 90, 65, 89,
+ 63, 31, 60, 94, 62, 65, 8,107, 63, 33, 23,170, 62, 77, 65, 65, 63, 21, 48, 32, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62, 53, 72,152, 63, 22,209,229, 62, 77, 65, 65, 63, 21, 48, 32, 62, 65, 8,107, 63, 33, 23,170,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 65, 8,107, 63, 33, 23,170, 62, 90, 65, 89,
+ 63, 31, 60, 94, 62, 78, 32,230, 63, 43, 52,211, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62, 52, 20,105, 63, 44,160,198, 62, 25,153,173, 63, 45, 28, 27, 62, 40, 69,216, 63, 34, 17,220, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 40, 69,216, 63, 34, 17,220, 62, 65, 8,107, 63, 33, 23,170, 62, 52, 20,105,
+ 63, 44,160,198, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 78, 32,230, 63, 43, 52,211,
+ 62, 52, 20,105, 63, 44,160,198, 62, 65, 8,107, 63, 33, 23,170, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62, 65, 8,107, 63, 33, 23,170, 62, 40, 69,216, 63, 34, 17,220, 62, 53, 72,152, 63, 22,209,229, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,103,139, 14, 63, 40,228,199, 62, 78, 32,230, 63, 43, 52,211,
+ 62, 90, 65, 89, 63, 31, 60, 94, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 90, 65, 89,
+ 63, 31, 60, 94, 62,113,237, 83, 63, 28,140,130, 62,103,139, 14, 63, 40,228,199, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 63, 37,200, 23, 62,103,139, 14, 63, 40,228,199, 62,113,237, 83, 63, 28,140,130,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,113,237, 83, 63, 28,140,130, 62, 90, 65, 89,
+ 63, 31, 60, 94, 62,100,246, 64, 63, 19, 29,246, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62, 25,153,180, 63, 23, 32,185, 62, 53, 72,152, 63, 22,209,229, 62, 40, 69,216, 63, 34, 17,220, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 40, 69,216, 63, 34, 17,220, 62, 10,237,133, 63, 34, 17,219, 62, 25,153,180,
+ 63, 23, 32,185, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,251,213,147, 63, 22,209,228,
+ 62, 25,153,180, 63, 23, 32,185, 62, 10,237,133, 63, 34, 17,219, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62, 10,237,133, 63, 34, 17,219, 62, 40, 69,216, 63, 34, 17,220, 62, 25,153,173, 63, 45, 28, 27, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,180, 63, 23, 32,185, 61,251,213,147, 63, 22,209,228,
+ 62, 12, 12, 67, 63, 11,116, 98, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 12, 12, 67,
+ 63, 11,116, 98, 62, 39, 39, 34, 63, 11,116, 98, 62, 25,153,180, 63, 23, 32,185, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62, 53, 72,152, 63, 22,209,229, 62, 25,153,180, 63, 23, 32,185, 62, 39, 39, 34, 63, 11,116, 98,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 39, 39, 34, 63, 11,116, 98, 62, 12, 12, 67,
+ 63, 11,116, 98, 62, 25,153,181, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62, 51, 51, 92, 63, 0, 1,244, 62, 76,204,254, 63, 0, 0, 0, 62, 65, 67, 47, 63, 11,111,147, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 65, 67, 47, 63, 11,111,147, 62, 39, 39, 34, 63, 11,116, 98, 62, 51, 51, 92,
+ 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,181, 63, 0, 0, 0,
+ 62, 51, 51, 92, 63, 0, 1,244, 62, 39, 39, 34, 63, 11,116, 98, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62, 39, 39, 34, 63, 11,116, 98, 62, 65, 67, 47, 63, 11,111,147, 62, 53, 72,152, 63, 22,209,229, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 0, 0, 8, 63, 0, 1,244, 62, 25,153,181, 63, 0, 0, 0,
+ 62, 12, 12, 67, 63, 11,116, 98, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 12, 12, 67,
+ 63, 11,116, 98, 61,227,224,109, 63, 11,111,147, 62, 0, 0, 8, 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 61,204,204,215, 63, 0, 0, 0, 62, 0, 0, 8, 63, 0, 1,244, 61,227,224,109, 63, 11,111,147,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,227,224,109, 63, 11,111,147, 62, 12, 12, 67,
+ 63, 11,116, 98, 61,251,213,147, 63, 22,209,228, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62, 25,153,196, 62,217, 58, 73, 61,253, 31,171, 62,217,196, 6, 62, 11,135, 1, 62,198,230,228, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 11,135, 1, 62,198,230,228, 62, 39,172,153, 62,198,230,230, 62, 25,153,196,
+ 62,217, 58, 73, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 52,163,179, 62,217,196, 7,
+ 62, 25,153,196, 62,217, 58, 73, 62, 39,172,153, 62,198,230,230, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62, 39,172,153, 62,198,230,230, 62, 11,135, 1, 62,198,230,228, 62, 25,153,214, 62,180,111,165, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,196, 62,217, 58, 73, 62, 52,163,179, 62,217,196, 7,
+ 62, 38,235,202, 62,236,211, 33, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 38,235,202,
+ 62,236,211, 33, 62, 12, 71,173, 62,236,211, 31, 62, 25,153,196, 62,217, 58, 73, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 61,253, 31,171, 62,217,196, 6, 62, 25,153,196, 62,217, 58, 73, 62, 12, 71,173, 62,236,211, 31,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 12, 71,173, 62,236,211, 31, 62, 38,235,202,
+ 62,236,211, 33, 62, 25,153,181, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62, 0, 0, 8, 63, 0, 1,244, 61,204,204,215, 63, 0, 0, 0, 61,228,166,251, 62,236,207, 67, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,228,166,251, 62,236,207, 67, 62, 12, 71,173, 62,236,211, 31, 62, 0, 0, 8,
+ 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,181, 63, 0, 0, 0,
+ 62, 0, 0, 8, 63, 0, 1,244, 62, 12, 71,173, 62,236,211, 31, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62, 12, 71,173, 62,236,211, 31, 61,228,166,251, 62,236,207, 67, 61,253, 31,171, 62,217,196, 6, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 51, 51, 92, 63, 0, 1,244, 62, 25,153,181, 63, 0, 0, 0,
+ 62, 38,235,202, 62,236,211, 33, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 38,235,202,
+ 62,236,211, 33, 62, 64,223,251, 62,236,207, 67, 62, 51, 51, 92, 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62, 76,204,254, 63, 0, 0, 0, 62, 51, 51, 92, 63, 0, 1,244, 62, 64,223,251, 62,236,207, 67,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 64,223,251, 62,236,207, 67, 62, 38,235,202,
+ 62,236,211, 33, 62, 52,163,179, 62,217,196, 7, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 61,203,228, 42, 63, 21, 48, 37, 61,156,122, 1, 63, 19, 29,254, 61,180,242,172, 63, 9,152, 96, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,180,242,172, 63, 9,152, 96, 61,227,224,109, 63, 11,111,147, 61,203,228, 42,
+ 63, 21, 48, 37, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,251,213,147, 63, 22,209,228,
+ 61,203,228, 42, 63, 21, 48, 37, 61,227,224,109, 63, 11,111,147, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 61,227,224,109, 63, 11,111,147, 61,180,242,172, 63, 9,152, 96, 61,204,204,215, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,203,228, 42, 63, 21, 48, 37, 61,251,213,147, 63, 22,209,228,
+ 61,228, 85,208, 63, 33, 23,179, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,228, 85,208,
+ 63, 33, 23,179, 61,177,227,212, 63, 31, 60,110, 61,203,228, 42, 63, 21, 48, 37, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 61,156,122, 1, 63, 19, 29,254, 61,203,228, 42, 63, 21, 48, 37, 61,177,227,212, 63, 31, 60,110,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,177,227,212, 63, 31, 60,110, 61,228, 85,208,
+ 63, 33, 23,179, 61,202, 36,175, 63, 43, 52,228, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 61,151, 80, 53, 63, 40,228,223, 61, 76,203,246, 63, 37,200, 48, 61,130,139,166, 63, 28,140,145, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,130,139,166, 63, 28,140,145, 61,177,227,212, 63, 31, 60,110, 61,151, 80, 53,
+ 63, 40,228,223, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,202, 36,175, 63, 43, 52,228,
+ 61,151, 80, 53, 63, 40,228,223, 61,177,227,212, 63, 31, 60,110, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 61,177,227,212, 63, 31, 60,110, 61,130,139,166, 63, 28,140,145, 61,156,122, 1, 63, 19, 29,254, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,254, 61,201, 63, 44,160,207, 61,202, 36,175, 63, 43, 52,228,
+ 61,228, 85,208, 63, 33, 23,179, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,228, 85,208,
+ 63, 33, 23,179, 62, 10,237,133, 63, 34, 17,219, 61,254, 61,201, 63, 44,160,207, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,173, 63, 45, 28, 27, 61,254, 61,201, 63, 44,160,207, 62, 10,237,133, 63, 34, 17,219,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 10,237,133, 63, 34, 17,219, 61,228, 85,208,
+ 63, 33, 23,179, 61,251,213,147, 63, 22,209,228, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,205, 6,245, 63, 21, 48, 37, 62,193, 10,155, 63, 22,209,229, 62,199, 7,229, 63, 11,111,147, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,199, 7,229, 63, 11,111,147, 62,210,195, 85, 63, 9,152, 96, 62,205, 6,245,
+ 63, 21, 48, 37, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,216,225,128, 63, 19, 29,254,
+ 62,205, 6,245, 63, 21, 48, 37, 62,210,195, 85, 63, 9,152, 96, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,210,195, 85, 63, 9,152, 96, 62,199, 7,229, 63, 11,111,147, 62,204,204,202, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,205, 6,245, 63, 21, 48, 37, 62,216,225,128, 63, 19, 29,254,
+ 62,211,135, 11, 63, 31, 60,110, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,211,135, 11,
+ 63, 31, 60,110, 62,198,234,140, 63, 33, 23,179, 62,205, 6,245, 63, 21, 48, 37, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,193, 10,155, 63, 22,209,229, 62,205, 6,245, 63, 21, 48, 37, 62,198,234,140, 63, 33, 23,179,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,198,234,140, 63, 33, 23,179, 62,211,135, 11,
+ 63, 31, 60,110, 62,205,118,212, 63, 43, 52,228, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,192,112,142, 63, 44,160,207, 62,179, 51, 42, 63, 45, 28, 28, 62,186,137, 61, 63, 34, 17,219, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,186,137, 61, 63, 34, 17,219, 62,198,234,140, 63, 33, 23,179, 62,192,112,142,
+ 63, 44,160,207, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,205,118,212, 63, 43, 52,228,
+ 62,192,112,142, 63, 44,160,207, 62,198,234,140, 63, 33, 23,179, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,198,234,140, 63, 33, 23,179, 62,186,137, 61, 63, 34, 17,219, 62,193, 10,155, 63, 22,209,229, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,218, 43,243, 63, 40,228,223, 62,205,118,212, 63, 43, 52,228,
+ 62,211,135, 11, 63, 31, 60,110, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,211,135, 11,
+ 63, 31, 60,110, 62,223, 93, 22, 63, 28,140,145, 62,218, 43,243, 63, 40,228,223, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102,129, 63, 37,200, 48, 62,218, 43,243, 63, 40,228,223, 62,223, 93, 22, 63, 28,140,145,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,223, 93, 22, 63, 28,140,145, 62,211,135, 11,
+ 63, 31, 60,110, 62,216,225,128, 63, 19, 29,254, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,179, 51, 38, 63, 23, 32,185, 62,193, 10,155, 63, 22,209,229, 62,186,137, 61, 63, 34, 17,219, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,186,137, 61, 63, 34, 17,219, 62,171,221, 20, 63, 34, 17,219, 62,179, 51, 38,
+ 63, 23, 32,185, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,165, 91,180, 63, 22,209,229,
+ 62,179, 51, 38, 63, 23, 32,185, 62,171,221, 20, 63, 34, 17,219, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,171,221, 20, 63, 34, 17,219, 62,186,137, 61, 63, 34, 17,219, 62,179, 51, 42, 63, 45, 28, 28, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 38, 63, 23, 32,185, 62,165, 91,180, 63, 22,209,229,
+ 62,172,108,111, 63, 11,116, 98, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,172,108,111,
+ 63, 11,116, 98, 62,185,249,222, 63, 11,116, 98, 62,179, 51, 38, 63, 23, 32,185, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,193, 10,155, 63, 22,209,229, 62,179, 51, 38, 63, 23, 32,185, 62,185,249,222, 63, 11,116, 98,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,185,249,222, 63, 11,116, 98, 62,172,108,111,
+ 63, 11,116, 98, 62,179, 51, 38, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,191,255,252, 63, 0, 1,244, 62,204,204,202, 63, 0, 0, 0, 62,199, 7,229, 63, 11,111,147, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,199, 7,229, 63, 11,111,147, 62,185,249,222, 63, 11,116, 98, 62,191,255,252,
+ 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 38, 63, 0, 0, 0,
+ 62,191,255,252, 63, 0, 1,244, 62,185,249,222, 63, 11,116, 98, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,185,249,222, 63, 11,116, 98, 62,199, 7,229, 63, 11,111,147, 62,193, 10,155, 63, 22,209,229, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,166,102, 82, 63, 0, 1,244, 62,179, 51, 38, 63, 0, 0, 0,
+ 62,172,108,111, 63, 11,116, 98, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,172,108,111,
+ 63, 11,116, 98, 62,159, 94,104, 63, 11,111,147, 62,166,102, 82, 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,153,153,129, 63, 0, 0, 0, 62,166,102, 82, 63, 0, 1,244, 62,159, 94,104, 63, 11,111,147,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,159, 94,104, 63, 11,111,147, 62,172,108,111,
+ 63, 11,116, 98, 62,165, 91,180, 63, 22,209,229, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,179, 51, 30, 62,217, 58, 73, 62,165,174, 39, 62,217,196, 7, 62,172, 41,180, 62,198,230,227, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,172, 41,180, 62,198,230,227, 62,186, 60,127, 62,198,230,225, 62,179, 51, 30,
+ 62,217, 58, 73, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,192,184, 21, 62,217,196, 6,
+ 62,179, 51, 30, 62,217, 58, 73, 62,186, 60,127, 62,198,230,225, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,186, 60,127, 62,198,230,225, 62,172, 41,180, 62,198,230,227, 62,179, 51, 21, 62,180,111,165, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 30, 62,217, 58, 73, 62,192,184, 21, 62,217,196, 6,
+ 62,185,220, 42, 62,236,211, 31, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,185,220, 42,
+ 62,236,211, 31, 62,172,138, 27, 62,236,211, 33, 62,179, 51, 30, 62,217, 58, 73, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,165,174, 39, 62,217,196, 7, 62,179, 51, 30, 62,217, 58, 73, 62,172,138, 27, 62,236,211, 33,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,172,138, 27, 62,236,211, 33, 62,185,220, 42,
+ 62,236,211, 31, 62,179, 51, 38, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,166,102, 82, 63, 0, 1,244, 62,153,153,129, 63, 0, 0, 0, 62,159,144, 3, 62,236,207, 67, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,159,144, 3, 62,236,207, 67, 62,172,138, 27, 62,236,211, 33, 62,166,102, 82,
+ 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 38, 63, 0, 0, 0,
+ 62,166,102, 82, 63, 0, 1,244, 62,172,138, 27, 62,236,211, 33, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,172,138, 27, 62,236,211, 33, 62,159,144, 3, 62,236,207, 67, 62,165,174, 39, 62,217,196, 7, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,191,255,252, 63, 0, 1,244, 62,179, 51, 38, 63, 0, 0, 0,
+ 62,185,220, 42, 62,236,211, 31, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,185,220, 42,
+ 62,236,211, 31, 62,198,214, 65, 62,236,207, 67, 62,191,255,252, 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,204,204,202, 63, 0, 0, 0, 62,191,255,252, 63, 0, 1,244, 62,198,214, 65, 62,236,207, 67,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,198,214, 65, 62,236,207, 67, 62,185,220, 42,
+ 62,236,211, 31, 62,192,184, 21, 62,217,196, 6, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,153, 95, 95, 63, 21, 48, 32, 62,141,132,224, 63, 19, 29,246, 62,147,163, 1, 63, 9,152, 91, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,147,163, 1, 63, 9,152, 91, 62,159, 94,104, 63, 11,111,147, 62,153, 95, 95,
+ 63, 21, 48, 32, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,165, 91,180, 63, 22,209,229,
+ 62,153, 95, 95, 63, 21, 48, 32, 62,159, 94,104, 63, 11,111,147, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,159, 94,104, 63, 11,111,147, 62,147,163, 1, 63, 9,152, 91, 62,153,153,129, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,153, 95, 95, 63, 21, 48, 32, 62,165, 91,180, 63, 22,209,229,
+ 62,159,123,203, 63, 33, 23,170, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,159,123,203,
+ 63, 33, 23,170, 62,146,223, 84, 63, 31, 60, 94, 62,153, 95, 95, 63, 21, 48, 32, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,141,132,224, 63, 19, 29,246, 62,153, 95, 95, 63, 21, 48, 32, 62,146,223, 84, 63, 31, 60, 94,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,146,223, 84, 63, 31, 60, 94, 62,159,123,203,
+ 63, 33, 23,170, 62,152,239,141, 63, 43, 52,211, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,140, 58,121, 63, 40,228,199, 62,128, 0, 0, 63, 37,200, 23, 62,135, 9, 86, 63, 28,140,130, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,135, 9, 86, 63, 28,140,130, 62,146,223, 84, 63, 31, 60, 94, 62,140, 58,121,
+ 63, 40,228,199, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,152,239,141, 63, 43, 52,211,
+ 62,140, 58,121, 63, 40,228,199, 62,146,223, 84, 63, 31, 60, 94, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,146,223, 84, 63, 31, 60, 94, 62,135, 9, 86, 63, 28,140,130, 62,141,132,224, 63, 19, 29,246, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,165,245,204, 63, 44,160,198, 62,152,239,141, 63, 43, 52,211,
+ 62,159,123,203, 63, 33, 23,170, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,159,123,203,
+ 63, 33, 23,170, 62,171,221, 20, 63, 34, 17,219, 62,165,245,204, 63, 44,160,198, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 42, 63, 45, 28, 28, 62,165,245,204, 63, 44,160,198, 62,171,221, 20, 63, 34, 17,219,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,171,221, 20, 63, 34, 17,219, 62,159,123,203,
+ 63, 33, 23,170, 62,165, 91,180, 63, 22,209,229, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 25,182,180, 63, 21, 48, 38, 63, 19,184,140, 63, 22,209,232, 63, 22,183, 43, 63, 11,111,149, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 22,183, 43, 63, 11,111,149, 63, 28,148,223, 63, 9,152, 94, 63, 25,182,180,
+ 63, 21, 48, 38, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 31,163,245, 63, 19, 29,253,
+ 63, 25,182,180, 63, 21, 48, 38, 63, 28,148,223, 63, 9,152, 94, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 28,148,223, 63, 9,152, 94, 63, 22,183, 43, 63, 11,111,149, 63, 25,153,155, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 25,182,180, 63, 21, 48, 38, 63, 31,163,245, 63, 19, 29,253,
+ 63, 28,246,191, 63, 31, 60,109, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 28,246,191,
+ 63, 31, 60,109, 63, 22,168,132, 63, 33, 23,180, 63, 25,182,180, 63, 21, 48, 38, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 19,184,140, 63, 22,209,232, 63, 25,182,180, 63, 21, 48, 38, 63, 22,168,132, 63, 33, 23,180,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 22,168,132, 63, 33, 23,180, 63, 28,246,191,
+ 63, 31, 60,109, 63, 25,238,169, 63, 43, 52,229, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 19,107,138, 63, 44,160,211, 63, 12,204,220, 63, 45, 28, 35, 63, 16,119,225, 63, 34, 17,225, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 16,119,225, 63, 34, 17,225, 63, 22,168,132, 63, 33, 23,180, 63, 19,107,138,
+ 63, 44,160,211, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 25,238,169, 63, 43, 52,229,
+ 63, 19,107,138, 63, 44,160,211, 63, 22,168,132, 63, 33, 23,180, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 22,168,132, 63, 33, 23,180, 63, 16,119,225, 63, 34, 17,225, 63, 19,184,140, 63, 22,209,232, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 32, 73, 51, 63, 40,228,221, 63, 25,238,169, 63, 43, 52,229,
+ 63, 28,246,191, 63, 31, 60,109, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 28,246,191,
+ 63, 31, 60,109, 63, 34,225,192, 63, 28,140,142, 63, 32, 73, 51, 63, 40,228,221, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,117, 63, 37,200, 45, 63, 32, 73, 51, 63, 40,228,221, 63, 34,225,192, 63, 28,140,142,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 34,225,192, 63, 28,140,142, 63, 28,246,191,
+ 63, 31, 60,109, 63, 31,163,245, 63, 19, 29,253, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 12,204,212, 63, 23, 32,188, 63, 19,184,140, 63, 22,209,232, 63, 16,119,225, 63, 34, 17,225, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 16,119,225, 63, 34, 17,225, 63, 9, 33,207, 63, 34, 17,226, 63, 12,204,212,
+ 63, 23, 32,188, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 5,225, 29, 63, 22,209,233,
+ 63, 12,204,212, 63, 23, 32,188, 63, 9, 33,207, 63, 34, 17,226, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 9, 33,207, 63, 34, 17,226, 63, 16,119,225, 63, 34, 17,225, 63, 12,204,220, 63, 45, 28, 35, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,212, 63, 23, 32,188, 63, 5,225, 29, 63, 22,209,233,
+ 63, 9,105,118, 63, 11,116,101, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 9,105,118,
+ 63, 11,116,101, 63, 16, 48, 43, 63, 11,116,100, 63, 12,204,212, 63, 23, 32,188, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 19,184,140, 63, 22,209,232, 63, 12,204,212, 63, 23, 32,188, 63, 16, 48, 43, 63, 11,116,100,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 16, 48, 43, 63, 11,116,100, 63, 9,105,118,
+ 63, 11,116,101, 63, 12,204,205, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 19, 51, 51, 63, 0, 1,244, 63, 25,153,155, 63, 0, 0, 0, 63, 22,183, 43, 63, 11,111,149, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 22,183, 43, 63, 11,111,149, 63, 16, 48, 43, 63, 11,116,100, 63, 19, 51, 51,
+ 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,205, 63, 0, 0, 0,
+ 63, 19, 51, 51, 63, 0, 1,244, 63, 16, 48, 43, 63, 11,116,100, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 16, 48, 43, 63, 11,116,100, 63, 22,183, 43, 63, 11,111,149, 63, 19,184,140, 63, 22,209,232, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 6,102,102, 63, 0, 1,244, 63, 12,204,205, 63, 0, 0, 0,
+ 63, 9,105,118, 63, 11,116,101, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 9,105,118,
+ 63, 11,116,101, 63, 2,226,118, 63, 11,111,149, 63, 6,102,102, 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 6,102,102, 63, 0, 1,244, 63, 2,226,118, 63, 11,111,149,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 2,226,118, 63, 11,111,149, 63, 9,105,118,
+ 63, 11,116,101, 63, 5,225, 29, 63, 22,209,233, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 12,204,198, 62,217, 58, 72, 63, 6, 10, 77, 62,217,196, 6, 63, 9, 72, 17, 62,198,230,227, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 9, 72, 17, 62,198,230,227, 63, 16, 81,117, 62,198,230,223, 63, 12,204,198,
+ 62,217, 58, 72, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 19,143, 64, 62,217,196, 4,
+ 63, 12,204,198, 62,217, 58, 72, 63, 16, 81,117, 62,198,230,223, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 16, 81,117, 62,198,230,223, 63, 9, 72, 17, 62,198,230,227, 63, 12,204,191, 62,180,111,160, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,198, 62,217, 58, 72, 63, 19,143, 64, 62,217,196, 4,
+ 63, 16, 33, 76, 62,236,211, 30, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 16, 33, 76,
+ 62,236,211, 30, 63, 9,120, 71, 62,236,211, 30, 63, 12,204,198, 62,217, 58, 72, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 6, 10, 77, 62,217,196, 6, 63, 12,204,198, 62,217, 58, 72, 63, 9,120, 71, 62,236,211, 30,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 9,120, 71, 62,236,211, 30, 63, 16, 33, 76,
+ 62,236,211, 30, 63, 12,204,205, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 6,102,102, 63, 0, 1,244, 63, 0, 0, 0, 63, 0, 0, 0, 63, 2,251, 62, 62,236,207, 67, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 2,251, 62, 62,236,207, 67, 63, 9,120, 71, 62,236,211, 30, 63, 6,102,102,
+ 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,205, 63, 0, 0, 0,
+ 63, 6,102,102, 63, 0, 1,244, 63, 9,120, 71, 62,236,211, 30, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 9,120, 71, 62,236,211, 30, 63, 2,251, 62, 62,236,207, 67, 63, 6, 10, 77, 62,217,196, 6, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 19, 51, 51, 63, 0, 1,244, 63, 12,204,205, 63, 0, 0, 0,
+ 63, 16, 33, 76, 62,236,211, 30, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 16, 33, 76,
+ 62,236,211, 30, 63, 22,158, 86, 62,236,207, 65, 63, 19, 51, 51, 63, 0, 1,244, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 25,153,155, 63, 0, 0, 0, 63, 19, 51, 51, 63, 0, 1,244, 63, 22,158, 86, 62,236,207, 65,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 22,158, 86, 62,236,207, 65, 63, 16, 33, 76,
+ 62,236,211, 30, 63, 19,143, 64, 62,217,196, 4, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,255,197,233, 63, 21, 48, 39, 62,243,235,101, 63, 19, 29,252, 62,250, 9,132, 63, 9,152, 94, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,250, 9,132, 63, 9,152, 94, 63, 2,226,118, 63, 11,111,149, 62,255,197,233,
+ 63, 21, 48, 39, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 5,225, 29, 63, 22,209,233,
+ 62,255,197,233, 63, 21, 48, 39, 63, 2,226,118, 63, 11,111,149, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 2,226,118, 63, 11,111,149, 62,250, 9,132, 63, 9,152, 94, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,255,197,233, 63, 21, 48, 39, 63, 5,225, 29, 63, 22,209,233,
+ 63, 2,241, 43, 63, 33, 23,181, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 2,241, 43,
+ 63, 33, 23,181, 62,249, 69,225, 63, 31, 60,110, 62,255,197,233, 63, 21, 48, 39, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,243,235,101, 63, 19, 29,252, 62,255,197,233, 63, 21, 48, 39, 62,249, 69,225, 63, 31, 60,110,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,249, 69,225, 63, 31, 60,110, 63, 2,241, 43,
+ 63, 33, 23,181, 62,255, 86, 30, 63, 43, 52,230, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,242,161, 9, 63, 40,228,223, 62,230,102,129, 63, 37,200, 48, 62,237,111,222, 63, 28,140,143, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,237,111,222, 63, 28,140,143, 62,249, 69,225, 63, 31, 60,110, 62,242,161, 9,
+ 63, 40,228,223, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,255, 86, 30, 63, 43, 52,230,
+ 62,242,161, 9, 63, 40,228,223, 62,249, 69,225, 63, 31, 60,110, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,249, 69,225, 63, 31, 60,110, 62,237,111,222, 63, 28,140,143, 62,243,235,101, 63, 19, 29,252, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 6, 46, 46, 63, 44,160,211, 62,255, 86, 30, 63, 43, 52,230,
+ 63, 2,241, 43, 63, 33, 23,181, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 2,241, 43,
+ 63, 33, 23,181, 63, 9, 33,207, 63, 34, 17,226, 63, 6, 46, 46, 63, 44,160,211, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,220, 63, 45, 28, 35, 63, 6, 46, 46, 63, 44,160,211, 63, 9, 33,207, 63, 34, 17,226,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 9, 33,207, 63, 34, 17,226, 63, 2,241, 43,
+ 63, 33, 23,181, 63, 5,225, 29, 63, 22,209,233, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 85,238,138, 62,187,220, 72, 63, 82,173,218, 62,210, 92, 55, 63, 79,189,229, 62,189,208,173, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 79,189,229, 62,189,208,173, 63, 82,250,230, 62,166,190,117, 63, 85,238,138,
+ 62,187,220, 72, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,149, 62,165,199,201,
+ 63, 85,238,138, 62,187,220, 72, 63, 82,250,230, 62,166,190,117, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 82,250,230, 62,166,190,117, 63, 79,189,229, 62,189,208,173, 63, 76,119,198, 62,169,150, 90, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 73,111,170, 62,193,135, 68, 63, 76,119,198, 62,169,150, 90,
+ 63, 79,189,229, 62,189,208,173, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 79,189,229,
+ 62,189,208,173, 63, 76,175,176, 62,213,159,192, 63, 73,111,170, 62,193,135, 68, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 70,194,112, 62,217,196, 19, 63, 73,111,170, 62,193,135, 68, 63, 76,175,176, 62,213,159,192,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 76,175,176, 62,213,159,192, 63, 79,189,229,
+ 62,189,208,173, 63, 82,173,218, 62,210, 92, 55, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 79,175, 52, 62,233, 32,218, 63, 76,204,193, 63, 0, 0, 0, 63, 73,209,128, 62,236,207, 75, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 73,209,128, 62,236,207, 75, 63, 76,175,176, 62,213,159,192, 63, 79,175, 52,
+ 62,233, 32,218, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 82,173,218, 62,210, 92, 55,
+ 63, 79,175, 52, 62,233, 32,218, 63, 76,175,176, 62,213,159,192, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 76,175,176, 62,213,159,192, 63, 73,209,128, 62,236,207, 75, 63, 70,194,112, 62,217,196, 19, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 73,111,170, 62,193,135, 68, 63, 70,194,112, 62,217,196, 19,
+ 63, 67,132,171, 62,198,230,253, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 67,132,171,
+ 62,198,230,253, 63, 70, 29, 61, 62,174, 54,114, 63, 73,111,170, 62,193,135, 68, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 76,119,198, 62,169,150, 90, 63, 73,111,170, 62,193,135, 68, 63, 70, 29, 61, 62,174, 54,114,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 70, 29, 61, 62,174, 54,114, 63, 67,132,171,
+ 62,198,230,253, 63, 64, 0, 0, 62,180,111,211, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 79,175, 52, 62,233, 32,218, 63, 82,173,218, 62,210, 92, 55, 63, 86, 54, 56, 62,233, 23, 58, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 86, 54, 56, 62,233, 23, 58, 63, 83, 51, 41, 62,255,252, 24, 63, 79,175, 52,
+ 62,233, 32,218, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 76,204,193, 63, 0, 0, 0,
+ 63, 79,175, 52, 62,233, 32,218, 63, 83, 51, 41, 62,255,252, 24, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 83, 51, 41, 62,255,252, 24, 63, 86, 54, 56, 62,233, 23, 58, 63, 89,153,147, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 92,252,239, 62,233, 23, 58, 63, 89,153,147, 63, 0, 0, 0,
+ 63, 86, 54, 56, 62,233, 23, 58, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 86, 54, 56,
+ 62,233, 23, 58, 63, 89,153,147, 62,209,190,143, 63, 92,252,239, 62,233, 23, 58, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 96,133, 78, 62,210, 92, 55, 63, 92,252,239, 62,233, 23, 58, 63, 89,153,147, 62,209,190,143,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,147, 62,209,190,143, 63, 86, 54, 56,
+ 62,233, 23, 58, 63, 82,173,218, 62,210, 92, 55, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 85,238,138, 62,187,220, 72, 63, 89,153,149, 62,165,199,201, 63, 93, 68,159, 62,187,220, 72, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 93, 68,159, 62,187,220, 72, 63, 89,153,147, 62,209,190,143, 63, 85,238,138,
+ 62,187,220, 72, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 82,173,218, 62,210, 92, 55,
+ 63, 85,238,138, 62,187,220, 72, 63, 89,153,147, 62,209,190,143, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 89,153,147, 62,209,190,143, 63, 93, 68,159, 62,187,220, 72, 63, 96,133, 78, 62,210, 92, 55, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 92,252,239, 62,233, 23, 58, 63, 96,133, 78, 62,210, 92, 55,
+ 63, 99,131,242, 62,233, 32,218, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 99,131,242,
+ 62,233, 32,218, 63, 95,255,254, 62,255,252, 24, 63, 92,252,239, 62,233, 23, 58, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,147, 63, 0, 0, 0, 63, 92,252,239, 62,233, 23, 58, 63, 95,255,254, 62,255,252, 24,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 95,255,254, 62,255,252, 24, 63, 99,131,242,
+ 62,233, 32,218, 63,102,102,101, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,111,174,139, 62,198,230,223, 63,108,112,192, 62,217,196, 4, 63,105,195,133, 62,193,135, 37, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,105,195,133, 62,193,135, 37, 63,109, 21,249, 62,174, 54, 65, 63,111,174,139,
+ 62,198,230,223, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 65, 62,180,111,160,
+ 63,111,174,139, 62,198,230,223, 63,109, 21,249, 62,174, 54, 65, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,109, 21,249, 62,174, 54, 65, 63,105,195,133, 62,193,135, 37, 63,102,187,106, 62,169,150, 54, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 99,117, 70, 62,189,208,155, 63,102,187,106, 62,169,150, 54,
+ 63,105,195,133, 62,193,135, 37, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,105,195,133,
+ 62,193,135, 37, 63,102,131,123, 62,213,159,181, 63, 99,117, 70, 62,189,208,155, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 96,133, 78, 62,210, 92, 55, 63, 99,117, 70, 62,189,208,155, 63,102,131,123, 62,213,159,181,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,102,131,123, 62,213,159,181, 63,105,195,133,
+ 62,193,135, 37, 63,108,112,192, 62,217,196, 4, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,105, 97,170, 62,236,207, 65, 63,102,102,101, 63, 0, 0, 0, 63, 99,131,242, 62,233, 32,218, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 99,131,242, 62,233, 32,218, 63,102,131,123, 62,213,159,181, 63,105, 97,170,
+ 62,236,207, 65, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,108,112,192, 62,217,196, 4,
+ 63,105, 97,170, 62,236,207, 65, 63,102,131,123, 62,213,159,181, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,102,131,123, 62,213,159,181, 63, 99,131,242, 62,233, 32,218, 63, 96,133, 78, 62,210, 92, 55, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 99,117, 70, 62,189,208,155, 63, 96,133, 78, 62,210, 92, 55,
+ 63, 93, 68,159, 62,187,220, 72, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 93, 68,159,
+ 62,187,220, 72, 63, 96, 56, 71, 62,166,190, 99, 63, 99,117, 70, 62,189,208,155, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,102,187,106, 62,169,150, 54, 63, 99,117, 70, 62,189,208,155, 63, 96, 56, 71, 62,166,190, 99,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 96, 56, 71, 62,166,190, 99, 63, 93, 68,159,
+ 62,187,220, 72, 63, 89,153,149, 62,165,199,201, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 99,107, 33, 63, 9,152, 94, 63, 96, 92, 11, 63, 19, 29,253, 63, 92,238, 21, 63, 9,150,112, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 92,238, 21, 63, 9,150,112, 63, 95,255,254, 62,255,252, 24, 63, 99,107, 33,
+ 63, 9,152, 94, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,102,102,101, 63, 0, 0, 0,
+ 63, 99,107, 33, 63, 9,152, 94, 63, 95,255,254, 62,255,252, 24, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 95,255,254, 62,255,252, 24, 63, 92,238, 21, 63, 9,150,112, 63, 89,153,147, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 86, 69, 14, 63, 9,150,112, 63, 89,153,147, 63, 0, 0, 0,
+ 63, 92,238, 21, 63, 9,150,112, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 92,238, 21,
+ 63, 9,150,112, 63, 89,153,143, 63, 19, 98,219, 63, 86, 69, 14, 63, 9,150,112, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 82,215, 19, 63, 19, 29,252, 63, 86, 69, 14, 63, 9,150,112, 63, 89,153,143, 63, 19, 98,219,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,143, 63, 19, 98,219, 63, 92,238, 21,
+ 63, 9,150,112, 63, 96, 92, 11, 63, 19, 29,253, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 93, 30, 63, 63, 28,140,143, 63, 89,153,139, 63, 37,200, 45, 63, 86, 20,218, 63, 28,140,143, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 86, 20,218, 63, 28,140,143, 63, 89,153,143, 63, 19, 98,219, 63, 93, 30, 63,
+ 63, 28,140,143, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 96, 92, 11, 63, 19, 29,253,
+ 63, 93, 30, 63, 63, 28,140,143, 63, 89,153,143, 63, 19, 98,219, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 89,153,143, 63, 19, 98,219, 63, 86, 20,218, 63, 28,140,143, 63, 82,215, 19, 63, 19, 29,252, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 86, 69, 14, 63, 9,150,112, 63, 82,215, 19, 63, 19, 29,252,
+ 63, 79,200, 1, 63, 9,152, 94, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 79,200, 1,
+ 63, 9,152, 94, 63, 83, 51, 41, 62,255,252, 24, 63, 86, 69, 14, 63, 9,150,112, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,147, 63, 0, 0, 0, 63, 86, 69, 14, 63, 9,150,112, 63, 83, 51, 41, 62,255,252, 24,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 83, 51, 41, 62,255,252, 24, 63, 79,200, 1,
+ 63, 9,152, 94, 63, 76,204,193, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 61, 18, 28,237, 62,187,220, 60, 60,188, 35,151, 62,210, 92, 46, 60, 60, 74,218, 62,189,208,150, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 60, 60, 74,218, 62,189,208,150, 60,197,197,195, 62,166,190, 89, 61, 18, 28,237,
+ 62,187,220, 60, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,205,194, 62,165,199,186,
+ 61, 18, 28,237, 62,187,220, 60, 60,197,197,195, 62,166,190, 89, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,131, 23, 23, 62,166,190, 89, 63,129,120,150, 62,189,208,150, 63,127,171, 15, 62,169,150, 52, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,124,162,241, 62,193,135, 36, 63,127,171, 15, 62,169,150, 52,
+ 63,129,120,150, 62,189,208,150, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,129,120,150,
+ 62,189,208,150, 63,127,226,244, 62,213,159,179, 63,124,162,241, 62,193,135, 36, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,121,245,179, 62,217,196, 6, 63,124,162,241, 62,193,135, 36, 63,127,226,244, 62,213,159,179,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,127,226,244, 62,213,159,179, 63,129,120,150,
+ 62,189,208,150, 63,130,240,142, 62,210, 92, 46, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,129,113, 59, 62,233, 32,214, 63,128, 0, 0, 63, 0, 0, 0, 63,125, 4,194, 62,236,207, 67, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,125, 4,194, 62,236,207, 67, 63,127,226,244, 62,213,159,179, 63,129,113, 59,
+ 62,233, 32,214, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,130,240,142, 62,210, 92, 46,
+ 63,129,113, 59, 62,233, 32,214, 63,127,226,244, 62,213,159,179, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,127,226,244, 62,213,159,179, 63,125, 4,194, 62,236,207, 67, 63,121,245,179, 62,217,196, 6, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,124,162,241, 62,193,135, 36, 63,121,245,179, 62,217,196, 6,
+ 63,118,183,239, 62,198,230,227, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,118,183,239,
+ 62,198,230,227, 63,121, 80,133, 62,174, 54, 65, 63,124,162,241, 62,193,135, 36, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,127,171, 15, 62,169,150, 52, 63,124,162,241, 62,193,135, 36, 63,121, 80,133, 62,174, 54, 65,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,121, 80,133, 62,174, 54, 65, 63,118,183,239,
+ 62,198,230,227, 63,115, 51, 65, 62,180,111,160, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 60, 56,157,110, 62,233, 32,214, 60,188, 35,151, 62,210, 92, 46, 61, 22,151, 95, 62,233, 23, 55, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 22,151, 95, 62,233, 23, 55, 60,204,204,176, 62,255,252, 24, 60, 56,157,110,
+ 62,233, 32,214, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 38, 11, 79,167, 63, 0, 0, 0,
+ 60, 56,157,110, 62,233, 32,214, 60,204,204,176, 62,255,252, 24, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 60,204,204,176, 62,255,252, 24, 61, 22,151, 95, 62,233, 23, 55, 61, 76,204,215, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,129,129, 87, 62,233, 23, 57, 61, 76,204,215, 63, 0, 0, 0,
+ 61, 22,151, 95, 62,233, 23, 55, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 22,151, 95,
+ 62,233, 23, 55, 61, 76,205, 68, 62,209,190,135, 61,129,129, 87, 62,233, 23, 57, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 61,157,196, 92, 62,210, 92, 49, 61,129,129, 87, 62,233, 23, 57, 61, 76,205, 68, 62,209,190,135,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,205, 68, 62,209,190,135, 61, 22,151, 95,
+ 62,233, 23, 55, 60,188, 35,151, 62,210, 92, 46, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 61, 18, 28,237, 62,187,220, 60, 61, 76,205,194, 62,165,199,186, 61,131,191, 7, 62,187,220, 62, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,131,191, 7, 62,187,220, 62, 61, 76,205, 68, 62,209,190,135, 61, 18, 28,237,
+ 62,187,220, 60, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 60,188, 35,151, 62,210, 92, 46,
+ 61, 18, 28,237, 62,187,220, 60, 61, 76,205, 68, 62,209,190,135, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 61, 76,205, 68, 62,209,190,135, 61,131,191, 7, 62,187,220, 62, 61,157,196, 92, 62,210, 92, 49, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,129,129, 87, 62,233, 23, 57, 61,157,196, 92, 62,210, 92, 49,
+ 61,181,185, 89, 62,233, 32,214, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,181,185, 89,
+ 62,233, 32,214, 61,153,153,154, 62,255,252, 25, 61,129,129, 87, 62,233, 23, 57, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,204,215, 63, 0, 0, 0, 61,129,129, 87, 62,233, 23, 57, 61,153,153,154, 62,255,252, 25,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,153,153,154, 62,255,252, 25, 61,181,185, 89,
+ 62,233, 32,214, 61,204,204,215, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62, 11,135, 1, 62,198,230,228, 61,253, 31,171, 62,217,196, 6, 61,231,181,251, 62,193,135, 38, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,231,181,251, 62,193,135, 38, 62, 1, 36,204, 62,174, 54, 70, 62, 11,135, 1,
+ 62,198,230,228, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,214, 62,180,111,165,
+ 62, 11,135, 1, 62,198,230,228, 62, 1, 36,204, 62,174, 54, 70, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62, 1, 36,204, 62,174, 54, 70, 61,231,181,251, 62,193,135, 38, 61,207,117, 70, 62,169,150, 54, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,181, 68, 35, 62,189,208,153, 61,207,117, 70, 62,169,150, 54,
+ 61,231,181,251, 62,193,135, 38, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,231,181,251,
+ 62,193,135, 38, 61,205,181,164, 62,213,159,180, 61,181, 68, 35, 62,189,208,153, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 61,157,196, 92, 62,210, 92, 49, 61,181, 68, 35, 62,189,208,153, 61,205,181,164, 62,213,159,180,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,205,181,164, 62,213,159,180, 61,231,181,251,
+ 62,193,135, 38, 61,253, 31,171, 62,217,196, 6, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 61,228,166,251, 62,236,207, 67, 61,204,204,215, 63, 0, 0, 0, 61,181,185, 89, 62,233, 32,214, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,181,185, 89, 62,233, 32,214, 61,205,181,164, 62,213,159,180, 61,228,166,251,
+ 62,236,207, 67, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,253, 31,171, 62,217,196, 6,
+ 61,228,166,251, 62,236,207, 67, 61,205,181,164, 62,213,159,180, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 61,205,181,164, 62,213,159,180, 61,181,185, 89, 62,233, 32,214, 61,157,196, 92, 62,210, 92, 49, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,181, 68, 35, 62,189,208,153, 61,157,196, 92, 62,210, 92, 49,
+ 61,131,191, 7, 62,187,220, 62, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,131,191, 7,
+ 62,187,220, 62, 61,155, 92, 79, 62,166,190, 91, 61,181, 68, 35, 62,189,208,153, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 61,207,117, 70, 62,169,150, 54, 61,181, 68, 35, 62,189,208,153, 61,155, 92, 79, 62,166,190, 91,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,155, 92, 79, 62,166,190, 91, 61,131,191, 7,
+ 62,187,220, 62, 61, 76,205,194, 62,165,199,186, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 61,180,242,172, 63, 9,152, 96, 61,156,122, 1, 63, 19, 29,254, 61,129, 10,100, 63, 9,150,113, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,129, 10,100, 63, 9,150,113, 61,153,153,154, 62,255,252, 25, 61,180,242,172,
+ 63, 9,152, 96, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,204,204,215, 63, 0, 0, 0,
+ 61,180,242,172, 63, 9,152, 96, 61,153,153,154, 62,255,252, 25, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 61,153,153,154, 62,255,252, 25, 61,129, 10,100, 63, 9,150,113, 61, 76,204,215, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 23,132,109, 63, 9,150,113, 61, 76,204,215, 63, 0, 0, 0,
+ 61,129, 10,100, 63, 9,150,113, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,129, 10,100,
+ 63, 9,150,113, 61, 76,204, 91, 63, 19, 98,220, 61, 23,132,109, 63, 9,150,113, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 60,193, 73,174, 63, 19, 29,253, 61, 23,132,109, 63, 9,150,113, 61, 76,204, 91, 63, 19, 98,220,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,204, 91, 63, 19, 98,220, 61,129, 10,100,
+ 63, 9,150,113, 61,156,122, 1, 63, 19, 29,254, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 61,130,139,166, 63, 28,140,145, 61, 76,203,246, 63, 37,200, 48, 61, 20,129, 13, 63, 28,140,143, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 20,129, 13, 63, 28,140,143, 61, 76,204, 91, 63, 19, 98,220, 61,130,139,166,
+ 63, 28,140,145, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,156,122, 1, 63, 19, 29,254,
+ 61,130,139,166, 63, 28,140,145, 61, 76,204, 91, 63, 19, 98,220, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 61, 76,204, 91, 63, 19, 98,220, 61, 20,129, 13, 63, 28,140,143, 60,193, 73,174, 63, 19, 29,253, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 23,132,109, 63, 9,150,113, 60,193, 73,174, 63, 19, 29,253,
+ 60, 62,207,114, 63, 9,152, 94, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 60, 62,207,114,
+ 63, 9,152, 94, 60,204,204,176, 62,255,252, 24, 61, 23,132,109, 63, 9,150,113, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,204,215, 63, 0, 0, 0, 61, 23,132,109, 63, 9,150,113, 60,204,204,176, 62,255,252, 24,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 60,204,204,176, 62,255,252, 24, 60, 62,207,114,
+ 63, 9,152, 94, 38, 11, 79,167, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,113, 83,237, 62,187,220, 79, 62,100, 81, 63, 62,210, 92, 60, 62, 88,145,110, 62,189,208,167, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 88,145,110, 62,189,208,167, 62,101,133, 91, 62,166,190,112, 62,113, 83,237,
+ 62,187,220, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 62,165,199,206,
+ 62,113, 83,237, 62,187,220, 79, 62,101,133, 91, 62,166,190,112, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,101,133, 91, 62,166,190,112, 62, 88,145,110, 62,189,208,167, 62, 75,120,239, 62,169,150, 70, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 63, 88,144, 62,193,135, 46, 62, 75,120,239, 62,169,150, 70,
+ 62, 88,145,110, 62,189,208,167, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 88,145,110,
+ 62,189,208,167, 62, 76, 88,170, 62,213,159,187, 62, 63, 88,144, 62,193,135, 46, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62, 52,163,179, 62,217,196, 7, 62, 63, 88,144, 62,193,135, 46, 62, 76, 88,170, 62,213,159,187,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 76, 88,170, 62,213,159,187, 62, 88,145,110,
+ 62,189,208,167, 62,100, 81, 63, 62,210, 92, 60, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62, 88, 86,190, 62,233, 32,221, 62, 76,204,254, 63, 0, 0, 0, 62, 64,223,251, 62,236,207, 67, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 64,223,251, 62,236,207, 67, 62, 76, 88,170, 62,213,159,187, 62, 88, 86,190,
+ 62,233, 32,221, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,100, 81, 63, 62,210, 92, 60,
+ 62, 88, 86,190, 62,233, 32,221, 62, 76, 88,170, 62,213,159,187, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62, 76, 88,170, 62,213,159,187, 62, 64,223,251, 62,236,207, 67, 62, 52,163,179, 62,217,196, 7, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 63, 88,144, 62,193,135, 46, 62, 52,163,179, 62,217,196, 7,
+ 62, 39,172,153, 62,198,230,230, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 39,172,153,
+ 62,198,230,230, 62, 50, 14,213, 62,174, 54, 78, 62, 63, 88,144, 62,193,135, 46, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62, 75,120,239, 62,169,150, 70, 62, 63, 88,144, 62,193,135, 46, 62, 50, 14,213, 62,174, 54, 78,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 50, 14,213, 62,174, 54, 78, 62, 39,172,153,
+ 62,198,230,230, 62, 25,153,214, 62,180,111,165, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62, 88, 86,190, 62,233, 32,221, 62,100, 81, 63, 62,210, 92, 60, 62,114,114,166, 62,233, 23, 63, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,114,114,166, 62,233, 23, 63, 62,102,102,126, 62,255,252, 25, 62, 88, 86,190,
+ 62,233, 32,221, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 76,204,254, 63, 0, 0, 0,
+ 62, 88, 86,190, 62,233, 32,221, 62,102,102,126, 62,255,252, 25, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,102,102,126, 62,255,252, 25, 62,114,114,166, 62,233, 23, 63, 62,128, 0, 0, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,134,198,173, 62,233, 23, 63, 62,128, 0, 0, 63, 0, 0, 0,
+ 62,114,114,166, 62,233, 23, 63, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,114,114,166,
+ 62,233, 23, 63, 62,128, 0, 0, 62,209,190,149, 62,134,198,173, 62,233, 23, 63, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,141,215, 97, 62,210, 92, 60, 62,134,198,173, 62,233, 23, 63, 62,128, 0, 0, 62,209,190,149,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 62,209,190,149, 62,114,114,166,
+ 62,233, 23, 63, 62,100, 81, 63, 62,210, 92, 60, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,113, 83,237, 62,187,220, 79, 62,128, 0, 0, 62,165,199,206, 62,135, 86, 9, 62,187,220, 79, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,135, 86, 9, 62,187,220, 79, 62,128, 0, 0, 62,209,190,149, 62,113, 83,237,
+ 62,187,220, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,100, 81, 63, 62,210, 92, 60,
+ 62,113, 83,237, 62,187,220, 79, 62,128, 0, 0, 62,209,190,149, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,128, 0, 0, 62,209,190,149, 62,135, 86, 9, 62,187,220, 79, 62,141,215, 97, 62,210, 92, 60, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,134,198,173, 62,233, 23, 63, 62,141,215, 97, 62,210, 92, 60,
+ 62,147,212,161, 62,233, 32,221, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,147,212,161,
+ 62,233, 32,221, 62,140,204,193, 62,255,252, 25, 62,134,198,173, 62,233, 23, 63, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 63, 0, 0, 0, 62,134,198,173, 62,233, 23, 63, 62,140,204,193, 62,255,252, 25,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,140,204,193, 62,255,252, 25, 62,147,212,161,
+ 62,233, 32,221, 62,153,153,129, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,172, 41,180, 62,198,230,227, 62,165,174, 39, 62,217,196, 7, 62,160, 83,184, 62,193,135, 46, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,160, 83,184, 62,193,135, 46, 62,166,248,150, 62,174, 54, 78, 62,172, 41,180,
+ 62,198,230,227, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 21, 62,180,111,165,
+ 62,172, 41,180, 62,198,230,227, 62,166,248,150, 62,174, 54, 78, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,166,248,150, 62,174, 54, 78, 62,160, 83,184, 62,193,135, 46, 62,154, 67,137, 62,169,150, 70, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,147,183, 73, 62,189,208,167, 62,154, 67,137, 62,169,150, 70,
+ 62,160, 83,184, 62,193,135, 46, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,160, 83,184,
+ 62,193,135, 46, 62,153,211,171, 62,213,159,187, 62,147,183, 73, 62,189,208,167, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,141,215, 97, 62,210, 92, 60, 62,147,183, 73, 62,189,208,167, 62,153,211,171, 62,213,159,187,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,153,211,171, 62,213,159,187, 62,160, 83,184,
+ 62,193,135, 46, 62,165,174, 39, 62,217,196, 7, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,159,144, 3, 62,236,207, 67, 62,153,153,129, 63, 0, 0, 0, 62,147,212,161, 62,233, 32,221, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,147,212,161, 62,233, 32,221, 62,153,211,171, 62,213,159,187, 62,159,144, 3,
+ 62,236,207, 67, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,165,174, 39, 62,217,196, 7,
+ 62,159,144, 3, 62,236,207, 67, 62,153,211,171, 62,213,159,187, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,153,211,171, 62,213,159,187, 62,147,212,161, 62,233, 32,221, 62,141,215, 97, 62,210, 92, 60, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,147,183, 73, 62,189,208,167, 62,141,215, 97, 62,210, 92, 60,
+ 62,135, 86, 9, 62,187,220, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,135, 86, 9,
+ 62,187,220, 79, 62,141, 61, 82, 62,166,190,112, 62,147,183, 73, 62,189,208,167, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,154, 67,137, 62,169,150, 70, 62,147,183, 73, 62,189,208,167, 62,141, 61, 82, 62,166,190,112,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,141, 61, 82, 62,166,190,112, 62,135, 86, 9,
+ 62,187,220, 79, 62,128, 0, 0, 62,165,199,206, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,147,163, 1, 63, 9,152, 91, 62,141,132,224, 63, 19, 29,246, 62,134,168,251, 63, 9,150,107, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,134,168,251, 63, 9,150,107, 62,140,204,193, 62,255,252, 25, 62,147,163, 1,
+ 63, 9,152, 91, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,153,153,129, 63, 0, 0, 0,
+ 62,147,163, 1, 63, 9,152, 91, 62,140,204,193, 62,255,252, 25, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,140,204,193, 62,255,252, 25, 62,134,168,251, 63, 9,150,107, 62,128, 0, 0, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,114,174, 11, 63, 9,150,107, 62,128, 0, 0, 63, 0, 0, 0,
+ 62,134,168,251, 63, 9,150,107, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,134,168,251,
+ 63, 9,150,107, 62,128, 0, 0, 63, 19, 98,209, 62,114,174, 11, 63, 9,150,107, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,100,246, 64, 63, 19, 29,246, 62,114,174, 11, 63, 9,150,107, 62,128, 0, 0, 63, 19, 98,209,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 63, 19, 98,209, 62,134,168,251,
+ 63, 9,150,107, 62,141,132,224, 63, 19, 29,246, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,135, 9, 86, 63, 28,140,130, 62,128, 0, 0, 63, 37,200, 23, 62,113,237, 83, 63, 28,140,130, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,113,237, 83, 63, 28,140,130, 62,128, 0, 0, 63, 19, 98,209, 62,135, 9, 86,
+ 63, 28,140,130, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,141,132,224, 63, 19, 29,246,
+ 62,135, 9, 86, 63, 28,140,130, 62,128, 0, 0, 63, 19, 98,209, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,128, 0, 0, 63, 19, 98,209, 62,113,237, 83, 63, 28,140,130, 62,100,246, 64, 63, 19, 29,246, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,114,174, 11, 63, 9,150,107, 62,100,246, 64, 63, 19, 29,246,
+ 62, 88,185,255, 63, 9,152, 90, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 88,185,255,
+ 63, 9,152, 90, 62,102,102,126, 62,255,252, 25, 62,114,174, 11, 63, 9,150,107, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 63, 0, 0, 0, 62,114,174, 11, 63, 9,150,107, 62,102,102,126, 62,255,252, 25,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,102,102,126, 62,255,252, 25, 62, 88,185,255,
+ 63, 9,152, 90, 62, 76,204,254, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,223, 16, 63, 62,187,220, 62, 62,216,142,233, 62,210, 92, 49, 62,210,174,248, 62,189,208,153, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,210,174,248, 62,189,208,153, 62,217, 40,237, 62,166,190, 91, 62,223, 16, 63,
+ 62,187,220, 62, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102, 72, 62,165,199,183,
+ 62,223, 16, 63, 62,187,220, 62, 62,217, 40,237, 62,166,190, 91, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,217, 40,237, 62,166,190, 91, 62,210,174,248, 62,189,208,153, 62,204, 34,175, 62,169,150, 54, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,198, 18,129, 62,193,135, 37, 62,204, 34,175, 62,169,150, 54,
+ 62,210,174,248, 62,189,208,153, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,210,174,248,
+ 62,189,208,153, 62,204,146,151, 62,213,159,180, 62,198, 18,129, 62,193,135, 37, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,192,184, 21, 62,217,196, 6, 62,198, 18,129, 62,193,135, 37, 62,204,146,151, 62,213,159,180,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,204,146,151, 62,213,159,180, 62,210,174,248,
+ 62,189,208,153, 62,216,142,233, 62,210, 92, 49, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,210,145,170, 62,233, 32,214, 62,204,204,202, 63, 0, 0, 0, 62,198,214, 65, 62,236,207, 67, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,198,214, 65, 62,236,207, 67, 62,204,146,151, 62,213,159,180, 62,210,145,170,
+ 62,233, 32,214, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,216,142,233, 62,210, 92, 49,
+ 62,210,145,170, 62,233, 32,214, 62,204,146,151, 62,213,159,180, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,204,146,151, 62,213,159,180, 62,198,214, 65, 62,236,207, 67, 62,192,184, 21, 62,217,196, 6, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,198, 18,129, 62,193,135, 37, 62,192,184, 21, 62,217,196, 6,
+ 62,186, 60,127, 62,198,230,225, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,186, 60,127,
+ 62,198,230,225, 62,191,109,154, 62,174, 54, 68, 62,198, 18,129, 62,193,135, 37, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,204, 34,175, 62,169,150, 54, 62,198, 18,129, 62,193,135, 37, 62,191,109,154, 62,174, 54, 68,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,191,109,154, 62,174, 54, 68, 62,186, 60,127,
+ 62,198,230,225, 62,179, 51, 21, 62,180,111,165, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,210,145,170, 62,233, 32,214, 62,216,142,233, 62,210, 92, 49, 62,223,159,171, 62,233, 23, 57, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,223,159,171, 62,233, 23, 57, 62,217,153,154, 62,255,252, 24, 62,210,145,170,
+ 62,233, 32,214, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,204,204,202, 63, 0, 0, 0,
+ 62,210,145,170, 62,233, 32,214, 62,217,153,154, 62,255,252, 24, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,217,153,154, 62,255,252, 24, 62,223,159,171, 62,233, 23, 57, 62,230,102,101, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,237, 45, 20, 62,233, 23, 55, 62,230,102,101, 63, 0, 0, 0,
+ 62,223,159,171, 62,233, 23, 57, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,223,159,171,
+ 62,233, 23, 57, 62,230,102, 88, 62,209,190,135, 62,237, 45, 20, 62,233, 23, 55, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,244, 61,199, 62,210, 92, 46, 62,237, 45, 20, 62,233, 23, 55, 62,230,102, 88, 62,209,190,135,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102, 88, 62,209,190,135, 62,223,159,171,
+ 62,233, 23, 57, 62,216,142,233, 62,210, 92, 49, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,223, 16, 63, 62,187,220, 62, 62,230,102, 72, 62,165,199,183, 62,237,188, 99, 62,187,220, 60, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,237,188, 99, 62,187,220, 60, 62,230,102, 88, 62,209,190,135, 62,223, 16, 63,
+ 62,187,220, 62, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,216,142,233, 62,210, 92, 49,
+ 62,223, 16, 63, 62,187,220, 62, 62,230,102, 88, 62,209,190,135, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,230,102, 88, 62,209,190,135, 62,237,188, 99, 62,187,220, 60, 62,244, 61,199, 62,210, 92, 46, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,237, 45, 20, 62,233, 23, 55, 62,244, 61,199, 62,210, 92, 46,
+ 62,250, 59, 21, 62,233, 32,213, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,250, 59, 21,
+ 62,233, 32,213, 62,243, 51, 53, 62,255,252, 24, 62,237, 45, 20, 62,233, 23, 55, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102,101, 63, 0, 0, 0, 62,237, 45, 20, 62,233, 23, 55, 62,243, 51, 53, 62,255,252, 24,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,243, 51, 53, 62,255,252, 24, 62,250, 59, 21,
+ 62,233, 32,213, 63, 0, 0, 0, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 9, 72, 17, 62,198,230,227, 63, 6, 10, 77, 62,217,196, 6, 63, 3, 93, 15, 62,193,135, 36, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 3, 93, 15, 62,193,135, 36, 63, 6,175,123, 62,174, 54, 65, 63, 9, 72, 17,
+ 62,198,230,227, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,191, 62,180,111,160,
+ 63, 9, 72, 17, 62,198,230,227, 63, 6,175,123, 62,174, 54, 65, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 6,175,123, 62,174, 54, 65, 63, 3, 93, 15, 62,193,135, 36, 63, 0, 84,241, 62,169,150, 52, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,250, 29,169, 62,189,208,150, 63, 0, 84,241, 62,169,150, 52,
+ 63, 3, 93, 15, 62,193,135, 36, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 3, 93, 15,
+ 62,193,135, 36, 63, 0, 29, 12, 62,213,159,179, 62,250, 29,169, 62,189,208,150, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,244, 61,199, 62,210, 92, 46, 62,250, 29,169, 62,189,208,150, 63, 0, 29, 12, 62,213,159,179,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 0, 29, 12, 62,213,159,179, 63, 3, 93, 15,
+ 62,193,135, 36, 63, 6, 10, 77, 62,217,196, 6, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 2,251, 62, 62,236,207, 67, 63, 0, 0, 0, 63, 0, 0, 0, 62,250, 59, 21, 62,233, 32,213, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,250, 59, 21, 62,233, 32,213, 63, 0, 29, 12, 62,213,159,179, 63, 2,251, 62,
+ 62,236,207, 67, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 6, 10, 77, 62,217,196, 6,
+ 63, 2,251, 62, 62,236,207, 67, 63, 0, 29, 12, 62,213,159,179, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 0, 29, 12, 62,213,159,179, 62,250, 59, 21, 62,233, 32,213, 62,244, 61,199, 62,210, 92, 46, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,250, 29,169, 62,189,208,150, 62,244, 61,199, 62,210, 92, 46,
+ 62,237,188, 99, 62,187,220, 60, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,237,188, 99,
+ 62,187,220, 60, 62,243,163,164, 62,166,190, 89, 62,250, 29,169, 62,189,208,150, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 0, 84,241, 62,169,150, 52, 62,250, 29,169, 62,189,208,150, 62,243,163,164, 62,166,190, 89,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,243,163,164, 62,166,190, 89, 62,237,188, 99,
+ 62,187,220, 60, 62,230,102, 72, 62,165,199,183, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,250, 9,132, 63, 9,152, 94, 62,243,235,101, 63, 19, 29,252, 62,237, 15,114, 63, 9,150,113, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,237, 15,114, 63, 9,150,113, 62,243, 51, 53, 62,255,252, 24, 62,250, 9,132,
+ 63, 9,152, 94, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0,
+ 62,250, 9,132, 63, 9,152, 94, 62,243, 51, 53, 62,255,252, 24, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,243, 51, 53, 62,255,252, 24, 62,237, 15,114, 63, 9,150,113, 62,230,102,101, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,223,189,103, 63, 9,150,112, 62,230,102,101, 63, 0, 0, 0,
+ 62,237, 15,114, 63, 9,150,113, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,237, 15,114,
+ 63, 9,150,113, 62,230,102,117, 63, 19, 98,220, 62,223,189,103, 63, 9,150,112, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,216,225,128, 63, 19, 29,254, 62,223,189,103, 63, 9,150,112, 62,230,102,117, 63, 19, 98,220,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102,117, 63, 19, 98,220, 62,237, 15,114,
+ 63, 9,150,113, 62,243,235,101, 63, 19, 29,252, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,237,111,222, 63, 28,140,143, 62,230,102,129, 63, 37,200, 48, 62,223, 93, 22, 63, 28,140,145, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,223, 93, 22, 63, 28,140,145, 62,230,102,117, 63, 19, 98,220, 62,237,111,222,
+ 63, 28,140,143, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,243,235,101, 63, 19, 29,252,
+ 62,237,111,222, 63, 28,140,143, 62,230,102,117, 63, 19, 98,220, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,230,102,117, 63, 19, 98,220, 62,223, 93, 22, 63, 28,140,145, 62,216,225,128, 63, 19, 29,254, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,223,189,103, 63, 9,150,112, 62,216,225,128, 63, 19, 29,254,
+ 62,210,195, 85, 63, 9,152, 96, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,210,195, 85,
+ 63, 9,152, 96, 62,217,153,154, 62,255,252, 24, 62,223,189,103, 63, 9,150,112, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102,101, 63, 0, 0, 0, 62,223,189,103, 63, 9,150,112, 62,217,153,154, 62,255,252, 24,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,217,153,154, 62,255,252, 24, 62,210,195, 85,
+ 63, 9,152, 96, 62,204,204,202, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 34,187, 97, 62,187,220, 72, 63, 31,122,178, 62,210, 92, 55, 63, 28,138,186, 62,189,208,155, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 28,138,186, 62,189,208,155, 63, 31,199,185, 62,166,190, 96, 63, 34,187, 97,
+ 62,187,220, 72, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,107, 62,165,199,201,
+ 63, 34,187, 97, 62,187,220, 72, 63, 31,199,185, 62,166,190, 96, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 31,199,185, 62,166,190, 96, 63, 28,138,186, 62,189,208,155, 63, 25, 68,150, 62,169,150, 54, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 22, 60,123, 62,193,135, 36, 63, 25, 68,150, 62,169,150, 54,
+ 63, 28,138,186, 62,189,208,155, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 28,138,186,
+ 62,189,208,155, 63, 25,124,133, 62,213,159,181, 63, 22, 60,123, 62,193,135, 36, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 19,143, 64, 62,217,196, 4, 63, 22, 60,123, 62,193,135, 36, 63, 25,124,133, 62,213,159,181,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 25,124,133, 62,213,159,181, 63, 28,138,186,
+ 62,189,208,155, 63, 31,122,178, 62,210, 92, 55, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 28,124, 14, 62,233, 32,218, 63, 25,153,155, 63, 0, 0, 0, 63, 22,158, 86, 62,236,207, 65, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 22,158, 86, 62,236,207, 65, 63, 25,124,133, 62,213,159,181, 63, 28,124, 14,
+ 62,233, 32,218, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 31,122,178, 62,210, 92, 55,
+ 63, 28,124, 14, 62,233, 32,218, 63, 25,124,133, 62,213,159,181, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 25,124,133, 62,213,159,181, 63, 22,158, 86, 62,236,207, 65, 63, 19,143, 64, 62,217,196, 4, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 22, 60,123, 62,193,135, 36, 63, 19,143, 64, 62,217,196, 4,
+ 63, 16, 81,117, 62,198,230,223, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 16, 81,117,
+ 62,198,230,223, 63, 18,234, 7, 62,174, 54, 65, 63, 22, 60,123, 62,193,135, 36, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 25, 68,150, 62,169,150, 54, 63, 22, 60,123, 62,193,135, 36, 63, 18,234, 7, 62,174, 54, 65,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 18,234, 7, 62,174, 54, 65, 63, 16, 81,117,
+ 62,198,230,223, 63, 12,204,191, 62,180,111,160, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 28,124, 14, 62,233, 32,218, 63, 31,122,178, 62,210, 92, 55, 63, 35, 3, 17, 62,233, 23, 58, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 35, 3, 17, 62,233, 23, 58, 63, 32, 0, 2, 62,255,252, 24, 63, 28,124, 14,
+ 62,233, 32,218, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 25,153,155, 63, 0, 0, 0,
+ 63, 28,124, 14, 62,233, 32,218, 63, 32, 0, 2, 62,255,252, 24, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 32, 0, 2, 62,255,252, 24, 63, 35, 3, 17, 62,233, 23, 58, 63, 38,102,109, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 41,201,200, 62,233, 23, 58, 63, 38,102,109, 63, 0, 0, 0,
+ 63, 35, 3, 17, 62,233, 23, 58, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 35, 3, 17,
+ 62,233, 23, 58, 63, 38,102,109, 62,209,190,143, 63, 41,201,200, 62,233, 23, 58, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 45, 82, 38, 62,210, 92, 55, 63, 41,201,200, 62,233, 23, 58, 63, 38,102,109, 62,209,190,143,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,109, 62,209,190,143, 63, 35, 3, 17,
+ 62,233, 23, 58, 63, 31,122,178, 62,210, 92, 55, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 34,187, 97, 62,187,220, 72, 63, 38,102,107, 62,165,199,201, 63, 42, 17,118, 62,187,220, 72, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 42, 17,118, 62,187,220, 72, 63, 38,102,109, 62,209,190,143, 63, 34,187, 97,
+ 62,187,220, 72, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 31,122,178, 62,210, 92, 55,
+ 63, 34,187, 97, 62,187,220, 72, 63, 38,102,109, 62,209,190,143, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 38,102,109, 62,209,190,143, 63, 42, 17,118, 62,187,220, 72, 63, 45, 82, 38, 62,210, 92, 55, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 41,201,200, 62,233, 23, 58, 63, 45, 82, 38, 62,210, 92, 55,
+ 63, 48, 80,204, 62,233, 32,218, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 48, 80,204,
+ 62,233, 32,218, 63, 44,204,215, 62,255,252, 23, 63, 41,201,200, 62,233, 23, 58, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,109, 63, 0, 0, 0, 63, 41,201,200, 62,233, 23, 58, 63, 44,204,215, 62,255,252, 23,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 44,204,215, 62,255,252, 23, 63, 48, 80,204,
+ 62,233, 32,218, 63, 51, 51, 63, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 60,123, 85, 62,198,230,253, 63, 57, 61,144, 62,217,196, 19, 63, 54,144, 86, 62,193,135, 68, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 54,144, 86, 62,193,135, 68, 63, 57,226,196, 62,174, 54,114, 63, 60,123, 85,
+ 62,198,230,253, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 62,180,111,211,
+ 63, 60,123, 85, 62,198,230,253, 63, 57,226,196, 62,174, 54,114, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 57,226,196, 62,174, 54,114, 63, 54,144, 86, 62,193,135, 68, 63, 51,136, 58, 62,169,150, 90, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 48, 66, 27, 62,189,208,173, 63, 51,136, 58, 62,169,150, 90,
+ 63, 54,144, 86, 62,193,135, 68, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 54,144, 86,
+ 62,193,135, 68, 63, 51, 80, 80, 62,213,159,192, 63, 48, 66, 27, 62,189,208,173, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 45, 82, 38, 62,210, 92, 55, 63, 48, 66, 27, 62,189,208,173, 63, 51, 80, 80, 62,213,159,192,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 51, 80, 80, 62,213,159,192, 63, 54,144, 86,
+ 62,193,135, 68, 63, 57, 61,144, 62,217,196, 19, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 54, 46,128, 62,236,207, 75, 63, 51, 51, 63, 63, 0, 0, 0, 63, 48, 80,204, 62,233, 32,218, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 48, 80,204, 62,233, 32,218, 63, 51, 80, 80, 62,213,159,192, 63, 54, 46,128,
+ 62,236,207, 75, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 57, 61,144, 62,217,196, 19,
+ 63, 54, 46,128, 62,236,207, 75, 63, 51, 80, 80, 62,213,159,192, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 51, 80, 80, 62,213,159,192, 63, 48, 80,204, 62,233, 32,218, 63, 45, 82, 38, 62,210, 92, 55, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 48, 66, 27, 62,189,208,173, 63, 45, 82, 38, 62,210, 92, 55,
+ 63, 42, 17,118, 62,187,220, 72, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 42, 17,118,
+ 62,187,220, 72, 63, 45, 5, 26, 62,166,190,117, 63, 48, 66, 27, 62,189,208,173, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 51,136, 58, 62,169,150, 90, 63, 48, 66, 27, 62,189,208,173, 63, 45, 5, 26, 62,166,190,117,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 45, 5, 26, 62,166,190,117, 63, 42, 17,118,
+ 62,187,220, 72, 63, 38,102,107, 62,165,199,201, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 48, 55,255, 63, 9,152, 94, 63, 45, 40,237, 63, 19, 29,252, 63, 41,186,242, 63, 9,150,112, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 41,186,242, 63, 9,150,112, 63, 44,204,215, 62,255,252, 23, 63, 48, 55,255,
+ 63, 9,152, 94, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 51, 51, 63, 63, 0, 0, 0,
+ 63, 48, 55,255, 63, 9,152, 94, 63, 44,204,215, 62,255,252, 23, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 44,204,215, 62,255,252, 23, 63, 41,186,242, 63, 9,150,112, 63, 38,102,109, 63, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 35, 17,235, 63, 9,150,112, 63, 38,102,109, 63, 0, 0, 0,
+ 63, 41,186,242, 63, 9,150,112, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 41,186,242,
+ 63, 9,150,112, 63, 38,102,113, 63, 19, 98,219, 63, 35, 17,235, 63, 9,150,112, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 31,163,245, 63, 19, 29,253, 63, 35, 17,235, 63, 9,150,112, 63, 38,102,113, 63, 19, 98,219,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,113, 63, 19, 98,219, 63, 41,186,242,
+ 63, 9,150,112, 63, 45, 40,237, 63, 19, 29,252, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 41,235, 38, 63, 28,140,141, 63, 38,102,117, 63, 37,200, 45, 63, 34,225,192, 63, 28,140,142, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 34,225,192, 63, 28,140,142, 63, 38,102,113, 63, 19, 98,219, 63, 41,235, 38,
+ 63, 28,140,141, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 45, 40,237, 63, 19, 29,252,
+ 63, 41,235, 38, 63, 28,140,141, 63, 38,102,113, 63, 19, 98,219, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 38,102,113, 63, 19, 98,219, 63, 34,225,192, 63, 28,140,142, 63, 31,163,245, 63, 19, 29,253, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 35, 17,235, 63, 9,150,112, 63, 31,163,245, 63, 19, 29,253,
+ 63, 28,148,223, 63, 9,152, 94, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 28,148,223,
+ 63, 9,152, 94, 63, 32, 0, 2, 62,255,252, 24, 63, 35, 17,235, 63, 9,150,112, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,109, 63, 0, 0, 0, 63, 35, 17,235, 63, 9,150,112, 63, 32, 0, 2, 62,255,252, 24,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 32, 0, 2, 62,255,252, 24, 63, 28,148,223,
+ 63, 9,152, 94, 63, 25,153,155, 63, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,107,129,188, 62,128, 45, 66, 63, 99, 71,235, 62,120, 76,222, 63,106, 37, 94, 62, 83, 97, 84, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,106, 37, 94, 62, 83, 97, 84, 63,115, 51, 65, 62, 97,151,248, 63,107,129,188,
+ 62,128, 45, 66, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 65, 62,135, 83,151,
+ 63,107,129,188, 62,128, 45, 66, 63,115, 51, 65, 62, 97,151,248, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,115, 51, 65, 62, 97,151,248, 63,106, 37, 94, 62, 83, 97, 84, 63,115, 51, 65, 62, 52,111, 90, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,107,129,188, 62,128, 45, 66, 63,115, 51, 65, 62,135, 83,151,
+ 63,108,123,142, 62,151,144,169, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,108,123,142,
+ 62,151,144,169, 63,101, 50,231, 62,146,201, 17, 63,107,129,188, 62,128, 45, 66, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 99, 71,235, 62,120, 76,222, 63,107,129,188, 62,128, 45, 66, 63,101, 50,231, 62,146,201, 17,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,101, 50,231, 62,146,201, 17, 63,108,123,142,
+ 62,151,144,169, 63,102,187,106, 62,169,150, 54, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 96, 56, 71, 62,166,190, 99, 63, 89,153,149, 62,165,199,201, 63, 93,238, 22, 62,144,101,243, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 93,238, 22, 62,144,101,243, 63,101, 50,231, 62,146,201, 17, 63, 96, 56, 71,
+ 62,166,190, 99, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,102,187,106, 62,169,150, 54,
+ 63, 96, 56, 71, 62,166,190, 99, 63,101, 50,231, 62,146,201, 17, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,101, 50,231, 62,146,201, 17, 63, 93,238, 22, 62,144,101,243, 63, 99, 71,235, 62,120, 76,222, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,109, 21,249, 62,174, 54, 65, 63,102,187,106, 62,169,150, 54,
+ 63,108,123,142, 62,151,144,169, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,108,123,142,
+ 62,151,144,169, 63,115, 51, 65, 62,157,231, 93, 63,109, 21,249, 62,174, 54, 65, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 65, 62,180,111,160, 63,109, 21,249, 62,174, 54, 65, 63,115, 51, 65, 62,157,231, 93,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 65, 62,157,231, 93, 63,108,123,142,
+ 62,151,144,169, 63,115, 51, 65, 62,135, 83,151, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 89,153,149, 62,115,162, 79, 63, 99, 71,235, 62,120, 76,222, 63, 93,238, 22, 62,144,101,243, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 93,238, 22, 62,144,101,243, 63, 85, 69, 21, 62,144,102, 3, 63, 89,153,149,
+ 62,115,162, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 79,235, 68, 62,120, 77, 37,
+ 63, 89,153,149, 62,115,162, 79, 63, 85, 69, 21, 62,144,102, 3, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 85, 69, 21, 62,144,102, 3, 63, 93,238, 22, 62,144,101,243, 63, 89,153,149, 62,165,199,201, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,149, 62,115,162, 79, 63, 79,235, 68, 62,120, 77, 37,
+ 63, 83,186, 24, 62, 70,176,245, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 83,186, 24,
+ 62, 70,176,245, 63, 95,121, 22, 62, 70,176,204, 63, 89,153,149, 62,115,162, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 99, 71,235, 62,120, 76,222, 63, 89,153,149, 62,115,162, 79, 63, 95,121, 22, 62, 70,176,204,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 95,121, 22, 62, 70,176,204, 63, 83,186, 24,
+ 62, 70,176,245, 63, 89,153,152, 62, 23, 31,198, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,103,119, 61, 62, 30,253,179, 63,115, 51, 65, 62, 52,111, 90, 63,106, 37, 94, 62, 83, 97, 84, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,106, 37, 94, 62, 83, 97, 84, 63, 95,121, 22, 62, 70,176,204, 63,103,119, 61,
+ 62, 30,253,179, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,152, 62, 23, 31,198,
+ 63,103,119, 61, 62, 30,253,179, 63, 95,121, 22, 62, 70,176,204, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 95,121, 22, 62, 70,176,204, 63,106, 37, 94, 62, 83, 97, 84, 63, 99, 71,235, 62,120, 76,222, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 75,187,248, 62, 30,253,241, 63, 89,153,152, 62, 23, 31,198,
+ 63, 83,186, 24, 62, 70,176,245, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 83,186, 24,
+ 62, 70,176,245, 63, 73, 13,214, 62, 83, 97,181, 63, 75,187,248, 62, 30,253,241, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 62, 52,111,202, 63, 75,187,248, 62, 30,253,241, 63, 73, 13,214, 62, 83, 97,181,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 73, 13,214, 62, 83, 97,181, 63, 83,186, 24,
+ 62, 70,176,245, 63, 79,235, 68, 62,120, 77, 37, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 89,153,152, 61,147, 41,111, 63, 64, 0, 0, 61,180,111,195, 63, 64, 0, 0, 61, 52, 65,111, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 61, 52, 65,111, 63,117, 49, 38, 61, 52, 64,225, 63, 89,153,152,
+ 61,147, 41,111, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 65, 61,180,111, 83,
+ 63, 89,153,152, 61,147, 41,111, 63,117, 49, 38, 61, 52, 64,225, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,117, 49, 38, 61, 52, 64,225, 63, 64, 0, 0, 61, 52, 65,111, 63,121,222,208,178,239, 9,102, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,152, 61,147, 41,111, 63,115, 51, 65, 61,180,111, 83,
+ 63, 99, 51,172, 61,231, 46, 48, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 99, 51,172,
+ 61,231, 46, 48, 63, 79,255,135, 61,231, 46,120, 63, 89,153,152, 61,147, 41,111, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 61,180,111,195, 63, 89,153,152, 61,147, 41,111, 63, 79,255,135, 61,231, 46,120,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 79,255,135, 61,231, 46,120, 63, 99, 51,172,
+ 61,231, 46, 48, 63, 89,153,152, 62, 23, 31,198, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 75,187,248, 62, 30,253,241, 63, 64, 0, 0, 62, 52,111,202, 63, 64, 0, 0, 62, 7, 71, 24, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 62, 7, 71, 24, 63, 79,255,135, 61,231, 46,120, 63, 75,187,248,
+ 62, 30,253,241, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,152, 62, 23, 31,198,
+ 63, 75,187,248, 62, 30,253,241, 63, 79,255,135, 61,231, 46,120, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 79,255,135, 61,231, 46,120, 63, 64, 0, 0, 62, 7, 71, 24, 63, 64, 0, 0, 61,180,111,195, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,103,119, 61, 62, 30,253,179, 63, 89,153,152, 62, 23, 31,198,
+ 63, 99, 51,172, 61,231, 46, 48, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 99, 51,172,
+ 61,231, 46, 48, 63,115, 51, 66, 62, 7, 70,199, 63,103,119, 61, 62, 30,253,179, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 65, 62, 52,111, 90, 63,103,119, 61, 62, 30,253,179, 63,115, 51, 66, 62, 7, 70,199,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 66, 62, 7, 70,199, 63, 99, 51,172,
+ 61,231, 46, 48, 63,115, 51, 65, 61,180,111, 83, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 71,177,122, 62,128, 45,120, 63, 64, 0, 0, 62,135, 83,218, 63, 64, 0, 0, 62, 97,152,115, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 62, 97,152,115, 63, 73, 13,214, 62, 83, 97,181, 63, 71,177,122,
+ 62,128, 45,120, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 79,235, 68, 62,120, 77, 37,
+ 63, 71,177,122, 62,128, 45,120, 63, 73, 13,214, 62, 83, 97,181, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 73, 13,214, 62, 83, 97,181, 63, 64, 0, 0, 62, 97,152,115, 63, 64, 0, 0, 62, 52,111,202, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 71,177,122, 62,128, 45,120, 63, 79,235, 68, 62,120, 77, 37,
+ 63, 78, 0, 72, 62,146,201, 52, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 78, 0, 72,
+ 62,146,201, 52, 63, 70,183,169, 62,151,144,219, 63, 71,177,122, 62,128, 45,120, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 62,135, 83,218, 63, 71,177,122, 62,128, 45,120, 63, 70,183,169, 62,151,144,219,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 70,183,169, 62,151,144,219, 63, 78, 0, 72,
+ 62,146,201, 52, 63, 76,119,198, 62,169,150, 90, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 70, 29, 61, 62,174, 54,114, 63, 64, 0, 0, 62,180,111,211, 63, 64, 0, 0, 62,157,231,162, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 62,157,231,162, 63, 70,183,169, 62,151,144,219, 63, 70, 29, 61,
+ 62,174, 54,114, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 76,119,198, 62,169,150, 90,
+ 63, 70, 29, 61, 62,174, 54,114, 63, 70,183,169, 62,151,144,219, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 70,183,169, 62,151,144,219, 63, 64, 0, 0, 62,157,231,162, 63, 64, 0, 0, 62,135, 83,218, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 82,250,230, 62,166,190,117, 63, 76,119,198, 62,169,150, 90,
+ 63, 78, 0, 72, 62,146,201, 52, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 78, 0, 72,
+ 62,146,201, 52, 63, 85, 69, 21, 62,144,102, 3, 63, 82,250,230, 62,166,190,117, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 89,153,149, 62,165,199,201, 63, 82,250,230, 62,166,190,117, 63, 85, 69, 21, 62,144,102, 3,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 85, 69, 21, 62,144,102, 3, 63, 78, 0, 72,
+ 62,146,201, 52, 63, 79,235, 68, 62,120, 77, 37, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 61,245,167,179, 62,128, 45, 72, 61,179,217, 94, 62,120, 76,222, 61,234,196,202, 62, 83, 97,100, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,234,196,202, 62, 83, 97,100, 62, 25,153,212, 62, 97,152, 2, 61,245,167,179,
+ 62,128, 45, 72, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,214, 62,135, 83,156,
+ 61,245,167,179, 62,128, 45, 72, 62, 25,153,212, 62, 97,152, 2, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62, 25,153,212, 62, 97,152, 2, 61,234,196,202, 62, 83, 97,100, 62, 25,153,214, 62, 52,111,106, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,245,167,179, 62,128, 45, 72, 62, 25,153,214, 62,135, 83,156,
+ 61,253,118, 62, 62,151,144,174, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,253,118, 62,
+ 62,151,144,174, 61,195, 49, 53, 62,146,201, 17, 61,245,167,179, 62,128, 45, 72, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 61,179,217, 94, 62,120, 76,222, 61,245,167,179, 62,128, 45, 72, 61,195, 49, 53, 62,146,201, 17,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,195, 49, 53, 62,146,201, 17, 61,253,118, 62,
+ 62,151,144,174, 61,207,117, 70, 62,169,150, 54, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 61,155, 92, 79, 62,166,190, 91, 61, 76,205,194, 62,165,199,186, 61,137, 10,212, 62,144,101,238, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,137, 10,212, 62,144,101,238, 61,195, 49, 53, 62,146,201, 17, 61,155, 92, 79,
+ 62,166,190, 91, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,207,117, 70, 62,169,150, 54,
+ 61,155, 92, 79, 62,166,190, 91, 61,195, 49, 53, 62,146,201, 17, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 61,195, 49, 53, 62,146,201, 17, 61,137, 10,212, 62,144,101,238, 61,179,217, 94, 62,120, 76,222, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 1, 36,204, 62,174, 54, 70, 61,207,117, 70, 62,169,150, 54,
+ 61,253,118, 62, 62,151,144,174, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,253,118, 62,
+ 62,151,144,174, 62, 25,153,213, 62,157,231,100, 62, 1, 36,204, 62,174, 54, 70, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,214, 62,180,111,165, 62, 1, 36,204, 62,174, 54, 70, 62, 25,153,213, 62,157,231,100,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,213, 62,157,231,100, 61,253,118, 62,
+ 62,151,144,174, 62, 25,153,214, 62,135, 83,156, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 61, 76,205,188, 62,115,162, 53, 61,179,217, 94, 62,120, 76,222, 61,137, 10,212, 62,144,101,238, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,137, 10,212, 62,144,101,238, 61, 7,133,207, 62,144,101,236, 61, 76,205,188,
+ 62,115,162, 53, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 60, 71,162,255, 62,120, 76,216,
+ 61, 76,205,188, 62,115,162, 53, 61, 7,133,207, 62,144,101,236, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 61, 7,133,207, 62,144,101,236, 61,137, 10,212, 62,144,101,238, 61, 76,205,194, 62,165,199,186, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,205,188, 62,115,162, 53, 60, 71,162,255, 62,120, 76,216,
+ 60,221,171,190, 62, 70,176,194, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 60,221,171,190,
+ 62, 70,176,194, 61,149, 98,194, 62, 70,176,194, 61, 76,205,188, 62,115,162, 53, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 61,179,217, 94, 62,120, 76,222, 61, 76,205,188, 62,115,162, 53, 61,149, 98,194, 62, 70,176,194,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,149, 98,194, 62, 70,176,194, 60,221,171,190,
+ 62, 70,176,194, 61, 76,205,193, 62, 23, 31,168, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 61,213, 83,198, 62, 30,253,179, 62, 25,153,214, 62, 52,111,106, 61,234,196,202, 62, 83, 97,100, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,234,196,202, 62, 83, 97,100, 61,149, 98,194, 62, 70,176,194, 61,213, 83,198,
+ 62, 30,253,179, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,205,193, 62, 23, 31,168,
+ 61,213, 83,198, 62, 30,253,179, 61,149, 98,194, 62, 70,176,194, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 61,149, 98,194, 62, 70,176,194, 61,234,196,202, 62, 83, 97,100, 61,179,217, 94, 62,120, 76,222, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,126,239, 59, 62, 30,253,174, 63,131,105,154, 62, 23, 31,168,
+ 63,131,118,175, 62, 70,176,194, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,131,118,175,
+ 62, 70,176,194, 63,124, 65, 30, 62, 83, 97, 90, 63,126,239, 59, 62, 30,253,174, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 65, 62, 52,111, 90, 63,126,239, 59, 62, 30,253,174, 63,124, 65, 30, 62, 83, 97, 90,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,124, 65, 30, 62, 83, 97, 90, 63,131,118,175,
+ 62, 70,176,194, 63,129,143, 70, 62,120, 76,216, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,131,105,156, 61,147, 41,101, 63,115, 51, 65, 61,180,111, 83, 63,117, 49, 38, 61, 52, 64,225, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,117, 49, 38, 61, 52, 64,225, 63,135,148,232, 60,125,158,144, 63,131,105,156,
+ 61,147, 41,101, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,215, 61,180,111,104,
+ 61,128,245,122, 61,147, 41,101, 62, 25,153,224, 61, 52, 64,225, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,135,148,232, 60,125,158,144, 63,117, 49, 38, 61, 52, 64,225, 63,121,222,208,178,239, 9,102, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,128,245,122, 61,147, 41,101, 62, 25,153,215, 61,180,111,104,
+ 61,179, 55, 89, 61,231, 46, 38, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,179, 55, 89,
+ 61,231, 46, 38, 60,208,147, 96, 61,231, 46, 48, 61,128,245,122, 61,147, 41,101, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 65, 61,180,111, 83, 63,131,105,156, 61,147, 41,101, 63,129,153,102, 61,231, 46, 48,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 60,208,147, 96, 61,231, 46, 48, 61,179, 55, 89,
+ 61,231, 46, 38, 61, 76,205,193, 62, 23, 31,168, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,126,239, 59, 62, 30,253,174, 63,115, 51, 65, 62, 52,111, 90, 63,115, 51, 66, 62, 7, 70,199, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 66, 62, 7, 70,199, 63,129,153,102, 61,231, 46, 48, 63,126,239, 59,
+ 62, 30,253,174, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,131,105,154, 62, 23, 31,168,
+ 63,126,239, 59, 62, 30,253,174, 63,129,153,102, 61,231, 46, 48, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,129,153,102, 61,231, 46, 48, 63,115, 51, 66, 62, 7, 70,199, 63,115, 51, 65, 61,180,111, 83, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,213, 83,198, 62, 30,253,179, 61, 76,205,193, 62, 23, 31,168,
+ 61,179, 55, 89, 61,231, 46, 38, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61,179, 55, 89,
+ 61,231, 46, 38, 62, 25,153,217, 62, 7, 70,204, 61,213, 83,198, 62, 30,253,179, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,214, 62, 52,111,106, 61,213, 83,198, 62, 30,253,179, 62, 25,153,217, 62, 7, 70,204,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,217, 62, 7, 70,204, 61,179, 55, 89,
+ 61,231, 46, 38, 62, 25,153,215, 61,180,111,104, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,122,228,192, 62,128, 45, 66, 63,115, 51, 65, 62,135, 83,151, 63,115, 51, 65, 62, 97,151,248, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 65, 62, 97,151,248, 63,124, 65, 30, 62, 83, 97, 90, 63,122,228,192,
+ 62,128, 45, 66, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,129,143, 70, 62,120, 76,216,
+ 63,122,228,192, 62,128, 45, 66, 63,124, 65, 30, 62, 83, 97, 90, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,124, 65, 30, 62, 83, 97, 90, 63,115, 51, 65, 62, 97,151,248, 63,115, 51, 65, 62, 52,111, 90, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,122,228,192, 62,128, 45, 66, 63,129,143, 70, 62,120, 76,216,
+ 63,128,153,201, 62,146,201, 14, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,128,153,201,
+ 62,146,201, 14, 63,121,234,239, 62,151,144,169, 63,122,228,192, 62,128, 45, 66, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 65, 62,135, 83,151, 63,122,228,192, 62,128, 45, 66, 63,121,234,239, 62,151,144,169,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,121,234,239, 62,151,144,169, 63,128,153,201,
+ 62,146,201, 14, 63,127,171, 15, 62,169,150, 52, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63,121, 80,133, 62,174, 54, 65, 63,115, 51, 65, 62,180,111,160, 63,115, 51, 65, 62,157,231, 93, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,115, 51, 65, 62,157,231, 93, 63,121,234,239, 62,151,144,169, 63,121, 80,133,
+ 62,174, 54, 65, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,127,171, 15, 62,169,150, 52,
+ 63,121, 80,133, 62,174, 54, 65, 63,121,234,239, 62,151,144,169, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63,121,234,239, 62,151,144,169, 63,115, 51, 65, 62,157,231, 93, 63,115, 51, 65, 62,135, 83,151, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63,131, 23, 23, 62,166,190, 89, 63,127,171, 15, 62,169,150, 52,
+ 63,128,153,201, 62,146,201, 14, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 59,153,200,136,
+ 62,146,201, 14, 61, 7,133,207, 62,144,101,236, 60,197,197,195, 62,166,190, 89, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 61, 76,205,194, 62,165,199,186, 60,197,197,195, 62,166,190, 89, 61, 7,133,207, 62,144,101,236,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 61, 7,133,207, 62,144,101,236, 59,153,200,136,
+ 62,146,201, 14, 60, 71,162,255, 62,120, 76,216, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,163,208, 32, 62,128, 45, 79, 62,147, 92,147, 62,120, 76,252, 62,161, 23,102, 62, 83, 97,115, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,161, 23,102, 62, 83, 97,115, 62,179, 51, 22, 62, 97,152, 2, 62,163,208, 32,
+ 62,128, 45, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 21, 62,135, 83,156,
+ 62,163,208, 32, 62,128, 45, 79, 62,179, 51, 22, 62, 97,152, 2, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,179, 51, 22, 62, 97,152, 2, 62,161, 23,102, 62, 83, 97,115, 62,179, 51, 21, 62, 52,111,101, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,163,208, 32, 62,128, 45, 79, 62,179, 51, 21, 62,135, 83,156,
+ 62,165,195,194, 62,151,144,181, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,165,195,194,
+ 62,151,144,181, 62,151, 50,134, 62,146,201, 29, 62,163,208, 32, 62,128, 45, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,147, 92,147, 62,120, 76,252, 62,163,208, 32, 62,128, 45, 79, 62,151, 50,134, 62,146,201, 29,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,151, 50,134, 62,146,201, 29, 62,165,195,194,
+ 62,151,144,181, 62,154, 67,137, 62,169,150, 70, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,141, 61, 82, 62,166,190,112, 62,128, 0, 0, 62,165,199,206, 62,136,168,247, 62,144,102, 3, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,136,168,247, 62,144,102, 3, 62,151, 50,134, 62,146,201, 29, 62,141, 61, 82,
+ 62,166,190,112, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,154, 67,137, 62,169,150, 70,
+ 62,141, 61, 82, 62,166,190,112, 62,151, 50,134, 62,146,201, 29, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,151, 50,134, 62,146,201, 29, 62,136,168,247, 62,144,102, 3, 62,147, 92,147, 62,120, 76,252, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,166,248,150, 62,174, 54, 78, 62,154, 67,137, 62,169,150, 70,
+ 62,165,195,194, 62,151,144,181, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,165,195,194,
+ 62,151,144,181, 62,179, 51, 21, 62,157,231, 98, 62,166,248,150, 62,174, 54, 78, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 21, 62,180,111,165, 62,166,248,150, 62,174, 54, 78, 62,179, 51, 21, 62,157,231, 98,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 21, 62,157,231, 98, 62,165,195,194,
+ 62,151,144,181, 62,179, 51, 21, 62,135, 83,156, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,128, 0, 0, 62,115,162, 89, 62,147, 92,147, 62,120, 76,252, 62,136,168,247, 62,144,102, 3, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,136,168,247, 62,144,102, 3, 62,110,174, 18, 62,144,102, 3, 62,128, 0, 0,
+ 62,115,162, 89, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 89, 70,217, 62,120, 76,252,
+ 62,128, 0, 0, 62,115,162, 89, 62,110,174, 18, 62,144,102, 3, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,110,174, 18, 62,144,102, 3, 62,136,168,247, 62,144,102, 3, 62,128, 0, 0, 62,165,199,206, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 62,115,162, 89, 62, 89, 70,217, 62,120, 76,252,
+ 62,104,130, 30, 62, 70,176,230, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,104,130, 30,
+ 62, 70,176,230, 62,139,190,241, 62, 70,176,230, 62,128, 0, 0, 62,115,162, 89, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,147, 92,147, 62,120, 76,252, 62,128, 0, 0, 62,115,162, 89, 62,139,190,241, 62, 70,176,230,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,139,190,241, 62, 70,176,230, 62,104,130, 30,
+ 62, 70,176,230, 62,128, 0, 0, 62, 23, 31,208, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,155,187, 41, 62, 30,253,205, 62,179, 51, 21, 62, 52,111,101, 62,161, 23,102, 62, 83, 97,115, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,161, 23,102, 62, 83, 97,115, 62,139,190,241, 62, 70,176,230, 62,155,187, 41,
+ 62, 30,253,205, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 62, 23, 31,208,
+ 62,155,187, 41, 62, 30,253,205, 62,139,190,241, 62, 70,176,230, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,139,190,241, 62, 70,176,230, 62,161, 23,102, 62, 83, 97,115, 62,147, 92,147, 62,120, 76,252, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 72,137,174, 62, 30,253,205, 62,128, 0, 0, 62, 23, 31,208,
+ 62,104,130, 30, 62, 70,176,230, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,104,130, 30,
+ 62, 70,176,230, 62, 61,209, 51, 62, 83, 97,115, 62, 72,137,174, 62, 30,253,205, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,214, 62, 52,111,106, 62, 72,137,174, 62, 30,253,205, 62, 61,209, 51, 62, 83, 97,115,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 61,209, 51, 62, 83, 97,115, 62,104,130, 30,
+ 62, 70,176,230, 62, 89, 70,217, 62,120, 76,252, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,127,255,255, 61,147, 41,141, 62, 25,153,215, 61,180,111,104, 62, 25,153,224, 61, 52, 64,225, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,224, 61, 52, 64,225, 62,179, 51, 15, 61, 52, 64,225, 62,127,255,255,
+ 61,147, 41,141, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 20, 61,180,111,104,
+ 62,127,255,255, 61,147, 41,141, 62,179, 51, 15, 61, 52, 64,225, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,179, 51, 15, 61, 52, 64,225, 62, 25,153,224, 61, 52, 64,225, 62,161,175,144,178,239, 9,102, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,127,255,255, 61,147, 41,141, 62,179, 51, 20, 61,180,111,104,
+ 62,147, 52, 12, 61,231, 46,109, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,147, 52, 12,
+ 61,231, 46,109, 62, 89,151,231, 61,231, 46,109, 62,127,255,255, 61,147, 41,141, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,215, 61,180,111,104, 62,127,255,255, 61,147, 41,141, 62, 89,151,231, 61,231, 46,109,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 89,151,231, 61,231, 46,109, 62,147, 52, 12,
+ 61,231, 46,109, 62,128, 0, 0, 62, 23, 31,208, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62, 72,137,174, 62, 30,253,205, 62, 25,153,214, 62, 52,111,106, 62, 25,153,217, 62, 7, 70,204, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,217, 62, 7, 70,204, 62, 89,151,231, 61,231, 46,109, 62, 72,137,174,
+ 62, 30,253,205, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 62, 23, 31,208,
+ 62, 72,137,174, 62, 30,253,205, 62, 89,151,231, 61,231, 46,109, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62, 89,151,231, 61,231, 46,109, 62, 25,153,217, 62, 7, 70,204, 62, 25,153,215, 61,180,111,104, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,155,187, 41, 62, 30,253,205, 62,128, 0, 0, 62, 23, 31,208,
+ 62,147, 52, 12, 61,231, 46,109, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,147, 52, 12,
+ 61,231, 46,109, 62,179, 51, 19, 62, 7, 70,204, 62,155,187, 41, 62, 30,253,205, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 21, 62, 52,111,101, 62,155,187, 41, 62, 30,253,205, 62,179, 51, 19, 62, 7, 70,204,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 19, 62, 7, 70,204, 62,147, 52, 12,
+ 61,231, 46,109, 62,179, 51, 20, 61,180,111,104, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62, 56, 95,192, 62,128, 45, 79, 62, 25,153,214, 62,135, 83,156, 62, 25,153,212, 62, 97,152, 2, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,212, 62, 97,152, 2, 62, 61,209, 51, 62, 83, 97,115, 62, 56, 95,192,
+ 62,128, 45, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 89, 70,217, 62,120, 76,252,
+ 62, 56, 95,192, 62,128, 45, 79, 62, 61,209, 51, 62, 83, 97,115, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62, 61,209, 51, 62, 83, 97,115, 62, 25,153,212, 62, 97,152, 2, 62, 25,153,214, 62, 52,111,106, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 56, 95,192, 62,128, 45, 79, 62, 89, 70,217, 62,120, 76,252,
+ 62, 81,154,245, 62,146,201, 29, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 81,154,245,
+ 62,146,201, 29, 62, 52,120,125, 62,151,144,181, 62, 56, 95,192, 62,128, 45, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,214, 62,135, 83,156, 62, 56, 95,192, 62,128, 45, 79, 62, 52,120,125, 62,151,144,181,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 52,120,125, 62,151,144,181, 62, 81,154,245,
+ 62,146,201, 29, 62, 75,120,239, 62,169,150, 70, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62, 50, 14,213, 62,174, 54, 78, 62, 25,153,214, 62,180,111,165, 62, 25,153,213, 62,157,231,100, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 25,153,213, 62,157,231,100, 62, 52,120,125, 62,151,144,181, 62, 50, 14,213,
+ 62,174, 54, 78, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 75,120,239, 62,169,150, 70,
+ 62, 50, 14,213, 62,174, 54, 78, 62, 52,120,125, 62,151,144,181, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62, 52,120,125, 62,151,144,181, 62, 25,153,213, 62,157,231,100, 62, 25,153,214, 62,135, 83,156, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,101,133, 91, 62,166,190,112, 62, 75,120,239, 62,169,150, 70,
+ 62, 81,154,245, 62,146,201, 29, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62, 81,154,245,
+ 62,146,201, 29, 62,110,174, 18, 62,144,102, 3, 62,101,133, 91, 62,166,190,112, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,128, 0, 0, 62,165,199,206, 62,101,133, 91, 62,166,190,112, 62,110,174, 18, 62,144,102, 3,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,110,174, 18, 62,144,102, 3, 62, 81,154,245,
+ 62,146,201, 29, 62, 89, 70,217, 62,120, 76,252, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 5, 27, 64, 62,128, 45, 66, 62,249,194,232, 62,120, 76,216, 63, 3,190,226, 62, 83, 97, 90, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 3,190,226, 62, 83, 97, 90, 63, 12,204,191, 62, 97,151,248, 63, 5, 27, 64,
+ 62,128, 45, 66, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,191, 62,135, 83,149,
+ 63, 5, 27, 64, 62,128, 45, 66, 63, 12,204,191, 62, 97,151,248, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 12,204,191, 62, 97,151,248, 63, 3,190,226, 62, 83, 97, 90, 63, 12,204,191, 62, 52,111, 90, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 5, 27, 64, 62,128, 45, 66, 63, 12,204,191, 62,135, 83,149,
+ 63, 6, 21, 17, 62,151,144,169, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 6, 21, 17,
+ 62,151,144,169, 62,253,152,222, 62,146,201, 14, 63, 5, 27, 64, 62,128, 45, 66, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,249,194,232, 62,120, 76,216, 63, 5, 27, 64, 62,128, 45, 66, 62,253,152,222, 62,146,201, 14,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,253,152,222, 62,146,201, 14, 63, 6, 21, 17,
+ 62,151,144,169, 63, 0, 84,241, 62,169,150, 52, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,243,163,164, 62,166,190, 89, 62,230,102, 72, 62,165,199,183, 62,239, 15, 70, 62,144,101,233, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,239, 15, 70, 62,144,101,233, 62,253,152,222, 62,146,201, 14, 62,243,163,164,
+ 62,166,190, 89, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 0, 84,241, 62,169,150, 52,
+ 62,243,163,164, 62,166,190, 89, 62,253,152,222, 62,146,201, 14, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,253,152,222, 62,146,201, 14, 62,239, 15, 70, 62,144,101,233, 62,249,194,232, 62,120, 76,216, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 6,175,123, 62,174, 54, 65, 63, 0, 84,241, 62,169,150, 52,
+ 63, 6, 21, 17, 62,151,144,169, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 6, 21, 17,
+ 62,151,144,169, 63, 12,204,191, 62,157,231, 90, 63, 6,175,123, 62,174, 54, 65, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,191, 62,180,111,160, 63, 6,175,123, 62,174, 54, 65, 63, 12,204,191, 62,157,231, 90,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,191, 62,157,231, 90, 63, 6, 21, 17,
+ 62,151,144,169, 63, 12,204,191, 62,135, 83,149, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,230,102, 72, 62,115,162, 53, 62,249,194,232, 62,120, 76,216, 62,239, 15, 70, 62,144,101,233, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,239, 15, 70, 62,144,101,233, 62,221,189, 75, 62,144,101,238, 62,230,102, 72,
+ 62,115,162, 53, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,211, 9,168, 62,120, 76,222,
+ 62,230,102, 72, 62,115,162, 53, 62,221,189, 75, 62,144,101,238, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,221,189, 75, 62,144,101,238, 62,239, 15, 70, 62,144,101,233, 62,230,102, 72, 62,165,199,183, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102, 72, 62,115,162, 53, 62,211, 9,168, 62,120, 76,222,
+ 62,218,167, 80, 62, 70,176,194, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,218,167, 80,
+ 62, 70,176,194, 62,242, 37, 68, 62, 70,176,194, 62,230,102, 72, 62,115,162, 53, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,249,194,232, 62,120, 76,216, 62,230,102, 72, 62,115,162, 53, 62,242, 37, 68, 62, 70,176,194,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,242, 37, 68, 62, 70,176,194, 62,218,167, 80,
+ 62, 70,176,194, 62,230,102, 72, 62, 23, 31,168, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 1, 16,197, 62, 30,253,174, 63, 12,204,191, 62, 52,111, 90, 63, 3,190,226, 62, 83, 97, 90, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 3,190,226, 62, 83, 97, 90, 62,242, 37, 68, 62, 70,176,194, 63, 1, 16,197,
+ 62, 30,253,174, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102, 72, 62, 23, 31,168,
+ 63, 1, 16,197, 62, 30,253,174, 62,242, 37, 68, 62, 70,176,194, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,242, 37, 68, 62, 70,176,194, 63, 3,190,226, 62, 83, 97, 90, 62,249,194,232, 62,120, 76,216, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,202,171, 14, 62, 30,253,179, 62,230,102, 72, 62, 23, 31,168,
+ 62,218,167, 80, 62, 70,176,194, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,218,167, 80,
+ 62, 70,176,194, 62,197, 78,205, 62, 83, 97, 95, 62,202,171, 14, 62, 30,253,179, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 21, 62, 52,111,101, 62,202,171, 14, 62, 30,253,179, 62,197, 78,205, 62, 83, 97, 95,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,197, 78,205, 62, 83, 97, 95, 62,218,167, 80,
+ 62, 70,176,194, 62,211, 9,168, 62,120, 76,222, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,230,102, 63, 61,147, 41,101, 62,179, 51, 20, 61,180,111,104, 62,179, 51, 15, 61, 52, 64,225, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 15, 61, 52, 64,225, 63, 12,204,189, 61, 52, 64,225, 62,230,102, 63,
+ 61,147, 41,101, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,191, 61,180,111, 83,
+ 62,230,102, 63, 61,147, 41,101, 63, 12,204,189, 61, 52, 64,225, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 12,204,189, 61, 52, 64,225, 62,179, 51, 15, 61, 52, 64,225, 62,161,175,144,178,239, 9,102, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102, 63, 61,147, 41,101, 63, 12,204,191, 61,180,111, 83,
+ 62,249,154,104, 61,231, 46, 48, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,249,154,104,
+ 61,231, 46, 48, 62,211, 50, 42, 61,231, 46, 48, 62,230,102, 63, 61,147, 41,101, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 20, 61,180,111,104, 62,230,102, 63, 61,147, 41,101, 62,211, 50, 42, 61,231, 46, 48,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,211, 50, 42, 61,231, 46, 48, 62,249,154,104,
+ 61,231, 46, 48, 62,230,102, 72, 62, 23, 31,168, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,202,171, 14, 62, 30,253,179, 62,179, 51, 21, 62, 52,111,101, 62,179, 51, 19, 62, 7, 70,204, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 19, 62, 7, 70,204, 62,211, 50, 42, 61,231, 46, 48, 62,202,171, 14,
+ 62, 30,253,179, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102, 72, 62, 23, 31,168,
+ 62,202,171, 14, 62, 30,253,179, 62,211, 50, 42, 61,231, 46, 48, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,211, 50, 42, 61,231, 46, 48, 62,179, 51, 19, 62, 7, 70,204, 62,179, 51, 20, 61,180,111,104, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 1, 16,197, 62, 30,253,174, 62,230,102, 72, 62, 23, 31,168,
+ 62,249,154,104, 61,231, 46, 48, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,249,154,104,
+ 61,231, 46, 48, 63, 12,204,191, 62, 7, 70,199, 63, 1, 16,197, 62, 30,253,174, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,191, 62, 52,111, 90, 63, 1, 16,197, 62, 30,253,174, 63, 12,204,191, 62, 7, 70,199,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,191, 62, 7, 70,199, 62,249,154,104,
+ 61,231, 46, 48, 63, 12,204,191, 61,180,111, 83, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,194,150, 19, 62,128, 45, 72, 62,179, 51, 21, 62,135, 83,156, 62,179, 51, 22, 62, 97,152, 2, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 22, 62, 97,152, 2, 62,197, 78,205, 62, 83, 97, 95, 62,194,150, 19,
+ 62,128, 45, 72, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,211, 9,168, 62,120, 76,222,
+ 62,194,150, 19, 62,128, 45, 72, 62,197, 78,205, 62, 83, 97, 95, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,197, 78,205, 62, 83, 97, 95, 62,179, 51, 22, 62, 97,152, 2, 62,179, 51, 21, 62, 52,111,101, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,194,150, 19, 62,128, 45, 72, 62,211, 9,168, 62,120, 76,222,
+ 62,207, 51,179, 62,146,201, 17, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,207, 51,179,
+ 62,146,201, 17, 62,192,162,113, 62,151,144,174, 62,194,150, 19, 62,128, 45, 72, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 21, 62,135, 83,156, 62,194,150, 19, 62,128, 45, 72, 62,192,162,113, 62,151,144,174,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,192,162,113, 62,151,144,174, 62,207, 51,179,
+ 62,146,201, 17, 62,204, 34,175, 62,169,150, 54, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 62,191,109,154, 62,174, 54, 68, 62,179, 51, 21, 62,180,111,165, 62,179, 51, 21, 62,157,231, 98, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,179, 51, 21, 62,157,231, 98, 62,192,162,113, 62,151,144,174, 62,191,109,154,
+ 62,174, 54, 68, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,204, 34,175, 62,169,150, 54,
+ 62,191,109,154, 62,174, 54, 68, 62,192,162,113, 62,151,144,174, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 62,192,162,113, 62,151,144,174, 62,179, 51, 21, 62,157,231, 98, 62,179, 51, 21, 62,135, 83,156, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,217, 40,237, 62,166,190, 91, 62,204, 34,175, 62,169,150, 54,
+ 62,207, 51,179, 62,146,201, 17, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,207, 51,179,
+ 62,146,201, 17, 62,221,189, 75, 62,144,101,238, 62,217, 40,237, 62,166,190, 91, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 62,230,102, 72, 62,165,199,183, 62,217, 40,237, 62,166,190, 91, 62,221,189, 75, 62,144,101,238,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 62,221,189, 75, 62,144,101,238, 62,207, 51,179,
+ 62,146,201, 17, 62,211, 9,168, 62,120, 76,222, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 56, 78,134, 62,128, 45,117, 63, 48, 20,188, 62,120, 77, 37, 63, 54,242, 42, 62, 83, 97,181, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 54,242, 42, 62, 83, 97,181, 63, 64, 0, 0, 62, 97,152,115, 63, 56, 78,134,
+ 62,128, 45,117, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 62,135, 83,218,
+ 63, 56, 78,134, 62,128, 45,117, 63, 64, 0, 0, 62, 97,152,115, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 64, 0, 0, 62, 97,152,115, 63, 54,242, 42, 62, 83, 97,181, 63, 64, 0, 0, 62, 52,111,202, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 56, 78,134, 62,128, 45,117, 63, 64, 0, 0, 62,135, 83,218,
+ 63, 57, 72, 87, 62,151,144,219, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 57, 72, 87,
+ 62,151,144,219, 63, 49,255,184, 62,146,201, 52, 63, 56, 78,134, 62,128, 45,117, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 48, 20,188, 62,120, 77, 37, 63, 56, 78,134, 62,128, 45,117, 63, 49,255,184, 62,146,201, 52,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 49,255,184, 62,146,201, 52, 63, 57, 72, 87,
+ 62,151,144,219, 63, 51,136, 58, 62,169,150, 90, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 45, 5, 26, 62,166,190,117, 63, 38,102,107, 62,165,199,201, 63, 42,186,235, 62,144,102, 5, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 42,186,235, 62,144,102, 5, 63, 49,255,184, 62,146,201, 52, 63, 45, 5, 26,
+ 62,166,190,117, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 51,136, 58, 62,169,150, 90,
+ 63, 45, 5, 26, 62,166,190,117, 63, 49,255,184, 62,146,201, 52, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 49,255,184, 62,146,201, 52, 63, 42,186,235, 62,144,102, 5, 63, 48, 20,188, 62,120, 77, 37, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 57,226,196, 62,174, 54,114, 63, 51,136, 58, 62,169,150, 90,
+ 63, 57, 72, 87, 62,151,144,219, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 57, 72, 87,
+ 62,151,144,219, 63, 64, 0, 0, 62,157,231,162, 63, 57,226,196, 62,174, 54,114, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 62,180,111,211, 63, 57,226,196, 62,174, 54,114, 63, 64, 0, 0, 62,157,231,162,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 62,157,231,162, 63, 57, 72, 87,
+ 62,151,144,219, 63, 64, 0, 0, 62,135, 83,218, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 38,102,107, 62,115,162, 79, 63, 48, 20,188, 62,120, 77, 37, 63, 42,186,235, 62,144,102, 5, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 42,186,235, 62,144,102, 5, 63, 34, 17,234, 62,144,101,243, 63, 38,102,107,
+ 62,115,162, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 28,184, 21, 62,120, 76,222,
+ 63, 38,102,107, 62,115,162, 79, 63, 34, 17,234, 62,144,101,243, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 34, 17,234, 62,144,101,243, 63, 42,186,235, 62,144,102, 5, 63, 38,102,107, 62,165,199,201, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,107, 62,115,162, 79, 63, 28,184, 21, 62,120, 76,222,
+ 63, 32,134,234, 62, 70,176,204, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 32,134,234,
+ 62, 70,176,204, 63, 44, 69,233, 62, 70,176,245, 63, 38,102,107, 62,115,162, 79, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 48, 20,188, 62,120, 77, 37, 63, 38,102,107, 62,115,162, 79, 63, 44, 69,233, 62, 70,176,245,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 44, 69,233, 62, 70,176,245, 63, 32,134,234,
+ 62, 70,176,204, 63, 38,102,104, 62, 23, 31,198, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 52, 68, 9, 62, 30,253,241, 63, 64, 0, 0, 62, 52,111,202, 63, 54,242, 42, 62, 83, 97,181, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 54,242, 42, 62, 83, 97,181, 63, 44, 69,233, 62, 70,176,245, 63, 52, 68, 9,
+ 62, 30,253,241, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,104, 62, 23, 31,198,
+ 63, 52, 68, 9, 62, 30,253,241, 63, 44, 69,233, 62, 70,176,245, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 44, 69,233, 62, 70,176,245, 63, 54,242, 42, 62, 83, 97,181, 63, 48, 20,188, 62,120, 77, 37, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 24,136,195, 62, 30,253,179, 63, 38,102,104, 62, 23, 31,198,
+ 63, 32,134,234, 62, 70,176,204, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 32,134,234,
+ 62, 70,176,204, 63, 21,218,162, 62, 83, 97, 84, 63, 24,136,195, 62, 30,253,179, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,191, 62, 52,111, 90, 63, 24,136,195, 62, 30,253,179, 63, 21,218,162, 62, 83, 97, 84,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 21,218,162, 62, 83, 97, 84, 63, 32,134,234,
+ 62, 70,176,204, 63, 28,184, 21, 62,120, 76,222, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 38,102,104, 61,147, 41,111, 63, 12,204,191, 61,180,111, 83, 63, 12,204,189, 61, 52, 64,225, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,189, 61, 52, 64,225, 63, 64, 0, 0, 61, 52, 65,111, 63, 38,102,104,
+ 61,147, 41,111, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 61,180,111,195,
+ 63, 38,102,104, 61,147, 41,111, 63, 64, 0, 0, 61, 52, 65,111, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 64, 0, 0, 61, 52, 65,111, 63, 12,204,189, 61, 52, 64,225, 63,121,222,208,178,239, 9,102, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,104, 61,147, 41,111, 63, 64, 0, 0, 61,180,111,195,
+ 63, 48, 0,122, 61,231, 46,120, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 48, 0,122,
+ 61,231, 46,120, 63, 28,204, 85, 61,231, 46, 48, 63, 38,102,104, 61,147, 41,111, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,191, 61,180,111, 83, 63, 38,102,104, 61,147, 41,111, 63, 28,204, 85, 61,231, 46, 48,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 28,204, 85, 61,231, 46, 48, 63, 48, 0,122,
+ 61,231, 46,120, 63, 38,102,104, 62, 23, 31,198, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 24,136,195, 62, 30,253,179, 63, 12,204,191, 62, 52,111, 90, 63, 12,204,191, 62, 7, 70,199, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,191, 62, 7, 70,199, 63, 28,204, 85, 61,231, 46, 48, 63, 24,136,195,
+ 62, 30,253,179, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,104, 62, 23, 31,198,
+ 63, 24,136,195, 62, 30,253,179, 63, 28,204, 85, 61,231, 46, 48, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 28,204, 85, 61,231, 46, 48, 63, 12,204,191, 62, 7, 70,199, 63, 12,204,191, 61,180,111, 83, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 52, 68, 9, 62, 30,253,241, 63, 38,102,104, 62, 23, 31,198,
+ 63, 48, 0,122, 61,231, 46,120, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 48, 0,122,
+ 61,231, 46,120, 63, 64, 0, 0, 62, 7, 71, 24, 63, 52, 68, 9, 62, 30,253,241, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 62, 52,111,202, 63, 52, 68, 9, 62, 30,253,241, 63, 64, 0, 0, 62, 7, 71, 24,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 64, 0, 0, 62, 7, 71, 24, 63, 48, 0,122,
+ 61,231, 46,120, 63, 64, 0, 0, 61,180,111,195, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 20,126, 68, 62,128, 45, 64, 63, 12,204,191, 62,135, 83,149, 63, 12,204,191, 62, 97,151,248, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,191, 62, 97,151,248, 63, 21,218,162, 62, 83, 97, 84, 63, 20,126, 68,
+ 62,128, 45, 64, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 28,184, 21, 62,120, 76,222,
+ 63, 20,126, 68, 62,128, 45, 64, 63, 21,218,162, 62, 83, 97, 84, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 21,218,162, 62, 83, 97, 84, 63, 12,204,191, 62, 97,151,248, 63, 12,204,191, 62, 52,111, 90, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 20,126, 68, 62,128, 45, 64, 63, 28,184, 21, 62,120, 76,222,
+ 63, 26,205, 25, 62,146,201, 14, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 26,205, 25,
+ 62,146,201, 14, 63, 19,132,114, 62,151,144,169, 63, 20,126, 68, 62,128, 45, 64, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,191, 62,135, 83,149, 63, 20,126, 68, 62,128, 45, 64, 63, 19,132,114, 62,151,144,169,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 19,132,114, 62,151,144,169, 63, 26,205, 25,
+ 62,146,201, 14, 63, 25, 68,150, 62,169,150, 54, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 63, 18,234, 7, 62,174, 54, 65, 63, 12,204,191, 62,180,111,160, 63, 12,204,191, 62,157,231, 90, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 12,204,191, 62,157,231, 90, 63, 19,132,114, 62,151,144,169, 63, 18,234, 7,
+ 62,174, 54, 65, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 25, 68,150, 62,169,150, 54,
+ 63, 18,234, 7, 62,174, 54, 65, 63, 19,132,114, 62,151,144,169, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 63, 19,132,114, 62,151,144,169, 63, 12,204,191, 62,157,231, 90, 63, 12,204,191, 62,135, 83,149, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 31,199,185, 62,166,190, 96, 63, 25, 68,150, 62,169,150, 54,
+ 63, 26,205, 25, 62,146,201, 14, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 26,205, 25,
+ 62,146,201, 14, 63, 34, 17,234, 62,144,101,243, 63, 31,199,185, 62,166,190, 96, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 63, 38,102,107, 62,165,199,201, 63, 31,199,185, 62,166,190, 96, 63, 34, 17,234, 62,144,101,243,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 63, 34, 17,234, 62,144,101,243, 63, 26,205, 25,
+ 62,146,201, 14, 63, 28,184, 21, 62,120, 76,222, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 80, 0, 12,120, 32, 32, 0, 0, 0, 59, 0, 0, 20, 0,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 77, 69, 0, 0, 1, 24, 13, 65,154, 64,
+ 0, 0, 0, 52, 0, 0, 0, 1, 13, 65,161,176, 13, 65,148,176, 0, 0, 0, 0, 0, 0, 0, 0, 77, 69,112,114,101,118,105,101,
+119, 46, 48, 48, 50, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,155,128, 13, 65,160,208, 13, 65,161, 16, 0, 0, 0, 0,
+ 13, 65,157, 16, 13, 65,159, 16, 0, 0, 0, 0, 13, 65,161,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,155,176,
+ 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,157,176, 0, 0, 0, 1, 0, 0, 0, 5,
+ 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,159,112, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 80, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,179,128, 0, 0,
+ 52, 64, 0, 0,188,142, 92,235, 63,128, 0, 0, 63,128, 0, 2, 60,142, 92,235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0, 4, 13, 65,155,128, 0, 0, 0, 0, 0, 0, 0, 1, 7,160, 8, 32, 68, 65, 84, 65, 0, 0, 1, 44,
+ 13, 65,155,176, 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 65,157, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 0, 0, 0,120,
+ 13, 65,157, 16, 0, 0, 0, 58, 0, 0, 0, 5, 63,128, 0, 0, 63,127,255,255, 39,251,255,255, 0, 0, 0, 0,127,255, 2,255,
+ 0, 0, 0, 0, 63,128, 0, 0,191,128, 0, 0,168, 2, 0, 0, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,191,128, 0, 1,
+191,127,255,253,167,251,255,253, 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0,191,127,255,250, 63,128, 0, 3, 40, 2, 0, 3,
+ 0, 0, 0, 0,127,255, 2,255, 0, 0, 0, 0, 59,110,239, 0, 60, 26,164,131,189, 14, 92,235, 12,228, 33, 95,133, 28, 3,255,
+ 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,157,176, 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 65,159, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 48, 13, 65,159, 16, 0, 0, 0, 55, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 2,
+ 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 34, 0, 0, 0, 2,
+ 0, 0, 0, 3, 0, 0, 0, 34, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,159,112, 0, 0, 1, 35, 0, 0, 0, 5, 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, 13, 65,160,208, 0, 0, 0, 5, 0, 0, 0, 20,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 86, 84,101,120, 0, 0, 0, 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, 65,161, 16, 0, 0, 0, 6, 0, 0, 0, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,111,108, 0, 0, 0, 0, 0, 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, 65,161,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 20, 13, 65,160,208, 0, 0, 0, 54, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 44, 13, 65,161, 16, 0, 0, 0, 65,
+ 0, 0, 0, 1, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 16, 13, 65,161,112, 0, 0, 0, 59,
+ 0, 0, 0, 4,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 77, 69, 0, 0, 1, 24, 13, 65,161,176,
+ 0, 0, 0, 52, 0, 0, 0, 1, 13, 65,169, 16, 13, 65,154, 64, 0, 0, 0, 0, 0, 0, 0, 0, 77, 69,112,114,101,118,105,101,
+119, 46, 48, 48, 51, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,162,240, 13, 65,168, 48, 13, 65,168,112, 0, 0, 0, 0,
+ 13, 65,164,128, 13, 65,166,112, 0, 0, 0, 0, 13, 65,168,208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,163, 32,
+ 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,165, 16, 0, 0, 0, 1, 0, 0, 0, 5,
+ 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,166,208, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 80, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,179,128, 0, 0,
+ 52, 64, 0, 0, 28,192, 0, 0, 63,128, 0, 0, 63,128, 0, 2, 55, 39,197,172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0, 4, 13, 65,162,240, 0, 0, 0, 0, 0, 0, 0, 1, 7,160, 16, 32, 68, 65, 84, 65, 0, 0, 1, 44,
+ 13, 65,163, 32, 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 65,164,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 0, 0, 0, 96,
+ 13, 65,164,128, 0, 0, 0, 58, 0, 0, 0, 4, 63,128, 0, 0, 63,127,255,255, 39,251,255,255, 0, 0, 0, 0,127,255, 3,255,
+ 0, 0, 0, 0, 63,128, 0, 0,191,128, 0, 0,168, 2, 0, 0, 0, 0, 0, 0,127,255, 3,255, 0, 0, 0, 0,191,128, 0, 1,
+191,127,255,253,167,251,255,253, 0, 0, 0, 0,127,255, 3,255, 0, 0, 0, 0,191,127,255,250, 63,128, 0, 3, 40, 2, 0, 3,
+ 0, 0, 0, 0,127,255, 3,255, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,165, 16, 0, 0, 1, 35, 0, 0, 0, 5,
+ 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 65,166,112, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 48, 13, 65,166,112, 0, 0, 0, 55, 0, 0, 0, 4,
+ 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0, 35, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 35, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,166,208, 0, 0, 1, 35,
+ 0, 0, 0, 5, 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, 13, 65,168, 48,
+ 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 86, 84,101,120, 0, 0, 0,
+ 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, 65,168,112, 0, 0, 0, 6,
+ 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,111,108, 0, 0, 0, 0, 0, 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, 65,168,208, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 20, 13, 65,168, 48, 0, 0, 0, 54,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 68, 65, 84, 65, 0, 0, 0, 44,
+ 13, 65,168,112, 0, 0, 0, 65, 0, 0, 0, 1, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 16,
+ 13, 65,168,208, 0, 0, 0, 59, 0, 0, 0, 4,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 77, 69,
+ 0, 0, 1, 24, 13, 65,169, 16, 0, 0, 0, 52, 0, 0, 0, 1, 13, 65,176,112, 13, 65,161,176, 0, 0, 0, 0, 0, 0, 0, 0,
+ 77, 69,112,114,101,118,105,101,119, 46, 48, 48, 52, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,170, 80, 13, 65,175,144,
+ 13, 65,175,208, 0, 0, 0, 0, 13, 65,171,224, 13, 65,173,208, 0, 0, 0, 0, 13, 65,176, 48, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 65,170,128, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,172,112,
+ 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,174, 48, 0, 0, 0, 3, 0, 0, 0, 5,
+ 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1,179,128, 0, 0, 52, 64, 0, 0, 28,192, 0, 0, 63,128, 0, 0, 63,128, 0, 2, 55, 39,197,172, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 65,170, 80, 0, 0, 0, 0, 0, 0, 0, 1, 7,160, 24, 32,
+ 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,170,128, 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 65,171,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 96, 13, 65,171,224, 0, 0, 0, 58, 0, 0, 0, 4, 63,128, 0, 0, 63,127,255,255, 39,251,255,255,
+ 0, 0, 0, 0,127,255, 3,255, 0, 0, 0, 0, 63,128, 0, 0,191,128, 0, 0,168, 2, 0, 0, 0, 0, 0, 0,127,255, 3,255,
+ 0, 0, 0, 0,191,128, 0, 1,191,127,255,253,167,251,255,253, 0, 0, 0, 0,127,255, 3,255, 0, 0, 0, 0,191,127,255,250,
+ 63,128, 0, 3, 40, 2, 0, 3, 0, 0, 0, 0,127,255, 3,255, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,172,112,
+ 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 65,173,208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 48, 13, 65,173,208,
+ 0, 0, 0, 55, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 35,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 35, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 35, 68, 65, 84, 65, 0, 0, 1, 44,
+ 13, 65,174, 48, 0, 0, 1, 35, 0, 0, 0, 5, 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, 13, 65,175,144, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 85, 86, 84,101,120, 0, 0, 0, 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, 65,175,208, 0, 0, 0, 6, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,111,108, 0,
+ 0, 0, 0, 0, 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, 65,176, 48,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 0, 0, 0, 20,
+ 13, 65,175,144, 0, 0, 0, 54, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2,
+ 68, 65, 84, 65, 0, 0, 0, 44, 13, 65,175,208, 0, 0, 0, 65, 0, 0, 0, 1, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 68, 65, 84, 65, 0, 0, 0, 16, 13, 65,176, 48, 0, 0, 0, 59, 0, 0, 0, 4,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255, 0, 0, 77, 69, 0, 0, 1, 24, 13, 65,176,112, 0, 0, 0, 52, 0, 0, 0, 1, 0, 0, 0, 0, 13, 65,169, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0, 77, 69, 67,117, 98,101, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 13, 65,177,176, 13, 65,183,176, 13, 65,184, 80, 0, 0, 0, 0, 13, 65,179, 64, 13, 65,181,144, 0, 0, 0, 0, 13, 65,185,128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,177,224, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 65,180, 48, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65,182, 80,
+ 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 12, 0, 0, 0, 6,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 51,128, 0, 0,180, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 4, 63,128, 0, 4,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 4, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 4, 13, 65,177,176, 0, 0, 0, 0,
+ 0, 0, 0, 1, 7,160, 8, 32, 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,177,224, 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 65,179, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0,192, 13, 65,179, 64, 0, 0, 0, 58, 0, 0, 0, 8, 63,128, 0, 0,
+ 63,127,255,255,191,128, 0, 0, 73,230, 73,230,182, 26, 3,255, 0, 0, 0, 0, 63,128, 0, 0,191,128, 0, 0,191,128, 0, 0,
+ 73,230,182, 26,182, 26, 3,255, 0, 0, 0, 0,191,128, 0, 1,191,127,255,253,191,128, 0, 0,182, 26,182, 26,182, 26, 3,255,
+ 0, 0, 0, 0,191,127,255,250, 63,128, 0, 3,191,128, 0, 0,182, 26, 73,230,182, 26, 3,255, 0, 0, 0, 0, 63,128, 0, 4,
+ 63,127,255,247, 63,128, 0, 0, 73,230, 73,230, 73,230, 3,255, 0, 0, 0, 0, 63,127,255,245,191,128, 0, 5, 63,128, 0, 0,
+ 73,230,182, 26, 73,230, 3,255, 0, 0, 0, 0,191,128, 0, 3,191,127,255,250, 63,128, 0, 0,182, 26,182, 26, 73,230, 3,255,
+ 0, 0, 0, 0,191,127,255,255, 63,128, 0, 0, 63,128, 0, 0,182, 26, 73,230, 73,230, 3,255, 0, 0, 0, 0, 68, 65, 84, 65,
+ 0, 0, 1, 44, 13, 65,180, 48, 0, 0, 1, 35, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 65,181,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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,
+ 0, 0, 0,144, 13, 65,181,144, 0, 0, 0, 55, 0, 0, 0, 12, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 35, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 35, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 35,
+ 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 35, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 35, 0, 0, 0, 6, 0, 0, 0, 7,
+ 0, 0, 0, 35, 0, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 35, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 35, 0, 0, 0, 0,
+ 0, 0, 0, 4, 0, 0, 0, 35, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 35, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0, 35,
+ 68, 65, 84, 65, 0, 0, 1, 44, 13, 65,182, 80, 0, 0, 1, 35, 0, 0, 0, 5, 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, 13, 65,183,176, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 85, 86, 84,101,120, 0, 0, 0, 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, 65,184, 80, 0, 0, 0, 6, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 67,111,108, 0, 0, 0, 0, 0, 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, 65,185,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0,120, 13, 65,183,176, 0, 0, 0, 54, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 0,
+ 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 2,
+ 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0, 2, 68, 65, 84, 65, 0, 0, 1, 8, 13, 65,184, 80, 0, 0, 0, 65, 0, 0, 0, 6,
+ 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0, 68, 65, 84, 65, 0, 0, 0, 96, 13, 65,185,128, 0, 0, 0, 59, 0, 0, 0, 24,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 80, 65,
+ 0, 0, 1,224, 7,161, 74, 32, 0, 0, 1, 41, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 80, 65, 80, 83,121,115, 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, 0, 0, 0, 0, 0, 0, 18, 0, 2, 0, 1, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 4,
+ 0, 6, 0, 8, 0, 5, 0, 5, 0, 3, 0,100, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 4, 0, 5, 0, 3, 0, 1,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,128, 63,128, 0, 0, 61,204,204,205,
+ 63, 76,204,205, 63,128, 0, 0, 66,200, 0, 0, 66, 72, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 63,128, 0, 0, 63, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,150, 0, 0, 0, 0, 0, 0, 0, 10, 63,182, 41,128, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0,189, 35,214,240, 0, 0, 0, 0,189,196,155,184, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 62, 76,204,205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 76,204,205,
+ 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 63,128, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 65, 32, 0, 0, 63,128, 0, 0, 62, 76,204,205, 62,153,153,154,
+ 63,128, 0, 0, 63,128, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0,
+ 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 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, 68, 78, 65, 49, 0, 0,166,136, 12,150,192, 32, 0, 0, 0, 0,
+ 0, 0, 0, 1, 83, 68, 78, 65, 78, 65, 77, 69, 0, 0, 9, 22, 42,110,101,120,116, 0, 42,112,114,101,118, 0, 42,100, 97,116,
+ 97, 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,112,111,105,110,116,101,114, 0,103,114,111,117,112, 0,118, 97,108, 0,118, 97,
+108, 50, 0,110, 97,109,101, 91, 51, 50, 93, 0,116,121,112,101, 0,115,117, 98,116,121,112,101, 0,102,108, 97,103, 0,115, 97,
+118,101,100, 0,100, 97,116, 97, 0,108,101,110, 0,116,111,116, 97,108,108,101,110, 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,105, 99,111,110, 95,105,100, 0, 42,112,114,111,112,101,114,116,105,101,
+115, 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, 50, 52, 48,
+ 93, 0,102,105,108,101,110, 97,109,101, 91, 50, 52, 48, 93, 0,116,111,116, 0,112, 97,100, 0, 42,112, 97,114,101,110,116, 0,
+119, 91, 50, 93, 0,104, 91, 50, 93, 0, 99,104, 97,110,103,101,100, 91, 50, 93, 0,112, 97,100, 48, 0,112, 97,100, 49, 0, 42,
+114,101, 99,116, 91, 50, 93, 0, 42,111, 98, 0, 98,108,111, 99,107,116,121,112,101, 0, 97,100,114, 99,111,100,101, 0,110, 97,
+109,101, 91, 49, 50, 56, 93, 0, 42, 98,112, 0, 42, 98,101,122,116, 0,109, 97,120,114, 99,116, 0,116,111,116,114, 99,116, 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,114,116, 0, 98,105,
+116,109, 97,115,107, 0,115,108,105,100,101, 95,109,105,110, 0,115,108,105,100,101, 95,109, 97,120, 0, 99,117,114,118, 97,108,
+ 0, 42,100,114,105,118,101,114, 0, 99,117,114,118,101, 0, 99,117,114, 0,115,104,111,119,107,101,121, 0,109,117,116,101,105,
+112,111, 0,112,111,115, 0,114,101,108, 97,116,105,118,101, 0,116,111,116,101,108,101,109, 0,112, 97,100, 50, 0, 42,119,101,
+105,103,104,116,115, 0,118,103,114,111,117,112, 91, 51, 50, 93, 0,115,108,105,100,101,114,109,105,110, 0,115,108,105,100,101,
+114,109, 97,120, 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, 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, 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, 42,102,111,114,109, 97,116, 0, 98,108,101,110, 0,108,105,110,101,110,111, 0,115,
+116, 97,114,116, 0,101,110,100, 0,102,108, 97,103,115, 0, 99,111,108,111,114, 91, 52, 93, 0,112, 97,100, 91, 52, 93, 0, 42,
+110, 97,109,101, 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,109, 97,114,107,101,114,115, 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,109,116,105,109,101, 0,115,105,122,101,
+ 0,115,101,101,107, 0,112, 97,115,115,101,112, 97,114,116, 97,108,112,104, 97, 0, 97,110,103,108,101, 0, 99,108,105,112,115,
+116, 97, 0, 99,108,105,112,101,110,100, 0,108,101,110,115, 0,111,114,116,104,111, 95,115, 99, 97,108,101, 0,100,114, 97,119,
+115,105,122,101, 0,115,104,105,102,116,120, 0,115,104,105,102,116,121, 0, 89, 70, 95,100,111,102,100,105,115,116, 0, 89, 70,
+ 95, 97,112,101,114,116,117,114,101, 0, 89, 70, 95, 98,107,104,116,121,112,101, 0, 89, 70, 95, 98,107,104, 98,105, 97,115, 0,
+ 89, 70, 95, 98,107,104,114,111,116, 0,115, 99,114,105,112,116,108,105,110,107, 0, 42,100,111,102, 95,111, 98, 0,102,114, 97,
+109,101,110,114, 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,
+ 99,121, 99,108, 0,111,107, 0,109,117,108,116,105, 95,105,110,100,101,120, 0,108, 97,121,101,114, 0,112, 97,115,115, 0,109,
+101,110,117,110,114, 0,105, 98,117,102,115, 0, 42,103,112,117,116,101,120,116,117,114,101, 0, 42, 97,110,105,109, 0, 42,114,
+114, 0,115,111,117,114, 99,101, 0,108, 97,115,116,102,114, 97,109,101, 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, 42,112,114,101,118,105,101,
+119, 0,108, 97,115,116,117,112,100, 97,116,101, 0,108, 97,115,116,117,115,101,100, 0, 97,110,105,109,115,112,101,101,100, 0,
+103,101,110, 95,120, 0,103,101,110, 95,121, 0,103,101,110, 95,116,121,112,101, 0, 97,115,112,120, 0, 97,115,112,121, 0, 42,
+118,110,111,100,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,117,118,110, 97,109,101, 91, 51, 50, 93, 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,112,109, 97,112,116,111, 0,
+112,109, 97,112,116,111,110,101,103, 0,110,111,114,109, 97,112,115,112, 97, 99,101, 0,112, 97,100, 91, 51, 93, 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,100,105,115,112,102, 97, 99, 0,119, 97,114,112,102, 97, 99, 0,110, 97,109,101, 91, 49, 54, 48, 93, 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,105,110,115,116, 97,110, 99,101, 95,105,110,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, 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,111, 98,105,109, 97,116, 91, 51, 93, 91, 51,
+ 93, 0,115,116,121,112,101, 0,118,105,101,119,115, 99, 97,108,101, 0,110,111,116,108, 97,121, 0, 99,117, 98,101,114,101,115,
+ 0,100,101,112,116,104, 0,114,101, 99, 97,108, 99, 0,108, 97,115,116,115,105,122,101, 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,109,103, 95, 72, 0,109,103, 95,108, 97, 99,117,110, 97,
+114,105,116,121, 0,109,103, 95,111, 99,116, 97,118,101,115, 0,109,103, 95,111,102,102,115,101,116, 0,109,103, 95,103, 97,105,
+110, 0,100,105,115,116, 95, 97,109,111,117,110,116, 0,110,115, 95,111,117,116,115, 99, 97,108,101, 0,118,110, 95,119, 49, 0,
+118,110, 95,119, 50, 0,118,110, 95,119, 51, 0,118,110, 95,119, 52, 0,118,110, 95,109,101,120,112, 0,118,110, 95,100,105,115,
+116,109, 0,118,110, 95, 99,111,108,116,121,112,101, 0,110,111,105,115,101,100,101,112,116,104, 0,110,111,105,115,101,116,121,
+112,101, 0,110,111,105,115,101, 98, 97,115,105,115, 0,110,111,105,115,101, 98, 97,115,105,115, 50, 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, 99,104,101,
+ 99,107,101,114,100,105,115,116, 0,110, 97, 98,108, 97, 0,105,117,115,101,114, 0, 42,112,108,117,103,105,110, 0, 42, 99,111,
+ 98, 97, 0, 42,101,110,118, 0,108,111, 99, 91, 51, 93, 0,114,111,116, 91, 51, 93, 0,109, 97,116, 91, 52, 93, 91, 52, 93, 0,
+109,105,110, 91, 51, 93, 0,109, 97,120, 91, 51, 93, 0,112, 97,100, 51, 0,109,111,100,101, 0,116,111,116,101,120, 0,115,104,
+100,119,114, 0,115,104,100,119,103, 0,115,104,100,119, 98, 0,115,104,100,119,112, 97,100, 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, 42, 99,117,114,102, 97,108,108,111,102,102, 0,102, 97,108,108,111,102,102, 95,116,121,112,101, 0,
+115,104, 97,100,115,112,111,116,115,105,122,101, 0, 98,105, 97,115, 0,115,111,102,116, 0, 98,117,102,115,105,122,101, 0,115,
+ 97,109,112, 0, 98,117,102,102,101,114,115, 0,102,105,108,116,101,114,116,121,112,101, 0, 98,117,102,102,108, 97,103, 0, 98,
+117,102,116,121,112,101, 0,114, 97,121, 95,115, 97,109,112, 0,114, 97,121, 95,115, 97,109,112,121, 0,114, 97,121, 95,115, 97,
+109,112,122, 0,114, 97,121, 95,115, 97,109,112, 95,116,121,112,101, 0, 97,114,101, 97, 95,115,104, 97,112,101, 0, 97,114,101,
+ 97, 95,115,105,122,101, 0, 97,114,101, 97, 95,115,105,122,101,121, 0, 97,114,101, 97, 95,115,105,122,101,122, 0, 97,100, 97,
+112,116, 95,116,104,114,101,115,104, 0,114, 97,121, 95,115, 97,109,112, 95,109,101,116,104,111,100, 0,116,101,120, 97, 99,116,
+ 0,115,104, 97,100,104, 97,108,111,115,116,101,112, 0,115,117,110, 95,101,102,102,101, 99,116, 95,116,121,112,101, 0,115,107,
+121, 98,108,101,110,100,116,121,112,101, 0,104,111,114,105,122,111,110, 95, 98,114,105,103,104,116,110,101,115,115, 0,115,112,
+114,101, 97,100, 0,115,117,110, 95, 98,114,105,103,104,116,110,101,115,115, 0,115,117,110, 95,115,105,122,101, 0, 98, 97, 99,
+107,115, 99, 97,116,116,101,114,101,100, 95,108,105,103,104,116, 0,115,117,110, 95,105,110,116,101,110,115,105,116,121, 0, 97,
+116,109, 95,116,117,114, 98,105,100,105,116,121, 0, 97,116,109, 95,105,110,115, 99, 97,116,116,101,114,105,110,103, 95,102, 97,
+ 99,116,111,114, 0, 97,116,109, 95,101,120,116,105,110, 99,116,105,111,110, 95,102, 97, 99,116,111,114, 0, 97,116,109, 95,100,
+105,115,116, 97,110, 99,101, 95,102, 97, 99,116,111,114, 0,115,107,121, 98,108,101,110,100,102, 97, 99, 0, 89, 70, 95,110,117,
+109,112,104,111,116,111,110,115, 0, 89, 70, 95,110,117,109,115,101, 97,114, 99,104, 0, 89, 70, 95,112,104,100,101,112,116,104,
+ 0, 89, 70, 95,117,115,101,113,109, 99, 0, 89, 70, 95, 98,117,102,115,105,122,101, 0, 89, 70, 95,112, 97,100, 0, 89, 70, 95,
+ 99, 97,117,115,116,105, 99, 98,108,117,114, 0, 89, 70, 95,108,116,114, 97,100,105,117,115, 0, 89, 70, 95,103,108,111,119,105,
+110,116, 0, 89, 70, 95,103,108,111,119,111,102,115, 0, 89, 70, 95,103,108,111,119,116,121,112,101, 0, 89, 70, 95,112, 97,100,
+ 50, 0, 42,109,116,101,120, 91, 49, 56, 93, 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,114, 97,121, 95,109,105,114,114,111,114, 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,116,114, 97,110,115,108,117, 99,101,110, 99,
+121, 0,102,114,101,115,110,101,108, 95,109,105,114, 0,102,114,101,115,110,101,108, 95,109,105,114, 95,105, 0,102,114,101,115,
+110,101,108, 95,116,114, 97, 0,102,114,101,115,110,101,108, 95,116,114, 97, 95,105, 0,102,105,108,116,101,114, 0,116,120, 95,
+108,105,109,105,116, 0,116,120, 95,102, 97,108,108,111,102,102, 0,114, 97,121, 95,100,101,112,116,104, 0,114, 97,121, 95,100,
+101,112,116,104, 95,116,114, 97, 0,104, 97,114, 0,115,101,101,100, 49, 0,115,101,101,100, 50, 0,103,108,111,115,115, 95,109,
+105,114, 0,103,108,111,115,115, 95,116,114, 97, 0,115, 97,109,112, 95,103,108,111,115,115, 95,109,105,114, 0,115, 97,109,112,
+ 95,103,108,111,115,115, 95,116,114, 97, 0, 97,100, 97,112,116, 95,116,104,114,101,115,104, 95,109,105,114, 0, 97,100, 97,112,
+116, 95,116,104,114,101,115,104, 95,116,114, 97, 0, 97,110,105,115,111, 95,103,108,111,115,115, 95,109,105,114, 0,100,105,115,
+116, 95,109,105,114, 0,102, 97,100,101,116,111, 95,109,105,114, 0,115,104, 97,100,101, 95,102,108, 97,103, 0,109,111,100,101,
+ 95,108, 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,
+115,116,114, 97,110,100, 95,115,116, 97, 0,115,116,114, 97,110,100, 95,101,110,100, 0,115,116,114, 97,110,100, 95,101, 97,115,
+101, 0,115,116,114, 97,110,100, 95,115,117,114,102,110,111,114, 0,115,116,114, 97,110,100, 95,109,105,110, 0,115,116,114, 97,
+110,100, 95,119,105,100,116,104,102, 97,100,101, 0,115,116,114, 97,110,100, 95,117,118,110, 97,109,101, 91, 51, 50, 93, 0,115,
+ 98,105, 97,115, 0,108, 98,105, 97,115, 0,115,104, 97,100, 95, 97,108,112,104, 97, 0,115,101,112,116,101,120, 0,114,103, 98,
+115,101,108, 0,112,114, 95,116,121,112,101, 0,117,115,101, 95,110,111,100,101,115, 0,112,114, 95, 98, 97, 99,107, 0,112,114,
+ 95,108, 97,109,112, 0,112, 97,100, 52, 0,109,108, 95,102,108, 97,103, 0,100,105,102,102, 95,115,104, 97,100,101,114, 0,115,
+112,101, 99, 95,115,104, 97,100,101,114, 0,114,111,117,103,104,110,101,115,115, 0,114,101,102,114, 97, 99, 0,112, 97,114, 97,
+109, 91, 52, 93, 0,114,109,115, 0,100, 97,114,107,110,101,115,115, 0, 42,114, 97,109,112, 95, 99,111,108, 0, 42,114, 97,109,
+112, 95,115,112,101, 99, 0,114, 97,109,112,105,110, 95, 99,111,108, 0,114, 97,109,112,105,110, 95,115,112,101, 99, 0,114, 97,
+109,112, 98,108,101,110,100, 95, 99,111,108, 0,114, 97,109,112, 98,108,101,110,100, 95,115,112,101, 99, 0,114, 97,109,112, 95,
+115,104,111,119, 0,114, 97,109,112,102, 97, 99, 95, 99,111,108, 0,114, 97,109,112,102, 97, 99, 95,115,112,101, 99, 0, 42,110,
+111,100,101,116,114,101,101, 0, 42,103,114,111,117,112, 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,115,115,115, 95,114,
+ 97,100,105,117,115, 91, 51, 93, 0,115,115,115, 95, 99,111,108, 91, 51, 93, 0,115,115,115, 95,101,114,114,111,114, 0,115,115,
+115, 95,115, 99, 97,108,101, 0,115,115,115, 95,105,111,114, 0,115,115,115, 95, 99,111,108,102, 97, 99, 0,115,115,115, 95,116,
+101,120,102, 97, 99, 0,115,115,115, 95,102,114,111,110,116, 0,115,115,115, 95, 98, 97, 99,107, 0,115,115,115, 95,102,108, 97,
+103, 0,115,115,115, 95,112,114,101,115,101,116, 0, 89, 70, 95, 97,114, 0, 89, 70, 95, 97,103, 0, 89, 70, 95, 97, 98, 0, 89,
+ 70, 95,100,115, 99, 97,108,101, 0, 89, 70, 95,100,112,119,114, 0, 89, 70, 95,100,115,109,112, 0, 89, 70, 95,112,114,101,115,
+101,116, 0, 89, 70, 95,100,106,105,116, 0,103,112,117,109, 97,116,101,114,105, 97,108, 0,110, 97,109,101, 91, 50, 53, 54, 93,
+ 0,115, 99, 97,108,101, 0, 42, 98, 98, 0,105, 49, 0,106, 49, 0,107, 49, 0,105, 50, 0,106, 50, 0,107, 50, 0,115,101,108,
+ 99,111,108, 49, 0,115,101,108, 99,111,108, 50, 0,113,117, 97,116, 91, 52, 93, 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, 42,109, 97,116, 0, 42,105,109, 97,116, 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,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,119,101,105,103,
+104,116, 0,114, 97,100,105,117,115, 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,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,116,105,108,116, 95,105,110,116,101,114,112, 0, 99,104, 97,114,
+105,100,120, 0,107,101,114,110, 0,104, 0,110,117,114, 98, 0, 42, 98,101,118,111, 98,106, 0, 42,116, 97,112,101,114,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,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,114,
+101,115,111,108,117, 95,114,101,110, 0,114,101,115,111,108,118, 95,114,101,110, 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,119,111,114,100,
+115,112, 97, 99,101, 0,117,108,112,111,115, 0,117,108,104,101,105,103,104,116, 0,120,111,102, 0,121,111,102, 0,108,105,110,
+101,119,105,100,116,104, 0, 42,115,116,114, 0,102, 97,109,105,108,121, 91, 50, 52, 93, 0, 42,118,102,111,110,116, 0, 42,118,
+102,111,110,116, 98, 0, 42,118,102,111,110,116,105, 0, 42,118,102,111,110,116, 98,105, 0,115,101,112, 99,104, 97,114, 0,116,
+111,116, 98,111,120, 0, 97, 99,116, 98,111,120, 0, 42,116, 98, 0,115,101,108,115,116, 97,114,116, 0,115,101,108,101,110,100,
+ 0, 42,115,116,114,105,110,102,111, 0, 99,117,114,105,110,102,111, 0,101,102,102,101, 99,116, 0, 42,109,102, 97, 99,101, 0,
+ 42,109,116,102, 97, 99,101, 0, 42,116,102, 97, 99,101, 0, 42,109,118,101,114,116, 0, 42,109,101,100,103,101, 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,109,
+115,101,108,101, 99,116, 0,118,100, 97,116, 97, 0,101,100, 97,116, 97, 0,102,100, 97,116, 97, 0,116,111,116,101,100,103,101,
+ 0,116,111,116,102, 97, 99,101, 0,116,111,116,115,101,108,101, 99,116, 0, 97, 99,116, 95,102, 97, 99,101, 0, 99,117, 98,101,
+109, 97,112,115,105,122,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,115,117, 98,115,117,114,102,116,121,112,101, 0, 42,109,114, 0, 42,112,118, 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,117,110,119,114, 97,112, 0,
+118, 49, 0,118, 50, 0,118, 51, 0,118, 52, 0,101,100, 99,111,100,101, 0, 99,114,101, 97,115,101, 0, 98,119,101,105,103,104,
+116, 0,100,101,102, 95,110,114, 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,117,118, 91, 50, 93, 0, 99,111, 91, 50, 93, 0,105,110,100,101,120, 0,102, 0,105, 0,115, 91, 50, 53, 54, 93, 0,
+118, 91, 52, 93, 0,109,105,100, 0,112, 97,100, 91, 50, 93, 0,118, 91, 50, 93, 0, 42,102, 97, 99,101,115, 0, 42, 99,111,108,
+102, 97, 99,101,115, 0, 42,101,100,103,101,115, 0, 42,101,100,103,101, 95, 98,111,117,110,100, 97,114,121, 95,115,116, 97,116,
+101,115, 0, 42,118,101,114,116, 95,101,100,103,101, 95,109, 97,112, 0, 42,118,101,114,116, 95,102, 97, 99,101, 95,109, 97,112,
+ 0, 42,109, 97,112, 95,109,101,109, 0, 42,118,101,114,116,115, 0,108,101,118,101,108,115, 0,108,101,118,101,108, 95, 99,111,
+117,110,116, 0, 99,117,114,114,101,110,116, 0,110,101,119,108,118,108, 0,101,100,103,101,108,118,108, 0,112,105,110,108,118,
+108, 0,114,101,110,100,101,114,108,118,108, 0,117,115,101, 95, 99,111,108, 0, 42,101,100,103,101, 95,102,108, 97,103,115, 0,
+ 42,101,100,103,101, 95, 99,114,101, 97,115,101,115, 0, 42,118,101,114,116, 95,109, 97,112, 0, 42,101,100,103,101, 95,109, 97,
+112, 0, 42,111,108,100, 95,102, 97, 99,101,115, 0, 42,111,108,100, 95,101,100,103,101,115, 0, 42,101,114,114,111,114, 0,109,
+111,100,105,102,105,101,114, 0,115,117, 98,100,105,118, 84,121,112,101, 0,114,101,110,100,101,114, 76,101,118,101,108,115, 0,
+ 42,101,109, 67, 97, 99,104,101, 0, 42,109, 67, 97, 99,104,101, 0,100,101,102, 97,120,105,115, 0,112, 97,100, 91, 54, 93, 0,
+108,101,110,103,116,104, 0,114, 97,110,100,111,109,105,122,101, 0,115,101,101,100, 0, 42,115,116, 97,114,116, 95, 99, 97,112,
+ 0, 42,101,110,100, 95, 99, 97,112, 0, 42, 99,117,114,118,101, 95,111, 98, 0, 42,111,102,102,115,101,116, 95,111, 98, 0,111,
+102,102,115,101,116, 91, 51, 93, 0,115, 99, 97,108,101, 91, 51, 93, 0,109,101,114,103,101, 95,100,105,115,116, 0,102,105,116,
+ 95,116,121,112,101, 0,111,102,102,115,101,116, 95,116,121,112,101, 0, 99,111,117,110,116, 0, 97,120,105,115, 0,116,111,108,
+101,114, 97,110, 99,101, 0, 42,109,105,114,114,111,114, 95,111, 98, 0,115,112,108,105,116, 95, 97,110,103,108,101, 0,118, 97,
+108,117,101, 0,114,101,115, 0,118, 97,108, 95,102,108, 97,103,115, 0,108,105,109, 95,102,108, 97,103,115, 0,101, 95,102,108,
+ 97,103,115, 0, 98,101,118,101,108, 95, 97,110,103,108,101, 0,100,101,102,103,114,112, 95,110, 97,109,101, 91, 51, 50, 93, 0,
+ 42,116,101,120,116,117,114,101, 0,115,116,114,101,110,103,116,104, 0,100,105,114,101, 99,116,105,111,110, 0,109,105,100,108,
+101,118,101,108, 0,116,101,120,109, 97,112,112,105,110,103, 0, 42,109, 97,112, 95,111, 98,106,101, 99,116, 0,117,118,108, 97,
+121,101,114, 95,110, 97,109,101, 91, 51, 50, 93, 0,117,118,108, 97,121,101,114, 95,116,109,112, 0, 42,112,114,111,106,101, 99,
+116,111,114,115, 91, 49, 48, 93, 0, 42,105,109, 97,103,101, 0,110,117,109, 95,112,114,111,106,101, 99,116,111,114,115, 0, 97,
+115,112,101, 99,116,120, 0, 97,115,112,101, 99,116,121, 0,112,101,114, 99,101,110,116, 0,102, 97, 99,101, 67,111,117,110,116,
+ 0,102, 97, 99, 0,114,101,112,101, 97,116, 0, 42,111, 98,106,101, 99,116, 99,101,110,116,101,114, 0,115,116, 97,114,116,120,
+ 0,115,116, 97,114,116,121, 0,104,101,105,103,104,116, 0,110, 97,114,114,111,119, 0,115,112,101,101,100, 0,100, 97,109,112,
+ 0,102, 97,108,108,111,102,102, 0,116,105,109,101,111,102,102,115, 0,108,105,102,101,116,105,109,101, 0,100,101,102,111,114,
+109,102,108, 97,103, 0,109,117,108,116,105, 0, 42,112,114,101,118, 67,111,115, 0,112, 97,114,101,110,116,105,110,118, 91, 52,
+ 93, 91, 52, 93, 0, 99,101,110,116, 91, 51, 93, 0, 42,105,110,100,101,120, 97,114, 0,116,111,116,105,110,100,101,120, 0,102,
+111,114, 99,101, 0, 42, 99,108,111,116,104, 79, 98,106,101, 99,116, 0, 42,115,105,109, 95,112, 97,114,109,115, 0, 42, 99,111,
+108,108, 95,112, 97,114,109,115, 0, 42,112,111,105,110,116, 95, 99, 97, 99,104,101, 0, 42,120, 0, 42,120,110,101,119, 0, 42,
+120,111,108,100, 0, 42, 99,117,114,114,101,110,116, 95,120,110,101,119, 0, 42, 99,117,114,114,101,110,116, 95,120, 0, 42, 99,
+117,114,114,101,110,116, 95,118, 0, 42,109,102, 97, 99,101,115, 0,110,117,109,118,101,114,116,115, 0,110,117,109,102, 97, 99,
+101,115, 0, 97, 98,115,111,114,112,116,105,111,110, 0,116,105,109,101, 0, 42, 98,118,104,116,114,101,101, 0,111,112,101,114,
+ 97,116,105,111,110, 0,118,101,114,116,101,120, 0,116,111,116,105,110,102,108,117,101,110, 99,101, 0,103,114,105,100,115,105,
+122,101, 0,110,101,101,100, 98,105,110,100, 0, 42, 98,105,110,100,119,101,105,103,104,116,115, 0, 42, 98,105,110,100, 99,111,
+115, 0,116,111,116, 99, 97,103,101,118,101,114,116, 0, 42,100,121,110,103,114,105,100, 0, 42,100,121,110,105,110,102,108,117,
+101,110, 99,101,115, 0, 42,100,121,110,118,101,114,116,115, 0, 42,112, 97,100, 50, 0,100,121,110,103,114,105,100,115,105,122,
+101, 0,100,121,110, 99,101,108,108,109,105,110, 91, 51, 93, 0,100,121,110, 99,101,108,108,119,105,100,116,104, 0, 98,105,110,
+100,109, 97,116, 91, 52, 93, 91, 52, 93, 0, 42,112,115,121,115, 0, 42,100,109, 0,116,111,116,100,109,118,101,114,116, 0,116,
+111,116,100,109,101,100,103,101, 0,116,111,116,100,109,102, 97, 99,101, 0,112,115,121,115, 0,114,116, 91, 50, 93, 0, 42,102,
+ 97, 99,101,112, 97, 0,118,103,114,111,117,112, 0,112,114,111,116,101, 99,116, 0, 42,116, 97,114,103,101,116, 0, 42, 97,117,
+120, 84, 97,114,103,101,116, 0,118,103,114,111,117,112, 95,110, 97,109,101, 91, 51, 50, 93, 0,107,101,101,112, 68,105,115,116,
+ 0,115,104,114,105,110,107, 84,121,112,101, 0,115,104,114,105,110,107, 79,112,116,115, 0,112,114,111,106, 65,120,105,115, 0,
+115,117, 98,115,117,114,102, 76,101,118,101,108,115, 0,112,110,116,115,119, 0,111,112,110,116,115,117, 0,111,112,110,116,115,
+118, 0,111,112,110,116,115,119, 0,116,121,112,101,117, 0,116,121,112,101,118, 0,116,121,112,101,119, 0,102,117, 0,102,118,
+ 0,102,119, 0,100,117, 0,100,118, 0,100,119, 0, 42,100,101,102, 0,118,101, 99, 91, 56, 93, 91, 51, 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,116,114, 97, 99,107, 0, 42,112,114,111,120,121, 0, 42,112,114,111,120,121, 95,103,114,111,117,112, 0, 42,112,114,111,
+120,121, 95,102,114,111,109, 0, 42, 97, 99,116,105,111,110, 0, 42,112,111,115,101,108,105, 98, 0, 42,112,111,115,101, 0, 99,
+111,110,115,116,114, 97,105,110,116, 67,104, 97,110,110,101,108,115, 0,100,101,102, 98, 97,115,101, 0,109,111,100,105,102,105,
+101,114,115, 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,111, 98,109, 97,116, 91, 52, 93, 91, 52, 93, 0, 99,111,110,115,116,105,110,118, 91, 52, 93, 91, 52, 93, 0,
+108, 97,121, 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,110,108, 97,102,108, 97,103, 0,112,114,111,116,101, 99,116,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,114,100, 97,109,112,105,110,103, 0,115,105,122,101,102, 97, 99, 0,109, 97,114,103,
+105,110, 0,100,116, 0,100,116,120, 0, 97, 99,116, 99,111,108, 0,101,109,112,116,121, 95,100,114, 97,119,116,121,112,101, 0,
+112, 97,100, 49, 91, 51, 93, 0,101,109,112,116,121, 95,100,114, 97,119,115,105,122,101, 0,100,117,112,102, 97, 99,101,115, 99,
+ 97, 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, 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,115,111,102,116,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, 99,111,110,115,116,114, 97,105,110,116,115, 0,110,108, 97,115,116,114,105,112,115, 0,104,
+111,111,107,115, 0,112, 97,114,116,105, 99,108,101,115,121,115,116,101,109, 0, 42,112,100, 0, 42,115,111,102,116, 0, 42,100,
+117,112, 95,103,114,111,117,112, 0,102,108,117,105,100,115,105,109, 70,108, 97,103, 0,114,101,115,116,114,105, 99,116,102,108,
+ 97,103, 0,115,104, 97,112,101,110,114, 0,115,104, 97,112,101,102,108, 97,103, 0,114,101, 99, 97,108, 99,111, 0, 98,111,100,
+121, 95,116,121,112,101, 0, 42,102,108,117,105,100,115,105,109, 83,101,116,116,105,110,103,115, 0, 42,100,101,114,105,118,101,
+100, 68,101,102,111,114,109, 0, 42,100,101,114,105,118,101,100, 70,105,110, 97,108, 0,108, 97,115,116, 68, 97,116, 97, 77, 97,
+115,107, 0,115,116, 97,116,101, 0,105,110,105,116, 95,115,116, 97,116,101, 0,103,112,117,108, 97,109,112, 0, 99,117,114,105,
+110,100,101,120, 0, 97, 99,116,105,118,101, 0,100,101,102,108,101, 99,116, 0,102,111,114, 99,101,102,105,101,108,100, 0,112,
+100,101,102, 95,100, 97,109,112, 0,112,100,101,102, 95,114,100, 97,109,112, 0,112,100,101,102, 95,112,101,114,109, 0,112,100,
+101,102, 95,102,114,105, 99,116, 0,112,100,101,102, 95,114,102,114,105, 99,116, 0,102, 95,115,116,114,101,110,103,116,104, 0,
+102, 95,112,111,119,101,114, 0,102, 95,100,105,115,116, 0,102, 95,100, 97,109,112, 0,109, 97,120,100,105,115,116, 0,109,105,
+110,100,105,115,116, 0,109, 97,120,114, 97,100, 0,109,105,110,114, 97,100, 0,102, 95,112,111,119,101,114, 95,114, 0,112,100,
+101,102, 95,115, 98,100, 97,109,112, 0,112,100,101,102, 95,115, 98,105,102,116, 0,112,100,101,102, 95,115, 98,111,102,116, 0,
+ 99,108,117,109,112, 95,102, 97, 99, 0, 99,108,117,109,112, 95,112,111,119, 0,107,105,110,107, 95,102,114,101,113, 0,107,105,
+110,107, 95,115,104, 97,112,101, 0,107,105,110,107, 95, 97,109,112, 0,102,114,101,101, 95,101,110,100, 0,116,101,120, 95,110,
+ 97, 98,108, 97, 0,116,101,120, 95,109,111,100,101, 0,107,105,110,107, 0,107,105,110,107, 95, 97,120,105,115, 0,114,116, 50,
+ 0, 42,114,110,103, 0,102, 95,110,111,105,115,101, 0,115,105,109,102,114, 97,109,101, 0,115,116, 97,114,116,102,114, 97,109,
+101, 0,101,110,100,102,114, 97,109,101, 0,101,100,105,116,102,114, 97,109,101, 0, 42,112, 97,114,116,105, 99,108,101,115, 0,
+116,111,116,112,111,105,110,116, 0,116,111,116,115,112,114,105,110,103, 0, 42, 98,112,111,105,110,116, 0, 42, 98,115,112,114,
+105,110,103, 0,110,111,100,101,109, 97,115,115, 0,103,114, 97,118, 0,109,101,100,105, 97,102,114,105, 99,116, 0,114,107,108,
+105,109,105,116, 0,112,104,121,115,105, 99,115, 95,115,112,101,101,100, 0,103,111, 97,108,115,112,114,105,110,103, 0,103,111,
+ 97,108,102,114,105, 99,116, 0,109,105,110,103,111, 97,108, 0,109, 97,120,103,111, 97,108, 0,100,101,102,103,111, 97,108, 0,
+118,101,114,116,103,114,111,117,112, 0,102,117,122,122,121,110,101,115,115, 0,105,110,115,112,114,105,110,103, 0,105,110,102,
+114,105, 99,116, 0,101,102,114, 97, 0,105,110,116,101,114,118, 97,108, 0,108,111, 99, 97,108, 0,115,111,108,118,101,114,102,
+108, 97,103,115, 0, 42, 42,107,101,121,115, 0,116,111,116,112,111,105,110,116,107,101,121, 0,115,101, 99,111,110,100,115,112,
+114,105,110,103, 0, 99,111,108, 98, 97,108,108, 0, 98, 97,108,108,100, 97,109,112, 0, 98, 97,108,108,115,116,105,102,102, 0,
+115, 98, 99, 95,109,111,100,101, 0, 97,101,114,111,101,100,103,101, 0,109,105,110,108,111,111,112,115, 0,109, 97,120,108,111,
+111,112,115, 0, 99,104,111,107,101, 0,115,111,108,118,101,114, 95, 73, 68, 0,112,108, 97,115,116,105, 99, 0,115,112,114,105,
+110,103,112,114,101,108,111, 97,100, 0, 42,115, 99,114, 97,116, 99,104, 0,115,104,101, 97,114,115,116,105,102,102, 0,105,110,
+112,117,115,104, 0, 42,112,111,105,110,116, 99, 97, 99,104,101, 0,115,104,111,119, 95, 97,100,118, 97,110, 99,101,100,111,112,
+116,105,111,110,115, 0,114,101,115,111,108,117,116,105,111,110,120,121,122, 0,112,114,101,118,105,101,119,114,101,115,120,121,
+122, 0,114,101, 97,108,115,105,122,101, 0,103,117,105, 68,105,115,112,108, 97,121, 77,111,100,101, 0,114,101,110,100,101,114,
+ 68,105,115,112,108, 97,121, 77,111,100,101, 0,118,105,115, 99,111,115,105,116,121, 86, 97,108,117,101, 0,118,105,115, 99,111,
+115,105,116,121, 77,111,100,101, 0,118,105,115, 99,111,115,105,116,121, 69,120,112,111,110,101,110,116, 0,103,114, 97,118,120,
+ 0,103,114, 97,118,121, 0,103,114, 97,118,122, 0, 97,110,105,109, 83,116, 97,114,116, 0, 97,110,105,109, 69,110,100, 0,103,
+115,116, 97,114, 0,109, 97,120, 82,101,102,105,110,101, 0,105,110,105, 86,101,108,120, 0,105,110,105, 86,101,108,121, 0,105,
+110,105, 86,101,108,122, 0, 42,111,114,103, 77,101,115,104, 0, 42,109,101,115,104, 83,117,114,102, 97, 99,101, 0, 42,109,101,
+115,104, 66, 66, 0,115,117,114,102,100, 97,116, 97, 80, 97,116,104, 91, 50, 52, 48, 93, 0, 98, 98, 83,116, 97,114,116, 91, 51,
+ 93, 0, 98, 98, 83,105,122,101, 91, 51, 93, 0,116,121,112,101, 70,108, 97,103,115, 0,100,111,109, 97,105,110, 78,111,118,101,
+ 99,103,101,110, 0,118,111,108,117,109,101, 73,110,105,116, 84,121,112,101, 0,112, 97,114,116, 83,108,105,112, 86, 97,108,117,
+101, 0,103,101,110,101,114, 97,116,101, 84,114, 97, 99,101,114,115, 0,103,101,110,101,114, 97,116,101, 80, 97,114,116,105, 99,
+108,101,115, 0,115,117,114,102, 97, 99,101, 83,109,111,111,116,104,105,110,103, 0,115,117,114,102, 97, 99,101, 83,117, 98,100,
+105,118,115, 0,117,110,117,115,101,100, 68, 78, 65, 68,117,109,109,121, 0,112, 97,114,116,105, 99,108,101, 73,110,102, 83,105,
+122,101, 0,112, 97,114,116,105, 99,108,101, 73,110,102, 65,108,112,104, 97, 0,102, 97,114, 70,105,101,108,100, 83,105,122,101,
+ 0, 42,109,101,115,104, 83,117,114,102, 78,111,114,109, 97,108,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,101,120,112, 0,114, 97,110,103,
+101, 0,108,105,110,102, 97, 99, 0,108,111,103,102, 97, 99, 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,112,104,121,115,105, 99,115, 69,110,103,105,110,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, 97,111,100,105,
+115,116, 0, 97,111,100,105,115,116,102, 97, 99, 0, 97,111,101,110,101,114,103,121, 0, 97,111, 98,105, 97,115, 0, 97,111,109,
+111,100,101, 0, 97,111,115, 97,109,112, 0, 97,111,109,105,120, 0, 97,111, 99,111,108,111,114, 0, 97,111, 95, 97,100, 97,112,
+116, 95,116,104,114,101,115,104, 0, 97,111, 95, 97,100, 97,112,116, 95,115,112,101,101,100, 95,102, 97, 99, 0, 97,111, 95, 97,
+112,112,114,111,120, 95,101,114,114,111,114, 0, 97,111, 95, 97,112,112,114,111,120, 95, 99,111,114,114,101, 99,116,105,111,110,
+ 0, 97,111, 95,115, 97,109,112, 95,109,101,116,104,111,100, 0, 97,111, 95,103, 97,116,104,101,114, 95,109,101,116,104,111,100,
+ 0, 97,111, 95, 97,112,112,114,111,120, 95,112, 97,115,115,101,115, 0, 42, 97,111,115,112,104,101,114,101, 0, 42, 97,111,116,
+ 97, 98,108,101,115, 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,101,108, 99,111,
+108, 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, 97,118,105, 99,111,100,101, 99,110, 97,109,101, 91, 49, 50, 56, 93, 0, 42, 99,100, 80, 97,114,109,115, 0, 42,
+112, 97,100, 0, 99,100, 83,105,122,101, 0,113,116, 99,111,100,101, 99,110, 97,109,101, 91, 49, 50, 56, 93, 0, 99,111,100,101,
+ 99, 0, 97,117,100,105,111, 95, 99,111,100,101, 99, 0,118,105,100,101,111, 95, 98,105,116,114, 97,116,101, 0, 97,117,100,105,
+111, 95, 98,105,116,114, 97,116,101, 0,103,111,112, 95,115,105,122,101, 0,114, 99, 95,109,105,110, 95,114, 97,116,101, 0,114,
+ 99, 95,109, 97,120, 95,114, 97,116,101, 0,114, 99, 95, 98,117,102,102,101,114, 95,115,105,122,101, 0,109,117,120, 95,112, 97,
+ 99,107,101,116, 95,115,105,122,101, 0,109,117,120, 95,114, 97,116,101, 0,109,105,120,114, 97,116,101, 0,109, 97,105,110, 0,
+ 42,109, 97,116, 95,111,118,101,114,114,105,100,101, 0, 42,108,105,103,104,116, 95,111,118,101,114,114,105,100,101, 0,108, 97,
+121, 95,122,109, 97,115,107, 0,108, 97,121,102,108, 97,103, 0,112, 97,115,115,102,108, 97,103, 0,112, 97,115,115, 95,120,111,
+114, 0, 42, 97,118,105, 99,111,100,101, 99,100, 97,116, 97, 0, 42,113,116, 99,111,100,101, 99,100, 97,116, 97, 0,102,102, 99,
+111,100,101, 99,100, 97,116, 97, 0, 99,102,114, 97, 0,112,115,102,114, 97, 0,112,101,102,114, 97, 0,105,109, 97,103,101,115,
+ 0,102,114, 97,109, 97,112,116,111, 0,116,104,114,101, 97,100,115, 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, 97,116,116,114,105, 98, 0,114,116, 49, 0,
+115,116,101,114,101,111,109,111,100,101, 0,100,105,109,101,110,115,105,111,110,115,112,114,101,115,101,116, 0,109, 97,120,105,
+109,115,105,122,101, 0,120,115, 99,104, 0,121,115, 99,104, 0,120,112, 97,114,116,115, 0,121,112, 97,114,116,115, 0,119,105,
+110,112,111,115, 0,112,108, 97,110,101,115, 0,105,109,116,121,112,101, 0,115,117, 98,105,109,116,121,112,101, 0,113,117, 97,
+108,105,116,121, 0,114,112, 97,100, 0,114,112, 97,100, 49, 0,114,112, 97,100, 50, 0,115, 99,101,109,111,100,101, 0,114,101,
+110,100,101,114,101,114, 0,111, 99,114,101,115, 0, 97,108,112,104, 97,109,111,100,101, 0,111,115, 97, 0,102,114,115, 95,115,
+101, 99, 0,101,100,103,101,105,110,116, 0,115, 97,102,101,116,121, 0, 98,111,114,100,101,114, 0,100,105,115,112,114,101, 99,
+116, 0,108, 97,121,101,114,115, 0, 97, 99,116,108, 97,121, 0,120, 97,115,112, 0,121, 97,115,112, 0,102,114,115, 95,115,101,
+ 99, 95, 98, 97,115,101, 0,103, 97,117,115,115, 0,112,111,115,116,109,117,108, 0,112,111,115,116,103, 97,109,109, 97, 0,112,
+111,115,116,104,117,101, 0,112,111,115,116,115, 97,116, 0,100,105,116,104,101,114, 95,105,110,116,101,110,115,105,116,121, 0,
+ 98, 97,107,101, 95,111,115, 97, 0, 98, 97,107,101, 95,102,105,108,116,101,114, 0, 98, 97,107,101, 95,109,111,100,101, 0, 98,
+ 97,107,101, 95,102,108, 97,103, 0, 98, 97,107,101, 95,110,111,114,109, 97,108, 95,115,112, 97, 99,101, 0, 98, 97,107,101, 95,
+113,117, 97,100, 95,115,112,108,105,116, 0, 98, 97,107,101, 95,109, 97,120,100,105,115,116, 0, 98, 97,107,101, 95, 98,105, 97,
+115,100,105,115,116, 0, 98, 97,107,101, 95,112, 97,100, 0, 71, 73,113,117, 97,108,105,116,121, 0, 71, 73, 99, 97, 99,104,101,
+ 0, 71, 73,109,101,116,104,111,100, 0, 71, 73,112,104,111,116,111,110,115, 0, 71, 73,100,105,114,101, 99,116, 0, 89, 70, 95,
+ 65, 65, 0, 89, 70,101,120,112,111,114,116,120,109,108, 0, 89, 70, 95,110,111, 98,117,109,112, 0, 89, 70, 95, 99,108, 97,109,
+112,114,103, 98, 0,121,102,112, 97,100, 49, 0, 71, 73,100,101,112,116,104, 0, 71, 73, 99, 97,117,115,100,101,112,116,104, 0,
+ 71, 73,112,105,120,101,108,115,112,101,114,115, 97,109,112,108,101, 0, 71, 73,112,104,111,116,111,110, 99,111,117,110,116, 0,
+ 71, 73,109,105,120,112,104,111,116,111,110,115, 0, 71, 73,112,104,111,116,111,110,114, 97,100,105,117,115, 0, 89, 70, 95,114,
+ 97,121,100,101,112,116,104, 0, 89, 70, 95, 65, 65,112, 97,115,115,101,115, 0, 89, 70, 95, 65, 65,115, 97,109,112,108,101,115,
+ 0,121,102,112, 97,100, 50, 0, 71, 73,115,104, 97,100,111,119,113,117, 97,108,105,116,121, 0, 71, 73,114,101,102,105,110,101,
+109,101,110,116, 0, 71, 73,112,111,119,101,114, 0, 71, 73,105,110,100,105,114,112,111,119,101,114, 0, 89, 70, 95,103, 97,109,
+109, 97, 0, 89, 70, 95,101,120,112,111,115,117,114,101, 0, 89, 70, 95,114, 97,121, 98,105, 97,115, 0, 89, 70, 95, 65, 65,112,
+105,120,101,108,115,105,122,101, 0, 89, 70, 95, 65, 65,116,104,114,101,115,104,111,108,100, 0, 98, 97, 99,107, 98,117,102, 91,
+ 49, 54, 48, 93, 0,112,105, 99, 91, 49, 54, 48, 93, 0,115,116, 97,109,112, 0,115,116, 97,109,112, 95,102,111,110,116, 95,105,
+100, 0,115,116, 97,109,112, 95,117,100, 97,116, 97, 91, 49, 54, 48, 93, 0,102,103, 95,115,116, 97,109,112, 91, 52, 93, 0, 98,
+103, 95,115,116, 97,109,112, 91, 52, 93, 0,115,105,109,112,108,105,102,121, 95,115,117, 98,115,117,114,102, 0,115,105,109,112,
+108,105,102,121, 95,115,104, 97,100,111,119,115, 97,109,112,108,101,115, 0,115,105,109,112,108,105,102,121, 95,112, 97,114,116,
+105, 99,108,101,115, 0,115,105,109,112,108,105,102,121, 95, 97,111,115,115,115, 0, 99,105,110,101,111,110,119,104,105,116,101,
+ 0, 99,105,110,101,111,110, 98,108, 97, 99,107, 0, 99,105,110,101,111,110,103, 97,109,109, 97, 0,112, 97,114,116,105, 99,108,
+101, 95,112,101,114, 99, 0,115,117, 98,115,117,114,102, 95,109, 97,120, 0,115,104, 97,100, 98,117,102,115, 97,109,112,108,101,
+ 95,109, 97,120, 0, 97,111, 95,101,114,114,111,114, 0, 99,111,108, 91, 51, 93, 0,102,114, 97,109,101, 0,110, 97,109,101, 91,
+ 54, 52, 93, 0, 42, 98,114,117,115,104, 0,116,111,111,108, 0,115,116,101,112, 0,105,110,118,101,114,116, 0,116,111,116,114,
+101,107,101,121, 0,116,111,116, 97,100,100,107,101,121, 0, 98,114,117,115,104,116,121,112,101, 0, 98,114,117,115,104, 91, 55,
+ 93, 0,101,109,105,116,116,101,114,100,105,115,116, 0,100,114, 97,119, 95,116,105,109,101,100, 0,110, 97,109,101, 91, 51, 54,
+ 93, 0,109, 97,116, 91, 51, 93, 91, 51, 93, 0, 99,111,114,110,101,114,116,121,112,101, 0,101,100,105,116, 98,117,116,102,108,
+ 97,103, 0,106,111,105,110,116,114,105,108,105,109,105,116, 0,100,101,103,114, 0,116,117,114,110, 0,101,120,116,114, 95,111,
+102,102,115, 0,100,111,117, 98,108,105,109,105,116, 0,115,101,103,109,101,110,116,115, 0,114,105,110,103,115, 0,118,101,114,
+116,105, 99,101,115, 0,117,110,119,114, 97,112,112,101,114, 0,117,118, 99, 97,108, 99, 95,114, 97,100,105,117,115, 0,117,118,
+ 99, 97,108, 99, 95, 99,117, 98,101,115,105,122,101, 0,117,118, 99, 97,108, 99, 95,109, 97,112,100,105,114, 0,117,118, 99, 97,
+108, 99, 95,109, 97,112, 97,108,105,103,110, 0,117,118, 99, 97,108, 99, 95,102,108, 97,103, 0, 97,117,116,111,105,107, 95, 99,
+104, 97,105,110,108,101,110, 0,105,109, 97,112, 97,105,110,116, 0,112, 97,114,116,105, 99,108,101, 0,115,101,108,101, 99,116,
+ 95,116,104,114,101,115,104, 0, 99,108,101, 97,110, 95,116,104,114,101,115,104, 0,114,101,116,111,112,111, 95,109,111,100,101,
+ 0,114,101,116,111,112,111, 95,112, 97,105,110,116, 95,116,111,111,108, 0,108,105,110,101, 95,100,105,118, 0,101,108,108,105,
+112,115,101, 95,100,105,118, 0,114,101,116,111,112,111, 95,104,111,116,115,112,111,116, 0,109,117,108,116,105,114,101,115, 95,
+115,117, 98,100,105,118, 95,116,121,112,101, 0,115,107,103,101,110, 95,114,101,115,111,108,117,116,105,111,110, 0,115,107,103,
+101,110, 95,116,104,114,101,115,104,111,108,100, 95,105,110,116,101,114,110, 97,108, 0,115,107,103,101,110, 95,116,104,114,101,
+115,104,111,108,100, 95,101,120,116,101,114,110, 97,108, 0,115,107,103,101,110, 95,108,101,110,103,116,104, 95,114, 97,116,105,
+111, 0,115,107,103,101,110, 95,108,101,110,103,116,104, 95,108,105,109,105,116, 0,115,107,103,101,110, 95, 97,110,103,108,101,
+ 95,108,105,109,105,116, 0,115,107,103,101,110, 95, 99,111,114,114,101,108, 97,116,105,111,110, 95,108,105,109,105,116, 0,115,
+107,103,101,110, 95,115,121,109,109,101,116,114,121, 95,108,105,109,105,116, 0,115,107,103,101,110, 95,111,112,116,105,111,110,
+115, 0,115,107,103,101,110, 95,112,111,115,116,112,114,111, 0,115,107,103,101,110, 95,112,111,115,116,112,114,111, 95,112, 97,
+115,115,101,115, 0,115,107,103,101,110, 95,115,117, 98,100,105,118,105,115,105,111,110,115, 91, 51, 93, 0,101,100,103,101, 95,
+109,111,100,101, 0,112, 97,100, 51, 91, 52, 93, 0,100,105,114, 0,118,105,101,119, 0, 42,115,101,115,115,105,111,110, 0, 42,
+ 99,117,109, 97,112, 0,100,114, 97,119, 98,114,117,115,104, 0,115,109,111,111,116,104, 98,114,117,115,104, 0,112,105,110, 99,
+104, 98,114,117,115,104, 0,105,110,102,108, 97,116,101, 98,114,117,115,104, 0,103,114, 97, 98, 98,114,117,115,104, 0,108, 97,
+121,101,114, 98,114,117,115,104, 0,102,108, 97,116,116,101,110, 98,114,117,115,104, 0,112,105,118,111,116, 91, 51, 93, 0, 98,
+114,117,115,104, 95,116,121,112,101, 0,116,101,120,110,114, 0,116,101,120,114,101,112,116, 0,116,101,120,102, 97,100,101, 0,
+116,101,120,115,101,112, 0, 97,118,101,114, 97,103,105,110,103, 0,116, 97, 98,108,101,116, 95,115,105,122,101, 0,116, 97, 98,
+108,101,116, 95,115,116,114,101,110,103,116,104, 0,115,121,109,109, 0,114, 97,107,101, 0, 97,120,105,115,108,111, 99,107, 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, 99,117,114,115,111,114, 91, 51, 93, 0,116,119, 99,101,110,116, 91, 51, 93, 0,116,119,109,105,110, 91, 51, 93, 0,116,119,
+109, 97,120, 91, 51, 93, 0,101,100,105,116, 98,117,116,115,105,122,101, 0,115,101,108,101, 99,116,109,111,100,101, 0,112,114,
+111,112,111,114,116,105,111,110, 97,108, 0,112,114,111,112, 95,109,111,100,101, 0, 97,117,116,111,109,101,114,103,101, 0,112,
+ 97,100, 53, 0,112, 97,100, 54, 0,112, 97,100, 55, 0, 42,101,100, 0, 42,114, 97,100,105,111, 0,102,114, 97,109,105,110,103,
+ 0, 42,116,111,111,108,115,101,116,116,105,110,103,115, 0, 97,117,100,105,111, 0,116,114, 97,110,115,102,111,114,109, 95,115,
+112, 97, 99,101,115, 0,106,117,109,112,102,114, 97,109,101, 0,115,110, 97,112, 95,109,111,100,101, 0,115,110, 97,112, 95,102,
+108, 97,103, 0,115,110, 97,112, 95,116, 97,114,103,101,116, 0, 42,116,104,101, 68, 97,103, 0,100, 97,103,105,115,118, 97,108,
+105,100, 0,100, 97,103,102,108, 97,103,115, 0,115, 99,117,108,112,116,100, 97,116, 97, 0,102,114, 97,109,101, 95,115,116,101,
+112, 0,122,111,111,109, 0, 98,108,101,110,100, 0,120,105,109, 0,121,105,109, 0,115,112, 97, 99,101,116,121,112,101, 0, 98,
+108,111, 99,107,115, 99, 97,108,101, 0, 42, 97,114,101, 97, 0, 98,108,111, 99,107,104, 97,110,100,108,101,114, 91, 56, 93, 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,119,105,110,109, 97,116, 49, 91,
+ 52, 93, 91, 52, 93, 0,118,105,101,119,109, 97,116, 49, 91, 52, 93, 91, 52, 93, 0,118,105,101,119,113,117, 97,116, 91, 52, 93,
+ 0,122,102, 97, 99, 0,108, 97,121, 95,117,115,101,100, 0,112,101,114,115,112, 0, 42,111, 98, 95, 99,101,110,116,114,101, 0,
+ 42, 98,103,112,105, 99, 0, 42,108,111, 99, 97,108,118,100, 0, 42,114,105, 0, 42,114,101,116,111,112,111, 95,118,105,101,119,
+ 95,100, 97,116, 97, 0, 42,100,101,112,116,104,115, 0,111, 98, 95, 99,101,110,116,114,101, 95, 98,111,110,101, 91, 51, 50, 93,
+ 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,112,105,118,111,116, 95,108, 97,115,116, 0,103,114,105,100, 0,103,114,105,100,118,
+105,101,119, 0,112,105,120,115,105,122,101, 0,110,101, 97,114, 0,102, 97,114, 0, 99, 97,109,100,120, 0, 99, 97,109,100,121,
+ 0,103,114,105,100,108,105,110,101,115, 0,118,105,101,119, 98,117,116, 0,103,114,105,100,102,108, 97,103, 0,109,111,100,101,
+115,101,108,101, 99,116, 0,116,119,116,121,112,101, 0,116,119,109,111,100,101, 0,116,119,102,108, 97,103, 0,116,119,100,114,
+ 97,119,102,108, 97,103, 0,116,119,109, 97,116, 91, 52, 93, 91, 52, 93, 0, 99,108,105,112, 91, 52, 93, 91, 52, 93, 0, 42, 99,
+108,105,112, 98, 98, 0, 97,102,116,101,114,100,114, 97,119, 0,122, 98,117,102, 0,120,114, 97,121, 0,102,108, 97,103, 50, 0,
+103,114,105,100,115,117, 98,100,105,118, 0,110,100,111,102,109,111,100,101, 0,110,100,111,102,102,105,108,116,101,114, 0, 42,
+112,114,111,112,101,114,116,105,101,115, 95,115,116,111,114, 97,103,101, 0, 42,103,112,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,111,108,100,119,105,110,120, 0,111,108,100,119,105,110,121, 0, 99,117,114,115,111,114, 91, 50, 93,
+ 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, 97, 99,116,110,
+ 97,109,101, 91, 51, 50, 93, 0, 99,111,110,115,116,110, 97,109,101, 91, 51, 50, 93, 0, 98,111,110,101,110, 97,109,101, 91, 51,
+ 50, 93, 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,108,111, 99,
+107, 0,109,101,100,105, 97,110, 91, 51, 93, 0, 99,117,114,115,101,110,115, 0, 99,117,114, 97, 99,116, 0, 97,108,105,103,110,
+ 0,116, 97, 98,111, 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,
+102,114,111,109, 0,115,104,111,119,103,114,111,117,112, 0,109,111,100,101,108,116,121,112,101, 0,115, 99,114,105,112,116, 98,
+108,111, 99,107, 0,114,101, 95, 97,108,105,103,110, 0,111,108,100,107,101,121,112,114,101,115,115, 0,116, 97, 98, 91, 55, 93,
+ 0, 99,104, 97,110,115,104,111,119,110, 0,122,101, 98,114, 97, 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, 50, 52, 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,102, 95,102,112, 0,
+102,112, 95,115,116,114, 91, 56, 93, 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, 40, 42,114,101,116,117,114,110,102,
+117,110, 99, 95,101,118,101,110,116, 41, 40, 41, 0, 40, 42,114,101,116,117,114,110,102,117,110, 99, 95, 97,114,103,115, 41, 40,
+ 41, 0, 42, 97,114,103, 49, 0, 42, 97,114,103, 50, 0, 42,109,101,110,117,112, 0, 42,112,117,112,109,101,110,117, 0,111,111,
+112,115, 0,118,105,115,105,102,108, 97,103, 0,116,114,101,101, 0, 42,116,114,101,101,115,116,111,114,101, 0,115,101, 97,114,
+ 99,104, 95,115,116,114,105,110,103, 91, 51, 50, 93, 0,115,101, 97,114, 99,104, 95,116,115,101, 0,115,101, 97,114, 99,104, 95,
+102,108, 97,103,115, 0,100,111, 95, 0,111,117,116,108,105,110,101,118,105,115, 0,115,116,111,114,101,102,108, 97,103, 0,100,
+101,112,115, 95,102,108, 97,103,115, 0,105,109, 97,110,114, 0, 99,117,114,116,105,108,101, 0,105,109,116,121,112,101,110,114,
+ 0,100,116, 95,117,118, 0,115,116,105, 99,107,121, 0,100,116, 95,117,118,115,116,114,101,116, 99,104, 0,112, 97,100, 91, 53,
+ 93, 0, 99,101,110,116,120, 0, 99,101,110,116,121, 0, 97,117,116,111,115,110, 97,112, 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,
+115,104,111,119,108,105,110,101,110,114,115, 0,116, 97, 98,110,117,109, 98,101,114, 0, 99,117,114,114,116, 97, 98, 95,115,101,
+116, 0,115,104,111,119,115,121,110,116, 97,120, 0,111,118,101,114,119,114,105,116,101, 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,119,111,114,100,119,114, 97,112, 0,100,111,
+112,108,117,103,105,110,115, 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, 98,114,111,119,115,101,114, 99, 97,108,108, 98, 97, 99,107, 0, 42,112,121, 95,103,108,
+111, 98, 97,108,100,105, 99,116, 0,108, 97,115,116,115,112, 97, 99,101, 0,115, 99,114,105,112,116,110, 97,109,101, 91, 50, 53,
+ 54, 93, 0,115, 99,114,105,112,116, 97,114,103, 91, 50, 53, 54, 93, 0, 42,115, 99,114,105,112,116, 0, 42, 98,117,116, 95,114,
+101,102,115, 0,114,101,100,114, 97,119,115, 0, 42,105,100, 0, 97,115,112,101, 99,116, 0, 42, 99,117,114,102,111,110,116, 0,
+ 42,101,100,105,116,116,114,101,101, 0,116,114,101,101,116,121,112,101, 0, 42,102,105,108,101,115, 0, 97, 99,116,105,118,101,
+ 95,102,105,108,101, 0,110,117,109,116,105,108,101,115,120, 0,110,117,109,116,105,108,101,115,121, 0,115,101,108,115,116, 97,
+116,101, 0,118,105,101,119,114,101, 99,116, 0, 98,111,111,107,109, 97,114,107,114,101, 99,116, 0,115, 99,114,111,108,108,112,
+111,115, 0,115, 99,114,111,108,108,104,101,105,103,104,116, 0,115, 99,114,111,108,108, 97,114,101, 97, 0, 97, 99,116,105,118,
+101, 95, 98,111,111,107,109, 97,114,107, 0,112,114,118, 95,119, 0,112,114,118, 95,104, 0, 42,105,109,103, 0,111,117,116,108,
+105,110,101, 91, 52, 93, 0,110,101,117,116,114, 97,108, 91, 52, 93, 0, 97, 99,116,105,111,110, 91, 52, 93, 0,115,101,116,116,
+105,110,103, 91, 52, 93, 0,115,101,116,116,105,110,103, 49, 91, 52, 93, 0,115,101,116,116,105,110,103, 50, 91, 52, 93, 0,110,
+117,109, 91, 52, 93, 0,116,101,120,116,102,105,101,108,100, 91, 52, 93, 0,116,101,120,116,102,105,101,108,100, 95,104,105, 91,
+ 52, 93, 0,112,111,112,117,112, 91, 52, 93, 0,116,101,120,116, 91, 52, 93, 0,116,101,120,116, 95,104,105, 91, 52, 93, 0,109,
+101,110,117, 95, 98, 97, 99,107, 91, 52, 93, 0,109,101,110,117, 95,105,116,101,109, 91, 52, 93, 0,109,101,110,117, 95,104,105,
+108,105,116,101, 91, 52, 93, 0,109,101,110,117, 95,116,101,120,116, 91, 52, 93, 0,109,101,110,117, 95,116,101,120,116, 95,104,
+105, 91, 52, 93, 0, 98,117,116, 95,100,114, 97,119,116,121,112,101, 0,105, 99,111,110,102,105,108,101, 91, 56, 48, 93, 0, 98,
+ 97, 99,107, 91, 52, 93, 0,104,101, 97,100,101,114, 91, 52, 93, 0,112, 97,110,101,108, 91, 52, 93, 0,115,104, 97,100,101, 49,
+ 91, 52, 93, 0,115,104, 97,100,101, 50, 91, 52, 93, 0,104,105,108,105,116,101, 91, 52, 93, 0,103,114,105,100, 91, 52, 93, 0,
+119,105,114,101, 91, 52, 93, 0,115,101,108,101, 99,116, 91, 52, 93, 0,108, 97,109,112, 91, 52, 93, 0, 97, 99,116,105,118,101,
+ 91, 52, 93, 0,103,114,111,117,112, 91, 52, 93, 0,103,114,111,117,112, 95, 97, 99,116,105,118,101, 91, 52, 93, 0,116,114, 97,
+110,115,102,111,114,109, 91, 52, 93, 0,118,101,114,116,101,120, 91, 52, 93, 0,118,101,114,116,101,120, 95,115,101,108,101, 99,
+116, 91, 52, 93, 0,101,100,103,101, 91, 52, 93, 0,101,100,103,101, 95,115,101,108,101, 99,116, 91, 52, 93, 0,101,100,103,101,
+ 95,115,101, 97,109, 91, 52, 93, 0,101,100,103,101, 95,115,104, 97,114,112, 91, 52, 93, 0,101,100,103,101, 95,102, 97, 99,101,
+115,101,108, 91, 52, 93, 0,102, 97, 99,101, 91, 52, 93, 0,102, 97, 99,101, 95,115,101,108,101, 99,116, 91, 52, 93, 0,102, 97,
+ 99,101, 95,100,111,116, 91, 52, 93, 0,110,111,114,109, 97,108, 91, 52, 93, 0, 98,111,110,101, 95,115,111,108,105,100, 91, 52,
+ 93, 0, 98,111,110,101, 95,112,111,115,101, 91, 52, 93, 0,115,116,114,105,112, 91, 52, 93, 0,115,116,114,105,112, 95,115,101,
+108,101, 99,116, 91, 52, 93, 0, 99,102,114, 97,109,101, 91, 52, 93, 0,118,101,114,116,101,120, 95,115,105,122,101, 0,102, 97,
+ 99,101,100,111,116, 95,115,105,122,101, 0, 98,112, 97,100, 91, 50, 93, 0,115,121,110,116, 97,120,108, 91, 52, 93, 0,115,121,
+110,116, 97,120,110, 91, 52, 93, 0,115,121,110,116, 97,120, 98, 91, 52, 93, 0,115,121,110,116, 97,120,118, 91, 52, 93, 0,115,
+121,110,116, 97,120, 99, 91, 52, 93, 0,109,111,118,105,101, 91, 52, 93, 0,105,109, 97,103,101, 91, 52, 93, 0,115, 99,101,110,
+101, 91, 52, 93, 0, 97,117,100,105,111, 91, 52, 93, 0,101,102,102,101, 99,116, 91, 52, 93, 0,112,108,117,103,105,110, 91, 52,
+ 93, 0,116,114, 97,110,115,105,116,105,111,110, 91, 52, 93, 0,109,101,116, 97, 91, 52, 93, 0,101,100,105,116,109,101,115,104,
+ 95, 97, 99,116,105,118,101, 91, 52, 93, 0,104, 97,110,100,108,101, 95,118,101,114,116,101,120, 91, 52, 93, 0,104, 97,110,100,
+108,101, 95,118,101,114,116,101,120, 95,115,101,108,101, 99,116, 91, 52, 93, 0,104, 97,110,100,108,101, 95,118,101,114,116,101,
+120, 95,115,105,122,101, 0,104,112, 97,100, 91, 55, 93, 0,115,111,108,105,100, 91, 52, 93, 0,116,117,105, 0,116, 98,117,116,
+115, 0,116,118, 51,100, 0,116,102,105,108,101, 0,116,105,112,111, 0,116,105,110,102,111, 0,116,115,110,100, 0,116, 97, 99,
+116, 0,116,110,108, 97, 0,116,115,101,113, 0,116,105,109, 97, 0,116,105,109, 97,115,101,108, 0,116,101,120,116, 0,116,111,
+111,112,115, 0,116,116,105,109,101, 0,116,110,111,100,101, 0,116, 97,114,109, 91, 50, 48, 93, 0, 98,112, 97,100, 91, 52, 93,
+ 0, 98,112, 97,100, 49, 91, 52, 93, 0,115,112,101, 99, 91, 52, 93, 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, 49, 54, 48, 93, 0,102,111,110,116,100,105,114, 91, 49, 54, 48, 93, 0,114,101,110,
+100,101,114,100,105,114, 91, 49, 54, 48, 93, 0,116,101,120,116,117,100,105,114, 91, 49, 54, 48, 93, 0,112,108,117,103,116,101,
+120,100,105,114, 91, 49, 54, 48, 93, 0,112,108,117,103,115,101,113,100,105,114, 91, 49, 54, 48, 93, 0,112,121,116,104,111,110,
+100,105,114, 91, 49, 54, 48, 93, 0,115,111,117,110,100,100,105,114, 91, 49, 54, 48, 93, 0,121,102,101,120,112,111,114,116,100,
+105,114, 91, 49, 54, 48, 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,119,104,101,101,108,108,105,110,101,115, 99,114,111,108,108, 0,117,105,102,108, 97,103, 0,108, 97,110,103,117,
+ 97,103,101, 0,117,115,101,114,112,114,101,102, 0,118,105,101,119,122,111,111,109, 0, 99,111,110,115,111,108,101, 95, 98,117,
+102,102,101,114, 0, 99,111,110,115,111,108,101, 95,111,117,116, 0,109,105,120, 98,117,102,115,105,122,101, 0,102,111,110,116,
+115,105,122,101, 0,101,110, 99,111,100,105,110,103, 0,116,114, 97,110,115,111,112,116,115, 0,109,101,110,117,116,104,114,101,
+115,104,111,108,100, 49, 0,109,101,110,117,116,104,114,101,115,104,111,108,100, 50, 0,102,111,110,116,110, 97,109,101, 91, 50,
+ 53, 54, 93, 0,116,104,101,109,101,115, 0,117,110,100,111,115,116,101,112,115, 0,117,110,100,111,109,101,109,111,114,121, 0,
+103,112, 95,109, 97,110,104, 97,116,116,101,110,100,105,115,116, 0,103,112, 95,101,117, 99,108,105,100,101, 97,110,100,105,115,
+116, 0, 99,117,114,115,115,105,122,101, 0,116, 98, 95,108,101,102,116,109,111,117,115,101, 0,116, 98, 95,114,105,103,104,116,
+109,111,117,115,101, 0,108,105,103,104,116, 91, 51, 93, 0,116,119, 95,104,111,116,115,112,111,116, 0,116,119, 95,102,108, 97,
+103, 0,116,119, 95,104, 97,110,100,108,101,115,105,122,101, 0,116,119, 95,115,105,122,101, 0,116,101,120,116,105,109,101,111,
+117,116, 0,116,101,120, 99,111,108,108,101, 99,116,114, 97,116,101, 0,109,101,109, 99, 97, 99,104,101,108,105,109,105,116, 0,
+112,114,101,102,101,116, 99,104,102,114, 97,109,101,115, 0,102,114, 97,109,101,115,101,114,118,101,114,112,111,114,116, 0,112,
+ 97,100, 95,114,111,116, 95, 97,110,103,108,101, 0,111, 98, 99,101,110,116,101,114, 95,100,105, 97, 0,114,118,105,115,105,122,
+101, 0,114,118,105, 98,114,105,103,104,116, 0,114,101, 99,101,110,116, 95,102,105,108,101,115, 0,115,109,111,111,116,104, 95,
+118,105,101,119,116,120, 0,103,108,114,101,115,108,105,109,105,116, 0,110,100,111,102, 95,112, 97,110, 0,110,100,111,102, 95,
+114,111,116, 97,116,101, 0,112, 97,100,115, 91, 50, 93, 0,112, 97,100, 91, 56, 93, 0,118,101,114,115,101,109, 97,115,116,101,
+114, 91, 49, 54, 48, 93, 0,118,101,114,115,101,117,115,101,114, 91, 49, 54, 48, 93, 0,103,108, 97,108,112,104, 97, 99,108,105,
+112, 0, 97,117,116,111,107,101,121, 95,109,111,100,101, 0, 97,117,116,111,107,101,121, 95,102,108, 97,103, 0, 99,111, 98, 97,
+ 95,119,101,105,103,104,116, 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,101,110,100,120, 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,104, 97,110,100,108,101,114, 91, 56, 93, 0, 42,110,101,119,118, 0,118,101, 99, 0, 42,118, 49, 0, 42,118,
+ 50, 0,112, 97,110,101,108,110, 97,109,101, 91, 54, 52, 93, 0,116, 97, 98,110, 97,109,101, 91, 54, 52, 93, 0,100,114, 97,119,
+110, 97,109,101, 91, 54, 52, 93, 0,111,102,115,120, 0,111,102,115,121, 0, 99,111,110,116,114,111,108, 0,115,110, 97,112, 0,
+111,108,100, 95,111,102,115,120, 0,111,108,100, 95,111,102,115,121, 0,115,111,114,116, 99,111,117,110,116,101,114, 0, 42,112,
+ 97,110,101,108,116, 97, 98, 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,112, 97,110,101,108,115, 0,115,
+117, 98,118,115,116,114, 91, 52, 93, 0,115,117, 98,118,101,114,115,105,111,110, 0,112, 97,100,115, 0,109,105,110,118,101,114,
+115,105,111,110, 0,109,105,110,115,117, 98,118,101,114,115,105,111,110, 0,100,105,115,112,108, 97,121,109,111,100,101, 0, 42,
+ 99,117,114,115, 99,114,101,101,110, 0, 42, 99,117,114,115, 99,101,110,101, 0,102,105,108,101,102,108, 97,103,115, 0,103,108,
+111, 98, 97,108,102, 0,110, 97,109,101, 91, 56, 48, 93, 0, 42,105, 98,117,102, 0, 42,105, 98,117,102, 95, 99,111,109,112, 0,
+ 42,115,101, 49, 0, 42,115,101, 50, 0, 42,115,101, 51, 0,110,114, 0, 98,111,116,116,111,109, 0,114,105,103,104,116, 0,120,
+111,102,115, 0,121,111,102,115, 0,108,105,102,116, 91, 51, 93, 0,103, 97,109,109, 97, 91, 51, 93, 0,103, 97,105,110, 91, 51,
+ 93, 0,115, 97,116,117,114, 97,116,105,111,110, 0,100,105,114, 91, 49, 54, 48, 93, 0,100,111,110,101, 0,115,116, 97,114,116,
+115,116,105,108,108, 0,101,110,100,115,116,105,108,108, 0, 42,115,116,114,105,112,100, 97,116, 97, 0,111,114,120, 0,111,114,
+121, 0, 42, 99,114,111,112, 0, 42,116,114, 97,110,115,102,111,114,109, 0, 42, 99,111,108,111,114, 95, 98, 97,108, 97,110, 99,
+101, 0, 42,116,115,116,114,105,112,100, 97,116, 97, 0, 42,116,115,116,114,105,112,100, 97,116, 97, 95,115,116, 97,114,116,115,
+116,105,108,108, 0, 42,116,115,116,114,105,112,100, 97,116, 97, 95,101,110,100,115,116,105,108,108, 0, 42,105, 98,117,102, 95,
+115,116, 97,114,116,115,116,105,108,108, 0, 42,105, 98,117,102, 95,101,110,100,115,116,105,108,108, 0, 42,105,110,115,116, 97,
+110, 99,101, 95,112,114,105,118, 97,116,101, 95,100, 97,116, 97, 0, 42, 42, 99,117,114,114,101,110,116, 95,112,114,105,118, 97,
+116,101, 95,100, 97,116, 97, 0, 42,116,109,112, 0,115,116, 97,114,116,111,102,115, 0,101,110,100,111,102,115, 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, 97,110,105,109, 95,112,114,101,115,101,101,107, 0, 42,115,116,114,105,112, 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,
+111,117,110,100, 0, 42,104,100, 97,117,100,105,111, 0,108,101,118,101,108, 0,112, 97,110, 0, 99,117,114,112,111,115, 0,115,
+116,114,111, 98,101, 0, 42,101,102,102,101, 99,116,100, 97,116, 97, 0, 97,110,105,109, 95,115,116, 97,114,116,111,102,115, 0,
+ 97,110,105,109, 95,101,110,100,111,102,115, 0, 98,108,101,110,100, 95,109,111,100,101, 0, 98,108,101,110,100, 95,111,112, 97,
+ 99,105,116,121, 0, 42,111,108,100, 98, 97,115,101,112, 0, 42,112, 97,114,115,101,113, 0, 42,115,101,113, 98, 97,115,101,112,
+ 0,109,101,116, 97,115,116, 97, 99,107, 0,101,100,103,101, 87,105,100,116,104, 0,102,111,114,119, 97,114,100, 0,119,105,112,
+101,116,121,112,101, 0,102, 77,105,110,105, 0,102, 67,108, 97,109,112, 0,102, 66,111,111,115,116, 0,100, 68,105,115,116, 0,
+100, 81,117, 97,108,105,116,121, 0, 98, 78,111, 67,111,109,112, 0, 83, 99, 97,108,101,120, 73,110,105, 0, 83, 99, 97,108,101,
+121, 73,110,105, 0, 83, 99, 97,108,101,120, 70,105,110, 0, 83, 99, 97,108,101,121, 70,105,110, 0,120, 73,110,105, 0,120, 70,
+105,110, 0,121, 73,110,105, 0,121, 70,105,110, 0,114,111,116, 73,110,105, 0,114,111,116, 70,105,110, 0,105,110,116,101,114,
+112,111,108, 97,116,105,111,110, 0, 42,102,114, 97,109,101, 77, 97,112, 0,103,108,111, 98, 97,108, 83,112,101,101,100, 0,108,
+ 97,115,116, 86, 97,108,105,100, 70,114, 97,109,101, 0, 98,117,116,116,121,112,101, 0,117,115,101,114,106,105,116, 0,115,116,
+ 97, 0,116,111,116,112, 97,114,116, 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,118,101, 99,116,115,105,122,
+101, 0,109, 97,120,108,101,110, 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,111,109, 97,116, 0,116,105,109,101,116,101,120, 0,115,112,101,101,100,116,
+101,120, 0,102,108, 97,103, 50,110,101,103, 0,118,101,114,116,103,114,111,117,112, 95,118, 0,118,103,114,111,117,112,110, 97,
+109,101, 91, 51, 50, 93, 0,118,103,114,111,117,112,110, 97,109,101, 95,118, 91, 51, 50, 93, 0, 42,107,101,121,115, 0,109,105,
+110,102, 97, 99, 0,117,115,101,100, 0,117,115,101,100,101,108,101,109, 0,100,120, 0,100,121, 0,108,105,110,107, 0,111,116,
+121,112,101, 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,100,101,108, 97,121, 0,100,117,114, 97,116,105,111,110, 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,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,106,111,121,105,110,100,
+101,120, 0, 97,120,105,115,102, 0, 98,117,116,116,111,110, 0, 98,117,116,116,111,110,102, 0,104, 97,116, 0,104, 97,116,102,
+ 0,112,114,101, 99,105,115,105,111,110, 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,111, 0,115,116, 97,116,101, 95,
+109, 97,115,107, 0, 42, 97, 99,116, 0,102,114, 97,109,101, 80,114,111,112, 91, 51, 50, 93, 0, 98,108,101,110,100,105,110, 0,
+112,114,105,111,114,105,116,121, 0,101,110,100, 95,114,101,115,101,116, 0,115,116,114,105,100,101, 97,120,105,115, 0,115,116,
+114,105,100,101,108,101,110,103,116,104, 0,115,110,100,110,114, 0,112, 97,100, 49, 91, 50, 93, 0,109, 97,107,101, 99,111,112,
+121, 0, 99,111,112,121,109, 97,100,101, 0,112, 97,100, 50, 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, 97,110,103, 86,101,108,111, 99,105,116,121, 91, 51,
+ 93, 0,108,111, 99, 97,108,102,108, 97,103, 0,100,121,110, 95,111,112,101,114, 97,116,105,111,110, 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,109, 97,120, 0,118,105,115,105,102, 97, 99, 0,114,111,116,100, 97,109,112, 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,109, 97,116,112,114,111,112, 91, 51, 50, 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,105,110,116, 95, 97,114,103, 0,102,108,111, 97,116, 95, 97,114,103, 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,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,115,116,114,101, 97,109, 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,
+115,116,114,101, 97,109,108,101,110, 0, 99,104, 97,110,110,101,108,115, 0,104,105,103,104,112,114,105,111, 0,112, 97,100, 91,
+ 49, 48, 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,108, 97,109,112,114,101,110, 0,103,111, 98,106,101, 99,116, 0,100,117,112,
+108,105, 95,111,102,115, 91, 51, 93, 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, 98,111,110,101, 95,109, 97,116, 91, 51, 93, 91, 51, 93, 0, 97,114,109, 95,104,101, 97,100,
+ 91, 51, 93, 0, 97,114,109, 95,116, 97,105,108, 91, 51, 93, 0, 97,114,109, 95,109, 97,116, 91, 52, 93, 91, 52, 93, 0,120,119,
+105,100,116,104, 0,122,119,105,100,116,104, 0,101, 97,115,101, 49, 0,101, 97,115,101, 50, 0,114, 97,100, 95,104,101, 97,100,
+ 0,114, 97,100, 95,116, 97,105,108, 0, 98,111,110,101, 98, 97,115,101, 0, 99,104, 97,105,110, 98, 97,115,101, 0,112, 97,116,
+104,102,108, 97,103, 0,108, 97,121,101,114, 95,112,114,111,116,101, 99,116,101,100, 0,103,104,111,115,116,101,112, 0,103,104,
+111,115,116,115,105,122,101, 0,103,104,111,115,116,116,121,112,101, 0,112, 97,116,104,115,105,122,101, 0,103,104,111,115,116,
+115,102, 0,103,104,111,115,116,101,102, 0,112, 97,116,104,115,102, 0,112, 97,116,104,101,102, 0,112, 97,116,104, 98, 99, 0,
+112, 97,116,104, 97, 99, 0, 99,111,110,115,116,102,108, 97,103, 0,105,107,102,108, 97,103, 0,115,101,108,101, 99,116,102,108,
+ 97,103, 0, 97,103,114,112, 95,105,110,100,101,120, 0, 42, 98,111,110,101, 0, 42, 99,104,105,108,100, 0,105,107,116,114,101,
+101, 0, 42, 98, 95, 98,111,110,101, 95,109, 97,116,115, 0, 42,100,117, 97,108, 95,113,117, 97,116, 0, 42, 98, 95, 98,111,110,
+101, 95,100,117, 97,108, 95,113,117, 97,116,115, 0, 99,104, 97,110, 95,109, 97,116, 91, 52, 93, 91, 52, 93, 0,112,111,115,101,
+ 95,109, 97,116, 91, 52, 93, 91, 52, 93, 0,112,111,115,101, 95,104,101, 97,100, 91, 51, 93, 0,112,111,115,101, 95,116, 97,105,
+108, 91, 51, 93, 0,108,105,109,105,116,109,105,110, 91, 51, 93, 0,108,105,109,105,116,109, 97,120, 91, 51, 93, 0,115,116,105,
+102,102,110,101,115,115, 91, 51, 93, 0,105,107,115,116,114,101,116, 99,104, 0, 42, 99,117,115,116,111,109, 0, 99,104, 97,110,
+ 98, 97,115,101, 0,112,114,111,120,121, 95,108, 97,121,101,114, 0,115,116,114,105,100,101, 95,111,102,102,115,101,116, 91, 51,
+ 93, 0, 99,121, 99,108,105, 99, 95,111,102,102,115,101,116, 91, 51, 93, 0, 97,103,114,111,117,112,115, 0, 97, 99,116,105,118,
+101, 95,103,114,111,117,112, 0, 99,117,115,116,111,109, 67,111,108, 0, 99,115, 0, 42,103,114,112, 0,114,101,115,101,114,118,
+101,100, 49, 0,103,114,111,117,112,115, 0, 97, 99,116,105,118,101, 95,109, 97,114,107,101,114, 0, 97, 99,116,110,114, 0, 97,
+ 99,116,119,105,100,116,104, 0,116,105,109,101,115,108,105,100,101, 0,110, 97,109,101, 91, 51, 48, 93, 0,111,119,110,115,112,
+ 97, 99,101, 0,116, 97,114,115,112, 97, 99,101, 0,101,110,102,111,114, 99,101, 0,104,101, 97,100,116, 97,105,108, 0, 42,116,
+ 97,114, 0,115,117, 98,116, 97,114,103,101,116, 91, 51, 50, 93, 0,109, 97,116,114,105,120, 91, 52, 93, 91, 52, 93, 0,115,112,
+ 97, 99,101, 0, 42,112,114,111,112, 0,116, 97,114,110,117,109, 0,116, 97,114,103,101,116,115, 0,105,116,101,114, 97,116,105,
+111,110,115, 0,114,111,111,116, 98,111,110,101, 0,109, 97,120, 95,114,111,111,116, 98,111,110,101, 0, 42,112,111,108,101,116,
+ 97,114, 0,112,111,108,101,115,117, 98,116, 97,114,103,101,116, 91, 51, 50, 93, 0,112,111,108,101, 97,110,103,108,101, 0,111,
+114,105,101,110,116,119,101,105,103,104,116, 0,103,114, 97, 98,116, 97,114,103,101,116, 91, 51, 93, 0,114,101,115,101,114,118,
+101,100, 50, 0,109,105,110,109, 97,120,102,108, 97,103, 0,115,116,117, 99,107, 0, 99, 97, 99,104,101, 91, 51, 93, 0,108,111,
+ 99,107,102,108, 97,103, 0,102,111,108,108,111,119,102,108, 97,103, 0,118,111,108,109,111,100,101, 0,112,108, 97,110,101, 0,
+111,114,103,108,101,110,103,116,104, 0, 98,117,108,103,101, 0,112,105,118, 88, 0,112,105,118, 89, 0,112,105,118, 90, 0, 97,
+120, 88, 0, 97,120, 89, 0, 97,120, 90, 0,109,105,110, 76,105,109,105,116, 91, 54, 93, 0,109, 97,120, 76,105,109,105,116, 91,
+ 54, 93, 0,101,120,116,114, 97, 70,122, 0,105,110,118,109, 97,116, 91, 52, 93, 91, 52, 93, 0,102,114,111,109, 0,116,111, 0,
+109, 97,112, 91, 51, 93, 0,101,120,112,111, 0,102,114,111,109, 95,109,105,110, 91, 51, 93, 0,102,114,111,109, 95,109, 97,120,
+ 91, 51, 93, 0,116,111, 95,109,105,110, 91, 51, 93, 0,116,111, 95,109, 97,120, 91, 51, 93, 0,122,109,105,110, 0,122,109, 97,
+120, 0, 99,104, 97,110,110,101,108, 91, 51, 50, 93, 0,110,111, 95,114,111,116, 95, 97,120,105,115, 0,115,116,114,105,100,101,
+ 95, 97,120,105,115, 0, 99,117,114,109,111,100, 0, 97, 99,116,115,116, 97,114,116, 0, 97, 99,116,101,110,100, 0, 97, 99,116,
+111,102,102,115, 0,115,116,114,105,100,101,108,101,110, 0, 98,108,101,110,100,111,117,116, 0,115,116,114,105,100,101, 99,104,
+ 97,110,110,101,108, 91, 51, 50, 93, 0,111,102,102,115, 95, 98,111,110,101, 91, 51, 50, 93, 0,104, 97,115,105,110,112,117,116,
+ 0,104, 97,115,111,117,116,112,117,116, 0,100, 97,116, 97,116,121,112,101, 0,115,111, 99,107,101,116,116,121,112,101, 0, 42,
+110,101,119, 95,115,111, 99,107, 0,110,115, 0,108,105,109,105,116, 0,115,116, 97, 99,107, 95,105,110,100,101,120, 0,105,110,
+116,101,114,110, 0,115,116, 97, 99,107, 95,105,110,100,101,120, 95,101,120,116, 0,108,111, 99,120, 0,108,111, 99,121, 0,111,
+119,110, 95,105,110,100,101,120, 0,116,111, 95,105,110,100,101,120, 0, 42,116,111,115,111, 99,107, 0, 42,108,105,110,107, 0,
+ 42,110,101,119, 95,110,111,100,101, 0,117,115,101,114,110, 97,109,101, 91, 51, 50, 93, 0,108, 97,115,116,121, 0,111,117,116,
+112,117,116,115, 0, 42,115,116,111,114, 97,103,101, 0,109,105,110,105,119,105,100,116,104, 0, 99,117,115,116,111,109, 49, 0,
+ 99,117,115,116,111,109, 50, 0,110,101,101,100, 95,101,120,101, 99, 0,101,120,101, 99, 0,116,111,116,114, 0, 98,117,116,114,
+ 0,112,114,118,114, 0, 42,116,121,112,101,105,110,102,111, 0, 42,102,114,111,109,110,111,100,101, 0, 42,116,111,110,111,100,
+101, 0, 42,102,114,111,109,115,111, 99,107, 0,110,111,100,101,115, 0,108,105,110,107,115, 0, 42,115,116, 97, 99,107, 0, 42,
+116,104,114,101, 97,100,115,116, 97, 99,107, 0,105,110,105,116, 0,115,116, 97, 99,107,115,105,122,101, 0, 99,117,114, 95,105,
+110,100,101,120, 0, 97,108,108,116,121,112,101,115, 0, 42,111,119,110,116,121,112,101, 0, 42,115,101,108,105,110, 0, 42,115,
+101,108,111,117,116, 0, 40, 42,116,105,109,101, 99,117,114,115,111,114, 41, 40, 41, 0, 40, 42,115,116, 97,116,115, 95,100,114,
+ 97,119, 41, 40, 41, 0, 40, 42,116,101,115,116, 95, 98,114,101, 97,107, 41, 40, 41, 0, 99,121, 99,108,105, 99, 0,109,111,118,
+105,101, 0,115, 97,109,112,108,101,115, 0,109,105,110,115,112,101,101,100, 0,112,101,114, 99,101,110,116,120, 0,112,101,114,
+ 99,101,110,116,121, 0, 98,111,107,101,104, 0, 99,117,114,118,101,100, 0,105,109, 97,103,101, 95,105,110, 95,119,105,100,116,
+104, 0,105,109, 97,103,101, 95,105,110, 95,104,101,105,103,104,116, 0, 99,101,110,116,101,114, 95,120, 0, 99,101,110,116,101,
+114, 95,121, 0,115,112,105,110, 0,105,116,101,114, 0,119,114, 97,112, 0,115,105,103,109, 97, 95, 99,111,108,111,114, 0,115,
+105,103,109, 97, 95,115,112, 97, 99,101, 0,104,117,101, 0,115, 97,116, 0,116, 49, 0,116, 50, 0,116, 51, 0,102,115,116,114,
+101,110,103,116,104, 0,102, 97,108,112,104, 97, 0,107,101,121, 91, 52, 93, 0,120, 49, 0,120, 50, 0,121, 49, 0,121, 50, 0,
+ 99,111,108,110, 97,109,101, 91, 51, 50, 93, 0, 98,107,116,121,112,101, 0,114,111,116, 97,116,105,111,110, 0,112,114,101,118,
+105,101,119, 0,103, 97,109, 99,111, 0,110,111, 95,122, 98,117,102, 0,102,115,116,111,112, 0,109, 97,120, 98,108,117,114, 0,
+ 98,116,104,114,101,115,104, 0, 42,100,105, 99,116, 0, 42,110,111,100,101, 0, 97,110,103,108,101, 95,111,102,115, 0, 99,111,
+108,109,111,100, 0,109,105,120, 0,116,104,114,101,115,104,111,108,100, 0,102, 97,100,101, 0,109, 0, 99, 0,106,105,116, 0,
+112,114,111,106, 0,102,105,116, 0,115,104,111,114,116,121, 0,109,105,110,116, 97, 98,108,101, 0,109, 97,120,116, 97, 98,108,
+101, 0,101,120,116, 95,105,110, 91, 50, 93, 0,101,120,116, 95,111,117,116, 91, 50, 93, 0, 42, 99,117,114,118,101, 0, 42,116,
+ 97, 98,108,101, 0, 42,112,114,101,109,117,108,116, 97, 98,108,101, 0, 99,117,114,114, 0, 99,108,105,112,114, 0, 99,109, 91,
+ 52, 93, 0, 98,108, 97, 99,107, 91, 51, 93, 0,119,104,105,116,101, 91, 51, 93, 0, 98,119,109,117,108, 91, 51, 93, 0,115, 97,
+109,112,108,101, 91, 51, 93, 0,111,102,102,115,101,116, 91, 50, 93, 0,105,110,110,101,114,114, 97,100,105,117,115, 0,114, 97,
+116,101, 0,114,103, 98, 91, 51, 93, 0, 99,108,111,110,101, 0, 97, 99,116,105,118,101, 95,114,110,100, 0, 42,108, 97,121,101,
+114,115, 0,116,111,116,108, 97,121,101,114, 0,109, 97,120,108, 97,121,101,114, 0,116,111,116,115,105,122,101, 0, 42,112,111,
+111,108, 0,101,100,105,116,102,108, 97,103, 0,118,101,108, 91, 51, 93, 0,114,111,116, 91, 52, 93, 0, 97,118,101, 91, 51, 93,
+ 0,110,117,109, 0,112, 97,114,101,110,116, 0,112, 97, 91, 52, 93, 0,119, 91, 52, 93, 0,102,117,118, 91, 52, 93, 0,102,111,
+102,102,115,101,116, 0,114, 97,110,100, 91, 51, 93, 0, 42,115,116,105, 99,107, 95,111, 98, 0, 42,104, 97,105,114, 0,105, 95,
+114,111,116, 91, 52, 93, 0,114, 95,114,111,116, 91, 52, 93, 0,114, 95, 97,118,101, 91, 51, 93, 0,114, 95,118,101, 91, 51, 93,
+ 0,100,105,101,116,105,109,101, 0, 98, 97,110,107, 0,115,105,122,101,109,117,108, 0,110,117,109, 95,100,109, 99, 97, 99,104,
+101, 0, 98,112,105, 0, 97,108,105,118,101, 0,108,111,111,112, 0,100,105,115,116,114, 0,112,104,121,115,116,121,112,101, 0,
+114,111,116,109,111,100,101, 0, 97,118,101,109,111,100,101, 0,114,101, 97, 99,116,101,118,101,110,116, 0,100,114, 97,119, 0,
+100,114, 97,119, 95, 97,115, 0,100,114, 97,119, 95,115,105,122,101, 0, 99,104,105,108,100,116,121,112,101, 0,100,114, 97,119,
+ 95,115,116,101,112, 0,114,101,110, 95,115,116,101,112, 0,104, 97,105,114, 95,115,116,101,112, 0,107,101,121,115, 95,115,116,
+101,112, 0, 97,100, 97,112,116, 95, 97,110,103,108,101, 0, 97,100, 97,112,116, 95,112,105,120, 0,114,111,116,102,114,111,109,
+ 0,105,110,116,101,103,114, 97,116,111,114, 0,110, 98,101,116,119,101,101,110, 0, 98,111,105,100,110,101,105,103,104, 98,111,
+117,114,115, 0, 98, 98, 95, 97,108,105,103,110, 0, 98, 98, 95,117,118, 95,115,112,108,105,116, 0, 98, 98, 95, 97,110,105,109,
+ 0, 98, 98, 95,115,112,108,105,116, 95,111,102,102,115,101,116, 0, 98, 98, 95,116,105,108,116, 0, 98, 98, 95,114, 97,110,100,
+ 95,116,105,108,116, 0, 98, 98, 95,111,102,102,115,101,116, 91, 50, 93, 0,115,105,109,112,108,105,102,121, 95,102,108, 97,103,
+ 0,115,105,109,112,108,105,102,121, 95,114,101,102,115,105,122,101, 0,115,105,109,112,108,105,102,121, 95,114, 97,116,101, 0,
+115,105,109,112,108,105,102,121, 95,116,114, 97,110,115,105,116,105,111,110, 0,115,105,109,112,108,105,102,121, 95,118,105,101,
+119,112,111,114,116, 0,116,105,109,101,116,119,101, 97,107, 0,106,105,116,102, 97, 99, 0,107,101,121,101,100, 95,116,105,109,
+101, 0,101,102,102, 95,104, 97,105,114, 0,103,114,105,100, 95,114,101,115, 0,112, 97,114,116,102, 97, 99, 0,116, 97,110,102,
+ 97, 99, 0,116, 97,110,112,104, 97,115,101, 0,114,101, 97, 99,116,102, 97, 99, 0, 97,118,101,102, 97, 99, 0,112,104, 97,115,
+101,102, 97, 99, 0,114, 97,110,100,114,111,116,102, 97, 99, 0,114, 97,110,100,112,104, 97,115,101,102, 97, 99, 0,114, 97,110,
+100,115,105,122,101, 0,114,101, 97, 99,116,115,104, 97,112,101, 0, 97, 99, 99, 91, 51, 93, 0,100,114, 97,103,102, 97, 99, 0,
+ 98,114,111,119,110,102, 97, 99, 0,100, 97,109,112,102, 97, 99, 0, 97, 98,115,108,101,110,103,116,104, 0,114, 97,110,100,108,
+101,110,103,116,104, 0, 99,104,105,108,100, 95,110, 98,114, 0,114,101,110, 95, 99,104,105,108,100, 95,110, 98,114, 0,112, 97,
+114,101,110,116,115, 0, 99,104,105,108,100,115,105,122,101, 0, 99,104,105,108,100,114, 97,110,100,115,105,122,101, 0, 99,104,
+105,108,100,114, 97,100, 0, 99,104,105,108,100,102,108, 97,116, 0, 99,104,105,108,100,115,112,114,101, 97,100, 0, 99,108,117,
+109,112,102, 97, 99, 0, 99,108,117,109,112,112,111,119, 0,114,111,117,103,104, 49, 0,114,111,117,103,104, 49, 95,115,105,122,
+101, 0,114,111,117,103,104, 50, 0,114,111,117,103,104, 50, 95,115,105,122,101, 0,114,111,117,103,104, 50, 95,116,104,114,101,
+115, 0,114,111,117,103,104, 95,101,110,100, 0,114,111,117,103,104, 95,101,110,100, 95,115,104, 97,112,101, 0, 98,114, 97,110,
+ 99,104, 95,116,104,114,101,115, 0,100,114, 97,119, 95,108,105,110,101, 91, 50, 93, 0,109, 97,120, 95,118,101,108, 0,109, 97,
+120, 95,108, 97,116, 95, 97, 99, 99, 0,109, 97,120, 95,116, 97,110, 95, 97, 99, 99, 0, 97,118,101,114, 97,103,101, 95,118,101,
+108, 0, 98, 97,110,107,105,110,103, 0,109, 97,120, 95, 98, 97,110,107, 0,103,114,111,117,110,100,122, 0, 98,111,105,100,102,
+ 97, 99, 91, 56, 93, 0, 98,111,105,100,114,117,108,101, 91, 56, 93, 0, 42,101,102,102, 95,103,114,111,117,112, 0, 42,100,117,
+112, 95,111, 98, 0, 42, 98, 98, 95,111, 98, 0, 42,112,100, 50, 0, 42,112, 97,114,116, 0, 42,101,100,105,116, 0, 42, 42,112,
+ 97,116,104, 99, 97, 99,104,101, 0, 42, 42, 99,104,105,108,100, 99, 97, 99,104,101, 0,112, 97,116,104, 99, 97, 99,104,101, 98,
+117,102,115, 0, 99,104,105,108,100, 99, 97, 99,104,101, 98,117,102,115, 0, 42,116, 97,114,103,101,116, 95,111, 98, 0, 42,107,
+101,121,101,100, 95,111, 98, 0, 42,108, 97,116,116,105, 99,101, 0,101,102,102,101, 99,116,111,114,115, 0,114,101, 97, 99,116,
+101,118,101,110,116,115, 0,116,111,116, 99,104,105,108,100, 0,116,111,116, 99, 97, 99,104,101,100, 0,116,111,116, 99,104,105,
+108,100, 99, 97, 99,104,101, 0,116, 97,114,103,101,116, 95,112,115,121,115, 0,107,101,121,101,100, 95,112,115,121,115, 0,116,
+111,116,107,101,121,101,100, 0, 98, 97,107,101,115,112, 97, 99,101, 0, 98, 98, 95,117,118,110, 97,109,101, 91, 51, 93, 91, 51,
+ 50, 93, 0,118,103,114,111,117,112, 91, 49, 50, 93, 0,118,103, 95,110,101,103, 0,114,116, 51, 0, 42,114,101,110,100,101,114,
+100, 97,116, 97, 0, 42, 99, 97, 99,104,101, 0, 67,100,105,115, 0, 67,118,105, 0, 91, 51, 93, 0,115,116,114,117, 99,116,117,
+114, 97,108, 0, 98,101,110,100,105,110,103, 0,109, 97,120, 95, 98,101,110,100, 0,109, 97,120, 95,115,116,114,117, 99,116, 0,
+109, 97,120, 95,115,104,101, 97,114, 0, 97,118,103, 95,115,112,114,105,110,103, 95,108,101,110, 0,116,105,109,101,115, 99, 97,
+108,101, 0,101,102,102, 95,102,111,114, 99,101, 95,115, 99, 97,108,101, 0,101,102,102, 95,119,105,110,100, 95,115, 99, 97,108,
+101, 0,115,105,109, 95,116,105,109,101, 95,111,108,100, 0,115,116,101,112,115, 80,101,114, 70,114, 97,109,101, 0,112,114,101,
+114,111,108,108, 0,109, 97,120,115,112,114,105,110,103,108,101,110, 0,115,111,108,118,101,114, 95,116,121,112,101, 0,118,103,
+114,111,117,112, 95, 98,101,110,100, 0,118,103,114,111,117,112, 95,109, 97,115,115, 0,118,103,114,111,117,112, 95,115,116,114,
+117, 99,116, 0,112,114,101,115,101,116,115, 0, 42, 99,111,108,108,105,115,105,111,110, 95,108,105,115,116, 0,101,112,115,105,
+108,111,110, 0,115,101,108,102, 95,102,114,105, 99,116,105,111,110, 0,115,101,108,102,101,112,115,105,108,111,110, 0,115,101,
+108,102, 95,108,111,111,112, 95, 99,111,117,110,116, 0,108,111,111,112, 95, 99,111,117,110,116, 0,112,114,101,115,115,117,114,
+101, 0, 42,112,111,105,110,116,115, 0,116,111,116,112,111,105,110,116,115, 0,116,104,105, 99,107,110,101,115,115, 0,115,116,
+114,111,107,101,115, 0,102,114, 97,109,101,110,117,109, 0, 42, 97, 99,116,102,114, 97,109,101, 0,103,115,116,101,112, 0,105,
+110,102,111, 91, 49, 50, 56, 93, 0,115, 98,117,102,102,101,114, 95,115,105,122,101, 0,115, 98,117,102,102,101,114, 95,115,102,
+108, 97,103, 0, 42,115, 98,117,102,102,101,114, 0, 0, 0, 0, 84, 89, 80, 69, 0, 0, 1, 91, 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,110,107, 68, 97,116, 97, 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, 80,114,111,112,101,114,116,121, 68, 97,116, 97, 0, 73, 68, 80,
+114,111,112,101,114,116,121, 0, 73, 68, 0, 76,105, 98,114, 97,114,121, 0, 70,105,108,101, 68, 97,116, 97, 0, 80,114,101,118,
+105,101,119, 73,109, 97,103,101, 0, 73,112,111, 68,114,105,118,101,114, 0, 79, 98,106,101, 99,116, 0, 73,112,111, 67,117,114,
+118,101, 0, 66, 80,111,105,110,116, 0, 66,101,122, 84,114,105,112,108,101, 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, 77, 97,114,
+107,101,114, 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,
+ 85,115,101,114, 0, 73,109, 97,103,101, 0, 71, 80, 85, 84,101,120,116,117,114,101, 0, 97,110,105,109, 0, 82,101,110,100,101,
+114, 82,101,115,117,108,116, 0, 77, 84,101,120, 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, 73,109, 66,117,102, 0, 84,101,120, 77, 97,112,112,
+105,110,103, 0, 76, 97,109,112, 0, 67,117,114,118,101, 77, 97,112,112,105,110,103, 0, 87, 97,118,101, 0, 77, 97,116,101,114,
+105, 97,108, 0, 98, 78,111,100,101, 84,114,101,101, 0, 71,114,111,117,112, 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, 66,111,117,110,100, 66,111,120, 0, 77,101,116, 97, 66, 97,108,108, 0, 78,
+117,114, 98, 0, 67,104, 97,114, 73,110,102,111, 0, 84,101,120,116, 66,111,120, 0, 67,117,114,118,101, 0, 80, 97,116,104, 0,
+ 77,101,115,104, 0, 77, 70, 97, 99,101, 0, 77, 84, 70, 97, 99,101, 0, 84, 70, 97, 99,101, 0, 77, 86,101,114,116, 0, 77, 69,
+100,103,101, 0, 77, 68,101,102,111,114,109, 86,101,114,116, 0, 77, 67,111,108, 0, 77, 83,116,105, 99,107,121, 0, 77, 83,101,
+108,101, 99,116, 0, 67,117,115,116,111,109, 68, 97,116, 97, 0, 77,117,108,116,105,114,101,115, 0, 80, 97,114,116,105, 97,108,
+ 86,105,115,105, 98,105,108,105,116,121, 0, 77, 68,101,102,111,114,109, 87,101,105,103,104,116, 0, 77, 84,101,120, 80,111,108,
+121, 0, 77, 76,111,111,112, 85, 86, 0, 77, 76,111,111,112, 67,111,108, 0, 77, 70,108,111, 97,116, 80,114,111,112,101,114,116,
+121, 0, 77, 73,110,116, 80,114,111,112,101,114,116,121, 0, 77, 83,116,114,105,110,103, 80,114,111,112,101,114,116,121, 0, 79,
+114,105,103, 83,112, 97, 99,101, 70, 97, 99,101, 0, 77,117,108,116,105,114,101,115, 67,111,108, 0, 77,117,108,116,105,114,101,
+115, 67,111,108, 70, 97, 99,101, 0, 77,117,108,116,105,114,101,115, 70, 97, 99,101, 0, 77,117,108,116,105,114,101,115, 69,100,
+103,101, 0, 77,117,108,116,105,114,101,115, 76,101,118,101,108, 0, 77,117,108,116,105,114,101,115, 77, 97,112, 78,111,100,101,
+ 0, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 83,117, 98,115,117,114,102, 77,111,100,105,102,105,101,114, 68, 97,116,
+ 97, 0, 76, 97,116,116,105, 99,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 67,117,114,118,101, 77,111,100,105,102,
+105,101,114, 68, 97,116, 97, 0, 66,117,105,108,100, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 65,114,114, 97,121, 77,
+111,100,105,102,105,101,114, 68, 97,116, 97, 0, 77,105,114,114,111,114, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 69,
+100,103,101, 83,112,108,105,116, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 66,101,118,101,108, 77,111,100,105,102,105,
+101,114, 68, 97,116, 97, 0, 66, 77,101,115,104, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 68,105,115,112,108, 97, 99,
+101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 85, 86, 80,114,111,106,101, 99,116, 77,111,100,105,102,105,101,114, 68,
+ 97,116, 97, 0, 68,101, 99,105,109, 97,116,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 83,109,111,111,116,104, 77,
+111,100,105,102,105,101,114, 68, 97,116, 97, 0, 67, 97,115,116, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 87, 97,118,
+101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 65,114,109, 97,116,117,114,101, 77,111,100,105,102,105,101,114, 68, 97,
+116, 97, 0, 72,111,111,107, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 83,111,102,116, 98,111,100,121, 77,111,100,105,
+102,105,101,114, 68, 97,116, 97, 0, 67,108,111,116,104, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 67,108,111,116,104,
+ 0, 67,108,111,116,104, 83,105,109, 83,101,116,116,105,110,103,115, 0, 67,108,111,116,104, 67,111,108,108, 83,101,116,116,105,
+110,103,115, 0, 80,111,105,110,116, 67, 97, 99,104,101, 0, 67,111,108,108,105,115,105,111,110, 77,111,100,105,102,105,101,114,
+ 68, 97,116, 97, 0, 66, 86, 72, 84,114,101,101, 0, 66,111,111,108,101, 97,110, 77,111,100,105,102,105,101,114, 68, 97,116, 97,
+ 0, 77, 68,101,102, 73,110,102,108,117,101,110, 99,101, 0, 77, 68,101,102, 67,101,108,108, 0, 77,101,115,104, 68,101,102,111,
+114,109, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 80, 97,114,116,105, 99,108,101, 83,121,115,116,101,109, 77,111,100,
+105,102,105,101,114, 68, 97,116, 97, 0, 80, 97,114,116,105, 99,108,101, 83,121,115,116,101,109, 0, 68,101,114,105,118,101,100,
+ 77,101,115,104, 0, 80, 97,114,116,105, 99,108,101, 73,110,115,116, 97,110, 99,101, 77,111,100,105,102,105,101,114, 68, 97,116,
+ 97, 0, 69,120,112,108,111,100,101, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 83,104,114,105,110,107,119,114, 97,112,
+ 77,111,100,105,102,105,101,114, 68, 97,116, 97, 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, 80, 97,114,116, 68,101,102,108,101, 99,116, 0, 83,111,102,116,
+ 66,111,100,121, 0, 70,108,117,105,100,115,105,109, 83,101,116,116,105,110,103,115, 0, 79, 98, 72,111,111,107, 0, 82, 78, 71,
+ 0, 83, 66, 86,101,114,116,101,120, 0, 66,111,100,121, 80,111,105,110,116, 0, 66,111,100,121, 83,112,114,105,110,103, 0, 83,
+ 66, 83, 99,114, 97,116, 99,104, 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, 81,117,105, 99,107,116,105,109,101, 67,111,100,101, 99, 68, 97,116, 97, 0, 70, 70, 77,112,101,103,
+ 67,111,100,101, 99, 68, 97,116, 97, 0, 65,117,100,105,111, 68, 97,116, 97, 0, 83, 99,101,110,101, 82,101,110,100,101,114, 76,
+ 97,121,101,114, 0, 82,101,110,100,101,114, 68, 97,116, 97, 0, 82,101,110,100,101,114, 80,114,111,102,105,108,101, 0, 71, 97,
+109,101, 70,114, 97,109,105,110,103, 0, 84,105,109,101, 77, 97,114,107,101,114, 0, 73,109, 97,103,101, 80, 97,105,110,116, 83,
+101,116,116,105,110,103,115, 0, 66,114,117,115,104, 0, 80, 97,114,116,105, 99,108,101, 66,114,117,115,104, 68, 97,116, 97, 0,
+ 80, 97,114,116,105, 99,108,101, 69,100,105,116, 83,101,116,116,105,110,103,115, 0, 84,114, 97,110,115,102,111,114,109, 79,114,
+105,101,110,116, 97,116,105,111,110, 0, 84,111,111,108, 83,101,116,116,105,110,103,115, 0, 66,114,117,115,104, 68, 97,116, 97,
+ 0, 83, 99,117,108,112,116, 68, 97,116, 97, 0, 83, 99,117,108,112,116, 83,101,115,115,105,111,110, 0, 83, 99,101,110,101, 0,
+ 68, 97,103, 70,111,114,101,115,116, 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, 82,101,110,100,101,114, 73,110,102,111, 0, 82,101,116,111,112,111, 86,105,101,119, 68, 97,
+116, 97, 0, 86,105,101,119, 68,101,112,116,104,115, 0, 98, 71, 80,100, 97,116, 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, 84,114,101,101, 83,116,111,114,101, 0, 84,114,101,101, 83,116,111,114,101, 69,
+108,101,109, 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, 99,114,105,112,116, 0, 83,112, 97, 99,101, 83, 99,114,105,112,116, 0, 83,112, 97, 99,101, 84,105,109,101, 0, 83,
+112, 97, 99,101, 78,111,100,101, 0, 83,112, 97, 99,101, 73,109, 97, 83,101,108, 0, 70,105,108,101, 76,105,115,116, 0, 84,104,
+101,109,101, 85, 73, 0, 84,104,101,109,101, 83,112, 97, 99,101, 0, 84,104,101,109,101, 87,105,114,101, 67,111,108,111,114, 0,
+ 98, 84,104,101,109,101, 0, 83,111,108,105,100, 76,105,103,104,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, 80, 97,110,101,108, 0, 70,105,108,101, 71,108,111, 98,
+ 97,108, 0, 83,116,114,105,112, 69,108,101,109, 0, 84, 83,116,114,105,112, 69,108,101,109, 0, 83,116,114,105,112, 67,114,111,
+112, 0, 83,116,114,105,112, 84,114, 97,110,115,102,111,114,109, 0, 83,116,114,105,112, 67,111,108,111,114, 66, 97,108, 97,110,
+ 99,101, 0, 83,116,114,105,112, 80,114,111,120,121, 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, 98, 83,111,117,110,100, 0,104,100, 97,117,100,105,111, 0, 77,101,116, 97, 83,116, 97, 99,107, 0,
+ 69,100,105,116,105,110,103, 0, 87,105,112,101, 86, 97,114,115, 0, 71,108,111,119, 86, 97,114,115, 0, 84,114, 97,110,115,102,
+111,114,109, 86, 97,114,115, 0, 83,111,108,105,100, 67,111,108,111,114, 86, 97,114,115, 0, 83,112,101,101,100, 67,111,110,116,
+114,111,108, 86, 97,114,115, 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, 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, 65, 99,116,117, 97,116,111,114, 83,101,110,115,111,114, 0, 98, 68,101,108, 97,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, 74,111,
+121,115,116,105, 99,107, 83,101,110,115,111,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, 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, 84,119,111, 68, 70,105,
+108,116,101,114, 65, 99,116,117, 97,116,111,114, 0, 98, 80, 97,114,101,110,116, 65, 99,116,117, 97,116,111,114, 0, 98, 83,116,
+ 97,116,101, 65, 99,116,117, 97,116,111,114, 0, 70,114,101,101, 67, 97,109,101,114, 97, 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, 79, 98,
+106,101, 99,116, 0, 66,111,110,101, 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, 71,114,111,117,112, 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, 67,104, 97,110,110,101,108, 0, 98, 67,111,110,
+115,116,114, 97,105,110,116, 0, 98, 67,111,110,115,116,114, 97,105,110,116, 84, 97,114,103,101,116, 0, 98, 80,121,116,104,111,
+110, 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, 77,105,110, 77, 97,120, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 83,105,122,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, 76,111, 99,107, 84,114, 97,
+ 99,107, 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, 83,116,114,101,116, 99,104, 84,111, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 82,105,103,105,100, 66,111,
+100,121, 74,111,105,110,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 67,108, 97,109,112, 84,111, 67,111,110,115,116,114,
+ 97,105,110,116, 0, 98, 67,104,105,108,100, 79,102, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 84,114, 97,110,115,102,111,
+114,109, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 76,111, 99, 76,105,109,105,116, 67,111,110,115,116,114, 97,105,110,116,
+ 0, 98, 82,111,116, 76,105,109,105,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 83,105,122,101, 76,105,109,105,116, 67,
+111,110,115,116,114, 97,105,110,116, 0, 98, 68,105,115,116, 76,105,109,105,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98,
+ 65, 99,116,105,111,110, 77,111,100,105,102,105,101,114, 0, 98, 65, 99,116,105,111,110, 83,116,114,105,112, 0, 98, 78,111,100,
+101, 83,116, 97, 99,107, 0, 98, 78,111,100,101, 83,111, 99,107,101,116, 0, 98, 78,111,100,101, 76,105,110,107, 0, 98, 78,111,
+100,101, 0, 98, 78,111,100,101, 80,114,101,118,105,101,119, 0, 98, 78,111,100,101, 84,121,112,101, 0, 78,111,100,101, 73,109,
+ 97,103,101, 65,110,105,109, 0, 78,111,100,101, 66,108,117,114, 68, 97,116, 97, 0, 78,111,100,101, 68, 66,108,117,114, 68, 97,
+116, 97, 0, 78,111,100,101, 66,105,108, 97,116,101,114, 97,108, 66,108,117,114, 68, 97,116, 97, 0, 78,111,100,101, 72,117,101,
+ 83, 97,116, 0, 78,111,100,101, 73,109, 97,103,101, 70,105,108,101, 0, 78,111,100,101, 67,104,114,111,109, 97, 0, 78,111,100,
+101, 84,119,111, 88, 89,115, 0, 78,111,100,101, 84,119,111, 70,108,111, 97,116,115, 0, 78,111,100,101, 71,101,111,109,101,116,
+114,121, 0, 78,111,100,101, 86,101,114,116,101,120, 67,111,108, 0, 78,111,100,101, 68,101,102,111, 99,117,115, 0, 78,111,100,
+101, 83, 99,114,105,112,116, 68,105, 99,116, 0, 78,111,100,101, 71,108, 97,114,101, 0, 78,111,100,101, 84,111,110,101,109, 97,
+112, 0, 78,111,100,101, 76,101,110,115, 68,105,115,116, 0, 67,117,114,118,101, 77, 97,112, 80,111,105,110,116, 0, 67,117,114,
+118,101, 77, 97,112, 0, 66,114,117,115,104, 67,108,111,110,101, 0, 67,117,115,116,111,109, 68, 97,116, 97, 76, 97,121,101,114,
+ 0, 72, 97,105,114, 75,101,121, 0, 80, 97,114,116,105, 99,108,101, 75,101,121, 0, 67,104,105,108,100, 80, 97,114,116,105, 99,
+108,101, 0, 80, 97,114,116,105, 99,108,101, 68, 97,116, 97, 0, 80, 97,114,116,105, 99,108,101, 83,101,116,116,105,110,103,115,
+ 0, 80, 97,114,116,105, 99,108,101, 69,100,105,116, 0, 80, 97,114,116,105, 99,108,101, 67, 97, 99,104,101, 75,101,121, 0, 76,
+105,110,107, 78,111,100,101, 0, 98, 71, 80, 68,115,112,111,105,110,116, 0, 98, 71, 80, 68,115,116,114,111,107,101, 0, 98, 71,
+ 80, 68,102,114, 97,109,101, 0, 98, 71, 80, 68,108, 97,121,101,114, 0, 0, 0, 84, 76, 69, 78, 0, 1, 0, 1, 0, 2, 0, 2,
+ 0, 4, 0, 4, 0, 4, 0, 4, 0, 8, 0, 0, 0, 8, 0, 12, 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, 20, 0, 76, 0, 52, 2, 40, 0, 0, 0, 32, 0,140, 3, 68, 0, 92, 0, 36, 0, 56,
+ 0, 84, 0,112, 0,120, 0, 16, 0, 24, 0, 40, 0,120, 0, 20, 0,132, 0, 32, 1,128, 0, 0, 0, 0, 0, 0, 0,136, 1, 4,
+ 1, 84, 0, 24, 3, 8, 0,168, 0, 0, 0,132, 1,120, 1, 8, 0, 56, 2,108, 0,124, 0, 76, 1, 68, 0, 0, 0,108, 0,104,
+ 0,136, 0, 56, 0, 8, 0, 16, 1, 56, 0, 0, 1, 24, 0, 20, 0, 44, 0, 60, 0, 24, 0, 12, 0, 12, 0, 4, 0, 8, 0, 8,
+ 0, 24, 0, 76, 0, 32, 0, 8, 0, 12, 0, 8, 0, 8, 0, 4, 0, 4, 1, 0, 0, 32, 0, 16, 0, 64, 0, 24, 0, 12, 0, 56,
+ 0, 0, 0, 52, 0, 68, 0, 88, 0, 96, 0, 68, 0,116, 0, 64, 0, 60, 0,108, 0, 60, 0,148, 0,152, 0, 60, 0, 92, 0,104,
+ 0,184, 0,100, 0,180, 0, 52, 0, 68, 0, 0, 0,132, 0, 28, 0, 20, 0,100, 0, 0, 0, 64, 0, 8, 0, 8, 0,216, 0, 76,
+ 1, 64, 0, 0, 0, 64, 0, 64, 0,108, 0,116, 0, 40, 0, 84, 0, 56, 0,128, 0,152, 1,132, 0,208, 0, 0, 0, 16, 0, 0,
+ 0, 0, 0, 0, 1,100, 0, 40, 0, 28, 0,176, 0,144, 0, 52, 0, 16, 0, 72, 3,180, 0, 56, 0, 16, 0, 80, 0, 12, 0,184,
+ 0, 8, 0, 72, 0, 80, 0,188, 0, 8, 0,168, 0, 0, 5, 96, 0, 0, 0, 60, 3, 4, 0, 36, 0,204, 0, 0, 0, 0, 0, 0,
+ 0, 20, 0,136, 0, 36, 1, 88, 0,220, 0,200, 1,200, 0, 0, 0, 0, 1, 8, 0, 12, 0, 12, 1, 8, 0,180, 0,128, 2, 80,
+ 0, 36, 0,164, 0,220, 2,132, 0, 0, 0,152, 0,208, 0, 16, 14, 56, 0, 56, 12, 32, 0,120, 0, 20, 0, 24, 0,228, 0, 32,
+ 0, 80, 0, 28, 0, 16, 0, 8, 0, 52, 0,160, 0,240, 1,168, 0,204, 1, 28, 0, 0, 0, 16, 0, 28, 0, 12, 0, 24, 0, 48,
+ 0, 16, 0, 20, 0, 16, 0, 24, 1, 56, 0, 0, 0, 56, 0, 44, 0, 64, 0, 48, 0, 8, 0, 44, 0, 72, 0,104, 0, 40, 0, 8,
+ 0, 72, 0, 44, 0, 40, 0,108, 0, 68, 0, 76, 0, 80, 0, 64, 0,128, 0, 4, 0, 60, 0, 12, 0, 92, 0, 28, 0, 20, 0, 80,
+ 0, 16, 0, 76, 0,104, 0, 52, 0, 28, 0, 96, 0, 60, 0, 56, 0,108, 0,140, 0, 4, 0, 20, 0, 12, 0, 8, 0, 40, 0, 0,
+ 0, 68, 0,176, 0, 24, 1, 4, 0,116, 1,152, 0, 72, 0, 64, 0,192, 0, 44, 0, 64, 0,116, 0, 60, 0,104, 0, 52, 0, 44,
+ 0, 44, 0, 68, 0, 44, 0, 64, 0, 44, 0, 20, 0, 52, 0, 96, 0, 12, 0,108, 0, 92, 0, 28, 0, 28, 0, 28, 0, 52, 0, 60,
+ 0,140, 0, 36, 0,120, 0, 24, 0,196, 0, 0, 0, 0, 0, 16, 0, 40, 0, 28, 0, 12, 0, 12, 1, 16, 0, 40, 0, 8, 0, 8,
+ 0, 64, 0, 32, 0, 24, 0, 8, 0, 24, 0, 32, 0, 8, 0, 12, 0, 44, 0, 20, 0, 60, 0, 24, 0, 56, 0, 72, 0,196, 1,224,
+ 0, 0, 0, 0, 0, 0, 0, 16, 0, 20, 0, 24, 0,172, 0, 0, 83, 84, 82, 67, 0, 0, 1, 50, 0, 10, 0, 2, 0, 10, 0, 0,
+ 0, 10, 0, 1, 0, 11, 0, 3, 0, 11, 0, 0, 0, 11, 0, 1, 0, 9, 0, 2, 0, 12, 0, 2, 0, 9, 0, 3, 0, 9, 0, 4,
+ 0, 13, 0, 2, 0, 2, 0, 5, 0, 2, 0, 6, 0, 14, 0, 2, 0, 4, 0, 5, 0, 4, 0, 6, 0, 15, 0, 2, 0, 7, 0, 5,
+ 0, 7, 0, 6, 0, 16, 0, 2, 0, 8, 0, 5, 0, 8, 0, 6, 0, 17, 0, 3, 0, 4, 0, 5, 0, 4, 0, 6, 0, 4, 0, 7,
+ 0, 18, 0, 3, 0, 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 7, 0, 19, 0, 3, 0, 8, 0, 5, 0, 8, 0, 6, 0, 8, 0, 7,
+ 0, 20, 0, 4, 0, 4, 0, 5, 0, 4, 0, 6, 0, 4, 0, 7, 0, 4, 0, 8, 0, 21, 0, 4, 0, 7, 0, 5, 0, 7, 0, 6,
+ 0, 7, 0, 7, 0, 7, 0, 8, 0, 22, 0, 4, 0, 8, 0, 5, 0, 8, 0, 6, 0, 8, 0, 7, 0, 8, 0, 8, 0, 23, 0, 4,
+ 0, 4, 0, 9, 0, 4, 0, 10, 0, 4, 0, 11, 0, 4, 0, 12, 0, 24, 0, 4, 0, 7, 0, 9, 0, 7, 0, 10, 0, 7, 0, 11,
+ 0, 7, 0, 12, 0, 25, 0, 4, 0, 9, 0, 13, 0, 12, 0, 14, 0, 4, 0, 15, 0, 4, 0, 16, 0, 26, 0, 10, 0, 26, 0, 0,
+ 0, 26, 0, 1, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 19, 0, 2, 0, 20, 0, 4, 0, 21, 0, 25, 0, 22, 0, 4, 0, 23,
+ 0, 4, 0, 24, 0, 27, 0, 9, 0, 9, 0, 0, 0, 9, 0, 1, 0, 27, 0, 25, 0, 28, 0, 26, 0, 0, 0, 27, 0, 2, 0, 28,
+ 0, 2, 0, 20, 0, 4, 0, 29, 0, 26, 0, 30, 0, 28, 0, 8, 0, 27, 0, 31, 0, 27, 0, 32, 0, 29, 0, 33, 0, 0, 0, 34,
+ 0, 0, 0, 35, 0, 4, 0, 36, 0, 4, 0, 37, 0, 28, 0, 38, 0, 30, 0, 6, 0, 4, 0, 39, 0, 4, 0, 40, 0, 2, 0, 41,
+ 0, 2, 0, 42, 0, 2, 0, 43, 0, 4, 0, 44, 0, 31, 0, 6, 0, 32, 0, 45, 0, 2, 0, 46, 0, 2, 0, 47, 0, 2, 0, 18,
+ 0, 2, 0, 20, 0, 0, 0, 48, 0, 33, 0, 21, 0, 33, 0, 0, 0, 33, 0, 1, 0, 34, 0, 49, 0, 35, 0, 50, 0, 24, 0, 51,
+ 0, 24, 0, 52, 0, 2, 0, 46, 0, 2, 0, 47, 0, 2, 0, 53, 0, 2, 0, 54, 0, 2, 0, 55, 0, 2, 0, 56, 0, 2, 0, 20,
+ 0, 2, 0, 57, 0, 7, 0, 11, 0, 7, 0, 12, 0, 4, 0, 58, 0, 7, 0, 59, 0, 7, 0, 60, 0, 7, 0, 61, 0, 31, 0, 62,
+ 0, 36, 0, 7, 0, 27, 0, 31, 0, 12, 0, 63, 0, 24, 0, 64, 0, 2, 0, 46, 0, 2, 0, 65, 0, 2, 0, 66, 0, 2, 0, 37,
+ 0, 37, 0, 16, 0, 37, 0, 0, 0, 37, 0, 1, 0, 7, 0, 67, 0, 7, 0, 61, 0, 2, 0, 18, 0, 2, 0, 47, 0, 2, 0, 68,
+ 0, 2, 0, 20, 0, 4, 0, 69, 0, 4, 0, 70, 0, 9, 0, 2, 0, 7, 0, 71, 0, 0, 0, 17, 0, 0, 0, 72, 0, 7, 0, 73,
+ 0, 7, 0, 74, 0, 38, 0, 12, 0, 27, 0, 31, 0, 37, 0, 75, 0, 0, 0, 76, 0, 4, 0, 77, 0, 7, 0, 61, 0, 12, 0, 78,
+ 0, 36, 0, 79, 0, 27, 0, 80, 0, 2, 0, 18, 0, 2, 0, 81, 0, 2, 0, 82, 0, 2, 0, 20, 0, 39, 0, 5, 0, 27, 0, 83,
+ 0, 2, 0, 84, 0, 2, 0, 85, 0, 2, 0, 86, 0, 4, 0, 37, 0, 40, 0, 6, 0, 40, 0, 0, 0, 40, 0, 1, 0, 0, 0, 87,
+ 0, 0, 0, 88, 0, 4, 0, 23, 0, 4, 0, 89, 0, 41, 0, 10, 0, 41, 0, 0, 0, 41, 0, 1, 0, 4, 0, 90, 0, 4, 0, 91,
+ 0, 4, 0, 92, 0, 4, 0, 43, 0, 4, 0, 14, 0, 4, 0, 93, 0, 0, 0, 94, 0, 0, 0, 95, 0, 42, 0, 15, 0, 27, 0, 31,
+ 0, 0, 0, 96, 0, 4, 0, 93, 0, 4, 0, 97, 0, 12, 0, 98, 0, 40, 0, 99, 0, 40, 0,100, 0, 4, 0,101, 0, 4, 0,102,
+ 0, 12, 0,103, 0, 0, 0,104, 0, 4, 0,105, 0, 4, 0,106, 0, 9, 0,107, 0, 8, 0,108, 0, 43, 0, 5, 0, 4, 0,109,
+ 0, 4, 0,110, 0, 4, 0, 93, 0, 4, 0, 37, 0, 9, 0, 2, 0, 44, 0, 20, 0, 27, 0, 31, 0, 2, 0, 18, 0, 2, 0, 20,
+ 0, 7, 0,111, 0, 7, 0,112, 0, 7, 0,113, 0, 7, 0,114, 0, 7, 0,115, 0, 7, 0,116, 0, 7, 0,117, 0, 7, 0,118,
+ 0, 7, 0,119, 0, 7, 0,120, 0, 7, 0,121, 0, 2, 0,122, 0, 2, 0,123, 0, 7, 0,124, 0, 36, 0, 79, 0, 39, 0,125,
+ 0, 32, 0,126, 0, 45, 0, 12, 0, 4, 0,127, 0, 4, 0,128, 0, 4, 0,129, 0, 4, 0,130, 0, 2, 0,131, 0, 2, 0,132,
+ 0, 2, 0, 20, 0, 2, 0,133, 0, 2, 0,134, 0, 2, 0,135, 0, 2, 0,136, 0, 2, 0,137, 0, 46, 0, 32, 0, 27, 0, 31,
+ 0, 0, 0, 34, 0, 12, 0,138, 0, 47, 0,139, 0, 48, 0,140, 0, 49, 0,141, 0, 2, 0,133, 0, 2, 0, 20, 0, 2, 0,142,
+ 0, 2, 0, 18, 0, 2, 0, 37, 0, 2, 0, 43, 0, 4, 0,143, 0, 2, 0,144, 0, 2, 0,145, 0, 2, 0,146, 0, 2, 0,147,
+ 0, 2, 0,148, 0, 2, 0,149, 0, 4, 0,150, 0, 4, 0,151, 0, 43, 0,152, 0, 30, 0,153, 0, 7, 0,154, 0, 4, 0,155,
+ 0, 2, 0,156, 0, 2, 0,157, 0, 2, 0,158, 0, 2, 0,159, 0, 7, 0,160, 0, 7, 0,161, 0, 9, 0,162, 0, 50, 0, 30,
+ 0, 2, 0,163, 0, 2, 0,164, 0, 2, 0,165, 0, 2, 0,166, 0, 32, 0,167, 0, 51, 0,168, 0, 0, 0,169, 0, 0, 0,170,
+ 0, 0, 0,171, 0, 0, 0,172, 0, 0, 0,173, 0, 7, 0,174, 0, 7, 0,175, 0, 2, 0,176, 0, 2, 0,177, 0, 2, 0,178,
+ 0, 2, 0,179, 0, 2, 0,180, 0, 2, 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, 57, 0, 7, 0,187, 0, 7, 0,188, 0, 7, 0,189, 0, 7, 0,190, 0, 7, 0,191, 0, 52, 0, 15, 0, 0, 0,192,
+ 0, 9, 0,193, 0, 0, 0,194, 0, 0, 0,195, 0, 4, 0,196, 0, 4, 0,197, 0, 9, 0,198, 0, 7, 0,199, 0, 7, 0,200,
+ 0, 7, 0,201, 0, 4, 0,202, 0, 9, 0,203, 0, 9, 0,204, 0, 4, 0,205, 0, 4, 0, 37, 0, 53, 0, 6, 0, 7, 0,182,
+ 0, 7, 0,183, 0, 7, 0,184, 0, 7, 0,206, 0, 7, 0, 67, 0, 4, 0, 64, 0, 54, 0, 5, 0, 2, 0, 20, 0, 2, 0, 36,
+ 0, 2, 0, 64, 0, 2, 0,207, 0, 53, 0,201, 0, 55, 0, 17, 0, 32, 0,167, 0, 46, 0,208, 0, 56, 0,209, 0, 7, 0,210,
+ 0, 7, 0,211, 0, 2, 0, 18, 0, 2, 0,212, 0, 7, 0,113, 0, 7, 0,114, 0, 7, 0,213, 0, 4, 0,214, 0, 2, 0,215,
+ 0, 2, 0,216, 0, 4, 0,133, 0, 4, 0,143, 0, 2, 0,217, 0, 2, 0,218, 0, 51, 0, 53, 0, 27, 0, 31, 0, 7, 0,219,
+ 0, 7, 0,220, 0, 7, 0,221, 0, 7, 0,222, 0, 7, 0,223, 0, 7, 0,224, 0, 7, 0,225, 0, 7, 0,226, 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,233, 0, 7, 0,234, 0, 7, 0,235,
+ 0, 7, 0,236, 0, 7, 0,237, 0, 7, 0,238, 0, 2, 0,239, 0, 2, 0,240, 0, 2, 0,241, 0, 2, 0,242, 0, 2, 0,243,
+ 0, 2, 0,244, 0, 2, 0,245, 0, 2, 0, 20, 0, 2, 0, 18, 0, 2, 0,212, 0, 7, 0,246, 0, 7, 0,247, 0, 7, 0,248,
+ 0, 7, 0,249, 0, 2, 0,250, 0, 2, 0,251, 0, 2, 0,252, 0, 2, 0,131, 0, 4, 0, 23, 0, 4, 0,128, 0, 4, 0,129,
+ 0, 4, 0,130, 0, 7, 0,253, 0, 7, 0,254, 0, 7, 0,188, 0, 45, 0,255, 0, 36, 0, 79, 0, 46, 0,208, 0, 52, 1, 0,
+ 0, 54, 1, 1, 0, 55, 1, 2, 0, 30, 0,153, 0, 57, 0, 8, 0, 7, 1, 3, 0, 7, 1, 4, 0, 7, 0,175, 0, 4, 0, 20,
+ 0, 7, 1, 5, 0, 7, 1, 6, 0, 7, 1, 7, 0, 32, 0, 45, 0, 58, 0, 77, 0, 27, 0, 31, 0, 2, 0, 18, 0, 2, 1, 8,
+ 0, 4, 1, 9, 0, 2, 0,177, 0, 2, 1, 10, 0, 7, 0,182, 0, 7, 0,183, 0, 7, 0,184, 0, 7, 0,185, 0, 7, 1, 11,
+ 0, 7, 1, 12, 0, 7, 1, 13, 0, 7, 1, 14, 0, 7, 1, 15, 0, 7, 1, 16, 0, 7, 1, 17, 0, 7, 1, 18, 0, 7, 1, 19,
+ 0, 7, 1, 20, 0, 7, 1, 21, 0, 59, 1, 22, 0, 2, 1, 23, 0, 2, 0, 70, 0, 7, 0,113, 0, 7, 0,114, 0, 7, 1, 24,
+ 0, 7, 1, 25, 0, 7, 1, 26, 0, 2, 1, 27, 0, 2, 1, 28, 0, 2, 1, 29, 0, 2, 1, 30, 0, 0, 1, 31, 0, 0, 1, 32,
+ 0, 2, 1, 33, 0, 2, 1, 34, 0, 2, 1, 35, 0, 2, 1, 36, 0, 2, 1, 37, 0, 7, 1, 38, 0, 7, 1, 39, 0, 7, 1, 40,
+ 0, 7, 1, 41, 0, 2, 1, 42, 0, 2, 0, 43, 0, 2, 1, 43, 0, 2, 1, 44, 0, 2, 1, 45, 0, 2, 1, 46, 0, 7, 1, 47,
+ 0, 7, 1, 48, 0, 7, 1, 49, 0, 7, 1, 50, 0, 7, 1, 51, 0, 7, 1, 52, 0, 7, 1, 53, 0, 7, 1, 54, 0, 7, 1, 55,
+ 0, 7, 1, 56, 0, 7, 1, 57, 0, 4, 1, 58, 0, 4, 1, 59, 0, 2, 1, 60, 0, 2, 1, 61, 0, 2, 1, 62, 0, 2, 1, 63,
+ 0, 7, 1, 64, 0, 7, 1, 65, 0, 7, 1, 66, 0, 7, 1, 67, 0, 2, 1, 68, 0, 2, 1, 69, 0, 50, 1, 70, 0, 36, 0, 79,
+ 0, 30, 0,153, 0, 39, 0,125, 0, 60, 0, 2, 0, 27, 0, 31, 0, 36, 0, 79, 0, 61, 0,129, 0, 27, 0, 31, 0, 2, 0,177,
+ 0, 2, 0, 20, 0, 7, 0,182, 0, 7, 0,183, 0, 7, 0,184, 0, 7, 1, 71, 0, 7, 1, 72, 0, 7, 1, 73, 0, 7, 1, 74,
+ 0, 7, 1, 75, 0, 7, 1, 76, 0, 7, 1, 77, 0, 7, 1, 78, 0, 7, 1, 79, 0, 7, 1, 80, 0, 7, 1, 81, 0, 7, 1, 82,
+ 0, 7, 1, 83, 0, 7, 1, 84, 0, 7, 1, 85, 0, 7, 1, 86, 0, 7, 1, 87, 0, 7, 1, 88, 0, 7, 1, 89, 0, 7, 1, 90,
+ 0, 7, 1, 91, 0, 7, 1, 92, 0, 7, 1, 93, 0, 7, 1, 94, 0, 7, 1, 95, 0, 7, 1, 96, 0, 7, 1, 97, 0, 2, 1, 98,
+ 0, 2, 1, 99, 0, 2, 1,100, 0, 0, 1,101, 0, 0, 1,102, 0, 7, 1,103, 0, 7, 1,104, 0, 2, 1,105, 0, 2, 1,106,
+ 0, 7, 1,107, 0, 7, 1,108, 0, 7, 1,109, 0, 7, 1,110, 0, 2, 1,111, 0, 2, 1,112, 0, 4, 1, 9, 0, 4, 1,113,
+ 0, 2, 1,114, 0, 2, 1,115, 0, 2, 1,116, 0, 2, 1,117, 0, 7, 1,118, 0, 7, 1,119, 0, 7, 1,120, 0, 7, 1,121,
+ 0, 7, 1,122, 0, 7, 1,123, 0, 7, 1,124, 0, 7, 1,125, 0, 7, 1,126, 0, 7, 1,127, 0, 0, 1,128, 0, 7, 1,129,
+ 0, 7, 1,130, 0, 7, 1,131, 0, 4, 1,132, 0, 0, 1,133, 0, 0, 1, 43, 0, 0, 1,134, 0, 0, 1,135, 0, 2, 1,136,
+ 0, 2, 1,137, 0, 2, 1,138, 0, 2, 1,139, 0, 2, 1,140, 0, 2, 1,141, 0, 7, 1,142, 0, 7, 1,143, 0, 7, 1,144,
+ 0, 7, 1,145, 0, 7, 1,146, 0, 2, 0,163, 0, 2, 0,164, 0, 54, 1,147, 0, 54, 1,148, 0, 0, 1,149, 0, 0, 1,150,
+ 0, 0, 1,151, 0, 0, 1,152, 0, 2, 1,153, 0, 2, 1, 8, 0, 7, 1,154, 0, 7, 1,155, 0, 50, 1, 70, 0, 62, 1,156,
+ 0, 36, 0, 79, 0, 63, 1,157, 0, 30, 0,153, 0, 7, 1,158, 0, 7, 1,159, 0, 7, 1,160, 0, 7, 1,161, 0, 7, 1,162,
+ 0, 2, 1,163, 0, 2, 0, 70, 0, 7, 1,164, 0, 7, 1,165, 0, 7, 1,166, 0, 7, 1,167, 0, 7, 1,168, 0, 7, 1,169,
+ 0, 7, 1,170, 0, 7, 1,171, 0, 7, 1,172, 0, 2, 1,173, 0, 2, 1,174, 0, 7, 1,175, 0, 7, 1,176, 0, 7, 1,177,
+ 0, 7, 1,178, 0, 7, 1,179, 0, 4, 1,180, 0, 4, 1,181, 0, 4, 1,182, 0, 39, 0,125, 0, 12, 1,183, 0, 64, 0, 6,
+ 0, 27, 0, 31, 0, 0, 1,184, 0, 7, 1,185, 0, 7, 0, 37, 0, 65, 0, 2, 0, 43, 0,152, 0, 66, 0, 26, 0, 66, 0, 0,
+ 0, 66, 0, 1, 0, 67, 1,186, 0, 4, 1,187, 0, 4, 1,188, 0, 4, 1,189, 0, 4, 1,190, 0, 4, 1,191, 0, 4, 1,192,
+ 0, 2, 0, 18, 0, 2, 0, 20, 0, 2, 1,193, 0, 2, 1,194, 0, 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 7, 0, 7, 1,195,
+ 0, 7, 1,196, 0, 7, 1,197, 0, 7, 1,198, 0, 7, 1,199, 0, 7, 1,200, 0, 7, 1,201, 0, 7, 0, 23, 0, 7, 1,202,
+ 0, 7, 1,203, 0, 68, 0, 15, 0, 27, 0, 31, 0, 67, 1,186, 0, 12, 1,204, 0, 12, 1,205, 0, 36, 0, 79, 0, 61, 1,206,
+ 0, 2, 0, 20, 0, 2, 1,207, 0, 4, 0,176, 0, 7, 1, 3, 0, 7, 0,175, 0, 7, 1, 4, 0, 7, 1,208, 0, 7, 1,209,
+ 0, 7, 1,210, 0, 35, 0, 10, 0, 7, 1,211, 0, 7, 1,212, 0, 7, 1,213, 0, 7, 1,214, 0, 2, 1,215, 0, 2, 1,216,
+ 0, 0, 1,217, 0, 0, 1,218, 0, 0, 1,219, 0, 0, 1,220, 0, 34, 0, 7, 0, 7, 1,221, 0, 7, 1,212, 0, 7, 1,213,
+ 0, 2, 1,217, 0, 2, 1,220, 0, 7, 1,214, 0, 7, 0, 37, 0, 69, 0, 21, 0, 69, 0, 0, 0, 69, 0, 1, 0, 2, 0, 18,
+ 0, 2, 1,222, 0, 2, 1,220, 0, 2, 0, 20, 0, 2, 1,223, 0, 2, 1,224, 0, 2, 1,225, 0, 2, 1,226, 0, 2, 1,227,
+ 0, 2, 1,228, 0, 2, 1,229, 0, 2, 1,230, 0, 7, 1,231, 0, 7, 1,232, 0, 34, 0, 49, 0, 35, 0, 50, 0, 2, 1,233,
+ 0, 2, 0, 37, 0, 4, 1,234, 0, 70, 0, 5, 0, 2, 1,235, 0, 2, 1,222, 0, 0, 0, 20, 0, 0, 0, 37, 0, 2, 0, 70,
+ 0, 71, 0, 4, 0, 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 8, 0, 7, 1,236, 0, 72, 0, 57, 0, 27, 0, 31, 0, 67, 1,186,
+ 0, 12, 1,237, 0, 12, 1,205, 0, 32, 1,238, 0, 32, 1,239, 0, 32, 1,240, 0, 36, 0, 79, 0, 73, 1,241, 0, 38, 1,242,
+ 0, 61, 1,206, 0, 12, 1,243, 0, 7, 1, 3, 0, 7, 0,175, 0, 7, 1, 4, 0, 4, 0,176, 0, 2, 1,244, 0, 2, 1,207,
+ 0, 2, 0, 20, 0, 2, 1,245, 0, 7, 1,246, 0, 7, 1,247, 0, 7, 1,248, 0, 2, 1,225, 0, 2, 1,226, 0, 2, 1,249,
+ 0, 2, 1,250, 0, 4, 0, 70, 0, 2, 0, 23, 0, 2, 0, 98, 0, 2, 0, 67, 0, 2, 1,251, 0, 7, 1,252, 0, 7, 1,253,
+ 0, 7, 1,254, 0, 7, 1,255, 0, 7, 2, 0, 0, 7, 2, 1, 0, 7, 2, 2, 0, 7, 2, 3, 0, 7, 2, 4, 0, 7, 2, 5,
+ 0, 0, 2, 6, 0, 0, 2, 7, 0, 64, 2, 8, 0, 64, 2, 9, 0, 64, 2, 10, 0, 64, 2, 11, 0, 4, 2, 12, 0, 4, 2, 13,
+ 0, 4, 2, 14, 0, 4, 0, 37, 0, 71, 2, 15, 0, 4, 2, 16, 0, 4, 2, 17, 0, 70, 2, 18, 0, 70, 2, 19, 0, 74, 0, 39,
+ 0, 27, 0, 31, 0, 67, 1,186, 0, 12, 2, 20, 0, 36, 0, 79, 0, 38, 1,242, 0, 61, 1,206, 0, 75, 2, 21, 0, 76, 2, 22,
+ 0, 77, 2, 23, 0, 78, 2, 24, 0, 79, 2, 25, 0, 80, 2, 26, 0, 81, 2, 27, 0, 82, 2, 28, 0, 74, 2, 29, 0, 83, 2, 30,
+ 0, 84, 2, 31, 0, 84, 2, 32, 0, 84, 2, 33, 0, 4, 0, 54, 0, 4, 2, 34, 0, 4, 2, 35, 0, 4, 2, 36, 0, 4, 2, 37,
+ 0, 4, 0,176, 0, 7, 1, 3, 0, 7, 0,175, 0, 7, 1, 4, 0, 7, 2, 38, 0, 7, 0, 37, 0, 2, 2, 39, 0, 2, 0, 20,
+ 0, 2, 2, 40, 0, 2, 2, 41, 0, 2, 1,207, 0, 2, 2, 42, 0, 85, 2, 43, 0, 86, 2, 44, 0, 9, 0,162, 0, 77, 0, 8,
+ 0, 9, 2, 45, 0, 7, 2, 46, 0, 4, 2, 47, 0, 0, 0, 20, 0, 0, 2, 48, 0, 2, 1, 9, 0, 2, 2, 49, 0, 2, 2, 50,
+ 0, 75, 0, 8, 0, 4, 2, 51, 0, 4, 2, 52, 0, 4, 2, 53, 0, 4, 2, 54, 0, 0, 0, 37, 0, 0, 1,222, 0, 0, 2, 55,
+ 0, 0, 0, 20, 0, 79, 0, 5, 0, 4, 2, 51, 0, 4, 2, 52, 0, 0, 2, 56, 0, 0, 2, 57, 0, 2, 0, 20, 0, 87, 0, 2,
+ 0, 4, 2, 58, 0, 7, 1,213, 0, 80, 0, 3, 0, 87, 2, 59, 0, 4, 2, 60, 0, 4, 0, 20, 0, 78, 0, 6, 0, 7, 2, 61,
+ 0, 2, 2, 62, 0, 0, 0, 20, 0, 0, 1,222, 0, 0, 2, 57, 0, 0, 0,181, 0, 81, 0, 4, 0, 0, 0,206, 0, 0, 0,182,
+ 0, 0, 0,183, 0, 0, 0,184, 0, 88, 0, 6, 0, 46, 2, 45, 0, 0, 0, 20, 0, 0, 2, 48, 0, 2, 1, 9, 0, 2, 2, 49,
+ 0, 2, 2, 50, 0, 89, 0, 1, 0, 7, 2, 63, 0, 90, 0, 5, 0, 0, 0,206, 0, 0, 0,182, 0, 0, 0,183, 0, 0, 0,184,
+ 0, 4, 0, 37, 0, 82, 0, 1, 0, 7, 2, 64, 0, 83, 0, 2, 0, 4, 2, 65, 0, 4, 0, 18, 0, 76, 0, 7, 0, 7, 2, 46,
+ 0, 46, 2, 45, 0, 0, 0, 20, 0, 0, 2, 48, 0, 2, 1, 9, 0, 2, 2, 49, 0, 2, 2, 50, 0, 91, 0, 1, 0, 7, 2, 66,
+ 0, 92, 0, 1, 0, 4, 2, 67, 0, 93, 0, 1, 0, 0, 2, 68, 0, 94, 0, 1, 0, 7, 2, 46, 0, 95, 0, 4, 0, 7, 0,206,
+ 0, 7, 0,182, 0, 7, 0,183, 0, 7, 0,184, 0, 96, 0, 1, 0, 95, 2, 47, 0, 97, 0, 5, 0, 4, 2, 69, 0, 4, 2, 70,
+ 0, 0, 0, 20, 0, 0, 1,222, 0, 0, 2, 71, 0, 98, 0, 2, 0, 4, 2, 72, 0, 4, 2, 70, 0, 99, 0, 14, 0, 99, 0, 0,
+ 0, 99, 0, 1, 0, 97, 2, 73, 0, 96, 2, 74, 0, 98, 2, 75, 0, 0, 2, 76, 0, 12, 2, 77, 0, 12, 2, 78, 0,100, 2, 79,
+ 0, 4, 0, 54, 0, 4, 2, 35, 0, 4, 2, 34, 0, 4, 0, 37, 0, 78, 2, 80, 0, 85, 0, 14, 0, 12, 2, 81, 0, 78, 2, 80,
+ 0, 0, 2, 82, 0, 0, 2, 83, 0, 0, 2, 84, 0, 0, 2, 85, 0, 0, 2, 86, 0, 0, 2, 87, 0, 0, 2, 88, 0, 0, 0, 20,
+ 0, 84, 2, 31, 0, 84, 2, 33, 0, 2, 2, 89, 0, 0, 2, 90, 0, 86, 0, 8, 0, 4, 2, 91, 0, 4, 2, 92, 0, 75, 2, 93,
+ 0, 79, 2, 94, 0, 4, 2, 35, 0, 4, 2, 34, 0, 4, 0, 54, 0, 4, 0, 37, 0,101, 0, 6, 0,101, 0, 0, 0,101, 0, 1,
+ 0, 4, 0, 18, 0, 4, 1, 9, 0, 0, 0, 17, 0, 0, 2, 95, 0,102, 0, 7, 0,101, 2, 96, 0, 2, 2, 97, 0, 2, 2, 81,
+ 0, 2, 2, 98, 0, 2, 0, 93, 0, 9, 2, 99, 0, 9, 2,100, 0,103, 0, 3, 0,101, 2, 96, 0, 32, 0,167, 0, 0, 0, 17,
+ 0,104, 0, 5, 0,101, 2, 96, 0, 32, 0,167, 0, 0, 0, 17, 0, 2, 2,101, 0, 0, 2,102, 0,105, 0, 5, 0,101, 2, 96,
+ 0, 7, 0, 91, 0, 7, 2,103, 0, 4, 2,104, 0, 4, 2,105, 0,106, 0, 13, 0,101, 2, 96, 0, 32, 2,106, 0, 32, 2,107,
+ 0, 32, 2,108, 0, 32, 2,109, 0, 7, 2,110, 0, 7, 2,111, 0, 7, 2,103, 0, 7, 2,112, 0, 4, 2,113, 0, 4, 2,114,
+ 0, 4, 0, 93, 0, 4, 2,115, 0,107, 0, 5, 0,101, 2, 96, 0, 2, 2,116, 0, 2, 0, 20, 0, 7, 2,117, 0, 32, 2,118,
+ 0,108, 0, 3, 0,101, 2, 96, 0, 7, 2,119, 0, 4, 0, 93, 0,109, 0, 10, 0,101, 2, 96, 0, 7, 2,120, 0, 4, 2,121,
+ 0, 4, 0, 37, 0, 2, 0, 93, 0, 2, 2,122, 0, 2, 2,123, 0, 2, 2,124, 0, 7, 2,125, 0, 0, 2,126, 0,110, 0, 3,
+ 0,101, 2, 96, 0, 7, 0, 37, 0, 4, 0, 18, 0,111, 0, 11, 0,101, 2, 96, 0, 51, 2,127, 0, 7, 2,128, 0, 4, 2,129,
+ 0, 0, 2,126, 0, 7, 2,130, 0, 4, 2,131, 0, 32, 2,132, 0, 0, 2,133, 0, 4, 2,134, 0, 4, 0, 37, 0,112, 0, 10,
+ 0,101, 2, 96, 0, 32, 2,135, 0, 46, 2,136, 0, 4, 0, 93, 0, 4, 2,137, 0, 7, 2,138, 0, 7, 2,139, 0, 0, 2,133,
+ 0, 4, 2,134, 0, 4, 0, 37, 0,113, 0, 3, 0,101, 2, 96, 0, 7, 2,140, 0, 4, 2,141, 0,114, 0, 5, 0,101, 2, 96,
+ 0, 7, 2,142, 0, 0, 2,126, 0, 2, 0, 20, 0, 2, 2,143, 0,115, 0, 8, 0,101, 2, 96, 0, 32, 0,167, 0, 7, 2,142,
+ 0, 7, 1,214, 0, 7, 0,109, 0, 0, 2,126, 0, 2, 0, 20, 0, 2, 0, 18, 0,116, 0, 21, 0,101, 2, 96, 0, 32, 2,144,
+ 0, 0, 2,126, 0, 51, 2,127, 0, 32, 2,132, 0, 2, 0, 20, 0, 2, 0, 37, 0, 7, 2,145, 0, 7, 2,146, 0, 7, 2,147,
+ 0, 7, 1,246, 0, 7, 2,148, 0, 7, 2,149, 0, 7, 2,150, 0, 7, 2,151, 0, 4, 2,131, 0, 4, 2,134, 0, 0, 2,133,
+ 0, 7, 2,152, 0, 7, 2,153, 0, 7, 0, 43, 0,117, 0, 7, 0,101, 2, 96, 0, 2, 2,154, 0, 2, 2,155, 0, 4, 0, 70,
+ 0, 32, 0,167, 0, 7, 2,156, 0, 0, 2,126, 0,118, 0, 9, 0,101, 2, 96, 0, 32, 0,167, 0, 7, 2,157, 0, 7, 2,158,
+ 0, 7, 2,151, 0, 4, 2,159, 0, 4, 2,160, 0, 7, 2,161, 0, 0, 0, 17, 0,119, 0, 1, 0,101, 2, 96, 0,120, 0, 5,
+ 0,101, 2, 96, 0,121, 2,162, 0,122, 2,163, 0,123, 2,164, 0,124, 2,165, 0,125, 0, 14, 0,101, 2, 96, 0, 78, 2,166,
+ 0, 78, 2,167, 0, 78, 2,168, 0, 78, 2,169, 0, 78, 2,170, 0, 78, 2,171, 0, 75, 2,172, 0, 4, 2,173, 0, 4, 2,174,
+ 0, 2, 2,175, 0, 2, 0, 37, 0, 7, 2,176, 0,126, 2,177, 0,127, 0, 4, 0,101, 2, 96, 0, 32, 0,167, 0, 4, 2,178,
+ 0, 4, 0, 37, 0,128, 0, 2, 0, 4, 2,179, 0, 7, 1,213, 0,129, 0, 2, 0, 4, 0,129, 0, 4, 2,180, 0,130, 0, 20,
+ 0,101, 2, 96, 0, 32, 0,167, 0, 0, 2,126, 0, 2, 2,181, 0, 2, 2,182, 0, 2, 0, 20, 0, 2, 0, 37, 0, 7, 2,183,
+ 0, 7, 2,184, 0, 4, 0, 54, 0, 4, 2,185, 0,129, 2,186, 0,128, 2,187, 0, 4, 2,188, 0, 4, 2,189, 0, 4, 2,190,
+ 0, 4, 2,180, 0, 7, 2,191, 0, 7, 2,192, 0, 7, 2,193, 0,131, 0, 8, 0,101, 2, 96, 0,132, 2,194, 0,133, 2,195,
+ 0, 4, 2,196, 0, 4, 2,197, 0, 4, 2,198, 0, 2, 0, 20, 0, 2, 0, 57, 0,134, 0, 5, 0,101, 2, 96, 0, 32, 0, 45,
+ 0, 2, 2,199, 0, 2, 0, 20, 0, 2, 2,200, 0,135, 0, 5, 0,101, 2, 96, 0, 4, 2,201, 0, 2, 0, 20, 0, 2, 2,202,
+ 0, 7, 2,203, 0,136, 0, 10, 0,101, 2, 96, 0, 32, 2,204, 0, 32, 2,205, 0, 0, 2,206, 0, 7, 2,207, 0, 2, 2,208,
+ 0, 2, 2,209, 0, 0, 2,210, 0, 0, 2,211, 0, 0, 2,102, 0,137, 0, 24, 0, 27, 0, 31, 0, 2, 1,223, 0, 2, 1,224,
+ 0, 2, 2,212, 0, 2, 0, 20, 0, 2, 2,213, 0, 2, 2,214, 0, 2, 2,215, 0, 2, 0, 70, 0, 0, 2,216, 0, 0, 2,217,
+ 0, 0, 2,218, 0, 0, 0, 18, 0, 4, 0, 37, 0, 7, 2,219, 0, 7, 2,220, 0, 7, 2,221, 0, 7, 2,222, 0, 7, 2,223,
+ 0, 7, 2,224, 0, 34, 2,225, 0, 36, 0, 79, 0, 38, 1,242, 0, 80, 2, 26, 0,138, 0, 3, 0,138, 0, 0, 0,138, 0, 1,
+ 0, 0, 0, 17, 0, 67, 0, 3, 0, 7, 2,226, 0, 4, 0, 20, 0, 4, 0, 37, 0, 32, 0,108, 0, 27, 0, 31, 0, 2, 0, 18,
+ 0, 2, 2,227, 0, 4, 2,228, 0, 4, 2,229, 0, 4, 2,230, 0, 0, 2,231, 0, 32, 0, 38, 0, 32, 2,232, 0, 32, 2,233,
+ 0, 32, 2,234, 0, 32, 2,235, 0, 36, 0, 79, 0, 73, 1,241, 0, 67, 1,186, 0,139, 2,236, 0,139, 2,237, 0,140, 2,238,
+ 0, 9, 0, 2, 0, 12, 2,239, 0, 12, 2, 20, 0, 12, 1,205, 0, 12, 2,240, 0, 12, 2,241, 0, 61, 1,206, 0, 7, 1, 3,
+ 0, 7, 2,242, 0, 7, 2,243, 0, 7, 0,175, 0, 7, 2,244, 0, 7, 1, 4, 0, 7, 2,245, 0, 7, 2,246, 0, 7, 2,157,
+ 0, 7, 2,247, 0, 7, 0,210, 0, 4, 2,248, 0, 2, 0, 20, 0, 2, 2,249, 0, 2, 2,250, 0, 2, 2,251, 0, 2, 2,252,
+ 0, 2, 2,253, 0, 2, 2,254, 0, 2, 2,255, 0, 2, 3, 0, 0, 2, 3, 1, 0, 2, 3, 2, 0, 2, 3, 3, 0, 4, 3, 4,
+ 0, 4, 3, 5, 0, 4, 3, 6, 0, 4, 3, 7, 0, 7, 3, 8, 0, 7, 3, 9, 0, 7, 3, 10, 0, 7, 3, 11, 0, 7, 3, 12,
+ 0, 7, 3, 13, 0, 7, 3, 14, 0, 7, 3, 15, 0, 7, 3, 16, 0, 7, 1, 8, 0, 0, 3, 17, 0, 0, 3, 18, 0, 0, 1,207,
+ 0, 0, 3, 19, 0, 0, 3, 20, 0, 0, 3, 21, 0, 7, 3, 22, 0, 7, 3, 23, 0, 39, 0,125, 0, 12, 3, 24, 0, 12, 3, 25,
+ 0, 12, 3, 26, 0, 12, 3, 27, 0, 7, 3, 28, 0, 2, 2, 65, 0, 2, 3, 29, 0, 7, 2, 47, 0, 4, 3, 30, 0, 4, 3, 31,
+ 0, 2, 3, 32, 0, 2, 0,217, 0, 7, 3, 33, 0, 12, 3, 34, 0, 12, 3, 35, 0, 12, 3, 36, 0, 12, 3, 37, 0,141, 3, 38,
+ 0,142, 3, 39, 0, 63, 3, 40, 0, 2, 3, 41, 0, 2, 3, 42, 0, 2, 3, 43, 0, 2, 3, 44, 0, 7, 2, 39, 0, 2, 3, 45,
+ 0, 2, 3, 46, 0,143, 3, 47, 0,133, 3, 48, 0,133, 3, 49, 0, 4, 3, 50, 0, 4, 3, 51, 0, 4, 3, 52, 0, 4, 0, 70,
+ 0, 9, 0,162, 0, 12, 3, 53, 0,144, 0, 14, 0,144, 0, 0, 0,144, 0, 1, 0, 32, 0, 38, 0, 7, 2,157, 0, 7, 1, 5,
+ 0, 7, 2,158, 0, 7, 2,151, 0, 0, 0, 17, 0, 4, 2,159, 0, 4, 2,160, 0, 4, 3, 54, 0, 2, 0, 18, 0, 2, 3, 55,
+ 0, 7, 2,161, 0,141, 0, 36, 0, 2, 3, 56, 0, 2, 3, 57, 0, 2, 0, 20, 0, 2, 2,151, 0, 7, 3, 58, 0, 7, 3, 59,
+ 0, 7, 3, 60, 0, 7, 3, 61, 0, 7, 3, 62, 0, 7, 3, 63, 0, 7, 3, 64, 0, 7, 3, 65, 0, 7, 3, 66, 0, 7, 3, 67,
+ 0, 7, 3, 68, 0, 7, 3, 69, 0, 7, 3, 70, 0, 7, 3, 71, 0, 7, 3, 72, 0, 7, 3, 73, 0, 7, 3, 74, 0, 7, 3, 75,
+ 0, 7, 3, 76, 0, 7, 3, 77, 0, 7, 3, 78, 0, 7, 3, 79, 0, 7, 3, 80, 0, 7, 3, 81, 0, 2, 3, 82, 0, 2, 3, 83,
+ 0, 2, 3, 84, 0, 2, 3, 85, 0, 51, 0,168, 0,145, 3, 86, 0, 7, 3, 87, 0, 4, 0, 37, 0,124, 0, 5, 0, 4, 0, 20,
+ 0, 4, 3, 88, 0, 4, 3, 89, 0, 4, 3, 90, 0, 4, 3, 91, 0,146, 0, 1, 0, 7, 1,221, 0,142, 0, 44, 0,132, 3, 92,
+ 0, 4, 3, 93, 0, 4, 3, 94, 0,147, 3, 95, 0,148, 3, 96, 0, 7, 0, 37, 0, 7, 3, 97, 0, 7, 3, 98, 0, 7, 3, 99,
+ 0, 7, 3,100, 0, 7, 3,101, 0, 7, 3,102, 0, 7, 3,103, 0, 7, 3,104, 0, 7, 3,105, 0, 7, 3,106, 0, 2, 3,107,
+ 0, 2, 3,108, 0, 7, 3,109, 0, 7, 3,110, 0, 4, 0,130, 0, 4, 3,111, 0, 4, 3,112, 0, 2, 3,113, 0, 2, 3,114,
+ 0,146, 3,115, 0, 4, 3,116, 0, 4, 0, 81, 0, 7, 3,117, 0, 7, 3,118, 0, 7, 3,119, 0, 7, 3,120, 0, 2, 3,121,
+ 0, 2, 3,122, 0, 2, 3,123, 0, 2, 3,124, 0, 2, 3,125, 0, 2, 3,126, 0, 2, 3,127, 0, 2, 3,128, 0,149, 3,129,
+ 0, 7, 3,130, 0, 7, 3,131, 0,124, 3,132, 0,143, 0, 40, 0, 2, 0, 18, 0, 2, 3,133, 0, 2, 3,134, 0, 2, 3,135,
+ 0, 7, 3,136, 0, 2, 3,137, 0, 2, 3,138, 0, 7, 3,139, 0, 2, 3,140, 0, 2, 3,141, 0, 7, 3,142, 0, 7, 3,143,
+ 0, 7, 3,144, 0, 7, 3,145, 0, 7, 3,146, 0, 7, 3,147, 0, 4, 3,148, 0, 7, 3,149, 0, 7, 3,150, 0, 7, 3,151,
+ 0, 74, 3,152, 0, 74, 3,153, 0, 74, 3,154, 0, 0, 3,155, 0, 7, 3,156, 0, 7, 3,157, 0, 36, 0, 79, 0, 2, 3,158,
+ 0, 0, 3,159, 0, 0, 3,160, 0, 7, 3,161, 0, 4, 3,162, 0, 7, 3,163, 0, 7, 3,164, 0, 4, 3,165, 0, 4, 3,166,
+ 0, 7, 3,167, 0, 7, 3,168, 0, 7, 3,169, 0, 78, 3,170, 0,150, 0, 66, 0, 27, 0, 31, 0, 2, 0,177, 0, 2, 1, 10,
+ 0, 2, 1, 43, 0, 2, 3,171, 0, 7, 3,172, 0, 7, 3,173, 0, 7, 3,174, 0, 7, 3,175, 0, 7, 3,176, 0, 7, 3,177,
+ 0, 7, 3,178, 0, 7, 3,179, 0, 7, 1, 77, 0, 7, 1, 79, 0, 7, 1, 78, 0, 7, 3,180, 0, 4, 3,181, 0, 7, 3,182,
+ 0, 7, 3,183, 0, 7, 3,184, 0, 7, 3,185, 0, 7, 3,186, 0, 7, 3,187, 0, 7, 3,188, 0, 2, 3,189, 0, 2, 1, 9,
+ 0, 4, 3,190, 0, 7, 3,191, 0, 7, 3,192, 0, 7, 3,193, 0, 7, 3,194, 0, 7, 3,195, 0, 7, 3,196, 0, 7, 3,197,
+ 0, 7, 3,198, 0, 7, 3,199, 0, 7, 3,200, 0, 7, 3,201, 0, 7, 3,202, 0, 2, 3,203, 0, 2, 3,204, 0, 2, 3,205,
+ 0, 2, 3,206, 0, 7, 3,207, 0, 7, 3,208, 0, 7, 3,209, 0, 7, 3,210, 0, 2, 3,211, 0, 2, 3,212, 0, 2, 3,213,
+ 0, 2, 3,214, 0, 7, 3,215, 0, 7, 3,216, 0, 7, 3,217, 0, 7, 3,218, 0, 2, 3,219, 0, 2, 3,220, 0, 2, 3,221,
+ 0, 2, 0, 43, 0, 7, 3,222, 0, 7, 3,223, 0, 36, 0, 79, 0, 50, 1, 70, 0, 30, 0,153, 0, 39, 0,125, 0,151, 0, 16,
+ 0, 2, 3,224, 0, 2, 3,225, 0, 2, 3,226, 0, 2, 0, 20, 0, 2, 3,227, 0, 2, 3,228, 0, 2, 3,229, 0, 2, 3,230,
+ 0, 2, 3,231, 0, 2, 3,232, 0, 2, 3,233, 0, 2, 3,234, 0, 4, 3,235, 0, 7, 3,236, 0, 7, 3,237, 0, 7, 3,238,
+ 0,152, 0, 8, 0,152, 0, 0, 0,152, 0, 1, 0, 4, 2,248, 0, 4, 3,239, 0, 4, 0, 20, 0, 2, 3,240, 0, 2, 3,241,
+ 0, 32, 0,167, 0,153, 0, 13, 0, 9, 3,242, 0, 9, 3,243, 0, 4, 3,244, 0, 4, 3,245, 0, 4, 3,246, 0, 4, 3,247,
+ 0, 4, 3,248, 0, 4, 3,249, 0, 4, 3,250, 0, 4, 3,251, 0, 4, 3,252, 0, 4, 0, 37, 0, 0, 3,253, 0,154, 0, 5,
+ 0, 9, 3,254, 0, 9, 3,255, 0, 4, 4, 0, 0, 4, 0, 70, 0, 0, 4, 1, 0,155, 0, 13, 0, 4, 0, 18, 0, 4, 4, 2,
+ 0, 4, 4, 3, 0, 4, 4, 4, 0, 4, 4, 5, 0, 4, 4, 6, 0, 4, 0, 93, 0, 4, 4, 7, 0, 4, 4, 8, 0, 4, 4, 9,
+ 0, 4, 4, 10, 0, 4, 4, 11, 0, 26, 0, 30, 0,156, 0, 4, 0, 4, 4, 12, 0, 7, 4, 13, 0, 2, 0, 20, 0, 2, 0,181,
+ 0,157, 0, 11, 0,157, 0, 0, 0,157, 0, 1, 0, 0, 0, 17, 0, 61, 4, 14, 0, 63, 4, 15, 0, 4, 2,248, 0, 4, 4, 16,
+ 0, 4, 4, 17, 0, 4, 0, 37, 0, 4, 4, 18, 0, 4, 4, 19, 0,158, 0,120, 0,153, 4, 20, 0,154, 4, 21, 0,155, 4, 22,
+ 0, 4, 4, 23, 0, 4, 0,130, 0, 4, 3,111, 0, 4, 4, 24, 0, 4, 4, 25, 0, 4, 4, 26, 0, 4, 4, 27, 0, 2, 0, 20,
+ 0, 2, 4, 28, 0, 7, 3, 9, 0, 7, 4, 29, 0, 7, 4, 30, 0, 7, 4, 31, 0, 7, 4, 32, 0, 7, 4, 33, 0, 2, 4, 34,
+ 0, 2, 4, 35, 0, 2, 4, 36, 0, 2, 4, 37, 0, 2, 0,216, 0, 2, 4, 38, 0, 2, 4, 39, 0, 2, 3, 85, 0, 2, 4, 40,
+ 0, 2, 4, 41, 0, 2, 1, 30, 0, 2, 0,109, 0, 2, 4, 42, 0, 2, 4, 43, 0, 2, 4, 44, 0, 2, 4, 45, 0, 2, 4, 46,
+ 0, 2, 4, 47, 0, 2, 4, 48, 0, 2, 4, 49, 0, 2, 4, 50, 0, 2, 1, 31, 0, 2, 4, 51, 0, 2, 4, 52, 0, 2, 4, 53,
+ 0, 2, 4, 54, 0, 4, 4, 55, 0, 4, 1, 9, 0, 2, 4, 56, 0, 2, 4, 57, 0, 2, 4, 58, 0, 2, 4, 59, 0, 2, 4, 60,
+ 0, 2, 4, 61, 0, 24, 4, 62, 0, 24, 4, 63, 0, 23, 4, 64, 0, 12, 4, 65, 0, 2, 4, 66, 0, 2, 0, 37, 0, 7, 4, 67,
+ 0, 7, 4, 68, 0, 7, 4, 69, 0, 7, 4, 70, 0, 7, 4, 71, 0, 7, 4, 72, 0, 7, 4, 73, 0, 7, 4, 74, 0, 7, 4, 75,
+ 0, 2, 4, 76, 0, 2, 4, 77, 0, 2, 4, 78, 0, 2, 4, 79, 0, 2, 4, 80, 0, 2, 4, 81, 0, 7, 4, 82, 0, 7, 4, 83,
+ 0, 7, 4, 84, 0, 2, 4, 85, 0, 2, 4, 86, 0, 2, 4, 87, 0, 2, 4, 88, 0, 2, 4, 89, 0, 2, 4, 90, 0, 2, 4, 91,
+ 0, 2, 4, 92, 0, 2, 4, 93, 0, 2, 4, 94, 0, 4, 4, 95, 0, 4, 4, 96, 0, 4, 4, 97, 0, 4, 4, 98, 0, 4, 4, 99,
+ 0, 7, 4,100, 0, 4, 4,101, 0, 4, 4,102, 0, 4, 4,103, 0, 4, 4,104, 0, 7, 4,105, 0, 7, 4,106, 0, 7, 4,107,
+ 0, 7, 4,108, 0, 7, 4,109, 0, 7, 4,110, 0, 7, 4,111, 0, 7, 4,112, 0, 7, 4,113, 0, 0, 4,114, 0, 0, 4,115,
+ 0, 4, 4,116, 0, 2, 4,117, 0, 2, 1, 8, 0, 0, 4,118, 0, 7, 4,119, 0, 7, 4,120, 0, 4, 4,121, 0, 4, 4,122,
+ 0, 7, 4,123, 0, 7, 4,124, 0, 2, 4,125, 0, 2, 4,126, 0, 7, 4,127, 0,159, 0, 9, 0,159, 0, 0, 0,159, 0, 1,
+ 0, 0, 0, 17, 0, 2, 4,128, 0, 2, 4,129, 0, 2, 4,130, 0, 2, 0, 43, 0, 7, 4,131, 0, 7, 0, 70, 0,160, 0, 5,
+ 0, 7, 4,132, 0, 0, 0, 18, 0, 0, 0, 43, 0, 0, 0, 70, 0, 0, 1, 8, 0,161, 0, 5, 0,161, 0, 0, 0,161, 0, 1,
+ 0, 4, 4,133, 0, 0, 4,134, 0, 4, 0, 20, 0,162, 0, 4, 0,163, 4,135, 0, 2, 0, 20, 0, 2, 4,136, 0, 4, 1, 8,
+ 0,164, 0, 4, 0, 2, 0,109, 0, 2, 2,128, 0, 2, 4,137, 0, 2, 4,138, 0,165, 0, 7, 0, 2, 0, 20, 0, 2, 4,139,
+ 0, 2, 4,140, 0, 2, 4,141, 0,164, 4,142, 0, 7, 4,143, 0, 4, 4,144, 0,166, 0, 4, 0,166, 0, 0, 0,166, 0, 1,
+ 0, 0, 4,145, 0, 7, 4,146, 0,167, 0, 42, 0, 2, 4,147, 0, 2, 4,148, 0, 7, 4,149, 0, 7, 4,150, 0, 2, 4,137,
+ 0, 2, 4,151, 0, 7, 4,152, 0, 7, 4,153, 0, 2, 4,154, 0, 2, 4,155, 0, 2, 4,156, 0, 2, 4,157, 0, 7, 4,158,
+ 0, 7, 4,159, 0, 2, 4,160, 0, 2, 4,161, 0, 2, 4,162, 0, 2, 4,163, 0,162, 4,164, 0,165, 4,165, 0, 7, 4,166,
+ 0, 7, 4,167, 0, 0, 4,168, 0, 0, 4,169, 0, 0, 4,170, 0, 0, 4,171, 0, 0, 4,172, 0, 0, 4,173, 0, 2, 4,174,
+ 0, 7, 4,175, 0, 7, 4,176, 0, 7, 4,177, 0, 7, 4,178, 0, 7, 4,179, 0, 7, 4,180, 0, 7, 4,181, 0, 2, 4,182,
+ 0, 0, 4,183, 0, 0, 4,184, 0, 0, 4,185, 0, 0, 4,186, 0, 0, 4,187, 0,168, 0, 6, 0, 2, 0,109, 0, 0, 2,128,
+ 0, 0, 4,188, 0, 0, 4,189, 0, 0, 0, 20, 0, 0, 2, 71, 0,169, 0, 26, 0,170, 4,190, 0, 50, 1, 70, 0, 59, 4,191,
+ 0,168, 4,192, 0,168, 4,193, 0,168, 4,194, 0,168, 4,195, 0,168, 4,196, 0,168, 4,197, 0,168, 4,198, 0, 7, 4,199,
+ 0, 2, 4,200, 0, 2, 1, 43, 0, 2, 4,201, 0, 2, 1,252, 0, 0, 4,202, 0, 0, 4,203, 0, 0, 4,204, 0, 0, 4,205,
+ 0, 0, 0, 93, 0, 0, 4,206, 0, 0, 4,207, 0, 0, 4,208, 0, 0, 4,209, 0, 0, 4,210, 0, 0, 2, 71, 0,171, 0, 43,
+ 0, 27, 0, 31, 0, 32, 4,211, 0,150, 4,212, 0,171, 4,213, 0, 46, 0,208, 0, 12, 4,214, 0,152, 4,215, 0, 7, 4,216,
+ 0, 7, 4,217, 0, 7, 4,218, 0, 7, 4,219, 0, 4, 2,248, 0, 7, 4,220, 0, 2, 4,221, 0, 2, 4,222, 0, 2, 4,223,
+ 0, 2, 4,224, 0, 2, 4,225, 0, 2, 4,226, 0, 2, 4,227, 0, 2, 1,135, 0, 62, 1,156, 0, 9, 4,228, 0,151, 4,229,
+ 0,160, 4,230, 0,167, 4,231, 0,158, 0,182, 0,156, 4,232, 0, 39, 0,125, 0, 12, 0,103, 0, 12, 4,233, 0, 2, 4,234,
+ 0, 2, 4,235, 0, 2, 4,236, 0, 2, 4,237, 0,172, 4,238, 0, 2, 4,239, 0, 2, 4,240, 0, 2, 1,138, 0, 2, 0,217,
+ 0,169, 4,241, 0, 4, 4,242, 0, 4, 0, 37, 0,173, 0, 9, 0, 46, 0,208, 0, 45, 0,255, 0, 7, 2, 3, 0, 7, 2, 4,
+ 0, 7, 0,109, 0, 7, 4,243, 0, 7, 4,244, 0, 2, 4,245, 0, 2, 4,246, 0,174, 0, 70, 0,175, 0, 0, 0,175, 0, 1,
+ 0, 4, 4,247, 0, 7, 4,248, 0,176, 4,249, 0, 2, 4,250, 0, 7, 4,251, 0, 7, 4,252, 0, 7, 4,253, 0, 7, 4,254,
+ 0, 7, 4,255, 0, 7, 5, 0, 0, 7, 5, 1, 0, 7, 1, 16, 0, 7, 5, 2, 0, 4, 5, 3, 0, 2, 5, 4, 0, 2, 4,189,
+ 0, 32, 4,211, 0, 32, 5, 5, 0,173, 5, 6, 0,174, 5, 7, 0,177, 5, 8, 0,178, 5, 9, 0,179, 5, 10, 0, 0, 5, 11,
+ 0, 2, 3,226, 0, 2, 5, 12, 0, 4, 2,248, 0, 4, 5, 13, 0, 2, 5, 14, 0, 2, 5, 15, 0, 2, 5, 16, 0, 0, 5, 17,
+ 0, 0, 0, 43, 0, 7, 0,115, 0, 7, 5, 18, 0, 7, 5, 19, 0, 7, 5, 20, 0, 7, 5, 21, 0, 7, 5, 22, 0, 7, 5, 23,
+ 0, 7, 5, 24, 0, 7, 0,174, 0, 7, 4,216, 0, 2, 5, 25, 0, 2, 5, 26, 0, 2, 5, 27, 0, 2, 5, 28, 0, 2, 0,137,
+ 0, 2, 4,201, 0, 2, 5, 29, 0, 2, 5, 30, 0, 2, 5, 31, 0, 2, 5, 32, 0, 7, 5, 33, 0, 7, 5, 34, 0, 67, 5, 35,
+ 0, 12, 5, 36, 0, 2, 5, 37, 0, 2, 2, 48, 0, 2, 5, 38, 0, 2, 0, 20, 0, 2, 5, 39, 0, 2, 5, 40, 0, 2, 1, 8,
+ 0, 0, 5, 41, 0, 0, 5, 42, 0, 9, 5, 43, 0,180, 5, 44, 0,181, 0, 19, 0, 24, 0, 36, 0, 24, 0, 64, 0, 23, 5, 45,
+ 0, 23, 5, 46, 0, 23, 5, 47, 0, 7, 5, 48, 0, 7, 5, 49, 0, 7, 5, 50, 0, 7, 5, 51, 0, 2, 5, 52, 0, 2, 5, 53,
+ 0, 2, 5, 54, 0, 2, 5, 55, 0, 2, 5, 56, 0, 2, 5, 57, 0, 4, 0, 20, 0, 7, 5, 58, 0, 2, 5, 15, 0, 0, 2,102,
+ 0,175, 0, 6, 0,175, 0, 0, 0,175, 0, 1, 0, 4, 4,247, 0, 7, 4,248, 0,176, 4,249, 0, 2, 4,250, 0,182, 0, 6,
+ 0,175, 0, 0, 0,175, 0, 1, 0, 4, 4,247, 0, 7, 4,248, 0,176, 4,249, 0, 2, 4,250, 0,183, 0, 27, 0,175, 0, 0,
+ 0,175, 0, 1, 0, 4, 4,247, 0, 7, 4,248, 0,176, 4,249, 0, 2, 4,250, 0, 4, 5, 59, 0, 4, 0, 70, 0,181, 5, 60,
+ 0, 9, 5, 61, 0, 12, 5, 62, 0, 36, 0, 79, 0, 27, 0, 80, 0, 0, 5, 63, 0, 0, 5, 64, 0, 0, 5, 65, 0, 2, 5, 66,
+ 0, 2, 5, 67, 0, 2, 5, 68, 0, 2, 5, 69, 0, 2, 0, 65, 0, 2, 0, 46, 0, 2, 0,137, 0, 2, 5, 70, 0, 4, 0, 20,
+ 0, 7, 5, 71, 0, 24, 0, 36, 0,184, 0, 29, 0,175, 0, 0, 0,175, 0, 1, 0, 4, 4,247, 0, 7, 4,248, 0,176, 4,249,
+ 0,177, 5, 8, 0, 2, 4,250, 0, 2, 5, 72, 0, 2, 5, 73, 0, 2, 5, 74, 0, 2, 5, 75, 0,181, 5, 60, 0, 2, 5, 76,
+ 0, 2, 0,137, 0, 2, 5, 67, 0, 2, 5, 77, 0, 9, 5, 78, 0, 2, 4,201, 0, 0, 5, 79, 0, 0, 5, 80, 0, 2, 5, 81,
+ 0, 2, 5, 82, 0, 2, 3, 1, 0, 2, 5, 83, 0, 2, 5, 84, 0, 0, 0, 37, 0, 0, 0, 20, 0, 0, 1, 43, 0, 0, 5, 85,
+ 0,185, 0, 16, 0,175, 0, 0, 0,175, 0, 1, 0, 4, 4,247, 0, 7, 4,248, 0,176, 4,249, 0, 2, 4,250, 0,181, 5, 60,
+ 0, 7, 2, 3, 0, 7, 2, 4, 0, 2, 5, 76, 0, 2, 0, 37, 0, 2, 5, 86, 0, 2, 5, 87, 0, 4, 0, 20, 0, 7, 4,243,
+ 0,180, 5, 44, 0,186, 0, 33, 0,175, 0, 0, 0,175, 0, 1, 0, 4, 4,247, 0, 7, 4,248, 0,176, 4,249, 0, 2, 4,250,
+ 0,187, 5, 88, 0, 4, 5, 89, 0, 0, 5, 90, 0, 0, 5, 91, 0, 0, 5, 92, 0, 2, 0, 18, 0, 2, 5, 93, 0, 2, 0, 20,
+ 0, 2, 5, 94, 0, 2, 5, 95, 0, 2, 5, 96, 0, 2, 5, 97, 0, 2, 0, 43, 0, 4, 0, 70, 0, 0, 5, 98, 0,188, 5, 99,
+ 0, 2, 5,100, 0, 2, 5,101, 0, 2, 5,102, 0, 2, 0,207, 0, 9, 5,103, 0, 9, 5,104, 0, 9, 5,105, 0, 9, 5,106,
+ 0, 9, 5,107, 0, 2, 5,108, 0, 0, 5,109, 0,189, 0, 23, 0,175, 0, 0, 0,175, 0, 1, 0, 4, 4,247, 0, 7, 4,248,
+ 0,176, 4,249, 0, 2, 4,250, 0,181, 5, 60, 0, 12, 5,110, 0, 2, 5, 67, 0, 2, 5,111, 0, 2, 0, 20, 0, 2, 0, 57,
+ 0, 9, 5, 78, 0, 12, 5,112, 0,190, 5,113, 0, 0, 5,114, 0,191, 5,115, 0, 4, 5,116, 0, 4, 5,117, 0, 2, 0, 18,
+ 0, 2, 5,118, 0, 2, 5,119, 0, 2, 5,120, 0,192, 0, 29, 0,175, 0, 0, 0,175, 0, 1, 0, 4, 4,247, 0, 7, 4,248,
+ 0,176, 4,249, 0, 2, 4,250, 0,181, 5, 60, 0, 46, 2,136, 0, 45, 0,255, 0, 59, 4,191, 0, 2, 1, 9, 0, 2, 0,137,
+ 0, 2, 5,121, 0, 2, 5,122, 0, 4, 0, 20, 0, 2, 4,221, 0, 2, 5,123, 0, 2, 5, 70, 0, 2, 5, 67, 0, 7, 4,243,
+ 0, 0, 5,124, 0, 0, 5,125, 0, 0, 5,126, 0, 0, 5,127, 0, 7, 2, 3, 0, 7, 2, 4, 0, 7, 5,128, 0, 7, 5,129,
+ 0,180, 5, 44, 0,193, 0, 11, 0,175, 0, 0, 0,175, 0, 1, 0, 4, 4,247, 0, 7, 4,248, 0,176, 4,249, 0, 2, 4,250,
+ 0, 2, 0,137, 0, 2, 5, 70, 0, 2, 5,130, 0, 2, 0, 20, 0,181, 5, 60, 0,194, 0, 24, 0,175, 0, 0, 0,175, 0, 1,
+ 0, 4, 4,247, 0, 7, 4,248, 0,176, 4,249, 0, 2, 4,250, 0, 42, 5,131, 0, 4, 5,132, 0, 4, 5,133, 0, 2, 0, 93,
+ 0, 2, 0,137, 0, 4, 5,134, 0, 4, 5,135, 0, 4, 5,136, 0, 4, 5,137, 0, 4, 5,138, 0, 4, 5,139, 0, 4, 5,140,
+ 0, 4, 5,141, 0, 7, 5,142, 0, 23, 5,143, 0, 23, 5,144, 0, 4, 5,145, 0, 4, 5,146, 0,195, 0, 10, 0, 27, 0, 31,
+ 0, 9, 5,147, 0, 9, 5,148, 0, 9, 5,149, 0, 9, 5,150, 0, 9, 5,151, 0, 4, 0, 93, 0, 4, 5,152, 0, 0, 5,153,
+ 0, 0, 5,154, 0,196, 0, 10, 0,175, 0, 0, 0,175, 0, 1, 0, 4, 4,247, 0, 7, 4,248, 0,176, 4,249, 0,195, 5,155,
+ 0, 2, 0, 93, 0, 2, 0,137, 0, 4, 0, 43, 0, 9, 5,156, 0,197, 0, 8, 0,175, 0, 0, 0,175, 0, 1, 0, 4, 4,247,
+ 0, 7, 4,248, 0,176, 4,249, 0,181, 5, 60, 0, 4, 0, 20, 0, 4, 5,157, 0,198, 0, 20, 0,175, 0, 0, 0,175, 0, 1,
+ 0, 4, 4,247, 0, 7, 4,248, 0,176, 4,249, 0, 2, 4,250, 0,181, 5, 60, 0, 27, 5,158, 0, 27, 0, 80, 0, 2, 0, 20,
+ 0, 2, 0,137, 0, 7, 5,159, 0, 9, 5,160, 0, 7, 2, 3, 0, 7, 2, 4, 0, 62, 1,156, 0, 62, 5,161, 0, 4, 5,162,
+ 0, 4, 0, 37, 0,180, 5, 44, 0,199, 0, 42, 0,175, 0, 0, 0,175, 0, 1, 0, 4, 4,247, 0, 7, 4,248, 0,176, 4,249,
+ 0, 2, 4,250, 0,181, 5, 60, 0,200, 5,163, 0, 0, 5, 90, 0, 0, 5, 91, 0, 0, 5, 92, 0, 2, 0, 18, 0, 2, 5,101,
+ 0, 2, 0, 20, 0, 2, 5, 94, 0, 9, 5,160, 0, 4, 5,164, 0, 4, 5,165, 0, 4, 5,166, 0, 4, 5,167, 0, 23, 5,168,
+ 0, 23, 5,169, 0, 7, 5,170, 0, 7, 5,171, 0, 7, 5,172, 0, 7, 5,159, 0, 2, 5,100, 0, 2, 0,207, 0, 2, 1, 95,
+ 0, 2, 5,173, 0, 2, 0, 37, 0, 2, 0, 43, 0, 2, 5,174, 0, 2, 5,175, 0, 9, 5,103, 0, 9, 5,104, 0, 9, 5,105,
+ 0, 9, 5,106, 0, 9, 5,107, 0, 2, 5,108, 0, 0, 5,109, 0, 56, 5,176, 0,201, 0, 20, 0, 0, 5,177, 0, 0, 5,178,
+ 0, 0, 5,179, 0, 0, 5,180, 0, 0, 5,181, 0, 0, 5,182, 0, 0, 5,183, 0, 0, 5,184, 0, 0, 5,185, 0, 0, 5,186,
+ 0, 0, 5,187, 0, 0, 5,188, 0, 0, 5,189, 0, 0, 5,190, 0, 0, 5,191, 0, 0, 5,192, 0, 0, 5,193, 0, 0, 5,194,
+ 0, 0, 0,181, 0, 0, 5,195, 0,202, 0, 54, 0, 0, 5,196, 0, 0, 5,187, 0, 0, 5,188, 0, 0, 5,197, 0, 0, 5,198,
+ 0, 0, 5,199, 0, 0, 5,200, 0, 0, 5,201, 0, 0, 5,202, 0, 0, 5,203, 0, 0, 5,204, 0, 0, 5,205, 0, 0, 5,206,
+ 0, 0, 5,207, 0, 0, 5,208, 0, 0, 5,209, 0, 0, 5,210, 0, 0, 5,211, 0, 0, 5,212, 0, 0, 5,213, 0, 0, 5,214,
+ 0, 0, 5,215, 0, 0, 5,216, 0, 0, 5,217, 0, 0, 5,218, 0, 0, 5,219, 0, 0, 5,220, 0, 0, 5,221, 0, 0, 5,222,
+ 0, 0, 5,223, 0, 0, 5,224, 0, 0, 5,225, 0, 0, 0, 95, 0, 0, 5,226, 0, 0, 5,227, 0, 0, 5,228, 0, 0, 5,229,
+ 0, 0, 5,230, 0, 0, 5,231, 0, 0, 5,232, 0, 0, 5,233, 0, 0, 5,234, 0, 0, 5,235, 0, 0, 5,236, 0, 0, 5,237,
+ 0, 0, 5,238, 0, 0, 5,239, 0, 0, 5,240, 0, 0, 5,241, 0, 0, 5,242, 0, 0, 5,243, 0, 0, 5,244, 0, 0, 5,245,
+ 0, 0, 5,246, 0,203, 0, 5, 0, 0, 5,247, 0, 0, 5,204, 0, 0, 5,206, 0, 2, 0, 20, 0, 2, 0, 37, 0,204, 0, 22,
+ 0,204, 0, 0, 0,204, 0, 1, 0, 0, 0, 17, 0,201, 5,248, 0,202, 5,249, 0,202, 5,250, 0,202, 5,251, 0,202, 5,252,
+ 0,202, 5,253, 0,202, 5,254, 0,202, 5,255, 0,202, 6, 0, 0,202, 6, 1, 0,202, 6, 2, 0,202, 6, 3, 0,202, 6, 4,
+ 0,202, 6, 5, 0,202, 6, 6, 0,202, 6, 7, 0,203, 6, 8, 0, 0, 6, 9, 0, 0, 6, 10, 0,205, 0, 5, 0, 4, 0, 20,
+ 0, 4, 0, 37, 0, 7, 2, 47, 0, 7, 6, 11, 0, 7, 1,221, 0,206, 0, 65, 0, 4, 0, 20, 0, 4, 6, 12, 0, 4, 6, 13,
+ 0, 0, 6, 14, 0, 0, 6, 15, 0, 0, 6, 16, 0, 0, 6, 17, 0, 0, 6, 18, 0, 0, 6, 19, 0, 0, 6, 20, 0, 0, 6, 21,
+ 0, 0, 6, 22, 0, 2, 6, 23, 0, 2, 6, 24, 0, 4, 6, 25, 0, 4, 6, 26, 0, 4, 6, 27, 0, 4, 6, 28, 0, 2, 6, 29,
+ 0, 2, 6, 30, 0, 2, 6, 31, 0, 2, 6, 32, 0, 4, 6, 33, 0, 4, 6, 34, 0, 2, 6, 35, 0, 2, 6, 36, 0, 2, 6, 37,
+ 0, 2, 6, 38, 0, 0, 6, 39, 0, 12, 6, 40, 0, 2, 6, 41, 0, 2, 6, 42, 0, 2, 6, 43, 0, 2, 6, 44, 0, 2, 0, 37,
+ 0, 2, 6, 45, 0, 2, 6, 46, 0, 2, 6, 47, 0,205, 6, 48, 0, 2, 6, 49, 0, 2, 6, 50, 0, 2, 6, 51, 0, 2, 6, 52,
+ 0, 4, 6, 53, 0, 4, 6, 54, 0, 4, 6, 55, 0, 4, 6, 56, 0, 2, 6, 57, 0, 2, 6, 58, 0, 2, 6, 59, 0, 2, 6, 60,
+ 0, 2, 6, 61, 0, 2, 6, 62, 0, 2, 6, 63, 0, 2, 6, 64, 0, 2, 6, 65, 0, 2, 6, 66, 0, 2, 6, 67, 0, 0, 6, 68,
+ 0, 0, 6, 69, 0, 0, 6, 70, 0, 7, 6, 71, 0, 2, 6, 72, 0, 2, 6, 73, 0, 54, 6, 74, 0,207, 0, 18, 0, 27, 0, 31,
+ 0, 12, 6, 75, 0, 12, 6, 76, 0, 12, 6, 77, 0,171, 6, 78, 0, 2, 2,145, 0, 2, 6, 79, 0, 2, 2,146, 0, 2, 6, 80,
+ 0, 2, 6, 81, 0, 2, 6, 82, 0, 2, 6, 83, 0, 2, 6, 84, 0, 2, 6, 85, 0, 2, 0, 37, 0, 2, 6, 86, 0, 2, 6, 87,
+ 0, 2, 6, 88, 0,208, 0, 5, 0,208, 0, 0, 0,208, 0, 1, 0,208, 6, 89, 0, 13, 6, 90, 0, 4, 0, 20, 0,209, 0, 7,
+ 0,209, 0, 0, 0,209, 0, 1, 0,208, 6, 91, 0,208, 6, 92, 0, 2, 4, 63, 0, 2, 0, 20, 0, 4, 0, 37, 0,210, 0, 17,
+ 0,210, 0, 0, 0,210, 0, 1, 0, 0, 6, 93, 0, 0, 6, 94, 0, 0, 6, 95, 0, 2, 6, 96, 0, 2, 6, 97, 0, 2, 6, 81,
+ 0, 2, 6, 82, 0, 2, 0, 20, 0, 2, 3, 55, 0, 2, 6, 98, 0, 2, 6, 99, 0, 2, 6,100, 0, 2, 6,101, 0, 4, 6,102,
+ 0,210, 6,103, 0,176, 0, 30, 0,176, 0, 0, 0,176, 0, 1, 0,208, 6, 91, 0,208, 6, 92, 0,208, 6,104, 0,208, 6,105,
+ 0,207, 6,106, 0, 7, 6,107, 0, 23, 0, 52, 0, 23, 6,108, 0, 23, 6,109, 0, 2, 6,110, 0, 2, 6,111, 0, 2, 6,112,
+ 0, 0, 4,247, 0, 0, 6,113, 0, 2, 6,114, 0, 2, 6,115, 0, 0, 6,116, 0, 0, 6,117, 0, 0, 6,118, 0, 0, 6,119,
+ 0, 2, 6,120, 0, 2, 6,121, 0, 2, 6,122, 0, 2, 0, 20, 0, 39, 0,125, 0, 12, 6,123, 0, 12, 6,124, 0, 12, 6,125,
+ 0,211, 0, 11, 0, 0, 6,126, 0, 2, 6,127, 0, 2, 6,128, 0, 2, 6,129, 0, 2, 6,130, 0, 2, 6,131, 0, 2, 4, 47,
+ 0, 9, 6,132, 0, 9, 6,133, 0, 4, 6,134, 0, 4, 6,135, 0,212, 0, 1, 0, 0, 6,136, 0,213, 0, 8, 0, 56, 6,137,
+ 0, 56, 6,138, 0,213, 6,139, 0,213, 6,140, 0,213, 6,141, 0, 2, 0,133, 0, 2, 0, 20, 0, 4, 6,142, 0,214, 0, 4,
+ 0, 4, 5,132, 0, 4, 6,143, 0, 4, 5,136, 0, 4, 6,144, 0,215, 0, 2, 0, 4, 6,145, 0, 4, 6,146, 0,216, 0, 7,
+ 0, 7, 6,147, 0, 7, 6,148, 0, 7, 6,149, 0, 4, 0, 20, 0, 4, 0, 37, 0, 7, 3,182, 0, 7, 6,150, 0,217, 0, 1,
+ 0, 0, 6,151, 0,218, 0, 21, 0,218, 0, 0, 0,218, 0, 1, 0, 4, 0, 57, 0, 4, 0, 23, 0, 4, 0, 28, 0, 4, 6,152,
+ 0, 4, 6,153, 0, 4, 6,154, 0,212, 6,155, 0, 0, 6,151, 0, 4, 6,156, 0, 4, 6,157, 0,217, 2,233, 0,214, 6,158,
+ 0,215, 6,159, 0,216, 6,160, 0,213, 6,161, 0,213, 6,162, 0,213, 6,163, 0, 56, 6,164, 0, 56, 6,165, 0,219, 0, 12,
+ 0, 0, 1,184, 0, 9, 0,193, 0, 0, 0,194, 0, 4, 0,197, 0, 4, 0,205, 0, 9, 0,198, 0, 7, 0,200, 0, 7, 0,201,
+ 0, 9, 6,166, 0, 9, 6,167, 0, 9, 0,202, 0, 9, 0,204, 0,220, 0, 45, 0,220, 0, 0, 0,220, 0, 1, 0, 9, 6,168,
+ 0, 9, 0, 26, 0, 0, 0, 27, 0, 4, 0, 20, 0, 4, 0, 18, 0, 4, 0, 23, 0, 4, 0, 91, 0, 4, 6,169, 0, 4, 6,170,
+ 0, 4, 6,153, 0, 4, 6,154, 0, 4, 6,171, 0, 4, 0,216, 0, 4, 6,172, 0, 4, 6,173, 0, 7, 6,174, 0, 7, 6,175,
+ 0, 4, 0,130, 0, 4, 6,176, 0,218, 6,177, 0, 36, 0, 79, 0,171, 6, 78, 0, 48, 0,140, 0, 7, 6,178, 0, 7, 6,179,
+ 0,219, 1, 0, 0,220, 6,180, 0,220, 6,181, 0,220, 6,182, 0, 12, 6,183, 0,221, 6,184, 0,222, 6,185, 0, 7, 6,186,
+ 0, 7, 6,187, 0, 4, 6,188, 0, 7, 6,189, 0, 9, 6,190, 0, 4, 6,191, 0, 4, 6,192, 0, 4, 6,193, 0, 7, 6,194,
+ 0, 4, 6, 83, 0, 4, 0, 37, 0,223, 0, 4, 0,223, 0, 0, 0,223, 0, 1, 0, 12, 6,195, 0,220, 6,196, 0,224, 0, 6,
+ 0, 12, 6,197, 0, 12, 6,183, 0, 12, 6,198, 0, 2, 0, 20, 0, 2, 0, 37, 0, 4, 0, 57, 0,225, 0, 4, 0, 7, 6,199,
+ 0, 7, 0,112, 0, 2, 6,200, 0, 2, 6,201, 0,226, 0, 6, 0, 7, 6,202, 0, 7, 6,203, 0, 7, 6,204, 0, 7, 6,205,
+ 0, 4, 6,206, 0, 4, 6,207, 0,227, 0, 12, 0, 7, 6,208, 0, 7, 6,209, 0, 7, 6,210, 0, 7, 6,211, 0, 7, 6,212,
+ 0, 7, 6,213, 0, 7, 6,214, 0, 7, 6,215, 0, 7, 6,216, 0, 7, 6,217, 0, 4, 2,140, 0, 4, 6,218, 0,228, 0, 2,
+ 0, 7, 4,132, 0, 7, 0, 37, 0,229, 0, 5, 0, 7, 6,219, 0, 7, 6,220, 0, 4, 0, 93, 0, 4, 2,103, 0, 4, 6,221,
+ 0,230, 0, 6, 0,230, 0, 0, 0,230, 0, 1, 0, 2, 0, 18, 0, 2, 0, 20, 0, 2, 6,222, 0, 2, 0, 57, 0,231, 0, 8,
+ 0,231, 0, 0, 0,231, 0, 1, 0, 2, 0, 18, 0, 2, 0, 20, 0, 2, 6,222, 0, 2, 0, 57, 0, 7, 0, 23, 0, 7, 0,130,
+ 0,232, 0, 45, 0,232, 0, 0, 0,232, 0, 1, 0, 2, 0, 18, 0, 2, 0, 20, 0, 2, 6,222, 0, 2, 0,212, 0, 2, 3,107,
+ 0, 2, 6,223, 0, 7, 6,224, 0, 7, 0, 92, 0, 7, 2,153, 0, 4, 6,225, 0, 4, 0, 81, 0, 4, 2,105, 0, 7, 6,226,
+ 0, 7, 6,227, 0, 7, 6,228, 0, 7, 6,229, 0, 7, 6,230, 0, 7, 6,231, 0, 7, 2,150, 0, 7, 0,254, 0, 7, 6,232,
+ 0, 7, 6,233, 0, 7, 0, 37, 0, 7, 6,234, 0, 7, 6,235, 0, 7, 6,236, 0, 2, 6,237, 0, 2, 6,238, 0, 2, 6,239,
+ 0, 2, 6,240, 0, 2, 6,241, 0, 2, 6,242, 0, 2, 6,243, 0, 2, 6,244, 0, 2, 5, 39, 0, 2, 6,245, 0, 2, 1,205,
+ 0, 2, 6,246, 0, 0, 6,247, 0, 0, 6,248, 0, 7, 0,210, 0,233, 6,249, 0, 63, 1,157, 0,234, 0, 16, 0,234, 0, 0,
+ 0,234, 0, 1, 0, 2, 0, 18, 0, 2, 0, 20, 0, 2, 6,222, 0, 2, 0,212, 0, 7, 2,145, 0, 7, 2,146, 0, 7, 2,147,
+ 0, 7, 1,246, 0, 7, 2,148, 0, 7, 2,149, 0, 7, 6,250, 0, 7, 2,150, 0, 7, 2,152, 0, 7, 2,153, 0,191, 0, 5,
+ 0, 2, 0, 18, 0, 2, 6,142, 0, 2, 0, 20, 0, 2, 6,251, 0, 27, 5,158, 0,190, 0, 3, 0, 4, 0, 69, 0, 4, 6,252,
+ 0,191, 0, 2, 0,235, 0, 12, 0,235, 0, 0, 0,235, 0, 1, 0, 2, 0, 18, 0, 2, 0, 20, 0, 2, 3, 17, 0, 2, 1,220,
+ 0, 7, 0, 5, 0, 7, 0, 6, 0, 7, 6,253, 0, 7, 6,254, 0, 27, 5,158, 0, 12, 6,255, 0,236, 0, 11, 0,236, 0, 0,
+ 0,236, 0, 1, 0, 0, 0, 17, 0, 2, 0, 18, 0, 2, 7, 0, 0, 4, 0, 22, 0, 4, 7, 1, 0, 2, 0, 20, 0, 2, 0, 37,
+ 0, 9, 7, 2, 0, 9, 7, 3, 0,237, 0, 5, 0, 0, 0, 17, 0, 7, 1, 16, 0, 7, 7, 4, 0, 4, 7, 5, 0, 4, 0, 37,
+ 0,238, 0, 4, 0, 2, 0, 18, 0, 2, 0, 20, 0, 2, 0, 43, 0, 2, 0, 70, 0,239, 0, 4, 0, 0, 0, 17, 0, 61, 7, 6,
+ 0, 7, 1, 16, 0, 7, 0, 37, 0,240, 0, 6, 0, 2, 7, 7, 0, 2, 7, 8, 0, 2, 0, 18, 0, 2, 7, 9, 0, 0, 7, 10,
+ 0, 0, 7, 11, 0,241, 0, 5, 0, 4, 0, 18, 0, 4, 0, 37, 0, 0, 0, 17, 0, 0, 7, 12, 0, 0, 7, 13, 0,242, 0, 3,
+ 0, 4, 0, 18, 0, 4, 0, 37, 0, 0, 0, 17, 0,243, 0, 4, 0, 2, 7, 14, 0, 2, 7, 15, 0, 2, 0, 20, 0, 2, 0, 37,
+ 0,244, 0, 6, 0, 0, 0, 17, 0, 0, 7, 16, 0, 2, 7, 17, 0, 2, 2,150, 0, 2, 1, 9, 0, 2, 0, 70, 0,245, 0, 5,
+ 0, 0, 0, 17, 0, 7, 0,112, 0, 7, 3,184, 0, 2, 0, 20, 0, 2, 2,116, 0,246, 0, 3, 0, 0, 0, 17, 0, 4, 2,105,
+ 0, 4, 7, 14, 0,247, 0, 7, 0, 0, 0, 17, 0, 7, 3,184, 0, 0, 7, 18, 0, 0, 7, 19, 0, 2, 1, 9, 0, 2, 0, 43,
+ 0, 4, 7, 20, 0,248, 0, 3, 0, 32, 7, 21, 0, 0, 7, 22, 0, 0, 7, 23, 0,249, 0, 17, 0,249, 0, 0, 0,249, 0, 1,
+ 0, 2, 0, 18, 0, 2, 7, 0, 0, 2, 0, 20, 0, 2, 7, 24, 0, 2, 7, 25, 0, 2, 7, 26, 0, 2, 0, 43, 0, 2, 0, 70,
+ 0, 0, 0, 17, 0, 9, 0, 2, 0,250, 7, 27, 0, 32, 0, 45, 0, 2, 4,138, 0, 2, 6,186, 0, 4, 0, 37, 0,251, 0, 10,
+ 0, 0, 0, 17, 0, 2, 0, 18, 0, 2, 7, 28, 0, 4, 2,116, 0, 4, 7, 29, 0, 4, 7, 30, 0, 4, 7, 31, 0, 4, 7, 32,
+ 0, 4, 7, 33, 0, 4, 7, 34, 0,252, 0, 1, 0, 0, 7, 35, 0,253, 0, 1, 0, 42, 5,131, 0,250, 0, 18, 0,250, 0, 0,
+ 0,250, 0, 1, 0,250, 7, 36, 0, 2, 0, 18, 0, 2, 0, 20, 0, 2, 7, 37, 0, 2, 7, 26, 0, 2, 7, 0, 0, 2, 7, 38,
+ 0, 2, 0, 70, 0, 2, 1, 8, 0, 0, 0, 17, 0, 9, 0, 2, 0,254, 7, 27, 0,249, 7, 39, 0, 2, 0, 15, 0, 2, 7, 40,
+ 0, 4, 7, 41, 0,255, 0, 3, 0, 4, 2,176, 0, 4, 0, 37, 0, 32, 0, 45, 1, 0, 0, 12, 0,139, 7, 42, 0, 2, 0, 18,
+ 0, 2, 0, 20, 0, 4, 6,224, 0, 4, 0, 92, 0, 0, 0, 17, 0, 0, 7, 43, 0, 2, 7, 44, 0, 2, 7, 45, 0, 2, 7, 46,
+ 0, 2, 7, 47, 0, 7, 7, 48, 1, 1, 0, 10, 0, 2, 0, 20, 0, 2, 7, 49, 0, 4, 6,224, 0, 4, 0, 92, 0, 2, 7, 50,
+ 0,221, 6,184, 0, 2, 0, 18, 0, 2, 7, 51, 0, 2, 7, 52, 0, 2, 7, 53, 1, 2, 0, 7, 0, 2, 0, 20, 0, 2, 7, 49,
+ 0, 4, 6,224, 0, 4, 0, 92, 0, 2, 0, 18, 0, 2, 7, 54, 0, 7, 7, 55, 1, 3, 0, 11, 0, 4, 2,176, 0, 2, 0, 18,
+ 0, 2, 0, 20, 0, 32, 0, 45, 0, 74, 7, 56, 0, 0, 0, 17, 0, 7, 7, 57, 0, 7, 7, 58, 0, 7, 0, 37, 0, 2, 7, 59,
+ 0, 2, 7, 60, 1, 4, 0, 5, 0, 2, 0, 18, 0, 2, 0, 20, 0, 4, 0, 37, 0,171, 6, 78, 0, 32, 4,211, 1, 5, 0, 5,
+ 0, 4, 0, 20, 0, 4, 0, 18, 0, 0, 0, 17, 0, 0, 7, 12, 0, 32, 0, 45, 1, 6, 0, 12, 0, 2, 0, 20, 0, 2, 0, 18,
+ 0, 2, 7, 0, 0, 2, 3, 11, 0, 7, 7, 61, 0, 7, 7, 62, 0, 7, 1, 3, 0, 7, 1, 4, 0, 7, 2,242, 0, 7, 2,245,
+ 0, 7, 7, 63, 0, 7, 7, 64, 1, 7, 0, 9, 0, 2, 0, 20, 0, 2, 0, 18, 0, 4, 6,224, 0, 4, 0, 92, 0, 0, 0, 17,
+ 0, 2, 0, 43, 0, 2, 0, 64, 0, 2, 7, 65, 0, 2, 7, 66, 1, 8, 0, 8, 0, 32, 0, 45, 0, 7, 2,147, 0, 7, 7, 67,
+ 0, 7, 7, 68, 0, 7, 2,142, 0, 2, 0, 20, 0, 2, 2,116, 0, 7, 7, 69, 1, 9, 0, 12, 0, 2, 0, 18, 0, 2, 1, 9,
+ 0, 2, 0, 20, 0, 2, 2,150, 0, 2, 2,176, 0, 2, 7, 70, 0, 4, 0, 37, 0, 7, 7, 71, 0, 7, 7, 72, 0, 7, 7, 73,
+ 0, 7, 7, 74, 0, 0, 7, 75, 1, 10, 0, 10, 0, 2, 0, 20, 0, 2, 0, 18, 0, 4, 6,224, 0, 4, 0, 92, 0, 0, 0, 17,
+ 0, 2, 0,181, 0, 2, 0, 64, 0, 2, 7, 65, 0, 2, 7, 66, 0, 63, 1,157, 1, 11, 0, 7, 0, 4, 2,105, 0, 4, 7, 76,
+ 0, 4, 7, 77, 0, 4, 7, 78, 0, 7, 7, 79, 0, 7, 7, 80, 0, 0, 7, 18, 1, 12, 0, 7, 0, 0, 7, 81, 0, 32, 7, 82,
+ 0, 0, 7, 22, 0, 2, 7, 83, 0, 2, 0, 43, 0, 4, 0, 70, 0, 0, 7, 23, 1, 13, 0, 6, 0, 2, 0, 20, 0, 2, 0, 18,
+ 0, 4, 6,224, 0, 4, 0, 92, 0, 0, 7, 84, 0, 0, 7, 85, 1, 14, 0, 1, 0, 4, 0, 20, 1, 15, 0, 6, 0, 0, 0, 95,
+ 0, 2, 0, 18, 0, 2, 0, 20, 0, 4, 7, 86, 0, 7, 7, 87, 0, 42, 5,131, 1, 16, 0, 3, 0, 0, 0, 95, 0, 4, 0, 18,
+ 0, 32, 0, 45, 1, 17, 0, 2, 0, 4, 0, 18, 0, 4, 5, 47, 0,254, 0, 10, 0,254, 0, 0, 0,254, 0, 1, 0,254, 7, 36,
+ 0, 2, 0, 18, 0, 2, 0, 20, 0, 2, 7, 0, 0, 2, 7, 88, 0, 0, 0, 17, 0, 9, 0, 2, 0, 32, 0, 45, 1, 18, 0, 10,
+ 0, 7, 3, 10, 0, 7, 7, 89, 0, 7, 7, 90, 0, 7, 7, 91, 0, 7, 7, 92, 0, 4, 0, 20, 0, 7, 7, 70, 0, 7, 7, 93,
+ 0, 7, 7, 94, 0, 7, 0, 37, 0,221, 0, 20, 0, 27, 0, 31, 0, 0, 0,192, 1, 19, 7, 95, 0, 9, 7, 96, 0, 43, 0,152,
+ 0, 43, 7, 97, 0, 9, 7, 98, 0, 36, 0, 79, 0, 7, 7, 55, 0, 7, 7, 99, 0, 7, 7,100, 0, 7, 7,101, 0, 7, 7,102,
+ 0, 7, 7,103, 0, 7, 7,104, 0, 4, 0, 93, 0, 4, 7,105, 0, 0, 7,106, 0, 0, 7,107, 0, 0, 7,108, 1, 20, 0, 6,
+ 0, 27, 0, 31, 0, 7, 7,109, 0, 7, 7,110, 0, 7, 7,111, 0, 2, 7,112, 0, 2, 7,113, 1, 21, 0, 14, 0,175, 0, 0,
+ 0,175, 0, 1, 0, 4, 4,247, 0, 7, 4,248, 0,176, 4,249, 0,181, 5, 60, 0,221, 6,184, 0, 2, 1, 9, 0, 2, 7, 49,
+ 0, 2, 2, 3, 0, 2, 2, 4, 0, 2, 0, 20, 0, 2, 5, 70, 0, 4, 0, 70, 1, 22, 0, 6, 1, 22, 0, 0, 1, 22, 0, 1,
+ 0, 32, 0, 45, 0, 9, 7,114, 0, 4, 0,217, 0, 4, 0, 37, 0, 63, 0, 4, 0, 27, 0, 31, 0, 12, 7,115, 0, 4, 0,135,
+ 0, 7, 7,116, 1, 23, 0, 25, 1, 23, 0, 0, 1, 23, 0, 1, 1, 23, 0, 38, 0, 12, 7,117, 0, 0, 0, 17, 0, 7, 7,118,
+ 0, 7, 7,119, 0, 7, 7,120, 0, 7, 7,121, 0, 4, 0, 20, 0, 7, 7,122, 0, 7, 7,123, 0, 7, 7,124, 0, 7, 1, 16,
+ 0, 7, 1,213, 0, 7, 7,125, 0, 7, 2,103, 0, 7, 7,126, 0, 7, 7,127, 0, 7, 7,128, 0, 7, 7,129, 0, 7, 7,130,
+ 0, 7, 0,175, 0, 2, 0,135, 0, 2, 4,154, 1, 24, 0, 19, 0, 27, 0, 31, 0, 12, 7,131, 0, 12, 7,132, 0, 4, 0, 20,
+ 0, 4, 3,226, 0, 2, 2,154, 0, 2, 7,133, 0, 2, 0,135, 0, 2, 7,134, 0, 2, 7,135, 0, 2, 7,136, 0, 2, 7,137,
+ 0, 2, 7,138, 0, 4, 7,139, 0, 4, 7,140, 0, 4, 7,141, 0, 4, 7,142, 0, 4, 7,143, 0, 4, 7,144, 1, 25, 0, 34,
+ 1, 25, 0, 0, 1, 25, 0, 1, 0, 12, 3, 34, 0, 0, 0, 17, 0, 2, 0, 20, 0, 2, 7,145, 0, 2, 7,146, 0, 2, 7,147,
+ 0, 2, 2,255, 0, 2, 7,148, 0, 4, 1,244, 0, 4, 7,141, 0, 4, 7,142, 1, 23, 7,149, 1, 25, 0, 38, 1, 25, 7,150,
+ 0, 12, 7,151, 0, 9, 7,152, 0, 9, 7,153, 0, 9, 7,154, 0, 7, 1, 3, 0, 7, 0,175, 0, 7, 1,195, 0, 7, 7,155,
+ 0, 7, 7,156, 0, 7, 2,247, 0, 7, 7,157, 0, 7, 7,158, 0, 7, 7,159, 0, 7, 7,160, 0, 7, 7,161, 0, 7, 7,162,
+ 0, 7, 1,241, 0, 32, 7,163, 0,140, 0, 9, 0, 12, 7,164, 0, 2, 0, 20, 0, 2, 7,165, 0, 7, 3, 9, 0, 7, 7,166,
+ 0, 7, 7,167, 0, 12, 7,168, 0, 4, 7,169, 0, 4, 0, 37, 1, 26, 0, 7, 1, 26, 0, 0, 1, 26, 0, 1, 0, 12, 7,106,
+ 0, 4, 0, 20, 0, 4, 7,170, 0, 0, 0, 17, 0,203, 7,171, 1, 27, 0, 8, 1, 27, 0, 0, 1, 27, 0, 1, 1, 26, 7,172,
+ 0, 36, 0, 79, 0, 12, 2,239, 0, 4, 0, 20, 0, 0, 0, 17, 0, 4, 7,173, 0,139, 0, 6, 0, 27, 0, 31, 0, 12, 7,164,
+ 0, 12, 7,174, 0, 12, 0,103, 0, 4, 7,175, 0, 4, 0, 37, 1, 28, 0, 16, 0,175, 0, 0, 0,175, 0, 1, 0, 4, 4,247,
+ 0, 7, 4,248, 0,176, 4,249, 0, 2, 4,250, 0,181, 5, 60, 0,139, 2,236, 0, 0, 1, 9, 0, 0, 5,130, 0, 2, 0, 20,
+ 0, 2, 7,176, 0, 2, 5, 67, 0, 2, 5, 70, 0, 2, 7,177, 0, 7, 7,178, 1, 29, 0, 5, 1, 29, 0, 0, 1, 29, 0, 1,
+ 0, 36, 0, 79, 0, 2, 0, 20, 0, 0, 7,179, 1, 30, 0, 12, 1, 30, 0, 0, 1, 30, 0, 1, 0, 9, 0, 2, 0, 2, 0, 18,
+ 0, 2, 0, 20, 0, 0, 7,180, 0, 0, 7,181, 0, 0, 7,179, 0, 7, 7,182, 0, 7, 7,183, 0, 4, 0, 37, 0, 36, 0, 79,
+ 1, 31, 0, 9, 1, 31, 0, 0, 1, 31, 0, 1, 0, 32, 7,184, 0, 0, 7,185, 0, 7, 7,186, 0, 2, 7,187, 0, 2, 0, 20,
+ 0, 2, 0, 18, 0, 2, 0, 37, 1, 32, 0, 7, 0, 42, 5,131, 0, 26, 7,188, 0, 4, 0, 20, 0, 4, 7,189, 0, 12, 7,190,
+ 0, 32, 7,184, 0, 0, 7,185, 1, 33, 0, 12, 0, 32, 7,184, 0, 2, 7,191, 0, 2, 0, 20, 0, 2, 7,192, 0, 2, 7,193,
+ 0, 0, 7,185, 0, 32, 7,194, 0, 0, 7,195, 0, 7, 7,196, 0, 7, 1,213, 0, 7, 7,197, 0, 7, 7,198, 1, 34, 0, 6,
+ 0, 32, 7,184, 0, 4, 7,173, 0, 4, 7,199, 0, 4, 0, 93, 0, 4, 0, 37, 0, 0, 7,185, 1, 35, 0, 4, 0, 32, 7,184,
+ 0, 4, 0, 20, 0, 4, 7,173, 0, 0, 7,185, 1, 36, 0, 4, 0, 32, 7,184, 0, 4, 0, 20, 0, 4, 7,173, 0, 0, 7,185,
+ 1, 37, 0, 10, 0, 32, 7,184, 0, 4, 7,200, 0, 7, 0,129, 0, 4, 0, 20, 0, 2, 5,125, 0, 2, 7,201, 0, 2, 0, 43,
+ 0, 2, 0, 70, 0, 7, 7,202, 0, 0, 7,185, 1, 38, 0, 4, 0, 32, 7,184, 0, 4, 0, 20, 0, 4, 7,173, 0, 0, 7,185,
+ 1, 39, 0, 10, 0, 32, 7,184, 0, 2, 0, 18, 0, 2, 3,113, 0, 4, 0, 91, 0, 4, 0, 92, 0, 7, 7, 67, 0, 7, 7, 68,
+ 0, 4, 0, 37, 0,139, 7, 42, 0, 0, 7,185, 1, 40, 0, 4, 0, 32, 7,184, 0, 4, 2,252, 0, 4, 7,203, 0, 0, 7,185,
+ 1, 41, 0, 5, 0, 32, 7,184, 0, 7, 0,129, 0, 4, 7,204, 0, 4, 2,252, 0, 4, 2,253, 1, 42, 0, 6, 0, 32, 7,184,
+ 0, 4, 7,205, 0, 4, 7,206, 0, 7, 7,207, 0, 7, 7,208, 0, 0, 7,185, 1, 43, 0, 16, 0, 32, 7,184, 0, 32, 7,150,
+ 0, 4, 0, 18, 0, 7, 7,209, 0, 7, 7,210, 0, 7, 7,211, 0, 7, 7,212, 0, 7, 7,213, 0, 7, 7,214, 0, 7, 7,215,
+ 0, 7, 7,216, 0, 7, 7,217, 0, 2, 0, 20, 0, 2, 0, 37, 0, 2, 0, 43, 0, 2, 0, 70, 1, 44, 0, 3, 0, 32, 7,184,
+ 0, 4, 0, 20, 0, 4, 5, 39, 1, 45, 0, 5, 0, 32, 7,184, 0, 4, 0, 20, 0, 4, 0, 37, 0, 7, 7,218, 0, 0, 7,185,
+ 1, 46, 0, 10, 0, 32, 7,184, 0, 0, 7,185, 0, 2, 7,219, 0, 2, 7,220, 0, 0, 7,221, 0, 0, 7,222, 0, 7, 7,223,
+ 0, 7, 7,224, 0, 7, 7,225, 0, 7, 7,226, 1, 47, 0, 8, 0, 7, 0, 9, 0, 7, 0, 10, 0, 7, 0, 11, 0, 7, 0, 12,
+ 0, 7, 7,227, 0, 7, 7,228, 0, 2, 0, 20, 0, 2, 5, 39, 1, 48, 0, 8, 0, 7, 0, 9, 0, 7, 0, 10, 0, 7, 0, 11,
+ 0, 7, 0, 12, 0, 7, 7,227, 0, 7, 7,228, 0, 2, 0, 20, 0, 2, 5, 39, 1, 49, 0, 8, 0, 7, 0, 9, 0, 7, 0, 10,
+ 0, 7, 0, 11, 0, 7, 0, 12, 0, 7, 7,227, 0, 7, 7,228, 0, 2, 0, 20, 0, 2, 5, 39, 1, 50, 0, 7, 0, 32, 7,184,
+ 0, 0, 7,185, 0, 7, 1, 16, 0, 7, 1, 26, 0, 2, 0, 20, 0, 2, 1, 9, 0, 4, 0, 37, 1, 51, 0, 10, 1, 51, 0, 0,
+ 1, 51, 0, 1, 0, 2, 0, 18, 0, 2, 0, 20, 0, 0, 7,229, 0, 7, 0,219, 0, 7, 0,220, 0, 2, 7,106, 0, 2, 7,230,
+ 0, 32, 0, 45, 1, 52, 0, 22, 1, 52, 0, 0, 1, 52, 0, 1, 0, 2, 0, 20, 0, 2, 1, 9, 0, 2, 7,231, 0, 2, 7,232,
+ 0, 36, 0, 79, 0,139, 7, 42, 0, 32, 0,167, 0, 7, 0, 91, 0, 7, 0, 92, 0, 7, 7,233, 0, 7, 7,234, 0, 7, 7,235,
+ 0, 7, 7,236, 0, 7, 2,143, 0, 7, 1,185, 0, 7, 7, 44, 0, 7, 7,237, 0, 0, 7,238, 0, 0, 7,239, 0, 12, 2,241,
+ 1, 53, 0, 8, 0, 7, 1,221, 0, 7, 7, 67, 0, 7, 7, 68, 0, 9, 0, 2, 0, 2, 7,240, 0, 2, 7,241, 0, 2, 7,242,
+ 0, 2, 7,243, 1, 54, 0, 18, 1, 54, 0, 0, 1, 54, 0, 1, 1, 54, 7,244, 0, 0, 0, 17, 1, 53, 7,245, 0, 2, 0, 18,
+ 0, 2, 0, 20, 0, 2, 7,246, 0, 2, 7,247, 0, 2, 7,248, 0, 2, 7,249, 0, 4, 0, 43, 0, 7, 7,250, 0, 7, 7,251,
+ 0, 4, 7,252, 0, 4, 7,253, 1, 54, 7,254, 1, 55, 7,255, 1, 56, 0, 30, 1, 56, 0, 0, 1, 56, 0, 1, 1, 56, 8, 0,
+ 0, 0, 0, 17, 0, 0, 8, 1, 0, 2, 0, 18, 0, 2, 0, 20, 0, 2, 6,152, 0, 2, 6,186, 0, 2, 8, 2, 0, 2, 0,137,
+ 0, 2, 7,247, 0, 2, 6,142, 0, 12, 7, 37, 0, 12, 8, 3, 0, 27, 5,158, 0, 9, 8, 4, 0, 7, 7,250, 0, 7, 7,251,
+ 0, 7, 1,246, 0, 7, 8, 5, 0, 2, 8, 6, 0, 2, 8, 7, 0, 2, 8, 8, 0, 2, 8, 9, 0, 24, 8, 10, 0, 24, 8, 11,
+ 0, 24, 8, 12, 1, 57, 0,153, 1, 58, 8, 13, 1, 55, 0, 6, 1, 55, 0, 0, 1, 55, 0, 1, 1, 56, 8, 14, 1, 56, 8, 15,
+ 1, 54, 8, 16, 1, 54, 7,254, 0, 62, 0, 16, 0, 27, 0, 31, 0, 12, 8, 17, 0, 12, 8, 18, 1, 53, 8, 19, 0, 12, 8, 20,
+ 0, 4, 0, 18, 0, 4, 8, 21, 0, 4, 8, 22, 0, 4, 8, 23, 0, 12, 8, 24, 1, 58, 8, 25, 1, 54, 8, 26, 1, 54, 8, 27,
+ 0, 9, 8, 28, 0, 9, 8, 29, 0, 4, 8, 30, 1, 59, 0, 6, 0, 4, 0,128, 0, 4, 0,130, 0, 4, 6,142, 0, 0, 8, 31,
+ 0, 0, 8, 32, 0, 2, 0, 37, 1, 60, 0, 16, 0, 2, 6, 81, 0, 2, 6, 82, 0, 2, 8, 33, 0, 2, 7, 90, 0, 2, 8, 34,
+ 0, 2, 0, 68, 0, 7, 2,142, 0, 7, 8, 35, 0, 7, 8, 36, 0, 2, 1, 30, 0, 0, 8, 37, 0, 0, 3,238, 0, 2, 8, 38,
+ 0, 2, 0, 37, 0, 4, 8, 39, 0, 4, 8, 40, 1, 61, 0, 9, 0, 7, 8, 41, 0, 7, 8, 42, 0, 7, 7,104, 0, 7, 0,112,
+ 0, 7, 8, 43, 0, 7, 4,243, 0, 2, 8, 44, 0, 0, 8, 45, 0, 0, 0, 37, 1, 62, 0, 4, 0, 7, 8, 46, 0, 7, 8, 47,
+ 0, 2, 8, 44, 0, 2, 0, 37, 1, 63, 0, 3, 0, 7, 8, 48, 0, 7, 8, 49, 0, 7, 0, 15, 1, 64, 0, 7, 0, 0, 1,184,
+ 0, 2, 4, 49, 0, 2, 4, 50, 0, 2, 4, 51, 0, 2, 4, 2, 0, 4, 0,130, 0, 4, 3,111, 1, 65, 0, 7, 0, 7, 8, 50,
+ 0, 7, 8, 51, 0, 7, 8, 52, 0, 7, 1,255, 0, 7, 8, 53, 0, 7, 8, 54, 0, 7, 8, 55, 1, 66, 0, 4, 0, 2, 8, 56,
+ 0, 2, 8, 57, 0, 2, 8, 58, 0, 2, 8, 59, 1, 67, 0, 2, 0, 7, 0, 5, 0, 7, 0, 6, 1, 68, 0, 2, 0, 0, 0,169,
+ 0, 0, 8, 60, 1, 69, 0, 1, 0, 0, 0, 17, 1, 70, 0, 10, 0, 0, 8, 61, 0, 0, 8, 62, 0, 0, 8, 63, 0, 0, 8, 64,
+ 0, 2, 8, 33, 0, 2, 8, 65, 0, 7, 8, 66, 0, 7, 8, 67, 0, 7, 8, 68, 0, 7, 1,185, 1, 71, 0, 2, 0, 9, 8, 69,
+ 0, 9, 8, 70, 1, 72, 0, 11, 0, 0, 4, 51, 0, 0, 0, 18, 0, 0, 8, 44, 0, 0, 0,112, 0, 0, 8, 71, 0, 0, 0,109,
+ 0, 0, 2, 71, 0, 7, 8, 72, 0, 7, 8, 73, 0, 7, 8, 74, 0, 7, 8, 75, 1, 73, 0, 8, 0, 7, 7, 7, 0, 7, 0,129,
+ 0, 7, 3,238, 0, 7, 2, 66, 0, 7, 8, 76, 0, 7, 0,206, 0, 7, 8, 77, 0, 4, 0, 18, 1, 74, 0, 4, 0, 2, 8, 78,
+ 0, 2, 8, 79, 0, 2, 8, 80, 0, 2, 0, 37, 1, 75, 0, 4, 0, 7, 0, 5, 0, 7, 0, 6, 0, 2, 0, 20, 0, 2, 8, 81,
+ 1, 76, 0, 10, 0, 2, 3, 93, 0, 2, 0, 20, 0, 7, 3,184, 0, 7, 8, 82, 0, 7, 8, 83, 0, 7, 8, 84, 0, 7, 8, 85,
+ 1, 75, 8, 86, 1, 75, 8, 87, 1, 75, 8, 88, 0, 59, 0, 9, 0, 4, 0, 20, 0, 4, 0, 64, 0, 24, 8, 89, 0, 24, 8, 90,
+ 1, 76, 8, 91, 0, 7, 8, 92, 0, 7, 8, 93, 0, 7, 8, 94, 0, 7, 8, 95, 1, 77, 0, 4, 0, 46, 2,136, 0, 7, 8, 96,
+ 0, 7, 1, 85, 0, 7, 0, 37, 0,163, 0, 13, 0, 27, 0, 31, 0, 2, 0, 20, 0, 2, 4,244, 0, 4, 0,109, 0, 7, 8, 97,
+ 0, 7, 1,252, 0, 7, 8, 98, 0, 7, 8, 99, 0, 7, 1, 85, 0, 2, 1, 43, 0, 2, 0, 37, 0, 50, 1, 70, 1, 77, 8,100,
+ 1, 78, 0, 8, 0, 4, 0, 18, 0, 4, 0,129, 0, 4, 0, 20, 0, 4, 3, 55, 0, 4, 8,101, 0, 0, 0, 95, 0, 0, 0, 17,
+ 0, 9, 0, 2, 0, 84, 0, 6, 1, 78, 8,102, 0, 4, 8,103, 0, 4, 8,104, 0, 4, 8,105, 0, 4, 0, 37, 0, 9, 8,106,
+ 1, 79, 0, 5, 0, 7, 2, 61, 0, 7, 2,176, 0, 7, 1,213, 0, 2, 8,107, 0, 2, 0, 37, 1, 80, 0, 5, 0, 7, 2, 61,
+ 0, 7, 8,108, 0, 7, 8,109, 0, 7, 8,110, 0, 7, 2,176, 1, 81, 0, 7, 0, 4, 8,111, 0, 4, 8,112, 0, 4, 8,113,
+ 0, 7, 8,114, 0, 7, 8,115, 0, 7, 8,116, 0, 7, 8,117, 1, 82, 0, 25, 0, 32, 8,118, 1, 80, 3, 51, 1, 79, 8,119,
+ 1, 80, 6,249, 0, 7, 8,120, 0, 7, 8,121, 0, 7, 8,122, 0, 7, 8,123, 0, 7, 8,115, 0, 7, 8,116, 0, 7, 2,176,
+ 0, 7, 2,153, 0, 7, 8,124, 0, 7, 8,125, 0, 7, 0,109, 0, 7, 8,126, 0, 4, 8,111, 0, 4, 8,127, 0, 4, 0, 37,
+ 0, 4, 0, 81, 0, 4, 8,128, 0, 2, 0, 20, 0, 2, 8,129, 0, 2, 8,130, 0, 2, 3, 85, 1, 83, 0,112, 0, 27, 0, 31,
+ 0, 4, 0, 20, 0, 2, 0, 18, 0, 2, 7,219, 0, 2, 8,131, 0, 2, 8,132, 0, 2, 8,133, 0, 2, 8,134, 0, 2, 8,135,
+ 0, 2, 8,136, 0, 2, 8,137, 0, 2, 8,138, 0, 2, 8,139, 0, 2, 8,140, 0, 2, 8,141, 0, 2, 8,142, 0, 2, 8,143,
+ 0, 2, 8,144, 0, 2, 8,145, 0, 2, 1,205, 0, 2, 6,242, 0, 2, 6,218, 0, 2, 8,146, 0, 2, 8,147, 0, 2, 3, 83,
+ 0, 2, 3, 84, 0, 2, 8,148, 0, 2, 8,149, 0, 2, 8,150, 0, 2, 8,151, 0, 2, 8,152, 0, 2, 8,153, 0, 7, 8,154,
+ 0, 7, 8,155, 0, 7, 8,156, 0, 2, 8,157, 0, 2, 8,158, 0, 7, 8,159, 0, 7, 8,160, 0, 7, 8,161, 0, 7, 6,224,
+ 0, 7, 0, 92, 0, 7, 2,153, 0, 7, 6,230, 0, 7, 8,162, 0, 7, 8,163, 0, 7, 8,164, 0, 7, 8,165, 0, 7, 0, 57,
+ 0, 4, 6,225, 0, 4, 6,223, 0, 4, 8,166, 0, 7, 6,226, 0, 7, 6,227, 0, 7, 6,228, 0, 7, 8,167, 0, 7, 8,168,
+ 0, 7, 8,169, 0, 7, 8,170, 0, 7, 8,171, 0, 7, 8,172, 0, 7, 8,173, 0, 7, 8,174, 0, 7, 3, 10, 0, 7, 0,109,
+ 0, 7, 8,175, 0, 7, 8,176, 0, 7, 8,177, 0, 7, 8,178, 0, 7, 8,179, 0, 7, 8,180, 0, 7, 2,103, 0, 7, 8,181,
+ 0, 7, 8,182, 0, 4, 8,183, 0, 4, 8,184, 0, 7, 8,185, 0, 7, 8,186, 0, 7, 8,187, 0, 7, 8,188, 0, 7, 8,189,
+ 0, 7, 8,190, 0, 7, 8,191, 0, 7, 8,192, 0, 7, 3, 79, 0, 7, 3, 77, 0, 7, 3, 78, 0, 7, 8,193, 0, 7, 8,194,
+ 0, 7, 8,195, 0, 7, 8,196, 0, 7, 8,197, 0, 7, 8,198, 0, 7, 8,199, 0, 7, 8,200, 0, 7, 8,201, 0, 7, 8,202,
+ 0, 7, 8,203, 0, 7, 8,204, 0, 7, 8,205, 0, 7, 8,206, 0, 7, 8,207, 0, 7, 8,208, 0, 7, 8,209, 0, 0, 8,210,
+ 0, 63, 3, 40, 0, 63, 8,211, 0, 32, 8,212, 0, 32, 8,213, 0, 36, 0, 79, 0,141, 3, 38, 0,141, 8,214, 0,132, 0, 37,
+ 0,132, 0, 0, 0,132, 0, 1, 1, 83, 8,215, 1, 82, 3, 92, 1, 81, 7,150, 1, 84, 8,216, 1, 85, 8,217, 1, 85, 8,218,
+ 0, 12, 8,219, 0, 12, 8,220, 0,142, 3, 39, 0, 32, 8,221, 0, 32, 8,222, 0, 32, 8,223, 0, 12, 8,224, 0, 12, 8,225,
+ 0, 7, 0,210, 0, 7, 4, 23, 0, 4, 2,105, 0, 4, 0, 20, 0, 4, 6,225, 0, 4, 8,226, 0, 4, 8,227, 0, 4, 8,228,
+ 0, 4, 0, 57, 0, 2, 0,217, 0, 2, 8,229, 0, 2, 8,230, 0, 2, 8,231, 0, 2, 3, 32, 0, 2, 8,232, 0, 0, 8,233,
+ 0, 2, 8,234, 0, 2, 8,235, 0, 2, 8,236, 0, 9, 8,237, 0,124, 3,132, 0,122, 0, 34, 1, 86, 8,238, 0, 7, 3,104,
+ 0, 7, 8,239, 0, 7, 8,240, 0, 7, 3,187, 0, 7, 8,241, 0, 7, 3, 17, 0, 7, 3, 10, 0, 7, 8,242, 0, 7, 1,254,
+ 0, 7, 8,243, 0, 7, 8,244, 0, 7, 8,245, 0, 7, 8,246, 0, 7, 8,247, 0, 7, 8,248, 0, 7, 3,105, 0, 7, 8,249,
+ 0, 7, 8,250, 0, 7, 8,251, 0, 7, 3,106, 0, 7, 3,102, 0, 7, 3,103, 0, 4, 8,252, 0, 4, 0, 93, 0, 4, 8,253,
+ 0, 4, 8,254, 0, 2, 8,255, 0, 2, 9, 0, 0, 2, 9, 1, 0, 2, 9, 2, 0, 2, 9, 3, 0, 2, 0, 37, 0, 4, 0, 70,
+ 0,123, 0, 8, 1, 86, 9, 4, 0, 7, 9, 5, 0, 7, 9, 6, 0, 7, 1,158, 0, 7, 9, 7, 0, 4, 0, 93, 0, 2, 9, 8,
+ 0, 2, 9, 9, 1, 87, 0, 4, 0, 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 7, 0, 7, 9, 10, 1, 88, 0, 6, 1, 88, 0, 0,
+ 1, 88, 0, 1, 1, 87, 9, 11, 0, 4, 9, 12, 0, 2, 9, 13, 0, 2, 0, 20, 1, 89, 0, 5, 1, 89, 0, 0, 1, 89, 0, 1,
+ 0, 12, 9, 14, 0, 4, 9, 15, 0, 4, 0, 20, 1, 90, 0, 9, 1, 90, 0, 0, 1, 90, 0, 1, 0, 12, 0,128, 1, 89, 9, 16,
+ 0, 4, 0, 20, 0, 2, 9, 13, 0, 2, 9, 17, 0, 7, 0, 94, 0, 0, 9, 18, 0,180, 0, 5, 0, 12, 4, 65, 0, 4, 0, 20,
+ 0, 2, 9, 19, 0, 2, 9, 20, 0, 9, 9, 21, 69, 78, 68, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
diff --git a/source/blender/editors/datafiles/prvicons.c b/source/blender/editors/datafiles/prvicons.c
new file mode 100644
index 00000000000..2a470e056cf
--- /dev/null
+++ b/source/blender/editors/datafiles/prvicons.c
@@ -0,0 +1,304 @@
+/* DataToC output of file <prvicons> */
+
+int datatoc_prvicons_size= 9534;
+char datatoc_prvicons[]= {
+137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0,192, 0, 0, 0,192, 8, 6, 0, 0, 0, 82,
+220,108, 7, 0, 0, 0, 1,115, 82, 71, 66, 0,174,206, 28,233, 0, 0, 0, 6, 98, 75, 71, 68, 0,255, 0,255, 0,255,160,189,
+167,147, 0, 0, 0, 9,112, 72, 89,115, 0, 0, 11, 19, 0, 0, 11, 19, 1, 0,154,156, 24, 0, 0, 0, 7,116, 73, 77, 69, 7,
+217, 3, 14, 12, 53, 26, 8,211, 40, 12, 0, 0, 0, 29,116, 69, 88,116, 67,111,109,109,101,110,116, 0, 67,114,101, 97,116,101,
+100, 32,119,105,116,104, 32, 84,104,101, 32, 71, 73, 77, 80,239,100, 37,110, 0, 0, 32, 0, 73, 68, 65, 84,120,218,237,125,123,
+120, 20, 85,182,239,175, 30, 93,213,121,116, 58, 47, 72, 32, 64,194, 0,137,134, 16, 68, 6, 6, 66, 8,207,235, 1,230,160,131,
+115,124,220, 17,189,119,230,206,225, 19,207,232,204,248, 64, 16,197,232,213,113, 12,160,163, 40,122, 70, 4, 6,225,115,102,206,
+209, 15,225,158,163, 3,142,142, 56, 38,228, 33, 4, 3, 73, 32, 60, 66, 72, 32,129,188, 31,221,233, 71, 85,221, 63,160,234, 84,
+ 63,211,143,170,238,228,176,127,223,215, 95, 63,170,171,123,213,174,223, 90,123,173,181,215,222, 27, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,184, 14,234,102,186,216, 89,179,102,165,139,162,120, 24, 64,158, 94,255,
+193,113, 92, 91, 89, 89, 89,186, 30,191, 61,121,242,100, 62, 41, 41,105,142, 32, 8, 38,189,228, 55, 24, 12,182,242,242,242,195,
+ 55, 11, 39,216,155,133, 64, 55,100,255,242,181,215, 94,227,138,138,138, 80, 85, 85,133,140,140, 12, 24,141, 70, 48, 12, 3,138,
+162, 64,211,244,127, 89, 6,138,242,251, 90,253,153,252,222, 98,177, 96,233,210,165,105,122,145, 63, 49, 49,113,238,150, 45, 91,
+232,162,162, 34, 28, 59,118, 12, 25, 25, 25,224, 56, 14, 44,123,253, 54, 50, 12,227,243,124,127,199,100,216,237,118, 44, 92,184,
+144,191,153,140, 34, 27, 44,129,182,110,221,202, 45, 88,176, 64, 33, 16,207,243, 96, 24, 6, 52, 77,123,144, 99, 40,226,184,191,
+214,139, 64,178,236, 91,182,108,225,139,138,138, 38, 2, 64, 85, 85, 21, 6, 7, 7,145,144,144, 0,150,101,149,107,144,175,195,
+215,195,223,241, 11, 23, 46, 64, 79,242,191,250,234,171,116, 81, 81, 81, 44, 0, 84, 84, 84, 32, 47, 47, 15,137,137,137,138,252,
+106,146,203, 74,225, 78,126, 95,159, 51, 12,163,155,252, 35, 94, 1,212, 4, 90,176, 96,193, 68, 0, 40, 47, 47, 71, 94, 94, 30,
+204,102,179, 79, 2,185,147,101,168, 99,231,207,159,215,203,237,249,114,243,230,205,252,194,133, 11, 39,202,159,211, 52, 13, 81,
+ 20, 93, 20,208, 31,185, 3, 85, 12, 61,201,191,120,241,226,216, 64, 44,122, 40,228,191, 89,193,134, 74, 32,134, 97, 32, 73,146,
+ 79, 2, 5, 75,126,249,181, 30,228, 47, 41, 41, 49, 46, 90,180, 40,203,151, 75, 16, 14,249,245,146,221, 31,249,221,201,172,190,
+158, 80,201,239,254,123, 68, 1,194, 32, 80,168,228,215,146, 68,106,217, 23, 47, 94,156,229,205, 39, 14,150,224,129, 28,139, 4,
+249, 3, 33, 49, 33,127,152, 10, 16, 40,129,100,119, 34, 88,242,251,250, 94, 36,200, 47,223,116, 57,232,213,138,252, 90,201, 63,
+ 20,249,229,246,247,229,186,132, 74,254,155,209, 21, 98, 67, 37,144,193, 96, 8,217,210,235,233, 2,169, 93, 54,247, 94, 75, 13,
+158,247, 76,118, 4,235,239,235,161, 0,129,144,223,151,252,196,242,107,160, 0,129, 18,136,227, 56,175,228, 9,135,252,234, 52,
+100,184,217, 30,117,188, 2, 0, 54,155, 13,141,141,141,104,106,106, 66,103,103,167, 75,250, 51, 92,171,175,149,252,254,200,111,
+179,217,112,225,194, 5, 52, 53, 53,161,171,171, 11,177,177,177, 30,100, 15,135,252, 55,107, 32,204, 6, 67, 32,249, 6,116,118,
+118, 34, 38, 38,198, 37,127, 30,109,242, 3,128, 40,138,135,111,228,249, 39,138,162,136,150,150, 22,212,213,213,225,244,233,211,
+104,111,111, 71, 66, 66, 2,146,147,147, 97, 54,155, 97, 50,153, 60, 20, 32,220, 88, 32, 92, 36, 37, 37,205,185,145,231,143, 21,
+ 4, 1, 45, 45, 45,168,175,175, 71, 67, 67, 3,218,219,219, 97, 50,153,144,148,148,132,196,196, 68,152, 76, 38,176, 44,235, 65,
+252,112,200,127,211,187, 64,162, 40, 30,190,145,231, 87, 8, 84, 91, 91,171, 16,200,100, 50, 33, 57, 57, 25,137,137,137,136,139,
+139,115,201,255,135, 75,126,141, 92,136,188,220,220, 92,108,223,190, 29, 13, 13, 13, 96, 24, 6,105,105,105, 72, 73, 73,193,216,
+177, 99,149, 65, 35,142,227, 96, 52, 26, 21, 2, 13,149,255, 15,230, 88, 56, 16, 4,193,148,155,155,139,183,223,126, 27,231,207,
+159, 7,195, 48, 24, 53,106, 20, 82, 83, 83,145,159,159, 15,150,101,193,243, 60, 56,142, 83,198, 95,124, 89,125, 66,254,208, 92,
+160,188,169, 83,167,226,173,183,222, 66, 67, 67, 3, 88,150, 69, 90, 90, 26,146,147,147, 49,109,218, 52,133, 64, 60,207,195,104,
+ 52,194, 96, 48,128,101, 89,205,200,175,133, 21,237,235,235, 67,124,124, 60,138,138,138,144,152,152,168, 4,233,234, 96,221, 96,
+ 48,120,144,200, 23,201, 35,157, 5,234,237,237,133,201,100, 66, 97, 97, 33,146,146,146, 60,200, 45,203,203,243,188, 34,191,183,
+ 94,128,144, 63,196, 24,160,183,183, 23,113,113,113, 10,129,220, 51, 61, 52, 77, 43, 74,192,243,188,242, 62,216,108,143,175, 99,
+225, 34, 46, 46, 14,249,249,249, 16, 4, 65,137, 77,212,207, 52, 77,131, 97, 24, 24, 12, 6,229,217, 91, 15, 16,106, 32, 28, 46,
+ 18, 18, 18, 48,125,250,116, 69,126, 95,153, 31,119,242, 19,183, 71, 35, 5,144, 9,228, 62, 74,170, 38, 16,203,178, 10,113, 56,
+142,115, 33, 80,184, 46, 81,216, 23,116,195,197,145, 36,201, 43,249,229,255, 83, 91,126,173, 98, 1, 45,228,151,173,187,211,233,
+ 28,146,180, 90,146, 95,118, 7,111,122, 5,144,173,187, 40,138, 30, 55, 86, 38,250,147,123,175,225,211,138, 86, 8,162, 20,210,
+159,246,239, 95,161, 91, 26, 84,125, 35,101, 37, 80, 63,220, 7,192,130,177,252,145, 8,132,189,213,245,248,203,238,120, 35,127,
+ 32,113,129,191,239,220,244, 10,160,190, 1,238, 55,153,166,105,252,105,195,237,232, 24, 0,254, 87, 73, 37,190,172,190,170,156,
+219,189,255, 71, 48,199, 25, 92,126,175,173,107, 16,223,157,239,193, 75,251,234,112,164,230,154,223,148,169, 22, 80,187, 82, 90,
+167, 56,135, 74,127,106,117, 13,129,100,117, 66, 33, 54, 33,191, 39,104, 95, 4,146,173,139,252,144, 3, 94,134, 97,208,209,209,
+ 1,214,217,131, 23, 30,204,113, 57,183,179,163, 3,237,237,237,232,232,232, 64,103,103, 39,186,186,186, 16,195,216, 49,239, 86,
+ 19, 62, 47, 41,196,242,217,233,126, 7,156,180,136, 1,180, 28,213, 13,134,252,122, 21,195, 69,138,252, 55,107, 44,224, 83, 1,
+134,242,221, 69, 81, 68, 70,162,251,205,242, 78,104, 65, 16, 96,183,217,240,220, 3,183,250,253, 15,173,160, 21,249, 3, 77,143,
+234, 85, 16, 71,200, 31, 5, 23,200, 87,208,232, 77, 17,226, 88,215, 27,206,120, 33,132,250,253,237,147, 76, 88,124,219,104, 93,
+201,239, 79,126, 45, 21, 67,175, 58, 32,119,191, 62, 28,242, 7, 26, 71,144, 44, 80,144, 46,132,175,238,158,166,135,174,243, 57,
+252,234,124, 8,130,160, 43,249,135,122,232,161, 24,122,129,144, 63, 10, 61,128,123, 16, 25,232,192, 21,195, 12,237, 58,233, 73,
+126, 95,242,235, 29, 11, 16,242,255, 55,139, 1, 66, 29,184,162,189,156,247, 96,201, 49,175,196,209,139,252,122,184, 60,145, 38,
+191, 58, 11, 71,200, 63, 76, 98,128, 64, 6,174, 24,198,245,152,213, 46,226,179,170,171, 17, 35,191,187,252,122,250,251,122, 90,
+126, 45,130, 89, 66,126, 13, 99,128, 64,235,247,153, 27, 89, 19,135, 32,161,165,221,138,205,255,126, 14, 22,155, 16,113,242,171,
+ 21, 64,175, 64, 56,146,196, 39,228,143, 98, 12, 16, 76, 9,115,194,221,159,249, 37,165,222,228, 15, 38, 11, 20,205, 73, 47,129,
+248,253,132,252, 81,238, 1, 2, 73,131,186,147, 65, 58,124, 15, 0,192,238, 20,113,233,170, 5,191,249,176, 30, 59, 63,187, 16,
+ 81,242, 7,146, 9,138,102,173, 79,168, 10, 65,200, 31,161, 32, 56, 80,203,239,141, 16, 86,171, 21, 54,155, 13, 16,157,200, 28,
+109,196, 27,143, 76, 71, 44,207, 16,242, 19,242,143, 60, 5, 8,165,126,223, 93, 49, 98,121, 6, 63,252,193,152,136, 95, 20, 33,
+ 63, 33,127, 84,210,160,222,206,251,243,115,115,163, 78,254,112,102,124, 17,242,223,164,105,208, 80,234,247,189, 29, 83, 47,158,
+ 21, 13, 37, 8,135,248,209, 32,127, 48,196, 38, 19,220,117, 10,130, 67,157,194,168,231, 18,129,161, 40, 0, 33, 63, 65,216, 49,
+ 64, 80, 35,193,132,252,218, 90, 39, 66,254,232,198, 0, 67,145,191,215,226,116, 57,215,253,125,212, 46,106, 4,147, 95, 38, 53,
+ 33,127,148,123,128, 64,252,255, 51, 45, 3, 46,231,213, 94,236,141,250, 5,133, 90,219, 79, 44, 63, 81, 0,175, 22,212, 23,249,
+ 47,180, 90,240,236,238, 90,151,243,214,191, 95,131,186,166,225,167, 4,129, 16,127,184,144,223, 23,177, 9,249, 35, 24, 4, 15,
+ 69,254, 5, 79,126,141,163,117,157, 30, 63,246,117, 77, 59,166,254,252, 16,242,191,103,198,161,223, 22, 97,116, 34, 31,117, 5,
+ 32,228, 39, 8, 74, 1, 2,201, 4,149,189,185,100,200, 31,142, 70,250,147,144,159, 64,147, 30, 96,168,165, 66,228, 37, 83,134,
+173, 95, 23, 0,241, 35, 89,158, 17,174, 34, 16,242, 71, 33, 8,142,196, 58,254,145, 12,130, 9,249, 9, 2, 82,128,145, 76,254,
+ 64,148,128,144,159, 32,172, 24, 96,184,195,110,183,227,236,217,179, 94,253,124,189,201,111, 48, 24,194,254, 13,167,211,137,134,
+134, 6,175, 10,160, 55,220,247,124,184, 41, 21,192,225,112,224,220,185,115, 81, 9, 22,195, 37, 16,207,243,109,243,231,207, 79,
+139,102,131,242, 60,223, 22,234,185, 49, 49, 49,182,130,130,130,168,238,211, 27, 19, 19, 99,187,153, 20,192,133,213, 5, 5, 5,
+173, 54,155, 45,234, 4, 42, 45, 45, 77, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,129, 38,
+ 8, 42,185,127, 99, 31,225,195, 0,242,244, 18,136,227,184,182,178,178, 50, 93,210,160,179,102,205,202, 23, 69,177, 28,128, 81,
+ 71,249,197,178,178, 50, 70, 39,249, 71,122,251, 15, 59,249,217, 32,133,255,242,198, 62,194,168,170,170,194,184,113,227,192,243,
+188,178, 85,170,251,128, 89,176,175,173, 86, 43,150, 44, 89,146,166, 35,249, 43,183,110,221, 74,233, 44, 63,173, 35,121,148,246,
+175,172,172, 68, 70, 70,134,135,252,190,228,243, 54,127,219,253,243,190,190, 62, 44, 95,190, 60, 77, 79,249,111,108,100, 62,108,
+248,195, 6, 35,252,150, 45, 91,248, 5, 11, 22, 76, 4,128,170,170, 42,216,108, 54,152,205,102,101,235, 36,127, 19,105, 2, 41,
+ 83, 62,127,254, 60,244, 36,255,230,205,155,233, 5, 11, 22,176, 35, 80,254,116, 81, 20,191,220,188,121,179,210,254,229,229,229,
+152, 58,117, 42, 18, 18, 18,188,202, 31,202,242,143, 23, 46, 92,208, 85,254, 45, 91,182,240, 69, 69, 69,195,138, 63,108, 48,194,
+ 47, 92,184,112,162,114, 34,203,186,212,252, 7, 34, 96, 36,118, 89,244, 71,254, 69,139, 22,177, 35, 80,254,116, 81, 20,191,124,
+245,213, 87,249, 69,139, 22, 41,237,207, 48,140,178,149,173, 86,107,159,234, 77,254,225,200, 31, 54, 64,203, 99, 92,184,112, 97,
+150,250,152, 92, 88,230,190, 21,105,184, 59,174,235, 65,254,146,146, 18, 23,242,143, 32,249,101,242, 27,151, 44, 89,226,209,254,
+238,174, 64,160,147,128, 34,181,240,239, 72,224, 15, 29,136,240,139, 22, 45,202,242,208,156, 27,126, 91, 32,141, 31, 76,119,166,
+ 7,249, 23, 47, 94,204,142, 64,249,125,146, 95,238, 1, 2,149, 63, 26,171,224,141, 20,254,176,161, 8,175,190, 0, 45,133,215,
+234, 6, 12, 69,254, 17, 32,191, 95,242,123, 35,144, 22,228,215,170, 92, 60, 16,254, 28, 56,112, 0,102,179, 25, 70,163, 17, 44,
+203,186,244,104,238,138,225, 45,104,151,229,125,250,233,167,181, 85, 0, 55,159, 45,203,215,137,114,233,178,183,110, 56, 28, 82,
+233,229,243,123,147,223, 91,214, 97, 24,200,175,248,252,190,200,175,110,127,111,132, 9,101, 85, 12,173, 98,152, 64,249,115,223,
+125,247, 33, 35, 35, 3,102,179, 25, 28,199,193, 96, 48, 40,189, 90, 36,219,159, 13, 36, 96, 1, 0,155,205,134,198,198, 70, 52,
+ 53, 53,161,171,171, 75,209,220, 96, 27, 93,207, 46,216, 31,249,189,201,207, 48, 12,174, 94,189,170,108, 6, 62,126,252,248, 33,
+229, 60,119,238,156,226,187,222,122,235,173, 90,203,175,100,123,212, 1,175, 44,255,133, 11, 23,112,241,226, 69,180,183,183, 35,
+ 38, 38,198,107,230, 39, 28,242,107, 37,191, 55,254,244,247,247,163,186,186, 26,199,142, 29,195,201,147, 39, 49, 48, 48,128,184,
+184, 56,151, 13,216, 3,181,252,234, 9, 78,235,215,175,215, 78, 1, 68, 81, 60,124, 35, 79, 59, 81, 20, 69,180,180,180,160,190,
+190, 30,167, 79,159, 70, 71, 71, 7,226,227,227,145,146,146, 2,179,217,140,132,132, 4, 69,232, 64,211,111,122,103, 81, 68, 81,
+ 44,191,145,231,103, 3,149,191,170,170, 10, 63,254,241,143,113,240,224, 65,165, 87,240,230, 87,202,159,151,150,150,226,167, 63,
+253, 41,118,237,218,133,220,220, 92,173,229, 63,124, 35,207, 63, 81, 20, 69, 52, 55, 55,163,174,174, 14,245,245,245,104,111,111,
+ 71,124,124, 60,146,146,146,144,148,148,132,184,184, 56, 15,139, 25, 77,242, 7,195,159,229,203,151, 35, 41, 41, 9, 38,147, 9,
+177,177,177,202, 88,128, 47, 62, 69, 50, 11,148,151,155,155,139,237,219,183,227,236,217,179, 96, 24, 6,163, 71,143, 70,106,106,
+ 42,198,142, 29, 11,142,227,192,178, 44,120,158, 87,122, 0,117, 47,160,197, 70,116, 97,194, 56,117,234,212,160,228, 63,118,236,
+ 24,142, 31, 63, 14,138,162,144,158,158,238,211,250, 40, 75,194,148,149,161,180,180, 20,146, 36,225,231, 63,255,185,214,242,231,
+229,230,230,226,173,183,222, 66, 67, 67, 3,104,154, 86,228,207,203,203, 83,172, 37,207,243,136,137,137, 81,222, 15,163, 93, 47,
+125,242,231,155,111,190, 1, 69, 81,202, 70,224, 44,203, 42,110,143, 58, 6, 8,196,242,171,123,128, 13, 27, 54,132,213,254, 30,
+ 62,114,127,127, 63, 76, 38, 19, 22, 44, 88,128,196,196, 68, 23, 63, 83, 94, 94,208, 96, 48,192, 96, 48,128,231,121,208, 52,173,
+108,235,169,133, 59, 20, 46,130,149,191,178,178, 82,249,206,209,163, 71, 21,247, 70,126,200,239,213,159,203,175,245,144,191,175,
+175, 15,177,177,177, 40, 44, 44,132,217,108,246, 32,128, 76, 24,142,227,192,113,156,210,246,129, 14, 34,233, 29,195,248,106,255,
+181,107,215,122,180,191,209,104, 84, 94,187, 43, 65,164,248,227,161, 0,113,113,113,152, 62,125, 58, 4, 65, 80,114,180,234,220,
+173, 76,120,131,193,160, 92,140, 63, 95, 52,216,207,195, 69,176,242,159, 59,119, 14,205,205,205, 24, 55,110, 92, 80, 36, 53,153,
+ 76,186,200, 31, 27, 27,139,105,211,166, 65, 20, 69,143,129, 34,185,205,100,249,213,214, 83, 62, 22,110, 76,160, 87,251,255,254,
+247,191,247,112, 39,101,222,248,202, 0,249,139, 7,228,199,198,141, 27,181, 85, 0,185,107, 82,167,217,188,237, 28,175,182,252,
+222,172,191, 32, 8,104,105,105,193,165, 75,151,208,218,218,138,246,246,118,116,117,117, 97, 96, 96, 0, 91,183,110,213,237, 6,
+ 4, 43, 63, 0,133,252,197,197,197,160,105, 26, 5, 5, 5,200,205,205, 69, 74, 74, 10, 58, 58, 58, 80, 91, 91,139,210,210, 82,
+136,162,136,226,226, 98,152, 76, 38,159, 89, 23, 45,228,231, 56,206,101,241, 49, 95,139, 21,171, 13,207,156, 57,115,208,214,118,
+125, 62,126,122,122, 58, 42, 43, 43, 67, 42,141,208,171,253,127,245,171, 95, 5,197,159,168,100,129,228, 1, 22,121, 57, 14,111,
+221,188,250, 61,195, 48,232,237,237, 69, 83, 83, 19,174, 92,185,130,107,215,174,161,171,171, 11,189,189,189,176, 88, 44,232,237,
+237, 69, 79, 79, 15,186,187,187,209,211,211,163,188,126,237,181,215,116, 27,132, 9, 86,126,247,209,201,135, 30,122, 8,153,153,
+153,202,103, 99,198,140,193,152, 49, 99, 48,121,242,100,236,217,179,199,229,251,122,200, 47,251,199,178,187,229,111,165,110,153,
+ 72,221,221,221,200,202,202, 66,125,125, 61, 0, 96,249,242,229,232,237,237, 69,114,114,114,196,199, 0,124,181,255,182,109,219,
+188, 38, 22,220,173,251,186,117,235, 34,186,119,179,135, 2,200,141,170, 30,110,247, 39,200,203, 47,191,236, 65,240,158,158, 30,
+244,245,245, 65, 20, 69, 36, 36, 36, 96,202,148, 41,152, 57,115, 38,178,179,179,241,194, 11, 47,232,122, 19,130,149, 31, 0,218,
+218,218,144,150,150,134,130,130, 2, 23,242, 83, 20,165,184, 33,153,153,153, 40, 40, 40, 0,112,189,234, 48, 38, 38, 70, 23,249,
+229,223,241, 70,126, 81, 20,241,248,227,143,227,242,229,203,120,241,197, 23,145,151,151, 7,154,166,209,211,211,131,185,115,231,
+226,210,165, 75, 74,111,208,221,221,141,148,148, 20, 80, 20,133, 83,167, 78, 97,221,186,117,152, 48, 97, 2,222,125,247, 93,151,
+ 49, 16,173, 51, 65,190,218,255,241,199, 31,215,101,224, 49,220,246,247,187, 71, 88, 32,130,236,221,187, 23, 52, 77, 99,252,248,
+241,152, 50,101, 10,230,205,155,135, 41, 83,166, 32, 59, 59, 27,217,217,217, 74,102, 69, 62,199,151, 2,104,185,104, 85,176,169,
+191,180,180,235, 21,180,185,185,185, 30,131, 75,106,200,199, 99, 98, 98,188, 22,112,105, 37,187,175,209,221, 39,158,120, 2, 51,
+103,206,196,139, 47,190,136, 13, 27, 54, 32, 61, 61, 29,171, 87,175,198, 31,255,248, 71,204,153, 51, 7,253,253,253,160,105, 26,
+185,185,185,216,181,107, 23, 86,175, 94,141,125,251,246, 65, 16, 4,236,217,179, 7, 31,127,252, 49,214,174, 93,139,247,223,127,
+ 95,215, 82, 14,138,162, 80, 83, 83, 3,150,101, 49,109,218, 52, 77,139,221,180, 54,158, 67,238, 20, 31, 72,212,125,233,210, 37,
+ 24,141,198,128, 9,167,247,114,133,193,202, 47, 35, 37, 37, 69,121,237, 30, 64,187, 31,119,143, 41,180,132,175,118,148, 45,191,
+ 40,138,216,177, 99, 7,254,246,183,191, 97,211,166, 77, 88,179,102, 13, 86,172, 88,129,227,199,143,131,166,105,220,117,215, 93,
+ 72, 72, 72,192, 7, 31,124,128,181,107,215, 34, 53, 53, 21, 3, 3, 3,184,243,206, 59,113,224,192, 1,221, 75, 57,104,154, 6,
+207,243,184,229,150, 91,192,178, 44, 4, 65,208, 44, 77,174,181,241,244,187, 83,124,160, 89, 27, 95,228,247,213,192,122,146, 63,
+ 20,249, 59, 58, 58,148,128,119,204, 24,223,251, 26,119,116,116, 0,184,190,252, 34,199,113,186,173, 53,234, 75,129, 95,122,233,
+ 37,172, 95,191, 30,239,191,255, 62,190,249,230, 27,228,231,231,227,147, 79, 62,193,229,203,151, 81, 89, 89,137,193,193, 65, 24,
+141, 70,212,214,214, 98,234,212,169,152, 61,123, 54,218,218,218, 80, 87, 87,135,156,156, 28, 60,247,220,115, 74, 2, 66,175, 44,
+156,252, 59,185,185,185, 46,228,127,227,141, 55, 92,140, 74,176,163,190,190,142, 61,255,252,243,225,197, 92,129, 16,104,168,192,
+ 35,216, 52,167,158,245,243,161,200, 47, 91,246,218,218, 90, 69, 1,212,191, 33,199, 1,181,181,215,119,196,145,215,208,212,131,
+252,254,218, 53, 55, 55, 23,227,198,141,195, 23, 95,124,129, 25, 51,102,160,166,166, 6,181,181,181,168,175,175,199,161, 67,135,
+148,193,167,153, 51,103, 98,245,234,213,200,201,201,193,192,192, 0, 82, 82, 82,112,233,210, 37,196,199,199, 99,250,244,233,186,
+142, 3,168,127, 71,109,249,221, 99,128,112, 75,102,180,226, 15, 27,172, 31,234,205,122, 7, 27,169,235,189,208,110,176,242,203,
+ 40, 45, 45,197,228,201,147,145,153,153,233,177,193,199,197,139, 23, 81, 90, 90, 10,189, 49,148,171,120,255,253,247,163,184,184,
+ 24,251,247,239, 71,109,109, 45,246,239,223,143, 35, 71,142,224,217,103,159,197,220,185,215, 55, 37,175,168,168,192, 83, 79, 61,
+133, 95,255,250,215, 88,185,114, 37, 56,142,195,198,141, 27,241,232,163,143, 70,164, 28,218, 91,251,191,254,250,235, 30, 61, 64,
+ 56,150, 95,126,189,105,211, 38,253, 20, 32, 16,237, 12,212,213,240, 53,103, 85, 79, 5, 8, 84,126,249,198,136,162,136, 61,123,
+246,248, 29, 7,240, 21, 31,232,165,192,114, 15,212,219,219,139,174,174, 46,236,219,183, 15,107,214,172,193,149, 43, 87, 80, 95,
+ 95,143, 35, 71,142,224,171,175,190, 66, 98, 98,162,242,253,204,204, 76, 44, 91,182, 12,133,133,133, 40, 42, 42, 66, 90, 90, 26,
+150, 46, 93,138, 15, 62,248, 0,107,214,172, 65,106,106, 42,146,146,146,116,155,203,224,173,253,159,120,226, 9,205,252,125, 45,
+101,101,195,201,160, 4, 59, 33, 35, 18,107,243,135, 42,191, 60, 16, 22,204, 13,142,148, 2, 20, 20, 20, 32, 43, 43, 11,115,230,
+204, 65, 97, 97, 33, 86,172, 88,129,202,202, 74, 28, 62,124, 24,207, 62,251,172, 11,249,229,135,217,108,198,166, 77,155,176,111,
+223, 62,108,220,184, 17, 75,150, 44, 65,107,107, 43, 94,127,253,117, 28, 63,126, 28,237,237,237,184,112,225,130,110, 46,144,251,
+227,181,215, 94,115,153,253, 21,142,229, 87,255,151, 46, 61, 64,176, 89,148,104,104,174, 30, 89,160,225, 0,111,174, 98,107,107,
+ 43,234,235,235,209,220,220,140,254,254,126,156, 56,113, 2, 14,135, 3, 13, 13, 13,152, 59,119,174,207, 54, 47, 40, 40,192,219,
+111,191,141,146,146, 18,180,180,180,224,238,187,239, 6,207,243,136,139,139,195,232,209,163,117,115,129,188,181,255,147, 79, 62,
+ 57,172, 44,191,166, 89,160,225, 68,254, 80,228,183, 88, 44,136,141,141, 13,184, 20, 66, 20, 69, 93,123, 51, 95,164, 84,143,254,
+202,243, 1,134,234,245,212, 37,198,238, 50,235, 57, 6,227, 46,215,214,173, 91,189,246,112,161, 88,126,221,123,128, 96, 6, 46,
+134,186, 1,209,218, 89, 38, 24,249, 99, 99, 99,131, 42,133,208,155,252,238,237,154,158,158,142,101,203,150, 97,238,220,185,200,
+205,205,197, 93,119,221,133,179,103,207, 98,246,236,217,168,168,168, 64,102,102,166,215,107, 59,122,244, 40, 86,174, 92, 9,171,
+213,138,184,184, 56,236,222,189, 27, 13, 13, 13,168,169,169, 65, 70, 70,134,174,110,169,187, 44,235,214,173,139,234, 76,181,144,
+ 71,130,135, 10, 36,253,165, 65,171,171,171,241,209, 71, 31,225,242,229,203,184,120,241, 34,146,147,147,135, 21,249,221, 27, 86,
+ 93, 10,161, 14,144,221, 75, 33, 34, 33,191,250, 58, 42, 43, 43,209,219,219,139,238,238,110,252,225, 15,127, 0,199,113,152, 55,
+111, 30, 30,122,232, 33,252,242,151,191,196,178,101,203,148,210,105,249,218,250,250,250, 80, 92, 92,140,242,242,114,216,108, 54,
+ 28, 56,112, 0,221,221,221,216,180,105, 19, 82, 82, 82,144,156,156,172, 43,249, 43, 42, 42,192, 48, 12,230,204,153, 3, 0,216,
+188,121,179,207, 94, 34, 88,203,175,107, 15, 16,108,142,214,155, 2,136,162,136,157, 59,119,162,167,167, 7,113,113,113,176, 90,
+173,104,106,106, 82,234,237,135, 11,249,101,249,229,218, 30,117, 41,132, 76,124,245, 56,128,124, 92, 79, 23,200,151,251,150,156,
+156,140,212,212, 84, 60,240,192, 3, 88,191,126, 61, 86,174, 92,137,236,236,108,172, 91,183, 14,133,133,133,216,180,105, 19, 10,
+ 10, 10, 64, 81, 20,142, 30, 61,138,226,226, 98,188,247,222,123,136,143,143,135,197, 98,193,238,221,187,177,123,247,110,100,103,
+103, 71,196,242,115, 28,135,156,156, 28,165,174, 73, 61,121, 61,152,146,109,189,225, 51, 8,246, 38, 88, 77, 77, 13, 14, 30, 60,
+136, 43, 87,174,224,226,197,139, 72, 74, 74,242,122,179, 94,121,229, 21, 52, 54, 54, 98,194,132, 9,232,233,233, 65, 71, 71, 7,
+172, 86, 43, 4, 65, 64,122,186,254,187, 31, 5,187,140,134, 92,219,227,173,212, 65, 61, 30, 32, 31,215, 59,155,229, 79,238, 61,
+123,246,224,209, 71, 31, 69,103,103, 39, 58, 59, 59,177,114,229, 74,204,159, 63, 31,251,246,237,195,246,237,219,193, 48, 12, 86,
+174, 92,137,242,242,114,196,199,199, 43, 3, 96,171, 87,175,198,142, 29, 59,240,230,155,111,234, 46, 63, 77,211,152, 53,107,150,
+ 75, 81, 95, 73, 73,201,144, 22, 63, 80,203, 31,177, 30, 64, 93,219,255,225,135, 31,194, 98,177, 32, 33, 33, 1,141,141,141,104,
+110,110, 70, 69, 69,133, 11, 33,228,155,244,167, 63,253, 9, 6,131, 1,231,206,157,131,197, 98, 65, 91, 91, 27,186,187,187, 33,
+ 8, 2, 30,124,240,193,168,165, 65,135,202, 2,169, 75, 33,220,201, 47, 31,143,180, 11,167,150,251,228,201,147,104,110,110,198,
+146, 37, 75,112,250,244,105,140, 31, 63, 30, 38,147, 9, 70,163, 17,207, 60,243, 12, 94,121,229, 21, 80, 20, 5,139,197, 2,187,
+221, 14,171,213,170,244, 0,247,222,123, 47, 86,173, 90,133, 19, 39, 78, 96,198,140, 25, 17, 73, 66,168,211,158,235,215,175, 31,
+ 50, 22,139,164,229, 15, 56, 6,160, 40, 10,191,251,221,239,208,210,210,226,215,162,171,133, 55,153, 76, 74, 53,160, 32, 8,112,
+ 56, 28,144, 36, 9,207, 61,247, 28, 54,110,220, 24,149,177, 0,127, 89, 32,185,182, 71, 93, 10,225, 45, 14,144, 75, 33,244,118,
+129,124,201,253,244,211, 79,227,253,247,223, 71,111,111, 47, 38, 79,158,140,207, 62,251, 12,239,188,243, 14,126,246,179,159, 97,
+249,242,229,104,105,105, 81, 50, 68, 7, 14, 28, 80, 42, 66,239,189,247, 94,176, 44,139,226,226, 98, 60,246,216, 99,248,250,235,
+175, 35,222,254, 37, 37, 37, 62,107,129,130,181,252,186,103,129,220,133,255,232,163,143,192,113,156, 87,139,254,192, 3, 15,120,
+104,238,222,189,123,241,212, 83, 79,161,169,169, 9,241,241,241, 72, 78, 78,198,134, 13, 27, 48,107,214,172,168, 90, 80, 95,150,
+ 71,174,237, 9,180, 20, 34, 82, 46,144,187,220,227,199,143,199, 39,159,124,130, 21, 43, 86,224,225,135, 31,198,164, 73,147,176,
+109,219, 54,236,217,179, 7, 29, 29, 29,184,239,190,251, 64, 81, 20,118,237,218,133,238,238,110,236,222,189, 27, 59,118,236,192,
+170, 85,171, 80, 92, 92,140, 67,135, 14,185,100,184, 34,217,254, 27, 54,108, 24, 86,150, 63,168, 32, 56, 62, 62, 30,167, 78,157,
+242,176,232, 27, 55,110,116,153,147, 41, 99,210,164, 73,248,248,227,143,163, 58,144, 20,108, 29,144,108,217, 3, 41,133,136,196,
+ 53,120,147,253,221,119,223,197, 35,143, 60,130,131, 7, 15, 98,235,214,173,184,237,182,219, 64, 81, 20,214,172, 89,131,173, 91,
+183, 42,138,220,208,208,128, 77,155, 54, 33, 59, 59, 27,219,182,109, 67,117,117, 53, 30,123,236, 49,100,102,102, 98,247,238,221,
+ 81,105,255,223,254,246,183, 67, 86,131,134,242, 95,186,245, 0,106,225,119,238,220,137,103,158,121, 70, 9,168,212, 22,125, 56,
+142,168, 6,187, 12,139,236,210, 4, 90, 10,161,183, 11,228, 75,118,131,193,128, 29, 59,118,120, 28, 79, 77, 77, 69,117,117,181,
+ 50,158,241,221,119,223, 33, 37, 37, 69,249,222,140, 25, 51,116,119,123,134,186,134,103,158,121,102, 88,142,200, 7,148, 5,154,
+ 52,105, 18,254,252,231, 63,143,152,114,130, 96,179, 64,193,146, 57, 26, 89, 32,127,228, 73, 74, 74, 66, 71, 71, 7, 70,141, 26,
+ 5, 0,200,200,200, 80,166, 67, 14,151,246,255,205,111,126,227,115, 12, 32,146, 22, 63,164, 44,208, 72,172,165, 9, 69,254, 64,
+ 75, 33,134,147,252,242,231,234,194,182,104,141,190,251,147,255,217,103,159, 29,150,252, 9, 40, 8,214,107,246, 80,180,131, 96,
+119,151, 38,208, 82,136, 72,215, 2, 5, 90, 54, 16,109,242,143, 68,254,208, 55, 59,249,213, 46,141,123, 41,132,250,123,234, 82,
+136, 72,186, 64,234,133,163, 8,249, 93,241,194, 11, 47,192,233,116,234,215, 3,140, 52,242,135, 43,127,160,165, 16,195, 33,139,
+ 53, 28,201, 31,105,254,132, 59, 31,216,107, 15, 48, 84, 38, 98, 36, 32, 88,249,229,244,102,160,165, 16,122,167, 67, 71, 50,249,
+ 71, 26,127, 60,122, 0,135,195,129,115,231,206,249, 92,193, 75, 79,168, 55,125, 8, 21,161,200, 47,187, 52,238,171, 66,200,121,
+107, 89, 9,228, 82, 8,249,251,103,206,156,209, 92,254,129,129, 1,156, 63,127, 62,160,149, 52,180, 38, 86,180,218, 63,154,252,
+113,145,170,160,160,160,213,102,179,165, 69, 83, 35,121,158,111, 43, 45, 45, 13,169, 98,110,238,220,185,130,221,110,167,163, 44,
+191, 88, 90, 90,202,132, 40,127,171,221,110, 31,177,237, 63,210,249, 67, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64,240,223, 21, 20,105, 2,130, 72,225,198, 62,194,135, 1,228,233,245, 31, 28,199,181,149,149,149, 5,156, 6,101,201,109,
+ 33,136, 32,249,191,188,177,143, 48,170,170,170,144,145,145,161,108, 88,238, 62, 73,201,125, 65, 48,247,215,222,150, 73,180, 88,
+ 44, 88,186,116,105, 80,227, 16, 68, 1, 8, 34, 70,254, 45, 91,182,240, 69, 69, 69, 19, 1,160,170,170, 10,131,131,131, 72, 72,
+ 72, 80, 54,201, 14,164,240,207,223,241, 11, 23, 46, 4, 45,155,203,168,169,209,104, 44,166,105,218, 1, 64, 10,228, 65, 81,148,
+ 13,192, 6,114,139, 9,134, 34,255,230,205,155,249,133, 11, 23, 78, 84,136, 71,211, 46, 53, 85,129,204,226,211,125,167,120,187,
+221,190,177,166,166,134,157, 56, 81,145,211, 99,114,184, 26,205,205,205,214,156,156,156,231, 1,188, 66,110, 53,129, 47,242,151,
+148,148, 24, 23, 45, 90,148,165, 62,166,222,161, 83,171,237,147, 66,129,139, 2,136,162,200,102,101,101,161,183,183,215,163,226,
+209,155, 34,164,165,165, 93, 3, 48,153,220,106, 2,127,228, 95,188,120,113,150,251,113,245,222,192, 90,238, 29, 22,150, 2,168,
+ 20,193,239, 68, 3, 89, 25, 4, 65, 16,201,173, 38, 8,150,252, 0,148, 29,238,229, 30, 64,171,141,243,194,138, 1,124, 89,123,
+121,211,102,249,161,238, 49, 0, 12, 2,200, 32,183,157,192,221,231,247, 69,126, 0,224,121,222,227,179, 96,253,125, 93,118,138,
+111,110,110,198,145, 35, 71, 48, 48, 48,160,144, 93, 77,122,245,103, 44,203,166,254,226, 23,191,232,123,231,157,119, 46,250,136,
+ 21, 40, 47, 10, 69,121, 81, 56,151,207,104,154,118,114, 28,247,242,224,224, 96, 49,161,212,200,204,246,168, 3, 94, 0,176,217,
+108,104,108,108, 68, 83, 83, 19, 58, 59, 59, 93,210,159,195,106,163,108,134, 97, 16, 19, 19,227, 98,237,125, 41, 0,128,132,123,
+238,185, 7,143, 60,242,136, 18, 51,200, 19, 72,124,229,113,213, 83, 13,221,143,201,104,106,106, 98,151, 47, 95,190, 17, 0, 81,
+128, 17, 4, 81, 20, 15,223,200,243, 79, 20, 69, 17, 45, 45, 45,168,171,171,195,233,211,167,209,222,222,142,132,132, 4, 36, 39,
+ 39,195,108, 54,195,100, 50,121, 40, 64,184,177, 64,216, 65, 48, 0, 56,157, 78,244,247,247,163,191,191,223, 27,225, 61,148,161,
+172,172, 76,209,102,111,110,148,183,158,193,215,111,202,207, 61, 61, 61,178,123, 69, 48,178,144,151,155,155,139,237,219,183,163,
+161,161, 1, 12,195, 32, 45, 45, 13, 41, 41, 41, 24, 59,118, 44, 56,142, 3,203,178,224, 56, 14, 70,163, 17, 44,203, 42,177,128,
+ 86,129,176, 38, 61, 64,108,108,172,203,142,136, 67,244, 2,144, 36,201,231,247,135, 58,207,219,177, 72, 45, 65, 72,160, 61,250,
+250,250, 16, 31, 31,143,162,162, 34, 36, 38, 38,202, 46,173,242, 44,175,112,199,113, 28,120,158, 7,195, 48, 16,122,175,161,225,
+173,255,141,254,150,179,136, 73, 29,131, 49,119, 60,140,177,119,252,159,232,100,129,156, 78, 39,250,250,250,208,215,215, 23,176,
+ 5,215,138,248,242,179,197, 98, 33, 76, 26,161,136,139,139, 67,126,126, 62, 4, 65,240,234,234,210, 52, 13,134, 97, 96, 48, 24,
+148,231,150,175,246, 34, 65,186,134,249,247, 44,133,197, 98,199,241, 67,111, 97,160,177, 26,217,255,252, 6, 40, 47,113,130,150,
+ 89, 32, 15, 5,144,151,215, 22, 69, 81, 83, 82, 7,115, 44,220,181, 94, 8,162, 7,217,197,241,182, 16,174,154,180, 12,195, 40,
+229, 15,163,231,174,194,201,191,238, 68,231,229, 22,140,190,117, 38, 10, 87,164,225,196,223,171,112,226,133,229,152,246,244,191,
+129, 55,167, 6,181, 15,181,102, 49, 64, 36, 20,192, 91,207, 66,122,128,145,173, 0, 44,203, 42,247,211,215,174,149,234,116,103,
+220,184, 91, 48,245,233,127,199,177, 45,247, 35,207, 1,140,187,125, 62,110,191, 99, 9,206,125, 91,137,111,215,207,199,109, 27,
+247, 35,126,194,173,250,151, 66,200, 49,128,209,104,132, 32, 8, 97, 19, 62,212,243,237,118, 59, 97,210, 8,133,175,101, 91, 36,
+135, 13,151,246,174, 71,111,221,223, 33,216,108,144, 36, 17,144, 36, 72,162,120,253, 53, 0,138,166,241,221,183,103, 64,153, 51,
+ 48,238,214,169,152, 52,243, 7, 72, 72, 78,194,177,231,151, 97,234,163,239, 97,244,172,229, 67,238, 86,170, 73, 15, 48, 48, 48,
+224, 17, 3,132, 74,106,111,239,135, 58,207,106,181, 18, 38,141, 96, 5,240,182,150, 81,235, 95,222, 69,220, 96, 51,110,255,209,
+ 63,128,229, 56, 80, 52, 11,138, 97,111, 60, 51, 0,197, 0, 20,125,253,193,242,144,156, 54,192, 97,193,168,239,229,160, 48,105,
+ 20,202,255,245, 23, 24,184,180, 22,147,254,105,157,223, 77, 54, 52,235, 1,100, 63, 92, 38,103, 93, 93, 29,170,171,171, 49, 56,
+ 56, 8,187,221, 14,135,195, 1,187,221,238,242,218,225,112,104,150,193,161,105, 90, 20, 69, 81,242,209,200, 86, 73,146, 54, 2,
+120,157, 80,110,120, 42,129, 90, 1,104,154,134,104,183, 34, 54, 54, 6, 28,108,160, 4, 1,144, 88, 64, 50, 0, 52, 11, 9, 70,
+ 64, 24, 0,104,246,186, 34, 56, 44,128, 36, 1, 6, 35,224,180, 33, 46,209,140,249,247,172, 66,213,103, 31,160,191,177, 6,183,
+ 61,245, 1, 40,138,214, 47, 11,228,173, 7, 56,121,242, 36,246,238,221,139,212,212,212, 72,181,163,207, 97,189,150,150,150,152,
+217,179,103,191,234,116, 58,137, 2, 12, 99, 5, 80, 19, 52,109,209, 67,104,220,245,107,156, 62,118,200,165, 22,128,102, 12,184,
+117,217, 61,152, 48,214, 4, 26, 34, 40,134,189,113,235, 69, 72,130, 19, 0, 5, 8,118, 24, 40, 96,206,157,255,136,227,127,253,
+ 18,117,239, 61,137,105,107,223,208,100,217, 69,175, 89, 32,163,209, 8,135,195,225,226,150,112, 28,135,212,212, 84, 52, 53, 53,
+185, 28, 11, 7,254, 74,173,253,161,175,175, 15, 78,167,211, 64,168, 54,124, 93, 32,247, 71, 76, 90, 22,114, 55,236, 87,122, 4,
+123, 71, 11,106,183,254, 79,228,204,153,143,140,172, 81,144,108,189,160, 24, 14, 84,242, 36,208, 19,139, 64, 37,100, 0, 20, 13,
+169,251, 34,196,179,159, 67,188, 82, 13, 88, 59, 49,125,225, 2,124,179,255, 0, 46, 29,154,129,204,101, 63, 11,123,217, 69, 15,
+ 5, 16, 4,193,101, 36,216,221, 87,183,219,237,176,217,108, 81,109,100,185,119, 34, 24,158,240, 87,229, 73,211, 52,250,206,126,
+139,134,119, 30,198,237, 63,188, 11, 73,102, 14,210,192, 53,128, 53,130,154,184, 0, 76,246, 10, 80,234,169,145,105,121,160, 71,
+ 79,133,112,250, 63,225, 60,177, 15,204, 96, 59,102, 47, 91,130, 35,127,120, 6, 19,254,199,131,160, 13,124,120, 89, 43,111,194,
+199,196,196,192,233,116,186, 88,104,185,122,207,189, 34, 52, 26,136,246,255, 19, 4, 31, 4,203,228,191,250,247,127,195,229,131,
+175, 99,238,170, 31, 35,150,177, 0,150, 94,128,225,129,132,113,160, 38,255, 3, 4, 81,196,153,166, 78,212, 54,118,194, 50,232,
+196,196,177, 9,152,153, 61, 26,252,148,101,144,202,182, 65,104,248, 11,184, 81, 57, 24, 53,126, 2,174, 30,251, 28, 99,126,240,
+ 67,109, 21, 64, 16, 4, 12, 12, 12,184,140, 3,184,247, 2,132,128, 4,193, 4,193, 20, 69,129,166, 40, 52,126, 88,140,193,179,
+101,152,183,234, 71,224,108, 87, 33, 57,132,235,214,158, 18, 32,101, 21, 65, 16, 37,156,187,220,141,191, 84, 52,193, 41,136, 56,
+118,230, 42,206,182,116,227,159,255,113, 42, 30,186,227, 22, 72,115, 31, 7, 26,254, 2,169,255, 42,198,140,189, 13,151, 14,239,
+210, 94, 1,228, 24, 64,206,197,203,100,231,121,222,235,156, 0,210, 3, 16,248,235, 1,228, 12, 80,237,155, 63,131,137, 19, 48,
+251,142,133, 96,196, 1, 88,185,116, 56, 41, 30,241,150, 6, 80,160, 32,198,141,129,228,116,162,236, 84, 43, 46,119, 12,160,170,
+190, 21,253,214,235,177,230,159,191,108,192,143, 11,179,192,143,206, 7, 77,209,144,172, 93, 48,103, 36,160,174,186, 50,108,121,
+253,246, 0,106,178,169,139,221,136, 2, 16, 4,154, 5,114,116,181,226, 84,201, 63, 33, 51, 39, 27,147,110,153, 0, 56, 7,208,
+221,231, 64,233,199,251, 48,239,254,135, 0,138,129, 36,216, 33, 56,157,144, 4, 1, 45,215,250,240, 85,245, 37,168,111,177,145,
+ 99, 0, 73,132,195,233, 0,127,253, 15,192, 24, 56, 56,172,253,218, 43, 0, 77,211,224,121, 30, 70,163,209,174,244, 93,155, 0,
+ 0, 4,137, 73, 68, 65, 84,133,112,242,123,162, 0, 4,129,246, 2,131, 87, 47,226,228,203,119, 34,191,168, 16,233,163,227, 1,
+209,137,182,214, 30,156,248,219, 87,136, 31,151, 3,199, 64, 15, 40, 51, 3,105,112, 0, 98,199, 89, 88, 17,139, 41, 99, 99,225,
+126,123, 23, 79, 31, 3, 65,112, 2, 45,223, 2,146, 8, 24, 98, 97,119, 72,136, 73, 14,127, 43, 2,143, 92,187, 60, 14, 32,247,
+ 2,253,253,253,202,236,176,225,244, 32, 24,222,228,167, 40, 10, 13,255,250, 47,200,159, 63, 15,105,137, 20, 36,198,128,198,243,
+173, 56, 89, 86,137, 89,175,124,137,180,194,123,208,121,249, 50,192, 39, 92, 31,248,250,250, 21,216,172, 22,204,201, 78,194,125,
+ 69,153, 24,101, 54,194, 28,103,192,178,239,143,197,157,115,198,194,225,112,128,173,120,227, 58,105, 19, 51,209,221,213,135,164,
+ 91,230,106,223, 3,200, 35,193,118,187,221, 37,240,245, 54,135, 51, 90, 86,153, 40,192,200, 80, 2,103,239, 53, 36,143,155, 7,
+ 73,178,227,244,137,211,104,191,218,141,217,175, 30,129, 33, 62, 17,227, 22,175, 70,217,255,123, 27, 89,121,121,160, 91,190, 5,
+107,237,130,177,244, 37,244,205,122, 26,119, 23,140,197,221, 5, 99,255, 43,150,128, 8, 67,197, 27, 48, 52,253, 13,160, 89,136,
+ 99,102,226,204,127,124,133,121,175,188,169,189, 2, 56,157, 78, 88, 44, 22, 12, 12, 12,184,144, 77,174,239, 38, 22,152, 32,208,
+ 30, 32,225,150, 2,148,127,250, 57, 28,150,126,152, 38,127, 31,183,255,223, 63,129, 49,240,215, 39,197,196,153, 49,126,249, 26,
+156, 59,245, 53,110,201,248, 62,132,115,159, 35,254,228, 78,112,173, 85,232,207, 95, 3,123,106, 62, 68,138, 1,215, 81,131,248,
+ 83,127, 0,127,165,236,186,245, 31, 55, 27,205, 45, 93, 24,117,219, 18,196,103, 76,209, 39, 6,144,103,235,168, 21,128,196, 0,
+ 4,193, 42,193, 45, 15,191, 5, 75,115, 61, 56, 83, 50,140, 41, 99, 61,198, 5, 38,174,252, 23,124,245,200,187, 48, 39, 23, 96,
+ 76,222, 61, 16, 78,255, 39,184,246,239,144,252,197, 47, 60,127,148,225,192, 76, 94,138, 46,167, 25,167, 43,190,192,226,237,199,
+ 53,145,213,107, 22,200,106,181,122,237, 1,252,213,242, 19, 5, 32,112, 87, 0,154,166, 97,202,156,234,187,126,159,143, 65,225,
+230,175, 81,245,210, 42,116,143, 78, 70,206,109, 15,129,106, 61, 6,169,175, 21, 82,223, 21, 64, 20, 64,197,167,129, 50,141, 1,
+149,158,143,198,243, 87,208,120,178, 12,133,175,254, 21,198,228,116,125, 20,192,189, 7,144, 9, 23, 19, 19, 67,122, 0,130,160,
+200, 31,200, 92,222,152,212, 12,204,127,173, 12,167,222,123, 2,127, 63,240, 23,140,157, 50, 5, 73,163, 38,195,148,147, 14,138,
+166,209,223,126, 13, 61,215,218,113,249,175, 21, 48,142,202,194,226,119,190, 3, 27, 19,175,153,188, 94,123, 0,139,197, 2,139,
+197,226, 98,241, 29, 14,135, 50, 97, 93,239, 73,235, 67, 17,156, 76,154, 31,222, 8,122,133, 7,214,128,252, 71,182,161,239, 82,
+ 61, 58, 78,254, 29,205,213,135,209,241,197, 62, 72,130, 19, 73,217,223, 71,202,140, 59, 48,253,174, 66, 36, 77,153,169,185,172,
+ 62,199, 1,228,145, 95,181, 98, 72,146, 4,167,211,169,217,156,221, 80, 45, 57,153, 51, 60, 50,130,224, 96, 22,181,162, 40, 10,
+230,204, 92,152, 51,115,241,189, 31,174,137,152,188, 94,123, 0,155,205,230,210, 3,200,100, 21, 69, 17, 14,135, 67,119, 2, 14,
+165, 24, 54,155, 13, 20, 69,137,196, 21, 26, 25, 74, 16, 8,249, 35,177,147,252,144, 10,192,178,108,255,213,171, 87,227, 71,143,
+ 30,237, 82, 10, 33,138, 34,210,210,210,148, 50,137,104, 90,127, 73,146,112,229,202, 21,240, 60,127,105,112,112,144,176,109,152,
+ 43,192,112, 38,191,135, 2, 24,141,198,147,135, 15, 31,158,179,116,233, 82,212,213,213, 65, 16, 4,101,121,148,217,179,103,163,
+171,171, 43,104,235,175,181,149,150, 36, 9, 53, 53, 53,131,162, 40,150, 17,170, 17,242,107,170, 0, 14,135, 99,211,206,157, 59,
+255, 99,213,170, 85,134,159,252,228, 39, 56,115,230, 12, 40,138, 66, 78, 78, 14,210,211,211,113,252,248,241,168,251,255,151, 47,
+ 95,198,167,159,126,234,176,219,237,207, 19,186,141,188, 32, 56,156,133,108,117, 87, 0,155,205,118,152,231,249,119, 86,174, 92,
+185,118,237,218,181,134, 69,139, 22, 33, 61, 61, 29, 61, 61, 61, 40, 47, 47, 15,105,185, 18, 45,122, 0, 65, 16,208,214,214,134,
+154,154, 26,235,193,131, 7, 5, 81, 20,127, 13,224, 12,161,218,200, 9,130,135, 35,249,125,107, 5,203, 46,141,141,141, 61,202,
+178,108, 63, 2,220, 47, 76,207, 7, 69, 81, 2,207,243,141, 6,131,225, 67, 0,217,132,102,195, 19, 51,103,206,148,156, 78,167,
+100,177, 88, 36,171,213, 42, 13, 14, 14, 74, 54,155, 77,178,219,237,146,195,225,144,156, 78,167, 36,138,162,110,143,250,250,122,
+105,230,204,153, 65, 89, 92,175, 43, 48, 59,157,206,207,157, 78,231,231,195,165, 97, 37, 73,138,250, 60,100,130,192, 96,183,219,
+113,246,236, 89,175,126,190,222,150,223, 96, 8,126,157, 4,178, 4, 57,129,102,224,121,190,109,254,252,249,105,209,150,129,220,
+ 9, 2, 2, 2, 2, 2, 2, 2, 2,191,248,255, 88,111,246,205,191, 63,162, 3, 0, 0, 0, 0, 73, 69, 78, 68,174, 66, 96,130,
+ 0};
+
diff --git a/source/blender/editors/datafiles/splash.jpg.c b/source/blender/editors/datafiles/splash.jpg.c
new file mode 100644
index 00000000000..c1ca8b575e6
--- /dev/null
+++ b/source/blender/editors/datafiles/splash.jpg.c
@@ -0,0 +1,2483 @@
+/* DataToC output of file <splash_jpg> */
+
+int datatoc_splash_jpg_size= 79258;
+char datatoc_splash_jpg[]= {
+255,216,255,224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 1, 0, 72, 0, 72, 0, 0,255,225, 0, 22, 69,120,
+105,102, 0, 0, 77, 77, 0, 42, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0,255,219, 0, 67, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2,
+ 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,255,219, 0, 67, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,255,192, 0, 17,
+ 8, 1, 15, 1,245, 3, 1, 34, 0, 2, 17, 1, 3, 17, 1,255,196, 0, 31, 0, 0, 1, 3, 5, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0, 7, 10, 3, 5, 6, 8, 9, 2, 1, 11,255,196, 0,103, 16, 0, 1, 3, 3, 2, 4, 3, 4, 6, 4, 7,
+ 11, 5, 9, 13, 9, 1, 2, 3, 4, 5, 6, 17, 0, 7, 8, 18, 33, 49, 19, 65, 81, 9, 20, 34, 97, 10, 21,113,129,145,240, 35,
+ 50,161,193, 22, 23, 24, 66,177,209,225, 25, 26, 36, 40, 51, 56, 73, 82, 98,232,241, 72,104,105,136,168, 41, 52, 57, 67, 84, 88,
+120,150,178, 37, 38, 68, 83, 87,115,130,135,147,152,181,200,210, 54, 89, 99,114,146,184,213,214,215,255,196, 0, 29, 1, 0, 0,
+ 6, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 5, 6, 7, 1, 4, 8, 9,255,196, 0, 80, 17, 0, 2, 1,
+ 2, 4, 4, 3, 4, 6, 7, 5, 7, 0, 7, 9, 0, 1, 2, 3, 4, 17, 0, 5, 18, 33, 6, 19, 49, 65, 7, 34, 81, 20, 97,113,
+240, 8, 35, 50,129,161,209, 21, 66, 82,145,177,193,210, 36, 51, 98,162,225, 9, 67, 83, 84,114,130,241, 52, 56, 68, 85,116,148,
+211, 22, 23, 24,115,131,146,147,180,181,255,218, 0, 12, 3, 1, 0, 2, 17, 3, 17, 0, 63, 0,159,198,150,150,150,134, 6, 22,
+150,150,190,100,122,143,199, 67, 3, 31,116,203,220, 60, 68,108,181,171,123, 70,219,170,254,224,209, 41,183,140,167, 25,101, 20,
+135,189,241, 73,101,249, 28,165,136,243,170, 77, 69, 84, 74,116,149,133,163,149,185, 15,180,226,185,211,132,158, 97,151,159, 35,
+212,126, 35, 92,108,227, 63,131, 43,145, 85,251,143,120, 54,213, 18,235,236, 86, 37,191, 87,185,237,148,243, 72,170, 67,146,224,
+ 11,147, 81,162,128, 57,167, 69, 42, 5, 75,143,213,230,242, 75, 94, 34, 50,148, 86,158, 42,113, 39, 27,112,159, 14, 38,119,193,
+ 60, 55, 23, 19,212, 81,204,173, 89, 4,134, 67, 34,209,128,198, 87,130, 56,138,188,146, 2, 0,242,151, 49,169, 50,114,101, 1,
+128,179,188, 40,225,158, 7,226,222, 37,108,143,142, 56,150,110, 23,166,172,133,150,142,120,196, 98, 54,173, 44,162, 36,158, 73,
+ 85,146, 56,200, 44,124,193, 4,140, 4,124,232,139, 41, 61,145,109,196, 58,132,173,181, 37,104, 80,200, 82, 72, 32,131,243, 26,
+247,174, 11,240,211,199, 61,219,180,206, 66,179, 55, 36, 79,186,108,118, 29, 68, 54,166, 58, 92,122,228,181,217, 65, 13, 22,219,
+ 47, 30,106,157, 61,174, 95,242, 14, 16,243, 97, 37, 45, 44,128,150,181,219,219, 46,247,181,247, 6,129, 2,231,180, 43, 48,171,
+148,106,139, 65,216,211, 33, 58, 29, 65,232, 57,219,113, 63,172,203,233, 86, 66,219, 88, 74,208,160, 66,146, 14,147,240,211,197,
+174, 19,241, 67, 46, 53, 25, 37, 79,179,102,180,202, 13, 86, 95, 49, 2,166,156,244, 38,219, 9, 97,213,178,207, 29,212,220, 7,
+ 17,201,120,194,158, 38,248, 69,197,190, 22,102, 66,159, 60,166,246,156,166,165,136,165,204, 33, 4,210,212,142,160, 95,115, 12,
+218,119,104, 36,179, 11, 18,134, 72,237, 33,202,244,180,180,181,103,226,173,194,210,210,210,208,192,194,210,210,210,208,192,194,
+210,210,210,208,192,194,210,210,210,208,192,194,210,210,210,208,192,194,210,210,210,208,192,194,210,210,210,208,192,194,210,210,
+215, 13,125,163,254,220, 13,158,224,130,240,159,178,214, 5,156,238,249,111,173, 45,150, 21,116, 81,219,173,155,110,200,219,199,
+ 39,194, 98,116, 8,215, 53,192,138,116,167,170,213,245, 68,151, 17,255, 0,171, 32,177,132, 50,233, 76,186,132, 39,249, 26, 91,
+214, 67,195,217,207, 19,102, 9,149,228,116, 47, 95, 90,224,177, 85, 42,161, 80, 16, 11,200,238, 85, 35, 64, 72, 5,157,128,185,
+ 10, 46,204, 1, 98,226, 46, 38,200,248, 79, 45,124,219,136, 51, 20,203,104, 81,130, 6, 96,204,206,237,114,169, 28,104, 26, 73,
+ 28,128, 78,148, 86, 58, 85,152,128,170,196,119, 43, 75, 80,124, 63, 73,159,141,131, 84, 83,195,103, 56, 94, 20, 82,242,212,138,
+127,240,103,117, 13, 77, 44, 20,171,195,105, 85,127,227,115,194, 91,193,101, 37, 75, 16,146, 20, 1, 1,180,147,204, 58,247,192,
+ 39,183,219,102,184,168,189,173,253,156,222,171, 32,236, 38,233,221, 18,227,210,109, 58,154,110, 6,238, 13,182,188,107,111,132,
+162, 53, 29,138,204,184,113, 36,218,181,233,114, 84, 26,131, 10, 91, 82, 88,144,233, 68,118,234,107,152,244,120,206,205,115,175,
+ 7,248,243, 35,161,151, 49,169,202, 86,166,150,157, 75,200,105,230,142,102,141, 64,185,102,140, 17, 33, 10, 55, 98,138,225, 64,
+ 44,108,160,156, 64,178, 47, 27,188, 58,226, 12,194, 28,174,151, 57,106, 90,186,150, 9, 16,169,134, 72, 82, 71, 38,202,171, 35,
+ 3, 26,179, 27, 5, 18, 50, 22, 36, 42,130,196, 12, 72, 35, 75, 94, 80,180,173, 41, 90, 8, 82, 84, 1, 73, 29, 65, 7,204, 29,
+122,213, 97,139,107, 11, 75, 75, 94, 29,117,182, 91,113,231,156, 67, 76,180,133, 56,235,174, 41, 40,109,182,208,146,165,184,226,
+212, 64, 66, 2, 65, 36,147,128, 6, 78,134, 6, 61,233,107,140, 28, 63,123, 94,236,238, 39,253,160,119,151, 9,219, 61,108,210,
+ 43,219, 63,103, 88,247, 29, 77,157,231, 77, 86, 91,178,239, 43,178,215,171, 80,169,213, 69,219, 84,214,227,166, 57,178,252,106,
+195,236,197,150, 92,117, 83,126,173,247,214, 23,238,178, 89, 3,231,181,219,218,129,127,123, 56, 15, 15,137,177,182,194,209,220,
+115,188,169,221, 85, 85, 13,213, 86,172,210,254,165,254, 47, 78,219,136, 94,225,245, 74, 79,188,123,199,240,222, 95,139,226,126,
+167,184,183,201,250,202,212,182, 30, 7,226,105,179,220,183,134,191, 71,242,179,156,218, 1, 81, 12, 50, 72,136,121, 70, 41, 38,
+ 5,203, 48, 17,183, 46, 39, 37, 28,171,130, 52,149, 12,109,136, 92,222, 32,240,164, 60, 61,154,241, 87,233, 46,118, 69,147, 78,
+105,167,158, 56,228,145,121,162,104,160, 34, 48,170, 90, 84,230,202,138, 36,140, 50, 48, 58,149,138,139,227,180, 26, 90,134, 23,
+247,207,155,251,255, 0,155, 30,209,127,235, 93,227,255, 0,232,210,254,249,243,127,127,243, 99,218, 47,253,107,188,127,253, 26,
+152,127,247, 29,226, 55,254,233,139,255, 0,155,166,255, 0,234, 98, 19,255, 0,226, 11,194,239,253,245, 55,255, 0, 37, 87,255,
+ 0,210,196,207,116,181,166,252, 3,241, 57, 89,226,255, 0,133,157,171,223,235,138,219,165,218, 85,203,250,153, 89,157, 81,183,
+232,178,101,204,165,211,157,166, 93, 53,202, 3,109,195,147, 56,120,175, 33,108, 82,154,113, 69,125, 66,221, 80, 29, 0,214,228,
+106,172,174,163,168,203,171,107, 50,250,180, 17,213, 80, 75, 36, 50,168, 33,128,146, 39, 40,224, 48, 36, 16, 25, 72,184, 36, 30,
+160,219, 22,246, 95, 93, 77,154, 80, 80,230, 84,110,100,163,204, 97,138,120,152,130,165,163,153, 22, 68, 37, 88, 6, 82, 85,129,
+ 32,128, 71, 66, 47,133,165,165,165,173, 92,110, 97,105,105,105,104, 96, 97,105,105,105,104, 96, 97,105,105,105,104, 96, 97,105,
+105,105,104, 96, 97,105,105,105,104, 96, 97,105,105,105,104, 96, 97,105,105,105,104, 96, 97,105,105,105,104, 96, 97,105,105,107,
+ 3,168,110, 45, 6, 60,249,116,122, 75, 21,123,182,183, 5,239,118,155, 75,181, 41,174, 85, 12, 9, 92,174,168,197,170, 85,150,
+166,169,212,105, 67,194, 32,183, 54,108,117,130,164,229, 32, 40, 29, 12, 12,103,154, 90,104,166,239, 21, 38,143, 91,167,219,119,
+ 13,169,123,209, 43,245,152, 83, 39,208,233, 9,165, 83, 46,121,213,134, 41,225,159,126, 83, 12, 88,181,170,177,130,134,188, 97,
+151, 38,251,171, 42,228, 95, 35,139,228, 86, 47,143, 95, 53, 54,130,157,111,109,119, 6, 76, 70,208, 28,118, 91, 44, 90, 40, 45,
+183,221,106, 77, 58, 85,222,220,217, 43, 74,114, 75,108,197,113,213, 99,149,182,214,178, 18, 70, 6, 28, 29, 45, 88,232, 23, 37,
+ 18,231,136,236,202, 36,244, 76,110, 60,135, 33,205, 97, 77,191, 18,125, 54,115, 56, 47, 83,234,212,201,141, 55, 38,149, 80, 64,
+ 82, 10,216,146,211, 78,164, 45, 36,160, 5, 2,111,154, 24, 24, 90, 90, 90, 90, 24, 24, 90, 90, 90, 90, 24, 24, 99,120,143,168,
+110,117, 51,103,174,233, 91, 65, 29,201, 23,200,138,203,116,255, 0,119,109,167,170, 12, 69,114, 67,104,169, 72,165, 50,240, 40,
+118,166,136, 69,226,200, 32,144,175,137, 0,184, 17,174, 20, 60,223, 25, 18, 95,121,199,215,190,238, 72, 83,138, 83,202, 92,139,
+187,156,186,165, 18,178,175,210,126,183, 54,117, 36,133, 36, 40, 16,160, 8, 61, 8, 35, 32,253,218,208,158, 40, 56,198,176, 54,
+ 85,185,246,165,163, 22,151,119,238,105, 66,153, 92, 54,212,151,168,214,187,171, 78, 67,245,249, 12, 43,244,179, 83,148,148,194,
+109, 65,206,185,121,108,167,148, 47,157, 60,116,224,190, 27,204, 99,139,140, 56,175,196,124,203,131,114,188,170, 14, 66,193, 75,
+ 56, 17, 77, 38,167,144,114, 96,182,185, 42,165,190,146, 16, 51, 50, 70,132,233, 84,102,199, 72,120, 15,198,220, 77,151, 75, 55,
+ 7,112,151,134,185,103, 26,102,153,172,252,246,158,170, 2,101,134, 61, 49,198,121,211,223, 68,116,145, 17,172, 23,210,170,242,
+ 53,139, 51,170,227,143,215, 53,223,196,133,153,238,191,194,219,167,117,237,195, 59,196,247, 52,214,107,151, 20, 5,201, 13, 99,
+196, 83, 45,200,148,149, 45, 41, 42, 0,144, 49,147,140,231, 88,195, 91,199,188,114, 93,109,134, 55, 39,112,100, 60,226,194, 90,
+101,171,158,186,235,142, 44,159,133, 40,109, 50,201, 90,179,216, 0, 78,177,155,198,244,186,247, 18,225,151,114, 93,181,137,181,
+218,221, 69,209,207, 34, 82,202,131,105, 39, 13, 68,134,194,112,136,145, 17,156, 33,166,210,148, 36,118, 25, 36,157,221,188, 47,
+ 45,145,246,104,112,186,239, 19, 59,221, 70, 93,217,123,214,159,133, 73,179,173, 8,106,140,213,106,227,187, 42,177, 94,153, 78,
+181,233, 18, 37,182,177, 72,167,177, 22, 51,207,212,167,150,214, 25,110, 59,132, 37,229,170, 52,119,121, 7,194,159, 15,120,203,
+198,222, 60,159,134,248, 23,136, 51,106,108,146, 23, 75,212, 85,212,201, 45, 66,164,141,162, 37, 49,195, 36, 81, 52,243,178,187,
+ 44, 97,214, 56,145, 92,188,204,177,150,110,196,241,107,196,110, 10,240, 51,128, 32,226,126, 62,225,252,162,167, 58,153, 28,251,
+ 61, 37, 52,112,211, 51, 70,161,230, 97, 36,209,203, 42,211,192,172,138,210, 20,105, 37,118,141, 82, 21,105, 2,174,163, 72,218,
+189,222,170,162, 69,126, 85,135,123,206, 76,183, 23, 46, 77, 77,218, 13, 81,227, 33,199,137, 91,146, 29,120,199, 37,106, 82,148,
+ 73, 81,238, 73, 58,203,118, 91,127, 55, 47,135,155,149,114,173,233, 18, 19, 1,201, 8, 23, 5,159, 86, 18, 27,166,212,210,217,
+229, 80,122, 50,192, 84, 10,130, 81,144,135,219, 1,196,246, 80, 91,101, 77,171,150, 85, 47,164,143,198, 35,151, 97,170, 81,118,
+183, 97,169, 54,130, 37,133,179,102, 61,111, 92, 53, 14,120, 40, 95,195, 22, 93,192,171,133,185, 46, 62,166,176, 22,235, 65,161,
+204, 74,144,218, 6, 18, 59,121,195,151, 16, 59, 31,237,121,225,250,232,188,108,251, 74, 62,216,241, 35,181,232,138,205,221,106,
+ 37,246,165,173,185,210, 97,201,126,152,244, 42,139,108,182,186,213,159, 85, 16,103, 34, 50,222,109, 50, 33,200,136,182, 92, 7,
+194, 14,201,234,207, 16,126,128,222, 38,248, 71,147,143, 16,120, 59,138,106, 38,207, 50,127,174,217,162, 46,210, 29,204,124,216,
+156,104,105,141,227, 9, 42, 77, 79, 51,176,134, 89, 64,146,237,200,222, 28,127,180, 43,194,191, 25, 51,195,225,207, 24,112,181,
+ 60, 89, 30,113,245, 32, 50,202, 17, 98, 29, 36, 17, 76,191, 88,176,139, 72,205, 19,193, 81, 10, 35, 77, 20, 76, 99, 32,118, 27,
+ 96,248,137,177,183,250,218, 21,123,106, 66,161,213,225, 37,166,235,214,228,213,160, 84,232,242,156, 78, 64,113, 41, 56,147, 13,
+101, 43,240,159, 71,192,224, 65, 7,149,105, 90, 19,106,226, 39,139,222, 29,184, 78,110,198,145,196, 38,229, 82,246,206, 6,226,
+214, 42, 20, 27, 86,171, 91,137, 84, 93, 38, 85, 78,151, 17,153,211, 89,157, 82,131, 5,214,105, 13,162, 43,237,171,196,148,182,
+ 91, 86, 72, 74,138,129, 26,224,102,199,110,133,115, 99,247, 86,135,116,199, 84,134, 26,129, 81,250,170,231,166, 5,148, 9,180,
+119, 95, 17,234,144,223,108, 28, 41,230,185, 75,173,103, 33, 47,197, 65,236, 8, 56,167,210,118,170,198,173,240,251,194, 53, 82,
+ 35,168,126, 52,237,202,189, 36,178,235,106, 10,109,214,222,179,169,238, 54,226, 20, 58, 41, 37, 10, 4, 31, 67,171, 87,232,151,
+199,112,248,245, 61, 22, 67,196,119,203,243,234, 9,141, 61,127,179,133, 66,234,105,230,150, 10,168,209,213,213, 57,175, 11,164,
+177,216,133,120,223, 78,133,116, 11, 85,125, 48,120, 26,127,163,229, 30, 99,196, 92, 52, 23, 49,200,107, 97, 90,156,188, 84,150,
+112,140, 42, 96,138,162,146, 87, 70, 70,147,148,147, 35,197, 32, 96, 89, 36,143, 86,182, 71, 38, 80,214, 61,247,102,238,101,169,
+ 68,190,118,250,231,162, 94, 86,117,203, 5,186,157, 2,229,183,106, 17,170,180, 90,196, 7, 74,146,220,186,125, 66, 35,138,110,
+ 83, 5, 72, 80,230, 66,136,202, 72,238, 8,214, 89,168, 64,112,175,237,189,221,253,134,225,159,102,120,123,225,163,133,105,251,
+189, 82,218,155, 26, 53, 58,249,186, 43,172, 93, 53, 88,104,168, 59, 62,163, 61,244, 83, 40, 54, 52,101, 57, 18,156,216,146, 0,
+149, 42, 82, 84,242,185,200,142,216, 71, 50,250, 53,193,103,210, 48,176, 55,151,114, 45,253,161,226,123,106,154,216,235,138,230,
+171,179,111,210,175,154, 45,102, 69, 70,198, 98,189, 45,246,226, 66,166, 92,208, 43, 49,218,153,107, 54,228,197,120, 94,244,183,
+101, 50,219,175, 32, 72, 17,218, 11,121, 61, 57,156,120, 63,198,153,119,233, 74,154,108,168,214, 80, 80, 73, 45,180,205, 3,212,
+154,116,102,229,204,244,233, 33,144,107,140, 7,210, 20,181,143,217, 29,185,103, 35,241,187,128,243, 63,209, 20,149, 89,184,162,
+204,179, 40,225, 7, 84, 53, 9, 74, 42, 93, 19,153, 2, 84,188, 98, 35,203,145,140,122,139,232,184,251,102,226,253,250,171,113,
+ 37,195,245, 6,251,107,107,171, 91,211,182, 52,173,200,122,165, 79,163, 51, 98,207,189,104, 17,110,183,106,213,101, 50,154, 93,
+ 53, 20, 39,167, 9, 42,157, 33, 82, 99,134, 90, 13,243,184, 95, 72, 64, 60,195, 47, 80, 32,128, 65, 4, 17,144, 71, 98, 53, 2,
+158, 50, 84,211,191, 72, 26,128,243, 1, 10, 14,113, 65,195,147,232, 82, 80,159,137,193, 34,193, 91, 78,246,248,156, 5, 45,144,
+174,224,164, 16,122, 13,118, 87,143, 15,111, 68, 62, 31,247, 89,238, 25,120, 83,218,134, 55,231,120,232,117, 24,214,189,203, 90,
+170, 59, 86,145,107, 83,239, 39, 22, 24,122,204,183,168, 86,222, 39,222, 53,230, 36, 56,219, 82, 84,212,136,236,177, 41, 11,138,
+145, 33,196, 56, 91, 91, 48,240,167, 51,118,225, 88,120,116,201,154,212,103,249,106,102, 51,243, 57,112,197, 76,172, 19, 86,169,
+ 89,130, 8,193,123, 6, 98, 25,182, 0, 19,182, 17,203, 60, 97,202,145, 56,190,163,137,196,121, 61, 47, 14,230,178,101,148,252,
+190,100,210,213,186,151,211,162, 37, 82,237, 35, 4,185, 84, 5, 84, 92,179, 1,190, 36,133,165,168,139,220,190,218,255, 0,106,
+111, 13,237, 80,239,190, 41,184, 29,183,169, 27, 89, 90,168, 69,138,228,225, 66,187,237, 23, 16,167,193,117, 20,246, 46, 35, 90,
+169, 70,163, 85,156,101, 14,120, 77, 84, 34,149,172,182,172, 54, 74, 84, 7, 85, 46,223,109,143, 13, 22,231, 5,182, 47, 26,148,
+171,102,247,187,237, 43,183,112,233,251, 83, 88,178, 40,166,138,205,225,100, 95, 50, 40, 85,218,228,250, 85,194,221, 66,123,108,
+120, 76, 51, 65,115,145,214,150,161, 37,154,132, 89, 13, 39,195,116,242,177,215,248,105,197,180, 35, 47,120,168,226,205,105,243,
+ 57,189,158, 25,168,170, 33,169,137,167,177, 60,146,241,185, 8,246, 6,193,244,130, 65, 0,146, 8,196,131, 46,241, 91,131, 43,
+206,100,147, 87, 77,147,212,229, 48,251, 76,240,215,211, 79, 73, 50,211,220, 14,112,142, 68, 5,227,187, 45,202,106, 32, 16, 72,
+ 0,223, 29,148,210,212, 92,183, 35,233, 31,162,243,160,209,233,124, 25,112,161,184,187,163,185, 51, 34, 63, 58,227,131,120, 83,
+170,147,233,118,147, 44,202,113,150,152,250,163,111,196,153,119, 10,221,142, 27,116,188,153, 48,153, 96,159, 12,248,202, 37, 72,
+198,248, 54,250, 69,151,109,251,190,214,214,200,241,107,178, 86,230,220,166,238,185, 96,217,113, 46,235, 45, 87, 21, 53,219, 86,
+231,169,204, 77, 62,159, 26,239,181,110,153, 50, 30, 76, 37,212, 94,142,195,174,178,251, 78, 69, 46,135, 23, 29,196,133, 99,108,
+248, 71,199,171, 65, 85, 94,249, 46,143, 99, 86,119,128,205, 7,180,136,210,247,113, 0,144,200, 87, 98, 84, 91, 83,129,116, 86,
+ 4, 95, 68,120,211,225,211,102, 52,121,116,121,233,147,219,157, 99,142,160, 83,212,123, 33,145,237,166, 51, 80, 99, 17,134,243,
+ 0,198,250, 99, 38,210, 50,144,109, 43, 29,120,113,198,217,109,199,157, 90, 91,105,164, 45,199, 28, 89, 9, 67,109,161, 37, 75,
+ 90,212,122, 37, 33, 32,146,124,128,215, 14,253,164,222,219,221,157,224, 86,233, 59, 61,101,218, 15,111, 86,249, 34,155, 14,165,
+ 92,161, 49, 88, 69, 18,210,176, 89,169,199,110,101, 41,155,170,176,220,103,222,151, 90,126, 19,172,190,154,124, 86,130,209, 30,
+ 75, 79, 63, 37,143, 17,182,220,230, 77,175,244,142, 56,132,142,220,122,222,253,112, 91,245, 86,205, 92,140,191, 79, 85,221,100,
+ 38,245,165, 74,102, 61, 69,151, 99,183, 46,153, 83,187,226,187, 77,174,184,128,224, 80,100, 59, 27,198, 13,148,165,214,201,230,
+ 8,229, 94, 22,113,190,113,150, 83,230,244,153, 69,168,170,198,168,121,147, 65, 20,147,169, 23, 6, 24,228,145, 93,245, 13,211,
+ 97,172, 88,173,193, 4,175,156,120,191,192, 25, 38,109, 81,146,214,231,119,174,163, 58,103,229, 65, 81, 52, 84,237,123, 17, 52,
+177, 70,232,133, 78,207,185,229,155,135,210, 65, 2, 71,219, 95,199,191, 8,187,217,187,147,118, 59,104, 55,194,208,220,189,198,
+166,208,234, 87, 13, 70,153,102, 59, 46,189, 76,133, 76,164,205,137, 79,158,183,238, 88, 81, 85, 78, 18, 91,151, 54, 58, 11, 41,
+148,167, 73, 89, 33, 4, 37, 68,109,254,160, 19,244,127,110,123,126,214,227,115,113,175, 26,237, 82, 45, 14,212,183,182, 43,113,
+ 46, 74,213,102,160,164,196,131, 73,183,233, 85,139,126,167, 62,165, 57,121, 34, 52, 86, 32, 48,235,174, 30,161, 9,104,247,198,
+186,103,185, 63, 72, 83,125,183,147,120, 38,237, 23,179,215,133,198,183, 45,182,164, 77, 98,145,112,222, 16,174, 10,229,197,113,
+192,167, 58, 82,245,199, 30,212,183,230, 68,102,215,162, 45, 1, 42, 11,168, 75,116,161,181,165, 79,248, 14, 57,225, 53, 36,226,
+ 95, 8,115, 26, 94, 38,172,201,120,104, 61, 93, 6, 89, 75, 4,245, 53,117,114,195, 4, 81, 25, 67,146,100,145,185,104,163,202,
+ 74,160,212,224, 2, 73, 32, 18, 34,220, 41,227, 94, 89, 89,194,148, 57,247, 21,178, 81,102, 57,181,101, 69, 61, 45, 29, 20, 83,
+212, 77, 48,132,160, 2, 56,151,153, 35,155,184, 12,231, 66, 18, 85, 64, 4,128,101,135,165,168,156,219,158,223, 30, 44,184,114,
+221, 75,123,111,253,161,252, 36, 55,183,244, 42,247,131, 37,117,235, 78,155, 93,160, 92, 80,232,239,201, 68,119,171,244,186,109,
+102,169, 54,159,121,211,227, 40, 44, 58,212, 57,113,220,230, 73, 71,139,226, 0,218,186, 89,198, 87,182,211,135, 30, 14,235, 27,
+ 75, 6,163,102,223, 59,171, 70,222, 93,176,167,238,197,161,117, 88, 18, 40, 31, 82,200,182,106,181, 25,180,248, 5, 70,177, 61,
+135,125,225,126,226,183, 10,124, 49,200,151, 18,149,128,224, 82, 83, 20,171,240,211,140,105,171,114,250, 40,178,177,152,182,106,
+143, 37, 52,148,179, 67, 60, 19,172, 66,242, 24,230, 71,208, 74, 13,202,146, 26,219,128, 70,248,152,209,120,173,192,245,116, 57,
+149,124,217,177,202,215, 39,120,227,171,138,178, 9,169,234, 41,218, 83,166, 46,100, 14,156,192, 28,236, 25, 67, 45,246, 36, 29,
+177,217,173,112,163,112,253,133, 28, 55, 95,188,105,212,248,162,173,202,171,215,108,187,186,163, 93,190, 47,125,152,175,202,157,
+ 87,160,214,183, 90,175, 85,141, 82,118,228,122,179, 46,114,165,201,181,228, 73,126,179, 50,101, 17,245, 57, 25,115, 93,105,180,
+ 56, 41, 5,116,160,202,240,191,237,190,220,158, 50,248,231,219, 77,158,218, 29,130,147,111,112,189, 93,145,119,193,184,247, 10,
+229,165,214,170, 87,151,189,209,182,206,237,185,233,142,205,168,210,100,170,143,106, 52,237,203, 71,166, 71,110, 59,134, 83,174,
+180,249, 30, 48,117,228, 33,185, 31,161, 92,200, 74,187,115, 37, 42,199,166, 64, 58, 74,170, 30, 49,240,218,181,169, 26,169,242,
+ 74,252,226,140, 25, 82, 41, 81,156, 65, 43,200,129, 36, 40, 91,149, 48,104,217,133,136,150, 59,130, 25, 75, 17,133,169, 38,224,
+127, 20,232, 22,181,105, 35,207,242,236,146,184,136,164,154, 23, 84, 53, 16,164,110, 94, 33, 32, 83, 44, 44,178,170,155,131, 20,
+182, 33,149,130,131,134,126,151,176,123, 71, 74,180, 27,176,226,237,253,162,205,158,136,126,226, 45,102,173,218, 59, 86,224,136,
+ 80, 27, 49, 69, 13,184, 98, 40,143,200, 0,228, 13,114,224, 99, 24,212, 4,189,180, 92, 57,109,223, 10,156,122, 93,182,174,205,
+192,141,105,218,119, 45,169,102,238,133, 50,218,161,145, 14,159,102,213,171,255, 0, 88, 69,169,211,168,140,199,193,165, 66, 53,
+106, 19,243,227,176,217, 74, 34,138,178, 89,140,150,163, 54,195, 77,254,136, 21, 90,173, 54,133, 75,169, 86,235, 51,225,210,168,
+244,120, 19, 42,149, 90,165, 66, 67, 81, 32, 83,105,180,248,238, 75,157, 62,108,183,214,148, 70,136,204, 86, 93,113,199, 22,160,
+132, 33,181, 41, 68, 0, 78,191, 57, 62, 35,175,107,151,218,161,237, 50,184, 37,109,235, 50,196, 29,229,220,202, 77,141,183,190,
+ 43, 14,184,170, 30,215, 90, 80,163, 80, 97,220,243, 97, 43, 10,140,219,118,133, 14,117,126,160,198, 73,109,217, 50,144,146,162,
+ 19,155, 39,192, 39,174,139, 62,226, 12,218,122,167,135, 34,160,161,145,235, 29,217,140, 69,217,213,208,184, 38,197,194, 71, 52,
+154,236, 88, 42,184,189,156,131, 86,125, 35,211, 47,155,135,120,111, 38,167,164, 73,184,135, 50,204, 35,142,133, 17, 84, 74, 17,
+ 81,146, 64,132, 0, 66, 51,201, 4,122, 1, 10, 89,144,218,233,113, 61,206, 11,119, 14,189,187, 28, 40,240,239,185, 23, 75,138,
+118,228,190,118, 83,107,110,250,243,171, 32,173,202,197,203, 99,208,235, 85, 53,168,134,209,146,102,205,124,159,129, 61, 79,234,
+167,176,217,253, 55, 59, 75,100,210,182,231,110,237, 11, 38,133, 20, 65,162,218,246,245, 30,223,164, 66, 7,152, 68,165, 81,169,
+241,233,212,232,193, 88, 25, 13,196,142,210,123, 15,213,211,141,170, 34,178, 72,102,172,170,154,158, 62, 77, 60,178, 59, 34,126,
+202, 51, 18,171,255, 0,106,144, 62,236,116, 69, 12, 83,193, 69, 71, 5, 76,188,250,152, 98,141, 36,127,219,117, 64, 29,191,238,
+ 96, 79,223,133,168,165,123,119,125,170,238,209, 91,175,240, 39,195,117,192,235,151, 29, 77, 14, 81,120,135,190, 40, 15,243,187,
+ 74,135, 49, 41,105,123, 57,111, 76,138,162,181,214,165, 33,194, 46, 23, 26, 41, 49,152, 90, 40,225, 78, 63, 38,166,204, 61,237,
+246,205,251, 82,224,240, 79,182,174,108,238,209, 85,161,203,226,135,116, 40,142,253, 82,227, 78, 37,255, 0,226,146,206,156,167,
+161,191,184, 53, 54, 18, 8, 53,247,252, 41,108, 80, 99, 56, 82, 61,229,165,212,159, 75,177,161, 8,147,185, 93,236,136,246, 94,
+213,106,214,149,199,198,255, 0, 17,212,217,179,238, 10,173,173,115,221, 27, 61, 64,185, 22,228,217,136, 85, 70,147, 62,106,247,
+ 98,229, 19,146,183,100,220, 18,214,234,221,164,120,203, 82,154,110, 66,170,174, 5,201,122, 11,177,110, 14, 3,225,236,179,135,
+178,212,241, 23,140, 33,215, 71, 11,133,202,168,154,193,235,170,175,228,151, 73,191,212,196,192,178,146, 8, 37, 76,132, 21, 68,
+ 89,105, 31, 17,120,151, 54,226,108,214, 79, 12, 56, 34,126, 93,116,209,151,206, 43,214,229, 40, 41, 45,231,132, 50,145,245,242,
+169, 10,202, 8, 32, 50,196, 8,105, 29,161,210,223,163,211,255, 0,132, 11,255, 0,169, 75,243,255, 0,199,236,141,116, 43,233,
+ 74,255, 0,148,224, 99,255, 0,154,226, 91,255, 0,107, 96, 53,207, 95,163,211,255, 0,132, 11,255, 0,169, 75,243,255, 0,199,
+236,141,116, 43,233, 74,255, 0,148,224, 99,255, 0,154,226, 91,255, 0,107, 96, 53,106,102,159,250,197,112,231,255, 0, 5, 39,
+255, 0,208,175,197, 59,147,255, 0,234,195,197, 95,252,124,127,255, 0,161,150,227,167,222,201,206, 30,246, 78,244,224, 27,134,
+234,253,209,181,155,125, 93,172,206,219,232,206,205,170, 85,108,219,118,161, 80,150,239,214, 85, 36,151,101, 76,151, 78, 91,146,
+ 29,229, 74, 71, 50,212, 78, 0,235,174,142,127, 36,254, 28,127,249, 20,218,239,253, 65,181,127,255, 0, 21,168, 67,236,206,242,
+251,107,106, 27, 11,183,118,135, 14,118,230,248,218,123, 35, 96,219, 49,169,246,138,246,239,108,225, 81, 63,132, 20,246, 12,185,
+ 95, 92,181,113, 85,232,203,170, 93,234,124,188,224,255, 0, 4,146,236, 21, 45,180,166, 60,100, 57,144,172,147,102,189,184,158,
+209,254, 22,247, 41, 54,175, 17, 19,170,123,167, 72,160, 84, 35,193,188,246,187,121,108,216, 86,109,253, 75, 99,149,165,201, 68,
+ 43,134, 21, 2, 5, 86,143, 93, 49, 75,106,105, 85, 86,234, 49,190, 62,117, 68, 87,136, 87,168, 78,113,225, 63, 21,230,217,158,
+127, 91,147,241, 53, 5,117, 75, 84,212,207,236, 81, 87, 72,103, 68,121,153,145, 24, 4,229,164,150,101, 82,174,202,138,219,115,
+ 58, 98,193,200,252,101,224,252,151, 41,225,202, 12,239,133, 51, 44,186,145, 41,105, 96,246,233,178,248,197, 59,201, 28, 17,171,
+186,157,124,201, 35,186,179, 6, 68,121, 25, 70,174, 95,164,237,173, 75, 62,218,177,233, 17,168, 22,157, 22,153,111,209, 33, 37,
+105,135, 73,163,193,139, 77,167, 68, 67,142,173,231, 17, 26, 20, 54,144,211, 9, 83,206, 56,178, 16,144, 10,156, 82,143, 82, 78,
+178, 93, 49, 28, 53,113, 19,183, 28, 85,108,189,139,190,123, 87, 80,118,125,159,125,210, 5, 74, 19,114,219,105,138,157, 46, 99,
+ 18, 31,167,214, 40, 85,152,204,188,226, 34,214, 96, 85,226, 78,135, 45,180, 56,227,105,126, 18,252, 55, 93,108,161,197, 62,250,
+231,250,168,106, 41,170,106, 41,234,227,104,170,224,119, 73, 85,193, 14,178, 43, 21,117,112,119, 12, 24, 16,215,222,247,190, 58,
+ 70,146,122, 90,170, 74,106,154, 41, 18,106, 58,136,209,225,120,200, 40,209, 58,134,141,144,141,138, 50,144, 84,141,172, 69,176,
+180,180,180,180,134, 54, 48,180,180,180,180, 48, 48,180,180,181,192,111,104, 5,251,125, 80, 56,143,220,198, 45,253,213,169, 89,
+ 9,183, 54,167,110,238, 27,118, 11,123,151,122, 90, 50,220,172,139,138,158,153, 72,178, 45,251,125,102, 37,197,116, 63, 9, 82,
+ 82,182, 38, 6, 89, 68,111, 26, 95,138, 30,142,216, 47, 57, 30, 78,249,221, 99, 81,164,226, 6, 84, 47,168,169,111,215, 68,181,
+129, 7,171,130, 78,246, 0,236, 78,216,215,169,168, 20,209,243, 10,234, 23,181,175,110,196,255, 0, 44,119,231, 75, 81,244,103,
+138, 29,229,219,186,190,226, 38,204,169, 55,100, 67,220,238, 34,247, 45,250,213,217,125, 65,164,205,147,104,206,165,216,118, 61,
+ 94,129,106,212, 95,186,100,197,162, 91,207, 73,151, 86,156,153, 30, 59,169, 82,141, 53,244,196,109,181, 55,135,114,241,198,191,
+ 22, 21,107, 15,123,247, 58, 21,239,182, 80, 41,252, 61,195,225,246, 85, 90,221,164,217,177,110, 10,125,254,238,232, 42, 29, 18,
+168, 34,221, 38,172, 62,174,129,245,162, 36,204, 82,163, 52,225, 82,101,134, 98,190,203,109, 37,110, 59,183, 5,230, 62, 70, 90,
+152, 57,114,114,192, 44,206, 14,169, 36, 72,144, 16,168,246,213, 43,132, 6,228, 91,204,218, 84,223, 8, 12,198, 29,193, 70,184,
+191, 64, 58, 0, 88,157,200,232,162,231,111,112,185,199,119, 52,181, 31,219,163,138, 13,215,187,247, 63,109,175,153, 87,125, 18,
+185,126,217, 23,151, 19, 82,104,252, 60,211, 45,201, 52,233,150, 71,240, 34,193,174,162,217,167,220,143,211,222, 93, 66,233,145,
+ 84,147, 75,108,134,220, 72,230,113,130,136,203, 97, 74,115,194,187,218, 60,116,241, 71, 94,159,183, 22,253, 63,112, 54,166,175,
+ 63,117,119, 39,104,237,104,115,229, 80,109,233,245, 11, 49,235,225,117,154,109,106,149, 86,182, 45, 90,232,117,138, 91, 85, 35,
+ 79, 91,126,254,228,106,167, 37, 61,109,158, 66,226,214,144,220, 23,153, 8,213,214,162, 27,132,212,225,139,174,147,174, 69, 33,
+ 78,131,172, 1, 25,109,118, 10,194,252,179, 32, 1,136, 25,140, 58,136, 42,221,108, 45, 99,125,129,245,219,115,107,117, 29,237,
+142,245,233,107,147,209,223,222, 43, 46,151,189,123,171, 87,168, 91,247, 45,193, 96,238,236,107, 86,163,184, 18,175, 13,204,135,
+ 26,223, 51,155,219,155,122,229,185,225,109, 4,121,171,160, 11, 66,149, 6,229,173, 86, 75, 18,101,144,211, 81, 94, 47, 30, 86,
+130,245,116,153,197,253,205,104,175,125,224,212,119, 98,196,186,104,182, 78,217,238,236,253,159,220, 25, 80,109,250, 84, 61,204,
+189,109, 75,111,110,106,180, 88,240, 28,129, 37, 16, 46,122,140, 59,158,240,173,209,164, 71,165, 4,181, 37,202, 9,253, 10, 30,
+ 67,199, 90, 31,253,157,169,144,255, 0,100,153, 42,109, 96,108, 24, 93,173, 25, 33,108, 27, 96, 37, 66, 3,232,144,141, 71,151,
+101, 98, 20,246,180, 31,222, 41, 75,252, 58,110, 5,250,122, 30,151, 3,109,247, 24,234,110,150,185,121,125,113, 27,190,246,141,
+ 14,226,220,138, 85,122,149, 95,137, 79,221, 29,192,219, 42, 86,219,187,104, 69,247, 57, 66,135,195,181,213,186,212,122,171,149,
+122,104, 85, 74, 93, 76, 92,212, 56,173,120, 13,169,182, 94,140,242,153, 95,134,178, 36,161,188,127,125,171, 86,214,225,238, 11,
+ 22,199, 16, 84,107,178,163,121, 39,108,124, 29,207, 68,141,169,183,108, 72,233,163,237,245,233, 92,170,211,106, 53,186,204, 89,
+ 52,202, 39, 35,139,138,182, 99, 49, 2,101, 90, 83, 81,212,194,240,184,239, 73, 25,143,134,171, 36, 66,194,104,254,198,161,110,
+ 97, 23, 14,138,202,199, 64, 11,164, 54,162,119, 6,214, 93, 86, 98,161,171, 35, 6,218, 79, 91,118,238, 9, 4, 11,239,126,158,
+238,246,218,253,134,210,215, 23,168,252, 66,238,173,122,152,237,253, 54,243, 85,110,231,171, 76,225,138,243,161,236,203, 18,102,
+193,102,123,213,219, 34,129, 34,173, 62,218,133, 2,172,137,173,218,242, 46,180,203,140,244, 86, 80,236, 39,101,213,208,220,211,
+ 33,228,132,186,236, 80,248,135,221,139,146,237,218,187, 18,214,222,123,102,243,129,185, 51,246,200,220,219,133,110,217,182,220,
+151, 54,246,175,118, 89, 27,207,114,220, 59,126,196, 88,238, 61, 5,154,162,127,128,148, 71,161,179, 83, 67,181, 56, 13,161,255,
+ 0,172, 27,152,151,144, 18,105,120, 98,178, 37,118, 51,199,104,151, 83,147,204, 1,108,138,237,184, 67,125, 33,173,125,181, 16,
+ 66,106,107,129,133,173,141,136, 1, 79,155,167, 77,247, 32,119,239,248,119,182, 58,147,171, 69,118,187, 74,182,233,114,107, 21,
+153,105,135, 2, 47,132,149,185,225,188,251,206,189, 33,212, 71,139, 18, 28, 72,205,173,217,211,223,148,235, 45, 49, 29,148, 45,
+231,222,121, 13, 52,133,184,180,164,182, 60, 63, 94, 23, 13,249,180,118,173,203,117,202,141, 58,225,125,219,146,149, 84,168, 68,
+134,221, 57,154,140,139,106,235,174,219, 34,165,238, 12,168,183, 13,217, 13, 81,219,121,198,219,253, 26, 28,125, 73,108, 37, 1,
+ 41, 13, 62,232,111,214,218, 88, 87, 53,221, 90,189,235,241,103, 84, 54,214, 35,223,192,237,191,166,243,212, 43,146,234,168,162,
+210,230,214,174, 85,210,219,108, 4, 84, 20,139,146, 5, 54, 10,228, 56,219,108, 55,239, 43,109,212,137,238, 41, 44, 50,192,240,
+207, 45, 59, 88,201, 19,178, 27,116,186,146, 13,137,182,215, 29, 72, 27,117,198,210,176,101, 86, 29, 24, 3,251,247,199,221,233,
+222,106,181,159, 75,167, 84,174,234, 93, 66,210,177,231, 69,184,235,115,168,180, 74,161,155,188,183, 37,187,104, 81,151, 91,175,
+ 70,163, 80, 40,200, 81,166, 32, 83, 84,169, 82,149, 18, 91,178,216,139, 78, 83, 11,126,159, 42,107, 42,103,136,187,179,237, 34,
+226,147,119,235, 63,197,223, 8,251,124,189,158,219,184, 97, 16, 40,176,233,212,196, 92,251,157, 84,166,150,212,167,102,185, 76,
+180, 34, 77,106,221,117,114, 22, 2, 25,135, 45, 15, 52,181, 45,110,204,125, 71,175,108,182, 23,109,174,187,130,169, 84,222,157,
+223,125,186,149,249,123, 65,247,101,210, 60,100,212,104, 54, 69,155, 36, 7,224,237,133,176,149, 2,203,148,166,146,166,158,173,
+205,109, 3,235,170,160, 43, 86, 98, 69,134,211, 59, 51,104,216,150, 77,129, 77,110,141, 99, 90, 54,213,159, 74,109, 41, 66,105,
+246,205, 18,155, 68,137,132,126,169, 91, 20,232,205,165,197,117, 57, 82,129, 81, 36,146, 73, 39, 78,217,109, 94, 95,150, 60,146,
+ 85, 80,254,145,169, 22,208, 11, 40,141, 58,223, 82,180,114, 93,186, 91, 96, 71, 98,164, 27,234,212,195, 81, 80, 21, 35,159,217,
+227,223, 81, 0,150, 61, 45, 98, 25,108, 58,223,168,247, 17,136,175,109,165,111,136, 46, 22,110, 90,253,251,188, 55,190,238, 65,
+226, 39,118,227, 73, 22,188, 43,214,173, 93, 15,170,216,230,151, 29, 53, 11,198, 13, 89,199, 26,118,108,119, 24,169, 38,135, 69,
+ 37,232,207,174, 19,213,119,127,239, 68, 64,213, 43,151,138,189,231,148,233, 93,203,191,247,220,103, 10,148,232,142,246,226, 85,
+105, 32, 96,149, 21, 51, 79,141, 84,100, 37, 35,175, 68, 55,129,142,128,107,190, 92, 81,109,158,214,113, 35, 67,184,108,237,202,
+102, 60, 43, 2,198,163,212, 42,247, 21,248,211, 49,155,173, 80, 37,183,202,252,118,173,218,155,209,221, 83, 79,170,117, 53,160,
+227, 77, 36,169,228, 67,121, 32,178,242,233,207, 57,194,234, 71, 15,220, 39, 90, 75,109,193, 77,191,119, 2,124, 94, 96,220,151,
+161,219,182,108,103,243,144, 18,185, 21,119,174, 89,106,100,163, 0,129,224,171,201, 60,131, 83,252,135, 54,165,204,160,150,105,
+ 50,197,106,184,152, 41, 60,176,194,223,170, 17,180, 5, 22, 29, 67, 58,155,146,119,189,240,193, 93, 73, 45, 59,170, 45, 73,228,
+176,184, 26,172,111,176, 36,139,220,223,181,129,216, 91,107, 91, 29, 21,246,100,113, 47,186, 91,235,125,110, 4, 59,162, 92, 75,
+222,214,164, 89,244,136,116,189,196,146,195,109, 87,221, 69, 6,164,227, 77, 68,157, 83,101,164,170,228,142,252,250,245, 93,166,
+ 94,150, 12,132,127, 7, 30, 90, 93,113,183, 73, 87,102,245,197, 62, 8,247, 59,106,118,179,113, 23,103, 90,182, 36, 75, 2, 30,
+235, 85,168,116, 25, 13,199,172,212,107, 14, 87, 43,209,216,152,205,189, 33,239,126, 9,109,170,147,105,114, 75, 75, 16,216,138,
+219,177, 93, 46, 62,219,134, 27, 74, 71,107, 53, 4,226,104,132,121,180,197, 40,197, 20,114, 5,101, 80, 0, 13,113,230,112, 20,
+149, 23,107,139, 2,109,109,247,185, 47,153,107, 22,165, 75,205,206,101,184, 39,115,107,116, 27,128,122, 88,239,235,233,133,165,
+165,165,168,254, 55,240,180, 29, 66,161, 2,147, 6, 93, 78,169, 50, 45, 58,157, 2, 59,178,166,206,154,251,113,162, 68,140,194,
+ 11,143, 72,147, 33,229, 4,178,202, 80,149, 21, 41, 68, 0, 6, 73,209,154,212,158, 53,182,250,255, 0,220,189,141,169,219,187,
+118,235,139,169,181, 89,166,213,106,148,134,158, 12, 59,113, 81, 32, 51, 52,201,162,180,181, 16,149, 58,102, 59, 6, 74, 80,165,
+ 0,225,167, 6,243,149, 0, 88,184,159, 52,173,201, 56,123, 58,205,242,220,170, 76,242,191, 45,166,150,104,105, 34,254,242,162,
+ 68, 66,203, 18,216, 19,118, 35,162,171, 57, 23, 8,172,214, 82,253,194,249, 85, 14,121,196, 89, 38, 79,153,230,209,228, 89,126,
+101, 83, 12, 51, 86, 75,253,221, 60,114, 56, 87,149,174, 85,108,160,245,102, 84, 6,197,221, 86,236, 52,131,138, 95,104, 4,186,
+199,214, 54, 22,197, 77,122, 13, 40,151,161,213,183, 5, 41, 91, 51,234, 13,245,109,214,109,116, 44, 5, 64,138,174,191,225,138,
+ 1,245,164,254,133, 45,116,112,232,102,217,108,157,245,187,134,183, 88,166,198,146,138, 37, 30, 21, 78,171, 88,184,102, 54,243,
+205,188,244, 72,207, 77,118, 44,101, 40,243, 79,168,186,180, 97, 88, 36, 32,185,206,226,129, 32, 43,100, 54, 19,129,203,238,248,
+173,181, 55,114, 41,115,173, 91,118, 27,233,241,105,111,225,154,189, 85, 72, 80,230,100,242, 40,251,132, 63, 37, 44,159, 21, 64,
+225,180,167, 62, 34,123,107,102,109,165,171,100,219,108, 91, 52,106, 68, 40,116,214, 97, 24, 34, 35, 12, 33,184,233,142,182,203,
+107,104, 54, 7, 80,164,169, 92,196,228,168,168,149, 18, 73, 58,227, 46, 26,240,155,196, 15, 27,243,131,198,254, 48,212, 79,148,
+100,169,175,216,178,205, 50, 64,197, 79,217, 84,129,142,186, 74, 91,129,173,223,251, 93, 72, 91,234, 0,172,216,237, 78, 38,241,
+115,195,223, 3, 50, 97,192,254, 13, 83, 65,156,103,114, 20, 53,217,166,164,168, 64, 71,218,103,168, 81,162,174,168,169,109, 8,
+159,217, 41, 75, 17,164,144,208,226, 44, 52,185, 13,195,169,211,165,188,142,118, 98,207,137, 33,212, 30,203,109,137, 13,184,226,
+ 8,249,165, 36,125,250,127,189,191, 59, 1,126,241, 15,193, 94,202,238,238,208,211,167, 93,244,109,151,184,170,119,101,215, 68,
+161,176,236,233,235,179,175, 10, 4, 24,142, 93, 76, 66,140, 20,185, 76,211, 95,167, 69, 50, 66, 18,165,179, 30,166,244,130, 3,
+ 76, 60,164,211,226,127,101, 42, 59, 29,186,181,187,117,109, 62,187,118,168,251,213,155, 78,162,182,200,106, 93, 34, 91,202, 95,
+186,135, 57, 66, 85, 38, 43,203, 84,119, 64,193,253, 26, 87,128,151, 18, 75,183,195, 79, 26, 53,221,151,166,139, 34,240,164,187,
+122,109,226,148,224,141, 17, 46,182,154,189, 13,183,212,165, 72,102, 2,165, 31, 10,109, 61, 74, 90,213,238,238,148, 4, 41,106,
+ 40,113, 41, 37, 5,151,232,189,226,236,127, 70,191, 20,115,188,175,140,233,189,135,151, 83, 26, 73, 43,163, 50, 69, 61, 47, 62,
+ 45, 50,104, 12,254,207, 83, 5, 76,154, 39,141, 95, 65, 49, 74, 20,198,204,234,241,244,170,240,114, 79,164,247,132,249, 46, 99,
+193,117, 94,220, 37,165,149,227,137, 29, 21,229,130,168,211,204, 26, 46, 97, 84,246,154, 89,233,163,215, 79, 35, 71,204, 2, 88,
+139, 9, 21, 81,160, 87,169,110,253, 27, 78, 31,247, 14,201, 78,246,241, 53,120, 64,159,107,237,173,207,108, 82,237,139, 90, 69,
+ 85,167,160,179,114, 68,163, 76,149, 92,175,220,241,144,248, 79,137, 70,138, 26,139, 29,153, 56, 45,188,228,137, 73,109, 71,193,
+ 94,122, 95, 89,143,236,147,185,110, 37,110, 61,103,134,205,190,118,245,118, 71,214, 47,186,246,201, 80, 28,168, 63, 81,230,241,
+ 76,135,214,152, 94,233, 38,103,139,215,198,113, 69,124,221,121,181,134,239,223, 25, 43,190,109,119, 54,195,105,109,159,226,243,
+110, 28, 97, 16,106, 24, 17,153,172,214,169,236, 0,134,169,158, 5, 63,244, 20,106, 55, 34, 82, 21, 29,165, 56,167, 82, 2, 22,
+180,183,204,210,189, 25,241,187,233,237,225,100,220, 3,152, 80,112,253, 92, 57,166, 99,153, 70,182,130, 10,152,234,164,119, 86,
+ 89, 18, 33,201, 5, 97, 70,145, 87,153, 52,237, 25, 88,195,132,133,228, 42, 7,154, 94, 3,127,179,211,197,122, 79, 17,114,220,
+207,136,233,166,203, 50,220,174, 70,250,249,233,164,165,141, 17,213,163,121,155,158,193,230,117,141,219,151, 5, 58,200, 30, 82,
+133,230, 72,149,201,211,219,222,171, 18,185,121,221,181,168, 8, 8,131, 86,185,107,149, 40,105, 74,121, 64,139, 58,167, 42, 76,
+127,132,143,135,244, 78, 35,167,207, 77, 71,183,193, 83,207, 4, 92, 7,166,161,226,120,232,185,171,137, 62, 46,121,194, 5,131,
+ 73,240, 82,160,174,160,134, 66, 7,221,173,145,216,173,173,169,238,230,227,208,109,120,108, 60,170,120,148,204,234,252,180, 33,
+ 69,184,116,136,238,161, 82, 57,156, 72,194, 30,120,132,178,214,123,173,224,113,202,149, 17,210, 31,105, 23,179, 6, 31,180, 15,
+107, 54,119,111,211,186, 82,118,157, 59, 83,112, 85,238, 6, 95,131,103, 71,187, 17, 86, 21,122, 52,122, 72,130, 99,187,113, 83,
+133, 57, 44,166, 58, 86,149,165, 78,133, 5, 20, 20, 12, 5,107,144,127,217,239, 11,228,156,117,155,248,159,196, 50, 53, 6, 69,
+ 81, 49,167, 14, 35,118, 89, 36,209, 81, 36,238,145,198, 25,217, 98,121, 98,141, 74,171, 13, 82, 58,223,200,246,236,191,246,140,
+186,241, 7,135,185, 87,133,124, 53, 18,230, 60, 67, 79, 0,168, 49,153, 35, 86,142, 62,101, 52,112, 70,242, 72,200,138,210,199,
+ 20,210,176,118, 83,166, 56,218,223, 88,151,102,125,130,112,118, 42,169,192, 62,220,155, 3,248, 58,253,211, 14, 69,121,189,216,
+141, 20,197,250,250, 61,248,229,122,168, 93,114,229,109, 39,197, 75,206, 82, 17, 78, 84, 37, 57,240,170, 2, 88, 75, 71, 8, 80,
+ 17,173,246,250, 13,156, 87,180, 78,224,103,100, 28,162, 63, 88,110,202,179, 25,220,245,218, 78, 69,118, 49,221,175,121,170, 25,
+141,184,237, 53, 69,181,220, 41,161, 42,215, 76,222, 83,227, 38, 98, 92, 68,140, 74, 75,192,117, 38,227,250, 54,119,189,161, 79,
+164, 73,216, 46, 46,110,123, 78,180,253, 25,154,101,232,154,149, 18,165, 73,135, 95,154,143, 16, 72,168,192,114,215,185, 18,237,
+ 62, 19,168, 82, 1,129, 35,223, 2, 20,149, 45, 50,202, 86, 27, 67,243,193,111,209,227,219,173,146,220,107,127,118,119,231,112,
+164,239, 85,205,109, 84,218,174, 81,173,207,169, 81, 69,178, 35, 87, 35, 60,153, 16,234,149,118, 37,204,149, 42,232,125,153, 9,
+ 75,205, 33,229,199,142, 93, 0,191, 29,240,156, 31, 80, 50,110, 36,240,255, 0,133,248,167,136,120,250,159,140,167,206,102,204,
+197, 81,139, 47, 20,147,199, 51, 60,242, 9, 52, 75, 52,159, 86,209,161, 80, 35, 44, 16, 5,210,199,204,186, 91,202,188,243,133,
+252, 73,226,222, 17,225,159, 14,106,120, 26,159, 34,131, 42, 52,130,108,204,214,211, 75, 2,165, 60, 92,190,100, 48, 71,245,171,
+ 35,134, 38, 64,165,201,109,106, 60,175,173,120,101,186,226,227, 30,216,222, 31,145,113,169,212,222, 13,238, 7, 6,204,215,213,
+ 43,196, 18, 19,114,181,106,109,123, 85, 19, 47,197,202,132,164,212,146,231,141,205,215,196, 74,201,235,211, 90,121,178,118,150,
+251, 86,248,244,118,209,176, 55, 14,149,181, 28, 67, 63,187,123,137, 77,165, 94, 87,124,150,160,183, 79,191, 68,251,137,138,172,
+ 71,101, 79,167,202, 75, 85,121,111,253, 99, 25,144,182,148,167, 95,150,150,144,124, 71, 18, 12,191, 55,139,216,145, 27,114,184,
+246,164,241,181, 23,126,103,210, 85, 77,220,141,186,220, 36,237,202,118,242, 36,168,229, 86, 2,232,107, 69, 32, 92,230,240,109,
+ 65,169, 66,136,128, 94,247, 2,166,125,229, 68, 33,194,145,159,188,127,251, 8,246,135,139,155,230, 86,246,237,181,237, 81,216,
+221,230,170,248, 18,174,153,244,186, 83, 85,171, 78,238,170, 68,109,180, 49, 90,169, 81, 81, 50, 35,244,171,136,165,166,146,236,
+232,146,128,119,194, 75,143, 69,117,254,103, 75,214, 91,226,215, 8, 67, 22, 85,150,205, 86, 35,138,175, 35,134,138,121,205, 36,
+147, 69, 73, 85, 26,176,229,203, 3,162,251, 69, 57,230, 48, 97, 30,180,109, 10,167,202,197,149,139, 52,240,103,141,106, 37,205,
+243, 72,104,140,147, 80,241, 4,245,244,244,226,182, 40, 37,173,163,149,163, 60,200,170, 35,145,189,154,161,121, 42, 80,203,203,
+117,214,204, 6,181, 8,220,174,226, 71,130,207,107,101, 91,105,167,218,220, 83,113,207,179,208,246,122,238,169,208,173,233,177,
+183, 54,243,164,208,173,170,181,102,101, 69,135,109,234, 98,103,201,178, 88, 45,207, 85, 69,134,150,209, 67,168, 82, 61,221, 78,
+173, 73,109,181,173, 58,117,197, 87, 1,155,253,192,167,179,178,235,160,238,229,199,101,215,173,141,200,226,147,102,174,107, 61,
+ 22, 93, 90,117, 86, 35,117, 8, 59,103,187,240,170,243,222, 92,168, 76,160, 38, 69, 61,202, 40,109,109,115,248,137,137,146,174,
+ 80,141,116,161,143,163,193,196, 46,228,213,168, 20,254, 34,120,219,187,111,155, 38,221,113,180,211,233, 77,199,185,174, 25,241,
+ 97,167, 8,114, 37, 29,203,202,228,122, 53,190,165, 48, 57, 82,234, 35,200, 8, 29, 60, 21,142,154,234,183, 19,126,200,187, 31,
+124, 56, 36,218,238, 11,108,125,198,175,109,125,165,181, 87,181, 22,242,163, 87, 39,211,158,220,106,188,245,210,168,215, 85, 46,
+ 68, 42,129,170,215,224,171,196,147, 34,233,147, 37,110,182,234, 91,105, 81,195, 44, 70,109,146,148, 54,214,158, 34,228,185, 53,
+ 87, 15, 81, 71,196,212, 85,249,107, 87, 71, 81, 94,180, 57, 43, 81, 65, 18, 68, 85,227,149, 89,109, 43, 77,170, 53, 86, 9, 12,
+154,144,144, 89, 2,128,238,210,120, 95,158,231,148,156, 75,152, 73,194,149,249,118,106,153,124,148,217,123,102, 25,242,215, 84,
+ 77, 36,193,146, 72,157, 90,240,164, 26,100,118, 66,243, 71,165,192, 96,175,172,152,216,127,163,207,182, 54, 85, 63,129, 26, 5,
+213, 18,131, 1,186,245,225,121, 94,117, 27,146,168, 35, 51,239,213,105, 84,250,195,212,170,127,190, 73, 8, 11,121,152,244,248,
+205, 54,202, 20, 74, 90, 10, 95, 32, 5,107, 39,133, 62,218,203,122,129,108,123, 96,109,245,210, 41,177,105,109,213,209,195,221,
+118,176, 97,180,134, 12,218,147,149, 56,208,159,168, 62, 91, 3,158, 81,133, 78,134,130,179,241, 17, 25, 57, 61, 53, 47, 47,103,
+175, 7, 75,224,115,135,139,127, 97,141,234,237,254,138, 5, 74,189, 81, 77,202,253, 13,187,113,201,102,185, 84,122,164,166,141,
+ 41,170,164,208,194, 90, 47,114, 3,239, 11, 42, 8,230, 56,206, 53,160, 92,119,251, 21,218,227, 43,139,138, 79, 20,201,223,169,
+214, 59,244,232, 27,125, 4,217,141,109,212,106,251, 11, 22, 36,247, 38,120,191, 94,185,121,196, 82, 76,164, 44, 39,151,221, 15,
+128, 83,205,151,129,228, 17,110, 24,227,108,134,131,196,238, 46,226, 60,195, 51,120,242,140,217, 51, 4,134,110, 92,238, 92, 77,
+ 42, 52, 0,198,177,153, 20,104, 81, 96,232, 2, 5, 0,233,176, 24,151,241,111, 0,241, 22, 99,225, 63, 5,112,190, 91,148,164,
+153,214, 76,249,107,207, 8,150,157, 4,109, 4, 46,181, 12, 36,105, 22, 38, 58,216,234, 40,236, 92,177, 35, 85,201,196, 94,166,
+255, 0, 4,227,251,102,171,138,226,141, 80,145,106,127, 43,106,227,151,155,183,111,130, 40, 41,134,253,197, 45,203,106, 77,100,
+206, 72,103,248, 45,250, 74, 26,201, 88, 17,189,203,148,159,208,106,118,219,255, 0, 77,225,202, 23, 11,155,155, 59,120,151,101,
+141,146,115,108, 43,142,220,242,235, 79, 83, 77, 2, 85,186,237, 13,231, 25, 76, 37,173, 94, 28,153, 78, 35,192,250,189, 49,242,
+243,146, 21, 28, 67, 5,242,214,185,225,237, 10,246, 37,236,223, 28, 51,160,110, 93, 50,230,159,180,155,231, 14,139, 6,141, 84,
+188,169, 20,168,245,170, 53,231, 14,149, 20, 69,166, 34,238,183, 93,151, 24,202,168, 48,195,108,176,204,230, 36,178,250, 35, 54,
+134, 94, 76,166,217,142,134,185,163, 99,253, 27,221,214,159, 80,165, 91,187,205,197,181,110,187,181,116,121, 33,246,109, 11, 90,
+155, 92, 73,125,180,171, 33,152,105,184, 43,142,194,160,169, 67,169,117,184,146, 84,156, 20,165, 25, 60,195,123, 59,206,248, 23,
+142, 41, 56, 79, 52,204, 56,182,110, 23,174,225,202,104,160,154,140, 82, 79, 49, 38, 34,167, 93, 35,197,104,209,156,173,149,152,
+146, 20, 70, 93, 84,165,153,191, 32,200, 60, 65,240,254,183,140,178,156,183,130,224,226,234, 14, 40,171,154,162, 10,227, 91, 4,
+ 0, 9,129, 81, 29,108,114,131, 35,162, 6,187,162,128, 11, 25, 66, 51,137, 46,188, 20,224,130, 37,122,161,107,241,207, 22,205,
+ 68,229,213,151,193,189,253, 34, 59,113,121,149, 53, 84, 40, 55,206,223, 79,185,147,150,134, 72, 22,172,106,177,123, 29, 60, 36,
+ 57,159,135, 58,112,125,151, 27,107,197,206,231,238,109,253, 66,224,219,124,109,173,154,220,132, 90,144,164, 85,209, 87,159, 18,
+ 13, 86,231,182,219,170,182,183,153,164,123,205, 6,114,159,102, 44,244,195,114, 64,108, 32,164, 58,218,149,148,246,148,183, 0,
+ 30,195,186,103, 4, 59,219, 95,221, 41, 91,210,238,236, 81,174, 43, 18,191, 97, 78,179,235, 27,115, 6,133, 5,234,101,126, 92,
+ 7,229, 25,178,149,117,212, 19, 61,159,118,131,224,173,133,199, 8,117, 50, 23,206,113,240,235, 95,184,128,250, 57, 52, 5,238,
+ 92,237,211,224,251,126,238,109,132,155, 34,168,253, 90,157,107, 61, 18,125, 66, 21,175, 38, 90,150,227,236,218, 87, 93, 26,179,
+ 18,165, 71,166,165, 75, 33,152,239, 9,107,109, 10, 40, 18,121, 2, 82, 39,213,158, 45,112, 93,125,119, 19,229,145,230,113,193,
+ 73,155,199, 76,244,245,181, 20, 18,212,211,115,163, 69, 71,134,162,150, 72,214, 70, 81,203, 66,172, 80,165,217,219, 82,178,174,
+170,226,135,193,142, 59,203,114,254, 18,205,101,202,100,158,183, 36,150,174, 58,154, 26, 92,198, 42, 74,174, 68,178, 51,199, 61,
+ 45, 92, 82, 52,106,228, 72,225,215,152, 30,200,138, 85,149,155, 79, 63,120,152,246,113,123, 73,247,246,235,219,109,167,226,139,
+140,141,138,188,175,178,213,122,187,181,118, 29,241,126, 64,166,221,115, 99, 73, 93, 54,159,112, 78,182, 41,145,237, 56,210,106,
+ 13, 56,228,106,115,110, 33, 60,254, 41,132, 84,218, 23,238,207, 41,173, 31,246,169,108, 70,229,240,207, 70,224,147, 98,119,114,
+163, 71,170,222,187,125,195,213,118,150,252,234, 12,137, 18,233, 70,139, 43,118,239, 89,244, 56,177,164,203, 97,167, 29, 12, 68,
+146, 91, 60,200, 72, 79, 32, 74, 71, 40, 26,238, 94,204,253, 30, 26,228,253,212,164,238,167, 22,156, 77, 94,219,207, 82,164, 79,
+131, 56,192,167, 63, 93,167, 79,170,174,154,224,118, 27, 85, 91,234,181, 93,149, 83, 76, 20,173, 8, 10,106, 34, 99, 59,203,144,
+220,182,137,206,183, 63,218, 81,236,103,137,199,254,225,237,141,254,141,242,159,182, 63,197,206,219,177,183,108, 80,227,216, 76,
+ 93,200,157, 30, 61,114,165, 89,102,162,106, 82,110,248, 10,142,176,154,138,153, 45, 22,157,230, 12, 37,207, 23, 42, 41,211, 54,
+ 91,226,118, 67,149,113, 15, 14, 82, 84,113, 37, 61,110, 65,151, 37, 76,179, 61, 46, 80,244,112, 67, 83, 36, 82,198,139, 2, 70,
+ 26, 87, 71,230,182,191,169, 81,168, 7, 46,218,138,163,238,105,225, 55, 17,103, 28, 53,197, 21,180,220, 43, 85, 67,196,121,172,
+148,176,195, 29,102,117, 29,117, 68,244,145,205, 12,142,213, 15, 41, 72, 99,120,249, 43,203,250,242,218, 47, 24,141,116,134,125,
+234,246,125,236,206,223,237,103, 9,155, 11, 64,179,173,250,125, 38, 3, 59, 97,100,212, 92, 17,163, 54,202,230, 85,234,214,237,
+ 54,167, 88,172, 76, 82, 19,151,234, 82,234, 82,100, 72,125,213,100,173,199,207,100,132,164,111, 48, 24, 24, 29,135, 65,166,203,
+102,236, 37,237,126,216, 88,187,122,185,202,169,155, 50,212,183,173,113, 82, 83, 9,138,169,233,160, 82, 33,210,147, 53, 81,146,
+234,196,117, 58,152,129,101,176,181,132, 21,242,133, 40, 12,150, 11,143, 78, 49,236,142, 6, 56,109,189,119,206,237,247,106,133,
+ 98, 35, 63, 80,109,189,164,235,165,183,175,125,198,171, 71,147,252, 28,183,209,200,180,173, 16, 18,168,242, 38, 84, 93, 65,230,
+143, 77,165,203,121,176,183, 80,219, 78,115,121,134,183, 63,207, 30, 26, 53,122,250,236,222,165,132, 99,114,242,188,210, 27, 18,
+ 91,123,146,215, 98,214,176,185,107, 0,113,212, 98,122, 30, 27,225,232,231,174,100,203,178,252,150,145, 76,135, 96,145, 71, 12,
+ 64, 48, 1,118,178,133,178,170,222,230,193, 65, 36, 12,113, 23,233, 10,251, 69,127,139,219, 56,240, 51,180,149,207, 14,246,220,
+ 58, 76, 90,158,253,213,105,238,225,251,107,110,170, 45,166, 69, 35,111,195,236,175,154, 61, 90,224, 64, 68,138,131,100,165, 72,
+161,165,182, 28,109,216,245,192,166,197,250, 63, 62,207,199, 44, 27, 45,238, 46,247, 46,142,166,111, 45,207,164, 38, 30,218,192,
+168, 71, 90, 31,183,118,209,231,218,148, 43,105,105,228, 15, 10,125,126, 68,104,146, 26, 88, 10, 34,147, 18, 26,217,112, 38,161,
+ 37,189,113, 27,217,255, 0,195, 62,227,251, 81,184,218,174,223,155,197, 50,161,115,219, 13, 92,234,221, 61,253,186, 37, 37,214,
+218,174, 63, 83,168,185, 34,149, 99, 68, 49,148,129, 0, 85, 37, 71,114, 43, 76, 50,166,145, 6,141, 74,151,238,188,134, 52,102,
+151,250, 18,218,182,237, 58,213,161,211,168,148,168,145,160,194,167,196,143, 18, 60, 88,140,183, 30, 52,118, 35,180,150,153,143,
+ 29,134, 82, 16,203, 8,109, 41, 74, 16,144, 18,148,164, 37, 32, 0, 53,117,113,253,101, 39, 0,112,165, 23,134, 89, 44,193,243,
+ 42,197, 90,140,226,116,234,236,225, 88, 67,126,160, 61,151,202,108, 86,153, 34, 86,213,206,123,208,254, 27, 80,214,248,145,198,
+ 53,254, 44,103,208, 52,121, 85, 11, 61, 54, 73, 76,251,132, 68, 44,166,123,116, 38, 59,183,152, 92, 53, 84,146,178,149,228, 32,
+ 25, 10, 82, 18,144,148,140, 4,128, 0,244, 3,160,215, 62, 61,164, 30,208, 29,190,246,125,108, 68,221,193,174,166, 21,195,185,
+183, 74,103,208,246,111,110, 92,144, 91,126,238,186,153,142,218,156,168, 84,144,203,169,118, 61,155, 75, 18,162, 72,171, 73, 65,
+ 65, 8,121,152,108,172, 76,155, 21, 42,223,186,157, 78,157, 69,167, 84, 43, 21,138,132, 42, 77, 34,147, 10, 85, 74,169, 84,169,
+ 74, 98, 13, 58,155, 78,130,195,146,166,207,159, 54, 83,137,106, 28, 38, 99, 52,235,142,186,226,146,134,208,218,150,181, 4,130,
+ 71, 9,184,174,225,239,128,223,109, 5,235,103,196,178,120,186,133, 90,187,118, 26,145,116,193, 93,191,180, 87, 53,159, 80,147,
+ 34,153,115,212,232,158,253, 88,147, 10,183, 72,146,245, 74,148,212,218, 52, 38,155,157, 7,154, 22,102, 37, 42,117, 74,117,156,
+212,252, 35, 69,149,207,156, 82,213,241, 20, 21, 13,195, 52, 45,174,178, 72, 34,146, 64,163, 75, 24,163,145,145, 78,133,154, 64,
+177,177,184,109, 37,180,144, 64, 34,228,227, 92,195, 55,166,201, 42,232,248, 98,122,101,226,188,193,116, 80,199, 81, 52, 81, 22,
+ 98,202, 37,146, 53,145,135, 49,160,137,154, 69, 91, 50,235, 85, 12, 10,155, 24,223,112, 43, 69,217,158, 45,184,165,187,120,165,
+246,138,241, 35,182,116,170,123, 23, 91,119, 61, 74,223,220,203,198,221,164,212,247, 82,240, 90,154,145, 18, 4,155,122, 83,169,
+ 76, 13,179,165,195,106, 27, 94,232,150, 88,134,243,109, 69,164,194,109, 80,163,204,105,153,125,220, 94,209,127,103,156, 61,184,
+186,232, 52, 94, 47, 56,125,117,247,237, 26,244, 24,113, 99,110, 45,186, 93,145, 37,234, 60,166, 35,176,203,104,151,241, 45, 78,
+ 41, 9, 74, 64,234, 84, 0,215, 43,127,189,146,225,251,255, 0,151,141,236,252,108, 47,255, 0,212,117, 98,186, 62,141, 70,193,
+ 80,109,171,134,184,206,250,111, 75,206,209,168,117,106,171, 77, 58,108, 79, 9,215, 41,240, 31,150,134,220,228,180,193,240,212,
+166, 64, 56, 32,224,156, 28,234,227,226,156,231,194,238, 48,205, 41, 42,234,248,179, 49,165,167,161, 88,226,165,164,134,136, 37,
+ 61, 52,107,164,104,141, 76,102,218,138,130,204,119, 54, 10, 44,136,138, 40,222, 15,200,252, 93,224,124,162,178,142,139,131, 50,
+202,202,154,247,146,106,202,201,235,245,213, 85, 72,218,137,121, 92, 72, 47,160, 51, 4, 81,176,187, 49,187,187,179,241,151,216,
+125,188,123, 87,177,188,108,155,223,120,111,251, 87,109,173, 15,226,150,243,164,127, 8,239, 10,196, 74, 37, 35,235, 57,181,155,
+ 69,248,144, 61,246,107,137, 71,189, 56,212, 57, 74, 66, 51,149, 6, 20, 64,192, 58,156, 37,241,179, 92, 40,241,203,106,237, 46,
+225,220,246,214,221,239,165,175,107, 85,218,191,118,150,241,196,122,245, 54, 52,165,184,202, 93,157, 69,169, 68,120, 38,161, 71,
+146,245, 54, 31,189, 67,112,189, 2,106,233, 81,140,168,239, 42, 43, 5,184, 0,123, 51,184, 59,180,120,227,226, 73,123, 35,122,
+ 92,215, 45,167, 72,254, 47,238, 75,185, 21, 91, 80,210,133, 79,223,104,181, 43,126, 19, 17,149,245,197, 62, 75, 62,234,182,234,
+239, 21,254,143,159,153,164,114,168, 12,131,250, 11,240,185,177,214,207, 9,155, 29,181,187, 7, 78,186,100,213, 41,118,141, 53,
+ 54,133,175, 62,230,151, 77, 98,183, 95,122, 59, 21, 90,234,227,165,168,172,176,212,202,144,167,198,170, 72, 83,113,218, 4, 70,
+167, 60,241, 64,109,167, 22, 49,227,201,203,105, 56,158,154,191, 47,204,234, 97,226,113, 20, 74,241,160, 40,145,211,114,230, 28,
+196,153, 44,218,218,229, 29,117,125,130,110, 45,140,253, 29, 23, 52,173,225, 42,188,187, 50,202,105,103,225, 38,158,102, 73,100,
+ 43, 36,146, 85,137, 41,207, 41,224,123,174,133, 0, 58, 57, 91,243, 2,216,220, 12, 63,180,219,118,145, 74,138,212, 72,144,152,
+ 67, 77, 33, 40, 72, 13,164, 97, 41, 24, 0, 0, 58, 12, 1,168,214,125, 36,238, 26, 44,170,175, 15, 59,113,196,205, 42,137, 14,
+ 22,224,216, 59,137, 73,176,171, 53,136,200, 98, 51,213, 75, 2,242,167, 86,221, 76, 42,145, 5, 42,168, 46, 29,213, 78,163, 42,
+ 16, 60,230, 50, 42,243,249, 18, 18,251,170, 18,111, 4, 30,160,228,122,141, 71, 19,233, 42,111, 69,183,107,112,145,182,219, 37,
+239,241,156,189,119, 91,118,169,119, 3, 20,143, 17,179, 37,155, 43,111,169, 53,105, 85,170,210,208, 57,148,210, 5,199, 87,180,
+163, 53,144,128,239,189,200, 40, 89,247,119, 16,170,219,194,167,174, 95, 16,120, 99,216, 11, 9, 94,160, 7,211,125,224, 42,220,
+240,214,234,188,157,100,223,109,175,219, 22,175,140, 41,151,191,134,156, 91,250, 68, 41,133, 41,137,143, 85,182,168, 14,158,207,
+166,253, 27,157,160, 45,183,222,221,240,212,253, 25, 45,199,171,212,118,115,136, 29,176,151, 33,247,169, 54,142,229, 80,110,122,
+ 75,110,168, 41,184,138,190, 45,181, 67,159, 26, 49, 42, 42, 67, 62, 61,152,135,139,120, 8, 14, 76, 91,137,202,221,112,234, 82,
+ 58,139,207,209,155,219, 90,149, 31, 99,247,187,115,230, 71,118, 60, 91,231,115,160,208,105,106,117,183, 80, 38,192,177,109,214,
+ 20,185,241,212,165,114,187, 24,213,110,170,156,110,100,164, 31, 22,152,242, 20,163,202, 2,101, 13,163,120,178,105,219,196, 78,
+ 41, 52,214,229,243,208, 27,116,230, 8, 34, 19,125,252,208,250,189,247,193, 60, 25, 90,149,240,199,132, 5, 93,249,190,206,228,
+ 95,175, 40,212, 76, 97,251,185, 38, 61, 63,225,181,182,194,210,210,210,213,119,139, 59, 11, 75, 75, 75, 67, 3, 11, 86,231,168,
+244,137, 50,219,159, 34,151, 78,126,123, 74,105,109, 77,122, 12,103,101,180,182, 20, 20,202,155,146,182,138,208,164, 40, 2,146,
+ 20, 10, 72,200,193,213,199, 75, 89, 4,141,193,177,247, 96, 98,222,186, 77, 45,198,165,199,114,155, 79,113,137,239,123,196,230,
+ 87, 14, 50,154,153, 32, 41, 11, 15,203,109, 77,226, 67,220,237,182,121,150, 10,178,128,115,144, 52,195, 92,219,245,176,182,149,
+122,185,103,220,245, 58,117, 38,177, 14,165, 62,137, 88,166,205,183,100,165, 18, 94,180,182,226, 54,233, 43,153,126,224, 91,159,
+ 5,155, 45,232,238,197, 88, 82,208,167,241, 10, 62,100,128,214,182, 39, 90,175,186,220, 34,237,174,239, 92, 87,189,203,114,202,
+174,179, 62,249,180,173,155, 70,114, 96, 73, 97,182,233,177,104, 55, 4, 90,205, 74,117, 39,196, 97, 70, 44,234,189, 58,155, 70,
+165,212,213,146,151,233,244,134, 89,229, 24, 36,239,229,230,133,166, 97,152,203, 44,112, 21,216,197, 98,193,245, 40, 4,130, 13,
+194,173,216,141,137,210, 0, 32,219, 9, 75,204, 10, 12, 42,165,129,253,111, 75, 29,135,199, 97,247,227,225,226,159,135, 84, 56,
+170,163,213, 95,119,172, 38, 13,219, 88,247,105, 22,125, 85,171,145, 66,203,155, 66,162,214, 18,136,138,166,123,195,149, 5, 46,
+227,166, 8,173,167, 43,148,194,220,113,158,102,153,112,164,250, 39, 17,220, 62, 92, 21, 58, 93, 58,145, 81,141, 34,185, 94,151,
+ 97,212,226,211,133,167, 80,106,170,170,149,249,112,215, 45,203,118, 92,198, 28,166,133,197,168, 51, 86,164, 85,125,241,199,121,
+ 87, 1,181,165,233, 10,109, 15,161, 74,182,220, 60, 32,109,125,201,123,215, 47,185,174, 86, 27,170, 87, 55, 43,109, 55, 45,216,
+204, 61, 29, 48, 33,205,219,106, 84,138, 75, 84, 24, 49,212,193, 12, 91,213, 70,167, 84,156,170,176, 58,201,118,122,151,204, 20,
+134,139,116,232, 92, 31,109,165,187,120,209,239,138, 92,218,235, 53,202, 30,226,110,142,227, 66,113, 79, 68,117,145, 63,115,169,
+177,233,206, 81,214,211,177,136, 85, 10,144,168, 20,183,233, 12,118,138,245, 57, 11,202,185,222, 14, 56,145,195,220,178, 86,106,
+161, 46,139,128, 74,144, 27, 78,161, 30,201,246, 67,125, 94,175,251,237,109,176,143,246,189, 67,202,133,111,239,189,175,107,245,
+235,111, 53,190,235,247,192,151, 23, 20,214,213,149,120,238,245,161,112, 90,149, 90,123,118, 93,223,110,218,116,155,146, 37, 34,
+165, 34,213,175, 92, 87,142,216, 91,119,181, 10, 5,199, 93,102, 0, 98,139, 83,155, 86,172,154, 91, 40,230,144, 74,145, 17, 79,
+169,147, 50, 58, 23,100,166,241,143,176,110, 91,118,252,155,150, 60,202,122, 85,111, 48,244,196,211,236,186,197,114,218,166, 92,
+206, 88,209,239, 59,138,199,163,207,137, 73, 87,214, 85,120,214,244,153,202, 90, 88,103,194,117, 48,100, 69, 14, 42, 91,110,197,
+ 77,226,167,194, 53, 62,224,168,214,164, 92,187,177,184,117,202, 93,207, 86,176,238,171,166,132,252, 75, 34, 52, 75,138,247,219,
+171, 22,218,178,232, 23,101, 70,124, 75, 81, 19, 90,146,100, 90,180,154,171,241, 99, 73, 98, 19,149, 8,201,195, 8,139,207, 29,
+204, 89,174, 3, 54,230, 28, 89, 84,218, 93,213,112, 83,169, 85, 8, 13,183, 62, 50,109,173,179,153, 84,126,170,109,166, 45,137,
+213, 38,111, 9,246, 59,149,202,124, 73, 44,199, 68,199, 96,199,169,183, 24, 77, 91,133, 9, 76, 55, 93,134,181,227, 28, 52, 99,
+ 65, 52,210, 44,161, 35,212, 99, 50, 88,176,141, 85,236, 90, 50, 67, 23,214,214,210, 86,214,179,139,144, 10, 77,101,201, 85, 4,
+ 92,245,183, 75,220,116, 61,133,133,239,123,246, 56,201,110, 78, 45, 54,210,143, 71,187, 69, 26,206,190,106, 23,221,159, 10,239,
+174, 77,176,164,109,229,114,157, 93,162,200,181,109, 26, 5,194,253,122,230, 66,160, 17,111,208,220,164,222, 86,170, 68,245, 41,
+ 75, 91, 85,192,134, 91,117,109,188,218, 1,107,139,222, 30, 41,208,160, 38,182,212,154, 96, 81, 98, 34,164, 83,236,138,173, 86,
+132,229,233, 73,143, 2, 77, 86,210,160,202,167, 82,150,229,102,224,167, 57, 85,155,240,177, 28,130,105,117, 4, 48,181,191, 26,
+ 67, 73,200,239, 78, 20,232,247, 93,227,184,151,181, 59,113,239,187, 58,175,186, 16,107, 20, 59,177, 20, 6,109, 25, 81, 38, 91,
+ 85,235, 26,194,177,234,148, 36, 49,113, 91, 83, 67, 13,174, 54,221, 80,228,162, 75,124,147, 24,118, 76,180,176,251,104,120,114,
+ 97, 71,129, 29,185,102, 75,134,157,116, 87,233,212,215,107,237,221,142,192,102,217,219, 23,234, 46,220,107,153, 26,125, 70, 66,
+175, 41, 86, 50,235,200,165, 73,156,220,169, 11,130,138,162, 26, 67,243,150, 16, 68, 68,166, 32,196, 67,134,204, 81,243,102,154,
+ 55, 96, 25,172, 90,225,180,141, 75,126, 89, 22, 86,190,141,141,197,203, 50,155, 12, 6,246,205, 70,202,164, 3,177,176,251,143,
+218,190,227,175,167, 96,112,231, 92,188, 65,108,253,156,237, 21, 85,234, 37,205, 77,117, 54,204, 75,162,127,188,109,197,114, 52,
+173,190,178,220,185,255, 0,131,148,235,130,242,141, 38,152,219,246,149, 21,117,198, 37, 41,160,227, 97,192,213, 50, 76,191, 5,
+ 44,199,113,212,227,232,226,211,100, 21, 21,169,244,186, 61,249, 82, 97,202,109,126,252,241,169,187, 81,118,165, 40,183,173,245,
+ 24,119, 77,250, 28,149, 70,101, 47, 81,162,201,144, 35, 61, 61,165, 56, 94,122, 73,102, 57,144,174,112,155,149,235,194,253, 54,
+254,147, 62, 77,127,114,247, 1, 75,185,109,201,150, 53,252,136,169,180, 27, 69,243,183,234,190,107,183,181, 30,208,169,151,173,
+119, 21, 76,139, 79, 23, 21, 86,150,196,154,122,162,203,114,155, 49,212, 72,121,217, 74, 76,164, 52,251,165,194,237,235, 26,209,
+179,173,109,147,172, 76,141, 81,133,182, 87,238,208, 87, 46,106,213,219, 71,163, 71,122,208,188,167,211, 39,166, 53,106,131, 47,
+109,107,104,172, 50,153,222,250,242,158,167, 46,147, 80, 97,184,166, 59, 47,172,204, 15, 66, 37, 60, 57, 12,220,152,228,168,144,
+ 77, 35, 16,197,159, 68,106,161, 88,234,102,104,191,104, 88, 1,114, 84,173,192,114,193,114,237, 84,161,152, 32, 33, 64,176, 2,
+228,155,141,128, 13,233,248,131,216, 12,110,107,245,216,236,216,210,174,155,102, 19, 51, 24,254, 12, 74,185,104,144, 74,126,174,
+102,127,139, 76,118,175, 5,151, 65,108,123,159,142,181,183,206, 74,121,146, 94, 82,148, 50, 14,180,215,116,165,219,144, 32,213,
+182,215,234, 10, 53,122,167, 42,135, 42,149,118,221,213, 70,214,169, 21,107,134,188,202,229, 86,106, 18, 4, 96,219,174,148,212,
+ 36,135,144,147, 32, 54,202,144, 24,109,164, 55, 29,160,157,199,135,107, 57, 22,193,139,100,166,162,160,236,107, 61,139, 88, 85,
+154, 99,195, 80,113,154, 42,105, 34,162,212,101, 58,174, 69,115, 39,197, 74, 10,206, 14, 19,204,123,235,144, 59,209, 19,116,167,
+ 75,115,110,234, 52,115,107,213, 46,219,210,159, 99,220,151,204, 58,236, 73,212,214, 41,117,135,213, 18,124,250, 47,142,152,243,
+ 99,207,171, 72, 8,129, 8,201,140,219, 77, 59, 90,111,154, 74,212,166,148,189, 76,174, 26,121,106,106, 29,239, 34, 68, 9, 80,
+110, 46, 9,181,201,219,183, 91,237,190,248, 60,236,234,136, 7,148,183, 95,203, 29, 10,217,141,236,135,113,237,133,155, 34,137,
+104, 94, 55, 7,131, 64,143, 79,110,109, 18,136,236,138, 4,185, 20, 96,229, 38, 91, 17,174, 7,228, 6, 36,186,204,216, 18, 99,
+188,239, 63, 35,146, 34,186,166, 84,235, 74,109,197,229,117,203,231,113,228, 81, 38, 76, 27,115, 80,181,169, 66, 35,130,109, 86,
+161, 91,167,203,170,192,109,238,102,132,198,233, 52, 53, 63, 33,184, 44,146,133,204,125, 1, 82, 99, 70,241, 95,139, 22, 83,173,
+ 37,181,115,182,167,188,183, 37,129, 6,159,182,219, 79, 95,118,221,177,236,232, 45,208,224,166,152,212, 39, 19, 54, 68, 95,130,
+ 92,184,146,164, 69, 83,145,233,254, 40, 83,113,195,107, 72,113,182, 68,151, 7,140,251,152,109,170, 91,157,184,213,165,133, 85,
+ 47,171,178,127, 33,230, 75,114,171,213, 23, 35,250,156,199, 84,159, 15,147, 25,200, 41,229,229,200, 61, 52,228,156, 45, 83, 33,
+ 46,213, 9, 12,109,184,184, 98,214, 61, 46, 54,177,183, 93,246,239,141,118,204, 17,118,208, 89,135, 93,192, 23,247,125,248,187,
+241, 61,191, 16,171, 20,120, 91, 43,100, 59, 38, 45, 50,223,155,227,110,163,143,165,182,103,212,183, 14, 41,104,204,160,206,247,
+ 98, 91,122,157, 79, 90, 99, 41,149, 50,183, 97,190,216,132,184, 46, 57, 2, 52, 39,156,210, 5, 41, 40, 66,220, 89, 66, 27,109,
+ 42, 90,220, 95,192,219,105, 72,202,150,226,212,112,218, 7, 82, 73, 32, 0, 59,247,214,204, 79,218,105, 60, 77, 67,171,238, 54,
+206,186,245, 31,112, 40,173, 83,169, 53,218, 12, 24,116,183,153,221, 11,113,130,220, 51,122, 91, 76, 85, 22,150, 26, 76, 26,164,
+146,195, 50, 28, 10, 83,241,203,235,111,199,134,228, 45,102,150, 23,179, 43,113,174,103,163, 78,220,186,172, 10, 83, 3,192,117,
+104,185,234,127,195, 25,237, 41, 32,164,174, 53,175, 72, 83, 84,104,143,114, 21,146,164,150,212, 20,190,185,198, 4,179, 46,173,
+203, 50,156,190, 58,121,100, 74, 87,131,103, 86, 97,169,159, 98, 92, 0, 11,184,125,138,176, 91,105, 32,109,107, 6,154,136,106,
+106,106, 25,213, 76,161,250, 16, 54, 3,176, 36,216, 2, 58, 17,126,183, 62,252, 48, 60, 43,109,125, 79,127,119,214,218,118,158,
+185, 44,218, 22,100,195, 85, 21,152, 78,173,176, 24,129, 33,164,215, 46, 72, 51, 89, 87,232,220,113,192,221, 34,148,242, 50,174,
+121,115,101, 55,205, 29,104,115, 82, 78,211, 25,177, 59, 3,102,236, 21,187, 50,139,108,185, 46,165, 62,173, 33,153, 53,170,245,
+ 73, 17,145, 54,114,162,180, 89,135, 17,150,162,180,148, 67,165,176,133, 61,224,176, 57,202, 21, 37,197, 41,197,149,100, 62,122,
+131,113, 6,106,185,165, 96,104,175,236,208, 11, 33, 34,197,137,182,166, 35,168,189,128, 0,244, 85, 23,220,156, 61, 80,210,154,
+104,136,127,239, 28,220,251,189, 7,243, 39,212,156, 45, 45, 45, 45, 48,227,119, 11, 95, 8, 4, 16, 70, 65,232, 65,215,221, 45,
+ 12, 12, 83, 67, 45, 53,146,219,104, 65, 61,202, 82, 1, 63,128,213, 77, 45, 45, 12, 12, 51,123,215,177,246, 78,250, 90,142,219,
+ 55,132, 15, 17, 77,169, 82, 41, 53, 88,229, 45, 85, 40,211,185, 57, 19, 46,159, 36,164,248,107,198, 2,208,160,166,221, 72,229,
+113, 10, 24,199, 21, 55, 95,128,189,229,176,101,201,126,218,136,213,251, 65, 75,139, 49,164, 82,249, 99, 86, 27,103, 36,161, 50,
+233, 82, 22, 57,221, 9,192,203, 14, 59,205,140,242,163, 60,162, 65,250,242,180, 33,192, 82,180,165, 96,247, 10, 0,143,219,170,
+147,196,127, 5, 56, 23,196,226,149, 89,229, 28,148,121,204, 74, 17, 43,169, 25, 98,168,208, 62,202, 73,169, 94, 41,209,127, 84,
+ 75, 27, 50, 11,136,217, 1, 55,183,188, 54,241,191,143, 60, 47, 87,165,200,171, 99,172,201,165,114,239, 65, 86,173, 45, 54,179,
+246,158, 61, 46,146,192,237,250,198, 41, 21, 92,216,200,174, 64,180, 88,213,177,251,198,219,222, 2,182,186,252, 11, 10,228,255,
+ 0,246, 90,178, 91,207,151,233,189,211,147, 31, 62,108,117,239,167,207,108,248, 36,222, 91,238,100,115, 87,165,127, 3,105, 10,
+113, 62, 60,170,176,241,106, 37,172,142,111,119,166, 48,172,135, 49,156,120,203,100, 12,103,174, 48,100, 58,105,148,245, 30, 99,
+ 13,130,123,231,195, 26, 33,168,236, 50, 48,211, 77,182, 63,217, 72, 31,208, 53, 83,100,223, 67,239, 15,232,107, 82,167, 52,206,
+115, 28,238,154, 50, 15,179,179, 69, 4,111, 99,246,100,120, 99, 18,149, 61,249,111, 17,244, 97,139,115, 58,250, 99,248,133, 95,
+ 67, 37, 46, 85,146,229,217, 29, 76,128,143,104, 85,150,162, 68,184,251, 81,164,210, 24,131, 14,220,200,229, 95,240,156,107,150,
+193,112,227,103,236,125, 9,184, 52,136,161,218,131,220,143, 84,106,146,130, 29,168, 84,101, 37, 56, 15, 74,120, 32, 14, 80, 10,
+130, 27, 64, 13,182, 9, 8, 72,201, 39,100,244,180,181,212,185, 94, 87,151,100,153,125, 38, 85,148,209, 71,151,101,180, 40, 35,
+134, 24,148, 36,113,160,232, 21, 70,221,110, 73,234,204, 75, 49, 36,147,142, 85,205,115, 92,203, 59,204,106,243,108,222,182, 76,
+199, 50,175,115, 36,211,204,197,228,145,207, 82,204,119,233, 96, 7, 69, 80, 21, 64, 0, 0,180,180,180,181,191,134,252, 45, 45,
+ 45, 45, 12, 12, 45, 45, 45, 45, 12, 12, 45, 45, 45, 45, 12, 12, 45, 45, 45, 45, 12, 12,104, 15, 16,151, 95, 24, 54,239, 17,123,
+ 83,103,109, 12, 84,212, 54, 75,118, 69,182, 47, 27,216,219,148, 90,131,187, 24,189,180,184,101, 92,219,132, 23, 42, 76, 82, 37,
+139,234,202,151, 77,160,210,125,241,138,135,213,181, 58,116,137,140,248, 9, 90, 64,231,117, 43,136,239,106,117,199, 89,185,105,
+117, 10, 52,219, 42, 68,189,220,218,235, 50,177, 79,135,177,151,213,106,118,216, 64,186,248,146,182,109, 10,197, 94,196,168,220,
+ 27, 33, 79,182,247, 3,109, 33,236,132,171,166,163, 88,171, 53,117,221,106,132,229, 62, 29, 72,212, 41,241, 36, 73,106, 28,131,
+ 84,132, 47, 28,201, 10,199,108,140,227, 84, 76, 88,197, 69, 69,150,202,143,115,203,215,203,250,134,165, 20, 60, 69, 77, 73, 4,
+113, 75,195,212, 85,111, 18,196, 57,143, 18,150,102,142, 70, 98,238, 24, 50,182,184,244, 70,234, 2,130, 99, 89, 13,218, 73,249,
+209, 44,195,134, 42,235,106, 36,154, 46, 37,175,163,142, 87,148,152,210,102, 8,171, 36,106,161, 35, 42,200,203,203,148, 73, 42,
+ 49, 44, 87,154,209,139, 36,116,252,158, 18,111, 54,228,113,174,250,120,178,217,207,122,222, 77,206,102,216,218,235, 50,169,182,
+183,141, 11, 96,170,118,165,187, 86,174, 81, 46, 93,174,102,187,109,151, 87,181,116,241,125,223,117,200,235,187,229, 59, 34,206,
+174, 87,232,109, 83,149, 52, 24,150,188,232,144,226,189,121,221,222, 37,189,160,182,229,237,191,208,108, 59, 58,250,169,203,183,
+173,190, 38,157,179,108,216,155, 3, 85,170, 88,180,107, 78,206,216,154,213,197,195,166,226,216,251,164,154, 35,177,247, 99,117,
+ 46, 45,225,139,109,211,166, 90,113,234, 19,223, 67, 85,233,113, 87,111, 66, 52,228,205,149,220, 51, 22, 58,149,204, 89, 65, 80,
+ 24, 4,167,168, 30,131,211, 95, 12, 72,196,133, 22, 91, 42, 29, 1,229, 25, 3,211, 75,197,197, 20,136,176,163,240,229, 36,235,
+ 18,176, 33,145, 44,210, 60, 84,241,180,133, 86, 48,170, 73,131,152, 2, 42,144,206,124,197, 76,130, 93,105,120, 70,177,218,103,
+143,138, 43, 96,121, 93, 72, 43, 36,132,172,105, 45, 76,169, 24,102,149,157,128, 21, 28,178,100,103, 82,136, 60,129,132, 70, 29,
+ 28,224,214,249,226, 54,181, 83,222,219, 55,136, 39, 43, 85,241,100, 94,246,107, 27,119,127, 86,246,245,141,190,145,120, 91, 23,
+102,204,109,181,247, 91,109,168,212,184, 17,169,213,150, 40,215,245,201,118,208,253,234, 19, 64,161,116, 5, 67,154,165,207,141,
+ 37, 70, 41, 62,217,106,175, 29, 60,104,113, 79, 93,164, 80,248, 84,226,128,108,102,199,212,235,214, 38,211,193,135,178, 27,169,
+ 46,147,113, 46, 44,255, 0,115,185,183, 61, 15,199,182, 20,196,245, 87, 38,211,216, 92, 23,154, 60,130,143, 6,156,148,254,148,
+200,113,217,206, 33,150,155, 57, 67,105, 73,237,144, 49,211,211, 67,187, 77,128,242,138,221,136,195,139, 61,212,180, 5, 19,247,
+157,111,240,175, 28,175, 11,103,243,113, 12, 25, 5, 53, 85, 91, 66,177, 70,164,152,227,133,180, 34, 75, 44,105, 26,133, 87,155,
+ 75, 19,164, 5, 65, 35,170, 0,166,216,110,227, 15, 15,159,139,248,110, 14, 25,168,226, 74,186, 58, 36,153,165,149,192, 89,101,
+157, 4,143, 36, 48,202,242,146,204,144,234, 80, 53, 18,206, 99,141,156,150, 92,126,116,252, 63,207,246,190,240,179,111, 84, 45,
+109,128,218, 78, 44,118,210,133, 86,172, 61, 95,169,195,163,240,195,113, 77,114,125, 93,248,145, 32,174,108,185,213,189,175,149,
+ 33,245,136,112, 98,182,132,169,210,134,210,214, 16,148,229, 89,216, 95,229,123,244,129, 63,242,126, 52, 63,251,173,204,255, 0,
+254, 61,169,231,253, 81, 76,255, 0,200, 99,127,246, 73,254,173, 47,170, 41,159,249, 12,111,254,201, 63,213,169,173, 79,140,244,
+149,147,203, 85, 89,225,206, 77, 85, 85, 49,212,242, 73, 10,188,142,118,221,157,162, 44,199,110,164,147,211,211, 16, 58, 95, 2,
+107,104,105,226,164,162,241, 71, 60,163,164,128,105, 72,162,157,227,141, 23,246, 81, 18, 80,170, 58,236, 0, 27,226, 37,155,115,
+253,212,126, 49,125,153,188,113,237,174,247,198,222,153, 59,193, 46,175, 96, 72,219,250, 22,228,109,202,182,202,225,187,172,138,
+ 21, 82,137,114,222,246,157,180,203,246,205, 29, 85, 20,205,129, 74,154,216, 8, 67,198, 83,220,180,197, 40, 34, 90,211,174,108,
+123, 29, 56, 93,226,149, 28,122,109, 85,237, 78,219,189,198,219,219,123,106,234,245,201,187,145,114,220,214,181,114,217,129, 10,
+149, 34,223,173, 81,102, 90, 18, 69,110, 36,113, 58,173, 81,126, 98, 97,251,154, 2,223,101, 46, 57, 49, 77,165, 17, 22,226, 63,
+ 64, 22, 96,195,143,159, 6, 51, 45,115, 12, 43,145, 0,100,124,245, 69,170, 85, 61,151,140,134,162, 50,135,137, 36,184,148, 36,
+ 40,147,243,198,154,161,241,114,174,151, 42,226,204,162,135,135, 40,168,169, 56,157,157,130, 68,186, 35,166,230,211, 71, 75, 40,
+ 72,213, 66, 72,165, 35, 14,129,130,132,145,152,182,181, 58,112,239, 63,130,212, 85,153,191, 6,103, 85,252, 79, 95, 95, 91,194,
+ 43, 26,151,149,181,201, 87,201,170,146,174, 18,242,179, 23,141,131,202, 81,202,150, 47, 18,162,175, 45,134,178, 91, 28,254, 11,
+ 94, 39,235,248,104,231,255, 0,249,185, 70,127,110,177,109,192,143, 34, 93,135,122,196,136,195,210,165, 74,180,238, 40,241,163,
+ 71,105,111, 72,145, 33,234, 68,198,217, 97,134, 91, 73, 83,175, 45,197, 37, 41, 74, 65, 82,148,160, 0, 36,235, 46,210, 35, 32,
+131,216,244, 58,169, 35,115, 27,163,129,114,132, 31,220,111,139,166, 68, 18, 35,161, 54, 14, 8,253,226,216,132, 15,176,167,134,
+142, 35,182,159,142,131,114,110,159, 15,251,217,182,150,232,218, 43,214,152,107,251,129,181, 87,213,153, 69,250,202, 85,110,207,
+118, 45, 59,235, 91,142,131, 25,143,127,113,168,178, 84,219, 62, 39,136,180,199,112,165, 36, 33, 68,117, 47,219,205,195, 55, 28,
+251,238, 54, 30,243,225,142, 29, 70,225,177,182, 89, 85,139,166,109,187, 96,220, 82, 40,155,167, 77,220,121,146, 24,110, 13,239,
+ 72,138,151, 99, 46,172,220, 26, 44, 70, 24,129,245,108,167, 42,145,159,169,206, 83,113, 11, 78,151, 83, 34,132,192,132,135, 60,
+100,198,101, 46,147,146,224, 64, 11,207,219,162, 84,132,172, 20,173, 41, 82, 79,112,160, 8, 63,113,213,149,152,120,159,153, 87,
+113,173, 39, 27,140,170,149, 43,105, 34, 16,136, 36, 15, 44, 37,116, 73, 27, 19,114,172, 24,164,140, 1, 7,202,108,119,232,106,
+156,179,194, 76,171, 47,224, 42,222, 1,108,226,174, 74, 26,217,140,230,162, 50,144,206,175,174, 41, 20, 11, 43,161, 85,120,148,
+144, 65,212, 46, 54,216,136, 25,208, 61,170, 30,218,237,168,164, 39,110,107,112,119, 42,161, 86,167,180,154,124, 73,123,145,195,
+123,147,175,152, 73, 79, 52,102, 82,236,185, 86,131, 14,213,229, 7, 80,172, 61, 80,106, 99,238,173, 39,196,113,206,163, 77,149,
+151,192,119,180,211,218, 97,189, 44,110, 46,255, 0, 64,220,170, 74,107, 38, 36, 90,246,237,239,133, 26, 85,175, 26,139,111, 48,
+234,221,106,157,101, 88, 47,198,128,235,144, 71,143, 49,200,112, 41, 20,248,116,144,252,135, 28,117,248,190, 58,222, 95,232, 6,
+237, 2,142,250,185,220,129, 29, 74,245,240,211,253, 90, 50, 61, 62, 20, 79,251,222, 43, 45, 99,205, 8, 0,254, 56,212,132,120,
+202,153,122,212, 79,195, 92, 13,149,240,246,109, 84,165, 90,170, 40,213,156,106,234, 81, 86, 56,128,223,205,165,153,208,176, 5,
+209,237, 99, 26, 62, 5,190,100,244,176,113, 87,136, 57,191, 19,100,212,110,174,148,114,202,202,135, 79, 64,238,210,202, 78,215,
+ 82,200,169, 32, 82, 66, 58, 94,248,215,190, 20,248,114,178,184, 89,217, 43, 15,102, 44, 56, 70, 37,191,100,208,163,210,163, 45,
+222, 85, 76,168, 74, 82,220,153, 87,173, 84,156, 72, 1,218,172,250,188,153,211, 37, 41, 41, 74, 21, 34,123,133,180, 33, 28,168,
+ 78,200,105,105,106,151,168,168,158,174,121,234,170,101,105,234, 42, 93,164,145,216,221,157,220,150,102, 98,119, 44,204, 73, 39,
+185, 56,189,233,169,169,232,233,169,232,233, 97, 90,122, 90, 84, 88,227,141, 5,149, 35, 69, 10,136,160,108, 21, 84, 0, 7, 96,
+ 48,180,180,180,180,142, 23,194,210,210,210,208,192,194,210,210,210,208,192,194,210,210,210,208,192,194,210,210,210,208,192,194,
+210,210,210,208,192,194,210,210,210,208,192,194,210,210,210,208,192,194,214, 53,117,217,246,213,239, 67,171,219,183, 69, 34, 21,
+ 94,149, 91,165, 79,163, 84, 24,146,195,107,113,112, 42,113, 93,135, 45,182, 95, 41,231,142,178,203,206,114,173, 5, 42, 66,136,
+ 82, 72, 80, 7, 89, 46,150,178, 24,169, 5, 77,136,238, 48, 8, 7, 98, 46, 49,196,171,235,133,221,241,219,202,252,170, 5, 5,
+186,133,255, 0,110, 54,227,142, 91,183, 24,180, 43, 87, 5, 89,218, 66,156, 34, 28, 91,130,109, 22,174,210, 93,171,176,128, 27,
+113,199, 24,105,215,249, 3,170, 47, 40,169,247, 49, 56,124, 52,111,189,235, 81,137, 67,173, 91, 85,184,244, 57,175, 52,212,250,
+127,240, 58,177,105,211,231, 52,181, 0, 89,174,220, 21,122,163,202, 77, 11,186,164,199, 97, 13, 46, 66, 17,224,173,197,178,183,
+ 24,123,188, 58, 90,146,167, 20, 85,172, 74,141, 2, 59,168,182,162, 91,115,107, 92,168, 54,223,184,232,119,216, 13,176,222,114,
+248,203, 92, 57, 11,126,155,126, 7,249,225,157,217,141,156,160,236,245,178,138, 85, 60, 53, 50,183, 53, 12, 57, 94,173,134, 82,
+202,230,190,210, 57, 90,139, 21,176, 63,193,105, 44, 36,169, 17,217, 29, 0, 37,106,202,214,163,167,139, 75, 75, 81,233,166,150,
+162, 87,154,103, 50, 73, 33,185, 39,231, 96, 58, 0, 54, 3, 97,182, 55,149, 85, 20, 42,139, 42,244,194,210,210,210,210, 88, 54,
+ 22,150,150,150,134, 6, 32,111,253,251,111,253, 25,127,246,206,255, 0,117, 13, 84, 31, 77,167, 61,189,153,157,251,127,142,111,
+251,168,234, 6,201, 25, 61, 71, 79,216,116, 66, 7, 92,227,160,237,253, 29,191, 61,180,202,213,149, 2,195, 94,231,220,191,150,
+ 52,249,178,126,215,224, 63, 44, 79, 25, 63, 77,151, 39,255, 0, 6,119,218,127,150,103,111,251, 41,107,223,247,236, 95,244,103,
+255, 0,219, 47,253,212,245, 4, 4, 2, 7, 95, 63, 47,223,170,169, 25, 61,186,122,250, 31, 81,243,210,126,219, 83,255, 0, 19,
+240, 95,203, 24,230,201,127,181,183,192, 98,119,163,233,176,103, 24,246,104, 30,163,167,248,229,121,231, 24,255, 0, 53, 62,250,
+168, 62,154,225, 35,175,179, 71, 31, 47,229,149,254,234,154,130, 42, 65,207, 67,215,212,255, 0, 96,209, 9,238, 1, 57,207, 66,
+113,249,198,136,213,245, 67, 97, 37,143,253, 43,249, 99, 60,217, 45,187,126, 3,242,196,238, 7,211, 87,201,199,247, 52,251,255,
+ 0,207, 39,240,255, 0,146,174,190,171,233,171,114,130,127,185,167,159,151,242,200,255, 0,117, 93, 65, 69, 9,235,159,151, 79,
+207,231,190,171, 4,115, 15,151,207,215,229,233,211, 26, 76,230, 21,118, 63, 93,254, 85,254,156, 37,237, 18,245,215,248, 15,203,
+ 19,165, 79,211, 89, 73, 4,159,102,170, 83,233,158, 50,135,207,254,106,191, 45, 18,215,211, 80,241, 19,205,253,205, 94, 80,123,
+127,142, 62,115,255, 0,101,109, 65, 56, 67,100,168, 18,128,163,223,185,239,242, 25,237,223, 87, 54,211,203,202, 0, 0,118, 29,
+ 49,229,158,131,238,210,103, 49,173, 22,250,254,191,225, 79,233,198, 13, 68,189,155,240, 31,150, 39, 74,159,166,146, 79,127,102,
+191, 47,111,249, 99,122,255, 0,213, 99, 85, 71,211, 69,207,250, 54, 71, 94,199,249, 98,244,199,175,249,172,106, 11,137, 0,145,
+159, 63, 79,199,240,209, 41, 7,203, 0,118, 57,237,143, 77, 96,230, 85,191,241,191,202,159,211,140,123, 76,223,183,248, 15,203,
+ 19,158,254,253, 11,254,141,175,251, 98,127,186,206,189,143,166,127,144, 15,247, 54,241,159,249,225,255, 0,186,214,160,208,144,
+ 8,234,123,244,199,237,253,218, 36, 39, 29,124,250,119, 29,189,116,145,205, 43,199,251,255, 0,242, 39,187,252, 56,199,180,205,
+109,218,196,123,135,229,137,201,143,166,116, 79,250, 55, 15,111,252,240,187,127,217,107, 94,199,211, 56, 39,191,179,119, 29, 51,
+254,120, 95,111,127,241, 91,233,219, 80,111, 66,135,111, 60,254, 7, 24,209, 8,238,125, 72,239,223, 31,119,231,182,138,115, 90,
+253,254,190,214,255, 0, 10,127, 78, 11,237, 51,116, 50, 88,250,233, 31,150, 39, 26, 62,153,166,112, 71,179,131, 57,237,142, 48,
+ 63,221,115, 94,135,211, 49, 57, 0,251, 55,241,156,227,252,112, 51,219,254,171,154,131,194, 82, 70, 48, 64,232, 51,143, 33,242,
+252, 52, 66, 49,158,191, 96,244,255, 0,142,136,115,108,195,114, 42, 46, 7,248, 19,250, 48, 95,107,159,246,255, 0, 5,252,177,
+ 56, 65,244,203, 15,159,179,135, 31,245,191,207,255, 0,149,221,122,254,252,175,166,127,185,197,246,143,229,127,219,211,254, 75,
+218,132, 10,112, 10,114,160, 9, 29, 7,168, 61,127,167, 94,243,144, 72,238,122,100,244,207,207, 69,253, 47,152,255, 0,204,127,
+146, 63,233,198, 13, 93, 64,255, 0,121,248, 47,229,137,189,127,126, 89,255, 0, 71, 16,255, 0,239,127,229,235,254,107,186, 95,
+223,150,127,209,197,255, 0,107,255, 0,247, 93,212, 32,130, 70, 78, 83,156,121,142,227,167, 97,235,175,129, 39, 36, 96,158,227,
+228, 15,174,116, 63, 75,230, 63,243, 31,228, 79,233,198, 61,174,163,175, 50,254,235, 47,229,137,191,255, 0,126, 86,112, 79,247,
+ 56,187, 99, 63,227,127,235,216,255, 0,154,238,144,250,101,100,228, 15,103, 9,200, 56,255, 0, 59,241,143,159, 95,228,189,168,
+ 65, 28, 19,201,158,160, 12,125,189, 71, 93,124,228, 56, 61, 58,142,199,215,215, 67,244,190, 96,127,246,143,242, 39,244,227, 34,
+170,163,188,157, 61,195,242,196,224, 26,250,101, 42,117,105, 66,125,155,238,173, 74, 90, 16,134,216,226,229,114, 31,117,110, 45,
+ 45,180,204,120,237,112,184, 87, 34, 67,142,173, 8,109,180, 2,183, 28,113, 40, 64, 42, 80, 26,145,125,139,237, 28,187,106,123,
+107, 97, 92,219,161,195,163, 59, 99,184,215, 61,173, 2,228,186,182,189,141,220, 55,106,172, 25, 85, 68,137, 81,173,154,141,204,
+118,206,154,106, 53,248,244,231,225,154,131,105,167, 50,136,178,214,252, 70,220,146, 35,151,215,249,251,123, 18,120, 79,167,111,
+111, 18,114,247,186,251,163, 49, 85,218,222, 24,163,210,111, 53,194,156,128,245, 62,228,222, 74,163,175, 29,169,183,157, 96,172,
+ 9,108, 83,222,131, 80,184,101, 52,174,132,209, 41,225, 89, 75,196, 25,105, 85,110, 39,101, 73,126,161, 41,197,174, 75,239,169,
+114,139,171,241, 63,239,176,162,251,170, 86,121,157, 65, 89,113, 67, 7, 35,169, 4, 18,115, 82,113,247,137,217,238, 79, 87, 22,
+ 91,147,230, 34, 26,136,198,185,156, 69, 79, 33, 23,221, 80, 44,145, 56, 6,222, 98,116,157,153,122,110, 71, 99,125, 27, 60, 13,
+161,241, 3, 47,175,226,174, 50,162,122,236,146, 71, 48, 81, 64, 36,150, 14,107, 70,214,150,114,244,239, 20,133,117,222, 36, 93,
+ 65,110,172, 77,203, 45,186,186,215,180, 61,151,139, 72, 78,210, 40, 56,230, 50,147,125, 47,149, 37, 77,151, 65,231,254, 5, 97,
+ 72, 9,229,201,242,231, 29, 51,240,235, 38,139,199, 80,146,160,145,181,193, 5,104, 75,168,255, 0,223,202, 78, 90, 39,195, 82,
+214, 13,164, 11,120,116,164, 96,142,161, 65, 94,120,215, 37, 97,212,227,199,149, 78, 9,151, 17,105,146, 42, 43,109,228,184,158,
+ 66,150,152, 96,162, 49, 81, 60,133,229, 15, 16,124, 93, 73, 25,192,198,117,127,135,119,198,133, 85,181,154, 92,152,232, 50, 28,
+186,224, 45, 77,133,168,134,145, 77,106,160,134,156, 25,228,241,210,136, 43, 91,107, 60,205,168,199, 90, 80, 50,188, 26,248,120,
+191,199, 91,223, 62,222,224, 91,217,168,122, 27,111,255, 0,163,123,205,183,183,173,183,183, 70,215,125, 26,252, 47,211,253,139,
+131,216, 17, 28,143,189,110,104,215, 17,164,174,118, 53,123,111, 17, 95, 80, 78,224,219, 29,102,143,198,144,125,124,131,109, 74,
+ 72, 74, 85,145,120,165,105,198, 84,135, 7, 50,109,142,133, 46,164,167, 31,102,112, 78, 53,145,195,226,200, 74,117, 13, 42,195,
+ 67, 36,164, 41,197, 27,185, 11, 13, 21, 41, 73,194,147,252, 30, 10, 94, 8, 28,197, 41, 32, 5,103, 39,166,121,115, 2,240,167,
+ 70, 20, 80,180,187,134,229,185, 73,145, 29,134,150,242,101, 73,157, 30, 64, 97,134,152, 42,230,117,245, 61, 19,152,140,164, 39,
+ 42, 42, 1, 32,105,211,165, 85, 16,235,177,228, 37,200,205, 55, 48,170, 47,130,211,169,144,168,175,186,194,157, 76, 57, 13,129,
+240,203, 11,104,243,140, 39,147,168, 74, 84, 64,202,195,197,222, 56, 99,182,126, 45,113,183,178,209,131, 98, 7, 66,105,253,247,
+233,115,110,128, 3,138,247, 55,240, 35,129, 40,195, 21,225,118,129, 72,107, 19, 85, 94,119, 82,194,219,213, 27,146,171,175, 96,
+ 71,152,124, 11,113,237, 58,246,213,110,191,179,158,220,176, 55, 74, 7, 3, 3,126,182, 34,238,121,155,106,229,220,202, 87, 17,
+ 78, 89, 19,118,199,113,165,190,239,212,246,205,239,105,183,176,245,193, 6,220,171, 67, 74, 62,167,174,138,129,141, 46,106, 28,
+166,201,143, 6, 89,138,153,124,121, 63, 76,188,131,211,217,192, 8,233,212,113,129,228,124,255, 0,205,115,211, 93,240,187,108,
+ 11, 23,121, 44, 27,215,104,183, 62,212,167,238, 22,218,110, 61,183, 91,177,239,203, 66,160,208, 85, 46,224,160, 85, 98, 2,253,
+ 61,213,161,121,131, 48, 56,162,244, 73, 72, 34, 68, 57,212,248,242,227, 45,183,153,109, 73,252,231,120,230,246,106,239,183, 6,
+ 60, 82, 94,220, 62, 83,108,205,193,221, 91, 81,182, 13,241,179, 87,213,187,104,220, 55, 36,155,231,104,106,242,164, 10, 21, 78,
+166,154, 13, 41,239, 10,232,165,186,219,212,154,235,124,169,228,168,210, 87, 32, 1, 30,100,114,171, 79,131, 60, 72,204,115,136,
+ 37,165,205, 43, 2, 87, 83,141, 66, 67, 28, 72,146,161, 61,172,129, 53,165,192,178,216, 50, 16, 84, 54,151,115,201,126, 41,240,
+ 67,240,133, 90, 87,229,108, 70, 77, 84,193, 66, 19,169,160,115,246, 86,238, 90, 66,143,111, 41,114, 72,109,181, 29, 64, 44,156,
+255, 0,191, 47,234, 71,247, 56, 71, 65,159,243,192,245,237,255, 0, 37,221,124,254,252,192,255, 0,251,184, 58,127,233,129,251,
+191,146,230,161, 89, 94,176, 47,187, 81,114, 17,117,216,247,149,174, 99,171,195,147,252, 35,181,171,244, 20,198,115,152,128,219,
+235,171,211, 88, 13, 56, 84, 8, 9, 81, 4,144, 64, 7, 88,123, 74, 75,159, 19, 69, 14,164, 21, 0,180, 45, 46, 36, 20,146, 20,
+ 9,109, 68, 2, 15,124,246,212,249, 51,218,185, 55,142,181, 92,123,132,103,248, 46, 42, 15,110,150,246, 51, 0,111,208,133,191,
+238,181,241, 56, 81,244,203,137,239,236,225,192, 29,201,226,255, 0,215,254,171,186,248,126,153,120, 29, 15,179,135,175,203,139,
+254,159,143,242, 93,212, 32, 71,158, 48, 9,235,223,204,253,191,118,188,167, 39,161,193,199, 83,242, 36,159,221,165,127, 75,230,
+ 63,243, 31,228, 79,233,193,189,170,162,223,222,111,255, 0, 72,252,177, 56, 1,244,203,201, 56, 30,206, 14,191,250, 95,255, 0,
+186,238,190, 43,233,152, 4,128,127,185,195,159, 80, 56,191,234, 62,223,241, 93,212, 32,142,124,128,239,248,116,243,251,245,224,
+ 2, 84,115,211, 3,186,122,117, 63,111,200,157, 15,210,249,143,252,199,249, 19,250,113,159,106,159,254, 39,224, 63, 44, 78, 11,
+251,242,241,128,127,185,197,247,127, 43,254,191,183,133,221, 47,239,203,198, 79,253,206, 35,129,231,252,175,186,125,255, 0,226,
+187,211, 80,130, 66, 58,149, 12,115,116, 4,159, 63,159,111,206, 53,240,167,226,206, 58,142,135, 29,189, 58,232,126,151,204,127,
+230, 63,200,159,211,129,237,117, 31,183,248, 47,229,137,190, 15,166, 96, 9, 35,251,156, 36, 99,204,241,125,223,236,255, 0, 21,
+237,123, 31, 76,184, 28,127,220,226,239,156,127,141,247,167,127,249, 47,106, 16, 24,207,151,108,247,244,199, 92,126,124,181,244,
+117,192,232, 61, 63,183,166,135,233,124,199,254, 99,252,145,255, 0, 78, 49,237, 85, 23, 31, 89,248, 47,229,137,191,143,166, 88,
+ 79,250, 56,122,245,233,252,175,255, 0,163,252, 87,122,235,233,250,101,100,119,246,112,227, 63,243,191,235,248,127, 37,221, 66,
+ 19, 3,190, 50, 71, 94,159,213,159,150,190,247, 32,249,119,193, 25,253,190, 93,244, 63, 75,230, 63,243, 31,228,143,250,112, 61,
+170,163,254, 39,224,191,150, 38,238,126,153,113, 31,232,224, 56,245,254, 87,248,253,159,201,119,166,169, 43,233,153, 17,254,141,
+252,140,227, 63,203, 3, 30, 93,255, 0,205,115, 80,137, 32,156,156, 0, 51,142,224,117,245, 61,123,245,213, 5, 32, 17,128, 51,
+158,253,127, 63,145,172,254,151,204, 44,127,180,111,255, 0, 68,127,211,140,251, 84,255, 0,183,248, 15,203, 19,121, 63, 76,212,
+130,113,236,221, 39, 7, 31,231,129,248,255, 0,201,111, 95, 15,211, 55, 35,183,179,120, 30,153,255, 0, 60, 47,217,254,107,125,
+245, 7,245,128, 51,129,133,119,198, 14, 62,255, 0, 77, 10,172,140,244, 29,122,244,245, 31,111,111,237,209,151, 54,175,239, 83,
+123,255, 0,129, 63,167, 25,246,169,251,191,224, 63, 44, 78, 33, 95, 76,228,167,253, 27,185, 30,191,203, 11,253,214,245, 72,253,
+ 51,220, 28,127,115,115, 63,245,194,255, 0,117,175, 77, 65,216,247,233,128,113,149, 30,227, 30,127,111,150,188, 16,112,114, 0,
+207, 92, 14,248,249,244,232, 59,232,227, 53,175, 32, 30,127, 95,240,167,244,224,235, 81, 49, 23, 50,126, 3,242,196,226, 85,244,
+208, 57,127,209,181,145,235,252,176,255, 0,221,103, 84,207,211, 67, 35,253, 27, 63,135, 24,191,238,177,168, 57, 45, 35, 56,193,
+193, 29,252,191, 31, 95,234,208,235, 73, 57,230, 30,125,255, 0,163, 74, 46,103, 90,127,223,127,149, 63,167, 0,212,205,183,155,
+175,184,126, 88,156,137,250,105, 24,200,254,230,199,108, 99,252,113,123,255, 0,217, 99, 84,213,244,210,249,127,209,175,159,250,
+227,126,239,228,175,168, 52, 41, 61, 72, 62, 89,255, 0,142,168, 41, 56, 62,164,103, 31,126, 58,232,227, 50,173,255, 0,141,127,
+251, 83,250,113,145, 81, 41,232,255, 0,128,252,177, 57,179,244,211,113,219,217,173,147,233,252,177,255, 0,221, 95, 94, 15,211,
+ 80,198,127,238,106,246,242,254, 88,253,127,254,213,181, 6, 5,142,164,147,229,220,116,200,251, 71, 97,211, 84,150, 6, 51,159,
+179,211,246,104,227, 48,172,218,243, 94,253,244,175,244,227, 62,209, 55,237,254, 3,242,196,231,207,211, 85, 32,103,251,154,121,
+199,252,242,113,255, 0,229, 87, 84,149,244,214, 72,255, 0, 70,150, 71,254,153, 61,191,236,169,168, 45,169, 56,237,219,247,143,
+ 95,191, 67, 44,117, 35, 3,175, 92,104,195, 48,171,190,242,237,255, 0, 74,254, 88, 56,158, 75,253,187,253,195,221,238,196,233,
+215,244,215,249, 15,254, 13, 12,143, 95,229,149,251,191,146,159,174,168, 31,166,202, 57,185, 71,179, 56,159, 60,255, 0, 44,190,
+159,179,133, 62,250,130,147,205,243,116, 35,207,203,167,159, 76,103,203,250,244, 42,153, 60,221,200, 3,183,150, 62,206,158,154,
+ 88, 86,212,216,125,109,255, 0,237, 95,203, 6,231, 73,183,159,240, 24,157,183,247,236,196,140,143,102,104,199,110,188,102,224,
+231,211, 31,201, 71, 94, 15,211,105,229,239,236,204,199,253,115,191,221, 71, 80, 71, 82, 0,206, 51,208,227,167, 94,222,154, 25,
+105, 72, 7, 35,174,124,242,122,252,243,246,104,235, 89, 57, 27,203,191,192,126, 88,199, 58, 77,183,189,253,195, 19,188,254,253,
+183,254,140,191,251,103,127,186,134,150,160,120, 80, 60,142, 63,111,239,210,209,253,170,163,254, 39,224,191,150, 13,205,147,246,
+191, 1,249, 99,234, 65, 0, 3,249,235,162,146, 15, 64,123,244, 31,156,106,138, 70, 79,203,207,243,246,232,132, 12,159,179,175,
+223,157,105, 22,185,191, 75,116,194,120,174, 1, 61,189,113,249,249,106,176, 0, 96,121,121,254,253, 83, 70,122,244,200, 36, 12,
+231,183,231, 58,174,144, 14,115,158,131, 61, 52, 76, 12,123, 74, 74, 73,234, 49,249,252, 52, 66, 7, 76,250,254,204,106,130, 50,
+ 71, 92,224,158,153,235,223,231,231,253,154, 41,180,246, 7,203,169,252,253,186, 65,141,205,241,131,176,191,166, 43,163, 29,135,
+197,143, 79,159,217,162,144,140,142,131, 3,207,237,253,231, 84, 17,208,244, 3,175,125, 20,140,253,223,191, 68, 98, 69,192,194,
+ 36, 91,248,227,210, 7, 98, 79, 83,230,122,244,253,253,180, 72,193, 3,207,211,167,159,110,218,164,145,147,246,117,209, 9,237,
+140,128, 1,200,251, 71,223,219, 73, 49,185,233,108, 99, 21, 18, 0,193,193,235,223, 61,241,233,162, 83,140, 14,157, 60,134,124,
+191,118,168,164,115, 31,219,247,116,237,162, 80,158,163,167, 65,235,162,147, 97,115,219, 4,244, 23,177,255, 0,199,207,250, 98,
+170, 64,242, 3,229,162, 82, 9,192,249,119,249,252,245,118,183, 45,171,130,238,172, 83,173,203, 86,135, 85,184,238, 26,180,164,
+196,164, 80,104, 52,233,117,122,213, 90, 99,129,106, 68, 58,109, 46,158,203,143,206,146,164,161,100, 33,180, 40,242,182,165, 16,
+ 2, 73,213,222,187, 99, 94,182,156,151, 98, 93, 54,117,215,108, 74, 96,148, 63, 30,227,182,235,180, 39, 90, 90, 78, 20, 28, 77,
+ 82,158,215, 41,230, 7, 90,109, 60, 43, 32,137,165, 81, 43, 11,133, 36,106,181,237,123,117,183,107,224,250, 36,229,180,162, 54,
+ 49, 41,179, 56, 83,164, 27, 94,197,173,164, 27, 88,218,247,182,248,198, 80,144,123,128, 8,207, 65,220,156,249,122,157, 86, 70,
+ 62, 33,143,179,215,239,252, 63,110,188, 32, 18, 50,217, 14, 1,220,161, 73,115,211,185, 65, 56,237,162, 27, 73, 86, 58,128,125,
+ 7,127, 95, 61,101,136,223,126,191,127,195, 26,250,131, 11,131,127,120,239,138,168, 73, 56,233,212, 12, 30,190, 64,234,179,125,
+ 79,108,128, 65, 3,191,221,251, 53,245, 40,236, 58,103,190,122,253,191,187, 85,144,140, 43,169, 3,207,228,114, 15, 95,217,164,
+240, 49, 84, 39, 42,193,232, 59,129,129,148,140,118,207,225,175, 74,108,245, 4,242,143, 47, 81,233,175,160,149,103, 24, 10,245,
+ 30, 99,243,231,175, 67,174, 2,178, 51,230, 48,123,121,159,195,246,235, 24,199,195,174, 40,165, 56,206, 85,212,156,142,157,254,
+204,246,215,148,164, 2, 50,163,223,238,235,242,243, 58,172,224,201, 29,122,122,142,157, 51,140,159,151, 93, 92,168,148, 58,189,
+195, 84,167, 81, 40,116,202,141,102,177, 88,152,213, 58,145, 73,165, 65,153, 85,171, 85,170, 18, 20, 16,196, 10, 77, 42, 3, 46,
+ 72,169,206, 90,136, 8,101,134,214,226,179,209, 58,195, 50,162,150,118, 10,171,185, 39, 96, 48, 91,133, 2,231, 97,181,254, 54,
+183,239,197,153, 93,240, 57, 64, 30,106, 3,174, 51,128, 61, 53,233, 88, 67, 69,215, 84, 27,101, 56,241, 29, 89, 8,105, 40,238,
+165, 21,172,129,140,103, 82, 39,224,247,232,242,113, 5,186, 44,209,175,126, 45,110,120,252, 41,109,245, 65, 45, 76, 98,212,168,
+192,137,115,111,205,126, 34,210,167, 80,219, 22, 95,189, 38, 13,132,167, 80,143,133, 85,151,221,152, 18,178, 69, 47,152, 99, 82,
+ 25,217,126, 4,125,158,220, 32, 70,111,248,177,225,226,214,187,174,202, 84,112,204,221,208,222,132,198,220,171,212,205,121,104,
+ 12, 72,241,238, 54,151, 77,163,211,164, 45, 56,103,220,169,241,154,109, 74,229, 79, 82, 64,134,103, 28,115,148,101,101,145, 24,
+213,204,187, 89, 14,215,247,144, 9,248, 27, 91,212,226,216,224,191, 5,184,251,142, 12,111,150,229, 38,134,142, 80, 8,158,164,
+ 20, 4, 18, 0,100,140,217,216, 94,195,204, 99,185,176, 23, 36, 3,170,254,203, 46, 26, 46, 77,165,224, 39,102,233,180,203, 98,
+123, 55, 94,240,135,247,210,247,144,229, 50, 82, 28,149, 42,249, 17,191,130, 80, 39,169,184,229, 79,197,133, 96,194,183,154,100,
+100, 99,197,117, 73, 37, 43, 81, 86,234, 87,236,203,238,132,204, 33, 46,221,170, 32,138,139, 45, 45,243, 6, 98, 99, 20,165,137,
+143,123,195,179, 60, 34, 27, 65,240,249, 15, 57, 79, 42,214, 17,130, 72, 35, 99,155,223, 42,234,221,136,202,101,194,143, 66,171,
+184,105,112,211, 76, 5,132,211,101,181, 28,123,180,100, 71, 82, 83,238,168, 82, 80,227, 9, 67, 73, 8, 14, 54,132, 97,180, 20,
+130, 37, 39,125, 42,234,171,170,153, 34,124,151,131,206,170, 19, 32, 54, 57,101,207,141,200,137,172, 48, 57,190, 37, 8,222, 27,
+165, 60,170, 39, 42, 9, 10,109, 42, 35,158,243, 89,104,243,106,250,186,249, 38,156,203, 86,236,231,104,202,139,157,149, 87, 85,
+236, 1, 10,190,110,130,198,230,248,244,231,129,168,248,183,129,184,107, 38,225,202, 14, 30,163,155, 47,200,105, 99, 77, 38, 89,
+121,146,114,215, 68,146, 59, 8,236,178, 22, 87,121, 1, 82, 69,181, 95, 73, 7, 26, 81, 90,169, 61, 79,168,208,167,204, 91, 44,
+184,170,148,168, 83, 66, 11,141, 70,124, 78,167, 84, 35, 51, 29,198, 66,130, 11, 8,121,168,165, 36,146,181, 41, 14, 44, 21, 40,
+224, 88,100, 92,178, 84,252, 41, 12, 58,134,169,236,223, 20, 56, 17, 31, 91,158, 31,213,209,106, 45, 85,162,212, 38, 53,239, 67,
+159,220,194,222,100,171, 9, 37, 41,111, 45,133, 37,120,214,238,238, 21,145,110,110,237, 53,104,141, 18,147, 65,187,160,213,226,
+ 84,226, 75, 44, 52,154, 77, 70,163,111,200,247,152,240,235,208,227,114,167,192,113, 14, 20, 25, 44,164, 59, 28,191,226, 56,135,
+145,206,141,115, 74,240, 69, 70,139, 58,226, 93, 94,157, 42,151, 38,217,171,209,163,191, 18, 75, 72, 91,241,167,211,107,148, 86,
+235, 13,120,141,225, 15,143,117,147,200,218,176,158,118,242,164,158, 78,241, 42,202,121,105,230, 69, 46, 37,138, 83,229, 96, 54,
+ 39, 96, 53, 11, 27, 48,191,217, 61,150,247, 32, 99,163,184, 11, 53,202,248,178,154, 72,228,131,244,126,105, 66,170,147,211, 72,
+202,218, 17,229, 26, 94, 18, 8, 15, 27, 23,116, 14,187, 34, 6, 89, 17, 67,170, 54,206, 82,238,185,177,160,198, 76,229,153, 13,
+208,110, 74, 4,198,235, 44, 56,149,128, 69,106, 35, 41,155, 33, 8,201, 46, 37,233,173,153, 1,226, 91, 60,203, 41, 39,176,223,
+221,171,219,215,238, 40,178, 42,213,233, 10,163,209,233,181, 8,142, 38,114, 84,251,110,185, 54, 35,209, 31, 13,197, 91,138, 79,
+143,206,150,212, 57,242,124, 38,229, 16, 84, 73,240,213,204, 75, 50,143, 87,173, 84,164, 89, 20,181,168, 46,225,151, 26,159, 71,
+109, 65, 14,184,229,111,223,226,166, 53, 41,224,179,148, 64,114, 79,132, 90,113, 73,200,104,184,146,174,118,146, 79,101,175,201,
+205,219,204,155,102,128,180, 26,125, 18, 28,150, 98,195,105, 10, 14, 85, 92,139, 49, 44, 74,113, 69,160, 66,149, 34, 98, 36, 58,
+ 20, 83,202,178,235,104, 56, 3, 26,125,225,170,120,167,231,215, 85,141,112,211,105, 68, 66,108, 25,200, 98, 1, 35,204, 2,129,
+118, 32,139,221, 73,211,171, 88,164, 60,112,168,124,170,167, 38,200,178,103, 72, 51, 44,237,231,149,166, 81,253,213, 50, 10, 79,
+172, 10, 67, 42,201, 44,175, 42,128,126,168, 90, 67,176, 82, 27, 44,157,124, 91, 86,163,172,210, 40,209, 33, 66,112,182,149, 48,
+228,143, 4,186,243,202,144,134,136, 71, 50, 71, 59,195,196, 43,253, 81,128,121,143, 54, 9,213, 9,123,191, 49,153,245, 55, 35,
+206,109,168,116,233,113, 41,236,173,165,115,203,126,108,150, 24,126, 66, 34,165,149,164, 32, 41,215,163,182,233, 78, 22,166,155,
+ 90,143, 48,108,145,165, 85, 75,154, 37, 70,161, 46,164,219,243,155,165,183, 95,162, 83, 41,204,184,183, 31,120, 38, 3,190, 45,
+101,232,203,231, 40, 76,115, 83, 50,127, 74, 20,164,143,112, 40,242, 9, 31, 98, 92, 79, 79,129, 78,140,203, 11,121,138,245, 72,
+215,101,185, 49,196, 39,158, 19, 18, 21, 36,165,158, 84,115,163,196,105,234,116,116, 44,252, 60,143,172,114,249,234,105,237,243,
+234, 88,226,151,149, 96, 84, 34, 93, 22,215, 29,128, 4, 3,181,141,183,216,168,177,185,166,163,240,166,136, 67, 12,245,145, 53,
+ 84,238, 0,153,166,177, 96,204, 18, 87, 55,144,155,186, 70,146, 43, 45,216,107,212, 1, 59, 91,122,169, 91,167, 70,186,227,184,
+197,203, 10,131, 87,163,189, 10, 69, 85,214,171,148, 90, 69,113,166, 35, 70, 56,136,137, 81,234,204,184,151,100,173,214,164,200,
+104, 6,254, 24,254, 26,193, 30, 33,214,177,238,127, 2, 62,206, 30, 34,208,151,119,167,131, 14, 31,170, 51,171, 76, 70,150,170,
+189, 2,208,133,100, 93, 16,152,156,135, 92, 15,166,232,176, 13, 54, 74,101,165,135, 57,220, 33, 69, 97,249, 39,169,192, 0, 26,
+ 93,210, 95,153, 46,142,195, 48,212,207,240,138, 76,170,188,247,144, 86,212,166, 41,209, 88, 17,109,147,200,217,240, 91,113,230,
+ 10, 86,128,162,166, 98,165, 96, 97,201, 9, 78,178,250, 69, 65,249,177,152,150,228,245, 53, 78,141,239,234,159, 40,211,220,125,
+234,189,102,123,128,204,166,210,121, 79, 70,152, 89, 40,114, 90,121,185, 11, 65,166,199,232,221,121,189,200,179, 42,152, 93, 92,
+ 75,230,181,135,235, 18,204, 69,152,107,221, 75, 2, 72,234, 69,174, 46, 14, 32, 60, 65,225, 38, 67, 80,102,246,156,185, 96,142,
+ 64,186, 65, 26,216, 43, 6, 40, 6,149,221,157,212, 46,150, 93, 69, 68,110,116,131, 41,199, 40, 55,231,232,175,112, 39,186, 52,
+233,149,158, 27,247,143,120, 56,116,174,173,153, 18, 34,210,174, 57,144,247,130,194,102, 74,185,149, 26, 52,200, 23, 10,162, 86,
+ 96,176, 86,182,130,146,213, 93,197,161,183, 1, 8, 39,149, 38, 53, 60,110,123, 1,189,162, 92, 20, 64,171,222, 82,246,226, 47,
+ 16,123, 65, 75, 15, 72,127,116,120,126, 77, 82,239, 20,202,115, 40, 46,174,117,219,183,111, 65, 69,126,215, 97, 8,232,243,169,
+139, 58, 27, 74, 74,185,166,114,142, 99,250, 18,209, 46,181,183,224, 68,113,102, 52,106,107,177, 37,200, 76, 89,105,113,113,218,
+ 56,118, 12, 55,101, 50, 10,230, 23, 86, 85, 37,215,208, 22,167,192, 67, 77,169, 69,206,125,108,205,177,123,137, 81,132,228, 77,
+240,230, 79,154,105,244,170, 68,172, 70,170, 45, 44,243, 23,229,205,128,165,133,198, 42, 67,110, 60,176,176,144,220, 86,155, 75,
+156,175,184, 82, 37,249,111, 22, 85, 64,218, 42, 36, 46,150,235,171, 86,247,176,186,185, 5,172, 47,228,140,198, 46, 44, 72,234,
+121,147,139, 60, 39, 92,176,153,168,117, 68,140,198,218, 71,144, 3, 98,138, 64,212,159,103, 84,140,214, 0, 32, 12, 28,131,124,
+126, 50,105,198, 21,146, 20, 2,150,143,132,228, 7, 26, 81,109,214,212, 65,248, 92, 74,194,146,164,156, 20,169, 37, 42, 0,131,
+165,219,161,234, 58, 18, 58,228,124,254, 71, 95,166,111,180,163,216, 17,194, 7, 31,240,238, 45,193,218,248,212,110, 26,248,173,
+144,137, 82,206,229, 89, 52, 54, 25,176,183, 2,186,219, 40,113, 49,183,135,111,169, 74,106, 53, 73,215,223,228, 75,245,122,111,
+187,214,152, 50, 20,235,206, 84, 2, 61,217,127,158,255, 0, 24,156, 20,241, 33,192,134,239,206,217, 30, 38, 54,238,125,139,118,
+182,211,245, 43,118,166,211,159, 90,217,123,137,109, 53, 37,113,155,187,182,234,235,101,180,177,115, 80,148,226, 64,116, 0,220,
+200, 46,171,221,234, 49, 34, 72, 30, 25,177,178,252,214,159, 48,137, 36,141,135,159,161, 6,234, 78,231, 77,251, 48, 0,221, 90,
+199,202,197,117, 32,214,105,170,234, 26,172,186, 65, 29, 84,101, 65, 54, 87,177, 10,215, 32, 13,141,138,150,236, 14,199,245, 75,
+111,141, 87,232, 7, 78,223, 46,186,240,164,147,156, 28, 3,215, 4,145,249,235,175, 68,129,142,189, 7, 76, 99,191,151,125, 32,
+ 65, 39, 61, 71, 76, 36,140,103,167,252,116,233,141, 78,248,166, 18, 9,199, 92,122,143, 95,234,239,175,161, 36,250,244,200, 30,
+ 93,115,158,191,142,170,121,127,171,248,116,215,196,144, 1,202,147,156,231,167, 92,228,232, 96,111,143,129, 56, 33, 89,201, 25,
+230,243,242,215,164,117, 4,143,135, 25, 61,115,251, 63, 29,125,233,140,254,206,216,252,245,215,209,215,246, 12, 1,220,121,253,
+253, 52, 48, 58,123,176,136,207, 68,245,233,231,142,164,103,246,106,130,219,198, 9,242, 61, 70,124,244, 78, 14, 58,140,121, 2,
+ 70, 49,246,252,191,175, 84,207,110,131, 39,246,103, 63,212,127,167, 88, 6,255, 0, 17,140,224, 37,160,224,249,103,215,184,207,
+168,252,247,208,170, 64, 0,231, 36, 18,123,250,252,190, 90,184, 57,205,158,184, 61, 58,231,190,125, 58,121,245,208,238, 32,242,
+231, 4,117,232, 58,231,175,203,236,214, 65,232,122, 99, 32,158,221, 78, 45,197, 1, 39, 32,245, 29, 49,158,152,199,174,188, 20,
+231, 36, 28,121, 28,159,179,207,240,209, 42, 73,234, 20, 7, 79,245,123,146,126,126, 67,174,168,242, 12, 40,100, 99,166, 0,243,
+235,158,231, 75,169,184,235,131,168, 34,219,109,243,243,111,195, 3, 40, 3,212,147,129,248,125,186,160, 70, 70, 63, 35, 70, 41,
+ 35, 56, 30,153, 63, 44, 13, 12,180,144, 73, 3,167,246,126,206,186, 81, 79,108, 24,216,116, 23,254, 71, 0,184, 0, 32,116,206,
+122,159,217,215, 31,158,154,162,160, 78, 58,100,103,175,175,221,163, 20,147,230, 7,221,216,158,250, 25, 89,201,230, 56, 39,183,
+207,211, 31,119,244,105, 92, 1,208, 95,113,129, 22,128,114, 64,199,200,249,250,140,104,117, 35,166, 6, 1,239,246,103,200,244,
+209,138,206, 65, 56,207,160,242,208,199,169,200,207, 95, 92, 14,221, 63,118,149, 7,160, 39,167,207, 95,158,248, 54, 5, 87, 76,
+228,103, 25,253,159,187, 66,172,116,206, 15, 78,216,253,164,244,237,211, 70,172,100,142,152,235,220, 30,253,124,255, 0, 62,122,
+ 25,196,228,156,100, 1,208,227,182, 79,228,104,248, 50,250, 91,127, 92, 91,215,128,112, 14, 73, 39,167,161, 29,123,232,115,223,
+168,235,158,191,184,104,199, 19,144, 83,211, 62,126,189, 61, 63, 13, 12, 80, 70, 78,114,125, 15,225,223, 58, 89,122, 97, 81,107,
+ 3,210,216, 29,105,243, 25,206,133, 90, 72, 39,183,153,251, 62,223,150,116,105, 25,251,186,250,103,228,126, 90, 25,105,206, 73,
+200, 62,126,125, 59,253,250, 85, 79, 91,157,176, 69,216,144,119,183,250, 96, 34, 48,113,165,175,107, 73, 39, 35,175,224, 52,180,
+174, 15,113,220,216,227,234, 49,143,233,209, 40, 24, 3,231,215,243,247,106,128,198, 6, 1, 31, 35,223, 85,211,204, 59,128, 49,
+233,223, 61, 58,233, 18,118, 3,231,221,140,226,178, 60,250,253,223,191, 85,209,220,253,157,189,127, 63,191, 84, 81,143, 33,215,
+204,234,178, 6,122,231,177,237,249,242,254,173, 16,157,137,190, 6, 8, 78,112,112, 70, 7,124,143,196,244,243,233,162, 27,234,
+126,239,234,213, 4,125,189,188,191,126,189, 18, 64, 86, 14, 8, 30,125, 1,207,244,255, 0,102,181,216,133,193, 78,224,142,199,
+ 7, 54,115,211, 61, 62,206,158,126, 99, 69,164, 14,128, 16,123, 15,151,236,213,189,146,233, 74, 78, 19,142,153,251,112, 63,171,
+ 71, 55,223,162,122,140, 28,224,246,249,233, 34,215,194, 71,174, 43,165, 61, 65, 57,232,123, 99,191,167,237,209, 9, 0,142,169,
+249,103, 39,175,175,217,170, 64, 18, 71,145,233,231,230,123,231,229,170,232,200, 36,116, 29,135,203,168,243, 62,103,182,176, 73,
+ 61,123, 96,167, 21,209,156, 1,208, 14,195,241,243,249,104,148, 3,216,156,228,224,103,250,117, 65,160, 72, 29, 58, 3,231,163,
+ 16, 58,231,175,203,211,211, 73,191,175,207,108, 99,107,145,181,206, 58,159,236,114,180, 36,215,120,223,178,238,166, 92,121,134,
+ 54,178,207,191,175,249, 50,154, 42, 65,101,248,212, 39,104, 52,196,151, 17,213,181, 46,101, 96,132,144, 65,248, 62,103, 82,170,
+147,119, 79,171, 52, 99,214, 12, 27,130, 56,200, 92, 43,154,147, 73,175,197,113, 32,149, 96,181, 85,136,238, 83,215,166,114, 61,
+117, 30,111, 98, 93, 13, 12,206,226,110,249, 80, 74, 93,129,102,217,118,147, 11, 61, 22,147, 89,172,205,170, 73, 66, 84, 58,128,
+180, 66,104, 17,242,215,110, 85, 89, 62, 34, 74, 78, 18,162, 18,178, 78, 2, 72, 24,243,252, 53,207,158, 33,214, 52,188, 67, 60,
+ 91,218,146, 56,163, 6,254,160, 73,191,190,242, 16, 55,233,143, 67,190,140,252, 57, 24,240,222, 10,185, 97, 89, 6,113, 87, 87,
+ 57, 12, 1, 4, 44,130,152, 2, 8,181,138,211,143,223,140, 91,113,184, 80,224,223,122, 90,127,248,197,225,195,111,141, 78, 74,
+ 74, 28,185,236, 6,100,109,189,210,202,149,255, 0,194, 25,155,109, 45,182, 30,116, 14,184,114, 58,193, 35, 36, 29,114,235,126,
+ 61,136,232,153, 30,101,195,194, 78,234, 11,142, 74, 18,167, 81,180, 59,192,184, 84, 27,145,224,126, 38,225,219, 27,129, 13, 41,
+129, 85,124,254,171,109, 79,106, 42,220, 56, 5,240, 78, 79, 93,141,126, 51,110,161,151, 93, 72, 82,213,250, 21,147,128,162,159,
+242,172,156,116, 75,192, 96,143,245,128,214,109,101, 34,179,125, 87, 98,219,150,188, 73,117, 58,171,235, 8, 75,113, 88,113,228,
+190,130,160,148, 6,130, 7,194,176,163,212,158,137, 41,207,108,226, 37, 67,197, 89,254, 85, 44,107, 65, 92,242,128,109,202,127,
+172,140,251,130, 53,244,131,234,154, 77,174, 21,133,241,105,113, 79,128,254, 26,113,109, 13, 76,249,182, 65, 22, 83, 80, 16,177,
+174,164, 11, 73, 52,123,127,120,210, 70,162, 57,108,123, 78,146,165,250,169,223, 16,133,191,246,226,251,218,171,186,173, 97,110,
+ 77,165,112,216,183,165, 5,229, 49, 86,182,110,106,115,212,202,172, 69, 5, 40, 7, 80,219,163,150,100, 37,129,150,164, 48,167,
+ 88,117, 63, 19,110, 40, 29, 97,233,193,243, 24, 29,250,143,184,116,215,232,143,190, 62,204, 45,147,226, 95,110, 34,219, 28, 90,
+ 85,225, 64,173,211, 34, 4,217, 87, 45, 7,192,123,116,108, 57, 14, 35,197, 13,193,172,182,131,239, 52,194,172,248,180,249,101,
+232,171,201,194, 80,172, 40,106, 85,157,236, 48,246, 94, 89, 49, 96, 11,150,111, 16, 59,185, 80, 43, 83, 18, 93,168,222, 84,251,
+ 54,159, 41,214,155,241, 92, 81,129, 64,166,133,196, 36,117, 74, 67,170,207,108,116,206,173,202, 63, 17, 40,214,142, 55,205,233,
+ 13, 21,112,217,227, 87,141,135,185,128, 46, 29, 67,117,210,202, 74,244,212,246,213,142, 20,207,126,143,124, 95, 14,119, 61, 31,
+ 6,200, 56,195, 36, 55,104,107, 68,114, 83, 2, 59,199, 46,168,204, 70, 69,177,250,200,100,120,157,124,223, 84, 73,137, 96,225,
+130, 70,121, 22, 8,237,202,133, 96,250, 28,227, 72,168, 32, 0, 58,146,113,140, 31, 63,151,222, 53, 61,230,125,146,190,201, 76,
+ 62,208,225,254,252, 87,128,217,112,248,251,193,118,173,197, 4, 39,152,242,173, 11, 29,115,211, 32,117,193,211, 69,186, 94,193,
+159,103, 5,247, 75, 55, 6,222,220,187,247,177,170,142,168,178, 84,212, 27,150,141,124,210, 39, 70, 74,144,228,182,226,199,187,
+233,222, 60, 23, 11, 1,196, 7, 82,242,195,107,113, 42,240,151,142, 83,177, 77,226, 46, 75, 83, 47, 41, 81,193,177, 55,242,216,
+ 0, 46, 73,185, 22,183,223,238,190, 25,235,190,143,254, 42,229,177,123, 69, 87, 14,170,171, 21, 80, 22,161, 11, 51, 57, 1, 84,
+ 2,160, 93,137, 3,114, 63,142, 35, 1,192, 79,179,155,127,248,252,190,165,208,246,210,151, 26,220,219,219, 90, 68, 49,185,187,
+209,119,179, 45,157,189,219,184,210,112,227,112,228, 57, 29, 33,219,162,244,145, 27,153, 80, 40, 80, 57,165, 61,128,236,151, 33,
+196, 10,146, 38,173,194, 71, 5, 92, 32,251, 61,109,198,127,137, 11, 71,248,111,187,134, 47,186, 92,156, 68, 95,208,233,213, 77,
+203,169,188,166,210,220,230, 45,176,210, 20,198,221, 91, 60,222, 42,147, 78,163,161, 14,132, 16,169, 50,102, 40, 41,100,251, 2,
+ 70,221,108,222,222,208,118, 35,135,219, 98,141,182,187, 99,183, 80,221, 22,253,169, 5,240, 28,175,120,202,109,117, 43,158,224,
+172,168, 42, 69,193,113,212,166, 35,154,109, 86, 73,117,239,122, 88, 75,220,172, 22,219, 70, 15, 39,112, 35,202,153, 34,108, 9,
+ 83, 16,228,242,167, 30,167,205, 67,209,101, 60,247, 40, 75,203,132,133,184, 16,103,115, 6,213,204,193,117,183,249,130, 73, 35,
+ 5, 53, 87, 20,120,131, 91,154, 84, 73, 73, 68,198,158,137, 73, 10, 65,221,198,214,239,181,250,134,185,234, 8, 61,113,217, 30,
+ 12,253, 20, 41, 50,184,169,243,158, 45,133,115, 76,244, 44,114,114,236, 90, 10,109,118,101, 69, 7,109, 69,110, 68,166,247, 32,
+244, 91, 5,122, 46, 93,207,151,112,185, 82, 84,201,237, 85,196,152,174,184, 88,241, 23,239,197, 8,146,129,239,112,210,195,217,
+143, 82, 97,220,134,151,240, 7,148,160,230, 82, 64, 42,108, 46, 11,170, 52,200,142, 42,108,229, 75,154, 25, 10,128,251,176,220,
+ 69, 62,231,164,248,160, 73,129, 34, 43, 32,148, 79,109,191, 21,101,149, 97,198,164, 54, 36, 52,149, 5,184, 19, 97,136,251,117,
+212, 9,207, 47,222, 75, 83,204, 70,166,198,109, 84,203,178,149, 49, 96, 25, 28,237,178,132,166, 28, 66,181,167, 45,188,144, 84,
+217, 47, 45,181,163,161,199,231,178,168,238, 61, 67,174,165, 50, 30, 68,210,138,101, 69, 41, 66,226,214, 24,154,175, 18, 68, 23,
+ 25,200, 16, 43,237, 53,206, 89, 40, 41,101,229, 18,227, 11, 67,153,107, 85,228,149, 94,103,214, 88,177,181,218,251, 49,190,198,
+219, 19,126,194,199,107,117, 59, 14,220,202, 56,115, 41,161,100,166,134, 46, 65,164,220,199, 24, 80,202, 6,149, 99, 29,208, 93,
+ 86,200,179, 38,148,109, 12,205,160, 36,107, 36, 87,151,170,161,165, 46,223,113,167,151, 78,170, 42, 43,148,218,139,143,133, 60,
+212,244, 50,100,136,203,150,242,135,136,250, 60, 22,164,198,112,144,183, 19, 29, 76, 58,165, 45, 0,185,112,131, 94,118, 83,239,
+ 68, 41,110,145, 84,110, 85, 61, 77, 75,109,178, 94,166,215,169,104, 8, 67,209,226,188, 8,118, 28,136,175, 69,146,129,147,227,
+180,167,144,130,160, 73, 24,237, 74,148, 41,180,184,241,225,200,118,224,181,231, 71,136, 98, 84,161,159, 30,183,110, 75,101,207,
+122,101,135, 67,139, 34,171, 78, 67,173,161, 72,116, 98, 92, 85,128,204,132, 60,193,241, 18, 44,199,101, 84, 85,252, 43,112,177,
+ 42, 84, 4, 52, 95, 52,245, 4,179, 84,167,160, 46, 60,163,202, 84, 82,137,173,158,119, 35, 43, 36, 50,180, 41,160, 2, 22, 0,
+ 48,114,196,178,177, 80, 55,211,178,238, 64,223,114,118,234, 70,226,196,234,190,160,112,250, 40,232,234, 98, 13, 29,180, 72, 74,
+135, 58,129, 51,142, 88, 77,113,191,149, 76,133, 66, 76,142, 54, 49,137, 46,240,201,115,180,187,121,113,159,112,167, 74,168,126,
+134,164, 39, 75, 21,246,192, 76,150, 24,152,101, 59, 6,160, 22,251,164, 23, 22, 86, 34,169, 37, 64, 41, 77,186,215,114,156,150,
+ 43,139, 43, 97,169, 85,218,101,105,162, 25, 69,219,106, 92, 52,234,159, 51,106,114, 59,213,187, 98, 11,114, 96,186,162,129,133,
+ 58,105, 47, 71, 91,228,165, 74,112,210, 83,241, 18,146, 11,135,106,214, 98, 78,172, 73,102, 43,177,164, 67,184,105,116,249, 76,
+184,164, 4, 42, 59,240, 23,245, 98,155,113,151,208, 49, 37,216,174, 66, 88, 82,250, 45,200,200,202,137, 72, 26,161,196, 82,249,
+ 44,237,191,114,123, 77,202,228,191, 13, 50,108,176,183, 27, 75,109,213, 41, 83,161, 73, 7, 42, 42, 37,230,219,111,224, 71, 41,
+ 82,129, 72, 56, 26, 82,178,211, 80,176, 96,117, 33, 87, 27,130, 65, 15,123,139,250, 43, 17,247,133,176, 59,154,251, 35,230,229,
+ 30, 34,101,181, 84,209,154,121,115, 5,168,137,162, 38,222, 89,169,228,145, 35,177, 23,211, 13, 74, 42,128,222, 98,209, 33, 93,
+247, 45,207, 13,114,155,103,122, 54,250,161, 33,214, 94,250,215,234,202,139,111,115, 54,235, 9,117,115, 33, 84, 25,247,117,161,
+ 36,186, 75,171,142,226, 92, 32,132,169, 8,234, 2,250,244,178,232,151, 46, 85, 85, 97, 46,180,218,152,141, 41,185, 10, 82,146,
+133, 56, 87, 49,135, 28, 75,206, 54,128, 82,149,182,149,114,148,252, 73, 40, 42, 25, 63,173,202,173,165,149,245, 27, 59,105, 37,
+133,198,106, 75, 46,199, 11,153,201,226, 56,179, 68,204,101, 51,206,133, 4,148,184,138,122, 64,229,229,233,145,221, 56, 61, 81,
+185, 75, 51, 27,159, 80,109, 41,125,186,148, 24,239, 53, 37,180,135, 92,106, 52,136,171,113, 78,165, 68,140, 37, 16,223, 89, 4,
+156,167,195, 25, 30,171,240,236,165,105,234,169,128, 26,161,150,226,251, 18, 25,116,220,216,131,250,167,125,192, 39,222,113, 12,
+241,161, 4,252, 89,144,102,166, 63, 45, 69, 19,211,173,192, 32, 52, 53, 5, 73,183,217, 0,172,167, 96,196,253, 93,251,227, 89,
+170,116,137,115, 41,150,180, 88,239, 52,228,155,128,190,219,171,105, 45,132, 20, 84,125,242,101,110, 97,109,192, 60, 15, 6, 4,
+169, 41, 7,205,101, 42, 4, 30,100,235, 48, 98,100,183,170,109, 55, 77,129, 26, 53, 90, 77, 38,159, 64,165, 69,109,165, 59, 30,
+ 52,118, 31, 90,205,199, 80, 1,144, 68, 88,139, 74, 3, 44,182, 0,117, 80,218,100,243, 23, 20, 81,245,170, 20,128,229,191, 57,
+231, 18,227,180,170, 21, 94, 83,170,231,105, 13,211, 41, 41,129, 19,194, 45,180, 74, 72,152,162,162,165,171, 24, 90,155, 91,121,
+ 64, 1, 10,190, 89,208,106, 49,147, 38,123,140,190, 42,215, 59,205, 63, 4, 41, 77, 7,232,116,248, 77, 39,221, 90,229, 3, 45,
+ 60,220, 25, 11,121, 77,164,169,180,203,154, 2,178,180,171, 50, 56, 55,242,106, 47,163,123,251,137,182,215, 39,127,128, 23, 32,
+147,183, 70, 90,252,198, 22,163,102,103,142,115, 15, 52,168, 39, 72, 47, 37, 68,133,131, 88,139,196,145, 68,178, 49, 42, 54, 4,
+ 38,158,106, 17,126,147, 14,157, 74,146,213, 34,214,106,160, 3,145, 23, 72, 93, 65,214,154,147, 60, 45,214,208,171,150,181,227,
+ 40,145, 58,176,135, 20, 0, 88, 40, 71,191, 85, 50,133, 16,199, 40,204,233,149,217, 16, 81, 74,106,213,167,196, 41,166, 68, 93,
+ 61,218,202,202,222,163, 83, 36,180,202,163, 63,224, 83, 73, 82,235, 51,209, 30, 63, 41, 12,169, 45,248,223, 4,213,169, 74, 90,
+ 53,128,211,101, 42, 82,164, 55,109,135, 89,147, 41, 74,163,196,152,181, 2,229, 14,132,196,169,105,114, 84,194,235, 37, 15,213,
+165,203, 74,222,142,144, 8, 75,184,116,146, 25,235,123, 77,126, 53, 26,159, 50,222,163, 82, 34, 87,170,209, 34,199,165,211, 98,
+196,145, 42, 52, 27, 97,182,148, 76,169,143,206,119,244, 45, 5, 21,254,145, 74, 46, 58,167, 16,167, 2, 71, 51,139,214,220,104,
+ 21,172, 65, 37,238, 69,201, 58,119, 82, 55, 23, 34,254, 81,127, 40,177, 82, 54, 23, 48,154,250, 57, 42, 21,105,164,129,171,170,
+ 20,141, 98, 87, 0,144,254, 73, 38,170, 44,234,129, 19, 88,176,146, 78, 89, 34,103,179,171,162, 77,157, 81,164,143,123,163, 8,
+ 73,114, 60, 56, 14, 56, 25,153, 92, 82, 27, 64,113,230,129,159,116,212,234,141,165, 30, 35,232,150,149, 34, 26,138, 67, 35,195,
+229,195, 64,160,161,215,163,214,229, 61,114,193,118, 3, 18,169,144,234,116,244, 83,105,213, 73,128, 42,170,162,244,180, 53, 84,
+173, 73,139, 52,114,195,114, 72, 17,209, 13, 46,130, 91, 66,252, 80,144,164,132,233,150,102,139, 89,170,162, 58, 42, 11,109, 2,
+156,194, 86,221, 33,181,251,181, 38, 42,218, 67, 77,174, 97,127,153, 78,214, 92, 14, 2,191, 29,239, 13,182, 62, 55, 80,210, 57,
+121,206,113, 74,153, 54,127,189, 8,203, 67,140,225,184,143, 85,220,123,222,211, 87,121,197,162, 59, 80,232,138, 96,225,196, 37,
+231, 93,231,158,158,124,173,226,166, 18,183, 1,113, 59,104,206, 7,217,212,166,214, 54, 39,125,193,177,184,189,190,201, 2,219,
+129,115,109, 36, 64,115,202, 58,106,133,145,131,199, 51,172,111, 27,220,150, 84, 18, 57, 32,181,236, 38,119,102,187, 2,172,173,
+245,138,161,227,115, 42,109, 53,183, 89,113,151,211, 75,165,167, 49, 32,171,220, 30, 90, 20,243,205, 83,164, 33,100, 75, 87,189,
+190,190,121, 21, 18,250, 71, 48, 94, 91,105, 75, 43,121, 74,230,229, 45,103, 23,124, 32,112,213,237, 11,217, 74,166,193,241, 37,
+103,179,117, 80, 93,247,138,133,163,115, 83, 94, 17,183, 11,108, 46,100,165,216,113, 47, 43, 30,236, 12, 41,116, 27,141,183,211,
+202, 18,144,184,181, 22,208, 98,204,139, 46, 18,220,104,135, 30,225, 76, 56, 81,105,212,133, 48, 41,180,229, 70,162,206,126, 38,
+ 92, 98,148,206, 66,164,193,166,164, 45,105,171,200, 68,140,120,203, 37, 97, 47, 60,174,114,244,144, 80, 29,171, 42,165, 30,155,
+ 49, 51, 37,181, 81, 79,132, 15,185,196,151,151,234,114, 30, 44,248, 41,113,104, 4,248,238,184,148,190,180,184, 74,188, 52,182,
+ 16,234,154, 81, 58,124,203,115, 9,169, 39, 2, 57, 12,104,246, 82,172, 26,204,163, 72, 34,253, 44, 52, 92, 91,236,149, 12,133,
+109,183, 62,241,103, 9, 69, 81, 77, 83, 52,208,150, 44, 27, 66,145,121, 36, 63,181, 37,206,204,250,129, 61,116,169,212, 89,131,
+ 43,201,249,104,123, 74,253,155,155,225,236,203,226, 10,102,204,110,202, 63,132, 86,125,198,138,149,127,100,183,134,155, 1,112,
+237,173,219,177,225,202, 67, 75,152,211, 60,203, 77, 6,247,167,123,204, 54,107,180, 85,184,167, 33, 62,251,114, 35,170, 69, 54,
+ 84, 73, 46,115,200, 36,167, 25,234, 60,137, 61, 71,217,242,198,191, 92,191,104, 95, 2, 27, 99,237, 47,225, 82,247,225,235,116,
+208,197, 6,191, 47, 55, 54,209,110, 43, 17, 27,149, 84,218, 45,211,165,197,120, 90,215,101, 56,171, 11,149, 13, 70, 66,225,214,
+ 96,115,165, 21, 26, 85, 74, 92, 66,166,214,227, 79, 55,249, 64,239, 46,206,238, 55, 15,155,187,185,155, 17,187,212, 5, 91, 27,
+163,180, 55,157,106,194,190,104,165,101,216,241,171,116, 57, 30, 18,166,211, 37, 16, 5, 70,131, 54, 18,226, 79,167, 74, 70, 81,
+ 42, 5, 78, 52,132, 18, 28, 26,183,178,186,229,171,129, 84, 73,169,212,119, 35, 85,129, 0,134,181,188,202, 72, 5,128,210,110,
+164,121,139, 34,115,126, 99,150,201,150, 78,208,177,215, 21,236,173,125, 91,218,250, 75,126,181,187, 55,113,190,246, 44, 91, 95,
+135,148,129,156,147,147,205,212, 31,144,244, 3, 58,243,202,158,132, 96,121,118,234, 51,223,167,152,213, 84,132,144, 83,212,144,
+122,231,250, 71, 93,121,229, 7,168,206, 61, 58,103,231,212,233,216,126,242, 48,223,133,202,123,243, 12,118,207,203,183,111, 61,
+ 32, 14,126, 17,140, 14,161, 90,245,202, 0,199,235, 2,114, 60,191,110,190, 5, 15,139, 57,201, 32,114,253,216,239,161,239,192,
+233,108,123, 39,162,135, 78,189, 62,195,246,249,106,136, 10, 78,112, 73, 80, 61,113,230, 62, 64,254,122,234,166, 18, 83,202,122,
+103,184,207, 81,130, 49,223,236,215,174, 80, 6, 9,201,199, 47,111, 46,189, 71,203, 89,192, 63, 27, 96, 53, 1,149, 31, 49,140,
+143,183,211, 84, 10,122,103,152,159, 49,204,115,211,229,233,253,186, 57,109,140, 0, 0, 42, 35,161, 61,188,137,207,221,161, 86,
+ 58,145,216,118,198, 58,231, 30, 93,116, 48, 63,158, 1,112, 96,228,246, 63,119,203, 84, 21,220, 28,101, 35,160,235,242,245, 31,
+102,138, 90, 22,121, 72,232, 51,231,247,231,247,104,117, 39, 61, 58, 2, 59, 96,249,104,234, 64,191,160,198, 65, 55,247,255, 0,
+ 60, 14,160, 50, 60,137, 24,206, 58,103,203, 61, 58,234,146,135,124,156,121, 99,160, 31, 51,219,236,252,116, 73,206, 49,128, 51,
+231,231,251,123,106,130,209,216,142,152, 32,159, 63,195, 75, 14,184, 84, 94,215, 29, 79,250, 96, 55, 19,215, 9, 7,190, 79,166,
+113,212,157, 10,180,231,174, 51,219, 30,163,230, 61,124,245,112, 94, 8, 35, 56,199,150, 58,254, 63, 97,208,174, 36,246, 79, 78,
+132,250,231,203,175,160,237,165,148,155, 11,141,240, 1, 23,176,233,128,148,158,253,122,158,192,247,206,126,126, 93,116, 42,219,
+ 61,126, 33,142,248, 29,128,238, 64,251,180, 98,130, 72,235,144,115,140, 99, 39,215, 61,190, 90, 29,105, 56, 32,252,142,124,190,
+223,195, 58, 58,223,238,254, 95, 39, 6,192,106, 72, 24,199,207,169,245, 30, 90,160,176, 6, 79, 92,227,183,145,249,118,249,104,
+165,167, 61,148, 78, 62, 93,254,239, 93, 12,179,220, 30,157, 60,198,115,242,249,127,110,150,193,148,246,192, 42, 80,207, 64,115,
+230, 7, 95,188,250,119,213, 21, 12,100, 99, 63,179,231,162,150,129,220, 12,103, 57, 35,191,246,104,101, 2, 7, 81,158,249, 35,
+174,127,183, 74, 39,124, 40,187,129,129,212, 62, 68,122,250,125,199, 84, 23,140,143, 92,117,213,117, 19,215,184, 4,231,175, 66,
+ 79,245,106,130,251,142,158, 93,255, 0,118,149, 29,122, 95, 24, 34,198,227,107,126,239,159,158,216, 20,140, 18, 59,227, 75, 95,
+ 85,250,199, 75, 75, 13,192, 56, 53,129,222,221,113,224, 31, 34, 70,125, 6,170,115,117, 4, 36,146,112,146, 71,252, 62, 67, 84,
+ 57, 57,156, 74,190, 46,131,167,126,189, 72,198, 14,138, 73, 72, 0,249,103,174,123,247,243,198,181,201, 39,189,191, 44, 27,238,
+190, 43,164,129,129,211, 63,236,245,233,243, 58, 32, 97, 35, 36,140, 31, 65,231,246,249,232,100,242,133, 16, 14, 78, 58,158,157,
+ 7,144, 58, 37, 4, 36, 28,167,155, 7,168,239,223,182,147, 44,119, 29,113,140, 86, 9, 88, 80, 33, 67,148,142,189, 58,147,229,
+223,183,125, 16, 27, 14, 36, 37, 73,206, 14, 71,113,233,215, 84,146,114, 59, 96,121,126,113,162,219, 33, 61, 20,122,227,203, 61,
+135,228,105, 51,107,111,211, 4, 38,221, 6,253,190,126, 24,172,132,132,167, 25,192, 31, 46,167,238,209,141,168,114,132,252,186,
+ 31, 95,234, 58, 17, 41, 24, 32,168,146,115,128, 59,159,179,174,138,108, 18,115,203,216, 12,131,215, 0,103,174,144,194, 71,174,
+ 42,227,160,207, 92,117,206, 62,223, 33,242,209, 40,194,176, 79, 64,124,186,245, 61,190,239,236,213, 16, 1, 81, 29, 64,242,237,
+249,245,209, 45,130, 6, 1,237,228,113,147,251, 59,104, 99, 7,241,193, 13,224,100, 14,158,159,183, 68, 33,125,121,112,122,103,
+ 36,117, 25,207,111,219,170, 8,237,156, 12,250,116,207,217,159, 61,101, 86,165,169,113,222,213,218, 85,175,104,208,234,151, 29,
+199, 92,154,205, 58,143, 67,162, 64,145, 83,170,213,103, 62,174, 86,162,193,129, 17,181, 57, 37,226, 79, 92, 12, 36, 30,101, 16,
+144, 78,144,150, 68,141, 93,157,130, 34,110, 73, 54, 0, 1,212,158,192, 96, 14,194,219,159, 78,228,237, 97,234, 73,216,119, 56,
+239, 95,177,184, 52,198,205,241, 34,250, 82,145, 37,219,203,111,154,116,243, 97, 74,140,138, 52,229,161, 36,121, 36, 56,165, 99,
+ 62,127,102,186,125, 58,178,168,165,224,240,108,180,227,106, 45,243,168,133, 3,219,224, 41,253, 99,156, 28,124,181,130,123, 43,
+ 61,153,123,231,176,246, 46,230, 76,226, 66, 69, 19,109, 99,238,172,123,102, 85,189,105, 61, 82,102,161,115, 83, 77, 53, 47, 41,
+114,110, 56,241, 22, 91,166,201, 83, 79, 37, 41, 96, 41, 78, 35, 7,156,131,211, 91,183,187, 60, 21, 87,216,164,202,171,216, 55,
+ 44, 43,172,211, 80,185, 34,157, 13,254, 73,133,108,167,153, 73,110, 58,212,124, 76,167,200,119,206,185,175,140,211,219,115,250,
+250,186,121,150,106, 87, 41,102, 86, 4,217, 99, 69, 62, 95,180, 64, 96, 69,237, 98, 6,161,177, 7, 30,160,125, 30, 51, 92,167,
+ 42,240,231,133, 50, 92,240,205,148,102, 10, 42, 3,172,240, 74,138,188,202,201,222, 50,206,202, 2,106, 70, 70,243, 90,193,183,
+223, 26, 33, 89,187, 38, 56,211,173, 73, 82, 68,134, 29,100, 33,180, 43,195,241,146,165,129, 30,115, 42, 79, 82,234, 84, 82, 20,
+ 61, 53,220,158, 22,104,113,246,115, 98,169, 87, 66,163,180,230,226,223, 48,159,157,245,162,217,109,215,233, 84,130, 15,134,212,
+ 53,167, 42, 99,197, 78, 84,181,167,226,199, 98, 53, 30, 10,163,245, 54,234,111,196,144,202,209, 82,166, 75, 80,109,137, 72, 83,
+ 78, 49, 38, 59,153,147, 79,146,210,250,165,126, 35,100, 96,227, 24,215,127,118,138,242,164,110, 62,192,109,157,106,149, 47, 30,
+229, 76, 54,197, 89, 17,150, 68,186,101, 86, 23, 51,106, 97,104, 7, 45,130, 23,217, 88,202,117, 28,118, 20, 81, 23,136,105,153,
+198,204, 58,139,149,189,143,111, 45,236, 65,254, 3, 29, 5,199,185,104,158, 14, 29,203,164, 80,217,101, 77, 86,170,133, 93,209,
+180,199,170, 20, 96, 14,241,187, 6, 37,127, 93,148, 45,136,181,242,106,229,223, 42,176, 31,122, 91,235, 11,114, 43,173, 63, 43,
+152,169,199,159,143,135,153, 45,243, 30,101,243,182,162,159,187,215, 88,194,171,109, 42, 52, 22,155,105,229, 73,168, 62, 22,203,
+206, 5, 45,198,219, 49,203, 37, 62, 31, 54,124, 70,223, 9,248,135, 92, 47,174,172,242, 97, 74,133, 54,150,235,136, 92,152,237,
+ 58,252, 89, 13, 45, 92,139, 46, 50,219,136, 74, 20, 9,248, 28, 41, 32,143, 62,190,122,188, 83, 18,164, 54,242,101, 71, 65,114,
+ 44, 22,132, 53, 40,114,187, 30, 75,239, 23, 82, 65, 72,234,224, 65, 70,125,121,117, 30, 87, 45,172,129,168,158,155,237,126,135,
+115,211,189,187,236, 62, 56,127,142,130,130,138,154, 49, 79, 24,120,134,234,170,193,123,180, 96, 91,169, 10, 66, 18, 15,151, 77,
+128, 4,226,231, 71,140,106,110,203,144, 95, 44, 50,131, 42, 92,249, 46, 56,161,202,196, 32,136,201,141, 24, 96, 36,190,183,201,
+194, 51,149, 21, 28,117,214,187,111,102,251,181, 33,243,106, 81,228, 61, 14, 37, 33, 97,130,251, 50, 21, 30, 63, 51,105,194,152,
+ 98,106,148, 82, 95, 81,200, 60,195,245,138,142, 20, 14, 19,125,222, 75,250, 78,218,216,238,219,180,169,142, 42,187, 85,231,169,
+204, 91,107,109, 14,183, 50,106, 86,182, 24,105,167,112,133,173,168,202, 43, 80,230, 79,199, 45, 56, 33, 67, 58,228,228,187,229,
+250,132,217, 47, 75, 67,178, 96, 58,242, 83, 61,164, 56,226,208,226,208,181,175,198,125, 46,167,157, 35,226,117, 68, 43,152, 40,
+ 32, 32, 40,140,101,246, 58, 73, 18,147,146,135, 76,211,128,242,145,107,170,177,186,198, 9,237,250,205,184,185,216,218,219,233,
+112,238, 72, 56,183, 63,169,204,229, 28,252,143,135,165, 49, 82, 40, 35,235,170, 18,203, 36,204,173, 96,202,132, 24, 98, 13,183,
+146, 66,118, 56,218,122,181,245, 81,114,145, 37,110, 60,103,198, 97,207,125,165, 84, 31, 79,131, 90,163,190,219, 97, 10,108, 48,
+ 26, 9,169, 66, 90, 80,227, 47,128, 80,181, 33,204,169, 42, 79, 34,145,144, 27,238, 36,202, 77, 46, 61, 71,146,158, 91, 77, 34,
+ 80,129, 80,121,196,192,149, 37,107, 67,234,250,134,230,105, 96,211,223,104,169, 92,205,169, 77, 58,128, 83,145,140, 41, 90,141,
+ 75,174,173, 77,251,204, 9, 44,170,156,220,176,219,244,224,164,200,165, 79,117,183, 20,184,138, 75,160,173,218,100,118, 89, 33,
+ 75, 40,230, 73, 95, 94, 82, 7, 38,179,218,117,105, 35,154,151, 61,164,211, 34, 50,180, 74,121,186,147,237,205,163, 21, 60,162,
+ 29,110, 35,204,164, 37,216,238, 48,180,134,146,248, 5,180,189,243,232,211, 62, 92,169,112,162,228, 27,221,109,123,121,123, 16,
+109,110,225, 46, 44,215,186, 62,199,161,242,220,190,156, 36,113,114, 47,203,109,107,162,234,192,145,231, 26, 47,177,110,190, 75,
+ 27, 13, 65,145,137, 24,220,138, 82,100, 86,167, 67, 85, 85, 5,217, 21, 54, 83, 26,153, 91,143, 41, 84,218,173, 77,175, 19,157,
+ 16,100, 78,167,184,142,105,169, 96,169, 46,243, 41,104,121,178, 22,223, 34,202,155, 23,250,140,137, 20,138,148,138,125, 82, 20,
+234,253, 56, 69,122, 35,244,247, 86,135, 43,244,199,152,112, 33,197, 60,228, 96,159,173,226,132, 50, 84,121,113, 53,165,176,135,
+ 82,167, 71,194, 53,242, 20, 11,121, 84,166, 35,198,155, 38, 4, 37,169, 19, 41,142,209, 42, 19,225,165,233, 62, 34, 25,142,226,
+ 80, 30,113, 17,157, 66,149,252,196,164, 18,216, 82, 84,115,167, 38,148,205,126,152,227, 49, 97,220, 38,171, 81, 86, 91, 68, 26,
+187, 13,248, 14, 69, 97, 62, 35,143,138,156,112, 22,101, 41, 15, 18, 22,226, 10,194,136,230,230,233,134,127, 42, 6, 37,206,199,
+117,101, 43,181,186,143,180, 75, 2,110, 73, 96, 5,128,176, 42, 44,157, 77, 28, 1,181, 71, 86,166, 56,195,160,133,227,150, 34,
+ 10, 48, 60,200,165, 70,147,146,168,163,204, 71, 45, 85,148, 2,193, 25,163,195,167,111,214, 86,203,172,196,137, 45,186,155,174,
+161, 10,167, 73,203, 62,227, 94,136,211,232, 33,202,160, 82,127,192,238, 54, 24, 88, 10,120, 37, 1,208,149, 43,151,151,153,182,
+170,166, 34,105,117, 25,181, 40,161, 79,194,159, 53, 78,221,148, 2,130,244,202, 62, 11,173,203,168,196,140,210,177,239,188,139,
+ 79,188, 52,148,143, 25, 25,113,159,210,140,171, 8,167, 26, 85, 94, 65,131, 35,235, 11,102,226,130, 87, 49,132, 48,166, 27,155,
+ 34,167, 24, 20, 49, 81,133, 37, 81,151, 26,170, 90,112, 31, 21,124,188,252,170, 13,201, 72, 73,201,204,105,149, 74,157, 57,200,
+147,110, 38,154,139, 18, 67,205,195,153,115, 70,104, 51, 79,155, 83, 70, 23, 21, 85, 85, 0,161, 70,146,242,249, 2, 78, 76,126,
+101,128,219,173,128,148,235, 34, 80,196, 0,231, 83, 92, 1,220, 90,204, 10,145,112, 0,185, 42, 1, 2,236,108, 45, 99,136,197,
+109, 57,134, 90,147, 78, 60,243,173,165,136,149, 15, 48,189,215,148, 86,241,202,190, 93, 81,152,134,165,148, 13, 11,202,242, 35,
+169,110,248,110,177, 16, 67, 42,158,104,128,170, 20,215, 22,194,141,110,142,176,131, 25,131,225, 54, 11,133, 84,196,180, 99,164,
+ 18, 82,252, 36, 58, 2, 73, 90,181,243,137,137,169, 94,219, 91, 8,140,165,159, 30,241,143, 84, 66,139,156,202,240, 96,192, 62,
+ 18,156, 82,206,124, 78, 89,140,129,203,241, 21, 30, 76, 19,163,109,106, 99,148,203,129,215,161, 22,149, 70,170, 36, 45,108,171,
+ 31,224, 53, 5,243, 58,217,101,215, 79,193, 25, 79,185, 33, 32, 39, 1,165,190, 66, 50,135, 15, 45,187,123,227, 46,167, 87,178,
+ 45,198, 26,115,194,143, 66,171,214,144, 26, 91,156,200,171, 26,148,118, 84,145, 31,151, 10, 8,167,198, 11, 4, 31,135,197,207,
+235, 37, 39, 74,201, 56, 20,179, 48,220, 2,160, 89,137, 27, 48,218,251, 92,218,224, 27,108,182,181,237,189, 90,213,112,199,197,
+185, 37, 66, 63, 50, 26, 82,245, 33,186, 21, 2, 41, 29,149,214,224, 41, 89,127, 85, 64, 0,155,129,164,168,195,121,106,210,157,
+ 49, 16,180, 67,123,221,105, 23,132,151, 98,143, 8,133,181, 9,233, 2,160,114,132,149, 41,152,202, 77, 80, 0,122, 20,224,133,
+140, 19,174,145,216, 85, 22,174,139, 58,117, 20,167,255, 0,116, 45,215,218,183, 92,253, 48,116, 59, 66,168, 71,135, 84,162,201,
+ 91,137, 33, 46,115, 83,165, 76,101, 96,101, 41, 92, 44,103,200,106,117,145,110,169,112,231, 15, 1,196,123,195, 84,153, 12,178,
+ 20,148, 41, 94, 28, 38,226,200,119,157,100,120, 95,165,138, 1,112,228,146,114,114,161,173,186,219, 8, 70,145, 86,150,137, 9,
+ 45, 70,158,138, 76, 55,148,216, 65,109, 45,150, 86,152,239,128, 57, 65, 12, 75,229,234,122,225,213,148,244,209,114,119,104,171,
+ 4,128,125, 92,254, 87,191, 96,110,192,158,223,104, 2,109,189,142,214,189,197,123,226,102,115, 14,101,151,130,175,170,167, 41,
+126,116, 54, 59,220, 24,181, 41, 23,243, 93, 94, 65, 97,177,125, 39,160, 56,182, 92, 20, 69, 77,185,225,210,208,218, 12,121,177,
+214,245,101,132,175,147, 20,200,207,169, 77, 67, 12,161, 64,187,239, 14, 55, 24, 58, 82,112,164,176,232,229, 32,231, 94, 29, 77,
+ 69,138,133, 70, 29, 29,163, 30,174,236, 24, 12, 74,171,176,182, 29, 93, 18,157, 80, 46,135, 10, 99,172, 22,209, 86,126, 34, 28,
+247, 86, 74,249, 90, 42, 50,212,149, 37,164,133, 61,149, 74, 50, 96,174,108,231,227,148, 73,104, 70, 98, 34, 90,232,251,142, 52,
+174, 65, 30, 63, 46, 28,230,126, 90,201,119, 25, 60,138,113, 64,225,189, 82,183,173,152,148,155,102,178,203,203, 68,215,166, 72,
+114,183, 95,156,227,173,149, 84,171, 51, 30, 74, 27, 67, 12,173, 36, 52,203, 81,219,102, 60, 68,130,144,203,109,165, 36,133,120,
+138,212,193, 31, 77,212,144, 72, 34,198,251, 27,245, 44, 15,154,214, 6,230,224,239,182,149, 3, 21, 18,113, 76, 43, 65, 3, 50,
+137,214, 49, 12, 40,135,117,121, 29,209,158, 71,223, 75, 42, 46,136,204,108, 8,145,132, 74,193,144, 72, 75, 74,213, 54, 21, 45,
+ 76, 91,246,218, 94,139, 17,193, 28, 86, 29, 14, 46,115,208,212,249, 67, 77, 64,167, 72,144, 20,185,149,135,226,180,158,101,145,
+202,195, 40, 83,141,144,227,200, 2,245, 21,216, 52, 92,248, 96, 70,161, 83,252,103, 98,197,145, 15,156,115, 78,109, 49, 66,157,
+109, 1,110,205,152,167, 16,175,119, 65,203,206,130,172,229, 69, 42, 23, 85,184,213, 38,116,122, 77, 49, 30,243,112, 48,191,122,
+156,175, 0,120, 52,218,131,205, 97, 18,106, 83,146,149, 4,194, 76, 0,146, 91, 88,241,164,101, 41,109,188,184, 10,126, 34,216,
+ 84, 0,137,213,234,155,149, 73,236,160, 76, 76,164,176,212,104,116,198,150,183, 7,131, 18, 42, 93,229,167,198,253, 69, 23,214,
+ 76,149,151, 57, 71,195,200,157,109, 69, 33, 82,243, 60,133,180,234,176,248,250,244,211,107, 91,226, 72,211,167,112,188,181,209,
+ 76,160,213,204,197,106, 0, 96, 24,179, 79, 82,204, 72, 51,121,144,128, 10,249, 98,149,218,225, 28,149, 89, 27,152,205, 94,144,
+220,249, 80,209, 79,171, 70, 91, 20,181,184,135, 92,141, 50, 72, 14, 84, 76,118, 19, 36, 34,177, 25,151, 21,138,119,187,114, 19,
+ 21, 68, 12,117,150,149,132,150,213,150, 54, 98,220,136, 16,188,119,163, 67,101, 5,113,196,105, 72,165,185, 82,119,197, 5,126,
+248,228,114,219,144,233,141, 70, 67,104,106, 56, 82,124, 82, 79,136,218, 88, 9,105, 88,156,247,222,169, 82,227,191, 45,232,212,
+218, 11, 78, 71, 98, 59,143,161,113, 39, 84, 75, 46,153, 13, 76,172, 45,229,243, 37,135, 29,104,251,180, 52,101,110, 6,210,236,
+148,169, 74, 12,138,140, 74,153, 50, 51,206, 33,177, 76,164,162, 59, 73,171, 73, 72,104, 78,168,197,125,231,124, 63, 6, 48,109,
+102,142,200, 60,234, 28,229, 82, 93, 7,244,104,105, 39, 91,241,105,141, 99, 37,254,169,195, 11, 90,214,220,144, 53, 30,151,233,
+216, 2, 62,226,207, 81, 79, 37, 64, 53, 1,150,150,100,144,129,164,144,145, 57, 33,117, 0, 73,102,157,197,144,162,146,201,229,
+185, 91, 7,133,199,163,200,101, 79,198,131, 70,106, 76,183, 83, 33, 17, 40,212,166, 60, 24,241,189,234, 27,101,247,106, 85,121,
+ 13, 51,138, 77, 9,190, 85, 34, 58,146,217, 82,185,213,225,182,227,202,108, 33,244,163, 51, 30,132, 13,122,179, 61, 46,206,167,
+178,218,106, 21, 83, 17,198,105,113, 16,255, 0,130,203, 84,152, 48,121,220,112, 58, 60, 70,144,219, 72, 14,202,154,226, 91, 75,
+137,117,229,164, 37,133,166, 84,233, 54,205, 18,152, 42, 78, 72, 74,100, 38,109, 70,157, 75,167,176,101,215,110,185, 45,168,183,
+ 26, 21, 45,132, 58, 22,233, 81, 25, 47, 73, 45, 70,101, 9, 42,121,228, 37, 28,165,217,183, 32,206,171, 85,105,149,250,165, 82,
+149, 14, 75, 94, 12,218, 69,174,167, 26, 93, 42,136,182,199, 51,171,157, 33,213,135,234, 53, 63, 17,100,187, 57, 41,104, 33, 40,
+ 8,142,218, 24, 74,121,221,169, 86, 22, 72,193,212,205, 96,202, 46, 67, 48,184, 22, 31,101,130,133,184, 4, 88, 49, 35, 72,181,
+216, 86, 28, 81, 1,116,150, 73, 25,169,242,225,205, 66,229, 73,146,164,163,105,104,209,130,181,131, 0, 76,135, 75, 68,143,118,
+149,228,145, 98,129, 95,138, 36,233,202,152,138,141, 93,169,141, 69, 80, 30,227, 5,244, 43,222, 82,165, 36,243, 74,171,176,208,
+ 41,106,160,226,222, 82, 83, 28,169, 98, 40, 10, 73, 90,220,201, 68, 52,254,150,111, 2,144,225,187,179,158,209,187, 10,132,211,
+ 79,213,165, 82,118, 15,137, 25, 20,246,210,148, 75, 91,140,190,246,200, 95,117, 36, 32,115, 57, 41, 10,102,175,109,202,146,122,
+ 41, 18,232,108, 40,225,134,134,166, 17, 71,172, 75,173,183,254, 28,202,224,136, 19,125,223,220,189,237,247, 37, 21,179, 37,214,
+ 81, 80,121,191, 1, 45, 16,166,130, 31,105, 33,106, 75, 76,149, 56,163,206,177,200,205,113,141,195,133, 51,141, 78, 12,248,147,
+225,150,176,148, 59, 23,119,182,166,230,182,237, 57, 15, 97,150,105,151,140, 70, 87, 85,176,107,200, 50, 27,253, 3,177,111, 58,
+ 93,191, 49,181, 28, 41, 2, 57, 60,193, 74,200,158,100,149,102, 22,210,191, 88,166,198,203,123,107, 2,250, 84, 17,179, 17,170,
+ 37, 36, 88, 6, 45,176, 1,135, 60,241, 94, 80,210,197, 55, 50, 52,167,146, 27, 38,149,177,141,119,250,189, 44, 46, 13,254,219,
+ 16,222,117, 4,220,220,223,242, 16, 41, 10, 0,121,103, 35, 29, 63, 35,174,144, 0,146,129,231,232,122,252,251,246,242,213,103,
+105,213, 58, 52,201,244, 90,252, 69,192,174,208,170, 53, 26, 21,114, 3,128,135, 96, 86,232,211, 30,166, 85,233,238,115, 96,133,
+177, 82,139, 41,165,103,205,147,175, 33, 3, 57, 79,194, 14, 78,124,199,203,236,212,253, 72, 96, 25, 78,160, 70,198,251, 27,216,
+220, 31, 76, 83,251,247, 22, 56,241,142, 65,215,160,207, 76,143, 35,229,243,210, 78, 79,144, 72, 39,250,186,145,142,218,250, 74,
+136, 25,198,115,208,129,220,124,245,247, 36,146,124,191,217,244,236,126,205,103,127,191, 3, 30, 72,200,230,229,206, 58,121, 15,
+199,215,251,117,236, 5, 31,245, 72,242, 7,190, 62,223, 76,233,114,133,144,114,164,245,198, 7, 65,219,215,238,215,190, 92,127,
+ 56,224,103, 31, 47,191,211, 67,221,233,129,138, 43, 71,124,156, 15,196, 14,221,186,244,208,171, 3, 3,191,166, 64,201,249,119,
+249,234,232,212, 41,147, 22,132, 71,105, 74, 46,186,134, 91, 32, 16, 29,125,194, 18,211, 12,249,188,250,213,209, 40, 72, 43, 89,
+ 56, 72, 39,166,186, 71,195,191,178, 43,142,110, 36, 99,196,171,219, 27, 61, 83,178,237, 25, 97,151, 26,188,247, 98, 90, 54,206,
+131, 38, 59,229, 63,225, 52,182,171,241,205, 66,178,148, 52,175, 16,166, 60, 5,115, 36, 97, 43,202,147,157,121,171, 41,169,236,
+ 37,148, 43, 55, 69,234,199,224,162,228,159,112,198,205, 37, 29, 93,124,188,138, 26, 89, 43, 38, 29, 86, 36,103, 32,122,182,144,
+116,143,123, 88,123,241,204, 5,140,156, 36,231, 29,252,135,224,124,251,232,117, 0, 14, 70, 1, 7, 7,183,159,203,207,166,117,
+177,124, 80,240,223,126,112,157,189,183,214,195,110,107, 49,211,119,216, 53, 54, 96,207,155, 77, 84,151,104,213,200,115,224,199,
+169,209,174, 75,118, 76,184,204,185, 50,223,157, 79,148,219,177,157,113,166,212, 74, 28, 66,144, 20,218,181,174,203,234, 48, 7,
+159, 79, 94,255, 0,111, 83,141,108, 83,203, 28,200,146,198,218,163,144, 2, 58,142,190,160,216,223,220, 69,240,155,199, 36, 18,
+203, 12,200, 98,158, 22,100,116, 59, 50,178,157, 44,164, 14,132, 16, 65,247,140, 12,160, 58, 18,122, 12,253,253, 63,179, 67,171,
+168,200, 61, 58,140,249,227,207,167,231,182,138, 63,173,208, 17,223,167,203, 25,201,252, 53, 69, 64, 1,142,253,115,246, 15, 67,
+173,144,108, 65,244,198, 70,227,125,199,254, 48, 26,129,245, 28,189,186,140,125,224,250,245,208,171,192,201, 25, 7,255, 0,104,
+122,103, 69,184, 70, 72, 57, 0, 30,195, 29,124,186,126, 31,179, 66, 47, 62,163, 30,158,121,249,116,210,202, 73, 23, 56, 0,108,
+ 61, 54,192,202,193,193,193, 4,247,206,116, 58,199,159,175, 67,233,162, 87,235,229,140,122, 96,250,252,244, 58,129,201,200,200,
+251,113,131,219, 56,209,199,198,216, 54, 6, 88, 0,100, 39,175,203,167,231,251, 52, 43,131, 39, 36, 2, 64,236, 58,254, 63, 61,
+ 22,231, 76,100,244,201,251, 60,134,132, 80, 30,188,221,127,104,193,245,251, 52,170,155,223,107, 91, 25, 22,223, 2, 44, 12, 18,
+ 70, 49,219,212,117,237,161, 87,243,234, 15,111, 44, 31, 92,249,249,232,197,140,103,249,222,127,105,251, 6,133,115, 24,236,123,
+246,244,239,223,229,165,147, 10,139, 27,123,190,126,126,252, 12,188,246,199, 76,103, 62,152,254,142,154, 13,206,249,201, 78, 51,
+156,140,231,211, 31, 46,250, 49,194, 2,122,244,243,207,151, 79, 93, 90,212,167,148,162, 20, 50,159, 34,158,248, 35,184,244,210,
+152, 2,247, 55,232, 48, 59,171, 82, 85,220,156,231,177,199, 79,179, 75, 84,137, 89, 82,129, 64,192, 61, 9,238,125,123,157, 45,
+ 11,159, 92,102,195,211, 7, 1,145,228, 49,230,115,215,175,153,251,245, 85, 41,199, 65,212,158,255, 0,159, 77, 82, 78,114, 7,
+145,207, 79, 35,223,203,237, 26, 37, 0,231, 61, 49,231,219,242, 53,130, 1,198,113, 85,164, 37, 39, 24, 29, 70, 51,230,123,121,
+232,129,156,245, 31, 8, 29,193,235,233,231,223,190,169,163, 29,176, 58,117, 7, 26,244,121,242, 2, 82, 20, 60,250,224,142,189,
+251,246,210, 76, 0,248,223, 3, 5, 39, 29, 51,146, 59,252,240,123,103,174,138, 64,206, 8, 35, 31,183,240,208,109, 54, 70, 78,
+ 78, 73,235,147,144, 6, 78, 6, 51,215, 70,163, 57,233,142,157,199,203,229,162, 27,218,255, 0,203,124, 17,187,155,224,134,240,
+161,156,231,174, 64,235,211, 29, 63,164,104,132,168,143, 60, 14,199, 24,243,245,249,127, 86,168,160, 96,103,207,203,243,246,141,
+ 16,132,224,228,245, 7,174, 63,160,231,215, 73, 16, 5,253,223, 39, 9, 28, 86, 71,127, 62,223,143,231, 58, 44, 1,220,122, 99,
+160,192,252, 52, 58, 82, 7,219,143,207,238,213, 86,242,162, 60,134,112, 57,142, 0,243, 42, 62,128, 12,232,167, 5, 97,182,231,
+108,101, 54,149,175, 93,188,238, 42, 37,171,108, 82,103,215,174, 43,142,169, 10,139, 68,162,210,216, 92,170,133, 82,169, 80,121,
+ 49,225, 64,134,195, 96,151, 31,113,229,164,118,194, 70, 84, 72, 0,157, 78, 55,217,195,236,235,180, 56, 5,219,136,183,189,229,
+ 6,143,114,241,101,120,210,144,245,197,112,186,195, 83, 99,109,101, 38,115, 41,113, 22, 77,152,167, 82, 66, 42, 9, 66,147,245,
+132,212, 0,227,174,130,132,144,210, 64, 58, 65,236, 48,224, 78,145,183,150, 91, 28,115,238,229, 25, 47, 93, 23, 10,101,211,120,
+127,163, 84,163,165, 73,163,211, 57, 87, 30,165,184, 46, 48,226, 73, 76,201, 4, 45,184,107, 35, 40,101, 37,105, 33, 78,103, 93,
+206,171,207,168, 77,158,242,214,234,165,120,206, 45,240,239, 57, 83,188,203, 36,252, 62,157, 9,239,170, 51,196, 46, 48,105, 37,
+147, 42,160,151, 76, 16,146, 37, 96,109,169,129, 27, 92,118, 83,208,119, 32,181,143,145,135,112,125, 25,188, 13,143, 54, 16,113,
+223, 19, 82,137, 17,172,244, 16, 72, 60,170,157,125,165,213,191, 93,246, 49,126,194, 16,247,212,254, 92,102,175, 95,155, 82, 46,
+162,100,151,208,236,151, 84, 86,135,157, 83,143, 45, 96,146, 94,142,181, 28,149, 31,231, 39, 61,245, 66,141,115,205,137, 57,175,
+ 1,247, 75, 76, 35,195, 76,148, 41, 72,125, 46, 37, 67,149, 50, 80, 63, 89,178,122,100,246, 29,245,245,218, 59,147,164, 45, 78,
+ 62,215, 50,202,148,134,101,254,133,244, 62,145,140,180,188,124, 11, 56,232, 71, 67,171, 83,148,233, 49,170, 13,190,247,248, 44,
+245,182, 90,104, 56,144,150, 39, 33, 63, 10,154,125, 67,225,241, 20,158,202,245,193,243,213, 56,106, 88,146,193,203,105,235,239,
+ 59, 19,191,201,199,127,158, 23,202,218,157,233,146, 24,236, 81,136, 80, 46, 1, 43,107,143, 46,174,130,197,183, 3,169,212, 47,
+102, 23,138, 45,142,166,222, 16, 42, 27,183,108,211, 81, 10,232,163, 70,247,155,186,155, 13,174, 83, 92,132, 0, 8,170,165,134,
+192, 6,115, 39, 5,106, 72,203,136, 86, 73,233,166,207,131,205,208,115,108,174, 89,118,133,206,234,163,216, 59,146,166, 20,169,
+ 42, 82,136,161, 93, 77,252, 49, 42, 33, 4,225,182,215,204,148,185,216, 20,171, 61,198,186, 27,110,114,132,166, 53, 69,148, 59,
+ 30, 90, 23, 25,101,236,171,154, 43,201,240,223,133, 36, 17,241, 35,145, 74,229, 39,161,215, 63,238,253,167,145,106,238,109,193,
+110,177, 27,154,158,103,166,165, 71,109,208, 75, 65,135,207,188, 66,117,149,227,252,159, 41,228,233,219, 3, 75,181, 66,188,109,
+ 27,157, 72,221, 61,223,199, 99,123,219,220, 65,219,108, 51,192, 88,210, 85,228, 53,174, 76,116,104, 30,157,201,185,229, 35, 0,
+ 2, 19,125,224,147, 75, 37,239,101, 33, 13,213, 69,250,103,114, 80, 10,102,173, 46, 58,164,199,113,180,212,163,184,159,141, 18,
+ 38,180,144, 27,150,219,136,255, 0, 40,194,218,193,244,234, 52, 13, 53,152, 76, 85,228, 75,126, 75,175, 83,218,112,212,170, 11,
+111, 28,170,135, 77,132,169, 78,242,115, 15,209,175, 45,242,143,153,236,117,227, 97,231, 85,171,148, 38,109,155,155,154, 91, 20,
+248,232,126,139, 84, 87,199, 38, 34, 85,134,223,163, 74, 82,186,185, 28, 40,126,141, 95,205, 7, 30, 67, 69,110,125, 33,219, 19,
+109,119, 58,172, 90, 66, 93,116, 66,166,211,214,225, 63,160,250,214, 82, 3,169, 64,233,241,150, 27,112, 39,168, 3,155, 62, 88,
+ 58,244,144,243,106,233,148, 11,197, 35,128,123,129,109,205,246,238, 6,199,184,235,108, 71, 42,184,155,216,242,188,198,154,162,
+ 95,237,180,208,232,140, 11, 90, 66,236,136,172,189,245, 3,160,145,212, 16,122,249, 73,227,159, 17,187,137, 50,231,190,101, 63,
+ 18,112,228,140,252,162,176, 30, 62, 10,228, 73, 82,164, 22, 95, 72, 63, 2, 91, 10, 66, 22,112, 8, 82, 66,185,126, 28, 29, 79,
+145, 81, 80,168, 42, 68,213, 63, 12, 37,188, 63, 45,130,209,128,132,156,150, 26, 75,203, 73, 74,254, 39, 10,138, 92, 67,124,164,
+229, 42, 25, 25,186,221,245, 35, 87,185, 43, 18,155, 90,227, 77,126,164,251,143, 7,129,118, 51,188,178, 11,120,144,148,242,135,
+ 91,232, 71, 50, 10, 92, 36, 36, 39,211, 88,139,213,131, 77,117,196,212, 27, 16,219, 83,220,225,196,169, 47,211,101,161, 71,194,
+ 11, 92,133, 4,174, 9, 66,203,105,113,183,145,240,248,193,124,202,108,130, 38, 34, 59,179, 29,137,125,253,230,246, 63,127,165,
+250, 13,186, 11,218,248,225,108,186, 60,159, 36,202,104, 33, 80,239, 79, 18, 6,232, 36, 44,108,206, 88,216,171,134,102, 58,137,
+189,193,232,183,182, 51,138,107,197,167, 35,145, 32,194, 75,137, 45,162,170,204,129, 26, 59,172, 0, 57, 16,250, 88, 42, 67,173,
+168, 44,132, 33, 97,105, 81, 89,194,193,192, 15, 21,183, 34, 93,189, 17,133,173,196,213, 88,150,133,188,239, 51, 44,199,149, 29,
+ 45,142, 86,210, 82,135, 2, 38, 68,112,144,144,148,168, 41, 39, 32,133, 0, 2, 89,200, 80,154,117,109,186,212,100,199,139, 80,
+101, 13, 33,216, 78,199,114, 51,238, 37, 74, 91, 78,189, 27,148,178,231, 80,164,172,130, 9, 41,201,238, 14,179,250, 11, 83,227,
+182,194,154,145, 2,161, 25,212,187, 44,196, 66,213, 18,124,111, 5,107,100,166, 20,148,169,198,211, 12,115,175,153, 42, 74, 80,
+ 70, 78, 78, 51,166,186,192,172,178, 6,109,136,220,117,189,189,227,117,177, 30,160, 27,119,233,139, 14,158,162, 39,142, 0,101,
+ 66, 93,128, 10,247, 70,216,130,108,214,176, 96,108, 65,243, 95,175,187, 27, 7,111,210, 27,168,182,211,116,199,151, 78, 75,232,
+110, 83,209,169,177, 26,125, 10,125, 72, 91,143,187, 34, 34,142, 34,172, 0,129,128,132, 45, 73, 72, 9, 43, 56, 80,206,163,202,
+184,216,125,223, 26,158,154,225, 56, 80,114,142,180, 69,150,162,178,150,227, 46, 61, 62,106,200, 76,129,146, 74, 91,146, 28, 87,
+ 54, 67,121, 73,211, 37, 69,159, 9, 83, 19, 42,175, 34,171, 13,106, 74,227,154,156, 84,200, 79,185,120,108,229,135, 25,169, 81,
+213,250, 96,176,134,208,128, 65, 64,248,130,145,141, 58,116, 74,219,236,148,159,175, 97, 86, 33,180,182, 20, 87, 17,108,199,169,
+180,216, 91,106, 47, 79,130,128, 61,245,230,208,113,204,207, 34,215,156,148,247,212, 94,170, 25,163,109,148, 76,140, 5,245, 41,
+218,254,142, 8,213,107,116, 44, 47, 97,229, 55,198,205, 75, 85, 29, 71,255, 0, 73, 68, 85, 96,178,164,159,111, 98,202,179, 71,
+229, 98, 69,134,130,202, 77,238, 0, 83, 96,239, 82,107, 84,106,164,152,205,214, 16,245, 17, 75,247,101, 22, 43, 1,232, 83,105,
+203,136,165, 50,229, 98, 34,151,202, 17,226, 61,202,145,202,178, 48,162,146,142,250,216,251,105,128,186, 36,170,100,211, 22, 67,
+ 77,176,209,122, 60,214,153,145, 30,167, 10, 65,240,214,164,164,158, 79, 13, 73, 45,115, 37,224,181, 33,120, 81,230, 79, 42,131,
+ 59, 69, 16,106,201,139, 50, 64,129, 87,142,243,161,150,146, 80,211,168, 90, 71,134,148, 54,236, 25, 3,150, 43,129, 5,101,229,
+ 41, 92,199,162, 51,130,112,245,208,236,136, 14, 52, 88,165, 63, 50,139, 34, 51,197,246, 98, 51,239, 14, 83,216, 91,139,113,121,
+ 76, 73,110,172, 58,223, 48, 72, 13,160,134,135,112,144, 6,154,194, 70, 23,117,229,143,129,216,236, 71, 80, 47, 96,118,184, 4,
+222,231,114, 6, 41,222, 44,205,105, 4, 73, 28,205, 45, 7, 45,193,177,250,212,141,149,187, 31, 44,137,107,144,124,172,109,102,
+184,117, 1,243, 59, 82,158,154, 90, 88,167,200,142,181,210,164,169,181, 70, 81, 89,144,237, 61,164, 97, 8,142, 95, 89, 89,114,
+156,227,128, 6,143, 58,148,202,185,146,172,161, 73, 41, 58,230,163,187, 82,190,163,190,164, 15,240, 15,170, 97, 12,245, 79, 47,
+184,169, 46, 41,174,193, 14,169,111,140,231,161, 40,198,122,227, 89, 5, 18, 3,176,154,143, 6,166,202, 9, 1, 73,143, 61,174,
+116,199,117, 99, 11,126, 47,134, 18, 84,193,229, 10, 37, 10, 37,180,225, 64, 40, 28, 13,100,168,166,120,245,217, 15,133,120,168,
+146,220, 87,219, 46, 28,171, 6, 52,112,158,128,225, 60,175, 70, 87,197,205,140, 40, 16,112, 64,214, 42,193, 90,101, 10,126,211,
+169,184,233,123, 31,188,110, 72,220, 3,125,207, 67,138, 55, 49,206,155,219,234, 42,132,129,216,197, 32, 46, 15,145,195, 50, 2,
+235,191, 86, 80, 85,250, 18, 70,227, 86,166, 57,149,157,109,178,148,183,224, 71, 1,183, 35,200,142,217, 40, 25, 72,109,212,201,
+ 82,185, 20,122,144,165,158,100,158,128,171, 25,198, 50,253,209, 40,136, 75,137, 56, 90, 16,244,102,139,216, 60,229, 92,174, 20,
+160, 14,224, 59,241,225, 62,105,200,244,214, 51,107,195,108,165,151, 16,146, 22, 20,133, 20, 2, 74, 64,121, 60,138, 65, 87, 76,
+ 96,117,207,114, 8,243, 3, 79, 5, 53,182,146, 64, 57,193,111,145, 35,178, 84, 80,226, 28,232,165,126,162,177,219, 31,234, 19,
+220,105,223, 44,132,121, 88,223, 77,198,253,250,119, 62,253,247,252,113, 75,113, 30,119, 60,175, 32, 4,249,186,239,191, 91,252,
+ 54,176,222,214,184,191,174, 50, 89, 20,195, 81,143, 72,144,180,173, 79,134, 84,226,176, 3,206, 10,131, 10, 49,156,120,149, 12,
+182, 3, 33,100, 31, 37,188, 73,238, 14,172, 46, 81, 36,215,106, 78,136, 82, 13, 46,159, 29,244,173,218,140, 98, 3,147, 86,130,
+148, 42,159, 79,101,212,148,184, 90, 82, 9,117,242, 64, 39,157,182, 86, 64, 39, 89,163,142, 4,210, 26,113,106,112, 18,169,104,
+109, 13,148, 32,151, 20,219, 9, 95, 85,156,163, 43, 88, 5, 64, 16, 3,157, 50, 73,215,199, 43, 45, 65, 83,113, 91, 14,161,136,
+145, 25, 84,196,198, 1,231, 22, 91, 74, 20,150,219,107, 33, 42,116,156, 18,165, 16, 57, 84, 58,142,131, 82, 86,141,140,129, 80,
+ 14, 99, 42, 29,250, 93,128, 39, 98, 55,238, 64,233, 99,214,219, 98,176,130,186,186, 61, 66,153, 3,200, 12,138,151, 0,172,107,
+174,228,216,130, 24,139,170,168, 32,128, 73,218,246, 35, 9,159, 71,167,209,161,120, 20,248,236,194,134,100,203, 91,178, 29, 95,
+186,251,203,202, 90, 28,149, 81,118, 76,215,143,188, 39,196, 74,202,151, 33, 97, 35,155,151,196, 40, 72,195, 37, 84,174, 73,169,
+ 84,154,106,129, 77, 18,105, 49, 10,229, 68,157, 80,241,218,102,167, 32,224, 55, 84, 90, 25,111,222,102,198, 15, 5,251,154, 64,
+109, 11,229, 46,180,231, 39, 33, 15,133, 74, 59,117,246,189,234,168,242, 95,136,212,199, 36,199,182,218,105,167,105,241,249, 74,
+146,211,181,151, 92, 73, 53, 87, 2,149,206,150, 9, 76, 54,221, 64, 80,109,197, 32, 43, 88,189, 94,149, 6, 43,205,191, 86,230,
+247,217,135,221,162,211,216,142,170,140,185,124,205,173, 45, 70,131, 10, 58,124,106,140,226, 75,124,160, 0,202, 50, 8, 82, 18,
+ 57,198,220, 72,224,134,210, 45,176,191, 96,122, 95,208, 6,189,206,219,216, 29,247,196,207, 33,174,134,153,155,219, 85,171,171,
+156, 48,220,187, 89,207, 83, 96, 67, 75, 32, 91,221,193, 17, 45,216,175, 48, 50,178,224, 84, 74, 44,154,236,184,109, 72,113,234,
+237,116,165,197,177, 54, 82,143,185,194,138,164,184,249, 16,105,241,143, 44,103,208,121, 50,164,146,226,240,182,220,119, 4,235,
+ 37,164, 65,153, 92, 80,137,106, 70,139, 82,125,151,164,197,155, 93,168,123,196,123, 46,150,251, 8,240,252, 17,238, 40, 42,185,
+170,222, 34,155, 80,141, 16,150, 88,230, 75,114,101, 51,130,141,103,113,118,222, 84,228,199,126,232, 95,240,106,136, 16,215,189,
+218, 86,235,201, 53,185, 52,220,146, 81,114, 92,236, 97, 49, 90,112,128, 36,194,166, 1,146,181, 52,236,199,138, 84, 53,147, 85,
+149, 73,182, 92,129, 6,223,109, 81,169,207,198,147, 79,163, 83, 41,232, 5, 82, 81, 29,145,152,108,180,165, 54, 91,134,211,156,
+200,113,210, 18,218, 3,193,103,153, 99, 39,101,145,165, 85,144, 39, 49,211,208,128,187,218,251,146, 58, 53,134,171, 94,215, 4,
+ 88,173,147,175,226,120,170,103,246,122, 6, 21,149, 44, 27, 66,168,189, 44, 37, 67, 23, 6, 68, 33, 36, 54, 58,210, 58,127,236,
+202,171,173,165,149, 12,145, 11, 77, 10,223,167, 90, 47,203,153, 93,154, 39,203,117,178,229, 86,225,153, 22, 43, 10, 90,217, 97,
+108,173,148, 73,109,194,197, 34,138,149,128, 98,176,158, 86, 18,160,180, 32,169,197, 18,171,243, 12, 71,188, 39, 42,174,205, 61,
+ 18, 45, 72,169, 45, 52,144,181, 82, 30,158,238, 86,184,179,219,134,160,218,163, 82,146,160,225,109, 14, 58,219,178, 20, 76,135,
+249, 18, 91,109, 56,227,176, 25,153, 75,137, 81,185,166,184,212, 78, 68,193,165, 81, 33, 56, 20,195, 85, 39, 10, 11, 82,165, 48,
+193, 47, 87,234,137,240,209,202,128,158, 72,168, 70, 91, 66, 74,214,240,187,209,162, 25,147, 29,241, 80,243, 20, 40, 45,185, 21,
+234,107,146, 57,170,243,146,235,172,178,227, 19,125,225,132, 36,196, 91,197, 42, 68,112,151, 28, 82, 94, 80,113,210, 62, 13, 58,
+210,106, 66,183, 75, 35, 17,168,117, 97,109,198,228, 16,111,212,237,190,224, 90,197,113, 23,172,103,117,158,190, 74,182,147, 48,
+ 80, 99,105, 64,211, 10, 1,101,209, 78,168, 99, 38,107,105,141, 52, 17, 20, 68,221,110,162, 55, 14,212, 81, 18,171, 73, 69, 54,
+151, 80,170,193,183,229,135,231, 85, 42,149, 41, 47, 79,143, 80,247, 20, 52,203, 16, 98,229,240,126,168,115,170, 31,125, 39,149,
+208,202, 26, 10, 40,231,230,113,232, 15, 68,139, 87,166, 53, 26, 60,198, 94,122, 51, 68, 71,148,250,148, 25,103, 63,162, 83,229,
+ 41, 41, 99, 37, 69, 44,160, 37, 60,201,103,152,129,206, 20, 27,135, 43, 8,141, 22,153, 2,220,110, 28,171,174,170,134, 89,142,
+153,169, 66, 35,209, 88,108,174, 57,126, 80,125, 99,220, 96,135, 91,113, 92,141,161, 33,199, 27, 75,101, 92,216, 34,241, 2, 53,
+ 62,152,134,101, 34,161, 49,233,206,169,137,117, 56,178,156, 90,231, 45,245,190, 29,112,130,215,199,159, 17, 9,113, 10, 64, 72,
+240,130, 80, 82, 83,212, 76,105, 31,217,222, 25, 64,230,104, 8,110,162,224, 1,102,223, 85,193, 99,246,172,183, 96, 73,103, 47,
+101, 81, 84,230, 84,205, 52, 18,164,134, 72,163,156,202, 35,140,221,164,118, 98, 85,165,150,214,109, 39, 74,162, 72,246, 71,229,
+ 5, 65, 26,139,159,203,207,219, 83,176,204,240,223,237, 79,227, 35,111, 41,204, 69,139, 67,175,238, 80,222, 59, 98, 36, 38,195,
+113,161,208,183,162,149, 7,112,132, 52,182,144, 3,101,170,213,102,182,215, 40,232,148,176,158,221,135, 48, 73, 36,100, 96, 99,
+184, 61,250,246,212,159, 62,150, 45,137, 6,222,246,135,108,254,224, 66, 67,137,123,117, 56, 94,183,220,168,135, 22,209, 74,230,
+ 88, 87,181,215, 66,109,109,161,180, 2,209, 52,250,172, 0,176,165, 45, 68,165, 61, 64, 1, 34, 48, 64,228, 21, 18, 15,251, 56,
+236,115,211, 86, 37, 3,171, 82, 68, 23,236, 70, 90, 53,182,195, 76,108,209,131,111, 66, 22,227,189,136,190,247,199, 60,230, 49,
+152,171,170, 80,253,162,193,143,184,200,162, 66, 62,237, 86,255, 0, 76,120, 41,206, 48,160,113,145,142,217,207,150, 15,125,123,
+ 0,227,148, 14, 92,116, 63,209,247,244,215,220, 39, 25, 35,191, 83,230, 71,159,125, 87,109,178,242,146,134, 70, 92, 87, 96,172,
+ 36, 4,128, 84,165, 45, 71,162, 80, 0, 36,146,112, 0,201,233,173,195,210,228,218,223,187, 26, 93,174,118,199,134, 90,117,213,
+ 33,166,208,167, 28, 90,185, 80,132, 2,165, 40,158,192, 1,174,165,240, 33,236,163,226, 11,141,133,195,187,161,181, 31,108, 54,
+ 57,185,170,102,161,188,215,148, 9, 46,210, 42,138,140,234, 81, 54,157,182,214,243, 78, 53, 39,113, 42,232,234,133, 62,203,140,
+ 81,226,186,164,251,205, 65, 68, 45,141,111,127,178,155,217, 11, 7,117,232,244, 30, 38,184,174,161,203,107,103,231,248, 21,109,
+173,218, 73,190,241, 78,168,239, 51, 13,168,169,155,182,242,228, 90, 36, 81,246,136,186,131,238,144,210, 90,151,113,134,203,171,
+ 91, 20,149, 36,203,150,181, 2, 36, 72,241, 41,180,202,125, 62, 5, 42,149, 74,131, 14,149, 68,162, 82,162, 70,166,209,168,180,
+168,109, 37,152, 52,202, 93, 50, 19, 72, 98,155, 79, 98, 58, 66, 90, 97,150,208,219,105, 24, 66, 83,166, 25,243, 9, 42, 36, 48,
+211, 63, 42, 59,216,200, 44, 75, 90,215, 17,131,112, 7, 91,187, 2, 54,178,171, 92,178, 89,124, 43,192, 18,102, 49, 69,153,103,
+ 74,240,208,200, 3, 69, 2,157, 18, 76,166,196, 60,141,179, 69, 19, 15,178, 22,210, 56, 58,131, 70,186, 89,244,203,132,143,102,
+ 23, 8,220, 37,199,165,207,176,182,222, 37,237,184,240,218, 71,188,239, 38,234, 68,167,221, 55,203,178, 8, 5,199,104, 48,157,
+143,245,101,141, 16,184, 57,155,143, 75,138,210,217, 36,230, 83,228,243,158,151, 69,160,187, 49,126, 36,133, 58,235,129, 35, 46,
+ 60, 86,226,143, 94,131,153, 68,246, 24, 3,200,118,213,202,135, 74,248, 27, 28,132,168,164, 41, 71, 3, 60,167,178,137,239,204,
+123, 15, 64, 52,232,211,232,248, 74, 64, 64, 35, 29, 71,146, 73,235,146,113,212, 96,254,205,107, 90, 40, 75,114,198,159, 86, 38,
+236,109,251, 76, 73, 38,219,253,162,109,208, 91, 22,226, 81, 83,208,192,148,180,116,233, 71, 78,189, 18, 53, 84, 94,219,144,182,
+187, 30,236,110,205,212,155,226, 36,191, 73,131,133,184, 14,237,254,198,241,107, 70,166, 37,170,205, 10,172,246,199,238, 12,230,
+ 90, 72, 51,232,213, 6,101, 92, 59,127, 50,122,210, 50,227,241,167, 51, 87,134,218,213,158, 86,166, 6,193, 0, 1,168,116,169,
+ 41, 33, 39,204,245,237,215, 39,203,251,117,250, 82,251,111,182,226,159,122,123, 47,248,158, 68,212,183,205,103,209,237,109,192,
+166, 56,164,149,248, 53, 59, 98,234,166, 45,165,183,223,145, 74, 98,100,132,103,253, 85,145,219, 95,154,217, 61, 0, 4, 2, 74,
+134, 8, 61, 7, 49,198, 52,227,147, 73,255, 0,165, 66, 15,216,112,195,220, 36, 0,159,222,225,201,223,169,197, 33,199,180,137,
+ 77,196, 45, 34, 0, 5,116, 17, 74, 69,250,190,167,136,155,109, 98,194, 32,222,246, 36,247,192,206,116, 56, 35,174, 1,207,238,
+253,186, 25, 65, 61,243,212,246,243, 7, 26, 53,192, 0,199, 55, 83,220,158,189,254, 95,142,132, 88, 87, 83,128, 65,237,142,152,
+192,193, 56,199,174,159,241, 15,192, 46, 18, 50, 66,124,241,246,227,185,249,232, 98, 58,147,216,252,251, 39,236, 30, 90, 53,207,
+ 47,191, 65, 58, 65,207,175,110,189,250, 16, 14, 52,178,244, 30,252, 20,218,254,159,207,182, 5,112,227, 39,190, 51,142,131, 31,
+120,199, 78,154, 17, 68,242,243, 31,159, 40,251,126,126,154, 37, 72, 61,249,137,198,122,121,118,238,122,245,213, 5,161, 68,100,
+ 16,191, 34,124,135,231,247,232,227,183,207,254, 48,111,134, 5, 42, 36, 16, 71,124,114,231,182, 61,126,122, 29, 68,103, 25,234,
+ 1,232, 6, 0,235,229,162, 84,147,145,215,246,116, 0,106,130,240, 62,121,237,229,142,217,251,124,180,162,141,133,183, 31, 63,
+ 61,177,144, 1, 62,151,192,138, 73, 25,229, 57,201, 57,255, 0,103,240,208,221,251,232,197, 2, 50, 70, 0,235,156, 30,227, 61,
+ 50, 61,116, 50,192, 29,129,245, 39,203,236,252,116,170,117,249,219, 10, 40, 4,116,183,200,197,185,230,249,199, 41, 42,198, 70,
+ 82, 58,103, 25,238, 71,150,116, 51,141,184, 1,235,202, 2,112,144, 0, 36,143,159,167,158,174, 42, 0, 30,132,158,249,207,174,
+132,121,178,164,158, 85,169, 7, 39, 24,254,119,219,234, 51,165,176,110,158,235,226,222, 82,148,255, 0,148, 36,147,212, 99,211,
+208,244,239,165,175, 69,181,182, 0, 82,148,225, 61, 73,192,233,242,239,165,161, 99,233,140,227,210, 7, 92,249, 15,233,252,157,
+ 20,130, 49,129,223,185,251,245, 65, 32,224, 12,117,234, 63, 19,255, 0, 13, 86, 64,238,124,199, 76,122,104, 96, 96,148,167, 3,
+175, 66,127, 28,126,227,253, 90,168,210, 0,200, 56, 61,207, 79,158, 58,231,243,223, 84,210, 73,233,142,131,166,126,239,219,162,
+ 91, 73, 57,233,223,215,207,166,147,112, 55, 61,255, 0,241,129,143, 96,121,224,159,199,161,251,180, 91, 63, 23,113,203,215, 25,
+238,123, 13, 83,109, 35,160,235,215,175,223,141, 18,148,131,208,116,233,158,223,102,147,193, 77,141,238,118,193, 72, 79,216,122,
+118,249,250,227,203,207, 85,146, 1, 56, 61, 61, 49,251, 7,109, 14,216,230,198,125, 50,122, 99, 68,160, 2, 64,198,125, 63,225,
+164, 90,192,144, 62,122, 97, 28, 86, 29, 14, 58,140,121,159, 62,158,186,218,174, 11,120,121,159,197, 23, 18,123, 87,179,145,130,
+147, 79,185,110, 40,206,220,178, 66, 73, 76, 27, 74,150,164,207,184,229,172,143,213, 6,158,202,219, 7,253,105, 35, 90,172, 1,
+206,113,144, 59,143,159,245,234, 71,254,193,173,178, 98,146,141,245,226, 34,165, 22, 63,188, 82,169,144,118,234,211,150,250, 66,
+158, 98, 93, 83, 19,235,142, 70,200,253, 26,253,223,221, 91, 42, 24, 61,198,152, 56,151, 50, 57, 86, 77, 91, 84,173,166, 80,186,
+ 80,142,161,155,107,143,122,130, 91,254,220, 76, 56, 7,134, 79, 24,113,142, 65,195,218, 75, 67, 95, 58,243,173,255, 0, 2, 48,
+101,152, 92,116,213, 26, 20, 7,179, 48,196,149,103,214, 45,203,102,139, 77,179,109,136,172, 83,237,139, 54,149, 2,215,182,224,
+ 65, 9,106, 37, 62,145, 72,142,136, 76,165, 49,147,211, 5, 45,100,145,212,231, 39, 86,118,235, 42,143,200,227, 47, 37,210,234,
+ 18, 24, 83,124,167, 5,120, 37, 7, 39,169, 39, 31,142,154, 22,235,241,228,173,213, 7, 98,188,149,229,164,178,233,228, 89, 82,
+186, 30,101,122, 21,107, 39,167, 33,181,182,204, 85, 70,113,109, 7, 2,195,161,204,169,167, 50, 20, 18,130, 15,196, 61, 53,201,
+ 85,114,187,206,236,205,119,148,147,111,221,239,252,122, 91,240,246,231,132, 50, 26, 12,191, 43,166,165,142, 30, 84, 80,168, 93,
+ 32, 13, 58, 85, 84,105,177,176, 1,109,176, 91, 3,211, 99,135,136,196,145, 38, 52,105,210, 76,121, 79,186, 10, 76,117,169, 45,
+200, 65, 31,170,160, 65,233,140,104,132,199, 66,144,161, 62, 50,221,107,148,150,150,164,248,168,109, 67, 33, 74, 86, 6, 71,200,
+131,160, 41,209,224, 56, 99,202,116, 72, 15, 50,217, 66,222,125, 75, 64,192, 24, 0,163,205, 35,215,229,172,162, 35,108, 56,218,
+125,222,104, 97,121,193, 42, 81,113, 50, 18,162, 73, 1,181,118, 3, 58, 69,199,148,148, 66,227,107,244,216,237,190,219,127, 28,
+ 18,170, 83, 9, 43,230,178, 30,161, 74, 4,185, 54, 11,164,181,128, 27, 95, 77,200, 59,139, 97, 81,169,202,247,134,228, 67, 90,
+ 39, 71, 36, 55, 34, 19,199, 15, 6,193, 24, 91, 89,234,160, 7,109, 86,220,221,191, 69, 90, 85,181,115, 68, 96, 46, 68, 6,140,
+ 7,138,147,149,150, 82,160,166,208,188,140,168, 39, 39, 25,242,233,167, 58,137, 71,166,201,142,194,201,142,212,216,196, 6,229,
+ 50,121, 11,153, 61, 65, 3,161,199,207, 78,207,240,125,201,244,162,195,141,165,106, 65, 67,236,188,216,248, 92, 90, 48, 74, 84,
+ 7, 98, 83,144,126,221,106,152,228,100,145, 44, 64,101, 22,223,184,183, 79,141,173,235, 98,111,138,187,136,120,137, 99,171,130,
+101, 58, 30, 38,100,109, 86, 82,202,195, 78,228, 88, 56, 32,141,236,172, 58, 16,109,124, 91,182, 90,193,101,183,152, 82, 35,165,
+ 30,248,200,113, 65, 41, 9, 79,140, 82, 57,198, 49,211,152,245,251, 78,155,223,104, 77, 33,251, 91,135,122,140,200,202, 44, 42,
+ 69,199, 77,109, 75, 9, 39,197,247,120, 85, 7, 27,105,208, 6, 86,128,176,147,145,219,151, 56, 58,220,141,174,167, 53, 29,232,
+216, 70, 58, 14,152,232,133,143,214, 72, 31,205, 26, 97,253,170,148,143, 23,133, 86,229, 70, 46,101,187,202, 15, 56,105, 57, 89,
+ 75,148,154,162, 84, 79, 78,191,171,143, 92,159, 93, 75, 50, 90,104,205, 42,203,166,242, 70,111,241,189,135,243,239,235,142,124,
+204,184,154,105,248,255, 0, 33,161,119,211, 75, 85, 83, 4,100,118,176,147, 86,254,237,133,254, 24,136, 5, 65,227, 38, 82,145,
+202,226, 39, 41,110,184,151,185,156,241, 27, 46, 17,149,180,210, 23,200,250, 75,169,109, 32, 45, 42, 64,235,207,202,174,244,225,
+ 84,213, 6, 69, 67,223,225,189, 84,158,167,131,113,207,129, 29,150,216,138, 80,148,182,153,212,240,151, 19, 0,248,133,126,240,
+180,243,120,152, 79,110,128, 7, 61,166, 95, 74, 93, 83,147, 93,247,105, 92,175, 73,101,190, 69, 71,105, 74,202,153, 10,108,130,
+212,142,100,163, 40, 88,230, 36,130,160, 83,202, 52, 77, 26, 68,232,229, 30, 27, 79,123,184, 37, 79,205,166,196,101, 85,116,182,
+ 73, 71, 35,108, 72, 90, 68,166,220, 46, 4, 56,180, 23, 84,209, 5, 97, 7, 3,149,225,214,234,123,129,216,253,221,239,113,176,
+ 23, 3,174,219, 95,167,161,116,245, 3,200,177,221,159,162,132,176, 97,182,229, 73, 27,128, 53, 11,223,179, 1,176, 39, 14, 61,
+179,110, 49, 87, 92,138,164, 73,146,233,178,165,150, 16,227, 84, 69, 42, 50, 94,109, 10, 71, 71, 96,168, 22, 37,159,133,105, 75,
+193, 9, 83,132,168, 41, 95, 14,158, 74, 45, 26,235,147, 34, 76,184,244,134,171, 40,104,204, 83,146, 41,175, 68,162, 76,140, 26,
+117, 76,161, 51,233,207, 31, 0,115,161,149,165, 62, 10,135, 57, 87,234, 12,157, 54,148,138,123, 5, 81,133,159, 38,108, 39, 22,
+195,242,231, 68, 66,152,157, 2, 68,128,208, 83,174, 57, 5,247, 3,144, 18,140,142,105, 41, 91,107, 89, 89, 79,134, 84,158,109,
+108,157,156,170,253, 2, 24,110, 77, 1, 74, 65,106, 28,151,106, 52, 57, 77,206,132,236,118,255, 0, 72,150,159,167,169, 41,148,
+219,202,116, 37,124,170,241, 18,165, 16, 50, 10,136,212,110,190, 89, 0,102, 91, 57, 54, 10,173, 96,125, 45,246,150,247,176,217,
+ 88,139,245,185,184,195,137,205,164,100, 34,153, 99,169,146, 43, 14, 92,202, 82, 66,118,230,106, 62, 73, 25, 71, 75,134,111, 41,
+ 23, 70, 4, 1,238,148,138, 91, 79,179, 2,163, 42,161,107, 43,221,217,145, 13, 23, 52, 5,211, 28, 76,196,148,190, 35,243,188,
+223,129, 37,188,163,195,105,198, 94, 1,193,212, 37, 68,105,199,141,108,212,103, 60,153,146,233, 80,100,164, 73,113, 42,158,134,
+163,128, 66,210,128,223, 59,193,178, 90, 87, 40, 29, 82, 74,185, 79, 84,231,174,179,235, 33,170, 93, 82, 77, 65,154,147, 17, 46,
+ 76,178,176, 41, 85, 40,140, 45,104,144,248, 64, 74, 13, 62,115,105,115, 41,101, 46,164,185,225,171,144, 31,132,142,153,120,104,
+155, 91,103, 58,196,127,118,165, 59,108,201,150,211, 50,140,139, 86,167, 83,165,188,209, 10, 66, 17, 17,112, 22,243,140, 60, 16,
+ 72, 81,231, 97,105,115,147,153, 93,245, 22,146,172,134,180,138,209, 72, 58,244, 55,189,174, 71,217, 35,212,143, 54,251,139, 30,
+173,181,252,117, 14, 86,239, 28,240, 77, 72,225, 81,117, 42, 44,182, 50, 45,220,171, 22,130, 84,251, 42, 72, 28,237, 90, 65, 85,
+ 58, 66,227, 1,178,236,216, 17,129,148,194,170,116,121,146, 79,188, 38, 93, 38, 95,133, 10, 82,217, 78, 91, 18, 24,229,114, 60,
+196,167,194, 87,134, 28,105, 10,115,149, 65, 71, 7, 26,218,107,126,109, 90, 10,162,154,132,152, 21, 33, 32, 55,133, 48,201,165,
+212, 26, 80, 33, 63, 20,102,159,113,167,222, 82, 65, 82,130, 11,105, 73, 39,225,199, 46,172,180, 45,177,175,198,113,230,233,151,
+117, 62,124, 98,178,148,183, 92,183,144,196,137, 9, 81,248,202,103, 82, 28, 65,109, 73,194,146, 20, 24,229, 74,149,158, 83,170,
+151,157, 90, 22,218, 91,117,139,187,113, 17, 73,181,172,155, 85,134,101,215,110,181,213, 99,253, 77, 72, 98, 68,134,161, 70, 15,
+171,149, 18, 12,199,165, 63, 30, 59, 44, 48,211,146,228, 58,240, 75, 8,112,149, 16,164, 80,243, 60,247, 50, 62,199,125,199,193,
+ 73, 23,219, 99,125,143, 82, 0,239, 80,241, 39, 21, 71,196,149,209, 83, 82,212,174,107, 81, 80,226, 56,226, 80,230,162, 70,147,
+234,226,138, 33, 50, 71, 80,238,238, 21, 99,138, 13,122,152,170,128,194,195, 15, 28,122,147,162, 40,105,244, 58,132, 37,223, 18,
+ 3,231,194,234,242, 86, 28,114, 59,165, 43, 30, 26,249,214,164,228,128,219,188,202,202,185,192,213,242, 37, 81,151, 30,143, 37,
+197, 57,226, 48, 3, 43, 43, 9, 11, 44,184,174,102,157, 83, 95,206, 90, 22, 66, 70, 64,200, 86,124,137, 13, 21,189,112, 82, 46,
+ 11,114,151,114, 91,117,216,119, 21,175,113, 83, 33, 86,232,117,120,238,174, 76,106,173, 26, 82, 67,145,101, 66,125,192, 11,141,
+ 45, 4,130,146,128,164, 41, 37,183, 57, 92, 66,210, 3,147,114,251,147,205, 46, 54, 83,202,178, 2, 20,226, 80,132,161, 96,169,
+ 73, 10, 36,120,173,129,204,140,147,204, 20, 64,198, 59,150,162, 37,117, 42, 5,134,194,253,108, 65,216,110,125, 71, 75, 11,250,
+ 92,139, 85, 45, 11, 75, 83, 85, 72,209,180, 51,196,206,140,172, 25, 25, 24, 29, 14,146, 35, 0,209,184, 32,134, 82, 46, 24, 18,
+ 55, 26, 78,240, 90,213, 31,208,130, 86, 9, 4, 18,130, 72, 73,229, 80, 42,230,108,126,177,199, 46,112, 65, 25,207, 93, 58,209,
+ 39,130, 16,145,159,214, 81, 60,157, 65,194, 72, 0,114,156,158,128, 96, 14,165, 71, 30,128,234, 46,217,220,212,153,116,202,237,
+193,112,215,105,214,197,177,108, 64,126,171, 91,175,213, 37,166, 53, 46,151, 79,136, 18,100, 76,145, 41, 67,244, 76, 39, 45,163,
+148, 5, 41,199, 22,134,154, 11, 82,210,147,121,177, 56,210,225,140,221, 20,202, 80,185, 43,180,231, 43, 85, 4,209,236,251,142,
+240,181,165,219, 54,109,110,224,123,244, 52,198,233,213,121,111, 56,150,164,191, 39, 34, 8,154,220, 70,223,145,203,133,133,114,
+ 37, 82, 44,159, 40,174,158,140, 87,178, 8,168, 83,237, 72, 72, 38,202, 69,200, 91,220,219, 97,125,133,250,145,136, 77,103, 11,
+113, 14, 98,249,179,100,188, 59, 93,159, 12,160, 94,161,169,105,165,154, 56,137, 78, 96, 87,150, 53,100, 83,203, 28,198, 91,150,
+ 88,129,148,174,133, 36,110,229,114, 79,128,205, 58,148,133, 31, 26, 20,100, 59, 45, 60,196,132,212, 39, 20,202,122, 50, 84, 70,
+ 84, 27, 10,142,218,188,129,109, 73,206, 70, 5,137,201, 14, 46, 63, 35,110,172, 30, 98,236,137, 60,136, 43, 66,208, 65, 73, 5,
+196,225,111,114,171,166, 73,229, 9, 25,193, 3, 88, 95,215,200,158,183, 30, 67,206, 41, 43,116,248,202,117,107,231, 82,249,143,
+ 62, 86,165,101, 75, 43, 42,230, 4, 2, 9, 87, 55,198, 14,178, 38, 92, 98, 67, 32, 20,251,201, 8, 88,240, 16,146,164, 41, 67,
+178,192, 65,194,147,145,216,231, 10,198,125,116,226,139,237, 51,153,109,101,216, 45,137,176, 85, 0, 40, 38,219,249, 64,243, 91,
+246,186, 2, 70, 32,113, 80,251, 44, 81, 44,131, 83,130, 89,141,129,187, 49,212,196,131,181,139, 18, 64, 38,192, 90,228,140, 52,
+ 23, 71, 18,155, 27,182,247,133, 23,109,175,221,230,219,141,180,184,238, 72,209,228,209,169,247,213,194,220, 10,181, 86, 20,201,
+ 78, 65,135, 62, 60,103,163,251,172, 38, 37, 75,102, 75, 81,164,214, 36, 66,142,250,153, 91,141,169,214,146, 84,119, 30,147, 66,
+165, 80,195,147, 41,232, 38,166,235,108, 25,149,121, 74, 76,250,173, 65, 50, 26, 67,141,184, 37,252, 94, 36, 34,194,208,182,218,
+140, 81, 20,180, 82, 89, 10,109, 73, 89,131, 15,180, 99,113, 31,190,120,217,226,105,247, 21, 37, 48,237,189,193,122,201,132,220,
+231, 27, 90,216,183,172, 58, 52, 11, 98, 37, 40,182,149, 41, 9,140,210,225,202, 12,167,155,149,105,150,162,177,158,154,222,143,
+101, 55,180,158,109,129,120, 91, 92, 38,241, 1,118, 84,165,108,197,201, 83,133, 67,218, 59,194,177, 84,117, 3,105,238, 58,130,
+145, 22,145,102,215, 42, 78,168,190, 54,130,167, 53,198, 99,180,128,239,129, 65,155, 33,153, 40, 74, 41,207, 76, 66, 18,163,204,
+ 18,106,169,105,103,136, 44,113,146,169, 37,205,135,152, 11, 55, 64, 21,137,251, 98,218, 65, 1,129, 26,156,119,103,137,223, 65,
+ 12,230,155,192,222, 23,241, 67,129,120,142,163, 57,207,166,202,105,115, 92,243, 34,120, 80,201, 36, 83,210, 71, 89, 57,203, 94,
+ 45, 47, 81, 37, 18,146,173, 69, 62,179, 89,161,231,164,145, 39, 16,209, 79, 40,202,229,206,203, 50, 92,167,210,208,107, 18,249,
+ 17,239,226, 44,119,234, 17,224,182,163,206,183, 36, 8,104, 87,141, 37, 68, 5, 37,149,169, 33,190,156,196,116, 73, 21, 52,233,
+ 79,123,195,137,167, 34,158,186,130, 89,101,234,213, 77, 81,234, 87, 35, 64,168, 41,152,136,167, 35, 45,198,233,144,132,186,180,
+161,158,159,161, 42, 57,214,118,211,109, 82,144, 99,162, 60,122,107, 81,146,184,210, 98, 6,209, 25, 12,173,165,168, 41,185, 13,
+180,145,149,165,224,224, 89, 57, 61,193, 61, 53,141, 63,114, 33,233, 11, 85, 22, 2,170, 6, 42, 84,212,185, 46,120, 80,168,201,
+117, 77,148,182, 88,156,160,181, 73,125, 4,163, 41,105, 11, 32, 40,146,226, 20, 64,212,177, 40,249,104,218,136, 93, 29, 1,247,
+238, 71,235, 92,237,232, 58, 18, 54,181,252,231,165,168, 98,130, 44,186,134,201, 24, 5,166,121, 54, 99,112, 87, 94,233, 10,130,
+202,186, 81,249,136, 78,144,193,201, 44, 84,122, 5, 38, 28, 86,234,113,156,144,169,205,161,212, 57, 82,170,201, 76,201, 45, 60,
+163,153,137,113,197,182,159,113,143,202,130, 20,219, 0, 33, 33, 33, 36,173, 0,232, 37,215, 92,148,250,153,181,195,113, 24,204,
+ 83,252, 40,144,178,220,218,116,212, 96,205, 77,188,203,169,196,146,181,168, 6,221,112, 41,150,139,220,205,165, 69, 32,139, 44,
+136,107,113,106,122,179, 49,215,100, 48,241,113, 20,248,234,113,186,107, 6, 70, 20,166,155,136, 28,230,125, 10, 89, 0,151, 66,
+148,164,164,149, 30,184, 24,253,199,122, 66,165, 47,234,152,208, 81, 88,170, 60,133,169,134,151, 37, 17, 89,142,182,144,160,195,
+138,116, 16,184,175,115,146, 26,228, 35,152, 2,144, 10, 70,182, 97, 64, 14,163,229,113,223,173,246,245,220,141,236, 46,119,233,
+208,144,112,239, 75,150, 79, 93, 50,162,150,205,103,109, 68,106,254,230, 52,186,181,201,144,170,200,168, 55, 28,194,177, 0, 89,
+ 74, 58, 49,195,130,197, 46,151, 71,143, 89,156,136, 50, 16,226,147,239, 45,220,146,230, 75, 91,181, 22,228,134, 85, 46, 53, 65,
+ 42,116,169,215, 27, 81,116, 21,143,136, 56,176, 83,223, 69,209,101,194,118,104,120,212,188,105, 41,116,182,242, 25, 83,206,149,
+ 54,218,214,160,181,186,242,194,131,168,108,182, 83,205,250,200,108, 3,147,240,233,134,126, 83,142,181, 21,235,160,213, 20,137,
+105,109,136,245, 1, 33,149, 69,131, 86, 73, 74,228,162, 18,225, 47,194, 98, 66,176,143,133,208, 29, 73, 36,133, 44,128, 52,237,
+ 91, 17,157, 91,145, 84,244,169,143,180,227, 68, 21, 75,109,133,243, 33,111,129, 20, 74,114, 56,241, 39,182, 84,174, 82, 70, 20,
+165,173, 69, 57,239,167,120,101, 42,241,198, 6,146, 55,181,138,219,126,164, 14,187, 16, 5,245, 16, 5,201, 45,115,133, 51, 76,
+165,169, 40,229,154,170,189,170,102,150,227, 88, 37,145,130, 42,169, 88,221,140,154,183, 83,169, 71, 40, 43,236,138, 6,155,195,
+227,233,107,174,155, 39,136,190, 10, 30, 97,107,118,164, 56,127,220, 70,158,146,160, 16,217,132,155,246,143,200,210,154, 35,155,
+222, 4,191,120, 37, 71, 9, 82, 86, 10, 64,235,168,152,132,228, 28,164,164, 19,215,231,143, 77, 73,155,233, 79, 95,204, 87,248,
+240,217,189,185, 66,217,147, 47,105,120,111,164,154,148,182,157, 83,138,126, 70,226,221,245,186,220, 86,150,133,146, 80,148, 83,
+104,144,212,158,249, 18,186,147,129,168,234,237,246,223,222, 27,165,119,219,150, 21,133,110, 86,174,219,186,237,172, 68,160, 91,
+118,213,189, 79,122,169, 91,174, 86, 39, 44, 34, 53, 58,153, 1,128, 75,239, 43,226, 82,212, 74, 91,101,180, 45,231,150,219, 72,
+ 90,211, 98,229, 79,202,203,150, 89, 92, 34,171, 76, 88,147,176, 28,199, 55,185,216, 11,111,185,252, 49,198, 60, 76,139,250,126,
+189, 32, 28,197,102,132, 46,145,114,196,195, 16, 0, 0, 1, 44, 73,181,128, 4,182,214, 7,108, 96,193, 42, 89, 72, 66,114, 71,
+100,165, 36,149, 99,176, 0,119, 58,237,167,177,211,217,215, 3,138,221,197,169,239, 54,241,210, 85, 43,135, 45,155,171,194, 77,
+122,148,248, 83,108,110,166,227, 37, 13, 84,169, 27, 94,149,140, 21,219,145, 99, 42, 44,251,145, 77,156,169,135,162, 82,185,144,
+185,207, 4,246, 39,129,175,163,187,181, 22, 69, 46,141,184, 92,116,214,164,223, 87,121,101,186,140,141,132,177,171,110,211,108,
+ 90, 17, 41, 14, 34,153,125,223, 20,181,162,117,229, 60, 3,201, 42, 45, 53,216, 84,224,161,200,151,229, 4,149, 43,177, 76, 91,
+ 27,113,181,244, 24,150, 14,210, 88, 54,166,216,237,189,188,185, 31, 81,216,214, 37, 26, 21, 6,221,166, 25,110,243, 75,144,204,
+ 24,141,132,174,107,238,225,201, 18, 29, 43,126, 67,129, 42,121,215, 23,130, 27,243, 44,205,164,167, 43, 26, 24,161, 39,118, 99,
+165,220,118, 10,191,105, 84,157,152,182,150,181,202,117, 86, 19,158, 18,240,238,182,106,218, 90,236,242, 5,138,150, 59, 56,166,
+ 62,103,145,133,180, 9, 71,217, 84,185, 12,200, 75, 22,182,135, 80, 11, 12,100, 74,154,169,242,176,132, 54,203,109, 54,195, 44,
+ 71,140,203, 81,226, 70,137, 29,164,179, 10, 4, 72,236,165, 45,195,134,212,102, 91, 75,109,182,148,182,219, 76,161, 8, 74, 80,
+ 18,144,232, 90,112, 2,249, 93,117, 25, 66,146,209, 71, 66, 22,162,163,134,241,211,245,150,177,159,152, 58,106,104,113, 92, 82,
+188, 39, 22, 57,159,117,107,144,172,114,134,208,144, 20,235, 77,249,242, 37, 62, 27, 96,249,156,159,144,217, 59, 62,158, 23, 33,
+162,160,146, 26, 67, 60,168,236,129, 33,209,134,130,134, 48, 2, 26, 35, 31, 51,211, 77,180, 46,116, 52,199,224, 54,176, 30,128,
+ 14,214, 29,134,219,219, 98, 14, 47,113, 78, 21, 72, 3, 87,123,254,238,135,222,126,240, 59, 91, 14,157, 22,158, 26,105,164,172,
+ 5,168, 4,243,159,213,231,121,125,145,208, 99, 30, 93, 60,129,211,139, 26, 35,109, 54, 49,133, 17,220, 16, 79, 83,232, 60,250,
+246, 31,187, 86,138,100, 68,165, 73, 8,229, 81,142, 64, 42, 86,112,183, 22,144, 21,130, 15, 85, 36, 19,242, 28,218,203,218, 78,
+ 49,240,169, 41, 70, 66, 74,122,165, 68,142,170,207,160, 57, 72,251,254, 88,216, 14, 90,230,251, 15,244,249,254,125, 48,211, 87,
+166, 54,210, 5,205,133,251,123,192,239,235,247, 3,211, 99,142, 83,123,105,234,144, 40, 62,204, 78, 45,213, 56,172, 10,158,223,
+193,161, 68,109,166,214,234,222,168,213,110,106, 44,120, 49,210,219,105,230, 42, 83,161,103,253,144,131,228, 53,249,148, 74,163,
+ 86, 33,178, 31,157, 73,168, 68, 97, 73, 37, 15, 75,136,244,102,150,130,114, 10, 29,117,176,149,119,242, 39, 7,166,117,250,228,
+239, 21, 54,139,113, 81,162, 91, 21,234, 77, 58,187, 2,167, 53,185, 83, 41, 53,168, 81, 42,144, 36, 71,167, 16,227,102, 68, 9,
+141, 45,167,146, 37,173,178,146,164,171, 5, 25,232, 70,154, 39,182,131,105, 43,148,145, 68,173,237, 86,217, 86,168,230, 58,226,
+138, 93, 86,195,181,102,211,147, 24,131,204,194, 99,191, 75, 41,109,188, 19,219,175, 94,132, 30,186,205, 29,108,244,181, 21, 13,
+ 12,113,200,178,104, 7, 83, 48, 55, 91,237,178,176,177,213,114,119, 55,218,198,215,196, 43,137,120, 6,163,136,230,167,205,151,
+ 49, 90, 53, 72, 22, 32,134, 2,250,180,203, 43,106, 45,205, 75, 41, 46, 64,178,159,179,125,239,183,228,250,227,101, 60,188,224,
+140,142,128,244,207,144,199,168,198, 48,126,122, 21,192, 0, 3,155, 35, 57,233,215,215,166,191, 65, 78, 47,125,129,220, 19,241,
+ 21, 2,167, 90,218,170, 35,252, 48,110, 99,233,144,252, 74,205,131, 29,202,134,222,212,103,172, 18,132, 92, 59,119, 53,242,134,
+ 99, 45,220,115, 59, 76,122, 43,169, 25, 41,109, 88,229, 48,230,227,131,217,183,196,255, 0, 1,119, 35,112,119,146,205, 19,108,
+ 74,180,247, 33,217,251,193,104,151,171, 59,105,118,144,165,248, 44, 49, 88, 13, 5,219,245,162,132,229, 84,234,138, 35,202, 73,
+200,108, 58,145,204,100,244,217,164, 82,178,199, 50, 26,105, 9, 0, 92,221, 24,250, 43,250,158,193,130,177,236,164, 11,226,164,
+206,184, 91, 56,200, 65,146,174, 1, 45, 32,219,159, 17, 47, 24,222,195, 93,194,188,123,216, 93,212, 33, 36, 42,187, 28,115,229,
+210,158,163,169, 24, 62, 96,119,253,255, 0,215,160,212, 66,187,167, 24,232, 58,249,116,198, 49,219,174,141,117, 3,152,133,229,
+ 39, 56, 41,199, 80,122,227, 65,120, 97,165,169, 73,201, 43,238, 14, 79, 41,235,146, 61, 52,244, 14,192, 1,182, 35,160, 31, 92,
+ 14,231, 32, 73, 74,186,231,203, 24,251,137,244,208,101, 3,148, 32, 40,165, 57,236, 60,201,209,133, 63, 26,186,168,231,201, 71,
+225, 29,187,121, 13, 81, 86, 50,122, 16,115,246, 12,124,177,163,142,222,236,103, 3, 40, 3,211, 29,186, 30,189,241,215, 57,208,
+203, 24, 36, 15, 67,140,252,199,207,203, 69, 47,208,103,166,115,229,147,129,215, 62,186, 25, 64,244,230, 29,124,143,175,113,215,
+212,233, 85,189,129,245,235,243,240,198, 69,172,126,125, 48, 42,129,193, 30,127,147,161, 85,246,156, 17,215,204, 2, 8,199,217,
+162,148, 58,146, 20,122,103,207,167,159, 83,161, 92, 42,235,233,230, 71,159, 95,232,210,139,215,173,176,170,143, 95,157,176, 50,
+206, 15, 76, 31, 80, 71,224,126,220,104, 85,168,227, 28,189,125, 61,126,206,154, 37,100,103, 3,200,156,244,243,249,232,117,227,
+ 57,235,233,242,251,180,182, 50,126, 54, 56, 25, 99,175,159, 81,231,229,242,210,215,178,172,119,200,244,198, 14,127, 31, 61, 45,
+ 40, 47, 97,229,191,200,255, 0, 79,155,224,126, 56,162,144, 64, 30,191,143,158,170,163, 62,125,137,232,115,220,250,106,159,236,
+213, 69, 35,156,131,204, 71,166, 63, 63,156,233, 54,219,160,220, 99, 35,227,108, 20,131,208, 14,228,121, 99,231,251,116, 80, 56,
+ 35,184,249,250,104, 22, 57,146, 8, 81,234, 59, 31, 80, 60,243,247,232,209,216,117,207,207, 68,223, 77,200,244,254, 88, 24, 45,
+ 24,207, 92,231,203, 69, 35,207,183,239,208,173,124,207, 92,126,127,118,138, 64,232, 79,221,249,252,249,105, 44, 16,142,190,251,
+ 15,145,130, 80, 58,103,215,250,244, 66, 49,140,129,215,212,247,207,245,106,146, 48, 57, 79,150, 7,252,116, 64,193,232, 49,223,
+ 31, 97,210, 44, 79, 91,236,127,211,253, 48,153,183, 97,138,128, 40, 5,103,208,224,119,235,169,123,123, 41,104,112,173, 78, 2,
+173,121, 73,134,167,220,191,111,139,158,183, 80,116, 97, 14, 1, 26, 65,131, 29, 41,199,146, 91,142, 0, 58,136,106, 65,193, 4,
+140,224,156,227,211,175, 77, 75,111,217,163,113,199,172,240, 9,183,233,105,231,146,187, 86,241,187, 45,249,133,131,143, 9,213,
+ 78,114, 75, 97,196,121, 2,219,168, 32,158,224,244,213,121,226, 65,147,244, 28, 33, 13,148,206,186,191,254, 57, 45,142,131,250,
+ 49, 71, 12,158, 42,209,137,118,101,162,169, 41,214,225,249,148,226,226,196, 27,233, 45,211,181,251, 99,118,128, 83,114,214,210,
+153,146,220,116,144,235,125, 10,212,129,205,144, 20,161,156,249,105,224,180,100,161, 50, 35, 25,130, 74, 80, 57, 85,206, 20,176,
+ 26,230,198, 22,164, 30,253,198,153, 40,181, 49,238,232, 92,122,195, 47, 73, 82,210,211, 81,100, 39,149,110,184,178, 82,218, 1,
+ 61,252,180,248,219,242,107, 80,222,162, 71,155, 77, 98,169, 61,192,124,102, 35, 56,130, 91,108,254,170, 94, 72,254,110, 58,245,
+215, 54,213, 70,193,217,152,217,148,130,111,182,219,117,233,112,127, 28,123, 9,151,215,172, 84,113,194,236,164,181,215,237,232,
+114,116,222,246,144, 11,142,228,222,194,248,216, 58, 84,210,135, 89,145,227, 49, 81,108,184, 26, 12,189,132,132,180,123, 21,146,
+ 58,249,103, 78, 29, 49,216,145,157, 46,202,141, 0, 50,165, 99,153,162,151, 0, 10,255, 0, 80, 14,216,207, 93, 55, 22,253, 58,
+116,249, 14,180,186, 68,194,162,227,110, 41, 40,100, 22,154, 72,236,208, 41,238, 63,167, 78,237, 50,222,105,197, 50,210,160,203,
+ 5, 43,248,209,238,139, 82, 16,172,254,170, 84, 6, 15, 64,123,246,209, 97,137,100, 58,121,100, 21, 38,219,129,125,253,251,159,
+203,124, 66, 51,202,138, 53, 13,169,202,221,119, 10,203,112,189, 71,216, 96, 1, 27,139,233,177,239,124, 60, 54,123, 86,252,196,
+161, 45,162, 50,155,229, 7,170, 74, 10,129,238, 6, 71,112,116,252,211,104,240,209, 29, 41,140,174, 68, 20,228, 53,207,204,217,
+ 24,234, 19,232,174,250,105,109, 74, 83,112,209, 24, 57, 24, 70, 14, 44, 8,200,152, 24,136,167,206,112,124, 36,200, 90, 75,189,
+ 71,243,115,233,167,174,148,195,204, 73,247,101,182,182, 20,172, 18,219,237, 41, 33, 67,200,161, 67,203,168,237,167,136,114,230,
+101,187, 11,252, 13,192,191, 66,125,255, 0,150, 57,147,139,234,195, 84,202, 96,169,114,138, 75, 0,206, 26,224,108, 77,134,219,
+119, 54,216,237,113,131,109,233, 2,149, 48,165, 68,165, 30, 38, 65, 7,177,206, 58, 19,172, 11,142,250,104,187,248, 72,189,156,
+100,243,201,160,212,173,234,211, 33, 37, 75, 0, 55, 52,196,120,156,116, 8,228,153,212,158,131, 26,214,142, 52, 56,200,162,240,
+178,104,182,149, 18,205,170,110, 30,239, 93,144, 68,251,106,214,167,179, 37,200,145,162, 56,240,138,204,250,159,186, 52,167, 29,
+ 74,229, 97, 13,180,210, 74,150, 65,201, 72, 25,215, 24,110,255, 0,109,214,236, 89,181,169,123, 63,196,206,212,209,225,216,219,
+139, 33, 54,133,121,152,140,200,163, 86,236,207,172, 95, 67, 44,213, 92, 50, 29, 90, 28,247, 39,220,142,243,241,228,161, 37,109,
+ 48,160, 22,133, 16,160,237,150,210, 77, 74, 30, 57, 24, 4,148, 29, 42, 55,123,122,233, 0,155, 3,252,176,190, 77,224,151, 30,
+113,173, 21, 7, 27,228,116, 52,241,195,151,149,172,136, 84,213,193, 77, 53, 92, 16, 72,162, 73, 41,163,149,129,100, 44, 12,107,
+ 36,134, 56,222, 75, 34,185, 39, 28,240,171, 81, 92, 18,235, 15,189, 50, 83, 15,182,251,205,242,193, 1,135, 11,172,188,227,129,
+215, 90,116, 41, 15,167,152, 55,128,160,127, 87,190,113,171,197,186,251, 84,199, 27,110,231, 91, 11, 8,109,105,102,164,211,204,
+152, 75, 4,120,205, 50,166, 93, 67,142, 51, 33,194, 84,147,146,190, 85, 0, 82,178, 59,103,187,207, 96, 84,168,155,135, 92,164,
+148,251,168,139, 80,118, 74,101, 49,206,195,115, 26, 83,165,196,200, 97,164,164,165, 44,172,160, 41, 39, 56, 83,110, 36,144, 0,
+213, 45,183,165,251,180,225, 57,214, 41,211,231, 46, 59,134, 32,155, 57,137, 75, 47, 56,165, 48,251,207, 7, 20,216, 97,211,207,
+ 28, 22,210,121,212,147,204,148,242,228,105,122,137, 21, 98, 46,198,247, 22, 0, 1,112,118, 0, 3,218,222,150,216,220,157,247,
+199, 91,101, 89,173, 61, 78, 87, 77, 84, 36, 38, 42,136, 21,215, 65,180,182, 96, 28, 89,154,203,123,157,181, 30,246, 5,126,214,
+ 30, 11, 94,207,114,229,117,201,237, 69,164,202,120,197,143, 54, 85, 82,157, 37,183,147, 22, 59,235,108, 65,134,165, 70,194,224,
+ 61,226, 33, 45,144,231, 55, 47,196,226,209,149,116,219,107, 39,110,107,207,161,154, 43, 53, 69,192,105,220, 59, 45, 51,224, 51,
+ 86, 64,151,226,135,152,104,200, 64, 67,211, 90, 7, 24, 74, 94, 41,111, 9,230, 0,233,156,176,182,201, 77,169, 18,170,137,115,
+223, 42,193,152,112, 99, 91,243,158,143, 35,199, 74,144,226, 36, 74,147, 13,192,137,144, 80,224, 4,151, 2,137, 82,194, 64, 37,
+ 56, 27,217,102, 90,215,133, 41, 49, 27,133, 84, 98,165, 57,224,159,142,189, 5,146, 26,113, 35,153,236,152,138,109, 46,169, 69,
+ 25, 87,137,133,140,117, 36, 18, 53, 10,175,145,203, 5,138, 80,109,208, 48, 59, 17, 96, 8,190,160,123,246, 0,108, 20, 27, 91,
+ 12, 57,247, 17, 10,106,116,134,130,190,154, 78, 89, 80,156,196, 87, 1,193, 91, 30, 97, 18,163,152,205,238,197, 65, 6,218, 88,
+ 22,108, 90,237,237,189,152,234,185, 95,164, 89,245,210,228,149, 56,245, 82,107, 53, 74,100,246, 35, 52,164,165,243, 25, 77,135,
+115,204,242, 70,121, 29, 74,177,211,148, 96, 43, 79, 29,187, 98, 95,172, 58,106, 17,164, 80, 67, 45, 56, 12, 74,109, 70,100,217,
+240, 85, 24,171,153, 44, 69,113,113, 82,236, 53, 20, 4,149, 21, 41, 69, 5, 39, 41, 86, 6,179,123,118,157, 92,141, 29, 16,156,
+183,161,203,117,169, 45, 41, 85, 8,181, 70, 27,109, 47,173,212,248,236, 71,106, 84, 99,132,175, 36, 36,133,242,100,225, 68, 4,
+141, 58,241, 37,169, 36,181, 81,162,206,163,163,196, 75,109,173,245,177, 34, 3, 69, 39,152,189,239,177, 10,146,225, 89, 79,232,
+208,128, 73,194,129, 72, 61,117,169, 79, 70,103, 39,152, 2,179,118,234, 61,230,215,211,210,196,129, 98, 64, 29,141,241, 79,103,
+220,101,153, 30,114, 70,144, 85, 43, 2, 13,228, 73, 14,130, 64, 58, 33,230, 2,133,252,192,233,140, 21,185, 0,130, 72,108,110,
+143, 14,191, 8,188, 39,209, 80,234, 30, 65,115,252, 6,171, 17,212, 71, 73, 7,149, 40, 68,198,155,113,192, 74, 65, 61,137, 39,
+175,124,235,131,126,216,205,247,152,111,141,190,225,194,146,243,176,233,118,141, 10,155,186,215,228, 17, 33,165,138,133,245,119,
+ 54,244,107, 38, 20,208,210,212, 86,213, 50,201, 6, 83, 77, 44,254,130, 77,220,242,193, 10, 9, 34, 68, 98,167, 69,113,239,115,
+ 98,162,209,150,227,169,100,164, 50,250, 30,142,153, 10, 67,104, 47,161,113,185,149,250,217,193,234, 7,124,117, 58,132,167,180,
+ 11,114,157,191, 56,207,226,110,235, 91,220,193,123,191,119, 82,161,167, 35, 13,210,109, 57,205,218, 52,134, 80,174, 65,250, 54,
+233,246,252,102,210, 48, 48,150,250,247, 58,147, 81,229,101, 16,136,212, 49,107,111,110,151,247,223,215,107,145,238, 29,206, 45,
+ 63,161,246, 88,153,247,139,149,156, 79,155,208, 8,233,184, 47, 46,150,174, 32,203, 38,147, 89, 80,241, 82,211,189,164,119, 95,
+ 36, 18,213,200,157, 74, 75, 28,114, 11, 50,130, 59,157,236,172,221, 24,215,231, 13, 23, 37,147, 81,118, 25,168,236,189,253, 46,
+152,218, 93,144,151,101, 53,102,223,141,191,116, 91,190, 19,107, 28,209, 97, 71,172, 69,186,152, 65,253, 80,165, 4,167, 7, 26,
+218,107,158,228,161,191, 61,218,125, 49, 94,245, 40,172, 37,210,202,148, 67, 42, 11,229, 81,117,224, 57, 60,114, 15, 92, 2,160,
+149, 14,100,228,234, 49,124, 2,239,229, 79,110, 55,233,155, 77,234,234,233,116, 45,237,130,141,181,173,200,114, 66, 99, 70,106,
+181, 46,104,159, 98, 79,117,194,147,225, 52,221,203, 17,152,171,112, 17,134,171,110,142, 96, 9,204,138,108,186, 50,226,248, 65,
+230, 94, 18,210,234,138,218,116, 40, 56,144,201,253, 42,228, 2,144, 82,232,125, 39,155,155,185, 24,199,163, 70,113, 75, 61, 53,
+ 66,211, 24,192,102, 80,250,173,177, 4,158,128,236,109,107, 27,244,244, 55,216,120,245,195,212, 92, 51,226,119, 20,241, 60, 83,
+ 51,208,241, 68,223,164, 41, 96, 4,170, 44,179, 42,251,111, 53,134,197,189,176, 77, 41,141,108,170,146,160, 98, 5,181, 97, 28,
+ 75,220,181, 26, 38,200,211,104,247, 69, 74,235,183,182,170,177,190,251, 65, 11,117,110,107, 14,159, 10,179,117, 91,182, 75,207,
+220, 78,183, 82,133, 14,168, 4, 79,171,216,186,153,183, 21, 41, 82,210, 98, 36, 41, 9,115, 46,170, 58, 78,196,185,236,244,224,
+218,187,107, 59,115,220,156, 71,239,126,228,237,173, 2,138,187,170,107, 84,230, 45, 75, 86, 5,193, 65,109,135,229, 52,252, 91,
+142,223,106, 82,213, 70,114, 67,192,198,106, 35, 40,154,243,242, 91,140,151, 91,112,244,112,233,245, 17, 14, 44,120,174, 52,203,
+140, 76,104,179, 45,183, 16,135, 25,122, 52,130,142,120,210,155,117, 36, 60,203,137, 64, 5,181,165, 73, 88, 7, 57,232, 53,131,
+111, 20,122,181,183,183, 23,101,181,105,248, 52,138, 5, 74, 76, 74,251,148,250,116, 97, 1, 16,222,167, 60,106, 47, 70,165, 53,
+ 21, 77,181, 6,159, 41,244,182,244,150, 67,100, 56,236,116,184, 10, 10,220, 42, 89, 95, 56,135, 46,142, 10, 39,138, 88, 81,180,
+202, 38, 14, 74,164,134,226, 72,138, 50,168,146, 61,200, 73, 86, 72,223,161, 85,177,213, 91,112,255, 0,139,220, 97, 77, 6, 89,
+195,156, 53,196, 21, 60, 22,207,152, 77, 60,242,208,138, 52, 21, 75, 82,148,144,150,121, 38,162,154,174,158,178, 4,129,185,117,
+ 52,245, 41,169, 36, 80, 81, 94, 4,118, 96,232,187,243,188, 52, 58, 53,183, 22,179,113, 84,169, 53,196, 81,160,251,245, 41,201,
+ 62,244,245, 37, 30, 24, 17,105,181, 9, 10,121,208,245, 77,152, 9,140,153, 37,110, 58,225,146,151,148,235,139,112, 41,106,217,
+189,151,227, 46,253,131,118,219,180,250,252,122,125,201, 79,118,165, 17,114,150,164, 24,178,216,166,197,117, 15,212, 36, 41,109,
+252, 46,145, 13,149,146, 84,156, 16,146,163,211, 58,229, 18,107,239, 62,242,147, 37,199, 31, 91,206,242,186,241,117,192,165, 58,
+115,211, 39,155,149,210,121, 78, 15,117, 43,161,198,175,245,237,208,133,180,123, 77,185, 27,181, 83,195,175,211, 41, 12,109,245,
+155, 17,197,165, 15, 85, 55, 47,117, 95, 93,149,109, 82, 48,149,164,169,198,162, 73,174, 84, 86, 89,234,134,109,247, 20,190, 92,
+115, 20, 34,161,174,138,166, 35, 73, 52,177, 73, 35, 11, 42,177, 35,177,251, 38,224,129,110,227,176,216, 3,139, 63, 49,225,124,
+159, 58,137,168,171, 50,122, 67, 83,155,200,176,199,104,150, 37, 89,170,228, 17, 68, 21,129,214,136, 36,145, 64, 37,137, 84, 80,
+ 88,147,124,113, 55,116,247, 70, 69,253,187,251,165,124,248,206, 6,183, 3,113, 47,219,205,230,124,103, 29,108, 53,115, 87, 43,
+ 21, 40,234, 47,172,146,232, 75, 18, 90, 9, 39, 39, 13, 39, 9,232, 14,172, 14,214,153,120, 48,183, 78, 92,152, 57,157, 10, 37,
+ 43,109,167, 26, 13,184,150,207, 80,131,206,176,172, 30,169, 9, 5, 24, 32,105,155,145, 77,159, 79,177, 55,214,248,122, 99,102,
+ 14,214,238, 37, 54,195,167, 33,244, 45,181,207,144,221, 5,213,204, 44, 21, 16,151,138, 88,241,164,244, 32,167,198, 64, 82, 64,
+ 41,200, 53, 27,141, 40,118,147, 76, 15, 45,169, 62, 12, 25,243, 2, 86, 20,234, 16,197, 62, 19, 65,165,164,117,229,247,167,138,
+ 73, 61, 22,177,202, 7, 66, 69,171, 7, 12,211, 48,141, 68, 97,196, 42, 34,118,176,243,125, 68, 82, 27,237,230, 26,101, 64, 77,
+183, 59, 94,221,125, 38,200,188, 76,203,114,202, 54,165,142, 67, 20,116, 65, 22, 8,217,183, 68, 90,250,204,182, 21, 7,236,171,
+ 60,153,116,228, 2, 70,148, 58,202,134,186, 15,209, 95,217,213,187,149,126, 36, 56, 44,216,253,206,187,174, 26,157,110,227,126,
+218,126,193,186,149,240,199, 84,155,163,109, 39,191,101, 84, 39,204,125,144, 23, 80,149, 50,149, 75,163, 76,121,231, 85,202,227,
+245, 23,148, 15, 58,213,173,192,169,181, 57,184,233, 69, 62, 75, 17,217,117,148, 54, 25,157, 8, 41, 77,184, 20, 57, 18, 85, 21,
+196, 40, 55,148, 36,167, 33,106,235,158,185, 26,226,103,176,146,232,171, 73,224,105,202, 90,107, 52,248, 49, 97,111,182,232,183,
+ 25,185,145,221,148,239,233,169,118, 36,151, 91, 74,223,144,136,236, 44, 74, 46, 41, 40,108,169, 68,173,101, 73,230, 86,187, 41,
+ 49,154,218,209,205, 42,173, 52, 52,180,165, 74, 68, 70, 98, 69,116,182, 9, 42, 83, 15,150, 84, 82,172,173, 43,228, 0,100, 3,
+231,140,166,170, 86,154, 21,107,179,160, 10, 88,238,110,160,139,147,114, 77,254, 59,238,122,227,195,207, 25,248,114,151,135,188,
+100,241, 27, 44,203,158, 10, 60,158,155, 59,204, 26,142,156, 69,166, 56,105,158,169,228,130, 24,163, 88,121, 65, 97,137,146, 53,
+ 32,147,100, 5,141,201,182, 5, 94, 69,230, 10, 94,145, 46,158,251, 79, 45,104,148,212, 6, 23, 14, 74,219,229, 12, 45,182, 36,
+ 58,225, 37,149, 97, 25,231, 83,121, 7,151,152,115,103, 88,171,145,168,116,244,134, 97,194,115,222,240,219,142,210,234,106,145,
+ 26, 99, 65,211,209,246,222,146, 74,159,116, 16, 64, 41,113, 93,130, 80,224, 61, 53,146,220, 18, 42,169, 71,189, 65,175, 23,224,
+ 43,196,110,100,138,180, 52, 73,141, 20,132,150,219,121,201, 49,146,211,140, 32,184, 66, 20, 84, 8, 65, 74, 73,198,117,138, 87,
+ 28,148,234,162, 34,187, 74,117,192,134,195,141, 85,221,124,204,165, 74, 66, 64, 8,106, 33,105, 1,113,212,225, 81, 86, 31, 66,
+ 49,205,221, 67, 11,214,189,142,171, 48,185,237,109,186,218,221,251, 94,219,220,117, 0,118,198,190, 89,205,228, 83,161,104,226,
+136,234,212,180,224,194,199, 64, 4, 7,140,136,249,140,128,157,144,137, 21, 72,107,233, 54, 57, 45, 21,111, 50,239,128,212,167,
+155,106, 99,237, 53, 50, 5, 82, 58,170,112,130, 22,133,248,114,226,201, 82, 20, 84,194, 84,162, 75, 79,133, 20,150,202,144,180,
+144, 70,158,219, 70,151, 29,231,155,118, 60,104,204, 22, 63,193,222,142,151, 20,169, 10,146,203,194, 58,208,195,190, 63,232,220,
+ 83,255, 0, 26, 27, 64, 12,165, 9, 10,230, 9, 32,105,148,162, 91,141, 33,248, 83, 89,126, 99, 48,230,182, 20,180,198,150,244,
+129, 79,113, 60,188,170,101,153,170,115,222, 32,173, 37, 93,149,240, 99,149,124,169, 9, 89,109,184,249,226, 98, 31, 5,220, 21,
+239,191, 17, 15,200,136,155,150,213,178,166,210,246,246, 59, 73,141, 4, 86, 55, 54,239,228,181,236, 42, 83, 8, 90,185, 31,124,
+220, 21, 40,178,202, 18,149,144,213, 45,220,101, 41, 86,157,232,209,181,169, 10,100,111, 40, 23, 59,177, 54,181,129, 23, 4,146,
+ 58, 1,212,220, 92, 98, 11,198,117,212,212,212,243, 58,213, 20, 77, 12,210, 54,146, 52,132, 30,109, 96, 29,244,170,155,187, 57,
+ 42, 0, 96,197, 77,204, 4,253,172,219,203, 47,139, 95,105,175, 18,183,101,176,204,138,245, 61,141,200,141,179, 22, 18, 41, 9,
+ 93, 86, 93,102,147,182,162, 46,222,210,152,166, 51, 24, 19, 62,108,219,142, 29, 80,176,134,211,151, 87, 57, 0, 2, 78, 76,168,
+189,147, 30,205, 59,119,129,141,189,137,185,219,145, 71,167,212,120,177,191,168, 72,110,225,150,239,131, 57,157,155,182, 42,104,
+109,241,183, 54,188,132,130,150,171,238,183,225,154,253, 69,162, 22,251,224,192,105, 98, 36,114, 29,230,127,176,159,128, 53, 76,
+144,190, 60,247,198,152,229, 94,166,106,149, 39, 54, 34, 21,106, 58, 84, 43, 87,116,135,159, 77,209,188,211,162, 60,140, 58,227,
+ 18,159,150,197, 29,103, 9, 19, 37, 74,154,140,150,153, 34, 80,232,121,231, 86, 94,194,151,206, 84,165,229, 89, 83,132,156,149,
+100,255, 0, 59,169,238,117, 52,214,174,144,192, 15,246,106, 75, 42,129,210, 73, 19,102,115,254, 20, 96,116, 95,171,221,172, 52,
+163, 53, 11,192,252, 48,106,170,102,226,204,206, 29, 53, 57,147,188,180,145, 48,254,234, 41, 9,101,148,237, 96,238,166,209,126,
+196, 86, 97,188,158, 91,213,199, 90, 49,104, 79,128,238, 30,144,121, 9, 61,192,192,201, 10,245,242,251,181,174, 71,196,148,241,
+192, 74,219,247,143, 25,101,101, 88, 83,109,158,100, 32,143,231,159, 20,183,140,231,245,116,231,222,179, 3,236,178,194, 18,160,
+158, 67,240,159,214,231, 63, 8,200,245,230, 7,246,107, 16,183,233,171,125,220,148, 41, 94, 26,193, 82, 72, 56, 30, 24, 42, 25,
+ 7,182, 93, 82,127,254,159,144,211, 69, 97,106,138,152,227, 83,176,254, 38,222,238,150,252, 15, 81,139, 78, 53, 68, 46, 72,176,
+ 83,107,124, 58,253,247,191,243,198,113,108,211, 19,227,169,194,215, 63,134,203, 99, 5, 93, 27,101,146, 22,246, 14, 62, 37, 45,
+242, 7,255, 0, 71, 91, 55,104, 83,196, 88,200, 91,141, 21, 62,226,125,225,196,142,201,144,233, 1,182,178,161,208, 1,200, 7,
+158, 18,112, 52,218,218, 20, 34, 11, 72, 82, 48,167, 29, 66, 86,162, 9, 37,168,227,198,115, 36,249,169,100, 15,158,126,122,216,
+ 74, 93, 56,165,176,160, 48, 80,160,230, 79, 96,234,193,228, 24,207, 80,150,250,245,243, 58,216,145,194,132,133, 59,122,123,247,
+233,252, 61, 58,123,176,171,188,113,197,169,205,134,223,126,214, 23,251,250,216,250, 19,223, 23,184, 45, 45, 45,164,250,130,146,
+ 81,130,165, 58, 79,198,161,205,211,205, 71, 39, 29,135,217,171,242, 82,161,202,146, 14, 66, 64, 79, 92, 18,112, 18,132, 16, 7,
+ 82, 71,151,110,167,174, 79, 64,225, 49,204, 6, 74,148, 8,194, 60,151,142,203, 80, 0,244,206, 50, 62, 95,110,173, 87,197, 93,
+ 84, 74, 17, 76,101,242,212,170,171, 93, 62,154, 51,254, 77,126, 25, 50,166, 56,148,245, 8,102, 57, 81, 78, 59,184,180, 13, 2,
+252,184,139,157,194,142,158,167,111,226,127,215, 17,237, 18, 87, 87, 69, 75, 8, 13, 45, 67,233, 30,130,251,146,127,194,160, 22,
+111, 64, 9,233,134, 94,191, 60,214,174, 57,178,155, 80, 92, 88,138,250,178, 34,146, 73, 75,205,197, 89,247,133,181,215,245, 87,
+ 40,172, 41, 93,185, 91, 30, 93,117,113,101,178,148, 36, 20,167, 60,185, 33, 32,115,124,125,242,123, 32, 17,235,228, 58,103, 58,
+ 6,155, 5, 49,217, 1, 3, 41, 72, 72, 43, 80,202,251,124, 13,167, 57,231,230, 87,116,142,188,202,202,181,122,119,157,164,242,
+182,128, 48,114, 74,210, 29, 82,148,174,231,149, 4, 14,112,122, 96,156, 36, 12,232, 82,130, 20, 22,181,207, 83,241,235,252,127,
+134, 38,117,241,198,136,144, 66, 60,145, 40, 65,126,182, 80, 5,205,187,158,167,191,125,177,107,145,209, 56, 56, 42,192, 31, 7,
+ 50,136, 81, 39,245,114, 6,113,145,215,212,143, 62,186,109,183, 18,195,178,183, 58,203,185,118,235,114, 45, 74, 13,245, 98, 93,
+244,185, 20,123,178,204,185,224,179, 84,161,215, 41,210,208, 90, 83, 50,227,188,143,209,202, 66, 15, 51, 50, 26, 45,202,140,234,
+ 80,244,119, 91, 90, 65, 46, 20,133,132,149, 18,121, 66, 82,146,158,167,227, 3, 9, 11,231,233,205,133, 28,116,233,240,231,231,
+171, 4,167,130,146, 70,115,130, 7, 41,230, 1,190, 97,133,140,168,119,230, 25, 87, 47,167, 66,115,128,228,164, 50,233, 32, 21,
+ 35,161, 23, 7,226, 15, 81,234, 45,238,196, 78,170, 0,218,129, 93, 72,247, 12, 8, 22, 32,141,193, 7, 98, 10,220, 16,110, 45,
+112,118,216,254,127, 62,215,111,101, 5,107,129, 75,173,157,208,218,223,173, 46,126, 22, 47,170,217,166,219, 21, 73,139,114,161,
+ 95,218,219,154, 98, 29,148,206,220,223, 83, 66, 63,194, 24, 91, 77,191,245, 45, 81, 88, 76,246, 99,150, 29,196,198,148, 28,226,
+ 11,202,192,207,250,185,206, 65,252, 7,207,183,227,175,213, 99,121,118,187,111,119,183,109,239,125,163,221, 75,114, 53,215,183,
+ 27,137, 66,147,110, 93,212, 9, 73, 66,132,168, 18, 70, 89,155, 1,197, 28,211,235,208,230, 33,137,116,249, 72, 41, 92,105,113,
+154, 90, 84, 7, 50, 85,249,178,113,225,194, 13,235,193, 55, 17,215,238,197, 93,238,191, 80,167, 82,159, 69,111,111,238,242,201,
+110, 45,251,182,117,197,186,245,165,117,196,233,203,239, 75,138,218,226,212, 26, 24, 84,122,141, 58, 75, 74, 74, 64, 71, 51,238,
+ 85, 86,192,138, 57,152,176,223,150,204,110, 72, 29, 81,137,234,203,216,159, 51, 46,237,118, 86, 99, 65,113,143, 12,174, 75, 50,
+215, 81, 41, 25,101, 83,105, 43,215,145, 46,237,160, 27,127,116,226,230, 50,126,201, 86, 67, 97,203,213,166, 30, 57, 89, 86, 50,
+ 57, 63, 91, 35,175,110,154,250,115,156,144,122,249,254,255, 0,158,190,132, 99,161, 63, 14, 7, 46, 51,204,122,121,244,234,117,
+245, 72,229, 29, 50,113,234,114, 6,127,226, 52,254, 46,118,196, 36, 11, 11,116,192,142, 40,231,160, 24, 29,207,175,231,166,135,
+ 82,137,238, 64,232,124,241,143,179, 68, 44, 19,211, 24,237,156, 99,160,245, 31,126, 52, 50,128,235,212,121,128, 78, 49,215,207,
+246,105, 68, 59, 91,211, 6,181,253,109,251,240, 59,128, 1,240,171,174,122,121,121,246,207,159,246,104,101,244,200,243, 35,246,
+ 1,147,162, 21,140, 28,140,254,113,161,148,112, 8,235,215, 56,237,248,125,154, 85,112,176,189,136, 39, 3,168, 0, 15,145, 62,
+ 99,204,143, 35,249,242,208,203,229,235,235,211,242,126,225,162, 87,140,117,249,224,122,159,158,135, 88,233,231,247,118,251,254,
+237, 44, 58,142,248,193,237,183, 67,243,247, 96, 69, 12, 31,183,175,217,165,175,171,198,113,140,126,255, 0,187,241,210,210,202,
+ 77,133,197,207,221,131, 99,202,112, 72, 7,242,117, 92, 15, 35,128, 60,190, 67,250,245, 69, 3, 39,236, 25,209, 40,239,246, 15,
+207,219,164,143,175,174, 6, 42,164,124, 64, 14,131,166, 15,207,236,243,242,209, 35,215, 56,198, 62,220,124,191, 62,122,164,143,
+ 51,208,255, 0, 72,235,253, 31,213,170,160,100,227, 56,233,145,243,252,254,237, 17,175,109,186,223, 3, 4,160,140,231, 62, 93,
+207, 79, 77, 22,130, 49,143, 63,233,251, 52, 26, 72, 30, 64,143,179,183,217,162, 1, 74,146, 72, 61, 65,252,115,142,159,159, 93,
+ 35,140, 48,184,235,108, 20,140, 18, 1,239,158,135,203,239,209,169, 7,166, 14, 79,145,253,186, 1,158,132, 17,149, 14,196, 19,
+140,124,243,251,180,122, 72, 79, 76,145,211,160,233,147,164, 9, 36,220,225, 54, 29,199,206,216, 33, 4,224,142,153, 29, 85,219,
+183,166,164, 73,236,110,220, 31,173,246,111,125,182,170, 68,175, 13,251,106,189, 68,191,169,177,199,196,183, 33, 84,227, 24, 21,
+ 2,134,250,229, 41,151, 17, 57, 35, 63,229, 6,117, 29,198,252,179,144,122, 1,230, 79,219,211, 93, 44,246, 85,110,228, 13,175,
+226,214,210,164,215,229, 24,246,198,234,192,168,237,157, 95,227,228,108, 75,174, 32, 59,111,188,224, 39, 4, 38,172,195,104, 4,
+246,247,157, 70,120,186,135,219,242, 26,232,130,234,146, 37,230, 46,215,221, 14,166,255, 0, 32, 97,247,226,198,240,131,136,227,
+225, 95, 18, 56, 87, 54,157,180, 83,123, 64,167,148,237, 97, 29, 72, 48,220,223,107, 43,186, 57,255, 0,166,248,146, 36, 30,101,
+188, 76,200, 92,160,148,190,196,228, 14, 82,218,114, 10, 92, 8,242, 87, 93,108,205,136,136, 94, 60,105,208,170, 83, 26,151, 9,
+191, 29, 82,222, 74,157, 92,231, 64, 7,195, 90, 79, 64,192,244,244, 26,103, 63,131,149,104,117, 26,148, 68,184,195,109, 83,228,
+173,134,209, 44, 2,226,202, 22, 82, 16,178, 79,234,114,242,159,179, 79,213,149, 33,113, 88, 77, 61,112, 27,121,229,248,106,149,
+ 58, 39, 41,101,148, 19,213, 63, 32, 79, 66, 62,237,115, 51,211,150,121, 6,155,219,175, 91,109,181,133,253,226,219,123,241,235,
+ 75,241, 11, 79, 76,188,137, 11, 48, 93,149, 89,118, 13,107,151, 89, 1,176, 11,212, 3, 98, 79, 75,219, 27, 67,183,181, 74,244,
+214,231, 56,229, 74,158,135, 38, 41, 14, 18,160,166,156, 74, 16,156, 36, 32,118, 65, 62,159,191, 89,190,241,113, 11,110,112,191,
+176,215,206,245, 95, 6, 20,202, 61,145, 74, 92,138,101, 45, 18,130,100, 92,247, 68,212,150, 40,116, 70,185,198, 84, 94,156,164,
+120,132, 3,202,211,110, 40,118,198,137,219,165, 83,139, 76,133, 80, 28, 90,114,210,212,240,109, 10,241, 74, 15, 76,167,253, 94,
+159,126,117,202, 47,164, 21, 92,174, 69,225,135,102, 32,209,169,178,160, 90,181,125,216,152,229,206,180, 71, 8,142,167,224, 81,
+ 11,148,102, 36,173,177,132,143, 17,201, 42, 66, 85,208,148,156,117, 26,113,203,168, 3, 58,157, 54,103, 33,125,118, 36, 94,196,
+237,222,227,213,182,195, 70, 89, 79, 69,197, 92, 91,144,112,245,125, 61,168, 43,234, 1,157,252,177,147, 20, 49, 60,207, 26,149,
+ 58,245, 75, 28, 77, 18,149, 55, 93, 87, 27,139,227,130,123,191,198,175, 16, 27,247,184, 53, 45,208,191,119, 70,231, 85, 90,163,
+ 41,199,233,180,154, 61,106,117, 46,133,107,211, 84,247, 52, 26, 77, 22,153, 17,228, 34, 20,118, 27, 40, 72, 87, 47, 57, 41, 37,
+106, 42, 36,235,167, 28, 15,251,109,119,107, 98,106,116,123, 7,136,169,179,119,107,102, 31,113,136, 72,172, 74, 90,101,223,214,
+ 83, 75, 33,180, 78,165,212, 93, 60,213,120,109,143,137,113,159, 82,138,146,217, 13,173, 11,198,163,142,186,235,108,188,164,169,
+213,165,121, 56, 0,143,231, 19,148, 16, 58,242,145,159, 46,186, 6,109,204,220, 84,151,229, 73, 75, 76,165, 69, 13,186,181,124,
+ 13,149,252, 65,167, 20,122, 32, 43,175, 41, 61, 51,208, 28,156, 25, 60, 92, 63, 80, 37, 67, 1, 49, 19,208,129,189,141,182,255,
+ 0, 21,246,184, 55, 7,184, 56,236,142, 32,151,195,140,255, 0,133,223,133,248,147,134,104, 42, 50, 10, 88,196,113,162,172,112,
+123, 24, 69,210,178, 83, 74,129,100,164,145, 7,247,111, 27, 39, 75, 54,164, 44,167,244, 98,220,125,244,218,109,207,181, 44, 93,
+211,218,219,134,218,187, 42, 87, 53, 36, 51, 69,220, 10, 51, 17,100, 76, 69,191, 35,149,215, 40, 82,159,113, 5,234, 52,228, 57,
+209,198, 86, 27,121,151, 16,161,243, 44, 38,219,240, 59,195,109,247,187, 50,119,219,118,236,200,251,153,118, 75,170, 65,173, 67,
+182,174,118,154,153,103,210,171, 16,188, 32,197, 90, 69, 61,192, 77,102, 97, 83, 13, 41, 94, 54, 91, 36,117, 74,129, 58,135, 95,
+ 6,188,107,223,252, 45,110, 43, 52,233, 52,170,149,203, 96,222, 20,101,215, 83,103, 60,250,190,174,187,227,193, 5,199, 38, 91,
+143, 44,148,196,174,178,208,123,149, 72,234,165, 37, 41, 87, 50, 84, 70,166, 95,193, 71, 19,251, 57,196,190,221, 82,183, 35,102,
+111, 8,119, 37, 13,224,211, 21,170, 59,206,165,155,154,207,170,129,201, 34,143,114, 82,138,185,226,186,219,193, 72, 75,184,240,
+221, 9,202, 85,215, 26,134,231,185, 70,123, 75,158, 38,105, 42,145, 71,202, 88,163,146, 50, 90, 29, 18, 16,197, 88, 92,133,119,
+146, 38,219,245,140,108,190,102, 70, 11,198, 92, 75,194, 16,120, 95, 13,105,224,204,246,176, 46,111, 21, 85, 20,213, 74,239, 79,
+ 89,200,142, 74,121, 30,138,165, 99, 8,209,242, 82,106, 70, 89, 32,229,195, 52, 53, 48, 77, 24, 84,168, 68, 26,105,237, 7,217,
+ 19, 64,220,153,215, 20, 88,210,156,133, 88,145, 38,124, 79,119,101, 69,163, 18,166,128,243,109, 37, 40, 1, 44,161,169, 41,117,
+174,100,245, 74, 25, 74, 0, 3, 3, 90, 51, 69,177,226,173,138, 60,234,204,122, 85, 38,221,129, 41, 51,103,211,161,176, 94,110,
+ 91,208,250,114, 84,204,148,115, 56,210,150,121,194, 65, 70, 22, 18, 73, 35, 82, 72,226, 42,210,160,110,117,160,197,162,168,115,
+ 29,188,213, 74,168, 86, 45, 9, 77, 65,126, 76, 10,156,120,126, 17,171,208,229, 78,105, 60,176,167,150, 84,151,226,161,194, 60,
+101, 71,113,182,200, 89, 26,226, 82, 54,226, 82, 43,245, 56, 55, 19,146,165, 82,168,173,189, 53,234,122,121,219,167,174, 92, 53,
+ 21,161,215,162,173,172, 60,148, 33, 24, 82, 73, 88,113, 92,185,201,201, 27,117,108,244,241,194, 26, 80, 4,200,175,177, 5,212,
+177, 33,144,129,246, 88,144, 74,234,211,113,184,242,225,135,128,248,146,174,159, 42,143, 44,172,115, 72,249,120, 15, 20,146, 35,
+ 63, 50,152, 72,218, 26, 20, 93,164,179,172,144,173,201, 8,234, 67,105,179, 12, 29,182,244,136,190,236,139,162, 43,211, 44,218,
+ 8,144,234,232,245, 56, 11, 17,235, 21,134,156,116,152, 20,134, 80,176,164, 56,209, 72, 43,143,200,135, 22,133,101, 74,113, 57,
+214,238,237,187,251,130,203, 76, 67,151, 72,167, 84, 98,133,170, 91,213, 42,148,233, 12, 76,138,192, 82,148,219,210, 68,113,202,
+170,138,219,193, 89, 73, 67,106, 72, 42, 40,200,248,181,222,133, 7,252, 38, 61, 94,168,236, 48,218, 34,198,106,222,121,215, 12,
+ 42, 5,177, 73, 72,109,202,131, 44, 54,165, 4,166,172,236,131,241, 5,128, 23,219,155,149, 1, 39,109, 54,169, 47,214,159,141,
+ 78, 48, 42, 53, 11, 73,106,126, 99,142,173,244,196,145,119,169,196,182,166,100,201, 84,167, 3,137,162,161,194, 72,100, 6,202,
+154, 9, 82,143,134, 60, 50,195, 58,115, 25,121,138, 2, 2, 5,250,155,236, 2,134,216,220, 95,168,238, 13,133,186, 73,115,220,
+216,213, 80, 74,207, 75, 13, 76, 72,128,234,144,106, 49, 40, 80,161, 99,149, 74, 52,149, 4,141,198,181, 87,112,116,142, 90,187,
+151,130,212,169,221, 85,192, 81, 71,162, 69,143, 17,233,177, 66,234,213,121,210, 29,109,249,104, 83,136, 47,211, 99,197,142,149,
+ 42, 58, 27, 13,132,100,161, 42, 4, 36, 14,234,214,192, 82,168,207, 6,100, 72,146,243,115, 36,115, 37,223,120, 83, 66, 40,134,
+150,151,200,182,225, 67,103,224,109,191, 19,152,143,214, 95, 97,205,166,202,221,175,203,122,100, 42,117, 14, 27, 48, 96, 45,217,
+109,187, 93,144,132, 73,164,149, 65, 11,113,200,212, 8,170, 80, 21,149,224, 37, 41,120,242, 70, 10, 10, 9, 83,160, 99, 78, 43,
+116,232,146, 18,162,237, 86,169, 54, 43, 79, 52,133, 63, 42,172,182,163, 42, 83,190, 32,120,165,166, 16,210, 27, 75, 65, 69,178,
+ 18,158, 64,162, 82, 50, 81,157,111, 81, 68, 21,129, 8, 22,227,101,189,237,123,109,114, 1,185,236,109,232, 47,107,226,137,226,
+141, 77, 41, 30,203, 30, 87, 20,158, 96,168, 26,121,138, 19,111,172,118,118,179, 18,159,221,137, 20, 88,110,150, 85,193, 53, 73,
+145,226,170, 46,101,196, 76,164,184, 28,240, 12,134,153, 95, 43, 10, 74,155, 46,181,207,144,121,194, 7, 62, 9, 82,143, 47,108,
+234, 4, 62,210, 58, 72,219,158, 58,184,155,183, 37, 40,183, 29,237,225,189,234, 44, 58, 57,127,200,220,181, 35,117,198, 37, 8,
+ 56,229,118,159, 89, 74,128,242, 87, 67,131,157, 78,142,170,138, 83,209,158, 69, 30, 52, 6,160, 54,228,136,114, 46, 38, 99, 50,
+181,206,146,133,248, 78, 67,166, 72,113, 37, 82, 16,149,149, 37,199,134, 91, 66,242, 26, 11, 88, 90,147, 16,207,164, 3,178,234,
+161,113, 5,183,251,173, 73,167,134,104, 59,189, 97,210,168, 85, 9, 52,211,200,236, 43,223,109,162, 38,218,168,185, 41,231, 21,
+137, 21, 23,168, 70,202,152,128, 87,226, 56, 92, 95,235,114,171, 51, 28,157, 98,150,190, 8,100,110, 92, 83,221, 79,199, 69,239,
+185,177,177, 27, 15,128,189,142, 45, 63,163,127, 17,212,112,127, 20,113, 29, 53, 38,185,106,243,156,177,196, 81, 58,133,230,212,
+ 82, 85, 83, 84, 44,108,169,172,160, 52,166,171, 97,169,163, 3, 91,114,200, 24,226, 4,154,196,244,219,106,220, 88, 18, 36,123,
+230,213,238,117, 58,151,184,116,120,110,184,212,168,118,117, 66, 76, 20,196,186,144,180, 43,157,136,145,234, 12,197, 91,146, 81,
+132, 70,114, 83, 75, 43, 75,110,100, 74,151,217,207,198,213, 39,137, 54,238, 61,133,221, 10,180, 42,127, 21,123, 72,167,219,169,
+193,146,168,241, 90,223,139, 2, 44,118,170, 52, 45,207,178, 66, 74, 81, 80,184, 88,183,166,211,141,199, 76,103,157,106, 33, 53,
+232,129,216,210,102,162, 20, 59,161,215,121,234, 81, 43, 84, 91,170,177,103,222,204, 45,171, 98,241,138,155,114,161, 89, 69, 74,
+148,180, 59, 78,143, 92,122,151, 17,151, 83,112, 82,132, 69,184,196,200,129,133, 59, 38, 25,125,133,176,243,141,180,149,244, 87,
+132,222, 13,248,140,184, 47,203, 39,113,120,121,171,199,191,238, 93,185, 98, 53,251,111, 91,251, 99, 85,166,215,175, 87, 41,240,
+ 42,241,155,165,214,182,154, 47,191, 41, 91,145,104,211,234, 42, 83, 92,148,103, 83, 85,163,199,117, 84,250,197, 33,136,225, 97,
+185,206,113,194,121,109,101, 27, 45,125, 80,163,171, 2, 95, 99, 38, 41,121,134,115,162, 78, 66,144,133, 38,141,138,205,202, 84,
+102,150,120,231,139,150,134, 90,104,163,158, 75,196,249,142,105,226,180,212, 89,118, 93,165,163,138,170,138, 74,220,202, 74,236,
+184,209, 80,208,200,239, 65, 46, 97, 87, 27,213, 71, 85, 72,252,182,203, 23, 53,133,225,134, 42, 12,195, 41,170,210,211, 69,154,
+203, 85,150,205,166,227,165, 61, 6, 5, 54, 97, 74,156, 18,227, 69,110, 35,140,180,165,169,249, 82,156, 67, 13, 71,138,218, 85,
+241,185,226,184,218, 91, 31, 9, 82,214, 50,122,244, 11,114,111, 27,114,131,182,251,199, 34,255, 0,136,154, 45,247,176,245, 58,
+ 22,218,111, 22,216,181, 81,143, 85,184, 45,221,195,188, 89,183,161, 89, 20, 42,100,159,117, 96, 92,148,187,141,187,194,223,118,
+133, 84,102, 59,113,170, 72,126, 72,105, 41,114, 12,164, 55, 75, 99,119,122,224,174, 51,245, 7, 19,219, 89,112,112,215,186,220,
+ 60,220,144,175, 61,215, 77,193,108, 87,174,237,159,151,101,211,226, 77,189, 33,110,173,151, 93,162, 70,144,154,221,142, 81, 76,
+164, 63, 80,165, 60,241,153, 77, 68,215, 72,114,100, 8,147, 31,135,146,113, 71,183, 59,103, 34, 92, 13,253,110,235,173,110,165,
+205,184,176,173,202,147,143,193,221, 91, 86, 92, 45,209,191,156,186,104, 59,129,181, 86,205,199,245, 20,121, 48,102,109,181,175,
+123,214, 32, 86,104, 82, 40,181, 28,208,209, 13, 52, 53,191, 38,135, 86,101,109,214, 19, 84,229,188, 53, 74,207,159,161,161,167,
+175,150, 56, 86,121,140,113,211, 67,100, 55, 51,107,101,157, 73,146, 72,180,145, 11, 42,168,147,153,162,197,146,162,201, 56,112,
+210,113,141, 46, 79,196, 20,245, 18, 53, 58,173, 84, 67, 46, 95,106,106,245, 73, 41,170, 2,208,207, 24, 52,245, 80, 86, 80, 37,
+ 72,165,150,158,114, 90,122,170, 9,135,212,151, 87,227, 20,104, 45, 87, 24, 85, 86,218,241, 42,148, 71,110, 43,170,211, 76,212,
+ 52,150,132,106,245,151,114, 85,109, 11,162,129, 84,104,168,251,149,106,157,112,209, 42,113,229, 48,188, 58,218,227,142,108, 33,
+ 77,169, 90, 21,237, 94,168,222, 22,133,223,195,254,202, 10, 93, 82, 93,177,180, 43,183,183,154,236,164, 81, 20,153,146, 98,238,
+125,229, 73,129, 91,163,213,175,116, 52,191, 22, 53, 66, 29,188,253,173, 71,167, 81, 57, 76,150,133,213, 81,149, 33, 81,220,148,
+211, 74,150,182,225,218, 92, 50,112,247,195,165,153, 77,165, 90,219,117, 99, 91,150, 60, 43,174,244,174,223, 49,109, 27,134,228,
+218,202,205,255, 0,107,212,149, 18,116,251,243,114,104,207,201,168, 51,121, 72,220, 7,211, 38,169, 13,184,115,170,215,251,244,
+217,244, 88,238, 70,155, 37,169, 49,121, 20,212, 93,185,118,222,225, 46,203,225,223, 98,183, 23,120,253,160,252,116, 84, 55,118,
+117,213,191, 91,223, 72,247, 69,219,219,105,184, 23,221, 98, 20,254, 44,230,237,204, 42,236,138,109, 42, 84,217,212,251,153,118,
+ 17,144, 93, 52,138,101,143, 85,175,174, 58,252, 58,125, 67, 79,254, 28, 54, 93,153,214,174,113, 79, 20,121,133, 44, 97,185,112,
+ 9,150,105,100, 73, 41, 86, 94, 92, 38, 35, 21,167, 43, 81, 29, 57,169,144, 44, 20,142, 37,170,101,154, 49, 70,106,111,238, 14,
+168,151,137,248,115,244,207, 19,210,215,101,116,144,212,140,186,131, 48,134,146, 36,164,139, 59,164,121,107,219, 53,204, 26,181,
+229,163,139, 38,160,162,201,235, 36,205,169, 85,235,234,125,154,190, 36,140, 9,162,154, 90, 72,169,213, 45,253,208,118,151, 97,
+ 90, 91,181, 38, 13,167,103, 94,215,213,102,231,174, 55, 49,215, 31,172,238, 77,247, 17,216,119, 14,228, 45, 49,233,233, 9, 77,
+ 46, 21, 66, 69,159, 70, 41,134,135, 99,193,140,211, 84,180,200,231,102, 82,155, 18,155, 83,131,120, 85,111,219,154, 3, 50,105,
+148,169, 19,160,193,160,214,170,113,194,103,214, 98,211,229,168,183, 62,159, 72, 66,178, 89,147, 84, 14,152,173,252, 45,248, 13,
+ 54,178, 84,149,147,169,133,123, 64,189,146, 86,255, 0, 13,187,109,182,187,145, 64,219,248,219,185, 14,215,178,234,116, 13,218,
+222, 42,148,217, 2, 53, 42,184,204, 22,226,237,117,131, 14,206,132,240,114,194,225,222,157, 83, 53,138,149,106,161, 29, 14, 73,
+171, 86, 42,171,153, 89,124,169,230,121, 34,177,182, 91, 65,116,111, 46,243,196,218,253,171,247,251,206,183,116,213,106,146,228,
+110, 45, 77,182, 89,136,139,118, 28,148,197,186,119, 9, 54,243, 47, 6,109,107, 54,152,143, 26, 45, 38, 35,139,255, 0, 5,141,
+ 9, 78,190, 85, 41,232,140,170,115, 83, 86,212,245, 25,140, 21,212, 63,162,231,161,141, 36,125, 43,202,166, 45, 35,172,211, 73,
+ 10, 63,152,169, 40,176, 6,149,220,186,195,120,162,104,238, 34,191,184, 15, 62,224,252,219,132,178,206, 51,225,190, 45, 60, 75,
+193,102,174,190, 55,168,174,180,249,164,116,185,109, 52,249, 86, 93, 75,153, 84,195, 32,246,103,141,107, 43,115,158, 82,101,249,
+ 74,150,205,227,150,183, 49,167,173,118,253, 35, 52,143, 98,189, 5, 54,159,179,243,109, 77,101, 98, 4,221,196,190,119, 71,112,
+ 90,102,181, 21, 8,139, 91,164,212,174, 88,182,196, 10,140, 85, 56, 18,219,240,220,254, 9,200, 41,115, 33, 74,231, 82,146,146,
+218,155, 42,234,187,209, 27,163,184,237, 90, 72,168, 42,130,200,240,165, 64,143, 38, 82,158,160,173, 74, 13, 9, 84,182,157,124,
+ 46, 93, 57, 73, 90, 10,152, 73, 43,100,172, 41,160,180,115, 32, 49, 27, 9, 77,177,109, 93,139,217,139, 99,111,227, 72,143,183,
+214,214,217,218,118,173,163, 6,173,153, 19, 88,131,108,210, 99,208,101, 65,174,135, 83,148,212,157,159, 79,150,244,181, 20,148,
+123,204,229, 43,177, 57,114,208,124, 17, 57,202, 83, 14,170, 36, 5,137, 85, 10, 36,185, 75, 84, 55, 96,202, 71, 42,132,120,171,
+113,106,241,219,116,146,219,173, 15, 11,186, 85,148,168,114,194,132,136,200,173, 31,158, 54, 80, 65, 3,168, 34,224,129,232, 65,
+213,184,220,116, 23,199, 0,113,150,101, 55, 20,241,127, 20,113, 19,235,165, 25,245,125, 85, 67,198,196,108,179, 84,182,152,185,
+133,129, 73,145, 89, 34, 14,220,203, 72, 8,103,229,150, 86,247, 81,110, 91, 49,167, 78,161,215, 37,212,219,113,213,165,218, 85,
+ 69,240,244, 26,132, 54,129, 11, 49,228,181, 29, 46, 66,168,140,245, 75,156,193,124,161,183, 27, 28,201, 86,190, 81,155,125,104,
+135, 34, 12,114,220,121, 41, 40, 98,157, 53,228,170, 35,114, 20,230, 86,221, 26, 80,200,167, 40,169,103,158, 59,169, 8,202,112,
+128,131,144, 60,211,163, 71,152,183,230, 83,229,191, 4,133,169,153, 76,134,179, 60,198, 89,109,232, 14,212,225, 62, 86,221, 65,
+ 13,185,148,165,196,101, 78, 32,243, 37,209,130, 19,153,208,146,134, 81, 41, 19, 11, 49,214, 86, 24,121,165,178,165, 69,168, 40,
+ 31,135, 1, 64,169, 46,149, 41, 36, 40,254,144, 5, 36,146,188,100, 38,134, 48, 25,152,141,172, 46, 77,136,220, 27,250,141,253,
+222,226,122,130,193, 89, 80, 41,169,164,139, 72,146, 84, 43,112,200, 85,236, 84, 40, 87, 84, 1, 94,219, 21,144, 93,244,155, 22,
+ 69,101,209,125,183,168,209, 97,190,250,204, 70,152, 5, 64,200,140,166,150,203,176, 87,241,151, 94,136,160,178,134,218, 89,230,
+ 82,128,202,114,162,164,100, 2, 53, 28,111,107, 60, 59,251,143, 63,104, 23, 11,126,205,170, 3, 53,106, 46,201,109,173, 53, 27,
+255, 0,189,117,166,249,216,137, 90,147, 49, 18,105,172,202, 66,146,174, 71, 98, 81, 45,102,106, 49, 24, 42,193, 53,155,189,229,
+160, 5,197, 73,215,123, 47,141,211, 98,142,167,173,155, 89,193, 42,229, 25,106, 76,148,165, 47, 71,180, 91,112, 5,120,181, 23,
+ 14, 83, 34,182, 58,174, 44, 18,162,180, 43,149,249, 92,173,165, 40,113,184,160,218,118,243, 51,158,189,219,161, 64, 93,228,170,
+ 58,109,137, 55, 99,177,210,229,194,253,186,103, 61, 86, 93, 46, 69, 85,196,248,174,194, 85, 90, 68,169, 42, 65, 86, 20,243,235,
+ 89,234,113,167, 76,190, 73, 36,154, 36, 66, 2,174,204,196,216,168, 96, 86,235, 97,187,142,171,113,179, 0, 79, 96, 43, 78, 39,
+200,167,207,168, 64,172,169, 48,195, 60,176,243, 35, 59,153,169,213,129,145, 9,184, 40,178,128, 35,189,201,120,217,238, 72, 33,
+152, 74, 45,191,110,218, 20, 10, 5,159,104, 82,163, 80,109, 43, 50,145, 78,182,173,138, 20, 36, 37,152,116,202, 37, 38, 58, 33,
+ 65,136,219,104, 24, 24, 97,176,165, 43,186,214,165, 45, 89, 82,137,214, 66,192, 44, 56, 50, 64, 66,255, 0, 84,246, 74, 22,174,
+188,167,230, 79,109,121, 92,114, 87,226,132,243, 5, 16,162,145,156, 45, 62, 69, 56,238,161,231,246,106,239, 2, 58, 29,109,109,
+140, 45, 4,158,231,170, 65, 29, 58, 31, 49,251,181, 41, 93,150,200, 52, 42,216, 5,236,161, 64, 0, 1,233,167,107, 95,107, 15,
+118, 6,132,133, 20,133,242, 45,129, 0, 88, 1,181,128, 29, 5,187, 14,150,219,160,198, 15, 92,140,185,115,138, 64, 42, 71,192,
+ 48, 51,148,245, 42, 81, 7,237,199,237,198,179, 75, 74,130,162,174,110, 64,124, 66, 48,124,213,215,155,149, 64,142,249, 35,240,
+215,148, 83, 60, 73,124,161, 36,156,132,103,190,121, 71, 64,125,124,254,243,173,128,177,237,177,134,150,166,134, 7, 42,186,224,
+143, 44, 12,121, 14,154, 67,202,160,201,111, 49,218,255, 0, 63,127,239,196,120,213, 0, 90,237,117,185, 55,251,239,238,249,252,
+ 47,182,197,185,224,181,226,148, 36, 57,202,148, 5,148,228,167,152, 5, 58, 79, 79, 76, 14,157,180,226, 8,126,236,203,104,229,
+ 60,234, 39, 41, 0,168,144,160, 20,178, 64, 31,173,203,129,242,206,178,138, 93, 27,145,148, 5, 35,225, 35, 39, 61,212, 7,196,
+ 78, 60,251, 1,143, 61,123,145, 19,153, 69, 69, 4, 41,106, 8, 66, 83,212,227, 32, 37, 32,103,190, 59,159, 85,124,134,144,177,
+221,137,249,239,127,225,134,106,140,228, 77, 49,141, 79,213,198,127,211,243, 54,237,139, 84,118, 89,109, 14, 61, 41,212, 70,139,
+ 13,135, 37,204,148,176, 18,212,104,172, 36,184,227,206, 40,246,108, 37, 56,249,146, 7,158,181,250,179, 86,126,239,172,200,171,
+165,165, 49, 78,105, 40,133, 70,101,239,129, 48, 41,109,171,225, 88, 0,126,146, 83,234,203,139, 61, 57, 66,130,124,177,167, 30,
+243,170, 10,151, 53,173, 13,126, 37, 62, 51,173,185, 94,117, 25,228,155, 49,165, 7, 24,164,151, 19,254, 82, 35, 74, 8, 47, 36,
+116, 83,129, 32,146, 1, 26,196,209, 13,152,192,120,189, 72, 36,248,109,160, 56, 2,128, 5, 63,163, 79, 92,103, 3, 39,160,236,
+ 58,233, 61, 70,161,194,166,241, 70,119, 63,180,195,227,217,127, 22,248, 41,196,175,135,160, 90, 56,228,204, 39, 66,107,106,150,
+209, 41, 6,241,194,108, 75, 91, 99,174, 91, 3,191,217,140, 1,191, 54, 69,192, 76, 50, 27,111, 13, 54, 73, 64, 9, 75,139, 82,
+155, 0, 43,169, 44,128, 9, 62, 93, 64,193, 61,206,129,152, 95, 41, 82,138,208, 22, 65, 72, 12,164, 32,165, 0, 36,148,163,152,
+144,217,234,147,145,223, 36,228, 96, 13, 93,159, 83,174,103,149, 32, 40,182,126, 55, 51,206,132,145,201,240,161, 7, 35, 62, 99,
+ 32,129,158,249,214, 55, 45,212, 37, 96, 41, 41,120,167,152, 0,148, 0,129,149,167, 39,148,225, 32,224,247, 61, 71,166,116,224,
+158, 91,109,185, 27,219,231,253,127,117,240,237, 35,179,146, 77,153,143,253,199,183,115,176,223,225,139, 75,238,163,147,144, 21,
+ 40, 96,142,116,142,164,165, 71,170,222, 82,187, 31,136, 4,140,243, 1,229,215, 88,252,183, 65, 72, 11, 82, 74,126, 16, 8, 28,
+184, 82, 72, 9, 66, 86,188, 18, 18,124,176, 62,100,224,157, 92, 39, 56,224, 82,146, 23,204,162,174, 95, 9, 9, 79, 55, 83,240,
+ 40,169, 64,252, 33, 36,252, 92,160,245,192,214, 45, 49,208,142,112, 21,241,171,170, 65, 78, 85,128, 50, 82, 74,129,229, 60,160,
+143,187,169,234, 53,176,135,175,112, 15,243, 31,187,175,201,195, 45, 82, 13,247,235,252, 62,255, 0,187,182,253,175,139, 84,247,
+ 82,160,163,130, 9, 39, 36,167,159,175,196, 10,138, 66,176, 19,215,191,145, 57, 25,215, 6, 61,188, 92, 35, 69,226, 19,132,201,
+ 91,199,110, 82,195,187,161,195, 10,102, 93,241, 28,140,192,126,125,115,105,170, 47, 48,214,226,219,142,184,128, 86,242, 33, 44,
+195,173,196, 64,207, 34,224, 76,242,116,235,186,178,222, 24, 37, 41, 81,237,144, 82,160, 20, 48, 84, 0, 3,162,199, 82, 58,245,
+ 31,127, 70,250,191, 79,164,215, 96, 84, 40, 85,216,173, 79,160,215, 96, 84, 40, 53,232, 14,182,151, 35,203,161,214, 98, 61, 73,
+173, 66,121,165,116,117,135,105,115,166, 54, 71,126, 85,224, 28,246,216, 14,203,105, 35, 63, 89, 25, 12,191, 17, 98, 47,238, 61,
+ 15,184,145,176, 59,197,243, 92,186, 44,214,138,175, 46,156,218, 42,180, 41,114, 7,145,137, 5, 36,183,172,110, 22, 65,210,229,
+109,238,199,229,128, 82, 2,137,239,143, 49,212, 31,152,199,126,154,248,172,145,219,166, 51,147,251,191, 13, 61,188, 74,237, 67,
+251, 7,196, 22,245,108,212,198, 21, 21, 91,103,185, 87,117,161, 21,133,168,173, 72,164, 83, 42,242, 5, 1, 65, 71,170,194,232,
+ 46, 83, 92, 10,235,144,230,114,115,146,198,169,106, 88, 4, 43,155,166, 71, 76,119,245, 30,186,153,211,202,179,197, 12,202,124,
+178,168, 97,235, 98, 1,254,120,230,119,142, 72,157,226,149,116, 75, 17, 42,227,209,212,233,101,251,152, 17,138, 46, 16, 70, 51,
+235,156, 28, 99,251,116, 42,177,142,195,148,103, 30,125,187,147,243,213,117,168, 30,224, 12,142,248,206, 79,217,161, 87,208, 31,
+ 60,156,126,255, 0,221,173,192, 44, 0,244,192, 29,190, 56, 29, 89,193,233,255, 0, 14,253, 52, 34,142,113,223,207,184, 3,240,
+209,107,237,223, 29, 71,231,243,233,161,156, 32, 2, 51,147,231,142,191, 62,154, 85, 7,124, 42, 44,119,192,171, 35,203, 63,126,
+113,231,228,117, 69,125,179,147,255, 0, 31, 93, 87, 95, 55,158, 49,229,249,245,208,235,199,207, 62, 94,159,126,149, 2,228, 99,
+ 29, 0, 3,231,255, 0, 24, 21,103,175,216, 49,159, 93, 45, 37,254,183,221,211, 75, 74,139,128, 0, 31,142, 13,143,168,198, 79,
+124,227,238,199, 79,219,162,145,140,118,235,230,113,251,254,205, 8,223, 83,147,145,208,244,251,241,215, 69, 35,177,235,231,219,
+247,232,141,107, 47,108, 12, 18,142,199,167,223,235,249,253,250,169,158,221,250,124,254,126, 94,154,164,140,245,233,211,215,247,
+124,245,237, 36, 40,144, 15, 99,131,223,161,210, 78, 54,248, 96, 99,223,140,142,249, 24, 0,103, 25,202, 78,139,108,149,129,212,
+ 0,124,241,215,168,233,211,239,253,154, 16,180, 1, 56, 0, 36,228,159, 79, 44,147,243,254,189, 86,109, 65, 36, 14,184,198, 2,
+143,203,212,253,218, 64,155,117,192,193,237, 39,151, 3,175, 66,123,119, 63, 63,144,209, 8, 95, 51,137, 73, 78, 57,115,241, 30,
+221, 60,178,126,122, 8, 60,140,148,130, 85,216,224,117, 87,159,124,253,167,240,209, 63, 11,137,248,186, 28,252, 35,168,207,219,
+248,233, 22,234,113,131,235,243,233,139,187, 64, 43,162,136, 63, 49,147,235,233,247,106,247, 70,169,212,104, 85, 90,117,110,145,
+ 41,200, 53, 90, 68,248,117, 58, 92,198,148, 80,236, 90,141, 62, 75, 82,225, 74,109, 67,170, 84,137, 44,180,175,184,141, 88,152,
+ 10,229, 79, 96, 48, 57,177,219, 35,167, 79,219,162,211,156, 40,118, 30, 71,184,249,245,242,233,162,144, 24, 21, 97,112,118, 32,
+239,132, 15,196,169, 30,155, 16, 71,112, 71, 67,137,193,240,233,185, 20, 62, 44,120,124,219, 61,240,167, 76, 71,191, 84,105,140,
+ 81, 55, 14,155, 5, 64, 73,165,223,148, 54,155,135, 89,139, 53, 8, 57,103,197,121,191, 25, 25,253,100, 72, 65, 4,131,173,161,
+180,210,245, 40,183, 10, 44, 52,248, 14,171,153,247, 36, 40,150,208,211,100, 16,181,171,201, 93, 7, 79, 83,168,161,123, 40,248,
+226,137,194,214,237,191, 97,110, 76,199, 6,196,111, 20,202,117, 42,239,113,106, 82,155,179,174, 82, 83, 18,135,123,178,146,127,
+ 69, 25, 42,113, 12, 78,199,254, 43,149,211,158, 67,169,140, 46,220,104,182,207,128,184,210,104, 79,178,197, 70,159, 80,128,226,
+ 36, 70,171, 65,146,132,189, 18, 92,121, 77,168,165,248,174, 52,182,212, 10, 73, 7,155, 84, 39, 16,240,233,203,115, 25, 99, 88,
+201,130, 67,170, 35,216,169, 61, 47,220,173,244,155,247,243, 17,102, 24,239,143, 11, 60, 80,110, 39,225,218, 88,107,103, 15,152,
+229,170,144,213, 33, 98, 60,234, 0, 89,236, 55, 34,117, 93, 98,219,115, 3,198, 8,209,135, 82,196,175,212,218,113,133,198, 84,
+117, 38, 71, 32, 67, 78,101, 4,182,142,157, 7,255, 0, 22,125,124,255, 0, 13,121,226,147, 97,169,220,100,236, 45,251,195,253,
+214, 96, 83, 89,184, 96, 55, 58,221,184,156, 71,138, 45,139,210,151,207, 34,220,169,161, 93,196,113, 36,248, 82,113,221,137, 11,
+244,198,172,116, 62,102,100,181, 29,160, 61,231,149, 60,142, 99,224,101,164,246, 3, 29,128, 25,233,173,128,164, 74, 18, 99,198,
+ 73,116,183, 25,181,114, 60,178, 57, 76,151, 16, 50,162,162, 14,124, 60,129,246,235, 82,158, 2,165,118,210,203, 98, 45,216,245,
+190,219, 94,253, 7,223,139, 66,108,214,122, 57,232,179, 76,177, 18,150,182,141,214,104,102,243, 49, 73, 35, 33,209,244,220,171,
+217,133,180,176,210,230,225,188,151,199,230,211,196, 86,208,238, 55, 15,155,153,121,237, 22,231, 81,100,219,215,221,143, 82,149,
+ 79,168, 71,125,106,110, 52,230, 88, 90,132,122,157, 46,106,128, 76,202,124,136,220,143, 71,121, 63, 11,141,186,146, 8, 36,141,
+107, 90,238,137,210, 99,242, 84,194, 39,208,228,243, 69,156,165,101, 50, 16,209, 35,156,184, 17,212, 56,158,138, 66,198, 72,229,
+ 26,253, 19,125,160,126,206, 29,169,246,133, 88,112,226,214,219,129,100,111, 5,191, 18, 68, 91, 19,116,219,132, 28,148,220, 38,
+208,181, 53, 65,186, 99,180, 66,170,182,233,119, 30, 25, 39,198,138, 86,165, 50,121, 74,144, 97, 29,196,223,179,219,138,238, 14,
+171, 85, 42, 30,238,109, 69,202,253,158,137,146, 26,165, 95,150,229, 61,202,229,149, 91,134,219,133, 41,155, 18,173, 13,165, 6,
+ 91, 82, 48,172, 57,202,180,231, 5, 26,179,178, 42,250, 57,225, 72,106,149, 86,169, 74,233, 44,116,220, 29,175, 27,118,123,216,
+133,216,130, 59,142,146,250,158, 42,173,226,215, 74,204,190,189,178,218,167,133,214,182,141,111, 32, 18,142,242, 68,219, 84,208,
+202,162, 69,119,250,199, 68, 58, 38, 17,181,158, 86, 98,205, 98,245,184,155,179,246,190,133,117, 81, 43,212, 69,205, 93,107,111,
+171,201,247,180,220, 22,125, 75,170,221,143, 77,172, 67, 70, 41, 51,212, 66,147,225, 62,180,195,146,121,152,117, 41, 82,145,153,
+ 39,123, 14, 56,116,186,118,163,136, 57,119,139, 91,231,181, 82,105,117, 56,211, 85,187, 59, 81, 50,174,154, 46,225, 86, 41,142,
+178,236, 71, 96, 81, 44, 39,154, 15, 79,169,138,138,154,146,169,140,169,198,154,240,202,146,121, 8,214,156,123, 19,246,162,147,
+184,219,245,181,214,173, 74,157,114, 91,212, 68, 94,177, 46, 9, 87,209,164, 82, 35,166,152,213, 40, 26,147,148,152, 53,249, 12,
+182,135,161, 77, 92,118,163,188,212,150,221, 87, 43,171, 72, 10, 95, 41,212,194,248,217,224, 59, 96,239,203,211,110,184,157,163,
+220,219,119,195,142,224,236,189, 90, 53,199,112,238,141,180,213, 54,131, 86,184,173, 90, 80,241,158,162,204,105,137, 44, 68,247,
+146,216,120, 38, 83,136, 82,185, 95, 91,106, 14, 36,132,105, 42,177, 85, 95, 69,196, 84,180,235, 13, 45, 13, 59, 8,229, 63, 84,
+100,153,228, 44,254,209,101,229, 8,180, 29, 45, 34, 57,120,102, 98,238, 84, 54,248,177,115, 46, 32,224,110, 24,171,225,142, 26,
+226,122,217,198,119,199, 25, 21, 76,116,245,242, 71, 93, 93, 67,144, 67, 83, 72,217,122,208,154, 38,146,170, 74,254,122,137, 97,
+203,171, 80,123,126, 86, 13, 50,114,230,134, 52, 43,104,160,110, 52,106,229, 82,239,218, 10,165,197, 42,143, 92,155,112, 63, 79,
+182,109,170,172, 86, 42, 53, 42,212, 72,110,166, 83, 17, 83, 38, 18,137,166,133, 50,164,172, 60, 85,240,145,228,123, 92,248,153,
+225, 90,117,139, 14,223,186,217,144,212,184,247, 13, 37,217,245,234, 50, 30, 68,154,188, 47,118, 5,245,153, 13, 36, 5, 84,225,
+248, 64, 45,114, 16,133, 4,120, 5,183,210,145,135, 23,170, 17,120,166,246,122,210,239, 8,251,245, 73,221, 42,108,202,125, 54,
+ 85,110, 12,136,116, 25,110, 42,164,252,181,186,183, 36, 84,100, 71,157,200,243,176,212,251, 97, 40,154,128, 27, 80, 87, 42, 0,
+ 73,215, 28,248,248,246,138,238,223, 31, 27,209,100, 13,189,190,175, 61,174,217, 13,133,184,168,247,110,220, 46,215,168, 72,182,
+ 43, 50,175, 26, 23,136,134,174, 58,133, 66, 41, 14,213, 96, 61,144,143,113,148, 85, 17,198,121,155,117,149,165, 68, 30, 78,240,
+151, 41,171,203,168,248,214,139,140,242,218,147, 61, 39, 46,146,154,176, 74, 94, 58,115, 70,238,237,110,102,210,194,237, 49, 74,
+101,167,176,152,106,242, 71,253,233, 17,120, 7,226,111,137,188, 85,195,180,126, 29,112,252,188, 55,150, 71, 72,245, 89,147,103,
+144, 54, 91, 11,230, 13, 18, 65,236,212,236,144, 84, 78,202,220,184,170, 37,144,199, 57,137, 21,156, 76,199,149, 3,245, 94,101,
+153, 14, 91, 11,118,106, 60, 38, 42, 50, 98,248, 52,232,255, 0,224, 76,210,169,176,210, 23, 58, 67, 75, 75,170,196,215, 65, 90,
+ 66,200, 82,134, 70, 57,121,122,190,116, 74, 93, 58,224,113, 52,104,137,117, 22,180, 38, 41,236, 84,166,201,117,250,127,189,196,
+138,202,165, 63, 77,135, 61,213, 5, 70,128,166,194, 12,199, 18,144,165,140,160, 16,130,179,166,155,101, 55,170,133,187,214,166,
+214,220, 55, 67, 20, 74, 22,231,223,150, 76, 91,182, 85,181, 1,133, 66,160,215,231,197,159, 82,164,204,170, 90, 80,221, 39,244,
+ 42,118,154,185, 47,211,155, 89,114, 42,164,175,221,144,228, 84, 39,195,216, 74,124, 72,107, 67,204, 60,133,205, 66,221, 76,153,
+140,248,200,105, 21,106,162,212,144,195,107,125, 39,244,116,228, 20,254,149, 32,124, 73, 74, 16, 82,160,149, 5, 73,200, 40,225,
+ 8, 33,133,138,157,182, 82, 3, 95, 73,181,137,216,116,212, 13,238,110, 49, 90,230,167, 55,225,188,207, 50,225,188,237,100,164,
+205,114, 10,186,138,102, 10, 67, 66,181, 20,181, 15, 75, 52,145, 56, 33,102, 11, 36, 14,177,206, 9, 14, 84, 59, 29,188,174, 84,
+ 59,173,112, 93,143, 85,131, 21,160,229,114, 44, 58, 45,153, 66, 12, 7, 27,139, 74, 91,136,101,170,139,205, 35,148, 83,216, 89,
+109, 47,175,160, 45,198, 97,150, 17,149, 40,129,153,191, 33,138, 45, 46, 76, 10,157, 73, 53,234,220,249, 45, 83,233,211, 28,109,
+ 44, 82,226, 34,114,131, 18, 43, 40,129, 31,153, 48, 97, 70, 47, 36,186,181,120,174, 58,242, 82,209, 95, 50,212, 18,208, 73, 83,
+ 80, 80,204,199,127,194, 85, 21,242, 79,187, 56,168,170,169,212,221,108, 50, 91,138,234,193,240,227,178,130, 24,101, 57,229,108,
+ 41, 75, 86, 74, 20, 9,139,172, 74,165, 58,245,126,172,220, 89,142, 26,131,177,226,196,130, 86,202, 30,125,154,122,189,198,155,
+ 17,167, 0, 8,166,198,149,239, 78, 60,238, 79,139,135, 31, 80, 75,139, 70,183,210, 72,208, 37,152, 14,131,107,157,246,216,129,
+183, 77,134,221,141,183, 54,195, 12,185,100, 85,145,194,212,139,125, 68,121, 69,150, 73, 36, 70, 28,168,213,141,221, 80, 38,242,
+239,121, 25,155,153,118, 55,137,194,174, 84, 41,148, 85,183, 64,162,120, 21, 9, 84,184, 49,145, 29, 46, 45, 79, 64,165, 64,110,
+ 50,132,154,165, 69,214,148, 82,194,220, 74,138,147, 28,101,231,150,232,192, 66, 9, 86,185, 17,237, 36,216, 24,156, 79,108, 45,
+ 91,106,157,145, 17,119,146,170, 52,251,163,110,235,115,214,150, 35,192,191,179, 38, 60, 55, 42, 47,160, 19, 2,219,168,211, 29,
+118,157, 56,164, 20, 50,202,227,203, 3,158, 10, 73,232,220,233,143,193,167,180,203, 82, 67,210, 37,192,145, 88,170, 20, 52,150,
+230, 54,253, 90,120,113, 41,119,149, 69, 38,115,235, 1, 12,182, 7,193, 25, 9, 82,185,130, 82,117,175,119,139, 85,218,217,157,
+245,121, 66, 42,143,213, 32,176,154,170,185, 28,143, 69, 75, 2,115,178,106, 74,141,250,175, 22, 25,108,248, 12, 35, 8, 91,142,
+ 54,181,252, 5,122, 88,213,203, 28,145, 75, 78,229, 37,167, 97, 34,183,236,148, 33,148,223, 96, 69,197,183,176, 63,102,214,216,
+ 58,240,190, 68,114,250,243,152, 23, 19,199, 8,114,242, 72, 72,231, 22,188,108,205,176,101,137,213,157,138,160, 37,149,131,121,
+245, 2, 96,171,183, 20,137,123, 31,191,149, 91, 47,123,232, 85, 27, 62, 93, 6,181, 34,220,190,237,155,214,132,186,220, 88,179,
+217,150,220, 71,128,149, 75,125,138,149,169, 90, 75,203, 96,211,110, 42, 91,143,176,165,184,194,229,195,126, 59,201,121, 83,127,
+216,175,102,198,192,241,189,192, 78,211, 93,151,173, 66,131, 11,121,110, 27,122,109, 78,202,226,103,134,152,244,170, 29,255, 0,
+106, 75, 77, 80,127, 7,147,118,200,183,170, 81,169, 27,137,124, 65,102, 20, 38,171, 53, 4, 24,110,205,241, 18,226,164,123,227,
+ 13,202,211, 37,186,124, 33,108, 79, 16, 66,211,103,113,182,182,139,118, 84,173, 7,156,166,216,183, 99,192, 67,187, 32,202, 95,
+ 52,202,236,231,238, 88,201, 46,213,173,214,193, 83,203,133, 49, 50, 99,173,245,243, 52,203, 11,115,159, 93, 2,225, 42,126,233,
+240,185,105, 84,108, 74, 45, 95,108, 43, 59, 35, 69, 97,250,141, 10,138,230,217, 90,251, 48,139, 9,233, 47,173, 83,167, 92, 23,
+133,177, 85, 69, 46,182,212,244, 48,183, 86,228,216,112,223, 43,138, 95,241, 29,230,228, 19,170, 78, 41,201,115, 12,218,154,183,
+ 54,203,228, 66,244,207, 79, 57, 83,174, 48,118,211, 36,113,139, 51,236,182,144,200,197,209, 89, 4, 74, 66, 18,100,220, 71,196,
+ 25,253, 47,135,176,101, 60, 41,197, 99, 32,207,114, 92,228,102, 52,138,194,116,168,154, 25, 34,146, 41,169,214,165, 68,180,176,
+199, 36,210, 6,122, 3, 28, 20,213, 45, 28,143, 83, 37, 84,238, 34,143, 74,120, 89,225,111,121,247,111,121,238, 89,155,225,184,
+220, 82,237,142,251,112,146,253, 17,207,229,239, 14,200,188, 40,150,199, 16, 91, 53,100,203,106,223,161,219, 59,177,105,238, 28,
+ 8,141,191,184, 84,122,123,188,237, 86, 66, 93,102,187, 65,135, 61,155,146,157, 54, 68,117, 85,170, 29, 5,246,132,237, 76,171,
+ 94,215,181, 54,235,103,182,227, 99,237,219, 50,147,100,221,151,117,186,253, 38,155, 38,143,114, 90, 87, 4,106,212, 53,220,242,
+118,242,194,180,160,179, 75,166, 81, 39, 84,235,112, 68,217,140, 61,226, 50,212,247, 22, 89,118, 35, 77,235, 83,184,202,246,199,
+112,111, 70,219,122,181, 6,171,108, 65,226,231,125,105,213,122,204, 75, 11,108,236, 27,130,252,141,176,118,155, 98, 2, 33,193,
+175,238,213,251, 13, 81, 98,223, 52,197,206, 75,206,187, 71,165, 38,170,196,168,241,155,138, 85, 9,111, 46, 98, 52, 47,111,189,
+188,183, 37,209,109, 10,103, 17, 22, 2,110,109,194,146,227,138,131,118,219,246,163,116, 11, 98,132,235,103, 52,122, 75,118,253,
+157, 38, 77, 80, 90, 17,210,101,178,248,116,206,118, 75, 83,212, 28,101,175, 1,149,162, 45,226,190, 70,185,231, 0,203,149,228,
+121,123,231,153,198,105, 91, 28,230, 88, 16, 36,112,211, 70,154,212, 24, 39,149,165, 18, 74,198, 72, 89, 35,105,100, 12, 41,231,
+158,112, 57,145,137,231, 10,100, 94, 51,241, 87, 23,112,111, 30,211,112, 52,153, 38, 73,225,242, 10, 90,124,155, 50,146, 42,116,
+ 99, 45, 52,112,243,178,218,153, 12, 21, 85, 52,171, 42,205, 88,212,181,201, 75,149,209, 37, 91, 81,100,148, 51, 81, 75, 49, 50,
+ 6,217,173,183,155,188, 84,118,173,158, 32,172,235, 87,118, 54,166,179,183,149,203,134,222,225,242, 30,215, 80,233, 54,151,241,
+165,100,213,106,245,122,156,138,221,227, 2,160,150, 46, 42,164,235,130,161, 57, 86,251,132, 51, 77,169, 64,173,174,167, 38, 59,
+ 85, 4, 56, 26, 3,109,118,123,135, 41,252, 96,110,135, 23,245,109,254,221,189,165,168,219,173, 91,123, 97, 87,216,251,190,175,
+183,219, 85, 99,219,212,155,126,209,183,217,137,183, 10,131, 66,169, 76,169,205,176,225, 70,165,194, 83,180,116,125, 88,219,175,
+148,178,243,175,199, 75,173, 59, 29, 61,249,246,206,238, 94,228,237, 61,211,181,155,117, 97, 50,205, 62,247,110,151, 14,183,114,
+ 57, 71,149,102, 55,111,211, 40,145,161,125, 74,213, 25, 54,141,222,227,180,202,188,130,169, 82, 23, 30,151, 57,136, 16,218, 83,
+108, 72, 50, 38, 25, 64,114, 67,110, 47,253,229,176,174, 10,205,199,103,238,253,237, 99, 85,238,119,154,122,231,157, 75,174,215,
+ 74,238, 7, 25, 46,152,207,214,220,157, 58, 73,170, 74,109, 18, 30, 75,110,190, 29,121,180, 44,165, 42, 9,232, 21,240,162,151,
+ 56,225, 46, 16,143, 36,205,178, 88,214,186,130,176,206,181, 50,212,206, 37,168,141, 97,228, 37, 63, 46, 9,201, 90, 37, 96,103,
+142, 25,155, 74,243, 26,157, 97,150, 33,237, 83,203,114,127,162,199,141,220, 86,188, 75, 85,151,241,125, 31, 2,167, 23,193, 83,
+150, 54, 91, 79, 78,166,152,101, 85,109, 75, 81, 85, 61, 59, 60, 98,150,158,166,174,122, 58, 72, 42,106,150,136,102, 51,123, 10,
+ 85,205,152, 73, 43, 44, 16,206,123,218, 61,196,127, 12, 59,235,177, 53, 46, 29,169, 86,189, 55,136,234,109,215, 88,166, 26,197,
+ 38, 53,233,116,109,198,223, 91,198,222, 80,171,209,234,119, 5,221, 67,164, 25,151, 10, 5, 85,136, 33,154, 93, 49, 37, 18, 15,
+233,100,202, 97,150,139,131,132,251, 87,179,251, 79,179,194,224,147,101,216,244,202, 5, 90,229,159, 17,119,149,211, 72,110, 69,
+ 46,248,110,163, 29,217, 43,129, 66,171, 79,122,116,167, 35, 90, 76, 72,147, 37,216,236, 37,215, 98,203,117,126,245, 45, 50,100,
+114,186,222,133,219, 60, 77,113, 16,220,102, 29,123,136, 11,214,170, 86,194,217,230,148,229, 46, 98, 20,211,128,115, 50,125,254,
+146,190,100,228,116,200, 4, 30,163, 7,187,151, 72,226,234,249,165, 72,105,119,173, 54,145,119,199, 91,105,138, 42,209,169,240,
+173,203,214, 44,100,188,211,178, 16,205,110,152,208,135,112, 48,176,215,197, 10,171, 13,109,124, 69,109,200, 97, 95, 24,214,226,
+126, 46,204,248,131, 53,169,253, 34,207, 26, 53,144, 71, 4, 79, 21, 56, 17,133, 22,229,150,231, 57, 26, 1, 47, 34,187, 2, 44,
+ 52,198,170,139, 50,202,126,130,126, 47,120,111,192,109,194,252, 57,154,229,220, 65,148, 9,205,116,180,137,154,214, 10,186,170,
+162, 10,137,109, 91, 69, 71,150,198,235, 25, 10, 22, 25,169,163,100, 69,105,125,166,116, 70,126,237,240,173,188,242,233, 18,100,
+237, 93,235, 42, 60,202,109,114, 92,138,190,220,221,209,196,104,148,181, 76, 74, 16,170,157,149, 92,105,110,132,210, 43,242, 74,
+ 19, 42,158,164,115,198,158,234, 36, 48,143, 6, 66,144,210,247,177, 85,202,124, 85, 41, 50, 23,238,234, 96,171,220, 84,131,201,
+ 81,167,186,242, 66,220,103,194,112,116,136,167, 49,204,218,135, 38,114,149, 36,142, 82,142, 24,109,205,249,100,111,109,188,154,
+141,169, 87,121,132, 69,149, 25,154,133, 12, 70,102, 35,244,170,162,202,228,211,227,215,160,171,156, 70, 90,220,109,197,198,112,
+ 60, 25,150,134, 86, 98, 60,242,193, 74, 54, 70, 21,203,185,137, 49, 41,209, 55, 38,242,181,228,211, 26, 17,157,129, 46,114, 42,
+180,121, 76,135,128,240,207,214,112,156,148,134, 86, 18, 75, 79, 49, 33, 50,163,165,120,248,146, 57, 73,105,106,159,147, 26, 7,
+ 37, 20,121, 74,249,129, 29,199, 81,176, 38,192,147,176,176, 11,229, 39, 28,113,196, 92, 57, 81,148,103, 21,249,110,121, 69, 46,
+ 69,155, 81,200,201, 87, 73, 60,114, 67, 44, 19, 46,155,235,139, 65,117, 46,165, 73, 11, 30,131,175, 80,250,185, 64,199, 74,170,
+247,117,187,111, 83,215, 94,171,203,137, 65,135, 79, 67,143,174,161,207, 41, 13, 62,140, 15, 16, 83, 24,105,167, 37, 84, 28, 81,
+ 82,130,227, 69,105,245, 45, 71, 41, 66,191, 91, 76,133, 87,124,171,187,130, 29,167,217, 76,213,237,251,106, 66,189,205,119,162,
+ 28, 98, 37,199, 86,142, 16,162,185, 54,235, 12, 41,106,181,161,242, 45, 99,199,119,154,162, 48, 80, 81, 16,158,154,182,205, 62,
+117, 86,178,221, 66,238,151, 81,166,214,156, 82,227, 66,168, 73,171, 77,171,198,152, 82,188,180,236, 27,145,222, 95,115, 36,148,
+242, 70, 81,136,160, 29, 56, 67,138, 29, 54, 42,202,179,153,139, 37,154,143, 44,138, 93, 90,115, 13,179, 42, 84, 55, 84,228, 58,
+130,154, 32,177, 34,167, 76,116,248, 83,164,158, 85, 21, 58, 66, 29,194,202, 84,242,134, 53,191, 74, 37,168,148, 34, 92,139,239,
+126,187,219,125,133,150,228,146, 47, 98, 55,179, 1,136, 86,103, 62, 91, 69, 8, 36,153,106, 8, 60,182,111, 58, 40,216,157, 54,
+ 98, 36, 0,234,243,171, 58, 3,101,229,106,179, 43,139,104, 91, 70, 44,120,176,217, 45, 59, 21,146,164, 50,232, 71, 43,133,111,
+117, 90,230,100,144,252,149, 40,149, 41,210, 74,150,181, 21, 44,149,171, 39, 97,160,209,196, 74, 98,138,211,204, 1,101, 39, 41,
+232,160, 84, 80, 91, 86,122, 5,117,207,217,171, 93,167, 74,230,109,190,118,227,151, 50, 18, 67, 73, 80,101,207,212, 10, 45,182,
+190,169, 65, 32, 16, 14, 72, 61, 50,113,157, 59,206,211,128,167,184,215,134, 84,218,139, 67, 9,202,136, 9, 81,207,134, 79,235,
+ 28, 17,243,252,113,169,165, 53, 56,166, 68,176, 35, 72, 23,245, 29, 5,183,191, 78,155,254, 24,174,234,171, 13, 76,138,146,157,
+228,111, 49,216, 94,228,111,219,173,201, 22,181,250,250,130,207, 61, 76, 83, 78,129,201,136,206, 30,102,214, 63,241, 74, 61,219,
+ 81,242, 79, 81,141, 92, 33, 83, 11, 11, 43, 74, 70, 79,235,128, 48,146,159, 95,183, 89,187, 48, 16,248,113,190, 78,100,130, 82,
+160,176, 65, 32, 28, 5, 99,215,168,252, 53, 65,216,162, 34,146,199,235, 39, 31, 2,200,193,233,215,144,231, 79, 81,206,164,117,
+233,252,125,253,240,213, 89,206, 82,241,176,243, 14,190,132,117, 7,227,110,189,143, 94,183,197,134,155, 9, 14, 77, 73, 35,160,
+115, 31,105,236,123,140,118,214,207,217,208, 91, 67, 45, 2, 19,212, 36, 12, 14,163,212,156,142,135,247,233,135,163, 69, 10,155,
+158, 95,135,196,200, 0,103, 57,200,252,115,173,138,183, 84,150, 18,214, 79, 47, 42, 82, 64,200,200,192, 25, 63, 34, 51,173,102,
+107,129,181,255, 0,158, 33, 53,234,201, 4,224,108,194,246,251,207,207,175,124, 57,232,109,180, 51,202, 72,248,130,113,142,248,
+ 78, 0, 31, 35,235,246,233,191,188, 42,206, 66,108,193,167,132,253,103, 41,181, 0, 71,255, 0, 2,140,174,134, 73, 35,245, 92,
+ 39, 33, 30,121,235,229,171,141, 90,228,106, 11, 32, 52, 80,236,183, 73, 12, 70, 4,229, 74, 7, 30, 43,152, 63, 3, 41, 29, 84,
+123, 28,224,100,235, 5, 13,173,197, 57, 46, 67,138,125,249, 46,120,146, 95, 88,253,117,156, 97, 40, 39,245, 91, 0,225, 35,176,
+ 29,180,142,179, 80,220,168,205,149,126,211, 15,223,164, 16,122,250,158,195,208,145,134,108,155, 45,116,149,107,106,210,241, 41,
+186,161,255, 0,120,194,221, 71,236, 47,127,218, 35, 79, 77, 86,176, 66,163, 8,205,225,197, 43, 56, 37,105, 65, 56, 36,252, 75,
+ 82,212,174,171,112,149, 28,156,245,207, 93, 15, 45,216,241, 57,146, 57, 27, 56,200, 72,192, 89, 78, 15, 85,168,159,128, 99, 39,
+226, 63, 33,223, 89, 20,167,114,130, 10,130, 80, 72,248, 26, 31, 30, 65, 0, 16,165, 3,208,231,174, 61, 61, 53,129,212,188, 52,
+ 7, 20, 82,214, 78, 74,148,226,186,164,228, 18, 84,181,103, 36,244,238,122, 30,157, 53,185, 26, 44,106,170,160, 1,238,236, 54,
+253,214,249,247,206,169,100,122,153, 25,234, 36,251, 71,160,233,212,122,216,124,236,119,197,146,116,196, 43,156, 23, 20,234,176,
+ 66, 83, 24, 44, 50, 18, 79, 66,235,132,167,159, 61, 50, 50, 18, 9,206, 15, 83,172, 58,116,165, 37, 64, 4,182,218, 73,199, 59,
+139, 10, 82, 73, 66,186, 33, 13, 30, 94, 96,174,108,228,231,168,198,123,139,140,202,131, 79, 30, 70,148,227,238, 33, 74, 65,102,
+ 43, 97,196, 54,147,211,226, 81, 41, 74,129, 0,103,226, 56,236, 70, 51,172, 78,114,228,243, 5, 43,193,100,115,243, 36,120,134,
+ 75,201,194,128, 42, 71, 54, 17,204, 60,206, 74,114,122, 18,116,112,214,210, 59,223,241,219,240,190,226,251,116,251,158,201,176,
+ 10, 23, 73, 61,143, 95,141,182, 61, 58, 16,167,226,118,197, 23,220, 24, 42, 82,202,147,250, 50,234,130,146,217, 45, 36,168,133,
+ 45, 94, 71,175,197,215,174, 49,223,174,177,233, 50,208, 66,131,105, 61,214, 66, 64, 78,114, 64, 32,244, 61, 27, 42, 36,100, 30,
+ 80, 0, 29,250,232,185,104, 66, 49, 33,199, 21,150,220, 43, 66,158, 90,158, 9, 94, 72,229, 74, 84,180,165, 36,173, 63,234,146,
+156,146, 6,173,114, 20, 80,180,165, 72, 80,112, 20,145,206,164, 41, 92,139, 1, 96,182,144,172, 56,130, 20, 14, 50, 0, 39, 56,
+233,141, 46,141, 98, 54,244,254, 95, 29,247,198,133, 76, 90,206,166, 58,175,233,178,237, 97,238,254, 93,189,215,178,204, 42, 33,
+ 93, 64, 42,248,136, 81, 57,235,147,209, 95,205, 61, 51,156,117,229,239,140,107, 16,158, 7, 42,147,206, 74,138, 85,241,171,148,
+ 17,140, 96,145,216, 96, 12,125,253, 6,178,233, 89, 1, 42, 89, 0,224,140, 40, 16,146,179,204,164, 55,201,216, 60,158,153, 29,
+114, 59,100,118,197,106, 10,207, 40, 35,170, 73,230, 36,114,149,103,155,161, 9, 87, 86,241,147,231,213, 88,193, 58, 92, 49,218,
+223,135,110,159,187,221,238,253,216,103,145, 0, 34,219,123,186,124,143,147,136, 13,251,114,237,134,237,143,105, 46,242, 73, 13,
+ 22,133,233,109,109,125,248,227,197, 1, 40,126, 69,118,199,166,197,148,182,249, 0,241, 0,122,146,174,101, 31,136,168,158, 98,
+ 78,117,200,194,180,168,126,137,101, 88,239,233,246,107,183,127, 72, 24,180,175,104, 99,158, 27,161,215, 19,195,254,205, 37,246,
+129,255, 0, 34,180,195,184,124, 52,148, 17,150,202,152, 45,175,169,201, 11, 7, 0, 99, 92, 70, 83,105,199, 81,140,246,229,242,
+249, 29, 75,178,155,181, 13, 41, 59,217,109,211,176, 36,116,235,219,242,199, 51,241, 50, 44,124, 69,158, 34,159, 47,181,212, 31,
+255, 0,116,172,199,247, 18,113, 76,168, 40,116, 72, 29, 62, 47, 63,188,117,208,235, 35, 24,207, 92,244,254,221, 86, 40, 35, 62,
+152,207, 95,232,251,116, 51,133, 67,168, 78, 71, 81,243,251,244,236, 6,194,221, 48,206,160, 29,173,211,161,253,216,162,179,229,
+143,191,211,175,217,170, 11, 0,227,176,245,245,199,175,207,160, 58,244,188,254,177,201, 82,124,188,177,231,246, 29, 81, 39, 39,
+ 58, 93, 70,194,221, 63,158, 20, 24,164,230, 60,136,232, 72,244, 39,183,109, 12,178, 9, 61,242, 59,122, 30,223,214,116, 74,241,
+130, 73, 3, 7,167,246,245,213,189,240,234,136,240,212,148, 97, 95, 22, 70, 74,128,236, 58,249,233, 68,235,140, 3,126,155,227,
+193, 36,156,254,113,165,175, 10, 63,237, 99,238,206,116,180,125, 62,182,191,207,191, 25,199,180,146, 15, 65,159,151,174,171,165,
+ 93,142, 58,142,227, 61, 70,135, 31,120,254,145,251,117, 92, 96,245, 30,127, 46,250, 37,188,191, 15,195,231,231,124, 12, 86,241,
+ 19,156,117,235,231,142,159,126,136,111, 10,193, 74,187, 28, 99, 24,201, 62,191,136,252, 53, 65, 9, 0,131,220,244,251, 58,232,
+164,225, 61,178, 7, 94,221,254,236,246,210, 76, 24,139,124,252,223, 25,219,239,197, 69,160,168,119,233,221, 93, 78, 6, 49,216,
+125,186, 33,164,115, 36, 40,247, 29, 66, 71,160,233,235,170, 64,133, 15,207,113,215, 69, 36,242,224,244,244, 35,208,105, 34, 0,
+ 39,190, 49,143,104,101, 42,238, 57, 85,215,168,198, 72,251,188,244,123,104, 72, 72, 24,201, 79, 78,191,187,166,132, 65, 39,226,
+ 72, 25,244, 39,167,152,251,180, 90, 22,144, 1, 87,195,147,231,252,236,250,124,244,153, 23,216,158,159,233,140, 17,124, 28,214,
+ 58,114,244, 24, 61, 62, 93,191,167, 70, 32, 12,103, 39,230, 60,137,199, 94,154, 13,178, 23,215,168, 29,253, 59, 99,250,245, 93,
+ 11, 73, 95, 47,114, 62,127,102,127,103,150,147,194, 39,221,190, 13,108,129,145,140,228, 16,160, 70, 82,164,158,133, 36,121,130,
+ 9,200,212,133,253,149, 30,214, 40,187, 66,197,191,195, 39, 20,245,169, 15,236,235,143,162, 14,220,110,140,213,189, 54,163,181,
+211,100,184, 17, 30,135,114, 58,162,165,203,177,148,226,240,211,164,149, 65,206, 21,150, 70, 83, 30,118,242, 14,122,121,126,206,
+218, 33, 39, 37, 68,227,168,229, 32,128, 82, 65,232, 65, 7,184, 56,237,231,157, 55,102, 89,109, 54,103, 78,208, 84, 37,251,171,
+ 11,106, 86,236, 71,240, 32,236, 71, 81,211, 14,249, 22,123,153,112,230, 99, 22,103,149,205,202,158, 63, 43, 43, 92,199, 44,100,
+130,209, 74,160,141, 72,214, 29,195, 41, 1,144,171, 0, 71,233,189, 78,163,199,149, 6, 5,118,137, 50,159, 88,161, 86, 97,179,
+ 50,145,112,209,228,179, 81,164,214, 32,202, 66, 93,106,101, 62,161, 25, 74,109,214,150,210,146, 82, 66,186,115,105,198,165,210,
+220, 45, 54,156, 0,210, 18,130, 16,156,144,132,160,130,113,234,163,215, 63,102,191, 63,142, 13, 61,168,188, 90,112, 88, 35, 91,
+187,121,119,179,119,109,106,165, 54,185,123, 83,184, 1,218,213,172,195, 74,112, 25, 31,193,231,222,112,191,110, 58,164, 21,224,
+ 48,176,215, 49, 7,195,198,117, 59, 45,161,226,130,149,124,109,157,131,126, 59,105, 34, 25,190,109, 42, 53,196,184,241, 30, 15,
+198,138,237, 78, 35, 82, 31,140,211,167,245,219, 66,220, 41, 7,190, 19,170,167, 56,203,165,200,101,140, 85,149,104,230,213,203,
+101,189,155, 78,155,220,117, 82, 3, 46,198,227,123, 43,181,137,199, 98,248,121,226, 4, 60,107, 28,144, 81,211, 52, 25,134, 94,
+168,243,195, 33, 13,165, 88,233, 15, 20,151, 2, 68,212, 8, 23, 84,117,184,212,128, 27,157,174,166,211,138,218,110, 68,166,202,
+ 12,226,136,177,129,232,166,216, 72,248,148, 83,159,213, 41, 3, 58,199,247,101,136,115, 44,202,189,191, 58, 53, 62,165, 75,147,
+ 13,232,255, 0, 85, 84,225, 70,168,193,124, 22,212, 1, 92, 57,109,173, 42, 25,207, 92,107, 7, 94,247, 82,222, 44,120, 49, 37,
+ 54,166,153, 62, 27, 97,162,180,183,147,212, 19,228,122,244,251, 53,166, 60, 82,241,139, 69,219,203, 98, 69, 54,140,180, 86,247,
+ 30,234,150,139, 66,201,183, 25,149, 29,233,234,185, 42,196, 70,134,169,113,219, 89,247, 70,154, 91,161,107, 46,114,242,132,100,
+244,206,153,205, 97,168, 2,158, 4, 44,100,219,125,135, 64, 78,228,219,222, 73,244,222,221,174, 76,131, 35,204,179,124,218,130,
+135, 45,164, 51, 85,202,227, 76,106, 62,206,255, 0,109,219,126, 90, 70,190,103,145,136, 84, 93, 78, 72, 23,191, 48,247,123,113,
+ 54,107, 98,106,146,105, 9,180, 41, 21,123,162,141, 80,151, 62,153,110, 91,228, 81,105,212,218,178,156,241, 34, 77,169, 72,130,
+226, 75, 2, 57,229, 90, 91, 71, 95, 19, 25, 61, 49,174,102,239,183, 16, 27,245,196,245, 64, 82,110,171,182,181, 46,217, 96, 6,
+ 35,218,212,137, 51, 32,219,108,198,105, 92,201, 85, 69,199, 30, 6,166,164,128, 10,220,112,144, 72,251, 53,214,202, 31,178,178,
+163,118, 58,154,214,227,110,196,250,141,229, 94, 90,234,215, 82,232,240, 89,168, 70,166, 84,170, 4,190,168, 41,121,249, 0, 76,
+ 90, 29,119,151, 56, 9,248, 73, 25,214,146,202,219, 91, 51,104,184,161,111,104, 55, 2,101, 83,114, 54,198,194,191,169, 77,110,
+ 68,221,177,164, 63, 85,175,214,237, 88,241,211, 82,147, 76,141, 78,128, 22, 91, 87,142,150, 98,205, 74, 85,132,248,171,248,142,
+ 53,173,150, 83, 84, 83,203, 81, 44,142,139,160, 27, 2,160,233, 3,114,117, 16, 12,141,127, 70, 80, 9, 35,125,241,233,239,130,
+ 41,224, 38,103, 13,117, 54, 67,153,205,226, 87, 28,112,190, 95, 45,125, 92,210, 83, 86,187,242,226, 42,178,174, 80,149,113,165,
+ 44, 65,229,100,134, 4,141,150,122,141, 81, 51, 73,162,237, 30,168,196,225,210,109,131,180,183,158,251, 93,182,173, 90, 77,131,
+ 96, 89,181, 75,242,173, 86, 98, 49,102, 9,183, 41, 18, 99, 82,213, 61,169,147, 28,108, 26,115,213,233,208, 41,241,139, 73, 89,
+155, 50, 88, 98, 57, 82,144,225, 71, 44,173,110, 47,174,107,174,254, 98, 13, 58,249, 85, 6,131, 87,171, 39,220, 44,241,181,244,
+153,180,166, 32, 5,149,154,122, 42,162,227, 19, 75,165,128, 71,188, 56,178,174,115,204, 82,145,128, 36, 3,237,235,223,234,222,
+215,112, 55,182,219, 31, 86, 98, 61,181,187,220,112, 95,208,183,126,253,180, 97, 54,220, 21,109,191, 13,155, 89, 33,113, 54, 95,
+106,218,165, 50, 18, 40,148,150,231,154,107,198, 55, 42, 67,242, 41,179, 93,113, 42,113, 74, 86,162, 97,177, 48,209, 39,113,161,
+ 58, 64, 13,211,225, 75,148, 51,140, 36,165,190, 84,143,159, 65,171, 75,135,178,168,107,242, 90,172,214,180, 51, 59,234, 16,134,
+ 17,190,133, 64, 20, 55,158, 54, 2, 70,146,225,136, 0,174,157, 43, 97,185,243, 63,233, 63,244,231,241, 66,159,196,102,225, 15,
+ 14, 51, 37,224,188,143,132, 9,142,161,114,156,207, 55,165,122,154,211,180,201, 83, 95,148,230, 89,116,181,212,212,192, 8,224,
+ 5,150, 25,142,186,190, 84,124,245,138, 25,117,109,141,230,157,201,225, 47, 99,174,184,147, 81, 37,251, 42,185,185, 27,109,239,
+116,234,109, 66,219,122, 4,155, 82,247,170, 85, 97,120, 77, 63, 82,121,198, 42, 45, 83,110,106, 65,247,182, 36,165, 14,184,226,
+150,194, 25, 9,113, 3,110,182,151,139,125,212,183,132,104, 23,139,113, 55, 18,137, 24, 33, 42,171,202,150,138, 77,231, 10, 58,
+ 80,148, 41,215,106,105,101,113,238, 23, 2, 0,109, 6, 99, 41,127,224, 0,190, 84,115,174, 89,251, 50,110,182,111,109,161,226,
+ 3,101, 36, 58,211,149,138, 21, 94,218,222,203, 78, 35,202, 81, 46, 82,231,199, 69,129,126,193,167,180, 63, 93,214,103,194,179,
+170, 50, 48, 15, 42,103, 21,168, 17,147,174,130,217,182, 49, 51,154, 91,177,188,102,144,164, 58, 35,144,191,242,169, 25, 99,159,
+148,124, 72, 7,226,207, 80, 49,207,131,216, 83, 92, 69, 69, 29, 6, 99, 95, 73, 34,235, 8,250,148,236, 9, 14, 17,197,138,133,
+ 2,215,210,116,217,110,164, 91, 97,105,119,134, 62, 33,208,248,151,225,118, 89,196, 28, 81, 28, 85,249,213, 91,213,189, 89, 99,
+ 36,143,237,143, 83, 41,169,117,146, 89,165,169, 6,105,139, 75,170, 73,228,145,245,134,150, 73, 9, 44,122, 97,110,111,221,149,
+120, 67,165,189, 58,161, 34,214,201,105,134,233, 55,148, 69, 83, 11, 50,221, 90, 92, 68, 40,213, 72,110,200,135, 46, 73, 41,108,
+171, 14,167,245, 84,130, 65,200,211,166, 94,171, 84,102, 51, 47,194,143, 89,131, 9, 5,184,240,105, 85, 40,147,218, 74,222, 40,
+ 89, 97,227, 2, 67,137, 97, 78,252, 5,254,110, 85,114,132, 39, 9, 72, 32,233, 93, 14,201,122, 65,143, 22,156,212, 69, 86,100,
+ 46, 44,135, 38, 57,135, 33,219,180,231, 22,234, 83, 60,161,192, 10,170,170, 8,144, 33,178, 71,233, 29, 30,242,191,208,181,133,
+191,182,125,129, 22,137, 24,184,219, 16,105,244,122,116,229, 24,172,196,140,227, 51,106, 82, 37,172, 0, 92,153,226, 37,249,213,
+ 57, 83, 22,165, 18,225, 82,222,113, 69, 74, 9, 71,234, 68, 9,208,198,209, 94,219,218,228, 15, 83,112, 65,184, 62,227,110,189,
+109,178,169, 62, 83, 5,218,149,249, 37,181, 42,198, 87, 89, 80,199,253,217, 86, 70, 70, 98,204, 20,146, 89,197,201,101, 22,230,
+ 59,242, 41,215, 69, 77, 73,128,236, 67, 18, 58,167,154,138,231, 60, 4,102,158,150, 80, 82,130,218,157,115, 45,198,101,174, 84,
+165, 1, 68,114, 52,130,156, 99, 89, 45, 34,212,134,228, 73, 16,146,227,205,181, 1,201, 78, 77,171, 38, 42,218,143,227,144, 4,
+201, 12,201,115, 36, 71, 12, 32,165, 43, 3,226,248,212,144, 10,146, 53,126,180,172,233, 73,154,154,212,168,202, 93,197, 80, 97,
+136,104,140,211,242,100,192,162,196,109,194,166, 41,208,221,148,163,201,135, 23,227, 62,232, 78, 95,127, 36, 0,218, 27, 1,238,
+160, 90,138,170,136,112, 34,196,122,116, 24,179, 26, 97,224,201, 66,151, 91,158, 22,121, 26, 8,112, 2,184,136,155,133, 28, 30,
+ 89, 15, 32, 1,204,132,117,220,138, 25,100, 69,141, 33, 42, 95,185,185, 36,108, 64,216, 41, 3,125, 76,119, 96, 54,234,214, 58,
+ 53,249,220, 11, 78,232,142,144,194,128, 23,101, 1, 6,175,214, 62,103,112,219,249, 82,197, 84,238,108, 17,110, 52,139,118, 47,
+ 29,184,225,215,110, 42,187,173,184,204,207, 72, 80, 85,167,183,182, 36, 9,173, 70,184,111,106,192, 66,170,116,219,106,146,227,
+200, 80,164, 50,235, 10, 77, 66,191, 84,117, 10,106,153, 79,228, 73,241, 36,174, 36,119,184, 21,190, 59,243,185,156, 69, 84,159,
+170,238, 77,125,233,212, 64,224,114,153, 96, 80,157,149, 74,219, 91,113,168,200, 9,139, 79,161,218,173,191,225,204,247,118,130,
+ 18,103,207, 18,106, 18, 92, 10,125,231,194,214, 80,151,139,218, 61,196, 11, 91,199,196,197,237, 22,149, 81, 84,157,189,217,229,
+191,180,182, 2, 88, 11, 17,100, 68,160,212, 84,221,239,112,178,210, 9,241,102,214,111,225, 52,151, 48, 84,168,148,168, 76,161,
+ 74,109,180,160,115,231,137,235,103,118, 56,127,147,104,217, 55,156,251,107,111,175,235,178,220,141,117, 86,109, 75,154,123,113,
+238, 29,183,163, 87, 2, 87,106,211,239, 74, 50,150,145, 64,189,234,148,231, 29,158,154, 36,149,174,165, 75,167,166, 52,138,188,
+ 24,138,159, 21,133,236, 83,112,252,185,180,169, 8,169, 20,176,234, 0, 18, 88, 7,176, 39, 89,211,114,119, 4, 70,189, 44,161,
+148, 22,190,159, 75,188, 43,225,207, 12,190,140,158, 22,229, 62, 49,120,177, 11,207,199,124, 79, 74, 43, 96,166,138,138, 92,199,
+ 54,166,167,120, 99,153, 50,252,166,134, 37,121,162,150, 40, 36,137,243,154,231,228, 65, 75, 44,172,185,141,117, 61, 12, 49,202,
+ 64,184,109,119,103,132,181, 74,129, 79,134,194,135, 43,190,237, 21,191, 29,100, 96, 37, 40,117, 73, 82, 99, 35, 32,124, 88, 42,
+ 63,170, 53,226,221,219, 54,154,144,210,159,144,184,110,188,191, 9,111, 50,130,176,158,110, 80, 84,251,171,202,128, 1, 93, 73,
+229, 25, 56, 37, 0,140,233,155,215,238,236,178, 81,245, 6,230,196,184, 38, 72,117,114,146,204, 10,157, 18,124,222, 68, 55,238,
+229, 13,192, 85, 62, 51,171,139,134,207, 35, 41,140,233,231,202,146,147,144,117, 96,166,239,230,251, 91, 78,170, 52,187,154,100,
+238, 69,175,198,143, 95,161, 83,106, 18,154,101, 79,165,231,152,117,164, 67,133, 45,134,212, 82, 91,194,156, 5, 45, 44,164, 2,
+ 66, 84,155, 34,147,133,243, 36,165, 20,116,217,188, 35,151,238,126, 97, 4,254,177,125, 68,239,211, 82,223,173,172, 0, 24,167,
+179, 47,246,170,125, 30,232,243,104, 31,139,124, 24,227,142, 30,161,169,102,142,147, 50,172,203, 50,121, 41,229, 42, 69,218, 3,
+ 30,118,241,202, 0,243,200, 41, 94,165,129, 22, 42, 88,227,163,116,203, 17, 8,185, 93,183,106,208,252, 38,221, 75,239, 69, 82,
+148,212, 98,226, 86,217,118, 44,165,167, 9, 65,101,223, 60,148,144,181, 96,168, 43, 0,252,174, 91,214,181,183, 10,117, 86,179,
+ 50,153, 73,166, 83,194,214,252,233, 83,209, 26, 43, 44,162, 64,140,219,206, 58,234,210,112,235,191, 11, 64,100, 44,244, 4,168,
+145,172,123, 98,119,186,189,184,148,118,141, 70,148,197, 50,191,111,207, 66,201,167,161,249, 52,249,241, 42,212,229, 7,204, 15,
+126, 66, 92,110, 3,140,161, 73,118, 19,202, 81, 97,108,148,161,199, 27, 91, 78,107, 86,119,238,216,221, 43,230,252,250,182, 13,
+ 58,183, 46,147, 70, 13, 38, 4, 56,116,185,179,162, 69, 46,180,223,141, 81,142,184,140, 41,147, 41,114, 84,242, 75,171, 82, 84,
+194, 91, 72,230, 64, 90,214,181, 33,200,201,170, 43, 89, 94,208, 24,128, 15,166, 66, 20,216, 3,112,111, 96, 88,110, 78,159,118,
+155,220, 99,160, 60, 98,250, 99,112,207,134,255, 0, 71, 46, 29,250, 64,120, 83,195, 50,248,169,148,241,245, 69, 30, 93,144,193,
+ 67, 79, 83, 28, 82,215, 85,189,122,153,115, 32,105,154,178,134, 26,105,168,101,163,146,156,211,189, 75,102,130, 44,173, 68,114,
+ 77,207, 71,110, 15, 18, 59, 61, 18,251,183, 45,234,180,107,233,187, 1,250,171, 17,238,235,214,213,164, 83,170,247, 53, 22,146,
+247, 59,114, 43, 22,149,141, 85,159, 17,119,100,134, 63, 68,234,163,187, 34, 18,164, 53,206,152,138,117,244,161,183, 58,193, 87,
+225, 15,135,235,154,206,165, 93,187, 71,198, 37,215,186, 16,174, 74, 84,106,197,183,252, 7,217, 27,135,115, 66,233,111,133,248,
+ 82,110, 88, 27,108,185, 18, 44, 98,226,138,217, 76, 74,176, 98,168,211,208, 31, 14, 67,113, 0, 40,199,138, 77, 58,219,219, 50,
+244,105,201,133,114, 94, 12, 56,227, 82,225, 41,246,106, 20,107,126, 74, 1, 10, 21,105,145, 29, 83, 87, 29,105,183,135, 90, 99,
+ 14, 24,108,168,230,161, 33,210,145, 21,121,134,197,241,157,196,167, 13,119,204,187,239,101,247, 94,228,180,103, 85, 93, 74,238,
+122, 27,239, 11,130,196,190, 89, 74, 3, 65,139,247,111,234,106, 52,187,152, 37,129,200,203,193,152,211, 98, 54, 3,112,101,197,
+108, 4,133,235, 56, 58, 10,228, 87,202, 71,178,152,134,242, 75,119, 19, 27,222,225, 88,150, 31,254, 96, 54, 34,214,141,213,129,
+ 30, 77, 63,251, 74,190,146, 28, 63,196,245, 21, 94, 41,241, 81, 90,138,137,238,120,103,135,232,114, 90, 51,145,166,250,161,204,
+ 42,243, 28,191, 56,115, 80,172, 17, 36,201,106, 30,171, 49,165, 99, 58,215,215,101, 85,180,199, 46,155,165, 84,250,206,231,112,
+167,186, 84,202,229, 58, 84, 41,147,169,133,248,238,197,175, 91,119, 93, 18,221,187,232,146, 84,224,168,218,183,125,171,122, 80,
+169,146, 69, 62, 91, 77,165,197, 50,182,199,186,202, 90, 37,197,125,153, 76,161,221, 73, 67,102,161,181,186, 27, 75, 97,238,133,
+149, 75,174, 53,111,223, 86,211, 87,109, 54,213,185, 35, 77,146,237, 17,137, 14,200,167, 84,169, 77, 86, 23, 24,190,212,104, 85,
+ 56,114,217, 98, 72, 75,241,159,101,166,228, 0, 16,240, 9,226,206,213,123,125,246,154,253,183, 26,179,248,203,225,125,202,139,
+ 46,178,168,179,235,251,104,229, 22,255, 0,179,166, 52, 82,164, 41,247,246,211,115,158,110,161, 69,150,180,149,143, 14,155, 84,
+150,134,210,172, 54,180,249,236,206,213,123, 69, 61,143,214,236,216, 85,123,123,115, 55,238,195,166,195,122, 53,197, 19,108, 46,
+ 26, 79, 16, 44,236,253, 26,226,128,250,223,131, 85,141,183, 84,234,188,232,106,173,199, 90,212, 89,142,137, 15, 83, 81,144,125,
+209,101, 40,228,141, 47, 10,102,180,149, 86,154,156, 24, 92, 29,108,129,135,154,226,204, 2, 44,137,115,111, 54,226,254, 93,182,
+ 24,147,120,185,244,188,240,119,233, 7,195,249, 54,103, 93, 17,224,159, 17,114, 33,203,106,209, 45, 37, 92,121,173, 8, 71, 34,
+150,170, 58,150,200,101,166,150, 41,220, 61, 44,139, 5, 76,112,171,213, 71, 20,136, 39, 4,118, 6, 29,186,134,194, 27,148,195,
+193, 62, 44, 68,187, 21,106,102, 84, 30, 70, 85,205,142, 80,158, 87,201, 81, 7,153,192, 0,192, 80, 64,211,149, 66,165,180,203,
+136, 67,104,240, 27, 90,130,130, 17,226, 37,166,148,162, 1, 67, 73, 94, 66, 83,252,227,140, 39, 39,160,215, 35, 46,223,110, 95,
+179,178,219,105,233,244,219,195,120, 47,233,139, 89,112, 67,182,118,102,191, 77,247,149, 21,115, 41,196,213,175, 41,244,200,241,
+ 80, 85,142,139,201,194,137, 9,207, 77,115,159,136,255, 0,164,222,229,137, 30,163, 15,134,190, 13,228, 85,153, 9, 87,213, 91,
+165,191, 87,204,167, 45, 40,174, 45, 76,182,204,169, 86, 14,216,198,101,228,255, 0,133,202,109,178,212,219,137,132, 41,194,148,
+158, 96,180,131, 37,202,248,118,182, 90,133,138, 42,118,185,221,117,133, 75,133, 32, 29,216,168,185,189,236, 14,163,109,129, 0,
+219,143,243, 63, 16,184, 90,150, 55,105,115,232, 42,165, 31,169, 77, 42,212,177, 32, 14,130, 18,226,224, 0, 53, 57, 0,216,238,
+ 55,196,195, 45, 68, 22,211,205,146,176,133, 54,151, 20,132, 15,133,229,231,144, 40,224, 37, 5, 65, 39,151,155,148, 18,158,152,
+235,167, 48, 77, 75,205,166, 35, 10,241, 36,158, 64,164, 52, 60, 79, 9, 9,207, 48, 83,160,114,149,103,148, 96,103,182, 73,215,
+230, 7, 43,219,203,237, 79,157,190,246,230,253, 61,196,180,212, 75,181, 94,156,213, 51,101,233,182,221, 22,223,225,210, 69, 2,
+168,227, 11,169,218,181,125,167,162,176,212,122,212, 25, 8,142,218,126,176,154,244,170,211, 68, 7, 88,168,182,234, 82,177,213,
+203,167,233, 12,113,211,199,133,235,182,188, 54,240, 99,176,227,101,238,251,254, 37, 46,135, 81,183,246,214,113,190,247, 95,112,
+ 47, 39, 98, 37,203,129, 54,157,199, 86,136,195, 22, 53,140,193,106, 91,252,225,149,204, 98, 19, 75,118, 84,180,165, 7, 18,169,
+178, 74,170, 69, 51, 56, 73,209, 23, 81,210,224, 42,219,115,204, 50, 5,109, 34,219,149, 87, 3,115,219, 16, 36,241, 71, 32,204,
+ 22, 85,167,138,163,219, 12,129, 32,128, 37,228,152,177, 1,116, 88,216, 92,246,107, 17,218,230,195, 19,125,171, 92,246,205, 30,
+ 90, 32, 84,171,244,168,149, 5, 16, 61,205, 83, 89,247,180,147,216, 56,218, 23,148,121,247,198,178,122,125, 22, 5,114, 40,154,
+138,154, 22,210,134, 80, 99,180,183,112, 79,162,136, 1, 95,118,123,235,152,220, 17,123, 63,247, 3,103,237, 26, 77,219,197, 85,
+255, 0, 51,114,119,174,160,202, 42, 21, 90, 12, 74,180,170,149,181,104,202,120, 37,197,211,222,171, 73, 81,114,229,171,182,181,
+ 40, 63, 37, 88,100,184,149,120, 41,228,194,143, 75,153,101, 48,185, 91,107,153,134,155, 1, 8,109,165, 41, 41, 74, 64, 1, 32,
+ 4,224, 99, 3, 80,103, 78, 51,204,101,157,185,180, 57, 21, 10,146, 34, 81, 20,149, 19,184,236,206, 95,148,177,131,216,104, 15,
+110,168,167,108, 60,209,182,123, 57,246,138,169,146,133, 91,117,142, 38,105,152,127,215, 43, 89, 24,145,251, 10, 7,241,197, 84,
+154,117, 14, 91, 72, 18,147, 35, 46,114, 97,104, 83,107, 42, 39, 25, 0,249,254,115,167, 66, 11,229, 77,120,141, 0,191,209, 21,
+ 33, 25,229,241, 84, 82, 74, 83,146, 59,103, 90,221, 94, 77, 82,101,118,154,148,130,244, 86,221,202,228,255, 0, 60, 39,160,229,
+ 89,254,119,200,247,211,203, 6,164, 88,105,150, 65,236,148,131,147,213, 56, 24,206, 62,221, 45,195,237,153,206, 43,169, 51,119,
+ 73,100,164,125, 34, 72,211, 64, 97, 96,110, 1,191, 81,243,214,210, 12,210,138, 24, 41, 40,102, 89, 57,178,213, 33,105, 1, 32,
+244, 32,111, 96, 45,125,246,219,221,139,140, 97, 48, 58,236,154,131, 46,153, 46,146, 87,204,146, 82,132, 15,242,109, 36,167,167,
+132, 6, 59,119,206,190,200,170,100,132,160, 21, 41, 56, 1, 36,134,210,133,100,156,114,158,195,191,225,170,166,170,211,105,248,
+149,212,255, 0, 59, 56, 36,156,100, 15, 64,113,246,235, 24,171,213,226, 60, 10,142, 60, 84,244, 75,137,232,164,103,245, 65, 82,
+ 71, 80, 58,100,117, 7, 79,209, 82,242,147, 69, 59,116,245, 27,159, 93,250,111,240,235,241,195,116, 85,144, 77, 56, 50,195,229,
+ 27,121,122, 40, 22, 2,202,123, 1,254, 33,247,226,229, 38, 74,212,210,138,159, 75, 96, 2, 2, 89, 3,156,146, 72,192, 46,118,
+242,234, 6,176,138,131,208,130,143, 59,105,144,180,243, 97,114, 84,183, 74, 71,117, 30, 85,124, 41, 72, 32,103,160,201,234, 15,
+ 82, 53,100,169,214,165, 52,218,131, 78,182, 91, 7, 5,229,115, 43, 41, 62,101, 9,253, 85, 99, 29,115,128,122, 16, 53,132, 78,
+168,190,250,242,169,137, 87, 33, 4, 48, 26, 80,111, 0, 28,172,132,175,226, 56, 4,128,162, 71,159, 77, 32,237, 34, 54,153, 1,
+ 86, 59,239,247,110, 15,243,248,219,221, 40,164,162, 89, 84,201, 21, 66,136,191,195,112,122,116, 32, 11,143,131, 90,221, 78,196,
+ 28, 93,170, 53, 86,220, 45,182,214,121,193, 56, 75, 24,202, 63,156,175,242,120, 8, 79,194, 49,147,208,172,140,107, 28,144,185,
+ 14,165,196,243, 54,128,227,107, 95, 40, 1,247,148, 10, 82,160,148, 36,114,161,156, 18,146,126, 53, 99, 7,225,193, 26, 21,201,
+165,223,209,170, 87, 43, 69,196,145,224,199,109, 32, 21,142, 84, 37, 68,147,135, 50, 73, 61, 7,235, 99, 61,180, 42,150, 9, 83,
+110, 45,199,193, 66,138, 91, 83,156,173,178, 57, 84,149, 20,132, 36, 4, 47, 4,158,234, 33, 74, 7,212,107, 34, 85, 36, 91,174,
+195,111,187, 14, 2, 4,136, 88, 88, 50,239,114, 9,216,252, 64,239,107,131,210,253,111, 96,106,135, 9,241, 91, 90,152,154,224,
+ 81, 10,117,183, 66,150,132,132, 32,132,199, 90, 18, 18,211, 62, 25,202,136,229, 86, 80, 71, 55, 78,180, 86,211,138, 90,218,109,
+210,132,173, 42, 40,195, 97,226,160,188,146,149, 61,202, 17, 24,252, 7, 4,147,128,148,146,114,179,143,162, 72, 66, 20, 93, 82,
+ 91, 32,243,151, 0, 13,184,226,121, 87,250, 54,210,216, 3, 57, 40,248,112, 84, 48,188,119,233,112,142, 86,234, 29, 75,124,173,
+161,158,235,112,133, 50, 75,156,174, 56,246, 66,135, 48, 3, 10, 10, 0,128, 64, 10, 4, 29,108, 70,250,118,191,227,252,183,237,
+110,134,223,125,175,163, 80,140,221,139, 15, 94,194,214,251,186,251,205,239,140,110,108, 82,150,189,228, 33,212, 54,225, 10,142,
+ 29,108, 40,168, 1,209, 40, 65, 63, 3, 28,169, 5, 42,200,193, 95, 80, 71,124, 14,168, 18,210, 86, 21,203,202, 82,160, 8, 0,
+169, 41, 24, 9, 81, 60,184, 87,196,165,224, 12, 28, 28,231,190,156,202,203, 43,100, 60,180,187, 46, 83,142,128, 90, 68,167, 20,
+ 70, 74,148,144,167, 1,235,149, 35,157, 71,249,216, 72, 0, 37, 61,155,106,154, 76,153, 41,136,149, 4,169,231,163,196, 66,202,
+129, 9,117,245, 33,158, 98,160,112, 71,136,224, 32,158,132,126, 26, 84, 48, 2,250,134,223,233,191,126,157,125,253,112,216,241,
+ 18,202,161, 65, 55, 29, 0,222,246,181,135,238, 29,126,252, 64, 99,219,127,112,181,112,123, 74,183,173,166, 28, 82,255, 0,130,
+214,206,212, 89,178, 82,176, 66, 90,159, 67,176,105, 47, 75, 67, 68,147,204,215,137, 82, 24, 35,204, 30,154,228,170,206, 51,216,
+231,166, 58, 99,237,251, 53,183, 60,121,238, 60, 93,220,227, 99,138,189,200,132,233,122,157,114,111,133,244,154,114,249,150,180,
+154,125, 6,168,171, 94, 25,104,172,228, 50, 89,161,161, 72, 29,130, 92, 0,116, 26,212,101,246, 56, 61, 59, 96,227, 63,241,212,
+247, 43,140,165, 5, 18,176,179, 8,144,144,122,130, 84, 18, 62, 32,155, 28,114,150,121, 50, 85,103,185,197, 66, 29, 81,207, 87,
+ 80,202,123, 21, 51, 57, 82, 15,189,108,126,252, 8,178, 15, 79, 76,232,117,245, 36,142,192,224,252,191,179, 85,214,174,254,137,
+207,231,246,104,101,224, 28,231,161,235,248,233,200,126,252,104, 1,220,109,129,221,230,199, 97,142,189,189, 51,215, 63,159, 61,
+ 14, 64, 0, 96,247, 29,126, 71, 68,169, 89, 62,120,252,245,208,202,238, 79,204,253,154, 92,108, 5,240, 48, 58,192,202,135, 67,
+215,243,231,249,198,133, 81, 3, 57,249,224,119,237,229,162, 28, 39,169,249,249,126,125, 52, 26,200,251,199,127,179, 74, 45,198,
+227,126,216,200,253,248,160,178, 50, 58, 3,211,207, 63,184,253,186, 90,240,163,147,159,195,236,210,210,184, 24,175,170,168, 61,
+ 49,215,167,225,161, 16,112,122,156,116,213, 97,248,103,161,251, 51,164,216, 90,227,174,173,255, 0, 60,100,245, 38,214,190, 14,
+ 73, 56, 0,142,152,239,145,247,116,213, 66,176, 7, 82,172,142,216,249,246,207,222, 52, 58, 84, 83,211, 29, 7,111,236, 58,242,
+ 80,162,174,101, 47, 8, 61,128,206, 71,222, 7,174,116,131,222,222,236,101, 69,254,127,150, 46,141,168, 96, 0, 57,137,206, 73,
+254,145,243,192,215,213, 44,173, 73, 8, 39, 9, 56, 87,124,103,247,245,254,141, 80,105,188,242,146,174, 81,158,128,117, 61, 49,
+215, 25,244,209,205,167, 57,192,206,127,164,117,237,249,237,164,172, 79,207,166, 48,109,219, 21, 90, 56, 35, 35, 32,143, 46,221,
+ 61,125, 15,125, 28, 57, 72, 79,160, 62,127,205,251, 62,125,244, 50,121,112, 0,252,253,190,154, 37,176, 85,142,192,124,135,244,
+231,207,166,177, 97,123,227, 24,184,178, 15, 76,159, 82, 63,163,247,234,184, 24, 57, 24,201, 57, 7, 31,135,219,161, 16,175, 35,
+231,219,250, 49,162,146,113,220,245,232, 65,198, 59,246,199,175,246,233, 22, 22, 36, 97, 50,187,220,155,223,231,255, 0, 56, 37,
+ 43, 8,199, 58,186,159, 32, 59,244,249,104,146,238, 70,113,140,249,250,227,183,159, 77, 4,113,144,190,153, 63, 44,227,184,200,
+252, 53, 81, 36,116, 32,231, 29,201,251,125, 7,150,146, 98, 58,223,225,130,219,221,123,117,193, 41,119, 24,248,249, 64, 32,224,
+227,175, 94,160,122,244,206,167, 39,236,166,220,118,247,115,129,157,165,148,252,148, 73,171, 88, 74,169,237,245, 93, 33, 73, 46,
+ 54,186, 44,133, 38, 1,113, 61, 74, 65,132,228,126, 92,227, 35,168,212, 42,118,215,108,110,189,211,185, 98,219, 86,181, 49, 83,
+231, 73, 5,229,186,227,137,139, 78,167,194, 66,128,145, 85,173, 84, 93, 79,135, 74,164,183,252,247,156,234,162, 66, 26, 67,174,
+148,160,203, 23,217, 2,214,215,112,241,106,238,110,209,215,119,102,143, 34,181, 87,151, 2,239,168, 76,172, 75,110,139,108, 53,
+ 53,136,201,133, 34, 21,179,239,238, 5,184,218, 82,218, 11,139,119,149,215, 15,196, 91, 66,126, 17, 4,227, 9,104,167,142,154,
+137,228, 6,169, 95, 86,155, 95, 74, 21, 96, 75,158,136, 11, 5, 3, 81, 26,142,194,230,246,184, 60, 26,124,214,135,136,167,204,
+ 41,105,100,124,178, 88, 36,167,158, 80, 44,129,137, 73, 35, 0,159,180,193,212, 2, 20, 18,129,238,218, 65, 23,235,214,231, 75,
+174,219, 59, 83,184, 21,235, 93,151, 30,184,224, 91,147, 13, 27,193,104,188,236,105,178, 18, 35, 38,162,134, 82, 50,234,163, 33,
+213,188, 0,207, 86, 70,181,171,102,120, 8,183,217,222,155,115,124, 46, 59,138, 53,229,105,208,108, 90,123, 86, 21, 10, 66,223,
+155, 42,179,121,215, 33,166, 69,211,124,221,210, 95,234,244,211, 45,231, 83, 25,177,128,216,198,122,164,107,107,162,239,150,195,
+ 32,148, 57,188,187,110,233,193, 75,141, 34,227,167, 60,130,146, 48,180, 45, 33,226, 20, 8, 39, 35,207, 26, 14,226,227, 7,134,
+ 29,183,182,107,183, 12,173,200,163,213,169,246,180, 23, 39,205,163, 89,141,125,115, 86, 84,102,186,172, 83,169,144,129, 84,133,
+127,178,128,126,237, 65,225,142,150,158, 82,226,162, 33,169,116, 0, 89,111,114, 69,200, 23, 59,157,133,183, 61,135, 91, 99,179,
+242,190, 62,226, 28,135, 33,205,114,204,161,165,203, 70,109,205,246,202,132, 82, 30, 74, 87,138, 56,249, 76,250,117, 70,177, 5,
+155, 76,136,234,116, 85, 84, 45,129,101, 97,144,207,224,179,103,238,181, 56,183, 81,123,208,158,152,250,158,156,245,169,125,220,
+ 20,116, 60,235,202, 42,121,197, 48,137, 42, 66,150, 73, 60,184, 78, 0, 56,244,208, 91,129,114,240,113,236,166,216,187,155,114,
+235, 20,202,117,183, 21,229,201,153, 69,162,189, 37,138,222,236,111, 13,232,227, 74, 84, 26, 29, 62,109, 77, 74,149, 44, 56,247,
+ 39,140,233, 40,139, 17,165, 41,231,112, 0,207, 27,248,128,250, 66,114,226, 82,170, 52,190, 16,184,115,190, 43, 19, 3, 14, 52,
+141,201,220,155,106,174, 41, 84,247,112, 66,100,195,183, 41,209, 86,185, 78,160, 14, 96, 30,113, 8, 56,248,186,103, 81,143,226,
+ 11,136,157,247,226,127,114,100,238, 30,253,238, 45,126,244,188,158,105,214,162,199,173, 62,168,205, 81,169,238, 40,172,211,168,
+ 86,223,192,221, 6,154, 50, 7, 43, 76,160,168, 1,206,181,158,186,127,203, 56,124,207, 46,161, 18,211, 34,253,166, 54, 14, 6,
+215,180,103,204, 24,247, 50, 42,129,179, 89,197,215, 20,239, 27,253, 36,248,135,244, 13, 71, 12, 80,113, 94, 97,196, 20,179,105,
+ 38, 7,168,168,108,188, 50,127,118,243,135, 96,181, 38, 34,111, 20, 96, 58,169,220, 60,100, 95, 24, 39,180,115,137,253,201,226,
+247,127,170,251,223,186, 82, 27,254, 16, 94, 74,118,124, 26, 44, 87, 92,118,155,105, 91, 81,121,162, 91, 54,141, 31,196, 63, 13,
+ 58, 13, 59, 9,230,192, 47, 62,243,210, 23,241,186,117,175, 92, 57,196, 97,202,237,211, 57,208,178,252, 42, 34,147, 24, 1,211,
+ 46,149, 5, 18, 60,253, 6,173,251,228,231, 53,219, 29,128, 65,247, 42, 12, 6, 79, 41,200, 5, 73, 4,129,215,191,174,178, 14,
+ 26,216,118, 93,122,230,134,202,121,164,204,167, 68,139, 29, 9,238,183,223,119,194,101, 41,207,153,113,104, 31,126,172,212,141,
+ 41,120,124,197, 24,209, 26, 34,128, 46,118, 28,192,119, 59,147,183, 82, 73, 39,169, 36,239,142, 53, 53,117, 21,115,214, 86, 85,
+ 74,211,213, 84,180,178, 72,231,118,103, 42,204, 73,176,238,123, 0, 0,232, 0, 27, 98,109, 63, 71,223,128,234,125,203,195, 15,
+ 16,156, 74,220,244,174,123,199,114, 99,200,218,237,155,145, 45,177,136,116,123, 98, 92, 90,221,217, 83,134,149,167,225, 85, 82,
+187, 18, 29, 56,186, 15,197, 30,152,164, 14,138, 57,216,168,246, 17,161,213, 31,142,228,117, 50, 90,146,235, 97, 10,230, 75,225,
+ 8, 56,228,115,185, 67,169,229, 41,229,239,204,112, 8, 58,236,151, 0,219, 99, 15, 98,184, 76,225,239,107,105,113, 83, 17,187,
+ 99,109,109,231,167,180,148,132, 41, 85,138,164, 38,234,181,105, 14,116, 28,206,174,124,199,201, 39,174,123,233,168,226, 23,134,
+171,150, 93,110,226,220, 91, 38, 61, 58,161, 65,144,255, 0,214,146,168, 44, 62,182, 43,237,206,148,240,247,152, 52,168, 9,103,
+146,167,207, 53,197, 58,202, 3,136, 63,166, 80, 94, 2, 65, 52,151, 19,209, 54, 99, 28, 89,138, 38,170,131,118,127, 82,142,117,
+ 40, 61, 55,137, 74,160,247, 13,239,215, 29,145,225,180,210,240,102, 89, 6, 69, 36,194, 24, 42,163, 73,100,212,214, 95,105,101,
+ 94,110,228,237,169,174, 22,254,128,108, 0, 3, 82,108,234, 84,116, 52,134,210,201, 41,147, 33, 50, 29, 8,240,203,143,186, 2,
+ 0, 83,220,201,207, 58, 67, 40, 7, 36, 0, 19,132,156,107, 99,104, 52, 8,210, 93, 98,116,150,210, 36,193,113, 47, 65, 13,129,
+225,199,203,101,135,198, 79,235, 74,113,133, 41, 10, 89, 5, 32, 16,148,242,167, 36,170, 87, 15, 59,203, 71, 82, 20,230,223, 76,
+148,128,134,151,205, 74,153, 75,168, 33,105,194, 64, 39, 19,144,162, 0, 37, 71, 41, 4, 99, 28,189,244,241,218,123, 83,186, 79,
+ 41,180, 35,109,238,133, 20,114,133, 45,113,162, 37, 61, 14, 28, 74,221,114,104, 72, 79, 81,147,216,245,198,162, 81,100,213, 74,
+ 64,146,146, 66, 91,182,134,244, 22,232, 13,237,215,211,210,214, 24,178, 78,125, 70,186,229,108,198, 24,237,177,102,158, 32, 0,
+ 54, 4, 18, 91, 96, 64, 3,222, 5,177,113,161,208, 12,134, 16,211, 10, 90, 34,143,242,202,115,224,151, 49,158,230, 50, 29, 74,
+147,238,236, 18,160, 10,191, 89, 64,114, 35, 1, 74, 86,178,171,163,112,237,237,158, 85,185, 95,170,208,239,234,203,242, 38,132,
+ 82,227,109,214,216,222,251,153, 34, 51,212,224,196,176,253,106,153, 99,209,229, 46,149, 79, 64,228, 45, 41,208,217,144,176, 88,
+142,149,168, 40, 7,150,209,216, 45,211,158,164, 57, 54,149, 73,183,217, 80,229, 46,213,234, 77, 72,113, 41, 0,142,127,114,166,
+182,234,138,136, 63, 8,231, 66,124,250,119,214,136,251,111,106,123,151,194, 15,179, 87,116,183, 91,103,247, 82,225,178,183, 81,
+ 55, 54,223, 91, 16,111, 43,121,168,212,249,212,202,101,201,112,177, 6,177, 22,136,227,168,117,112,106, 47,198, 43, 67,115,185,
+253,229,144, 74,152, 83, 75,194,132,166,147,135,179, 55,167,146,177,104,218, 8,163, 49,131, 44,171,101, 82,242, 36,105,101, 37,
+ 93,174,238, 0,210, 13,137,213,184,190, 34, 25,199,137,124, 27,150, 48, 25,157, 89,207,105, 98, 73,154, 90, 74, 25,209,101,153,
+ 68, 78,197, 69, 87, 38,162, 8,201, 42, 11,115, 17,137, 23, 64, 22,225,150, 51,124,116,238, 62,206,240, 93,121,221, 53,125,139,
+ 98,254,183,183,166,236,173,213, 46,123, 18,139,190, 78, 91,107,223,205,183,143,115, 74,157, 85, 27,132,254,217,209, 34,200,137,
+176,244,148, 57, 59,154,223,149,118,189, 34,254,168, 6,195,212,202, 37, 1,178,229,101, 17,220,184, 46,123,134,236,174, 85,110,
+107,134,183, 87,184,110, 58,228,233,117, 42,229,201, 93,156,253, 74,191, 90,168,206,125,114, 39, 77,169, 84,100,184, 86,235,239,
+ 72, 90,214,224, 4, 37, 74, 86, 72, 39, 36,218, 42,181, 73,149,138,165, 74,181, 92,157, 58,167, 88,172,212,165, 86, 43, 53,106,
+148,217, 85, 42,173, 98,179, 80,115,198,159, 87,171,212,230,186,183,234,149, 55,158, 37, 78,200,125,199, 29,112,245, 90,142, 6,
+128,109,101,110, 97, 36, 6,179,241,128, 71, 49, 62,185,242, 26,176,114, 30, 31,163,201, 33,178, 14,117, 76,191,106, 66, 5,197,
+194,141, 9,251, 40, 52,128, 22,229,136, 85,214,206, 85, 72,164,252,120,250, 73,120,157,244,128,204,169, 36,227, 28,238, 99,195,
+217, 60,113, 67, 69,150,137,165,120, 17, 41,193, 88,102,171,119, 98,213,213,195, 83,191,180, 77,245,112, 73, 61, 64,160,130,138,
+ 25,228,133,136, 90,148,234, 57, 93, 9,121, 9, 80, 90, 91,144,148,188,144,176,114,149,165, 14, 2, 18,224, 80, 4, 40, 96,130,
+ 50, 8, 58,204,169,155,143,113,209,211, 21,169,110,192,185,160, 68, 11, 17,232,183,173, 53,187,170,154,198, 82, 82, 61,205,249,
+174, 9,212,229, 15,255, 0,131, 48, 54, 63,248,163,211, 24, 96,228, 10, 88,201, 41, 7,162,137,244,238, 63, 57,213, 53,164, 43,
+ 36, 14,185,200,252,159,150,159, 39,166,130,161, 52, 77, 10,202,163,166,160, 13,137,238, 13,174,167,222, 44, 71, 99,138,111,135,
+120,167,136,248, 74,170,106,190, 27,206,170, 50,105, 42,192, 74,133,134, 66,176,213, 68, 13,249, 53,148,230,244,245,180,228,253,
+170,106,184,166,129,255, 0, 94, 54, 24,116,231,239,189,238,150, 89,133, 64,254, 15,237,252, 36,248,206,123,141,131, 77, 48, 29,
+151, 33,230,210,209,151, 80,170, 84,195,206,184,250, 26, 64,229, 8, 74, 50,160,149, 45,107, 8,109, 8,177,171,117,119, 10,108,
+ 7,169,170,189,110,207,170,159, 74,208,253, 57, 21,201,173, 71,113, 46,161, 40,144,133, 73, 74,196,165, 54,232, 78, 92,111,222,
+ 60, 37,149,168,148,124, 74,206, 0,166,219,230, 33,120, 36,117,206,124,251,143,219,175,170, 91, 74, 90, 19,207,241, 32, 19,200,
+147,240,156,250,254,205, 37, 29, 21, 36, 32,133,167, 64, 24,223,236,130,111,182,228,145,114, 71, 98, 73, 54,218,248,156,102,190,
+ 58,120,209,157,242, 99,172,241, 87, 62,130,146,154,148, 80,197, 71, 69,153,213,101,153,108, 20, 34, 40,225, 52, 84,185, 86, 89,
+ 37, 30, 91, 75, 70,241, 68,139, 37, 45, 45, 36, 84,242,232, 13, 44,108,196,177,172,227,188,193, 37, 92,169, 75,105, 8,109,150,
+208, 16,219,109,131,209, 13,161, 0, 37,180,228,147,128, 7, 82, 79,114,117, 72,146,163,205,129,140, 14, 81,216,140,129,158,184,
+237,223, 94, 84,177,158,216, 4,224, 31, 32, 73,237,246,107,233, 9, 80, 79, 50,129,198, 79,194, 64, 35,215, 61,126,205,109, 95,
+111, 47,109,189,216,170, 85, 2,233, 91,105, 10, 6,221, 0, 3,160, 30,158,131,165,177,229,212,133,160,131,128,125,112, 51,211,
+236,243,208,105, 11,230, 60,201, 8,109,191,139,226,248, 78, 71,159,207,251,116,122, 20, 20, 50, 7,145,200, 61,199,151, 95,191,
+ 67,169, 36, 55,151, 49,215,161,201, 4,252,137, 0,246,233,161,179,111,219, 6,177, 6,221,251,126,255, 0,227,138,110,123,186,
+192, 82,130,150, 8,200,194, 73, 3,182, 73, 31, 61, 75,227,232,215,112,195, 99,223,219, 35,198, 38,227,110,133,131,105,238, 13,
+175,184,202,183,248,125, 93,173,121, 80, 32, 92, 54,253,118,207, 69, 45,203,170,246,167, 78,131, 84, 97,109,174, 60,137,213,122,
+ 35, 78,132,242,171, 48, 16,160,164,173,180, 40, 68, 24,149,143, 8, 54,158,138, 74,147,205,144,144,181, 99, 24, 3, 29, 15,109,
+ 77,123,217,103,184,103,103,189,143,246,187,116, 6,164, 81,171,123,149,186,219,227, 85,173,205, 79, 52,105,170,164, 82,174,168,
+214,139, 78,199,144,180,167,195,143, 48, 82, 93, 67, 79,160,169, 10,102, 26,210,135, 57,138,185, 98,156, 99,155,193,146,101, 73,
+ 89, 80, 12,138, 37, 10,177,139, 6,150, 66,173,201,141, 9,232, 76,161, 9, 36, 16,136, 25,200, 33, 72,197,129,225,126, 86,115,
+110, 47,162,164, 72,185,210,136,228,101, 7,117,187, 20,132,234,244, 26,101,111,190,214,223, 28,193,223, 63, 97, 79, 4,115,184,
+194,185,209,179, 27,239,185, 54,175, 14,116,135,150, 47, 93,165,163, 83,105,149,186,237,191,122,205, 66,164,162,196,218,237,215,
+185, 31,144,220,155, 36, 48,243, 62, 60,137,208, 39,207,167, 56,164, 69,140,229, 65, 78,120,204,111, 6,212,251, 26,125,155,123,
+125, 58,216,185,109,203, 55,136,138,110,227, 80, 37,198,122,216,220, 26, 55, 21,119,221,175,121,219,245,200,177,194,145,114, 81,
+170, 86,149, 42, 2,105, 21,166,212, 60, 80,227, 40, 75, 45,172,132,134,150,223,194,108, 27, 71,113,203,157, 91,184, 42,197, 34,
+ 81,147,122, 93, 21, 71, 34,115, 36, 46, 82,152,170, 10,100, 82,181,243,128,150,154, 17, 84,177,200, 6, 11,105, 81, 80, 1, 58,
+222,155, 74,229,118,163, 38,164,121, 90,136,212, 8,204, 83, 34,180,202,131,110,158, 98, 36, 84,159, 83, 97, 28,172, 45, 43, 91,
+109, 37, 72,230, 95, 43, 74, 4,164,144, 53, 71,103,220, 99,198,175, 58,200,217,245, 68, 48,132, 0,197, 3,242, 22,221, 8, 44,
+154,100,147,169, 93, 83,188,174, 86,218,156,144,111,212,220, 79,225, 79, 9,228, 78,100,161,201,225, 89, 2,172,143, 33, 82, 89,
+164,178,130,234, 9,180,107,204, 58,149, 35, 85, 80,157, 55, 14,113,212,219, 99,136,234,228,106,101, 18,155, 87, 66, 43,171,106,
+ 35, 20,230,230,213, 86,165, 86,106, 81,233,145,219,143,245,157, 94,162,202, 82, 39,213,158, 8, 74,228, 72,240,144, 31,125,213,
+185,225,160,171,151, 78,181,189,187, 22,141,226,232,140,220,143,169,234, 75,115,193,110, 28,247, 27, 75, 82, 94,236, 27,137, 40,
+ 30, 71, 22, 72,232,147,202,162,122, 0, 78,185, 81, 30,244,240, 36, 85, 11, 97, 75,143, 66,134,205, 38, 36,144,114,151,170,110,
+182,100, 75, 96, 4,171,162,144,234,163,165, 65, 32,245, 74,178, 8, 26, 10, 61,219, 41,136, 17,203,239, 31,124,142,204,154,156,
+175, 13,210,158, 95,136, 52,201,108,142,169, 62, 50,148,126, 69,191,150,148,202,184,199, 54,167,208, 37,169, 53,106, 7,153,101,
+243, 27, 0,162,250,143,152, 27,234, 59,146, 0,182,199, 21,248,142,186,130, 68, 16, 73,204, 22, 91,197, 37,200, 58,148,200, 0,
+ 63,105,108,186, 23, 99,179, 29,212,244, 27,233,106,113,119,182,151,183, 20,183,231, 10, 22, 90, 95,184,110,205,174,179, 85,117,
+110, 45,213, 17,214, 92,183,173,234,168,126, 51, 38,204, 66,193,230,145, 91,105, 50,153,247,130, 7, 35, 78, 18,214, 74,210,172,
+108,130,235,136, 99,157,106, 88,230, 57, 24,206,126, 30,184, 29,122, 99, 35,174,184,239,193,253,153,180, 27, 99,196,214,228,110,
+244, 17, 42,218,187,248,132,179, 97,219,181,104, 40,144,201,180,230,222, 73,172,174,167, 38,226,195,235, 46,192,175,213,208,195,
+104,125, 33, 94,236,228,180, 23,194, 91,114, 74,129,232,125,205,113, 42, 50,221, 64,113, 73, 41, 74,147,200, 62, 21,165,105, 39,
+ 60,201, 61,142, 2,178, 62, 90,181,184,106,180,102,212,111, 59, 48, 18, 60,132, 50, 0, 46,130,202, 66,144, 55,247,134, 61, 71,
+223,105,215, 25, 75,194, 85,210,100,173,193,144,212,211,209, 46, 91, 68,149,130,172,222, 99,154, 8,239, 94,118,188, 98, 35, 41,
+ 2, 1, 17,229,242, 66,157,152,184, 14,149, 74,248,109,178, 71,136, 2,123,168,115, 2, 14, 14, 57,186,118, 32,228, 31, 62,191,
+ 45, 97, 51, 47, 98, 23,151, 29, 87,134,165, 30, 85, 12,144, 73, 56, 9, 36, 28,115,140,128, 50, 48,190,217,242,214,190, 84,238,
+181,120,174, 53,206, 10,138, 20,251,121, 81,248,208, 14, 28,111, 62,153, 35,167,145, 94,177,148, 93,188,217,104,175,152, 41, 36,
+165, 46, 12,115, 32, 15,137, 25, 36, 18,180, 96,127,181,202,144,175, 93, 74, 99,129, 80,108,110,126, 63, 15,221,249,252,113, 22,
+167,164, 88,198,195, 87, 75,254, 23,239,215,227,252,142, 54,149,187,161, 46,158,100,184, 10, 85,203,158,101, 4,148,156,144,121,
+194,199,192,114, 21,229,141, 90, 42,114,158, 91,107,145, 76, 8,113,208, 10,213, 17, 74, 45,161,212,100,229, 76, 41, 32,144,224,
+234,174, 78,161, 92,159, 14, 20,113,166, 18, 37,213,201,202, 92,120, 40, 0, 57, 92, 36, 41, 65, 39, 56, 67,160,145,146, 15, 76,
+158,152, 57, 32, 19,157,102,144,110, 4,175,225, 82,207, 50, 70, 72, 4,148,117, 57,200,207, 83,144, 6, 64,237,203,243,234,149,
+ 69, 58, 78,154, 36, 23,244, 61,193,236,111,235,211,249,140,110, 67, 81, 45, 20,162,104, 13,237,177, 83,114,174, 63,101,198,215,
+ 30,253,136,189,193, 83,190, 47,109,215,101,185,200,130,228,102,194, 92, 90, 75,164, 58,231, 42,146, 73,229, 80,113, 35, 60,189,
+138,136,248, 74,128, 86, 58,234,234,212,199,221, 1, 78,200, 88, 33, 68, 16,142,102, 27, 82, 21,132,242, 40, 55,146, 82,112, 59,
+ 17,133, 39, 33, 64,231, 88, 13,198,183, 11, 6,169, 79, 9, 91,204, 2,185,108,130,176,149,181,132,149,201, 71,135,250,206,161,
+180,146,226,123,173, 0,158,139, 29,113,232,181,233,174, 28,169, 77,128,142, 71, 27, 45,169,120, 83, 43, 79, 55, 50,121,143,249,
+ 64, 84,147,211,161, 24,193,202,134, 98,211, 43, 81,204, 98,153,246,107,216,216, 88,131,109,238, 59,250,223,241, 6,248,157, 80,
+188,121,165, 42,212, 83, 34, 68,192,217,212,145,169, 24,117,235,185,235,117, 35,175,186,197, 67,227, 22, 64, 10, 60,141,168,243,
+128, 10,146, 74,212, 91, 65, 32, 37, 74, 41, 42, 91, 32,227,252,152,234, 9,207, 49, 35, 87,149, 84, 92,140,217, 90, 25, 74, 60,
+117, 4, 33, 47,165,213,199,195,201, 42,109,160,129,149,198,144,226,142, 19,206, 49,147,240,163,148,243,105,158,139, 82, 82,138,
+ 1,113, 92,142, 19,203, 33,183,156,229, 70, 87,204,203,109,242,184,163, 29,174,101,225, 33, 28,203, 82,148,148,148,231, 35, 87,
+196, 84,214,134,138,188, 73, 40,112,151,217, 83,209,203,109,180,180,164,252, 94, 34, 22,162,183,100,103, 28,223,168, 83,130,148,
+143,136,157, 47, 28,195,190,192, 88, 95,247,119,235,183,190,247,177,191, 77,244, 42,224,209,114, 95, 93,183,232,119,183,196,245,
+ 29, 59, 16, 63, 12,178,167, 82,117,101,214,158,116,143, 5, 24, 90, 23,206,135,176,149, 30,171, 28,152, 67,133,148, 37, 68,130,
+ 72, 82,136,233,216,106,111, 20,187,199, 75,216, 78, 31,183,187,123,107, 14, 3, 11,107, 54,178,243,187,194, 90, 57,118, 69, 74,
+ 29, 37,232,118,227, 17, 80,181, 15, 26, 67,151, 45, 70,140,218, 83,159,252, 98,186,121,105,253,153, 86, 47, 7, 9,115, 32, 43,
+ 45, 41,124,222, 48,200, 88, 62, 39, 83,200,159,140,117, 57, 42,192,233,231,168,229,253, 33,126, 36,209,101,112,247,183,156, 51,
+ 81,166, 20,220,123,253,118,139,190,234,105, 14,114,189, 19,107, 54,170,107, 47, 14,101, 54,172, 24,245, 77,192,149, 76,140,166,
+ 92,229,230,106,223,125, 65, 36, 5, 99,118,157, 26,170,122,122, 52, 39, 85, 75, 0,125, 66,117,118, 29, 62,202, 6, 59,122,116,
+190,198, 41,159, 87,166, 83,147,230, 89,163, 16,134,138, 38,100,189,183,152,128,144,169, 29,124,210,178, 41,223, 96, 73,219, 16,
+244, 92,153, 82,150,236,202,131,161,234,140,247,159,157, 80,125, 32, 97,234,132,215,151, 38,107,224, 96,116, 92,167, 94, 87,207,
+155, 66,172,131,211,207, 61,115,246,127,110,136,115,169, 29,135,115,161, 87,230,174,152,245,239,216,121,254,124,181,105,160, 0,
+ 11,108, 63, 45,182,199, 34, 42,236, 13,205,207,174,253, 14, 6, 86, 50,113,249, 63, 47,150,135, 81, 10,242,192,235,159,159,204,
+250,104,133,250,130, 20, 72,252,244, 26, 21, 71,161, 62,125, 79,223,165, 20, 18, 70, 21,192,234, 32,117,249,224,103,231,246,124,
+180, 51,131, 57,234, 1, 4,245,209, 90, 17,194, 14,122,247, 57,199,203,231,165,199, 81,129,129, 85,211,167, 82, 79,115,242,244,
+199,166,116, 42,200,207,108,117,199,219,215,207, 68,185,242,238, 7,159,111, 95,223,160,150, 79,126,152, 61,193,243, 61,127, 63,
+118,148, 65, 97,210,247,249,255, 0, 92, 12, 82, 36, 2,122,129,247,254,255, 0, 61, 45, 81, 95,235,119,242,252, 62, 95,159, 93,
+ 45, 31, 3,108, 86, 29,251,103,229,162, 52, 42, 87,219, 61, 15,145,199, 76,131,229,170,129, 68,158, 94,108,116,207,111,159, 94,
+190,189,244, 71, 2,221,108, 70, 14,195,173,190, 63,195, 7, 54,123, 21,125,223, 63, 67,162, 7, 95, 35,246,121,232, 38,240, 58,
+100,147,243,252,247,254,173, 22,149,245,244, 62, 94,126, 95,102,146,193, 58,116, 56, 41,161,203,212,156, 99,200,252,243,216,104,
+214,200,243, 0,253,248, 39, 64,165, 89, 29,191, 17,231,231,131,157, 86,108, 20, 44,168,172, 16,172, 1,159, 47,179,238,210,109,
+233,109,135,242,198,113,112, 10,193, 1, 67, 4,249,129,223,237, 35,243,215, 68,167, 3,168,200, 39,161, 29,191,102,122,118,208,
+169, 81, 32, 12, 12,140,119,237,140, 1,140,143, 60,232,128,172,100,156,100, 96,228, 96,147,246, 99,229,253, 58, 79, 24,193,141,
+168,119, 61,113,211,239,233,131,248,104,132, 28,224,245, 56,235,243,233,235,143, 45, 0,133,103, 3,168, 4,250, 14,255, 0,105,
+213,126,108, 17,133, 41, 57,207,234,250,255, 0,195, 72, 55, 94,183,198, 45,251,240, 96,194,212, 65,206, 15, 99,156, 99,167, 83,
+223,166,178,107, 86,133, 46,228,174, 83,168, 84,230,131,242,231,203,102, 43, 41, 89,195, 69,215, 20,122,190,224,255, 0, 37, 29,
+ 13,165,110, 56,175,230,182,210,136,235,140,226,141,149,172,148, 40,242,164,140,243, 0,115,229,231,167, 83,107,106,201,163,215,
+ 27,102, 59,168,106,161, 80, 68,168, 17,165,168, 14,120,254,244,202,121,148,223, 55,119,212,203,110,165, 63, 53,159, 44,231, 74,
+177,164,138,154,105, 34, 0,200,138, 72,248,250,159,147,183, 77,240,231,146,208,195,153,231, 25, 94, 91, 81, 57,166,167,174,158,
+ 24,157,199, 85, 87,117, 86, 43,125,181, 16,108,183,219, 81, 23,218,248,222,138,101,205,111,109, 53,188,139, 14,206, 6, 92,185,
+106, 97,219,158,165, 20, 33,169,181,218,147,105,229, 75,211,229, 39,172,106,107, 74, 42, 76, 88,249,229,105,177,148,165, 78,169,
+197,168,202, 52, 58,189,201, 45,107,152,251,134, 43,136,241, 26,136,133, 56,212, 96, 73,206, 22, 82,160,183,187,255, 0, 56,129,
+159,230,233,172,181,109,231,101, 77,113,174, 96, 84,151, 11,234, 90,143, 58,214,238,114,165,184,181, 28,173,106, 39,185,234,115,
+211,167, 77,109, 61,163, 22, 44, 22, 27, 91,137, 83,171, 74,128, 82, 1,207,234,158,188,201, 56, 29,255, 0, 15,232,173, 43,102,
+142,152, 57, 86,230,207, 39,153,152,245, 98,109,185,219,238, 30,131, 97,176,176,238, 92,135,135, 96,160,165,130,158,154,139,217,
+233,169,194,164, 80, 40,217, 20, 91,173,247,102, 39,119, 98,117, 51, 18,204, 75, 18,113,157, 88, 27, 77, 6,162,243, 10, 91, 45,
+173,210, 17,204,134,249,192, 79, 80, 63,214,237,246,249, 13,116,123, 98,182, 58, 4, 74,205, 30,167, 79,136,195, 21, 8,242, 27,
+109,110,132, 5, 41, 73, 87,235,167, 43, 4, 56,130,140,228, 96,131,208, 99, 90,225,182, 40, 67,142, 48, 16,148,176,211,139,108,
+165, 13,164, 41,196,146, 1, 0, 28, 0,122,103,200,227, 93, 65,218,186,205,175,107,194, 23, 45,203, 58, 29, 22,218,182, 96, 72,
+174,220,149,170,131,237,177, 22,155, 74,165,199, 84,185,211,101,200,116,132,182,210, 35, 52,242,142, 78,112,156, 0, 78, 6,171,
+ 12,238,173,234,222, 88,228,156,164,106, 9, 35,215,160, 2,195,177, 61,189, 58, 92,224,103,185,230,105,150, 32,167,167,102, 26,
+193, 82, 7,165,183, 6,219, 90,219, 1,190, 56,205,197,103,181,207,127,173, 13,203,184,118,215,133,170,141, 31,104,108,203, 18,
+227,169,219,114,110, 38,173, 59,114,175,120,222, 85,138, 12,199, 41,181,154,156,153, 53,154,123,241,232,148,133, 84,163, 74,110,
+ 60, 86, 88, 82,220,105,176,227,238,146,190, 68,232,182,233,123, 64,184,141,223,154, 60,154, 6,249, 57,181,123,167, 78,146, 84,
+227, 18,107,187, 67, 98, 81,110, 42,116,165, 0,145, 34,159,117,218,148,120,114, 99,114,227,163,101, 42, 70, 84,115,229,173, 86,
+221,155,170, 61,231,185, 27,133,121, 69, 66, 4, 43,174,251,188, 46,104, 37,150,148,210, 87, 78,184, 46,106,173, 86,152,226, 26,
+ 95, 86,138,160, 76,140, 84,147,241, 37, 74, 32,128, 65, 26,194,202,138, 27, 72, 66, 66,146,164,249,147,216,250,231,207, 87, 69,
+ 31, 7,240,224,142,134,170,163, 33,165,108,202, 5, 70, 19,180, 17,154,132,144, 1,186,205,167,154,132, 27,219, 75, 46,158,139,
+101,216,113, 46,113,196, 25,150,101,152,213,213, 75, 88,211,164,146,185, 69, 33, 74, 4,212,116, 0, 45,109,150,194,253, 77,174,
+196,146, 78, 25, 29,226, 14, 57,121,205,113,232,130, 3,142,211,225,184, 35,161,210,251, 60,158, 24,194,153,113, 74, 39,194,232,
+ 48, 51,240,246,211,245,236,251,162,194,185,248,143,179, 45,121, 83, 19, 21,250,213,203,107,181, 9,165, 71,118, 87,191,186,213,
+102, 27,130, 3, 81,152, 66,148,243,239, 41, 41,105, 3, 24, 5,238,101,124, 41, 58,101,247,161,159, 22,181, 69,168, 39, 42,110,
+109, 13,166,193,234, 48,228,124, 36,164,245,239,145,174,129,251, 9,174,186, 5,165,237, 66,225,233,203,134,153, 75,169,179, 93,
+122,232,183,105,102,171, 29,185, 77,211,107,245, 27,114,161,245, 77, 90, 19,110,130,148, 84,153,121,149, 6, 86, 70, 82, 94, 37,
+ 63, 16, 4, 76,106,145,166,225,202,216,163,115, 19,154,118, 0,141,244, 17,182,175, 48,111,179,107,216,131,211,124, 55,240,245,
+ 50,102,121,237, 29, 36,238, 33, 74,218,128,140, 64, 27,115, 13,172,189, 64, 38,246, 91,130, 3, 17,112, 70,216,253, 60,108,203,
+170, 61, 38,218,163, 69,169,210,215, 6,123, 52,168, 12, 42, 18, 30, 74,149, 13, 45,197,109, 30, 2,136,232, 84,156, 96,142,195,
+ 24,211,173, 99,205,135, 95, 67,163,195, 82,216,105,226,174, 71,124,148,149, 2, 51,235,129,141,105, 44, 90,227,175,203,110, 58,
+159, 60,234,145,200,227,139, 86,113,133,225, 74, 81,201,236,156,159,187,231,170, 28, 4,113, 50,246,254,220,188, 78,211, 27,167,
+174,157, 67,217,253,200, 98,198,160, 62,226, 84,149,213,154,110, 59,134, 85, 65, 74, 80,193, 38, 67, 46,128,145,156, 36,167, 56,
+206,171,117,160,130,138,122, 97,237, 82,206,210, 2,164, 74,193,245,233, 0,234, 42, 2,170,144,127,100, 1,189,173,233,213,116,
+ 57, 94,103,152,229, 89,246,102,140,213, 17,228,201, 12,179, 73, 36,128, 58, 9,234, 18,153, 52, 40,182,162,210, 72,183, 8, 0,
+ 85, 5,141,128, 24,234, 84, 22, 97,190,160,211,140,160, 37, 73, 9, 37, 39,151, 35,203, 4,118, 61, 53,114,153, 78,153, 71,107,
+235, 40, 14, 61, 50,158,222, 60, 88,104, 36,186,207,108, 43,161,248,155, 29, 63, 29, 97, 20,201,202, 47,103,152,116,235,202, 79,
+126,158, 94,167,229,242,211,203,110,200,247,142, 86,186, 45, 43, 28,139, 74,199, 69, 36,140, 40, 28,142,185,211,232,142, 26,149,
+210,124,143,250,172, 54, 32,246,233,212,123,143,108, 87, 57,193,168,203, 88, 74,126,186, 30,174,140,110, 24, 27, 95,115,186,183,
+163, 11, 88,251,182, 38, 90,149,147, 81,103, 43,113, 42, 36,101, 41, 4, 97, 63,236,131,246,106, 57,159, 74,191,116, 98, 90,254,
+207, 59, 39,109,189,229, 13,212,183,107,126, 44,232,173, 70, 10, 79,139, 34,151,103,194,170,220, 21, 37, 33, 4,228,182,151, 83,
+ 3,152,129,211,196, 79, 81,158,178, 30,102,146,109,219,145, 41, 96, 40, 65,169, 43,197,142,145,209, 8,117, 68, 7, 25, 3,237,
+ 80, 32,127,181,168, 24,253, 41,190, 42,105,187,177,198, 54,217,240,225,110, 85, 81, 54,139,195,101,145, 34,125,214,152,206, 7,
+ 99,181,184,187,128,182, 37, 59, 9,124,170,199,189,197,183, 98, 83,146,176,122,161, 83, 8, 58, 74, 58,202,145, 17,201,101, 26,
+102,168,170,131, 88,244, 90,105, 22,173,158,223,176,226, 5,136,155, 90,243, 32,234,192, 98, 1,158, 71, 76,139, 85, 95, 79,189,
+ 36,176, 18,155, 91,205, 48,228,232,235,246,147, 91,189,183, 39,148,198,196, 2,113, 23,105, 12,224,142, 92,114,128, 57,115,230,
+ 60,193, 31,158,218,166,220,116, 96,148,167, 35,185, 0, 30,135,231,131,219, 70, 58, 91,112,228,147,129,219,200,129,212,245, 26,
+163,239, 1,162,164,182, 58, 16, 2,148, 48,123,246,233,248,234, 69,123,110, 78,199,253, 49, 95,238,192, 91,182, 41,184,218,146,
+112, 2, 85,145,205,128,115,240,232,117,175,166, 2,185, 84,122,144,123,252,146, 48, 58,249,126, 26,246,165,183,205,207,226,242,
+ 41, 68, 0,146,160, 57,188,186,141, 8,236,164,182,248, 10, 66, 79, 40,192, 24,234, 78, 51,205,246,235, 5,182,178,131,140,233,
+ 61,206, 62, 37, 37,100,130, 84,143, 85, 20,247,251, 9,215,196, 52,218, 22, 28,108, 23, 20, 73, 10, 73, 32, 16, 58,117, 3, 29,
+117,111, 83,203,146,247, 41,116,161,190, 96,162,140,245, 64, 79,113,246,247,209,173,134,220,112, 58,130,174, 68,156, 21, 96,167,
+ 56, 29,142,124,186,235, 23, 38,226,214,237,108, 24, 0, 8,223,231,108, 84,202, 80,181, 45, 75, 37, 10,236,140, 14, 84, 19,208,
+ 21, 19,249,206,145,240, 91, 89, 35, 4,168, 2,181, 39, 36, 1,143, 63,207,219,175, 14,180,248, 91,135,225, 44, 44, 19,203,230,
+113,158,202, 35,190,147, 72, 75,188,184, 10, 97,180,167,149, 94,101, 68,116,193,200,235,219, 67,113,176,234, 62,253,255, 0,241,
+140, 88, 27,158,199,247, 99,223,138,128,176, 16, 74,202,192,200, 64,234, 51,216,159,151,174,144, 56,112,168,255, 0,226,210, 65,
+ 39,211,169,193, 30,191,219,161,201, 91, 97,101, 11,229, 33,124,169,112,164, 97, 67, 25, 41,193, 29, 62,221, 18,149, 30, 64, 28,
+ 41, 83,138,201, 81,233,203,131,211, 7,167, 95,158,178,160,129,238,248, 99, 4, 11,219,211,111,159,187, 23, 91,122,216,174,223,
+151, 45,171,103, 91, 30, 48,173, 94, 23, 45, 2,211,161,169,134,124,101,166,185,117,214,160,219,116, 71, 18,206, 63, 72,148,213,
+170,176,202,135,110, 84,156,234,116,188, 70, 90, 86,214,200,237,141,191,195,253,145, 22, 45, 26,196,217,203, 30,212,219, 59,118,
+140,216, 15, 52,105,182, 85, 52,210,220,144,228,146, 7,188, 57, 58,187, 14,173, 81,121,213,101,199,100, 86,221,117,213, 5,175,
+ 81, 5,246,122, 41,151,120,231,225, 49,165, 45,167, 25, 70,253,237,171,138,109, 68, 6,138,152,185, 35, 72, 66, 58,164,128, 60,
+ 86, 81,140,142,248, 24,212,167,184,174,185,213, 80,146,133, 73, 46,189, 42,116,101,176,243,171,116,136,206,165, 92,181, 24,242,
+ 29, 66,122, 56,175,137,244, 12,128,174,102,202,115,202, 19,170, 83,197, 9,101,168,206,184,107, 46, 36,242, 99,215, 57,177, 27,
+176, 33,119, 7,246, 0,242,159,241,145,183,126,148,250, 56,229,176,205,157, 87,230, 36, 3, 52, 82, 67, 18,237,186, 42,142,113,
+ 96, 78,222,114, 22,253,238,138, 65,198,134,236,221,125, 48,227, 85,230, 51, 33,182, 20, 46,139,193, 78, 71,146, 11,172,173, 49,
+107,213, 39, 22,218,176, 65,104, 45,181, 17,240, 28,231, 10, 57,192,214,224, 91, 87, 56, 52,186,124, 87, 37, 60,195, 17, 27,114,
+181, 86,168, 52,165, 33,208,211,232, 84,135, 35,180, 82,172, 45,194,149, 57,206, 62, 17,225,181,156,149, 19,174,110, 88, 21,191,
+119,114,244,165,183,202, 67, 27,155,118,199, 87, 58,178, 4, 89, 50, 96,212,208,176,140,117, 30, 4,208, 18, 6,122, 47,168, 24,
+193,216,148,220,233, 17, 19, 8, 58,234,126,185,152,195,115,214,218,208, 94, 77, 49, 13,178,244,133,248,196, 0,223,193, 29,180,
+ 33, 36,116, 68,133,242,242,101, 71, 81,250,188,185,106, 15, 67,113, 99,239,183,107,245,232, 9,183,107,219,224, 58,227, 63,165,
+142,190,158, 48, 77,158,254, 98, 55,217,118, 36, 14,246, 5,200, 7,112, 64, 22, 35,166,219,210, 47,185, 82,233, 80,131,107,114,
+ 60,217, 83, 30,159, 55, 1, 97, 10,126, 99,143, 59,200, 93, 39, 36,248, 79, 52,216, 74,146, 85,208,149, 28,227, 87, 58,150,229,
+ 67,154,202, 4, 96, 35, 72,171, 77,110, 44, 73,100, 36,180,229, 58,157,136,136, 91,136, 10,230,111,157,193, 37,215, 17,208,101,
+244,168,228,117,214,181, 64,187,158,122, 93, 82, 99, 15, 54,251, 37,214,153,128, 31,117, 72,105,199, 39,177,225, 23,146,164,156,
+ 48,194, 20,135,157, 91,128,140, 41,148,243,100, 17,156, 82,117,230,220,185,110, 46,150,234,204, 86,210,213, 38, 18,207, 68,178,
+246, 20,194,221,232, 57,159, 45, 69, 67,133, 75, 72, 8, 74,217, 4,243, 28,107, 65,114,134, 28,192, 19, 72,150,215,216,116,216,
+247, 29,143,240, 35,215, 20,246,103,146, 44,245, 78,252,176,174,237,171, 80, 54,208, 8, 14, 67, 30,182, 4,169, 0,130, 8,141,
+150,215, 27,108,165, 82,240, 65, 91,130, 60,226,182,132,167,101,192,151, 29,238, 83, 25, 20,197,120, 81,158, 74,218, 87,253,240,
+ 30, 74,156, 5, 56, 40, 82,144, 70, 78, 52,237, 90, 94,211,206, 31,238, 61,215, 87, 13,251,187,120,211,246, 99,125,216,166,219,
+ 53, 27, 46, 70,225,213,169,180,173,188,223,218, 29,126, 20,116,211,238, 11, 14,254,117,214,224,219,183,114,235, 2,165, 77,157,
+110,215,151, 5,255, 0,172, 41,143, 26,124,233,201, 95,132,215, 47,235,155,134,253, 49,169,137,139, 33, 17,217, 13,120,112, 82,
+ 15, 49,240, 35, 44,163,195,112,169, 32,252,110,120,100, 14,255, 0, 6, 84, 78,117,197,111,105,134,220,238, 93,231, 65,219, 45,
+247,167,109,213,197, 90,217,251, 58,155,114,237,149,225,186, 16,105,102,169,111,209,111, 26,133,206,237,223, 6,220,186, 37, 68,
+ 46, 57, 71, 74,105,117,120,239,199,126, 99, 76,195, 90,234,170,101,153, 10,125, 14,182,139, 3,128,178,227, 14,113,200,102, 49,
+197, 94,146, 41, 26,186, 58, 14,100, 76, 1, 54,102, 4, 50,105,239,205,107, 48,109,241, 25,226,106, 58,222, 29,225,154,236,230,
+154,152, 85, 54, 88,209,177,136, 41, 60,216,218,101,137,193, 42, 24,198,232,143,175, 85,138,168,137,139, 93, 73, 6,112,183, 37,
+ 78,163, 2, 75,208,150,135,161,212, 82,216,153, 17,169,141,173,151,176,166,195,172,115, 50,232, 25,142,243, 42,192, 88,248, 20,
+135, 67,169, 82,146, 1,214, 30,110,102,229, 6,164, 37,229,248, 15,167,153, 14, 21,167,199,131, 45,149, 41,178,218,193,232,133,
+ 37,208,234, 20,133, 14,138, 74,146,161,200,172,136, 53,240,131,237,106,226,159,133, 24, 84, 59, 53,218,219, 59,239,178, 52,133,
+176, 33,109, 62,233,213, 42,115, 87,110, 83,210, 19,207, 27,108,183, 21,133,187, 86,176, 89, 90, 16,222, 98,161, 83,232,235, 9,
+248,233, 74,207, 48,145,223, 13,254,212,238, 15,184,152,159, 78,162,209, 47,183, 54,118,249,175,188,219, 14,237, 94,249, 74,164,
+218,245, 37, 92, 79,169, 49, 99, 27, 63,112,216,112, 91,183,164,105,106, 74, 80,226, 84,253, 38,123,107, 83, 14,125, 94,162,183,
+ 66,108,186,204,183, 48,166,102,149, 71, 62,156, 30,169,168,233, 30,174,159,105, 0, 23, 14,192, 50,168, 43,245,131, 77,196, 95,
+135,248,215,135,243,244,142, 40, 42,125,147, 48, 63,251, 60,246, 73, 9, 31,170,141,253,220,164,236, 80, 35,107,102, 86, 28,176,
+ 93, 65,235,149, 54,227,231, 82,252, 98,143,120,111, 30, 50, 3,153, 10, 74,242,148,190,207, 95,141,149, 1,219,201, 64,160,158,
+157, 92, 10, 45,120, 41, 72, 30, 42,210,211,129, 60,138, 36, 39,194, 40, 56, 9,201,199, 34, 15,194, 82,125, 71, 47, 98, 51,173,
+ 78, 57, 42, 4,150,225, 74, 68,136, 85, 24,204, 38, 66, 27,148,194,153, 91,140, 60,112,210,188, 53,165, 42, 92, 71, 18,144, 65,
+ 31, 2,199, 43,141, 41, 93, 9,204,232,245,213, 45, 41,192, 82, 28, 24, 15, 5,245, 67,125, 1,240,211,143,214, 37, 36, 97, 93,
+148, 8, 56, 7, 58,212, 89, 53, 45,155,126,155,250,244,189,247,220,131,214,195,222, 7, 80, 36, 83, 0,111,109,143, 66, 55,176,
+233,219,176,244,244,232,113,182,208,103, 41,109, 2,130, 8, 28,170, 10, 7, 24, 72, 25,194,155, 35,170,130,179,216, 16,115,215,
+ 3, 58,111, 43, 10,114,143, 57, 62, 8, 83,116,247,138,158,104, 35, 42,247, 7, 50, 75,237, 35, 36,226, 62, 87,206, 17,241, 16,
+ 21,132,140, 32, 1,125,182,231,180,168, 76, 58, 9, 40, 84,116,130,133, 30, 98,133, 5, 4,164,144,145,213, 29,122,131,213, 61,
+ 0, 36, 29, 13,118, 6,157,142,165,164,161, 74, 66,131,137, 36, 16, 75,137, 11,198, 66, 58, 1,225,133,117, 7,177,199, 76,105,
+179, 52,167, 21, 20,206, 20, 94, 88,188,203,247, 14,159,247, 13,175,219, 99,141,204,138,188,229,245,233,172,222,154,164,132,144,
+123,143, 71,223, 96, 84,155,244, 59,106, 94,135,127, 84,218,177, 40, 8,109, 77,171,152, 21,173,176,163,224,169, 71,153, 72,125,
+ 10, 73,232,160, 71, 80,122,228,147,140,224,235, 37,102,160, 10, 82,164,185,132, 45, 57, 74,215,202,149, 96,228, 37, 5, 93, 73,
+ 30, 65, 68,115, 96,128, 73,233,134, 98,157, 41, 13, 56, 75, 78,101, 30, 32, 41,200, 60,139,109,106, 31,174,223, 79,137, 36, 30,
+189,207, 76,140,117,214, 72,221,101, 45,182,162,165, 36, 32,100,243, 41, 75, 81, 70,115,204, 0,245,193,235,219, 60,157,117, 24,
+134, 67,166,254,131,225,214,223,195,240,185, 63, 9,141,122, 6,118, 85, 58,239,247, 92,246,191,191,212,255, 0,166, 51, 26,229,
+207, 71,161, 82,171, 21,250,253, 86, 21, 10,222,160,210,170, 53,218,245,110,162,164,183, 78,161,208,104,176,228, 85, 43,117,153,
+206, 45, 73, 9,137, 18,151, 18, 91,238,228,225, 72,142,160,158,165, 57,252,241,248,236,226,198,175,198,143, 19,187,139,190,210,
+211, 34, 37,167, 54, 67, 54,134,209, 80, 36, 40,149, 91,187, 67,106, 59, 42, 29,153, 29,224, 82, 63,247, 86,123, 78,203,172, 84,
+ 21,128,163, 54,224,117, 10,232,210,117,219,143,110, 55, 31,168,247, 9,220, 13,237, 45,117,106,153, 60, 65,155,196,245,118,153,
+ 33, 73,250,186,148,129, 22,167,110,108,123, 50,218, 88,204,249,174, 8,181, 59,157,180,158,102, 99, 49, 2,144,247, 42,222,154,
+216,140, 58,201, 42, 87, 55, 92,245, 24,242, 62, 93, 51,208, 99, 86, 23, 10,101,174,168,115, 74,133,179,204,161, 98, 4,110, 35,
+184, 38, 79,255, 0, 83,109, 63,224, 1,129, 34, 76,115,135,139, 28, 75, 29, 69, 68,124, 51, 69, 46,168,168, 95, 93, 91, 41,184,
+105,192,178, 67,126,252,133, 36,200, 55,250,214,208, 64,120,119,164,226,207, 66, 6, 58, 99, 61,253,127,110,168, 40,146, 14, 79,
+145, 3,176,234,117,236,175, 32,140,119,245,254,173, 14,178, 50, 7,166,115,251, 53, 54,197, 56, 6,195,215,223,143, 26, 25,222,
+163,190,112,127,103, 95,199,190,136, 80, 4, 28,249,117,233,242,208,171,236, 62,223,191, 74,170,144, 55, 30,252, 27, 3,172, 12,
+ 19,233,219,241, 26, 21,194,122,100, 96, 15, 50,122, 99,167,203, 68, 45, 88, 7,168,198,127, 12,119,207,207, 39,246,104, 39, 14,
+ 65,238,122,244,207, 92,117,243,209,240, 49, 73,194,122,158,135,167, 78,221,191,225,160,214, 70, 49,230,127,175, 85,214,124,179,
+246,254,237, 12,162,115,131,131,230, 15,203, 74,168,176, 3,231,255, 0, 56, 24,164,161,156,124, 57,251,241,165,175, 42, 81, 4,
+128,123,105,104,248, 61,215,161,234, 61,195, 9, 4, 17,131,140,142,223,159,183, 85, 65,193, 7,254, 56,208,233, 56, 57,252,117,
+ 84, 28,245,242,237,243,207,245,104, 16, 14,221,176,115,176,176,216,246,251,173,130,144,113,212,117, 31,209,147,251, 52, 64, 81,
+ 7, 3, 57,199, 92, 12,227,237,208,169, 35,151, 56,237,220,122,227,174,171,161, 97, 64, 96, 17,233,247, 31,233,206,144, 35,125,
+251,225, 50, 15,218,181,186,127, 44, 28,217, 61,137,207, 79,219,211, 69,160,115, 4,228,115, 96,228, 12,227,183,110,191,142,129,
+ 66,176,164,143, 53, 1,246,117,209,136, 61,199,167, 81,162,144, 13,182,219, 5,193,232, 56,201, 61,187,103,231,233,170,157, 57,
+128,201,237,219,190,122,158,195, 61,244, 58, 14, 70, 85,219,229,220,254, 78,137, 78, 6, 9,248,142, 58, 30,199,229,215, 73,176,
+ 32,251,176, 49, 85,178, 80, 71, 49, 24, 29,179,128,122,159,234,206,170,161,228,172,227, 5, 63, 51,208,106,130,129, 57, 36, 12,
+ 43,246, 12,103,250, 53,245, 33, 41, 28,169, 39,168,200, 39,169,243, 62,154,215,113,110,214,192,193, 69, 75, 80, 41, 11, 40, 72,
+242, 79,235, 44,117,198, 14,142,138, 84,193, 74,208,181,165,208, 82,164,172, 44,165,214,212,133, 5,182,227,107, 79, 84, 56,149,
+ 0, 82, 71,108,122,116,213,184, 21,116, 32, 12, 36, 16,175, 92,121, 99,240, 58, 41, 11, 82,192,198, 50,156, 1,158,159,143,207,
+ 73,144, 8, 32,238, 14, 5,200, 32,131, 98, 8, 32,251,198,227,247, 28,108, 53,141,190,213,107,108,134, 43,180,182,171,204,124,
+ 41, 19, 35, 60,136, 85, 18,145,128, 11,205,175, 13,186,160, 60,210,164,149, 28,156, 13,108,141,181,197, 54,220, 70, 82,197, 66,
+151,116,195,121, 72,202,146,221, 49,185,109,229, 32,244, 75,141, 75, 60,221,199, 95, 93,115,201, 4,164,124, 94,189,207, 82, 7,
+168,253,186, 37,176, 66,144, 22, 84,164,142,169, 32,227,161,236, 8,243,244,251,245, 28,174,225,188,174,181,153,164,137,162,103,
+235,203,114,160,244,191,151,117, 31,114,140, 91,121, 55,141,220,125,147,211,199, 74,107,169,243, 88,225, 80,170,107, 41,214, 89,
+ 52,139, 90,242,161,142, 87, 35,177,119,115,110,248,235,133,191,199,206,218,219, 45, 52,170,125,157,118,214,229, 55,146,132,186,
+136,148,166,213,201,219,244,179,102,224, 18, 71,250,170, 3, 29,180,196,241, 5,199, 86,232,111,197, 1,251, 8, 50,221,147,182,
+143, 56,211,211,237, 58, 60,167,100, 74,185,156,140,226, 94,138,213,215, 87, 83,109,251,229, 61,183,144,219,158,226,195,104,140,
+227,141,161,111,151,249, 82,145,162, 3,148,130, 92, 5,192, 20, 20,148,231,148, 55,212,227, 4, 14,186, 61,162, 86,176,146,225,
+ 80, 56,228,194,113,201,219,161,207,235,116, 56,211,117, 47, 5,112,245, 21, 84,117,201, 69,207,170,132,134, 71,149,218, 77, 12,
+ 8, 33,149, 73,229,134, 82, 46,173,163, 82,145,169, 72, 32, 28, 53,241, 15,138,188, 97,196,116,243, 82,213, 84,195, 69, 77, 80,
+ 10,200,180,176, 44, 69,212,245, 83, 35, 25, 38, 10,219,134, 85,145, 85,193, 42,192,169, 32,158,135, 75,235,241, 20,165,243,156,
+130,149,228,227,191,234,252,191,175, 69, 53,226, 20,169,146, 9, 42, 80, 87, 50,134, 0, 79, 79,192,118,208,142, 44, 52,130, 84,
+175,137, 56,248,146, 49,143, 64,122,117,233,170,145,222, 81, 66, 66, 73,248,178, 73, 87, 82, 79,108, 12,246, 29, 53, 36, 61, 54,
+ 29, 62, 70, 43, 94,183, 35,123, 91,175,205,241,136,238,148, 54,166, 91, 20,250,139, 88, 47,209,166,170, 59,233, 79,254, 76,255,
+ 0, 80,172, 99,160,230, 39,240, 58,198,120,103,221, 57,187, 25,196,150,199,238,244, 21,134, 94,176, 55, 62,210,175,186,181, 28,
+ 15,112,143, 87,142,138,146, 84,113,217, 84,215,101, 39,255, 0,165,167,117,218,108,106,205, 62,177, 68, 90, 2, 93,157, 79,120,
+165, 71,245, 68,134, 82, 86,218,243,228,123,254, 61,245,167, 85, 38, 11,109,188,210,135,233,152, 91,140,184,160,122,120,145,212,
+ 83,145,142,255, 0,171,251,117,187, 66, 18,104,170, 41, 36,251, 18,234, 83,255, 0, 68,162,196,254,253, 93,251,227, 20,149, 82,
+101,249,133, 45,100, 91, 73, 4,145,202,189, 62,212,108,174, 63, 16, 49,250,180,211,238,200,245, 37, 67,171,211,156, 15,194,174,
+ 65,129, 89,167, 45, 4, 20,189, 10,173, 21,153,145,214,133,121,160,178,242,122,249,231,190,180,239,217, 89,188,242,168, 28,101,
+113,223,195, 53, 74,165, 21,248,241,110,200, 59,151,105, 48,148, 54,212,150, 99, 85, 66, 25,171, 70, 90,211,133, 72, 8,121,198,
+149,215, 37, 35, 61,129,214,138,112,241,237, 18,181,246,247,217, 85,195,199, 23, 55,221,185, 92,188, 87,110,170,222,216,155,158,
+135, 70,113,168, 85, 74,133,213, 66,154,237,182,137,209,228,212, 2, 90,247, 81, 18, 12,119,150,178,172, 40, 40,165, 36,172, 99,
+ 92, 76,225,195,218, 43,112,108,191,180, 68,241,163, 87,137, 53,218, 13,213,121, 85, 13,251,109, 69,117, 79, 59,252, 93,220,210,
+ 61,214, 85, 57,148,140, 9,179,169,240, 12, 87, 90, 24,253, 35,176,207, 39, 85,140,213, 94,201, 95, 89, 89, 81, 50, 68, 88,229,
+ 41, 44, 77, 97,114,211,137, 33, 50, 70,130,251,177,141, 24, 11,126,210,130,124,216,234, 92,247,139,178,110, 30,135,135, 86, 26,
+240,171,156,212, 69, 53, 68, 96, 18, 70, 89, 60, 14, 18, 89, 46, 45,161,102,104,166, 0, 18,247,167,107, 0, 6,255, 0,166, 5,
+ 42,103, 57, 65, 82,185, 64, 32,133,247,194,134, 58, 28,253,191,183, 79,189,167, 40,130,133, 15,136,130, 15, 48,207, 92,244,234,
+ 62,127,191, 90,215,182,213,122, 45,249,108, 90, 55,197,175, 49, 85, 11, 94,248,160,211,110, 91,114,123,145,228,195, 92,170, 77,
+ 82, 51,114,163, 41,232, 51, 90,109,232,174,134,220, 0,165,196, 37, 67, 29,181,181, 22,173, 32,176,218, 22,172, 0, 58,144, 15,
+ 48, 35,161,232, 51,211,182,149,165,204, 0,210,250,182, 96, 8, 55,216,131,107, 17,234, 8,177, 7,208,223, 12,252,106,244,209,
+ 69, 44, 79,229,112, 89, 74,158,160,131,165,148,142,161,131, 2, 8,234, 8, 32,216,139, 99, 84,189,166, 92, 73, 94, 92, 36,240,
+ 71,190, 60, 72,109,253,170,139,190,243,218,251, 81,202,181, 6,152,247, 63,185,197,151, 53,246,105,136,172, 84, 2, 7, 50,224,
+ 67, 84,180,200,117, 35, 4,165,140, 2,158,227,242,123,220, 13,193,188,183,102,246,187, 55, 70,255, 0,174,202,185,175,125,193,
+184,106,119,117,217, 95,154,225, 92,154,165,106,179, 33, 82,165,200, 61,127, 70,202, 74,130, 26, 64,248, 91,109,180, 33, 32, 37,
+ 35, 95,176,103, 17, 91, 65, 79,226, 3, 96, 55,155,100,106, 73,104,195,221, 29,180,188, 44,162,167,194, 11, 49,228,215,104,147,
+ 33, 65,146,176,160, 71, 43, 83, 28, 97,207,145,107, 58,252,126,111,173,183,174,109,101,223,114,237,205,200,243, 14, 87,172,107,
+134,183,104, 86, 21, 21,196,191, 31,235, 27,118,163, 34,153, 41,108, 62,142,143, 50,181,199, 42, 74,135,250,248,242,211,205, 11,
+ 23,205,103,169,168,185,146,170,158, 46, 83,159, 68,102, 90,132, 67,211,202, 69, 43,202,122,183, 50, 37, 98,121,105,106, 87, 55,
+ 74,198,201,233,231,141, 79,232,234, 57,204, 82, 16, 6,132,158, 85, 50, 83,153, 27,174,169, 99, 74,129, 10, 55,149, 68, 19,180,
+118, 47, 41, 56, 67,100,168,171,151,155, 61, 79, 95, 60,122, 15, 61, 35,130,164,243, 43,195,200,232, 85,144,149, 30,190,103,160,
+235,163,138, 10, 81,148,161, 61, 1, 57,207,196, 1,237,229,215, 58,179, 73, 73,100, 1, 32,169,109,175, 10,108,133,117, 65, 61,
+ 64, 35,211,190,164, 33, 71, 78,184,138, 6, 12,221,108,127,211,249, 99,203,205, 18,188,146,148,164, 30,157,114,114, 49,212,122,
+121,235,227,237, 45,212, 2, 7, 84,167,184, 57,230,251,255, 0,214,210,105,196,231,225,201, 72, 78,112, 71,161,193,239,249,235,
+162,163, 54,227,231, 9,229,102, 56, 25, 86,126, 37, 18, 58,142,158,154, 26, 64,223,165,177,147,211,115,112, 58,252,252,223, 22,
+213, 70,117,150,146,176,201, 81, 88,230, 39, 35,152, 1,253, 61,115,159,248,104,168,146,144,231,232,202,255, 0, 85, 56, 40,229,
+ 0, 30,157, 78,124,245,114, 83, 5, 65, 72, 11,202,122,142,131, 4, 30,196,245,208, 41,136,220, 55, 57,130, 80,160,172,229, 74,
+ 5, 71, 24, 57,192, 61,188,255, 0, 13,102,195,174, 10, 13,246,245,219,231,231,243,194, 75,106, 66,138,139,202,121, 62, 73, 39,
+ 41, 64,244,249,235,195,175,165, 29, 16,164,129,215, 3,176, 10,244,237,242, 58, 13,247, 86, 20,162,210,241,205,219, 9,199, 76,
+118, 57,252,252,244, 57,121,183, 22, 18,162,114, 8, 46, 36,167,166,122, 30,132,122,147,160, 1, 61,122,224,218,109,176, 59,124,
+252,244,193, 73, 62, 42,249,210,160,160, 6, 10, 58, 4,243,117,237,215,174,169,202,116,144,148,163, 9, 35, 41,232,112, 73, 35,
+ 26,244,226,149,225, 44, 52,218, 83,202, 50, 6,112, 73, 3,166, 20, 60,186,106,200, 38, 56, 22,159, 25, 41, 42, 74,136,229, 35,
+ 39,237,230, 7, 25, 25,253,154,205,172, 79, 99,140,129,115,240,254,120,124,184,115,189,156,218,173,243,217,253,196,140,226,154,
+114,201,221, 29,189,186,157,144, 2, 28, 76,104,148, 91,202,137, 62,170,234,144,226,146, 10, 19, 71,106,164, 78, 72,192,235,229,
+214, 89,252, 84, 79,135, 38,165, 91,167, 64,144,125,222, 21, 90, 83,212,194, 9,203,148,103,102,202,149, 75,147, 29,226,231,198,
+199,134,165,180, 86,174, 83,250, 48, 82,145,204,117, 12,134, 36, 32, 58, 89,144,219,141, 68,148, 28, 97,215, 25,112,135,124, 41,
+ 13,150, 30, 13,148,156,182,191, 13,197,224,142,160,224,143, 93, 73,106,193,222, 9,123,221,195,158,213,110, 37, 84, 5,220,177,
+173,145, 99,221,170, 9, 90, 82,245,211, 97, 33,139, 66,186,235,106,113, 41, 18, 89,144,221, 38,151, 80,109,206,169,241,170, 79,
+ 3,133,165, 68,213,126, 32,229,133,243, 12,131, 53, 81,228,136,205, 3,157,175,169,213, 36,139,223,107, 71, 40,244, 5,135, 82,
+109,142,146,250, 55,230, 49,199,158,230,217, 92,205,165,166,142, 42,152,199,111,171, 99, 12,173,241,188,212,235,255, 0,117,239,
+229,177,215, 10, 45,116,211,119, 43,112,233,170, 37,182,230, 76,183, 43,177, 16, 48, 67,141,212,104,203,167, 84, 84,210, 85,250,
+200,247,186, 39, 42,135, 76,169,127, 17,201, 25,126, 41,181,229, 37, 94,246,130,227,139, 83, 98,158,134,210,180,160,134,139,132,
+169, 8,228,234, 57,157, 60,196,119, 33,160, 58, 3,173, 54,220,106,162,232,187,147, 64,173, 32,128,221,114,157, 86,182,101,168,
+ 2,112,236, 98,110, 58, 71, 42, 0,200, 82,156,139, 85,108,168, 12, 37, 47, 14, 99,215, 89,237, 42,241,122, 42, 89,121,149,120,
+143, 68,240,228, 71, 67,193, 97, 42,112, 20,248,104, 82,146, 14, 81,149, 36, 43, 61,130,149,202, 79, 77, 54,154, 98,201, 79, 48,
+ 93,157, 23,215,245, 64,140,254,242,183,247, 3,113,214,216,234,185,107, 85, 90,190,153,200,103,134, 73, 8,185,181,196,141,207,
+ 0,122,217, 95, 77,199,166, 54, 18,161, 94,151, 79,143,238,201, 90,156, 74, 11,144,195, 67, 45,167,222,100,242,185, 41,107, 79,
+ 47, 68,161,128,211, 94, 17, 4,143,139,237,214, 33, 94,188,163, 65,166, 48,194, 95, 91,117, 54,202,144,132, 54,165,128,183, 95,
+199,188,184,162,159,133, 33, 12,114, 39, 3,184,113, 99, 62, 90,108,110,125,200,155, 57,192,243,237, 54,135, 98, 37, 65,105,104,
+184, 83, 38, 67,170, 74,157,117,106, 82, 65,231, 43, 42, 36,158,164, 28,103,182,152, 91,179,113, 22,203, 82, 31,144,227,141,177,
+ 29,133, 60,243,188,138,117,126, 27,202,229, 79,134,132,140,173,213,186,224, 64,230, 35, 28,249, 82,146,156,168,109, 83, 80,180,
+133, 70,155,131,247,250, 91,173,253,215,233,123,143,190, 31,153,230, 40,116,234, 94, 76,155, 11, 13,199,112,250,136, 0, 48,181,
+193, 30,164,142,215, 14, 21,209,121,205, 91,172,198,128, 37,214, 37,203,151, 18,147, 71,162, 69, 74,158,159, 91,173, 84, 31, 76,
+ 74, 61, 38, 10, 82, 57,149, 46, 76,199,210,132, 36,116, 79,141,204,122, 13, 72,111,103,182,153,253,140,217, 59, 59,105,234,166,
+ 43,245,214, 40,146,102,238, 75,165,136,243,169,213, 75,230,241,120, 86, 47, 54, 36,211,230,178,227, 21, 26, 75, 53, 55, 26,167,
+ 24,207,180,236,119, 35,210, 16, 22,218,146,117, 21, 91, 99,137, 58,134,192,111, 54,211,110, 76,122, 84, 42,181,197,100,221,246,
+174,224,205,167, 84,216, 19,169,212,123, 66, 37, 89, 42,151, 77, 97,181, 39,195,159,114, 79,128,212,245,169,240, 22,212,111,116,
+105, 13,225, 69, 58,152,173,218,236, 42,179,108, 87,233, 14,186,253, 46,181, 6,157,112, 82, 30,120, 56,211,238,209,110, 10,124,
+106,204, 5, 62,219,128, 41, 18, 61,194,107, 60,193, 64, 44, 45, 4, 30,186,117,106,119,163, 48,188,177,253, 92,232,116, 31,218,
+177, 26,182, 29, 0, 5,108,118, 44, 24,145,181,142, 35,114,231,116, 85,239,152,101,148,181,162, 92,195, 43,146, 35, 87, 18,135,
+188, 13, 42, 22,128, 23, 42, 35, 98, 66,200, 24, 35, 57,137,208,164,161, 30,202,120, 41,197,183,177,147, 96, 55,194,117, 82,245,
+225,250,163, 11,134,125,197,158,169, 14,206,182,216,166, 75,169,236, 93,114,190,156,248,141,189,108,196, 90,166,237,169,121,196,
+181,250,106, 40,147, 79, 30, 49,116, 81,219, 78,117, 26, 30, 33,248, 90,223,142, 22,238, 53, 90,251,235,183, 21, 75, 77,169,146,
+228, 66,162, 92,232, 13, 87,118,250,239,240, 22,241, 75,150,189,233, 78, 11,167,214, 10,153, 99,198, 17,203,141,204,109,181,161,
+ 79, 69,104,144, 53, 62, 58,210, 27,142,235,239, 21,135, 25, 12,160, 78,108, 32,130, 2, 20,150,218,156,215,108, 60,148,173, 41,
+ 88, 7, 42, 65, 24, 28,201, 25,193,174,203,122,131,116,219,213,139,110,241,182,232, 55,173,161,112, 70, 84, 43,170,207,186,169,
+ 84,234,253,183,113,211,152,109, 97, 46, 84,104,245, 86, 28,142,237, 70, 59, 5,226,196,128,132,200, 66, 22,182,154,125,146, 80,
+180,201,178,222, 38,170,167,211, 29, 71,246,200, 86,223,104,218, 69, 29, 1, 87,177,189,186,233, 96,214, 30, 85, 40, 0, 56,170,
+184,143,195,156,143, 60, 18, 84, 69, 23,232,156,193,247, 18,194,160, 70,237,183,247,176,221, 84,146, 79,219, 83, 27,110, 29,203,
+146,109, 13, 30, 23, 61,163, 28,100,240,219, 38,149,107,237,182,228, 73,189,236,148, 58,150,218,218, 61,216, 67,151,221,136,166,
+144,210, 25,240, 41, 6,169, 45, 53, 11, 53, 66, 58, 57, 80,186, 76,248, 97,190, 98,160,218,142,164,109,178,158,214,237,167,175,
+ 65,161,127, 41,109,181,191,248, 74,174, 85,212,196, 72,247,141,118,159, 86,189,184,118,184, 38, 56,243,200, 67, 20,205,205,163,
+ 65, 92,187,103,244,108,243,134, 42,113, 37,120, 42,121, 41,114,160, 80, 84,117,167,220, 73,251, 19,182,242,247,150,245,217,194,
+ 29,220,173,162,186,165, 45,185,180,237,176,187,166,214,235, 27,115, 85,154,242,203,141, 53,105,221,169,247,138,213,131, 33,111,
+ 58, 60, 24,243, 19, 85,132,218, 80, 19,227,198, 71,195,173, 7,218,190, 57,120,161,246,121,238,117,107,135, 46, 42, 54,246,212,
+222,125,182, 66,215, 76,220,221,149,190,133,155,115,191, 81,182,165,170, 84, 41, 82,173,155,198,146,212,216, 50,159,240,155,121,
+200,241,235, 44, 76, 97,206, 80,135,152,140,178,151, 90,121,170,146, 44,222, 17, 46, 79, 77, 21,101, 90,144,210, 68,210, 26, 90,
+141, 23, 26,157, 24, 36,177, 72,226,224,221,193, 66, 60,166,100, 39,106,230,105,184,247,129,158, 20,172,144,102, 25, 56, 96,130,
+ 73, 11, 77, 13,172, 72, 85,114, 4,208,176, 63,238,220,198, 0, 12,193, 90,219,205,107,111, 55, 22,222,185,109,106, 77,203,105,
+ 92,212, 27,170,209,172,183,227,209, 46,123, 90,179, 79,185, 45,186,219, 47,160, 44, 55, 78,175, 80,230, 63, 25,215,130, 20, 20,
+227, 72,116,188,206, 64,121,180, 19,141,103,175, 87,204,134,148,133, 47,152,148,124, 42, 90,135, 81,202, 0, 79, 42,142, 57,128,
+233,159,246, 64, 39, 57, 58,138, 47, 16, 27, 71,120,112, 95, 98,211, 61,164, 94,203, 13,207,174,217,124, 50,238, 29,187,102,110,
+ 70,229,240,243,119,189, 42, 85,155, 77,162,222,245, 72, 16, 41,117, 22,108,155,169,231, 90,184,109, 7,235, 46,162,151, 58,152,
+243,203,175,208,101,130,245, 6,171, 58,144, 89,145, 18, 68,155, 3,127,214,247,155, 98,118,115,120,231, 91,109, 90,114,247, 99,
+108,236,173,194,145,108,177, 83, 77, 90, 45,188,253,219, 67,139, 87,122,147, 14,164,243,190, 44,248, 45,185, 37, 98, 59,143,101,
+242,194,155, 18, 15,188, 7, 73,143,214,196, 35,167,138,170, 9,185,212,211, 51, 37,153,116, 75, 28,128, 41, 49, 75, 29,205,152,
+ 95,170,150, 83,177,218,235,123, 43,134,115,213,207,218, 72,189,141,233,170,169,213, 93,148,221,209,145,142,149,120,220, 40,189,
+200,177, 4, 41, 27, 0, 8,185,198,215,109,149, 22, 37,219,112, 75,167, 73,165, 92, 21,191,118,183,110, 26,195, 20,107, 85,228,
+ 68,174, 84,165, 82,105,206,202, 98, 44, 87, 92,162,212, 48,165, 45,180,169,192,152,142,168,161, 4, 36, 36,229, 99, 64, 56,226,
+223, 77,219,218,203, 74,243,176,184,111,131,100,212,184,131,106,210,106,188,182,174,237,198,176,104,236,108,117, 26,191,107,238,
+ 45,231, 67,159,114, 83,238, 42,188, 53,220, 59,203, 46,201,218,125,206,169,219, 54,146, 99,166,100,164,216,146,234, 18,227,161,
+ 2,157, 2,167,204, 14, 62, 61,170,123,199,195,134,245,239, 23, 13,187,105,102,194,182,165, 83,246,238,171,105, 84,183, 81, 53,
+244,170,245,137, 87,220,107, 45,183,233,117,187, 54, 41,166, 73,133, 64,143, 76,250,217,135,130,156, 67,211,229, 61, 20,165, 50,
+ 32,160,164,235,150,155,127,199,229, 2,218,166,220, 17, 47,141,155,184,239,201,213, 27, 39,106,105,180,122,212,125,229,250,134,
+170,214,227,109, 78,199,111,230,200, 68,190,174,249,149,109,181,172,187,121, 82,106, 16, 56,129,184, 42,147, 41, 97,218,124,229,
+ 79,183,224, 36,215,213, 28,203,110, 70,206, 69,195,144, 85, 69, 5, 70, 98,154,105,203, 23, 84, 82, 9,145, 88, 2,188,203, 43,
+ 29, 22,223, 64,107,155,217,130, 11,134,211,227, 63, 18,206, 91, 83, 89,150,100, 83,153,115, 5, 2, 9,166,100,112, 41,101, 77,
+ 75, 50,195,172,141, 83, 43,150, 83, 39, 47, 66,149,186, 60,183, 82,141,110,225,240, 39,196,221,155, 81,191,231,222,141, 89,213,
+ 55,237, 88,247,245,205,127,221,171,222,173,181,185, 61,226,240,182,175, 86,237, 91,186,211,159, 89, 98,236,113,202,246,245, 75,
+190,106,209,152,110,218,100, 61,112, 84, 36,212, 28, 91, 16, 22,220,105,170,139,127,159,236,242,222,186, 77, 26,239,166, 87,232,
+112,233,215,213,183,115, 90,106,118,188, 55, 27,106, 92,217,154, 61,128,237, 3,137,199,119, 10,177,114,223, 77,221,139, 75, 53,
+122, 53,223,195, 53,253, 73,112, 71,241, 98,181, 54,200,172, 83,221,113,115,223,163, 51, 57,230,147,199, 5,183,187,182,199, 20,
+139,188,118,233,203, 98,159, 84,186,183,115,137, 91, 34, 52, 27,238, 84,170,188, 61,236,220, 94, 32, 44,203,171,108, 40,237, 75,
+107,110, 95,141, 88,160, 80,145, 95,186, 77, 97,137,205, 83, 25,174,211,162,188, 99, 84, 40,149, 52, 64,143, 46,157, 75,218, 83,
+101, 77,186,105, 19,162,236, 45,249,108,218, 84, 43,254,198,220, 58,109, 34,211,226, 14,155, 2,237, 19,173,203,215,141, 77,199,
+186,173,217,247,125, 99, 98,170, 16,170,182,125,110,232,227, 78,236,167,187, 2, 77, 5,212,166,211,181,219,161, 84, 87, 88,151,
+ 81,153, 91, 22, 42,173, 58,216, 2, 66,109,243,176,249,247,227,159,188,172,197,153,181, 23,220,146, 73, 36,158,189,183, 55,238,
+119,191, 83,134, 79,133, 94, 26, 54,163,119, 40, 23,245, 15,114,220,191,142,226,213, 56,139,225,227,133,189,165,172,237,181,249,
+ 97,155, 30,221,191,119,242,131,196, 96,167, 93,151,172, 39,236,250,202, 55, 62,208,102,241,218,107, 53,128,138, 37,126,130,149,
+ 83,107, 53, 9,204, 84,230, 17, 17,189, 55,212,190, 3,248,146,172,211,160,212,169,214,189,181, 33,186,142,219,211,247, 54, 44,
+ 95,227, 14,196,106,162,186,125, 98,181,178,180, 58, 45,166,105,207, 92, 9,120,110,100,217, 28, 70,108,107,177,109,190, 79,173,
+221, 99,115, 41,203, 76, 94, 97, 37, 17,242,109,137,226,246,211,217,104,251,163, 81,127,101, 62,187,186,171,187,235,180,188, 70,
+108,210,237,235,249, 22, 93,137,180,219,153,179, 84,221,245,137,101, 55, 93,179, 23, 99,212,230,110, 13,155, 14,126,244, 71,153,
+ 30,155, 22,183,110, 58,135, 44,136,172,191, 58, 84,105, 79,178,151,218, 87,181, 90,244, 52,109,183, 49,108, 26,164,171,191,110,
+ 45, 11, 30,153, 2,181,115,110, 83,149,219, 97,171,198,196,221, 46, 9,183, 14, 21,126,223,177, 98,217, 80,152,183,109,137, 17,
+184, 39,182,216,149, 73,247,169,115, 94,157,126,212, 38,174,188,170,109, 62,145, 66,136,100, 17, 21, 93, 71,204, 47,211,227,220,
+219,115,111,195,225,108, 1,107, 11,252,252,239,134,106, 63,179,199,115,133,155,125,215,171,187,135,179,118,237,197,106,110,150,
+201,109,205, 10,223,153,185,246, 52,250, 21,249, 15,122,172, 61,215,189,169, 23, 85,173,123,210,110, 87,226, 85,161,161,221,180,
+ 69, 50, 35, 16,154,153,245,133, 70,101, 86, 39,143, 18,101,191, 50, 43,173, 61,131,193, 94,250,238,142,241,110, 54,200, 89,144,
+172,105,247,150,215, 94, 63,197,253,209, 54,126,230, 88,150,253,156,245,230,245,238,157,187,165, 91,118,205,231,112, 87,162,211,
+175, 26,213, 74,234, 15,179, 73,139, 75,126, 92,138,179, 48,164, 75,167,183, 38, 43, 46, 58,157,172,107,218, 71,106,187,184,205,
+ 93,151, 6,202,110, 37,197,110,209,175, 29,134,190,172,246, 39,241, 13, 5,253,203,160, 93, 60, 62,109,135, 18,118,213,139,112,
+ 73,220, 10,142,200, 73,165, 84,170,177,119, 63,136, 8, 23, 60, 70,218,180,225,210,217,143,182,241, 40,114,169,117, 3, 80,155,
+ 86, 12, 7, 9,252, 89,216,124, 52,223,247, 21,199, 92,217,203,159,115,109, 71,183, 27,106,119, 94,200,183,218,221,216, 86, 93,
+205,110,222, 91, 37,184,134,249,219,247, 46, 91,196,109, 93, 86, 53,227, 71, 49,101, 84,161,213,227,179, 69,164, 59, 61,217, 13,
+ 76,139, 38,154,150, 85, 17,245,109, 21,212, 94,194,230,253,122,118,237,252, 63,118, 51,229,219,231,249, 97,202,188, 61,155,155,
+199,118,239,117,185,183,155, 45,111,219, 48,169,151,253,165,181,247, 29,144,197,255, 0,186, 86, 69,154,185,177,175,167, 54,191,
+110,233, 53, 41,149, 43,218,189, 9,184,108,215,247,190,249,155, 69,160, 50,234,210,253, 65,250, 53, 77,200,172, 42,159, 74,151,
+ 45,166,227,134, 30, 29,118,127,120,246,186,191, 46,244, 59,148,198,229, 93, 91,162,198,209,109, 69, 98,214,187, 45,122, 85,145,
+109,220,147, 54,155,112,111,218, 69, 66,255, 0,180,170,251,125, 80,157,121, 82,101,220,150,181, 18,154,240,167,215,104, 46, 83,
+162, 85, 36,212, 19,245,147,172, 55, 5,237,158,182,189,170,118,111,241,175,183,251,177,186, 92, 50,213, 47,138,213,133, 67,216,
+ 27,113, 74,181,183,186, 14,223, 84,174,122, 47, 11,119,174,202,223, 59, 29, 14,226,170,191,178,245,148,204,114,158,230,219,222,
+ 52, 89,210, 61,212, 74,157,109,221,244, 74,100,119,233,207,218,140,207,171,105,175, 15, 60, 86,219, 59, 19,183, 23, 37,185, 55,
+107, 42,215,157,246,197,244,141,202,218,155,189,189,196,135,110,218,246, 85,232,222,219,222,187,117, 26,163,120, 88,142,109,229,
+ 70, 70,225, 69,136,139,192, 85, 33, 71,143, 94,160, 33, 53, 10, 36,116,205, 53, 8, 43,126, 27,135, 2, 45, 74,111,229,107,222,
+224,251,173,219,227,235,252,241,159, 47, 99,243,255, 0,140,109,229,209,192, 61,139, 67,254, 54, 13, 55,134, 30, 56,238,159,226,
+247,134,189,165,221,155, 88, 82,239, 26, 58,127,141, 58,134,224, 29,184,254, 17,110,133,181,238,252, 37, 74,228,217,202, 39,240,
+190,165,239, 17, 99,253,100,191,208, 49,227,221, 17,185, 92,241,117, 46,135,178,187, 35, 81, 28, 31,213, 31,183,183,186,171, 31,
+122,172,157,204, 93,241,102,218,215,157,151, 58,233,188,119, 54,204,184,111, 91, 90,206,160,237,157, 94,102,218, 53, 31,110,232,
+ 55, 5,201, 73,181, 97, 62,229, 82, 21,212,253, 17,170,156,202,136, 53,143, 5,170,122,233,238,255, 0, 21,182, 21,251, 73,221,
+ 38,109, 61,163,187,173, 42,230,243,109,206,204,217,215,189, 66,226,221,186, 53,235, 74,102,187,180, 15, 88,202,106,225,181, 40,
+212,205,160,161, 61, 71,164,207,141,102,114, 42,155, 50,125, 77,232,203,169,120,130,166,250, 89,240,157,111,237,173,252,177, 83,
+ 70,217,139, 67,114,246,121,205,192,178,182,194,199,221,235, 38,179, 78,133,124, 51,107,215,171,138,221, 10,189,205, 93,167, 93,
+ 54,173,114, 93,149, 85,143,101, 93, 20, 42,173,118, 11,240,157,147, 78,174, 70,121,218, 70, 95,139,225,190, 91,109, 66, 82,230,
+223, 59,143,119,166, 50, 8,184, 3,231,127,135,166, 49, 78, 42,118,162,139,177,156, 68,238,246,208, 80, 63,132, 77, 83,182,246,
+242,168, 91, 74,166, 93,239, 65,153,117,219,117, 40, 41,100, 86,172,219,150,169, 75,166,194,137, 94,175, 81, 43, 42,159, 72,151,
+ 83,133, 10, 28, 42,156,138, 35,149, 8, 81, 34,197,146,211, 13,173, 88,184,129,221,147,190, 91,193,122,238,130, 40, 10,181,162,
+ 92,146,233,172,210,109,231,107, 47, 92,147, 40,244, 11,118,135, 75,181,237,216, 53, 75,142, 68, 40,170,184,107, 72,161, 81,105,
+222,253, 60, 68,134,137,147, 11,242, 90,133, 13,183, 81, 21,165,172, 21, 55, 58, 70,221,186,116,193,180,169,223,215, 31,255,217,
+};
+
diff --git a/source/blender/editors/gpencil/Makefile b/source/blender/editors/gpencil/Makefile
new file mode 100644
index 00000000000..bb76c9c2b23
--- /dev/null
+++ b/source/blender/editors/gpencil/Makefile
@@ -0,0 +1,57 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_gpencil
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+CPPFLAGS += -I$(NAN_BMFONT)/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I$(NAN_ELBEEM)/include
+
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../gpu
+CPPFLAGS += -I../../render/extern/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/gpencil/SConscript b/source/blender/editors/gpencil/SConscript
new file mode 100644
index 00000000000..6c47b2f69ff
--- /dev/null
+++ b/source/blender/editors/gpencil/SConscript
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' #/intern/guardedalloc #intern/bmfont ../../gpu'
+incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
+
+env.BlenderLib ( 'bf_editors_gpencil', sources, Split(incs), [], libtype=['core'], priority=[45] )
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
new file mode 100644
index 00000000000..fd59539bb56
--- /dev/null
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -0,0 +1,1064 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_listBase.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_blender.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_gpencil.h"
+#include "BKE_sequence.h"
+#include "BKE_utildefines.h"
+
+#include "PIL_time.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "ED_gpencil.h"
+#include "ED_sequencer.h"
+#include "ED_util.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "gpencil_intern.h"
+
+/* ************************************************** */
+/* GREASE PENCIL PANEL-UI DRAWING */
+
+/* Every space which implements Grease-Pencil functionality should have a panel
+ * for the settings. All of the space-dependent parts should be coded in the panel
+ * code for that space, but the rest is all handled by generic panel here.
+ */
+
+/* ------- Callbacks ----------- */
+/* These are just 'dummy wrappers' around gpencil api calls */
+
+#if 0
+// XXX
+/* make layer active one after being clicked on */
+void gp_ui_activelayer_cb (void *gpd, void *gpl)
+{
+ gpencil_layer_setactive(gpd, gpl);
+
+ scrarea_queue_winredraw(curarea);
+ allqueue(REDRAWACTION, 0);
+}
+
+/* rename layer and set active */
+void gp_ui_renamelayer_cb (void *gpd_arg, void *gpl_arg)
+{
+ bGPdata *gpd= (bGPdata *)gpd_arg;
+ bGPDlayer *gpl= (bGPDlayer *)gpl_arg;
+
+ BLI_uniquename(&gpd->layers, gpl, "GP_Layer", '.', offsetof(bGPDlayer, info[0]), 128);
+ gpencil_layer_setactive(gpd, gpl);
+
+ scrarea_queue_winredraw(curarea);
+ allqueue(REDRAWACTION, 0);
+}
+
+/* add a new layer */
+void gp_ui_addlayer_cb (void *gpd, void *dummy)
+{
+ gpencil_layer_addnew(gpd);
+
+ scrarea_queue_winredraw(curarea);
+ allqueue(REDRAWACTION, 0);
+}
+
+/* delete active layer */
+void gp_ui_dellayer_cb (void *gpd, void *dummy)
+{
+ gpencil_layer_delactive(gpd);
+
+ scrarea_queue_winredraw(curarea);
+ allqueue(REDRAWACTION, 0);
+}
+
+/* delete last stroke of active layer */
+void gp_ui_delstroke_cb (void *gpd, void *gpl)
+{
+ bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
+
+ if (gpf->framenum != CFRA) return;
+
+ gpencil_layer_setactive(gpd, gpl);
+ gpencil_frame_delete_laststroke(gpl, gpf);
+
+ scrarea_queue_winredraw(curarea);
+}
+
+/* delete active frame of active layer */
+void gp_ui_delframe_cb (void *gpd, void *gpl)
+{
+ bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
+
+ gpencil_layer_setactive(gpd, gpl);
+ gpencil_layer_delframe(gpl, gpf);
+
+ scrarea_queue_winredraw(curarea);
+ allqueue(REDRAWACTION, 0);
+}
+
+/* convert the active layer to geometry */
+void gp_ui_convertlayer_cb (void *gpd, void *gpl)
+{
+ gpencil_layer_setactive(gpd, gpl);
+ gpencil_convert_menu();
+
+ scrarea_queue_winredraw(curarea);
+}
+#endif
+
+/* ------- Drawing Code ------- */
+
+#if 0
+/* XXX */
+/* draw the controls for a given layer */
+static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short *xco, short *yco)
+{
+ uiBut *but;
+ short active= (gpl->flag & GP_LAYER_ACTIVE);
+ short width= 314;
+ short height;
+ int rb_col;
+
+ /* unless button has own callback, it adds this callback to button */
+ uiBlockSetFunc(block, gp_ui_activelayer_cb, gpd, gpl);
+
+ /* draw header */
+ {
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+
+ /* rounded header */
+ if (active) uiBlockSetCol(block, TH_BUT_ACTION);
+ rb_col= (active)?-20:20;
+ uiDefBut(block, ROUNDBOX, B_REDR, "", *xco-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15.0, (float)(rb_col-20), "");
+ if (active) uiBlockSetCol(block, TH_AUTO);
+
+ /* lock toggle */
+ uiDefIconButBitI(block, ICONTOG, GP_LAYER_LOCKED, B_REDR, ICON_UNLOCKED, *xco-7, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Layer cannot be modified");
+ }
+
+ /* when layer is locked or hidden, only draw header */
+ if (gpl->flag & (GP_LAYER_LOCKED|GP_LAYER_HIDE)) {
+ char name[256]; /* gpl->info is 128, but we need space for 'locked/hidden' as well */
+
+ height= 0;
+
+ /* visibility button (only if hidden but not locked!) */
+ if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED))
+ uiDefIconButBitI(block, ICONTOG, GP_LAYER_HIDE, B_REDR, ICON_RESTRICT_VIEW_OFF, *xco+12, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Visibility of layer");
+
+ /* name */
+ if (gpl->flag & GP_LAYER_HIDE)
+ sprintf(name, "%s (Hidden)", gpl->info);
+ else
+ sprintf(name, "%s (Locked)", gpl->info);
+ uiDefBut(block, LABEL, 1, name, *xco+35, *yco, 240, 20, NULL, 0.0, 0.0, 0, 0, "Short description of what this layer is for (optional)");
+
+ /* delete button (only if hidden but not locked!) */
+ if ((gpl->flag & GP_LAYER_HIDE) & !(gpl->flag & GP_LAYER_LOCKED)) {
+ but= uiDefIconBut(block, BUT, B_REDR, ICON_X, *xco+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete layer");
+ uiButSetFunc(but, gp_ui_dellayer_cb, gpd, NULL);
+ }
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ }
+ else {
+ height= 97;
+
+ /* draw rest of header */
+ {
+ /* visibility button */
+ uiDefIconButBitI(block, ICONTOG, GP_LAYER_HIDE, B_REDR, ICON_RESTRICT_VIEW_OFF, *xco+12, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Visibility of layer");
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ /* name */
+ but= uiDefButC(block, TEX, B_REDR, "Info:", *xco+36, *yco, 240, 19, gpl->info, 0, 127, 0, 0, "Short description of what this layer is for (optional)");
+ uiButSetFunc(but, gp_ui_renamelayer_cb, gpd, gpl);
+
+ /* delete 'button' */
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+
+ but= uiDefIconBut(block, BUT, B_REDR, ICON_X, *xco+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete layer");
+ uiButSetFunc(but, gp_ui_dellayer_cb, gpd, NULL);
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ }
+
+ /* draw backdrop */
+ if (active) uiBlockSetCol(block, TH_BUT_ACTION);
+ uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-height, width, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, "");
+ if (active) uiBlockSetCol(block, TH_AUTO);
+
+ /* draw settings */
+ {
+ /* color */
+ uiBlockBeginAlign(block);
+ uiDefButF(block, COL, B_REDR, "", *xco, *yco-26, 150, 19, gpl->color, 0, 0, 0, 0, "Color to use for all strokes on this Grease Pencil Layer");
+ uiDefButF(block, NUMSLI, B_REDR, "Opacity: ", *xco,*yco-45,150,19, &gpl->color[3], 0.3f, 1.0f, 0, 0, "Visibility of stroke (0.3 to 1.0)");
+ uiBlockEndAlign(block);
+
+ /* stroke thickness */
+ uiDefButS(block, NUMSLI, B_REDR, "Thickness:", *xco, *yco-75, 150, 20, &gpl->thickness, 1, 10, 0, 0, "Thickness of strokes (in pixels)");
+
+ /* debugging options */
+ if (G.f & G_DEBUG) {
+ uiDefButBitI(block, TOG, GP_LAYER_DRAWDEBUG, B_REDR, "Show Points", *xco, *yco-95, 150, 20, &gpl->flag, 0, 0, 0, 0, "Show points which form the strokes");
+ }
+
+ /* onion-skinning */
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOG, GP_LAYER_ONIONSKIN, B_REDR, "Onion-Skin", *xco+160, *yco-26, 140, 20, &gpl->flag, 0, 0, 0, 0, "Ghost frames on either side of frame");
+ uiDefButS(block, NUMSLI, B_REDR, "GStep:", *xco+160, *yco-46, 140, 20, &gpl->gstep, 0, 120, 0, 0, "Max number of frames on either side of active frame to show (0 = just 'first' available sketch on either side)");
+ uiBlockEndAlign(block);
+
+ /* options */
+ uiBlockBeginAlign(block);
+ if (curarea->spacetype == SPACE_VIEW3D) {
+ but= uiDefBut(block, BUT, B_REDR, "Convert to...", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Converts this layer's strokes to geometry (Hotkey = Alt-Shift-C)");
+ uiButSetFunc(but, gp_ui_convertlayer_cb, gpd, gpl);
+ }
+ else {
+ but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer (Hotkey = Alt-XKEY/DEL)");
+ uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl);
+ }
+
+ but= uiDefBut(block, BUT, B_REDR, "Del Last Stroke", *xco+160, *yco-95, 140, 20, NULL, 0, 0, 0, 0, "Erases the last stroke from the active frame (Hotkey = Alt-XKEY/DEL)");
+ uiButSetFunc(but, gp_ui_delstroke_cb, gpd, gpl);
+ uiBlockEndAlign(block);
+ }
+ }
+
+ /* adjust height for new to start */
+ (*yco) -= (height + 27);
+}
+#endif
+/* Draw the contents for a grease-pencil panel. This assumes several things:
+ * - that panel has been created, is 318 x 204. max yco is 225
+ * - that a toggle for turning on/off gpencil drawing is 150 x 20, starting from (10,225)
+ * which is basically the top left-hand corner
+ * It will return the amount of extra space to extend the panel by
+ */
+short draw_gpencil_panel (uiBlock *block, bGPdata *gpd, ScrArea *sa)
+{
+#if 0
+ uiBut *but;
+ bGPDlayer *gpl;
+ short xco= 10, yco= 170;
+
+ /* draw gpd settings first */
+ {
+ /* add new layer buttons */
+ but= uiDefBut(block, BUT, B_REDR, "Add New Layer", 10,205,150,20, 0, 0, 0, 0, 0, "Adds a new Grease Pencil Layer");
+ uiButSetFunc(but, gp_ui_addlayer_cb, gpd, NULL);
+
+
+ /* show override lmb-clicks button + painting lock */
+ uiBlockBeginAlign(block);
+ if ((gpd->flag & GP_DATA_EDITPAINT)==0) {
+ uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 130, 20, &gpd->flag, 0, 0, 0, 0, "Interpret click-drag as new strokes");
+
+ uiBlockSetCol(block, TH_BUT_SETTING);
+ uiDefIconButBitI(block, ICONTOG, GP_DATA_LMBPLOCK, B_REDR, ICON_UNLOCKED, 300, 225, 20, 20, &gpd->flag, 0.0, 0.0, 0, 0, "Painting cannot occur with Shift-LMB (when making selections)");
+ uiBlockSetCol(block, TH_AUTO);
+ }
+ else
+ uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 150, 20, &gpd->flag, 0, 0, 0, 0, "Interpret click-drag as new strokes");
+ uiBlockEndAlign(block);
+
+ /* 'view align' button (naming depends on context) */
+ if (sa->spacetype == SPACE_VIEW3D)
+ uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Sketch in 3D", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added in 3D-space");
+ else
+ uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Stick to View", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added on 2d-canvas");
+ }
+
+ /* draw for each layer */
+ for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
+ gp_drawui_layer(block, gpd, gpl, &xco, &yco);
+ }
+
+ /* return new height if necessary */
+ return (yco < 0) ? (204 - yco) : 204;
+#endif
+ return 0;
+}
+
+/* ************************************************** */
+/* GREASE PENCIL DRAWING */
+
+/* ----- General Defines ------ */
+
+/* flags for sflag */
+enum {
+ GP_DRAWDATA_NOSTATUS = (1<<0), /* don't draw status info */
+ GP_DRAWDATA_ONLY3D = (1<<1), /* only draw 3d-strokes */
+ GP_DRAWDATA_ONLYV2D = (1<<2), /* only draw 'canvas' strokes */
+ GP_DRAWDATA_ONLYI2D = (1<<3), /* only draw 'image' strokes */
+};
+
+/* thickness above which we should use special drawing */
+#define GP_DRAWTHICKNESS_SPECIAL 3
+
+/* ----- Tool Buffer Drawing ------ */
+
+/* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */
+static void gp_draw_stroke_buffer (tGPspoint *points, int totpoints, short thickness, short dflag, short sflag)
+{
+ tGPspoint *pt;
+ int i;
+
+ /* error checking */
+ if ((points == NULL) || (totpoints <= 0))
+ return;
+
+ /* check if buffer can be drawn */
+ if (dflag & (GP_DRAWDATA_ONLY3D|GP_DRAWDATA_ONLYV2D))
+ return;
+
+ /* if drawing a single point, draw it larger */
+ if (totpoints == 1) {
+ /* draw point */
+ glBegin(GL_POINTS);
+ glVertex2f(points->x, points->y);
+ glEnd();
+ }
+ else if (sflag & GP_STROKE_ERASER) {
+ /* don't draw stroke at all! */
+ }
+ else {
+ float oldpressure = 0.0f;
+
+ /* draw stroke curve */
+ if (G.f & G_DEBUG) setlinestyle(2);
+
+ glBegin(GL_LINE_STRIP);
+ for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
+ if (fabs(pt->pressure - oldpressure) > 0.2f) {
+ glEnd();
+ glLineWidth(pt->pressure * thickness);
+ glBegin(GL_LINE_STRIP);
+
+ glVertex2f(pt->x, pt->y);
+
+ oldpressure = pt->pressure;
+ }
+ else
+ glVertex2f(pt->x, pt->y);
+ }
+ glEnd();
+
+ if (G.f & G_DEBUG) setlinestyle(0);
+ }
+}
+
+/* ----- Existing Strokes Drawing (3D and Point) ------ */
+
+/* draw a given stroke - just a single dot (only one point) */
+static void gp_draw_stroke_point (bGPDspoint *points, short thickness, short sflag, int offsx, int offsy, int winx, int winy)
+{
+ /* draw point */
+ if (sflag & GP_STROKE_3DSPACE) {
+ glBegin(GL_POINTS);
+ glVertex3f(points->x, points->y, points->z);
+ glEnd();
+ }
+ else {
+ int spacetype= 0; // XXX make local gpencil state var?
+ float co[2];
+
+ /* get coordinates of point */
+ if (sflag & GP_STROKE_2DSPACE) {
+ co[0]= points->x;
+ co[1]= points->y;
+ }
+ else if (sflag & GP_STROKE_2DIMAGE) {
+ co[0]= (points->x * winx) + offsx;
+ co[1]= (points->y * winy) + offsy;
+ }
+ else {
+ co[0]= (points->x / 1000 * winx);
+ co[1]= (points->y / 1000 * winy);
+ }
+
+ /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, simple dot looks ok
+ * - also mandatory in if Image Editor 'image-based' dot
+ */
+ if ( (thickness < GP_DRAWTHICKNESS_SPECIAL) ||
+ ((spacetype==SPACE_IMAGE) && (sflag & GP_STROKE_2DSPACE)) )
+ {
+ glBegin(GL_POINTS);
+ glVertex2fv(co);
+ glEnd();
+ }
+ else
+ {
+ /* draw filled circle as is done in circf (but without the matrix push/pops which screwed things up) */
+ GLUquadricObj *qobj = gluNewQuadric();
+
+ gluQuadricDrawStyle(qobj, GLU_FILL);
+
+ /* need to translate drawing position, but must reset after too! */
+ glTranslatef(co[0], co[1], 0.);
+ gluDisk(qobj, 0.0, thickness, 32, 1);
+ glTranslatef(-co[0], -co[1], 0.);
+
+ gluDeleteQuadric(qobj);
+ }
+ }
+}
+
+/* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */
+static void gp_draw_stroke_3d (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, short debug, int winx, int winy)
+{
+ bGPDspoint *pt;
+ float oldpressure = 0.0f;
+ int i;
+
+ /* draw stroke curve */
+ glBegin(GL_LINE_STRIP);
+ for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
+ if (fabs(pt->pressure - oldpressure) > 0.2f) {
+ glEnd();
+ glLineWidth(pt->pressure * thickness);
+ glBegin(GL_LINE_STRIP);
+
+ glVertex3f(pt->x, pt->y, pt->z);
+
+ oldpressure = pt->pressure;
+ }
+ else
+ glVertex3f(pt->x, pt->y, pt->z);
+ }
+ glEnd();
+
+ /* draw debug points of curve on top? */
+ if (debug) {
+ glBegin(GL_POINTS);
+ for (i=0, pt=points; i < totpoints && pt; i++, pt++)
+ glVertex3f(pt->x, pt->y, pt->z);
+ glEnd();
+ }
+}
+
+/* ----- Fancy 2D-Stroke Drawing ------ */
+
+/* draw a given stroke in 2d */
+static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag,
+ short debug, int offsx, int offsy, int winx, int winy)
+{
+ int spacetype= 0; // XXX make local gpencil state var?
+
+ /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, 'smooth' opengl lines look better
+ * - 'smooth' opengl lines are also required if Image Editor 'image-based' stroke
+ */
+ if ( (thickness < GP_DRAWTHICKNESS_SPECIAL) ||
+ ((spacetype==SPACE_IMAGE) && (dflag & GP_DRAWDATA_ONLYV2D)) )
+ {
+ bGPDspoint *pt;
+ int i;
+
+ glBegin(GL_LINE_STRIP);
+ for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
+ if (sflag & GP_STROKE_2DSPACE) {
+ glVertex2f(pt->x, pt->y);
+ }
+ else if (sflag & GP_STROKE_2DIMAGE) {
+ const float x= (pt->x * winx) + offsx;
+ const float y= (pt->y * winy) + offsy;
+
+ glVertex2f(x, y);
+ }
+ else {
+ const float x= (pt->x / 1000 * winx);
+ const float y= (pt->y / 1000 * winy);
+
+ glVertex2f(x, y);
+ }
+ }
+ glEnd();
+ }
+
+ /* tesselation code - draw stroke as series of connected quads with connection
+ * edges rotated to minimise shrinking artifacts, and rounded endcaps
+ */
+ else
+ {
+ bGPDspoint *pt1, *pt2;
+ float pm[2];
+ int i;
+
+ glShadeModel(GL_FLAT);
+ glBegin(GL_QUADS);
+
+ for (i=0, pt1=points, pt2=points+1; i < (totpoints-1); i++, pt1++, pt2++) {
+ float s0[2], s1[2]; /* segment 'center' points */
+ float t0[2], t1[2]; /* tesselated coordinates */
+ float m1[2], m2[2]; /* gradient and normal */
+ float mt[2], sc[2]; /* gradient for thickness, point for end-cap */
+ float pthick; /* thickness at segment point */
+
+ /* get x and y coordinates from points */
+ if (sflag & GP_STROKE_2DSPACE) {
+ s0[0]= pt1->x; s0[1]= pt1->y;
+ s1[0]= pt2->x; s1[1]= pt2->y;
+ }
+ else if (sflag & GP_STROKE_2DIMAGE) {
+ s0[0]= (pt1->x * winx) + offsx;
+ s0[1]= (pt1->y * winy) + offsy;
+ s1[0]= (pt2->x * winx) + offsx;
+ s1[1]= (pt2->y * winy) + offsy;
+ }
+ else {
+ s0[0]= (pt1->x / 1000 * winx);
+ s0[1]= (pt1->y / 1000 * winy);
+ s1[0]= (pt2->x / 1000 * winx);
+ s1[1]= (pt2->y / 1000 * winy);
+ }
+
+ /* calculate gradient and normal - 'angle'=(ny/nx) */
+ m1[1]= s1[1] - s0[1];
+ m1[0]= s1[0] - s0[0];
+ Normalize2(m1);
+ m2[1]= -m1[0];
+ m2[0]= m1[1];
+
+ /* always use pressure from first point here */
+ pthick= (pt1->pressure * thickness);
+
+ /* if the first segment, start of segment is segment's normal */
+ if (i == 0) {
+ /* draw start cap first
+ * - make points slightly closer to center (about halfway across)
+ */
+ mt[0]= m2[0] * pthick * 0.5f;
+ mt[1]= m2[1] * pthick * 0.5f;
+ sc[0]= s0[0] - (m1[0] * pthick * 0.75f);
+ sc[1]= s0[1] - (m1[1] * pthick * 0.75f);
+
+ t0[0]= sc[0] - mt[0];
+ t0[1]= sc[1] - mt[1];
+ t1[0]= sc[0] + mt[0];
+ t1[1]= sc[1] + mt[1];
+
+ glVertex2fv(t0);
+ glVertex2fv(t1);
+
+ /* calculate points for start of segment */
+ mt[0]= m2[0] * pthick;
+ mt[1]= m2[1] * pthick;
+
+ t0[0]= s0[0] - mt[0];
+ t0[1]= s0[1] - mt[1];
+ t1[0]= s0[0] + mt[0];
+ t1[1]= s0[1] + mt[1];
+
+ /* draw this line twice (first to finish off start cap, then for stroke) */
+ glVertex2fv(t1);
+ glVertex2fv(t0);
+ glVertex2fv(t0);
+ glVertex2fv(t1);
+ }
+ /* if not the first segment, use bisector of angle between segments */
+ else {
+ float mb[2]; /* bisector normal */
+ float athick, dfac; /* actual thickness, difference between thicknesses */
+
+ /* calculate gradient of bisector (as average of normals) */
+ mb[0]= (pm[0] + m2[0]) / 2;
+ mb[1]= (pm[1] + m2[1]) / 2;
+ Normalize2(mb);
+
+ /* calculate gradient to apply
+ * - as basis, use just pthick * bisector gradient
+ * - if cross-section not as thick as it should be, add extra padding to fix it
+ */
+ mt[0]= mb[0] * pthick;
+ mt[1]= mb[1] * pthick;
+ athick= Vec2Length(mt);
+ dfac= pthick - (athick * 2);
+ if ( ((athick * 2) < pthick) && (IS_EQ(athick, pthick)==0) )
+ {
+ mt[0] += (mb[0] * dfac);
+ mt[1] += (mb[1] * dfac);
+ }
+
+ /* calculate points for start of segment */
+ t0[0]= s0[0] - mt[0];
+ t0[1]= s0[1] - mt[1];
+ t1[0]= s0[0] + mt[0];
+ t1[1]= s0[1] + mt[1];
+
+ /* draw this line twice (once for end of current segment, and once for start of next) */
+ glVertex2fv(t1);
+ glVertex2fv(t0);
+ glVertex2fv(t0);
+ glVertex2fv(t1);
+ }
+
+ /* if last segment, also draw end of segment (defined as segment's normal) */
+ if (i == totpoints-2) {
+ /* for once, we use second point's pressure (otherwise it won't be drawn) */
+ pthick= (pt2->pressure * thickness);
+
+ /* calculate points for end of segment */
+ mt[0]= m2[0] * pthick;
+ mt[1]= m2[1] * pthick;
+
+ t0[0]= s1[0] - mt[0];
+ t0[1]= s1[1] - mt[1];
+ t1[0]= s1[0] + mt[0];
+ t1[1]= s1[1] + mt[1];
+
+ /* draw this line twice (once for end of stroke, and once for endcap)*/
+ glVertex2fv(t1);
+ glVertex2fv(t0);
+ glVertex2fv(t0);
+ glVertex2fv(t1);
+
+
+ /* draw end cap as last step
+ * - make points slightly closer to center (about halfway across)
+ */
+ mt[0]= m2[0] * pthick * 0.5f;
+ mt[1]= m2[1] * pthick * 0.5f;
+ sc[0]= s1[0] + (m1[0] * pthick * 0.75f);
+ sc[1]= s1[1] + (m1[1] * pthick * 0.75f);
+
+ t0[0]= sc[0] - mt[0];
+ t0[1]= sc[1] - mt[1];
+ t1[0]= sc[0] + mt[0];
+ t1[1]= sc[1] + mt[1];
+
+ glVertex2fv(t1);
+ glVertex2fv(t0);
+ }
+
+ /* store stroke's 'natural' normal for next stroke to use */
+ Vec2Copyf(pm, m2);
+ }
+
+ glEnd();
+ }
+
+ /* draw debug points of curve on top? (original stroke points) */
+ if (debug) {
+ bGPDspoint *pt;
+ int i;
+
+ glBegin(GL_POINTS);
+ for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
+ if (sflag & GP_STROKE_2DSPACE) {
+ glVertex2f(pt->x, pt->y);
+ }
+ else if (sflag & GP_STROKE_2DIMAGE) {
+ const float x= (float)((pt->x * winx) + offsx);
+ const float y= (float)((pt->y * winy) + offsy);
+
+ glVertex2f(x, y);
+ }
+ else {
+ const float x= (float)(pt->x / 1000 * winx);
+ const float y= (float)(pt->y / 1000 * winy);
+
+ glVertex2f(x, y);
+ }
+ }
+ glEnd();
+ }
+}
+
+/* ----- General Drawing ------ */
+
+/* draw a set of strokes */
+static void gp_draw_strokes (bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag,
+ short debug, short lthick, float color[4])
+{
+ bGPDstroke *gps;
+
+ /* set color first (may need to reset it again later too) */
+ glColor4f(color[0], color[1], color[2], color[3]);
+
+ for (gps= gpf->strokes.first; gps; gps= gps->next) {
+ /* check if stroke can be drawn - checks here generally fall into pairs */
+ if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & GP_STROKE_3DSPACE))
+ continue;
+ if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE))
+ continue;
+ if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE))
+ continue;
+ if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE))
+ continue;
+ if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE))
+ continue;
+ if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE))
+ continue;
+ if ((gps->points == 0) || (gps->totpoints < 1))
+ continue;
+
+ /* check which stroke-drawer to use */
+ if (gps->totpoints == 1)
+ gp_draw_stroke_point(gps->points, lthick, gps->flag, offsx, offsy, winx, winy);
+ else if (dflag & GP_DRAWDATA_ONLY3D)
+ gp_draw_stroke_3d(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy);
+ else if (gps->totpoints > 1)
+ gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, offsx, offsy, winx, winy);
+ }
+}
+
+/* draw grease-pencil datablock */
+static void gp_draw_data (bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
+{
+ bGPDlayer *gpl, *actlay=NULL;
+
+ /* turn on smooth lines (i.e. anti-aliasing) */
+ glEnable(GL_LINE_SMOOTH);
+
+ /* turn on alpha-blending */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ /* loop over layers, drawing them */
+ for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
+ bGPDframe *gpf;
+
+ short debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? 1 : 0;
+ short lthick= gpl->thickness;
+ float color[4], tcolor[4];
+
+ /* don't draw layer if hidden */
+ if (gpl->flag & GP_LAYER_HIDE)
+ continue;
+
+ /* if layer is active one, store pointer to it */
+ if (gpl->flag & GP_LAYER_ACTIVE)
+ actlay= gpl;
+
+ /* get frame to draw */
+ gpf= gpencil_layer_getframe(gpl, cfra, 0);
+ if (gpf == NULL)
+ continue;
+
+ /* set color, stroke thickness, and point size */
+ glLineWidth(lthick);
+ QUATCOPY(color, gpl->color); // just for copying 4 array elements
+ QUATCOPY(tcolor, gpl->color); // additional copy of color (for ghosting)
+ glColor4f(color[0], color[1], color[2], color[3]);
+ glPointSize((float)(gpl->thickness + 2));
+
+ /* draw 'onionskins' (frame left + right) */
+ if (gpl->flag & GP_LAYER_ONIONSKIN) {
+ /* drawing method - only immediately surrounding (gstep = 0), or within a frame range on either side (gstep > 0)*/
+ if (gpl->gstep) {
+ bGPDframe *gf;
+ float fac;
+
+ /* draw previous frames first */
+ for (gf=gpf->prev; gf; gf=gf->prev) {
+ /* check if frame is drawable */
+ if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
+ /* alpha decreases with distance from curframe index */
+ fac= (float)(gpf->framenum - gf->framenum) / (float)gpl->gstep;
+ tcolor[3] = color[3] - fac;
+ gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
+ }
+ else
+ break;
+ }
+
+ /* now draw next frames */
+ for (gf= gpf->next; gf; gf=gf->next) {
+ /* check if frame is drawable */
+ if ((gf->framenum - gpf->framenum) <= gpl->gstep) {
+ /* alpha decreases with distance from curframe index */
+ fac= (float)(gf->framenum - gpf->framenum) / (float)gpl->gstep;
+ tcolor[3] = color[3] - fac;
+ gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
+ }
+ else
+ break;
+ }
+
+ /* restore alpha */
+ glColor4f(color[0], color[1], color[2], color[3]);
+ }
+ else {
+ /* draw the strokes for the ghost frames (at half of the alpha set by user) */
+ if (gpf->prev) {
+ tcolor[3] = (color[3] / 7);
+ gp_draw_strokes(gpf->prev, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
+ }
+
+ if (gpf->next) {
+ tcolor[3] = (color[3] / 4);
+ gp_draw_strokes(gpf->next, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
+ }
+
+ /* restore alpha */
+ glColor4f(color[0], color[1], color[2], color[3]);
+ }
+ }
+
+ /* draw the strokes already in active frame */
+ tcolor[3]= color[3];
+ gp_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
+
+ /* Check if may need to draw the active stroke cache, only if this layer is the active layer
+ * that is being edited. (Stroke buffer is currently stored in gp-data)
+ */
+ if ((G.f & G_GREASEPENCIL) && (gpl->flag & GP_LAYER_ACTIVE) &&
+ (gpf->flag & GP_FRAME_PAINT))
+ {
+ /* Buffer stroke needs to be drawn with a different linestyle to help differentiate them from normal strokes. */
+ gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag);
+ }
+ }
+
+ /* turn off alpha blending, then smooth lines */
+ glDisable(GL_BLEND); // alpha blending
+ glDisable(GL_LINE_SMOOTH); // smooth lines
+
+ /* show info for debugging the status of gpencil */
+ if ( ((dflag & GP_DRAWDATA_NOSTATUS)==0) && (gpd->flag & GP_DATA_DISPINFO) ) {
+ char printable[256];
+ short xmax;
+
+ /* get text to display */
+ if (actlay) {
+ if (gpd->flag & GP_DATA_EDITPAINT)
+ UI_ThemeColor(TH_BONE_POSE); // should be blue-ish
+ else if (actlay->actframe == NULL)
+ UI_ThemeColor(TH_REDALERT);
+ else if (actlay->actframe->framenum == cfra)
+ UI_ThemeColor(TH_VERTEX_SELECT); // should be yellow
+ else
+ UI_ThemeColor(TH_TEXT_HI);
+
+ if (actlay->actframe) {
+ sprintf(printable, "GPencil: Layer ('%s'), Frame (%d)%s",
+ actlay->info, actlay->actframe->framenum,
+ ((gpd->flag & GP_DATA_EDITPAINT)?" , Draw Mode On":"") );
+ }
+ else {
+ sprintf(printable, "GPencil: Layer ('%s'), Frame <None>%s",
+ actlay->info, ((gpd->flag & GP_DATA_EDITPAINT)?" , Draw Mode On":"") );
+ }
+ }
+ else {
+ UI_ThemeColor(TH_REDALERT);
+ sprintf(printable, "GPencil: Layer <None>");
+ }
+ xmax= GetButStringLength(printable);
+
+ /* only draw it if view is wide enough (assume padding of 20 is enough for now) */
+ if (winx > (xmax + 20)) {
+ glRasterPos2i(winx-xmax, winy-20);
+ BMF_DrawString(G.fonts, printable);
+ }
+ }
+
+ /* restore initial gl conditions */
+ glLineWidth(1.0);
+ glPointSize(1.0);
+ glColor4f(0, 0, 0, 1);
+}
+
+/* ----- Grease Pencil Sketches Drawing API ------ */
+
+/* draw grease-pencil sketches to specified 2d-view that uses ibuf corrections */
+void draw_gpencil_2dimage (bContext *C, ImBuf *ibuf)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= CTX_wm_region(C);
+ Scene *scene= CTX_data_scene(C);
+ bGPdata *gpd;
+ int offsx, offsy, sizex, sizey;
+ int dflag = GP_DRAWDATA_NOSTATUS;
+
+ /* check that we have grease-pencil stuff to draw */
+ if (ELEM(NULL, sa, ibuf)) return;
+ gpd= gpencil_data_getactive(sa);
+ if (gpd == NULL) return;
+
+ /* calculate rect */
+ switch (sa->spacetype) {
+ case SPACE_IMAGE: /* image */
+ {
+
+ /* just draw using standard scaling (settings here are currently ignored anyways) */
+ // FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled
+ offsx= 0;
+ offsy= 0;
+ sizex= ar->winx;
+ sizey= ar->winy;
+
+ wmOrtho2(ar->v2d.cur.xmin, ar->v2d.cur.xmax, ar->v2d.cur.ymin, ar->v2d.cur.ymax);
+
+ dflag |= GP_DRAWDATA_ONLYV2D;
+ }
+ break;
+
+ case SPACE_SEQ: /* sequence */
+ {
+ SpaceSeq *sseq= (SpaceSeq *)sa->spacedata.first;
+ float zoom, zoomx, zoomy;
+
+ /* calculate accessory values */
+ zoom= (float)(SEQ_ZOOM_FAC(sseq->zoom));
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
+ /* XXX sequencer zoom should store it? */
+ zoomx = zoom; // * ((float)G.scene->r.xasp / (float)G.scene->r.yasp);
+ zoomy = zoom;
+ }
+ else
+ zoomx = zoomy = zoom;
+
+ /* calculate transforms (Note: we use ibuf here, as we have it) */
+ sizex= (int)(zoomx * ibuf->x);
+ sizey= (int)(zoomy * ibuf->y);
+ offsx= (int)( (ar->winx-sizex)/2 + sseq->xof );
+ offsy= (int)( (ar->winy-sizey)/2 + sseq->yof );
+
+ dflag |= GP_DRAWDATA_ONLYI2D;
+ }
+ break;
+
+ default: /* for spacetype not yet handled */
+ offsx= 0;
+ offsy= 0;
+ sizex= ar->winx;
+ sizey= ar->winy;
+
+ dflag |= GP_DRAWDATA_ONLYI2D;
+ break;
+ }
+
+
+ /* draw it! */
+ gp_draw_data(gpd, offsx, offsy, sizex, sizey, CFRA, dflag);
+}
+
+/* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly
+ * Note: this gets called twice - first time with onlyv2d=1 to draw 'canvas' strokes, second time with onlyv2d=0 for screen-aligned strokes
+ */
+void draw_gpencil_2dview (bContext *C, short onlyv2d)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= CTX_wm_region(C);
+ Scene *scene= CTX_data_scene(C);
+ bGPdata *gpd;
+ int dflag = 0;
+
+ /* check that we have grease-pencil stuff to draw */
+ if (sa == NULL) return;
+ gpd= gpencil_data_getactive(sa);
+ if (gpd == NULL) return;
+
+ /* draw it! */
+ if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D|GP_DRAWDATA_NOSTATUS);
+ gp_draw_data(gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag);
+}
+
+/* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly
+ * Note: this gets called twice - first time with only3d=1 to draw 3d-strokes, second time with only3d=0 for screen-aligned strokes
+ */
+void draw_gpencil_3dview (bContext *C, short only3d)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= CTX_wm_region(C);
+ Scene *scene= CTX_data_scene(C);
+ bGPdata *gpd;
+ int dflag = 0;
+
+ /* check that we have grease-pencil stuff to draw */
+ gpd= gpencil_data_getactive(sa);
+ if (gpd == NULL) return;
+
+ /* draw it! */
+ if (only3d) dflag |= (GP_DRAWDATA_ONLY3D|GP_DRAWDATA_NOSTATUS);
+ gp_draw_data(gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag);
+}
+
+/* draw grease-pencil sketches to opengl render window assuming that matrices are already set correctly */
+// XXX porting note, ogl render will probably be a window with one 3d region
+void draw_gpencil_oglrender (bContext *C)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= (View3D *)sa->spacedata.first;
+ ARegion *ar= CTX_wm_region(C);
+ Scene *scene= CTX_data_scene(C);
+ bGPdata *gpd;
+
+ /* assume gpencil data comes from v3d */
+ if (v3d == NULL) return;
+ gpd= v3d->gpd;
+ if (gpd == NULL) return;
+
+ /* pass 1: draw 3d-strokes ------------ > */
+ gp_draw_data(gpd, 0, 0, ar->winx, ar->winy, CFRA, (GP_DRAWDATA_NOSTATUS|GP_DRAWDATA_ONLY3D));
+
+ /* pass 2: draw 2d-strokes ------------ > */
+ /* adjust view matrices */
+ wmOrtho2(-0.375f, (float)(ar->winx)-0.375f, -0.375f, (float)(ar->winy)-0.375f);
+ glLoadIdentity();
+
+ /* draw it! */
+ gp_draw_data(gpd, 0, 0, ar->winx, ar->winy, CFRA, GP_DRAWDATA_NOSTATUS);
+}
+
+/* ************************************************** */
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c
new file mode 100644
index 00000000000..28748d4a631
--- /dev/null
+++ b/source/blender/editors/gpencil/editaction_gpencil.c
@@ -0,0 +1,740 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "DNA_listBase.h"
+#include "DNA_action_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+#include "BKE_blender.h"
+#include "BKE_fcurve.h"
+#include "BKE_gpencil.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "PIL_time.h"
+
+#include "ED_anim_api.h"
+#include "ED_gpencil.h"
+#include "ED_keyframes_edit.h"
+#include "ED_keyframes_draw.h"
+#include "ED_markers.h"
+#include "ED_util.h"
+#include "ED_types.h"
+
+#include "gpencil_intern.h"
+
+/* XXX */
+static void actdata_filter() {} // is now ANIM_animdata_filter()
+static void BIF_undo_push() {}
+static void error() {}
+static void *get_action_context() {return NULL;} // is now ANIM_animdata_get_context()
+/* XXX */
+
+
+/* ***************************************** */
+/* NOTE ABOUT THIS FILE:
+ * This file contains code for editing Grease Pencil data in the Action Editor
+ * as a 'keyframes', so that a user can adjust the timing of Grease Pencil drawings.
+ * Therefore, this file mostly contains functions for selecting Grease-Pencil frames.
+ */
+/* ***************************************** */
+/* Generics - Loopers */
+
+/* Loops over the gp-frames for a gp-layer, and applies the given callback */
+short gplayer_frames_looper (bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPDframe *, Scene *))
+{
+ bGPDframe *gpf;
+
+ /* error checker */
+ if (gpl == NULL)
+ return 0;
+
+ /* do loop */
+ for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+ /* execute callback */
+ if (gpf_cb(gpf, scene))
+ return 1;
+ }
+
+ /* nothing to return */
+ return 0;
+}
+
+/* ****************************************** */
+/* Data Conversion Tools */
+
+/* make a listing all the gp-frames in a layer as cfraelems */
+void gplayer_make_cfra_list (bGPDlayer *gpl, ListBase *elems, short onlysel)
+{
+ bGPDframe *gpf;
+ CfraElem *ce;
+
+ /* error checking */
+ if (ELEM(NULL, gpl, elems))
+ return;
+
+ /* loop through gp-frames, adding */
+ for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+ if ((onlysel == 0) || (gpf->flag & GP_FRAME_SELECT)) {
+ ce= MEM_callocN(sizeof(CfraElem), "CfraElem");
+
+ ce->cfra= (float)gpf->framenum;
+ ce->sel= (gpf->flag & GP_FRAME_SELECT) ? 1 : 0;
+
+ BLI_addtail(elems, ce);
+ }
+ }
+}
+
+/* ***************************************** */
+/* Selection Tools */
+
+/* check if one of the frames in this layer is selected */
+short is_gplayer_frame_selected (bGPDlayer *gpl)
+{
+ bGPDframe *gpf;
+
+ /* error checking */
+ if (gpl == NULL)
+ return 0;
+
+ /* stop at the first one found */
+ for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+ if (gpf->flag & GP_FRAME_SELECT)
+ return 1;
+ }
+
+ /* not found */
+ return 0;
+}
+
+/* helper function - select gp-frame based on SELECT_* mode */
+static void gpframe_select (bGPDframe *gpf, short select_mode)
+{
+ switch (select_mode) {
+ case SELECT_ADD:
+ gpf->flag |= GP_FRAME_SELECT;
+ break;
+ case SELECT_SUBTRACT:
+ gpf->flag &= ~GP_FRAME_SELECT;
+ break;
+ case SELECT_INVERT:
+ gpf->flag ^= GP_FRAME_SELECT;
+ break;
+ }
+}
+
+/* set all/none/invert select (like above, but with SELECT_* modes) */
+void select_gpencil_frames (bGPDlayer *gpl, short select_mode)
+{
+ bGPDframe *gpf;
+
+ /* error checking */
+ if (gpl == NULL)
+ return;
+
+ /* handle according to mode */
+ for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+ gpframe_select(gpf, select_mode);
+ }
+}
+
+/* set all/none/invert select */
+void set_gplayer_frame_selection (bGPDlayer *gpl, short mode)
+{
+ /* error checking */
+ if (gpl == NULL)
+ return;
+
+ /* convert mode to select_mode */
+ switch (mode) {
+ case 2:
+ mode= SELECT_INVERT;
+ break;
+ case 1:
+ mode= SELECT_ADD;
+ break;
+ case 0:
+ mode= SELECT_SUBTRACT;
+ break;
+ default:
+ return;
+ }
+
+ /* now call the standard function */
+ select_gpencil_frames (gpl, mode);
+}
+
+/* select the frame in this layer that occurs on this frame (there should only be one at most) */
+void select_gpencil_frame (bGPDlayer *gpl, int selx, short select_mode)
+{
+ bGPDframe *gpf;
+
+ /* search through frames for a match */
+ for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+ /* there should only be one frame with this frame-number */
+ if (gpf->framenum == selx) {
+ gpframe_select(gpf, select_mode);
+ break;
+ }
+ }
+}
+
+/* select the frames in this layer that occur within the bounds specified */
+void borderselect_gplayer_frames (bGPDlayer *gpl, float min, float max, short select_mode)
+{
+ bGPDframe *gpf;
+
+ /* only select those frames which are in bounds */
+ for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+ if (IN_RANGE(gpf->framenum, min, max))
+ gpframe_select(gpf, select_mode);
+ }
+}
+
+
+/* De-selects or inverts the selection of Layers for a grease-pencil block
+ * mode: 0 = default behaviour (select all), 1 = test if (de)select all, 2 = invert all
+ */
+void deselect_gpencil_layers (void *data, short mode)
+{
+ ListBase act_data = {NULL, NULL};
+ bActListElem *ale;
+ int filter, sel=1;
+
+ /* filter data */
+ filter= ACTFILTER_VISIBLE;
+ actdata_filter(&act_data, filter, data, ACTCONT_GPENCIL);
+
+ /* See if we should be selecting or deselecting */
+ if (mode == 1) {
+ for (ale= act_data.first; ale; ale= ale->next) {
+ if (sel == 0)
+ break;
+
+ if (ale->flag & GP_LAYER_SELECT)
+ sel= 0;
+ }
+ }
+ else
+ sel= 0;
+
+ /* Now set the flags */
+ for (ale= act_data.first; ale; ale= ale->next) {
+ bGPDlayer *gpl= (bGPDlayer *)ale->data;
+
+ if (mode == 2)
+ gpl->flag ^= GP_LAYER_SELECT;
+ else if (sel)
+ gpl->flag |= GP_LAYER_SELECT;
+ else
+ gpl->flag &= ~GP_LAYER_SELECT;
+
+ gpl->flag &= ~GP_LAYER_ACTIVE;
+ }
+
+ /* Cleanup */
+ BLI_freelistN(&act_data);
+}
+
+/* ***************************************** */
+/* Frame Editing Tools */
+
+/* Delete selected grease-pencil layers */
+void delete_gpencil_layers (void)
+{
+ ListBase act_data = {NULL, NULL};
+ bActListElem *ale, *next;
+ void *data;
+ short datatype;
+ int filter;
+
+ /* determine what type of data we are operating on */
+ data = get_action_context(&datatype);
+ if (data == NULL) return;
+ if (datatype != ACTCONT_GPENCIL) return;
+
+ /* filter data */
+ filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_CHANNELS | ACTFILTER_SEL);
+ actdata_filter(&act_data, filter, data, datatype);
+
+ /* clean up grease-pencil layers */
+ for (ale= act_data.first; ale; ale= next) {
+ bGPdata *gpd= (bGPdata *)ale->owner;
+ bGPDlayer *gpl= (bGPDlayer *)ale->data;
+ next= ale->next;
+
+ /* free layer and its data */
+ if (SEL_GPL(gpl)) {
+ free_gpencil_frames(gpl);
+ BLI_freelinkN(&gpd->layers, gpl);
+ }
+
+ /* free temp memory */
+ BLI_freelinkN(&act_data, ale);
+ }
+
+ BIF_undo_push("Delete GPencil Layers");
+}
+
+/* Delete selected frames */
+void delete_gplayer_frames (bGPDlayer *gpl)
+{
+ bGPDframe *gpf, *gpfn;
+
+ /* error checking */
+ if (gpl == NULL)
+ return;
+
+ /* check for frames to delete */
+ for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
+ gpfn= gpf->next;
+
+ if (gpf->flag & GP_FRAME_SELECT)
+ gpencil_layer_delframe(gpl, gpf);
+ }
+}
+
+/* Duplicate selected frames from given gp-layer */
+void duplicate_gplayer_frames (bGPDlayer *gpl)
+{
+ bGPDframe *gpf, *gpfn;
+
+ /* error checking */
+ if (gpl == NULL)
+ return;
+
+ /* duplicate selected frames */
+ for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
+ gpfn= gpf->next;
+
+ /* duplicate this frame */
+ if (gpf->flag & GP_FRAME_SELECT) {
+ bGPDframe *gpfd;
+
+ /* duplicate frame, and deselect self */
+ gpfd= gpencil_frame_duplicate(gpf);
+ gpf->flag &= ~GP_FRAME_SELECT;
+
+ BLI_insertlinkafter(&gpl->frames, gpf, gpfd);
+ }
+ }
+}
+
+/* -------------------------------------- */
+/* Copy and Paste Tools */
+/* - The copy/paste buffer currently stores a set of GP_Layers, with temporary
+ * GP_Frames with the necessary strokes
+ * - Unless there is only one element in the buffer, names are also tested to check for compatability.
+ * - All pasted frames are offset by the same amount. This is calculated as the difference in the times of
+ * the current frame and the 'first keyframe' (i.e. the earliest one in all channels).
+ * - The earliest frame is calculated per copy operation.
+ */
+
+/* globals for copy/paste data (like for other copy/paste buffers) */
+ListBase gpcopybuf = {NULL, NULL};
+static int gpcopy_firstframe= 999999999;
+
+/* This function frees any MEM_calloc'ed copy/paste buffer data */
+void free_gpcopybuf ()
+{
+ free_gpencil_layers(&gpcopybuf);
+
+ gpcopybuf.first= gpcopybuf.last= NULL;
+ gpcopy_firstframe= 999999999;
+}
+
+/* This function adds data to the copy/paste buffer, freeing existing data first
+ * Only the selected GP-layers get their selected keyframes copied.
+ */
+void copy_gpdata ()
+{
+ ListBase act_data = {NULL, NULL};
+ bActListElem *ale;
+ int filter;
+ void *data;
+ short datatype;
+
+ /* clear buffer first */
+ free_gpcopybuf();
+
+ /* get data */
+ data= get_action_context(&datatype);
+ if (data == NULL) return;
+ if (datatype != ACTCONT_GPENCIL) return;
+
+ /* filter data */
+ filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL);
+ actdata_filter(&act_data, filter, data, datatype);
+
+ /* assume that each of these is an ipo-block */
+ for (ale= act_data.first; ale; ale= ale->next) {
+ bGPDlayer *gpls, *gpln;
+ bGPDframe *gpf, *gpfn;
+
+ /* get new layer to put into buffer */
+ gpls= (bGPDlayer *)ale->data;
+ gpln= MEM_callocN(sizeof(bGPDlayer), "GPCopyPasteLayer");
+
+ gpln->frames.first= gpln->frames.last= NULL;
+ strcpy(gpln->info, gpls->info);
+
+ BLI_addtail(&gpcopybuf, gpln);
+
+ /* loop over frames, and copy only selected frames */
+ for (gpf= gpls->frames.first; gpf; gpf= gpf->next) {
+ /* if frame is selected, make duplicate it and its strokes */
+ if (gpf->flag & GP_FRAME_SELECT) {
+ /* add frame to buffer */
+ gpfn= gpencil_frame_duplicate(gpf);
+ BLI_addtail(&gpln->frames, gpfn);
+
+ /* check if this is the earliest frame encountered so far */
+ if (gpf->framenum < gpcopy_firstframe)
+ gpcopy_firstframe= gpf->framenum;
+ }
+ }
+ }
+
+ /* check if anything ended up in the buffer */
+ if (ELEM(NULL, gpcopybuf.first, gpcopybuf.last))
+ error("Nothing copied to buffer");
+
+ /* free temp memory */
+ BLI_freelistN(&act_data);
+}
+
+void paste_gpdata (Scene *scene)
+{
+ ListBase act_data = {NULL, NULL};
+ bActListElem *ale;
+ int filter;
+ void *data;
+ short datatype;
+
+ const int offset = (CFRA - gpcopy_firstframe);
+ short no_name= 0;
+
+ /* check if buffer is empty */
+ if (ELEM(NULL, gpcopybuf.first, gpcopybuf.last)) {
+ error("No data in buffer to paste");
+ return;
+ }
+ /* check if single channel in buffer (disregard names if so) */
+ if (gpcopybuf.first == gpcopybuf.last)
+ no_name= 1;
+
+ /* get data */
+ data= get_action_context(&datatype);
+ if (data == NULL) return;
+ if (datatype != ACTCONT_GPENCIL) return;
+
+ /* filter data */
+ filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_FOREDIT);
+ actdata_filter(&act_data, filter, data, datatype);
+
+ /* from selected channels */
+ for (ale= act_data.first; ale; ale= ale->next) {
+ bGPDlayer *gpld= (bGPDlayer *)ale->data;
+ bGPDlayer *gpls= NULL;
+ bGPDframe *gpfs, *gpf;
+
+ /* find suitable layer from buffer to use to paste from */
+ for (gpls= gpcopybuf.first; gpls; gpls= gpls->next) {
+ /* check if layer name matches */
+ if ((no_name) || (strcmp(gpls->info, gpld->info)==0))
+ break;
+ }
+
+ /* this situation might occur! */
+ if (gpls == NULL)
+ continue;
+
+ /* add frames from buffer */
+ for (gpfs= gpls->frames.first; gpfs; gpfs= gpfs->next) {
+ /* temporarily apply offset to buffer-frame while copying */
+ gpfs->framenum += offset;
+
+ /* get frame to copy data into (if no frame returned, then just ignore) */
+ gpf= gpencil_layer_getframe(gpld, gpfs->framenum, 1);
+ if (gpf) {
+ bGPDstroke *gps, *gpsn;
+ ScrArea *sa;
+
+ /* get area that gp-data comes from */
+ sa= gpencil_data_findowner((bGPdata *)ale->owner);
+
+ /* this should be the right frame... as it may be a pre-existing frame,
+ * must make sure that only compatible stroke types get copied over
+ * - we cannot just add a duplicate frame, as that would cause errors
+ * - need to check for compatible types to minimise memory usage (copying 'junk' over)
+ */
+ for (gps= gpfs->strokes.first; gps; gps= gps->next) {
+ short stroke_ok;
+
+ /* if there's an area, check that it supports this type of stroke */
+ if (sa) {
+ stroke_ok= 0;
+
+ /* check if spacetype supports this type of stroke
+ * - NOTE: must sync this with gp_paint_initstroke() in gpencil.c
+ */
+ switch (sa->spacetype) {
+ case SPACE_VIEW3D: /* 3D-View: either screen-aligned or 3d-space */
+ if ((gps->flag == 0) || (gps->flag & GP_STROKE_3DSPACE))
+ stroke_ok= 1;
+ break;
+
+ case SPACE_NODE: /* Nodes Editor: either screen-aligned or view-aligned */
+ case SPACE_IMAGE: /* Image Editor: either screen-aligned or view\image-aligned */
+ if ((gps->flag == 0) || (gps->flag & GP_STROKE_2DSPACE))
+ stroke_ok= 1;
+ break;
+
+ case SPACE_SEQ: /* Sequence Editor: either screen-aligned or view-aligned */
+ if ((gps->flag == 0) || (gps->flag & GP_STROKE_2DIMAGE))
+ stroke_ok= 1;
+ break;
+ }
+ }
+ else
+ stroke_ok= 1;
+
+ /* if stroke is ok, we make a copy of this stroke and add to frame */
+ if (stroke_ok) {
+ /* make a copy of stroke, then of its points array */
+ gpsn= MEM_dupallocN(gps);
+ gpsn->points= MEM_dupallocN(gps->points);
+
+ /* append stroke to frame */
+ BLI_addtail(&gpf->strokes, gpsn);
+ }
+ }
+
+ /* if no strokes (i.e. new frame) added, free gpf */
+ if (gpf->strokes.first == NULL)
+ gpencil_layer_delframe(gpld, gpf);
+ }
+
+ /* unapply offset from buffer-frame */
+ gpfs->framenum -= offset;
+ }
+ }
+
+ /* free temp memory */
+ BLI_freelistN(&act_data);
+
+ /* undo and redraw stuff */
+ BIF_undo_push("Paste Grease Pencil Frames");
+}
+
+/* -------------------------------------- */
+/* Snap Tools */
+
+static short snap_gpf_nearest (bGPDframe *gpf, Scene *scene)
+{
+ if (gpf->flag & GP_FRAME_SELECT)
+ gpf->framenum= (int)(floor(gpf->framenum+0.5));
+ return 0;
+}
+
+static short snap_gpf_nearestsec (bGPDframe *gpf, Scene *scene)
+{
+ float secf = (float)FPS;
+ if (gpf->flag & GP_FRAME_SELECT)
+ gpf->framenum= (int)(floor(gpf->framenum/secf + 0.5f) * secf);
+ return 0;
+}
+
+static short snap_gpf_cframe (bGPDframe *gpf, Scene *scene)
+{
+ if (gpf->flag & GP_FRAME_SELECT)
+ gpf->framenum= (int)CFRA;
+ return 0;
+}
+
+static short snap_gpf_nearmarker (bGPDframe *gpf, Scene *scene)
+{
+ if (gpf->flag & GP_FRAME_SELECT)
+ gpf->framenum= (int)find_nearest_marker_time(&scene->markers, (float)gpf->framenum);
+ return 0;
+}
+
+
+/* snap selected frames to ... */
+void snap_gplayer_frames (bGPDlayer *gpl, Scene *scene, short mode)
+{
+ switch (mode) {
+ case 1: /* snap to nearest frame */
+ gplayer_frames_looper(gpl, scene, snap_gpf_nearest);
+ break;
+ case 2: /* snap to current frame */
+ gplayer_frames_looper(gpl, scene, snap_gpf_cframe);
+ break;
+ case 3: /* snap to nearest marker */
+ gplayer_frames_looper(gpl, scene, snap_gpf_nearmarker);
+ break;
+ case 4: /* snap to nearest second */
+ gplayer_frames_looper(gpl, scene, snap_gpf_nearestsec);
+ break;
+ default: /* just in case */
+ gplayer_frames_looper(gpl, scene, snap_gpf_nearest);
+ break;
+ }
+}
+
+/* -------------------------------------- */
+/* Mirror Tools */
+
+static short mirror_gpf_cframe (bGPDframe *gpf, Scene *scene)
+{
+ int diff;
+
+ if (gpf->flag & GP_FRAME_SELECT) {
+ diff= CFRA - gpf->framenum;
+ gpf->framenum= CFRA;
+ }
+
+ return 0;
+}
+
+static short mirror_gpf_yaxis (bGPDframe *gpf, Scene *scene)
+{
+ int diff;
+
+ if (gpf->flag & GP_FRAME_SELECT) {
+ diff= -gpf->framenum;
+ gpf->framenum= diff;
+ }
+
+ return 0;
+}
+
+static short mirror_gpf_xaxis (bGPDframe *gpf, Scene *scene)
+{
+ int diff;
+
+ if (gpf->flag & GP_FRAME_SELECT) {
+ diff= -gpf->framenum;
+ gpf->framenum= diff;
+ }
+
+ return 0;
+}
+
+static short mirror_gpf_marker (bGPDframe *gpf, Scene *scene)
+{
+ static TimeMarker *marker;
+ static short initialised = 0;
+ int diff;
+
+ /* In order for this mirror function to work without
+ * any extra arguments being added, we use the case
+ * of bezt==NULL to denote that we should find the
+ * marker to mirror over. The static pointer is safe
+ * to use this way, as it will be set to null after
+ * each cycle in which this is called.
+ */
+
+ if (gpf) {
+ /* mirroring time */
+ if ((gpf->flag & GP_FRAME_SELECT) && (marker)) {
+ diff= (marker->frame - gpf->framenum);
+ gpf->framenum= (marker->frame + diff);
+ }
+ }
+ else {
+ /* initialisation time */
+ if (initialised) {
+ /* reset everything for safety */
+ marker = NULL;
+ initialised = 0;
+ }
+ else {
+ /* try to find a marker */
+ for (marker= scene->markers.first; marker; marker=marker->next) {
+ if (marker->flag & SELECT) {
+ initialised = 1;
+ break;
+ }
+ }
+
+ if (initialised == 0)
+ marker = NULL;
+ }
+ }
+
+ return 0;
+}
+
+
+/* mirror selected gp-frames on... */
+void mirror_gplayer_frames (bGPDlayer *gpl, Scene *scene, short mode)
+{
+ switch (mode) {
+ case 1: /* mirror over current frame */
+ gplayer_frames_looper(gpl, scene, mirror_gpf_cframe);
+ break;
+ case 2: /* mirror over frame 0 */
+ gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis);
+ break;
+ case 3: /* mirror over value 0 */
+ gplayer_frames_looper(gpl, scene, mirror_gpf_xaxis);
+ break;
+ case 4: /* mirror over marker */
+ mirror_gpf_marker(NULL, NULL);
+ gplayer_frames_looper(gpl, scene, mirror_gpf_marker);
+ mirror_gpf_marker(NULL, NULL);
+ break;
+ default: /* just in case */
+ gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis);
+ break;
+ }
+}
+
+/* ***************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
new file mode 100644
index 00000000000..a745e5f4084
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -0,0 +1,1715 @@
+/**
+ * $Id: gpencil.c 19758 2009-04-16 13:10:08Z aligorith $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "DNA_listBase.h"
+#include "DNA_armature_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_vec_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_armature.h"
+#include "BKE_blender.h"
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_global.h"
+#include "BKE_gpencil.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_view2d.h"
+
+#include "ED_armature.h"
+#include "ED_gpencil.h"
+#include "ED_sequencer.h"
+#include "ED_view3d.h"
+
+#include "PIL_time.h" /* sleep */
+
+#include "gpencil_intern.h"
+
+/* XXX */
+static void BIF_undo_push() {}
+static void error() {}
+static int pupmenu() {return 0;}
+static void add_object_draw() {}
+static int get_activedevice() {return 0;}
+#define L_MOUSE 0
+#define R_MOUSE 0
+
+/* ************************************************** */
+/* XXX - OLD DEPRECEATED CODE... */
+
+/* ----------- GP-Datablock API ------------- */
+
+/* get the appropriate bGPdata from the active/given context */
+// XXX region or region data?
+bGPdata *gpencil_data_getactive (ScrArea *sa)
+{
+ ScrArea *curarea= NULL; // XXX
+
+ /* error checking */
+ if ((sa == NULL) && (curarea == NULL))
+ return NULL;
+ if (sa == NULL)
+ sa= curarea;
+
+ /* handle depending on spacetype */
+ switch (sa->spacetype) {
+ case SPACE_VIEW3D:
+ {
+ View3D *v3d= sa->spacedata.first;
+ return v3d->gpd;
+ }
+ break;
+ case SPACE_NODE:
+ {
+ SpaceNode *snode= sa->spacedata.first;
+ return snode->gpd;
+ }
+ break;
+ case SPACE_SEQ:
+ {
+ SpaceSeq *sseq= sa->spacedata.first;
+
+ /* only applicable for image modes */
+ if (sseq->mainb != SEQ_DRAW_SEQUENCE)
+ return sseq->gpd;
+ }
+ break;
+ case SPACE_IMAGE:
+ {
+ SpaceImage *sima= sa->spacedata.first;
+ return sima->gpd;
+ }
+ break;
+ }
+
+ /* nothing found */
+ return NULL;
+}
+
+/* set bGPdata for the active/given context, and return success/fail */
+short gpencil_data_setactive (ScrArea *sa, bGPdata *gpd)
+{
+ ScrArea *curarea= NULL; // XXX
+
+ /* error checking */
+ if ((sa == NULL) && (curarea == NULL))
+ return 0;
+ if (gpd == NULL)
+ return 0;
+ if (sa == NULL)
+ sa= curarea;
+
+ /* handle depending on spacetype */
+ // TODO: someday we should have multi-user data, so no need to loose old data
+ switch (sa->spacetype) {
+ case SPACE_VIEW3D:
+ {
+ View3D *v3d= sa->spacedata.first;
+
+ /* free the existing block */
+ if (v3d->gpd)
+ free_gpencil_data(v3d->gpd);
+ v3d->gpd= gpd;
+
+ return 1;
+ }
+ break;
+ case SPACE_NODE:
+ {
+ SpaceNode *snode= sa->spacedata.first;
+
+ /* free the existing block */
+ if (snode->gpd)
+ free_gpencil_data(snode->gpd);
+ snode->gpd= gpd;
+
+ /* set special settings */
+ gpd->flag |= GP_DATA_VIEWALIGN;
+
+ return 1;
+ }
+ break;
+ case SPACE_SEQ:
+ {
+ SpaceSeq *sseq= sa->spacedata.first;
+
+ /* only applicable if right mode */
+ if (sseq->mainb != SEQ_DRAW_SEQUENCE) {
+ /* free the existing block */
+ if (sseq->gpd)
+ free_gpencil_data(sseq->gpd);
+ sseq->gpd= gpd;
+
+ return 1;
+ }
+ }
+ break;
+ case SPACE_IMAGE:
+ {
+ SpaceImage *sima= sa->spacedata.first;
+
+ if (sima->gpd)
+ free_gpencil_data(sima->gpd);
+ sima->gpd= gpd;
+
+ return 1;
+ }
+ break;
+ }
+
+ /* failed to add */
+ return 0;
+}
+
+/* return the ScrArea that has the given GP-datablock
+ * - assumes that only searching in current screen
+ * - is based on GP-datablocks only being able to
+ * exist for one area at a time (i.e. not multiuser)
+ */
+ScrArea *gpencil_data_findowner (bGPdata *gpd)
+{
+ bScreen *curscreen= NULL; // XXX
+ ScrArea *sa;
+
+ /* error checking */
+ if (gpd == NULL)
+ return NULL;
+
+ /* loop over all scrareas for current screen, and check if that area has this gpd */
+ for (sa= curscreen->areabase.first; sa; sa= sa->next) {
+ /* use get-active func to see if match */
+ if (gpencil_data_getactive(sa) == gpd)
+ return sa;
+ }
+
+ /* not found */
+ return NULL;
+}
+
+/* ************************************************** */
+/* GREASE-PENCIL EDITING - Tools */
+
+/* --------- Data Deletion ---------- */
+
+/* delete the last stroke on the active layer */
+void gpencil_delete_laststroke (bGPdata *gpd, int cfra)
+{
+ bGPDlayer *gpl= gpencil_layer_getactive(gpd);
+ bGPDframe *gpf= gpencil_layer_getframe(gpl, cfra, 0);
+
+ gpencil_frame_delete_laststroke(gpl, gpf);
+}
+
+/* delete the active frame */
+void gpencil_delete_actframe (bGPdata *gpd, int cfra)
+{
+ bGPDlayer *gpl= gpencil_layer_getactive(gpd);
+ bGPDframe *gpf= gpencil_layer_getframe(gpl, cfra, 0);
+
+ gpencil_layer_delframe(gpl, gpf);
+}
+
+
+
+/* delete various grase-pencil elements
+ * mode: 1 - last stroke
+ * 2 - active frame
+ * 3 - active layer
+ */
+void gpencil_delete_operation (int cfra, short mode)
+{
+ bGPdata *gpd;
+
+ /* get datablock to work on */
+ gpd= gpencil_data_getactive(NULL);
+ if (gpd == NULL) return;
+
+ switch (mode) {
+ case 1: /* last stroke */
+ gpencil_delete_laststroke(gpd, cfra);
+ break;
+ case 2: /* active frame */
+ gpencil_delete_actframe(gpd, cfra);
+ break;
+ case 3: /* active layer */
+ gpencil_layer_delactive(gpd);
+ break;
+ }
+
+ /* redraw and undo-push */
+ BIF_undo_push("GPencil Delete");
+}
+
+/* display a menu for deleting different grease-pencil elements */
+void gpencil_delete_menu (void)
+{
+ bGPdata *gpd= gpencil_data_getactive(NULL);
+ int cfra= 0; // XXX
+ short mode;
+
+ /* only show menu if it will be relevant */
+ if (gpd == NULL) return;
+
+ mode= pupmenu("Grease Pencil Erase...%t|Last Stroke%x1|Active Frame%x2|Active Layer%x3");
+ if (mode <= 0) return;
+
+ gpencil_delete_operation(cfra, mode);
+}
+
+/* --------- Data Conversion ---------- */
+
+/* convert the coordinates from the given stroke point into 3d-coordinates */
+static void gp_strokepoint_convertcoords (bGPDstroke *gps, bGPDspoint *pt, float p3d[3])
+{
+ ARegion *ar= NULL; // XXX
+
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ /* directly use 3d-coordinates */
+ VecCopyf(p3d, &pt->x);
+ }
+ else {
+ short mval[2];
+ int mx, my;
+ float *fp= give_cursor(NULL, NULL); // XXX should be scene, v3d
+ float dvec[3];
+
+ /* get screen coordinate */
+ if (gps->flag & GP_STROKE_2DSPACE) {
+ // XXX
+ // View2D *v2d= spacelink_get_view2d(curarea->spacedata.first);
+ // UI_view2d_view_to_region(v2d, pt->x, pt->y, &mx, &my);
+ }
+ else {
+ // XXX
+ // mx= (short)(pt->x / 1000 * curarea->winx);
+ // my= (short)(pt->y / 1000 * curarea->winy);
+ }
+
+ /* convert screen coordinate to 3d coordinates
+ * - method taken from editview.c - mouse_cursor()
+ */
+ project_short_noclip(ar, fp, mval);
+ window_to_3d_delta(ar, dvec, mval[0]-mx, mval[1]-my);
+ VecSubf(p3d, fp, dvec);
+ }
+}
+
+/* --- */
+
+/* convert stroke to 3d path */
+static void gp_stroke_to_path (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu)
+{
+ bGPDspoint *pt;
+ Nurb *nu;
+ BPoint *bp;
+ int i;
+
+ /* create new 'nurb' within the curve */
+ nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)");
+
+ nu->pntsu= gps->totpoints;
+ nu->pntsv= 1;
+ nu->orderu= gps->totpoints;
+ nu->flagu= 2; /* endpoint */
+ nu->resolu= 32;
+
+ nu->bp= (BPoint *)MEM_callocN(sizeof(BPoint)*gps->totpoints, "bpoints");
+
+ /* add points */
+ for (i=0, pt=gps->points, bp=nu->bp; i < gps->totpoints; i++, pt++, bp++) {
+ float p3d[3];
+
+ /* get coordinates to add at */
+ gp_strokepoint_convertcoords(gps, pt, p3d);
+ VecCopyf(bp->vec, p3d);
+
+ /* set settings */
+ bp->f1= SELECT;
+ bp->radius = bp->weight = pt->pressure * gpl->thickness;
+ }
+
+ /* add nurb to curve */
+ BLI_addtail(&cu->nurb, nu);
+}
+
+/* convert stroke to 3d bezier */
+static void gp_stroke_to_bezier (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu)
+{
+ bGPDspoint *pt;
+ Nurb *nu;
+ BezTriple *bezt;
+ int i;
+
+ /* create new 'nurb' within the curve */
+ nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)");
+
+ nu->pntsu= gps->totpoints;
+ nu->resolu= 12;
+ nu->resolv= 12;
+ nu->type= CU_BEZIER;
+ nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints*sizeof(BezTriple), "bezts");
+
+ /* add points */
+ for (i=0, pt=gps->points, bezt=nu->bezt; i < gps->totpoints; i++, pt++, bezt++) {
+ float p3d[3];
+
+ /* get coordinates to add at */
+ gp_strokepoint_convertcoords(gps, pt, p3d);
+
+ /* TODO: maybe in future the handles shouldn't be in same place */
+ VecCopyf(bezt->vec[0], p3d);
+ VecCopyf(bezt->vec[1], p3d);
+ VecCopyf(bezt->vec[2], p3d);
+
+ /* set settings */
+ bezt->h1= bezt->h2= HD_FREE;
+ bezt->f1= bezt->f2= bezt->f3= SELECT;
+ bezt->radius = bezt->weight = pt->pressure * gpl->thickness * 0.1f;
+ }
+
+ /* must calculate handles or else we crash */
+ calchandlesNurb(nu);
+
+ /* add nurb to curve */
+ BLI_addtail(&cu->nurb, nu);
+}
+
+/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */
+static void gp_layer_to_curve (bGPdata *gpd, bGPDlayer *gpl, Scene *scene, short mode)
+{
+ bGPDframe *gpf= gpencil_layer_getframe(gpl, scene->r.cfra, 0);
+ bGPDstroke *gps;
+ Object *ob;
+ Curve *cu;
+
+ /* error checking */
+ if (ELEM3(NULL, gpd, gpl, gpf))
+ return;
+
+ /* only convert if there are any strokes on this layer's frame to convert */
+ if (gpf->strokes.first == NULL)
+ return;
+
+ /* init the curve object (remove rotation and get curve data from it)
+ * - must clear transforms set on object, as those skew our results
+ */
+ add_object_draw(OB_CURVE);
+ ob= OBACT;
+ ob->loc[0]= ob->loc[1]= ob->loc[2]= 0;
+ ob->rot[0]= ob->rot[1]= ob->rot[2]= 0;
+ cu= ob->data;
+ cu->flag |= CU_3D;
+
+ /* rename object and curve to layer name */
+ rename_id((ID *)ob, gpl->info);
+ rename_id((ID *)cu, gpl->info);
+
+ /* add points to curve */
+ for (gps= gpf->strokes.first; gps; gps= gps->next) {
+ switch (mode) {
+ case 1:
+ gp_stroke_to_path(gpl, gps, cu);
+ break;
+ case 2:
+ gp_stroke_to_bezier(gpl, gps, cu);
+ break;
+ }
+ }
+}
+
+/* --- */
+
+/* convert a stroke to a bone chain */
+static void gp_stroke_to_bonechain (bGPDlayer *gpl, bGPDstroke *gps, bArmature *arm, ListBase *bones)
+{
+ EditBone *ebo, *prev=NULL;
+ bGPDspoint *pt, *ptn;
+ int i;
+
+ /* add each segment separately */
+ for (i=0, pt=gps->points, ptn=gps->points+1; i < (gps->totpoints-1); prev=ebo, i++, pt++, ptn++) {
+ float p3da[3], p3db[3];
+
+ /* get coordinates to add at */
+ gp_strokepoint_convertcoords(gps, pt, p3da);
+ gp_strokepoint_convertcoords(gps, ptn, p3db);
+
+ /* allocate new bone */
+ ebo= MEM_callocN(sizeof(EditBone), "eBone");
+
+ VecCopyf(ebo->head, p3da);
+ VecCopyf(ebo->tail, p3db);
+
+ /* add new bone - note: sync with editarmature.c::add_editbone() */
+ {
+ BLI_strncpy(ebo->name, "Stroke", 32);
+ unique_editbone_name(bones, ebo->name, NULL);
+
+ BLI_addtail(bones, ebo);
+
+ if (i > 0)
+ {
+ ebo->flag |= BONE_CONNECTED;
+ }
+ ebo->weight= 1.0f;
+ ebo->dist= 0.25f;
+ ebo->xwidth= 0.1f;
+ ebo->zwidth= 0.1f;
+ ebo->ease1= 1.0f;
+ ebo->ease2= 1.0f;
+ ebo->rad_head= pt->pressure * gpl->thickness * 0.1f;
+ ebo->rad_tail= ptn->pressure * gpl->thickness * 0.1f;
+ ebo->segments= 1;
+ ebo->layer= arm->layer;
+ }
+
+ /* set parenting */
+ ebo->parent= prev;
+ }
+}
+
+/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */
+static void gp_layer_to_armature (bGPdata *gpd, bGPDlayer *gpl, Scene *scene, View3D *v3d, short mode)
+{
+ bGPDframe *gpf= gpencil_layer_getframe(gpl, scene->r.cfra, 0);
+ bGPDstroke *gps;
+ Object *ob;
+ bArmature *arm;
+
+ /* error checking */
+ if (ELEM3(NULL, gpd, gpl, gpf))
+ return;
+
+ /* only convert if there are any strokes on this layer's frame to convert */
+ if (gpf->strokes.first == NULL)
+ return;
+
+ /* init the armature object (remove rotation and assign armature data to it)
+ * - must clear transforms set on object, as those skew our results
+ */
+ add_object_draw(OB_ARMATURE);
+ ob= OBACT;
+ ob->loc[0]= ob->loc[1]= ob->loc[2]= 0;
+ ob->rot[0]= ob->rot[1]= ob->rot[2]= 0;
+ arm= ob->data;
+
+ /* rename object and armature to layer name */
+ rename_id((ID *)ob, gpl->info);
+ rename_id((ID *)arm, gpl->info);
+
+ /* this is editmode armature */
+ arm->edbo= MEM_callocN(sizeof(ListBase), "arm edbo");
+
+ /* convert segments to bones, strokes to bone chains */
+ for (gps= gpf->strokes.first; gps; gps= gps->next) {
+ gp_stroke_to_bonechain(gpl, gps, arm, arm->edbo);
+ }
+
+ /* adjust roll of bones
+ * - set object as EditMode object, but need to clear afterwards!
+ * - use 'align to world z-up' option
+ */
+ {
+ /* set our data as if we're in editmode to fool auto_align_armature() */
+ scene->obedit= ob;
+
+ /* WARNING: need to make sure this magic number doesn't change */
+ auto_align_armature(scene, v3d, 2);
+
+ scene->obedit= NULL;
+ }
+
+ /* flush editbones to armature */
+ ED_armature_from_edit(scene, ob);
+ ED_armature_edit_free(ob);
+}
+
+/* --- */
+
+/* convert grease-pencil strokes to another representation
+ * mode: 1 - Active layer to path
+ * 2 - Active layer to bezier
+ * 3 - Active layer to armature
+ */
+void gpencil_convert_operation (short mode)
+{
+ Scene *scene= NULL; // XXX
+ View3D *v3d= NULL; // XXX
+ RegionView3D *rv3d= NULL; // XXX
+ bGPdata *gpd;
+ float *fp= give_cursor(scene, v3d);
+
+ /* get datablock to work on */
+ gpd= gpencil_data_getactive(NULL);
+ if (gpd == NULL) return;
+
+ /* initialise 3d-cursor correction globals */
+ initgrabz(rv3d, fp[0], fp[1], fp[2]);
+
+ /* handle selection modes */
+ switch (mode) {
+ case 1: /* active layer only (to path) */
+ case 2: /* active layer only (to bezier) */
+ {
+ bGPDlayer *gpl= gpencil_layer_getactive(gpd);
+ gp_layer_to_curve(gpd, gpl, scene, mode);
+ }
+ break;
+ case 3: /* active layer only (to armature) */
+ {
+ bGPDlayer *gpl= gpencil_layer_getactive(gpd);
+ gp_layer_to_armature(gpd, gpl, scene, v3d, mode);
+ }
+ break;
+ }
+
+ /* redraw and undo-push */
+ BIF_undo_push("GPencil Convert");
+}
+
+/* display a menu for converting grease-pencil strokes */
+void gpencil_convert_menu (void)
+{
+ bGPdata *gpd= gpencil_data_getactive(NULL);
+ short mode;
+
+ /* only show menu if it will be relevant */
+ if (gpd == NULL) return;
+
+ mode= pupmenu("Grease Pencil Convert %t|Active Layer To Path%x1|Active Layer to Bezier%x2|Active Layer to Armature%x3");
+ if (mode <= 0) return;
+
+ gpencil_convert_operation(mode);
+}
+
+/* ************************************************** */
+/* GREASE-PENCIL EDITING MODE - Painting */
+
+/* ---------- 'Globals' and Defines ----------------- */
+
+/* maximum sizes of gp-session buffer */
+#define GP_STROKE_BUFFER_MAX 5000
+
+/* Macros for accessing sensitivity thresholds... */
+ /* minimum number of pixels mouse should move before new point created */
+#define MIN_MANHATTEN_PX (U.gp_manhattendist)
+ /* minimum length of new segment before new point can be added */
+#define MIN_EUCLIDEAN_PX (U.gp_euclideandist)
+
+/* macro to test if only converting endpoints - only for use when converting! */
+#define GP_BUFFER2STROKE_ENDPOINTS ((gpd->flag & GP_DATA_EDITPAINT) && (ctrl))
+
+/* ------ */
+
+/* Temporary 'Stroke' Operation data */
+typedef struct tGPsdata {
+ Scene *scene; /* current scene from context */
+ ScrArea *sa; /* area where painting originated */
+ ARegion *ar; /* region where painting originated */
+ View2D *v2d; /* needed for GP_STROKE_2DSPACE */
+
+ ImBuf *ibuf; /* needed for GP_STROKE_2DIMAGE */
+ struct IBufViewSettings {
+ int offsx, offsy; /* offsets */
+ int sizex, sizey; /* dimensions to use as scale-factor */
+ } im2d_settings; /* needed for GP_STROKE_2DIMAGE */
+
+ bGPdata *gpd; /* gp-datablock layer comes from */
+ bGPDlayer *gpl; /* layer we're working on */
+ bGPDframe *gpf; /* frame we're working on */
+
+ short status; /* current status of painting */
+ short paintmode; /* mode for painting */
+
+ short mval[2]; /* current mouse-position */
+ short mvalo[2]; /* previous recorded mouse-position */
+
+ float pressure; /* current stylus pressure */
+ float opressure; /* previous stylus pressure */
+
+ short radius; /* radius of influence for eraser */
+} tGPsdata;
+
+/* values for tGPsdata->status */
+enum {
+ GP_STATUS_NORMAL = 0, /* running normally */
+ GP_STATUS_ERROR, /* something wasn't correctly set up */
+ GP_STATUS_DONE /* painting done */
+};
+
+/* values for tGPsdata->paintmode */
+enum {
+ GP_PAINTMODE_DRAW = 0,
+ GP_PAINTMODE_ERASER
+};
+
+/* Return flags for adding points to stroke buffer */
+enum {
+ GP_STROKEADD_INVALID = -2, /* error occurred - insufficient info to do so */
+ GP_STROKEADD_OVERFLOW = -1, /* error occurred - cannot fit any more points */
+ GP_STROKEADD_NORMAL, /* point was successfully added */
+ GP_STROKEADD_FULL /* cannot add any more points to buffer */
+};
+
+/* ---------- Stroke Editing ------------ */
+
+/* clear the session buffers (call this before AND after a paint operation) */
+static void gp_session_validatebuffer (tGPsdata *p)
+{
+ bGPdata *gpd= p->gpd;
+
+ /* clear memory of buffer (or allocate it if starting a new session) */
+ if (gpd->sbuffer)
+ memset(gpd->sbuffer, 0, sizeof(tGPspoint)*GP_STROKE_BUFFER_MAX);
+ else
+ gpd->sbuffer= MEM_callocN(sizeof(tGPspoint)*GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer");
+
+ /* reset indices */
+ gpd->sbuffer_size = 0;
+
+ /* reset flags */
+ gpd->sbuffer_sflag= 0;
+}
+
+/* check if the current mouse position is suitable for adding a new point */
+static short gp_stroke_filtermval (tGPsdata *p, short mval[2], short pmval[2])
+{
+ short dx= abs(mval[0] - pmval[0]);
+ short dy= abs(mval[1] - pmval[1]);
+
+ /* check if mouse moved at least certain distance on both axes (best case) */
+ if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX))
+ return 1;
+
+ /* check if the distance since the last point is significant enough */
+ // future optimisation: sqrt here may be too slow?
+ else if (sqrt(dx*dx + dy*dy) > MIN_EUCLIDEAN_PX)
+ return 1;
+
+ /* mouse 'didn't move' */
+ else
+ return 0;
+}
+
+/* convert screen-coordinates to buffer-coordinates */
+static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[])
+{
+ bGPdata *gpd= p->gpd;
+
+ /* in 3d-space - pt->x/y/z are 3 side-by-side floats */
+ if (gpd->sbuffer_sflag & GP_STROKE_3DSPACE) {
+ const short mx=mval[0], my=mval[1];
+ float *fp= give_cursor(p->scene, NULL); // XXX NULL could be v3d
+ float dvec[3];
+
+ /* Current method just converts each point in screen-coordinates to
+ * 3D-coordinates using the 3D-cursor as reference. In general, this
+ * works OK, but it could of course be improved.
+ *
+ * TODO:
+ * - investigate using nearest point(s) on a previous stroke as
+ * reference point instead or as offset, for easier stroke matching
+ * - investigate projection onto geometry (ala retopo)
+ */
+
+ /* method taken from editview.c - mouse_cursor() */
+ project_short_noclip(p->ar, fp, mval);
+ window_to_3d_delta(p->ar, dvec, mval[0]-mx, mval[1]-my);
+ VecSubf(out, fp, dvec);
+ }
+
+ /* 2d - on 'canvas' (assume that p->v2d is set) */
+ else if ((gpd->sbuffer_sflag & GP_STROKE_2DSPACE) && (p->v2d)) {
+ float x, y;
+
+ UI_view2d_region_to_view(p->v2d, mval[0], mval[1], &x, &y);
+
+ out[0]= x;
+ out[1]= y;
+ }
+
+ /* 2d - on image 'canvas' (assume that p->v2d is set) */
+ else if (gpd->sbuffer_sflag & GP_STROKE_2DIMAGE) {
+ int sizex, sizey, offsx, offsy;
+
+ /* get stored settings
+ * - assume that these have been set already (there are checks that set sane 'defaults' just in case)
+ */
+ sizex= p->im2d_settings.sizex;
+ sizey= p->im2d_settings.sizey;
+ offsx= p->im2d_settings.offsx;
+ offsy= p->im2d_settings.offsy;
+
+ /* calculate new points */
+ out[0]= (float)(mval[0] - offsx) / (float)sizex;
+ out[1]= (float)(mval[1] - offsy) / (float)sizey;
+ }
+
+ /* 2d - relative to screen (viewport area) */
+ else {
+ out[0] = (float)(mval[0]) / (float)(p->sa->winx) * 1000;
+ out[1] = (float)(mval[1]) / (float)(p->sa->winy) * 1000;
+ }
+}
+
+/* add current stroke-point to buffer (returns whether point was successfully added) */
+static short gp_stroke_addpoint (tGPsdata *p, short mval[2], float pressure)
+{
+ bGPdata *gpd= p->gpd;
+ tGPspoint *pt;
+
+ /* check if still room in buffer */
+ if (gpd->sbuffer_size >= GP_STROKE_BUFFER_MAX)
+ return GP_STROKEADD_OVERFLOW;
+
+ /* get pointer to destination point */
+ pt= ((tGPspoint *)(gpd->sbuffer) + gpd->sbuffer_size);
+
+ /* store settings */
+ pt->x= mval[0];
+ pt->y= mval[1];
+ pt->pressure= pressure;
+
+ /* increment counters */
+ gpd->sbuffer_size++;
+
+ /* check if another operation can still occur */
+ if (gpd->sbuffer_size == GP_STROKE_BUFFER_MAX)
+ return GP_STROKEADD_FULL;
+ else
+ return GP_STROKEADD_NORMAL;
+}
+
+/* smooth a stroke (in buffer) before storing it */
+static void gp_stroke_smooth (tGPsdata *p)
+{
+ bGPdata *gpd= p->gpd;
+ int i=0, cmx=gpd->sbuffer_size;
+ int ctrl= 0; // XXX
+
+ /* only smooth if smoothing is enabled, and we're not doing a straight line */
+ if (!(U.gp_settings & GP_PAINT_DOSMOOTH) || GP_BUFFER2STROKE_ENDPOINTS)
+ return;
+
+ /* don't try if less than 2 points in buffer */
+ if ((cmx <= 2) || (gpd->sbuffer == NULL))
+ return;
+
+ /* apply weighting-average (note doing this along path sequentially does introduce slight error) */
+ for (i=0; i < gpd->sbuffer_size; i++) {
+ tGPspoint *pc= (((tGPspoint *)gpd->sbuffer) + i);
+ tGPspoint *pb= (i-1 > 0)?(pc-1):(pc);
+ tGPspoint *pa= (i-2 > 0)?(pc-2):(pb);
+ tGPspoint *pd= (i+1 < cmx)?(pc+1):(pc);
+ tGPspoint *pe= (i+2 < cmx)?(pc+2):(pd);
+
+ pc->x= (short)(0.1*pa->x + 0.2*pb->x + 0.4*pc->x + 0.2*pd->x + 0.1*pe->x);
+ pc->y= (short)(0.1*pa->y + 0.2*pb->y + 0.4*pc->y + 0.2*pd->y + 0.1*pe->y);
+ }
+}
+
+/* simplify a stroke (in buffer) before storing it
+ * - applies a reverse Chaikin filter
+ * - code adapted from etch-a-ton branch (editarmature_sketch.c)
+ */
+static void gp_stroke_simplify (tGPsdata *p)
+{
+ bGPdata *gpd= p->gpd;
+ tGPspoint *old_points= (tGPspoint *)gpd->sbuffer;
+ short num_points= gpd->sbuffer_size;
+ short flag= gpd->sbuffer_sflag;
+ short i, j;
+ int ctrl= 0; // XXX
+
+ /* only simplify if simlification is enabled, and we're not doing a straight line */
+ if (!(U.gp_settings & GP_PAINT_DOSIMPLIFY) || GP_BUFFER2STROKE_ENDPOINTS)
+ return;
+
+ /* don't simplify if less than 4 points in buffer */
+ if ((num_points <= 2) || (old_points == NULL))
+ return;
+
+ /* clear buffer (but don't free mem yet) so that we can write to it
+ * - firstly set sbuffer to NULL, so a new one is allocated
+ * - secondly, reset flag after, as it gets cleared auto
+ */
+ gpd->sbuffer= NULL;
+ gp_session_validatebuffer(p);
+ gpd->sbuffer_sflag = flag;
+
+/* macro used in loop to get position of new point
+ * - used due to the mixture of datatypes in use here
+ */
+#define GP_SIMPLIFY_AVPOINT(offs, sfac) \
+ { \
+ co[0] += (float)(old_points[offs].x * sfac); \
+ co[1] += (float)(old_points[offs].y * sfac); \
+ pressure += old_points[offs].pressure * sfac; \
+ }
+
+ for (i = 0, j = 0; i < num_points; i++)
+ {
+ if (i - j == 3)
+ {
+ float co[2], pressure;
+ short mco[2];
+
+ /* initialise values */
+ co[0]= 0;
+ co[1]= 0;
+ pressure = 0;
+
+ /* using macro, calculate new point */
+ GP_SIMPLIFY_AVPOINT(j, -0.25f);
+ GP_SIMPLIFY_AVPOINT(j+1, 0.75f);
+ GP_SIMPLIFY_AVPOINT(j+2, 0.75f);
+ GP_SIMPLIFY_AVPOINT(j+3, -0.25f);
+
+ /* set values for adding */
+ mco[0]= (short)co[0];
+ mco[1]= (short)co[1];
+
+ /* ignore return values on this... assume to be ok for now */
+ gp_stroke_addpoint(p, mco, pressure);
+
+ j += 2;
+ }
+ }
+
+ /* free old buffer */
+ MEM_freeN(old_points);
+}
+
+
+/* make a new stroke from the buffer data */
+static void gp_stroke_newfrombuffer (tGPsdata *p)
+{
+ bGPdata *gpd= p->gpd;
+ bGPDstroke *gps;
+ bGPDspoint *pt;
+ tGPspoint *ptc;
+ int i, totelem;
+ int ctrl= 0; // XXX
+
+ /* get total number of points to allocate space for:
+ * - in 'Draw Mode', holding the Ctrl-Modifier will only take endpoints
+ * - otherwise, do whole stroke
+ */
+ if (GP_BUFFER2STROKE_ENDPOINTS)
+ totelem = (gpd->sbuffer_size >= 2) ? 2: gpd->sbuffer_size;
+ else
+ totelem = gpd->sbuffer_size;
+
+ /* exit with error if no valid points from this stroke */
+ if (totelem == 0) {
+ if (G.f & G_DEBUG)
+ printf("Error: No valid points in stroke buffer to convert (tot=%d) \n", gpd->sbuffer_size);
+ return;
+ }
+
+ /* allocate memory for a new stroke */
+ gps= MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
+
+ /* allocate enough memory for a continuous array for storage points */
+ pt= gps->points= MEM_callocN(sizeof(bGPDspoint)*totelem, "gp_stroke_points");
+
+ /* copy appropriate settings for stroke */
+ gps->totpoints= totelem;
+ gps->thickness= p->gpl->thickness;
+ gps->flag= gpd->sbuffer_sflag;
+
+ /* copy points from the buffer to the stroke */
+ if (GP_BUFFER2STROKE_ENDPOINTS) {
+ /* 'Draw Mode' + Ctrl-Modifier - only endpoints */
+ {
+ /* first point */
+ ptc= gpd->sbuffer;
+
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x);
+
+ /* copy pressure */
+ pt->pressure= ptc->pressure;
+
+ pt++;
+ }
+
+ if (totelem == 2) {
+ /* last point if applicable */
+ ptc= ((tGPspoint *)gpd->sbuffer) + (gpd->sbuffer_size - 1);
+
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x);
+
+ /* copy pressure */
+ pt->pressure= ptc->pressure;
+ }
+ }
+ else {
+ /* convert all points (normal behaviour) */
+ for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++) {
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x);
+
+ /* copy pressure */
+ pt->pressure= ptc->pressure;
+
+ pt++;
+ }
+ }
+
+ /* add stroke to frame */
+ BLI_addtail(&p->gpf->strokes, gps);
+}
+
+/* --- 'Eraser' for 'Paint' Tool ------ */
+
+/* eraser tool - remove segment from stroke/split stroke (after lasso inside) */
+static short gp_stroke_eraser_splitdel (bGPDframe *gpf, bGPDstroke *gps, int i)
+{
+ bGPDspoint *pt_tmp= gps->points;
+ bGPDstroke *gsn = NULL;
+
+ /* if stroke only had two points, get rid of stroke */
+ if (gps->totpoints == 2) {
+ /* free stroke points, then stroke */
+ MEM_freeN(pt_tmp);
+ BLI_freelinkN(&gpf->strokes, gps);
+
+ /* nothing left in stroke, so stop */
+ return 1;
+ }
+
+ /* if last segment, just remove segment from the stroke */
+ else if (i == gps->totpoints - 2) {
+ /* allocate new points array, and assign most of the old stroke there */
+ gps->totpoints--;
+ gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points");
+ memcpy(gps->points, pt_tmp, sizeof(bGPDspoint)*gps->totpoints);
+
+ /* free temp buffer */
+ MEM_freeN(pt_tmp);
+
+ /* nothing left in stroke, so stop */
+ return 1;
+ }
+
+ /* if first segment, just remove segment from the stroke */
+ else if (i == 0) {
+ /* allocate new points array, and assign most of the old stroke there */
+ gps->totpoints--;
+ gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points");
+ memcpy(gps->points, pt_tmp + 1, sizeof(bGPDspoint)*gps->totpoints);
+
+ /* free temp buffer */
+ MEM_freeN(pt_tmp);
+
+ /* no break here, as there might still be stuff to remove in this stroke */
+ return 0;
+ }
+
+ /* segment occurs in 'middle' of stroke, so split */
+ else {
+ /* duplicate stroke, and assign 'later' data to that stroke */
+ gsn= MEM_dupallocN(gps);
+ gsn->prev= gsn->next= NULL;
+ BLI_insertlinkafter(&gpf->strokes, gps, gsn);
+
+ gsn->totpoints= gps->totpoints - i;
+ gsn->points= MEM_callocN(sizeof(bGPDspoint)*gsn->totpoints, "gp_stroke_points");
+ memcpy(gsn->points, pt_tmp + i, sizeof(bGPDspoint)*gsn->totpoints);
+
+ /* adjust existing stroke */
+ gps->totpoints= i;
+ gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points");
+ memcpy(gps->points, pt_tmp, sizeof(bGPDspoint)*i);
+
+ /* free temp buffer */
+ MEM_freeN(pt_tmp);
+
+ /* nothing left in stroke, so stop */
+ return 1;
+ }
+}
+
+/* eraser tool - check if part of stroke occurs within last segment drawn by eraser */
+static short gp_stroke_eraser_strokeinside (short mval[], short mvalo[], short rad, short x0, short y0, short x1, short y1)
+{
+ /* simple within-radius check for now */
+ if (edge_inside_circle(mval[0], mval[1], rad, x0, y0, x1, y1))
+ return 1;
+
+ /* not inside */
+ return 0;
+}
+
+/* eraser tool - evaluation per stroke */
+static void gp_stroke_eraser_dostroke (tGPsdata *p, short mval[], short mvalo[], short rad, rcti *rect, bGPDframe *gpf, bGPDstroke *gps)
+{
+ bGPDspoint *pt1, *pt2;
+ int x0=0, y0=0, x1=0, y1=0;
+ short xyval[2];
+ int i;
+
+ if (gps->totpoints == 0) {
+ /* just free stroke */
+ if (gps->points)
+ MEM_freeN(gps->points);
+ BLI_freelinkN(&gpf->strokes, gps);
+ }
+ else if (gps->totpoints == 1) {
+ /* get coordinates */
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ project_short(p->ar, &gps->points->x, xyval);
+ x0= xyval[0];
+ y0= xyval[1];
+ }
+ else if (gps->flag & GP_STROKE_2DSPACE) {
+ UI_view2d_view_to_region(p->v2d, gps->points->x, gps->points->y, &x0, &y0);
+ }
+ else if (gps->flag & GP_STROKE_2DIMAGE) {
+ int offsx, offsy, sizex, sizey;
+
+ /* get stored settings */
+ sizex= p->im2d_settings.sizex;
+ sizey= p->im2d_settings.sizey;
+ offsx= p->im2d_settings.offsx;
+ offsy= p->im2d_settings.offsy;
+
+ /* calculate new points */
+ x0= (short)((gps->points->x * sizex) + offsx);
+ y0= (short)((gps->points->y * sizey) + offsy);
+ }
+ else {
+ x0= (short)(gps->points->x / 1000 * p->sa->winx);
+ y0= (short)(gps->points->y / 1000 * p->sa->winy);
+ }
+
+ /* do boundbox check first */
+ if (BLI_in_rcti(rect, x0, y0)) {
+ /* only check if point is inside */
+ if ( ((x0-mval[0])*(x0-mval[0]) + (y0-mval[1])*(y0-mval[1])) <= rad*rad ) {
+ /* free stroke */
+ MEM_freeN(gps->points);
+ BLI_freelinkN(&gpf->strokes, gps);
+ }
+ }
+ }
+ else {
+ /* loop over the points in the stroke, checking for intersections
+ * - an intersection will require the stroke to be split
+ */
+ for (i=0; (i+1) < gps->totpoints; i++) {
+ /* get points to work with */
+ pt1= gps->points + i;
+ pt2= gps->points + i + 1;
+
+ /* get coordinates */
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ project_short(p->ar, &pt1->x, xyval);
+ x0= xyval[0];
+ y0= xyval[1];
+
+ project_short(p->ar, &pt2->x, xyval);
+ x1= xyval[0];
+ y1= xyval[1];
+ }
+ else if (gps->flag & GP_STROKE_2DSPACE) {
+ UI_view2d_view_to_region(p->v2d, pt1->x, pt1->y, &x0, &y0);
+
+ UI_view2d_view_to_region(p->v2d, pt2->x, pt2->y, &x1, &y1);
+ }
+ else if (gps->flag & GP_STROKE_2DIMAGE) {
+ int offsx, offsy, sizex, sizey;
+
+ /* get stored settings */
+ sizex= p->im2d_settings.sizex;
+ sizey= p->im2d_settings.sizey;
+ offsx= p->im2d_settings.offsx;
+ offsy= p->im2d_settings.offsy;
+
+ /* calculate new points */
+ x0= (short)((pt1->x * sizex) + offsx);
+ y0= (short)((pt1->y * sizey) + offsy);
+
+ x1= (short)((pt2->x * sizex) + offsx);
+ y1= (short)((pt2->y * sizey) + offsy);
+ }
+ else {
+ x0= (short)(pt1->x / 1000 * p->sa->winx);
+ y0= (short)(pt1->y / 1000 * p->sa->winy);
+ x1= (short)(pt2->x / 1000 * p->sa->winx);
+ y1= (short)(pt2->y / 1000 * p->sa->winy);
+ }
+
+ /* check that point segment of the boundbox of the eraser stroke */
+ if (BLI_in_rcti(rect, x0, y0) || BLI_in_rcti(rect, x1, y1)) {
+ /* check if point segment of stroke had anything to do with
+ * eraser region (either within stroke painted, or on its lines)
+ * - this assumes that linewidth is irrelevant
+ */
+ if (gp_stroke_eraser_strokeinside(mval, mvalo, rad, x0, y0, x1, y1)) {
+ /* if function returns true, break this loop (as no more point to check) */
+ if (gp_stroke_eraser_splitdel(gpf, gps, i))
+ break;
+ }
+ }
+ }
+ }
+}
+
+/* erase strokes which fall under the eraser strokes */
+static void gp_stroke_doeraser (tGPsdata *p)
+{
+ bGPDframe *gpf= p->gpf;
+ bGPDstroke *gps, *gpn;
+ rcti rect;
+
+ /* rect is rectangle of eraser */
+ rect.xmin= p->mval[0] - p->radius;
+ rect.ymin= p->mval[1] - p->radius;
+ rect.xmax= p->mval[0] + p->radius;
+ rect.ymax= p->mval[1] + p->radius;
+
+ /* loop over strokes, checking segments for intersections */
+ for (gps= gpf->strokes.first; gps; gps= gpn) {
+ gpn= gps->next;
+ gp_stroke_eraser_dostroke(p, p->mval, p->mvalo, p->radius, &rect, gpf, gps);
+ }
+}
+
+/* ---------- 'Paint' Tool ------------ */
+
+/* init new painting session */
+static void gp_session_initpaint (bContext *C, tGPsdata *p)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ ARegion *ar= CTX_wm_region(C);
+
+ /* clear previous data (note: is on stack) */
+ memset(p, 0, sizeof(tGPsdata));
+
+ /* make sure the active view (at the starting time) is a 3d-view */
+ if (curarea == NULL) {
+ p->status= GP_STATUS_ERROR;
+ if (G.f & G_DEBUG)
+ printf("Error: No active view for painting \n");
+ return;
+ }
+
+ /* pass on current scene */
+ p->scene= CTX_data_scene(C);
+
+ switch (curarea->spacetype) {
+ /* supported views first */
+ case SPACE_VIEW3D:
+ {
+ View3D *v3d= curarea->spacedata.first;
+
+ /* set current area */
+ p->sa= curarea;
+ p->ar= ar;
+
+ /* check that gpencil data is allowed to be drawn */
+ if ((v3d->flag2 & V3D_DISPGP)==0) {
+ p->status= GP_STATUS_ERROR;
+ if (G.f & G_DEBUG)
+ printf("Error: In active view, Grease Pencil not shown \n");
+ return;
+ }
+ }
+ break;
+ case SPACE_NODE:
+ {
+ SpaceNode *snode= curarea->spacedata.first;
+
+ /* set current area */
+ p->sa= curarea;
+ p->ar= ar;
+ p->v2d= &ar->v2d;
+
+ /* check that gpencil data is allowed to be drawn */
+ if ((snode->flag & SNODE_DISPGP)==0) {
+ p->status= GP_STATUS_ERROR;
+ if (G.f & G_DEBUG)
+ printf("Error: In active view, Grease Pencil not shown \n");
+ return;
+ }
+ }
+ break;
+ case SPACE_SEQ:
+ {
+ SpaceSeq *sseq= curarea->spacedata.first;
+
+ /* set current area */
+ p->sa= curarea;
+ p->ar= ar;
+ p->v2d= &ar->v2d;
+
+ /* check that gpencil data is allowed to be drawn */
+ if (sseq->mainb == SEQ_DRAW_SEQUENCE) {
+ p->status= GP_STATUS_ERROR;
+ if (G.f & G_DEBUG)
+ printf("Error: In active view (sequencer), active mode doesn't support Grease Pencil \n");
+ return;
+ }
+ if ((sseq->flag & SEQ_DRAW_GPENCIL)==0) {
+ p->status= GP_STATUS_ERROR;
+ if (G.f & G_DEBUG)
+ printf("Error: In active view, Grease Pencil not shown \n");
+ return;
+ }
+ }
+ break;
+ case SPACE_IMAGE:
+ {
+ SpaceImage *sima= curarea->spacedata.first;
+
+ /* set the current area */
+ p->sa= curarea;
+ p->ar= ar;
+ p->v2d= &ar->v2d;
+ p->ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser);
+
+ /* check that gpencil data is allowed to be drawn */
+ if ((sima->flag & SI_DISPGP)==0) {
+ p->status= GP_STATUS_ERROR;
+ if (G.f & G_DEBUG)
+ printf("Error: In active view, Grease Pencil not shown \n");
+ return;
+ }
+ }
+ break;
+ /* unsupported views */
+ default:
+ {
+ p->status= GP_STATUS_ERROR;
+ if (G.f & G_DEBUG)
+ printf("Error: Active view not appropriate for Grease Pencil drawing \n");
+ return;
+ }
+ break;
+ }
+
+ /* get gp-data */
+ p->gpd= gpencil_data_getactive(p->sa);
+ if (p->gpd == NULL) {
+ short ok;
+
+ p->gpd= gpencil_data_addnew("GPencil");
+ ok= gpencil_data_setactive(p->sa, p->gpd);
+
+ /* most of the time, the following check isn't needed */
+ if (ok == 0) {
+ /* free gpencil data as it can't be used */
+ free_gpencil_data(p->gpd);
+ p->gpd= NULL;
+ p->status= GP_STATUS_ERROR;
+ if (G.f & G_DEBUG)
+ printf("Error: Could not assign newly created Grease Pencil data to active area \n");
+ return;
+ }
+ }
+
+ /* set edit flags */
+ G.f |= G_GREASEPENCIL;
+
+ /* clear out buffer (stored in gp-data) in case something contaminated it */
+ gp_session_validatebuffer(p);
+
+ /* set 'default' im2d_settings just in case something that uses this doesn't set it */
+ p->im2d_settings.sizex= 1;
+ p->im2d_settings.sizey= 1;
+}
+
+/* cleanup after a painting session */
+static void gp_session_cleanup (tGPsdata *p)
+{
+ bGPdata *gpd= p->gpd;
+
+ /* error checking */
+ if (gpd == NULL)
+ return;
+
+ /* free stroke buffer */
+ if (gpd->sbuffer) {
+ MEM_freeN(gpd->sbuffer);
+ gpd->sbuffer= NULL;
+ }
+
+ /* clear flags */
+ gpd->sbuffer_size= 0;
+ gpd->sbuffer_sflag= 0;
+}
+
+/* init new stroke */
+static void gp_paint_initstroke (tGPsdata *p, short paintmode)
+{
+ /* get active layer (or add a new one if non-existent) */
+ p->gpl= gpencil_layer_getactive(p->gpd);
+ if (p->gpl == NULL)
+ p->gpl= gpencil_layer_addnew(p->gpd);
+ if (p->gpl->flag & GP_LAYER_LOCKED) {
+ p->status= GP_STATUS_ERROR;
+ if (G.f & G_DEBUG)
+ printf("Error: Cannot paint on locked layer \n");
+ return;
+ }
+
+ /* get active frame (add a new one if not matching frame) */
+ p->gpf= gpencil_layer_getframe(p->gpl, p->scene->r.cfra, 1);
+ if (p->gpf == NULL) {
+ p->status= GP_STATUS_ERROR;
+ if (G.f & G_DEBUG)
+ printf("Error: No frame created (gpencil_paint_init) \n");
+ return;
+ }
+ else
+ p->gpf->flag |= GP_FRAME_PAINT;
+
+ /* set 'eraser' for this stroke if using eraser */
+ p->paintmode= paintmode;
+ if (p->paintmode == GP_PAINTMODE_ERASER)
+ p->gpd->sbuffer_sflag |= GP_STROKE_ERASER;
+
+ /* check if points will need to be made in view-aligned space */
+ if (p->gpd->flag & GP_DATA_VIEWALIGN) {
+ switch (p->sa->spacetype) {
+ case SPACE_VIEW3D:
+ {
+ View3D *v3d= (View3D *)p->sa->spacedata.first;
+ RegionView3D *rv3d= NULL; // XXX
+ float *fp= give_cursor(p->scene, v3d);
+
+ initgrabz(rv3d, fp[0], fp[1], fp[2]);
+
+ p->gpd->sbuffer_sflag |= GP_STROKE_3DSPACE;
+ }
+ break;
+ case SPACE_NODE:
+ {
+ p->gpd->sbuffer_sflag |= GP_STROKE_2DSPACE;
+ }
+ break;
+ case SPACE_SEQ:
+ {
+ SpaceSeq *sseq= (SpaceSeq *)p->sa->spacedata.first;
+ int rectx, recty;
+ float zoom, zoomx, zoomy;
+
+ /* set draw 2d-stroke flag */
+ p->gpd->sbuffer_sflag |= GP_STROKE_2DIMAGE;
+
+ /* calculate zoom factor */
+ zoom= (float)(SEQ_ZOOM_FAC(sseq->zoom));
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
+ zoomx = zoom * ((float)p->scene->r.xasp / (float)p->scene->r.yasp);
+ zoomy = zoom;
+ }
+ else
+ zoomx = zoomy = zoom;
+
+ /* calculate rect size to use to calculate the size of the drawing area
+ * - We use the size of the output image not the size of the ibuf being shown
+ * as it is too messy getting the ibuf (and could be too slow). This should be
+ * a reasonable for most cases anyway.
+ */
+ rectx= (p->scene->r.size * p->scene->r.xsch) / 100;
+ recty= (p->scene->r.size * p->scene->r.ysch) / 100;
+
+ /* set offset and scale values for opertations to use */
+ p->im2d_settings.sizex= (int)(zoomx * rectx);
+ p->im2d_settings.sizey= (int)(zoomy * recty);
+ p->im2d_settings.offsx= (int)((p->sa->winx-p->im2d_settings.sizex)/2 + sseq->xof);
+ p->im2d_settings.offsy= (int)((p->sa->winy-p->im2d_settings.sizey)/2 + sseq->yof);
+ }
+ break;
+ case SPACE_IMAGE:
+ {
+ /* check if any ibuf available */
+ if (p->ibuf)
+ p->gpd->sbuffer_sflag |= GP_STROKE_2DSPACE;
+ }
+ break;
+ }
+ }
+}
+
+/* finish off a stroke (clears buffer, but doesn't finish the paint operation) */
+static void gp_paint_strokeend (tGPsdata *p)
+{
+ /* check if doing eraser or not */
+ if ((p->gpd->sbuffer_sflag & GP_STROKE_ERASER) == 0) {
+ /* smooth stroke before transferring? */
+ gp_stroke_smooth(p);
+
+ /* simplify stroke before transferring? */
+ gp_stroke_simplify(p);
+
+ /* transfer stroke to frame */
+ gp_stroke_newfrombuffer(p);
+ }
+
+ /* clean up buffer now */
+ gp_session_validatebuffer(p);
+}
+
+/* finish off stroke painting operation */
+static void gp_paint_cleanup (tGPsdata *p)
+{
+ /* finish off a stroke */
+ gp_paint_strokeend(p);
+
+ /* "unlock" frame */
+ p->gpf->flag &= ~GP_FRAME_PAINT;
+
+ /* add undo-push so stroke can be undone */
+ /* FIXME: currently disabled, as it's impossible to get this working nice
+ * as gpenci data is on currently screen-level (which isn't saved to undo files)
+ */
+ //BIF_undo_push("GPencil Stroke");
+
+ /* force redraw after drawing action */
+ // XXX force_draw_plus(SPACE_ACTION, 0);
+}
+
+/* -------- */
+
+/* main call to paint a new stroke */
+// XXX will become modal(), gets event, includes all info!
+short gpencil_paint (bContext *C, short paintmode)
+{
+ tGPsdata p;
+ short ok = GP_STROKEADD_NORMAL;
+
+ /* init paint-data */
+ gp_session_initpaint(C, &p);
+ if (p.status == GP_STATUS_ERROR) {
+ gp_session_cleanup(&p);
+ return 0;
+ }
+ gp_paint_initstroke(&p, paintmode);
+ if (p.status == GP_STATUS_ERROR) {
+ gp_session_cleanup(&p);
+ return 0;
+ }
+
+ /* set cursor to indicate drawing */
+ // XXX (cursor callbacks in regiontype) setcursor_space(p.sa->spacetype, CURSOR_VPAINT);
+
+ /* init drawing-device settings */
+ // XXX getmouseco_areawin(p.mval);
+ // XXX p.pressure = get_pressure();
+
+ p.mvalo[0]= p.mval[0];
+ p.mvalo[1]= p.mval[1];
+ p.opressure= p.pressure;
+
+ /* radius for eraser circle is defined in userprefs now */
+ // TODO: make this more easily tweaked...
+ p.radius= U.gp_eraser;
+
+ /* start drawing eraser-circle (if applicable) */
+ //if (paintmode == GP_PAINTMODE_ERASER)
+ // XXX draw_sel_circle(p.mval, NULL, p.radius, p.radius, 0); // draws frontbuffer, but sets backbuf again
+
+ /* only allow painting of single 'dots' if:
+ * - pressure is not excessive (as it can be on some windows tablets)
+ * - draw-mode for active datablock is turned on
+ * - not erasing
+ */
+ if (paintmode != GP_PAINTMODE_ERASER) {
+ if (!(p.pressure >= 0.99f) || (p.gpd->flag & GP_DATA_EDITPAINT)) {
+ gp_stroke_addpoint(&p, p.mval, p.pressure);
+ }
+ }
+
+ /* XXX paint loop */
+ if(0) {
+ /* get current user input */
+ // XXX getmouseco_areawin(p.mval);
+ // XXX p.pressure = get_pressure();
+
+ /* only add current point to buffer if mouse moved (otherwise wait until it does) */
+ if (paintmode == GP_PAINTMODE_ERASER) {
+ /* do 'live' erasing now */
+ gp_stroke_doeraser(&p);
+
+ // XXX draw_sel_circle(p.mval, p.mvalo, p.radius, p.radius, 0);
+ // XXX force_draw(0);
+
+ p.mvalo[0]= p.mval[0];
+ p.mvalo[1]= p.mval[1];
+ p.opressure= p.pressure;
+ }
+ else if (gp_stroke_filtermval(&p, p.mval, p.mvalo)) {
+ /* try to add point */
+ ok= gp_stroke_addpoint(&p, p.mval, p.pressure);
+
+ /* handle errors while adding point */
+ if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) {
+ /* finish off old stroke */
+ gp_paint_strokeend(&p);
+
+ /* start a new stroke, starting from previous point */
+ gp_stroke_addpoint(&p, p.mvalo, p.opressure);
+ ok= gp_stroke_addpoint(&p, p.mval, p.pressure);
+ }
+ else if (ok == GP_STROKEADD_INVALID) {
+ /* the painting operation cannot continue... */
+ error("Cannot paint stroke");
+ p.status = GP_STATUS_ERROR;
+
+ if (G.f & G_DEBUG)
+ printf("Error: Grease-Pencil Paint - Add Point Invalid \n");
+ // XXX break;
+ }
+ // XXX force_draw(0);
+
+ p.mvalo[0]= p.mval[0];
+ p.mvalo[1]= p.mval[1];
+ p.opressure= p.pressure;
+ }
+
+ /* do mouse checking at the end, so don't check twice, and potentially
+ * miss a short tap
+ */
+ }
+
+ /* clear edit flags */
+ G.f &= ~G_GREASEPENCIL;
+
+ /* restore cursor to indicate end of drawing */
+ // XXX (cursor callbacks in regiontype) setcursor_space(p.sa->spacetype, CURSOR_STD);
+
+ /* check size of buffer before cleanup, to determine if anything happened here */
+ if (paintmode == GP_PAINTMODE_ERASER) {
+ ok= 1; /* assume that we did something... */
+ // XXX draw_sel_circle(NULL, p.mvalo, 0, p.radius, 0);
+ }
+ else
+ ok= p.gpd->sbuffer_size;
+
+ /* cleanup */
+ gp_paint_cleanup(&p);
+ gp_session_cleanup(&p);
+
+ /* done! return if a stroke was successfully added */
+ return ok;
+}
+
+
+/* All event (loops) handling checking if stroke drawing should be initiated
+ * should call this function.
+ */
+short gpencil_do_paint (bContext *C)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ bGPdata *gpd = gpencil_data_getactive(sa);
+ short retval= 0;
+ int alt= 0, shift= 0, mbut= 0; // XXX
+
+ /* check if possible to do painting */
+ if (gpd == NULL)
+ return 0;
+
+ /* currently, we will only 'paint' if:
+ * 1. draw-mode on gpd is set (for accessibility reasons)
+ * a) single dots are only available by this method if a single click is made
+ * b) a straight line is drawn if ctrl-modifier is held (check is done when stroke is converted!)
+ * 2. if shift-modifier is held + lmb -> 'quick paint'
+ *
+ * OR
+ *
+ * draw eraser stroke if:
+ * 1. using the eraser on a tablet
+ * 2. draw-mode on gpd is set (for accessiblity reasons)
+ * (eraser is mapped to right-mouse)
+ * 3. Alt + 'select' mouse-button
+ * i.e. if LMB = select: Alt-LMB
+ * if RMB = select: Alt-RMB
+ */
+ if (get_activedevice() == 2) {
+ /* eraser on a tablet - always try to erase strokes */
+ retval = gpencil_paint(C, GP_PAINTMODE_ERASER);
+ }
+ else if (gpd->flag & GP_DATA_EDITPAINT) {
+ /* try to paint/erase */
+ if (mbut == L_MOUSE)
+ retval = gpencil_paint(C, GP_PAINTMODE_DRAW);
+ else if (mbut == R_MOUSE)
+ retval = gpencil_paint(C, GP_PAINTMODE_ERASER);
+ }
+ else if (!(gpd->flag & GP_DATA_LMBPLOCK)) {
+ /* try to paint/erase as not locked */
+ if (shift && (mbut == L_MOUSE)) {
+ retval = gpencil_paint(C, GP_PAINTMODE_DRAW);
+ }
+ else if (alt) {
+ if ((U.flag & USER_LMOUSESELECT) && (mbut == L_MOUSE))
+ retval = gpencil_paint(C, GP_PAINTMODE_ERASER);
+ else if (!(U.flag & USER_LMOUSESELECT) && (mbut == R_MOUSE))
+ retval = gpencil_paint(C, GP_PAINTMODE_ERASER);
+ }
+ }
+
+ /* return result of trying to paint */
+ return retval;
+}
+
+/* ************************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
new file mode 100644
index 00000000000..721d8544225
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -0,0 +1,81 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_GPENCIL_INTERN_H
+#define ED_GPENCIL_INTERN_H
+
+/* internal exports only */
+/******************************************************* */
+/* FILTERED ACTION DATA - TYPES */
+
+/* XXX - TODO: replace this with the modern bAnimListElem... */
+/* This struct defines a structure used for quick access */
+typedef struct bActListElem {
+ struct bActListElem *next, *prev;
+
+ void *data; /* source data this elem represents */
+ int type; /* one of the ACTTYPE_* values */
+ int flag; /* copy of elem's flags for quick access */
+ int index; /* copy of adrcode where applicable */
+
+ void *key_data; /* motion data - ipo or ipo-curve */
+ short datatype; /* type of motion data to expect */
+
+ struct bActionGroup *grp; /* action group that owns the channel */
+
+ void *owner; /* will either be an action channel or fake ipo-channel (for keys) */
+ short ownertype; /* type of owner */
+} bActListElem;
+
+/******************************************************* */
+/* FILTER ACTION DATA - METHODS/TYPES */
+
+/* filtering flags - under what circumstances should a channel be added */
+typedef enum ACTFILTER_FLAGS {
+ ACTFILTER_VISIBLE = (1<<0), /* should channels be visible */
+ ACTFILTER_SEL = (1<<1), /* should channels be selected */
+ ACTFILTER_FOREDIT = (1<<2), /* does editable status matter */
+ ACTFILTER_CHANNELS = (1<<3), /* do we only care that it is a channel */
+ ACTFILTER_IPOKEYS = (1<<4), /* only channels referencing ipo's */
+ ACTFILTER_ONLYICU = (1<<5), /* only reference ipo-curves */
+ ACTFILTER_FORDRAWING = (1<<6), /* make list for interface drawing */
+ ACTFILTER_ACTGROUPED = (1<<7) /* belongs to the active group */
+} ACTFILTER_FLAGS;
+
+/* Action Editor - Main Data types */
+typedef enum ACTCONT_TYPES {
+ ACTCONT_NONE = 0,
+ ACTCONT_ACTION,
+ ACTCONT_SHAPEKEY,
+ ACTCONT_GPENCIL
+} ACTCONT_TYPES;
+
+
+
+
+#endif /* ED_GPENCIL_INTERN_H */
+
diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h
new file mode 100644
index 00000000000..014201648c9
--- /dev/null
+++ b/source/blender/editors/include/BIF_gl.h
@@ -0,0 +1,77 @@
+/**
+ * $Id: BIF_gl.h 10455 2007-04-04 13:18:41Z campbellbarton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * os dependent include locations of gl.h
+ */
+
+#ifndef BIF_GL_H
+#define BIF_GL_H
+
+ /* Although not really a great idea to copy these defines
+ * from Windows' winnt.h, this lets us use GL without including
+ * windows.h everywhere (or BLI_winstuff.h) which is a good thing.
+ */
+#ifdef WIN32
+#ifndef APIENTRY
+#define APIENTRY __stdcall
+#endif
+
+#ifndef CALLBACK
+#define CALLBACK __stdcall
+#endif
+
+#ifndef WINGDIAPI
+#define WINGDIAPI __declspec(dllimport)
+#endif
+#endif
+
+#include "GL/glew.h"
+
+ /*
+ * these should be phased out. cpack should be replaced in
+ * code with calls to glColor3ub, lrectwrite probably should
+ * change to a function. - zr
+ */
+/*
+ *
+ * This define converts a numerical value to the equivalent 24-bit
+ * color, 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);}
+
+/* glStippleDefines, defined in glutil.c */
+extern GLubyte stipple_halftone[128];
+extern GLubyte stipple_quarttone[128];
+
+#endif /* #ifdef BIF_GL_H */
+
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
new file mode 100644
index 00000000000..63bd451132d
--- /dev/null
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -0,0 +1,216 @@
+/**
+ * $Id: BIF_glutil.h
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation 2002-2008
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BIF_GLUTIL_H
+#define BIF_GLUTIL_H
+
+struct rcti;
+struct rctf;
+
+void fdrawbezier(float vec[4][3]);
+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 sdrawtri(short x1, short y1, short x2, short y2);
+void sdrawtrifill(short x1, short y1, short x2, short y2);
+void sdrawbox(short x1, short y1, short x2, short y2);
+
+void sdrawXORline(int x0, int y0, int x1, int y1);
+void sdrawXORline4(int nr, int x0, int y0, int x1, int y1);
+
+void fdrawXORellipse(float xofs, float yofs, float hw, float hh);
+void fdrawXORcirc(float xofs, float yofs, float rad);
+
+
+ /**
+ * 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, int row_w, int format, int type, 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 byte or float format, and the
+ * modelview and projection matrices are assumed to define a
+ * 1-to-1 mapping to screen space.
+ */
+
+ /* only for float rects, converts to 32 bits and draws */
+void glaDrawPixelsSafe_to32(float fx, float fy, int img_w, int img_h, int row_w, float *rectf);
+
+
+void glaDrawPixelsTex (float x, float y, int img_w, int img_h, int format, 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);
+
+ /** Adjust the transformation mapping of a 2d area */
+void gla2DGetMap(gla2DDrawInfo *di, struct rctf *rect);
+void gla2DSetMap(gla2DDrawInfo *di, struct rctf *rect);
+
+
+/* use this for platform hacks. glPointSize is solved here */
+void bglBegin(int mode);
+void bglEnd(void);
+void bglVertex3fv(float *vec);
+void bglVertex3f(float x, float y, float z);
+void bglVertex2fv(float *vec);
+/* intel gfx cards frontbuffer problem */
+void bglFlush(void);
+int is_a_really_crappy_intel_card(void);
+void set_inverted_drawing(int enable);
+void setlinestyle(int nr);
+
+
+/* own working polygon offset */
+void bglPolygonOffset(float viewdist, float dist);
+
+/* For caching opengl matrices (gluProject/gluUnProject) */
+typedef struct bglMats {
+ double modelview[16];
+ double projection[16];
+ int viewport[4];
+} bglMats;
+void bgl_get_mats(bglMats *mats);
+
+#endif /* BIF_GLUTIL_H */
+
diff --git a/source/blender/editors/include/BIF_retopo.h b/source/blender/editors/include/BIF_retopo.h
new file mode 100644
index 00000000000..cc2fda56b07
--- /dev/null
+++ b/source/blender/editors/include/BIF_retopo.h
@@ -0,0 +1,110 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 by Nicholas Bishop
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BIF_RETOPO_H
+#define BIF_RETOPO_H
+
+#include "DNA_vec_types.h"
+
+/* For bglMats */
+#include "BIF_glutil.h"
+
+struct EditVert;
+struct Mesh;
+struct View3D;
+
+typedef struct RetopoViewData {
+ bglMats mats;
+
+ char queue_matrix_update;
+} RetopoViewData;
+
+typedef struct RetopoPaintPoint {
+ struct RetopoPaintPoint *next, *prev;
+ vec2s loc;
+ short index;
+ float co[3];
+ struct EditVert *eve;
+} RetopoPaintPoint;
+
+typedef struct RetopoPaintLine {
+ struct RetopoPaintLine *next, *prev;
+ ListBase points;
+ ListBase hitlist; /* RetopoPaintHit */
+ RetopoPaintPoint *cyclic;
+} RetopoPaintLine;
+
+typedef struct RetopoPaintSel {
+ struct RetopoPaintSel *next, *prev;
+ RetopoPaintLine *line;
+ char first;
+} RetopoPaintSel;
+
+typedef struct RetopoPaintData {
+ char in_drag;
+ short sloc[2];
+
+ ListBase lines;
+ ListBase intersections; /* RetopoPaintPoint */
+
+ short seldist;
+ RetopoPaintSel nearest;
+
+ struct View3D *paint_v3d;
+} RetopoPaintData;
+
+RetopoPaintData *get_retopo_paint_data(void);
+
+char retopo_mesh_check(void);
+char retopo_curve_check(void);
+
+void retopo_end_okee(void);
+
+void retopo_free_paint_data(RetopoPaintData *rpd);
+void retopo_free_paint(void);
+
+char retopo_mesh_paint_check(void);
+void retopo_paint_view_update(struct View3D *v3d);
+void retopo_force_update(void);
+void retopo_paint_toggle(void*,void*);
+char retopo_paint(const unsigned short event);
+void retopo_draw_paint_lines(void);
+RetopoPaintData *retopo_paint_data_copy(RetopoPaintData *rpd);
+
+void retopo_toggle(void*,void*);
+void retopo_do_vert(struct View3D *v3d, float *v);
+void retopo_do_all(void);
+void retopo_do_all_cb(void *, void *);
+void retopo_queue_updates(struct View3D *v3d);
+
+void retopo_matrix_update(struct View3D *v3d);
+
+void retopo_free_view_data(struct View3D *v3d);
+
+#endif
diff --git a/source/blender/editors/include/BIF_transform.h b/source/blender/editors/include/BIF_transform.h
new file mode 100644
index 00000000000..d16ac563eb3
--- /dev/null
+++ b/source/blender/editors/include/BIF_transform.h
@@ -0,0 +1,165 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BIF_TRANSFORM_H
+#define BIF_TRANSFORM_H
+
+/* ******************* Registration Function ********************** */
+
+struct wmWindowManager;
+struct ListBase;
+struct wmEvent;
+struct bContext;
+struct Object;
+struct uiMenuItem;
+
+void transform_keymap_for_space(struct wmWindowManager *wm, struct ListBase *keymap, int spaceid);
+void transform_operatortypes(void);
+
+/* ******************** Macros & Prototypes *********************** */
+
+/* MODE AND NUMINPUT FLAGS */
+enum {
+ TFM_INIT = -1,
+ TFM_DUMMY,
+ TFM_TRANSLATION,
+ TFM_ROTATION,
+ TFM_RESIZE,
+ TFM_TOSPHERE,
+ TFM_SHEAR,
+ TFM_WARP,
+ TFM_SHRINKFATTEN,
+ TFM_TILT,
+ TFM_TRACKBALL,
+ TFM_PUSHPULL,
+ TFM_CREASE,
+ TFM_MIRROR,
+ TFM_BONESIZE,
+ TFM_BONE_ENVELOPE,
+ TFM_CURVE_SHRINKFATTEN,
+ TFM_BONE_ROLL,
+ TFM_TIME_TRANSLATE,
+ TFM_TIME_SLIDE,
+ TFM_TIME_SCALE,
+ TFM_TIME_EXTEND,
+ TFM_BAKE_TIME,
+ TFM_BEVEL,
+ TFM_BWEIGHT,
+ TFM_ALIGN
+} TfmMode;
+
+/* TRANSFORM CONTEXTS */
+#define CTX_NONE 0
+#define CTX_TEXTURE 1
+#define CTX_EDGE 2
+#define CTX_NO_PET 4
+#define CTX_TWEAK 8
+#define CTX_NO_MIRROR 16
+#define CTX_AUTOCONFIRM 32
+#define CTX_BMESH 64
+#define CTX_NDOF 128
+
+/* Standalone call to get the transformation center corresponding to the current situation
+ * returns 1 if successful, 0 otherwise (usually means there's no selection)
+ * (if 0 is returns, *vec is unmodified)
+ * */
+int calculateTransformCenter(struct bContext *C, struct wmEvent *event, int centerMode, float *vec);
+
+struct TransInfo;
+struct ScrArea;
+struct Base;
+struct Scene;
+struct Object;
+
+void BIF_setSingleAxisConstraint(float vec[3], char *text);
+void BIF_setDualAxisConstraint(float vec1[3], float vec2[3], char *text);
+void BIF_setLocalAxisConstraint(char axis, char *text);
+void BIF_setLocalLockConstraint(char axis, char *text);
+
+int BIF_snappingSupported(struct Object *obedit);
+
+struct TransformOrientation;
+struct bContext;
+
+void BIF_clearTransformOrientation(struct bContext *C);
+void BIF_removeTransformOrientation(struct bContext *C, struct TransformOrientation *ts);
+void BIF_manageTransformOrientation(struct bContext *C, int confirm, int set);
+int BIF_menuselectTransformOrientation(void);
+void BIF_selectTransformOrientation(struct bContext *C, struct TransformOrientation *ts);
+void BIF_selectTransformOrientationValue(struct bContext *C, int orientation);
+
+void BIF_menuTransformOrientation(struct bContext *C, struct uiMenuItem *head, void *arg);
+char * BIF_menustringTransformOrientation(const struct bContext *C, char *title); /* the returned value was allocated and needs to be freed after use */
+int BIF_countTransformOrientation(const struct bContext *C);
+
+void BIF_getPropCenter(float *center);
+
+void BIF_TransformSetUndo(char *str);
+
+void BIF_selectOrientation(void);
+
+/* view3d manipulators */
+void initManipulator(int mode);
+void ManipulatorTransform();
+
+//int BIF_do_manipulator(struct ScrArea *sa);
+//void BIF_draw_manipulator(struct ScrArea *sa);
+
+/* Snapping */
+
+
+typedef struct DepthPeel
+{
+ struct DepthPeel *next, *prev;
+
+ float depth;
+ float p[3];
+ float no[3];
+ struct Object *ob;
+ int flag;
+} DepthPeel;
+
+struct ListBase;
+
+typedef enum SnapMode
+{
+ SNAP_ALL = 0,
+ SNAP_NOT_SELECTED = 1,
+ SNAP_NOT_OBEDIT = 2
+} SnapMode;
+
+#define SNAP_MIN_DISTANCE 30
+
+int peelObjectsTransForm(struct TransInfo *t, struct ListBase *depth_peels, short mval[2]);
+int peelObjectsContext(struct bContext *C, struct ListBase *depth_peels, short mval[2]);
+int snapObjectsTransform(struct TransInfo *t, short mval[2], int *dist, float *loc, float *no, SnapMode mode);
+int snapObjectsContext(struct bContext *C, short mval[2], int *dist, float *loc, float *no, SnapMode mode);
+
+#endif
+
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
new file mode 100644
index 00000000000..0210e3d6a85
--- /dev/null
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -0,0 +1,352 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_ANIM_API_H
+#define ED_ANIM_API_H
+
+struct ID;
+struct Scene;
+struct ListBase;
+struct bContext;
+struct wmWindowManager;
+struct ScrArea;
+struct ARegion;
+struct View2D;
+struct gla2DDrawInfo;
+struct Object;
+struct bActionGroup;
+struct FCurve;
+struct IpoCurve; // xxx
+
+/* ************************************************ */
+/* ANIMATION CHANNEL FILTERING */
+/* anim_filter.c */
+
+/* --------------- Context --------------------- */
+
+/* This struct defines a structure used for animation-specific
+ * 'context' information
+ */
+typedef struct bAnimContext {
+ void *data; /* data to be filtered for use in animation editor */
+ short datatype; /* type of data eAnimCont_Types */
+
+ short mode; /* editor->mode */
+ short spacetype; /* sa->spacetype */
+ short regiontype; /* active region -> type (channels or main) */
+ struct ScrArea *sa; /* editor */
+ struct ARegion *ar; /* region within editor */
+
+ struct Scene *scene; /* active scene */
+ struct Object *obact; /* active object */
+} bAnimContext;
+
+/* Main Data container types */
+// XXX was ACTCONT_*
+typedef enum eAnimCont_Types {
+ ANIMCONT_NONE = 0, /* invalid or no data */
+ ANIMCONT_ACTION, /* action (bAction) */
+ ANIMCONT_SHAPEKEY, /* shapekey (Key) */
+ ANIMCONT_GPENCIL, /* grease pencil (screen) */
+ ANIMCONT_DOPESHEET, /* dopesheet (bDopesheet) */
+ ANIMCONT_FCURVES, /* animation F-Curves (bDopesheet) */ // XXX
+ ANIMCONT_DRIVERS, /* drivers (bDopesheet) */
+} eAnimCont_Types;
+
+/* --------------- Channels -------------------- */
+
+/* This struct defines a structure used for quick and uniform access for
+ * channels of animation data
+ */
+typedef struct bAnimListElem {
+ struct bAnimListElem *next, *prev;
+
+ void *data; /* source data this elem represents */
+ int type; /* one of the ANIMTYPE_* values */
+ int flag; /* copy of elem's flags for quick access */
+ int index; /* copy of adrcode where applicable */
+
+ void *key_data; /* motion data - ipo or ipo-curve */
+ short datatype; /* type of motion data to expect */
+
+ struct ID *id; /* ID block that channel is attached to (may be used */
+
+ void *owner; /* group or channel which acts as this channel's owner */
+ short ownertype; /* type of owner */
+} bAnimListElem;
+
+
+/* Some types for easier type-testing */
+// XXX was ACTTYPE_*
+typedef enum eAnim_ChannelType {
+ ANIMTYPE_NONE= 0,
+ ANIMTYPE_SPECIALDATA,
+
+ ANIMTYPE_SCENE,
+ ANIMTYPE_OBJECT,
+ ANIMTYPE_GROUP,
+ ANIMTYPE_FCURVE,
+
+ ANIMTYPE_FILLACTD,
+ ANIMTYPE_FILLDRIVERS,
+ ANIMTYPE_FILLMATD,
+
+ ANIMTYPE_DSMAT,
+ ANIMTYPE_DSLAM,
+ ANIMTYPE_DSCAM,
+ ANIMTYPE_DSCUR,
+ ANIMTYPE_DSSKEY,
+ ANIMTYPE_DSWOR,
+
+ ANIMTYPE_SHAPEKEY, // XXX probably can become depreceated???
+
+ ANIMTYPE_GPDATABLOCK,
+ ANIMTYPE_GPLAYER,
+} eAnim_ChannelType;
+
+/* types of keyframe data in bAnimListElem */
+typedef enum eAnim_KeyType {
+ ALE_NONE = 0, /* no keyframe data */
+ ALE_FCURVE, /* F-Curve */
+ ALE_GPFRAME, /* Grease Pencil Frames */
+
+ // XXX the following are for summaries... should these be kept?
+ ALE_SCE, /* Scene summary */
+ ALE_OB, /* Object summary */
+ ALE_ACT, /* Action summary */
+ ALE_GROUP, /* Action Group summary */
+} eAnim_KeyType;
+
+/* ----------------- Filtering -------------------- */
+
+/* filtering flags - under what circumstances should a channel be added */
+// XXX was ACTFILTER_*
+typedef enum eAnimFilter_Flags {
+ ANIMFILTER_VISIBLE = (1<<0), /* should channels be visible (in terms of hierarchy only) */
+ ANIMFILTER_SEL = (1<<1), /* should channels be selected */
+ ANIMFILTER_UNSEL = (1<<2), /* should channels be NOT selected */
+ ANIMFILTER_FOREDIT = (1<<3), /* does editable status matter */
+ ANIMFILTER_CURVESONLY = (1<<4), /* don't include summary-channels, etc. */
+ ANIMFILTER_CHANNELS = (1<<5), /* make list for interface drawing */
+ ANIMFILTER_ACTGROUPED = (1<<6), /* belongs to the active actiongroup */
+ ANIMFILTER_CURVEVISIBLE = (1<<7), /* F-Curve is visible for editing/viewing in Graph Editor */
+ ANIMFILTER_ACTIVE = (1<<8), /* channel should be 'active' */ // FIXME: this is only relevant for F-Curves for now
+} eAnimFilter_Flags;
+
+
+/* ---------- Flag Checking Macros ------------ */
+// xxx check on all of these flags again...
+
+/* Dopesheet only */
+ /* 'Scene' channels */
+#define SEL_SCEC(sce) ((sce->flag & SCE_DS_SELECTED))
+#define EXPANDED_SCEC(sce) ((sce->flag & SCE_DS_COLLAPSED)==0)
+ /* 'Sub-Scene' channels (flags stored in Data block) */
+#define FILTER_WOR_SCED(wo) ((wo->flag & WO_DS_EXPAND))
+ /* 'Object' channels */
+#define SEL_OBJC(base) ((base->flag & SELECT))
+#define EXPANDED_OBJC(ob) ((ob->nlaflag & OB_ADS_COLLAPSED)==0)
+ /* 'Sub-object' channels (flags stored in Object block) */
+#define FILTER_MAT_OBJC(ob) ((ob->nlaflag & OB_ADS_SHOWMATS))
+ /* 'Sub-object' channels (flags stored in Data block) */
+#define FILTER_SKE_OBJD(key) ((key->flag & KEYBLOCK_DS_EXPAND))
+#define FILTER_MAT_OBJD(ma) ((ma->flag & MA_DS_EXPAND))
+#define FILTER_LAM_OBJD(la) ((la->flag & LA_DS_EXPAND))
+#define FILTER_CAM_OBJD(ca) ((ca->flag & CAM_DS_EXPAND))
+#define FILTER_CUR_OBJD(cu) ((cu->flag & CU_DS_EXPAND))
+ /* 'Sub-object/Action' channels (flags stored in Action) */
+#define SEL_ACTC(actc) ((actc->flag & ACT_SELECTED))
+#define EXPANDED_ACTC(actc) ((actc->flag & ACT_COLLAPSED)==0)
+ /* 'Sub-AnimData' chanenls */
+#define EXPANDED_DRVD(adt) ((adt->flag & ADT_DRIVERS_COLLAPSED)==0)
+
+/* Actions (also used for Dopesheet) */
+ /* Action Channel Group */
+#define EDITABLE_AGRP(agrp) ((agrp->flag & AGRP_PROTECTED)==0)
+#define EXPANDED_AGRP(agrp) (agrp->flag & AGRP_EXPANDED)
+#define SEL_AGRP(agrp) ((agrp->flag & AGRP_SELECTED) || (agrp->flag & AGRP_ACTIVE))
+ /* F-Curve Channels */
+#define EDITABLE_FCU(fcu) ((fcu->flag & FCURVE_PROTECTED)==0)
+#define SEL_FCU(fcu) (fcu->flag & (FCURVE_ACTIVE|FCURVE_SELECTED))
+
+/* Grease Pencil only */
+ /* Grease Pencil datablock settings */
+#define EXPANDED_GPD(gpd) (gpd->flag & GP_DATA_EXPAND)
+ /* Grease Pencil Layer settings */
+#define EDITABLE_GPL(gpl) ((gpl->flag & GP_LAYER_LOCKED)==0)
+#define SEL_GPL(gpl) ((gpl->flag & GP_LAYER_ACTIVE) || (gpl->flag & GP_LAYER_SELECT))
+
+/* -------------- Channel Defines -------------- */
+
+/* channel heights */
+#define ACHANNEL_FIRST -16
+#define ACHANNEL_HEIGHT 16
+#define ACHANNEL_HEIGHT_HALF 8
+#define ACHANNEL_SKIP 2
+#define ACHANNEL_STEP (ACHANNEL_HEIGHT + ACHANNEL_SKIP)
+
+/* channel widths */
+#define ACHANNEL_NAMEWIDTH 200
+
+/* channel toggle-buttons */
+#define ACHANNEL_BUTTON_WIDTH 16
+
+/* ---------------- API -------------------- */
+
+/* Obtain list of filtered Animation channels to operate on.
+ * Returns the number of channels in the list
+ */
+int ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, int filter_mode, void *data, short datatype);
+
+/* Obtain current anim-data context from Blender Context info.
+ * Returns whether the operation was successful.
+ */
+short ANIM_animdata_get_context(const struct bContext *C, bAnimContext *ac);
+
+/* Obtain current anim-data context (from Animation Editor) given
+ * that Blender Context info has already been set.
+ * Returns whether the operation was successful.
+ */
+short ANIM_animdata_context_getdata(bAnimContext *ac);
+
+/* ************************************************ */
+/* ANIMATION CHANNELS LIST */
+/* anim_channels.c */
+
+/* ------------------------ API -------------------------- */
+
+/* Deselect all animation channels */
+void ANIM_deselect_anim_channels(void *data, short datatype, short test, short sel);
+
+/* Set the 'active' channel of type channel_type, in the given action */
+void ANIM_set_active_channel(void *data, short datatype, int filter, void *channel_data, short channel_type);
+
+/* --------------- Settings and/or Defines -------------- */
+
+/* flag-setting behaviour */
+enum {
+ ACHANNEL_SETFLAG_CLEAR = 0,
+ ACHANNEL_SETFLAG_ADD,
+ ACHANNEL_SETFLAG_TOGGLE
+} eAnimChannels_SetFlag;
+
+/* ************************************************ */
+/* DRAWING API */
+/* anim_draw.c */
+
+/* ---------- Current Frame Drawing ---------------- */
+
+/* flags for Current Frame Drawing */
+enum {
+ /* plain time indicator with no special indicators */
+ DRAWCFRA_PLAIN = 0,
+ /* draw box indicating current frame number */
+ DRAWCFRA_SHOW_NUMBOX = (1<<0),
+ /* time indication in seconds or frames */
+ DRAWCFRA_UNIT_SECONDS = (1<<1),
+ /* show time-offset line */
+ DRAWCFRA_SHOW_TIMEOFS = (1<<2),
+} eAnimEditDraw_CurrentFrame;
+
+/* main call to draw current-frame indicator in an Animation Editor */
+void ANIM_draw_cfra(const struct bContext *C, struct View2D *v2d, short flag);
+
+/* ------------- Preview Range Drawing -------------- */
+
+/* main call to draw preview range curtains */
+void ANIM_draw_previewrange(const struct bContext *C, struct View2D *v2d);
+
+/* ************************************************* */
+/* ASSORTED TOOLS */
+
+/* ------------ Animation F-Curves <-> Icons/Names Mapping ------------ */
+/* anim_ipo_utils.c */
+
+int geticon_anim_blocktype(short blocktype);
+
+void getname_anim_fcurve(char *name, struct ID *id, struct FCurve *fcu);
+
+
+void ipo_rainbow(int cur, int tot, float *out);
+
+
+/* ------------- NLA-Mapping ----------------------- */
+/* anim_draw.c */
+
+/* Obtain the Object providing NLA-scaling for the given channel if applicable */
+struct Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale);
+
+/* Set/clear temporary mapping of coordinates from 'local-action' time to 'global-nla-scaled' time */
+void ANIM_nla_mapping_draw(struct gla2DDrawInfo *di, struct Object *ob, short restore);
+
+/* Apply/Unapply NLA mapping to all keyframes in the nominated IPO block */
+void ANIM_nla_mapping_apply_fcurve(struct Object *ob, struct FCurve *fcu, short restore, short only_keys);
+
+/* ------------- xxx macros ----------------------- */
+
+#define BEZSELECTED(bezt) ((bezt->f2 & SELECT) || (bezt->f1 & SELECT) || (bezt->f3 & SELECT))
+
+
+/* --------- anim_deps.c, animation updates -------- */
+
+ /* generic update flush, does tagged objects only, reads from Context screen (layers) and scene */
+void ED_anim_dag_flush_update(const struct bContext *C);
+ /* only flush object */
+void ED_anim_object_flush_update(const struct bContext *C, struct Object *ob);
+
+/* pose <-> action syncing */
+void ANIM_action_to_pose_sync(struct Object *ob);
+void ANIM_pose_to_action_sync(struct Object *ob, struct ScrArea *sa);
+
+
+/* what types of animation data was changed (for sending notifiers from animation tools) */
+enum {
+ ANIM_CHANGED_BOTH= 0,
+ ANIM_CHANGED_KEYFRAMES_VALUES,
+ ANIM_CHANGED_KEYFRAMES_SELECT,
+ ANIM_CHANGED_CHANNELS
+} eAnimData_Changed;
+
+/* Send notifiers on behalf of animation editing tools, based on various context info */
+void ANIM_animdata_send_notifiers(struct bContext *C, bAnimContext *ac, short data_changed);
+
+/* ************************************************* */
+/* OPERATORS */
+
+ /* generic animation channels */
+void ED_operatortypes_animchannels(void);
+void ED_keymap_animchannels(struct wmWindowManager *wm);
+
+ /* generic time editing */
+void ED_operatortypes_anim(void);
+void ED_keymap_anim(struct wmWindowManager *wm);
+
+/* ************************************************ */
+
+#endif /* ED_ANIM_API_H */
+
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
new file mode 100644
index 00000000000..0f2ac6e3027
--- /dev/null
+++ b/source/blender/editors/include/ED_armature.h
@@ -0,0 +1,151 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_ARMATURE_H
+#define ED_ARMATURE_H
+
+struct bContext;
+struct Scene;
+struct Object;
+struct Base;
+struct Bone;
+struct bArmature;
+struct bPoseChannel;
+struct wmWindowManager;
+struct ListBase;
+struct View3D;
+struct ViewContext;
+struct RegionView3D;
+
+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];
+ 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*/
+ int flag;
+
+ int parNr; /* Used for retrieving values from the menu system */
+
+ float dist, weight;
+ float xwidth, length, zwidth; /* put them in order! transform uses this as scale */
+ float ease1, ease2;
+ float rad_head, rad_tail;
+ short layer, segments;
+
+ float oldlength; /* for envelope scaling */
+
+} EditBone;
+
+#define BONESEL_ROOT 0x10000000
+#define BONESEL_TIP 0x20000000
+#define BONESEL_BONE 0x40000000
+#define BONESEL_ANY (BONESEL_TIP|BONESEL_ROOT|BONESEL_BONE)
+
+#define BONESEL_NOSEL 0x80000000 /* Indicates a negative number */
+
+/* useful macros */
+#define EBONE_VISIBLE(arm, ebone) ((arm->layer & ebone->layer) && !(ebone->flag & BONE_HIDDEN_A))
+#define EBONE_EDITABLE(ebone) ((ebone->flag & BONE_SELECTED) && !(ebone->flag & BONE_EDITMODE_LOCKED))
+
+/* used in bone_select_hierachy() */
+#define BONE_SELECT_PARENT 0
+#define BONE_SELECT_CHILD 1
+
+/* armature_ops.c */
+void ED_operatortypes_armature(void);
+void ED_keymap_armature(struct wmWindowManager *wm);
+
+/* editarmature.c */
+void ED_armature_from_edit(struct Scene *scene, struct Object *obedit);
+void ED_armature_to_edit(struct Object *ob);
+void ED_armature_edit_free(struct Object *ob);
+void ED_armature_edit_remake(struct Object *obedit);
+int ED_do_pose_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer,
+ short hits, short extend);
+void mouse_armature(struct bContext *C, short mval[2], int extend);
+struct Bone *get_indexed_bone (struct Object *ob, int index);
+float ED_rollBoneToVector(EditBone *bone, float new_up_axis[3]);
+EditBone *ED_armature_bone_get_mirrored(struct ListBase *edbo, EditBone *ebo); // XXX this is needed for populating the context iterators
+
+void add_primitive_bone(struct Scene *scene, struct View3D *v3d, struct RegionView3D *rv3d);
+
+void transform_armature_mirror_update(struct Object *obedit);
+void clear_armature(struct Scene *scene, struct Object *ob, char mode);
+void create_vgroups_from_armature(struct Scene *scene, struct Object *ob, struct Object *par);
+void docenter_armature (struct Scene *scene, struct View3D *v3d, struct Object *ob, int centermode);
+
+void auto_align_armature(struct Scene *scene, struct View3D *v3d, short mode);
+void unique_editbone_name(struct ListBase *ebones, char *name, EditBone *bone); /* if bone is already in list, pass it as param to ignore it */
+void armature_bone_rename(struct Object *ob, char *oldnamep, char *newnamep);
+
+void undo_push_armature(struct bContext *C, char *name);
+
+/* poseobject.c */
+void ED_armature_exit_posemode(struct bContext *C, struct Base *base);
+void ED_armature_enter_posemode(struct bContext *C, struct Base *base);
+int ED_pose_channel_in_IK_chain(struct Object *ob, struct bPoseChannel *pchan);
+void ED_pose_deselectall(struct Object *ob, int test, int doundo);
+
+/* sketch */
+
+int ED_operator_sketch_mode_active_stroke(struct bContext *C);
+int ED_operator_sketch_full_mode(struct bContext *C);
+int ED_operator_sketch_mode(struct bContext *C);
+
+void BIF_freeSketch(struct bContext *C);
+void BIF_convertSketch(struct bContext *C);
+void BIF_deleteSketch(struct bContext *C);
+void BIF_selectAllSketch(struct bContext *C, int mode); /* -1: deselect, 0: select, 1: toggle */
+
+void BIF_makeListTemplates(struct bContext *C);
+char *BIF_listTemplates(struct bContext *C);
+int BIF_currentTemplate(struct bContext *C);
+void BIF_freeTemplates(struct bContext *C);
+void BIF_setTemplate(struct bContext *C, int index);
+int BIF_nbJointsTemplate(struct bContext *C);
+char * BIF_nameBoneTemplate(struct bContext *C);
+
+void BDR_drawSketch(struct bContext *vc);
+int BDR_drawSketchNames(struct ViewContext *vc);
+
+#endif /* ED_ARMATURE_H */
+
+
+
diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h
new file mode 100644
index 00000000000..c619ee80f70
--- /dev/null
+++ b/source/blender/editors/include/ED_curve.h
@@ -0,0 +1,64 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_CURVE_H
+#define ED_CURVE_H
+
+struct Base;
+struct bContext;
+struct Object;
+struct Scene;
+struct Text;
+struct View3D;
+struct wmWindowManager;
+
+/* curve_ops.c */
+void ED_operatortypes_curve(void);
+void ED_keymap_curve (struct wmWindowManager *wm);
+
+/* editcurve.c */
+void undo_push_curve (struct bContext *C, char *name);
+ListBase *curve_get_editcurve(struct Object *ob);
+
+void load_editNurb (struct Object *obedit);
+void make_editNurb (struct Object *obedit);
+void free_editNurb (struct Object *obedit);
+
+void mouse_nurb (struct bContext *C, short mval[2], int extend);
+
+struct Nurb *add_nurbs_primitive(struct bContext *C, int type, int newname);
+
+/* editfont.h */
+void undo_push_font (struct bContext *C, char *name);
+void make_editText (struct Object *obedit);
+void load_editText (struct Object *obedit);
+void free_editText (struct Object *obedit);
+
+void ED_text_to_object(struct bContext *C, struct Text *text, int split_lines);
+
+#endif /* ED_CURVE_H */
+
diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h
new file mode 100644
index 00000000000..5d24b93418b
--- /dev/null
+++ b/source/blender/editors/include/ED_datafiles.h
@@ -0,0 +1,56 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_DATAFILES_H
+#define ED_DATAFILES_H
+
+/* Datafiles embedded in Blender */
+
+extern int datatoc_B_blend_size;
+extern char datatoc_B_blend[];
+
+extern int datatoc_blenderbuttons_size;
+extern char datatoc_blenderbuttons[];
+
+extern int datatoc_prvicons_size;
+extern char datatoc_prvicons[];
+
+extern int datatoc_splash_jpg_size;
+extern char datatoc_splash_jpg[];
+
+extern int datatoc_Bfont_size;
+extern char datatoc_Bfont[];
+
+extern int datatoc_bfont_ttf_size;
+extern char datatoc_bfont_ttf[];
+
+extern int datatoc_bmonofont_ttf_size;
+extern char datatoc_bmonofont_ttf[];
+
+#endif /* ED_DATAFILES_H */
+
diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h
new file mode 100644
index 00000000000..bb5ced66428
--- /dev/null
+++ b/source/blender/editors/include/ED_fileselect.h
@@ -0,0 +1,103 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_FILES_H
+#define ED_FILES_H
+
+struct SpaceFile;
+
+#define FILE_SHORTDISPLAY 1
+#define FILE_LONGDISPLAY 2
+#define FILE_IMGDISPLAY 3
+
+typedef struct FileSelectParams {
+ int type; /* the mode of the filebrowser, FILE_BLENDER, FILE_SPECIAL, FILE_MAIN or FILE_LOADLIB */
+ char title[24]; /* title, also used for the text of the execute button */
+ char dir[240]; /* directory */
+ char file[80]; /* file */
+
+ short flag; /* settings for filter, hiding files and display mode */
+ short sort; /* sort order */
+ short display; /* display mode flag */
+ short filter; /* filter when (flags & FILE_FILTER) is true */
+
+ /* XXX - temporary, better move to filelist */
+ short active_bookmark;
+ int active_file;
+ int selstate;
+
+ /* XXX --- still unused -- */
+ short f_fp; /* show font preview */
+ char fp_str[8]; /* string to use for font preview */
+
+ char *pupmenu; /* allows menu for save options - result stored in menup */
+ short menu; /* currently selected option in pupmenu */
+ /* XXX --- end unused -- */
+} FileSelectParams;
+
+#define FILE_LAYOUT_HOR 1
+#define FILE_LAYOUT_VER 2
+
+typedef struct FileLayout
+{
+ /* view settings - XXX - move into own struct */
+ short prv_w;
+ short prv_h;
+ short tile_w;
+ short tile_h;
+ short tile_border_x;
+ short tile_border_y;
+ short prv_border_x;
+ short prv_border_y;
+ short rows;
+ short columns;
+ short width;
+ short height;
+ short flag;
+
+} FileLayout;
+
+FileSelectParams* ED_fileselect_get_params(struct SpaceFile *sfile);
+
+short ED_fileselect_set_params(struct SpaceFile *sfile, int type, const char *title, const char *path,
+ short flag, short display, short filter);
+
+void ED_fileselect_reset_params(struct SpaceFile *sfile);
+
+
+void ED_fileselect_init_layout(struct SpaceFile *sfile, struct ARegion *ar);
+
+
+FileLayout* ED_fileselect_get_layout(struct SpaceFile *sfile, struct ARegion *ar);
+
+int ED_fileselect_layout_offset(FileLayout* layout, int x, int y);
+
+void ED_fileselect_layout_tilepos(FileLayout* layout, int tile, short *x, short *y);
+
+
+#endif /* ED_FILES_H */
+
diff --git a/source/blender/editors/include/ED_fluidsim.h b/source/blender/editors/include/ED_fluidsim.h
new file mode 100644
index 00000000000..bda879173c3
--- /dev/null
+++ b/source/blender/editors/include/ED_fluidsim.h
@@ -0,0 +1,52 @@
+/**
+ * BKE_fluidsim.h
+ *
+ * $Id: LBM_fluidsim.h 17433 2008-11-12 21:16:53Z blendix $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_FLUIDSIM_H
+#define ED_FLUIDSIM_H
+
+struct Object;
+struct FluidsimSettings;
+
+extern double fluidsimViscosityPreset[6];
+extern char* fluidsimViscosityPresetString[6];
+
+/* allocates and initializes fluidsim data */
+struct FluidsimSettings* fluidsimSettingsNew(struct Object *srcob);
+
+/* frees internal data itself */
+void fluidsimSettingsFree(struct FluidsimSettings* sb);
+
+/* duplicate internal data */
+struct FluidsimSettings* fluidsimSettingsCopy(struct FluidsimSettings* sb);
+
+
+#endif /* ED_FLUIDSIM_H */
+
+
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
new file mode 100644
index 00000000000..ad8124c89d7
--- /dev/null
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -0,0 +1,83 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_GPENCIL_H
+#define ED_GPENCIL_H
+
+struct ListBase;
+struct bScreen;
+struct ScrArea;
+struct ARegion;
+struct View3D;
+struct SpaceNode;
+struct SpaceSeq;
+struct bGPdata;
+struct bGPDlayer;
+struct bGPDframe;
+struct bGPdata;
+struct uiBlock;
+struct ImBuf;
+
+
+
+/* ------------- Grease-Pencil Helpers -------------- */
+
+/* Temporary 'Stroke Point' data */
+typedef struct tGPspoint {
+ short x, y; /* x and y coordinates of cursor (in relative to area) */
+ float pressure; /* pressure of tablet at this point */
+} tGPspoint;
+
+/* ------------ Grease-Pencil Depreceated Stuff ------------------ */
+
+struct bGPdata *gpencil_data_getactive(struct ScrArea *sa);
+short gpencil_data_setactive(struct ScrArea *sa, struct bGPdata *gpd);
+struct ScrArea *gpencil_data_findowner(struct bGPdata *gpd);
+
+/* ------------ Grease-Pencil Editing API ------------------ */
+
+void gpencil_delete_actframe(struct bGPdata *gpd, int cfra);
+void gpencil_delete_laststroke(struct bGPdata *gpd, int cfra);
+
+void gpencil_delete_operation(int cfra, short mode);
+void gpencil_delete_menu(void);
+
+void gpencil_convert_operation(short mode);
+void gpencil_convert_menu(void);
+
+short gpencil_do_paint(struct bContext *C);
+
+/* ------------ Grease-Pencil Drawing API ------------------ */
+/* drawgpencil.c */
+
+void draw_gpencil_2dimage(struct bContext *C, struct ImBuf *ibuf);
+void draw_gpencil_2dview(struct bContext *C, short onlyv2d);
+void draw_gpencil_3dview(struct bContext *C, short only3d);
+void draw_gpencil_oglrender(struct bContext *C);
+
+
+#endif /* ED_GPENCIL_H */
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
new file mode 100644
index 00000000000..566105109b2
--- /dev/null
+++ b/source/blender/editors/include/ED_image.h
@@ -0,0 +1,63 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_IMAGE_H
+#define ED_IMAGE_H
+
+struct SpaceImage;
+struct bContext;
+struct Image;
+struct ImageUser;
+struct uiBlock;
+
+/* space_image.c, exported for transform */
+struct Image *ED_space_image(struct SpaceImage *sima);
+void ED_space_image_set(struct bContext *C, struct SpaceImage *sima, struct Scene *scene, struct Object *obedit, struct Image *ima);
+
+struct ImBuf *ED_space_image_buffer(struct SpaceImage *sima);
+void ED_space_image_size(struct SpaceImage *sima, int *width, int *height);
+void ED_space_image_aspect(struct SpaceImage *sima, float *aspx, float *aspy);
+void ED_space_image_zoom(struct SpaceImage *sima, struct ARegion *ar, float *zoomx, float *zoomy);
+void ED_space_image_uv_aspect(struct SpaceImage *sima, float *aspx, float *aspy);
+
+void ED_image_size(struct Image *ima, int *width, int *height);
+void ED_image_aspect(struct Image *ima, float *aspx, float *aspy);
+void ED_image_uv_aspect(struct Image *ima, float *aspx, float *aspy);
+
+int ED_space_image_show_render(struct SpaceImage *sima);
+int ED_space_image_show_paint(struct SpaceImage *sima);
+int ED_space_image_show_uvedit(struct SpaceImage *sima, struct Object *obedit);
+int ED_space_image_show_uvshadow(struct SpaceImage *sima, struct Object *obedit);
+
+void ED_image_uiblock_panel(const struct bContext *C, struct uiBlock *block, struct Image **ima_pp,
+ struct ImageUser *iuser, short redraw, short imagechanged);
+
+/* image_render.c, export for screen_ops.c, render operator */
+void ED_space_image_output(struct bContext *C);
+
+#endif /* ED_IMAGE_H */
+
diff --git a/source/blender/editors/include/ED_interface.h b/source/blender/editors/include/ED_interface.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/source/blender/editors/include/ED_interface.h
diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h
new file mode 100644
index 00000000000..81420ac95e5
--- /dev/null
+++ b/source/blender/editors/include/ED_keyframes_draw.h
@@ -0,0 +1,98 @@
+/**
+ * $Id: BDR_drawaction.h 17579 2008-11-26 11:01:56Z aligorith $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_KEYFRAMES_DRAW_H
+#define ED_KEYFRAMES_DRAW_H
+
+struct BezTriple;
+struct FCurve;
+struct gla2DDrawInfo;
+struct bAction;
+struct bActionGroup;
+struct Object;
+struct ListBase;
+struct bGPDlayer;
+struct Scene;
+
+/* ****************************** Base Structs ****************************** */
+
+/* Keyframe Column Struct */
+typedef struct ActKeyColumn {
+ struct ActKeyColumn *next, *prev;
+ short sel, handle_type;
+ float cfra;
+
+ /* only while drawing - used to determine if long-keyframe needs to be drawn */
+ short modified;
+ short totcurve;
+} ActKeyColumn;
+
+/* 'Long Keyframe' Struct */
+typedef struct ActKeyBlock {
+ struct ActKeyBlock *next, *prev;
+ short sel, handle_type;
+ float val;
+ float start, end;
+
+ /* only while drawing - used to determine if block needs to be drawn */
+ short modified;
+ short totcurve;
+} ActKeyBlock;
+
+
+/* Inclusion-Range Limiting Struct (optional) */
+typedef struct ActKeysInc {
+ struct bDopeSheet *ads; /* dopesheet data (for dopesheet mode) */
+ struct Object *ob; /* owner object for NLA-scaling info (if Object channels, is just Object) */
+ short actmode; /* mode of the Action Editor (-1 is for NLA) */
+
+ float start, end; /* frames (global-time) to only consider keys between */ // XXX not used anymore!
+} ActKeysInc;
+
+/* ******************************* Methods ****************************** */
+
+/* Channel Drawing */
+void draw_fcurve_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct FCurve *fcu, float ypos);
+void draw_agroup_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct bActionGroup *agrp, float ypos);
+void draw_action_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct bAction *act, float ypos);
+void draw_object_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct Object *ob, float ypos);
+void draw_scene_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct Scene *sce, float ypos);
+void draw_gpl_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct bGPDlayer *gpl, float ypos);
+
+/* Keydata Generation */
+void fcurve_to_keylist(struct FCurve *fcu, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void agroup_to_keylist(struct bActionGroup *agrp, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void action_to_keylist(struct bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void action_nlascaled_to_keylist(struct Object *ob, struct bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void ob_to_keylist(struct Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void scene_to_keylist(struct Scene *sce, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void gpl_to_keylist(struct bGPDlayer *gpl, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+
+#endif /* ED_KEYFRAMES_DRAW_H */
+
diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h
new file mode 100644
index 00000000000..44d4e26fea5
--- /dev/null
+++ b/source/blender/editors/include/ED_keyframes_edit.h
@@ -0,0 +1,159 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_KEYFRAMES_EDIT_H
+#define ED_KEYFRAMES_EDIT_H
+
+struct bAnimContext;
+struct bAnimListElem;
+struct FCurve;
+struct BezTriple;
+struct Scene;
+
+/* ************************************************ */
+/* Common Macros and Defines */
+
+/* --------- BezTriple Selection ------------- */
+
+#define BEZSELECTED(bezt) ((bezt->f2 & SELECT) || (bezt->f1 & SELECT) || (bezt->f3 & SELECT))
+
+#define BEZ_SEL(bezt) { (bezt)->f1 |= SELECT; (bezt)->f2 |= SELECT; (bezt)->f3 |= SELECT; }
+#define BEZ_DESEL(bezt) { (bezt)->f1 &= ~SELECT; (bezt)->f2 &= ~SELECT; (bezt)->f3 &= ~SELECT; }
+#define BEZ_INVSEL(bezt) { (bezt)->f1 ^= SELECT; (bezt)->f2 ^= SELECT; (bezt)->f3 ^= SELECT; }
+
+/* --------- Tool Flags ------------ */
+
+/* bezt validation */
+typedef enum eEditKeyframes_Validate {
+ BEZT_OK_FRAME = 1,
+ BEZT_OK_FRAMERANGE,
+ BEZT_OK_SELECTED,
+ BEZT_OK_VALUE,
+ BEZT_OK_VALUERANGE,
+ BEZT_OK_REGION,
+} eEditKeyframes_Validate;
+
+/* ------------ */
+
+/* select tools */
+typedef enum eEditKeyframes_Select {
+ SELECT_REPLACE = (1<<0),
+ SELECT_ADD = (1<<1),
+ SELECT_SUBTRACT = (1<<2),
+ SELECT_INVERT = (1<<4),
+} eEditKeyframes_Select;
+
+/* snapping tools */
+typedef enum eEditKeyframes_Snap {
+ SNAP_KEYS_CURFRAME = 1,
+ SNAP_KEYS_NEARFRAME,
+ SNAP_KEYS_NEARSEC,
+ SNAP_KEYS_NEARMARKER,
+ SNAP_KEYS_HORIZONTAL,
+} eEditKeyframes_Snap;
+
+/* mirroring tools */
+typedef enum eEditKeyframes_Mirror {
+ MIRROR_KEYS_CURFRAME = 1,
+ MIRROR_KEYS_YAXIS,
+ MIRROR_KEYS_XAXIS,
+ MIRROR_KEYS_MARKER,
+} eEditKeyframes_Mirror;
+
+/* ************************************************ */
+/* Non-Destuctive Editing API (keyframes_edit.c) */
+
+/* --- Generic Properties for Bezier Edit Tools ----- */
+
+typedef struct BeztEditData {
+ ListBase list; /* temp list for storing custom list of data to check */
+ struct Scene *scene; /* pointer to current scene - many tools need access to cfra/etc. */
+ void *data; /* pointer to custom data - usually 'Object' but also 'rectf', but could be other types too */
+ float f1, f2; /* storage of times/values as 'decimals' */
+ int i1, i2; /* storage of times/values/flags as 'whole' numbers */
+} BeztEditData;
+
+/* ------- Function Pointer Typedefs ---------------- */
+
+ /* callback function that refreshes the IPO curve after use */
+typedef void (*FcuEditFunc)(struct FCurve *fcu);
+ /* callback function that operates on the given BezTriple */
+typedef short (*BeztEditFunc)(BeztEditData *bed, struct BezTriple *bezt);
+
+/* ---------------- Looping API --------------------- */
+
+/* functions for looping over keyframes */
+ /* function for working with F-Curve data only (i.e. when filters have been chosen to explicitly use this) */
+short ANIM_fcurve_keys_bezier_loop(BeztEditData *bed, struct FCurve *fcu, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb);
+ /* function for working with any type (i.e. one of the known types) of animation channel
+ * - filterflag is bDopeSheet->flag (DOPESHEET_FILTERFLAG)
+ */
+short ANIM_animchannel_keys_bezier_loop(BeztEditData *bed, struct bAnimListElem *ale, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag);
+ /* same as above, except bAnimListElem wrapper is not needed...
+ * - keytype is eAnim_KeyType
+ */
+short ANIM_animchanneldata_keys_bezier_loop(BeztEditData *bed, void *data, int keytype, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag);
+
+/* functions for making sure all keyframes are in good order */
+void ANIM_editkeyframes_refresh(struct bAnimContext *ac);
+
+/* ----------- BezTriple Callback Getters ---------- */
+
+/* accessories */
+BeztEditFunc ANIM_editkeyframes_ok(short mode);
+
+/* edit */
+BeztEditFunc ANIM_editkeyframes_snap(short mode);
+BeztEditFunc ANIM_editkeyframes_mirror(short mode);
+BeztEditFunc ANIM_editkeyframes_select(short mode);
+BeztEditFunc ANIM_editkeyframes_handles(short mode);
+BeztEditFunc ANIM_editkeyframes_ipo(short mode);
+
+/* ----------- BezTriple Callback (Assorted Utilities) ---------- */
+
+short bezt_calc_average(BeztEditData *bed, struct BezTriple *bezt);
+
+/* ************************************************ */
+/* Destructive Editing API (keyframes_general.c) */
+
+void delete_fcurve_key(struct FCurve *fcu, int index, short do_recalc);
+void delete_fcurve_keys(struct FCurve *fcu);
+void duplicate_fcurve_keys(struct FCurve *fcu);
+
+void clean_fcurve(struct FCurve *fcu, float thresh);
+void smooth_fcurve(struct FCurve *fcu);
+
+/* ----------- */
+
+void free_anim_copybuf(void);
+short copy_animedit_keys(struct bAnimContext *ac, ListBase *anim_data);
+short paste_animedit_keys(struct bAnimContext *ac, ListBase *anim_data);
+
+/* ************************************************ */
+
+#endif /* ED_KEYFRAMES_EDIT_H */
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
new file mode 100644
index 00000000000..fbb469f8d43
--- /dev/null
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -0,0 +1,213 @@
+/**
+ * $Id: BIF_keyframing.h 17216 2008-10-29 11:20:02Z aligorith $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place * Suite 330, Boston, MA 02111*1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * This is a new part of Blender (with some old code)
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_KEYFRAMING_H
+#define ED_KEYFRAMING_H
+
+struct ListBase;
+struct ID;
+
+struct KeyingSet;
+
+struct bAction;
+struct FCurve;
+struct BezTriple;
+
+struct bPoseChannel;
+struct bConstraint;
+
+struct bContext;
+struct wmOperatorType;
+
+/* ************ Keyframing Management **************** */
+
+/* Get (or add relevant data to be able to do so) the Active Action for the given
+ * Animation Data block, given an ID block where the Animation Data should reside.
+ */
+struct bAction *verify_adt_action(struct ID *id, short add);
+
+/* Get (or add relevant data to be able to do so) F-Curve from the given Action.
+ * This assumes that all the destinations are valid.
+ */
+struct FCurve *verify_fcurve(struct bAction *act, const char group[], const char rna_path[], const int array_index, short add);
+
+/* -------- */
+
+/* Lesser Keyframing API call:
+ * Use this when validation of necessary animation data isn't necessary as it already
+ * exists, and there is a beztriple that can be directly copied into the array.
+ */
+int insert_bezt_fcurve(struct FCurve *fcu, struct BezTriple *bezt);
+
+/* Main Keyframing API call:
+ * Use this when validation of necessary animation data isn't necessary as it
+ * already exists. It will insert a keyframe using the current value being keyframed.
+ */
+void insert_vert_fcurve(struct FCurve *fcu, float x, float y, short flag);
+
+/* -------- */
+
+/* Main Keyframing API calls:
+ * Use this to create any necessary animation data, and then insert a keyframe
+ * using the current value being keyframed, in the relevant place. Returns success.
+ */
+short insert_keyframe(struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag);
+
+/* Main Keyframing API call:
+ * Use this to delete keyframe on current frame for relevant channel. Will perform checks just in case.
+ */
+short delete_keyframe(struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag);
+
+/* -------- */
+
+/* Main Keyframe Management operators:
+ * These handle keyframes management from various spaces. They only make use of
+ * Keying Sets.
+ */
+void ANIM_OT_insert_keyframe(struct wmOperatorType *ot);
+void ANIM_OT_delete_keyframe(struct wmOperatorType *ot);
+
+/* Main Keyframe Management operators:
+ * These handle keyframes management from various spaces. They will handle the menus
+ * required for each space.
+ */
+void ANIM_OT_insert_keyframe_menu(struct wmOperatorType *ot);
+void ANIM_OT_delete_keyframe_menu(struct wmOperatorType *ot); // xxx unimplemented yet
+void ANIM_OT_delete_keyframe_old(struct wmOperatorType *ot); // xxx rename and keep?
+
+/* Keyframe managment operators for UI buttons. */
+void ANIM_OT_insert_keyframe_button(struct wmOperatorType *ot);
+void ANIM_OT_delete_keyframe_button(struct wmOperatorType *ot);
+
+/* ************ Keying Sets ********************** */
+
+/* temporary struct to gather data combos to keyframe
+ * (is used by modify_keyframes for 'relative' KeyingSets, provided via the dsources arg)
+ */
+typedef struct bCommonKeySrc {
+ struct bCommonKeySrc *next, *prev;
+
+ /* general data/destination-source settings */
+ struct ID *id; /* id-block this comes from */
+
+ /* specific cases */
+ struct bPoseChannel *pchan;
+ struct bConstraint *con;
+} bCommonKeySrc;
+
+/* -------- */
+
+/* mode for modify_keyframes */
+enum {
+ MODIFYKEY_MODE_INSERT = 0,
+ MODIFYKEY_MODE_DELETE,
+} eModifyKey_Modes;
+
+/* Keyframing Helper Call - use the provided Keying Set to Add/Remove Keyframes */
+int modify_keyframes(struct bContext *C, struct ListBase *dsources, struct bAction *act, struct KeyingSet *ks, short mode, float cfra);
+
+/* -------- */
+
+/* Generate menu of KeyingSets */
+char *ANIM_build_keyingsets_menu(struct ListBase *list, short for_edit);
+
+/* Get the first builtin KeyingSet with the given name, which occurs after the given one (or start of list if none given) */
+struct KeyingSet *ANIM_builtin_keyingset_get_named(struct KeyingSet *prevKS, char name[]);
+
+/* Initialise builtin KeyingSets on startup */
+void init_builtin_keyingsets(void);
+
+/* -------- */
+
+/* KeyingSet Editing Operators:
+ * These can add a new KeyingSet and/or add 'destinations' to the KeyingSets,
+ * acting as a means by which they can be added outside the Outliner.
+ */
+void ANIM_OT_keyingset_add_new(struct wmOperatorType *ot);
+void ANIM_OT_keyingset_add_destination(struct wmOperatorType *ot);
+
+/* ************ Drivers ********************** */
+
+/* Main Driver Management API calls:
+ * Add a new driver for the specified property on the given ID block
+ */
+short ANIM_add_driver (struct ID *id, const char rna_path[], int array_index, short flag);
+
+/* Main Driver Management API calls:
+ * Remove the driver for the specified property on the given ID block (if available)
+ */
+short ANIM_remove_driver (struct ID *id, const char rna_path[], int array_index, short flag);
+
+/* Driver management operators for UI buttons */
+void ANIM_OT_add_driver_button(struct wmOperatorType *ot);
+void ANIM_OT_remove_driver_button(struct wmOperatorType *ot);
+
+/* ************ Auto-Keyframing ********************** */
+/* Notes:
+ * - All the defines for this (User-Pref settings and Per-Scene settings)
+ * are defined in DNA_userdef_types.h
+ * - Scene settings take presidence over those for userprefs, with old files
+ * inheriting userpref settings for the scene settings
+ * - "On/Off + Mode" are stored per Scene, but "settings" are currently stored
+ * as userprefs
+ */
+
+/* Auto-Keying macros for use by various tools */
+ /* check if auto-keyframing is enabled (per scene takes presidence) */
+#define IS_AUTOKEY_ON(scene) ((scene) ? (scene->autokey_mode & AUTOKEY_ON) : (U.autokey_mode & AUTOKEY_ON))
+ /* check the mode for auto-keyframing (per scene takes presidence) */
+#define IS_AUTOKEY_MODE(scene, mode) ((scene) ? (scene->autokey_mode == AUTOKEY_MODE_##mode) : (U.autokey_mode == AUTOKEY_MODE_##mode))
+ /* check if a flag is set for auto-keyframing (as userprefs only!) */
+#define IS_AUTOKEY_FLAG(flag) (U.autokey_flag & AUTOKEY_FLAG_##flag)
+
+/* ************ Keyframe Checking ******************** */
+
+/* Main Keyframe Checking API call:
+ * Checks whether a keyframe exists for the given ID-block one the given frame.
+ * - It is recommended to call this method over the other keyframe-checkers directly,
+ * in case some detail of the implementation changes...
+ * - frame: the value of this is quite often result of frame_to_float(CFRA)
+ */
+short id_frame_has_keyframe(struct ID *id, float frame, short filter);
+
+/* filter flags for id_cfra_has_keyframe
+ *
+ * WARNING: do not alter order of these, as also stored in files
+ * (for v3d->keyflags)
+ */
+enum {
+ /* general */
+ ANIMFILTER_KEYS_LOCAL = (1<<0), /* only include locally available anim data */
+ ANIMFILTER_KEYS_MUTED = (1<<1), /* include muted elements */
+ ANIMFILTER_KEYS_ACTIVE = (1<<2), /* only include active-subelements */
+
+ /* object specific */
+ ANIMFILTER_KEYS_NOMAT = (1<<9), /* don't include material keyframes */
+ ANIMFILTER_KEYS_NOSKEY = (1<<10), /* don't include shape keys (for geometry) */
+} eAnimFilterFlags;
+
+#endif /* ED_KEYFRAMING_H */
diff --git a/source/blender/editors/include/ED_markers.h b/source/blender/editors/include/ED_markers.h
new file mode 100644
index 00000000000..0e9a82083a6
--- /dev/null
+++ b/source/blender/editors/include/ED_markers.h
@@ -0,0 +1,51 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_MARKERS_H
+#define ED_MARKERS_H
+
+
+/* flags for drawing markers */
+enum {
+ DRAW_MARKERS_LINES = (1<<0),
+ DRAW_MARKERS_LOCAL = (1<<1)
+};
+
+struct wmWindowManager;
+struct bContext;
+
+void draw_markers_time(const struct bContext *C, int flag);
+int find_nearest_marker_time(ListBase *markers, float dx);
+
+/* called in screen_ops.c:ED_operatortypes_screen() */
+void ED_marker_operatortypes(void);
+/* called in screen_ops.c:ED_keymap_screen() */
+void ED_marker_keymap(struct wmWindowManager *wm);
+
+
+#endif /* ED_MARKERS_H */
+
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
new file mode 100644
index 00000000000..6dff4ee6ca4
--- /dev/null
+++ b/source/blender/editors/include/ED_mesh.h
@@ -0,0 +1,174 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_MESH_H
+#define ED_MESH_H
+
+struct ID;
+struct View3D;
+struct ARegion;
+struct EditMesh;
+struct EditVert;
+struct EditEdge;
+struct EditFace;
+struct bContext;
+struct wmWindowManager;
+struct EditSelection;
+struct ViewContext;
+struct bDeformGroup;
+struct MDeformWeight;
+struct MDeformVert;
+struct Scene;
+struct Mesh;
+struct MCol;
+struct UvVertMap;
+struct UvMapVert;
+struct CustomData;
+
+// edge and face flag both
+#define EM_FGON 2
+// face flag
+#define EM_FGON_DRAW 1
+
+/* editbutflag */
+#define B_CLOCKWISE 1
+#define B_KEEPORIG 2
+#define B_BEAUTY 4
+#define B_SMOOTH 8
+#define B_BEAUTY_SHORT 16
+#define B_AUTOFGON 32
+#define B_KNIFE 0x80
+#define B_PERCENTSUBD 0x40
+#define B_MESH_X_MIRROR 0x100
+#define B_JOINTRIA_UV 0x200
+#define B_JOINTRIA_VCOL 0X400
+#define B_JOINTRIA_SHARP 0X800
+#define B_JOINTRIA_MAT 0X1000
+
+
+/* meshtools.c */
+
+intptr_t mesh_octree_table(struct Object *ob, struct EditMesh *em, float *co, char mode);
+struct EditVert *editmesh_get_x_mirror_vert(struct Object *ob, struct EditMesh *em, float *co);
+int mesh_get_x_mirror_vert(struct Object *ob, int index);
+int *mesh_get_x_mirror_faces(struct Object *ob, struct EditMesh *em);
+
+/* mesh_ops.c */
+void ED_operatortypes_mesh(void);
+void ED_keymap_mesh(struct wmWindowManager *wm);
+
+
+/* editmesh.c */
+
+void ED_spacetypes_init(void);
+void ED_keymap_mesh(struct wmWindowManager *wm);
+
+void make_editMesh(struct Scene *scene, Object *ob);
+void load_editMesh(struct Scene *scene, Object *ob);
+void remake_editMesh(struct Scene *scene, Object *ob);
+void free_editMesh(struct EditMesh *em);
+
+void recalc_editnormals(struct EditMesh *em);
+
+void EM_init_index_arrays(struct EditMesh *em, int forVert, int forEdge, int forFace);
+void EM_free_index_arrays(void);
+struct EditVert *EM_get_vert_for_index(int index);
+struct EditEdge *EM_get_edge_for_index(int index);
+struct EditFace *EM_get_face_for_index(int index);
+int EM_texFaceCheck(struct EditMesh *em);
+int EM_vertColorCheck(struct EditMesh *em);
+
+void undo_push_mesh(struct bContext *C, char *name);
+
+
+/* editmesh_lib.c */
+
+struct EditFace *EM_get_actFace(struct EditMesh *em, int sloppy);
+void EM_set_actFace(struct EditMesh *em, struct EditFace *efa);
+float EM_face_area(struct EditFace *efa);
+void EM_add_data_layer(struct EditMesh *em, struct CustomData *data, int type);
+
+void EM_select_edge(struct EditEdge *eed, int sel);
+void EM_select_face(struct EditFace *efa, int sel);
+void EM_select_face_fgon(struct EditMesh *em, struct EditFace *efa, int val);
+void EM_select_swap(struct EditMesh *em);
+void EM_toggle_select_all(struct EditMesh *em);
+void EM_selectmode_flush(struct EditMesh *em);
+void EM_deselect_flush(struct EditMesh *em);
+void EM_selectmode_set(struct EditMesh *em);
+void EM_select_flush(struct EditMesh *em);
+void EM_convertsel(struct EditMesh *em, short oldmode, short selectmode);
+void EM_validate_selections(struct EditMesh *em);
+
+ /* exported to transform */
+int EM_get_actSelection(struct EditMesh *em, struct EditSelection *ese);
+void EM_editselection_normal(float *normal, struct EditSelection *ese);
+void EM_editselection_plane(float *plane, struct EditSelection *ese);
+void EM_editselection_center(float *center, struct EditSelection *ese);
+
+struct UvVertMap *EM_make_uv_vert_map(struct EditMesh *em, int selected, int do_face_idx_array, float *limit);
+struct UvMapVert *EM_get_uv_map_vert(struct UvVertMap *vmap, unsigned int v);
+void EM_free_uv_vert_map(struct UvVertMap *vmap);
+
+/* editmesh_mods.c */
+extern unsigned int em_vertoffs, em_solidoffs, em_wireoffs;
+
+void mouse_mesh(struct bContext *C, short mval[2], short extend);
+int EM_check_backbuf(unsigned int index);
+int EM_mask_init_backbuf_border(struct ViewContext *vc, short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax);
+void EM_free_backbuf(void);
+int EM_init_backbuf_border(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
+int EM_init_backbuf_circle(struct ViewContext *vc, short xs, short ys, short rads);
+
+void EM_hide_mesh(struct EditMesh *em, int swap);
+void EM_reveal_mesh(struct EditMesh *em);
+
+/* editface.c */
+struct MTFace *EM_get_active_mtface(struct EditMesh *em, struct EditFace **act_efa, struct MCol **mcol, int sloppy);
+
+/* editdeform.c XXX rename functions? */
+
+#define WEIGHT_REPLACE 1
+#define WEIGHT_ADD 2
+#define WEIGHT_SUBTRACT 3
+
+void add_defgroup (Object *ob);
+void create_dverts(struct ID *id);
+float get_vert_defgroup (Object *ob, struct bDeformGroup *dg, int vertnum);
+void remove_vert_defgroup (Object *ob, struct bDeformGroup *dg, int vertnum);
+void remove_verts_defgroup (Object *obedit, int allverts);
+void vertexgroup_select_by_name(Object *ob, char *name);
+void add_vert_to_defgroup (Object *ob, struct bDeformGroup *dg, int vertnum,
+ float weight, int assignmode);
+
+struct bDeformGroup *add_defgroup_name (Object *ob, char *name);
+struct MDeformWeight *verify_defweight (struct MDeformVert *dv, int defgroup);
+struct MDeformWeight *get_defweight (struct MDeformVert *dv, int defgroup);
+
+
+#endif /* ED_MESH_H */
+
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
new file mode 100644
index 00000000000..0cd5551f17f
--- /dev/null
+++ b/source/blender/editors/include/ED_node.h
@@ -0,0 +1,35 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_NODE_H
+#define ED_NODE_H
+
+/* drawnode.c */
+void ED_init_node_butfuncs(void);
+
+#endif /* ED_NODE_H */
+
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
new file mode 100644
index 00000000000..8ff716476ad
--- /dev/null
+++ b/source/blender/editors/include/ED_object.h
@@ -0,0 +1,92 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_OBJECT_H
+#define ED_OBJECT_H
+
+struct wmWindowManager;
+struct Scene;
+struct Object;
+struct bContext;
+struct Base;
+struct View3D;
+struct bConstraint;
+struct KeyBlock;
+struct Lattice;
+struct Mesh;
+struct Curve;
+
+/* object_edit.c */
+void ED_operatortypes_object(void);
+void ED_keymap_object(struct wmWindowManager *wm);
+
+ /* send your own notifier for select! */
+void ED_base_object_select(struct Base *base, short mode);
+ /* includes notifier */
+void ED_base_object_activate(struct bContext *C, struct Base *base);
+
+void ED_base_object_free_and_unlink(struct Scene *scene, struct Base *base);
+
+void ED_object_apply_obmat(struct Object *ob);
+ /* single object duplicate, if dupflag==0, fully linked, else it uses U.dupflag */
+Base *ED_object_add_duplicate(struct Scene *scene, struct Base *base, int usedupflag);
+
+
+/* bitflags for enter/exit editmode */
+#define EM_FREEDATA 1
+#define EM_FREEUNDO 2
+#define EM_WAITCURSOR 4
+void ED_object_exit_editmode(struct bContext *C, int flag);
+void ED_object_enter_editmode(struct bContext *C, int flag);
+
+void ED_object_base_init_from_view(struct bContext *C, struct Base *base);
+
+/* cleanup */
+int object_data_is_libdata(struct Object *ob);
+
+/* constraints */
+struct bConstraint *add_new_constraint (short type);
+void add_constraint_to_object (struct bConstraint *con, struct Object *ob);
+
+/* editlattice.c */
+void mouse_lattice(struct bContext *C, short mval[2], int extend);
+void undo_push_lattice(struct bContext *C, char *name);
+
+/* editkey.c */
+void insert_shapekey(struct Scene *scene, struct Object *ob);
+void delete_key(struct Scene *scene, struct Object *ob);
+void key_to_mesh(struct KeyBlock *kb, struct Mesh *me);
+void mesh_to_key(struct Mesh *me, struct KeyBlock *kb);
+void key_to_latt(struct KeyBlock *kb, struct Lattice *lt);
+void latt_to_key(struct Lattice *lt, struct KeyBlock *kb);
+void key_to_curve(struct KeyBlock *kb, struct Curve *cu, struct ListBase *nurb);
+void curve_to_key(struct Curve *cu, struct KeyBlock *kb, struct ListBase *nurb);
+
+
+
+#endif /* ED_OBJECT_H */
+
diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h
new file mode 100644
index 00000000000..0e5d7302837
--- /dev/null
+++ b/source/blender/editors/include/ED_particle.h
@@ -0,0 +1,74 @@
+/*
+ * $Id: ED_editparticle.h $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by Janne Karhu.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_PARTICLE_H
+#define ED_PARTICLE_H
+
+struct bContext;
+struct Object;
+struct ParticleEditSettings;
+struct ParticleSystem;
+struct RadialControl;
+struct rcti;
+struct wmWindowManager;
+
+/* particle edit mode */
+void PE_change_act(void *ob_v, void *act_v);
+void PE_change_act_psys(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
+int PE_can_edit(struct ParticleSystem *psys);
+
+/* access */
+struct ParticleSystem *PE_get_current(struct Scene *scene, struct Object *ob);
+short PE_get_current_num(struct Object *ob);
+int PE_minmax(struct Scene *scene, float *min, float *max);
+struct ParticleEditSettings *PE_settings(Scene *scene);
+
+/* update calls */
+void PE_hide_keys_time(struct Scene *scene, struct ParticleSystem *psys, float cfra);
+void PE_update_object(struct Scene *scene, struct Object *ob, int useflag);
+
+/* selection tools */
+int PE_mouse_particles(struct bContext *C, short *mval, int extend);
+int PE_border_select(struct bContext *C, struct rcti *rect, int select);
+int PE_circle_select(struct bContext *C, int selecting, short *mval, float rad);
+int PE_lasso_select(struct bContext *C, short mcords[][2], short moves, short select);
+
+/* undo */
+void PE_undo_push(Scene *scene, char *str);
+void PE_undo_step(Scene *scene, int step);
+void PE_undo(Scene *scene);
+void PE_redo(Scene *scene);
+void PE_undo_menu(Scene *scene, Object *ob);
+
+/* operators */
+void ED_operatortypes_particle(void);
+void ED_keymap_particle(struct wmWindowManager *wm);
+
+#endif /* ED_PARTICLE_H */
+
diff --git a/source/blender/editors/include/ED_previewrender.h b/source/blender/editors/include/ED_previewrender.h
new file mode 100644
index 00000000000..e74f19af110
--- /dev/null
+++ b/source/blender/editors/include/ED_previewrender.h
@@ -0,0 +1,79 @@
+/**
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_PREVIEWRENDER_H
+#define ED_PREVIEWRENDER_H
+
+#include "DNA_vec_types.h"
+
+struct View3D;
+struct SpaceButs;
+struct RenderInfo;
+struct Image;
+struct ScrArea;
+struct uiBlock;
+struct Render;
+struct bContext;
+struct ID;
+
+#define PREVIEW_RENDERSIZE 140
+
+typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
+
+/* stores rendered preview - is also used for icons */
+typedef struct RenderInfo {
+ int pr_rectx;
+ int pr_recty;
+ short curtile, tottile, status;
+ rcti disprect; /* storage for view3d preview rect */
+ unsigned int* rect;
+ struct Render *re; /* persistant render */
+} RenderInfo;
+
+/* ri->status */
+#define PR_DBASE 1
+#define PR_DISPRECT 2
+#define PR_PROJECTED 4
+#define PR_ROTATED 8
+
+/* Render the preview
+
+pr_method:
+- PR_DRAW_RENDER: preview is rendered and drawn, as indicated by called context (buttons panel)
+- PR_ICON_RENDER: the preview is not drawn and the function is not dynamic,
+ so no events are processed. Hopefully fast enough for at least 32x32
+- PR_DO_RENDER: preview is rendered, not drawn, but events are processed for afterqueue,
+ in use for node editor now.
+*/
+
+#define PR_DRAW_RENDER 0
+#define PR_ICON_RENDER 1
+#define PR_DO_RENDER 2
+
+void ED_preview_init_dbase(void);
+void ED_preview_free_dbase(void);
+
+void ED_preview_shader_job(const struct bContext *C, void *owner, struct ID *id, int sizex, int sizey);
+
+
+#endif
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
new file mode 100644
index 00000000000..847120a5804
--- /dev/null
+++ b/source/blender/editors/include/ED_screen.h
@@ -0,0 +1,138 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_SCREEN_H
+#define ED_SCREEN_H
+
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view2d_types.h"
+#include "DNA_view3d_types.h"
+
+struct wmWindowManager;
+struct wmWindow;
+struct wmNotifier;
+struct wmEvent;
+struct bContext;
+struct SpaceType;
+struct Scene;
+struct bScreen;
+struct ARegion;
+struct uiBlock;
+struct rcti;
+
+/* regions */
+void ED_region_do_listen(struct ARegion *ar, struct wmNotifier *note);
+void ED_region_do_draw(struct bContext *C, struct ARegion *ar);
+void ED_region_exit(struct bContext *C, struct ARegion *ar);
+void ED_region_pixelspace(struct ARegion *ar);
+void ED_region_init(struct bContext *C, struct ARegion *ar);
+void ED_region_tag_redraw(struct ARegion *ar);
+void ED_region_tag_redraw_partial(struct ARegion *ar, struct rcti *rct);
+
+/* spaces */
+void ED_spacetypes_init(void);
+void ED_spacetypes_keymap(struct wmWindowManager *wm);
+int ED_area_header_standardbuttons(const struct bContext *C, struct uiBlock *block, int yco);
+void ED_area_overdraw(struct bContext *C);
+void ED_area_overdraw_flush(struct bContext *C, struct ScrArea *sa, struct ARegion *ar);
+
+
+/* areas */
+void ED_area_initialize(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *sa);
+void ED_area_exit(struct bContext *C, struct ScrArea *sa);
+int ED_screen_area_active(const struct bContext *C);
+void ED_area_do_listen(ScrArea *sa, struct wmNotifier *note);
+void ED_area_tag_redraw(ScrArea *sa);
+void ED_area_tag_refresh(ScrArea *sa);
+void ED_area_do_refresh(struct bContext *C, ScrArea *sa);
+void ED_area_headerprint(ScrArea *sa, const char *str);
+void ED_area_newspace(struct bContext *C, ScrArea *sa, int type);
+void ED_area_prevspace(struct bContext *C);
+void ED_area_swapspace(struct bContext *C, ScrArea *sa1, ScrArea *sa2);
+
+/* screens */
+void ED_screens_initialize(struct wmWindowManager *wm);
+void ED_screen_draw(struct wmWindow *win);
+void ED_screen_refresh(struct wmWindowManager *wm, struct wmWindow *win);
+void ED_screen_do_listen(struct wmWindow *win, struct wmNotifier *note);
+bScreen *ED_screen_duplicate(struct wmWindow *win, struct bScreen *sc);
+void ED_screen_set(struct bContext *C, struct bScreen *sc);
+void ED_screen_set_scene(struct bContext *C, struct Scene *scene);
+void ED_screen_set_subwinactive(struct wmWindow *win, struct wmEvent *event);
+void ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen);
+void ED_screen_animation_timer(struct bContext *C, int enable);
+int ED_screen_full_newspace(struct bContext *C, ScrArea *sa, int type);
+void ED_screen_full_prevspace(struct bContext *C);
+
+/* anim */
+void ED_update_for_newframe(const struct bContext *C, int mute);
+unsigned int ED_screen_view3d_layers(struct bScreen *screen);
+
+void ED_operatortypes_screen(void);
+void ED_keymap_screen(struct wmWindowManager *wm);
+
+/* operators; context poll callbacks */
+int ED_operator_screenactive(struct bContext *C);
+int ED_operator_screen_mainwinactive(struct bContext *C);
+int ED_operator_areaactive(struct bContext *C);
+int ED_operator_regionactive(struct bContext *C);
+
+int ED_operator_scene_editable(struct bContext *C);
+
+int ED_operator_view3d_active(struct bContext *C);
+int ED_operator_timeline_active(struct bContext *C);
+int ED_operator_outliner_active(struct bContext *C);
+int ED_operator_file_active(struct bContext *C);
+int ED_operator_action_active(struct bContext *C);
+int ED_operator_buttons_active(struct bContext *C);
+int ED_operator_node_active(struct bContext *C);
+int ED_operator_ipo_active(struct bContext *C);
+int ED_operator_sequencer_active(struct bContext *C);
+int ED_operator_image_active(struct bContext *C);
+
+int ED_operator_object_active(struct bContext *C);
+int ED_operator_editmesh(struct bContext *C);
+int ED_operator_editarmature(struct bContext *C);
+int ED_operator_editcurve(struct bContext *C);
+int ED_operator_editsurf(struct bContext *C);
+int ED_operator_editsurfcurve(struct bContext *C);
+int ED_operator_editfont(struct bContext *C);
+int ED_operator_uvedit(struct bContext *C);
+int ED_operator_uvmap(struct bContext *C);
+int ED_operator_posemode(struct bContext *C);
+
+
+/* default keymaps, bitflags */
+#define ED_KEYMAP_UI 1
+#define ED_KEYMAP_VIEW2D 2
+#define ED_KEYMAP_MARKERS 4
+#define ED_KEYMAP_ANIMATION 8
+#define ED_KEYMAP_FRAMES 16
+
+#endif /* ED_SCREEN_H */
+
diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h
new file mode 100644
index 00000000000..7910351f318
--- /dev/null
+++ b/source/blender/editors/include/ED_screen_types.h
@@ -0,0 +1,57 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_SCREEN_TYPES_H__
+#define ED_SCREEN_TYPES_H__
+
+typedef struct AZone {
+ struct AZone *next, *prev;
+ int type;
+ short flag;
+ short do_draw;
+ int pos;
+ short x1, y1, x2, y2;
+} AZone;
+
+/* actionzone type */
+#define AZONE_TRI 1
+#define AZONE_QUAD 2
+
+/* actionzone flag */
+
+/* actionzone pos */
+#define AZONE_S 1
+#define AZONE_SW 2
+#define AZONE_W 3
+#define AZONE_NW 4
+#define AZONE_N 5
+#define AZONE_NE 6
+#define AZONE_E 7
+#define AZONE_SE 8
+
+#endif /* ED_SCREEN_TYPES_H__ */
diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h
new file mode 100644
index 00000000000..c6a8881a0c6
--- /dev/null
+++ b/source/blender/editors/include/ED_sculpt.h
@@ -0,0 +1,45 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Nicholas Bishop
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_SCULPT_H
+#define ED_SCULPT_H
+
+struct bContext;
+struct wmWindowManager;
+
+/* sculpt.c */
+void ED_operatortypes_sculpt(void);
+void ED_keymap_sculpt(struct wmWindowManager *wm);
+
+/* paint_ops.c */
+void ED_operatortypes_paint(void);
+
+/* paint_image.c */
+void undo_imagepaint_step(int step);
+void undo_imagepaint_clear(void);
+
+#endif
diff --git a/source/blender/editors/include/ED_sequencer.h b/source/blender/editors/include/ED_sequencer.h
new file mode 100644
index 00000000000..2a3b5445dfe
--- /dev/null
+++ b/source/blender/editors/include/ED_sequencer.h
@@ -0,0 +1,31 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009, Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_SEQUENCER_H
+#define ED_SEQUENCER_H
+
+#define SEQ_ZOOM_FAC(szoom) (szoom > 0)? (szoom) : (szoom == 0)? (1.0) : (-1.0/szoom)
+
+
+#endif /* ED_SEQUENCER_H */
diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h
new file mode 100644
index 00000000000..08d2894ddf7
--- /dev/null
+++ b/source/blender/editors/include/ED_space_api.h
@@ -0,0 +1,70 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_SPACE_API_H
+#define ED_SPACE_API_H
+
+struct ARegionType;
+struct bContext;
+
+/* the pluginnable API for export to editors */
+
+/* calls for registering default spaces */
+void ED_spacetype_outliner(void);
+void ED_spacetype_time(void);
+void ED_spacetype_view3d(void);
+void ED_spacetype_ipo(void);
+void ED_spacetype_image(void);
+void ED_spacetype_node(void);
+void ED_spacetype_buttons(void);
+void ED_spacetype_info(void);
+void ED_spacetype_file(void);
+void ED_spacetype_sound(void);
+void ED_spacetype_action(void);
+void ED_spacetype_nla(void);
+void ED_spacetype_script(void);
+void ED_spacetype_text(void);
+void ED_spacetype_sequencer(void);
+
+/* calls for instancing and freeing spacetype static data
+ called in WM_init_exit */
+/* in space_file.c */
+void ED_file_init(void);
+void ED_file_exit(void);
+
+#define REGION_DRAW_PRE 1
+#define REGION_DRAW_POST 0
+
+void *ED_region_draw_cb_activate(struct ARegionType *,
+ void (*draw)(const struct bContext *, struct ARegion *, void *),
+ void *custumdata, int type);
+void ED_region_draw_cb_draw(const struct bContext *, struct ARegion *, int);
+void ED_region_draw_cb_exit(struct ARegionType *, void *);
+
+#endif /* ED_SPACE_API_H */
+
diff --git a/source/blender/editors/include/ED_text.h b/source/blender/editors/include/ED_text.h
new file mode 100644
index 00000000000..873777affe8
--- /dev/null
+++ b/source/blender/editors/include/ED_text.h
@@ -0,0 +1,36 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_TEXT_H
+#define ED_TEXT_H
+
+struct bContext;
+
+void ED_text_undo_step(struct bContext *C, int step);
+
+#endif /* ED_TEXT_H */
+
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
new file mode 100644
index 00000000000..1d47d8ad190
--- /dev/null
+++ b/source/blender/editors/include/ED_transform.h
@@ -0,0 +1,33 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_TRANSFORM_H
+#define ED_TRANSFORM_H
+
+
+#endif /* ED_TRANSFORM_H */
+
diff --git a/source/blender/editors/include/ED_types.h b/source/blender/editors/include/ED_types.h
new file mode 100644
index 00000000000..2ff89f97e98
--- /dev/null
+++ b/source/blender/editors/include/ED_types.h
@@ -0,0 +1,54 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_TYPES_H
+#define ED_TYPES_H
+
+/* **************** GENERAL EDITOR-WIDE TYPES AND DEFINES ************************** */
+
+/* old blender defines... should be depricated? */
+#define DESELECT 0
+#define SELECT 1
+#define ACTIVE 2
+
+/* nonstandard define, sometimes in math.h */
+#ifndef MAXFLOAT
+#define MAXFLOAT ((float)3.40282347e+38)
+#endif
+
+/* buttons */
+#define XIC 20
+#define YIC 20
+
+/* proposal = put scene pointers on function calls? */
+#define BASACT (scene->basact)
+#define OBACT (BASACT? BASACT->object: 0)
+
+
+
+#endif /* ED_TYPES_H */
+
diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h
new file mode 100644
index 00000000000..7ccbf1ff18d
--- /dev/null
+++ b/source/blender/editors/include/ED_util.h
@@ -0,0 +1,74 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_UTIL_H
+#define ED_UTIL_H
+
+struct Object;
+struct bContext;
+struct ARegion;
+struct uiBlock;
+struct wmOperator;
+struct wmOperatorType;
+
+/* ed_util.c */
+
+void ED_editors_exit (struct bContext *C);
+
+/* ************** Undo ************************ */
+
+/* undo.c */
+void ED_undo_push (struct bContext *C, char *str);
+void ED_undo_push_op (struct bContext *C, struct wmOperator *op);
+void ED_undo_pop (struct bContext *C);
+void ED_undo_redo (struct bContext *C);
+void ED_OT_undo (struct wmOperatorType *ot);
+void ED_OT_redo (struct wmOperatorType *ot);
+
+/* undo_editmode.c */
+void undo_editmode_push(struct bContext *C, char *name,
+ void * (*getdata)(struct bContext *C),
+ void (*freedata)(void *),
+ void (*to_editmode)(void *, void *),
+ void *(*from_editmode)(void *),
+ int (*validate_undo)(void *, void *));
+
+
+void *undo_editmode_get_prev (struct Object *ob);
+struct uiBlock *editmode_undohistorymenu(struct bContext *C, struct ARegion *ar, void *arg_unused);
+void undo_editmode_menu (struct bContext *C);
+void undo_editmode_clear (void);
+void undo_editmode_step (struct bContext *C, int step);
+
+
+/* ************** XXX OLD CRUFT WARNING ************* */
+
+void apply_keyb_grid(int shift, int ctrl, float *val, float fac1, float fac2, float fac3, int invert);
+int GetButStringLength(char *str);
+
+#endif /* ED_UTIL_H */
+
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
new file mode 100644
index 00000000000..74a9be75db6
--- /dev/null
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -0,0 +1,63 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_UVEDIT_H
+#define ED_UVEDIT_H
+
+struct bContext;
+struct Scene;
+struct Object;
+struct MTFace;
+struct EditFace;
+struct Image;
+struct wmWindowManager;
+
+/* uvedit_ops.c */
+void ED_operatortypes_uvedit(void);
+void ED_keymap_uvedit(struct wmWindowManager *wm);
+
+void ED_uvedit_assign_image(struct Scene *scene, struct Object *obedit, struct Image *ima, struct Image *previma);
+void ED_uvedit_set_tile(struct bContext *C, struct Scene *scene, struct Object *obedit, struct Image *ima, int curtile, int dotile);
+int ED_uvedit_minmax(struct Scene *scene, struct Image *ima, struct Object *obedit, float *min, float *max);
+
+int ED_uvedit_test_silent(struct Object *obedit);
+int ED_uvedit_test(struct Object *obedit);
+
+int uvedit_face_visible(struct Scene *scene, struct Image *ima, struct EditFace *efa, struct MTFace *tf);
+int uvedit_face_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf);
+int uvedit_edge_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
+int uvedit_uv_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
+
+int ED_uvedit_nearest_uv(struct Scene *scene, struct Object *obedit, struct Image *ima, float co[2], float uv[2]);
+
+/* uvedit_unwrap.c */
+void ED_uvedit_live_unwrap_begin(struct Scene *scene, struct Object *obedit);
+void ED_uvedit_live_unwrap_re_solve(void);
+void ED_uvedit_live_unwrap_end(short cancel);
+
+#endif /* ED_UVEDIT_H */
+
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
new file mode 100644
index 00000000000..fbe6362db7c
--- /dev/null
+++ b/source/blender/editors/include/ED_view3d.h
@@ -0,0 +1,138 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_VIEW3D_H
+#define ED_VIEW3D_H
+
+/* ********* exports for space_view3d/ module ********** */
+struct ARegion;
+struct View3D;
+struct RegionView3D;
+struct ViewContext;
+struct bglMats;
+struct BPoint;
+struct Nurb;
+struct BezTriple;
+struct EditVert;
+struct EditEdge;
+struct EditFace;
+struct ImBuf;
+struct Scene;
+struct bContext;
+
+/* for derivedmesh drawing callbacks, for view3d_select, .... */
+typedef struct ViewContext {
+ Scene *scene;
+ Object *obact;
+ Object *obedit;
+ struct ARegion *ar;
+ struct View3D *v3d;
+ struct RegionView3D *rv3d;
+ struct EditMesh *em;
+ short mval[2];
+} ViewContext;
+
+typedef struct ViewDepths {
+ unsigned short w, h;
+ float *depths;
+ double depth_range[2];
+
+ char damaged;
+} ViewDepths;
+
+
+float *give_cursor(struct Scene *scene, struct View3D *v3d);
+
+void initgrabz(struct RegionView3D *rv3d, float x, float y, float z);
+void window_to_3d(struct ARegion *ar, float *vec, short mx, short my);
+void window_to_3d_delta(struct ARegion *ar, float *vec, short mx, short my);
+
+/* Depth buffer */
+float read_cached_depth(struct ViewContext *vc, int x, int y);
+void request_depth_update(struct RegionView3D *rv3d);
+
+/* Projection */
+#define IS_CLIPPED 12000
+
+void project_short(struct ARegion *ar, float *vec, short *adr);
+void project_short_noclip(struct ARegion *ar, float *vec, short *adr);
+
+void project_int(struct ARegion *ar, float *vec, int *adr);
+void project_int_noclip(struct ARegion *ar, float *vec, int *adr);
+
+void project_float(struct ARegion *ar, float *vec, float *adr);
+void project_float_noclip(struct ARegion *ar, float *vec, float *adr);
+
+void viewline(struct ARegion *ar, struct View3D *v3d, short mval[2], float ray_start[3], float ray_end[3]);
+void viewray(struct ARegion *ar, struct View3D *v3d, short mval[2], float ray_start[3], float ray_normal[3]);
+
+int get_view3d_viewplane(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize);
+int get_view3d_ortho(struct View3D *v3d, struct RegionView3D *rv3d);
+void view3d_get_object_project_mat(struct RegionView3D *v3d, struct Object *ob, float pmat[4][4], float vmat[4][4]);
+void view3d_project_float(struct ARegion *a, float *vec, float *adr, float mat[4][4]);
+
+/* drawobject.c itterators */
+void mesh_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct EditVert *eve, int x, int y, int index), void *userData, int clipVerts);
+void mesh_foreachScreenEdge(struct ViewContext *vc, void (*func)(void *userData, struct EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts);
+void mesh_foreachScreenFace(struct ViewContext *vc, void (*func)(void *userData, struct EditFace *efa, int x, int y, int index), void *userData);
+void nurbs_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct Nurb *nu, struct BPoint *bp, struct BezTriple *bezt, int beztindex, int x, int y), void *userData);
+void lattice_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct BPoint *bp, int x, int y), void *userData);
+
+int view3d_test_clipping(struct RegionView3D *rv3d, float *vec);
+void view3d_align_axis_to_vector(struct View3D *v3d, struct RegionView3D *rv3d, int axisidx, float vec[3]);
+
+void drawcircball(int mode, float *cent, float rad, float tmat[][4]);
+
+/* backbuffer select and draw support */
+void view3d_validate_backbuf(struct ViewContext *vc);
+struct ImBuf *view3d_read_backbuf(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
+unsigned int view3d_sample_backbuf_rect(struct ViewContext *vc, short mval[2], int size, unsigned int min, unsigned int max, int *dist, short strict,
+ void *handle, unsigned int (*indextest)(void *handle, unsigned int index));
+unsigned int view3d_sample_backbuf(struct ViewContext *vc, int x, int y);
+
+int view_autodist(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, short *mval, float mouse_worldloc[3]);
+
+/* select */
+#define MAXPICKBUF 10000
+short view3d_opengl_select(struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, rcti *input);
+
+void view3d_set_viewcontext(struct bContext *C, struct ViewContext *vc);
+void view3d_operator_needs_opengl(const struct bContext *C);
+void view3d_get_view_aligned_coordinate(struct ViewContext *vc, float *fp, short mval[2]);
+void view3d_get_object_project_mat(struct RegionView3D *v3d, struct Object *ob, float pmat[4][4], float vmat[4][4]);;
+void view3d_get_transformation(struct ViewContext *vc, struct Object *ob, struct bglMats *mats);
+
+/* XXX should move to arithb.c */
+int edge_inside_circle(short centx, short centy, short rad, short x1, short y1, short x2, short y2);
+int lasso_inside(short mcords[][2], short moves, short sx, short sy);
+int lasso_inside_edge(short mcords[][2], short moves, int x0, int y0, int x1, int y1);
+
+/* modes */
+void ED_view3d_exit_paint_modes(struct bContext *C);
+
+#endif /* ED_VIEW3D_H */
+
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
new file mode 100644
index 00000000000..5a827a2311b
--- /dev/null
+++ b/source/blender/editors/include/UI_interface.h
@@ -0,0 +1,617 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef UI_INTERFACE_H
+#define UI_INTERFACE_H
+
+/* Struct Declarations */
+
+struct ID;
+struct Main;
+struct ListBase;
+struct ARegion;
+struct ScrArea;
+struct wmWindow;
+struct wmWindowManager;
+struct wmOperator;
+struct AutoComplete;
+struct bContext;
+struct Panel;
+struct PanelType;
+struct PointerRNA;
+struct PropertyRNA;
+struct ReportList;
+struct rcti;
+struct uiFontStyle;
+
+typedef struct uiBut uiBut;
+typedef struct uiBlock uiBlock;
+typedef struct uiPopupBlockHandle uiPopupBlockHandle;
+
+/* Defines */
+
+/* uiBlock->dt */
+#define UI_EMBOSS 0 /* use widget style for drawing */
+#define UI_EMBOSSN 1 /* Nothing, only icon and/or text */
+#define UI_EMBOSSP 2 /* Pulldown menu style */
+#define UI_EMBOSST 3 /* Table */
+
+/* uiBlock->direction */
+#define UI_TOP 1
+#define UI_DOWN 2
+#define UI_LEFT 4
+#define UI_RIGHT 8
+#define UI_DIRECTION 15
+#define UI_CENTER 16
+#define UI_SHIFT_FLIPPED 32
+
+/* uiBlock->autofill (not yet used) */
+#define UI_BLOCK_COLLUMNS 1
+#define UI_BLOCK_ROWS 2
+
+/* uiBlock->flag (controls) */
+#define UI_BLOCK_LOOP 1
+#define UI_BLOCK_REDRAW 2
+#define UI_BLOCK_RET_1 4 /* XXX 2.5 not implemented */
+#define UI_BLOCK_NUMSELECT 8
+#define UI_BLOCK_ENTER_OK 16
+#define UI_BLOCK_NOSHADOW 32
+#define UI_BLOCK_NO_HILITE 64 /* XXX 2.5 not implemented */
+#define UI_BLOCK_MOVEMOUSE_QUIT 128
+#define UI_BLOCK_KEEP_OPEN 256
+#define UI_BLOCK_POPUP 512
+
+/* uiPopupBlockHandle->menuretval */
+#define UI_RETURN_CANCEL 1 /* cancel all menus cascading */
+#define UI_RETURN_OK 2 /* choice made */
+#define UI_RETURN_OUT 4 /* left the menu */
+
+ /* block->flag bits 12-15 are identical to but->flag bits */
+
+/* panel controls */
+#define UI_PNL_TRANSP 1
+#define UI_PNL_SOLID 2
+
+#define UI_PNL_CLOSE 32
+#define UI_PNL_STOW 64
+#define UI_PNL_TO_MOUSE 128
+#define UI_PNL_UNSTOW 256
+#define UI_PNL_SCALE 512
+
+/* warning the first 6 flags are internal */
+/* but->flag */
+#define UI_TEXT_LEFT 64
+#define UI_ICON_LEFT 128
+#define UI_ICON_RIGHT 256
+ /* control for button type block */
+#define UI_MAKE_TOP 512
+#define UI_MAKE_DOWN 1024
+#define UI_MAKE_LEFT 2048
+#define UI_MAKE_RIGHT 4096
+
+ /* button align flag, for drawing groups together */
+#define UI_BUT_ALIGN (15<<14)
+#define UI_BUT_ALIGN_TOP (1<<14)
+#define UI_BUT_ALIGN_LEFT (1<<15)
+#define UI_BUT_ALIGN_RIGHT (1<<16)
+#define UI_BUT_ALIGN_DOWN (1<<17)
+
+#define UI_BUT_DISABLED (1<<18)
+ /* dont draw hilite on mouse over */
+#define UI_NO_HILITE (1<<19)
+#define UI_BUT_ANIMATED (1<<20)
+#define UI_BUT_ANIMATED_KEY (1<<21)
+#define UI_BUT_DRIVEN (1<<22)
+
+
+/* Button types, bits stored in 1 value... and a short even!
+- bits 0-4: bitnr (0-31)
+- bits 5-7: pointer type
+- bit 8: for 'bit'
+- bit 9-15: button type (now 6 bits, 64 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 ICONTEXTROW (25<<9)
+#define HSVCUBE (26<<9)
+#define PULLDOWN (27<<9)
+#define ROUNDBOX (28<<9)
+#define CHARTAB (29<<9)
+#define BUT_COLORBAND (30<<9)
+#define BUT_NORMAL (31<<9)
+#define BUT_CURVE (32<<9)
+#define BUT_TOGDUAL (33<<9)
+#define ICONTOGN (34<<9)
+#define FTPREVIEW (35<<9)
+#define NUMABS (36<<9)
+#define HMENU (37<<9)
+#define TOGBUT (38<<9)
+#define BUTTYPE (63<<9)
+
+/* Drawing
+ *
+ * Functions to draw various shapes, taking theme settings into account.
+ * Used for code that draws its own UI style elements. */
+
+void uiEmboss(float x1, float y1, float x2, float y2, int sel);
+void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad);
+void uiSetRoundBox(int type);
+int uiGetRoundBox(void);
+void uiRoundRect(float minx, float miny, float maxx, float maxy, float rad);
+void uiDrawMenuBox(float minx, float miny, float maxx, float maxy, short flag, short direction);
+void uiDrawBoxShadow(unsigned char alpha, float minx, float miny, float maxx, float maxy);
+
+/* Menus
+ *
+ * These functions are used by popup menus, toolbox and header menus. They
+ * assume uiMenuItem head is already created, which is done by uiMenuButton
+ * for header menus, or can be done with uiPupMenuBegin for popups. These
+ * functions do not use uiDefBut functions in order to simplify creating
+ * them, and to permit other types of menus (radial, ..) in the future. */
+
+typedef struct uiMenuItem uiMenuItem;
+
+typedef void (*uiMenuCreateFunc)(struct bContext *C, uiMenuItem *head, void *arg1);
+typedef void (*uiMenuHandleFunc)(struct bContext *C, void *arg, int event);
+
+void uiMenuFunc(uiMenuItem *head, uiMenuHandleFunc handlefunc, void *argv);
+void uiMenuContext(uiMenuItem *head, int opcontext);
+
+void uiMenuItemVal(uiMenuItem *head, const char *name, int icon, int argval);
+
+void uiMenuItemEnumO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, int value);
+void uiMenuItemBooleanO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, int value);
+void uiMenuItemsEnumO(uiMenuItem *head, char *opname, char *propname);
+void uiMenuItemIntO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, int value);
+void uiMenuItemFloatO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, float value);
+void uiMenuItemStringO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, char *value);
+void uiMenuItemO(uiMenuItem *head, int icon, char *opname);
+
+void uiMenuItemBooleanR(uiMenuItem *head, struct PointerRNA *ptr, char *propname);
+void uiMenuItemEnumR(uiMenuItem *head, struct PointerRNA *ptr, char *propname, int value);
+void uiMenuItemsEnumR(uiMenuItem *head, struct PointerRNA *ptr, char *propname);
+
+void uiMenuLevel(uiMenuItem *head, const char *name, uiMenuCreateFunc newlevel);
+void uiMenuLevelEnumO(uiMenuItem *head, char *opname, char *propname);
+void uiMenuLevelEnumR(uiMenuItem *head, struct PointerRNA *ptr, char *propname);
+
+void uiMenuSeparator(uiMenuItem *head);
+
+/* Popup Menus
+ *
+ * Functions used to create popup menus. For more extended menus the
+ * uiPupMenuBegin/End functions can be used to define own items with
+ * the uiMenu functions inbetween. If it is a simple confirmation menu
+ * or similar, popups can be created with a single function call. */
+
+uiMenuItem *uiPupMenuBegin(const char *title, int icon);
+void uiPupMenuEnd(struct bContext *C, struct uiMenuItem *head);
+
+void uiPupMenuOkee(struct bContext *C, char *opname, char *str, ...);
+void uiPupMenuSaveOver(struct bContext *C, struct wmOperator *op, char *filename);
+void uiPupMenuNotice(struct bContext *C, char *str, ...);
+void uiPupMenuError(struct bContext *C, char *str, ...);
+void uiPupMenuReports(struct bContext *C, struct ReportList *reports);
+
+void uiPupMenuSetActive(int val);
+
+/* Popup Blocks
+ *
+ * Functions used to create popup blocks. These are like popup menus
+ * but allow using all button types and creating an own layout. */
+
+typedef uiBlock* (*uiBlockCreateFunc)(struct bContext *C, struct ARegion *ar, void *arg1);
+
+void uiPupBlock(struct bContext *C, uiBlockCreateFunc func, void *arg);
+void uiPupBlockO(struct bContext *C, uiBlockCreateFunc func, void *arg, char *opname, int opcontext);
+
+/* Blocks
+ *
+ * Functions for creating, drawing and freeing blocks. A Block is a
+ * container of buttons and used for various purposes.
+ *
+ * Begin/Define Buttons/End/Draw is the typical order in which these
+ * function should be called, though for popup blocks Draw is left out.
+ * Freeing blocks is done by the screen/ module automatically.
+ *
+ * */
+
+uiBlock *uiBeginBlock(const struct bContext *C, struct ARegion *region, const char *name, short dt);
+void uiEndBlock(const struct bContext *C, uiBlock *block);
+void uiDrawBlock(const struct bContext *C, struct uiBlock *block);
+
+uiBlock *uiGetBlock(char *name, struct ARegion *ar);
+
+void uiBlockSetEmboss(uiBlock *block, short dt);
+
+void uiFreeBlock(const struct bContext *C, uiBlock *block);
+void uiFreeBlocks(const struct bContext *C, struct ListBase *lb);
+void uiFreeInactiveBlocks(const struct bContext *C, struct ListBase *lb);
+
+void uiBlockSetButLock(uiBlock *block, int val, char *lockstr);
+void uiBlockClearButLock(uiBlock *block);
+
+/* automatic aligning, horiz or verical */
+void uiBlockBeginAlign(uiBlock *block);
+void uiBlockEndAlign(uiBlock *block);
+
+void uiBoundsBlock(struct uiBlock *block, int addval);
+void uiTextBoundsBlock(uiBlock *block, int addval);
+void uiPopupBoundsBlock(uiBlock *block, int addval, int mx, int my);
+void uiMenuPopupBoundsBlock(uiBlock *block, int addvall, int mx, int my);
+
+int uiBlocksGetYMin (struct ListBase *lb);
+
+void uiBlockSetDirection (uiBlock *block, int direction);
+void uiBlockFlipOrder (uiBlock *block);
+void uiBlockSetFlag (uiBlock *block, int flag);
+void uiBlockClearFlag (uiBlock *block, int flag);
+void uiBlockSetXOfs (uiBlock *block, int xofs);
+
+int uiButGetRetVal (uiBut *but);
+
+void uiButSetFlag (uiBut *but, int flag);
+void uiButClearFlag (uiBut *but, int flag);
+
+/* Buttons
+ *
+ * Functions to define various types of buttons in a block. Postfixes:
+ * - F: float
+ * - I: int
+ * - S: short
+ * - C: char
+ * - R: RNA
+ * - O: operator */
+
+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 *uiDefButBitF(uiBlock *block, int type, int bit, 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 *uiDefButBitI(uiBlock *block, int type, int bit, 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 *uiDefButBitS(uiBlock *block, int type, int bit, 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 *uiDefButBitC(uiBlock *block, int type, int bit, 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 *uiDefButR(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, struct PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefButO(uiBlock *block, int type, char *opname, int opcontext, char *str, short x1, short y1, short x2, short y2, 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 *uiDefIconButBitF(uiBlock *block, int type, int bit, 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 *uiDefIconButBitI(uiBlock *block, int type, int bit, 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 *uiDefIconButBitS(uiBlock *block, int type, int bit, 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);
+uiBut *uiDefIconButBitC(uiBlock *block, int type, int bit, int retval, int icon, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefIconButR(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, struct PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefIconButO(uiBlock *block, int type, char *opname, int opcontext, int icon, short x1, short y1, short x2, short y2, char *tip);
+
+uiBut *uiDefIconTextBut(uiBlock *block,
+ int type, int retval, int icon, char *str,
+ short x1, short y1,
+ short x2, short y2,
+ void *poin,
+ float min, float max,
+ float a1, float a2, char *tip);
+uiBut *uiDefIconTextButF(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefIconTextButBitF(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefIconTextButI(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefIconTextButBitI(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefIconTextButS(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefIconTextButBitS(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefIconTextButC(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefIconTextButBitC(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefIconTextButR(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, struct PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefIconTextButO(uiBlock *block, int type, char *opname, int opcontext, int icon, char *str, short x1, short y1, short x2, short y2, char *tip);
+
+/* for passing inputs to ButO buttons */
+struct PointerRNA *uiButGetOperatorPtrRNA(uiBut *but);
+
+/* Special Buttons
+ *
+ * Butons with a more specific purpose:
+ * - IDPoinBut: for creating buttons that work on a pointer to an ID block.
+ * - MenuBut: buttons that popup a menu (in headers usually).
+ * - PulldownBut: like MenuBut, but creating a uiBlock (for compatibility).
+ * - BlockBut: buttons that popup a block with more buttons.
+ * - KeyevtBut: buttons that can be used to turn key events into values.
+ * - PickerButtons: buttons like the color picker (for code sharing).
+ * - AutoButR: RNA property button with type automatically defined. */
+
+#define UI_ID_RENAME 1
+#define UI_ID_BROWSE 2
+#define UI_ID_ADD_NEW 4
+#define UI_ID_OPEN 8
+#define UI_ID_ALONE 16
+#define UI_ID_DELETE 32
+#define UI_ID_LOCAL 64
+#define UI_ID_AUTO_NAME 128
+#define UI_ID_FAKE_USER 256
+#define UI_ID_PIN 512
+#define UI_ID_BROWSE_RENDER 1024
+#define UI_ID_FULL (UI_ID_RENAME|UI_ID_BROWSE|UI_ID_ADD_NEW|UI_ID_OPEN|UI_ID_ALONE|UI_ID_DELETE|UI_ID_LOCAL)
+
+typedef void (*uiIDPoinFuncFP)(struct bContext *C, char *str, struct ID **idpp);
+typedef void (*uiIDPoinFunc)(struct bContext *C, struct ID *id, int event);
+
+uiBut *uiDefIDPoinBut(uiBlock *block, uiIDPoinFuncFP func, short blocktype, int retval, char *str,
+ short x1, short y1, short x2, short y2, void *idpp, char *tip);
+int uiDefIDPoinButs(uiBlock *block, struct Main *main, struct ID *parid, struct ID *id, int id_code, short *pin_p, int x, int y, uiIDPoinFunc func, int events);
+
+uiBut *uiDefPulldownBut(uiBlock *block, uiBlockCreateFunc func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip);
+uiBut *uiDefMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip);
+uiBut *uiDefIconTextMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int icon, char *str, short x1, short y1, short x2, short y2, char *tip);
+
+uiBut *uiDefBlockBut(uiBlock *block, uiBlockCreateFunc func, void *func_arg1, char *str, short x1, short y1, short x2, short y2, char *tip);
+uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int retval, int icon, short x1, short y1, short x2, short y2, char *tip);
+uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int icon, 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 uiBlockPickerButtons(struct uiBlock *block, float *col, float *hsv, float *old, char *hexcol, char mode, short retval);
+
+uiBut *uiDefAutoButR(uiBlock *block, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, char *name, int icon, int x1, int y1, int x2, int y2);
+int uiDefAutoButsRNA(const struct bContext *C, uiBlock *block, struct PointerRNA *ptr);
+
+/* Links
+ *
+ * Game engine logic brick links. Non-functional currently in 2.5,
+ * code to handle and draw these is disabled internally. */
+
+void uiSetButLink(struct uiBut *but, void **poin, void ***ppoin, short *tot, int from, int to);
+
+void uiComposeLinks(uiBlock *block);
+uiBut *uiFindInlink(uiBlock *block, void *poin);
+
+/* Callbacks
+ *
+ * uiBlockSetHandleFunc/ButmFunc are for handling events through a callback.
+ * HandleFunc gets the retval passed on, and ButmFunc gets a2. The latter is
+ * mostly for compatibility with older code.
+ *
+ * uiButSetCompleteFunc is for tab completion.
+ *
+ * uiBlockSetFunc and uiButSetFunc are callbacks run when a button is used,
+ * in case events, operators or RNA are not sufficient to handle the button.
+ *
+ * uiButSetNFunc will free the argument with MEM_freeN. */
+
+typedef void (*uiButHandleFunc)(struct bContext *C, void *arg1, void *arg2);
+typedef void (*uiButHandleNFunc)(struct bContext *C, void *argN, void *arg2);
+typedef void (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg);
+typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event);
+
+void uiBlockSetHandleFunc(uiBlock *block, uiBlockHandleFunc func, void *arg);
+void uiBlockSetButmFunc (uiBlock *block, uiMenuHandleFunc func, void *arg);
+
+void uiBlockSetFunc (uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2);
+void uiButSetFunc (uiBut *but, uiButHandleFunc func, void *arg1, void *arg2);
+void uiButSetNFunc (uiBut *but, uiButHandleNFunc func, void *argN, void *arg2);
+
+void uiButSetCompleteFunc(uiBut *but, uiButCompleteFunc func, void *arg);
+
+void uiBlockSetDrawExtraFunc(uiBlock *block, void (*func)(struct bContext *C, uiBlock *block));
+
+/* Autocomplete
+ *
+ * Tab complete helper functions, for use in uiButCompleteFunc callbacks.
+ * Call begin once, then multiple times do_name with all possibilities,
+ * and finally end to finish and get the completed name. */
+
+typedef struct AutoComplete AutoComplete;
+
+AutoComplete *autocomplete_begin(char *startname, int maxlen);
+void autocomplete_do_name(AutoComplete *autocpl, const char *name);
+void autocomplete_end(AutoComplete *autocpl, char *autoname);
+
+/* Panels
+ *
+ * Functions for creating, freeing and drawing panels. The API here
+ * could use a good cleanup, though how they will function in 2.5 is
+ * not clear yet so we postpone that. */
+
+void uiBeginPanels(const struct bContext *C, struct ARegion *ar);
+void uiEndPanels(const struct bContext *C, struct ARegion *ar);
+
+struct Panel *uiBeginPanel(struct ARegion *ar, uiBlock *block, struct PanelType *pt);
+void uiEndPanel(uiBlock *block, int width, int height);
+
+void uiPanelsHome(struct ARegion *ar);
+
+/* deprecated */
+extern int uiNewPanel(const struct bContext *C, struct ARegion *ar, uiBlock *block, char *panelname, char *tabname, int ofsx, int ofsy, int sizex, int sizey);
+extern void uiNewPanelHeight(struct uiBlock *block, int sizey);
+extern void uiNewPanelTitle(struct uiBlock *block, char *str);
+
+/* Handlers
+ *
+ * Handlers that can be registered in regions, areas and windows for
+ * handling WM events. Mostly this is done automatic by modules such
+ * as screen/ if ED_KEYMAP_UI is set, or internally in popup functions. */
+
+void UI_add_region_handlers(struct ListBase *handlers);
+void UI_add_area_handlers(struct ListBase *handlers);
+void UI_add_popup_handlers(struct bContext *C, struct ListBase *handlers, uiPopupBlockHandle *menu);
+
+/* Legacy code
+ * Callbacks and utils to get 2.48 work */
+
+void test_idbutton_cb(struct bContext *C, void *namev, void *arg2);
+void test_scriptpoin_but(struct bContext *C, char *name, struct ID **idpp);
+void test_actionpoin_but(struct bContext *C, char *name, struct ID **idpp);
+void test_obpoin_but(struct bContext *C, char *name, struct ID **idpp);
+void test_meshobpoin_but(struct bContext *C, char *name, struct ID **idpp);
+void test_meshpoin_but(struct bContext *C, char *name, struct ID **idpp);
+void test_matpoin_but(struct bContext *C, char *name, struct ID **idpp);
+void test_scenepoin_but(struct bContext *C, char *name, struct ID **idpp);
+void test_grouppoin_but(struct bContext *C, char *name, struct ID **idpp);
+void test_texpoin_but(struct bContext *C, char *name, struct ID **idpp);
+void test_imapoin_but(struct bContext *C, char *name, struct ID **idpp);
+void autocomplete_bone(struct bContext *C, char *str, void *arg_v);
+void autocomplete_vgroup(struct bContext *C, char *str, void *arg_v);
+
+struct CurveMapping;
+struct rctf;
+void curvemap_buttons(uiBlock *block, struct CurveMapping *cumap, char labeltype, short event, short redraw, struct rctf *rect);
+
+
+/* Module
+ *
+ * init and exit should be called before using this module. init_userdef must
+ * be used to reinitialize some internal state if user preferences change. */
+
+void UI_init(void);
+void UI_init_userdef(void);
+void UI_exit(void);
+
+/* XXX hide this */
+
+uiBut *uiDefMenuButO(uiBlock *block, char *opname, char *name);
+uiBut *uiDefMenuSep(uiBlock *block);
+uiBut *uiDefMenuSub(uiBlock *block, uiBlockCreateFunc func, char *name);
+uiBut *uiDefMenuTogR(uiBlock *block, struct PointerRNA *ptr, char *propname, char *propvalue, char *name);
+
+/* Layout
+ *
+ * More automated layout of buttons. Has three levels:
+ * - Layout: contains a number templates, within a bounded width or height.
+ * - Template: predefined layouts for buttons with a number of slots, each
+ * slot can contain multiple items.
+ * - Item: item to put in a template slot, being either an RNA property,
+ * operator, label or menu currently. */
+
+/* layout */
+#define UI_LAYOUT_HORIZONTAL 0
+#define UI_LAYOUT_VERTICAL 1
+
+typedef struct uiLayout uiLayout;
+
+uiLayout *uiLayoutBegin(int dir, int x, int y, int size, int em);
+void uiLayoutContext(uiLayout *layout, int opcontext);
+void uiLayoutEnd(const struct bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y);
+
+/* layout specifiers */
+void uiLayoutRow(uiLayout *layout);
+void uiLayoutColumn(uiLayout *layout);
+void uiLayoutColumnFlow(uiLayout *layout, int number);
+void uiLayoutSplit(uiLayout *layout, int number, int lr);
+uiLayout *uiLayoutBox(uiLayout *layout);
+uiLayout *uiLayoutSub(uiLayout *layout, int n);
+
+/* templates */
+void uiTemplateHeaderMenus(uiLayout *layout);
+void uiTemplateHeaderButtons(uiLayout *layout);
+void uiTemplateHeaderID(uiLayout *layout, struct PointerRNA *ptr, char *propname, int flag, uiIDPoinFunc func);
+void uiTemplateSetColor(uiLayout *layout, int color);
+
+/* items */
+void uiItemO(uiLayout *layout, char *name, int icon, char *opname);
+void uiItemEnumO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value);
+void uiItemsEnumO(uiLayout *layout, char *opname, char *propname);
+void uiItemBooleanO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value);
+void uiItemIntO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value);
+void uiItemFloatO(uiLayout *layout, char *name, int icon, char *opname, char *propname, float value);
+void uiItemStringO(uiLayout *layout, char *name, int icon, char *opname, char *propname, char *value);
+void uiItemFullO(uiLayout *layout, char *name, int icon, char *idname, struct IDProperty *properties, int context);
+
+void uiItemR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, int expand);
+void uiItemFullR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, int expand);
+
+void uiItemL(uiLayout *layout, char *name, int icon);
+
+void uiItemM(uiLayout *layout, char *name, int icon, uiMenuCreateFunc func);
+
+/* utilities */
+#define UI_PANEL_WIDTH 340
+#define UI_COMPACT_PANEL_WIDTH 160
+
+typedef void (*uiHeaderCreateFunc)(const struct bContext *C, uiLayout *layout);
+typedef void (*uiPanelCreateFunc)(const struct bContext *C, uiLayout *layout);
+
+void uiRegionPanelLayout(const struct bContext *C, struct ARegion *ar, int vertical, char *context);
+void uiRegionHeaderLayout(const struct bContext *C, struct ARegion *ar);
+
+/* Animation */
+
+void uiAnimContextProperty(const struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop, int *index);
+
+/* Styled text draw */
+void uiStyleFontSet(struct uiFontStyle *fs);
+void uiStyleFontDraw(struct uiFontStyle *fs, struct rcti *rect, char *str);
+
+int UI_GetStringWidth(char *str); // XXX temp
+void UI_DrawString(float x, float y, char *str); // XXX temp
+
+#endif /* UI_INTERFACE_H */
+
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
new file mode 100644
index 00000000000..bf160b4ad68
--- /dev/null
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -0,0 +1,70 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef UI_INTERFACE_ICONS_H
+#define UI_INTERFACE_ICONS_H
+
+struct Image;
+struct ImBuf;
+struct World;
+struct Tex;
+struct Lamp;
+struct Material;
+
+typedef struct IconFile {
+ struct IconFile *next, *prev;
+ char filename[80]; // FILE_MAXFILE size
+ int index;
+} IconFile;
+
+#define ICON_DEFAULT_HEIGHT 16
+#define ICON_DEFAULT_WIDTH 16
+#define PREVIEW_DEFAULT_HEIGHT 96
+
+/*
+ Resizable Icons for Blender
+*/
+void UI_icons_init(int first_dyn_id);
+int UI_icon_get_width(int icon_id);
+int UI_icon_get_height(int icon_id);
+
+void UI_icon_draw(float x, float y, int icon_id);
+void UI_icon_draw_preview(float x, float y, int icon_id, int nocreate);
+
+void UI_icon_draw_aspect(float x, float y, int icon_id, float aspect);
+void UI_icon_draw_aspect_blended(float x, float y, int icon_id, float aspect, int shade);
+void UI_icon_draw_size_blended(float x, float y, int size, int icon_id, int shade);
+void UI_icons_free();
+void UI_icons_free_drawinfo(void *drawinfo);
+
+struct ListBase *UI_iconfile_list(void);
+int UI_iconfile_get_index(char *filename);
+
+
+#endif /* UI_INTERFACE_ICONS_H */
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
new file mode 100644
index 00000000000..e6c2dfb31e7
--- /dev/null
+++ b/source/blender/editors/include/UI_resources.h
@@ -0,0 +1,962 @@
+/**
+ * $Id: UI_resources.h 13057 2007-12-30 12:08:28Z aligorith $
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef UI_RESOURCES_H
+#define UI_RESOURCES_H
+
+/* elubie: TODO: move the typedef for icons to UI_interface_icons.h */
+/* and add/replace include of UI_resources.h by UI_interface_icons.h */
+
+typedef enum {
+#define BIFICONID_FIRST (ICON_BLENDER)
+ /* ui */
+ ICON_BLENDER,
+ ICON_HELP,
+ ICON_ERROR,
+ ICON_BLANK1, // XXX this is used lots, it's not actually 'blank'
+ ICON_TRIA_RIGHT,
+ ICON_TRIA_DOWN,
+ ICON_TRIA_LEFT,
+ ICON_TRIA_UP,
+ ICON_BLANK002,
+ ICON_PLUS,
+ ICON_DISCLOSURE_TRI_DOWN,
+ ICON_DISCLOSURE_TRI_RIGHT,
+ ICON_RADIOBUT_OFF,
+ ICON_RADIOBUT_ON,
+ ICON_MENU_PANEL,
+ ICON_PYTHON,
+ ICON_BLANK003,
+ ICON_DOT,
+ ICON_BLANK004,
+ ICON_X,
+ ICON_BLANK005,
+ ICON_GO_LEFT,
+ ICON_BLANK006,
+ ICON_BLANK007,
+ ICON_BLANK008,
+ ICON_BLANK008b,
+
+ /* ui */
+ ICON_FULLSCREEN,
+ ICON_SPLITSCREEN,
+ ICON_RIGHTARROW_THIN,
+ ICON_BORDERMOVE,
+ ICON_VIEWZOOM,
+ ICON_ZOOMIN,
+ ICON_ZOOMOUT,
+ ICON_PANEL_CLOSE,
+ ICON_BLANK009,
+ ICON_EYEDROPPER,
+ ICON_BLANK010,
+ ICON_AUTO,
+ ICON_CHECKBOX_DEHLT,
+ ICON_CHECKBOX_HLT,
+ ICON_UNLOCKED,
+ ICON_LOCKED,
+ ICON_BLANK013,
+ ICON_BLANK014,
+ ICON_BLANK015,
+ ICON_RIGHTARROW,
+ ICON_DOWNARROW_HLT,
+ ICON_DOTSUP,
+ ICON_DOTSDOWN,
+ ICON_LINK,
+ ICON_INLINK,
+ ICON_BLANK012b,
+
+ /* available */
+ ICON_BLANK016,
+ ICON_BLANK017,
+ ICON_BLANK018,
+ ICON_BLANK019,
+ ICON_BLANK020,
+ ICON_BLANK021,
+ ICON_BLANK022,
+ ICON_BLANK023,
+ ICON_BLANK024,
+ ICON_BLANK025,
+ ICON_BLANK026,
+ ICON_BLANK027,
+ ICON_BLANK028,
+ ICON_BLANK029,
+ ICON_BLANK030,
+ ICON_BLANK031,
+ ICON_BLANK032,
+ ICON_BLANK033,
+ ICON_BLANK034,
+ ICON_BLANK035,
+ ICON_BLANK036,
+ ICON_BLANK037,
+ ICON_BLANK038,
+ ICON_BLANK039,
+ ICON_BLANK040,
+ ICON_BLANK040b,
+
+ /* BUTTONS */
+ ICON_LAMP,
+ ICON_MATERIAL,
+ ICON_TEXTURE,
+ ICON_ANIM,
+ ICON_WORLD,
+ ICON_SCENE,
+ ICON_EDIT,
+ ICON_GAME,
+ ICON_RADIO,
+ ICON_SCRIPT,
+ ICON_PARTICLES,
+ ICON_PHYSICS,
+ ICON_SPEAKER,
+ ICON_BLANK041,
+ ICON_BLANK042,
+ ICON_BLANK043,
+ ICON_BLANK044,
+ ICON_BLANK045,
+ ICON_BLANK046,
+ ICON_BLANK047,
+ ICON_BLANK048,
+ ICON_BLANK049,
+ ICON_BLANK050,
+ ICON_BLANK051,
+ ICON_BLANK052,
+ ICON_BLANK052b,
+
+ /* EDITORS */
+ 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_SCRIPTWIN,
+ ICON_TIME,
+ ICON_NODE,
+ ICON_BLANK053,
+ ICON_BLANK054,
+ ICON_BLANK055,
+ ICON_BLANK056,
+ ICON_BLANK057,
+ ICON_BLANK058,
+ ICON_BLANK059,
+ ICON_BLANK060,
+ ICON_BLANK061,
+ ICON_BLANK061b,
+
+ /* MODES */
+ ICON_OBJECT_DATAMODE, // XXX fix this up
+ ICON_EDITMODE_HLT,
+ ICON_FACESEL_HLT,
+ ICON_VPAINT_HLT,
+ ICON_TPAINT_HLT,
+ ICON_WPAINT_HLT,
+ ICON_SCULPTMODE_HLT,
+ ICON_POSE_HLT,
+ ICON_PARTICLEMODE,
+ ICON_BLANK062,
+ ICON_BLANK063,
+ ICON_BLANK064,
+ ICON_BLANK065,
+ ICON_BLANK066,
+ ICON_BLANK067,
+ ICON_BLANK068,
+ ICON_BLANK069,
+ ICON_BLANK070,
+ ICON_BLANK071,
+ ICON_BLANK072,
+ ICON_BLANK073,
+ ICON_BLANK074,
+ ICON_BLANK075,
+ ICON_BLANK076,
+ ICON_BLANK077,
+ ICON_BLANK077b,
+
+ /* DATA */
+ ICON_SCENE_DATA,
+ ICON_RENDERLAYERS,
+ ICON_WORLD_DATA,
+ ICON_OBJECT_DATA,
+ ICON_MESH_DATA,
+ ICON_CURVE_DATA,
+ ICON_MBALL_DATA,
+ ICON_LATTICE_DATA,
+ ICON_LAMP_DATA,
+ ICON_MATERIAL_DATA,
+ ICON_TEXTURE_DATA,
+ ICON_ANIM_DATA,
+ ICON_CAMERA_DATA,
+ ICON_PARTICLE_DATA,
+ ICON_LIBRARY_DATA_DIRECT,
+ ICON_GROUP,
+ ICON_ARMATURE_DATA,
+ ICON_POSE_DATA,
+ ICON_BONE_DATA,
+ ICON_CONSTRAINT,
+ ICON_SHAPEKEY_DATA,
+ ICON_VGROUP,
+ ICON_BLANK079,
+ ICON_PACKAGE,
+ ICON_UGLYPACKAGE,
+ ICON_BLANK079b,
+
+ /* DATA */
+ ICON_BRUSH_DATA,
+ ICON_IMAGE_DATA,
+ ICON_FILE,
+ ICON_FCURVE,
+ ICON_FONT,
+ ICON_RENDER_RESULT,
+ ICON_BLANK080A,
+ ICON_BLANK080B,
+ ICON_BLANK080C,
+ ICON_BLANK080D,
+ ICON_BLANK080E,
+ ICON_BLANK080F,
+ ICON_BLANK080,
+ ICON_BLANK081,
+ ICON_LIBRARY_DATA_INDIRECT,
+ ICON_BLANK082,
+ ICON_BLANK083,
+ ICON_BLANK084,
+ ICON_BLANK085,
+ ICON_BLANK086,
+ ICON_BLANK087,
+ ICON_BLANK088,
+ ICON_BLANK089,
+ ICON_BLANK090,
+ ICON_RNA,
+ ICON_BLANK090b,
+
+ /* available */
+ ICON_BLANK092,
+ ICON_BLANK093,
+ ICON_BLANK094,
+ ICON_BLANK095,
+ ICON_BLANK096,
+ ICON_BLANK097,
+ ICON_BLANK098,
+ ICON_BLANK099,
+ ICON_BLANK100,
+ ICON_BLANK101,
+ ICON_BLANK102,
+ ICON_BLANK103,
+ ICON_BLANK104,
+ ICON_BLANK105,
+ ICON_BLANK106,
+ ICON_BLANK107,
+ ICON_BLANK108,
+ ICON_BLANK109,
+ ICON_BLANK110,
+ ICON_BLANK111,
+ ICON_BLANK112,
+ ICON_BLANK113,
+ ICON_BLANK114,
+ ICON_BLANK115,
+ ICON_BLANK116,
+ ICON_BLANK116b,
+
+ /* OUTLINER */
+ ICON_OUTLINER_OB_EMPTY,
+ ICON_OUTLINER_OB_MESH,
+ ICON_OUTLINER_OB_CURVE,
+ ICON_OUTLINER_OB_LATTICE,
+ ICON_OUTLINER_OB_META,
+ ICON_OUTLINER_OB_LAMP,
+ ICON_OUTLINER_OB_CAMERA,
+ ICON_OUTLINER_OB_ARMATURE,
+ ICON_OUTLINER_OB_FONT,
+ ICON_OUTLINER_OB_SURFACE,
+ ICON_BLANK119,
+ ICON_BLANK120,
+ ICON_BLANK121,
+ ICON_BLANK122,
+ ICON_BLANK123,
+ ICON_BLANK124,
+ ICON_BLANK125,
+ ICON_BLANK126,
+ ICON_BLANK127,
+ ICON_RESTRICT_VIEW_OFF,
+ ICON_RESTRICT_VIEW_ON,
+ ICON_RESTRICT_SELECT_OFF,
+ ICON_RESTRICT_SELECT_ON,
+ ICON_RESTRICT_RENDER_OFF,
+ ICON_RESTRICT_RENDER_ON,
+ ICON_BLANK127b,
+
+ /* OUTLINER */
+ ICON_BLANK128,
+ ICON_OUTLINER_DATA_MESH,
+ ICON_OUTLINER_DATA_CURVE,
+ ICON_OUTLINER_DATA_LATTICE,
+ ICON_OUTLINER_DATA_META,
+ ICON_OUTLINER_DATA_LAMP,
+ ICON_OUTLINER_DATA_CAMERA,
+ ICON_OUTLINER_DATA_ARMATURE,
+ ICON_OUTLINER_DATA_POSE,
+ ICON_OUTLINER_DATA_GENERIC,
+ ICON_BLANK128b,
+ ICON_BLANK129,
+ ICON_BLANK130,
+ ICON_BLANK131,
+ ICON_BLANK132,
+ ICON_BLANK133,
+ ICON_BLANK134,
+ ICON_BLANK135,
+ ICON_BLANK136,
+ ICON_BLANK137,
+ ICON_BLANK138,
+ ICON_BLANK139,
+ ICON_BLANK140,
+ ICON_BLANK141,
+ ICON_BLANK142,
+ ICON_BLANK142b,
+
+ /* MODIFIERS */
+ ICON_MODIFIER,
+ ICON_MOD_WAVE,
+ ICON_MOD_BUILD,
+ ICON_MOD_DECIM,
+ ICON_MOD_MIRROR,
+ ICON_MOD_SOFT,
+ ICON_MOD_SUBSURF,
+ ICON_HOOK,
+ ICON_MOD_PARTICLEINSTANCE,
+ ICON_MOD_PARTICLES,
+ ICON_MOD_BOOLEAN,
+ ICON_MOD_EDGESPLIT,
+ ICON_MOD_ARRAY,
+ ICON_MOD_UVPROJECT,
+ ICON_MOD_DISPLACE,
+ ICON_MOD_CURVE,
+ ICON_MOD_LATTICE,
+ ICON_BLANK143,
+ ICON_MOD_ARMATURE,
+ ICON_BLANK147,
+ ICON_BLANK148,
+ ICON_BLANK149,
+ ICON_BLANK150,
+ ICON_BLANK151,
+ ICON_BLANK152,
+ ICON_BLANK152b,
+
+ /* available */
+ ICON_BLANK153,
+ ICON_BLANK154,
+ ICON_BLANK155,
+ ICON_BLANK156,
+ ICON_BLANK157,
+ ICON_BLANK158,
+ ICON_BLANK159,
+ ICON_BLANK160,
+ ICON_BLANK161,
+ ICON_BLANK162,
+ ICON_BLANK163,
+ ICON_BLANK164,
+ ICON_BLANK165,
+ ICON_BLANK166,
+ ICON_BLANK167,
+ ICON_BLANK168,
+ ICON_BLANK169,
+ ICON_BLANK170,
+ ICON_BLANK171,
+ ICON_BLANK172,
+ ICON_BLANK173,
+ ICON_BLANK174,
+ ICON_BLANK175,
+ ICON_BLANK176,
+ ICON_BLANK177,
+ ICON_BLANK177b,
+
+ /* ANIMATION */
+ ICON_REC,
+ ICON_PLAY,
+ ICON_FF,
+ ICON_REW,
+ ICON_PAUSE,
+ ICON_PREV_KEYFRAME,
+ ICON_NEXT_KEYFRAME,
+ ICON_PLAY_AUDIO,
+ ICON_BLANK178,
+ ICON_BLANK179,
+ ICON_BLANK180,
+ ICON_PMARKER_ACT,
+ ICON_PMARKER_SEL,
+ ICON_PMARKER,
+ ICON_MARKER_HLT,
+ ICON_MARKER,
+ ICON_SPACE2, // XXX
+ ICON_SPACE3, // XXX
+ ICON_BLANK181,
+ ICON_KEY_DEHLT,
+ ICON_KEY_HLT,
+ ICON_MUTE_IPO_OFF,
+ ICON_MUTE_IPO_ON,
+ ICON_BLANK182,
+ ICON_BLANK183,
+ ICON_BLANK183b,
+
+ /* available */
+ ICON_BLANK184,
+ ICON_BLANK185,
+ ICON_BLANK186,
+ ICON_BLANK187,
+ ICON_BLANK188,
+ ICON_BLANK189,
+ ICON_BLANK190,
+ ICON_BLANK191,
+ ICON_BLANK192,
+ ICON_BLANK193,
+ ICON_BLANK194,
+ ICON_BLANK195,
+ ICON_BLANK196,
+ ICON_BLANK197,
+ ICON_BLANK198,
+ ICON_BLANK199,
+ ICON_BLANK200,
+ ICON_BLANK201,
+ ICON_BLANK202,
+ ICON_BLANK203,
+ ICON_BLANK204,
+ ICON_BLANK205,
+ ICON_BLANK206,
+ ICON_BLANK207,
+ ICON_BLANK208,
+ ICON_BLANK208b,
+
+ /* EDITING */
+ ICON_VERTEXSEL,
+ ICON_EDGESEL,
+ ICON_FACESEL,
+ ICON_LINKEDSEL,
+ ICON_BLANK210,
+ ICON_ROTATE,
+ ICON_CURSOR,
+ ICON_ROTATECOLLECTION,
+ ICON_ROTATECENTER,
+ ICON_ROTACTIVE,
+ ICON_ALIGN,
+ ICON_BLANK211,
+ ICON_SMOOTHCURVE,
+ ICON_SPHERECURVE,
+ ICON_ROOTCURVE,
+ ICON_SHARPCURVE,
+ ICON_LINCURVE,
+ ICON_NOCURVE,
+ ICON_RNDCURVE,
+ ICON_PROP_OFF,
+ ICON_PROP_ON,
+ ICON_PROP_CON,
+ ICON_BLANK212,
+ ICON_BLANK213,
+ ICON_BLANK214,
+ ICON_BLANK214b,
+
+ /* EDITING */
+ ICON_MAN_TRANS,
+ ICON_MAN_ROT,
+ ICON_MAN_SCALE,
+ ICON_MANIPUL,
+ ICON_BLANK215,
+ ICON_SNAP_GEAR,
+ ICON_SNAP_GEO,
+ ICON_SNAP_NORMAL,
+ ICON_SNAP_VERTEX,
+ ICON_SNAP_EDGE,
+ ICON_SNAP_FACE,
+ ICON_BLANK218b,
+ ICON_STICKY_UVS_LOC,
+ ICON_STICKY_UVS_DISABLE,
+ ICON_STICKY_UVS_VERT,
+ ICON_CLIPUV_DEHLT,
+ ICON_CLIPUV_HLT,
+ ICON_BLANK219,
+ ICON_BLANK220,
+ ICON_BLANK221,
+ ICON_BLANK222,
+ ICON_BLANK223,
+ ICON_BLANK224,
+ ICON_BLANK225,
+ ICON_BLANK226,
+ ICON_BLANK226b,
+
+ /* EDITING */
+ ICON_PASTEDOWN,
+ ICON_COPYDOWN,
+ ICON_PASTEFLIPUP,
+ ICON_PASTEFLIPDOWN,
+ ICON_BLANK227,
+ ICON_BLANK228,
+ ICON_BLANK229,
+ ICON_BLANK230,
+ ICON_BLANK231,
+ ICON_BLANK232,
+ ICON_BLANK233,
+ ICON_BLANK234,
+ ICON_BLANK235,
+ ICON_BLANK236,
+ ICON_BLANK237,
+ ICON_BLANK238,
+ ICON_BLANK239,
+ ICON_BLANK240,
+ ICON_BLANK241,
+ ICON_BLANK242,
+ ICON_BLANK243,
+ ICON_BLANK244,
+ ICON_BLANK245,
+ ICON_BLANK246,
+ ICON_BLANK247,
+ ICON_BLANK247b,
+
+ /* 3D VIEW */
+ ICON_BBOX,
+ ICON_WIRE,
+ ICON_SOLID,
+ ICON_SMOOTH,
+ ICON_POTATO,
+ ICON_BLANK248,
+ ICON_ORTHO,
+ ICON_BLANK249,
+ ICON_CAMERA,
+ ICON_LOCKVIEW_OFF,
+ ICON_LOCKVIEW_ON,
+ ICON_BLANK250,
+ ICON_AXIS_SIDE,
+ ICON_AXIS_FRONT,
+ ICON_AXIS_TOP,
+ ICON_NDOF_DOM,
+ ICON_NDOF_TURN,
+ ICON_NDOF_FLY,
+ ICON_NDOF_TRANS,
+ ICON_LAYER_USED,
+ ICON_LAYER_ACTIVE,
+ ICON_BLANK254,
+ ICON_BLANK255,
+ ICON_BLANK256,
+ ICON_BLANK257,
+ ICON_BLANK257b,
+
+ /* available */
+ ICON_BLANK258,
+ ICON_BLANK259,
+ ICON_BLANK260,
+ ICON_BLANK261,
+ ICON_BLANK262,
+ ICON_BLANK263,
+ ICON_BLANK264,
+ ICON_BLANK265,
+ ICON_BLANK266,
+ ICON_BLANK267,
+ ICON_BLANK268,
+ ICON_BLANK269,
+ ICON_BLANK270,
+ ICON_BLANK271,
+ ICON_BLANK272,
+ ICON_BLANK273,
+ ICON_BLANK274,
+ ICON_BLANK275,
+ ICON_BLANK276,
+ ICON_BLANK277,
+ ICON_BLANK278,
+ ICON_BLANK279,
+ ICON_BLANK280,
+ ICON_BLANK281,
+ ICON_BLANK282,
+ ICON_BLANK282b,
+
+ /* FILE SELECT */
+ ICON_SORTALPHA,
+ ICON_SORTBYEXT,
+ ICON_SORTTIME,
+ ICON_SORTSIZE,
+ ICON_LONGDISPLAY,
+ ICON_SHORTDISPLAY,
+ ICON_GHOST,
+ ICON_IMGDISPLAY,
+ ICON_BLANK284,
+ ICON_BLANK285,
+ ICON_BOOKMARKS,
+ ICON_FONTPREVIEW,
+ ICON_FILTER,
+ ICON_BLANK285E,
+ ICON_BLANK285F,
+ ICON_FILE_PARENT,
+ ICON_FILE_REFRESH,
+ ICON_FILE_FOLDER,
+ ICON_FILE_BLANK,
+ ICON_FILE_BLEND,
+ ICON_FILE_IMAGE,
+ ICON_FILE_MOVIE,
+ ICON_FILE_SCRIPT,
+ ICON_FILE_SOUND,
+ ICON_FILE_FONT,
+ ICON_BLANK291b,
+
+ /* available */
+ ICON_BLANK292,
+ ICON_BLANK293,
+ ICON_BLANK294,
+ ICON_BLANK295,
+ ICON_BLANK296,
+ ICON_BLANK297,
+ ICON_BLANK298,
+ ICON_BLANK299,
+ ICON_BLANK300,
+ ICON_BLANK301,
+ ICON_BLANK302,
+ ICON_BLANK303,
+ ICON_BLANK304,
+ ICON_BLANK305,
+ ICON_BLANK306,
+ ICON_BLANK307,
+ ICON_BLANK308,
+ ICON_BLANK309,
+ ICON_BLANK310,
+ ICON_BLANK311,
+ ICON_BLANK312,
+ ICON_BLANK313,
+ ICON_BLANK314,
+ ICON_BLANK315,
+ ICON_BLANK316,
+ ICON_BLANK316b,
+
+ /* SHADING / TEXT */
+ ICON_MATPLANE,
+ ICON_MATSPHERE,
+ ICON_MATCUBE,
+ ICON_MONKEY,
+ ICON_HAIR,
+ ICON_RING,
+ ICON_BLANK317,
+ ICON_BLANK318,
+ ICON_BLANK319,
+ ICON_BLANK320,
+ ICON_BLANK321,
+ ICON_BLANK322,
+ ICON_WORDWRAP_OFF,
+ ICON_WORDWRAP_ON,
+ ICON_SYNTAX_OFF,
+ ICON_SYNTAX_ON,
+ ICON_LINENUMBERS_OFF,
+ ICON_LINENUMBERS_ON,
+ ICON_SCRIPTPLUGINS, // XXX CREATE NEW
+ ICON_BLANK323,
+ ICON_BLANK324,
+ ICON_BLANK325,
+ ICON_BLANK326,
+ ICON_BLANK327,
+ ICON_BLANK328,
+ ICON_BLANK328b,
+
+ /* SEQUENCE / IMAGE EDITOR */
+ ICON_SEQ_SEQUENCER,
+ ICON_SEQ_PREVIEW,
+ ICON_SEQ_LUMA_WAVEFORM,
+ ICON_SEQ_CHROMA_SCOPE,
+ ICON_SEQ_HISTOGRAM,
+ ICON_BLANK330,
+ ICON_BLANK331,
+ ICON_BLANK332,
+ ICON_BLANK333,
+ ICON_IMAGE_RGB, // XXX CHANGE TO STRAIGHT ALPHA, Z ETC
+ ICON_IMAGE_RGB_ALPHA,
+ ICON_IMAGE_ALPHA,
+ ICON_IMAGE_ZDEPTH,
+ ICON_IMAGEFILE,
+ ICON_BLANK336,
+ ICON_BLANK337,
+ ICON_BLANK338,
+ ICON_BLANK339,
+ ICON_BLANK340,
+ ICON_BLANK341,
+ ICON_BLANK342,
+ ICON_BLANK343,
+ ICON_BLANK344,
+ ICON_BLANK345,
+ ICON_BLANK346,
+ ICON_BLANK346b,
+
+ /* vector icons */
+
+ VICON_VIEW3D,
+ VICON_EDIT,
+ VICON_EDITMODE_DEHLT,
+ VICON_EDITMODE_HLT,
+ VICON_DISCLOSURE_TRI_RIGHT,
+ VICON_DISCLOSURE_TRI_DOWN,
+ VICON_MOVE_UP,
+ VICON_MOVE_DOWN,
+ VICON_X
+
+#define BIFICONID_LAST (VICON_X)
+#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 = 0,
+ 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,
+
+ BUTTEXTCOLOR,
+ BUTTEXTPRESSED,
+ BUTSBACKGROUND,
+
+ VIEWPORTBACKCOLOR,
+ VIEWPORTGRIDCOLOR,
+ VIEWPORTACTIVECOLOR,
+ VIEWPORTSELECTEDCOLOR,
+ VIEWPORTUNSELCOLOR,
+
+ EDITVERTSEL,
+ EDITVERTUNSEL,
+ EDITEDGESEL,
+ EDITEDGEUNSEL
+
+#define BIFCOLORID_LAST (EDITEDGEUNSEL)
+#define BIFNCOLORIDS (BIFCOLORID_LAST-BIFCOLORID_FIRST + 1)
+
+} BIFColorID;
+
+/* XXX WARNING: this is saved in file, so do not change order! */
+enum {
+ TH_AUTO, /* for buttons, to signal automatic color assignment */
+
+// uibutton colors
+ TH_BUT_OUTLINE,
+ TH_BUT_NEUTRAL,
+ TH_BUT_ACTION,
+ TH_BUT_SETTING,
+ TH_BUT_SETTING1,
+ TH_BUT_SETTING2,
+ TH_BUT_NUM,
+ TH_BUT_TEXTFIELD,
+ TH_BUT_POPUP,
+ TH_BUT_TEXT,
+ TH_BUT_TEXT_HI,
+ TH_MENU_BACK,
+ TH_MENU_ITEM,
+ TH_MENU_HILITE,
+ TH_MENU_TEXT,
+ TH_MENU_TEXT_HI,
+
+ TH_BUT_DRAWTYPE,
+
+ TH_REDALERT,
+ TH_CUSTOM,
+
+ TH_BUT_TEXTFIELD_HI,
+ TH_ICONFILE,
+
+ TH_THEMEUI,
+// common colors among spaces
+
+ TH_BACK,
+ TH_TEXT,
+ TH_TEXT_HI,
+ TH_HEADER,
+ TH_HEADERDESEL,
+ TH_PANEL,
+ TH_SHADE1,
+ TH_SHADE2,
+ TH_HILITE,
+
+ TH_GRID,
+ TH_WIRE,
+ TH_SELECT,
+ TH_ACTIVE,
+ TH_GROUP,
+ TH_GROUP_ACTIVE,
+ TH_TRANSFORM,
+ TH_VERTEX,
+ TH_VERTEX_SELECT,
+ TH_VERTEX_SIZE,
+ TH_EDGE,
+ TH_EDGE_SELECT,
+ TH_EDGE_SEAM,
+ TH_EDGE_FACESEL,
+ TH_FACE,
+ TH_FACE_SELECT,
+ TH_NORMAL,
+ TH_FACE_DOT,
+ TH_FACEDOT_SIZE,
+ TH_CFRAME,
+
+ TH_SYNTAX_B,
+ TH_SYNTAX_V,
+ TH_SYNTAX_C,
+ TH_SYNTAX_L,
+ TH_SYNTAX_N,
+
+ TH_BONE_SOLID,
+ TH_BONE_POSE,
+
+ TH_STRIP,
+ TH_STRIP_SELECT,
+
+ TH_LAMP,
+
+ TH_NODE,
+ TH_NODE_IN_OUT,
+ TH_NODE_OPERATOR,
+ TH_NODE_CONVERTOR,
+ TH_NODE_GROUP,
+
+ TH_SEQ_MOVIE,
+ TH_SEQ_IMAGE,
+ TH_SEQ_SCENE,
+ TH_SEQ_AUDIO,
+ TH_SEQ_EFFECT,
+ TH_SEQ_PLUGIN,
+ TH_SEQ_TRANSITION,
+ TH_SEQ_META,
+
+ TH_EDGE_SHARP,
+ TH_EDITMESH_ACTIVE,
+
+ TH_HANDLE_VERTEX,
+ TH_HANDLE_VERTEX_SELECT,
+ TH_HANDLE_VERTEX_SIZE,
+
+ TH_DOPESHEET_CHANNELOB,
+ TH_DOPESHEET_CHANNELSUBOB,
+};
+/* XXX WARNING: previous is saved in file, so do not change order! */
+
+/* specific defines per space should have higher define values */
+
+struct bTheme;
+struct PointerRNA;
+
+// THE CODERS API FOR THEMES:
+
+// sets the color
+void UI_ThemeColor(int colorid);
+
+// sets the color plus alpha
+void UI_ThemeColor4(int colorid);
+
+// sets color plus offset for shade
+void UI_ThemeColorShade(int colorid, int offset);
+
+// sets color plus offset for alpha
+void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset);
+
+// sets color, which is blend between two theme colors
+void UI_ThemeColorBlend(int colorid1, int colorid2, float fac);
+// same, with shade offset
+void UI_ThemeColorBlendShade(int colorid1, int colorid2, float fac, int offset);
+void UI_ThemeColorBlendShadeAlpha(int colorid1, int colorid2, float fac, int offset, int alphaoffset);
+
+// returns one value, not scaled
+float UI_GetThemeValuef(int colorid);
+int UI_GetThemeValue(int colorid);
+
+// get three color values, scaled to 0.0-1.0 range
+void UI_GetThemeColor3fv(int colorid, float *col);
+
+// get the 3 or 4 byte values
+void UI_GetThemeColor3ubv(int colorid, char *col);
+void UI_GetThemeColor4ubv(int colorid, char *col);
+
+// get a theme color from specified space type
+void UI_GetThemeColorType4ubv(int colorid, int spacetype, char *col);
+
+// blends and shades between two color pointers
+void UI_ColorPtrBlendShade3ubv(char *cp1, char *cp2, float fac, int offset);
+
+// get a 3 byte color, blended and shaded between two other char color pointers
+void UI_GetColorPtrBlendShade3ubv(char *cp1, char *cp2, char *col, float fac, int offset);
+
+// get pointer from RNA pointer
+int UI_GetIconRNA(struct PointerRNA *ptr);
+
+struct ScrArea;
+
+// internal (blender) usage only, for init and set active
+void UI_SetTheme(struct ScrArea *sa);
+void ui_theme_init_userdef (void);
+void ui_resources_init (void);
+void ui_resources_free (void);
+
+/* only for buttons in theme editor! */
+char *UI_ThemeGetColorPtr(struct bTheme *btheme, int spacetype, int colorid);
+char *UI_ThemeColorsPup(int spacetype);
+
+#endif /* UI_ICONS_H */
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
new file mode 100644
index 00000000000..0650a5611dc
--- /dev/null
+++ b/source/blender/editors/include/UI_view2d.h
@@ -0,0 +1,192 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation, Joshua Leung
+ *
+ *
+ * Generic 2d view with should allow drawing grids,
+ * panning, zooming, scrolling, ..
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef UI_VIEW2D_H
+#define UI_VIEW2D_H
+
+/* ------------------------------------------ */
+/* Settings and Defines: */
+
+/* ---- General Defines ---- */
+
+/* generic value to use when coordinate lies out of view when converting */
+#define V2D_IS_CLIPPED 12000
+
+/* Common View2D view types
+ * NOTE: only define a type here if it completely sets all (+/- a few) of the relevant flags
+ * and settings for a View2D region, and that set of settings is used in more
+ * than one specific place
+ */
+enum {
+ /* custom view type (region has defined all necessary flags already) */
+ V2D_COMMONVIEW_CUSTOM = -1,
+ /* standard (only use this when setting up a new view, as a sensible base for most settings) */
+ V2D_COMMONVIEW_STANDARD,
+ /* listview (i.e. Outliner) */
+ V2D_COMMONVIEW_LIST,
+ /* headers (this is basically the same as listview, but no y-panning) */
+ V2D_COMMONVIEW_HEADER,
+ /* ui listviews, tries to wrap tot inside region width */
+ V2D_COMMONVIEW_LIST_UI,
+ /* ui region containing panels */
+ V2D_COMMONVIEW_PANELS_UI,
+} eView2D_CommonViewTypes;
+
+/* ---- Defines for Scroller/Grid Arguments ----- */
+
+/* 'dummy' argument to pass when argument is irrelevant */
+#define V2D_ARG_DUMMY -1
+
+/* Grid units */
+enum {
+ /* for drawing time */
+ V2D_UNIT_SECONDS = 0,
+ V2D_UNIT_FRAMES,
+ V2D_UNIT_FRAMESCALE,
+
+ /* for drawing values */
+ V2D_UNIT_VALUES,
+ V2D_UNIT_DEGREES,
+ V2D_UNIT_TIME,
+ V2D_UNIT_SECONDSSEQ,
+} eView2D_Units;
+
+/* clamping of grid values to whole numbers */
+enum {
+ V2D_GRID_NOCLAMP = 0,
+ V2D_GRID_CLAMP,
+} eView2D_Clamp;
+
+/* flags for grid-lines to draw */
+enum {
+ V2D_HORIZONTAL_LINES = (1<<0),
+ V2D_VERTICAL_LINES = (1<<1),
+ V2D_HORIZONTAL_AXIS = (1<<2),
+ V2D_VERTICAL_AXIS = (1<<3),
+ V2D_HORIZONTAL_FINELINES = (1<<4),
+
+ V2D_GRIDLINES_MAJOR = (V2D_VERTICAL_LINES|V2D_VERTICAL_AXIS|V2D_HORIZONTAL_LINES|V2D_HORIZONTAL_AXIS),
+ V2D_GRIDLINES_ALL = (V2D_GRIDLINES_MAJOR|V2D_HORIZONTAL_FINELINES),
+} eView2D_Gridlines;
+
+/* ------ Defines for Scrollers ----- */
+
+/* scroller thickness */
+#define V2D_SCROLL_HEIGHT 16
+#define V2D_SCROLL_WIDTH 16
+
+/* half the size (in pixels) of scroller 'handles' */
+#define V2D_SCROLLER_HANDLE_SIZE 5
+
+/* ------ Define for UI_view2d_sync ----- */
+
+/* means copy it from another v2d */
+#define V2D_LOCK_SET 0
+/* means copy it to the other v2ds */
+#define V2D_LOCK_COPY 1
+
+
+/* ------------------------------------------ */
+/* Macros: */
+
+/* test if mouse in a scrollbar (assume that scroller availability has been tested) */
+#define IN_2D_VERT_SCROLL(v2d, co) (BLI_in_rcti(&v2d->vert, co[0], co[1]))
+#define IN_2D_HORIZ_SCROLL(v2d, co) (BLI_in_rcti(&v2d->hor, co[0], co[1]))
+
+/* ------------------------------------------ */
+/* Type definitions: */
+
+struct View2D;
+struct View2DGrid;
+struct View2DScrollers;
+
+struct wmWindowManager;
+struct bScreen;
+struct ScrArea;
+struct bContext;
+struct rctf;
+
+typedef struct View2DGrid View2DGrid;
+typedef struct View2DScrollers View2DScrollers;
+
+/* ----------------------------------------- */
+/* Prototypes: */
+
+/* refresh and validation (of view rects) */
+void UI_view2d_region_reinit(struct View2D *v2d, short type, int winx, int winy);
+
+void UI_view2d_curRect_validate(struct View2D *v2d);
+void UI_view2d_curRect_reset(struct View2D *v2d);
+void UI_view2d_sync(struct bScreen *screen, struct ScrArea *sa, struct View2D *v2dcur, int flag);
+
+void UI_view2d_totRect_set(struct View2D *v2d, int width, int height);
+
+/* view matrix operations */
+void UI_view2d_view_ortho(const struct bContext *C, struct View2D *v2d);
+void UI_view2d_view_orthoSpecial(const struct bContext *C, struct View2D *v2d, short xaxis);
+void UI_view2d_view_restore(const struct bContext *C);
+
+/* grid drawing */
+View2DGrid *UI_view2d_grid_calc(const struct bContext *C, struct View2D *v2d, short xunits, short xclamp, short yunits, short yclamp, int winx, int winy);
+void UI_view2d_grid_draw(const struct bContext *C, struct View2D *v2d, View2DGrid *grid, int flag);
+void UI_view2d_constant_grid_draw(const struct bContext *C, struct View2D *v2d);
+void UI_view2d_grid_free(View2DGrid *grid);
+
+/* scrollbar drawing */
+View2DScrollers *UI_view2d_scrollers_calc(const struct bContext *C, struct View2D *v2d, short xunits, short xclamp, short yunits, short yclamp);
+void UI_view2d_scrollers_draw(const struct bContext *C, struct View2D *v2d, View2DScrollers *scrollers);
+void UI_view2d_scrollers_free(View2DScrollers *scrollers);
+
+/* list view tools */
+void UI_view2d_listview_cell_to_view(struct View2D *v2d, short columnwidth, short rowheight, float startx, float starty, int column, int row, struct rctf *rect);
+void UI_view2d_listview_view_to_cell(struct View2D *v2d, short columnwidth, short rowheight, float startx, float starty, float viewx, float viewy, int *column, int *row);
+void UI_view2d_listview_visible_cells(struct View2D *v2d, short columnwidth, short rowheight, float startx, float starty, int *column_min, int *column_max, int *row_min, int *row_max);
+
+/* coordinate conversion */
+void UI_view2d_region_to_view(struct View2D *v2d, int x, int y, float *viewx, float *viewy);
+void UI_view2d_view_to_region(struct View2D *v2d, float x, float y, int *regionx, int *regiony);
+void UI_view2d_to_region_no_clip(struct View2D *v2d, float x, float y, int *regionx, int *region_y);
+
+/* utilities */
+struct View2D *UI_view2d_fromcontext(const struct bContext *C);
+struct View2D *UI_view2d_fromcontext_rwin(const struct bContext *C);
+
+void UI_view2d_getscale(struct View2D *v2d, float *x, float *y);
+
+short UI_view2d_mouse_in_scrollers(const struct bContext *C, struct View2D *v2d, int x, int y);
+
+
+/* operators */
+void ui_view2d_operatortypes(void);
+void UI_view2d_keymap(struct wmWindowManager *wm);
+
+#endif /* UI_VIEW2D_H */
+
diff --git a/source/blender/editors/interface/Makefile b/source/blender/editors/interface/Makefile
new file mode 100644
index 00000000000..fa9550041c5
--- /dev/null
+++ b/source/blender/editors/interface/Makefile
@@ -0,0 +1,61 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_interface
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+CPPFLAGS += -I$(NAN_BMFONT)/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../ftfont
+CPPFLAGS += -I../../blenfont
+
+# own include
+
+CPPFLAGS += -I../include
+
+ifeq ($(INTERNATIONAL), true)
+ CPPFLAGS += -DINTERNATIONAL
+endif
+
diff --git a/source/blender/editors/interface/SConscript b/source/blender/editors/interface/SConscript
new file mode 100644
index 00000000000..fa89cd4891c
--- /dev/null
+++ b/source/blender/editors/interface/SConscript
@@ -0,0 +1,20 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+for source in env.Glob('*_api.c'):
+ sources.remove(source)
+
+incs = '../include ../../blenlib ../../blenfont ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../makesrna ../../windowmanager #/intern/guardedalloc #intern/bmfont'
+incs += ' #/extern/glew/include'
+
+defs = []
+
+if env['WITH_BF_INTERNATIONAL']:
+ incs += ' ../../ftfont'
+ defs.append('INTERNATIONAL')
+ defs.append('FTGL_STATIC_LIBRARY')
+
+env.BlenderLib ( 'bf_editors_interface', sources, Split(incs), Split(defs), libtype=['core'], priority=[110] )
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
new file mode 100644
index 00000000000..221ad23a846
--- /dev/null
+++ b/source/blender/editors/interface/interface.c
@@ -0,0 +1,3066 @@
+/**
+ * $Id: interface.c 16882 2008-10-02 12:29:45Z ton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation 2002-2008, full recode.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <float.h>
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ID.h"
+#include "DNA_listBase.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h"
+
+#include "BKE_context.h"
+#include "BKE_idprop.h"
+#include "BKE_library.h"
+#include "BKE_screen.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "BLF_api.h"
+
+#include "UI_interface.h"
+
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "wm_subwindow.h"
+#include "wm_window.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+
+#include "interface_intern.h"
+
+#define MENU_WIDTH 120
+#define MENU_ITEM_HEIGHT 20
+#define MENU_SEP_HEIGHT 6
+
+/*
+ * a full doc with API notes can be found in bf-blender/blender/doc/interface_API.txt
+ *
+ * uiBlahBlah() external function
+ * ui_blah_blah() internal function
+ */
+
+static void ui_free_but(const bContext *C, uiBut *but);
+static void ui_rna_ID_autocomplete(bContext *C, char *str, void *arg_but);
+
+/* ************* translation ************** */
+
+int ui_translate_buttons()
+{
+ return (U.transopts & USER_TR_BUTTONS);
+}
+
+int ui_translate_menus()
+{
+ return (U.transopts & USER_TR_MENUS);
+}
+
+int ui_translate_tooltips()
+{
+ return (U.transopts & USER_TR_TOOLTIPS);
+}
+
+/* ************* window matrix ************** */
+
+void ui_block_to_window_fl(const ARegion *ar, uiBlock *block, float *x, float *y)
+{
+ float gx, gy;
+ int sx, sy, getsizex, getsizey;
+
+ getsizex= ar->winrct.xmax-ar->winrct.xmin+1;
+ getsizey= ar->winrct.ymax-ar->winrct.ymin+1;
+ sx= ar->winrct.xmin;
+ sy= ar->winrct.ymin;
+
+ gx= *x;
+ gy= *y;
+
+ if(block->panel) {
+ gx += block->panel->ofsx;
+ gy += block->panel->ofsy;
+ }
+
+ *x= ((float)sx) + ((float)getsizex)*(0.5+ 0.5*(gx*block->winmat[0][0]+ gy*block->winmat[1][0]+ block->winmat[3][0]));
+ *y= ((float)sy) + ((float)getsizey)*(0.5+ 0.5*(gx*block->winmat[0][1]+ gy*block->winmat[1][1]+ block->winmat[3][1]));
+}
+
+void ui_block_to_window(const ARegion *ar, uiBlock *block, int *x, int *y)
+{
+ float fx, fy;
+
+ fx= *x;
+ fy= *y;
+
+ ui_block_to_window_fl(ar, block, &fx, &fy);
+
+ *x= (int)(fx+0.5f);
+ *y= (int)(fy+0.5f);
+}
+
+void ui_block_to_window_rct(const ARegion *ar, uiBlock *block, rctf *graph, rcti *winr)
+{
+ rctf tmpr;
+
+ tmpr= *graph;
+ ui_block_to_window_fl(ar, block, &tmpr.xmin, &tmpr.ymin);
+ ui_block_to_window_fl(ar, block, &tmpr.xmax, &tmpr.ymax);
+
+ winr->xmin= tmpr.xmin;
+ winr->ymin= tmpr.ymin;
+ winr->xmax= tmpr.xmax;
+ winr->ymax= tmpr.ymax;
+}
+
+void ui_window_to_block_fl(const ARegion *ar, uiBlock *block, float *x, float *y) /* for mouse cursor */
+{
+ float a, b, c, d, e, f, px, py;
+ int sx, sy, getsizex, getsizey;
+
+ getsizex= ar->winrct.xmax-ar->winrct.xmin+1;
+ getsizey= ar->winrct.ymax-ar->winrct.ymin+1;
+ sx= ar->winrct.xmin;
+ sy= ar->winrct.ymin;
+
+ a= .5*((float)getsizex)*block->winmat[0][0];
+ b= .5*((float)getsizex)*block->winmat[1][0];
+ c= .5*((float)getsizex)*(1.0+block->winmat[3][0]);
+
+ d= .5*((float)getsizey)*block->winmat[0][1];
+ e= .5*((float)getsizey)*block->winmat[1][1];
+ f= .5*((float)getsizey)*(1.0+block->winmat[3][1]);
+
+ px= *x - sx;
+ py= *y - sy;
+
+ *y= (a*(py-f) + d*(c-px))/(a*e-d*b);
+ *x= (px- b*(*y)- c)/a;
+
+ if(block->panel) {
+ *x -= block->panel->ofsx;
+ *y -= block->panel->ofsy;
+ }
+}
+
+void ui_window_to_block(const ARegion *ar, uiBlock *block, int *x, int *y)
+{
+ float fx, fy;
+
+ fx= *x;
+ fy= *y;
+
+ ui_window_to_block_fl(ar, block, &fx, &fy);
+
+ *x= (int)(fx+0.5f);
+ *y= (int)(fy+0.5f);
+}
+
+void ui_window_to_region(const ARegion *ar, int *x, int *y)
+{
+ *x-= ar->winrct.xmin;
+ *y-= ar->winrct.ymin;
+}
+
+/* ******************* block calc ************************* */
+
+void ui_block_translate(uiBlock *block, int x, int y)
+{
+ uiBut *bt;
+
+ for(bt= block->buttons.first; bt; bt=bt->next) {
+ bt->x1 += x;
+ bt->y1 += y;
+ bt->x2 += x;
+ bt->y2 += y;
+ }
+
+ block->minx += x;
+ block->miny += y;
+ block->maxx += x;
+ block->maxy += y;
+}
+
+static void ui_text_bounds_block(uiBlock *block, float offset)
+{
+ uiStyle *style= U.uistyles.first; // XXX pass on as arg
+ uiBut *bt;
+ int i = 0, j, x1addval= offset, nextcol;
+
+ uiStyleFontSet(&style->widget);
+
+ for(bt= block->buttons.first; bt; bt= bt->next) {
+ if(bt->type!=SEPR) {
+ //int transopts= ui_translate_buttons();
+ //if(bt->type==TEX || bt->type==IDPOIN) transopts= 0;
+
+ j= BLF_width(bt->drawstr);
+
+ if(j > i) i = j;
+ }
+ }
+
+ /* cope with multi collumns */
+ bt= block->buttons.first;
+ while(bt) {
+ if(bt->next && bt->x1 < bt->next->x1)
+ nextcol= 1;
+ else nextcol= 0;
+
+ bt->x1 = x1addval;
+ bt->x2 = bt->x1 + i + block->bounds;
+
+ ui_check_but(bt); // clips text again
+
+ if(nextcol)
+ x1addval+= i + block->bounds;
+
+ bt= bt->next;
+ }
+}
+
+void ui_bounds_block(uiBlock *block)
+{
+ uiBut *bt;
+ int xof;
+
+ if(block->buttons.first==NULL) {
+ if(block->panel) {
+ block->minx= 0.0; block->maxx= block->panel->sizex;
+ block->miny= 0.0; block->maxy= block->panel->sizey;
+ }
+ }
+ else {
+
+ 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 -= block->bounds;
+ block->miny -= block->bounds;
+ block->maxx += block->bounds;
+ block->maxy += block->bounds;
+ }
+
+ /* hardcoded exception... but that one is annoying with larger safety */
+ bt= block->buttons.first;
+ if(bt && strncmp(bt->str, "ERROR", 5)==0) xof= 10;
+ else xof= 40;
+
+ block->safety.xmin= block->minx-xof;
+ block->safety.ymin= block->miny-xof;
+ block->safety.xmax= block->maxx+xof;
+ block->safety.ymax= block->maxy+xof;
+}
+
+static void ui_popup_bounds_block(const bContext *C, uiBlock *block, int menu)
+{
+ wmWindow *window= CTX_wm_window(C);
+ int startx, starty, endx, endy, width, height;
+ int oldbounds, mx, my, xmax, ymax;
+
+ oldbounds= block->bounds;
+
+ /* compute mouse position with user defined offset */
+ ui_bounds_block(block);
+ mx= window->eventstate->x + block->minx + block->mx;
+ my= window->eventstate->y + block->miny + block->my;
+
+ wm_window_get_size(window, &xmax, &ymax);
+
+ /* first we ensure wide enough text bounds */
+ if(menu) {
+ if(block->flag & UI_BLOCK_LOOP) {
+ block->bounds= 50;
+ ui_text_bounds_block(block, block->minx);
+ }
+ }
+
+ /* next we recompute bounds */
+ block->bounds= oldbounds;
+ ui_bounds_block(block);
+
+ /* and we adjust the position to fit within window */
+ width= block->maxx - block->minx;
+ height= block->maxy - block->miny;
+
+ startx= mx-(0.8*(width));
+ starty= my;
+
+ if(startx<10)
+ startx= 10;
+ if(starty<10)
+ starty= 10;
+
+ endx= startx+width;
+ endy= starty+height;
+
+ if(endx>xmax) {
+ endx= xmax-10;
+ startx= endx-width;
+ }
+ if(endy>ymax-20) {
+ endy= ymax-20;
+ starty= endy-height;
+ }
+
+ ui_block_translate(block, startx - block->minx, starty - block->miny);
+
+ /* now recompute bounds and safety */
+ ui_bounds_block(block);
+}
+
+/* used for various cases */
+void uiBoundsBlock(uiBlock *block, int addval)
+{
+ if(block==NULL)
+ return;
+
+ block->bounds= addval;
+ block->dobounds= 1;
+}
+
+/* used for pulldowns */
+void uiTextBoundsBlock(uiBlock *block, int addval)
+{
+ block->bounds= addval;
+ block->dobounds= 2;
+}
+
+/* used for block popups */
+void uiPopupBoundsBlock(uiBlock *block, int addval, int mx, int my)
+{
+ block->bounds= addval;
+ block->dobounds= 3;
+ block->mx= mx;
+ block->my= my;
+}
+
+/* used for menu popups */
+void uiMenuPopupBoundsBlock(uiBlock *block, int addval, int mx, int my)
+{
+ block->bounds= addval;
+ block->dobounds= 4;
+ block->mx= mx;
+ block->my= my;
+}
+
+/* ************** LINK LINE DRAWING ************* */
+
+/* link line drawing is not part of buttons or theme.. so we stick with it here */
+
+static void ui_draw_linkline(uiBut *but, 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) glColor3ub(100,100,100);
+ 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, line);
+ line= line->next;
+ }
+ }
+ but= but->next;
+ }
+}
+
+/* ************** BLOCK ENDING FUNCTION ************* */
+
+static int ui_but_equals_old(uiBut *but, uiBut *oldbut)
+{
+ /* various properties are being compared here, hopfully sufficient
+ * to catch all cases, but it is simple to add more checks later */
+ if(but->retval != oldbut->retval) return 0;
+ if(but->rnapoin.data != oldbut->rnapoin.data) return 0;
+ if(but->rnaprop != oldbut->rnaprop)
+ if(but->rnaindex != oldbut->rnaindex) return 0;
+ if(but->func != oldbut->func) return 0;
+ if(but->funcN != oldbut->funcN) return 0;
+ if(oldbut->func_arg1 != oldbut && but->func_arg1 != oldbut->func_arg1) return 0;
+ if(oldbut->func_arg2 != oldbut && but->func_arg2 != oldbut->func_arg2) return 0;
+ if(!but->funcN && (but->poin != oldbut->poin || but->pointype != oldbut->pointype)) return 0;
+
+ return 1;
+}
+
+static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut *but)
+{
+ uiBlock *oldblock;
+ uiBut *oldbut;
+ int found= 0;
+
+ oldblock= block->oldblock;
+ if(!oldblock)
+ return found;
+
+ for(oldbut=oldblock->buttons.first; oldbut; oldbut=oldbut->next) {
+ if(ui_but_equals_old(oldbut, but)) {
+ if(oldbut->active) {
+ but->flag= oldbut->flag;
+ but->active= oldbut->active;
+ but->pos= oldbut->pos;
+ but->editstr= oldbut->editstr;
+ but->editval= oldbut->editval;
+ but->editvec= oldbut->editvec;
+ but->editcoba= oldbut->editcoba;
+ but->editcumap= oldbut->editcumap;
+ but->selsta= oldbut->selsta;
+ but->selend= oldbut->selend;
+ but->softmin= oldbut->softmin;
+ but->softmax= oldbut->softmax;
+ found= 1;
+
+ oldbut->active= NULL;
+ }
+
+ /* ensures one button can get activated, and in case the buttons
+ * draw are the same this gives O(1) lookup for each button */
+ BLI_remlink(&oldblock->buttons, oldbut);
+ ui_free_but(C, oldbut);
+
+ break;
+ }
+ }
+
+ return found;
+}
+
+void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
+{
+ uiBut *but;
+ IDProperty *prop;
+ char buf[512], *butstr;
+
+ /* only do it before bounding */
+ if(block->minx != block->maxx)
+ return;
+
+ for(but=block->buttons.first; but; but=but->next) {
+ if(but->opname) {
+ prop= (but->opptr)? but->opptr->data: NULL;
+
+ if(WM_key_event_operator_string(C, but->opname, but->opcontext, prop, buf, sizeof(buf))) {
+ butstr= MEM_mallocN(strlen(but->str)+strlen(buf)+2, "menu_block_set_keymaps");
+ strcpy(butstr, but->str);
+ strcat(butstr, "|");
+ strcat(butstr, buf);
+
+ but->str= but->strdata;
+ BLI_strncpy(but->str, butstr, sizeof(but->strdata));
+ MEM_freeN(butstr);
+
+ ui_check_but(but);
+ }
+ }
+ }
+}
+
+void uiEndBlock(const bContext *C, uiBlock *block)
+{
+ uiBut *but;
+ Scene *scene= CTX_data_scene(C);
+
+ /* inherit flags from 'old' buttons that was drawn here previous, based
+ * on matching buttons, we need this to make button event handling non
+ * blocking, while still alowing buttons to be remade each redraw as it
+ * is expected by blender code */
+ for(but=block->buttons.first; but; but=but->next) {
+ if(ui_but_update_from_old_block(C, block, but))
+ ui_check_but(but);
+
+ /* temp? Proper check for greying out */
+ if(but->opname) {
+ wmOperatorType *ot= WM_operatortype_find(but->opname);
+ if(ot==NULL || (ot->poll && ot->poll((bContext *)C)==0)) {
+ but->flag |= UI_BUT_DISABLED;
+ but->lock = 1;
+ }
+ }
+
+ /* only update soft range while not editing */
+ if(but->rnaprop && !(but->editval || but->editstr || but->editvec))
+ ui_set_but_soft_range(but, ui_get_but_val(but));
+
+ ui_but_anim_flag(but, (scene)? scene->r.cfra: 0.0f);
+ }
+
+ if(block->oldblock) {
+ block->auto_open= block->oldblock->auto_open;
+ block->auto_open_last= block->oldblock->auto_open_last;
+ block->tooltipdisabled= block->oldblock->tooltipdisabled;
+
+ block->oldblock= NULL;
+ }
+
+ /* handle pending stuff */
+ if(block->flag & UI_BLOCK_LOOP) ui_menu_block_set_keymaps(C, block);
+
+ /* after keymaps! */
+ if(block->dobounds == 1) ui_bounds_block(block);
+ else if(block->dobounds == 2) ui_text_bounds_block(block, 0.0f);
+ else if(block->dobounds) ui_popup_bounds_block(C, block, (block->dobounds == 4));
+
+ if(block->minx==0.0 && block->maxx==0.0) uiBoundsBlock(block, 0);
+ if(block->flag & UI_BUT_ALIGN) uiBlockEndAlign(block);
+
+ block->endblock= 1;
+}
+
+/* ************** BLOCK DRAWING FUNCTION ************* */
+
+void ui_fontscale(short *points, float aspect)
+{
+ if(aspect < 0.9f || aspect > 1.1f) {
+ float pointsf= *points;
+
+ /* for some reason scaling fonts goes too fast compared to widget size */
+ aspect= sqrt(aspect);
+ pointsf /= aspect;
+
+ if(aspect > 1.0)
+ *points= ceil(pointsf);
+ else
+ *points= floor(pointsf);
+ }
+}
+
+/* project button or block (but==NULL) to pixels in regionspace */
+static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, uiBut *but)
+{
+ float gx, gy;
+ float getsizex, getsizey;
+
+ getsizex= ar->winx;
+ getsizey= ar->winy;
+
+ gx= (but?but->x1:block->minx) + (block->panel?block->panel->ofsx:0.0f);
+ gy= (but?but->y1:block->miny) + (block->panel?block->panel->ofsy:0.0f);
+
+ rect->xmin= floor(getsizex*(0.5+ 0.5*(gx*block->winmat[0][0]+ gy*block->winmat[1][0]+ block->winmat[3][0])));
+ rect->ymin= floor(getsizey*(0.5+ 0.5*(gx*block->winmat[0][1]+ gy*block->winmat[1][1]+ block->winmat[3][1])));
+
+ gx= (but?but->x2:block->maxx) + (block->panel?block->panel->ofsx:0.0f);
+ gy= (but?but->y2:block->maxy) + (block->panel?block->panel->ofsy:0.0f);
+
+ rect->xmax= floor(getsizex*(0.5+ 0.5*(gx*block->winmat[0][0]+ gy*block->winmat[1][0]+ block->winmat[3][0])));
+ rect->ymax= floor(getsizey*(0.5+ 0.5*(gx*block->winmat[0][1]+ gy*block->winmat[1][1]+ block->winmat[3][1])));
+}
+
+/* uses local copy of style, to scale things down, and allow widgets to change stuff */
+void uiDrawBlock(const bContext *C, uiBlock *block)
+{
+ uiStyle style= *((uiStyle *)U.uistyles.first); // XXX pass on as arg
+ ARegion *ar;
+ uiBut *but;
+ rcti rect;
+
+ /* get menu region or area region */
+ ar= CTX_wm_menu(C);
+ if(!ar)
+ ar= CTX_wm_region(C);
+
+ if(!block->endblock)
+ uiEndBlock(C, block);
+
+ /* we set this only once */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ /* scale fonts */
+ ui_fontscale(&style.paneltitle.points, block->aspect);
+ ui_fontscale(&style.grouplabel.points, block->aspect);
+ ui_fontscale(&style.widgetlabel.points, block->aspect);
+ ui_fontscale(&style.widget.points, block->aspect);
+
+ /* scale block min/max to rect */
+ ui_but_to_pixelrect(&rect, ar, block, NULL);
+
+ /* pixel space for AA widgets */
+ wmPushMatrix();
+ wmLoadIdentity();
+
+ wmOrtho2(-0.01f, ar->winx-0.01f, -0.01f, ar->winy-0.01f);
+
+ /* back */
+ if(block->flag & UI_BLOCK_LOOP)
+ ui_draw_menu_back(&style, block, &rect);
+ else if(block->panel)
+ ui_draw_panel(ar, &style, block, &rect);
+
+ if(block->drawextra) block->drawextra(C, block);
+
+ /* widgets */
+ for(but= block->buttons.first; but; but= but->next) {
+ ui_but_to_pixelrect(&rect, ar, block, but);
+ ui_draw_but(ar, &style, but, &rect);
+ }
+
+ /* restore matrix */
+ wmPopMatrix();
+
+ ui_draw_links(block);
+}
+
+/* ************* EVENTS ************* */
+
+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 || but->type==ICONTOGN) 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= 2;
+ break;
+ case KEYEVT:
+ if (value==-1) push= 1;
+ break;
+ case TOGBUT:
+ case TOG:
+ case TOGR:
+ case TOG3:
+ case BUT_TOGDUAL:
+ case ICONTOG:
+ if(value!=but->hardmin) push= 1;
+ break;
+ case ICONTOGN:
+ case TOGN:
+ if(value==0.0) push= 1;
+ break;
+ case ROW:
+ if(value == but->hardmax) 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;
+}
+
+/* XXX 2.50 no links supported yet */
+
+#if 0
+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->hardmin ) {
+ 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;
+}
+
+uiBut *uiFindInlink(uiBlock *block, void *poin)
+{
+ return ui_find_inlink(block, poin);
+}
+
+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(ar, bt);
+ }
+ if(bto && bto!=bt) {
+ bto->flag &= ~UI_ACTIVE;
+ ui_draw_but(ar, 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 UI_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;
+}
+#endif
+
+/* ************************************************ */
+
+void uiBlockSetButLock(uiBlock *block, int val, char *lockstr)
+{
+ if(val) {
+ block->lock |= val;
+ block->lockstr= lockstr;
+ }
+}
+
+void uiBlockClearButLock(uiBlock *block)
+{
+ block->lock= 0;
+ block->lockstr= NULL;
+}
+
+/* *************************************************************** */
+
+
+/* XXX 2.50 no links supported yet */
+#if 0
+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(REDRAWBUTSLOGIC, 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) {
+ foundone= 1;
+ 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;
+ }
+ }
+
+ /* check for a 'found one' to prevent going to 'frontbuffer' mode.
+ this slows done gfx quite some, and at OSX the 'finish' forces a swapbuffer */
+ if(foundone) {
+ glDrawBuffer(GL_FRONT);
+
+ /* draw */
+ 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, line);
+ }
+ }
+ else if(line->flag & UI_SELECT) {
+ line->flag &= ~UI_SELECT;
+ ui_draw_linkline(but, line);
+ }
+ line= line->next;
+ }
+ }
+ but= but->next;
+ }
+ bglFlush();
+ glDrawBuffer(GL_BACK);
+ }
+}
+#endif
+
+/* ******************************************************* */
+
+/* XXX 2.50 no screendump supported yet */
+
+#if 0
+/* nasty but safe way to store screendump rect */
+static int scr_x=0, scr_y=0, scr_sizex=0, scr_sizey=0;
+
+static void ui_set_screendump_bbox(uiBlock *block)
+{
+ if(block) {
+ scr_x= block->minx;
+ scr_y= block->miny;
+ scr_sizex= block->maxx - block->minx;
+ scr_sizey= block->maxy - block->miny;
+ }
+ else {
+ scr_sizex= scr_sizey= 0;
+ }
+}
+
+/* used for making screenshots for menus, called in screendump.c */
+int uiIsMenu(int *x, int *y, int *sizex, int *sizey)
+{
+ if(scr_sizex!=0 && scr_sizey!=0) {
+ *x= scr_x;
+ *y= scr_y;
+ *sizex= scr_sizex;
+ *sizey= scr_sizey;
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
+/* *********************** data get/set ***********************
+ * this either works with the pointed to data, or can work with
+ * an edit override pointer while dragging for example */
+
+/* for buttons pointing to color for example */
+void ui_get_but_vectorf(uiBut *but, float *vec)
+{
+ PropertyRNA *prop;
+ int a, tot;
+
+ if(but->editvec) {
+ VECCOPY(vec, but->editvec);
+ return;
+ }
+
+ if(but->rnaprop) {
+ prop= but->rnaprop;
+
+ vec[0]= vec[1]= vec[2]= 0.0f;
+
+ if(RNA_property_type(prop) == PROP_FLOAT) {
+ tot= RNA_property_array_length(prop);
+ tot= MIN2(tot, 3);
+
+ for(a=0; a<tot; a++)
+ vec[a]= RNA_property_float_get_index(&but->rnapoin, prop, a);
+ }
+ }
+ else if(but->pointype == CHA) {
+ char *cp= (char *)but->poin;
+ vec[0]= ((float)cp[0])/255.0;
+ vec[1]= ((float)cp[1])/255.0;
+ vec[2]= ((float)cp[2])/255.0;
+ }
+ else if(but->pointype == FLO) {
+ float *fp= (float *)but->poin;
+ VECCOPY(vec, fp);
+ }
+}
+
+/* for buttons pointing to color for example */
+void ui_set_but_vectorf(uiBut *but, float *vec)
+{
+ PropertyRNA *prop;
+ int a, tot;
+
+ if(but->editvec) {
+ VECCOPY(but->editvec, vec);
+ return;
+ }
+
+ if(but->rnaprop) {
+ prop= but->rnaprop;
+
+ if(RNA_property_type(prop) == PROP_FLOAT) {
+ tot= RNA_property_array_length(prop);
+ tot= MIN2(tot, 3);
+
+ for(a=0; a<tot; a++)
+ RNA_property_float_set_index(&but->rnapoin, prop, a, vec[a]);
+ }
+ }
+ else if(but->pointype == CHA) {
+ char *cp= (char *)but->poin;
+ cp[0]= (char)(0.5 +vec[0]*255.0);
+ cp[1]= (char)(0.5 +vec[1]*255.0);
+ cp[2]= (char)(0.5 +vec[2]*255.0);
+ }
+ else if(but->pointype == FLO) {
+ float *fp= (float *)but->poin;
+ VECCOPY(fp, vec);
+ }
+}
+
+int ui_is_but_float(uiBut *but)
+{
+ if(but->pointype==FLO && but->poin)
+ return 1;
+
+ if(but->rnaprop && RNA_property_type(but->rnaprop) == PROP_FLOAT)
+ return 1;
+
+ return 0;
+}
+
+double ui_get_but_val(uiBut *but)
+{
+ PropertyRNA *prop;
+ double value = 0.0;
+
+ if(but->editval) { return *(but->editval); }
+ if(but->poin==NULL && but->rnapoin.data==NULL) return 0.0;
+
+ if(but->rnaprop) {
+ prop= but->rnaprop;
+
+ switch(RNA_property_type(prop)) {
+ case PROP_BOOLEAN:
+ if(RNA_property_array_length(prop))
+ value= RNA_property_boolean_get_index(&but->rnapoin, prop, but->rnaindex);
+ else
+ value= RNA_property_boolean_get(&but->rnapoin, prop);
+ break;
+ case PROP_INT:
+ if(RNA_property_array_length(prop))
+ value= RNA_property_int_get_index(&but->rnapoin, prop, but->rnaindex);
+ else
+ value= RNA_property_int_get(&but->rnapoin, prop);
+ break;
+ case PROP_FLOAT:
+ if(RNA_property_array_length(prop))
+ value= RNA_property_float_get_index(&but->rnapoin, prop, but->rnaindex);
+ else
+ value= RNA_property_float_get(&but->rnapoin, prop);
+ break;
+ case PROP_ENUM:
+ value= RNA_property_enum_get(&but->rnapoin, prop);
+ break;
+ default:
+ value= 0.0;
+ break;
+ }
+ }
+ else if(but->type== HSVSLI) {
+ float h, s, v, *fp;
+
+ fp= (but->editvec)? but->editvec: (float *)but->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 *)but->poin;
+ }
+ else if( but->pointype == SHO ) {
+ value= *(short *)but->poin;
+ }
+ else if( but->pointype == INT ) {
+ value= *(int *)but->poin;
+ }
+ else if( but->pointype == FLO ) {
+ value= *(float *)but->poin;
+ }
+
+ return value;
+}
+
+void ui_set_but_val(uiBut *but, double value)
+{
+ PropertyRNA *prop;
+
+ /* value is a hsv value: convert to rgb */
+ if(but->rnaprop) {
+ prop= but->rnaprop;
+
+ if(RNA_property_editable(&but->rnapoin, prop)) {
+ switch(RNA_property_type(prop)) {
+ case PROP_BOOLEAN:
+ if(RNA_property_array_length(prop))
+ RNA_property_boolean_set_index(&but->rnapoin, prop, but->rnaindex, value);
+ else
+ RNA_property_boolean_set(&but->rnapoin, prop, value);
+ break;
+ case PROP_INT:
+ if(RNA_property_array_length(prop))
+ RNA_property_int_set_index(&but->rnapoin, prop, but->rnaindex, value);
+ else
+ RNA_property_int_set(&but->rnapoin, prop, value);
+ break;
+ case PROP_FLOAT:
+ if(RNA_property_array_length(prop))
+ RNA_property_float_set_index(&but->rnapoin, prop, but->rnaindex, value);
+ else
+ RNA_property_float_set(&but->rnapoin, prop, value);
+ break;
+ case PROP_ENUM:
+ RNA_property_enum_set(&but->rnapoin, prop, value);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else if(but->pointype==0);
+ else if(but->type==HSVSLI ) {
+ float h, s, v, *fp;
+
+ fp= (but->editvec)? but->editvec: (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 {
+ /* first do rounding */
+ if(but->pointype==CHA)
+ value= (char)floor(value+0.5);
+ else if(but->pointype==SHO ) {
+ /* gcc 3.2.1 seems to have problems
+ * casting a double like 32772.0 to
+ * a short so we cast to an int, then
+ to a short */
+ int gcckludge;
+ gcckludge = (int) floor(value+0.5);
+ value= (short)gcckludge;
+ }
+ else if(but->pointype==INT )
+ value= (int)floor(value+0.5);
+ else if(but->pointype==FLO ) {
+ float fval= (float)value;
+ if(fval>= -0.00001f && fval<= 0.00001f) fval= 0.0f; /* prevent negative zero */
+ value= fval;
+ }
+
+ /* then set value with possible edit override */
+ if(but->editval)
+ *but->editval= value;
+ else if(but->pointype==CHA)
+ *((char *)but->poin)= (char)value;
+ else if(but->pointype==SHO)
+ *((short *)but->poin)= (short)value;
+ else if(but->pointype==INT)
+ *((int *)but->poin)= (int)value;
+ else if(but->pointype==FLO)
+ *((float *)but->poin)= (float)value;
+ }
+
+ /* update select flag */
+ ui_is_but_sel(but);
+}
+
+int ui_get_but_string_max_length(uiBut *but)
+{
+ if(but->type == TEX)
+ return but->hardmax;
+ else if(but->type == IDPOIN)
+ return sizeof(((ID*)NULL)->name)-2;
+ else
+ return UI_MAX_DRAW_STR;
+}
+
+void ui_get_but_string(uiBut *but, char *str, int maxlen)
+{
+ if(but->rnaprop && ELEM(but->type, TEX, IDPOIN)) {
+ PropertyType type;
+ char *buf= NULL;
+
+ type= RNA_property_type(but->rnaprop);
+
+ if(type == PROP_STRING) {
+ /* RNA string */
+ buf= RNA_property_string_get_alloc(&but->rnapoin, but->rnaprop, str, maxlen);
+ }
+ else if(type == PROP_POINTER) {
+ /* RNA pointer */
+ PointerRNA ptr= RNA_property_pointer_get(&but->rnapoin, but->rnaprop);
+ PropertyRNA *nameprop;
+
+ if(ptr.data && (nameprop = RNA_struct_name_property(ptr.type)))
+ buf= RNA_property_string_get_alloc(&ptr, nameprop, str, maxlen);
+ else
+ BLI_strncpy(str, "", maxlen);
+ }
+ else
+ BLI_strncpy(str, "", maxlen);
+
+ if(buf && buf != str) {
+ /* string was too long, we have to truncate */
+ BLI_strncpy(str, buf, maxlen);
+ MEM_freeN(buf);
+ }
+ }
+ else if(but->type == IDPOIN) {
+ /* ID pointer */
+ ID *id= *(but->idpoin_idpp);
+
+ if(id) BLI_strncpy(str, id->name+2, maxlen);
+ else BLI_strncpy(str, "", maxlen);
+
+ return;
+ }
+ else if(but->type == TEX) {
+ /* string */
+ BLI_strncpy(str, but->poin, maxlen);
+ return;
+ }
+ else {
+ /* number */
+ double value;
+
+ value= ui_get_but_val(but);
+
+ if(ui_is_but_float(but)) {
+ if(but->a2) { /* amount of digits defined */
+ if(but->a2==1) BLI_snprintf(str, maxlen, "%.1f", value);
+ else if(but->a2==2) BLI_snprintf(str, maxlen, "%.2f", value);
+ else if(but->a2==3) BLI_snprintf(str, maxlen, "%.3f", value);
+ else BLI_snprintf(str, maxlen, "%.4f", value);
+ }
+ else
+ BLI_snprintf(str, maxlen, "%.3f", value);
+ }
+ else
+ BLI_snprintf(str, maxlen, "%d", (int)value);
+ }
+}
+
+static void ui_rna_ID_collection(bContext *C, uiBut *but, PointerRNA *ptr, PropertyRNA **prop)
+{
+ CollectionPropertyIterator iter;
+ PropertyRNA *iterprop, *iprop;
+ StructRNA *srna;
+
+ /* look for collection property in Main */
+ RNA_pointer_create(NULL, &RNA_Main, CTX_data_main(C), ptr);
+
+ iterprop= RNA_struct_iterator_property(ptr->type);
+ RNA_property_collection_begin(ptr, iterprop, &iter);
+ *prop= NULL;
+
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ iprop= iter.ptr.data;
+
+ /* if it's a collection and has same pointer type, we've got it */
+ if(RNA_property_type(iprop) == PROP_COLLECTION) {
+ srna= RNA_property_pointer_type(iprop);
+
+ if(RNA_property_pointer_type(but->rnaprop) == srna) {
+ *prop= iprop;
+ break;
+ }
+ }
+ }
+
+ RNA_property_collection_end(&iter);
+}
+
+/* autocomplete callback for RNA pointers */
+static void ui_rna_ID_autocomplete(bContext *C, char *str, void *arg_but)
+{
+ uiBut *but= arg_but;
+ AutoComplete *autocpl;
+ CollectionPropertyIterator iter;
+ PointerRNA ptr;
+ PropertyRNA *prop, *nameprop;
+ char *name;
+
+ if(str[0]==0) return;
+
+ /* get the collection */
+ ui_rna_ID_collection(C, but, &ptr, &prop);
+ if(prop==NULL) return;
+
+ autocpl= autocomplete_begin(str, ui_get_but_string_max_length(but));
+ RNA_property_collection_begin(&ptr, prop, &iter);
+
+ /* loop over items in collection */
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) {
+ name= RNA_property_string_get_alloc(&iter.ptr, nameprop, NULL, 0);
+
+ if(name) {
+ /* test item name */
+ autocomplete_do_name(autocpl, name);
+ MEM_freeN(name);
+ }
+ }
+ }
+
+ RNA_property_collection_end(&iter);
+ autocomplete_end(autocpl, str);
+}
+
+int ui_set_but_string(bContext *C, uiBut *but, const char *str)
+{
+ if(but->rnaprop && ELEM(but->type, TEX, IDPOIN)) {
+ if(RNA_property_editable(&but->rnapoin, but->rnaprop)) {
+ PropertyType type;
+
+ type= RNA_property_type(but->rnaprop);
+
+ if(type == PROP_STRING) {
+ /* RNA string */
+ RNA_property_string_set(&but->rnapoin, but->rnaprop, str);
+ return 1;
+ }
+ else if(type == PROP_POINTER) {
+ /* RNA pointer */
+ PointerRNA ptr, rptr;
+ PropertyRNA *prop;
+
+ /* XXX only ID pointers at the moment, needs to support
+ * custom collection too for bones, vertex groups, .. */
+ ui_rna_ID_collection(C, but, &ptr, &prop);
+
+ if(prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr)) {
+ RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr);
+ return 1;
+ }
+ else
+ return 0;
+ }
+ }
+ }
+ else if(but->type == IDPOIN) {
+ /* ID pointer */
+ but->idpoin_func(C, (char*)str, but->idpoin_idpp);
+ return 1;
+ }
+ else if(but->type == TEX) {
+ /* string */
+ BLI_strncpy(but->poin, str, but->hardmax);
+ return 1;
+ }
+ else {
+ double value;
+
+ /* XXX 2.50 missing python api */
+#if 0
+ if(BPY_button_eval(str, &value)) {
+ BKE_report(CTX_reports(C), RPT_WARNING, "Invalid Python expression, check console");
+ value = 0.0f; /* Zero out value on error */
+
+ if(str[0])
+ return 0;
+ }
+#else
+ value= atof(str);
+#endif
+
+ if(!ui_is_but_float(but)) value= (int)value;
+ if(but->type==NUMABS) value= fabs(value);
+
+ /* not that we use hard limits here */
+ if(value<but->hardmin) value= but->hardmin;
+ if(value>but->hardmax) value= but->hardmax;
+
+ ui_set_but_val(but, value);
+ return 1;
+ }
+
+ return 0;
+}
+
+static double soft_range_round_up(double value, double max)
+{
+ /* round up to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, .. */
+ double newmax= pow(10.0, ceil(log(value)/log(10.0)));
+
+ if(newmax*0.2 >= max && newmax*0.2 >= value)
+ return newmax*0.2;
+ else if(newmax*0.5 >= max && newmax*0.5 >= value)
+ return newmax*0.5;
+ else
+ return newmax;
+}
+
+static double soft_range_round_down(double value, double max)
+{
+ /* round down to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, .. */
+ double newmax= pow(10.0, floor(log(value)/log(10.0)));
+
+ if(newmax*5.0 <= max && newmax*5.0 <= value)
+ return newmax*5.0;
+ else if(newmax*2.0 <= max && newmax*2.0 <= value)
+ return newmax*2.0;
+ else
+ return newmax;
+}
+
+void ui_set_but_soft_range(uiBut *but, double value)
+{
+ PropertyType type;
+ double softmin, softmax, step, precision;
+
+ if(but->rnaprop) {
+ type= RNA_property_type(but->rnaprop);
+
+ if(type == PROP_INT) {
+ int imin, imax, istep;
+
+ RNA_property_int_ui_range(&but->rnapoin, but->rnaprop, &imin, &imax, &istep);
+ softmin= imin;
+ softmax= imax;
+ step= istep;
+ precision= 1;
+ }
+ else if(type == PROP_FLOAT) {
+ float fmin, fmax, fstep, fprecision;
+
+ RNA_property_float_ui_range(&but->rnapoin, but->rnaprop, &fmin, &fmax, &fstep, &fprecision);
+ softmin= fmin;
+ softmax= fmax;
+ step= fstep;
+ precision= fprecision;
+ }
+ else
+ return;
+
+ /* clamp button range to something reasonable in case
+ * we get -inf/inf from RNA properties */
+ softmin= MAX2(softmin, -1e4);
+ softmax= MIN2(softmax, 1e4);
+
+ /* if the value goes out of the soft/max range, adapt the range */
+ if(value+1e-10 < softmin) {
+ if(value < 0.0)
+ softmin= -soft_range_round_up(-value, -softmin);
+ else
+ softmin= soft_range_round_down(value, softmin);
+
+ if(softmin < but->hardmin)
+ softmin= but->hardmin;
+ }
+ else if(value-1e-10 > softmax) {
+ if(value < 0.0)
+ softmax= -soft_range_round_down(-value, -softmax);
+ else
+ softmax= soft_range_round_up(value, softmax);
+
+ if(softmax > but->hardmax)
+ softmax= but->hardmax;
+ }
+
+ but->softmin= softmin;
+ but->softmax= softmax;
+ }
+}
+
+/* ******************* Free ********************/
+
+static void ui_free_link(uiLink *link)
+{
+ if(link) {
+ BLI_freelistN(&link->lines);
+ MEM_freeN(link);
+ }
+}
+
+/* can be called with C==NULL */
+static void ui_free_but(const bContext *C, uiBut *but)
+{
+ if(but->opptr) {
+ WM_operator_properties_free(but->opptr);
+ MEM_freeN(but->opptr);
+ }
+ if(but->func_argN) MEM_freeN(but->func_argN);
+ if(but->active) {
+ /* XXX solve later, buttons should be free-able without context? */
+ if(C)
+ ui_button_active_cancel(C, but);
+ else
+ if(but->active)
+ MEM_freeN(but->active);
+ }
+ if(but->str && but->str != but->strdata) MEM_freeN(but->str);
+ ui_free_link(but->link);
+
+ MEM_freeN(but);
+}
+
+/* can be called with C==NULL */
+void uiFreeBlock(const bContext *C, uiBlock *block)
+{
+ uiBut *but;
+
+ while( (but= block->buttons.first) ) {
+ BLI_remlink(&block->buttons, but);
+ ui_free_but(C, but);
+ }
+
+ BLI_freelistN(&block->saferct);
+
+ MEM_freeN(block);
+}
+
+/* can be called with C==NULL */
+void uiFreeBlocks(const bContext *C, ListBase *lb)
+{
+ uiBlock *block;
+
+ while( (block= lb->first) ) {
+ BLI_remlink(lb, block);
+ uiFreeBlock(C, block);
+ }
+}
+
+void uiFreeInactiveBlocks(const bContext *C, ListBase *lb)
+{
+ uiBlock *block, *nextblock;
+
+ for(block=lb->first; block; block=nextblock) {
+ nextblock= block->next;
+
+ if(!block->handle) {
+ if(!block->active) {
+ BLI_remlink(lb, block);
+ uiFreeBlock(C, block);
+ }
+ else
+ block->active= 0;
+ }
+ }
+}
+
+uiBlock *uiBeginBlock(const bContext *C, ARegion *region, const char *name, short dt)
+{
+ ListBase *lb;
+ uiBlock *block, *oldblock= NULL;
+ wmWindow *window;
+ int getsizex, getsizey;
+
+ window= CTX_wm_window(C);
+ lb= &region->uiblocks;
+
+ /* each listbase only has one block with this name, free block
+ * if is already there so it can be rebuilt from scratch */
+ if(lb) {
+ for (oldblock= lb->first; oldblock; oldblock= oldblock->next)
+ if (BLI_streq(oldblock->name, name))
+ break;
+
+ if (oldblock) {
+ oldblock->active= 0;
+ oldblock->panel= NULL;
+ }
+ }
+
+ block= MEM_callocN(sizeof(uiBlock), "uiBlock");
+ block->oldblock= oldblock;
+ block->active= 1;
+ block->dt= dt;
+
+ /* at the beginning of the list! for dynamical menus/blocks */
+ if(lb)
+ BLI_addhead(lb, block);
+
+ BLI_strncpy(block->name, name, sizeof(block->name));
+
+ /* window matrix and aspect */
+ if(region->swinid) {
+ wm_subwindow_getmatrix(window, region->swinid, block->winmat);
+ wm_subwindow_getsize(window, region->swinid, &getsizex, &getsizey);
+
+ /* TODO - investigate why block->winmat[0][0] is negative
+ * in the image view when viewRedrawForce is called */
+ block->aspect= 2.0/fabs( (getsizex)*block->winmat[0][0]);
+ }
+ else {
+ /* no subwindow created yet, for menus for example, so we
+ * use the main window instead, since buttons are created
+ * there anyway */
+ wm_subwindow_getmatrix(window, window->screen->mainwin, block->winmat);
+ wm_subwindow_getsize(window, window->screen->mainwin, &getsizex, &getsizey);
+
+ block->aspect= 2.0/fabs(getsizex*block->winmat[0][0]);
+ block->auto_open= 2;
+ block->flag |= UI_BLOCK_LOOP; /* tag as menu */
+ }
+
+ return block;
+}
+
+uiBlock *uiGetBlock(char *name, ARegion *ar)
+{
+ uiBlock *block= ar->uiblocks.first;
+
+ while(block) {
+ if( strcmp(name, block->name)==0 ) return block;
+ block= block->next;
+ }
+
+ return NULL;
+}
+
+void uiBlockSetEmboss(uiBlock *block, short dt)
+{
+ block->dt= dt;
+}
+
+void ui_check_but(uiBut *but)
+{
+ /* if something changed in the button */
+ double value;
+ float okwidth;
+ int transopts= ui_translate_buttons();
+
+ ui_is_but_sel(but);
+
+ if(but->type==TEX || but->type==IDPOIN) transopts= 0;
+
+ /* 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->hardmin) ui_set_but_val(but, but->hardmin);
+ else if(value > but->hardmax) ui_set_but_val(but, but->hardmax);
+ break;
+
+ case NUMABS:
+ value= fabs( ui_get_but_val(but) );
+ if(value < but->hardmin) ui_set_but_val(but, but->hardmin);
+ else if(value > but->hardmax) ui_set_but_val(but, but->hardmax);
+ break;
+
+ case ICONTOG:
+ case ICONTOGN:
+ 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->hardmin);
+ break;
+
+ case ICONTEXTROW:
+ value= ui_get_but_val(but);
+ but->iconadd= (int)value- (int)(but->hardmin);
+ break;
+ }
+
+
+ /* safety is 4 to enable small number buttons (like 'users') */
+ okwidth= -4 + (but->x2 - but->x1);
+
+ /* name: */
+ switch( but->type ) {
+
+ case MENU:
+ case ICONTEXTROW:
+
+ 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:
+ case NUMABS:
+
+ value= ui_get_but_val(but);
+
+ if(ui_is_but_float(but)) {
+ if(value == FLT_MAX) sprintf(but->drawstr, "%sinf", but->str);
+ else if(value == -FLT_MAX) sprintf(but->drawstr, "%s-inf", but->str);
+ else if(but->a2) { /* amount of digits defined */
+ if(but->a2==1) sprintf(but->drawstr, "%s%.1f", but->str, value);
+ else if(but->a2==2) sprintf(but->drawstr, "%s%.2f", but->str, value);
+ else if(but->a2==3) sprintf(but->drawstr, "%s%.3f", but->str, value);
+ else sprintf(but->drawstr, "%s%.4f", but->str, value);
+ }
+ else {
+ if(but->hardmax<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);
+ }
+
+ if(but->rnaprop) {
+ PropertySubType pstype = RNA_property_subtype(but->rnaprop);
+
+ if (pstype == PROP_PERCENTAGE)
+ strcat(but->drawstr, "%");
+ }
+ break;
+
+ case LABEL:
+ if(ui_is_but_float(but)) {
+ value= ui_get_but_val(but);
+ if(but->a2) { /* amount of digits defined */
+ if(but->a2==1) sprintf(but->drawstr, "%s%.1f", but->str, value);
+ else if(but->a2==2) sprintf(but->drawstr, "%s%.2f", but->str, value);
+ else if(but->a2==3) sprintf(but->drawstr, "%s%.3f", but->str, value);
+ else sprintf(but->drawstr, "%s%.4f", but->str, value);
+ }
+ else {
+ sprintf(but->drawstr, "%s%.2f", but->str, value);
+ }
+ }
+ else strcpy(but->drawstr, but->str);
+
+ break;
+
+ case IDPOIN:
+ case TEX:
+ if(!but->editstr) {
+ char str[UI_MAX_DRAW_STR];
+
+ ui_get_but_string(but, str, UI_MAX_DRAW_STR-strlen(but->str));
+
+ strcpy(but->drawstr, but->str);
+ strcat(but->drawstr, str);
+ }
+ break;
+
+ case KEYEVT:
+ strcpy(but->drawstr, but->str);
+ if (but->flag & UI_SELECT) {
+ strcat(but->drawstr, "Press a key");
+ } else {
+ strcat(but->drawstr, WM_key_event_string((short) ui_get_but_val(but)));
+ }
+ break;
+
+ case BUT_TOGDUAL:
+ /* trying to get the dual-icon to left of text... not very nice */
+ if(but->str[0]) {
+ strcpy(but->drawstr, " ");
+ strcpy(but->drawstr+2, but->str);
+ }
+ break;
+ default:
+ strcpy(but->drawstr, but->str);
+
+ }
+
+ /* if we are doing text editing, this will override the drawstr */
+ if(but->editstr) {
+ strcpy(but->drawstr, but->str);
+ strcat(but->drawstr, but->editstr);
+ }
+
+ /* text clipping moved to widget drawing code itself */
+}
+
+
+void uiBlockBeginAlign(uiBlock *block)
+{
+ /* if other align was active, end it */
+ if(block->flag & UI_BUT_ALIGN) uiBlockEndAlign(block);
+
+ block->flag |= UI_BUT_ALIGN_DOWN;
+ /* buttons declared after this call will this align flag */
+}
+
+static int buts_are_horiz(uiBut *but1, uiBut *but2)
+{
+ float dx, dy;
+
+ dx= fabs( but1->x2 - but2->x1);
+ dy= fabs( but1->y1 - but2->y2);
+
+ if(dx > dy) return 0;
+ return 1;
+}
+
+void uiBlockEndAlign(uiBlock *block)
+{
+ uiBut *prev, *but=NULL, *next;
+ int flag= 0, cols=0, rows=0;
+ int theme= UI_GetThemeValue(TH_BUT_DRAWTYPE);
+
+ if ( !(ELEM4(theme, TH_MINIMAL, TH_SHADED, TH_ROUNDED, TH_ROUNDSHADED)) ) {
+ block->flag &= ~UI_BUT_ALIGN; // all 4 flags
+ return;
+ }
+
+ /* auto align:
+ - go back to first button of align start (ALIGN_DOWN)
+ - compare triples, and define flags
+ */
+ prev= block->buttons.last;
+ while(prev) {
+ if( (prev->flag & UI_BUT_ALIGN_DOWN)) but= prev;
+ else break;
+
+ if(but && but->next) {
+ if(buts_are_horiz(but, but->next)) cols++;
+ else rows++;
+ }
+
+ prev= prev->prev;
+ }
+ if(but==NULL) return;
+
+ /* rows==0: 1 row, cols==0: 1 collumn */
+
+ /* note; how it uses 'flag' in loop below (either set it, or OR it) is confusing */
+ prev= NULL;
+ while(but) {
+ next= but->next;
+
+ /* clear old flag */
+ but->flag &= ~UI_BUT_ALIGN_DOWN;
+
+ if(flag==0) { /* first case */
+ if(next) {
+ if(buts_are_horiz(but, next)) {
+ if(rows==0)
+ flag= UI_BUT_ALIGN_RIGHT;
+ else
+ flag= UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT;
+ }
+ else {
+ flag= UI_BUT_ALIGN_DOWN;
+ }
+ }
+ }
+ else if(next==NULL) { /* last case */
+ if(prev) {
+ if(buts_are_horiz(prev, but)) {
+ if(rows==0)
+ flag= UI_BUT_ALIGN_LEFT;
+ else
+ flag= UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT;
+ }
+ else flag= UI_BUT_ALIGN_TOP;
+ }
+ }
+ else if(buts_are_horiz(but, next)) {
+ /* check if this is already second row */
+ if( prev && buts_are_horiz(prev, but)==0) {
+ flag |= UI_BUT_ALIGN_TOP;
+ /* exception case: bottom row */
+ if(rows>0) {
+ uiBut *bt= but;
+ while(bt) {
+ if(bt->next && buts_are_horiz(bt, bt->next)==0 ) break;
+ bt= bt->next;
+ }
+ if(bt==0) flag= UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT;
+ }
+ }
+ else flag |= UI_BUT_ALIGN_LEFT;
+ }
+ else {
+ if(cols==0) {
+ flag |= UI_BUT_ALIGN_TOP;
+ }
+ else { /* next button switches to new row */
+ if( (flag & UI_BUT_ALIGN_TOP)==0) { /* stil top row */
+ if(prev)
+ flag= UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT;
+ else
+ flag |= UI_BUT_ALIGN_DOWN;
+ }
+ else
+ flag |= UI_BUT_ALIGN_TOP;
+ }
+ }
+
+ but->flag |= flag;
+
+ /* merge coordinates */
+ if(prev) {
+ // simple cases
+ if(rows==0) {
+ but->x1= (prev->x2+but->x1)/2.0;
+ prev->x2= but->x1;
+ }
+ else if(cols==0) {
+ but->y2= (prev->y1+but->y2)/2.0;
+ prev->y1= but->y2;
+ }
+ else {
+ if(buts_are_horiz(prev, but)) {
+ but->x1= (prev->x2+but->x1)/2.0;
+ prev->x2= but->x1;
+ /* copy height too */
+ but->y2= prev->y2;
+ }
+ else if(prev->prev && buts_are_horiz(prev->prev, prev)==0) {
+ /* the previous button is a single one in its row */
+ but->y2= (prev->y1+but->y2)/2.0;
+ prev->y1= but->y2;
+ }
+ else {
+ /* the previous button is not a single one in its row */
+ but->y2= prev->y1;
+ }
+ }
+ }
+
+ prev= but;
+ but= next;
+ }
+
+ block->flag &= ~UI_BUT_ALIGN; // all 4 flags
+}
+
+#if 0
+static void uiBlockEndAligno(uiBlock *block)
+{
+ uiBut *but;
+
+ /* correct last defined button */
+ but= block->buttons.last;
+ if(but) {
+ /* vertical align case */
+ if( (block->flag & UI_BUT_ALIGN) == (UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_DOWN) ) {
+ but->flag &= ~UI_BUT_ALIGN_DOWN;
+ }
+ /* horizontal align case */
+ if( (block->flag & UI_BUT_ALIGN) == (UI_BUT_ALIGN_LEFT|UI_BUT_ALIGN_RIGHT) ) {
+ but->flag &= ~UI_BUT_ALIGN_RIGHT;
+ }
+ /* else do nothing, manually provided flags */
+ }
+ block->flag &= ~UI_BUT_ALIGN; // all 4 flags
+}
+#endif
+
+/*
+ui_def_but is the function that draws many button types
+
+for float buttons:
+ "a1" Click Step (how much to change the value each click)
+ "a2" Number of decimal point values to display. 0 defaults to 3 (0.000) 1,2,3, and a maximum of 4,
+ all greater values will be clamped to 4.
+
+*/
+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) { /* a pointer is required */
+ if(poin==NULL)
+ return NULL;
+ }
+
+ but= MEM_callocN(sizeof(uiBut), "uiBut");
+
+ but->type= type & BUTTYPE;
+ but->pointype= type & BUTPOIN;
+ but->bit= type & BIT;
+ but->bitnr= type & 31;
+ but->icon = 0;
+
+ 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;
+ but->x2= (x1+x2);
+ but->y2= (y1+y2);
+
+ but->poin= poin;
+ but->hardmin= but->softmin= min;
+ but->hardmax= but->softmax= max;
+ but->a1= a1;
+ but->a2= a2;
+ but->tip= tip;
+
+ but->lock= block->lock;
+ but->lockstr= block->lockstr;
+ but->dt= block->dt;
+
+ but->aspect= 1.0f; //XXX block->aspect;
+ but->block= block; // pointer back, used for frontbuffer status, and picker
+
+ but->func= block->func;
+ but->func_arg1= block->func_arg1;
+ but->func_arg2= block->func_arg2;
+
+ but->pos= -1; /* cursor invisible */
+
+ if(ELEM(but->type, NUM, NUMABS)) { /* add a space to name */
+ 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(but->type==HSVCUBE) { /* hsv buttons temp storage */
+ float rgb[3];
+ ui_get_but_vectorf(but, rgb);
+ rgb_to_hsv(rgb[0], rgb[1], rgb[2], but->hsv, but->hsv+1, but->hsv+2);
+ }
+
+ if((block->flag & UI_BLOCK_LOOP) || ELEM6(but->type, MENU, TEX, LABEL, IDPOIN, BLOCK, BUTM)) {
+ but->flag |= UI_TEXT_LEFT;
+ }
+
+ if(but->type==BUT_TOGDUAL) {
+ but->flag |= UI_ICON_LEFT;
+ }
+
+ but->flag |= (block->flag & UI_BUT_ALIGN);
+ if(block->flag & UI_BLOCK_NO_HILITE)
+ but->flag |= UI_NO_HILITE;
+
+ if (but->lock) {
+ if (but->lockstr) {
+ but->flag |= UI_BUT_DISABLED;
+ }
+ }
+
+ if(but->type == ROUNDBOX) {
+ but->flag |= UI_NO_HILITE;
+ BLI_addhead(&block->buttons, but);
+ }
+ else
+ BLI_addtail(&block->buttons, but);
+
+ return but;
+}
+
+uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, char *tip)
+{
+ uiBut *but;
+ PropertyRNA *prop;
+ PropertyType proptype;
+ int freestr= 0;
+
+ prop= RNA_struct_find_property(ptr, propname);
+
+ if(prop) {
+ proptype= RNA_property_type(prop);
+
+ /* use rna values if parameters are not specified */
+ if(!str) {
+ if(type == MENU && proptype == PROP_ENUM) {
+ const EnumPropertyItem *item;
+ DynStr *dynstr;
+ int i, totitem;
+
+ RNA_property_enum_items(ptr, prop, &item, &totitem);
+
+ dynstr= BLI_dynstr_new();
+ BLI_dynstr_appendf(dynstr, "%s%%t", RNA_property_ui_name(prop));
+ for(i=0; i<totitem; i++)
+ BLI_dynstr_appendf(dynstr, "|%s %%x%d", item[i].name, item[i].value);
+ str= BLI_dynstr_get_cstring(dynstr);
+ BLI_dynstr_free(dynstr);
+
+ freestr= 1;
+ }
+ else if(type == ROW && proptype == PROP_ENUM) {
+ const EnumPropertyItem *item;
+ int i, totitem;
+
+ RNA_property_enum_items(ptr, prop, &item, &totitem);
+ for(i=0; i<totitem; i++)
+ if(item[i].value == (int)max)
+ str= (char*)item[i].name;
+
+ if(!str)
+ str= (char*)RNA_property_ui_name(prop);
+ }
+ else
+ str= (char*)RNA_property_ui_name(prop);
+ }
+
+ if(!tip) {
+ if(type == ROW && proptype == PROP_ENUM) {
+ const EnumPropertyItem *item;
+ int i, totitem;
+
+ RNA_property_enum_items(ptr, prop, &item, &totitem);
+
+ for(i=0; i<totitem; i++) {
+ if(item[i].value == (int)max) {
+ if(item[i].description[0])
+ tip= (char*)item[i].description;
+ break;
+ }
+ }
+ }
+ }
+
+ if(!tip)
+ tip= (char*)RNA_property_ui_description(prop);
+
+ if(min == max || a1 == -1 || a2 == -1) {
+ if(proptype == PROP_INT) {
+ int hardmin, hardmax, softmin, softmax, step;
+
+ RNA_property_int_range(ptr, prop, &hardmin, &hardmax);
+ RNA_property_int_ui_range(ptr, prop, &softmin, &softmax, &step);
+
+ if(min == max) {
+ min= hardmin;
+ max= hardmax;
+ }
+ if(a1 == -1)
+ a1= step;
+ if(a2 == -1)
+ a2= 0;
+ }
+ else if(proptype == PROP_FLOAT) {
+ float hardmin, hardmax, softmin, softmax, step, precision;
+
+ RNA_property_float_range(ptr, prop, &hardmin, &hardmax);
+ RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
+
+ if(min == max) {
+ min= hardmin;
+ max= hardmax;
+ }
+ if(a1 == -1)
+ a1= step;
+ if(a2 == -1)
+ a2= precision;
+ }
+ else if(proptype == PROP_STRING) {
+ min= 0;
+ max= RNA_property_string_maxlength(prop);
+ if(max == 0) /* interface code should ideally support unlimited length */
+ max= UI_MAX_DRAW_STR;
+ }
+ }
+ }
+ else
+ str= (char*)propname;
+
+ /* now create button */
+ but= ui_def_but(block, type, retval, str, x1, y1, x2, y2, NULL, min, max, a1, a2, tip);
+
+ if(prop) {
+ but->rnapoin= *ptr;
+ but->rnaprop= prop;
+
+ if(RNA_property_array_length(but->rnaprop))
+ but->rnaindex= index;
+ else
+ but->rnaindex= 0;
+
+ if(type == IDPOIN)
+ uiButSetCompleteFunc(but, ui_rna_ID_autocomplete, but);
+ }
+
+ if (!prop || !RNA_property_editable(&but->rnapoin, prop)) {
+ but->flag |= UI_BUT_DISABLED;
+ but->lock = 1;
+ but->lockstr = "";
+ }
+
+ if(freestr)
+ MEM_freeN(str);
+
+ return but;
+}
+
+uiBut *ui_def_but_operator(uiBlock *block, int type, char *opname, int opcontext, char *str, short x1, short y1, short x2, short y2, char *tip)
+{
+ uiBut *but;
+ wmOperatorType *ot;
+
+ ot= WM_operatortype_find(opname);
+
+ if(!str) {
+ if(ot) str= ot->name;
+ else str= opname;
+ }
+
+ if ((!tip || tip[0]=='\0') && ot && ot->description) {
+ tip= ot->description;
+ }
+
+ but= ui_def_but(block, type, -1, str, x1, y1, x2, y2, NULL, 0, 0, 0, 0, tip);
+ but->opname= opname;
+ but->opcontext= opcontext;
+
+ if(!ot) {
+ but->flag |= UI_BUT_DISABLED;
+ but->lock = 1;
+ but->lockstr = "";
+ }
+
+ 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;
+}
+
+ /* if _x_ is a power of two (only one bit) return the power,
+ * otherwise return -1.
+ * (1<<findBitIndex(x))==x for powers of two.
+ */
+static int findBitIndex(unsigned int x) {
+ if (!x || (x&(x-1))!=0) { /* x&(x-1) strips lowest bit */
+ return -1;
+ } else {
+ int idx= 0;
+
+ if (x&0xFFFF0000) idx+=16, x>>=16;
+ if (x&0xFF00) idx+=8, x>>=8;
+ if (x&0xF0) idx+=4, x>>=4;
+ if (x&0xC) idx+=2, x>>=2;
+ if (x&0x2) idx+=1;
+
+ return idx;
+ }
+}
+
+/* autocomplete helper functions */
+struct AutoComplete {
+ int maxlen;
+ char *truncate;
+ char *startname;
+};
+
+AutoComplete *autocomplete_begin(char *startname, int maxlen)
+{
+ AutoComplete *autocpl;
+
+ autocpl= MEM_callocN(sizeof(AutoComplete), "AutoComplete");
+ autocpl->maxlen= maxlen;
+ autocpl->truncate= MEM_callocN(sizeof(char)*maxlen, "AutoCompleteTruncate");
+ autocpl->startname= startname;
+
+ return autocpl;
+}
+
+void autocomplete_do_name(AutoComplete *autocpl, const char *name)
+{
+ char *truncate= autocpl->truncate;
+ char *startname= autocpl->startname;
+ int a;
+
+ for(a=0; a<autocpl->maxlen-1; a++) {
+ if(startname[a]==0 || startname[a]!=name[a])
+ break;
+ }
+ /* found a match */
+ if(startname[a]==0) {
+ /* first match */
+ if(truncate[0]==0)
+ BLI_strncpy(truncate, name, autocpl->maxlen);
+ else {
+ /* remove from truncate what is not in bone->name */
+ for(a=0; a<autocpl->maxlen-1; a++) {
+ if(truncate[a]!=name[a])
+ truncate[a]= 0;
+ }
+ }
+ }
+}
+
+void autocomplete_end(AutoComplete *autocpl, char *autoname)
+{
+ if(autocpl->truncate[0])
+ BLI_strncpy(autoname, autocpl->truncate, autocpl->maxlen);
+ else {
+ if (autoname != autocpl->startname) /* dont copy a string over its self */
+ BLI_strncpy(autoname, autocpl->startname, autocpl->maxlen);
+ }
+ MEM_freeN(autocpl->truncate);
+ MEM_freeN(autocpl);
+}
+
+/* autocomplete callback for ID buttons */
+static void autocomplete_id(bContext *C, char *str, void *arg_v)
+{
+ int blocktype= (intptr_t)arg_v;
+ ListBase *listb= wich_libbase(CTX_data_main(C), blocktype);
+
+ if(listb==NULL) return;
+
+ /* search if str matches the beginning of an ID struct */
+ if(str[0]) {
+ AutoComplete *autocpl= autocomplete_begin(str, 22);
+ ID *id;
+
+ for(id= listb->first; id; id= id->next)
+ autocomplete_do_name(autocpl, id->name+2);
+
+ autocomplete_end(autocpl, str);
+ }
+}
+
+static uiBut *uiDefButBit(uiBlock *block, int type, int bit, int retval, char *str, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, char *tip)
+{
+ int bitIdx= findBitIndex(bit);
+ if (bitIdx==-1) {
+ return NULL;
+ } else {
+ return uiDefBut(block, type|BIT|bitIdx, retval, str, x1, y1, x2, y2, poin, min, max, a1, a2, 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)
+{
+ return uiDefBut(block, type|FLO, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefButBitF(uiBlock *block, int type, int bit, 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 uiDefButBit(block, type|FLO, bit, 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 *uiDefButBitI(uiBlock *block, int type, int bit, 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 uiDefButBit(block, type|INT, bit, 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 *uiDefButBitS(uiBlock *block, int type, int bit, 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 uiDefButBit(block, type|SHO, bit, 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 *uiDefButBitC(uiBlock *block, int type, int bit, 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 uiDefButBit(block, type|CHA, bit, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefButR(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, char *tip)
+{
+ uiBut *but;
+
+ but= ui_def_but_rna(block, type, retval, str, x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip);
+ if(but)
+ ui_check_but(but);
+
+ return but;
+}
+uiBut *uiDefButO(uiBlock *block, int type, char *opname, int opcontext, char *str, short x1, short y1, short x2, short y2, char *tip)
+{
+ uiBut *but;
+
+ but= ui_def_but_operator(block, type, opname, opcontext, str, x1, y1, x2, y2, tip);
+ if(but)
+ ui_check_but(but);
+
+ return but;
+}
+
+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;
+}
+static uiBut *uiDefIconButBit(uiBlock *block, int type, int bit, int retval, int icon, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, char *tip)
+{
+ int bitIdx= findBitIndex(bit);
+ if (bitIdx==-1) {
+ return NULL;
+ } else {
+ return uiDefIconBut(block, type|BIT|bitIdx, retval, icon, x1, y1, x2, y2, poin, min, max, a1, a2, 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)
+{
+ return uiDefIconBut(block, type|FLO, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefIconButBitF(uiBlock *block, int type, int bit, 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 uiDefIconButBit(block, type|FLO, bit, 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 *uiDefIconButBitI(uiBlock *block, int type, int bit, 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 uiDefIconButBit(block, type|INT, bit, 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 *uiDefIconButBitS(uiBlock *block, int type, int bit, 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 uiDefIconButBit(block, type|SHO, bit, 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);
+}
+uiBut *uiDefIconButBitC(uiBlock *block, int type, int bit, 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 uiDefIconButBit(block, type|CHA, bit, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefIconButR(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, char *tip)
+{
+ uiBut *but;
+
+ but= ui_def_but_rna(block, type, retval, "", x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip);
+ if(but) {
+ but->icon= (BIFIconID) icon;
+ but->flag|= UI_HAS_ICON;
+ ui_check_but(but);
+ }
+
+ return but;
+}
+uiBut *uiDefIconButO(uiBlock *block, int type, char *opname, int opcontext, int icon, short x1, short y1, short x2, short y2, char *tip)
+{
+ uiBut *but;
+
+ but= ui_def_but_operator(block, type, opname, opcontext, "", x1, y1, x2, y2, tip);
+ if(but) {
+ but->icon= (BIFIconID) icon;
+ but->flag|= UI_HAS_ICON;
+ ui_check_but(but);
+ }
+
+ return but;
+}
+
+/* Button containing both string label and icon */
+uiBut *uiDefIconTextBut(uiBlock *block, int type, int retval, int icon, 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);
+
+ but->icon= (BIFIconID) icon;
+ but->flag|= UI_HAS_ICON;
+
+ but->flag|= UI_ICON_LEFT;
+
+ ui_check_but(but);
+
+ return but;
+}
+static uiBut *uiDefIconTextButBit(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, char *tip)
+{
+ int bitIdx= findBitIndex(bit);
+ if (bitIdx==-1) {
+ return NULL;
+ } else {
+ return uiDefIconTextBut(block, type|BIT|bitIdx, retval, icon, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip);
+ }
+}
+
+uiBut *uiDefIconTextButF(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip)
+{
+ return uiDefIconTextBut(block, type|FLO, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefIconTextButBitF(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip)
+{
+ return uiDefIconTextButBit(block, type|FLO, bit, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefIconTextButI(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip)
+{
+ return uiDefIconTextBut(block, type|INT, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefIconTextButBitI(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip)
+{
+ return uiDefIconTextButBit(block, type|INT, bit, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefIconTextButS(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip)
+{
+ return uiDefIconTextBut(block, type|SHO, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefIconTextButBitS(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip)
+{
+ return uiDefIconTextButBit(block, type|SHO, bit, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefIconTextButC(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip)
+{
+ return uiDefIconTextBut(block, type|CHA, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefIconTextButBitC(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip)
+{
+ return uiDefIconTextButBit(block, type|CHA, bit, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefIconTextButR(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, char *tip)
+{
+ uiBut *but;
+
+ but= ui_def_but_rna(block, type, retval, str, x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip);
+ if(but) {
+ but->icon= (BIFIconID) icon;
+ but->flag|= UI_HAS_ICON;
+ but->flag|= UI_ICON_LEFT;
+ ui_check_but(but);
+ }
+
+ return but;
+}
+uiBut *uiDefIconTextButO(uiBlock *block, int type, char *opname, int opcontext, int icon, char *str, short x1, short y1, short x2, short y2, char *tip)
+{
+ uiBut *but;
+
+ but= ui_def_but_operator(block, type, opname, opcontext, str, x1, y1, x2, y2, tip);
+ if(but) {
+ but->icon= (BIFIconID) icon;
+ but->flag|= UI_HAS_ICON;
+ but->flag|= UI_ICON_LEFT;
+ ui_check_but(but);
+ }
+
+ return but;
+}
+
+static int ui_menu_y(uiBlock *block)
+{
+ uiBut *but= block->buttons.last;
+
+ if(but) return but->y1;
+ else return 0;
+}
+
+uiBut *uiDefMenuButO(uiBlock *block, char *opname, char *name)
+{
+ int y= ui_menu_y(block) - MENU_ITEM_HEIGHT;
+ return uiDefIconTextButO(block, BUT, opname, WM_OP_INVOKE_REGION_WIN, ICON_BLANK1, name, 0, y, MENU_WIDTH, MENU_ITEM_HEIGHT-1, NULL);
+}
+
+uiBut *uiDefMenuSep(uiBlock *block)
+{
+ int y= ui_menu_y(block) - MENU_SEP_HEIGHT;
+ return uiDefBut(block, SEPR, 0, "", 0, y, MENU_WIDTH, MENU_SEP_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
+}
+
+uiBut *uiDefMenuSub(uiBlock *block, uiBlockCreateFunc func, char *name)
+{
+ int y= ui_menu_y(block) - MENU_ITEM_HEIGHT;
+ return uiDefIconTextBlockBut(block, func, NULL, ICON_RIGHTARROW_THIN, name, 0, y, MENU_WIDTH, MENU_ITEM_HEIGHT-1, "");
+}
+
+uiBut *uiDefMenuTogR(uiBlock *block, PointerRNA *ptr, char *propname, char *propvalue, char *name)
+{
+ uiBut *but;
+ PropertyRNA *prop;
+ PropertyType type;
+ const EnumPropertyItem *item;
+ int a, value, totitem, icon= ICON_CHECKBOX_DEHLT;
+ int y= ui_menu_y(block) - MENU_ITEM_HEIGHT;
+
+ prop= RNA_struct_find_property(ptr, propname);
+ if(prop) {
+ type= RNA_property_type(prop);
+
+ if(type == PROP_BOOLEAN) {
+ if(RNA_property_boolean_get(ptr, prop))
+ icon= ICON_CHECKBOX_HLT;
+
+ return uiDefIconTextButR(block, TOG, 0, icon, name, 0, y, MENU_WIDTH, MENU_ITEM_HEIGHT-1, ptr, propname, 0, 0, 0, 0, 0, NULL);
+ }
+ else if(type == PROP_ENUM) {
+ RNA_property_enum_items(ptr, prop, &item, &totitem);
+
+ value= 0;
+ for(a=0; a<totitem; a++) {
+ if(propvalue && strcmp(propvalue, item[a].identifier) == 0) {
+ value= item[a].value;
+ if(!name)
+ name= (char*)item[a].name;
+
+ if(RNA_property_enum_get(ptr, prop) == value)
+ icon= ICON_CHECKBOX_HLT;
+ break;
+ }
+ }
+
+ if(a != totitem)
+ return uiDefIconTextButR(block, ROW, 0, icon, name, 0, y, MENU_WIDTH, MENU_ITEM_HEIGHT-1, ptr, propname, 0, 0, value, 0, 0, NULL);
+ }
+ }
+
+ /* not found */
+ uiBlockSetButLock(block, 1, "");
+ but= uiDefIconTextBut(block, BUT, 0, ICON_BLANK1, propname, 0, y, MENU_WIDTH, MENU_ITEM_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
+ uiBlockClearButLock(block);
+
+ return but;
+}
+
+/* END Button containing both string label and icon */
+
+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;
+}
+
+void uiBlockSetDirection(uiBlock *block, int direction)
+{
+ block->direction= direction;
+}
+
+/* this call escapes if there's alignment flags */
+void uiBlockFlipOrder(uiBlock *block)
+{
+ ListBase lb;
+ uiBut *but, *next;
+ float centy, miny=10000, maxy= -10000;
+
+// if(U.uiflag & USER_PLAINMENUS)
+// return;
+
+ for(but= block->buttons.first; but; but= but->next) {
+ if(but->flag & UI_BUT_ALIGN) return;
+ if(but->y1 < miny) miny= but->y1;
+ if(but->y2 > maxy) maxy= but->y2;
+ }
+ /* mirror trick */
+ centy= (miny+maxy)/2.0;
+ for(but= block->buttons.first; but; but= but->next) {
+ but->y1 = centy-(but->y1-centy);
+ but->y2 = centy-(but->y2-centy);
+ SWAP(float, but->y1, but->y2);
+ }
+
+ /* also flip order in block itself, for example for arrowkey */
+ lb.first= lb.last= NULL;
+ but= block->buttons.first;
+ while(but) {
+ next= but->next;
+ BLI_remlink(&block->buttons, but);
+ BLI_addtail(&lb, but);
+ but= next;
+ }
+ block->buttons= lb;
+}
+
+
+void uiBlockSetFlag(uiBlock *block, int flag)
+{
+ block->flag|= flag;
+}
+
+void uiBlockClearFlag(uiBlock *block, int flag)
+{
+ block->flag&= ~flag;
+}
+
+void uiBlockSetXOfs(uiBlock *block, int xofs)
+{
+ block->xofs= xofs;
+}
+
+void uiButSetFlag(uiBut *but, int flag)
+{
+ but->flag|= flag;
+}
+
+void uiButClearFlag(uiBut *but, int flag)
+{
+ but->flag&= ~flag;
+}
+
+int uiButGetRetVal(uiBut *but)
+{
+ return but->retval;
+}
+
+PointerRNA *uiButGetOperatorPtrRNA(uiBut *but)
+{
+ if(but->opname && !but->opptr) {
+ but->opptr= MEM_callocN(sizeof(PointerRNA), "uiButOpPtr");
+ WM_operator_properties_create(but->opptr, but->opname);
+ }
+
+ return but->opptr;
+}
+
+void uiBlockSetHandleFunc(uiBlock *block, uiBlockHandleFunc func, void *arg)
+{
+ block->handle_func= func;
+ block->handle_func_arg= arg;
+}
+
+void uiBlockSetButmFunc(uiBlock *block, uiMenuHandleFunc func, void *arg)
+{
+ block->butm_func= func;
+ block->butm_func_arg= arg;
+}
+
+void uiBlockSetFunc(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2)
+{
+ block->func= func;
+ block->func_arg1= arg1;
+ block->func_arg2= arg2;
+}
+
+void uiBlockSetDrawExtraFunc(uiBlock *block, void (*func)())
+{
+ block->drawextra= func;
+}
+
+void uiButSetFunc(uiBut *but, uiButHandleFunc func, void *arg1, void *arg2)
+{
+ but->func= func;
+ but->func_arg1= arg1;
+ but->func_arg2= arg2;
+}
+
+void uiButSetNFunc(uiBut *but, uiButHandleNFunc funcN, void *argN, void *arg2)
+{
+ but->funcN= funcN;
+ but->func_argN= argN;
+ but->func_arg2= arg2;
+}
+
+void uiButSetCompleteFunc(uiBut *but, uiButCompleteFunc func, void *arg)
+{
+ but->autocomplete_func= func;
+ but->autofunc_arg= arg;
+}
+
+uiBut *uiDefIDPoinBut(uiBlock *block, uiIDPoinFuncFP func, short blocktype, 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);
+
+ if(blocktype)
+ uiButSetCompleteFunc(but, autocomplete_id, (void *)(intptr_t)blocktype);
+
+ return but;
+}
+
+uiBut *uiDefBlockBut(uiBlock *block, uiBlockCreateFunc 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_create_func= func;
+ ui_check_but(but);
+ return but;
+}
+
+uiBut *uiDefPulldownBut(uiBlock *block, uiBlockCreateFunc func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip)
+{
+ uiBut *but= ui_def_but(block, PULLDOWN, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
+ but->block_create_func= func;
+ ui_check_but(but);
+ return but;
+}
+
+uiBut *uiDefMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip)
+{
+ uiBut *but= ui_def_but(block, HMENU, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
+ but->menu_create_func= func;
+ ui_check_but(but);
+ return but;
+}
+
+uiBut *uiDefIconTextMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int icon, char *str, short x1, short y1, short x2, short y2, char *tip)
+{
+ uiBut *but= ui_def_but(block, HMENU, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
+
+ but->icon= (BIFIconID) icon;
+ but->flag|= UI_HAS_ICON;
+
+ but->flag|= UI_ICON_LEFT;
+ but->flag|= UI_ICON_RIGHT;
+
+ but->menu_create_func= func;
+ ui_check_but(but);
+
+ return but;
+}
+
+/* Block button containing both string label and icon */
+uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int icon, 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->icon= (BIFIconID) icon;
+ but->flag|= UI_HAS_ICON;
+
+ but->flag|= UI_ICON_LEFT;
+ but->flag|= UI_ICON_RIGHT;
+
+ but->block_create_func= func;
+ ui_check_but(but);
+
+ return but;
+}
+
+/* Block button containing icon */
+uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int retval, int icon, short x1, short y1, short x2, short y2, char *tip)
+{
+ uiBut *but= ui_def_but(block, BLOCK, retval, "", x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
+
+ but->icon= (BIFIconID) icon;
+ but->flag|= UI_HAS_ICON;
+
+ but->flag|= UI_ICON_LEFT;
+ but->flag|= UI_ICON_RIGHT;
+
+ but->block_create_func= func;
+ ui_check_but(but);
+
+ return 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);
+}
+
+/* Program Init/Exit */
+
+void UI_init(void)
+{
+ ui_resources_init();
+}
+
+void UI_init_userdef()
+{
+ uiStyleInit();
+ ui_theme_init_userdef();
+}
+
+void UI_exit(void)
+{
+ uiStyleExit();
+ ui_resources_free();
+}
+
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
new file mode 100644
index 00000000000..6775a639597
--- /dev/null
+++ b/source/blender/editors/interface/interface_anim.c
@@ -0,0 +1,157 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "BLI_listbase.h"
+
+#include "BKE_animsys.h"
+#include "BKE_context.h"
+#include "BKE_fcurve.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "interface_intern.h"
+
+void ui_but_anim_flag(uiBut *but, float cfra)
+{
+ but->flag &= ~(UI_BUT_ANIMATED|UI_BUT_ANIMATED_KEY|UI_BUT_DRIVEN);
+
+ if(but->rnaprop && but->rnapoin.id.data) {
+ AnimData *adt= BKE_animdata_from_id(but->rnapoin.id.data);
+ FCurve *fcu;
+ char *path;
+
+ if (adt) {
+ if ((adt->action && adt->action->curves.first) || (adt->drivers.first)) {
+ /* XXX this function call can become a performance bottleneck */
+ path= RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);
+
+ if (path) {
+ /* animation takes priority over drivers */
+ if (adt->action && adt->action->curves.first) {
+ fcu= list_find_fcurve(&adt->action->curves, path, but->rnaindex);
+
+ if (fcu) {
+ but->flag |= UI_BUT_ANIMATED;
+
+ if (on_keyframe_fcurve(fcu, cfra))
+ but->flag |= UI_BUT_ANIMATED_KEY;
+ }
+ }
+
+ /* if not animated, check if driven */
+ if ((but->flag & UI_BUT_ANIMATED)==0 && (adt->drivers.first)) {
+ fcu= list_find_fcurve(&adt->drivers, path, but->rnaindex);
+
+ if (fcu)
+ but->flag |= UI_BUT_DRIVEN;
+ }
+
+ MEM_freeN(path);
+ }
+ }
+ }
+ }
+}
+
+void uiAnimContextProperty(const bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop, int *index)
+{
+ ARegion *ar= CTX_wm_region(C);
+ uiBlock *block;
+ uiBut *but;
+
+ if(ar) {
+ for(block=ar->uiblocks.first; block; block=block->next) {
+ for(but=block->buttons.first; but; but= but->next) {
+ if(but->active && but->rnapoin.id.data) {
+ *ptr= but->rnapoin;
+ *prop= but->rnaprop;
+ *index= but->rnaindex;
+ return;
+ }
+ }
+ }
+ }
+}
+
+void ui_but_anim_insert_keyframe(bContext *C)
+{
+ /* this operator calls uiAnimContextProperty above */
+ WM_operator_name_call(C, "ANIM_OT_insert_keyframe_button", WM_OP_INVOKE_DEFAULT, NULL);
+}
+
+void ui_but_anim_delete_keyframe(bContext *C)
+{
+ /* this operator calls uiAnimContextProperty above */
+ WM_operator_name_call(C, "ANIM_OT_delete_keyframe_button", WM_OP_INVOKE_DEFAULT, NULL);
+}
+
+void ui_but_anim_add_driver(bContext *C)
+{
+ /* this operator calls uiAnimContextProperty above */
+ WM_operator_name_call(C, "ANIM_OT_add_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
+}
+
+void ui_but_anim_remove_driver(bContext *C)
+{
+ /* this operator calls uiAnimContextProperty above */
+ WM_operator_name_call(C, "ANIM_OT_remove_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
+}
+
+// TODO: refine the logic for adding/removing drivers...
+void ui_but_anim_menu(bContext *C, uiBut *but)
+{
+ uiMenuItem *head;
+ int length;
+
+ if(but->rnapoin.data && but->rnaprop) {
+ head= uiPupMenuBegin(RNA_property_ui_name(but->rnaprop), 0);
+
+ length= RNA_property_array_length(but->rnaprop);
+
+ if(but->flag & UI_BUT_ANIMATED_KEY) {
+ if(length) {
+ uiMenuItemBooleanO(head, "Delete Keyframes", 0, "ANIM_OT_delete_keyframe_button", "all", 1);
+ uiMenuItemBooleanO(head, "Delete Single Keyframe", 0, "ANIM_OT_delete_keyframe_button", "all", 0);
+
+ uiMenuItemBooleanO(head, "Remove Driver", 0, "ANIM_OT_remove_driver_button", "all", 1);
+ uiMenuItemBooleanO(head, "Remove Single Driver", 0, "ANIM_OT_remove_driver_button", "all", 0);
+ }
+ else {
+ uiMenuItemBooleanO(head, "Delete Keyframe", 0, "ANIM_OT_delete_keyframe_button", "all", 0);
+
+ uiMenuItemBooleanO(head, "Remove Driver", 0, "ANIM_OT_remove_driver_button", "all", 0);
+ }
+ }
+ else if(RNA_property_animateable(&but->rnapoin, but->rnaprop)) {
+ if(length) {
+ uiMenuItemBooleanO(head, "Insert Keyframes", 0, "ANIM_OT_insert_keyframe_button", "all", 1);
+ uiMenuItemBooleanO(head, "Insert Single Keyframe", 0, "ANIM_OT_insert_keyframe_button", "all", 0);
+
+ uiMenuItemBooleanO(head, "Add Driver", 0, "ANIM_OT_add_driver_button", "all", 1);
+ uiMenuItemBooleanO(head, "Add Single Driver", 0, "ANIM_OT_add_driver_button", "all", 0);
+ }
+ else {
+ uiMenuItemBooleanO(head, "Insert Keyframe", 0, "ANIM_OT_insert_keyframe_button", "all", 0);
+
+ uiMenuItemBooleanO(head, "Add Driver", 0, "ANIM_OT_add_driver_button", "all", 0);
+ }
+ }
+
+ uiPupMenuEnd(C, head);
+ }
+}
+
diff --git a/source/blender/editors/interface/interface_api.c b/source/blender/editors/interface/interface_api.c
new file mode 100644
index 00000000000..a184655df83
--- /dev/null
+++ b/source/blender/editors/interface/interface_api.c
@@ -0,0 +1,91 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "RNA_define.h"
+#include "RNA_types.h"
+
+#include "UI_interface.h"
+
+static void api_ui_item_common(FunctionRNA *func)
+{
+ RNA_def_string(func, "text", "", 0, "", "Override automatic text of the item.");
+ RNA_def_int(func, "icon", 0, 0, INT_MAX, "", "Override automatic icon of the item.", 0, INT_MAX);
+}
+
+void RNA_api_ui_layout(StructRNA *srna)
+{
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ /* simple layout specifiers */
+ func= RNA_def_function(srna, "row", "uiLayoutRow");
+ func= RNA_def_function(srna, "column", "uiLayoutColumn");
+ func= RNA_def_function(srna, "column_flow", "uiLayoutColumnFlow");
+ parm= RNA_def_int(func, "columns", 0, 0, INT_MAX, "", "Number of columns, 0 is automatic.", 0, INT_MAX);
+
+ /* box layout */
+ func= RNA_def_function(srna, "box", "uiLayoutBox");
+ parm= RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in.");
+ RNA_def_function_return(func, parm);
+
+ /* split layout */
+ func= RNA_def_function(srna, "split", "uiLayoutSplit");
+ parm= RNA_def_int(func, "number", 2, 0, INT_MAX, "", "Number of splits.", 0, INT_MAX);
+ parm= RNA_def_boolean(func, "lr", 0, "", "LR.");
+
+ /* sub layout */
+ func= RNA_def_function(srna, "sub", "uiLayoutSub");
+ parm= RNA_def_int(func, "n", 0, 0, INT_MAX, "", "Index of sub-layout.", 0, INT_MAX);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm= RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in.");
+ RNA_def_function_return(func, parm);
+
+ func= RNA_def_function(srna, "template_header_menus", "uiTemplateHeaderMenus");
+ //func= RNA_def_function(srna, "template_header_ID", "uiTemplateHeaderID");
+
+ /* items */
+ func= RNA_def_function(srna, "itemR", "uiItemR");
+ api_ui_item_common(func);
+ parm= RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property.");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in data.");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail.");
+
+ func= RNA_def_function(srna, "itemO", "uiItemO");
+ api_ui_item_common(func);
+ parm= RNA_def_string(func, "operator", "", 0, "", "Identifier of the operator.");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ func= RNA_def_function(srna, "itemL", "uiItemL");
+ api_ui_item_common(func);
+}
+
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
new file mode 100644
index 00000000000..153db7aa77d
--- /dev/null
+++ b/source/blender/editors/interface/interface_draw.c
@@ -0,0 +1,1125 @@
+/**
+ * $Id: interface_draw.c 15733 2008-07-24 09:23:13Z aligorith $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "DNA_color_types.h"
+#include "DNA_listBase.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BLI_arithb.h"
+
+#include "BKE_colortools.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+
+#include "interface_intern.h"
+
+#define UI_RB_ALPHA 16
+#define UI_DISABLED_ALPHA_OFFS -160
+
+static int roundboxtype= 15;
+
+void uiSetRoundBox(int type)
+{
+ /* Not sure the roundbox function is the best place to change this
+ * if this is undone, its not that big a deal, only makes curves edges
+ * square for the */
+ if (UI_GetThemeValue(TH_BUT_DRAWTYPE) == TH_MINIMAL)
+ roundboxtype= 0;
+ else
+ roundboxtype= type;
+
+ /* flags to set which corners will become rounded:
+
+ 1------2
+ | |
+ 8------4
+ */
+
+}
+
+int uiGetRoundBox(void)
+{
+ if (ELEM3(UI_GetThemeValue(TH_BUT_DRAWTYPE), TH_MINIMAL, TH_SHADED, TH_OLDSKOOL))
+ return 0;
+ else
+ return roundboxtype;
+}
+
+void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad)
+{
+ float vec[7][2]= {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
+ {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
+ int a;
+
+ /* mult */
+ for(a=0; a<7; a++) {
+ vec[a][0]*= rad; vec[a][1]*= rad;
+ }
+
+ glBegin(mode);
+
+ /* start with corner right-bottom */
+ if(roundboxtype & 4) {
+ glVertex2f(maxx-rad, miny);
+ for(a=0; a<7; a++) {
+ glVertex2f(maxx-rad+vec[a][0], miny+vec[a][1]);
+ }
+ glVertex2f(maxx, miny+rad);
+ }
+ else glVertex2f(maxx, miny);
+
+ /* corner right-top */
+ if(roundboxtype & 2) {
+ glVertex2f(maxx, maxy-rad);
+ for(a=0; a<7; a++) {
+ glVertex2f(maxx-vec[a][1], maxy-rad+vec[a][0]);
+ }
+ glVertex2f(maxx-rad, maxy);
+ }
+ else glVertex2f(maxx, maxy);
+
+ /* corner left-top */
+ if(roundboxtype & 1) {
+ glVertex2f(minx+rad, maxy);
+ for(a=0; a<7; a++) {
+ glVertex2f(minx+rad-vec[a][0], maxy-vec[a][1]);
+ }
+ glVertex2f(minx, maxy-rad);
+ }
+ else glVertex2f(minx, maxy);
+
+ /* corner left-bottom */
+ if(roundboxtype & 8) {
+ glVertex2f(minx, miny+rad);
+ for(a=0; a<7; a++) {
+ glVertex2f(minx+vec[a][1], miny+rad-vec[a][0]);
+ }
+ glVertex2f(minx+rad, miny);
+ }
+ else glVertex2f(minx, miny);
+
+ glEnd();
+}
+
+static void round_box_shade_col(float *col1, float *col2, float fac)
+{
+ float col[3];
+
+ col[0]= (fac*col1[0] + (1.0-fac)*col2[0]);
+ col[1]= (fac*col1[1] + (1.0-fac)*col2[1]);
+ col[2]= (fac*col1[2] + (1.0-fac)*col2[2]);
+
+ glColor3fv(col);
+}
+
+
+/* linear horizontal shade within button or in outline */
+/* view2d scrollers use it */
+void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown)
+{
+ float vec[7][2]= {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
+ {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
+ float div= maxy-miny;
+ float coltop[3], coldown[3], color[4];
+ int a;
+
+ /* mult */
+ for(a=0; a<7; a++) {
+ vec[a][0]*= rad; vec[a][1]*= rad;
+ }
+ /* get current color, needs to be outside of glBegin/End */
+ glGetFloatv(GL_CURRENT_COLOR, color);
+
+ /* 'shade' defines strength of shading */
+ coltop[0]= color[0]+shadetop; if(coltop[0]>1.0) coltop[0]= 1.0;
+ coltop[1]= color[1]+shadetop; if(coltop[1]>1.0) coltop[1]= 1.0;
+ coltop[2]= color[2]+shadetop; if(coltop[2]>1.0) coltop[2]= 1.0;
+ coldown[0]= color[0]+shadedown; if(coldown[0]<0.0) coldown[0]= 0.0;
+ coldown[1]= color[1]+shadedown; if(coldown[1]<0.0) coldown[1]= 0.0;
+ coldown[2]= color[2]+shadedown; if(coldown[2]<0.0) coldown[2]= 0.0;
+
+ if (UI_GetThemeValue(TH_BUT_DRAWTYPE) != TH_MINIMAL) {
+ glShadeModel(GL_SMOOTH);
+ glBegin(mode);
+ }
+
+ /* start with corner right-bottom */
+ if(roundboxtype & 4) {
+
+ round_box_shade_col(coltop, coldown, 0.0);
+ glVertex2f(maxx-rad, miny);
+
+ for(a=0; a<7; a++) {
+ round_box_shade_col(coltop, coldown, vec[a][1]/div);
+ glVertex2f(maxx-rad+vec[a][0], miny+vec[a][1]);
+ }
+
+ round_box_shade_col(coltop, coldown, rad/div);
+ glVertex2f(maxx, miny+rad);
+ }
+ else {
+ round_box_shade_col(coltop, coldown, 0.0);
+ glVertex2f(maxx, miny);
+ }
+
+ /* corner right-top */
+ if(roundboxtype & 2) {
+
+ round_box_shade_col(coltop, coldown, (div-rad)/div);
+ glVertex2f(maxx, maxy-rad);
+
+ for(a=0; a<7; a++) {
+ round_box_shade_col(coltop, coldown, (div-rad+vec[a][1])/div);
+ glVertex2f(maxx-vec[a][1], maxy-rad+vec[a][0]);
+ }
+ round_box_shade_col(coltop, coldown, 1.0);
+ glVertex2f(maxx-rad, maxy);
+ }
+ else {
+ round_box_shade_col(coltop, coldown, 1.0);
+ glVertex2f(maxx, maxy);
+ }
+
+ /* corner left-top */
+ if(roundboxtype & 1) {
+
+ round_box_shade_col(coltop, coldown, 1.0);
+ glVertex2f(minx+rad, maxy);
+
+ for(a=0; a<7; a++) {
+ round_box_shade_col(coltop, coldown, (div-vec[a][1])/div);
+ glVertex2f(minx+rad-vec[a][0], maxy-vec[a][1]);
+ }
+
+ round_box_shade_col(coltop, coldown, (div-rad)/div);
+ glVertex2f(minx, maxy-rad);
+ }
+ else {
+ round_box_shade_col(coltop, coldown, 1.0);
+ glVertex2f(minx, maxy);
+ }
+
+ /* corner left-bottom */
+ if(roundboxtype & 8) {
+
+ round_box_shade_col(coltop, coldown, rad/div);
+ glVertex2f(minx, miny+rad);
+
+ for(a=0; a<7; a++) {
+ round_box_shade_col(coltop, coldown, (rad-vec[a][1])/div);
+ glVertex2f(minx+vec[a][1], miny+rad-vec[a][0]);
+ }
+
+ round_box_shade_col(coltop, coldown, 0.0);
+ glVertex2f(minx+rad, miny);
+ }
+ else {
+ round_box_shade_col(coltop, coldown, 0.0);
+ glVertex2f(minx, miny);
+ }
+
+ glEnd();
+ glShadeModel(GL_FLAT);
+}
+
+/* linear vertical shade within button or in outline */
+/* view2d scrollers use it */
+void gl_round_box_vertical_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadeLeft, float shadeRight)
+{
+ float vec[7][2]= {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
+ {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
+ float div= maxx-minx;
+ float colLeft[3], colRight[3], color[4];
+ int a;
+
+ /* mult */
+ for(a=0; a<7; a++) {
+ vec[a][0]*= rad; vec[a][1]*= rad;
+ }
+ /* get current color, needs to be outside of glBegin/End */
+ glGetFloatv(GL_CURRENT_COLOR, color);
+
+ /* 'shade' defines strength of shading */
+ colLeft[0]= color[0]+shadeLeft; if(colLeft[0]>1.0) colLeft[0]= 1.0;
+ colLeft[1]= color[1]+shadeLeft; if(colLeft[1]>1.0) colLeft[1]= 1.0;
+ colLeft[2]= color[2]+shadeLeft; if(colLeft[2]>1.0) colLeft[2]= 1.0;
+ colRight[0]= color[0]+shadeRight; if(colRight[0]<0.0) colRight[0]= 0.0;
+ colRight[1]= color[1]+shadeRight; if(colRight[1]<0.0) colRight[1]= 0.0;
+ colRight[2]= color[2]+shadeRight; if(colRight[2]<0.0) colRight[2]= 0.0;
+
+ if (UI_GetThemeValue(TH_BUT_DRAWTYPE) != TH_MINIMAL) {
+ glShadeModel(GL_SMOOTH);
+ glBegin(mode);
+ }
+
+ /* start with corner right-bottom */
+ if(roundboxtype & 4) {
+ round_box_shade_col(colLeft, colRight, 0.0);
+ glVertex2f(maxx-rad, miny);
+
+ for(a=0; a<7; a++) {
+ round_box_shade_col(colLeft, colRight, vec[a][0]/div);
+ glVertex2f(maxx-rad+vec[a][0], miny+vec[a][1]);
+ }
+
+ round_box_shade_col(colLeft, colRight, rad/div);
+ glVertex2f(maxx, miny+rad);
+ }
+ else {
+ round_box_shade_col(colLeft, colRight, 0.0);
+ glVertex2f(maxx, miny);
+ }
+
+ /* corner right-top */
+ if(roundboxtype & 2) {
+ round_box_shade_col(colLeft, colRight, 0.0);
+ glVertex2f(maxx, maxy-rad);
+
+ for(a=0; a<7; a++) {
+
+ round_box_shade_col(colLeft, colRight, (div-rad-vec[a][0])/div);
+ glVertex2f(maxx-vec[a][1], maxy-rad+vec[a][0]);
+ }
+ round_box_shade_col(colLeft, colRight, (div-rad)/div);
+ glVertex2f(maxx-rad, maxy);
+ }
+ else {
+ round_box_shade_col(colLeft, colRight, 0.0);
+ glVertex2f(maxx, maxy);
+ }
+
+ /* corner left-top */
+ if(roundboxtype & 1) {
+ round_box_shade_col(colLeft, colRight, (div-rad)/div);
+ glVertex2f(minx+rad, maxy);
+
+ for(a=0; a<7; a++) {
+ round_box_shade_col(colLeft, colRight, (div-rad+vec[a][0])/div);
+ glVertex2f(minx+rad-vec[a][0], maxy-vec[a][1]);
+ }
+
+ round_box_shade_col(colLeft, colRight, 1.0);
+ glVertex2f(minx, maxy-rad);
+ }
+ else {
+ round_box_shade_col(colLeft, colRight, 1.0);
+ glVertex2f(minx, maxy);
+ }
+
+ /* corner left-bottom */
+ if(roundboxtype & 8) {
+ round_box_shade_col(colLeft, colRight, 1.0);
+ glVertex2f(minx, miny+rad);
+
+ for(a=0; a<7; a++) {
+ round_box_shade_col(colLeft, colRight, (vec[a][0])/div);
+ glVertex2f(minx+vec[a][1], miny+rad-vec[a][0]);
+ }
+
+ round_box_shade_col(colLeft, colRight, 1.0);
+ glVertex2f(minx+rad, miny);
+ }
+ else {
+ round_box_shade_col(colLeft, colRight, 1.0);
+ glVertex2f(minx, miny);
+ }
+
+ glEnd();
+ glShadeModel(GL_FLAT);
+}
+
+/* plain antialiased unfilled rectangle */
+void uiRoundRect(float minx, float miny, float maxx, float maxy, float rad)
+{
+ float color[4];
+
+ if(roundboxtype & UI_RB_ALPHA) {
+ glGetFloatv(GL_CURRENT_COLOR, color);
+ color[3]= 0.5;
+ glColor4fv(color);
+ glEnable( GL_BLEND );
+ }
+
+ /* set antialias line */
+ if (UI_GetThemeValue(TH_BUT_DRAWTYPE) != TH_MINIMAL) {
+ glEnable( GL_LINE_SMOOTH );
+ glEnable( GL_BLEND );
+ }
+
+ gl_round_box(GL_LINE_LOOP, minx, miny, maxx, maxy, rad);
+
+ glDisable( GL_BLEND );
+ glDisable( GL_LINE_SMOOTH );
+}
+
+/* plain fake antialiased unfilled round rectangle */
+void uiRoundRectFakeAA(float minx, float miny, float maxx, float maxy, float rad, float asp)
+{
+ float color[4], alpha;
+ float raddiff;
+ int i, passes=4;
+
+ /* get the colour and divide up the alpha */
+ glGetFloatv(GL_CURRENT_COLOR, color);
+ alpha = 1; //color[3];
+ color[3]= 0.5*alpha/(float)passes;
+ glColor4fv(color);
+
+ /* set the 'jitter amount' */
+ raddiff = (1/(float)passes) * asp;
+
+ glEnable( GL_BLEND );
+
+ /* draw lots of lines on top of each other */
+ for (i=passes; i>=(-passes); i--) {
+ gl_round_box(GL_LINE_LOOP, minx, miny, maxx, maxy, rad+(i*raddiff));
+ }
+
+ glDisable( GL_BLEND );
+
+ color[3] = alpha;
+ glColor4fv(color);
+}
+
+/* (old, used in outliner) plain antialiased filled box */
+void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad)
+{
+ float color[4];
+
+ if(roundboxtype & UI_RB_ALPHA) {
+ glGetFloatv(GL_CURRENT_COLOR, color);
+ color[3]= 0.5;
+ glColor4fv(color);
+ glEnable( GL_BLEND );
+ }
+
+ /* solid part */
+ gl_round_box(GL_POLYGON, minx, miny, maxx, maxy, rad);
+
+ /* set antialias line */
+ if (UI_GetThemeValue(TH_BUT_DRAWTYPE) != TH_MINIMAL) {
+ glEnable( GL_LINE_SMOOTH );
+ glEnable( GL_BLEND );
+ }
+
+ gl_round_box(GL_LINE_LOOP, minx, miny, maxx, maxy, rad);
+
+ glDisable( GL_BLEND );
+ glDisable( GL_LINE_SMOOTH );
+}
+
+
+/* ************** generic embossed rect, for window sliders etc ************* */
+
+
+/* text_draw.c uses this */
+void uiEmboss(float x1, float y1, float x2, float y2, int sel)
+{
+
+ /* below */
+ if(sel) glColor3ub(200,200,200);
+ else glColor3ub(50,50,50);
+ fdrawline(x1, y1, x2, y1);
+
+ /* right */
+ fdrawline(x2, y1, x2, y2);
+
+ /* top */
+ if(sel) glColor3ub(50,50,50);
+ else glColor3ub(200,200,200);
+ fdrawline(x1, y2, x2, y2);
+
+ /* left */
+ fdrawline(x1, y1, x1, y2);
+
+}
+
+/* ************** TEXT AND ICON DRAWING FUNCTIONS ************* */
+
+
+#if 0
+#ifdef INTERNATIONAL
+static void ui_draw_but_CHARTAB(uiBut *but)
+{
+ /* XXX 2.50 bad global access */
+ /* Some local variables */
+ float sx, sy, ex, ey;
+ float width, height;
+ float butw, buth;
+ int x, y, cs;
+ wchar_t wstr[2];
+ unsigned char ustr[16];
+ PackedFile *pf;
+ int result = 0;
+ int charmax = G.charmax;
+
+ /* <builtin> font in use. There are TTF <builtin> and non-TTF <builtin> fonts */
+ if(!strcmp(G.selfont->name, "<builtin>"))
+ {
+ if(G.ui_international == TRUE)
+ {
+ charmax = 0xff;
+ }
+ else
+ {
+ charmax = 0xff;
+ }
+ }
+
+ /* Category list exited without selecting the area */
+ if(G.charmax == 0)
+ charmax = G.charmax = 0xffff;
+
+ /* Calculate the size of the button */
+ width = abs(rect->xmax - rect->xmin);
+ height = abs(rect->ymax - rect->ymin);
+
+ butw = floor(width / 12);
+ buth = floor(height / 6);
+
+ /* Initialize variables */
+ sx = rect->xmin;
+ ex = rect->xmin + butw;
+ sy = rect->ymin + height - buth;
+ ey = rect->ymin + height;
+
+ cs = G.charstart;
+
+ /* Set the font, in case it is not <builtin> font */
+ if(G.selfont && strcmp(G.selfont->name, "<builtin>"))
+ {
+ char tmpStr[256];
+
+ // Is the font file packed, if so then use the packed file
+ if(G.selfont->packedfile)
+ {
+ pf = G.selfont->packedfile;
+ FTF_SetFont(pf->data, pf->size, 14.0);
+ }
+ else
+ {
+ int err;
+
+ strcpy(tmpStr, G.selfont->name);
+ BLI_convertstringcode(tmpStr, G.sce);
+ err = FTF_SetFont((unsigned char *)tmpStr, 0, 14.0);
+ }
+ }
+ else
+ {
+ if(G.ui_international == TRUE)
+ {
+ FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, 14.0);
+ }
+ }
+
+ /* Start drawing the button itself */
+ glShadeModel(GL_SMOOTH);
+
+ glColor3ub(200, 200, 200);
+ glRectf((rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
+
+ glColor3ub(0, 0, 0);
+ for(y = 0; y < 6; y++)
+ {
+ // Do not draw more than the category allows
+ if(cs > charmax) break;
+
+ for(x = 0; x < 12; x++)
+ {
+ // Do not draw more than the category allows
+ if(cs > charmax) break;
+
+ // Draw one grid cell
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(sx, sy);
+ glVertex2f(ex, sy);
+ glVertex2f(ex, ey);
+ glVertex2f(sx, ey);
+ glEnd();
+
+ // Draw character inside the cell
+ memset(wstr, 0, sizeof(wchar_t)*2);
+ memset(ustr, 0, 16);
+
+ // Set the font to be either unicode or <builtin>
+ wstr[0] = cs;
+ if(strcmp(G.selfont->name, "<builtin>"))
+ {
+ wcs2utf8s((char *)ustr, (wchar_t *)wstr);
+ }
+ else
+ {
+ if(G.ui_international == TRUE)
+ {
+ wcs2utf8s((char *)ustr, (wchar_t *)wstr);
+ }
+ else
+ {
+ ustr[0] = cs;
+ ustr[1] = 0;
+ }
+ }
+
+ if((G.selfont && strcmp(G.selfont->name, "<builtin>")) || (G.selfont && !strcmp(G.selfont->name, "<builtin>") && G.ui_international == TRUE))
+ {
+ float wid;
+ float llx, lly, llz, urx, ury, urz;
+ float dx, dy;
+ float px, py;
+
+ // Calculate the position
+ wid = FTF_GetStringWidth((char *) ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
+ FTF_GetBoundingBox((char *) ustr, &llx,&lly,&llz,&urx,&ury,&urz, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
+ dx = urx-llx;
+ dy = ury-lly;
+
+ // This isn't fully functional since the but->aspect isn't working like I suspected
+ px = sx + ((butw/but->aspect)-dx)/2;
+ py = sy + ((buth/but->aspect)-dy)/2;
+
+ // Set the position and draw the character
+ ui_rasterpos_safe(px, py, but->aspect);
+ FTF_DrawString((char *) ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
+ }
+ else
+ {
+ ui_rasterpos_safe(sx + butw/2, sy + buth/2, but->aspect);
+ UI_DrawString(but->font, (char *) ustr, 0);
+ }
+
+ // Calculate the next position and character
+ sx += butw; ex +=butw;
+ cs++;
+ }
+ /* Add the y position and reset x position */
+ sy -= buth;
+ ey -= buth;
+ sx = rect->xmin;
+ ex = rect->xmin + butw;
+ }
+ glShadeModel(GL_FLAT);
+
+ /* Return Font Settings to original */
+ if(U.fontsize && U.fontname[0])
+ {
+ result = FTF_SetFont((unsigned char *)U.fontname, 0, U.fontsize);
+ }
+ else if (U.fontsize)
+ {
+ result = FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, U.fontsize);
+ }
+
+ if (result == 0)
+ {
+ result = FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, 11);
+ }
+
+ /* resets the font size */
+ if(G.ui_international == TRUE)
+ {
+ // uiSetCurFont(but->block, UI_HELV);
+ }
+}
+
+#endif // INTERNATIONAL
+#endif
+
+void ui_draw_but_COLORBAND(uiBut *but, rcti *rect)
+{
+ ColorBand *coba;
+ CBData *cbd;
+ float x1, y1, sizex, sizey;
+ float dx, v3[2], v1[2], v2[2], v1a[2], v2a[2];
+ int a;
+
+ coba= (ColorBand *)(but->editcoba? but->editcoba: but->poin);
+ if(coba==NULL) return;
+
+ x1= rect->xmin;
+ y1= rect->ymin;
+ sizex= rect->xmax-x1;
+ sizey= rect->ymax-y1;
+
+ /* first background, to show tranparency */
+ dx= sizex/12.0;
+ v1[0]= x1;
+ for(a=0; a<12; a++) {
+ if(a & 1) glColor3f(0.3, 0.3, 0.3); else glColor3f(0.8, 0.8, 0.8);
+ glRectf(v1[0], y1, v1[0]+dx, y1+0.5*sizey);
+ if(a & 1) glColor3f(0.8, 0.8, 0.8); else glColor3f(0.3, 0.3, 0.3);
+ glRectf(v1[0], y1+0.5*sizey, v1[0]+dx, y1+sizey);
+ v1[0]+= dx;
+ }
+
+ glShadeModel(GL_SMOOTH);
+ glEnable(GL_BLEND);
+
+ cbd= coba->data;
+
+ v1[0]= v2[0]= x1;
+ v1[1]= y1;
+ v2[1]= y1+sizey;
+
+ glBegin(GL_QUAD_STRIP);
+
+ glColor4fv( &cbd->r );
+ glVertex2fv(v1); glVertex2fv(v2);
+
+ for(a=0; a<coba->tot; a++, cbd++) {
+
+ v1[0]=v2[0]= x1+ cbd->pos*sizex;
+
+ glColor4fv( &cbd->r );
+ glVertex2fv(v1); glVertex2fv(v2);
+ }
+
+ v1[0]=v2[0]= x1+ sizex;
+ glVertex2fv(v1); glVertex2fv(v2);
+
+ glEnd();
+ glShadeModel(GL_FLAT);
+ glDisable(GL_BLEND);
+
+ /* outline */
+ v1[0]= x1; v1[1]= y1;
+
+ cpack(0x0);
+ glBegin(GL_LINE_LOOP);
+ glVertex2fv(v1);
+ v1[0]+= sizex;
+ glVertex2fv(v1);
+ v1[1]+= sizey;
+ glVertex2fv(v1);
+ v1[0]-= sizex;
+ glVertex2fv(v1);
+ glEnd();
+
+
+ /* help lines */
+ v1[0]= v2[0]=v3[0]= x1;
+ v1[1]= y1;
+ v1a[1]= y1+0.25*sizey;
+ v2[1]= y1+0.5*sizey;
+ v2a[1]= y1+0.75*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]=v1a[0]=v2a[0]= x1+ cbd->pos*sizex;
+
+ if(a==coba->cur) {
+ glColor3ub(0, 0, 0);
+ glVertex2fv(v1);
+ glVertex2fv(v3);
+ glEnd();
+
+ setlinestyle(2);
+ glBegin(GL_LINES);
+ glColor3ub(255, 255, 255);
+ glVertex2fv(v1);
+ glVertex2fv(v3);
+ glEnd();
+ setlinestyle(0);
+ glBegin(GL_LINES);
+
+ /* glColor3ub(0, 0, 0);
+ glVertex2fv(v1);
+ glVertex2fv(v1a);
+ glColor3ub(255, 255, 255);
+ glVertex2fv(v1a);
+ glVertex2fv(v2);
+ glColor3ub(0, 0, 0);
+ glVertex2fv(v2);
+ glVertex2fv(v2a);
+ glColor3ub(255, 255, 255);
+ glVertex2fv(v2a);
+ glVertex2fv(v3);
+ */
+ }
+ else {
+ glColor3ub(0, 0, 0);
+ glVertex2fv(v1);
+ glVertex2fv(v2);
+
+ glColor3ub(255, 255, 255);
+ glVertex2fv(v2);
+ glVertex2fv(v3);
+ }
+ }
+ glEnd();
+}
+
+void ui_draw_but_NORMAL(uiBut *but, rcti *rect)
+{
+ static GLuint displist=0;
+ int a, old[8];
+ GLfloat diff[4], diffn[4]={1.0f, 1.0f, 1.0f, 1.0f};
+ float vec0[4]={0.0f, 0.0f, 0.0f, 0.0f};
+ float dir[4], size;
+
+ /* store stuff */
+ glGetMaterialfv(GL_FRONT, GL_DIFFUSE, diff);
+
+ /* backdrop */
+ UI_ThemeColor(TH_BUT_NEUTRAL);
+ uiSetRoundBox(15);
+ gl_round_box(GL_POLYGON, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f);
+
+ /* sphere color */
+ glMaterialfv(GL_FRONT, GL_DIFFUSE, diffn);
+ glCullFace(GL_BACK); glEnable(GL_CULL_FACE);
+
+ /* disable blender light */
+ for(a=0; a<8; a++) {
+ old[a]= glIsEnabled(GL_LIGHT0+a);
+ glDisable(GL_LIGHT0+a);
+ }
+
+ /* own light */
+ glEnable(GL_LIGHT7);
+ glEnable(GL_LIGHTING);
+
+ VECCOPY(dir, (float *)but->poin);
+ dir[3]= 0.0f; /* glLight needs 4 args, 0.0 is sun */
+ glLightfv(GL_LIGHT7, GL_POSITION, dir);
+ glLightfv(GL_LIGHT7, GL_DIFFUSE, diffn);
+ glLightfv(GL_LIGHT7, GL_SPECULAR, vec0);
+ glLightf(GL_LIGHT7, GL_CONSTANT_ATTENUATION, 1.0f);
+ glLightf(GL_LIGHT7, GL_LINEAR_ATTENUATION, 0.0f);
+
+ /* transform to button */
+ glPushMatrix();
+ glTranslatef(rect->xmin + 0.5f*(rect->xmax-rect->xmin), rect->ymin+ 0.5f*(rect->ymax-rect->ymin), 0.0f);
+ size= (rect->xmax-rect->xmin)/200.f;
+ glScalef(size, size, size);
+
+ if(displist==0) {
+ GLUquadricObj *qobj;
+
+ displist= glGenLists(1);
+ glNewList(displist, GL_COMPILE_AND_EXECUTE);
+
+ qobj= gluNewQuadric();
+ gluQuadricDrawStyle(qobj, GLU_FILL);
+ glShadeModel(GL_SMOOTH);
+ gluSphere( qobj, 100.0, 32, 24);
+ glShadeModel(GL_FLAT);
+ gluDeleteQuadric(qobj);
+
+ glEndList();
+ }
+ else glCallList(displist);
+
+ /* restore */
+ glPopMatrix();
+ glDisable(GL_LIGHTING);
+ glDisable(GL_CULL_FACE);
+ glMaterialfv(GL_FRONT, GL_DIFFUSE, diff);
+
+ glDisable(GL_LIGHT7);
+
+ /* enable blender light */
+ for(a=0; a<8; a++) {
+ if(old[a])
+ glEnable(GL_LIGHT0+a);
+ }
+}
+
+static void ui_draw_but_curve_grid(rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step)
+{
+ float dx, dy, fx, fy;
+
+ glBegin(GL_LINES);
+ dx= step*zoomx;
+ fx= rect->xmin + zoomx*(-offsx);
+ if(fx > rect->xmin) fx -= dx*( floor(fx-rect->xmin));
+ while(fx < rect->xmax) {
+ glVertex2f(fx, rect->ymin);
+ glVertex2f(fx, rect->ymax);
+ fx+= dx;
+ }
+
+ dy= step*zoomy;
+ fy= rect->ymin + zoomy*(-offsy);
+ if(fy > rect->ymin) fy -= dy*( floor(fy-rect->ymin));
+ while(fy < rect->ymax) {
+ glVertex2f(rect->xmin, fy);
+ glVertex2f(rect->xmax, fy);
+ fy+= dy;
+ }
+ glEnd();
+
+}
+
+void ui_draw_but_CURVE(ARegion *ar, uiBut *but, rcti *rect)
+{
+ CurveMapping *cumap;
+ CurveMap *cuma;
+ CurveMapPoint *cmp;
+ float fx, fy, fac[2], zoomx, zoomy, offsx, offsy;
+ GLint scissor[4];
+ int a;
+
+ cumap= (CurveMapping *)(but->editcumap? but->editcumap: but->poin);
+ cuma= cumap->cm+cumap->cur;
+
+ /* need scissor test, curve can draw outside of boundary */
+ glGetIntegerv(GL_VIEWPORT, scissor);
+ glScissor(ar->winrct.xmin + rect->xmin, ar->winrct.ymin+rect->ymin, rect->xmax-rect->xmin, rect->ymax-rect->ymin);
+
+ /* calculate offset and zoom */
+ zoomx= (rect->xmax-rect->xmin-2.0*but->aspect)/(cumap->curr.xmax - cumap->curr.xmin);
+ zoomy= (rect->ymax-rect->ymin-2.0*but->aspect)/(cumap->curr.ymax - cumap->curr.ymin);
+ offsx= cumap->curr.xmin-but->aspect/zoomx;
+ offsy= cumap->curr.ymin-but->aspect/zoomy;
+
+ /* backdrop */
+ if(cumap->flag & CUMA_DO_CLIP) {
+ UI_ThemeColorShade(TH_BUT_NEUTRAL, -20);
+ glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ UI_ThemeColor(TH_BUT_NEUTRAL);
+ glRectf(rect->xmin + zoomx*(cumap->clipr.xmin-offsx),
+ rect->ymin + zoomy*(cumap->clipr.ymin-offsy),
+ rect->xmin + zoomx*(cumap->clipr.xmax-offsx),
+ rect->ymin + zoomy*(cumap->clipr.ymax-offsy));
+ }
+ else {
+ UI_ThemeColor(TH_BUT_NEUTRAL);
+ glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ }
+
+ /* grid, every .25 step */
+ UI_ThemeColorShade(TH_BUT_NEUTRAL, -16);
+ ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 0.25f);
+ /* grid, every 1.0 step */
+ UI_ThemeColorShade(TH_BUT_NEUTRAL, -24);
+ ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 1.0f);
+ /* axes */
+ UI_ThemeColorShade(TH_BUT_NEUTRAL, -50);
+ glBegin(GL_LINES);
+ glVertex2f(rect->xmin, rect->ymin + zoomy*(-offsy));
+ glVertex2f(rect->xmax, rect->ymin + zoomy*(-offsy));
+ glVertex2f(rect->xmin + zoomx*(-offsx), rect->ymin);
+ glVertex2f(rect->xmin + zoomx*(-offsx), rect->ymax);
+ glEnd();
+
+ /* cfra option */
+ /* XXX 2.48
+ if(cumap->flag & CUMA_DRAW_CFRA) {
+ glColor3ub(0x60, 0xc0, 0x40);
+ glBegin(GL_LINES);
+ glVertex2f(rect->xmin + zoomx*(cumap->sample[0]-offsx), rect->ymin);
+ glVertex2f(rect->xmin + zoomx*(cumap->sample[0]-offsx), rect->ymax);
+ glEnd();
+ }*/
+ /* sample option */
+ /* XXX 2.48
+ * if(cumap->flag & CUMA_DRAW_SAMPLE) {
+ if(cumap->cur==3) {
+ float lum= cumap->sample[0]*0.35f + cumap->sample[1]*0.45f + cumap->sample[2]*0.2f;
+ glColor3ub(240, 240, 240);
+
+ glBegin(GL_LINES);
+ glVertex2f(rect->xmin + zoomx*(lum-offsx), rect->ymin);
+ glVertex2f(rect->xmin + zoomx*(lum-offsx), rect->ymax);
+ glEnd();
+ }
+ else {
+ if(cumap->cur==0)
+ glColor3ub(240, 100, 100);
+ else if(cumap->cur==1)
+ glColor3ub(100, 240, 100);
+ else
+ glColor3ub(100, 100, 240);
+
+ glBegin(GL_LINES);
+ glVertex2f(rect->xmin + zoomx*(cumap->sample[cumap->cur]-offsx), rect->ymin);
+ glVertex2f(rect->xmin + zoomx*(cumap->sample[cumap->cur]-offsx), rect->ymax);
+ glEnd();
+ }
+ }*/
+
+ /* the curve */
+ UI_ThemeColorBlend(TH_TEXT, TH_BUT_NEUTRAL, 0.35);
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+ glBegin(GL_LINE_STRIP);
+
+ if(cuma->table==NULL)
+ curvemapping_changed(cumap, 0); /* 0 = no remove doubles */
+ cmp= cuma->table;
+
+ /* first point */
+ if((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0)
+ glVertex2f(rect->xmin, rect->ymin + zoomy*(cmp[0].y-offsy));
+ else {
+ fx= rect->xmin + zoomx*(cmp[0].x-offsx + cuma->ext_in[0]);
+ fy= rect->ymin + zoomy*(cmp[0].y-offsy + cuma->ext_in[1]);
+ glVertex2f(fx, fy);
+ }
+ for(a=0; a<=CM_TABLE; a++) {
+ fx= rect->xmin + zoomx*(cmp[a].x-offsx);
+ fy= rect->ymin + zoomy*(cmp[a].y-offsy);
+ glVertex2f(fx, fy);
+ }
+ /* last point */
+ if((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0)
+ glVertex2f(rect->xmax, rect->ymin + zoomy*(cmp[CM_TABLE].y-offsy));
+ else {
+ fx= rect->xmin + zoomx*(cmp[CM_TABLE].x-offsx - cuma->ext_out[0]);
+ fy= rect->ymin + zoomy*(cmp[CM_TABLE].y-offsy - cuma->ext_out[1]);
+ glVertex2f(fx, fy);
+ }
+ glEnd();
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+
+ /* the points, use aspect to make them visible on edges */
+ cmp= cuma->curve;
+ glPointSize(3.0f);
+ bglBegin(GL_POINTS);
+ for(a=0; a<cuma->totpoint; a++) {
+ if(cmp[a].flag & SELECT)
+ UI_ThemeColor(TH_TEXT_HI);
+ else
+ UI_ThemeColor(TH_TEXT);
+ fac[0]= rect->xmin + zoomx*(cmp[a].x-offsx);
+ fac[1]= rect->ymin + zoomy*(cmp[a].y-offsy);
+ bglVertex2fv(fac);
+ }
+ bglEnd();
+ glPointSize(1.0f);
+
+ /* restore scissortest */
+ glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+
+ /* outline */
+ UI_ThemeColor(TH_BUT_OUTLINE);
+ fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+}
+
+
+/* ****************************************************** */
+
+
+static void ui_shadowbox(float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha)
+{
+ glEnable(GL_BLEND);
+ glShadeModel(GL_SMOOTH);
+
+ /* right quad */
+ glBegin(GL_POLYGON);
+ glColor4ub(0, 0, 0, alpha);
+ glVertex2f(maxx, miny);
+ glVertex2f(maxx, maxy-0.3*shadsize);
+ glColor4ub(0, 0, 0, 0);
+ glVertex2f(maxx+shadsize, maxy-0.75*shadsize);
+ glVertex2f(maxx+shadsize, miny);
+ glEnd();
+
+ /* corner shape */
+ glBegin(GL_POLYGON);
+ glColor4ub(0, 0, 0, alpha);
+ glVertex2f(maxx, miny);
+ glColor4ub(0, 0, 0, 0);
+ glVertex2f(maxx+shadsize, miny);
+ glVertex2f(maxx+0.7*shadsize, miny-0.7*shadsize);
+ glVertex2f(maxx, miny-shadsize);
+ glEnd();
+
+ /* bottom quad */
+ glBegin(GL_POLYGON);
+ glColor4ub(0, 0, 0, alpha);
+ glVertex2f(minx+0.3*shadsize, miny);
+ glVertex2f(maxx, miny);
+ glColor4ub(0, 0, 0, 0);
+ glVertex2f(maxx, miny-shadsize);
+ glVertex2f(minx+0.5*shadsize, miny-shadsize);
+ glEnd();
+
+ glDisable(GL_BLEND);
+ glShadeModel(GL_FLAT);
+}
+
+void uiDrawBoxShadow(unsigned char alpha, float minx, float miny, float maxx, float maxy)
+{
+ /* accumulated outline boxes to make shade not linear, is more pleasant */
+ ui_shadowbox(minx, miny, maxx, maxy, 11.0, (20*alpha)>>8);
+ ui_shadowbox(minx, miny, maxx, maxy, 7.0, (40*alpha)>>8);
+ ui_shadowbox(minx, miny, maxx, maxy, 5.0, (80*alpha)>>8);
+
+}
+
+
+void ui_dropshadow(rctf *rct, float radius, float aspect, int select)
+{
+ float rad;
+ float a;
+ char alpha= 2;
+
+ glEnable(GL_BLEND);
+
+ if(radius > (rct->ymax-rct->ymin-10.0f)/2.0f)
+ rad= (rct->ymax-rct->ymin-10.0f)/2.0f;
+ else
+ rad= radius;
+
+ if(select) a= 12.0f*aspect; else a= 12.0f*aspect;
+ for(; a>0.0f; a-=aspect) {
+ /* alpha ranges from 2 to 20 or so */
+ glColor4ub(0, 0, 0, alpha);
+ alpha+= 2;
+
+ gl_round_box(GL_POLYGON, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax-10.0f + a, rad+a);
+ }
+
+ /* outline emphasis */
+ glEnable( GL_LINE_SMOOTH );
+ glColor4ub(0, 0, 0, 100);
+ gl_round_box(GL_LINE_LOOP, rct->xmin-0.5f, rct->ymin-0.5f, rct->xmax+0.5f, rct->ymax+0.5f, radius);
+ glDisable( GL_LINE_SMOOTH );
+
+ glDisable(GL_BLEND);
+}
+
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
new file mode 100644
index 00000000000..924d7df8c45
--- /dev/null
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -0,0 +1,3823 @@
+/**
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <float.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_color_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "PIL_time.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_idprop.h"
+#include "BKE_report.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLF_api.h"
+
+#include "interface_intern.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/***************** structs and defines ****************/
+
+#define BUTTON_TOOLTIP_DELAY 0.500
+#define BUTTON_FLASH_DELAY 0.020
+#define BUTTON_AUTO_OPEN_THRESH 0.3
+#define BUTTON_MOUSE_TOWARDS_THRESH 1.0
+
+typedef enum uiButtonActivateType {
+ BUTTON_ACTIVATE_OVER,
+ BUTTON_ACTIVATE,
+ BUTTON_ACTIVATE_APPLY,
+ BUTTON_ACTIVATE_TEXT_EDITING,
+ BUTTON_ACTIVATE_OPEN
+} uiButtonActivateType;
+
+typedef enum uiHandleButtonState {
+ BUTTON_STATE_INIT,
+ BUTTON_STATE_HIGHLIGHT,
+ BUTTON_STATE_WAIT_FLASH,
+ BUTTON_STATE_WAIT_RELEASE,
+ BUTTON_STATE_WAIT_KEY_EVENT,
+ BUTTON_STATE_NUM_EDITING,
+ BUTTON_STATE_TEXT_EDITING,
+ BUTTON_STATE_TEXT_SELECTING,
+ BUTTON_STATE_MENU_OPEN,
+ BUTTON_STATE_EXIT
+} uiHandleButtonState;
+
+typedef struct uiHandleButtonData {
+ wmWindow *window;
+ ARegion *region;
+
+ int interactive;
+
+ /* overall state */
+ uiHandleButtonState state;
+ int cancel, retval;
+ int applied, appliedinteractive;
+ wmTimer *flashtimer;
+
+ /* edited value */
+ char *str, *origstr;
+ double value, origvalue, startvalue;
+ float vec[3], origvec[3];
+ int togdual, togonly;
+ ColorBand *coba;
+ CurveMapping *cumap;
+
+ /* tooltip */
+ ARegion *tooltip;
+ wmTimer *tooltiptimer;
+ wmTimer *autoopentimer;
+
+ /* text selection/editing */
+ int maxlen, selextend, selstartx;
+
+ /* number editing / dragging */
+ int draglastx, draglasty;
+ int dragstartx, dragstarty;
+ int dragchange, draglock, dragsel;
+ float dragf, dragfstart;
+ CBData *dragcbd;
+
+ /* menu open */
+ uiPopupBlockHandle *menu;
+ int menuretval;
+
+ /* post activate */
+ uiButtonActivateType posttype;
+ uiBut *postbut;
+} uiHandleButtonData;
+
+typedef struct uiAfterFunc {
+ struct uiAfterFunc *next, *prev;
+
+ uiButHandleFunc func;
+ void *func_arg1;
+ void *func_arg2;
+
+ uiButHandleNFunc funcN;
+ void *func_argN;
+
+ uiBlockHandleFunc handle_func;
+ void *handle_func_arg;
+ int retval;
+
+ uiMenuHandleFunc butm_func;
+ void *butm_func_arg;
+ int a2;
+
+ const char *opname;
+ int opcontext;
+ PointerRNA *opptr;
+
+ PointerRNA rnapoin;
+ PropertyRNA *rnaprop;
+} uiAfterFunc;
+
+static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state);
+static int ui_handler_region_menu(bContext *C, wmEvent *event, void *userdata);
+static int ui_handler_popup(bContext *C, wmEvent *event, void *userdata);
+static void ui_handler_remove_popup(bContext *C, void *userdata);
+static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type);
+
+/* ******************** menu navigation helpers ************** */
+
+static uiBut *ui_but_prev(uiBut *but)
+{
+ while(but->prev) {
+ but= but->prev;
+ if(but->type!=LABEL && but->type!=SEPR && but->type!=ROUNDBOX) return but;
+ }
+ return NULL;
+}
+
+static uiBut *ui_but_next(uiBut *but)
+{
+ while(but->next) {
+ but= but->next;
+ if(but->type!=LABEL && but->type!=SEPR && but->type!=ROUNDBOX) 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 && but->type!=ROUNDBOX) 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 && but->type!=ROUNDBOX) return but;
+ but= but->prev;
+ }
+ return NULL;
+}
+
+/* ********************** button apply/revert ************************/
+
+static ListBase UIAfterFuncs = {NULL, NULL};
+
+static void ui_apply_but_func(bContext *C, uiBut *but)
+{
+ uiAfterFunc *after;
+ uiBlock *block= but->block;
+
+ /* these functions are postponed and only executed after all other
+ * handling is done, i.e. menus are closed, in order to avoid conflicts
+ * with these functions removing the buttons we are working with */
+
+ if(but->func || but->funcN || block->handle_func || (but->type == BUTM && block->butm_func) || but->opname || but->rnaprop) {
+ after= MEM_callocN(sizeof(uiAfterFunc), "uiAfterFunc");
+
+ after->func= but->func;
+ after->func_arg1= but->func_arg1;
+ after->func_arg2= but->func_arg2;
+
+ after->funcN= but->funcN;
+ after->func_argN= but->func_argN;
+
+ after->handle_func= block->handle_func;
+ after->handle_func_arg= block->handle_func_arg;
+ after->retval= but->retval;
+
+ if(but->type == BUTM) {
+ after->butm_func= block->butm_func;
+ after->butm_func_arg= block->butm_func_arg;
+ after->a2= but->a2;
+ }
+
+ after->opname= but->opname;
+ after->opcontext= but->opcontext;
+ after->opptr= but->opptr;
+
+ after->rnapoin= but->rnapoin;
+ after->rnaprop= but->rnaprop;
+
+ but->opname= NULL;
+ but->opcontext= 0;
+ but->opptr= NULL;
+
+ BLI_addtail(&UIAfterFuncs, after);
+ }
+}
+
+static void ui_apply_but_funcs_after(bContext *C)
+{
+ uiAfterFunc *afterf, after;
+ ListBase funcs;
+
+ /* copy to avoid recursive calls */
+ funcs= UIAfterFuncs;
+ UIAfterFuncs.first= UIAfterFuncs.last= NULL;
+
+ for(afterf=funcs.first; afterf; afterf=after.next) {
+ after= *afterf; /* copy to avoid memleak on exit() */
+ BLI_freelinkN(&funcs, afterf);
+
+ if(after.func)
+ after.func(C, after.func_arg1, after.func_arg2);
+ if(after.funcN)
+ after.funcN(C, after.func_argN, after.func_arg2);
+
+ if(after.handle_func)
+ after.handle_func(C, after.handle_func_arg, after.retval);
+ if(after.butm_func)
+ after.butm_func(C, after.butm_func_arg, after.a2);
+
+ if(after.opname)
+ WM_operator_name_call(C, after.opname, after.opcontext, after.opptr);
+ if(after.opptr) {
+ WM_operator_properties_free(after.opptr);
+ MEM_freeN(after.opptr);
+ }
+
+ if(after.rnapoin.data)
+ RNA_property_update(C, &after.rnapoin, after.rnaprop);
+ }
+}
+
+static void ui_apply_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ ui_apply_but_func(C, but);
+
+ data->retval= but->retval;
+ data->applied= 1;
+}
+
+static void ui_apply_but_BUTM(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ ui_set_but_val(but, but->hardmin);
+ ui_apply_but_func(C, but);
+
+ data->retval= but->retval;
+ data->applied= 1;
+}
+
+static void ui_apply_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ if(but->type == COL)
+ ui_set_but_vectorf(but, data->vec);
+ else if(ELEM3(but->type, MENU, ICONROW, ICONTEXTROW))
+ ui_set_but_val(but, data->value);
+
+ ui_check_but(but);
+ ui_apply_but_func(C, but);
+ data->retval= but->retval;
+ data->applied= 1;
+}
+
+static void ui_apply_but_TOG(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data)
+{
+ double value;
+ int w, lvalue, push;
+
+ /* local hack... */
+ if(but->type==BUT_TOGDUAL && data->togdual) {
+ if(but->pointype==SHO)
+ but->poin += 2;
+ else if(but->pointype==INT)
+ but->poin += 4;
+ }
+
+ 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(!data->togonly) {
+ lvalue= 1<<(but->bitnr);
+
+ ui_set_but_val(but, (double)lvalue);
+ }
+ else {
+ if(lvalue==0) lvalue= 1<<(but->bitnr);
+ }
+ }
+
+ ui_set_but_val(but, (double)lvalue);
+ if(but->type==ICONTOG || but->type==ICONTOGN) ui_check_but(but);
+ }
+ else {
+
+ if(value==0.0) push= 1;
+ else push= 0;
+
+ if(but->type==TOGN || but->type==ICONTOGN) push= !push;
+ ui_set_but_val(but, (double)push);
+ if(but->type==ICONTOG || but->type==ICONTOGN) ui_check_but(but);
+ }
+
+ /* end local hack... */
+ if(but->type==BUT_TOGDUAL && data->togdual) {
+ if(but->pointype==SHO)
+ but->poin -= 2;
+ else if(but->pointype==INT)
+ but->poin -= 4;
+ }
+
+ ui_apply_but_func(C, but);
+
+ data->retval= but->retval;
+ data->applied= 1;
+}
+
+static void ui_apply_but_ROW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data)
+{
+ ui_set_but_val(but, but->hardmax);
+ ui_apply_but_func(C, but);
+
+ data->retval= but->retval;
+ data->applied= 1;
+}
+
+static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ if(!data->str)
+ return;
+
+ ui_set_but_string(C, but, data->str);
+ ui_check_but(but);
+
+ /* give butfunc the original text too */
+ /* feature used for bone renaming, channels, etc */
+ if(but->func_arg2==NULL) but->func_arg2= data->origstr;
+ ui_apply_but_func(C, but);
+ if(but->func_arg2==data->origstr) but->func_arg2= NULL;
+
+ data->retval= but->retval;
+ data->applied= 1;
+}
+
+static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ if(data->str) {
+ if(ui_set_but_string(C, but, data->str)) {
+ data->value= ui_get_but_val(but);
+ }
+ else {
+ data->cancel= 1;
+ return;
+ }
+ }
+ else
+ ui_set_but_val(but, data->value);
+
+ ui_check_but(but);
+ ui_apply_but_func(C, but);
+
+ data->retval= but->retval;
+ data->applied= 1;
+}
+
+static void ui_apply_but_LABEL(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ ui_apply_but_func(C, but);
+ data->retval= but->retval;
+ data->applied= 1;
+}
+
+static void ui_apply_but_TOG3(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ 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_check_but(but);
+ ui_apply_but_func(C, but);
+ data->retval= but->retval;
+ data->applied= 1;
+}
+
+static void ui_apply_but_VEC(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ ui_set_but_vectorf(but, data->vec);
+ ui_check_but(but);
+ ui_apply_but_func(C, but);
+
+ data->retval= but->retval;
+ data->applied= 1;
+}
+
+static void ui_apply_but_COLORBAND(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ ui_apply_but_func(C, but);
+ data->retval= but->retval;
+ data->applied= 1;
+}
+
+static void ui_apply_but_CURVE(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ ui_apply_but_func(C, but);
+ data->retval= but->retval;
+ data->applied= 1;
+}
+
+static void ui_apply_but_IDPOIN(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ ui_set_but_string(C, but, data->str);
+ ui_check_but(but);
+ ui_apply_but_func(C, but);
+ data->retval= but->retval;
+ data->applied= 1;
+}
+
+#ifdef INTERNATIONAL
+static void ui_apply_but_CHARTAB(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ ui_apply_but_func(C, but);
+ data->retval= but->retval;
+ data->applied= 1;
+}
+#endif
+
+static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, int interactive)
+{
+ char *editstr;
+ double *editval;
+ float *editvec;
+ ColorBand *editcoba;
+ CurveMapping *editcumap;
+
+ data->retval= 0;
+
+ /* if we cancel and have not applied yet, there is nothing to do,
+ * otherwise we have to restore the original value again */
+ if(data->cancel) {
+ if(!data->applied)
+ return;
+
+ if(data->str) MEM_freeN(data->str);
+ data->str= data->origstr;
+ data->origstr= NULL;
+ data->value= data->origvalue;
+ data->origvalue= 0.0;
+ VECCOPY(data->vec, data->origvec);
+ data->origvec[0]= data->origvec[1]= data->origvec[2]= 0.0f;
+ }
+ else {
+ /* we avoid applying interactive edits a second time
+ * at the end with the appliedinteractive flag */
+ if(interactive)
+ data->appliedinteractive= 1;
+ else if(data->appliedinteractive)
+ return;
+ }
+
+ /* ensures we are writing actual values */
+ editstr= but->editstr;
+ editval= but->editval;
+ editvec= but->editvec;
+ editcoba= but->editcoba;
+ editcumap= but->editcumap;
+ but->editstr= NULL;
+ but->editval= NULL;
+ but->editvec= NULL;
+ but->editcoba= NULL;
+ but->editcumap= NULL;
+
+ /* handle different types */
+ switch(but->type) {
+ case BUT:
+ ui_apply_but_BUT(C, but, data);
+ break;
+ case TEX:
+ ui_apply_but_TEX(C, but, data);
+ break;
+ case TOGBUT:
+ case TOG:
+ case TOGR:
+ case ICONTOG:
+ case ICONTOGN:
+ case TOGN:
+ case BUT_TOGDUAL:
+ ui_apply_but_TOG(C, block, but, data);
+ break;
+ case ROW:
+ ui_apply_but_ROW(C, block, but, data);
+ break;
+ case SCROLL:
+ break;
+ case NUM:
+ case NUMABS:
+ ui_apply_but_NUM(C, but, data);
+ break;
+ case SLI:
+ case NUMSLI:
+ ui_apply_but_NUM(C, but, data);
+ break;
+ case HSVSLI:
+ break;
+ case ROUNDBOX:
+ case LABEL:
+ ui_apply_but_LABEL(C, but, data);
+ break;
+ case TOG3:
+ ui_apply_but_TOG3(C, but, data);
+ break;
+ case MENU:
+ case ICONROW:
+ case ICONTEXTROW:
+ case BLOCK:
+ case PULLDOWN:
+ case HMENU:
+ case COL:
+ ui_apply_but_BLOCK(C, but, data);
+ break;
+ case BUTM:
+ ui_apply_but_BUTM(C, but, data);
+ break;
+ case BUT_NORMAL:
+ case HSVCUBE:
+ ui_apply_but_VEC(C, but, data);
+ break;
+ case BUT_COLORBAND:
+ ui_apply_but_COLORBAND(C, but, data);
+ break;
+ case BUT_CURVE:
+ ui_apply_but_CURVE(C, but, data);
+ break;
+ case IDPOIN:
+ ui_apply_but_IDPOIN(C, but, data);
+ break;
+#ifdef INTERNATIONAL
+ case CHARTAB:
+ ui_apply_but_CHARTAB(C, but, data);
+ break;
+#endif
+ case LINK:
+ case INLINK:
+ break;
+ }
+
+ but->editstr= editstr;
+ but->editval= editval;
+ but->editvec= editvec;
+ but->editcoba= editcoba;
+ but->editcumap= editcumap;
+}
+
+/* ******************* copy and paste ******************** */
+
+/* c = copy, v = paste */
+static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, char mode)
+{
+ static ColorBand but_copypaste_coba = {0};
+ char buf[UI_MAX_DRAW_STR+1]= {0};
+ double val;
+
+ if(mode=='v' && but->lock)
+ return;
+
+ if(mode=='v') {
+ /* extract first line from clipboard in case of multi-line copies */
+ char *p = WM_clipboard_text_get(0);
+ if(p) {
+ int i = 0;
+ while (*p && *p!='\r' && *p!='\n' && i<UI_MAX_DRAW_STR) {
+ buf[i++]=*p;
+ p++;
+ }
+ buf[i]= 0;
+ MEM_freeN(p);
+ }
+ }
+
+ /* numeric value */
+ if ELEM4(but->type, NUM, NUMABS, NUMSLI, HSVSLI) {
+
+ if(but->poin==NULL && but->rnapoin.data==NULL);
+ else if(mode=='c') {
+ sprintf(buf, "%f", ui_get_but_val(but));
+ WM_clipboard_text_set(buf, 0);
+ }
+ else {
+ if (sscanf(buf, " %lf ", &val) == 1) {
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+ data->value= val;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ }
+
+ /* RGB triple */
+ else if(but->type==COL) {
+ float rgb[3];
+
+ if(but->poin==NULL && but->rnapoin.data==NULL);
+ else if(mode=='c') {
+
+ ui_get_but_vectorf(but, rgb);
+ sprintf(buf, "[%f, %f, %f]", rgb[0], rgb[1], rgb[2]);
+ WM_clipboard_text_set(buf, 0);
+
+ }
+ else {
+ if (sscanf(buf, "[%f, %f, %f]", &rgb[0], &rgb[1], &rgb[2]) == 3) {
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+ VECCOPY(data->vec, rgb);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ }
+
+ /* text/string and ID data */
+ else if(ELEM(but->type, TEX, IDPOIN)) {
+ uiHandleButtonData *data= but->active;
+
+ if(but->poin==NULL && but->rnapoin.data==NULL);
+ else if(mode=='c') {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ BLI_strncpy(buf, data->str, UI_MAX_DRAW_STR);
+ WM_clipboard_text_set(data->str, 0);
+ data->cancel= 1;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ BLI_strncpy(data->str, buf, data->maxlen);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ /* colorband (not supported by system clipboard) */
+ else if(but->type==BUT_COLORBAND) {
+ if(mode=='c') {
+ if(but->poin)
+ return;
+
+ memcpy(&but_copypaste_coba, but->poin, sizeof(ColorBand));
+ }
+ else {
+ if(but_copypaste_coba.tot==0)
+ return;
+
+ if(!but->poin)
+ but->poin= MEM_callocN(sizeof(ColorBand), "colorband");
+
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+ memcpy(data->coba, &but_copypaste_coba, sizeof(ColorBand) );
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+}
+
+/* ************* in-button text selection/editing ************* */
+
+/* return 1 if char ch is special character, otherwise return 0 */
+static short test_special_char(char ch)
+{
+ switch(ch) {
+ case '\\':
+ case '/':
+ case '~':
+ case '!':
+ case '@':
+ case '#':
+ case '$':
+ case '%':
+ case '^':
+ case '&':
+ case '*':
+ case '(':
+ case ')':
+ case '+':
+ case '=':
+ case '{':
+ case '}':
+ case '[':
+ case ']':
+ case ':':
+ case ';':
+ case '\'':
+ case '\"':
+ case '<':
+ case '>':
+ case ',':
+ case '.':
+ case '?':
+ case '_':
+ case '-':
+ case ' ':
+ return 1;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data)
+{
+ char *str;
+ int x, changed;
+
+ str= data->str;
+ changed= (but->selsta != but->selend);
+
+ for(x=0; x< strlen(str); x++) {
+ if (but->selend + x <= strlen(str) ) {
+ str[but->selsta + x]= str[but->selend + x];
+ } else {
+ str[but->selsta + x]= '\0';
+ break;
+ }
+ }
+
+ but->pos = but->selend = but->selsta;
+
+ return changed;
+}
+
+static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, short x)
+{
+ uiStyle *style= U.uistyles.first; // XXX pass on as arg
+ char *origstr;
+
+ uiStyleFontSet(&style->widget);
+
+ origstr= MEM_callocN(sizeof(char)*(data->maxlen+1), "ui_textedit origstr");
+
+ BLI_strncpy(origstr, but->drawstr, data->maxlen+1);
+ but->pos= strlen(origstr)-but->ofs;
+
+ while((BLF_width(origstr+but->ofs) + but->x1) > x) {
+ if (but->pos <= 0) break;
+ but->pos--;
+ origstr[but->pos+but->ofs] = 0;
+ }
+
+ but->pos -= strlen(but->str);
+ but->pos += but->ofs;
+ if(but->pos<0) but->pos= 0;
+
+ MEM_freeN(origstr);
+}
+
+static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data, short x)
+{
+ if (x > data->selstartx) data->selextend = EXTEND_RIGHT;
+ else if (x < data->selstartx) data->selextend = EXTEND_LEFT;
+
+ ui_textedit_set_cursor_pos(but, data, x);
+
+ if (data->selextend == EXTEND_RIGHT) but->selend = but->pos;
+ if (data->selextend == EXTEND_LEFT) but->selsta = but->pos;
+
+ ui_check_but(but);
+}
+
+static int ui_textedit_type_ascii(uiBut *but, uiHandleButtonData *data, char ascii)
+{
+ char *str;
+ int len, x, changed= 0;
+
+ str= data->str;
+ len= strlen(str);
+
+ if(len-(but->selend - but->selsta)+1 <= data->maxlen) {
+ /* type over the current selection */
+ if ((but->selend - but->selsta) > 0)
+ changed= ui_textedit_delete_selection(but, data);
+
+ len= strlen(str);
+ if(len < data->maxlen) {
+ for(x= data->maxlen; x>but->pos; x--)
+ str[x]= str[x-1];
+ str[but->pos]= ascii;
+ str[len+1]= '\0';
+
+ but->pos++;
+ changed= 1;
+ }
+ }
+
+ return WM_UI_HANDLER_BREAK;
+}
+
+void ui_textedit_move(uiBut *but, uiHandleButtonData *data, int direction, int select, int jump)
+{
+ char *str;
+ int len;
+
+ str= data->str;
+ len= strlen(str);
+
+ if(direction) { /* right*/
+ /* if there's a selection */
+ if ((but->selend - but->selsta) > 0) {
+ /* extend the selection based on the first direction taken */
+ if(select) {
+ if (!data->selextend) {
+ data->selextend = EXTEND_RIGHT;
+ }
+ if (data->selextend == EXTEND_RIGHT) {
+ but->selend++;
+ if (but->selend > len) but->selend = len;
+ } else if (data->selextend == EXTEND_LEFT) {
+ but->selsta++;
+ /* if the selection start has gone past the end,
+ * flip them so they're in sync again */
+ if (but->selsta == but->selend) {
+ but->pos = but->selsta;
+ data->selextend = EXTEND_RIGHT;
+ }
+ }
+ } else {
+ but->selsta = but->pos = but->selend;
+ data->selextend = 0;
+ }
+ } else {
+ if(select) {
+ /* make a selection, starting from the cursor position */
+ but->selsta = but->pos;
+
+ but->pos++;
+ if(but->pos>strlen(str)) but->pos= strlen(str);
+
+ but->selend = but->pos;
+ } else if(jump) {
+ /* jump betweenn special characters (/,\,_,-, etc.),
+ * look at function test_special_char() for complete
+ * list of special character, ctr -> */
+ while(but->pos < len) {
+ but->pos++;
+ if(test_special_char(str[but->pos])) break;
+ }
+ } else {
+ but->pos++;
+ if(but->pos>strlen(str)) but->pos= strlen(str);
+ }
+ }
+ }
+ else { /* left */
+ /* if there's a selection */
+ if ((but->selend - but->selsta) > 0) {
+ /* extend the selection based on the first direction taken */
+ if(select) {
+ if (!data->selextend) {
+ data->selextend = EXTEND_LEFT;
+ }
+ if (data->selextend == EXTEND_LEFT) {
+ but->selsta--;
+ if (but->selsta < 0) but->selsta = 0;
+ } else if (data->selextend == EXTEND_RIGHT) {
+ but->selend--;
+ /* if the selection start has gone past the end,
+ * flip them so they're in sync again */
+ if (but->selsta == but->selend) {
+ but->pos = but->selsta;
+ data->selextend = EXTEND_LEFT;
+ }
+ }
+ } else {
+ but->pos = but->selend = but->selsta;
+ data->selextend = 0;
+ }
+ } else {
+ if(select) {
+ /* make a selection, starting from the cursor position */
+ but->selend = but->pos;
+
+ but->pos--;
+ if(but->pos<0) but->pos= 0;
+
+ but->selsta = but->pos;
+ } else if(jump) {
+ /* jump betweenn special characters (/,\,_,-, etc.),
+ * look at function test_special_char() for complete
+ * list of special character, ctr -> */
+ while(but->pos > 0){
+ but->pos--;
+ if(test_special_char(str[but->pos])) break;
+ }
+ } else {
+ if(but->pos>0) but->pos--;
+ }
+ }
+ }
+}
+
+void ui_textedit_move_end(uiBut *but, uiHandleButtonData *data, int direction, int select)
+{
+ char *str;
+
+ str= data->str;
+
+ if(direction) { /* right */
+ if(select) {
+ but->selsta = but->pos;
+ but->selend = strlen(str);
+ data->selextend = EXTEND_RIGHT;
+ } else {
+ but->selsta = but->selend = but->pos= strlen(str);
+ }
+ }
+ else { /* left */
+ if(select) {
+ but->selend = but->pos;
+ but->selsta = 0;
+ data->selextend = EXTEND_LEFT;
+ } else {
+ but->selsta = but->selend = but->pos= 0;
+ }
+ }
+}
+
+static int ui_textedit_delete(uiBut *but, uiHandleButtonData *data, int direction, int all)
+{
+ char *str;
+ int len, x, changed= 0;
+
+ str= data->str;
+ len= strlen(str);
+
+ if(all) {
+ if(len) changed=1;
+ str[0]= 0;
+ but->pos= 0;
+ }
+ else if(direction) { /* delete */
+ if ((but->selend - but->selsta) > 0) {
+ changed= ui_textedit_delete_selection(but, data);
+ }
+ else if(but->pos>=0 && but->pos<len) {
+ for(x=but->pos; x<len; x++)
+ str[x]= str[x+1];
+ str[len-1]='\0';
+ changed= 1;
+ }
+ }
+ else { /* backspace */
+ if(len!=0) {
+ if ((but->selend - but->selsta) > 0) {
+ ui_textedit_delete_selection(but, data);
+ }
+ else if(but->pos>0) {
+ for(x=but->pos; x<len; x++)
+ str[x-1]= str[x];
+ str[len-1]='\0';
+
+ but->pos--;
+ changed= 1;
+ }
+ }
+ }
+
+ return changed;
+}
+
+static int ui_textedit_autocomplete(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ char *str;
+ int changed= 1;
+
+ str= data->str;
+ but->autocomplete_func(C, str, but->autofunc_arg);
+ but->pos= strlen(str);
+
+ return changed;
+}
+
+static int ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, int paste, int copy, int cut)
+{
+ char buf[UI_MAX_DRAW_STR]={0};
+ char *str, *p, *pbuf;
+ int len, x, y, i, changed= 0;
+
+ str= data->str;
+ len= strlen(str);
+
+ /* paste */
+ if (paste) {
+ /* extract the first line from the clipboard */
+ p = pbuf= WM_clipboard_text_get(0);
+
+ if(p && p[0]) {
+ i= 0;
+ while (*p && *p!='\r' && *p!='\n' && i<UI_MAX_DRAW_STR-1) {
+ buf[i++]=*p;
+ p++;
+ }
+ buf[i]= 0;
+
+ /* paste over the current selection */
+ if ((but->selend - but->selsta) > 0)
+ ui_textedit_delete_selection(but, data);
+
+ for (y=0; y<strlen(buf); y++)
+ {
+ /* add contents of buffer */
+ if(len < data->maxlen) {
+ for(x= data->maxlen; x>but->pos; x--)
+ str[x]= str[x-1];
+ str[but->pos]= buf[y];
+ but->pos++;
+ len++;
+ str[len]= '\0';
+ }
+ }
+
+ changed= 1;
+ }
+
+ if(pbuf)
+ MEM_freeN(pbuf);
+ }
+ /* cut & copy */
+ else if (copy || cut) {
+ /* copy the contents to the copypaste buffer */
+ for(x= but->selsta; x <= but->selend; x++) {
+ if (x==but->selend)
+ buf[x] = '\0';
+ else
+ buf[(x - but->selsta)] = str[x];
+ }
+
+ WM_clipboard_text_set(buf, 0);
+
+ /* for cut only, delete the selection afterwards */
+ if(cut)
+ if((but->selend - but->selsta) > 0)
+ changed= ui_textedit_delete_selection(but, data);
+ }
+
+ return changed;
+}
+
+static void ui_textedit_begin(uiBut *but, uiHandleButtonData *data)
+{
+ if(data->str) {
+ MEM_freeN(data->str);
+ data->str= NULL;
+ }
+
+ /* retrieve string */
+ data->maxlen= ui_get_but_string_max_length(but);
+ data->str= MEM_callocN(sizeof(char)*(data->maxlen+1), "textedit str");
+ ui_get_but_string(but, data->str, data->maxlen+1);
+
+ data->origstr= BLI_strdup(data->str);
+ data->selextend= 0;
+ data->selstartx= 0;
+
+ /* set cursor pos to the end of the text */
+ but->editstr= data->str;
+ but->pos= strlen(data->str);
+ but->selsta= 0;
+ but->selend= strlen(but->drawstr) - strlen(but->str);
+
+ ui_check_but(but);
+}
+
+static void ui_textedit_end(uiBut *but, uiHandleButtonData *data)
+{
+ if(but) {
+ but->editstr= 0;
+ but->pos= -1;
+ }
+}
+
+static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonData *data)
+{
+ uiBut *but;
+
+ /* label and roundbox can overlap real buttons (backdrops...) */
+ if(actbut->type==LABEL && actbut->type==ROUNDBOX)
+ return;
+
+ for(but= actbut->next; but; but= but->next) {
+ if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) {
+ data->postbut= but;
+ data->posttype= BUTTON_ACTIVATE_TEXT_EDITING;
+ return;
+ }
+ }
+ for(but= block->buttons.first; but!=actbut; but= but->next) {
+ if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) {
+ data->postbut= but;
+ data->posttype= BUTTON_ACTIVATE_TEXT_EDITING;
+ return;
+ }
+ }
+}
+
+static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonData *data)
+{
+ uiBut *but;
+
+ /* label and roundbox can overlap real buttons (backdrops...) */
+ if(actbut->type==LABEL && actbut->type==ROUNDBOX)
+ return;
+
+ for(but= actbut->prev; but; but= but->prev) {
+ if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) {
+ data->postbut= but;
+ data->posttype= BUTTON_ACTIVATE_TEXT_EDITING;
+ return;
+ }
+ }
+ for(but= block->buttons.last; but!=actbut; but= but->prev) {
+ if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) {
+ data->postbut= but;
+ data->posttype= BUTTON_ACTIVATE_TEXT_EDITING;
+ return;
+ }
+ }
+}
+
+static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+ int mx, my, changed= 0, retval= WM_UI_HANDLER_CONTINUE;
+
+ switch(event->type) {
+ case RIGHTMOUSE:
+ case ESCKEY:
+ data->cancel= 1;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ retval= WM_UI_HANDLER_BREAK;
+ break;
+ case LEFTMOUSE: {
+ if(event->val==KM_PRESS) {
+ mx= event->x;
+ my= event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if ((but->y1 <= my) && (my <= but->y2) && (but->x1 <= mx) && (mx <= but->x2)) {
+ ui_textedit_set_cursor_pos(but, data, mx);
+ but->selsta = but->selend = but->pos;
+ data->selstartx= mx;
+
+ button_activate_state(C, but, BUTTON_STATE_TEXT_SELECTING);
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ else {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ }
+ break;
+ }
+ }
+
+ if(event->val==KM_PRESS) {
+ switch (event->type) {
+ case VKEY:
+ case XKEY:
+ case CKEY:
+ if(event->ctrl || event->oskey) {
+ if(event->type == VKEY)
+ changed= ui_textedit_copypaste(but, data, 1, 0, 0);
+ else if(event->type == CKEY)
+ changed= ui_textedit_copypaste(but, data, 0, 1, 0);
+ else if(event->type == XKEY)
+ changed= ui_textedit_copypaste(but, data, 0, 0, 1);
+
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ break;
+ case RIGHTARROWKEY:
+ ui_textedit_move(but, data, 1, event->shift, event->ctrl);
+ retval= WM_UI_HANDLER_BREAK;
+ break;
+ case LEFTARROWKEY:
+ ui_textedit_move(but, data, 0, event->shift, event->ctrl);
+ retval= WM_UI_HANDLER_BREAK;
+ break;
+ case DOWNARROWKEY:
+ case ENDKEY:
+ ui_textedit_move_end(but, data, 1, event->shift);
+ retval= WM_UI_HANDLER_BREAK;
+ break;
+ case UPARROWKEY:
+ case HOMEKEY:
+ ui_textedit_move_end(but, data, 0, event->shift);
+ retval= WM_UI_HANDLER_BREAK;
+ break;
+ case PADENTER:
+ case RETKEY:
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ retval= WM_UI_HANDLER_BREAK;
+ break;
+ case DELKEY:
+ changed= ui_textedit_delete(but, data, 1, 0);
+ retval= WM_UI_HANDLER_BREAK;
+ break;
+
+ case BACKSPACEKEY:
+ changed= ui_textedit_delete(but, data, 0, event->shift);
+ retval= WM_UI_HANDLER_BREAK;
+ break;
+
+ case TABKEY:
+ /* there is a key conflict here, we can't tab with autocomplete */
+ if(but->autocomplete_func) {
+ changed= ui_textedit_autocomplete(C, but, data);
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ /* the hotkey here is not well defined, was G.qual so we check all */
+ else if(event->shift || event->ctrl || event->alt || event->oskey) {
+ ui_textedit_prev_but(block, but, data);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else {
+ ui_textedit_next_but(block, but, data);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ retval= WM_UI_HANDLER_BREAK;
+ break;
+ }
+
+ if(event->ascii && (retval == WM_UI_HANDLER_CONTINUE)) {
+ changed= ui_textedit_type_ascii(but, data, event->ascii);
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ if(changed) {
+ if(data->interactive) ui_apply_button(C, block, but, data, 1);
+ else ui_check_but(but);
+ }
+
+ if(changed || (retval == WM_UI_HANDLER_BREAK))
+ ED_region_tag_redraw(data->region);
+}
+
+static void ui_do_but_textedit_select(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+ int mx, my, retval= WM_UI_HANDLER_CONTINUE;
+
+ switch(event->type) {
+ case MOUSEMOVE: {
+ mx= event->x;
+ my= event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ ui_textedit_set_cursor_select(but, data, mx);
+ retval= WM_UI_HANDLER_BREAK;
+ break;
+ }
+ case LEFTMOUSE:
+ if(event->val == 0)
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ retval= WM_UI_HANDLER_BREAK;
+ break;
+ }
+
+ if(retval == WM_UI_HANDLER_BREAK) {
+ ui_check_but(but);
+ ED_region_tag_redraw(data->region);
+ }
+}
+
+/* ************* number editing for various types ************* */
+
+static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
+{
+ float softrange, softmin, softmax;
+
+ if(but->type == BUT_CURVE) {
+ data->cumap= (CurveMapping*)but->poin;
+ but->editcumap= data->coba;
+ }
+ else if(but->type == BUT_COLORBAND) {
+ data->coba= (ColorBand*)but->poin;
+ but->editcoba= data->coba;
+ }
+ else if(ELEM(but->type, BUT_NORMAL, HSVCUBE)) {
+ ui_get_but_vectorf(but, data->origvec);
+ VECCOPY(data->vec, data->origvec);
+ but->editvec= data->vec;
+ }
+ else {
+ data->startvalue= ui_get_but_val(but);
+ data->origvalue= data->startvalue;
+ data->value= data->origvalue;
+ but->editval= &data->value;
+
+ softmin= but->softmin;
+ softmax= but->softmax;
+ softrange= softmax - softmin;
+
+ data->dragfstart= (softrange == 0.0)? 0.0: (data->value - softmin)/softrange;
+ data->dragf= data->dragfstart;
+ }
+
+ data->dragchange= 0;
+ data->draglock= 1;
+}
+
+static void ui_numedit_end(uiBut *but, uiHandleButtonData *data)
+{
+ but->editval= NULL;
+ but->editvec= NULL;
+ but->editcoba= NULL;
+ but->editcumap= NULL;
+
+ data->dragstartx= 0;
+ data->draglastx= 0;
+ data->dragchange= 0;
+ data->dragcbd= NULL;
+ data->dragsel= 0;
+}
+
+static void ui_numedit_apply(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data)
+{
+ if(data->interactive) ui_apply_button(C, block, but, data, 1);
+ else ui_check_but(but);
+
+ ED_region_tag_redraw(data->region);
+}
+
+/* ****************** menu opening for various types **************** */
+
+static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ uiBlockCreateFunc func= NULL;
+ uiBlockHandleCreateFunc handlefunc= NULL;
+ uiMenuCreateFunc menufunc= NULL;
+ void *arg= NULL;
+
+ switch(but->type) {
+ case BLOCK:
+ case PULLDOWN:
+ func= but->block_create_func;
+ arg= but->poin;
+ break;
+ case HMENU:
+ menufunc= but->menu_create_func;
+ arg= but->poin;
+ break;
+ case MENU:
+ data->origvalue= ui_get_but_val(but);
+ data->value= data->origvalue;
+ but->editval= &data->value;
+
+ handlefunc= ui_block_func_MENU;
+ arg= but;
+ break;
+ case ICONROW:
+ handlefunc= ui_block_func_ICONROW;
+ arg= but;
+ break;
+ case ICONTEXTROW:
+ handlefunc= ui_block_func_ICONTEXTROW;
+ arg= but;
+ break;
+ case COL:
+ ui_get_but_vectorf(but, data->origvec);
+ VECCOPY(data->vec, data->origvec);
+ but->editvec= data->vec;
+
+ handlefunc= ui_block_func_COL;
+ arg= but;
+ break;
+ }
+
+ if(func || handlefunc) {
+ data->menu= ui_popup_block_create(C, data->region, but, func, handlefunc, arg);
+ if(but->block->handle)
+ data->menu->popup= but->block->handle->popup;
+ }
+ else if(menufunc) {
+ data->menu= ui_popup_menu_create(C, data->region, but, menufunc, arg);
+ if(but->block->handle)
+ data->menu->popup= but->block->handle->popup;
+ }
+
+ /* this makes adjacent blocks auto open from now on */
+ //if(but->block->auto_open==0) but->block->auto_open= 1;
+}
+
+static void ui_blockopen_end(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ if(but) {
+ but->editval= NULL;
+ but->editvec= NULL;
+
+ but->block->auto_open_last= PIL_check_seconds_timer();
+ }
+
+ if(data->menu) {
+ ui_popup_block_free(C, data->menu);
+ data->menu= NULL;
+ }
+}
+
+/* ***************** events for different button types *************** */
+
+static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+ if(data->state == BUTTON_STATE_HIGHLIGHT) {
+ if(event->type == LEFTMOUSE && event->val==KM_PRESS) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_RELEASE);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if(event->type == LEFTMOUSE && but->block->handle) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if(ELEM(event->type, PADENTER, RETKEY) && event->val==KM_PRESS) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_FLASH);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if(data->state == BUTTON_STATE_WAIT_RELEASE) {
+ if(event->type == LEFTMOUSE && event->val!=KM_PRESS) {
+ if(!(but->flag & UI_SELECT))
+ data->cancel= 1;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+ if(data->state == BUTTON_STATE_HIGHLIGHT) {
+ if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if(data->state == BUTTON_STATE_WAIT_KEY_EVENT) {
+ if(event->type == MOUSEMOVE)
+ return WM_UI_HANDLER_CONTINUE;
+
+ if(event->val==KM_PRESS) {
+ if(WM_key_event_string(event->type)[0])
+ ui_set_but_val(but, event->type);
+ else
+ data->cancel= 1;
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+ if(data->state == BUTTON_STATE_HIGHLIGHT) {
+ if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if(data->state == BUTTON_STATE_TEXT_EDITING) {
+ ui_do_but_textedit(C, block, but, data, event);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if(data->state == BUTTON_STATE_TEXT_SELECTING) {
+ ui_do_but_textedit_select(C, block, but, data, event);
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+ if(data->state == BUTTON_STATE_HIGHLIGHT) {
+ if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) {
+ data->togdual= event->ctrl;
+ data->togonly= !event->shift;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+ if(data->state == BUTTON_STATE_HIGHLIGHT) {
+ if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, int snap, int mx)
+{
+ float deler, tempf, softmin, softmax, softrange;
+ int lvalue, temp, changed= 0;
+
+ if(mx == data->draglastx)
+ return changed;
+
+ /* drag-lock - prevent unwanted scroll adjustments */
+ /* change value (now 3) to adjust threshold in pixels */
+ if(data->draglock) {
+ if(abs(mx-data->dragstartx) <= 3)
+ return changed;
+
+ data->draglock= 0;
+ data->dragstartx= mx; /* ignore mouse movement within drag-lock */
+ }
+
+ softmin= but->softmin;
+ softmax= but->softmax;
+ softrange= softmax - softmin;
+
+ deler= 500;
+ if(!ui_is_but_float(but)) {
+ if((softrange)<100) deler= 200.0;
+ if((softrange)<25) deler= 50.0;
+ }
+ deler /= fac;
+
+ if(ui_is_but_float(but) && softrange > 11) {
+ /* non linear change in mouse input- good for high precicsion */
+ data->dragf+= (((float)(mx-data->draglastx))/deler) * (fabs(data->dragstartx-mx)*0.002);
+ } else if (!ui_is_but_float(but) && softrange > 129) { /* only scale large int buttons */
+ /* non linear change in mouse input- good for high precicsionm ints need less fine tuning */
+ data->dragf+= (((float)(mx-data->draglastx))/deler) * (fabs(data->dragstartx-mx)*0.004);
+ } else {
+ /*no scaling */
+ data->dragf+= ((float)(mx-data->draglastx))/deler ;
+ }
+
+ if(data->dragf>1.0) data->dragf= 1.0;
+ if(data->dragf<0.0) data->dragf= 0.0;
+ data->draglastx= mx;
+ tempf= (softmin + data->dragf*softrange);
+
+ if(!ui_is_but_float(but)) {
+ temp= floor(tempf+.5);
+
+ if(tempf==softmin || tempf==softmax);
+ else if(snap) {
+ if(snap == 2) temp= 100*(temp/100);
+ else temp= 10*(temp/10);
+ }
+
+ CLAMP(temp, softmin, softmax);
+ lvalue= (int)data->value;
+
+ if(temp != lvalue) {
+ data->dragchange= 1;
+ data->value= (double)temp;
+ changed= 1;
+ }
+ }
+ else {
+ temp= 0;
+
+ if(snap) {
+ if(snap == 2) {
+ if(tempf==softmin || tempf==softmax);
+ else if(softrange < 2.10) tempf= 0.01*floor(100.0*tempf);
+ else if(softrange < 21.0) tempf= 0.1*floor(10.0*tempf);
+ else tempf= floor(tempf);
+ }
+ else {
+ if(tempf==softmin || tempf==softmax);
+ else if(softrange < 2.10) tempf= 0.1*floor(10*tempf);
+ else if(softrange < 21.0) tempf= floor(tempf);
+ else tempf= 10.0*floor(tempf/10.0);
+ }
+ }
+
+ CLAMP(tempf, softmin, softmax);
+
+ if(tempf != data->value) {
+ data->dragchange= 1;
+ data->value= tempf;
+ changed= 1;
+ }
+ }
+
+ return changed;
+}
+
+static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+ int mx, my, click= 0;
+ int retval= WM_UI_HANDLER_CONTINUE;
+
+ mx= event->x;
+ my= event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if(data->state == BUTTON_STATE_HIGHLIGHT) {
+ if(event->val==KM_PRESS) {
+ if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->shift) {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ else if(event->type == LEFTMOUSE) {
+ data->dragstartx= mx;
+ data->draglastx= mx;
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ else if(ELEM(event->type, PADENTER, RETKEY) && event->val==KM_PRESS)
+ click= 1;
+ }
+ }
+ else if(data->state == BUTTON_STATE_NUM_EDITING) {
+ if(event->type == LEFTMOUSE && event->val!=KM_PRESS) {
+ if(data->dragchange)
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ else
+ click= 1;
+ }
+ else if(event->type == MOUSEMOVE) {
+ float fac;
+ int snap;
+
+ fac= 1.0f;
+ if(event->shift) fac /= 10.0f;
+ if(event->alt) fac /= 20.0f;
+
+ if(event->custom == EVT_DATA_TABLET) {
+ wmTabletData *wmtab= event->customdata;
+
+ /* de-sensitise based on tablet pressure */
+ if (ELEM(wmtab->Active, DEV_STYLUS, DEV_ERASER))
+ fac *= wmtab->Pressure;
+ }
+
+ snap= (event->ctrl)? (event->shift)? 2: 1: 0;
+
+ if(ui_numedit_but_NUM(but, data, fac, snap, mx))
+ ui_numedit_apply(C, block, but, data);
+ }
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ else if(data->state == BUTTON_STATE_TEXT_EDITING) {
+ ui_do_but_textedit(C, block, but, data, event);
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ else if(data->state == BUTTON_STATE_TEXT_SELECTING) {
+ ui_do_but_textedit_select(C, block, but, data, event);
+ retval= WM_UI_HANDLER_BREAK;
+ }
+
+ if(click) {
+ /* we can click on the side arrows to increment/decrement,
+ * or click inside to edit the value directly */
+ float tempf, softmin, softmax;
+ int temp;
+
+ softmin= but->softmin;
+ softmax= but->softmax;
+
+ if(!ui_is_but_float(but)) {
+ if(mx < (but->x1 + (but->x2 - but->x1)/3 - 3)) {
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ temp= (int)data->value - 1;
+ if(temp>=softmin && temp<=softmax)
+ data->value= (double)temp;
+ else
+ data->cancel= 1;
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else if(mx > (but->x1 + (2*(but->x2 - but->x1)/3) + 3)) {
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ temp= (int)data->value + 1;
+ if(temp>=softmin && temp<=softmax)
+ data->value= (double)temp;
+ else
+ data->cancel= 1;
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ }
+ else {
+ if(mx < (but->x1 + (but->x2 - but->x1)/3 - 3)) {
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ tempf= data->value - 0.01*but->a1;
+ if (tempf < softmin) tempf = softmin;
+ data->value= tempf;
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else if(mx > but->x1 + (2*((but->x2 - but->x1)/3) + 3)) {
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ tempf= data->value + 0.01*but->a1;
+ if (tempf > softmax) tempf = softmax;
+ data->value= tempf;
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ }
+
+ retval= WM_UI_HANDLER_BREAK;
+ }
+
+ return retval;
+}
+
+static int ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, int shift, int ctrl, int mx)
+{
+ float deler, f, tempf, softmin, softmax, softrange;
+ int temp, lvalue, changed= 0;
+
+ softmin= but->softmin;
+ softmax= but->softmax;
+ softrange= softmax - softmin;
+
+ if(but->type==NUMSLI) deler= ((but->x2-but->x1) - 5.0*but->aspect);
+ else if(but->type==HSVSLI) deler= ((but->x2-but->x1)/2 - 5.0*but->aspect);
+ else deler= (but->x2-but->x1- 5.0*but->aspect);
+
+ f= (float)(mx-data->dragstartx)/deler + data->dragfstart;
+
+ if(shift)
+ f= (f-data->dragfstart)/10.0 + data->dragfstart;
+
+ CLAMP(f, 0.0, 1.0);
+ tempf= softmin + f*softrange;
+ temp= floor(tempf+.5);
+
+ if(ctrl) {
+ if(tempf==softmin || tempf==softmax);
+ else if(ui_is_but_float(but)) {
+
+ if(shift) {
+ if(tempf==softmin || tempf==softmax);
+ else if(softmax-softmin < 2.10) tempf= 0.01*floor(100.0*tempf);
+ else if(softmax-softmin < 21.0) tempf= 0.1*floor(10.0*tempf);
+ else tempf= floor(tempf);
+ }
+ else {
+ if(softmax-softmin < 2.10) tempf= 0.1*floor(10*tempf);
+ else if(softmax-softmin < 21.0) tempf= floor(tempf);
+ else tempf= 10.0*floor(tempf/10.0);
+ }
+ }
+ else {
+ temp= 10*(temp/10);
+ tempf= temp;
+ }
+ }
+
+ if(!ui_is_but_float(but)) {
+ lvalue= floor(data->value+0.5);
+
+ CLAMP(temp, softmin, softmax);
+
+ if(temp != lvalue) {
+ data->value= temp;
+ data->dragchange= 1;
+ changed= 1;
+ }
+ }
+ else {
+ CLAMP(tempf, softmin, softmax);
+
+ if(tempf != data->value) {
+ data->value= tempf;
+ data->dragchange= 1;
+ changed= 1;
+ }
+ }
+
+ return changed;
+}
+
+static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+ int mx, my, click= 0;
+ int retval= WM_UI_HANDLER_CONTINUE;
+
+ mx= event->x;
+ my= event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if(data->state == BUTTON_STATE_HIGHLIGHT) {
+ if(event->val==KM_PRESS) {
+ if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->shift) {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ else if(event->type == LEFTMOUSE) {
+ data->dragstartx= mx;
+ data->draglastx= mx;
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ else if(ELEM(event->type, PADENTER, RETKEY) && event->val==KM_PRESS)
+ click= 1;
+ }
+ }
+ else if(data->state == BUTTON_STATE_NUM_EDITING) {
+ if(event->type == LEFTMOUSE && event->val!=KM_PRESS) {
+ if(data->dragchange)
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ else
+ click= 1;
+ }
+ else if(event->type == MOUSEMOVE) {
+ if(ui_numedit_but_SLI(but, data, event->shift, event->ctrl, mx))
+ ui_numedit_apply(C, block, but, data);
+ }
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ else if(data->state == BUTTON_STATE_TEXT_EDITING) {
+ ui_do_but_textedit(C, block, but, data, event);
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ else if(data->state == BUTTON_STATE_TEXT_SELECTING) {
+ ui_do_but_textedit_select(C, block, but, data, event);
+ retval= WM_UI_HANDLER_BREAK;
+ }
+
+ if(click) {
+ if (event->ctrl) {
+ /* nudge slider to the left or right */
+ float f, tempf, softmin, softmax, softrange;
+ int temp;
+
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ softmin= but->softmin;
+ softmax= but->softmax;
+ softrange= softmax - softmin;
+
+ tempf= data->value;
+ temp= (int)data->value;
+
+ if(but->type==SLI) f= (float)(mx-but->x1)/(but->x2-but->x1);
+ else f= (float)(mx- but->x1)/(but->x2-but->x1);
+
+ f= softmin + f*softrange;
+
+ if(!ui_is_but_float(but)) {
+ if(f<temp) temp--;
+ else temp++;
+
+ if(temp>=softmin && temp<=softmax)
+ data->value= temp;
+ else
+ data->cancel= 1;
+ }
+ else {
+ if(f<tempf) tempf-=.01;
+ else tempf+=.01;
+
+ if(tempf>=softmin && tempf<=softmax)
+ data->value= tempf;
+ else
+ data->cancel= 1;
+ }
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ else {
+ /* edit the value directly */
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ return retval;
+}
+
+static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+ if(data->state == BUTTON_STATE_HIGHLIGHT) {
+ if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) {
+ button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+static int ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data, int mx, int my)
+{
+ float dx, dy, rad, radsq, mrad, *fp;
+ int mdx, mdy, changed= 1;
+
+ /* button is presumed square */
+ /* if mouse moves outside of sphere, it does negative normal */
+
+ fp= data->origvec;
+ rad= (but->x2 - but->x1);
+ radsq= rad*rad;
+
+ if(fp[2]>0.0f) {
+ mdx= (rad*fp[0]);
+ mdy= (rad*fp[1]);
+ }
+ else if(fp[2]> -1.0f) {
+ mrad= rad/sqrt(fp[0]*fp[0] + fp[1]*fp[1]);
+
+ mdx= 2.0f*mrad*fp[0] - (rad*fp[0]);
+ mdy= 2.0f*mrad*fp[1] - (rad*fp[1]);
+ }
+ else mdx= mdy= 0;
+
+ dx= (float)(mx+mdx-data->dragstartx);
+ dy= (float)(my+mdy-data->dragstarty);
+
+ fp= data->vec;
+ mrad= dx*dx+dy*dy;
+ if(mrad < radsq) { /* inner circle */
+ fp[0]= dx;
+ fp[1]= dy;
+ fp[2]= sqrt( radsq-dx*dx-dy*dy );
+ }
+ else { /* outer circle */
+
+ mrad= rad/sqrt(mrad); // veclen
+
+ dx*= (2.0f*mrad - 1.0f);
+ dy*= (2.0f*mrad - 1.0f);
+
+ mrad= dx*dx+dy*dy;
+ if(mrad < radsq) {
+ fp[0]= dx;
+ fp[1]= dy;
+ fp[2]= -sqrt( radsq-dx*dx-dy*dy );
+ }
+ }
+ Normalize(fp);
+
+ data->draglastx= mx;
+ data->draglasty= my;
+
+ return changed;
+}
+
+static int ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+ int mx, my;
+
+ mx= event->x;
+ my= event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if(data->state == BUTTON_STATE_HIGHLIGHT) {
+ if(event->type==LEFTMOUSE && event->val==KM_PRESS) {
+ data->dragstartx= mx;
+ data->dragstarty= my;
+ data->draglastx= mx;
+ data->draglasty= my;
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ /* also do drag the first time */
+ if(ui_numedit_but_NORMAL(but, data, mx, my))
+ ui_numedit_apply(C, block, but, data);
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if(data->state == BUTTON_STATE_NUM_EDITING) {
+ if(event->type == MOUSEMOVE) {
+ if(mx!=data->draglastx || my!=data->draglasty) {
+ if(ui_numedit_but_NORMAL(but, data, mx, my))
+ ui_numedit_apply(C, block, but, data);
+ }
+ }
+ else if(event->type==LEFTMOUSE && event->val!=KM_PRESS)
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, int my)
+{
+ float x, y;
+ int changed= 1;
+
+ /* relative position within box */
+ x= ((float)mx-but->x1)/(but->x2-but->x1);
+ y= ((float)my-but->y1)/(but->y2-but->y1);
+ CLAMP(x, 0.0, 1.0);
+ CLAMP(y, 0.0, 1.0);
+
+ if(but->a1==0) {
+ but->hsv[0]= x;
+ but->hsv[2]= y;
+ }
+ else if(but->a1==1) {
+ but->hsv[0]= x;
+ but->hsv[1]= y;
+ }
+ else if(but->a1==2) {
+ but->hsv[2]= x;
+ but->hsv[1]= y;
+ }
+ else
+ but->hsv[0]= x;
+
+ ui_set_but_hsv(but); // converts to rgb
+
+ // update button values and strings
+ ui_update_block_buts_hsv(but->block, but->hsv);
+
+ data->draglastx= mx;
+ data->draglasty= my;
+
+ return changed;
+}
+
+static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+ int mx, my;
+
+ mx= event->x;
+ my= event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if(data->state == BUTTON_STATE_HIGHLIGHT) {
+ if(event->type==LEFTMOUSE && event->val==KM_PRESS) {
+ data->dragstartx= mx;
+ data->dragstarty= my;
+ data->draglastx= mx;
+ data->draglasty= my;
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ /* also do drag the first time */
+ if(ui_numedit_but_HSVCUBE(but, data, mx, my))
+ ui_numedit_apply(C, block, but, data);
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if(data->state == BUTTON_STATE_NUM_EDITING) {
+ if(event->type == MOUSEMOVE) {
+ if(mx!=data->draglastx || my!=data->draglasty) {
+ if(ui_numedit_but_HSVCUBE(but, data, mx, my))
+ ui_numedit_apply(C, block, but, data);
+ }
+ }
+ else if(event->type==LEFTMOUSE && event->val!=KM_PRESS)
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+static int verg_colorband(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 WM_UI_HANDLER_CONTINUE;
+}
+
+static void ui_colorband_update(ColorBand *coba)
+{
+ int a;
+
+ if(coba->tot<2) return;
+
+ for(a=0; a<coba->tot; a++) coba->data[a].cur= a;
+ qsort(coba->data, coba->tot, sizeof(CBData), verg_colorband);
+ for(a=0; a<coba->tot; a++) {
+ if(coba->data[a].cur==coba->cur) {
+ coba->cur= a;
+ break;
+ }
+ }
+}
+
+static int ui_numedit_but_COLORBAND(uiBut *but, uiHandleButtonData *data, int mx)
+{
+ float dx;
+ int changed= 0;
+
+ if(data->draglastx == mx)
+ return changed;
+
+ dx= ((float)(mx - data->draglastx))/(but->x2-but->x1);
+ data->dragcbd->pos += dx;
+ CLAMP(data->dragcbd->pos, 0.0, 1.0);
+
+ ui_colorband_update(data->coba);
+ data->dragcbd= data->coba->data + data->coba->cur; /* because qsort */
+
+ data->draglastx= mx;
+ changed= 1;
+
+ return changed;
+}
+
+static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+ ColorBand *coba;
+ CBData *cbd;
+ int mx, my, a, xco, mindist= 12;
+
+ mx= event->x;
+ my= event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if(data->state == BUTTON_STATE_HIGHLIGHT) {
+ if(event->type==LEFTMOUSE && event->val==KM_PRESS) {
+ coba= (ColorBand*)but->poin;
+
+ if(event->ctrl) {
+ /* insert new key on mouse location */
+ if(coba->tot < MAXCOLORBAND-1) {
+ float pos= ((float)(mx - but->x1))/(but->x2-but->x1);
+ float col[4];
+
+ do_colorband(coba, pos, col); /* executes it */
+
+ coba->tot++;
+ coba->cur= coba->tot-1;
+
+ coba->data[coba->cur].r= col[0];
+ coba->data[coba->cur].g= col[1];
+ coba->data[coba->cur].b= col[2];
+ coba->data[coba->cur].a= col[3];
+ coba->data[coba->cur].pos= pos;
+
+ ui_colorband_update(coba);
+ }
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else {
+ data->dragstartx= mx;
+ data->dragstarty= my;
+ data->draglastx= mx;
+ data->draglasty= my;
+
+ /* activate new key when mouse is close */
+ for(a=0, cbd= coba->data; a<coba->tot; a++, cbd++) {
+ xco= but->x1 + (cbd->pos*(but->x2-but->x1));
+ xco= ABS(xco-mx);
+ if(a==coba->cur) xco+= 5; // selected one disadvantage
+ if(xco<mindist) {
+ coba->cur= a;
+ mindist= xco;
+ }
+ }
+
+ data->dragcbd= coba->data + coba->cur;
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+ }
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if(data->state == BUTTON_STATE_NUM_EDITING) {
+ if(event->type == MOUSEMOVE) {
+ if(mx!=data->draglastx || my!=data->draglasty) {
+ if(ui_numedit_but_COLORBAND(but, data, mx))
+ ui_numedit_apply(C, block, but, data);
+ }
+ }
+ else if(event->type==LEFTMOUSE && event->val!=KM_PRESS)
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap, int mx, int my)
+{
+ CurveMapping *cumap= data->cumap;
+ CurveMap *cuma= cumap->cm+cumap->cur;
+ CurveMapPoint *cmp= cuma->curve;
+ float fx, fy, zoomx, zoomy, offsx, offsy;
+ int a, changed= 0;
+
+ zoomx= (but->x2-but->x1)/(cumap->curr.xmax-cumap->curr.xmin);
+ zoomy= (but->y2-but->y1)/(cumap->curr.ymax-cumap->curr.ymin);
+ offsx= cumap->curr.xmin;
+ offsy= cumap->curr.ymin;
+
+ if(data->dragsel != -1) {
+ int moved_point= 0; /* for ctrl grid, can't use orig coords because of sorting */
+
+ fx= (mx-data->draglastx)/zoomx;
+ fy= (my-data->draglasty)/zoomy;
+ for(a=0; a<cuma->totpoint; a++) {
+ if(cmp[a].flag & SELECT) {
+ float origx= cmp[a].x, origy= cmp[a].y;
+ cmp[a].x+= fx;
+ cmp[a].y+= fy;
+ if(snap) {
+ cmp[a].x= 0.125f*floor(0.5f + 8.0f*cmp[a].x);
+ cmp[a].y= 0.125f*floor(0.5f + 8.0f*cmp[a].y);
+ }
+ if(cmp[a].x!=origx || cmp[a].y!=origy)
+ moved_point= 1;
+ }
+ }
+
+ curvemapping_changed(cumap, 0); /* no remove doubles */
+
+ if(moved_point) {
+ data->draglastx= mx;
+ data->draglasty= my;
+ changed= 1;
+ }
+
+ data->dragchange= 1; /* mark for selection */
+ }
+ else {
+ fx= (mx-data->draglastx)/zoomx;
+ fy= (my-data->draglasty)/zoomy;
+
+ /* clamp for clip */
+ if(cumap->flag & CUMA_DO_CLIP) {
+ if(cumap->curr.xmin-fx < cumap->clipr.xmin)
+ fx= cumap->curr.xmin - cumap->clipr.xmin;
+ else if(cumap->curr.xmax-fx > cumap->clipr.xmax)
+ fx= cumap->curr.xmax - cumap->clipr.xmax;
+ if(cumap->curr.ymin-fy < cumap->clipr.ymin)
+ fy= cumap->curr.ymin - cumap->clipr.ymin;
+ else if(cumap->curr.ymax-fy > cumap->clipr.ymax)
+ fy= cumap->curr.ymax - cumap->clipr.ymax;
+ }
+
+ cumap->curr.xmin-=fx;
+ cumap->curr.ymin-=fy;
+ cumap->curr.xmax-=fx;
+ cumap->curr.ymax-=fy;
+
+ data->draglastx= mx;
+ data->draglasty= my;
+
+ changed= 1;
+ }
+
+ return changed;
+}
+
+static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+ int mx, my, a, changed= 0;
+
+ mx= event->x;
+ my= event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if(data->state == BUTTON_STATE_HIGHLIGHT) {
+ if(event->type==LEFTMOUSE && event->val==KM_PRESS) {
+ CurveMapping *cumap= (CurveMapping*)but->poin;
+ CurveMap *cuma= cumap->cm+cumap->cur;
+ CurveMapPoint *cmp= cuma->curve;
+ float fx, fy, zoomx, zoomy, offsx, offsy;
+ float dist, mindist= 200.0f; // 14 pixels radius
+ int sel= -1;
+
+ zoomx= (but->x2-but->x1)/(cumap->curr.xmax-cumap->curr.xmin);
+ zoomy= (but->y2-but->y1)/(cumap->curr.ymax-cumap->curr.ymin);
+ offsx= cumap->curr.xmin;
+ offsy= cumap->curr.ymin;
+
+ if(event->ctrl) {
+ fx= ((float)my - but->x1)/zoomx + offsx;
+ fy= ((float)my - but->y1)/zoomy + offsy;
+
+ curvemap_insert(cuma, fx, fy);
+ curvemapping_changed(cumap, 0);
+ changed= 1;
+ }
+
+ /* check for selecting of a point */
+ cmp= cuma->curve; /* ctrl adds point, new malloc */
+ for(a=0; a<cuma->totpoint; a++) {
+ fx= but->x1 + zoomx*(cmp[a].x-offsx);
+ fy= but->y1 + zoomy*(cmp[a].y-offsy);
+ dist= (fx-mx)*(fx-mx) + (fy-my)*(fy-my);
+ if(dist < mindist) {
+ sel= a;
+ mindist= dist;
+ }
+ }
+
+ if (sel == -1) {
+ /* if the click didn't select anything, check if it's clicked on the
+ * curve itself, and if so, add a point */
+ fx= ((float)mx - but->x1)/zoomx + offsx;
+ fy= ((float)my - but->y1)/zoomy + offsy;
+
+ cmp= cuma->table;
+
+ /* loop through the curve segment table and find what's near the mouse.
+ * 0.05 is kinda arbitrary, but seems to be what works nicely. */
+ for(a=0; a<=CM_TABLE; a++) {
+ if ( ( fabs(fx - cmp[a].x) < (0.05) ) && ( fabs(fy - cmp[a].y) < (0.05) ) ) {
+
+ curvemap_insert(cuma, fx, fy);
+ curvemapping_changed(cumap, 0);
+
+ changed= 1;
+
+ /* reset cmp back to the curve points again, rather than drawing segments */
+ cmp= cuma->curve;
+
+ /* find newly added point and make it 'sel' */
+ for(a=0; a<cuma->totpoint; a++)
+ if(cmp[a].x == fx)
+ sel = a;
+
+ break;
+ }
+ }
+ }
+
+ if(sel!= -1) {
+ /* ok, we move a point */
+ /* deselect all if this one is deselect. except if we hold shift */
+ if(event->shift==0 && (cmp[sel].flag & SELECT)==0)
+ for(a=0; a<cuma->totpoint; a++)
+ cmp[a].flag &= ~SELECT;
+ cmp[sel].flag |= SELECT;
+ }
+ else {
+ /* move the view */
+ data->cancel= 1;
+ }
+
+ data->dragsel= sel;
+
+ data->dragstartx= mx;
+ data->dragstarty= my;
+ data->draglastx= mx;
+ data->draglasty= my;
+
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if(data->state == BUTTON_STATE_NUM_EDITING) {
+ if(event->type == MOUSEMOVE) {
+ if(mx!=data->draglastx || my!=data->draglasty) {
+ if(ui_numedit_but_CURVE(but, data, event->shift, mx, my))
+ ui_numedit_apply(C, block, but, data);
+ }
+ }
+ else if(event->type==LEFTMOUSE && event->val!=KM_PRESS) {
+ if(data->dragsel != -1) {
+ CurveMapping *cumap= data->cumap;
+ CurveMap *cuma= cumap->cm+cumap->cur;
+ CurveMapPoint *cmp= cuma->curve;
+
+ if(!data->dragchange) {
+ /* deselect all, select one */
+ if(event->shift==0) {
+ for(a=0; a<cuma->totpoint; a++)
+ cmp[a].flag &= ~SELECT;
+ cmp[data->dragsel].flag |= SELECT;
+ }
+ }
+ else
+ curvemapping_changed(cumap, 1); /* remove doubles */
+ }
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+#ifdef INTERNATIONAL
+static int ui_do_but_CHARTAB(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+ /* XXX 2.50 bad global and state access */
+#if 0
+ float sx, sy, ex, ey;
+ float width, height;
+ float butw, buth;
+ int mx, my, x, y, cs, che;
+
+ mx= event->x;
+ my= event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if(data->state == BUTTON_STATE_HIGHLIGHT) {
+ if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) {
+ /* Calculate the size of the button */
+ width = abs(but->x2 - but->x1);
+ height = abs(but->y2 - but->y1);
+
+ butw = floor(width / 12);
+ buth = floor(height / 6);
+
+ /* Initialize variables */
+ sx = but->x1;
+ ex = but->x1 + butw;
+ sy = but->y1 + height - buth;
+ ey = but->y1 + height;
+
+ cs = G.charstart;
+
+ /* And the character is */
+ x = (int) ((mx / butw) - 0.5);
+ y = (int) (6 - ((my / buth) - 0.5));
+
+ che = cs + (y*12) + x;
+
+ if(che > G.charmax)
+ che = 0;
+
+ if(G.obedit)
+ {
+ do_textedit(0,0,che);
+ }
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if(ELEM(event->type, WHEELUPMOUSE, PAGEUPKEY)) {
+ for(but= block->buttons.first; but; but= but->next) {
+ if(but->type == CHARTAB) {
+ G.charstart = G.charstart - (12*6);
+ if(G.charstart < 0)
+ G.charstart = 0;
+ if(G.charstart < G.charmin)
+ G.charstart = G.charmin;
+ ui_draw_but(but);
+
+ //Really nasty... to update the num button from the same butblock
+ for(bt= block->buttons.first; bt; bt= bt->next)
+ {
+ if(ELEM(bt->type, NUM, NUMABS)) {
+ ui_check_but(bt);
+ ui_draw_but(bt);
+ }
+ }
+ retval=UI_CONT;
+ break;
+ }
+ }
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if(ELEM(event->type, WHEELDOWNMOUSE, PAGEDOWNKEY)) {
+ for(but= block->buttons.first; but; but= but->next)
+ {
+ if(but->type == CHARTAB)
+ {
+ G.charstart = G.charstart + (12*6);
+ if(G.charstart > (0xffff - 12*6))
+ G.charstart = 0xffff - (12*6);
+ if(G.charstart > G.charmax - 12*6)
+ G.charstart = G.charmax - 12*6;
+ ui_draw_but(but);
+
+ for(bt= block->buttons.first; bt; bt= bt->next)
+ {
+ if(ELEM(bt->type, NUM, NUMABS)) {
+ ui_check_but(bt);
+ ui_draw_but(bt);
+ }
+ }
+
+ but->flag |= UI_ACTIVE;
+ retval=UI_RETURN_OK;
+ break;
+ }
+ }
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+#endif
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+#endif
+
+static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
+{
+ uiHandleButtonData *data;
+ int retval;
+
+ data= but->active;
+ retval= WM_UI_HANDLER_CONTINUE;
+
+ if(but->flag & UI_BUT_DISABLED)
+ return WM_UI_HANDLER_BREAK;
+
+ if(data->state == BUTTON_STATE_HIGHLIGHT) {
+ /* handle copy-paste */
+ if(ELEM(event->type, CKEY, VKEY) && event->val==KM_PRESS && (event->ctrl || event->oskey)) {
+ ui_but_copy_paste(C, but, data, (event->type == CKEY)? 'c': 'v');
+ return WM_UI_HANDLER_BREAK;
+ }
+ /* handle keyframeing */
+ else if(event->type == IKEY && event->val == KM_PRESS) {
+ if(event->alt)
+ ui_but_anim_delete_keyframe(C);
+ else
+ ui_but_anim_insert_keyframe(C);
+
+ ED_region_tag_redraw(CTX_wm_region(C));
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ /* handle driver adding */
+ else if(event->type == DKEY && event->val == KM_PRESS) {
+ if(event->alt)
+ ui_but_anim_remove_driver(C);
+ else
+ ui_but_anim_add_driver(C);
+
+ ED_region_tag_redraw(CTX_wm_region(C));
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ /* handle menu */
+ else if(event->type == RIGHTMOUSE && event->val == KM_PRESS) {
+ ui_but_anim_menu(C, but);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ /* verify if we can edit this button */
+ if(ELEM(event->type, LEFTMOUSE, RETKEY)) {
+ /* this should become disabled button .. */
+ if(but->lock) {
+ if(but->lockstr) {
+ BKE_report(NULL, RPT_WARNING, but->lockstr);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if(but->pointype && but->poin==0) {
+ /* there's a pointer needed */
+ BKE_reportf(NULL, RPT_WARNING, "DoButton pointer error: %s", but->str);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ switch(but->type) {
+ case BUT:
+ retval= ui_do_but_BUT(C, but, data, event);
+ break;
+ case KEYEVT:
+ retval= ui_do_but_KEYEVT(C, but, data, event);
+ break;
+ case TOGBUT:
+ case TOG:
+ case TOGR:
+ case ICONTOG:
+ case ICONTOGN:
+ case TOGN:
+ case BUT_TOGDUAL:
+ retval= ui_do_but_TOG(C, but, data, event);
+ break;
+#if 0
+ case SCROLL:
+ /* DrawBut(b, 1); */
+ /* do_scrollbut(b); */
+ /* DrawBut(b,0); */
+ break;
+#endif
+ case NUM:
+ case NUMABS:
+ retval= ui_do_but_NUM(C, block, but, data, event);
+ break;
+ case SLI:
+ case NUMSLI:
+ case HSVSLI:
+ retval= ui_do_but_SLI(C, block, but, data, event);
+ break;
+ case ROUNDBOX:
+ case LABEL:
+ case TOG3:
+ case ROW:
+ retval= ui_do_but_EXIT(C, but, data, event);
+ break;
+ case TEX:
+ case IDPOIN:
+ retval= ui_do_but_TEX(C, block, but, data, event);
+ break;
+ case MENU:
+ retval= ui_do_but_BLOCK(C, but, data, event);
+ break;
+ case ICONROW:
+ retval= ui_do_but_BLOCK(C, but, data, event);
+ break;
+ case ICONTEXTROW:
+ retval= ui_do_but_BLOCK(C, but, data, event);
+ break;
+ case BLOCK:
+ case PULLDOWN:
+ case HMENU:
+ retval= ui_do_but_BLOCK(C, but, data, event);
+ break;
+ case BUTM:
+ retval= ui_do_but_BUT(C, but, data, event);
+ break;
+ case COL:
+ if(but->a1 == -1) // signal to prevent calling up color picker
+ retval= ui_do_but_EXIT(C, but, data, event);
+ else
+ retval= ui_do_but_BLOCK(C, but, data, event);
+ break;
+ case BUT_NORMAL:
+ retval= ui_do_but_NORMAL(C, block, but, data, event);
+ break;
+ case BUT_COLORBAND:
+ retval= ui_do_but_COLORBAND(C, block, but, data, event);
+ break;
+ case BUT_CURVE:
+ retval= ui_do_but_CURVE(C, block, but, data, event);
+ break;
+ case HSVCUBE:
+ retval= ui_do_but_HSVCUBE(C, block, but, data, event);
+ break;
+#ifdef INTERNATIONAL
+ case CHARTAB:
+ retval= ui_do_but_CHARTAB(C, block, but, data, event);
+ break;
+#endif
+ /* XXX 2.50 links not implemented yet */
+#if 0
+ case LINK:
+ case INLINK:
+ retval= retval= ui_do_but_LINK(block, but);
+ break;
+#endif
+ }
+
+ return retval;
+}
+
+/* ************************ button utilities *********************** */
+
+static int ui_but_contains_pt(uiBut *but, int mx, int my)
+{
+ return ((but->x1<mx && but->x2>=mx) && (but->y1<my && but->y2>=my));
+}
+
+static uiBut *ui_but_find_activated(ARegion *ar)
+{
+ uiBlock *block;
+ uiBut *but;
+
+ for(block=ar->uiblocks.first; block; block=block->next)
+ for(but=block->buttons.first; but; but= but->next)
+ if(but->active)
+ return but;
+
+ return NULL;
+}
+
+static void ui_blocks_set_tooltips(ARegion *ar, int enable)
+{
+ uiBlock *block;
+
+ if(!ar)
+ return;
+
+ /* we disabled buttons when when they were already shown, and
+ * re-enable them on mouse move */
+ for(block=ar->uiblocks.first; block; block=block->next)
+ block->tooltipdisabled= !enable;
+}
+
+static int ui_mouse_inside_region(ARegion *ar, int x, int y)
+{
+ uiBlock *block;
+ int mx, my;
+
+ /* check if the mouse is in the region, and in case of a view2d also check
+ * if it is inside the view2d itself, not over scrollbars for example */
+ if(!BLI_in_rcti(&ar->winrct, x, y)) {
+ for(block=ar->uiblocks.first; block; block=block->next)
+ block->auto_open= 0;
+
+ return 0;
+ }
+
+ if(ar->v2d.mask.xmin!=ar->v2d.mask.xmax) {
+ mx= x;
+ my= y;
+ ui_window_to_region(ar, &mx, &my);
+
+ if(!BLI_in_rcti(&ar->v2d.mask, mx, my))
+ return 0;
+ }
+
+ return 1;
+}
+
+static int ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y)
+{
+ if(!ui_mouse_inside_region(ar, x, y))
+ return 0;
+
+ ui_window_to_block(ar, but->block, &x, &y);
+
+ if(!ui_but_contains_pt(but, x, y))
+ return 0;
+
+ return 1;
+}
+
+static uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
+{
+ uiBlock *block;
+ uiBut *but, *butover= NULL;
+ int mx, my;
+
+ if(!ui_mouse_inside_region(ar, x, y))
+ return NULL;
+
+ for(block=ar->uiblocks.first; block; block=block->next) {
+ mx= x;
+ my= y;
+ ui_window_to_block(ar, block, &mx, &my);
+
+ for(but=block->buttons.first; but; but= but->next) {
+ /* give precedence to already activated buttons */
+ if(but->flag & UI_NO_HILITE)
+ continue;
+
+ if(ui_but_contains_pt(but, mx, my))
+ if(!butover || (!butover->active && but->active))
+ butover= but;
+ }
+ }
+
+ return butover;
+}
+
+/* ****************** button state handling **************************/
+
+static int button_modal_state(uiHandleButtonState state)
+{
+ return ELEM6(state, BUTTON_STATE_WAIT_RELEASE, BUTTON_STATE_WAIT_KEY_EVENT,
+ BUTTON_STATE_NUM_EDITING, BUTTON_STATE_TEXT_EDITING,
+ BUTTON_STATE_TEXT_SELECTING, BUTTON_STATE_MENU_OPEN);
+}
+
+static void button_tooltip_timer_reset(uiBut *but)
+{
+ uiHandleButtonData *data;
+
+ data= but->active;
+
+ if(data->tooltiptimer) {
+ WM_event_remove_window_timer(data->window, data->tooltiptimer);
+ data->tooltiptimer= NULL;
+ }
+
+ if(U.flag & USER_TOOLTIPS)
+ if(!but->block->tooltipdisabled)
+ data->tooltiptimer= WM_event_add_window_timer(data->window, TIMER, BUTTON_TOOLTIP_DELAY);
+}
+
+static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state)
+{
+ uiHandleButtonData *data;
+
+ data= but->active;
+ if(data->state == state)
+ return;
+
+ /* highlight has timers for tooltips and auto open */
+ if(state == BUTTON_STATE_HIGHLIGHT) {
+ but->flag &= ~UI_SELECT;
+
+ button_tooltip_timer_reset(but);
+
+ /* automatic open pulldown block timer */
+ if(ELEM4(but->type, BLOCK, PULLDOWN, HMENU, ICONTEXTROW)) {
+ if(!data->autoopentimer) {
+ int time;
+
+ if(but->block->auto_open==2) time= 1; // test for toolbox
+ else if(but->block->flag & UI_BLOCK_LOOP || but->block->auto_open) time= 5*U.menuthreshold2;
+ else if(U.uiflag & USER_MENUOPENAUTO) time= 5*U.menuthreshold1;
+ else time= -1;
+
+ if(time >= 0)
+ data->autoopentimer= WM_event_add_window_timer(data->window, TIMER, 0.02*(double)time);
+ }
+ }
+ }
+ else {
+ but->flag |= UI_SELECT;
+
+ if(data->tooltiptimer) {
+ WM_event_remove_window_timer(data->window, data->tooltiptimer);
+ data->tooltiptimer= NULL;
+ }
+ if(data->tooltip) {
+ ui_tooltip_free(C, data->tooltip);
+ data->tooltip= NULL;
+ }
+
+ if(data->autoopentimer) {
+ WM_event_remove_window_timer(data->window, data->autoopentimer);
+ data->autoopentimer= NULL;
+ }
+ }
+
+ /* text editing */
+ if(state == BUTTON_STATE_TEXT_EDITING && data->state != BUTTON_STATE_TEXT_SELECTING)
+ ui_textedit_begin(but, data);
+ else if(data->state == BUTTON_STATE_TEXT_EDITING && state != BUTTON_STATE_TEXT_SELECTING)
+ ui_textedit_end(but, data);
+
+ /* number editing */
+ if(state == BUTTON_STATE_NUM_EDITING)
+ ui_numedit_begin(but, data);
+ else if(data->state == BUTTON_STATE_NUM_EDITING)
+ ui_numedit_end(but, data);
+
+ /* menu open */
+ if(state == BUTTON_STATE_MENU_OPEN)
+ ui_blockopen_begin(C, but, data);
+ else if(data->state == BUTTON_STATE_MENU_OPEN)
+ ui_blockopen_end(C, but, data);
+
+ /* add a short delay before exiting, to ensure there is some feedback */
+ if(state == BUTTON_STATE_WAIT_FLASH) {
+ data->flashtimer= WM_event_add_window_timer(data->window, TIMER, BUTTON_FLASH_DELAY);
+ }
+ else if(data->flashtimer) {
+ WM_event_remove_window_timer(data->window, data->flashtimer);
+ data->flashtimer= NULL;
+ }
+
+ /* add a blocking ui handler at the window handler for blocking, modal states
+ * but not for popups, because we already have a window level handler*/
+ if(!(but->block->handle && but->block->handle->popup)) {
+ if(button_modal_state(state)) {
+ if(!button_modal_state(data->state))
+ WM_event_add_ui_handler(C, &data->window->handlers, ui_handler_region_menu, NULL, data);
+ }
+ else {
+ if(button_modal_state(data->state))
+ WM_event_remove_ui_handler(&data->window->handlers, ui_handler_region_menu, NULL, data);
+ }
+ }
+
+ data->state= state;
+
+ ui_check_but(but);
+
+ /* redraw */
+ ED_region_tag_redraw(data->region);
+}
+
+static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type)
+{
+ uiHandleButtonData *data;
+
+ /* setup struct */
+ data= MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData");
+ data->window= CTX_wm_window(C);
+ data->region= ar;
+ data->interactive= but->type==BUT_CURVE?0:1; // XXX temp
+ data->state = BUTTON_STATE_INIT;
+
+ /* activate button */
+ but->flag |= UI_ACTIVE;
+ but->active= data;
+
+ /* we disable auto_open in the block after a threshold, because we still
+ * want to allow auto opening adjacent menus even if no button is activated
+ * inbetween going over to the other button, but only for a short while */
+ if(type == BUTTON_ACTIVATE_OVER && but->block->auto_open)
+ if(but->block->auto_open_last+BUTTON_AUTO_OPEN_THRESH < PIL_check_seconds_timer())
+ but->block->auto_open= 0;
+
+ button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
+
+ if(type == BUTTON_ACTIVATE_OPEN) {
+ button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+
+ /* activate first button in submenu */
+ if(data->menu && data->menu->region) {
+ ARegion *subar= data->menu->region;
+ uiBlock *subblock= subar->uiblocks.first;
+ uiBut *subbut;
+
+ if(subblock) {
+ subbut= ui_but_first(subblock);
+
+ if(subbut)
+ ui_handle_button_activate(C, subar, subbut, BUTTON_ACTIVATE);
+ }
+ }
+ }
+ else if(type == BUTTON_ACTIVATE_TEXT_EDITING)
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ else if(type == BUTTON_ACTIVATE_APPLY)
+ button_activate_state(C, but, BUTTON_STATE_WAIT_FLASH);
+}
+
+static void button_activate_exit(bContext *C, uiHandleButtonData *data, uiBut *but, int mousemove)
+{
+ uiBlock *block= but->block;
+
+ /* ensure we are in the exit state */
+ if(data->state != BUTTON_STATE_EXIT)
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+
+ /* apply the button action or value */
+ ui_apply_button(C, block, but, data, 0);
+
+ /* if this button is in a menu, this will set the button return
+ * value to the button value and the menu return value to ok, the
+ * menu return value will be picked up and the menu will close */
+ if(block->handle && !(block->flag & UI_BLOCK_KEEP_OPEN) && !data->cancel) {
+ uiPopupBlockHandle *menu;
+
+ menu= block->handle;
+ menu->butretval= data->retval;
+ menu->menuretval= UI_RETURN_OK;
+ }
+
+ /* disable tooltips until mousemove */
+ ui_blocks_set_tooltips(data->region, 0);
+
+ /* clean up */
+ if(data->str)
+ MEM_freeN(data->str);
+ if(data->origstr)
+ MEM_freeN(data->origstr);
+
+ /* redraw (data is but->active!) */
+ ED_region_tag_redraw(data->region);
+
+ /* clean up button */
+ MEM_freeN(but->active);
+ but->active= NULL;
+ but->flag &= ~(UI_ACTIVE|UI_SELECT);
+ ui_check_but(but);
+
+ /* adds empty mousemove in queue for re-init handler, in case mouse is
+ * still over a button. we cannot just check for this ourselfs because
+ * at this point the mouse may be over a button in another region */
+ if(mousemove)
+ WM_event_add_mousemove(C);
+}
+
+void ui_button_active_cancel(const bContext *C, uiBut *but)
+{
+ uiHandleButtonData *data;
+
+ /* this gets called when the button somehow disappears while it is still
+ * active, this is bad for user interaction, but we need to handle this
+ * case cleanly anyway in case it happens */
+ if(but->active) {
+ data= but->active;
+ data->cancel= 1;
+ button_activate_exit((bContext*)C, data, but, 0);
+ }
+}
+
+/************** handle activating a button *************/
+
+static int ui_handle_button_over(bContext *C, wmEvent *event, ARegion *ar)
+{
+ uiBut *but;
+
+ if(event->type == MOUSEMOVE) {
+ but= ui_but_find_mouse_over(ar, event->x, event->y);
+
+ if(but)
+ button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type)
+{
+ uiBut *oldbut;
+ uiHandleButtonData *data;
+
+ oldbut= ui_but_find_activated(ar);
+ if(oldbut) {
+ data= oldbut->active;
+ data->cancel= 1;
+ button_activate_exit(C, data, oldbut, 0);
+ }
+
+ button_activate_init(C, ar, but, type);
+}
+
+/************ handle events for an activated button ***********/
+
+static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
+{
+ uiHandleButtonData *data;
+ uiBlock *block;
+ ARegion *ar;
+ uiBut *postbut;
+ uiButtonActivateType posttype;
+ int retval;
+
+ data= but->active;
+ block= but->block;
+ ar= data->region;
+
+ retval= WM_UI_HANDLER_CONTINUE;
+
+ if(data->state == BUTTON_STATE_HIGHLIGHT) {
+ switch(event->type) {
+ case MOUSEMOVE:
+ /* verify if we are still over the button, if not exit */
+ if(!ui_mouse_inside_button(ar, but, event->x, event->y)) {
+ data->cancel= 1;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else if(event->x!=event->prevx || event->y!=event->prevy) {
+ /* re-enable tooltip on mouse move */
+ ui_blocks_set_tooltips(ar, 1);
+ button_tooltip_timer_reset(but);
+ }
+
+ break;
+ case TIMER: {
+ /* handle tooltip timer */
+ if(event->customdata == data->tooltiptimer) {
+ WM_event_remove_window_timer(data->window, data->tooltiptimer);
+ data->tooltiptimer= NULL;
+
+ if(!data->tooltip)
+ data->tooltip= ui_tooltip_create(C, data->region, but);
+ }
+ /* handle menu auto open timer */
+ else if(event->customdata == data->autoopentimer) {
+ WM_event_remove_window_timer(data->window, data->autoopentimer);
+ data->autoopentimer= NULL;
+
+ if(ui_mouse_inside_button(ar, but, event->x, event->y))
+ button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+ }
+
+ retval= WM_UI_HANDLER_CONTINUE;
+ break;
+ default:
+ /* handle button type specific events */
+ retval= ui_do_button(C, block, but, event);
+ }
+ }
+ }
+ else if(data->state == BUTTON_STATE_WAIT_RELEASE) {
+ switch(event->type) {
+ case MOUSEMOVE:
+ /* deselect the button when moving the mouse away */
+ if(ui_mouse_inside_button(ar, but, event->x, event->y)) {
+ if(!(but->flag & UI_SELECT)) {
+ but->flag |= UI_SELECT;
+ data->cancel= 0;
+ ED_region_tag_redraw(data->region);
+ }
+ }
+ else {
+ if(but->flag & UI_SELECT) {
+ but->flag &= ~UI_SELECT;
+ data->cancel= 1;
+ ED_region_tag_redraw(data->region);
+ }
+ }
+ break;
+ default:
+ /* otherwise catch mouse release event */
+ ui_do_button(C, block, but, event);
+ break;
+ }
+
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ else if(data->state == BUTTON_STATE_WAIT_FLASH) {
+ switch(event->type) {
+ case TIMER: {
+ if(event->customdata == data->flashtimer)
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+
+ retval= WM_UI_HANDLER_CONTINUE;
+ }
+ else if(data->state == BUTTON_STATE_MENU_OPEN) {
+ switch(event->type) {
+ case MOUSEMOVE: {
+ uiBut *bt= ui_but_find_mouse_over(ar, event->x, event->y);
+
+ if(bt && bt->active != data) {
+ data->cancel= 1;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ break;
+ }
+ }
+
+ ui_do_button(C, block, but, event);
+ retval= WM_UI_HANDLER_CONTINUE;
+ }
+ else {
+ ui_do_button(C, block, but, event);
+ retval= WM_UI_HANDLER_BREAK;
+ }
+
+ if(data->state == BUTTON_STATE_EXIT) {
+ postbut= data->postbut;
+ posttype= data->posttype;
+
+ button_activate_exit(C, data, but, (postbut == NULL));
+
+ /* for jumping to the next button with tab while text editing */
+ if(postbut)
+ button_activate_init(C, ar, postbut, posttype);
+ }
+
+ return retval;
+}
+
+static void ui_handle_button_closed_submenu(bContext *C, wmEvent *event, uiBut *but)
+{
+ uiHandleButtonData *data;
+ uiPopupBlockHandle *menu;
+
+ data= but->active;
+ menu= data->menu;
+
+ /* copy over return values from the closing menu */
+ if(menu->menuretval == UI_RETURN_OK) {
+ if(but->type == COL)
+ VECCOPY(data->vec, menu->retvec)
+ else if(ELEM3(but->type, MENU, ICONROW, ICONTEXTROW))
+ data->value= menu->retvalue;
+ }
+
+ /* now change button state or exit, which will close the submenu */
+ if(ELEM(menu->menuretval, UI_RETURN_OK, UI_RETURN_CANCEL)) {
+ if(menu->menuretval != UI_RETURN_OK)
+ data->cancel= 1;
+
+ button_activate_exit(C, data, but, 1);
+ }
+ else if(menu->menuretval == UI_RETURN_OUT) {
+ if(ui_mouse_inside_button(data->region, but, event->x, event->y)) {
+ button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
+ }
+ else {
+ data->cancel= 1;
+ button_activate_exit(C, data, but, 1);
+ }
+ }
+}
+
+/* ************************* menu handling *******************************/
+
+/* function used to prevent loosing the open menu when using nested pulldowns,
+ * when moving mouse towards the pulldown menu over other buttons that could
+ * steal the highlight from the current button, only checks:
+ *
+ * - while mouse moves in triangular area defined old mouse position and
+ * left/right side of new menu
+ * - only for 1 second
+ */
+
+static void ui_mouse_motion_towards_init(uiPopupBlockHandle *menu, int mx, int my, int force)
+{
+ if(!menu->dotowards || force) {
+ menu->dotowards= 1;
+ menu->towardsx= mx;
+ menu->towardsy= my;
+
+ if(force)
+ menu->towardstime= DBL_MAX; /* unlimited time */
+ else
+ menu->towardstime= PIL_check_seconds_timer();
+ }
+}
+
+static int ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *menu, int mx, int my)
+{
+ float p1[2], p2[2], p3[2], p4[2], oldp[2], newp[2];
+ int closer;
+
+ if(!menu->dotowards) return 0;
+ if((block->direction & UI_TOP) || (block->direction & UI_DOWN)) {
+ menu->dotowards= 0;
+ return menu->dotowards;
+ }
+
+ /* verify that we are moving towards one of the edges of the
+ * menu block, in other words, in the triangle formed by the
+ * initial mouse location and two edge points. */
+ p1[0]= block->minx-20;
+ p1[1]= block->miny-20;
+
+ p2[0]= block->maxx+20;
+ p2[1]= block->miny-20;
+
+ p3[0]= block->maxx+20;
+ p3[1]= block->maxy+20;
+
+ p4[0]= block->minx-20;
+ p4[1]= block->maxy+20;
+
+ oldp[0]= menu->towardsx;
+ oldp[1]= menu->towardsy;
+
+ newp[0]= mx;
+ newp[1]= my;
+
+ if(Vec2Lenf(oldp, newp) < 4.0f)
+ return menu->dotowards;
+
+ closer= 0;
+ closer |= IsectPT2Df(newp, oldp, p1, p2);
+ closer |= IsectPT2Df(newp, oldp, p2, p3);
+ closer |= IsectPT2Df(newp, oldp, p3, p4);
+ closer |= IsectPT2Df(newp, oldp, p4, p1);
+
+ if(!closer)
+ menu->dotowards= 0;
+
+ /* 1 second timer */
+ if(PIL_check_seconds_timer() - menu->towardstime > BUTTON_MOUSE_TOWARDS_THRESH)
+ menu->dotowards= 0;
+
+ return menu->dotowards;
+}
+
+int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu, int topmenu)
+{
+ ARegion *ar;
+ uiBlock *block;
+ uiBut *but, *bt;
+ int inside, act, count, mx, my, retval;
+
+ ar= menu->region;
+ block= ar->uiblocks.first;
+
+ act= 0;
+ retval= WM_UI_HANDLER_CONTINUE;
+
+ mx= event->x;
+ my= event->y;
+ ui_window_to_block(ar, block, &mx, &my);
+
+ /* check if mouse is inside block */
+ inside= 0;
+ if(block->minx <= mx && block->maxx >= mx)
+ if(block->miny <= my && block->maxy >= my)
+ inside= 1;
+
+ if((but=ui_but_find_activated(ar)) && button_modal_state(but->active->state)) {
+ /* if a button is activated modal, always reset the start mouse
+ * position of the towards mechanism to avoid loosing focus,
+ * and don't handle events */
+ ui_mouse_motion_towards_init(menu, mx, my, 1);
+ }
+ else if(event->type != TIMER) {
+ /* for ui_mouse_motion_towards_block */
+ if(event->type == MOUSEMOVE)
+ ui_mouse_motion_towards_init(menu, mx, my, 0);
+
+ switch(event->type) {
+ /* closing sublevels of pulldowns */
+ case LEFTARROWKEY:
+ if(event->val==KM_PRESS && (block->flag & UI_BLOCK_LOOP))
+ if(BLI_countlist(&block->saferct) > 0)
+ menu->menuretval= UI_RETURN_OUT;
+
+ retval= WM_UI_HANDLER_BREAK;
+ break;
+
+ /* opening sublevels of pulldowns */
+ case RIGHTARROWKEY:
+ if(event->val==KM_PRESS && (block->flag & UI_BLOCK_LOOP)) {
+ but= ui_but_find_activated(ar);
+
+ if(!but) {
+ /* no item active, we make first active */
+ if(block->direction & UI_TOP) but= ui_but_last(block);
+ else but= ui_but_first(block);
+ }
+
+ if(but && ELEM(but->type, BLOCK, HMENU))
+ ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_OPEN);
+ }
+
+ retval= WM_UI_HANDLER_BREAK;
+ break;
+
+ case UPARROWKEY:
+ case DOWNARROWKEY:
+ case WHEELUPMOUSE:
+ case WHEELDOWNMOUSE:
+ /* arrowkeys: only handle for block_loop blocks */
+ if(inside || (block->flag & UI_BLOCK_LOOP)) {
+ if(event->val==KM_PRESS) {
+ but= ui_but_find_activated(ar);
+ if(but) {
+ if(ELEM(event->type, DOWNARROWKEY, WHEELDOWNMOUSE)) {
+ if(block->direction & UI_TOP) but= ui_but_prev(but);
+ else but= ui_but_next(but);
+ }
+ else {
+ if(block->direction & UI_TOP) but= ui_but_next(but);
+ else but= ui_but_prev(but);
+ }
+
+ if(but)
+ ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE);
+ }
+
+ if(!but) {
+ if(ELEM(event->type, UPARROWKEY, WHEELUPMOUSE)) {
+ if(block->direction & UI_TOP) bt= ui_but_first(block);
+ else bt= ui_but_last(block);
+ }
+ else {
+ if(block->direction & UI_TOP) bt= ui_but_last(block);
+ else bt= ui_but_first(block);
+ }
+
+ if(bt)
+ ui_handle_button_activate(C, ar, bt, BUTTON_ACTIVATE);
+ }
+ }
+ }
+
+ retval= WM_UI_HANDLER_BREAK;
+ break;
+
+ case ONEKEY: case PAD1:
+ act= 1;
+ case TWOKEY: case PAD2:
+ if(act==0) act= 2;
+ case THREEKEY: case PAD3:
+ if(act==0) act= 3;
+ case FOURKEY: case PAD4:
+ if(act==0) act= 4;
+ case FIVEKEY: case PAD5:
+ if(act==0) act= 5;
+ case SIXKEY: case PAD6:
+ if(act==0) act= 6;
+ case SEVENKEY: case PAD7:
+ if(act==0) act= 7;
+ case EIGHTKEY: case PAD8:
+ if(act==0) act= 8;
+ case NINEKEY: case PAD9:
+ if(act==0) act= 9;
+ case ZEROKEY: case PAD0:
+ if(act==0) act= 10;
+
+ if(block->flag & UI_BLOCK_NUMSELECT) {
+ if(event->alt) act+= 10;
+
+ count= 0;
+ for(but= block->buttons.first; but; but= but->next) {
+ int doit= 0;
+
+ if(but->type!=LABEL && but->type!=SEPR)
+ count++;
+
+ /* exception for menus like layer buts, with button aligning they're not drawn in order */
+ if(but->type==TOGR) {
+ if(but->bitnr==act-1)
+ doit= 1;
+ }
+ else if(count==act)
+ doit=1;
+
+ if(doit) {
+ ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_APPLY);
+ break;
+ }
+ }
+ }
+
+ retval= WM_UI_HANDLER_BREAK;
+ break;
+ }
+
+ /* here we check return conditions for menus */
+ if(block->flag & UI_BLOCK_LOOP) {
+ /* if we click outside the block, verify if we clicked on the
+ * button that opened us, otherwise we need to close */
+ if(inside==0) {
+ uiSafetyRct *saferct= block->saferct.first;
+
+ if(ELEM3(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE) && event->val==KM_PRESS)
+ if(saferct && !BLI_in_rctf(&saferct->parent, event->x, event->y))
+ menu->menuretval= UI_RETURN_OK;
+ }
+
+ if(menu->menuretval);
+ else if(event->type==ESCKEY && event->val==KM_PRESS) {
+ /* esc cancels this and all preceding menus */
+ menu->menuretval= UI_RETURN_CANCEL;
+ }
+ else if(ELEM(event->type, RETKEY, PADENTER) && event->val==KM_PRESS) {
+ /* enter will always close this block, but we let the event
+ * get handled by the button if it is activated */
+ if(!ui_but_find_activated(ar))
+ menu->menuretval= UI_RETURN_OK;
+ }
+ else {
+ ui_mouse_motion_towards_check(block, menu, mx, my);
+
+ /* check mouse moving outside of the menu */
+ if(inside==0 && (block->flag & UI_BLOCK_MOVEMOUSE_QUIT)) {
+ uiSafetyRct *saferct;
+
+ /* check for all parent rects, enables arrowkeys to be used */
+ for(saferct=block->saferct.first; saferct; saferct= saferct->next) {
+ /* for mouse move we only check our own rect, for other
+ * events we check all preceding block rects too to make
+ * arrow keys navigation work */
+ if(event->type!=MOUSEMOVE || saferct==block->saferct.first) {
+ if(BLI_in_rctf(&saferct->parent, (float)event->x, (float)event->y))
+ break;
+ if(BLI_in_rctf(&saferct->safety, (float)event->x, (float)event->y))
+ break;
+ }
+ }
+
+ /* strict check, and include the parent rect */
+ if(!menu->dotowards && !saferct)
+ menu->menuretval= (block->flag & UI_BLOCK_KEEP_OPEN)? UI_RETURN_OK: UI_RETURN_OUT;
+ else if(menu->dotowards && event->type==MOUSEMOVE)
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
+ }
+
+ /* if we are didn't handle the event yet, lets pass it on to
+ * buttons inside this region. disabled inside check .. not sure
+ * anymore why it was there? but i meant enter enter didn't work
+ * for example when mouse was not over submenu */
+ if((/*inside &&*/ !menu->menuretval && retval == WM_UI_HANDLER_CONTINUE) || event->type == TIMER) {
+ but= ui_but_find_activated(ar);
+
+ if(but) {
+ ScrArea *ctx_area= CTX_wm_area(C);
+ ARegion *ctx_region= CTX_wm_region(C);
+
+ if(menu->ctx_area) CTX_wm_area_set(C, menu->ctx_area);
+ if(menu->ctx_region) CTX_wm_region_set(C, menu->ctx_region);
+
+ retval= ui_handle_button_event(C, event, but);
+
+ if(menu->ctx_area) CTX_wm_area_set(C, ctx_area);
+ if(menu->ctx_region) CTX_wm_region_set(C, ctx_region);
+ }
+ else
+ retval= ui_handle_button_over(C, event, ar);
+ }
+
+ /* if we set a menu return value, ensure we continue passing this on to
+ * lower menus and buttons, so always set continue then, and if we are
+ * inside the region otherwise, ensure we swallow the event */
+ if(menu->menuretval)
+ return WM_UI_HANDLER_CONTINUE;
+ else if(inside)
+ return WM_UI_HANDLER_BREAK;
+ else
+ return retval;
+}
+
+static int ui_handle_menu_closed_submenu(bContext *C, wmEvent *event, uiPopupBlockHandle *menu)
+{
+ ARegion *ar;
+ uiBut *but;
+ uiBlock *block;
+ uiHandleButtonData *data;
+ uiPopupBlockHandle *submenu;
+ int mx, my;
+
+ ar= menu->region;
+ block= ar->uiblocks.first;
+
+ but= ui_but_find_activated(ar);
+ data= but->active;
+ submenu= data->menu;
+
+ if(submenu->menuretval) {
+ /* first decide if we want to close our own menu cascading, if
+ * so pass on the sub menu return value to our own menu handle */
+ if(ELEM(submenu->menuretval, UI_RETURN_OK, UI_RETURN_CANCEL)) {
+ if(!(block->flag & UI_BLOCK_KEEP_OPEN)) {
+ menu->menuretval= submenu->menuretval;
+ menu->butretval= data->retval;
+ }
+ }
+
+ /* now let activated button in this menu exit, which
+ * will actually close the submenu too */
+ ui_handle_button_closed_submenu(C, event, but);
+ }
+
+ /* for cases where close does not cascade, allow the user to
+ * move the mouse back towards the menu without closing */
+ mx= event->x;
+ my= event->y;
+ ui_window_to_block(ar, block, &mx, &my);
+ ui_mouse_motion_towards_init(menu, mx, my, 1);
+
+ if(menu->menuretval)
+ return WM_UI_HANDLER_CONTINUE;
+ else
+ return WM_UI_HANDLER_BREAK;
+}
+
+static int ui_handle_menus_recursive(bContext *C, wmEvent *event, uiPopupBlockHandle *menu)
+{
+ uiBut *but;
+ uiHandleButtonData *data;
+ uiPopupBlockHandle *submenu;
+ int retval= WM_UI_HANDLER_CONTINUE;
+
+ /* check if we have a submenu, and handle events for it first */
+ but= ui_but_find_activated(menu->region);
+ data= (but)? but->active: NULL;
+ submenu= (data)? data->menu: NULL;
+
+ if(submenu)
+ retval= ui_handle_menus_recursive(C, event, submenu);
+
+ /* now handle events for our own menu */
+ if(retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) {
+ if(submenu && submenu->menuretval)
+ retval= ui_handle_menu_closed_submenu(C, event, menu);
+ else
+ retval= ui_handle_menu_event(C, event, menu, (submenu == NULL));
+ }
+
+ return retval;
+}
+
+/* *************** UI event handlers **************** */
+
+static int ui_handler_region(bContext *C, wmEvent *event, void *userdata)
+{
+ ARegion *ar;
+ uiBut *but;
+ int retval;
+
+ /* here we handle buttons at the region level, non-modal */
+ ar= CTX_wm_region(C);
+ retval= WM_UI_HANDLER_CONTINUE;
+
+ if(ar==NULL) return retval;
+ if(ar->uiblocks.first==NULL) return retval;
+
+ /* either handle events for already activated button or try to activate */
+ but= ui_but_find_activated(ar);
+
+ if(!but || !button_modal_state(but->active->state))
+ retval= ui_handler_panel_region(C, event);
+
+ if(retval == WM_UI_HANDLER_CONTINUE) {
+ if(but)
+ retval= ui_handle_button_event(C, event, but);
+ else
+ retval= ui_handle_button_over(C, event, ar);
+ }
+
+ /* re-enable tooltips */
+ if(event->type == MOUSEMOVE && (event->x!=event->prevx || event->y!=event->prevy))
+ ui_blocks_set_tooltips(ar, 1);
+
+ /* delayed apply callbacks */
+ ui_apply_but_funcs_after(C);
+
+ return retval;
+}
+
+static void ui_handler_remove_region(bContext *C, void *userdata)
+{
+ bScreen *sc;
+ ARegion *ar;
+
+ ar= CTX_wm_region(C);
+ if(ar == NULL) return;
+
+ uiFreeBlocks(C, &ar->uiblocks);
+
+ sc= CTX_wm_screen(C);
+ if(sc == NULL) return;
+
+ /* delayed apply callbacks, but not for screen level regions, those
+ * we rather do at the very end after closing them all, which will
+ * be done in ui_handler_region/window */
+ if(BLI_findindex(&sc->regionbase, ar) == -1)
+ ui_apply_but_funcs_after(C);
+}
+
+static int ui_handler_region_menu(bContext *C, wmEvent *event, void *userdata)
+{
+ ARegion *ar;
+ uiBut *but;
+ uiHandleButtonData *data;
+ int retval;
+
+ /* here we handle buttons at the window level, modal, for example
+ * while number sliding, text editing, or when a menu block is open */
+ ar= CTX_wm_menu(C);
+ if(!ar)
+ ar= CTX_wm_region(C);
+
+ but= ui_but_find_activated(ar);
+
+ if(but) {
+ /* handle activated button events */
+ data= but->active;
+
+ if(data->state == BUTTON_STATE_MENU_OPEN) {
+ /* handle events for menus and their buttons recursively,
+ * this will handle events from the top to the bottom menu */
+ retval= ui_handle_menus_recursive(C, event, data->menu);
+
+ /* handle events for the activated button */
+ if(retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) {
+ if(data->menu->menuretval)
+ ui_handle_button_closed_submenu(C, event, but);
+ else
+ ui_handle_button_event(C, event, but);
+ }
+ }
+ else {
+ /* handle events for the activated button */
+ ui_handle_button_event(C, event, but);
+ }
+ }
+
+ /* re-enable tooltips */
+ if(event->type == MOUSEMOVE && (event->x!=event->prevx || event->y!=event->prevy))
+ ui_blocks_set_tooltips(ar, 1);
+
+ /* delayed apply callbacks */
+ ui_apply_but_funcs_after(C);
+
+ /* we block all events, this is modal interaction */
+ return WM_UI_HANDLER_BREAK;
+}
+
+/* two types of popups, one with operator + enum, other with regular callbacks */
+static int ui_handler_popup(bContext *C, wmEvent *event, void *userdata)
+{
+ uiPopupBlockHandle *menu= userdata;
+
+ ui_handle_menus_recursive(C, event, menu);
+
+ /* free if done, does not free handle itself */
+ if(menu->menuretval) {
+ /* copy values, we have to free first (closes region) */
+ uiPopupBlockHandle temp= *menu;
+
+ ui_popup_block_free(C, menu);
+ WM_event_remove_ui_handler(&CTX_wm_window(C)->handlers, ui_handler_popup, ui_handler_remove_popup, menu);
+
+ if(temp.menuretval == UI_RETURN_OK) {
+ if(temp.popup_func)
+ temp.popup_func(C, temp.popup_arg, temp.retvalue);
+ if(temp.opname)
+ WM_operator_name_call(C, temp.opname, temp.opcontext, NULL);
+ }
+ else if(temp.cancel_func)
+ temp.cancel_func(temp.popup_arg);
+ }
+ else {
+ /* re-enable tooltips */
+ if(event->type == MOUSEMOVE && (event->x!=event->prevx || event->y!=event->prevy))
+ ui_blocks_set_tooltips(menu->region, 1);
+ }
+
+ /* delayed apply callbacks */
+ ui_apply_but_funcs_after(C);
+
+ /* we block all events, this is modal interaction */
+ return WM_UI_HANDLER_BREAK;
+}
+
+static void ui_handler_remove_popup(bContext *C, void *userdata)
+{
+ uiPopupBlockHandle *menu= userdata;
+
+ /* free menu block if window is closed for some reason */
+ ui_popup_block_free(C, menu);
+
+ /* delayed apply callbacks */
+ ui_apply_but_funcs_after(C);
+}
+
+void UI_add_region_handlers(ListBase *handlers)
+{
+ WM_event_remove_ui_handler(handlers, ui_handler_region, ui_handler_remove_region, NULL);
+ WM_event_add_ui_handler(NULL, handlers, ui_handler_region, ui_handler_remove_region, NULL);
+}
+
+void UI_add_popup_handlers(bContext *C, ListBase *handlers, uiPopupBlockHandle *menu)
+{
+ WM_event_add_ui_handler(C, handlers, ui_handler_popup, ui_handler_remove_popup, menu);
+}
+
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
new file mode 100644
index 00000000000..0c97c1fd008
--- /dev/null
+++ b/source/blender/editors/interface/interface_icons.c
@@ -0,0 +1,977 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributors: Blender Foundation, full recode
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include <direct.h>
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_storage_types.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+
+
+#include "BKE_utildefines.h"
+#include "BKE_image.h"
+#include "BKE_icons.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+
+// XXX #include "BIF_previewrender.h"
+// XXX #include "BIF_screen.h"
+
+#include "UI_resources.h" /* elubie: should be removed once the enum for the ICONS is in BIF_preview_icons.h */
+#include "interface_intern.h"
+#include "ED_datafiles.h"
+
+#define ICON_IMAGE_W 600
+#define ICON_IMAGE_H 512
+
+#define ICON_GRID_COLS 26
+#define ICON_GRID_ROWS 24
+
+#define ICON_GRID_MARGIN 5
+#define ICON_GRID_W 16
+#define ICON_GRID_H 16
+
+typedef struct IconImage {
+ int w;
+ int h;
+ unsigned int *rect;
+} IconImage;
+
+typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
+
+typedef struct DrawInfo {
+ int w;
+ int h;
+ float aspect;
+ VectorDrawFunc drawFunc; /* If drawFunc is defined then it is a vector icon, otherwise use rect */
+ IconImage* icon;
+} DrawInfo;
+
+/* ******************* STATIC LOCAL VARS ******************* */
+/* static here to cache results of icon directory scan, so it's not
+ * scanning the filesystem each time the menu is drawn */
+static struct ListBase iconfilelist = {0, 0};
+
+
+/* **************************************************** */
+
+static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int size)
+{
+ Icon *new_icon = NULL;
+ IconImage *iimg = NULL;
+ DrawInfo *di;
+ int y = 0;
+ int imgsize = 0;
+
+ new_icon = MEM_callocN(sizeof(Icon), "texicon");
+
+ new_icon->obj = 0; /* icon is not for library object */
+ new_icon->type = 0;
+
+ di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
+ di->drawFunc = 0;
+ di->w = size;
+ di->h = size;
+ di->aspect = 1.0f;
+
+ iimg = MEM_mallocN(sizeof(IconImage), "icon_img");
+ iimg->rect = MEM_mallocN(size*size*sizeof(unsigned int), "icon_rect");
+ iimg->w = size;
+ iimg->h = size;
+
+ /* Here we store the rect in the icon - same as before */
+ imgsize = bbuf->x;
+ for (y=0; y<size; y++) {
+ memcpy(&iimg->rect[y*size], &bbuf->rect[(y+yofs)*imgsize+xofs], size*sizeof(int));
+ }
+
+ di->icon = iimg;
+
+ new_icon->drawinfo_free = UI_icons_free_drawinfo;
+ new_icon->drawinfo = di;
+
+ BKE_icon_set(icon_id, new_icon);
+}
+
+static void def_internal_vicon( int icon_id, VectorDrawFunc drawFunc)
+{
+ Icon *new_icon = NULL;
+ DrawInfo* di;
+
+ new_icon = MEM_callocN(sizeof(Icon), "texicon");
+
+ new_icon->obj = 0; /* icon is not for library object */
+ new_icon->type = 0;
+
+ di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
+ di->drawFunc =drawFunc;
+ di->w = ICON_DEFAULT_HEIGHT;
+ di->h = ICON_DEFAULT_HEIGHT;
+ di->aspect = 1.0f;
+ di->icon = NULL;
+
+ new_icon->drawinfo_free = 0;
+ new_icon->drawinfo = di;
+
+ BKE_icon_set(icon_id, new_icon);
+}
+
+/* Vector Icon Drawing Routines */
+
+ /* Utilities */
+
+static void viconutil_set_point(GLint pt[2], int x, int y)
+{
+ pt[0] = x;
+ pt[1] = y;
+}
+
+static void viconutil_draw_tri(GLint (*pts)[2])
+{
+ glBegin(GL_TRIANGLES);
+ glVertex2iv(pts[0]);
+ glVertex2iv(pts[1]);
+ glVertex2iv(pts[2]);
+ glEnd();
+}
+
+static void viconutil_draw_lineloop(GLint (*pts)[2], int numPoints)
+{
+ int i;
+
+ glBegin(GL_LINE_LOOP);
+ for (i=0; i<numPoints; i++) {
+ glVertex2iv(pts[i]);
+ }
+ glEnd();
+}
+
+static void viconutil_draw_lineloop_smooth(GLint (*pts)[2], int numPoints)
+{
+ glEnable(GL_LINE_SMOOTH);
+ viconutil_draw_lineloop(pts, numPoints);
+ glDisable(GL_LINE_SMOOTH);
+}
+
+static void viconutil_draw_points(GLint (*pts)[2], int numPoints, int pointSize)
+{
+ int i;
+
+ glBegin(GL_QUADS);
+ for (i=0; i<numPoints; i++) {
+ int x = pts[i][0], y = pts[i][1];
+
+ glVertex2i(x-pointSize,y-pointSize);
+ glVertex2i(x+pointSize,y-pointSize);
+ glVertex2i(x+pointSize,y+pointSize);
+ glVertex2i(x-pointSize,y+pointSize);
+ }
+ glEnd();
+}
+
+ /* Drawing functions */
+
+static void vicon_x_draw(int x, int y, int w, int h, float alpha)
+{
+ x += 3;
+ y += 3;
+ w -= 6;
+ h -= 6;
+
+ glEnable( GL_LINE_SMOOTH );
+
+ glLineWidth(2.5);
+
+ glColor4f(0.0, 0.0, 0.0, alpha);
+ glBegin(GL_LINES);
+ glVertex2i(x ,y );
+ glVertex2i(x+w,y+h);
+ glVertex2i(x+w,y );
+ glVertex2i(x ,y+h);
+ glEnd();
+
+ glLineWidth(1.0);
+
+ glDisable( GL_LINE_SMOOTH );
+}
+
+static void vicon_view3d_draw(int x, int y, int w, int h, float alpha)
+{
+ int cx = x + w/2;
+ int cy = y + h/2;
+ int d = MAX2(2, h/3);
+
+ glColor4f(0.5, 0.5, 0.5, alpha);
+ glBegin(GL_LINES);
+ glVertex2i(x , cy-d);
+ glVertex2i(x+w, cy-d);
+ glVertex2i(x , cy+d);
+ glVertex2i(x+w, cy+d);
+
+ glVertex2i(cx-d, y );
+ glVertex2i(cx-d, y+h);
+ glVertex2i(cx+d, y );
+ glVertex2i(cx+d, y+h);
+ glEnd();
+
+ glColor4f(0.0, 0.0, 0.0, alpha);
+ glBegin(GL_LINES);
+ glVertex2i(x , cy);
+ glVertex2i(x+w, cy);
+ glVertex2i(cx, y );
+ glVertex2i(cx, y+h);
+ glEnd();
+}
+
+static void vicon_edit_draw(int x, int y, int w, int h, float alpha)
+{
+ GLint pts[4][2];
+
+ viconutil_set_point(pts[0], x+3 , y+3 );
+ viconutil_set_point(pts[1], x+w-3, y+3 );
+ viconutil_set_point(pts[2], x+w-3, y+h-3);
+ viconutil_set_point(pts[3], x+3 , y+h-3);
+
+ glColor4f(0.0, 0.0, 0.0, alpha);
+ viconutil_draw_lineloop(pts, 4);
+
+ glColor3f(1, 1, 0.0);
+ viconutil_draw_points(pts, 4, 1);
+}
+
+static void vicon_editmode_hlt_draw(int x, int y, int w, int h, float alpha)
+{
+ GLint pts[3][2];
+
+ viconutil_set_point(pts[0], x+w/2, y+h-2);
+ viconutil_set_point(pts[1], x+3, y+4);
+ viconutil_set_point(pts[2], x+w-3, y+4);
+
+ glColor4f(0.5, 0.5, 0.5, alpha);
+ viconutil_draw_tri(pts);
+
+ glColor4f(0.0, 0.0, 0.0, 1);
+ viconutil_draw_lineloop_smooth(pts, 3);
+
+ glColor3f(1, 1, 0.0);
+ viconutil_draw_points(pts, 3, 1);
+}
+
+static void vicon_editmode_dehlt_draw(int x, int y, int w, int h, float alpha)
+{
+ GLint pts[3][2];
+
+ viconutil_set_point(pts[0], x+w/2, y+h-2);
+ viconutil_set_point(pts[1], x+3, y+4);
+ viconutil_set_point(pts[2], x+w-3, y+4);
+
+ glColor4f(0.0f, 0.0f, 0.0f, 1);
+ viconutil_draw_lineloop_smooth(pts, 3);
+
+ glColor3f(.9f, .9f, .9f);
+ viconutil_draw_points(pts, 3, 1);
+}
+
+static void vicon_disclosure_tri_right_draw(int x, int y, int w, int h, float alpha)
+{
+ GLint pts[3][2];
+ int cx = x+w/2;
+ int cy = y+w/2;
+ int d = w/3, d2 = w/5;
+
+ viconutil_set_point(pts[0], cx-d2, cy+d);
+ viconutil_set_point(pts[1], cx-d2, cy-d);
+ viconutil_set_point(pts[2], cx+d2, cy);
+
+ glShadeModel(GL_SMOOTH);
+ glBegin(GL_TRIANGLES);
+ glColor4f(0.8f, 0.8f, 0.8f, alpha);
+ glVertex2iv(pts[0]);
+ glVertex2iv(pts[1]);
+ glColor4f(0.3f, 0.3f, 0.3f, alpha);
+ glVertex2iv(pts[2]);
+ glEnd();
+ glShadeModel(GL_FLAT);
+
+ glColor4f(0.0f, 0.0f, 0.0f, 1);
+ viconutil_draw_lineloop_smooth(pts, 3);
+}
+
+static void vicon_disclosure_tri_down_draw(int x, int y, int w, int h, float alpha)
+{
+ GLint pts[3][2];
+ int cx = x+w/2;
+ int cy = y+w/2;
+ int d = w/3, d2 = w/5;
+
+ viconutil_set_point(pts[0], cx+d, cy+d2);
+ viconutil_set_point(pts[1], cx-d, cy+d2);
+ viconutil_set_point(pts[2], cx, cy-d2);
+
+ glShadeModel(GL_SMOOTH);
+ glBegin(GL_TRIANGLES);
+ glColor4f(0.8f, 0.8f, 0.8f, alpha);
+ glVertex2iv(pts[0]);
+ glVertex2iv(pts[1]);
+ glColor4f(0.3f, 0.3f, 0.3f, alpha);
+ glVertex2iv(pts[2]);
+ glEnd();
+ glShadeModel(GL_FLAT);
+
+ glColor4f(0.0f, 0.0f, 0.0f, 1);
+ viconutil_draw_lineloop_smooth(pts, 3);
+}
+
+static void vicon_move_up_draw(int x, int y, int w, int h, float alpha)
+{
+ int d=-2;
+
+ glEnable(GL_LINE_SMOOTH);
+ glLineWidth(1);
+ glColor3f(0.0, 0.0, 0.0);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2i(x+w/2-d*2, y+h/2+d);
+ glVertex2i(x+w/2, y+h/2-d + 1);
+ glVertex2i(x+w/2+d*2, y+h/2+d);
+ glEnd();
+
+ glLineWidth(1.0);
+ glDisable(GL_LINE_SMOOTH);
+}
+
+static void vicon_move_down_draw(int x, int y, int w, int h, float alpha)
+{
+ int d=2;
+
+ glEnable(GL_LINE_SMOOTH);
+ glLineWidth(1);
+ glColor3f(0.0, 0.0, 0.0);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2i(x+w/2-d*2, y+h/2+d);
+ glVertex2i(x+w/2, y+h/2-d - 1);
+ glVertex2i(x+w/2+d*2, y+h/2+d);
+ glEnd();
+
+ glLineWidth(1.0);
+ glDisable(GL_LINE_SMOOTH);
+}
+
+static void init_internal_icons()
+{
+ bTheme *btheme= U.themes.first;
+ ImBuf *bbuf= NULL;
+ int x, y;
+ char iconfilestr[FILE_MAXDIR+FILE_MAXFILE];
+ char filenamestr[FILE_MAXFILE+16]; // 16 == strlen(".blender/icons/")+1
+
+ if ((btheme!=NULL) && (strlen(btheme->tui.iconfile) > 0)) {
+
+#ifdef WIN32
+ sprintf(filenamestr, "icons/%s", btheme->tui.iconfile);
+#else
+ sprintf(filenamestr, ".blender/icons/%s", btheme->tui.iconfile);
+#endif
+
+ BLI_make_file_string("/", iconfilestr, BLI_gethome(), filenamestr);
+
+ if (BLI_exists(iconfilestr)) {
+ bbuf = IMB_loadiffname(iconfilestr, IB_rect);
+ if(bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H) {
+ printf("\n***WARNING***\nIcons file %s too small.\nUsing built-in Icons instead\n", iconfilestr);
+ IMB_freeImBuf(bbuf);
+ bbuf= NULL;
+ }
+ }
+ }
+ if(bbuf==NULL)
+ bbuf = IMB_ibImageFromMemory((int *)datatoc_blenderbuttons, datatoc_blenderbuttons_size, IB_rect);
+
+ for (y=0; y<ICON_GRID_ROWS; y++) {
+ for (x=0; x<ICON_GRID_COLS; x++) {
+ def_internal_icon(bbuf, BIFICONID_FIRST + y*ICON_GRID_COLS + x,
+ x*(ICON_GRID_W+ICON_GRID_MARGIN)+ICON_GRID_MARGIN,
+ y*(ICON_GRID_H+ICON_GRID_MARGIN)+ICON_GRID_MARGIN, ICON_GRID_W);
+ }
+ }
+
+ def_internal_vicon(VICON_VIEW3D, vicon_view3d_draw);
+ def_internal_vicon(VICON_EDIT, vicon_edit_draw);
+ def_internal_vicon(VICON_EDITMODE_DEHLT, vicon_editmode_dehlt_draw);
+ def_internal_vicon(VICON_EDITMODE_HLT, vicon_editmode_hlt_draw);
+ def_internal_vicon(VICON_DISCLOSURE_TRI_RIGHT, vicon_disclosure_tri_right_draw);
+ def_internal_vicon(VICON_DISCLOSURE_TRI_DOWN, vicon_disclosure_tri_down_draw);
+ def_internal_vicon(VICON_MOVE_UP, vicon_move_up_draw);
+ def_internal_vicon(VICON_MOVE_DOWN, vicon_move_down_draw);
+ def_internal_vicon(VICON_X, vicon_x_draw);
+
+ IMB_freeImBuf(bbuf);
+}
+
+
+static void init_iconfile_list(struct ListBase *list)
+{
+ IconFile *ifile;
+ ImBuf *bbuf= NULL;
+ struct direntry *dir;
+ int restoredir = 1; /* restore to current directory */
+ int totfile, i, index=1;
+ int ifilex, ifiley;
+ char icondirstr[FILE_MAX];
+ char iconfilestr[FILE_MAX+16]; /* allow 256 chars for file+dir */
+ char olddir[FILE_MAX];
+
+ list->first = list->last = NULL;
+
+#ifdef WIN32
+ BLI_make_file_string("/", icondirstr, BLI_gethome(), "icons");
+#else
+ BLI_make_file_string("/", icondirstr, BLI_gethome(), ".blender/icons");
+#endif
+
+ if(BLI_exists(icondirstr)==0)
+ return;
+
+ /* since BLI_getdir changes the current working directory, restore it
+ back to old value afterwards */
+ if(!BLI_getwdN(olddir))
+ restoredir = 0;
+ totfile = BLI_getdir(icondirstr, &dir);
+ if (restoredir)
+ chdir(olddir);
+
+ for(i=0; i<totfile; i++) {
+ if( (dir[i].type & S_IFREG) ) {
+ char *filename = dir[i].relname;
+
+ if(BLI_testextensie(filename, ".png")) {
+
+ /* check to see if the image is the right size, continue if not */
+ /* copying strings here should go ok, assuming that we never get back
+ a complete path to file longer than 256 chars */
+ sprintf(iconfilestr, "%s/%s", icondirstr, filename);
+ if(BLI_exists(iconfilestr)) bbuf = IMB_loadiffname(iconfilestr, IB_rect);
+
+ ifilex = bbuf->x;
+ ifiley = bbuf->y;
+ IMB_freeImBuf(bbuf);
+
+ if ((ifilex != ICON_IMAGE_W) || (ifiley != ICON_IMAGE_H))
+ continue;
+
+ /* found a potential icon file, so make an entry for it in the cache list */
+ ifile = MEM_callocN(sizeof(IconFile), "IconFile");
+
+ BLI_strncpy(ifile->filename, filename, sizeof(ifile->filename));
+ ifile->index = index;
+
+ BLI_addtail(list, ifile);
+
+ index++;
+ }
+ }
+ }
+
+ /* free temporary direntry structure that's been created by BLI_getdir() */
+ i= totfile-1;
+
+ for(; i>=0; i--){
+ MEM_freeN(dir[i].relname);
+ if (dir[i].string) MEM_freeN(dir[i].string);
+ }
+ free(dir);
+ dir= 0;
+}
+
+static void free_iconfile_list(struct ListBase *list)
+{
+ IconFile *ifile=NULL, *next_ifile=NULL;
+
+ for(ifile=list->first; ifile; ifile=next_ifile) {
+ next_ifile = ifile->next;
+ BLI_freelinkN(list, ifile);
+ }
+}
+
+int UI_iconfile_get_index(char *filename)
+{
+ IconFile *ifile;
+ ListBase *list=&(iconfilelist);
+
+ for(ifile=list->first; ifile; ifile=ifile->next) {
+ if ( BLI_streq(filename, ifile->filename)) {
+ return ifile->index;
+ }
+ }
+
+ return 0;
+}
+
+ListBase *UI_iconfile_list(void)
+{
+ ListBase *list=&(iconfilelist);
+
+ return list;
+}
+
+
+void UI_icons_free()
+{
+ free_iconfile_list(&iconfilelist);
+ BKE_icons_free();
+}
+
+void UI_icons_free_drawinfo(void *drawinfo)
+{
+ DrawInfo *di = drawinfo;
+
+ if (di)
+ {
+ if (di->icon) {
+ MEM_freeN(di->icon->rect);
+ MEM_freeN(di->icon);
+ }
+ MEM_freeN(di);
+ }
+}
+
+static DrawInfo *icon_create_drawinfo()
+{
+ DrawInfo *di = NULL;
+
+ di = MEM_callocN(sizeof(DrawInfo), "di_icon");
+
+ di->drawFunc = 0;
+ di->w = ICON_DEFAULT_HEIGHT;
+ di->h = ICON_DEFAULT_HEIGHT;
+ di->icon = NULL;
+ di->aspect = 1.0f;
+
+ return di;
+}
+
+int UI_icon_get_width(int icon_id)
+{
+ Icon *icon = NULL;
+ DrawInfo *di = NULL;
+
+ icon = BKE_icon_get(icon_id);
+
+ if (!icon) {
+ printf("UI_icon_get_width: Internal error, no icon for icon ID: %d\n", icon_id);
+ return 0;
+ }
+
+ di = (DrawInfo *)icon->drawinfo;
+ if (!di) {
+ di = icon_create_drawinfo();
+ icon->drawinfo = di;
+ }
+
+ if (di)
+ return di->w;
+
+ return 0;
+}
+
+int UI_icon_get_height(int icon_id)
+{
+ Icon *icon = NULL;
+ DrawInfo *di = NULL;
+
+ icon = BKE_icon_get(icon_id);
+
+ if (!icon) {
+ printf("UI_icon_get_height: Internal error, no icon for icon ID: %d\n", icon_id);
+ return 0;
+ }
+
+ di = (DrawInfo*)icon->drawinfo;
+
+ if (!di) {
+ di = icon_create_drawinfo();
+ icon->drawinfo = di;
+ }
+
+ if (di)
+ return di->h;
+
+ return 0;
+}
+
+void UI_icons_init(int first_dyn_id)
+{
+ init_iconfile_list(&iconfilelist);
+ BKE_icons_init(first_dyn_id);
+ init_internal_icons();
+}
+
+#if 0
+static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned int *rect)
+{
+ struct ImBuf *ima;
+ unsigned int *drect, *srect;
+ float scaledx, scaledy;
+ short ex, ey, dx, dy;
+
+ /* paranoia test */
+ if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL))
+ return;
+
+ /* waste of cpu cyles... but the imbuf API has no other way to scale fast (ton) */
+ ima = IMB_dupImBuf(ibuf);
+
+ if (!ima)
+ return;
+
+ if (ima->x > ima->y) {
+ scaledx = (float)w;
+ scaledy = ( (float)ima->y/(float)ima->x )*(float)w;
+ }
+ else {
+ scaledx = ( (float)ima->x/(float)ima->y )*(float)h;
+ scaledy = (float)h;
+ }
+
+ ex = (short)scaledx;
+ ey = (short)scaledy;
+
+ dx = (w - ex) / 2;
+ dy = (h - ey) / 2;
+
+ IMB_scalefastImBuf(ima, ex, ey);
+
+ /* if needed, convert to 32 bits */
+ if(ima->rect==NULL)
+ IMB_rect_from_float(ima);
+
+ srect = ima->rect;
+ drect = rect;
+
+ drect+= dy*w+dx;
+ for (;ey > 0; ey--){
+ memcpy(drect,srect, ex * sizeof(int));
+ drect += w;
+ srect += ima->x;
+ }
+ IMB_freeImBuf(ima);
+}
+
+/* Render size for preview images at level miplevel */
+static int preview_render_size(int miplevel)
+{
+ switch (miplevel) {
+ case 0: return 32;
+ case 1: return PREVIEW_DEFAULT_HEIGHT;
+ }
+ return 0;
+}
+
+static void icon_create_mipmap(struct PreviewImage* prv_img, int miplevel)
+{
+ unsigned int size = preview_render_size(miplevel);
+
+ if (!prv_img) {
+ printf("Error: requested preview image does not exist");
+ }
+ if (!prv_img->rect[miplevel]) {
+ prv_img->w[miplevel] = size;
+ prv_img->h[miplevel] = size;
+ prv_img->changed[miplevel] = 1;
+ prv_img->rect[miplevel] = MEM_callocN(size*size*sizeof(unsigned int), "prv_rect");
+ }
+}
+
+/* create single icon from jpg, png etc. */
+static void icon_from_image(Image *img, int miplevel)
+{
+ unsigned int pr_size;
+ short image_loaded = 0;
+ struct ImBuf* ibuf=NULL;
+ PreviewImage* pi;
+
+ /* img->ok is zero when Image cannot load */
+ if (img==NULL || img->ok==0)
+ return;
+
+ /* elubie: this needs to be changed: here image is always loaded if not
+ already there. Very expensive for large images. Need to find a way to
+ only get existing ibuf */
+ ibuf = BKE_image_get_ibuf(img, NULL);
+ if(ibuf==NULL || ibuf->rect==NULL) {
+ return;
+ }
+
+ pi = BKE_previewimg_get((ID*)img);
+
+ if(!pi) {
+ printf("preview image could'nt be allocated");
+ return;
+ }
+ /* we can only create the preview rect here, since loading possibly deallocated
+ old preview */
+ icon_create_mipmap(pi, miplevel);
+
+ pr_size = img->preview->w[miplevel]*img->preview->h[miplevel]*sizeof(unsigned int);
+
+ image_loaded = 1;
+ icon_copy_rect(ibuf, img->preview->w[miplevel], img->preview->h[miplevel], img->preview->rect[miplevel]);
+}
+
+static void set_alpha(char* cp, int sizex, int sizey, char alpha)
+{
+ int x,y;
+ for(y=0; y<sizey; y++) {
+ for(x=0; x<sizex; x++, cp+=4) {
+ cp[3]= alpha;
+ }
+ }
+}
+#endif
+
+/* only called when icon has changed */
+/* only call with valid pointer from UI_icon_draw */
+static void icon_set_image(ID *id, DrawInfo *di, PreviewImage* prv_img, int miplevel)
+{
+#if 0 // XXX - preview renders have to be redesigned - possibly low level op (elubie)
+ RenderInfo ri;
+ unsigned int pr_size = 0;
+
+ if (!di) return;
+
+ if (!prv_img) {
+ printf("No preview image for this ID: %s\n", id->name);
+ return;
+ }
+
+ /* no drawing (see last parameter doDraw, just calculate preview image
+ - hopefully small enough to be fast */
+ if (GS(id->name) == ID_IM)
+ icon_from_image((struct Image*)id, miplevel);
+ else {
+ /* create the preview rect */
+ icon_create_mipmap(prv_img, miplevel);
+
+ ri.curtile= 0;
+ ri.tottile= 0;
+ ri.rect = NULL;
+ ri.pr_rectx = prv_img->w[miplevel];
+ ri.pr_recty = prv_img->h[miplevel];
+
+ pr_size = ri.pr_rectx*ri.pr_recty*sizeof(unsigned int);
+
+ BIF_previewrender(id, &ri, NULL, PR_ICON_RENDER);
+
+ /* world is rendered with alpha=0, so it wasn't displayed
+ this could be render option for sky to, for later */
+ if (GS(id->name) == ID_WO) {
+ set_alpha( (char*) ri.rect, ri.pr_rectx, ri.pr_recty, 255);
+ }
+ else if (GS(id->name) == ID_MA) {
+ Material* mat = (Material*)id;
+ if (mat->mode & MA_HALO) {
+ set_alpha( (char*) ri.rect, ri.pr_rectx, ri.pr_recty, 255);
+ }
+ }
+
+ if (ri.rect) {
+ memcpy(prv_img->rect[miplevel], ri.rect, pr_size);
+
+ /* and clean up */
+ MEM_freeN(ri.rect);
+ ri.rect = 0;
+ }
+ }
+#endif
+}
+
+static void icon_draw_rect(float x, float y, int w, int h, float aspect, int rw, int rh, unsigned int *rect)
+{
+
+ glRasterPos2f(x, y);
+ // XXX ui_rasterpos_safe(x, y, aspect);
+
+ if((w<1 || h<1)) {
+ // XXX - TODO 2.5 verify whether this case can happen
+ // and only print in debug
+ printf("what the heck! - icons are %i x %i pixels?\n", w, h);
+ }
+ /* rect contains image in 'rendersize', we only scale if needed */
+ else if(rw!=w && rh!=h) {
+ ImBuf *ima;
+ if(w>2000 || h>2000) { /* something has gone wrong! */
+ printf("insane icon size w=%d h=%d\n",w,h);
+ return;
+ }
+ /* first allocate imbuf for scaling and copy preview into it */
+ ima = IMB_allocImBuf(rw, rh, 32, IB_rect, 0);
+ memcpy(ima->rect, rect, rw*rh*sizeof(unsigned int));
+
+ /* scale it */
+ IMB_scaleImBuf(ima, w, h);
+ glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, ima->rect);
+
+ IMB_freeImBuf(ima);
+ }
+ else
+ glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+}
+
+/* Drawing size for preview images at level miplevel */
+static int preview_size(int miplevel)
+{
+ switch (miplevel) {
+ case 0: return ICON_DEFAULT_HEIGHT;
+ case 1: return PREVIEW_DEFAULT_HEIGHT;
+ }
+ return 0;
+}
+
+static void icon_draw_size(float x, float y, int icon_id, float aspect, int miplevel, int draw_size, int nocreate)
+{
+ Icon *icon = NULL;
+ DrawInfo *di = NULL;
+
+ icon = BKE_icon_get(icon_id);
+
+ if (!icon) {
+ printf("icon_draw_mipmap: Internal error, no icon for icon ID: %d\n", icon_id);
+ return;
+ }
+
+ di = (DrawInfo*)icon->drawinfo;
+
+ if (!di) {
+ di = icon_create_drawinfo();
+
+ icon->drawinfo = di;
+ icon->drawinfo_free = UI_icons_free_drawinfo;
+ }
+
+ di->aspect = aspect;
+ /* scale width and height according to aspect */
+ di->w = (int)(draw_size/di->aspect + 0.5f);
+ di->h = (int)(draw_size/di->aspect + 0.5f);
+
+ if (di->drawFunc) {
+ /* vector icons use the uiBlock transformation, they are not drawn
+ with untransformed coordinates like the other icons */
+ di->drawFunc(x, y, ICON_DEFAULT_HEIGHT, ICON_DEFAULT_HEIGHT, 1.0f);
+ }
+ else if (di->icon) {
+ /* it is a builtin icon */
+ if (!di->icon->rect) return; /* something has gone wrong! */
+
+ icon_draw_rect(x,y,di->w, di->h, di->aspect, di->icon->w, di->icon->h, di->icon->rect);
+ }
+ else {
+ PreviewImage* pi = BKE_previewimg_get((ID*)icon->obj);
+
+ if (pi) {
+ if (!nocreate && (pi->changed[miplevel] ||!pi->rect[miplevel])) /* changed only ever set by dynamic icons */
+ {
+ // XXX waitcursor(1);
+ /* create the preview rect if necessary */
+ icon_set_image((ID*)icon->obj, icon->drawinfo, pi, miplevel);
+ pi->changed[miplevel] = 0;
+ // XXX waitcursor(0);
+ }
+
+ if (!pi->rect[miplevel]) return; /* something has gone wrong! */
+
+ icon_draw_rect(x,y,di->w, di->h, di->aspect, pi->w[miplevel], pi->h[miplevel], pi->rect[miplevel]);
+ }
+ }
+}
+
+static void icon_draw_mipmap(float x, float y, int icon_id, float aspect, int miplevel, int nocreate)
+{
+ int draw_size = preview_size(miplevel);
+ icon_draw_size(x,y,icon_id, aspect, miplevel, draw_size, nocreate);
+}
+
+
+void UI_icon_draw_aspect(float x, float y, int icon_id, float aspect)
+{
+ icon_draw_mipmap(x,y,icon_id, aspect, PREVIEW_MIPMAP_ZERO, 0);
+}
+
+void UI_icon_draw(float x, float y, int icon_id)
+{
+ UI_icon_draw_aspect(x, y, icon_id, 1.0f);
+}
+
+void UI_icon_draw_size_blended(float x, float y, int size, int icon_id, int shade)
+{
+ if(shade < 0) {
+ float r= (128+shade)/128.0f;
+ glPixelTransferf(GL_ALPHA_SCALE, r);
+ }
+
+ icon_draw_size(x,y,icon_id, 1.0f, 0, size, 1);
+
+ if(shade < 0)
+ glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
+}
+
+void UI_icon_draw_preview(float x, float y, int icon_id, int nocreate)
+{
+ icon_draw_mipmap(x,y,icon_id, 1.0f, PREVIEW_MIPMAP_LARGE, nocreate);
+}
+
+void UI_icon_draw_aspect_blended(float x, float y, int icon_id, float aspect, int shade)
+{
+ if(shade < 0) {
+ float r= (128+shade)/128.0f;
+ glPixelTransferf(GL_ALPHA_SCALE, r);
+ }
+
+ UI_icon_draw_aspect(x, y, icon_id, aspect);
+
+ if(shade < 0)
+ glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
+}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
new file mode 100644
index 00000000000..06041dc202e
--- /dev/null
+++ b/source/blender/editors/interface/interface_intern.h
@@ -0,0 +1,392 @@
+/**
+ * $Id: interface.h 14444 2008-04-16 22:40:48Z hos $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef INTERFACE_H
+#define INTERFACE_H
+
+#include "UI_resources.h"
+#include "RNA_types.h"
+
+struct ARegion;
+struct bContext;
+struct IDProperty;
+struct uiHandleButtonData;
+struct wmEvent;
+struct wmWindow;
+struct uiStyle;
+
+/* ****************** general defines ************** */
+
+/* visual types for drawing */
+/* for time being separated from functional types */
+typedef enum {
+ /* standard set */
+ UI_WTYPE_TOGGLE,
+ UI_WTYPE_OPTION,
+ UI_WTYPE_RADIO,
+ UI_WTYPE_NUMBER,
+ UI_WTYPE_SLIDER,
+ UI_WTYPE_EXEC,
+
+ /* strings */
+ UI_WTYPE_NAME,
+ UI_WTYPE_NAME_LINK,
+ UI_WTYPE_POINTER_LINK,
+ UI_WTYPE_FILENAME,
+
+ /* menus */
+ UI_WTYPE_MENU_RADIO,
+ UI_WTYPE_MENU_POINTER_LINK,
+
+ UI_WTYPE_PULLDOWN,
+ UI_WTYPE_MENU_ITEM,
+ UI_WTYPE_MENU_BACK,
+
+ /* specials */
+ UI_WTYPE_ICON,
+ UI_WTYPE_SWATCH,
+ UI_WTYPE_RGB_PICKER,
+ UI_WTYPE_NORMAL
+
+} uiWidgetTypeEnum;
+
+
+
+#define UI_MAX_DRAW_STR 400
+#define UI_MAX_NAME_STR 64
+#define UI_ARRAY 29
+
+/* panel limits */
+#define UI_PANEL_MINX 100
+#define UI_PANEL_MINY 70
+
+/* uiBut->flag */
+#define UI_SELECT 1
+#define UI_MOUSE_OVER 2
+#define UI_ACTIVE 4
+#define UI_HAS_ICON 8
+#define UI_TEXTINPUT 16
+
+/* warn: rest of uiBut->flag in UI_interface.h */
+
+/* internal panel drawing defines */
+#define PNL_GRID 4
+#define PNL_DIST 8
+#define PNL_SAFETY 8
+#define PNL_HEADER 20
+
+/* panel->flag */
+#define PNL_SELECT 1
+#define PNL_CLOSEDX 2
+#define PNL_CLOSEDY 4
+#define PNL_CLOSED 6
+#define PNL_TABBED 8
+#define PNL_OVERLAP 16
+
+/* Button text selection:
+ * extension direction, selextend, inside ui_do_but_TEX */
+#define EXTEND_LEFT 1
+#define EXTEND_RIGHT 2
+
+typedef struct {
+ short xim, yim;
+ unsigned int *rect;
+ short xofs, yofs;
+} uiIconImage;
+
+
+typedef struct uiLinkLine { /* only for draw/edit */
+ struct uiLinkLine *next, *prev;
+
+ short flag, pad;
+
+ struct uiBut *from, *to;
+} uiLinkLine;
+
+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 {
+ struct uiBut *next, *prev;
+ short type, pointype, bit, bitnr, retval, strwidth, ofs, pos, selsta, selend;
+ int flag;
+
+ char *str;
+ char strdata[UI_MAX_NAME_STR];
+ char drawstr[UI_MAX_DRAW_STR];
+
+ float x1, y1, x2, y2;
+
+ char *poin;
+ float hardmin, hardmax, softmin, softmax;
+ float a1, a2, hsv[3]; // hsv is temp memory for hsv buttons
+ float aspect;
+
+ uiButHandleFunc func;
+ void *func_arg1;
+ void *func_arg2;
+
+ uiButHandleNFunc funcN;
+ void *func_argN;
+
+ void (*embossfunc)(int , int , float, float, float, float, float, int);
+ void (*sliderfunc)(int , float, float, float, float, float, float, int);
+
+ uiButCompleteFunc autocomplete_func;
+ void *autofunc_arg;
+
+ uiLink *link;
+
+ char *tip, *lockstr;
+
+ BIFIconID icon;
+ short but_align; /* aligning buttons, horiz/vertical */
+ short lock, win;
+ short iconadd, dt;
+
+ /* IDPOIN data */
+ uiIDPoinFuncFP idpoin_func;
+ ID **idpoin_idpp;
+
+ /* BLOCK data */
+ uiBlockCreateFunc block_create_func;
+
+ /* HMENU data */
+ uiMenuCreateFunc menu_create_func;
+
+ /* RNA data */
+ struct PointerRNA rnapoin;
+ struct PropertyRNA *rnaprop;
+ int rnaindex;
+
+ /* Operator data */
+ const char *opname;
+ int opcontext;
+ struct IDProperty *opproperties;
+ struct PointerRNA *opptr;
+
+ /* active button data */
+ struct uiHandleButtonData *active;
+
+ char *editstr;
+ double *editval;
+ float *editvec;
+ void *editcoba;
+ void *editcumap;
+
+ /* pointer back */
+ uiBlock *block;
+};
+
+struct uiBlock {
+ uiBlock *next, *prev;
+
+ ListBase buttons;
+ Panel *panel;
+ uiBlock *oldblock;
+
+ char name[UI_MAX_NAME_STR];
+
+ float winmat[4][4];
+
+ float minx, miny, maxx, maxy;
+ float aspect;
+
+ uiButHandleFunc func;
+ void *func_arg1;
+ void *func_arg2;
+
+ uiMenuHandleFunc butm_func;
+ void *butm_func_arg;
+
+ uiBlockHandleFunc handle_func;
+ void *handle_func_arg;
+
+ /* extra draw function for custom blocks */
+ void (*drawextra)();
+
+ int afterval, flag;
+
+ short direction, dt;
+ short auto_open, in_use;
+ double auto_open_last;
+
+ int lock;
+ char *lockstr;
+
+ float xofs, yofs; // offset to parent button
+ int bounds, dobounds, mx, my; // for doing delayed
+ int endblock; // uiEndBlock done?
+
+ rctf safety; // pulldowns, to detect outside, can differ per case how it is created
+ ListBase saferct; // uiSafetyRct list
+
+ uiPopupBlockHandle *handle; // handle
+ int tooltipdisabled; // to avoid tooltip after click
+
+ int active; // to keep blocks while drawing and free them afterwards
+};
+
+typedef struct uiSafetyRct {
+ struct uiSafetyRct *next, *prev;
+ rctf parent;
+ rctf safety;
+} uiSafetyRct;
+
+/* interface.c */
+
+extern int ui_translate_buttons(void);
+extern int ui_translate_menus(void);
+extern int ui_translate_tooltips(void);
+
+void ui_fontscale(short *points, float aspect);
+
+extern void ui_block_to_window_fl(const struct ARegion *ar, uiBlock *block, float *x, float *y);
+extern void ui_block_to_window(const struct ARegion *ar, uiBlock *block, int *x, int *y);
+extern void ui_block_to_window_rct(const struct ARegion *ar, uiBlock *block, rctf *graph, rcti *winr);
+extern void ui_window_to_block_fl(const struct ARegion *ar, uiBlock *block, float *x, float *y);
+extern void ui_window_to_block(const struct ARegion *ar, uiBlock *block, int *x, int *y);
+extern void ui_window_to_region(const ARegion *ar, int *x, int *y);
+
+extern double ui_get_but_val(uiBut *but);
+extern void ui_set_but_val(uiBut *but, double value);
+extern void ui_set_but_hsv(uiBut *but);
+extern void ui_get_but_vectorf(uiBut *but, float *vec);
+extern void ui_set_but_vectorf(uiBut *but, float *vec);
+
+extern void ui_get_but_string(uiBut *but, char *str, int maxlen);
+extern int ui_set_but_string(struct bContext *C, uiBut *but, const char *str);
+extern int ui_get_but_string_max_length(uiBut *but);
+
+extern void ui_set_but_soft_range(uiBut *but, double value);
+
+extern void ui_check_but(uiBut *but);
+extern int ui_is_but_float(uiBut *but);
+extern void ui_update_block_buts_hsv(uiBlock *block, float *hsv);
+
+extern void ui_bounds_block(uiBlock *block);
+extern void ui_block_translate(uiBlock *block, int x, int y);
+
+/* interface_regions.c */
+
+struct uiPopupBlockHandle {
+ /* internal */
+ struct ARegion *region;
+ int towardsx, towardsy;
+ double towardstime;
+ int dotowards;
+
+ int popup;
+ void (*popup_func)(struct bContext *C, void *arg, int event);
+ void (*cancel_func)(void *arg);
+ void *popup_arg;
+
+ /* for operator popups */
+ const char *opname;
+ int opcontext;
+ ScrArea *ctx_area;
+ ARegion *ctx_region;
+
+ /* return values */
+ int butretval;
+ int menuretval;
+ float retvalue;
+ float retvec[3];
+};
+
+uiBlock *ui_block_func_MENU(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but);
+uiBlock *ui_block_func_ICONROW(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but);
+uiBlock *ui_block_func_ICONTEXTROW(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but);
+uiBlock *ui_block_func_COL(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but);
+
+struct ARegion *ui_tooltip_create(struct bContext *C, struct ARegion *butregion, uiBut *but);
+void ui_tooltip_free(struct bContext *C, struct ARegion *ar);
+
+typedef uiBlock* (*uiBlockHandleCreateFunc)(struct bContext *C, struct uiPopupBlockHandle *handle, void *arg1);
+
+uiPopupBlockHandle *ui_popup_block_create(struct bContext *C, struct ARegion *butregion, uiBut *but,
+ uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, void *arg);
+uiPopupBlockHandle *ui_popup_menu_create(struct bContext *C, struct ARegion *butregion, uiBut *but,
+ uiMenuCreateFunc create_func, void *arg);
+void ui_popup_block_free(struct bContext *C, uiPopupBlockHandle *handle);
+
+void ui_set_name_menu(uiBut *but, int value);
+
+struct AutoComplete;
+struct AutoComplete *autocomplete_begin(char *startname, int maxlen);
+void autocomplete_do_name(struct AutoComplete *autocpl, const char *name);
+void autocomplete_end(struct AutoComplete *autocpl, char *autoname);
+
+/* interface_panel.c */
+extern int ui_handler_panel_region(struct bContext *C, struct wmEvent *event);
+extern void ui_draw_panel(struct ARegion *ar, struct uiStyle *style, uiBlock *block, rcti *rect);
+
+/* interface_draw.c */
+extern void ui_dropshadow(rctf *rct, float radius, float aspect, int select);
+
+extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);
+extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown);
+extern void gl_round_box_vertical_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadeLeft, float shadeRight);
+
+void ui_draw_but_COLORBAND(uiBut *but, rcti *rect);
+void ui_draw_but_NORMAL(uiBut *but, rcti *rect);
+void ui_draw_but_CURVE(ARegion *ar, uiBut *but, rcti *rect);
+
+
+/* interface_handlers.c */
+extern void ui_button_active_cancel(const struct bContext *C, uiBut *but);
+
+/* interface_widgets.c */
+void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3);
+void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect);
+extern void ui_draw_but(ARegion *ar, struct uiStyle *style, uiBut *but, rcti *rect);
+
+/* interface_style.c */
+void uiStyleInit(void);
+void uiStyleExit(void);
+
+
+/* interface_anim.c */
+void ui_but_anim_flag(uiBut *but, float cfra);
+void ui_but_anim_insert_keyframe(struct bContext *C);
+void ui_but_anim_delete_keyframe(struct bContext *C);
+void ui_but_anim_add_driver(struct bContext *C);
+void ui_but_anim_remove_driver(struct bContext *C);
+void ui_but_anim_menu(struct bContext *C, uiBut *but);
+
+#endif
+
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
new file mode 100644
index 00000000000..e0059041774
--- /dev/null
+++ b/source/blender/editors/interface/interface_layout.c
@@ -0,0 +1,1308 @@
+
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ID.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_listbase.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_idprop.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "BIF_gl.h"
+
+#include "ED_util.h"
+#include "ED_types.h"
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "interface_intern.h"
+
+/************************ Structs and Defines *************************/
+
+#define COLUMN_SPACE 5
+#define TEMPLATE_SPACE 5
+#define BOX_SPACE 5
+#define BUTTON_SPACE_X 5
+#define BUTTON_SPACE_Y 2
+
+#define RNA_NO_INDEX -1
+
+#define EM_UNIT_X XIC
+#define EM_UNIT_Y YIC
+
+/* Item */
+
+typedef enum uiItemType {
+ ITEM_OPERATOR,
+ ITEM_RNA_PROPERTY,
+ ITEM_MENU,
+ ITEM_LABEL
+} uiItemType;
+
+enum uiItemFlag {
+ ITEM_ICON,
+ ITEM_TEXT
+};
+
+typedef struct uiItem {
+ struct uiItem *next, *prev;
+ uiItemType type;
+ int slot;
+
+ char *name;
+ int icon;
+} uiItem;
+
+typedef struct uiItemRNA {
+ uiItem item;
+
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+ int expand;
+} uiItemRNA;
+
+typedef struct uiItemOp {
+ uiItem item;
+
+ wmOperatorType *ot;
+ IDProperty *properties;
+ int context;
+} uiItemOp;
+
+typedef struct uiItemLMenu {
+ uiItem item;
+
+ uiMenuCreateFunc func;
+} uiItemLMenu;
+
+/* Template */
+
+typedef enum uiTemplateType {
+ TEMPLATE_ROW,
+ TEMPLATE_COLUMN,
+ TEMPLATE_COLUMN_FLOW,
+ TEMPLATE_SPLIT,
+ TEMPLATE_BOX,
+
+ TEMPLATE_HEADER_MENUS,
+ TEMPLATE_HEADER_BUTTONS,
+ TEMPLATE_HEADER_ID
+} uiTemplateType;
+
+typedef struct uiTemplate {
+ struct uiTemplate *next, *prev;
+ uiTemplateType type;
+
+ ListBase items;
+ int color, slot;
+} uiTemplate;
+
+typedef struct uiTemplateFlow {
+ uiTemplate template;
+ int number;
+} uiTemplateFlow;
+
+typedef struct uiTemplateSplt {
+ uiTemplate template;
+ int number;
+ int lr;
+ uiLayout **sublayout;
+} uiTemplateSplt;
+
+typedef struct uiTemplateBx {
+ uiTemplate template;
+ uiLayout *sublayout;
+} uiTemplateBx;
+
+typedef struct uiTemplateHeadID {
+ uiTemplate template;
+
+ PointerRNA ptr;
+ char *propname;
+ int flag;
+ uiIDPoinFunc func;
+} uiTemplateHeadID;
+
+/* Layout */
+
+struct uiLayout {
+ ListBase templates;
+ int opcontext;
+ int dir;
+ int x, y, w, h;
+ int emw, emh;
+};
+
+void ui_layout_free(uiLayout *layout);
+void ui_layout_end(const bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y);
+
+/************************** Item ***************************/
+
+#define UI_FIT_EXPAND 1
+
+static int ui_item_fit(int item, int pos, int all, int available, int spacing, int last, int flag)
+{
+ if(all > available-spacing) {
+ /* contents is bigger than available space */
+ if(last)
+ return available-pos;
+ else
+ return (item*(available-spacing))/all;
+ }
+ else {
+ /* contents is smaller or equal to available space */
+ if(flag & UI_FIT_EXPAND) {
+ if(last)
+ return available-pos;
+ else
+ return (item*(available-spacing))/all;
+ }
+ else
+ return item;
+ }
+}
+
+/* create buttons for an item with an RNA array */
+static void ui_item_array(uiBlock *block, uiItemRNA *rnaitem, int len, int x, int y, int w, int h)
+{
+ PropertyType type;
+ PropertySubType subtype;
+ char *name;
+ int a;
+
+ /* retrieve type and subtype */
+ type= RNA_property_type(rnaitem->prop);
+ subtype= RNA_property_subtype(rnaitem->prop);
+
+ /* create label */
+ if(rnaitem->item.name)
+ name= (char*)rnaitem->item.name;
+ else
+ name= (char*)RNA_property_ui_name(rnaitem->prop);
+
+ if(strcmp(name, "") != 0)
+ uiDefBut(block, LABEL, 0, name, x, y + h - EM_UNIT_Y, w, EM_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+
+ /* create buttons */
+ uiBlockBeginAlign(block);
+
+ if(type == PROP_BOOLEAN && len == 20) {
+ /* special check for layer layout */
+ int butw, buth;
+
+ butw= ui_item_fit(EM_UNIT_X, 0, EM_UNIT_X*10 + BUTTON_SPACE_X, w, 0, 0, UI_FIT_EXPAND);
+ buth= MIN2(EM_UNIT_Y, butw);
+
+ y += 2*(EM_UNIT_Y - buth);
+
+ uiBlockBeginAlign(block);
+ for(a=0; a<5; a++)
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a, "", ICON_BLANK1, x + butw*a, y+buth, butw, buth);
+ for(a=0; a<5; a++)
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a+10, "", ICON_BLANK1, x + butw*a, y, butw, buth);
+ uiBlockEndAlign(block);
+
+ x += 5*butw + BUTTON_SPACE_X;
+
+ uiBlockBeginAlign(block);
+ for(a=0; a<5; a++)
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a+5, "", ICON_BLANK1, x + butw*a, y+buth, butw, buth);
+ for(a=0; a<5; a++)
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a+15, "", ICON_BLANK1, x + butw*a, y, butw, buth);
+ uiBlockEndAlign(block);
+ }
+ else if(subtype == PROP_MATRIX) {
+ /* matrix layout */
+ int row, col;
+
+ len= ceil(sqrt(len));
+
+ h /= len;
+ w /= len;
+
+ // XXX test
+ for(a=0; a<len; a++) {
+ col= a%len;
+ row= a/len;
+
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a, "", 0, x + w*col, y+(row-a-1)*EM_UNIT_Y, w, EM_UNIT_Y);
+ }
+ }
+ else if(len <= 4 && ELEM3(subtype, PROP_ROTATION, PROP_VECTOR, PROP_COLOR)) {
+ /* layout for known array subtypes */
+ static char vectoritem[4]= {'X', 'Y', 'Z', 'W'};
+ static char quatitem[4]= {'W', 'X', 'Y', 'Z'};
+ static char coloritem[4]= {'R', 'G', 'B', 'A'};
+ char str[3];
+
+ for(a=0; a<len; a++) {
+ if(len == 4 && subtype == PROP_ROTATION)
+ str[0]= quatitem[a];
+ else if(subtype == PROP_VECTOR || subtype == PROP_ROTATION)
+ str[0]= vectoritem[a];
+ else
+ str[0]= coloritem[a];
+
+ if(type == PROP_BOOLEAN) {
+ str[1]= '\0';
+ }
+ else {
+ str[1]= ':';
+ str[2]= '\0';
+ }
+
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a, str, 0, x, y+(len-a-1)*EM_UNIT_Y, w, EM_UNIT_Y);
+ }
+ }
+ else {
+ /* default array layout */
+ for(a=0; a<len; a++)
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a, "", 0, x, y+(len-a-1)*EM_UNIT_Y, w, EM_UNIT_Y);
+ }
+
+ uiBlockEndAlign(block);
+}
+
+static void ui_item_enum_row(uiBlock *block, uiItemRNA *rnaitem, int x, int y, int w, int h)
+{
+ const EnumPropertyItem *item;
+ int a, totitem, pos, itemw;
+ const char *propname;
+
+ propname= RNA_property_identifier(rnaitem->prop);
+ RNA_property_enum_items(&rnaitem->ptr, rnaitem->prop, &item, &totitem);
+
+ uiBlockBeginAlign(block);
+ pos= 0;
+ for(a=0; a<totitem; a++) {
+ itemw= ui_item_fit(1, pos, totitem, w, 0, a == totitem-1, UI_FIT_EXPAND);
+ uiDefButR(block, ROW, 0, NULL, x+pos, y, itemw, h, &rnaitem->ptr, propname, -1, 0, item[a].value, -1, -1, NULL);
+ pos += itemw;
+ }
+ uiBlockEndAlign(block);
+}
+
+/* create label + button for RNA property */
+static void ui_item_with_label(uiBlock *block, uiItemRNA *rnaitem, int x, int y, int w, int h)
+{
+ char *name;
+
+ if(rnaitem->item.name)
+ name= (char*)rnaitem->item.name;
+ else
+ name= (char*)RNA_property_ui_name(rnaitem->prop);
+
+ if(strcmp(name, "") != 0) {
+ w= w/2;
+ uiDefBut(block, LABEL, 0, name, x, y, w, h, NULL, 0.0, 0.0, 0, 0, "");
+ x += w;
+ }
+
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, rnaitem->index, "", rnaitem->item.icon, x, y, w, h);
+}
+
+/* create buttons for an arbitrary item */
+static void ui_item_buts(uiBlock *block, uiItem *item, int x, int y, int w, int h)
+{
+ if(item->type == ITEM_RNA_PROPERTY) {
+ /* RNA property */
+ uiItemRNA *rnaitem= (uiItemRNA*)item;
+ PropertyType type;
+ int len;
+
+ /* retrieve info */
+ type= RNA_property_type(rnaitem->prop);
+ len= RNA_property_array_length(rnaitem->prop);
+
+ /* array property */
+ if(rnaitem->index == RNA_NO_INDEX && len > 0)
+ ui_item_array(block, rnaitem, len, x, y, w, h);
+ /* expanded enum */
+ else if(type == PROP_ENUM && rnaitem->expand)
+ ui_item_enum_row(block, rnaitem, x, y, w, h);
+ /* property with separate label */
+ else if(type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER)
+ ui_item_with_label(block, rnaitem, x, y, w, h);
+ /* single button */
+ else
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, rnaitem->index, (char*)item->name, item->icon, x, y, w, h);
+ }
+ else if(item->type == ITEM_OPERATOR) {
+ /* operator */
+ uiItemOp *opitem= (uiItemOp*)item;
+ uiBut *but;
+
+ if(item->icon && item->name)
+ but= uiDefIconTextButO(block, BUT, opitem->ot->idname, opitem->context, item->icon, (char*)item->name, x, y, w, h, NULL);
+ else if(item->icon)
+ but= uiDefIconButO(block, BUT, opitem->ot->idname, opitem->context, item->icon, x, y, w, h, NULL);
+ /* text only */
+ else
+ but= uiDefButO(block, BUT, opitem->ot->idname, opitem->context, (char*)item->name, x, y, w, h, NULL);
+
+ if(but && opitem->properties) {
+ /* assign properties */
+ PointerRNA *opptr= uiButGetOperatorPtrRNA(but);
+ opptr->data= opitem->properties;
+ opitem->properties= NULL;
+ }
+ }
+ else if(item->type == ITEM_MENU) {
+ /* menu */
+ uiItemLMenu *menuitem= (uiItemLMenu*)item;
+
+ uiDefMenuBut(block, menuitem->func, NULL, (char*)item->name, x, y-2, w-3, h+4, "");
+ }
+ else if(item->type == ITEM_LABEL) {
+ /* label */
+
+ if(item->icon && item->name)
+ uiDefIconTextBut(block, LABEL, 0, item->icon, (char*)item->name, x, y, w, h, NULL, 0.0, 0.0, 0, 0, "");
+ else if(item->icon)
+ uiDefIconBut(block, LABEL, 0, item->icon, x, y, w, h, NULL, 0.0, 0.0, 0, 0, "");
+ else if((char*)item->name)
+ uiDefBut(block, LABEL, 0, (char*)item->name, x, y, w, h, NULL, 0.0, 0.0, 0, 0, "");
+ }
+ else {
+ /* separator */
+ uiDefBut(block, SEPR, 0, "", x, y, w, h, NULL, 0.0, 0.0, 0, 0, "");
+ }
+}
+
+/* estimated size of text + icon */
+static int ui_text_icon_width(char *name, int icon)
+{
+ if(icon && name && strcmp(name, "") == 0)
+ return EM_UNIT_X; /* icon only */
+ else if(icon)
+ return 10*EM_UNIT_X; /* icon + text */
+ else
+ return 10*EM_UNIT_X; /* text only */
+}
+
+/* estimated size of an item */
+static void ui_item_size(uiItem *item, int *r_w, int *r_h)
+{
+ int w, h;
+
+ if(item->type == ITEM_RNA_PROPERTY) {
+ /* RNA property */
+ uiItemRNA *rnaitem= (uiItemRNA*)item;
+ PropertyType type;
+ PropertySubType subtype;
+ int len;
+
+ w= ui_text_icon_width(item->name, item->icon);
+ h= EM_UNIT_Y;
+
+ /* arbitrary extended width by type */
+ type= RNA_property_type(rnaitem->prop);
+ subtype= RNA_property_subtype(rnaitem->prop);
+ len= RNA_property_array_length(rnaitem->prop);
+
+ if(type == PROP_STRING)
+ w += 10*EM_UNIT_X;
+
+ /* increase height for arrays */
+ if(rnaitem->index == RNA_NO_INDEX && len > 0) {
+ if(item->name && strcmp(item->name, "") == 0 && item->icon == 0)
+ h= 0;
+
+ if(type == PROP_BOOLEAN && len == 20)
+ h += 2*EM_UNIT_Y;
+ else if(subtype == PROP_MATRIX)
+ h += ceil(sqrt(len))*EM_UNIT_Y;
+ else
+ h += len*EM_UNIT_Y;
+ }
+ }
+ else {
+ /* other */
+ w= ui_text_icon_width(item->name, item->icon);
+ h= EM_UNIT_Y;
+ }
+
+ if(r_w) *r_w= w;
+ if(r_h) *r_h= h;
+}
+
+static void ui_item_free(uiItem *item)
+{
+ if(item->type == ITEM_OPERATOR) {
+ uiItemOp *opitem= (uiItemOp*)item;
+
+ if(opitem->properties) {
+ IDP_FreeProperty(opitem->properties);
+ MEM_freeN(opitem->properties);
+ }
+ }
+}
+
+/* operator items */
+void uiItemFullO(uiLayout *layout, char *name, int icon, char *idname, IDProperty *properties, int context)
+{
+ uiTemplate *template= layout->templates.last;
+ wmOperatorType *ot= WM_operatortype_find(idname);
+ uiItemOp *opitem;
+
+ if(!template)
+ return;
+ if(!ot)
+ return;
+
+ opitem= MEM_callocN(sizeof(uiItemOp), "uiItemOp");
+
+ opitem->item.name= name;
+ opitem->item.icon= icon;
+ opitem->item.type= ITEM_OPERATOR;
+ opitem->item.slot= template->slot;
+
+ opitem->ot= ot;
+ opitem->properties= properties;
+ opitem->context= context;
+
+ BLI_addtail(&template->items, opitem);
+}
+
+void uiItemEnumO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
+{
+ PointerRNA ptr;
+
+ WM_operator_properties_create(&ptr, opname);
+ RNA_enum_set(&ptr, propname, value);
+
+ uiItemFullO(layout, name, icon, opname, ptr.data, layout->opcontext);
+}
+
+void uiItemsEnumO(uiLayout *layout, char *opname, char *propname)
+{
+ wmOperatorType *ot= WM_operatortype_find(opname);
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ if(!ot || !ot->srna)
+ return;
+
+ RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
+ prop= RNA_struct_find_property(&ptr, propname);
+
+ if(prop && RNA_property_type(prop) == PROP_ENUM) {
+ const EnumPropertyItem *item;
+ int totitem, i;
+
+ RNA_property_enum_items(&ptr, prop, &item, &totitem);
+
+ for(i=0; i<totitem; i++)
+ uiItemEnumO(layout, "", 0, opname, propname, item[i].value);
+ }
+}
+
+void uiItemBooleanO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
+{
+ PointerRNA ptr;
+
+ WM_operator_properties_create(&ptr, opname);
+ RNA_boolean_set(&ptr, propname, value);
+
+ uiItemFullO(layout, name, icon, opname, ptr.data, layout->opcontext);
+}
+
+void uiItemIntO(uiLayout *layout, char *name, int icon, char *opname, char *propname, int value)
+{
+ PointerRNA ptr;
+
+ WM_operator_properties_create(&ptr, opname);
+ RNA_int_set(&ptr, propname, value);
+
+ uiItemFullO(layout, name, icon, opname, ptr.data, layout->opcontext);
+}
+
+void uiItemFloatO(uiLayout *layout, char *name, int icon, char *opname, char *propname, float value)
+{
+ PointerRNA ptr;
+
+ WM_operator_properties_create(&ptr, opname);
+ RNA_float_set(&ptr, propname, value);
+
+ uiItemFullO(layout, name, icon, opname, ptr.data, layout->opcontext);
+}
+
+void uiItemStringO(uiLayout *layout, char *name, int icon, char *opname, char *propname, char *value)
+{
+ PointerRNA ptr;
+
+ WM_operator_properties_create(&ptr, opname);
+ RNA_string_set(&ptr, propname, value);
+
+ uiItemFullO(layout, name, icon, opname, ptr.data, layout->opcontext);
+}
+
+void uiItemO(uiLayout *layout, char *name, int icon, char *opname)
+{
+ uiItemFullO(layout, name, icon, opname, NULL, layout->opcontext);
+}
+
+/* RNA property items */
+void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int expand)
+{
+ uiTemplate *template= layout->templates.last;
+ uiItemRNA *rnaitem;
+
+ if(!ptr->data || !prop)
+ return;
+ if(!template)
+ return;
+
+ rnaitem= MEM_callocN(sizeof(uiItemRNA), "uiItemRNA");
+
+ rnaitem->item.name= name;
+ rnaitem->item.icon= icon;
+ rnaitem->item.type= ITEM_RNA_PROPERTY;
+ rnaitem->item.slot= template->slot;
+
+ rnaitem->ptr= *ptr;
+ rnaitem->prop= prop;
+ rnaitem->index= index;
+ rnaitem->expand= expand;
+
+ BLI_addtail(&template->items, rnaitem);
+}
+
+void uiItemR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, char *propname, int expand)
+{
+ PropertyRNA *prop;
+
+ prop= RNA_struct_find_property(ptr, propname);
+
+ if(!ptr->data)
+ return;
+ if(!prop) {
+ printf("uiItemR: property not found: %s\n",propname);
+ return;
+ }
+
+ uiItemFullR(layout, name, icon, ptr, prop, RNA_NO_INDEX, expand);
+}
+
+/* menu item */
+void uiItemM(uiLayout *layout, char *name, int icon, uiMenuCreateFunc func)
+{
+ uiTemplate *template= layout->templates.last;
+ uiItemLMenu *menuitem;
+
+ if(!template)
+ return;
+
+ menuitem= MEM_callocN(sizeof(uiItemLMenu), "uiItemLMenu");
+
+ menuitem->item.name= name;
+ menuitem->item.icon= icon;
+ menuitem->item.type= ITEM_MENU;
+ menuitem->item.slot= template->slot;
+
+ menuitem->func= func;
+
+ BLI_addtail(&template->items, menuitem);
+}
+
+/* label item */
+void uiItemL(uiLayout *layout, char *name, int icon)
+{
+ uiTemplate *template= layout->templates.last;
+ uiItem *item;
+
+ if(!template)
+ return;
+
+ item= MEM_callocN(sizeof(uiItem), "uiItem");
+
+ item->name= name;
+ item->icon= icon;
+ item->type= ITEM_LABEL;
+ item->slot= template->slot;
+
+ BLI_addtail(&template->items, item);
+}
+
+/**************************** Template ***************************/
+
+/* single row layout */
+static void ui_layout_row(uiLayout *layout, uiBlock *block, uiTemplate *template)
+{
+ uiItem *item;
+ int tot=0, totw= 0, maxh= 0, itemw, itemh, x, w;
+
+ /* estimate total width of buttons */
+ for(item=template->items.first; item; item=item->next) {
+ ui_item_size(item, &itemw, &itemh);
+ totw += itemw;
+ maxh= MAX2(maxh, itemh);
+ tot++;
+ }
+
+ if(totw == 0)
+ return;
+
+ /* create buttons starting from left */
+ x= 0;
+ w= layout->w;
+
+ for(item=template->items.first; item; item=item->next) {
+ ui_item_size(item, &itemw, &itemh);
+ itemw= ui_item_fit(itemw, x, totw, w, (tot-1)*BUTTON_SPACE_X, !item->next, UI_FIT_EXPAND);
+
+ ui_item_buts(block, item, layout->x+x, layout->y-itemh, itemw, itemh);
+ x += itemw+BUTTON_SPACE_X;
+ }
+
+ layout->y -= maxh;
+}
+
+/* multi-column layout */
+static void ui_layout_column(uiLayout *layout, uiBlock *block, uiTemplate *template)
+{
+ uiItem *item;
+ int col, totcol= 0, x, y, miny, itemw, itemh, w;
+
+ /* compute number of columns */
+ for(item=template->items.first; item; item=item->next)
+ totcol= MAX2(item->slot+1, totcol);
+
+ if(totcol == 0)
+ return;
+
+ x= 0;
+ miny= 0;
+ w= layout->w;
+
+ /* create column per column */
+ for(col=0; col<totcol; col++) {
+ y= 0;
+
+ itemw= ui_item_fit(1, x, totcol, w, (totcol-1)*COLUMN_SPACE, col == totcol-1, UI_FIT_EXPAND);
+
+ for(item=template->items.first; item; item=item->next) {
+ if(item->slot != col)
+ continue;
+
+ ui_item_size(item, NULL, &itemh);
+
+ y -= itemh;
+ ui_item_buts(block, item, layout->x+x, layout->y+y, itemw, itemh);
+ y -= BUTTON_SPACE_Y;
+ }
+
+ x += itemw + COLUMN_SPACE;
+ miny= MIN2(miny, y);
+ }
+
+ layout->y += miny;
+}
+
+/* multi-column layout, automatically flowing to the next */
+static void ui_layout_column_flow(uiLayout *layout, uiBlock *block, uiTemplate *template)
+{
+ uiTemplateFlow *flow= (uiTemplateFlow*)template;
+ uiItem *item;
+ int col, x, y, w, emh, emy, miny, itemw, itemh, maxw=0;
+ int toth, totcol, totitem;
+
+ /* compute max needed width and total height */
+ toth= 0;
+ totitem= 0;
+ for(item=template->items.first; item; item=item->next) {
+ ui_item_size(item, &itemw, &itemh);
+ maxw= MAX2(maxw, itemw);
+ toth += itemh;
+ totitem++;
+ }
+
+ if(flow->number <= 0) {
+ /* auto compute number of columns, not very good */
+ if(maxw == 0)
+ return;
+
+ totcol= MAX2(layout->emw/maxw, 1);
+ totcol= MIN2(totcol, totitem);
+ }
+ else
+ totcol= flow->number;
+
+ /* compute sizes */
+ x= 0;
+ y= 0;
+ emy= 0;
+ miny= 0;
+
+ w= layout->w;
+ emh= toth/totcol;
+
+ /* create column per column */
+ col= 0;
+ for(item=template->items.first; item; item=item->next) {
+ ui_item_size(item, NULL, &itemh);
+ itemw= ui_item_fit(1, x, totcol, w, (totcol-1)*COLUMN_SPACE, col == totcol-1, UI_FIT_EXPAND);
+
+ y -= itemh;
+ emy -= itemh;
+ ui_item_buts(block, item, layout->x+x, layout->y+y, itemw, itemh);
+ y -= BUTTON_SPACE_Y;
+ miny= MIN2(miny, y);
+
+ /* decide to go to next one */
+ if(col < totcol-1 && emy <= -emh) {
+ x += itemw + COLUMN_SPACE;
+ y= 0;
+ col++;
+ }
+ }
+
+ layout->y += miny;
+}
+
+#if 0
+/* left-right layout, with buttons aligned on both sides */
+static void ui_layout_split(uiLayout *layout, uiBlock *block, uiTemplate *template)
+{
+ uiItem *item;
+ int tot=0, totw= 0, maxh= 0, itemw, itemh, lx, rx, w;
+
+ /* estimate total width of buttons */
+ for(item=template->items.first; item; item=item->next) {
+ ui_item_size(item, &itemw, &itemh);
+ totw += itemw;
+ maxh= MAX2(maxh, itemh);
+ tot++;
+ }
+
+ if(totw == 0)
+ return;
+
+ /* create buttons starting from left and right */
+ lx= 0;
+ rx= 0;
+ w= layout->w - BUTTON_SPACE_X*(tot-1) + BUTTON_SPACE_X;
+
+ for(item=template->items.first; item; item=item->next) {
+ ui_item_size(item, &itemw, &itemh);
+
+ if(item->slot == UI_TSLOT_LR_LEFT) {
+ itemw= ui_item_fit(itemw, lx, totw, w, 0, 0);
+ ui_item_buts(block, item, layout->x+lx, layout->y-itemh, itemw, itemh);
+ lx += itemw + BUTTON_SPACE_X;
+ }
+ else {
+ itemw= ui_item_fit(itemw, totw + rx, totw, w, 0, 0);
+ rx -= itemw + BUTTON_SPACE_X;
+ ui_item_buts(block, item, layout->x+layout->w+rx, layout->y-itemh, itemw, itemh);
+ }
+ }
+
+ layout->y -= maxh;
+}
+#endif
+
+/* split in columns */
+static void ui_layout_split(const bContext *C, uiLayout *layout, uiBlock *block, uiTemplate *template)
+{
+ uiTemplateSplt *split= (uiTemplateSplt*)template;
+ uiLayout *sublayout;
+ int a, x, y, miny, w= layout->w, h= layout->h, splitw;
+
+ x= 0;
+ y= 0;
+ miny= layout->y;
+
+ for(a=0; a<split->number; a++) {
+ sublayout= split->sublayout[a];
+
+ splitw= ui_item_fit(1, x, split->number, w, (split->number-1)*COLUMN_SPACE, a == split->number-1, UI_FIT_EXPAND);
+ sublayout->x= layout->x + x;
+ sublayout->w= splitw;
+ sublayout->y= layout->y;
+ sublayout->h= h;
+
+ sublayout->emw= layout->emw/split->number;
+ sublayout->emh= layout->emh;
+
+ /* do layout for elements in sublayout */
+ ui_layout_end(C, block, sublayout, NULL, &y);
+ miny= MIN2(y, miny);
+
+ x += splitw + COLUMN_SPACE;
+ }
+
+ layout->y= miny;
+}
+
+/* element in a box layout */
+static void ui_layout_box(const bContext *C, uiLayout *layout, uiBlock *block, uiTemplate *template)
+{
+ uiTemplateBx *box= (uiTemplateBx*)template;
+ int starty, startx, w= layout->w, h= layout->h;
+
+ startx= layout->x;
+ starty= layout->y;
+
+ /* some extra padding */
+ box->sublayout->x= layout->x + BOX_SPACE;
+ box->sublayout->w= w - 2*BOX_SPACE;
+ box->sublayout->y= layout->y - BOX_SPACE;
+ box->sublayout->h= h;
+
+ box->sublayout->emw= layout->emw;
+ box->sublayout->emh= layout->emh;
+
+ /* do layout for elements in sublayout */
+ ui_layout_end(C, block, box->sublayout, NULL, &layout->y);
+
+ /* roundbox around the sublayout */
+ uiDefBut(block, ROUNDBOX, 0, "", startx, layout->y, w, starty - layout->y, NULL, 7.0, 0.0, 3, 20, "");
+}
+
+static void ui_layout_header_buttons(uiLayout *layout, uiBlock *block, uiTemplate *template)
+{
+ uiItem *item;
+ int itemw, itemh;
+
+ uiBlockBeginAlign(block);
+
+ for(item=template->items.first; item; item=item->next) {
+ ui_item_size(item, &itemw, &itemh);
+ ui_item_buts(block, item, layout->x, layout->y, itemw, itemh);
+ layout->x += itemw;
+ }
+
+ uiBlockEndAlign(block);
+}
+
+static void ui_layout_header_menus(const bContext *C, uiLayout *layout, uiBlock *block, uiTemplate *template)
+{
+ ScrArea *sa= CTX_wm_area(C);
+
+ layout->x= ED_area_header_standardbuttons(C, block, layout->y);
+
+ if((sa->flag & HEADER_NO_PULLDOWN)==0) {
+ uiBlockSetEmboss(block, UI_EMBOSSP);
+ ui_layout_header_buttons(layout, block, template);
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+}
+
+static void ui_layout_header_id(const bContext *C, uiLayout *layout, uiBlock *block, uiTemplate *template)
+{
+ uiTemplateHeadID *idtemplate= (uiTemplateHeadID*)template;
+ PointerRNA idptr;
+
+ idptr= RNA_pointer_get(&idtemplate->ptr, idtemplate->propname);
+
+ layout->x= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)idptr.data, ID_TXT, NULL,
+ layout->x, layout->y, idtemplate->func,
+ UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_OPEN|UI_ID_DELETE);
+}
+
+void ui_template_free(uiTemplate *template)
+{
+ uiItem *item;
+ int a;
+
+ if(template->type == TEMPLATE_BOX) {
+ uiTemplateBx *box= (uiTemplateBx*)template;
+ ui_layout_free(box->sublayout);
+ }
+ if(template->type == TEMPLATE_SPLIT) {
+ uiTemplateSplt *split= (uiTemplateSplt*)template;
+
+ for(a=0; a<split->number; a++)
+ ui_layout_free(split->sublayout[a]);
+ MEM_freeN(split->sublayout);
+ }
+
+ for(item=template->items.first; item; item=item->next)
+ ui_item_free(item);
+
+ BLI_freelistN(&template->items);
+}
+
+/* template create functions */
+void uiLayoutRow(uiLayout *layout)
+{
+ uiTemplate *template;
+
+ template= MEM_callocN(sizeof(uiTemplate), "uiTemplate");
+ template->type= TEMPLATE_ROW;
+
+ BLI_addtail(&layout->templates, template);
+}
+
+void uiLayoutColumn(uiLayout *layout)
+{
+ uiTemplate *template;
+
+ template= MEM_callocN(sizeof(uiTemplate), "uiTemplate");
+ template->type= TEMPLATE_COLUMN;
+
+ BLI_addtail(&layout->templates, template);
+}
+
+void uiLayoutColumnFlow(uiLayout *layout, int number)
+{
+ uiTemplateFlow *flow;
+
+ flow= MEM_callocN(sizeof(uiTemplateFlow), "uiTemplateFlow");
+ flow->template.type= TEMPLATE_COLUMN_FLOW;
+ flow->number= number;
+ BLI_addtail(&layout->templates, flow);
+}
+
+uiLayout *uiLayoutBox(uiLayout *layout)
+{
+ uiTemplateBx *box;
+
+ box= MEM_callocN(sizeof(uiTemplateBx), "uiTemplateBx");
+ box->template.type= TEMPLATE_BOX;
+ box->sublayout= uiLayoutBegin(layout->dir, 0, 0, 0, 0);
+ BLI_addtail(&layout->templates, box);
+
+ return box->sublayout;
+}
+
+void uiLayoutSplit(uiLayout *layout, int number, int lr)
+{
+ uiTemplateSplt *split;
+ int a;
+
+ split= MEM_callocN(sizeof(uiTemplateSplt), "uiTemplateSplt");
+ split->template.type= TEMPLATE_SPLIT;
+ split->number= number;
+ split->lr= lr;
+ split->sublayout= MEM_callocN(sizeof(uiLayout*)*number, "uiTemplateSpltSub");
+
+ for(a=0; a<number; a++)
+ split->sublayout[a]= uiLayoutBegin(layout->dir, 0, 0, 0, 0);
+
+ BLI_addtail(&layout->templates, split);
+}
+
+uiLayout *uiLayoutSub(uiLayout *layout, int n)
+{
+ uiTemplate *template= layout->templates.last;
+
+ if(template) {
+ switch(template->type) {
+ case TEMPLATE_SPLIT:
+ if(n >= 0 && n < ((uiTemplateSplt*)template)->number)
+ return ((uiTemplateSplt*)template)->sublayout[n];
+ break;
+ case TEMPLATE_BOX:
+ return ((uiTemplateBx*)template)->sublayout;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+void uiTemplateHeaderMenus(uiLayout *layout)
+{
+ uiTemplate *template;
+
+ template= MEM_callocN(sizeof(uiTemplate), "uiTemplate");
+ template->type= TEMPLATE_HEADER_MENUS;
+
+ BLI_addtail(&layout->templates, template);
+}
+
+void uiTemplateHeaderButtons(uiLayout *layout)
+{
+ uiTemplate *template;
+
+ template= MEM_callocN(sizeof(uiTemplate), "uiTemplate");
+ template->type= TEMPLATE_HEADER_BUTTONS;
+
+ BLI_addtail(&layout->templates, template);
+}
+
+void uiTemplateHeaderID(uiLayout *layout, PointerRNA *ptr, char *propname, int flag, uiIDPoinFunc func)
+{
+ uiTemplateHeadID *idtemplate;
+
+ idtemplate= MEM_callocN(sizeof(uiTemplateHeadID), "uiTemplateHeadID");
+ idtemplate->template.type= TEMPLATE_HEADER_ID;
+ idtemplate->ptr= *ptr;
+ idtemplate->propname= propname;
+ idtemplate->flag= flag;
+ idtemplate->func= func;
+
+ BLI_addtail(&layout->templates, idtemplate);
+}
+
+void uiTemplateSetColor(uiLayout *layout, int color)
+{
+ uiTemplate *template= layout->templates.last;
+
+ if(template)
+ template->color= color;
+}
+
+void uiTemplateSlot(uiLayout *layout, int slot)
+{
+ uiTemplate *template= layout->templates.last;
+
+ if(template)
+ template->slot= slot;
+}
+
+/********************** Layout *******************/
+
+static void ui_layout_templates(const bContext *C, uiBlock *block, uiLayout *layout)
+{
+ uiTemplate *template;
+
+ if(layout->dir == UI_LAYOUT_HORIZONTAL) {
+ for(template=layout->templates.first; template; template=template->next) {
+ switch(template->type) {
+ case TEMPLATE_HEADER_MENUS:
+ ui_layout_header_menus(C, layout, block, template);
+ break;
+ case TEMPLATE_HEADER_ID:
+ ui_layout_header_id(C, layout, block, template);
+ break;
+ case TEMPLATE_HEADER_BUTTONS:
+ default:
+ ui_layout_header_buttons(layout, block, template);
+ break;
+ }
+ }
+
+ layout->x += TEMPLATE_SPACE;
+ }
+ else {
+ for(template=layout->templates.first; template; template=template->next) {
+ if(template->color) {
+ // XXX oldcolor= uiBlockGetCol(block);
+ // XXX uiBlockSetCol(block, template->color);
+ }
+
+ switch(template->type) {
+ case TEMPLATE_ROW:
+ ui_layout_row(layout, block, template);
+ break;
+ case TEMPLATE_COLUMN_FLOW:
+ ui_layout_column_flow(layout, block, template);
+ break;
+ case TEMPLATE_SPLIT:
+ ui_layout_split(C, layout, block, template);
+ break;
+ case TEMPLATE_BOX:
+ ui_layout_box(C, layout, block, template);
+ break;
+ case TEMPLATE_COLUMN:
+ default:
+ ui_layout_column(layout, block, template);
+ break;
+ }
+
+ // XXX if(template->color)
+ // XXX uiBlockSetCol(block, oldcolor);
+
+ layout->y -= TEMPLATE_SPACE;
+ }
+ }
+}
+
+void ui_layout_end(const bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y)
+{
+ ui_layout_templates(C, block, layout);
+
+ if(x) *x= layout->x;
+ if(y) *y= layout->y;
+
+}
+
+void ui_layout_free(uiLayout *layout)
+{
+ uiTemplate *template;
+
+ for(template=layout->templates.first; template; template=template->next)
+ ui_template_free(template);
+
+ BLI_freelistN(&layout->templates);
+ MEM_freeN(layout);
+}
+
+uiLayout *uiLayoutBegin(int dir, int x, int y, int size, int em)
+{
+ uiLayout *layout;
+
+ layout= MEM_callocN(sizeof(uiLayout), "uiLayout");
+ layout->opcontext= WM_OP_INVOKE_REGION_WIN;
+ layout->dir= dir;
+ layout->x= x;
+ layout->y= y;
+
+ if(dir == UI_LAYOUT_HORIZONTAL) {
+ layout->h= size;
+ layout->emh= em*EM_UNIT_Y;
+ }
+ else {
+ layout->w= size;
+ layout->emw= em*EM_UNIT_X;
+ }
+
+ return layout;
+}
+
+void uiLayoutContext(uiLayout *layout, int opcontext)
+{
+ layout->opcontext= opcontext;
+}
+
+void uiLayoutEnd(const bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y)
+{
+ ui_layout_end(C, block, layout, x, y);
+ ui_layout_free(layout);
+}
+
+/************************ Utilities ************************/
+
+void uiRegionPanelLayout(const bContext *C, ARegion *ar, int vertical, char *context)
+{
+ uiBlock *block;
+ PanelType *pt;
+ Panel *panel;
+ float col[3];
+ int xco, yco, x=PNL_DIST, y=-PNL_HEADER-PNL_DIST, w, em;
+
+ // XXX this only hides cruft
+
+ /* clear */
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ uiBeginPanels(C, ar);
+
+ for(pt= ar->type->paneltypes.first; pt; pt= pt->next) {
+ if(context)
+ if(!pt->context || strcmp(context, pt->context) != 0)
+ continue;
+
+ if(pt->draw && (!pt->poll || pt->poll(C, pt))) {
+ block= uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
+ panel= uiBeginPanel(ar, block, pt);
+
+ if(panel) {
+ if(vertical) {
+ w= (ar->type->minsizex)? ar->type->minsizex-12: block->aspect*ar->winx-12;
+ em= (ar->type->minsizex)? 10: 20;
+ }
+ else {
+ w= (ar->type->minsizex)? ar->type->minsizex-12: UI_PANEL_WIDTH-12;
+ em= (ar->type->minsizex)? 10: 20;
+ }
+
+ panel->type= pt;
+ panel->layout= uiLayoutBegin(UI_LAYOUT_VERTICAL, PNL_SAFETY, 0, w-2*PNL_SAFETY, em);
+
+ pt->draw(C, panel);
+
+ uiLayoutEnd(C, block, panel->layout, &xco, &yco);
+ panel->layout= NULL;
+ uiEndPanel(block, w, -yco + 12);
+ }
+ else {
+ w= PNL_HEADER;
+ yco= PNL_HEADER;
+ }
+
+ uiEndBlock(C, block);
+
+ if(vertical)
+ y += yco+PNL_DIST;
+ else
+ x += w+PNL_DIST;
+ }
+ }
+
+ uiEndPanels(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+void uiRegionHeaderLayout(const bContext *C, ARegion *ar)
+{
+ uiBlock *block;
+ uiLayout *layout;
+ HeaderType *ht;
+ Header header = {0};
+ float col[3];
+ int xco, yco;
+
+ // XXX this only hides cruft
+
+ /* clear */
+ if(ED_screen_area_active(C))
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ else
+ UI_GetThemeColor3fv(TH_HEADERDESEL, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ xco= 8;
+ yco= 3;
+
+ /* draw all headers types */
+ for(ht= ar->type->headertypes.first; ht; ht= ht->next) {
+ block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
+ layout= uiLayoutBegin(UI_LAYOUT_HORIZONTAL, xco, yco, 24, 1);
+
+ if(ht->draw) {
+ header.type= ht;
+ header.layout= layout;
+ ht->draw(C, &header);
+ }
+
+ uiLayoutEnd(C, block, layout, &xco, &yco);
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+ }
+
+ /* always as last */
+ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
new file mode 100644
index 00000000000..7d1f8d59552
--- /dev/null
+++ b/source/blender/editors/interface/interface_panel.c
@@ -0,0 +1,1656 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2003-2009 full recode.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* a full doc with API notes can be found in bf-blender/blender/doc/interface_API.txt */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "interface_intern.h"
+
+/*********************** defines and structs ************************/
+
+#define ANIMATION_TIME 0.30
+#define ANIMATION_INTERVAL 0.02
+
+#define PNL_LAST_ADDED 1
+#define PNL_ACTIVE 2
+#define PNL_WAS_ACTIVE 4
+#define PNL_ANIM_ALIGN 8
+
+typedef enum uiHandlePanelState {
+ PANEL_STATE_DRAG,
+ PANEL_STATE_DRAG_SCALE,
+ PANEL_STATE_WAIT_UNTAB,
+ PANEL_STATE_ANIMATION,
+ PANEL_STATE_EXIT
+} uiHandlePanelState;
+
+typedef struct uiHandlePanelData {
+ uiHandlePanelState state;
+
+ /* animation */
+ wmTimer *animtimer;
+ double starttime;
+
+ /* dragging */
+ int startx, starty;
+ int startofsx, startofsy;
+ int startsizex, startsizey;
+} uiHandlePanelData;
+
+static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelState state);
+
+/*********************** space specific code ************************/
+/* temporary code to remove all sbuts stuff from panel code */
+
+static int panel_aligned(ScrArea *sa, ARegion *ar)
+{
+ if(sa->spacetype==SPACE_BUTS && ar->regiontype == RGN_TYPE_WINDOW) {
+ SpaceButs *sbuts= sa->spacedata.first;
+ return sbuts->align;
+ }
+ else if(ar->regiontype==RGN_TYPE_UI)
+ return BUT_VERTICAL;
+
+ return 0;
+}
+
+static int panels_re_align(ScrArea *sa, ARegion *ar, Panel **r_pa)
+{
+ Panel *pa;
+ int active= 0;
+
+ *r_pa= NULL;
+
+ if(sa->spacetype==SPACE_BUTS && ar->regiontype == RGN_TYPE_WINDOW) {
+ SpaceButs *sbuts= sa->spacedata.first;
+
+ if(sbuts->align)
+ if(sbuts->re_align || sbuts->mainbo!=sbuts->mainb || sbuts->tabo!=sbuts->tab[sbuts->mainb])
+ return 1;
+ }
+ else if(ar->regiontype==RGN_TYPE_UI)
+ return 1;
+
+ for(pa=ar->panels.first; pa; pa=pa->next) {
+ if((pa->runtime_flag & PNL_WAS_ACTIVE) && !(pa->runtime_flag & PNL_ACTIVE))
+ return 1;
+ if(!(pa->runtime_flag & PNL_WAS_ACTIVE) && (pa->runtime_flag & PNL_ACTIVE))
+ return 1;
+ if(pa->activedata)
+ active= 1;
+ }
+
+ for(pa=ar->panels.first; pa; pa=pa->next) {
+ if(pa->runtime_flag & PNL_ANIM_ALIGN) {
+ if(!active)
+ *r_pa= pa;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/****************************** panels ******************************/
+
+static void ui_panel_copy_offset(Panel *pa, Panel *papar)
+{
+ /* with respect to sizes... papar is parent */
+
+ pa->ofsx= papar->ofsx;
+ pa->ofsy= papar->ofsy + papar->sizey-pa->sizey;
+}
+
+Panel *uiBeginPanel(ARegion *ar, uiBlock *block, PanelType *pt)
+{
+ Panel *pa, *patab, *palast, *panext;
+ char *panelname= pt->label;
+ char *tabname= pt->label;
+ char *hookname= NULL;
+ int newpanel;
+
+ /* check if Panel exists, then use that one */
+ for(pa=ar->panels.first; pa; pa=pa->next)
+ if(strncmp(pa->panelname, panelname, UI_MAX_NAME_STR)==0)
+ if(strncmp(pa->tabname, tabname, UI_MAX_NAME_STR)==0)
+ break;
+
+ newpanel= (pa == NULL);
+
+ if(!newpanel) {
+ pa->type= pt;
+ }
+ else {
+ /* new panel */
+ pa= MEM_callocN(sizeof(Panel), "new panel");
+ pa->type= pt;
+ BLI_strncpy(pa->panelname, panelname, UI_MAX_NAME_STR);
+ BLI_strncpy(pa->tabname, tabname, UI_MAX_NAME_STR);
+
+ pa->ofsx= PNL_DIST;
+ pa->ofsy= PNL_DIST;
+ pa->sizex= 0;
+ pa->sizey= 0;
+
+ BLI_addtail(&ar->panels, pa);
+
+ /* make new Panel tabbed? */
+ if(hookname) {
+ for(patab= ar->panels.first; patab; patab= patab->next) {
+ if((patab->runtime_flag & PNL_ACTIVE) && patab->paneltab==NULL) {
+ if(strncmp(hookname, patab->panelname, UI_MAX_NAME_STR)==0) {
+ if(strncmp(tabname, patab->tabname, UI_MAX_NAME_STR)==0) {
+ pa->paneltab= patab;
+ ui_panel_copy_offset(pa, patab);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* if a new panel is added, we insert it right after the panel
+ * that was last added. this way new panels are inserted in the
+ * right place between versions */
+ for(palast=ar->panels.first; palast; palast=palast->next)
+ if(palast->runtime_flag & PNL_LAST_ADDED)
+ break;
+
+ if(newpanel) {
+ pa->sortorder= (palast)? palast->sortorder+1: 0;
+
+ for(panext=ar->panels.first; panext; panext=panext->next)
+ if(panext != pa && panext->sortorder >= pa->sortorder)
+ panext->sortorder++;
+ }
+
+ if(palast)
+ palast->runtime_flag &= ~PNL_LAST_ADDED;
+
+ /* assign to block */
+ block->panel= pa;
+ pa->runtime_flag |= PNL_ACTIVE|PNL_LAST_ADDED;
+
+ if(pa->paneltab) return NULL;
+ if(pa->flag & PNL_CLOSED) return NULL;
+
+ /* the 'return 0' above makes this to be in end. otherwise closes panels show wrong title */
+ pa->drawname[0]= 0;
+
+ return pa;
+}
+
+void uiEndPanel(uiBlock *block, int width, int height)
+{
+ Panel *pa= block->panel;
+
+ if(pa->sizex != width || pa->sizey != height) {
+ pa->runtime_flag |= PNL_ANIM_ALIGN;
+ pa->ofsy += pa->sizey-height;
+ }
+
+ pa->sizex= width;
+ pa->sizey= height;
+}
+
+#if 0
+void uiPanelToMouse(const bContext *C, Panel *pa)
+{
+ /* global control over this feature; UI_PNL_TO_MOUSE only called for hotkey panels */
+ if(U.uiflag & USER_PANELPINNED);
+ else if(pa->control & UI_PNL_TO_MOUSE) {
+ int mx, my;
+
+ mx= CTX_wm_window(C)->eventstate->x;
+ my= CTX_wm_window(C)->eventstate->y;
+
+ pa->ofsx= mx-pa->sizex/2;
+ pa->ofsy= my-pa->sizey/2;
+
+ if(pa->flag & PNL_CLOSED) pa->flag &= ~PNL_CLOSED;
+ }
+
+ if(pa->control & UI_PNL_UNSTOW) {
+ if(pa->flag & PNL_CLOSEDY) {
+ pa->flag &= ~PNL_CLOSED;
+ }
+ }
+}
+#endif
+
+/* ofsx/ofsy only used for new panel definitions */
+/* return 1 if visible (create buttons!) */
+int uiNewPanel(const bContext *C, ARegion *ar, uiBlock *block, char *panelname, char *tabname, int ofsx, int ofsy, int sizex, int sizey)
+{
+ Panel *pa;
+
+ /* check if Panel exists, then use that one */
+ for(pa=ar->panels.first; pa; pa=pa->next)
+ if(strncmp(pa->panelname, panelname, UI_MAX_NAME_STR)==0)
+ if(strncmp(pa->tabname, tabname, UI_MAX_NAME_STR)==0)
+ break;
+
+ if(pa) {
+ /* scale correction */
+ if(pa->control & UI_PNL_SCALE);
+ else {
+ pa->sizex= sizex;
+ if(pa->sizey != sizey) {
+ pa->ofsy+= (pa->sizey - sizey); // check uiNewPanelHeight()
+ pa->sizey= sizey;
+ }
+ }
+ }
+ else {
+ /* new panel */
+ pa= MEM_callocN(sizeof(Panel), "new panel");
+ BLI_addtail(&ar->panels, pa);
+ strncpy(pa->panelname, panelname, UI_MAX_NAME_STR);
+ strncpy(pa->tabname, tabname, UI_MAX_NAME_STR);
+
+ pa->ofsx= ofsx & ~(PNL_GRID-1);
+ pa->ofsy= ofsy & ~(PNL_GRID-1);
+ pa->sizex= sizex;
+ pa->sizey= sizey;
+
+#if 0
+ /* make new Panel tabbed? */
+ if(panel_tabbed && group_tabbed) {
+ Panel *papar;
+ for(papar= ar->panels.first; papar; papar= papar->next) {
+ if(papar->active && papar->paneltab==NULL) {
+ if( strncmp(panel_tabbed, papar->panelname, UI_MAX_NAME_STR)==0) {
+ if( strncmp(group_tabbed, papar->tabname, UI_MAX_NAME_STR)==0) {
+ pa->paneltab= papar;
+ copy_panel_offset(pa, papar);
+ break;
+ }
+ }
+ }
+ }
+ }
+#endif
+ }
+
+ block->panel= pa;
+ pa->runtime_flag |= PNL_ACTIVE;
+
+ /* clear ugly globals */
+ // XXX pa->control= pnl_control;
+ // XXX panel_tabbed= group_tabbed= NULL;
+ // XXX pa->control= UI_PNL_TRANSP; // back to default
+
+ if(pa->paneltab) return 0;
+ if(pa->flag & PNL_CLOSED) return 0;
+
+ /* the 'return 0' above makes this to be in end. otherwise closes panels show wrong title */
+ pa->drawname[0]= 0;
+
+ return 1;
+}
+
+void uiNewPanelHeight(uiBlock *block, int sizey)
+{
+ if(sizey<0) sizey= 0;
+
+ if(block->panel) {
+ block->panel->ofsy+= (block->panel->sizey - sizey);
+ block->panel->sizey= sizey;
+ }
+}
+
+void uiNewPanelTitle(uiBlock *block, char *str)
+{
+ if(block->panel)
+ BLI_strncpy(block->panel->drawname, str, UI_MAX_NAME_STR);
+}
+
+static int panel_has_tabs(ARegion *ar, Panel *panel)
+{
+ Panel *pa= ar->panels.first;
+
+ if(panel==NULL) return 0;
+
+ while(pa) {
+ if((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab==panel) {
+ return 1;
+ }
+ pa= pa->next;
+ }
+ return 0;
+}
+
+static void ui_scale_panel_block(uiBlock *block)
+{
+ uiBut *but;
+ float facx= 1.0, facy= 1.0;
+ int centerx= 0, topy=0, tabsy=0;
+
+ if(block->panel==NULL) return;
+
+ /* buttons min/max centered, offset calculated */
+ ui_bounds_block(block);
+
+ if((!block->panel->type) && block->maxx-block->minx > block->panel->sizex - 2*PNL_SAFETY)
+ facx= (block->panel->sizex - (2*PNL_SAFETY))/(block->maxx-block->minx);
+ else
+ centerx= (block->panel->sizex-(block->maxx-block->minx) - 2*PNL_SAFETY)/2;
+
+ // tabsy= PNL_HEADER*panel_has_tabs(block->panel);
+ if((!block->panel->type) && (block->maxy-block->miny) > block->panel->sizey - 2*PNL_SAFETY - tabsy)
+ facy= (block->panel->sizey - (2*PNL_SAFETY) - tabsy)/(block->maxy-block->miny);
+ else
+ topy= (block->panel->sizey- 2*PNL_SAFETY - tabsy) - (block->maxy-block->miny) ;
+
+ for(but= block->buttons.first; but; but=but->next) {
+ but->x1= PNL_SAFETY+centerx+ facx*(but->x1-block->minx);
+ but->y1= PNL_SAFETY+topy + facy*(but->y1-block->miny);
+ but->x2= PNL_SAFETY+centerx+ facx*(but->x2-block->minx);
+ but->y2= PNL_SAFETY+topy + facy*(but->y2-block->miny);
+ if(facx!=1.0) ui_check_but(but); /* for strlen */
+ }
+
+ block->maxx= block->panel->sizex;
+ block->maxy= block->panel->sizey;
+ block->minx= block->miny= 0.0;
+}
+
+// for 'home' key
+void uiPanelsHome(ARegion *ar)
+{
+ Panel *pa;
+ uiBlock *block;
+ View2D *v2d;
+ float minx=10000, maxx= -10000, miny=10000, maxy= -10000;
+ int done=0;
+
+ v2d= &ar->v2d;
+
+ for(pa= ar->panels.first; pa; pa=pa->next) {
+ if((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab==NULL) {
+ done= 1;
+ if(pa->ofsx < minx) minx= pa->ofsx;
+ if(pa->ofsx+pa->sizex > maxx) maxx= pa->ofsx+pa->sizex;
+ if(pa->ofsy < miny) miny= pa->ofsy;
+ if(pa->ofsy+pa->sizey+PNL_HEADER > maxy) maxy= pa->ofsy+pa->sizey+PNL_HEADER;
+ }
+ }
+
+ if(done) {
+ v2d->tot.xmin= minx-PNL_DIST;
+ v2d->tot.xmax= maxx+PNL_DIST;
+ v2d->tot.ymin= miny-PNL_DIST;
+ v2d->tot.ymax= maxy+PNL_DIST;
+ }
+ else {
+ v2d->tot.xmin= 0;
+ v2d->tot.xmax= 1280;
+ v2d->tot.ymin= 0;
+ v2d->tot.ymax= 228;
+
+ /* no panels, but old 'loose' buttons, as in old logic editor */
+ for(block= ar->uiblocks.first; block; block= block->next) {
+ if(block->minx < v2d->tot.xmin) v2d->tot.xmin= block->minx;
+ if(block->maxx > v2d->tot.xmax) v2d->tot.xmax= block->maxx;
+ if(block->miny < v2d->tot.ymin) v2d->tot.ymin= block->miny;
+ if(block->maxy > v2d->tot.ymax) v2d->tot.ymax= block->maxy;
+ }
+ }
+}
+
+// make sure the panels are not outside 'tot' area
+static void ui_panels_update_totrct(ARegion *ar)
+{
+ Panel *pa;
+ uiBlock *block;
+ View2D *v2d;
+ int done=0;
+
+ v2d= &ar->v2d;
+
+ v2d->tot.xmin= 0.0f;
+ v2d->tot.xmax= ar->winx;
+ v2d->tot.ymax= 0.0f;
+ v2d->tot.ymin= -ar->winy;
+
+ for(pa= ar->panels.first; pa; pa=pa->next) {
+ if((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab==NULL) {
+ done= 1;
+
+ if(pa->ofsx < v2d->tot.xmin)
+ v2d->tot.xmin= pa->ofsx;
+ if(pa->ofsx+pa->sizex > v2d->tot.xmax)
+ v2d->tot.xmax= pa->ofsx+pa->sizex;
+ if(pa->ofsy < v2d->tot.ymin)
+ v2d->tot.ymin= pa->ofsy;
+ if(pa->ofsy+pa->sizey+PNL_HEADER > v2d->tot.ymax)
+ v2d->tot.ymax= pa->ofsy+pa->sizey+PNL_HEADER;
+ }
+ }
+
+ if(done==0) {
+ /* no panels, but old 'loose' buttons, as in old logic editor */
+ for(block= ar->uiblocks.first; block; block= block->next) {
+ if(block->minx < v2d->tot.xmin) v2d->tot.xmin= block->minx;
+ if(block->maxx > v2d->tot.xmax) v2d->tot.xmax= block->maxx;
+ if(block->miny < v2d->tot.ymin) v2d->tot.ymin= block->miny;
+ if(block->maxy > v2d->tot.ymax) v2d->tot.ymax= block->maxy;
+ }
+ }
+
+ UI_view2d_totRect_set(v2d, v2d->tot.xmax, v2d->tot.ymin);
+}
+
+uiBlock *uiFindOpenPanelBlockName(ListBase *lb, char *name)
+{
+ uiBlock *block;
+ Panel *pa;
+
+ for(block= lb->first; block; block= block->next) {
+ pa= block->panel;
+
+ if(pa && (pa->runtime_flag & PNL_ACTIVE) && pa->paneltab==NULL) {
+ if(pa->flag & PNL_CLOSED);
+ else if(strncmp(name, pa->panelname, UI_MAX_NAME_STR)==0) break;
+ }
+ }
+
+ return block;
+}
+
+/**************************** drawing *******************************/
+
+/* extern used by previewrender */
+void uiPanelPush(uiBlock *block)
+{
+ glPushMatrix();
+
+ if(block->panel)
+ glTranslatef((float)block->panel->ofsx, (float)block->panel->ofsy, 0.0);
+}
+
+void uiPanelPop(uiBlock *block)
+{
+ glPopMatrix();
+}
+
+/* triangle 'icon' for panel header */
+void ui_draw_tria_icon(float x, float y, char dir)
+{
+ if(dir=='h') {
+ ui_draw_anti_tria(x-1, y, x-1, y+11.0, x+9, y+6.25);
+ }
+ else {
+ ui_draw_anti_tria(x-3, y+10, x+8-1, y+10, x+4.25-2, y);
+ }
+}
+
+/* triangle 'icon' inside rect */
+void ui_draw_tria_rect(rctf *rect, char dir)
+{
+ if(dir=='h') {
+ float half= 0.5f*(rect->ymax - rect->ymin);
+ ui_draw_anti_tria(rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin+half);
+ }
+ else {
+ float half= 0.5f*(rect->xmax - rect->xmin);
+ ui_draw_anti_tria(rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin+half, rect->ymin);
+ }
+}
+
+void ui_draw_anti_x(float x1, float y1, float x2, float y2)
+{
+
+ /* set antialias line */
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+
+ glLineWidth(2.0);
+
+ fdrawline(x1, y1, x2, y2);
+ fdrawline(x1, y2, x2, y1);
+
+ glLineWidth(1.0);
+
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+
+}
+
+/* x 'icon' for panel header */
+static void ui_draw_x_icon(float x, float y)
+{
+ UI_ThemeColor(TH_TEXT_HI);
+
+ ui_draw_anti_x(x, y, x+9.375, y+9.375);
+
+}
+
+#define PNL_ICON 20
+
+static void ui_draw_panel_scalewidget(rcti *rect)
+{
+ float xmin, xmax, dx;
+ float ymin, ymax, dy;
+
+ xmin= rect->xmax-PNL_HEADER+2;
+ xmax= rect->xmax-3;
+ ymin= rect->ymin+3;
+ ymax= rect->ymin+PNL_HEADER-2;
+
+ dx= 0.5f*(xmax-xmin);
+ dy= 0.5f*(ymax-ymin);
+
+ glEnable(GL_BLEND);
+ glColor4ub(255, 255, 255, 50);
+ fdrawline(xmin, ymin, xmax, ymax);
+ fdrawline(xmin+dx, ymin, xmax, ymax-dy);
+
+ glColor4ub(0, 0, 0, 50);
+ fdrawline(xmin, ymin+1, xmax, ymax+1);
+ fdrawline(xmin+dx, ymin+1, xmax, ymax-dy+1);
+ glDisable(GL_BLEND);
+}
+
+static void ui_draw_panel_dragwidget(rctf *rect)
+{
+ float xmin, xmax, dx;
+ float ymin, ymax, dy;
+
+ xmin= rect->xmin;
+ xmax= rect->xmax;
+ ymin= rect->ymin;
+ ymax= rect->ymax;
+
+ dx= 0.333f*(xmax-xmin);
+ dy= 0.333f*(ymax-ymin);
+
+ glEnable(GL_BLEND);
+ glColor4ub(255, 255, 255, 50);
+ fdrawline(xmin, ymax, xmax, ymin);
+ fdrawline(xmin+dx, ymax, xmax, ymin+dy);
+ fdrawline(xmin+2*dx, ymax, xmax, ymin+2*dy);
+
+ glColor4ub(0, 0, 0, 50);
+ fdrawline(xmin, ymax+1, xmax, ymin+1);
+ fdrawline(xmin+dx, ymax+1, xmax, ymin+dy+1);
+ fdrawline(xmin+2*dx, ymax+1, xmax, ymin+2*dy+1);
+ glDisable(GL_BLEND);
+}
+
+
+static void ui_draw_panel_header_style(ARegion *ar, uiStyle *style, uiBlock *block, rcti *rect)
+{
+ Panel *panel= block->panel;
+ Panel *pa;
+ rcti hrect;
+ float width;
+ int a, nr= 1, pnl_icons;
+ char *activename= panel->drawname[0]?panel->drawname:panel->panelname;
+ char *panelname;
+
+ /* count */
+ for(pa= ar->panels.first; pa; pa=pa->next)
+ if(pa->runtime_flag & PNL_ACTIVE)
+ if(pa->paneltab==panel)
+ nr++;
+
+ if(panel->control & UI_PNL_CLOSE) pnl_icons=(2*PNL_ICON+10)/block->aspect;
+ else pnl_icons= (PNL_ICON+10)/block->aspect;
+
+ if(nr==1) {
+
+ /* active tab */
+ /* draw text label */
+ UI_ThemeColor(TH_TEXT);
+
+ hrect= *rect;
+ hrect.xmin= rect->xmin+pnl_icons;
+ uiStyleFontDraw(&style->paneltitle, &hrect, activename);
+
+ return;
+ }
+
+ a= 0;
+ width= (rect->xmax-rect->xmin - 3 - pnl_icons - PNL_ICON)/nr;
+ for(pa= ar->panels.first; pa; pa=pa->next) {
+ panelname= pa->drawname[0]?pa->drawname:pa->panelname;
+
+ if((pa->runtime_flag & PNL_ACTIVE) && (pa==panel || pa->paneltab==panel)) {
+ float col[3];
+
+ UI_GetThemeColor3fv(TH_TEXT, col);
+
+ /* active tab */
+ if(pa==panel)
+ glColor4f(col[0], col[1], col[2], 1.0f);
+ else
+ glColor4f(col[0], col[1], col[2], 0.5f);
+
+ hrect= *rect;
+ hrect.xmin= rect->xmin+pnl_icons + a*width;
+ hrect.xmax= hrect.xmin + width;
+ uiStyleFontDraw(&style->paneltitle, &hrect, panelname);
+
+ a++;
+ }
+ }
+}
+
+static void rectf_scale(rctf *rect, float scale)
+{
+ float centx= 0.5f*(rect->xmin+rect->xmax);
+ float centy= 0.5f*(rect->ymin+rect->ymax);
+ float sizex= 0.5f*scale*(rect->xmax - rect->xmin);
+ float sizey= 0.5f*scale*(rect->ymax - rect->ymin);
+
+ rect->xmin= centx - sizex;
+ rect->xmax= centx + sizex;
+ rect->ymin= centy - sizey;
+ rect->ymax= centy + sizey;
+}
+
+void ui_draw_panel(ARegion *ar, uiStyle *style, uiBlock *block, rcti *rect)
+{
+ Panel *panel= block->panel, *prev;
+ rcti headrect;
+ rctf itemrect;
+ int ofsx;
+
+ if(panel->paneltab) return;
+
+ /* calculate header rect */
+ headrect= *rect;
+ headrect.ymin= headrect.ymax;
+ headrect.ymax= headrect.ymin + floor(PNL_HEADER/block->aspect);
+
+ /* divider only when there's a previous panel */
+ prev= panel->prev;
+ while(prev) {
+ if(prev->runtime_flag & PNL_ACTIVE) break;
+ prev= prev->prev;
+ }
+
+ if(prev) {
+ float minx= rect->xmin+10.0f/block->aspect;
+ float maxx= rect->xmax-10.0f/block->aspect;
+ float y= headrect.ymax;
+
+ glEnable(GL_BLEND);
+ glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
+ fdrawline(minx, y+1, maxx, y+1);
+ glColor4f(1.0f, 1.0f, 1.0f, 0.25f);
+ fdrawline(minx, y, maxx, y);
+ glDisable(GL_BLEND);
+ }
+
+ /* title */
+ if(!(panel->flag & PNL_CLOSEDX)) {
+ ui_draw_panel_header_style(ar, style, block, &headrect);
+
+ /* itemrect smaller */
+ itemrect.xmax= headrect.xmax - 10.0f/block->aspect;
+ itemrect.xmin= itemrect.xmax - (headrect.ymax-headrect.ymin);
+ itemrect.ymin= headrect.ymin;
+ itemrect.ymax= headrect.ymax;
+ rectf_scale(&itemrect, 0.8f);
+ ui_draw_panel_dragwidget(&itemrect);
+ }
+
+ /* if the panel is minimized vertically:
+ * (------)
+ */
+ if(panel->flag & PNL_CLOSEDY) {
+
+
+ /* if it's being overlapped by a panel being dragged */
+ if(panel->flag & PNL_OVERLAP) {
+ UI_ThemeColor(TH_TEXT_HI);
+ uiRoundRect(rect->xmin, rect->ymax, rect->xmax, rect->ymax+PNL_HEADER, 8);
+ }
+
+ }
+ else if(panel->flag & PNL_CLOSEDX) {
+
+ }
+ /* an open panel */
+ else {
+
+ /* in some occasions, draw a border */
+ if(panel->flag & PNL_SELECT) {
+ if(panel->control & UI_PNL_SOLID) uiSetRoundBox(15);
+ else uiSetRoundBox(3);
+
+ UI_ThemeColorShade(TH_HEADER, -120);
+ uiRoundRect(rect->xmin, rect->ymin, rect->xmax, headrect.ymax+1, 8);
+ }
+ if(panel->flag & PNL_OVERLAP) {
+ if(panel->control & UI_PNL_SOLID) uiSetRoundBox(15);
+ else uiSetRoundBox(3);
+
+ UI_ThemeColor(TH_TEXT_HI);
+ uiRoundRect(rect->xmin, rect->ymin, rect->xmax, headrect.ymax+1, 8);
+ }
+
+ if(panel->control & UI_PNL_SCALE)
+ ui_draw_panel_scalewidget(rect);
+ }
+
+ /* draw optional close icon */
+
+ ofsx= 6;
+ if(panel->control & UI_PNL_CLOSE) {
+
+ ui_draw_x_icon(rect->xmin+2+ofsx, rect->ymax+2);
+ ofsx= 22;
+ }
+
+ /* draw collapse icon */
+ UI_ThemeColor(TH_TEXT);
+
+ /* itemrect smaller */
+ itemrect.xmin= headrect.xmin + 10.0f/block->aspect;
+ itemrect.xmax= itemrect.xmin + (headrect.ymax-headrect.ymin);
+ itemrect.ymin= headrect.ymin;
+ itemrect.ymax= headrect.ymax;
+
+ rectf_scale(&itemrect, 0.7f);
+
+ if(panel->flag & PNL_CLOSEDY)
+ ui_draw_tria_rect(&itemrect, 'h');
+ else if(panel->flag & PNL_CLOSEDX)
+ ui_draw_tria_rect(&itemrect, 'h');
+ else
+ ui_draw_tria_rect(&itemrect, 'v');
+
+
+}
+
+/************************** panel alignment *************************/
+
+/* this function is needed because uiBlock and Panel itself dont
+change sizey or location when closed */
+static int get_panel_real_ofsy(Panel *pa)
+{
+ if(pa->flag & PNL_CLOSEDY) return pa->ofsy+pa->sizey;
+ else if(pa->paneltab && (pa->paneltab->flag & PNL_CLOSEDY)) return pa->ofsy+pa->sizey;
+ else if(pa->paneltab) return pa->paneltab->ofsy;
+ else return pa->ofsy;
+}
+
+static int get_panel_real_ofsx(Panel *pa)
+{
+ if(pa->flag & PNL_CLOSEDX) return pa->ofsx+PNL_HEADER;
+ else if(pa->paneltab && (pa->paneltab->flag & PNL_CLOSEDX)) return pa->ofsx+PNL_HEADER;
+ else return pa->ofsx+pa->sizex;
+}
+
+typedef struct PanelSort {
+ Panel *pa, *orig;
+} PanelSort;
+
+/* note about sorting;
+ the sortorder has a lower value for new panels being added.
+ however, that only works to insert a single panel, when more new panels get
+ added the coordinates of existing panels and the previously stored to-be-insterted
+ panels do not match for sorting */
+
+static int find_leftmost_panel(const void *a1, const void *a2)
+{
+ const PanelSort *ps1=a1, *ps2=a2;
+
+ if(ps1->pa->ofsx > ps2->pa->ofsx) return 1;
+ else if(ps1->pa->ofsx < ps2->pa->ofsx) return -1;
+ else if(ps1->pa->sortorder > ps2->pa->sortorder) return 1;
+ else if(ps1->pa->sortorder < ps2->pa->sortorder) return -1;
+
+ return 0;
+}
+
+
+static int find_highest_panel(const void *a1, const void *a2)
+{
+ const PanelSort *ps1=a1, *ps2=a2;
+
+ if(ps1->pa->ofsy+ps1->pa->sizey < ps2->pa->ofsy+ps2->pa->sizey) return 1;
+ else if(ps1->pa->ofsy+ps1->pa->sizey > ps2->pa->ofsy+ps2->pa->sizey) return -1;
+ else if(ps1->pa->sortorder > ps2->pa->sortorder) return 1;
+ else if(ps1->pa->sortorder < ps2->pa->sortorder) return -1;
+
+ return 0;
+}
+
+static int compare_panel(const void *a1, const void *a2)
+{
+ const PanelSort *ps1=a1, *ps2=a2;
+
+ if(ps1->pa->sortorder > ps2->pa->sortorder) return 1;
+ else if(ps1->pa->sortorder < ps2->pa->sortorder) return -1;
+
+ return 0;
+}
+
+/* this doesnt draw */
+/* returns 1 when it did something */
+int uiAlignPanelStep(ScrArea *sa, ARegion *ar, float fac, int drag)
+{
+ Panel *pa;
+ PanelSort *ps, *panelsort, *psnext;
+ int a, tot=0, done;
+ int align= panel_aligned(sa, ar);
+
+ /* count active, not tabbed panels */
+ for(pa= ar->panels.first; pa; pa= pa->next)
+ if((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab==NULL)
+ tot++;
+
+ if(tot==0) return 0;
+
+ /* extra; change close direction? */
+ for(pa= ar->panels.first; pa; pa= pa->next) {
+ if((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab==NULL) {
+ if((pa->flag & PNL_CLOSEDX) && (align==BUT_VERTICAL))
+ pa->flag ^= PNL_CLOSED;
+ else if((pa->flag & PNL_CLOSEDY) && (align==BUT_HORIZONTAL))
+ pa->flag ^= PNL_CLOSED;
+ }
+ }
+
+ /* sort panels */
+ panelsort= MEM_callocN(tot*sizeof(PanelSort), "panelsort");
+
+ ps= panelsort;
+ for(pa= ar->panels.first; pa; pa= pa->next) {
+ if((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab==NULL) {
+ ps->pa= MEM_dupallocN(pa);
+ ps->orig= pa;
+ ps++;
+ }
+ }
+
+ if(drag) {
+ /* while we are dragging, we sort on location and update sortorder */
+ if(align==BUT_VERTICAL)
+ qsort(panelsort, tot, sizeof(PanelSort), find_highest_panel);
+ else
+ qsort(panelsort, tot, sizeof(PanelSort), find_leftmost_panel);
+
+ for(ps=panelsort, a=0; a<tot; a++, ps++)
+ ps->orig->sortorder= a;
+ }
+ else
+ /* otherwise use sortorder */
+ qsort(panelsort, tot, sizeof(PanelSort), compare_panel);
+
+ /* no smart other default start loc! this keeps switching f5/f6/etc compatible */
+ ps= panelsort;
+ ps->pa->ofsx= PNL_DIST;
+ ps->pa->ofsy= -ps->pa->sizey-PNL_HEADER-PNL_DIST;
+
+ for(a=0; a<tot-1; a++, ps++) {
+ psnext= ps+1;
+
+ if(align==BUT_VERTICAL) {
+ psnext->pa->ofsx= ps->pa->ofsx;
+ psnext->pa->ofsy= get_panel_real_ofsy(ps->pa) - psnext->pa->sizey-PNL_HEADER-PNL_DIST;
+ }
+ else {
+ psnext->pa->ofsx= get_panel_real_ofsx(ps->pa)+PNL_DIST;
+ psnext->pa->ofsy= ps->pa->ofsy + ps->pa->sizey - psnext->pa->sizey;
+ }
+ }
+
+ /* we interpolate */
+ done= 0;
+ ps= panelsort;
+ for(a=0; a<tot; a++, ps++) {
+ if((ps->pa->flag & PNL_SELECT)==0) {
+ if((ps->orig->ofsx != ps->pa->ofsx) || (ps->orig->ofsy != ps->pa->ofsy)) {
+ ps->orig->ofsx= floor(0.5 + fac*ps->pa->ofsx + (1.0-fac)*ps->orig->ofsx);
+ ps->orig->ofsy= floor(0.5 + fac*ps->pa->ofsy + (1.0-fac)*ps->orig->ofsy);
+ done= 1;
+ }
+ }
+ }
+
+ /* copy locations to tabs */
+ for(pa= ar->panels.first; pa; pa= pa->next)
+ if(pa->paneltab && (pa->runtime_flag & PNL_ACTIVE))
+ ui_panel_copy_offset(pa, pa->paneltab);
+
+ /* free panelsort array */
+ for(ps= panelsort, a=0; a<tot; a++, ps++)
+ MEM_freeN(ps->pa);
+ MEM_freeN(panelsort);
+
+ return done;
+}
+
+
+static void ui_do_animate(const bContext *C, Panel *panel)
+{
+ uiHandlePanelData *data= panel->activedata;
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= CTX_wm_region(C);
+ float fac;
+
+ fac= (PIL_check_seconds_timer()-data->starttime)/ANIMATION_TIME;
+ fac= sqrt(fac);
+ fac= MIN2(fac, 1.0f);
+
+ /* for max 1 second, interpolate positions */
+ if(uiAlignPanelStep(sa, ar, fac, 0))
+ ED_region_tag_redraw(ar);
+ else
+ fac= 1.0f;
+
+ if(fac >= 1.0f) {
+ panel_activate_state(C, panel, PANEL_STATE_EXIT);
+ return;
+ }
+}
+
+void uiBeginPanels(const bContext *C, ARegion *ar)
+{
+ Panel *pa;
+
+ /* set all panels as inactive, so that at the end we know
+ * which ones were used */
+ for(pa=ar->panels.first; pa; pa=pa->next) {
+ if(pa->runtime_flag & PNL_ACTIVE)
+ pa->runtime_flag= PNL_WAS_ACTIVE;
+ else
+ pa->runtime_flag= 0;
+ }
+}
+
+/* only draws blocks with panels */
+void uiEndPanels(const bContext *C, ARegion *ar)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ uiBlock *block;
+ Panel *panot, *panew, *patest, *pa;
+
+ /* scaling contents */
+ for(block= ar->uiblocks.first; block; block= block->next)
+ if(block->active && block->panel)
+ ui_scale_panel_block(block);
+
+ /* consistancy; are panels not made, whilst they have tabs */
+ for(panot= ar->panels.first; panot; panot= panot->next) {
+ if((panot->runtime_flag & PNL_ACTIVE)==0) { // not made
+
+ for(panew= ar->panels.first; panew; panew= panew->next) {
+ if((panew->runtime_flag & PNL_ACTIVE)) {
+ if(panew->paneltab==panot) { // panew is tab in notmade pa
+ break;
+ }
+ }
+ }
+ /* now panew can become the new parent, check all other tabs */
+ if(panew) {
+ for(patest= ar->panels.first; patest; patest= patest->next) {
+ if(patest->paneltab == panot) {
+ patest->paneltab= panew;
+ }
+ }
+ panot->paneltab= panew;
+ panew->paneltab= NULL;
+ ED_region_tag_redraw(ar); // the buttons panew were not made
+ }
+ }
+ }
+
+ /* re-align, possibly with animation */
+ if(panels_re_align(sa, ar, &pa)) {
+ if(pa)
+ panel_activate_state(C, pa, PANEL_STATE_ANIMATION);
+ else
+ uiAlignPanelStep(sa, ar, 1.0, 0);
+ }
+
+ if(sa->spacetype!=SPACE_BUTS) {
+#if 0 // XXX make float panel exception
+ SpaceLink *sl= sa->spacedata.first;
+ for(block= ar->uiblocks.first; block; block= block->next) {
+ if(block->active && block->panel && block->panel->active && block->panel->paneltab == NULL) {
+ float dx=0.0, dy=0.0, minx, miny, maxx, maxy, miny_panel;
+
+ minx= sl->blockscale*block->panel->ofsx;
+ maxx= sl->blockscale*(block->panel->ofsx+block->panel->sizex);
+ miny= sl->blockscale*(block->panel->ofsy+block->panel->sizey);
+ maxy= sl->blockscale*(block->panel->ofsy+block->panel->sizey+PNL_HEADER);
+ miny_panel= sl->blockscale*(block->panel->ofsy);
+
+ /* check to see if snapped panels have been left out in the open by resizing a window
+ * and if so, offset them back to where they belong */
+ if (block->panel->snap) {
+ if (((block->panel->snap) & PNL_SNAP_RIGHT) &&
+ (maxx < (float)sa->winx)) {
+
+ dx = sa->winx-maxx;
+ block->panel->ofsx+= dx/sl->blockscale;
+ }
+ if (((block->panel->snap) & PNL_SNAP_TOP) &&
+ (maxy < (float)sa->winy)) {
+
+ dy = sa->winy-maxy;
+ block->panel->ofsy+= dy/sl->blockscale;
+ }
+
+ /* reset these vars with updated panel offset distances */
+ minx= sl->blockscale*block->panel->ofsx;
+ maxx= sl->blockscale*(block->panel->ofsx+block->panel->sizex);
+ miny= sl->blockscale*(block->panel->ofsy+block->panel->sizey);
+ maxy= sl->blockscale*(block->panel->ofsy+block->panel->sizey+PNL_HEADER);
+ miny_panel= sl->blockscale*(block->panel->ofsy);
+ } else
+ /* reset to no snapping */
+ block->panel->snap = PNL_SNAP_NONE;
+
+
+ /* clip panels (headers) for non-butspace situations (maybe make optimized event later) */
+
+ /* check left and right edges */
+ if (minx < PNL_SNAP_DIST) {
+ dx = -minx;
+ block->panel->snap |= PNL_SNAP_LEFT;
+ }
+ else if (maxx > ((float)sa->winx - PNL_SNAP_DIST)) {
+ dx= sa->winx-maxx;
+ block->panel->snap |= PNL_SNAP_RIGHT;
+ }
+ if(minx + dx < 0.0) dx= -minx; // when panel cant fit, put it fixed here
+
+ /* check top and bottom edges */
+ if ((miny_panel < PNL_SNAP_DIST) && (miny_panel > -PNL_SNAP_DIST)) {
+ dy= -miny_panel;
+ block->panel->snap |= PNL_SNAP_BOTTOM;
+ }
+ if(miny < PNL_SNAP_DIST) {
+ dy= -miny;
+ block->panel->snap |= PNL_SNAP_BOTTOM;
+ }
+ else if(maxy > ((float)sa->winy - PNL_SNAP_DIST)) {
+ dy= sa->winy-maxy;
+ block->panel->snap |= PNL_SNAP_TOP;
+ }
+ if(miny + dy < 0.0) dy= -miny; // when panel cant fit, put it fixed here
+
+
+ block->panel->ofsx+= dx/sl->blockscale;
+ block->panel->ofsy+= dy/sl->blockscale;
+
+ /* copy locations */
+ for(patest= ar->panels.first; patest; patest= patest->next) {
+ if(patest->paneltab==block->panel) ui_panel_copy_offset(patest, block->panel);
+ }
+
+ }
+ }
+#endif
+ }
+
+ /* update v2d->totrct and update view */
+ ui_panels_update_totrct(ar);
+ UI_view2d_view_restore(C);
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ /* draw panels, selected on top */
+ for(block= ar->uiblocks.first; block; block=block->next) {
+ if(block->active && block->panel && !(block->panel->flag & PNL_SELECT)) {
+ uiDrawBlock(C, block);
+ }
+ }
+
+ for(block= ar->uiblocks.first; block; block=block->next) {
+ if(block->active && block->panel && (block->panel->flag & PNL_SELECT)) {
+ uiDrawBlock(C, block);
+ }
+ }
+}
+
+/* ------------ panel merging ---------------- */
+
+static void check_panel_overlap(ARegion *ar, Panel *panel)
+{
+ Panel *pa;
+
+ /* also called with panel==NULL for clear */
+
+ for(pa=ar->panels.first; pa; pa=pa->next) {
+ pa->flag &= ~PNL_OVERLAP;
+ if(panel && (pa != panel)) {
+ if(pa->paneltab==NULL && (pa->runtime_flag & PNL_ACTIVE)) {
+ float safex= 0.2, safey= 0.2;
+
+ if(pa->flag & PNL_CLOSEDX) safex= 0.05;
+ else if(pa->flag & PNL_CLOSEDY) safey= 0.05;
+ else if(panel->flag & PNL_CLOSEDX) safex= 0.05;
+ else if(panel->flag & PNL_CLOSEDY) safey= 0.05;
+
+ if(pa->ofsx > panel->ofsx- safex*panel->sizex)
+ if(pa->ofsx+pa->sizex < panel->ofsx+ (1.0+safex)*panel->sizex)
+ if(pa->ofsy > panel->ofsy- safey*panel->sizey)
+ if(pa->ofsy+pa->sizey < panel->ofsy+ (1.0+safey)*panel->sizey)
+ pa->flag |= PNL_OVERLAP;
+ }
+ }
+ }
+}
+
+static void test_add_new_tabs(ARegion *ar)
+{
+ Panel *pa, *pasel=NULL, *palap=NULL;
+ /* search selected and overlapped panel */
+
+ pa= ar->panels.first;
+ while(pa) {
+ if(pa->runtime_flag & PNL_ACTIVE) {
+ if(pa->flag & PNL_SELECT) pasel= pa;
+ if(pa->flag & PNL_OVERLAP) palap= pa;
+ }
+ pa= pa->next;
+ }
+
+ if(pasel && palap==NULL) {
+
+ /* copy locations */
+ pa= ar->panels.first;
+ while(pa) {
+ if(pa->paneltab==pasel) {
+ ui_panel_copy_offset(pa, pasel);
+ }
+ pa= pa->next;
+ }
+ }
+
+ if(pasel==NULL || palap==NULL) return;
+
+ /* the overlapped panel becomes a tab */
+ palap->paneltab= pasel;
+
+ /* the selected panel gets coords of overlapped one */
+ ui_panel_copy_offset(pasel, palap);
+
+ /* and its tabs */
+ pa= ar->panels.first;
+ while(pa) {
+ if(pa->paneltab == pasel) {
+ ui_panel_copy_offset(pa, palap);
+ }
+ pa= pa->next;
+ }
+
+ /* but, the overlapped panel already can have tabs too! */
+ pa= ar->panels.first;
+ while(pa) {
+ if(pa->paneltab == palap) {
+ pa->paneltab = pasel;
+ }
+ pa= pa->next;
+ }
+}
+
+/************************ panel dragging ****************************/
+
+static void ui_do_drag(const bContext *C, wmEvent *event, Panel *panel)
+{
+ uiHandlePanelData *data= panel->activedata;
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= CTX_wm_region(C);
+ short align= panel_aligned(sa, ar), dx=0, dy=0;
+
+ /* first clip for window, no dragging outside */
+ if(!BLI_in_rcti(&ar->winrct, event->x, event->y))
+ return;
+
+ dx= (event->x-data->startx) & ~(PNL_GRID-1);
+ dy= (event->y-data->starty) & ~(PNL_GRID-1);
+
+ if(data->state == PANEL_STATE_DRAG_SCALE) {
+ panel->sizex = MAX2(data->startsizex+dx, UI_PANEL_MINX);
+
+ if(data->startsizey-dy < UI_PANEL_MINY)
+ dy= -UI_PANEL_MINY+data->startsizey;
+
+ panel->sizey= data->startsizey-dy;
+ panel->ofsy= data->startofsy+dy;
+ }
+ else {
+ /* reset the panel snapping, to allow dragging away from snapped edges */
+ panel->snap = PNL_SNAP_NONE;
+
+ panel->ofsx = data->startofsx+dx;
+ panel->ofsy = data->startofsy+dy;
+ check_panel_overlap(ar, panel);
+
+ if(align) uiAlignPanelStep(sa, ar, 0.2, 1);
+ }
+
+ ED_region_tag_redraw(ar);
+}
+
+static void ui_do_untab(const bContext *C, wmEvent *event, Panel *panel)
+{
+ uiHandlePanelData *data= panel->activedata;
+ ARegion *ar= CTX_wm_region(C);
+ Panel *pa, *panew= NULL;
+ int nr;
+
+ /* wait until a threshold is passed to untab */
+ if(abs(event->x-data->startx) + abs(event->y-data->starty) > 6) {
+ /* find new parent panel */
+ nr= 0;
+ for(pa= ar->panels.first; pa; pa=pa->next) {
+ if(pa->paneltab==panel) {
+ panew= pa;
+ nr++;
+ }
+ }
+
+ /* make old tabs point to panew */
+ panew->paneltab= NULL;
+
+ for(pa= ar->panels.first; pa; pa=pa->next)
+ if(pa->paneltab==panel)
+ pa->paneltab= panew;
+
+ panel_activate_state(C, panel, PANEL_STATE_DRAG);
+ }
+}
+
+/******************* region level panel interaction *****************/
+
+static void panel_clicked_tabs(const bContext *C, ScrArea *sa, ARegion *ar, uiBlock *block, int mousex)
+{
+ Panel *pa, *tabsel=NULL, *panel= block->panel;
+ int nr= 1, a, width, ofsx;
+
+ ofsx= PNL_ICON;
+ if(block->panel->type && (block->panel->control & UI_PNL_CLOSE)) ofsx+= PNL_ICON;
+
+ /* count */
+ for(pa= ar->panels.first; pa; pa=pa->next)
+ if(pa!=panel)
+ if((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab==panel)
+ nr++;
+
+ if(nr==1) return;
+
+ /* find clicked tab, mouse in panel coords */
+ a= 0;
+ width= (int)((float)(panel->sizex - ofsx-10)/nr);
+ pa= ar->panels.first;
+ while(pa) {
+ if(pa==panel || ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab==panel)) {
+ if((mousex > ofsx+a*width) && (mousex < ofsx+(a+1)*width)) {
+ tabsel= pa;
+ break;
+ }
+ a++;
+ }
+ pa= pa->next;
+ }
+
+ if(tabsel) {
+ if(tabsel == panel) {
+ panel_activate_state(C, panel, PANEL_STATE_WAIT_UNTAB);
+ }
+ else {
+ /* tabsel now becomes parent for all others */
+ panel->paneltab= tabsel;
+ tabsel->paneltab= NULL;
+
+ pa= ar->panels.first;
+ while(pa) {
+ if(pa->paneltab == panel) pa->paneltab = tabsel;
+ pa= pa->next;
+ }
+
+ /* copy locations to tabs */
+ for(pa= ar->panels.first; pa; pa= pa->next) {
+ if(pa->paneltab && pa->runtime_flag & PNL_ACTIVE) {
+ ui_panel_copy_offset(pa, pa->paneltab);
+ }
+ }
+
+ /* panels now differ size.. */
+ if(panel_aligned(sa, ar))
+ panel_activate_state(C, tabsel, PANEL_STATE_ANIMATION);
+
+ ED_region_tag_redraw(ar);
+ }
+ }
+
+}
+
+/* this function is supposed to call general window drawing too */
+/* also it supposes a block has panel, and isnt a menu */
+static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, int my)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= CTX_wm_region(C);
+ Panel *pa;
+ int align= panel_aligned(sa, ar), button= 0;
+
+ /* mouse coordinates in panel space! */
+
+ /* XXX weak code, currently it assumes layout style for location of widgets */
+
+ /* check open/collapsed button */
+ if(block->panel->flag & PNL_CLOSEDX) {
+ if(my >= block->maxy) button= 1;
+ }
+ else if(block->panel->control & UI_PNL_CLOSE) {
+ if(mx <= block->minx+10+PNL_ICON-2) button= 2;
+ else if(mx <= block->minx+10+2*PNL_ICON+2) button= 1;
+ }
+ else if(mx <= block->minx+10+PNL_ICON+2) {
+ button= 1;
+ }
+
+ if(button) {
+ if(button==2) { // close
+ ED_region_tag_redraw(ar);
+ }
+ else { // collapse
+ if(block->panel->flag & PNL_CLOSED) {
+ block->panel->flag &= ~PNL_CLOSED;
+ /* snap back up so full panel aligns with screen edge */
+ if (block->panel->snap & PNL_SNAP_BOTTOM)
+ block->panel->ofsy= 0;
+ }
+ else if(align==BUT_HORIZONTAL) {
+ block->panel->flag |= PNL_CLOSEDX;
+ }
+ else {
+ /* snap down to bottom screen edge*/
+ block->panel->flag |= PNL_CLOSEDY;
+ if (block->panel->snap & PNL_SNAP_BOTTOM)
+ block->panel->ofsy= -block->panel->sizey;
+ }
+
+ for(pa= ar->panels.first; pa; pa= pa->next) {
+ if(pa->paneltab==block->panel) {
+ if(block->panel->flag & PNL_CLOSED) pa->flag |= PNL_CLOSED;
+ else pa->flag &= ~PNL_CLOSED;
+ }
+ }
+ }
+
+ if(align)
+ panel_activate_state(C, block->panel, PANEL_STATE_ANIMATION);
+ else
+ ED_region_tag_redraw(ar);
+ }
+ else if(block->panel->flag & PNL_CLOSED) {
+ panel_activate_state(C, block->panel, PANEL_STATE_DRAG);
+ }
+ /* check if clicked in tabbed area */
+ else if(mx < block->maxx-PNL_ICON-3 && panel_has_tabs(ar, block->panel)) {
+ panel_clicked_tabs(C, sa, ar, block, mx);
+ }
+ else {
+ panel_activate_state(C, block->panel, PANEL_STATE_DRAG);
+ }
+}
+
+int ui_handler_panel_region(bContext *C, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ uiBlock *block;
+ int retval, mx, my, inside_header= 0, inside_scale= 0, inside;
+
+ retval= WM_UI_HANDLER_CONTINUE;
+
+ for(block=ar->uiblocks.last; block; block=block->prev) {
+ mx= event->x;
+ my= event->y;
+ ui_window_to_block(ar, block, &mx, &my);
+
+ /* check if inside boundbox */
+ inside= 0;
+
+ if(block->panel && block->panel->paneltab==NULL)
+ if(block->minx <= mx && block->maxx >= mx)
+ if(block->miny <= my && block->maxy+PNL_HEADER >= my)
+ inside= 1;
+
+ if(inside) {
+ /* clicked at panel header? */
+ if(block->panel->flag & PNL_CLOSEDX) {
+ if(block->minx <= mx && block->minx+PNL_HEADER >= mx)
+ inside_header= 1;
+ }
+ else if((block->maxy <= my) && (block->maxy+PNL_HEADER >= my)) {
+ inside_header= 1;
+ }
+ else if(block->panel->control & UI_PNL_SCALE) {
+ if(block->maxx-PNL_HEADER <= mx)
+ if(block->miny+PNL_HEADER >= my)
+ inside_scale= 1;
+ }
+
+ if(event->val==KM_PRESS) {
+ if(event->type == LEFTMOUSE) {
+ if(inside_header) {
+ ui_handle_panel_header(C, block, mx, my);
+ break;
+ }
+ else if(inside_scale && !(block->panel->flag & PNL_CLOSED)) {
+ panel_activate_state(C, block->panel, PANEL_STATE_DRAG_SCALE);
+ break;
+ }
+ }
+ else if(event->type == ESCKEY) {
+ /*XXX 2.50 if(block->handler) {
+ rem_blockhandler(sa, block->handler);
+ ED_region_tag_redraw(ar);
+ retval= WM_UI_HANDLER_BREAK;
+ }*/
+ }
+ else if(event->type==PADPLUSKEY || event->type==PADMINUS) {
+ int zoom=0;
+
+ /* if panel is closed, only zoom if mouse is over the header */
+ if (block->panel->flag & (PNL_CLOSEDX|PNL_CLOSEDY)) {
+ if (inside_header)
+ zoom=1;
+ }
+ else
+ zoom=1;
+
+#if 0 // XXX make float panel exception?
+ if(zoom) {
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceLink *sl= sa->spacedata.first;
+
+ if(sa->spacetype!=SPACE_BUTS) {
+ if(!(block->panel->control & UI_PNL_SCALE)) {
+ if(event->type==PADPLUSKEY) sl->blockscale+= 0.1;
+ else sl->blockscale-= 0.1;
+ CLAMP(sl->blockscale, 0.6, 1.0);
+
+ ED_region_tag_redraw(ar);
+ retval= WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
+#endif
+ }
+ }
+ }
+ }
+
+ return retval;
+}
+
+/**************** window level modal panel interaction **************/
+
+static int ui_handler_panel(bContext *C, wmEvent *event, void *userdata)
+{
+ Panel *panel= userdata;
+ uiHandlePanelData *data= panel->activedata;
+
+ /* verify if we can stop */
+ if(event->type == LEFTMOUSE && event->val!=KM_PRESS) {
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= CTX_wm_region(C);
+ int align= panel_aligned(sa, ar);
+
+ if(align)
+ panel_activate_state(C, panel, PANEL_STATE_ANIMATION);
+ else
+ panel_activate_state(C, panel, PANEL_STATE_EXIT);
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if(event->type == MOUSEMOVE) {
+ if(data->state == PANEL_STATE_WAIT_UNTAB)
+ ui_do_untab(C, event, panel);
+ else if(data->state == PANEL_STATE_DRAG)
+ ui_do_drag(C, event, panel);
+ }
+ else if(event->type == TIMER && event->customdata == data->animtimer) {
+ if(data->state == PANEL_STATE_ANIMATION)
+ ui_do_animate(C, panel);
+ else if(data->state == PANEL_STATE_DRAG)
+ ui_do_drag(C, event, panel);
+ }
+
+ data= panel->activedata;
+
+ if(data && data->state == PANEL_STATE_ANIMATION)
+ return WM_UI_HANDLER_CONTINUE;
+ else
+ return WM_UI_HANDLER_BREAK;
+}
+
+static void ui_handler_remove_panel(bContext *C, void *userdata)
+{
+ Panel *pa= userdata;
+
+ panel_activate_state(C, pa, PANEL_STATE_EXIT);
+}
+
+static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelState state)
+{
+ uiHandlePanelData *data= pa->activedata;
+ wmWindow *win= CTX_wm_window(C);
+ ARegion *ar= CTX_wm_region(C);
+
+ if(data && data->state == state)
+ return;
+
+ if(state == PANEL_STATE_EXIT || state == PANEL_STATE_ANIMATION) {
+ if(data && data->state != PANEL_STATE_ANIMATION) {
+ test_add_new_tabs(ar); // also copies locations of tabs in dragged panel
+ check_panel_overlap(ar, NULL); // clears
+ }
+
+ pa->flag &= ~PNL_SELECT;
+ }
+ else
+ pa->flag |= PNL_SELECT;
+
+ if(data && data->animtimer) {
+ WM_event_remove_window_timer(win, data->animtimer);
+ data->animtimer= NULL;
+ }
+
+ if(state == PANEL_STATE_EXIT) {
+ MEM_freeN(data);
+ pa->activedata= NULL;
+
+ WM_event_remove_ui_handler(&win->handlers, ui_handler_panel, ui_handler_remove_panel, pa);
+ }
+ else {
+ if(!data) {
+ data= MEM_callocN(sizeof(uiHandlePanelData), "uiHandlePanelData");
+ pa->activedata= data;
+
+ WM_event_add_ui_handler(C, &win->handlers, ui_handler_panel, ui_handler_remove_panel, pa);
+ }
+
+ if(ELEM(state, PANEL_STATE_ANIMATION, PANEL_STATE_DRAG))
+ data->animtimer= WM_event_add_window_timer(win, TIMER, ANIMATION_INTERVAL);
+
+ data->state= state;
+ data->startx= win->eventstate->x;
+ data->starty= win->eventstate->y;
+ data->startofsx= pa->ofsx;
+ data->startofsy= pa->ofsy;
+ data->startsizex= pa->sizex;
+ data->startsizey= pa->sizey;
+ data->starttime= PIL_check_seconds_timer();
+ }
+
+ ED_region_tag_redraw(ar);
+
+ /* XXX exception handling, 3d window preview panel */
+ /* if(block->drawextra==BIF_view3d_previewdraw)
+ BIF_view3d_previewrender_clear(curarea);*/
+
+ /* XXX exception handling, 3d window preview panel */
+ /* if(block->drawextra==BIF_view3d_previewdraw)
+ BIF_view3d_previewrender_signal(curarea, PR_DISPRECT);
+ else if(strcmp(block->name, "image_panel_preview")==0)
+ image_preview_event(2); */
+}
+
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
new file mode 100644
index 00000000000..181513b58bc
--- /dev/null
+++ b/source/blender/editors/interface/interface_regions.c
@@ -0,0 +1,2389 @@
+/**
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_view2d_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h"
+
+#include "BKE_context.h"
+#include "BKE_report.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "wm_draw.h"
+#include "wm_subwindow.h"
+#include "wm_window.h"
+
+#include "RNA_access.h"
+
+#include "BIF_gl.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "BLF_api.h"
+
+#include "ED_screen.h"
+
+#include "interface_intern.h"
+
+#define MENU_BUTTON_HEIGHT 20
+#define MENU_SEPR_HEIGHT 6
+#define B_NOP -1
+#define MENU_SHADOW_SIDE 8
+#define MENU_SHADOW_BOTTOM 10
+#define MENU_TOP 8
+
+/*********************** Menu Data Parsing ********************* */
+
+typedef struct {
+ char *str;
+ int retval;
+ int icon;
+} MenuEntry;
+
+typedef struct {
+ char *instr;
+ char *title;
+ int titleicon;
+
+ 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->titleicon= 0;
+ md->items= NULL;
+ md->nitems= md->itemssize= 0;
+
+ return md;
+}
+
+static void menudata_set_title(MenuData *md, char *title, int titleicon)
+{
+ if (!md->title)
+ md->title= title;
+ if (!md->titleicon)
+ md->titleicon= titleicon;
+}
+
+static void menudata_add_item(MenuData *md, char *str, int retval, int icon)
+{
+ 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->items[md->nitems].icon= icon;
+ md->nitems++;
+}
+
+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()
+ */
+MenuData *decompose_menu_string(char *str)
+{
+ char *instr= BLI_strdup(str);
+ MenuData *md= menudata_new(instr);
+ char *nitem= NULL, *s= instr;
+ int nicon=0, 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 (s[1]=='i') {
+ nicon= atoi(s+2);
+
+ *s= '\0';
+ s++;
+ }
+ } else if (c=='|' || c=='\0') {
+ if (nitem) {
+ *s= '\0';
+
+ if (nitem_is_title) {
+ menudata_set_title(md, nitem, nicon);
+ nitem_is_title= 0;
+ } else {
+ /* prevent separator to get a value */
+ if(nitem[0]=='%' && nitem[1]=='l')
+ menudata_add_item(md, nitem, -1, nicon);
+ else
+ menudata_add_item(md, nitem, nretval, nicon);
+ nretval= md->nitems+1;
+ }
+
+ nitem= NULL;
+ nicon= 0;
+ }
+
+ if (c=='\0')
+ break;
+ } else if (!nitem)
+ nitem= s;
+
+ s++;
+ }
+
+ return md;
+}
+
+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);
+}
+
+/******************** Creating Temporary regions ******************/
+
+ARegion *ui_add_temporary_region(bScreen *sc)
+{
+ ARegion *ar;
+
+ ar= MEM_callocN(sizeof(ARegion), "area region");
+ BLI_addtail(&sc->regionbase, ar);
+
+ ar->regiontype= RGN_TYPE_TEMPORARY;
+ ar->alignment= RGN_ALIGN_FLOAT;
+
+ return ar;
+}
+
+void ui_remove_temporary_region(bContext *C, bScreen *sc, ARegion *ar)
+{
+ if(CTX_wm_window(C))
+ wm_draw_region_clear(CTX_wm_window(C), ar);
+
+ ED_region_exit(C, ar);
+ BKE_area_region_free(NULL, ar); /* NULL: no spacetype */
+ BLI_freelinkN(&sc->regionbase, ar);
+}
+
+/************************* Creating Tooltips **********************/
+
+typedef struct uiTooltipData {
+ rcti bbox;
+ uiFontStyle fstyle;
+ char *tip;
+} uiTooltipData;
+
+static void ui_tooltip_region_draw(const bContext *C, ARegion *ar)
+{
+ uiTooltipData *data= ar->regiondata;
+
+ ui_draw_menu_back(U.uistyles.first, NULL, &data->bbox);
+
+ /* draw text */
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ uiStyleFontSet(&data->fstyle);
+ uiStyleFontDraw(&data->fstyle, &data->bbox, data->tip);
+}
+
+static void ui_tooltip_region_free(ARegion *ar)
+{
+ uiTooltipData *data;
+
+ data= ar->regiondata;
+ MEM_freeN(data->tip);
+ MEM_freeN(data);
+ ar->regiondata= NULL;
+}
+
+ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
+{
+ uiStyle *style= U.uistyles.first; // XXX pass on as arg
+ static ARegionType type;
+ ARegion *ar;
+ uiTooltipData *data;
+ float fonth, fontw, aspect= but->block->aspect;
+ float x1f, x2f, y1f, y2f;
+ int x1, x2, y1, y2, winx, winy, ofsx, ofsy;
+
+ if(!but->tip || strlen(but->tip)==0)
+ return NULL;
+
+ /* create area region */
+ ar= ui_add_temporary_region(CTX_wm_screen(C));
+
+ memset(&type, 0, sizeof(ARegionType));
+ type.draw= ui_tooltip_region_draw;
+ type.free= ui_tooltip_region_free;
+ ar->type= &type;
+
+ /* create tooltip data */
+ data= MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
+ data->tip= BLI_strdup(but->tip);
+
+ /* set font, get bb */
+ data->fstyle= style->widget; /* copy struct */
+ data->fstyle.align= UI_STYLE_TEXT_CENTER;
+ ui_fontscale(&data->fstyle.points, aspect);
+ uiStyleFontSet(&data->fstyle);
+ fontw= aspect * BLF_width(data->tip);
+ fonth= aspect * BLF_height(data->tip);
+
+ ar->regiondata= data;
+
+ /* compute position */
+ ofsx= (but->block->panel)? but->block->panel->ofsx: 0;
+ ofsy= (but->block->panel)? but->block->panel->ofsy: 0;
+
+ x1f= (but->x1+but->x2)/2.0f + ofsx - 16.0f*aspect;
+ x2f= x1f + fontw + 16.0f*aspect;
+ y2f= but->y1 + ofsy - 15.0f*aspect;
+ y1f= y2f - fonth - 10.0f*aspect;
+
+ /* copy to int, gets projected if possible too */
+ x1= x1f; y1= y1f; x2= x2f; y2= y2f;
+
+ if(butregion) {
+ /* XXX temp, region v2ds can be empty still */
+ if(butregion->v2d.cur.xmin != butregion->v2d.cur.xmax) {
+ UI_view2d_to_region_no_clip(&butregion->v2d, x1f, y1f, &x1, &y1);
+ UI_view2d_to_region_no_clip(&butregion->v2d, x2f, y2f, &x2, &y2);
+ }
+
+ x1 += butregion->winrct.xmin;
+ x2 += butregion->winrct.xmin;
+ y1 += butregion->winrct.ymin;
+ y2 += butregion->winrct.ymin;
+ }
+
+ wm_window_get_size(CTX_wm_window(C), &winx, &winy);
+
+ if(x2 > winx) {
+ /* super size */
+ if(x2 > winx + x1) {
+ x2= winx;
+ x1= 0;
+ }
+ else {
+ x1 -= x2-winx;
+ x2= winx;
+ }
+ }
+ if(y1 < 0) {
+ y1 += 36;
+ y2 += 36;
+ }
+
+ /* widget rect, in region coords */
+ data->bbox.xmin= MENU_SHADOW_SIDE;
+ data->bbox.xmax= x2-x1 + MENU_SHADOW_SIDE;
+ data->bbox.ymin= MENU_SHADOW_BOTTOM;
+ data->bbox.ymax= y2-y1 + MENU_SHADOW_BOTTOM;
+
+ /* region bigger for shadow */
+ ar->winrct.xmin= x1 - MENU_SHADOW_SIDE;
+ ar->winrct.xmax= x2 + MENU_SHADOW_SIDE;
+ ar->winrct.ymin= y1 - MENU_SHADOW_BOTTOM;
+ ar->winrct.ymax= y2 + MENU_TOP;
+
+ /* adds subwindow */
+ ED_region_init(C, ar);
+
+ /* notify change and redraw */
+ ED_region_tag_redraw(ar);
+
+ return ar;
+}
+
+void ui_tooltip_free(bContext *C, ARegion *ar)
+{
+ ui_remove_temporary_region(C, CTX_wm_screen(C), ar);
+}
+
+/************************* Creating Menu Blocks **********************/
+
+/* position block relative to but, result is in window space */
+static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, uiBlock *block)
+{
+ uiBut *bt;
+ uiSafetyRct *saferct;
+ rctf butrct;
+ float aspect;
+ int xsize, ysize, xof=0, yof=0, center;
+ short dir1= 0, dir2=0;
+
+ /* transform to window coordinates, using the source button region/block */
+ butrct.xmin= but->x1; butrct.xmax= but->x2;
+ butrct.ymin= but->y1; butrct.ymax= but->y2;
+
+ ui_block_to_window_fl(butregion, but->block, &butrct.xmin, &butrct.ymin);
+ ui_block_to_window_fl(butregion, but->block, &butrct.xmax, &butrct.ymax);
+
+ /* calc block rect */
+ if(block->minx == 0.0f && block->maxx == 0.0f) {
+ if(block->buttons.first) {
+ 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;
+ }
+ }
+ else {
+ /* we're nice and allow empty blocks too */
+ block->minx= block->miny= 0;
+ block->maxx= block->maxy= 20;
+ }
+ }
+
+ aspect= (float)(block->maxx - block->minx + 4);
+ ui_block_to_window_fl(butregion, but->block, &block->minx, &block->miny);
+ ui_block_to_window_fl(butregion, but->block, &block->maxx, &block->maxy);
+
+ //block->minx-= 2.0; block->miny-= 2.0;
+ //block->maxx+= 2.0; block->maxy+= 2.0;
+
+ xsize= block->maxx - block->minx+4; // 4 for shadow
+ ysize= block->maxy - block->miny+4;
+ aspect/= (float)xsize;
+
+ if(but) {
+ int left=0, right=0, top=0, down=0;
+ int winx, winy;
+
+ wm_window_get_size(window, &winx, &winy);
+
+ if(block->direction & UI_CENTER) center= ysize/2;
+ else center= 0;
+
+ if( butrct.xmin-xsize > 0.0) left= 1;
+ if( butrct.xmax+xsize < winx) right= 1;
+ if( butrct.ymin-ysize+center > 0.0) down= 1;
+ if( butrct.ymax+ysize-center < winy) top= 1;
+
+ dir1= block->direction & UI_DIRECTION;
+
+ /* secundary directions */
+ if(dir1 & (UI_TOP|UI_DOWN)) {
+ if(dir1 & UI_LEFT) dir2= UI_LEFT;
+ else if(dir1 & UI_RIGHT) dir2= UI_RIGHT;
+ dir1 &= (UI_TOP|UI_DOWN);
+ }
+
+ if(dir2==0) if(dir1==UI_LEFT || dir1==UI_RIGHT) dir2= UI_DOWN;
+ if(dir2==0) if(dir1==UI_TOP || dir1==UI_DOWN) dir2= UI_LEFT;
+
+ /* no space at all? dont change */
+ if(left || right) {
+ 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(down || top) {
+ 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= butrct.xmin - block->maxx;
+ if(dir2==UI_TOP) yof= butrct.ymin - block->miny-center;
+ else yof= butrct.ymax - block->maxy+center;
+ }
+ else if(dir1==UI_RIGHT) {
+ xof= butrct.xmax - block->minx;
+ if(dir2==UI_TOP) yof= butrct.ymin - block->miny-center;
+ else yof= butrct.ymax - block->maxy+center;
+ }
+ else if(dir1==UI_TOP) {
+ yof= butrct.ymax - block->miny;
+ if(dir2==UI_RIGHT) xof= butrct.xmax - block->maxx;
+ else xof= butrct.xmin - block->minx;
+ // changed direction?
+ if((dir1 & block->direction)==0) {
+ if(block->direction & UI_SHIFT_FLIPPED)
+ xof+= dir2==UI_LEFT?25:-25;
+ uiBlockFlipOrder(block);
+ }
+ }
+ else if(dir1==UI_DOWN) {
+ yof= butrct.ymin - block->maxy;
+ if(dir2==UI_RIGHT) xof= butrct.xmax - block->maxx;
+ else xof= butrct.xmin - block->minx;
+ // changed direction?
+ if((dir1 & block->direction)==0) {
+ if(block->direction & UI_SHIFT_FLIPPED)
+ xof+= dir2==UI_LEFT?25:-25;
+ uiBlockFlipOrder(block);
+ }
+ }
+
+ /* and now we handle the exception; no space below or to top */
+ if(top==0 && down==0) {
+ if(dir1==UI_LEFT || dir1==UI_RIGHT) {
+ // align with bottom of screen
+ yof= ysize;
+ }
+ }
+
+ /* or no space left or right */
+ if(left==0 && right==0) {
+ if(dir1==UI_TOP || dir1==UI_DOWN) {
+ // align with left size of screen
+ xof= -block->minx+5;
+ }
+ }
+
+ // apply requested offset in the block
+ xof += block->xofs/block->aspect;
+ yof += block->yofs/block->aspect;
+ }
+
+ /* apply */
+
+ for(bt= block->buttons.first; bt; bt= bt->next) {
+ ui_block_to_window_fl(butregion, but->block, &bt->x1, &bt->y1);
+ ui_block_to_window_fl(butregion, but->block, &bt->x2, &bt->y2);
+
+ bt->x1 += xof;
+ bt->x2 += xof;
+ bt->y1 += yof;
+ bt->y2 += yof;
+
+ bt->aspect= 1.0;
+ // ui_check_but recalculates drawstring size in pixels
+ ui_check_but(bt);
+ }
+
+ block->minx += xof;
+ block->miny += yof;
+ block->maxx += xof;
+ block->maxy += yof;
+
+ /* safety calculus */
+ if(but) {
+ float midx= (butrct.xmin+butrct.xmax)/2.0;
+ float midy= (butrct.ymin+butrct.ymax)/2.0;
+
+ /* when you are outside parent button, safety there should be smaller */
+
+ // parent button to left
+ if( midx < block->minx ) block->safety.xmin= block->minx-3;
+ else block->safety.xmin= block->minx-40;
+ // parent button to right
+ if( midx > block->maxx ) block->safety.xmax= block->maxx+3;
+ else block->safety.xmax= block->maxx+40;
+
+ // parent button on bottom
+ if( midy < block->miny ) block->safety.ymin= block->miny-3;
+ else block->safety.ymin= block->miny-40;
+ // parent button on top
+ if( midy > block->maxy ) block->safety.ymax= block->maxy+3;
+ else block->safety.ymax= block->maxy+40;
+
+ // exception for switched pulldowns...
+ if(dir1 && (dir1 & block->direction)==0) {
+ if(dir2==UI_RIGHT) block->safety.xmax= block->maxx+3;
+ if(dir2==UI_LEFT) block->safety.xmin= block->minx-3;
+ }
+ block->direction= dir1;
+ }
+ else {
+ block->safety.xmin= block->minx-40;
+ block->safety.ymin= block->miny-40;
+ block->safety.xmax= block->maxx+40;
+ block->safety.ymax= block->maxy+40;
+ }
+
+ /* keep a list of these, needed for pulldown menus */
+ saferct= MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct");
+ saferct->parent= butrct;
+ saferct->safety= block->safety;
+ BLI_freelistN(&block->saferct);
+ if(but)
+ BLI_duplicatelist(&block->saferct, &but->block->saferct);
+ BLI_addhead(&block->saferct, saferct);
+}
+
+static void ui_block_region_draw(const bContext *C, ARegion *ar)
+{
+ uiBlock *block;
+
+ for(block=ar->uiblocks.first; block; block=block->next)
+ uiDrawBlock(C, block);
+}
+
+uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut *but, uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, void *arg)
+{
+ wmWindow *window= CTX_wm_window(C);
+ static ARegionType type;
+ ARegion *ar;
+ uiBlock *block;
+ uiBut *bt;
+ uiPopupBlockHandle *handle;
+ uiSafetyRct *saferct;
+
+ /* create handle */
+ handle= MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
+
+ /* store context for operator */
+ handle->ctx_area= CTX_wm_area(C);
+ handle->ctx_region= CTX_wm_region(C);
+
+ /* create area region */
+ ar= ui_add_temporary_region(CTX_wm_screen(C));
+
+ memset(&type, 0, sizeof(ARegionType));
+ type.draw= ui_block_region_draw;
+ ar->type= &type;
+
+ UI_add_region_handlers(&ar->handlers);
+
+ handle->region= ar;
+ ar->regiondata= handle;
+
+ /* create ui block */
+ if(create_func)
+ block= create_func(C, handle->region, arg);
+ else
+ block= handle_create_func(C, handle, arg);
+ block->handle= handle;
+
+ if(!block->endblock)
+ uiEndBlock(C, block);
+
+ /* if this is being created from a button */
+ if(but) {
+ if(ELEM3(but->type, BLOCK, PULLDOWN, HMENU))
+ block->xofs = -2; /* for proper alignment */
+
+ /* only used for automatic toolbox, so can set the shift flag */
+ if(but->flag & UI_MAKE_TOP) {
+ block->direction= UI_TOP|UI_SHIFT_FLIPPED;
+ uiBlockFlipOrder(block);
+ }
+ if(but->flag & UI_MAKE_DOWN) block->direction= UI_DOWN|UI_SHIFT_FLIPPED;
+ if(but->flag & UI_MAKE_LEFT) block->direction |= UI_LEFT;
+ if(but->flag & UI_MAKE_RIGHT) block->direction |= UI_RIGHT;
+
+ ui_block_position(window, butregion, but, block);
+ }
+ else {
+ /* keep a list of these, needed for pulldown menus */
+ saferct= MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct");
+ saferct->safety= block->safety;
+ BLI_addhead(&block->saferct, saferct);
+ block->flag |= UI_BLOCK_POPUP;
+ }
+
+ /* the block and buttons were positioned in window space as in 2.4x, now
+ * these menu blocks are regions so we bring it back to region space.
+ * additionally we add some padding for the menu shadow or rounded menus */
+ ar->winrct.xmin= block->minx - MENU_SHADOW_SIDE;
+ ar->winrct.xmax= block->maxx + MENU_SHADOW_SIDE;
+ ar->winrct.ymin= block->miny - MENU_SHADOW_BOTTOM;
+ ar->winrct.ymax= block->maxy + MENU_TOP;
+
+ block->minx -= ar->winrct.xmin;
+ block->maxx -= ar->winrct.xmin;
+ block->miny -= ar->winrct.ymin;
+ block->maxy -= ar->winrct.ymin;
+
+ for(bt= block->buttons.first; bt; bt= bt->next) {
+ bt->x1 -= ar->winrct.xmin;
+ bt->x2 -= ar->winrct.xmin;
+ bt->y1 -= ar->winrct.ymin;
+ bt->y2 -= ar->winrct.ymin;
+ }
+
+ block->flag |= UI_BLOCK_LOOP|UI_BLOCK_MOVEMOUSE_QUIT;
+
+ /* adds subwindow */
+ ED_region_init(C, ar);
+
+ /* get winmat now that we actually have the subwindow */
+ wmSubWindowSet(window, ar->swinid);
+ // XXX ton, AA pixel space...
+ wmOrtho2(0.0, (float)ar->winrct.xmax-ar->winrct.xmin+1, 0.0, (float)ar->winrct.ymax-ar->winrct.ymin+1);
+
+ wm_subwindow_getmatrix(window, ar->swinid, block->winmat);
+
+ /* notify change and redraw */
+ ED_region_tag_redraw(ar);
+
+ return handle;
+}
+
+void ui_popup_block_free(bContext *C, uiPopupBlockHandle *handle)
+{
+ ui_remove_temporary_region(C, CTX_wm_screen(C), handle->region);
+ MEM_freeN(handle);
+}
+
+/***************************** Menu Button ***************************/
+
+uiBlock *ui_block_func_MENU(bContext *C, uiPopupBlockHandle *handle, void *arg_but)
+{
+ uiBut *but= arg_but;
+ uiBlock *block;
+ uiBut *bt;
+ MenuData *md;
+ ListBase lb;
+ float aspect;
+ int width, height, boxh, columns, rows, startx, starty, x1, y1, xmax, a;
+
+ /* create the block */
+ block= uiBeginBlock(C, handle->region, "menu", UI_EMBOSSP);
+ block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT;
+
+ /* compute menu data */
+ md= decompose_menu_string(but->str);
+
+ /* columns and row calculation */
+ columns= (md->nitems+20)/20;
+ if(columns<1)
+ columns= 1;
+ if(columns>8)
+ columns= (md->nitems+25)/25;
+
+ rows= md->nitems/columns;
+ if(rows<1)
+ rows= 1;
+ while(rows*columns<md->nitems)
+ rows++;
+
+ /* prevent scaling up of pupmenu */
+ aspect= but->aspect;
+ if(aspect < 1.0f)
+ aspect = 1.0f;
+
+ /* size and location */
+ if(md->title)
+ width= 1.5*aspect*strlen(md->title)+UI_GetStringWidth(md->title);
+ else
+ width= 0;
+
+ for(a=0; a<md->nitems; a++) {
+ xmax= aspect*UI_GetStringWidth(md->items[a].str);
+ if(md->items[a].icon)
+ xmax += 20*aspect;
+ if(xmax>width)
+ width= xmax;
+ }
+
+ width+= 10;
+ if(width < (but->x2 - but->x1))
+ width = (but->x2 - but->x1);
+ if(width<50)
+ width=50;
+
+ boxh= MENU_BUTTON_HEIGHT;
+
+ height= rows*boxh;
+ if(md->title)
+ height+= boxh;
+
+ /* here we go! */
+ startx= but->x1;
+ starty= but->y1;
+
+ if(md->title) {
+ uiBut *bt;
+
+ if (md->titleicon) {
+ bt= uiDefIconTextBut(block, LABEL, 0, md->titleicon, md->title, startx, (short)(starty+rows*boxh), (short)width, (short)boxh, NULL, 0.0, 0.0, 0, 0, "");
+ } else {
+ bt= uiDefBut(block, LABEL, 0, md->title, startx, (short)(starty+rows*boxh), (short)width, (short)boxh, NULL, 0.0, 0.0, 0, 0, "");
+ bt->flag= UI_TEXT_LEFT;
+ }
+ }
+
+ for(a=0; a<md->nitems; a++) {
+
+ x1= startx + width*((int)(md->nitems-a-1)/rows);
+ y1= starty - boxh*(rows - ((md->nitems - a - 1)%rows)) + (rows*boxh);
+
+ if (strcmp(md->items[md->nitems-a-1].str, "%l")==0) {
+ bt= uiDefBut(block, SEPR, B_NOP, "", x1, y1,(short)(width-(rows>1)), (short)(boxh-1), NULL, 0.0, 0.0, 0, 0, "");
+ }
+ else if(md->items[md->nitems-a-1].icon) {
+ bt= uiDefIconTextButF(block, BUTM|FLO, B_NOP, md->items[md->nitems-a-1].icon ,md->items[md->nitems-a-1].str, x1, y1,(short)(width-(rows>1)), (short)(boxh-1), &handle->retvalue, (float) md->items[md->nitems-a-1].retval, 0.0, 0, 0, "");
+ }
+ else {
+ bt= uiDefButF(block, BUTM|FLO, B_NOP, md->items[md->nitems-a-1].str, x1, y1,(short)(width-(rows>1)), (short)(boxh-1), &handle->retvalue, (float) md->items[md->nitems-a-1].retval, 0.0, 0, 0, "");
+ }
+ }
+
+ menudata_free(md);
+
+ /* the code up here has flipped locations, because of change of preferred order */
+ /* thats why we have to switch list order too, to make arrowkeys work */
+
+ lb.first= lb.last= NULL;
+ bt= block->buttons.first;
+ while(bt) {
+ uiBut *next= bt->next;
+ BLI_remlink(&block->buttons, bt);
+ BLI_addhead(&lb, bt);
+ bt= next;
+ }
+ block->buttons= lb;
+
+ block->direction= UI_TOP;
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+uiBlock *ui_block_func_ICONROW(bContext *C, uiPopupBlockHandle *handle, void *arg_but)
+{
+ uiBut *but= arg_but;
+ uiBlock *block;
+ int a;
+
+ block= uiBeginBlock(C, handle->region, "menu", UI_EMBOSSP);
+ block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT;
+
+ for(a=(int)but->hardmin; a<=(int)but->hardmax; a++) {
+ uiDefIconButF(block, BUTM|FLO, B_NOP, but->icon+(a-but->hardmin), 0, (short)(18*a), (short)(but->x2-but->x1-4), 18, &handle->retvalue, (float)a, 0.0, 0, 0, "");
+ }
+
+ block->direction= UI_TOP;
+
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+uiBlock *ui_block_func_ICONTEXTROW(bContext *C, uiPopupBlockHandle *handle, void *arg_but)
+{
+ uiBut *but= arg_but;
+ uiBlock *block;
+ MenuData *md;
+ int width, xmax, ypos, a;
+
+ block= uiBeginBlock(C, handle->region, "menu", UI_EMBOSSP);
+ block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT;
+
+ md= decompose_menu_string(but->str);
+
+ /* size and location */
+ /* expand menu width to fit labels */
+ if(md->title)
+ width= 2*strlen(md->title)+UI_GetStringWidth(md->title);
+ else
+ width= 0;
+
+ for(a=0; a<md->nitems; a++) {
+ xmax= UI_GetStringWidth(md->items[a].str);
+ if(xmax>width) width= xmax;
+ }
+
+ width+= 30;
+ if (width<50) width=50;
+
+ ypos = 1;
+
+ /* loop through the menu options and draw them out with icons & text labels */
+ for(a=0; a<md->nitems; a++) {
+
+ /* add a space if there's a separator (%l) */
+ if (strcmp(md->items[a].str, "%l")==0) {
+ ypos +=3;
+ }
+ else {
+ uiDefIconTextButF(block, BUTM|FLO, B_NOP, (short)((but->icon)+(md->items[a].retval-but->hardmin)), md->items[a].str, 0, ypos,(short)width, 19, &handle->retvalue, (float) md->items[a].retval, 0.0, 0, 0, "");
+ ypos += 20;
+ }
+ }
+
+ if(md->title) {
+ uiBut *bt;
+
+ bt= uiDefBut(block, LABEL, 0, md->title, 0, ypos, (short)width, 19, NULL, 0.0, 0.0, 0, 0, "");
+ bt->flag= UI_TEXT_LEFT;
+ }
+
+ menudata_free(md);
+
+ block->direction= UI_TOP;
+
+ uiBoundsBlock(block, 3);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static void ui_warp_pointer(short x, short y)
+{
+ /* XXX 2.50 which function to use for this? */
+#if 0
+ /* OSX has very poor mousewarp support, it sends events;
+ this causes a menu being pressed immediately ... */
+ #ifndef __APPLE__
+ warp_pointer(x, y);
+ #endif
+#endif
+}
+
+/********************* Color Button ****************/
+
+/* picker sizes S hsize, F full size, D spacer, B button/pallette height */
+#define SPICK 110.0
+#define FPICK 180.0
+#define DPICK 6.0
+#define BPICK 24.0
+
+#define UI_PALETTE_TOT 16
+/* note; in tot+1 the old color is stored */
+static float palette[UI_PALETTE_TOT+1][3]= {
+{0.93, 0.83, 0.81}, {0.88, 0.89, 0.73}, {0.69, 0.81, 0.57}, {0.51, 0.76, 0.64},
+{0.37, 0.56, 0.61}, {0.33, 0.29, 0.55}, {0.46, 0.21, 0.51}, {0.40, 0.12, 0.18},
+{1.0, 1.0, 1.0}, {0.85, 0.85, 0.85}, {0.7, 0.7, 0.7}, {0.56, 0.56, 0.56},
+{0.42, 0.42, 0.42}, {0.28, 0.28, 0.28}, {0.14, 0.14, 0.14}, {0.0, 0.0, 0.0}
+};
+
+/* for picker, while editing hsv */
+void ui_set_but_hsv(uiBut *but)
+{
+ float col[3];
+
+ hsv_to_rgb(but->hsv[0], but->hsv[1], but->hsv[2], col, col+1, col+2);
+ ui_set_but_vectorf(but, col);
+}
+
+static void update_picker_hex(uiBlock *block, float *rgb)
+{
+ uiBut *bt;
+ char col[16];
+
+ sprintf(col, "%02X%02X%02X", (unsigned int)(rgb[0]*255.0), (unsigned int)(rgb[1]*255.0), (unsigned int)(rgb[2]*255.0));
+
+ // this updates button strings, is hackish... but button pointers are on stack of caller function
+
+ for(bt= block->buttons.first; bt; bt= bt->next) {
+ if(strcmp(bt->str, "Hex: ")==0) {
+ strcpy(bt->poin, col);
+ ui_check_but(bt);
+ break;
+ }
+ }
+}
+
+void ui_update_block_buts_hsv(uiBlock *block, float *hsv)
+{
+ uiBut *bt;
+ float r, g, b;
+ float rgb[3];
+
+ // this updates button strings, is hackish... but button pointers are on stack of caller function
+ hsv_to_rgb(hsv[0], hsv[1], hsv[2], &r, &g, &b);
+
+ rgb[0] = r; rgb[1] = g; rgb[2] = b;
+ update_picker_hex(block, rgb);
+
+ for(bt= block->buttons.first; bt; bt= bt->next) {
+ if(bt->type==HSVCUBE) {
+ VECCOPY(bt->hsv, hsv);
+ ui_set_but_hsv(bt);
+ }
+ else if(bt->str[1]==' ') {
+ if(bt->str[0]=='R') {
+ ui_set_but_val(bt, r);
+ }
+ else if(bt->str[0]=='G') {
+ ui_set_but_val(bt, g);
+ }
+ else if(bt->str[0]=='B') {
+ ui_set_but_val(bt, b);
+ }
+ else if(bt->str[0]=='H') {
+ ui_set_but_val(bt, hsv[0]);
+ }
+ else if(bt->str[0]=='S') {
+ ui_set_but_val(bt, hsv[1]);
+ }
+ else if(bt->str[0]=='V') {
+ ui_set_but_val(bt, hsv[2]);
+ }
+ }
+ }
+}
+
+static void ui_update_block_buts_hex(uiBlock *block, char *hexcol)
+{
+ uiBut *bt;
+ float r=0, g=0, b=0;
+ float h, s, v;
+
+
+ // this updates button strings, is hackish... but button pointers are on stack of caller function
+ hex_to_rgb(hexcol, &r, &g, &b);
+ rgb_to_hsv(r, g, b, &h, &s, &v);
+
+ for(bt= block->buttons.first; bt; bt= bt->next) {
+ if(bt->type==HSVCUBE) {
+ bt->hsv[0] = h;
+ bt->hsv[1] = s;
+ bt->hsv[2] = v;
+ ui_set_but_hsv(bt);
+ }
+ else if(bt->str[1]==' ') {
+ if(bt->str[0]=='R') {
+ ui_set_but_val(bt, r);
+ }
+ else if(bt->str[0]=='G') {
+ ui_set_but_val(bt, g);
+ }
+ else if(bt->str[0]=='B') {
+ ui_set_but_val(bt, b);
+ }
+ else if(bt->str[0]=='H') {
+ ui_set_but_val(bt, h);
+ }
+ else if(bt->str[0]=='S') {
+ ui_set_but_val(bt, s);
+ }
+ else if(bt->str[0]=='V') {
+ ui_set_but_val(bt, v);
+ }
+ }
+ }
+}
+
+/* bt1 is palette but, col1 is original color */
+/* callback to copy from/to palette */
+static void do_palette_cb(bContext *C, void *bt1, void *col1)
+{
+ uiBut *but1= (uiBut *)bt1;
+ float *col= (float *)col1;
+ float *fp, hsv[3];
+
+ fp= (float *)but1->poin;
+
+ /* XXX 2.50 bad access, how to solve?
+ *
+ if( (get_qual() & LR_CTRLKEY) ) {
+ VECCOPY(fp, col);
+ }
+ else*/ {
+ VECCOPY(col, fp);
+ }
+
+ rgb_to_hsv(col[0], col[1], col[2], hsv, hsv+1, hsv+2);
+ ui_update_block_buts_hsv(but1->block, hsv);
+ update_picker_hex(but1->block, col);
+}
+
+/* bt1 is num but, hsv1 is pointer to original color in hsv space*/
+/* callback to handle changes in num-buts in picker */
+static void do_palette1_cb(bContext *C, void *bt1, void *hsv1)
+{
+ uiBut *but1= (uiBut *)bt1;
+ float *hsv= (float *)hsv1;
+ float *fp= NULL;
+
+ if(but1->str[1]==' ') {
+ if(but1->str[0]=='R') fp= (float *)but1->poin;
+ else if(but1->str[0]=='G') fp= ((float *)but1->poin)-1;
+ else if(but1->str[0]=='B') fp= ((float *)but1->poin)-2;
+ }
+ if(fp) {
+ rgb_to_hsv(fp[0], fp[1], fp[2], hsv, hsv+1, hsv+2);
+ }
+ ui_update_block_buts_hsv(but1->block, hsv);
+}
+
+/* bt1 is num but, col1 is pointer to original color */
+/* callback to handle changes in num-buts in picker */
+static void do_palette2_cb(bContext *C, void *bt1, void *col1)
+{
+ uiBut *but1= (uiBut *)bt1;
+ float *rgb= (float *)col1;
+ float *fp= NULL;
+
+ if(but1->str[1]==' ') {
+ if(but1->str[0]=='H') fp= (float *)but1->poin;
+ else if(but1->str[0]=='S') fp= ((float *)but1->poin)-1;
+ else if(but1->str[0]=='V') fp= ((float *)but1->poin)-2;
+ }
+ if(fp) {
+ hsv_to_rgb(fp[0], fp[1], fp[2], rgb, rgb+1, rgb+2);
+ }
+ ui_update_block_buts_hsv(but1->block, fp);
+}
+
+static void do_palette_hex_cb(bContext *C, void *bt1, void *hexcl)
+{
+ uiBut *but1= (uiBut *)bt1;
+ char *hexcol= (char *)hexcl;
+
+ ui_update_block_buts_hex(but1->block, hexcol);
+}
+
+/* used for both 3d view and image window */
+static void do_palette_sample_cb(bContext *C, void *bt1, void *col1) /* frontbuf */
+{
+ /* XXX 2.50 this should become an operator? */
+#if 0
+ uiBut *but1= (uiBut *)bt1;
+ uiBut *but;
+ float tempcol[4];
+ int x=0, y=0;
+ short mval[2];
+ float hsv[3];
+ short capturing;
+ int oldcursor;
+ Window *win;
+ unsigned short dev;
+
+ oldcursor=get_cursor();
+ win=winlay_get_active_window();
+
+ while (get_mbut() & L_MOUSE) UI_wait_for_statechange();
+
+ SetBlenderCursor(BC_EYEDROPPER_CURSOR);
+
+ /* loop and wait for a mouse click */
+ capturing = TRUE;
+ while(capturing) {
+ char ascii;
+ short val;
+
+ dev = extern_qread_ext(&val, &ascii);
+
+ if(dev==INPUTCHANGE) break;
+ if(get_mbut() & R_MOUSE) break;
+ else if(get_mbut() & L_MOUSE) {
+ uiGetMouse(mywinget(), mval);
+ x= mval[0]; y= mval[1];
+
+ capturing = FALSE;
+ break;
+ }
+ else if(dev==ESCKEY) break;
+ }
+ window_set_cursor(win, oldcursor);
+
+ if(capturing) return;
+
+ if(x<0 || y<0) return;
+
+ /* if we've got a glick, use OpenGL to sample the color under the mouse pointer */
+ glReadBuffer(GL_FRONT);
+ glReadPixels(x, y, 1, 1, GL_RGBA, GL_FLOAT, tempcol);
+ glReadBuffer(GL_BACK);
+
+ /* and send that color back to the picker */
+ rgb_to_hsv(tempcol[0], tempcol[1], tempcol[2], hsv, hsv+1, hsv+2);
+ ui_update_block_buts_hsv(but1->block, hsv);
+ update_picker_hex(but1->block, tempcol);
+
+ for (but= but1->block->buttons.first; but; but= but->next) {
+ ui_check_but(but);
+ ui_draw_but(but);
+ }
+
+ but= but1->block->buttons.first;
+ ui_block_flush_back(but->block);
+#endif
+}
+
+/* color picker, Gimp version. mode: 'f' = floating panel, 'p' = popup */
+/* col = read/write to, hsv/old/hexcol = memory for temporal use */
+void uiBlockPickerButtons(uiBlock *block, float *col, float *hsv, float *old, char *hexcol, char mode, short retval)
+{
+ uiBut *bt;
+ float h, offs;
+ int a;
+
+ VECCOPY(old, col); // old color stored there, for palette_cb to work
+
+ // the cube intersection
+ bt= uiDefButF(block, HSVCUBE, retval, "", 0,DPICK+BPICK,FPICK,FPICK, col, 0.0, 0.0, 2, 0, "");
+
+ bt= uiDefButF(block, HSVCUBE, retval, "", 0,0,FPICK,BPICK, col, 0.0, 0.0, 3, 0, "");
+
+ // palette
+
+ uiBlockSetEmboss(block, UI_EMBOSSP);
+
+ bt=uiDefButF(block, COL, retval, "", FPICK+DPICK, 0, BPICK,BPICK, old, 0.0, 0.0, -1, 0, "Old color, click to restore");
+ uiButSetFunc(bt, do_palette_cb, bt, col);
+ uiDefButF(block, COL, retval, "", FPICK+DPICK, BPICK+DPICK, BPICK,60-BPICK-DPICK, col, 0.0, 0.0, -1, 0, "Active color");
+
+ h= (DPICK+BPICK+FPICK-64)/(UI_PALETTE_TOT/2.0);
+ uiBlockBeginAlign(block);
+ for(a= -1+UI_PALETTE_TOT/2; a>=0; a--) {
+ bt= uiDefButF(block, COL, retval, "", FPICK+DPICK, 65.0+(float)a*h, BPICK/2, h, palette[a+UI_PALETTE_TOT/2], 0.0, 0.0, -1, 0, "Click to choose, hold CTRL to store in palette");
+ uiButSetFunc(bt, do_palette_cb, bt, col);
+ bt= uiDefButF(block, COL, retval, "", FPICK+DPICK+BPICK/2, 65.0+(float)a*h, BPICK/2, h, palette[a], 0.0, 0.0, -1, 0, "Click to choose, hold CTRL to store in palette");
+ uiButSetFunc(bt, do_palette_cb, bt, col);
+ }
+ uiBlockEndAlign(block);
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ // buttons
+ rgb_to_hsv(col[0], col[1], col[2], hsv, hsv+1, hsv+2);
+ sprintf(hexcol, "%02X%02X%02X", (unsigned int)(col[0]*255.0), (unsigned int)(col[1]*255.0), (unsigned int)(col[2]*255.0));
+
+ offs= FPICK+2*DPICK+BPICK;
+
+ /* note; made this a TOG now, with NULL pointer. Is because BUT now gets handled with a afterfunc */
+ bt= uiDefIconTextBut(block, TOG, UI_RETURN_OK, ICON_EYEDROPPER, "Sample", offs+55, 170, 85, 20, NULL, 0, 0, 0, 0, "Sample the color underneath the following mouse click (ESC or RMB to cancel)");
+ uiButSetFunc(bt, do_palette_sample_cb, bt, col);
+ uiButSetFlag(bt, UI_TEXT_LEFT);
+
+ bt= uiDefBut(block, TEX, retval, "Hex: ", offs, 140, 140, 20, hexcol, 0, 8, 0, 0, "Hex triplet for color (#RRGGBB)");
+ uiButSetFunc(bt, do_palette_hex_cb, bt, hexcol);
+
+ uiBlockBeginAlign(block);
+ bt= uiDefButF(block, NUMSLI, retval, "R ", offs, 110, 140,20, col, 0.0, 1.0, 10, 3, "");
+ uiButSetFunc(bt, do_palette1_cb, bt, hsv);
+ bt= uiDefButF(block, NUMSLI, retval, "G ", offs, 90, 140,20, col+1, 0.0, 1.0, 10, 3, "");
+ uiButSetFunc(bt, do_palette1_cb, bt, hsv);
+ bt= uiDefButF(block, NUMSLI, retval, "B ", offs, 70, 140,20, col+2, 0.0, 1.0, 10, 3, "");
+ uiButSetFunc(bt, do_palette1_cb, bt, hsv);
+
+ uiBlockBeginAlign(block);
+ bt= uiDefButF(block, NUMSLI, retval, "H ", offs, 40, 140,20, hsv, 0.0, 1.0, 10, 3, "");
+ uiButSetFunc(bt, do_palette2_cb, bt, col);
+ bt= uiDefButF(block, NUMSLI, retval, "S ", offs, 20, 140,20, hsv+1, 0.0, 1.0, 10, 3, "");
+ uiButSetFunc(bt, do_palette2_cb, bt, col);
+ bt= uiDefButF(block, NUMSLI, retval, "V ", offs, 0, 140,20, hsv+2, 0.0, 1.0, 10, 3, "");
+ uiButSetFunc(bt, do_palette2_cb, bt, col);
+ uiBlockEndAlign(block);
+}
+
+uiBlock *ui_block_func_COL(bContext *C, uiPopupBlockHandle *handle, void *arg_but)
+{
+ uiBut *but= arg_but;
+ uiBlock *block;
+ static float hsvcol[3], oldcol[3];
+ static char hexcol[128];
+
+ block= uiBeginBlock(C, handle->region, "colorpicker", UI_EMBOSS);
+ block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_KEEP_OPEN;
+
+ VECCOPY(handle->retvec, but->editvec);
+ uiBlockPickerButtons(block, handle->retvec, hsvcol, oldcol, hexcol, 'p', 0);
+
+ /* and lets go */
+ block->direction= UI_TOP;
+ uiBoundsBlock(block, 3);
+
+ return block;
+}
+
+/* ******************** PUPmenu ****************** */
+
+static int pupmenu_set= 0;
+
+void uiPupMenuSetActive(int val)
+{
+ pupmenu_set= val;
+}
+
+/* value== -1 read, otherwise set */
+static int pupmenu_memory(char *str, int value)
+{
+ static char mem[256], first=1;
+ int val=0, nr=0;
+
+ if(first) {
+ memset(mem, 0, 256);
+ first= 0;
+ }
+ while(str[nr]) {
+ val+= str[nr];
+ nr++;
+ }
+
+ if(value >= 0) mem[ val & 255 ]= value;
+ else return mem[ val & 255 ];
+
+ return 0;
+}
+
+#define PUP_LABELH 6
+
+typedef struct uiPupMenuInfo {
+ char *instr;
+ int mx, my;
+ int startx, starty;
+ int maxrow;
+} uiPupMenuInfo;
+
+uiBlock *ui_block_func_PUPMENU(bContext *C, uiPopupBlockHandle *handle, void *arg_info)
+{
+ uiBlock *block;
+ uiPupMenuInfo *info;
+ int columns, rows, mousemove[2]= {0, 0}, mousewarp= 0;
+ int width, height, xmax, ymax, maxrow;
+ int a, startx, starty, endx, endy, x1, y1;
+ int lastselected;
+ MenuData *md;
+
+ info= arg_info;
+ maxrow= info->maxrow;
+ height= 0;
+
+ /* block stuff first, need to know the font */
+ block= uiBeginBlock(C, handle->region, "menu", UI_EMBOSSP);
+ uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_NUMSELECT);
+ block->direction= UI_DOWN;
+
+ md= decompose_menu_string(info->instr);
+
+ rows= md->nitems;
+ columns= 1;
+
+ /* size and location, title slightly bigger for bold */
+ if(md->title) {
+ width= 2*strlen(md->title)+UI_GetStringWidth(md->title);
+ width /= columns;
+ }
+ else width= 0;
+
+ for(a=0; a<md->nitems; a++) {
+ xmax= UI_GetStringWidth(md->items[a].str);
+ if(xmax>width) width= xmax;
+
+ if(strcmp(md->items[a].str, "%l")==0) height+= PUP_LABELH;
+ else height+= MENU_BUTTON_HEIGHT;
+ }
+
+ width+= 10;
+ if (width<50) width=50;
+
+ wm_window_get_size(CTX_wm_window(C), &xmax, &ymax);
+
+ /* set first item */
+ lastselected= 0;
+ if(pupmenu_set) {
+ lastselected= pupmenu_set-1;
+ pupmenu_set= 0;
+ }
+ else if(md->nitems>1) {
+ lastselected= pupmenu_memory(info->instr, -1);
+ }
+
+ startx= info->mx-(0.8*(width));
+ starty= info->my-height+MENU_BUTTON_HEIGHT/2;
+ if(lastselected>=0 && lastselected<md->nitems) {
+ for(a=0; a<md->nitems; a++) {
+ if(a==lastselected) break;
+ if( strcmp(md->items[a].str, "%l")==0) starty+= PUP_LABELH;
+ else starty+=MENU_BUTTON_HEIGHT;
+ }
+
+ //starty= info->my-height+MENU_BUTTON_HEIGHT/2+lastselected*MENU_BUTTON_HEIGHT;
+ }
+
+ if(startx<10) {
+ startx= 10;
+ }
+ if(starty<10) {
+ mousemove[1]= 10-starty;
+ starty= 10;
+ }
+
+ endx= startx+width*columns;
+ endy= starty+height;
+
+ if(endx>xmax) {
+ endx= xmax-10;
+ startx= endx-width*columns;
+ }
+ if(endy>ymax-20) {
+ mousemove[1]= ymax-endy-20;
+ endy= ymax-20;
+ starty= endy-height;
+ }
+
+ if(mousemove[0] || mousemove[1]) {
+ ui_warp_pointer(info->mx+mousemove[0], info->my+mousemove[1]);
+ mousemove[0]= info->mx;
+ mousemove[1]= info->my;
+ mousewarp= 1;
+ }
+
+ /* here we go! */
+ if(md->title) {
+ uiBut *bt;
+ char titlestr[256];
+
+ if(md->titleicon) {
+ width+= 20;
+ sprintf(titlestr, " %s", md->title);
+ uiDefIconTextBut(block, LABEL, 0, md->titleicon, titlestr, startx, (short)(starty+height), width, MENU_BUTTON_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
+ }
+ else {
+ bt= uiDefBut(block, LABEL, 0, md->title, startx, (short)(starty+height), columns*width, MENU_BUTTON_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
+ bt->flag= UI_TEXT_LEFT;
+ }
+
+ //uiDefBut(block, SEPR, 0, "", startx, (short)(starty+height)-MENU_SEPR_HEIGHT, width, MENU_SEPR_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
+ }
+
+ x1= startx + width*((int)a/rows);
+ y1= starty + height - MENU_BUTTON_HEIGHT; // - MENU_SEPR_HEIGHT;
+
+ for(a=0; a<md->nitems; a++) {
+ char *name= md->items[a].str;
+ int icon = md->items[a].icon;
+
+ if(strcmp(name, "%l")==0) {
+ uiDefBut(block, SEPR, B_NOP, "", x1, y1, width, PUP_LABELH, NULL, 0, 0.0, 0, 0, "");
+ y1 -= PUP_LABELH;
+ }
+ else if (icon) {
+ uiDefIconButF(block, BUTM, B_NOP, icon, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, &handle->retvalue, (float) md->items[a].retval, 0.0, 0, 0, "");
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else {
+ uiDefButF(block, BUTM, B_NOP, name, x1, y1, width, MENU_BUTTON_HEIGHT-1, &handle->retvalue, (float) md->items[a].retval, 0.0, 0, 0, "");
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ }
+
+ uiBoundsBlock(block, 1);
+ uiEndBlock(C, block);
+
+ menudata_free(md);
+
+ /* XXX 2.5 need to store last selected */
+#if 0
+ /* calculate last selected */
+ if(event & ui_return_ok) {
+ lastselected= 0;
+ for(a=0; a<md->nitems; a++) {
+ if(val==md->items[a].retval) lastselected= a;
+ }
+
+ pupmenu_memory(info->instr, lastselected);
+ }
+#endif
+
+ /* XXX 2.5 need to warp back */
+#if 0
+ if(mousemove[1] && (event & ui_return_out)==0)
+ ui_warp_pointer(mousemove[0], mousemove[1]);
+ return val;
+#endif
+
+ return block;
+}
+
+uiBlock *ui_block_func_PUPMENUCOL(bContext *C, uiPopupBlockHandle *handle, void *arg_info)
+{
+ uiBlock *block;
+ uiPupMenuInfo *info;
+ int columns, rows, mousemove[2]= {0, 0}, mousewarp;
+ int width, height, xmax, ymax, maxrow;
+ int a, startx, starty, endx, endy, x1, y1;
+ float fvalue;
+ MenuData *md;
+
+ info= arg_info;
+ maxrow= info->maxrow;
+ height= 0;
+
+ /* block stuff first, need to know the font */
+ block= uiBeginBlock(C, handle->region, "menu", UI_EMBOSSP);
+ uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_NUMSELECT);
+ block->direction= UI_DOWN;
+
+ md= decompose_menu_string(info->instr);
+
+ /* columns and row calculation */
+ columns= (md->nitems+maxrow)/maxrow;
+ if (columns<1) columns= 1;
+
+ if(columns > 8) {
+ maxrow += 5;
+ columns= (md->nitems+maxrow)/maxrow;
+ }
+
+ rows= (int) md->nitems/columns;
+ if (rows<1) rows= 1;
+
+ while (rows*columns<(md->nitems+columns) ) rows++;
+
+ /* size and location, title slightly bigger for bold */
+ if(md->title) {
+ width= 2*strlen(md->title)+UI_GetStringWidth(md->title);
+ width /= columns;
+ }
+ else width= 0;
+
+ for(a=0; a<md->nitems; a++) {
+ xmax= UI_GetStringWidth(md->items[a].str);
+ if(xmax>width) width= xmax;
+ }
+
+ width+= 10;
+ if (width<50) width=50;
+
+ height= rows*MENU_BUTTON_HEIGHT;
+ if (md->title) height+= MENU_BUTTON_HEIGHT;
+
+ wm_window_get_size(CTX_wm_window(C), &xmax, &ymax);
+
+ /* find active item */
+ fvalue= handle->retvalue;
+ 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 = info->mx-width/2 - ((int)(a)/rows)*width;
+ else
+ startx= info->mx-width/2;
+ starty = info->my-height + MENU_BUTTON_HEIGHT/2 + ((a)%rows)*MENU_BUTTON_HEIGHT;
+
+ if (md->title) starty+= MENU_BUTTON_HEIGHT;
+
+ 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;
+ }
+
+ if(mousemove[0] || mousemove[1]) {
+ ui_warp_pointer(info->mx+mousemove[0], info->my+mousemove[1]);
+ mousemove[0]= info->mx;
+ mousemove[1]= info->my;
+ mousewarp= 1;
+ }
+
+ /* here we go! */
+ if(md->title) {
+ uiBut *bt;
+
+ if(md->titleicon) {
+ }
+ else {
+ bt= uiDefBut(block, LABEL, 0, md->title, startx, (short)(starty+rows*MENU_BUTTON_HEIGHT), columns*width, MENU_BUTTON_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
+ bt->flag= UI_TEXT_LEFT;
+ }
+ }
+
+ for(a=0; a<md->nitems; a++) {
+ char *name= md->items[a].str;
+ int icon = md->items[a].icon;
+
+ x1= startx + width*((int)a/rows);
+ y1= starty - MENU_BUTTON_HEIGHT*(a%rows) + (rows-1)*MENU_BUTTON_HEIGHT;
+
+ if(strcmp(name, "%l")==0) {
+ uiDefBut(block, SEPR, B_NOP, "", x1, y1, width, PUP_LABELH, NULL, 0, 0.0, 0, 0, "");
+ y1 -= PUP_LABELH;
+ }
+ else if (icon) {
+ uiDefIconButF(block, BUTM, B_NOP, icon, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, &handle->retvalue, (float) md->items[a].retval, 0.0, 0, 0, "");
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else {
+ uiDefButF(block, BUTM, B_NOP, name, x1, y1, width, MENU_BUTTON_HEIGHT-1, &handle->retvalue, (float) md->items[a].retval, 0.0, 0, 0, "");
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ }
+
+ uiBoundsBlock(block, 1);
+ uiEndBlock(C, block);
+
+ menudata_free(md);
+
+ /* XXX 2.5 need to warp back */
+#if 0
+ if((event & UI_RETURN_OUT)==0)
+ ui_warp_pointer(mousemove[0], mousemove[1]);
+#endif
+
+ return block;
+}
+
+/************************** Menu Definitions ***************************/
+
+/* prototype */
+static uiBlock *ui_block_func_MENU_ITEM(bContext *C, uiPopupBlockHandle *handle, void *arg_info);
+
+#define MAX_MENU_STR 64
+
+/* type, internal */
+#define MENU_ITEM_TITLE 0
+#define MENU_ITEM_ITEM 1
+#define MENU_ITEM_SEPARATOR 2
+#define MENU_ITEM_OPNAME 10
+#define MENU_ITEM_OPNAME_BOOL 11
+#define MENU_ITEM_OPNAME_ENUM 12
+#define MENU_ITEM_OPNAME_INT 13
+#define MENU_ITEM_OPNAME_FLOAT 14
+#define MENU_ITEM_OPNAME_STRING 15
+#define MENU_ITEM_RNA_BOOL 20
+#define MENU_ITEM_RNA_ENUM 21
+#define MENU_ITEM_LEVEL 30
+#define MENU_ITEM_LEVEL_OPNAME_ENUM 31
+#define MENU_ITEM_LEVEL_RNA_ENUM 32
+
+struct uiMenuItem {
+ struct uiMenuItem *next, *prev;
+
+ int type;
+ int icon;
+ char name[MAX_MENU_STR];
+
+ char *opname; /* static string */
+ char *propname; /* static string */
+
+ int retval, enumval, boolval, intval;
+ float fltval;
+ char *strval;
+ int opcontext;
+ uiMenuHandleFunc eventfunc;
+ void *argv;
+ uiMenuCreateFunc newlevel;
+ PointerRNA rnapoin;
+
+ ListBase items;
+};
+
+typedef struct uiMenuInfo {
+ uiMenuItem *head;
+ int mx, my, popup, slideout;
+ int startx, starty;
+} uiMenuInfo;
+
+/************************ Menu Definitions to uiBlocks ***********************/
+
+const char *ui_menu_enumpropname(char *opname, const char *propname, int retval)
+{
+ wmOperatorType *ot= WM_operatortype_find(opname);
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ if(!ot || !ot->srna)
+ return "";
+
+ RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
+ prop= RNA_struct_find_property(&ptr, propname);
+
+ if(prop) {
+ const EnumPropertyItem *item;
+ int totitem, i;
+
+ RNA_property_enum_items(&ptr, prop, &item, &totitem);
+
+ for (i=0; i<totitem; i++) {
+ if(item[i].value==retval)
+ return item[i].name;
+ }
+ }
+
+ return "";
+}
+
+typedef struct MenuItemLevel {
+ int opcontext;
+ char *opname;
+ char *propname;
+ PointerRNA rnapoin;
+} MenuItemLevel;
+
+/* make a menu level from enum properties */
+static void menu_item_enum_opname_menu(bContext *C, uiMenuItem *head, void *arg)
+{
+ MenuItemLevel *lvl= (MenuItemLevel*)(((uiBut*)arg)->func_argN);
+
+ head->opcontext= lvl->opcontext;
+ uiMenuItemsEnumO(head, lvl->opname, lvl->propname);
+}
+
+static void menu_item_enum_rna_menu(bContext *C, uiMenuItem *head, void *arg)
+{
+ MenuItemLevel *lvl= (MenuItemLevel*)(((uiBut*)arg)->func_argN);
+
+ head->opcontext= lvl->opcontext;
+ uiMenuItemsEnumR(head, &lvl->rnapoin, lvl->propname);
+}
+
+static uiBlock *ui_block_func_MENU_ITEM(bContext *C, uiPopupBlockHandle *handle, void *arg_info)
+{
+ uiBlock *block;
+ uiBut *but;
+ uiMenuInfo *info= arg_info;
+ uiMenuItem *head, *item;
+ MenuItemLevel *lvl;
+ ScrArea *sa;
+ ARegion *ar;
+ static int counter= 0;
+ int width, height, icon;
+ int startx, starty, x1, y1;
+ char str[16];
+
+ head= info->head;
+ height= 0;
+
+ /* block stuff first, need to know the font */
+ sprintf(str, "tb %d", counter++);
+ block= uiBeginBlock(C, handle->region, str, UI_EMBOSSP);
+ uiBlockSetButmFunc(block, head->eventfunc, head->argv);
+ block->direction= UI_DOWN;
+
+ width= 50; // fixed with, uiMenuPopupBoundsBlock will compute actual width
+
+ for(item= head->items.first; item; item= item->next) {
+ if(0) height+= PUP_LABELH; // XXX sepr line
+ else height+= MENU_BUTTON_HEIGHT;
+ }
+
+ startx= 0;
+ starty= 0;
+
+ /* here we go! */
+ if(head->name[0]) {
+ char titlestr[256];
+
+ if(head->icon) {
+ width+= 20;
+ sprintf(titlestr, " %s", head->name);
+ uiDefIconTextBut(block, LABEL, 0, head->icon, titlestr, startx, (short)(starty+height), width, MENU_BUTTON_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
+ }
+ else {
+ but= uiDefBut(block, LABEL, 0, head->name, startx, (short)(starty+height), width, MENU_BUTTON_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
+ but->flag= UI_TEXT_LEFT;
+ }
+
+ //uiDefBut(block, SEPR, 0, "", startx, (short)(starty+height)-MENU_SEPR_HEIGHT, width, MENU_SEPR_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
+ }
+
+ x1= startx;
+ y1= starty + height - MENU_BUTTON_HEIGHT; // - MENU_SEPR_HEIGHT;
+
+ for(item= head->items.first; item; item= item->next) {
+
+ if(item->type==MENU_ITEM_LEVEL) {
+ uiDefIconTextMenuBut(block, item->newlevel, NULL, ICON_RIGHTARROW_THIN, item->name, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, NULL);
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_LEVEL_OPNAME_ENUM) {
+ but= uiDefIconTextMenuBut(block, menu_item_enum_opname_menu, NULL, ICON_RIGHTARROW_THIN, item->name, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, NULL);
+
+ /* XXX warning, abuse of func_arg! */
+ lvl= MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
+ lvl->opname= item->opname;
+ lvl->propname= item->propname;
+ lvl->opcontext= item->opcontext;
+
+ but->poin= (char*)but;
+ but->func_argN= lvl;
+
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_LEVEL_RNA_ENUM) {
+ but= uiDefIconTextMenuBut(block, menu_item_enum_rna_menu, NULL, ICON_RIGHTARROW_THIN, item->name, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, NULL);
+
+ /* XXX warning, abuse of func_arg! */
+ lvl= MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
+ lvl->rnapoin= item->rnapoin;
+ lvl->propname= item->propname;
+ lvl->opcontext= item->opcontext;
+
+ but->poin= (char*)but;
+ but->func_argN= lvl;
+
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_OPNAME_BOOL) {
+ but= uiDefIconTextButO(block, BUTM, item->opname, item->opcontext, item->icon, item->name, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, "");
+ RNA_boolean_set(uiButGetOperatorPtrRNA(but), item->propname, item->boolval);
+
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_OPNAME_ENUM) {
+ const char *name;
+ char bname[64];
+
+ /* If no name is given, use the enum name */
+ if (item->name[0] == '\0')
+ name= ui_menu_enumpropname(item->opname, item->propname, item->enumval);
+ else
+ name= item->name;
+
+ BLI_strncpy(bname, name, sizeof(bname));
+
+ but= uiDefIconTextButO(block, BUTM, item->opname, item->opcontext, item->icon, bname, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, "");
+ RNA_enum_set(uiButGetOperatorPtrRNA(but), item->propname, item->enumval);
+
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_OPNAME_INT) {
+ but= uiDefIconTextButO(block, BUTM, item->opname, head->opcontext, item->icon, item->name, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, "");
+ RNA_int_set(uiButGetOperatorPtrRNA(but), item->propname, item->intval);
+
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_OPNAME_FLOAT) {
+ but= uiDefIconTextButO(block, BUTM, item->opname, item->opcontext, item->icon, item->name, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, "");
+ RNA_float_set(uiButGetOperatorPtrRNA(but), item->propname, item->fltval);
+
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_OPNAME_STRING) {
+ but= uiDefIconTextButO(block, BUTM, item->opname, item->opcontext, item->icon, item->name, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, "");
+ RNA_string_set(uiButGetOperatorPtrRNA(but), item->propname, item->strval);
+
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_OPNAME) {
+ uiDefIconTextButO(block, BUTM, item->opname, item->opcontext, item->icon, NULL, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, NULL);
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_RNA_BOOL) {
+ PropertyRNA *prop= RNA_struct_find_property(&item->rnapoin, item->propname);
+
+ if(prop && RNA_property_type(prop) == PROP_BOOLEAN) {
+ icon= (RNA_property_boolean_get(&item->rnapoin, prop))? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT;
+ uiDefIconTextButR(block, TOG, 0, icon, NULL, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, &item->rnapoin, item->propname, 0, 0, 0, 0, 0, NULL);
+ }
+ else {
+ uiBlockSetButLock(block, 1, "");
+ uiDefIconTextBut(block, BUT, 0, ICON_BLANK1, item->propname, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, NULL, 0.0, 0.0, 0, 0, "");
+ uiBlockClearButLock(block);
+ }
+
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type==MENU_ITEM_RNA_ENUM) {
+ PropertyRNA *prop= RNA_struct_find_property(&item->rnapoin, item->propname);
+
+ if(prop && RNA_property_type(prop) == PROP_ENUM) {
+ icon= (RNA_property_enum_get(&item->rnapoin, prop) == item->enumval)? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT;
+ uiDefIconTextButR(block, ROW, 0, icon, NULL, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, &item->rnapoin, item->propname, 0, 0, item->enumval, 0, 0, NULL);
+ }
+ else {
+ uiBlockSetButLock(block, 1, "");
+ uiDefIconTextBut(block, BUT, 0, ICON_BLANK1, item->propname, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, NULL, 0.0, 0.0, 0, 0, "");
+ uiBlockClearButLock(block);
+ }
+
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else if(item->type == MENU_ITEM_ITEM) {
+ uiDefIconTextButF(block, BUTM, B_NOP, item->icon, item->name, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, &handle->retvalue, 0.0, 0.0, 0, item->retval, "");
+ y1 -= MENU_BUTTON_HEIGHT;
+ }
+ else {
+ uiDefBut(block, SEPR, 0, "", x1, y1, width+16, MENU_SEPR_HEIGHT-1, NULL, 0.0, 0.0, 0, 0, "");
+ y1 -= MENU_SEPR_HEIGHT;
+ }
+ }
+
+ if(info->popup) {
+ uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT|UI_BLOCK_RET_1);
+ uiBlockSetDirection(block, UI_DOWN);
+
+ /* here we set an offset for the mouse position */
+ uiMenuPopupBoundsBlock(block, 1, 0, -height+MENU_BUTTON_HEIGHT/2);
+ }
+ else {
+ /* for a header menu we set the direction automatic */
+ if(!info->slideout) {
+ sa= CTX_wm_area(C);
+ ar= CTX_wm_region(C);
+
+ if(sa && sa->headertype==HEADERDOWN) {
+ if(ar && ar->regiontype == RGN_TYPE_HEADER) {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+ }
+ }
+
+ uiTextBoundsBlock(block, 50);
+ }
+
+ /* if menu slides out of other menu, override direction */
+ if(info->slideout)
+ uiBlockSetDirection(block, UI_RIGHT);
+
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut *but, uiMenuCreateFunc menu_func, void *arg)
+{
+ uiPopupBlockHandle *handle;
+ uiMenuItem *head;
+ uiMenuInfo info;
+
+ head= MEM_callocN(sizeof(uiMenuItem), "menu dummy");
+ head->opcontext= WM_OP_INVOKE_REGION_WIN;
+
+ menu_func(C, head, arg);
+
+ memset(&info, 0, sizeof(info));
+ info.head= head;
+ info.slideout= (but && (but->block->flag & UI_BLOCK_LOOP));
+
+ handle= ui_popup_block_create(C, butregion, but, NULL, ui_block_func_MENU_ITEM, &info);
+
+ BLI_freelistN(&head->items);
+ MEM_freeN(head);
+
+ return handle;
+}
+
+/*************************** Menu Creating API **************************/
+
+/* internal add func */
+static uiMenuItem *ui_menu_add_item(uiMenuItem *head, const char *name, int icon, int argval)
+{
+ uiMenuItem *item= MEM_callocN(sizeof(uiMenuItem), "menu item");
+
+ BLI_strncpy(item->name, name, MAX_MENU_STR);
+ if(icon)
+ item->icon= icon;
+ else
+ item->icon= ICON_BLANK1;
+ item->retval= argval;
+
+ item->opcontext= head->opcontext;
+
+ BLI_addtail(&head->items, item);
+
+ return item;
+}
+
+/* set callback for regular items */
+void uiMenuFunc(uiMenuItem *head, void (*eventfunc)(bContext *, void *, int), void *argv)
+{
+ head->eventfunc= eventfunc;
+ head->argv= argv;
+}
+
+/* optionally set different context for all items in one level */
+void uiMenuContext(uiMenuItem *head, int opcontext)
+{
+ head->opcontext= opcontext;
+}
+
+
+/* regular item, with retval */
+void uiMenuItemVal(uiMenuItem *head, const char *name, int icon, int argval)
+{
+ uiMenuItem *item= ui_menu_add_item(head, name, icon, argval);
+
+ item->type = MENU_ITEM_ITEM;
+}
+
+/* regular operator item */
+void uiMenuItemO(uiMenuItem *head, int icon, char *opname)
+{
+ uiMenuItem *item= ui_menu_add_item(head, "", icon, 0);
+
+ item->opname= opname; // static!
+ item->type = MENU_ITEM_OPNAME;
+}
+
+/* single operator item with property */
+void uiMenuItemEnumO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, int value)
+{
+ uiMenuItem *item= ui_menu_add_item(head, name, icon, 0);
+
+ item->opname= opname; // static!
+ item->propname= propname; // static!
+ item->enumval= value;
+ item->type = MENU_ITEM_OPNAME_ENUM;
+}
+
+/* single operator item with property */
+void uiMenuItemIntO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, int value)
+{
+ uiMenuItem *item= ui_menu_add_item(head, name, icon, 0);
+
+ item->opname= opname; // static!
+ item->propname= propname; // static!
+ item->intval= value;
+ item->type = MENU_ITEM_OPNAME_INT;
+}
+
+/* single operator item with property */
+void uiMenuItemFloatO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, float value)
+{
+ uiMenuItem *item= ui_menu_add_item(head, name, icon, 0);
+
+ item->opname= opname; // static!
+ item->propname= propname; // static!
+ item->fltval= value;
+ item->type = MENU_ITEM_OPNAME_FLOAT;
+}
+
+/* single operator item with property */
+void uiMenuItemBooleanO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, int value)
+{
+ uiMenuItem *item= ui_menu_add_item(head, name, icon, 0);
+
+ item->opname= opname; // static!
+ item->propname= propname; // static!
+ item->boolval= value;
+ item->type = MENU_ITEM_OPNAME_BOOL;
+}
+
+/* single operator item with property */
+void uiMenuItemStringO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, char *value)
+{
+ uiMenuItem *item= ui_menu_add_item(head, name, icon, 0);
+
+ item->opname= opname; // static!
+ item->propname= propname; // static!
+ item->strval= value;
+ item->type = MENU_ITEM_OPNAME_STRING;
+}
+
+/* add all operator items with property */
+void uiMenuItemsEnumO(uiMenuItem *head, char *opname, char *propname)
+{
+ wmOperatorType *ot= WM_operatortype_find(opname);
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ if(!ot || !ot->srna)
+ return;
+
+ RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
+ prop= RNA_struct_find_property(&ptr, propname);
+
+ if(prop && RNA_property_type(prop) == PROP_ENUM) {
+ const EnumPropertyItem *item;
+ int totitem, i;
+
+ RNA_property_enum_items(&ptr, prop, &item, &totitem);
+
+ for (i=0; i<totitem; i++)
+ uiMenuItemEnumO(head, "", 0, opname, propname, item[i].value);
+ }
+}
+
+/* rna property toggle */
+void uiMenuItemBooleanR(uiMenuItem *head, PointerRNA *ptr, char *propname)
+{
+ uiMenuItem *item= ui_menu_add_item(head, "", 0, 0);
+
+ item->propname= propname; // static!
+ item->rnapoin= *ptr;
+ item->type = MENU_ITEM_RNA_BOOL;
+}
+
+void uiMenuItemEnumR(uiMenuItem *head, PointerRNA *ptr, char *propname, int value)
+{
+ uiMenuItem *item= ui_menu_add_item(head, "", 0, 0);
+
+ item->propname= propname; // static!
+ item->rnapoin= *ptr;
+ item->enumval= value;
+ item->type = MENU_ITEM_RNA_ENUM;
+}
+
+/* add all rna items with property */
+void uiMenuItemsEnumR(uiMenuItem *head, PointerRNA *ptr, char *propname)
+{
+ PropertyRNA *prop;
+
+ prop= RNA_struct_find_property(ptr, propname);
+
+ if(prop && RNA_property_type(prop) == PROP_ENUM) {
+ const EnumPropertyItem *item;
+ int totitem, i;
+
+ RNA_property_enum_items(ptr, prop, &item, &totitem);
+
+ for (i=0; i<totitem; i++)
+ uiMenuItemEnumR(head, ptr, propname, item[i].value);
+ }
+}
+
+/* generic new menu level */
+void uiMenuLevel(uiMenuItem *head, const char *name, uiMenuCreateFunc newlevel)
+{
+ uiMenuItem *item= ui_menu_add_item(head, name, 0, 0);
+
+ item->type = MENU_ITEM_LEVEL;
+ item->newlevel= newlevel;
+}
+
+/* make a new level from enum properties */
+void uiMenuLevelEnumO(uiMenuItem *head, char *opname, char *propname)
+{
+ uiMenuItem *item= ui_menu_add_item(head, "", 0, 0);
+ wmOperatorType *ot;
+
+ item->type = MENU_ITEM_LEVEL_OPNAME_ENUM;
+ ot= WM_operatortype_find(opname);
+ if(ot)
+ BLI_strncpy(item->name, ot->name, MAX_MENU_STR);
+
+ item->opname= opname; // static!
+ item->propname= propname; // static!
+}
+
+/* make a new level from enum properties */
+void uiMenuLevelEnumR(uiMenuItem *head, PointerRNA *ptr, char *propname)
+{
+ uiMenuItem *item= ui_menu_add_item(head, "", 0, 0);
+ PropertyRNA *prop;
+
+ item->type = MENU_ITEM_LEVEL_RNA_ENUM;
+ prop= RNA_struct_find_property(ptr, propname);
+ if(prop)
+ BLI_strncpy(item->name, RNA_property_ui_name(prop), MAX_MENU_STR);
+
+ item->rnapoin= *ptr;
+ item->propname= propname; // static!
+}
+
+/* separator */
+void uiMenuSeparator(uiMenuItem *head)
+{
+ uiMenuItem *item= ui_menu_add_item(head, "", 0, 0);
+
+ item->type = MENU_ITEM_SEPARATOR;
+}
+
+/*************************** Popup Menu API **************************/
+
+/* only return handler, and set optional title */
+uiMenuItem *uiPupMenuBegin(const char *title, int icon)
+{
+ uiMenuItem *item= MEM_callocN(sizeof(uiMenuItem), "menu start");
+
+ item->type = MENU_ITEM_TITLE;
+ item->opcontext= WM_OP_EXEC_REGION_WIN;
+ item->icon= icon;
+
+ /* NULL is no title */
+ if(title)
+ BLI_strncpy(item->name, title, MAX_MENU_STR);
+
+ return item;
+}
+
+/* set the whole structure to work */
+void uiPupMenuEnd(bContext *C, uiMenuItem *head)
+{
+ wmWindow *window= CTX_wm_window(C);
+ uiMenuInfo info;
+ uiPopupBlockHandle *menu;
+
+ memset(&info, 0, sizeof(info));
+ info.popup= 1;
+ info.mx= window->eventstate->x;
+ info.my= window->eventstate->y;
+ info.head= head;
+
+ menu= ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_MENU_ITEM, &info);
+ menu->popup= 1;
+
+ UI_add_popup_handlers(C, &window->handlers, menu);
+ WM_event_add_mousemove(C);
+
+ BLI_freelistN(&head->items);
+ MEM_freeN(head);
+}
+
+/* ************** standard pupmenus *************** */
+
+/* this one can called with operatortype name and operators */
+static uiPopupBlockHandle *ui_pup_menu(bContext *C, int maxrow, uiMenuHandleFunc func, void *arg, char *str, ...)
+{
+ wmWindow *window= CTX_wm_window(C);
+ uiPupMenuInfo info;
+ uiPopupBlockHandle *menu;
+
+ memset(&info, 0, sizeof(info));
+ info.mx= window->eventstate->x;
+ info.my= window->eventstate->y;
+ info.maxrow= maxrow;
+ info.instr= str;
+
+ menu= ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_PUPMENU, &info);
+ menu->popup= 1;
+
+ UI_add_popup_handlers(C, &window->handlers, menu);
+ WM_event_add_mousemove(C);
+
+ menu->popup_func= func;
+ menu->popup_arg= arg;
+
+ return menu;
+}
+
+
+static void operator_name_cb(bContext *C, void *arg, int retval)
+{
+ const char *opname= arg;
+
+ if(opname && retval > 0)
+ WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
+}
+
+static void vconfirm_opname(bContext *C, char *opname, 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);
+
+ ui_pup_menu(C, 0, operator_name_cb, opname, buf);
+}
+
+static void operator_cb(bContext *C, void *arg, int retval)
+{
+ wmOperator *op= arg;
+
+ if(op && retval > 0)
+ WM_operator_call(C, op);
+ else
+ WM_operator_free(op);
+}
+
+static void confirm_cancel_operator(void *opv)
+{
+ WM_operator_free(opv);
+}
+
+static void confirm_operator(bContext *C, wmOperator *op, char *title, char *item)
+{
+ uiPopupBlockHandle *handle;
+ char *s, buf[512];
+
+ s= buf;
+ if (title) s+= sprintf(s, "%s%%t|%s", title, item);
+
+ handle= ui_pup_menu(C, 0, operator_cb, op, buf);
+ handle->cancel_func= confirm_cancel_operator;
+}
+
+
+void uiPupMenuOkee(bContext *C, char *opname, char *str, ...)
+{
+ va_list ap;
+ char titlestr[256];
+
+ sprintf(titlestr, "OK? %%i%d", ICON_HELP);
+
+ va_start(ap, str);
+ vconfirm_opname(C, opname, titlestr, str, ap);
+ va_end(ap);
+}
+
+
+void uiPupMenuSaveOver(bContext *C, wmOperator *op, char *filename)
+{
+ size_t len= strlen(filename);
+
+ if(len==0)
+ return;
+
+ if(filename[len-1]=='/' || filename[len-1]=='\\') {
+ uiPupMenuError(C, "Cannot overwrite a directory");
+ WM_operator_free(op);
+ return;
+ }
+ if(BLI_exists(filename)==0)
+ operator_cb(C, op, 1);
+ else
+ confirm_operator(C, op, "Save over", filename);
+}
+
+void uiPupMenuNotice(bContext *C, char *str, ...)
+{
+ va_list ap;
+
+ va_start(ap, str);
+ vconfirm_opname(C, NULL, NULL, str, ap);
+ va_end(ap);
+}
+
+void uiPupMenuError(bContext *C, char *str, ...)
+{
+ va_list ap;
+ char nfmt[256];
+ char titlestr[256];
+
+ sprintf(titlestr, "Error %%i%d", ICON_ERROR);
+
+ sprintf(nfmt, "%s", str);
+
+ va_start(ap, str);
+ vconfirm_opname(C, NULL, titlestr, nfmt, ap);
+ va_end(ap);
+}
+
+void uiPupMenuReports(bContext *C, ReportList *reports)
+{
+ Report *report;
+ DynStr *ds;
+ char *str;
+
+ if(!reports || !reports->list.first)
+ return;
+ if(!CTX_wm_window(C))
+ return;
+
+ ds= BLI_dynstr_new();
+
+ for(report=reports->list.first; report; report=report->next) {
+ if(report->type >= RPT_ERROR)
+ BLI_dynstr_appendf(ds, "Error %%i%d%%t|%s", ICON_ERROR, report->message);
+ else if(report->type >= RPT_WARNING)
+ BLI_dynstr_appendf(ds, "Warning %%i%d%%t|%s", ICON_ERROR, report->message);
+ }
+
+ str= BLI_dynstr_get_cstring(ds);
+ ui_pup_menu(C, 0, NULL, NULL, str);
+ MEM_freeN(str);
+
+ BLI_dynstr_free(ds);
+}
+
+/*************************** Popup Block API **************************/
+
+void uiPupBlockO(bContext *C, uiBlockCreateFunc func, void *arg, char *opname, int opcontext)
+{
+ wmWindow *window= CTX_wm_window(C);
+ uiPopupBlockHandle *handle;
+
+ handle= ui_popup_block_create(C, NULL, NULL, func, NULL, arg);
+ handle->popup= 1;
+ handle->opname= opname;
+ handle->opcontext= opcontext;
+
+ UI_add_popup_handlers(C, &window->handlers, handle);
+ WM_event_add_mousemove(C);
+}
+
+void uiPupBlock(bContext *C, uiBlockCreateFunc func, void *arg)
+{
+ uiPupBlockO(C, func, arg, NULL, 0);
+}
+
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
new file mode 100644
index 00000000000..99702097329
--- /dev/null
+++ b/source/blender/editors/interface/interface_style.c
@@ -0,0 +1,263 @@
+/**
+* ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ID.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_listbase.h"
+#include "BLI_rect.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "BLF_api.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_datafiles.h"
+#include "ED_util.h"
+#include "ED_types.h"
+
+#include "interface_intern.h"
+
+
+/* style + theme + layout-engine = UI */
+
+/*
+ This is a complete set of layout rules, the 'state' of the Layout
+ Engine. Multiple styles are possible, defined via C or Python. Styles
+ get a name, and will typically get activated per region type, like
+ "Header", or "Listview" or "Toolbar". Properties of Style definitions
+ are:
+
+ - default collumn properties, internal spacing, aligning, min/max width
+ - button alignment rules (for groups)
+ - label placement rules
+ - internal labeling or external labeling default
+ - default minimum widths for buttons/labels (in amount of characters)
+ - font types, styles and relative sizes for Panel titles, labels, etc.
+
+*/
+
+
+/* ********************************************** */
+
+static uiStyle *ui_style_new(ListBase *styles, const char *name)
+{
+ uiStyle *style= MEM_callocN(sizeof(uiStyle), "new style");
+
+ BLI_addtail(styles, style);
+ BLI_strncpy(style->name, name, MAX_STYLE_NAME);
+
+ style->paneltitle.uifont_id= UIFONT_DEFAULT;
+ style->paneltitle.points= 14;
+ style->paneltitle.shadow= 5;
+ style->paneltitle.shadx= 2;
+ style->paneltitle.shady= -2;
+ style->paneltitle.shadowalpha= 0.25f;
+ style->paneltitle.shadowcolor= 0.0f;
+
+ style->grouplabel.uifont_id= UIFONT_DEFAULT;
+ style->grouplabel.points= 12;
+ style->grouplabel.shadow= 3;
+ style->grouplabel.shadx= 1;
+ style->grouplabel.shady= -1;
+ style->grouplabel.shadowalpha= 0.25f;
+
+ style->widgetlabel.uifont_id= UIFONT_DEFAULT;
+ style->widgetlabel.points= 11;
+ style->widgetlabel.shadow= 3;
+ style->widgetlabel.shadx= 1;
+ style->widgetlabel.shady= -1;
+ style->widgetlabel.shadowalpha= 0.3f;
+ style->widgetlabel.shadowcolor= 1.0f;
+
+ style->widget.uifont_id= UIFONT_DEFAULT;
+ style->widget.points= 11;
+ style->widget.shadowalpha= 0.25f;
+
+ return style;
+}
+
+static uiFont *uifont_to_blfont(int id)
+{
+ uiFont *font= U.uifonts.first;
+
+ for(; font; font= font->next) {
+ if(font->uifont_id==id) {
+ return font;
+ }
+ }
+ return U.uifonts.first;
+}
+
+/* *************** draw ************************ */
+
+static void ui_font_shadow_draw(uiFontStyle *fs, int x, int y, char *str)
+{
+ float color[4];
+
+ glGetFloatv(GL_CURRENT_COLOR, color);
+
+ glColor4f(fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha);
+
+ BLF_blur(fs->shadow);
+ BLF_position(x+fs->shadx, y+fs->shady, 0.0f);
+ BLF_draw(str);
+ BLF_blur(0);
+
+ glColor4fv(color);
+}
+
+void uiStyleFontDraw(uiFontStyle *fs, rcti *rect, char *str)
+{
+ float height;
+ int xofs=0, yofs;
+
+ uiStyleFontSet(fs);
+
+ height= BLF_height("A");
+ yofs= floor( 0.5f*(rect->ymax - rect->ymin - height));
+
+ if(fs->align==UI_STYLE_TEXT_CENTER)
+ xofs= floor( 0.5f*(rect->xmax - rect->xmin - BLF_width(str)));
+ else if(fs->align==UI_STYLE_TEXT_RIGHT)
+ xofs= rect->xmax - rect->xmin - BLF_width(str);
+
+ /* clip is very strict, so we give it some space */
+ BLF_clipping(rect->xmin-4, rect->ymin-4, rect->xmax+4, rect->ymax+4);
+ BLF_enable(BLF_CLIPPING);
+
+ if(fs->shadow)
+ ui_font_shadow_draw(fs, rect->xmin+xofs, rect->ymin+yofs, str);
+
+ BLF_position(rect->xmin+xofs, rect->ymin+yofs, 0.0f);
+ BLF_draw(str);
+
+ BLF_disable(BLF_CLIPPING);
+}
+
+/* ************** helpers ************************ */
+
+/* temporarily, does widget font */
+int UI_GetStringWidth(char *str)
+{
+ uiStyle *style= U.uistyles.first;
+
+ uiStyleFontSet(&style->widget);
+ return BLF_width(str);
+}
+
+/* temporarily, does widget font */
+void UI_DrawString(float x, float y, char *str)
+{
+ uiStyle *style= U.uistyles.first;
+
+ uiStyleFontSet(&style->widget);
+ BLF_position(x, y, 0.0f);
+ BLF_draw(str);
+}
+
+/* ************** init exit ************************ */
+
+/* called on each .B.blend read */
+/* reading without uifont will create one */
+void uiStyleInit(void)
+{
+ uiFont *font= U.uifonts.first;
+ uiStyle *style= U.uistyles.first;
+
+ /* recover from uninitialized dpi */
+ CLAMP(U.dpi, 72, 240);
+
+ /* default builtin */
+ if(font==NULL) {
+ font= MEM_callocN(sizeof(uiFont), "ui font");
+ BLI_addtail(&U.uifonts, font);
+
+ strcpy(font->filename, "default");
+ font->uifont_id= UIFONT_DEFAULT;
+ }
+
+ for(font= U.uifonts.first; font; font= font->next) {
+
+ if(font->uifont_id==UIFONT_DEFAULT) {
+ font->blf_id= BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
+ }
+ else {
+ font->blf_id= BLF_load(font->filename);
+ if(font->blf_id == -1)
+ font->blf_id= BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
+ }
+
+ if (font->blf_id == -1)
+ printf("uiStyleInit error, no fonts available\n");
+ else {
+ BLF_set(font->blf_id);
+ BLF_size(11, U.dpi); /* ? just for speed to initialize? */
+ BLF_size(12, U.dpi);
+ BLF_size(14, U.dpi);
+ }
+ }
+
+ if(style==NULL) {
+ ui_style_new(&U.uistyles, "Default Style");
+ }
+}
+
+
+void uiStyleExit(void)
+{
+ BLI_freelistN(&U.uifonts);
+ BLI_freelistN(&U.uistyles);
+
+}
+
+void uiStyleFontSet(uiFontStyle *fs)
+{
+ uiFont *font= uifont_to_blfont(fs->uifont_id);
+
+ BLF_set(font->blf_id);
+ BLF_size(fs->points, U.dpi);
+}
+
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
new file mode 100644
index 00000000000..5ef1e68bd59
--- /dev/null
+++ b/source/blender/editors/interface/interface_utils.c
@@ -0,0 +1,1060 @@
+/**
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_color_types.h"
+#include "DNA_listBase.h"
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_idprop.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "ED_screen.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#define DEF_BUT_WIDTH 150
+#define DEF_ICON_BUT_WIDTH 20
+#define DEF_BUT_HEIGHT 20
+
+/*************************** RNA Utilities ******************************/
+
+int UI_GetIconRNA(PointerRNA *ptr)
+{
+ StructRNA *rnatype= ptr->type;
+
+ if(rnatype == &RNA_Scene)
+ return ICON_SCENE_DATA;
+ else if(rnatype == &RNA_World)
+ return ICON_WORLD_DATA;
+ else if(rnatype == &RNA_Object)
+ return ICON_OBJECT_DATA;
+ else if(rnatype == &RNA_Mesh)
+ return ICON_MESH_DATA;
+ else if(rnatype == &RNA_MeshVertex)
+ return ICON_VERTEXSEL;
+ else if(rnatype == &RNA_MeshEdge)
+ return ICON_EDGESEL;
+ else if(rnatype == &RNA_MeshFace)
+ return ICON_FACESEL;
+ else if(rnatype == &RNA_MeshTextureFace)
+ return ICON_FACESEL_HLT;
+ else if(rnatype == &RNA_VertexGroup)
+ return ICON_VGROUP;
+ else if(rnatype == &RNA_VertexGroupElement)
+ return ICON_VGROUP;
+ else if(rnatype == &RNA_Curve)
+ return ICON_CURVE_DATA;
+ else if(rnatype == &RNA_MetaBall)
+ return ICON_MBALL_DATA;
+ else if(rnatype == &RNA_MetaElement)
+ return ICON_OUTLINER_DATA_META;
+ else if(rnatype == &RNA_Lattice)
+ return ICON_LATTICE_DATA;
+ else if(rnatype == &RNA_Armature)
+ return ICON_ARMATURE_DATA;
+ else if(rnatype == &RNA_Bone)
+ return ICON_BONE_DATA;
+ else if(rnatype == &RNA_Camera)
+ return ICON_CAMERA_DATA;
+ else if(rnatype == &RNA_LocalLamp)
+ return ICON_LAMP_DATA;
+ else if(rnatype == &RNA_AreaLamp)
+ return ICON_LAMP_DATA;
+ else if(rnatype == &RNA_SpotLamp)
+ return ICON_LAMP_DATA;
+ else if(rnatype == &RNA_SunLamp)
+ return ICON_LAMP_DATA;
+ else if(rnatype == &RNA_HemiLamp)
+ return ICON_LAMP_DATA;
+ else if(rnatype == &RNA_Lamp)
+ return ICON_LAMP_DATA;
+ else if(rnatype == &RNA_Group)
+ return ICON_GROUP;
+ else if(rnatype == &RNA_ParticleSystem)
+ return ICON_PARTICLE_DATA;
+ else if(rnatype == &RNA_ParticleSettings)
+ return ICON_PARTICLE_DATA;
+ else if(rnatype == &RNA_Material)
+ return ICON_MATERIAL_DATA;
+ else if(rnatype == &RNA_Texture)
+ return ICON_TEXTURE_DATA;
+ else if(rnatype == &RNA_TextureSlot)
+ return ICON_TEXTURE_DATA;
+ else if(rnatype == &RNA_WorldTextureSlot)
+ return ICON_TEXTURE_DATA;
+ else if(rnatype == &RNA_MaterialTextureSlot)
+ return ICON_TEXTURE_DATA;
+ else if(rnatype == &RNA_Image)
+ return ICON_IMAGE_DATA;
+ else if(rnatype == &RNA_Screen)
+ return ICON_SPLITSCREEN;
+ else if(rnatype == &RNA_NodeTree)
+ return ICON_NODE;
+ else if(rnatype == &RNA_Text)
+ return ICON_TEXT;
+ else if(rnatype == &RNA_Sound)
+ return ICON_SOUND;
+ else if(rnatype == &RNA_Brush)
+ return ICON_BRUSH_DATA;
+ else if(rnatype == &RNA_VectorFont)
+ return ICON_FONT;
+ else if(rnatype == &RNA_Library)
+ return ICON_LIBRARY_DATA_DIRECT;
+ else if(rnatype == &RNA_Action)
+ return ICON_ACTION;
+ else if(rnatype == &RNA_FCurve)
+ return ICON_ANIM_DATA;
+ //else if(rnatype == &RNA_Ipo)
+ // return ICON_ANIM_DATA;
+ else if(rnatype == &RNA_Key)
+ return ICON_SHAPEKEY_DATA;
+ else if(rnatype == &RNA_Main)
+ return ICON_BLENDER;
+ else if(rnatype == &RNA_Struct)
+ return ICON_RNA;
+ else if(rnatype == &RNA_Property)
+ return ICON_RNA;
+ else if(rnatype == &RNA_BooleanProperty)
+ return ICON_RNA;
+ else if(rnatype == &RNA_IntProperty)
+ return ICON_RNA;
+ else if(rnatype == &RNA_FloatProperty)
+ return ICON_RNA;
+ else if(rnatype == &RNA_StringProperty)
+ return ICON_RNA;
+ else if(rnatype == &RNA_EnumProperty)
+ return ICON_RNA;
+ else if(rnatype == &RNA_EnumPropertyItem)
+ return ICON_RNA;
+ else if(rnatype == &RNA_PointerProperty)
+ return ICON_RNA;
+ else if(rnatype == &RNA_CollectionProperty)
+ return ICON_RNA;
+ else if(rnatype == &RNA_GameObjectSettings)
+ return ICON_GAME;
+ else if(rnatype == &RNA_ScriptLink)
+ return ICON_PYTHON;
+
+ /* modifiers */
+ else if(rnatype == &RNA_SubsurfModifier)
+ return ICON_MOD_SUBSURF;
+ else if(rnatype == &RNA_ArmatureModifier)
+ return ICON_MOD_ARMATURE;
+ else if(rnatype == &RNA_LatticeModifier)
+ return ICON_MOD_LATTICE;
+ else if(rnatype == &RNA_CurveModifier)
+ return ICON_MOD_CURVE;
+ else if(rnatype == &RNA_BuildModifier)
+ return ICON_MOD_BUILD;
+ else if(rnatype == &RNA_MirrorModifier)
+ return ICON_MOD_MIRROR;
+ else if(rnatype == &RNA_DecimateModifier)
+ return ICON_MOD_DECIM;
+ else if(rnatype == &RNA_WaveModifier)
+ return ICON_MOD_WAVE;
+ else if(rnatype == &RNA_HookModifier)
+ return ICON_HOOK;
+ else if(rnatype == &RNA_SoftbodyModifier)
+ return ICON_MOD_SOFT;
+ else if(rnatype == &RNA_BooleanModifier)
+ return ICON_MOD_BOOLEAN;
+ else if(rnatype == &RNA_ParticleInstanceModifier)
+ return ICON_MOD_PARTICLEINSTANCE;
+ else if(rnatype == &RNA_ParticleSystemModifier)
+ return ICON_MOD_PARTICLES;
+ else if(rnatype == &RNA_EdgeSplitModifier)
+ return ICON_MOD_EDGESPLIT;
+ else if(rnatype == &RNA_ArrayModifier)
+ return ICON_MOD_ARRAY;
+ else if(rnatype == &RNA_UVProjectModifier)
+ return ICON_MOD_UVPROJECT;
+ else if(rnatype == &RNA_DisplaceModifier)
+ return ICON_MOD_DISPLACE;
+ else
+ return ICON_DOT;
+}
+
+uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int index, char *name, int icon, int x1, int y1, int x2, int y2)
+{
+ uiBut *but=NULL;
+ const char *propname= RNA_property_identifier(prop);
+ int arraylen= RNA_property_array_length(prop);
+
+ switch(RNA_property_type(prop)) {
+ case PROP_BOOLEAN: {
+ int value, length;
+
+ if(arraylen && index == -1)
+ return NULL;
+
+ length= RNA_property_array_length(prop);
+
+ if(length)
+ value= RNA_property_boolean_get_index(ptr, prop, index);
+ else
+ value= RNA_property_boolean_get(ptr, prop);
+
+ if(icon && name && strcmp(name, "") == 0)
+ but= uiDefIconButR(block, ICONTOG, 0, icon, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
+ else if(icon)
+ but= uiDefIconTextButR(block, ICONTOG, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
+ else
+ but= uiDefButR(block, TOG, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
+ break;
+ }
+ case PROP_INT:
+ case PROP_FLOAT:
+ if(arraylen && index == -1) {
+ if(RNA_property_subtype(prop) == PROP_COLOR)
+ but= uiDefButR(block, COL, 0, name, x1, y1, x2, y2, ptr, propname, 0, 0, 0, -1, -1, NULL);
+ }
+ else if(RNA_property_subtype(prop) == PROP_PERCENTAGE)
+ but= uiDefButR(block, NUMSLI, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
+ else
+ but= uiDefButR(block, NUM, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
+ break;
+ case PROP_ENUM:
+ but= uiDefButR(block, MENU, 0, NULL, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
+ break;
+ case PROP_STRING:
+ but= uiDefButR(block, TEX, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
+ break;
+ case PROP_POINTER: {
+ PointerRNA pptr;
+ int icon;
+
+ pptr= RNA_property_pointer_get(ptr, prop);
+ if(!pptr.type)
+ pptr.type= RNA_property_pointer_type(prop);
+ icon= UI_GetIconRNA(&pptr);
+
+ but= uiDefIconTextButR(block, IDPOIN, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
+ break;
+ }
+ case PROP_COLLECTION: {
+ char text[256];
+ sprintf(text, "%d items", RNA_property_collection_length(ptr, prop));
+ but= uiDefBut(block, LABEL, 0, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, NULL);
+ uiButSetFlag(but, UI_BUT_DISABLED);
+ break;
+ }
+ default:
+ but= NULL;
+ break;
+ }
+
+ return but;
+}
+
+int uiDefAutoButsRNA(const bContext *C, uiBlock *block, PointerRNA *ptr)
+{
+ CollectionPropertyIterator iter;
+ PropertyRNA *iterprop, *prop;
+ uiLayout *layout;
+ char *name;
+ int x= 0, y= 0;
+
+ layout= uiLayoutBegin(UI_LAYOUT_VERTICAL, x, y, DEF_BUT_WIDTH*2, 20);
+
+ uiLayoutColumn(layout);
+ uiItemL(layout, (char*)RNA_struct_ui_name(ptr->type), 0);
+
+ iterprop= RNA_struct_iterator_property(ptr->type);
+ RNA_property_collection_begin(ptr, iterprop, &iter);
+
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ prop= iter.ptr.data;
+
+ if(strcmp(RNA_property_identifier(prop), "rna_type") == 0)
+ continue;
+
+ uiLayoutSplit(layout, 2, 0);
+
+ name= (char*)RNA_property_ui_name(prop);
+ uiLayoutColumn(uiLayoutSub(layout, 0));
+ uiItemL(uiLayoutSub(layout, 0), name, 0);
+ uiLayoutColumn(uiLayoutSub(layout, 1));
+ uiItemFullR(uiLayoutSub(layout, 1), "", 0, ptr, prop, -1, 0);
+ }
+
+ RNA_property_collection_end(&iter);
+ uiLayoutEnd(C, block, layout, &x, &y);
+
+ return -y;
+}
+
+/***************************** ID Utilities *******************************/
+
+typedef struct uiIDPoinParams {
+ uiIDPoinFunc func;
+ ID *id;
+ short id_code;
+ short browsenr;
+} uiIDPoinParams;
+
+static void idpoin_cb(bContext *C, void *arg_params, void *arg_event)
+{
+ Main *bmain;
+ ListBase *lb;
+ uiIDPoinParams *params= (uiIDPoinParams*)arg_params;
+ uiIDPoinFunc func= params->func;
+ ID *id= params->id, *idtest;
+ int nr, event= GET_INT_FROM_POINTER(arg_event);
+
+ bmain= CTX_data_main(C);
+ lb= wich_libbase(bmain, params->id_code);
+
+ if(event == UI_ID_BROWSE && params->browsenr == 32767)
+ event= UI_ID_ADD_NEW;
+ else if(event == UI_ID_BROWSE && params->browsenr == 32766)
+ event= UI_ID_OPEN;
+
+ switch(event) {
+ case UI_ID_RENAME:
+ if(id) test_idbutton(id->name+2);
+ else return;
+ break;
+ case UI_ID_BROWSE: {
+ if(id==0) id= lb->first;
+ if(id==0) return;
+
+ if(params->browsenr== -2) {
+ /* XXX implement or find a replacement
+ * activate_databrowse((ID *)G.buts->lockpoin, GS(id->name), 0, B_MESHBROWSE, &params->browsenr, do_global_buttons); */
+ return;
+ }
+ if(params->browsenr < 0)
+ return;
+
+ for(idtest=lb->first, nr=1; idtest; idtest=idtest->next, nr++) {
+ if(nr==params->browsenr) {
+ if(id == idtest)
+ return;
+
+ id= idtest;
+
+ break;
+ }
+ }
+ break;
+ }
+ case UI_ID_DELETE:
+ id= NULL;
+ break;
+ case UI_ID_FAKE_USER:
+ if(id) {
+ if(id->flag & LIB_FAKEUSER) id->us++;
+ else id->us--;
+ }
+ else return;
+ break;
+ case UI_ID_PIN:
+ break;
+ case UI_ID_ADD_NEW:
+ break;
+ case UI_ID_OPEN:
+ break;
+ case UI_ID_ALONE:
+ if(!id || id->us < 1)
+ return;
+ break;
+ case UI_ID_LOCAL:
+ if(!id || id->us < 1)
+ return;
+ break;
+ case UI_ID_AUTO_NAME:
+ break;
+ }
+
+ if(func)
+ func(C, id, event);
+}
+
+int uiDefIDPoinButs(uiBlock *block, Main *bmain, ID *parid, ID *id, int id_code, short *pin_p, int x, int y, uiIDPoinFunc func, int events)
+{
+ ListBase *lb;
+ uiBut *but;
+ uiIDPoinParams *params, *dup_params;
+ char *str=NULL, str1[10];
+ int len, add_addbutton=0;
+
+ /* setup struct that we will pass on with the buttons */
+ params= MEM_callocN(sizeof(uiIDPoinParams), "uiIDPoinParams");
+ params->id= id;
+ params->id_code= id_code;
+ params->func= func;
+
+ lb= wich_libbase(bmain, id_code);
+
+ /* create buttons */
+ uiBlockBeginAlign(block);
+
+ /* XXX solve?
+ if(id && id->us>1)
+ uiBlockSetCol(block, TH_BUT_SETTING1);
+
+ if((events & UI_ID_PIN) && *pin_p)
+ uiBlockSetCol(block, TH_BUT_SETTING2);
+ */
+
+ /* pin button */
+ if(id && (events & UI_ID_PIN)) {
+ but= uiDefIconButS(block, ICONTOG, (events & UI_ID_PIN), ICON_KEY_DEHLT, x, y ,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, pin_p, 0, 0, 0, 0, "Keeps this view displaying the current data regardless of what object is selected");
+ uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_PIN));
+ x+= DEF_ICON_BUT_WIDTH;
+ }
+
+ /* browse menu */
+ if(events & UI_ID_BROWSE) {
+ char *extrastr= NULL;
+
+ if(ELEM4(id_code, ID_MA, ID_TE, ID_BR, ID_PA))
+ add_addbutton= 1;
+
+ if(ELEM8(id_code, ID_SCE, ID_SCR, ID_MA, ID_TE, ID_WO, ID_IP, ID_AC, ID_BR) || id_code == ID_PA)
+ extrastr= "ADD NEW %x 32767";
+ else if(id_code==ID_TXT)
+ extrastr= "OPEN NEW %x 32766 |ADD NEW %x 32767";
+ else if(id_code==ID_SO)
+ extrastr= "OPEN NEW %x 32766";
+
+ /* XXX should be moved out of this function
+ uiBlockSetButLock(block, G.scene->id.lib!=0, "Can't edit external libdata");
+ if( id_code==ID_SCE || id_code==ID_SCR ) uiBlockClearButLock(block); */
+
+ /* XXX should be moved out of this function
+ if(curarea->spacetype==SPACE_BUTS)
+ uiBlockSetButLock(block, id_code!=ID_SCR && G.obedit!=0 && G.buts->mainb==CONTEXT_EDITING, "Cannot perform in EditMode"); */
+
+ if(parid)
+ uiBlockSetButLock(block, parid->lib!=0, "Can't edit external libdata");
+
+ if(lb) {
+ if(id_code!=ID_IM || (events & UI_ID_BROWSE_RENDER))
+ IDnames_to_pupstring(&str, NULL, extrastr, lb, id, &params->browsenr);
+ else
+ IMAnames_to_pupstring(&str, NULL, extrastr, lb, id, &params->browsenr);
+ }
+
+ dup_params= MEM_dupallocN(params);
+ but= uiDefButS(block, MENU, 0, str, x, y, DEF_ICON_BUT_WIDTH, DEF_BUT_HEIGHT, &dup_params->browsenr, 0, 0, 0, 0, "Browse existing choices, or add new");
+ uiButSetNFunc(but, idpoin_cb, dup_params, SET_INT_IN_POINTER(UI_ID_BROWSE));
+ x+= DEF_ICON_BUT_WIDTH;
+
+ uiBlockClearButLock(block);
+
+ MEM_freeN(str);
+ }
+
+ /* text button with name */
+ if(id) {
+ /* XXX solve?
+ if(id->us > 1)
+ uiBlockSetCol(block, TH_BUT_SETTING1);
+ */
+ /* pinned data?
+ if((events & UI_ID_PIN) && *pin_p)
+ uiBlockSetCol(block, TH_BUT_SETTING2);
+ */
+ /* redalert overrides pin color
+ if(id->us<=0)
+ uiBlockSetCol(block, TH_REDALERT);
+ */
+ uiBlockSetButLock(block, id->lib!=0, "Can't edit external libdata");
+
+ /* name button */
+ if(GS(id->name)==ID_SCE)
+ strcpy(str1, "SCE:");
+ else if(GS(id->name)==ID_SCE)
+ strcpy(str1, "SCR:");
+ else if(GS(id->name)==ID_MA && ((Material*)id)->use_nodes)
+ strcpy(str1, "NT:");
+ else {
+ str1[0]= id->name[0];
+ str1[1]= id->name[1];
+ str1[2]= ':';
+ str1[3]= 0;
+ }
+
+ if(GS(id->name)==ID_IP) len= 110;
+ else if((y) && (GS(id->name)==ID_AC)) len= 100; // comes from button panel (poselib)
+ else if(y) len= 140; // comes from button panel
+ else len= 120;
+
+ but= uiDefBut(block, TEX, 0, str1,x, y, (short)len, DEF_BUT_HEIGHT, id->name+2, 0.0, 21.0, 0, 0, "Displays current Datablock name. Click to change.");
+ uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_RENAME));
+
+ x+= len;
+
+ uiBlockClearButLock(block);
+
+ /* lib make local button */
+ if(id->lib) {
+ if(id->flag & LIB_INDIRECT) uiDefIconBut(block, BUT, 0, 0 /* XXX ICON_DATALIB */,x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Indirect Library Datablock. Cannot change.");
+ else {
+ but= uiDefIconBut(block, BUT, 0, 0 /* XXX ICON_PARLIB */, x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0,
+ (events & UI_ID_LOCAL)? "Direct linked Library Datablock. Click to make local.": "Direct linked Library Datablock, cannot make local.");
+ uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_ALONE));
+ }
+
+ x+= DEF_ICON_BUT_WIDTH;
+ }
+
+ /* number of users / make local button */
+ if((events & UI_ID_ALONE) && id->us>1) {
+ int butwidth;
+
+ uiBlockSetButLock(block, (events & UI_ID_PIN) && *pin_p, "Can't make pinned data single-user");
+
+ sprintf(str1, "%d", id->us);
+ butwidth= (id->us<10)? DEF_ICON_BUT_WIDTH: DEF_ICON_BUT_WIDTH+10;
+
+ but= uiDefBut(block, BUT, 0, str1, x, y, butwidth, DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
+ uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_ALONE));
+ x+= butwidth;
+
+ uiBlockClearButLock(block);
+ }
+
+ /* delete button */
+ if(events & UI_ID_DELETE) {
+ uiBlockSetButLock(block, (events & UI_ID_PIN) && *pin_p, "Can't unlink pinned data");
+ if(parid && parid->lib);
+ else {
+ but= uiDefIconBut(block, BUT, 0, ICON_X, x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Deletes link to this Datablock");
+ uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_DELETE));
+ x+= DEF_ICON_BUT_WIDTH;
+ }
+
+ uiBlockClearButLock(block);
+ }
+
+ /* auto name button */
+ if(events & UI_ID_AUTO_NAME) {
+ if(parid && parid->lib);
+ else {
+ but= uiDefIconBut(block, BUT, 0, ICON_AUTO,x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Generates an automatic name");
+ uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_AUTO_NAME));
+ x+= DEF_ICON_BUT_WIDTH;
+ }
+ }
+
+ /* fake user button */
+ if(events & UI_ID_FAKE_USER) {
+ but= uiDefButBitS(block, TOG, LIB_FAKEUSER, 0, "F", x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, &id->flag, 0, 0, 0, 0, "Saves this datablock even if it has no users");
+ uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_FAKE_USER));
+ x+= DEF_ICON_BUT_WIDTH;
+ }
+ }
+ /* add new button */
+ else if(add_addbutton) {
+ if(parid) uiBlockSetButLock(block, parid->lib!=0, "Can't edit external libdata");
+ dup_params= MEM_dupallocN(params);
+ but= uiDefButS(block, TOG, 0, "Add New", x, y, 110, DEF_BUT_HEIGHT, &dup_params->browsenr, params->browsenr, 32767.0, 0, 0, "Add new data block");
+ uiButSetNFunc(but, idpoin_cb, dup_params, SET_INT_IN_POINTER(UI_ID_ADD_NEW));
+ x+= 110;
+ }
+
+ uiBlockEndAlign(block);
+
+ MEM_freeN(params);
+
+ return x;
+}
+
+/* ****************************** default button callbacks ******************* */
+/* ************ LEGACY WARNING, only to get things work with 2.48 code! ****** */
+
+void test_idbutton_cb(struct bContext *C, void *namev, void *arg2)
+{
+ char *name= namev;
+
+ test_idbutton(name+2);
+}
+
+
+void test_scriptpoin_but(struct bContext *C, char *name, ID **idpp)
+{
+ ID *id;
+
+ id= CTX_data_main(C)->text.first;
+ while(id) {
+ if( strcmp(name, id->name+2)==0 ) {
+ *idpp= id;
+ return;
+ }
+ id= id->next;
+ }
+ *idpp= NULL;
+}
+
+void test_actionpoin_but(struct bContext *C, char *name, ID **idpp)
+{
+ ID *id;
+
+ id= CTX_data_main(C)->action.first;
+ while(id) {
+ if( strcmp(name, id->name+2)==0 ) {
+ id_us_plus(id);
+ *idpp= id;
+ return;
+ }
+ id= id->next;
+ }
+ *idpp= NULL;
+}
+
+
+void test_obpoin_but(struct bContext *C, char *name, ID **idpp)
+{
+ ID *id;
+
+// XXX if(idpp == (ID **)&(emptytex.object)) {
+// error("You must add a texture first");
+// *idpp= 0;
+// return;
+// }
+
+ id= CTX_data_main(C)->object.first;
+ while(id) {
+ if( strcmp(name, id->name+2)==0 ) {
+ *idpp= id;
+ id_lib_extern(id); /* checks lib data, sets correct flag for saving then */
+ return;
+ }
+ id= id->next;
+ }
+ *idpp= NULL;
+}
+
+/* tests for an object of type OB_MESH */
+void test_meshobpoin_but(struct bContext *C, char *name, ID **idpp)
+{
+ ID *id;
+
+ id = CTX_data_main(C)->object.first;
+ while(id) {
+ Object *ob = (Object *)id;
+ if(ob->type == OB_MESH && strcmp(name, id->name + 2) == 0) {
+ *idpp = id;
+ /* checks lib data, sets correct flag for saving then */
+ id_lib_extern(id);
+ return;
+ }
+ id = id->next;
+ }
+ *idpp = NULL;
+}
+
+void test_meshpoin_but(struct bContext *C, char *name, ID **idpp)
+{
+ ID *id;
+
+ if( *idpp ) (*idpp)->us--;
+
+ id= CTX_data_main(C)->mesh.first;
+ while(id) {
+ if( strcmp(name, id->name+2)==0 ) {
+ *idpp= id;
+ id_us_plus(id);
+ return;
+ }
+ id= id->next;
+ }
+ *idpp= NULL;
+}
+
+void test_matpoin_but(struct bContext *C, char *name, ID **idpp)
+{
+ ID *id;
+
+ if( *idpp ) (*idpp)->us--;
+
+ id= CTX_data_main(C)->mat.first;
+ while(id) {
+ if( strcmp(name, id->name+2)==0 ) {
+ *idpp= id;
+ id_us_plus(id);
+ return;
+ }
+ id= id->next;
+ }
+ *idpp= NULL;
+}
+
+void test_scenepoin_but(struct bContext *C, char *name, ID **idpp)
+{
+ ID *id;
+
+ if( *idpp ) (*idpp)->us--;
+
+ id= CTX_data_main(C)->scene.first;
+ while(id) {
+ if( strcmp(name, id->name+2)==0 ) {
+ *idpp= id;
+ id_us_plus(id);
+ return;
+ }
+ id= id->next;
+ }
+ *idpp= NULL;
+}
+
+void test_grouppoin_but(struct bContext *C, char *name, ID **idpp)
+{
+ ID *id;
+
+ if( *idpp ) (*idpp)->us--;
+
+ id= CTX_data_main(C)->group.first;
+ while(id) {
+ if( strcmp(name, id->name+2)==0 ) {
+ *idpp= id;
+ id_us_plus(id);
+ return;
+ }
+ id= id->next;
+ }
+ *idpp= NULL;
+}
+
+void test_texpoin_but(struct bContext *C, char *name, ID **idpp)
+{
+ ID *id;
+
+ if( *idpp ) (*idpp)->us--;
+
+ id= CTX_data_main(C)->tex.first;
+ while(id) {
+ if( strcmp(name, id->name+2)==0 ) {
+ *idpp= id;
+ id_us_plus(id);
+ return;
+ }
+ id= id->next;
+ }
+ *idpp= NULL;
+}
+
+void test_imapoin_but(struct bContext *C, char *name, ID **idpp)
+{
+ ID *id;
+
+ if( *idpp ) (*idpp)->us--;
+
+ id= CTX_data_main(C)->image.first;
+ while(id) {
+ if( strcmp(name, id->name+2)==0 ) {
+ *idpp= id;
+ id_us_plus(id);
+ return;
+ }
+ id= id->next;
+ }
+ *idpp= NULL;
+}
+
+/* autocomplete callback for buttons */
+void autocomplete_bone(struct bContext *C, char *str, void *arg_v)
+{
+ Object *ob= (Object *)arg_v;
+
+ if(ob==NULL || ob->pose==NULL) return;
+
+ /* search if str matches the beginning of name */
+ if(str[0]) {
+ AutoComplete *autocpl= autocomplete_begin(str, 32);
+ bPoseChannel *pchan;
+
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next)
+ autocomplete_do_name(autocpl, pchan->name);
+
+ autocomplete_end(autocpl, str);
+ }
+}
+
+/* autocomplete callback for buttons */
+void autocomplete_vgroup(struct bContext *C, char *str, void *arg_v)
+{
+ Object *ob= (Object *)arg_v;
+
+ if(ob==NULL) return;
+
+ /* search if str matches the beginning of a name */
+ if(str[0]) {
+ AutoComplete *autocpl= autocomplete_begin(str, 32);
+ bDeformGroup *dg;
+
+ for(dg= ob->defbase.first; dg; dg= dg->next)
+ if(dg->name!=str)
+ autocomplete_do_name(autocpl, dg->name);
+
+ autocomplete_end(autocpl, str);
+ }
+}
+
+
+/* ----------- custom button group ---------------------- */
+
+static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *unused)
+{
+ CurveMapping *cumap = cumap_v;
+ float d;
+
+ /* we allow 20 times zoom */
+ if( (cumap->curr.xmax - cumap->curr.xmin) > 0.04f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
+ d= 0.1154f*(cumap->curr.xmax - cumap->curr.xmin);
+ cumap->curr.xmin+= d;
+ cumap->curr.xmax-= d;
+ d= 0.1154f*(cumap->curr.ymax - cumap->curr.ymin);
+ cumap->curr.ymin+= d;
+ cumap->curr.ymax-= d;
+ }
+}
+
+static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *unused)
+{
+ CurveMapping *cumap = cumap_v;
+ float d, d1;
+
+ /* we allow 20 times zoom, but dont view outside clip */
+ if( (cumap->curr.xmax - cumap->curr.xmin) < 20.0f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
+ d= d1= 0.15f*(cumap->curr.xmax - cumap->curr.xmin);
+
+ if(cumap->flag & CUMA_DO_CLIP)
+ if(cumap->curr.xmin-d < cumap->clipr.xmin)
+ d1= cumap->curr.xmin - cumap->clipr.xmin;
+ cumap->curr.xmin-= d1;
+
+ d1= d;
+ if(cumap->flag & CUMA_DO_CLIP)
+ if(cumap->curr.xmax+d > cumap->clipr.xmax)
+ d1= -cumap->curr.xmax + cumap->clipr.xmax;
+ cumap->curr.xmax+= d1;
+
+ d= d1= 0.15f*(cumap->curr.ymax - cumap->curr.ymin);
+
+ if(cumap->flag & CUMA_DO_CLIP)
+ if(cumap->curr.ymin-d < cumap->clipr.ymin)
+ d1= cumap->curr.ymin - cumap->clipr.ymin;
+ cumap->curr.ymin-= d1;
+
+ d1= d;
+ if(cumap->flag & CUMA_DO_CLIP)
+ if(cumap->curr.ymax+d > cumap->clipr.ymax)
+ d1= -cumap->curr.ymax + cumap->clipr.ymax;
+ cumap->curr.ymax+= d1;
+ }
+}
+
+static void curvemap_buttons_setclip(bContext *C, void *cumap_v, void *unused)
+{
+ CurveMapping *cumap = cumap_v;
+
+ curvemapping_changed(cumap, 0);
+}
+
+static void curvemap_buttons_delete(bContext *C, void *cumap_v, void *unused)
+{
+ CurveMapping *cumap = cumap_v;
+
+ curvemap_remove(cumap->cm+cumap->cur, SELECT);
+ curvemapping_changed(cumap, 0);
+}
+
+/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
+static uiBlock *curvemap_clipping_func(struct bContext *C, struct ARegion *ar, void *cumap_v)
+{
+ CurveMapping *cumap = cumap_v;
+ uiBlock *block;
+ uiBut *bt;
+
+ block= uiBeginBlock(C, ar, "curvemap_clipping_func", UI_EMBOSS);
+
+ /* use this for a fake extra empy space around the buttons */
+ uiDefBut(block, LABEL, 0, "", -4, 16, 128, 106, NULL, 0, 0, 0, 0, "");
+
+ bt= uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping",
+ 0,100,120,18, &cumap->flag, 0.0, 0.0, 10, 0, "");
+ uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL);
+
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, 0, "Min X ", 0,74,120,18, &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, "");
+ uiDefButF(block, NUM, 0, "Min Y ", 0,56,120,18, &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, "");
+ uiDefButF(block, NUM, 0, "Max X ", 0,38,120,18, &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, "");
+ uiDefButF(block, NUM, 0, "Max Y ", 0,20,120,18, &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+
+ uiEndBlock(C, block);
+ return block;
+}
+
+
+static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
+{
+ CurveMapping *cumap = cumap_v;
+ CurveMap *cuma= cumap->cm+cumap->cur;
+
+ switch(event) {
+ case 0:
+ curvemap_reset(cuma, &cumap->clipr);
+ curvemapping_changed(cumap, 0);
+ break;
+ case 1:
+ cumap->curr= cumap->clipr;
+ break;
+ case 2: /* set vector */
+ curvemap_sethandle(cuma, 1);
+ curvemapping_changed(cumap, 0);
+ break;
+ case 3: /* set auto */
+ curvemap_sethandle(cuma, 0);
+ curvemapping_changed(cumap, 0);
+ break;
+ case 4: /* extend horiz */
+ cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
+ curvemapping_changed(cumap, 0);
+ break;
+ case 5: /* extend extrapolate */
+ cuma->flag |= CUMA_EXTEND_EXTRAPOLATE;
+ curvemapping_changed(cumap, 0);
+ break;
+ }
+ ED_region_tag_redraw(CTX_wm_region(C));
+}
+
+static uiBlock *curvemap_tools_func(struct bContext *C, struct ARegion *ar, void *cumap_v)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS);
+ uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Horizontal", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Extrapolated", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 50);
+
+ uiEndBlock(C, block);
+ return block;
+}
+
+/* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */
+void curvemap_buttons(uiBlock *block, CurveMapping *cumap, char labeltype, short event, short redraw, rctf *rect)
+{
+ uiBut *bt;
+ float dx, fy= rect->ymax-18.0f;
+ int icon;
+ short xco, yco;
+
+ yco= (short)(rect->ymax-18.0f);
+
+ /* curve choice options + tools/settings, 8 icons + spacer */
+ dx= (rect->xmax-rect->xmin)/(9.0f);
+
+ uiBlockBeginAlign(block);
+ if(labeltype=='v') { /* vector */
+ xco= (short)rect->xmin;
+ if(cumap->cm[0].curve)
+ uiDefButI(block, ROW, redraw, "X", xco, yco+2, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
+ xco= (short)(rect->xmin+1.0f*dx);
+ if(cumap->cm[1].curve)
+ uiDefButI(block, ROW, redraw, "Y", xco, yco+2, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
+ xco= (short)(rect->xmin+2.0f*dx);
+ if(cumap->cm[2].curve)
+ uiDefButI(block, ROW, redraw, "Z", xco, yco+2, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
+ }
+ else if(labeltype=='c') { /* color */
+ xco= (short)rect->xmin;
+ if(cumap->cm[3].curve)
+ uiDefButI(block, ROW, redraw, "C", xco, yco+2, dx, 16, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
+ xco= (short)(rect->xmin+1.0f*dx);
+ if(cumap->cm[0].curve)
+ uiDefButI(block, ROW, redraw, "R", xco, yco+2, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
+ xco= (short)(rect->xmin+2.0f*dx);
+ if(cumap->cm[1].curve)
+ uiDefButI(block, ROW, redraw, "G", xco, yco+2, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
+ xco= (short)(rect->xmin+3.0f*dx);
+ if(cumap->cm[2].curve)
+ uiDefButI(block, ROW, redraw, "B", xco, yco+2, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
+ }
+ /* else no channels ! */
+ uiBlockEndAlign(block);
+
+ xco= (short)(rect->xmin+4.5f*dx);
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+ bt= uiDefIconBut(block, BUT, redraw, ICON_ZOOMIN, xco, yco, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom in");
+ uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL);
+
+ xco= (short)(rect->xmin+5.25f*dx);
+ bt= uiDefIconBut(block, BUT, redraw, ICON_ZOOMOUT, xco, yco, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom out");
+ uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL);
+
+ xco= (short)(rect->xmin+6.0f*dx);
+ bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, event, ICON_MODIFIER, xco, yco, dx, 18, "Tools");
+
+ xco= (short)(rect->xmin+7.0f*dx);
+ if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT;
+ bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, event, icon, xco, yco, dx, 18, "Clipping Options");
+
+ xco= (short)(rect->xmin+8.0f*dx);
+ bt= uiDefIconBut(block, BUT, event, ICON_X, xco, yco, dx, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Delete points");
+ uiButSetFunc(bt, curvemap_buttons_delete, cumap, NULL);
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ uiDefBut(block, BUT_CURVE, event, "",
+ rect->xmin, rect->ymin, rect->xmax-rect->xmin, fy-rect->ymin,
+ cumap, 0.0f, 1.0f, 0, 0, "");
+}
+
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
new file mode 100644
index 00000000000..3025b1bfc29
--- /dev/null
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -0,0 +1,1866 @@
+/**
+* ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ID.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_listbase.h"
+#include "BLI_rect.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "BLF_api.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_util.h"
+#include "ED_types.h"
+
+#include "interface_intern.h"
+
+/* ************** widget base functions ************** */
+/*
+ - in: roundbox codes for corner types and radius
+ - return: array of [size][2][x,y] points, the edges of the roundbox, + UV coords
+
+ - draw black box with alpha 0 on exact button boundbox
+ - for ever AA step:
+ - draw the inner part for a round filled box, with color blend codes or texture coords
+ - draw outline in outline color
+ - draw outer part, bottom half, extruded 1 pixel to bottom, for emboss shadow
+ - draw extra decorations
+ - draw background color box with alpha 1 on exact button boundbox
+
+ */
+
+/* fill this struct with polygon info to draw AA'ed */
+/* it has outline, back, and two optional tria meshes */
+
+typedef struct uiWidgetTrias {
+ int tot;
+
+ float vec[32][2];
+ int (*index)[3];
+
+} uiWidgetTrias;
+
+typedef struct uiWidgetStateColors {
+ float inner_anim[4];
+ float inner_anim_sel[4];
+ float inner_key[4];
+ float inner_key_sel[4];
+ float inner_driven[4];
+ float inner_driven_sel[4];
+} uiWidgetStateColors;
+
+typedef struct uiWidgetColors {
+ float outline[3];
+ float inner[4];
+ float inner_sel[4];
+ float item[3];
+ float text[3];
+ float text_sel[3];
+ short shaded;
+ float shadetop, shadedown;
+
+} uiWidgetColors;
+
+typedef struct uiWidgetBase {
+
+ int totvert, halfwayvert;
+ float outer_v[64][2];
+ float inner_v[64][2];
+ float inner_uv[64][2];
+
+ short inner, outline, emboss; /* set on/off */
+
+ uiWidgetTrias tria1;
+ uiWidgetTrias tria2;
+
+} uiWidgetBase;
+
+/* uiWidgetType: for time being only for visual appearance,
+ later, a handling callback can be added too
+*/
+typedef struct uiWidgetType {
+
+ /* pointer to theme color definition */
+ uiWidgetColors *wcol_theme;
+
+ /* converted colors for state */
+ uiWidgetColors wcol;
+
+ void (*state)(struct uiWidgetType *, int state);
+ void (*draw)(uiWidgetColors *, rcti *, int state, int roundboxalign);
+ void (*custom)(uiBut *, uiWidgetColors *, rcti *, int state, int roundboxalign);
+ void (*text)(uiFontStyle *, uiBut *, rcti *, float *col);
+
+} uiWidgetType;
+
+
+/* *********************** draw data ************************** */
+
+static float cornervec[9][2]= {{0.0, 0.0}, {0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169},
+{0.707, 0.293}, {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}, {1.0, 1.0}};
+
+static float jit[8][2]= {{0.468813 , -0.481430}, {-0.155755 , -0.352820},
+{0.219306 , -0.238501}, {-0.393286 , -0.110949}, {-0.024699 , 0.013908},
+{0.343805 , 0.147431}, {-0.272855 , 0.269918}, {0.095909 , 0.388710}};
+
+static float num_tria_vert[19][2]= {
+{0.382684, 0.923879}, {0.000001, 1.000000}, {-0.382683, 0.923880}, {-0.707107, 0.707107},
+{-0.923879, 0.382684}, {-1.000000, 0.000000}, {-0.923880, -0.382684}, {-0.707107, -0.707107},
+{-0.382683, -0.923880}, {0.000000, -1.000000}, {0.382684, -0.923880}, {0.707107, -0.707107},
+{0.923880, -0.382684}, {1.000000, -0.000000}, {0.923880, 0.382683}, {0.707107, 0.707107},
+{-0.352077, 0.532607}, {-0.352077, -0.549313}, {0.729843, -0.008353}};
+
+static int num_tria_face[19][3]= {
+{13, 14, 18}, {17, 5, 6}, {12, 13, 18}, {17, 6, 7}, {15, 18, 14}, {16, 4, 5}, {16, 5, 17}, {18, 11, 12},
+{18, 17, 10}, {18, 10, 11}, {17, 9, 10}, {15, 0, 18}, {18, 0, 16}, {3, 4, 16}, {8, 9, 17}, {8, 17, 7},
+{2, 3, 16}, {1, 2, 16}, {16, 0, 1}};
+
+static float menu_tria_vert[6][2]= {
+{-0.41, 0.16}, {0.41, 0.16}, {0, 0.82},
+{0, -0.82}, {-0.41, -0.16}, {0.41, -0.16}};
+
+static int menu_tria_face[2][3]= {{2, 0, 1}, {3, 5, 4}};
+
+static float check_tria_vert[6][2]= {
+{-0.578579, 0.253369}, {-0.392773, 0.412794}, {-0.004241, -0.328551},
+{-0.003001, 0.034320}, {1.055313, 0.864744}, {0.866408, 1.026895}};
+
+static int check_tria_face[4][3]= {
+{3, 2, 4}, {3, 4, 5}, {1, 0, 3}, {0, 2, 3}};
+
+/* ************************************************* */
+
+void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3)
+{
+ float color[4];
+ int j;
+
+ glEnable(GL_BLEND);
+ glGetFloatv(GL_CURRENT_COLOR, color);
+ color[3]= 0.125;
+ glColor4fv(color);
+
+ /* for each AA step */
+ for(j=0; j<8; j++) {
+ glTranslatef(1.0*jit[j][0], 1.0*jit[j][1], 0.0f);
+
+ glBegin(GL_POLYGON);
+ glVertex2f(x1, y1);
+ glVertex2f(x2, y2);
+ glVertex2f(x3, y3);
+ glEnd();
+
+ glTranslatef(-1.0*jit[j][0], -1.0*jit[j][1], 0.0f);
+ }
+
+ glDisable(GL_BLEND);
+
+}
+
+static void widget_init(uiWidgetBase *wtb)
+{
+ wtb->totvert= wtb->halfwayvert= 0;
+ wtb->tria1.tot= 0;
+ wtb->tria2.tot= 0;
+
+ wtb->inner= 1;
+ wtb->outline= 1;
+ wtb->emboss= 1;
+}
+
+/* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */
+/* return tot */
+static int round_box_shadow_edges(float (*vert)[2], rcti *rect, float rad, int roundboxalign, float step)
+{
+ float vec[9][2];
+ float minx, miny, maxx, maxy;
+ int a, tot= 0;
+
+ rad+= step;
+
+ if(2.0f*rad > rect->ymax-rect->ymin)
+ rad= 0.5f*(rect->ymax-rect->ymin);
+
+ minx= rect->xmin-step;
+ miny= rect->ymin-step;
+ maxx= rect->xmax+step;
+ maxy= rect->ymax+step;
+
+ /* mult */
+ for(a=0; a<9; a++) {
+ vec[a][0]= rad*cornervec[a][0];
+ vec[a][1]= rad*cornervec[a][1];
+ }
+
+ /* start with left-top, anti clockwise */
+ if(roundboxalign & 1) {
+ for(a=0; a<9; a++, tot++) {
+ vert[tot][0]= minx+rad-vec[a][0];
+ vert[tot][1]= maxy-vec[a][1];
+ }
+ }
+ else {
+ for(a=0; a<9; a++, tot++) {
+ vert[tot][0]= minx;
+ vert[tot][1]= maxy;
+ }
+ }
+
+ if(roundboxalign & 8) {
+ for(a=0; a<9; a++, tot++) {
+ vert[tot][0]= minx+vec[a][1];
+ vert[tot][1]= miny+rad-vec[a][0];
+ }
+ }
+ else {
+ for(a=0; a<9; a++, tot++) {
+ vert[tot][0]= minx;
+ vert[tot][1]= miny;
+ }
+ }
+
+ if(roundboxalign & 4) {
+ for(a=0; a<9; a++, tot++) {
+ vert[tot][0]= maxx-rad+vec[a][0];
+ vert[tot][1]= miny+vec[a][1];
+ }
+ }
+ else {
+ for(a=0; a<9; a++, tot++) {
+ vert[tot][0]= maxx;
+ vert[tot][1]= miny;
+ }
+ }
+
+ if(roundboxalign & 2) {
+ for(a=0; a<9; a++, tot++) {
+ vert[tot][0]= maxx-vec[a][1];
+ vert[tot][1]= maxy-rad+vec[a][0];
+ }
+ }
+ else {
+ for(a=0; a<9; a++, tot++) {
+ vert[tot][0]= maxx;
+ vert[tot][1]= maxy;
+ }
+ }
+ return tot;
+}
+
+
+
+static void round_box_edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, float rad)
+{
+ float vec[9][2], veci[9][2];
+ float minx= rect->xmin, miny= rect->ymin, maxx= rect->xmax, maxy= rect->ymax;
+ float radi; /* rad inner */
+ float minxi= minx + 1.0f; /* boundbox inner */
+ float maxxi= maxx - 1.0f;
+ float minyi= miny + 1.0f;
+ float maxyi= maxy - 1.0f;
+ float facxi= 1.0f/(maxxi-minxi); /* for uv */
+ float facyi= 1.0f/(maxyi-minyi);
+ int a, tot= 0;
+
+ if(2.0f*rad > rect->ymax-rect->ymin)
+ rad= 0.5f*(rect->ymax-rect->ymin);
+
+ radi= rad - 1.0f;
+
+ /* mult */
+ for(a=0; a<9; a++) {
+ veci[a][0]= radi*cornervec[a][0];
+ veci[a][1]= radi*cornervec[a][1];
+ vec[a][0]= rad*cornervec[a][0];
+ vec[a][1]= rad*cornervec[a][1];
+ }
+
+ /* corner left-bottom */
+ if(roundboxalign & 8) {
+
+ for(a=0; a<9; a++, tot++) {
+ wt->inner_v[tot][0]= minxi+veci[a][1];
+ wt->inner_v[tot][1]= minyi+radi-veci[a][0];
+
+ wt->outer_v[tot][0]= minx+vec[a][1];
+ wt->outer_v[tot][1]= miny+rad-vec[a][0];
+
+ wt->inner_uv[tot][0]= facxi*(wt->inner_v[tot][0] - minxi);
+ wt->inner_uv[tot][1]= facyi*(wt->inner_v[tot][1] - minyi);
+ }
+ }
+ else {
+ wt->inner_v[tot][0]= minxi;
+ wt->inner_v[tot][1]= minyi;
+
+ wt->outer_v[tot][0]= minx;
+ wt->outer_v[tot][1]= miny;
+
+ wt->inner_uv[tot][0]= 0.0f;
+ wt->inner_uv[tot][1]= 0.0f;
+
+ tot++;
+ }
+
+ /* corner right-bottom */
+ if(roundboxalign & 4) {
+
+ for(a=0; a<9; a++, tot++) {
+ wt->inner_v[tot][0]= maxxi-radi+veci[a][0];
+ wt->inner_v[tot][1]= minyi+veci[a][1];
+
+ wt->outer_v[tot][0]= maxx-rad+vec[a][0];
+ wt->outer_v[tot][1]= miny+vec[a][1];
+
+ wt->inner_uv[tot][0]= facxi*(wt->inner_v[tot][0] - minxi);
+ wt->inner_uv[tot][1]= facyi*(wt->inner_v[tot][1] - minyi);
+ }
+ }
+ else {
+ wt->inner_v[tot][0]= maxxi;
+ wt->inner_v[tot][1]= minyi;
+
+ wt->outer_v[tot][0]= maxx;
+ wt->outer_v[tot][1]= miny;
+
+ wt->inner_uv[tot][0]= 1.0f;
+ wt->inner_uv[tot][1]= 0.0f;
+
+ tot++;
+ }
+
+ wt->halfwayvert= tot;
+
+ /* corner right-top */
+ if(roundboxalign & 2) {
+
+ for(a=0; a<9; a++, tot++) {
+ wt->inner_v[tot][0]= maxxi-veci[a][1];
+ wt->inner_v[tot][1]= maxyi-radi+veci[a][0];
+
+ wt->outer_v[tot][0]= maxx-vec[a][1];
+ wt->outer_v[tot][1]= maxy-rad+vec[a][0];
+
+ wt->inner_uv[tot][0]= facxi*(wt->inner_v[tot][0] - minxi);
+ wt->inner_uv[tot][1]= facyi*(wt->inner_v[tot][1] - minyi);
+ }
+ }
+ else {
+ wt->inner_v[tot][0]= maxxi;
+ wt->inner_v[tot][1]= maxyi;
+
+ wt->outer_v[tot][0]= maxx;
+ wt->outer_v[tot][1]= maxy;
+
+ wt->inner_uv[tot][0]= 1.0f;
+ wt->inner_uv[tot][1]= 1.0f;
+
+ tot++;
+ }
+
+ /* corner left-top */
+ if(roundboxalign & 1) {
+
+ for(a=0; a<9; a++, tot++) {
+ wt->inner_v[tot][0]= minxi+radi-veci[a][0];
+ wt->inner_v[tot][1]= maxyi-veci[a][1];
+
+ wt->outer_v[tot][0]= minx+rad-vec[a][0];
+ wt->outer_v[tot][1]= maxy-vec[a][1];
+
+ wt->inner_uv[tot][0]= facxi*(wt->inner_v[tot][0] - minxi);
+ wt->inner_uv[tot][1]= facyi*(wt->inner_v[tot][1] - minyi);
+ }
+
+ }
+ else {
+
+ wt->inner_v[tot][0]= minxi;
+ wt->inner_v[tot][1]= maxyi;
+
+ wt->outer_v[tot][0]= minx;
+ wt->outer_v[tot][1]= maxy;
+
+ wt->inner_uv[tot][0]= 0.0f;
+ wt->inner_uv[tot][1]= 1.0f;
+
+ tot++;
+ }
+
+ wt->totvert= tot;
+}
+
+/* based on button rect, return scaled array of triangles */
+static void widget_num_tria(uiWidgetTrias *tria, rcti *rect, float triasize, char where)
+{
+ float centx, centy, size;
+ int a;
+
+ /* center position and size */
+ centx= (float)rect->xmin + 0.5f*(rect->ymax-rect->ymin);
+ centy= (float)rect->ymin + 0.5f*(rect->ymax-rect->ymin);
+ size= -0.5f*triasize*(rect->ymax-rect->ymin);
+
+ if(where=='r') {
+ centx= (float)rect->xmax - 0.5f*(rect->ymax-rect->ymin);
+ size= -size;
+ }
+
+ for(a=0; a<19; a++) {
+ tria->vec[a][0]= size*num_tria_vert[a][0] + centx;
+ tria->vec[a][1]= size*num_tria_vert[a][1] + centy;
+ }
+
+ tria->tot= 19;
+ tria->index= num_tria_face;
+}
+
+static void widget_trias_draw(uiWidgetTrias *tria)
+{
+ int a;
+
+ glBegin(GL_TRIANGLES);
+ for(a=0; a<tria->tot; a++) {
+ glVertex2fv(tria->vec[ tria->index[a][0] ]);
+ glVertex2fv(tria->vec[ tria->index[a][1] ]);
+ glVertex2fv(tria->vec[ tria->index[a][2] ]);
+ }
+ glEnd();
+
+}
+
+static void widget_menu_trias(uiWidgetTrias *tria, rcti *rect)
+{
+ float centx, centy, size, asp;
+ int a;
+
+ /* center position and size */
+ centx= rect->xmax - 0.5f*(rect->ymax-rect->ymin);
+ centy= rect->ymin + 0.5f*(rect->ymax-rect->ymin);
+ size= 0.4f*(rect->ymax-rect->ymin);
+
+ /* XXX exception */
+ asp= ((float)rect->xmax-rect->xmin)/((float)rect->ymax-rect->ymin);
+ if(asp > 1.2f && asp < 2.6f)
+ centx= rect->xmax - 0.3f*(rect->ymax-rect->ymin);
+
+ for(a=0; a<6; a++) {
+ tria->vec[a][0]= size*menu_tria_vert[a][0] + centx;
+ tria->vec[a][1]= size*menu_tria_vert[a][1] + centy;
+ }
+
+ tria->tot= 2;
+ tria->index= menu_tria_face;
+}
+
+static void widget_check_trias(uiWidgetTrias *tria, rcti *rect)
+{
+ float centx, centy, size;
+ int a;
+
+ /* center position and size */
+ centx= rect->xmin + 0.5f*(rect->ymax-rect->ymin);
+ centy= rect->ymin + 0.5f*(rect->ymax-rect->ymin);
+ size= 0.5f*(rect->ymax-rect->ymin);
+
+ for(a=0; a<6; a++) {
+ tria->vec[a][0]= size*check_tria_vert[a][0] + centx;
+ tria->vec[a][1]= size*check_tria_vert[a][1] + centy;
+ }
+
+ tria->tot= 4;
+ tria->index= check_tria_face;
+}
+
+
+/* prepares shade colors */
+static void shadecolors4(float *coltop, float *coldown, float *color, float shadetop, float shadedown)
+{
+
+ coltop[0]= CLAMPIS(color[0]+shadetop, 0.0f, 1.0f);
+ coltop[1]= CLAMPIS(color[1]+shadetop, 0.0f, 1.0f);
+ coltop[2]= CLAMPIS(color[2]+shadetop, 0.0f, 1.0f);
+ coltop[3]= color[3];
+
+ coldown[0]= CLAMPIS(color[0]+shadedown, 0.0f, 1.0f);
+ coldown[1]= CLAMPIS(color[1]+shadedown, 0.0f, 1.0f);
+ coldown[2]= CLAMPIS(color[2]+shadedown, 0.0f, 1.0f);
+ coldown[3]= color[3];
+}
+
+static void round_box_shade_col4(float *col1, float *col2, float fac)
+{
+ float col[4];
+
+ col[0]= (fac*col1[0] + (1.0-fac)*col2[0]);
+ col[1]= (fac*col1[1] + (1.0-fac)*col2[1]);
+ col[2]= (fac*col1[2] + (1.0-fac)*col2[2]);
+ col[3]= (fac*col1[3] + (1.0-fac)*col2[3]);
+
+ glColor4fv(col);
+}
+
+static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
+{
+ int j, a;
+
+ glEnable(GL_BLEND);
+
+ /* backdrop non AA */
+ if(wtb->inner) {
+ if(wcol->shaded==0) {
+ /* filled center, solid */
+ glColor4fv(wcol->inner);
+ glBegin(GL_POLYGON);
+ for(a=0; a<wtb->totvert; a++)
+ glVertex2fv(wtb->inner_v[a]);
+ glEnd();
+ }
+ else {
+ float col1[4], col2[4];
+
+ shadecolors4(col1, col2, wcol->inner, wcol->shadetop, wcol->shadedown);
+
+ glShadeModel(GL_SMOOTH);
+ glBegin(GL_POLYGON);
+ for(a=0; a<wtb->totvert; a++) {
+ round_box_shade_col4(col1, col2, wtb->inner_uv[a][1]);
+ glVertex2fv(wtb->inner_v[a]);
+ }
+ glEnd();
+ glShadeModel(GL_FLAT);
+ }
+ }
+
+ /* for each AA step */
+ if(wtb->outline) {
+ for(j=0; j<8; j++) {
+ glTranslatef(1.0*jit[j][0], 1.0*jit[j][1], 0.0f);
+
+ /* outline */
+ glColor4f(wcol->outline[0], wcol->outline[1], wcol->outline[0], 0.125);
+ glBegin(GL_QUAD_STRIP);
+ for(a=0; a<wtb->totvert; a++) {
+ glVertex2fv(wtb->outer_v[a]);
+ glVertex2fv(wtb->inner_v[a]);
+ }
+ glVertex2fv(wtb->outer_v[0]);
+ glVertex2fv(wtb->inner_v[0]);
+ glEnd();
+
+ /* emboss bottom shadow */
+ if(wtb->emboss) {
+ glColor4f(1.0f, 1.0f, 1.0f, 0.02f);
+ glBegin(GL_QUAD_STRIP);
+ for(a=0; a<wtb->halfwayvert; a++) {
+ glVertex2fv(wtb->outer_v[a]);
+ glVertex2f(wtb->outer_v[a][0], wtb->outer_v[a][1]-1.0f);
+ }
+ glEnd();
+ }
+
+ glTranslatef(-1.0*jit[j][0], -1.0*jit[j][1], 0.0f);
+ }
+ }
+
+ /* decoration */
+ if(wtb->tria1.tot || wtb->tria2.tot) {
+ /* for each AA step */
+ for(j=0; j<8; j++) {
+ glTranslatef(1.0*jit[j][0], 1.0*jit[j][1], 0.0f);
+
+ if(wtb->tria1.tot) {
+ glColor4f(wcol->item[0], wcol->item[1], wcol->item[2], 0.125);
+ widget_trias_draw(&wtb->tria1);
+ }
+ if(wtb->tria2.tot) {
+ glColor4f(wcol->item[0], wcol->item[1], wcol->item[2], 0.125);
+ widget_trias_draw(&wtb->tria2);
+ }
+
+ glTranslatef(-1.0*jit[j][0], -1.0*jit[j][1], 0.0f);
+ }
+ }
+
+ glDisable(GL_BLEND);
+
+}
+
+/* *********************** text/icon ************************************** */
+
+
+/* icons have been standardized... and this call draws in untransformed coordinates */
+#define ICON_HEIGHT 16.0f
+
+static void widget_draw_icon(uiBut *but, BIFIconID icon, int blend, rcti *rect)
+{
+ float xs=0, ys=0, aspect, height;
+
+ /* this icon doesn't need draw... */
+ if(icon==ICON_BLANK1) return;
+
+ /* we need aspect from block, for menus... these buttons are scaled in uiPositionBlock() */
+ aspect= but->block->aspect;
+ if(aspect != but->aspect) {
+ /* prevent scaling up icon in pupmenu */
+ if (aspect < 1.0f) {
+ height= ICON_HEIGHT;
+ aspect = 1.0f;
+
+ }
+ else
+ height= ICON_HEIGHT/aspect;
+ }
+ else
+ height= ICON_HEIGHT;
+
+ if(but->flag & UI_ICON_LEFT) {
+ if (but->type==BUT_TOGDUAL) {
+ if (but->drawstr[0]) {
+ xs= rect->xmin-1.0;
+ } else {
+ xs= (rect->xmin+rect->xmax- height)/2.0;
+ }
+ }
+ else if (but->block->flag & UI_BLOCK_LOOP) {
+ xs= rect->xmin+1.0;
+ }
+ else if ((but->type==ICONROW) || (but->type==ICONTEXTROW)) {
+ xs= rect->xmin+3.0;
+ }
+ else {
+ xs= rect->xmin+4.0;
+ }
+ ys= (rect->ymin+rect->ymax- height)/2.0;
+ }
+ if(but->flag & UI_ICON_RIGHT) {
+ xs= rect->xmax-17.0;
+ ys= (rect->ymin+rect->ymax- height)/2.0;
+ }
+ if (!((but->flag & UI_ICON_RIGHT) || (but->flag & UI_ICON_LEFT))) {
+ xs= (rect->xmin+rect->xmax- height)/2.0;
+ ys= (rect->ymin+rect->ymax- height)/2.0;
+ }
+
+ glEnable(GL_BLEND);
+
+ /* calculate blend color */
+ if ELEM3(but->type, TOG, ROW, TOGN) {
+ if(but->flag & UI_SELECT);
+ else if(but->flag & UI_ACTIVE);
+ else blend= -60;
+ }
+ if (but->flag & UI_BUT_DISABLED) blend = -100;
+
+ UI_icon_draw_aspect_blended(xs, ys, icon, aspect, blend);
+
+ glDisable(GL_BLEND);
+}
+
+/* sets but->ofs to make sure text is correctly visible */
+static void ui_text_leftclip(uiFontStyle *fstyle, uiBut *but, rcti *rect)
+{
+ int okwidth= rect->xmax-rect->xmin;
+
+ /* need to set this first */
+ uiStyleFontSet(fstyle);
+
+ but->strwidth= BLF_width(but->drawstr);
+ but->ofs= 0;
+
+ while(but->strwidth > okwidth ) {
+
+ but->ofs++;
+ but->strwidth= BLF_width(but->drawstr+but->ofs);
+
+ /* textbut exception */
+ if(but->editstr && but->pos != -1) {
+ int 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;
+ }
+}
+
+static void widget_draw_text(uiFontStyle *fstyle, uiBut *but, rcti *rect)
+{
+// int transopts;
+ char *cpoin;
+
+// ui_rasterpos_safe(x, y, but->aspect);
+// if(but->type==IDPOIN) transopts= 0; // no translation, of course!
+// else transopts= ui_translate_buttons();
+
+ /* cut string in 2 parts */
+ cpoin= strchr(but->drawstr, '|');
+ if(cpoin) *cpoin= 0;
+
+ if(but->editstr || (but->flag & UI_TEXT_LEFT))
+ fstyle->align= UI_STYLE_TEXT_LEFT;
+ else
+ fstyle->align= UI_STYLE_TEXT_CENTER;
+
+ uiStyleFontDraw(fstyle, rect, but->drawstr+but->ofs);
+
+ /* part text right aligned */
+ if(cpoin) {
+ fstyle->align= UI_STYLE_TEXT_RIGHT;
+ rect->xmax-=5;
+ uiStyleFontDraw(fstyle, rect, cpoin+1);
+ *cpoin= '|';
+ }
+}
+
+/* draws text and icons for buttons */
+static void widget_draw_text_icon(uiFontStyle *fstyle, uiBut *but, rcti *rect, float *col)
+{
+ short t, pos, ch;
+ short selsta_tmp, selend_tmp, selsta_draw, selwidth_draw;
+
+ if(but==NULL) return;
+
+ /* cutting off from left part */
+ if ELEM3(but->type, NUM, NUMABS, TEX) {
+ ui_text_leftclip(fstyle, but, rect);
+ }
+ else but->ofs= 0;
+
+ /* check for button text label */
+ if (but->type == ICONTEXTROW) {
+ widget_draw_icon(but, (BIFIconID) (but->icon+but->iconadd), 0, rect);
+ }
+ else {
+
+ /* text button selection and cursor */
+ if(but->editstr && but->pos != -1) {
+
+ if ((but->selend - but->selsta) > 0) {
+ /* text button selection */
+ selsta_tmp = but->selsta + strlen(but->str);
+ selend_tmp = but->selend + strlen(but->str);
+
+ if(but->drawstr[0]!=0) {
+ ch= but->drawstr[selsta_tmp];
+ but->drawstr[selsta_tmp]= 0;
+
+ uiStyleFontSet(fstyle);
+
+ selsta_draw = BLF_width(but->drawstr+but->ofs) + 3;
+
+ but->drawstr[selsta_tmp]= ch;
+
+
+ ch= but->drawstr[selend_tmp];
+ but->drawstr[selend_tmp]= 0;
+
+ selwidth_draw = BLF_width(but->drawstr+but->ofs) + 3;
+
+ but->drawstr[selend_tmp]= ch;
+
+ UI_ThemeColor(TH_BUT_TEXTFIELD_HI);
+ glRects(rect->xmin+selsta_draw+1, rect->ymin+2, rect->xmin+selwidth_draw+1, rect->ymax-2);
+ }
+ } else {
+ /* text cursor */
+ pos= but->pos+strlen(but->str);
+ if(pos >= but->ofs) {
+ if(but->drawstr[0]!=0) {
+ ch= but->drawstr[pos];
+ but->drawstr[pos]= 0;
+
+ uiStyleFontSet(fstyle);
+
+ t= BLF_width(but->drawstr+but->ofs) + 3;
+
+ but->drawstr[pos]= ch;
+ }
+ else t= 3;
+
+ glColor3ub(255,0,0);
+ glRects(rect->xmin+t, rect->ymin+2, rect->xmin+t+2, rect->ymax-2);
+ }
+ }
+ }
+
+ if(but->type==BUT_TOGDUAL) {
+ int dualset= 0;
+ if(but->pointype==SHO)
+ dualset= BTST( *(((short *)but->poin)+1), but->bitnr);
+ else if(but->pointype==INT)
+ dualset= BTST( *(((int *)but->poin)+1), but->bitnr);
+
+ widget_draw_icon(but, ICON_DOT, dualset?0:-100, rect);
+ }
+
+ if(but->drawstr[0]!=0) {
+
+ /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
+ and offset the text label to accomodate it */
+
+ if ( (but->flag & UI_HAS_ICON) && (but->flag & UI_ICON_LEFT) ) {
+ widget_draw_icon(but, but->icon, 0, rect);
+
+ rect->xmin += UI_icon_get_width(but->icon);
+
+ if(but->editstr || (but->flag & UI_TEXT_LEFT))
+ rect->xmin += 5;
+ }
+ else if(but->flag & UI_TEXT_LEFT)
+ rect->xmin += 5;
+
+ glColor3fv(col);
+ widget_draw_text(fstyle, but, rect);
+
+ }
+ /* if there's no text label, then check to see if there's an icon only and draw it */
+ else if( but->flag & UI_HAS_ICON ) {
+ widget_draw_icon(but, (BIFIconID) (but->icon+but->iconadd), 0, rect);
+ }
+ }
+}
+
+
+
+/* *********************** widget types ************************************* */
+
+
+/* uiWidgetStateColors
+ float inner_anim[4];
+ float inner_anim_sel[4];
+ float inner_key[4];
+ float inner_key_sel[4];
+ float inner_driven[4];
+ float inner_driven_sel[4];
+
+*/
+
+static struct uiWidgetStateColors wcol_state= {
+ {0.45, 0.75, 0.3f, 1.0f},
+ {0.35, 0.65, 0.2f, 1.0f},
+ {0.95, 0.9, 0.4f, 1.0f},
+ {0.85, 0.8, 0.3f, 1.0f},
+ {0.7f, 0.0, 1.0f, 1.0f},
+ {0.6f, 0.0, 0.9f, 1.0f}
+};
+
+/* uiWidgetColors
+ float outline[3];
+ float inner[4];
+ float inner_sel[4];
+ float item[3];
+ float text[3];
+ float text_sel[3];
+
+ short shaded;
+ float shadetop, shadedown;
+*/
+
+static struct uiWidgetColors wcol_num= {
+ {0.1f, 0.1f, 0.1f},
+ {0.7f, 0.7f, 0.7f, 1.0f},
+ {0.6f, 0.6f, 0.6f, 1.0f},
+ {0.35f, 0.35f, 0.35f},
+
+ {0.0f, 0.0f, 0.0f},
+ {1.0f, 1.0f, 1.0f},
+
+ 1,
+ -0.08f, 0.0f
+};
+
+static struct uiWidgetColors wcol_numslider= {
+ {0.1f, 0.1f, 0.1f},
+ {0.7f, 0.7f, 0.7f, 1.0f},
+ {0.6f, 0.6f, 0.6f, 1.0f},
+ {0.5f, 0.5f, 0.5f},
+
+ {0.0f, 0.0f, 0.0f},
+ {1.0f, 1.0f, 1.0f},
+
+ 1,
+ -0.08f, 0.0f
+};
+
+static struct uiWidgetColors wcol_text= {
+ {0.1f, 0.1f, 0.1f},
+ {0.6f, 0.6f, 0.6f, 1.0f},
+ {0.6f, 0.6f, 0.6f, 1.0f},
+ {0.35f, 0.35f, 0.35f},
+
+ {0.0f, 0.0f, 0.0f},
+ {1.0f, 1.0f, 1.0f},
+
+ 1,
+ 0.0f, 0.1f
+};
+
+static struct uiWidgetColors wcol_option= {
+ {0.0f, 0.0f, 0.0f},
+ {0.25f, 0.25f, 0.25f, 1.0f},
+ {0.25f, 0.25f, 0.25f, 1.0f},
+ {1.0f, 1.0f, 1.0f},
+
+ {0.0f, 0.0f, 0.0f},
+ {1.0f, 1.0f, 1.0f},
+
+ 1,
+ 0.1f, -0.08f
+};
+
+/* button that shows popup */
+static struct uiWidgetColors wcol_menu= {
+ {0.0f, 0.0f, 0.0f},
+ {0.25f, 0.25f, 0.25f, 1.0f},
+ {0.25f, 0.25f, 0.25f, 1.0f},
+ {1.0f, 1.0f, 1.0f},
+
+ {1.0f, 1.0f, 1.0f},
+ {0.8f, 0.8f, 0.8f},
+
+ 1,
+ 0.1f, -0.08f
+};
+
+/* button that starts pulldown */
+static struct uiWidgetColors wcol_pulldown= {
+ {0.0f, 0.0f, 0.0f},
+ {0.25f, 0.25f, 0.25f, 1.0f},
+ {0.18f, 0.48f, 0.85f, 1.0f},
+ {1.0f, 1.0f, 1.0f},
+
+ {1.0f, 1.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f},
+
+ 0,
+ 0.1f, -0.08f
+};
+
+/* button inside menu */
+static struct uiWidgetColors wcol_menu_item= {
+ {0.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 0.3},
+ {0.23f, 0.53f, 0.9f, 1.0f},
+ {1.0f, 1.0f, 1.0f},
+
+ {1.0f, 1.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f},
+
+ 0,
+ 0.15f, 0.0f
+};
+
+/* backdrop menu + title text color */
+static struct uiWidgetColors wcol_menu_back= {
+ {0.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 0.6},
+ {0.18f, 0.48f, 0.85f, 0.8f},
+ {1.0f, 1.0f, 1.0f},
+
+ {1.0f, 1.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f},
+
+ 0,
+ 0.1f, -0.08f
+};
+
+
+static struct uiWidgetColors wcol_radio= {
+ {0.0f, 0.0f, 0.0f},
+ {0.25f, 0.25f, 0.25f, 1.0f},
+ {0.34f, 0.5f, 0.76f, 1.0f},
+ {1.0f, 1.0f, 1.0f},
+
+ {1.0f, 1.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f},
+
+ 1,
+ 0.1f, -0.1f
+};
+
+static struct uiWidgetColors wcol_regular= {
+ {0.1f, 0.1f, 0.1f},
+ {0.6f, 0.6f, 0.6f, 1.0f},
+ {0.4f, 0.4f, 0.4f, 1.0f},
+ {0.1f, 0.1f, 0.1f},
+
+ {0.0f, 0.0f, 0.0f},
+ {1.0f, 1.0f, 1.0f},
+
+ 0,
+ 0.0f, 0.0f
+};
+
+static struct uiWidgetColors wcol_regular_shade= {
+ {0.1f, 0.1f, 0.1f},
+ {0.6f, 0.6f, 0.6f, 1.0f},
+ {0.4f, 0.4f, 0.4f, 1.0f},
+ {0.1f, 0.1f, 0.1f},
+
+ {0.0f, 0.0f, 0.0f},
+ {1.0f, 1.0f, 1.0f},
+
+ 1,
+ 0.1f, -0.1f
+};
+
+/* ************ button callbacks, state ***************** */
+
+/* copy colors from theme, and set changes in it based on state */
+static void widget_state(uiWidgetType *wt, int state)
+{
+ wt->wcol= *(wt->wcol_theme);
+
+ if(state & UI_SELECT) {
+ if(state & UI_BUT_ANIMATED_KEY)
+ QUATCOPY(wt->wcol.inner, wcol_state.inner_key_sel)
+ else if(state & UI_BUT_ANIMATED)
+ QUATCOPY(wt->wcol.inner, wcol_state.inner_anim_sel)
+ else if(state & UI_BUT_DRIVEN)
+ QUATCOPY(wt->wcol.inner, wcol_state.inner_driven_sel)
+ else
+ QUATCOPY(wt->wcol.inner, wt->wcol.inner_sel)
+
+ VECCOPY(wt->wcol.text, wt->wcol.text_sel);
+
+ /* only flip shade if it's not "pushed in" already */
+ if(wt->wcol.shaded && wt->wcol.shadetop>wt->wcol.shadedown) {
+ SWAP(float, wt->wcol.shadetop, wt->wcol.shadedown);
+ }
+ }
+ else {
+ if(state & UI_BUT_ANIMATED_KEY)
+ QUATCOPY(wt->wcol.inner, wcol_state.inner_key)
+ else if(state & UI_BUT_ANIMATED)
+ QUATCOPY(wt->wcol.inner, wcol_state.inner_anim)
+ else if(state & UI_BUT_DRIVEN)
+ QUATCOPY(wt->wcol.inner, wcol_state.inner_driven)
+
+ if(state & UI_ACTIVE) /* mouse over? */
+ VecMulf(wt->wcol.inner, 1.1f);
+ }
+}
+
+/* special case, button that calls pulldown */
+static void widget_state_pulldown(uiWidgetType *wt, int state)
+{
+ wt->wcol= *(wt->wcol_theme);
+
+ QUATCOPY(wt->wcol.inner, wt->wcol.inner_sel);
+ VECCOPY(wt->wcol.outline, wt->wcol.inner);
+
+ if(state & UI_ACTIVE)
+ VECCOPY(wt->wcol.text, wt->wcol.text_sel);
+}
+
+/* special case, menu items */
+static void widget_state_menu_item(uiWidgetType *wt, int state)
+{
+ wt->wcol= *(wt->wcol_theme);
+
+ if(state & UI_BUT_DISABLED) {
+ wt->wcol.text[0]= 0.5f*(wt->wcol.text[0]+wt->wcol.text_sel[0]);
+ wt->wcol.text[1]= 0.5f*(wt->wcol.text[1]+wt->wcol.text_sel[1]);
+ wt->wcol.text[2]= 0.5f*(wt->wcol.text[2]+wt->wcol.text_sel[2]);
+ }
+ else if(state & UI_ACTIVE) {
+ QUATCOPY(wt->wcol.inner, wt->wcol.inner_sel);
+ VECCOPY(wt->wcol.text, wt->wcol.text_sel);
+
+ wt->wcol.shaded= 1;
+ }
+}
+
+
+/* ************ menu backdrop ************************* */
+
+/* outside of rect, rad to left/bottom/right */
+static void widget_softshadow(rcti *rect, int roundboxalign, float radin, float radout)
+{
+ uiWidgetBase wtb;
+ rcti rect1= *rect;
+ float alpha, alphastep;
+ int step, tot, a;
+
+ /* prevent tooltips to not show round shadow */
+ if( 2.0f*radout > 0.2f*(rect1.ymax-rect1.ymin) )
+ rect1.ymax -= 0.2f*(rect1.ymax-rect1.ymin);
+ else
+ rect1.ymax -= 2.0f*radout;
+
+ /* inner part */
+ tot= round_box_shadow_edges(wtb.inner_v, &rect1, radin, roundboxalign & 12, 0.0f);
+
+ /* inverse linear shadow alpha */
+ alpha= 0.15;
+ alphastep= 0.67;
+
+ for(step= 1; step<=radout; step++, alpha*=alphastep) {
+ round_box_shadow_edges(wtb.outer_v, &rect1, radin, 15, (float)step);
+
+ glColor4f(0.0f, 0.0f, 0.0f, alpha);
+
+ glBegin(GL_QUAD_STRIP);
+ for(a=0; a<tot; a++) {
+ glVertex2fv(wtb.outer_v[a]);
+ glVertex2fv(wtb.inner_v[a]);
+ }
+ glEnd();
+ }
+
+}
+
+static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int direction)
+{
+ uiWidgetBase wtb;
+ int roundboxalign= 15;
+
+ widget_init(&wtb);
+
+ /* menu is 2nd level or deeper */
+ if (flag & UI_BLOCK_POPUP) {
+ rect->ymin -= 4.0;
+ rect->ymax += 4.0;
+ }
+ else if (direction == UI_DOWN) {
+ roundboxalign= 12;
+ rect->ymin -= 4.0;
+ }
+ else if (direction == UI_TOP) {
+ roundboxalign= 3;
+ rect->ymax += 4.0;
+ }
+
+ glEnable(GL_BLEND);
+ widget_softshadow(rect, roundboxalign, 5.0f, 8.0f);
+
+ round_box_edges(&wtb, roundboxalign, rect, 5.0f);
+ wtb.emboss= 0;
+ widgetbase_draw(&wtb, wcol);
+
+ glDisable(GL_BLEND);
+}
+
+/* ************ custom buttons, old stuff ************** */
+
+/* draws in resolution of 20x4 colors */
+static void ui_draw_but_HSVCUBE(uiBut *but, rcti *rect)
+{
+ int a;
+ float h,s,v;
+ float dx, dy, sx1, sx2, sy, x, y;
+ float col0[4][3]; // left half, rect bottom to top
+ float col1[4][3]; // right half, rect bottom to top
+
+ h= but->hsv[0];
+ s= but->hsv[1];
+ v= but->hsv[2];
+
+ /* draw series of gouraud rects */
+ glShadeModel(GL_SMOOTH);
+
+ if(but->a1==0) { // H and V vary
+ hsv_to_rgb(0.0, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
+ hsv_to_rgb(0.0, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
+ hsv_to_rgb(0.0, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(0.0, s, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]);
+ x= h; y= v;
+ }
+ else if(but->a1==1) { // H and S vary
+ hsv_to_rgb(0.0, 0.0, v, &col1[0][0], &col1[0][1], &col1[0][2]);
+ hsv_to_rgb(0.0, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
+ hsv_to_rgb(0.0, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(0.0, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]);
+ x= h; y= s;
+ }
+ else if(but->a1==2) { // S and V vary
+ hsv_to_rgb(h, 0.0, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
+ hsv_to_rgb(h, 0.333, 0.0, &col1[1][0], &col1[1][1], &col1[1][2]);
+ hsv_to_rgb(h, 0.666, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(h, 1.0, 0.0, &col1[3][0], &col1[3][1], &col1[3][2]);
+ x= v; y= s;
+ }
+ else { // only hue slider
+ hsv_to_rgb(0.0, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]);
+ VECCOPY(col1[1], col1[0]);
+ VECCOPY(col1[2], col1[0]);
+ VECCOPY(col1[3], col1[0]);
+ x= h; y= 0.5;
+ }
+
+ for(dx=0.0; dx<1.0; dx+= 0.05) {
+ // previous color
+ VECCOPY(col0[0], col1[0]);
+ VECCOPY(col0[1], col1[1]);
+ VECCOPY(col0[2], col1[2]);
+ VECCOPY(col0[3], col1[3]);
+
+ // new color
+ if(but->a1==0) { // H and V vary
+ hsv_to_rgb(dx, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
+ hsv_to_rgb(dx, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
+ hsv_to_rgb(dx, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(dx, s, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]);
+ }
+ else if(but->a1==1) { // H and S vary
+ hsv_to_rgb(dx, 0.0, v, &col1[0][0], &col1[0][1], &col1[0][2]);
+ hsv_to_rgb(dx, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
+ hsv_to_rgb(dx, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(dx, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]);
+ }
+ else if(but->a1==2) { // S and V vary
+ hsv_to_rgb(h, 0.0, dx, &col1[0][0], &col1[0][1], &col1[0][2]);
+ hsv_to_rgb(h, 0.333, dx, &col1[1][0], &col1[1][1], &col1[1][2]);
+ hsv_to_rgb(h, 0.666, dx, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(h, 1.0, dx, &col1[3][0], &col1[3][1], &col1[3][2]);
+ }
+ else { // only H
+ hsv_to_rgb(dx, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]);
+ VECCOPY(col1[1], col1[0]);
+ VECCOPY(col1[2], col1[0]);
+ VECCOPY(col1[3], col1[0]);
+ }
+
+ // rect
+ sx1= rect->xmin + dx*(rect->xmax-rect->xmin);
+ sx2= rect->xmin + (dx+0.05)*(rect->xmax-rect->xmin);
+ sy= rect->ymin;
+ dy= (rect->ymax-rect->ymin)/3.0;
+
+ glBegin(GL_QUADS);
+ for(a=0; a<3; a++, sy+=dy) {
+ glColor3fv(col0[a]);
+ glVertex2f(sx1, sy);
+
+ glColor3fv(col1[a]);
+ glVertex2f(sx2, sy);
+
+ glColor3fv(col1[a+1]);
+ glVertex2f(sx2, sy+dy);
+
+ glColor3fv(col0[a+1]);
+ glVertex2f(sx1, sy+dy);
+ }
+ glEnd();
+ }
+
+ glShadeModel(GL_FLAT);
+
+ /* cursor */
+ x= rect->xmin + x*(rect->xmax-rect->xmin);
+ y= rect->ymin + y*(rect->ymax-rect->ymin);
+ CLAMP(x, rect->xmin+3.0, rect->xmax-3.0);
+ CLAMP(y, rect->ymin+3.0, rect->ymax-3.0);
+
+ fdrawXORcirc(x, y, 3.1);
+
+ /* outline */
+ glColor3ub(0, 0, 0);
+ fdrawbox((rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
+}
+
+
+/* ************ button callbacks, draw ***************** */
+
+static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+{
+ uiWidgetBase wtb;
+
+ widget_init(&wtb);
+
+ /* fully rounded */
+ round_box_edges(&wtb, roundboxalign, rect, 0.5f*(rect->ymax - rect->ymin));
+
+ /* decoration */
+ if(!(state & UI_TEXTINPUT)) {
+ widget_num_tria(&wtb.tria1, rect, 0.6f, 0);
+ widget_num_tria(&wtb.tria2, rect, 0.6f, 'r');
+ }
+ widgetbase_draw(&wtb, wcol);
+
+ /* text space */
+ rect->xmin += (rect->ymax-rect->ymin);
+ rect->xmax -= (rect->ymax-rect->ymin);
+
+}
+
+static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+{
+ uiWidgetBase wtb, wtb1;
+ rcti rect1;
+ double value;
+ float offs, fac, outline[3];
+
+ widget_init(&wtb);
+ widget_init(&wtb1);
+
+ /* backdrop first */
+
+ /* fully rounded */
+ offs= 0.5f*(rect->ymax - rect->ymin);
+ round_box_edges(&wtb, roundboxalign, rect, offs);
+
+ wtb.outline= 0;
+ widgetbase_draw(&wtb, wcol);
+
+ /* slider part */
+ rect1= *rect;
+
+ value= ui_get_but_val(but);
+ fac= (value-but->softmin)*(rect1.xmax - rect1.xmin - 2.0f*offs)/(but->softmax - but->softmin);
+
+ rect1.xmax= rect1.xmin + fac + 2.0f*offs;
+ round_box_edges(&wtb1, roundboxalign, &rect1, offs);
+
+ VECCOPY(outline, wcol->outline);
+ VECCOPY(wcol->outline, wcol->item);
+ VECCOPY(wcol->inner, wcol->item);
+ SWAP(float, wcol->shadetop, wcol->shadedown);
+
+ widgetbase_draw(&wtb1, wcol);
+ VECCOPY(wcol->outline, outline);
+ SWAP(float, wcol->shadetop, wcol->shadedown);
+
+ /* outline */
+ wtb.outline= 1;
+ wtb.inner= 0;
+ widgetbase_draw(&wtb, wcol);
+
+}
+
+static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+{
+ uiWidgetBase wtb;
+
+ widget_init(&wtb);
+
+ /* half rounded */
+ round_box_edges(&wtb, roundboxalign, rect, 4.0f);
+
+ ui_get_but_vectorf(but, wcol->inner);
+
+ widgetbase_draw(&wtb, wcol);
+
+}
+
+
+static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+{
+ uiWidgetBase wtb;
+
+ widget_init(&wtb);
+
+ /* half rounded */
+ round_box_edges(&wtb, roundboxalign, rect, 4.0f);
+
+ widgetbase_draw(&wtb, wcol);
+
+}
+
+
+static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+{
+ uiWidgetBase wtb;
+
+ widget_init(&wtb);
+
+ /* half rounded */
+ round_box_edges(&wtb, roundboxalign, rect, 4.0f);
+
+ /* decoration */
+ widget_menu_trias(&wtb.tria1, rect);
+
+ widgetbase_draw(&wtb, wcol);
+
+ /* text space */
+ rect->xmax -= (rect->ymax-rect->ymin);
+
+}
+
+static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+{
+ if(state & UI_ACTIVE) {
+ uiWidgetBase wtb;
+
+ widget_init(&wtb);
+
+ /* fully rounded */
+ round_box_edges(&wtb, roundboxalign, rect, 0.5f*(rect->ymax - rect->ymin));
+
+ widgetbase_draw(&wtb, wcol);
+ }
+}
+
+static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+{
+ uiWidgetBase wtb;
+
+ widget_init(&wtb);
+
+ /* not rounded, no outline */
+ wtb.outline= 0;
+ round_box_edges(&wtb, 0, rect, 0.0f);
+
+ widgetbase_draw(&wtb, wcol);
+}
+
+
+static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+{
+ uiWidgetBase wtb;
+ rcti recttemp= *rect;
+ int delta;
+
+ widget_init(&wtb);
+
+ /* square */
+ recttemp.xmax= recttemp.xmin + (recttemp.ymax-recttemp.ymin);
+
+ /* smaller */
+ delta= 1 + (recttemp.ymax-recttemp.ymin)/8;
+ recttemp.xmin+= delta;
+ recttemp.ymin+= delta;
+ recttemp.xmax-= delta;
+ recttemp.ymax-= delta;
+
+ /* half rounded */
+ round_box_edges(&wtb, 15, &recttemp, 4.0f);
+
+ /* decoration */
+ if(state & UI_SELECT) {
+ widget_check_trias(&wtb.tria1, &recttemp);
+ }
+
+ widgetbase_draw(&wtb, wcol);
+
+ /* text space */
+ rect->xmin += (rect->ymax-rect->ymin) + delta;
+}
+
+
+static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+{
+ uiWidgetBase wtb;
+
+ widget_init(&wtb);
+
+ /* half rounded */
+ round_box_edges(&wtb, roundboxalign, rect, 4.0f);
+
+ widgetbase_draw(&wtb, wcol);
+
+}
+
+static void widget_but(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+{
+ uiWidgetBase wtb;
+
+ widget_init(&wtb);
+
+ /* half rounded */
+ round_box_edges(&wtb, roundboxalign, rect, 4.0f);
+
+ widgetbase_draw(&wtb, wcol);
+
+}
+
+static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+{
+ uiWidgetBase wtb;
+
+ widget_init(&wtb);
+
+ /* fully rounded */
+ round_box_edges(&wtb, roundboxalign, rect, 0.5f*(rect->ymax - rect->ymin));
+
+ widgetbase_draw(&wtb, wcol);
+}
+
+static void widget_disabled(rcti *rect)
+{
+ float col[4];
+
+ glEnable(GL_BLEND);
+
+ /* can't use theme TH_BACK or TH_PANEL... undefined */
+ glGetFloatv(GL_COLOR_CLEAR_VALUE, col);
+ glColor4f(col[0], col[1], col[2], 0.5f);
+ glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+
+ glDisable(GL_BLEND);
+}
+
+static uiWidgetType *widget_type(uiWidgetTypeEnum type)
+{
+ static uiWidgetType wt;
+
+ /* defaults */
+ wt.wcol_theme= &wcol_regular;
+ wt.state= widget_state;
+ wt.draw= widget_but;
+ wt.custom= NULL;
+ wt.text= widget_draw_text_icon;
+
+ switch(type) {
+ case UI_WTYPE_TOGGLE:
+ break;
+
+ case UI_WTYPE_OPTION:
+ wt.wcol_theme= &wcol_option;
+ wt.draw= widget_optionbut;
+ break;
+
+ case UI_WTYPE_RADIO:
+ wt.wcol_theme= &wcol_radio;
+ wt.draw= widget_radiobut;
+ break;
+
+ case UI_WTYPE_NUMBER:
+ wt.wcol_theme= &wcol_num;
+ wt.draw= widget_numbut;
+ break;
+
+ case UI_WTYPE_SLIDER:
+ wt.wcol_theme= &wcol_numslider;
+ wt.custom= widget_numslider;
+ break;
+
+ case UI_WTYPE_EXEC:
+ wt.wcol_theme= &wcol_regular_shade;
+ wt.draw= widget_roundbut;
+ break;
+
+
+ /* strings */
+ case UI_WTYPE_NAME:
+ wt.wcol_theme= &wcol_text;
+ wt.draw= widget_textbut;
+ break;
+
+ case UI_WTYPE_NAME_LINK:
+ break;
+
+ case UI_WTYPE_POINTER_LINK:
+ break;
+
+ case UI_WTYPE_FILENAME:
+ break;
+
+
+ /* start menus */
+ case UI_WTYPE_MENU_RADIO:
+ wt.wcol_theme= &wcol_menu;
+ wt.draw= widget_menubut;
+ break;
+
+ case UI_WTYPE_MENU_POINTER_LINK:
+ wt.wcol_theme= &wcol_menu;
+ wt.draw= widget_menubut;
+ break;
+
+
+ case UI_WTYPE_PULLDOWN:
+ wt.wcol_theme= &wcol_pulldown;
+ wt.draw= widget_pulldownbut;
+ wt.state= widget_state_pulldown;
+ break;
+
+ /* in menus */
+ case UI_WTYPE_MENU_ITEM:
+ wt.wcol_theme= &wcol_menu_item;
+ wt.draw= widget_menu_itembut;
+ wt.state= widget_state_menu_item;
+ break;
+
+ case UI_WTYPE_MENU_BACK:
+ wt.wcol_theme= &wcol_menu_back;
+ wt.draw= widget_menu_back;
+ break;
+
+ /* specials */
+ case UI_WTYPE_ICON:
+ wt.draw= NULL;
+ break;
+
+ case UI_WTYPE_SWATCH:
+ wt.custom= widget_swatch;
+ break;
+
+ case UI_WTYPE_RGB_PICKER:
+ break;
+
+ case UI_WTYPE_NORMAL:
+ break;
+ }
+
+ return &wt;
+}
+
+
+static int widget_roundbox_set(uiBut *but, rcti *rect)
+{
+ /* alignment */
+ if(but->flag & UI_BUT_ALIGN) {
+
+ if(but->flag & UI_BUT_ALIGN_TOP)
+ rect->ymax+= 1;
+ if(but->flag & UI_BUT_ALIGN_LEFT)
+ rect->xmin-= 1;
+
+ switch(but->flag & UI_BUT_ALIGN) {
+ case UI_BUT_ALIGN_TOP:
+ return (12);
+ break;
+ case UI_BUT_ALIGN_DOWN:
+ return (3);
+ break;
+ case UI_BUT_ALIGN_LEFT:
+ return (6);
+ break;
+ case UI_BUT_ALIGN_RIGHT:
+ return (9);
+ break;
+
+ case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
+ return (1);
+ break;
+ case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
+ return (2);
+ break;
+ case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
+ return (8);
+ break;
+ case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
+ return (4);
+ break;
+
+ default:
+ return (0);
+ break;
+ }
+ }
+ return 15;
+}
+
+/* conversion from old to new buttons, so still messy */
+void ui_draw_but(ARegion *ar, uiStyle *style, uiBut *but, rcti *rect)
+{
+ uiWidgetType *wt= NULL;
+
+ /* handle menus seperately */
+ if(but->dt==UI_EMBOSSP) {
+ switch (but->type) {
+ case LABEL:
+ widget_draw_text_icon(&style->widgetlabel, but, rect, wcol_menu_back.text);
+ break;
+ case SEPR:
+ break;
+
+ default:
+ wt= widget_type(UI_WTYPE_MENU_ITEM);
+ }
+ }
+ else if(but->dt==UI_EMBOSSN) {
+ /* "nothing" */
+ wt= widget_type(UI_WTYPE_ICON);
+ }
+ else {
+
+ switch (but->type) {
+ case LABEL:
+ if(but->block->flag & UI_BLOCK_LOOP)
+ widget_draw_text_icon(&style->widgetlabel, but, rect, wcol_menu_back.text);
+ else
+ widget_draw_text_icon(&style->widgetlabel, but, rect, wcol_regular.text);
+ break;
+ case SEPR:
+ break;
+ case BUT:
+ wt= widget_type(UI_WTYPE_EXEC);
+ break;
+ case NUM:
+ wt= widget_type(UI_WTYPE_NUMBER);
+ break;
+ case NUMSLI:
+ case HSVSLI:
+ wt= widget_type(UI_WTYPE_SLIDER);
+ break;
+ case ROW:
+ wt= widget_type(UI_WTYPE_RADIO);
+ break;
+ case TEX:
+ wt= widget_type(UI_WTYPE_NAME);
+ break;
+ case TOGBUT:
+ wt= widget_type(UI_WTYPE_TOGGLE);
+ break;
+ case TOG:
+ case TOGN:
+ case TOG3:
+ if (!(but->flag & UI_HAS_ICON)) {
+ wt= widget_type(UI_WTYPE_OPTION);
+ but->flag |= UI_TEXT_LEFT;
+ }
+ else
+ wt= widget_type(UI_WTYPE_TOGGLE);
+ break;
+ case MENU:
+ case BLOCK:
+ case ICONTEXTROW:
+ wt= widget_type(UI_WTYPE_MENU_RADIO);
+ break;
+
+ case PULLDOWN:
+ case HMENU:
+ wt= widget_type(UI_WTYPE_PULLDOWN);
+ break;
+
+ case BUTM:
+ wt= widget_type(UI_WTYPE_MENU_ITEM);
+ break;
+
+ case COL:
+ wt= widget_type(UI_WTYPE_SWATCH);
+ break;
+
+ // XXX four old button types
+ case HSVCUBE:
+ ui_draw_but_HSVCUBE(but, rect);
+ break;
+ case BUT_COLORBAND:
+ ui_draw_but_COLORBAND(but, rect);
+ break;
+ case BUT_NORMAL:
+ ui_draw_but_NORMAL(but, rect);
+ break;
+ case BUT_CURVE:
+ ui_draw_but_CURVE(ar, but, rect);
+ break;
+
+ default:
+ wt= widget_type(UI_WTYPE_TOGGLE);
+ }
+ }
+
+ if(wt) {
+ rcti disablerect= *rect; /* rect gets clipped smaller for text */
+ int roundboxalign, state;
+
+ roundboxalign= widget_roundbox_set(but, rect);
+ state= but->flag;
+ if(but->editstr) state |= UI_TEXTINPUT;
+
+ wt->state(wt, state);
+ if(wt->custom)
+ wt->custom(but, &wt->wcol, rect, state, roundboxalign);
+ else if(wt->draw)
+ wt->draw(&wt->wcol, rect, state, roundboxalign);
+ wt->text(&style->widget, but, rect, wt->wcol.text);
+
+ if(state & UI_BUT_DISABLED)
+ if(but->dt!=UI_EMBOSSP)
+ widget_disabled(&disablerect);
+ }
+}
+
+void ui_draw_menu_back(uiStyle *style, uiBlock *block, rcti *rect)
+{
+ uiWidgetType *wt= widget_type(UI_WTYPE_MENU_BACK);
+
+ wt->state(wt, 0);
+ if(block)
+ wt->draw(&wt->wcol, rect, block->flag, block->direction);
+ else
+ wt->draw(&wt->wcol, rect, 0, 0);
+
+}
+
+/* test function only */
+void drawnewstuff()
+{
+ rcti rect;
+
+ rect.xmin= 10; rect.xmax= 10+100;
+ rect.ymin= -30; rect.ymax= -30+18;
+ widget_numbut(&wcol_num, &rect, 0, 15);
+
+ rect.xmin= 120; rect.xmax= 120+100;
+ rect.ymin= -30; rect.ymax= -30+20;
+ widget_numbut(&wcol_num, &rect, 0, 15);
+
+ rect.xmin= 10; rect.xmax= 10+100;
+ rect.ymin= -60; rect.ymax= -60+20;
+ widget_menubut(&wcol_menu, &rect, 0, 15);
+
+ rect.xmin= 120; rect.xmax= 120+100;
+ widget_but(&wcol_regular, &rect, 0, 15);
+
+ rect.xmin= 10; rect.xmax= 10+100;
+ rect.ymin= -90; rect.ymax= -90+20;
+ widget_radiobut(&wcol_radio, &rect, 1, 9);
+
+ rect.xmin= 109; rect.xmax= 110+100;
+ rect.ymin= -90; rect.ymax= -90+20;
+ widget_radiobut(&wcol_radio, &rect, 0, 6);
+
+ rect.xmin= 240; rect.xmax= 240+30;
+ rect.ymin= -90; rect.ymax= -90+30;
+ widget_roundbut(&wcol_regular_shade, &rect, 0, 15);
+}
+
+
+
+
diff --git a/source/blender/editors/interface/keyval.c b/source/blender/editors/interface/keyval.c
new file mode 100644
index 00000000000..f2172ac8cf0
--- /dev/null
+++ b/source/blender/editors/interface/keyval.c
@@ -0,0 +1,540 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "stdio.h"
+#include "ctype.h"
+#include "string.h"
+
+#include "BKE_global.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "WM_types.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 "";
+}
+
+/*
+ * Decodes key combination strings [qual1+[qual2+[...]]]keyname
+ * The '+'s may be replaced by '-' or ' ' characters to support different
+ * formats. No additional whitespace is allowed. The keyname may be an internal
+ * name, like "RETKEY", or a more common name, like "Return". Decoding is case-
+ * insensitive.
+ *
+ * Example strings: "Ctrl+L", "ALT-ESC", "Shift A"
+ *
+ * Returns 1 if successful.
+ */
+int decode_key_string(char *str, unsigned short *key, unsigned short *qual)
+{
+ int i, prev, len, invalid=0;
+
+ len= strlen(str);
+ *key= *qual= 0;
+
+ /* Convert to upper case */
+ for (i=0; i<len; i++) {
+ str[i]= toupper(str[i]);
+ }
+
+ /* Handle modifiers */
+ for (prev=i=0; i<len; i++) {
+ if (str[i]==' ' || str[i]=='+' || str[i]=='-') {
+// XXX if (!strncmp(str+prev, "CTRL", i-prev)) *qual |= LR_CTRLKEY;
+// else if (!strncmp(str+prev, "ALT", i-prev)) *qual |= LR_ALTKEY;
+// else if (!strncmp(str+prev, "SHIFT", i-prev)) *qual |= LR_SHIFTKEY;
+// else if (!strncmp(str+prev, "COMMAND", i-prev)) *qual |= LR_COMMANDKEY;
+ prev=i+1;
+ }
+ }
+
+ /* Compare last part against key names */
+ if ((len-prev==1) || ((len-prev==4) && !strncmp(str+prev, "KEY", 3))) {
+
+ if (str[prev]>='A' && str[prev]<='Z') {
+ *key= str[prev]-'A'+AKEY;
+ } else if (str[prev]>='0' && str[prev]<='9') {
+ *key= str[prev]-'0'+ZEROKEY;
+ } else {
+ invalid= 1;
+ }
+
+ } else if (!strncmp(str+prev, "ZEROKEY", len-prev) || !strncmp(str+prev, "ZERO", len-prev)) {
+ *key= ZEROKEY;
+ } else if (!strncmp(str+prev, "ONEKEY", len-prev) || !strncmp(str+prev, "ONE", len-prev)) {
+ *key= ONEKEY;
+ } else if (!strncmp(str+prev, "TWOKEY", len-prev) || !strncmp(str+prev, "TWO", len-prev)) {
+ *key= TWOKEY;
+ } else if (!strncmp(str+prev, "THREEKEY", len-prev) || !strncmp(str+prev, "THREE", len-prev)) {
+ *key= THREEKEY;
+ } else if (!strncmp(str+prev, "FOURKEY", len-prev) || !strncmp(str+prev, "FOUR", len-prev)) {
+ *key= FOURKEY;
+ } else if (!strncmp(str+prev, "FIVEKEY", len-prev) || !strncmp(str+prev, "FIVE", len-prev)) {
+ *key= FIVEKEY;
+ } else if (!strncmp(str+prev, "SIZEKEY", len-prev) || !strncmp(str+prev, "SIX", len-prev)) {
+ *key= SIXKEY;
+ } else if (!strncmp(str+prev, "SEVENKEY", len-prev) || !strncmp(str+prev, "SEVEN", len-prev)) {
+ *key= SEVENKEY;
+ } else if (!strncmp(str+prev, "EIGHTKEY", len-prev) || !strncmp(str+prev, "EIGHT", len-prev)) {
+ *key= EIGHTKEY;
+ } else if (!strncmp(str+prev, "NINEKEY", len-prev) || !strncmp(str+prev, "NINE", len-prev)) {
+ *key= NINEKEY;
+
+ } else if (!strncmp(str+prev, "ESCKEY", len-prev) || !strncmp(str+prev, "ESC", len-prev)) {
+ *key= ESCKEY;
+ } else if (!strncmp(str+prev, "TABKEY", len-prev) || !strncmp(str+prev, "TAB", len-prev)) {
+ *key= TABKEY;
+ } else if (!strncmp(str+prev, "RETKEY", len-prev) || !strncmp(str+prev, "RETURN", len-prev) || !strncmp(str+prev, "ENTER", len-prev)) {
+ *key= RETKEY;
+ } else if (!strncmp(str+prev, "SPACEKEY", len-prev) || !strncmp(str+prev, "SPACE", len-prev)) {
+ *key= SPACEKEY;
+ } else if (!strncmp(str+prev, "LINEFEEDKEY", len-prev) || !strncmp(str+prev, "LINEFEED", len-prev)) {
+ *key= LINEFEEDKEY;
+ } else if (!strncmp(str+prev, "BACKSPACEKEY", len-prev) || !strncmp(str+prev, "BACKSPACE", len-prev)) {
+ *key= BACKSPACEKEY;
+ } else if (!strncmp(str+prev, "DELKEY", len-prev) || !strncmp(str+prev, "DELETE", len-prev)) {
+ *key= DELKEY;
+
+ } else if (!strncmp(str+prev, "SEMICOLONKEY", len-prev) || !strncmp(str+prev, "SEMICOLON", len-prev)) {
+ *key= SEMICOLONKEY;
+ } else if (!strncmp(str+prev, "PERIODKEY", len-prev) || !strncmp(str+prev, "PERIOD", len-prev)) {
+ *key= PERIODKEY;
+ } else if (!strncmp(str+prev, "COMMAKEY", len-prev) || !strncmp(str+prev, "COMMA", len-prev)) {
+ *key= COMMAKEY;
+ } else if (!strncmp(str+prev, "QUOTEKEY", len-prev) || !strncmp(str+prev, "QUOTE", len-prev)) {
+ *key= QUOTEKEY;
+ } else if (!strncmp(str+prev, "ACCENTGRAVEKEY", len-prev) || !strncmp(str+prev, "ACCENTGRAVE", len-prev)) {
+ *key= ACCENTGRAVEKEY;
+ } else if (!strncmp(str+prev, "MINUSKEY", len-prev) || !strncmp(str+prev, "MINUS", len-prev)) {
+ *key= MINUSKEY;
+ } else if (!strncmp(str+prev, "SLASHKEY", len-prev) || !strncmp(str+prev, "SLASH", len-prev)) {
+ *key= SLASHKEY;
+ } else if (!strncmp(str+prev, "BACKSLASHKEY", len-prev) || !strncmp(str+prev, "BACKSLASH", len-prev)) {
+ *key= BACKSLASHKEY;
+ } else if (!strncmp(str+prev, "EQUALKEY", len-prev) || !strncmp(str+prev, "EQUAL", len-prev)) {
+ *key= EQUALKEY;
+ } else if (!strncmp(str+prev, "LEFTBRACKETKEY", len-prev) || !strncmp(str+prev, "LEFTBRACKET", len-prev)) {
+ *key= LEFTBRACKETKEY;
+ } else if (!strncmp(str+prev, "RIGHTBRACKETKEY", len-prev) || !strncmp(str+prev, "RIGHTBRACKET", len-prev)) {
+ *key= RIGHTBRACKETKEY;
+ } else if (!strncmp(str+prev, "DELKEY", len-prev) || !strncmp(str+prev, "DELETE", len-prev)) {
+ *key= DELKEY;
+
+ } else if (!strncmp(str+prev, "LEFTARROWKEY", len-prev) || !strncmp(str+prev, "LEFTARROW", len-prev)) {
+ *key= LEFTARROWKEY;
+ } else if (!strncmp(str+prev, "DOWNARROWKEY", len-prev) || !strncmp(str+prev, "DOWNARROW", len-prev)) {
+ *key= DOWNARROWKEY;
+ } else if (!strncmp(str+prev, "RIGHTARROWKEY", len-prev) || !strncmp(str+prev, "RIGHTARROW", len-prev)) {
+ *key= RIGHTARROWKEY;
+ } else if (!strncmp(str+prev, "UPARROWKEY", len-prev) || !strncmp(str+prev, "UPARROW", len-prev)) {
+ *key= UPARROWKEY;
+
+ } else if (!strncmp(str+prev, "PAD", 3)) {
+
+ if (len-prev<=4) {
+
+ if (str[prev]>='0' && str[prev]<='9') {
+ *key= str[prev]-'0'+ZEROKEY;
+ } else {
+ invalid= 1;
+ }
+
+ } else if (!strncmp(str+prev+3, "PERIODKEY", len-prev-3) || !strncmp(str+prev+3, "PERIOD", len-prev-3)) {
+ *key= PADPERIOD;
+ } else if (!strncmp(str+prev+3, "SLASHKEY", len-prev-3) || !strncmp(str+prev+3, "SLASH", len-prev-3)) {
+ *key= PADSLASHKEY;
+ } else if (!strncmp(str+prev+3, "ASTERKEY", len-prev-3) || !strncmp(str+prev+3, "ASTERISK", len-prev-3)) {
+ *key= PADASTERKEY;
+ } else if (!strncmp(str+prev+3, "MINUSKEY", len-prev-3) || !strncmp(str+prev+3, "MINUS", len-prev-3)) {
+ *key= PADMINUS;
+ } else if (!strncmp(str+prev+3, "ENTERKEY", len-prev-3) || !strncmp(str+prev+3, "ENTER", len-prev-3)) {
+ *key= PADENTER;
+ } else if (!strncmp(str+prev+3, "PLUSKEY", len-prev-3) || !strncmp(str+prev+3, "PLUS", len-prev-3)) {
+ *key= PADPLUSKEY;
+ } else {
+ invalid= 1;
+ }
+
+ } else if (!strncmp(str+prev, "F1KEY", len-prev) || !strncmp(str+prev, "F1", len-prev)) {
+ *key= F1KEY;
+ } else if (!strncmp(str+prev, "F2KEY", len-prev) || !strncmp(str+prev, "F2", len-prev)) {
+ *key= F2KEY;
+ } else if (!strncmp(str+prev, "F3KEY", len-prev) || !strncmp(str+prev, "F3", len-prev)) {
+ *key= F3KEY;
+ } else if (!strncmp(str+prev, "F4KEY", len-prev) || !strncmp(str+prev, "F4", len-prev)) {
+ *key= F4KEY;
+ } else if (!strncmp(str+prev, "F5KEY", len-prev) || !strncmp(str+prev, "F5", len-prev)) {
+ *key= F5KEY;
+ } else if (!strncmp(str+prev, "F6KEY", len-prev) || !strncmp(str+prev, "F6", len-prev)) {
+ *key= F6KEY;
+ } else if (!strncmp(str+prev, "F7KEY", len-prev) || !strncmp(str+prev, "F7", len-prev)) {
+ *key= F7KEY;
+ } else if (!strncmp(str+prev, "F8KEY", len-prev) || !strncmp(str+prev, "F8", len-prev)) {
+ *key= F8KEY;
+ } else if (!strncmp(str+prev, "F9KEY", len-prev) || !strncmp(str+prev, "F9", len-prev)) {
+ *key= F9KEY;
+ } else if (!strncmp(str+prev, "F10KEY", len-prev) || !strncmp(str+prev, "F10", len-prev)) {
+ *key= F10KEY;
+ } else if (!strncmp(str+prev, "F11KEY", len-prev) || !strncmp(str+prev, "F11", len-prev)) {
+ *key= F11KEY;
+ } else if (!strncmp(str+prev, "F12KEY", len-prev) || !strncmp(str+prev, "F12", len-prev)) {
+ *key= F12KEY;
+
+ } else if (!strncmp(str+prev, "PAUSEKEY", len-prev) || !strncmp(str+prev, "PAUSE", len-prev)) {
+ *key= PAUSEKEY;
+ } else if (!strncmp(str+prev, "INSERTKEY", len-prev) || !strncmp(str+prev, "INSERT", len-prev)) {
+ *key= INSERTKEY;
+ } else if (!strncmp(str+prev, "HOMEKEY", len-prev) || !strncmp(str+prev, "HOME", len-prev)) {
+ *key= HOMEKEY;
+ } else if (!strncmp(str+prev, "PAGEUPKEY", len-prev) || !strncmp(str+prev, "PAGEUP", len-prev)) {
+ *key= PAGEUPKEY;
+ } else if (!strncmp(str+prev, "PAGEDOWNKEY", len-prev) || !strncmp(str+prev, "PAGEDOWN", len-prev)) {
+ *key= PAGEDOWNKEY;
+ } else if (!strncmp(str+prev, "ENDKEY", len-prev) || !strncmp(str+prev, "END", len-prev)) {
+ *key= ENDKEY;
+
+ } else {
+ invalid= 1;
+ }
+
+ if (!invalid && *key) {
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
new file mode 100644
index 00000000000..039ebcc91f9
--- /dev/null
+++ b/source/blender/editors/interface/resources.c
@@ -0,0 +1,987 @@
+/**
+ * $Id: resources.c 12755 2007-12-02 05:50:38Z aligorith $
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN 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 HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_userdef_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+
+#include "UI_resources.h"
+#include "UI_interface_icons.h"
+//#include "UI_icons.h"
+
+#include "BLI_blenlib.h"
+
+/* global for themes */
+typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
+
+static bTheme *theme_active=NULL;
+static int theme_spacetype= SPACE_VIEW3D;
+
+
+void ui_resources_init(void)
+{
+ UI_icons_init(BIFICONID_LAST+1);
+}
+
+void ui_resources_free(void)
+{
+ UI_icons_free();
+}
+
+
+/* ******************************************************** */
+/* THEMES */
+/* ******************************************************** */
+
+char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
+{
+ ThemeSpace *ts= NULL;
+ static char error[4]={240, 0, 240, 255};
+ static char alert[4]={240, 60, 60, 255};
+ static char headerdesel[4]={0,0,0,255};
+ static char custom[4]={0,0,0,255};
+
+ char *cp= error;
+
+ if(btheme) {
+
+ // first check for ui buttons theme
+ if(colorid < TH_THEMEUI) {
+
+ switch(colorid) {
+ case TH_BUT_OUTLINE:
+ cp= btheme->tui.outline; break;
+ case TH_BUT_NEUTRAL:
+ cp= btheme->tui.neutral; break;
+ case TH_BUT_ACTION:
+ cp= btheme->tui.action; break;
+ case TH_BUT_SETTING:
+ cp= btheme->tui.setting; break;
+ case TH_BUT_SETTING1:
+ cp= btheme->tui.setting1; break;
+ case TH_BUT_SETTING2:
+ cp= btheme->tui.setting2; break;
+ case TH_BUT_NUM:
+ cp= btheme->tui.num; break;
+ case TH_BUT_TEXTFIELD:
+ cp= btheme->tui.textfield; break;
+ case TH_BUT_TEXTFIELD_HI:
+ cp= btheme->tui.textfield_hi; break;
+ case TH_BUT_POPUP:
+ cp= btheme->tui.popup; break;
+ case TH_BUT_TEXT:
+ cp= btheme->tui.text; break;
+ case TH_BUT_TEXT_HI:
+ cp= btheme->tui.text_hi; break;
+ case TH_MENU_BACK:
+ cp= btheme->tui.menu_back; break;
+ case TH_MENU_ITEM:
+ cp= btheme->tui.menu_item; break;
+ case TH_MENU_HILITE:
+ cp= btheme->tui.menu_hilite; break;
+ case TH_MENU_TEXT:
+ cp= btheme->tui.menu_text; break;
+ case TH_MENU_TEXT_HI:
+ cp= btheme->tui.menu_text_hi; break;
+
+ case TH_BUT_DRAWTYPE:
+ cp= &btheme->tui.but_drawtype; break;
+
+ case TH_ICONFILE:
+ cp= btheme->tui.iconfile; break;
+
+ case TH_REDALERT:
+ cp= alert; break;
+ case TH_CUSTOM:
+ cp= custom; break;
+ }
+ }
+ else {
+
+ switch(spacetype) {
+ case SPACE_BUTS:
+ ts= &btheme->tbuts;
+ break;
+ case SPACE_VIEW3D:
+ ts= &btheme->tv3d;
+ break;
+ case SPACE_IPO:
+ ts= &btheme->tipo;
+ break;
+ case SPACE_FILE:
+ ts= &btheme->tfile;
+ break;
+ case SPACE_NLA:
+ ts= &btheme->tnla;
+ break;
+ case SPACE_ACTION:
+ ts= &btheme->tact;
+ break;
+ case SPACE_SEQ:
+ ts= &btheme->tseq;
+ break;
+ case SPACE_IMAGE:
+ ts= &btheme->tima;
+ break;
+ case SPACE_IMASEL:
+ ts= &btheme->timasel;
+ break;
+ case SPACE_TEXT:
+ ts= &btheme->text;
+ break;
+ case SPACE_OUTLINER:
+ ts= &btheme->toops;
+ break;
+ case SPACE_SOUND:
+ ts= &btheme->tsnd;
+ break;
+ case SPACE_INFO:
+ ts= &btheme->tinfo;
+ break;
+ case SPACE_TIME:
+ ts= &btheme->ttime;
+ break;
+ case SPACE_NODE:
+ ts= &btheme->tnode;
+ break;
+ default:
+ ts= &btheme->tv3d;
+ break;
+ }
+
+ switch(colorid) {
+ case TH_BACK:
+ cp= ts->back; break;
+ case TH_TEXT:
+ cp= ts->text; break;
+ case TH_TEXT_HI:
+ cp= ts->text_hi; break;
+ case TH_HEADER:
+ cp= ts->header; break;
+ case TH_HEADERDESEL:
+ /* we calculate a dynamic builtin header deselect color, also for pulldowns... */
+ cp= ts->header;
+ headerdesel[0]= cp[0]>10?cp[0]-10:0;
+ headerdesel[1]= cp[1]>10?cp[1]-10:0;
+ headerdesel[2]= cp[2]>10?cp[2]-10:0;
+ cp= headerdesel;
+ break;
+ case TH_PANEL:
+ cp= ts->panel; break;
+ case TH_SHADE1:
+ cp= ts->shade1; break;
+ case TH_SHADE2:
+ cp= ts->shade2; break;
+ case TH_HILITE:
+ cp= ts->hilite; break;
+
+ case TH_GRID:
+ cp= ts->grid; break;
+ case TH_WIRE:
+ cp= ts->wire; break;
+ case TH_LAMP:
+ cp= ts->lamp; break;
+ case TH_SELECT:
+ cp= ts->select; break;
+ case TH_ACTIVE:
+ cp= ts->active; break;
+ case TH_GROUP:
+ cp= ts->group; break;
+ case TH_GROUP_ACTIVE:
+ cp= ts->group_active; break;
+ case TH_TRANSFORM:
+ cp= ts->transform; break;
+ case TH_VERTEX:
+ cp= ts->vertex; break;
+ case TH_VERTEX_SELECT:
+ cp= ts->vertex_select; break;
+ case TH_VERTEX_SIZE:
+ cp= &ts->vertex_size; break;
+ case TH_EDGE:
+ cp= ts->edge; break;
+ case TH_EDGE_SELECT:
+ cp= ts->edge_select; break;
+ case TH_EDGE_SEAM:
+ cp= ts->edge_seam; break;
+ case TH_EDGE_SHARP:
+ cp= ts->edge_sharp; break;
+ case TH_EDITMESH_ACTIVE:
+ cp= ts->editmesh_active; break;
+ case TH_EDGE_FACESEL:
+ cp= ts->edge_facesel; break;
+ case TH_FACE:
+ cp= ts->face; break;
+ case TH_FACE_SELECT:
+ cp= ts->face_select; break;
+ case TH_FACE_DOT:
+ cp= ts->face_dot; break;
+ case TH_FACEDOT_SIZE:
+ cp= &ts->facedot_size; break;
+ case TH_NORMAL:
+ cp= ts->normal; break;
+ case TH_BONE_SOLID:
+ cp= ts->bone_solid; break;
+ case TH_BONE_POSE:
+ cp= ts->bone_pose; break;
+ case TH_STRIP:
+ cp= ts->strip; break;
+ case TH_STRIP_SELECT:
+ cp= ts->strip_select; break;
+ case TH_CFRAME:
+ cp= ts->cframe; break;
+
+ case TH_SYNTAX_B:
+ cp= ts->syntaxb; break;
+ case TH_SYNTAX_V:
+ cp= ts->syntaxv; break;
+ case TH_SYNTAX_C:
+ cp= ts->syntaxc; break;
+ case TH_SYNTAX_L:
+ cp= ts->syntaxl; break;
+ case TH_SYNTAX_N:
+ cp= ts->syntaxn; break;
+
+ case TH_NODE:
+ cp= ts->syntaxl; break;
+ case TH_NODE_IN_OUT:
+ cp= ts->syntaxn; break;
+ case TH_NODE_OPERATOR:
+ cp= ts->syntaxb; break;
+ case TH_NODE_CONVERTOR:
+ cp= ts->syntaxv; break;
+ case TH_NODE_GROUP:
+ cp= ts->syntaxc; break;
+
+ case TH_SEQ_MOVIE:
+ cp= ts->movie; break;
+ case TH_SEQ_IMAGE:
+ cp= ts->image; break;
+ case TH_SEQ_SCENE:
+ cp= ts->scene; break;
+ case TH_SEQ_AUDIO:
+ cp= ts->audio; break;
+ case TH_SEQ_EFFECT:
+ cp= ts->effect; break;
+ case TH_SEQ_PLUGIN:
+ cp= ts->plugin; break;
+ case TH_SEQ_TRANSITION:
+ cp= ts->transition; break;
+ case TH_SEQ_META:
+ cp= ts->meta; break;
+
+ case TH_HANDLE_VERTEX:
+ cp= ts->handle_vertex;
+ break;
+ case TH_HANDLE_VERTEX_SELECT:
+ cp= ts->handle_vertex_select;
+ break;
+ case TH_HANDLE_VERTEX_SIZE:
+ cp= &ts->handle_vertex_size;
+ break;
+
+ case TH_DOPESHEET_CHANNELOB:
+ cp= ts->ds_channel;
+ break;
+ case TH_DOPESHEET_CHANNELSUBOB:
+ cp= ts->ds_subchannel;
+ break;
+
+ }
+ }
+ }
+
+ return cp;
+}
+
+#define SETCOL(col, r, g, b, a) col[0]=r; col[1]=g; col[2]= b; col[3]= a;
+
+/* initialize
+ Note: when you add new colors, created & saved themes need initialized
+ in usiblender.c, search for "versionfile"
+*/
+void ui_theme_init_userdef(void)
+{
+ bTheme *btheme= U.themes.first;
+
+ /* we search for the theme with name Default */
+ for(btheme= U.themes.first; btheme; btheme= btheme->next) {
+ if(strcmp("Default", btheme->name)==0) break;
+ }
+
+ if(btheme==NULL) {
+ btheme= MEM_callocN(sizeof(bTheme), "theme");
+ BLI_addtail(&U.themes, btheme);
+ strcpy(btheme->name, "Default");
+ }
+
+ UI_SetTheme(NULL); // make sure the global used in this file is set
+
+ /* UI buttons */
+ SETCOL(btheme->tui.outline, 130, 130, 130, 255);
+ SETCOL(btheme->tui.neutral, 165, 165, 165, 255);
+ SETCOL(btheme->tui.action, 165, 165, 165, 255);
+ SETCOL(btheme->tui.setting, 165, 165, 165, 255);
+ SETCOL(btheme->tui.setting1, 165, 165, 165, 255);
+ SETCOL(btheme->tui.setting2, 165, 165, 165, 255);
+ SETCOL(btheme->tui.num, 165, 165, 165, 255);
+ SETCOL(btheme->tui.textfield, 143, 142, 143, 255);
+ SETCOL(btheme->tui.textfield_hi,255, 151, 26, 255);
+ SETCOL(btheme->tui.popup, 174, 174, 174, 255);
+
+ SETCOL(btheme->tui.text, 0,0,0, 255);
+ SETCOL(btheme->tui.text_hi, 255, 255, 255, 255);
+
+ SETCOL(btheme->tui.menu_back, 220, 220, 220, 235);
+ SETCOL(btheme->tui.menu_item, 255, 255, 255, 20);
+ SETCOL(btheme->tui.menu_hilite, 110, 110, 110, 255);
+ SETCOL(btheme->tui.menu_text, 0, 0, 0, 255);
+ SETCOL(btheme->tui.menu_text_hi, 255, 255, 255, 255);
+
+ btheme->tui.but_drawtype= TH_ROUNDSHADED;
+ BLI_strncpy(btheme->tui.iconfile, "", sizeof(btheme->tui.iconfile));
+
+ /* space view3d */
+ SETCOL(btheme->tv3d.back, 90, 90, 90, 255);
+ SETCOL(btheme->tv3d.text, 0, 0, 0, 255);
+ SETCOL(btheme->tv3d.text_hi, 255, 255, 255, 255);
+ SETCOL(btheme->tv3d.header, 185, 185, 185, 255);
+ SETCOL(btheme->tv3d.panel, 165, 165, 165, 127);
+
+ SETCOL(btheme->tv3d.shade1, 160, 160, 160, 100);
+ SETCOL(btheme->tv3d.shade2, 0x7f, 0x70, 0x70, 100);
+
+ SETCOL(btheme->tv3d.grid, 74, 74, 74 , 255);
+ SETCOL(btheme->tv3d.wire, 0x0, 0x0, 0x0, 255);
+ SETCOL(btheme->tv3d.lamp, 0, 0, 0, 40);
+ SETCOL(btheme->tv3d.select, 241, 88, 0, 255);
+ SETCOL(btheme->tv3d.active, 255, 140, 25, 255);
+ SETCOL(btheme->tv3d.group, 16, 64, 16, 255);
+ SETCOL(btheme->tv3d.group_active, 85, 187, 85, 255);
+ SETCOL(btheme->tv3d.transform, 0xff, 0xff, 0xff, 255);
+ SETCOL(btheme->tv3d.vertex, 0, 0, 0, 255);
+ SETCOL(btheme->tv3d.vertex_select, 255, 133, 0, 255);
+ btheme->tv3d.vertex_size= 3;
+ SETCOL(btheme->tv3d.edge, 0x0, 0x0, 0x0, 255);
+ SETCOL(btheme->tv3d.edge_select, 255, 160, 0, 255);
+ SETCOL(btheme->tv3d.edge_seam, 219, 37, 18, 255);
+ SETCOL(btheme->tv3d.edge_facesel, 75, 75, 75, 255);
+ SETCOL(btheme->tv3d.face, 0, 0, 0, 18);
+ SETCOL(btheme->tv3d.face_select, 255, 133, 0, 60);
+ SETCOL(btheme->tv3d.normal, 0x22, 0xDD, 0xDD, 255);
+ SETCOL(btheme->tv3d.face_dot, 255, 133, 0, 255);
+ btheme->tv3d.facedot_size= 4;
+ SETCOL(btheme->tv3d.cframe, 0x60, 0xc0, 0x40, 255);
+
+ SETCOL(btheme->tv3d.bone_solid, 200, 200, 200, 255);
+ SETCOL(btheme->tv3d.bone_pose, 80, 200, 255, 80); // alpha 80 is not meant editable, used for wire+action draw
+
+
+ /* space buttons */
+ /* to have something initialized */
+ btheme->tbuts= btheme->tv3d;
+
+ SETCOL(btheme->tbuts.back, 0x82, 0x82, 0x82, 255);
+ SETCOL(btheme->tbuts.header, 185, 185, 185, 255);
+ SETCOL(btheme->tbuts.panel, 0x82, 0x82, 0x82, 255);
+
+ /* space ipo */
+ /* to have something initialized */
+ btheme->tipo= btheme->tv3d;
+
+ SETCOL(btheme->tipo.grid, 94, 94, 94, 255);
+ SETCOL(btheme->tipo.back, 120, 120, 120, 255);
+ SETCOL(btheme->tipo.header, 185, 185, 185, 255);
+ SETCOL(btheme->tipo.panel, 255, 255, 255, 150);
+ SETCOL(btheme->tipo.shade1, 172, 172, 172, 100);
+ SETCOL(btheme->tipo.shade2, 0x70, 0x70, 0x70, 100);
+ SETCOL(btheme->tipo.vertex, 0, 0, 0, 255);
+ SETCOL(btheme->tipo.vertex_select, 255, 133, 0, 255);
+ SETCOL(btheme->tipo.hilite, 0x60, 0xc0, 0x40, 255);
+ btheme->tipo.vertex_size= 3;
+
+ SETCOL(btheme->tipo.handle_vertex, 0, 0, 0, 255);
+ SETCOL(btheme->tipo.handle_vertex_select, 255, 133, 0, 255);
+ btheme->tipo.handle_vertex_size= 3;
+
+ SETCOL(btheme->tipo.ds_channel, 82, 96, 110, 255);
+ SETCOL(btheme->tipo.ds_subchannel, 124, 137, 150, 255);
+ SETCOL(btheme->tipo.group, 79, 101, 73, 255);
+ SETCOL(btheme->tipo.group_active, 135, 177, 125, 255);
+
+ /* space file */
+ /* to have something initialized */
+ btheme->tfile= btheme->tv3d;
+ SETCOL(btheme->tfile.back, 90, 90, 90, 255);
+ SETCOL(btheme->tfile.text, 250, 250, 250, 255);
+ SETCOL(btheme->tfile.text_hi, 15, 15, 15, 255);
+ SETCOL(btheme->tfile.header, 185, 185, 185, 255);
+ SETCOL(btheme->tfile.panel, 180, 180, 180, 255); // bookmark/ui regions
+ SETCOL(btheme->tfile.active, 130, 130, 130, 255); // selected files
+ SETCOL(btheme->tfile.hilite, 255, 140, 25, 255); // selected files
+
+ SETCOL(btheme->tfile.grid, 250, 250, 250, 255);
+ SETCOL(btheme->tfile.image, 250, 250, 250, 255);
+ SETCOL(btheme->tfile.movie, 250, 250, 250, 255);
+ SETCOL(btheme->tfile.scene, 250, 250, 250, 255);
+
+
+ /* space action */
+ btheme->tact= btheme->tv3d;
+ SETCOL(btheme->tact.back, 116, 116, 116, 255);
+ SETCOL(btheme->tact.text, 0, 0, 0, 255);
+ SETCOL(btheme->tact.text_hi, 255, 255, 255, 255);
+ SETCOL(btheme->tact.header, 185, 185, 185, 255);
+ SETCOL(btheme->tact.grid, 94, 94, 94, 255);
+ SETCOL(btheme->tact.face, 166, 166, 166, 255); // RVK
+ SETCOL(btheme->tact.shade1, 172, 172, 172, 255); // sliders
+ SETCOL(btheme->tact.shade2, 74, 74, 74, 100); // bar
+ SETCOL(btheme->tact.hilite, 255, 160, 0, 100); // bar
+ SETCOL(btheme->tact.strip_select, 255, 160, 0, 255);
+ SETCOL(btheme->tact.strip, 78, 78, 78, 255);
+ SETCOL(btheme->tact.group, 79, 101, 73, 255);
+ SETCOL(btheme->tact.group_active, 135, 177, 125, 255)
+ SETCOL(btheme->tact.ds_channel, 82, 96, 110, 255);
+ SETCOL(btheme->tact.ds_subchannel, 124, 137, 150, 255);
+
+
+ /* space nla */
+ btheme->tnla= btheme->tv3d;
+ SETCOL(btheme->tnla.back, 116, 116, 116, 255);
+ SETCOL(btheme->tnla.text, 0, 0, 0, 255);
+ SETCOL(btheme->tnla.text_hi, 255, 255, 255, 255);
+ SETCOL(btheme->tnla.header, 185, 185, 185, 255);
+ SETCOL(btheme->tnla.grid, 94, 94, 94, 255);
+ SETCOL(btheme->tnla.shade1, 172, 172, 172, 255); // sliders
+ SETCOL(btheme->tnla.shade2, 84, 44, 31, 100); // bar
+ SETCOL(btheme->tnla.hilite, 17, 27, 60, 100); // bar
+ SETCOL(btheme->tnla.strip_select, 0xff, 0xff, 0xaa, 255);
+ SETCOL(btheme->tnla.strip, 0xe4, 0x9c, 0xc6, 255);
+
+ /* space seq */
+ btheme->tseq= btheme->tv3d;
+ SETCOL(btheme->tseq.back, 116, 116, 116, 255);
+ SETCOL(btheme->tseq.movie, 81, 105, 135, 255);
+ SETCOL(btheme->tseq.image, 109, 88, 129, 255);
+ SETCOL(btheme->tseq.scene, 78, 152, 62, 255);
+ SETCOL(btheme->tseq.audio, 46, 143, 143, 255);
+ SETCOL(btheme->tseq.effect, 169, 84, 124, 255);
+ SETCOL(btheme->tseq.plugin, 126, 126, 80, 255);
+ SETCOL(btheme->tseq.transition, 162, 95, 111, 255);
+ SETCOL(btheme->tseq.meta, 109, 145, 131, 255);
+
+
+ /* space image */
+ btheme->tima= btheme->tv3d;
+ SETCOL(btheme->tima.back, 53, 53, 53, 255);
+ SETCOL(btheme->tima.vertex, 0, 0, 0, 255);
+ SETCOL(btheme->tima.vertex_select, 255, 133, 0, 255);
+ btheme->tima.vertex_size= 3;
+ btheme->tima.facedot_size= 3;
+ SETCOL(btheme->tima.face, 255, 255, 255, 10);
+ SETCOL(btheme->tima.face_select, 255, 133, 0, 60);
+ SETCOL(btheme->tima.editmesh_active, 255, 255, 255, 128);
+
+ /* space imageselect */
+ btheme->timasel= btheme->tv3d;
+ SETCOL(btheme->timasel.active, 195, 195, 195, 255); /* active tile */
+ SETCOL(btheme->timasel.grid, 94, 94, 94, 255); /* active file text */
+ SETCOL(btheme->timasel.back, 110, 110, 110, 255);
+ SETCOL(btheme->timasel.header, 185, 185, 185, 255);
+ SETCOL(btheme->timasel.shade1, 94, 94, 94, 255); /* bar */
+ SETCOL(btheme->timasel.shade2, 172, 172, 172, 255); /* sliders */
+ SETCOL(btheme->timasel.hilite, 17, 27, 60, 100); /* selected tile */
+ SETCOL(btheme->timasel.text, 0, 0, 0, 255);
+ SETCOL(btheme->timasel.text_hi, 255, 255, 255, 255);
+ SETCOL(btheme->timasel.panel, 132, 132, 132, 255);
+
+ /* space text */
+ btheme->text= btheme->tv3d;
+ SETCOL(btheme->text.back, 153, 153, 153, 255);
+ SETCOL(btheme->text.shade1, 143, 143, 143, 255);
+ SETCOL(btheme->text.shade2, 0xc6, 0x77, 0x77, 255);
+ SETCOL(btheme->text.hilite, 255, 0, 0, 255);
+
+ /* syntax highlighting */
+ SETCOL(btheme->text.syntaxn, 0, 0, 200, 255); /* Numbers Blue*/
+ SETCOL(btheme->text.syntaxl, 100, 0, 0, 255); /* Strings red */
+ SETCOL(btheme->text.syntaxc, 0, 100, 50, 255); /* Comments greenish */
+ SETCOL(btheme->text.syntaxv, 95, 95, 0, 255); /* Special */
+ SETCOL(btheme->text.syntaxb, 128, 0, 80, 255); /* Builtin, red-purple */
+
+ /* space oops */
+ btheme->toops= btheme->tv3d;
+ SETCOL(btheme->toops.back, 153, 153, 153, 255);
+
+ /* space info */
+ btheme->tinfo= btheme->tv3d;
+ SETCOL(btheme->tinfo.back, 153, 153, 153, 255);
+
+ /* space sound */
+ btheme->tsnd= btheme->tv3d;
+ SETCOL(btheme->tsnd.back, 153, 153, 153, 255);
+ SETCOL(btheme->tsnd.shade1, 173, 173, 173, 255); // sliders
+ SETCOL(btheme->tsnd.grid, 140, 140, 140, 255);
+
+ /* space time */
+ btheme->ttime= btheme->tsnd; // same as sound space
+
+ /* space node, re-uses syntax color storage */
+ btheme->tnode= btheme->tv3d;
+ SETCOL(btheme->tnode.edge_select, 255, 255, 255, 255);
+ SETCOL(btheme->tnode.syntaxl, 150, 150, 150, 255); /* TH_NODE, backdrop */
+ SETCOL(btheme->tnode.syntaxn, 129, 131, 144, 255); /* in/output */
+ SETCOL(btheme->tnode.syntaxb, 127,127,127, 255); /* operator */
+ SETCOL(btheme->tnode.syntaxv, 142, 138, 145, 255); /* generator */
+ SETCOL(btheme->tnode.syntaxc, 120, 145, 120, 255); /* group */
+
+}
+
+char *UI_ThemeColorsPup(int spacetype)
+{
+ char *cp= MEM_callocN(32*32, "theme pup");
+ char *str = cp;
+
+ if(spacetype==0) {
+ str += sprintf(str, "Outline %%x%d|", TH_BUT_OUTLINE);
+ str += sprintf(str, "Neutral %%x%d|", TH_BUT_NEUTRAL);
+ str += sprintf(str, "Action %%x%d|", TH_BUT_ACTION);
+ str += sprintf(str, "Setting %%x%d|", TH_BUT_SETTING);
+ str += sprintf(str, "Special Setting 1%%x%d|", TH_BUT_SETTING1);
+ str += sprintf(str, "Special Setting 2 %%x%d|", TH_BUT_SETTING2);
+ str += sprintf(str, "Number Input %%x%d|", TH_BUT_NUM);
+ str += sprintf(str, "Text Input %%x%d|", TH_BUT_TEXTFIELD);
+ str += sprintf(str, "Text Input Highlight %%x%d|", TH_BUT_TEXTFIELD_HI);
+ str += sprintf(str, "Popup %%x%d|", TH_BUT_POPUP);
+ str += sprintf(str, "Text %%x%d|", TH_BUT_TEXT);
+ str += sprintf(str, "Text Highlight %%x%d|", TH_BUT_TEXT_HI);
+ str += sprintf(str, "%%l|");
+ str += sprintf(str, "Menu Background %%x%d|", TH_MENU_BACK);
+ str += sprintf(str, "Menu Item %%x%d|", TH_MENU_ITEM);
+ str += sprintf(str, "Menu Item Highlight %%x%d|", TH_MENU_HILITE);
+ str += sprintf(str, "Menu Text %%x%d|", TH_MENU_TEXT);
+ str += sprintf(str, "Menu Text Highlight %%x%d|", TH_MENU_TEXT_HI);
+ str += sprintf(str, "%%l|");
+ str += sprintf(str, "Drawtype %%x%d|", TH_BUT_DRAWTYPE);
+ str += sprintf(str, "%%l|");
+ str += sprintf(str, "Icon File %%x%d|", TH_ICONFILE);
+ }
+ else {
+ // first defaults for each space
+ str += sprintf(str, "Background %%x%d|", TH_BACK);
+ str += sprintf(str, "Text %%x%d|", TH_TEXT);
+ str += sprintf(str, "Text Highlight %%x%d|", TH_TEXT_HI);
+ str += sprintf(str, "Header %%x%d|", TH_HEADER);
+
+ switch(spacetype) {
+ case SPACE_VIEW3D:
+ str += sprintf(str, "Panel %%x%d|", TH_PANEL);
+ str += sprintf(str, "%%l|");
+ str += sprintf(str, "Grid %%x%d|", TH_GRID);
+ str += sprintf(str, "Wire %%x%d|", TH_WIRE);
+ str += sprintf(str, "Lamp %%x%d|", TH_LAMP);
+ str += sprintf(str, "Object Selected %%x%d|", TH_SELECT);
+ str += sprintf(str, "Object Active %%x%d|", TH_ACTIVE);
+ str += sprintf(str, "Object Grouped %%x%d|", TH_GROUP);
+ str += sprintf(str, "Object Grouped Active %%x%d|", TH_GROUP_ACTIVE);
+ str += sprintf(str, "Transform %%x%d|", TH_TRANSFORM);
+ str += sprintf(str, "%%l|");
+ str += sprintf(str, "Vertex %%x%d|", TH_VERTEX);
+ str += sprintf(str, "Vertex Selected %%x%d|", TH_VERTEX_SELECT);
+ str += sprintf(str, "Vertex Size %%x%d|", TH_VERTEX_SIZE);
+ str += sprintf(str, "Edge Selected %%x%d|", TH_EDGE_SELECT);
+ str += sprintf(str, "Edge Seam %%x%d|", TH_EDGE_SEAM);
+ str += sprintf(str, "Edge Sharp %%x%d|", TH_EDGE_SHARP);
+ str += sprintf(str, "Edge UV Face Select %%x%d|", TH_EDGE_FACESEL);
+ str += sprintf(str, "Face (transp) %%x%d|", TH_FACE);
+ str += sprintf(str, "Face Selected (transp) %%x%d|", TH_FACE_SELECT);
+ str += sprintf(str, "Face Dot Selected %%x%d|", TH_FACE_DOT);
+ str += sprintf(str, "Face Dot Size %%x%d|", TH_FACEDOT_SIZE);
+ str += sprintf(str, "Active Vert/Edge/Face %%x%d|", TH_EDITMESH_ACTIVE);
+ str += sprintf(str, "Normal %%x%d|", TH_NORMAL);
+ str += sprintf(str, "Bone Solid %%x%d|", TH_BONE_SOLID);
+ str += sprintf(str, "Bone Pose %%x%d", TH_BONE_POSE);
+ str += sprintf(str, "Current Frame %%x%d", TH_CFRAME);
+ break;
+ case SPACE_IPO:
+ str += sprintf(str, "Panel %%x%d|", TH_PANEL);
+ str += sprintf(str, "%%l|");
+ str += sprintf(str, "Grid %%x%d|", TH_GRID);
+ str += sprintf(str, "Window Sliders %%x%d|", TH_SHADE1);
+ str += sprintf(str, "Ipo Channels %%x%d|", TH_SHADE2);
+ str += sprintf(str, "Vertex %%x%d|", TH_VERTEX);
+ str += sprintf(str, "Vertex Selected %%x%d|", TH_VERTEX_SELECT);
+ str += sprintf(str, "Vertex Size %%x%d|", TH_VERTEX_SIZE);
+ str += sprintf(str, "Current Frame %%x%d", TH_CFRAME);
+ break;
+ case SPACE_FILE:
+ str += sprintf(str, "Selected file %%x%d", TH_HILITE);
+ break;
+ case SPACE_NLA:
+ //str += sprintf(str, "Panel %%x%d|", TH_PANEL);
+ str += sprintf(str, "%%l|");
+ str += sprintf(str, "Grid %%x%d|", TH_GRID);
+ str += sprintf(str, "View Sliders %%x%d|", TH_SHADE1);
+ str += sprintf(str, "Bars %%x%d|", TH_SHADE2);
+ str += sprintf(str, "Bars selected %%x%d|", TH_HILITE);
+ str += sprintf(str, "Strips %%x%d|", TH_STRIP);
+ str += sprintf(str, "Strips selected %%x%d|", TH_STRIP_SELECT);
+ str += sprintf(str, "Current Frame %%x%d", TH_CFRAME);
+ break;
+ case SPACE_ACTION:
+ //str += sprintf(str, "Panel %%x%d|", TH_PANEL);
+ str += sprintf(str, "%%l|");
+ str += sprintf(str, "Grid %%x%d|", TH_GRID);
+ str += sprintf(str, "RVK Sliders %%x%d|", TH_FACE);
+ str += sprintf(str, "View Sliders %%x%d|", TH_SHADE1);
+ str += sprintf(str, "Channels %%x%d|", TH_SHADE2);
+ str += sprintf(str, "Channels Selected %%x%d|", TH_HILITE);
+ str += sprintf(str, "Long Key %%x%d|", TH_STRIP);
+ str += sprintf(str, "Long Key selected %%x%d|", TH_STRIP_SELECT);
+ str += sprintf(str, "Current Frame %%x%d", TH_CFRAME);
+ break;
+ case SPACE_IMAGE:
+ str += sprintf(str, "%%l|");
+ str += sprintf(str, "Vertex %%x%d|", TH_VERTEX);
+ str += sprintf(str, "Vertex Selected %%x%d|", TH_VERTEX_SELECT);
+ str += sprintf(str, "Vertex Size %%x%d|", TH_VERTEX_SIZE);
+ str += sprintf(str, "Face %%x%d|", TH_FACE);
+ str += sprintf(str, "Face Selected %%x%d", TH_FACE_SELECT);
+ break;
+ case SPACE_SEQ:
+ str += sprintf(str, "Grid %%x%d|", TH_GRID);
+ str += sprintf(str, "Window Sliders %%x%d|", TH_SHADE1);
+ str += sprintf(str, "%%l|");
+ str += sprintf(str, "Movie Strip %%x%d|", TH_SEQ_MOVIE);
+ str += sprintf(str, "Image Strip %%x%d|", TH_SEQ_IMAGE);
+ str += sprintf(str, "Scene Strip %%x%d|", TH_SEQ_SCENE);
+ str += sprintf(str, "Audio Strip %%x%d|", TH_SEQ_AUDIO);
+ str += sprintf(str, "Effect Strip %%x%d|", TH_SEQ_EFFECT);
+ str += sprintf(str, "Plugin Strip %%x%d|", TH_SEQ_PLUGIN);
+ str += sprintf(str, "Transition Strip %%x%d|", TH_SEQ_TRANSITION);
+ str += sprintf(str, "Meta Strip %%x%d|", TH_SEQ_META);
+ str += sprintf(str, "Current Frame %%x%d", TH_CFRAME);
+ break;
+ case SPACE_SOUND:
+ str += sprintf(str, "Grid %%x%d|", TH_GRID);
+ str += sprintf(str, "Window Slider %%x%d|", TH_SHADE1);
+ str += sprintf(str, "Current Frame %%x%d", TH_CFRAME);
+ break;
+ case SPACE_BUTS:
+ str += sprintf(str, "Panel %%x%d|", TH_PANEL);
+ break;
+ case SPACE_IMASEL:
+ str += sprintf(str, "Tiles %%x%d|", TH_PANEL);
+ str += sprintf(str, "Scrollbar %%x%d|", TH_SHADE1);
+ str += sprintf(str, "Scroll Handle %%x%d|", TH_SHADE2);
+ str += sprintf(str, "Selected File %%x%d|", TH_HILITE);
+ str += sprintf(str, "Active File %%x%d|", TH_ACTIVE);
+ str += sprintf(str, "Active File Text%%x%d|", TH_GRID);
+ break;
+ case SPACE_TEXT:
+ str += sprintf(str, "Scroll Bar %%x%d|", TH_SHADE1);
+ str += sprintf(str, "Selected Text %%x%d|", TH_SHADE2);
+ str += sprintf(str, "Cursor %%x%d|", TH_HILITE);
+ str += sprintf(str, "%%l|");
+ str += sprintf(str, "Syntax Builtin %%x%d|", TH_SYNTAX_B);
+ str += sprintf(str, "Syntax Special %%x%d|", TH_SYNTAX_V);
+ str += sprintf(str, "Syntax Comment %%x%d|", TH_SYNTAX_C);
+ str += sprintf(str, "Syntax Strings %%x%d|", TH_SYNTAX_L);
+ str += sprintf(str, "Syntax Numbers %%x%d|", TH_SYNTAX_N);
+ break;
+ case SPACE_TIME:
+ str += sprintf(str, "Grid %%x%d|", TH_GRID);
+ str += sprintf(str, "Current Frame %%x%d", TH_CFRAME);
+ break;
+ case SPACE_NODE:
+ str += sprintf(str, "Wires %%x%d|", TH_WIRE);
+ str += sprintf(str, "Wires Select %%x%d|", TH_EDGE_SELECT);
+ str += sprintf(str, "%%l|");
+ str += sprintf(str, "Node Backdrop %%x%d|", TH_NODE);
+ str += sprintf(str, "In/Out Node %%x%d|", TH_NODE_IN_OUT);
+ str += sprintf(str, "Convertor Node %%x%d|", TH_NODE_CONVERTOR);
+ str += sprintf(str, "Operator Node %%x%d|", TH_NODE_OPERATOR);
+ str += sprintf(str, "Group Node %%x%d|", TH_NODE_GROUP);
+ break;
+ }
+ }
+ return cp;
+}
+
+void UI_SetTheme(ScrArea *sa)
+{
+ if(sa==NULL) { // called for safety, when delete themes
+ theme_active= U.themes.first;
+ theme_spacetype= SPACE_VIEW3D;
+ }
+ else {
+ // later on, a local theme can be found too
+ theme_active= U.themes.first;
+ theme_spacetype= sa->spacetype;
+
+ }
+}
+
+// for space windows only
+void UI_ThemeColor(int colorid)
+{
+ char *cp;
+
+ cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ glColor3ub(cp[0], cp[1], cp[2]);
+
+}
+
+// plus alpha
+void UI_ThemeColor4(int colorid)
+{
+ char *cp;
+
+ cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ glColor4ub(cp[0], cp[1], cp[2], cp[3]);
+
+}
+
+// set the color with offset for shades
+void UI_ThemeColorShade(int colorid, int offset)
+{
+ int r, g, b;
+ char *cp;
+
+ cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ r= offset + (int) cp[0];
+ CLAMP(r, 0, 255);
+ g= offset + (int) cp[1];
+ CLAMP(g, 0, 255);
+ b= offset + (int) cp[2];
+ CLAMP(b, 0, 255);
+ //glColor3ub(r, g, b);
+ glColor4ub(r, g, b, cp[3]);
+}
+void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset)
+{
+ int r, g, b, a;
+ char *cp;
+
+ cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ r= coloffset + (int) cp[0];
+ CLAMP(r, 0, 255);
+ g= coloffset + (int) cp[1];
+ CLAMP(g, 0, 255);
+ b= coloffset + (int) cp[2];
+ CLAMP(b, 0, 255);
+ a= alphaoffset + (int) cp[3];
+ CLAMP(a, 0, 255);
+ glColor4ub(r, g, b, a);
+}
+
+// blend between to theme colors, and set it
+void UI_ThemeColorBlend(int colorid1, int colorid2, float fac)
+{
+ int r, g, b;
+ char *cp1, *cp2;
+
+ cp1= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ cp2= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+
+ if(fac<0.0) fac=0.0; else if(fac>1.0) fac= 1.0;
+ r= floor((1.0-fac)*cp1[0] + fac*cp2[0]);
+ g= floor((1.0-fac)*cp1[1] + fac*cp2[1]);
+ b= floor((1.0-fac)*cp1[2] + fac*cp2[2]);
+
+ glColor3ub(r, g, b);
+}
+
+// blend between to theme colors, shade it, and set it
+void UI_ThemeColorBlendShade(int colorid1, int colorid2, float fac, int offset)
+{
+ int r, g, b;
+ char *cp1, *cp2;
+
+ cp1= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ cp2= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+
+ if(fac<0.0) fac=0.0; else if(fac>1.0) fac= 1.0;
+ r= offset+floor((1.0-fac)*cp1[0] + fac*cp2[0]);
+ g= offset+floor((1.0-fac)*cp1[1] + fac*cp2[1]);
+ b= offset+floor((1.0-fac)*cp1[2] + fac*cp2[2]);
+
+ CLAMP(r, 0, 255);
+ CLAMP(g, 0, 255);
+ CLAMP(b, 0, 255);
+
+ glColor3ub(r, g, b);
+}
+
+// blend between to theme colors, shade it, and set it
+void UI_ThemeColorBlendShadeAlpha(int colorid1, int colorid2, float fac, int offset, int alphaoffset)
+{
+ int r, g, b, a;
+ char *cp1, *cp2;
+
+ cp1= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ cp2= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+
+ if(fac<0.0) fac=0.0; else if(fac>1.0) fac= 1.0;
+ r= offset+floor((1.0-fac)*cp1[0] + fac*cp2[0]);
+ g= offset+floor((1.0-fac)*cp1[1] + fac*cp2[1]);
+ b= offset+floor((1.0-fac)*cp1[2] + fac*cp2[2]);
+ a= alphaoffset+floor((1.0-fac)*cp1[3] + fac*cp2[3]);
+
+ CLAMP(r, 0, 255);
+ CLAMP(g, 0, 255);
+ CLAMP(b, 0, 255);
+ CLAMP(a, 0, 255);
+
+ glColor4ub(r, g, b, a);
+}
+
+
+// get individual values, not scaled
+float UI_GetThemeValuef(int colorid)
+{
+ char *cp;
+
+ cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ return ((float)cp[0]);
+
+}
+
+// get individual values, not scaled
+int UI_GetThemeValue(int colorid)
+{
+ char *cp;
+
+ cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ return ((int) cp[0]);
+
+}
+
+
+// get the color, range 0.0-1.0
+void UI_GetThemeColor3fv(int colorid, float *col)
+{
+ char *cp;
+
+ cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ col[0]= ((float)cp[0])/255.0;
+ col[1]= ((float)cp[1])/255.0;
+ col[2]= ((float)cp[2])/255.0;
+}
+
+// get the color, in char pointer
+void UI_GetThemeColor3ubv(int colorid, char *col)
+{
+ char *cp;
+
+ cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ col[0]= cp[0];
+ col[1]= cp[1];
+ col[2]= cp[2];
+}
+
+// get the color, in char pointer
+void UI_GetThemeColor4ubv(int colorid, char *col)
+{
+ char *cp;
+
+ cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ col[0]= cp[0];
+ col[1]= cp[1];
+ col[2]= cp[2];
+ col[3]= cp[3];
+}
+
+void UI_GetThemeColorType4ubv(int colorid, int spacetype, char *col)
+{
+ char *cp;
+
+ cp= UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
+ col[0]= cp[0];
+ col[1]= cp[1];
+ col[2]= cp[2];
+ col[3]= cp[3];
+}
+
+// blends and shades between two char color pointers
+void UI_ColorPtrBlendShade3ubv(char *cp1, char *cp2, float fac, int offset)
+{
+ int r, g, b;
+
+ if(fac<0.0) fac=0.0; else if(fac>1.0) fac= 1.0;
+ r= offset+floor((1.0-fac)*cp1[0] + fac*cp2[0]);
+ g= offset+floor((1.0-fac)*cp1[1] + fac*cp2[1]);
+ b= offset+floor((1.0-fac)*cp1[2] + fac*cp2[2]);
+
+ r= r<0?0:(r>255?255:r);
+ g= g<0?0:(g>255?255:g);
+ b= b<0?0:(b>255?255:b);
+
+ glColor3ub(r, g, b);
+}
+
+// get a 3 byte color, blended and shaded between two other char color pointers
+void UI_GetColorPtrBlendShade3ubv(char *cp1, char *cp2, char *col, float fac, int offset)
+{
+ int r, g, b;
+
+ if(fac<0.0) fac=0.0; else if(fac>1.0) fac= 1.0;
+ r= offset+floor((1.0-fac)*cp1[0] + fac*cp2[0]);
+ g= offset+floor((1.0-fac)*cp1[1] + fac*cp2[1]);
+ b= offset+floor((1.0-fac)*cp1[2] + fac*cp2[2]);
+
+ r= r<0?0:(r>255?255:r);
+ g= g<0?0:(g>255?255:g);
+ b= b<0?0:(b>255?255:b);
+
+ col[0] = r;
+ col[1] = g;
+ col[2] = b;
+}
+
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
new file mode 100644
index 00000000000..3b503f00fd3
--- /dev/null
+++ b/source/blender/editors/interface/view2d.c
@@ -0,0 +1,1965 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <limits.h>
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view2d_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "WM_api.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "ED_screen.h"
+
+#include "BMF_Api.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "interface_intern.h"
+
+/* *********************************************************************** */
+
+/* helper to allow scrollbars to dynamically hide */
+static int view2d_scroll_mapped(int scroll)
+{
+ if(scroll & V2D_SCROLL_HORIZONTAL_HIDE)
+ scroll &= ~(V2D_SCROLL_HORIZONTAL);
+ if(scroll & V2D_SCROLL_VERTICAL_HIDE)
+ scroll &= ~(V2D_SCROLL_VERTICAL);
+ return scroll;
+}
+
+/* called each time cur changes, to dynamically update masks */
+static void view2d_masks(View2D *v2d)
+{
+ int scroll;
+
+ /* mask - view frame */
+ v2d->mask.xmin= v2d->mask.ymin= 0;
+ v2d->mask.xmax= v2d->winx - 1; /* -1 yes! masks are pixels */
+ v2d->mask.ymax= v2d->winy - 1;
+
+#if 0
+ v2d->scroll &= ~(V2D_SCROLL_HORIZONTAL_HIDE|V2D_SCROLL_VERTICAL_HIDE);
+ /* check size if: */
+ if (v2d->scroll & V2D_SCROLL_HORIZONTAL)
+ if(!(v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL))
+ if (v2d->tot.xmax-v2d->tot.xmin <= v2d->cur.xmax-v2d->cur.xmin)
+ v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
+ if (v2d->scroll & V2D_SCROLL_VERTICAL)
+ if(!(v2d->scroll & V2D_SCROLL_SCALE_VERTICAL))
+ if (v2d->tot.ymax-v2d->tot.ymin <= v2d->cur.ymax-v2d->cur.ymin)
+ v2d->scroll |= V2D_SCROLL_VERTICAL_HIDE;
+#endif
+ scroll= view2d_scroll_mapped(v2d->scroll);
+
+ /* scrollers shrink mask area, but should be based off regionsize
+ * - they can only be on one to two edges of the region they define
+ * - if they overlap, they must not occupy the corners (which are reserved for other widgets)
+ */
+ if (scroll) {
+ /* vertical scroller */
+ if (scroll & V2D_SCROLL_LEFT) {
+ /* on left-hand edge of region */
+ v2d->vert= v2d->mask;
+ v2d->vert.xmax= V2D_SCROLL_WIDTH;
+ v2d->mask.xmin= v2d->vert.xmax + 1;
+ }
+ else if (scroll & V2D_SCROLL_RIGHT) {
+ /* on right-hand edge of region */
+ v2d->vert= v2d->mask;
+ v2d->vert.xmax++; /* one pixel extra... was leaving a minor gap... */
+ v2d->vert.xmin= v2d->vert.xmax - V2D_SCROLL_WIDTH;
+ v2d->mask.xmax= v2d->vert.xmin - 1;
+ }
+
+ /* horizontal scroller */
+ if (scroll & (V2D_SCROLL_BOTTOM|V2D_SCROLL_BOTTOM_O)) {
+ /* on bottom edge of region (V2D_SCROLL_BOTTOM_O is outliner, the other is for standard) */
+ v2d->hor= v2d->mask;
+ v2d->hor.ymax= V2D_SCROLL_HEIGHT;
+ v2d->mask.ymin= v2d->hor.ymax + 1;
+ }
+ else if (scroll & V2D_SCROLL_TOP) {
+ /* on upper edge of region */
+ v2d->hor= v2d->mask;
+ v2d->hor.ymin= v2d->hor.ymax - V2D_SCROLL_HEIGHT;
+ v2d->mask.ymax= v2d->hor.ymin - 1;
+ }
+
+ /* adjust vertical scroller if there's a horizontal scroller, to leave corner free */
+ if (scroll & V2D_SCROLL_VERTICAL) {
+ /* just set y min/max for vertical scroller to y min/max of mask as appropriate */
+ if (scroll & (V2D_SCROLL_BOTTOM|V2D_SCROLL_BOTTOM_O)) {
+ /* on bottom edge of region (V2D_SCROLL_BOTTOM_O is outliner, the other is for standard) */
+ v2d->vert.ymin= v2d->mask.ymin;
+ }
+ else if (scroll & V2D_SCROLL_TOP) {
+ /* on upper edge of region */
+ v2d->vert.ymax= v2d->mask.ymax;
+ }
+ }
+ }
+
+}
+
+/* Refresh and Validation */
+
+/* Initialise all relevant View2D data (including view rects if first time) and/or refresh mask sizes after view resize
+ * - for some of these presets, it is expected that the region will have defined some
+ * additional settings necessary for the customisation of the 2D viewport to its requirements
+ * - this function should only be called from region init() callbacks, where it is expected that
+ * this is called before UI_view2d_size_update(), as this one checks that the rects are properly initialised.
+ */
+void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
+{
+ short tot_changed= 0;
+
+ /* XXX always set state vars for buttonsview, this is hardcoded */
+ switch (type) {
+ /* panels view, with free/horizontal/vertical align */
+ case V2D_COMMONVIEW_PANELS_UI:
+ {
+ /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
+ v2d->keepzoom= (V2D_KEEPASPECT|V2D_KEEPZOOM);
+ v2d->minzoom= 0.5f;
+ v2d->maxzoom= 2.0f;
+
+ v2d->align= (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_POS_Y);
+ v2d->keeptot= V2D_KEEPTOT_BOUNDS;
+ }
+ break;
+ }
+
+
+ /* initialise data if there is a need for such */
+ if ((v2d->flag & V2D_IS_INITIALISED) == 0) {
+ /* set initialised flag so that View2D doesn't get reinitialised next time again */
+ v2d->flag |= V2D_IS_INITIALISED;
+
+ /* see eView2D_CommonViewTypes in UI_view2d.h for available view presets */
+ switch (type) {
+ /* 'standard view' - optimum setup for 'standard' view behaviour, that should be used new views as basis for their
+ * own unique View2D settings, which should be used instead of this in most cases...
+ */
+ case V2D_COMMONVIEW_STANDARD:
+ {
+ /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
+ v2d->keepzoom= (V2D_KEEPASPECT|V2D_KEEPZOOM);
+ v2d->minzoom= 0.01f;
+ v2d->maxzoom= 1000.0f;
+
+ /* tot rect and cur should be same size, and aligned using 'standard' OpenGL coordinates for now
+ * - region can resize 'tot' later to fit other data
+ * - keeptot is only within bounds, as strict locking is not that critical
+ * - view is aligned for (0,0) -> (winx-1, winy-1) setup
+ */
+ v2d->align= (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_NEG_Y);
+ v2d->keeptot= V2D_KEEPTOT_BOUNDS;
+
+ v2d->tot.xmin= v2d->tot.ymin= 0.0f;
+ v2d->tot.xmax= (float)(winx - 1);
+ v2d->tot.ymax= (float)(winy - 1);
+
+ v2d->cur= v2d->tot;
+
+ /* scrollers - should we have these by default? */
+ // XXX for now, we don't override this, or set it either!
+ }
+ break;
+
+ /* 'list/channel view' - zoom, aspect ratio, and alignment restrictions are set here */
+ case V2D_COMMONVIEW_LIST:
+ {
+ /* zoom + aspect ratio are locked */
+ v2d->keepzoom = (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_KEEPZOOM|V2D_KEEPASPECT);
+ v2d->minzoom= v2d->maxzoom= 1.0f;
+
+ /* tot rect has strictly regulated placement, and must only occur in +/- quadrant */
+ v2d->align = (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_POS_Y);
+ v2d->keeptot = V2D_KEEPTOT_STRICT;
+ tot_changed= 1;
+
+ /* scroller settings are currently not set here... that is left for regions... */
+ }
+ break;
+
+ /* 'header' regions - zoom, aspect ratio, alignment, and panning restrictions are set here */
+ case V2D_COMMONVIEW_HEADER:
+ {
+ /* zoom + aspect ratio are locked */
+ v2d->keepzoom = (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_KEEPZOOM|V2D_KEEPASPECT);
+ v2d->minzoom= v2d->maxzoom= 1.0f;
+ v2d->min[0]= v2d->max[0]= (float)(winx-1);
+ v2d->min[1]= v2d->max[1]= (float)(winy-1);
+
+ /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
+ v2d->align = (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_NEG_Y);
+ v2d->keeptot = V2D_KEEPTOT_STRICT;
+ tot_changed= 1;
+
+ /* panning in y-axis is prohibited */
+ v2d->keepofs= V2D_LOCKOFS_Y;
+
+ /* absolutely no scrollers allowed */
+ v2d->scroll= 0;
+
+ /* pixel offsets need to be applied for smooth UI controls */
+ v2d->flag |= (V2D_PIXELOFS_X|V2D_PIXELOFS_Y);
+ }
+ break;
+
+ /* ui listviews, tries to wrap 'tot' inside region width */
+ case V2D_COMMONVIEW_LIST_UI:
+ {
+ /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
+ v2d->keepzoom= (V2D_KEEPASPECT|V2D_KEEPZOOM);
+ v2d->minzoom= 0.5f;
+ v2d->maxzoom= 2.0f;
+
+ v2d->align= (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_POS_Y);
+ v2d->keeptot= V2D_KEEPTOT_BOUNDS;
+
+ v2d->tot.xmin= 0.0f;
+ v2d->tot.xmax= 336.f; // XXX 320 width + 2 x PNL_DIST
+
+ v2d->tot.ymax= 0.0f;
+ v2d->tot.ymin= -336.0f*((float)winy)/(float)winx;
+
+ v2d->cur= v2d->tot;
+ }
+ break;
+
+ /* panels view, with free/horizontal/vertical align */
+ case V2D_COMMONVIEW_PANELS_UI:
+ {
+ /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
+ v2d->keepzoom= (V2D_KEEPASPECT|V2D_KEEPZOOM);
+ v2d->minzoom= 0.5f;
+ v2d->maxzoom= 2.0f;
+
+ v2d->align= (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_POS_Y);
+ v2d->keeptot= V2D_KEEPTOT_BOUNDS;
+
+ v2d->tot.xmin= 0.0f;
+ v2d->tot.xmax= winx;
+
+ v2d->tot.ymax= 0.0f;
+ v2d->tot.ymin= -winy;
+
+ v2d->cur= v2d->tot;
+ }
+ break;
+
+ /* other view types are completely defined using their own settings already */
+ default:
+ /* we don't do anything here, as settings should be fine, but just make sure that rect */
+ break;
+ }
+ }
+
+ /* store view size */
+ v2d->winx= winx;
+ v2d->winy= winy;
+
+ /* set masks */
+ view2d_masks(v2d);
+
+ /* set 'tot' rect before setting cur? */
+ if (tot_changed)
+ UI_view2d_totRect_set(v2d, winx, winy);
+ else
+ UI_view2d_curRect_validate(v2d);
+
+}
+
+/* Ensure View2D rects remain in a viable configuration
+ * - cur is not allowed to be: larger than max, smaller than min, or outside of tot
+ */
+// XXX pre2.5 -> this used to be called test_view2d()
+void UI_view2d_curRect_validate(View2D *v2d)
+{
+ float totwidth, totheight, curwidth, curheight, width, height;
+ float winx, winy;
+ rctf *cur, *tot;
+
+ /* use mask as size of region that View2D resides in, as it takes into account scrollbars already */
+ winx= (float)(v2d->mask.xmax - v2d->mask.xmin + 1);
+ winy= (float)(v2d->mask.ymax - v2d->mask.ymin + 1);
+
+ /* get pointers to rcts for less typing */
+ cur= &v2d->cur;
+ tot= &v2d->tot;
+
+ /* we must satisfy the following constraints (in decreasing order of importance):
+ * - alignment restrictions are respected
+ * - cur must not fall outside of tot
+ * - axis locks (zoom and offset) must be maintained
+ * - zoom must not be excessive (check either sizes or zoom values)
+ * - aspect ratio should be respected (NOTE: this is quite closely realted to zoom too)
+ */
+
+ /* Step 1: if keepzoom, adjust the sizes of the rects only
+ * - firstly, we calculate the sizes of the rects
+ * - curwidth and curheight are saved as reference... modify width and height values here
+ */
+ totwidth= tot->xmax - tot->xmin;
+ totheight= tot->ymax - tot->ymin;
+ curwidth= width= cur->xmax - cur->xmin;
+ curheight= height= cur->ymax - cur->ymin;
+
+ /* if zoom is locked, size on the appropriate axis is reset to mask size */
+ if (v2d->keepzoom & V2D_LOCKZOOM_X)
+ width= winx;
+ if (v2d->keepzoom & V2D_LOCKZOOM_Y)
+ height= winy;
+
+ /* keepzoom (V2D_KEEPZOOM set), indicates that zoom level on each axis must not exceed limits
+ * NOTE: in general, it is not expected that the lock-zoom will be used in conjunction with this
+ */
+ if (v2d->keepzoom & V2D_KEEPZOOM) {
+ float zoom, fac;
+
+ /* check if excessive zoom on x-axis */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) {
+ zoom= winx / width;
+ if ((zoom < v2d->minzoom) || (zoom > v2d->maxzoom)) {
+ fac= (zoom < v2d->minzoom) ? (zoom / v2d->minzoom) : (zoom / v2d->maxzoom);
+ width *= fac;
+ }
+ }
+
+ /* check if excessive zoom on y-axis */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) {
+ zoom= winy / height;
+ if ((zoom < v2d->minzoom) || (zoom > v2d->maxzoom)) {
+ fac= (zoom < v2d->minzoom) ? (zoom / v2d->minzoom) : (zoom / v2d->maxzoom);
+ height *= fac;
+ }
+ }
+ }
+ else {
+ /* make sure sizes don't exceed that of the min/max sizes (even though we're not doing zoom clamping) */
+ CLAMP(width, v2d->min[0], v2d->max[0]);
+ CLAMP(height, v2d->min[1], v2d->max[1]);
+ }
+
+ /* check if we should restore aspect ratio (if view size changed) */
+ if (v2d->keepzoom & V2D_KEEPASPECT) {
+ short do_x=0, do_y=0, do_cur, do_win;
+ float curRatio, winRatio;
+
+ /* when a window edge changes, the aspect ratio can't be used to
+ * find which is the best new 'cur' rect. thats why it stores 'old'
+ */
+ if (winx != v2d->oldwinx) do_x= 1;
+ if (winy != v2d->oldwiny) do_y= 1;
+
+ curRatio= height / width;
+ winRatio= winy / winx;
+
+ /* both sizes change (area/region maximised) */
+ if (do_x == do_y) {
+ if (do_x && do_y) {
+ /* here is 1,1 case, so all others must be 0,0 */
+ if (ABS(winx - v2d->oldwinx) > ABS(winy - v2d->oldwiny)) do_y= 0;
+ else do_x= 0;
+ }
+ else if (winRatio > 1.0f) do_x= 0;
+ else do_x= 1;
+ }
+ do_cur= do_x;
+ do_win= do_y;
+
+ if (do_cur) {
+ if ((v2d->keeptot == V2D_KEEPTOT_STRICT) && (winx != v2d->oldwinx)) {
+ /* special exception for Outliner (and later channel-lists):
+ * - The view may be moved left to avoid contents being pushed out of view when view shrinks.
+ * - The keeptot code will make sure cur->xmin will not be less than tot->xmin (which cannot be allowed)
+ * - width is not adjusted for changed ratios here...
+ */
+ if (winx < v2d->oldwinx) {
+ float temp = v2d->oldwinx - winx;
+
+ cur->xmin -= temp;
+ cur->xmax -= temp;
+
+ /* width does not get modified, as keepaspect here is just set to make
+ * sure visible area adjusts to changing view shape!
+ */
+ }
+ }
+ else {
+ /* portrait window: correct for x */
+ width= height / winRatio;
+ }
+ }
+ else {
+ if ((v2d->keeptot == V2D_KEEPTOT_STRICT) && (winy != v2d->oldwiny)) {
+ /* special exception for Outliner (and later channel-lists):
+ * - Currently, no actions need to be taken here...
+ */
+
+ if (winy < v2d->oldwiny) {
+ float temp = v2d->oldwiny - winy;
+
+ cur->ymin += temp;
+ cur->ymax += temp;
+ }
+
+ }
+ else {
+ /* landscape window: correct for y */
+ height = width * winRatio;
+ }
+ }
+
+ /* store region size for next time */
+ v2d->oldwinx= (short)winx;
+ v2d->oldwiny= (short)winy;
+ }
+
+ /* Step 2: apply new sizes to cur rect, but need to take into account alignment settings here... */
+ if ((width != curwidth) || (height != curheight)) {
+ float temp, dh;
+
+ /* resize from centerpoint */
+ if (width != curwidth) {
+ temp= (cur->xmax + cur->xmin) * 0.5f;
+ dh= width * 0.5f;
+
+ cur->xmin = temp - dh;
+ cur->xmax = temp + dh;
+ }
+ if (height != curheight) {
+ temp= (cur->ymax + cur->ymin) * 0.5f;
+ dh= height * 0.5f;
+
+ cur->ymin = temp - dh;
+ cur->ymax = temp + dh;
+ }
+ }
+
+ /* Step 3: adjust so that it doesn't fall outside of bounds of 'tot' */
+ if (v2d->keeptot) {
+ float temp, diff;
+
+ /* recalculate extents of cur */
+ curwidth= cur->xmax - cur->xmin;
+ curheight= cur->ymax - cur->ymin;
+
+ /* width */
+ if ( (curwidth > totwidth) && !(v2d->keepzoom & (V2D_KEEPZOOM|V2D_LOCKZOOM_X)) ) {
+ /* if zoom doesn't have to be maintained, just clamp edges */
+ if (cur->xmin < tot->xmin) cur->xmin= tot->xmin;
+ if (cur->xmax > tot->xmax) cur->xmax= tot->xmax;
+ }
+ else if (v2d->keeptot == V2D_KEEPTOT_STRICT) {
+ /* This is an exception for the outliner (and later channel-lists, headers)
+ * - must clamp within tot rect (absolutely no excuses)
+ * --> therefore, cur->xmin must not be less than tot->xmin
+ */
+ if (cur->xmin < tot->xmin) {
+ /* move cur across so that it sits at minimum of tot */
+ temp= tot->xmin - cur->xmin;
+
+ cur->xmin += temp;
+ cur->xmax += temp;
+ }
+ else if (cur->xmax > tot->xmax) {
+ /* - only offset by difference of cur-xmax and tot-xmax if that would not move
+ * cur-xmin to lie past tot-xmin
+ * - otherwise, simply shift to tot-xmin???
+ */
+ temp= cur->xmax - tot->xmax;
+
+ if ((cur->xmin - temp) < tot->xmin) {
+ /* only offset by difference from cur-min and tot-min */
+ temp= cur->xmin - tot->xmin;
+
+ cur->xmin -= temp;
+ cur->xmax -= temp;
+ }
+ else {
+ cur->xmin -= temp;
+ cur->xmax -= temp;
+ }
+ }
+ }
+ else {
+ /* This here occurs when:
+ * - width too big, but maintaining zoom (i.e. widths cannot be changed)
+ * - width is OK, but need to check if outside of boundaries
+ *
+ * So, resolution is to just shift view by the gap between the extremities.
+ * We favour moving the 'minimum' across, as that's origin for most things
+ * (XXX - in the past, max was favoured... if there are bugs, swap!)
+ */
+ if ((cur->ymin < tot->ymin) && (cur->ymax > tot->ymax)) {
+ /* outside boundaries on both sides, so take middle-point of tot, and place in balanced way */
+ temp= (tot->ymax + tot->ymin) * 0.5f;
+ diff= curheight * 0.5f;
+
+ cur->ymin= temp - diff;
+ cur->ymax= temp + diff;
+ }
+ else if (cur->xmin < tot->xmin) {
+ /* move cur across so that it sits at minimum of tot */
+ temp= tot->xmin - cur->xmin;
+
+ cur->xmin += temp;
+ cur->xmax += temp;
+ }
+ else if (cur->xmax > tot->xmax) {
+ /* - only offset by difference of cur-xmax and tot-xmax if that would not move
+ * cur-xmin to lie past tot-xmin
+ * - otherwise, simply shift to tot-xmin???
+ */
+ temp= cur->xmax - tot->xmax;
+
+ if ((cur->xmin - temp) < tot->xmin) {
+ /* only offset by difference from cur-min and tot-min */
+ temp= cur->xmin - tot->xmin;
+
+ cur->xmin -= temp;
+ cur->xmax -= temp;
+ }
+ else {
+ cur->xmin -= temp;
+ cur->xmax -= temp;
+ }
+ }
+ }
+
+ /* height */
+ if ( (curheight > totheight) && !(v2d->keepzoom & (V2D_KEEPZOOM|V2D_LOCKZOOM_Y)) ) {
+ /* if zoom doesn't have to be maintained, just clamp edges */
+ if (cur->ymin < tot->ymin) cur->ymin= tot->ymin;
+ if (cur->ymax > tot->ymax) cur->ymax= tot->ymax;
+ }
+ else {
+ /* This here occurs when:
+ * - height too big, but maintaining zoom (i.e. heights cannot be changed)
+ * - height is OK, but need to check if outside of boundaries
+ *
+ * So, resolution is to just shift view by the gap between the extremities.
+ * We favour moving the 'minimum' across, as that's origin for most things
+ */
+ if ((cur->ymin < tot->ymin) && (cur->ymax > tot->ymax)) {
+ /* outside boundaries on both sides, so take middle-point of tot, and place in balanced way */
+ temp= (tot->ymax + tot->ymin) * 0.5f;
+ diff= curheight * 0.5f;
+
+ cur->ymin= temp - diff;
+ cur->ymax= temp + diff;
+ }
+ else if (cur->ymin < tot->ymin) {
+ /* there's still space remaining, so shift up */
+ temp= tot->ymin - cur->ymin;
+
+ cur->ymin += temp;
+ cur->ymax += temp;
+ }
+ else if (cur->ymax > tot->ymax) {
+ /* there's still space remaining, so shift down */
+ temp= cur->ymax - tot->ymax;
+
+ cur->ymin -= temp;
+ cur->ymax -= temp;
+ }
+ }
+ }
+
+ /* Step 4: Make sure alignment restrictions are respected */
+ if (v2d->align) {
+ /* If alignment flags are set (but keeptot is not), they must still be respected, as although
+ * they don't specify any particular bounds to stay within, they do define ranges which are
+ * invalid.
+ *
+ * Here, we only check to make sure that on each axis, the 'cur' rect doesn't stray into these
+ * invalid zones, otherwise we offset.
+ */
+
+ /* handle width - posx and negx flags are mutually exclusive, so watch out */
+ if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
+ /* width is in negative-x half */
+ if (v2d->cur.xmax > 0) {
+ v2d->cur.xmin -= v2d->cur.xmax;
+ v2d->cur.xmax= 0.0f;
+ }
+ }
+ else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
+ /* width is in positive-x half */
+ if (v2d->cur.xmin < 0) {
+ v2d->cur.xmax -= v2d->cur.xmin;
+ v2d->cur.xmin = 0.0f;
+ }
+ }
+
+ /* handle height - posx and negx flags are mutually exclusive, so watch out */
+ if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
+ /* height is in negative-y half */
+ if (v2d->cur.ymax > 0) {
+ v2d->cur.ymin -= v2d->cur.ymax;
+ v2d->cur.ymax = 0.0f;
+ }
+ }
+ else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
+ /* height is in positive-y half */
+ if (v2d->cur.ymin < 0) {
+ v2d->cur.ymax -= v2d->cur.ymin;
+ v2d->cur.ymin = 0.0f;
+ }
+ }
+ }
+
+ /* set masks */
+ view2d_masks(v2d);
+}
+
+/* ------------------ */
+
+/* Called by menus to activate it, or by view2d operators to make sure 'related' views stay in synchrony */
+void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
+{
+ ScrArea *sa;
+ ARegion *ar;
+
+ /* don't continue if no view syncing to be done */
+ if ((v2dcur->flag & (V2D_VIEWSYNC_SCREEN_TIME|V2D_VIEWSYNC_AREA_VERTICAL)) == 0)
+ return;
+
+ /* check if doing within area syncing (i.e. channels/vertical) */
+ if ((v2dcur->flag & V2D_VIEWSYNC_AREA_VERTICAL) && (area)) {
+ for (ar= area->regionbase.first; ar; ar= ar->next) {
+ /* don't operate on self */
+ if (v2dcur != &ar->v2d) {
+ /* only if view has vertical locks enabled */
+ if (ar->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL) {
+ if (flag == V2D_LOCK_COPY) {
+ /* other views with locks on must copy active */
+ ar->v2d.cur.ymin= v2dcur->cur.ymin;
+ ar->v2d.cur.ymax= v2dcur->cur.ymax;
+ }
+ else { /* V2D_LOCK_SET */
+ /* active must copy others */
+ v2dcur->cur.ymin= ar->v2d.cur.ymin;
+ v2dcur->cur.ymax= ar->v2d.cur.ymax;
+ }
+
+ /* region possibly changed, so refresh */
+ ED_region_tag_redraw(ar);
+ }
+ }
+ }
+ }
+
+ /* check if doing whole screen syncing (i.e. time/horizontal) */
+ if ((v2dcur->flag & V2D_VIEWSYNC_SCREEN_TIME) && (screen)) {
+ for (sa= screen->areabase.first; sa; sa= sa->next) {
+ for (ar= sa->regionbase.first; ar; ar= ar->next) {
+ /* don't operate on self */
+ if (v2dcur != &ar->v2d) {
+ /* only if view has horizontal locks enabled */
+ if (ar->v2d.flag & V2D_VIEWSYNC_SCREEN_TIME) {
+ if (flag == V2D_LOCK_COPY) {
+ /* other views with locks on must copy active */
+ ar->v2d.cur.xmin= v2dcur->cur.xmin;
+ ar->v2d.cur.xmax= v2dcur->cur.xmax;
+ }
+ else { /* V2D_LOCK_SET */
+ /* active must copy others */
+ v2dcur->cur.xmin= ar->v2d.cur.xmin;
+ v2dcur->cur.xmax= ar->v2d.cur.xmax;
+ }
+
+ /* region possibly changed, so refresh */
+ ED_region_tag_redraw(ar);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/* Restore 'cur' rect to standard orientation (i.e. optimal maximum view of tot)
+ * This does not take into account if zooming the view on an axis will improve the view (if allowed)
+ */
+void UI_view2d_curRect_reset (View2D *v2d)
+{
+ float width, height;
+
+ /* assume width and height of 'cur' rect by default, should be same size as mask */
+ width= (float)(v2d->mask.xmax - v2d->mask.xmin + 1);
+ height= (float)(v2d->mask.ymax - v2d->mask.ymin + 1);
+
+ /* handle width - posx and negx flags are mutually exclusive, so watch out */
+ if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
+ /* width is in negative-x half */
+ v2d->cur.xmin= (float)-width;
+ v2d->cur.xmax= 0.0f;
+ }
+ else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
+ /* width is in positive-x half */
+ v2d->cur.xmin= 0.0f;
+ v2d->cur.xmax= (float)width;
+ }
+ else {
+ /* width is centered around x==0 */
+ const float dx= (float)width / 2.0f;
+
+ v2d->cur.xmin= -dx;
+ v2d->cur.xmax= dx;
+ }
+
+ /* handle height - posx and negx flags are mutually exclusive, so watch out */
+ if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
+ /* height is in negative-y half */
+ v2d->cur.ymin= (float)-height;
+ v2d->cur.ymax= 0.0f;
+ }
+ else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
+ /* height is in positive-y half */
+ v2d->cur.ymin= 0.0f;
+ v2d->cur.ymax= (float)height;
+ }
+ else {
+ /* height is centered around y==0 */
+ const float dy= (float)height / 2.0f;
+
+ v2d->cur.ymin= -dy;
+ v2d->cur.ymax= dy;
+ }
+}
+
+/* ------------------ */
+
+/* Change the size of the maximum viewable area (i.e. 'tot' rect) */
+void UI_view2d_totRect_set (View2D *v2d, int width, int height)
+{
+ int scroll= view2d_scroll_mapped(v2d->scroll);
+
+ /* don't do anything if either value is 0 */
+ width= abs(width);
+ height= abs(height);
+
+ /* hrumf! */
+ if(scroll & V2D_SCROLL_HORIZONTAL)
+ width -= V2D_SCROLL_WIDTH;
+ if(scroll & V2D_SCROLL_VERTICAL)
+ height -= V2D_SCROLL_HEIGHT;
+
+ if (ELEM3(0, v2d, width, height)) {
+ printf("Error: View2D totRect set exiting: v2d=%p width=%d height=%d \n", v2d, width, height); // XXX temp debug info
+ return;
+ }
+
+ /* handle width - posx and negx flags are mutually exclusive, so watch out */
+ if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
+ /* width is in negative-x half */
+ v2d->tot.xmin= (float)-width;
+ v2d->tot.xmax= 0.0f;
+ }
+ else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
+ /* width is in positive-x half */
+ v2d->tot.xmin= 0.0f;
+ v2d->tot.xmax= (float)width;
+ }
+ else {
+ /* width is centered around x==0 */
+ const float dx= (float)width / 2.0f;
+
+ v2d->tot.xmin= -dx;
+ v2d->tot.xmax= dx;
+ }
+
+ /* handle height - posx and negx flags are mutually exclusive, so watch out */
+ if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
+ /* height is in negative-y half */
+ v2d->tot.ymin= (float)-height;
+ v2d->tot.ymax= 0.0f;
+ }
+ else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
+ /* height is in positive-y half */
+ v2d->tot.ymin= 0.0f;
+ v2d->tot.ymax= (float)height;
+ }
+ else {
+ /* height is centered around y==0 */
+ const float dy= (float)height / 2.0f;
+
+ v2d->tot.ymin= -dy;
+ v2d->tot.ymax= dy;
+ }
+
+ /* make sure that 'cur' rect is in a valid state as a result of these changes */
+ UI_view2d_curRect_validate(v2d);
+}
+
+/* *********************************************************************** */
+/* View Matrix Setup */
+
+/* mapping function to ensure 'cur' draws extended over the area where sliders are */
+static void view2d_map_cur_using_mask(View2D *v2d, rctf *curmasked)
+{
+ *curmasked= v2d->cur;
+
+ if (view2d_scroll_mapped(v2d->scroll)) {
+ float dx= (v2d->cur.xmax-v2d->cur.xmin)/((float)(v2d->mask.xmax-v2d->mask.xmin+1));
+ float dy= (v2d->cur.ymax-v2d->cur.ymin)/((float)(v2d->mask.ymax-v2d->mask.ymin+1));
+
+ if (v2d->mask.xmin != 0)
+ curmasked->xmin -= dx*(float)v2d->mask.xmin;
+ if (v2d->mask.xmax+1 != v2d->winx)
+ curmasked->xmax += dx*(float)(v2d->winx - v2d->mask.xmax-1);
+
+ if (v2d->mask.ymin != 0)
+ curmasked->ymin -= dy*(float)v2d->mask.ymin;
+ if (v2d->mask.ymax+1 != v2d->winy)
+ curmasked->ymax += dy*(float)(v2d->winy - v2d->mask.ymax-1);
+
+ }
+}
+
+/* Set view matrices to use 'cur' rect as viewing frame for View2D drawing */
+void UI_view2d_view_ortho(const bContext *C, View2D *v2d)
+{
+ rctf curmasked;
+ float xofs, yofs;
+
+ /* pixel offsets (-0.375f) are needed to get 1:1 correspondance with pixels for smooth UI drawing,
+ * but only applied where requsted
+ */
+ /* XXX ton: fix this! */
+ xofs= 0.0f; // (v2d->flag & V2D_PIXELOFS_X) ? 0.375f : 0.0f;
+ yofs= 0.0f; // (v2d->flag & V2D_PIXELOFS_Y) ? 0.375f : 0.0f;
+
+ /* apply mask-based adjustments to cur rect (due to scrollers), to eliminate scaling artifacts */
+ view2d_map_cur_using_mask(v2d, &curmasked);
+
+ /* set matrix on all appropriate axes */
+ wmOrtho2(curmasked.xmin-xofs, curmasked.xmax-xofs, curmasked.ymin-yofs, curmasked.ymax-yofs);
+
+ /* XXX is this necessary? */
+ wmLoadIdentity();
+}
+
+/* Set view matrices to only use one axis of 'cur' only
+ * - xaxis = if non-zero, only use cur x-axis, otherwise use cur-yaxis (mostly this will be used for x)
+ */
+void UI_view2d_view_orthoSpecial(const bContext *C, View2D *v2d, short xaxis)
+{
+ ARegion *ar= CTX_wm_region(C);
+ rctf curmasked;
+ float xofs, yofs;
+
+ /* pixel offsets (-0.375f) are needed to get 1:1 correspondance with pixels for smooth UI drawing,
+ * but only applied where requsted
+ */
+ /* XXX temp (ton) */
+ xofs= 0.0f; // (v2d->flag & V2D_PIXELOFS_X) ? 0.375f : 0.0f;
+ yofs= 0.0f; // (v2d->flag & V2D_PIXELOFS_Y) ? 0.375f : 0.0f;
+
+ /* apply mask-based adjustments to cur rect (due to scrollers), to eliminate scaling artifacts */
+ view2d_map_cur_using_mask(v2d, &curmasked);
+
+ /* only set matrix with 'cur' coordinates on relevant axes */
+ if (xaxis)
+ wmOrtho2(curmasked.xmin-xofs, curmasked.xmax-xofs, -yofs, ar->winy-yofs);
+ else
+ wmOrtho2(-xofs, ar->winx-xofs, curmasked.ymin-yofs, curmasked.ymax-yofs);
+
+ /* XXX is this necessary? */
+ wmLoadIdentity();
+}
+
+
+/* Restore view matrices after drawing */
+void UI_view2d_view_restore(const bContext *C)
+{
+ ED_region_pixelspace(CTX_wm_region(C));
+}
+
+/* *********************************************************************** */
+/* Gridlines */
+
+/* minimum pixels per gridstep */
+#define MINGRIDSTEP 35
+
+/* View2DGrid is typedef'd in UI_view2d.h */
+struct View2DGrid {
+ float dx, dy; /* stepsize (in pixels) between gridlines */
+ float startx, starty; /* initial coordinates to start drawing grid from */
+ int powerx, powery; /* step as power of 10 */
+};
+
+/* --------------- */
+
+/* try to write step as a power of 10 */
+static void step_to_grid(float *step, int *power, int unit)
+{
+ const float loga= (float)log10(*step);
+ float rem;
+
+ *power= (int)(loga);
+
+ rem= loga - (*power);
+ rem= (float)pow(10.0, rem);
+
+ if (loga < 0.0f) {
+ if (rem < 0.2f) rem= 0.2f;
+ else if(rem < 0.5f) rem= 0.5f;
+ else rem= 1.0f;
+
+ *step= rem * (float)pow(10.0, (*power));
+
+ /* for frames, we want 1.0 frame intervals only */
+ if (unit == V2D_UNIT_FRAMES) {
+ rem = 1.0f;
+ *step = 1.0f;
+ }
+
+ /* prevents printing 1.0 2.0 3.0 etc */
+ if (rem == 1.0f) (*power)++;
+ }
+ else {
+ if (rem < 2.0f) rem= 2.0f;
+ else if(rem < 5.0f) rem= 5.0f;
+ else rem= 10.0f;
+
+ *step= rem * (float)pow(10.0, (*power));
+
+ (*power)++;
+ /* prevents printing 1.0, 2.0, 3.0, etc. */
+ if (rem == 10.0f) (*power)++;
+ }
+}
+
+/* Intialise settings necessary for drawing gridlines in a 2d-view
+ * - Currently, will return pointer to View2DGrid struct that needs to
+ * be freed with UI_view2d_grid_free()
+ * - Is used for scrollbar drawing too (for units drawing)
+ * - Units + clamping args will be checked, to make sure they are valid values that can be used
+ * so it is very possible that we won't return grid at all!
+ *
+ * - xunits,yunits = V2D_UNIT_* grid steps in seconds or frames
+ * - xclamp,yclamp = V2D_CLAMP_* only show whole-number intervals
+ * - winx = width of region we're drawing to
+ * - winy = height of region we're drawing into
+ */
+View2DGrid *UI_view2d_grid_calc(const bContext *C, View2D *v2d, short xunits, short xclamp, short yunits, short yclamp, int winx, int winy)
+{
+ Scene *scene= CTX_data_scene(C);
+ View2DGrid *grid;
+ float space, pixels, seconddiv;
+ int secondgrid;
+
+ /* check that there are at least some workable args */
+ if (ELEM(V2D_ARG_DUMMY, xunits, xclamp) && ELEM(V2D_ARG_DUMMY, yunits, yclamp))
+ return NULL;
+
+ /* grid here is allocated... */
+ grid= MEM_callocN(sizeof(View2DGrid), "View2DGrid");
+
+ /* rule: gridstep is minimal GRIDSTEP pixels */
+ if (xunits == V2D_UNIT_SECONDS) {
+ secondgrid= 1;
+ seconddiv= (float)(0.01 * FPS);
+ }
+ else {
+ secondgrid= 0;
+ seconddiv= 1.0f;
+ }
+
+ /* calculate x-axis grid scale (only if both args are valid) */
+ if (ELEM(V2D_ARG_DUMMY, xunits, xclamp) == 0) {
+ space= v2d->cur.xmax - v2d->cur.xmin;
+ pixels= (float)(v2d->mask.xmax - v2d->mask.xmin);
+
+ grid->dx= (MINGRIDSTEP * space) / (seconddiv * pixels);
+ step_to_grid(&grid->dx, &grid->powerx, xunits);
+ grid->dx *= seconddiv;
+
+ if (xclamp == V2D_GRID_CLAMP) {
+ if (grid->dx < 0.1f) grid->dx= 0.1f;
+ grid->powerx-= 2;
+ if (grid->powerx < -2) grid->powerx= -2;
+ }
+ }
+
+ /* calculate y-axis grid scale (only if both args are valid) */
+ if (ELEM(V2D_ARG_DUMMY, yunits, yclamp) == 0) {
+ space= v2d->cur.ymax - v2d->cur.ymin;
+ pixels= (float)winy;
+
+ grid->dy= MINGRIDSTEP * space / pixels;
+ step_to_grid(&grid->dy, &grid->powery, yunits);
+
+ if (yclamp == V2D_GRID_CLAMP) {
+ if (grid->dy < 1.0f) grid->dy= 1.0f;
+ if (grid->powery < 1) grid->powery= 1;
+ }
+ }
+
+ /* calculate start position */
+ if (ELEM(V2D_ARG_DUMMY, xunits, xclamp) == 0) {
+ grid->startx= seconddiv*(v2d->cur.xmin/seconddiv - (float)fmod(v2d->cur.xmin/seconddiv, grid->dx/seconddiv));
+ if (v2d->cur.xmin < 0.0f) grid->startx-= grid->dx;
+ }
+ else
+ grid->startx= v2d->cur.xmin;
+
+ if (ELEM(V2D_ARG_DUMMY, yunits, yclamp) == 0) {
+ grid->starty= (v2d->cur.ymin - (float)fmod(v2d->cur.ymin, grid->dy));
+ if (v2d->cur.ymin < 0.0f) grid->starty-= grid->dy;
+ }
+ else
+ grid->starty= v2d->cur.ymin;
+
+ return grid;
+}
+
+/* Draw gridlines in the given 2d-region */
+void UI_view2d_grid_draw(const bContext *C, View2D *v2d, View2DGrid *grid, int flag)
+{
+ float vec1[2], vec2[2];
+ int a, step;
+
+ /* check for grid first, as it may not exist */
+ if (grid == NULL)
+ return;
+
+ /* vertical lines */
+ if (flag & V2D_VERTICAL_LINES) {
+ /* initialise initial settings */
+ vec1[0]= vec2[0]= grid->startx;
+ vec1[1]= grid->starty;
+ vec2[1]= v2d->cur.ymax;
+
+ /* minor gridlines */
+ step= (v2d->mask.xmax - v2d->mask.xmin + 1) / MINGRIDSTEP;
+ UI_ThemeColor(TH_GRID);
+
+ for (a=0; a<step; a++) {
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec1);
+ glVertex2fv(vec2);
+ glEnd();
+
+ vec2[0]= vec1[0]+= grid->dx;
+ }
+
+ /* major gridlines */
+ vec2[0]= vec1[0]-= 0.5f*grid->dx;
+ UI_ThemeColorShade(TH_GRID, 16);
+
+ step++;
+ for (a=0; a<=step; a++) {
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec1);
+ glVertex2fv(vec2);
+ glEnd();
+
+ vec2[0]= vec1[0]-= grid->dx;
+ }
+ }
+
+ /* horizontal lines */
+ if (flag & V2D_HORIZONTAL_LINES) {
+ /* only major gridlines */
+ vec1[1]= vec2[1]= grid->starty;
+ vec1[0]= grid->startx;
+ vec2[0]= v2d->cur.xmax;
+
+ step= (v2d->mask.ymax - v2d->mask.ymin + 1) / MINGRIDSTEP;
+
+ UI_ThemeColor(TH_GRID);
+ for (a=0; a<=step; a++) {
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec1);
+ glVertex2fv(vec2);
+ glEnd();
+
+ vec2[1]= vec1[1]+= grid->dy;
+ }
+
+ /* fine grid lines */
+ vec2[1]= vec1[1]-= 0.5f*grid->dy;
+ step++;
+
+ if (flag & V2D_HORIZONTAL_FINELINES) {
+ UI_ThemeColorShade(TH_GRID, 16);
+ for (a=0; a<step; a++) {
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec1);
+ glVertex2fv(vec2);
+ glEnd();
+
+ vec2[1]= vec1[1]-= grid->dy;
+ }
+ }
+ }
+
+ /* Axes are drawn as darker lines */
+ UI_ThemeColorShade(TH_GRID, -50);
+
+ /* horizontal axis */
+ if (flag & V2D_HORIZONTAL_AXIS) {
+ vec1[0]= v2d->cur.xmin;
+ vec2[0]= v2d->cur.xmax;
+ vec1[1]= vec2[1]= 0.0f;
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec1);
+ glVertex2fv(vec2);
+ glEnd();
+ }
+
+ /* vertical axis */
+ if (flag & V2D_VERTICAL_AXIS) {
+ vec1[1]= v2d->cur.ymin;
+ vec2[1]= v2d->cur.ymax;
+ vec1[0]= vec2[0]= 0.0f;
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec1);
+ glVertex2fv(vec2);
+ glEnd();
+ }
+}
+
+/* Draw a constant grid in given 2d-region */
+void UI_view2d_constant_grid_draw(const bContext *C, View2D *v2d)
+{
+ float start, step= 25.0f;
+
+ UI_ThemeColorShade(TH_BACK, -10);
+
+ start= v2d->cur.xmin - (float)fmod(v2d->cur.xmin, step);
+
+ glBegin(GL_LINES);
+ for(; start<v2d->cur.xmax; start+=step) {
+ glVertex2f(start, v2d->cur.ymin);
+ glVertex2f(start, v2d->cur.ymax);
+ }
+
+ start= v2d->cur.ymin - (float)fmod(v2d->cur.ymin, step);
+ for(; start<v2d->cur.ymax; start+=step) {
+ glVertex2f(v2d->cur.xmin, start);
+ glVertex2f(v2d->cur.xmax, start);
+ }
+
+ /* X and Y axis */
+ UI_ThemeColorShade(TH_BACK, -18);
+ glVertex2f(0.0f, v2d->cur.ymin);
+ glVertex2f(0.0f, v2d->cur.ymax);
+ glVertex2f(v2d->cur.xmin, 0.0f);
+ glVertex2f(v2d->cur.xmax, 0.0f);
+
+ glEnd();
+}
+
+/* free temporary memory used for drawing grid */
+void UI_view2d_grid_free(View2DGrid *grid)
+{
+ /* only free if there's a grid */
+ if (grid)
+ MEM_freeN(grid);
+}
+
+/* *********************************************************************** */
+/* Scrollers */
+
+/* View2DScrollers is typedef'd in UI_view2d.h
+ * WARNING: the start of this struct must not change, as view2d_ops.c uses this too.
+ * For now, we don't need to have a separate (internal) header for structs like this...
+ */
+struct View2DScrollers {
+ /* focus bubbles */
+ int vert_min, vert_max; /* vertical scrollbar */
+ int hor_min, hor_max; /* horizontal scrollbar */
+
+ /* scales */
+ View2DGrid *grid; /* grid for coordinate drawing */
+ short xunits, xclamp; /* units and clamping options for x-axis */
+ short yunits, yclamp; /* units and clamping options for y-axis */
+};
+
+/* Calculate relevant scroller properties */
+View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, short xunits, short xclamp, short yunits, short yclamp)
+{
+ View2DScrollers *scrollers;
+ rcti vert, hor;
+ float fac, totsize, scrollsize;
+ int scroll= view2d_scroll_mapped(v2d->scroll);
+
+ vert= v2d->vert;
+ hor= v2d->hor;
+
+ /* scrollers is allocated here... */
+ scrollers= MEM_callocN(sizeof(View2DScrollers), "View2DScrollers");
+
+ /* scroller 'buttons':
+ * - These should always remain within the visible region of the scrollbar
+ * - They represent the region of 'tot' that is visible in 'cur'
+ */
+
+ /* horizontal scrollers */
+ if (scroll & V2D_SCROLL_HORIZONTAL) {
+ /* scroller 'button' extents */
+ totsize= v2d->tot.xmax - v2d->tot.xmin;
+ scrollsize= (float)(hor.xmax - hor.xmin);
+
+ fac= (v2d->cur.xmin - v2d->tot.xmin) / totsize;
+ scrollers->hor_min= (int)(hor.xmin + (fac * scrollsize));
+
+ fac= (v2d->cur.xmax - v2d->tot.xmin) / totsize;
+ scrollers->hor_max= (int)(hor.xmin + (fac * scrollsize));
+
+ if (scrollers->hor_min > scrollers->hor_max)
+ scrollers->hor_min= scrollers->hor_max;
+ }
+
+ /* vertical scrollers */
+ if (scroll & V2D_SCROLL_VERTICAL) {
+ /* scroller 'button' extents */
+ totsize= v2d->tot.ymax - v2d->tot.ymin;
+ scrollsize= (float)(vert.ymax - vert.ymin);
+
+ fac= (v2d->cur.ymin- v2d->tot.ymin) / totsize;
+ scrollers->vert_min= (int)(vert.ymin + (fac * scrollsize));
+
+ fac= (v2d->cur.ymax - v2d->tot.ymin) / totsize;
+ scrollers->vert_max= (int)(vert.ymin + (fac * scrollsize));
+
+ if (scrollers->vert_min > scrollers->vert_max)
+ scrollers->vert_min= scrollers->vert_max;
+ }
+
+ /* grid markings on scrollbars */
+ if (scroll & (V2D_SCROLL_SCALE_HORIZONTAL|V2D_SCROLL_SCALE_VERTICAL)) {
+ /* store clamping */
+ scrollers->xclamp= xclamp;
+ scrollers->xunits= xunits;
+ scrollers->yclamp= yclamp;
+ scrollers->yunits= yunits;
+
+ scrollers->grid= UI_view2d_grid_calc(C, v2d, xunits, xclamp, yunits, yclamp, (hor.xmax - hor.xmin), (vert.ymax - vert.ymin));
+ }
+
+ /* return scrollers */
+ return scrollers;
+}
+
+/* Print scale marking along a time scrollbar */
+static void scroll_printstr(View2DScrollers *scrollers, Scene *scene, float x, float y, float val, int power, short unit, char dir)
+{
+ int len;
+ char str[32];
+
+ /* adjust the scale unit to work ok */
+ if (dir == 'v') {
+ /* here we bump up the power by factor of 10, as
+ * rotation values (hence 'degrees') are divided by 10 to
+ * be able to show the curves at the same time
+ */
+ if ELEM(unit, V2D_UNIT_DEGREES, V2D_UNIT_TIME) {
+ power += 1;
+ val *= 10;
+ }
+ }
+
+ /* get string to print */
+ if (unit == V2D_UNIT_SECONDS) {
+ /* SMPTE timecode style:
+ * - In general, minutes and seconds should be shown, as most clips will be
+ * within this length. Hours will only be included if relevant.
+ * - Only show frames when zoomed in enough for them to be relevant
+ * (using separator convention of ';' for frames, ala QuickTime).
+ * When showing frames, use slightly different display to avoid confusion with mm:ss format
+ */
+ int hours=0, minutes=0, seconds=0, frames=0;
+ char neg[2]= "";
+
+ /* get values */
+ if (val < 0) {
+ /* correction for negative values */
+ sprintf(neg, "-");
+ val = -val;
+ }
+ if (val >= 3600) {
+ /* hours */
+ /* XXX should we only display a single digit for hours since clips are
+ * VERY UNLIKELY to be more than 1-2 hours max? However, that would
+ * go against conventions...
+ */
+ hours= (int)val / 3600;
+ val= (float)fmod(val, 3600);
+ }
+ if (val >= 60) {
+ /* minutes */
+ minutes= (int)val / 60;
+ val= (float)fmod(val, 60);
+ }
+ if (power <= 0) {
+ /* seconds + frames
+ * Frames are derived from 'fraction' of second. We need to perform some additional rounding
+ * to cope with 'half' frames, etc., which should be fine in most cases
+ */
+ seconds= (int)val;
+ frames= (int)floor( ((val - seconds) * FPS) + 0.5f );
+ }
+ else {
+ /* seconds (with pixel offset) */
+ seconds= (int)floor(val + 0.375f);
+ }
+
+ /* print timecode to temp string buffer */
+ if (power <= 0) {
+ /* include "frames" in display */
+ if (hours) sprintf(str, "%s%02d:%02d:%02d;%02d", neg, hours, minutes, seconds, frames);
+ else if (minutes) sprintf(str, "%s%02d:%02d;%02d", neg, minutes, seconds, frames);
+ else sprintf(str, "%s%d;%02d", neg, seconds, frames);
+ }
+ else {
+ /* don't include 'frames' in display */
+ if (hours) sprintf(str, "%s%02d:%02d:%02d", neg, hours, minutes, seconds);
+ else sprintf(str, "%s%02d:%02d", neg, minutes, seconds);
+ }
+ }
+ else {
+ /* round to whole numbers if power is >= 1 (i.e. scale is coarse) */
+ if (power <= 0) sprintf(str, "%.*f", 1-power, val);
+ else sprintf(str, "%d", (int)floor(val + 0.375f));
+ }
+
+ /* get length of string, and adjust printing location to fit it into the horizontal scrollbar */
+ len= strlen(str);
+ if (dir == 'h') {
+ /* seconds/timecode display has slightly longer strings... */
+ if (unit == V2D_UNIT_SECONDS)
+ x-= 3*len;
+ else
+ x-= 4*len;
+ }
+
+ /* Add degree sympbol to end of string for vertical scrollbar? */
+ if ((dir == 'v') && (unit == V2D_UNIT_DEGREES)) {
+ str[len]= 186;
+ str[len+1]= 0;
+ }
+
+ /* draw it */
+ glRasterPos2f(x, y);
+ BMF_DrawString(G.fonts, str); // XXX check this again when new text-drawing api is done
+}
+
+/* local defines for scrollers drawing */
+ /* radius of scroller 'button' caps */
+#define V2D_SCROLLCAP_RAD 5
+ /* shading factor for scroller 'bar' */
+#define V2D_SCROLLBAR_SHADE 0.1f
+ /* shading factor for scroller 'button' caps */
+#define V2D_SCROLLCAP_SHADE 0.2f
+
+/* Draw scrollbars in the given 2d-region */
+void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *vs)
+{
+ Scene *scene= CTX_data_scene(C);
+ const short darker= -50, dark= -10, light= 20, lighter= 50;
+ rcti vert, hor, corner;
+ int scroll= view2d_scroll_mapped(v2d->scroll);
+
+ /* make copies of rects for less typing */
+ vert= v2d->vert;
+ hor= v2d->hor;
+
+ /* horizontal scrollbar */
+ if (scroll & V2D_SCROLL_HORIZONTAL) {
+ /* scroller backdrop */
+ UI_ThemeColorShade(TH_SHADE1, light);
+ glRecti(hor.xmin, hor.ymin, hor.xmax, hor.ymax);
+
+ /* scroller 'button'
+ * - if view is zoomable in x, draw handles too
+ * - handles are drawn darker
+ * - no slider when view is > total for non-zoomable views
+ * (otherwise, zoomable ones tend to flicker)
+ */
+ if ( (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) ||
+ ((v2d->tot.xmax - v2d->tot.xmin) > (v2d->cur.xmax - v2d->cur.xmin)) )
+ {
+ if (v2d->keepzoom & V2D_LOCKZOOM_X) {
+ /* draw base bar as rounded shape */
+ UI_ThemeColorShade(TH_SHADE1, dark);
+ uiSetRoundBox(15);
+
+ /* check that box is large enough for round drawing */
+ if ((vs->hor_max - vs->hor_min) < (V2D_SCROLLCAP_RAD * 2)) {
+ /* Rounded box still gets drawn at the minimum size limit
+ * This doesn't represent extreme scaling well, but looks nicer...
+ */
+ float mid= 0.5f * (vs->hor_max + vs->hor_min);
+
+ gl_round_box_shade(GL_POLYGON,
+ mid-V2D_SCROLLCAP_RAD, (float)hor.ymin+2,
+ mid+V2D_SCROLLCAP_RAD, (float)hor.ymax-2,
+ V2D_SCROLLCAP_RAD, V2D_SCROLLBAR_SHADE, -V2D_SCROLLBAR_SHADE);
+ }
+ else {
+ /* draw rounded box as per normal */
+ gl_round_box_shade(GL_POLYGON,
+ (float)vs->hor_min, (float)hor.ymin+2,
+ (float)vs->hor_max, (float)hor.ymax-2,
+ V2D_SCROLLCAP_RAD, V2D_SCROLLBAR_SHADE, -V2D_SCROLLBAR_SHADE);
+ }
+ }
+ else {
+ /* base bar drawn as shaded rect */
+ UI_ThemeColorShade(TH_SHADE1, dark);
+ uiSetRoundBox(0);
+ gl_round_box_shade(GL_POLYGON,
+ (float)vs->hor_min, (float)hor.ymin+2,
+ (float)vs->hor_max, (float)hor.ymax-2,
+ V2D_SCROLLCAP_RAD, V2D_SCROLLBAR_SHADE, -V2D_SCROLLBAR_SHADE);
+
+ /* 'minimum' handle */
+ uiSetRoundBox(9);
+ UI_ThemeColorShade(TH_SHADE1, darker);
+
+ gl_round_box_shade(GL_POLYGON,
+ (float)vs->hor_min-V2D_SCROLLER_HANDLE_SIZE, (float)hor.ymin+2,
+ (float)vs->hor_min+V2D_SCROLLER_HANDLE_SIZE, (float)hor.ymax-2,
+ V2D_SCROLLCAP_RAD, V2D_SCROLLCAP_SHADE, -V2D_SCROLLCAP_SHADE);
+
+ /* maximum handle */
+ uiSetRoundBox(6);
+ UI_ThemeColorShade(TH_SHADE1, darker);
+
+ gl_round_box_shade(GL_POLYGON,
+ (float)vs->hor_max-V2D_SCROLLER_HANDLE_SIZE, (float)hor.ymin+2,
+ (float)vs->hor_max+V2D_SCROLLER_HANDLE_SIZE, (float)hor.ymax-2,
+ V2D_SCROLLCAP_RAD, V2D_SCROLLCAP_SHADE, -V2D_SCROLLCAP_SHADE);
+ }
+ }
+
+ /* scale indicators */
+ // XXX will need to update the font drawing when the new stuff comes in
+ if ((scroll & V2D_SCROLL_SCALE_HORIZONTAL) && (vs->grid)) {
+ View2DGrid *grid= vs->grid;
+ float fac, dfac, fac2, val;
+
+ /* the numbers: convert grid->startx and -dx to scroll coordinates
+ * - fac is x-coordinate to draw to
+ * - dfac is gap between scale markings
+ */
+ fac= (grid->startx - v2d->cur.xmin) / (v2d->cur.xmax - v2d->cur.xmin);
+ fac= (float)hor.xmin + fac*(hor.xmax - hor.xmin);
+
+ dfac= (grid->dx) / (v2d->cur.xmax - v2d->cur.xmin);
+ dfac= dfac * (hor.xmax - hor.xmin);
+
+ /* set starting value, and text color */
+ UI_ThemeColor(TH_TEXT);
+ val= grid->startx;
+
+ /* if we're clamping to whole numbers only, make sure entries won't be repeated */
+ if (vs->xclamp == V2D_GRID_CLAMP) {
+ while (grid->dx < 0.9999f) {
+ grid->dx *= 2.0f;
+ dfac *= 2.0f;
+ }
+ }
+ if (vs->xunits == V2D_UNIT_FRAMES)
+ grid->powerx= 1;
+
+ /* draw numbers in the appropriate range */
+ if (dfac > 0.0f) {
+ for (; fac < hor.xmax; fac+=dfac, val+=grid->dx) {
+ switch (vs->xunits) {
+ case V2D_UNIT_FRAMES: /* frames (as whole numbers)*/
+ scroll_printstr(vs, scene, fac, 3.0f+(float)(hor.ymin), val, grid->powerx, V2D_UNIT_FRAMES, 'h');
+ break;
+
+ case V2D_UNIT_FRAMESCALE: /* frames (not always as whole numbers) */
+ scroll_printstr(vs, scene, fac, 3.0f+(float)(hor.ymin), val, grid->powerx, V2D_UNIT_FRAMESCALE, 'h');
+ break;
+
+ case V2D_UNIT_SECONDS: /* seconds */
+ fac2= val/(float)FPS;
+ scroll_printstr(vs, scene, fac, 3.0f+(float)(hor.ymin), fac2, grid->powerx, V2D_UNIT_SECONDS, 'h');
+ break;
+
+ case V2D_UNIT_SECONDSSEQ: /* seconds with special calculations (only used for sequencer only) */
+ {
+ float time;
+
+ fac2= val/(float)FPS;
+ time= (float)floor(fac2);
+ fac2= fac2-time;
+
+ scroll_printstr(vs, scene, fac, 3.0f+(float)(hor.ymin), time+(float)FPS*fac2/100.0f, grid->powerx, V2D_UNIT_SECONDSSEQ, 'h');
+ }
+ break;
+
+ case V2D_UNIT_DEGREES: /* Graph Editor for rotation Drivers */
+ /* HACK: although we're drawing horizontal, we make this draw as 'vertical', just to get degree signs */
+ scroll_printstr(vs, scene, fac, 3.0f+(float)(hor.ymin), val, grid->powerx, V2D_UNIT_DEGREES, 'v');
+ break;
+ }
+ }
+ }
+ }
+
+ /* decoration outer bevel line */
+ UI_ThemeColorShade(TH_SHADE1, lighter);
+ if (scroll & (V2D_SCROLL_BOTTOM|V2D_SCROLL_BOTTOM_O))
+ sdrawline(hor.xmin, hor.ymax, hor.xmax, hor.ymax);
+ else if (scroll & V2D_SCROLL_TOP)
+ sdrawline(hor.xmin, hor.ymin, hor.xmax, hor.ymin);
+ }
+
+ /* vertical scrollbar */
+ if (scroll & V2D_SCROLL_VERTICAL) {
+ /* scroller backdrop */
+ UI_ThemeColorShade(TH_SHADE1, light);
+ glRecti(vert.xmin, vert.ymin, vert.xmax, vert.ymax);
+
+ /* scroller 'button'
+ * - if view is zoomable in y, draw handles too
+ * - handles are drawn darker
+ * - no slider when view is > total for non-zoomable views
+ * (otherwise, zoomable ones tend to flicker)
+ */
+ if ( (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) ||
+ ((v2d->tot.ymax - v2d->tot.ymin) > (v2d->cur.ymax - v2d->cur.ymin)) )
+ {
+ if (v2d->keepzoom & V2D_LOCKZOOM_Y) {
+ /* draw base bar as rounded shape */
+ UI_ThemeColorShade(TH_SHADE1, dark);
+ uiSetRoundBox(15);
+
+ /* check that box is large enough for round drawing */
+ if ((vs->vert_max - vs->vert_min) < (V2D_SCROLLCAP_RAD * 2)) {
+ /* Rounded box still gets drawn at the minimum size limit
+ * This doesn't represent extreme scaling well, but looks nicer...
+ */
+ float mid= 0.5f * (vs->vert_max + vs->vert_min);
+
+ gl_round_box_vertical_shade(GL_POLYGON,
+ (float)vert.xmin+2, mid-V2D_SCROLLCAP_RAD,
+ (float)vert.xmax-2, mid+V2D_SCROLLCAP_RAD,
+ V2D_SCROLLCAP_RAD, V2D_SCROLLBAR_SHADE, -V2D_SCROLLBAR_SHADE);
+ }
+ else {
+ /* draw rounded box as per normal */
+ gl_round_box_vertical_shade(GL_POLYGON,
+ (float)vert.xmin+2, (float)vs->vert_min,
+ (float)vert.xmax-2, (float)vs->vert_max,
+ V2D_SCROLLCAP_RAD, V2D_SCROLLBAR_SHADE, -V2D_SCROLLBAR_SHADE);
+ }
+ }
+ else {
+ /* base bar drawn as shaded rect */
+ UI_ThemeColorShade(TH_SHADE1, dark);
+ uiSetRoundBox(0);
+ gl_round_box_vertical_shade(GL_POLYGON,
+ (float)vert.xmin+2, (float)vs->vert_min,
+ (float)vert.xmax-2, (float)vs->vert_max,
+ V2D_SCROLLCAP_RAD, V2D_SCROLLBAR_SHADE, -V2D_SCROLLBAR_SHADE);
+
+ /* 'minimum' handle */
+ UI_ThemeColorShade(TH_SHADE1, darker);
+ uiSetRoundBox(12);
+
+ gl_round_box_vertical_shade(GL_POLYGON,
+ (float)vert.xmin+2, (float)vs->vert_min-V2D_SCROLLER_HANDLE_SIZE,
+ (float)vert.xmax-2, (float)vs->vert_min+V2D_SCROLLER_HANDLE_SIZE,
+ V2D_SCROLLCAP_RAD, V2D_SCROLLCAP_SHADE, -V2D_SCROLLCAP_SHADE);
+
+ /* maximum handle */
+ UI_ThemeColorShade(TH_SHADE1, darker);
+ uiSetRoundBox(3);
+
+ gl_round_box_vertical_shade(GL_POLYGON,
+ (float)vert.xmin+2, (float)vs->vert_max-V2D_SCROLLER_HANDLE_SIZE,
+ (float)vert.xmax-2, (float)vs->vert_max+V2D_SCROLLER_HANDLE_SIZE,
+ V2D_SCROLLCAP_RAD, V2D_SCROLLCAP_SHADE, -V2D_SCROLLCAP_SHADE);
+ }
+ }
+
+ /* scale indiators */
+ // XXX will need to update the font drawing when the new stuff comes in
+ if ((scroll & V2D_SCROLL_SCALE_VERTICAL) && (vs->grid)) {
+ View2DGrid *grid= vs->grid;
+ float fac, dfac, val;
+
+ /* the numbers: convert grid->starty and dy to scroll coordinates
+ * - fac is y-coordinate to draw to
+ * - dfac is gap between scale markings
+ * - these involve a correction for horizontal scrollbar
+ * NOTE: it's assumed that that scrollbar is there if this is involved!
+ */
+ fac= (grid->starty- v2d->cur.ymin) / (v2d->cur.ymax - v2d->cur.ymin);
+ fac= (vert.ymin + V2D_SCROLL_HEIGHT) + fac*(vert.ymax - vert.ymin - V2D_SCROLL_HEIGHT);
+
+ dfac= (grid->dy) / (v2d->cur.ymax - v2d->cur.ymin);
+ dfac= dfac * (vert.ymax - vert.ymin - V2D_SCROLL_HEIGHT);
+
+ /* set starting value, and text color */
+ UI_ThemeColor(TH_TEXT);
+ val= grid->starty;
+
+ /* if vertical clamping (to whole numbers) is used (i.e. in Sequencer), apply correction */
+ // XXX only relevant to Sequencer, so need to review this when we port that code
+ if (vs->yclamp == V2D_GRID_CLAMP)
+ fac += 0.5f * dfac;
+
+ /* draw vertical steps */
+ if (dfac > 0.0f) {
+ for (; fac < vert.ymax; fac+= dfac, val += grid->dy) {
+ scroll_printstr(vs, scene, (float)(vert.xmax)-14.0f, fac, val, grid->powery, vs->yunits, 'v');
+ }
+ }
+ }
+
+ /* decoration outer bevel line */
+ UI_ThemeColorShade(TH_SHADE1, lighter);
+ if (scroll & V2D_SCROLL_RIGHT)
+ sdrawline(vert.xmin, vert.ymin, vert.xmin, vert.ymax);
+ else if (scroll & V2D_SCROLL_LEFT)
+ sdrawline(vert.xmax, vert.ymin, vert.xmax, vert.ymax);
+ }
+
+ /* draw a 'sunken square' to cover up any overlapping corners resulting from intersection of overflowing scroller data */
+ if ((scroll & V2D_SCROLL_VERTICAL) && (scroll & V2D_SCROLL_HORIZONTAL)) {
+ /* set bounds (these should be right) */
+ corner.xmin= vert.xmin;
+ corner.xmax= vert.xmax;
+ corner.ymin= hor.ymin;
+ corner.ymax= hor.ymax;
+
+ /* firstly, draw using background color to cover up any overlapping junk */
+ UI_ThemeColor(TH_SHADE1);
+ glRecti(corner.xmin, corner.ymin, corner.xmax, corner.ymax);
+
+ /* now, draw suggestive highlighting... */
+ /* first, dark lines on top to suggest scrollers overlap box */
+ UI_ThemeColorShade(TH_SHADE1, darker);
+ sdrawline(corner.xmin, corner.ymin, corner.xmin, corner.ymax);
+ sdrawline(corner.xmin, corner.ymax, corner.xmax, corner.ymax);
+ /* now, light lines on bottom to show box is sunken in */
+ UI_ThemeColorShade(TH_SHADE1, lighter);
+ sdrawline(corner.xmax, corner.ymin, corner.xmax, corner.ymax);
+ sdrawline(corner.xmin, corner.ymin, corner.xmax, corner.ymin);
+ }
+}
+
+/* free temporary memory used for drawing scrollers */
+void UI_view2d_scrollers_free(View2DScrollers *scrollers)
+{
+ /* need to free grid as well... */
+ if (scrollers->grid) MEM_freeN(scrollers->grid);
+ MEM_freeN(scrollers);
+}
+
+/* *********************************************************************** */
+/* List View Utilities */
+
+/* Get the view-coordinates of the nominated cell
+ * - columnwidth, rowheight = size of each 'cell'
+ * - startx, starty = coordinates (in 'tot' rect space) that the list starts from
+ * This should be (0,0) for most views. However, for those where the starting row was offsetted
+ * (like for Animation Editor channel lists, to make the first entry more visible), these will be
+ * the min-coordinates of the first item.
+ * - column, row = the 2d-corodinates (in 2D-view / 'tot' rect space) the cell exists at
+ * - rect = coordinates of the cell (passed as single var instead of 4 separate, as it's more useful this way)
+ */
+void UI_view2d_listview_cell_to_view(View2D *v2d, short columnwidth, short rowheight, float startx, float starty, int column, int row, rctf *rect)
+{
+ /* sanity checks */
+ if ELEM(NULL, v2d, rect)
+ return;
+ if ((columnwidth <= 0) && (rowheight <= 0)) {
+ rect->xmin= rect->xmax= 0.0f;
+ rect->ymin= rect->ymax= 0.0f;
+ return;
+ }
+
+ /* x-coordinates */
+ rect->xmin= startx + (float)(columnwidth * column);
+ rect->xmax= startx + (float)(columnwidth * (column + 1));
+
+ if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
+ /* simply negate the values for the coordinates if in negative half */
+ rect->xmin = -rect->xmin;
+ rect->xmax = -rect->xmax;
+ }
+
+ /* y-coordinates */
+ rect->ymin= starty + (float)(rowheight * row);
+ rect->ymax= starty + (float)(rowheight * (row + 1));
+
+ if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
+ /* simply negate the values for the coordinates if in negative half */
+ rect->ymin = -rect->ymin;
+ rect->ymax = -rect->ymax;
+ }
+}
+
+/* Get the 'cell' (row, column) that the given 2D-view coordinates (i.e. in 'tot' rect space) lie in.
+ * - columnwidth, rowheight = size of each 'cell'
+ * - startx, starty = coordinates (in 'tot' rect space) that the list starts from
+ * This should be (0,0) for most views. However, for those where the starting row was offsetted
+ * (like for Animation Editor channel lists, to make the first entry more visible), these will be
+ * the min-coordinates of the first item.
+ * - viewx, viewy = 2D-coordinates (in 2D-view / 'tot' rect space) to get the cell for
+ * - column, row = the 'coordinates' of the relevant 'cell'
+ */
+void UI_view2d_listview_view_to_cell(View2D *v2d, short columnwidth, short rowheight, float startx, float starty,
+ float viewx, float viewy, int *column, int *row)
+{
+ /* adjust view coordinates to be all positive ints, corrected for the start offset */
+ const int x= (int)(floor(fabs(viewx) + 0.5f) - startx);
+ const int y= (int)(floor(fabs(viewy) + 0.5f) - starty);
+
+ /* sizes must not be negative */
+ if ( (v2d == NULL) || ((columnwidth <= 0) && (rowheight <= 0)) ) {
+ if (column) *column= 0;
+ if (row) *row= 0;
+
+ return;
+ }
+
+ /* get column */
+ if ((column) && (columnwidth > 0))
+ *column= x / columnwidth;
+ else if (column)
+ *column= 0;
+
+ /* get row */
+ if ((row) && (rowheight > 0))
+ *row= y / rowheight;
+ else if (row)
+ *row= 0;
+}
+
+/* Get the 'extreme' (min/max) column and row indices which are visible within the 'cur' rect
+ * - columnwidth, rowheight = size of each 'cell'
+ * - startx, starty = coordinates that the list starts from, which should be (0,0) for most views
+ * - column/row_min/max = the starting and ending column/row indices
+ */
+void UI_view2d_listview_visible_cells(View2D *v2d, short columnwidth, short rowheight, float startx, float starty,
+ int *column_min, int *column_max, int *row_min, int *row_max)
+{
+ /* using 'cur' rect coordinates, call the cell-getting function to get the cells for this */
+ if (v2d) {
+ /* min */
+ UI_view2d_listview_view_to_cell(v2d, columnwidth, rowheight, startx, starty,
+ v2d->cur.xmin, v2d->cur.ymin, column_min, row_min);
+
+ /* max*/
+ UI_view2d_listview_view_to_cell(v2d, columnwidth, rowheight, startx, starty,
+ v2d->cur.xmax, v2d->cur.ymax, column_max, row_max);
+ }
+}
+
+/* *********************************************************************** */
+/* Coordinate Conversions */
+
+/* Convert from screen/region space to 2d-View space
+ *
+ * - x,y = coordinates to convert
+ * - viewx,viewy = resultant coordinates
+ */
+void UI_view2d_region_to_view(View2D *v2d, int x, int y, float *viewx, float *viewy)
+{
+ float div, ofs;
+
+ if (viewx) {
+ div= (float)(v2d->mask.xmax - v2d->mask.xmin);
+ ofs= (float)v2d->mask.xmin;
+
+ *viewx= v2d->cur.xmin + (v2d->cur.xmax-v2d->cur.xmin) * ((float)x - ofs) / div;
+ }
+
+ if (viewy) {
+ div= (float)(v2d->mask.ymax - v2d->mask.ymin);
+ ofs= (float)v2d->mask.ymin;
+
+ *viewy= v2d->cur.ymin + (v2d->cur.ymax - v2d->cur.ymin) * ((float)y - ofs) / div;
+ }
+}
+
+/* Convert from 2d-View space to screen/region space
+ * - Coordinates are clamped to lie within bounds of region
+ *
+ * - x,y = coordinates to convert
+ * - regionx,regiony = resultant coordinates
+ */
+void UI_view2d_view_to_region(View2D *v2d, float x, float y, int *regionx, int *regiony)
+{
+ /* set initial value in case coordinate lies outside of bounds */
+ if (regionx)
+ *regionx= V2D_IS_CLIPPED;
+ if (regiony)
+ *regiony= V2D_IS_CLIPPED;
+
+ /* express given coordinates as proportional values */
+ x= (x - v2d->cur.xmin) / (v2d->cur.xmax - v2d->cur.xmin);
+ y= (y - v2d->cur.ymin) / (v2d->cur.ymax - v2d->cur.ymin);
+
+ /* check if values are within bounds */
+ if ((x>=0.0f) && (x<=1.0f) && (y>=0.0f) && (y<=1.0f)) {
+ if (regionx)
+ *regionx= (int)(v2d->mask.xmin + x*(v2d->mask.xmax-v2d->mask.xmin));
+ if (regiony)
+ *regiony= (int)(v2d->mask.ymin + y*(v2d->mask.ymax-v2d->mask.ymin));
+ }
+}
+
+/* Convert from 2d-view space to screen/region space
+ * - Coordinates are NOT clamped to lie within bounds of region
+ *
+ * - x,y = coordinates to convert
+ * - regionx,regiony = resultant coordinates
+ */
+void UI_view2d_to_region_no_clip(View2D *v2d, float x, float y, int *regionx, int *regiony)
+{
+ /* step 1: express given coordinates as proportional values */
+ x= (x - v2d->cur.xmin) / (v2d->cur.xmax - v2d->cur.xmin);
+ y= (y - v2d->cur.ymin) / (v2d->cur.ymax - v2d->cur.ymin);
+
+ /* step 2: convert proportional distances to screen coordinates */
+ x= v2d->mask.xmin + x*(v2d->mask.xmax - v2d->mask.xmin);
+ y= v2d->mask.ymin + y*(v2d->mask.ymax - v2d->mask.ymin);
+
+ /* although we don't clamp to lie within region bounds, we must avoid exceeding size of ints */
+ if (regionx) {
+ if (x < INT_MIN) *regionx= INT_MIN;
+ else if(x > INT_MAX) *regionx= INT_MAX;
+ else *regionx= (int)x;
+ }
+ if (regiony) {
+ if (y < INT_MIN) *regiony= INT_MIN;
+ else if(y > INT_MAX) *regiony= INT_MAX;
+ else *regiony= (int)y;
+ }
+}
+
+/* *********************************************************************** */
+/* Utilities */
+
+/* View2D data by default resides in region, so get from region stored in context */
+View2D *UI_view2d_fromcontext(const bContext *C)
+{
+ ScrArea *area= CTX_wm_area(C);
+ ARegion *region= CTX_wm_region(C);
+
+ if (area == NULL) return NULL;
+ if (region == NULL) return NULL;
+ return &(region->v2d);
+}
+
+/* same as above, but it returns regionwindow. Utility for pulldowns or buttons */
+View2D *UI_view2d_fromcontext_rwin(const bContext *C)
+{
+ ScrArea *area= CTX_wm_area(C);
+ ARegion *region= CTX_wm_region(C);
+
+ if (area == NULL) return NULL;
+ if (region == NULL) return NULL;
+ if (region->regiontype!=RGN_TYPE_WINDOW) {
+ ARegion *ar= area->regionbase.first;
+ for(; ar; ar= ar->next)
+ if(ar->regiontype==RGN_TYPE_WINDOW)
+ return &(ar->v2d);
+ return NULL;
+ }
+ return &(region->v2d);
+}
+
+
+/* Calculate the scale per-axis of the drawing-area
+ * - Is used to inverse correct drawing of icons, etc. that need to follow view
+ * but not be affected by scale
+ *
+ * - x,y = scale on each axis
+ */
+void UI_view2d_getscale(View2D *v2d, float *x, float *y)
+{
+ if (x) *x = (v2d->mask.xmax - v2d->mask.xmin) / (v2d->cur.xmax - v2d->cur.xmin);
+ if (y) *y = (v2d->mask.ymax - v2d->mask.ymin) / (v2d->cur.ymax - v2d->cur.ymin);
+}
+
+/* Check if mouse is within scrollers
+ * - Returns appropriate code for match
+ * 'h' = in horizontal scroller
+ * 'v' = in vertical scroller
+ * 0 = not in scroller
+ *
+ * - x,y = mouse coordinates in screen (not region) space
+ */
+short UI_view2d_mouse_in_scrollers (const bContext *C, View2D *v2d, int x, int y)
+{
+ ARegion *ar= CTX_wm_region(C);
+ int co[2];
+ int scroll= view2d_scroll_mapped(v2d->scroll);
+
+ /* clamp x,y to region-coordinates first */
+ co[0]= x - ar->winrct.xmin;
+ co[1]= y - ar->winrct.ymin;
+
+ /* check if within scrollbars */
+ if (scroll & V2D_SCROLL_HORIZONTAL) {
+ if (IN_2D_HORIZ_SCROLL(v2d, co)) return 'h';
+ }
+ if (scroll & V2D_SCROLL_VERTICAL) {
+ if (IN_2D_VERT_SCROLL(v2d, co)) return 'v';
+ }
+
+ /* not found */
+ return 0;
+}
+
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
new file mode 100644
index 00000000000..6da9512f9e0
--- /dev/null
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -0,0 +1,1311 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_vec_types.h"
+#include "DNA_view2d_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+
+#include "ED_screen.h"
+
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+
+/* ********************************************************* */
+/* VIEW PANNING OPERATOR */
+
+/* This group of operators come in several forms:
+ * 1) Modal 'dragging' with MMB - where movement of mouse dictates amount to pan view by
+ * 2) Scrollwheel 'steps' - rolling mousewheel by one step moves view by predefined amount
+ *
+ * In order to make sure this works, each operator must define the following RNA-Operator Props:
+ * deltax, deltay - define how much to move view by (relative to zoom-correction factor)
+ */
+
+/* ------------------ Shared 'core' stuff ---------------------- */
+
+/* temp customdata for operator */
+typedef struct v2dViewPanData {
+ bScreen *sc; /* screen where view pan was initiated */
+ ScrArea *sa; /* area where view pan was initiated */
+ View2D *v2d; /* view2d we're operating in */
+
+ float facx, facy; /* amount to move view relative to zoom */
+
+ /* options for version 1 */
+ int startx, starty; /* mouse x/y values in window when operator was initiated */
+ int lastx, lasty; /* previous x/y values of mouse in window */
+
+ short in_scroller; /* for MMB in scrollers (old feature in past, but now not that useful) */
+} v2dViewPanData;
+
+/* initialise panning customdata */
+static int view_pan_init(bContext *C, wmOperator *op)
+{
+ ARegion *ar= CTX_wm_region(C);
+ v2dViewPanData *vpd;
+ View2D *v2d;
+ float winx, winy;
+
+ /* regions now have v2d-data by default, so check for region */
+ if (ar == NULL)
+ return 0;
+
+ /* check if panning is allowed at all */
+ v2d= &ar->v2d;
+ if ((v2d->keepofs & V2D_LOCKOFS_X) && (v2d->keepofs & V2D_LOCKOFS_Y))
+ return 0;
+
+ /* set custom-data for operator */
+ vpd= MEM_callocN(sizeof(v2dViewPanData), "v2dViewPanData");
+ op->customdata= vpd;
+
+ /* set pointers to owners */
+ vpd->sc= CTX_wm_screen(C);
+ vpd->sa= CTX_wm_area(C);
+ vpd->v2d= v2d;
+
+ /* calculate translation factor - based on size of view */
+ winx= (float)(ar->winrct.xmax - ar->winrct.xmin);
+ winy= (float)(ar->winrct.ymax - ar->winrct.ymin);
+ vpd->facx= (v2d->cur.xmax - v2d->cur.xmin) / winx;
+ vpd->facy= (v2d->cur.ymax - v2d->cur.ymin) / winy;
+
+ return 1;
+}
+
+/* apply transform to view (i.e. adjust 'cur' rect) */
+static void view_pan_apply(bContext *C, wmOperator *op)
+{
+ v2dViewPanData *vpd= op->customdata;
+ View2D *v2d= vpd->v2d;
+ float dx, dy;
+
+ /* calculate amount to move view by */
+ dx= vpd->facx * (float)RNA_int_get(op->ptr, "deltax");
+ dy= vpd->facy * (float)RNA_int_get(op->ptr, "deltay");
+
+ /* only move view on an axis if change is allowed */
+ if ((v2d->keepofs & V2D_LOCKOFS_X)==0) {
+ v2d->cur.xmin += dx;
+ v2d->cur.xmax += dx;
+ }
+ if ((v2d->keepofs & V2D_LOCKOFS_Y)==0) {
+ v2d->cur.ymin += dy;
+ v2d->cur.ymax += dy;
+ }
+
+ /* validate that view is in valid configuration after this operation */
+ UI_view2d_curRect_validate(v2d);
+
+ /* request updates to be done... */
+ ED_area_tag_redraw(vpd->sa);
+ UI_view2d_sync(vpd->sc, vpd->sa, v2d, V2D_LOCK_COPY);
+}
+
+/* cleanup temp customdata */
+static void view_pan_exit(bContext *C, wmOperator *op)
+{
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ op->customdata= NULL;
+ }
+}
+
+/* ------------------ Modal Drag Version (1) ---------------------- */
+
+/* for 'redo' only, with no user input */
+static int view_pan_exec(bContext *C, wmOperator *op)
+{
+ if (!view_pan_init(C, op))
+ return OPERATOR_CANCELLED;
+
+ view_pan_apply(C, op);
+ view_pan_exit(C, op);
+ return OPERATOR_FINISHED;
+}
+
+/* set up modal operator and relevant settings */
+static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ wmWindow *window= CTX_wm_window(C);
+ v2dViewPanData *vpd;
+ View2D *v2d;
+
+ /* set up customdata */
+ if (!view_pan_init(C, op))
+ return OPERATOR_PASS_THROUGH;
+
+ vpd= op->customdata;
+ v2d= vpd->v2d;
+
+ /* set initial settings */
+ vpd->startx= vpd->lastx= event->x;
+ vpd->starty= vpd->lasty= event->y;
+ RNA_int_set(op->ptr, "deltax", 0);
+ RNA_int_set(op->ptr, "deltay", 0);
+
+ if (v2d->keepofs & V2D_LOCKOFS_X)
+ WM_cursor_modal(window, BC_NS_SCROLLCURSOR);
+ else if (v2d->keepofs & V2D_LOCKOFS_Y)
+ WM_cursor_modal(window, BC_EW_SCROLLCURSOR);
+ else
+ WM_cursor_modal(window, BC_NSEW_SCROLLCURSOR);
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, &window->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* handle user input - calculations of mouse-movement need to be done here, not in the apply callback! */
+static int view_pan_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ v2dViewPanData *vpd= op->customdata;
+
+ /* execute the events */
+ switch (event->type) {
+ case MOUSEMOVE:
+ {
+ /* calculate new delta transform, then store mouse-coordinates for next-time */
+ RNA_int_set(op->ptr, "deltax", (vpd->lastx - event->x));
+ RNA_int_set(op->ptr, "deltay", (vpd->lasty - event->y));
+
+ vpd->lastx= event->x;
+ vpd->lasty= event->y;
+
+ view_pan_apply(C, op);
+ }
+ break;
+
+ case MIDDLEMOUSE:
+ if (event->val==0) {
+ /* calculate overall delta mouse-movement for redo */
+ RNA_int_set(op->ptr, "deltax", (vpd->startx - vpd->lastx));
+ RNA_int_set(op->ptr, "deltay", (vpd->starty - vpd->lasty));
+
+ view_pan_exit(C, op);
+ WM_cursor_restore(CTX_wm_window(C));
+
+ return OPERATOR_FINISHED;
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void VIEW2D_OT_pan(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Pan View";
+ ot->idname= "VIEW2D_OT_pan";
+
+ /* api callbacks */
+ ot->exec= view_pan_exec;
+ ot->invoke= view_pan_invoke;
+ ot->modal= view_pan_modal;
+
+ /* operator is repeatable */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* rna - must keep these in sync with the other operators */
+ RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
+}
+
+/* ------------------ Scrollwheel Versions (2) ---------------------- */
+
+/* this operator only needs this single callback, where it callsthe view_pan_*() methods */
+static int view_scrollright_exec(bContext *C, wmOperator *op)
+{
+ v2dViewPanData *vpd;
+
+ /* initialise default settings (and validate if ok to run) */
+ if (!view_pan_init(C, op))
+ return OPERATOR_PASS_THROUGH;
+
+ /* also, check if can pan in horizontal axis */
+ vpd= op->customdata;
+ if (vpd->v2d->keepofs & V2D_LOCKOFS_X) {
+ view_pan_exit(C, op);
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* set RNA-Props - only movement in positive x-direction */
+ RNA_int_set(op->ptr, "deltax", 20);
+ RNA_int_set(op->ptr, "deltay", 0);
+
+ /* apply movement, then we're done */
+ view_pan_apply(C, op);
+ view_pan_exit(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW2D_OT_scroll_right(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Scroll Right";
+ ot->idname= "VIEW2D_OT_scroll_right";
+
+ /* api callbacks */
+ ot->exec= view_scrollright_exec;
+
+ /* operator is repeatable */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* rna - must keep these in sync with the other operators */
+ RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
+}
+
+
+
+/* this operator only needs this single callback, where it callsthe view_pan_*() methods */
+static int view_scrollleft_exec(bContext *C, wmOperator *op)
+{
+ v2dViewPanData *vpd;
+
+ /* initialise default settings (and validate if ok to run) */
+ if (!view_pan_init(C, op))
+ return OPERATOR_PASS_THROUGH;
+
+ /* also, check if can pan in horizontal axis */
+ vpd= op->customdata;
+ if (vpd->v2d->keepofs & V2D_LOCKOFS_X) {
+ view_pan_exit(C, op);
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* set RNA-Props - only movement in negative x-direction */
+ RNA_int_set(op->ptr, "deltax", -20);
+ RNA_int_set(op->ptr, "deltay", 0);
+
+ /* apply movement, then we're done */
+ view_pan_apply(C, op);
+ view_pan_exit(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW2D_OT_scroll_left(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Scroll Left";
+ ot->idname= "VIEW2D_OT_scroll_left";
+
+ /* api callbacks */
+ ot->exec= view_scrollleft_exec;
+
+ /* operator is repeatable */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* rna - must keep these in sync with the other operators */
+ RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
+}
+
+
+/* this operator only needs this single callback, where it callsthe view_pan_*() methods */
+static int view_scrolldown_exec(bContext *C, wmOperator *op)
+{
+ v2dViewPanData *vpd;
+
+ /* initialise default settings (and validate if ok to run) */
+ if (!view_pan_init(C, op))
+ return OPERATOR_PASS_THROUGH;
+
+ /* also, check if can pan in vertical axis */
+ vpd= op->customdata;
+ if (vpd->v2d->keepofs & V2D_LOCKOFS_Y) {
+ view_pan_exit(C, op);
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* set RNA-Props */
+ RNA_int_set(op->ptr, "deltax", 0);
+ RNA_int_set(op->ptr, "deltay", -20);
+
+ /* apply movement, then we're done */
+ view_pan_apply(C, op);
+ view_pan_exit(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW2D_OT_scroll_down(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Scroll Down";
+ ot->idname= "VIEW2D_OT_scroll_down";
+
+ /* api callbacks */
+ ot->exec= view_scrolldown_exec;
+
+ /* operator is repeatable */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* rna - must keep these in sync with the other operators */
+ RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
+}
+
+
+
+/* this operator only needs this single callback, where it callsthe view_pan_*() methods */
+static int view_scrollup_exec(bContext *C, wmOperator *op)
+{
+ v2dViewPanData *vpd;
+
+ /* initialise default settings (and validate if ok to run) */
+ if (!view_pan_init(C, op))
+ return OPERATOR_PASS_THROUGH;
+
+ /* also, check if can pan in vertical axis */
+ vpd= op->customdata;
+ if (vpd->v2d->keepofs & V2D_LOCKOFS_Y) {
+ view_pan_exit(C, op);
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* set RNA-Props */
+ RNA_int_set(op->ptr, "deltax", 0);
+ RNA_int_set(op->ptr, "deltay", 20);
+
+ /* apply movement, then we're done */
+ view_pan_apply(C, op);
+ view_pan_exit(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW2D_OT_scroll_up(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Scroll Up";
+ ot->idname= "VIEW2D_OT_scroll_up";
+
+ /* api callbacks */
+ ot->exec= view_scrollup_exec;
+
+ /* operator is repeatable */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* rna - must keep these in sync with the other operators */
+ RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
+}
+
+/* ********************************************************* */
+/* SINGLE-STEP VIEW ZOOMING OPERATOR */
+
+/* This group of operators come in several forms:
+ * 1) Scrollwheel 'steps' - rolling mousewheel by one step zooms view by predefined amount
+ * 2) Scrollwheel 'steps' + alt + ctrl/shift - zooms view on one axis only (ctrl=x, shift=y) // XXX this could be implemented...
+ * 3) Pad +/- Keys - pressing each key moves the zooms the view by a predefined amount
+ *
+ * In order to make sure this works, each operator must define the following RNA-Operator Props:
+ * zoomfacx, zoomfacy - These two zoom factors allow for non-uniform scaling.
+ * It is safe to scale by 0, as these factors are used to determine
+ * amount to enlarge 'cur' by
+ */
+
+/* ------------------ 'Shared' stuff ------------------------ */
+
+/* check if step-zoom can be applied */
+static short view_zoomstep_ok(bContext *C)
+{
+ ARegion *ar= CTX_wm_region(C);
+ View2D *v2d;
+
+ /* check if there's a region in context to work with */
+ if (ar == NULL)
+ return 0;
+ v2d= &ar->v2d;
+
+ /* check that 2d-view is zoomable */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) && (v2d->keepzoom & V2D_LOCKZOOM_Y))
+ return 0;
+
+ /* view is zoomable */
+ return 1;
+}
+
+/* apply transform to view (i.e. adjust 'cur' rect) */
+static void view_zoomstep_apply(bContext *C, wmOperator *op)
+{
+ ARegion *ar= CTX_wm_region(C);
+ View2D *v2d= &ar->v2d;
+ float dx, dy;
+
+ /* calculate amount to move view by */
+ dx= (v2d->cur.xmax - v2d->cur.xmin) * (float)RNA_float_get(op->ptr, "zoomfacx");
+ dy= (v2d->cur.ymax - v2d->cur.ymin) * (float)RNA_float_get(op->ptr, "zoomfacy");
+
+ /* only resize view on an axis if change is allowed */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) {
+ v2d->cur.xmin += dx;
+ v2d->cur.xmax -= dx;
+ }
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) {
+ v2d->cur.ymin += dy;
+ v2d->cur.ymax -= dy;
+ }
+
+ /* validate that view is in valid configuration after this operation */
+ UI_view2d_curRect_validate(v2d);
+
+ /* request updates to be done... */
+ ED_area_tag_redraw(CTX_wm_area(C));
+ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
+}
+
+/* --------------- Individual Operators ------------------- */
+
+/* this operator only needs this single callback, where it calls the view_zoom_*() methods */
+static int view_zoomin_exec(bContext *C, wmOperator *op)
+{
+ /* check that there's an active region, as View2D data resides there */
+ if (!view_zoomstep_ok(C))
+ return OPERATOR_PASS_THROUGH;
+
+ /* set RNA-Props - zooming in by uniform factor */
+ RNA_float_set(op->ptr, "zoomfacx", 0.0375f);
+ RNA_float_set(op->ptr, "zoomfacy", 0.0375f);
+
+ /* apply movement, then we're done */
+ view_zoomstep_apply(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW2D_OT_zoom_in(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Zoom In";
+ ot->idname= "VIEW2D_OT_zoom_in";
+
+ /* api callbacks */
+ ot->exec= view_zoomin_exec;
+
+ /* operator is repeatable */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* rna - must keep these in sync with the other operators */
+ RNA_def_float(ot->srna, "zoomfacx", 0, -FLT_MAX, FLT_MAX, "Zoom Factor X", "", -FLT_MAX, FLT_MAX);
+ RNA_def_float(ot->srna, "zoomfacy", 0, -FLT_MAX, FLT_MAX, "Zoom Factor Y", "", -FLT_MAX, FLT_MAX);
+}
+
+
+
+/* this operator only needs this single callback, where it callsthe view_zoom_*() methods */
+static int view_zoomout_exec(bContext *C, wmOperator *op)
+{
+ /* check that there's an active region, as View2D data resides there */
+ if (!view_zoomstep_ok(C))
+ return OPERATOR_PASS_THROUGH;
+
+ /* set RNA-Props - zooming in by uniform factor */
+ RNA_float_set(op->ptr, "zoomfacx", -0.0375f);
+ RNA_float_set(op->ptr, "zoomfacy", -0.0375f);
+
+ /* apply movement, then we're done */
+ view_zoomstep_apply(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW2D_OT_zoom_out(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Zoom Out";
+ ot->idname= "VIEW2D_OT_zoom_out";
+
+ /* api callbacks */
+ ot->exec= view_zoomout_exec;
+
+ /* operator is repeatable */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* rna - must keep these in sync with the other operators */
+ RNA_def_float(ot->srna, "zoomfacx", 0, -FLT_MAX, FLT_MAX, "Zoom Factor X", "", -FLT_MAX, FLT_MAX);
+ RNA_def_float(ot->srna, "zoomfacy", 0, -FLT_MAX, FLT_MAX, "Zoom Factor Y", "", -FLT_MAX, FLT_MAX);
+}
+
+/* ********************************************************* */
+/* DRAG-ZOOM OPERATOR */
+
+/* MMB Drag - allows non-uniform scaling by dragging mouse
+ *
+ * In order to make sure this works, each operator must define the following RNA-Operator Props:
+ * deltax, deltay - amounts to add to each side of the 'cur' rect
+ */
+
+/* ------------------ Shared 'core' stuff ---------------------- */
+
+/* temp customdata for operator */
+typedef struct v2dViewZoomData {
+ View2D *v2d; /* view2d we're operating in */
+
+ int lastx, lasty; /* previous x/y values of mouse in window */
+ float dx, dy; /* running tally of previous delta values (for obtaining final zoom) */
+} v2dViewZoomData;
+
+/* initialise panning customdata */
+static int view_zoomdrag_init(bContext *C, wmOperator *op)
+{
+ ARegion *ar= CTX_wm_region(C);
+ v2dViewZoomData *vzd;
+ View2D *v2d;
+
+ /* regions now have v2d-data by default, so check for region */
+ if (ar == NULL)
+ return 0;
+ v2d= &ar->v2d;
+
+ /* check that 2d-view is zoomable */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) && (v2d->keepzoom & V2D_LOCKZOOM_Y))
+ return 0;
+
+ /* set custom-data for operator */
+ vzd= MEM_callocN(sizeof(v2dViewZoomData), "v2dViewZoomData");
+ op->customdata= vzd;
+
+ /* set pointers to owners */
+ vzd->v2d= v2d;
+
+ return 1;
+}
+
+/* apply transform to view (i.e. adjust 'cur' rect) */
+static void view_zoomdrag_apply(bContext *C, wmOperator *op)
+{
+ v2dViewZoomData *vzd= op->customdata;
+ View2D *v2d= vzd->v2d;
+ float dx, dy;
+
+ /* get amount to move view by */
+ dx= RNA_float_get(op->ptr, "deltax");
+ dy= RNA_float_get(op->ptr, "deltay");
+
+ /* only move view on an axis if change is allowed */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) {
+ v2d->cur.xmin += dx;
+ v2d->cur.xmax -= dx;
+ }
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) {
+ v2d->cur.ymin += dy;
+ v2d->cur.ymax -= dy;
+ }
+
+ /* validate that view is in valid configuration after this operation */
+ UI_view2d_curRect_validate(v2d);
+
+ /* request updates to be done... */
+ ED_area_tag_redraw(CTX_wm_area(C));
+ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
+}
+
+/* cleanup temp customdata */
+static void view_zoomdrag_exit(bContext *C, wmOperator *op)
+{
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ op->customdata= NULL;
+ }
+}
+
+/* for 'redo' only, with no user input */
+static int view_zoomdrag_exec(bContext *C, wmOperator *op)
+{
+ if (!view_zoomdrag_init(C, op))
+ return OPERATOR_PASS_THROUGH;
+
+ view_zoomdrag_apply(C, op);
+ view_zoomdrag_exit(C, op);
+ return OPERATOR_FINISHED;
+}
+
+/* set up modal operator and relevant settings */
+static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ wmWindow *window= CTX_wm_window(C);
+ v2dViewZoomData *vzd;
+ View2D *v2d;
+
+ /* set up customdata */
+ if (!view_zoomdrag_init(C, op))
+ return OPERATOR_PASS_THROUGH;
+
+ vzd= op->customdata;
+ v2d= vzd->v2d;
+
+ /* set initial settings */
+ vzd->lastx= event->x;
+ vzd->lasty= event->y;
+ RNA_float_set(op->ptr, "deltax", 0);
+ RNA_float_set(op->ptr, "deltay", 0);
+
+ if (v2d->keepofs & V2D_LOCKOFS_X)
+ WM_cursor_modal(window, BC_NS_SCROLLCURSOR);
+ else if (v2d->keepofs & V2D_LOCKOFS_Y)
+ WM_cursor_modal(window, BC_EW_SCROLLCURSOR);
+ else
+ WM_cursor_modal(window, BC_NSEW_SCROLLCURSOR);
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, &window->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* handle user input - calculations of mouse-movement need to be done here, not in the apply callback! */
+static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ v2dViewZoomData *vzd= op->customdata;
+ View2D *v2d= vzd->v2d;
+
+ /* execute the events */
+ switch (event->type) {
+ case MOUSEMOVE:
+ {
+ float dx, dy;
+
+ /* calculate new delta transform, based on zooming mode */
+ if (U.viewzoom == USER_ZOOM_SCALE) {
+ /* 'scale' zooming */
+ float dist;
+
+ /* x-axis transform */
+ dist = (v2d->mask.xmax - v2d->mask.xmin) / 2.0f;
+ dx= 1.0f - ((float)fabs(vzd->lastx - dist) + 2.0f) / ((float)fabs(event->x - dist) + 2.0f);
+ dx*= 0.5f * (v2d->cur.xmax - v2d->cur.xmin);
+
+ /* y-axis transform */
+ dist = (v2d->mask.ymax - v2d->mask.ymin) / 2.0f;
+ dy= 1.0f - ((float)fabs(vzd->lasty - dist) + 2.0f) / ((float)fabs(event->y - dist) + 2.0f);
+ dy*= 0.5f * (v2d->cur.ymax - v2d->cur.ymin);
+ }
+ else {
+ /* 'continuous' or 'dolly' */
+ float fac;
+
+ /* x-axis transform */
+ fac= 0.01f * (event->x - vzd->lastx);
+ dx= fac * (v2d->cur.xmax - v2d->cur.xmin);
+
+ /* y-axis transform */
+ fac= 0.01f * (event->y - vzd->lasty);
+ dy= fac * (v2d->cur.ymax - v2d->cur.ymin);
+
+ /* continous zoom shouldn't move that fast... */
+ if (U.viewzoom == USER_ZOOM_CONT) { // XXX store this setting as RNA prop?
+ dx /= 20.0f;
+ dy /= 20.0f;
+ }
+ }
+
+ /* set transform amount, and add current deltas to stored total delta (for redo) */
+ RNA_float_set(op->ptr, "deltax", dx);
+ RNA_float_set(op->ptr, "deltay", dy);
+ vzd->dx += dx;
+ vzd->dy += dy;
+
+ /* store mouse coordinates for next time, if not doing continuous zoom
+ * - continuous zoom only depends on distance of mouse to starting point to determine rate of change
+ */
+ if (U.viewzoom != USER_ZOOM_CONT) { // XXX store this setting as RNA prop?
+ vzd->lastx= event->x;
+ vzd->lasty= event->y;
+ }
+
+ /* apply zooming */
+ view_zoomdrag_apply(C, op);
+ }
+ break;
+
+ case MIDDLEMOUSE:
+ if (event->val==0) {
+ /* for redo, store the overall deltas - need to respect zoom-locks here... */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0)
+ RNA_float_set(op->ptr, "deltax", vzd->dx);
+ else
+ RNA_float_set(op->ptr, "deltax", 0);
+
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0)
+ RNA_float_set(op->ptr, "deltay", vzd->dy);
+ else
+ RNA_float_set(op->ptr, "deltay", 0);
+
+ /* free customdata */
+ view_zoomdrag_exit(C, op);
+ WM_cursor_restore(CTX_wm_window(C));
+
+ return OPERATOR_FINISHED;
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void VIEW2D_OT_zoom(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Zoom View";
+ ot->idname= "VIEW2D_OT_zoom";
+
+ /* api callbacks */
+ ot->exec= view_zoomdrag_exec;
+ ot->invoke= view_zoomdrag_invoke;
+ ot->modal= view_zoomdrag_modal;
+
+ /* operator is repeatable */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* rna - must keep these in sync with the other operators */
+ RNA_def_float(ot->srna, "deltax", 0, -FLT_MAX, FLT_MAX, "Delta X", "", -FLT_MAX, FLT_MAX);
+ RNA_def_float(ot->srna, "deltay", 0, -FLT_MAX, FLT_MAX, "Delta Y", "", -FLT_MAX, FLT_MAX);
+}
+
+/* ********************************************************* */
+/* BORDER-ZOOM */
+
+/* The user defines a rect using standard borderselect tools, and we use this rect to
+ * define the new zoom-level of the view in the following ways:
+ * 1) LEFTMOUSE - zoom in to view
+ * 2) RIGHTMOUSE - zoom out of view
+ *
+ * Currently, these key mappings are hardcoded, but it shouldn't be too important to
+ * have custom keymappings for this...
+ */
+
+static int view_borderzoom_exec(bContext *C, wmOperator *op)
+{
+ ARegion *ar= CTX_wm_region(C);
+ View2D *v2d= &ar->v2d;
+ rctf rect;
+ int event_type;
+
+ /* convert coordinates of rect to 'tot' rect coordinates */
+ UI_view2d_region_to_view(v2d, RNA_int_get(op->ptr, "xmin"), RNA_int_get(op->ptr, "ymin"), &rect.xmin, &rect.ymin);
+ UI_view2d_region_to_view(v2d, RNA_int_get(op->ptr, "xmax"), RNA_int_get(op->ptr, "ymax"), &rect.xmax, &rect.ymax);
+
+ /* check if zooming in/out view */
+ // XXX hardcoded for now!
+ event_type= RNA_int_get(op->ptr, "event_type");
+
+ if (event_type == LEFTMOUSE) {
+ /* zoom in:
+ * - 'cur' rect will be defined by the coordinates of the border region
+ * - just set the 'cur' rect to have the same coordinates as the border region
+ * if zoom is allowed to be changed
+ */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) {
+ v2d->cur.xmin= rect.xmin;
+ v2d->cur.xmax= rect.xmax;
+ }
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) {
+ v2d->cur.ymin= rect.ymin;
+ v2d->cur.ymax= rect.ymax;
+ }
+ }
+ else {
+ /* zoom out:
+ * - the current 'cur' rect coordinates are going to end upwhere the 'rect' ones are,
+ * but the 'cur' rect coordinates will need to be adjusted to take in more of the view
+ * - calculate zoom factor, and adjust using center-point
+ */
+ float zoom, center, size;
+
+ // TODO: is this zoom factor calculation valid? It seems to produce same results everytime...
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) {
+ size= (v2d->cur.xmax - v2d->cur.xmin);
+ zoom= size / (rect.xmax - rect.xmin);
+ center= (v2d->cur.xmax + v2d->cur.xmin) * 0.5f;
+
+ v2d->cur.xmin= center - (size * zoom);
+ v2d->cur.xmax= center + (size * zoom);
+ }
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) {
+ size= (v2d->cur.ymax - v2d->cur.ymin);
+ zoom= size / (rect.ymax - rect.ymin);
+ center= (v2d->cur.ymax + v2d->cur.ymin) * 0.5f;
+
+ v2d->cur.ymin= center - (size * zoom);
+ v2d->cur.ymax= center + (size * zoom);
+ }
+ }
+
+ /* validate that view is in valid configuration after this operation */
+ UI_view2d_curRect_validate(v2d);
+
+ /* request updates to be done... */
+ ED_area_tag_redraw(CTX_wm_area(C));
+ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW2D_OT_zoom_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Zoom to Border";
+ ot->idname= "VIEW2D_OT_zoom_border";
+
+ /* api callbacks */
+ ot->invoke= WM_border_select_invoke;
+ ot->exec= view_borderzoom_exec;
+ ot->modal= WM_border_select_modal;
+
+ ot->poll= ED_operator_areaactive;
+
+ /* rna */
+ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+}
+
+/* ********************************************************* */
+/* SCROLLERS */
+
+/* Scrollers should behave in the following ways, when clicked on with LMB (and dragged):
+ * 1) 'Handles' on end of 'bubble' - when the axis that the scroller represents is zoomable,
+ * enlarge 'cur' rect on the relevant side
+ * 2) 'Bubble'/'bar' - just drag, and bar should move with mouse (view pans opposite)
+ *
+ * In order to make sure this works, each operator must define the following RNA-Operator Props:
+ * deltax, deltay - define how much to move view by (relative to zoom-correction factor)
+ */
+
+/* customdata for scroller-invoke data */
+typedef struct v2dScrollerMove {
+ View2D *v2d; /* View2D data that this operation affects */
+
+ short scroller; /* scroller that mouse is in ('h' or 'v') */
+ short zone; /* -1 is min zoomer, 0 is bar, 1 is max zoomer */ // XXX find some way to provide visual feedback of this (active colour?)
+
+ float fac; /* view adjustment factor, based on size of region */
+ float delta; /* amount moved by mouse on axis of interest */
+
+ int lastx, lasty; /* previous mouse coordinates (in screen coordinates) for determining movement */
+} v2dScrollerMove;
+
+
+/* View2DScrollers is typedef'd in UI_view2d.h
+ * This is a CUT DOWN VERSION of the 'real' version, which is defined in view2d.c, as we only need focus bubble info
+ * WARNING: the start of this struct must not change, so that it stays in sync with the 'real' version
+ * For now, we don't need to have a separate (internal) header for structs like this...
+ */
+struct View2DScrollers {
+ /* focus bubbles */
+ int vert_min, vert_max; /* vertical scrollbar */
+ int hor_min, hor_max; /* horizontal scrollbar */
+};
+
+/* quick enum for vsm->zone (scroller handles) */
+enum {
+ SCROLLHANDLE_MIN= -1,
+ SCROLLHANDLE_BAR,
+ SCROLLHANDLE_MAX
+} eV2DScrollerHandle_Zone;
+
+/* ------------------------ */
+
+/* check if mouse is within scroller handle
+ * - mouse = relevant mouse coordinate in region space
+ * - sc_min, sc_max = extents of scroller
+ * - sh_min, sh_max = positions of scroller handles
+ */
+static short mouse_in_scroller_handle(int mouse, int sc_min, int sc_max, int sh_min, int sh_max)
+{
+ short in_min, in_max, in_view=1;
+
+ /* firstly, check if
+ * - 'bubble' fills entire scroller
+ * - 'bubble' completely out of view on either side
+ */
+ if ((sh_min <= sc_min) && (sh_max >= sc_max)) in_view= 0;
+ if (sh_min == sh_max) {
+ if (sh_min <= sc_min) in_view= 0;
+ if (sh_max >= sc_max) in_view= 0;
+ }
+ else {
+ if (sh_max <= sc_min) in_view= 0;
+ if (sh_min >= sc_max) in_view= 0;
+ }
+
+
+ if (in_view == 0) {
+ /* handles are only activated if the mouse is within the relative quater lengths of the scroller */
+ int qLen = (sc_max + sc_min) / 4;
+
+ if (mouse >= (sc_max - qLen))
+ return SCROLLHANDLE_MAX;
+ else if (mouse <= qLen)
+ return SCROLLHANDLE_MIN;
+ else
+ return SCROLLHANDLE_BAR;
+ }
+
+ /* check if mouse is in or past either handle */
+ in_max= ( (mouse >= (sh_max - V2D_SCROLLER_HANDLE_SIZE)) && (mouse <= (sh_max + V2D_SCROLLER_HANDLE_SIZE)) );
+ in_min= ( (mouse <= (sh_min + V2D_SCROLLER_HANDLE_SIZE)) && (mouse >= (sh_min - V2D_SCROLLER_HANDLE_SIZE)) );
+
+ /* check if overlap --> which means user clicked on bar, as bar is within handles region */
+ if (in_max && in_min)
+ return SCROLLHANDLE_BAR;
+ else if (in_max)
+ return SCROLLHANDLE_MAX;
+ else if (in_min)
+ return SCROLLHANDLE_MIN;
+
+ /* unlikely to happen, though we just cover it in case */
+ return SCROLLHANDLE_BAR;
+}
+
+/* initialise customdata for scroller manipulation operator */
+static void scroller_activate_init(bContext *C, wmOperator *op, wmEvent *event, short in_scroller)
+{
+ v2dScrollerMove *vsm;
+ View2DScrollers *scrollers;
+ ARegion *ar= CTX_wm_region(C);
+ View2D *v2d= &ar->v2d;
+ float mask_size;
+ int x, y;
+
+ /* set custom-data for operator */
+ vsm= MEM_callocN(sizeof(v2dScrollerMove), "v2dScrollerMove");
+ op->customdata= vsm;
+
+ /* set general data */
+ vsm->v2d= v2d;
+ vsm->scroller= in_scroller;
+
+ /* store mouse-coordinates, and convert mouse/screen coordinates to region coordinates */
+ vsm->lastx = event->x;
+ vsm->lasty = event->y;
+ x= event->x - ar->winrct.xmin;
+ y= event->y - ar->winrct.ymin;
+
+ /* 'zone' depends on where mouse is relative to bubble
+ * - zooming must be allowed on this axis, otherwise, default to pan
+ */
+ scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ if (in_scroller == 'h') {
+ /* horizontal scroller - calculate adjustment factor first */
+ mask_size= (float)(v2d->hor.xmax - v2d->hor.xmin);
+ vsm->fac= (v2d->tot.xmax - v2d->tot.xmin) / mask_size;
+
+ /* get 'zone' (i.e. which part of scroller is activated) */
+ if (v2d->keepzoom & V2D_LOCKZOOM_X) {
+ /* default to scroll, as handles not usable */
+ vsm->zone= SCROLLHANDLE_BAR;
+ }
+ else {
+ /* check which handle we're in */
+ vsm->zone= mouse_in_scroller_handle(x, v2d->hor.xmin, v2d->hor.xmax, scrollers->hor_min, scrollers->hor_max);
+ }
+ }
+ else {
+ /* vertical scroller - calculate adjustment factor first */
+ mask_size= (float)(v2d->vert.ymax - v2d->vert.ymin);
+ vsm->fac= (v2d->tot.ymax - v2d->tot.ymin) / mask_size;
+
+ /* get 'zone' (i.e. which part of scroller is activated) */
+ if (v2d->keepzoom & V2D_LOCKZOOM_Y) {
+ /* default to scroll, as handles not usable */
+ vsm->zone= SCROLLHANDLE_BAR;
+ }
+ else {
+ /* check which handle we're in */
+ vsm->zone= mouse_in_scroller_handle(y, v2d->vert.ymin, v2d->vert.ymax, scrollers->vert_min, scrollers->vert_max);
+ }
+ }
+ UI_view2d_scrollers_free(scrollers);
+}
+
+/* cleanup temp customdata */
+static void scroller_activate_exit(bContext *C, wmOperator *op)
+{
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ op->customdata= NULL;
+ }
+}
+
+/* apply transform to view (i.e. adjust 'cur' rect) */
+static void scroller_activate_apply(bContext *C, wmOperator *op)
+{
+ v2dScrollerMove *vsm= op->customdata;
+ View2D *v2d= vsm->v2d;
+ float temp;
+
+ /* calculate amount to move view by */
+ temp= vsm->fac * vsm->delta;
+
+ /* type of movement */
+ switch (vsm->zone) {
+ case SCROLLHANDLE_MIN:
+ /* only expand view on axis if zoom is allowed */
+ if ((vsm->scroller == 'h') && !(v2d->keepzoom & V2D_LOCKZOOM_X))
+ v2d->cur.xmin -= temp;
+ if ((vsm->scroller == 'v') && !(v2d->keepzoom & V2D_LOCKZOOM_Y))
+ v2d->cur.ymin -= temp;
+ break;
+
+ case SCROLLHANDLE_MAX:
+ /* only expand view on axis if zoom is allowed */
+ if ((vsm->scroller == 'h') && !(v2d->keepzoom & V2D_LOCKZOOM_X))
+ v2d->cur.xmax += temp;
+ if ((vsm->scroller == 'v') && !(v2d->keepzoom & V2D_LOCKZOOM_Y))
+ v2d->cur.ymax += temp;
+ break;
+
+ default: /* SCROLLHANDLE_BAR */
+ /* only move view on an axis if panning is allowed */
+ if ((vsm->scroller == 'h') && !(v2d->keepofs & V2D_LOCKOFS_X)) {
+ v2d->cur.xmin += temp;
+ v2d->cur.xmax += temp;
+ }
+ if ((vsm->scroller == 'v') && !(v2d->keepofs & V2D_LOCKOFS_Y)) {
+ v2d->cur.ymin += temp;
+ v2d->cur.ymax += temp;
+ }
+ break;
+ }
+
+ /* validate that view is in valid configuration after this operation */
+ UI_view2d_curRect_validate(v2d);
+
+ /* request updates to be done... */
+ ED_area_tag_redraw(CTX_wm_area(C));
+ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
+}
+
+/* handle user input for scrollers - calculations of mouse-movement need to be done here, not in the apply callback! */
+static int scroller_activate_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ v2dScrollerMove *vsm= op->customdata;
+
+ /* execute the events */
+ switch (event->type) {
+ case MOUSEMOVE:
+ {
+ /* calculate new delta transform, then store mouse-coordinates for next-time */
+ if (vsm->zone != SCROLLHANDLE_MIN) {
+ /* if using bar (i.e. 'panning') or 'max' zoom widget */
+ switch (vsm->scroller) {
+ case 'h': /* horizontal scroller - so only horizontal movement ('cur' moves opposite to mouse) */
+ vsm->delta= (float)(event->x - vsm->lastx);
+ break;
+ case 'v': /* vertical scroller - so only vertical movement ('cur' moves opposite to mouse) */
+ vsm->delta= (float)(event->y - vsm->lasty);
+ break;
+ }
+ }
+ else {
+ /* using 'min' zoom widget */
+ switch (vsm->scroller) {
+ case 'h': /* horizontal scroller - so only horizontal movement ('cur' moves with mouse) */
+ vsm->delta= (float)(vsm->lastx - event->x);
+ break;
+ case 'v': /* vertical scroller - so only vertical movement ('cur' moves with to mouse) */
+ vsm->delta= (float)(vsm->lasty - event->y);
+ break;
+ }
+ }
+
+ /* store previous coordinates */
+ vsm->lastx= event->x;
+ vsm->lasty= event->y;
+
+ scroller_activate_apply(C, op);
+ }
+ break;
+
+ case LEFTMOUSE:
+ if (event->val==0) {
+ scroller_activate_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+
+/* a click (or click drag in progress) should have occurred, so check if it happened in scrollbar */
+static int scroller_activate_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ View2D *v2d= NULL;
+ short in_scroller= 0;
+
+ /* firstly, check context to see if mouse is actually in region */
+ // XXX isn't this the job of poll() callbacks which can't check events, but only context?
+ if (ar == NULL)
+ return OPERATOR_PASS_THROUGH;//OPERATOR_CANCELLED;
+ else
+ v2d= &ar->v2d;
+
+ /* check if mouse in scrollbars, if they're enabled */
+ in_scroller= UI_view2d_mouse_in_scrollers(C, v2d, event->x, event->y);
+
+ /* if in a scroller, init customdata then set modal handler which will catch mousedown to start doing useful stuff */
+ if (in_scroller) {
+ v2dScrollerMove *vsm;
+
+ /* initialise customdata */
+ scroller_activate_init(C, op, event, in_scroller);
+ vsm= (v2dScrollerMove *)op->customdata;
+
+ /* check if zone is inappropriate (i.e. 'bar' but panning is banned), so cannot continue */
+ if (vsm->zone == SCROLLHANDLE_BAR) {
+ if ( ((vsm->scroller=='h') && (v2d->keepofs & V2D_LOCKOFS_X)) ||
+ ((vsm->scroller=='v') && (v2d->keepofs & V2D_LOCKOFS_Y)) )
+ {
+ /* free customdata initialised */
+ scroller_activate_exit(C, op);
+
+ /* can't catch this event for ourselves, so let it go to someone else? */
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
+
+ /* still ok, so can add */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ /* not in scroller, so nothing happened... (pass through let's something else catch event) */
+ return OPERATOR_PASS_THROUGH;
+ }
+}
+
+/* LMB-Drag in Scrollers - not repeatable operator! */
+void VIEW2D_OT_scroller_activate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Scroller Activate";
+ ot->idname= "VIEW2D_OT_scroller_activate";
+
+ /* api callbacks */
+ ot->invoke= scroller_activate_invoke;
+ ot->modal= scroller_activate_modal;
+}
+
+/* ********************************************************* */
+/* Registration */
+
+void ui_view2d_operatortypes(void)
+{
+ WM_operatortype_append(VIEW2D_OT_pan);
+
+ WM_operatortype_append(VIEW2D_OT_scroll_left);
+ WM_operatortype_append(VIEW2D_OT_scroll_right);
+ WM_operatortype_append(VIEW2D_OT_scroll_up);
+ WM_operatortype_append(VIEW2D_OT_scroll_down);
+
+ WM_operatortype_append(VIEW2D_OT_zoom_in);
+ WM_operatortype_append(VIEW2D_OT_zoom_out);
+
+ WM_operatortype_append(VIEW2D_OT_zoom);
+ WM_operatortype_append(VIEW2D_OT_zoom_border);
+
+ WM_operatortype_append(VIEW2D_OT_scroller_activate);
+}
+
+void UI_view2d_keymap(wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "View2D", 0, 0);
+
+ /* pan/scroll */
+ WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MIDDLEMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0);
+
+ WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_right", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_left", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0);
+
+ /* zoom - single step */
+ WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", WHEELOUTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", WHEELINMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", PADMINUS, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0);
+
+ /* scroll up/down - no modifiers, only when zoom fails */
+ /* these may fail if zoom is disallowed, in which case they should pass on event */
+ WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", WHEELDOWNMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", WHEELUPMOUSE, KM_PRESS, 0, 0);
+ /* these may be necessary if vertical scroll is disallowed */
+ WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_right", WHEELDOWNMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_left", WHEELUPMOUSE, KM_PRESS, 0, 0);
+
+ /* zoom - drag */
+ WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
+
+ /* borderzoom - drag */
+ WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_border", BKEY, KM_PRESS, KM_SHIFT, 0);
+
+ /* scrollers */
+ WM_keymap_add_item(keymap, "VIEW2D_OT_scroller_activate", LEFTMOUSE, KM_PRESS, 0, 0);
+
+ /* Alternative keymap for buttons listview */
+ keymap= WM_keymap_listbase(wm, "View2D Buttons List", 0, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MIDDLEMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", WHEELDOWNMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", WHEELUPMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
+}
+
diff --git a/source/blender/editors/mesh/Makefile b/source/blender/editors/mesh/Makefile
new file mode 100644
index 00000000000..60b1fa1c329
--- /dev/null
+++ b/source/blender/editors/mesh/Makefile
@@ -0,0 +1,57 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_mesh
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+CPPFLAGS += -I$(NAN_BMFONT)/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I$(NAN_ELBEEM)/include
+
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../gpu
+CPPFLAGS += -I../../render/extern/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/mesh/SConscript b/source/blender/editors/mesh/SConscript
new file mode 100644
index 00000000000..e99351e1a70
--- /dev/null
+++ b/source/blender/editors/mesh/SConscript
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' #/intern/guardedalloc #intern/bmfont ../../gpu'
+incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
+
+env.BlenderLib ( 'bf_editors_mesh', sources, Split(incs), [], libtype=['core'], priority=[45] )
diff --git a/source/blender/editors/mesh/editdeform.c b/source/blender/editors/mesh/editdeform.c
new file mode 100644
index 00000000000..3019aabf371
--- /dev/null
+++ b/source/blender/editors/mesh/editdeform.c
@@ -0,0 +1,1089 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * Creator-specific support for vertex deformation groups
+ * Added: apply deform function (ton)
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_cloth_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_scene_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_depsgraph.h"
+#include "BKE_deform.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_lattice.h"
+#include "BKE_mesh.h"
+#include "BKE_utildefines.h"
+
+#include "ED_mesh.h"
+#include "ED_view3d.h"
+#include "mesh_intern.h"
+
+/* XXX */
+static void BIF_undo_push() {}
+static void error() {}
+
+static Lattice *def_get_lattice(Object *ob)
+{
+ if(ob->type==OB_LATTICE) {
+ Lattice *lt= ob->data;
+ if(lt->editlatt)
+ return lt->editlatt;
+ return lt;
+ }
+ return NULL;
+}
+
+/* only in editmode */
+void sel_verts_defgroup (Object *obedit, int select)
+{
+ EditVert *eve;
+ Object *ob;
+ int i;
+ MDeformVert *dvert;
+
+ ob= obedit;
+
+ if (!ob)
+ return;
+
+ switch (ob->type){
+ case OB_MESH:
+ {
+ Mesh *me= ob->data;
+ EditMesh *em = BKE_mesh_get_editmesh(me);
+
+ for (eve=em->verts.first; eve; eve=eve->next){
+ dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+
+ if (dvert && dvert->totweight){
+ for (i=0; i<dvert->totweight; i++){
+ if (dvert->dw[i].def_nr == (ob->actdef-1)){
+ if (select) eve->f |= SELECT;
+ else eve->f &= ~SELECT;
+
+ break;
+ }
+ }
+ }
+ }
+ /* this has to be called, because this function operates on vertices only */
+ if(select) EM_select_flush(em); // vertices to edges/faces
+ else EM_deselect_flush(em);
+
+ BKE_mesh_end_editmesh(me, em);
+ }
+ break;
+ case OB_LATTICE:
+ {
+ Lattice *lt= def_get_lattice(ob);
+
+ if(lt->dvert) {
+ BPoint *bp;
+ int a, tot;
+
+ dvert= lt->dvert;
+
+ tot= lt->pntsu*lt->pntsv*lt->pntsw;
+ for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
+ for (i=0; i<dvert->totweight; i++){
+ if (dvert->dw[i].def_nr == (ob->actdef-1)) {
+ if(select) bp->f1 |= SELECT;
+ else bp->f1 &= ~SELECT;
+
+ break;
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* check if deform vertex has defgroup index */
+MDeformWeight *get_defweight (MDeformVert *dv, int defgroup)
+{
+ int i;
+
+ if (!dv || defgroup<0)
+ return NULL;
+
+ for (i=0; i<dv->totweight; i++){
+ if (dv->dw[i].def_nr == defgroup)
+ return dv->dw+i;
+ }
+ return NULL;
+}
+
+/* Ensures that mv has a deform weight entry for
+ the specified defweight group */
+/* Note this function is mirrored in editmesh_tools.c, for use for editvertices */
+MDeformWeight *verify_defweight (MDeformVert *dv, int defgroup)
+{
+ MDeformWeight *newdw;
+
+ /* do this check always, this function is used to check for it */
+ if (!dv || defgroup<0)
+ return NULL;
+
+ newdw = get_defweight (dv, defgroup);
+ if (newdw)
+ return newdw;
+
+ 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.0f;
+ dv->dw[dv->totweight].def_nr=defgroup;
+ /* Group index */
+
+ dv->totweight++;
+
+ return dv->dw+(dv->totweight-1);
+}
+
+bDeformGroup *add_defgroup_name (Object *ob, char *name)
+{
+ bDeformGroup *defgroup;
+
+ if (!ob)
+ return NULL;
+
+ defgroup = MEM_callocN (sizeof(bDeformGroup), "add deformGroup");
+
+ BLI_strncpy (defgroup->name, name, 32);
+
+ BLI_addtail(&ob->defbase, defgroup);
+ unique_vertexgroup_name(defgroup, ob);
+
+ ob->actdef = BLI_countlist(&ob->defbase);
+
+ return defgroup;
+}
+
+void add_defgroup (Object *ob)
+{
+ add_defgroup_name (ob, "Group");
+}
+
+
+void duplicate_defgroup ( Object *ob )
+{
+ bDeformGroup *dg, *cdg;
+ char name[32], s[32];
+ MDeformWeight *org, *cpy;
+ MDeformVert *dvert;
+ Mesh *me;
+ int i, idg, icdg;
+
+ if (ob->type != OB_MESH)
+ return;
+
+ dg = BLI_findlink (&ob->defbase, (ob->actdef-1));
+ if (!dg)
+ return;
+
+ if (strstr(dg->name, "_copy")) {
+ BLI_strncpy (name, dg->name, 32); /* will be renamed _copy.001... etc */
+ } else {
+ BLI_snprintf (name, 32, "%s_copy", dg->name);
+ while (get_named_vertexgroup (ob, name)) {
+ if ((strlen (name) + 6) > 32) {
+ error ("Error: the name for the new group is > 32 characters");
+ return;
+ }
+ strcpy (s, name);
+ BLI_snprintf (name, 32, "%s_copy", s);
+ }
+ }
+
+ cdg = copy_defgroup (dg);
+ strcpy (cdg->name, name);
+ unique_vertexgroup_name(cdg, ob);
+
+ BLI_addtail (&ob->defbase, cdg);
+
+ idg = (ob->actdef-1);
+ ob->actdef = BLI_countlist (&ob->defbase);
+ icdg = (ob->actdef-1);
+
+ me = get_mesh (ob);
+ if (!me->dvert)
+ return;
+
+ for (i = 0; i < me->totvert; i++) {
+ dvert = me->dvert+i;
+ org = get_defweight (dvert, idg);
+ if (org) {
+ cpy = verify_defweight (dvert, icdg);
+ cpy->weight = org->weight;
+ }
+ }
+}
+
+static void del_defgroup_update_users(Object *ob, int id)
+{
+ ExplodeModifierData *emd;
+ ModifierData *md;
+ ParticleSystem *psys;
+ ClothModifierData *clmd;
+ ClothSimSettings *clsim;
+ int a;
+
+ /* these cases don't use names to refer to vertex groups, so when
+ * they get deleted the numbers get out of sync, this corrects that */
+
+ if(ob->soft) {
+ if(ob->soft->vertgroup == id)
+ ob->soft->vertgroup= 0;
+ else if(ob->soft->vertgroup > id)
+ ob->soft->vertgroup--;
+ }
+
+ for(md=ob->modifiers.first; md; md=md->next) {
+ if(md->type == eModifierType_Explode) {
+ emd= (ExplodeModifierData*)md;
+
+ if(emd->vgroup == id)
+ emd->vgroup= 0;
+ else if(emd->vgroup > id)
+ emd->vgroup--;
+ }
+ else if(md->type == eModifierType_Cloth) {
+ clmd= (ClothModifierData*)md;
+ clsim= clmd->sim_parms;
+
+ if(clsim) {
+ if(clsim->vgroup_mass == id)
+ clsim->vgroup_mass= 0;
+ else if(clsim->vgroup_mass > id)
+ clsim->vgroup_mass--;
+
+ if(clsim->vgroup_bend == id)
+ clsim->vgroup_bend= 0;
+ else if(clsim->vgroup_bend > id)
+ clsim->vgroup_bend--;
+
+ if(clsim->vgroup_struct == id)
+ clsim->vgroup_struct= 0;
+ else if(clsim->vgroup_struct > id)
+ clsim->vgroup_struct--;
+ }
+ }
+ }
+
+ for(psys=ob->particlesystem.first; psys; psys=psys->next) {
+ for(a=0; a<PSYS_TOT_VG; a++)
+ if(psys->vgroup[a] == id)
+ psys->vgroup[a]= 0;
+ else if(psys->vgroup[a] > id)
+ psys->vgroup[a]--;
+ }
+}
+
+void del_defgroup_in_object_mode ( Object *ob )
+{
+ bDeformGroup *dg;
+ MDeformVert *dvert;
+ Mesh *me;
+ int i, e;
+
+ if ((!ob) || (ob->type != OB_MESH))
+ return;
+
+ dg = BLI_findlink (&ob->defbase, (ob->actdef-1));
+ if (!dg)
+ return;
+
+ me = get_mesh (ob);
+ if (me->dvert) {
+ for (i = 0; i < me->totvert; i++) {
+ dvert = me->dvert + i;
+ if (dvert) {
+ if (get_defweight (dvert, (ob->actdef-1)))
+ remove_vert_defgroup (ob, dg, i);
+ }
+ }
+
+ for (i = 0; i < me->totvert; i++) {
+ dvert = me->dvert+i;
+ if (dvert) {
+ for (e = 0; e < dvert->totweight; e++) {
+ if (dvert->dw[e].def_nr > (ob->actdef-1))
+ dvert->dw[e].def_nr--;
+ }
+ }
+ }
+ }
+
+ del_defgroup_update_users(ob, ob->actdef);
+
+ /* Update the active deform index if necessary */
+ if (ob->actdef == BLI_countlist(&ob->defbase))
+ ob->actdef--;
+
+ /* Remove the group */
+ BLI_freelinkN (&ob->defbase, dg);
+}
+
+void del_defgroup (Object *ob)
+{
+ bDeformGroup *defgroup;
+ 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(ob, 1);
+
+ /* Make sure that any verts with higher indices are adjusted accordingly */
+ if(ob->type==OB_MESH) {
+ Mesh *me= ob->data;
+ EditMesh *em = BKE_mesh_get_editmesh(me);
+ EditVert *eve;
+ MDeformVert *dvert;
+
+ for (eve=em->verts.first; eve; eve=eve->next){
+ dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+
+ if (dvert)
+ for (i=0; i<dvert->totweight; i++)
+ if (dvert->dw[i].def_nr > (ob->actdef-1))
+ dvert->dw[i].def_nr--;
+ }
+ BKE_mesh_end_editmesh(me, em);
+ }
+ else if(ob->type==OB_LATTICE) {
+ Lattice *lt= def_get_lattice(ob);
+ BPoint *bp;
+ MDeformVert *dvert= lt->dvert;
+ int a, tot;
+
+ if (dvert) {
+ tot= lt->pntsu*lt->pntsv*lt->pntsw;
+ for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
+ for (i=0; i<dvert->totweight; i++){
+ if (dvert->dw[i].def_nr > (ob->actdef-1))
+ dvert->dw[i].def_nr--;
+ }
+ }
+ }
+ }
+
+ del_defgroup_update_users(ob, ob->actdef);
+
+ /* Update the active deform index if necessary */
+ if (ob->actdef==BLI_countlist(&ob->defbase))
+ ob->actdef--;
+
+ /* Remove the group */
+ BLI_freelinkN (&ob->defbase, defgroup);
+
+ /* remove all dverts */
+ if(ob->actdef==0) {
+ if(ob->type==OB_MESH) {
+ Mesh *me= ob->data;
+ CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
+ me->dvert= NULL;
+ }
+ else if(ob->type==OB_LATTICE) {
+ Lattice *lt= def_get_lattice(ob);
+ if (lt->dvert) {
+ MEM_freeN(lt->dvert);
+ lt->dvert= NULL;
+ }
+ }
+ }
+}
+
+void del_all_defgroups (Object *ob)
+{
+ /* Sanity check */
+ if (ob == NULL)
+ return;
+
+ /* Remove all DVerts */
+ if (ob->type==OB_MESH) {
+ Mesh *me= ob->data;
+ CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
+ me->dvert= NULL;
+ }
+ else if(ob->type==OB_LATTICE) {
+ Lattice *lt= def_get_lattice(ob);
+ if (lt->dvert) {
+ MEM_freeN(lt->dvert);
+ lt->dvert= NULL;
+ }
+ }
+
+ /* Remove all DefGroups */
+ BLI_freelistN(&ob->defbase);
+
+ /* Fix counters/indices */
+ ob->actdef= 0;
+}
+
+void create_dverts(ID *id)
+{
+ /* create deform verts
+ */
+
+ if( GS(id->name)==ID_ME) {
+ Mesh *me= (Mesh *)id;
+ me->dvert= CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
+ }
+ else if( GS(id->name)==ID_LT) {
+ Lattice *lt= (Lattice *)id;
+ lt->dvert= MEM_callocN(sizeof(MDeformVert)*lt->pntsu*lt->pntsv*lt->pntsw, "lattice deformVert");
+ }
+}
+
+/* for mesh in object mode
+ lattice can be in editmode */
+void remove_vert_def_nr (Object *ob, int def_nr, int vertnum)
+{
+ /* This routine removes the vertex from the deform
+ * group with number def_nr.
+ *
+ * This routine is meant to be fast, so it is the
+ * responsibility of the calling routine to:
+ * a) test whether ob is non-NULL
+ * b) test whether ob is a mesh
+ * c) calculate def_nr
+ */
+
+ MDeformWeight *newdw;
+ MDeformVert *dvert= NULL;
+ int i;
+
+ /* get the deform vertices corresponding to the
+ * vertnum
+ */
+ if(ob->type==OB_MESH) {
+ if( ((Mesh*)ob->data)->dvert )
+ dvert = ((Mesh*)ob->data)->dvert + vertnum;
+ }
+ else if(ob->type==OB_LATTICE) {
+ Lattice *lt= def_get_lattice(ob);
+
+ if(lt->dvert)
+ dvert = lt->dvert + vertnum;
+ }
+
+ if(dvert==NULL)
+ return;
+
+ /* for all of the deform weights in the
+ * deform vert
+ */
+ for (i=dvert->totweight - 1 ; i>=0 ; i--){
+
+ /* if the def_nr is the same as the one
+ * for our weight group then remove it
+ * from this deform vert.
+ */
+ if (dvert->dw[i].def_nr == def_nr) {
+ dvert->totweight--;
+
+ /* if there are still other deform weights
+ * attached to this vert then remove this
+ * deform weight, and reshuffle the others
+ */
+ if (dvert->totweight) {
+ newdw = MEM_mallocN (sizeof(MDeformWeight)*(dvert->totweight),
+ "deformWeight");
+ if (dvert->dw){
+ memcpy (newdw, dvert->dw, sizeof(MDeformWeight)*i);
+ memcpy (newdw+i, dvert->dw+i+1,
+ sizeof(MDeformWeight)*(dvert->totweight-i));
+ MEM_freeN (dvert->dw);
+ }
+ dvert->dw=newdw;
+ }
+ /* if there are no other deform weights
+ * left then just remove the deform weight
+ */
+ else {
+ MEM_freeN (dvert->dw);
+ dvert->dw = NULL;
+ break;
+ }
+ }
+ }
+
+}
+
+/* for Mesh in Object mode */
+/* allows editmode for Lattice */
+void add_vert_defnr (Object *ob, int def_nr, int vertnum,
+ float weight, int assignmode)
+{
+ /* add the vert to the deform group with the
+ * specified number
+ */
+ MDeformVert *dv= NULL;
+ MDeformWeight *newdw;
+ int i;
+
+ /* get the vert */
+ if(ob->type==OB_MESH) {
+ if(((Mesh*)ob->data)->dvert)
+ dv = ((Mesh*)ob->data)->dvert + vertnum;
+ }
+ else if(ob->type==OB_LATTICE) {
+ Lattice *lt= def_get_lattice(ob);
+
+ if(lt->dvert)
+ dv = lt->dvert + vertnum;
+ }
+
+ if(dv==NULL)
+ return;
+
+ /* Lets first check to see if this vert is
+ * already in the weight group -- if so
+ * lets update it
+ */
+ for (i=0; i<dv->totweight; i++){
+
+ /* if this weight cooresponds to the
+ * deform group, then add it using
+ * the assign mode provided
+ */
+ if (dv->dw[i].def_nr == def_nr){
+
+ switch (assignmode) {
+ case WEIGHT_REPLACE:
+ dv->dw[i].weight=weight;
+ break;
+ case WEIGHT_ADD:
+ dv->dw[i].weight+=weight;
+ if (dv->dw[i].weight >= 1.0)
+ dv->dw[i].weight = 1.0;
+ break;
+ case WEIGHT_SUBTRACT:
+ dv->dw[i].weight-=weight;
+ /* if the weight is zero or less then
+ * remove the vert from the deform group
+ */
+ if (dv->dw[i].weight <= 0.0)
+ remove_vert_def_nr(ob, def_nr, vertnum);
+ break;
+ }
+ return;
+ }
+ }
+
+ /* if the vert wasn't in the deform group then
+ * we must take a different form of action ...
+ */
+
+ switch (assignmode) {
+ case WEIGHT_SUBTRACT:
+ /* if we are subtracting then we don't
+ * need to do anything
+ */
+ return;
+
+ case WEIGHT_REPLACE:
+ case WEIGHT_ADD:
+ /* if we are doing an additive assignment, then
+ * we need to create the deform weight
+ */
+ 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=weight;
+ dv->dw[dv->totweight].def_nr=def_nr;
+
+ dv->totweight++;
+ break;
+ }
+}
+
+/* called while not in editmode */
+void add_vert_to_defgroup (Object *ob, bDeformGroup *dg, int vertnum,
+ float weight, int assignmode)
+{
+ /* add the vert to the deform group with the
+ * specified assign mode
+ */
+ int def_nr;
+
+ /* get the deform group number, exit if
+ * it can't be found
+ */
+ def_nr = get_defgroup_num(ob, dg);
+ if (def_nr < 0) return;
+
+ /* if there's no deform verts then
+ * create some
+ */
+ if(ob->type==OB_MESH) {
+ if (!((Mesh*)ob->data)->dvert)
+ create_dverts(ob->data);
+ }
+ else if(ob->type==OB_LATTICE) {
+ if (!((Lattice*)ob->data)->dvert)
+ create_dverts(ob->data);
+ }
+
+ /* call another function to do the work
+ */
+ add_vert_defnr (ob, def_nr, vertnum, weight, assignmode);
+}
+
+/* Only available in editmode */
+void assign_verts_defgroup (Object *obedit, float weight)
+{
+ Object *ob;
+ EditVert *eve;
+ bDeformGroup *dg, *eg;
+ MDeformWeight *newdw;
+ MDeformVert *dvert;
+ int i, done;
+
+// XXX if(multires_level1_test()) return;
+
+ ob= obedit;
+
+ if (!ob)
+ return;
+
+ dg=BLI_findlink(&ob->defbase, ob->actdef-1);
+ if (!dg){
+ error ("No vertex group is active");
+ return;
+ }
+
+ switch (ob->type){
+ case OB_MESH:
+ {
+ Mesh *me= ob->data;
+ EditMesh *em = BKE_mesh_get_editmesh(me);
+
+ if (!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT))
+ EM_add_data_layer(em, &em->vdata, CD_MDEFORMVERT);
+
+ /* Go through the list of editverts and assign them */
+ for (eve=em->verts.first; eve; eve=eve->next){
+ dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+
+ if (dvert && (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<dvert->totweight; i++){
+ eg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr);
+ /* Find the actual group */
+ if (eg==dg){
+ dvert->dw[i].weight= weight;
+ done=1;
+ break;
+ }
+ }
+ /* If not: Add the group and set its weight */
+ if (!done){
+ newdw = MEM_callocN (sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
+ if (dvert->dw){
+ memcpy (newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
+ MEM_freeN (dvert->dw);
+ }
+ dvert->dw=newdw;
+
+ dvert->dw[dvert->totweight].weight= weight;
+ dvert->dw[dvert->totweight].def_nr= ob->actdef-1;
+
+ dvert->totweight++;
+
+ }
+ }
+ }
+ BKE_mesh_end_editmesh(me, em);
+ }
+ break;
+ case OB_LATTICE:
+ {
+ Lattice *lt= def_get_lattice(ob);
+ BPoint *bp;
+ int a, tot;
+
+ if(lt->dvert==NULL)
+ create_dverts(&lt->id);
+
+ tot= lt->pntsu*lt->pntsv*lt->pntsw;
+ for(a=0, bp= lt->def; a<tot; a++, bp++) {
+ if(bp->f1 & SELECT)
+ add_vert_defnr (ob, ob->actdef-1, a, weight, WEIGHT_REPLACE);
+ }
+ }
+ break;
+ default:
+ printf ("Assigning deformation groups to unknown object type\n");
+ break;
+ }
+
+}
+
+/* mesh object mode, lattice can be in editmode */
+void remove_vert_defgroup (Object *ob, bDeformGroup *dg, int vertnum)
+{
+ /* This routine removes the vertex from the specified
+ * deform group.
+ */
+
+ int def_nr;
+
+ /* if the object is NULL abort
+ */
+ if (!ob)
+ return;
+
+ /* get the deform number that cooresponds
+ * to this deform group, and abort if it
+ * can not be found.
+ */
+ def_nr = get_defgroup_num(ob, dg);
+ if (def_nr < 0) return;
+
+ /* call another routine to do the work
+ */
+ remove_vert_def_nr (ob, def_nr, vertnum);
+}
+
+/* for mesh in object mode lattice can be in editmode */
+static float get_vert_def_nr (Object *ob, int def_nr, int vertnum)
+{
+ MDeformVert *dvert= NULL;
+ int i;
+
+ /* get the deform vertices corresponding to the
+ * vertnum
+ */
+ if(ob->type==OB_MESH) {
+ if( ((Mesh*)ob->data)->dvert )
+ dvert = ((Mesh*)ob->data)->dvert + vertnum;
+ }
+ else if(ob->type==OB_LATTICE) {
+ Lattice *lt= def_get_lattice(ob);
+
+ if(lt->dvert)
+ dvert = lt->dvert + vertnum;
+ }
+
+ if(dvert==NULL)
+ return 0.0f;
+
+ for(i=dvert->totweight-1 ; i>=0 ; i--)
+ if(dvert->dw[i].def_nr == def_nr)
+ return dvert->dw[i].weight;
+
+ return 0.0f;
+}
+
+/* mesh object mode, lattice can be in editmode */
+float get_vert_defgroup (Object *ob, bDeformGroup *dg, int vertnum)
+{
+ int def_nr;
+
+ if(!ob)
+ return 0.0f;
+
+ def_nr = get_defgroup_num(ob, dg);
+ if(def_nr < 0) return 0.0f;
+
+ return get_vert_def_nr (ob, def_nr, vertnum);
+}
+
+/* Only available in editmode */
+/* removes from active defgroup, if allverts==0 only selected vertices */
+void remove_verts_defgroup (Object *obedit, int allverts)
+{
+ Object *ob;
+ EditVert *eve;
+ MDeformVert *dvert;
+ MDeformWeight *newdw;
+ bDeformGroup *dg, *eg;
+ int i;
+
+// XXX if(multires_level1_test()) return;
+
+ ob= obedit;
+
+ if (!ob)
+ return;
+
+ dg=BLI_findlink(&ob->defbase, ob->actdef-1);
+ if (!dg){
+ error ("No vertex group is active");
+ return;
+ }
+
+ switch (ob->type){
+ case OB_MESH:
+ {
+ Mesh *me= ob->data;
+ EditMesh *em = BKE_mesh_get_editmesh(me);
+
+ for (eve=em->verts.first; eve; eve=eve->next){
+ dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+
+ if (dvert && dvert->dw && ((eve->f & 1) || allverts)){
+ for (i=0; i<dvert->totweight; i++){
+ /* Find group */
+ eg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr);
+ if (eg == dg){
+ dvert->totweight--;
+ if (dvert->totweight){
+ newdw = MEM_mallocN (sizeof(MDeformWeight)*(dvert->totweight), "deformWeight");
+
+ if (dvert->dw){
+ memcpy (newdw, dvert->dw, sizeof(MDeformWeight)*i);
+ memcpy (newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i));
+ MEM_freeN (dvert->dw);
+ }
+ dvert->dw=newdw;
+ }
+ else{
+ MEM_freeN (dvert->dw);
+ dvert->dw=NULL;
+ break;
+ }
+ }
+ }
+ }
+ }
+ BKE_mesh_end_editmesh(me, em);
+ }
+ break;
+ case OB_LATTICE:
+ {
+ Lattice *lt= def_get_lattice(ob);
+
+ if(lt->dvert) {
+ BPoint *bp;
+ int a, tot= lt->pntsu*lt->pntsv*lt->pntsw;
+
+ for(a=0, bp= lt->def; a<tot; a++, bp++) {
+ if(allverts || (bp->f1 & SELECT))
+ remove_vert_defgroup (ob, dg, a);
+ }
+ }
+ }
+ break;
+
+ default:
+ printf ("Removing deformation groups from unknown object type\n");
+ break;
+ }
+}
+
+/* Only available in editmode */
+/* removes from all defgroup, if allverts==0 only selected vertices */
+void remove_verts_defgroups(Object *obedit, int allverts)
+{
+ Object *ob;
+ int actdef, defCount;
+
+// XXX if (multires_level1_test()) return;
+
+ ob= obedit;
+ if (ob == NULL) return;
+
+ actdef= ob->actdef;
+ defCount= BLI_countlist(&ob->defbase);
+
+ if (defCount == 0) {
+ error("Object has no vertex groups");
+ return;
+ }
+
+ /* To prevent code redundancy, we just use remove_verts_defgroup, but that
+ * only operates on the active vgroup. So we iterate through all groups, by changing
+ * active group index
+ */
+ for (ob->actdef= 1; ob->actdef <= defCount; ob->actdef++)
+ remove_verts_defgroup(ob, allverts);
+
+ ob->actdef= actdef;
+}
+
+void vertexgroup_select_by_name(Object *ob, char *name)
+{
+ bDeformGroup *curdef;
+ int actdef= 1;
+
+ if(ob==NULL) return;
+
+ for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++){
+ if (!strcmp(curdef->name, name)) {
+ ob->actdef= actdef;
+ return;
+ }
+ }
+ ob->actdef=0; // this signals on painting to create a new one, if a bone in posemode is selected */
+}
+
+/* This function provides a shortcut for adding/removing verts from
+ * vertex groups. It is called by the Ctrl-G hotkey in EditMode for Meshes
+ * and Lattices. (currently only restricted to those two)
+ * It is only responsible for
+ */
+void vgroup_assign_with_menu(Scene *scene, Object *ob)
+{
+ VPaint *wp= scene->toolsettings->wpaint;
+ int defCount;
+ int mode= 0;
+
+ /* prevent crashes */
+ if (wp==NULL || ob==NULL) return;
+
+ defCount= BLI_countlist(&ob->defbase);
+
+ /* give user choices of adding to current/new or removing from current */
+// XXX if (defCount && ob->actdef)
+// mode = pupmenu("Vertex Groups %t|Add Selected to New Group %x1|Add Selected to Active Group %x2|Remove Selected from Active Group %x3|Remove Selected from All Groups %x4");
+// else
+// mode= pupmenu("Vertex Groups %t|Add Selected to New Group %x1");
+
+ /* handle choices */
+ switch (mode) {
+ case 1: /* add to new group */
+ add_defgroup(ob);
+ assign_verts_defgroup(ob, wp->brush->alpha);
+ BIF_undo_push("Assign to vertex group");
+ break;
+ case 2: /* add to current group */
+ assign_verts_defgroup(ob, wp->brush->alpha);
+ BIF_undo_push("Assign to vertex group");
+ break;
+ case 3: /* remove from current group */
+ remove_verts_defgroup(ob, 0);
+ BIF_undo_push("Remove from vertex group");
+ break;
+ case 4: /* remove from all groups */
+ remove_verts_defgroups(ob, 0);
+ BIF_undo_push("Remove from all vertex groups");
+ break;
+ }
+}
+
+/* This function provides a shortcut for commonly used vertex group
+ * functions - change weight (not implemented), change active group, delete active group,
+ * when Ctrl-Shift-G is used in EditMode, for Meshes and Lattices (only for now).
+ */
+void vgroup_operation_with_menu(Object *ob)
+{
+ int defCount;
+ int mode= 0;
+
+ /* prevent crashes and useless cases */
+ if (ob==NULL) return;
+
+ defCount= BLI_countlist(&ob->defbase);
+ if (defCount == 0) return;
+
+ /* give user choices of adding to current/new or removing from current */
+// XXX if (ob->actdef)
+// mode = pupmenu("Vertex Groups %t|Change Active Group%x1|Delete Active Group%x2|Delete All Groups%x3");
+// else
+// mode= pupmenu("Vertex Groups %t|Change Active Group%x1|Delete All Groups%x3");
+
+ /* handle choices */
+ switch (mode) {
+ case 1: /* change active group*/
+ {
+ char *menustr= NULL; // XXX get_vertexgroup_menustr(ob);
+ short nr;
+
+ if (menustr) {
+// XXX nr= pupmenu(menustr);
+
+ if ((nr >= 1) && (nr <= defCount))
+ ob->actdef= nr;
+
+ MEM_freeN(menustr);
+ }
+ }
+ break;
+ case 2: /* delete active group */
+ {
+ del_defgroup(ob);
+ BIF_undo_push("Delete vertex group");
+ }
+ break;
+ case 3: /* delete all groups */
+ {
+ del_all_defgroups(ob);
+ BIF_undo_push("Delete all vertex groups");
+ }
+ break;
+ }
+}
+
+
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
new file mode 100644
index 00000000000..a6c5e5beccf
--- /dev/null
+++ b/source/blender/editors/mesh/editface.c
@@ -0,0 +1,727 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_heap.h"
+#include "BLI_edgehash.h"
+#include "BLI_editVert.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_image_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+#include "BKE_customdata.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "GPU_draw.h"
+
+#ifndef DISABLE_PYTHON
+//#include "BPY_extern.h"
+//#include "BPY_menus.h"
+#endif
+
+#include "ED_mesh.h"
+#include "ED_object.h"
+#include "ED_view3d.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* own include */
+#include "mesh_intern.h"
+
+/* ***************** XXX **************** */
+static int sample_backbuf_rect() {return 0;}
+static int sample_backbuf() {return 0;}
+static void error() {}
+static int pupmenu() {return 0;}
+/* ***************** XXX **************** */
+
+
+/* returns 0 if not found, otherwise 1 */
+int facesel_face_pick(View3D *v3d, Mesh *me, short *mval, unsigned int *index, short rect)
+{
+ if (!me || me->totface==0)
+ return 0;
+
+ if (v3d->flag & V3D_NEEDBACKBUFDRAW) {
+// XXX drawview.c! check_backbuf();
+// XXX persp(PERSP_VIEW);
+ }
+
+ if (rect) {
+ /* sample rect to increase changes of selecting, so that when clicking
+ on an edge in the backbuf, we can still select a face */
+ int dist;
+ *index = sample_backbuf_rect(mval, 3, 1, me->totface+1, &dist,0,NULL);
+ }
+ else
+ /* sample only on the exact position */
+ *index = sample_backbuf(mval[0], mval[1]);
+
+ if ((*index)<=0 || (*index)>(unsigned int)me->totface)
+ return 0;
+
+ (*index)--;
+
+ return 1;
+}
+
+/* last_sel, use em->act_face otherwise get the last selected face in the editselections
+ * at the moment, last_sel is mainly useful for gaking sure the space image dosnt flicker */
+MTFace *EM_get_active_mtface(EditMesh *em, EditFace **act_efa, MCol **mcol, int sloppy)
+{
+ EditFace *efa = NULL;
+
+ if(!EM_texFaceCheck(em))
+ return NULL;
+
+ efa = EM_get_actFace(em, sloppy);
+
+ if (efa) {
+ if (mcol) {
+ if (CustomData_has_layer(&em->fdata, CD_MCOL))
+ *mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
+ else
+ *mcol = NULL;
+ }
+ if (act_efa) *act_efa = efa;
+ return CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ }
+ if (act_efa) *act_efa= NULL;
+ if(mcol) *mcol = NULL;
+ return NULL;
+}
+
+void reveal_tface(Scene *scene)
+{
+ Mesh *me;
+ MFace *mface;
+ int a;
+
+ me= get_mesh(OBACT);
+ if(me==0 || me->totface==0) return;
+
+ mface= me->mface;
+ a= me->totface;
+ while(a--) {
+ if(mface->flag & ME_HIDE) {
+ mface->flag |= ME_FACE_SEL;
+ mface->flag -= ME_HIDE;
+ }
+ mface++;
+ }
+
+// XXX notifier! object_tface_flags_changed(OBACT, 0);
+}
+
+void hide_tface(Scene *scene)
+{
+ Mesh *me;
+ MFace *mface;
+ int a;
+ int shift=0, alt= 0; // XXX
+
+ me= get_mesh(OBACT);
+ if(me==0 || me->totface==0) return;
+
+ if(alt) {
+ reveal_tface(scene);
+ return;
+ }
+
+ mface= me->mface;
+ a= me->totface;
+ while(a--) {
+ if(mface->flag & ME_HIDE);
+ else {
+ if(shift) {
+ if( (mface->flag & ME_FACE_SEL)==0) mface->flag |= ME_HIDE;
+ }
+ else {
+ if( (mface->flag & ME_FACE_SEL)) mface->flag |= ME_HIDE;
+ }
+ }
+ if(mface->flag & ME_HIDE) mface->flag &= ~ME_FACE_SEL;
+
+ mface++;
+ }
+
+// XXX notifier! object_tface_flags_changed(OBACT, 0);
+}
+
+void select_linked_tfaces(Scene *scene, View3D *v3d, int mode)
+{
+ Object *ob;
+ Mesh *me;
+ short mval[2];
+ unsigned int index=0;
+
+ ob = OBACT;
+ me = get_mesh(ob);
+ if(me==0 || me->totface==0) return;
+
+ if (mode==0 || mode==1) {
+ if (!(ob->lay & v3d->lay))
+ error("The active object is not in this layer");
+
+// XXX getmouseco_areawin(mval);
+ if (!facesel_face_pick(v3d, me, mval, &index, 1)) return;
+ }
+
+// XXX unwrapper.c select_linked_tfaces_with_seams(mode, me, index);
+}
+
+void deselectall_tface(Scene *scene)
+{
+ Mesh *me;
+ MFace *mface;
+ int a, sel;
+
+ me= get_mesh(OBACT);
+ if(me==0) return;
+
+ mface= me->mface;
+ a= me->totface;
+ sel= 0;
+ while(a--) {
+ if(mface->flag & ME_HIDE);
+ else if(mface->flag & ME_FACE_SEL) sel= 1;
+ mface++;
+ }
+
+ mface= me->mface;
+ a= me->totface;
+ while(a--) {
+ if(mface->flag & ME_HIDE);
+ else {
+ if(sel) mface->flag &= ~ME_FACE_SEL;
+ else mface->flag |= ME_FACE_SEL;
+ }
+ mface++;
+ }
+
+// XXX notifier! object_tface_flags_changed(OBACT, 0);
+}
+
+void selectswap_tface(Scene *scene)
+{
+ Mesh *me;
+ MFace *mface;
+ int a;
+
+ me= get_mesh(OBACT);
+ if(me==0) return;
+
+ mface= me->mface;
+ a= me->totface;
+ while(a--) {
+ if(mface->flag & ME_HIDE);
+ else {
+ if(mface->flag & ME_FACE_SEL) mface->flag &= ~ME_FACE_SEL;
+ else mface->flag |= ME_FACE_SEL;
+ }
+ mface++;
+ }
+
+// XXX notifier! object_tface_flags_changed(OBACT, 0);
+}
+
+int minmax_tface(Scene *scene, float *min, float *max)
+{
+ Object *ob;
+ Mesh *me;
+ MFace *mf;
+ MTFace *tf;
+ MVert *mv;
+ int a, ok=0;
+ float vec[3], bmat[3][3];
+
+ ob = OBACT;
+ if (ob==0) return ok;
+ me= get_mesh(ob);
+ if(me==0 || me->mtface==0) return ok;
+
+ Mat3CpyMat4(bmat, ob->obmat);
+
+ mv= me->mvert;
+ mf= me->mface;
+ tf= me->mtface;
+ for (a=me->totface; a>0; a--, mf++, tf++) {
+ if (mf->flag & ME_HIDE || !(mf->flag & ME_FACE_SEL))
+ continue;
+
+ VECCOPY(vec, (mv+mf->v1)->co);
+ Mat3MulVecfl(bmat, vec);
+ VecAddf(vec, vec, ob->obmat[3]);
+ DO_MINMAX(vec, min, max);
+
+ VECCOPY(vec, (mv+mf->v2)->co);
+ Mat3MulVecfl(bmat, vec);
+ VecAddf(vec, vec, ob->obmat[3]);
+ DO_MINMAX(vec, min, max);
+
+ VECCOPY(vec, (mv+mf->v3)->co);
+ Mat3MulVecfl(bmat, vec);
+ VecAddf(vec, vec, ob->obmat[3]);
+ DO_MINMAX(vec, min, max);
+
+ if (mf->v4) {
+ VECCOPY(vec, (mv+mf->v4)->co);
+ Mat3MulVecfl(bmat, vec);
+ VecAddf(vec, vec, ob->obmat[3]);
+ DO_MINMAX(vec, min, max);
+ }
+ ok= 1;
+ }
+ return ok;
+}
+
+/* ******************** edge loop shortest path ********************* */
+
+#define ME_SEAM_DONE 2 /* reuse this flag */
+
+static float edgetag_cut_cost(EditMesh *em, int e1, int e2, int vert)
+{
+ EditVert *v = EM_get_vert_for_index(vert);
+ EditEdge *eed1 = EM_get_edge_for_index(e1), *eed2 = EM_get_edge_for_index(e2);
+ EditVert *v1 = EM_get_vert_for_index( (eed1->v1->tmp.l == vert)? eed1->v2->tmp.l: eed1->v1->tmp.l );
+ EditVert *v2 = EM_get_vert_for_index( (eed2->v1->tmp.l == vert)? eed2->v2->tmp.l: eed2->v1->tmp.l );
+ float cost, d1[3], d2[3];
+
+ cost = VecLenf(v1->co, v->co);
+ cost += VecLenf(v->co, v2->co);
+
+ VecSubf(d1, v->co, v1->co);
+ VecSubf(d2, v2->co, v->co);
+
+ cost = cost + 0.5f*cost*(2.0f - fabs(d1[0]*d2[0] + d1[1]*d2[1] + d1[2]*d2[2]));
+
+ return cost;
+}
+
+static void edgetag_add_adjacent(EditMesh *em, Heap *heap, int mednum, int vertnum, int *nedges, int *edges, int *prevedge, float *cost)
+{
+ int startadj, endadj = nedges[vertnum+1];
+
+ for (startadj = nedges[vertnum]; startadj < endadj; startadj++) {
+ int adjnum = edges[startadj];
+ EditEdge *eedadj = EM_get_edge_for_index(adjnum);
+ float newcost;
+
+ if (eedadj->f2 & ME_SEAM_DONE)
+ continue;
+
+ newcost = cost[mednum] + edgetag_cut_cost(em, mednum, adjnum, vertnum);
+
+ if (cost[adjnum] > newcost) {
+ cost[adjnum] = newcost;
+ prevedge[adjnum] = mednum;
+ BLI_heap_insert(heap, newcost, SET_INT_IN_POINTER(adjnum));
+ }
+ }
+}
+
+void edgetag_context_set(Scene *scene, EditEdge *eed, int val)
+{
+
+ switch (scene->toolsettings->edge_mode) {
+ case EDGE_MODE_SELECT:
+ EM_select_edge(eed, val);
+ break;
+ case EDGE_MODE_TAG_SEAM:
+ if (val) {eed->seam = 255;}
+ else {eed->seam = 0;}
+ break;
+ case EDGE_MODE_TAG_SHARP:
+ if (val) {eed->sharp = 1;}
+ else {eed->sharp = 0;}
+ break;
+ case EDGE_MODE_TAG_CREASE:
+ if (val) {eed->crease = 1.0f;}
+ else {eed->crease = 0.0f;}
+ break;
+ case EDGE_MODE_TAG_BEVEL:
+ if (val) {eed->bweight = 1.0f;}
+ else {eed->bweight = 0.0f;}
+ break;
+ }
+}
+
+int edgetag_context_check(Scene *scene, EditEdge *eed)
+{
+ switch (scene->toolsettings->edge_mode) {
+ case EDGE_MODE_SELECT:
+ return (eed->f & SELECT) ? 1 : 0;
+ case EDGE_MODE_TAG_SEAM:
+ return eed->seam ? 1 : 0;
+ case EDGE_MODE_TAG_SHARP:
+ return eed->sharp ? 1 : 0;
+ case EDGE_MODE_TAG_CREASE:
+ return eed->crease ? 1 : 0;
+ case EDGE_MODE_TAG_BEVEL:
+ return eed->bweight ? 1 : 0;
+ }
+ return 0;
+}
+
+
+int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge *target)
+{
+ EditEdge *eed;
+ EditVert *ev;
+
+ Heap *heap;
+ float *cost;
+ int a, totvert=0, totedge=0, *nedges, *edges, *prevedge, mednum = -1, nedgeswap = 0;
+
+
+ /* we need the vert */
+ for (ev= em->verts.first, totvert=0; ev; ev= ev->next) {
+ ev->tmp.l = totvert;
+ totvert++;
+ }
+
+ for (eed= em->edges.first; eed; eed = eed->next) {
+ eed->f2 = 0;
+ if (eed->h) {
+ eed->f2 |= ME_SEAM_DONE;
+ }
+ eed->tmp.l = totedge;
+ totedge++;
+ }
+
+ /* alloc */
+ nedges = MEM_callocN(sizeof(*nedges)*totvert+1, "SeamPathNEdges");
+ edges = MEM_mallocN(sizeof(*edges)*totedge*2, "SeamPathEdges");
+ prevedge = MEM_mallocN(sizeof(*prevedge)*totedge, "SeamPathPrevious");
+ cost = MEM_mallocN(sizeof(*cost)*totedge, "SeamPathCost");
+
+ /* count edges, compute adjacent edges offsets and fill adjacent edges */
+ for (eed= em->edges.first; eed; eed = eed->next) {
+ nedges[eed->v1->tmp.l+1]++;
+ nedges[eed->v2->tmp.l+1]++;
+ }
+
+ for (a=1; a<totvert; a++) {
+ int newswap = nedges[a+1];
+ nedges[a+1] = nedgeswap + nedges[a];
+ nedgeswap = newswap;
+ }
+ nedges[0] = nedges[1] = 0;
+
+ for (a=0, eed= em->edges.first; eed; a++, eed = eed->next) {
+ edges[nedges[eed->v1->tmp.l+1]++] = a;
+ edges[nedges[eed->v2->tmp.l+1]++] = a;
+
+ cost[a] = 1e20f;
+ prevedge[a] = -1;
+ }
+
+ /* regular dijkstra shortest path, but over edges instead of vertices */
+ heap = BLI_heap_new();
+ BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(source->tmp.l));
+ cost[source->tmp.l] = 0.0f;
+
+ EM_init_index_arrays(em, 1, 1, 0);
+
+
+ while (!BLI_heap_empty(heap)) {
+ mednum = GET_INT_FROM_POINTER(BLI_heap_popmin(heap));
+ eed = EM_get_edge_for_index( mednum );
+
+ if (mednum == target->tmp.l)
+ break;
+
+ if (eed->f2 & ME_SEAM_DONE)
+ continue;
+
+ eed->f2 |= ME_SEAM_DONE;
+
+ edgetag_add_adjacent(em, heap, mednum, eed->v1->tmp.l, nedges, edges, prevedge, cost);
+ edgetag_add_adjacent(em, heap, mednum, eed->v2->tmp.l, nedges, edges, prevedge, cost);
+ }
+
+
+ MEM_freeN(nedges);
+ MEM_freeN(edges);
+ MEM_freeN(cost);
+ BLI_heap_free(heap, NULL);
+
+ for (eed= em->edges.first; eed; eed = eed->next) {
+ eed->f2 &= ~ME_SEAM_DONE;
+ }
+
+ if (mednum != target->tmp.l) {
+ MEM_freeN(prevedge);
+ EM_free_index_arrays();
+ return 0;
+ }
+
+ /* follow path back to source and mark as seam */
+ if (mednum == target->tmp.l) {
+ short allseams = 1;
+
+ mednum = target->tmp.l;
+ do {
+ eed = EM_get_edge_for_index( mednum );
+ if (!edgetag_context_check(scene, eed)) {
+ allseams = 0;
+ break;
+ }
+ mednum = prevedge[mednum];
+ } while (mednum != source->tmp.l);
+
+ mednum = target->tmp.l;
+ do {
+ eed = EM_get_edge_for_index( mednum );
+ if (allseams)
+ edgetag_context_set(scene, eed, 0);
+ else
+ edgetag_context_set(scene, eed, 1);
+ mednum = prevedge[mednum];
+ } while (mednum != -1);
+ }
+
+ MEM_freeN(prevedge);
+ EM_free_index_arrays();
+ return 1;
+}
+
+/* *************************************** */
+
+static void seam_edgehash_insert_face(EdgeHash *ehash, MFace *mf)
+{
+ BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL);
+ BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL);
+ if (mf->v4) {
+ BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL);
+ BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL);
+ }
+ else
+ BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL);
+}
+
+void seam_mark_clear_tface(Scene *scene, short mode)
+{
+ Mesh *me;
+ MFace *mf;
+ MEdge *med;
+ int a;
+
+ me= get_mesh(OBACT);
+ if(me==0 || me->totface==0) return;
+
+ if (mode == 0)
+ mode = pupmenu("Seams%t|Mark Border Seam %x1|Clear Seam %x2");
+
+ if (mode != 1 && mode != 2)
+ return;
+
+ if (mode == 2) {
+ EdgeHash *ehash = BLI_edgehash_new();
+
+ for (a=0, mf=me->mface; a<me->totface; a++, mf++)
+ if (!(mf->flag & ME_HIDE) && (mf->flag & ME_FACE_SEL))
+ seam_edgehash_insert_face(ehash, mf);
+
+ for (a=0, med=me->medge; a<me->totedge; a++, med++)
+ if (BLI_edgehash_haskey(ehash, med->v1, med->v2))
+ med->flag &= ~ME_SEAM;
+
+ BLI_edgehash_free(ehash, NULL);
+ }
+ else {
+ /* mark edges that are on both selected and deselected faces */
+ EdgeHash *ehash1 = BLI_edgehash_new();
+ EdgeHash *ehash2 = BLI_edgehash_new();
+
+ for (a=0, mf=me->mface; a<me->totface; a++, mf++) {
+ if ((mf->flag & ME_HIDE) || !(mf->flag & ME_FACE_SEL))
+ seam_edgehash_insert_face(ehash1, mf);
+ else
+ seam_edgehash_insert_face(ehash2, mf);
+ }
+
+ for (a=0, med=me->medge; a<me->totedge; a++, med++)
+ if (BLI_edgehash_haskey(ehash1, med->v1, med->v2) &&
+ BLI_edgehash_haskey(ehash2, med->v1, med->v2))
+ med->flag |= ME_SEAM;
+
+ BLI_edgehash_free(ehash1, NULL);
+ BLI_edgehash_free(ehash2, NULL);
+ }
+
+// XXX if (G.rt == 8)
+// unwrap_lscm(1);
+
+ me->drawflag |= ME_DRAWSEAMS;
+
+// XXX notifier! object_tface_flags_changed(OBACT, 1);
+}
+
+void face_select(Scene *scene, View3D *v3d)
+{
+ Object *ob;
+ Mesh *me;
+ MFace *mface, *msel;
+ short mval[2];
+ unsigned int a, index;
+ int shift= 0; // XXX
+
+ /* Get the face under the cursor */
+ ob = OBACT;
+ if (!(ob->lay & v3d->lay)) {
+ error("The active object is not in this layer");
+ }
+ me = get_mesh(ob);
+// XXX getmouseco_areawin(mval);
+
+ if (!facesel_face_pick(v3d, me, mval, &index, 1)) return;
+
+ msel= (((MFace*)me->mface)+index);
+ if (msel->flag & ME_HIDE) return;
+
+ /* clear flags */
+ mface = me->mface;
+ a = me->totface;
+ if ((shift)==0) {
+ while (a--) {
+ mface->flag &= ~ME_FACE_SEL;
+ mface++;
+ }
+ }
+
+ me->act_face = (int)index;
+
+ if (shift) {
+ if (msel->flag & ME_FACE_SEL)
+ msel->flag &= ~ME_FACE_SEL;
+ else
+ msel->flag |= ME_FACE_SEL;
+ }
+ else msel->flag |= ME_FACE_SEL;
+
+ /* image window redraw */
+
+
+// XXX notifier! object_tface_flags_changed(OBACT, 1);
+}
+
+void face_borderselect(Scene *scene, ARegion *ar)
+{
+ Mesh *me;
+ MFace *mface;
+ rcti rect;
+ struct ImBuf *ibuf;
+ unsigned int *rt;
+ int a, sx, sy, index, val= 0;
+ char *selar;
+
+ me= get_mesh(OBACT);
+ if(me==0) return;
+ if(me->totface==0) return;
+
+// XXX val= get_border(&rect, 3);
+
+ /* why readbuffer here? shouldn't be necessary (maybe a flush or so) */
+ glReadBuffer(GL_BACK);
+#ifdef __APPLE__
+ glReadBuffer(GL_AUX0); /* apple only */
+#endif
+
+ 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;
+
+ ibuf = IMB_allocImBuf(sx,sy,32,IB_rect,0);
+ rt = ibuf->rect;
+ glReadPixels(rect.xmin+ar->winrct.xmin, rect.ymin+ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ if(ENDIAN_ORDER==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
+
+ a= sx*sy;
+ while(a--) {
+ if(*rt) {
+ index= WM_framebuffer_to_index(*rt);
+ if(index<=me->totface) selar[index]= 1;
+ }
+ rt++;
+ }
+
+ mface= me->mface;
+ for(a=1; a<=me->totface; a++, mface++) {
+ if(selar[a]) {
+ if(mface->flag & ME_HIDE);
+ else {
+ if(val==LEFTMOUSE) mface->flag |= ME_FACE_SEL;
+ else mface->flag &= ~ME_FACE_SEL;
+ }
+ }
+ }
+
+ IMB_freeImBuf(ibuf);
+ MEM_freeN(selar);
+
+
+// XXX notifier! object_tface_flags_changed(OBACT, 0);
+ }
+#ifdef __APPLE__
+ glReadBuffer(GL_BACK);
+#endif
+}
+
+
diff --git a/source/blender/editors/mesh/editmesh.c b/source/blender/editors/mesh/editmesh.c
new file mode 100644
index 00000000000..40373c9f327
--- /dev/null
+++ b/source/blender/editors/mesh/editmesh.c
@@ -0,0 +1,2029 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, full recode 2002-2008
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "DNA_customdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.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_modifier_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_dynstr.h"
+#include "BLI_rand.h"
+
+#include "BKE_cloth.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_global.h"
+#include "BKE_key.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_pointcache.h"
+#include "BKE_softbody.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+
+#include "LBM_fluidsim.h"
+
+#include "BIF_retopo.h"
+
+#include "ED_mesh.h"
+#include "ED_object.h"
+#include "ED_util.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* own include */
+#include "mesh_intern.h"
+
+/*
+editmesh.c:
+ - add/alloc/free data
+ - hashtables
+ - enter/exit editmode
+*/
+
+/* XXX */
+static void BIF_undo_push() {}
+static void error() {}
+
+
+/* ***************** HASH ********************* */
+
+
+#define EDHASHSIZE (512*512)
+#define EDHASH(a, b) (a % EDHASHSIZE)
+
+
+/* ************ ADD / REMOVE / FIND ****************** */
+
+static void *calloc_em(EditMesh *em, size_t size, size_t nr)
+{
+ return calloc(size, nr);
+}
+
+/* used to bypass normal calloc with fast one */
+static void *(*callocvert)(EditMesh *, size_t, size_t) = calloc_em;
+static void *(*callocedge)(EditMesh *, size_t, size_t) = calloc_em;
+static void *(*callocface)(EditMesh *, size_t, size_t) = calloc_em;
+
+EditVert *addvertlist(EditMesh *em, float *vec, EditVert *example)
+{
+ EditVert *eve;
+ static int hashnr= 0;
+
+ eve= callocvert(em, sizeof(EditVert), 1);
+ BLI_addtail(&em->verts, eve);
+ em->totvert++;
+
+ if(vec) VECCOPY(eve->co, vec);
+
+ eve->hash= hashnr++;
+ if( hashnr>=EDHASHSIZE) hashnr= 0;
+
+ /* new verts get keyindex of -1 since they did not
+ * have a pre-editmode vertex order
+ */
+ eve->keyindex = -1;
+
+ if(example) {
+ CustomData_em_copy_data(&em->vdata, &em->vdata, example->data, &eve->data);
+ eve->bweight = example->bweight;
+ }
+ else {
+ CustomData_em_set_default(&em->vdata, &eve->data);
+ }
+
+ return eve;
+}
+
+void free_editvert (EditMesh *em, EditVert *eve)
+{
+
+ EM_remove_selection(em, eve, EDITVERT);
+ CustomData_em_free_block(&em->vdata, &eve->data);
+ if(eve->fast==0)
+ free(eve);
+
+ em->totvert--;
+}
+
+
+EditEdge *findedgelist(EditMesh *em, EditVert *v1, EditVert *v2)
+{
+ EditVert *v3;
+ struct HashEdge *he;
+
+ /* swap ? */
+ if( v1 > v2) {
+ v3= v2;
+ v2= v1;
+ v1= v3;
+ }
+
+ if(em->hashedgetab==NULL)
+ em->hashedgetab= MEM_callocN(EDHASHSIZE*sizeof(struct HashEdge), "hashedgetab");
+
+ he= em->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(EditMesh *em, EditEdge *eed)
+{
+ /* assuming that eed is not in the list yet, and that a find has been done before */
+
+ struct HashEdge *first, *he;
+
+ first= em->hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash);
+
+ if( first->eed==0 ) {
+ first->eed= eed;
+ }
+ else {
+ he= &eed->hash;
+ he->eed= eed;
+ he->next= first->next;
+ first->next= he;
+ }
+}
+
+static void remove_hashedge(EditMesh *em, EditEdge *eed)
+{
+ /* assuming eed is in the list */
+
+ struct HashEdge *first, *he, *prev=NULL;
+
+ he=first= em->hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash);
+
+ while(he) {
+ if(he->eed == eed) {
+ /* remove from list */
+ if(he==first) {
+ if(first->next) {
+ he= first->next;
+ first->eed= he->eed;
+ first->next= he->next;
+ }
+ else he->eed= 0;
+ }
+ else {
+ prev->next= he->next;
+ }
+ return;
+ }
+ prev= he;
+ he= he->next;
+ }
+}
+
+EditEdge *addedgelist(EditMesh *em, EditVert *v1, EditVert *v2, EditEdge *example)
+{
+ EditVert *v3;
+ EditEdge *eed;
+ int swap= 0;
+
+ if(v1==v2) return NULL;
+ if(v1==NULL || v2==NULL) return NULL;
+
+ /* swap ? */
+ if(v1>v2) {
+ v3= v2;
+ v2= v1;
+ v1= v3;
+ swap= 1;
+ }
+
+ /* find in hashlist */
+ eed= findedgelist(em, v1, v2);
+
+ if(eed==NULL) {
+
+ eed= (EditEdge *)callocedge(em, sizeof(EditEdge), 1);
+ eed->v1= v1;
+ eed->v2= v2;
+ BLI_addtail(&em->edges, eed);
+ eed->dir= swap;
+ insert_hashedge(em, eed);
+ em->totedge++;
+
+ /* copy edge data:
+ rule is to do this with addedgelist call, before addfacelist */
+ if(example) {
+ eed->crease= example->crease;
+ eed->bweight= example->bweight;
+ eed->sharp = example->sharp;
+ eed->seam = example->seam;
+ eed->h |= (example->h & EM_FGON);
+ }
+ }
+
+ return eed;
+}
+
+void remedge(EditMesh *em, EditEdge *eed)
+{
+ BLI_remlink(&em->edges, eed);
+ remove_hashedge(em, eed);
+
+ em->totedge--;
+}
+
+void free_editedge(EditMesh *em, EditEdge *eed)
+{
+ EM_remove_selection(em, eed, EDITEDGE);
+ if(eed->fast==0){
+ free(eed);
+ }
+}
+
+void free_editface(EditMesh *em, EditFace *efa)
+{
+ EM_remove_selection(em, efa, EDITFACE);
+
+ if (em->act_face==efa) {
+ EM_set_actFace(em, em->faces.first == efa ? NULL : em->faces.first);
+ }
+
+ CustomData_em_free_block(&em->fdata, &efa->data);
+ if(efa->fast==0)
+ free(efa);
+
+ em->totface--;
+}
+
+void free_vertlist(EditMesh *em, ListBase *edve)
+{
+ EditVert *eve, *next;
+
+ if (!edve) return;
+
+ eve= edve->first;
+ while(eve) {
+ next= eve->next;
+ free_editvert(em, eve);
+ eve= next;
+ }
+ edve->first= edve->last= NULL;
+ em->totvert= em->totvertsel= 0;
+}
+
+void free_edgelist(EditMesh *em, ListBase *lb)
+{
+ EditEdge *eed, *next;
+
+ eed= lb->first;
+ while(eed) {
+ next= eed->next;
+ free_editedge(em, eed);
+ eed= next;
+ }
+ lb->first= lb->last= NULL;
+ em->totedge= em->totedgesel= 0;
+}
+
+void free_facelist(EditMesh *em, ListBase *lb)
+{
+ EditFace *efa, *next;
+
+ efa= lb->first;
+ while(efa) {
+ next= efa->next;
+ free_editface(em, efa);
+ efa= next;
+ }
+ lb->first= lb->last= NULL;
+ em->totface= em->totfacesel= 0;
+}
+
+EditFace *addfacelist(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, EditFace *example, EditFace *exampleEdges)
+{
+ EditFace *efa;
+ EditEdge *e1, *e2=0, *e3=0, *e4=0;
+
+ /* added sanity check... seems to happen for some tools, or for enter editmode for corrupted meshes */
+ if(v1==v4 || v2==v4 || v3==v4) v4= NULL;
+
+ /* add face to list and do the edges */
+ if(exampleEdges) {
+ e1= addedgelist(em, v1, v2, exampleEdges->e1);
+ e2= addedgelist(em, v2, v3, exampleEdges->e2);
+ if(v4) e3= addedgelist(em, v3, v4, exampleEdges->e3);
+ else e3= addedgelist(em, v3, v1, exampleEdges->e3);
+ if(v4) e4= addedgelist(em, v4, v1, exampleEdges->e4);
+ }
+ else {
+ e1= addedgelist(em, v1, v2, NULL);
+ e2= addedgelist(em, v2, v3, NULL);
+ if(v4) e3= addedgelist(em, v3, v4, NULL);
+ else e3= addedgelist(em, v3, v1, NULL);
+ if(v4) e4= addedgelist(em, v4, v1, NULL);
+ }
+
+ if(v1==v2 || v2==v3 || v1==v3) return NULL;
+ if(e2==0) return NULL;
+
+ efa= (EditFace *)callocface(em, sizeof(EditFace), 1);
+ efa->v1= v1;
+ efa->v2= v2;
+ efa->v3= v3;
+ efa->v4= v4;
+
+ efa->e1= e1;
+ efa->e2= e2;
+ efa->e3= e3;
+ efa->e4= e4;
+
+ if(example) {
+ efa->mat_nr= example->mat_nr;
+ efa->flag= example->flag;
+ CustomData_em_copy_data(&em->fdata, &em->fdata, example->data, &efa->data);
+ }
+ else {
+ efa->mat_nr= em->mat_nr;
+
+ CustomData_em_set_default(&em->fdata, &efa->data);
+ }
+
+ BLI_addtail(&em->faces, efa);
+ em->totface++;
+
+ if(efa->v4) {
+ CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, efa->n);
+ CalcCent4f(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
+ }
+ else {
+ CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n);
+ CalcCent3f(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co);
+ }
+
+ return efa;
+}
+
+/* ************************ end add/new/find ************ */
+
+/* ************************ Edit{Vert,Edge,Face} utilss ***************************** */
+
+/* some nice utility functions */
+
+EditVert *editedge_getOtherVert(EditEdge *eed, EditVert *eve)
+{
+ if (eve==eed->v1) {
+ return eed->v2;
+ } else if (eve==eed->v2) {
+ return eed->v1;
+ } else {
+ return NULL;
+ }
+}
+
+EditVert *editedge_getSharedVert(EditEdge *eed, EditEdge *eed2)
+{
+ if (eed->v1==eed2->v1 || eed->v1==eed2->v2) {
+ return eed->v1;
+ } else if (eed->v2==eed2->v1 || eed->v2==eed2->v2) {
+ return eed->v2;
+ } else {
+ return NULL;
+ }
+}
+
+int editedge_containsVert(EditEdge *eed, EditVert *eve)
+{
+ return (eed->v1==eve || eed->v2==eve);
+}
+
+int editface_containsVert(EditFace *efa, EditVert *eve)
+{
+ return (efa->v1==eve || efa->v2==eve || efa->v3==eve || (efa->v4 && efa->v4==eve));
+}
+
+int editface_containsEdge(EditFace *efa, EditEdge *eed)
+{
+ return (efa->e1==eed || efa->e2==eed || efa->e3==eed || (efa->e4 && efa->e4==eed));
+}
+
+
+/* ************************ stuct EditMesh manipulation ***************************** */
+
+/* fake callocs for fastmalloc below */
+static void *calloc_fastvert(EditMesh *em, size_t size, size_t nr)
+{
+ EditVert *eve= em->curvert++;
+ eve->fast= 1;
+ return eve;
+}
+static void *calloc_fastedge(EditMesh *em, size_t size, size_t nr)
+{
+ EditEdge *eed= em->curedge++;
+ eed->fast= 1;
+ return eed;
+}
+static void *calloc_fastface(EditMesh *em, size_t size, size_t nr)
+{
+ EditFace *efa= em->curface++;
+ efa->fast= 1;
+ return efa;
+}
+
+/* allocate 1 chunk for all vertices, edges, faces. These get tagged to
+ prevent it from being freed
+*/
+static void init_editmesh_fastmalloc(EditMesh *em, int totvert, int totedge, int totface)
+{
+ if(totvert) em->allverts= MEM_callocN(totvert*sizeof(EditVert), "allverts");
+ else em->allverts= NULL;
+ em->curvert= em->allverts;
+
+ if(totedge==0) totedge= 4*totface; // max possible
+
+ if(totedge) em->alledges= MEM_callocN(totedge*sizeof(EditEdge), "alledges");
+ else em->alledges= NULL;
+ em->curedge= em->alledges;
+
+ if(totface) em->allfaces= MEM_callocN(totface*sizeof(EditFace), "allfaces");
+ else em->allfaces= NULL;
+ em->curface= em->allfaces;
+
+ callocvert= calloc_fastvert;
+ callocedge= calloc_fastedge;
+ callocface= calloc_fastface;
+}
+
+static void end_editmesh_fastmalloc(void)
+{
+ callocvert= calloc_em;
+ callocedge= calloc_em;
+ callocface= calloc_em;
+}
+
+/* do not free editmesh itself here */
+void free_editMesh(EditMesh *em)
+{
+ if(em==NULL) return;
+
+ if(em->verts.first) free_vertlist(em, &em->verts);
+ if(em->edges.first) free_edgelist(em, &em->edges);
+ if(em->faces.first) free_facelist(em, &em->faces);
+ if(em->selected.first) BLI_freelistN(&(em->selected));
+
+ CustomData_free(&em->vdata, 0);
+ CustomData_free(&em->fdata, 0);
+
+ if(em->derivedFinal) {
+ if (em->derivedFinal!=em->derivedCage) {
+ em->derivedFinal->needsFree= 1;
+ em->derivedFinal->release(em->derivedFinal);
+ }
+ em->derivedFinal= NULL;
+ }
+ if(em->derivedCage) {
+ em->derivedCage->needsFree= 1;
+ em->derivedCage->release(em->derivedCage);
+ em->derivedCage= NULL;
+ }
+
+ /* DEBUG: hashtabs are slowest part of enter/exit editmode. here a testprint */
+#if 0
+ if(em->hashedgetab) {
+ HashEdge *he, *hen;
+ int a, used=0, max=0, nr;
+ he= em->hashedgetab;
+ for(a=0; a<EDHASHSIZE; a++, he++) {
+ if(he->eed) used++;
+ hen= he->next;
+ nr= 0;
+ while(hen) {
+ nr++;
+ hen= hen->next;
+ }
+ if(max<nr) max= nr;
+ }
+ printf("hastab used %d max %d\n", used, max);
+ }
+#endif
+ if(em->hashedgetab) MEM_freeN(em->hashedgetab);
+ em->hashedgetab= NULL;
+
+ if(em->allverts) MEM_freeN(em->allverts);
+ if(em->alledges) MEM_freeN(em->alledges);
+ if(em->allfaces) MEM_freeN(em->allfaces);
+
+ em->allverts= em->curvert= NULL;
+ em->alledges= em->curedge= NULL;
+ em->allfaces= em->curface= NULL;
+
+ mesh_octree_table(NULL, NULL, NULL, 'e');
+
+ em->totvert= em->totedge= em->totface= 0;
+
+// XXX if(em->retopo_paint_data) retopo_free_paint_data(em->retopo_paint_data);
+ em->retopo_paint_data= NULL;
+ em->act_face = NULL;
+}
+
+static void editMesh_set_hash(EditMesh *em)
+{
+ EditEdge *eed;
+
+ if(em->hashedgetab) MEM_freeN(em->hashedgetab);
+ em->hashedgetab= NULL;
+
+ for(eed=em->edges.first; eed; eed= eed->next) {
+ if( findedgelist(em, eed->v1, eed->v2)==NULL )
+ insert_hashedge(em, eed);
+ }
+
+}
+
+
+/* ************************ IN & OUT EDITMODE ***************************** */
+
+
+static void edge_normal_compare(EditEdge *eed, EditFace *efa1)
+{
+ EditFace *efa2;
+ float cent1[3], cent2[3];
+ float inp;
+
+ efa2 = eed->tmp.f;
+ if(efa1==efa2) return;
+
+ inp= efa1->n[0]*efa2->n[0] + efa1->n[1]*efa2->n[1] + efa1->n[2]*efa2->n[2];
+ if(inp<0.999 && inp >-0.999) eed->f2= 1;
+
+ if(efa1->v4) CalcCent4f(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co, efa1->v4->co);
+ else CalcCent3f(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co);
+ if(efa2->v4) CalcCent4f(cent2, efa2->v1->co, efa2->v2->co, efa2->v3->co, efa2->v4->co);
+ else CalcCent3f(cent2, efa2->v1->co, efa2->v2->co, efa2->v3->co);
+
+ VecSubf(cent1, cent2, cent1);
+ Normalize(cent1);
+ inp= cent1[0]*efa1->n[0] + cent1[1]*efa1->n[1] + cent1[2]*efa1->n[2];
+
+ if(inp < -0.001 ) eed->f1= 1;
+}
+
+#if 0
+typedef struct {
+ EditEdge *eed;
+ float noLen,no[3];
+ int adjCount;
+} EdgeDrawFlagInfo;
+
+static int edgeDrawFlagInfo_cmp(const void *av, const void *bv)
+{
+ const EdgeDrawFlagInfo *a = av;
+ const EdgeDrawFlagInfo *b = bv;
+
+ if (a->noLen<b->noLen) return -1;
+ else if (a->noLen>b->noLen) return 1;
+ else return 0;
+}
+#endif
+
+static void edge_drawflags(Mesh *me, EditMesh *em)
+{
+ EditVert *eve;
+ EditEdge *eed, *e1, *e2, *e3, *e4;
+ EditFace *efa;
+
+ /* - count number of times edges are used in faces: 0 en 1 time means draw edge
+ * - edges more than 1 time used: in *tmp.f is pointer to first face
+ * - check all faces, when normal differs to much: draw (flag becomes 1)
+ */
+
+ /* later on: added flags for 'cylinder' and 'sphere' intersection tests in old
+ game engine (2.04)
+ */
+
+ recalc_editnormals(em);
+
+ /* init */
+ eve= em->verts.first;
+ while(eve) {
+ eve->f1= 1; /* during test it's set at zero */
+ eve= eve->next;
+ }
+ eed= em->edges.first;
+ while(eed) {
+ eed->f2= eed->f1= 0;
+ eed->tmp.f = 0;
+ eed= eed->next;
+ }
+
+ efa= em->faces.first;
+ while(efa) {
+ e1= efa->e1;
+ e2= efa->e2;
+ e3= efa->e3;
+ e4= efa->e4;
+ if(e1->f2<4) e1->f2+= 1;
+ if(e2->f2<4) e2->f2+= 1;
+ if(e3->f2<4) e3->f2+= 1;
+ if(e4 && e4->f2<4) e4->f2+= 1;
+
+ if(e1->tmp.f == 0) e1->tmp.f = (void *) efa;
+ if(e2->tmp.f == 0) e2->tmp.f = (void *) efa;
+ if(e3->tmp.f ==0) e3->tmp.f = (void *) efa;
+ if(e4 && (e4->tmp.f == 0)) e4->tmp.f = (void *) efa;
+
+ efa= efa->next;
+ }
+
+ if(me->drawflag & ME_ALLEDGES) {
+ efa= em->faces.first;
+ while(efa) {
+ if(efa->e1->f2>=2) efa->e1->f2= 1;
+ if(efa->e2->f2>=2) efa->e2->f2= 1;
+ if(efa->e3->f2>=2) efa->e3->f2= 1;
+ if(efa->e4 && efa->e4->f2>=2) efa->e4->f2= 1;
+
+ efa= efa->next;
+ }
+ }
+ else {
+
+ /* handle single-edges for 'test cylinder flag' (old engine) */
+
+ eed= em->edges.first;
+ while(eed) {
+ if(eed->f2==1) eed->f1= 1;
+ eed= eed->next;
+ }
+
+ /* all faces, all edges with flag==2: compare normal */
+ efa= em->faces.first;
+ while(efa) {
+ if(efa->e1->f2==2) edge_normal_compare(efa->e1, efa);
+ else efa->e1->f2= 1;
+ if(efa->e2->f2==2) edge_normal_compare(efa->e2, efa);
+ else efa->e2->f2= 1;
+ if(efa->e3->f2==2) edge_normal_compare(efa->e3, efa);
+ else efa->e3->f2= 1;
+ if(efa->e4) {
+ if(efa->e4->f2==2) edge_normal_compare(efa->e4, efa);
+ else efa->e4->f2= 1;
+ }
+ efa= efa->next;
+ }
+
+ /* sphere collision flag */
+
+ eed= em->edges.first;
+ while(eed) {
+ if(eed->f1!=1) {
+ eed->v1->f1= eed->v2->f1= 0;
+ }
+ eed= eed->next;
+ }
+
+ }
+}
+
+static int editmesh_pointcache_edit(Scene *scene, Object *ob, int totvert, PTCacheID *pid_p, float mat[][4], int load)
+{
+ Cloth *cloth;
+ SoftBody *sb;
+ ClothModifierData *clmd;
+ PTCacheID pid, tmpid;
+ int cfra= (int)scene->r.cfra, found= 0;
+
+ pid.cache= NULL;
+
+ /* check for cloth */
+ if(modifiers_isClothEnabled(ob)) {
+ clmd= (ClothModifierData*)modifiers_findByType(ob, eModifierType_Cloth);
+ cloth= clmd->clothObject;
+
+ BKE_ptcache_id_from_cloth(&tmpid, ob, clmd);
+
+ /* verify vertex count and baked status */
+ if(cloth && (totvert == cloth->numverts)) {
+ if((tmpid.cache->flag & PTCACHE_BAKED) && (tmpid.cache->flag & PTCACHE_BAKE_EDIT)) {
+ pid= tmpid;
+
+ if(load && (pid.cache->flag & PTCACHE_BAKE_EDIT_ACTIVE))
+ found= 1;
+ }
+ }
+ }
+
+ /* check for softbody */
+ if(!found && ob->soft) {
+ sb= ob->soft;
+
+ BKE_ptcache_id_from_softbody(&tmpid, ob, sb);
+
+ /* verify vertex count and baked status */
+ if(sb->bpoint && (totvert == sb->totpoint)) {
+ if((tmpid.cache->flag & PTCACHE_BAKED) && (tmpid.cache->flag & PTCACHE_BAKE_EDIT)) {
+ pid= tmpid;
+
+ if(load && (pid.cache->flag & PTCACHE_BAKE_EDIT_ACTIVE))
+ found= 1;
+ }
+ }
+ }
+
+ /* if not making editmesh verify editing was active for this point cache */
+ if(load) {
+ if(found)
+ pid.cache->flag &= ~PTCACHE_BAKE_EDIT_ACTIVE;
+ else
+ return 0;
+ }
+
+ /* check if we have cache for this frame */
+ if(pid.cache && BKE_ptcache_id_exist(&pid, cfra)) {
+ *pid_p = pid;
+
+ if(load) {
+ Mat4CpyMat4(mat, ob->obmat);
+ }
+ else {
+ pid.cache->editframe= cfra;
+ pid.cache->flag |= PTCACHE_BAKE_EDIT_ACTIVE;
+ Mat4Invert(mat, ob->obmat); /* ob->imat is not up to date */
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/* turns Mesh into editmesh */
+void make_editMesh(Scene *scene, Object *ob)
+{
+ Mesh *me= ob->data;
+ MFace *mface;
+ MVert *mvert;
+ MSelect *mselect;
+ KeyBlock *actkey;
+ EditMesh *em;
+ EditVert *eve, **evlist, *eve1, *eve2, *eve3, *eve4;
+ EditFace *efa;
+ EditEdge *eed;
+ EditSelection *ese;
+ PTCacheID pid;
+ Cloth *cloth;
+ SoftBody *sb;
+ float cacheco[3], cachemat[4][4], *co;
+ int tot, a, cacheedit= 0, eekadoodle= 0;
+
+ if(me->edit_mesh==NULL)
+ me->edit_mesh= MEM_callocN(sizeof(EditMesh), "editmesh");
+ else
+ /* because of reload */
+ free_editMesh(me->edit_mesh);
+
+ em= me->edit_mesh;
+
+ em->selectmode= scene->selectmode; // warning needs to be synced
+ em->act_face = NULL;
+ em->totvert= tot= me->totvert;
+ em->totedge= me->totedge;
+ em->totface= me->totface;
+
+ if(tot==0) {
+ return;
+ }
+
+ /* initialize fastmalloc for editmesh */
+ init_editmesh_fastmalloc(em, me->totvert, me->totedge, me->totface);
+
+ actkey = ob_get_keyblock(ob);
+ if(actkey) {
+ tot= actkey->totelem;
+ /* undo-ing in past for previous editmode sessions gives corrupt 'keyindex' values */
+ undo_editmode_clear();
+ }
+
+
+ /* make editverts */
+ CustomData_copy(&me->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
+ mvert= me->mvert;
+
+ cacheedit= editmesh_pointcache_edit(scene, ob, tot, &pid, cachemat, 0);
+
+ evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist");
+ for(a=0; a<tot; a++, mvert++) {
+
+ if(cacheedit) {
+ if(pid.type == PTCACHE_TYPE_CLOTH) {
+ cloth= ((ClothModifierData*)pid.data)->clothObject;
+ VECCOPY(cacheco, cloth->verts[a].x)
+ }
+ else if(pid.type == PTCACHE_TYPE_SOFTBODY) {
+ sb= (SoftBody*)pid.data;
+ VECCOPY(cacheco, sb->bpoint[a].pos)
+ }
+
+ Mat4MulVecfl(cachemat, cacheco);
+ co= cacheco;
+ }
+ else
+ co= mvert->co;
+
+ eve= addvertlist(em, co, NULL);
+ evlist[a]= eve;
+
+ // face select sets selection in next loop
+ if( (FACESEL_PAINT_TEST)==0 )
+ eve->f |= (mvert->flag & 1);
+
+ if (mvert->flag & ME_HIDE) eve->h= 1;
+ eve->no[0]= mvert->no[0]/32767.0;
+ eve->no[1]= mvert->no[1]/32767.0;
+ eve->no[2]= mvert->no[2]/32767.0;
+
+ eve->bweight= ((float)mvert->bweight)/255.0f;
+
+ /* lets overwrite the keyindex of the editvert
+ * with the order it used to be in before
+ * editmode
+ */
+ eve->keyindex = a;
+
+ CustomData_to_em_block(&me->vdata, &em->vdata, a, &eve->data);
+ }
+
+ if(actkey && actkey->totelem!=me->totvert);
+ else {
+ MEdge *medge= me->medge;
+
+ CustomData_copy(&me->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0);
+ /* make edges */
+ for(a=0; a<me->totedge; a++, medge++) {
+ eed= addedgelist(em, evlist[medge->v1], evlist[medge->v2], NULL);
+ /* eed can be zero when v1 and v2 are identical, dxf import does this... */
+ if(eed) {
+ eed->crease= ((float)medge->crease)/255.0f;
+ eed->bweight= ((float)medge->bweight)/255.0f;
+
+ if(medge->flag & ME_SEAM) eed->seam= 1;
+ if(medge->flag & ME_SHARP) eed->sharp = 1;
+ if(medge->flag & SELECT) eed->f |= SELECT;
+ if(medge->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines!
+ if(medge->flag & ME_HIDE) eed->h |= 1;
+ if(em->selectmode==SCE_SELECT_EDGE)
+ EM_select_edge(eed, eed->f & SELECT); // force edge selection to vertices, seems to be needed ...
+ CustomData_to_em_block(&me->edata,&em->edata, a, &eed->data);
+ }
+ }
+
+ CustomData_copy(&me->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
+
+ /* make faces */
+ mface= me->mface;
+
+ for(a=0; a<me->totface; a++, mface++) {
+ eve1= evlist[mface->v1];
+ eve2= evlist[mface->v2];
+ if(!mface->v3) eekadoodle= 1;
+ eve3= evlist[mface->v3];
+ if(mface->v4) eve4= evlist[mface->v4]; else eve4= NULL;
+
+ efa= addfacelist(em, eve1, eve2, eve3, eve4, NULL, NULL);
+
+ if(efa) {
+ CustomData_to_em_block(&me->fdata, &em->fdata, a, &efa->data);
+
+ efa->mat_nr= mface->mat_nr;
+ efa->flag= mface->flag & ~ME_HIDE;
+
+ /* select and hide face flag */
+ if(mface->flag & ME_HIDE) {
+ efa->h= 1;
+ } else {
+ if (a==me->act_face) {
+ EM_set_actFace(em, efa);
+ }
+
+ /* dont allow hidden and selected */
+ if(mface->flag & ME_FACE_SEL) {
+ efa->f |= SELECT;
+
+ if(FACESEL_PAINT_TEST) {
+ EM_select_face(efa, 1); /* flush down */
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(eekadoodle)
+ error("This Mesh has old style edgecodes, please put it in the bugtracker!");
+
+ MEM_freeN(evlist);
+
+ end_editmesh_fastmalloc(); // resets global function pointers
+
+ if(me->mselect){
+ //restore editselections
+ EM_init_index_arrays(em, 1,1,1);
+ mselect = me->mselect;
+
+ for(a=0; a<me->totselect; a++, mselect++){
+ /*check if recorded selection is still valid, if so copy into editmesh*/
+ if( (mselect->type == EDITVERT && me->mvert[mselect->index].flag & SELECT) || (mselect->type == EDITEDGE && me->medge[mselect->index].flag & SELECT) || (mselect->type == EDITFACE && me->mface[mselect->index].flag & ME_FACE_SEL) ){
+ ese = MEM_callocN(sizeof(EditSelection), "Edit Selection");
+ ese->type = mselect->type;
+ if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(mselect->index); else
+ if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(mselect->index); else
+ if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(mselect->index);
+ BLI_addtail(&(em->selected),ese);
+ }
+ }
+ EM_free_index_arrays();
+ }
+ /* this creates coherent selections. also needed for older files */
+ EM_selectmode_set(em);
+ /* paranoia check to enforce hide rules */
+ EM_hide_reset(em);
+ /* sets helper flags which arent saved */
+ EM_fgon_flags(em);
+
+ if (EM_get_actFace(em, 0)==NULL) {
+ EM_set_actFace(em, em->faces.first ); /* will use the first face, this is so we alwats have an active face */
+ }
+
+ /* vertex coordinates change with cache edit, need to recalc */
+ if(cacheedit)
+ recalc_editnormals(em);
+
+}
+
+/* makes Mesh out of editmesh */
+void load_editMesh(Scene *scene, Object *ob)
+{
+ Mesh *me= ob->data;
+ MVert *mvert, *oldverts;
+ MEdge *medge;
+ MFace *mface;
+ MSelect *mselect;
+ EditMesh *em= me->edit_mesh;
+ EditVert *eve;
+ EditFace *efa, *efa_act;
+ EditEdge *eed;
+ EditSelection *ese;
+ SoftBody *sb;
+ Cloth *cloth;
+ ClothModifierData *clmd;
+ PTCacheID pid;
+ float *fp, *newkey, *oldkey, nor[3], cacheco[3], cachemat[4][4];
+ int i, a, ototvert, cacheedit= 0;
+
+ /* this one also tests of edges are not in faces: */
+ /* eed->f2==0: not in face, f2==1: draw it */
+ /* eed->f1 : flag for dynaface (cylindertest, old engine) */
+ /* eve->f1 : flag for dynaface (sphere test, old engine) */
+ /* eve->f2 : being used in vertexnormals */
+ edge_drawflags(me, em);
+
+ EM_stats_update(em);
+
+ /* new Vertex block */
+ if(em->totvert==0) mvert= NULL;
+ else mvert= MEM_callocN(em->totvert*sizeof(MVert), "loadeditMesh vert");
+
+ /* new Edge block */
+ if(em->totedge==0) medge= NULL;
+ else medge= MEM_callocN(em->totedge*sizeof(MEdge), "loadeditMesh edge");
+
+ /* new Face block */
+ if(em->totface==0) mface= NULL;
+ else mface= MEM_callocN(em->totface*sizeof(MFace), "loadeditMesh face");
+
+ /* lets save the old verts just in case we are actually working on
+ * a key ... we now do processing of the keys at the end */
+ oldverts= me->mvert;
+ ototvert= me->totvert;
+
+ /* don't free this yet */
+ CustomData_set_layer(&me->vdata, CD_MVERT, NULL);
+
+ /* free custom data */
+ CustomData_free(&me->vdata, me->totvert);
+ CustomData_free(&me->edata, me->totedge);
+ CustomData_free(&me->fdata, me->totface);
+
+ /* add new custom data */
+ me->totvert= em->totvert;
+ me->totedge= em->totedge;
+ me->totface= em->totface;
+
+ CustomData_copy(&em->vdata, &me->vdata, CD_MASK_MESH, CD_CALLOC, me->totvert);
+ CustomData_copy(&em->edata, &me->edata, CD_MASK_MESH, CD_CALLOC, me->totedge);
+ CustomData_copy(&em->fdata, &me->fdata, CD_MASK_MESH, CD_CALLOC, me->totface);
+
+ CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert);
+ CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge);
+ CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, mface, me->totface);
+ mesh_update_customdata_pointers(me);
+
+ /* the vertices, use ->tmp.l as counter */
+ eve= em->verts.first;
+ a= 0;
+
+ /* check for point cache editing */
+ cacheedit= editmesh_pointcache_edit(scene, ob, em->totvert, &pid, cachemat, 1);
+
+ while(eve) {
+ if(cacheedit) {
+ if(pid.type == PTCACHE_TYPE_CLOTH) {
+ clmd= (ClothModifierData*)pid.data;
+ cloth= clmd->clothObject;
+
+ /* assign position */
+ VECCOPY(cacheco, cloth->verts[a].x)
+ VECCOPY(cloth->verts[a].x, eve->co);
+ Mat4MulVecfl(cachemat, cloth->verts[a].x);
+
+ /* find plausible velocity, not physical correct but gives
+ * nicer results when commented */
+ VECSUB(cacheco, cloth->verts[a].x, cacheco);
+ VecMulf(cacheco, clmd->sim_parms->stepsPerFrame*10.0f);
+ VECADD(cloth->verts[a].v, cloth->verts[a].v, cacheco);
+ }
+ else if(pid.type == PTCACHE_TYPE_SOFTBODY) {
+ sb= (SoftBody*)pid.data;
+
+ /* assign position */
+ VECCOPY(cacheco, sb->bpoint[a].pos)
+ VECCOPY(sb->bpoint[a].pos, eve->co);
+ Mat4MulVecfl(cachemat, sb->bpoint[a].pos);
+
+ /* changing velocity for softbody doesn't seem to give
+ * good results? */
+#if 0
+ VECSUB(cacheco, sb->bpoint[a].pos, cacheco);
+ VecMulf(cacheco, sb->minloops*10.0f);
+ VECADD(sb->bpoint[a].vec, sb->bpoint[a].pos, cacheco);
+#endif
+ }
+
+ if(oldverts)
+ VECCOPY(mvert->co, oldverts[a].co)
+ }
+ else
+ VECCOPY(mvert->co, eve->co);
+
+ mvert->mat_nr= 255; /* what was this for, halos? */
+
+ /* vertex normal */
+ VECCOPY(nor, eve->no);
+ VecMulf(nor, 32767.0);
+ VECCOPY(mvert->no, nor);
+
+ /* note: it used to remove me->dvert when it was not in use, cancelled
+ that... annoying when you have a fresh vgroup */
+ CustomData_from_em_block(&em->vdata, &me->vdata, eve->data, a);
+
+ eve->tmp.l = a++; /* counter */
+
+ mvert->flag= 0;
+ mvert->flag |= (eve->f & SELECT);
+ if (eve->h) mvert->flag |= ME_HIDE;
+
+ mvert->bweight= (char)(255.0*eve->bweight);
+
+ eve= eve->next;
+ mvert++;
+ }
+
+ /* write changes to cache */
+ if(cacheedit) {
+ if(pid.type == PTCACHE_TYPE_CLOTH)
+ cloth_write_cache(ob, pid.data, pid.cache->editframe);
+ else if(pid.type == PTCACHE_TYPE_SOFTBODY)
+ sbWriteCache(ob, pid.cache->editframe);
+ }
+
+ /* the edges */
+ a= 0;
+ eed= em->edges.first;
+ while(eed) {
+ medge->v1= (unsigned int) eed->v1->tmp.l;
+ medge->v2= (unsigned int) eed->v2->tmp.l;
+
+ medge->flag= (eed->f & SELECT) | ME_EDGERENDER;
+ if(eed->f2<2) medge->flag |= ME_EDGEDRAW;
+ if(eed->f2==0) medge->flag |= ME_LOOSEEDGE;
+ if(eed->sharp) medge->flag |= ME_SHARP;
+ if(eed->seam) medge->flag |= ME_SEAM;
+ if(eed->h & EM_FGON) medge->flag |= ME_FGON; // different defines yes
+ if(eed->h & 1) medge->flag |= ME_HIDE;
+
+ medge->crease= (char)(255.0*eed->crease);
+ medge->bweight= (char)(255.0*eed->bweight);
+ CustomData_from_em_block(&em->edata, &me->edata, eed->data, a);
+
+ eed->tmp.l = a++;
+
+ medge++;
+ eed= eed->next;
+ }
+
+ /* the faces */
+ a = 0;
+ efa= em->faces.first;
+ efa_act= EM_get_actFace(em, 0);
+ i = 0;
+ me->act_face = -1;
+ while(efa) {
+ mface= &((MFace *) me->mface)[i];
+
+ mface->v1= (unsigned int) efa->v1->tmp.l;
+ mface->v2= (unsigned int) efa->v2->tmp.l;
+ mface->v3= (unsigned int) efa->v3->tmp.l;
+ if (efa->v4) mface->v4 = (unsigned int) efa->v4->tmp.l;
+
+ mface->mat_nr= efa->mat_nr;
+
+ mface->flag= efa->flag;
+ /* bit 0 of flag is already taken for smooth... */
+
+ if(efa->h) {
+ mface->flag |= ME_HIDE;
+ mface->flag &= ~ME_FACE_SEL;
+ } else {
+ if(efa->f & 1) mface->flag |= ME_FACE_SEL;
+ else mface->flag &= ~ME_FACE_SEL;
+ }
+
+ /* mat_nr in vertex */
+ if(me->totcol>1) {
+ mvert= me->mvert+mface->v1;
+ if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
+ mvert= me->mvert+mface->v2;
+ if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
+ mvert= me->mvert+mface->v3;
+ if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
+ if(mface->v4) {
+ mvert= me->mvert+mface->v4;
+ if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
+ }
+ }
+
+ /* watch: efa->e1->f2==0 means loose edge */
+
+ if(efa->e1->f2==1) {
+ efa->e1->f2= 2;
+ }
+ if(efa->e2->f2==1) {
+ efa->e2->f2= 2;
+ }
+ if(efa->e3->f2==1) {
+ efa->e3->f2= 2;
+ }
+ if(efa->e4 && efa->e4->f2==1) {
+ efa->e4->f2= 2;
+ }
+
+ CustomData_from_em_block(&em->fdata, &me->fdata, efa->data, i);
+
+ /* no index '0' at location 3 or 4 */
+ test_index_face(mface, &me->fdata, i, efa->v4?4:3);
+
+ if (efa_act == efa)
+ me->act_face = a;
+
+ efa->tmp.l = a++;
+ i++;
+ efa= efa->next;
+ }
+
+ /* patch hook indices and vertex parents */
+ {
+ Object *ob;
+ ModifierData *md;
+ EditVert **vertMap = NULL;
+ int i,j;
+
+ for (ob=G.main->object.first; ob; ob=ob->id.next) {
+ if (ob->parent==ob && ELEM(ob->partype, PARVERT1,PARVERT3)) {
+
+ /* duplicate code from below, make it function later...? */
+ if (!vertMap) {
+ vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");
+
+ for (eve=em->verts.first; eve; eve=eve->next) {
+ if (eve->keyindex!=-1)
+ vertMap[eve->keyindex] = eve;
+ }
+ }
+ if(ob->par1 < ototvert) {
+ eve = vertMap[ob->par1];
+ if(eve) ob->par1= eve->tmp.l;
+ }
+ if(ob->par2 < ototvert) {
+ eve = vertMap[ob->par2];
+ if(eve) ob->par2= eve->tmp.l;
+ }
+ if(ob->par3 < ototvert) {
+ eve = vertMap[ob->par3];
+ if(eve) ob->par3= eve->tmp.l;
+ }
+
+ }
+ if (ob->data==me) {
+ for (md=ob->modifiers.first; md; md=md->next) {
+ if (md->type==eModifierType_Hook) {
+ HookModifierData *hmd = (HookModifierData*) md;
+
+ if (!vertMap) {
+ vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");
+
+ for (eve=em->verts.first; eve; eve=eve->next) {
+ if (eve->keyindex!=-1)
+ vertMap[eve->keyindex] = eve;
+ }
+ }
+
+ for (i=j=0; i<hmd->totindex; i++) {
+ if(hmd->indexar[i] < ototvert) {
+ eve = vertMap[hmd->indexar[i]];
+
+ if (eve) {
+ hmd->indexar[j++] = eve->tmp.l;
+ }
+ }
+ else j++;
+ }
+
+ hmd->totindex = j;
+ }
+ }
+ }
+ }
+
+ if (vertMap) MEM_freeN(vertMap);
+ }
+
+ /* are there keys? */
+ if(me->key) {
+ KeyBlock *currkey, *actkey = ob_get_keyblock(ob);
+
+ /* Lets reorder the key data so that things line up roughly
+ * with the way things were before editmode */
+ currkey = me->key->block.first;
+ while(currkey) {
+
+ fp= newkey= MEM_callocN(me->key->elemsize*em->totvert, "currkey->data");
+ oldkey = currkey->data;
+
+ eve= em->verts.first;
+
+ i = 0;
+ mvert = me->mvert;
+ while(eve) {
+ if (eve->keyindex >= 0 && eve->keyindex < currkey->totelem) { // valid old vertex
+ if(currkey == actkey) {
+ if (actkey == me->key->refkey) {
+ VECCOPY(fp, mvert->co);
+ }
+ else {
+ VECCOPY(fp, mvert->co);
+ if(oldverts) {
+ VECCOPY(mvert->co, oldverts[eve->keyindex].co);
+ }
+ }
+ }
+ else {
+ if(oldkey) {
+ VECCOPY(fp, oldkey + 3 * eve->keyindex);
+ }
+ }
+ }
+ else {
+ VECCOPY(fp, mvert->co);
+ }
+ fp+= 3;
+ ++i;
+ ++mvert;
+ eve= eve->next;
+ }
+ currkey->totelem= em->totvert;
+ if(currkey->data) MEM_freeN(currkey->data);
+ currkey->data = newkey;
+
+ currkey= currkey->next;
+ }
+ }
+
+ if(oldverts) MEM_freeN(oldverts);
+
+ i = 0;
+ for(ese=em->selected.first; ese; ese=ese->next) i++;
+ me->totselect = i;
+ if(i==0) mselect= NULL;
+ else mselect= MEM_callocN(i*sizeof(MSelect), "loadeditMesh selections");
+
+ if(me->mselect) MEM_freeN(me->mselect);
+ me->mselect= mselect;
+
+ for(ese=em->selected.first; ese; ese=ese->next){
+ mselect->type = ese->type;
+ if(ese->type == EDITVERT) mselect->index = ((EditVert*)ese->data)->tmp.l;
+ else if(ese->type == EDITEDGE) mselect->index = ((EditEdge*)ese->data)->tmp.l;
+ else if(ese->type == EDITFACE) mselect->index = ((EditFace*)ese->data)->tmp.l;
+ mselect++;
+ }
+
+ /* to be sure: clear ->tmp.l pointers */
+ eve= em->verts.first;
+ while(eve) {
+ eve->tmp.l = 0;
+ eve= eve->next;
+ }
+
+ eed= em->edges.first;
+ while(eed) {
+ eed->tmp.l = 0;
+ eed= eed->next;
+ }
+
+ efa= em->faces.first;
+ while(efa) {
+ efa->tmp.l = 0;
+ efa= efa->next;
+ }
+
+ /* remake softbody of all users */
+ if(me->id.us>1) {
+ Base *base;
+ for(base= scene->base.first; base; base= base->next)
+ if(base->object->data==me)
+ base->object->recalc |= OB_RECALC_DATA;
+ }
+
+ mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+}
+
+void remake_editMesh(Scene *scene, Object *ob)
+{
+ make_editMesh(scene, ob);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ BIF_undo_push("Undo all changes");
+}
+
+/* *************** Operator: separate parts *************/
+
+static EnumPropertyItem prop_separate_types[] = {
+ {0, "SELECTED", "Selection", ""},
+ {1, "MATERIAL", "By Material", ""},
+ {2, "LOOSE", "By loose parts", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* return 1: success */
+static int mesh_separate_selected(Scene *scene, Base *editbase)
+{
+ EditMesh *em, *emnew;
+ EditVert *eve, *v1;
+ EditEdge *eed, *e1;
+ EditFace *efa, *f1;
+ Object *obedit;
+ Mesh *me, *menew;
+ Base *basenew;
+
+ if(editbase==NULL) return 0;
+
+ obedit= editbase->object;
+ me= obedit->data;
+ em= BKE_mesh_get_editmesh(me);
+ if(me->key) {
+ error("Can't separate with vertex keys");
+ BKE_mesh_end_editmesh(me, em);
+ return 0;
+ }
+
+ if(em->selected.first)
+ BLI_freelistN(&(em->selected)); /* clear the selection order */
+
+ EM_selectmode_set(em); // enforce full consistent selection flags
+
+ EM_stats_update(em);
+
+ if(em->totvertsel==0) {
+ BKE_mesh_end_editmesh(me, em);
+ return 0;
+ }
+
+ /* we are going to work as follows:
+ * 1. add a linked duplicate object: this will be the new one, we remember old pointer
+ * 2. give new object empty mesh and put in editmode
+ * 3: do a split if needed on current editmesh.
+ * 4. copy over: all NOT selected verts, edges, faces
+ * 5. call load_editMesh() on the new object
+ */
+
+ /* 1 */
+ basenew= ED_object_add_duplicate(scene, editbase, 0); /* 0 = fully linked */
+ ED_base_object_select(basenew, BA_DESELECT);
+
+ /* 2 */
+ basenew->object->data= menew= add_mesh(me->id.name); /* empty */
+ me->id.us--;
+ make_editMesh(scene, basenew->object);
+ emnew= menew->edit_mesh;
+
+ /* 3 */
+ /* SPLIT: first make duplicate */
+ adduplicateflag(em, SELECT);
+ /* SPLIT: old faces have 3x flag 128 set, delete these ones */
+ delfaceflag(em, 128);
+ /* since we do tricky things with verts/edges/faces, this makes sure all is selected coherent */
+ EM_selectmode_set(em);
+
+ /* 4 */
+ /* move over: everything that is selected */
+ for(eve= em->verts.first; eve; eve= v1) {
+ v1= eve->next;
+ if(eve->f & SELECT) {
+ BLI_remlink(&em->verts, eve);
+ BLI_addtail(&emnew->verts, eve);
+ }
+ }
+
+ for(eed= em->edges.first; eed; eed= e1) {
+ e1= eed->next;
+ if(eed->f & SELECT) {
+ BLI_remlink(&em->edges, eed);
+ BLI_addtail(&emnew->edges, eed);
+ }
+ }
+
+ for(efa= em->faces.first; efa; efa= f1) {
+ f1= efa->next;
+ if (efa == em->act_face && (efa->f & SELECT)) {
+ EM_set_actFace(em, NULL);
+ }
+
+ if(efa->f & SELECT) {
+ BLI_remlink(&em->faces, efa);
+ BLI_addtail(&emnew->faces, efa);
+ }
+ }
+
+ /* 5 */
+ load_editMesh(scene, basenew->object);
+ free_editMesh(emnew);
+
+ /* hashedges are invalid now, make new! */
+ editMesh_set_hash(em);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ DAG_object_flush_update(scene, basenew->object, OB_RECALC_DATA);
+
+ BKE_mesh_end_editmesh(me, em);
+
+ return 1;
+}
+
+/* return 1: success */
+static int mesh_separate_material(Scene *scene, Base *editbase)
+{
+ Mesh *me= editbase->object->data;
+ EditMesh *em= BKE_mesh_get_editmesh(me);
+ unsigned char curr_mat;
+
+ for (curr_mat = 1; curr_mat < editbase->object->totcol; ++curr_mat) {
+ /* clear selection, we're going to use that to select material group */
+ EM_clear_flag_all(em, SELECT);
+ /* select the material */
+ editmesh_select_by_material(em, curr_mat);
+ /* and now separate */
+ if(0==mesh_separate_selected(scene, editbase)) {
+ BKE_mesh_end_editmesh(me, em);
+ return 0;
+ }
+ }
+
+ BKE_mesh_end_editmesh(me, em);
+ return 1;
+}
+
+/* return 1: success */
+static int mesh_separate_loose(Scene *scene, Base *editbase)
+{
+ Mesh *me;
+ EditMesh *em;
+ int doit= 1;
+
+ me= editbase->object->data;
+ em= BKE_mesh_get_editmesh(me);
+
+ if(me->key) {
+ error("Can't separate with vertex keys");
+ BKE_mesh_end_editmesh(me, em);
+ return 0;
+ }
+
+ EM_clear_flag_all(em, SELECT);
+
+ while(doit && em->verts.first) {
+ /* Select a random vert to start with */
+ EditVert *eve= em->verts.first;
+ eve->f |= SELECT;
+
+ selectconnected_mesh_all(em);
+
+ /* and now separate */
+ doit= mesh_separate_selected(scene, editbase);
+ }
+
+ BKE_mesh_end_editmesh(me, em);
+ return 1;
+}
+
+
+static int mesh_separate_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Base *base= CTX_data_active_base(C);
+ int retval= 0;
+
+ if(RNA_enum_is_equal(op->ptr, "type", "SELECTED"))
+ retval= mesh_separate_selected(scene, base);
+ else if(RNA_enum_is_equal(op->ptr, "type", "MATERIAL"))
+ retval= mesh_separate_material (scene, base);
+ else if(RNA_enum_is_equal(op->ptr, "type", "LOOSE"))
+ retval= mesh_separate_loose(scene, base);
+
+ if(retval) {
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, base->object);
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_CANCELLED;
+}
+
+void MESH_OT_separate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mesh Separate";
+ ot->idname= "MESH_OT_separate";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= mesh_separate_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", prop_separate_types, 0, "Type", "");
+}
+
+
+/* ******************************************** */
+
+/* *************** UNDO ***************************** */
+/* new mesh undo, based on pushing editmesh data itself */
+/* reuses same code as for global and curve undo... unify that (ton) */
+
+/* only one 'hack', to save memory it doesn't store the first push, but does a remake editmesh */
+
+/* a compressed version of editmesh data */
+
+typedef struct EditVertC
+{
+ float no[3];
+ float co[3];
+ unsigned char f, h;
+ short bweight;
+ int keyindex;
+} EditVertC;
+
+typedef struct EditEdgeC
+{
+ int v1, v2;
+ unsigned char f, h, seam, sharp, pad;
+ short crease, bweight, fgoni;
+} EditEdgeC;
+
+typedef struct EditFaceC
+{
+ int v1, v2, v3, v4;
+ unsigned char mat_nr, flag, f, h, fgonf;
+ short pad1;
+} EditFaceC;
+
+typedef struct EditSelectionC{
+ short type;
+ int index;
+}EditSelectionC;
+
+typedef struct UndoMesh {
+ EditVertC *verts;
+ EditEdgeC *edges;
+ EditFaceC *faces;
+ EditSelectionC *selected;
+ int totvert, totedge, totface, totsel;
+ short selectmode;
+ RetopoPaintData *retopo_paint_data;
+ char retopo_mode;
+ CustomData vdata, edata, fdata;
+} UndoMesh;
+
+/* for callbacks */
+
+static void free_undoMesh(void *umv)
+{
+ UndoMesh *um= umv;
+
+ if(um->verts) MEM_freeN(um->verts);
+ if(um->edges) MEM_freeN(um->edges);
+ if(um->faces) MEM_freeN(um->faces);
+ if(um->selected) MEM_freeN(um->selected);
+// XXX if(um->retopo_paint_data) retopo_free_paint_data(um->retopo_paint_data);
+ CustomData_free(&um->vdata, um->totvert);
+ CustomData_free(&um->edata, um->totedge);
+ CustomData_free(&um->fdata, um->totface);
+ MEM_freeN(um);
+}
+
+static void *editMesh_to_undoMesh(void *emv)
+{
+ EditMesh *em= (EditMesh *)emv;
+ UndoMesh *um;
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+ EditSelection *ese;
+ EditVertC *evec=NULL;
+ EditEdgeC *eedc=NULL;
+ EditFaceC *efac=NULL;
+ EditSelectionC *esec=NULL;
+ int a;
+
+ um= MEM_callocN(sizeof(UndoMesh), "undomesh");
+
+ um->selectmode = em->selectmode;
+
+ for(eve=em->verts.first; eve; eve= eve->next) um->totvert++;
+ for(eed=em->edges.first; eed; eed= eed->next) um->totedge++;
+ for(efa=em->faces.first; efa; efa= efa->next) um->totface++;
+ for(ese=em->selected.first; ese; ese=ese->next) um->totsel++;
+ /* malloc blocks */
+
+ if(um->totvert) evec= um->verts= MEM_callocN(um->totvert*sizeof(EditVertC), "allvertsC");
+ if(um->totedge) eedc= um->edges= MEM_callocN(um->totedge*sizeof(EditEdgeC), "alledgesC");
+ if(um->totface) efac= um->faces= MEM_callocN(um->totface*sizeof(EditFaceC), "allfacesC");
+ if(um->totsel) esec= um->selected= MEM_callocN(um->totsel*sizeof(EditSelectionC), "allselections");
+
+ if(um->totvert) CustomData_copy(&em->vdata, &um->vdata, CD_MASK_EDITMESH, CD_CALLOC, um->totvert);
+ if(um->totedge) CustomData_copy(&em->edata, &um->edata, CD_MASK_EDITMESH, CD_CALLOC, um->totedge);
+ if(um->totface) CustomData_copy(&em->fdata, &um->fdata, CD_MASK_EDITMESH, CD_CALLOC, um->totface);
+
+ /* now copy vertices */
+ a = 0;
+ for(eve=em->verts.first; eve; eve= eve->next, evec++, a++) {
+ VECCOPY(evec->co, eve->co);
+ VECCOPY(evec->no, eve->no);
+
+ evec->f= eve->f;
+ evec->h= eve->h;
+ evec->keyindex= eve->keyindex;
+ eve->tmp.l = a; /*store index*/
+ evec->bweight= (short)(eve->bweight*255.0);
+
+ CustomData_from_em_block(&em->vdata, &um->vdata, eve->data, a);
+ }
+
+ /* copy edges */
+ a = 0;
+ for(eed=em->edges.first; eed; eed= eed->next, eedc++, a++) {
+ eedc->v1= (int)eed->v1->tmp.l;
+ eedc->v2= (int)eed->v2->tmp.l;
+ eedc->f= eed->f;
+ eedc->h= eed->h;
+ eedc->seam= eed->seam;
+ eedc->sharp= eed->sharp;
+ eedc->crease= (short)(eed->crease*255.0);
+ eedc->bweight= (short)(eed->bweight*255.0);
+ eedc->fgoni= eed->fgoni;
+ eed->tmp.l = a; /*store index*/
+ CustomData_from_em_block(&em->edata, &um->edata, eed->data, a);
+
+ }
+
+ /* copy faces */
+ a = 0;
+ for(efa=em->faces.first; efa; efa= efa->next, efac++, a++) {
+ efac->v1= (int)efa->v1->tmp.l;
+ efac->v2= (int)efa->v2->tmp.l;
+ efac->v3= (int)efa->v3->tmp.l;
+ if(efa->v4) efac->v4= (int)efa->v4->tmp.l;
+ else efac->v4= -1;
+
+ efac->mat_nr= efa->mat_nr;
+ efac->flag= efa->flag;
+ efac->f= efa->f;
+ efac->h= efa->h;
+ efac->fgonf= efa->fgonf;
+
+ efa->tmp.l = a; /*store index*/
+
+ CustomData_from_em_block(&em->fdata, &um->fdata, efa->data, a);
+ }
+
+ a = 0;
+ for(ese=em->selected.first; ese; ese=ese->next, esec++){
+ esec->type = ese->type;
+ if(ese->type == EDITVERT) a = esec->index = ((EditVert*)ese->data)->tmp.l;
+ else if(ese->type == EDITEDGE) a = esec->index = ((EditEdge*)ese->data)->tmp.l;
+ else if(ese->type == EDITFACE) a = esec->index = ((EditFace*)ese->data)->tmp.l;
+ }
+
+// XXX um->retopo_paint_data= retopo_paint_data_copy(em->retopo_paint_data);
+// um->retopo_mode= scene->toolsettings->retopo_mode;
+
+ return um;
+}
+
+static void undoMesh_to_editMesh(void *umv, void *emv)
+{
+ EditMesh *em= (EditMesh *)emv;
+ UndoMesh *um= (UndoMesh *)umv;
+ EditVert *eve, **evar=NULL;
+ EditEdge *eed;
+ EditFace *efa;
+ EditSelection *ese;
+ EditVertC *evec;
+ EditEdgeC *eedc;
+ EditFaceC *efac;
+ EditSelectionC *esec;
+ int a=0;
+
+ free_editMesh(em);
+
+ /* malloc blocks */
+ memset(em, 0, sizeof(EditMesh));
+
+ em->selectmode = um->selectmode;
+
+ init_editmesh_fastmalloc(em, um->totvert, um->totedge, um->totface);
+
+ CustomData_free(&em->vdata, 0);
+ CustomData_free(&em->edata, 0);
+ CustomData_free(&em->fdata, 0);
+
+ CustomData_copy(&um->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
+ CustomData_copy(&um->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0);
+ CustomData_copy(&um->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
+
+ /* now copy vertices */
+
+ if(um->totvert) evar= MEM_mallocN(um->totvert*sizeof(EditVert *), "vertex ar");
+ for(a=0, evec= um->verts; a<um->totvert; a++, evec++) {
+ eve= addvertlist(em, evec->co, NULL);
+ evar[a]= eve;
+
+ VECCOPY(eve->no, evec->no);
+ eve->f= evec->f;
+ eve->h= evec->h;
+ eve->keyindex= evec->keyindex;
+ eve->bweight= ((float)evec->bweight)/255.0f;
+
+ CustomData_to_em_block(&um->vdata, &em->vdata, a, &eve->data);
+ }
+
+ /* copy edges */
+ for(a=0, eedc= um->edges; a<um->totedge; a++, eedc++) {
+ eed= addedgelist(em, evar[eedc->v1], evar[eedc->v2], NULL);
+
+ eed->f= eedc->f;
+ eed->h= eedc->h;
+ eed->seam= eedc->seam;
+ eed->sharp= eedc->sharp;
+ eed->fgoni= eedc->fgoni;
+ eed->crease= ((float)eedc->crease)/255.0f;
+ eed->bweight= ((float)eedc->bweight)/255.0f;
+ CustomData_to_em_block(&um->edata, &em->edata, a, &eed->data);
+ }
+
+ /* copy faces */
+ for(a=0, efac= um->faces; a<um->totface; a++, efac++) {
+ if(efac->v4 != -1)
+ efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], evar[efac->v4], NULL, NULL);
+ else
+ efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], NULL, NULL ,NULL);
+
+ efa->mat_nr= efac->mat_nr;
+ efa->flag= efac->flag;
+ efa->f= efac->f;
+ efa->h= efac->h;
+ efa->fgonf= efac->fgonf;
+
+ CustomData_to_em_block(&um->fdata, &em->fdata, a, &efa->data);
+ }
+
+ end_editmesh_fastmalloc();
+ if(evar) MEM_freeN(evar);
+
+ em->totvert = um->totvert;
+ em->totedge = um->totedge;
+ em->totface = um->totface;
+ /*restore stored editselections*/
+ if(um->totsel){
+ EM_init_index_arrays(em, 1,1,1);
+ for(a=0, esec= um->selected; a<um->totsel; a++, esec++){
+ ese = MEM_callocN(sizeof(EditSelection), "Edit Selection");
+ ese->type = esec->type;
+ if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(esec->index); else
+ if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(esec->index); else
+ if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(esec->index);
+ BLI_addtail(&(em->selected),ese);
+ }
+ EM_free_index_arrays();
+ }
+
+// XXX retopo_free_paint();
+// em->retopo_paint_data= retopo_paint_data_copy(um->retopo_paint_data);
+// scene->toolsettings->retopo_mode= um->retopo_mode;
+// if(scene->toolsettings->retopo_mode) {
+// XXX if(G.vd->depths) G.vd->depths->damaged= 1;
+// retopo_queue_updates(G.vd);
+// retopo_paint_view_update(G.vd);
+// }
+
+}
+
+static void *getEditMesh(bContext *C)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ if(obedit && obedit->type==OB_MESH) {
+ Mesh *me= obedit->data;
+ return me->edit_mesh;
+ }
+ return NULL;
+}
+
+/* and this is all the undo system needs to know */
+void undo_push_mesh(bContext *C, char *name)
+{
+ undo_editmode_push(C, name, getEditMesh, free_undoMesh, undoMesh_to_editMesh, editMesh_to_undoMesh, NULL);
+}
+
+
+
+/* *************** END UNDO *************/
+
+static EditVert **g_em_vert_array = NULL;
+static EditEdge **g_em_edge_array = NULL;
+static EditFace **g_em_face_array = NULL;
+
+void EM_init_index_arrays(EditMesh *em, int forVert, int forEdge, int forFace)
+{
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+ int i;
+
+ if (forVert) {
+ em->totvert= BLI_countlist(&em->verts);
+ g_em_vert_array = MEM_mallocN(sizeof(*g_em_vert_array)*em->totvert, "em_v_arr");
+
+ for (i=0,eve=em->verts.first; eve; i++,eve=eve->next)
+ g_em_vert_array[i] = eve;
+ }
+
+ if (forEdge) {
+ em->totedge= BLI_countlist(&em->edges);
+ g_em_edge_array = MEM_mallocN(sizeof(*g_em_edge_array)*em->totedge, "em_e_arr");
+
+ for (i=0,eed=em->edges.first; eed; i++,eed=eed->next)
+ g_em_edge_array[i] = eed;
+ }
+
+ if (forFace) {
+ em->totface= BLI_countlist(&em->faces);
+ g_em_face_array = MEM_mallocN(sizeof(*g_em_face_array)*em->totface, "em_f_arr");
+
+ for (i=0,efa=em->faces.first; efa; i++,efa=efa->next)
+ g_em_face_array[i] = efa;
+ }
+}
+
+void EM_free_index_arrays(void)
+{
+ if (g_em_vert_array) MEM_freeN(g_em_vert_array);
+ if (g_em_edge_array) MEM_freeN(g_em_edge_array);
+ if (g_em_face_array) MEM_freeN(g_em_face_array);
+ g_em_vert_array = NULL;
+ g_em_edge_array = NULL;
+ g_em_face_array = NULL;
+}
+
+EditVert *EM_get_vert_for_index(int index)
+{
+ return g_em_vert_array?g_em_vert_array[index]:NULL;
+}
+
+EditEdge *EM_get_edge_for_index(int index)
+{
+ return g_em_edge_array?g_em_edge_array[index]:NULL;
+}
+
+EditFace *EM_get_face_for_index(int index)
+{
+ return g_em_face_array?g_em_face_array[index]:NULL;
+}
+
+/* can we edit UV's for this mesh?*/
+int EM_texFaceCheck(EditMesh *em)
+{
+ /* some of these checks could be a touch overkill */
+ if ( (em) &&
+ (em->faces.first) &&
+ (CustomData_has_layer(&em->fdata, CD_MTFACE)))
+ return 1;
+ return 0;
+}
+
+/* can we edit colors for this mesh?*/
+int EM_vertColorCheck(EditMesh *em)
+{
+ /* some of these checks could be a touch overkill */
+ if ( (em) &&
+ (em->faces.first) &&
+ (CustomData_has_layer(&em->fdata, CD_MCOL)))
+ return 1;
+ return 0;
+}
+
+
+void em_setup_viewcontext(bContext *C, ViewContext *vc)
+{
+ view3d_set_viewcontext(C, vc);
+
+ if(vc->obedit) {
+ Mesh *me= vc->obedit->data;
+ vc->em= me->edit_mesh;
+ }
+}
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
new file mode 100644
index 00000000000..57fb2c19c75
--- /dev/null
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -0,0 +1,1641 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.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 "DNA_windowmanager_types.h"
+
+#include "RNA_types.h"
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+#include "BKE_report.h"
+
+#include "BIF_retopo.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_util.h"
+#include "ED_view3d.h"
+#include "ED_screen.h"
+
+#include "mesh_intern.h"
+
+/* bpymenu removed XXX */
+
+/* XXX */
+#define add_numbut(a, b, c, d, e, f, g) {}
+/* XXX */
+
+static float icovert[12][3] = {
+ {0.0f,0.0f,-200.0f},
+ {144.72f, -105.144f,-89.443f},
+ {-55.277f, -170.128,-89.443f},
+ {-178.885f,0.0f,-89.443f},
+ {-55.277f,170.128f,-89.443f},
+ {144.72f,105.144f,-89.443f},
+ {55.277f,-170.128f,89.443f},
+ {-144.72f,-105.144f,89.443f},
+ {-144.72f,105.144f,89.443f},
+ {55.277f,170.128f,89.443f},
+ {178.885f,0.0f,89.443f},
+ {0.0f,0.0f,200.0f}
+};
+static short icoface[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}
+};
+
+/* *************** add-click-mesh (extrude) operator ************** */
+
+static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ViewContext vc;
+ EditVert *eve, *v1;
+ float min[3], max[3];
+ int done= 0;
+
+ em_setup_viewcontext(C, &vc);
+
+ INIT_MINMAX(min, max);
+
+ for(v1= vc.em->verts.first;v1; v1=v1->next) {
+ if(v1->f & SELECT) {
+ DO_MINMAX(v1->co, min, max);
+ done= 1;
+ }
+ }
+
+ /* call extrude? */
+ if(done) {
+ EditEdge *eed;
+ float vec[3], cent[3], mat[3][3];
+ float nor[3]= {0.0, 0.0, 0.0};
+
+ /* check for edges that are half selected, use for rotation */
+ done= 0;
+ for(eed= vc.em->edges.first; eed; eed= eed->next) {
+ if( (eed->v1->f & SELECT)+(eed->v2->f & SELECT) == SELECT ) {
+ if(eed->v1->f & SELECT) VecSubf(vec, eed->v1->co, eed->v2->co);
+ else VecSubf(vec, eed->v2->co, eed->v1->co);
+ VecAddf(nor, nor, vec);
+ done= 1;
+ }
+ }
+ if(done) Normalize(nor);
+
+ /* center */
+ VecAddf(cent, min, max);
+ VecMulf(cent, 0.5f);
+ VECCOPY(min, cent);
+
+ Mat4MulVecfl(vc.obedit->obmat, min); // view space
+ view3d_get_view_aligned_coordinate(&vc, min, event->mval);
+ Mat4Invert(vc.obedit->imat, vc.obedit->obmat);
+ Mat4MulVecfl(vc.obedit->imat, min); // back in object space
+
+ VecSubf(min, min, cent);
+
+ /* calculate rotation */
+ Mat3One(mat);
+ if(done) {
+ float dot;
+
+ VECCOPY(vec, min);
+ Normalize(vec);
+ dot= INPR(vec, nor);
+
+ if( fabs(dot)<0.999) {
+ float cross[3], si, q1[4];
+
+ Crossf(cross, nor, vec);
+ Normalize(cross);
+ dot= 0.5f*saacos(dot);
+ si= (float)sin(dot);
+ q1[0]= (float)cos(dot);
+ q1[1]= cross[0]*si;
+ q1[2]= cross[1]*si;
+ q1[3]= cross[2]*si;
+
+ QuatToMat3(q1, mat);
+ }
+ }
+
+ extrudeflag(vc.obedit, vc.em, SELECT, nor);
+ rotateflag(vc.em, SELECT, cent, mat);
+ translateflag(vc.em, SELECT, min);
+
+ recalc_editnormals(vc.em);
+ }
+ else {
+ float mat[3][3],imat[3][3];
+ float *curs= give_cursor(vc.scene, vc.v3d);
+
+ VECCOPY(min, curs);
+ view3d_get_view_aligned_coordinate(&vc, min, event->mval);
+
+ eve= addvertlist(vc.em, 0, NULL);
+
+ Mat3CpyMat4(mat, vc.obedit->obmat);
+ Mat3Inv(imat, mat);
+
+ VECCOPY(eve->co, min);
+ Mat3MulVecfl(imat, eve->co);
+ VecSubf(eve->co, eve->co, vc.obedit->obmat[3]);
+
+ eve->f= SELECT;
+ }
+
+ //retopo_do_all();
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
+ DAG_object_flush_update(vc.scene, vc.obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Duplicate or Extrude at 3D Cursor";
+ ot->idname= "MESH_OT_dupli_extrude_cursor";
+
+ /* api callbacks */
+ ot->invoke= dupli_extrude_cursor;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+/* ********************** */
+
+/* selected faces get hidden edges */
+int make_fgon(EditMesh *em, wmOperator *op, int make)
+{
+ EditFace *efa;
+ EditEdge *eed;
+ EditVert *eve;
+ float *nor=NULL; // reference
+ int done=0;
+
+ if(make==0) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ efa->fgonf= 0;
+ efa->e1->h &= ~EM_FGON;
+ efa->e2->h &= ~EM_FGON;
+ efa->e3->h &= ~EM_FGON;
+ if(efa->e4) efa->e4->h &= ~EM_FGON;
+ done= 1;
+ }
+ }
+ EM_fgon_flags(em); // redo flags and indices for fgons
+
+ return done;
+ }
+
+ /* tagging edges. rule is:
+ - edge used by exactly 2 selected faces
+ - no vertices allowed with only tagged edges (return)
+ - face normals are allowed to difffer
+
+ */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->f1= 0; // amount of selected
+ eed->f2= 0; // amount of unselected
+ }
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ if(nor==NULL) nor= efa->n;
+ if(efa->e1->f1 < 3) efa->e1->f1++;
+ if(efa->e2->f1 < 3) efa->e2->f1++;
+ if(efa->e3->f1 < 3) efa->e3->f1++;
+ if(efa->e4 && efa->e4->f1 < 3) efa->e4->f1++;
+ }
+ else {
+ if(efa->e1->f2 < 3) efa->e1->f2++;
+ if(efa->e2->f2 < 3) efa->e2->f2++;
+ if(efa->e3->f2 < 3) efa->e3->f2++;
+ if(efa->e4 && efa->e4->f2 < 3) efa->e4->f2++;
+ }
+ }
+ // now eed->f1 becomes tagged edge
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f1==2 && eed->f2==0) eed->f1= 1;
+ else eed->f1= 0;
+ }
+
+ // no vertices allowed with only tagged edges
+ for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f1) {
+ eed->v1->f1 |= 1;
+ eed->v2->f1 |= 1;
+ }
+ else {
+ eed->v1->f1 |= 2;
+ eed->v2->f1 |= 2;
+ }
+ }
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f1==1) break;
+ }
+ if(eve) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot make a polygon with interior vertices");
+ return 0;
+ }
+
+ // check for faces
+ if(nor==NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No faces were selected to make FGon");
+ return 0;
+ }
+
+ // and there we go
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f1) {
+ eed->h |= EM_FGON;
+ done= 1;
+ }
+ }
+
+ if(done)
+ EM_fgon_flags(em); // redo flags and indices for fgons
+ return done;
+}
+
+static int make_fgon_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+
+ if( make_fgon(em, op, 1) ) {
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+}
+
+void MESH_OT_fgon_make(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Make F-gon";
+ ot->idname= "MESH_OT_fgon_make";
+
+ /* api callbacks */
+ ot->exec= make_fgon_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int clear_fgon_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+
+ if( make_fgon(em, op, 0) ) {
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+}
+
+void MESH_OT_fgon_clear(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Clear F-gon";
+ ot->idname= "MESH_OT_fgon_clear";
+
+ /* api callbacks */
+ ot->exec= clear_fgon_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* precondition; 4 vertices selected, check for 4 edges and create face */
+static EditFace *addface_from_edges(EditMesh *em)
+{
+ EditEdge *eed, *eedar[4]={NULL, NULL, NULL, NULL};
+ EditVert *v1=NULL, *v2=NULL, *v3=NULL, *v4=NULL;
+ int a;
+
+ /* find the 4 edges */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if( (eed->f & SELECT) || (eed->v1->f & eed->v2->f & SELECT) ) {
+ if(eedar[0]==NULL) eedar[0]= eed;
+ else if(eedar[1]==NULL) eedar[1]= eed;
+ else if(eedar[2]==NULL) eedar[2]= eed;
+ else eedar[3]= eed;
+
+ }
+ }
+
+
+ if(eedar[3]) {
+ /* first 2 points */
+ v1= eedar[0]->v1;
+ v2= eedar[0]->v2;
+
+ /* find the 2 edges connected to first edge */
+ for(a=1; a<4; a++) {
+ if( eedar[a]->v1 == v2) v3= eedar[a]->v2;
+ else if(eedar[a]->v2 == v2) v3= eedar[a]->v1;
+ else if( eedar[a]->v1 == v1) v4= eedar[a]->v2;
+ else if(eedar[a]->v2 == v1) v4= eedar[a]->v1;
+ }
+
+ /* verify if last edge exists */
+ if(v3 && v4) {
+ for(a=1; a<4; a++) {
+ if( eedar[a]->v1==v3 && eedar[a]->v2==v4) break;
+ if( eedar[a]->v2==v3 && eedar[a]->v1==v4) break;
+ }
+ if(a!=4) {
+ return addfacelist(em, v1, v2, v3, v4, NULL, NULL);
+ }
+ }
+ }
+ return NULL;
+}
+
+/* ******************************* */
+
+/* this also allows to prevent triangles being made in quads */
+static int compareface_overlaps(EditFace *vl1, EditFace *vl2)
+{
+ EditVert *v1, *v2, *v3, *v4;
+ int equal= 0;
+
+ v1= vl2->v1;
+ v2= vl2->v2;
+ v3= vl2->v3;
+ v4= vl2->v4;
+
+ if(vl1==vl2) return 0;
+
+ if(v4==NULL && vl1->v4==NULL) {
+ if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1) equal++;
+ if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2) equal++;
+ if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3) equal++;
+ }
+ else {
+ if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1 || vl1->v4==v1) equal++;
+ if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2 || vl1->v4==v2) equal++;
+ if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3 || vl1->v4==v3) equal++;
+ if(vl1->v1==v4 || vl1->v2==v4 || vl1->v3==v4 || vl1->v4==v4) equal++;
+ }
+
+ if(v4 && vl1->v4) {
+ if(equal==4) return 1;
+ }
+ else
+ if(equal>=3) return 1;
+
+ return 0;
+}
+
+/* checks for existance, and for tria overlapping inside quad */
+static EditFace *exist_face_overlaps(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4)
+{
+ EditFace *efa, efatest;
+
+ efatest.v1= v1;
+ efatest.v2= v2;
+ efatest.v3= v3;
+ efatest.v4= v4;
+
+ efa= em->faces.first;
+ while(efa) {
+ if(compareface_overlaps(&efatest, efa)) return efa;
+ efa= efa->next;
+ }
+ return NULL;
+}
+
+/* will be new face smooth or solid? depends on smoothness of face neighbours
+ * of new face, if function return 1, then new face will be smooth, when functio
+ * will return zero, then new face will be solid */
+static void fix_new_face(EditMesh *em, EditFace *eface)
+{
+ struct EditFace *efa;
+ struct EditEdge *eed=NULL;
+ struct EditVert *v1 = eface->v1, *v2 = eface->v2, *v3 = eface->v3, *v4 = eface->v4;
+ struct EditVert *ev1=NULL, *ev2=NULL;
+ short smooth=0; /* "total smoothnes" of faces in neighbourhood */
+ short coef; /* "weight" of smoothness */
+ short count=0; /* number of edges with same direction as eface */
+ short vi00=0, vi01=0, vi10=0, vi11=0; /* vertex indexes */
+
+ efa = em->faces.first;
+
+ while(efa) {
+
+ if(efa==eface) {
+ efa = efa->next;
+ continue;
+ }
+
+ coef = 0;
+ ev1 = ev2 = NULL;
+ eed = NULL;
+
+ if(efa->v1==v1 || efa->v2==v1 || efa->v3==v1 || efa->v4==v1) {
+ ev1 = v1;
+ coef++;
+ }
+ if(efa->v1==v2 || efa->v2==v2 || efa->v3==v2 || efa->v4==v2) {
+ if(ev1) ev2 = v2;
+ else ev1 = v2;
+ coef++;
+ }
+ if(efa->v1==v3 || efa->v2==v3 || efa->v3==v3 || efa->v4==v3) {
+ if(coef<2) {
+ if(ev1) ev2 = v3;
+ else ev1 = v3;
+ }
+ coef++;
+ }
+ if((v4) && (efa->v1==v4 || efa->v2==v4 || efa->v3==v4 || efa->v4==v4)) {
+ if(ev1 && coef<2) ev2 = v4;
+ coef++;
+ }
+
+ /* "democracy" of smoothness */
+ if(efa->flag & ME_SMOOTH)
+ smooth += coef;
+ else
+ smooth -= coef;
+
+ /* try to find edge using vertexes ev1 and ev2 */
+ if((ev1) && (ev2) && (ev1!=ev2)) eed = findedgelist(em, ev1, ev2);
+
+ /* has bordering edge of efa same direction as edge of eface ? */
+ if(eed) {
+ if(eed->v1==v1) vi00 = 1;
+ else if(eed->v1==v2) vi00 = 2;
+ else if(eed->v1==v3) vi00 = 3;
+ else if(v4 && eed->v1==v4) vi00 = 4;
+
+ if(eed->v2==v1) vi01 = 1;
+ else if(eed->v2==v2) vi01 = 2;
+ else if(eed->v2==v3) vi01 = 3;
+ else if(v4 && eed->v2==v4) vi01 = 4;
+
+ if(v4) {
+ if(vi01==1 && vi00==4) vi00 = 0;
+ if(vi01==4 && vi00==1) vi01 = 0;
+ }
+ else {
+ if(vi01==1 && vi00==3) vi00 = 0;
+ if(vi01==3 && vi00==1) vi01 = 0;
+ }
+
+ if(eed->v1==efa->v1) vi10 = 1;
+ else if(eed->v1==efa->v2) vi10 = 2;
+ else if(eed->v1==efa->v3) vi10 = 3;
+ else if(efa->v4 && eed->v1==efa->v4) vi10 = 4;
+
+ if(eed->v2==efa->v1) vi11 = 1;
+ else if(eed->v2==efa->v2) vi11 = 2;
+ else if(eed->v2==efa->v3) vi11 = 3;
+ else if(efa->v4 && eed->v2==efa->v4) vi11 = 4;
+
+ if(efa->v4) {
+ if(vi11==1 && vi10==4) vi10 = 0;
+ if(vi11==4 && vi10==1) vi11 = 0;
+ }
+ else {
+ if(vi11==1 && vi10==3) vi10 = 0;
+ if(vi11==3 && vi10==1) vi11 = 0;
+ }
+
+ if(((vi00>vi01) && (vi10>vi11)) ||
+ ((vi00<vi01) && (vi10<vi11)))
+ count++;
+ else
+ count--;
+ }
+
+ efa = efa->next;
+ }
+
+ /* set up smoothness according voting of face in neighbourhood */
+ if(smooth >= 0)
+ eface->flag |= ME_SMOOTH;
+ else
+ eface->flag &= ~ME_SMOOTH;
+
+ /* flip face, when too much "face normals" in neighbourhood is different */
+ if(count > 0) {
+ flipface(em, eface);
+ }
+}
+
+/* only adds quads or trias when there's edges already */
+void addfaces_from_edgenet(EditMesh *em)
+{
+ EditVert *eve1, *eve2, *eve3, *eve4;
+
+ for(eve1= em->verts.first; eve1; eve1= eve1->next) {
+ for(eve2= em->verts.first; (eve1->f & 1) && eve2; eve2= eve2->next) {
+ if(findedgelist(em, eve1,eve2)) {
+ for(eve3= em->verts.first; (eve2->f & 1) && eve3; eve3= eve3->next) {
+ if((eve2!=eve3 && (eve3->f & 1) && findedgelist(em, eve1,eve3))) {
+ EditEdge *sh_edge= NULL;
+ EditVert *sh_vert= NULL;
+
+ sh_edge= findedgelist(em, eve2,eve3);
+
+ if(sh_edge) { /* Add a triangle */
+ if(!exist_face_overlaps(em, eve1,eve2,eve3,NULL))
+ fix_new_face(em, addfacelist(em, eve1,eve2,eve3,NULL,NULL,NULL));
+ }
+ else { /* Check for a shared vertex */
+ for(eve4= em->verts.first; eve4; eve4= eve4->next) {
+ if(eve4!=eve1 && eve4!=eve2 && eve4!=eve3 && (eve4->f & 1) &&
+ !findedgelist(em, eve1,eve4) && findedgelist(em, eve2,eve4) &&
+ findedgelist(em, eve3,eve4)) {
+ sh_vert= eve4;
+ break;
+ }
+ }
+
+ if(sh_vert) {
+ if(sh_vert) {
+ if(!exist_face_overlaps(em, eve1,eve2,eve4,eve3))
+ fix_new_face(em, addfacelist(em, eve1,eve2,eve4,eve3,NULL,NULL));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ EM_select_flush(em);
+
+// XXX DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+}
+
+static void addedgeface_mesh(EditMesh *em, wmOperator *op)
+{
+ EditVert *eve, *neweve[4];
+ EditEdge *eed;
+ EditFace *efa;
+ short amount=0;
+
+ /* how many selected ? */
+ if(em->selectmode & SCE_SELECT_EDGE) {
+ /* in edge mode finding selected vertices means flushing down edge codes... */
+ /* can't make face with only edge selection info... */
+ EM_selectmode_set(em);
+ }
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f & SELECT) {
+ amount++;
+ if(amount>4) break;
+ neweve[amount-1]= eve;
+ }
+ }
+
+ if(amount==2) {
+ eed= addedgelist(em, neweve[0], neweve[1], NULL);
+ EM_select_edge(eed, 1);
+
+ // XXX DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ return;
+ }
+ else if(amount > 4) {
+ addfaces_from_edgenet(em);
+ return;
+ }
+ else if(amount<2) {
+ BKE_report(op->reports, RPT_ERROR, "More vertices are needed to make an edge/face");
+ return;
+ }
+
+ efa= NULL; // check later
+
+ if(amount==3) {
+
+ if(exist_face_overlaps(em, neweve[0], neweve[1], neweve[2], NULL)==0) {
+ efa= addfacelist(em, neweve[0], neweve[1], neweve[2], 0, NULL, NULL);
+ EM_select_face(efa, 1);
+ }
+ else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face");
+ }
+ else if(amount==4) {
+ /* this test survives when theres 2 triangles */
+ if(exist_face(em, neweve[0], neweve[1], neweve[2], neweve[3])==0) {
+ int tria= 0;
+
+ /* remove trias if they exist, 4 cases.... */
+ if(exist_face(em, neweve[0], neweve[1], neweve[2], NULL)) tria++;
+ if(exist_face(em, neweve[0], neweve[1], neweve[3], NULL)) tria++;
+ if(exist_face(em, neweve[0], neweve[2], neweve[3], NULL)) tria++;
+ if(exist_face(em, neweve[1], neweve[2], neweve[3], NULL)) tria++;
+
+ if(tria==2) join_triangles(em);
+ else if(exist_face_overlaps(em, neweve[0], neweve[1], neweve[2], neweve[3])==0) {
+ /* If there are 4 Verts, But more selected edges, we need to call addfaces_from_edgenet */
+ EditEdge *eedcheck;
+ int count;
+ count = 0;
+ for(eedcheck= em->edges.first; eedcheck; eedcheck= eedcheck->next) {
+ if(eedcheck->f & SELECT) {
+ count++;
+ }
+ }
+
+ if(count++ > 4){
+ addfaces_from_edgenet(em);
+ return;
+ } else {
+ /* if 4 edges exist, we just create the face, convex or not */
+ efa= addface_from_edges(em);
+ if(efa==NULL) {
+
+ /* the order of vertices can be anything, 6 cases to check */
+ if( convex(neweve[0]->co, neweve[1]->co, neweve[2]->co, neweve[3]->co) ) {
+ efa= addfacelist(em, neweve[0], neweve[1], neweve[2], neweve[3], NULL, NULL);
+ }
+ else if( convex(neweve[0]->co, neweve[2]->co, neweve[3]->co, neweve[1]->co) ) {
+ efa= addfacelist(em, neweve[0], neweve[2], neweve[3], neweve[1], NULL, NULL);
+ }
+ else if( convex(neweve[0]->co, neweve[2]->co, neweve[1]->co, neweve[3]->co) ) {
+ efa= addfacelist(em, neweve[0], neweve[2], neweve[1], neweve[3], NULL, NULL);
+ }
+ else if( convex(neweve[0]->co, neweve[1]->co, neweve[3]->co, neweve[2]->co) ) {
+ efa= addfacelist(em, neweve[0], neweve[1], neweve[3], neweve[2], NULL, NULL);
+ }
+ else if( convex(neweve[0]->co, neweve[3]->co, neweve[2]->co, neweve[1]->co) ) {
+ efa= addfacelist(em, neweve[0], neweve[3], neweve[2], neweve[1], NULL, NULL);
+ }
+ else if( convex(neweve[0]->co, neweve[3]->co, neweve[1]->co, neweve[2]->co) ) {
+ efa= addfacelist(em, neweve[0], neweve[3], neweve[1], neweve[2], NULL, NULL);
+ }
+ else printf("cannot find nice quad from concave set of vertices\n");
+ }
+ }
+ }
+ else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face");
+ }
+ else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face");
+ }
+
+ if(efa) {
+ EM_select_face(efa, 1);
+
+ fix_new_face(em, efa);
+
+ recalc_editnormals(em);
+ }
+ }
+
+static int addedgeface_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+
+ addedgeface_mesh(em, op);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_edge_face_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Make Edge/Face";
+ ot->idname= "MESH_OT_edge_face_add";
+
+ /* api callbacks */
+ ot->exec= addedgeface_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+
+
+
+/* ************************ primitives ******************* */
+
+// HACK: these can also be found in cmoview.tga.c, but are here so that they can be found by linker
+// this hack is only used so that scons+mingw + split-sources hack works
+ // ------------------------------- start copied code
+/* 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},
+};
+ // ------------------------------- end copied code
+
+
+#define PRIM_PLANE 0
+#define PRIM_CUBE 1
+#define PRIM_CIRCLE 4
+#define PRIM_CYLINDER 5
+#define PRIM_CONE 7
+#define PRIM_GRID 10
+#define PRIM_UVSPHERE 11
+#define PRIM_ICOSPHERE 12
+#define PRIM_MONKEY 13
+
+static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int seg,
+ int subdiv, float dia, float depth, int ext, int fill)
+{
+ /*
+ * type - for the type of shape
+ * dia - the radius for cone,sphere cylinder etc.
+ * depth -
+ * ext - extrude
+ * fill - end capping, and option to fill in circle
+ * cent[3] - center of the data.
+ * */
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+ EditVert *eve, *v1=NULL, *v2, *v3, *v4=NULL, *vtop, *vdown;
+ float phi, phid, vec[3];
+ float q[4], cmat[3][3], nor[3]= {0.0, 0.0, 0.0};
+ short a, b;
+
+ EM_clear_flag_all(em, SELECT);
+
+ phid= 2.0f*(float)M_PI/tot;
+ phi= .25f*(float)M_PI;
+
+ switch(type) {
+ case PRIM_GRID: /* grid */
+ /* clear flags */
+ eve= em->verts.first;
+ while(eve) {
+ eve->f= 0;
+ eve= eve->next;
+ }
+ /* one segment first: the X axis */
+ phi= 1.0;
+ phid= 2.0/((float)tot-1);
+ for(a=0;a<tot;a++) {
+ vec[0]= dia*phi;
+ vec[1]= - dia;
+ vec[2]= 0.0f;
+ Mat4MulVecfl(mat,vec);
+ eve= addvertlist(em, vec, NULL);
+ eve->f= 1+2+4;
+ if (a) {
+ addedgelist(em, eve->prev, eve, NULL);
+ }
+ phi-=phid;
+ }
+ /* extrude and translate */
+ vec[0]= vec[2]= 0.0;
+ vec[1]= dia*phid;
+ Mat4Mul3Vecfl(mat, vec);
+
+ for(a=0;a<seg-1;a++) {
+ extrudeflag_vert(obedit, em, 2, nor); // nor unused
+ translateflag(em, 2, vec);
+ }
+ break;
+ case PRIM_UVSPHERE: /* UVsphere */
+
+ /* clear all flags */
+ eve= em->verts.first;
+ while(eve) {
+ eve->f= 0;
+ eve= eve->next;
+ }
+
+ /* one segment first */
+ phi= 0;
+ phid/=2;
+ for(a=0; a<=tot; a++) {
+ vec[0]= dia*sin(phi);
+ vec[1]= 0.0;
+ vec[2]= dia*cos(phi);
+ eve= addvertlist(em, vec, NULL);
+ eve->f= 1+2+4;
+ if(a==0) v1= eve;
+ else addedgelist(em, eve->prev, eve, NULL);
+ phi+= phid;
+ }
+
+ /* extrude and rotate */
+ phi= M_PI/seg;
+ q[0]= cos(phi);
+ q[3]= sin(phi);
+ q[1]=q[2]= 0;
+ QuatToMat3(q, cmat);
+
+ for(a=0; a<seg; a++) {
+ extrudeflag_vert(obedit, em, 2, nor); // nor unused
+ rotateflag(em, 2, v1->co, cmat);
+ }
+
+ removedoublesflag(em, 4, 0, 0.0001);
+
+ /* and now do imat */
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f & SELECT) {
+ Mat4MulVecfl(mat,eve->co);
+ }
+ eve= eve->next;
+ }
+ break;
+ case PRIM_ICOSPHERE: /* Icosphere */
+ {
+ EditVert *eva[12];
+ EditEdge *eed;
+
+ /* clear all flags */
+ eve= em->verts.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(em, vec, NULL);
+ eva[a]->f= 1+2;
+ }
+ for(a=0;a<20;a++) {
+ EditFace *evtemp;
+ v1= eva[ icoface[a][0] ];
+ v2= eva[ icoface[a][1] ];
+ v3= eva[ icoface[a][2] ];
+ evtemp = addfacelist(em, v1, v2, v3, 0, NULL, NULL);
+ evtemp->e1->f = 1+2;
+ evtemp->e2->f = 1+2;
+ evtemp->e3->f = 1+2;
+ }
+
+ dia*=200;
+ for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0,1,0);
+ /* and now do imat */
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f & 2) {
+ Mat4MulVecfl(mat,eve->co);
+ }
+ eve= eve->next;
+ }
+
+ // Clear the flag 2 from the edges
+ for(eed=em->edges.first;eed;eed=eed->next){
+ if(eed->f & 2){
+ eed->f &= !2;
+ }
+ }
+ }
+ break;
+ case PRIM_MONKEY: /* 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(em, v, NULL);
+ tv[i]->f |= SELECT;
+ tv[monkeynv+i]= (fabs(v[0]= -v[0])<0.001)?tv[i]:addvertlist(em, v, NULL);
+ tv[monkeynv+i]->f |= SELECT;
+ }
+ for (i=0; i<monkeynf; i++) {
+ addfacelist(em, 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, NULL);
+ addfacelist(em, 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, NULL);
+ }
+
+ MEM_freeN(tv);
+
+ /* and now do imat */
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f & SELECT) {
+ Mat4MulVecfl(mat,eve->co);
+ }
+ }
+ recalc_editnormals(em);
+ }
+ break;
+ default: /* all types except grid, sphere... */
+ if(type==PRIM_CONE);
+ else if(ext==0)
+ depth= 0.0f;
+
+ /* vertices */
+ vtop= vdown= v1= v2= 0;
+ for(b=0; b<=ext; b++) {
+ for(a=0; a<tot; a++) {
+
+ vec[0]= dia*sin(phi);
+ vec[1]= dia*cos(phi);
+ vec[2]= b?depth:-depth;
+
+ Mat4MulVecfl(mat, vec);
+ eve= addvertlist(em, vec, NULL);
+ eve->f= SELECT;
+ if(a==0) {
+ if(b==0) v1= eve;
+ else v2= eve;
+ }
+ phi+=phid;
+ }
+ }
+
+ /* center vertices */
+ /* type PRIM_CONE can only have 1 one side filled
+ * if the cone has no capping, dont add vtop */
+ if((fill && type>1) || type == PRIM_CONE) {
+ vec[0]= vec[1]= 0.0f;
+ vec[2]= -depth;
+ Mat4MulVecfl(mat, vec);
+ vdown= addvertlist(em, vec, NULL);
+ if((ext || type==PRIM_CONE) && fill) {
+ vec[0]= vec[1]= 0.0f;
+ vec[2]= depth;
+ Mat4MulVecfl(mat,vec);
+ vtop= addvertlist(em, vec, NULL);
+ }
+ } else {
+ vdown= v1;
+ vtop= v2;
+ }
+ if(vtop) vtop->f= SELECT;
+ if(vdown) vdown->f= SELECT;
+
+ /* top and bottom face */
+ if(fill || type==PRIM_CONE) {
+ if(tot==4 && (type==0 || type==1)) {
+ v3= v1->next->next;
+ if(ext) v4= v2->next->next;
+
+ addfacelist(em, v3, v1->next, v1, v3->next, NULL, NULL);
+ if(ext) addfacelist(em, v2, v2->next, v4, v4->next, NULL, NULL);
+
+ }
+ else {
+ v3= v1;
+ v4= v2;
+ for(a=1; a<tot; a++) {
+ addfacelist(em, vdown, v3, v3->next, 0, NULL, NULL);
+ v3= v3->next;
+ if(ext && fill) {
+ addfacelist(em, vtop, v4, v4->next, 0, NULL, NULL);
+ v4= v4->next;
+ }
+ }
+ if(type>1) {
+ addfacelist(em, vdown, v3, v1, 0, NULL, NULL);
+ if(ext) addfacelist(em, vtop, v4, v2, 0, NULL, NULL);
+ }
+ }
+ }
+ else if(type==PRIM_CIRCLE) { /* we need edges for a circle */
+ v3= v1;
+ for(a=1;a<tot;a++) {
+ addedgelist(em, v3, v3->next, NULL);
+ v3= v3->next;
+ }
+ addedgelist(em, v3, v1, NULL);
+ }
+ /* side faces */
+ if(ext) {
+ v3= v1;
+ v4= v2;
+ for(a=1; a<tot; a++) {
+ addfacelist(em, v3, v3->next, v4->next, v4, NULL, NULL);
+ v3= v3->next;
+ v4= v4->next;
+ }
+ addfacelist(em, v3, v1, v2, v4, NULL, NULL);
+ }
+ else if(type==PRIM_CONE && fill) {
+ /* add the bottom flat area of the cone
+ * if capping is disabled dont bother */
+ v3= v1;
+ for(a=1; a<tot; a++) {
+ addfacelist(em, vtop, v3->next, v3, 0, NULL, NULL);
+ v3= v3->next;
+ }
+ addfacelist(em, vtop, v1, v3, 0, NULL, NULL);
+ }
+ }
+
+ EM_stats_update(em);
+ /* simple selection flush OK, based on fact it's a single model */
+ EM_select_flush(em); /* flushes vertex -> edge -> face selection */
+
+ if(type!=0 && type!=13)
+ righthandfaces(em, 1); /* otherwise monkey has eyes in wrong direction */
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+}
+
+
+/* uses context to figure out transform for primitive */
+/* returns standard diameter */
+static float new_primitive_matrix(bContext *C, float primmat[][4])
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d =CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ float *curs, mat[3][3], vmat[3][3], cmat[3][3], imat[3][3];
+
+ Mat4One(primmat);
+
+ if(rv3d)
+ Mat3CpyMat4(vmat, rv3d->viewmat);
+ else
+ Mat3One(vmat);
+
+ /* inverse transform for view and object */
+ Mat3CpyMat4(mat, obedit->obmat);
+ Mat3MulMat3(cmat, vmat, mat);
+ Mat3Inv(imat, cmat);
+ Mat4CpyMat3(primmat, imat);
+
+ /* center */
+ curs= give_cursor(scene, v3d);
+ VECCOPY(primmat[3], curs);
+ Mat3Inv(imat, mat);
+ Mat3MulVecfl(imat, primmat[3]);
+ VECSUB(primmat[3], primmat[3], obedit->obmat[3]);
+
+ if(v3d) return v3d->grid;
+ return 1.0f;
+}
+
+/* ********* add primitive operators ************* */
+
+static int add_primitive_plane_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ float dia, mat[4][4];
+
+ dia= new_primitive_matrix(C, mat);
+ /* plane (diameter of 1.41 makes it unit size) */
+ dia*= sqrt(2.0f);
+
+ make_prim(obedit, PRIM_PLANE, mat, 4, 0, 0, dia, 0.0f, 0, 1);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_plane_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Plane";
+ ot->idname= "MESH_OT_primitive_plane_add";
+
+ /* api callbacks */
+ ot->exec= add_primitive_plane_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int add_primitive_cube_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ float dia, mat[4][4];
+
+ dia= new_primitive_matrix(C, mat);
+ /* plane (diameter of 1.41 makes it unit size) */
+ dia*= sqrt(2.0f);
+
+ make_prim(obedit, PRIM_CUBE, mat, 4, 0, 0, dia, 1.0f, 1, 1);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_cube_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Cube";
+ ot->idname= "MESH_OT_primitive_cube_add";
+
+ /* api callbacks */
+ ot->exec= add_primitive_cube_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int add_primitive_circle_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ float dia, mat[4][4];
+
+ dia= new_primitive_matrix(C, mat);
+ dia *= RNA_float_get(op->ptr,"radius");
+
+ make_prim(obedit, PRIM_CIRCLE, mat, RNA_int_get(op->ptr, "vertices"), 0, 0, dia, 0.0f, 0,
+ RNA_boolean_get(op->ptr, "fill"));
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_circle_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Circle";
+ ot->idname= "MESH_OT_primitive_circle_add";
+
+ /* api callbacks */
+ ot->exec= add_primitive_circle_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 3, 500);
+ RNA_def_float(ot->srna, "radius", 1.0f, -FLT_MAX, FLT_MAX, "Radius", "", 0.001, 100.00);
+ RNA_def_boolean(ot->srna, "fill", 0, "Fill", "");
+}
+
+static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ float dia, mat[4][4];
+
+ dia= new_primitive_matrix(C, mat);
+ dia *= RNA_float_get(op->ptr, "radius");
+
+ make_prim(obedit, PRIM_CYLINDER, mat, RNA_int_get(op->ptr, "vertices"), 0, 0, dia,
+ RNA_float_get(op->ptr, "depth"), 1, 1);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_cylinder_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Cylinder";
+ ot->idname= "MESH_OT_primitive_cylinder_add";
+
+ /* api callbacks */
+ ot->exec= add_primitive_cylinder_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
+ RNA_def_float(ot->srna, "radius", 1.0f, -FLT_MAX, FLT_MAX, "Radius", "", 0.001, 100.00);
+ RNA_def_float(ot->srna, "depth", 1.0f, -FLT_MAX, FLT_MAX, "Depth", "", 0.001, 100.00);
+}
+
+static int add_primitive_tube_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ float dia, mat[4][4];
+
+ dia= new_primitive_matrix(C, mat);
+ dia *= RNA_float_get(op->ptr, "radius");
+
+ make_prim(obedit, PRIM_CYLINDER, mat, RNA_int_get(op->ptr, "vertices"), 0, 0, dia,
+ RNA_float_get(op->ptr, "depth"), 1, 0);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_tube_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Tube";
+ ot->idname= "MESH_OT_primitive_tube_add";
+
+ /* api callbacks */
+ ot->exec= add_primitive_tube_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
+ RNA_def_float(ot->srna, "radius", 1.0f, -FLT_MAX, FLT_MAX, "Radius", "", 0.001, 100.00);
+ RNA_def_float(ot->srna, "depth", 1.0f, -FLT_MAX, FLT_MAX, "Depth", "", 0.001, 100.00);
+}
+
+static int add_primitive_cone_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ float dia, mat[4][4];
+
+ dia= new_primitive_matrix(C, mat);
+ dia *= RNA_float_get(op->ptr, "radius");
+
+ make_prim(obedit, PRIM_CONE, mat, RNA_int_get(op->ptr, "vertices"), 0, 0, dia,
+ RNA_float_get(op->ptr, "depth"), 0, RNA_boolean_get(op->ptr, "cap_end"));
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_cone_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Cone";
+ ot->idname= "MESH_OT_primitive_cone_add";
+
+ /* api callbacks */
+ ot->exec= add_primitive_cone_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
+ RNA_def_float(ot->srna, "radius", 1.0f, -FLT_MAX, FLT_MAX, "Radius", "", 0.001, 100.00);
+ RNA_def_float(ot->srna, "depth", 1.0f, -FLT_MAX, FLT_MAX, "Depth", "", 0.001, 100.00);
+ RNA_def_boolean(ot->srna, "cap_end", 0, "Cap End", "");
+
+}
+
+static int add_primitive_grid_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ float dia, mat[4][4];
+
+ dia= new_primitive_matrix(C, mat);
+ dia*= RNA_float_get(op->ptr, "size");
+
+ make_prim(obedit, PRIM_GRID, mat, RNA_int_get(op->ptr, "x_subdivisions"),
+ RNA_int_get(op->ptr, "y_subdivisions"), 0, dia, 0.0f, 0, 1);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_grid_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Grid";
+ ot->idname= "MESH_OT_primitive_grid_add";
+
+ /* api callbacks */
+ ot->exec= add_primitive_grid_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "x_subdivisions", 10, INT_MIN, INT_MAX, "X Subdivisions", "", 3, 1000);
+ RNA_def_int(ot->srna, "y_subdivisions", 10, INT_MIN, INT_MAX, "Y Subdivisons", "", 3, 1000);
+ RNA_def_float(ot->srna, "size", 1.0f, -FLT_MAX, FLT_MAX, "Size", "", 0.001, FLT_MAX);
+}
+
+static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ float mat[4][4];
+
+ new_primitive_matrix(C, mat);
+
+ make_prim(obedit, PRIM_MONKEY, mat, 0, 0, 2, 0.0f, 0.0f, 0, 0);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_monkey_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Monkey";
+ ot->idname= "MESH_OT_primitive_monkey_add";
+
+ /* api callbacks */
+ ot->exec= add_primitive_monkey_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ float dia, mat[4][4];
+
+ dia= new_primitive_matrix(C, mat);
+ dia*= RNA_float_get(op->ptr, "size");
+
+ make_prim(obedit, PRIM_UVSPHERE, mat, RNA_int_get(op->ptr, "rings"),
+ RNA_int_get(op->ptr, "segments"), 0, dia, 0.0f, 0, 0);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add UV Sphere";
+ ot->idname= "MESH_OT_primitive_uv_sphere_add";
+
+ /* api callbacks */
+ ot->exec= add_primitive_uvsphere_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "segments", 32, INT_MIN, INT_MAX, "Segments", "", 3, 500);
+ RNA_def_int(ot->srna, "rings", 24, INT_MIN, INT_MAX, "Rings", "", 3, 500);
+ RNA_def_float(ot->srna, "size", 1.0f, -FLT_MAX, FLT_MAX, "Size", "", 0.001, 100.00);
+}
+
+static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ float dia, mat[4][4];
+
+ dia= new_primitive_matrix(C, mat);
+ dia*= RNA_float_get(op->ptr, "size");
+
+ make_prim(obedit, PRIM_ICOSPHERE, mat, 0, 0,
+ RNA_int_get(op->ptr, "subdivisions"), dia, 0.0f, 0, 0);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Ico Sphere";
+ ot->idname= "MESH_OT_primitive_ico_sphere_add";
+
+ /* api callbacks */
+ ot->exec= add_primitive_icosphere_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "subdivisions", 2, 0, 6, "Subdivisions", "", 0, 8);
+ RNA_def_float(ot->srna, "size", 1.0f, 0.0f, FLT_MAX, "Size", "", 0.001f, 100.00);
+}
+
diff --git a/source/blender/editors/mesh/editmesh_lib.c b/source/blender/editors/mesh/editmesh_lib.c
new file mode 100644
index 00000000000..bfa381550df
--- /dev/null
+++ b/source/blender/editors/mesh/editmesh_lib.c
@@ -0,0 +1,2280 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 by Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/*
+
+editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data
+
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_utildefines.h"
+
+#include "ED_mesh.h"
+#include "ED_view3d.h"
+
+#include "mesh_intern.h"
+
+/* ****************** stats *************** */
+
+int EM_nfaces_selected(EditMesh *em)
+{
+ EditFace *efa;
+ int count= 0;
+
+ for (efa= em->faces.first; efa; efa= efa->next)
+ if (efa->f & SELECT)
+ count++;
+
+ em->totfacesel= count;
+
+ return count;
+}
+
+int EM_nedges_selected(EditMesh *em)
+{
+ EditEdge *eed;
+ int count= 0;
+
+ for (eed= em->edges.first; eed; eed= eed->next)
+ if(eed->f & SELECT)
+ count++;
+
+ em->totedgesel= count;
+
+ return count;
+}
+
+int EM_nvertices_selected(EditMesh *em)
+{
+ EditVert *eve;
+ int count= 0;
+
+ for (eve= em->verts.first; eve; eve= eve->next)
+ if (eve->f & SELECT)
+ count++;
+
+ em->totvertsel= count;
+
+ return count;
+}
+
+void EM_stats_update(EditMesh *em)
+{
+
+ em->totvert= BLI_countlist(&em->verts);
+ em->totedge= BLI_countlist(&em->edges);
+ em->totface= BLI_countlist(&em->faces);
+
+ EM_nvertices_selected(em);
+ EM_nedges_selected(em);
+ EM_nfaces_selected(em);
+}
+
+/* ************************************** */
+
+/* this replaces the active flag used in uv/face mode */
+void EM_set_actFace(EditMesh *em, EditFace *efa)
+{
+ em->act_face = efa;
+}
+
+EditFace *EM_get_actFace(EditMesh *em, int sloppy)
+{
+ if (em->act_face) {
+ return em->act_face;
+ } else if (sloppy) {
+ EditFace *efa= NULL;
+ EditSelection *ese;
+
+ ese = em->selected.last;
+ for (; ese; ese=ese->prev){
+ if(ese->type == EDITFACE) {
+ efa = (EditFace *)ese->data;
+
+ if (efa->h) efa= NULL;
+ else break;
+ }
+ }
+ if (efa==NULL) {
+ for (efa= em->faces.first; efa; efa= efa->next) {
+ if (efa->f & SELECT)
+ break;
+ }
+ }
+ return efa; /* can still be null */
+ }
+ return NULL;
+}
+
+int EM_get_actSelection(EditMesh *em, EditSelection *ese)
+{
+ EditSelection *ese_last = em->selected.last;
+ EditFace *efa = EM_get_actFace(em, 0);
+
+ ese->next = ese->prev = NULL;
+
+ if (ese_last) {
+ if (ese_last->type == EDITFACE) { /* if there is an active face, use it over the last selected face */
+ if (efa) {
+ ese->data = (void *)efa;
+ } else {
+ ese->data = ese_last->data;
+ }
+ ese->type = EDITFACE;
+ } else {
+ ese->data = ese_last->data;
+ ese->type = ese_last->type;
+ }
+ } else if (efa) { /* no */
+ ese->data = (void *)efa;
+ ese->type = EDITFACE;
+ } else {
+ ese->data = NULL;
+ return 0;
+ }
+ return 1;
+}
+
+/* ********* Selection History ************ */
+static int EM_check_selection(EditMesh *em, void *data)
+{
+ EditSelection *ese;
+
+ for(ese = em->selected.first; ese; ese = ese->next){
+ if(ese->data == data) return 1;
+ }
+
+ return 0;
+}
+
+void EM_remove_selection(EditMesh *em, void *data, int type)
+{
+ EditSelection *ese;
+ for(ese=em->selected.first; ese; ese = ese->next){
+ if(ese->data == data){
+ BLI_freelinkN(&(em->selected),ese);
+ break;
+ }
+ }
+}
+
+void EM_store_selection(EditMesh *em, void *data, int type)
+{
+ EditSelection *ese;
+ if(!EM_check_selection(em, data)){
+ ese = (EditSelection*) MEM_callocN( sizeof(EditSelection), "Edit Selection");
+ ese->type = type;
+ ese->data = data;
+ BLI_addtail(&(em->selected),ese);
+ }
+}
+
+void EM_validate_selections(EditMesh *em)
+{
+ EditSelection *ese, *nextese;
+
+ ese = em->selected.first;
+
+ while(ese){
+ nextese = ese->next;
+ if(ese->type == EDITVERT && !(((EditVert*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese);
+ else if(ese->type == EDITEDGE && !(((EditEdge*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese);
+ else if(ese->type == EDITFACE && !(((EditFace*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese);
+ ese = nextese;
+ }
+}
+
+static void EM_strip_selections(EditMesh *em)
+{
+ EditSelection *ese, *nextese;
+ if(!(em->selectmode & SCE_SELECT_VERTEX)){
+ ese = em->selected.first;
+ while(ese){
+ nextese = ese->next;
+ if(ese->type == EDITVERT) BLI_freelinkN(&(em->selected),ese);
+ ese = nextese;
+ }
+ }
+ if(!(em->selectmode & SCE_SELECT_EDGE)){
+ ese=em->selected.first;
+ while(ese){
+ nextese = ese->next;
+ if(ese->type == EDITEDGE) BLI_freelinkN(&(em->selected), ese);
+ ese = nextese;
+ }
+ }
+ if(!(em->selectmode & SCE_SELECT_FACE)){
+ ese=em->selected.first;
+ while(ese){
+ nextese = ese->next;
+ if(ese->type == EDITFACE) BLI_freelinkN(&(em->selected), ese);
+ ese = nextese;
+ }
+ }
+}
+
+/* generic way to get data from an EditSelection type
+These functions were written to be used by the Modifier widget when in Rotate about active mode,
+but can be used anywhere.
+EM_editselection_center
+EM_editselection_normal
+EM_editselection_plane
+*/
+void EM_editselection_center(float *center, EditSelection *ese)
+{
+ if (ese->type==EDITVERT) {
+ EditVert *eve= ese->data;
+ VecCopyf(center, eve->co);
+ } else if (ese->type==EDITEDGE) {
+ EditEdge *eed= ese->data;
+ VecAddf(center, eed->v1->co, eed->v2->co);
+ VecMulf(center, 0.5);
+ } else if (ese->type==EDITFACE) {
+ EditFace *efa= ese->data;
+ VecCopyf(center, efa->cent);
+ }
+}
+
+void EM_editselection_normal(float *normal, EditSelection *ese)
+{
+ if (ese->type==EDITVERT) {
+ EditVert *eve= ese->data;
+ VecCopyf(normal, eve->no);
+ } else if (ese->type==EDITEDGE) {
+ EditEdge *eed= ese->data;
+ float plane[3]; /* need a plane to correct the normal */
+ float vec[3]; /* temp vec storage */
+
+ VecAddf(normal, eed->v1->no, eed->v2->no);
+ VecSubf(plane, eed->v2->co, eed->v1->co);
+
+ /* the 2 vertex normals will be close but not at rightangles to the edge
+ for rotate about edge we want them to be at right angles, so we need to
+ do some extra colculation to correct the vert normals,
+ we need the plane for this */
+ Crossf(vec, normal, plane);
+ Crossf(normal, plane, vec);
+ Normalize(normal);
+
+ } else if (ese->type==EDITFACE) {
+ EditFace *efa= ese->data;
+ VecCopyf(normal, efa->n);
+ }
+}
+
+/* Calculate a plane that is rightangles to the edge/vert/faces normal
+also make the plane run allong an axis that is related to the geometry,
+because this is used for the manipulators Y axis.*/
+void EM_editselection_plane(float *plane, EditSelection *ese)
+{
+ if (ese->type==EDITVERT) {
+ EditVert *eve= ese->data;
+ float vec[3]={0,0,0};
+
+ if (ese->prev) { /*use previously selected data to make a usefull vertex plane */
+ EM_editselection_center(vec, ese->prev);
+ VecSubf(plane, vec, eve->co);
+ } else {
+ /* make a fake plane thats at rightangles to the normal
+ we cant make a crossvec from a vec thats the same as the vec
+ unlikely but possible, so make sure if the normal is (0,0,1)
+ that vec isnt the same or in the same direction even.*/
+ if (eve->no[0]<0.5) vec[0]=1;
+ else if (eve->no[1]<0.5) vec[1]=1;
+ else vec[2]=1;
+ Crossf(plane, eve->no, vec);
+ }
+ } else if (ese->type==EDITEDGE) {
+ EditEdge *eed= ese->data;
+
+ /*the plane is simple, it runs allong the edge
+ however selecting different edges can swap the direction of the y axis.
+ this makes it less likely for the y axis of the manipulator
+ (running along the edge).. to flip less often.
+ at least its more pradictable */
+ if (eed->v2->co[1] > eed->v1->co[1]) /*check which to do first */
+ VecSubf(plane, eed->v2->co, eed->v1->co);
+ else
+ VecSubf(plane, eed->v1->co, eed->v2->co);
+
+ } else if (ese->type==EDITFACE) {
+ EditFace *efa= ese->data;
+ float vec[3];
+ if (efa->v4) { /*if its a quad- set the plane along the 2 longest edges.*/
+ float vecA[3], vecB[3];
+ VecSubf(vecA, efa->v4->co, efa->v3->co);
+ VecSubf(vecB, efa->v1->co, efa->v2->co);
+ VecAddf(plane, vecA, vecB);
+
+ VecSubf(vecA, efa->v1->co, efa->v4->co);
+ VecSubf(vecB, efa->v2->co, efa->v3->co);
+ VecAddf(vec, vecA, vecB);
+ /*use the biggest edge length*/
+ if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
+ VecCopyf(plane, vec);
+ } else {
+ /*start with v1-2 */
+ VecSubf(plane, efa->v1->co, efa->v2->co);
+
+ /*test the edge between v2-3, use if longer */
+ VecSubf(vec, efa->v2->co, efa->v3->co);
+ if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
+ VecCopyf(plane, vec);
+
+ /*test the edge between v1-3, use if longer */
+ VecSubf(vec, efa->v3->co, efa->v1->co);
+ if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
+ VecCopyf(plane, vec);
+ }
+ }
+ Normalize(plane);
+}
+
+
+
+void EM_select_face(EditFace *efa, int sel)
+{
+ if(sel) {
+ efa->f |= SELECT;
+ efa->e1->f |= SELECT;
+ efa->e2->f |= SELECT;
+ efa->e3->f |= SELECT;
+ if(efa->e4) efa->e4->f |= SELECT;
+ efa->v1->f |= SELECT;
+ efa->v2->f |= SELECT;
+ efa->v3->f |= SELECT;
+ if(efa->v4) efa->v4->f |= SELECT;
+ }
+ else {
+ efa->f &= ~SELECT;
+ efa->e1->f &= ~SELECT;
+ efa->e2->f &= ~SELECT;
+ efa->e3->f &= ~SELECT;
+ if(efa->e4) efa->e4->f &= ~SELECT;
+ efa->v1->f &= ~SELECT;
+ efa->v2->f &= ~SELECT;
+ efa->v3->f &= ~SELECT;
+ if(efa->v4) efa->v4->f &= ~SELECT;
+ }
+}
+
+void EM_select_edge(EditEdge *eed, int sel)
+{
+ if(sel) {
+ eed->f |= SELECT;
+ eed->v1->f |= SELECT;
+ eed->v2->f |= SELECT;
+ }
+ else {
+ eed->f &= ~SELECT;
+ eed->v1->f &= ~SELECT;
+ eed->v2->f &= ~SELECT;
+ }
+}
+
+void EM_select_face_fgon(EditMesh *em, EditFace *efa, int val)
+{
+ short index=0;
+
+ if(efa->fgonf==0) EM_select_face(efa, val);
+ else {
+ if(efa->e1->fgoni) index= efa->e1->fgoni;
+ if(efa->e2->fgoni) index= efa->e2->fgoni;
+ if(efa->e3->fgoni) index= efa->e3->fgoni;
+ if(efa->v4 && efa->e4->fgoni) index= efa->e4->fgoni;
+
+ if(index==0) printf("wrong fgon select\n");
+
+ // select all ngon faces with index
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->fgonf) {
+ if(efa->e1->fgoni==index || efa->e2->fgoni==index ||
+ efa->e3->fgoni==index || (efa->e4 && efa->e4->fgoni==index) ) {
+ EM_select_face(efa, val);
+ }
+ }
+ }
+ }
+}
+
+
+/* only vertices */
+int faceselectedOR(EditFace *efa, int flag)
+{
+ if ((efa->v1->f | efa->v2->f | efa->v3->f | (efa->v4?efa->v4->f:0))&flag) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+// replace with (efa->f & SELECT)
+int faceselectedAND(EditFace *efa, int flag)
+{
+ if ((efa->v1->f & efa->v2->f & efa->v3->f & (efa->v4?efa->v4->f:flag))&flag) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void EM_clear_flag_all(EditMesh *em, int flag)
+{
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+
+ for (eve= em->verts.first; eve; eve= eve->next) eve->f &= ~flag;
+ for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~flag;
+ for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~flag;
+
+ if(flag & SELECT) {
+ BLI_freelistN(&(em->selected));
+ em->totvertsel= em->totedgesel= em->totfacesel= 0;
+ }
+}
+
+void EM_set_flag_all(EditMesh *em, int flag)
+{
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+
+ for (eve= em->verts.first; eve; eve= eve->next) if(eve->h==0) eve->f |= flag;
+ for (eed= em->edges.first; eed; eed= eed->next) if(eed->h==0) eed->f |= flag;
+ for (efa= em->faces.first; efa; efa= efa->next) if(efa->h==0) efa->f |= flag;
+
+ if(flag & SELECT) {
+ em->totvertsel= em->totvert;
+ em->totedgesel= em->totedge;
+ em->totfacesel= em->totface;
+ }
+}
+
+/* flush for changes in vertices only */
+void EM_deselect_flush(EditMesh *em)
+{
+ EditEdge *eed;
+ EditFace *efa;
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->v1->f & eed->v2->f & SELECT);
+ else eed->f &= ~SELECT;
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->v4) {
+ if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT );
+ else efa->f &= ~SELECT;
+ }
+ else {
+ if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT );
+ else efa->f &= ~SELECT;
+ }
+ }
+ EM_nedges_selected(em);
+ EM_nfaces_selected(em);
+}
+
+
+/* flush selection to edges & faces */
+
+/* this only based on coherent selected vertices, for example when adding new
+ objects. call clear_flag_all() before you select vertices to be sure it ends OK!
+
+*/
+
+void EM_select_flush(EditMesh *em)
+{
+ EditEdge *eed;
+ EditFace *efa;
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT;
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->v4) {
+ if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT ) efa->f |= SELECT;
+ }
+ else {
+ if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT ) efa->f |= SELECT;
+ }
+ }
+ EM_nedges_selected(em);
+ EM_nfaces_selected(em);
+}
+
+/* when vertices or edges can be selected, also make fgon consistent */
+static void check_fgons_selection(EditMesh *em)
+{
+ EditFace *efa, *efan;
+ EditEdge *eed;
+ ListBase *lbar;
+ int sel, desel, index, totfgon= 0;
+
+ /* count amount of fgons */
+ for(eed= em->edges.first; eed; eed= eed->next)
+ if(eed->fgoni>totfgon) totfgon= eed->fgoni;
+
+ if(totfgon==0) return;
+
+ lbar= MEM_callocN((totfgon+1)*sizeof(ListBase), "listbase array");
+
+ /* put all fgons in lbar */
+ for(efa= em->faces.first; efa; efa= efan) {
+ efan= efa->next;
+ index= efa->e1->fgoni;
+ if(index==0) index= efa->e2->fgoni;
+ if(index==0) index= efa->e3->fgoni;
+ if(index==0 && efa->e4) index= efa->e4->fgoni;
+ if(index) {
+ BLI_remlink(&em->faces, efa);
+ BLI_addtail(&lbar[index], efa);
+ }
+ }
+
+ /* now check the fgons */
+ for(index=1; index<=totfgon; index++) {
+ /* we count on vertices/faces/edges being set OK, so we only have to set ngon itself */
+ sel= desel= 0;
+ for(efa= lbar[index].first; efa; efa= efa->next) {
+ if(efa->e1->fgoni==0) {
+ if(efa->e1->f & SELECT) sel++;
+ else desel++;
+ }
+ if(efa->e2->fgoni==0) {
+ if(efa->e2->f & SELECT) sel++;
+ else desel++;
+ }
+ if(efa->e3->fgoni==0) {
+ if(efa->e3->f & SELECT) sel++;
+ else desel++;
+ }
+ if(efa->e4 && efa->e4->fgoni==0) {
+ if(efa->e4->f & SELECT) sel++;
+ else desel++;
+ }
+
+ if(sel && desel) break;
+ }
+
+ if(sel && desel) sel= 0;
+ else if(sel) sel= 1;
+ else sel= 0;
+
+ /* select/deselect and put back */
+ for(efa= lbar[index].first; efa; efa= efa->next) {
+ if(sel) efa->f |= SELECT;
+ else efa->f &= ~SELECT;
+ }
+ addlisttolist(&em->faces, &lbar[index]);
+ }
+
+ MEM_freeN(lbar);
+}
+
+
+/* flush to edges & faces */
+
+/* based on select mode it selects edges/faces
+ assumed is that verts/edges/faces were properly selected themselves
+ with the calls above
+*/
+
+void EM_selectmode_flush(EditMesh *em)
+{
+ EditEdge *eed;
+ EditFace *efa;
+
+ // flush to edges & faces
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT;
+ else eed->f &= ~SELECT;
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->v4) {
+ if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT) efa->f |= SELECT;
+ else efa->f &= ~SELECT;
+ }
+ else {
+ if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT) efa->f |= SELECT;
+ else efa->f &= ~SELECT;
+ }
+ }
+ }
+ // flush to faces
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->e4) {
+ if(efa->e1->f & efa->e2->f & efa->e3->f & efa->e4->f & SELECT) efa->f |= SELECT;
+ else efa->f &= ~SELECT;
+ }
+ else {
+ if(efa->e1->f & efa->e2->f & efa->e3->f & SELECT) efa->f |= SELECT;
+ else efa->f &= ~SELECT;
+ }
+ }
+ }
+ // make sure selected faces have selected edges too, for extrude (hack?)
+ else if(em->selectmode & SCE_SELECT_FACE) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) EM_select_face(efa, 1);
+ }
+ }
+
+ if(!(em->selectmode & SCE_SELECT_FACE))
+ check_fgons_selection(em);
+
+ EM_nvertices_selected(em);
+ EM_nedges_selected(em);
+ EM_nfaces_selected(em);
+}
+
+void EM_convertsel(EditMesh *em, short oldmode, short selectmode)
+{
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+ /*clear flags*/
+ for(eve= em->verts.first; eve; eve= eve->next) eve->f1 = 0;
+ for(eed= em->edges.first; eed; eed= eed->next) eed->f1 = 0;
+ for(efa= em->faces.first; efa; efa= efa->next) efa->f1 = 0;
+
+ /*have to find out what the selectionmode was previously*/
+ if(oldmode == SCE_SELECT_VERTEX) {
+ if(selectmode == SCE_SELECT_EDGE){
+ /*select all edges associated with every selected vertex*/
+ for(eed= em->edges.first; eed; eed= eed->next){
+ if(eed->v1->f&SELECT) eed->f1 = 1;
+ else if(eed->v2->f&SELECT) eed->f1 = 1;
+ }
+
+ for(eed= em->edges.first; eed; eed= eed->next){
+ if(eed->f1 == 1) EM_select_edge(eed,1);
+ }
+ }
+ else if(selectmode == SCE_SELECT_FACE){
+ /*select all faces associated with every selected vertex*/
+ for(efa= em->faces.first; efa; efa= efa->next){
+ if(efa->v1->f&SELECT) efa->f1 = 1;
+ else if(efa->v2->f&SELECT) efa->f1 = 1;
+ else if(efa->v3->f&SELECT) efa->f1 = 1;
+ else{
+ if(efa->v4){
+ if(efa->v4->f&SELECT) efa->f1 =1;
+ }
+ }
+ }
+ for(efa= em->faces.first; efa; efa= efa->next){
+ if(efa->f1 == 1) EM_select_face(efa,1);
+ }
+ }
+ }
+
+ if(oldmode == SCE_SELECT_EDGE){
+ if(selectmode == SCE_SELECT_FACE){
+ for(efa= em->faces.first; efa; efa= efa->next){
+ if(efa->e1->f&SELECT) efa->f1 = 1;
+ else if(efa->e2->f&SELECT) efa->f1 = 1;
+ else if(efa->e3->f&SELECT) efa->f1 = 1;
+ else if(efa->e4){
+ if(efa->e4->f&SELECT) efa->f1 = 1;
+ }
+ }
+ for(efa= em->faces.first; efa; efa= efa->next){
+ if(efa->f1 == 1) EM_select_face(efa,1);
+ }
+ }
+ }
+
+ check_fgons_selection(em);
+
+ EM_nvertices_selected(em);
+ EM_nedges_selected(em);
+ EM_nfaces_selected(em);
+}
+
+/* when switching select mode, makes sure selection is consistent for editing */
+/* also for paranoia checks to make sure edge or face mode works */
+void EM_selectmode_set(EditMesh *em)
+{
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+
+ EM_strip_selections(em); /*strip EditSelections from em->selected that are not relevant to new mode*/
+
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ /* vertices -> edges -> faces */
+ for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~SELECT;
+ for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~SELECT;
+
+ EM_select_flush(em);
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ /* deselect vertices, and select again based on edge select */
+ for(eve= em->verts.first; eve; eve= eve->next) eve->f &= ~SELECT;
+ for(eed= em->edges.first; eed; eed= eed->next)
+ if(eed->f & SELECT) EM_select_edge(eed, 1);
+ /* selects faces based on edge status */
+ EM_selectmode_flush(em);
+ }
+ else if(em->selectmode & SCE_SELECT_FACE) {
+ /* deselect eges, and select again based on face select */
+ for(eed= em->edges.first; eed; eed= eed->next) EM_select_edge(eed, 0);
+
+ for(efa= em->faces.first; efa; efa= efa->next)
+ if(efa->f & SELECT) EM_select_face(efa, 1);
+ }
+
+ EM_nvertices_selected(em);
+ EM_nedges_selected(em);
+ EM_nfaces_selected(em);
+}
+
+/* paranoia check, actually only for entering editmode. rule:
+- vertex hidden, always means edge is hidden too
+- edge hidden, always means face is hidden too
+- face hidden, dont change anything
+*/
+void EM_hide_reset(EditMesh *em)
+{
+ EditEdge *eed;
+ EditFace *efa;
+
+ for(eed= em->edges.first; eed; eed= eed->next)
+ if(eed->v1->h || eed->v2->h) eed->h |= 1;
+
+ for(efa= em->faces.first; efa; efa= efa->next)
+ if((efa->e1->h & 1) || (efa->e2->h & 1) || (efa->e3->h & 1) || (efa->e4 && (efa->e4->h & 1)))
+ efa->h= 1;
+
+}
+
+void EM_data_interp_from_verts(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *eve, float fac)
+{
+ void *src[2];
+ float w[2];
+
+ if (v1->data && v2->data) {
+ src[0]= v1->data;
+ src[1]= v2->data;
+ w[0] = 1.0f-fac;
+ w[1] = fac;
+
+ CustomData_em_interp(&em->vdata, src, w, NULL, 2, eve->data);
+ }
+}
+
+void EM_data_interp_from_faces(EditMesh *em, EditFace *efa1, EditFace *efa2, EditFace *efan, int i1, int i2, int i3, int i4)
+{
+ float w[2][4][4];
+ void *src[2];
+ int count = (efa2)? 2: 1;
+
+ if (efa1->data) {
+ /* set weights for copying from corners directly to other corners */
+ memset(w, 0, sizeof(w));
+
+ w[i1/4][0][i1%4]= 1.0f;
+ w[i2/4][1][i2%4]= 1.0f;
+ w[i3/4][2][i3%4]= 1.0f;
+ if (i4 != -1)
+ w[i4/4][3][i4%4]= 1.0f;
+
+ src[0]= efa1->data;
+ src[1]= (efa2)? efa2->data: NULL;
+
+ CustomData_em_interp(&em->fdata, src, NULL, (float*)w, count, efan->data);
+ }
+}
+
+EditFace *EM_face_from_faces(EditMesh *em, EditFace *efa1, EditFace *efa2, int i1, int i2, int i3, int i4)
+{
+ EditFace *efan;
+ EditVert **v[2];
+
+ v[0]= &efa1->v1;
+ v[1]= (efa2)? &efa2->v1: NULL;
+
+ efan= addfacelist(em, v[i1/4][i1%4], v[i2/4][i2%4], v[i3/4][i3%4],
+ (i4 == -1)? 0: v[i4/4][i4%4], efa1, NULL);
+
+ EM_data_interp_from_faces(em, efa1, efa2, efan, i1, i2, i3, i4);
+
+ return efan;
+}
+
+static void update_data_blocks(EditMesh *em, CustomData *olddata, CustomData *data)
+{
+ EditFace *efa;
+ EditVert *eve;
+ void *block;
+
+ if (data == &em->vdata) {
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ block = NULL;
+ CustomData_em_set_default(data, &block);
+ CustomData_em_copy_data(olddata, data, eve->data, &block);
+ CustomData_em_free_block(olddata, &eve->data);
+ eve->data= block;
+ }
+ }
+ else if (data == &em->fdata) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ block = NULL;
+ CustomData_em_set_default(data, &block);
+ CustomData_em_copy_data(olddata, data, efa->data, &block);
+ CustomData_em_free_block(olddata, &efa->data);
+ efa->data= block;
+ }
+ }
+}
+
+void EM_add_data_layer(EditMesh *em, CustomData *data, int type)
+{
+ CustomData olddata;
+
+ olddata= *data;
+ olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
+ CustomData_add_layer(data, type, CD_CALLOC, NULL, 0);
+
+ update_data_blocks(em, &olddata, data);
+ if (olddata.layers) MEM_freeN(olddata.layers);
+}
+
+void EM_free_data_layer(EditMesh *em, CustomData *data, int type)
+{
+ CustomData olddata;
+
+ olddata= *data;
+ olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
+ CustomData_free_layer_active(data, type, 0);
+
+ update_data_blocks(em, &olddata, data);
+ if (olddata.layers) MEM_freeN(olddata.layers);
+}
+
+/* ******** EXTRUDE ********* */
+
+static void add_normal_aligned(float *nor, float *add)
+{
+ if( INPR(nor, add) < -0.9999f)
+ VecSubf(nor, nor, add);
+ else
+ VecAddf(nor, nor, add);
+}
+
+static void set_edge_directions_f2(EditMesh *em, int val)
+{
+ EditFace *efa;
+ int do_all= 1;
+
+ /* edge directions are used for extrude, to detect direction of edges that make new faces */
+ /* we have set 'f2' flags in edges that need to get a direction set (e.g. get new face) */
+ /* the val argument differs... so we need it as arg */
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ do_all= 0;
+ if(efa->e1->f2<val) {
+ if(efa->e1->v1 == efa->v1) efa->e1->dir= 0;
+ else efa->e1->dir= 1;
+ }
+ if(efa->e2->f2<val) {
+ if(efa->e2->v1 == efa->v2) efa->e2->dir= 0;
+ else efa->e2->dir= 1;
+ }
+ if(efa->e3->f2<val) {
+ if(efa->e3->v1 == efa->v3) efa->e3->dir= 0;
+ else efa->e3->dir= 1;
+ }
+ if(efa->e4 && efa->e4->f2<val) {
+ if(efa->e4->v1 == efa->v4) efa->e4->dir= 0;
+ else efa->e4->dir= 1;
+ }
+ }
+ }
+ /* ok, no faces done... then we at least set it for exterior edges */
+ if(do_all) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->e1->v1 == efa->v1) efa->e1->dir= 0;
+ else efa->e1->dir= 1;
+ if(efa->e2->v1 == efa->v2) efa->e2->dir= 0;
+ else efa->e2->dir= 1;
+ if(efa->e3->v1 == efa->v3) efa->e3->dir= 0;
+ else efa->e3->dir= 1;
+ if(efa->e4) {
+ if(efa->e4->v1 == efa->v4) efa->e4->dir= 0;
+ else efa->e4->dir= 1;
+ }
+ }
+ }
+}
+
+/* individual face extrude */
+/* will use vertex normals for extrusion directions, so *nor is unaffected */
+short extrudeflag_face_indiv(EditMesh *em, short flag, float *nor)
+{
+ EditVert *eve, *v1, *v2, *v3, *v4;
+ EditEdge *eed;
+ EditFace *efa, *nextfa;
+
+ if(em==NULL) return 0;
+
+ /* selected edges with 1 or more selected face become faces */
+ /* selected faces each makes new faces */
+ /* always remove old faces, keeps volumes manifold */
+ /* select the new extrusion, deselect old */
+
+ /* step 1; init, count faces in edges */
+ recalc_editnormals(em);
+
+ for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0; // new select flag
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->f2= 0; // amount of unselected faces
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT);
+ else {
+ efa->e1->f2++;
+ efa->e2->f2++;
+ efa->e3->f2++;
+ if(efa->e4) efa->e4->f2++;
+ }
+ }
+
+ /* step 2: make new faces from faces */
+ for(efa= em->faces.last; efa; efa= efa->prev) {
+ if(efa->f & SELECT) {
+ v1= addvertlist(em, efa->v1->co, efa->v1);
+ v2= addvertlist(em, efa->v2->co, efa->v2);
+ v3= addvertlist(em, efa->v3->co, efa->v3);
+
+ v1->f1= v2->f1= v3->f1= 1;
+ VECCOPY(v1->no, efa->n);
+ VECCOPY(v2->no, efa->n);
+ VECCOPY(v3->no, efa->n);
+ if(efa->v4) {
+ v4= addvertlist(em, efa->v4->co, efa->v4);
+ v4->f1= 1;
+ VECCOPY(v4->no, efa->n);
+ }
+ else v4= NULL;
+
+ /* side faces, clockwise */
+ addfacelist(em, efa->v2, v2, v1, efa->v1, efa, NULL);
+ addfacelist(em, efa->v3, v3, v2, efa->v2, efa, NULL);
+ if(efa->v4) {
+ addfacelist(em, efa->v4, v4, v3, efa->v3, efa, NULL);
+ addfacelist(em, efa->v1, v1, v4, efa->v4, efa, NULL);
+ }
+ else {
+ addfacelist(em, efa->v1, v1, v3, efa->v3, efa, NULL);
+ }
+ /* top face */
+ addfacelist(em, v1, v2, v3, v4, efa, NULL);
+ }
+ }
+
+ /* step 3: remove old faces */
+ efa= em->faces.first;
+ while(efa) {
+ nextfa= efa->next;
+ if(efa->f & SELECT) {
+ BLI_remlink(&em->faces, efa);
+ free_editface(em, efa);
+ }
+ efa= nextfa;
+ }
+
+ /* step 4: redo selection */
+ EM_clear_flag_all(em, SELECT);
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f1) eve->f |= SELECT;
+ }
+
+ EM_select_flush(em);
+
+ return 'n';
+}
+
+
+/* extrudes individual edges */
+/* nor is filled with constraint vector */
+short extrudeflag_edges_indiv(EditMesh *em, short flag, float *nor)
+{
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+
+ for(eve= em->verts.first; eve; eve= eve->next) eve->tmp.v = NULL;
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->tmp.f = NULL;
+ eed->f2= ((eed->f & flag)!=0);
+ }
+
+ set_edge_directions_f2(em, 2);
+
+ /* sample for next loop */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->e1->tmp.f = efa;
+ efa->e2->tmp.f = efa;
+ efa->e3->tmp.f = efa;
+ if(efa->e4) efa->e4->tmp.f = efa;
+ }
+ /* make the faces */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f & flag) {
+ if(eed->v1->tmp.v == NULL)
+ eed->v1->tmp.v = addvertlist(em, eed->v1->co, eed->v1);
+ if(eed->v2->tmp.v == NULL)
+ eed->v2->tmp.v = addvertlist(em, eed->v2->co, eed->v2);
+
+ if(eed->dir==1)
+ addfacelist(em, eed->v1, eed->v2,
+ eed->v2->tmp.v, eed->v1->tmp.v,
+ eed->tmp.f, NULL);
+ else
+ addfacelist(em, eed->v2, eed->v1,
+ eed->v1->tmp.v, eed->v2->tmp.v,
+ eed->tmp.f, NULL);
+
+ /* for transform */
+ if(eed->tmp.f) {
+ efa = eed->tmp.f;
+ if (efa->f & SELECT) add_normal_aligned(nor, efa->n);
+ }
+ }
+ }
+ Normalize(nor);
+
+ /* set correct selection */
+ EM_clear_flag_all(em, SELECT);
+ for(eve= em->verts.last; eve; eve= eve->prev) {
+ if(eve->tmp.v) {
+ eve->tmp.v->f |= flag;
+ }
+ }
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->v1->f & eed->v2->f & flag) eed->f |= flag;
+ }
+
+ if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // g is grab
+ return 'n'; // n is for normal constraint
+}
+
+/* extrudes individual vertices */
+short extrudeflag_verts_indiv(EditMesh *em, short flag, float *nor)
+{
+ EditVert *eve;
+
+ /* make the edges */
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f & flag) {
+ eve->tmp.v = addvertlist(em, eve->co, eve);
+ addedgelist(em, eve, eve->tmp.v, NULL);
+ }
+ else eve->tmp.v = NULL;
+ }
+
+ /* set correct selection */
+ EM_clear_flag_all(em, SELECT);
+
+ for(eve= em->verts.last; eve; eve= eve->prev)
+ if (eve->tmp.v)
+ eve->tmp.v->f |= flag;
+
+ return 'g'; // g is grab
+}
+
+
+/* this is actually a recode of extrudeflag(), using proper edge/face select */
+/* hurms, doesnt use 'flag' yet, but its not called by primitive making stuff anyway */
+static short extrudeflag_edge(Object *obedit, EditMesh *em, short flag, float *nor)
+{
+ /* all select edges/faces: extrude */
+ /* old select is cleared, in new ones it is set */
+ EditVert *eve, *nextve;
+ EditEdge *eed, *nexted;
+ EditFace *efa, *nextfa, *efan;
+ short del_old= 0;
+ ModifierData *md;
+
+ if(em==NULL) return 0;
+
+ md = obedit->modifiers.first;
+
+ /* selected edges with 0 or 1 selected face become faces */
+ /* selected faces generate new faces */
+
+ /* if *one* selected face has edge with unselected face; remove old selected faces */
+
+ /* if selected edge is not used anymore; remove */
+ /* if selected vertex is not used anymore: remove */
+
+ /* select the new extrusion, deselect old */
+
+
+ /* step 1; init, count faces in edges */
+ recalc_editnormals(em);
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ eve->tmp.v = NULL;
+ eve->f1= 0;
+ }
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->f1= 0; // amount of unselected faces
+ eed->f2= 0; // amount of selected faces
+ if(eed->f & SELECT) {
+ eed->v1->f1= 1; // we call this 'selected vertex' now
+ eed->v2->f1= 1;
+ }
+ eed->tmp.f = NULL; // here we tuck face pointer, as sample
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ efa->e1->f2++;
+ efa->e2->f2++;
+ efa->e3->f2++;
+ if(efa->e4) efa->e4->f2++;
+
+ // sample for next loop
+ efa->e1->tmp.f = efa;
+ efa->e2->tmp.f = efa;
+ efa->e3->tmp.f = efa;
+ if(efa->e4) efa->e4->tmp.f = efa;
+ }
+ else {
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->e4) efa->e4->f1++;
+ }
+ }
+
+ /* If a mirror modifier with clipping is on, we need to adjust some
+ * of the cases above to handle edges on the line of symmetry.
+ */
+ for (; md; md=md->next) {
+ if (md->type==eModifierType_Mirror) {
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ if(mmd->flag & MOD_MIR_CLIPPING) {
+ float mtx[4][4];
+ if (mmd->mirror_ob) {
+ float imtx[4][4];
+ Mat4Invert(imtx, mmd->mirror_ob->obmat);
+ Mat4MulMat4(mtx, obedit->obmat, imtx);
+ }
+
+ for (eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f2 == 1) {
+ float co1[3], co2[3];
+
+ VecCopyf(co1, eed->v1->co);
+ VecCopyf(co2, eed->v2->co);
+
+ if (mmd->mirror_ob) {
+ VecMat4MulVecfl(co1, mtx, co1);
+ VecMat4MulVecfl(co2, mtx, co2);
+ }
+
+ if (mmd->flag & MOD_MIR_AXIS_X)
+ if ( (fabs(co1[0]) < mmd->tolerance) &&
+ (fabs(co2[0]) < mmd->tolerance) )
+ ++eed->f2;
+
+ if (mmd->flag & MOD_MIR_AXIS_Y)
+ if ( (fabs(co1[1]) < mmd->tolerance) &&
+ (fabs(co2[1]) < mmd->tolerance) )
+ ++eed->f2;
+
+ if (mmd->flag & MOD_MIR_AXIS_Z)
+ if ( (fabs(co1[2]) < mmd->tolerance) &&
+ (fabs(co2[2]) < mmd->tolerance) )
+ ++eed->f2;
+ }
+ }
+ }
+ }
+ }
+
+ set_edge_directions_f2(em, 2);
+
+ /* step 1.5: if *one* selected face has edge with unselected face; remove old selected faces */
+ for(efa= em->faces.last; efa; efa= efa->prev) {
+ if(efa->f & SELECT) {
+ if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1 || (efa->e4 && efa->e4->f1)) {
+ del_old= 1;
+ break;
+ }
+ }
+ }
+
+ /* step 2: make new faces from edges */
+ for(eed= em->edges.last; eed; eed= eed->prev) {
+ if(eed->f & SELECT) {
+ if(eed->f2<2) {
+ if(eed->v1->tmp.v == NULL)
+ eed->v1->tmp.v = addvertlist(em, eed->v1->co, eed->v1);
+ if(eed->v2->tmp.v == NULL)
+ eed->v2->tmp.v = addvertlist(em, eed->v2->co, eed->v2);
+
+ /* if del_old, the preferred normal direction is exact
+ * opposite as for keep old faces
+ */
+ if(eed->dir!=del_old)
+ addfacelist(em, eed->v1, eed->v2,
+ eed->v2->tmp.v, eed->v1->tmp.v,
+ eed->tmp.f, NULL);
+ else
+ addfacelist(em, eed->v2, eed->v1,
+ eed->v1->tmp.v, eed->v2->tmp.v,
+ eed->tmp.f, NULL);
+ }
+ }
+ }
+
+ /* step 3: make new faces from faces */
+ for(efa= em->faces.last; efa; efa= efa->prev) {
+ if(efa->f & SELECT) {
+ if (efa->v1->tmp.v == NULL)
+ efa->v1->tmp.v = addvertlist(em, efa->v1->co, efa->v1);
+ if (efa->v2->tmp.v ==NULL)
+ efa->v2->tmp.v = addvertlist(em, efa->v2->co, efa->v2);
+ if (efa->v3->tmp.v ==NULL)
+ efa->v3->tmp.v = addvertlist(em, efa->v3->co, efa->v3);
+ if (efa->v4 && (efa->v4->tmp.v == NULL))
+ efa->v4->tmp.v = addvertlist(em, efa->v4->co, efa->v4);
+
+ if(del_old==0) { // keep old faces means flipping normal
+ if(efa->v4)
+ efan = addfacelist(em, efa->v4->tmp.v, efa->v3->tmp.v,
+ efa->v2->tmp.v, efa->v1->tmp.v, efa, efa);
+ else
+ efan = addfacelist(em, efa->v3->tmp.v, efa->v2->tmp.v,
+ efa->v1->tmp.v, NULL, efa, efa);
+ }
+ else {
+ if(efa->v4)
+ efan = addfacelist(em, efa->v1->tmp.v, efa->v2->tmp.v,
+ efa->v3->tmp.v, efa->v4->tmp.v, efa, efa);
+ else
+ efan = addfacelist(em, efa->v1->tmp.v, efa->v2->tmp.v,
+ efa->v3->tmp.v, NULL, efa, efa);
+ }
+
+ if (em->act_face == efa) {
+ em->act_face = efan;
+ }
+
+ /* for transform */
+ add_normal_aligned(nor, efa->n);
+ }
+ }
+
+ if(del_old) {
+
+ /* step 4: remove old faces, if del_old */
+ efa= em->faces.first;
+ while(efa) {
+ nextfa= efa->next;
+ if(efa->f & SELECT) {
+ BLI_remlink(&em->faces, efa);
+ free_editface(em, efa);
+ }
+ efa= nextfa;
+ }
+
+
+ /* step 5: remove selected unused edges */
+ /* start tagging again */
+ for(eed= em->edges.first; eed; eed= eed->next) eed->f1=0;
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->e1->f1= 1;
+ efa->e2->f1= 1;
+ efa->e3->f1= 1;
+ if(efa->e4) efa->e4->f1= 1;
+ }
+ /* remove */
+ eed= em->edges.first;
+ while(eed) {
+ nexted= eed->next;
+ if(eed->f & SELECT) {
+ if(eed->f1==0) {
+ remedge(em, eed);
+ free_editedge(em, eed);
+ }
+ }
+ eed= nexted;
+ }
+
+ /* step 6: remove selected unused vertices */
+ for(eed= em->edges.first; eed; eed= eed->next)
+ eed->v1->f1= eed->v2->f1= 0;
+
+ eve= em->verts.first;
+ while(eve) {
+ nextve= eve->next;
+ if(eve->f1) {
+ // hack... but we need it for step 7, redoing selection
+ if(eve->tmp.v) eve->tmp.v->tmp.v= eve->tmp.v;
+
+ BLI_remlink(&em->verts, eve);
+ free_editvert(em, eve);
+ }
+ eve= nextve;
+ }
+ }
+
+ Normalize(nor); // translation normal grab
+
+ /* step 7: redo selection */
+ EM_clear_flag_all(em, SELECT);
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->tmp.v) {
+ eve->tmp.v->f |= SELECT;
+ }
+ }
+
+ EM_select_flush(em);
+
+ if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // grab
+ return 'n'; // normal constraint
+}
+
+short extrudeflag_vert(Object *obedit, EditMesh *em, short flag, float *nor)
+{
+ /* all verts/edges/faces with (f & 'flag'): extrude */
+ /* from old verts, 'flag' is cleared, in new ones it is set */
+ EditVert *eve, *v1, *v2, *v3, *v4, *nextve;
+ EditEdge *eed, *e1, *e2, *e3, *e4, *nexted;
+ EditFace *efa, *efa2, *nextvl;
+ short sel=0, del_old= 0, is_face_sel=0;
+ ModifierData *md;
+
+ if(em==NULL) return 0;
+
+ md = obedit->modifiers.first;
+
+ /* clear vert flag f1, we use this to detect a loose selected vertice */
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f & flag) eve->f1= 1;
+ else eve->f1= 0;
+ eve= eve->next;
+ }
+ /* clear edges counter flag, if selected we set it at 1 */
+ eed= em->edges.first;
+ while(eed) {
+ if( (eed->v1->f & flag) && (eed->v2->f & flag) ) {
+ eed->f2= 1;
+ eed->v1->f1= 0;
+ eed->v2->f1= 0;
+ }
+ else eed->f2= 0;
+
+ eed->f1= 1; /* this indicates it is an 'old' edge (in this routine we make new ones) */
+ eed->tmp.f = NULL; /* used as sample */
+
+ eed= eed->next;
+ }
+
+ /* we set a flag in all selected faces, and increase the associated edge counters */
+
+ efa= em->faces.first;
+ while(efa) {
+ efa->f1= 0;
+
+ if(faceselectedAND(efa, flag)) {
+ e1= efa->e1;
+ e2= efa->e2;
+ e3= efa->e3;
+ e4= efa->e4;
+
+ if(e1->f2 < 3) e1->f2++;
+ if(e2->f2 < 3) e2->f2++;
+ if(e3->f2 < 3) e3->f2++;
+ if(e4 && e4->f2 < 3) e4->f2++;
+
+ efa->f1= 1;
+ is_face_sel= 1; // for del_old
+ }
+ else if(faceselectedOR(efa, flag)) {
+ e1= efa->e1;
+ e2= efa->e2;
+ e3= efa->e3;
+ e4= efa->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;
+ }
+
+ // sample for next loop
+ efa->e1->tmp.f = efa;
+ efa->e2->tmp.f = efa;
+ efa->e3->tmp.f = efa;
+ if(efa->e4) efa->e4->tmp.f = efa;
+
+ efa= efa->next;
+ }
+
+ set_edge_directions_f2(em, 3);
+
+ /* the current state now is:
+ eve->f1==1: loose selected vertex
+
+ eed->f2==0 : edge is not selected, no extrude
+ eed->f2==1 : edge selected, is not part of a face, extrude
+ eed->f2==2 : edge selected, is part of 1 face, extrude
+ eed->f2==3 : edge selected, is part of more faces, no extrude
+
+ eed->f1==0: new edge
+ eed->f1==1: edge selected, is part of selected face, when eed->f==3: remove
+ eed->f1==2: edge selected, part of a partially selected face
+
+ efa->f1==1 : duplicate this face
+ */
+
+ /* If a mirror modifier with clipping is on, we need to adjust some
+ * of the cases above to handle edges on the line of symmetry.
+ */
+ for (; md; md=md->next) {
+ if (md->type==eModifierType_Mirror) {
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ if(mmd->flag & MOD_MIR_CLIPPING) {
+ float mtx[4][4];
+ if (mmd->mirror_ob) {
+ float imtx[4][4];
+ Mat4Invert(imtx, mmd->mirror_ob->obmat);
+ Mat4MulMat4(mtx, obedit->obmat, imtx);
+ }
+
+ for (eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f2 == 2) {
+ float co1[3], co2[3];
+
+ VecCopyf(co1, eed->v1->co);
+ VecCopyf(co2, eed->v2->co);
+
+ if (mmd->mirror_ob) {
+ VecMat4MulVecfl(co1, mtx, co1);
+ VecMat4MulVecfl(co2, mtx, co2);
+ }
+
+ if (mmd->flag & MOD_MIR_AXIS_X)
+ if ( (fabs(co1[0]) < mmd->tolerance) &&
+ (fabs(co2[0]) < mmd->tolerance) )
+ ++eed->f2;
+
+ if (mmd->flag & MOD_MIR_AXIS_Y)
+ if ( (fabs(co1[1]) < mmd->tolerance) &&
+ (fabs(co2[1]) < mmd->tolerance) )
+ ++eed->f2;
+ if (mmd->flag & MOD_MIR_AXIS_Z)
+ if ( (fabs(co1[2]) < mmd->tolerance) &&
+ (fabs(co2[2]) < mmd->tolerance) )
+ ++eed->f2;
+ }
+ }
+ }
+ }
+ }
+
+ /* copy all selected vertices, */
+ /* write pointer to new vert in old struct at eve->tmp.v */
+ eve= em->verts.last;
+ while(eve) {
+ eve->f &= ~128; /* clear, for later test for loose verts */
+ if(eve->f & flag) {
+ sel= 1;
+ v1= addvertlist(em, 0, NULL);
+
+ VECCOPY(v1->co, eve->co);
+ v1->f= eve->f;
+ eve->f-= flag;
+ eve->tmp.v = v1;
+ }
+ else eve->tmp.v = 0;
+ eve= eve->prev;
+ }
+
+ if(sel==0) return 0;
+
+ /* all edges with eed->f2==1 or eed->f2==2 become faces */
+
+ /* if del_old==1 then extrude is in partial geometry, to keep it manifold.
+ verts with f1==0 and (eve->f & 128)==0) are removed
+ edges with eed->f2>2 are removed
+ faces with efa->f1 are removed
+ if del_old==0 the extrude creates a volume.
+ */
+
+ /* find if we delete old faces */
+ if(is_face_sel) {
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if( (eed->f2==1 || eed->f2==2) ) {
+ if(eed->f1==2) {
+ del_old= 1;
+ break;
+ }
+ }
+ }
+ }
+
+ eed= em->edges.last;
+ while(eed) {
+ nexted= eed->prev;
+ if( eed->f2<3) {
+ eed->v1->f |= 128; /* = no loose vert! */
+ eed->v2->f |= 128;
+ }
+ if( (eed->f2==1 || eed->f2==2) ) {
+
+ /* if del_old, the preferred normal direction is exact opposite as for keep old faces */
+ if(eed->dir != del_old)
+ efa2 = addfacelist(em, eed->v1, eed->v2,
+ eed->v2->tmp.v, eed->v1->tmp.v,
+ eed->tmp.f, NULL);
+ else
+ efa2 = addfacelist(em, eed->v2, eed->v1,
+ eed->v1->tmp.v, eed->v2->tmp.v,
+ eed->tmp.f, NULL);
+
+ /* Needs smarter adaption of existing creases.
+ * If addedgelist is used, make sure seams are set to 0 on these
+ * new edges, since we do not want to add any seams on extrusion.
+ */
+ efa2->e1->crease= eed->crease;
+ efa2->e2->crease= eed->crease;
+ efa2->e3->crease= eed->crease;
+ if(efa2->e4) efa2->e4->crease= eed->crease;
+ }
+
+ eed= nexted;
+ }
+ if(del_old) {
+ eed= em->edges.first;
+ while(eed) {
+ nexted= eed->next;
+ if(eed->f2==3 && eed->f1==1) {
+ remedge(em, eed);
+ free_editedge(em, eed);
+ }
+ eed= nexted;
+ }
+ }
+ /* duplicate faces, if necessary remove old ones */
+ efa= em->faces.first;
+ while(efa) {
+ nextvl= efa->next;
+ if(efa->f1 & 1) {
+
+ v1 = efa->v1->tmp.v;
+ v2 = efa->v2->tmp.v;
+ v3 = efa->v3->tmp.v;
+ if(efa->v4)
+ v4 = efa->v4->tmp.v;
+ else
+ v4= 0;
+
+ /* hmm .. not sure about edges here */
+ if(del_old==0) // if we keep old, we flip normal
+ efa2= addfacelist(em, v3, v2, v1, v4, efa, efa);
+ else
+ efa2= addfacelist(em, v1, v2, v3, v4, efa, efa);
+
+ /* for transform */
+ add_normal_aligned(nor, efa->n);
+
+ if(del_old) {
+ BLI_remlink(&em->faces, efa);
+ free_editface(em, efa);
+ }
+ }
+ efa= nextvl;
+ }
+
+ Normalize(nor); // for grab
+
+ /* for all vertices with eve->tmp.v!=0
+ if eve->f1==1: make edge
+ if flag!=128 : if del_old==1: remove
+ */
+ eve= em->verts.last;
+ while(eve) {
+ nextve= eve->prev;
+ if(eve->tmp.v) {
+ if(eve->f1==1) addedgelist(em, eve, eve->tmp.v, NULL);
+ else if( (eve->f & 128)==0) {
+ if(del_old) {
+ BLI_remlink(&em->verts,eve);
+ free_editvert(em, eve);
+ eve= NULL;
+ }
+ }
+ }
+ if(eve) {
+ eve->f &= ~128;
+ }
+ eve= nextve;
+ }
+ // since its vertex select mode now, it also deselects higher order
+ EM_selectmode_flush(em);
+
+ if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // g is grab, for correct undo print
+ return 'n';
+}
+
+/* generic extrude */
+short extrudeflag(Object *obedit, EditMesh *em, short flag, float *nor)
+{
+ if(em->selectmode & SCE_SELECT_VERTEX)
+ return extrudeflag_vert(obedit, em, flag, nor);
+ else
+ return extrudeflag_edge(obedit, em, flag, nor);
+
+}
+
+void rotateflag(EditMesh *em, short flag, float *cent, float rotmat[][3])
+{
+ /* all verts with (flag & 'flag') rotate */
+ EditVert *eve;
+
+ eve= em->verts.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(EditMesh *em, short flag, float *vec)
+{
+ /* all verts with (flag & 'flag') translate */
+ EditVert *eve;
+
+ eve= em->verts.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;
+ }
+}
+
+/* helper call for below */
+static EditVert *adduplicate_vertex(EditMesh *em, EditVert *eve, int flag)
+{
+ /* FIXME: copy deformation weight from eve ok here? */
+ EditVert *v1= addvertlist(em, eve->co, eve);
+
+ v1->f= eve->f;
+ eve->f-= flag;
+ eve->f|= 128;
+
+ eve->tmp.v = v1;
+
+ return v1;
+}
+
+/* old selection has flag 128 set, and flag 'flag' cleared
+new selection has flag 'flag' set */
+void adduplicateflag(EditMesh *em, int flag)
+{
+ EditVert *eve, *v1, *v2, *v3, *v4;
+ EditEdge *eed, *newed;
+ EditFace *efa, *newfa, *act_efa = EM_get_actFace(em, 0);
+
+ EM_clear_flag_all(em, 128);
+ EM_selectmode_set(em); // paranoia check, selection now is consistent
+
+ /* vertices first */
+ for(eve= em->verts.last; eve; eve= eve->prev) {
+
+ if(eve->f & flag)
+ adduplicate_vertex(em, eve, flag);
+ else
+ eve->tmp.v = NULL;
+ }
+
+ /* copy edges, note that vertex selection can be independent of edge */
+ for(eed= em->edges.last; eed; eed= eed->prev) {
+ if( eed->f & flag ) {
+ v1 = eed->v1->tmp.v;
+ if(v1==NULL) v1= adduplicate_vertex(em, eed->v1, flag);
+ v2 = eed->v2->tmp.v;
+ if(v2==NULL) v2= adduplicate_vertex(em, eed->v2, flag);
+
+ newed= addedgelist(em, v1, v2, eed);
+
+ newed->f= eed->f;
+ eed->f -= flag;
+ eed->f |= 128;
+ }
+ }
+
+ /* then duplicate faces, again create new vertices if needed */
+ for(efa= em->faces.last; efa; efa= efa->prev) {
+ if(efa->f & flag) {
+ v1 = efa->v1->tmp.v;
+ if(v1==NULL) v1= adduplicate_vertex(em, efa->v1, flag);
+ v2 = efa->v2->tmp.v;
+ if(v2==NULL) v2= adduplicate_vertex(em, efa->v2, flag);
+ v3 = efa->v3->tmp.v;
+ if(v3==NULL) v3= adduplicate_vertex(em, efa->v3, flag);
+ if(efa->v4) {
+ v4 = efa->v4->tmp.v;
+ if(v4==NULL) v4= adduplicate_vertex(em, efa->v4, flag);
+ }
+ else v4= NULL;
+
+ newfa= addfacelist(em, v1, v2, v3, v4, efa, efa);
+
+ if (efa==act_efa) {
+ EM_set_actFace(em, newfa);
+ }
+
+ newfa->f= efa->f;
+ efa->f -= flag;
+ efa->f |= 128;
+ }
+ }
+
+ EM_fgon_flags(em); // redo flags and indices for fgons
+}
+
+void delfaceflag(EditMesh *em, int flag)
+{
+ /* delete all faces with 'flag', including loose edges and loose vertices */
+ /* this is maybe a bit weird, but this function is used for 'split' and 'separate' */
+ /* in remaining vertices/edges 'flag' is cleared */
+ EditVert *eve,*nextve;
+ EditEdge *eed, *nexted;
+ EditFace *efa,*nextvl;
+
+ /* to detect loose edges, we put f2 flag on 1 */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f & flag) eed->f2= 1;
+ else eed->f2= 0;
+ }
+
+ /* delete faces */
+ efa= em->faces.first;
+ while(efa) {
+ nextvl= efa->next;
+ if(efa->f & flag) {
+
+ efa->e1->f2= 1;
+ efa->e2->f2= 1;
+ efa->e3->f2= 1;
+ if(efa->e4) {
+ efa->e4->f2= 1;
+ }
+
+ BLI_remlink(&em->faces, efa);
+ free_editface(em, efa);
+ }
+ efa= nextvl;
+ }
+
+ /* all remaining faces: make sure we keep the edges */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->e1->f2= 0;
+ efa->e2->f2= 0;
+ efa->e3->f2= 0;
+ if(efa->e4) {
+ efa->e4->f2= 0;
+ }
+ }
+
+ /* remove tagged edges, and clear remaining ones */
+ eed= em->edges.first;
+ while(eed) {
+ nexted= eed->next;
+
+ if(eed->f2==1) {
+ remedge(em, eed);
+ free_editedge(em, eed);
+ }
+ else {
+ eed->f &= ~flag;
+ eed->v1->f &= ~flag;
+ eed->v2->f &= ~flag;
+ }
+ eed= nexted;
+ }
+
+ /* vertices with 'flag' now are the loose ones, and will be removed */
+ eve= em->verts.first;
+ while(eve) {
+ nextve= eve->next;
+ if(eve->f & flag) {
+ BLI_remlink(&em->verts, eve);
+ free_editvert(em, eve);
+ }
+ eve= nextve;
+ }
+
+}
+
+/* ********************* */
+#if 0
+static int check_vnormal_flip(float *n, float *vnorm)
+{
+ float inp;
+
+ inp= n[0]*vnorm[0]+n[1]*vnorm[1]+n[2]*vnorm[2];
+
+ /* angles 90 degrees: dont flip */
+ if(inp> -0.000001) return 0;
+
+ return 1;
+}
+#endif
+
+
+
+/* does face centers too */
+void recalc_editnormals(EditMesh *em)
+{
+ EditFace *efa;
+ EditVert *eve;
+
+ for(eve= em->verts.first; eve; eve=eve->next) {
+ eve->no[0] = eve->no[1] = eve->no[2] = 0.0;
+ }
+
+ for(efa= em->faces.first; efa; efa=efa->next) {
+ if(efa->v4) {
+ CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, efa->n);
+ CalcCent4f(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
+ VecAddf(efa->v4->no, efa->v4->no, efa->n);
+ }
+ else {
+ CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n);
+ CalcCent3f(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co);
+ }
+ VecAddf(efa->v1->no, efa->v1->no, efa->n);
+ VecAddf(efa->v2->no, efa->v2->no, efa->n);
+ VecAddf(efa->v3->no, efa->v3->no, efa->n);
+ }
+
+ /* following Mesh convention; we use vertex coordinate itself for normal in this case */
+ for(eve= em->verts.first; eve; eve=eve->next) {
+ if (Normalize(eve->no)==0.0) {
+ VECCOPY(eve->no, eve->co);
+ Normalize(eve->no);
+ }
+ }
+}
+
+int compareface(EditFace *vl1, EditFace *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;
+}
+
+/* checks for existance, not tria overlapping inside quad */
+EditFace *exist_face(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4)
+{
+ EditFace *efa, efatest;
+
+ efatest.v1= v1;
+ efatest.v2= v2;
+ efatest.v3= v3;
+ efatest.v4= v4;
+
+ efa= em->faces.first;
+ while(efa) {
+ if(compareface(&efatest, efa)) return efa;
+ efa= efa->next;
+ }
+ return NULL;
+}
+
+/* evaluate if entire quad is a proper convex quad */
+int convex(float *v1, float *v2, float *v3, float *v4)
+{
+ float nor[3], nor1[3], nor2[3], vec[4][2];
+
+ /* define projection, do both trias apart, quad is undefined! */
+ CalcNormFloat(v1, v2, v3, nor1);
+ CalcNormFloat(v1, v3, v4, nor2);
+ nor[0]= ABS(nor1[0]) + ABS(nor2[0]);
+ nor[1]= ABS(nor1[1]) + ABS(nor2[1]);
+ nor[2]= ABS(nor1[2]) + ABS(nor2[2]);
+
+ if(nor[2] >= nor[0] && nor[2] >= nor[1]) {
+ vec[0][0]= v1[0]; vec[0][1]= v1[1];
+ vec[1][0]= v2[0]; vec[1][1]= v2[1];
+ vec[2][0]= v3[0]; vec[2][1]= v3[1];
+ vec[3][0]= v4[0]; vec[3][1]= v4[1];
+ }
+ else if(nor[1] >= nor[0] && nor[1]>= nor[2]) {
+ vec[0][0]= v1[0]; vec[0][1]= v1[2];
+ vec[1][0]= v2[0]; vec[1][1]= v2[2];
+ vec[2][0]= v3[0]; vec[2][1]= v3[2];
+ vec[3][0]= v4[0]; vec[3][1]= v4[2];
+ }
+ else {
+ vec[0][0]= v1[1]; vec[0][1]= v1[2];
+ vec[1][0]= v2[1]; vec[1][1]= v2[2];
+ vec[2][0]= v3[1]; vec[2][1]= v3[2];
+ vec[3][0]= v4[1]; vec[3][1]= v4[2];
+ }
+
+ /* linetests, the 2 diagonals have to instersect to be convex */
+ if( IsectLL2Df(vec[0], vec[2], vec[1], vec[3]) > 0 ) return 1;
+ return 0;
+}
+
+
+/* ********************* Fake Polgon support (FGon) ***************** */
+
+
+/* results in:
+ - faces having ->fgonf flag set (also for draw)
+ - edges having ->fgoni index set (for select)
+*/
+
+float EM_face_area(EditFace *efa)
+{
+ if(efa->v4) return AreaQ3Dfl(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
+ else return AreaT3Dfl(efa->v1->co, efa->v2->co, efa->v3->co);
+}
+
+float EM_face_perimeter(EditFace *efa)
+{
+ if(efa->v4) return
+ VecLenf(efa->v1->co, efa->v2->co)+
+ VecLenf(efa->v2->co, efa->v3->co)+
+ VecLenf(efa->v3->co, efa->v4->co)+
+ VecLenf(efa->v4->co, efa->v1->co);
+
+ else return
+ VecLenf(efa->v1->co, efa->v2->co)+
+ VecLenf(efa->v2->co, efa->v3->co)+
+ VecLenf(efa->v3->co, efa->v1->co);
+}
+
+void EM_fgon_flags(EditMesh *em)
+{
+ EditFace *efa, *efan, *efamax;
+ EditEdge *eed;
+ ListBase listb={NULL, NULL};
+ float size, maxsize;
+ short done, curindex= 1;
+
+ // for each face with fgon edge AND not fgon flag set
+ for(eed= em->edges.first; eed; eed= eed->next) eed->fgoni= 0; // index
+ for(efa= em->faces.first; efa; efa= efa->next) efa->fgonf= 0; // flag
+
+ // for speed & simplicity, put fgon face candidates in new listbase
+ efa= em->faces.first;
+ while(efa) {
+ efan= efa->next;
+ if( (efa->e1->h & EM_FGON) || (efa->e2->h & EM_FGON) ||
+ (efa->e3->h & EM_FGON) || (efa->e4 && (efa->e4->h & EM_FGON)) ) {
+ BLI_remlink(&em->faces, efa);
+ BLI_addtail(&listb, efa);
+ }
+ efa= efan;
+ }
+
+ // find an undone face with fgon edge
+ for(efa= listb.first; efa; efa= efa->next) {
+ if(efa->fgonf==0) {
+
+ // init this face
+ efa->fgonf= EM_FGON;
+ if(efa->e1->h & EM_FGON) efa->e1->fgoni= curindex;
+ if(efa->e2->h & EM_FGON) efa->e2->fgoni= curindex;
+ if(efa->e3->h & EM_FGON) efa->e3->fgoni= curindex;
+ if(efa->e4 && (efa->e4->h & EM_FGON)) efa->e4->fgoni= curindex;
+
+ // we search for largest face, to give facedot drawing rights
+ maxsize= EM_face_area(efa);
+ efamax= efa;
+
+ // now flush curendex over edges and set faceflags
+ done= 1;
+ while(done==1) {
+ done= 0;
+
+ for(efan= listb.first; efan; efan= efan->next) {
+ if(efan->fgonf==0) {
+ // if one if its edges has index set, do other too
+ if( (efan->e1->fgoni==curindex) || (efan->e2->fgoni==curindex) ||
+ (efan->e3->fgoni==curindex) || (efan->e4 && (efan->e4->fgoni==curindex)) ) {
+
+ efan->fgonf= EM_FGON;
+ if(efan->e1->h & EM_FGON) efan->e1->fgoni= curindex;
+ if(efan->e2->h & EM_FGON) efan->e2->fgoni= curindex;
+ if(efan->e3->h & EM_FGON) efan->e3->fgoni= curindex;
+ if(efan->e4 && (efan->e4->h & EM_FGON)) efan->e4->fgoni= curindex;
+
+ size= EM_face_area(efan);
+ if(size>maxsize) {
+ efamax= efan;
+ maxsize= size;
+ }
+ done= 1;
+ }
+ }
+ }
+ }
+
+ efamax->fgonf |= EM_FGON_DRAW;
+ curindex++;
+
+ }
+ }
+
+ // put fgon face candidates back in listbase
+ efa= listb.first;
+ while(efa) {
+ efan= efa->next;
+ BLI_remlink(&listb, efa);
+ BLI_addtail(&em->faces, efa);
+ efa= efan;
+ }
+
+ // remove fgon flags when edge not in fgon (anymore)
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->fgoni==0) eed->h &= ~EM_FGON;
+ }
+
+}
+
+/* editmesh vertmap, copied from intern.mesh.c
+ * if do_face_idx_array is 0 it means we need to run it as well as freeing
+ * */
+
+UvVertMap *EM_make_uv_vert_map(EditMesh *em, int selected, int do_face_idx_array, float *limit)
+{
+ EditVert *ev;
+ EditFace *efa;
+ int totverts;
+
+ /* vars from original func */
+ UvVertMap *vmap;
+ UvMapVert *buf;
+ MTFace *tf;
+ unsigned int a;
+ int i, totuv, nverts;
+
+ if (do_face_idx_array)
+ EM_init_index_arrays(em, 0, 0, 1);
+
+ /* we need the vert */
+ for (ev= em->verts.first, totverts=0; ev; ev= ev->next, totverts++) {
+ ev->tmp.l = totverts;
+ }
+
+ totuv = 0;
+
+ /* generate UvMapVert array */
+ for (efa= em->faces.first; efa; efa= efa->next)
+ if(!selected || ((!efa->h) && (efa->f & SELECT)))
+ totuv += (efa->v4)? 4: 3;
+
+ if(totuv==0) {
+ if (do_face_idx_array)
+ EM_free_index_arrays();
+ return NULL;
+ }
+ vmap= (UvVertMap*)MEM_callocN(sizeof(*vmap), "UvVertMap");
+ if (!vmap) {
+ if (do_face_idx_array)
+ EM_free_index_arrays();
+ return NULL;
+ }
+
+ vmap->vert= (UvMapVert**)MEM_callocN(sizeof(*vmap->vert)*totverts, "UvMapVert*");
+ buf= vmap->buf= (UvMapVert*)MEM_callocN(sizeof(*vmap->buf)*totuv, "UvMapVert");
+
+ if (!vmap->vert || !vmap->buf) {
+ free_uv_vert_map(vmap);
+ if (do_face_idx_array)
+ EM_free_index_arrays();
+ return NULL;
+ }
+
+ for (a=0, efa= em->faces.first; efa; a++, efa= efa->next) {
+ if(!selected || ((!efa->h) && (efa->f & SELECT))) {
+ nverts= (efa->v4)? 4: 3;
+
+ for(i=0; i<nverts; i++) {
+ buf->tfindex= i;
+ buf->f= a;
+ buf->separate = 0;
+
+ buf->next= vmap->vert[(*(&efa->v1 + i))->tmp.l];
+ vmap->vert[(*(&efa->v1 + i))->tmp.l]= buf;
+
+ buf++;
+ }
+ }
+ }
+
+ /* sort individual uvs for each vert */
+ for(a=0, ev=em->verts.first; ev; a++, ev= ev->next) {
+ UvMapVert *newvlist= NULL, *vlist=vmap->vert[a];
+ UvMapVert *iterv, *v, *lastv, *next;
+ float *uv, *uv2, uvdiff[2];
+
+ while(vlist) {
+ v= vlist;
+ vlist= vlist->next;
+ v->next= newvlist;
+ newvlist= v;
+
+ efa = EM_get_face_for_index(v->f);
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ uv = tf->uv[v->tfindex];
+
+ lastv= NULL;
+ iterv= vlist;
+
+ while(iterv) {
+ next= iterv->next;
+ efa = EM_get_face_for_index(iterv->f);
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ uv2 = tf->uv[iterv->tfindex];
+
+ Vec2Subf(uvdiff, uv2, uv);
+
+ if(fabs(uv[0]-uv2[0]) < limit[0] && fabs(uv[1]-uv2[1]) < limit[1]) {
+ if(lastv) lastv->next= next;
+ else vlist= next;
+ iterv->next= newvlist;
+ newvlist= iterv;
+ }
+ else
+ lastv=iterv;
+
+ iterv= next;
+ }
+
+ newvlist->separate = 1;
+ }
+
+ vmap->vert[a]= newvlist;
+ }
+
+ if (do_face_idx_array)
+ EM_free_index_arrays();
+
+ return vmap;
+}
+
+UvMapVert *EM_get_uv_map_vert(UvVertMap *vmap, unsigned int v)
+{
+ return vmap->vert[v];
+}
+
+void EM_free_uv_vert_map(UvVertMap *vmap)
+{
+ if (vmap) {
+ if (vmap->vert) MEM_freeN(vmap->vert);
+ if (vmap->buf) MEM_freeN(vmap->buf);
+ MEM_freeN(vmap);
+ }
+}
+
diff --git a/source/blender/editors/mesh/editmesh_loop.c b/source/blender/editors/mesh/editmesh_loop.c
new file mode 100644
index 00000000000..d0f7517df78
--- /dev/null
+++ b/source/blender/editors/mesh/editmesh_loop.c
@@ -0,0 +1,735 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/*
+
+editmesh_loop: tools with own drawing subloops, select, knife, subdiv
+
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_ghash.h"
+
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+
+#include "PIL_time.h"
+
+#include "BIF_gl.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "mesh_intern.h"
+
+/* **** XXX ******** */
+static void BIF_undo_push() {}
+static void BIF_undo() {}
+static void error() {}
+static int qtest() {return 0;}
+/* **** XXX ******** */
+
+
+/* New LoopCut */
+static void edgering_sel(EditMesh *em, EditEdge *startedge, int select, int previewlines)
+{
+ EditEdge *eed;
+ EditFace *efa;
+ EditVert *v[2][2];
+ float co[2][3];
+ int looking= 1,i;
+
+ /* in eed->f1 we put the valence (amount of faces in edge) */
+ /* in eed->f2 we put tagged flag as correct loop */
+ /* in efa->f1 we put tagged flag as correct to select */
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->f1= 0;
+ eed->f2= 0;
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->f1= 0;
+ if(efa->h==0) {
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->e4) efa->e4->f1++;
+ }
+ }
+
+ // tag startedge OK
+ startedge->f2= 1;
+
+ while(looking) {
+ looking= 0;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->e4 && efa->f1==0 && efa->h == 0) { // not done quad
+ if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok
+
+ // if edge tagged, select opposing edge and mark face ok
+ if(efa->e1->f2) {
+ efa->e3->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ else if(efa->e2->f2) {
+ efa->e4->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ if(efa->e3->f2) {
+ efa->e1->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ if(efa->e4->f2) {
+ efa->e2->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ }
+ }
+ }
+ }
+
+ if(previewlines > 0 && select == 0){
+// XXX persp(PERSP_VIEW);
+// XXX glPushMatrix();
+// XXX mymultmatrix(obedit->obmat);
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->v4 == NULL) { continue; }
+ if(efa->h == 0){
+ if(efa->e1->f2 == 1){
+ if(efa->e1->h == 1 || efa->e3->h == 1 )
+ continue;
+
+ v[0][0] = efa->v1;
+ v[0][1] = efa->v2;
+ v[1][0] = efa->v4;
+ v[1][1] = efa->v3;
+ } else if(efa->e2->f2 == 1){
+ if(efa->e2->h == 1 || efa->e4->h == 1)
+ continue;
+ v[0][0] = efa->v2;
+ v[0][1] = efa->v3;
+ v[1][0] = efa->v1;
+ v[1][1] = efa->v4;
+ } else { continue; }
+
+ for(i=1;i<=previewlines;i++){
+ co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0];
+ co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1];
+ co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2];
+
+ co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0];
+ co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1];
+ co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2];
+ glColor3ub(255, 0, 255);
+ glBegin(GL_LINES);
+ glVertex3f(co[0][0],co[0][1],co[0][2]);
+ glVertex3f(co[1][0],co[1][1],co[1][2]);
+ glEnd();
+ }
+ }
+ }
+ glPopMatrix();
+ } else {
+
+ /* (de)select the edges */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f2) EM_select_edge(eed, select);
+ }
+ }
+}
+void CutEdgeloop(Object *obedit, wmOperator *op, EditMesh *em, int numcuts)
+{
+ ViewContext vc; // XXX
+ EditEdge *nearest=NULL, *eed;
+ float fac;
+ int keys = 0, holdnum=0, selectmode, dist;
+ short mvalo[2] = {0,0}, mval[2];
+ short event=0, val, choosing=1, cancel=0, cuthalf = 0, smooth=0;
+ short hasHidden = 0;
+ char msg[128];
+
+ selectmode = em->selectmode;
+
+ if(em->selectmode & SCE_SELECT_FACE){
+ em->selectmode = SCE_SELECT_EDGE;
+ EM_selectmode_set(em);
+ }
+
+
+ BIF_undo_push("Loopcut Begin");
+ while(choosing && !cancel){
+// XXX getmouseco_areawin(mval);
+ if (mval[0] != mvalo[0] || mval[1] != mvalo[1]) {
+ mvalo[0] = mval[0];
+ mvalo[1] = mval[1];
+ dist= 50;
+ nearest = findnearestedge(&vc, &dist); // returns actual distance in dist
+// scrarea_do_windraw(curarea); // after findnearestedge, backbuf!
+
+ sprintf(msg,"Number of Cuts: %d",numcuts);
+ if(smooth){
+ sprintf(msg,"%s (S)mooth: on",msg);
+ } else {
+ sprintf(msg,"%s (S)mooth: off",msg);
+ }
+
+// headerprint(msg);
+ /* Need to figure preview */
+ if(nearest){
+ edgering_sel(em, nearest, 0, numcuts);
+ }
+// XXX screen_swapbuffers();
+
+ /* backbuffer refresh for non-apples (no aux) */
+#ifndef __APPLE__
+// XXX if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
+// backdrawview3d(0);
+// }
+#endif
+ }
+ else PIL_sleep_ms(10); // idle
+
+
+ while(qtest())
+ {
+ val=0;
+// XXX event= extern_qread(&val);
+ if(val && (event == MOUSEX || event == MOUSEY)){ ; }
+ else if(val && ((event==LEFTMOUSE || event==RETKEY) || (event == MIDDLEMOUSE || event==PADENTER)))
+ {
+ if(event == MIDDLEMOUSE){
+ cuthalf = 1;
+ }
+ if (nearest==NULL)
+ cancel = 1;
+ choosing=0;
+ mvalo[0] = -1;
+ }
+ else if(val && (event==ESCKEY || event==RIGHTMOUSE ))
+ {
+ choosing=0;
+ cancel = 1;
+ mvalo[0] = -1;
+ }
+ else if(val && (event==PADPLUSKEY || event==WHEELUPMOUSE))
+ {
+ numcuts++;
+ mvalo[0] = -1;
+ }
+ else if(val && (event==PADMINUS || event==WHEELDOWNMOUSE))
+ {
+ if(numcuts > 1){
+ numcuts--;
+ mvalo[0] = -1;
+ }
+ }
+ else if(val && event==SKEY)
+ {
+ if(smooth){smooth=0;}
+ else { smooth=1; }
+ mvalo[0] = -1;
+ }
+
+ else if(val){
+ holdnum = -1;
+ switch(event){
+ case PAD9:
+ case NINEKEY:
+ holdnum = 9; break;
+ case PAD8:
+ case EIGHTKEY:
+ holdnum = 8;break;
+ case PAD7:
+ case SEVENKEY:
+ holdnum = 7;break;
+ case PAD6:
+ case SIXKEY:
+ holdnum = 6;break;
+ case PAD5:
+ case FIVEKEY:
+ holdnum = 5;break;
+ case PAD4:
+ case FOURKEY:
+ holdnum = 4;break;
+ case PAD3:
+ case THREEKEY:
+ holdnum = 3; break;
+ case PAD2:
+ case TWOKEY:
+ holdnum = 2;break;
+ case PAD1:
+ case ONEKEY:
+ holdnum = 1; break;
+ case PAD0:
+ case ZEROKEY:
+ holdnum = 0;break;
+ case BACKSPACEKEY:
+ holdnum = -2;break;
+ }
+ if(holdnum >= 0 && numcuts*10 < 130){
+ if(keys == 0){ // first level numeric entry
+ if(holdnum > 0){
+ numcuts = holdnum;
+ keys++;
+ }
+ } else if(keys > 0){//highrt level numeric entry
+ numcuts *= 10;
+ numcuts += holdnum;
+ keys++;
+ }
+ } else if (holdnum == -2){// backspace
+ if (keys > 1){
+ numcuts /= 10;
+ keys--;
+ } else {
+ numcuts=1;
+ keys = 0;
+ }
+ }
+ mvalo[0] = -1;
+ break;
+ } // End Numeric Entry
+ } //End while(qtest())
+ } // End Choosing
+
+ if(cancel){
+ return;
+ }
+ /* clean selection */
+ for(eed=em->edges.first; eed; eed = eed->next){
+ EM_select_edge(eed,0);
+ }
+ /* select edge ring */
+ edgering_sel(em, nearest, 1, 0);
+
+ /* now cut the loops */
+ if(smooth){
+ fac= 1.0f;
+// XXX if(fbutton(&fac, 0.0f, 5.0f, 10, 10, "Smooth:")==0) return;
+ fac= 0.292f*fac;
+ esubdivideflag(obedit, em, SELECT,fac,B_SMOOTH,numcuts,SUBDIV_SELECT_LOOPCUT);
+ } else {
+ esubdivideflag(obedit, em, SELECT,0,0,numcuts,SUBDIV_SELECT_LOOPCUT);
+ }
+ /* if this was a single cut, enter edgeslide mode */
+ if(numcuts == 1 && hasHidden == 0){
+ if(cuthalf)
+ EdgeSlide(em, op, 1,0.0);
+ else {
+ if(EdgeSlide(em, op, 0,0.0) == -1){
+ BIF_undo();
+ }
+ }
+ }
+
+ if(em->selectmode != selectmode){
+ em->selectmode = selectmode;
+ EM_selectmode_set(em);
+ }
+
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ return;
+}
+
+
+/* *************** LOOP SELECT ************* */
+#if 0
+static short edgeFaces(EditMesh *em, EditEdge *e)
+{
+ EditFace *search=NULL;
+ short count = 0;
+
+ search = em->faces.first;
+ while(search){
+ if((search->e1 == e || search->e2 == e) || (search->e3 == e || search->e4 == e))
+ count++;
+ search = search->next;
+ }
+ return count;
+}
+#endif
+
+
+
+/* ***************** TRAIL ************************
+
+Read a trail of mouse coords and return them as an array of CutCurve structs
+len returns number of mouse coords read before commiting with RETKEY
+It is up to the caller to free the block when done with it,
+
+XXX Is only used here, so local inside this file (ton)
+ */
+
+#define TRAIL_POLYLINE 1 /* For future use, They don't do anything yet */
+#define TRAIL_FREEHAND 2
+#define TRAIL_MIXED 3 /* (1|2) */
+#define TRAIL_AUTO 4
+#define TRAIL_MIDPOINTS 8
+
+typedef struct CutCurve {
+ float x;
+ float y;
+} CutCurve;
+
+
+/* ******************************************************************** */
+/* Knife Subdivide Tool. Subdivides edges intersected by a mouse trail
+ drawn by user.
+
+ Currently mapped to KKey when in MeshEdit mode.
+ Usage:
+ Hit Shift K, Select Centers or Exact
+ Hold LMB down to draw path, hit RETKEY.
+ ESC cancels as expected.
+
+ Contributed by Robert Wenzlaff (Det. Thorn).
+
+ 2.5 revamp:
+ - non modal (no menu before cutting)
+ - exit on mouse release
+ - polygon/segment drawing can become handled by WM cb later
+
+*/
+
+#define KNIFE_EXACT 1
+#define KNIFE_MIDPOINT 2
+#define KNIFE_MULTICUT 3
+
+static EnumPropertyItem knife_items[]= {
+ {KNIFE_EXACT, "EXACT", "Exact", ""},
+ {KNIFE_MIDPOINT, "MIDPOINTS", "Midpoints", ""},
+ {KNIFE_MULTICUT, "MULTICUT", "Multicut", ""},
+ {0, NULL, NULL}
+};
+
+/* seg_intersect() Determines if and where a mouse trail intersects an EditEdge */
+
+static float seg_intersect(EditEdge *e, CutCurve *c, int len, char mode, struct GHash *gh)
+{
+#define MAXSLOPE 100000
+ float x11, y11, x12=0, y12=0, x2max, x2min, y2max;
+ float y2min, dist, lastdist=0, xdiff2, xdiff1;
+ float m1, b1, m2, b2, x21, x22, y21, y22, xi;
+ float yi, x1min, x1max, y1max, y1min, perc=0;
+ float *scr;
+ float threshold;
+ int i;
+
+ threshold = 0.000001; /*tolerance for vertex intersection*/
+ // XXX threshold = scene->toolsettings->select_thresh / 100;
+
+ /* Get screen coords of verts */
+ scr = BLI_ghash_lookup(gh, e->v1);
+ x21=scr[0];
+ y21=scr[1];
+
+ scr = BLI_ghash_lookup(gh, e->v2);
+ x22=scr[0];
+ y22=scr[1];
+
+ xdiff2=(x22-x21);
+ if (xdiff2) {
+ m2=(y22-y21)/xdiff2;
+ b2= ((x22*y21)-(x21*y22))/xdiff2;
+ }
+ else {
+ m2=MAXSLOPE; /* Verticle slope */
+ b2=x22;
+ }
+
+ /*check for *exact* vertex intersection first*/
+ if(mode!=KNIFE_MULTICUT){
+ for (i=0; i<len; i++){
+ if (i>0){
+ x11=x12;
+ y11=y12;
+ }
+ else {
+ x11=c[i].x;
+ y11=c[i].y;
+ }
+ x12=c[i].x;
+ y12=c[i].y;
+
+ /*test e->v1*/
+ if((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)){
+ e->v1->f1 = 1;
+ perc = 0;
+ return(perc);
+ }
+ /*test e->v2*/
+ else if((x11 == x22 && y11 == y22) || (x12 == x22 && y12 == y22)){
+ e->v2->f1 = 1;
+ perc = 0;
+ return(perc);
+ }
+ }
+ }
+
+ /*now check for edge interesect (may produce vertex intersection as well)*/
+ for (i=0; i<len; i++){
+ if (i>0){
+ x11=x12;
+ y11=y12;
+ }
+ else {
+ x11=c[i].x;
+ y11=c[i].y;
+ }
+ x12=c[i].x;
+ y12=c[i].y;
+
+ /* Perp. Distance from point to line */
+ if (m2!=MAXSLOPE) dist=(y12-m2*x12-b2);/* /sqrt(m2*m2+1); Only looking for */
+ /* change in sign. Skip extra math */
+ else dist=x22-x12;
+
+ if (i==0) lastdist=dist;
+
+ /* if dist changes sign, and intersect point in edge's Bound Box*/
+ if ((lastdist*dist)<=0){
+ xdiff1=(x12-x11); /* Equation of line between last 2 points */
+ if (xdiff1){
+ m1=(y12-y11)/xdiff1;
+ b1= ((x12*y11)-(x11*y12))/xdiff1;
+ }
+ else{
+ m1=MAXSLOPE;
+ b1=x12;
+ }
+ x2max=MAX2(x21,x22)+0.001; /* prevent missed edges */
+ x2min=MIN2(x21,x22)-0.001; /* due to round off error */
+ y2max=MAX2(y21,y22)+0.001;
+ y2min=MIN2(y21,y22)-0.001;
+
+ /* Found an intersect, calc intersect point */
+ if (m1==m2){ /* co-incident lines */
+ /* cut at 50% of overlap area*/
+ x1max=MAX2(x11, x12);
+ x1min=MIN2(x11, x12);
+ xi= (MIN2(x2max,x1max)+MAX2(x2min,x1min))/2.0;
+
+ y1max=MAX2(y11, y12);
+ y1min=MIN2(y11, y12);
+ yi= (MIN2(y2max,y1max)+MAX2(y2min,y1min))/2.0;
+ }
+ else if (m2==MAXSLOPE){
+ xi=x22;
+ yi=m1*x22+b1;
+ }
+ else if (m1==MAXSLOPE){
+ xi=x12;
+ yi=m2*x12+b2;
+ }
+ else {
+ xi=(b1-b2)/(m2-m1);
+ yi=(b1*m2-m1*b2)/(m2-m1);
+ }
+
+ /* Intersect inside bounding box of edge?*/
+ if ((xi>=x2min)&&(xi<=x2max)&&(yi<=y2max)&&(yi>=y2min)){
+ /*test for vertex intersect that may be 'close enough'*/
+ if(mode!=KNIFE_MULTICUT){
+ if(xi <= (x21 + threshold) && xi >= (x21 - threshold)){
+ if(yi <= (y21 + threshold) && yi >= (y21 - threshold)){
+ e->v1->f1 = 1;
+ perc = 0;
+ break;
+ }
+ }
+ if(xi <= (x22 + threshold) && xi >= (x22 - threshold)){
+ if(yi <= (y22 + threshold) && yi >= (y22 - threshold)){
+ e->v2->f1 = 1;
+ perc = 0;
+ break;
+ }
+ }
+ }
+ if ((m2<=1.0)&&(m2>=-1.0)) perc = (xi-x21)/(x22-x21);
+ else perc=(yi-y21)/(y22-y21); /*lower slope more accurate*/
+ //isect=32768.0*(perc+0.0000153); /* Percentage in 1/32768ths */
+
+ break;
+ }
+ }
+ lastdist=dist;
+ }
+ return(perc);
+}
+
+
+#define MAX_CUTS 256
+
+static int knife_cut_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+ ARegion *ar= CTX_wm_region(C);
+ EditEdge *eed;
+ EditVert *eve;
+ CutCurve curve[MAX_CUTS];
+ struct GHash *gh;
+ float isect=0.0;
+ float *scr, co[4];
+ int len=0;
+ short numcuts=1, mode= RNA_int_get(op->ptr, "type");
+
+ if (EM_nvertices_selected(em) < 2) {
+ error("No edges are selected to operate on");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;;
+ }
+
+ /* get the cut curve */
+ RNA_BEGIN(op->ptr, itemptr, "path") {
+
+ RNA_float_get_array(&itemptr, "loc", (float *)&curve[len]);
+ len++;
+ if(len>= MAX_CUTS) break;
+ }
+ RNA_END;
+
+ if(len<2) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ /*store percentage of edge cut for KNIFE_EXACT here.*/
+ for(eed=em->edges.first; eed; eed= eed->next)
+ eed->tmp.fp = 0.0;
+
+ /*the floating point coordinates of verts in screen space will be stored in a hash table according to the vertices pointer*/
+ gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ for(eve=em->verts.first; eve; eve=eve->next){
+ scr = MEM_mallocN(sizeof(float)*2, "Vertex Screen Coordinates");
+ VECCOPY(co, eve->co);
+ co[3]= 1.0;
+ Mat4MulVec4fl(obedit->obmat, co);
+ project_float(ar, co, scr);
+ BLI_ghash_insert(gh, eve, scr);
+ eve->f1 = 0; /*store vertex intersection flag here*/
+
+ }
+
+ eed= em->edges.first;
+ while(eed) {
+ if( eed->v1->f & eed->v2->f & SELECT ){ // NOTE: uses vertex select, subdiv doesnt do edges yet
+ isect= seg_intersect(eed, curve, len, mode, gh);
+ if (isect!=0.0f) eed->f2= 1;
+ else eed->f2=0;
+ eed->tmp.fp= isect;
+ //printf("isect=%i\n", isect);
+ }
+ else {
+ eed->f2=0;
+ eed->f1=0;
+ }
+ eed= eed->next;
+ }
+
+ if (mode==KNIFE_MIDPOINT) esubdivideflag(obedit, em, SELECT, 0, B_KNIFE, 1, SUBDIV_SELECT_ORIG);
+ else if (mode==KNIFE_MULTICUT) esubdivideflag(obedit, em, SELECT, 0, B_KNIFE, numcuts, SUBDIV_SELECT_ORIG);
+ else esubdivideflag(obedit, em, SELECT, 0, B_KNIFE|B_PERCENTSUBD, 1, SUBDIV_SELECT_ORIG);
+
+ eed=em->edges.first;
+ while(eed){
+ eed->f2=0;
+ eed->f1=0;
+ eed=eed->next;
+ }
+
+ BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+
+void MESH_OT_knife_cut(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ ot->name= "Knife Cut";
+ ot->idname= "MESH_OT_knife_cut";
+
+ ot->invoke= WM_gesture_lines_invoke;
+ ot->modal= WM_gesture_lines_modal;
+ ot->exec= knife_cut_exec;
+
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", knife_items, KNIFE_EXACT, "Type", "");
+ prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
+
+ /* internal */
+ RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
+}
+
+/* ******************************************************* */
+
diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c
new file mode 100644
index 00000000000..faa3176c958
--- /dev/null
+++ b/source/blender/editors/mesh/editmesh_mods.c
@@ -0,0 +1,4610 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/*
+
+editmesh_mods.c, UI level access, no geometry changes
+
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "MTC_matrixops.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+
+#include "BKE_context.h"
+#include "BKE_displist.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_material.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+#include "BKE_report.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "RE_render_ext.h" /* externtex */
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "mesh_intern.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+/* XXX */
+static void waitcursor() {}
+static int pupmenu() {return 0;}
+
+/* ****************************** MIRROR **************** */
+
+void EM_select_mirrored(Object *obedit, EditMesh *em)
+{
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ EditVert *eve, *v1;
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f & SELECT) {
+ v1= editmesh_get_x_mirror_vert(obedit, em, eve->co);
+ if(v1) {
+ eve->f &= ~SELECT;
+ v1->f |= SELECT;
+ }
+ }
+ }
+ }
+}
+
+void EM_automerge(int update)
+{
+// XXX int len;
+
+// if ((scene->automerge) &&
+// (obedit && obedit->type==OB_MESH) &&
+// (((Mesh*)obedit->data)->mr==NULL)
+// ) {
+// len = removedoublesflag(1, 1, scene->toolsettings->doublimit);
+// if (len) {
+// em->totvert -= len; /* saves doing a countall */
+// if (update) {
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+// }
+// }
+// }
+}
+
+/* ****************************** SELECTION ROUTINES **************** */
+
+unsigned int em_solidoffs=0, em_wireoffs=0, em_vertoffs=0; /* set in drawobject.c ... for colorindices */
+
+/* facilities for border select and circle select */
+static char *selbuf= NULL;
+
+/* opengl doesn't support concave... */
+static void draw_triangulated(short mcords[][2], short tot)
+{
+ ListBase lb={NULL, NULL};
+ DispList *dl;
+ float *fp;
+ int a;
+
+ /* make displist */
+ dl= MEM_callocN(sizeof(DispList), "poly disp");
+ dl->type= DL_POLY;
+ dl->parts= 1;
+ dl->nr= tot;
+ dl->verts= fp= MEM_callocN(tot*3*sizeof(float), "poly verts");
+ BLI_addtail(&lb, dl);
+
+ for(a=0; a<tot; a++, fp+=3) {
+ fp[0]= (float)mcords[a][0];
+ fp[1]= (float)mcords[a][1];
+ }
+
+ /* do the fill */
+ filldisplist(&lb, &lb);
+
+ /* do the draw */
+ dl= lb.first; /* filldisplist adds in head of list */
+ if(dl->type==DL_INDEX3) {
+ int *index;
+
+ a= dl->parts;
+ fp= dl->verts;
+ index= dl->index;
+ glBegin(GL_TRIANGLES);
+ while(a--) {
+ glVertex3fv(fp+3*index[0]);
+ glVertex3fv(fp+3*index[1]);
+ glVertex3fv(fp+3*index[2]);
+ index+= 3;
+ }
+ glEnd();
+ }
+
+ freedisplist(&lb);
+}
+
+
+/* reads rect, and builds selection array for quick lookup */
+/* returns if all is OK */
+int EM_init_backbuf_border(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
+{
+ struct ImBuf *buf;
+ unsigned int *dr;
+ int a;
+
+ if(vc->obedit==NULL || vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
+
+ buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ if(buf==NULL) return 0;
+ if(em_vertoffs==0) return 0;
+
+ dr = buf->rect;
+
+ /* build selection lookup */
+ selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
+
+ a= (xmax-xmin+1)*(ymax-ymin+1);
+ while(a--) {
+ if(*dr>0 && *dr<=em_vertoffs)
+ selbuf[*dr]= 1;
+ dr++;
+ }
+ IMB_freeImBuf(buf);
+ return 1;
+}
+
+int EM_check_backbuf(unsigned int index)
+{
+ if(selbuf==NULL) return 1;
+ if(index>0 && index<=em_vertoffs)
+ return selbuf[index];
+ return 0;
+}
+
+void EM_free_backbuf(void)
+{
+ if(selbuf) MEM_freeN(selbuf);
+ selbuf= NULL;
+}
+
+/* mcords is a polygon mask
+ - grab backbuffer,
+ - draw with black in backbuffer,
+ - grab again and compare
+ returns 'OK'
+*/
+int EM_mask_init_backbuf_border(ViewContext *vc, short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
+{
+ unsigned int *dr, *drm;
+ struct ImBuf *buf, *bufmask;
+ int a;
+
+ /* method in use for face selecting too */
+ if(vc->obedit==NULL) {
+ if(FACESEL_PAINT_TEST);
+ else return 0;
+ }
+ else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
+
+ buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ if(buf==NULL) return 0;
+ if(em_vertoffs==0) return 0;
+
+ dr = buf->rect;
+
+ /* draw the mask */
+ glDisable(GL_DEPTH_TEST);
+
+ glColor3ub(0, 0, 0);
+
+ /* yah, opengl doesn't do concave... tsk! */
+ ED_region_pixelspace(vc->ar);
+ draw_triangulated(mcords, tot);
+
+ glBegin(GL_LINE_LOOP); /* for zero sized masks, lines */
+ for(a=0; a<tot; a++) glVertex2s(mcords[a][0], mcords[a][1]);
+ glEnd();
+
+ glFinish(); /* to be sure readpixels sees mask */
+
+ /* grab mask */
+ bufmask= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ drm = bufmask->rect;
+ if(bufmask==NULL) return 0; /* only when mem alloc fails, go crash somewhere else! */
+
+ /* build selection lookup */
+ selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
+
+ a= (xmax-xmin+1)*(ymax-ymin+1);
+ while(a--) {
+ if(*dr>0 && *dr<=em_vertoffs && *drm==0) selbuf[*dr]= 1;
+ dr++; drm++;
+ }
+ IMB_freeImBuf(buf);
+ IMB_freeImBuf(bufmask);
+ return 1;
+
+}
+
+/* circle shaped sample area */
+int EM_init_backbuf_circle(ViewContext *vc, short xs, short ys, short rads)
+{
+ struct ImBuf *buf;
+ unsigned int *dr;
+ short xmin, ymin, xmax, ymax, xc, yc;
+ int radsq;
+
+ /* method in use for face selecting too */
+ if(vc->obedit==NULL) {
+ if(FACESEL_PAINT_TEST);
+ else return 0;
+ }
+ else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
+
+ xmin= xs-rads; xmax= xs+rads;
+ ymin= ys-rads; ymax= ys+rads;
+ buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ if(em_vertoffs==0) return 0;
+ if(buf==NULL) return 0;
+
+ dr = buf->rect;
+
+ /* build selection lookup */
+ selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
+ radsq= rads*rads;
+ for(yc= -rads; yc<=rads; yc++) {
+ for(xc= -rads; xc<=rads; xc++, dr++) {
+ if(xc*xc + yc*yc < radsq) {
+ if(*dr>0 && *dr<=em_vertoffs) selbuf[*dr]= 1;
+ }
+ }
+ }
+
+ IMB_freeImBuf(buf);
+ return 1;
+
+}
+
+static void findnearestvert__doClosest(void *userData, EditVert *eve, int x, int y, int index)
+{
+ struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } *data = userData;
+
+ if (data->pass==0) {
+ if (index<=data->lastIndex)
+ return;
+ } else {
+ if (index>data->lastIndex)
+ return;
+ }
+
+ if (data->dist>3) {
+ int temp = abs(data->mval[0] - x) + abs(data->mval[1]- y);
+ if ((eve->f&1) == data->select) {
+ if (data->strict == 1)
+ return;
+ else
+ temp += 5;
+ }
+
+ if (temp<data->dist) {
+ data->dist = temp;
+ data->closest = eve;
+ data->closestIndex = index;
+ }
+ }
+}
+
+
+
+
+static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int index)
+{
+ EditMesh *em= (EditMesh *)handle;
+ EditVert *eve = BLI_findlink(&em->verts, index-1);
+
+ if(eve && (eve->f & SELECT)) return 0;
+ return 1;
+}
+/**
+ * findnearestvert
+ *
+ * dist (in/out): minimal distance to the nearest and at the end, actual distance
+ * sel: selection bias
+ * if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts
+ * if 0, unselected vertice are given the bias
+ * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased
+ */
+EditVert *findnearestvert(ViewContext *vc, int *dist, short sel, short strict)
+{
+ if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)){
+ int distance;
+ unsigned int index;
+ EditVert *eve;
+
+ if(strict) index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_wireoffs, 0xFFFFFF, &distance, strict, vc->em, findnearestvert__backbufIndextest);
+ else index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_wireoffs, 0xFFFFFF, &distance, 0, NULL, NULL);
+
+ eve = BLI_findlink(&vc->em->verts, index-1);
+
+ if(eve && distance < *dist) {
+ *dist = distance;
+ return eve;
+ } else {
+ return NULL;
+ }
+
+ }
+ else {
+ struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } data;
+ static int lastSelectedIndex=0;
+ static EditVert *lastSelected=NULL;
+
+ if (lastSelected && BLI_findlink(&vc->em->verts, lastSelectedIndex)!=lastSelected) {
+ lastSelectedIndex = 0;
+ lastSelected = NULL;
+ }
+
+ data.lastIndex = lastSelectedIndex;
+ data.mval[0] = vc->mval[0];
+ data.mval[1] = vc->mval[1];
+ data.select = sel;
+ data.dist = *dist;
+ data.strict = strict;
+ data.closest = NULL;
+ data.closestIndex = 0;
+
+ data.pass = 0;
+ mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
+
+ if (data.dist>3) {
+ data.pass = 1;
+ mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
+ }
+
+ *dist = data.dist;
+ lastSelected = data.closest;
+ lastSelectedIndex = data.closestIndex;
+
+ return data.closest;
+ }
+}
+
+/* returns labda for closest distance v1 to line-piece v2-v3 */
+static float labda_PdistVL2Dfl( float *v1, float *v2, float *v3)
+{
+ float rc[2], len;
+
+ rc[0]= v3[0]-v2[0];
+ rc[1]= v3[1]-v2[1];
+ len= rc[0]*rc[0]+ rc[1]*rc[1];
+ if(len==0.0f)
+ return 0.0f;
+
+ return ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
+}
+
+/* note; uses v3d, so needs active 3d window */
+static void findnearestedge__doClosest(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
+{
+ struct { ViewContext vc; float mval[2]; int dist; EditEdge *closest; } *data = userData;
+ float v1[2], v2[2];
+ int distance;
+
+ v1[0] = x0;
+ v1[1] = y0;
+ v2[0] = x1;
+ v2[1] = y1;
+
+ distance= PdistVL2Dfl(data->mval, v1, v2);
+
+ if(eed->f & SELECT) distance+=5;
+ if(distance < data->dist) {
+ if(data->vc.rv3d->rflag & RV3D_CLIPPING) {
+ float labda= labda_PdistVL2Dfl(data->mval, v1, v2);
+ float vec[3];
+
+ vec[0]= eed->v1->co[0] + labda*(eed->v2->co[0] - eed->v1->co[0]);
+ vec[1]= eed->v1->co[1] + labda*(eed->v2->co[1] - eed->v1->co[1]);
+ vec[2]= eed->v1->co[2] + labda*(eed->v2->co[2] - eed->v1->co[2]);
+ Mat4MulVecfl(data->vc.obedit->obmat, vec);
+
+ if(view3d_test_clipping(data->vc.rv3d, vec)==0) {
+ data->dist = distance;
+ data->closest = eed;
+ }
+ }
+ else {
+ data->dist = distance;
+ data->closest = eed;
+ }
+ }
+}
+EditEdge *findnearestedge(ViewContext *vc, int *dist)
+{
+
+ if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
+ int distance;
+ unsigned int index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_solidoffs, em_wireoffs, &distance,0, NULL, NULL);
+ EditEdge *eed = BLI_findlink(&vc->em->edges, index-1);
+
+ if (eed && distance<*dist) {
+ *dist = distance;
+ return eed;
+ } else {
+ return NULL;
+ }
+ }
+ else {
+ struct { ViewContext vc; float mval[2]; int dist; EditEdge *closest; } data;
+
+ data.vc= *vc;
+ data.mval[0] = vc->mval[0];
+ data.mval[1] = vc->mval[1];
+ data.dist = *dist;
+ data.closest = NULL;
+
+ mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, 2);
+
+ *dist = data.dist;
+ return data.closest;
+ }
+}
+
+static void findnearestface__getDistance(void *userData, EditFace *efa, int x, int y, int index)
+{
+ struct { short mval[2]; int dist; EditFace *toFace; } *data = userData;
+
+ if (efa==data->toFace) {
+ int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
+
+ if (temp<data->dist)
+ data->dist = temp;
+ }
+}
+static void findnearestface__doClosest(void *userData, EditFace *efa, int x, int y, int index)
+{
+ struct { short mval[2], pass; int dist, lastIndex, closestIndex; EditFace *closest; } *data = userData;
+
+ if (data->pass==0) {
+ if (index<=data->lastIndex)
+ return;
+ } else {
+ if (index>data->lastIndex)
+ return;
+ }
+
+ if (data->dist>3) {
+ int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
+
+ if (temp<data->dist) {
+ data->dist = temp;
+ data->closest = efa;
+ data->closestIndex = index;
+ }
+ }
+}
+static EditFace *findnearestface(ViewContext *vc, int *dist)
+{
+
+ if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
+ unsigned int index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]);
+ EditFace *efa = BLI_findlink(&vc->em->faces, index-1);
+
+ if (efa) {
+ struct { short mval[2]; int dist; EditFace *toFace; } data;
+
+ data.mval[0] = vc->mval[0];
+ data.mval[1] = vc->mval[1];
+ data.dist = 0x7FFF; /* largest short */
+ data.toFace = efa;
+
+ mesh_foreachScreenFace(vc, findnearestface__getDistance, &data);
+
+ if(vc->em->selectmode == SCE_SELECT_FACE || data.dist<*dist) { /* only faces, no dist check */
+ *dist= data.dist;
+ return efa;
+ }
+ }
+
+ return NULL;
+ }
+ else {
+ struct { short mval[2], pass; int dist, lastIndex, closestIndex; EditFace *closest; } data;
+ static int lastSelectedIndex=0;
+ static EditFace *lastSelected=NULL;
+
+ if (lastSelected && BLI_findlink(&vc->em->faces, lastSelectedIndex)!=lastSelected) {
+ lastSelectedIndex = 0;
+ lastSelected = NULL;
+ }
+
+ data.lastIndex = lastSelectedIndex;
+ data.mval[0] = vc->mval[0];
+ data.mval[1] = vc->mval[1];
+ data.dist = *dist;
+ data.closest = NULL;
+ data.closestIndex = 0;
+
+ data.pass = 0;
+ mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
+
+ if (data.dist>3) {
+ data.pass = 1;
+ mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
+ }
+
+ *dist = data.dist;
+ lastSelected = data.closest;
+ lastSelectedIndex = data.closestIndex;
+
+ return data.closest;
+ }
+}
+
+/* best distance based on screen coords.
+ use em->selectmode to define how to use
+ selected vertices and edges get disadvantage
+ return 1 if found one
+*/
+static int unified_findnearest(ViewContext *vc, EditVert **eve, EditEdge **eed, EditFace **efa)
+{
+ EditMesh *em= vc->em;
+ int dist= 75;
+
+ *eve= NULL;
+ *eed= NULL;
+ *efa= NULL;
+
+ /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
+ view3d_validate_backbuf(vc);
+
+ if(em->selectmode & SCE_SELECT_VERTEX)
+ *eve= findnearestvert(vc, &dist, SELECT, 0);
+ if(em->selectmode & SCE_SELECT_FACE)
+ *efa= findnearestface(vc, &dist);
+
+ dist-= 20; /* since edges select lines, we give dots advantage of 20 pix */
+ if(em->selectmode & SCE_SELECT_EDGE)
+ *eed= findnearestedge(vc, &dist);
+
+ /* return only one of 3 pointers, for frontbuffer redraws */
+ if(*eed) {
+ *efa= NULL; *eve= NULL;
+ }
+ else if(*efa) {
+ *eve= NULL;
+ }
+
+ return (*eve || *eed || *efa);
+}
+
+
+/* **************** SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */
+
+/* selects new faces/edges/verts based on the
+ existing selection
+
+FACES GROUP
+ mode 1: same material
+ mode 2: same image
+ mode 3: same area
+ mode 4: same perimeter
+ mode 5: same normal
+ mode 6: same co-planer
+*/
+
+static EnumPropertyItem prop_simface_types[] = {
+ {1, "MATERIAL", "Material", ""},
+ {2, "IMAGE", "Image", ""},
+ {3, "AREA", "Area", ""},
+ {4, "PERIMETER", "Perimeter", ""},
+ {5, "NORMAL", "Normal", ""},
+ {6, "COPLANAR", "Co-planar", ""},
+ {0, NULL, NULL, NULL}
+};
+
+
+/* this as a way to compare the ares, perim of 2 faces thay will scale to different sizes
+*0.5 so smaller faces arnt ALWAYS selected with a thresh of 1.0 */
+#define SCALE_CMP(a,b) ((a+a*thresh >= b) && (a-(a*thresh*0.5) <= b))
+
+static int similar_face_select__internal(Scene *scene, EditMesh *em, int mode)
+{
+ EditFace *efa, *base_efa=NULL;
+ unsigned int selcount=0; /*count how many new faces we select*/
+
+ /*deselcount, count how many deselected faces are left, so we can bail out early
+ also means that if there are no deselected faces, we can avoid a lot of looping */
+ unsigned int deselcount=0;
+ float thresh= scene->toolsettings->select_thresh;
+ short ok=0;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if (!efa->h) {
+ if (efa->f & SELECT) {
+ efa->f1=1;
+ ok=1;
+ } else {
+ efa->f1=0;
+ deselcount++; /* a deselected face we may select later */
+ }
+ }
+ }
+
+ if (!ok || !deselcount) /* no data selected OR no more data to select */
+ return 0;
+
+ /*if mode is 3 then record face areas, 4 record perimeter */
+ if (mode==3) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->tmp.fp= EM_face_area(efa);
+ }
+ } else if (mode==4) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->tmp.fp= EM_face_perimeter(efa);
+ }
+ }
+
+ for(base_efa= em->faces.first; base_efa; base_efa= base_efa->next) {
+ if (base_efa->f1) { /* This was one of the faces originaly selected */
+ if (mode==1) { /* same material */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if (
+ !(efa->f & SELECT) &&
+ !efa->h &&
+ base_efa->mat_nr == efa->mat_nr
+ ) {
+ EM_select_face(efa, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ } else if (mode==2) { /* same image */
+ MTFace *tf, *base_tf;
+
+ base_tf = (MTFace*)CustomData_em_get(&em->fdata, base_efa->data,
+ CD_MTFACE);
+
+ if(!base_tf)
+ return selcount;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if (!(efa->f & SELECT) && !efa->h) {
+ tf = (MTFace*)CustomData_em_get(&em->fdata, efa->data,
+ CD_MTFACE);
+
+ if(base_tf->tpage == tf->tpage) {
+ EM_select_face(efa, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ }
+ } else if (mode==3 || mode==4) { /* same area OR same perimeter, both use the same temp var */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if (
+ (!(efa->f & SELECT) && !efa->h) &&
+ SCALE_CMP(base_efa->tmp.fp, efa->tmp.fp)
+ ) {
+ EM_select_face(efa, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ } else if (mode==5) { /* same normal */
+ float angle;
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if (!(efa->f & SELECT) && !efa->h) {
+ angle= VecAngle2(base_efa->n, efa->n);
+ if (angle/180.0<=thresh) {
+ EM_select_face(efa, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ }
+ } else if (mode==6) { /* same planer */
+ float angle, base_dot, dot;
+ base_dot= Inpf(base_efa->cent, base_efa->n);
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if (!(efa->f & SELECT) && !efa->h) {
+ angle= VecAngle2(base_efa->n, efa->n);
+ if (angle/180.0<=thresh) {
+ dot=Inpf(efa->cent, base_efa->n);
+ if (fabs(base_dot-dot) <= thresh) {
+ EM_select_face(efa, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ }
+ }
+ }
+ }
+ } /* end base_efa loop */
+ return selcount;
+}
+
+static int similar_face_select_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Mesh *me= obedit->data;
+ EditMesh *em= BKE_mesh_get_editmesh(me);
+
+ int selcount = similar_face_select__internal(scene, em, RNA_int_get(op->ptr, "type"));
+
+ if (selcount) {
+ /* here was an edge-mode only select flush case, has to be generalized */
+ EM_selectmode_flush(em);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ BKE_mesh_end_editmesh(me, em);
+ return OPERATOR_FINISHED;
+ }
+
+ BKE_mesh_end_editmesh(me, em);
+ return OPERATOR_CANCELLED;
+}
+
+void MESH_OT_faces_select_similar(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Similar Face Select";
+ ot->idname= "MESH_OT_faces_select_similar";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= similar_face_select_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", prop_simface_types, 0, "Type", "");
+}
+
+/* ***************************************************** */
+
+/*
+EDGE GROUP
+ mode 1: same length
+ mode 2: same direction
+ mode 3: same number of face users
+ mode 4: similar face angles.
+ mode 5: similar crease
+ mode 6: similar seam
+ mode 7: similar sharp
+*/
+
+static EnumPropertyItem prop_simedge_types[] = {
+ {1, "LENGTH", "Length", ""},
+ {2, "DIR", "Direction", ""},
+ {3, "FACE", "Amount of Vertices in Face", ""},
+ {4, "FACE_ANGLE", "Face Angles", ""},
+ {5, "CREASE", "Crease", ""},
+ {6, "SEAM", "Seam", ""},
+ {7, "SHARP", "Sharpness", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int similar_edge_select__internal(Scene *scene, EditMesh *em, int mode)
+{
+ EditEdge *eed, *base_eed=NULL;
+ unsigned int selcount=0; /* count how many new edges we select*/
+
+ /*count how many visible selected edges there are,
+ so we can return when there are none left */
+ unsigned int deselcount=0;
+
+ short ok=0;
+ float thresh= scene->toolsettings->select_thresh;
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if (!eed->h) {
+ if (eed->f & SELECT) {
+ eed->f1=1;
+ ok=1;
+ } else {
+ eed->f1=0;
+ deselcount++;
+ }
+ /* set all eed->tmp.l to 0 we use it later.
+ for counting face users*/
+ eed->tmp.l=0;
+ eed->f2=0; /* only for mode 4, edge animations */
+ }
+ }
+
+ if (!ok || !deselcount) /* no data selected OR no more data to select*/
+ return 0;
+
+ if (mode==1) { /*store length*/
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if (!eed->h) /* dont calc data for hidden edges*/
+ eed->tmp.fp= VecLenf(eed->v1->co, eed->v2->co);
+ }
+ } else if (mode==3) { /*store face users*/
+ EditFace *efa;
+ /* cound how many faces each edge uses use tmp->l */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->e1->tmp.l++;
+ efa->e2->tmp.l++;
+ efa->e3->tmp.l++;
+ if (efa->e4) efa->e4->tmp.l++;
+ }
+ } else if (mode==4) { /*store edge angles */
+ EditFace *efa;
+ int j;
+ /* cound how many faces each edge uses use tmp.l */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ /* here we use the edges temp data to assign a face
+ if a face has alredy been assigned (eed->f2==1)
+ we calculate the angle between the current face and
+ the edges previously found face.
+ store the angle in eed->tmp.fp (loosing the face eed->tmp.f)
+ but tagging eed->f2==2, so we know not to look at it again.
+ This only works for edges that connect to 2 faces. but its good enough
+ */
+
+ /* se we can loop through face edges*/
+ j=0;
+ eed= efa->e1;
+ while (j<4) {
+ if (j==1) eed= efa->e2;
+ else if (j==2) eed= efa->e3;
+ else if (j==3) {
+ eed= efa->e4;
+ if (!eed)
+ break;
+ } /* done looping */
+
+ if (!eed->h) { /* dont calc data for hidden edges*/
+ if (eed->f2==2)
+ break;
+ else if (eed->f2==0) /* first access, assign the face */
+ eed->tmp.f= efa;
+ else if (eed->f2==1) /* second, we assign the angle*/
+ eed->tmp.fp= VecAngle2(eed->tmp.f->n, efa->n)/180;
+ eed->f2++; /* f2==0 no face assigned. f2==1 one face found. f2==2 angle calculated.*/
+ }
+ j++;
+ }
+ }
+ }
+
+ for(base_eed= em->edges.first; base_eed; base_eed= base_eed->next) {
+ if (base_eed->f1) {
+ if (mode==1) { /* same length */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if (
+ !(eed->f & SELECT) &&
+ !eed->h &&
+ SCALE_CMP(base_eed->tmp.fp, eed->tmp.fp)
+ ) {
+ EM_select_edge(eed, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ } else if (mode==2) { /* same direction */
+ float base_dir[3], dir[3], angle;
+ VecSubf(base_dir, base_eed->v1->co, base_eed->v2->co);
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if (!(eed->f & SELECT) && !eed->h) {
+ VecSubf(dir, eed->v1->co, eed->v2->co);
+ angle= VecAngle2(base_dir, dir);
+
+ if (angle>90) /* use the smallest angle between the edges */
+ angle= fabs(angle-180.0f);
+
+ if (angle/90.0<=thresh) {
+ EM_select_edge(eed, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ }
+ } else if (mode==3) { /* face users */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if (
+ !(eed->f & SELECT) &&
+ !eed->h &&
+ base_eed->tmp.l==eed->tmp.l
+ ) {
+ EM_select_edge(eed, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ } else if (mode==4 && base_eed->f2==2) { /* edge angles, f2==2 means the edge has an angle. */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if (
+ !(eed->f & SELECT) &&
+ !eed->h &&
+ eed->f2==2 &&
+ (fabs(base_eed->tmp.fp-eed->tmp.fp)<=thresh)
+ ) {
+ EM_select_edge(eed, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ } else if (mode==5) { /* edge crease */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if (
+ !(eed->f & SELECT) &&
+ !eed->h &&
+ (fabs(base_eed->crease-eed->crease) <= thresh)
+ ) {
+ EM_select_edge(eed, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ } else if (mode==6) { /* edge seam */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if (
+ !(eed->f & SELECT) &&
+ !eed->h &&
+ (eed->seam == base_eed->seam)
+ ) {
+ EM_select_edge(eed, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ } else if (mode==7) { /* edge sharp */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if (
+ !(eed->f & SELECT) &&
+ !eed->h &&
+ (eed->sharp == base_eed->sharp)
+ ) {
+ EM_select_edge(eed, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ }
+ }
+ }
+ return selcount;
+}
+/* wrap the above function but do selection flushing edge to face */
+static int similar_edge_select_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Mesh *me= obedit->data;
+ EditMesh *em= BKE_mesh_get_editmesh(me);
+
+ int selcount = similar_edge_select__internal(scene, em, RNA_int_get(op->ptr, "type"));
+
+ if (selcount) {
+ /* here was an edge-mode only select flush case, has to be generalized */
+ EM_selectmode_flush(em);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ BKE_mesh_end_editmesh(me, em);
+ return OPERATOR_FINISHED;
+ }
+
+ BKE_mesh_end_editmesh(me, em);
+ return OPERATOR_CANCELLED;
+}
+
+void MESH_OT_edges_select_similar(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Similar Edge Select";
+ ot->idname= "MESH_OT_edges_select_similar";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= similar_edge_select_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", prop_simedge_types, 0, "Type", "");
+}
+
+/* ********************************* */
+
+/*
+VERT GROUP
+ mode 1: same normal
+ mode 2: same number of face users
+ mode 3: same vertex groups
+*/
+static EnumPropertyItem prop_simvertex_types[] = {
+ {0, "NORMAL", "Normal", ""},
+ {1, "FACE", "Amount of Vertices in Face", ""},
+ {2, "VGROUP", "Vertex Groups", ""},
+ {0, NULL, NULL, NULL}
+};
+
+
+static int similar_vert_select_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Mesh *me= obedit->data;
+ EditMesh *em= BKE_mesh_get_editmesh(me);
+ EditVert *eve, *base_eve=NULL;
+ unsigned int selcount=0; /* count how many new edges we select*/
+
+ /*count how many visible selected edges there are,
+ so we can return when there are none left */
+ unsigned int deselcount=0;
+
+ short ok=0;
+ float thresh= scene->toolsettings->select_thresh;
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if (!eve->h) {
+ if (eve->f & SELECT) {
+ eve->f1=1;
+ ok=1;
+ } else {
+ eve->f1=0;
+ deselcount++;
+ }
+ /* set all eve->tmp.l to 0 we use them later.*/
+ eve->tmp.l=0;
+ }
+
+ }
+
+ if (!ok || !deselcount) { /* no data selected OR no more data to select*/
+ BKE_mesh_end_editmesh(me, em);
+ return 0;
+ }
+
+ if(RNA_enum_is_equal(op->ptr, "type", "FACE")) {
+ /* store face users */
+ EditFace *efa;
+
+ /* count how many faces each edge uses use tmp->l */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->v1->tmp.l++;
+ efa->v2->tmp.l++;
+ efa->v3->tmp.l++;
+ if (efa->v4) efa->v4->tmp.l++;
+ }
+ }
+
+
+ for(base_eve= em->verts.first; base_eve; base_eve= base_eve->next) {
+ if (base_eve->f1) {
+
+ if(RNA_enum_is_equal(op->ptr, "type", "NORMAL")) {
+ float angle;
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if (!(eve->f & SELECT) && !eve->h) {
+ angle= VecAngle2(base_eve->no, eve->no);
+ if (angle/180.0<=thresh) {
+ eve->f |= SELECT;
+ selcount++;
+ deselcount--;
+ if (!deselcount) {/*have we selected all posible faces?, if so return*/
+ BKE_mesh_end_editmesh(me, em);
+ return selcount;
+ }
+ }
+ }
+ }
+ }
+ else if(RNA_enum_is_equal(op->ptr, "type", "FACE")) {
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if (
+ !(eve->f & SELECT) &&
+ !eve->h &&
+ base_eve->tmp.l==eve->tmp.l
+ ) {
+ eve->f |= SELECT;
+ selcount++;
+ deselcount--;
+ if (!deselcount) {/*have we selected all posible faces?, if so return*/
+ BKE_mesh_end_editmesh(me, em);
+ return selcount;
+ }
+ }
+ }
+ }
+ else if(RNA_enum_is_equal(op->ptr, "type", "VGROUP")) {
+ MDeformVert *dvert, *base_dvert;
+ short i, j; /* weight index */
+
+ base_dvert= CustomData_em_get(&em->vdata, base_eve->data,
+ CD_MDEFORMVERT);
+
+ if (!base_dvert || base_dvert->totweight == 0) {
+ BKE_mesh_end_editmesh(me, em);
+ return selcount;
+ }
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ dvert= CustomData_em_get(&em->vdata, eve->data,
+ CD_MDEFORMVERT);
+
+ if (dvert && !(eve->f & SELECT) && !eve->h && dvert->totweight) {
+ /* do the extra check for selection in the following if, so were not
+ checking verts that may be alredy selected */
+ for (i=0; base_dvert->totweight >i && !(eve->f & SELECT); i++) {
+ for (j=0; dvert->totweight >j; j++) {
+ if (base_dvert->dw[i].def_nr==dvert->dw[j].def_nr) {
+ eve->f |= SELECT;
+ selcount++;
+ deselcount--;
+ if (!deselcount) { /*have we selected all posible faces?, if so return*/
+ BKE_mesh_end_editmesh(me, em);
+ return selcount;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } /* end basevert loop */
+
+ if(selcount) {
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ BKE_mesh_end_editmesh(me, em);
+ return OPERATOR_FINISHED;
+ }
+
+ BKE_mesh_end_editmesh(me, em);
+ return OPERATOR_CANCELLED;
+}
+
+void MESH_OT_vertices_select_similar(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Similar Vertex Select";
+ ot->idname= "MESH_OT_vertices_select_similar";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= similar_vert_select_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", prop_simvertex_types, 0, "Type", "");
+}
+
+/* ******************************************* */
+
+
+int mesh_layers_menu_charlen(CustomData *data, int type)
+{
+ int i, len = 0;
+ /* see if there is a duplicate */
+ for(i=0; i<data->totlayer; i++) {
+ if((&data->layers[i])->type == type) {
+ /* we could count the chars here but we'll just assumeme each
+ * is 32 chars with some room for the menu text - 40 should be fine */
+ len+=40;
+ }
+ }
+ return len;
+}
+
+/* this function adds menu text into an existing string.
+ * this string's size should be allocated with mesh_layers_menu_charlen */
+void mesh_layers_menu_concat(CustomData *data, int type, char *str)
+{
+ int i, count = 0;
+ char *str_pt = str;
+ CustomDataLayer *layer;
+
+ /* see if there is a duplicate */
+ for(i=0; i<data->totlayer; i++) {
+ layer = &data->layers[i];
+ if(layer->type == type) {
+ str_pt += sprintf(str_pt, "%s%%x%d|", layer->name, count);
+ count++;
+ }
+ }
+}
+
+int mesh_layers_menu(CustomData *data, int type) {
+ int ret;
+ char *str_pt, *str;
+
+ str_pt = str = MEM_mallocN(mesh_layers_menu_charlen(data, type) + 18, "layer menu");
+ str[0] = '\0';
+
+ str_pt += sprintf(str_pt, "Layers%%t|");
+
+ mesh_layers_menu_concat(data, type, str_pt);
+
+ ret = pupmenu(str);
+ MEM_freeN(str);
+ return ret;
+}
+
+void EM_mesh_copy_edge(EditMesh *em, short type)
+{
+ EditSelection *ese;
+ short change=0;
+
+ EditEdge *eed, *eed_act;
+ float vec[3], vec_mid[3], eed_len, eed_len_act;
+
+ if (!em) return;
+
+ ese = em->selected.last;
+ if (!ese) return;
+
+ eed_act = (EditEdge*)ese->data;
+
+ switch (type) {
+ case 1: /* copy crease */
+ for(eed=em->edges.first; eed; eed=eed->next) {
+ if (eed->f & SELECT && eed != eed_act && eed->crease != eed_act->crease) {
+ eed->crease = eed_act->crease;
+ change = 1;
+ }
+ }
+ break;
+ case 2: /* copy bevel weight */
+ for(eed=em->edges.first; eed; eed=eed->next) {
+ if (eed->f & SELECT && eed != eed_act && eed->bweight != eed_act->bweight) {
+ eed->bweight = eed_act->bweight;
+ change = 1;
+ }
+ }
+ break;
+
+ case 3: /* copy length */
+ eed_len_act = VecLenf(eed_act->v1->co, eed_act->v2->co);
+ for(eed=em->edges.first; eed; eed=eed->next) {
+ if (eed->f & SELECT && eed != eed_act) {
+
+ eed_len = VecLenf(eed->v1->co, eed->v2->co);
+
+ if (eed_len == eed_len_act) continue;
+ /* if this edge is zero length we cont do anything with it*/
+ if (eed_len == 0.0f) continue;
+ if (eed_len_act == 0.0f) {
+ VecAddf(vec_mid, eed->v1->co, eed->v2->co);
+ VecMulf(vec_mid, 0.5);
+ VECCOPY(eed->v1->co, vec_mid);
+ VECCOPY(eed->v2->co, vec_mid);
+ } else {
+ /* copy the edge length */
+ VecAddf(vec_mid, eed->v1->co, eed->v2->co);
+ VecMulf(vec_mid, 0.5);
+
+ /* SCALE 1 */
+ VecSubf(vec, eed->v1->co, vec_mid);
+ VecMulf(vec, eed_len_act/eed_len);
+ VecAddf(eed->v1->co, vec, vec_mid);
+
+ /* SCALE 2 */
+ VecSubf(vec, eed->v2->co, vec_mid);
+ VecMulf(vec, eed_len_act/eed_len);
+ VecAddf(eed->v2->co, vec, vec_mid);
+ }
+ change = 1;
+ }
+ }
+
+ if (change)
+ recalc_editnormals(em);
+
+ break;
+ }
+
+ if (change) {
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ }
+}
+
+void EM_mesh_copy_face(EditMesh *em, wmOperator *op, short type)
+{
+ short change=0;
+
+ EditFace *efa, *efa_act;
+ MTFace *tf, *tf_act = NULL;
+ MCol *mcol, *mcol_act = NULL;
+ if (!em) return;
+ efa_act = EM_get_actFace(em, 0);
+
+ if (!efa_act) return;
+
+ tf_act = CustomData_em_get(&em->fdata, efa_act->data, CD_MTFACE);
+ mcol_act = CustomData_em_get(&em->fdata, efa_act->data, CD_MCOL);
+
+ switch (type) {
+ case 1: /* copy material */
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT && efa->mat_nr != efa_act->mat_nr) {
+ efa->mat_nr = efa_act->mat_nr;
+ change = 1;
+ }
+ }
+ break;
+ case 2: /* copy image */
+ if (!tf_act) {
+ BKE_report(op->reports, RPT_ERROR, "mesh has no uv/image layers");
+ return;
+ }
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT && efa != efa_act) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if (tf_act->tpage) {
+ tf->tpage = tf_act->tpage;
+ tf->mode |= TF_TEX;
+ } else {
+ tf->tpage = NULL;
+ tf->mode &= ~TF_TEX;
+ }
+ tf->tile= tf_act->tile;
+ change = 1;
+ }
+ }
+ break;
+
+ case 3: /* copy UV's */
+ if (!tf_act) {
+ BKE_report(op->reports, RPT_ERROR, "mesh has no uv/image layers");
+ return;
+ }
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT && efa != efa_act) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ memcpy(tf->uv, tf_act->uv, sizeof(tf->uv));
+ change = 1;
+ }
+ }
+ break;
+ case 4: /* mode's */
+ if (!tf_act) {
+ BKE_report(op->reports, RPT_ERROR, "mesh has no uv/image layers");
+ return;
+ }
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT && efa != efa_act) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ tf->mode= tf_act->mode;
+ change = 1;
+ }
+ }
+ break;
+ case 5: /* copy transp's */
+ if (!tf_act) {
+ BKE_report(op->reports, RPT_ERROR, "mesh has no uv/image layers");
+ return;
+ }
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT && efa != efa_act) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ tf->transp= tf_act->transp;
+ change = 1;
+ }
+ }
+ break;
+
+ case 6: /* copy vcols's */
+ if (!mcol_act) {
+ BKE_report(op->reports, RPT_ERROR, "mesh has no color layers");
+ return;
+ } else {
+ /* guess the 4th color if needs be */
+ float val =- 1;
+
+ if (!efa_act->v4) {
+ /* guess the othe vale, we may need to use it
+ *
+ * Modifying the 4th value of the mcol is ok here since its not seen
+ * on a triangle
+ * */
+ val = ((float)(mcol_act->r + (mcol_act+1)->r + (mcol_act+2)->r)) / 3; CLAMP(val, 0, 255);
+ (mcol_act+3)->r = (char)val;
+
+ val = ((float)(mcol_act->g + (mcol_act+1)->g + (mcol_act+2)->g)) / 3; CLAMP(val, 0, 255);
+ (mcol_act+3)->g = (char)val;
+
+ val = ((float)(mcol_act->b + (mcol_act+1)->b + (mcol_act+2)->b)) / 3; CLAMP(val, 0, 255);
+ (mcol_act+3)->b = (char)val;
+ }
+
+
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT && efa != efa_act) {
+ /* TODO - make copy from tri to quad guess the 4th vert */
+ mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
+ memcpy(mcol, mcol_act, sizeof(MCol)*4);
+ change = 1;
+ }
+ }
+ }
+ break;
+ }
+
+ if (change) {
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ }
+}
+
+
+void EM_mesh_copy_face_layer(EditMesh *em, wmOperator *op, short type)
+{
+ short change=0;
+
+ EditFace *efa;
+ MTFace *tf, *tf_from;
+ MCol *mcol, *mcol_from;
+
+ if (!em) return;
+
+ switch(type) {
+ case 7:
+ case 8:
+ case 9:
+ if (CustomData_number_of_layers(&em->fdata, CD_MTFACE)<2) {
+ BKE_report(op->reports, RPT_ERROR, "mesh does not have multiple uv/image layers");
+ return;
+ } else {
+ int layer_orig_idx, layer_idx;
+
+ layer_idx = mesh_layers_menu(&em->fdata, CD_MTFACE);
+ if (layer_idx<0) return;
+
+ /* warning, have not updated mesh pointers however this is not needed since we swicth back */
+ layer_orig_idx = CustomData_get_active_layer(&em->fdata, CD_MTFACE);
+ if (layer_idx==layer_orig_idx)
+ return;
+
+ /* get the tfaces */
+ CustomData_set_layer_active(&em->fdata, CD_MTFACE, (int)layer_idx);
+ /* store the tfaces in our temp */
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT) {
+ efa->tmp.p = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ }
+ }
+ CustomData_set_layer_active(&em->fdata, CD_MTFACE, layer_orig_idx);
+ }
+ break;
+
+ case 10: /* select vcol layers - make sure this stays in sync with above code */
+ if (CustomData_number_of_layers(&em->fdata, CD_MCOL)<2) {
+ BKE_report(op->reports, RPT_ERROR, "mesh does not have multiple color layers");
+ return;
+ } else {
+ int layer_orig_idx, layer_idx;
+
+ layer_idx = mesh_layers_menu(&em->fdata, CD_MCOL);
+ if (layer_idx<0) return;
+
+ /* warning, have not updated mesh pointers however this is not needed since we swicth back */
+ layer_orig_idx = CustomData_get_active_layer(&em->fdata, CD_MCOL);
+ if (layer_idx==layer_orig_idx)
+ return;
+
+ /* get the tfaces */
+ CustomData_set_layer_active(&em->fdata, CD_MCOL, (int)layer_idx);
+ /* store the tfaces in our temp */
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT) {
+ efa->tmp.p = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
+ }
+ }
+ CustomData_set_layer_active(&em->fdata, CD_MCOL, layer_orig_idx);
+
+ }
+ break;
+ }
+
+ /* layer copy only - sanity checks done above */
+ switch (type) {
+ case 7: /* copy UV's only */
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT) {
+ tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ memcpy(tf->uv, tf_from->uv, sizeof(tf->uv));
+ change = 1;
+ }
+ }
+ break;
+ case 8: /* copy image settings only */
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT) {
+ tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if (tf_from->tpage) {
+ tf->tpage = tf_from->tpage;
+ tf->mode |= TF_TEX;
+ } else {
+ tf->tpage = NULL;
+ tf->mode &= ~TF_TEX;
+ }
+ tf->tile= tf_from->tile;
+ change = 1;
+ }
+ }
+ break;
+ case 9: /* copy all tface info */
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT) {
+ tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ memcpy(tf->uv, ((MTFace *)efa->tmp.p)->uv, sizeof(tf->uv));
+ tf->tpage = tf_from->tpage;
+ tf->mode = tf_from->mode;
+ tf->transp = tf_from->transp;
+ change = 1;
+ }
+ }
+ break;
+ case 10:
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT) {
+ mcol_from = (MCol *)efa->tmp.p;
+ mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
+ memcpy(mcol, mcol_from, sizeof(MCol)*4);
+ change = 1;
+ }
+ }
+ break;
+ }
+
+ if (change) {
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ }
+}
+
+
+/* ctrl+c in mesh editmode */
+void mesh_copy_menu(EditMesh *em, wmOperator *op)
+{
+ EditSelection *ese;
+ int ret;
+ if (!em) return;
+
+ ese = em->selected.last;
+
+ /* Faces can have a NULL ese, so dont return on a NULL ese here */
+
+ if(ese && ese->type == EDITVERT) {
+ /* EditVert *ev, *ev_act = (EditVert*)ese->data;
+ ret= pupmenu(""); */
+ } else if(ese && ese->type == EDITEDGE) {
+ ret= pupmenu("Copy Active Edge to Selected%t|Crease%x1|Bevel Weight%x2|Length%x3");
+ if (ret<1) return;
+
+ EM_mesh_copy_edge(em, ret);
+
+ } else if(ese==NULL || ese->type == EDITFACE) {
+ ret= pupmenu(
+ "Copy Face Selected%t|"
+ "Active Material%x1|Active Image%x2|Active UV Coords%x3|"
+ "Active Mode%x4|Active Transp%x5|Active Vertex Colors%x6|%l|"
+
+ "TexFace UVs from layer%x7|"
+ "TexFace Images from layer%x8|"
+ "TexFace All from layer%x9|"
+ "Vertex Colors from layer%x10");
+ if (ret<1) return;
+
+ if (ret<=6) {
+ EM_mesh_copy_face(em, op, ret);
+ } else {
+ EM_mesh_copy_face_layer(em, op, ret);
+ }
+ }
+}
+
+
+/* **************** LOOP SELECTS *************** */
+
+/* selects quads in loop direction of indicated edge */
+/* only flush over edges with valence <= 2 */
+void faceloop_select(EditMesh *em, EditEdge *startedge, int select)
+{
+ EditEdge *eed;
+ EditFace *efa;
+ int looking= 1;
+
+ /* in eed->f1 we put the valence (amount of faces in edge) */
+ /* in eed->f2 we put tagged flag as correct loop */
+ /* in efa->f1 we put tagged flag as correct to select */
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->f1= 0;
+ eed->f2= 0;
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->f1= 0;
+ if(efa->h==0) {
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->e4) efa->e4->f1++;
+ }
+ }
+
+ /* tag startedge OK*/
+ startedge->f2= 1;
+
+ while(looking) {
+ looking= 0;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->h==0 && efa->e4 && efa->f1==0) { /* not done quad */
+ if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */
+
+ /* if edge tagged, select opposing edge and mark face ok */
+ if(efa->e1->f2) {
+ efa->e3->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ else if(efa->e2->f2) {
+ efa->e4->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ if(efa->e3->f2) {
+ efa->e1->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ if(efa->e4->f2) {
+ efa->e2->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ }
+ }
+ }
+ }
+
+ /* (de)select the faces */
+ if(select!=2) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f1) EM_select_face(efa, select);
+ }
+ }
+}
+
+
+/* helper for edgeloop_select, checks for eed->f2 tag in faces */
+static int edge_not_in_tagged_face(EditMesh *em, EditEdge *eed)
+{
+ EditFace *efa;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->h==0) {
+ if(efa->e1==eed || efa->e2==eed || efa->e3==eed || efa->e4==eed) { /* edge is in face */
+ if(efa->e1->f2 || efa->e2->f2 || efa->e3->f2 || (efa->e4 && efa->e4->f2)) { /* face is tagged */
+ return 0;
+ }
+ }
+ }
+ }
+ return 1;
+}
+
+/* selects or deselects edges that:
+- if edges has 2 faces:
+ - has vertices with valence of 4
+ - not shares face with previous edge
+- if edge has 1 face:
+ - has vertices with valence 4
+ - not shares face with previous edge
+ - but also only 1 face
+- if edge no face:
+ - has vertices with valence 2
+*/
+static void edgeloop_select(EditMesh *em, EditEdge *starteed, int select)
+{
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+ int looking= 1;
+
+ /* in f1 we put the valence (amount of edges in a vertex, or faces in edge) */
+ /* in eed->f2 and efa->f1 we put tagged flag as correct loop */
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ eve->f1= 0;
+ eve->f2= 0;
+ }
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->f1= 0;
+ eed->f2= 0;
+ if((eed->h & 1)==0) { /* fgon edges add to valence too */
+ eed->v1->f1++; eed->v2->f1++;
+ }
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->f1= 0;
+ if(efa->h==0) {
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->e4) efa->e4->f1++;
+ }
+ }
+
+ /* looped edges & vertices get tagged f2 */
+ starteed->f2= 1;
+ if(starteed->v1->f1<5) starteed->v1->f2= 1;
+ if(starteed->v2->f1<5) starteed->v2->f2= 1;
+ /* sorry, first edge isnt even ok */
+ if(starteed->v1->f2==0 && starteed->v2->f2==0) looking= 0;
+
+ while(looking) {
+ looking= 0;
+
+ /* find correct valence edges which are not tagged yet, but connect to tagged one */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->h==0 && eed->f2==0) { /* edge not hidden, not tagged */
+ if( (eed->v1->f1<5 && eed->v1->f2) || (eed->v2->f1<5 && eed->v2->f2)) { /* valence of vertex OK, and is tagged */
+ /* new edge is not allowed to be in face with tagged edge */
+ if(edge_not_in_tagged_face(em, eed)) {
+ if(eed->f1==starteed->f1) { /* same amount of faces */
+ looking= 1;
+ eed->f2= 1;
+ if(eed->v2->f1<5) eed->v2->f2= 1;
+ if(eed->v1->f1<5) eed->v1->f2= 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ /* and we do the select */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f2) EM_select_edge(eed, select);
+ }
+}
+
+/*
+ Almostly exactly the same code as faceloop select
+*/
+static void edgering_select(EditMesh *em, EditEdge *startedge, int select)
+{
+ EditEdge *eed;
+ EditFace *efa;
+ int looking= 1;
+
+ /* in eed->f1 we put the valence (amount of faces in edge) */
+ /* in eed->f2 we put tagged flag as correct loop */
+ /* in efa->f1 we put tagged flag as correct to select */
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->f1= 0;
+ eed->f2= 0;
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->f1= 0;
+ if(efa->h==0) {
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->e4) efa->e4->f1++;
+ }
+ }
+
+ /* tag startedge OK */
+ startedge->f2= 1;
+
+ while(looking) {
+ looking= 0;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->e4 && efa->f1==0 && !efa->h) { /* not done quad */
+ if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */
+
+ /* if edge tagged, select opposing edge and mark face ok */
+ if(efa->e1->f2) {
+ efa->e3->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ else if(efa->e2->f2) {
+ efa->e4->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ if(efa->e3->f2) {
+ efa->e1->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ if(efa->e4->f2) {
+ efa->e2->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ }
+ }
+ }
+ }
+
+ /* (de)select the edges */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f2) EM_select_edge(eed, select);
+ }
+}
+
+static int loop_multiselect(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+ EditEdge *eed;
+ EditEdge **edarray;
+ int edindex, edfirstcount;
+ int looptype= RNA_boolean_get(op->ptr, "ring");
+
+ /* sets em->totedgesel */
+ EM_nedges_selected(em);
+
+ edarray = MEM_mallocN(sizeof(EditEdge*)*em->totedgesel,"edge array");
+ edindex = 0;
+ edfirstcount = em->totedgesel;
+
+ for(eed=em->edges.first; eed; eed=eed->next){
+ if(eed->f&SELECT){
+ edarray[edindex] = eed;
+ edindex += 1;
+ }
+ }
+
+ if(looptype){
+ for(edindex = 0; edindex < edfirstcount; edindex +=1){
+ eed = edarray[edindex];
+ edgering_select(em, eed,SELECT);
+ }
+ EM_selectmode_flush(em);
+ }
+ else{
+ for(edindex = 0; edindex < edfirstcount; edindex +=1){
+ eed = edarray[edindex];
+ edgeloop_select(em, eed,SELECT);
+ }
+ EM_selectmode_flush(em);
+ }
+ MEM_freeN(edarray);
+// if (EM_texFaceCheck())
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_loop_multi_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Multi Select Loops";
+ ot->idname= "MESH_OT_loop_multi_select";
+
+ /* api callbacks */
+ ot->exec= loop_multiselect;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "ring", 0, "Ring", "");
+}
+
+
+/* ***************** MAIN MOUSE SELECTION ************** */
+
+
+/* ***************** loop select (non modal) ************** */
+
+static void mouse_mesh_loop(bContext *C, short mval[2], short extend, short ring)
+{
+ ViewContext vc;
+ EditMesh *em;
+ EditEdge *eed;
+ int select= 1;
+ int dist= 50;
+
+ em_setup_viewcontext(C, &vc);
+ vc.mval[0]= mval[0];
+ vc.mval[1]= mval[1];
+ em= vc.em;
+
+ eed= findnearestedge(&vc, &dist);
+ if(eed) {
+ if(extend==0) EM_clear_flag_all(em, SELECT);
+
+ if((eed->f & SELECT)==0) select=1;
+ else if(extend) select=0;
+
+ if(em->selectmode & SCE_SELECT_FACE) {
+ faceloop_select(em, eed, select);
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ if(ring)
+ edgering_select(em, eed, select);
+ else
+ edgeloop_select(em, eed, select);
+ }
+ else if(em->selectmode & SCE_SELECT_VERTEX) {
+ if(ring)
+ edgering_select(em, eed, select);
+ else
+ edgeloop_select(em, eed, select);
+ }
+
+ EM_selectmode_flush(em);
+// if (EM_texFaceCheck())
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
+ }
+}
+
+static int mesh_select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+
+ view3d_operator_needs_opengl(C);
+
+ mouse_mesh_loop(C, event->mval, RNA_boolean_get(op->ptr, "extend"),
+ RNA_boolean_get(op->ptr, "ring"));
+
+ /* cannot do tweaks for as long this keymap is after transform map */
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_loop_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Loop Select";
+ ot->idname= "MESH_OT_loop_select";
+
+ /* api callbacks */
+ ot->invoke= mesh_select_loop_invoke;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
+ RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", "");
+}
+
+/* ******************* mesh shortest path select, uses prev-selected edge ****************** */
+
+/* since you want to create paths with multiple selects, it doesn't have extend option */
+static void mouse_mesh_shortest_path(bContext *C, short mval[2])
+{
+ ViewContext vc;
+ EditMesh *em;
+ EditEdge *eed;
+ int dist= 50;
+
+ em_setup_viewcontext(C, &vc);
+ vc.mval[0]= mval[0];
+ vc.mval[1]= mval[1];
+ em= vc.em;
+
+ eed= findnearestedge(&vc, &dist);
+ if(eed) {
+ Mesh *me= vc.obedit->data;
+ int path = 0;
+
+ if (em->selected.last) {
+ EditSelection *ese = em->selected.last;
+
+ if(ese && ese->type == EDITEDGE) {
+ EditEdge *eed_act;
+ eed_act = (EditEdge*)ese->data;
+ if (eed_act != eed) {
+ if (edgetag_shortest_path(vc.scene, em, eed_act, eed)) {
+ EM_remove_selection(em, eed_act, EDITEDGE);
+ path = 1;
+ }
+ }
+ }
+ }
+ if (path==0) {
+ int act = (edgetag_context_check(vc.scene, eed)==0);
+ edgetag_context_set(vc.scene, eed, act); /* switch the edge option */
+ }
+
+ EM_selectmode_flush(em);
+
+ /* even if this is selected it may not be in the selection list */
+ if(edgetag_context_check(vc.scene, eed)==0)
+ EM_remove_selection(em, eed, EDITEDGE);
+ else
+ EM_store_selection(em, eed, EDITEDGE);
+
+ /* force drawmode for mesh */
+ switch (vc.scene->toolsettings->edge_mode) {
+
+ case EDGE_MODE_TAG_SEAM:
+ me->drawflag |= ME_DRAWSEAMS;
+ break;
+ case EDGE_MODE_TAG_SHARP:
+ me->drawflag |= ME_DRAWSHARP;
+ break;
+ case EDGE_MODE_TAG_CREASE:
+ me->drawflag |= ME_DRAWCREASES;
+ break;
+ case EDGE_MODE_TAG_BEVEL:
+ me->drawflag |= ME_DRAWBWEIGHTS;
+ break;
+ }
+
+ DAG_object_flush_update(vc.scene, vc.obedit, OB_RECALC_DATA);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
+ }
+}
+
+
+static int mesh_shortest_path_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+
+ view3d_operator_needs_opengl(C);
+
+ mouse_mesh_shortest_path(C, event->mval);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_shortest_path(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Shortest Path Select";
+ ot->idname= "MESH_OT_select_shortest_path";
+
+ /* api callbacks */
+ ot->invoke= mesh_shortest_path_select_invoke;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
+}
+
+
+/* ************************************************** */
+
+
+/* here actual select happens */
+/* gets called via generic mouse select operator */
+void mouse_mesh(bContext *C, short mval[2], short extend)
+{
+ ViewContext vc;
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+
+ /* setup view context for argument to callbacks */
+ em_setup_viewcontext(C, &vc);
+ vc.mval[0]= mval[0];
+ vc.mval[1]= mval[1];
+
+ if(unified_findnearest(&vc, &eve, &eed, &efa)) {
+
+ if(extend==0) EM_clear_flag_all(vc.em, SELECT);
+
+ if(efa) {
+ /* set the last selected face */
+ EM_set_actFace(vc.em, efa);
+
+ if( (efa->f & SELECT)==0 ) {
+ EM_store_selection(vc.em, efa, EDITFACE);
+ EM_select_face_fgon(vc.em, efa, 1);
+ }
+ else if(extend) {
+ EM_remove_selection(vc.em, efa, EDITFACE);
+ EM_select_face_fgon(vc.em, efa, 0);
+ }
+ }
+ else if(eed) {
+ if((eed->f & SELECT)==0) {
+ EM_store_selection(vc.em, eed, EDITEDGE);
+ EM_select_edge(eed, 1);
+ }
+ else if(extend) {
+ EM_remove_selection(vc.em, eed, EDITEDGE);
+ EM_select_edge(eed, 0);
+ }
+ }
+ else if(eve) {
+ if((eve->f & SELECT)==0) {
+ eve->f |= SELECT;
+ EM_store_selection(vc.em, eve, EDITVERT);
+ }
+ else if(extend){
+ EM_remove_selection(vc.em, eve, EDITVERT);
+ eve->f &= ~SELECT;
+ }
+ }
+
+ EM_selectmode_flush(vc.em);
+
+// if (EM_texFaceCheck()) {
+
+ if (efa && efa->mat_nr != vc.obedit->actcol-1) {
+ vc.obedit->actcol= efa->mat_nr+1;
+ vc.em->mat_nr= efa->mat_nr;
+// BIF_preview_changed(ID_MA);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
+
+}
+
+/* *********** select linked ************* */
+
+/* for use with selectconnected_delimit_mesh only! */
+#define is_edge_delimit_ok(eed) ((eed->tmp.l == 1) && (eed->seam==0))
+#define is_face_tag(efa) is_edge_delimit_ok(efa->e1) || is_edge_delimit_ok(efa->e2) || is_edge_delimit_ok(efa->e3) || (efa->v4 && is_edge_delimit_ok(efa->e4))
+
+#define face_tag(efa)\
+if(efa->v4) efa->tmp.l= efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= efa->e4->tmp.l= 1;\
+else efa->tmp.l= efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= 1;
+
+/* all - 1) use all faces for extending the selection 2) only use the mouse face
+* sel - 1) select 0) deselect
+* */
+
+/* legacy warning, this function combines too much :) */
+static int select_linked_limited_invoke(ViewContext *vc, short all, short sel)
+{
+ EditMesh *em= vc->em;
+ EditFace *efa;
+ EditEdge *eed;
+ EditVert *eve;
+ short done=1, change=0;
+
+ if(em->faces.first==0) return OPERATOR_CANCELLED;
+
+ /* flag all edges+faces as off*/
+ for(eed= em->edges.first; eed; eed= eed->next)
+ eed->tmp.l=0;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->tmp.l = 0;
+ }
+
+ if (all) {
+ // XXX verts?
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f & SELECT)
+ eed->tmp.l= 1;
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+
+ if (efa->f & SELECT) {
+ face_tag(efa);
+ } else {
+ efa->tmp.l = 0;
+ }
+ }
+ }
+ else {
+ if( unified_findnearest(vc, &eve, &eed, &efa) ) {
+
+ if(efa) {
+ efa->tmp.l = 1;
+ face_tag(efa);
+ }
+ else if(eed)
+ eed->tmp.l= 1;
+ else {
+ for(eed= em->edges.first; eed; eed= eed->next)
+ if(eed->v1==eve || eed->v2==eve)
+ break;
+ eed->tmp.l= 1;
+ }
+ }
+ else
+ return OPERATOR_FINISHED;
+ }
+
+ while(done==1) {
+ done= 0;
+ /* simple algo - select all faces that have a selected edge
+ * this intern selects the edge, repeat until nothing is left to do */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if ((efa->tmp.l == 0) && (!efa->h)) {
+ if (is_face_tag(efa)) {
+ face_tag(efa);
+ done= 1;
+ }
+ }
+ }
+ }
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if (efa->tmp.l) {
+ if (sel) {
+ if (!(efa->f & SELECT)) {
+ EM_select_face(efa, 1);
+ change = 1;
+ }
+ } else {
+ if (efa->f & SELECT) {
+ EM_select_face(efa, 0);
+ change = 1;
+ }
+ }
+ }
+ }
+
+ if (!change)
+ return OPERATOR_CANCELLED;
+
+ if (!sel) /* make sure de-selecting faces didnt de-select the verts/edges connected to selected faces, this is common with boundries */
+ for(efa= em->faces.first; efa; efa= efa->next)
+ if (efa->f & SELECT)
+ EM_select_face(efa, 1);
+
+ // if (EM_texFaceCheck())
+
+ return OPERATOR_FINISHED;
+}
+
+#undef is_edge_delimit_ok
+#undef is_face_tag
+#undef face_tag
+
+static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ViewContext vc;
+ EditVert *eve, *v1, *v2;
+ EditEdge *eed;
+ EditFace *efa;
+ short done=1, toggle=0;
+ int sel= !RNA_boolean_get(op->ptr, "deselect");
+ int limit= RNA_boolean_get(op->ptr, "limit");
+
+ /* unified_finednearest needs ogl */
+ view3d_operator_needs_opengl(C);
+
+ /* setup view context for argument to callbacks */
+ em_setup_viewcontext(C, &vc);
+
+ if(vc.em->edges.first==0) return OPERATOR_CANCELLED;
+
+ vc.mval[0]= event->mval[0];
+ vc.mval[1]= event->mval[1];
+
+ /* return warning! */
+ if(limit) {
+ int retval= select_linked_limited_invoke(&vc, 0, sel);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ return retval;
+ }
+
+ if( unified_findnearest(&vc, &eve, &eed, &efa)==0 ) {
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_CANCELLED;
+ }
+
+ /* clear test flags */
+ for(v1= vc.em->verts.first; v1; v1= v1->next) v1->f1= 0;
+
+ /* start vertex/face/edge */
+ if(eve) eve->f1= 1;
+ else if(eed) eed->v1->f1= eed->v2->f1= 1;
+ else efa->v1->f1= efa->v2->f1= efa->v3->f1= 1;
+
+ /* set flag f1 if affected */
+ while(done==1) {
+ done= 0;
+ toggle++;
+
+ if(toggle & 1) eed= vc.em->edges.first;
+ else eed= vc.em->edges.last;
+
+ while(eed) {
+ v1= eed->v1;
+ v2= eed->v2;
+
+ if(eed->h==0) {
+ if(v1->f1 && v2->f1==0) {
+ v2->f1= 1;
+ done= 1;
+ }
+ else if(v1->f1==0 && v2->f1) {
+ v1->f1= 1;
+ done= 1;
+ }
+ }
+
+ if(toggle & 1) eed= eed->next;
+ else eed= eed->prev;
+ }
+ }
+
+ /* now use vertex f1 flag to select/deselect */
+ for(eed= vc.em->edges.first; eed; eed= eed->next) {
+ if(eed->v1->f1 && eed->v2->f1)
+ EM_select_edge(eed, sel);
+ }
+ for(efa= vc.em->faces.first; efa; efa= efa->next) {
+ if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1))
+ EM_select_face(efa, sel);
+ }
+ /* no flush needed, connected geometry is done */
+
+// if (EM_texFaceCheck())
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_linked_pick(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Linked";
+ ot->idname= "MESH_OT_select_linked_pick";
+
+ /* api callbacks */
+ ot->invoke= select_linked_pick_invoke;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
+ RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", "");
+}
+
+
+/* ************************* */
+
+void selectconnected_mesh_all(EditMesh *em)
+{
+ EditVert *v1,*v2;
+ EditEdge *eed;
+ short done=1, toggle=0;
+
+ if(em->edges.first==0) return;
+
+ while(done==1) {
+ done= 0;
+
+ toggle++;
+ if(toggle & 1) eed= em->edges.first;
+ else eed= em->edges.last;
+
+ while(eed) {
+ v1= eed->v1;
+ v2= eed->v2;
+ if(eed->h==0) {
+ if(v1->f & SELECT) {
+ if( (v2->f & SELECT)==0 ) {
+ v2->f |= SELECT;
+ done= 1;
+ }
+ }
+ else if(v2->f & SELECT) {
+ if( (v1->f & SELECT)==0 ) {
+ v1->f |= SELECT;
+ done= 1;
+ }
+ }
+ }
+ if(toggle & 1) eed= eed->next;
+ else eed= eed->prev;
+ }
+ }
+
+ /* now use vertex select flag to select rest */
+ EM_select_flush(em);
+
+ // if (EM_texFaceCheck())
+}
+
+static int select_linked_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
+
+ if( RNA_boolean_get(op->ptr, "limit") ) {
+ ViewContext vc;
+ em_setup_viewcontext(C, &vc);
+ select_linked_limited_invoke(&vc, 1, 1);
+ }
+ else
+ selectconnected_mesh_all(em);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Linked All";
+ ot->idname= "MESH_OT_select_linked";
+
+ /* api callbacks */
+ ot->exec= select_linked_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", "");
+}
+
+
+/* ************************* */
+
+/* swap is 0 or 1, if 1 it hides not selected */
+void EM_hide_mesh(EditMesh *em, int swap)
+{
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+ int a;
+
+ if(em==NULL) return;
+
+ /* hide happens on least dominant select mode, and flushes up, not down! (helps preventing errors in subsurf) */
+ /* - vertex hidden, always means edge is hidden too
+ - edge hidden, always means face is hidden too
+ - face hidden, only set face hide
+ - then only flush back down what's absolute hidden
+ */
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if((eve->f & SELECT)!=swap) {
+ eve->f &= ~SELECT;
+ eve->h= 1;
+ }
+ }
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->v1->h || eed->v2->h) {
+ eed->h |= 1;
+ eed->f &= ~SELECT;
+ }
+ }
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->e1->h & 1 || efa->e2->h & 1 || efa->e3->h & 1 || (efa->e4 && efa->e4->h & 1)) {
+ efa->h= 1;
+ efa->f &= ~SELECT;
+ }
+ }
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if((eed->f & SELECT)!=swap) {
+ eed->h |= 1;
+ EM_select_edge(eed, 0);
+ }
+ }
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->e1->h & 1 || efa->e2->h & 1 || efa->e3->h & 1 || (efa->e4 && efa->e4->h & 1)) {
+ efa->h= 1;
+ efa->f &= ~SELECT;
+ }
+ }
+ }
+ else {
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if((efa->f & SELECT)!=swap) {
+ efa->h= 1;
+ EM_select_face(efa, 0);
+ }
+ }
+ }
+
+ /* flush down, only whats 100% hidden */
+ for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
+ for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0;
+
+ if(em->selectmode & SCE_SELECT_FACE) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->h) a= 1; else a= 2;
+ efa->e1->f1 |= a;
+ efa->e2->f1 |= a;
+ efa->e3->f1 |= a;
+ if(efa->e4) efa->e4->f1 |= a;
+ /* When edges are not delt with in their own loop, we need to explicitly re-selct select edges that are joined to unselected faces */
+ if (swap && (em->selectmode == SCE_SELECT_FACE) && (efa->f & SELECT)) {
+ EM_select_face(efa, 1);
+ }
+ }
+ }
+
+ if(em->selectmode >= SCE_SELECT_EDGE) {
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f1==1) eed->h |= 1;
+ if(eed->h & 1) a= 1; else a= 2;
+ eed->v1->f1 |= a;
+ eed->v2->f1 |= a;
+ }
+ }
+
+ if(em->selectmode >= SCE_SELECT_VERTEX) {
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f1==1) eve->h= 1;
+ }
+ }
+
+ em->totedgesel= em->totfacesel= em->totvertsel= 0;
+// if(EM_texFaceCheck())
+
+ // DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+}
+
+static int hide_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+
+ EM_hide_mesh(em, RNA_boolean_get(op->ptr, "unselected"));
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_hide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Hide Selection";
+ ot->idname= "MESH_OT_hide";
+
+ /* api callbacks */
+ ot->exec= hide_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected.");
+}
+
+void EM_reveal_mesh(EditMesh *em)
+{
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+
+ if(em==NULL) return;
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->h) {
+ eve->h= 0;
+ eve->f |= SELECT;
+ }
+ }
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->h & 1) {
+ eed->h &= ~1;
+ if(em->selectmode & SCE_SELECT_VERTEX);
+ else EM_select_edge(eed, 1);
+ }
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->h) {
+ efa->h= 0;
+ if(em->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX));
+ else EM_select_face(efa, 1);
+ }
+ }
+
+ EM_fgon_flags(em); /* redo flags and indices for fgons */
+ EM_selectmode_flush(em);
+
+// if (EM_texFaceCheck())
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+}
+
+static int reveal_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+
+ EM_reveal_mesh(em);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_reveal(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Reveal Hidden";
+ ot->idname= "MESH_OT_reveal";
+
+ /* api callbacks */
+ ot->exec= reveal_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+void select_faces_by_numverts(EditMesh *em, wmOperator *op, int numverts)
+{
+ EditFace *efa;
+
+ /* Selects trias/qiads or isolated verts, and edges that do not have 2 neighboring
+ * faces
+ */
+
+ /* for loose vertices/edges, we first select all, loop below will deselect */
+ if(numverts==5)
+ EM_set_flag_all(em, SELECT);
+ else if(em->selectmode!=SCE_SELECT_FACE) {
+ BKE_report(op->reports, RPT_ERROR, "Only works in face selection mode");
+ return;
+ }
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if (efa->e4) {
+ EM_select_face(efa, (numverts==4) );
+ }
+ else {
+ EM_select_face(efa, (numverts==3) );
+ }
+ }
+
+// if (EM_texFaceCheck())
+
+}
+
+static int select_sharp_edges_exec(bContext *C, wmOperator *op)
+{
+ /* Find edges that have exactly two neighboring faces,
+ * check the angle between those faces, and if angle is
+ * small enough, select the edge
+ */
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+ EditEdge *eed;
+ EditFace *efa;
+ EditFace **efa1;
+ EditFace **efa2;
+ intptr_t edgecount = 0, i = 0;
+ float sharpness, fsharpness;
+
+ /* 'standard' behaviour - check if selected, then apply relevant selection */
+
+ if(em->selectmode==SCE_SELECT_FACE) {
+ BKE_report(op->reports, RPT_ERROR, "Doesn't work in face selection mode");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ sharpness= RNA_float_get(op->ptr, "sharpness");
+ fsharpness = ((180.0 - sharpness) * M_PI) / 180.0;
+
+ /* count edges, use tmp.l */
+ eed= em->edges.first;
+ while(eed) {
+ edgecount++;
+ eed->tmp.l = i;
+ eed= eed->next;
+ ++i;
+ }
+
+ /* for each edge, we want a pointer to two adjacent faces */
+ efa1 = MEM_callocN(edgecount*sizeof(EditFace *),
+ "pairs of edit face pointers");
+ efa2 = MEM_callocN(edgecount*sizeof(EditFace *),
+ "pairs of edit face pointers");
+
+#define face_table_edge(eed) { \
+ i = eed->tmp.l; \
+ if (i != -1) { \
+ if (efa1[i]) { \
+ if (efa2[i]) { \
+ /* invalidate, edge has more than two neighbors */ \
+ eed->tmp.l = -1; \
+ } \
+ else { \
+ efa2[i] = efa; \
+ } \
+ } \
+ else { \
+ efa1[i] = efa; \
+ } \
+ } \
+ }
+
+ /* find the adjacent faces of each edge, we want only two */
+ efa= em->faces.first;
+ while(efa) {
+ face_table_edge(efa->e1);
+ face_table_edge(efa->e2);
+ face_table_edge(efa->e3);
+ if (efa->e4) {
+ face_table_edge(efa->e4);
+ }
+ efa= efa->next;
+ }
+
+#undef face_table_edge
+
+ eed = em->edges.first;
+ while(eed) {
+ i = eed->tmp.l;
+ if (i != -1) {
+ /* edge has two or less neighboring faces */
+ if ( (efa1[i]) && (efa2[i]) ) {
+ /* edge has exactly two neighboring faces, check angle */
+ float angle;
+ angle = saacos(efa1[i]->n[0]*efa2[i]->n[0] +
+ efa1[i]->n[1]*efa2[i]->n[1] +
+ efa1[i]->n[2]*efa2[i]->n[2]);
+ if (fabs(angle) >= fsharpness)
+ EM_select_edge(eed, 1);
+ }
+ }
+
+ eed= eed->next;
+ }
+
+ MEM_freeN(efa1);
+ MEM_freeN(efa2);
+
+// if (EM_texFaceCheck())
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); //TODO is this needed ?
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_edges_select_sharp(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Sharp Edges";
+ ot->idname= "MESH_OT_edges_select_sharp";
+
+ /* api callbacks */
+ ot->exec= select_sharp_edges_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_float(ot->srna, "sharpness", 0.01f, 0.0f, FLT_MAX, "sharpness", "", 0.0f, 180.0f);
+}
+
+
+static void select_linked_flat_faces(EditMesh *em, wmOperator *op, float sharpness)
+{
+ /* Find faces that are linked to selected faces that are
+ * relatively flat (angle between faces is higher than
+ * specified angle)
+ */
+ EditEdge *eed;
+ EditFace *efa;
+ EditFace **efa1;
+ EditFace **efa2;
+ intptr_t edgecount = 0, i, faceselcount=0, faceselcountold=0;
+ float fsharpness;
+
+ if(em->selectmode!=SCE_SELECT_FACE) {
+ BKE_report(op->reports, RPT_ERROR, "Only works in face selection mode");
+ return;
+ }
+
+ fsharpness = ((180.0 - sharpness) * M_PI) / 180.0;
+
+ i=0;
+ /* count edges, use tmp.l */
+ eed= em->edges.first;
+ while(eed) {
+ edgecount++;
+ eed->tmp.l = i;
+ eed= eed->next;
+ ++i;
+ }
+
+ /* for each edge, we want a pointer to two adjacent faces */
+ efa1 = MEM_callocN(edgecount*sizeof(EditFace *),
+ "pairs of edit face pointers");
+ efa2 = MEM_callocN(edgecount*sizeof(EditFace *),
+ "pairs of edit face pointers");
+
+#define face_table_edge(eed) { \
+ i = eed->tmp.l; \
+ if (i != -1) { \
+ if (efa1[i]) { \
+ if (efa2[i]) { \
+ /* invalidate, edge has more than two neighbors */ \
+ eed->tmp.l = -1; \
+ } \
+ else { \
+ efa2[i] = efa; \
+ } \
+ } \
+ else { \
+ efa1[i] = efa; \
+ } \
+ } \
+ }
+
+ /* find the adjacent faces of each edge, we want only two */
+ efa= em->faces.first;
+ while(efa) {
+ face_table_edge(efa->e1);
+ face_table_edge(efa->e2);
+ face_table_edge(efa->e3);
+ if (efa->e4) {
+ face_table_edge(efa->e4);
+ }
+
+ /* while were at it, count the selected faces */
+ if (efa->f & SELECT) ++faceselcount;
+
+ efa= efa->next;
+ }
+
+#undef face_table_edge
+
+ eed= em->edges.first;
+ while(eed) {
+ i = eed->tmp.l;
+ if (i != -1) {
+ /* edge has two or less neighboring faces */
+ if ( (efa1[i]) && (efa2[i]) ) {
+ /* edge has exactly two neighboring faces, check angle */
+ float angle;
+ angle = saacos(efa1[i]->n[0]*efa2[i]->n[0] +
+ efa1[i]->n[1]*efa2[i]->n[1] +
+ efa1[i]->n[2]*efa2[i]->n[2]);
+ /* invalidate: edge too sharp */
+ if (fabs(angle) >= fsharpness)
+ eed->tmp.l = -1;
+ }
+ else {
+ /* invalidate: less than two neighbors */
+ eed->tmp.l = -1;
+ }
+ }
+
+ eed= eed->next;
+ }
+
+#define select_flat_neighbor(eed) { \
+ i = eed->tmp.l; \
+ if (i!=-1) { \
+ if (! (efa1[i]->f & SELECT) ) { \
+ EM_select_face(efa1[i], 1); \
+ ++faceselcount; \
+ } \
+ if (! (efa2[i]->f & SELECT) ) { \
+ EM_select_face(efa2[i], 1); \
+ ++faceselcount; \
+ } \
+ } \
+ }
+
+ while (faceselcount != faceselcountold) {
+ faceselcountold = faceselcount;
+
+ efa= em->faces.first;
+ while(efa) {
+ if (efa->f & SELECT) {
+ select_flat_neighbor(efa->e1);
+ select_flat_neighbor(efa->e2);
+ select_flat_neighbor(efa->e3);
+ if (efa->e4) {
+ select_flat_neighbor(efa->e4);
+ }
+ }
+ efa= efa->next;
+ }
+ }
+
+#undef select_flat_neighbor
+
+ MEM_freeN(efa1);
+ MEM_freeN(efa2);
+
+// if (EM_texFaceCheck())
+
+}
+
+static int select_linked_flat_faces_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+
+ select_linked_flat_faces(em, op, RNA_float_get(op->ptr, "sharpness"));
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_faces_select_linked_flat(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Linked Flat Faces";
+ ot->idname= "MESH_OT_faces_select_linked_flat";
+
+ /* api callbacks */
+ ot->exec= select_linked_flat_faces_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_float(ot->srna, "sharpness", 0.0f, 0.0f, FLT_MAX, "sharpness", "", 0.0f, 180.0f);
+}
+
+void select_non_manifold(EditMesh *em, wmOperator *op )
+{
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+
+ /* Selects isolated verts, and edges that do not have 2 neighboring
+ * faces
+ */
+
+ if(em->selectmode==SCE_SELECT_FACE) {
+ BKE_report(op->reports, RPT_ERROR, "Doesn't work in face selection mode");
+ return;
+ }
+
+ eve= em->verts.first;
+ while(eve) {
+ /* this will count how many edges are connected
+ * to this vert */
+ eve->f1= 0;
+ eve= eve->next;
+ }
+
+ eed= em->edges.first;
+ while(eed) {
+ /* this will count how many faces are connected to
+ * this edge */
+ eed->f1= 0;
+ /* increase edge count for verts */
+ ++eed->v1->f1;
+ ++eed->v2->f1;
+ eed= eed->next;
+ }
+
+ efa= em->faces.first;
+ while(efa) {
+ /* increase face count for edges */
+ ++efa->e1->f1;
+ ++efa->e2->f1;
+ ++efa->e3->f1;
+ if (efa->e4)
+ ++efa->e4->f1;
+ efa= efa->next;
+ }
+
+ /* select verts that are attached to an edge that does not
+ * have 2 neighboring faces */
+ eed= em->edges.first;
+ while(eed) {
+ if (eed->h==0 && eed->f1 != 2) {
+ EM_select_edge(eed, 1);
+ }
+ eed= eed->next;
+ }
+
+ /* select isolated verts */
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ eve= em->verts.first;
+ while(eve) {
+ if (eve->f1 == 0) {
+ if (!eve->h) eve->f |= SELECT;
+ }
+ eve= eve->next;
+ }
+ }
+
+// if (EM_texFaceCheck())
+
+}
+
+static int select_non_manifold_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+
+ select_non_manifold(em, op);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_non_manifold(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Non Manifold";
+ ot->idname= "MESH_OT_select_non_manifold";
+
+ /* api callbacks */
+ ot->exec= select_non_manifold_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+void EM_select_swap(EditMesh *em) /* exported for UV */
+{
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->h==0) {
+ if(eve->f & SELECT) eve->f &= ~SELECT;
+ else eve->f|= SELECT;
+ }
+ }
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->h==0) {
+ EM_select_edge(eed, !(eed->f & SELECT));
+ }
+ }
+ }
+ else {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->h==0) {
+ EM_select_face(efa, !(efa->f & SELECT));
+ }
+ }
+ }
+
+ EM_selectmode_flush(em);
+
+// if (EM_texFaceCheck())
+
+}
+
+static int select_invert_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+
+ EM_select_swap(em);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_invert(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Invert";
+ ot->idname= "MESH_OT_select_invert";
+
+ /* api callbacks */
+ ot->exec= select_invert_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ******************** (de)select all operator **************** */
+
+void EM_toggle_select_all(EditMesh *em) /* exported for UV */
+{
+ if(EM_nvertices_selected(em))
+ EM_clear_flag_all(em, SELECT);
+ else
+ EM_set_flag_all(em, SELECT);
+}
+
+static int toggle_select_all_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+
+ EM_toggle_select_all(em);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ BKE_mesh_end_editmesh(obedit->data, em);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_all_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select or Deselect All";
+ ot->idname= "MESH_OT_select_all_toggle";
+
+ /* api callbacks */
+ ot->exec= toggle_select_all_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ******************** **************** */
+
+void EM_select_more(EditMesh *em)
+{
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f & SELECT) eve->f1= 1;
+ else eve->f1 = 0;
+ }
+
+ /* set f1 flags in vertices to select 'more' */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->h==0) {
+ if (eed->v1->f & SELECT)
+ eed->v2->f1 = 1;
+ if (eed->v2->f & SELECT)
+ eed->v1->f1 = 1;
+ }
+ }
+
+ /* new selected edges, but not in facemode */
+ if(em->selectmode <= SCE_SELECT_EDGE) {
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->h==0) {
+ if(eed->v1->f1 && eed->v2->f1) EM_select_edge(eed, 1);
+ }
+ }
+ }
+ /* new selected faces */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->h==0) {
+ if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1))
+ EM_select_face(efa, 1);
+ }
+ }
+}
+
+static int select_more(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)) ;
+
+ EM_select_more(em);
+
+// if (EM_texFaceCheck(em))
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_more(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select More";
+ ot->idname= "MESH_OT_select_more";
+
+ /* api callbacks */
+ ot->exec= select_more;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+void EM_select_less(EditMesh *em)
+{
+ EditEdge *eed;
+ EditFace *efa;
+
+ if(em->selectmode <= SCE_SELECT_EDGE) {
+ /* eed->f1 == 1: edge with a selected and deselected vert */
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->f1= 0;
+ if(eed->h==0) {
+
+ if ( !(eed->v1->f & SELECT) && (eed->v2->f & SELECT) )
+ eed->f1= 1;
+ if ( (eed->v1->f & SELECT) && !(eed->v2->f & SELECT) )
+ eed->f1= 1;
+ }
+ }
+
+ /* deselect edges with flag set */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if (eed->h==0 && eed->f1 == 1) {
+ EM_select_edge(eed, 0);
+ }
+ }
+ EM_deselect_flush(em);
+
+ }
+ else {
+ /* deselect faces with 1 or more deselect edges */
+ /* eed->f1 == mixed selection edge */
+ for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->h==0) {
+ if(efa->f & SELECT) {
+ efa->e1->f1 |= 1;
+ efa->e2->f1 |= 1;
+ efa->e3->f1 |= 1;
+ if(efa->e4) efa->e4->f1 |= 1;
+ }
+ else {
+ efa->e1->f1 |= 2;
+ efa->e2->f1 |= 2;
+ efa->e3->f1 |= 2;
+ if(efa->e4) efa->e4->f1 |= 2;
+ }
+ }
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->h==0) {
+ if(efa->e1->f1==3 || efa->e2->f1==3 || efa->e3->f1==3 || (efa->e4 && efa->e4->f1==3)) {
+ EM_select_face(efa, 0);
+ }
+ }
+ }
+ EM_selectmode_flush(em);
+
+ }
+}
+
+static int select_less(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+
+ EM_select_less(em);
+
+// if (EM_texFaceCheck(em))
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_less(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Less";
+ ot->idname= "MESH_OT_select_less";
+
+ /* api callbacks */
+ ot->exec= select_less;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static void selectrandom_mesh(EditMesh *em, float perc) /* randomly selects a user-set % of vertices/edges/faces */
+{
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+ float randfac= perc;
+ /* Get the percentage of vertices to randomly select as 'randfac' */
+// XXX if(button(&randfac,0, 100,"Percentage:")==0) return;
+
+ BLI_srand( BLI_rand() ); /* random seed */
+
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->h==0) {
+ if (BLI_frand() < randfac)
+ eve->f |= SELECT;
+ }
+ }
+ EM_selectmode_flush(em);
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->h==0) {
+ if (BLI_frand() < randfac)
+ EM_select_edge(eed, 1);
+ }
+ }
+ EM_selectmode_flush(em);
+ }
+ else {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->h==0) {
+ if (BLI_frand() < randfac)
+ EM_select_face(efa, 1);
+ }
+ }
+
+ EM_selectmode_flush(em);
+ }
+// if (EM_texFaceCheck())
+}
+
+static int mesh_select_random_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+
+ selectrandom_mesh(em, RNA_float_get(op->ptr,"percent"));
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_random(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Random";
+ ot->idname= "MESH_OT_select_random";
+
+ /* api callbacks */
+ ot->exec= mesh_select_random_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_float_percentage(ot->srna, "percent", 0.5f, 0.0f, 1.0f, "Percent", "Percentage of vertices to select randomly.", 0.0001f, 1.0f);
+}
+
+void editmesh_select_by_material(EditMesh *em, int index)
+{
+ EditFace *efa;
+
+ for (efa=em->faces.first; efa; efa= efa->next) {
+ if (efa->mat_nr==index) {
+ EM_select_face(efa, 1);
+ }
+ }
+
+ EM_selectmode_flush(em);
+}
+
+void editmesh_deselect_by_material(EditMesh *em, int index)
+{
+ EditFace *efa;
+
+ for (efa=em->faces.first; efa; efa= efa->next) {
+ if (efa->mat_nr==index) {
+ EM_select_face(efa, 0);
+ }
+ }
+
+ EM_selectmode_flush(em);
+}
+
+static void mesh_selection_type(Scene *scene, EditMesh *em, int val)
+{
+ if(val>0) {
+ if(val==1) {
+ em->selectmode= SCE_SELECT_VERTEX;
+ EM_selectmode_set(em);
+ }
+ else if(val==2) {
+ //if(ctrl) EM_convertsel(em, em->selectmode, SCE_SELECT_EDGE);
+ em->selectmode= SCE_SELECT_EDGE;
+ EM_selectmode_set(em);
+ }
+
+ else{
+ //if((ctrl)) EM_convertsel(em, em->selectmode, SCE_SELECT_FACE);
+ em->selectmode= SCE_SELECT_FACE;
+ EM_selectmode_set(em);
+ }
+
+ /* note, em stores selectmode to be able to pass it on everywhere without scene,
+ this is only until all select modes and toolsettings are settled more */
+ scene->selectmode= em->selectmode;
+// if (EM_texFaceCheck())
+ }
+}
+
+static EnumPropertyItem prop_mesh_edit_types[] = {
+ {1, "VERT", "Vertices", ""},
+ {2, "EDGE", "Edges", ""},
+ {3, "FACE", "Faces", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int mesh_selection_type_exec(bContext *C, wmOperator *op)
+{
+
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+
+ mesh_selection_type(CTX_data_scene(C), em, RNA_enum_get(op->ptr,"type"));
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_selection_type(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Selection Mode";
+ ot->idname= "MESH_OT_selection_type";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= mesh_selection_type_exec;
+
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "type", prop_mesh_edit_types, 0, "Type", "Set the mesh selection type");
+
+}
+/* ************************* SEAMS AND EDGES **************** */
+
+static int editmesh_mark_seam(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+ Mesh *me= ((Mesh *)obedit->data);
+ EditEdge *eed;
+ int clear = RNA_boolean_get(op->ptr, "clear");
+
+ /* auto-enable seams drawing */
+ if(clear==0) {
+ me->drawflag |= ME_DRAWSEAMS;
+ }
+
+ if(clear) {
+ eed= em->edges.first;
+ while(eed) {
+ if((eed->h==0) && (eed->f & SELECT)) {
+ eed->seam = 0;
+ }
+ eed= eed->next;
+ }
+ }
+ else {
+ eed= em->edges.first;
+ while(eed) {
+ if((eed->h==0) && (eed->f & SELECT)) {
+ eed->seam = 1;
+ }
+ eed= eed->next;
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_mark_seam(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mark seam";
+ ot->idname= "MESH_OT_mark_seam";
+
+ /* api callbacks */
+ ot->exec= editmesh_mark_seam;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
+}
+
+static int editmesh_mark_sharp(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+ Mesh *me= ((Mesh *)obedit->data);
+ int set = RNA_boolean_get(op->ptr, "set");
+ EditEdge *eed;
+
+ /* auto-enable sharp edge drawing */
+ if(set) {
+ me->drawflag |= ME_DRAWSHARP;
+ }
+
+ if(set) {
+ eed= em->edges.first;
+ while(eed) {
+ if(!eed->h && (eed->f & SELECT)) eed->sharp = 1;
+ eed = eed->next;
+ }
+ } else {
+ eed= em->edges.first;
+ while(eed) {
+ if(!eed->h && (eed->f & SELECT)) eed->sharp = 0;
+ eed = eed->next;
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_mark_sharp(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mark sharp";
+ ot->idname= "MESH_OT_mark_sharp";
+
+ /* api callbacks */
+ ot->exec= editmesh_mark_sharp;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "set", 0, "Set", "");
+}
+
+void BME_Menu() {
+ short ret;
+ ret= pupmenu("BME modeller%t|Select Edges of Vert%x1");
+
+ switch(ret)
+ {
+ case 1:
+ //BME_edges_of_vert();
+ break;
+ }
+}
+
+
+
+void Vertex_Menu(EditMesh *em)
+{
+ short ret;
+ ret= pupmenu("Vertex Specials%t|Remove Doubles%x1|Merge%x2|Smooth %x3|Select Vertex Path%x4|Blend From Shape%x5|Propagate To All Shapes%x6");
+
+ switch(ret)
+ {
+ case 1:
+// XXX notice("Removed %d Vertices", removedoublesflag(1, 0, scene->toolsettings->doublimit));
+ break;
+ case 2:
+// XXX mergemenu(em);
+ break;
+ case 3:
+// XXX vertexsmooth(em);
+ break;
+ case 4:
+// XXX pathselect(em);
+ break;
+ case 5:
+// XXX shape_copy_select_from(em);
+ break;
+ case 6:
+// XXX shape_propagate(em);
+ break;
+ }
+ /* some items crashed because this is in the original W menu but not here. should really manage this better */
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+}
+
+
+void Edge_Menu(EditMesh *em)
+{
+ short ret;
+
+ ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2|Rotate Edge CW%x3|Rotate Edge CCW%x4|Loopcut%x6|Edge Slide%x5|Edge Loop Select%x7|Edge Ring Select%x8|Loop to Region%x9|Region to Loop%x10|Mark Sharp%x11|Clear Sharp%x12");
+
+ switch(ret)
+ {
+ case 1:
+ //editmesh_mark_seam(em, 0);
+ break;
+ case 2:
+ //editmesh_mark_seam(em, 1);
+ break;
+ case 3:
+// edge_rotate_selected(em, 2);
+ break;
+ case 4:
+// edge_rotate_selected(em, 1);
+ break;
+ case 5:
+// EdgeSlide(em, 0,0.0);
+ break;
+ case 6:
+// CutEdgeloop(em, 1);
+ break;
+ case 7:
+// loop_multiselect(em, 0);
+ break;
+ case 8:
+// loop_multiselect(em, 1);
+ break;
+ case 9:
+// loop_to_region(em);
+ break;
+ case 10:
+// region_to_loop(em);
+ break;
+ case 11:
+// editmesh_mark_sharp(em, 1);
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ break;
+ case 12:
+// editmesh_mark_sharp(em, 0);
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ break;
+ }
+ /* some items crashed because this is in the original W menu but not here. should really manage this better */
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+}
+
+void Face_Menu(EditMesh *em)
+{
+ short ret;
+ ret= pupmenu(
+ "Face Specials%t|Flip Normals%x1|Bevel%x2|Shade Smooth%x3|Shade Flat%x4|"
+ "Triangulate (Ctrl T)%x5|Quads from Triangles (Alt J)%x6|Flip Triangle Edges (Ctrl Shift F)%x7|%l|"
+ "Face Mode Set%x8|Face Mode Clear%x9|%l|"
+ "UV Rotate (Shift - CCW)%x10|UV Mirror (Shift - Switch Axis)%x11|"
+ "Color Rotate (Shift - CCW)%x12|Color Mirror (Shift - Switch Axis)%x13");
+
+ switch(ret)
+ {
+ case 1:
+// flip_editnormals(em);
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ break;
+ case 2:
+// bevel_menu(em);
+ break;
+ case 3:
+// mesh_set_smooth_faces(em, 1);
+ break;
+ case 4:
+// mesh_set_smooth_faces(em, 0);
+ break;
+
+ case 5: /* Quads to Tris */
+// convert_to_triface(em, 0);
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ break;
+ case 6: /* Tris to Quads */
+// join_triangles(em);
+ break;
+ case 7: /* Flip triangle edges */
+// edge_flip(em);
+ break;
+ case 8:
+// mesh_set_face_flags(em, 1);
+ break;
+ case 9:
+// mesh_set_face_flags(em, 0);
+ break;
+
+ /* uv texface options */
+ case 10:
+// mesh_rotate_uvs(em);
+ break;
+ case 11:
+// mesh_mirror_uvs(em);
+ break;
+ case 12:
+// mesh_rotate_colors(em);
+ break;
+ case 13:
+// mesh_mirror_colors(em);
+ break;
+ }
+ /* some items crashed because this is in the original W menu but not here. should really manage this better */
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+}
+
+
+/* **************** NORMALS ************** */
+
+/* XXX value of select is messed up, it means two things */
+void righthandfaces(EditMesh *em, int select) /* makes faces righthand turning */
+{
+ EditEdge *eed, *ed1, *ed2, *ed3, *ed4;
+ EditFace *efa, *startvl;
+ float maxx, nor[3], cent[3];
+ int totsel, found, foundone, direct, turn, tria_nr;
+
+ /* based at a select-connected to witness loose objects */
+
+ /* count per edge the amount of faces */
+
+ /* find the ultimate left, front, upper face (not manhattan dist!!) */
+ /* also evaluate both triangle cases in quad, since these can be non-flat */
+
+ /* put normal to the outside, and set the first direction flags in edges */
+
+ /* then check the object, and set directions / direction-flags: but only for edges with 1 or 2 faces */
+ /* this is in fact the 'select connected' */
+
+ /* in case (selected) faces were not done: start over with 'find the ultimate ...' */
+
+ waitcursor(1);
+
+ eed= em->edges.first;
+ while(eed) {
+ eed->f2= 0; /* edge direction */
+ eed->f1= 0; /* counter */
+ eed= eed->next;
+ }
+
+ /* count faces and edges */
+ totsel= 0;
+ efa= em->faces.first;
+ while(efa) {
+ if(select==0 || (efa->f & SELECT) ) {
+ efa->f1= 1;
+ totsel++;
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->v4) efa->e4->f1++;
+ }
+ else efa->f1= 0;
+
+ efa= efa->next;
+ }
+
+ while(totsel>0) {
+ /* from the outside to the inside */
+
+ efa= em->faces.first;
+ startvl= NULL;
+ maxx= -1.0e10;
+ tria_nr= 0;
+
+ while(efa) {
+ if(efa->f1) {
+ CalcCent3f(cent, efa->v1->co, efa->v2->co, efa->v3->co);
+ cent[0]= cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2];
+
+ if(cent[0]>maxx) {
+ maxx= cent[0];
+ startvl= efa;
+ tria_nr= 0;
+ }
+ if(efa->v4) {
+ CalcCent3f(cent, efa->v1->co, efa->v3->co, efa->v4->co);
+ cent[0]= cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2];
+
+ if(cent[0]>maxx) {
+ maxx= cent[0];
+ startvl= efa;
+ tria_nr= 1;
+ }
+ }
+ }
+ efa= efa->next;
+ }
+
+ if (startvl==NULL)
+ startvl= em->faces.first;
+
+ /* set first face correct: calc normal */
+
+ if(tria_nr==1) {
+ CalcNormFloat(startvl->v1->co, startvl->v3->co, startvl->v4->co, nor);
+ CalcCent3f(cent, startvl->v1->co, startvl->v3->co, startvl->v4->co);
+ } else {
+ CalcNormFloat(startvl->v1->co, startvl->v2->co, startvl->v3->co, nor);
+ CalcCent3f(cent, startvl->v1->co, startvl->v2->co, startvl->v3->co);
+ }
+ /* first normal is oriented this way or the other */
+ if(select) {
+ if(select==2) {
+ if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] > 0.0) flipface(em, startvl);
+ }
+ else {
+ if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipface(em, startvl);
+ }
+ }
+ else if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipface(em, startvl);
+
+
+ eed= startvl->e1;
+ if(eed->v1==startvl->v1) eed->f2= 1;
+ else eed->f2= 2;
+
+ eed= startvl->e2;
+ if(eed->v1==startvl->v2) eed->f2= 1;
+ else eed->f2= 2;
+
+ eed= startvl->e3;
+ if(eed->v1==startvl->v3) eed->f2= 1;
+ else eed->f2= 2;
+
+ eed= startvl->e4;
+ if(eed) {
+ if(eed->v1==startvl->v4) eed->f2= 1;
+ else eed->f2= 2;
+ }
+
+ startvl->f1= 0;
+ totsel--;
+
+ /* test normals */
+ found= 1;
+ direct= 1;
+ while(found) {
+ found= 0;
+ if(direct) efa= em->faces.first;
+ else efa= em->faces.last;
+ while(efa) {
+ if(efa->f1) {
+ turn= 0;
+ foundone= 0;
+
+ ed1= efa->e1;
+ ed2= efa->e2;
+ ed3= efa->e3;
+ ed4= efa->e4;
+
+ if(ed1->f2) {
+ if(ed1->v1==efa->v1 && ed1->f2==1) turn= 1;
+ if(ed1->v2==efa->v1 && ed1->f2==2) turn= 1;
+ foundone= 1;
+ }
+ else if(ed2->f2) {
+ if(ed2->v1==efa->v2 && ed2->f2==1) turn= 1;
+ if(ed2->v2==efa->v2 && ed2->f2==2) turn= 1;
+ foundone= 1;
+ }
+ else if(ed3->f2) {
+ if(ed3->v1==efa->v3 && ed3->f2==1) turn= 1;
+ if(ed3->v2==efa->v3 && ed3->f2==2) turn= 1;
+ foundone= 1;
+ }
+ else if(ed4 && ed4->f2) {
+ if(ed4->v1==efa->v4 && ed4->f2==1) turn= 1;
+ if(ed4->v2==efa->v4 && ed4->f2==2) turn= 1;
+ foundone= 1;
+ }
+
+ if(foundone) {
+ found= 1;
+ totsel--;
+ efa->f1= 0;
+
+ if(turn) {
+ if(ed1->v1==efa->v1) ed1->f2= 2;
+ else ed1->f2= 1;
+ if(ed2->v1==efa->v2) ed2->f2= 2;
+ else ed2->f2= 1;
+ if(ed3->v1==efa->v3) ed3->f2= 2;
+ else ed3->f2= 1;
+ if(ed4) {
+ if(ed4->v1==efa->v4) ed4->f2= 2;
+ else ed4->f2= 1;
+ }
+
+ flipface(em, efa);
+
+ }
+ else {
+ if(ed1->v1== efa->v1) ed1->f2= 1;
+ else ed1->f2= 2;
+ if(ed2->v1==efa->v2) ed2->f2= 1;
+ else ed2->f2= 2;
+ if(ed3->v1==efa->v3) ed3->f2= 1;
+ else ed3->f2= 2;
+ if(ed4) {
+ if(ed4->v1==efa->v4) ed4->f2= 1;
+ else ed4->f2= 2;
+ }
+ }
+ }
+ }
+ if(direct) efa= efa->next;
+ else efa= efa->prev;
+ }
+ direct= 1-direct;
+ }
+ }
+
+ recalc_editnormals(em);
+
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ waitcursor(0);
+}
+
+
+static int righthandfaces_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+
+ /* 'standard' behaviour - check if selected, then apply relevant selection */
+
+ // XXX need other args
+ righthandfaces(em, RNA_boolean_get(op->ptr, "inside"));
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); //TODO is this needed ?
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_normals_make_consistent(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Make Normals Consistent";
+ ot->idname= "MESH_OT_normals_make_consistent";
+
+ /* api callbacks */
+ ot->exec= righthandfaces_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "inside", 0, "Inside", "");
+}
+
+/* ********** ALIGN WITH VIEW **************** */
+
+
+static void editmesh_calc_selvert_center(EditMesh *em, float cent_r[3])
+{
+ EditVert *eve;
+ int nsel= 0;
+
+ cent_r[0]= cent_r[1]= cent_r[0]= 0.0;
+
+ for (eve= em->verts.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 mface_is_selected(MFace *mf)
+{
+ return (!(mf->flag & ME_HIDE) && (mf->flag & ME_FACE_SEL));
+}
+
+ /* 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, RegionView3D *rv3d, Mesh *me, wmOperator *op, int axis)
+{
+ float norm[3];
+ int i, totselected = 0;
+
+ norm[0]= norm[1]= norm[2]= 0.0;
+ for (i=0; i<me->totface; i++) {
+ MFace *mf= ((MFace*) me->mface) + i;
+
+ if (mface_is_selected(mf)) {
+ 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];
+
+ totselected++;
+ }
+ }
+
+ if (totselected == 0)
+ BKE_report(op->reports, RPT_ERROR, "No faces selected.");
+ else
+ view3d_align_axis_to_vector(v3d, rv3d, axis, norm);
+}
+
+/* helper for below, to survive non-uniform scaled objects */
+static void face_getnormal_obspace(Object *obedit, EditFace *efa, float *fno)
+{
+ float vec[4][3];
+
+ VECCOPY(vec[0], efa->v1->co);
+ Mat4Mul3Vecfl(obedit->obmat, vec[0]);
+ VECCOPY(vec[1], efa->v2->co);
+ Mat4Mul3Vecfl(obedit->obmat, vec[1]);
+ VECCOPY(vec[2], efa->v3->co);
+ Mat4Mul3Vecfl(obedit->obmat, vec[2]);
+ if(efa->v4) {
+ VECCOPY(vec[3], efa->v4->co);
+ Mat4Mul3Vecfl(obedit->obmat, vec[3]);
+
+ CalcNormFloat4(vec[0], vec[1], vec[2], vec[3], fno);
+ }
+ else CalcNormFloat(vec[0], vec[1], vec[2], fno);
+}
+
+
+void editmesh_align_view_to_selected(Object *obedit, EditMesh *em, wmOperator *op, View3D *v3d, RegionView3D *rv3d, int axis)
+{
+ int nselverts= EM_nvertices_selected(em);
+ float norm[3]={0.0, 0.0, 0.0}; /* used for storing the mesh normal */
+
+ if (nselverts==0) {
+ BKE_report(op->reports, RPT_ERROR, "No faces or vertices selected.");
+ }
+ else if (EM_nfaces_selected(em)) {
+ EditFace *efa;
+ for (efa= em->faces.first; efa; efa= efa->next) {
+ if (faceselectedAND(efa, SELECT)) {
+ float fno[3];
+
+ face_getnormal_obspace(obedit, efa, fno);
+ norm[0]+= fno[0];
+ norm[1]+= fno[1];
+ norm[2]+= fno[2];
+ }
+ }
+
+ view3d_align_axis_to_vector(v3d, rv3d, axis, norm);
+ }
+ else if (nselverts>2) {
+ float cent[3];
+ EditVert *eve, *leve= NULL;
+
+ editmesh_calc_selvert_center(em, cent);
+ for (eve= em->verts.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;
+ }
+ }
+
+ Mat4Mul3Vecfl(obedit->obmat, norm);
+ view3d_align_axis_to_vector(v3d, rv3d, axis, norm);
+ }
+ else if (nselverts==2) { /* Align view to edge (or 2 verts) */
+ EditVert *eve, *leve= NULL;
+
+ for (eve= em->verts.first; eve; eve= eve->next) {
+ if (eve->f & SELECT) {
+ if (leve) {
+ norm[0]= leve->co[0] - eve->co[0];
+ norm[1]= leve->co[1] - eve->co[1];
+ norm[2]= leve->co[2] - eve->co[2];
+ break; /* we know there are only 2 verts so no need to keep looking */
+ }
+ leve= eve;
+ }
+ }
+ Mat4Mul3Vecfl(obedit->obmat, norm);
+ view3d_align_axis_to_vector(v3d, rv3d, axis, norm);
+ }
+ else if (nselverts==1) { /* Align view to vert normal */
+ EditVert *eve;
+
+ for (eve= em->verts.first; eve; eve= eve->next) {
+ if (eve->f & SELECT) {
+ norm[0]= eve->no[0];
+ norm[1]= eve->no[1];
+ norm[2]= eve->no[2];
+ break; /* we know this is the only selected vert, so no need to keep looking */
+ }
+ }
+ Mat4Mul3Vecfl(obedit->obmat, norm);
+ view3d_align_axis_to_vector(v3d, rv3d, axis, norm);
+ }
+}
+
+/* **************** VERTEX DEFORMS *************** */
+
+static int smooth_vertex(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Mesh *me= obedit->data;
+ EditMesh *em= (EditMesh *)me;
+
+ EditVert *eve, *eve_mir = NULL;
+ EditEdge *eed;
+ float *adror, *adr, fac;
+ float fvec[3];
+ int teller=0;
+ ModifierData *md= obedit->modifiers.first;
+
+ if(em==NULL) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* count */
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f & SELECT) teller++;
+ eve= eve->next;
+ }
+ if(teller==0) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ adr=adror= (float *)MEM_callocN(3*sizeof(float *)*teller, "vertsmooth");
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f & SELECT) {
+ eve->tmp.p = (void*)adr;
+ eve->f1= 0;
+ eve->f2= 0;
+ adr+= 3;
+ }
+ eve= eve->next;
+ }
+
+ /* if there is a mirror modifier with clipping, flag the verts that
+ * are within tolerance of the plane(s) of reflection
+ */
+ for (; md; md=md->next) {
+ if (md->type==eModifierType_Mirror) {
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ if(mmd->flag & MOD_MIR_CLIPPING) {
+ for (eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f & SELECT) {
+
+ switch(mmd->axis){
+ case 0:
+ if (fabs(eve->co[0]) < mmd->tolerance)
+ eve->f2 |= 1;
+ break;
+ case 1:
+ if (fabs(eve->co[1]) < mmd->tolerance)
+ eve->f2 |= 2;
+ break;
+ case 2:
+ if (fabs(eve->co[2]) < mmd->tolerance)
+ eve->f2 |= 4;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ eed= em->edges.first;
+ while(eed) {
+ if( (eed->v1->f & SELECT) || (eed->v2->f & SELECT) ) {
+ fvec[0]= (eed->v1->co[0]+eed->v2->co[0])/2.0;
+ fvec[1]= (eed->v1->co[1]+eed->v2->co[1])/2.0;
+ fvec[2]= (eed->v1->co[2]+eed->v2->co[2])/2.0;
+
+ if((eed->v1->f & SELECT) && eed->v1->f1<255) {
+ eed->v1->f1++;
+ VecAddf(eed->v1->tmp.p, eed->v1->tmp.p, fvec);
+ }
+ if((eed->v2->f & SELECT) && eed->v2->f1<255) {
+ eed->v2->f1++;
+ VecAddf(eed->v2->tmp.p, eed->v2->tmp.p, fvec);
+ }
+ }
+ eed= eed->next;
+ }
+
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f & SELECT) {
+ if(eve->f1) {
+
+ if (scene->toolsettings->editbutflag & B_MESH_X_MIRROR) {
+ eve_mir= editmesh_get_x_mirror_vert(obedit, em, eve->co);
+ }
+
+ adr = eve->tmp.p;
+ fac= 0.5/(float)eve->f1;
+
+ eve->co[0]= 0.5*eve->co[0]+fac*adr[0];
+ eve->co[1]= 0.5*eve->co[1]+fac*adr[1];
+ eve->co[2]= 0.5*eve->co[2]+fac*adr[2];
+
+
+ /* clip if needed by mirror modifier */
+ if (eve->f2) {
+ if (eve->f2 & 1) {
+ eve->co[0]= 0.0f;
+ }
+ if (eve->f2 & 2) {
+ eve->co[1]= 0.0f;
+ }
+ if (eve->f2 & 4) {
+ eve->co[2]= 0.0f;
+ }
+ }
+
+ if (eve_mir) {
+ eve_mir->co[0]=-eve->co[0];
+ eve_mir->co[1]= eve->co[1];
+ eve_mir->co[2]= eve->co[2];
+ }
+
+ }
+ eve->tmp.p= NULL;
+ }
+ eve= eve->next;
+ }
+ MEM_freeN(adror);
+
+ recalc_editnormals(em);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_vertices_smooth(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Smooth Vertex";
+ ot->idname= "MESH_OT_vertices_smooth";
+
+ /* api callbacks */
+ ot->exec= smooth_vertex;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_UNDO;
+}
+
+void vertexnoise(Object *obedit, EditMesh *em)
+{
+ Material *ma;
+ Tex *tex;
+ EditVert *eve;
+ float b2, ofs, vec[3];
+
+ if(em==NULL) return;
+
+ ma= give_current_material(obedit, 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 *)em->verts.first;
+ while(eve) {
+ if(eve->f & SELECT) {
+
+ 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 {
+ float tin, dum;
+ externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum);
+ eve->co[2]+= 0.05*tin;
+ }
+ }
+ eve= eve->next;
+ }
+
+ recalc_editnormals(em);
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+}
+
+static void vertices_to_sphere(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, float perc)
+{
+ EditVert *eve;
+ float *curs, len, vec[3], cent[3], fac, facm, imat[3][3], bmat[3][3];
+ int tot;
+
+// XXX if(button(&perc, 1, 100, "Percentage:")==0) return;
+
+ fac= perc/100.0f;
+ facm= 1.0f-fac;
+
+ Mat3CpyMat4(bmat, obedit->obmat);
+ Mat3Inv(imat, bmat);
+
+ /* center */
+ curs= give_cursor(scene, v3d);
+ cent[0]= curs[0]-obedit->obmat[3][0];
+ cent[1]= curs[1]-obedit->obmat[3][1];
+ cent[2]= curs[2]-obedit->obmat[3][2];
+ Mat3MulVecfl(imat, cent);
+
+ len= 0.0;
+ tot= 0;
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f & SELECT) {
+ tot++;
+ len+= VecLenf(cent, eve->co);
+ }
+ eve= eve->next;
+ }
+ len/=tot;
+
+ if(len==0.0) len= 10.0;
+
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f & SELECT) {
+ vec[0]= eve->co[0]-cent[0];
+ vec[1]= eve->co[1]-cent[1];
+ vec[2]= eve->co[2]-cent[2];
+
+ Normalize(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;
+ }
+
+ recalc_editnormals(em);
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+}
+
+static int vertices_to_sphere_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+
+ vertices_to_sphere(scene, v3d, obedit, em, RNA_float_get(op->ptr,"percent"));
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_vertices_transform_to_sphere(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Vertices to Sphere";
+ ot->idname= "MESH_OT_vertices_transform_to_sphere";
+
+ /* api callbacks */
+ ot->exec= vertices_to_sphere_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+
+ /* props */
+ RNA_def_float(ot->srna, "percent", 100.0f, 0.0f, 100.0f, "Percent", "DOC_BROKEN", 0.01f, 100.0f);
+}
+
+void flipface(EditMesh *em, EditFace *efa)
+{
+ if(efa->v4) {
+ SWAP(EditVert *, efa->v2, efa->v4);
+ SWAP(EditEdge *, efa->e1, efa->e4);
+ SWAP(EditEdge *, efa->e2, efa->e3);
+ EM_data_interp_from_faces(em, efa, NULL, efa, 0, 3, 2, 1);
+ }
+ else {
+ SWAP(EditVert *, efa->v2, efa->v3);
+ SWAP(EditEdge *, efa->e1, efa->e3);
+ efa->e2->dir= 1-efa->e2->dir;
+ EM_data_interp_from_faces(em, efa, NULL, efa, 0, 2, 1, 3);
+ }
+
+ if(efa->v4) CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, efa->n);
+ else CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n);
+}
+
+
+static int flip_editnormals(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+ EditFace *efa;
+
+ efa= em->faces.first;
+ while(efa) {
+ if( efa->f & SELECT ){
+ flipface(em, efa);
+ }
+ efa= efa->next;
+ }
+
+ /* update vertex normals too */
+ recalc_editnormals(em);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_flip_editnormals(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Flip Normals";
+ ot->idname= "MESH_OT_flip_editnormals";
+
+ /* api callbacks */
+ ot->exec= flip_editnormals;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
new file mode 100644
index 00000000000..f3868b1f01c
--- /dev/null
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -0,0 +1,7088 @@
+ /* $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Johnny Matthews, Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/*
+
+editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise in mods.c
+
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+#include "PIL_time.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_key_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_types.h"
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+#include "BLI_ghash.h"
+#include "BLI_linklist.h"
+#include "BLI_heap.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+#include "BKE_bmesh.h"
+#include "BKE_report.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BMF_Api.h"
+
+#include "ED_mesh.h"
+#include "ED_view3d.h"
+#include "ED_util.h"
+#include "ED_screen.h"
+#include "BIF_transform.h"
+
+#include "UI_interface.h"
+
+#include "mesh_intern.h"
+
+/* XXX */
+static int extern_qread() {return 0;}
+static void waitcursor() {}
+static int pupmenu() {return 0;}
+static int qtest() {return 0;}
+#define add_numbut(a, b, c, d, e, f, g) {}
+static int snap_sel_to_curs() {return 0;}
+static int snap_to_center() {return 0;}
+
+/* XXX */
+
+/* local prototypes ---------------*/
+static void free_tagged_edges_faces(EditMesh *em, EditEdge *eed, EditFace *efa);
+int EdgeLoopDelete(EditMesh *em, wmOperator *op);
+
+/********* qsort routines *********/
+
+
+typedef struct xvertsort {
+ float x;
+ EditVert *v1;
+} xvertsort;
+
+static int vergxco(const void *v1, const void *v2)
+{
+ const xvertsort *x1=v1, *x2=v2;
+
+ if( x1->x > x2->x ) return 1;
+ else if( x1->x < x2->x) return -1;
+ return 0;
+}
+
+struct facesort {
+ uintptr_t x;
+ struct EditFace *efa;
+};
+
+
+static int vergface(const void *v1, const void *v2)
+{
+ const struct facesort *x1=v1, *x2=v2;
+
+ if( x1->x > x2->x ) return 1;
+ else if( x1->x < x2->x) return -1;
+ return 0;
+}
+
+
+/* *********************************** */
+
+void convert_to_triface(EditMesh *em, int direction)
+{
+ EditFace *efa, *efan, *next;
+ float fac;
+
+ efa= em->faces.last;
+ while(efa) {
+ next= efa->prev;
+ if(efa->v4) {
+ if(efa->f & SELECT) {
+ /* choose shortest diagonal for split */
+ fac= VecLenf(efa->v1->co, efa->v3->co) - VecLenf(efa->v2->co, efa->v4->co);
+ /* this makes sure exact squares get split different in both cases */
+ if( (direction==0 && fac<FLT_EPSILON) || (direction && fac>0.0f) ) {
+ efan= EM_face_from_faces(em, efa, NULL, 0, 1, 2, -1);
+ if(efa->f & SELECT) EM_select_face(efan, 1);
+ efan= EM_face_from_faces(em, efa, NULL, 0, 2, 3, -1);
+ if(efa->f & SELECT) EM_select_face(efan, 1);
+ }
+ else {
+ efan= EM_face_from_faces(em, efa, NULL, 0, 1, 3, -1);
+ if(efa->f & SELECT) EM_select_face(efan, 1);
+ efan= EM_face_from_faces(em, efa, NULL, 1, 2, 3, -1);
+ if(efa->f & SELECT) EM_select_face(efan, 1);
+ }
+
+ BLI_remlink(&em->faces, efa);
+ free_editface(em, efa);
+ }
+ }
+ efa= next;
+ }
+
+ EM_fgon_flags(em); // redo flags and indices for fgons
+
+
+}
+
+int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /* return amount */
+{
+ /*
+ flag - Test with vert->flags
+ automerge - Alternative operation, merge unselected into selected.
+ Used for "Auto Weld" mode. warning.
+ limit - Quick manhattan distance between verts.
+ */
+
+ /* all verts with (flag & 'flag') are being evaluated */
+ EditVert *eve, *v1, *nextve;
+ EditEdge *eed, *e1, *nexted;
+ EditFace *efa, *nextvl;
+ xvertsort *sortblock, *sb, *sb1;
+ struct facesort *vlsortblock, *vsb, *vsb1;
+ int a, b, test, amount;
+
+
+ /* flag 128 is cleared, count */
+
+ /* Normal non weld operation */
+ eve= em->verts.first;
+ amount= 0;
+ while(eve) {
+ eve->f &= ~128;
+ if(eve->h==0 && (automerge || (eve->f & flag))) amount++;
+ eve= eve->next;
+ }
+ if(amount==0) return 0;
+
+ /* allocate memory and qsort */
+ sb= sortblock= MEM_mallocN(sizeof(xvertsort)*amount,"sortremovedoub");
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->h==0 && (automerge || (eve->f & flag))) {
+ sb->x= eve->co[0]+eve->co[1]+eve->co[2];
+ sb->v1= eve;
+ sb++;
+ }
+ eve= eve->next;
+ }
+ qsort(sortblock, amount, sizeof(xvertsort), vergxco);
+
+
+ /* test for doubles */
+ sb= sortblock;
+ if (automerge) {
+ for(a=0; a<amount; a++, sb++) {
+ eve= sb->v1;
+ if( (eve->f & 128)==0 ) {
+ sb1= sb+1;
+ for(b=a+1; b<amount && (eve->f & 128)==0; b++, sb1++) {
+ if(sb1->x - sb->x > limit) break;
+
+ /* when automarge, only allow unselected->selected */
+ v1= sb1->v1;
+ if( (v1->f & 128)==0 ) {
+ if ((eve->f & flag)==0 && (v1->f & flag)==1) {
+ if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
+ (float)fabs(v1->co[1]-eve->co[1])<=limit &&
+ (float)fabs(v1->co[2]-eve->co[2])<=limit)
+ { /* unique bit */
+ eve->f|= 128;
+ eve->tmp.v = v1;
+ }
+ } else if( (eve->f & flag)==1 && (v1->f & flag)==0 ) {
+ if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
+ (float)fabs(v1->co[1]-eve->co[1])<=limit &&
+ (float)fabs(v1->co[2]-eve->co[2])<=limit)
+ { /* unique bit */
+ v1->f|= 128;
+ v1->tmp.v = eve;
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ for(a=0; a<amount; a++, sb++) {
+ eve= sb->v1;
+ if( (eve->f & 128)==0 ) {
+ sb1= sb+1;
+ for(b=a+1; b<amount; b++, sb1++) {
+ /* first test: simpel dist */
+ if(sb1->x - sb->x > limit) break;
+ v1= sb1->v1;
+
+ /* second test: is vertex allowed */
+ if( (v1->f & 128)==0 ) {
+ if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
+ (float)fabs(v1->co[1]-eve->co[1])<=limit &&
+ (float)fabs(v1->co[2]-eve->co[2])<=limit)
+ {
+ v1->f|= 128;
+ v1->tmp.v = eve;
+ }
+ }
+ }
+ }
+ }
+ }
+ MEM_freeN(sortblock);
+
+ if (!automerge)
+ for(eve = em->verts.first; eve; eve=eve->next)
+ if((eve->f & flag) && (eve->f & 128))
+ EM_data_interp_from_verts(em, eve, eve->tmp.v, eve->tmp.v, 0.5f);
+
+ /* test edges and insert again */
+ eed= em->edges.first;
+ while(eed) {
+ eed->f2= 0;
+ eed= eed->next;
+ }
+ eed= em->edges.last;
+ while(eed) {
+ nexted= eed->prev;
+
+ if(eed->f2==0) {
+ if( (eed->v1->f & 128) || (eed->v2->f & 128) ) {
+ remedge(em, eed);
+
+ if(eed->v1->f & 128) eed->v1 = eed->v1->tmp.v;
+ if(eed->v2->f & 128) eed->v2 = eed->v2->tmp.v;
+ e1= addedgelist(em, eed->v1, eed->v2, eed);
+
+ if(e1) {
+ e1->f2= 1;
+ if(eed->f & SELECT)
+ e1->f |= SELECT;
+ }
+ if(e1!=eed) free_editedge(em, eed);
+ }
+ }
+ eed= nexted;
+ }
+
+ /* first count amount of test faces */
+ efa= (struct EditFace *)em->faces.first;
+ amount= 0;
+ while(efa) {
+ efa->f1= 0;
+ if(efa->v1->f & 128) efa->f1= 1;
+ else if(efa->v2->f & 128) efa->f1= 1;
+ else if(efa->v3->f & 128) efa->f1= 1;
+ else if(efa->v4 && (efa->v4->f & 128)) efa->f1= 1;
+
+ if(efa->f1==1) amount++;
+ efa= efa->next;
+ }
+
+ /* test faces for double vertices, and if needed remove them */
+ efa= (struct EditFace *)em->faces.first;
+ while(efa) {
+ nextvl= efa->next;
+ if(efa->f1==1) {
+
+ if(efa->v1->f & 128) efa->v1= efa->v1->tmp.v;
+ if(efa->v2->f & 128) efa->v2= efa->v2->tmp.v;
+ if(efa->v3->f & 128) efa->v3= efa->v3->tmp.v;
+ if(efa->v4 && (efa->v4->f & 128)) efa->v4= efa->v4->tmp.v;
+
+ test= 0;
+ if(efa->v1==efa->v2) test+=1;
+ if(efa->v2==efa->v3) test+=2;
+ if(efa->v3==efa->v1) test+=4;
+ if(efa->v4==efa->v1) test+=8;
+ if(efa->v3==efa->v4) test+=16;
+ if(efa->v2==efa->v4) test+=32;
+
+ if(test) {
+ if(efa->v4) {
+ if(test==1 || test==2) {
+ efa->v2= efa->v3;
+ efa->v3= efa->v4;
+ efa->v4= 0;
+
+ EM_data_interp_from_faces(em, efa, NULL, efa, 0, 2, 3, 3);
+
+ test= 0;
+ }
+ else if(test==8 || test==16) {
+ efa->v4= 0;
+ test= 0;
+ }
+ else {
+ BLI_remlink(&em->faces, efa);
+ free_editface(em, efa);
+ amount--;
+ }
+ }
+ else {
+ BLI_remlink(&em->faces, efa);
+ free_editface(em, efa);
+ amount--;
+ }
+ }
+
+ if(test==0) {
+ /* set edge pointers */
+ efa->e1= findedgelist(em, efa->v1, efa->v2);
+ efa->e2= findedgelist(em, efa->v2, efa->v3);
+ if(efa->v4==0) {
+ efa->e3= findedgelist(em, efa->v3, efa->v1);
+ efa->e4= 0;
+ }
+ else {
+ efa->e3= findedgelist(em, efa->v3, efa->v4);
+ efa->e4= findedgelist(em, efa->v4, efa->v1);
+ }
+ }
+ }
+ efa= nextvl;
+ }
+
+ /* double faces: sort block */
+ /* count again, now all selected faces */
+ amount= 0;
+ efa= em->faces.first;
+ while(efa) {
+ efa->f1= 0;
+ if(faceselectedOR(efa, 1)) {
+ efa->f1= 1;
+ amount++;
+ }
+ efa= efa->next;
+ }
+
+ if(amount) {
+ /* double faces: sort block */
+ vsb= vlsortblock= MEM_mallocN(sizeof(struct facesort)*amount, "sortremovedoub");
+ efa= em->faces.first;
+ while(efa) {
+ if(efa->f1 & 1) {
+ if(efa->v4) vsb->x= (uintptr_t) MIN4( (uintptr_t)efa->v1, (uintptr_t)efa->v2, (uintptr_t)efa->v3, (uintptr_t)efa->v4);
+ else vsb->x= (uintptr_t) MIN3( (uintptr_t)efa->v1, (uintptr_t)efa->v2, (uintptr_t)efa->v3);
+
+ vsb->efa= efa;
+ vsb++;
+ }
+ efa= efa->next;
+ }
+
+ qsort(vlsortblock, amount, sizeof(struct facesort), vergface);
+
+ vsb= vlsortblock;
+ for(a=0; a<amount; a++) {
+ efa= vsb->efa;
+ if( (efa->f1 & 128)==0 ) {
+ vsb1= vsb+1;
+
+ for(b=a+1; b<amount; b++) {
+
+ /* first test: same pointer? */
+ if(vsb->x != vsb1->x) break;
+
+ /* second test: is test permitted? */
+ efa= vsb1->efa;
+ if( (efa->f1 & 128)==0 ) {
+ if( compareface(efa, vsb->efa)) efa->f1 |= 128;
+
+ }
+ vsb1++;
+ }
+ }
+ vsb++;
+ }
+
+ MEM_freeN(vlsortblock);
+
+ /* remove double faces */
+ efa= (struct EditFace *)em->faces.first;
+ while(efa) {
+ nextvl= efa->next;
+ if(efa->f1 & 128) {
+ BLI_remlink(&em->faces, efa);
+ free_editface(em, efa);
+ }
+ efa= nextvl;
+ }
+ }
+
+ /* remove double vertices */
+ a= 0;
+ eve= (struct EditVert *)em->verts.first;
+ while(eve) {
+ nextve= eve->next;
+ if(automerge || eve->f & flag) {
+ if(eve->f & 128) {
+ a++;
+ BLI_remlink(&em->verts, eve);
+ free_editvert(em, eve);
+ }
+ }
+ eve= nextve;
+ }
+
+ return a; /* amount */
+}
+
+static int removedoublesflag_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+ char msg[100];
+
+ int cnt = removedoublesflag(em,1,0,scene->toolsettings->doublimit);
+
+ if(cnt)
+ {
+ sprintf(msg, "Removed %d vertices", cnt);
+ BKE_report(op->reports, RPT_INFO, msg);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_remove_doubles(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Remove Doubles";
+ ot->idname= "MESH_OT_remove_doubles";
+
+ /* api callbacks */
+ ot->exec= removedoublesflag_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+// XXX is this needed?
+/* called from buttons */
+static void xsortvert_flag__doSetX(void *userData, EditVert *eve, int x, int y, int index)
+{
+ xvertsort *sortblock = userData;
+
+ sortblock[index].x = x;
+}
+
+/* all verts with (flag & 'flag') are sorted */
+void xsortvert_flag(bContext *C, int flag)
+{
+ ViewContext vc;
+ EditVert *eve;
+ xvertsort *sortblock;
+ ListBase tbase;
+ int i, amount;
+
+ em_setup_viewcontext(C, &vc);
+
+ amount = BLI_countlist(&vc.em->verts);
+ sortblock = MEM_callocN(sizeof(xvertsort)*amount,"xsort");
+ for (i=0,eve= vc.em->verts.first; eve; i++,eve=eve->next)
+ if(eve->f & flag)
+ sortblock[i].v1 = eve;
+
+ mesh_foreachScreenVert(&vc, xsortvert_flag__doSetX, sortblock, 0);
+ qsort(sortblock, amount, sizeof(xvertsort), vergxco);
+
+ /* make temporal listbase */
+ tbase.first= tbase.last= 0;
+ for (i=0; i<amount; i++) {
+ eve = sortblock[i].v1;
+
+ if (eve) {
+ BLI_remlink(&vc.em->verts, eve);
+ BLI_addtail(&tbase, eve);
+ }
+ }
+
+ addlisttolist(&vc.em->verts, &tbase);
+
+ MEM_freeN(sortblock);
+
+}
+
+/* called from buttons */
+void hashvert_flag(EditMesh *em, int flag)
+{
+ /* switch vertex order using hash table */
+ EditVert *eve;
+ struct xvertsort *sortblock, *sb, onth, *newsort;
+ ListBase tbase;
+ int amount, a, b;
+
+ /* count */
+ eve= em->verts.first;
+ amount= 0;
+ while(eve) {
+ if(eve->f & flag) amount++;
+ eve= eve->next;
+ }
+ if(amount==0) return;
+
+ /* allocate memory */
+ sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*amount,"sortremovedoub");
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f & flag) {
+ sb->v1= eve;
+ sb++;
+ }
+ eve= eve->next;
+ }
+
+ BLI_srand(1);
+
+ sb= sortblock;
+ for(a=0; a<amount; a++, sb++) {
+ b= (int)(amount*BLI_drand());
+ if(b>=0 && b<amount) {
+ newsort= sortblock+b;
+ onth= *sb;
+ *sb= *newsort;
+ *newsort= onth;
+ }
+ }
+
+ /* make temporal listbase */
+ tbase.first= tbase.last= 0;
+ sb= sortblock;
+ while(amount--) {
+ eve= sb->v1;
+ BLI_remlink(&em->verts, eve);
+ BLI_addtail(&tbase, eve);
+ sb++;
+ }
+
+ addlisttolist(&em->verts, &tbase);
+
+ MEM_freeN(sortblock);
+
+}
+
+/* generic extern called extruder */
+void extrude_mesh(Object *obedit, EditMesh *em, wmOperator *op)
+{
+ Scene *scene= NULL; // XXX CTX!
+ float nor[3]= {0.0, 0.0, 0.0};
+ short nr, transmode= 0;
+
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ if(em->totvertsel==0) nr= 0;
+ else if(em->totvertsel==1) nr= 4;
+ else if(em->totedgesel==0) nr= 4;
+ else if(em->totfacesel==0)
+ nr= 3; // pupmenu("Extrude %t|Only Edges%x3|Only Vertices%x4");
+ else if(em->totfacesel==1)
+ nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3|Only Vertices%x4");
+ else
+ nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4");
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ if (em->totedgesel==0) nr = 0;
+ else if (em->totedgesel==1) nr = 3;
+ else if(em->totfacesel==0) nr = 3;
+ else if(em->totfacesel==1)
+ nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3");
+ else
+ nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3");
+ }
+ else {
+ if (em->totfacesel == 0) nr = 0;
+ else if (em->totfacesel == 1) nr = 1;
+ else
+ nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2");
+ }
+
+ if(nr<1) return;
+
+ if(nr==1) transmode= extrudeflag(obedit, em, SELECT, nor);
+ else if(nr==4) transmode= extrudeflag_verts_indiv(em, SELECT, nor);
+ else if(nr==3) transmode= extrudeflag_edges_indiv(em, SELECT, nor);
+ else transmode= extrudeflag_face_indiv(em, SELECT, nor);
+
+ if(transmode==0) {
+ BKE_report(op->reports, RPT_ERROR, "Not a valid selection for extrude");
+ }
+ else {
+ EM_fgon_flags(em);
+
+ /* We need to force immediate calculation here because
+ * transform may use derived objects (which are now stale).
+ *
+ * This shouldn't be necessary, derived queries should be
+ * automatically building this data if invalid. Or something.
+ */
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ object_handle_update(scene, obedit);
+
+ /* individual faces? */
+// BIF_TransformSetUndo("Extrude");
+ if(nr==2) {
+// initTransform(TFM_SHRINKFATTEN, CTX_NO_PET|CTX_NO_MIRROR);
+// Transform();
+ }
+ else {
+// initTransform(TFM_TRANSLATION, CTX_NO_PET|CTX_NO_MIRROR);
+ if(transmode=='n') {
+ Mat4MulVecfl(obedit->obmat, nor);
+ VecSubf(nor, nor, obedit->obmat[3]);
+// BIF_setSingleAxisConstraint(nor, "along normal");
+ }
+// Transform();
+ }
+ }
+
+}
+
+// XXX should be a menu item
+static int mesh_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ extrude_mesh(obedit,em, op);
+
+ RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
+ WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+/* extrude without transform */
+static int mesh_extrude_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
+
+ extrude_mesh(obedit,em, op);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+
+void MESH_OT_extrude(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude Mesh";
+ ot->idname= "MESH_OT_extrude";
+
+ /* api callbacks */
+ ot->invoke= mesh_extrude_invoke;
+ ot->exec= mesh_extrude_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* to give to transform */
+ RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+}
+
+static int split_mesh(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ WM_cursor_wait(1);
+
+ /* make duplicate first */
+ adduplicateflag(em, SELECT);
+ /* old faces have flag 128 set, delete them */
+ delfaceflag(em, 128);
+ recalc_editnormals(em);
+
+ WM_cursor_wait(0);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_split(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Split Mesh";
+ ot->idname= "MESH_OT_split";
+
+ /* api callbacks */
+ ot->exec= split_mesh;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+static int extrude_repeat_mesh(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+
+ int steps = RNA_int_get(op->ptr,"steps");
+
+ float offs = RNA_float_get(op->ptr,"offset");
+
+ float dvec[3], tmat[3][3], bmat[3][3], nor[3]= {0.0, 0.0, 0.0};
+ short a;
+
+ /* dvec */
+ dvec[0]= rv3d->persinv[2][0];
+ dvec[1]= rv3d->persinv[2][1];
+ dvec[2]= rv3d->persinv[2][2];
+ Normalize(dvec);
+ dvec[0]*= offs;
+ dvec[1]*= offs;
+ dvec[2]*= offs;
+
+ /* base correction */
+ Mat3CpyMat4(bmat, obedit->obmat);
+ Mat3Inv(tmat, bmat);
+ Mat3MulVecfl(tmat, dvec);
+
+ for(a=0; a<steps; a++) {
+ extrudeflag(obedit, em, SELECT, nor);
+ translateflag(em, SELECT, dvec);
+ }
+
+ recalc_editnormals(em);
+
+ EM_fgon_flags(em);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_extrude_repeat(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude Repeat Mesh";
+ ot->idname= "MESH_OT_extrude_repeat";
+
+ /* api callbacks */
+ ot->exec= extrude_repeat_mesh;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, 100.0f, "Offset", "", 0.0f, FLT_MAX);
+ RNA_def_int(ot->srna, "steps", 10, 0, 180, "Steps", "", 0, INT_MAX);
+}
+
+/* ************************** spin operator ******************** */
+
+static int spin_mesh(bContext *C, float *dvec, int steps, float degr, int dupli )
+{
+ Object *obedit= CTX_data_edit_object(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ EditVert *eve,*nextve;
+ float nor[3]= {0.0f, 0.0f, 0.0f};
+ 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= 1;
+
+ /* imat and center and size */
+ Mat3CpyMat4(bmat, obedit->obmat);
+ Mat3Inv(imat,bmat);
+
+ curs= give_cursor(scene, v3d);
+ VECCOPY(cent, curs);
+ cent[0]-= obedit->obmat[3][0];
+ cent[1]-= obedit->obmat[3][1];
+ cent[2]-= obedit->obmat[3][2];
+ Mat3MulVecfl(imat, cent);
+
+ phi= degr*M_PI/360.0;
+ phi/= steps;
+ if(scene->toolsettings->editbutflag & B_CLOCKWISE) phi= -phi;
+
+ if(dvec) {
+ n[0]= rv3d->viewinv[1][0];
+ n[1]= rv3d->viewinv[1][1];
+ n[2]= rv3d->viewinv[1][2];
+ } else {
+ n[0]= rv3d->viewinv[2][0];
+ n[1]= rv3d->viewinv[2][1];
+ n[2]= rv3d->viewinv[2][2];
+ }
+ Normalize(n);
+
+ q[0]= (float)cos(phi);
+ si= (float)sin(phi);
+ q[1]= n[0]*si;
+ q[2]= n[1]*si;
+ q[3]= n[2]*si;
+ QuatToMat3(q, cmat);
+
+ Mat3MulMat3(tmat,cmat,bmat);
+ Mat3MulMat3(bmat,imat,tmat);
+
+ if(dupli==0)
+ if(scene->toolsettings->editbutflag & B_KEEPORIG)
+ adduplicateflag(em, 1);
+
+ for(a=0; a<steps; a++) {
+ if(dupli==0) ok= extrudeflag(obedit, em, SELECT, nor);
+ else adduplicateflag(em, SELECT);
+
+ if(ok==0)
+ break;
+
+ rotateflag(em, SELECT, cent, bmat);
+ if(dvec) {
+ Mat3MulVecfl(bmat,dvec);
+ translateflag(em, SELECT, dvec);
+ }
+ }
+
+ if(ok==0) {
+ /* no vertices or only loose ones selected, remove duplicates */
+ eve= em->verts.first;
+ while(eve) {
+ nextve= eve->next;
+ if(eve->f & SELECT) {
+ BLI_remlink(&em->verts,eve);
+ free_editvert(em, eve);
+ }
+ eve= nextve;
+ }
+ }
+ else {
+ recalc_editnormals(em);
+
+ EM_fgon_flags(em);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return ok;
+}
+
+static int spin_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ int ok;
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ ok= spin_mesh(C, NULL, RNA_int_get(op->ptr,"steps"), RNA_float_get(op->ptr,"degrees"), RNA_boolean_get(op->ptr,"dupli"));
+ if(ok==0) {
+ BKE_report(op->reports, RPT_ERROR, "No valid vertices are selected");
+ return OPERATOR_CANCELLED;
+ }
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_spin(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Spin";
+ ot->idname= "MESH_OT_spin";
+
+ /* api callbacks */
+ ot->exec= spin_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /*props */
+ RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, INT_MAX);
+ RNA_def_boolean(ot->srna, "dupli", 0, "Dupli", "Make Duplicates");
+ RNA_def_float(ot->srna, "degrees", 90.0f, -FLT_MAX, FLT_MAX, "Degrees", "Degrees", -360.0f, 360.0f);
+}
+
+static int screw_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ EditVert *eve,*v1=0,*v2=0;
+ EditEdge *eed;
+ float dvec[3], nor[3];
+ int steps, turns;
+
+ turns= RNA_int_get(op->ptr, "turns");
+ steps= RNA_int_get(op->ptr, "steps");
+
+ /* clear flags */
+ for(eve= em->verts.first; eve; eve= eve->next)
+ eve->f1= 0;
+
+ /* edges set flags in verts */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->v1->f & SELECT) {
+ if(eed->v2->f & SELECT) {
+ /* watch: f1 is a byte */
+ if(eed->v1->f1<2) eed->v1->f1++;
+ if(eed->v2->f1<2) eed->v2->f1++;
+ }
+ }
+ }
+ /* find two vertices with eve->f1==1, more or less is wrong */
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f1==1) {
+ if(v1==NULL) v1= eve;
+ else if(v2==NULL) v2= eve;
+ else {
+ v1= NULL;
+ break;
+ }
+ }
+ }
+ if(v1==NULL || v2==NULL) {
+ BKE_report(op->reports, RPT_ERROR, "You have to select a string of connected vertices too");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* calculate dvec */
+ dvec[0]= ( v1->co[0]- v2->co[0] )/steps;
+ dvec[1]= ( v1->co[1]- v2->co[1] )/steps;
+ dvec[2]= ( v1->co[2]- v2->co[2] )/steps;
+
+ VECCOPY(nor, 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];
+ }
+
+ if(spin_mesh(C, dvec, turns*steps, 360.0f*turns, 0)) {
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No valid vertices are selected");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+}
+
+void MESH_OT_screw(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Screw";
+ ot->idname= "MESH_OT_screw";
+
+ /* api callbacks */
+ ot->exec= screw_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /*props */
+ RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, 256);
+ RNA_def_int(ot->srna, "turns", 1, 0, INT_MAX, "Turns", "Turns", 0, 256);
+}
+
+static void erase_edges(EditMesh *em, ListBase *l)
+{
+ EditEdge *ed, *nexted;
+
+ ed = (EditEdge *) l->first;
+ while(ed) {
+ nexted= ed->next;
+ if( (ed->v1->f & SELECT) || (ed->v2->f & SELECT) ) {
+ remedge(em, ed);
+ free_editedge(em, ed);
+ }
+ ed= nexted;
+ }
+}
+
+static void erase_faces(EditMesh *em, ListBase *l)
+{
+ EditFace *f, *nextf;
+
+ f = (EditFace *) l->first;
+
+ while(f) {
+ nextf= f->next;
+ if( faceselectedOR(f, SELECT) ) {
+ BLI_remlink(l, f);
+ free_editface(em, f);
+ }
+ f = nextf;
+ }
+}
+
+static void erase_vertices(EditMesh *em, ListBase *l)
+{
+ EditVert *v, *nextv;
+
+ v = (EditVert *) l->first;
+ while(v) {
+ nextv= v->next;
+ if(v->f & 1) {
+ BLI_remlink(l, v);
+ free_editvert(em, v);
+ }
+ v = nextv;
+ }
+}
+
+void delete_mesh(Object *obedit, EditMesh *em, wmOperator *op, int event)
+{
+ EditFace *efa, *nextvl;
+ EditVert *eve,*nextve;
+ EditEdge *eed,*nexted;
+ int count;
+ char *str="Erase";
+
+
+ if(event<1) return;
+
+ if(event==10 ) {
+ str= "Erase Vertices";
+ erase_edges(em, &em->edges);
+ erase_faces(em, &em->faces);
+ erase_vertices(em, &em->verts);
+ }
+ else if(event==6) {
+ if(!EdgeLoopDelete(em, op))
+ return;
+
+ str= "Erase Edge Loop";
+ }
+ else if(event==4) {
+ str= "Erase Edges & Faces";
+ efa= em->faces.first;
+ while(efa) {
+ nextvl= efa->next;
+ /* delete only faces with 1 or more edges selected */
+ count= 0;
+ if(efa->e1->f & SELECT) count++;
+ if(efa->e2->f & SELECT) count++;
+ if(efa->e3->f & SELECT) count++;
+ if(efa->e4 && (efa->e4->f & SELECT)) count++;
+ if(count) {
+ BLI_remlink(&em->faces, efa);
+ free_editface(em, efa);
+ }
+ efa= nextvl;
+ }
+ eed= em->edges.first;
+ while(eed) {
+ nexted= eed->next;
+ if(eed->f & SELECT) {
+ remedge(em, eed);
+ free_editedge(em, eed);
+ }
+ eed= nexted;
+ }
+ efa= em->faces.first;
+ while(efa) {
+ nextvl= efa->next;
+ event=0;
+ if( efa->v1->f & SELECT) event++;
+ if( efa->v2->f & SELECT) event++;
+ if( efa->v3->f & SELECT) event++;
+ if(efa->v4 && (efa->v4->f & SELECT)) event++;
+
+ if(event>1) {
+ BLI_remlink(&em->faces, efa);
+ free_editface(em, efa);
+ }
+ efa= nextvl;
+ }
+ }
+ else if(event==1) {
+ str= "Erase Edges";
+ // faces first
+ efa= em->faces.first;
+ while(efa) {
+ nextvl= efa->next;
+ event=0;
+ if( efa->e1->f & SELECT) event++;
+ if( efa->e2->f & SELECT) event++;
+ if( efa->e3->f & SELECT) event++;
+ if(efa->e4 && (efa->e4->f & SELECT)) event++;
+
+ if(event) {
+ BLI_remlink(&em->faces, efa);
+ free_editface(em, efa);
+ }
+ efa= nextvl;
+ }
+ eed= em->edges.first;
+ while(eed) {
+ nexted= eed->next;
+ if(eed->f & SELECT) {
+ remedge(em, eed);
+ free_editedge(em, eed);
+ }
+ eed= nexted;
+ }
+ /* to remove loose vertices: */
+ eed= em->edges.first;
+ while(eed) {
+ if( eed->v1->f & SELECT) eed->v1->f-=SELECT;
+ if( eed->v2->f & SELECT) eed->v2->f-=SELECT;
+ eed= eed->next;
+ }
+ eve= em->verts.first;
+ while(eve) {
+ nextve= eve->next;
+ if(eve->f & SELECT) {
+ BLI_remlink(&em->verts,eve);
+ free_editvert(em, eve);
+ }
+ eve= nextve;
+ }
+
+ }
+ else if(event==2) {
+ str="Erase Faces";
+ delfaceflag(em, SELECT);
+ }
+ else if(event==3) {
+ str= "Erase All";
+ if(em->verts.first) free_vertlist(em, &em->verts);
+ if(em->edges.first) free_edgelist(em, &em->edges);
+ if(em->faces.first) free_facelist(em, &em->faces);
+ if(em->selected.first) BLI_freelistN(&(em->selected));
+ }
+ else if(event==5) {
+ str= "Erase Only Faces";
+ efa= em->faces.first;
+ while(efa) {
+ nextvl= efa->next;
+ if(efa->f & SELECT) {
+ BLI_remlink(&em->faces, efa);
+ free_editface(em, efa);
+ }
+ efa= nextvl;
+ }
+ }
+
+ EM_fgon_flags(em); // redo flags and indices for fgons
+
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+}
+
+/* Note, these values must match delete_mesh() event values */
+static EnumPropertyItem prop_mesh_delete_types[] = {
+ {10,"VERT", "Vertices", ""},
+ {1, "EDGE", "Edges", ""},
+ {2, "FACE", "Faces", ""},
+ {3, "ALL", "All", ""},
+ {4, "EDGE_FACE","Edges & Faces", ""},
+ {5, "ONLY_FACE","Only Faces", ""},
+ {6, "EDGE_LOOP","Edge Loop", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int delete_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ delete_mesh(obedit,em, op,RNA_enum_get(op->ptr, "type"));
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete";
+ ot->idname= "MESH_OT_delete";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= delete_mesh_exec;
+
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /*props */
+ RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, 10, "Type", "Method used for deleting mesh data");
+}
+
+
+/*GB*/
+/*-------------------------------------------------------------------------------*/
+/*--------------------------- Edge Based Subdivide ------------------------------*/
+
+#define EDGENEW 2
+#define FACENEW 2
+#define EDGEINNER 4
+#define EDGEOLD 8
+
+/*used by faceloop cut to select only edges valid for edge slide*/
+#define DOUBLEOPFILL 16
+
+/* calculates offset for co, based on fractal, sphere or smooth settings */
+static void alter_co(float *co, EditEdge *edge, float rad, int beauty, float perc)
+{
+ float vec1[3], fac;
+
+ if(beauty & B_SMOOTH) {
+ /* we calculate an offset vector vec1[], to be added to *co */
+ float len, fac, nor[3], nor1[3], nor2[3];
+
+ VecSubf(nor, edge->v1->co, edge->v2->co);
+ len= 0.5f*Normalize(nor);
+
+ VECCOPY(nor1, edge->v1->no);
+ VECCOPY(nor2, edge->v2->no);
+
+ /* cosine angle */
+ fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
+
+ vec1[0]= fac*nor1[0];
+ vec1[1]= fac*nor1[1];
+ vec1[2]= fac*nor1[2];
+
+ /* cosine angle */
+ fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
+
+ vec1[0]+= fac*nor2[0];
+ vec1[1]+= fac*nor2[1];
+ vec1[2]+= fac*nor2[2];
+
+ vec1[0]*= rad*len;
+ vec1[1]*= rad*len;
+ vec1[2]*= rad*len;
+
+ co[0] += vec1[0];
+ co[1] += vec1[1];
+ co[2] += vec1[2];
+ }
+ else {
+ if(rad > 0.0) { /* subdivide sphere */
+ Normalize(co);
+ co[0]*= rad;
+ co[1]*= rad;
+ co[2]*= rad;
+ }
+ else if(rad< 0.0) { /* fractal subdivide */
+ fac= rad* VecLenf(edge->v1->co, edge->v2->co);
+ vec1[0]= fac*(float)(0.5-BLI_drand());
+ vec1[1]= fac*(float)(0.5-BLI_drand());
+ vec1[2]= fac*(float)(0.5-BLI_drand());
+ VecAddf(co, co, vec1);
+ }
+
+ }
+}
+
+/* assumes in the edge is the correct interpolated vertices already */
+/* percent defines the interpolation, rad and beauty are for special options */
+/* results in new vertex with correct coordinate, vertex normal and weight group info */
+static EditVert *subdivide_edge_addvert(EditMesh *em, EditEdge *edge, float rad, int beauty, float percent)
+{
+ EditVert *ev;
+ float co[3];
+
+ co[0] = (edge->v2->co[0]-edge->v1->co[0])*percent + edge->v1->co[0];
+ co[1] = (edge->v2->co[1]-edge->v1->co[1])*percent + edge->v1->co[1];
+ co[2] = (edge->v2->co[2]-edge->v1->co[2])*percent + edge->v1->co[2];
+
+ /* offset for smooth or sphere or fractal */
+ alter_co(co, edge, rad, beauty, percent);
+
+ /* clip if needed by mirror modifier */
+ if (edge->v1->f2) {
+ if ( edge->v1->f2 & edge->v2->f2 & 1) {
+ co[0]= 0.0f;
+ }
+ if ( edge->v1->f2 & edge->v2->f2 & 2) {
+ co[1]= 0.0f;
+ }
+ if ( edge->v1->f2 & edge->v2->f2 & 4) {
+ co[2]= 0.0f;
+ }
+ }
+
+ ev = addvertlist(em, co, NULL);
+
+ /* vert data (vgroups, ..) */
+ EM_data_interp_from_verts(em, edge->v1, edge->v2, ev, percent);
+
+ /* normal */
+ ev->no[0] = (edge->v2->no[0]-edge->v1->no[0])*percent + edge->v1->no[0];
+ ev->no[1] = (edge->v2->no[1]-edge->v1->no[1])*percent + edge->v1->no[1];
+ ev->no[2] = (edge->v2->no[2]-edge->v1->no[2])*percent + edge->v1->no[2];
+ Normalize(ev->no);
+
+ return ev;
+}
+
+static void flipvertarray(EditVert** arr, short size)
+{
+ EditVert *hold;
+ int i;
+
+ for(i=0; i<size/2; i++) {
+ hold = arr[i];
+ arr[i] = arr[size-i-1];
+ arr[size-i-1] = hold;
+ }
+}
+
+static void facecopy(EditMesh *em, EditFace *source, EditFace *target)
+{
+ float *v1 = source->v1->co, *v2 = source->v2->co, *v3 = source->v3->co;
+ float *v4 = source->v4? source->v4->co: NULL;
+ float w[4][4];
+
+ CustomData_em_copy_data(&em->fdata, &em->fdata, source->data, &target->data);
+
+ target->mat_nr = source->mat_nr;
+ target->flag = source->flag;
+ target->h = source->h;
+
+ InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v1->co, w[0]);
+ InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v2->co, w[1]);
+ InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v3->co, w[2]);
+ if (target->v4)
+ InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v4->co, w[3]);
+
+ CustomData_em_interp(&em->fdata, &source->data, NULL, (float*)w, 1, target->data);
+}
+
+static void fill_quad_single(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, int seltype)
+{
+ EditEdge *cedge=NULL;
+ EditVert *v[4], **verts;
+ EditFace *hold;
+ short start=0, end, left, right, vertsize,i;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
+ else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
+ else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
+ else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}
+
+ // Point verts to the array of new verts for cedge
+ verts = BLI_ghash_lookup(gh, cedge);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0] != v[start]) {flipvertarray(verts,numcuts+2);}
+ end = (start+1)%4;
+ left = (start+2)%4;
+ right = (start+3)%4;
+
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ |---*---*---|
+ | |
+ | |
+ | |
+ -------------
+ left right
+
+ where start,end,left, right are indexes of EditFace->v1, etc (stored in v)
+ and 0,1,2... are the indexes of the new verts stored in verts
+
+ We will fill this case like this or this depending on even or odd cuts
+
+ |---*---*---| |---*---|
+ | / \ | | / \ |
+ | / \ | | / \ |
+ |/ \| |/ \|
+ ------------- ---------
+ */
+
+ // Make center face
+ if(vertsize % 2 == 0) {
+ hold = addfacelist(em, verts[(vertsize-1)/2],verts[((vertsize-1)/2)+1],v[left],v[right], NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ hold->e4->f2 |= EDGEINNER;
+ }else{
+ hold = addfacelist(em, verts[(vertsize-1)/2],v[left],v[right],NULL, NULL,NULL);
+ hold->e1->f2 |= EDGEINNER;
+ hold->e3->f2 |= EDGEINNER;
+ }
+ facecopy(em, efa,hold);
+
+ // Make side faces
+ for(i=0;i<(vertsize-1)/2;i++) {
+ hold = addfacelist(em, verts[i],verts[i+1],v[right],NULL,NULL,NULL);
+ facecopy(em, efa,hold);
+ if(i+1 != (vertsize-1)/2) {
+ if(seltype == SUBDIV_SELECT_INNER) {
+ hold->e2->f2 |= EDGEINNER;
+ }
+ }
+ hold = addfacelist(em, verts[vertsize-2-i],verts[vertsize-1-i],v[left],NULL,NULL,NULL);
+ facecopy(em, efa,hold);
+ if(i+1 != (vertsize-1)/2) {
+ if(seltype == SUBDIV_SELECT_INNER) {
+ hold->e3->f2 |= EDGEINNER;
+ }
+ }
+ }
+}
+
+static void fill_tri_single(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, int seltype)
+{
+ EditEdge *cedge=NULL;
+ EditVert *v[3], **verts;
+ EditFace *hold;
+ short start=0, end, op, vertsize,i;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+
+ if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
+ else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
+ else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
+
+ // Point verts to the array of new verts for cedge
+ verts = BLI_ghash_lookup(gh, cedge);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0] != v[start]) {flipvertarray(verts,numcuts+2);}
+ end = (start+1)%3;
+ op = (start+2)%3;
+
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ |---*---*---|
+ \ |
+ \ |
+ \ |
+ \ |
+ \ |
+ \ |
+ |op
+
+ where start,end,op are indexes of EditFace->v1, etc (stored in v)
+ and 0,1,2... are the indexes of the new verts stored in verts
+
+ We will fill this case like this or this depending on even or odd cuts
+
+ 3 2 1 0
+ |---*---*---|
+ \ \ \ |
+ \ \ \ |
+ \ \ \ |
+ \ \ \|
+ \ \\|
+ \ |
+ |op
+ */
+
+ // Make side faces
+ for(i=0;i<(vertsize-1);i++) {
+ hold = addfacelist(em, verts[i],verts[i+1],v[op],NULL,NULL,NULL);
+ if(i+1 != vertsize-1) {
+ if(seltype == SUBDIV_SELECT_INNER) {
+ hold->e2->f2 |= EDGEINNER;
+ }
+ }
+ facecopy(em, efa,hold);
+ }
+}
+
+static void fill_quad_double_op(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
+{
+ EditEdge *cedge[2]={NULL, NULL};
+ EditVert *v[4], **verts[2];
+ EditFace *hold;
+ short start=0, end, left, right, vertsize,i;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(efa->e1->f & SELECT) { cedge[0] = efa->e1; cedge[1] = efa->e3; start = 0;}
+ else if(efa->e2->f & SELECT) { cedge[0] = efa->e2; cedge[1] = efa->e4; start = 1;}
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+ verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
+ end = (start+1)%4;
+ left = (start+2)%4;
+ right = (start+3)%4;
+ if(verts[1][0] != v[left]) {flipvertarray(verts[1],numcuts+2);}
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ |---*---*---|
+ | |
+ | |
+ | |
+ |---*---*---|
+ 0 1 2 3
+ left right
+
+ We will fill this case like this or this depending on even or odd cuts
+
+ |---*---*---|
+ | | | |
+ | | | |
+ | | | |
+ |---*---*---|
+ */
+
+ // Make side faces
+ for(i=0;i<vertsize-1;i++) {
+ hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-2-i],verts[1][vertsize-1-i],NULL,NULL);
+ if(i < vertsize-2) {
+ hold->e2->f2 |= EDGEINNER;
+ hold->e2->f2 |= DOUBLEOPFILL;
+ }
+ facecopy(em, efa,hold);
+ }
+}
+
+static void fill_quad_double_adj_path(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
+{
+ EditEdge *cedge[2]={NULL, NULL};
+ EditVert *v[4], **verts[2];
+ EditFace *hold;
+ short start=0, start2=0, vertsize,i;
+ int ctrl= 0; // XXX
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;}
+ if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;}
+ if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3;}
+ if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0;}
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+ verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ start2 0|---*---*---|
+ | |
+ 1* |
+ | |
+ 2* |
+ | |
+ end2 3|-----------|
+
+ We will fill this case like this or this depending on even or odd cuts
+ |---*---*---|
+ | / / / |
+ * / / |
+ | / / |
+ * / |
+ | / |
+ |-----------|
+ */
+
+ // Make outside tris
+ hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
+ /* when ctrl is depressed, only want verts on the cutline selected */
+ if (ctrl)
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+ hold = addfacelist(em, verts[0][0],verts[1][vertsize-1],v[(start2+2)%4],NULL,NULL,NULL);
+ /* when ctrl is depressed, only want verts on the cutline selected */
+ if (ctrl)
+ hold->e1->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+ //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
+ // hold->e1->h |= EM_FGON;
+ //}
+ // Make side faces
+
+ for(i=0;i<numcuts;i++) {
+ hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+ }
+ //EM_fgon_flags(em);
+
+}
+
+static void fill_quad_double_adj_fan(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
+{
+ EditEdge *cedge[2]={NULL, NULL};
+ EditVert *v[4], *op=NULL, **verts[2];
+ EditFace *hold;
+ short start=0, start2=0, vertsize,i;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1; op = efa->v4;}
+ if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2; op = efa->v1;}
+ if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3; op = efa->v2;}
+ if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0; op = efa->v3;}
+
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+ verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ start2 0|---*---*---|
+ | |
+ 1* |
+ | |
+ 2* |
+ | |
+ end2 3|-----------|op
+
+ We will fill this case like this or this (warning horrible ascii art follows)
+ |---*---*---|
+ | \ \ \ |
+ *---\ \ \ |
+ | \ \ \ \|
+ *---- \ \ \ |
+ | --- \\\|
+ |-----------|
+ */
+
+ for(i=0;i<=numcuts;i++) {
+ hold = addfacelist(em, op,verts[1][numcuts-i],verts[1][numcuts-i+1],NULL,NULL,NULL);
+ hold->e1->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+
+ hold = addfacelist(em, op,verts[0][i],verts[0][i+1],NULL,NULL,NULL);
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+ }
+}
+
+static void fill_quad_double_adj_inner(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
+{
+ EditEdge *cedge[2]={NULL, NULL};
+ EditVert *v[4], *op=NULL, **verts[2],**inner;
+ EditFace *hold;
+ short start=0, start2=0, vertsize,i;
+ float co[3];
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1; op = efa->v4;}
+ if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2; op = efa->v1;}
+ if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3; op = efa->v2;}
+ if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0; op = efa->v3;}
+
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+ verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ start2 0|---*---*---|
+ | |
+ 1* |
+ | |
+ 2* |
+ | |
+ end2 3|-----------|op
+
+ We will fill this case like this or this (warning horrible ascii art follows)
+ |---*-----*---|
+ | * / |
+ * \ / |
+ | * |
+ | / \ |
+ * \ |
+ | \ |
+ |-------------|
+ */
+
+ // Add Inner Vert(s)
+ inner = MEM_mallocN(sizeof(EditVert*)*numcuts,"New inner verts");
+
+ for(i=0;i<numcuts;i++) {
+ co[0] = (verts[0][numcuts-i]->co[0] + verts[1][i+1]->co[0] ) / 2 ;
+ co[1] = (verts[0][numcuts-i]->co[1] + verts[1][i+1]->co[1] ) / 2 ;
+ co[2] = (verts[0][numcuts-i]->co[2] + verts[1][i+1]->co[2] ) / 2 ;
+ inner[i] = addvertlist(em, co, NULL);
+ inner[i]->f2 |= EDGEINNER;
+
+ EM_data_interp_from_verts(em, verts[0][numcuts-i], verts[1][i+1], inner[i], 0.5f);
+ }
+
+ // Add Corner Quad
+ hold = addfacelist(em, verts[0][numcuts+1],verts[1][1],inner[0],verts[0][numcuts],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+ // Add Bottom Quads
+ hold = addfacelist(em, verts[0][0],verts[0][1],inner[numcuts-1],op,NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+
+ hold = addfacelist(em, op,inner[numcuts-1],verts[1][numcuts],verts[1][numcuts+1],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+
+ //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
+ // hold->e1->h |= EM_FGON;
+ //}
+ // Add Fill Quads (if # cuts > 1)
+
+ for(i=0;i<numcuts-1;i++) {
+ hold = addfacelist(em, inner[i],verts[1][i+1],verts[1][i+2],inner[i+1],NULL,NULL);
+ hold->e1->f2 |= EDGEINNER;
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+
+ hold = addfacelist(em, inner[i],inner[i+1],verts[0][numcuts-1-i],verts[0][numcuts-i],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ hold->e4->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+
+ //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
+ // hold->e1->h |= EM_FGON;
+ //}
+ }
+
+ //EM_fgon_flags(em);
+
+ MEM_freeN(inner);
+}
+
+static void fill_tri_double(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
+{
+ EditEdge *cedge[2]={NULL, NULL};
+ EditVert *v[3], **verts[2];
+ EditFace *hold;
+ short start=0, start2=0, vertsize,i;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+
+ if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;}
+ if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;}
+ if(efa->e3->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e1; start = 2; start2 = 0;}
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+ verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ start2 0|---*---*---|
+ | /
+ 1* /
+ | /
+ 2* /
+ | /
+ end2 3|
+
+ We will fill this case like this or this depending on even or odd cuts
+ |---*---*---|
+ | / / /
+ * / /
+ | / /
+ * /
+ | /
+ |
+ */
+
+ // Make outside tri
+ hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+ // Make side faces
+
+ for(i=0;i<numcuts;i++) {
+ hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+ }
+}
+
+static void fill_quad_triple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
+{
+ EditEdge *cedge[3]={0};
+ EditVert *v[4], **verts[3];
+ EditFace *hold;
+ short start=0, start2=0, start3=0, vertsize, i, repeats;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(!(efa->e1->f & SELECT)) {
+ cedge[0] = efa->e2;
+ cedge[1] = efa->e3;
+ cedge[2] = efa->e4;
+ start = 1;start2 = 2;start3 = 3;
+ }
+ if(!(efa->e2->f & SELECT)) {
+ cedge[0] = efa->e3;
+ cedge[1] = efa->e4;
+ cedge[2] = efa->e1;
+ start = 2;start2 = 3;start3 = 0;
+ }
+ if(!(efa->e3->f & SELECT)) {
+ cedge[0] = efa->e4;
+ cedge[1] = efa->e1;
+ cedge[2] = efa->e2;
+ start = 3;start2 = 0;start3 = 1;
+ }
+ if(!(efa->e4->f & SELECT)) {
+ cedge[0] = efa->e1;
+ cedge[1] = efa->e2;
+ cedge[2] = efa->e3;
+ start = 0;start2 = 1;start3 = 2;
+ }
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+ verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+ verts[2] = BLI_ghash_lookup(gh, cedge[2]);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
+ if(verts[2][0] != v[start3]) {flipvertarray(verts[2],numcuts+2);}
+ /*
+ We should have something like this now
+
+ start2
+ 3 2 1 0
+ start3 0|---*---*---|3
+ | |
+ 1* *2
+ | |
+ 2* *1
+ | |
+ 3|-----------|0 start
+
+ We will fill this case like this or this depending on even or odd cuts
+ there are a couple of differences. For odd cuts, there is a tri in the
+ middle as well as 1 quad at the bottom (not including the extra quads
+ for odd cuts > 1
+
+ For even cuts, there is a quad in the middle and 2 quads on the bottom
+
+ they are numbered here for clarity
+
+ 1 outer tris and bottom quads
+ 2 inner tri or quad
+ 3 repeating quads
+
+ |---*---*---*---|
+ |1/ / \ \ 1|
+ |/ 3 / \ 3 \|
+ * / 2 \ *
+ | / \ |
+ |/ \ |
+ *---------------*
+ | 3 |
+ | |
+ *---------------*
+ | |
+ | 1 |
+ | |
+ |---------------|
+
+ |---*---*---*---*---|
+ | 1/ / \ \ 1|
+ | / / \ \ |
+ |/ 3 / \ 3 \|
+ * / \ *
+ | / \ |
+ | / 2 \ |
+ |/ \|
+ *-------------------*
+ | |
+ | 3 |
+ | |
+ *-------------------*
+ | |
+ | 1 |
+ | |
+ *-------------------*
+ | |
+ | 1 |
+ | |
+ |-------------------|
+
+ */
+
+ // Make outside tris
+ hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+ hold = addfacelist(em, verts[1][vertsize-2],verts[1][vertsize-1],verts[2][1],NULL,NULL,NULL);
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+ // Make bottom quad
+ hold = addfacelist(em, verts[0][0],verts[0][1],verts[2][vertsize-2],verts[2][vertsize-1],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+ //If it is even cuts, add the 2nd lower quad
+ if(numcuts % 2 == 0) {
+ hold = addfacelist(em, verts[0][1],verts[0][2],verts[2][vertsize-3],verts[2][vertsize-2],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+ // Also Make inner quad
+ hold = addfacelist(em, verts[1][numcuts/2],verts[1][(numcuts/2)+1],verts[2][numcuts/2],verts[0][(numcuts/2)+1],NULL,NULL);
+ hold->e3->f2 |= EDGEINNER;
+ //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
+ // hold->e3->h |= EM_FGON;
+ //}
+ facecopy(em, efa,hold);
+ repeats = (numcuts / 2) -1;
+ } else {
+ // Make inner tri
+ hold = addfacelist(em, verts[1][(numcuts/2)+1],verts[2][(numcuts/2)+1],verts[0][(numcuts/2)+1],NULL,NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
+ // hold->e2->h |= EM_FGON;
+ //}
+ facecopy(em, efa,hold);
+ repeats = ((numcuts+1) / 2)-1;
+ }
+
+ // cuts for 1 and 2 do not have the repeating quads
+ if(numcuts < 3) {repeats = 0;}
+ for(i=0;i<repeats;i++) {
+ //Make side repeating Quads
+ hold = addfacelist(em, verts[1][i+1],verts[1][i+2],verts[0][vertsize-i-3],verts[0][vertsize-i-2],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+ hold = addfacelist(em, verts[1][vertsize-i-3],verts[1][vertsize-i-2],verts[2][i+1],verts[2][i+2],NULL,NULL);
+ hold->e4->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+ }
+ // Do repeating bottom quads
+ for(i=0;i<repeats;i++) {
+ if(numcuts % 2 == 1) {
+ hold = addfacelist(em, verts[0][1+i],verts[0][2+i],verts[2][vertsize-3-i],verts[2][vertsize-2-i],NULL,NULL);
+ } else {
+ hold = addfacelist(em, verts[0][2+i],verts[0][3+i],verts[2][vertsize-4-i],verts[2][vertsize-3-i],NULL,NULL);
+ }
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(em, efa,hold);
+ }
+ //EM_fgon_flags(em);
+}
+
+static void fill_quad_quadruple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, float rad, int beauty)
+{
+ EditVert **verts[4], ***innerverts;
+ EditFace *hold;
+ EditEdge temp;
+ short vertsize, i, j;
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, efa->e1);
+ verts[1] = BLI_ghash_lookup(gh, efa->e2);
+ verts[2] = BLI_ghash_lookup(gh, efa->e3);
+ verts[3] = BLI_ghash_lookup(gh, efa->e4);
+
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}
+ if(verts[2][0] == efa->v3) {flipvertarray(verts[2],numcuts+2);}
+ if(verts[3][0] == efa->v4) {flipvertarray(verts[3],numcuts+2);}
+ /*
+ We should have something like this now
+ 1
+
+ 3 2 1 0
+ 0|---*---*---|0
+ | |
+ 1* *1
+ 2 | | 4
+ 2* *2
+ | |
+ 3|---*---*---|3
+ 3 2 1 0
+
+ 3
+ // we will fill a 2 dim array of editvert*s to make filling easier
+ // the innervert order is shown
+
+ 0 0---1---2---3
+ | | | |
+ 1 0---1---2---3
+ | | | |
+ 2 0---1---2---3
+ | | | |
+ 3 0---1---2---3
+
+ */
+ innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts outer array");
+ for(i=0;i<numcuts+2;i++) {
+ innerverts[i] = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts inner array");
+ }
+
+ // first row is e1 last row is e3
+ for(i=0;i<numcuts+2;i++) {
+ innerverts[0][i] = verts[0][(numcuts+1)-i];
+ innerverts[numcuts+1][i] = verts[2][(numcuts+1)-i];
+ }
+
+ for(i=1;i<=numcuts;i++) {
+ /* we create a fake edge for the next loop */
+ temp.v2 = innerverts[i][0] = verts[1][i];
+ temp.v1 = innerverts[i][numcuts+1] = verts[3][i];
+
+ for(j=1;j<=numcuts;j++) {
+ float percent= (float)j/(float)(numcuts+1);
+
+ innerverts[i][(numcuts+1)-j]= subdivide_edge_addvert(em, &temp, rad, beauty, percent);
+ }
+ }
+ // Fill with faces
+ for(i=0;i<numcuts+1;i++) {
+ for(j=0;j<numcuts+1;j++) {
+ hold = addfacelist(em, innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],innerverts[i+1][j+1],NULL,NULL);
+ hold->e1->f2 = EDGENEW;
+ hold->e2->f2 = EDGENEW;
+ hold->e3->f2 = EDGENEW;
+ hold->e4->f2 = EDGENEW;
+
+ if(i != 0) { hold->e1->f2 |= EDGEINNER; }
+ if(j != 0) { hold->e2->f2 |= EDGEINNER; }
+ if(i != numcuts) { hold->e3->f2 |= EDGEINNER; }
+ if(j != numcuts) { hold->e4->f2 |= EDGEINNER; }
+
+ facecopy(em, efa,hold);
+ }
+ }
+ // Clean up our dynamic multi-dim array
+ for(i=0;i<numcuts+2;i++) {
+ MEM_freeN(innerverts[i]);
+ }
+ MEM_freeN(innerverts);
+}
+
+static void fill_tri_triple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, float rad, int beauty)
+{
+ EditVert **verts[3], ***innerverts;
+ short vertsize, i, j;
+ EditFace *hold;
+ EditEdge temp;
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, efa->e1);
+ verts[1] = BLI_ghash_lookup(gh, efa->e2);
+ verts[2] = BLI_ghash_lookup(gh, efa->e3);
+
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}
+ if(verts[2][0] != efa->v3) {flipvertarray(verts[2],numcuts+2);}
+ /*
+ We should have something like this now
+ 3
+
+ 3 2 1 0
+ 0|---*---*---|3
+ | /
+ 1 1* *2
+ | /
+ 2* *1 2
+ | /
+ 3|/
+ 0
+
+ we will fill a 2 dim array of editvert*s to make filling easier
+
+ 3
+
+ 0 0---1---2---3---4
+ | / | / |/ | /
+ 1 0---1----2---3
+ 1 | / | / | /
+ 2 0----1---2 2
+ | / | /
+ |/ |/
+ 3 0---1
+ | /
+ |/
+ 4 0
+
+ */
+
+ innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"tri-tri subdiv inner verts outer array");
+ for(i=0;i<numcuts+2;i++) {
+ innerverts[i] = MEM_mallocN(sizeof(EditVert*)*((numcuts+2)-i),"tri-tri subdiv inner verts inner array");
+ }
+ //top row is e3 backwards
+ for(i=0;i<numcuts+2;i++) {
+ innerverts[0][i] = verts[2][(numcuts+1)-i];
+ }
+
+ for(i=1;i<=numcuts+1;i++) {
+ //fake edge, first vert is from e1, last is from e2
+ temp.v1= innerverts[i][0] = verts[0][i];
+ temp.v2= innerverts[i][(numcuts+1)-i] = verts[1][(numcuts+1)-i];
+
+ for(j=1;j<(numcuts+1)-i;j++) {
+ float percent= (float)j/(float)((numcuts+1)-i);
+
+ innerverts[i][((numcuts+1)-i)-j]= subdivide_edge_addvert(em, &temp, rad, beauty, 1-percent);
+ }
+ }
+
+ // Now fill the verts with happy little tris :)
+ for(i=0;i<=numcuts+1;i++) {
+ for(j=0;j<(numcuts+1)-i;j++) {
+ //We always do the first tri
+ hold = addfacelist(em, innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],NULL,NULL,NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ if(i != 0) { hold->e1->f2 |= EDGEINNER; }
+ if(j != 0) { hold->e2->f2 |= EDGEINNER; }
+ if(j+1 != (numcuts+1)-i) {hold->e3->f2 |= EDGEINNER;}
+
+ facecopy(em, efa,hold);
+ //if there are more to come, we do the 2nd
+ if(j+1 <= numcuts-i) {
+ hold = addfacelist(em, innerverts[i+1][j],innerverts[i+1][j+1],innerverts[i][j+1],NULL,NULL,NULL);
+ facecopy(em, efa,hold);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ }
+ }
+ }
+
+ // Clean up our dynamic multi-dim array
+ for(i=0;i<numcuts+2;i++) {
+ MEM_freeN(innerverts[i]);
+ }
+ MEM_freeN(innerverts);
+}
+
+//Next two fill types are for knife exact only and are provided to allow for knifing through vertices
+//This means there is no multicut!
+static void fill_quad_doublevert(EditMesh *em, EditFace *efa, int v1, int v2)
+{
+ EditFace *hold;
+ /*
+ Depending on which two vertices have been knifed through (v1 and v2), we
+ triangulate like the patterns below.
+ X-------| |-------X
+ | \ | | / |
+ | \ | | / |
+ | \ | | / |
+ --------X X--------
+ */
+
+ if(v1 == 1 && v2 == 3){
+ hold= addfacelist(em, efa->v1, efa->v2, efa->v3, 0, efa, NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(em, efa, hold);
+
+ hold= addfacelist(em, efa->v1, efa->v3, efa->v4, 0, efa, NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ hold->e1->f2 |= EDGEINNER;
+ facecopy(em, efa, hold);
+ }
+ else{
+ hold= addfacelist(em, efa->v1, efa->v2, efa->v4, 0, efa, NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(em, efa, hold);
+
+ hold= addfacelist(em, efa->v2, efa->v3, efa->v4, 0, efa, NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(em, efa, hold);
+ }
+}
+
+static void fill_quad_singlevert(EditMesh *em, EditFace *efa, struct GHash *gh)
+{
+ EditEdge *cedge=NULL;
+ EditVert *v[4], **verts;
+ EditFace *hold;
+ short start=0, end, left, right, vertsize;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
+ else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
+ else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
+ else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}
+
+ // Point verts to the array of new verts for cedge
+ verts = BLI_ghash_lookup(gh, cedge);
+ //This is the index size of the verts array
+ vertsize = 3;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0] != v[start]) {flipvertarray(verts,3);}
+ end = (start+1)%4;
+ left = (start+2)%4;
+ right = (start+3)%4;
+
+/*
+ We should have something like this now
+
+ end start
+ 2 1 0
+ |-----*-----|
+ | |
+ | |
+ | |
+ -------------
+ left right
+
+ where start,end,left, right are indexes of EditFace->v1, etc (stored in v)
+ and 0,1,2 are the indexes of the new verts stored in verts. We fill like
+ this, depending on whether its vertex 'left' or vertex 'right' thats
+ been knifed through...
+
+ |---*---| |---*---|
+ | / | | \ |
+ | / | | \ |
+ |/ | | \|
+ X-------- --------X
+*/
+
+ if(v[left]->f1){
+ //triangle is composed of cutvert, end and left
+ hold = addfacelist(em, verts[1],v[end],v[left],NULL, NULL,NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(em, efa, hold);
+
+ //quad is composed of cutvert, left, right and start
+ hold = addfacelist(em, verts[1],v[left],v[right],v[start], NULL, NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ hold->e4->f2 |= EDGENEW;
+ hold->e1->f2 |= EDGEINNER;
+ facecopy(em, efa, hold);
+ }
+ else if(v[right]->f1){
+ //triangle is composed of cutvert, right and start
+ hold = addfacelist(em, verts[1],v[right],v[start], NULL, NULL, NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ hold->e1->f2 |= EDGEINNER;
+ facecopy(em, efa, hold);
+ //quad is composed of cutvert, end, left, right
+ hold = addfacelist(em, verts[1],v[end], v[left], v[right], NULL, NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ hold->e4->f2 |= EDGENEW;
+ hold->e4->f2 |= EDGEINNER;
+ facecopy(em, efa, hold);
+ }
+
+}
+
+// This function takes an example edge, the current point to create and
+// the total # of points to create, then creates the point and return the
+// editvert pointer to it.
+static EditVert *subdivideedgenum(EditMesh *em, EditEdge *edge, int curpoint, int totpoint, float rad, int beauty)
+{
+ EditVert *ev;
+ float percent;
+
+ if (beauty & (B_PERCENTSUBD) && totpoint == 1)
+ //percent=(float)(edge->tmp.l)/32768.0f;
+ percent= edge->tmp.fp;
+ else
+ percent= (float)curpoint/(float)(totpoint+1);
+
+ ev= subdivide_edge_addvert(em, edge, rad, beauty, percent);
+ ev->f = edge->v1->f;
+
+ return ev;
+}
+
+void esubdivideflag(Object *obedit, EditMesh *em, int flag, float rad, int beauty, int numcuts, int seltype)
+{
+ EditFace *ef;
+ EditEdge *eed, *cedge, *sort[4];
+ EditVert *eve, **templist;
+ struct GHash *gh;
+ float length[4], v1mat[3], v2mat[3], v3mat[3], v4mat[3];
+ int i, j, edgecount, touchcount, facetype,hold;
+ ModifierData *md= obedit->modifiers.first;
+ int ctrl= 0; // XXX
+
+ //Set faces f1 to 0 cause we need it later
+ for(ef=em->faces.first;ef;ef = ef->next) ef->f1 = 0;
+ for(eve=em->verts.first; eve; eve=eve->next) {
+ if(!(beauty & B_KNIFE)) /* knife sets this flag for vertex cuts */
+ eve->f1 = 0;
+ eve->f2 = 0;
+ }
+
+ for (; md; md=md->next) {
+ if (md->type==eModifierType_Mirror) {
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ if(mmd->flag & MOD_MIR_CLIPPING) {
+ for (eve= em->verts.first; eve; eve= eve->next) {
+ eve->f2= 0;
+ switch(mmd->axis){
+ case 0:
+ if (fabs(eve->co[0]) < mmd->tolerance)
+ eve->f2 |= 1;
+ break;
+ case 1:
+ if (fabs(eve->co[1]) < mmd->tolerance)
+ eve->f2 |= 2;
+ break;
+ case 2:
+ if (fabs(eve->co[2]) < mmd->tolerance)
+ eve->f2 |= 4;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ //Flush vertex flags upward to the edges
+ for(eed = em->edges.first;eed;eed = eed->next) {
+ //if(eed->f & flag && eed->v1->f == eed->v2->f) {
+ // eed->f |= eed->v1->f;
+ // }
+ eed->f2 = 0;
+ if(eed->f & flag) {
+ eed->f2 |= EDGEOLD;
+ }
+ }
+
+ // We store an array of verts for each edge that is subdivided,
+ // we put this array as a value in a ghash which is keyed by the EditEdge*
+
+ // Now for beauty subdivide deselect edges based on length
+ if(beauty & B_BEAUTY) {
+ for(ef = em->faces.first;ef;ef = ef->next) {
+ if(!ef->v4) {
+ continue;
+ }
+ if(ef->f & SELECT) {
+ VECCOPY(v1mat, ef->v1->co);
+ VECCOPY(v2mat, ef->v2->co);
+ VECCOPY(v3mat, ef->v3->co);
+ VECCOPY(v4mat, ef->v4->co);
+ Mat4Mul3Vecfl(obedit->obmat, v1mat);
+ Mat4Mul3Vecfl(obedit->obmat, v2mat);
+ Mat4Mul3Vecfl(obedit->obmat, v3mat);
+ Mat4Mul3Vecfl(obedit->obmat, v4mat);
+
+ length[0] = VecLenf(v1mat, v2mat);
+ length[1] = VecLenf(v2mat, v3mat);
+ length[2] = VecLenf(v3mat, v4mat);
+ length[3] = VecLenf(v4mat, v1mat);
+ sort[0] = ef->e1;
+ sort[1] = ef->e2;
+ sort[2] = ef->e3;
+ sort[3] = ef->e4;
+
+
+ // Beauty Short Edges
+ if(beauty & B_BEAUTY_SHORT) {
+ for(j=0;j<2;j++) {
+ hold = -1;
+ for(i=0;i<4;i++) {
+ if(length[i] < 0) {
+ continue;
+ } else if(hold == -1) {
+ hold = i;
+ } else {
+ if(length[hold] < length[i]) {
+ hold = i;
+ }
+ }
+ }
+ if (hold > -1) {
+ sort[hold]->f &= ~SELECT;
+ sort[hold]->f2 |= EDGENEW;
+ length[hold] = -1;
+ }
+ }
+ }
+
+ // Beauty Long Edges
+ else {
+ for(j=0;j<2;j++) {
+ hold = -1;
+ for(i=0;i<4;i++) {
+ if(length[i] < 0) {
+ continue;
+ } else if(hold == -1) {
+ hold = i;
+ } else {
+ if(length[hold] > length[i]) {
+ hold = i;
+ }
+ }
+ }
+ if (hold > -1) {
+ sort[hold]->f &= ~SELECT;
+ sort[hold]->f2 |= EDGENEW;
+ length[hold] = -1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ // If we are knifing, We only need the selected edges that were cut, so deselect if it was not cut
+ if(beauty & B_KNIFE) {
+ for(eed= em->edges.first;eed;eed=eed->next) {
+ if( eed->tmp.fp == 0 ) {
+ EM_select_edge(eed,0);
+ }
+ }
+ }
+ // So for each edge, if it is selected, we allocate an array of size cuts+2
+ // so we can have a place for the v1, the new verts and v2
+ for(eed=em->edges.first;eed;eed = eed->next) {
+ if(eed->f & flag) {
+ templist = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"vertlist");
+ templist[0] = eed->v1;
+ for(i=0;i<numcuts;i++) {
+ // This function creates the new vert and returns it back
+ // to the array
+ templist[i+1] = subdivideedgenum(em, eed, i+1, numcuts, rad, beauty);
+ //while we are here, we can copy edge info from the original edge
+ cedge = addedgelist(em, templist[i],templist[i+1],eed);
+ // Also set the edge f2 to EDGENEW so that we can use this info later
+ cedge->f2 = EDGENEW;
+ }
+ templist[i+1] = eed->v2;
+ //Do the last edge too
+ cedge = addedgelist(em, templist[i],templist[i+1],eed);
+ cedge->f2 = EDGENEW;
+ // Now that the edge is subdivided, we can put its verts in the ghash
+ BLI_ghash_insert(gh, eed, templist);
+ }
+ }
+
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ // Now for each face in the mesh we need to figure out How many edges were cut
+ // and which filling method to use for that face
+ for(ef = em->faces.first;ef;ef = ef->next) {
+ edgecount = 0;
+ facetype = 3;
+ if(ef->e1->f & flag) {edgecount++;}
+ if(ef->e2->f & flag) {edgecount++;}
+ if(ef->e3->f & flag) {edgecount++;}
+ if(ef->v4) {
+ facetype = 4;
+ if(ef->e4->f & flag) {edgecount++;}
+ }
+ if(facetype == 4) {
+ switch(edgecount) {
+ case 0:
+ if(beauty & B_KNIFE && numcuts == 1){
+ /*Test for when knifing through two opposite verts but no edges*/
+ touchcount = 0;
+ if(ef->v1->f1) touchcount++;
+ if(ef->v2->f1) touchcount++;
+ if(ef->v3->f1) touchcount++;
+ if(ef->v4->f1) touchcount++;
+ if(touchcount == 2){
+ if(ef->v1->f1 && ef->v3->f1){
+ ef->f1 = SELECT;
+ fill_quad_doublevert(em, ef, 1, 3);
+ }
+ else if(ef->v2->f1 && ef->v4->f1){
+ ef->f1 = SELECT;
+ fill_quad_doublevert(em, ef, 2, 4);
+ }
+ }
+ }
+ break;
+
+ case 1:
+ if(beauty & B_KNIFE && numcuts == 1){
+ /*Test for when knifing through an edge and one vert*/
+ touchcount = 0;
+ if(ef->v1->f1) touchcount++;
+ if(ef->v2->f1) touchcount++;
+ if(ef->v3->f1) touchcount++;
+ if(ef->v4->f1) touchcount++;
+
+ if(touchcount == 1){
+ if( (ef->e1->f & flag && ( !ef->e1->v1->f1 && !ef->e1->v2->f1 )) ||
+ (ef->e2->f & flag && ( !ef->e2->v1->f1 && !ef->e2->v2->f1 )) ||
+ (ef->e3->f & flag && ( !ef->e3->v1->f1 && !ef->e3->v2->f1 )) ||
+ (ef->e4->f & flag && ( !ef->e4->v1->f1 && !ef->e4->v2->f1 )) ){
+
+ ef->f1 = SELECT;
+ fill_quad_singlevert(em, ef, gh);
+ }
+ else{
+ ef->f1 = SELECT;
+ fill_quad_single(em, ef, gh, numcuts, seltype);
+ }
+ }
+ else{
+ ef->f1 = SELECT;
+ fill_quad_single(em, ef, gh, numcuts, seltype);
+ }
+ }
+ else{
+ ef->f1 = SELECT;
+ fill_quad_single(em, ef, gh, numcuts, seltype);
+ }
+ break;
+ case 2: ef->f1 = SELECT;
+ // if there are 2, we check if edge 1 and 3 are either both on or off that way
+ // we can tell if the selected pair is Adjacent or Opposite of each other
+ if((ef->e1->f & flag && ef->e3->f & flag) ||
+ (ef->e2->f & flag && ef->e4->f & flag)) {
+ fill_quad_double_op(em, ef, gh, numcuts);
+ }else{
+ switch(0) { // XXX scene->toolsettings->cornertype) {
+ case 0: fill_quad_double_adj_path(em, ef, gh, numcuts); break;
+ case 1: fill_quad_double_adj_inner(em, ef, gh, numcuts); break;
+ case 2: fill_quad_double_adj_fan(em, ef, gh, numcuts); break;
+ }
+
+ }
+ break;
+ case 3: ef->f1 = SELECT;
+ fill_quad_triple(em, ef, gh, numcuts);
+ break;
+ case 4: ef->f1 = SELECT;
+ fill_quad_quadruple(em, ef, gh, numcuts, rad, beauty);
+ break;
+ }
+ } else {
+ switch(edgecount) {
+ case 0: break;
+ case 1: ef->f1 = SELECT;
+ fill_tri_single(em, ef, gh, numcuts, seltype);
+ break;
+ case 2: ef->f1 = SELECT;
+ fill_tri_double(em, ef, gh, numcuts);
+ break;
+ case 3: ef->f1 = SELECT;
+ fill_tri_triple(em, ef, gh, numcuts, rad, beauty);
+ break;
+ }
+ }
+ }
+
+ // Delete Old Edges and Faces
+ for(eed = em->edges.first;eed;eed = eed->next) {
+ if(BLI_ghash_haskey(gh,eed)) {
+ eed->f1 = SELECT;
+ } else {
+ eed->f1 = 0;
+ }
+ }
+ free_tagged_edges_faces(em, em->edges.first, em->faces.first);
+
+ if(seltype == SUBDIV_SELECT_ORIG && !ctrl) {
+ /* bugfix: vertex could get flagged as "not-selected"
+ // solution: clear flags before, not at the same time as setting SELECT flag -dg
+ */
+ for(eed = em->edges.first;eed;eed = eed->next) {
+ if(!(eed->f2 & EDGENEW || eed->f2 & EDGEOLD)) {
+ eed->f &= !flag;
+ EM_select_edge(eed,0);
+ }
+ }
+ for(eed = em->edges.first;eed;eed = eed->next) {
+ if(eed->f2 & EDGENEW || eed->f2 & EDGEOLD) {
+ eed->f |= flag;
+ EM_select_edge(eed,1);
+ }
+ }
+ } else if ((seltype == SUBDIV_SELECT_INNER || seltype == SUBDIV_SELECT_INNER_SEL)|| ctrl) {
+ for(eed = em->edges.first;eed;eed = eed->next) {
+ if(eed->f2 & EDGEINNER) {
+ eed->f |= flag;
+ EM_select_edge(eed,1);
+ if(eed->v1->f & EDGEINNER) eed->v1->f |= SELECT;
+ if(eed->v2->f & EDGEINNER) eed->v2->f |= SELECT;
+ }else{
+ eed->f &= !flag;
+ EM_select_edge(eed,0);
+ }
+ }
+ } else if(seltype == SUBDIV_SELECT_LOOPCUT){
+ for(eed = em->edges.first;eed;eed = eed->next) {
+ if(eed->f2 & DOUBLEOPFILL){
+ eed->f |= flag;
+ EM_select_edge(eed,1);
+ }else{
+ eed->f &= !flag;
+ EM_select_edge(eed,0);
+ }
+ }
+ }
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ for(eed = em->edges.first;eed;eed = eed->next) {
+ if(eed->f & SELECT) {
+ eed->v1->f |= SELECT;
+ eed->v2->f |= SELECT;
+ }
+ }
+ }
+
+ //fix hide flags for edges. First pass, hide edges of hidden faces
+ for(ef=em->faces.first; ef; ef=ef->next){
+ if(ef->h){
+ ef->e1->h |= 1;
+ ef->e2->h |= 1;
+ ef->e3->h |= 1;
+ if(ef->e4) ef->e4->h |= 1;
+ }
+ }
+ //second pass: unhide edges of visible faces adjacent to hidden faces
+ for(ef=em->faces.first; ef; ef=ef->next){
+ if(ef->h == 0){
+ ef->e1->h &= ~1;
+ ef->e2->h &= ~1;
+ ef->e3->h &= ~1;
+ if(ef->e4) ef->e4->h &= ~1;
+ }
+ }
+
+ // Free the ghash and call MEM_freeN on all the value entries to return
+ // that memory
+ BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
+
+ EM_selectmode_flush(em);
+ for(ef=em->faces.first;ef;ef = ef->next) {
+ if(ef->e4) {
+ if( (ef->e1->f & SELECT && ef->e2->f & SELECT) &&
+ (ef->e3->f & SELECT && ef->e4->f & SELECT) ) {
+ ef->f |= SELECT;
+ }
+ } else {
+ if( (ef->e1->f & SELECT && ef->e2->f & SELECT) && ef->e3->f & SELECT) {
+ ef->f |= SELECT;
+ }
+ }
+ }
+
+ recalc_editnormals(em);
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+}
+
+static int count_selected_edges(EditEdge *ed)
+{
+ int totedge = 0;
+ while(ed) {
+ ed->tmp.p = 0;
+ if( ed->f & SELECT ) totedge++;
+ ed= ed->next;
+ }
+ return totedge;
+}
+
+/* hurms, as if this makes code readable! It's pointerpointer hiding... (ton) */
+typedef EditFace *EVPtr;
+typedef EVPtr EVPTuple[2];
+
+/** builds EVPTuple array efaa of face tuples (in fact pointers to EditFaces)
+ sharing one edge.
+ arguments: selected edge list, face list.
+ Edges will also be tagged accordingly (see eed->f2) */
+
+static int collect_quadedges(EVPTuple *efaa, EditEdge *eed, EditFace *efa)
+{
+ EditEdge *e1, *e2, *e3;
+ EVPtr *evp;
+ int i = 0;
+
+ /* run through edges, if selected, set pointer edge-> facearray */
+ while(eed) {
+ eed->f2= 0;
+ eed->f1= 0;
+ if( eed->f & SELECT ) {
+ eed->tmp.p = (EditVert *) (&efaa[i]);
+ i++;
+ }
+ else eed->tmp.p = NULL;
+
+ eed= eed->next;
+ }
+
+
+ /* find edges pointing to 2 faces by procedure:
+
+ - run through faces and their edges, increase
+ face counter e->f1 for each face
+ */
+
+ while(efa) {
+ efa->f1= 0;
+ if(efa->v4==0 && (efa->f & SELECT)) { /* if selected triangle */
+ e1= efa->e1;
+ e2= efa->e2;
+ e3= efa->e3;
+ if(e1->f2<3 && e1->tmp.p) {
+ if(e1->f2<2) {
+ evp= (EVPtr *) e1->tmp.p;
+ evp[(int)e1->f2] = efa;
+ }
+ e1->f2+= 1;
+ }
+ if(e2->f2<3 && e2->tmp.p) {
+ if(e2->f2<2) {
+ evp= (EVPtr *) e2->tmp.p;
+ evp[(int)e2->f2]= efa;
+ }
+ e2->f2+= 1;
+ }
+ if(e3->f2<3 && e3->tmp.p) {
+ if(e3->f2<2) {
+ evp= (EVPtr *) e3->tmp.p;
+ evp[(int)e3->f2]= efa;
+ }
+ e3->f2+= 1;
+ }
+ }
+ else {
+ /* set to 3 to make sure these are not flipped or joined */
+ efa->e1->f2= 3;
+ efa->e2->f2= 3;
+ efa->e3->f2= 3;
+ if (efa->e4) efa->e4->f2= 3;
+ }
+
+ efa= efa->next;
+ }
+ return i;
+}
+
+
+/* returns vertices of two adjacent triangles forming a quad
+ - can be righthand or lefthand
+
+ 4-----3
+ |\ |
+ | \ 2 | <- efa1
+ | \ |
+ efa-> | 1 \ |
+ | \|
+ 1-----2
+
+*/
+#define VTEST(face, num, other) \
+ (face->v##num != other->v1 && face->v##num != other->v2 && face->v##num != other->v3)
+
+static void givequadverts(EditFace *efa, EditFace *efa1, EditVert **v1, EditVert **v2, EditVert **v3, EditVert **v4, int *vindex)
+{
+ if VTEST(efa, 1, efa1) {
+ *v1= efa->v1;
+ *v2= efa->v2;
+ vindex[0]= 0;
+ vindex[1]= 1;
+ }
+ else if VTEST(efa, 2, efa1) {
+ *v1= efa->v2;
+ *v2= efa->v3;
+ vindex[0]= 1;
+ vindex[1]= 2;
+ }
+ else if VTEST(efa, 3, efa1) {
+ *v1= efa->v3;
+ *v2= efa->v1;
+ vindex[0]= 2;
+ vindex[1]= 0;
+ }
+
+ if VTEST(efa1, 1, efa) {
+ *v3= efa1->v1;
+ *v4= efa1->v2;
+ vindex[2]= 0;
+ vindex[3]= 1;
+ }
+ else if VTEST(efa1, 2, efa) {
+ *v3= efa1->v2;
+ *v4= efa1->v3;
+ vindex[2]= 1;
+ vindex[3]= 2;
+ }
+ else if VTEST(efa1, 3, efa) {
+ *v3= efa1->v3;
+ *v4= efa1->v1;
+ vindex[2]= 2;
+ vindex[3]= 0;
+ }
+ else
+ *v3= *v4= NULL;
+}
+
+/* Helper functions for edge/quad edit features*/
+static void untag_edges(EditFace *f)
+{
+ f->e1->f1 = 0;
+ f->e2->f1 = 0;
+ f->e3->f1 = 0;
+ if (f->e4) f->e4->f1 = 0;
+}
+
+/** remove and free list of tagged edges and faces */
+static void free_tagged_edges_faces(EditMesh *em, EditEdge *eed, EditFace *efa)
+{
+ EditEdge *nexted;
+ EditFace *nextvl;
+
+ while(efa) {
+ nextvl= efa->next;
+ if(efa->f1) {
+ BLI_remlink(&em->faces, efa);
+ free_editface(em, efa);
+ }
+ else
+ /* avoid deleting edges that are still in use */
+ untag_edges(efa);
+ efa= nextvl;
+ }
+
+ while(eed) {
+ nexted= eed->next;
+ if(eed->f1) {
+ remedge(em, eed);
+ free_editedge(em, eed);
+ }
+ eed= nexted;
+ }
+}
+
+
+/* ******************** BEGIN TRIANGLE TO QUAD ************************************* */
+static float measure_facepair(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, float limit)
+{
+
+ /*gives a 'weight' to a pair of triangles that join an edge to decide how good a join they would make*/
+ /*Note: this is more complicated than it needs to be and should be cleaned up...*/
+ float measure = 0.0, noA1[3], noA2[3], noB1[3], noB2[3], normalADiff, normalBDiff,
+ edgeVec1[3], edgeVec2[3], edgeVec3[3], edgeVec4[3], diff,
+ minarea, maxarea, areaA, areaB;
+
+ /*First Test: Normal difference*/
+ CalcNormFloat(v1->co, v2->co, v3->co, noA1);
+ CalcNormFloat(v1->co, v3->co, v4->co, noA2);
+
+ if(noA1[0] == noA2[0] && noA1[1] == noA2[1] && noA1[2] == noA2[2]) normalADiff = 0.0;
+ else normalADiff = VecAngle2(noA1, noA2);
+ //if(!normalADiff) normalADiff = 179;
+ CalcNormFloat(v2->co, v3->co, v4->co, noB1);
+ CalcNormFloat(v4->co, v1->co, v2->co, noB2);
+
+ if(noB1[0] == noB2[0] && noB1[1] == noB2[1] && noB1[2] == noB2[2]) normalBDiff = 0.0;
+ else normalBDiff = VecAngle2(noB1, noB2);
+ //if(!normalBDiff) normalBDiff = 179;
+
+ measure += (normalADiff/360) + (normalBDiff/360);
+ if(measure > limit) return measure;
+
+ /*Second test: Colinearity*/
+ VecSubf(edgeVec1, v1->co, v2->co);
+ VecSubf(edgeVec2, v2->co, v3->co);
+ VecSubf(edgeVec3, v3->co, v4->co);
+ VecSubf(edgeVec4, v4->co, v1->co);
+
+ diff = 0.0;
+
+ diff = (
+ fabs(VecAngle2(edgeVec1, edgeVec2) - 90) +
+ fabs(VecAngle2(edgeVec2, edgeVec3) - 90) +
+ fabs(VecAngle2(edgeVec3, edgeVec4) - 90) +
+ fabs(VecAngle2(edgeVec4, edgeVec1) - 90)) / 360;
+ if(!diff) return 0.0;
+
+ measure += diff;
+ if(measure > limit) return measure;
+
+ /*Third test: Concavity*/
+ areaA = AreaT3Dfl(v1->co, v2->co, v3->co) + AreaT3Dfl(v1->co, v3->co, v4->co);
+ areaB = AreaT3Dfl(v2->co, v3->co, v4->co) + AreaT3Dfl(v4->co, v1->co, v2->co);
+
+ if(areaA <= areaB) minarea = areaA;
+ else minarea = areaB;
+
+ if(areaA >= areaB) maxarea = areaA;
+ else maxarea = areaB;
+
+ if(!maxarea) measure += 1;
+ else measure += (1 - (minarea / maxarea));
+
+ return measure;
+}
+
+#define T2QUV_LIMIT 0.005
+#define T2QCOL_LIMIT 3
+static int compareFaceAttribs(EditMesh *em, EditFace *f1, EditFace *f2, EditEdge *eed)
+{
+ /*Test to see if the per-face attributes for the joining edge match within limit*/
+ MTFace *tf1, *tf2;
+ unsigned int *col1, *col2;
+ short i,attrok=0, flag = 0, /* XXX scene->toolsettings->editbutflag,*/ fe1[2], fe2[2];
+
+ tf1 = CustomData_em_get(&em->fdata, f1->data, CD_MTFACE);
+ tf2 = CustomData_em_get(&em->fdata, f2->data, CD_MTFACE);
+
+ col1 = CustomData_em_get(&em->fdata, f1->data, CD_MCOL);
+ col2 = CustomData_em_get(&em->fdata, f2->data, CD_MCOL);
+
+ /*store indices for faceedges*/
+ f1->v1->f1 = 0;
+ f1->v2->f1 = 1;
+ f1->v3->f1 = 2;
+
+ fe1[0] = eed->v1->f1;
+ fe1[1] = eed->v2->f1;
+
+ f2->v1->f1 = 0;
+ f2->v2->f1 = 1;
+ f2->v3->f1 = 2;
+
+ fe2[0] = eed->v1->f1;
+ fe2[1] = eed->v2->f1;
+
+ /*compare faceedges for each face attribute. Additional per face attributes can be added later*/
+ /*do UVs*/
+ if(flag & B_JOINTRIA_UV){
+
+ if(tf1 == NULL || tf2 == NULL) attrok |= B_JOINTRIA_UV;
+ else if(tf1->tpage != tf2->tpage); /*do nothing*/
+ else{
+ for(i = 0; i < 2; i++){
+ if(tf1->uv[fe1[i]][0] + T2QUV_LIMIT > tf2->uv[fe2[i]][0] && tf1->uv[fe1[i]][0] - T2QUV_LIMIT < tf2->uv[fe2[i]][0] &&
+ tf1->uv[fe1[i]][1] + T2QUV_LIMIT > tf2->uv[fe2[i]][1] && tf1->uv[fe1[i]][1] - T2QUV_LIMIT < tf2->uv[fe2[i]][1]) attrok |= B_JOINTRIA_UV;
+ }
+ }
+ }
+
+ /*do VCOLs*/
+ if(flag & B_JOINTRIA_VCOL){
+ if(!col1 || !col2) attrok |= B_JOINTRIA_VCOL;
+ else{
+ char *f1vcol, *f2vcol;
+ for(i = 0; i < 2; i++){
+ f1vcol = (char *)&(col1[fe1[i]]);
+ f2vcol = (char *)&(col2[fe2[i]]);
+
+ /*compare f1vcol with f2vcol*/
+ if( f1vcol[1] + T2QCOL_LIMIT > f2vcol[1] && f1vcol[1] - T2QCOL_LIMIT < f2vcol[1] &&
+ f1vcol[2] + T2QCOL_LIMIT > f2vcol[2] && f1vcol[2] - T2QCOL_LIMIT < f2vcol[2] &&
+ f1vcol[3] + T2QCOL_LIMIT > f2vcol[3] && f1vcol[3] - T2QCOL_LIMIT < f2vcol[3]) attrok |= B_JOINTRIA_VCOL;
+ }
+ }
+ }
+
+ if( ((attrok & B_JOINTRIA_UV) == (flag & B_JOINTRIA_UV)) && ((attrok & B_JOINTRIA_VCOL) == (flag & B_JOINTRIA_VCOL)) ) return 1;
+ return 0;
+}
+
+static int fplcmp(const void *v1, const void *v2)
+{
+ const EditEdge *e1= *((EditEdge**)v1), *e2=*((EditEdge**)v2);
+
+ if( e1->crease > e2->crease) return 1;
+ else if( e1->crease < e2->crease) return -1;
+
+ return 0;
+}
+
+/*Bitflags for edges.*/
+#define T2QDELETE 1
+#define T2QCOMPLEX 2
+#define T2QJOIN 4
+void join_triangles(EditMesh *em)
+{
+ EditVert *v1, *v2, *v3, *v4, *eve;
+ EditEdge *eed, **edsortblock = NULL, **edb = NULL;
+ EditFace *efa;
+ EVPTuple *efaar = NULL;
+ EVPtr *efaa = NULL;
+ float *creases = NULL;
+ float measure; /*Used to set tolerance*/
+ float limit = 0.0f; // XXX scene->toolsettings->jointrilimit;
+ int i, ok, totedge=0, totseledge=0, complexedges, vindex[4];
+
+ /*if we take a long time on very dense meshes we want waitcursor to display*/
+ waitcursor(1);
+
+ totseledge = count_selected_edges(em->edges.first);
+ if(totseledge==0) return;
+
+ /*abusing crease value to store weights for edge pairs. Nasty*/
+ for(eed=em->edges.first; eed; eed=eed->next) totedge++;
+ if(totedge) creases = MEM_callocN(sizeof(float) * totedge, "Join Triangles Crease Array");
+ for(eed=em->edges.first, i = 0; eed; eed=eed->next, i++){
+ creases[i] = eed->crease;
+ eed->crease = 0.0;
+ }
+
+ /*clear temp flags*/
+ for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = eve->f2 = 0;
+ for(eed=em->edges.first; eed; eed=eed->next) eed->f2 = eed->f1 = 0;
+ for(efa=em->faces.first; efa; efa=efa->next) efa->f1 = efa->tmp.l = 0;
+
+ /*For every selected 2 manifold edge, create pointers to its two faces.*/
+ efaar= (EVPTuple *) MEM_callocN(totseledge * sizeof(EVPTuple), "Tri2Quad");
+ ok = collect_quadedges(efaar, em->edges.first, em->faces.first);
+ complexedges = 0;
+
+ if(ok){
+
+
+ /*clear tmp.l flag and store number of faces that are selected and coincident to current face here.*/
+ for(eed=em->edges.first; eed; eed=eed->next){
+ /* eed->f2 is 2 only if this edge is part of exactly two
+ triangles, and both are selected, and it has EVPTuple assigned */
+ if(eed->f2 == 2){
+ efaa= (EVPtr *) eed->tmp.p;
+ efaa[0]->tmp.l++;
+ efaa[1]->tmp.l++;
+ }
+ }
+
+ for(eed=em->edges.first; eed; eed=eed->next){
+ if(eed->f2 == 2){
+ efaa= (EVPtr *) eed->tmp.p;
+ v1 = v2 = v3 = v4 = NULL;
+ givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
+ if(v1 && v2 && v3 && v4){
+ /*test if simple island first. This mimics 2.42 behaviour and the tests are less restrictive.*/
+ if(efaa[0]->tmp.l == 1 && efaa[1]->tmp.l == 1){
+ eed->f1 |= T2QJOIN;
+ efaa[0]->f1 = 1; //mark for join
+ efaa[1]->f1 = 1; //mark for join
+ }
+ else{
+
+ /* The face pair is part of a 'complex' island, so the rules for dealing with it are more involved.
+ Depending on what options the user has chosen, this face pair can be 'thrown out' based upon the following criteria:
+
+ 1: the two faces do not share the same material
+ 2: the edge joining the two faces is marked as sharp.
+ 3: the two faces UV's do not make a good match
+ 4: the two faces Vertex colors do not make a good match
+
+ If the face pair passes all the applicable tests, it is then given a 'weight' with the measure_facepair() function.
+ This measures things like concavity, colinearity ect. If this weight is below the threshold set by the user
+ the edge joining them is marked as being 'complex' and will be compared against other possible pairs which contain one of the
+ same faces in the current pair later.
+
+ This technique is based upon an algorithm that Campbell Barton developed for his Tri2Quad script that was previously part of
+ the python scripts bundled with Blender releases.
+ */
+
+// XXX if(scene->toolsettings->editbutflag & B_JOINTRIA_SHARP && eed->sharp); /*do nothing*/
+// else if(scene->toolsettings->editbutflag & B_JOINTRIA_MAT && efaa[0]->mat_nr != efaa[1]->mat_nr); /*do nothing*/
+// else if(((scene->toolsettings->editbutflag & B_JOINTRIA_UV) || (scene->toolsettings->editbutflag & B_JOINTRIA_VCOL)) &&
+ compareFaceAttribs(em, efaa[0], efaa[1], eed); // XXX == 0); /*do nothing*/
+// else{
+ measure = measure_facepair(v1, v2, v3, v4, limit);
+ if(measure < limit){
+ complexedges++;
+ eed->f1 |= T2QCOMPLEX;
+ eed->crease = measure; /*we dont mark edges for join yet*/
+ }
+// }
+ }
+ }
+ }
+ }
+
+ /*Quicksort the complex edges according to their weighting*/
+ if(complexedges){
+ edsortblock = edb = MEM_callocN(sizeof(EditEdge*) * complexedges, "Face Pairs quicksort Array");
+ for(eed = em->edges.first; eed; eed=eed->next){
+ if(eed->f1 & T2QCOMPLEX){
+ *edb = eed;
+ edb++;
+ }
+ }
+ qsort(edsortblock, complexedges, sizeof(EditEdge*), fplcmp);
+ /*now go through and mark the edges who get the highest weighting*/
+ for(edb=edsortblock, i=0; i < complexedges; edb++, i++){
+ efaa = (EVPtr *)((*edb)->tmp.p); /*suspect!*/
+ if( !efaa[0]->f1 && !efaa[1]->f1){
+ efaa[0]->f1 = 1; //mark for join
+ efaa[1]->f1 = 1; //mark for join
+ (*edb)->f1 |= T2QJOIN;
+ }
+ }
+ }
+
+ /*finally go through all edges marked for join (simple and complex) and create new faces*/
+ for(eed=em->edges.first; eed; eed=eed->next){
+ if(eed->f1 & T2QJOIN){
+ efaa= (EVPtr *)eed->tmp.p;
+ v1 = v2 = v3 = v4 = NULL;
+ givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
+ if((v1 && v2 && v3 && v4) && (exist_face(em, v1, v2, v3, v4)==0)){ /*exist_face is very slow! Needs to be adressed.*/
+ /*flag for delete*/
+ eed->f1 |= T2QDELETE;
+ /*create new quad and select*/
+ efa = EM_face_from_faces(em, efaa[0], efaa[1], vindex[0], vindex[1], 4+vindex[2], 4+vindex[3]);
+ EM_select_face(efa,1);
+ }
+ else{
+ efaa[0]->f1 = 0;
+ efaa[1]->f1 = 0;
+ }
+ }
+ }
+ }
+
+ /*free data and cleanup*/
+ if(creases){
+ for(eed=em->edges.first, i = 0; eed; eed=eed->next, i++) eed->crease = creases[i];
+ MEM_freeN(creases);
+ }
+ for(eed=em->edges.first; eed; eed=eed->next){
+ if(eed->f1 & T2QDELETE) eed->f1 = 1;
+ else eed->f1 = 0;
+ }
+ free_tagged_edges_faces(em, em->edges.first, em->faces.first);
+ if(efaar) MEM_freeN(efaar);
+ if(edsortblock) MEM_freeN(edsortblock);
+
+ EM_selectmode_flush(em);
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+}
+/* ******************** END TRIANGLE TO QUAD ************************************* */
+
+#define FACE_MARKCLEAR(f) (f->f1 = 1)
+
+/* quick hack, basically a copy of beauty_fill */
+void edge_flip(EditMesh *em)
+{
+ EditVert *v1, *v2, *v3, *v4;
+ EditEdge *eed, *nexted;
+ EditFace *efa, *w;
+ //void **efaar, **efaa;
+ EVPTuple *efaar;
+ EVPtr *efaa;
+ int totedge, ok, vindex[4];
+
+ /* - all selected edges with two faces
+ * - find the faces: store them in edges (using datablock)
+ * - per edge: - test convex
+ * - test edge: flip?
+ - if true: remedge, addedge, all edges at the edge get new face pointers
+ */
+
+ EM_selectmode_flush(em); // makes sure in selectmode 'face' the edges of selected faces are selected too
+
+ totedge = count_selected_edges(em->edges.first);
+ if(totedge==0) return;
+
+ /* temporary array for : edge -> face[1], face[2] */
+ efaar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "edgeflip");
+
+ ok = collect_quadedges(efaar, em->edges.first, em->faces.first);
+
+ eed= em->edges.first;
+ while(eed) {
+ nexted= eed->next;
+
+ if(eed->f2==2) { /* points to 2 faces */
+
+ efaa= (EVPtr *) eed->tmp.p;
+
+ /* don't do it if flagged */
+
+ ok= 1;
+ efa= efaa[0];
+ if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
+ efa= efaa[1];
+ if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
+
+ if(ok) {
+ /* test convex */
+ givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
+
+/*
+ 4-----3 4-----3
+ |\ | | /|
+ | \ 1 | | 1 / |
+ | \ | -> | / |
+ | 0 \ | | / 0 |
+ | \| |/ |
+ 1-----2 1-----2
+*/
+ /* make new faces */
+ if (v1 && v2 && v3) {
+ if( convex(v1->co, v2->co, v3->co, v4->co) ) {
+ if(exist_face(em, v1, v2, v3, v4)==0) {
+ /* outch this may break seams */
+ w= EM_face_from_faces(em, efaa[0], efaa[1], vindex[0],
+ vindex[1], 4+vindex[2], -1);
+
+ EM_select_face(w, 1);
+
+ /* outch this may break seams */
+ w= EM_face_from_faces(em, efaa[0], efaa[1], vindex[0],
+ 4+vindex[2], 4+vindex[3], -1);
+
+ EM_select_face(w, 1);
+ }
+ /* tag as to-be-removed */
+ FACE_MARKCLEAR(efaa[1]);
+ FACE_MARKCLEAR(efaa[0]);
+ eed->f1 = 1;
+
+ } /* endif test convex */
+ }
+ }
+ }
+ eed= nexted;
+ }
+
+ /* clear tagged edges and faces: */
+ free_tagged_edges_faces(em, em->edges.first, em->faces.first);
+
+ MEM_freeN(efaar);
+
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+}
+
+static void edge_rotate(EditMesh *em, wmOperator *op, EditEdge *eed,int dir)
+{
+ EditVert **verts[2];
+ EditFace *face[2], *efa, *newFace[2];
+ EditEdge **edges[2], **hiddenedges, *srchedge;
+ int facecount, p1, p2, p3, p4, fac1, fac2, i, j;
+ int numhidden, numshared, p[2][4];
+
+ /* check to make sure that the edge is only part of 2 faces */
+ facecount = 0;
+ for(efa = em->faces.first;efa;efa = efa->next) {
+ if((efa->e1 == eed || efa->e2 == eed) || (efa->e3 == eed || efa->e4 == eed)) {
+ if(facecount >= 2) {
+ /* more than two faces with this edge */
+ return;
+ }
+ else {
+ face[facecount] = efa;
+ facecount++;
+ }
+ }
+ }
+
+ if(facecount < 2)
+ return;
+
+ /* how many edges does each face have */
+ if(face[0]->e4) fac1= 4;
+ else fac1= 3;
+
+ if(face[1]->e4) fac2= 4;
+ else fac2= 3;
+
+ /* make a handy array for verts and edges */
+ verts[0]= &face[0]->v1;
+ edges[0]= &face[0]->e1;
+ verts[1]= &face[1]->v1;
+ edges[1]= &face[1]->e1;
+
+ /* we don't want to rotate edges between faces that share more than one edge */
+ numshared= 0;
+ for(i=0; i<fac1; i++)
+ for(j=0; j<fac2; j++)
+ if (edges[0][i] == edges[1][j])
+ numshared++;
+
+ if(numshared > 1)
+ return;
+
+ /* we want to construct an array of vertex indicis in both faces, starting at
+ the last vertex of the edge being rotated.
+ - first we find the two vertices that lie on the rotating edge
+ - then we make sure they are ordered according to the face vertex order
+ - and then we construct the array */
+ p1= p2= p3= p4= 0;
+
+ for(i=0; i<4; i++) {
+ if(eed->v1 == verts[0][i]) p1 = i;
+ if(eed->v2 == verts[0][i]) p2 = i;
+ if(eed->v1 == verts[1][i]) p3 = i;
+ if(eed->v2 == verts[1][i]) p4 = i;
+ }
+
+ if((p1+1)%fac1 == p2)
+ SWAP(int, p1, p2);
+ if((p3+1)%fac2 == p4)
+ SWAP(int, p3, p4);
+
+ for (i = 0; i < 4; i++) {
+ p[0][i]= (p1 + i)%fac1;
+ p[1][i]= (p3 + i)%fac2;
+ }
+
+ /* create an Array of the Edges who have h set prior to rotate */
+ numhidden = 0;
+ for(srchedge = em->edges.first;srchedge;srchedge = srchedge->next)
+ if(srchedge->h && ((srchedge->v1->f & SELECT) || (srchedge->v2->f & SELECT)))
+ numhidden++;
+
+ hiddenedges = MEM_mallocN(sizeof(EditVert*)*numhidden+1, "RotateEdgeHiddenVerts");
+ if(!hiddenedges) {
+ BKE_report(op->reports, RPT_ERROR, "Memory allocation failed");
+ return;
+ }
+
+ numhidden = 0;
+ for(srchedge=em->edges.first; srchedge; srchedge=srchedge->next)
+ if(srchedge->h && (srchedge->v1->f & SELECT || srchedge->v2->f & SELECT))
+ hiddenedges[numhidden++] = srchedge;
+
+ /* create the 2 new faces */
+ if(fac1 == 3 && fac2 == 3) {
+ /* no need of reverse setup */
+
+ newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1);
+ newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1);
+ }
+ else if(fac1 == 4 && fac2 == 3) {
+ if(dir == 1) {
+ newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]);
+ newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1);
+ } else if (dir == 2) {
+ newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][2], 4+p[1][1], p[0][0], p[0][1]);
+ newFace[1]= EM_face_from_faces(em, face[1], face[0], 4+p[0][2], p[1][0], p[1][1], -1);
+
+ verts[0][p[0][2]]->f |= SELECT;
+ verts[1][p[1][1]]->f |= SELECT;
+ }
+ }
+ else if(fac1 == 3 && fac2 == 4) {
+ if(dir == 1) {
+ newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1);
+ newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]);
+ } else if (dir == 2) {
+ newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][0], p[0][1], 4+p[1][2], -1);
+ newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], 4+p[0][1], 4+p[0][2]);
+
+ verts[0][p[0][1]]->f |= SELECT;
+ verts[1][p[1][2]]->f |= SELECT;
+ }
+
+ }
+ else if(fac1 == 4 && fac2 == 4) {
+ if(dir == 1) {
+ newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]);
+ newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]);
+ } else if (dir == 2) {
+ newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][2], p[0][3], 4+p[1][1], 4+p[1][2]);
+ newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][2], p[1][3], 4+p[0][1], 4+p[0][2]);
+
+ verts[0][p[0][2]]->f |= SELECT;
+ verts[1][p[1][2]]->f |= SELECT;
+ }
+ }
+ else
+ return; /* This should never happen */
+
+ if(dir == 1 || (fac1 == 3 && fac2 == 3)) {
+ verts[0][p[0][1]]->f |= SELECT;
+ verts[1][p[1][1]]->f |= SELECT;
+ }
+
+ /* copy old edge's flags to new center edge*/
+ for(srchedge=em->edges.first;srchedge;srchedge=srchedge->next) {
+ if((srchedge->v1->f & SELECT) && (srchedge->v2->f & SELECT)) {
+ srchedge->f = eed->f;
+ srchedge->h = eed->h;
+ srchedge->dir = eed->dir;
+ srchedge->seam = eed->seam;
+ srchedge->crease = eed->crease;
+ srchedge->bweight = eed->bweight;
+ }
+ }
+
+ /* resetting hidden flag */
+ for(numhidden--; numhidden>=0; numhidden--)
+ hiddenedges[numhidden]->h= 1;
+
+ /* check for orhphan edges */
+ for(srchedge=em->edges.first; srchedge; srchedge=srchedge->next)
+ srchedge->f1= -1;
+
+ /* cleanup */
+ MEM_freeN(hiddenedges);
+
+ /* get rid of the old edge and faces*/
+ remedge(em, eed);
+ free_editedge(em, eed);
+ BLI_remlink(&em->faces, face[0]);
+ free_editface(em, face[0]);
+ BLI_remlink(&em->faces, face[1]);
+ free_editface(em, face[1]);
+}
+
+// XXX ton please check
+/* only accepts 1 selected edge, or 2 selected faces */
+static int edge_rotate_selected(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ int dir = RNA_int_get(op->ptr,"dir"); // dir == 2 when clockwise and ==1 for counter CW.
+ EditEdge *eed;
+ EditFace *efa;
+ short edgeCount = 0;
+
+ /*clear new flag for new edges, count selected edges */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->f1= 0;
+ eed->f2 &= ~2;
+ if(eed->f & SELECT) edgeCount++;
+ }
+
+ if(edgeCount>1) {
+ /* more selected edges, check faces */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->e4) efa->e4->f1++;
+ }
+ }
+ edgeCount= 0;
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f1==2) edgeCount++;
+ }
+ if(edgeCount==1) {
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f1==2) {
+ edge_rotate(em, op, eed,dir);
+ break;
+ }
+ }
+ }
+ else
+ {
+ BKE_report(op->reports, RPT_ERROR, "Select one edge or two adjacent faces");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else if(edgeCount==1) {
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f & SELECT) {
+ EM_select_edge(eed, 0);
+ edge_rotate(em, op, eed,dir);
+ break;
+ }
+ }
+ }
+ else
+ {
+ BKE_report(op->reports, RPT_ERROR, "Select one edge or two adjacent faces");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+
+ /* flush selected vertices (again) to edges/faces */
+ EM_select_flush(em);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+
+}
+
+void MESH_OT_edge_rotate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Rotate Selected Edge";
+ ot->idname= "MESH_OT_edge_rotate";
+
+ /* api callbacks */
+ ot->exec= edge_rotate_selected;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "dir", 1, 1, 2, "Direction", "Clockwise and Counter Clockwise", 1, 2);
+}
+
+
+/******************* BEVEL CODE STARTS HERE ********************/
+
+ /* XXX old bevel not ported yet */
+
+void bevel_menu(EditMesh *em)
+{
+ BME_Mesh *bm;
+ BME_TransData_Head *td;
+// TransInfo *t;
+ int options, res, gbm_free = 0;
+
+// t = BIF_GetTransInfo();
+ if (!G.editBMesh) {
+ G.editBMesh = MEM_callocN(sizeof(*(G.editBMesh)),"bevel_menu() G.editBMesh");
+ gbm_free = 1;
+ }
+
+ G.editBMesh->options = BME_BEVEL_RUNNING | BME_BEVEL_SELECT;
+ G.editBMesh->res = 1;
+
+ while(G.editBMesh->options & BME_BEVEL_RUNNING) {
+ options = G.editBMesh->options;
+ res = G.editBMesh->res;
+ bm = BME_editmesh_to_bmesh(em);
+// BIF_undo_push("Pre-Bevel");
+ free_editMesh(em);
+ BME_bevel(bm,0.1f,res,options,0,0,&td);
+ BME_bmesh_to_editmesh(bm, td, em);
+ EM_selectmode_flush(em);
+ G.editBMesh->bm = bm;
+ G.editBMesh->td = td;
+// initTransform(TFM_BEVEL,CTX_BMESH);
+// Transform();
+ BME_free_transdata(td);
+ BME_free_mesh(bm);
+// if (t->state != TRANS_CONFIRM) {
+// BIF_undo();
+// }
+ if (options == G.editBMesh->options) {
+ G.editBMesh->options &= ~BME_BEVEL_RUNNING;
+ }
+ }
+
+ if (gbm_free) {
+ MEM_freeN(G.editBMesh);
+ G.editBMesh = NULL;
+ }
+}
+
+
+/* *********** END BEVEL *********/
+
+/* this utility function checks to see if 2 edit edges share a face,
+returns 1 if they do
+returns 0 if they do not, or if the function is passed the same edge 2 times
+*/
+short sharesFace(EditMesh *em, EditEdge* e1, EditEdge* e2)
+{
+ EditFace *search=NULL;
+
+ search = em->faces.first;
+ if (e1 == e2){
+ return 0 ;
+ }
+ while(search){
+ if(
+ ((search->e1 == e1 || search->e2 == e1) || (search->e3 == e1 || search->e4 == e1)) &&
+ ((search->e1 == e2 || search->e2 == e2) || (search->e3 == e2 || search->e4 == e2))
+ ) {
+ return 1;
+ }
+ search = search->next;
+ }
+ return 0;
+}
+
+
+typedef struct SlideUv {
+ float origuv[2];
+ float *uv_up, *uv_down;
+ //float *fuv[4];
+ LinkNode *fuv_list;
+} SlideUv;
+
+typedef struct SlideVert {
+ EditEdge *up,*down;
+ EditVert origvert;
+} SlideVert;
+
+int EdgeSlide(EditMesh *em, wmOperator *op, short immediate, float imperc)
+{
+ return 0;
+/* XXX REFACTOR - #if 0'd for now, otherwise can't make 64bit windows builds on 64bit machine */
+#if 0
+useless:
+ goto useless // because it doesn't do anything right now
+
+// NumInput num; XXX
+ Mesh *me= NULL; // XXX
+ EditFace *efa;
+ EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL;
+ EditVert *ev, *nearest;
+ LinkNode *edgelist = NULL, *vertlist=NULL, *look;
+ GHash *vertgh;
+
+ SlideVert *tempsv;
+ float perc = 0, percp = 0,vertdist; // XXX, projectMat[4][4], viewMat[4][4];
+ float shiftlabda= 0.0f,len = 0.0f;
+ int i = 0,j, numsel, numadded=0, timesthrough = 0, vertsel=0, prop=1, cancel = 0,flip=0;
+ int wasshift = 0;
+
+ /* UV correction vars */
+ GHash **uvarray= NULL;
+ int uvlay_tot= CustomData_number_of_layers(&em->fdata, CD_MTFACE);
+ int uvlay_idx;
+ SlideUv *slideuvs=NULL, *suv=NULL, *suv_last=NULL;
+ float uv_tmp[2];
+ LinkNode *fuv_link;
+
+ short event, draw=1;
+ short mval[2], mvalo[2];
+ char str[128];
+ float labda = 0.0f;
+
+// initNumInput(&num);
+
+// view3d_get_object_project_mat(curarea, obedit, projectMat, viewMat);
+
+ mvalo[0] = -1; mvalo[1] = -1;
+ numsel =0;
+
+ // Get number of selected edges and clear some flags
+ for(eed=em->edges.first;eed;eed=eed->next) {
+ eed->f1 = 0;
+ eed->f2 = 0;
+ if(eed->f & SELECT) numsel++;
+ }
+
+ for(ev=em->verts.first;ev;ev=ev->next) {
+ ev->f1 = 0;
+ }
+
+ //Make sure each edge only has 2 faces
+ // make sure loop doesn't cross face
+ for(efa=em->faces.first;efa;efa=efa->next) {
+ int ct = 0;
+ if(efa->e1->f & SELECT) {
+ ct++;
+ efa->e1->f1++;
+ if(efa->e1->f1 > 2) {
+ BKE_report(op->reports, RPT_ERROR, "3+ face edge");
+ return 0;
+ }
+ }
+ if(efa->e2->f & SELECT) {
+ ct++;
+ efa->e2->f1++;
+ if(efa->e2->f1 > 2) {
+ BKE_report(op->reports, RPT_ERROR, "3+ face edge");
+ return 0;
+ }
+ }
+ if(efa->e3->f & SELECT) {
+ ct++;
+ efa->e3->f1++;
+ if(efa->e3->f1 > 2) {
+ BKE_report(op->reports, RPT_ERROR, "3+ face edge");
+ return 0;
+ }
+ }
+ if(efa->e4 && efa->e4->f & SELECT) {
+ ct++;
+ efa->e4->f1++;
+ if(efa->e4->f1 > 2) {
+ BKE_report(op->reports, RPT_ERROR, "3+ face edge");
+ return 0;
+ }
+ }
+ // Make sure loop is not 2 edges of same face
+ if(ct > 1) {
+ BKE_report(op->reports, RPT_ERROR, "Loop crosses itself");
+ return 0;
+ }
+ }
+ // Get # of selected verts
+ for(ev=em->verts.first;ev;ev=ev->next) {
+ if(ev->f & SELECT) vertsel++;
+ }
+
+ // Test for multiple segments
+ if(vertsel > numsel+1) {
+ BKE_report(op->reports, RPT_ERROR, "Please choose a single edge loop");
+ return 0;
+ }
+
+ // Get the edgeloop in order - mark f1 with SELECT once added
+ for(eed=em->edges.first;eed;eed=eed->next) {
+ if((eed->f & SELECT) && !(eed->f1 & SELECT)) {
+ // If this is the first edge added, just put it in
+ if(!edgelist) {
+ BLI_linklist_prepend(&edgelist,eed);
+ numadded++;
+ first = eed;
+ last = eed;
+ eed->f1 = SELECT;
+ } else {
+ if(editedge_getSharedVert(eed, last)) {
+ BLI_linklist_append(&edgelist,eed);
+ eed->f1 = SELECT;
+ numadded++;
+ last = eed;
+ } else if(editedge_getSharedVert(eed, first)) {
+ BLI_linklist_prepend(&edgelist,eed);
+ eed->f1 = SELECT;
+ numadded++;
+ first = eed;
+ }
+ }
+ }
+ if(eed->next == NULL && numadded != numsel) {
+ eed=em->edges.first;
+ timesthrough++;
+ }
+
+ // It looks like there was an unexpected case - Hopefully should not happen
+ if(timesthrough >= numsel*2) {
+ BLI_linklist_free(edgelist,NULL);
+ BKE_report(op->reports, RPT_ERROR, "Could not order loop");
+ return 0;
+ }
+ }
+
+ // Put the verts in order in a linklist
+ look = edgelist;
+ while(look) {
+ eed = look->link;
+ if(!vertlist) {
+ if(look->next) {
+ temp = look->next->link;
+
+ //This is the first entry takes care of extra vert
+ if(eed->v1 != temp->v1 && eed->v1 != temp->v2) {
+ BLI_linklist_append(&vertlist,eed->v1);
+ eed->v1->f1 = 1;
+ } else {
+ BLI_linklist_append(&vertlist,eed->v2);
+ eed->v2->f1 = 1;
+ }
+ } else {
+ //This is the case that we only have 1 edge
+ BLI_linklist_append(&vertlist,eed->v1);
+ eed->v1->f1 = 1;
+ }
+ }
+ // for all the entries
+ if(eed->v1->f1 != 1) {
+ BLI_linklist_append(&vertlist,eed->v1);
+ eed->v1->f1 = 1;
+ } else if(eed->v2->f1 != 1) {
+ BLI_linklist_append(&vertlist,eed->v2);
+ eed->v2->f1 = 1;
+ }
+ look = look->next;
+ }
+
+ // populate the SlideVerts
+
+ vertgh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ look = vertlist;
+ while(look) {
+ i=0;
+ j=0;
+ ev = look->link;
+ tempsv = (struct SlideVert*)MEM_mallocN(sizeof(struct SlideVert),"SlideVert");
+ tempsv->up = NULL;
+ tempsv->down = NULL;
+ tempsv->origvert.co[0] = ev->co[0];
+ tempsv->origvert.co[1] = ev->co[1];
+ tempsv->origvert.co[2] = ev->co[2];
+ tempsv->origvert.no[0] = ev->no[0];
+ tempsv->origvert.no[1] = ev->no[1];
+ tempsv->origvert.no[2] = ev->no[2];
+ // i is total edges that vert is on
+ // j is total selected edges that vert is on
+
+ for(eed=em->edges.first;eed;eed=eed->next) {
+ if(eed->v1 == ev || eed->v2 == ev) {
+ i++;
+ if(eed->f & SELECT) {
+ j++;
+ }
+ }
+ }
+ // If the vert is in the middle of an edge loop, it touches 2 selected edges and 2 unselected edges
+ if(i == 4 && j == 2) {
+ for(eed=em->edges.first;eed;eed=eed->next) {
+ if(editedge_containsVert(eed, ev)) {
+ if(!(eed->f & SELECT)) {
+ if(!tempsv->up) {
+ tempsv->up = eed;
+ } else if (!(tempsv->down)) {
+ tempsv->down = eed;
+ }
+ }
+ }
+ }
+ }
+ // If it is on the end of the loop, it touches 1 selected and as least 2 more unselected
+ if(i >= 3 && j == 1) {
+ for(eed=em->edges.first;eed;eed=eed->next) {
+ if(editedge_containsVert(eed, ev) && eed->f & SELECT) {
+ for(efa = em->faces.first;efa;efa=efa->next) {
+ if(editface_containsEdge(efa, eed)) {
+ if(editedge_containsVert(efa->e1, ev) && efa->e1 != eed) {
+ if(!tempsv->up) {
+ tempsv->up = efa->e1;
+ } else if (!(tempsv->down)) {
+ tempsv->down = efa->e1;
+ }
+ }
+ if(editedge_containsVert(efa->e2, ev) && efa->e2 != eed) {
+ if(!tempsv->up) {
+ tempsv->up = efa->e2;
+ } else if (!(tempsv->down)) {
+ tempsv->down = efa->e2;
+ }
+ }
+ if(editedge_containsVert(efa->e3, ev) && efa->e3 != eed) {
+ if(!tempsv->up) {
+ tempsv->up = efa->e3;
+ } else if (!(tempsv->down)) {
+ tempsv->down = efa->e3;
+ }
+ }
+ if(efa->e4) {
+ if(editedge_containsVert(efa->e4, ev) && efa->e4 != eed) {
+ if(!tempsv->up) {
+ tempsv->up = efa->e4;
+ } else if (!(tempsv->down)) {
+ tempsv->down = efa->e4;
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+ }
+ if(i > 4 && j == 2) {
+ BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
+ BLI_linklist_free(vertlist,NULL);
+ BLI_linklist_free(edgelist,NULL);
+ return 0;
+ }
+ BLI_ghash_insert(vertgh,ev,tempsv);
+
+ look = look->next;
+ }
+
+ // make sure the UPs nad DOWNs are 'faceloops'
+ // Also find the nearest slidevert to the cursor
+// XXX getmouseco_areawin(mval);
+ look = vertlist;
+ nearest = NULL;
+ vertdist = -1;
+ while(look) {
+ tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
+
+ if(!tempsv->up || !tempsv->down) {
+ BKE_report(op->reports, RPT_ERROR, "Missing rails");
+ BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
+ BLI_linklist_free(vertlist,NULL);
+ BLI_linklist_free(edgelist,NULL);
+ return 0;
+ }
+
+ if(me->drawflag & ME_DRAW_EDGELEN) {
+ if(!(tempsv->up->f & SELECT)) {
+ tempsv->up->f |= SELECT;
+ tempsv->up->f2 |= 16;
+ } else {
+ tempsv->up->f2 |= ~16;
+ }
+ if(!(tempsv->down->f & SELECT)) {
+ tempsv->down->f |= SELECT;
+ tempsv->down->f2 |= 16;
+ } else {
+ tempsv->down->f2 |= ~16;
+ }
+ }
+
+ if(look->next != NULL) {
+ SlideVert *sv;
+
+ sv = BLI_ghash_lookup(vertgh,(EditVert*)look->next->link);
+
+ if(sv) {
+ float tempdist, co[2];
+
+ if(!sharesFace(em, tempsv->up,sv->up)) {
+ EditEdge *swap;
+ swap = sv->up;
+ sv->up = sv->down;
+ sv->down = swap;
+ }
+
+// view3d_project_float(curarea, tempsv->origvert.co, co, projectMat);
+
+ tempdist = sqrt(pow(co[0] - mval[0],2)+pow(co[1] - mval[1],2));
+
+ if(vertdist < 0) {
+ vertdist = tempdist;
+ nearest = (EditVert*)look->link;
+ } else if ( tempdist < vertdist ) {
+ vertdist = tempdist;
+ nearest = (EditVert*)look->link;
+ }
+ }
+ }
+
+
+
+ look = look->next;
+ }
+
+
+ if (uvlay_tot) { // XXX && (scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
+ int maxnum = 0;
+ uvarray = MEM_callocN( uvlay_tot * sizeof(GHash *), "SlideUVs Array");
+ suv_last = slideuvs = MEM_callocN( uvlay_tot * (numadded+1) * sizeof(SlideUv), "SlideUVs"); /* uvLayers * verts */
+ suv = NULL;
+
+ for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+
+ uvarray[uvlay_idx] = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ for(ev=em->verts.first;ev;ev=ev->next) {
+ ev->tmp.l = 0;
+ }
+ look = vertlist;
+ while(look) {
+ float *uv_new;
+ tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
+
+ ev = look->link;
+ suv = NULL;
+ for(efa = em->faces.first;efa;efa=efa->next) {
+ if (ev->tmp.l != -1) { /* test for self, in this case its invalid */
+ int k=-1; /* face corner */
+
+ /* Is this vert in the faces corner? */
+ if (efa->v1==ev) k=0;
+ else if (efa->v2==ev) k=1;
+ else if (efa->v3==ev) k=2;
+ else if (efa->v4 && efa->v4==ev) k=3;
+
+ if (k != -1) {
+ MTFace *tf = CustomData_em_get_n(&em->fdata, efa->data, CD_MTFACE, uvlay_idx);
+ EditVert *ev_up, *ev_down;
+
+ uv_new = tf->uv[k];
+
+ if (ev->tmp.l) {
+ if (fabs(suv->origuv[0]-uv_new[0]) > 0.0001 || fabs(suv->origuv[1]-uv_new[1])) {
+ ev->tmp.l = -1; /* Tag as invalid */
+ BLI_linklist_free(suv->fuv_list,NULL);
+ suv->fuv_list = NULL;
+ BLI_ghash_remove(uvarray[uvlay_idx],ev, NULL, NULL);
+ suv = NULL;
+ break;
+ }
+ } else {
+ ev->tmp.l = 1;
+ suv = suv_last;
+
+ suv->fuv_list = NULL;
+ suv->uv_up = suv->uv_down = NULL;
+ suv->origuv[0] = uv_new[0];
+ suv->origuv[1] = uv_new[1];
+
+ BLI_linklist_prepend(&suv->fuv_list, uv_new);
+ BLI_ghash_insert(uvarray[uvlay_idx],ev,suv);
+
+ suv_last++; /* advance to next slide UV */
+ maxnum++;
+ }
+
+ /* Now get the uvs along the up or down edge if we can */
+ if (suv) {
+ if (!suv->uv_up) {
+ ev_up = editedge_getOtherVert(tempsv->up,ev);
+ if (efa->v1==ev_up) suv->uv_up = tf->uv[0];
+ else if (efa->v2==ev_up) suv->uv_up = tf->uv[1];
+ else if (efa->v3==ev_up) suv->uv_up = tf->uv[2];
+ else if (efa->v4 && efa->v4==ev_up) suv->uv_up = tf->uv[3];
+ }
+ if (!suv->uv_down) { /* if the first face was apart of the up edge, it cant be apart of the down edge */
+ ev_down = editedge_getOtherVert(tempsv->down,ev);
+ if (efa->v1==ev_down) suv->uv_down = tf->uv[0];
+ else if (efa->v2==ev_down) suv->uv_down = tf->uv[1];
+ else if (efa->v3==ev_down) suv->uv_down = tf->uv[2];
+ else if (efa->v4 && efa->v4==ev_down) suv->uv_down = tf->uv[3];
+ }
+
+ /* Copy the pointers to the face UV's */
+ BLI_linklist_prepend(&suv->fuv_list, uv_new);
+ }
+ }
+ }
+ }
+ look = look->next;
+ }
+ } /* end uv layer loop */
+ } /* end uvlay_tot */
+
+
+
+ // we should have enough info now to slide
+
+ len = 0.0f;
+
+ percp = -1;
+ while(draw) {
+ /* For the % calculation */
+ short mval[2];
+ float rc[2];
+ float v2[2], v3[2];
+ EditVert *centerVert, *upVert, *downVert;
+
+// XXX getmouseco_areawin(mval);
+
+ if (!immediate && (mval[0] == mvalo[0] && mval[1] == mvalo[1])) {
+ PIL_sleep_ms(10);
+ } else {
+ char *p = str;
+ int ctrl= 0, shift= 0; // XXX
+
+ mvalo[0] = mval[0];
+ mvalo[1] = mval[1];
+
+
+ tempsv = BLI_ghash_lookup(vertgh,nearest);
+
+ centerVert = editedge_getSharedVert(tempsv->up, tempsv->down);
+ upVert = editedge_getOtherVert(tempsv->up, centerVert);
+ downVert = editedge_getOtherVert(tempsv->down, centerVert);
+
+// view3d_project_float(curarea, upVert->co, v2, projectMat);
+// view3d_project_float(curarea, downVert->co, v3, projectMat);
+
+ /* Determine the % on which the loop should be cut */
+
+ rc[0]= v3[0]-v2[0];
+ rc[1]= v3[1]-v2[1];
+ len= rc[0]*rc[0]+ rc[1]*rc[1];
+ if (len==0) {len = 0.0001;}
+
+ if (shift) {
+ wasshift = 0;
+ labda= ( rc[0]*((mval[0]-v2[0])) + rc[1]*((mval[1]-v2[1])) )/len;
+ }
+ else {
+ if (wasshift==0) {
+ wasshift = 1;
+ shiftlabda = labda;
+ }
+ labda= ( rc[0]*((mval[0]-v2[0])) + rc[1]*((mval[1]-v2[1])) )/len / 10.0 + shiftlabda;
+ }
+
+
+ if(labda<=0.0) labda=0.0;
+ else if(labda>=1.0)labda=1.0;
+
+ perc=((1-labda)*2)-1;
+
+ if(shift == 0 && ctrl==0) {
+ perc *= 100;
+ perc = floor(perc);
+ perc /= 100;
+ } else if (ctrl) {
+ perc *= 10;
+ perc = floor(perc);
+ perc /= 10;
+ }
+
+ if(prop == 0) {
+ len = VecLenf(upVert->co,downVert->co)*((perc+1)/2);
+ if(flip == 1) {
+ len = VecLenf(upVert->co,downVert->co) - len;
+ }
+ }
+
+ if (0) // XXX hasNumInput(&num))
+ {
+// XXX applyNumInput(&num, &perc);
+
+ if (prop)
+ {
+ perc = MIN2(perc, 1);
+ perc = MAX2(perc, -1);
+ }
+ else
+ {
+ len = MIN2(perc, VecLenf(upVert->co,downVert->co));
+ len = MAX2(len, 0);
+ }
+ }
+
+ //Adjust Edgeloop
+ if(immediate) {
+ perc = imperc;
+ }
+ percp = perc;
+ if(prop) {
+ look = vertlist;
+ while(look) {
+ EditVert *tempev;
+ ev = look->link;
+ tempsv = BLI_ghash_lookup(vertgh,ev);
+
+ tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev);
+ VecLerpf(ev->co, tempsv->origvert.co, tempev->co, fabs(perc));
+
+ if (0) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
+ for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+ suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
+ if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
+ Vec2Lerpf(uv_tmp, suv->origuv, (perc>=0)?suv->uv_up:suv->uv_down, fabs(perc));
+ fuv_link = suv->fuv_list;
+ while (fuv_link) {
+ VECCOPY2D(((float *)fuv_link->link), uv_tmp);
+ fuv_link = fuv_link->next;
+ }
+ }
+ }
+ }
+
+ look = look->next;
+ }
+ }
+ else {
+ //Non prop code
+ look = vertlist;
+ while(look) {
+ float newlen;
+ ev = look->link;
+ tempsv = BLI_ghash_lookup(vertgh,ev);
+ newlen = (len / VecLenf(editedge_getOtherVert(tempsv->up,ev)->co,editedge_getOtherVert(tempsv->down,ev)->co));
+ if(newlen > 1.0) {newlen = 1.0;}
+ if(newlen < 0.0) {newlen = 0.0;}
+ if(flip == 0) {
+ VecLerpf(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen));
+ if (0) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
+ /* dont do anything if no UVs */
+ for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+ suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
+ if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
+ Vec2Lerpf(uv_tmp, suv->uv_down, suv->uv_up, fabs(newlen));
+ fuv_link = suv->fuv_list;
+ while (fuv_link) {
+ VECCOPY2D(((float *)fuv_link->link), uv_tmp);
+ fuv_link = fuv_link->next;
+ }
+ }
+ }
+ }
+ } else{
+ VecLerpf(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen));
+
+ if (0) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
+ /* dont do anything if no UVs */
+ for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+ suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
+ if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
+ Vec2Lerpf(uv_tmp, suv->uv_up, suv->uv_down, fabs(newlen));
+ fuv_link = suv->fuv_list;
+ while (fuv_link) {
+ VECCOPY2D(((float *)fuv_link->link), uv_tmp);
+ fuv_link = fuv_link->next;
+ }
+ }
+ }
+ }
+ }
+ look = look->next;
+ }
+
+ }
+
+ // Highlight the Control Edges
+// scrarea_do_windraw(curarea);
+// persp(PERSP_VIEW);
+// glPushMatrix();
+// mymultmatrix(obedit->obmat);
+
+ glColor3ub(0, 255, 0);
+ glBegin(GL_LINES);
+ glVertex3fv(upVert->co);
+ glVertex3fv(downVert->co);
+ glEnd();
+
+ if(prop == 0) {
+ // draw start edge for non-prop
+ glPointSize(5);
+ glBegin(GL_POINTS);
+ glColor3ub(255,0,255);
+ if(flip) {
+ glVertex3fv(upVert->co);
+ } else {
+ glVertex3fv(downVert->co);
+ }
+ glEnd();
+ }
+
+
+ glPopMatrix();
+
+ if(prop) {
+ p += sprintf(str, "(P)ercentage: ");
+ } else {
+ p += sprintf(str, "Non (P)rop Length: ");
+ }
+
+ if (0) // XXX hasNumInput(&num))
+ {
+ char num_str[20];
+
+ // XX outputNumInput(&num, num_str);
+ p += sprintf(p, "%s", num_str);
+ }
+ else
+ {
+ if (prop)
+ {
+ p += sprintf(p, "%f", perc);
+ }
+ else
+ {
+ p += sprintf(p, "%f", len);
+ }
+ }
+
+
+ if (prop == 0) {
+ p += sprintf(p, ", Press (F) to flip control side");
+ }
+
+// headerprint(str);
+// screen_swapbuffers();
+ }
+ if(!immediate) {
+ while(qtest()) {
+ short val=0;
+ event= extern_qread(&val); // extern_qread stores important events for the mainloop to handle
+
+ /* val==0 on key-release event */
+ if (val) {
+ if(ELEM(event, ESCKEY, RIGHTMOUSE)) {
+ prop = 1; // Go back to prop mode
+ imperc = 0; // This is the % that gets set for immediate
+ immediate = 1; //Run through eval code 1 more time
+ cancel = 1; // Return -1
+ mvalo[0] = -1;
+ } else if(ELEM3(event, PADENTER, LEFTMOUSE, RETKEY)) {
+ draw = 0; // End looping now
+ } else if(event==MIDDLEMOUSE) {
+ perc = 0;
+ immediate = 1;
+ } else if(event==PKEY) {
+// XXX initNumInput(&num); /* reset num input */
+ if (prop) {
+ prop = 0;
+// XXX num.flag |= NUM_NO_NEGATIVE;
+ }
+ else {
+ prop = 1;
+ }
+ mvalo[0] = -1;
+ } else if(event==FKEY) {
+ (flip == 1) ? (flip = 0):(flip = 1);
+ mvalo[0] = -1;
+ } else if(ELEM(event, RIGHTARROWKEY, WHEELUPMOUSE)) { // Scroll through Control Edges
+ look = vertlist;
+ while(look) {
+ if(nearest == (EditVert*)look->link) {
+ if(look->next == NULL) {
+ nearest = (EditVert*)vertlist->link;
+ } else {
+ nearest = (EditVert*)look->next->link;
+ }
+ mvalo[0] = -1;
+ break;
+ }
+ look = look->next;
+ }
+ } else if(ELEM(event, LEFTARROWKEY, WHEELDOWNMOUSE)) { // Scroll through Control Edges
+ look = vertlist;
+ while(look) {
+ if(look->next) {
+ if(look->next->link == nearest) {
+ nearest = (EditVert*)look->link;
+ mvalo[0] = -1;
+ break;
+ }
+ } else {
+ if((EditVert*)vertlist->link == nearest) {
+ nearest = look->link;
+ mvalo[0] = -1;
+ break;
+ }
+ }
+ look = look->next;
+ }
+ }
+
+// XXX if (handleNumInput(&num, event))
+ {
+ mvalo[0] = -1; /* NEED A BETTER WAY TO TRIGGER REDRAW */
+ }
+ }
+
+ }
+ } else {
+ draw = 0;
+ }
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ }
+
+
+ if(me->drawflag & ME_DRAW_EDGELEN) {
+ look = vertlist;
+ while(look) {
+ tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
+ if(tempsv != NULL) {
+ tempsv->up->f &= !SELECT;
+ tempsv->down->f &= !SELECT;
+ }
+ look = look->next;
+ }
+ }
+
+// force_draw(0);
+
+ if(!immediate)
+ EM_automerge(0);
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+// scrarea_queue_winredraw(curarea);
+
+ //BLI_ghash_free(edgesgh, freeGHash, NULL);
+ BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
+ BLI_linklist_free(vertlist,NULL);
+ BLI_linklist_free(edgelist,NULL);
+
+ if (uvlay_tot) { // XXX && (scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
+ for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+ BLI_ghash_free(uvarray[uvlay_idx], NULL, NULL);
+ }
+ MEM_freeN(uvarray);
+ MEM_freeN(slideuvs);
+
+ suv = suv_last-1;
+ while (suv >= slideuvs) {
+ if (suv->fuv_list) {
+ BLI_linklist_free(suv->fuv_list,NULL);
+ }
+ suv--;
+ }
+ }
+
+ if(cancel == 1) {
+ return -1;
+ }
+
+ return 1;
+#endif // END OF XXX
+}
+
+int EdgeLoopDelete(EditMesh *em, wmOperator *op)
+{
+
+ /* temporal flag setting so we keep UVs when deleting edge loops,
+ * this is a bit of a hack but it works how you would want in almost all cases */
+ // short uvcalc_flag_orig = 0; // XXX scene->toolsettings->uvcalc_flag;
+ // scene->toolsettings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT;
+
+ if(!EdgeSlide(em, op, 1, 1)) {
+ return 0;
+ }
+
+ /* restore uvcalc flag */
+ // scene->toolsettings->uvcalc_flag = uvcalc_flag_orig;
+
+ EM_select_more(em);
+ removedoublesflag(em, 1,0, 0.001);
+ EM_select_flush(em);
+ // DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ return 1;
+}
+
+
+/* -------------------- More tools ------------------ */
+#if 0
+void mesh_set_face_flags(EditMesh *em, short mode)
+{
+ EditFace *efa;
+ MTFace *tface;
+ short m_tex=0, m_tiles=0, m_shared=0,
+ m_light=0, m_invis=0, m_collision=0,
+ m_twoside=0, m_obcolor=0, m_halo=0,
+ m_billboard=0, m_shadow=0, m_text=0,
+ m_sort=0;
+ short flag = 0, change = 0;
+
+// XXX if (!EM_texFaceCheck()) {
+// error("not a mesh with uv/image layers");
+// return;
+// }
+
+ add_numbut(0, TOG|SHO, "Texture", 0, 0, &m_tex, NULL);
+ add_numbut(1, TOG|SHO, "Tiles", 0, 0, &m_tiles, NULL);
+ add_numbut(2, TOG|SHO, "Light", 0, 0, &m_light, NULL);
+ add_numbut(3, TOG|SHO, "Invisible", 0, 0, &m_invis, NULL);
+ add_numbut(4, TOG|SHO, "Collision", 0, 0, &m_collision, NULL);
+ add_numbut(5, TOG|SHO, "Shared", 0, 0, &m_shared, NULL);
+ add_numbut(6, TOG|SHO, "Twoside", 0, 0, &m_twoside, NULL);
+ add_numbut(7, TOG|SHO, "ObColor", 0, 0, &m_obcolor, NULL);
+ add_numbut(8, TOG|SHO, "Halo", 0, 0, &m_halo, NULL);
+ add_numbut(9, TOG|SHO, "Billboard", 0, 0, &m_billboard, NULL);
+ add_numbut(10, TOG|SHO, "Shadow", 0, 0, &m_shadow, NULL);
+ add_numbut(11, TOG|SHO, "Text", 0, 0, &m_text, NULL);
+ add_numbut(12, TOG|SHO, "Sort", 0, 0, &m_sort, NULL);
+
+ if (!do_clever_numbuts((mode ? "Set Flags" : "Clear Flags"), 13, REDRAW))
+ return;
+
+ /* these 2 cant both be on */
+ if (mode) /* are we seeting*/
+ if (m_halo)
+ m_billboard = 0;
+
+ if (m_tex) flag |= TF_TEX;
+ if (m_tiles) flag |= TF_TILES;
+ if (m_shared) flag |= TF_SHAREDCOL;
+ if (m_light) flag |= TF_LIGHT;
+ if (m_invis) flag |= TF_INVISIBLE;
+ if (m_collision) flag |= TF_DYNAMIC;
+ if (m_twoside) flag |= TF_TWOSIDE;
+ if (m_obcolor) flag |= TF_OBCOL;
+ if (m_halo) flag |= TF_BILLBOARD;
+ if (m_billboard) flag |= TF_BILLBOARD2;
+ if (m_shadow) flag |= TF_SHADOW;
+ if (m_text) flag |= TF_BMFONT;
+ if (m_sort) flag |= TF_ALPHASORT;
+
+ if (flag==0)
+ return;
+
+ efa= em->faces.first;
+ while(efa) {
+ if(efa->f & SELECT) {
+ tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if (mode) tface->mode |= flag;
+ else tface->mode &= ~flag;
+ change = 1;
+ }
+ efa= efa->next;
+ }
+
+}
+#endif
+
+void mesh_set_smooth_faces(EditMesh *em, short event)
+{
+ EditFace *efa;
+
+ if(em==NULL) return;
+
+ efa= em->faces.first;
+ while(efa) {
+ if(efa->f & SELECT) {
+ if(event==1) efa->flag |= ME_SMOOTH;
+ else if(event==0) efa->flag &= ~ME_SMOOTH;
+ }
+ efa= efa->next;
+ }
+
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+}
+
+/* ********************** mesh rip ********************** */
+
+/* helper to find edge for edge_rip */
+static float mesh_rip_edgedist(ARegion *ar, float mat[][4], float *co1, float *co2, short *mval)
+{
+ float vec1[3], vec2[3], mvalf[2];
+
+ view3d_project_float(ar, co1, vec1, mat);
+ view3d_project_float(ar, co2, vec2, mat);
+ mvalf[0]= (float)mval[0];
+ mvalf[1]= (float)mval[1];
+
+ return PdistVL2Dfl(mvalf, vec1, vec2);
+}
+
+/* helper for below */
+static void mesh_rip_setface(EditMesh *em, EditFace *sefa)
+{
+ /* put new vertices & edges in best face */
+ if(sefa->v1->tmp.v) sefa->v1= sefa->v1->tmp.v;
+ if(sefa->v2->tmp.v) sefa->v2= sefa->v2->tmp.v;
+ if(sefa->v3->tmp.v) sefa->v3= sefa->v3->tmp.v;
+ if(sefa->v4 && sefa->v4->tmp.v) sefa->v4= sefa->v4->tmp.v;
+
+ sefa->e1= addedgelist(em, sefa->v1, sefa->v2, sefa->e1);
+ sefa->e2= addedgelist(em, sefa->v2, sefa->v3, sefa->e2);
+ if(sefa->v4) {
+ sefa->e3= addedgelist(em, sefa->v3, sefa->v4, sefa->e3);
+ sefa->e4= addedgelist(em, sefa->v4, sefa->v1, sefa->e4);
+ }
+ else
+ sefa->e3= addedgelist(em, sefa->v3, sefa->v1, sefa->e3);
+
+}
+
+/* based on mouse cursor position, it defines how is being ripped */
+static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ RegionView3D *rv3d= ar->regiondata;
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ EditVert *eve, *nextve;
+ EditEdge *eed, *seed= NULL;
+ EditFace *efa, *sefa= NULL;
+ float projectMat[4][4], vec[3], dist, mindist, viewMat[4][4];
+ short doit= 1, *mval= event->mval; // XXX ,propmode,prop;
+
+
+// XXX propmode = scene->prop_mode;
+// scene->prop_mode = 0;
+// prop = scene->proportional;
+// scene->proportional = 0;
+
+ /* select flush... vertices are important */
+ EM_selectmode_set(em);
+
+ view3d_get_object_project_mat(rv3d, obedit, projectMat, viewMat);
+
+ /* find best face, exclude triangles and break on face select or faces with 2 edges select */
+ mindist= 1000000.0f;
+ for(efa= em->faces.first; efa; efa=efa->next) {
+ if( efa->f & 1)
+ break;
+ if(efa->v4 && faceselectedOR(efa, SELECT) ) {
+ int totsel=0;
+
+ if(efa->e1->f & SELECT) totsel++;
+ if(efa->e2->f & SELECT) totsel++;
+ if(efa->e3->f & SELECT) totsel++;
+ if(efa->e4->f & SELECT) totsel++;
+
+ if(totsel>1)
+ break;
+ view3d_project_float(ar, efa->cent, vec, projectMat);
+ dist= sqrt( (vec[0]-mval[0])*(vec[0]-mval[0]) + (vec[1]-mval[1])*(vec[1]-mval[1]) );
+ if(dist<mindist) {
+ mindist= dist;
+ sefa= efa;
+ }
+ }
+ }
+
+ if(efa) {
+ BKE_report(op->reports, RPT_ERROR, "Can't perform ripping with faces selected this way");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+ if(sefa==NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No proper selection or faces included");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+
+ /* duplicate vertices, new vertices get selected */
+ for(eve = em->verts.last; eve; eve= eve->prev) {
+ eve->tmp.v = NULL;
+ if(eve->f & SELECT) {
+ eve->tmp.v = addvertlist(em, eve->co, eve);
+ eve->f &= ~SELECT;
+ eve->tmp.v->f |= SELECT;
+ }
+ }
+
+ /* find the best candidate edge */
+ /* or one of sefa edges is selected... */
+ if(sefa->e1->f & SELECT) seed= sefa->e2;
+ if(sefa->e2->f & SELECT) seed= sefa->e1;
+ if(sefa->e3->f & SELECT) seed= sefa->e2;
+ if(sefa->e4 && sefa->e4->f & SELECT) seed= sefa->e3;
+
+ /* or we do the distance trick */
+ if(seed==NULL) {
+ mindist= 1000000.0f;
+ if(sefa->e1->v1->tmp.v || sefa->e1->v2->tmp.v) {
+ dist = mesh_rip_edgedist(ar, projectMat,
+ sefa->e1->v1->co,
+ sefa->e1->v2->co, mval);
+ if(dist<mindist) {
+ seed= sefa->e1;
+ mindist= dist;
+ }
+ }
+ if(sefa->e2->v1->tmp.v || sefa->e2->v2->tmp.v) {
+ dist = mesh_rip_edgedist(ar, projectMat,
+ sefa->e2->v1->co,
+ sefa->e2->v2->co, mval);
+ if(dist<mindist) {
+ seed= sefa->e2;
+ mindist= dist;
+ }
+ }
+ if(sefa->e3->v1->tmp.v || sefa->e3->v2->tmp.v) {
+ dist= mesh_rip_edgedist(ar, projectMat,
+ sefa->e3->v1->co,
+ sefa->e3->v2->co, mval);
+ if(dist<mindist) {
+ seed= sefa->e3;
+ mindist= dist;
+ }
+ }
+ if(sefa->e4 && (sefa->e4->v1->tmp.v || sefa->e4->v2->tmp.v)) {
+ dist= mesh_rip_edgedist(ar, projectMat,
+ sefa->e4->v1->co,
+ sefa->e4->v2->co, mval);
+ if(dist<mindist) {
+ seed= sefa->e4;
+ mindist= dist;
+ }
+ }
+ }
+
+ if(seed==NULL) { // never happens?
+ BKE_report(op->reports, RPT_ERROR, "No proper edge found to start");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ faceloop_select(em, seed, 2); // tmp abuse for finding all edges that need duplicated, returns OK faces with f1
+
+ /* duplicate edges in the loop, with at least 1 vertex selected, needed for selection flip */
+ for(eed = em->edges.last; eed; eed= eed->prev) {
+ eed->tmp.v = NULL;
+ if((eed->v1->tmp.v) || (eed->v2->tmp.v)) {
+ EditEdge *newed;
+
+ newed= addedgelist(em, eed->v1->tmp.v?eed->v1->tmp.v:eed->v1,
+ eed->v2->tmp.v?eed->v2->tmp.v:eed->v2, eed);
+ if(eed->f & SELECT) {
+ EM_select_edge(eed, 0);
+ EM_remove_selection(em, eed, EDITEDGE);
+ EM_select_edge(newed, 1);
+ }
+ eed->tmp.v = (EditVert *)newed;
+ }
+ }
+
+ /* first clear edges to help finding neighbours */
+ for(eed = em->edges.last; eed; eed= eed->prev) eed->f1= 0;
+
+ /* put new vertices & edges && flag in best face */
+ mesh_rip_setface(em, sefa);
+
+ /* starting with neighbours of best face, we loop over the seam */
+ sefa->f1= 2;
+ doit= 1;
+ while(doit) {
+ doit= 0;
+
+ for(efa= em->faces.first; efa; efa=efa->next) {
+ /* new vert in face */
+ if (efa->v1->tmp.v || efa->v2->tmp.v ||
+ efa->v3->tmp.v || (efa->v4 && efa->v4->tmp.v)) {
+ /* face is tagged with loop */
+ if(efa->f1==1) {
+ mesh_rip_setface(em, efa);
+ efa->f1= 2;
+ doit= 1;
+ }
+ }
+ }
+ }
+
+ /* remove loose edges, that were part of a ripped face */
+ for(eve = em->verts.first; eve; eve= eve->next) eve->f1= 0;
+ for(eed = em->edges.last; eed; eed= eed->prev) eed->f1= 0;
+ for(efa= em->faces.first; efa; efa=efa->next) {
+ efa->e1->f1= 1;
+ efa->e2->f1= 1;
+ efa->e3->f1= 1;
+ if(efa->e4) efa->e4->f1= 1;
+ }
+
+ for(eed = em->edges.last; eed; eed= seed) {
+ seed= eed->prev;
+ if(eed->f1==0) {
+ if(eed->v1->tmp.v || eed->v2->tmp.v ||
+ (eed->v1->f & SELECT) || (eed->v2->f & SELECT)) {
+ remedge(em, eed);
+ free_editedge(em, eed);
+ eed= NULL;
+ }
+ }
+ if(eed) {
+ eed->v1->f1= 1;
+ eed->v2->f1= 1;
+ }
+ }
+
+ /* and remove loose selected vertices, that got duplicated accidentally */
+ for(eve = em->verts.first; eve; eve= nextve) {
+ nextve= eve->next;
+ if(eve->f1==0 && (eve->tmp.v || (eve->f & SELECT))) {
+ BLI_remlink(&em->verts,eve);
+ free_editvert(em, eve);
+ }
+ }
+
+ RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
+ WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+// scene->prop_mode = propmode;
+// XXX scene->proportional = prop;
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_rip(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Rip";
+ ot->idname= "MESH_OT_rip";
+
+ /* api callbacks */
+ ot->invoke= mesh_rip_invoke;
+ ot->poll= ED_operator_editmesh; // XXX + v3d!
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* to give to transform */
+ RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+}
+
+
+/* ************************************** */
+
+void shape_propagate(Scene *scene, Object *obedit, EditMesh *em, wmOperator *op)
+{
+ EditVert *ev = NULL;
+ Mesh* me = (Mesh*)obedit->data;
+ Key* ky = NULL;
+ KeyBlock* kb = NULL;
+ Base* base=NULL;
+
+
+ if(me->key){
+ ky = me->key;
+ } else {
+ BKE_report(op->reports, RPT_ERROR, "Object Has No Key");
+ return;
+ }
+
+ if(ky->block.first){
+ for(ev = em->verts.first; ev ; ev = ev->next){
+ if(ev->f & SELECT){
+ for(kb=ky->block.first;kb;kb = kb->next){
+ float *data;
+ data = kb->data;
+ VECCOPY(data+(ev->keyindex*3),ev->co);
+ }
+ }
+ }
+ } else {
+ BKE_report(op->reports, RPT_ERROR, "Object Has No Blendshapes");
+ return;
+ }
+
+ //TAG Mesh Objects that share this data
+ for(base = scene->base.first; base; base = base->next){
+ if(base->object && base->object->data == me){
+ base->object->recalc = OB_RECALC_DATA;
+ }
+ }
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ return;
+}
+
+void shape_copy_from_lerp(EditMesh *em, KeyBlock* thisBlock, KeyBlock* fromBlock)
+{
+ EditVert *ev = NULL;
+ short mval[2], curval[2], event = 0, finished = 0, canceled = 0, fullcopy=0 ;
+ float perc = 0;
+ char str[64];
+ float *data, *odata;
+
+ data = fromBlock->data;
+ odata = thisBlock->data;
+
+// XXX getmouseco_areawin(mval);
+ curval[0] = mval[0] + 1; curval[1] = mval[1] + 1;
+
+ while (finished == 0)
+ {
+// XXX getmouseco_areawin(mval);
+ if (mval[0] != curval[0] || mval[1] != curval[1])
+ {
+
+ if(mval[0] > curval[0])
+ perc += 0.1;
+ else if(mval[0] < curval[0])
+ perc -= 0.1;
+
+ if(perc < 0) perc = 0;
+ if(perc > 1) perc = 1;
+
+ curval[0] = mval[0];
+ curval[1] = mval[1];
+
+ if(fullcopy == 1){
+ perc = 1;
+ }
+
+ for(ev = em->verts.first; ev ; ev = ev->next){
+ if(ev->f & SELECT){
+ VecLerpf(ev->co,odata+(ev->keyindex*3),data+(ev->keyindex*3),perc);
+ }
+ }
+ sprintf(str,"Blending at %d%c MMB to Copy at 100%c",(int)(perc*100),'%','%');
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+// headerprint(str);
+// force_draw(0);
+
+ if(fullcopy == 1){
+ break;
+ }
+
+ } else {
+ PIL_sleep_ms(10);
+ }
+
+ while(qtest()) {
+ short val=0;
+ event= extern_qread(&val);
+ if(val){
+ if(ELEM3(event, PADENTER, LEFTMOUSE, RETKEY)){
+ finished = 1;
+ }
+ else if (event == MIDDLEMOUSE){
+ fullcopy = 1;
+ }
+ else if (ELEM3(event,ESCKEY,RIGHTMOUSE,RIGHTMOUSE)){
+ canceled = 1;
+ finished = 1;
+ }
+ }
+ }
+ }
+ if(!canceled);
+ else
+ for(ev = em->verts.first; ev ; ev = ev->next){
+ if(ev->f & SELECT){
+ VECCOPY(ev->co, odata+(ev->keyindex*3));
+ }
+ }
+ return;
+}
+
+
+
+void shape_copy_select_from(Object *obedit, EditMesh *em, wmOperator *op)
+{
+ Mesh* me = (Mesh*)obedit->data;
+ EditVert *ev = NULL;
+ int totverts = 0,curshape = obedit->shapenr;
+
+ Key* ky = NULL;
+ KeyBlock *kb = NULL,*thisBlock = NULL;
+ int maxlen=32, nr=0, a=0;
+ char *menu;
+
+ if(me->key){
+ ky = me->key;
+ } else {
+ BKE_report(op->reports, RPT_ERROR, "Object Has No Key");
+ return;
+ }
+
+ if(ky->block.first){
+ for(kb=ky->block.first;kb;kb = kb->next){
+ maxlen += 40; // Size of a block name
+ if(a == curshape-1){
+ thisBlock = kb;
+ }
+
+ a++;
+ }
+ a=0;
+ menu = MEM_callocN(maxlen, "Copy Shape Menu Text");
+ strcpy(menu, "Copy Vert Positions from Shape %t|");
+ for(kb=ky->block.first;kb;kb = kb->next){
+ if(a != curshape-1){
+ sprintf(menu,"%s %s %cx%d|",menu,kb->name,'%',a);
+ }
+ a++;
+ }
+// XXX nr = pupmenu_col(menu, 20);
+ MEM_freeN(menu);
+ } else {
+ BKE_report(op->reports, RPT_ERROR, "Object Has No Blendshapes");
+ return;
+ }
+
+ a = 0;
+
+ for(kb=ky->block.first;kb;kb = kb->next){
+ if(a == nr){
+
+ for(ev = em->verts.first;ev;ev = ev->next){
+ totverts++;
+ }
+
+ if(me->totvert != totverts){
+ BKE_report(op->reports, RPT_ERROR, "Shape Has had Verts Added/Removed, please cycle editmode before copying");
+ return;
+ }
+ shape_copy_from_lerp(em, thisBlock,kb);
+
+ return;
+ }
+ a++;
+ }
+ return;
+}
+
+/* Collection Routines|Currently used by the improved merge code*/
+/* buildEdge_collection() creates a list of lists*/
+/* these lists are filled with edges that are topologically connected.*/
+/* This whole tool needs to be redone, its rather poorly implemented...*/
+
+typedef struct Collection{
+ struct Collection *next, *prev;
+ int index;
+ ListBase collectionbase;
+} Collection;
+
+typedef struct CollectedEdge{
+ struct CollectedEdge *next, *prev;
+ EditEdge *eed;
+} CollectedEdge;
+
+#define MERGELIMIT 0.000001
+
+static void build_edgecollection(EditMesh *em, ListBase *allcollections)
+{
+ EditEdge *eed;
+ Collection *edgecollection, *newcollection;
+ CollectedEdge *newedge;
+
+ int currtag = 1;
+ short ebalanced = 0;
+ short collectionfound = 0;
+
+ for (eed=em->edges.first; eed; eed = eed->next){
+ eed->tmp.l = 0;
+ eed->v1->tmp.l = 0;
+ eed->v2->tmp.l = 0;
+ }
+
+ /*1st pass*/
+ for(eed=em->edges.first; eed; eed=eed->next){
+ if(eed->f&SELECT){
+ eed->v1->tmp.l = currtag;
+ eed->v2->tmp.l = currtag;
+ currtag +=1;
+ }
+ }
+
+ /*2nd pass - Brute force. Loop through selected faces until there are no 'unbalanced' edges left (those with both vertices 'tmp.l' tag matching */
+ while(ebalanced == 0){
+ ebalanced = 1;
+ for(eed=em->edges.first; eed; eed = eed->next){
+ if(eed->f&SELECT){
+ if(eed->v1->tmp.l != eed->v2->tmp.l) /*unbalanced*/{
+ if(eed->v1->tmp.l > eed->v2->tmp.l && eed->v2->tmp.l !=0) eed->v1->tmp.l = eed->v2->tmp.l;
+ else if(eed->v1 != 0) eed->v2->tmp.l = eed->v1->tmp.l;
+ ebalanced = 0;
+ }
+ }
+ }
+ }
+
+ /*3rd pass, set all the edge flags (unnessecary?)*/
+ for(eed=em->edges.first; eed; eed = eed->next){
+ if(eed->f&SELECT) eed->tmp.l = eed->v1->tmp.l;
+ }
+
+ for(eed=em->edges.first; eed; eed=eed->next){
+ if(eed->f&SELECT){
+ if(allcollections->first){
+ for(edgecollection = allcollections->first; edgecollection; edgecollection=edgecollection->next){
+ if(edgecollection->index == eed->tmp.l){
+ newedge = MEM_mallocN(sizeof(CollectedEdge), "collected edge");
+ newedge->eed = eed;
+ BLI_addtail(&(edgecollection->collectionbase), newedge);
+ collectionfound = 1;
+ break;
+ }
+ else collectionfound = 0;
+ }
+ }
+ if(allcollections->first == NULL || collectionfound == 0){
+ newcollection = MEM_mallocN(sizeof(Collection), "element collection");
+ newcollection->index = eed->tmp.l;
+ newcollection->collectionbase.first = 0;
+ newcollection->collectionbase.last = 0;
+
+ newedge = MEM_mallocN(sizeof(CollectedEdge), "collected edge");
+ newedge->eed = eed;
+
+ BLI_addtail(&(newcollection->collectionbase), newedge);
+ BLI_addtail(allcollections, newcollection);
+ }
+ }
+
+ }
+}
+
+static void freecollections(ListBase *allcollections)
+{
+ struct Collection *curcollection;
+
+ for(curcollection = allcollections->first; curcollection; curcollection = curcollection->next)
+ BLI_freelistN(&(curcollection->collectionbase));
+ BLI_freelistN(allcollections);
+}
+
+/*Begin UV Edge Collapse Code
+ Like Edge subdivide, Edge Collapse should handle UV's intelligently, but since UV's are a per-face attribute, normal edge collapse will fail
+ in areas such as the boundries of 'UV islands'. So for each edge collection we need to build a set of 'welded' UV vertices and edges for it.
+ The welded UV edges can then be sorted and collapsed.
+*/
+typedef struct wUV{
+ struct wUV *next, *prev;
+ ListBase nodes;
+ float u, v; /*cached copy of UV coordinates pointed to by nodes*/
+ EditVert *eve;
+ int f;
+} wUV;
+
+typedef struct wUVNode{
+ struct wUVNode *next, *prev;
+ float *u; /*pointer to original tface data*/
+ float *v; /*pointer to original tface data*/
+} wUVNode;
+
+typedef struct wUVEdge{
+ struct wUVEdge *next, *prev;
+ float v1uv[2], v2uv[2]; /*nasty.*/
+ struct wUV *v1, *v2; /*oriented same as editedge*/
+ EditEdge *eed;
+ int f;
+} wUVEdge;
+
+typedef struct wUVEdgeCollect{ /*used for grouping*/
+ struct wUVEdgeCollect *next, *prev;
+ wUVEdge *uved;
+ int id;
+} wUVEdgeCollect;
+
+static void append_weldedUV(EditMesh *em, EditFace *efa, EditVert *eve, int tfindex, ListBase *uvverts)
+{
+ wUV *curwvert, *newwvert;
+ wUVNode *newnode;
+ int found;
+ MTFace *tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ found = 0;
+
+ for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){
+ if(curwvert->eve == eve && curwvert->u == tf->uv[tfindex][0] && curwvert->v == tf->uv[tfindex][1]){
+ newnode = MEM_callocN(sizeof(wUVNode), "Welded UV Vert Node");
+ newnode->u = &(tf->uv[tfindex][0]);
+ newnode->v = &(tf->uv[tfindex][1]);
+ BLI_addtail(&(curwvert->nodes), newnode);
+ found = 1;
+ break;
+ }
+ }
+
+ if(!found){
+ newnode = MEM_callocN(sizeof(wUVNode), "Welded UV Vert Node");
+ newnode->u = &(tf->uv[tfindex][0]);
+ newnode->v = &(tf->uv[tfindex][1]);
+
+ newwvert = MEM_callocN(sizeof(wUV), "Welded UV Vert");
+ newwvert->u = *(newnode->u);
+ newwvert->v = *(newnode->v);
+ newwvert->eve = eve;
+
+ BLI_addtail(&(newwvert->nodes), newnode);
+ BLI_addtail(uvverts, newwvert);
+
+ }
+}
+
+static void build_weldedUVs(EditMesh *em, ListBase *uvverts)
+{
+ EditFace *efa;
+ for(efa=em->faces.first; efa; efa=efa->next){
+ if(efa->v1->f1) append_weldedUV(em, efa, efa->v1, 0, uvverts);
+ if(efa->v2->f1) append_weldedUV(em, efa, efa->v2, 1, uvverts);
+ if(efa->v3->f1) append_weldedUV(em, efa, efa->v3, 2, uvverts);
+ if(efa->v4 && efa->v4->f1) append_weldedUV(em, efa, efa->v4, 3, uvverts);
+ }
+}
+
+static void append_weldedUVEdge(EditMesh *em, EditFace *efa, EditEdge *eed, ListBase *uvedges)
+{
+ wUVEdge *curwedge, *newwedge;
+ int v1tfindex, v2tfindex, found;
+ MTFace *tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ found = 0;
+
+ if(eed->v1 == efa->v1) v1tfindex = 0;
+ else if(eed->v1 == efa->v2) v1tfindex = 1;
+ else if(eed->v1 == efa->v3) v1tfindex = 2;
+ else /* if(eed->v1 == efa->v4) */ v1tfindex = 3;
+
+ if(eed->v2 == efa->v1) v2tfindex = 0;
+ else if(eed->v2 == efa->v2) v2tfindex = 1;
+ else if(eed->v2 == efa->v3) v2tfindex = 2;
+ else /* if(eed->v2 == efa->v4) */ v2tfindex = 3;
+
+ for(curwedge=uvedges->first; curwedge; curwedge=curwedge->next){
+ if(curwedge->eed == eed && curwedge->v1uv[0] == tf->uv[v1tfindex][0] && curwedge->v1uv[1] == tf->uv[v1tfindex][1] && curwedge->v2uv[0] == tf->uv[v2tfindex][0] && curwedge->v2uv[1] == tf->uv[v2tfindex][1]){
+ found = 1;
+ break; //do nothing, we don't need another welded uv edge
+ }
+ }
+
+ if(!found){
+ newwedge = MEM_callocN(sizeof(wUVEdge), "Welded UV Edge");
+ newwedge->v1uv[0] = tf->uv[v1tfindex][0];
+ newwedge->v1uv[1] = tf->uv[v1tfindex][1];
+ newwedge->v2uv[0] = tf->uv[v2tfindex][0];
+ newwedge->v2uv[1] = tf->uv[v2tfindex][1];
+ newwedge->eed = eed;
+
+ BLI_addtail(uvedges, newwedge);
+ }
+}
+
+static void build_weldedUVEdges(EditMesh *em, ListBase *uvedges, ListBase *uvverts)
+{
+ wUV *curwvert;
+ wUVEdge *curwedge;
+ EditFace *efa;
+
+ for(efa=em->faces.first; efa; efa=efa->next){
+ if(efa->e1->f1) append_weldedUVEdge(em, efa, efa->e1, uvedges);
+ if(efa->e2->f1) append_weldedUVEdge(em, efa, efa->e2, uvedges);
+ if(efa->e3->f1) append_weldedUVEdge(em, efa, efa->e3, uvedges);
+ if(efa->e4 && efa->e4->f1) append_weldedUVEdge(em, efa, efa->e4, uvedges);
+ }
+
+
+ //link vertices: for each uvedge, search uvverts to populate v1 and v2 pointers
+ for(curwedge=uvedges->first; curwedge; curwedge=curwedge->next){
+ for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){
+ if(curwedge->eed->v1 == curwvert->eve && curwedge->v1uv[0] == curwvert->u && curwedge->v1uv[1] == curwvert->v){
+ curwedge->v1 = curwvert;
+ break;
+ }
+ }
+ for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){
+ if(curwedge->eed->v2 == curwvert->eve && curwedge->v2uv[0] == curwvert->u && curwedge->v2uv[1] == curwvert->v){
+ curwedge->v2 = curwvert;
+ break;
+ }
+ }
+ }
+}
+
+static void free_weldedUVs(ListBase *uvverts)
+{
+ wUV *curwvert;
+ for(curwvert = uvverts->first; curwvert; curwvert=curwvert->next) BLI_freelistN(&(curwvert->nodes));
+ BLI_freelistN(uvverts);
+}
+
+static void collapse_edgeuvs(EditMesh *em)
+{
+ ListBase uvedges, uvverts, allcollections;
+ wUVEdge *curwedge;
+ wUVNode *curwnode;
+ wUVEdgeCollect *collectedwuve, *newcollectedwuve;
+ Collection *wuvecollection, *newcollection;
+ int curtag, balanced, collectionfound= 0, vcount;
+ float avg[2];
+
+ if (!EM_texFaceCheck(em))
+ return;
+
+ uvverts.first = uvverts.last = uvedges.first = uvedges.last = allcollections.first = allcollections.last = NULL;
+
+ build_weldedUVs(em, &uvverts);
+ build_weldedUVEdges(em, &uvedges, &uvverts);
+
+ curtag = 0;
+
+ for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){
+ curwedge->v1->f = curtag;
+ curwedge->v2->f = curtag;
+ curtag +=1;
+ }
+
+ balanced = 0;
+ while(!balanced){
+ balanced = 1;
+ for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){
+ if(curwedge->v1->f != curwedge->v2->f){
+ if(curwedge->v1->f > curwedge->v2->f) curwedge->v1->f = curwedge->v2->f;
+ else curwedge->v2->f = curwedge->v1->f;
+ balanced = 0;
+ }
+ }
+ }
+
+ for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next) curwedge->f = curwedge->v1->f;
+
+
+ for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){
+ if(allcollections.first){
+ for(wuvecollection = allcollections.first; wuvecollection; wuvecollection=wuvecollection->next){
+ if(wuvecollection->index == curwedge->f){
+ newcollectedwuve = MEM_callocN(sizeof(wUVEdgeCollect), "Collected Welded UV Edge");
+ newcollectedwuve->uved = curwedge;
+ BLI_addtail(&(wuvecollection->collectionbase), newcollectedwuve);
+ collectionfound = 1;
+ break;
+ }
+
+ else collectionfound = 0;
+ }
+ }
+ if(allcollections.first == NULL || collectionfound == 0){
+ newcollection = MEM_callocN(sizeof(Collection), "element collection");
+ newcollection->index = curwedge->f;
+ newcollection->collectionbase.first = 0;
+ newcollection->collectionbase.last = 0;
+
+ newcollectedwuve = MEM_callocN(sizeof(wUVEdgeCollect), "Collected Welded UV Edge");
+ newcollectedwuve->uved = curwedge;
+
+ BLI_addtail(&(newcollection->collectionbase), newcollectedwuve);
+ BLI_addtail(&allcollections, newcollection);
+ }
+ }
+
+ for(wuvecollection=allcollections.first; wuvecollection; wuvecollection=wuvecollection->next){
+
+ vcount = avg[0] = avg[1] = 0;
+
+ for(collectedwuve= wuvecollection->collectionbase.first; collectedwuve; collectedwuve = collectedwuve->next){
+ avg[0] += collectedwuve->uved->v1uv[0];
+ avg[1] += collectedwuve->uved->v1uv[1];
+
+ avg[0] += collectedwuve->uved->v2uv[0];
+ avg[1] += collectedwuve->uved->v2uv[1];
+
+ vcount +=2;
+
+ }
+
+ avg[0] /= vcount; avg[1] /= vcount;
+
+ for(collectedwuve= wuvecollection->collectionbase.first; collectedwuve; collectedwuve = collectedwuve->next){
+ for(curwnode=collectedwuve->uved->v1->nodes.first; curwnode; curwnode=curwnode->next){
+ *(curwnode->u) = avg[0];
+ *(curwnode->v) = avg[1];
+ }
+ for(curwnode=collectedwuve->uved->v2->nodes.first; curwnode; curwnode=curwnode->next){
+ *(curwnode->u) = avg[0];
+ *(curwnode->v) = avg[1];
+ }
+ }
+ }
+
+ free_weldedUVs(&uvverts);
+ BLI_freelistN(&uvedges);
+ freecollections(&allcollections);
+}
+
+/*End UV Edge collapse code*/
+
+static void collapseuvs(EditMesh *em, EditVert *mergevert)
+{
+ EditFace *efa;
+ MTFace *tf;
+ int uvcount;
+ float uvav[2];
+
+ if (!EM_texFaceCheck(em))
+ return;
+
+ uvcount = 0;
+ uvav[0] = 0;
+ uvav[1] = 0;
+
+ for(efa = em->faces.first; efa; efa=efa->next){
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(efa->v1->f1 && ELEM(mergevert, NULL, efa->v1)) {
+ uvav[0] += tf->uv[0][0];
+ uvav[1] += tf->uv[0][1];
+ uvcount += 1;
+ }
+ if(efa->v2->f1 && ELEM(mergevert, NULL, efa->v2)){
+ uvav[0] += tf->uv[1][0];
+ uvav[1] += tf->uv[1][1];
+ uvcount += 1;
+ }
+ if(efa->v3->f1 && ELEM(mergevert, NULL, efa->v3)){
+ uvav[0] += tf->uv[2][0];
+ uvav[1] += tf->uv[2][1];
+ uvcount += 1;
+ }
+ if(efa->v4 && efa->v4->f1 && ELEM(mergevert, NULL, efa->v4)){
+ uvav[0] += tf->uv[3][0];
+ uvav[1] += tf->uv[3][1];
+ uvcount += 1;
+ }
+ }
+
+ if(uvcount > 0) {
+ uvav[0] /= uvcount;
+ uvav[1] /= uvcount;
+
+ for(efa = em->faces.first; efa; efa=efa->next){
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(efa->v1->f1){
+ tf->uv[0][0] = uvav[0];
+ tf->uv[0][1] = uvav[1];
+ }
+ if(efa->v2->f1){
+ tf->uv[1][0] = uvav[0];
+ tf->uv[1][1] = uvav[1];
+ }
+ if(efa->v3->f1){
+ tf->uv[2][0] = uvav[0];
+ tf->uv[2][1] = uvav[1];
+ }
+ if(efa->v4 && efa->v4->f1){
+ tf->uv[3][0] = uvav[0];
+ tf->uv[3][1] = uvav[1];
+ }
+ }
+ }
+}
+
+int collapseEdges(EditMesh *em)
+{
+ EditVert *eve;
+ EditEdge *eed;
+
+ ListBase allcollections;
+ CollectedEdge *curredge;
+ Collection *edgecollection;
+
+ int totedges, groupcount, mergecount,vcount;
+ float avgcount[3];
+
+ allcollections.first = 0;
+ allcollections.last = 0;
+
+ mergecount = 0;
+
+ build_edgecollection(em, &allcollections);
+ groupcount = BLI_countlist(&allcollections);
+
+
+ for(edgecollection = allcollections.first; edgecollection; edgecollection = edgecollection->next){
+ totedges = BLI_countlist(&(edgecollection->collectionbase));
+ mergecount += totedges;
+ avgcount[0] = 0; avgcount[1] = 0; avgcount[2] = 0;
+
+ vcount = 0;
+
+ for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){
+ avgcount[0] += ((EditEdge*)curredge->eed)->v1->co[0];
+ avgcount[1] += ((EditEdge*)curredge->eed)->v1->co[1];
+ avgcount[2] += ((EditEdge*)curredge->eed)->v1->co[2];
+
+ avgcount[0] += ((EditEdge*)curredge->eed)->v2->co[0];
+ avgcount[1] += ((EditEdge*)curredge->eed)->v2->co[1];
+ avgcount[2] += ((EditEdge*)curredge->eed)->v2->co[2];
+
+ vcount +=2;
+ }
+
+ avgcount[0] /= vcount; avgcount[1] /=vcount; avgcount[2] /= vcount;
+
+ for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){
+ VECCOPY(((EditEdge*)curredge->eed)->v1->co,avgcount);
+ VECCOPY(((EditEdge*)curredge->eed)->v2->co,avgcount);
+ }
+
+ if (EM_texFaceCheck(em)) {
+ /*uv collapse*/
+ for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0;
+ for(eed=em->edges.first; eed; eed=eed->next) eed->f1 = 0;
+ for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){
+ curredge->eed->v1->f1 = 1;
+ curredge->eed->v2->f1 = 1;
+ curredge->eed->f1 = 1;
+ }
+ collapse_edgeuvs(em);
+ }
+
+ }
+ freecollections(&allcollections);
+ removedoublesflag(em, 1, 0, MERGELIMIT);
+ /*get rid of this!*/
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+// if (EM_texFaceCheck())
+
+ return mergecount;
+}
+
+int merge_firstlast(EditMesh *em, int first, int uvmerge)
+{
+ EditVert *eve,*mergevert;
+ EditSelection *ese;
+
+ /* do sanity check in mergemenu in edit.c ?*/
+ if(first == 0){
+ ese = em->selected.last;
+ mergevert= (EditVert*)ese->data;
+ }
+ else{
+ ese = em->selected.first;
+ mergevert = (EditVert*)ese->data;
+ }
+
+ if(mergevert->f&SELECT){
+ for (eve=em->verts.first; eve; eve=eve->next){
+ if (eve->f&SELECT)
+ VECCOPY(eve->co,mergevert->co);
+ }
+ }
+
+ if(uvmerge && CustomData_has_layer(&em->fdata, CD_MTFACE)){
+
+ for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0;
+ for(eve=em->verts.first; eve; eve=eve->next){
+ if(eve->f&SELECT) eve->f1 = 1;
+ }
+ collapseuvs(em, mergevert);
+ }
+
+ return removedoublesflag(em, 1, 0, MERGELIMIT);
+}
+
+int merge_target(EditMesh *em, int target, int uvmerge)
+{
+ EditVert *eve;
+
+ if(target) snap_sel_to_curs();
+ else snap_to_center();
+
+ if(uvmerge && CustomData_has_layer(&em->fdata, CD_MTFACE)){
+ for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0;
+ for(eve=em->verts.first; eve; eve=eve->next){
+ if(eve->f&SELECT) eve->f1 = 1;
+ }
+ collapseuvs(em, NULL);
+ }
+
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ return removedoublesflag(em, 1, 0, MERGELIMIT);
+
+}
+#undef MERGELIMIT
+
+typedef struct PathNode{
+ int u;
+ int visited;
+ ListBase edges;
+} PathNode;
+
+typedef struct PathEdge{
+ struct PathEdge *next, *prev;
+ int v;
+ float w;
+} PathEdge;
+
+void pathselect(EditMesh *em, wmOperator *op)
+{
+ EditVert *eve, *s, *t;
+ EditEdge *eed;
+ EditSelection *ese;
+ PathEdge *newpe, *currpe;
+ PathNode *currpn;
+ PathNode *Q;
+ int v, *previous, pathvert, pnindex; /*pnindex redundant?*/
+ int unbalanced, totnodes;
+ short physical;
+ float *cost;
+ Heap *heap; /*binary heap for sorting pointers to PathNodes based upon a 'cost'*/
+
+ s = t = NULL;
+
+ ese = ((EditSelection*)em->selected.last);
+ if(ese && ese->type == EDITVERT && ese->prev && ese->prev->type == EDITVERT){
+ physical= pupmenu("Distance Method? %t|Edge Length%x1|Topological%x0");
+
+ t = (EditVert*)ese->data;
+ s = (EditVert*)ese->prev->data;
+
+ /*need to find out if t is actually reachable by s....*/
+ for(eve=em->verts.first; eve; eve=eve->next){
+ eve->f1 = 0;
+ }
+
+ s->f1 = 1;
+
+ unbalanced = 1;
+ totnodes = 1;
+ while(unbalanced){
+ unbalanced = 0;
+ for(eed=em->edges.first; eed; eed=eed->next){
+ if(!eed->h){
+ if(eed->v1->f1 && !eed->v2->f1){
+ eed->v2->f1 = 1;
+ totnodes++;
+ unbalanced = 1;
+ }
+ else if(eed->v2->f1 && !eed->v1->f1){
+ eed->v1->f1 = 1;
+ totnodes++;
+ unbalanced = 1;
+ }
+ }
+ }
+ }
+
+
+
+ if(s->f1 && t->f1){ /*t can be reached by s*/
+ Q = MEM_callocN(sizeof(PathNode)*totnodes, "Path Select Nodes");
+ totnodes = 0;
+ for(eve=em->verts.first; eve; eve=eve->next){
+ if(eve->f1){
+ Q[totnodes].u = totnodes;
+ Q[totnodes].edges.first = 0;
+ Q[totnodes].edges.last = 0;
+ Q[totnodes].visited = 0;
+ eve->tmp.p = &(Q[totnodes]);
+ totnodes++;
+ }
+ else eve->tmp.p = NULL;
+ }
+
+ for(eed=em->edges.first; eed; eed=eed->next){
+ if(!eed->h){
+ if(eed->v1->f1){
+ currpn = ((PathNode*)eed->v1->tmp.p);
+
+ newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge");
+ newpe->v = ((PathNode*)eed->v2->tmp.p)->u;
+ if(physical){
+ newpe->w = VecLenf(eed->v1->co, eed->v2->co);
+ }
+ else newpe->w = 1;
+ newpe->next = 0;
+ newpe->prev = 0;
+ BLI_addtail(&(currpn->edges), newpe);
+ }
+ if(eed->v2->f1){
+ currpn = ((PathNode*)eed->v2->tmp.p);
+ newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge");
+ newpe->v = ((PathNode*)eed->v1->tmp.p)->u;
+ if(physical){
+ newpe->w = VecLenf(eed->v1->co, eed->v2->co);
+ }
+ else newpe->w = 1;
+ newpe->next = 0;
+ newpe->prev = 0;
+ BLI_addtail(&(currpn->edges), newpe);
+ }
+ }
+ }
+
+ heap = BLI_heap_new();
+ cost = MEM_callocN(sizeof(float)*totnodes, "Path Select Costs");
+ previous = MEM_callocN(sizeof(int)*totnodes, "PathNode indices");
+
+ for(v=0; v < totnodes; v++){
+ cost[v] = 1000000;
+ previous[v] = -1; /*array of indices*/
+ }
+
+ pnindex = ((PathNode*)s->tmp.p)->u;
+ cost[pnindex] = 0;
+ BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(pnindex));
+
+ while( !BLI_heap_empty(heap) ){
+
+ pnindex = GET_INT_FROM_POINTER(BLI_heap_popmin(heap));
+ currpn = &(Q[pnindex]);
+
+ if(currpn == (PathNode*)t->tmp.p) /*target has been reached....*/
+ break;
+
+ for(currpe=currpn->edges.first; currpe; currpe=currpe->next){
+ if(!Q[currpe->v].visited){
+ if( cost[currpe->v] > (cost[currpn->u ] + currpe->w) ){
+ cost[currpe->v] = cost[currpn->u] + currpe->w;
+ previous[currpe->v] = currpn->u;
+ Q[currpe->v].visited = 1;
+ BLI_heap_insert(heap, cost[currpe->v], SET_INT_IN_POINTER(currpe->v));
+ }
+ }
+ }
+ }
+
+ pathvert = ((PathNode*)t->tmp.p)->u;
+ while(pathvert != -1){
+ for(eve=em->verts.first; eve; eve=eve->next){
+ if(eve->f1){
+ if( ((PathNode*)eve->tmp.p)->u == pathvert) eve->f |= SELECT;
+ }
+ }
+ pathvert = previous[pathvert];
+ }
+
+ for(v=0; v < totnodes; v++) BLI_freelistN(&(Q[v].edges));
+ MEM_freeN(Q);
+ MEM_freeN(cost);
+ MEM_freeN(previous);
+ BLI_heap_free(heap, NULL);
+ EM_select_flush(em);
+ // DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+// if (EM_texFaceCheck())
+ }
+ }
+ else{
+ BKE_report(op->reports, RPT_ERROR, "Path Selection requires that exactly two vertices be selected");
+ return;
+ }
+}
+
+static int region_to_loop(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ EditEdge *eed;
+ EditFace *efa;
+
+ if(em->totfacesel){
+ for(eed=em->edges.first; eed; eed=eed->next) eed->f1 = 0;
+
+ for(efa=em->faces.first; efa; efa=efa->next){
+ if(efa->f&SELECT){
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->e4)
+ efa->e4->f1++;
+ }
+ }
+
+ EM_clear_flag_all(em, SELECT);
+
+ for(eed=em->edges.first; eed; eed=eed->next){
+ if(eed->f1 == 1) EM_select_edge(eed, 1);
+ }
+
+ em->selectmode = SCE_SELECT_EDGE;
+ EM_selectmode_set(em);
+ // DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+// if (EM_texFaceCheck())
+
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_region_to_loop(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Region to Loop";
+ ot->idname= "MESH_OT_region_to_loop";
+
+ /* api callbacks */
+ ot->exec= region_to_loop;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int validate_loop(EditMesh *em, Collection *edgecollection)
+{
+ EditEdge *eed;
+ EditFace *efa;
+ CollectedEdge *curredge;
+
+ /*1st test*/
+ for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
+ curredge->eed->v1->f1 = 0;
+ curredge->eed->v2->f1 = 0;
+ }
+ for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
+ curredge->eed->v1->f1++;
+ curredge->eed->v2->f1++;
+ }
+ for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
+ if(curredge->eed->v1->f1 > 2) return(0); else
+ if(curredge->eed->v2->f1 > 2) return(0);
+ }
+
+ /*2nd test*/
+ for(eed = em->edges.first; eed; eed=eed->next) eed->f1 = 0;
+ for(efa=em->faces.first; efa; efa=efa->next){
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->e4) efa->e4->f1++;
+ }
+ for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
+ if(curredge->eed->f1 > 2) return(0);
+ }
+ return(1);
+}
+
+static int loop_bisect(EditMesh *em, Collection *edgecollection){
+
+ EditFace *efa, *sf1, *sf2;
+ EditEdge *eed, *sed;
+ CollectedEdge *curredge;
+ int totsf1, totsf2, unbalanced,balancededges;
+
+ for(eed=em->edges.first; eed; eed=eed->next) eed->f1 = eed->f2 = 0;
+ for(efa=em->faces.first; efa; efa=efa->next) efa->f1 = 0;
+
+ for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next) curredge->eed->f1 = 1;
+
+ sf1 = sf2 = NULL;
+ sed = ((CollectedEdge*)edgecollection->collectionbase.first)->eed;
+
+ for(efa=em->faces.first; efa; efa=efa->next){
+ if(sf2) break;
+ else if(sf1){
+ if(efa->e1 == sed || efa->e2 == sed || efa->e3 == sed || ( (efa->e4) ? efa->e4 == sed : 0) ) sf2 = efa;
+ }
+ else{
+ if(efa->e1 == sed || efa->e2 == sed || efa->e3 == sed || ( (efa->e4) ? efa->e4 == sed : 0) ) sf1 = efa;
+ }
+ }
+
+ if(sf1==NULL || sf2==NULL)
+ return(-1);
+
+ if(!(sf1->e1->f1)) sf1->e1->f2 = 1;
+ if(!(sf1->e2->f1)) sf1->e2->f2 = 1;
+ if(!(sf1->e3->f1)) sf1->e3->f2 = 1;
+ if(sf1->e4 && !(sf1->e4->f1)) sf1->e4->f2 = 1;
+ sf1->f1 = 1;
+ totsf1 = 1;
+
+ if(!(sf2->e1->f1)) sf2->e1->f2 = 2;
+ if(!(sf2->e2->f1)) sf2->e2->f2 = 2;
+ if(!(sf2->e3->f1)) sf2->e3->f2 = 2;
+ if(sf2->e4 && !(sf2->e4->f1)) sf2->e4->f2 = 2;
+ sf2->f1 = 2;
+ totsf2 = 1;
+
+ /*do sf1*/
+ unbalanced = 1;
+ while(unbalanced){
+ unbalanced = 0;
+ for(efa=em->faces.first; efa; efa=efa->next){
+ balancededges = 0;
+ if(efa->f1 == 0){
+ if(efa->e1->f2 == 1 || efa->e2->f2 == 1 || efa->e3->f2 == 1 || ( (efa->e4) ? efa->e4->f2 == 1 : 0) ){
+ balancededges += efa->e1->f2 = (efa->e1->f1) ? 0 : 1;
+ balancededges += efa->e2->f2 = (efa->e2->f1) ? 0 : 1;
+ balancededges += efa->e3->f2 = (efa->e3->f1) ? 0 : 1;
+ if(efa->e4) balancededges += efa->e4->f2 = (efa->e4->f1) ? 0 : 1;
+ if(balancededges){
+ unbalanced = 1;
+ efa->f1 = 1;
+ totsf1++;
+ }
+ }
+ }
+ }
+ }
+
+ /*do sf2*/
+ unbalanced = 1;
+ while(unbalanced){
+ unbalanced = 0;
+ for(efa=em->faces.first; efa; efa=efa->next){
+ balancededges = 0;
+ if(efa->f1 == 0){
+ if(efa->e1->f2 == 2 || efa->e2->f2 == 2 || efa->e3->f2 == 2 || ( (efa->e4) ? efa->e4->f2 == 2 : 0) ){
+ balancededges += efa->e1->f2 = (efa->e1->f1) ? 0 : 2;
+ balancededges += efa->e2->f2 = (efa->e2->f1) ? 0 : 2;
+ balancededges += efa->e3->f2 = (efa->e3->f1) ? 0 : 2;
+ if(efa->e4) balancededges += efa->e4->f2 = (efa->e4->f1) ? 0 : 2;
+ if(balancededges){
+ unbalanced = 1;
+ efa->f1 = 2;
+ totsf2++;
+ }
+ }
+ }
+ }
+ }
+
+ if(totsf1 < totsf2) return(1);
+ else return(2);
+}
+
+static int loop_to_region(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+
+ EditFace *efa;
+ ListBase allcollections={NULL,NULL};
+ Collection *edgecollection;
+ int testflag;
+
+ build_edgecollection(em, &allcollections);
+
+ for(edgecollection = (Collection *)allcollections.first; edgecollection; edgecollection=edgecollection->next){
+ if(validate_loop(em, edgecollection)){
+ testflag = loop_bisect(em, edgecollection);
+ for(efa=em->faces.first; efa; efa=efa->next){
+ if(efa->f1 == testflag){
+ if(efa->f&SELECT) EM_select_face(efa, 0);
+ else EM_select_face(efa,1);
+ }
+ }
+ }
+ }
+
+ for(efa=em->faces.first; efa; efa=efa->next){ /*fix this*/
+ if(efa->f&SELECT) EM_select_face(efa,1);
+ }
+
+ freecollections(&allcollections);
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+// if (EM_texFaceCheck())
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_loop_to_region(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Loop to Region";
+ ot->idname= "MESH_OT_loop_to_region";
+
+ /* api callbacks */
+ ot->exec= loop_to_region;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+// XXX please check if these functions do what you want them to
+/* texface and vertex color editmode tools for the face menu */
+
+static int mesh_rotate_uvs(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ EditFace *efa;
+ short change = 0, ccw;
+ MTFace *tf;
+ float u1, v1;
+ int shift = 0; // XXX
+
+ if (!EM_texFaceCheck(em)) {
+ BKE_report(op->reports, RPT_ERROR, "mesh has no uv/image layers");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ ccw = (shift);
+
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ u1= tf->uv[0][0];
+ v1= tf->uv[0][1];
+
+ if (ccw) {
+ if(efa->v4) {
+ tf->uv[0][0]= tf->uv[3][0];
+ tf->uv[0][1]= tf->uv[3][1];
+
+ tf->uv[3][0]= tf->uv[2][0];
+ tf->uv[3][1]= tf->uv[2][1];
+ } else {
+ tf->uv[0][0]= tf->uv[2][0];
+ tf->uv[0][1]= tf->uv[2][1];
+ }
+
+ tf->uv[2][0]= tf->uv[1][0];
+ tf->uv[2][1]= tf->uv[1][1];
+
+ tf->uv[1][0]= u1;
+ tf->uv[1][1]= v1;
+ } else {
+ tf->uv[0][0]= tf->uv[1][0];
+ tf->uv[0][1]= tf->uv[1][1];
+
+ tf->uv[1][0]= tf->uv[2][0];
+ tf->uv[1][1]= tf->uv[2][1];
+
+ if(efa->v4) {
+ tf->uv[2][0]= tf->uv[3][0];
+ tf->uv[2][1]= tf->uv[3][1];
+
+ tf->uv[3][0]= u1;
+ tf->uv[3][1]= v1;
+ }
+ else {
+ tf->uv[2][0]= u1;
+ tf->uv[2][1]= v1;
+ }
+ }
+ change = 1;
+ }
+ }
+
+ if (change) {
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+static int mesh_mirror_uvs(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ EditFace *efa;
+ short change = 0, altaxis;
+ MTFace *tf;
+ float u1, v1;
+ int shift= 0; // XXX
+
+ if (!EM_texFaceCheck(em)) {
+ BKE_report(op->reports, RPT_ERROR, "mesh has no uv/image layers");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ altaxis = (shift);
+
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if (altaxis) {
+ u1= tf->uv[1][0];
+ v1= tf->uv[1][1];
+ if(efa->v4) {
+
+ tf->uv[1][0]= tf->uv[2][0];
+ tf->uv[1][1]= tf->uv[2][1];
+
+ tf->uv[2][0]= u1;
+ tf->uv[2][1]= v1;
+
+ u1= tf->uv[3][0];
+ v1= tf->uv[3][1];
+
+ tf->uv[3][0]= tf->uv[0][0];
+ tf->uv[3][1]= tf->uv[0][1];
+
+ tf->uv[0][0]= u1;
+ tf->uv[0][1]= v1;
+ }
+ else {
+ tf->uv[1][0]= tf->uv[2][0];
+ tf->uv[1][1]= tf->uv[2][1];
+ tf->uv[2][0]= u1;
+ tf->uv[2][1]= v1;
+ }
+
+ } else {
+ u1= tf->uv[0][0];
+ v1= tf->uv[0][1];
+ if(efa->v4) {
+
+ tf->uv[0][0]= tf->uv[1][0];
+ tf->uv[0][1]= tf->uv[1][1];
+
+ tf->uv[1][0]= u1;
+ tf->uv[1][1]= v1;
+
+ u1= tf->uv[3][0];
+ v1= tf->uv[3][1];
+
+ tf->uv[3][0]= tf->uv[2][0];
+ tf->uv[3][1]= tf->uv[2][1];
+
+ tf->uv[2][0]= u1;
+ tf->uv[2][1]= v1;
+ }
+ else {
+ tf->uv[0][0]= tf->uv[1][0];
+ tf->uv[0][1]= tf->uv[1][1];
+ tf->uv[1][0]= u1;
+ tf->uv[1][1]= v1;
+ }
+ }
+ change = 1;
+ }
+ }
+
+ if (change) {
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+static int mesh_rotate_colors(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ EditFace *efa;
+ short change = 0, ccw;
+ MCol tmpcol, *mcol;
+ int shift= 0; // XXX
+
+ if (!EM_vertColorCheck(em)) {
+ BKE_report(op->reports, RPT_ERROR, "mesh has no color layers");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ ccw = (shift);
+
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT) {
+ mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
+ tmpcol= mcol[0];
+
+ if (ccw) {
+ if(efa->v4) {
+ mcol[0]= mcol[3];
+ mcol[3]= mcol[2];
+ } else {
+ mcol[0]= mcol[2];
+ }
+ mcol[2]= mcol[1];
+ mcol[1]= tmpcol;
+ } else {
+ mcol[0]= mcol[1];
+ mcol[1]= mcol[2];
+
+ if(efa->v4) {
+ mcol[2]= mcol[3];
+ mcol[3]= tmpcol;
+ }
+ else
+ mcol[2]= tmpcol;
+ }
+ change = 1;
+ }
+ }
+
+ if (change) {
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+
+static int mesh_mirror_colors(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ EditFace *efa;
+ short change = 0, altaxis;
+ MCol tmpcol, *mcol;
+ int shift= 0; // XXX
+
+ if (!EM_vertColorCheck(em)) {
+ BKE_report(op->reports, RPT_ERROR, "Mesh has no color layers");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ altaxis = (shift);
+
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT) {
+ mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
+ if (altaxis) {
+ tmpcol= mcol[1];
+ mcol[1]= mcol[2];
+ mcol[2]= tmpcol;
+
+ if(efa->v4) {
+ tmpcol= mcol[0];
+ mcol[0]= mcol[3];
+ mcol[3]= tmpcol;
+ }
+ } else {
+ tmpcol= mcol[0];
+ mcol[0]= mcol[1];
+ mcol[1]= tmpcol;
+
+ if(efa->v4) {
+ tmpcol= mcol[2];
+ mcol[2]= mcol[3];
+ mcol[3]= tmpcol;
+ }
+ }
+ change = 1;
+ }
+ }
+
+ if (change) {
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_uvs_rotate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Rotate UVs";
+ ot->idname= "MESH_OT_uvs_rotate";
+
+ /* api callbacks */
+ ot->exec= mesh_rotate_uvs;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+void MESH_OT_uvs_mirror(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mirror UVs";
+ ot->idname= "MESH_OT_uvs_mirror";
+
+ /* api callbacks */
+ ot->exec= mesh_mirror_uvs;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+void MESH_OT_colors_rotate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Rotate Colors";
+ ot->idname= "MESH_OT_colors_rotate";
+
+ /* api callbacks */
+ ot->exec= mesh_rotate_colors;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+void MESH_OT_colors_mirror(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mirror Colors";
+ ot->idname= "MESH_OT_colors_mirror";
+
+ /* api callbacks */
+ ot->exec= mesh_mirror_colors;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int subdivide_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ esubdivideflag(obedit, em, 1, 0.0, scene->toolsettings->editbutflag, 1, 0);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_subdivide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Subdivide";
+ ot->idname= "MESH_OT_subdivide";
+
+ /* api callbacks */
+ ot->exec= subdivide_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int subdivide_multi_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ esubdivideflag(obedit, em, 1, 0.0, scene->toolsettings->editbutflag, RNA_int_get(op->ptr,"number_cuts"), 0);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_subdivide_multi(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Subdivide Multi";
+ ot->idname= "MESH_OT_subdivide_multi";
+
+ /* api callbacks */
+ ot->exec= subdivide_multi_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "number_cuts", 4, 1, 100, "Number of Cuts", "", 1, INT_MAX);
+}
+
+static int subdivide_multi_fractal_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ esubdivideflag(obedit, em, 1, -(RNA_float_get(op->ptr, "random_factor")/100), scene->toolsettings->editbutflag, RNA_int_get(op->ptr, "number_cuts"), 0);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_subdivide_multi_fractal(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Subdivide Multi Fractal";
+ ot->idname= "MESH_OT_subdivide_multi_fractal";
+
+ /* api callbacks */
+ ot->exec= subdivide_multi_fractal_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "number_cuts", 4, 1, 100, "Number of Cuts", "", 1, INT_MAX);
+ RNA_def_float(ot->srna, "random_factor", 5.0, 0.0f, FLT_MAX, "Random Factor", "", 0.0f, 1000.0f);
+}
+
+static int subdivide_smooth_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ esubdivideflag(obedit, em, 1, 0.292f*RNA_float_get(op->ptr, "smoothness"), scene->toolsettings->editbutflag | B_SMOOTH, 1, 0);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_subdivide_smooth(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Subdivide Smooth";
+ ot->idname= "MESH_OT_subdivide_smooth";
+
+ /* api callbacks */
+ ot->exec= subdivide_smooth_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_float(ot->srna, "smoothness", 1.0f, 0.0f, 1000.0f, "Smoothness", "", 0.0f, FLT_MAX);
+}
+
+static int subdivs_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ uiMenuItem *head;
+
+ head= uiPupMenuBegin("Subdivision Type", 0);
+ uiMenuItemsEnumO(head, "MESH_OT_subdivs", "type");
+ uiPupMenuEnd(C, head);
+
+ return OPERATOR_CANCELLED;
+}
+
+static int subdivs_exec(bContext *C, wmOperator *op)
+{
+ switch(RNA_int_get(op->ptr, "type"))
+ {
+ case 0: // simple
+ subdivide_exec(C,op);
+ break;
+ case 1: // multi
+ subdivide_multi_exec(C,op);
+ break;
+ case 2: // fractal;
+ subdivide_multi_fractal_exec(C,op);
+ break;
+ case 3: //smooth
+ subdivide_smooth_exec(C,op);
+ break;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_subdivs(wmOperatorType *ot)
+{
+ static EnumPropertyItem type_items[]= {
+ {0, "SIMPLE", "Simple", ""},
+ {1, "MULTI", "Multi", ""},
+ {2, "FRACTAL", "Fractal", ""},
+ {3, "SMOOTH", "Smooth", ""},
+ {0, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "subdivs";
+ ot->idname= "MESH_OT_subdivs";
+
+ /* api callbacks */
+ ot->invoke= subdivs_invoke;
+ ot->exec= subdivs_exec;
+
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /*props */
+ RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
+
+ /* this is temp, the ops are different, but they are called from subdivs, so all the possible props should be here as well*/
+ RNA_def_int(ot->srna, "number_cuts", 4, 1, 10, "Number of Cuts", "", 1, INT_MAX);
+ RNA_def_float(ot->srna, "random_factor", 5.0, 0.0f, FLT_MAX, "Random Factor", "", 0.0f, 1000.0f);
+ RNA_def_float(ot->srna, "smoothness", 1.0f, 0.0f, 1000.0f, "Smoothness", "", 0.0f, FLT_MAX);
+
+}
+
+/* ************************************* */
+
+/* note; the EM_selectmode_set() calls here illustrate how badly constructed it all is... from before the
+edge/face flags, with very mixed results.... */
+static void beauty_fill(EditMesh *em)
+{
+ EditVert *v1, *v2, *v3, *v4;
+ EditEdge *eed, *nexted;
+ EditEdge dia1, dia2;
+ EditFace *efa, *w;
+ // void **efaar, **efaa;
+ EVPTuple *efaar;
+ EVPtr *efaa;
+ float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2;
+ int totedge, ok, notbeauty=8, onedone, vindex[4];
+
+ /* - all selected edges with two faces
+ * - find the faces: store them in edges (using datablock)
+ * - per edge: - test convex
+ * - test edge: flip?
+ * - if true: remedge, addedge, all edges at the edge get new face pointers
+ */
+
+ EM_selectmode_set(em); // makes sure in selectmode 'face' the edges of selected faces are selected too
+
+ totedge = count_selected_edges(em->edges.first);
+ if(totedge==0) return;
+
+ /* temp block with face pointers */
+ efaar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "beautyfill");
+
+ while (notbeauty) {
+ notbeauty--;
+
+ ok = collect_quadedges(efaar, em->edges.first, em->faces.first);
+
+ /* there we go */
+ onedone= 0;
+
+ eed= em->edges.first;
+ while(eed) {
+ nexted= eed->next;
+
+ /* f2 is set in collect_quadedges() */
+ if(eed->f2==2 && eed->h==0) {
+
+ efaa = (EVPtr *) eed->tmp.p;
+
+ /* none of the faces should be treated before, nor be part of fgon */
+ ok= 1;
+ efa= efaa[0];
+ if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
+ if(efa->fgonf) ok= 0;
+ efa= efaa[1];
+ if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
+ if(efa->fgonf) ok= 0;
+
+ if(ok) {
+ /* test convex */
+ givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
+ if(v1 && v2 && v3 && v4) {
+ if( convex(v1->co, v2->co, v3->co, v4->co) ) {
+
+ /* test edges */
+ if( (v1) > (v3) ) {
+ dia1.v1= v3;
+ dia1.v2= v1;
+ }
+ else {
+ dia1.v1= v1;
+ dia1.v2= v3;
+ }
+
+ if( (v2) > (v4) ) {
+ dia2.v1= v4;
+ dia2.v2= v2;
+ }
+ else {
+ dia2.v1= v2;
+ dia2.v2= v4;
+ }
+
+ /* testing rule:
+ * the area divided by the total edge lengths
+ */
+
+ len1= VecLenf(v1->co, v2->co);
+ len2= VecLenf(v2->co, v3->co);
+ len3= VecLenf(v3->co, v4->co);
+ len4= VecLenf(v4->co, v1->co);
+ len5= VecLenf(v1->co, v3->co);
+ len6= VecLenf(v2->co, v4->co);
+
+ opp1= AreaT3Dfl(v1->co, v2->co, v3->co);
+ opp2= AreaT3Dfl(v1->co, v3->co, v4->co);
+
+ fac1= opp1/(len1+len2+len5) + opp2/(len3+len4+len5);
+
+ opp1= AreaT3Dfl(v2->co, v3->co, v4->co);
+ opp2= AreaT3Dfl(v2->co, v4->co, v1->co);
+
+ fac2= opp1/(len2+len3+len6) + opp2/(len4+len1+len6);
+
+ ok= 0;
+ if(fac1 > fac2) {
+ if(dia2.v1==eed->v1 && dia2.v2==eed->v2) {
+ eed->f1= 1;
+ efa= efaa[0];
+ efa->f1= 1;
+ efa= efaa[1];
+ efa->f1= 1;
+
+ w= EM_face_from_faces(em, efaa[0], efaa[1],
+ vindex[0], vindex[1], 4+vindex[2], -1);
+ w->f |= SELECT;
+
+
+ w= EM_face_from_faces(em, efaa[0], efaa[1],
+ vindex[0], 4+vindex[2], 4+vindex[3], -1);
+ w->f |= SELECT;
+
+ onedone= 1;
+ }
+ }
+ else if(fac1 < fac2) {
+ if(dia1.v1==eed->v1 && dia1.v2==eed->v2) {
+ eed->f1= 1;
+ efa= efaa[0];
+ efa->f1= 1;
+ efa= efaa[1];
+ efa->f1= 1;
+
+
+ w= EM_face_from_faces(em, efaa[0], efaa[1],
+ vindex[1], 4+vindex[2], 4+vindex[3], -1);
+ w->f |= SELECT;
+
+
+ w= EM_face_from_faces(em, efaa[0], efaa[1],
+ vindex[0], 4+vindex[1], 4+vindex[3], -1);
+ w->f |= SELECT;
+
+ onedone= 1;
+ }
+ }
+ }
+ }
+ }
+
+ }
+ eed= nexted;
+ }
+
+ free_tagged_edges_faces(em, em->edges.first, em->faces.first);
+
+ if(onedone==0) break;
+
+ EM_selectmode_set(em); // new edges/faces were added
+ }
+
+ MEM_freeN(efaar);
+
+ EM_select_flush(em);
+
+}
+
+/* Got this from scanfill.c. You will need to juggle around the
+* callbacks for the scanfill.c code a bit for this to work. */
+static void fill_mesh(EditMesh *em)
+{
+ EditVert *eve,*v1;
+ EditEdge *eed,*e1,*nexted;
+ EditFace *efa,*nextvl, *efan;
+ short ok;
+
+ if(em==NULL) return;
+ waitcursor(1);
+
+ /* copy all selected vertices */
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f & SELECT) {
+ v1= BLI_addfillvert(eve->co);
+ eve->tmp.v= v1;
+ v1->tmp.v= eve;
+ v1->xs= 0; // used for counting edges
+ }
+ eve= eve->next;
+ }
+ /* copy all selected edges */
+ eed= em->edges.first;
+ while(eed) {
+ if( (eed->v1->f & SELECT) && (eed->v2->f & SELECT) ) {
+ e1= BLI_addfilledge(eed->v1->tmp.v, eed->v2->tmp.v);
+ e1->v1->xs++;
+ e1->v2->xs++;
+ }
+ eed= eed->next;
+ }
+ /* from all selected faces: remove vertices and edges to prevent doubles */
+ /* all edges add values, faces subtract,
+ then remove edges with vertices ->xs<2 */
+ efa= em->faces.first;
+ ok= 0;
+ while(efa) {
+ nextvl= efa->next;
+ if( faceselectedAND(efa, 1) ) {
+ efa->v1->tmp.v->xs--;
+ efa->v2->tmp.v->xs--;
+ efa->v3->tmp.v->xs--;
+ if(efa->v4) efa->v4->tmp.v->xs--;
+ ok= 1;
+
+ }
+ efa= nextvl;
+ }
+ if(ok) { /* there are faces selected */
+ eed= filledgebase.first;
+ while(eed) {
+ nexted= eed->next;
+ if(eed->v1->xs<2 || eed->v2->xs<2) {
+ BLI_remlink(&filledgebase,eed);
+ }
+ eed= nexted;
+ }
+ }
+
+ if(BLI_edgefill(0, em->mat_nr)) {
+ efa= fillfacebase.first;
+ while(efa) {
+ /* normals default pointing up */
+ efan= addfacelist(em, efa->v3->tmp.v, efa->v2->tmp.v,
+ efa->v1->tmp.v, 0, NULL, NULL);
+ if(efan) EM_select_face(efan, 1);
+ efa= efa->next;
+ }
+ }
+
+ BLI_end_edgefill();
+ beauty_fill(em);
+
+ WM_cursor_wait(0);
+ EM_select_flush(em);
+
+}
+
+
+static int fill_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ fill_mesh(em);
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+
+}
+
+void MESH_OT_fill(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Fill Mesh";
+ ot->idname= "MESH_OT_fill";
+
+ /* api callbacks */
+ ot->exec= fill_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int beauty_fill_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ beauty_fill(em);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_beauty_fill(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Beauty Fill";
+ ot->idname= "MESH_OT_beauty_fill";
+
+ /* api callbacks */
+ ot->exec= beauty_fill_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int quads_convert_to_tris_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ convert_to_triface(em,0);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_quads_convert_to_tris(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Quads to Tris";
+ ot->idname= "MESH_OT_quads_convert_to_tris";
+
+ /* api callbacks */
+ ot->exec= quads_convert_to_tris_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int tris_convert_to_quads_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ join_triangles(em);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_tris_convert_to_quads(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Tris to Quads";
+ ot->idname= "MESH_OT_tris_convert_to_quads";
+
+ /* api callbacks */
+ ot->exec= tris_convert_to_quads_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int edge_flip_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ edge_flip(em);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_edge_flip(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Edge Flip";
+ ot->idname= "MESH_OT_edge_flip";
+
+ /* api callbacks */
+ ot->exec= edge_flip_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int mesh_faces_shade_smooth_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ mesh_set_smooth_faces(em,1);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_faces_shade_smooth(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Smooth Face Shading";
+ ot->idname= "MESH_OT_faces_shade_smooth";
+
+ /* api callbacks */
+ ot->exec= mesh_faces_shade_smooth_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int mesh_faces_shade_solid_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ mesh_set_smooth_faces(em,0);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_faces_shade_solid(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Flat Face Shading";
+ ot->idname= "MESH_OT_faces_shade_solid";
+
+ /* api callbacks */
+ ot->exec= mesh_faces_shade_solid_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
new file mode 100644
index 00000000000..f7d2fcfc1f2
--- /dev/null
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -0,0 +1,237 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* Internal for editmesh_xxxx.c functions */
+
+#ifndef MESH_INTERN_H
+#define MESH_INTERN_H
+
+struct bContext;
+struct wmOperatorType;
+
+#define UVCOPY(t, s) memcpy(t, s, 2 * sizeof(float));
+
+/* ******************** editface.c */
+
+int edgetag_context_check(Scene *scene, EditEdge *eed);
+void edgetag_context_set(Scene *scene, EditEdge *eed, int val);
+int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge *target);
+
+/* ******************* editmesh.c */
+
+extern void free_editvert(EditMesh *em, EditVert *eve);
+extern void free_editedge(EditMesh *em, EditEdge *eed);
+extern void free_editface(EditMesh *em, EditFace *efa);
+void free_editMesh(EditMesh *em);
+
+extern void free_vertlist(EditMesh *em, ListBase *edve);
+extern void free_edgelist(EditMesh *em, ListBase *lb);
+extern void free_facelist(EditMesh *em, ListBase *lb);
+
+extern void remedge(EditMesh *em, EditEdge *eed);
+
+extern struct EditVert *addvertlist(EditMesh *em, float *vec, struct EditVert *example);
+extern struct EditEdge *addedgelist(EditMesh *em, struct EditVert *v1, struct EditVert *v2, struct EditEdge *example);
+extern struct EditFace *addfacelist(EditMesh *em, struct EditVert *v1, struct EditVert *v2, struct EditVert *v3, struct EditVert *v4, struct EditFace *example, struct EditFace *exampleEdges);
+extern struct EditEdge *findedgelist(EditMesh *em, struct EditVert *v1, struct EditVert *v2);
+
+EditVert *editedge_getOtherVert(EditEdge *eed, EditVert *eve);
+EditVert *editedge_getSharedVert(EditEdge *eed, EditEdge *eed2);
+int editedge_containsVert(struct EditEdge *eed, struct EditVert *eve);
+int editface_containsVert(struct EditFace *efa, struct EditVert *eve);
+int editface_containsEdge(struct EditFace *efa, struct EditEdge *eed);
+
+void em_setup_viewcontext(struct bContext *C, ViewContext *vc);
+
+void MESH_OT_separate(struct wmOperatorType *ot);
+
+/* ******************* editmesh_add.c */
+void MESH_OT_primitive_plane_add(struct wmOperatorType *ot);
+void MESH_OT_primitive_cube_add(struct wmOperatorType *ot);
+void MESH_OT_primitive_circle_add(struct wmOperatorType *ot);
+void MESH_OT_primitive_cylinder_add(struct wmOperatorType *ot);
+void MESH_OT_primitive_tube_add(struct wmOperatorType *ot);
+void MESH_OT_primitive_cone_add(struct wmOperatorType *ot);
+void MESH_OT_primitive_grid_add(struct wmOperatorType *ot);
+void MESH_OT_primitive_monkey_add(struct wmOperatorType *ot);
+void MESH_OT_primitive_uv_sphere_add(struct wmOperatorType *ot);
+void MESH_OT_primitive_ico_sphere_add(struct wmOperatorType *ot);
+void MESH_OT_dupli_extrude_cursor(struct wmOperatorType *ot);
+void MESH_OT_edge_face_add(struct wmOperatorType *ot);
+
+void MESH_OT_fgon_make(struct wmOperatorType *ot);
+void MESH_OT_fgon_clear(struct wmOperatorType *ot);
+
+/* ******************* editmesh_lib.c */
+void EM_stats_update(EditMesh *em);
+
+extern void EM_fgon_flags(EditMesh *em);
+extern void EM_hide_reset(EditMesh *em);
+
+extern int faceselectedOR(EditFace *efa, int flag);
+extern int faceselectedAND(EditFace *efa, int flag);
+
+void EM_remove_selection(EditMesh *em, void *data, int type);
+void EM_clear_flag_all(EditMesh *em, int flag);
+void EM_set_flag_all(EditMesh *em, int flag);
+
+void EM_data_interp_from_verts(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *eve, float fac);
+void EM_data_interp_from_faces(EditMesh *em, EditFace *efa1, EditFace *efa2, EditFace *efan, int i1, int i2, int i3, int i4);
+
+int EM_nvertices_selected(EditMesh *em);
+int EM_nedges_selected(EditMesh *em);
+int EM_nfaces_selected(EditMesh *em);
+
+float EM_face_perimeter(EditFace *efa);
+
+void EM_store_selection(EditMesh *em, void *data, int type);
+
+extern EditFace *exist_face(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4);
+extern void flipface(EditMesh *em, EditFace *efa); // flips for normal direction
+extern int compareface(EditFace *vl1, EditFace *vl2);
+
+/* flag for selection bits, *nor will be filled with normal for extrusion constraint */
+/* return value defines if such normal was set */
+extern short extrudeflag_face_indiv(EditMesh *em, short flag, float *nor);
+extern short extrudeflag_verts_indiv(EditMesh *em, short flag, float *nor);
+extern short extrudeflag_edges_indiv(EditMesh *em, short flag, float *nor);
+extern short extrudeflag_vert(Object *obedit, EditMesh *em, short flag, float *nor);
+extern short extrudeflag(Object *obedit, EditMesh *em, short flag, float *nor);
+
+extern void adduplicateflag(EditMesh *em, int flag);
+extern void delfaceflag(EditMesh *em, int flag);
+
+extern void rotateflag(EditMesh *em, short flag, float *cent, float rotmat[][3]);
+extern void translateflag(EditMesh *em, short flag, float *vec);
+
+extern int convex(float *v1, float *v2, float *v3, float *v4);
+
+extern struct EditFace *EM_face_from_faces(EditMesh *em, struct EditFace *efa1,
+ struct EditFace *efa2, int i1, int i2, int i3, int i4);
+
+
+/* ******************* editmesh_loop.c */
+
+#define LOOP_SELECT 1
+#define LOOP_CUT 2
+
+void MESH_OT_knife_cut(struct wmOperatorType *ot);
+
+/* ******************* editmesh_mods.c */
+void MESH_OT_loop_select(struct wmOperatorType *ot);
+void MESH_OT_select_all_toggle(struct wmOperatorType *ot);
+void MESH_OT_select_more(struct wmOperatorType *ot);
+void MESH_OT_select_less(struct wmOperatorType *ot);
+void MESH_OT_select_invert(struct wmOperatorType *ot);
+void MESH_OT_select_non_manifold(struct wmOperatorType *ot);
+void MESH_OT_select_linked(struct wmOperatorType *ot);
+void MESH_OT_select_linked_pick(struct wmOperatorType *ot);
+void MESH_OT_hide(struct wmOperatorType *ot);
+void MESH_OT_reveal(struct wmOperatorType *ot);
+void MESH_OT_normals_make_consistent(struct wmOperatorType *ot);
+void MESH_OT_faces_select_linked_flat(struct wmOperatorType *ot);
+void MESH_OT_edges_select_sharp(struct wmOperatorType *ot);
+void MESH_OT_select_shortest_path(struct wmOperatorType *ot);
+void MESH_OT_vertices_select_similar(struct wmOperatorType *ot);
+void MESH_OT_edges_select_similar(struct wmOperatorType *ot);
+void MESH_OT_faces_select_similar(struct wmOperatorType *ot);
+void MESH_OT_select_random(struct wmOperatorType *ot);
+void MESH_OT_vertices_transform_to_sphere(struct wmOperatorType *ot);
+void MESH_OT_selection_type(struct wmOperatorType *ot);
+void MESH_OT_loop_multi_select(struct wmOperatorType *ot);
+void MESH_OT_mark_seam(struct wmOperatorType *ot);
+void MESH_OT_mark_sharp(struct wmOperatorType *ot);
+void MESH_OT_vertices_smooth(struct wmOperatorType *ot);
+void MESH_OT_flip_editnormals(struct wmOperatorType *ot);
+
+extern EditEdge *findnearestedge(ViewContext *vc, int *dist);
+extern void EM_automerge(int update);
+void editmesh_select_by_material(EditMesh *em, int index);
+void righthandfaces(EditMesh *em, int select); /* makes faces righthand turning */
+void EM_select_more(EditMesh *em);
+void selectconnected_mesh_all(EditMesh *em);
+void faceloop_select(EditMesh *em, EditEdge *startedge, int select);
+
+/**
+ * findnearestvert
+ *
+ * dist (in/out): minimal distance to the nearest and at the end, actual distance
+ * sel: selection bias
+ * if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts
+ * if 0, unselected vertice are given the bias
+ * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased
+ */
+extern EditVert *findnearestvert(ViewContext *vc, int *dist, short sel, short strict);
+
+
+/* ******************* editmesh_tools.c */
+
+#define SUBDIV_SELECT_ORIG 0
+#define SUBDIV_SELECT_INNER 1
+#define SUBDIV_SELECT_INNER_SEL 2
+#define SUBDIV_SELECT_LOOPCUT 3
+
+void join_triangles(EditMesh *em);
+int removedoublesflag(EditMesh *em, short flag, short automerge, float limit); /* return amount */
+void esubdivideflag(Object *obedit, EditMesh *em, int flag, float rad, int beauty, int numcuts, int seltype);
+int EdgeSlide(EditMesh *em, wmOperator *op, short immediate, float imperc);
+
+void MESH_OT_subdivide(struct wmOperatorType *ot);
+void MESH_OT_subdivs(struct wmOperatorType *ot);
+void MESH_OT_subdivide_multi(struct wmOperatorType *ot);
+void MESH_OT_subdivide_multi_fractal(struct wmOperatorType *ot);
+void MESH_OT_subdivide_smooth(struct wmOperatorType *ot);
+void MESH_OT_remove_doubles(struct wmOperatorType *ot);
+void MESH_OT_extrude(struct wmOperatorType *ot);
+void MESH_OT_spin(struct wmOperatorType *ot);
+void MESH_OT_screw(struct wmOperatorType *ot);
+
+void MESH_OT_fill(struct wmOperatorType *ot);
+void MESH_OT_beauty_fill(struct wmOperatorType *ot);
+void MESH_OT_quads_convert_to_tris(struct wmOperatorType *ot);
+void MESH_OT_tris_convert_to_quads(struct wmOperatorType *ot);
+void MESH_OT_edge_flip(struct wmOperatorType *ot);
+void MESH_OT_faces_shade_smooth(struct wmOperatorType *ot);
+void MESH_OT_faces_shade_solid(struct wmOperatorType *ot);
+void MESH_OT_split(struct wmOperatorType *ot);
+void MESH_OT_extrude_repeat(struct wmOperatorType *ot);
+void MESH_OT_edge_rotate(struct wmOperatorType *ot);
+void MESH_OT_loop_to_region(struct wmOperatorType *ot);
+void MESH_OT_region_to_loop(struct wmOperatorType *ot);
+
+void MESH_OT_uvs_rotate(struct wmOperatorType *ot);
+void MESH_OT_uvs_mirror(struct wmOperatorType *ot);
+void MESH_OT_colors_rotate(struct wmOperatorType *ot);
+void MESH_OT_colors_mirror(struct wmOperatorType *ot);
+
+void MESH_OT_delete(struct wmOperatorType *ot);
+void MESH_OT_rip(struct wmOperatorType *ot);
+
+#endif // MESH_INTERN_H
+
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
new file mode 100644
index 00000000000..5a86180a60f
--- /dev/null
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -0,0 +1,296 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_mesh.h"
+#include "ED_view3d.h"
+
+#include "BIF_transform.h"
+
+#include "mesh_intern.h"
+
+
+static int mesh_add_duplicate_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh(ob->data);
+
+ adduplicateflag(em, SELECT);
+
+ BKE_mesh_end_editmesh(ob->data, em);
+ return OPERATOR_FINISHED;
+}
+
+static int mesh_add_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ WM_cursor_wait(1);
+ mesh_add_duplicate_exec(C, op);
+ WM_cursor_wait(0);
+
+ RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
+ WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+ return OPERATOR_FINISHED;
+}
+
+static void MESH_OT_duplicate_add(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Add Duplicate";
+ ot->idname= "MESH_OT_duplicate_add";
+
+ /* api callbacks */
+ ot->invoke= mesh_add_duplicate_invoke;
+ ot->exec= mesh_add_duplicate_exec;
+
+ ot->poll= ED_operator_editmesh;
+
+ /* to give to transform */
+ RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+}
+
+
+/* ************************** registration **********************************/
+
+void ED_operatortypes_mesh(void)
+{
+ WM_operatortype_append(MESH_OT_select_all_toggle);
+ WM_operatortype_append(MESH_OT_select_more);
+ WM_operatortype_append(MESH_OT_select_less);
+ WM_operatortype_append(MESH_OT_select_invert);
+ WM_operatortype_append(MESH_OT_select_non_manifold);
+ WM_operatortype_append(MESH_OT_select_linked);
+ WM_operatortype_append(MESH_OT_select_linked_pick);
+ WM_operatortype_append(MESH_OT_select_random);
+ WM_operatortype_append(MESH_OT_selection_type);
+ WM_operatortype_append(MESH_OT_hide);
+ WM_operatortype_append(MESH_OT_reveal);
+ WM_operatortype_append(MESH_OT_normals_make_consistent);
+ WM_operatortype_append(MESH_OT_subdivide);
+ WM_operatortype_append(MESH_OT_subdivide_multi);
+ WM_operatortype_append(MESH_OT_subdivide_multi_fractal);
+ WM_operatortype_append(MESH_OT_subdivide_smooth);
+ WM_operatortype_append(MESH_OT_subdivs);
+ WM_operatortype_append(MESH_OT_faces_select_linked_flat);
+ WM_operatortype_append(MESH_OT_edges_select_sharp);
+ WM_operatortype_append(MESH_OT_primitive_plane_add);
+ WM_operatortype_append(MESH_OT_primitive_cube_add);
+ WM_operatortype_append(MESH_OT_primitive_circle_add);
+ WM_operatortype_append(MESH_OT_primitive_cylinder_add);
+ WM_operatortype_append(MESH_OT_primitive_tube_add);
+ WM_operatortype_append(MESH_OT_primitive_cone_add);
+ WM_operatortype_append(MESH_OT_primitive_grid_add);
+ WM_operatortype_append(MESH_OT_primitive_monkey_add);
+ WM_operatortype_append(MESH_OT_primitive_uv_sphere_add);
+ WM_operatortype_append(MESH_OT_primitive_ico_sphere_add);
+ WM_operatortype_append(MESH_OT_fgon_clear);
+ WM_operatortype_append(MESH_OT_fgon_make);
+ WM_operatortype_append(MESH_OT_duplicate_add);
+ WM_operatortype_append(MESH_OT_remove_doubles);
+ WM_operatortype_append(MESH_OT_extrude);
+ WM_operatortype_append(MESH_OT_spin);
+ WM_operatortype_append(MESH_OT_screw);
+
+ WM_operatortype_append(MESH_OT_vertices_transform_to_sphere);
+ WM_operatortype_append(MESH_OT_split);
+ WM_operatortype_append(MESH_OT_extrude_repeat);
+ WM_operatortype_append(MESH_OT_edge_rotate);
+ WM_operatortype_append(MESH_OT_loop_to_region);
+ WM_operatortype_append(MESH_OT_region_to_loop);
+
+ WM_operatortype_append(MESH_OT_uvs_rotate);
+ WM_operatortype_append(MESH_OT_uvs_mirror);
+ WM_operatortype_append(MESH_OT_colors_rotate);
+ WM_operatortype_append(MESH_OT_colors_mirror);
+
+ WM_operatortype_append(MESH_OT_fill);
+ WM_operatortype_append(MESH_OT_beauty_fill);
+ WM_operatortype_append(MESH_OT_quads_convert_to_tris);
+ WM_operatortype_append(MESH_OT_tris_convert_to_quads);
+ WM_operatortype_append(MESH_OT_edge_flip);
+ WM_operatortype_append(MESH_OT_faces_shade_smooth);
+ WM_operatortype_append(MESH_OT_faces_shade_solid);
+
+ WM_operatortype_append(MESH_OT_delete);
+
+ WM_operatortype_append(MESH_OT_separate);
+ WM_operatortype_append(MESH_OT_dupli_extrude_cursor);
+ WM_operatortype_append(MESH_OT_loop_select);
+ WM_operatortype_append(MESH_OT_edge_face_add);
+ WM_operatortype_append(MESH_OT_select_shortest_path);
+ WM_operatortype_append(MESH_OT_vertices_select_similar);
+ WM_operatortype_append(MESH_OT_edges_select_similar);
+ WM_operatortype_append(MESH_OT_faces_select_similar);
+ WM_operatortype_append(MESH_OT_loop_multi_select);
+ WM_operatortype_append(MESH_OT_mark_seam);
+ WM_operatortype_append(MESH_OT_mark_sharp);
+ WM_operatortype_append(MESH_OT_vertices_smooth);
+ WM_operatortype_append(MESH_OT_flip_editnormals);
+ WM_operatortype_append(MESH_OT_knife_cut);
+ WM_operatortype_append(MESH_OT_rip);
+
+}
+
+/* note mesh keymap also for other space? */
+void ED_keymap_mesh(wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "EditMesh", 0, 0);
+ wmKeymapItem *kmi;
+
+ /* selecting */
+ /* standard mouse selection goes via space_view3d */
+ WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
+ kmi= WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_SHIFT|KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+ kmi= WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_ALT|KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "ring", 1);
+ kmi= WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_SHIFT|KM_ALT|KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+ RNA_boolean_set(kmi->ptr, "ring", 1);
+
+ WM_keymap_add_item(keymap, "MESH_OT_select_shortest_path", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "MESH_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_select_invert", IKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_select_non_manifold", MKEY, KM_PRESS, (KM_CTRL|KM_SHIFT|KM_ALT), 0);
+
+ WM_keymap_add_item(keymap, "MESH_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_select_linked_pick", LKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_select_linked_pick", LKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "deselect", 1);
+
+ RNA_float_set(WM_keymap_add_item(keymap, "MESH_OT_faces_select_linked_flat", FKEY, KM_PRESS, (KM_CTRL|KM_SHIFT|KM_ALT), 0)->ptr,"sharpness",135.0);
+ RNA_float_set(WM_keymap_add_item(keymap, "MESH_OT_edges_select_sharp", SKEY, KM_PRESS, (KM_CTRL|KM_SHIFT|KM_ALT), 0)->ptr,"sharpness",135.0);
+
+ WM_keymap_add_item(keymap, "MESH_OT_select_random", SPACEKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_vertices_transform_to_sphere", SKEY, KM_PRESS, KM_CTRL|KM_SHIFT , 0);
+
+ WM_keymap_add_item(keymap, "MESH_OT_mark_seam", ONEKEY, KM_PRESS, KM_CTRL , 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_mark_seam", ONEKEY, KM_PRESS, KM_ALT , 0)->ptr,"clear",1);
+
+ WM_keymap_add_item(keymap, "MESH_OT_mark_sharp", TWOKEY, KM_PRESS, KM_CTRL , 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_mark_sharp", TWOKEY, KM_PRESS, KM_ALT , 0)->ptr,"set",1);
+
+ /* temp hotkeys! */
+ WM_keymap_add_item(keymap, "MESH_OT_vertices_select_similar", GKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_edges_select_similar", GKEY, KM_PRESS, KM_SHIFT2|KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_faces_select_similar", GKEY, KM_PRESS, KM_SHIFT|KM_CTRL2, 0);
+
+ /* selection mode */
+ WM_keymap_add_item(keymap, "MESH_OT_selection_type", TABKEY, KM_PRESS, KM_CTRL, 0);
+
+ /* hide */
+ WM_keymap_add_item(keymap, "MESH_OT_hide", HKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "unselected", 1);
+ WM_keymap_add_item(keymap, "MESH_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
+
+ /* tools */
+ WM_keymap_add_item(keymap, "MESH_OT_normals_make_consistent", NKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_normals_make_consistent", NKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0)->ptr, "inside", 1);
+ WM_keymap_add_item(keymap, "MESH_OT_vertices_smooth", THREEKEY, KM_PRESS, KM_CTRL , 0);
+ WM_keymap_add_item(keymap, "MESH_OT_flip_editnormals", THREEKEY, KM_PRESS, KM_ALT , 0);
+
+ WM_keymap_add_item(keymap, "MESH_OT_subdivs", WKEY, KM_PRESS, 0, 0); // this is the menu
+ /*WM_keymap_add_item(keymap, "MESH_OT_subdivide_multi", WKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_subdivide_multi_fractal", WKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_subdivide_smooth", WKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);*/
+ WM_keymap_add_item(keymap, "MESH_OT_remove_doubles", VKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_extrude", EKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "MESH_OT_spin", RKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_screw", NINEKEY, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "VIEW3D_OT_editmesh_face_toolbox", FKEY, KM_PRESS, KM_CTRL, 0); /* operators below are in this toolbox */
+ WM_keymap_add_item(keymap, "MESH_OT_fill", FKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_beauty_fill", FKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_quads_convert_to_tris", TKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_tris_convert_to_quads", JKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "MESH_OT_split", FOURKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_extrude_repeat", FOURKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_edge_rotate", FIVEKEY, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "MESH_OT_loop_to_region",SIXKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_region_to_loop",SIXKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "MESH_OT_uvs_rotate",SEVENKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_uvs_mirror",SEVENKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_colors_rotate",EIGHTKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_colors_mirror",EIGHTKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "MESH_OT_rip",VKEY, KM_PRESS, 0, 0);
+
+ /* add/remove */
+ WM_keymap_add_item(keymap, "MESH_OT_edge_face_add", FKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_duplicate_add", DKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "OBJECT_OT_mesh_add", AKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_separate", PKEY, KM_PRESS, KM_SHIFT, 0);
+ /* use KM_RELEASE because same key is used for tweaks */
+ WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", LEFTMOUSE, KM_RELEASE, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "MESH_OT_delete", XKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "MESH_OT_fgon_make", FKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_fgon_clear", FKEY, KM_PRESS, KM_SHIFT|KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, KM_ALT|KM_CTRL, 0);
+
+ /* UV's */
+ WM_keymap_add_item(keymap, "UV_OT_mapping_menu", UKEY, KM_PRESS, 0, 0);
+}
+
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
new file mode 100644
index 00000000000..d835fdb8eed
--- /dev/null
+++ b/source/blender/editors/mesh/meshtools.c
@@ -0,0 +1,1135 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 by Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/*
+ meshtools.c: no editmode (violated already :), tools operating on meshes
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_image_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_material_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_ghash.h"
+#include "BLI_rand.h" /* for randome face sorting */
+#include "BLI_threads.h"
+
+
+#include "BKE_blender.h"
+#include "BKE_depsgraph.h"
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+#include "BKE_report.h"
+
+#include "RE_pipeline.h"
+#include "RE_shader_ext.h"
+
+#include "PIL_time.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "GPU_draw.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+#include "ED_mesh.h"
+#include "ED_object.h"
+#include "ED_view3d.h"
+
+/* own include */
+#include "mesh_intern.h"
+
+
+/* from rendercode.c */
+#define VECMUL(dest, f) dest[0]*= f; dest[1]*= f; dest[2]*= f
+
+/* XXX */
+static void BIF_undo_push() {}
+static void waitcursor() {}
+static void error() {}
+static int pupmenu() {return 0;}
+/* XXX */
+
+
+/* * ********************** no editmode!!! *********** */
+
+/* join selected meshes into the active mesh, context sensitive
+return 0 if no join is made (error) and 1 of the join is done */
+int join_mesh(Scene *scene, View3D *v3d, wmOperator *op)
+{
+ Base *base, *nextb;
+ Object *ob;
+ Material **matar, *ma;
+ Mesh *me;
+ MVert *mvert, *mvertmain;
+ MEdge *medge = NULL, *medgemain;
+ MFace *mface = NULL, *mfacemain;
+ float imat[4][4], cmat[4][4];
+ int a, b, totcol, totedge=0, totvert=0, totface=0, ok=0, vertofs, map[MAXMAT];
+ int i, j, index, haskey=0, hasmulti=0, edgeofs, faceofs;
+ bDeformGroup *dg, *odg;
+ MDeformVert *dvert;
+ CustomData vdata, edata, fdata;
+
+ if(scene->obedit) return 0;
+
+ ob= OBACT;
+ if(!ob || ob->type!=OB_MESH) return 0;
+
+ if (object_data_is_libdata(ob)) {
+// XXX error_libdata();
+ return 0;
+ }
+
+ /* count & check */
+ base= FIRSTBASE;
+ while(base) {
+ if(TESTBASELIB_BGMODE(base)) { /* BGMODE since python can access */
+ if(base->object->type==OB_MESH) {
+ me= base->object->data;
+ totvert+= me->totvert;
+ totface+= me->totface;
+
+ if(base->object == ob) ok= 1;
+
+ if(me->key) {
+ haskey= 1;
+ break;
+ }
+ if(me->mr) {
+ hasmulti= 1;
+ break;
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ if(haskey) {
+ BKE_report(op->reports, RPT_ERROR, "Can't join meshes with vertex keys");
+ return 0;
+ }
+ if(hasmulti) {
+ BKE_report(op->reports, RPT_ERROR, "Can't join meshes with Multires");
+ return 0;
+ }
+ /* that way the active object is always selected */
+ if(ok==0) return 0;
+
+ if(totvert==0 || totvert>MESH_MAX_VERTS) return 0;
+
+ /* if needed add edges to other meshes */
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB_BGMODE(base)) {
+ if(base->object->type==OB_MESH) {
+ me= base->object->data;
+ totedge += me->totedge;
+ }
+ }
+ }
+
+ /* new material indices and material array */
+ matar= MEM_callocN(sizeof(void *)*MAXMAT, "join_mesh");
+ totcol= ob->totcol;
+
+ /* obact materials in new main array, is nicer start! */
+ for(a=1; a<=ob->totcol; a++) {
+ matar[a-1]= give_current_material(ob, a);
+ id_us_plus((ID *)matar[a-1]);
+ /* increase id->us : will be lowered later */
+ }
+
+ base= FIRSTBASE;
+ while(base) {
+ if(TESTBASELIB_BGMODE(base)) {
+ if(ob!=base->object && base->object->type==OB_MESH) {
+ me= base->object->data;
+
+ // 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), "join deformGroup");
+ memcpy (odg, dg, sizeof(bDeformGroup));
+ BLI_addtail(&ob->defbase, odg);
+ }
+
+ }
+ if (ob->defbase.first && ob->actdef==0)
+ ob->actdef=1;
+
+ 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;
+
+ memset(&vdata, 0, sizeof(vdata));
+ memset(&edata, 0, sizeof(edata));
+ memset(&fdata, 0, sizeof(fdata));
+
+ mvert= CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
+ medge= CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
+ mface= CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface);
+
+ mvertmain= mvert;
+ medgemain= medge;
+ mfacemain= mface;
+
+ /* inverse transorm all selected meshes in this object */
+ Mat4Invert(imat, ob->obmat);
+
+ vertofs= 0;
+ edgeofs= 0;
+ faceofs= 0;
+ base= FIRSTBASE;
+ while(base) {
+ nextb= base->next;
+ if (TESTBASELIB_BGMODE(base)) {
+ if(base->object->type==OB_MESH) {
+
+ me= base->object->data;
+
+ if(me->totvert) {
+ CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
+ CustomData_copy_data(&me->vdata, &vdata, 0, vertofs, me->totvert);
+
+ dvert= CustomData_get(&vdata, vertofs, CD_MDEFORMVERT);
+
+ /* NEW VERSION */
+ if (dvert){
+ 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);
+ if(odg) {
+ // 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;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(base->object != ob) {
+ /* watch this: switch matmul order really goes wrong */
+ Mat4MulMat4(cmat, base->object->obmat, imat);
+
+ a= me->totvert;
+ while(a--) {
+ Mat4MulVecfl(cmat, mvert->co);
+ mvert++;
+ }
+ }
+ else mvert+= me->totvert;
+ }
+ if(me->totface) {
+
+ /* make mapping for materials */
+ 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;
+ }
+ }
+ }
+ }
+
+ CustomData_merge(&me->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface);
+ CustomData_copy_data(&me->fdata, &fdata, 0, faceofs, me->totface);
+
+ for(a=0; a<me->totface; a++, mface++) {
+ mface->v1+= vertofs;
+ mface->v2+= vertofs;
+ mface->v3+= vertofs;
+ if(mface->v4) mface->v4+= vertofs;
+
+ mface->mat_nr= map[(int)mface->mat_nr];
+ }
+
+ faceofs += me->totface;
+ }
+
+ if(me->totedge) {
+ CustomData_merge(&me->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge);
+ CustomData_copy_data(&me->edata, &edata, 0, edgeofs, me->totedge);
+
+ for(a=0; a<me->totedge; a++, medge++) {
+ medge->v1+= vertofs;
+ medge->v2+= vertofs;
+ }
+
+ edgeofs += me->totedge;
+ }
+
+ vertofs += me->totvert;
+
+ if(base->object!=ob)
+ ED_base_object_free_and_unlink(scene, base);
+ }
+ }
+ base= nextb;
+ }
+
+ me= ob->data;
+
+ CustomData_free(&me->vdata, me->totvert);
+ CustomData_free(&me->edata, me->totedge);
+ CustomData_free(&me->fdata, me->totface);
+
+ me->totvert= totvert;
+ me->totedge= totedge;
+ me->totface= totface;
+
+ me->vdata= vdata;
+ me->edata= edata;
+ me->fdata= fdata;
+
+ mesh_update_customdata_pointers(me);
+
+ /* old 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;
+
+ /* other mesh users */
+ test_object_materials((ID *)me);
+
+ DAG_scene_sort(scene); // removed objects, need to rebuild dag before editmode call
+
+// XXX enter_editmode(EM_WAITCURSOR);
+// exit_editmode(EM_FREEDATA|EM_WAITCURSOR); // freedata, but no undo
+
+ BIF_undo_push("Join Mesh");
+ return 1;
+}
+
+
+/* ********************** SORT FACES ******************* */
+
+static void permutate(void *list, int num, int size, int *index)
+{
+ void *buf;
+ int len;
+ int i;
+
+ len = num * size;
+
+ buf = MEM_mallocN(len, "permutate");
+ memcpy(buf, list, len);
+
+ for (i = 0; i < num; i++) {
+ memcpy((char *)list + (i * size), (char *)buf + (index[i] * size), size);
+ }
+ MEM_freeN(buf);
+}
+
+/* sort faces on view axis */
+static float *face_sort_floats;
+static int float_sort(const void *v1, const void *v2)
+{
+ float x1, x2;
+
+ x1 = face_sort_floats[((int *) v1)[0]];
+ x2 = face_sort_floats[((int *) v2)[0]];
+
+ if( x1 > x2 ) return 1;
+ else if( x1 < x2 ) return -1;
+ return 0;
+}
+
+
+void sort_faces(Scene *scene, View3D *v3d)
+{
+ RegionView3D *rv3d= NULL; // get from context
+ Object *ob= OBACT;
+ Mesh *me;
+ CustomDataLayer *layer;
+ int i, *index;
+ short event;
+ float reverse = 1;
+ int ctrl= 0; // XXX
+
+ if(!ob) return;
+ if(scene->obedit) return;
+ if(ob->type!=OB_MESH) return;
+ if (!v3d) return;
+
+ me= ob->data;
+ if(me->totface==0) return;
+
+ event = pupmenu(
+ "Sort Faces (Ctrl to reverse)%t|"
+ "View Axis%x1|"
+ "Cursor Distance%x2|"
+ "Material%x3|"
+ "Selection%x4|"
+ "Randomize%x5");
+
+ if (event==-1) return;
+
+ if(ctrl)
+ reverse = -1;
+
+/* create index list */
+ index = (int *) MEM_mallocN(sizeof(int) * me->totface, "sort faces");
+ for (i = 0; i < me->totface; i++) {
+ index[i] = i;
+ }
+
+ face_sort_floats = (float *) MEM_mallocN(sizeof(float) * me->totface, "sort faces float");
+
+/* sort index list instead of faces itself
+ and apply this permutation to all face layers */
+
+ if (event == 5) {
+ /* Random */
+ for(i=0; i<me->totface; i++) {
+ face_sort_floats[i] = BLI_frand();
+ }
+ qsort(index, me->totface, sizeof(int), float_sort);
+ } else {
+ MFace *mf;
+ float vec[3];
+ float mat[4][4];
+ float cur[3];
+
+ if (event == 1)
+ Mat4MulMat4(mat, OBACT->obmat, rv3d->viewmat); /* apply the view matrix to the object matrix */
+ else if (event == 2) { /* sort from cursor */
+ if( v3d && v3d->localview ) {
+ VECCOPY(cur, v3d->cursor);
+ } else {
+ VECCOPY(cur, scene->cursor);
+ }
+ Mat4Invert(mat, OBACT->obmat);
+ Mat4MulVecfl(mat, cur);
+ }
+
+ mf= me->mface;
+ for(i=0; i<me->totface; i++, mf++) {
+
+ if (event==3) {
+ face_sort_floats[i] = ((float)mf->mat_nr)*reverse;
+ } else if (event==4) {
+ /*selected first*/
+ if (mf->flag & ME_FACE_SEL) face_sort_floats[i] = 0.0;
+ else face_sort_floats[i] = reverse;
+ } else {
+ /* find the faces center */
+ VECADD(vec, (me->mvert+mf->v1)->co, (me->mvert+mf->v2)->co);
+ if (mf->v4) {
+ VECADD(vec, vec, (me->mvert+mf->v3)->co);
+ VECADD(vec, vec, (me->mvert+mf->v4)->co);
+ VECMUL(vec, 0.25f);
+ } else {
+ VECADD(vec, vec, (me->mvert+mf->v3)->co);
+ VECMUL(vec, 1.0f/3.0f);
+ } /* done */
+
+ if (event == 1) { /* sort on view axis */
+ Mat4MulVecfl(mat, vec);
+ face_sort_floats[i] = vec[2] * reverse;
+ } else { /* distance from cursor*/
+ face_sort_floats[i] = VecLenf(cur, vec) * reverse; /* back to front */
+ }
+ }
+ }
+ qsort(index, me->totface, sizeof(int), float_sort);
+ }
+
+ MEM_freeN(face_sort_floats);
+
+ for(i = 0; i < me->fdata.totlayer; i++) {
+ layer = &me->fdata.layers[i];
+ permutate(layer->data, me->totface, CustomData_sizeof(layer->type), index);
+ }
+
+ MEM_freeN(index);
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+}
+
+
+
+/* ********************* MESH VERTEX OCTREE LOOKUP ************* */
+
+/* important note; this is unfinished, needs better API for editmode, and custom threshold */
+
+#define MOC_RES 8
+#define MOC_NODE_RES 8
+#define MOC_THRESH 0.0002f
+
+typedef struct MocNode {
+ struct MocNode *next;
+ intptr_t index[MOC_NODE_RES];
+} MocNode;
+
+static int mesh_octree_get_base_offs(float *co, float *offs, float *div)
+{
+ int vx, vy, vz;
+
+ vx= floor( (co[0]-offs[0])/div[0] );
+ vy= floor( (co[1]-offs[1])/div[1] );
+ vz= floor( (co[2]-offs[2])/div[2] );
+
+ CLAMP(vx, 0, MOC_RES-1);
+ CLAMP(vy, 0, MOC_RES-1);
+ CLAMP(vz, 0, MOC_RES-1);
+
+ return (vx*MOC_RES*MOC_RES) + vy*MOC_RES + vz;
+}
+
+static void mesh_octree_add_node(MocNode **bt, intptr_t index)
+{
+ if(*bt==NULL) {
+ *bt= MEM_callocN(sizeof(MocNode), "MocNode");
+ (*bt)->index[0]= index;
+ }
+ else {
+ int a;
+ for(a=0; a<MOC_NODE_RES; a++) {
+ if((*bt)->index[a]==index)
+ return;
+ else if((*bt)->index[a]==0) {
+ (*bt)->index[a]= index;
+ return;
+ }
+ }
+ mesh_octree_add_node(&(*bt)->next, index);
+ }
+}
+
+static void mesh_octree_free_node(MocNode **bt)
+{
+ if( (*bt)->next ) {
+ mesh_octree_free_node(&(*bt)->next);
+ }
+ MEM_freeN(*bt);
+}
+
+
+/* temporal define, just to make nicer code below */
+#define MOC_ADDNODE(vx, vy, vz) mesh_octree_add_node(basetable + ((vx)*MOC_RES*MOC_RES) + (vy)*MOC_RES + (vz), index)
+
+static void mesh_octree_add_nodes(MocNode **basetable, float *co, float *offs, float *div, intptr_t index)
+{
+ float fx, fy, fz;
+ int vx, vy, vz;
+
+ if (isnan(co[0]) || !finite(co[0]) ||
+ isnan(co[1]) || !finite(co[1]) ||
+ isnan(co[2]) || !finite(co[2])
+ ) {
+ return;
+ }
+
+ fx= (co[0]-offs[0])/div[0];
+ fy= (co[1]-offs[1])/div[1];
+ fz= (co[2]-offs[2])/div[2];
+ CLAMP(fx, 0.0f, MOC_RES-MOC_THRESH);
+ CLAMP(fy, 0.0f, MOC_RES-MOC_THRESH);
+ CLAMP(fz, 0.0f, MOC_RES-MOC_THRESH);
+
+ vx= floor(fx);
+ vy= floor(fy);
+ vz= floor(fz);
+
+ MOC_ADDNODE(vx, vy, vz);
+
+ if( vx>0 )
+ if( fx-((float)vx)-MOC_THRESH < 0.0f)
+ MOC_ADDNODE(vx-1, vy, vz);
+ if( vx<MOC_RES-2 )
+ if( fx-((float)vx)+MOC_THRESH > 1.0f)
+ MOC_ADDNODE(vx+1, vy, vz);
+
+ if( vy>0 )
+ if( fy-((float)vy)-MOC_THRESH < 0.0f)
+ MOC_ADDNODE(vx, vy-1, vz);
+ if( vy<MOC_RES-2 )
+ if( fy-((float)vy)+MOC_THRESH > 1.0f)
+ MOC_ADDNODE(vx, vy+1, vz);
+
+ if( vz>0 )
+ if( fz-((float)vz)-MOC_THRESH < 0.0f)
+ MOC_ADDNODE(vx, vy, vz-1);
+ if( vz<MOC_RES-2 )
+ if( fz-((float)vz)+MOC_THRESH > 1.0f)
+ MOC_ADDNODE(vx, vy, vz+1);
+
+}
+
+static intptr_t mesh_octree_find_index(MocNode **bt, float (*orco)[3], MVert *mvert, float *co)
+{
+ float *vec;
+ int a;
+
+ if(*bt==NULL)
+ return -1;
+
+ for(a=0; a<MOC_NODE_RES; a++) {
+ if((*bt)->index[a]) {
+ /* does mesh verts and editmode, code looks potential dangerous, octree should really be filled OK! */
+ if(orco) {
+ vec= orco[(*bt)->index[a]-1];
+ if(FloatCompare(vec, co, MOC_THRESH))
+ return (*bt)->index[a]-1;
+ }
+ else if(mvert) {
+ vec= (mvert+(*bt)->index[a]-1)->co;
+ if(FloatCompare(vec, co, MOC_THRESH))
+ return (*bt)->index[a]-1;
+ }
+ else {
+ EditVert *eve= (EditVert *)((*bt)->index[a]);
+ if(FloatCompare(eve->co, co, MOC_THRESH))
+ return (*bt)->index[a];
+ }
+ }
+ else return -1;
+ }
+ if( (*bt)->next)
+ return mesh_octree_find_index(&(*bt)->next, orco, mvert, co);
+
+ return -1;
+}
+
+static struct {
+ MocNode **table;
+ float offs[3], div[3];
+ float (*orco)[3];
+ float orcoloc[3];
+} MeshOctree = {NULL, {0, 0, 0}, {0, 0, 0}, NULL};
+
+/* mode is 's' start, or 'e' end, or 'u' use */
+/* if end, ob can be NULL */
+intptr_t mesh_octree_table(Object *ob, EditMesh *em, float *co, char mode)
+{
+ MocNode **bt;
+
+ if(mode=='u') { /* use table */
+ if(MeshOctree.table==NULL)
+ mesh_octree_table(ob, em, NULL, 's');
+
+ if(MeshOctree.table) {
+ Mesh *me= ob->data;
+ bt= MeshOctree.table + mesh_octree_get_base_offs(co, MeshOctree.offs, MeshOctree.div);
+ if(em)
+ return mesh_octree_find_index(bt, NULL, NULL, co);
+ else
+ return mesh_octree_find_index(bt, MeshOctree.orco, me->mvert, co);
+ }
+ return -1;
+ }
+ else if(mode=='s') { /* start table */
+ Mesh *me= ob->data;
+ float min[3], max[3];
+
+ /* we compute own bounding box and don't reuse ob->bb because
+ * we are using the undeformed coordinates*/
+ INIT_MINMAX(min, max);
+
+ if(em && me->edit_mesh==em) {
+ EditVert *eve;
+
+ for(eve= em->verts.first; eve; eve= eve->next)
+ DO_MINMAX(eve->co, min, max)
+ }
+ else {
+ MVert *mvert;
+ float *vco;
+ int a, totvert;
+
+ MeshOctree.orco= mesh_getRefKeyCos(me, &totvert);
+ mesh_get_texspace(me, MeshOctree.orcoloc, NULL, NULL);
+
+ for(a=0, mvert= me->mvert; a<me->totvert; a++, mvert++) {
+ vco= (MeshOctree.orco)? MeshOctree.orco[a]: mvert->co;
+ DO_MINMAX(vco, min, max);
+ }
+ }
+
+ /* for quick unit coordinate calculus */
+ VECCOPY(MeshOctree.offs, min);
+ MeshOctree.offs[0]-= MOC_THRESH; /* we offset it 1 threshold unit extra */
+ MeshOctree.offs[1]-= MOC_THRESH;
+ MeshOctree.offs[2]-= MOC_THRESH;
+
+ VecSubf(MeshOctree.div, max, min);
+ MeshOctree.div[0]+= 2*MOC_THRESH; /* and divide with 2 threshold unit more extra (try 8x8 unit grid on paint) */
+ MeshOctree.div[1]+= 2*MOC_THRESH;
+ MeshOctree.div[2]+= 2*MOC_THRESH;
+
+ VecMulf(MeshOctree.div, 1.0f/MOC_RES);
+ if(MeshOctree.div[0]==0.0f) MeshOctree.div[0]= 1.0f;
+ if(MeshOctree.div[1]==0.0f) MeshOctree.div[1]= 1.0f;
+ if(MeshOctree.div[2]==0.0f) MeshOctree.div[2]= 1.0f;
+
+ if(MeshOctree.table) /* happens when entering this call without ending it */
+ mesh_octree_table(ob, em, co, 'e');
+
+ MeshOctree.table= MEM_callocN(MOC_RES*MOC_RES*MOC_RES*sizeof(void *), "sym table");
+
+ if(em && me->edit_mesh==em) {
+ EditVert *eve;
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ mesh_octree_add_nodes(MeshOctree.table, eve->co, MeshOctree.offs, MeshOctree.div, (intptr_t)(eve));
+ }
+ }
+ else {
+ MVert *mvert;
+ float *vco;
+ int a;
+
+ for(a=0, mvert= me->mvert; a<me->totvert; a++, mvert++) {
+ vco= (MeshOctree.orco)? MeshOctree.orco[a]: mvert->co;
+ mesh_octree_add_nodes(MeshOctree.table, vco, MeshOctree.offs, MeshOctree.div, a+1);
+ }
+ }
+ }
+ else if(mode=='e') { /* end table */
+ if(MeshOctree.table) {
+ int a;
+
+ for(a=0, bt=MeshOctree.table; a<MOC_RES*MOC_RES*MOC_RES; a++, bt++) {
+ if(*bt) mesh_octree_free_node(bt);
+ }
+ MEM_freeN(MeshOctree.table);
+ MeshOctree.table= NULL;
+ }
+ if(MeshOctree.orco) {
+ MEM_freeN(MeshOctree.orco);
+ MeshOctree.orco= NULL;
+ }
+ }
+ return 0;
+}
+
+int mesh_get_x_mirror_vert(Object *ob, int index)
+{
+ Mesh *me= ob->data;
+ MVert *mvert;
+ float vec[3];
+
+ if(MeshOctree.orco) {
+ float *loc= MeshOctree.orcoloc;
+
+ vec[0]= -(MeshOctree.orco[index][0] + loc[0]) - loc[0];
+ vec[1]= MeshOctree.orco[index][1];
+ vec[2]= MeshOctree.orco[index][2];
+ }
+ else {
+ mvert= me->mvert+index;
+ vec[0]= -mvert->co[0];
+ vec[1]= mvert->co[1];
+ vec[2]= mvert->co[2];
+ }
+
+ return mesh_octree_table(ob, NULL, vec, 'u');
+}
+
+EditVert *editmesh_get_x_mirror_vert(Object *ob, EditMesh *em, float *co)
+{
+ float vec[3];
+ intptr_t poinval;
+
+ /* ignore nan verts */
+ if (isnan(co[0]) || !finite(co[0]) ||
+ isnan(co[1]) || !finite(co[1]) ||
+ isnan(co[2]) || !finite(co[2])
+ )
+ return NULL;
+
+ vec[0]= -co[0];
+ vec[1]= co[1];
+ vec[2]= co[2];
+
+ poinval= mesh_octree_table(ob, em, vec, 'u');
+ if(poinval != -1)
+ return (EditVert *)(poinval);
+ return NULL;
+}
+
+static unsigned int mirror_facehash(void *ptr)
+{
+ MFace *mf= ptr;
+ int v0, v1;
+
+ if(mf->v4) {
+ v0= MIN4(mf->v1, mf->v2, mf->v3, mf->v4);
+ v1= MAX4(mf->v1, mf->v2, mf->v3, mf->v4);
+ }
+ else {
+ v0= MIN3(mf->v1, mf->v2, mf->v3);
+ v1= MAX3(mf->v1, mf->v2, mf->v3);
+ }
+
+ return ((v0*39)^(v1*31));
+}
+
+static int mirror_facerotation(MFace *a, MFace *b)
+{
+ if(b->v4) {
+ if(a->v1==b->v1 && a->v2==b->v2 && a->v3==b->v3 && a->v4==b->v4)
+ return 0;
+ else if(a->v4==b->v1 && a->v1==b->v2 && a->v2==b->v3 && a->v3==b->v4)
+ return 1;
+ else if(a->v3==b->v1 && a->v4==b->v2 && a->v1==b->v3 && a->v2==b->v4)
+ return 2;
+ else if(a->v2==b->v1 && a->v3==b->v2 && a->v4==b->v3 && a->v1==b->v4)
+ return 3;
+ }
+ else {
+ if(a->v1==b->v1 && a->v2==b->v2 && a->v3==b->v3)
+ return 0;
+ else if(a->v3==b->v1 && a->v1==b->v2 && a->v2==b->v3)
+ return 1;
+ else if(a->v2==b->v1 && a->v3==b->v2 && a->v1==b->v3)
+ return 2;
+ }
+
+ return -1;
+}
+
+static int mirror_facecmp(void *a, void *b)
+{
+ return (mirror_facerotation((MFace*)a, (MFace*)b) == -1);
+}
+
+int *mesh_get_x_mirror_faces(Object *ob, EditMesh *em)
+{
+ Mesh *me= ob->data;
+ MVert *mv, *mvert= me->mvert;
+ MFace mirrormf, *mf, *hashmf, *mface= me->mface;
+ GHash *fhash;
+ int *mirrorverts, *mirrorfaces;
+ int a;
+
+ mirrorverts= MEM_callocN(sizeof(int)*me->totvert, "MirrorVerts");
+ mirrorfaces= MEM_callocN(sizeof(int)*2*me->totface, "MirrorFaces");
+
+ mesh_octree_table(ob, em, NULL, 's');
+
+ for(a=0, mv=mvert; a<me->totvert; a++, mv++)
+ mirrorverts[a]= mesh_get_x_mirror_vert(ob, a);
+
+ mesh_octree_table(ob, em, NULL, 'e');
+
+ fhash= BLI_ghash_new(mirror_facehash, mirror_facecmp);
+ for(a=0, mf=mface; a<me->totface; a++, mf++)
+ BLI_ghash_insert(fhash, mf, mf);
+
+ for(a=0, mf=mface; a<me->totface; a++, mf++) {
+ mirrormf.v1= mirrorverts[mf->v3];
+ mirrormf.v2= mirrorverts[mf->v2];
+ mirrormf.v3= mirrorverts[mf->v1];
+ mirrormf.v4= (mf->v4)? mirrorverts[mf->v4]: 0;
+
+ /* make sure v4 is not 0 if a quad */
+ if(mf->v4 && mirrormf.v4==0) {
+ SWAP(int, mirrormf.v1, mirrormf.v3);
+ SWAP(int, mirrormf.v2, mirrormf.v4);
+ }
+
+ hashmf= BLI_ghash_lookup(fhash, &mirrormf);
+ if(hashmf) {
+ mirrorfaces[a*2]= hashmf - mface;
+ mirrorfaces[a*2+1]= mirror_facerotation(&mirrormf, hashmf);
+ }
+ else
+ mirrorfaces[a*2]= -1;
+ }
+
+ BLI_ghash_free(fhash, NULL, NULL);
+ MEM_freeN(mirrorverts);
+
+ return mirrorfaces;
+}
+
+/* ****************** render BAKING ********************** */
+
+/* threaded break test */
+static int thread_break(void *unused)
+{
+ return G.afbreek;
+}
+
+static ScrArea *biggest_image_area(bScreen *screen)
+{
+ ScrArea *sa, *big= NULL;
+ int size, maxsize= 0;
+
+ for(sa= screen->areabase.first; sa; sa= sa->next) {
+ if(sa->spacetype==SPACE_IMAGE) {
+ size= sa->winx*sa->winy;
+ if(sa->winx > 10 && sa->winy > 10 && size > maxsize) {
+ maxsize= size;
+ big= sa;
+ }
+ }
+ }
+ return big;
+}
+
+
+typedef struct BakeRender {
+ Render *re;
+ struct Object *actob;
+ int event, tot, ready;
+} BakeRender;
+
+static void *do_bake_render(void *bake_v)
+{
+ BakeRender *bkr= bake_v;
+
+ bkr->tot= RE_bake_shade_all_selected(bkr->re, bkr->event, bkr->actob);
+ bkr->ready= 1;
+
+ return NULL;
+}
+
+
+void objects_bake_render(Scene *scene, short event, char **error_msg)
+{
+ Object *actob= OBACT;
+ int active= scene->r.bake_flag & R_BAKE_TO_ACTIVE;
+ short prev_r_raytrace= 0, prev_wo_amb_occ= 0;
+
+ if(event==0) event= scene->r.bake_mode;
+
+ if(scene->r.renderer!=R_INTERN) {
+ *error_msg = "Bake only supported for Internal Renderer";
+ return;
+ }
+
+ if(active && !actob) {
+ *error_msg = "No active object";
+ return;
+ }
+
+ if(event>0) {
+ bScreen *screen= NULL; // XXX CTX
+ Render *re= RE_NewRender("_Bake View_");
+ ScrArea *area= biggest_image_area(screen);
+ ListBase threads;
+ BakeRender bkr;
+ int timer=0, tot; // XXX, sculptmode= G.f & G_SCULPTMODE;
+
+// XXX if(sculptmode) set_sculptmode();
+
+ if(event==1) event= RE_BAKE_ALL;
+ else if(event==2) event= RE_BAKE_AO;
+ else if(event==3) event= RE_BAKE_NORMALS;
+ else if(event==4) event= RE_BAKE_TEXTURE;
+ else if(event==5) event= RE_BAKE_DISPLACEMENT;
+ else event= RE_BAKE_SHADOW;
+
+ if(event==RE_BAKE_AO) {
+ if(scene->world==NULL) {
+ *error_msg = "No world set up";
+ return;
+ }
+
+ /* If raytracing or AO is disabled, switch it on temporarily for baking. */
+ prev_wo_amb_occ = (scene->world->mode & WO_AMB_OCC) != 0;
+ scene->world->mode |= WO_AMB_OCC;
+ }
+ if(event==RE_BAKE_AO || active) {
+ prev_r_raytrace = (scene->r.mode & R_RAYTRACE) != 0;
+ scene->r.mode |= R_RAYTRACE;
+ }
+
+ waitcursor(1);
+ RE_test_break_cb(re, NULL, thread_break);
+ G.afbreek= 0; /* blender_test_break uses this global */
+
+ RE_Database_Baking(re, scene, event, (active)? actob: NULL);
+
+ /* baking itself is threaded, cannot use test_break in threads. we also update optional imagewindow */
+
+ BLI_init_threads(&threads, do_bake_render, 1);
+ bkr.re= re;
+ bkr.event= event;
+ bkr.ready= 0;
+ bkr.actob= (active)? actob: NULL;
+ BLI_insert_thread(&threads, &bkr);
+
+ while(bkr.ready==0) {
+ PIL_sleep_ms(50);
+ if(bkr.ready)
+ break;
+
+ if (!G.background) {
+ blender_test_break();
+
+ timer++;
+ if(area && timer==20) {
+ Image *ima= RE_bake_shade_get_image();
+ if(ima) ((SpaceImage *)area->spacedata.first)->image= ima;
+// XX scrarea_do_windraw(area);
+// myswapbuffers();
+ timer= 0;
+ }
+ }
+ }
+ BLI_end_threads(&threads);
+ tot= bkr.tot;
+
+ RE_Database_Free(re);
+ waitcursor(0);
+
+ if(tot==0) *error_msg = "No Images found to bake to";
+ else {
+ Image *ima;
+ /* force OpenGL reload and mipmap recalc */
+ for(ima= G.main->image.first; ima; ima= ima->id.next) {
+ if(ima->ok==IMA_OK_LOADED) {
+ ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
+ if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
+ GPU_free_image(ima);
+ imb_freemipmapImBuf(ibuf);
+ }
+ }
+ }
+ }
+
+ /* restore raytrace and AO */
+ if(event==RE_BAKE_AO)
+ if(prev_wo_amb_occ == 0)
+ scene->world->mode &= ~WO_AMB_OCC;
+
+ if(event==RE_BAKE_AO || active)
+ if(prev_r_raytrace == 0)
+ scene->r.mode &= ~R_RAYTRACE;
+
+// XXX if(sculptmode) set_sculptmode();
+
+ }
+}
+
+/* all selected meshes with UV maps are rendered for current scene visibility */
+static void objects_bake_render_ui(Scene *scene, short event)
+{
+ char *error_msg = NULL;
+// int is_editmode = (obedit!=NULL);
+
+ /* Deal with editmode, this is a bit clunky but since UV's are in editmode, users are likely to bake from their */
+// XXX if (is_editmode) exit_editmode(0);
+
+ objects_bake_render(scene, event, &error_msg);
+
+// XXX if (is_editmode) enter_editmode(0);
+
+ if (error_msg)
+ error(error_msg);
+}
+
+void objects_bake_render_menu(Scene *scene)
+{
+ short event;
+
+ event= pupmenu("Bake Selected Meshes %t|Full Render %x1|Ambient Occlusion %x2|Normals %x3|Texture Only %x4|Displacement %x5|Shadow %x6");
+ if (event < 1) return;
+ objects_bake_render_ui(scene, event);
+}
+
diff --git a/source/blender/editors/object/Makefile b/source/blender/editors/object/Makefile
new file mode 100644
index 00000000000..9011f566bc6
--- /dev/null
+++ b/source/blender/editors/object/Makefile
@@ -0,0 +1,54 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_object
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+CPPFLAGS += -I$(NAN_BMFONT)/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../python
+CPPFLAGS += -I../../imbuf
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/object/SConscript b/source/blender/editors/object/SConscript
new file mode 100644
index 00000000000..5cd7a3b91af
--- /dev/null
+++ b/source/blender/editors/object/SConscript
@@ -0,0 +1,16 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc'
+incs += ' #/intern/guardedalloc #intern/bmfont'
+incs += ' ../../makesrna ../../python'
+
+defs = []
+
+if not env['WITH_BF_PYTHON']:
+ defs.append('DISABLE_PYTHON')
+
+env.BlenderLib ( 'bf_editors_object', sources, Split(incs), defs, libtype=['core'], priority=[35] )
diff --git a/source/blender/editors/object/editconstraint.c b/source/blender/editors/object/editconstraint.c
new file mode 100644
index 00000000000..d0e487f98c7
--- /dev/null
+++ b/source/blender/editors/object/editconstraint.c
@@ -0,0 +1,891 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung, Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_dynstr.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_text_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_constraint.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+
+#ifndef DISABLE_PYTHON
+#include "BPY_extern.h"
+#endif
+
+#include "ED_object.h"
+
+#include "object_intern.h"
+
+/* XXX */
+static void BIF_undo_push() {}
+static void error() {}
+static int okee() {return 0;}
+static int pupmenu() {return 0;}
+
+/* -------------- Get Active Constraint Data ---------------------- */
+
+
+/* if object in posemode, active bone constraints, else object constraints */
+ListBase *get_active_constraints (Object *ob)
+{
+ if (ob == NULL)
+ return NULL;
+
+ if (ob->flag & OB_POSEMODE) {
+ bPoseChannel *pchan;
+
+ pchan = get_active_posechannel(ob);
+ if (pchan)
+ return &pchan->constraints;
+ }
+ else
+ return &ob->constraints;
+
+ return NULL;
+}
+
+/* single constraint */
+bConstraint *get_active_constraint (Object *ob)
+{
+ ListBase *lb= get_active_constraints(ob);
+
+ if (lb) {
+ bConstraint *con;
+
+ for (con= lb->first; con; con=con->next) {
+ if (con->flag & CONSTRAINT_ACTIVE)
+ return con;
+ }
+ }
+
+ return NULL;
+}
+
+/* single channel, for ipo */
+bConstraintChannel *get_active_constraint_channel (Scene *scene, Object *ob)
+{
+ bConstraint *con;
+
+ if (ob->flag & OB_POSEMODE) {
+ //if (ob->action) { // XXX old animation system
+ bPoseChannel *pchan;
+
+ pchan = get_active_posechannel(ob);
+ if (pchan) {
+ for (con= pchan->constraints.first; con; con= con->next) {
+ if (con->flag & CONSTRAINT_ACTIVE)
+ break;
+ }
+
+ if (con) {
+#if 0 // XXX old animation system
+ bActionChannel *achan = get_action_channel(ob->action, pchan->name);
+ if (achan) {
+ for (chan= achan->constraintChannels.first; chan; chan= chan->next) {
+ if (!strcmp(chan->name, con->name))
+ break;
+ }
+ return chan;
+ }
+#endif // XXX old animation system
+ }
+ }
+ //} // xxx old animation system
+ }
+ else {
+ for (con= ob->constraints.first; con; con= con->next) {
+ if (con->flag & CONSTRAINT_ACTIVE)
+ break;
+ }
+
+ if (con) {
+#if 0 // XXX old animation system
+ ListBase *lb= get_active_constraint_channels(scene, ob, 0);
+
+ if (lb) {
+ for (chan= lb->first; chan; chan= chan->next) {
+ if (!strcmp(chan->name, con->name))
+ break;
+ }
+
+ return chan;
+ }
+#endif // XXX old animation system
+ }
+ }
+
+ return NULL;
+}
+
+/* -------------- Constraint Management (Add New, Remove, Rename) -------------------- */
+/* ------------- PyConstraints ------------------ */
+
+/* this callback sets the text-file to be used for selected menu item */
+void validate_pyconstraint_cb (void *arg1, void *arg2)
+{
+ bPythonConstraint *data = arg1;
+ Text *text= NULL;
+ int index = *((int *)arg2);
+ int i;
+
+ /* exception for no script */
+ if (index) {
+ /* innovative use of a for...loop to search */
+ for (text=G.main->text.first, i=1; text && index!=i; i++, text=text->id.next);
+ }
+ data->text = text;
+}
+
+#ifndef DISABLE_PYTHON
+/* this returns a string for the list of usable pyconstraint script names */
+char *buildmenu_pyconstraints (Text *con_text, int *pyconindex)
+{
+ DynStr *pupds= BLI_dynstr_new();
+ Text *text;
+ char *str;
+ char buf[64];
+ int i;
+
+ /* add title first */
+ sprintf(buf, "Scripts: %%t|[None]%%x0|");
+ BLI_dynstr_append(pupds, buf);
+
+ /* init active-index first */
+ if (con_text == NULL)
+ *pyconindex= 0;
+
+ /* loop through markers, adding them */
+ for (text=G.main->text.first, i=1; text; i++, text=text->id.next) {
+ /* this is important to ensure that right script is shown as active */
+ if (text == con_text) *pyconindex = i;
+
+ /* only include valid pyconstraint scripts */
+ if (BPY_is_pyconstraint(text)) {
+ BLI_dynstr_append(pupds, text->id.name+2);
+
+ sprintf(buf, "%%x%d", i);
+ BLI_dynstr_append(pupds, buf);
+
+ if (text->id.next)
+ BLI_dynstr_append(pupds, "|");
+ }
+ }
+
+ /* convert to normal MEM_malloc'd string */
+ str= BLI_dynstr_get_cstring(pupds);
+ BLI_dynstr_free(pupds);
+
+ return str;
+}
+#endif /* DISABLE_PYTHON */
+
+/* this callback gets called when the 'refresh' button of a pyconstraint gets pressed */
+void update_pyconstraint_cb (void *arg1, void *arg2)
+{
+ Object *owner= (Object *)arg1;
+ bConstraint *con= (bConstraint *)arg2;
+#ifndef DISABLE_PYTHON
+ if (owner && con)
+ BPY_pyconstraint_update(owner, con);
+#endif
+}
+
+/* Creates a new constraint, initialises its data, and returns it */
+bConstraint *add_new_constraint (short type)
+{
+ bConstraint *con;
+ bConstraintTypeInfo *cti;
+
+ con = MEM_callocN(sizeof(bConstraint), "Constraint");
+
+ /* Set up a generic constraint datablock */
+ con->type = type;
+ con->flag |= CONSTRAINT_EXPAND;
+ con->enforce = 1.0F;
+ strcpy(con->name, "Const");
+
+ /* Load the data for it */
+ cti = constraint_get_typeinfo(con);
+ if (cti) {
+ con->data = MEM_callocN(cti->size, cti->structName);
+
+ /* only constraints that change any settings need this */
+ if (cti->new_data)
+ cti->new_data(con->data);
+ }
+
+ return con;
+}
+
+/* Adds the given constraint to the Object-level set of constraints for the given Object */
+void add_constraint_to_object (bConstraint *con, Object *ob)
+{
+ ListBase *list;
+ list = &ob->constraints;
+
+ if (list) {
+ unique_constraint_name(con, list);
+ BLI_addtail(list, con);
+
+ if (proxylocked_constraints_owner(ob, NULL))
+ con->flag |= CONSTRAINT_PROXY_LOCAL;
+
+ con->flag |= CONSTRAINT_ACTIVE;
+ for (con= con->prev; con; con= con->prev)
+ con->flag &= ~CONSTRAINT_ACTIVE;
+ }
+}
+
+/* helper function for add_constriant - sets the last target for the active constraint */
+static void set_constraint_nth_target (bConstraint *con, Object *target, char subtarget[], int index)
+{
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+ int num_targets, i;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+ num_targets= BLI_countlist(&targets);
+
+ if (index < 0) {
+ if (abs(index) < num_targets)
+ index= num_targets - abs(index);
+ else
+ index= num_targets - 1;
+ }
+ else if (index >= num_targets) {
+ index= num_targets - 1;
+ }
+
+ for (ct=targets.first, i=0; ct; ct= ct->next, i++) {
+ if (i == index) {
+ ct->tar= target;
+ strcpy(ct->subtarget, subtarget);
+ break;
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+}
+
+/* context: active object in posemode, active channel, optional selected channel */
+void add_constraint (Scene *scene, View3D *v3d, short only_IK)
+{
+ Object *ob= OBACT, *obsel=NULL;
+ bPoseChannel *pchanact=NULL, *pchansel=NULL;
+ bConstraint *con=NULL;
+ Base *base;
+ short nr;
+
+ /* paranoia checks */
+ if ((ob==NULL) || (ob==scene->obedit))
+ return;
+
+ if ((ob->pose) && (ob->flag & OB_POSEMODE)) {
+ bArmature *arm= ob->data;
+
+ /* find active channel */
+ pchanact= get_active_posechannel(ob);
+ if (pchanact==NULL)
+ return;
+
+ /* find selected bone */
+ for (pchansel=ob->pose->chanbase.first; pchansel; pchansel=pchansel->next) {
+ if (pchansel != pchanact) {
+ if (pchansel->bone->flag & BONE_SELECTED) {
+ if (pchansel->bone->layer & arm->layer)
+ break;
+ }
+ }
+ }
+ }
+
+ /* find selected object */
+ for (base= FIRSTBASE; base; base= base->next) {
+ if ((TESTBASE(v3d, base)) && (base->object!=ob))
+ obsel= base->object;
+ }
+
+ /* the only_IK caller has checked for posemode! */
+ if (only_IK) {
+ for (con= pchanact->constraints.first; con; con= con->next) {
+ if (con->type==CONSTRAINT_TYPE_KINEMATIC) break;
+ }
+ if (con) {
+ error("Pose Channel already has IK");
+ return;
+ }
+
+ if (pchansel)
+ nr= pupmenu("Add IK Constraint%t|To Active Bone%x10");
+ else if (obsel)
+ nr= pupmenu("Add IK Constraint%t|To Active Object%x10");
+ else
+ nr= pupmenu("Add IK Constraint%t|To New Empty Object%x10|Without Target%x11");
+ }
+ else {
+ if (pchanact) {
+ if (pchansel)
+ nr= pupmenu("Add Constraint to Active Bone%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
+ else if ((obsel) && (obsel->type==OB_CURVE))
+ nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|Stretch To%x7|%l|Action%x16|Script%x18");
+ else if ((obsel) && (obsel->type==OB_MESH))
+ nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Shrinkwrap%x22|Stretch To%x7|%l|Action%x16|Script%x18");
+ else if (obsel)
+ nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
+ else
+ nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
+ }
+ else {
+ if ((obsel) && (obsel->type==OB_CURVE))
+ nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|%l|Action%x16|Script%x18");
+ else if ((obsel) && (obsel->type==OB_MESH))
+ nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Shrinkwrap%x22|%l|Action%x16|Script%x18");
+ else if (obsel)
+ nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18");
+ else
+ nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18");
+ }
+ }
+
+ if (nr < 1) return;
+
+ /* handle IK separate */
+ if (nr==10 || nr==11) {
+ /* ik - prevent weird chains... */
+ if (pchansel) {
+ bPoseChannel *pchan= pchanact;
+ while (pchan) {
+ if (pchan==pchansel) break;
+ pchan= pchan->parent;
+ }
+ if (pchan) {
+ error("IK root cannot be linked to IK tip");
+ return;
+ }
+
+ pchan= pchansel;
+ while (pchan) {
+ if (pchan==pchanact) break;
+ pchan= pchan->parent;
+ }
+ if (pchan) {
+ error("IK tip cannot be linked to IK root");
+ return;
+ }
+ }
+
+ con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
+ BLI_addtail(&pchanact->constraints, con);
+ unique_constraint_name(con, &pchanact->constraints);
+ pchanact->constflag |= PCHAN_HAS_IK; /* for draw, but also for detecting while pose solving */
+ if (nr==11)
+ pchanact->constflag |= PCHAN_HAS_TARGET;
+ if (proxylocked_constraints_owner(ob, pchanact))
+ con->flag |= CONSTRAINT_PROXY_LOCAL;
+ }
+ else {
+ /* normal constraints - add data */
+ if (nr==1) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIKE);
+ else if (nr==2) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIKE);
+ else if (nr==3) con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
+ else if (nr==4) con = add_new_constraint(CONSTRAINT_TYPE_MINMAX);
+ else if (nr==5) con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
+ else if (nr==6) {
+ Curve *cu= obsel->data;
+ cu->flag |= CU_PATH;
+ con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
+ }
+ else if (nr==7) con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO);
+ else if (nr==8) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIKE);
+ else if (nr==13) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIMIT);
+ else if (nr==14) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIMIT);
+ else if (nr==15) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIMIT);
+ else if (nr==16) {
+ /* TODO: add a popup-menu to display list of available actions to use (like for pyconstraints) */
+ con = add_new_constraint(CONSTRAINT_TYPE_ACTION);
+ }
+ else if (nr==17) {
+ Curve *cu= obsel->data;
+ cu->flag |= CU_PATH;
+ con = add_new_constraint(CONSTRAINT_TYPE_CLAMPTO);
+ }
+ else if (nr==18) {
+ char *menustr;
+ int scriptint= 0;
+#ifndef DISABLE_PYTHON
+ /* popup a list of usable scripts */
+ menustr = buildmenu_pyconstraints(NULL, &scriptint);
+ scriptint = pupmenu(menustr);
+ MEM_freeN(menustr);
+
+ /* only add constraint if a script was chosen */
+ if (scriptint) {
+ /* add constraint */
+ con = add_new_constraint(CONSTRAINT_TYPE_PYTHON);
+ validate_pyconstraint_cb(con->data, &scriptint);
+
+ /* make sure target allowance is set correctly */
+ BPY_pyconstraint_update(ob, con);
+ }
+#endif
+ }
+ else if (nr==19) {
+ con = add_new_constraint(CONSTRAINT_TYPE_CHILDOF);
+
+ /* if this constraint is being added to a posechannel, make sure
+ * the constraint gets evaluated in pose-space
+ */
+ if (pchanact) {
+ con->ownspace = CONSTRAINT_SPACE_POSE;
+ con->flag |= CONSTRAINT_SPACEONCE;
+ }
+ }
+ else if (nr==20) con = add_new_constraint(CONSTRAINT_TYPE_TRANSFORM);
+ else if (nr==21) con = add_new_constraint(CONSTRAINT_TYPE_DISTLIMIT);
+ else if (nr==22) con = add_new_constraint(CONSTRAINT_TYPE_SHRINKWRAP);
+
+ if (con==NULL) return; /* paranoia */
+
+ if (pchanact) {
+ BLI_addtail(&pchanact->constraints, con);
+ unique_constraint_name(con, &pchanact->constraints);
+ pchanact->constflag |= PCHAN_HAS_CONST; /* for draw */
+ if (proxylocked_constraints_owner(ob, pchanact))
+ con->flag |= CONSTRAINT_PROXY_LOCAL;
+ }
+ else {
+ BLI_addtail(&ob->constraints, con);
+ unique_constraint_name(con, &ob->constraints);
+ if (proxylocked_constraints_owner(ob, NULL))
+ con->flag |= CONSTRAINT_PROXY_LOCAL;
+ }
+ }
+
+ /* set the target */
+ if (pchansel) {
+ set_constraint_nth_target(con, ob, pchansel->name, 0);
+ }
+ else if (obsel) {
+ set_constraint_nth_target(con, obsel, "", 0);
+ }
+ else if (ELEM4(nr, 11, 13, 14, 15)==0) { /* add new empty as target */
+ Base *base= BASACT, *newbase;
+ Object *obt;
+
+ obt= add_object(scene, OB_EMPTY);
+ /* set layers OK */
+ newbase= BASACT;
+ newbase->lay= base->lay;
+ obt->lay= newbase->lay;
+
+ /* transform cent to global coords for loc */
+ if (pchanact) {
+ if (only_IK)
+ VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_tail);
+ else
+ VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_head);
+ }
+ else
+ VECCOPY(obt->loc, ob->obmat[3]);
+
+ set_constraint_nth_target(con, obt, "", 0);
+
+ /* restore, add_object sets active */
+ BASACT= base;
+ base->flag |= SELECT;
+ }
+
+ /* active flag */
+ con->flag |= CONSTRAINT_ACTIVE;
+ for (con= con->prev; con; con= con->prev)
+ con->flag &= ~CONSTRAINT_ACTIVE;
+
+ DAG_scene_sort(scene); // sort order of objects
+
+ if (pchanact) {
+ ob->pose->flag |= POSE_RECALC; // sort pose channels
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA); // and all its relations
+ }
+ else
+ DAG_object_flush_update(scene, ob, OB_RECALC_OB); // and all its relations
+
+ if (only_IK)
+ BIF_undo_push("Add IK Constraint");
+ else
+ BIF_undo_push("Add Constraint");
+
+}
+
+/* Remove all constraints from the active object */
+void ob_clear_constraints (Scene *scene)
+{
+ Object *ob= OBACT;
+
+ /* paranoia checks */
+ if ((ob==NULL) || (ob==scene->obedit) || (ob->flag & OB_POSEMODE))
+ return;
+
+ /* get user permission */
+ if (okee("Clear Constraints")==0)
+ return;
+
+ /* do freeing */
+ free_constraints(&ob->constraints);
+
+ /* do updates */
+ DAG_object_flush_update(scene, ob, OB_RECALC_OB);
+
+ BIF_undo_push("Clear Constraint(s)");
+}
+
+/* Rename the given constraint
+ * - con already has the new name
+ */
+void rename_constraint (Object *ob, bConstraint *con, char *oldname)
+{
+ bConstraint *tcon;
+ ListBase *conlist= NULL;
+ int from_object= 0;
+ char *channame="";
+
+ /* get context by searching for con (primitive...) */
+ for (tcon= ob->constraints.first; tcon; tcon= tcon->next) {
+ if (tcon==con)
+ break;
+ }
+
+ if (tcon) {
+ conlist= &ob->constraints;
+ channame= "Object";
+ from_object= 1;
+ }
+ else if (ob->pose) {
+ bPoseChannel *pchan;
+
+ for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+ for (tcon= pchan->constraints.first; tcon; tcon= tcon->next) {
+ if (tcon==con)
+ break;
+ }
+ if (tcon)
+ break;
+ }
+
+ if (tcon) {
+ conlist= &pchan->constraints;
+ channame= pchan->name;
+ }
+ }
+
+ if (conlist==NULL) {
+ printf("rename constraint failed\n"); /* should not happen in UI */
+ return;
+ }
+
+ /* first make sure it's a unique name within context */
+ unique_constraint_name (con, conlist);
+}
+
+
+/* ------------- Constraint Sanity Testing ------------------- */
+
+/* checks validity of object pointers, and NULLs,
+ * if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag
+ */
+static void test_constraints (Object *owner, const char substring[])
+{
+ bConstraint *curcon;
+ ListBase *conlist= NULL;
+ int type;
+
+ if (owner==NULL) return;
+
+ /* Check parents */
+ if (strlen(substring)) {
+ switch (owner->type) {
+ case OB_ARMATURE:
+ type = CONSTRAINT_OBTYPE_BONE;
+ break;
+ default:
+ type = CONSTRAINT_OBTYPE_OBJECT;
+ break;
+ }
+ }
+ else
+ type = CONSTRAINT_OBTYPE_OBJECT;
+
+ /* Get the constraint list for this object */
+ switch (type) {
+ case CONSTRAINT_OBTYPE_OBJECT:
+ conlist = &owner->constraints;
+ break;
+ case CONSTRAINT_OBTYPE_BONE:
+ {
+ Bone *bone;
+ bPoseChannel *chan;
+
+ bone = get_named_bone( ((bArmature *)owner->data), substring );
+ chan = get_pose_channel(owner->pose, substring);
+ if (bone && chan) {
+ conlist = &chan->constraints;
+ }
+ }
+ break;
+ }
+
+ /* Check all constraints - is constraint valid? */
+ if (conlist) {
+ for (curcon = conlist->first; curcon; curcon=curcon->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ /* clear disabled-flag first */
+ curcon->flag &= ~CONSTRAINT_DISABLE;
+
+ if (curcon->type == CONSTRAINT_TYPE_KINEMATIC) {
+ bKinematicConstraint *data = curcon->data;
+
+ /* bad: we need a separate set of checks here as poletarget is
+ * optional... otherwise poletarget must exist too or else
+ * the constraint is deemed invalid
+ */
+ if (exist_object(data->tar) == 0) {
+ data->tar = NULL;
+ curcon->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (data->tar == owner) {
+ if (!get_named_bone(get_armature(owner), data->subtarget)) {
+ curcon->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+
+ if (data->poletar) {
+ if (exist_object(data->poletar) == 0) {
+ data->poletar = NULL;
+ curcon->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (data->poletar == owner) {
+ if (!get_named_bone(get_armature(owner), data->polesubtarget)) {
+ curcon->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ }
+
+ /* targets have already been checked for this */
+ continue;
+ }
+ else if (curcon->type == CONSTRAINT_TYPE_ACTION) {
+ bActionConstraint *data = curcon->data;
+
+ /* validate action */
+ if (data->act == NULL)
+ curcon->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (curcon->type == CONSTRAINT_TYPE_FOLLOWPATH) {
+ bFollowPathConstraint *data = curcon->data;
+
+ /* don't allow track/up axes to be the same */
+ if (data->upflag==data->trackflag)
+ curcon->flag |= CONSTRAINT_DISABLE;
+ if (data->upflag+3==data->trackflag)
+ curcon->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (curcon->type == CONSTRAINT_TYPE_TRACKTO) {
+ bTrackToConstraint *data = curcon->data;
+
+ /* don't allow track/up axes to be the same */
+ if (data->reserved2==data->reserved1)
+ curcon->flag |= CONSTRAINT_DISABLE;
+ if (data->reserved2+3==data->reserved1)
+ curcon->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (curcon->type == CONSTRAINT_TYPE_LOCKTRACK) {
+ bLockTrackConstraint *data = curcon->data;
+
+ if (data->lockflag==data->trackflag)
+ curcon->flag |= CONSTRAINT_DISABLE;
+ if (data->lockflag+3==data->trackflag)
+ curcon->flag |= CONSTRAINT_DISABLE;
+ }
+
+ /* Check targets for constraints */
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(curcon, &targets);
+
+ /* disable and clear constraints targets that are incorrect */
+ for (ct= targets.first; ct; ct= ct->next) {
+ /* general validity checks (for those constraints that need this) */
+ if (exist_object(ct->tar) == 0) {
+ ct->tar = NULL;
+ curcon->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (ct->tar == owner) {
+ if (!get_named_bone(get_armature(owner), ct->subtarget)) {
+ curcon->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+
+ /* target checks for specific constraints */
+ if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) {
+ if (ct->tar) {
+ if (ct->tar->type != OB_CURVE) {
+ ct->tar= NULL;
+ curcon->flag |= CONSTRAINT_DISABLE;
+ }
+ else {
+ Curve *cu= ct->tar->data;
+
+ /* auto-set 'Path' setting on curve so this works */
+ cu->flag |= CU_PATH;
+ }
+ }
+ }
+ }
+
+ /* free any temporary targets */
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(curcon, &targets, 0);
+ }
+ }
+ }
+}
+
+static void test_bonelist_constraints (Object *owner, ListBase *list)
+{
+ Bone *bone;
+
+ for (bone = list->first; bone; bone = bone->next) {
+ test_constraints(owner, bone->name);
+ test_bonelist_constraints(owner, &bone->childbase);
+ }
+}
+
+void object_test_constraints (Object *owner)
+{
+ test_constraints(owner, "");
+
+ if (owner->type==OB_ARMATURE) {
+ bArmature *arm= get_armature(owner);
+
+ if (arm)
+ test_bonelist_constraints(owner, &arm->bonebase);
+ }
+}
+
+/* ********************** CONSTRAINT-SPECIFIC STUFF ********************* */
+
+/* ------------- Child-Of Constraint ------------------ */
+
+/* ChildOf Constraint - set inverse callback */
+void childof_const_setinv (void *conv, void *scenev)
+{
+ bConstraint *con= (bConstraint *)conv;
+ Scene *scene= (Scene *)scenev;
+ bChildOfConstraint *data= (bChildOfConstraint *)con->data;
+ Object *ob= OBACT;
+ bPoseChannel *pchan= NULL;
+
+ /* try to find a pose channel */
+ if (ob && ob->pose)
+ pchan= get_active_posechannel(ob);
+
+ /* calculate/set inverse matrix */
+ if (pchan) {
+ float pmat[4][4], cinf;
+ float imat[4][4], tmat[4][4];
+
+ /* make copy of pchan's original pose-mat (for use later) */
+ Mat4CpyMat4(pmat, pchan->pose_mat);
+
+ /* disable constraint for pose to be solved without it */
+ cinf= con->enforce;
+ con->enforce= 0.0f;
+
+ /* solve pose without constraint */
+ where_is_pose(scene, ob);
+
+ /* determine effect of constraint by removing the newly calculated
+ * pchan->pose_mat from the original pchan->pose_mat, thus determining
+ * the effect of the constraint
+ */
+ Mat4Invert(imat, pchan->pose_mat);
+ Mat4MulMat4(tmat, imat, pmat);
+ Mat4Invert(data->invmat, tmat);
+
+ /* recalculate pose with new inv-mat */
+ con->enforce= cinf;
+ where_is_pose(scene, ob);
+ }
+ else if (ob) {
+ Object workob;
+ /* use what_does_parent to find inverse - just like for normal parenting.
+ * NOTE: what_does_parent uses a static workob defined in object.c
+ */
+ what_does_parent(scene, ob, &workob);
+ Mat4Invert(data->invmat, workob.obmat);
+ }
+ else
+ Mat4One(data->invmat);
+}
+
+/* ChildOf Constraint - clear inverse callback */
+void childof_const_clearinv (void *conv, void *unused)
+{
+ bConstraint *con= (bConstraint *)conv;
+ bChildOfConstraint *data= (bChildOfConstraint *)con->data;
+
+ /* simply clear the matrix */
+ Mat4One(data->invmat);
+}
diff --git a/source/blender/editors/object/editgroup.c b/source/blender/editors/object/editgroup.c
new file mode 100644
index 00000000000..b49e2040b03
--- /dev/null
+++ b/source/blender/editors/object/editgroup.c
@@ -0,0 +1,257 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_group_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_depsgraph.h"
+#include "BKE_group.h"
+#include "BKE_global.h"
+#include "BKE_context.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+
+#include "ED_view3d.h"
+#include "ED_space_api.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "object_intern.h"
+
+static int objects_add_active_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= OBACT, *obt;
+ Group *group;
+ int ok = 0;
+
+ if (!ob) return OPERATOR_CANCELLED;
+
+ /* linking to same group requires its own loop so we can avoid
+ looking up the active objects groups each time */
+
+ group= G.main->group.first;
+ while(group) {
+ if(object_in_group(ob, group)) {
+ /* Assign groups to selected objects */
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ obt= base->object;
+ add_to_group(group, obt);
+ obt->flag |= OB_FROMGROUP;
+ base->flag |= OB_FROMGROUP;
+ base->object->recalc= OB_RECALC_OB;
+ ok = 1;
+ }
+ CTX_DATA_END;
+ }
+ group= group->id.next;
+ }
+
+ if (!ok) BKE_report(op->reports, RPT_ERROR, "Active Object contains no groups");
+
+ DAG_scene_sort(CTX_data_scene(C));
+
+ WM_event_add_notifier(C, NC_GROUP|NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+
+}
+
+void GROUP_OT_objects_add_active(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Add Selected To Active Group";
+ ot->description = "Add the object to an object group that contains the active object.";
+ ot->idname= "GROUP_OT_objects_add_active";
+
+ /* api callbacks */
+ ot->exec= objects_add_active_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int objects_remove_active_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= OBACT, *obt;
+ Group *group;
+ int ok = 0;
+
+ if (!ob) return OPERATOR_CANCELLED;
+
+ /* linking to same group requires its own loop so we can avoid
+ looking up the active objects groups each time */
+
+ group= G.main->group.first;
+ while(group) {
+ if(object_in_group(ob, group)) {
+ /* Assign groups to selected objects */
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ obt= base->object;
+ rem_from_group(group, obt);
+ obt->flag &= ~OB_FROMGROUP;
+ base->flag &= ~OB_FROMGROUP;
+ base->object->recalc= OB_RECALC_OB;
+ ok = 1;
+ }
+ CTX_DATA_END;
+ }
+ group= group->id.next;
+ }
+
+ if (!ok) BKE_report(op->reports, RPT_ERROR, "Active Object contains no groups");
+
+ DAG_scene_sort(CTX_data_scene(C));
+
+ WM_event_add_notifier(C, NC_GROUP|NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+
+}
+
+void GROUP_OT_objects_remove_active(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Remove Selected From active group";
+ ot->description = "Remove the object from an object group that contains the active object.";
+ ot->idname= "GROUP_OT_objects_remove_active";
+
+ /* api callbacks */
+ ot->exec= objects_remove_active_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int group_remove_exec(bContext *C, wmOperator *op)
+{
+ Group *group= NULL;
+
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ group = NULL;
+ while( (group = find_group(base->object, group)) ) {
+ rem_from_group(group, base->object);
+ }
+ base->object->flag &= ~OB_FROMGROUP;
+ base->flag &= ~OB_FROMGROUP;
+ base->object->recalc= OB_RECALC_OB;
+ }
+ CTX_DATA_END;
+
+ DAG_scene_sort(CTX_data_scene(C));
+
+ WM_event_add_notifier(C, NC_GROUP|NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+
+}
+
+void GROUP_OT_objects_remove(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Remove from group";
+ ot->description = "Remove selected objects from all groups.";
+ ot->idname= "GROUP_OT_objects_remove";
+
+ /* api callbacks */
+ ot->exec= group_remove_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int group_create_exec(bContext *C, wmOperator *op)
+{
+ Group *group= NULL;
+ char gid[32]; //group id
+
+ RNA_string_get(op->ptr, "GID", gid);
+
+ group= add_group(gid);
+
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ add_to_group(group, base->object);
+ base->object->flag |= OB_FROMGROUP;
+ base->flag |= OB_FROMGROUP;
+ base->object->recalc= OB_RECALC_OB;
+ }
+ CTX_DATA_END;
+
+ DAG_scene_sort(CTX_data_scene(C));
+
+ WM_event_add_notifier(C, NC_GROUP|NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+
+}
+
+void GROUP_OT_group_create(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Create New Group";
+ ot->description = "Create an object group.";
+ ot->idname= "GROUP_OT_group_create";
+
+ /* api callbacks */
+ ot->exec= group_create_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_string(ot->srna, "GID", "Group", 32, "Name", "Name of the new group");
+}
+
diff --git a/source/blender/editors/object/editkey.c b/source/blender/editors/object/editkey.c
new file mode 100644
index 00000000000..913046c5ab8
--- /dev/null
+++ b/source/blender/editors/object/editkey.c
@@ -0,0 +1,562 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, shapekey support
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <string.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_action_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view2d_types.h"
+
+#include "BKE_action.h"
+#include "BKE_anim.h"
+#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+#include "ED_object.h"
+
+#include "object_intern.h"
+
+/* XXX */
+static void BIF_undo_push() {}
+static void error() {}
+/* XXX */
+
+#if 0 // XXX old animation system
+static void default_key_ipo(Scene *scene, Key *key)
+{
+ IpoCurve *icu;
+ BezTriple *bezt;
+
+ key->ipo= add_ipo(scene, "KeyIpo", ID_KE);
+
+ icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
+
+ icu->blocktype= ID_KE;
+ icu->adrcode= KEY_SPEED;
+ icu->flag= IPO_VISIBLE|IPO_SELECT|IPO_AUTO_HORIZ;
+ 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);
+}
+#endif // XXX old animation system
+
+
+/* **************************************** */
+
+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);
+ }
+}
+
+static KeyBlock *add_keyblock(Scene *scene, Key *key)
+{
+ KeyBlock *kb;
+ float curpos= -0.1;
+ int tot;
+
+ kb= key->block.last;
+ if(kb) curpos= kb->pos;
+
+ kb= MEM_callocN(sizeof(KeyBlock), "Keyblock");
+ BLI_addtail(&key->block, kb);
+ kb->type= KEY_CARDINAL;
+ tot= BLI_countlist(&key->block);
+ if(tot==1) strcpy(kb->name, "Basis");
+ else sprintf(kb->name, "Key %d", tot-1);
+ kb->adrcode= tot-1;
+
+ key->totkey++;
+ if(key->totkey==1) key->refkey= kb;
+
+ // XXX kb->pos is the confusing old horizontal-line RVK crap in old IPO Editor...
+ if(key->type == KEY_RELATIVE)
+ kb->pos= curpos+0.1;
+ else {
+#if 0 // XXX old animation system
+ curpos= bsystem_time(scene, 0, (float)CFRA, 0.0);
+ if(calc_ipo_spec(key->ipo, KEY_SPEED, &curpos)==0) {
+ curpos /= 100.0;
+ }
+ kb->pos= curpos;
+
+ sort_keys(key);
+#endif // XXX old animation system
+ }
+ return kb;
+}
+
+void insert_meshkey(Scene *scene, Mesh *me, short rel)
+{
+ Key *key;
+ KeyBlock *kb;
+
+ if(me->key==NULL) {
+ me->key= add_key( (ID *)me);
+
+ if(rel)
+ me->key->type = KEY_RELATIVE;
+// else
+// default_key_ipo(scene, me->key); // XXX old animation system
+ }
+ key= me->key;
+
+ kb= add_keyblock(scene, key);
+
+ mesh_to_key(me, kb);
+}
+
+/* ******************** */
+
+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);
+ }
+
+}
+
+/* exported to python... hrms, should not, use object levels! (ton) */
+void insert_lattkey(Scene *scene, Lattice *lt, short rel)
+{
+ Key *key;
+ KeyBlock *kb;
+
+ if(lt->key==NULL) {
+ lt->key= add_key( (ID *)lt);
+// default_key_ipo(scene, lt->key); // XXX old animation system
+ }
+ key= lt->key;
+
+ kb= add_keyblock(scene, key);
+
+ latt_to_key(lt, kb);
+}
+
+/* ******************************** */
+
+void curve_to_key(Curve *cu, KeyBlock *kb, ListBase *nurb)
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ float *fp;
+ int a, tot;
+
+ /* count */
+ 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[0]= bezt->alfa;
+ fp+= 3; /* alphas */
+ 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;
+ bezt->alfa= fp[0];
+ fp+= 3; /* alphas */
+
+ 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(Scene *scene, Curve *cu, short rel)
+{
+ Key *key;
+ KeyBlock *kb;
+
+ if(cu->key==NULL) {
+ cu->key= add_key( (ID *)cu);
+
+ if (rel)
+ cu->key->type = KEY_RELATIVE;
+// else
+// default_key_ipo(scene, cu->key); // XXX old animation system
+ }
+ key= cu->key;
+
+ kb= add_keyblock(scene, key);
+
+ if(cu->editnurb->first) curve_to_key(cu, kb, cu->editnurb);
+ else curve_to_key(cu, kb, &cu->nurb);
+}
+
+
+/* ******************** */
+
+void insert_shapekey(Scene *scene, Object *ob)
+{
+ if(get_mesh(ob) && get_mesh(ob)->mr) {
+ error("Cannot create shape keys on a multires mesh.");
+ }
+ else {
+ Key *key;
+
+ if(ob->type==OB_MESH) insert_meshkey(scene, ob->data, 1);
+ else if ELEM(ob->type, OB_CURVE, OB_SURF) insert_curvekey(scene, ob->data, 1);
+ else if(ob->type==OB_LATTICE) insert_lattkey(scene, ob->data, 1);
+
+ key= ob_get_key(ob);
+ ob->shapenr= BLI_countlist(&key->block);
+
+ BIF_undo_push("Add Shapekey");
+ }
+}
+
+void delete_key(Scene *scene, Object *ob)
+{
+ KeyBlock *kb, *rkb;
+ Key *key;
+ //IpoCurve *icu;
+
+ key= ob_get_key(ob);
+ if(key==NULL) return;
+
+ kb= BLI_findlink(&key->block, ob->shapenr-1);
+
+ if(kb) {
+ for(rkb= key->block.first; rkb; rkb= rkb->next)
+ if(rkb->relative == ob->shapenr-1)
+ rkb->relative= 0;
+
+ 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);
+
+ for(kb= key->block.first; kb; kb= kb->next) {
+ if(kb->adrcode>=ob->shapenr)
+ kb->adrcode--;
+ }
+
+#if 0 // XXX old animation system
+ if(key->ipo) {
+
+ for(icu= key->ipo->curve.first; icu; icu= icu->next) {
+ if(icu->adrcode==ob->shapenr-1) {
+ BLI_remlink(&key->ipo->curve, icu);
+ free_ipo_curve(icu);
+ break;
+ }
+ }
+ for(icu= key->ipo->curve.first; icu; icu= icu->next)
+ if(icu->adrcode>=ob->shapenr)
+ icu->adrcode--;
+ }
+#endif // XXX old animation system
+
+ if(ob->shapenr>1) ob->shapenr--;
+ }
+
+ if(key->totkey==0) {
+ if(GS(key->from->name)==ID_ME) ((Mesh *)key->from)->key= NULL;
+ else if(GS(key->from->name)==ID_CU) ((Curve *)key->from)->key= NULL;
+ else if(GS(key->from->name)==ID_LT) ((Lattice *)key->from)->key= NULL;
+
+ free_libblock_us(&(G.main->key), key);
+ }
+
+ DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA);
+
+ BIF_undo_push("Delete Shapekey");
+}
+
+void move_keys(Object *ob)
+{
+#if 0
+ /* XXX probably goes away entirely */
+ Key *key;
+ KeyBlock *kb;
+ float div, dy, oldpos, vec[3], dvec[3];
+ int 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==NULL) return;
+
+ key= ob_get_key(ob);
+ if(key==NULL) return;
+
+ /* which kb is involved */
+ kb= BLI_findlink(&key->block, ob->shapenr-1);
+ if(kb==NULL) return;
+
+ oldpos= kb->pos;
+
+ 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 & USER_AUTOGRABGRID);
+ apply_keyb_grid(vec+1, 0.0, 1.0, 0.1, U.flag & USER_AUTOGRABGRID);
+
+ kb->pos= oldpos+vec[1];
+
+ sprintf(str, "Y: %.3f ", vec[1]);
+ headerprint(str);
+
+ xo= mval[0];
+ yo= mval[1];
+
+ force_draw(0);
+ }
+ 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) {
+ kb->pos= oldpos;
+ }
+
+ sort_keys(key);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+ /* for boundbox */
+ editipo_changed(G.sipo, 0);
+
+ BIF_undo_push("Move Shapekey(s)");
+#endif
+}
diff --git a/source/blender/editors/object/editlattice.c b/source/blender/editors/object/editlattice.c
new file mode 100644
index 00000000000..523f38dd432
--- /dev/null
+++ b/source/blender/editors/object/editlattice.c
@@ -0,0 +1,343 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_armature.h"
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_mesh.h"
+#include "BKE_utildefines.h"
+
+#include "ED_object.h"
+#include "ED_view3d.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "object_intern.h"
+
+/* ***************************** */
+
+static int okee() {return 0;}
+
+void free_editLatt(Object *ob)
+{
+ Lattice *lt= ob->data;
+
+ if(lt->editlatt) {
+ if(lt->editlatt->def) MEM_freeN(lt->editlatt->def);
+ if(lt->editlatt->dvert)
+ free_dverts(lt->editlatt->dvert, lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw);
+
+ MEM_freeN(lt->editlatt);
+ lt->editlatt= NULL;
+ }
+}
+
+
+static void setflagsLatt(Object *obedit, int flag)
+{
+ Lattice *lt= obedit->data;
+ BPoint *bp;
+ int a;
+
+ bp= lt->editlatt->def;
+
+ a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
+
+ while(a--) {
+ if(bp->hide==0) {
+ bp->f1= flag;
+ }
+ bp++;
+ }
+}
+
+
+
+void make_editLatt(Object *obedit)
+{
+ Lattice *lt= obedit->data;
+ KeyBlock *actkey;
+
+ free_editLatt(obedit);
+
+ lt= obedit->data;
+
+ actkey = ob_get_keyblock(obedit);
+ if(actkey) {
+ key_to_latt(actkey, lt);
+ }
+
+ lt->editlatt= MEM_dupallocN(lt);
+ lt->editlatt->def= MEM_dupallocN(lt->def);
+
+ if(lt->dvert) {
+ int tot= lt->pntsu*lt->pntsv*lt->pntsw;
+ lt->editlatt->dvert = MEM_mallocN (sizeof (MDeformVert)*tot, "Lattice MDeformVert");
+ copy_dverts(lt->editlatt->dvert, lt->dvert, tot);
+ }
+
+ //BIF_undo_push("Original");
+}
+
+
+void load_editLatt(Object *obedit)
+{
+ Lattice *lt;
+ KeyBlock *actkey;
+ BPoint *bp;
+ float *fp;
+ int tot;
+
+ lt= obedit->data;
+
+ actkey = ob_get_keyblock(obedit);
+ if(actkey) {
+ /* active key: vertices */
+ tot= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
+
+ if(actkey->data) MEM_freeN(actkey->data);
+
+ fp=actkey->data= MEM_callocN(lt->key->elemsize*tot, "actkey->data");
+ actkey->totelem= tot;
+
+ bp= lt->editlatt->def;
+ while(tot--) {
+ VECCOPY(fp, bp->vec);
+ fp+= 3;
+ bp++;
+ }
+ }
+ else {
+
+ MEM_freeN(lt->def);
+
+ lt->def= MEM_dupallocN(lt->editlatt->def);
+
+ lt->flag= lt->editlatt->flag;
+
+ lt->pntsu= lt->editlatt->pntsu;
+ lt->pntsv= lt->editlatt->pntsv;
+ lt->pntsw= lt->editlatt->pntsw;
+
+ lt->typeu= lt->editlatt->typeu;
+ lt->typev= lt->editlatt->typev;
+ lt->typew= lt->editlatt->typew;
+ }
+
+ if(lt->dvert) {
+ free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw);
+ lt->dvert= NULL;
+ }
+
+ if(lt->editlatt->dvert) {
+ int tot= lt->pntsu*lt->pntsv*lt->pntsw;
+
+ lt->dvert = MEM_mallocN (sizeof (MDeformVert)*tot, "Lattice MDeformVert");
+ copy_dverts(lt->dvert, lt->editlatt->dvert, tot);
+ }
+
+}
+
+void remake_editLatt(Object *obedit)
+{
+ if(okee("Reload original data")==0) return;
+
+ make_editLatt(obedit);
+
+ //BIF_undo_push("Reload original");
+}
+
+
+void deselectall_Latt(Object *obedit)
+{
+ Lattice *lt= obedit->data;
+ BPoint *bp;
+ int a;
+
+ bp= lt->editlatt->def;
+
+ a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
+
+ while(a--) {
+ if(bp->hide==0) {
+ if(bp->f1) {
+ setflagsLatt(obedit, 0);
+ //BIF_undo_push("(De)select all");
+ return;
+ }
+ }
+ bp++;
+ }
+ setflagsLatt(obedit, 1);
+ //BIF_undo_push("(De)select all");
+}
+
+static void findnearestLattvert__doClosest(void *userData, BPoint *bp, int x, int y)
+{
+ struct { BPoint *bp; short dist, select, mval[2]; } *data = userData;
+ float temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
+
+ if ((bp->f1 & SELECT)==data->select) temp += 5;
+ if (temp<data->dist) {
+ data->dist = temp;
+
+ data->bp = bp;
+ }
+}
+static BPoint *findnearestLattvert(ViewContext *vc, short mval[2], int sel)
+{
+ /* sel==1: selected gets a disadvantage */
+ /* in nurb and bezt or bp the nearest is written */
+ /* return 0 1 2: handlepunt */
+ struct { BPoint *bp; short dist, select, mval[2]; } data = {0};
+
+ data.dist = 100;
+ data.select = sel;
+ data.mval[0]= mval[0];
+ data.mval[1]= mval[1];
+
+ lattice_foreachScreenVert(vc, findnearestLattvert__doClosest, &data);
+
+ return data.bp;
+}
+
+
+void mouse_lattice(bContext *C, short mval[2], int extend)
+{
+ ViewContext vc;
+ BPoint *bp=0;
+
+ view3d_set_viewcontext(C, &vc);
+
+ bp= findnearestLattvert(&vc, mval, 1);
+
+ if(bp) {
+ if(extend==0) {
+
+ setflagsLatt(vc.obedit, 0);
+ bp->f1 |= SELECT;
+
+ }
+ else {
+ bp->f1 ^= SELECT; /* swap */
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
+ //BIF_undo_push("Select");
+ }
+}
+
+
+/* **************** undo for lattice object ************** */
+
+typedef struct UndoLattice {
+ BPoint *def;
+ int pntsu, pntsv, pntsw;
+} UndoLattice;
+
+static void undoLatt_to_editLatt(void *data, void *edata)
+{
+ UndoLattice *ult= (UndoLattice*)data;
+ Lattice *editlatt= (Lattice *)edata;
+ int a= editlatt->pntsu*editlatt->pntsv*editlatt->pntsw;
+
+ memcpy(editlatt->def, ult->def, a*sizeof(BPoint));
+}
+
+static void *editLatt_to_undoLatt(void *edata)
+{
+ UndoLattice *ult= MEM_callocN(sizeof(UndoLattice), "UndoLattice");
+ Lattice *editlatt= (Lattice *)edata;
+
+ ult->def= MEM_dupallocN(editlatt->def);
+ ult->pntsu= editlatt->pntsu;
+ ult->pntsv= editlatt->pntsv;
+ ult->pntsw= editlatt->pntsw;
+
+ return ult;
+}
+
+static void free_undoLatt(void *data)
+{
+ UndoLattice *ult= (UndoLattice*)data;
+
+ if(ult->def) MEM_freeN(ult->def);
+ MEM_freeN(ult);
+}
+
+static int validate_undoLatt(void *data, void *edata)
+{
+ UndoLattice *ult= (UndoLattice*)data;
+ Lattice *editlatt= (Lattice *)edata;
+
+ return (ult->pntsu == editlatt->pntsu &&
+ ult->pntsv == editlatt->pntsv &&
+ ult->pntsw == editlatt->pntsw);
+}
+
+static void *get_editlatt(bContext *C)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ if(obedit && obedit->type==OB_LATTICE) {
+ Lattice *lt= obedit->data;
+ return lt->editlatt;
+ }
+ return NULL;
+}
+
+
+/* and this is all the undo system needs to know */
+void undo_push_lattice(bContext *C, char *name)
+{
+ undo_editmode_push(C, name, get_editlatt, free_undoLatt, undoLatt_to_editLatt, editLatt_to_undoLatt, validate_undoLatt);
+}
+
+
+
+/***/
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
new file mode 100644
index 00000000000..eeba0ad22ae
--- /dev/null
+++ b/source/blender/editors/object/object_edit.c
@@ -0,0 +1,6523 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2002-2008 full recode
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "IMB_imbuf_types.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_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_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_nla_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_fluidsim.h"
+#include "DNA_object_force.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_property_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_world_types.h"
+#include "DNA_modifier_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_ghash.h"
+#include "BLI_rand.h"
+
+#include "BKE_action.h"
+#include "BKE_anim.h"
+#include "BKE_armature.h"
+#include "BKE_booleanops.h"
+#include "BKE_constraint.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_blender.h"
+#include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_effect.h"
+#include "BKE_font.h"
+#include "BKE_global.h"
+#include "BKE_group.h"
+#include "BKE_image.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_nla.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+#include "BKE_property.h"
+#include "BKE_report.h"
+#include "BKE_sca.h"
+#include "BKE_scene.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+#include "BKE_modifier.h"
+
+#include "ED_anim_api.h"
+#include "ED_armature.h"
+#include "ED_curve.h"
+#include "ED_particle.h"
+#include "ED_mesh.h"
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+#include "ED_view3d.h"
+
+#include "BMF_Api.h"
+
+#include "BIF_transform.h"
+
+#include "UI_interface.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+/* for menu/popup icons etc etc*/
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "object_intern.h" // own include
+
+/* ************* XXX **************** */
+static void error() {}
+static void waitcursor() {}
+static int pupmenu() {return 0;}
+static int pupmenu_col() {return 0;}
+static int okee() {return 0;}
+
+/* port over here */
+static bContext *C;
+static void error_libdata() {}
+
+/* ********************************** */
+
+/* --------------------------------- */
+
+/* simple API for object selection, rather than just using the flag
+ * this takes into account the 'restrict selection in 3d view' flag.
+ * deselect works always, the restriction just prevents selection */
+
+/* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! */
+
+void ED_base_object_select(Base *base, short mode)
+{
+ if (base) {
+ if (mode==BA_SELECT) {
+ if (!(base->object->restrictflag & OB_RESTRICT_SELECT))
+ if (mode==BA_SELECT) base->flag |= SELECT;
+ }
+ else if (mode==BA_DESELECT) {
+ base->flag &= ~SELECT;
+ }
+ base->object->flag= base->flag;
+ }
+}
+
+/* also to set active NULL */
+void ED_base_object_activate(bContext *C, Base *base)
+{
+ Scene *scene= CTX_data_scene(C);
+ Base *tbase;
+
+ /* activating a non-mesh, should end a couple of modes... */
+ if(base && base->object->type!=OB_MESH)
+ ED_view3d_exit_paint_modes(C);
+
+ /* sets scene->basact */
+ BASACT= base;
+
+ if(base) {
+
+ /* XXX old signals, remember to handle notifiers now! */
+ // select_actionchannel_by_name(base->object->action, "Object", 1);
+
+ /* disable temporal locks */
+ for(tbase=FIRSTBASE; tbase; tbase= tbase->next) {
+ if(base!=tbase && (tbase->object->shapeflag & OB_SHAPE_TEMPLOCK)) {
+ tbase->object->shapeflag &= ~OB_SHAPE_TEMPLOCK;
+ DAG_object_flush_update(scene, tbase->object, OB_RECALC_DATA);
+ }
+ }
+ WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);
+ }
+ else
+ WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, NULL);
+}
+
+
+/*
+ * Returns true if the Object data is a from an external blend file (libdata)
+ */
+int object_data_is_libdata(Object *ob)
+{
+ if (!ob) return 0;
+ if (ob->proxy) return 0;
+ if (ob->id.lib) return 1;
+ if (!ob->data) return 0;
+ if (((ID *)ob->data)->lib) return 1;
+ return 0;
+}
+
+
+
+/* exported */
+void ED_object_base_init_from_view(bContext *C, Base *base)
+{
+ View3D *v3d= CTX_wm_view3d(C);
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= base->object;
+
+ if (scene==NULL)
+ return;
+
+ if (v3d==NULL) {
+ base->lay = scene->lay;
+ VECCOPY(ob->loc, scene->cursor);
+ }
+ else {
+ 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, scene->cursor);
+ }
+
+ if (U.flag & USER_ADD_VIEWALIGNED) {
+ ARegion *ar= CTX_wm_region(C);
+ if(ar) {
+ RegionView3D *rv3d= ar->regiondata;
+
+ rv3d->viewquat[0]= -rv3d->viewquat[0];
+ QuatToEul(rv3d->viewquat, ob->rot);
+ rv3d->viewquat[0]= -rv3d->viewquat[0];
+ }
+ }
+ }
+ where_is_object(scene, ob);
+}
+
+/* ******************* add object operator ****************** */
+
+static EnumPropertyItem prop_object_types[] = {
+ {OB_EMPTY, "EMPTY", "Empty", ""},
+ {OB_MESH, "MESH", "Mesh", ""},
+ {OB_CURVE, "CURVE", "Curve", ""},
+ {OB_SURF, "SURFACE", "Surface", ""},
+ {OB_FONT, "TEXT", "Text", ""},
+ {OB_MBALL, "META", "Meta", ""},
+ {OB_LAMP, "LAMP", "Lamp", ""},
+ {OB_CAMERA, "CAMERA", "Camera", ""},
+ {OB_ARMATURE, "ARMATURE", "Armature", ""},
+ {OB_LATTICE, "LATTICE", "Lattice", ""},
+ {0, NULL, NULL, NULL}
+};
+
+
+
+void add_object_draw(Scene *scene, View3D *v3d, int type) /* for toolbox or menus, only non-editmode stuff */
+{
+ /* keep here to get things compile, remove later */
+}
+
+/* for object add primitive operators */
+static Object *object_add_type(bContext *C, int type)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob;
+
+ /* XXX hrms, this is editor level operator, remove? */
+ ED_view3d_exit_paint_modes(C);
+
+ /* for as long scene has editmode... */
+ if (CTX_data_edit_object(C))
+ ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* freedata, and undo */
+
+ /* deselects all, sets scene->basact */
+ ob= add_object(scene, type);
+ /* editor level activate, notifiers */
+ ED_base_object_activate(C, BASACT);
+
+ /* more editor stuff */
+ ED_object_base_init_from_view(C, BASACT);
+
+ DAG_scene_sort(scene);
+
+ return ob;
+}
+
+/* for object add operator */
+static int object_add_exec(bContext *C, wmOperator *op)
+{
+ object_add_type(C, RNA_int_get(op->ptr, "type"));
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_object_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Object";
+ ot->description = "Add an object to the scene.";
+ ot->idname= "OBJECT_OT_object_add";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= object_add_exec;
+
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", prop_object_types, 0, "Type", "");
+}
+
+/* ***************** add primitives *************** */
+/* ****** work both in and outside editmode ****** */
+
+static EnumPropertyItem prop_mesh_types[] = {
+ {0, "PLANE", "Plane", ""},
+ {1, "CUBE", "Cube", ""},
+ {2, "CIRCLE", "Circle", ""},
+ {3, "UVSPHERE", "UVsphere", ""},
+ {4, "ICOSPHERE", "Icosphere", ""},
+ {5, "CYLINDER", "Cylinder", ""},
+ {6, "CONE", "Cone", ""},
+ {7, "GRID", "Grid", ""},
+ {8, "MONKEY", "Monkey", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int object_add_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ int newob= 0;
+
+ if(obedit==NULL || obedit->type!=OB_MESH) {
+ object_add_type(C, OB_MESH);
+ ED_object_enter_editmode(C, 0);
+ newob = 1;
+ }
+ else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ switch(RNA_enum_get(op->ptr, "type")) {
+ case 0:
+ WM_operator_name_call(C, "MESH_OT_primitive_plane_add", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ case 1:
+ WM_operator_name_call(C, "MESH_OT_primitive_cube_add", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ case 2:
+ WM_operator_name_call(C, "MESH_OT_primitive_circle_add", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ case 3:
+ WM_operator_name_call(C, "MESH_OT_primitive_uv_sphere_add", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ case 4:
+ WM_operator_name_call(C, "MESH_OT_primitive_ico_sphere_add", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ case 5:
+ WM_operator_name_call(C, "MESH_OT_primitive_cylinder_add", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ case 6:
+ WM_operator_name_call(C, "MESH_OT_primitive_cone_add", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ case 7:
+ WM_operator_name_call(C, "MESH_OT_primitive_grid_add", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ case 8:
+ WM_operator_name_call(C, "MESH_OT_primitive_monkey_add", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ }
+ /* userdef */
+ if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
+ ED_object_exit_editmode(C, EM_FREEDATA);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void OBJECT_OT_mesh_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Mesh";
+ ot->description = "Add a mesh object to the scene.";
+ ot->idname= "OBJECT_OT_mesh_add";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= object_add_mesh_exec;
+
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= 0;
+
+ RNA_def_enum(ot->srna, "type", prop_mesh_types, 0, "Primitive", "");
+}
+
+static EnumPropertyItem prop_curve_types[] = {
+ {CU_BEZIER|CU_2D|CU_PRIM_CURVE, "BEZIER_CURVE", "Bezier Curve", ""},
+ {CU_BEZIER|CU_2D|CU_PRIM_CIRCLE, "BEZIER_CIRCLE", "Bezier Circle", ""},
+ {CU_NURBS|CU_2D|CU_PRIM_CURVE, "NURBS_CURVE", "NURBS Curve", ""},
+ {CU_NURBS|CU_2D|CU_PRIM_CIRCLE, "NURBS_CIRCLE", "NURBS Circle", ""},
+ {CU_NURBS|CU_2D|CU_PRIM_PATH, "PATH", "Path", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int object_add_curve_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb;
+ Nurb *nu;
+ int newob= 0;
+
+ if(obedit==NULL || obedit->type!=OB_CURVE) {
+ object_add_type(C, OB_CURVE);
+ ED_object_enter_editmode(C, 0);
+ newob = 1;
+ }
+ else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ obedit= CTX_data_edit_object(C);
+ nu= add_nurbs_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
+ editnurb= curve_get_editcurve(obedit);
+ BLI_addtail(editnurb, nu);
+
+ /* userdef */
+ if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
+ ED_object_exit_editmode(C, EM_FREEDATA);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+static int object_add_curve_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ uiMenuItem *head;
+
+ head= uiPupMenuBegin(op->type->name, 0);
+ if(!obedit || obedit->type == OB_CURVE)
+ uiMenuItemsEnumO(head, op->type->idname, "type");
+ else
+ uiMenuItemsEnumO(head, "OBJECT_OT_surface_add", "type");
+ uiPupMenuEnd(C, head);
+
+ return OPERATOR_CANCELLED;
+}
+
+void OBJECT_OT_curve_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Curve";
+ ot->description = "Add a curve object to the scene.";
+ ot->idname= "OBJECT_OT_curve_add";
+
+ /* api callbacks */
+ ot->invoke= object_add_curve_invoke;
+ ot->exec= object_add_curve_exec;
+
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", prop_curve_types, 0, "Primitive", "");
+}
+
+static EnumPropertyItem prop_surface_types[]= {
+ {CU_PRIM_CURVE|CU_NURBS, "NURBS_CURVE", "NURBS Curve", ""},
+ {CU_PRIM_CIRCLE|CU_NURBS, "NURBS_CIRCLE", "NURBS Circle", ""},
+ {CU_PRIM_PATCH|CU_NURBS, "NURBS_SURFACE", "NURBS Surface", ""},
+ {CU_PRIM_TUBE|CU_NURBS, "NURBS_TUBE", "NURBS Tube", ""},
+ {CU_PRIM_SPHERE|CU_NURBS, "NURBS_SPHERE", "NURBS Sphere", ""},
+ {CU_PRIM_DONUT|CU_NURBS, "NURBS_DONUT", "NURBS Donut", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int object_add_surface_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb;
+ Nurb *nu;
+ int newob= 0;
+
+ if(obedit==NULL || obedit->type!=OB_SURF) {
+ object_add_type(C, OB_SURF);
+ ED_object_enter_editmode(C, 0);
+ newob = 1;
+ }
+ else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ obedit= CTX_data_edit_object(C);
+ nu= add_nurbs_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
+ editnurb= curve_get_editcurve(obedit);
+ BLI_addtail(editnurb, nu);
+
+ /* userdef */
+ if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
+ ED_object_exit_editmode(C, EM_FREEDATA);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_surface_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Surface";
+ ot->description = "Add a surface object to the scene.";
+ ot->idname= "OBJECT_OT_surface_add";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= object_add_surface_exec;
+
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", prop_surface_types, 0, "Primitive", "");
+}
+
+static int object_add_text_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+
+ if(obedit && obedit->type==OB_FONT)
+ return OPERATOR_CANCELLED;
+
+ object_add_type(C, OB_FONT);
+ obedit= CTX_data_active_object(C);
+
+ if(U.flag & USER_ADD_EDITMODE)
+ ED_object_enter_editmode(C, 0);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_text_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Text";
+ ot->description = "Add a text object to the scene";
+ ot->idname= "OBJECT_OT_text_add";
+
+ /* api callbacks */
+ ot->exec= object_add_text_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int object_armature_add_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ View3D *v3d= CTX_wm_view3d(C);
+ RegionView3D *rv3d= NULL;
+ int newob= 0;
+
+ if ((obedit==NULL) || (obedit->type != OB_ARMATURE)) {
+ object_add_type(C, OB_ARMATURE);
+ ED_object_enter_editmode(C, 0);
+ newob = 1;
+ }
+ else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ if(v3d)
+ rv3d= CTX_wm_region(C)->regiondata;
+
+ /* v3d and rv3d are allowed to be NULL */
+ add_primitive_bone(CTX_data_scene(C), v3d, rv3d);
+
+ /* userdef */
+ if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
+ ED_object_exit_editmode(C, EM_FREEDATA);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_armature_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Armature";
+ ot->description = "Add an armature object to the scene.";
+ ot->idname= "OBJECT_OT_armature_add";
+
+ /* api callbacks */
+ ot->exec= object_armature_add_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+static int object_primitive_add_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ uiMenuItem *head= uiPupMenuBegin("Add Object", 0);
+
+ uiMenuLevelEnumO(head, "OBJECT_OT_mesh_add", "type");
+ uiMenuLevelEnumO(head, "OBJECT_OT_curve_add", "type");
+ uiMenuLevelEnumO(head, "OBJECT_OT_surface_add", "type");
+ uiMenuItemO(head, 0, "OBJECT_OT_text_add");
+ uiMenuItemEnumO(head, "", 0, "OBJECT_OT_object_add", "type", OB_MBALL);
+ uiMenuItemEnumO(head, "", 0, "OBJECT_OT_object_add", "type", OB_CAMERA);
+ uiMenuItemEnumO(head, "", 0, "OBJECT_OT_object_add", "type", OB_LAMP);
+ uiMenuItemEnumO(head, "", 0, "OBJECT_OT_object_add", "type", OB_EMPTY);
+ uiMenuItemO(head, 0, "OBJECT_OT_armature_add");
+ uiMenuItemEnumO(head, "", 0, "OBJECT_OT_object_add", "type", OB_LATTICE);
+
+ uiPupMenuEnd(C, head);
+
+ /* this operator is only for a menu, not used further */
+ return OPERATOR_CANCELLED;
+}
+
+/* only used as menu */
+void OBJECT_OT_primitive_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Primitive";
+ ot->description = "Add a primitive object.";
+ ot->idname= "OBJECT_OT_primitive_add";
+
+ /* api callbacks */
+ ot->invoke= object_primitive_add_invoke;
+
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= 0;
+}
+
+
+/* ******************************* */
+
+/* remove base from a specific scene */
+/* note: now unlinks constraints as well */
+void ED_base_object_free_and_unlink(Scene *scene, Base *base)
+{
+ BLI_remlink(&scene->base, base);
+ free_libblock_us(&G.main->object, base->object);
+ if(scene->basact==base) scene->basact= NULL;
+ MEM_freeN(base);
+}
+
+static int object_delete_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ int islamp= 0;
+
+ if(CTX_data_edit_object(C))
+ return OPERATOR_CANCELLED;
+
+ ED_view3d_exit_paint_modes(C);
+
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+
+ if(base->object->type==OB_LAMP) islamp= 1;
+
+ /* remove from current scene only */
+ ED_base_object_free_and_unlink(scene, base);
+ }
+ CTX_DATA_END;
+
+ if(islamp) reshadeall_displist(scene); /* only frees displist */
+
+ DAG_scene_sort(scene);
+ ED_anim_dag_flush_update(C);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, CTX_data_scene(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_delete(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Delete Objects";
+ ot->description = "Delete the object.";
+ ot->idname= "OBJECT_OT_delete";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= object_delete_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+
+
+static void single_object_users__forwardModifierLinks(void *userData, Object *ob, Object **obpoin)
+{
+ ID_NEW(*obpoin);
+}
+
+static void copy_object__forwardModifierLinks(void *userData, Object *ob,
+ ID **idpoin)
+{
+ /* this is copied from ID_NEW; it might be better to have a macro */
+ if(*idpoin && (*idpoin)->newid) *idpoin = (*idpoin)->newid;
+}
+
+
+/* after copying objects, copied data should get new pointers */
+static void copy_object_set_idnew(Scene *scene, View3D *v3d, int dupflag)
+{
+ Base *base;
+ Object *ob;
+ Material *ma, *mao;
+ ID *id;
+#if 0 // XXX old animation system
+ Ipo *ipo;
+ bActionStrip *strip;
+#endif // XXX old animation system
+ int a;
+
+ /* XXX check object pointers */
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ ob= base->object;
+ relink_constraints(&ob->constraints);
+ if (ob->pose){
+ bPoseChannel *chan;
+ for (chan = ob->pose->chanbase.first; chan; chan=chan->next){
+ relink_constraints(&chan->constraints);
+ }
+ }
+ modifiers_foreachIDLink(ob, copy_object__forwardModifierLinks, NULL);
+ ID_NEW(ob->parent);
+ ID_NEW(ob->track);
+ ID_NEW(ob->proxy);
+ ID_NEW(ob->proxy_group);
+
+#if 0 // XXX old animation system
+ for(strip= ob->nlastrips.first; strip; strip= strip->next) {
+ bActionModifier *amod;
+ for(amod= strip->modifiers.first; amod; amod= amod->next)
+ ID_NEW(amod->ob);
+ }
+#endif // XXX old animation system
+ }
+ }
+
+ /* materials */
+ if( dupflag & USER_DUP_MAT) {
+ mao= G.main->mat.first;
+ while(mao) {
+ if(mao->id.newid) {
+
+ ma= (Material *)mao->id.newid;
+
+ if(dupflag & USER_DUP_TEX) {
+ for(a=0; a<MAX_MTEX; 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--;
+ }
+ }
+ }
+ }
+#if 0 // XXX old animation system
+ id= (ID *)ma->ipo;
+ if(id) {
+ ID_NEW_US(ma->ipo)
+ else ma->ipo= copy_ipo(ma->ipo);
+ id->us--;
+ }
+#endif // XXX old animation system
+ }
+ mao= mao->id.next;
+ }
+ }
+
+#if 0 // XXX old animation system
+ /* lamps */
+ if( dupflag & USER_DUP_IPO) {
+ Lamp *la= G.main->lamp.first;
+ while(la) {
+ if(la->id.newid) {
+ Lamp *lan= (Lamp *)la->id.newid;
+ id= (ID *)lan->ipo;
+ if(id) {
+ ID_NEW_US(lan->ipo)
+ else lan->ipo= copy_ipo(lan->ipo);
+ id->us--;
+ }
+ }
+ la= la->id.next;
+ }
+ }
+
+ /* ipos */
+ ipo= G.main->ipo.first;
+ while(ipo) {
+ if(ipo->id.lib==NULL && ipo->id.newid) {
+ Ipo *ipon= (Ipo *)ipo->id.newid;
+ IpoCurve *icu;
+ for(icu= ipon->curve.first; icu; icu= icu->next) {
+ if(icu->driver) {
+ ID_NEW(icu->driver->ob);
+ }
+ }
+ }
+ ipo= ipo->id.next;
+ }
+#endif // XXX old animation system
+
+ set_sca_new_poins();
+
+ clear_id_newpoins();
+
+}
+
+static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float *cent)
+{
+ EditVert *eve;
+ int *index, nr, totvert=0;
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f & SELECT) totvert++;
+ }
+ if(totvert==0) return 0;
+
+ *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
+ *tot= totvert;
+ nr= 0;
+ cent[0]= cent[1]= cent[2]= 0.0;
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f & SELECT) {
+ *index= nr; index++;
+ VecAddf(cent, cent, eve->co);
+ }
+ nr++;
+ }
+
+ VecMulf(cent, 1.0f/(float)totvert);
+
+ return totvert;
+}
+
+static int return_editmesh_vgroup(Object *obedit, EditMesh *em, char *name, float *cent)
+{
+ MDeformVert *dvert;
+ EditVert *eve;
+ int i, totvert=0;
+
+ cent[0]= cent[1]= cent[2]= 0.0;
+
+ if(obedit->actdef) {
+
+ /* find the vertices */
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+
+ if(dvert) {
+ for(i=0; i<dvert->totweight; i++){
+ if(dvert->dw[i].def_nr == (obedit->actdef-1)) {
+ totvert++;
+ VecAddf(cent, cent, eve->co);
+ }
+ }
+ }
+ }
+ if(totvert) {
+ bDeformGroup *defGroup = BLI_findlink(&obedit->defbase, obedit->actdef-1);
+ strcpy(name, defGroup->name);
+ VecMulf(cent, 1.0f/(float)totvert);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void select_editmesh_hook(Object *ob, HookModifierData *hmd)
+{
+ Mesh *me= ob->data;
+ EditMesh *em= BKE_mesh_get_editmesh(me);
+ EditVert *eve;
+ int index=0, nr=0;
+
+ for(eve= em->verts.first; eve; eve= eve->next, nr++) {
+ if(nr==hmd->indexar[index]) {
+ eve->f |= SELECT;
+ if(index < hmd->totindex-1) index++;
+ }
+ }
+ EM_select_flush(em);
+
+ BKE_mesh_end_editmesh(me, em);
+}
+
+static int return_editlattice_indexar(Lattice *editlatt, int *tot, int **indexar, float *cent)
+{
+ BPoint *bp;
+ int *index, nr, totvert=0, a;
+
+ /* count */
+ a= editlatt->pntsu*editlatt->pntsv*editlatt->pntsw;
+ bp= editlatt->def;
+ while(a--) {
+ if(bp->f1 & SELECT) {
+ if(bp->hide==0) totvert++;
+ }
+ bp++;
+ }
+
+ if(totvert==0) return 0;
+
+ *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
+ *tot= totvert;
+ nr= 0;
+ cent[0]= cent[1]= cent[2]= 0.0;
+
+ a= editlatt->pntsu*editlatt->pntsv*editlatt->pntsw;
+ bp= editlatt->def;
+ while(a--) {
+ if(bp->f1 & SELECT) {
+ if(bp->hide==0) {
+ *index= nr; index++;
+ VecAddf(cent, cent, bp->vec);
+ }
+ }
+ bp++;
+ nr++;
+ }
+
+ VecMulf(cent, 1.0f/(float)totvert);
+
+ return totvert;
+}
+
+static void select_editlattice_hook(Object *obedit, HookModifierData *hmd)
+{
+ Lattice *lt= obedit->data;
+ BPoint *bp;
+ int index=0, nr=0, a;
+
+ /* count */
+ a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
+ bp= lt->editlatt->def;
+ while(a--) {
+ if(hmd->indexar[index]==nr) {
+ bp->f1 |= SELECT;
+ if(index < hmd->totindex-1) index++;
+ }
+ nr++;
+ bp++;
+ }
+}
+
+static int return_editcurve_indexar(Object *obedit, int *tot, int **indexar, float *cent)
+{
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int *index, a, nr, totvert=0;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->f1 & SELECT) totvert++;
+ if(bezt->f2 & SELECT) totvert++;
+ if(bezt->f3 & SELECT) totvert++;
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp->f1 & SELECT) totvert++;
+ bp++;
+ }
+ }
+ }
+ if(totvert==0) return 0;
+
+ *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
+ *tot= totvert;
+ nr= 0;
+ cent[0]= cent[1]= cent[2]= 0.0;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->f1 & SELECT) {
+ *index= nr; index++;
+ VecAddf(cent, cent, bezt->vec[0]);
+ }
+ nr++;
+ if(bezt->f2 & SELECT) {
+ *index= nr; index++;
+ VecAddf(cent, cent, bezt->vec[1]);
+ }
+ nr++;
+ if(bezt->f3 & SELECT) {
+ *index= nr; index++;
+ VecAddf(cent, cent, bezt->vec[2]);
+ }
+ nr++;
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp->f1 & SELECT) {
+ *index= nr; index++;
+ VecAddf(cent, cent, bp->vec);
+ }
+ nr++;
+ bp++;
+ }
+ }
+ }
+
+ VecMulf(cent, 1.0f/(float)totvert);
+
+ return totvert;
+}
+
+void ED_object_apply_obmat(Object *ob)
+{
+ float mat[3][3], imat[3][3], tmat[3][3];
+
+ /* from obmat to loc rot size */
+
+ if(ob==NULL) return;
+ Mat3CpyMat4(mat, ob->obmat);
+
+ VECCOPY(ob->loc, ob->obmat[3]);
+
+ 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];
+
+}
+
+int hook_getIndexArray(Object *obedit, int *tot, int **indexar, char *name, float *cent_r)
+{
+ *indexar= NULL;
+ *tot= 0;
+ name[0]= 0;
+
+ switch(obedit->type) {
+ case OB_MESH:
+ {
+ Mesh *me= obedit->data;
+ EditMesh *em = BKE_mesh_get_editmesh(me);
+
+ /* check selected vertices first */
+ if( return_editmesh_indexar(em, tot, indexar, cent_r)) {
+ BKE_mesh_end_editmesh(me, em);
+ return 1;
+ } else {
+ int ret = return_editmesh_vgroup(obedit, em, name, cent_r);
+ BKE_mesh_end_editmesh(me, em);
+ return ret;
+ }
+ }
+ case OB_CURVE:
+ case OB_SURF:
+ return return_editcurve_indexar(obedit, tot, indexar, cent_r);
+ case OB_LATTICE:
+ {
+ Lattice *lt= obedit->data;
+ return return_editlattice_indexar(lt->editlatt, tot, indexar, cent_r);
+ }
+ default:
+ return 0;
+ }
+}
+
+static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
+{
+ ListBase *editnurb= curve_get_editcurve(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int index=0, a, nr=0;
+
+ for(nu= editnurb->first; nu; nu= nu->next) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(nr == hmd->indexar[index]) {
+ bezt->f1 |= SELECT;
+ if(index<hmd->totindex-1) index++;
+ }
+ nr++;
+ if(nr == hmd->indexar[index]) {
+ bezt->f2 |= SELECT;
+ if(index<hmd->totindex-1) index++;
+ }
+ nr++;
+ if(nr == hmd->indexar[index]) {
+ bezt->f3 |= SELECT;
+ if(index<hmd->totindex-1) index++;
+ }
+ nr++;
+
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(nr == hmd->indexar[index]) {
+ bp->f1 |= SELECT;
+ if(index<hmd->totindex-1) index++;
+ }
+ nr++;
+ bp++;
+ }
+ }
+ }
+}
+
+void obedit_hook_select(Object *ob, HookModifierData *hmd)
+{
+
+ if(ob->type==OB_MESH) select_editmesh_hook(ob, hmd);
+ else if(ob->type==OB_LATTICE) select_editlattice_hook(ob, hmd);
+ else if(ob->type==OB_CURVE) select_editcurve_hook(ob, hmd);
+ else if(ob->type==OB_SURF) select_editcurve_hook(ob, hmd);
+}
+
+
+void add_hook(Scene *scene, View3D *v3d, int mode)
+{
+ ModifierData *md = NULL;
+ HookModifierData *hmd = NULL;
+ Object *ob=NULL;
+ Object *obedit= scene->obedit; // XXX get from context
+
+ if(obedit==NULL) return;
+
+ /* preconditions */
+ if(mode==2) { /* selected object */
+ Base *base;
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ if(base!=BASACT) {
+ ob= base->object;
+ break;
+ }
+ }
+ }
+ if(ob==NULL) {
+ error("Requires selected Object");
+ return;
+ }
+ }
+ else if(mode!=1) {
+ int maxlen=0, a, nr;
+ char *cp;
+
+ /* make pupmenu with hooks */
+ for(md=obedit->modifiers.first; md; md= md->next) {
+ if (md->type==eModifierType_Hook)
+ maxlen+=32;
+ }
+
+ if(maxlen==0) {
+ error("Object has no hooks yet");
+ return;
+ }
+
+ cp= MEM_callocN(maxlen+32, "temp string");
+ if(mode==3) strcpy(cp, "Remove %t|");
+ else if(mode==4) strcpy(cp, "Reassign %t|");
+ else if(mode==5) strcpy(cp, "Select %t|");
+ else if(mode==6) strcpy(cp, "Clear Offset %t|");
+
+ for(md=obedit->modifiers.first; md; md= md->next) {
+ if (md->type==eModifierType_Hook) {
+ strcat(cp, md->name);
+ strcat(cp, " |");
+ }
+ }
+
+ nr= pupmenu(cp);
+ MEM_freeN(cp);
+
+ if(nr<1) return;
+
+ a= 1;
+ for(md=obedit->modifiers.first; md; md=md->next) {
+ if (md->type==eModifierType_Hook) {
+ if(a==nr) break;
+ a++;
+ }
+ }
+
+ hmd = (HookModifierData*) md;
+ ob= hmd->object;
+ }
+
+ /* do it, new hooks or reassign */
+ if(mode==1 || mode==2 || mode==4) {
+ float cent[3];
+ int tot, ok, *indexar;
+ char name[32];
+
+ ok = hook_getIndexArray(obedit, &tot, &indexar, name, cent);
+
+ if(ok==0) {
+ error("Requires selected vertices or active Vertex Group");
+ }
+ else {
+
+ if(mode==1) {
+ Base *base= BASACT, *newbase;
+
+ ob= add_object(scene, OB_EMPTY);
+ /* set layers OK */
+ newbase= BASACT;
+ newbase->lay= base->lay;
+ ob->lay= newbase->lay;
+
+ /* transform cent to global coords for loc */
+ VecMat4MulVecfl(ob->loc, obedit->obmat, cent);
+
+ /* restore, add_object sets active */
+ BASACT= base;
+ }
+ /* if mode is 2 or 4, ob has been set */
+
+ /* new hook */
+ if(mode==1 || mode==2) {
+ ModifierData *md = obedit->modifiers.first;
+
+ while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
+ md = md->next;
+ }
+
+ hmd = (HookModifierData*) modifier_new(eModifierType_Hook);
+ BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
+ sprintf(hmd->modifier.name, "Hook-%s", ob->id.name+2);
+ }
+ else if (hmd->indexar) MEM_freeN(hmd->indexar); /* reassign, hook was set */
+
+ hmd->object= ob;
+ hmd->indexar= indexar;
+ VECCOPY(hmd->cent, cent);
+ hmd->totindex= tot;
+ BLI_strncpy(hmd->name, name, 32);
+
+ if(mode==1 || mode==2) {
+ /* matrix calculus */
+ /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
+ /* (parentinv ) */
+
+ where_is_object(scene, ob);
+
+ Mat4Invert(ob->imat, ob->obmat);
+ /* apparently this call goes from right to left... */
+ Mat4MulSerie(hmd->parentinv, ob->imat, obedit->obmat, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ }
+ }
+ }
+ else if(mode==3) { /* remove */
+ BLI_remlink(&obedit->modifiers, md);
+ modifier_free(md);
+ }
+ else if(mode==5) { /* select */
+ obedit_hook_select(obedit, hmd);
+ }
+ else if(mode==6) { /* clear offset */
+ where_is_object(scene, ob); /* ob is hook->parent */
+
+ Mat4Invert(ob->imat, ob->obmat);
+ /* this call goes from right to left... */
+ Mat4MulSerie(hmd->parentinv, ob->imat, obedit->obmat, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ }
+
+ DAG_scene_sort(scene);
+}
+
+
+/* use this when the loc/size/rot of the parent has changed but the children should stay in the same place
+ * apply-size-rot or object center for eg */
+static void ignore_parent_tx(Scene *scene, Object *ob )
+{
+ Object workob;
+ Object *ob_child;
+
+ /* a change was made, adjust the children to compensate */
+ for (ob_child=G.main->object.first; ob_child; ob_child=ob_child->id.next) {
+ if (ob_child->parent == ob) {
+ ED_object_apply_obmat(ob_child);
+ what_does_parent(scene, ob_child, &workob);
+ Mat4Invert(ob_child->parentinv, workob.obmat);
+ }
+ }
+}
+
+
+void add_hook_menu(Scene *scene, View3D *v3d)
+{
+ Object *obedit= scene->obedit; // XXX get from context
+ int mode;
+
+ if(obedit==NULL) return;
+
+ if(modifiers_findByType(obedit, eModifierType_Hook))
+ mode= pupmenu("Hooks %t|Add, To New Empty %x1|Add, To Selected Object %x2|Remove... %x3|Reassign... %x4|Select... %x5|Clear Offset...%x6");
+ else
+ mode= pupmenu("Hooks %t|Add, New Empty %x1|Add, To Selected Object %x2");
+
+ if(mode<1) return;
+
+ /* do operations */
+ add_hook(scene, v3d, mode);
+}
+
+/* ******************** clear parent operator ******************* */
+
+static EnumPropertyItem prop_clear_parent_types[] = {
+ {0, "CLEAR", "Clear Parent", ""},
+ {1, "CLEAR_KEEP_TRANSFORM", "Clear and Keep Transformation (Clear Track)", ""},
+ {2, "CLEAR_INVERSE", "Clear Parent Inverse", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* note, poll should check for editable scene */
+static int parent_clear_exec(bContext *C, wmOperator *op)
+{
+
+ CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
+
+ if(RNA_enum_is_equal(op->ptr, "type", "CLEAR")) {
+ ob->parent= NULL;
+ }
+ if(RNA_enum_is_equal(op->ptr, "type", "CLEAR_KEEP_TRANSFORM")) {
+ ob->parent= NULL;
+ ob->track= NULL;
+ ED_object_apply_obmat(ob);
+ }
+ if(RNA_enum_is_equal(op->ptr, "type", "CLEAR_INVERSE")) {
+ Mat4One(ob->parentinv);
+ }
+ ob->recalc |= OB_RECALC;
+ }
+ CTX_DATA_END;
+
+ DAG_scene_sort(CTX_data_scene(C));
+ ED_anim_dag_flush_update(C);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_parent_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Clear parent";
+ ot->description = "Clear the object's parenting.";
+ ot->idname= "OBJECT_OT_parent_clear";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= parent_clear_exec;
+
+ ot->poll= ED_operator_object_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", prop_clear_parent_types, 0, "Type", "");
+}
+
+/* ******************** clear track operator ******************* */
+
+
+static EnumPropertyItem prop_clear_track_types[] = {
+ {0, "CLEAR", "Clear Track", ""},
+ {1, "CLEAR_KEEP_TRANSFORM", "Clear and Keep Transformation (Clear Track)", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* note, poll should check for editable scene */
+static int object_track_clear_exec(bContext *C, wmOperator *op)
+{
+ if(CTX_data_edit_object(C)) {
+ BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in EditMode");
+ return OPERATOR_CANCELLED;
+ }
+ CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
+ ob->track= NULL;
+ ob->recalc |= OB_RECALC;
+
+ if(RNA_enum_is_equal(op->ptr, "type", "CLEAR_KEEP_TRANSFORM")) {
+ ED_object_apply_obmat(ob);
+ }
+ }
+ CTX_DATA_END;
+
+ DAG_scene_sort(CTX_data_scene(C));
+ ED_anim_dag_flush_update(C);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_track_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Clear track";
+ ot->description = "Clear tracking constraint or flag from object.";
+ ot->idname= "OBJECT_OT_track_clear";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= object_track_clear_exec;
+
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", "");
+}
+
+/* *****************Selection Operators******************* */
+static EnumPropertyItem prop_select_types[] = {
+ {0, "EXCLUSIVE", "Exclusive", ""},
+ {1, "EXTEND", "Extend", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* ****** Select by Type ****** */
+
+static int object_select_by_type_exec(bContext *C, wmOperator *op)
+{
+ short obtype, seltype;
+
+ obtype = RNA_enum_get(op->ptr, "type");
+ seltype = RNA_enum_get(op->ptr, "seltype");
+
+ if (seltype == 0) {
+ CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
+ ED_base_object_select(base, BA_DESELECT);
+ }
+ CTX_DATA_END;
+ }
+
+ CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
+ if(base->object->type==obtype) {
+ ED_base_object_select(base, BA_SELECT);
+ }
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_select_by_type(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select By Type";
+ ot->description = "Select all visible objects that are of a type.";
+ ot->idname= "OBJECT_OT_select_by_type";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= object_select_by_type_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "seltype", prop_select_types, 0, "Selection", "Extend selection or clear selection then select");
+ RNA_def_enum(ot->srna, "type", prop_object_types, 1, "Type", "");
+
+}
+/* ****** selection by links *******/
+
+static EnumPropertyItem prop_select_linked_types[] = {
+ {1, "IPO", "Object IPO", ""}, // XXX depreceated animation system stuff...
+ {2, "OBDATA", "Ob Data", ""},
+ {3, "MATERIAL", "Material", ""},
+ {4, "TEXTURE", "Texture", ""},
+ {5, "DUPGROUP", "Dupligroup", ""},
+ {6, "PARTICLE", "Particle System", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int object_select_linked_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob;
+ void *obdata = NULL;
+ Material *mat = NULL, *mat1;
+ Tex *tex=0;
+ int a, b;
+ int nr = RNA_enum_get(op->ptr, "type");
+ short changed = 0, seltype;
+ /* events (nr):
+ * Object Ipo: 1
+ * ObData: 2
+ * Current Material: 3
+ * Current Texture: 4
+ * DupliGroup: 5
+ * PSys: 6
+ */
+
+ seltype = RNA_enum_get(op->ptr, "seltype");
+
+ if (seltype == 0) {
+ CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
+ ED_base_object_select(base, BA_DESELECT);
+ }
+ CTX_DATA_END;
+ }
+
+ ob= OBACT;
+ if(ob==0){
+ BKE_report(op->reports, RPT_ERROR, "No Active Object");
+ return OPERATOR_CANCELLED;
+ }
+
+ if(nr==1) {
+ // XXX old animation system
+ //ipo= ob->ipo;
+ //if(ipo==0) return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
+ }
+ else if(nr==2) {
+ if(ob->data==0) return OPERATOR_CANCELLED;
+ obdata= ob->data;
+ }
+ else if(nr==3 || nr==4) {
+ mat= give_current_material(ob, ob->actcol);
+ if(mat==0) return OPERATOR_CANCELLED;
+ if(nr==4) {
+ if(mat->mtex[ (int)mat->texact ]) tex= mat->mtex[ (int)mat->texact ]->tex;
+ if(tex==0) return OPERATOR_CANCELLED;
+ }
+ }
+ else if(nr==5) {
+ if(ob->dup_group==NULL) return OPERATOR_CANCELLED;
+ }
+ else if(nr==6) {
+ if(ob->particlesystem.first==NULL) return OPERATOR_CANCELLED;
+ }
+ else return OPERATOR_CANCELLED;
+
+ CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
+ if(nr==1) {
+ // XXX old animation system
+ //if(base->object->ipo==ipo) base->flag |= SELECT;
+ //changed = 1;
+ }
+ else if(nr==2) {
+ if(base->object->data==obdata) base->flag |= SELECT;
+ changed = 1;
+ }
+ 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;
+ changed = 1;
+ }
+ else if(mat1 && nr==4) {
+ for(b=0; b<MAX_MTEX; b++) {
+ if(mat1->mtex[b]) {
+ if(tex==mat1->mtex[b]->tex) {
+ base->flag |= SELECT;
+ changed = 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if(nr==5) {
+ if(base->object->dup_group==ob->dup_group) {
+ base->flag |= SELECT;
+ changed = 1;
+ }
+ }
+ else if(nr==6) {
+ /* loop through other, then actives particles*/
+ ParticleSystem *psys;
+ ParticleSystem *psys_act;
+
+ for(psys=base->object->particlesystem.first; psys; psys=psys->next) {
+ for(psys_act=ob->particlesystem.first; psys_act; psys_act=psys_act->next) {
+ if (psys->part == psys_act->part) {
+ base->flag |= SELECT;
+ changed = 1;
+ break;
+ }
+ }
+
+ if (base->flag & SELECT) {
+ break;
+ }
+ }
+ }
+ base->object->flag= base->flag;
+ }
+ CTX_DATA_END;
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void OBJECT_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Linked";
+ ot->description = "Select all visible objects that are linked.";
+ ot->idname= "OBJECT_OT_select_linked";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= object_select_linked_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", prop_select_linked_types, 0, "Type", "");
+ RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
+
+}
+/* ****** selection by layer *******/
+
+static int object_select_by_layer_exec(bContext *C, wmOperator *op)
+{
+ unsigned int layernum;
+ short seltype;
+
+ seltype = RNA_enum_get(op->ptr, "seltype");
+ layernum = RNA_int_get(op->ptr, "layer");
+
+ if (seltype == 0) {
+ CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
+ ED_base_object_select(base, BA_DESELECT);
+ }
+ CTX_DATA_END;
+ }
+
+ CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
+ if(base->lay == (1<< (layernum -1)))
+ ED_base_object_select(base, BA_SELECT);
+ }
+ CTX_DATA_END;
+
+ /* undo? */
+ WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_select_by_layer(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "select by layer";
+ ot->description = "Select all visible objects on a layer.";
+ ot->idname= "OBJECT_OT_select_by_layer";
+
+ /* api callbacks */
+ /*ot->invoke = XXX - need a int grid popup*/
+ ot->exec= object_select_by_layer_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "layer", 1, 1, 20, "Layer", "", 1, 20);
+ RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
+}
+
+/* ****** invert selection *******/
+static int object_select_invert_exec(bContext *C, wmOperator *op)
+{
+ CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
+ if (base->flag & SELECT)
+ ED_base_object_select(base, BA_DESELECT);
+ else
+ ED_base_object_select(base, BA_SELECT);
+ }
+ CTX_DATA_END;
+
+ /* undo? */
+ WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_select_invert(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Invert selection";
+ ot->description = "Invert th select of all visible objects.";
+ ot->idname= "OBJECT_OT_select_invert";
+
+ /* api callbacks */
+ ot->exec= object_select_invert_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+/* ****** (de)select All *******/
+
+static int object_select_de_select_all_exec(bContext *C, wmOperator *op)
+{
+
+ int a=0, ok=0;
+
+ CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
+ if (base->flag & SELECT) {
+ ok= a= 1;
+ break;
+ }
+ else ok=1;
+ }
+ CTX_DATA_END;
+
+ if (!ok) return OPERATOR_PASS_THROUGH;
+
+ CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
+ if (a) ED_base_object_select(base, BA_DESELECT);
+ else ED_base_object_select(base, BA_SELECT);
+ }
+ CTX_DATA_END;
+
+ /* undo? */
+ WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_select_all_toggle(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "deselect all";
+ ot->description = "(de)select all visible objects in scene.";
+ ot->idname= "OBJECT_OT_select_all_toggle";
+
+ /* api callbacks */
+ ot->exec= object_select_de_select_all_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+/* ****** random selection *******/
+
+static int object_select_random_exec(bContext *C, wmOperator *op)
+{
+ float percent;
+ short seltype;
+
+ seltype = RNA_enum_get(op->ptr, "seltype");
+
+ if (seltype == 0) {
+ CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
+ ED_base_object_select(base, BA_DESELECT);
+ }
+ CTX_DATA_END;
+ }
+ percent = RNA_float_get(op->ptr, "percent");
+
+ CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
+ if (BLI_frand() < percent) {
+ ED_base_object_select(base, BA_SELECT);
+ }
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_select_random(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Random select";
+ ot->description = "Set select on random visible objects.";
+ ot->idname= "OBJECT_OT_select_random";
+
+ /* api callbacks */
+ /*ot->invoke= object_select_random_invoke XXX - need a number popup ;*/
+ ot->exec = object_select_random_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_float_percentage(ot->srna, "percent", 0.5f, 0.0f, 1.0f, "Percent", "percentage of objects to randomly select", 0.0001f, 1.0f);
+ RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
+}
+
+/* ******** Clear object Translation *********** */
+
+static int object_location_clear_exec(bContext *C, wmOperator *op)
+{
+ int armature_clear= 0;
+
+ CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
+ if((G.f & G_WEIGHTPAINT)==0) {
+ if ((ob->protectflag & OB_LOCK_LOCX)==0)
+ ob->loc[0]= ob->dloc[0]= 0.0f;
+ if ((ob->protectflag & OB_LOCK_LOCY)==0)
+ ob->loc[1]= ob->dloc[1]= 0.0f;
+ if ((ob->protectflag & OB_LOCK_LOCZ)==0)
+ ob->loc[2]= ob->dloc[2]= 0.0f;
+ }
+ ob->recalc |= OB_RECALC_OB;
+ }
+ CTX_DATA_END;
+
+ if(armature_clear==0) /* in this case flush was done */
+ ED_anim_dag_flush_update(C);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void OBJECT_OT_location_clear(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Clear Object Location";
+ ot->description = "Clear the object's location.";
+ ot->idname= "OBJECT_OT_location_clear";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= object_location_clear_exec;
+ ot->poll= ED_operator_object_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int object_rotation_clear_exec(bContext *C, wmOperator *op)
+{
+ int armature_clear= 0;
+
+ CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
+ if((G.f & G_WEIGHTPAINT)==0) {
+ /* eulers can only get cleared if they are not protected */
+ if ((ob->protectflag & OB_LOCK_ROTX)==0)
+ ob->rot[0]= ob->drot[0]= 0.0f;
+ if ((ob->protectflag & OB_LOCK_ROTY)==0)
+ ob->rot[1]= ob->drot[1]= 0.0f;
+ if ((ob->protectflag & OB_LOCK_ROTZ)==0)
+ ob->rot[2]= ob->drot[2]= 0.0f;
+ }
+ ob->recalc |= OB_RECALC_OB;
+ }
+ CTX_DATA_END;
+
+ if(armature_clear==0) /* in this case flush was done */
+ ED_anim_dag_flush_update(C);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void OBJECT_OT_rotation_clear(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Clear Object Rotation";
+ ot->description = "Clear the object's rotation.";
+ ot->idname= "OBJECT_OT_rotation_clear";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= object_rotation_clear_exec;
+ ot->poll= ED_operator_object_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int object_scale_clear_exec(bContext *C, wmOperator *op)
+{
+ int armature_clear= 0;
+
+ CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
+ if((G.f & G_WEIGHTPAINT)==0) {
+ if ((ob->protectflag & OB_LOCK_SCALEX)==0) {
+ ob->dsize[0]= 0.0f;
+ ob->size[0]= 1.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_SCALEY)==0) {
+ ob->dsize[1]= 0.0f;
+ ob->size[1]= 1.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_SCALEZ)==0) {
+ ob->dsize[2]= 0.0f;
+ ob->size[2]= 1.0f;
+ }
+ }
+ ob->recalc |= OB_RECALC_OB;
+ }
+ CTX_DATA_END;
+
+ if(armature_clear==0) /* in this case flush was done */
+ ED_anim_dag_flush_update(C);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_scale_clear(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Clear Object Scale";
+ ot->description = "Clear the object's scale.";
+ ot->idname= "OBJECT_OT_scale_clear";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= object_scale_clear_exec;
+ ot->poll= ED_operator_object_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int object_origin_clear_exec(bContext *C, wmOperator *op)
+{
+ float *v1, *v3, mat[3][3];
+ int armature_clear= 0;
+
+ CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
+ if(ob->parent) {
+ v1= ob->loc;
+ v3= ob->parentinv[3];
+
+ Mat3CpyMat4(mat, ob->parentinv);
+ VECCOPY(v3, v1);
+ v3[0]= -v3[0];
+ v3[1]= -v3[1];
+ v3[2]= -v3[2];
+ Mat3MulVecfl(mat, v3);
+ }
+ ob->recalc |= OB_RECALC_OB;
+ }
+ CTX_DATA_END;
+
+ if(armature_clear==0) /* in this case flush was done */
+ ED_anim_dag_flush_update(C);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_origin_clear(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Clear Object Origin";
+ ot->description = "Clear the object's origin.";
+ ot->idname= "OBJECT_OT_origin_clear";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= object_origin_clear_exec;
+ ot->poll= ED_operator_object_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ********* clear/set restrict view *********/
+static int object_restrictview_clear_exec(bContext *C, wmOperator *op)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= sa->spacedata.first;
+ Scene *scene= CTX_data_scene(C);
+ Base *base;
+ int changed = 0;
+
+ /* XXX need a context loop to handle such cases */
+ for(base = FIRSTBASE; base; base=base->next){
+ if((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) {
+ base->flag |= SELECT;
+ base->object->flag = base->flag;
+ base->object->restrictflag &= ~OB_RESTRICT_VIEW;
+ changed = 1;
+ }
+ }
+ if (changed) {
+ DAG_scene_sort(scene);
+ WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_restrictview_clear(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Clear restrict view";
+ ot->description = "Reveal the object by setting the restrictview flag.";
+ ot->idname= "OBJECT_OT_restrictview_clear";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= object_restrictview_clear_exec;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static EnumPropertyItem prop_set_restrictview_types[] = {
+ {0, "SELECTED", "Selected", ""},
+ {1, "UNSELECTED", "Unselected ", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int object_restrictview_set_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ short changed = 0;
+
+ CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
+ if(RNA_enum_is_equal(op->ptr, "type", "SELECTED")){
+ if (base->flag & SELECT){
+ base->flag &= ~SELECT;
+ base->object->flag = base->flag;
+ base->object->restrictflag |= OB_RESTRICT_VIEW;
+ changed = 1;
+ if (base==BASACT) {
+ ED_base_object_activate(C, NULL);
+ }
+ }
+ }
+ else if (RNA_enum_is_equal(op->ptr, "type", "UNSELECTED")){
+ if (!(base->flag & SELECT)){
+ base->object->restrictflag |= OB_RESTRICT_VIEW;
+ changed = 1;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if (changed) {
+ DAG_scene_sort(scene);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
+
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_restrictview_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set restrict view";
+ ot->description = "Hide the object by setting the restrictview flag.";
+ ot->idname= "OBJECT_OT_restrictview_set";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= object_restrictview_set_exec;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", prop_set_restrictview_types, 0, "Type", "");
+
+}
+/* ************* Slow Parent ******************* */
+static int object_slowparent_set_exec(bContext *C, wmOperator *op)
+{
+
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+
+ if(base->object->parent) base->object->partype |= PARSLOW;
+ base->object->recalc |= OB_RECALC_OB;
+
+ }
+ CTX_DATA_END;
+
+ ED_anim_dag_flush_update(C);
+
+ WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_slowparent_set(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Set Slow Parent";
+ ot->description = "Set the object's slow parent.";
+ ot->idname= "OBJECT_OT_slow_parent_set";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= object_slowparent_set_exec;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int object_slowparent_clear_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ if(base->object->parent) {
+ if(base->object->partype & PARSLOW) {
+ base->object->partype -= PARSLOW;
+ where_is_object(scene, base->object);
+ base->object->partype |= PARSLOW;
+ base->object->recalc |= OB_RECALC_OB;
+ }
+ }
+
+ }
+ CTX_DATA_END;
+
+ ED_anim_dag_flush_update(C);
+
+ WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_slowparent_clear(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Clear Slow Parent";
+ ot->description = "Clear the object's slow parent.";
+ ot->idname= "OBJECT_OT_slow_parent_clear";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= object_slowparent_clear_exec;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+/* ******************** **************** */
+
+// XXX
+#define BEZSELECTED_HIDDENHANDLES(bezt) ((G.f & G_HIDDENHANDLES) ? (bezt)->f2 & SELECT : BEZSELECTED(bezt))
+/* only in edit mode */
+void make_vertex_parent(Scene *scene, Object *obedit, View3D *v3d)
+{
+ EditVert *eve;
+ Base *base;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ Object *par, *ob;
+ int a, v1=0, v2=0, v3=0, v4=0, nr=1;
+
+ /* we need 1 to 3 selected vertices */
+
+ if(obedit->type==OB_MESH) {
+ Mesh *me= obedit->data;
+ EditMesh *em = BKE_mesh_get_editmesh(me);
+
+ eve= em->verts.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 if(v4==0) v4= nr;
+ else break;
+ }
+ nr++;
+ eve= eve->next;
+ }
+
+ BKE_mesh_end_editmesh(me, em);
+ }
+ else if(ELEM(obedit->type, OB_SURF, OB_CURVE)) {
+ ListBase *editnurb= curve_get_editcurve(obedit);
+
+ nu= editnurb->first;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(BEZSELECTED_HIDDENHANDLES(bezt)) {
+ if(v1==0) v1= nr;
+ else if(v2==0) v2= nr;
+ else if(v3==0) v3= nr;
+ else if(v4==0) v4= 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 if(v4==0) v4= nr;
+ else break;
+ }
+ nr++;
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ }
+ else if(obedit->type==OB_LATTICE) {
+ Lattice *lt= obedit->data;
+
+ a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
+ bp= lt->editlatt->def;
+ while(a--) {
+ if(bp->f1 & SELECT) {
+ if(v1==0) v1= nr;
+ else if(v2==0) v2= nr;
+ else if(v3==0) v3= nr;
+ else if(v4==0) v4= nr;
+ else break;
+ }
+ nr++;
+ bp++;
+ }
+ }
+
+ if(v4 || !((v1 && v2==0 && v3==0) || (v1 && v2 && v3)) ) {
+ error("Select either 1 or 3 vertices to parent to");
+ return;
+ }
+
+ if(okee("Make vertex parent")==0) return;
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ if(base!=BASACT) {
+
+ ob= base->object;
+ ob->recalc |= OB_RECALC;
+ par= BASACT->object->parent;
+
+ while(par) {
+ if(par==ob) break;
+ par= par->parent;
+ }
+ if(par) {
+ error("Loop in parents");
+ }
+ else {
+ Object workob;
+
+ ob->parent= BASACT->object;
+ if(v3) {
+ ob->partype= PARVERT3;
+ ob->par1= v1-1;
+ ob->par2= v2-1;
+ ob->par3= v3-1;
+
+ /* inverse parent matrix */
+ what_does_parent(scene, ob, &workob);
+ Mat4Invert(ob->parentinv, workob.obmat);
+ }
+ else {
+ ob->partype= PARVERT1;
+ ob->par1= v1-1;
+
+ /* inverse parent matrix */
+ what_does_parent(scene, ob, &workob);
+ Mat4Invert(ob->parentinv, workob.obmat);
+ }
+ }
+ }
+ }
+ }
+
+ DAG_scene_sort(scene);
+}
+
+static Object *group_objects_menu(Group *group)
+{
+ GroupObject *go;
+ int len= 0;
+ short a, nr;
+ char *str;
+
+ for(go= group->gobject.first; go; go= go->next) {
+ if(go->ob)
+ len++;
+ }
+ if(len==0) return NULL;
+
+ str= MEM_callocN(40+32*len, "menu");
+
+ strcpy(str, "Make Proxy for: %t");
+ a= strlen(str);
+ for(nr=1, go= group->gobject.first; go; go= go->next, nr++) {
+ a+= sprintf(str+a, "|%s %%x%d", go->ob->id.name+2, nr);
+ }
+
+ a= pupmenu_col(str, 20);
+ MEM_freeN(str);
+ if(a>0) {
+ go= BLI_findlink(&group->gobject, a-1);
+ return go->ob;
+ }
+ return NULL;
+}
+
+
+/* adds empty object to become local replacement data of a library-linked object */
+void make_proxy(Scene *scene)
+{
+ Object *ob= OBACT;
+ Object *gob= NULL;
+
+ if(scene->id.lib) return;
+ if(ob==NULL) return;
+
+
+ if(ob->dup_group && ob->dup_group->id.lib) {
+ gob= ob;
+ /* gives menu with list of objects in group */
+ ob= group_objects_menu(ob->dup_group);
+ }
+ else if(ob->id.lib) {
+ if(okee("Make Proxy Object")==0)
+ return;
+ }
+ else {
+ error("Can only make proxy for a referenced object or group");
+ return;
+ }
+
+ if(ob) {
+ Object *newob;
+ Base *newbase, *oldbase= BASACT;
+ char name[32];
+
+ newob= add_object(scene, OB_EMPTY);
+ if(gob)
+ strcpy(name, gob->id.name+2);
+ else
+ strcpy(name, ob->id.name+2);
+ strcat(name, "_proxy");
+ rename_id(&newob->id, name);
+
+ /* set layers OK */
+ newbase= BASACT; /* add_object sets active... */
+ newbase->lay= oldbase->lay;
+ newob->lay= newbase->lay;
+
+ /* remove base, leave user count of object, it gets linked in object_make_proxy */
+ if(gob==NULL) {
+ BLI_remlink(&scene->base, oldbase);
+ MEM_freeN(oldbase);
+ }
+ object_make_proxy(newob, ob, gob);
+
+ DAG_scene_sort(scene);
+ DAG_object_flush_update(scene, newob, OB_RECALC);
+ }
+}
+
+/* ******************** make parent operator *********************** */
+
+#define PAR_OBJECT 0
+#define PAR_ARMATURE 1
+#define PAR_BONE 2
+#define PAR_CURVE 3
+#define PAR_FOLLOW 4
+#define PAR_PATH_CONST 5
+#define PAR_LATTICE 6
+#define PAR_VERTEX 7
+#define PAR_TRIA 8
+
+static EnumPropertyItem prop_make_parent_types[] = {
+ {PAR_OBJECT, "OBJECT", "Object", ""},
+ {PAR_ARMATURE, "ARMATURE", "Armature Deform", ""},
+ {PAR_BONE, "BONE", "Bone", ""},
+ {PAR_CURVE, "CURVE", "Curve Deform", ""},
+ {PAR_FOLLOW, "FOLLOW", "Follow Path", ""},
+ {PAR_PATH_CONST, "PATH_CONST", "Path Constraint", ""},
+ {PAR_LATTICE, "LATTICE", "Lattice Deform", ""},
+ {PAR_VERTEX, "VERTEX", "Vertex", ""},
+ {PAR_TRIA, "TRIA", "Triangle", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int test_parent_loop(Object *par, Object *ob)
+{
+ /* test if 'ob' is a parent somewhere in par's parents */
+
+ if(par == NULL) return 0;
+ if(ob == par) return 1;
+
+ return test_parent_loop(par->parent, ob);
+}
+
+
+static int parent_set_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *par= CTX_data_active_object(C);
+ bPoseChannel *pchan= NULL;
+ int partype= RNA_enum_get(op->ptr, "type");
+
+ par->recalc |= OB_RECALC_OB;
+
+ /* preconditions */
+ if(partype==PAR_FOLLOW || partype==PAR_PATH_CONST) {
+ if(par->type!=OB_CURVE)
+ return OPERATOR_CANCELLED;
+ else {
+ Curve *cu= par->data;
+
+ if((cu->flag & CU_PATH)==0) {
+ cu->flag |= CU_PATH|CU_FOLLOW;
+ makeDispListCurveTypes(scene, par, 0); /* force creation of path data */
+ }
+ else cu->flag |= CU_FOLLOW;
+
+ /* fall back on regular parenting now */
+ partype= PAR_OBJECT;
+ }
+ }
+ else if(partype==PAR_BONE) {
+ pchan= get_active_posechannel(par);
+
+ if(pchan==NULL) {
+ error("No active Bone");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ /* context itterator */
+ CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
+
+ if(ob!=par) {
+
+ if( test_parent_loop(par, ob) ) {
+ error("Loop in parents");
+ }
+ else {
+ Object workob;
+
+ /* apply transformation of previous parenting */
+ ED_object_apply_obmat(ob);
+
+ ob->parent= par;
+
+ /* handle types */
+ if (pchan)
+ strcpy (ob->parsubstr, pchan->name);
+ else
+ ob->parsubstr[0]= 0;
+
+ /* constraint */
+ if(partype==PAR_PATH_CONST) {
+ bConstraint *con;
+ bFollowPathConstraint *data;
+ float cmat[4][4], vec[3];
+
+ con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
+ strcpy (con->name, "AutoPath");
+
+ data = con->data;
+ data->tar = par;
+
+ add_constraint_to_object(con, ob);
+
+ get_constraint_target_matrix(con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra - give_timeoffset(ob));
+ VecSubf(vec, ob->obmat[3], cmat[3]);
+
+ ob->loc[0] = vec[0];
+ ob->loc[1] = vec[1];
+ }
+ else if(partype==PAR_ARMATURE && ob->type==OB_MESH && par->type == OB_ARMATURE) {
+
+ if(1) {
+ /* Prompt the user as to whether he wants to
+ * add some vertex groups based on the bones
+ * in the parent armature.
+ */
+ create_vgroups_from_armature(scene, ob, par);
+
+ /* get corrected inverse */
+ ob->partype= PAROBJECT;
+ what_does_parent(scene, ob, &workob);
+
+ ob->partype= PARSKEL;
+ }
+ else
+ what_does_parent(scene, ob, &workob);
+
+ Mat4Invert(ob->parentinv, workob.obmat);
+ }
+ else {
+ /* calculate inverse parent matrix */
+ what_does_parent(scene, ob, &workob);
+ Mat4Invert(ob->parentinv, workob.obmat);
+ }
+
+ ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
+
+ if( ELEM3(partype, PAR_CURVE, PAR_ARMATURE, PAR_LATTICE) )
+ ob->partype= PARSKEL; /* note, dna define, not operator property */
+ else
+ ob->partype= PAROBJECT; /* note, dna define, not operator property */
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ DAG_scene_sort(CTX_data_scene(C));
+ ED_anim_dag_flush_update(C);
+
+ return OPERATOR_FINISHED;
+}
+
+static int parent_set_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Object *ob= CTX_data_active_object(C);
+ uiMenuItem *head= uiPupMenuBegin("Set Parent To", 0);
+
+ uiMenuContext(head, WM_OP_EXEC_DEFAULT);
+ uiMenuItemEnumO(head, "", 0, "OBJECT_OT_parent_set", "type", PAR_OBJECT);
+
+ /* ob becomes parent, make the associated menus */
+ if(ob->type==OB_ARMATURE) {
+ uiMenuItemEnumO(head, "", 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE);
+ uiMenuItemEnumO(head, "", 0, "OBJECT_OT_parent_set", "type", PAR_BONE);
+ }
+ else if(ob->type==OB_CURVE) {
+ uiMenuItemEnumO(head, "", 0, "OBJECT_OT_parent_set", "type", PAR_CURVE);
+ uiMenuItemEnumO(head, "", 0, "OBJECT_OT_parent_set", "type", PAR_FOLLOW);
+ uiMenuItemEnumO(head, "", 0, "OBJECT_OT_parent_set", "type", PAR_PATH_CONST);
+ }
+ else if(ob->type == OB_LATTICE) {
+ uiMenuItemEnumO(head, "", 0, "OBJECT_OT_parent_set", "type", PAR_LATTICE);
+ }
+
+ uiPupMenuEnd(C, head);
+
+ return OPERATOR_CANCELLED;
+}
+
+
+void OBJECT_OT_parent_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Make parent";
+ ot->description = "Set the object's parenting.";
+ ot->idname= "OBJECT_OT_parent_set";
+
+ /* api callbacks */
+ ot->invoke= parent_set_invoke;
+ ot->exec= parent_set_exec;
+
+ ot->poll= ED_operator_object_active;
+
+ /* flags */
+ ot->flag= 0;
+
+ RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
+}
+
+/* *** make track ***** */
+static EnumPropertyItem prop_make_track_types[] = {
+ {1, "TRACKTO", "TrackTo Constraint", ""},
+ {2, "LOCKTRACK", "LockTrack Constraint", ""},
+ {3, "OLDTRACK", "Old Track", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int track_set_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+
+ if(RNA_enum_is_equal(op->ptr, "type", "TRACKTO")){
+ bConstraint *con;
+ bTrackToConstraint *data;
+
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ if(base!=BASACT) {
+ con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
+ strcpy (con->name, "AutoTrack");
+
+ data = con->data;
+ data->tar = BASACT->object;
+ base->object->recalc |= OB_RECALC;
+
+ /* Lamp and Camera track differently by default */
+ if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
+ data->reserved1 = TRACK_nZ;
+ data->reserved2 = UP_Y;
+ }
+
+ add_constraint_to_object(con, base->object);
+ }
+ }
+ CTX_DATA_END;
+ }
+ else if(RNA_enum_is_equal(op->ptr, "type", "LOCKTRACK")){
+ bConstraint *con;
+ bLockTrackConstraint *data;
+
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ if(base!=BASACT) {
+ con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
+ strcpy (con->name, "AutoTrack");
+
+ data = con->data;
+ data->tar = BASACT->object;
+ base->object->recalc |= OB_RECALC;
+
+ /* Lamp and Camera track differently by default */
+ if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
+ data->trackflag = TRACK_nZ;
+ data->lockflag = LOCK_Y;
+ }
+
+ add_constraint_to_object(con, base->object);
+ }
+ }
+ CTX_DATA_END;
+ }
+ else if(RNA_enum_is_equal(op->ptr, "type", "OLDTRACK")){
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ if(base!=BASACT) {
+ base->object->track= BASACT->object;
+ base->object->recalc |= OB_RECALC;
+ }
+ }
+ CTX_DATA_END;
+ }
+ DAG_scene_sort(CTX_data_scene(C));
+ ED_anim_dag_flush_update(C);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_track_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Make Track";
+ ot->description = "Make the object track another object, either by constraint or old way or locked track.";
+ ot->idname= "OBJECT_OT_track_set";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= track_set_exec;
+
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
+}
+
+/* ************* Make Dupli Real ********* */
+static void make_object_duplilist_real(Scene *scene, View3D *v3d, Base *base)
+{
+ Base *basen;
+ Object *ob;
+ ListBase *lb;
+ DupliObject *dob;
+
+ if(!base && !(base = BASACT))
+ return;
+
+ if(!(base->object->transflag & OB_DUPLI))
+ return;
+
+ lb= object_duplilist(scene, base->object);
+
+ for(dob= lb->first; dob; dob= dob->next) {
+ ob= copy_object(dob->ob);
+ /* font duplis can have a totcol without material, we get them from parent
+ * should be implemented better...
+ */
+ if(ob->mat==NULL) ob->totcol= 0;
+
+ basen= MEM_dupallocN(base);
+ basen->flag &= ~OB_FROMDUPLI;
+ BLI_addhead(&scene->base, basen); /* addhead: othwise eternal loop */
+ basen->object= ob;
+ ob->ipo= NULL; /* make sure apply works */
+ ob->parent= ob->track= NULL;
+ ob->disp.first= ob->disp.last= NULL;
+ ob->transflag &= ~OB_DUPLI;
+
+ Mat4CpyMat4(ob->obmat, dob->mat);
+ ED_object_apply_obmat(ob);
+ }
+
+ copy_object_set_idnew(scene, v3d, 0);
+
+ free_object_duplilist(lb);
+
+ base->object->transflag &= ~OB_DUPLI;
+}
+
+
+static int object_dupli_set_real_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= sa->spacedata.first;
+
+ clear_id_newpoins();
+
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ make_object_duplilist_real(scene, v3d, base);
+ }
+ CTX_DATA_END;
+
+ DAG_scene_sort(CTX_data_scene(C));
+ ED_anim_dag_flush_update(C);
+ WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_dupli_set_real(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Make Dupli Real";
+ ot->description = "Make dupli objects attached to this object real.";
+ ot->idname= "OBJECT_OT_dupli_set_real";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= object_dupli_set_real_exec;
+
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+/* ******************* Set Object Center ********************** */
+
+static EnumPropertyItem prop_set_center_types[] = {
+ {0, "CENTER", "ObData to Center", "Move object data around Object center"},
+ {1, "CENTERNEW", "Center New", "Move Object center to center of object data"},
+ {2, "CENTERCURSOR", "Center Cursor", "Move Object Center to position of the 3d cursor"},
+ {0, NULL, NULL, NULL}
+};
+
+/* 0 == do center, 1 == center new, 2 == center cursor */
+static int object_center_set_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= sa->spacedata.first;
+ Object *obedit= CTX_data_edit_object(C);
+ Object *ob;
+ Mesh *me, *tme;
+ Curve *cu;
+/* BezTriple *bezt;
+ BPoint *bp; */
+ Nurb *nu, *nu1;
+ EditVert *eve;
+ float cent[3], centn[3], min[3], max[3], omat[3][3];
+ int a, total= 0;
+ int centermode = RNA_enum_get(op->ptr, "type");
+
+ /* keep track of what is changed */
+ int tot_change=0, tot_lib_error=0, tot_multiuser_arm_error=0;
+ MVert *mvert;
+
+ if(scene->id.lib || v3d==NULL){
+ BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed on Lib data");
+ return OPERATOR_CANCELLED;
+ }
+ if (obedit && centermode > 0) {
+ BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in EditMode");
+ return OPERATOR_CANCELLED;
+ }
+ cent[0]= cent[1]= cent[2]= 0.0;
+
+ if(obedit) {
+
+ INIT_MINMAX(min, max);
+
+ if(obedit->type==OB_MESH) {
+ Mesh *me= obedit->data;
+ EditMesh *em = BKE_mesh_get_editmesh(me);
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(v3d->around==V3D_CENTROID) {
+ total++;
+ VECADD(cent, cent, eve->co);
+ }
+ else {
+ DO_MINMAX(eve->co, min, max);
+ }
+ }
+
+ if(v3d->around==V3D_CENTROID) {
+ VecMulf(cent, 1.0f/(float)total);
+ }
+ else {
+ cent[0]= (min[0]+max[0])/2.0f;
+ cent[1]= (min[1]+max[1])/2.0f;
+ cent[2]= (min[2]+max[2])/2.0f;
+ }
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ VecSubf(eve->co, eve->co, cent);
+ }
+
+ recalc_editnormals(em);
+ tot_change++;
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ BKE_mesh_end_editmesh(me, em);
+ }
+ }
+
+ /* reset flags */
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ base->object->flag &= ~OB_DONE;
+ }
+ CTX_DATA_END;
+
+ for (me= G.main->mesh.first; me; me= me->id.next) {
+ me->flag &= ~ME_ISDONE;
+ }
+
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ if((base->object->flag & OB_DONE)==0) {
+ base->object->flag |= OB_DONE;
+
+ if(obedit==NULL && (me=get_mesh(base->object)) ) {
+ if (me->id.lib) {
+ tot_lib_error++;
+ } else {
+ if(centermode==2) {
+ VECCOPY(cent, give_cursor(scene, v3d));
+ 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.0f;
+ cent[1]= (min[1]+max[1])/2.0f;
+ cent[2]= (min[2]+max[2])/2.0f;
+ }
+
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ VecSubf(mvert->co, mvert->co, cent);
+ }
+
+ if (me->key) {
+ KeyBlock *kb;
+ for (kb=me->key->block.first; kb; kb=kb->next) {
+ float *fp= kb->data;
+
+ for (a=0; a<kb->totelem; a++, fp+=3) {
+ VecSubf(fp, fp, cent);
+ }
+ }
+ }
+
+ me->flag |= ME_ISDONE;
+
+ if(centermode) {
+ 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];
+
+ where_is_object(scene, base->object);
+ ignore_parent_tx(scene, base->object);
+
+ /* other users? */
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ ob = base->object;
+ if((ob->flag & OB_DONE)==0) {
+ tme= get_mesh(ob);
+
+ if(tme==me) {
+
+ ob->flag |= OB_DONE;
+ ob->recalc= OB_RECALC_OB|OB_RECALC_DATA;
+
+ 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];
+
+ where_is_object(scene, ob);
+ ignore_parent_tx(scene, ob);
+
+ if(tme && (tme->flag & ME_ISDONE)==0) {
+ mvert= tme->mvert;
+ for(a=0; a<tme->totvert; a++, mvert++) {
+ VecSubf(mvert->co, mvert->co, cent);
+ }
+
+ if (tme->key) {
+ KeyBlock *kb;
+ for (kb=tme->key->block.first; kb; kb=kb->next) {
+ float *fp= kb->data;
+
+ for (a=0; a<kb->totelem; a++, fp+=3) {
+ VecSubf(fp, fp, cent);
+ }
+ }
+ }
+
+ tme->flag |= ME_ISDONE;
+ }
+ }
+ }
+
+ ob= ob->id.next;
+ }
+ CTX_DATA_END;
+ }
+ tot_change++;
+ }
+ }
+ else if (ELEM(base->object->type, OB_CURVE, OB_SURF)) {
+
+ /* weak code here... (ton) */
+ if(obedit==base->object) {
+ ListBase *editnurb= curve_get_editcurve(obedit);
+
+ nu1= editnurb->first;
+ cu= obedit->data;
+ }
+ else {
+ cu= base->object->data;
+ nu1= cu->nurb.first;
+ }
+
+ if (cu->id.lib) {
+ tot_lib_error++;
+ } else {
+ if(centermode==2) {
+ VECCOPY(cent, give_cursor(scene, v3d));
+ Mat4Invert(base->object->imat, base->object->obmat);
+ Mat4MulVecfl(base->object->imat, cent);
+
+ /* don't allow Z change if curve is 2D */
+ if( !( cu->flag & CU_3D ) )
+ 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.0f;
+ cent[1]= (min[1]+max[1])/2.0f;
+ cent[2]= (min[2]+max[2])/2.0f;
+ }
+
+ nu= nu1;
+ while(nu) {
+ if( (nu->type & 7)==CU_BEZIER) {
+ 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(centermode && 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];
+
+ where_is_object(scene, base->object);
+ ignore_parent_tx(scene, base->object);
+ }
+
+ tot_change++;
+ if(obedit) {
+ if (centermode==0) {
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ }
+ break;
+ }
+ }
+ }
+ else if(base->object->type==OB_FONT) {
+ /* get from bb */
+
+ cu= base->object->data;
+
+ if(cu->bb==0) {
+ /* do nothing*/
+ } else if (cu->id.lib) {
+ tot_lib_error++;
+ } else {
+ cu->xof= -0.5f*( cu->bb->vec[4][0] - cu->bb->vec[0][0]);
+ cu->yof= -0.5f -0.5f*( cu->bb->vec[0][1] - cu->bb->vec[2][1]); /* extra 0.5 is the height o above line */
+
+ /* not really ok, do this better once! */
+ cu->xof /= cu->fsize;
+ cu->yof /= cu->fsize;
+
+ tot_change++;
+ }
+ }
+ else if(base->object->type==OB_ARMATURE) {
+ bArmature *arm = base->object->data;
+
+ if (arm->id.lib) {
+ tot_lib_error++;
+ } else if(arm->id.us>1) {
+ /*error("Can't apply to a multi user armature");
+ return;*/
+ tot_multiuser_arm_error++;
+ } else {
+ /* Function to recenter armatures in editarmature.c
+ * Bone + object locations are handled there.
+ */
+ docenter_armature(scene, v3d, base->object, centermode);
+ tot_change++;
+
+ where_is_object(scene, base->object);
+ ignore_parent_tx(scene, base->object);
+
+ if(obedit)
+ break;
+ }
+ }
+ base->object->recalc= OB_RECALC_OB|OB_RECALC_DATA;
+ }
+ }
+ CTX_DATA_END;
+
+ if (tot_change) {
+ ED_anim_dag_flush_update(C);
+ }
+
+ /* Warn if any errors occured */
+ if (tot_lib_error+tot_multiuser_arm_error) {
+ BKE_reportf(op->reports, RPT_WARNING, "%i Object(s) Not Centered, %i Changed:",tot_lib_error+tot_multiuser_arm_error, tot_change);
+ if (tot_lib_error)
+ BKE_reportf(op->reports, RPT_WARNING, "|%i linked library objects",tot_lib_error);
+ if (tot_multiuser_arm_error)
+ BKE_reportf(op->reports, RPT_WARNING, "|%i multiuser armature object(s)",tot_multiuser_arm_error);
+ }
+
+ return OPERATOR_FINISHED;
+}
+void OBJECT_OT_center_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Center";
+ ot->description = "Set the object's center, by either moving the data, or set to center of data, or use 3d cursor";
+ ot->idname= "OBJECT_OT_center_set";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= object_center_set_exec;
+
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", prop_set_center_types, 0, "Type", "");
+}
+/* ******************* toggle editmode operator ***************** */
+
+void ED_object_exit_editmode(bContext *C, int flag)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Object *ob;
+ int freedata = flag & EM_FREEDATA;
+
+ if(obedit==NULL) return;
+
+ if(flag & EM_WAITCURSOR) waitcursor(1);
+ if(obedit->type==OB_MESH) {
+ Mesh *me= obedit->data;
+
+// if(EM_texFaceCheck())
+
+// if(retopo_mesh_paint_check())
+// retopo_end_okee();
+
+ if(me->edit_mesh->totvert>MESH_MAX_VERTS) {
+ error("Too many vertices");
+ return;
+ }
+ load_editMesh(scene, obedit);
+
+ if(freedata) free_editMesh(me->edit_mesh);
+
+ if(G.f & G_WEIGHTPAINT)
+ mesh_octree_table(obedit, NULL, NULL, 'e');
+ }
+ else if (obedit->type==OB_ARMATURE) {
+ ED_armature_from_edit(scene, obedit);
+ if(freedata)
+ ED_armature_edit_free(obedit);
+ }
+ else if(ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ load_editNurb(obedit);
+ if(freedata) free_editNurb(obedit);
+ }
+ else if(obedit->type==OB_FONT && freedata) {
+ load_editText(obedit);
+ if(freedata) free_editText(obedit);
+ }
+ else if(obedit->type==OB_LATTICE) {
+ load_editLatt(obedit);
+ if(freedata) free_editLatt(obedit);
+ }
+ else if(obedit->type==OB_MBALL) {
+// extern ListBase editelems;
+// load_editMball();
+// if(freedata) BLI_freelistN(&editelems);
+ }
+
+ ob= obedit;
+
+ /* for example; displist make is different in editmode */
+ if(freedata) obedit= NULL;
+ scene->obedit= obedit; // XXX for context
+
+ /* also flush ob recalc, doesn't take much overhead, but used for particles */
+ DAG_object_flush_update(scene, ob, OB_RECALC_OB|OB_RECALC_DATA);
+
+ if(obedit==NULL) // XXX && (flag & EM_FREEUNDO))
+ ED_undo_push(C, "Editmode");
+
+ if(flag & EM_WAITCURSOR) waitcursor(0);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, scene);
+
+}
+
+
+void ED_object_enter_editmode(bContext *C, int flag)
+{
+ Scene *scene= CTX_data_scene(C);
+ Base *base= CTX_data_active_base(C);
+ Object *ob= base->object;
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= NULL;
+ int ok= 0;
+
+ if(scene->id.lib) return;
+ if(base==NULL) return;
+
+ if(sa->spacetype==SPACE_VIEW3D)
+ v3d= sa->spacedata.first;
+
+ if((v3d==NULL || (base->lay & v3d->lay))==0) return;
+
+ if(ob->data==NULL) return;
+
+ if (object_data_is_libdata(ob)) {
+ error_libdata();
+ return;
+ }
+
+ if(flag & EM_WAITCURSOR) waitcursor(1);
+
+ ED_view3d_exit_paint_modes(C);
+
+ if(ob->type==OB_MESH) {
+ Mesh *me= ob->data;
+
+ if(me->pv) mesh_pmv_off(ob, me);
+ ok= 1;
+ scene->obedit= ob; // context sees this
+
+ make_editMesh(scene, ob);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_MESH, scene);
+ }
+ else if (ob->type==OB_ARMATURE){
+ bArmature *arm= base->object->data;
+ if (!arm) return;
+ /*
+ * The function object_data_is_libdata make a problem here, the
+ * check for ob->proxy return 0 and let blender enter to edit mode
+ * this causa a crash when you try leave the edit mode.
+ * The problem is that i can't remove the ob->proxy check from
+ * object_data_is_libdata that prevent the bugfix #6614, so
+ * i add this little hack here.
+ */
+ if(arm->id.lib) {
+ error_libdata();
+ return;
+ }
+ ok=1;
+ scene->obedit= ob;
+ ED_armature_to_edit(ob);
+ /* to ensure all goes in restposition and without striding */
+ DAG_object_flush_update(scene, ob, OB_RECALC);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_ARMATURE, scene);
+ }
+ else if(ob->type==OB_FONT) {
+ scene->obedit= ob; // XXX for context
+ ok= 1;
+ make_editText(ob);
+ WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_TEXT, scene);
+ }
+ else if(ob->type==OB_MBALL) {
+ scene->obedit= ob; // XXX for context
+// ok= 1;
+// XXX make_editMball();
+ WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_MBALL, scene);
+
+ }
+ else if(ob->type==OB_LATTICE) {
+ scene->obedit= ob; // XXX for context
+ ok= 1;
+ make_editLatt(ob);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_LATTICE, scene);
+ }
+ else if(ob->type==OB_SURF || ob->type==OB_CURVE) {
+ ok= 1;
+ scene->obedit= ob; // XXX for context
+ make_editNurb(ob);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_CURVE, scene);
+ }
+
+ if(ok) {
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+ else {
+ scene->obedit= NULL; // XXX for context
+ WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, scene);
+ }
+
+ if(flag & EM_WAITCURSOR) waitcursor(0);
+}
+
+static int editmode_toggle_exec(bContext *C, wmOperator *op)
+{
+
+ if(!CTX_data_edit_object(C))
+ ED_object_enter_editmode(C, EM_WAITCURSOR);
+ else
+ ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Toggle Editmode";
+ ot->description = "Toggle object's editmode.";
+ ot->idname= "OBJECT_OT_editmode_toggle";
+
+ /* api callbacks */
+ ot->exec= editmode_toggle_exec;
+
+ ot->poll= ED_operator_object_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* *************************** */
+
+
+void check_editmode(int type)
+{
+ Object *obedit= NULL; // XXX
+
+ if (obedit==NULL || obedit->type==type) return;
+
+// XXX ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* freedata, and undo */
+}
+void movetolayer(Scene *scene, View3D *v3d)
+{
+ Base *base;
+ unsigned int lay= 0, local;
+ int islamp= 0;
+
+ if(scene->id.lib) return;
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if (TESTBASE(v3d, base)) lay |= base->lay;
+ }
+ if(lay==0) return;
+ lay &= 0xFFFFFF;
+
+ if(lay==0) return;
+
+ if(v3d->localview) {
+ /* now we can move out of localview. */
+ if (!okee("Move from localview")) return;
+ for(base= FIRSTBASE; base; base= base->next) {
+ if (TESTBASE(v3d, base)) {
+ lay= base->lay & ~v3d->lay;
+ base->lay= lay;
+ base->object->lay= lay;
+ base->object->flag &= ~SELECT;
+ base->flag &= ~SELECT;
+ if(base->object->type==OB_LAMP) islamp= 1;
+ }
+ }
+ } else {
+// XXX if( movetolayer_buts(&lay, NULL)==0 ) return;
+
+ /* normal non localview operation */
+ for(base= FIRSTBASE; base; base= base->next) {
+ if (TESTBASE(v3d, base)) {
+ /* upper byte is used for local view */
+ local= base->lay & 0xFF000000;
+ base->lay= lay + local;
+ base->object->lay= lay;
+ if(base->object->type==OB_LAMP) islamp= 1;
+ }
+ }
+ }
+ if(islamp) reshadeall_displist(scene); /* only frees */
+
+ /* warning, active object may be hidden now */
+
+ DAG_scene_sort(scene);
+
+}
+
+
+#if 0
+// XXX should be in view3d?
+
+/* context: ob = lamp */
+/* code should be replaced with proper (custom) transform handles for lamp properties */
+static void spot_interactive(Object *ob, int mode)
+{
+ Lamp *la= ob->data;
+ float transfac, dx, dy, ratio, origval;
+ int keep_running= 1, center2d[2];
+ short mval[2], mvalo[2];
+
+// getmouseco_areawin(mval);
+// getmouseco_areawin(mvalo);
+
+ project_int(ob->obmat[3], center2d);
+ if( center2d[0] > 100000 ) { /* behind camera */
+// center2d[0]= curarea->winx/2;
+// center2d[1]= curarea->winy/2;
+ }
+
+// helpline(mval, center2d);
+
+ /* ratio is like scaling */
+ dx = (float)(center2d[0] - mval[0]);
+ dy = (float)(center2d[1] - mval[1]);
+ transfac = (float)sqrt( dx*dx + dy*dy);
+ if(transfac==0.0f) transfac= 1.0f;
+
+ if(mode==1)
+ origval= la->spotsize;
+ else if(mode==2)
+ origval= la->dist;
+ else if(mode==3)
+ origval= la->clipsta;
+ else
+ origval= la->clipend;
+
+ while (keep_running>0) {
+
+// getmouseco_areawin(mval);
+
+ /* essential for idling subloop */
+ if(mval[0]==mvalo[0] && mval[1]==mvalo[1]) {
+ PIL_sleep_ms(2);
+ }
+ else {
+ char str[32];
+
+ dx = (float)(center2d[0] - mval[0]);
+ dy = (float)(center2d[1] - mval[1]);
+ ratio = (float)(sqrt( dx*dx + dy*dy))/transfac;
+
+ /* do the trick */
+
+ if(mode==1) { /* spot */
+ la->spotsize = ratio*origval;
+ CLAMP(la->spotsize, 1.0f, 180.0f);
+ sprintf(str, "Spot size %.2f\n", la->spotsize);
+ }
+ else if(mode==2) { /* dist */
+ la->dist = ratio*origval;
+ CLAMP(la->dist, 0.01f, 5000.0f);
+ sprintf(str, "Distance %.2f\n", la->dist);
+ }
+ else if(mode==3) { /* sta */
+ la->clipsta = ratio*origval;
+ CLAMP(la->clipsta, 0.001f, 5000.0f);
+ sprintf(str, "Distance %.2f\n", la->clipsta);
+ }
+ else if(mode==4) { /* end */
+ la->clipend = ratio*origval;
+ CLAMP(la->clipend, 0.1f, 5000.0f);
+ sprintf(str, "Clip End %.2f\n", la->clipend);
+ }
+
+ /* cleanup */
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+
+ /* handle shaded mode */
+// XXX shade_buttons_change_3d();
+
+ /* DRAW */
+ headerprint(str);
+ force_draw_plus(SPACE_BUTS, 0);
+
+// helpline(mval, center2d);
+ }
+
+ while( qtest() ) {
+ short val;
+ unsigned short event= extern_qread(&val);
+
+ switch (event){
+ case ESCKEY:
+ case RIGHTMOUSE:
+ keep_running= 0;
+ break;
+ case LEFTMOUSE:
+ case SPACEKEY:
+ case PADENTER:
+ case RETKEY:
+ if(val)
+ keep_running= -1;
+ break;
+ }
+ }
+ }
+
+ if(keep_running==0) {
+ if(mode==1)
+ la->spotsize= origval;
+ else if(mode==2)
+ la->dist= origval;
+ else if(mode==3)
+ la->clipsta= origval;
+ else
+ la->clipend= origval;
+ }
+
+}
+#endif
+
+void special_editmenu(Scene *scene, View3D *v3d)
+{
+// XXX static short numcuts= 2;
+ Object *ob= OBACT;
+ Object *obedit= NULL; // XXX
+ float fac;
+ int nr,ret=0;
+ short randfac;
+
+ if(ob==NULL) return;
+
+ if(obedit==NULL) {
+
+ if(ob->flag & OB_POSEMODE) {
+// XXX pose_special_editmenu();
+ }
+ else if(FACESEL_PAINT_TEST) {
+ Mesh *me= get_mesh(ob);
+ MTFace *tface;
+ MFace *mface;
+ int a;
+
+ if(me==0 || me->mtface==0) return;
+
+ nr= pupmenu("Specials%t|Set Tex%x1| Shared%x2| Light%x3| Invisible%x4| Collision%x5| TwoSide%x6|Clr Tex%x7| Shared%x8| Light%x9| Invisible%x10| Collision%x11| TwoSide%x12");
+
+ tface= me->mtface;
+ mface= me->mface;
+ for(a=me->totface; a>0; a--, tface++, mface++) {
+ if(mface->flag & ME_FACE_SEL) {
+ 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_TWOSIDE; break;
+ case 7:
+ tface->mode &= ~TF_TEX;
+ tface->tpage= 0;
+ break;
+ case 8:
+ tface->mode &= ~TF_SHAREDCOL; break;
+ case 9:
+ tface->mode &= ~TF_LIGHT; break;
+ case 10:
+ tface->mode &= ~TF_INVISIBLE; break;
+ case 11:
+ tface->mode &= ~TF_DYNAMIC; break;
+ case 12:
+ tface->mode &= ~TF_TWOSIDE; break;
+ }
+ }
+ }
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+ else if(G.f & G_VERTEXPAINT) {
+ Mesh *me= get_mesh(ob);
+
+ if(me==0 || (me->mcol==NULL && me->mtface==NULL) ) return;
+
+ nr= pupmenu("Specials%t|Shared VertexCol%x1");
+ if(nr==1) {
+
+// XXX do_shared_vertexcol(me);
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+ }
+ else if(G.f & G_WEIGHTPAINT) {
+ Object *par= modifiers_isDeformedByArmature(ob);
+
+ if(par && (par->flag & OB_POSEMODE)) {
+ nr= pupmenu("Specials%t|Apply Bone Envelopes to Vertex Groups %x1|Apply Bone Heat Weights to Vertex Groups %x2");
+
+// XXX if(nr==1 || nr==2)
+// XXX pose_adds_vgroups(ob, (nr == 2));
+ }
+ }
+ else if(G.f & G_PARTICLEEDIT) {
+#if 0
+ // XXX
+ ParticleSystem *psys = PE_get_current(ob);
+ ParticleEditSettings *pset = PE_settings();
+
+ if(!psys)
+ return;
+
+ if(scene->selectmode & SCE_SELECT_POINT)
+ nr= pupmenu("Specials%t|Rekey%x1|Subdivide%x2|Select First%x3|Select Last%x4|Remove Doubles%x5");
+ else
+ nr= pupmenu("Specials%t|Rekey%x1|Remove Doubles%x5");
+
+ switch(nr) {
+ case 1:
+// XXX if(button(&pset->totrekey, 2, 100, "Number of Keys:")==0) return;
+ waitcursor(1);
+ PE_rekey();
+ break;
+ case 2:
+ PE_subdivide();
+ break;
+ case 3:
+ PE_select_root();
+ break;
+ case 4:
+ PE_select_tip();
+ break;
+ case 5:
+ PE_remove_doubles();
+ break;
+ }
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ if(nr>0) waitcursor(0);
+#endif
+ }
+ else {
+ Base *base, *base_select= NULL;
+
+ /* Get the active object mesh. */
+ Mesh *me= get_mesh(ob);
+
+ /* Booleans, if the active object is a mesh... */
+ if (me && ob->id.lib==NULL) {
+
+ /* Bring up a little menu with the boolean operation choices on. */
+ nr= pupmenu("Boolean Tools%t|Intersect%x1|Union%x2|Difference%x3|Add Intersect Modifier%x4|Add Union Modifier%x5|Add Difference Modifier%x6");
+
+ 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. */
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ if(base->object != ob) base_select= base;
+ }
+ }
+
+ if (base_select) {
+ if (get_mesh(base_select->object)) {
+ if(nr <= 3){
+ waitcursor(1);
+// XXX ret = NewBooleanMesh(BASACT,base_select,nr);
+ if (ret==0) {
+ error("An internal error occurred");
+ } else if(ret==-1) {
+ error("Selected meshes must have faces to perform boolean operations");
+ } else if (ret==-2) {
+ error("Both meshes must be a closed mesh");
+ }
+ waitcursor(0);
+ } else {
+ BooleanModifierData *bmd = NULL;
+ bmd = (BooleanModifierData *)modifier_new(eModifierType_Boolean);
+ BLI_addtail(&ob->modifiers, bmd);
+ bmd->object = base_select->object;
+ bmd->modifier.mode |= eModifierMode_Realtime;
+ switch(nr){
+ case 4: bmd->operation = eBooleanModifierOp_Intersect; break;
+ case 5: bmd->operation = eBooleanModifierOp_Union; break;
+ case 6: bmd->operation = eBooleanModifierOp_Difference; break;
+ }
+// XXX do_common_editbuts(B_CHANGEDEP);
+ }
+ } else {
+ error("Please select 2 meshes");
+ }
+ } else {
+ error("Please select 2 meshes");
+ }
+ }
+
+ }
+ else if (ob->type == OB_FONT) {
+ /* removed until this gets a decent implementation (ton) */
+/* nr= pupmenu("Split %t|Characters%x1");
+ if (nr > 0) {
+ switch(nr) {
+ case 1: split_font();
+ }
+ }
+*/
+ }
+ }
+ }
+ else if(obedit->type==OB_MESH) {
+ /* This is all that is needed, since all other functionality is in Ctrl+ V/E/F but some users didnt like, so for now have the old/big menu */
+ /*
+ nr= pupmenu("Subdivide Mesh%t|Subdivide%x1|Subdivide Multi%x2|Subdivide Multi Fractal%x3|Subdivide Smooth%x4");
+ switch(nr) {
+ case 1:
+ waitcursor(1);
+ esubdivideflag(1, 0.0, scene->toolsettings->editbutflag, 1, 0);
+
+ break;
+ case 2:
+ if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
+ waitcursor(1);
+ esubdivideflag(1, 0.0, scene->toolsettings->editbutflag, numcuts, 0);
+ break;
+ case 3:
+ if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
+ randfac= 10;
+ if(button(&randfac, 1, 100, "Rand fac:")==0) return;
+ waitcursor(1);
+ fac= -( (float)randfac )/100;
+ esubdivideflag(1, fac, scene->toolsettings->editbutflag, numcuts, 0);
+ break;
+
+ case 4:
+ fac= 1.0f;
+ if(fbutton(&fac, 0.0f, 5.0f, 10, 10, "Smooth:")==0) return;
+ fac= 0.292f*fac;
+
+ waitcursor(1);
+ esubdivideflag(1, fac, scene->toolsettings->editbutflag | B_SMOOTH, 1, 0);
+ break;
+ }
+ */
+
+ nr= pupmenu("Specials%t|Subdivide%x1|Subdivide Multi%x2|Subdivide Multi Fractal%x3|Subdivide Smooth%x12|Merge%x4|Remove Doubles%x5|Hide%x6|Reveal%x7|Select Swap%x8|Flip Normals %x9|Smooth %x10|Bevel %x11|Set Smooth %x14|Set Solid %x15|Blend From Shape%x16|Propagate To All Shapes%x17|Select Vertex Path%x18");
+
+ switch(nr) {
+ case 1:
+ waitcursor(1);
+// XXX esubdivideflag(1, 0.0, scene->toolsettings->editbutflag, 1, 0);
+
+ break;
+ case 2:
+// XXX if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
+ waitcursor(1);
+// XXX esubdivideflag(1, 0.0, scene->toolsettings->editbutflag, numcuts, 0);
+ break;
+ case 3:
+// XXX if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
+ randfac= 10;
+// XXX if(button(&randfac, 1, 100, "Rand fac:")==0) return;
+ waitcursor(1);
+ fac= -( (float)randfac )/100;
+// XXX esubdivideflag(1, fac, scene->toolsettings->editbutflag, numcuts, 0);
+ break;
+
+ case 12: /* smooth */
+ /* if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return; */
+ fac= 1.0f;
+// XXX if(fbutton(&fac, 0.0f, 5.0f, 10, 10, "Smooth:")==0) return;
+// XXX fac= 0.292f*fac;
+
+ waitcursor(1);
+// XXX esubdivideflag(1, fac, scene->toolsettings->editbutflag | B_SMOOTH, 1, 0);
+ break;
+
+ case 4:
+// XXX mergemenu();
+ break;
+ case 5:
+// XXX notice("Removed %d Vertices", removedoublesflag(1, 0, scene->toolsettings->doublimit));
+ break;
+ case 6:
+// XXX hide_mesh(0);
+ break;
+ case 7:
+// XXX reveal_mesh();
+ break;
+ case 8:
+// XXX selectswap_mesh();
+ break;
+ case 9:
+// XXX flip_editnormals();
+ break;
+ case 10:
+// XXX vertexsmooth();
+ break;
+ case 11:
+// XXX bevel_menu();
+ break;
+ case 14:
+// XXX mesh_set_smooth_faces(1);
+ break;
+ case 15:
+// XXX mesh_set_smooth_faces(0);
+ break;
+ case 16:
+// XXX shape_copy_select_from();
+ break;
+ case 17:
+// XXX shape_propagate();
+ break;
+ case 18:
+// XXX pathselect();
+ break;
+ }
+
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ if(nr>0) waitcursor(0);
+
+ }
+ else if(ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+
+ nr= pupmenu("Specials%t|Subdivide%x1|Switch Direction%x2|Set Goal Weight%x3|Set Radius%x4|Smooth%x5|Smooth Radius%x6");
+
+ switch(nr) {
+ case 1:
+// XXX subdivideNurb();
+ break;
+ case 2:
+// XXX switchdirectionNurb2();
+ break;
+ case 3:
+// XXX setweightNurb();
+ break;
+ case 4:
+// XXX setradiusNurb();
+ break;
+ case 5:
+// XXX smoothNurb();
+ break;
+ case 6:
+// XXX smoothradiusNurb();
+ break;
+ }
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ }
+ else if(obedit->type==OB_ARMATURE) {
+ nr= pupmenu("Specials%t|Subdivide %x1|Subdivide Multi%x2|Switch Direction%x7|Flip Left-Right Names%x3|%l|AutoName Left-Right%x4|AutoName Front-Back%x5|AutoName Top-Bottom%x6");
+// if(nr==1)
+// XXX subdivide_armature(1);
+ if(nr==2) {
+// XXX if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
+ waitcursor(1);
+// XXX subdivide_armature(numcuts);
+ }
+// else if(nr==3)
+// XXX armature_flip_names();
+ else if(ELEM3(nr, 4, 5, 6)) {
+// XXX armature_autoside_names(nr-4);
+ }
+// else if(nr == 7)
+// XXX switch_direction_armature();
+ }
+ else if(obedit->type==OB_LATTICE) {
+ Lattice *lt= obedit->data;
+ static float weight= 1.0f;
+ { // XXX
+// XXX if(fbutton(&weight, 0.0f, 1.0f, 10, 10, "Set Weight")) {
+ int a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
+ BPoint *bp= lt->editlatt->def;
+
+ while(a--) {
+ if(bp->f1 & SELECT)
+ bp->weight= weight;
+ bp++;
+ }
+ }
+ }
+
+}
+
+static void curvetomesh(Scene *scene, Object *ob)
+{
+ Curve *cu;
+ DispList *dl;
+
+ ob->flag |= OB_DONE;
+ cu= ob->data;
+
+ dl= cu->disp.first;
+ if(dl==0) makeDispListCurveTypes(scene, ob, 0); /* force creation */
+
+ nurbs_to_mesh(ob); /* also does users */
+ if (ob->type != OB_MESH) {
+ error("can't convert curve to mesh");
+ } else {
+ object_free_modifiers(ob);
+ }
+}
+
+void convertmenu(Scene *scene, View3D *v3d)
+{
+ Base *base, *basen=NULL, *basact, *basedel=NULL;
+ Object *obact, *ob, *ob1;
+ Object *obedit= NULL; // XXX
+ Curve *cu;
+ Nurb *nu;
+ MetaBall *mb;
+ Mesh *me;
+ int ok=0, nr = 0, a;
+
+ if(scene->id.lib) return;
+
+ obact= OBACT;
+ if (obact == NULL) return;
+ if(!obact->flag & SELECT) return;
+ if(obedit) return;
+
+ basact= BASACT; /* will be restored */
+
+ if(obact->type==OB_FONT) {
+ nr= pupmenu("Convert Font to%t|Curve%x1|Curve (Single filling group)%x2|Mesh%x3");
+ if(nr>0) ok= 1;
+ }
+ else if(obact->type==OB_MBALL) {
+ nr= pupmenu("Convert Metaball to%t|Mesh (keep original)%x1|Mesh (Delete Original)%x2");
+ if(nr>0) ok= 1;
+ }
+ else if(obact->type==OB_CURVE) {
+ nr= pupmenu("Convert Curve to%t|Mesh");
+ if(nr>0) ok= 1;
+ }
+ else if(obact->type==OB_SURF) {
+ nr= pupmenu("Convert Nurbs Surface to%t|Mesh");
+ if(nr>0) ok= 1;
+ }
+ else if(obact->type==OB_MESH) {
+ nr= pupmenu("Convert Modifiers to%t|Mesh (Keep Original)%x1|Mesh (Delete Original)%x2");
+ if(nr>0) ok= 1;
+ }
+ if(ok==0) return;
+
+ /* don't forget multiple users! */
+
+ /* reset flags */
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ base->object->flag &= ~OB_DONE;
+ }
+ }
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+
+ ob= base->object;
+
+ if(ob->flag & OB_DONE);
+ else if(ob->type==OB_MESH && ob->modifiers.first) { /* converting a mesh with no modifiers causes a segfault */
+ DerivedMesh *dm;
+
+ basedel = base;
+
+ ob->flag |= OB_DONE;
+
+ ob1= copy_object(ob);
+ ob1->recalc |= OB_RECALC;
+
+ basen= MEM_mallocN(sizeof(Base), "duplibase");
+ *basen= *base;
+ BLI_addhead(&scene->base, basen); /* addhead: otherwise eternal loop */
+ basen->object= ob1;
+ basen->flag |= SELECT;
+ base->flag &= ~SELECT;
+ ob->flag &= ~SELECT;
+
+ /* decrement original mesh's usage count */
+ me= ob1->data;
+ me->id.us--;
+
+ /* make a new copy of the mesh */
+ ob1->data= copy_mesh(me);
+
+ /* make new mesh data from the original copy */
+ dm= mesh_get_derived_final(scene, ob1, CD_MASK_MESH);
+ /* dm= mesh_create_derived_no_deform(ob1, NULL); this was called original (instead of get_derived). man o man why! (ton) */
+
+ DM_to_mesh(dm, ob1->data);
+
+ dm->release(dm);
+ object_free_modifiers(ob1); /* after derivedmesh calls! */
+
+ /* If the original object is active then make this object active */
+ if (ob == obact) {
+ // XXX ED_base_object_activate(C, basen);
+ basact = basen;
+ }
+ }
+ else if(ob->type==OB_FONT) {
+ ob->flag |= OB_DONE;
+
+ ob->type= OB_CURVE;
+ cu= ob->data;
+
+ if(cu->vfont) {
+ cu->vfont->id.us--;
+ cu->vfont= 0;
+ }
+ if(cu->vfontb) {
+ cu->vfontb->id.us--;
+ cu->vfontb= 0;
+ }
+ if(cu->vfonti) {
+ cu->vfonti->id.us--;
+ cu->vfonti= 0;
+ }
+ if(cu->vfontbi) {
+ cu->vfontbi->id.us--;
+ cu->vfontbi= 0;
+ }
+ /* other users */
+ if(cu->id.us>1) {
+ ob1= G.main->object.first;
+ while(ob1) {
+ if(ob1->data==cu) {
+ ob1->type= OB_CURVE;
+ ob1->recalc |= OB_RECALC;
+ }
+ ob1= ob1->id.next;
+ }
+ }
+ if (nr==2 || nr==3) {
+ nu= cu->nurb.first;
+ while(nu) {
+ nu->charidx= 0;
+ nu= nu->next;
+ }
+ }
+ if (nr==3) {
+ curvetomesh(scene, ob);
+ }
+ }
+ else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ if(nr==1) {
+ curvetomesh(scene, ob);
+ }
+ }
+ else if(ob->type==OB_MBALL) {
+
+ if(nr==1 || nr == 2) {
+ ob= find_basis_mball(scene, ob);
+
+ if(ob->disp.first && !(ob->flag&OB_DONE)) {
+ basedel = base;
+
+ ob->flag |= OB_DONE;
+
+ ob1= copy_object(ob);
+ ob1->recalc |= OB_RECALC;
+
+ basen= MEM_mallocN(sizeof(Base), "duplibase");
+ *basen= *base;
+ BLI_addhead(&scene->base, basen); /* addhead: othwise eternal loop */
+ basen->object= ob1;
+ basen->flag |= SELECT;
+ basedel->flag &= ~SELECT;
+ ob->flag &= ~SELECT;
+
+ mb= ob1->data;
+ mb->id.us--;
+
+ ob1->data= add_mesh("Mesh");
+ 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);
+
+ /* So we can see the wireframe */
+ BASACT= basen;
+
+ /* If the original object is active then make this object active */
+ if (ob == obact) {
+ // XXX ED_base_object_activate(C, basen);
+ basact = basen;
+ }
+
+ }
+ }
+ }
+ }
+ if(basedel != NULL && nr == 2) {
+ ED_base_object_free_and_unlink(scene, basedel);
+ }
+ basedel = NULL;
+ }
+
+ /* delete object should renew depsgraph */
+ if(nr==2)
+ DAG_scene_sort(scene);
+
+ /* texspace and normals */
+ if(!basen) BASACT= base;
+
+// XXX ED_object_enter_editmode(C, 0);
+// XXX exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR); /* freedata, but no undo */
+ BASACT= basact;
+
+
+ DAG_scene_sort(scene);
+}
+
+/* Change subdivision or particle properties of mesh object ob, if level==-1
+ * then toggle subsurf, else set to level set allows to toggle multiple
+ * selections */
+
+static void object_has_subdivision_particles(Object *ob, int *havesubdiv, int *havepart, int depth)
+{
+ if(ob->type==OB_MESH) {
+ if(modifiers_findByType(ob, eModifierType_Subsurf))
+ *havesubdiv= 1;
+ if(modifiers_findByType(ob, eModifierType_ParticleSystem))
+ *havepart= 1;
+ }
+
+ if(ob->dup_group && depth <= 4) {
+ GroupObject *go;
+
+ for(go= ob->dup_group->gobject.first; go; go= go->next)
+ object_has_subdivision_particles(go->ob, havesubdiv, havepart, depth+1);
+ }
+}
+
+static void object_flip_subdivison_particles(Scene *scene, Object *ob, int *set, int level, int mode, int particles, int depth)
+{
+ ModifierData *md;
+
+ if(ob->type==OB_MESH) {
+ if(particles) {
+ for(md=ob->modifiers.first; md; md=md->next) {
+ if(md->type == eModifierType_ParticleSystem) {
+ ParticleSystemModifierData *psmd = (ParticleSystemModifierData*)md;
+
+ if(*set == -1)
+ *set= psmd->modifier.mode&(mode);
+
+ if (*set)
+ psmd->modifier.mode &= ~(mode);
+ else
+ psmd->modifier.mode |= (mode);
+ }
+ }
+ }
+ else {
+ md = modifiers_findByType(ob, eModifierType_Subsurf);
+
+ if (md) {
+ SubsurfModifierData *smd = (SubsurfModifierData*) md;
+
+ if (level == -1) {
+ if(*set == -1)
+ *set= smd->modifier.mode&(mode);
+
+ if (*set)
+ smd->modifier.mode &= ~(mode);
+ else
+ smd->modifier.mode |= (mode);
+ } else {
+ smd->levels = level;
+ }
+ }
+ else if(depth == 0 && *set != 0) {
+ SubsurfModifierData *smd = (SubsurfModifierData*) modifier_new(eModifierType_Subsurf);
+
+ BLI_addtail(&ob->modifiers, smd);
+
+ if (level!=-1) {
+ smd->levels = level;
+ }
+
+ if(*set == -1)
+ *set= 1;
+ }
+ }
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+
+ if(ob->dup_group && depth<=4) {
+ GroupObject *go;
+
+ for(go= ob->dup_group->gobject.first; go; go= go->next)
+ object_flip_subdivison_particles(scene, go->ob, set, level, mode, particles, depth+1);
+ }
+}
+
+/* Change subdivision properties of mesh object ob, if
+* level==-1 then toggle subsurf, else set to level.
+*/
+
+void flip_subdivison(Scene *scene, View3D *v3d, int level)
+{
+ Base *base;
+ int set= -1;
+ int mode, pupmode, particles= 0, havesubdiv= 0, havepart= 0;
+ int alt= 0; // XXX
+
+ if(alt)
+ mode= eModifierMode_Realtime;
+ else
+ mode= eModifierMode_Render|eModifierMode_Realtime;
+
+ if(level == -1) {
+ if (scene->obedit) { // XXX get from context
+ object_has_subdivision_particles(scene->obedit, &havesubdiv, &havepart, 0);
+ } else {
+ for(base= scene->base.first; base; base= base->next) {
+ if(((level==-1) && (TESTBASE(v3d, base))) || (TESTBASELIB(v3d, base))) {
+ object_has_subdivision_particles(base->object, &havesubdiv, &havepart, 0);
+ }
+ }
+ }
+ }
+ else
+ havesubdiv= 1;
+
+ if(havesubdiv && havepart) {
+ pupmode= pupmenu("Switch%t|Subsurf %x1|Particle Systems %x2");
+ if(pupmode <= 0)
+ return;
+ else if(pupmode == 2)
+ particles= 1;
+ }
+ else if(havepart)
+ particles= 1;
+
+ if (scene->obedit) { // XXX get from context
+ object_flip_subdivison_particles(scene, scene->obedit, &set, level, mode, particles, 0);
+ } else {
+ for(base= scene->base.first; base; base= base->next) {
+ if(((level==-1) && (TESTBASE(v3d, base))) || (TESTBASELIB(v3d, base))) {
+ object_flip_subdivison_particles(scene, base->object, &set, level, mode, particles, 0);
+ }
+ }
+ }
+
+ ED_anim_dag_flush_update(C);
+}
+
+static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
+{
+ bProperty *prop;
+ Base *base;
+ int nr, tot=0;
+ char *str;
+
+ prop= ob->prop.first;
+ while(prop) {
+ tot++;
+ prop= prop->next;
+ }
+
+ str= MEM_callocN(50 + 33*tot, "copymenu prop");
+
+ if (tot)
+ strcpy(str, "Copy Property %t|Replace All|Merge All|%l");
+ else
+ strcpy(str, "Copy Property %t|Clear All (no properties on active)");
+
+ tot= 0;
+ prop= ob->prop.first;
+ while(prop) {
+ tot++;
+ strcat(str, "|");
+ strcat(str, prop->name);
+ prop= prop->next;
+ }
+
+ nr= pupmenu(str);
+
+ if ( nr==1 || nr==2 ) {
+ for(base= FIRSTBASE; base; base= base->next) {
+ if((base != BASACT) &&(TESTBASELIB(v3d, base))) {
+ if (nr==1) { /* replace */
+ copy_properties( &base->object->prop, &ob->prop );
+ } else {
+ for(prop = ob->prop.first; prop; prop= prop->next ) {
+ set_ob_property(base->object, prop);
+ }
+ }
+ }
+ }
+ } else if(nr>0) {
+ prop = BLI_findlink(&ob->prop, nr-4); /* account for first 3 menu items & menu index starting at 1*/
+
+ if(prop) {
+ for(base= FIRSTBASE; base; base= base->next) {
+ if((base != BASACT) &&(TESTBASELIB(v3d, base))) {
+ set_ob_property(base->object, prop);
+ }
+ }
+ }
+ }
+ MEM_freeN(str);
+
+}
+
+static void copymenu_logicbricks(Scene *scene, View3D *v3d, Object *ob)
+{
+ Base *base;
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(base->object != ob) {
+ if(TESTBASELIB(v3d, 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;
+
+ /* set the initial state */
+ base->object->state= ob->state;
+ base->object->init_state= ob->init_state;
+ }
+ }
+ }
+}
+
+static void copymenu_modifiers(Scene *scene, View3D *v3d, Object *ob)
+{
+ Base *base;
+ int i, event;
+ char str[512];
+ char *errorstr= NULL;
+
+ strcpy(str, "Copy Modifiers %t");
+
+ sprintf(str+strlen(str), "|All%%x%d|%%l", NUM_MODIFIER_TYPES);
+
+ for (i=eModifierType_None+1; i<NUM_MODIFIER_TYPES; i++) {
+ ModifierTypeInfo *mti = modifierType_getInfo(i);
+
+ if(ELEM3(i, eModifierType_Hook, eModifierType_Softbody, eModifierType_ParticleInstance)) continue;
+
+ if(i == eModifierType_Collision)
+ continue;
+
+ if ( (mti->flags&eModifierTypeFlag_AcceptsCVs) ||
+ (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
+ sprintf(str+strlen(str), "|%s%%x%d", mti->name, i);
+ }
+ }
+
+ event = pupmenu(str);
+ if(event<=0) return;
+
+ for (base= FIRSTBASE; base; base= base->next) {
+ if(base->object != ob) {
+ if(TESTBASELIB(v3d, base)) {
+ ModifierData *md;
+
+ base->object->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
+
+ if (base->object->type==ob->type) {
+ /* copy all */
+ if (event==NUM_MODIFIER_TYPES) {
+ object_free_modifiers(base->object);
+
+ for (md=ob->modifiers.first; md; md=md->next) {
+ ModifierData *nmd = NULL;
+
+ if(ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_ParticleInstance)) continue;
+
+ if(md->type == eModifierType_Collision)
+ continue;
+
+ nmd = modifier_new(md->type);
+ modifier_copyData(md, nmd);
+ BLI_addtail(&base->object->modifiers, nmd);
+ }
+
+ copy_object_particlesystems(base->object, ob);
+ copy_object_softbody(base->object, ob);
+ } else {
+ /* copy specific types */
+ ModifierData *md, *mdn;
+
+ /* remove all with type 'event' */
+ for (md=base->object->modifiers.first; md; md=mdn) {
+ mdn= md->next;
+ if(md->type==event) {
+ BLI_remlink(&base->object->modifiers, md);
+ modifier_free(md);
+ }
+ }
+
+ /* copy all with type 'event' */
+ for (md=ob->modifiers.first; md; md=md->next) {
+ if (md->type==event) {
+
+ mdn = modifier_new(event);
+ BLI_addtail(&base->object->modifiers, mdn);
+
+ modifier_copyData(md, mdn);
+ }
+ }
+
+ if(event == eModifierType_ParticleSystem) {
+ object_free_particlesystems(base->object);
+ copy_object_particlesystems(base->object, ob);
+ }
+ else if(event == eModifierType_Softbody) {
+ object_free_softbody(base->object);
+ copy_object_softbody(base->object, ob);
+ }
+ }
+ }
+ else
+ errorstr= "Did not copy modifiers to other Object types";
+ }
+ }
+ }
+
+// if(errorstr) notice(errorstr);
+
+ DAG_scene_sort(scene);
+
+}
+
+/* both pointers should exist */
+static void copy_texture_space(Object *to, Object *ob)
+{
+ float *poin1= NULL, *poin2= NULL;
+ int texflag= 0;
+
+ if(ob->type==OB_MESH) {
+ texflag= ((Mesh *)ob->data)->texflag;
+ poin2= ((Mesh *)ob->data)->loc;
+ }
+ else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ texflag= ((Curve *)ob->data)->texflag;
+ poin2= ((Curve *)ob->data)->loc;
+ }
+ else if(ob->type==OB_MBALL) {
+ texflag= ((MetaBall *)ob->data)->texflag;
+ poin2= ((MetaBall *)ob->data)->loc;
+ }
+ else
+ return;
+
+ if(to->type==OB_MESH) {
+ ((Mesh *)to->data)->texflag= texflag;
+ poin1= ((Mesh *)to->data)->loc;
+ }
+ else if (ELEM3(to->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ ((Curve *)to->data)->texflag= texflag;
+ poin1= ((Curve *)to->data)->loc;
+ }
+ else if(to->type==OB_MBALL) {
+ ((MetaBall *)to->data)->texflag= texflag;
+ poin1= ((MetaBall *)to->data)->loc;
+ }
+ else
+ return;
+
+ memcpy(poin1, poin2, 9*sizeof(float)); /* this was noted in DNA_mesh, curve, mball */
+
+ if(to->type==OB_MESH) ;
+ else if(to->type==OB_MBALL) tex_space_mball(to);
+ else tex_space_curve(to->data);
+
+}
+
+void copy_attr(Scene *scene, View3D *v3d, short event)
+{
+ Object *ob;
+ Base *base;
+ Curve *cu, *cu1;
+ Nurb *nu;
+ int do_scene_sort= 0;
+
+ if(scene->id.lib) return;
+
+ if(!(ob=OBACT)) return;
+
+ if(scene->obedit) { // XXX get from context
+ /* obedit_copymenu(); */
+ return;
+ }
+ if(event==9) {
+ copymenu_properties(scene, v3d, ob);
+ return;
+ }
+ else if(event==10) {
+ copymenu_logicbricks(scene, v3d, ob);
+ return;
+ }
+ else if(event==24) {
+ copymenu_modifiers(scene, v3d, ob);
+ return;
+ }
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(base != BASACT) {
+ if(TESTBASELIB(v3d, base)) {
+ base->object->recalc |= OB_RECALC_OB;
+
+ 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);
+ /* Quats arnt used yet */
+ /*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;
+ base->object->empty_drawtype= ob->empty_drawtype;
+ base->object->empty_drawsize= ob->empty_drawsize;
+ }
+ 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);
+
+ base->object->dup_group= ob->dup_group;
+ if(ob->dup_group)
+ id_us_plus((ID *)ob->dup_group);
+ }
+ 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==11) { /* all physical attributes */
+ base->object->gameflag = ob->gameflag;
+ base->object->inertia = ob->inertia;
+ base->object->formfactor = ob->formfactor;
+ base->object->damping= ob->damping;
+ base->object->rdamping= ob->rdamping;
+ base->object->min_vel= ob->min_vel;
+ base->object->max_vel= ob->max_vel;
+ if (ob->gameflag & OB_BOUNDS) {
+ base->object->boundtype = ob->boundtype;
+ }
+ base->object->margin= ob->margin;
+ base->object->bsoft= copy_bulletsoftbody(ob->bsoft);
+
+ }
+ else if(event==17) { /* tex space */
+ copy_texture_space(base->object, ob);
+ }
+ 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;
+ cu1->wordspace= cu->wordspace;
+ cu1->ulpos= cu->ulpos;
+ cu1->ulheight= cu->ulheight;
+ if(cu1->vfont) cu1->vfont->id.us--;
+ cu1->vfont= cu->vfont;
+ id_us_plus((ID *)cu1->vfont);
+ if(cu1->vfontb) cu1->vfontb->id.us--;
+ cu1->vfontb= cu->vfontb;
+ id_us_plus((ID *)cu1->vfontb);
+ if(cu1->vfonti) cu1->vfonti->id.us--;
+ cu1->vfonti= cu->vfonti;
+ id_us_plus((ID *)cu1->vfonti);
+ if(cu1->vfontbi) cu1->vfontbi->id.us--;
+ cu1->vfontbi= cu->vfontbi;
+ id_us_plus((ID *)cu1->vfontbi);
+
+ BKE_text_to_curve(scene, base->object, 0); /* needed? */
+
+
+ strcpy(cu1->family, cu->family);
+
+ base->object->recalc |= OB_RECALC_DATA;
+ }
+ }
+ 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->taperobj= cu->taperobj;
+ cu1->width= cu->width;
+ cu1->bevresol= cu->bevresol;
+ cu1->ext1= cu->ext1;
+ cu1->ext2= cu->ext2;
+
+ base->object->recalc |= OB_RECALC_DATA;
+ }
+ }
+ else if(event==25) { /* curve resolution */
+
+ if(ELEM(base->object->type, OB_CURVE, OB_FONT)) {
+ cu= ob->data;
+ cu1= base->object->data;
+
+ cu1->resolu= cu->resolu;
+ cu1->resolu_ren= cu->resolu_ren;
+
+ nu= cu1->nurb.first;
+
+ while(nu) {
+ nu->resolu= cu1->resolu;
+ nu= nu->next;
+ }
+
+ base->object->recalc |= OB_RECALC_DATA;
+ }
+ }
+ else if(event==21){
+ if (base->object->type==OB_MESH) {
+ ModifierData *md = modifiers_findByType(ob, eModifierType_Subsurf);
+
+ if (md) {
+ ModifierData *tmd = modifiers_findByType(base->object, eModifierType_Subsurf);
+
+ if (!tmd) {
+ tmd = modifier_new(eModifierType_Subsurf);
+ BLI_addtail(&base->object->modifiers, tmd);
+ }
+
+ modifier_copyData(md, tmd);
+ base->object->recalc |= OB_RECALC_DATA;
+ }
+ }
+ }
+ else if(event==22) {
+ /* Copy the constraint channels over */
+ copy_constraints(&base->object->constraints, &ob->constraints);
+
+ do_scene_sort= 1;
+ }
+ else if(event==23) {
+ base->object->softflag= ob->softflag;
+ if(base->object->soft) sbFree(base->object->soft);
+
+ base->object->soft= copy_softbody(ob->soft);
+
+ if (!modifiers_findByType(base->object, eModifierType_Softbody)) {
+ BLI_addhead(&base->object->modifiers, modifier_new(eModifierType_Softbody));
+ }
+ }
+ else if(event==26) {
+#if 0 // XXX old animation system
+ copy_nlastrips(&base->object->nlastrips, &ob->nlastrips);
+#endif // XXX old animation system
+ }
+ else if(event==27) { /* autosmooth */
+ if (base->object->type==OB_MESH) {
+ Mesh *me= ob->data;
+ Mesh *cme= base->object->data;
+ cme->smoothresh= me->smoothresh;
+ if(me->flag & ME_AUTOSMOOTH)
+ cme->flag |= ME_AUTOSMOOTH;
+ else
+ cme->flag &= ~ME_AUTOSMOOTH;
+ }
+ }
+ else if(event==28) { /* UV orco */
+ if(ELEM(base->object->type, OB_CURVE, OB_SURF)) {
+ cu= ob->data;
+ cu1= base->object->data;
+
+ if(cu->flag & CU_UV_ORCO)
+ cu1->flag |= CU_UV_ORCO;
+ else
+ cu1->flag &= ~CU_UV_ORCO;
+ }
+ }
+ else if(event==29) { /* protected bits */
+ base->object->protectflag= ob->protectflag;
+ }
+ else if(event==30) { /* index object */
+ base->object->index= ob->index;
+ }
+ else if(event==31) { /* object color */
+ QUATCOPY(base->object->col, ob->col);
+ }
+ }
+ }
+ }
+
+ if(do_scene_sort)
+ DAG_scene_sort(scene);
+
+ ED_anim_dag_flush_update(C);
+
+}
+
+void copy_attr_menu(Scene *scene, View3D *v3d)
+{
+ Object *ob;
+ short event;
+ char str[512];
+
+ if(!(ob=OBACT)) return;
+
+ if (scene->obedit) { // XXX get from context
+// if (ob->type == OB_MESH)
+// XXX mesh_copy_menu();
+ return;
+ }
+
+ /* Object Mode */
+
+ /* If you change this menu, don't forget to update the menu in header_view3d.c
+ * view3d_edit_object_copyattrmenu() and in toolbox.c
+ */
+
+ strcpy(str, "Copy Attributes %t|Location%x1|Rotation%x2|Size%x3|Draw Options%x4|Time Offset%x5|Dupli%x6|Object Color%x31|%l|Mass%x7|Damping%x8|All Physical Attributes%x11|Properties%x9|Logic Bricks%x10|Protected Transform%x29|%l");
+
+ strcat (str, "|Object Constraints%x22");
+ strcat (str, "|NLA Strips%x26");
+
+// XXX if (OB_SUPPORT_MATERIAL(ob)) {
+// strcat(str, "|Texture Space%x17");
+// }
+
+ if(ob->type == OB_FONT) strcat(str, "|Font Settings%x18|Bevel Settings%x19");
+ if(ob->type == OB_CURVE) strcat(str, "|Bevel Settings%x19|UV Orco%x28");
+
+ if((ob->type == OB_FONT) || (ob->type == OB_CURVE)) {
+ strcat(str, "|Curve Resolution%x25");
+ }
+
+ if(ob->type==OB_MESH){
+ strcat(str, "|Subsurf Settings%x21|AutoSmooth%x27");
+ }
+
+ if(ob->soft) strcat(str, "|Soft Body Settings%x23");
+
+ strcat(str, "|Pass Index%x30");
+
+ if(ob->type==OB_MESH || ob->type==OB_CURVE || ob->type==OB_LATTICE || ob->type==OB_SURF){
+ strcat(str, "|Modifiers ...%x24");
+ }
+
+ event= pupmenu(str);
+ if(event<= 0) return;
+
+ copy_attr(scene, v3d, event);
+}
+
+
+void link_to_scene(unsigned short nr)
+{
+#if 0
+ Scene *sce= (Scene*) BLI_findlink(&G.main->scene, G.curscreen->scenenr-1);
+ Base *base, *nbase;
+
+ if(sce==0) return;
+ if(sce->id.lib) return;
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASE(v3d, base)) {
+
+ nbase= MEM_mallocN( sizeof(Base), "newbase");
+ *nbase= *base;
+ BLI_addhead( &(sce->base), nbase);
+ id_us_plus((ID *)base->object);
+ }
+ }
+#endif
+}
+
+
+void make_links(Scene *scene, View3D *v3d, short event)
+{
+ Object *ob, *obt;
+ Base *base, *nbase, *sbase;
+ Scene *sce = NULL;
+ ID *id;
+ int a;
+ short nr=0;
+ char *strp;
+
+ if(!(ob=OBACT)) return;
+
+ if(event==1) {
+ IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->scene), 0, &nr);
+
+ if(nr == -2) {
+ MEM_freeN(strp);
+
+// XXX activate_databrowse((ID *)scene, ID_SCE, 0, B_INFOSCE, &(G.curscreen->scenenr), link_to_scene );
+
+ return;
+ }
+ else {
+ event= pupmenu_col(strp, 20);
+ 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==scene) {
+ error("This is the current scene");
+ return;
+ }
+ if(sce==0 || sce->id.lib) return;
+
+ /* remember: is needed below */
+ event= 1;
+ }
+ }
+
+ /* All non group linking */
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(event==1 || base != BASACT) {
+
+ obt= base->object;
+
+ if(TESTBASE(v3d, base)) {
+
+ if(event==1) { /* to scene */
+
+ /* test if already linked */
+ sbase= sce->base.first;
+ while(sbase) {
+ if(sbase->object==base->object) break;
+ sbase= sbase->next;
+ }
+ if(sbase) { /* remove */
+ continue;
+ }
+
+ nbase= MEM_mallocN( sizeof(Base), "newbase");
+ *nbase= *base;
+ BLI_addhead( &(sce->base), nbase);
+ id_us_plus((ID *)base->object);
+ }
+ }
+ if(TESTBASELIB(v3d, 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;
+
+ /* if amount of material indices changed: */
+ test_object_materials(obt->data);
+
+ obt->recalc |= OB_RECALC_DATA;
+ }
+ }
+ else if(event==4) { /* ob ipo */
+#if 0 // XXX old animation system
+ if(obt->ipo) obt->ipo->id.us--;
+ obt->ipo= ob->ipo;
+ if(obt->ipo) {
+ id_us_plus((ID *)obt->ipo);
+ do_ob_ipo(scene, obt);
+ }
+#endif // XXX old animation system
+ }
+ else if(event==6) {
+ if(ob->dup_group) ob->dup_group->id.us--;
+ obt->dup_group= ob->dup_group;
+ if(obt->dup_group) {
+ id_us_plus((ID *)obt->dup_group);
+ obt->transflag |= OB_DUPLIGROUP;
+ }
+ }
+ else if(event==3) { /* materials */
+
+ /* new approach, using functions from kernel */
+ for(a=0; a<ob->totcol; a++) {
+ Material *ma= give_current_material(ob, a+1);
+ assign_material(obt, ma, a+1); /* also works with ma==NULL */
+ }
+ }
+ }
+ }
+ }
+
+ ED_anim_dag_flush_update(C);
+
+}
+
+void make_links_menu(Scene *scene, View3D *v3d)
+{
+ Object *ob;
+ short event=0;
+ char str[140];
+
+ if(!(ob=OBACT)) return;
+
+ strcpy(str, "Make Links %t|To Scene...%x1|%l|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, "|Text Data%x2|Materials%x3");
+ else if(ob->type==OB_SURF)
+ strcat(str, "|Surface 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;
+
+ make_links(scene, v3d, event);
+}
+
+static void apply_objects_internal(Scene *scene, View3D *v3d, int apply_scale, int apply_rot )
+{
+ Base *base, *basact;
+ Object *ob;
+ bArmature *arm;
+ Mesh *me;
+ Curve *cu;
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ MVert *mvert;
+ float mat[3][3];
+ int a, change = 0;
+
+ if (!apply_scale && !apply_rot) {
+ /* do nothing? */
+ error("Nothing to do!");
+ return;
+ }
+ /* first check if we can execute */
+ for (base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ ob= base->object;
+ if(ob->type==OB_MESH) {
+ me= ob->data;
+
+ if(me->id.us>1) {
+ error("Can't apply to a multi user mesh, doing nothing.");
+ return;
+ }
+ }
+ else if (ob->type==OB_ARMATURE) {
+ arm= ob->data;
+
+ if(arm->id.us>1) {
+ error("Can't apply to a multi user armature, doing nothing.");
+ return;
+ }
+ }
+ else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ cu= ob->data;
+
+ if(cu->id.us>1) {
+ error("Can't apply to a multi user curve, doing nothing.");
+ return;
+ }
+ if(cu->key) {
+ error("Can't apply to a curve with vertex keys, doing nothing.");
+ return;
+ }
+ }
+ }
+ }
+
+ /* now execute */
+ basact= BASACT;
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ ob= base->object;
+
+ if(ob->type==OB_MESH) {
+ /* calculate matrix */
+ if (apply_scale && apply_rot)
+ object_to_mat3(ob, mat);
+ else if (apply_scale)
+ object_scale_to_mat3(ob, mat);
+ else
+ object_rot_to_mat3(ob, mat);
+
+ /* get object data */
+ me= ob->data;
+
+ /* adjust data */
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ Mat3MulVecfl(mat, mvert->co);
+ }
+
+ if (me->key) {
+ KeyBlock *kb;
+
+ for (kb=me->key->block.first; kb; kb=kb->next) {
+ float *fp= kb->data;
+
+ for (a=0; a<kb->totelem; a++, fp+=3)
+ Mat3MulVecfl(mat, fp);
+ }
+ }
+
+ /* adjust transforms */
+ if (apply_scale)
+ ob->size[0]= ob->size[1]= ob->size[2]= 1.0f;
+ if (apply_rot)
+ ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0f;
+ /*QuatOne(ob->quat);*/ /* Quats arnt used yet */
+
+ where_is_object(scene, ob);
+
+ /* texspace and normals */
+ BASACT= base;
+// XXX ED_object_enter_editmode(C, 0);
+// XXX ED_object_exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR); /* freedata, but no undo */
+ BASACT= basact;
+
+ change = 1;
+ }
+ else if (ob->type==OB_ARMATURE) {
+ if (apply_scale && apply_rot)
+ object_to_mat3(ob, mat);
+ else if (apply_scale)
+ object_scale_to_mat3(ob, mat);
+ else
+ object_rot_to_mat3(ob, mat);
+ arm= ob->data;
+
+ /* see checks above */
+// XXX apply_rot_armature(ob, mat);
+
+ /* Reset the object's transforms */
+ if (apply_scale)
+ ob->size[0]= ob->size[1]= ob->size[2]= 1.0;
+ if (apply_rot)
+ ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0;
+ /*QuatOne(ob->quat); (not used anymore)*/
+
+ where_is_object(scene, ob);
+
+ change = 1;
+ }
+ else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ float scale;
+ if (apply_scale && apply_rot)
+ object_to_mat3(ob, mat);
+ else if (apply_scale)
+ object_scale_to_mat3(ob, mat);
+ else
+ object_rot_to_mat3(ob, mat);
+ scale = Mat3ToScalef(mat);
+ cu= ob->data;
+
+ /* see checks above */
+
+ nu= cu->nurb.first;
+ while(nu) {
+ if( (nu->type & 7)==CU_BEZIER) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ Mat3MulVecfl(mat, bezt->vec[0]);
+ Mat3MulVecfl(mat, bezt->vec[1]);
+ Mat3MulVecfl(mat, bezt->vec[2]);
+ bezt->radius *= scale;
+ bezt++;
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ Mat3MulVecfl(mat, bp->vec);
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ if (apply_scale)
+ ob->size[0]= ob->size[1]= ob->size[2]= 1.0;
+ if (apply_rot)
+ ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0;
+ /*QuatOne(ob->quat); (quats arnt used anymore)*/
+
+ where_is_object(scene, ob);
+
+ /* texspace and normals */
+ BASACT= base;
+// XXX ED_object_enter_editmode(C, 0);
+// XXX ED_object_exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR); /* freedata, but no undo */
+ BASACT= basact;
+
+ change = 1;
+ } else {
+ continue;
+ }
+
+ ignore_parent_tx(scene, ob);
+ }
+ }
+ if (change) {
+ }
+}
+
+void apply_objects_locrot(Scene *scene, View3D *v3d)
+{
+ apply_objects_internal(scene, v3d, 1, 1);
+}
+
+void apply_objects_scale(Scene *scene, View3D *v3d)
+{
+ apply_objects_internal(scene, v3d, 1, 0);
+}
+
+void apply_objects_rot(Scene *scene, View3D *v3d)
+{
+ apply_objects_internal(scene, v3d, 0, 1);
+}
+
+void apply_objects_visual_tx( Scene *scene, View3D *v3d )
+{
+ Base *base;
+ Object *ob;
+ int change = 0;
+
+ for (base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ ob= base->object;
+ where_is_object(scene, ob);
+ VECCOPY(ob->loc, ob->obmat[3]);
+ Mat4ToSize(ob->obmat, ob->size);
+ Mat4ToEul(ob->obmat, ob->rot);
+
+ where_is_object(scene, ob);
+
+ change = 1;
+ }
+ }
+ if (change) {
+ }
+}
+
+/* ************************************** */
+
+
+void single_object_users(Scene *scene, View3D *v3d, int flag)
+{
+ Base *base;
+ Object *ob, *obn;
+
+ clear_sca_new_poins(); /* sensor/contr/act */
+
+ /* duplicate (must set newid) */
+ for(base= FIRSTBASE; base; base= base->next) {
+ ob= base->object;
+
+ if( (base->flag & flag)==flag ) {
+ if(ob->id.lib==NULL && ob->id.us>1) {
+ /* base gets copy of object */
+ obn= copy_object(ob);
+ base->object= obn;
+ ob->id.us--;
+ }
+ }
+ }
+
+ ID_NEW(scene->camera);
+ if(v3d) ID_NEW(v3d->camera);
+
+ /* object pointers */
+ for(base= FIRSTBASE; base; base= base->next) {
+ ob= base->object;
+ if(ob->id.lib==NULL) {
+ relink_constraints(&base->object->constraints);
+ if (base->object->pose){
+ bPoseChannel *chan;
+ for (chan = base->object->pose->chanbase.first; chan; chan=chan->next){
+ relink_constraints(&chan->constraints);
+ }
+ }
+ modifiers_foreachObjectLink(base->object, single_object_users__forwardModifierLinks, NULL);
+
+ ID_NEW(ob->parent);
+ ID_NEW(ob->track);
+ }
+ }
+
+ 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(Scene *scene, View3D *v3d, int flag)
+{
+ Object *ob;
+ Lamp *la;
+ Curve *cu;
+ //Camera *cam;
+ Base *base;
+ Mesh *me;
+ ID *id;
+ int a;
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ ob= base->object;
+ if(ob->id.lib==NULL && (base->flag & flag)==flag ) {
+ id= ob->data;
+
+ if(id && id->us>1 && id->lib==0) {
+ ob->recalc= OB_RECALC_DATA;
+
+ switch(ob->type) {
+ case OB_LAMP:
+ if(id && id->us>1 && id->lib==NULL) {
+ ob->data= la= copy_lamp(ob->data);
+ for(a=0; a<MAX_MTEX; 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:
+ me= ob->data= copy_mesh(ob->data);
+ //if(me && me->key)
+ // ipo_idnew(me->key->ipo); /* drivers */
+ 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);
+ ID_NEW(cu->taperobj);
+ break;
+ case OB_LATTICE:
+ ob->data= copy_lattice(ob->data);
+ break;
+ case OB_ARMATURE:
+ ob->recalc |= OB_RECALC_DATA;
+ ob->data= copy_armature(ob->data);
+ armature_rebuild_pose(ob, ob->data);
+ break;
+ default:
+ printf("ERROR single_obdata_users: %s\n", id->name);
+ error("Read console");
+ return;
+ }
+
+ id->us--;
+ id->newid= ob->data;
+
+ }
+
+#if 0 // XXX old animation system
+ id= (ID *)ob->action;
+ if (id && id->us>1 && id->lib==NULL){
+ if(id->newid){
+ ob->action= (bAction *)id->newid;
+ id_us_plus(id->newid);
+ }
+ else {
+ ob->action= copy_action(ob->action);
+ id->us--;
+ id->newid=(ID *)ob->action;
+ }
+ }
+ id= (ID *)ob->ipo;
+ if(id && id->us>1 && id->lib==NULL) {
+ 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;
+ }
+ ipo_idnew(ob->ipo); /* drivers */
+ }
+ /* other ipos */
+ 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);
+ ipo_idnew(la->ipo); /* drivers */
+ }
+ break;
+ case OB_CAMERA:
+ cam= ob->data;
+ if(cam->ipo && cam->ipo->id.us>1) {
+ cam->ipo->id.us--;
+ cam->ipo= copy_ipo(cam->ipo);
+ ipo_idnew(cam->ipo); /* drivers */
+ }
+ break;
+ }
+#endif // XXX old animation system
+ }
+ }
+
+ me= G.main->mesh.first;
+ while(me) {
+ ID_NEW(me->texcomesh);
+ me= me->id.next;
+ }
+}
+
+void single_ipo_users(Scene *scene, View3D *v3d, int flag)
+{
+#if 0 // XXX old animation system
+ Object *ob;
+ Base *base;
+ ID *id;
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ ob= base->object;
+ if(ob->id.lib==NULL && (flag==0 || (base->flag & SELECT)) ) {
+ ob->recalc= OB_RECALC_DATA;
+
+ id= (ID *)ob->ipo;
+ if(id && id->us>1 && id->lib==NULL) {
+ ob->ipo= copy_ipo(ob->ipo);
+ id->us--;
+ ipo_idnew(ob->ipo); /* drivers */
+ }
+ }
+ }
+#endif // XXX old animation system
+}
+
+void single_mat_users(Scene *scene, View3D *v3d, int flag)
+{
+ Object *ob;
+ Base *base;
+ Material *ma, *man;
+ Tex *tex;
+ int a, b;
+
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ ob= base->object;
+ if(ob->id.lib==NULL && (flag==0 || (base->flag & SELECT)) ) {
+
+ for(a=1; a<=ob->totcol; a++) {
+ ma= give_current_material(ob, a);
+ if(ma) {
+ /* do not test for LIB_NEW: this functions guaranteed delivers single_users! */
+
+ if(ma->id.us>1) {
+ man= copy_material(ma);
+
+ man->id.us= 0;
+ assign_material(ob, man, a);
+
+#if 0 // XXX old animation system
+ if(ma->ipo) {
+ man->ipo= copy_ipo(ma->ipo);
+ ma->ipo->id.us--;
+ ipo_idnew(ma->ipo); /* drivers */
+ }
+#endif // XXX old animation system
+
+ for(b=0; b<MAX_MTEX; 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--;
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+ }
+}
+
+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()
+{
+ /* only when 'parent' blocks are LIB_NEW */
+ 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<MAX_MTEX; 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<MAX_MTEX; 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<MAX_MTEX; 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)
+{
+ /* only when 'parent' blocks are LIB_NEW */
+
+ 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<MAX_MTEX; a++) {
+ if(ma->mtex[a]) {
+ ID_NEW(ma->mtex[a]->object);
+ }
+ }
+ }
+ ma= ma->id.next;
+ }
+}
+
+void single_user(Scene *scene, View3D *v3d)
+{
+ int nr;
+
+ if(scene->id.lib) return;
+
+ clear_id_newpoins();
+
+ nr= pupmenu("Make Single User%t|Object|Object & ObData|Object & ObData & Materials+Tex|Materials+Tex|Ipos");
+ if(nr>0) {
+
+ if(nr==1) single_object_users(scene, v3d, 1);
+
+ else if(nr==2) {
+ single_object_users(scene, v3d, 1);
+ single_obdata_users(scene, v3d, 1);
+ }
+ else if(nr==3) {
+ single_object_users(scene, v3d, 1);
+ single_obdata_users(scene, v3d, 1);
+ single_mat_users(scene, v3d, 1); /* also tex */
+
+ }
+ else if(nr==4) {
+ single_mat_users(scene, v3d, 1);
+ }
+ else if(nr==5) {
+ single_ipo_users(scene, v3d, 1);
+ }
+
+
+ clear_id_newpoins();
+
+ }
+}
+
+/* ************************************************************* */
+
+/* helper for below, ma was checked to be not NULL */
+static void make_local_makelocalmaterial(Material *ma)
+{
+ //ID *id;
+ int b;
+
+ make_local_material(ma);
+
+ for(b=0; b<MAX_MTEX; b++) {
+ if(ma->mtex[b] && ma->mtex[b]->tex) {
+ make_local_texture(ma->mtex[b]->tex);
+ }
+ }
+
+#if 0 // XXX old animation system
+ id= (ID *)ma->ipo;
+ if(id && id->lib) make_local_ipo(ma->ipo);
+#endif // XXX old animation system
+
+ /* nodetree? XXX */
+}
+
+void make_local(Scene *scene, View3D *v3d, int mode)
+{
+ Base *base;
+ Object *ob;
+ //bActionStrip *strip;
+ ParticleSystem *psys;
+ Material *ma, ***matarar;
+ Lamp *la;
+ Curve *cu;
+ ID *id;
+ int a, b;
+
+ /* WATCH: the function new_id(..) re-inserts the id block!!! */
+ if(scene->id.lib) return;
+
+ if(mode==3) {
+ all_local(NULL, 0); /* NULL is all libs */
+ return;
+ }
+ else if(mode<1) return;
+
+ clear_id_newpoins();
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if( TESTBASE(v3d, base) ) {
+ ob= base->object;
+ if(ob->id.lib) {
+ make_local_object(ob);
+ }
+ }
+ }
+
+ /* maybe object pointers */
+ for(base= FIRSTBASE; base; base= base->next) {
+ if( TESTBASE(v3d, base) ) {
+ ob= base->object;
+ if(ob->id.lib==NULL) {
+ ID_NEW(ob->parent);
+ ID_NEW(ob->track);
+ }
+ }
+ }
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if( TESTBASE(v3d, base) ) {
+ ob= base->object;
+ id= ob->data;
+
+ if(id && mode>1) {
+
+ switch(ob->type) {
+ case OB_LAMP:
+ make_local_lamp((Lamp *)id);
+
+ la= ob->data;
+#if 0 // XXX old animation system
+ id= (ID *)la->ipo;
+ if(id && id->lib) make_local_ipo(la->ipo);
+#endif // XXX old animation system
+ 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);
+#if 0 // XXX old animation system
+ id= (ID *)cu->ipo;
+ if(id && id->lib) make_local_ipo(cu->ipo);
+#endif // XXX old animation system
+ 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;
+ }
+
+ for(psys=ob->particlesystem.first; psys; psys=psys->next)
+ make_local_particlesettings(psys->part);
+ }
+
+#if 0 // XXX old animation system
+ 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);
+
+ for(strip=ob->nlastrips.first; strip; strip=strip->next) {
+ if(strip->act && strip->act->id.lib)
+ make_local_action(strip->act);
+ }
+#endif // XXX old animation system
+ }
+ }
+
+ if(mode>1) {
+ for(base= FIRSTBASE; base; base= base->next) {
+ if( TESTBASE(v3d, base) ) {
+ ob= base->object;
+ if(ob->type==OB_LAMP) {
+ la= ob->data;
+ for(b=0; b<MAX_MTEX; 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_makelocalmaterial(ma);
+ }
+
+ matarar= (Material ***)give_matarar(ob);
+ if (matarar) {
+ for(a=0; a<ob->totcol; a++) {
+ ma= (*matarar)[a];
+ if(ma)
+ make_local_makelocalmaterial(ma);
+ }
+ }
+ }
+ }
+ }
+ }
+
+}
+
+void make_local_menu(Scene *scene, View3D *v3d)
+{
+ int mode;
+
+ /* If you modify this menu, please remember to update view3d_edit_object_makelocalmenu
+ * in header_view3d.c and the menu in toolbox.c
+ */
+
+ if(scene->id.lib) return;
+
+ mode = pupmenu("Make Local%t|Selected Objects %x1|Selected Objects and Data %x2|All %x3");
+
+ if (mode <= 0) return;
+
+ make_local(scene, v3d, mode);
+}
+
+/* ************************ ADD DUPLICATE ******************** */
+
+/*
+ dupflag: a flag made from constants declared in DNA_userdef_types.h
+ The flag tells adduplicate() weather to copy data linked to the object, or to reference the existing data.
+ U.dupflag for default operations or you can construct a flag as python does
+ if the dupflag is 0 then no data will be copied (linked duplicate) */
+
+/* used below, assumes id.new is correct */
+/* leaves selection of base/object unaltered */
+static Base *object_add_duplicate_internal(Scene *scene, Base *base, int dupflag)
+{
+ Base *basen= NULL;
+ Material ***matarar;
+ Object *ob, *obn;
+ ID *id;
+ int a, didit;
+
+ ob= base->object;
+ if(ob->flag & OB_POSEMODE) {
+ ; /* nothing? */
+ }
+ else {
+ obn= copy_object(ob);
+ obn->recalc |= OB_RECALC;
+
+ basen= MEM_mallocN(sizeof(Base), "duplibase");
+ *basen= *base;
+ BLI_addhead(&scene->base, basen); /* addhead: prevent eternal loop */
+ basen->object= obn;
+
+ if(basen->flag & OB_FROMGROUP) {
+ Group *group;
+ for(group= G.main->group.first; group; group= group->id.next) {
+ if(object_in_group(ob, group))
+ add_to_group(group, obn);
+ }
+ obn->flag |= OB_FROMGROUP; /* this flag is unset with copy_object() */
+ }
+
+ /* duplicates using userflags */
+#if 0 // XXX old animation system
+ if(dupflag & USER_DUP_IPO) {
+ bConstraintChannel *chan;
+ 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 & USER_DUP_ACT){ /* Not buttons in the UI to modify this, add later? */
+ id= (ID *)obn->action;
+ if (id){
+ ID_NEW_US(obn->action)
+ else{
+ obn->action= copy_action(obn->action);
+ }
+ id->us--;
+ }
+ }
+#endif // XXX old animation system
+ if(dupflag & USER_DUP_MAT) {
+ 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 & USER_DUP_MESH) {
+ ID_NEW_US2( obn->data )
+ else {
+ obn->data= copy_mesh(obn->data);
+
+ if(obn->fluidsimSettings) {
+ obn->fluidsimSettings->orgMesh = (Mesh *)obn->data;
+ }
+
+ didit= 1;
+ }
+ id->us--;
+ }
+ break;
+ case OB_CURVE:
+ if(dupflag & USER_DUP_CURVE) {
+ ID_NEW_US2(obn->data )
+ else {
+ obn->data= copy_curve(obn->data);
+ didit= 1;
+ }
+ id->us--;
+ }
+ break;
+ case OB_SURF:
+ if(dupflag & USER_DUP_SURF) {
+ ID_NEW_US2( obn->data )
+ else {
+ obn->data= copy_curve(obn->data);
+ didit= 1;
+ }
+ id->us--;
+ }
+ break;
+ case OB_FONT:
+ if(dupflag & USER_DUP_FONT) {
+ ID_NEW_US2( obn->data )
+ else {
+ obn->data= copy_curve(obn->data);
+ didit= 1;
+ }
+ id->us--;
+ }
+ break;
+ case OB_MBALL:
+ if(dupflag & USER_DUP_MBALL) {
+ ID_NEW_US2(obn->data )
+ else {
+ obn->data= copy_mball(obn->data);
+ didit= 1;
+ }
+ id->us--;
+ }
+ break;
+ case OB_LAMP:
+ if(dupflag & USER_DUP_LAMP) {
+ ID_NEW_US2(obn->data )
+ else obn->data= copy_lamp(obn->data);
+ id->us--;
+ }
+ break;
+
+ case OB_ARMATURE:
+ obn->recalc |= OB_RECALC_DATA;
+ if(obn->pose) obn->pose->flag |= POSE_RECALC;
+
+ if(dupflag & USER_DUP_ARM) {
+ ID_NEW_US2(obn->data )
+ else {
+ obn->data= copy_armature(obn->data);
+ armature_rebuild_pose(obn, obn->data);
+ didit= 1;
+ }
+ id->us--;
+ }
+
+ break;
+
+ case OB_LATTICE:
+ if(dupflag!=0) {
+ ID_NEW_US2(obn->data )
+ else obn->data= copy_lattice(obn->data);
+ id->us--;
+ }
+ break;
+ case OB_CAMERA:
+ if(dupflag!=0) {
+ ID_NEW_US2(obn->data )
+ else obn->data= copy_camera(obn->data);
+ id->us--;
+ }
+ break;
+ }
+
+ if(dupflag & USER_DUP_MAT) {
+ 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--;
+ }
+ }
+ }
+ }
+ }
+ return basen;
+}
+
+/* single object duplicate, if dupflag==0, fully linked, else it uses U.dupflag */
+/* leaves selection of base/object unaltered */
+Base *ED_object_add_duplicate(Scene *scene, Base *base, int usedupflag)
+{
+ Base *basen;
+ int dupflag= usedupflag?U.dupflag:0;
+
+ clear_id_newpoins();
+ clear_sca_new_poins(); /* sensor/contr/act */
+
+ basen= object_add_duplicate_internal(scene, base, dupflag);
+
+ DAG_scene_sort(scene);
+
+ return basen;
+}
+
+/* contextual operator dupli */
+static int duplicate_add_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ View3D *v3d= CTX_wm_view3d(C);
+ int dupflag= U.dupflag;
+
+ clear_id_newpoins();
+ clear_sca_new_poins(); /* sensor/contr/act */
+
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ Base *basen= object_add_duplicate_internal(scene, base, dupflag);
+
+ /* XXX context conflict maybe, itterator could solve this? */
+ ED_base_object_select(base, BA_DESELECT);
+ /* new object becomes active */
+ if(BASACT==base)
+ ED_base_object_activate(C, basen);
+
+ }
+ CTX_DATA_END;
+
+ /* XXX fix this for context */
+ copy_object_set_idnew(scene, v3d, dupflag);
+
+ DAG_scene_sort(scene);
+ ED_anim_dag_flush_update(C);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+static int duplicate_add_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ duplicate_add_exec(C, op);
+
+ RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
+ WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_duplicate_add(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Add Duplicate";
+ ot->description = "Duplicate the object.";
+ ot->idname= "OBJECT_OT_duplicate_add";
+
+ /* api callbacks */
+ ot->invoke= duplicate_add_invoke;
+ ot->exec= duplicate_add_exec;
+
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* to give to transform */
+ RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+}
+
+/* ********************** */
+
+void image_aspect(Scene *scene, View3D *v3d)
+{
+ /* all selected objects with an image map: scale in image aspect */
+ Base *base;
+ Object *ob;
+ Material *ma;
+ Tex *tex;
+ float x, y, space;
+ int a, b, done;
+
+ if(scene->obedit) return; // XXX get from context
+ if(scene->id.lib) return;
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, 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<MAX_MTEX; b++) {
+ if(ma->mtex[b] && ma->mtex[b]->tex) {
+ tex= ma->mtex[b]->tex;
+ if(tex->type==TEX_IMAGE && tex->ima) {
+ ImBuf *ibuf= BKE_image_get_ibuf(tex->ima, NULL);
+
+ /* texturespace */
+ space= 1.0;
+ if(ob->type==OB_MESH) {
+ float size[3];
+ mesh_get_texspace(ob->data, NULL, NULL, size);
+ space= size[0]/size[1];
+ }
+ else if(ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
+ Curve *cu= ob->data;
+ space= cu->size[0]/cu->size[1];
+ }
+
+ x= ibuf->x/space;
+ y= ibuf->y;
+
+ if(x>y) ob->size[0]= ob->size[1]*x/y;
+ else ob->size[1]= ob->size[0]*y/x;
+
+ done= 1;
+ DAG_object_flush_update(scene, ob, OB_RECALC_OB);
+ }
+ }
+ if(done) break;
+ }
+ }
+ if(done) break;
+ }
+ }
+ }
+
+}
+
+void set_ob_ipoflags(Scene *scene, View3D *v3d)
+{
+#if 0 // XXX old animation system
+ Base *base;
+ int set= 1;
+
+ if (!v3d) {
+ error("Can't do this! Open a 3D window");
+ return;
+ }
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ if(base->object->ipoflag & OB_DRAWKEY) {
+ set= 0;
+ break;
+ }
+ }
+ }
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ if(set) {
+ base->object->ipoflag |= OB_DRAWKEY;
+ if(base->object->ipo) base->object->ipo->showkey= 1;
+ }
+ else {
+ base->object->ipoflag &= ~OB_DRAWKEY;
+ if(base->object->ipo) base->object->ipo->showkey= 0;
+ }
+ }
+ }
+#endif // XXX old animation system
+}
+
+
+void select_select_keys(Scene *scene, View3D *v3d)
+{
+#if 0 // XXX old animation system
+ Base *base;
+ IpoCurve *icu;
+ BezTriple *bezt;
+ int a;
+
+ if (!v3d) {
+ error("Can't do this! Open a 3D window");
+ return;
+ }
+
+ if(scene->id.lib) return;
+
+ if(okee("Show and select all keys")==0) return;
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, 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;
+ }
+ }
+ }
+ }
+
+
+#endif // XXX old animation system
+}
+
+
+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(Scene *scene, View3D *v3d)
+{
+ Base *base, **basesort, **bs;
+ float start, delta;
+ int tot=0, a;
+ short offset=25;
+
+ if(BASACT==0 || v3d==NULL) return;
+// XXX if(button(&offset, 0, 1000,"Total time")==0) return;
+
+ /* make array of all bases, xco yco (screen) */
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ tot++;
+ }
+ }
+
+ delta= (float)offset/(float)tot;
+ start= OBACT->sf;
+
+ bs= basesort= MEM_mallocN(sizeof(void *)*tot,"autotimeoffs");
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ *bs= base;
+ bs++;
+ }
+ }
+ qsort(basesort, tot, sizeof(void *), vergbaseco);
+
+ bs= basesort;
+ for(a=0; a<tot; a++) {
+
+ (*bs)->object->sf= start;
+ start+= delta;
+
+ bs++;
+ }
+ MEM_freeN(basesort);
+
+}
+
+void ofs_timeoffs(Scene *scene, View3D *v3d)
+{
+ Base *base;
+ float offset=0.0f;
+
+ if(BASACT==0 || v3d==NULL) return;
+
+// XXX if(fbutton(&offset, -10000.0f, 10000.0f, 10, 10, "Offset")==0) return;
+
+ /* make array of all bases, xco yco (screen) */
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ base->object->sf += offset;
+ if (base->object->sf < -MAXFRAMEF) base->object->sf = -MAXFRAMEF;
+ else if (base->object->sf > MAXFRAMEF) base->object->sf = MAXFRAMEF;
+ }
+ }
+
+}
+
+
+void rand_timeoffs(Scene *scene, View3D *v3d)
+{
+ Base *base;
+ float rand=0.0f;
+
+ if(BASACT==0 || v3d==NULL) return;
+
+// XXX if(fbutton(&rand, 0.0f, 10000.0f, 10, 10, "Randomize")==0) return;
+
+ rand *= 2;
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ base->object->sf += (BLI_drand()-0.5) * rand;
+ if (base->object->sf < -MAXFRAMEF) base->object->sf = -MAXFRAMEF;
+ else if (base->object->sf > MAXFRAMEF) base->object->sf = MAXFRAMEF;
+ }
+ }
+
+}
+
+
+void texspace_edit(Scene *scene, View3D *v3d)
+{
+ Base *base;
+ int nr=0;
+
+ /* first test if from visible and selected objects
+ * texspacedraw is set:
+ */
+
+ if(scene->obedit) return; // XXX get from context
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ break;
+ }
+ }
+
+ if(base==0) {
+ return;
+ }
+
+ nr= pupmenu("Texture Space %t|Grab/Move%x1|Size%x2");
+ if(nr<1) return;
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ base->object->dtx |= OB_TEXSPACE;
+ }
+ }
+
+
+ if(nr==1) {
+// XXX initTransform(TFM_TRANSLATION, CTX_TEXTURE);
+// XXX Transform();
+ }
+ else if(nr==2) {
+// XXX initTransform(TFM_RESIZE, CTX_TEXTURE);
+// XXX Transform();
+ }
+ else if(nr==3) {
+// XXX initTransform(TFM_ROTATION, CTX_TEXTURE);
+// XXX Transform();
+ }
+}
+
+/* ******************************************************************** */
+/* Mirror function in Edit Mode */
+
+void mirrormenu(void)
+{
+// XXX initTransform(TFM_MIRROR, CTX_NO_PET);
+// XXX Transform();
+}
+
+void hookmenu(Scene *scene, View3D *v3d)
+{
+ /* only called in object mode */
+ short event, changed=0;
+ Object *ob;
+ Base *base;
+ ModifierData *md;
+ HookModifierData *hmd;
+
+ event= pupmenu("Modify Hooks for Selected...%t|Reset Offset%x1|Recenter at Cursor%x2");
+ if (event==-1) return;
+ if (event==2 && !(v3d)) {
+ error("Cannot perform this operation without a 3d view");
+ return;
+ }
+
+ for (base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ for (md = base->object->modifiers.first; md; md=md->next) {
+ if (md->type==eModifierType_Hook) {
+ ob = base->object;
+ hmd = (HookModifierData*) md;
+
+ /*
+ * Copied from modifiers_cursorHookCenter and
+ * modifiers_clearHookOffset, should consolidate
+ * */
+
+ if (event==1) {
+ if(hmd->object) {
+ Mat4Invert(hmd->object->imat, hmd->object->obmat);
+ Mat4MulSerie(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ changed= 1;
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+ } else {
+ float *curs = give_cursor(scene, v3d);
+ float bmat[3][3], imat[3][3];
+
+ where_is_object(scene, ob);
+
+ Mat3CpyMat4(bmat, ob->obmat);
+ Mat3Inv(imat, bmat);
+
+ curs= give_cursor(scene, v3d);
+ hmd->cent[0]= curs[0]-ob->obmat[3][0];
+ hmd->cent[1]= curs[1]-ob->obmat[3][1];
+ hmd->cent[2]= curs[2]-ob->obmat[3][2];
+ Mat3MulVecfl(imat, hmd->cent);
+
+ changed= 1;
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+ }
+ }
+ }
+ }
+
+ if (changed) {
+ }
+}
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
new file mode 100644
index 00000000000..1c56b0c7115
--- /dev/null
+++ b/source/blender/editors/object/object_intern.h
@@ -0,0 +1,88 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_OBJECT_INTERN_H
+#define ED_OBJECT_INTERN_H
+
+struct wmOperatorType;
+struct KeyBlock;
+struct Lattice;
+struct Curve;
+struct Object;
+struct Mesh;
+
+/* internal exports only */
+
+
+/* object_edit.c */
+void OBJECT_OT_editmode_toggle(struct wmOperatorType *ot);
+void OBJECT_OT_parent_set(struct wmOperatorType *ot);
+void OBJECT_OT_parent_clear(struct wmOperatorType *ot);
+void OBJECT_OT_track_set(struct wmOperatorType *ot);
+void OBJECT_OT_track_clear(struct wmOperatorType *ot);
+void OBJECT_OT_select_all_toggle(struct wmOperatorType *ot);
+void OBJECT_OT_select_invert(struct wmOperatorType *ot);
+void OBJECT_OT_select_random(struct wmOperatorType *ot);
+void OBJECT_OT_select_by_type(struct wmOperatorType *ot);
+void OBJECT_OT_select_by_layer(struct wmOperatorType *ot);
+void OBJECT_OT_select_linked(struct wmOperatorType *ot);
+void OBJECT_OT_location_clear(struct wmOperatorType *ot);
+void OBJECT_OT_rotation_clear(struct wmOperatorType *ot);
+void OBJECT_OT_scale_clear(struct wmOperatorType *ot);
+void OBJECT_OT_origin_clear(struct wmOperatorType *ot);
+void OBJECT_OT_restrictview_set(struct wmOperatorType *ot);
+void OBJECT_OT_restrictview_clear(struct wmOperatorType *ot);
+void OBJECT_OT_slowparent_set(struct wmOperatorType *ot);
+void OBJECT_OT_slowparent_clear(struct wmOperatorType *ot);
+void OBJECT_OT_center_set(struct wmOperatorType *ot);
+void OBJECT_OT_dupli_set_real(struct wmOperatorType *ot);
+void OBJECT_OT_object_add(struct wmOperatorType *ot);
+void OBJECT_OT_duplicate_add(struct wmOperatorType *ot);
+void OBJECT_OT_delete(struct wmOperatorType *ot);
+
+void OBJECT_OT_mesh_add(struct wmOperatorType *ot);
+void OBJECT_OT_curve_add(struct wmOperatorType *ot);
+void OBJECT_OT_surface_add(struct wmOperatorType *ot);
+void OBJECT_OT_text_add(struct wmOperatorType *ot);
+void OBJECT_OT_armature_add(struct wmOperatorType *ot);
+ /* only used as menu */
+void OBJECT_OT_primitive_add(struct wmOperatorType *ot);
+
+/* editlattice.c */
+void free_editLatt(Object *ob);
+void make_editLatt(Object *obedit);
+void load_editLatt(Object *obedit);
+void remake_editLatt(Object *obedit);
+
+/* editgroup.c */
+void GROUP_OT_group_create(struct wmOperatorType *ot);
+void GROUP_OT_objects_remove(struct wmOperatorType *ot);
+void GROUP_OT_objects_add_active(struct wmOperatorType *ot);
+void GROUP_OT_objects_remove_active(struct wmOperatorType *ot);
+
+#endif /* ED_OBJECT_INTERN_H */
+
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
new file mode 100644
index 00000000000..6c8c6e6b60f
--- /dev/null
+++ b/source/blender/editors/object/object_ops.c
@@ -0,0 +1,148 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_object.h"
+
+#include "object_intern.h"
+
+
+/* ************************** registration **********************************/
+
+
+void ED_operatortypes_object(void)
+{
+ WM_operatortype_append(OBJECT_OT_editmode_toggle);
+ WM_operatortype_append(OBJECT_OT_parent_set);
+ WM_operatortype_append(OBJECT_OT_parent_clear);
+ WM_operatortype_append(OBJECT_OT_track_set);
+ WM_operatortype_append(OBJECT_OT_track_clear);
+ WM_operatortype_append(OBJECT_OT_select_invert);
+ WM_operatortype_append(OBJECT_OT_select_random);
+ WM_operatortype_append(OBJECT_OT_select_all_toggle);
+ WM_operatortype_append(OBJECT_OT_select_by_type);
+ WM_operatortype_append(OBJECT_OT_select_by_layer);
+ WM_operatortype_append(OBJECT_OT_select_linked);
+ WM_operatortype_append(OBJECT_OT_location_clear);
+ WM_operatortype_append(OBJECT_OT_rotation_clear);
+ WM_operatortype_append(OBJECT_OT_scale_clear);
+ WM_operatortype_append(OBJECT_OT_origin_clear);
+ WM_operatortype_append(OBJECT_OT_restrictview_clear);
+ WM_operatortype_append(OBJECT_OT_restrictview_set);
+ WM_operatortype_append(OBJECT_OT_slowparent_set);
+ WM_operatortype_append(OBJECT_OT_slowparent_clear);
+ WM_operatortype_append(OBJECT_OT_center_set);
+ WM_operatortype_append(OBJECT_OT_dupli_set_real);
+ WM_operatortype_append(OBJECT_OT_duplicate_add);
+ WM_operatortype_append(GROUP_OT_group_create);
+ WM_operatortype_append(GROUP_OT_objects_remove);
+ WM_operatortype_append(GROUP_OT_objects_add_active);
+ WM_operatortype_append(GROUP_OT_objects_remove_active);
+
+ WM_operatortype_append(OBJECT_OT_delete);
+ WM_operatortype_append(OBJECT_OT_mesh_add);
+ WM_operatortype_append(OBJECT_OT_curve_add);
+ WM_operatortype_append(OBJECT_OT_text_add);
+ WM_operatortype_append(OBJECT_OT_surface_add);
+ WM_operatortype_append(OBJECT_OT_armature_add);
+ WM_operatortype_append(OBJECT_OT_object_add);
+ WM_operatortype_append(OBJECT_OT_primitive_add);
+}
+
+void ED_keymap_object(wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "Object Non-modal", 0, 0);
+
+ /* Note: this keymap works disregarding mode */
+ WM_keymap_add_item(keymap, "OBJECT_OT_editmode_toggle", TABKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "OBJECT_OT_center_set", CKEY, KM_PRESS, KM_ALT|KM_CTRL, 0);
+
+ /* Note: this keymap gets disabled in non-objectmode, */
+ keymap= WM_keymap_listbase(wm, "Object Mode", 0, 0);
+
+ WM_keymap_add_item(keymap, "OBJECT_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "OBJECT_OT_select_invert", IKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "OBJECT_OT_select_random", PADASTERKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "OBJECT_OT_select_by_type", PADASTERKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "OBJECT_OT_select_by_layer", PADASTERKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "OBJECT_OT_select_linked", LKEY, KM_PRESS, KM_SHIFT, 0);
+
+ WM_keymap_verify_item(keymap, "OBJECT_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_verify_item(keymap, "OBJECT_OT_parent_clear", PKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "OBJECT_OT_track_set", TKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_verify_item(keymap, "OBJECT_OT_track_set", TKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_verify_item(keymap, "OBJECT_OT_location_clear", GKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "OBJECT_OT_rotation_clear", RKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "OBJECT_OT_scale_clear", SKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "OBJECT_OT_origin_clear", OKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_verify_item(keymap, "OBJECT_OT_restrictview_clear", HKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "OBJECT_OT_restrictview_set", HKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_verify_item(keymap, "OBJECT_OT_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "OBJECT_OT_primitive_add", AKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_verify_item(keymap, "OBJECT_OT_duplicate_add", DKEY, KM_PRESS, KM_SHIFT, 0);
+
+ // XXX this should probably be in screen instead... here for testing purposes in the meantime... - Aligorith
+ WM_keymap_verify_item(keymap, "ANIM_OT_insert_keyframe_menu", IKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "ANIM_OT_delete_keyframe_old", IKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_verify_item(keymap, "GROUP_OT_group_create", GKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove", GKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "GROUP_OT_objects_add_active", GKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
+ WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_active", GKEY, KM_PRESS, KM_SHIFT|KM_ALT, 0);
+
+}
+
diff --git a/source/blender/editors/physics/Makefile b/source/blender/editors/physics/Makefile
new file mode 100644
index 00000000000..bd2dbc65f91
--- /dev/null
+++ b/source/blender/editors/physics/Makefile
@@ -0,0 +1,57 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_physics
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+CPPFLAGS += -I$(NAN_BMFONT)/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I$(NAN_ELBEEM)/include
+
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../gpu
+CPPFLAGS += -I../../render/extern/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/physics/SConscript b/source/blender/editors/physics/SConscript
new file mode 100644
index 00000000000..241962442d4
--- /dev/null
+++ b/source/blender/editors/physics/SConscript
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' #/intern/guardedalloc #intern/bmfont ../../gpu'
+incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
+
+env.BlenderLib ( 'bf_editors_physics', sources, Split(incs), [], libtype=['core'], priority=[45] )
diff --git a/source/blender/editors/physics/ed_fluidsim.c b/source/blender/editors/physics/ed_fluidsim.c
new file mode 100644
index 00000000000..215a72d6927
--- /dev/null
+++ b/source/blender/editors/physics/ed_fluidsim.c
@@ -0,0 +1,1149 @@
+/**
+ * fluidsim.c
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#ifdef WIN32 /* Windos */
+#ifndef snprintf
+#define snprintf _snprintf
+#endif
+#endif
+
+#include "MEM_guardedalloc.h"
+
+/* types */
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_fluidsim.h"
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_key_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_threads.h"
+#include "BLI_arithb.h"
+
+#include "BKE_blender.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_displist.h"
+#include "BKE_effect.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_modifier.h"
+#include "BKE_main.h"
+#include "BKE_key.h"
+#include "BKE_scene.h"
+#include "BKE_object.h"
+#include "BKE_softbody.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_ipo.h"
+
+#include "PIL_time.h"
+
+#include "LBM_fluidsim.h"
+
+#include "BIF_gl.h"
+
+#include "ED_fluidsim.h"
+#include "ED_screen.h"
+
+/* XXX */
+/* from header info.c */
+static int start_progress_bar(void) {return 0;};
+static void end_progress_bar(void) {};
+static void waitcursor() {};
+static int progress_bar(float done, char *busy_info) {return 0;}
+static int pupmenu() {return 0;}
+/* XXX */
+
+
+double fluidsimViscosityPreset[6] = {
+ -1.0, /* unused */
+ -1.0, /* manual */
+ 1.0e-6, /* water */
+ 5.0e-5, /* some (thick) oil */
+ 2.0e-3, /* ca. honey */
+ -1.0 /* end */
+};
+
+char* fluidsimViscosityPresetString[6] = {
+ "UNUSED", /* unused */
+ "UNUSED", /* manual */
+ " = 1.0 * 10^-6", /* water */
+ " = 5.0 * 10^-5", /* some (thick) oil */
+ " = 2.0 * 10^-3", /* ca. honey */
+ "INVALID" /* end */
+};
+
+/* enable/disable overall compilation */
+#ifndef DISABLE_ELBEEM
+
+
+/* ********************** fluid sim settings struct functions ********************** */
+
+/* helper function */
+void fluidsimGetGeometryObjFilename(struct Object *ob, char *dst) { //, char *srcname) {
+ //snprintf(dst,FILE_MAXFILE, "%s_cfgdata_%s.bobj.gz", srcname, ob->id.name);
+ snprintf(dst,FILE_MAXFILE, "fluidcfgdata_%s.bobj.gz", ob->id.name);
+}
+
+
+
+
+/* ******************************************************************************** */
+/* ********************** fluid sim channel helper functions ********************** */
+/* ******************************************************************************** */
+
+// no. of entries for the two channel sizes
+#define CHANNEL_FLOAT 1
+#define CHANNEL_VEC 3
+
+#define FS_FREE_ONECHANNEL(c,str) { \
+ if(c){ MEM_freeN(c); c=NULL; } \
+} // end ONE CHANN, debug: fprintf(stderr,"freeing " str " \n");
+
+#define FS_FREE_CHANNELS { \
+ FS_FREE_ONECHANNEL(timeAtIndex,"timeAtIndex");\
+ FS_FREE_ONECHANNEL(timeAtFrame,"timeAtFrame");\
+ FS_FREE_ONECHANNEL(channelDomainTime,"channelDomainTime"); \
+ FS_FREE_ONECHANNEL(channelDomainGravity,"channelDomainGravity");\
+ FS_FREE_ONECHANNEL(channelDomainViscosity,"channelDomainViscosity");\
+ for(i=0;i<256;i++) { \
+ FS_FREE_ONECHANNEL(channelObjMove[i][0],"channelObjMove0"); \
+ FS_FREE_ONECHANNEL(channelObjMove[i][1],"channelObjMove1"); \
+ FS_FREE_ONECHANNEL(channelObjMove[i][2],"channelObjMove2"); \
+ FS_FREE_ONECHANNEL(channelObjInivel[i],"channelObjInivel"); \
+ FS_FREE_ONECHANNEL(channelObjActive[i],"channelObjActive"); \
+ FS_FREE_ONECHANNEL(channelAttractforceStrength[i],"channelAttractforceStrength"); \
+ FS_FREE_ONECHANNEL(channelAttractforceRadius[i],"channelAttractforceRadius"); \
+ FS_FREE_ONECHANNEL(channelVelocityforceStrength[i],"channelVelocityforceStrength"); \
+ FS_FREE_ONECHANNEL(channelVelocityforceRadius[i],"channelVelocityforceRadius"); \
+ } \
+} // end FS FREE CHANNELS
+
+
+// simplify channels before printing
+// for API this is done anyway upon init
+#if 0
+static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char *str, int entries)
+{
+ int i,j;
+ int channelSize = paramsize;
+
+ if(entries==3) {
+ elbeemSimplifyChannelVec3( channel, &channelSize);
+ } else if(entries==1) {
+ elbeemSimplifyChannelFloat( channel, &channelSize);
+ } else {
+ // invalid, cant happen?
+ }
+
+ fprintf(file, " CHANNEL %s = \n", str);
+ for(i=0; i<channelSize;i++) {
+ fprintf(file," ");
+ for(j=0;j<=entries;j++) { // also print time value
+ fprintf(file," %f ", channel[i*(entries+1)+j] );
+ if(j==entries-1){ fprintf(file," "); }
+ }
+ fprintf(file," \n");
+ }
+
+ fprintf(file, " ; \n" );
+}
+#endif
+
+static void fluidsimInitChannel(Scene *scene, float **setchannel, int size, float *time,
+ int *icuIds, float *defaults, Ipo* ipo, int entries)
+{
+#if 0
+ /* goes away completely */
+ int i,j;
+ IpoCurve* icus[3];
+ char *cstr = NULL;
+ float *channel = NULL;
+ float aniFrlen = scene->r.framelen;
+ int current_frame = scene->r.cfra;
+ if((entries<1) || (entries>3)) {
+ printf("fluidsimInitChannel::Error - invalid no. of entries: %d\n",entries);
+ entries = 1;
+ }
+
+ cstr = "fluidsiminit_channelfloat";
+ if(entries>1) cstr = "fluidsiminit_channelvec";
+ channel = MEM_callocN( size* (entries+1)* sizeof(float), cstr );
+
+ if(ipo) {
+ for(j=0; j<entries; j++) icus[j] = find_ipocurve(ipo, icuIds[j] );
+ } else {
+ for(j=0; j<entries; j++) icus[j] = NULL;
+ }
+
+ for(j=0; j<entries; j++) {
+ if(icus[j]) {
+ for(i=1; i<=size; i++) {
+ /* Bugfix to make python drivers working
+ // which uses Blender.get("curframe")
+ */
+ scene->r.cfra = floor(aniFrlen*((float)i));
+
+ // XXX calc_icu(icus[j], aniFrlen*((float)i) );
+ channel[(i-1)*(entries+1) + j] = icus[j]->curval;
+ }
+ } else {
+ for(i=1; i<=size; i++) { channel[(i-1)*(entries+1) + j] = defaults[j]; }
+ }
+ //printf("fluidsimInitChannel entry:%d , ",j); for(i=1; i<=size; i++) { printf(" val%d:%f ",i, channel[(i-1)*(entries+1) + j] ); } printf(" \n"); // DEBUG
+ }
+ // set time values
+ for(i=1; i<=size; i++) {
+ channel[(i-1)*(entries+1) + entries] = time[i];
+ }
+ scene->r.cfra = current_frame;
+ *setchannel = channel;
+#endif
+}
+
+static void fluidsimInitMeshChannel(bContext *C, float **setchannel, int size, Object *obm, int vertices,
+ float *time, int modifierIndex)
+{
+ Scene *scene= CTX_data_scene(C);
+ float *channel = NULL;
+ int mallsize = size* (3*vertices+1);
+ int frame,i;
+ int numVerts=0, numTris=0;
+ int setsize = 3*vertices+1;
+
+ channel = MEM_callocN( mallsize* sizeof(float), "fluidsim_meshchannel" );
+
+ //fprintf(stderr,"\n\nfluidsimInitMeshChannel size%d verts%d mallsize%d \n\n\n",size,vertices,mallsize);
+ for(frame=1; frame<=size; frame++) {
+ float *verts=NULL;
+ int *tris=NULL;
+ scene->r.cfra = frame;
+ ED_update_for_newframe(C, 1);
+
+ initElbeemMesh(scene, obm, &numVerts, &verts, &numTris, &tris, 1, modifierIndex);
+ //fprintf(stderr,"\nfluidsimInitMeshChannel frame%d verts%d/%d \n\n",frame,vertices,numVerts);
+ for(i=0; i<3*vertices;i++) {
+ channel[(frame-1)*setsize + i] = verts[i];
+ //fprintf(stdout," frame%d vert%d=%f \n",frame,i,verts[i]);
+ //if(i%3==2) fprintf(stdout,"\n");
+ }
+ channel[(frame-1)*setsize + setsize-1] = time[frame];
+
+ MEM_freeN(verts);
+ MEM_freeN(tris);
+ }
+ *setchannel = channel;
+}
+
+
+/* ******************************************************************************** */
+/* ********************** simulation thread ************************* */
+/* ******************************************************************************** */
+
+static volatile int globalBakeState = 0; // 0 everything ok, -1 abort simulation, -2 sim error, 1 sim done
+static volatile int globalBakeFrame = 0;
+static volatile int g_break= 0;
+
+// run simulation in seperate thread
+static void *fluidsimSimulateThread(void *unused) { // *ptr) {
+ //char* fnameCfgPath = (char*)(ptr);
+ int ret=0;
+
+ ret = elbeemSimulate();
+ BLI_lock_thread(LOCK_CUSTOM1);
+ if(globalBakeState==0) {
+ if(ret==0) {
+ // if no error, set to normal exit
+ globalBakeState = 1;
+ } else {
+ // simulation failed, display error
+ globalBakeState = -2;
+ }
+ }
+ BLI_unlock_thread(LOCK_CUSTOM1);
+ return NULL;
+}
+
+
+int runSimulationCallback(void *data, int status, int frame) {
+ //elbeemSimulationSettings *settings = (elbeemSimulationSettings*)data;
+ //printf("elbeem blender cb s%d, f%d, domainid:%d \n", status,frame, settings->domainId ); // DEBUG
+ int state = 0;
+ if(status==FLUIDSIM_CBSTATUS_NEWFRAME) {
+ BLI_lock_thread(LOCK_CUSTOM1);
+ globalBakeFrame = frame-1;
+ BLI_unlock_thread(LOCK_CUSTOM1);
+ }
+
+ //if((frameCounter==3) && (!frameStop)) { frameStop=1; return 1; }
+
+ BLI_lock_thread(LOCK_CUSTOM1);
+ state = globalBakeState;
+ BLI_unlock_thread(LOCK_CUSTOM1);
+
+ if(state!=0) {
+ return FLUIDSIM_CBRET_ABORT;
+ }
+
+ return FLUIDSIM_CBRET_CONTINUE;
+}
+
+
+/* ******************************************************************************** */
+/* ********************** write fluidsim config to file ************************* */
+/* ******************************************************************************** */
+
+void fluidsimBake(bContext *C, struct Object *ob)
+{
+ Scene *scene= CTX_data_scene(C);
+ FILE *fileCfg;
+ int i;
+ struct Object *fsDomain = NULL;
+ FluidsimSettings *domainSettings;
+ struct Object *obit = NULL; /* object iterator */
+ Base *base;
+ int origFrame = scene->r.cfra;
+ char debugStrBuffer[256];
+ int dirExist = 0;
+ int gridlevels = 0;
+ int simAborted = 0; // was the simulation aborted by user?
+ int doExportOnly = 0;
+ char *exportEnvStr = "BLENDER_ELBEEMEXPORTONLY";
+ const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp
+ //char *channelNames[3] = { "translation","rotation","scale" };
+
+ char *suffixConfig = "fluidsim.cfg";
+ char *suffixSurface = "fluidsurface";
+ char newSurfdataPath[FILE_MAXDIR+FILE_MAXFILE]; // modified output settings
+ char targetDir[FILE_MAXDIR+FILE_MAXFILE]; // store & modify output settings
+ char targetFile[FILE_MAXDIR+FILE_MAXFILE]; // temp. store filename from targetDir for access
+ int outStringsChanged = 0; // modified? copy back before baking
+ int haveSomeFluid = 0; // check if any fluid objects are set
+
+ // config vars, inited before either export or run...
+ double calcViscosity = 0.0;
+ int noFrames;
+ double aniFrameTime;
+ float aniFrlen;
+ int channelObjCount;
+ float *bbStart = NULL;
+ float *bbSize = NULL;
+ float domainMat[4][4];
+ float invDomMat[4][4];
+ // channel data
+ int allchannelSize; // fixed by no. of frames
+ int startFrame = 1; // dont use scene->r.sfra here, always start with frame 1
+ // easy frame -> sim time calc
+ float *timeAtFrame=NULL, *timeAtIndex=NULL;
+ // domain
+ float *channelDomainTime = NULL;
+ float *channelDomainViscosity = NULL;
+ float *channelDomainGravity = NULL;
+ // objects (currently max. 256 objs)
+ float *channelObjMove[256][3]; // object movments , 0=trans, 1=rot, 2=scale
+ float *channelObjInivel[256]; // initial velocities
+ float *channelObjActive[256]; // obj active channel
+
+ /* fluid control channels */
+ float *channelAttractforceStrength[256];
+ float *channelAttractforceRadius[256];
+ float *channelVelocityforceStrength[256];
+ float *channelVelocityforceRadius[256];
+ FluidsimModifierData *fluidmd = NULL;
+ Mesh *mesh = NULL;
+
+ if(getenv(strEnvName)) {
+ int dlevel = atoi(getenv(strEnvName));
+ elbeemSetDebugLevel(dlevel);
+ snprintf(debugStrBuffer,256,"fluidsimBake::msg: Debug messages activated due to envvar '%s'\n",strEnvName);
+ elbeemDebugOut(debugStrBuffer);
+ }
+ if(getenv(exportEnvStr)) {
+ doExportOnly = atoi(getenv(exportEnvStr));
+ snprintf(debugStrBuffer,256,"fluidsimBake::msg: Exporting mode set to '%d' due to envvar '%s'\n",doExportOnly, exportEnvStr);
+ elbeemDebugOut(debugStrBuffer);
+ }
+
+ // make sure it corresponds to startFrame setting
+ // old: noFrames = scene->r.efra - scene->r.sfra +1;
+ noFrames = scene->r.efra - 0;
+ if(noFrames<=0) {
+ pupmenu("Fluidsim Bake Error%t|No frames to export - check your animation range settings. Aborted%x0");
+ return;
+ }
+
+ /* no object pointer, find in selected ones.. */
+ if(!ob) {
+ for(base=scene->base.first; base; base= base->next) {
+ if ((base)->flag & SELECT)
+ {
+ FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
+
+ if(fluidmdtmp && (base->object->type==OB_MESH))
+ {
+ if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN)
+ {
+ ob = base->object;
+ break;
+ }
+ }
+ }
+ }
+ // no domains found?
+ if(!ob) return;
+ }
+
+ channelObjCount = 0;
+ for(base=scene->base.first; base; base= base->next)
+ {
+ FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
+ obit = base->object;
+ if( fluidmdtmp &&
+ (obit->type==OB_MESH) &&
+ (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) && // if has to match 3 places! // CHECKMATCH
+ (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) )
+ {
+ channelObjCount++;
+ }
+ }
+
+ if (channelObjCount>=255) {
+ pupmenu("Fluidsim Bake Error%t|Cannot bake with more then 256 objects");
+ return;
+ }
+
+ /* check if there's another domain... */
+ for(base=scene->base.first; base; base= base->next)
+ {
+ FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
+ obit = base->object;
+ if( fluidmdtmp &&(obit->type==OB_MESH))
+ {
+ if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN)
+ {
+ if(obit != ob)
+ {
+ pupmenu("Fluidsim Bake Error%t|There should be only one domain object! Aborted%x0");
+ return;
+ }
+ }
+ }
+ }
+
+ // check if theres any fluid
+ // abort baking if not...
+ for(base=scene->base.first; base; base= base->next)
+ {
+ FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
+ obit = base->object;
+ if( fluidmdtmp &&
+ (obit->type==OB_MESH) &&
+ ((fluidmdtmp->fss->type == OB_FLUIDSIM_FLUID) ||
+ (fluidmdtmp->fss->type == OB_FLUIDSIM_INFLOW) ))
+ {
+ haveSomeFluid = 1;
+ break;
+ }
+ }
+ if(!haveSomeFluid) {
+ pupmenu("Fluidsim Bake Error%t|No fluid objects in scene... Aborted%x0");
+ return;
+ }
+
+ /* these both have to be valid, otherwise we wouldnt be here */
+ /* dont use ob here after...*/
+ fsDomain = ob;
+ fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
+ domainSettings = fluidmd->fss;
+ ob = NULL;
+ mesh = fsDomain->data;
+
+ // calculate bounding box
+ fluid_get_bb(mesh->mvert, mesh->totvert, fsDomain->obmat, domainSettings->bbStart, domainSettings->bbSize);
+
+ // reset last valid frame
+ domainSettings->lastgoodframe = -1;
+
+ /* rough check of settings... */
+ if(domainSettings->previewresxyz > domainSettings->resolutionxyz) {
+ snprintf(debugStrBuffer,256,"fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz , domainSettings->resolutionxyz);
+ elbeemDebugOut(debugStrBuffer);
+ domainSettings->previewresxyz = domainSettings->resolutionxyz;
+ }
+ // set adaptive coarsening according to resolutionxyz
+ // this should do as an approximation, with in/outflow
+ // doing this more accurate would be overkill
+ // perhaps add manual setting?
+ if(domainSettings->maxRefine <0) {
+ if(domainSettings->resolutionxyz>128) {
+ gridlevels = 2;
+ } else
+ if(domainSettings->resolutionxyz>64) {
+ gridlevels = 1;
+ } else {
+ gridlevels = 0;
+ }
+ } else {
+ gridlevels = domainSettings->maxRefine;
+ }
+ snprintf(debugStrBuffer,256,"fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name , gridlevels );
+ elbeemDebugOut(debugStrBuffer);
+
+ // prepare names...
+ strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
+ strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR);
+ BLI_convertstringcode(targetDir, G.sce); // fixed #frame-no
+
+ strcpy(targetFile, targetDir);
+ strcat(targetFile, suffixConfig);
+ if(!doExportOnly) { strcat(targetFile,".tmp"); } // dont overwrite/delete original file
+ // make sure all directories exist
+ // as the bobjs use the same dir, this only needs to be checked
+ // for the cfg output
+ BLI_make_existing_file(targetFile);
+
+ // check selected directory
+ // simply try to open cfg file for writing to test validity of settings
+ fileCfg = fopen(targetFile, "w");
+ if(fileCfg) {
+ dirExist = 1; fclose(fileCfg);
+ // remove cfg dummy from directory test
+ if(!doExportOnly) { BLI_delete(targetFile, 0,0); }
+ }
+
+ if((strlen(targetDir)<1) || (!dirExist)) {
+ char blendDir[FILE_MAXDIR+FILE_MAXFILE], blendFile[FILE_MAXDIR+FILE_MAXFILE];
+ // invalid dir, reset to current/previous
+ strcpy(blendDir, G.sce);
+ BLI_splitdirstring(blendDir, blendFile);
+ if(strlen(blendFile)>6){
+ int len = strlen(blendFile);
+ if( (blendFile[len-6]=='.')&& (blendFile[len-5]=='b')&& (blendFile[len-4]=='l')&&
+ (blendFile[len-3]=='e')&& (blendFile[len-2]=='n')&& (blendFile[len-1]=='d') ){
+ blendFile[len-6] = '\0';
+ }
+ }
+ // todo... strip .blend ?
+ snprintf(newSurfdataPath,FILE_MAXFILE+FILE_MAXDIR,"//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name);
+
+ snprintf(debugStrBuffer,256,"fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath);
+ elbeemDebugOut(debugStrBuffer);
+ outStringsChanged=1;
+ }
+
+ // check if modified output dir is ok
+ if(outStringsChanged) {
+ char dispmsg[FILE_MAXDIR+FILE_MAXFILE+256];
+ int selection=0;
+ strcpy(dispmsg,"Output settings set to: '");
+ strcat(dispmsg, newSurfdataPath);
+ strcat(dispmsg, "'%t|Continue with changed settings%x1|Discard and abort%x0");
+
+ // ask user if thats what he/she wants...
+ selection = pupmenu(dispmsg);
+ if(selection<1) return; // 0 from menu, or -1 aborted
+ strcpy(targetDir, newSurfdataPath);
+ strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR);
+ BLI_convertstringcode(targetDir, G.sce); // fixed #frame-no
+ }
+
+ // --------------------------------------------------------------------------------------------
+ // dump data for start frame
+ // CHECK more reasonable to number frames according to blender?
+ // dump data for frame 0
+ scene->r.cfra = startFrame;
+ ED_update_for_newframe(C, 1);
+
+ // init common export vars for both file export and run
+ for(i=0; i<256; i++) {
+ channelObjMove[i][0] = channelObjMove[i][1] = channelObjMove[i][2] = NULL;
+ channelObjInivel[i] = NULL;
+ channelObjActive[i] = NULL;
+ channelAttractforceStrength[i] = NULL;
+ channelAttractforceRadius[i] = NULL;
+ channelVelocityforceStrength[i] = NULL;
+ channelVelocityforceRadius[i] = NULL;
+ }
+ allchannelSize = scene->r.efra; // always use till last frame
+ aniFrameTime = (domainSettings->animEnd - domainSettings->animStart)/(double)noFrames;
+ // blender specific - scale according to map old/new settings in anim panel:
+ aniFrlen = scene->r.framelen;
+ if(domainSettings->viscosityMode==1) {
+ /* manual mode, visc=value/(10^-vexp) */
+ calcViscosity = (1.0/pow(10.0,domainSettings->viscosityExponent)) * domainSettings->viscosityValue;
+ } else {
+ calcViscosity = fluidsimViscosityPreset[ domainSettings->viscosityMode ];
+ }
+
+ bbStart = domainSettings->bbStart;
+ bbSize = domainSettings->bbSize;
+
+ // always init
+ { int timeIcu[1] = { FLUIDSIM_TIME };
+ float timeDef[1] = { 1. };
+ int gravIcu[3] = { FLUIDSIM_GRAV_X, FLUIDSIM_GRAV_Y, FLUIDSIM_GRAV_Z };
+ float gravDef[3];
+ int viscIcu[1] = { FLUIDSIM_VISC };
+ float viscDef[1] = { 1. };
+
+ gravDef[0] = domainSettings->gravx;
+ gravDef[1] = domainSettings->gravy;
+ gravDef[2] = domainSettings->gravz;
+
+ // time channel is a bit special, init by hand...
+ timeAtIndex = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatindex");
+ for(i=0; i<=scene->r.efra; i++) {
+ timeAtIndex[i] = (float)(i-startFrame);
+ }
+ fluidsimInitChannel(scene, &channelDomainTime, allchannelSize, timeAtIndex, timeIcu,timeDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB
+ // time channel is a multiplicator for aniFrameTime
+ if(channelDomainTime) {
+ for(i=0; i<allchannelSize; i++) {
+ channelDomainTime[i*2+0] = aniFrameTime * channelDomainTime[i*2+0];
+ if(channelDomainTime[i*2+0]<0.) channelDomainTime[i*2+0] = 0.;
+ }
+ }
+ timeAtFrame = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatframe");
+ timeAtFrame[0] = timeAtFrame[1] = domainSettings->animStart; // start at index 1
+ if(channelDomainTime) {
+ for(i=2; i<=allchannelSize; i++) {
+ timeAtFrame[i] = timeAtFrame[i-1]+channelDomainTime[(i-1)*2+0];
+ }
+ } else {
+ for(i=2; i<=allchannelSize; i++) { timeAtFrame[i] = timeAtFrame[i-1]+aniFrameTime; }
+ }
+
+ fluidsimInitChannel(scene, &channelDomainViscosity, allchannelSize, timeAtFrame, viscIcu,viscDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB
+ if(channelDomainViscosity) {
+ for(i=0; i<allchannelSize; i++) { channelDomainViscosity[i*2+0] = calcViscosity * channelDomainViscosity[i*2+0]; }
+ }
+ fluidsimInitChannel(scene, &channelDomainGravity, allchannelSize, timeAtFrame, gravIcu,gravDef, domainSettings->ipo, CHANNEL_VEC );
+ } // domain channel init
+
+ // init obj movement channels
+ channelObjCount=0;
+ for(base=scene->base.first; base; base= base->next)
+ {
+ FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
+ obit = base->object;
+
+ if( fluidmdtmp &&
+ (obit->type==OB_MESH) &&
+ (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) && // if has to match 3 places! // CHECKMATCH
+ (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) ) {
+
+ // cant use fluidsimInitChannel for obj channels right now, due
+ // to the special DXXX channels, and the rotation specialities
+ IpoCurve *icuex[3][3];
+ //IpoCurve *par_icuex[3][3];
+#if 0
+ int icuIds[3][3] = {
+ {OB_LOC_X, OB_LOC_Y, OB_LOC_Z},
+ {OB_ROT_X, OB_ROT_Y, OB_ROT_Z},
+ {OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z}
+ };
+ int icudIds[3][3] = {
+ {OB_DLOC_X, OB_DLOC_Y, OB_DLOC_Z},
+ {OB_DROT_X, OB_DROT_Y, OB_DROT_Z},
+ {OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z}
+ };
+#endif
+ // relative ipos
+ IpoCurve *icudex[3][3];
+ //IpoCurve *par_icudex[3][3];
+ int j,k;
+ float vals[3] = {0.0,0.0,0.0};
+ int o = channelObjCount;
+ int inivelIcu[3] = { FLUIDSIM_VEL_X, FLUIDSIM_VEL_Y, FLUIDSIM_VEL_Z };
+ float inivelDefs[3];
+ int activeIcu[1] = { FLUIDSIM_ACTIVE };
+ float activeDefs[1] = { 1 }; // default to on
+
+ inivelDefs[0] = fluidmdtmp->fss->iniVelx;
+ inivelDefs[1] = fluidmdtmp->fss->iniVely;
+ inivelDefs[2] = fluidmdtmp->fss->iniVelz;
+
+ // check & init loc,rot,size
+ for(j=0; j<3; j++) {
+ for(k=0; k<3; k++) {
+ // XXX icuex[j][k] = find_ipocurve(obit->ipo, icuIds[j][k] );
+ // XXX icudex[j][k] = find_ipocurve(obit->ipo, icudIds[j][k] );
+ // XXX lines below were already disabled!
+ //if(obit->parent) {
+ //par_icuex[j][k] = find_ipocurve(obit->parent->ipo, icuIds[j][k] );
+ //par_icudex[j][k] = find_ipocurve(obit->parent->ipo, icudIds[j][k] );
+ //}
+ }
+ }
+
+ for(j=0; j<3; j++) {
+ channelObjMove[o][j] = MEM_callocN( allchannelSize*4*sizeof(float), "fluidsiminit_objmovchannel");
+ for(i=1; i<=allchannelSize; i++) {
+
+ for(k=0; k<3; k++) {
+ if(icuex[j][k]) {
+ // IPO exists, use it ...
+ // XXX calc_icu(icuex[j][k], aniFrlen*((float)i) );
+ vals[k] = icuex[j][k]->curval;
+ if(obit->parent) {
+ // add parent transform, multiply scaling, add trafo&rot
+ //calc_icu(par_icuex[j][k], aniFrlen*((float)i) );
+ //if(j==2) { vals[k] *= par_icuex[j][k]->curval; }
+ //else { vals[k] += par_icuex[j][k]->curval; }
+ }
+ } else {
+ // use defaults from static values
+ float setval=0.0;
+ if(j==0) {
+ setval = obit->loc[k];
+ if(obit->parent){ setval += obit->parent->loc[k]; }
+ } else if(j==1) {
+ setval = ( 180.0*obit->rot[k] )/( 10.0*M_PI );
+ if(obit->parent){ setval = ( 180.0*(obit->rot[k]+obit->parent->rot[k]) )/( 10.0*M_PI ); }
+ } else {
+ setval = obit->size[k];
+ if(obit->parent){ setval *= obit->parent->size[k]; }
+ }
+ vals[k] = setval;
+ }
+ if(icudex[j][k]) {
+ // XXX calc_icu(icudex[j][k], aniFrlen*((float)i) );
+ //vals[k] += icudex[j][k]->curval;
+ // add transform, multiply scaling, add trafo&rot
+ if(j==2) { vals[k] *= icudex[j][k]->curval; }
+ else { vals[k] += icudex[j][k]->curval; }
+ if(obit->parent) {
+ // add parent transform, multiply scaling, add trafo&rot
+ //calc_icu(par_icuex[j][k], aniFrlen*((float)i) );
+ //if(j==2) { vals[k] *= par_icudex[j][k]->curval; }
+ //else { vals[k] += par_icudex[j][k]->curval; }
+ }
+ }
+ } // k
+
+ for(k=0; k<3; k++) {
+ float set = vals[k];
+ if(j==1) { // rot is downscaled by 10 for ipo !?
+ set = 360.0 - (10.0*set);
+ }
+ channelObjMove[o][j][(i-1)*4 + k] = set;
+ } // k
+ channelObjMove[o][j][(i-1)*4 + 3] = timeAtFrame[i];
+ }
+ }
+
+ {
+ int attrFSIcu[1] = { FLUIDSIM_ATTR_FORCE_STR };
+ int attrFRIcu[1] = { FLUIDSIM_ATTR_FORCE_RADIUS };
+ int velFSIcu[1] = { FLUIDSIM_VEL_FORCE_STR };
+ int velFRIcu[1] = { FLUIDSIM_VEL_FORCE_RADIUS };
+
+ float attrFSDefs[1];
+ float attrFRDefs[1];
+ float velFSDefs[1];
+ float velFRDefs[1];
+
+ attrFSDefs[0] = fluidmdtmp->fss->attractforceStrength;
+ attrFRDefs[0] = fluidmdtmp->fss->attractforceRadius;
+ velFSDefs[0] = fluidmdtmp->fss->velocityforceStrength;
+ velFRDefs[0] = fluidmdtmp->fss->velocityforceRadius;
+
+ fluidsimInitChannel(scene, &channelAttractforceStrength[o], allchannelSize, timeAtFrame, attrFSIcu,attrFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
+ fluidsimInitChannel(scene, &channelAttractforceRadius[o], allchannelSize, timeAtFrame, attrFRIcu,attrFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
+ fluidsimInitChannel(scene, &channelVelocityforceStrength[o], allchannelSize, timeAtFrame, velFSIcu,velFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
+ fluidsimInitChannel(scene, &channelVelocityforceRadius[o], allchannelSize, timeAtFrame, velFRIcu,velFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
+ }
+
+ fluidsimInitChannel(scene, &channelObjInivel[o], allchannelSize, timeAtFrame, inivelIcu,inivelDefs, fluidmdtmp->fss->ipo, CHANNEL_VEC );
+ fluidsimInitChannel(scene, &channelObjActive[o], allchannelSize, timeAtFrame, activeIcu,activeDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
+
+
+ channelObjCount++;
+
+ }
+ }
+
+ // init trafo matrix
+ Mat4CpyMat4(domainMat, fsDomain->obmat);
+ if(!Mat4Invert(invDomMat, domainMat)) {
+ snprintf(debugStrBuffer,256,"fluidsimBake::error - Invalid obj matrix?\n");
+ elbeemDebugOut(debugStrBuffer);
+ // FIXME add fatal msg
+ FS_FREE_CHANNELS;
+ return;
+ }
+
+
+ // --------------------------------------------------------------------------------------------
+ // start writing / exporting
+ strcpy(targetFile, targetDir);
+ strcat(targetFile, suffixConfig);
+ if(!doExportOnly) { strcat(targetFile,".tmp"); } // dont overwrite/delete original file
+ // make sure these directories exist as well
+ if(outStringsChanged) {
+ BLI_make_existing_file(targetFile);
+ }
+
+ if(!doExportOnly) {
+ ListBase threads;
+
+ // perform simulation with El'Beem api and threads
+ elbeemSimulationSettings fsset;
+ elbeemResetSettings(&fsset);
+ fsset.version = 1;
+
+ // setup global settings
+ for(i=0 ; i<3; i++) fsset.geoStart[i] = bbStart[i];
+ for(i=0 ; i<3; i++) fsset.geoSize[i] = bbSize[i];
+
+ // simulate with 50^3
+ fsset.resolutionxyz = (int)domainSettings->resolutionxyz;
+ fsset.previewresxyz = (int)domainSettings->previewresxyz;
+ // 10cm water domain
+ fsset.realsize = domainSettings->realsize;
+ fsset.viscosity = calcViscosity;
+ // earth gravity
+ fsset.gravity[0] = domainSettings->gravx;
+ fsset.gravity[1] = domainSettings->gravy;
+ fsset.gravity[2] = domainSettings->gravz;
+ // simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz
+ fsset.animStart = domainSettings->animStart;
+ fsset.aniFrameTime = aniFrameTime;
+ fsset.noOfFrames = noFrames; // is otherwise subtracted in parser
+ strcpy(targetFile, targetDir);
+ strcat(targetFile, suffixSurface);
+ // defaults for compressibility and adaptive grids
+ fsset.gstar = domainSettings->gstar;
+ fsset.maxRefine = domainSettings->maxRefine; // check <-> gridlevels
+ fsset.generateParticles = domainSettings->generateParticles;
+ fsset.numTracerParticles = domainSettings->generateTracers;
+ fsset.surfaceSmoothing = domainSettings->surfaceSmoothing;
+ fsset.surfaceSubdivs = domainSettings->surfaceSubdivs;
+ fsset.farFieldSize = domainSettings->farFieldSize;
+ strcpy( fsset.outputPath, targetFile);
+
+ // domain channels
+ fsset.channelSizeFrameTime =
+ fsset.channelSizeViscosity =
+ fsset.channelSizeGravity = allchannelSize;
+ fsset.channelFrameTime = channelDomainTime;
+ fsset.channelViscosity = channelDomainViscosity;
+ fsset.channelGravity = channelDomainGravity;
+
+ fsset.runsimCallback = &runSimulationCallback;
+ fsset.runsimUserData = &fsset;
+
+ if( (domainSettings->typeFlags&OB_FSBND_NOSLIP)) fsset.domainobsType = FLUIDSIM_OBSTACLE_NOSLIP;
+ else if((domainSettings->typeFlags&OB_FSBND_PARTSLIP)) fsset.domainobsType = FLUIDSIM_OBSTACLE_PARTSLIP;
+ else if((domainSettings->typeFlags&OB_FSBND_FREESLIP)) fsset.domainobsType = FLUIDSIM_OBSTACLE_FREESLIP;
+ fsset.domainobsPartslip = domainSettings->partSlipValue;
+ fsset.generateVertexVectors = (domainSettings->domainNovecgen==0);
+
+ // init blender trafo matrix
+ // fprintf(stderr,"elbeemInit - mpTrafo:\n");
+ { int j;
+ for(i=0; i<4; i++) {
+ for(j=0; j<4; j++) {
+ fsset.surfaceTrafo[i*4+j] = invDomMat[j][i];
+ // fprintf(stderr,"elbeemInit - mpTrafo %d %d = %f (%d) \n", i,j, fsset.surfaceTrafo[i*4+j] , (i*4+j) );
+ }
+ } }
+
+ // init solver with settings
+ elbeemInit();
+ elbeemAddDomain(&fsset);
+
+ // init objects
+ channelObjCount = 0;
+ for(base=scene->base.first; base; base= base->next) {
+ FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
+ obit = base->object;
+ //{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG
+ if( fluidmdtmp && // if has to match 3 places! // CHECKMATCH
+ (obit->type==OB_MESH) &&
+ (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) &&
+ (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE))
+ {
+ float *verts=NULL;
+ int *tris=NULL;
+ int numVerts=0, numTris=0;
+ int o = channelObjCount;
+ int deform = (fluidmdtmp->fss->domainNovecgen); // misused value
+ // todo - use blenderInitElbeemMesh
+ int modifierIndex = modifiers_indexInObject(obit, (ModifierData *)fluidmdtmp);
+
+ elbeemMesh fsmesh;
+ elbeemResetMesh( &fsmesh );
+ fsmesh.type = fluidmdtmp->fss->type;
+ // get name of object for debugging solver
+ fsmesh.name = obit->id.name;
+
+ initElbeemMesh(scene, obit, &numVerts, &verts, &numTris, &tris, 0, modifierIndex);
+ fsmesh.numVertices = numVerts;
+ fsmesh.numTriangles = numTris;
+ fsmesh.vertices = verts;
+ fsmesh.triangles = tris;
+
+ fsmesh.channelSizeTranslation =
+ fsmesh.channelSizeRotation =
+ fsmesh.channelSizeScale =
+ fsmesh.channelSizeInitialVel =
+ fsmesh.channelSizeActive = allchannelSize;
+
+ fsmesh.channelTranslation = channelObjMove[o][0];
+ fsmesh.channelRotation = channelObjMove[o][1];
+ fsmesh.channelScale = channelObjMove[o][2];
+ fsmesh.channelActive = channelObjActive[o];
+ if( (fsmesh.type == OB_FLUIDSIM_FLUID) ||
+ (fsmesh.type == OB_FLUIDSIM_INFLOW)) {
+ fsmesh.channelInitialVel = channelObjInivel[o];
+ fsmesh.localInivelCoords = ((fluidmdtmp->fss->typeFlags&OB_FSINFLOW_LOCALCOORD)?1:0);
+ }
+
+ if( (fluidmdtmp->fss->typeFlags&OB_FSBND_NOSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
+ else if((fluidmdtmp->fss->typeFlags&OB_FSBND_PARTSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP;
+ else if((fluidmdtmp->fss->typeFlags&OB_FSBND_FREESLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP;
+ fsmesh.obstaclePartslip = fluidmdtmp->fss->partSlipValue;
+ fsmesh.volumeInitType = fluidmdtmp->fss->volumeInitType;
+ fsmesh.obstacleImpactFactor = fluidmdtmp->fss->surfaceSmoothing; // misused value
+
+ if(fsmesh.type == OB_FLUIDSIM_CONTROL)
+ {
+ // control fluids will get exported as whole
+ deform = 1;
+
+ fsmesh.cpsTimeStart = fluidmdtmp->fss->cpsTimeStart;
+ fsmesh.cpsTimeEnd = fluidmdtmp->fss->cpsTimeEnd;
+ fsmesh.cpsQuality = fluidmdtmp->fss->cpsQuality;
+ fsmesh.obstacleType = (fluidmdtmp->fss->flag & OB_FLUIDSIM_REVERSE);
+
+ fsmesh.channelSizeAttractforceRadius =
+ fsmesh.channelSizeVelocityforceStrength =
+ fsmesh.channelSizeVelocityforceRadius =
+ fsmesh.channelSizeAttractforceStrength = allchannelSize;
+
+ fsmesh.channelAttractforceStrength = channelAttractforceStrength[o];
+ fsmesh.channelAttractforceRadius = channelAttractforceRadius[o];
+ fsmesh.channelVelocityforceStrength = channelVelocityforceStrength[o];
+ fsmesh.channelVelocityforceRadius = channelVelocityforceRadius[o];
+ }
+ else
+ {
+ // set channels to 0
+ fsmesh.channelAttractforceStrength =
+ fsmesh.channelAttractforceRadius =
+ fsmesh.channelVelocityforceStrength =
+ fsmesh.channelVelocityforceRadius = NULL;
+ }
+
+ // animated meshes
+ if(deform) {
+ fsmesh.channelSizeVertices = allchannelSize;
+ fluidsimInitMeshChannel(C, &fsmesh.channelVertices, allchannelSize, obit, numVerts, timeAtFrame, modifierIndex);
+ scene->r.cfra = startFrame;
+ ED_update_for_newframe(C, 1);
+ // remove channels
+ fsmesh.channelTranslation =
+ fsmesh.channelRotation =
+ fsmesh.channelScale = NULL;
+ }
+
+ elbeemAddMesh(&fsmesh);
+
+ if(verts) MEM_freeN(verts);
+ if(tris) MEM_freeN(tris);
+ if(fsmesh.channelVertices) MEM_freeN(fsmesh.channelVertices);
+ channelObjCount++;
+ } // valid mesh
+ } // objects
+ //domainSettings->type = OB_FLUIDSIM_DOMAIN; // enable for bake display again
+ //fsDomain->fluidsimFlag = OB_FLUIDSIM_ENABLE; // disable during bake
+
+ // set to neutral, -1 means user abort, -2 means init error
+ globalBakeState = 0;
+ globalBakeFrame = 0;
+ BLI_init_threads(&threads, fluidsimSimulateThread, 1);
+ BLI_insert_thread(&threads, targetFile);
+
+ {
+ int done = 0;
+ float noFramesf = (float)noFrames;
+ float percentdone = 0.0;
+ int lastRedraw = -1;
+
+ g_break= 0;
+ G.afbreek= 0; /* blender_test_break uses this global */
+
+ start_progress_bar();
+
+ while(done==0) {
+ char busy_mess[80];
+
+ waitcursor(1);
+
+ // lukep we add progress bar as an interim mesure
+ percentdone = globalBakeFrame / noFramesf;
+ sprintf(busy_mess, "baking fluids %d / %d |||", globalBakeFrame, (int) noFramesf);
+ progress_bar(percentdone, busy_mess );
+
+ // longer delay to prevent frequent redrawing
+ PIL_sleep_ms(2000);
+
+ BLI_lock_thread(LOCK_CUSTOM1);
+ if(globalBakeState != 0) done = 1; // 1=ok, <0=error/abort
+ BLI_unlock_thread(LOCK_CUSTOM1);
+
+ if (!G.background) {
+ g_break= blender_test_break();
+
+ if(g_break)
+ {
+ // abort...
+ BLI_lock_thread(LOCK_CUSTOM1);
+
+ if(domainSettings)
+ domainSettings->lastgoodframe = startFrame+globalBakeFrame;
+
+ done = -1;
+ globalBakeFrame = 0;
+ globalBakeState = -1;
+ simAborted = 1;
+ BLI_unlock_thread(LOCK_CUSTOM1);
+ break;
+ }
+ }
+
+ // redraw the 3D for showing progress once in a while...
+ if(lastRedraw!=globalBakeFrame) {
+#if 0
+ ScrArea *sa;
+ scene->r.cfra = startFrame+globalBakeFrame;
+ lastRedraw = globalBakeFrame;
+ ED_update_for_newframe(C, 1);
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->spacetype == SPACE_VIEW3D) { scrarea_do_windraw(sa); }
+ sa= sa->next;
+ }
+ screen_swapbuffers();
+#endif
+ } // redraw
+ }
+ end_progress_bar();
+ }
+ BLI_end_threads(&threads);
+ } // El'Beem API init, thread creation
+ // --------------------------------------------------------------------------------------------
+ else
+ { // write config file to be run with command line simulator
+ pupmenu("Fluidsim Bake Message%t|Config file export not supported.%x0");
+ } // config file export done!
+
+ // --------------------------------------------------------------------------------------------
+ FS_FREE_CHANNELS;
+
+ // go back to "current" blender time
+ waitcursor(0);
+
+ if(globalBakeState >= 0)
+ {
+ if(domainSettings)
+ domainSettings->lastgoodframe = startFrame+globalBakeFrame;
+ }
+
+ scene->r.cfra = origFrame;
+ ED_update_for_newframe(C, 1);
+
+ if(!simAborted) {
+ char fsmessage[512];
+ char elbeemerr[256];
+ strcpy(fsmessage,"Fluidsim Bake Error: ");
+ // check if some error occurred
+ if(globalBakeState==-2) {
+ strcat(fsmessage,"Failed to initialize [Msg: ");
+
+ elbeemGetErrorString(elbeemerr);
+ strcat(fsmessage,elbeemerr);
+
+ strcat(fsmessage,"] |OK%x0");
+ pupmenu(fsmessage);
+ } // init error
+ }
+
+ // elbeemFree();
+}
+
+void fluidsimFreeBake(struct Object *ob)
+{
+ /* not implemented yet */
+}
+
+
+#else /* DISABLE_ELBEEM */
+
+/* compile dummy functions for disabled fluid sim */
+
+FluidsimSettings *fluidsimSettingsNew(struct Object *srcob) {
+ return NULL;
+}
+
+void fluidsimSettingsFree(FluidsimSettings *fss) {
+}
+
+FluidsimSettings* fluidsimSettingsCopy(FluidsimSettings *fss) {
+ return NULL;
+}
+
+/* only compile dummy functions */
+void fluidsimBake(bContext *C, struct Object *ob) {
+}
+
+void fluidsimFreeBake(struct Object *ob) {
+}
+
+#endif /* DISABLE_ELBEEM */
+
diff --git a/source/blender/editors/physics/editparticle.c b/source/blender/editors/physics/editparticle.c
new file mode 100644
index 00000000000..96f3ad2f8df
--- /dev/null
+++ b/source/blender/editors/physics/editparticle.c
@@ -0,0 +1,3924 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by Janne Karhu.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_force.h"
+#include "DNA_object_types.h"
+#include "DNA_vec_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_DerivedMesh.h"
+#include "BKE_depsgraph.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_object.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_particle.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_utildefines.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h"
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+
+#include "PIL_time.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "ED_mesh.h"
+#include "ED_particle.h"
+#include "ED_view3d.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "physics_intern.h"
+
+static void PE_create_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys);
+static void ParticleUndo_clear(ParticleSystem *psys);
+
+#define LOOP_PARTICLES(i, pa) for(i=0, pa=psys->particles; i<totpart; i++, pa++)
+#define LOOP_KEYS(k, key) if(psys->edit)for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++)
+
+/**************************** utilities *******************************/
+
+static int PE_poll(bContext *C)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+ ParticleSystem *psys;
+
+ if(!scene || !ob)
+ return 0;
+
+ psys= PE_get_current(scene, ob);
+
+ return (psys && psys->edit && (G.f & G_PARTICLEEDIT));
+}
+
+static int PE_poll_3dview(bContext *C)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+ ParticleSystem *psys;
+
+ if(!scene || !ob || !CTX_wm_region_view3d(C))
+ return 0;
+
+ psys= PE_get_current(scene, ob);
+
+ return (psys && psys->edit && (G.f & G_PARTICLEEDIT));
+}
+
+static void PE_free_particle_edit(ParticleSystem *psys)
+{
+ ParticleEdit *edit= psys->edit;
+ int i, totpart= psys->totpart;
+
+ if(edit==0) return;
+
+ ParticleUndo_clear(psys);
+
+ if(edit->keys) {
+ for(i=0; i<totpart; i++) {
+ if(edit->keys[i])
+ MEM_freeN(edit->keys[i]);
+ }
+
+ MEM_freeN(edit->keys);
+ }
+
+ if(edit->mirror_cache)
+ MEM_freeN(edit->mirror_cache);
+
+ if(edit->emitter_cosnos) {
+ MEM_freeN(edit->emitter_cosnos);
+ edit->emitter_cosnos= 0;
+ }
+
+ if(edit->emitter_field) {
+ BLI_kdtree_free(edit->emitter_field);
+ edit->emitter_field= 0;
+ }
+
+ MEM_freeN(edit);
+
+ psys->edit= NULL;
+ psys->free_edit= NULL;
+}
+
+/************************************************/
+/* Edit Mode Helpers */
+/************************************************/
+
+int PE_can_edit(ParticleSystem *psys)
+{
+ return (psys && psys->edit && (G.f & G_PARTICLEEDIT));
+}
+
+ParticleEditSettings *PE_settings(Scene *scene)
+{
+ return &scene->toolsettings->particle;
+}
+
+/* always gets atleast the first particlesystem even if PSYS_CURRENT flag is not set */
+ParticleSystem *PE_get_current(Scene *scene, Object *ob)
+{
+ ParticleSystem *psys;
+
+ if(ob==NULL)
+ return NULL;
+
+ psys= ob->particlesystem.first;
+ while(psys) {
+ if(psys->flag & PSYS_CURRENT)
+ break;
+ psys=psys->next;
+ }
+
+ if(psys==NULL && ob->particlesystem.first) {
+ psys=ob->particlesystem.first;
+ psys->flag |= PSYS_CURRENT;
+ }
+
+ /* this happens when Blender is started with particle
+ * edit mode enabled XXX there's a draw error then? */
+ if(psys && psys_check_enabled(ob, psys) && (ob == OBACT) && (G.f & G_PARTICLEEDIT))
+ if(psys->part->type == PART_HAIR && psys->flag & PSYS_EDITED)
+ if(psys->edit == NULL)
+ PE_create_particle_edit(scene, ob, psys);
+
+ return psys;
+}
+
+/* returns -1 if no system has PSYS_CURRENT flag */
+short PE_get_current_num(Object *ob)
+{
+ short num=0;
+ ParticleSystem *psys= ob->particlesystem.first;
+
+ while(psys) {
+ if(psys->flag & PSYS_CURRENT)
+ return num;
+ num++;
+ psys=psys->next;
+ }
+
+ return -1;
+}
+
+void PE_hide_keys_time(Scene *scene, ParticleSystem *psys, float cfra)
+{
+ ParticleData *pa;
+ ParticleEditKey *key;
+ ParticleEditSettings *pset=PE_settings(scene);
+ int i, k, totpart= psys->totpart;
+
+ if(pset->draw_timed && scene->selectmode==SCE_SELECT_POINT) {
+ LOOP_PARTICLES(i, pa) {
+ LOOP_KEYS(k, key) {
+ if(fabs(cfra-*key->time) < pset->draw_timed)
+ key->flag &= ~PEK_HIDE;
+ else {
+ key->flag |= PEK_HIDE;
+ key->flag &= ~PEK_SELECT;
+ }
+ }
+ }
+ }
+ else {
+ LOOP_PARTICLES(i, pa) {
+ LOOP_KEYS(k, key) {
+ key->flag &= ~PEK_HIDE;
+ }
+ }
+ }
+}
+
+/****************** common struct passed to callbacks ******************/
+
+typedef struct PEData {
+ ViewContext vc;
+ bglMats mats;
+
+ Scene *scene;
+ Object *ob;
+ DerivedMesh *dm;
+ ParticleSystem *psys;
+
+ short *mval;
+ rcti *rect;
+ float rad;
+ float dist;
+ float dval;
+ int select;
+
+ float *dvec;
+ float combfac;
+ float pufffac;
+ float cutfac;
+ float smoothfac;
+ float weightfac;
+ float growfac;
+
+ int invert;
+ int tot;
+ float vec[3];
+} PEData;
+
+static void PE_set_data(bContext *C, PEData *data)
+{
+ memset(data, 0, sizeof(*data));
+
+ data->scene= CTX_data_scene(C);
+ data->ob= CTX_data_active_object(C);
+ data->psys= PE_get_current(data->scene, data->ob);
+}
+
+static void PE_set_view3d_data(bContext *C, PEData *data)
+{
+ PE_set_data(C, data);
+
+ view3d_set_viewcontext(C, &data->vc);
+ view3d_get_transformation(&data->vc, data->ob, &data->mats);
+
+ if((data->vc.v3d->drawtype>OB_WIRE) && (data->vc.v3d->flag & V3D_ZBUF_SELECT))
+ view3d_validate_backbuf(&data->vc);
+}
+
+/*************************** selection utilities *******************************/
+
+static int key_test_depth(PEData *data, float co[3])
+{
+ View3D *v3d= data->vc.v3d;
+ RegionView3D *rv3d= data->vc.rv3d;
+ double ux, uy, uz;
+ float depth;
+ short wco[3], x,y;
+
+ /* nothing to do */
+ if((v3d->drawtype<=OB_WIRE) || (v3d->flag & V3D_ZBUF_SELECT)==0)
+ return 1;
+
+ project_short(data->vc.ar, co, wco);
+
+ if(wco[0] == IS_CLIPPED)
+ return 0;
+
+ gluProject(co[0],co[1],co[2], data->mats.modelview, data->mats.projection,
+ (GLint *)data->mats.viewport, &ux, &uy, &uz);
+
+ x=wco[0];
+ y=wco[1];
+
+ // XXX verify ..
+
+ if(rv3d->depths && x<rv3d->depths->w && y<rv3d->depths->h) {
+ /* the 0.0001 is an experimental threshold to make selecting keys right next to a surface work better */
+ if((float)uz - 0.0001 > rv3d->depths->depths[y*rv3d->depths->w+x])
+ return 0;
+ else
+ return 1;
+ }
+ else {
+ x+= (short)data->vc.ar->winrct.xmin;
+ y+= (short)data->vc.ar->winrct.ymin;
+
+ glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
+
+ if((float)uz - 0.0001 > depth)
+ return 0;
+ else
+ return 1;
+ }
+}
+
+static int key_inside_circle(PEData *data, float rad, float co[3], float *distance)
+{
+ float dx, dy, dist;
+ short sco[2];
+
+ project_short(data->vc.ar, co, sco);
+
+ if(sco[0] == IS_CLIPPED)
+ return 0;
+
+ dx= data->mval[0] - sco[0];
+ dy= data->mval[1] - sco[1];
+ dist= sqrt(dx*dx + dy*dy);
+
+ if(dist > rad)
+ return 0;
+
+ if(key_test_depth(data, co)) {
+ if(distance)
+ *distance=dist;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static int key_inside_rect(PEData *data, float co[3])
+{
+ short sco[2];
+
+ project_short(data->vc.ar, co,sco);
+
+ if(sco[0] == IS_CLIPPED)
+ return 0;
+
+ if(sco[0] > data->rect->xmin && sco[0] < data->rect->xmax &&
+ sco[1] > data->rect->ymin && sco[1] < data->rect->ymax)
+ return key_test_depth(data, co);
+
+ return 0;
+}
+
+static int key_inside_test(PEData *data, float co[3])
+{
+ if(data->mval)
+ return key_inside_circle(data, data->rad, co, NULL);
+ else
+ return key_inside_rect(data, co);
+}
+
+static int particle_is_selected(ParticleSystem *psys, ParticleData *pa)
+{
+ ParticleEditKey *key;
+ int sel, i, k;
+
+ if(pa->flag & PARS_HIDE)
+ return 0;
+
+ sel= 0;
+ i= pa - psys->particles;
+
+ LOOP_KEYS(k, key)
+ if(key->flag & PEK_SELECT)
+ return 1;
+
+ return 0;
+}
+
+/*************************** iterators *******************************/
+
+typedef void (*ForParticleFunc)(PEData *data, int pa_index);
+typedef void (*ForKeyFunc)(PEData *data, int pa_index, int key_index);
+typedef void (*ForKeyMatFunc)(PEData *data, float mat[][4], float imat[][4], int pa_index, int key_index);
+
+static void for_mouse_hit_keys(PEData *data, ForKeyFunc func, int nearest)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleEdit *edit= psys->edit;
+ ParticleData *pa;
+ ParticleEditKey *key;
+ int i, k, totpart, nearest_pa, nearest_key;
+ float dist= data->rad;
+
+ /* in path select mode we have no keys */
+ if(data->scene->selectmode==SCE_SELECT_PATH)
+ return;
+
+ totpart= psys->totpart;
+ nearest_pa= -1;
+ nearest_key= -1;
+
+ LOOP_PARTICLES(i, pa) {
+ if(pa->flag & PARS_HIDE) continue;
+
+ if(data->scene->selectmode == SCE_SELECT_END) {
+ /* only do end keys */
+ key= edit->keys[i] + pa->totkey-1;
+
+ if(nearest) {
+ if(key_inside_circle(data, dist, key->world_co, &dist)) {
+ nearest_pa= i;
+ nearest_key= pa->totkey-1;
+ }
+ }
+ else if(key_inside_test(data, key->world_co))
+ func(data, i, pa->totkey-1);
+ }
+ else {
+ /* do all keys */
+ key= edit->keys[i];
+
+ LOOP_KEYS(k, key) {
+ if(key->flag & PEK_HIDE) continue;
+
+ if(nearest) {
+ if(key_inside_circle(data, dist, key->world_co, &dist)) {
+ nearest_pa= i;
+ nearest_key= k;
+ }
+ }
+ else if(key_inside_test(data, key->world_co))
+ func(data, i, k);
+ }
+ }
+ }
+
+ /* do nearest only */
+ if(nearest && nearest_pa > -1)
+ func(data, nearest_pa, nearest_key);
+}
+
+static void foreach_mouse_hit_particle(PEData *data, ForParticleFunc func, int selected)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleData *pa;
+ ParticleEditKey *key;
+ int i, k, totpart;
+
+ totpart= psys->totpart;
+
+ /* all is selected in path mode */
+ if(data->scene->selectmode==SCE_SELECT_PATH)
+ selected=0;
+
+ LOOP_PARTICLES(i, pa) {
+ if(pa->flag & PARS_HIDE) continue;
+
+ if(data->scene->selectmode==SCE_SELECT_END) {
+ /* only do end keys */
+ key= psys->edit->keys[i] + pa->totkey-1;
+
+ if(selected==0 || key->flag & PEK_SELECT)
+ if(key_inside_circle(data, data->rad, key->world_co, &data->dist))
+ func(data, i);
+ }
+ else {
+ /* do all keys */
+ LOOP_KEYS(k, key) {
+ if(key->flag & PEK_HIDE) continue;
+
+ if(selected==0 || key->flag & PEK_SELECT) {
+ if(key_inside_circle(data, data->rad, key->world_co, &data->dist)) {
+ func(data, i);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleData *pa;
+ ParticleEditKey *key;
+ ParticleSystemModifierData *psmd=0;
+ int i, k, totpart;
+ float mat[4][4], imat[4][4];
+
+ psmd= psys_get_modifier(data->ob,psys);
+ totpart= psys->totpart;
+
+ /* all is selected in path mode */
+ if(data->scene->selectmode==SCE_SELECT_PATH)
+ selected= 0;
+
+ Mat4One(imat);
+ Mat4One(mat);
+
+ LOOP_PARTICLES(i, pa) {
+ if(pa->flag & PARS_HIDE) continue;
+
+ psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, pa, mat);
+ Mat4Invert(imat,mat);
+
+ if(data->scene->selectmode==SCE_SELECT_END) {
+ /* only do end keys */
+ key= psys->edit->keys[i] + pa->totkey-1;
+
+ if(selected==0 || key->flag & PEK_SELECT)
+ if(key_inside_circle(data, data->rad, key->world_co, &data->dist))
+ func(data, mat, imat, i, pa->totkey-1);
+ }
+ else {
+ /* do all keys */
+ LOOP_KEYS(k, key) {
+ if(key->flag&PEK_HIDE) continue;
+
+ if(selected==0 || key->flag & PEK_SELECT)
+ if(key_inside_circle(data, data->rad, key->world_co, &data->dist))
+ func(data, mat, imat, i, k);
+ }
+ }
+ }
+}
+
+static void foreach_selected_particle(PEData *data, ForParticleFunc func)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleData *pa;
+ int i, totpart;
+
+ totpart= psys->totpart;
+
+ LOOP_PARTICLES(i, pa)
+ if(particle_is_selected(psys, pa))
+ func(data, i);
+}
+
+static void foreach_selected_key(PEData *data, ForKeyFunc func)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleData *pa;
+ ParticleEditKey *key;
+ int i, k, totpart;
+
+ totpart= psys->totpart;
+
+ LOOP_PARTICLES(i, pa) {
+ if(pa->flag & PARS_HIDE) continue;
+
+ key= psys->edit->keys[i];
+
+ LOOP_KEYS(k, key)
+ if(key->flag & PEK_SELECT)
+ func(data, i, k);
+ }
+}
+
+void PE_foreach_particle(PEData *data, ForParticleFunc func)
+{
+ ParticleSystem *psys= data->psys;
+ int i, totpart;
+
+ totpart= psys->totpart;
+
+ for(i=0; i<totpart; i++)
+ func(data, i);
+}
+
+static int count_selected_keys(Scene *scene, ParticleSystem *psys)
+{
+ ParticleData *pa;
+ ParticleEditKey *key;
+ int i, k, totpart, sel= 0;
+
+ totpart= psys->totpart;
+
+ LOOP_PARTICLES(i, pa) {
+ if(pa->flag & PARS_HIDE) continue;
+
+ key= psys->edit->keys[i];
+
+ if(scene->selectmode==SCE_SELECT_POINT) {
+ for(k=0; k<pa->totkey; k++,key++)
+ if(key->flag & PEK_SELECT)
+ sel++;
+ }
+ else if(scene->selectmode==SCE_SELECT_END) {
+ key += pa->totkey-1;
+
+ if(key->flag & PEK_SELECT)
+ sel++;
+ }
+ }
+
+ return sel;
+}
+
+/************************************************/
+/* Particle Edit Mirroring */
+/************************************************/
+
+static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
+{
+ ParticleEdit *edit;
+ ParticleData *pa;
+ ParticleSystemModifierData *psmd;
+ KDTree *tree;
+ KDTreeNearest nearest;
+ float mat[4][4], co[3];
+ int i, index, totpart;
+
+ edit= psys->edit;
+ psmd= psys_get_modifier(ob, psys);
+ totpart= psys->totpart;
+
+ tree= BLI_kdtree_new(totpart);
+
+ /* insert particles into kd tree */
+ LOOP_PARTICLES(i, pa) {
+ psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat);
+ VECCOPY(co, pa->hair[0].co);
+ Mat4MulVecfl(mat, co);
+ BLI_kdtree_insert(tree, i, co, NULL);
+ }
+
+ BLI_kdtree_balance(tree);
+
+ /* lookup particles and set in mirror cache */
+ if(!edit->mirror_cache)
+ edit->mirror_cache= MEM_callocN(sizeof(int)*totpart, "PE mirror cache");
+
+ LOOP_PARTICLES(i, pa) {
+ psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat);
+ VECCOPY(co, pa->hair[0].co);
+ Mat4MulVecfl(mat, co);
+ co[0]= -co[0];
+
+ index= BLI_kdtree_find_nearest(tree, co, NULL, &nearest);
+
+ /* this needs a custom threshold still, duplicated for editmode mirror */
+ if(index != -1 && index != i && (nearest.dist <= 0.0002f))
+ edit->mirror_cache[i]= index;
+ else
+ edit->mirror_cache[i]= -1;
+ }
+
+ /* make sure mirrors are in two directions */
+ LOOP_PARTICLES(i, pa) {
+ if(edit->mirror_cache[i]) {
+ index= edit->mirror_cache[i];
+ if(edit->mirror_cache[index] != i)
+ edit->mirror_cache[i]= -1;
+ }
+ }
+
+ BLI_kdtree_free(tree);
+}
+
+static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys, ParticleData *pa, ParticleData *mpa)
+{
+ HairKey *hkey, *mhkey;
+ ParticleEditKey *key, *mkey;
+ ParticleEdit *edit;
+ float mat[4][4], mmat[4][4], immat[4][4];
+ int i, mi, k;
+
+ edit= psys->edit;
+ i= pa - psys->particles;
+
+ /* find mirrored particle if needed */
+ if(!mpa) {
+ if(!edit->mirror_cache)
+ PE_update_mirror_cache(ob, psys);
+
+ mi= edit->mirror_cache[i];
+ if(mi == -1)
+ return;
+ mpa= psys->particles + mi;
+ }
+ else
+ mi= mpa - psys->particles;
+
+ /* make sure they have the same amount of keys */
+ if(pa->totkey != mpa->totkey) {
+ if(mpa->hair) MEM_freeN(mpa->hair);
+ if(edit->keys[mi]) MEM_freeN(edit->keys[mi]);
+
+ mpa->hair= MEM_dupallocN(pa->hair);
+ edit->keys[mi]= MEM_dupallocN(edit->keys[i]);
+ mpa->totkey= pa->totkey;
+
+ mhkey= mpa->hair;
+ mkey= edit->keys[mi];
+ for(k=0; k<mpa->totkey; k++, mkey++, mhkey++) {
+ mkey->co= mhkey->co;
+ mkey->time= &mhkey->time;
+ mkey->flag &= PEK_SELECT;
+ }
+ }
+
+ /* mirror positions and tags */
+ psys_mat_hair_to_orco(ob, dm, psys->part->from, pa, mat);
+ psys_mat_hair_to_orco(ob, dm, psys->part->from, mpa, mmat);
+ Mat4Invert(immat, mmat);
+
+ hkey=pa->hair;
+ mhkey=mpa->hair;
+ key= edit->keys[i];
+ mkey= edit->keys[mi];
+ for(k=0; k<pa->totkey; k++, hkey++, mhkey++, key++, mkey++) {
+ VECCOPY(mhkey->co, hkey->co);
+ Mat4MulVecfl(mat, mhkey->co);
+ mhkey->co[0]= -mhkey->co[0];
+ Mat4MulVecfl(immat, mhkey->co);
+
+ if(key->flag & PEK_TAG)
+ mkey->flag |= PEK_TAG;
+ }
+
+ if(pa->flag & PARS_TAG)
+ mpa->flag |= PARS_TAG;
+ if(pa->flag & PARS_EDIT_RECALC)
+ mpa->flag |= PARS_EDIT_RECALC;
+}
+
+static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
+{
+ ParticleEdit *edit;
+ ParticleData *pa;
+ ParticleSystemModifierData *psmd;
+ int i, totpart;
+
+ edit= psys->edit;
+ psmd= psys_get_modifier(ob, psys);
+ totpart= psys->totpart;
+
+ /* we delay settings the PARS_EDIT_RECALC for mirrored particles
+ * to avoid doing mirror twice */
+ LOOP_PARTICLES(i, pa) {
+ if(pa->flag & PARS_EDIT_RECALC) {
+ PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
+
+ if(edit->mirror_cache[i] != -1)
+ psys->particles[edit->mirror_cache[i]].flag &= ~PARS_EDIT_RECALC;
+ }
+ }
+
+ LOOP_PARTICLES(i, pa)
+ if(pa->flag & PARS_EDIT_RECALC)
+ if(edit->mirror_cache[i] != -1)
+ psys->particles[edit->mirror_cache[i]].flag |= PARS_EDIT_RECALC;
+
+ edit->totkeys= psys_count_keys(psys);
+}
+
+/************************************************/
+/* Edit Calculation */
+/************************************************/
+/* tries to stop edited particles from going through the emitter's surface */
+static void pe_deflect_emitter(Scene *scene, Object *ob, ParticleSystem *psys)
+{
+ ParticleEdit *edit;
+ ParticleData *pa;
+ ParticleEditKey *key;
+ ParticleEditSettings *pset= PE_settings(scene);
+ ParticleSystemModifierData *psmd= psys_get_modifier(ob,psys);
+ int i, k, totpart,index;
+ float *vec, *nor, dvec[3], dot, dist_1st;
+ float hairimat[4][4], hairmat[4][4];
+
+ if(psys==0)
+ return;
+
+ if((pset->flag & PE_DEFLECT_EMITTER)==0)
+ return;
+
+ edit= psys->edit;
+ totpart= psys->totpart;
+
+ LOOP_PARTICLES(i, pa) {
+ if(!(pa->flag & PARS_EDIT_RECALC))
+ continue;
+
+ psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, hairmat);
+
+ LOOP_KEYS(k, key) {
+ Mat4MulVecfl(hairmat, key->co);
+ }
+ //}
+
+ //LOOP_PARTICLES(i, pa) {
+ key=psys->edit->keys[i]+1;
+
+ dist_1st=VecLenf((key-1)->co,key->co);
+ dist_1st*=0.75f*pset->emitterdist;
+
+ for(k=1; k<pa->totkey; k++, key++) {
+ index= BLI_kdtree_find_nearest(edit->emitter_field,key->co,NULL,NULL);
+
+ vec=edit->emitter_cosnos +index*6;
+ nor=vec+3;
+
+ VecSubf(dvec, key->co, vec);
+
+ dot=Inpf(dvec,nor);
+ VECCOPY(dvec,nor);
+
+ if(dot>0.0f) {
+ if(dot<dist_1st) {
+ Normalize(dvec);
+ VecMulf(dvec,dist_1st-dot);
+ VecAddf(key->co,key->co,dvec);
+ }
+ }
+ else {
+ Normalize(dvec);
+ VecMulf(dvec,dist_1st-dot);
+ VecAddf(key->co,key->co,dvec);
+ }
+ if(k==1)
+ dist_1st*=1.3333f;
+ }
+ //}
+
+ //LOOP_PARTICLES(i, pa) {
+
+ Mat4Invert(hairimat,hairmat);
+
+ LOOP_KEYS(k, key) {
+ Mat4MulVecfl(hairimat, key->co);
+ }
+ }
+}
+/* force set distances between neighbouring keys */
+void PE_apply_lengths(Scene *scene, ParticleSystem *psys)
+{
+ ParticleEdit *edit;
+ ParticleData *pa;
+ ParticleEditKey *key;
+ ParticleEditSettings *pset=PE_settings(scene);
+ int i, k, totpart;
+ float dv1[3];
+
+ if(psys==0)
+ return;
+
+ if((pset->flag & PE_KEEP_LENGTHS)==0)
+ return;
+
+ edit= psys->edit;
+ totpart= psys->totpart;
+
+ LOOP_PARTICLES(i, pa) {
+ if(!(pa->flag & PARS_EDIT_RECALC))
+ continue;
+
+ for(k=1, key=edit->keys[i] + 1; k<pa->totkey; k++, key++) {
+ VecSubf(dv1, key->co, (key - 1)->co);
+ Normalize(dv1);
+ VecMulf(dv1, (key - 1)->length);
+ VecAddf(key->co, (key - 1)->co, dv1);
+ }
+ }
+}
+/* try to find a nice solution to keep distances between neighbouring keys */
+static void pe_iterate_lengths(Scene *scene, ParticleSystem *psys)
+{
+ ParticleEdit *edit;
+ ParticleData *pa;
+ ParticleEditKey *key;
+ ParticleEditSettings *pset=PE_settings(scene);
+ int i, j, k, totpart;
+ float tlen;
+ float dv0[3]= {0.0f, 0.0f, 0.0f};
+ float dv1[3]= {0.0f, 0.0f, 0.0f};
+ float dv2[3]= {0.0f, 0.0f, 0.0f};
+
+ if(psys==0)
+ return;
+
+ if((pset->flag & PE_KEEP_LENGTHS)==0)
+ return;
+
+ edit= psys->edit;
+ totpart= psys->totpart;
+
+ LOOP_PARTICLES(i, pa) {
+ if(!(pa->flag & PARS_EDIT_RECALC))
+ continue;
+
+ for(j=1; j<pa->totkey; j++) {
+ float mul= 1.0f / (float)pa->totkey;
+
+ if(pset->flag & PE_LOCK_FIRST) {
+ key= edit->keys[i] + 1;
+ k= 1;
+ dv1[0]= dv1[1]= dv1[2]= 0.0;
+ }
+ else {
+ key= edit->keys[i];
+ k= 0;
+ dv0[0]= dv0[1]= dv0[2]= 0.0;
+ }
+
+ for(; k<pa->totkey; k++, key++) {
+ if(k) {
+ VecSubf(dv0, (key - 1)->co, key->co);
+ tlen= Normalize(dv0);
+ VecMulf(dv0, (mul * (tlen - (key - 1)->length)));
+ }
+
+ if(k < pa->totkey - 1) {
+ VecSubf(dv2, (key + 1)->co, key->co);
+ tlen= Normalize(dv2);
+ VecMulf(dv2, mul * (tlen - key->length));
+ }
+
+ if(k) {
+ VecAddf((key-1)->co,(key-1)->co,dv1);
+ }
+
+ VECADD(dv1,dv0,dv2);
+ }
+ }
+ }
+}
+/* set current distances to be kept between neighbouting keys */
+static void recalc_lengths(ParticleSystem *psys)
+{
+ ParticleData *pa;
+ ParticleEditKey *key;
+ int i, k, totpart;
+
+ if(psys==0)
+ return;
+
+ totpart= psys->totpart;
+
+ LOOP_PARTICLES(i, pa) {
+ key= psys->edit->keys[i];
+ for(k=0; k<pa->totkey-1; k++, key++) {
+ key->length= VecLenf(key->co, (key + 1)->co);
+ }
+ }
+}
+
+/* calculate a tree for finding nearest emitter's vertice */
+static void recalc_emitter_field(Object *ob, ParticleSystem *psys)
+{
+ DerivedMesh *dm=psys_get_modifier(ob,psys)->dm;
+ ParticleEdit *edit= psys->edit;
+ MFace *mface;
+ MVert *mvert;
+ float *vec, *nor;
+ int i, totface, totvert;
+
+ if(edit->emitter_cosnos)
+ MEM_freeN(edit->emitter_cosnos);
+
+ BLI_kdtree_free(edit->emitter_field);
+
+ totface=dm->getNumFaces(dm);
+ totvert=dm->getNumVerts(dm);
+
+ edit->emitter_cosnos=MEM_callocN(totface*6*sizeof(float),"emitter cosnos");
+
+ edit->emitter_field= BLI_kdtree_new(totface);
+
+ vec=edit->emitter_cosnos;
+ nor=vec+3;
+
+ mvert=dm->getVertDataArray(dm,CD_MVERT);
+ for(i=0; i<totface; i++, vec+=6, nor+=6) {
+ mface=dm->getFaceData(dm,i,CD_MFACE);
+
+ mvert=dm->getVertData(dm,mface->v1,CD_MVERT);
+ VECCOPY(vec,mvert->co);
+ VECCOPY(nor,mvert->no);
+
+ mvert=dm->getVertData(dm,mface->v2,CD_MVERT);
+ VECADD(vec,vec,mvert->co);
+ VECADD(nor,nor,mvert->no);
+
+ mvert=dm->getVertData(dm,mface->v3,CD_MVERT);
+ VECADD(vec,vec,mvert->co);
+ VECADD(nor,nor,mvert->no);
+
+ if(mface->v4) {
+ mvert=dm->getVertData(dm,mface->v4,CD_MVERT);
+ VECADD(vec,vec,mvert->co);
+ VECADD(nor,nor,mvert->no);
+
+ VecMulf(vec,0.25);
+ }
+ else
+ VecMulf(vec,0.3333f);
+
+ Normalize(nor);
+
+ BLI_kdtree_insert(edit->emitter_field, i, vec, NULL);
+ }
+
+ BLI_kdtree_balance(edit->emitter_field);
+}
+
+static void PE_update_selection(Scene *scene, Object *ob, int useflag)
+{
+ ParticleSystem *psys= PE_get_current(scene, ob);
+ ParticleEdit *edit= psys->edit;
+ ParticleEditSettings *pset= PE_settings(scene);
+ ParticleSettings *part= psys->part;
+ ParticleData *pa;
+ HairKey *hkey;
+ ParticleEditKey *key;
+ float cfra= CFRA;
+ int i, k, totpart;
+
+ totpart= psys->totpart;
+
+ /* flag all particles to be updated if not using flag */
+ if(!useflag)
+ LOOP_PARTICLES(i, pa)
+ pa->flag |= PARS_EDIT_RECALC;
+
+ /* flush edit key flag to hair key flag to preserve selection
+ * on save */
+ LOOP_PARTICLES(i, pa) {
+ key= edit->keys[i];
+
+ for(k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, key++)
+ hkey->editflag= key->flag;
+ }
+
+ psys_cache_paths(scene, ob, psys, CFRA, 1);
+
+ if(part->childtype && (pset->flag & PE_SHOW_CHILD))
+ psys_cache_child_paths(scene, ob, psys, cfra, 1);
+
+ /* disable update flag */
+ LOOP_PARTICLES(i, pa)
+ pa->flag &= ~PARS_EDIT_RECALC;
+}
+
+void PE_update_object(Scene *scene, Object *ob, int useflag)
+{
+ ParticleSystem *psys= PE_get_current(scene, ob);
+ ParticleEditSettings *pset= PE_settings(scene);
+ ParticleSettings *part= psys->part;
+ ParticleData *pa;
+ float cfra= CFRA;
+ int i, totpart= psys->totpart;
+
+ /* flag all particles to be updated if not using flag */
+ if(!useflag)
+ LOOP_PARTICLES(i, pa)
+ pa->flag |= PARS_EDIT_RECALC;
+
+ /* do post process on particle edit keys */
+ pe_iterate_lengths(scene, psys);
+ pe_deflect_emitter(scene, ob, psys);
+ PE_apply_lengths(scene, psys);
+ if(pset->flag & PE_X_MIRROR)
+ PE_apply_mirror(ob,psys);
+ psys_update_world_cos(ob,psys);
+ PE_hide_keys_time(scene, psys, cfra);
+
+ /* regenerate path caches */
+ psys_cache_paths(scene, ob, psys, cfra, 1);
+
+ if(part->childtype && (pset->flag & PE_SHOW_CHILD))
+ psys_cache_child_paths(scene, ob, psys, cfra, 1);
+
+ /* disable update flag */
+ LOOP_PARTICLES(i, pa)
+ pa->flag &= ~PARS_EDIT_RECALC;
+}
+
+/************************************************/
+/* Edit Selections */
+/************************************************/
+
+/*-----selection callbacks-----*/
+
+static void select_key(PEData *data, int pa_index, int key_index)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleData *pa= psys->particles + pa_index;
+ ParticleEditKey *key= psys->edit->keys[pa_index] + key_index;
+
+ if(data->select)
+ key->flag |= PEK_SELECT;
+ else
+ key->flag &= ~PEK_SELECT;
+
+ pa->flag |= PARS_EDIT_RECALC;
+}
+
+static void select_keys(PEData *data, int pa_index, int key_index)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleData *pa= psys->particles + pa_index;
+ ParticleEditKey *key= psys->edit->keys[pa_index];
+ int k;
+
+ for(k=0; k<pa->totkey; k++,key++) {
+ if(data->select)
+ key->flag |= PEK_SELECT;
+ else
+ key->flag &= ~PEK_SELECT;
+ }
+
+ pa->flag |= PARS_EDIT_RECALC;
+}
+
+static void toggle_key_select(PEData *data, int pa_index, int key_index)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleData *pa= psys->particles + pa_index;
+
+ if(psys->edit->keys[pa_index][key_index].flag&PEK_SELECT)
+ psys->edit->keys[pa_index][key_index].flag &= ~PEK_SELECT;
+ else
+ psys->edit->keys[pa_index][key_index].flag |= PEK_SELECT;
+
+ pa->flag |= PARS_EDIT_RECALC;
+}
+
+/************************ de select all operator ************************/
+
+static int de_select_all_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+ ParticleSystem *psys= PE_get_current(scene, ob);
+ ParticleEdit *edit= 0;
+ ParticleData *pa;
+ ParticleEditKey *key;
+ int i, k, totpart, sel= 0;
+
+ edit= psys->edit;
+ totpart= psys->totpart;
+
+ LOOP_PARTICLES(i, pa) {
+ if(pa->flag & PARS_HIDE) continue;
+ LOOP_KEYS(k, key) {
+ if(key->flag & PEK_SELECT) {
+ sel= 1;
+ key->flag &= ~PEK_SELECT;
+ pa->flag |= PARS_EDIT_RECALC;
+ }
+ }
+ }
+
+ if(sel==0) {
+ LOOP_PARTICLES(i, pa) {
+ if(pa->flag & PARS_HIDE) continue;
+ LOOP_KEYS(k, key) {
+ if(!(key->flag & PEK_SELECT)) {
+ key->flag |= PEK_SELECT;
+ pa->flag |= PARS_EDIT_RECALC;
+ }
+ }
+ }
+ }
+
+ PE_update_selection(scene, ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_select_all_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select or Deselect All";
+ ot->idname= "PARTICLE_OT_select_all_toggle";
+
+ /* api callbacks */
+ ot->exec= de_select_all_exec;
+ ot->poll= PE_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/************************ pick select operator ************************/
+
+int PE_mouse_particles(bContext *C, short *mval, int extend)
+{
+ PEData data;
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+ ParticleSystem *psys= PE_get_current(scene, ob);
+ ParticleEdit *edit= 0;
+ ParticleData *pa;
+ ParticleEditKey *key;
+ int i, k, totpart;
+
+ if(!PE_can_edit(psys))
+ return OPERATOR_CANCELLED;
+
+ edit= psys->edit;
+ totpart= psys->totpart;
+
+ if(!extend) {
+ LOOP_PARTICLES(i, pa) {
+ if(pa->flag & PARS_HIDE) continue;
+ LOOP_KEYS(k, key) {
+ if(key->flag & PEK_SELECT) {
+ key->flag &= ~PEK_SELECT;
+ pa->flag |= PARS_EDIT_RECALC;
+ }
+ }
+ }
+ }
+
+ PE_set_view3d_data(C, &data);
+ data.mval= mval;
+ data.rad= 75.0f;
+
+ for_mouse_hit_keys(&data, toggle_key_select, 1); /* nearest only */
+
+ PE_update_selection(scene, ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob);
+
+ return OPERATOR_FINISHED;
+}
+
+/************************ select first operator ************************/
+
+static void select_root(PEData *data, int pa_index)
+{
+ ParticleSystem *psys= data->psys;
+
+ psys->edit->keys[pa_index]->flag |= PEK_SELECT;
+}
+
+static int select_first_exec(bContext *C, wmOperator *op)
+{
+ PEData data;
+
+ PE_set_data(C, &data);
+ PE_foreach_particle(&data, select_root);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_select_first(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select First";
+ ot->idname= "PARTICLE_OT_select_first";
+
+ /* api callbacks */
+ ot->exec= select_first_exec;
+ ot->poll= PE_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/************************ select last operator ************************/
+
+static void select_tip(PEData *data, int pa_index)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleData *pa= psys->particles + pa_index;
+ ParticleEditKey *key= psys->edit->keys[pa_index] + pa->totkey-1;
+
+ key->flag |= PEK_SELECT;
+}
+
+static int select_last_exec(bContext *C, wmOperator *op)
+{
+ PEData data;
+
+ PE_set_data(C, &data);
+ PE_foreach_particle(&data, select_tip);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_select_last(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Last";
+ ot->idname= "PARTICLE_OT_select_last";
+
+ /* api callbacks */
+ ot->exec= select_last_exec;
+ ot->poll= PE_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/************************ select linked operator ************************/
+
+static int select_linked_exec(bContext *C, wmOperator *op)
+{
+ PEData data;
+ short mval[2];
+ int location[2];
+
+ RNA_int_get_array(op->ptr, "location", location);
+ mval[0]= location[0];
+ mval[1]= location[1];
+
+ view3d_operator_needs_opengl(C);
+
+ PE_set_view3d_data(C, &data);
+ data.mval= mval;
+ data.rad=75.0f;
+ data.select= !RNA_boolean_get(op->ptr, "deselect");
+
+ for_mouse_hit_keys(&data, select_keys, 1); /* nearest only */
+ PE_update_selection(data.scene, data.ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int select_linked_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ int location[2];
+
+ location[0]= event->x - ar->winrct.xmin;
+ location[1]= event->y - ar->winrct.ymin;
+ RNA_int_set_array(op->ptr, "location", location);
+
+ return select_linked_exec(C, op);
+}
+
+void PARTICLE_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Linked";
+ ot->idname= "PARTICLE_OT_select_linked";
+
+ /* api callbacks */
+ ot->exec= select_linked_exec;
+ ot->invoke= select_linked_invoke;
+ ot->poll= PE_poll_3dview;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect linked keys rather than selecting them.");
+ RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "", 0, 16384);
+}
+
+/************************ border select operator ************************/
+
+int PE_border_select(bContext *C, rcti *rect, int select)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+ ParticleSystem *psys= PE_get_current(scene, ob);
+ PEData data;
+
+ if(!PE_can_edit(psys))
+ return OPERATOR_CANCELLED;
+
+ PE_set_view3d_data(C, &data);
+ data.rect= rect;
+ data.select= select;
+
+ for_mouse_hit_keys(&data, select_key, 0);
+
+ PE_update_selection(scene, ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+/************************ circle select operator ************************/
+
+int PE_circle_select(bContext *C, int selecting, short *mval, float rad)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+ ParticleSystem *psys= PE_get_current(scene, ob);
+ PEData data;
+
+ if(!PE_can_edit(psys))
+ return OPERATOR_FINISHED;
+
+ PE_set_view3d_data(C, &data);
+ data.mval= mval;
+ data.rad= rad;
+ data.select= selecting;
+
+ for_mouse_hit_keys(&data, select_key, 0);
+
+ PE_update_selection(scene, ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+/************************ lasso select operator ************************/
+
+int PE_lasso_select(bContext *C, short mcords[][2], short moves, short select)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+ ARegion *ar= CTX_wm_region(C);
+ ParticleSystem *psys= PE_get_current(scene, ob);
+ ParticleSystemModifierData *psmd;
+ ParticleEdit *edit;
+ ParticleData *pa;
+ ParticleEditKey *key;
+ float co[3], mat[4][4];
+ short vertco[2];
+ int i, k, totpart;
+
+ if(!PE_can_edit(psys))
+ return OPERATOR_CANCELLED;
+
+ psmd= psys_get_modifier(ob, psys);
+ edit= psys->edit;
+ totpart= psys->totpart;
+
+ LOOP_PARTICLES(i, pa) {
+ if(pa->flag & PARS_HIDE) continue;
+
+ psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
+
+ if(scene->selectmode==SCE_SELECT_POINT) {
+ LOOP_KEYS(k, key) {
+ VECCOPY(co, key->co);
+ Mat4MulVecfl(mat, co);
+ project_short(ar, co, vertco);
+ if((vertco[0] != IS_CLIPPED) && lasso_inside(mcords,moves,vertco[0],vertco[1])) {
+ if(select && !(key->flag & PEK_SELECT)) {
+ key->flag |= PEK_SELECT;
+ pa->flag |= PARS_EDIT_RECALC;
+ }
+ else if(key->flag & PEK_SELECT) {
+ key->flag &= ~PEK_SELECT;
+ pa->flag |= PARS_EDIT_RECALC;
+ }
+ }
+ }
+ }
+ else if(scene->selectmode==SCE_SELECT_END) {
+ key= edit->keys[i] + pa->totkey - 1;
+
+ VECCOPY(co, key->co);
+ Mat4MulVecfl(mat, co);
+ project_short(ar, co,vertco);
+ if((vertco[0] != IS_CLIPPED) && lasso_inside(mcords,moves,vertco[0],vertco[1])) {
+ if(select && !(key->flag & PEK_SELECT)) {
+ key->flag |= PEK_SELECT;
+ pa->flag |= PARS_EDIT_RECALC;
+ }
+ else if(key->flag & PEK_SELECT) {
+ key->flag &= ~PEK_SELECT;
+ pa->flag |= PARS_EDIT_RECALC;
+ }
+ }
+ }
+ }
+
+ PE_update_selection(scene, ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+/*************************** hide operator **************************/
+
+static int hide_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_active_object(C);
+ Scene *scene= CTX_data_scene(C);
+ ParticleSystem *psys= PE_get_current(scene, ob);
+ ParticleEdit *edit;
+ ParticleEditKey *key;
+ ParticleData *pa;
+ int i, k, totpart;
+
+ edit= psys->edit;
+ totpart= psys->totpart;
+
+ if(RNA_enum_get(op->ptr, "unselected")) {
+ LOOP_PARTICLES(i, pa) {
+ if(!particle_is_selected(psys, pa)) {
+ pa->flag |= PARS_HIDE;
+ pa->flag |= PARS_EDIT_RECALC;
+
+ LOOP_KEYS(k, key)
+ key->flag &= ~PEK_SELECT;
+ }
+ }
+ }
+ else {
+ LOOP_PARTICLES(i, pa) {
+ if(particle_is_selected(psys, pa)) {
+ pa->flag |= PARS_HIDE;
+ pa->flag |= PARS_EDIT_RECALC;
+
+ LOOP_KEYS(k, key)
+ key->flag &= ~PEK_SELECT;
+ }
+ }
+ }
+
+ PE_update_selection(scene, ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_hide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Hide Selected";
+ ot->idname= "PARTICLE_OT_hide";
+
+ /* api callbacks */
+ ot->exec= hide_exec;
+ ot->poll= PE_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected.");
+}
+
+/*************************** reveal operator **************************/
+
+static int reveal_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_active_object(C);
+ Scene *scene= CTX_data_scene(C);
+ ParticleSystem *psys= PE_get_current(scene, ob);
+ ParticleEdit *edit;
+ ParticleEditKey *key;
+ ParticleData *pa;
+ int i, k, totpart;
+
+ edit= psys->edit;
+ totpart= psys->totpart;
+
+ LOOP_PARTICLES(i, pa) {
+ if(pa->flag & PARS_HIDE) {
+ pa->flag &= ~PARS_HIDE;
+ pa->flag |= PARS_EDIT_RECALC;
+
+ LOOP_KEYS(k, key)
+ key->flag |= PEK_SELECT;
+ }
+ }
+
+ PE_update_selection(scene, ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_reveal(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Reveal";
+ ot->idname= "PARTICLE_OT_reveal";
+
+ /* api callbacks */
+ ot->exec= reveal_exec;
+ ot->poll= PE_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/************************ select less operator ************************/
+
+static void select_less_keys(PEData *data, int pa_index)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleEdit *edit= psys->edit;
+ ParticleData *pa= &psys->particles[pa_index];
+ ParticleEditKey *key;
+ int k;
+
+ for(k=0,key=edit->keys[pa_index]; k<pa->totkey; k++,key++) {
+ if((key->flag & PEK_SELECT)==0) continue;
+
+ if(k==0) {
+ if(((key+1)->flag&PEK_SELECT)==0)
+ key->flag |= PEK_TO_SELECT;
+ }
+ else if(k==pa->totkey-1) {
+ if(((key-1)->flag&PEK_SELECT)==0)
+ key->flag |= PEK_TO_SELECT;
+ }
+ else {
+ if((((key-1)->flag & (key+1)->flag) & PEK_SELECT)==0)
+ key->flag |= PEK_TO_SELECT;
+ }
+ }
+
+ for(k=0,key=edit->keys[pa_index]; k<pa->totkey; k++,key++) {
+ if(key->flag&PEK_TO_SELECT)
+ key->flag &= ~(PEK_TO_SELECT|PEK_SELECT);
+ }
+}
+
+static int select_less_exec(bContext *C, wmOperator *op)
+{
+ PEData data;
+
+ PE_set_data(C, &data);
+ PE_foreach_particle(&data, select_less_keys);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_select_less(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Less";
+ ot->idname= "PARTICLE_OT_select_less";
+
+ /* api callbacks */
+ ot->exec= select_less_exec;
+ ot->poll= PE_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/************************ select more operator ************************/
+
+static void select_more_keys(PEData *data, int pa_index)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleEdit *edit= psys->edit;
+ ParticleData *pa= &psys->particles[pa_index];
+ ParticleEditKey *key;
+ int k;
+
+ for(k=0,key=edit->keys[pa_index]; k<pa->totkey; k++,key++) {
+ if(key->flag & PEK_SELECT) continue;
+
+ if(k==0) {
+ if((key+1)->flag&PEK_SELECT)
+ key->flag |= PEK_TO_SELECT;
+ }
+ else if(k==pa->totkey-1) {
+ if((key-1)->flag&PEK_SELECT)
+ key->flag |= PEK_TO_SELECT;
+ }
+ else {
+ if(((key-1)->flag | (key+1)->flag) & PEK_SELECT)
+ key->flag |= PEK_TO_SELECT;
+ }
+ }
+
+ for(k=0,key=edit->keys[pa_index]; k<pa->totkey; k++,key++) {
+ if(key->flag&PEK_TO_SELECT) {
+ key->flag &= ~PEK_TO_SELECT;
+ key->flag |= PEK_SELECT;
+ }
+ }
+}
+
+static int select_more_exec(bContext *C, wmOperator *op)
+{
+ PEData data;
+
+ PE_set_data(C, &data);
+ PE_foreach_particle(&data, select_more_keys);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_select_more(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select More";
+ ot->idname= "PARTICLE_OT_select_more";
+
+ /* api callbacks */
+ ot->exec= select_more_exec;
+ ot->poll= PE_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/************************ rekey operator ************************/
+
+static void rekey_particle(PEData *data, int pa_index)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleData *pa= &psys->particles[pa_index];
+ ParticleEdit *edit= psys->edit;
+ ParticleEditSettings *pset= PE_settings(data->scene);
+ ParticleKey state;
+ HairKey *key, *new_keys;
+ ParticleEditKey *ekey;
+ float dval, sta, end;
+ int k;
+
+ pa->flag |= PARS_REKEY;
+
+ key= new_keys= MEM_callocN(pset->totrekey * sizeof(HairKey),"Hair re-key keys");
+
+ /* root and tip stay the same */
+ VECCOPY(key->co, pa->hair->co);
+ VECCOPY((key + pset->totrekey - 1)->co, (pa->hair + pa->totkey - 1)->co);
+
+ sta= key->time= pa->hair->time;
+ end= (key + pset->totrekey - 1)->time= (pa->hair + pa->totkey - 1)->time;
+ dval= (end - sta) / (float)(pset->totrekey - 1);
+
+ /* interpolate new keys from old ones */
+ for(k=1,key++; k<pset->totrekey-1; k++,key++) {
+ state.time= (float)k / (float)(pset->totrekey-1);
+ psys_get_particle_on_path(data->scene, data->ob, psys, pa_index, &state, 0);
+ VECCOPY(key->co, state.co);
+ key->time= sta + k * dval;
+ }
+
+ /* replace keys */
+ if(pa->hair)
+ MEM_freeN(pa->hair);
+ pa->hair= new_keys;
+
+ pa->totkey=pset->totrekey;
+
+ if(edit->keys[pa_index])
+ MEM_freeN(edit->keys[pa_index]);
+ ekey= edit->keys[pa_index]= MEM_callocN(pa->totkey * sizeof(ParticleEditKey),"Hair re-key edit keys");
+
+ for(k=0, key=pa->hair; k<pa->totkey; k++, key++, ekey++) {
+ ekey->co= key->co;
+ ekey->time= &key->time;
+ }
+
+ pa->flag &= ~PARS_REKEY;
+ pa->flag |= PARS_EDIT_RECALC;
+}
+
+static int rekey_exec(bContext *C, wmOperator *op)
+{
+ PEData data;
+ ParticleEditSettings *pset;
+
+ PE_set_data(C, &data);
+
+ pset= PE_settings(data.scene);
+ pset->totrekey= RNA_int_get(op->ptr, "keys");
+
+ data.dval= 1.0f / (float)(pset->totrekey-1);
+
+ foreach_selected_particle(&data, rekey_particle);
+
+ data.psys->edit->totkeys= psys_count_keys(data.psys);
+ recalc_lengths(data.psys);
+
+ PE_update_object(data.scene, data.ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, data.ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_rekey(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Rekey";
+ ot->idname= "PARTICLE_OT_rekey";
+
+ /* api callbacks */
+ ot->exec= rekey_exec;
+ ot->invoke= WM_operator_redo;
+ ot->poll= PE_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "keys", 2, 2, INT_MAX, "Number of Keys", "", 2, 100);
+}
+
+static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float path_time)
+{
+ ParticleSystem *psys= PE_get_current(scene, ob);
+ ParticleEdit *edit=0;
+ ParticleData *pa;
+ ParticleKey state;
+ HairKey *new_keys, *key;
+ ParticleEditKey *ekey;
+ int k;
+
+ if(psys==0) return;
+
+ edit= psys->edit;
+
+ pa= &psys->particles[pa_index];
+
+ pa->flag |= PARS_REKEY;
+
+ key= new_keys= MEM_dupallocN(pa->hair);
+
+ /* interpolate new keys from old ones (roots stay the same) */
+ for(k=1, key++; k < pa->totkey; k++, key++) {
+ state.time= path_time * (float)k / (float)(pa->totkey-1);
+ psys_get_particle_on_path(scene, ob, psys, pa_index, &state, 0);
+ VECCOPY(key->co, state.co);
+ }
+
+ /* replace hair keys */
+ if(pa->hair)
+ MEM_freeN(pa->hair);
+ pa->hair= new_keys;
+
+ /* update edit pointers */
+ for(k=0, key=pa->hair, ekey=edit->keys[pa_index]; k<pa->totkey; k++, key++, ekey++) {
+ ekey->co= key->co;
+ ekey->time= &key->time;
+ }
+
+ pa->flag &= ~PARS_REKEY;
+}
+
+/************************* utilities **************************/
+
+static int remove_tagged_particles(Scene *scene, Object *ob, ParticleSystem *psys)
+{
+ ParticleEdit *edit= psys->edit;
+ ParticleEditSettings *pset= PE_settings(scene);
+ ParticleData *pa, *npa=0, *new_pars=0;
+ ParticleEditKey **key, **nkey=0, **new_keys=0;
+ ParticleSystemModifierData *psmd;
+ int i, totpart, new_totpart= psys->totpart, removed= 0;
+
+ if(pset->flag & PE_X_MIRROR) {
+ /* mirror tags */
+ psmd= psys_get_modifier(ob, psys);
+ totpart= psys->totpart;
+
+ LOOP_PARTICLES(i, pa)
+ if(pa->flag & PARS_TAG)
+ PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
+ }
+
+ for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++) {
+ if(pa->flag & PARS_TAG) {
+ new_totpart--;
+ removed++;
+ }
+ }
+
+ if(new_totpart != psys->totpart) {
+ if(new_totpart) {
+ npa= new_pars= MEM_callocN(new_totpart * sizeof(ParticleData), "ParticleData array");
+ nkey= new_keys= MEM_callocN(new_totpart * sizeof(ParticleEditKey *), "ParticleEditKey array");
+ }
+
+ pa= psys->particles;
+ key= edit->keys;
+ for(i=0; i<psys->totpart; i++, pa++, key++) {
+ if(pa->flag & PARS_TAG) {
+ if(*key)
+ MEM_freeN(*key);
+ if(pa->hair)
+ MEM_freeN(pa->hair);
+ }
+ else {
+ memcpy(npa, pa, sizeof(ParticleData));
+ memcpy(nkey, key, sizeof(ParticleEditKey*));
+ npa++;
+ nkey++;
+ }
+ }
+
+ if(psys->particles) MEM_freeN(psys->particles);
+ psys->particles= new_pars;
+
+ if(edit->keys) MEM_freeN(edit->keys);
+ edit->keys= new_keys;
+
+ if(edit->mirror_cache) {
+ MEM_freeN(edit->mirror_cache);
+ edit->mirror_cache= NULL;
+ }
+
+ psys->totpart= new_totpart;
+
+ edit->totkeys= psys_count_keys(psys);
+ }
+
+ return removed;
+}
+
+static void remove_tagged_keys(Scene *scene, Object *ob, ParticleSystem *psys)
+{
+ ParticleEdit *edit= psys->edit;
+ ParticleEditSettings *pset= PE_settings(scene);
+ ParticleData *pa;
+ HairKey *key, *nkey, *new_keys=0;
+ ParticleEditKey *ekey;
+ ParticleSystemModifierData *psmd;
+ int i, k, totpart= psys->totpart;
+ short new_totkey;
+
+ if(pset->flag & PE_X_MIRROR) {
+ /* mirror key tags */
+ psmd= psys_get_modifier(ob, psys);
+
+ LOOP_PARTICLES(i, pa) {
+ LOOP_KEYS(k,ekey) {
+ if(ekey->flag & PEK_TAG) {
+ PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
+ break;
+ }
+ }
+ }
+ }
+
+ LOOP_PARTICLES(i, pa) {
+ new_totkey= pa->totkey;
+ LOOP_KEYS(k,ekey) {
+ if(ekey->flag & PEK_TAG)
+ new_totkey--;
+ }
+ /* we can't have elements with less than two keys*/
+ if(new_totkey < 2)
+ pa->flag |= PARS_TAG;
+ }
+ remove_tagged_particles(scene, ob, psys);
+
+ totpart= psys->totpart;
+
+ LOOP_PARTICLES(i, pa) {
+ new_totkey= pa->totkey;
+ LOOP_KEYS(k,ekey) {
+ if(ekey->flag & PEK_TAG)
+ new_totkey--;
+ }
+ if(new_totkey != pa->totkey) {
+ key= pa->hair;
+ nkey= new_keys= MEM_callocN(new_totkey*sizeof(HairKey), "HairKeys");
+
+ for(k=0, ekey=edit->keys[i]; k<new_totkey; k++, key++, nkey++, ekey++) {
+ while(ekey->flag & PEK_TAG && key < pa->hair + pa->totkey) {
+ key++;
+ ekey++;
+ }
+
+ if(key < pa->hair + pa->totkey) {
+ VECCOPY(nkey->co, key->co);
+ nkey->time= key->time;
+ nkey->weight= key->weight;
+ }
+ }
+ if(pa->hair)
+ MEM_freeN(pa->hair);
+
+ pa->hair= new_keys;
+
+ pa->totkey=new_totkey;
+
+ if(edit->keys[i])
+ MEM_freeN(edit->keys[i]);
+ ekey= edit->keys[i]= MEM_callocN(new_totkey*sizeof(ParticleEditKey), "particle edit keys");
+
+ for(k=0, key=pa->hair; k<pa->totkey; k++, key++, ekey++) {
+ ekey->co= key->co;
+ ekey->time= &key->time;
+ }
+ }
+ }
+
+ edit->totkeys= psys_count_keys(psys);
+}
+
+/************************ subdivide opertor *********************/
+
+/* works like normal edit mode subdivide, inserts keys between neighbouring selected keys */
+static void subdivide_particle(PEData *data, int pa_index)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleEdit *edit= psys->edit;
+ ParticleData *pa= &psys->particles[pa_index];
+
+ ParticleKey state;
+ HairKey *key, *nkey, *new_keys;
+ ParticleEditKey *ekey, *nekey, *new_ekeys;
+
+ int k;
+ short totnewkey=0;
+ float endtime;
+
+ for(k=0, ekey=edit->keys[pa_index]; k<pa->totkey-1; k++,ekey++) {
+ if(ekey->flag&PEK_SELECT && (ekey+1)->flag&PEK_SELECT)
+ totnewkey++;
+ }
+
+ if(totnewkey==0) return;
+
+ pa->flag |= PARS_REKEY;
+
+ nkey= new_keys= MEM_callocN((pa->totkey+totnewkey)*(sizeof(HairKey)),"Hair subdivide keys");
+ nekey= new_ekeys= MEM_callocN((pa->totkey+totnewkey)*(sizeof(ParticleEditKey)),"Hair subdivide edit keys");
+ endtime= pa->hair[pa->totkey-1].time;
+
+ for(k=0, key=pa->hair, ekey=edit->keys[pa_index]; k<pa->totkey-1; k++, key++, ekey++) {
+
+ memcpy(nkey,key,sizeof(HairKey));
+ memcpy(nekey,ekey,sizeof(ParticleEditKey));
+
+ nekey->co= nkey->co;
+ nekey->time= &nkey->time;
+
+ nkey++;
+ nekey++;
+
+ if(ekey->flag & PEK_SELECT && (ekey+1)->flag & PEK_SELECT) {
+ nkey->time= (key->time + (key+1)->time)*0.5f;
+ state.time= (endtime != 0.0f)? nkey->time/endtime: 0.0f;
+ psys_get_particle_on_path(data->scene, data->ob, psys, pa_index, &state, 0);
+ VECCOPY(nkey->co, state.co);
+
+ nekey->co= nkey->co;
+ nekey->time= &nkey->time;
+ nekey->flag |= PEK_SELECT;
+
+ nekey++;
+ nkey++;
+ }
+ }
+ /*tip still not copied*/
+ memcpy(nkey,key,sizeof(HairKey));
+ memcpy(nekey,ekey,sizeof(ParticleEditKey));
+
+ nekey->co= nkey->co;
+ nekey->time= &nkey->time;
+
+ if(pa->hair)
+ MEM_freeN(pa->hair);
+ pa->hair= new_keys;
+
+ if(edit->keys[pa_index])
+ MEM_freeN(edit->keys[pa_index]);
+
+ edit->keys[pa_index]= new_ekeys;
+
+ pa->totkey += totnewkey;
+ pa->flag |= PARS_EDIT_RECALC;
+ pa->flag &= ~PARS_REKEY;
+}
+
+static int subdivide_exec(bContext *C, wmOperator *op)
+{
+ PEData data;
+
+ PE_set_data(C, &data);
+ PE_foreach_particle(&data, subdivide_particle);
+
+ data.psys->edit->totkeys= psys_count_keys(data.psys);
+
+ recalc_lengths(data.psys);
+ psys_update_world_cos(data.ob, data.psys);
+
+ PE_update_object(data.scene, data.ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, data.ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_subdivide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Subdivide";
+ ot->idname= "PARTICLE_OT_subdivide";
+
+ /* api callbacks */
+ ot->exec= subdivide_exec;
+ ot->poll= PE_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/************************ remove doubles opertor *********************/
+
+static int remove_doubles_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+ ParticleSystem *psys= PE_get_current(scene, ob);
+ ParticleEditSettings *pset=PE_settings(scene);
+ ParticleData *pa;
+ ParticleEdit *edit;
+ ParticleSystemModifierData *psmd;
+ KDTree *tree;
+ KDTreeNearest nearest[10];
+ float mat[4][4], co[3], threshold= RNA_float_get(op->ptr, "threshold");
+ int i, n, totn, removed, totpart, flag, totremoved;
+
+ edit= psys->edit;
+ psmd= psys_get_modifier(ob, psys);
+ totremoved= 0;
+
+ do {
+ removed= 0;
+
+ totpart= psys->totpart;
+ tree=BLI_kdtree_new(totpart);
+
+ /* insert particles into kd tree */
+ LOOP_PARTICLES(i, pa) {
+ if(particle_is_selected(psys, pa)) {
+ psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, mat);
+ VECCOPY(co, pa->hair[0].co);
+ Mat4MulVecfl(mat, co);
+ BLI_kdtree_insert(tree, i, co, NULL);
+ }
+ }
+
+ BLI_kdtree_balance(tree);
+
+ /* tag particles to be removed */
+ LOOP_PARTICLES(i, pa) {
+ if(particle_is_selected(psys, pa)) {
+ psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, mat);
+ VECCOPY(co, pa->hair[0].co);
+ Mat4MulVecfl(mat, co);
+
+ totn= BLI_kdtree_find_n_nearest(tree,10,co,NULL,nearest);
+
+ for(n=0; n<totn; n++) {
+ /* this needs a custom threshold still */
+ if(nearest[n].index > i && nearest[n].dist < threshold) {
+ if(!(pa->flag & PARS_TAG)) {
+ pa->flag |= PARS_TAG;
+ removed++;
+ }
+ }
+ }
+ }
+ }
+
+ BLI_kdtree_free(tree);
+
+ /* remove tagged particles - don't do mirror here! */
+ flag= pset->flag;
+ pset->flag &= ~PE_X_MIRROR;
+ remove_tagged_particles(scene, ob, psys);
+ pset->flag= flag;
+ totremoved += removed;
+ } while(removed);
+
+ if(totremoved == 0)
+ return OPERATOR_CANCELLED;
+
+ BKE_reportf(op->reports, RPT_INFO, "Remove %d double particles.", totremoved);
+
+ psys_update_world_cos(ob, psys);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_remove_doubles(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Remove Doubles";
+ ot->idname= "PARTICLE_OT_remove_doubles";
+
+ /* api callbacks */
+ ot->exec= remove_doubles_exec;
+ ot->poll= PE_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float(ot->srna, "threshold", 0.0002f, 0.0f, FLT_MAX, "Threshold", "Threshold distance withing which particles are removed", 0.00001f, 0.1f);
+}
+
+/************************ cursor drawing *******************************/
+
+static void brush_drawcursor(bContext *C, int x, int y, void *customdata)
+{
+ ParticleEditSettings *pset= PE_settings(CTX_data_scene(C));
+ ParticleBrushData *brush;
+
+ if(pset->brushtype < 0)
+ return;
+
+ brush= &pset->brush[pset->brushtype];
+
+ if(brush) {
+ glPushMatrix();
+
+ glTranslatef((float)x, (float)y, 0.0f);
+
+ glColor4ub(255, 255, 255, 128);
+ glEnable(GL_LINE_SMOOTH );
+ glEnable(GL_BLEND);
+ glutil_draw_lined_arc(0.0, M_PI*2.0, brush->size, 40);
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH );
+
+ glPopMatrix();
+ }
+}
+
+static void toggle_particle_cursor(bContext *C, int enable)
+{
+ ParticleEditSettings *pset= PE_settings(CTX_data_scene(C));
+
+ if(pset->paintcursor && !enable) {
+ WM_paint_cursor_end(CTX_wm_manager(C), pset->paintcursor);
+ pset->paintcursor = NULL;
+ }
+ else if(enable)
+ pset->paintcursor= WM_paint_cursor_activate(CTX_wm_manager(C), PE_poll, brush_drawcursor, NULL);
+}
+
+/********************* radial control operator *********************/
+
+static int brush_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ParticleEditSettings *pset= PE_settings(CTX_data_scene(C));
+ ParticleBrushData *brush;
+ int mode = RNA_enum_get(op->ptr, "mode");
+ float original_value;
+
+ if(pset->brushtype < 0)
+ return OPERATOR_CANCELLED;
+
+ brush= &pset->brush[pset->brushtype];
+
+ toggle_particle_cursor(C, 0);
+
+ if(mode == WM_RADIALCONTROL_SIZE)
+ original_value = brush->size;
+ else if(mode == WM_RADIALCONTROL_STRENGTH)
+ original_value = brush->strength;
+
+ RNA_float_set(op->ptr, "initial_value", original_value);
+
+ return WM_radial_control_invoke(C, op, event);
+}
+
+static int brush_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ int ret = WM_radial_control_modal(C, op, event);
+
+ if(ret != OPERATOR_RUNNING_MODAL)
+ toggle_particle_cursor(C, 1);
+
+ return ret;
+}
+
+static int brush_radial_control_exec(bContext *C, wmOperator *op)
+{
+ ParticleEditSettings *pset= PE_settings(CTX_data_scene(C));
+ ParticleBrushData *brush;
+ int mode = RNA_enum_get(op->ptr, "mode");
+ float new_value = RNA_float_get(op->ptr, "new_value");
+
+ if(pset->brushtype < 0)
+ return OPERATOR_CANCELLED;
+
+ brush= &pset->brush[pset->brushtype];
+
+ if(mode == WM_RADIALCONTROL_SIZE)
+ brush->size= new_value;
+ else if(mode == WM_RADIALCONTROL_STRENGTH)
+ brush->strength= new_value;
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_brush_radial_control(wmOperatorType *ot)
+{
+ WM_OT_radial_control_partial(ot);
+
+ ot->name= "Brush Radial Control";
+ ot->idname= "PARTICLE_OT_brush_radial_control";
+
+ ot->invoke= brush_radial_control_invoke;
+ ot->modal= brush_radial_control_modal;
+ ot->exec= brush_radial_control_exec;
+ ot->poll= PE_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/*************************** delete operator **************************/
+
+enum { DEL_PARTICLE, DEL_KEY };
+
+static EnumPropertyItem delete_type_items[]= {
+ {DEL_PARTICLE, "PARTICLE", "Particle", ""},
+ {DEL_KEY, "KEY", "Key", ""},
+ {0, NULL, NULL}};
+
+static void set_delete_particle(PEData *data, int pa_index)
+{
+ ParticleSystem *psys= data->psys;
+
+ psys->particles[pa_index].flag |= PARS_TAG;
+}
+
+static void set_delete_particle_key(PEData *data, int pa_index, int key_index)
+{
+ ParticleSystem *psys= data->psys;
+
+ psys->edit->keys[pa_index][key_index].flag |= PEK_TAG;
+}
+
+static int delete_exec(bContext *C, wmOperator *op)
+{
+ PEData data;
+ int type= RNA_enum_get(op->ptr, "type");
+
+ PE_set_data(C, &data);
+
+ if(type == DEL_KEY) {
+ foreach_selected_key(&data, set_delete_particle_key);
+ remove_tagged_keys(data.scene, data.ob, data.psys);
+ recalc_lengths(data.psys);
+ }
+ else if(type == DEL_PARTICLE) {
+ foreach_selected_particle(&data, set_delete_particle);
+ remove_tagged_particles(data.scene, data.ob, data.psys);
+ recalc_lengths(data.psys);
+ }
+
+ DAG_object_flush_update(data.scene, data.ob, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, data.ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete";
+ ot->idname= "PARTICLE_OT_delete";
+
+ /* api callbacks */
+ ot->exec= delete_exec;
+ ot->invoke= WM_menu_invoke;
+ ot->poll= PE_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", delete_type_items, DEL_PARTICLE, "Type", "Delete a full particle or only keys.");
+}
+
+/*************************** mirror operator **************************/
+
+static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
+{
+ Mesh *me= (Mesh*)(ob->data);
+ ParticleSystemModifierData *psmd;
+ ParticleSystem *psys= PE_get_current(scene, ob);
+ ParticleEdit *edit;
+ ParticleData *pa, *newpa, *new_pars;
+ ParticleEditKey *ekey, **newkey, **key, **new_keys;
+ HairKey *hkey;
+ int *mirrorfaces;
+ int i, k, rotation, totpart, newtotpart;
+
+ edit= psys->edit;
+ psmd= psys_get_modifier(ob, psys);
+
+ mirrorfaces= mesh_get_x_mirror_faces(ob, NULL);
+
+ if(!edit->mirror_cache)
+ PE_update_mirror_cache(ob, psys);
+
+ totpart= psys->totpart;
+ newtotpart= psys->totpart;
+ LOOP_PARTICLES(i, pa) {
+ if(pa->flag & PARS_HIDE) continue;
+
+ if(!tagged) {
+ if(particle_is_selected(psys, pa)) {
+ if(edit->mirror_cache[i] != -1) {
+ /* already has a mirror, don't need to duplicate */
+ PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
+ continue;
+ }
+ else
+ pa->flag |= PARS_TAG;
+ }
+ }
+
+ if((pa->flag & PARS_TAG) && mirrorfaces[pa->num*2] != -1)
+ newtotpart++;
+ }
+
+ if(newtotpart != psys->totpart) {
+ /* allocate new arrays and copy existing */
+ new_pars= MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new");
+ new_keys= MEM_callocN(newtotpart*sizeof(ParticleEditKey*), "ParticleEditKey new");
+
+ memcpy(new_pars, psys->particles, totpart*sizeof(ParticleData));
+ memcpy(new_keys, edit->keys, totpart*sizeof(ParticleEditKey*));
+
+ if(psys->particles) MEM_freeN(psys->particles);
+ psys->particles= new_pars;
+
+ if(edit->keys) MEM_freeN(edit->keys);
+ edit->keys= new_keys;
+
+ if(edit->mirror_cache) {
+ MEM_freeN(edit->mirror_cache);
+ edit->mirror_cache= NULL;
+ }
+
+ psys->totpart= newtotpart;
+
+ /* create new elements */
+ pa= psys->particles;
+ newpa= psys->particles + totpart;
+ key= edit->keys;
+ newkey= edit->keys + totpart;
+
+ for(i=0; i<totpart; i++, pa++, key++) {
+ if(pa->flag & PARS_HIDE) continue;
+
+ if(!(pa->flag & PARS_TAG) || mirrorfaces[pa->num*2] == -1)
+ continue;
+
+ /* duplicate */
+ *newpa= *pa;
+ if(pa->hair) newpa->hair= MEM_dupallocN(pa->hair);
+ if(pa->keys) newpa->keys= MEM_dupallocN(pa->keys);
+ if(*key) *newkey= MEM_dupallocN(*key);
+
+ /* rotate weights according to vertex index rotation */
+ rotation= mirrorfaces[pa->num*2+1];
+ newpa->fuv[0]= pa->fuv[2];
+ newpa->fuv[1]= pa->fuv[1];
+ newpa->fuv[2]= pa->fuv[0];
+ newpa->fuv[3]= pa->fuv[3];
+ while(rotation-- > 0)
+ if(me->mface[pa->num].v4)
+ SHIFT4(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2], newpa->fuv[3])
+ else
+ SHIFT3(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2])
+
+ /* assign face inddex */
+ newpa->num= mirrorfaces[pa->num*2];
+ newpa->num_dmcache= psys_particle_dm_face_lookup(ob,psmd->dm,newpa->num,newpa->fuv, NULL);
+
+ /* update edit key pointers */
+ ekey= *newkey;
+ for(k=0, hkey=newpa->hair; k<newpa->totkey; k++, hkey++, ekey++) {
+ ekey->co= hkey->co;
+ ekey->time= &hkey->time;
+ }
+
+ /* map key positions as mirror over x axis */
+ PE_mirror_particle(ob, psmd->dm, psys, pa, newpa);
+
+ newpa++;
+ newkey++;
+ }
+
+ edit->totkeys= psys_count_keys(psys);
+ }
+
+ for(pa=psys->particles, i=0; i<psys->totpart; i++, pa++)
+ pa->flag &= ~PARS_TAG;
+
+ MEM_freeN(mirrorfaces);
+}
+
+static int mirror_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+ ParticleSystem *psys= PE_get_current(scene, ob);
+
+ PE_mirror_x(scene, ob, 0);
+
+ psys_update_world_cos(ob, psys);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_mirror(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mirror";
+ ot->idname= "PARTICLE_OT_mirror";
+
+ /* api callbacks */
+ ot->exec= mirror_exec;
+ ot->poll= PE_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/*********************** set brush operator **********************/
+
+static EnumPropertyItem brush_type_items[]= {
+ {PE_BRUSH_NONE, "NONE", "None", ""},
+ {PE_BRUSH_COMB, "COMB", "Comb", ""},
+ {PE_BRUSH_SMOOTH, "SMOOTH", "Smooth", ""},
+ {PE_BRUSH_WEIGHT, "WEIGHT", "Weight", ""},
+ {PE_BRUSH_ADD, "ADD", "Add", ""},
+ {PE_BRUSH_LENGTH, "LENGTH", "Length", ""},
+ {PE_BRUSH_PUFF, "PUFF", "Puff", ""},
+ {PE_BRUSH_CUT, "CUT", "Cut", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int set_brush_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ ParticleEditSettings *pset= PE_settings(scene);
+
+ pset->brushtype= RNA_enum_get(op->ptr, "type");
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_brush_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Brush";
+ ot->idname= "PARTICLE_OT_brush_set";
+
+ /* api callbacks */
+ ot->exec= set_brush_exec;
+ ot->invoke= WM_menu_invoke;
+ ot->poll= PE_poll;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", brush_type_items, PE_BRUSH_NONE, "Type", "Brush type to select for editing.");
+}
+
+/************************* brush edit callbacks ********************/
+
+static void brush_comb(PEData *data, float mat[][4], float imat[][4], int pa_index, int key_index)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleData *pa= &psys->particles[pa_index];
+ ParticleEditSettings *pset= PE_settings(data->scene);
+ HairKey *key= pa->hair + key_index;
+ float cvec[3], fac;
+
+ if(pset->flag & PE_LOCK_FIRST && key_index == 0) return;
+
+ fac= (float)pow((double)(1.0f - data->dist / data->rad), (double)data->combfac);
+
+ VECCOPY(cvec,data->dvec);
+ Mat4Mul3Vecfl(imat,cvec);
+ VecMulf(cvec, fac);
+ VECADD(key->co, key->co, cvec);
+
+ pa->flag |= PARS_EDIT_RECALC;
+}
+
+static void brush_cut(PEData *data, int pa_index)
+{
+ ParticleSystem *psys= data->psys;
+ ARegion *ar= data->vc.ar;
+ Object *ob= data->ob;
+ ParticleData *pa= &psys->particles[pa_index];
+ ParticleCacheKey *key= psys->pathcache[pa_index];
+ float rad2, cut_time= 1.0;
+ float x0, x1, v0, v1, o0, o1, xo0, xo1, d, dv;
+ int k, cut, keys= (int)pow(2.0, (double)psys->part->draw_step);
+ short vertco[2];
+
+ /* blunt scissors */
+ if(BLI_frand() > data->cutfac) return;
+
+ rad2= data->rad * data->rad;
+
+ cut=0;
+
+ project_short_noclip(ar, key->co, vertco);
+ x0= (float)vertco[0];
+ x1= (float)vertco[1];
+
+ o0= (float)data->mval[0];
+ o1= (float)data->mval[1];
+
+ xo0= x0 - o0;
+ xo1= x1 - o1;
+
+ /* check if root is inside circle */
+ if(xo0*xo0 + xo1*xo1 < rad2 && key_test_depth(data, key->co)) {
+ cut_time= -1.0f;
+ cut= 1;
+ }
+ else {
+ /* calculate path time closest to root that was inside the circle */
+ for(k=1, key++; k<=keys; k++, key++) {
+ project_short_noclip(ar, key->co, vertco);
+
+ if(key_test_depth(data, key->co) == 0) {
+ x0= (float)vertco[0];
+ x1= (float)vertco[1];
+
+ xo0= x0 - o0;
+ xo1= x1 - o1;
+ continue;
+ }
+
+ v0= (float)vertco[0] - x0;
+ v1= (float)vertco[1] - x1;
+
+ dv= v0*v0 + v1*v1;
+
+ d= (v0*xo1 - v1*xo0);
+
+ d= dv * rad2 - d*d;
+
+ if(d > 0.0f) {
+ d= sqrt(d);
+
+ cut_time= -(v0*xo0 + v1*xo1 + d);
+
+ if(cut_time > 0.0f) {
+ cut_time /= dv;
+
+ if(cut_time < 1.0f) {
+ cut_time += (float)(k-1);
+ cut_time /= (float)keys;
+ cut= 1;
+ break;
+ }
+ }
+ }
+
+ x0= (float)vertco[0];
+ x1= (float)vertco[1];
+
+ xo0= x0 - o0;
+ xo1= x1 - o1;
+ }
+ }
+
+ if(cut) {
+ if(cut_time < 0.0f) {
+ pa->flag |= PARS_TAG;
+ }
+ else {
+ rekey_particle_to_time(data->scene, ob, pa_index, cut_time);
+ pa->flag |= PARS_EDIT_RECALC;
+ }
+ }
+}
+
+static void brush_length(PEData *data, int pa_index)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleData *pa= &psys->particles[pa_index];
+ HairKey *key;
+ float dvec[3],pvec[3];
+ int k;
+
+ key= pa->hair;
+ VECCOPY(pvec,key->co);
+
+ for(k=1, key++; k<pa->totkey; k++,key++) {
+ VECSUB(dvec,key->co,pvec);
+ VECCOPY(pvec,key->co);
+ VecMulf(dvec,data->growfac);
+ VECADD(key->co,(key-1)->co,dvec);
+ }
+
+ pa->flag |= PARS_EDIT_RECALC;
+}
+
+static void brush_puff(PEData *data, int pa_index)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleData *pa= &psys->particles[pa_index];
+ ParticleEdit *edit= psys->edit;
+ HairKey *key;
+ float mat[4][4], imat[4][4];
+ float lastco[3], rootco[3], co[3], nor[3], kco[3], dco[3], fac, length;
+ int k;
+
+ psys_mat_hair_to_global(data->ob, data->dm, psys->part->from, pa, mat);
+ Mat4Invert(imat,mat);
+
+ /* find root coordinate and normal on emitter */
+ key= pa->hair;
+ VECCOPY(co, key->co);
+ Mat4MulVecfl(mat, co);
+
+ pa_index= BLI_kdtree_find_nearest(edit->emitter_field, co, NULL, NULL);
+ if(pa_index == -1) return;
+
+ VECCOPY(rootco, co);
+ VecCopyf(nor, &psys->edit->emitter_cosnos[pa_index*6+3]);
+ Normalize(nor);
+ length= 0.0f;
+
+ fac= (float)pow((double)(1.0f - data->dist / data->rad), (double)data->pufffac);
+ fac *= 0.025f;
+ if(data->invert)
+ fac= -fac;
+
+ for(k=1, key++; k<pa->totkey; k++, key++) {
+ /* compute position as if hair was standing up straight */
+ VECCOPY(lastco, co);
+ VECCOPY(co, key->co);
+ Mat4MulVecfl(mat, co);
+ length += VecLenf(lastco, co);
+
+ VECADDFAC(kco, rootco, nor, length);
+
+ /* blend between the current and straight position */
+ VECSUB(dco, kco, co);
+ VECADDFAC(co, co, dco, fac);
+
+ VECCOPY(key->co, co);
+ Mat4MulVecfl(imat, key->co);
+ }
+
+ pa->flag |= PARS_EDIT_RECALC;
+}
+
+static void brush_smooth_get(PEData *data, float mat[][4], float imat[][4], int pa_index, int key_index)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleData *pa= &psys->particles[pa_index];
+ HairKey *key= pa->hair + key_index;
+
+ if(key_index) {
+ float dvec[3];
+
+ VecSubf(dvec,key->co,(key-1)->co);
+ Mat4Mul3Vecfl(mat,dvec);
+ VECADD(data->vec,data->vec,dvec);
+ data->tot++;
+ }
+}
+
+static void brush_smooth_do(PEData *data, float mat[][4], float imat[][4], int pa_index, int key_index)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleData *pa= &psys->particles[pa_index];
+ HairKey *key= pa->hair + key_index;
+ float vec[3], dvec[3];
+
+ if(key_index) {
+ VECCOPY(vec,data->vec);
+ Mat4Mul3Vecfl(imat,vec);
+
+ VecSubf(dvec,key->co,(key-1)->co);
+
+ VECSUB(dvec,vec,dvec);
+ VecMulf(dvec,data->smoothfac);
+
+ VECADD(key->co,key->co,dvec);
+ }
+
+ pa->flag |= PARS_EDIT_RECALC;
+}
+
+static void brush_add(PEData *data, short number)
+{
+ Scene *scene= data->scene;
+ Object *ob= data->ob;
+ ParticleSystem *psys= data->psys;
+ ParticleData *add_pars= MEM_callocN(number*sizeof(ParticleData),"ParticleData add");
+ ParticleSystemModifierData *psmd= psys_get_modifier(ob,psys);
+ ParticleEditSettings *pset= PE_settings(scene);
+ ParticleEdit *edit= psys->edit;
+ int i, k, n= 0, totpart= psys->totpart;
+ short mco[2];
+ short dmx= 0, dmy= 0;
+ float co1[3], co2[3], min_d, imat[4][4];
+ float framestep, timestep= psys_get_timestep(psys->part);
+ short size= pset->brush[PE_BRUSH_ADD].size;
+ short size2= size*size;
+ DerivedMesh *dm=0;
+ Mat4Invert(imat,ob->obmat);
+
+ BLI_srandom(psys->seed+data->mval[0]+data->mval[1]);
+
+ /* painting onto the deformed mesh, could be an option? */
+ if(psmd->dm->deformedOnly)
+ dm= psmd->dm;
+ else
+ dm= mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+
+ for(i=0; i<number; i++) {
+ if(number>1) {
+ dmx=dmy=size;
+ while(dmx*dmx+dmy*dmy>size2) {
+ dmx=(short)((2.0f*BLI_frand()-1.0f)*size);
+ dmy=(short)((2.0f*BLI_frand()-1.0f)*size);
+ }
+ }
+
+ mco[0]= data->mval[0] + dmx;
+ mco[1]= data->mval[1] + dmy;
+ viewline(data->vc.ar, data->vc.v3d, mco, co1, co2);
+
+ Mat4MulVecfl(imat,co1);
+ Mat4MulVecfl(imat,co2);
+ min_d=2.0;
+
+ /* warning, returns the derived mesh face */
+ if(psys_intersect_dm(scene, ob,dm,0,co1,co2,&min_d,&add_pars[n].num,add_pars[n].fuv,0,0,0,0)) {
+ add_pars[n].num_dmcache= psys_particle_dm_face_lookup(ob,psmd->dm,add_pars[n].num,add_pars[n].fuv,NULL);
+ n++;
+ }
+ }
+ if(n) {
+ int newtotpart=totpart+n;
+ float hairmat[4][4], cur_co[3];
+ KDTree *tree=0;
+ ParticleData *pa, *new_pars= MEM_callocN(newtotpart*sizeof(ParticleData),"ParticleData new");
+ ParticleEditKey *ekey, **key, **new_keys= MEM_callocN(newtotpart*sizeof(ParticleEditKey *),"ParticleEditKey array new");
+ HairKey *hkey;
+
+ /* save existing elements */
+ memcpy(new_pars, psys->particles, totpart * sizeof(ParticleData));
+ memcpy(new_keys, edit->keys, totpart * sizeof(ParticleEditKey*));
+
+ /* change old arrays to new ones */
+ if(psys->particles) MEM_freeN(psys->particles);
+ psys->particles= new_pars;
+
+ if(edit->keys) MEM_freeN(edit->keys);
+ edit->keys= new_keys;
+
+ if(edit->mirror_cache) {
+ MEM_freeN(edit->mirror_cache);
+ edit->mirror_cache= NULL;
+ }
+
+ /* create tree for interpolation */
+ if(pset->flag & PE_INTERPOLATE_ADDED && psys->totpart) {
+ tree=BLI_kdtree_new(psys->totpart);
+
+ for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
+ psys_particle_on_dm(psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,cur_co,0,0,0,0,0);
+ BLI_kdtree_insert(tree, i, cur_co, NULL);
+ }
+
+ BLI_kdtree_balance(tree);
+ }
+
+ psys->totpart= newtotpart;
+
+ /* create new elements */
+ pa= psys->particles + totpart;
+ key= edit->keys + totpart;
+
+ for(i=totpart; i<newtotpart; i++, pa++, key++) {
+ memcpy(pa, add_pars + i - totpart, sizeof(ParticleData));
+ pa->hair= MEM_callocN(pset->totaddkey * sizeof(HairKey), "BakeKey key add");
+ ekey= *key= MEM_callocN(pset->totaddkey * sizeof(ParticleEditKey), "ParticleEditKey add");
+ pa->totkey= pset->totaddkey;
+
+ for(k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, ekey++) {
+ ekey->co= hkey->co;
+ ekey->time= &hkey->time;
+ }
+
+ pa->size= 1.0f;
+ initialize_particle(pa,i,ob,psys,psmd);
+ reset_particle(scene, pa,psys,psmd,ob,0.0,1.0,0,0,0);
+ pa->flag |= PARS_EDIT_RECALC;
+ if(pset->flag & PE_X_MIRROR)
+ pa->flag |= PARS_TAG; /* signal for duplicate */
+
+ framestep= pa->lifetime/(float)(pset->totaddkey-1);
+
+ if(tree) {
+ HairKey *hkey;
+ ParticleKey key[3];
+ KDTreeNearest ptn[3];
+ int w, maxw;
+ float maxd, mind, dd, totw=0.0, weight[3];
+
+ psys_particle_on_dm(psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,0,0);
+ maxw= BLI_kdtree_find_n_nearest(tree,3,co1,NULL,ptn);
+
+ maxd= ptn[maxw-1].dist;
+ mind= ptn[0].dist;
+ dd= maxd - mind;
+
+ for(w=0; w<maxw; w++) {
+ weight[w]= (float)pow(2.0, (double)(-6.0f * ptn[w].dist / maxd));
+ totw += weight[w];
+ }
+ for(;w<3; w++) {
+ weight[w]= 0.0f;
+ }
+
+ for(w=0; w<maxw; w++)
+ weight[w] /= totw;
+
+ for(k=0; k<pset->totaddkey; k++) {
+ hkey= pa->hair + k;
+ hkey->time= pa->time + k * framestep;
+
+ key[0].time= hkey->time/ 100.0f;
+ psys_get_particle_on_path(scene, ob, psys, ptn[0].index, key, 0);
+ VecMulf(key[0].co, weight[0]);
+
+ if(maxw>1) {
+ key[1].time= key[0].time;
+ psys_get_particle_on_path(scene, ob, psys, ptn[1].index, key + 1, 0);
+ VecMulf(key[1].co, weight[1]);
+ VECADD(key[0].co, key[0].co, key[1].co);
+
+ if(maxw>2) {
+ key[2].time= key[0].time;
+ psys_get_particle_on_path(scene, ob, psys, ptn[2].index, key + 2, 0);
+ VecMulf(key[2].co, weight[2]);
+ VECADD(key[0].co, key[0].co, key[2].co);
+ }
+ }
+
+ if(k==0)
+ VECSUB(co1, pa->state.co, key[0].co);
+
+ VECADD(pa->hair[k].co, key[0].co, co1);
+
+ pa->hair[k].time= key[0].time;
+ }
+ }
+ else {
+ for(k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
+ VECADDFAC(hkey->co, pa->state.co, pa->state.vel, k * framestep * timestep);
+ pa->hair[k].time += k * framestep;
+ }
+ }
+ for(k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
+ psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
+ Mat4Invert(imat,hairmat);
+ Mat4MulVecfl(imat, hkey->co);
+ }
+ }
+ edit->totkeys= psys_count_keys(psys);
+
+ if(tree)
+ BLI_kdtree_free(tree);
+ }
+ if(add_pars)
+ MEM_freeN(add_pars);
+
+ if(!psmd->dm->deformedOnly)
+ dm->release(dm);
+}
+
+static void brush_weight(PEData *data, float mat[][4], float imat[][4], int pa_index, int key_index)
+{
+ ParticleSystem *psys= data->psys;
+ ParticleData *pa;
+
+ /* roots have full weight allways */
+ if(key_index) {
+ pa= &psys->particles[pa_index];
+ pa->hair[key_index].weight= data->weightfac;
+ pa->flag |= PARS_EDIT_RECALC;
+ }
+}
+
+/************************* brush edit operator ********************/
+
+typedef struct BrushEdit {
+ Scene *scene;
+ Object *ob;
+ ParticleSystem *psys;
+
+ int first;
+ int lastmouse[2];
+} BrushEdit;
+
+static int brush_edit_init(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+ ParticleSystem *psys= PE_get_current(scene, ob);
+ ParticleEditSettings *pset= PE_settings(scene);
+ ARegion *ar= CTX_wm_region(C);
+ BrushEdit *bedit;
+
+ if(pset->brushtype < 0)
+ return 0;
+
+ initgrabz(ar->regiondata, ob->obmat[3][0], ob->obmat[3][1], ob->obmat[3][2]);
+
+ bedit= MEM_callocN(sizeof(BrushEdit), "BrushEdit");
+ bedit->first= 1;
+ op->customdata= bedit;
+
+ bedit->scene= scene;
+ bedit->ob= ob;
+ bedit->psys= psys;
+
+ return 1;
+}
+
+static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
+{
+ BrushEdit *bedit= op->customdata;
+ Scene *scene= bedit->scene;
+ Object *ob= bedit->ob;
+ ParticleSystem *psys= bedit->psys;
+ ParticleEditSettings *pset= PE_settings(scene);
+ ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
+ ParticleBrushData *brush= &pset->brush[pset->brushtype];
+ ARegion *ar= CTX_wm_region(C);
+ float vec1[3], vec2[3];
+ short mval[2], mvalo[2];
+ int flip, mouse[2], dx, dy, removed= 0, selected= 0;
+
+ RNA_int_get_array(itemptr, "mouse", mouse);
+ flip= RNA_boolean_get(itemptr, "flip");
+
+ if(bedit->first) {
+ bedit->lastmouse[0]= mouse[0];
+ bedit->lastmouse[1]= mouse[1];
+ }
+
+ dx= mouse[0] - bedit->lastmouse[0];
+ dy= mouse[1] - bedit->lastmouse[1];
+
+ mval[0]= mouse[0];
+ mval[1]= mouse[1];
+
+ mvalo[0]= bedit->lastmouse[0];
+ mvalo[1]= bedit->lastmouse[1];
+
+ if(((pset->brushtype == PE_BRUSH_ADD) ?
+ (sqrt(dx * dx + dy * dy) > pset->brush[PE_BRUSH_ADD].step) : (dx != 0 || dy != 0))
+ || bedit->first) {
+
+ view3d_operator_needs_opengl(C);
+ selected= (short)count_selected_keys(scene, psys);
+
+ switch(pset->brushtype) {
+ case PE_BRUSH_COMB:
+ {
+ PEData data;
+
+ PE_set_view3d_data(C, &data);
+ data.mval= mval;
+ data.rad= (float)brush->size;
+
+ data.combfac= (float)(brush->strength - 50) / 50.0f;
+ if(data.combfac < 0.0f)
+ data.combfac= 1.0f - 9.0f * data.combfac;
+ else
+ data.combfac= 1.0f - data.combfac;
+
+ Mat4Invert(ob->imat, ob->obmat);
+
+ window_to_3d(ar, vec1, mvalo[0], mvalo[1]);
+ window_to_3d(ar, vec2, mval[0], mval[1]);
+ VECSUB(vec1, vec2, vec1);
+ data.dvec= vec1;
+
+ foreach_mouse_hit_key(&data, brush_comb, selected);
+ break;
+ }
+ case PE_BRUSH_CUT:
+ {
+ PEData data;
+
+ PE_set_view3d_data(C, &data);
+ data.mval= mval;
+ data.rad= (float)brush->size;
+ data.cutfac= (float)(brush->strength / 100.0f);
+
+ if(selected)
+ foreach_selected_particle(&data, brush_cut);
+ else
+ PE_foreach_particle(&data, brush_cut);
+
+ removed= remove_tagged_particles(scene, ob, psys);
+ if(pset->flag & PE_KEEP_LENGTHS)
+ recalc_lengths(psys);
+ break;
+ }
+ case PE_BRUSH_LENGTH:
+ {
+ PEData data;
+
+ PE_set_view3d_data(C, &data);
+ data.mval= mval;
+
+ data.rad= (float)brush->size;
+ data.growfac= (float)brush->strength / 5000.0f;
+
+ if(brush->invert ^ flip)
+ data.growfac= 1.0f - data.growfac;
+ else
+ data.growfac= 1.0f + data.growfac;
+
+ foreach_mouse_hit_particle(&data, brush_length, selected);
+
+ if(pset->flag & PE_KEEP_LENGTHS)
+ recalc_lengths(psys);
+ break;
+ }
+ case PE_BRUSH_PUFF:
+ {
+ PEData data;
+
+ PE_set_view3d_data(C, &data);
+ data.dm= psmd->dm;
+ data.mval= mval;
+ data.rad= (float)brush->size;
+
+ data.pufffac= (float)(brush->strength - 50) / 50.0f;
+ if(data.pufffac < 0.0f)
+ data.pufffac= 1.0f - 9.0f * data.pufffac;
+ else
+ data.pufffac= 1.0f - data.pufffac;
+
+ data.invert= (brush->invert ^ flip);
+ Mat4Invert(ob->imat, ob->obmat);
+
+ foreach_mouse_hit_particle(&data, brush_puff, selected);
+ break;
+ }
+ case PE_BRUSH_ADD:
+ {
+ PEData data;
+
+ if(psys->part->from==PART_FROM_FACE) {
+ PE_set_view3d_data(C, &data);
+ data.mval= mval;
+
+ brush_add(&data, brush->strength);
+
+ if(pset->flag & PE_KEEP_LENGTHS)
+ recalc_lengths(psys);
+ }
+ break;
+ }
+ case PE_BRUSH_WEIGHT:
+ {
+ PEData data;
+
+ PE_set_view3d_data(C, &data);
+ data.mval= mval;
+ data.rad= (float)brush->size;
+
+ data.weightfac= (float)(brush->strength / 100.0f);
+
+ foreach_mouse_hit_key(&data, brush_weight, selected);
+ break;
+ }
+ case PE_BRUSH_SMOOTH:
+ {
+ PEData data;
+
+ PE_set_view3d_data(C, &data);
+ data.mval= mval;
+ data.rad= (float)brush->size;
+
+ data.vec[0]= data.vec[1]= data.vec[2]= 0.0f;
+ data.tot= 0;
+
+ data.smoothfac= (float)(brush->strength / 100.0f);
+
+ Mat4Invert(ob->imat, ob->obmat);
+
+ foreach_mouse_hit_key(&data, brush_smooth_get, selected);
+
+ if(data.tot) {
+ VecMulf(data.vec, 1.0f / (float)data.tot);
+ foreach_mouse_hit_key(&data, brush_smooth_do, selected);
+ }
+
+ break;
+ }
+ }
+ if((pset->flag & PE_KEEP_LENGTHS)==0)
+ recalc_lengths(psys);
+
+ if(pset->brushtype == PE_BRUSH_ADD || removed) {
+ if(pset->brushtype == PE_BRUSH_ADD && (pset->flag & PE_X_MIRROR))
+ PE_mirror_x(scene, ob, 1);
+
+ psys_update_world_cos(ob,psys);
+ psys_free_path_cache(psys);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+ else
+ PE_update_object(scene, ob, 1);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
+
+ bedit->lastmouse[0]= mouse[0];
+ bedit->lastmouse[1]= mouse[1];
+ bedit->first= 0;
+ }
+}
+
+static void brush_edit_exit(bContext *C, wmOperator *op)
+{
+ BrushEdit *bedit= op->customdata;
+
+ MEM_freeN(bedit);
+}
+
+static int brush_edit_exec(bContext *C, wmOperator *op)
+{
+ if(!brush_edit_init(C, op))
+ return OPERATOR_CANCELLED;
+
+ RNA_BEGIN(op->ptr, itemptr, "stroke") {
+ brush_edit_apply(C, op, &itemptr);
+ }
+ RNA_END;
+
+ brush_edit_exit(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+static void brush_edit_apply_event(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ PointerRNA itemptr;
+ int mouse[2];
+
+ mouse[0]= event->x - ar->winrct.xmin;
+ mouse[1]= event->y - ar->winrct.ymin;
+
+ /* fill in stroke */
+ RNA_collection_add(op->ptr, "stroke", &itemptr);
+
+ RNA_int_set_array(&itemptr, "mouse", mouse);
+ RNA_boolean_set(&itemptr, "flip", event->shift != 0); // XXX hardcoded
+
+ /* apply */
+ brush_edit_apply(C, op, &itemptr);
+}
+
+static int brush_edit_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ if(!brush_edit_init(C, op))
+ return OPERATOR_CANCELLED;
+
+ brush_edit_apply_event(C, op, event);
+
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int brush_edit_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ switch(event->type) {
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE: // XXX hardcoded
+ brush_edit_exit(C, op);
+ return OPERATOR_FINISHED;
+ case MOUSEMOVE:
+ brush_edit_apply_event(C, op, event);
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int brush_edit_cancel(bContext *C, wmOperator *op)
+{
+ brush_edit_exit(C, op);
+
+ return OPERATOR_CANCELLED;
+}
+
+void PARTICLE_OT_brush_edit(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Brush Edit";
+ ot->idname= "PARTICLE_OT_brush_edit";
+
+ /* api callbacks */
+ ot->exec= brush_edit_exec;
+ ot->invoke= brush_edit_invoke;
+ ot->modal= brush_edit_modal;
+ ot->cancel= brush_edit_cancel;
+ ot->poll= PE_poll_3dview;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+}
+
+/*********************** undo ***************************/
+
+static void free_ParticleUndo(ParticleUndo *undo)
+{
+ ParticleData *pa;
+ int i;
+
+ for(i=0, pa=undo->particles; i<undo->totpart; i++, pa++) {
+ if(pa->hair)
+ MEM_freeN(pa->hair);
+ if(undo->keys[i])
+ MEM_freeN(undo->keys[i]);
+ }
+ if(undo->keys)
+ MEM_freeN(undo->keys);
+
+ if(undo->particles)
+ MEM_freeN(undo->particles);
+
+ //if(undo->emitter_cosnos)
+ // MEM_freeN(undo->emitter_cosnos);
+}
+
+static void make_ParticleUndo(ParticleSystem *psys, ParticleUndo *undo)
+{
+ ParticleData *pa,*upa;
+ int i;
+
+ undo->totpart= psys->totpart;
+ undo->totkeys= psys->edit->totkeys;
+
+ upa= undo->particles= MEM_dupallocN(psys->particles);
+ undo->keys= MEM_dupallocN(psys->edit->keys);
+
+ for(i=0, pa=psys->particles; i<undo->totpart; i++, pa++, upa++) {
+ upa->hair= MEM_dupallocN(pa->hair);
+ undo->keys[i]= MEM_dupallocN(psys->edit->keys[i]);
+ /* no need to update edit key->co & key->time pointers here */
+ }
+}
+
+static void get_ParticleUndo(ParticleSystem *psys, ParticleUndo *undo)
+{
+ ParticleData *pa, *upa;
+ ParticleEditKey *key;
+ HairKey *hkey;
+ int i, k, totpart= psys->totpart;
+
+ LOOP_PARTICLES(i, pa) {
+ if(pa->hair)
+ MEM_freeN(pa->hair);
+
+ if(psys->edit->keys[i])
+ MEM_freeN(psys->edit->keys[i]);
+ }
+ if(psys->particles)
+ MEM_freeN(psys->particles);
+ if(psys->edit->keys)
+ MEM_freeN(psys->edit->keys);
+ if(psys->edit->mirror_cache) {
+ MEM_freeN(psys->edit->mirror_cache);
+ psys->edit->mirror_cache= NULL;
+ }
+
+ pa= psys->particles= MEM_dupallocN(undo->particles);
+ psys->edit->keys= MEM_dupallocN(undo->keys);
+
+ for(i=0,upa=undo->particles; i<undo->totpart; i++, upa++, pa++) {
+ hkey= pa->hair= MEM_dupallocN(upa->hair);
+ key= psys->edit->keys[i]= MEM_dupallocN(undo->keys[i]);
+ for(k=0; k<pa->totkey; k++, hkey++, key++) {
+ key->co= hkey->co;
+ key->time= &hkey->time;
+ }
+ }
+
+ psys->totpart= undo->totpart;
+ psys->edit->totkeys= undo->totkeys;
+}
+
+void PE_undo_push(Scene *scene, char *str)
+{
+ ParticleSystem *psys= PE_get_current(scene, OBACT);
+ ParticleEdit *edit= 0;
+ ParticleUndo *undo;
+ int nr;
+
+ if(!PE_can_edit(psys)) return;
+ edit= psys->edit;
+
+ /* remove all undos after (also when curundo==NULL) */
+ while(edit->undo.last != edit->curundo) {
+ undo= edit->undo.last;
+ BLI_remlink(&edit->undo, undo);
+ free_ParticleUndo(undo);
+ MEM_freeN(undo);
+ }
+
+ /* make new */
+ edit->curundo= undo= MEM_callocN(sizeof(ParticleUndo), "particle undo file");
+ strncpy(undo->name, str, 64-1);
+ BLI_addtail(&edit->undo, undo);
+
+ /* and limit amount to the maximum */
+ nr= 0;
+ undo= edit->undo.last;
+ while(undo) {
+ nr++;
+ if(nr==U.undosteps) break;
+ undo= undo->prev;
+ }
+ if(undo) {
+ while(edit->undo.first!=undo) {
+ ParticleUndo *first= edit->undo.first;
+ BLI_remlink(&edit->undo, first);
+ free_ParticleUndo(first);
+ MEM_freeN(first);
+ }
+ }
+
+ /* copy */
+ make_ParticleUndo(psys,edit->curundo);
+}
+
+void PE_undo_step(Scene *scene, int step)
+{
+ ParticleSystem *psys= PE_get_current(scene, OBACT);
+ ParticleEdit *edit= 0;
+
+ if(!PE_can_edit(psys)) return;
+ edit= psys->edit;
+
+ if(step==0) {
+ get_ParticleUndo(psys,edit->curundo);
+ }
+ else if(step==1) {
+
+ if(edit->curundo==NULL || edit->curundo->prev==NULL);
+ else {
+ if(G.f & G_DEBUG) printf("undo %s\n", edit->curundo->name);
+ edit->curundo= edit->curundo->prev;
+ get_ParticleUndo(psys, edit->curundo);
+ }
+ }
+ else {
+ /* curundo has to remain current situation! */
+
+ if(edit->curundo==NULL || edit->curundo->next==NULL);
+ else {
+ get_ParticleUndo(psys, edit->curundo->next);
+ edit->curundo= edit->curundo->next;
+ if(G.f & G_DEBUG) printf("redo %s\n", edit->curundo->name);
+ }
+ }
+
+ DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA);
+}
+
+static void ParticleUndo_number(Scene *scene, ParticleEdit *edit, int nr)
+{
+ ParticleUndo *undo;
+ int a=1;
+
+ for(undo= edit->undo.first; undo; undo= undo->next, a++) {
+ if(a==nr) break;
+ }
+ edit->curundo= undo;
+ PE_undo_step(scene, 0);
+}
+
+static void ParticleUndo_clear(ParticleSystem *psys)
+{
+ ParticleUndo *undo;
+ ParticleEdit *edit;
+
+ if(psys==0) return;
+
+ edit= psys->edit;
+
+ if(edit==0) return;
+
+ undo= edit->undo.first;
+ while(undo) {
+ free_ParticleUndo(undo);
+ undo= undo->next;
+ }
+ BLI_freelistN(&edit->undo);
+ edit->curundo= NULL;
+}
+
+void PE_undo(Scene *scene)
+{
+ PE_undo_step(scene, 1);
+}
+
+void PE_redo(Scene *scene)
+{
+ PE_undo_step(scene, -1);
+}
+
+void PE_undo_menu(Scene *scene, Object *ob)
+{
+ ParticleSystem *psys= PE_get_current(scene, ob);
+ ParticleEdit *edit= 0;
+ ParticleUndo *undo;
+ DynStr *ds;
+ short event;
+ char *menu;
+
+ if(!PE_can_edit(psys)) return;
+ edit= psys->edit;
+
+ ds= BLI_dynstr_new();
+
+ BLI_dynstr_append(ds, "Particlemode Undo History %t");
+
+ for(undo= edit->undo.first; undo; undo= undo->next) {
+ BLI_dynstr_append(ds, "|");
+ BLI_dynstr_append(ds, undo->name);
+ }
+
+ menu= BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+// XXX event= pupmenu_col(menu, 20);
+ MEM_freeN(menu);
+
+ if(event>0) ParticleUndo_number(scene, edit,event);
+}
+
+/************************ utilities ******************************/
+
+int PE_minmax(Scene *scene, float *min, float *max)
+{
+ Object *ob= OBACT;
+ ParticleSystem *psys= PE_get_current(scene, ob);
+ ParticleSystemModifierData *psmd;
+ ParticleData *pa;
+ ParticleEditKey *key;
+ float co[3], mat[4][4];
+ int i, k, totpart, ok= 0;
+
+ if(!PE_can_edit(psys)) return ok;
+
+ psmd= psys_get_modifier(ob, psys);
+ totpart= psys->totpart;
+
+ LOOP_PARTICLES(i, pa) {
+ if(pa->flag & PARS_HIDE) continue;
+
+ psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
+
+ LOOP_KEYS(k, key) {
+ if(key->flag & PEK_SELECT) {
+ VECCOPY(co, key->co);
+ Mat4MulVecfl(mat, co);
+ DO_MINMAX(co, min, max);
+ ok= 1;
+ }
+ }
+ }
+
+ if(!ok) {
+ minmax_object(ob, min, max);
+ ok= 1;
+ }
+
+ return ok;
+}
+
+/************************ particle edit toggle operator ************************/
+
+/* initialize needed data for bake edit */
+static void PE_create_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys)
+{
+ ParticleEdit *edit= psys->edit;
+ ParticleData *pa;
+ ParticleEditKey *key;
+ HairKey *hkey;
+ int i, k, totpart= psys->totpart, alloc=1;
+
+ if((psys->flag & PSYS_EDITED)==0)
+ return;
+
+ if(edit) {
+ int newtotkeys= psys_count_keys(psys);
+
+ if(newtotkeys == edit->totkeys)
+ alloc=0;
+ }
+
+ if(alloc) {
+ if(edit) {
+ printf("ParticleEdit exists already! Poke jahka!");
+ PE_free_particle_edit(psys);
+ }
+
+ edit= psys->edit=MEM_callocN(sizeof(ParticleEdit), "PE_create_particle_edit");
+ psys->free_edit= PE_free_particle_edit;
+
+ edit->keys=MEM_callocN(totpart*sizeof(ParticleEditKey*),"ParticleEditKey array");
+
+ LOOP_PARTICLES(i, pa) {
+ key= edit->keys[i]= MEM_callocN(pa->totkey*sizeof(ParticleEditKey),"ParticleEditKeys");
+ for(k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, key++) {
+ key->co= hkey->co;
+ key->time= &hkey->time;
+ key->flag= hkey->editflag;
+ }
+ }
+
+ edit->totkeys= psys_count_keys(psys);
+
+ UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col);
+ UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col);
+ }
+
+ recalc_lengths(psys);
+ recalc_emitter_field(ob, psys);
+ psys_update_world_cos(ob, psys);
+
+ if(alloc) {
+ ParticleUndo_clear(psys);
+ PE_undo_push(scene, "Original");
+ }
+}
+
+static int particle_edit_toggle_poll(bContext *C)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+
+ if(!scene || !ob || ob->id.lib)
+ return 0;
+
+ return (ob->particlesystem.first != NULL);
+}
+
+static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+ ParticleSystem *psys= PE_get_current(scene, ob);
+
+ if(psys==NULL) {
+ psys= ob->particlesystem.first;
+ psys->flag |= PSYS_CURRENT;
+ }
+
+ if(!(G.f & G_PARTICLEEDIT)) {
+ if(psys && psys->part->type == PART_HAIR && psys->flag & PSYS_EDITED) {
+ if(psys_check_enabled(ob, psys)) {
+ if(psys->edit==NULL)
+ PE_create_particle_edit(scene, ob, psys);
+
+ psys_update_world_cos(ob, psys);
+ }
+ }
+
+ G.f |= G_PARTICLEEDIT;
+ toggle_particle_cursor(C, 1);
+ WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_PARTICLE, NULL);
+ }
+ else {
+ G.f &= ~G_PARTICLEEDIT;
+ toggle_particle_cursor(C, 0);
+ WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
+ }
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_particle_edit_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Particle Edit Toggle";
+ ot->idname= "PARTICLE_OT_particle_edit_toggle";
+
+ /* api callbacks */
+ ot->exec= particle_edit_toggle_exec;
+ ot->poll= particle_edit_toggle_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+/************************ set editable operator ************************/
+
+static int set_editable_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+ ParticleSystem *psys= PE_get_current(scene, ob);
+
+ if(psys->flag & PSYS_EDITED) {
+ if(1) { // XXX okee("Lose changes done in particle mode?")) {
+ if(psys->edit)
+ PE_free_particle_edit(psys);
+
+ psys->flag &= ~PSYS_EDITED;
+ psys->recalc |= PSYS_RECALC_HAIR;
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+ }
+ else {
+ if(psys_check_enabled(ob, psys)) {
+ psys->flag |= PSYS_EDITED;
+
+ if(G.f & G_PARTICLEEDIT)
+ PE_create_particle_edit(scene, ob, psys);
+ }
+ else
+ BKE_report(op->reports, RPT_ERROR, "Particle system not enabled, skipping set editable");
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_editable_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Editable";
+ ot->idname= "PARTICLE_OT_editable_set";
+
+ /* api callbacks */
+ ot->exec= set_editable_exec;
+ ot->poll= particle_edit_toggle_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/*********************** change active **************************/
+
+void PE_change_act(void *ob_v, void *act_v)
+{
+ Scene *scene= NULL; // XXX
+ Object *ob= ob_v;
+ ParticleSystem *psys;
+ short act= *((short*)act_v) - 1;
+
+ if((psys=psys_get_current(ob)))
+ psys->flag &= ~PSYS_CURRENT;
+
+ if(act>=0) {
+ if((psys=BLI_findlink(&ob->particlesystem,act))) {
+ psys->flag |= PSYS_CURRENT;
+
+ if(psys_check_enabled(ob, psys)) {
+ if(G.f & G_PARTICLEEDIT && !psys->edit)
+ PE_create_particle_edit(scene, ob, psys);
+ psys_update_world_cos(ob, psys);
+ }
+ }
+ }
+}
+
+void PE_change_act_psys(Scene *scene, Object *ob, ParticleSystem *psys)
+{
+ ParticleSystem *p;
+
+ if((p=psys_get_current(ob)))
+ p->flag &= ~PSYS_CURRENT;
+
+ psys->flag |= PSYS_CURRENT;
+
+ if(psys_check_enabled(ob, psys)) {
+ if(G.f & G_PARTICLEEDIT && !psys->edit)
+ PE_create_particle_edit(scene, ob, psys);
+
+ psys_update_world_cos(ob, psys);
+ }
+}
+
+/*********************** specials menu **************************/
+
+static int specials_menu_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Scene *scene= CTX_data_scene(C);
+ uiMenuItem *head;
+
+ head= uiPupMenuBegin("Specials", 0);
+
+ uiMenuItemO(head, 0, "PARTICLE_OT_rekey");
+ if(scene->selectmode & SCE_SELECT_POINT) {
+ uiMenuItemO(head, 0, "PARTICLE_OT_subdivide");
+ uiMenuItemO(head, 0, "PARTICLE_OT_select_first");
+ uiMenuItemO(head, 0, "PARTICLE_OT_select_last");
+ }
+ uiMenuItemO(head, 0, "PARTICLE_OT_remove_doubles");
+
+ uiPupMenuEnd(C, head);
+
+ return OPERATOR_CANCELLED;
+}
+
+void PARTICLE_OT_specials_menu(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Specials Menu";
+ ot->idname= "PARTICLE_OT_specials_menu";
+
+ /* api callbacks */
+ ot->invoke= specials_menu_invoke;
+ ot->poll= PE_poll;
+}
+
+/**************************** registration **********************************/
+
+void ED_operatortypes_particle(void)
+{
+ WM_operatortype_append(PARTICLE_OT_select_all_toggle);
+ WM_operatortype_append(PARTICLE_OT_select_first);
+ WM_operatortype_append(PARTICLE_OT_select_last);
+ WM_operatortype_append(PARTICLE_OT_select_linked);
+ WM_operatortype_append(PARTICLE_OT_select_less);
+ WM_operatortype_append(PARTICLE_OT_select_more);
+
+ WM_operatortype_append(PARTICLE_OT_hide);
+ WM_operatortype_append(PARTICLE_OT_reveal);
+
+ WM_operatortype_append(PARTICLE_OT_rekey);
+ WM_operatortype_append(PARTICLE_OT_subdivide);
+ WM_operatortype_append(PARTICLE_OT_remove_doubles);
+ WM_operatortype_append(PARTICLE_OT_delete);
+ WM_operatortype_append(PARTICLE_OT_mirror);
+
+ WM_operatortype_append(PARTICLE_OT_brush_set);
+ WM_operatortype_append(PARTICLE_OT_brush_edit);
+ WM_operatortype_append(PARTICLE_OT_brush_radial_control);
+
+ WM_operatortype_append(PARTICLE_OT_specials_menu);
+
+ WM_operatortype_append(PARTICLE_OT_particle_edit_toggle);
+ WM_operatortype_append(PARTICLE_OT_editable_set);
+}
+
+void ED_keymap_particle(wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "Particle", 0, 0);
+
+ WM_keymap_add_item(keymap, "PARTICLE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "PARTICLE_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "PARTICLE_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "PARTICLE_OT_select_linked", LKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "PARTICLE_OT_select_linked", LKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "deselect", 1);
+
+ WM_keymap_add_item(keymap, "PARTICLE_OT_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "PARTICLE_OT_delete", DELKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "PARTICLE_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "PARTICLE_OT_hide", HKEY, KM_PRESS, 0, 0);
+ RNA_enum_set(WM_keymap_add_item(keymap, "PARTICLE_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "unselected", 1);
+
+ WM_keymap_add_item(keymap, "PARTICLE_OT_brush_edit", ACTIONMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "PARTICLE_OT_brush_edit", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(WM_keymap_add_item(keymap, "PARTICLE_OT_brush_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "PARTICLE_OT_brush_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH);
+
+ WM_keymap_add_item(keymap, "PARTICLE_OT_specials_menu", WKEY, KM_PRESS, 0, 0);
+}
+
diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h
new file mode 100644
index 00000000000..e03649575cb
--- /dev/null
+++ b/source/blender/editors/physics/physics_intern.h
@@ -0,0 +1,38 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by Janne Karhu.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_PHYSICS_INTERN_H
+#define ED_PHYSICS_INTERN_H
+
+
+#endif /* ED_PHYSICS_INTERN_H */
+
diff --git a/source/blender/editors/preview/Makefile b/source/blender/editors/preview/Makefile
new file mode 100644
index 00000000000..84514d73570
--- /dev/null
+++ b/source/blender/editors/preview/Makefile
@@ -0,0 +1,57 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_preview
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+CPPFLAGS += -I$(NAN_BMFONT)/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I$(NAN_ELBEEM)/include
+
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../gpu
+CPPFLAGS += -I../../render/extern/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/preview/SConscript b/source/blender/editors/preview/SConscript
new file mode 100644
index 00000000000..dcc80e8c626
--- /dev/null
+++ b/source/blender/editors/preview/SConscript
@@ -0,0 +1,12 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' #/intern/guardedalloc #intern/bmfont ../../gpu'
+incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
+incs += ' ../../blenloader'
+
+env.BlenderLib ( 'bf_editors_preview', sources, Split(incs), [], libtype=['core'], priority=[45] )
diff --git a/source/blender/editors/preview/previewrender.c b/source/blender/editors/preview/previewrender.c
new file mode 100644
index 00000000000..407674163a6
--- /dev/null
+++ b/source/blender/editors/preview/previewrender.c
@@ -0,0 +1,1084 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* global includes */
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BLO_readfile.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "DNA_texture_types.h"
+#include "DNA_world_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_image_types.h"
+#include "DNA_material_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_icons.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_texture.h"
+#include "BKE_material.h"
+#include "BKE_node.h"
+#include "BKE_world.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "PIL_time.h"
+
+#include "RE_pipeline.h"
+
+#include "GPU_material.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_anim_api.h"
+#include "ED_view3d.h"
+
+#include "UI_interface.h"
+
+#include "previewrender_intern.h"
+
+#define PR_XMIN 10
+#define PR_YMIN 5
+#define PR_XMAX 200
+#define PR_YMAX 195
+
+/* XXX */
+static int qtest() {return 0;}
+/* XXX */
+
+typedef struct ShaderPreview {
+ /* from wmJob */
+ void *owner;
+ short *stop, *do_update;
+
+ Scene *scene;
+ ID *id;
+
+ int sizex, sizey;
+ int pr_method;
+} ShaderPreview;
+
+
+static void set_previewrect(ScrArea *sa, RenderInfo *ri)
+{
+ ARegion *ar= NULL; // XXX
+ rctf viewplane;
+
+ BLI_init_rctf(&viewplane, PR_XMIN, PR_XMAX, PR_YMIN, PR_YMAX);
+
+// ui_graphics_to_window_rct(ar->win, &viewplane, &ri->disprect);
+
+ /* correction for gla draw */
+ BLI_translate_rcti(&ri->disprect, -ar->winrct.xmin, -ar->winrct.ymin);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+
+ glaDefine2DArea(&ar->winrct);
+
+ ri->pr_rectx= (ri->disprect.xmax-ri->disprect.xmin);
+ ri->pr_recty= (ri->disprect.ymax-ri->disprect.ymin);
+}
+
+static void end_previewrect(ARegion *ar)
+{
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ // restore viewport / scissor which was set by glaDefine2DArea
+ glViewport(ar->winrct.xmin, ar->winrct.ymin, ar->winx, ar->winy);
+ glScissor(ar->winrct.xmin, ar->winrct.ymin, ar->winx, ar->winy);
+
+}
+
+/* unused now */
+void draw_tex_crop(Tex *tex)
+{
+ rcti rct;
+ int ret= 0;
+
+ if(tex==0) return;
+
+ if(tex->type==TEX_IMAGE) {
+ if(tex->cropxmin==0.0f) ret++;
+ if(tex->cropymin==0.0f) ret++;
+ if(tex->cropxmax==1.0f) ret++;
+ if(tex->cropymax==1.0f) 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);
+ }
+
+}
+
+/* temporal abuse; if id_code is -1 it only does texture.... solve! */
+void BIF_preview_changed(short id_code)
+{
+#if 0
+ ScrArea *sa;
+
+ for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ if(sa->spacetype==SPACE_BUTS) {
+ SpaceButs *sbuts= sa->spacedata.first;
+ if(sbuts->mainb==CONTEXT_SHADING) {
+ int tab= sbuts->tab[CONTEXT_SHADING];
+ if(tab==TAB_SHADING_MAT && (id_code==ID_MA || id_code==ID_TE)) {
+ if (sbuts->ri) sbuts->ri->curtile= 0;
+ addafterqueue(sa->win, RENDERPREVIEW, 1);
+ }
+ else if(tab==TAB_SHADING_TEX && (id_code==ID_TE || id_code==-1)) {
+ if (sbuts->ri) sbuts->ri->curtile= 0;
+ addafterqueue(sa->win, RENDERPREVIEW, 1);
+ }
+ else if(tab==TAB_SHADING_LAMP && (id_code==ID_LA || id_code==ID_TE)) {
+ if (sbuts->ri) sbuts->ri->curtile= 0;
+ addafterqueue(sa->win, RENDERPREVIEW, 1);
+ }
+ else if(tab==TAB_SHADING_WORLD && (id_code==ID_WO || id_code==ID_TE)) {
+ if (sbuts->ri) sbuts->ri->curtile= 0;
+ addafterqueue(sa->win, RENDERPREVIEW, 1);
+ }
+ }
+ else if (sbuts->ri)
+ sbuts->ri->curtile= 0; /* ensure changes always result in re-render when context is restored */
+ }
+ else if(sa->spacetype==SPACE_NODE) {
+ SpaceNode *snode= sa->spacedata.first;
+ if(snode->treetype==NTREE_SHADER && (id_code==ID_MA || id_code==ID_TE)) {
+ snode_tag_dirty(snode);
+ }
+ }
+ else if(sa->spacetype==SPACE_VIEW3D) {
+ View3D *vd= sa->spacedata.first;
+ /* if is has a renderinfo, we consider that reason for signalling */
+ if (vd->ri) {
+ vd->ri->curtile= 0;
+ addafterqueue(sa->win, RENDERPREVIEW, 1);
+ }
+ }
+ }
+
+ if(ELEM4(id_code, ID_MA, ID_TE, ID_LA, ID_WO)) {
+ Object *ob;
+ Material *ma;
+
+ if(id_code == ID_WO) {
+ for(ma=G.main->mat.first; ma; ma=ma->id.next) {
+ if(ma->gpumaterial.first) {
+ GPU_material_free(ma);
+ }
+ }
+ }
+ else if(id_code == ID_LA) {
+ for(ob=G.main->object.first; ob; ob=ob->id.next) {
+ if(ob->gpulamp.first) {
+ GPU_lamp_free(ob);
+ }
+ }
+ } else if(OBACT) {
+ Object *ob = OBACT;
+
+ ma= give_current_material(ob, ob->actcol);
+ if(ma && ma->gpumaterial.first) {
+ GPU_material_free(ma);
+ }
+ }
+ }
+#endif
+}
+
+/* *************************** Preview for buttons *********************** */
+
+static Main *pr_main= NULL;
+
+void ED_preview_init_dbase(void)
+{
+ BlendFileData *bfd;
+ extern int datatoc_preview_blend_size;
+ extern char datatoc_preview_blend[];
+
+ G.fileflags |= G_FILE_NO_UI;
+ bfd= BLO_read_from_memory(datatoc_preview_blend, datatoc_preview_blend_size, NULL);
+ if (bfd) {
+ pr_main= bfd->main;
+
+ MEM_freeN(bfd);
+ }
+ G.fileflags &= ~G_FILE_NO_UI;
+}
+
+void ED_preview_free_dbase(void)
+{
+ if(pr_main)
+ free_main(pr_main);
+}
+
+static Object *find_object(ListBase *lb, const char *name)
+{
+ Object *ob;
+ for(ob= lb->first; ob; ob= ob->id.next)
+ if(strcmp(ob->id.name+2, name)==0)
+ break;
+ return ob;
+}
+
+/* call this with a pointer to initialize preview scene */
+/* call this with NULL to restore assigned ID pointers in preview scene */
+static Scene *preview_prepare_scene(Scene *scene, int id_type, ShaderPreview *sp)
+{
+ Scene *sce;
+ Base *base;
+ ID *id= sp?sp->id:NULL;
+
+ if(pr_main==NULL) return NULL;
+
+ sce= pr_main->scene.first;
+ if(sce) {
+ /* this flag tells render to not execute depsgraph or ipos etc */
+ sce->r.scemode |= R_PREVIEWBUTS;
+ /* set world always back, is used now */
+ sce->world= pr_main->world.first;
+ /* now: exposure copy */
+ if(scene->world) {
+ sce->world->exp= scene->world->exp;
+ sce->world->range= scene->world->range;
+ }
+
+ sce->r.cfra= scene->r.cfra;
+
+ if(id_type==ID_MA) {
+ Material *mat= (Material *)id;
+
+ if(id) {
+ init_render_material(mat, 0, NULL); /* call that retrieves mode_l */
+ end_render_material(mat);
+
+ /* turn on raytracing if needed */
+ if(mat->mode_l & (MA_RAYTRANSP|MA_RAYMIRROR))
+ sce->r.mode |= R_RAYTRACE;
+ if(mat->sss_flag & MA_DIFF_SSS)
+ sce->r.mode |= R_SSS;
+
+ /* turn off fake shadows if needed */
+ /* this only works in a specific case where the preview.blend contains
+ * an object starting with 'c' which has a material linked to it (not the obdata)
+ * and that material has a fake shadow texture in the active texture slot */
+ for(base= sce->base.first; base; base= base->next) {
+ if(base->object->id.name[2]=='c') {
+ Material *shadmat= give_current_material(base->object, base->object->actcol);
+ if(shadmat) {
+ if (mat->mode & MA_SHADBUF) shadmat->septex = 0;
+ else shadmat->septex |= 1;
+ }
+ }
+ }
+
+
+ if(sp->pr_method==PR_ICON_RENDER) {
+ if (mat->mode & MA_HALO) {
+ sce->lay= 1<<MA_FLAT;
+ }
+ else {
+ sce->lay= 1<<MA_SPHERE_A;
+ }
+ }
+ else {
+ sce->lay= 1<<mat->pr_type;
+ if(mat->nodetree)
+ ntreeInitPreview(mat->nodetree, sp->sizex, sp->sizey);
+ }
+ }
+ else {
+ sce->r.mode &= ~(R_OSA|R_RAYTRACE|R_SSS);
+ }
+
+ for(base= sce->base.first; base; base= base->next) {
+ if(base->object->id.name[2]=='p') {
+ if(ELEM4(base->object->type, OB_MESH, OB_CURVE, OB_SURF, OB_MBALL))
+ assign_material(base->object, mat, base->object->actcol);
+ }
+ }
+ }
+ else if(id_type==ID_TE) {
+ Tex *tex= (Tex *)id;
+
+ sce->lay= 1<<MA_TEXTURE;
+
+ for(base= sce->base.first; base; base= base->next) {
+ if(base->object->id.name[2]=='t') {
+ Material *mat= give_current_material(base->object, base->object->actcol);
+ if(mat && mat->mtex[0]) {
+ mat->mtex[0]->tex= tex;
+ /* show alpha in this case */
+ if(tex==NULL || (tex->flag & TEX_PRV_ALPHA)) {
+ mat->mtex[0]->mapto |= MAP_ALPHA;
+ mat->alpha= 0.0f;
+ }
+ else {
+ mat->mtex[0]->mapto &= ~MAP_ALPHA;
+ mat->alpha= 1.0f;
+ }
+ }
+ }
+ }
+ }
+ else if(id_type==ID_LA) {
+ Lamp *la= (Lamp *)id;
+
+ if(la && la->type==LA_SUN && (la->sun_effect_type & LA_SUN_EFFECT_SKY)) {
+ sce->lay= 1<<MA_ATMOS;
+ sce->world= scene->world;
+ sce->camera= (Object *)find_object(&pr_main->object, "CameraAtmo");
+ }
+ else {
+ sce->lay= 1<<MA_LAMP;
+ sce->world= NULL;
+ sce->camera= (Object *)find_object(&pr_main->object, "Camera");
+ }
+ sce->r.mode &= ~R_SHADOW;
+
+ for(base= sce->base.first; base; base= base->next) {
+ if(base->object->id.name[2]=='p') {
+ if(base->object->type==OB_LAMP)
+ base->object->data= la;
+ }
+ }
+ }
+ else if(id_type==ID_WO) {
+ sce->lay= 1<<MA_SKY;
+ sce->world= (World *)id;
+ }
+
+ return sce;
+ }
+
+ return NULL;
+}
+
+void previewrender_progress(void *handle, RenderResult *rr, volatile rcti *renrect)
+{
+ SpaceButs *sbuts= NULL; // XXX
+ RenderLayer *rl;
+ RenderInfo *ri= sbuts->ri;
+ float ofsx, ofsy;
+
+ if(renrect) return;
+
+ rl= rr->layers.first;
+
+ ofsx= ri->disprect.xmin + rr->tilerect.xmin;
+ ofsy= ri->disprect.ymin + rr->tilerect.ymin;
+
+ glDrawBuffer(GL_FRONT);
+ glaDrawPixelsSafe_to32(ofsx, ofsy, rr->rectx, rr->recty, rr->rectx, rl->rectf);
+ bglFlush();
+ glDrawBuffer(GL_BACK);
+}
+
+
+/* called by interface_icons.c, or by BIF_previewrender_buts or by nodes... */
+void BIF_previewrender(Scene *scene, struct ID *id, struct RenderInfo *ri, struct ScrArea *area, int pr_method)
+{
+ SpaceButs *sbuts= NULL; // XXX
+ Render *re;
+ RenderStats *rstats;
+ Scene *sce;
+ int oldx= ri->pr_rectx, oldy= ri->pr_recty;
+ char name [32];
+
+ if(ri->tottile && ri->curtile>=ri->tottile) return;
+
+ /* check for return with a new event */
+ if(pr_method!=PR_ICON_RENDER && qtest()) {
+// if(area)
+// addafterqueue(area->win, RENDERPREVIEW, 1);
+ return;
+ }
+
+ /* get the stuff from the builtin preview dbase */
+// sce= preview_prepare_scene(scene, ri, GS(id->name), id, pr_method);
+ if(sce==NULL) return;
+
+ /* set drawing conditions OK */
+ if(area) {
+ sbuts= area->spacedata.first; /* needed for flag */
+
+ set_previewrect(area, ri); // uses UImat
+
+ /* because preview render size can differs */
+ if(ri->rect && (oldx!=ri->pr_rectx || oldy!=ri->pr_recty)) {
+ MEM_freeN(ri->rect);
+ ri->rect= NULL;
+ ri->curtile= 0;
+ }
+ }
+
+// XXX sprintf(name, "ButsPreview %d", area?area->win:0);
+ re= RE_GetRender(name);
+
+ /* full refreshed render from first tile */
+ if(re==NULL || ri->curtile==0) {
+
+ re= RE_NewRender(name);
+
+ /* handle cases */
+ if(pr_method==PR_DRAW_RENDER) {
+// RE_display_draw_cb(re, previewrender_progress);
+// RE_test_break_cb(re, qtest);
+ sce->r.scemode |= R_NODE_PREVIEW;
+ if(sbuts->flag & SB_PRV_OSA)
+ sce->r.mode |= R_OSA;
+ sce->r.scemode &= ~R_NO_IMAGE_LOAD;
+ }
+ else if(pr_method==PR_DO_RENDER) {
+// RE_test_break_cb(re, qtest);
+ sce->r.scemode |= R_NODE_PREVIEW;
+ sce->r.scemode &= ~R_NO_IMAGE_LOAD;
+ }
+ else { /* PR_ICON_RENDER */
+ sce->r.scemode &= ~R_NODE_PREVIEW;
+ sce->r.scemode |= R_NO_IMAGE_LOAD;
+ }
+
+ /* allocates render result */
+ RE_InitState(re, NULL, &sce->r, ri->pr_rectx, ri->pr_recty, NULL);
+
+ /* enforce preview image clear */
+ if(GS(id->name)==ID_MA) {
+ Material *ma= (Material *)id;
+ ntreeClearPreview(ma->nodetree);
+ }
+ }
+ /* entire cycle for render engine */
+ RE_SetCamera(re, sce->camera);
+ RE_Database_FromScene(re, sce, 1);
+ RE_TileProcessor(re, ri->curtile, 0); // actual render engine
+ RE_Database_Free(re);
+
+ /* handle results */
+ if(pr_method==PR_ICON_RENDER) {
+ if(ri->rect==NULL)
+ ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
+ RE_ResultGet32(re, ri->rect);
+ }
+ else {
+ rstats= RE_GetStats(re);
+
+ if(rstats->partsdone!=ri->curtile) {
+ if(ri->rect==NULL)
+ ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
+ RE_ResultGet32(re, ri->rect);
+ }
+
+ if(rstats->totpart==rstats->partsdone && rstats->partsdone) {
+ // allqueues
+ }
+ else {
+// if(pr_method==PR_DRAW_RENDER && qtest())
+// addafterqueue(area->win, RENDERPREVIEW, 1);
+ }
+
+ ri->curtile= rstats->partsdone;
+ ri->tottile= rstats->totpart;
+ }
+
+ /* unassign the pointers, reset vars */
+// preview_prepare_scene(scene, ri, GS(id->name), NULL, 0);
+
+}
+
+
+/* afterqueue call */
+void BIF_previewrender_buts(Scene *scene, SpaceButs *sbuts)
+{
+// ScrArea *sa= NULL; // XXX
+ ARegion *ar= NULL; // XXX
+ uiBlock *block;
+ struct ID* id = 0;
+// struct ID* idfrom = 0;
+ struct ID* idshow = 0;
+ Object *ob;
+
+ if (!sbuts->ri) return;
+
+
+// block= uiFindOpenPanelBlockName(&sa->uiblocks, "Preview");
+ if(block==NULL) return;
+
+ ob= ((scene->basact)? (scene->basact)->object: 0);
+
+ /* we cant trust this global lockpoin.. for example with headerless window */
+// buttons_active_id(&id, &idfrom);
+ sbuts->lockpoin= id;
+
+ if(sbuts->mainb==CONTEXT_SHADING) {
+ int tab= sbuts->tab[CONTEXT_SHADING];
+
+ if(tab==TAB_SHADING_MAT)
+ idshow = sbuts->lockpoin;
+ else if(tab==TAB_SHADING_TEX)
+ idshow = sbuts->lockpoin;
+ else if(tab==TAB_SHADING_LAMP) {
+ if(ob && ob->type==OB_LAMP) idshow= ob->data;
+ }
+ else if(tab==TAB_SHADING_WORLD)
+ idshow = sbuts->lockpoin;
+ }
+ else if(sbuts->mainb==CONTEXT_OBJECT) {
+ if(ob && ob->type==OB_LAMP) idshow = ob->data;
+ }
+
+ if (idshow) {
+ BKE_icon_changed(BKE_icon_getid(idshow));
+// uiPanelPush(block);
+// BIF_previewrender(scene, idshow, sbuts->ri, sbuts->area, PR_DRAW_RENDER);
+// uiPanelPop(block);
+ end_previewrect(ar);
+ }
+ else {
+ /* no active block to draw. But we do draw black if possible */
+ if(sbuts->ri->rect) {
+ memset(sbuts->ri->rect, 0, sizeof(int)*sbuts->ri->pr_rectx*sbuts->ri->pr_recty);
+ sbuts->ri->tottile= 10000;
+// addqueue(sa->win, REDRAW, 1);
+ }
+ return;
+ }
+}
+
+
+/* is panel callback, supposed to be called with correct panel offset matrix */
+void BIF_previewdraw(ScrArea *sa, uiBlock *block)
+{
+ ARegion *ar= NULL; // XXX
+ SpaceButs *sbuts= sa->spacedata.first;
+ short id_code= 0;
+
+ if(sbuts->lockpoin) {
+ ID *id= sbuts->lockpoin;
+ id_code= GS(id->name);
+ }
+
+ if (!sbuts->ri) {
+ sbuts->ri= MEM_callocN(sizeof(RenderInfo), "butsrenderinfo");
+ sbuts->ri->tottile = 10000;
+ }
+
+ if (sbuts->ri->rect==NULL) BIF_preview_changed(id_code);
+ else {
+ RenderInfo *ri= sbuts->ri;
+ int oldx= ri->pr_rectx, oldy= ri->pr_recty;
+
+ /* we now do scalable previews! */
+ set_previewrect(sa, ri);
+ if( ABS(oldx-ri->pr_rectx)<2 && ABS(oldy-ri->pr_recty)<2 ) {
+ /* restore old values for drawing! */
+ ri->pr_rectx= oldx;
+ ri->pr_recty= oldy;
+ glaDrawPixelsSafe(ri->disprect.xmin, ri->disprect.ymin, ri->pr_rectx, ri->pr_recty, ri->pr_rectx, GL_RGBA, GL_UNSIGNED_BYTE, ri->rect);
+ }
+ else {
+ MEM_freeN(ri->rect);
+ ri->rect= NULL;
+ sbuts->ri->curtile= 0;
+ }
+ end_previewrect(ar);
+ }
+ if(sbuts->ri->curtile==0) BIF_preview_changed(id_code);
+
+}
+
+/* *************************** Preview for 3d window *********************** */
+
+void view3d_previewrender_progress(RenderResult *rr, volatile rcti *renrect)
+{
+// ScrArea *sa= NULL; // XXX
+// View3D *v3d= NULL; // XXX
+ RenderLayer *rl;
+ int ofsx, ofsy;
+
+ if(renrect) return;
+
+ rl= rr->layers.first;
+
+ /* this case is when we render envmaps... */
+// if(rr->rectx > v3d->ri->pr_rectx || rr->recty > v3d->ri->pr_recty)
+// return;
+
+// ofsx= v3d->ri->disprect.xmin + rr->tilerect.xmin;
+// ofsy= v3d->ri->disprect.ymin + rr->tilerect.ymin;
+
+ glDrawBuffer(GL_FRONT);
+// glaDefine2DArea(&sa->winrct);
+ glaDrawPixelsSafe_to32(ofsx, ofsy, rr->rectx, rr->recty, rr->rectx, rl->rectf);
+ bglFlush();
+ glDrawBuffer(GL_BACK);
+
+}
+
+void BIF_view3d_previewrender_signal(ScrArea *sa, short signal)
+{
+#if 0
+ View3D *v3d= sa->spacedata.first;
+
+ /* this can be called from other window... solve! */
+ if(sa->spacetype!=SPACE_VIEW3D)
+ return; // XXX
+
+ if(v3d && v3d->ri) {
+ RenderInfo *ri= v3d->ri;
+ ri->status &= ~signal;
+ ri->curtile= 0;
+ //printf("preview signal %d\n", signal);
+ if(ri->re && (signal & PR_DBASE))
+ RE_Database_Free(ri->re);
+
+// addafterqueue(sa->win, RENDERPREVIEW, 1);
+ }
+#endif
+}
+
+void BIF_view3d_previewrender_free(View3D *v3d)
+{
+#if 0
+ if(v3d->ri) {
+ RenderInfo *ri= v3d->ri;
+ if(ri->re) {
+// printf("free render\n");
+ RE_Database_Free(ri->re);
+ RE_FreeRender(ri->re);
+ ri->re= NULL;
+ }
+ if (v3d->ri->rect) MEM_freeN(v3d->ri->rect);
+ MEM_freeN(v3d->ri);
+ v3d->ri= NULL;
+ }
+#endif
+}
+
+/* returns 1 if OK, do not call while in panel space! */
+static int view3d_previewrender_get_rects(ScrArea *sa, rctf *viewplane, RenderInfo *ri, float *clipsta, float *clipend, int *ortho, float *pixsize)
+{
+ View3D *v3d= NULL; // XXX
+ RegionView3D *rv3d= NULL; // XXX
+ int rectx, recty;
+// uiBlock *block;
+
+// block= uiFindOpenPanelBlockName(&sa->uiblocks, "Preview");
+// if(block==NULL) return 0;
+
+ /* calculate preview rect size */
+// BLI_init_rctf(viewplane, 15.0f, (block->maxx - block->minx)-15.0f, 15.0f, (block->maxy - block->miny)-15.0f);
+// uiPanelPush(block);
+// ui_graphics_to_window_rct(sa->win, viewplane, &ri->disprect);
+// uiPanelPop(block);
+
+ /* correction for gla draw */
+// BLI_translate_rcti(&ri->disprect, -sa->winrct.xmin, -sa->winrct.ymin);
+
+ *ortho= get_view3d_viewplane(v3d, rv3d, sa->winx, sa->winy, viewplane, clipsta, clipend, pixsize);
+
+ rectx= ri->disprect.xmax - ri->disprect.xmin;
+ recty= ri->disprect.ymax - ri->disprect.ymin;
+
+ if(rectx<4 || recty<4) return 0;
+
+ if(ri->rect && (rectx!=ri->pr_rectx || recty!=ri->pr_recty)) {
+ MEM_freeN(ri->rect);
+ ri->rect= NULL;
+ ri->curtile= 0;
+ printf("changed size\n");
+ }
+ ri->pr_rectx= rectx;
+ ri->pr_recty= recty;
+
+ return 1;
+}
+
+/* called before a panel gets moved/scaled, makes sure we can see through */
+void BIF_view3d_previewrender_clear(ScrArea *sa)
+{
+#if 0
+ View3D *v3d= sa->spacedata.first;
+
+ if(v3d->ri) {
+ RenderInfo *ri= v3d->ri;
+ ri->curtile= 0;
+ if(ri->rect)
+ MEM_freeN(ri->rect);
+ ri->rect= NULL;
+ }
+#endif
+}
+
+/* afterqueue call */
+void BIF_view3d_previewrender(Scene *scene, ScrArea *sa)
+{
+ bContext *C= NULL;
+ View3D *v3d= sa->spacedata.first;
+ RegionView3D *rv3d= NULL; // XXX
+ Render *re;
+ RenderInfo *ri; /* preview struct! */
+ RenderStats *rstats;
+ RenderData rdata;
+ rctf viewplane;
+ float clipsta, clipend, pixsize;
+ int orth;
+
+ /* first get the render info right */
+// if (!v3d->ri) {
+// ri= v3d->ri= MEM_callocN(sizeof(RenderInfo), "butsrenderinfo");
+// ri->tottile= 10000;
+// }
+// ri= v3d->ri;
+
+ if(0==view3d_previewrender_get_rects(sa, &viewplane, ri, &clipsta, &clipend, &orth, &pixsize))
+ return;
+
+ /* render is finished, so return */
+ if(ri->tottile && ri->curtile>=ri->tottile) return;
+
+ /* or return with a new event */
+ if(qtest()) {
+// addafterqueue(sa->win, RENDERPREVIEW, 1);
+ return;
+ }
+ //printf("Enter previewrender\n");
+ /* ok, are we rendering all over? */
+ if(ri->re==NULL) {
+ char name[32];
+
+ ri->status= 0;
+
+ sprintf(name, "View3dPreview %p", sa);
+ re= ri->re= RE_NewRender(name);
+ //RE_display_draw_cb(re, view3d_previewrender_progress);
+ //RE_stats_draw_cb(re, view3d_previewrender_stats);
+ //RE_test_break_cb(re, qtest);
+
+ /* no osa, blur, seq, layers, etc for preview render */
+ rdata= scene->r;
+ rdata.mode &= ~(R_OSA|R_MBLUR);
+ rdata.scemode &= ~(R_DOSEQ|R_DOCOMP|R_FREE_IMAGE);
+ rdata.layers.first= rdata.layers.last= NULL;
+ rdata.renderer= R_INTERN;
+
+ RE_InitState(re, NULL, &rdata, sa->winx, sa->winy, &ri->disprect);
+
+ if(orth)
+ RE_SetOrtho(re, &viewplane, clipsta, clipend);
+ else
+ RE_SetWindow(re, &viewplane, clipsta, clipend);
+ RE_SetPixelSize(re, pixsize);
+
+ /* until here are no escapes */
+ ri->status |= PR_DISPRECT;
+ ri->curtile= 0;
+ //printf("new render\n");
+ }
+
+ re= ri->re;
+
+ PIL_sleep_ms(100); /* wait 0.1 second if theres really no event... */
+ if(qtest()==0) {
+
+ /* check status */
+ if((ri->status & PR_DISPRECT)==0) {
+ RE_SetDispRect(ri->re, &ri->disprect);
+ if(orth)
+ RE_SetOrtho(ri->re, &viewplane, clipsta, clipend);
+ else
+ RE_SetWindow(ri->re, &viewplane, clipsta, clipend);
+ RE_SetPixelSize(re, pixsize);
+ ri->status |= PR_DISPRECT;
+ ri->curtile= 0;
+ //printf("disprect update\n");
+ }
+ if((ri->status & PR_DBASE)==0) {
+ unsigned int lay= scene->lay;
+
+ RE_SetView(re, rv3d->viewmat);
+
+ /* allow localview render for objects with lights in normal layers */
+ if(v3d->lay & 0xFF000000)
+ scene->lay |= v3d->lay;
+ else scene->lay= v3d->lay;
+
+ RE_Database_FromScene(re, scene, 0); // 0= dont use camera view
+ scene->lay= lay;
+
+ rstats= RE_GetStats(re);
+ if(rstats->convertdone)
+ ri->status |= PR_DBASE|PR_PROJECTED|PR_ROTATED;
+ ri->curtile= 0;
+
+ /* database can have created render-resol data... */
+ if(rstats->convertdone)
+ ED_anim_dag_flush_update(C); // <--- only current scene XXX
+
+ //printf("dbase update\n");
+ }
+ if((ri->status & PR_PROJECTED)==0) {
+ if(ri->status & PR_DBASE) {
+ if(orth)
+ RE_SetOrtho(ri->re, &viewplane, clipsta, clipend);
+ else
+ RE_SetWindow(ri->re, &viewplane, clipsta, clipend);
+ RE_DataBase_ApplyWindow(re);
+ ri->status |= PR_PROJECTED;
+ }
+ ri->curtile= 0;
+ //printf("project update\n");
+ }
+
+ /* OK, can we enter render code? */
+ if(ri->status==(PR_DISPRECT|PR_DBASE|PR_PROJECTED|PR_ROTATED)) {
+ //printf("curtile %d tottile %d\n", ri->curtile, ri->tottile);
+ RE_TileProcessor(ri->re, ri->curtile, 0);
+
+ if(ri->rect==NULL)
+ ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "preview view3d rect");
+
+ RE_ResultGet32(ri->re, ri->rect);
+ }
+
+ rstats= RE_GetStats(ri->re);
+// if(rstats->totpart==rstats->partsdone && rstats->partsdone)
+// addqueue(sa->win, REDRAW, 1);
+// else
+// addafterqueue(sa->win, RENDERPREVIEW, 1);
+
+ ri->curtile= rstats->partsdone;
+ ri->tottile= rstats->totpart;
+ }
+ else {
+// addafterqueue(sa->win, RENDERPREVIEW, 1);
+ }
+
+ //printf("\n");
+}
+
+/* in panel space! */
+static void view3d_previewdraw_rect(ScrArea *sa, uiBlock *block, RenderInfo *ri)
+{
+// rctf dispf;
+
+ if(ri->rect==NULL)
+ return;
+
+// BLI_init_rctf(&dispf, 15.0f, (block->maxx - block->minx)-15.0f, 15.0f, (block->maxy - block->miny)-15.0f);
+// ui_graphics_to_window_rct(sa->win, &dispf, &ri->disprect);
+
+ /* correction for gla draw */
+// BLI_translate_rcti(&ri->disprect, -sa->winrct.xmin, -sa->winrct.ymin);
+
+ /* when panel scale changed, free rect */
+ if(ri->disprect.xmax-ri->disprect.xmin != ri->pr_rectx ||
+ ri->disprect.ymax-ri->disprect.ymin != ri->pr_recty) {
+ MEM_freeN(ri->rect);
+ ri->rect= NULL;
+ }
+ else {
+// glaDefine2DArea(&sa->winrct);
+ glaDrawPixelsSafe(ri->disprect.xmin, ri->disprect.ymin, ri->pr_rectx, ri->pr_recty, ri->pr_rectx, GL_RGBA, GL_UNSIGNED_BYTE, ri->rect);
+ }
+}
+
+/* is panel callback, supposed to be called with correct panel offset matrix */
+void BIF_view3d_previewdraw(struct ScrArea *sa, struct uiBlock *block)
+{
+ RegionView3D *rv3d= NULL;
+
+// if (v3d->ri==NULL || v3d->ri->rect==NULL)
+// addafterqueue(sa->win, RENDERPREVIEW, 1);
+// else {
+ view3d_previewdraw_rect(sa, block, rv3d->ri);
+// if(v3d->ri->curtile==0)
+// addafterqueue(sa->win, RENDERPREVIEW, 1);
+// }
+}
+
+
+/* **************************** New preview system ****************** */
+
+/* called by renderer, sets job update value */
+static void shader_preview_draw(void *spv, RenderResult *rr, volatile struct rcti *rect)
+{
+ ShaderPreview *sp= spv;
+
+ *(sp->do_update)= 1;
+}
+
+/* called by renderer, checks job value */
+static int shader_preview_break(void *spv)
+{
+ ShaderPreview *sp= spv;
+
+ return *(sp->stop);
+}
+
+
+static void shader_preview_startjob(void *customdata, short *stop, short *do_update)
+{
+ ShaderPreview *sp= customdata;
+ Render *re;
+ Scene *sce;
+ char name [32];
+
+ sp->stop= stop;
+ sp->do_update= do_update;
+
+ /* get the stuff from the builtin preview dbase */
+ sce= preview_prepare_scene(sp->scene, GS(sp->id->name), sp);
+ if(sce==NULL) return;
+
+ sprintf(name, "Preview %p", sp->owner);
+ re= RE_GetRender(name);
+
+ /* full refreshed render from first tile */
+ if(re==NULL) {
+ re= RE_NewRender(name);
+
+ /* sce->r gets copied in RE_InitState! */
+ if(sp->pr_method==PR_DO_RENDER) {
+ sce->r.scemode |= R_NODE_PREVIEW;
+ sce->r.scemode &= ~R_NO_IMAGE_LOAD;
+ }
+ else { /* PR_ICON_RENDER */
+ sce->r.scemode &= ~R_NODE_PREVIEW;
+ sce->r.scemode |= R_NO_IMAGE_LOAD;
+ }
+
+ /* allocates render result */
+ RE_InitState(re, NULL, &sce->r, sp->sizex, sp->sizey, NULL);
+ }
+
+ /* callbacs are cleared on GetRender() */
+ if(sp->pr_method==PR_DO_RENDER) {
+ RE_display_draw_cb(re, sp, shader_preview_draw);
+ RE_test_break_cb(re, sp, shader_preview_break);
+ }
+
+ /* entire cycle for render engine */
+ RE_SetCamera(re, sce->camera);
+ RE_Database_FromScene(re, sce, 1);
+ RE_TileProcessor(re, 0, 0); // actual render engine
+ RE_Database_Free(re);
+
+ *do_update= 1;
+
+ /* handle results */
+ if(sp->pr_method==PR_ICON_RENDER) {
+ //if(ri->rect==NULL)
+ // ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
+ //RE_ResultGet32(re, ri->rect);
+ }
+
+ /* unassign the pointers, reset vars */
+ preview_prepare_scene(sp->scene, GS(sp->id->name), NULL);
+
+}
+
+static void shader_preview_free(void *customdata)
+{
+ ShaderPreview *sp= customdata;
+
+ MEM_freeN(sp);
+}
+
+void ED_preview_shader_job(const bContext *C, void *owner, ID *id, int sizex, int sizey)
+{
+ wmJob *steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner);
+ ShaderPreview *sp= MEM_callocN(sizeof(ShaderPreview), "shader preview");
+
+ /* customdata for preview thread */
+ sp->scene= CTX_data_scene(C);
+ sp->owner= owner;
+ sp->sizex= sizex;
+ sp->sizey= sizey;
+ sp->pr_method= PR_DO_RENDER;
+ sp->id = id;
+
+ /* setup job */
+ WM_jobs_customdata(steve, sp, shader_preview_free);
+ WM_jobs_timer(steve, 0.1, NC_MATERIAL, NC_MATERIAL);
+ WM_jobs_callbacks(steve, shader_preview_startjob, NULL, NULL);
+
+ WM_jobs_start(steve);
+}
+
+
diff --git a/source/blender/editors/preview/previewrender_intern.h b/source/blender/editors/preview/previewrender_intern.h
new file mode 100644
index 00000000000..7d42727914b
--- /dev/null
+++ b/source/blender/editors/preview/previewrender_intern.h
@@ -0,0 +1,69 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef PREVIEWRENDER_INTERN_H
+#define PREVIEWRENDER_INTERN_H
+
+/* internal exports only */
+
+
+typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
+
+/* stores rendered preview - is also used for icons */
+typedef struct RenderInfo {
+ int pr_rectx;
+ int pr_recty;
+ short curtile, tottile, status;
+ rcti disprect; /* storage for view3d preview rect */
+ unsigned int* rect;
+ struct Render *re; /* persistant render */
+} RenderInfo;
+
+/* ri->status */
+#define PR_DBASE 1
+#define PR_DISPRECT 2
+#define PR_PROJECTED 4
+#define PR_ROTATED 8
+
+/* Render the preview
+
+pr_method:
+- PR_DRAW_RENDER: preview is rendered and drawn, as indicated by called context (buttons panel)
+- PR_ICON_RENDER: the preview is not drawn and the function is not dynamic,
+ so no events are processed. Hopefully fast enough for at least 32x32
+- PR_DO_RENDER: preview is rendered, not drawn, but events are processed for afterqueue,
+ in use for node editor now.
+ */
+
+#define PR_DRAW_RENDER 0
+#define PR_ICON_RENDER 1
+#define PR_DO_RENDER 2
+
+
+#endif /* PREVIEWRENDER_INTERN_H */
+
diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt
new file mode 100644
index 00000000000..42480f65268
--- /dev/null
+++ b/source/blender/editors/screen/CMakeLists.txt
@@ -0,0 +1,83 @@
+# $Id: CMakeLists.txt 12931 2007-12-17 18:20:48Z theeth $
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+FILE(GLOB SRC */*.c)
+
+SET(INC ../../windowmanager
+ ../../editors/include
+ ../../../../intern/guardedalloc ../../../../intern/memutil
+ ../../blenlib ../../makesdna ../../makesrna ../../blenkernel
+ ../../include ../../../../intern/bmfont ../../imbuf
+ ../../render/extern/include ../../../../intern/bsp/extern
+ ../../radiosity/extern/include
+ ../../../intern/decimation/extern ../../blenloader
+ ../../../kernel/gen_system ../../../../intern/SoundSystem ../../readstreamglue
+ ../../quicktime ../../../../intern/elbeem/extern
+ ../../../../intern/ghost ../../../../intern/opennl/extern
+ ../../nodes
+ ${SDL_INC}
+)
+
+IF(WITH_INTERNATIONAL)
+ SET(INC ${INC} ../../ftfont)
+ ADD_DEFINITIONS(-DINTERNATIONAL)
+ ADD_DEFINITIONS(-DFTGL_STATIC_LIBRARY)
+ENDIF(WITH_INTERNATIONAL)
+
+IF(WITH_OPENEXR)
+ ADD_DEFINITIONS(-DWITH_OPENEXR)
+ENDIF(WITH_OPENEXR)
+
+IF(WITH_QUICKTIME)
+ SET(INC ${INC} ${QUICKTIME_INC})
+ ADD_DEFINITIONS(-DWITH_QUICKTIME)
+ENDIF(WITH_QUICKTIME)
+
+IF(WITH_FFMPEG)
+ SET(INC ${INC} ${FFMPEG_INC})
+ ADD_DEFINITIONS(-DWITH_FFMPEG)
+ENDIF(WITH_FFMPEG)
+
+IF(WITH_PYTHON)
+ SET(INC ${INC} ../../python ${PYTHON_INC})
+ELSE(WITH_PYTHON)
+ ADD_DEFINITIONS(-DDISABLE_PYTHON)
+ENDIF(WITH_PYTHON)
+
+IF(WIN32)
+ SET(INC ${INC} ${PTHREADS_INC})
+ENDIF(WIN32)
+
+# TODO buildinfo
+IF(BF_BUILDINFO)
+ ADD_DEFINITIONS(-DNAN_BUILDINFO)
+ENDIF(BF_BUILDINFO)
+
+BLENDERLIB_NOLIST(bf_editors "${SRC}" "${INC}")
+
diff --git a/source/blender/editors/screen/Makefile b/source/blender/editors/screen/Makefile
new file mode 100644
index 00000000000..d18d15d00d9
--- /dev/null
+++ b/source/blender/editors/screen/Makefile
@@ -0,0 +1,56 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_screen
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_BMFONT)/include
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I../../render/extern/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/screen/SConscript b/source/blender/editors/screen/SConscript
new file mode 100644
index 00000000000..c291533790a
--- /dev/null
+++ b/source/blender/editors/screen/SConscript
@@ -0,0 +1,16 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../blenloader ../../windowmanager ../../python ../../makesrna'
+incs += ' ../../render/extern/include'
+incs += ' #/intern/guardedalloc #/extern/glew/include #intern/bmfont'
+
+defs = ''
+
+if not env['WITH_BF_PYTHON']:
+ defs += 'DISABLE_PYTHON'
+
+env.BlenderLib ( 'bf_editors_screen', sources, Split(incs), Split(defs), libtype=['core'], priority=[105] )
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
new file mode 100644
index 00000000000..54775c4e5ab
--- /dev/null
+++ b/source/blender/editors/screen/area.c
@@ -0,0 +1,910 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "wm_subwindow.h"
+
+#include "ED_screen.h"
+#include "ED_screen_types.h"
+#include "ED_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "BMF_Api.h"
+
+#ifndef DISABLE_PYTHON
+#include "BPY_extern.h"
+#endif
+
+#include "screen_intern.h"
+
+/* general area and region code */
+
+static void region_draw_emboss(ARegion *ar)
+{
+ short winx, winy;
+
+ winx= ar->winrct.xmax-ar->winrct.xmin;
+ winy= ar->winrct.ymax-ar->winrct.ymin;
+
+ /* set transp line */
+ glEnable( GL_BLEND );
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+
+ /* right */
+ glColor4ub(0,0,0, 50);
+ sdrawline(winx, 0, winx, winy);
+
+ /* bottom */
+ glColor4ub(0,0,0, 80);
+ sdrawline(0, 0, winx, 0);
+
+ /* top */
+ glColor4ub(255,255,255, 60);
+ sdrawline(0, winy, winx, winy);
+
+ /* left */
+ glColor4ub(255,255,255, 50);
+ sdrawline(0, 0, 0, winy);
+
+ glDisable( GL_BLEND );
+}
+
+void ED_region_pixelspace(ARegion *ar)
+{
+ int width= ar->winrct.xmax-ar->winrct.xmin+1;
+ int height= ar->winrct.ymax-ar->winrct.ymin+1;
+
+ wmOrtho2(-0.375, (float)width-0.375, -0.375, (float)height-0.375);
+ wmLoadIdentity();
+}
+
+/* only exported for WM */
+void ED_region_do_listen(ARegion *ar, wmNotifier *note)
+{
+ /* generic notes first */
+ switch(note->category) {
+ case NC_WM:
+ if(note->data==ND_FILEREAD)
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_WINDOW:
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_SCREEN:
+ if(note->action==NA_EDITED)
+ ED_region_tag_redraw(ar);
+ /* pass on */
+ default:
+ if(ar->type && ar->type->listener)
+ ar->type->listener(ar, note);
+ }
+}
+
+/* only exported for WM */
+void ED_area_do_listen(ScrArea *sa, wmNotifier *note)
+{
+ /* no generic notes? */
+ if(sa->type && sa->type->listener) {
+ sa->type->listener(sa, note);
+ }
+}
+
+/* only exported for WM */
+void ED_area_do_refresh(bContext *C, ScrArea *sa)
+{
+ /* no generic notes? */
+ if(sa->type && sa->type->refresh) {
+ sa->type->refresh(C, sa);
+ }
+ sa->do_refresh= 0;
+}
+
+/* based on screen region draw tags, set draw tags in azones, and future region tabs etc */
+/* only exported for WM */
+void ED_area_overdraw_flush(bContext *C, ScrArea *sa, ARegion *ar)
+{
+ AZone *az;
+
+ for(az= sa->actionzones.first; az; az= az->next) {
+ int xs= (az->x1+az->x2)/2, ys= (az->y1+az->y2)/2;
+
+ /* test if inside */
+ if(BLI_in_rcti(&ar->winrct, xs, ys)) {
+ az->do_draw= 1;
+ }
+ }
+}
+
+/* only exported for WM */
+void ED_area_overdraw(bContext *C)
+{
+ wmWindow *win= CTX_wm_window(C);
+ bScreen *screen= CTX_wm_screen(C);
+ ScrArea *sa;
+
+ /* Draw AZones, in screenspace */
+ wmSubWindowSet(win, screen->mainwin);
+
+ glEnable( GL_BLEND );
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+
+ for(sa= screen->areabase.first; sa; sa= sa->next) {
+ AZone *az;
+ for(az= sa->actionzones.first; az; az= az->next) {
+ if(az->do_draw) {
+ if(az->type==AZONE_TRI) {
+ glColor4ub(0, 0, 0, 70);
+ sdrawtrifill(az->x1, az->y1, az->x2, az->y2);
+ }
+ az->do_draw= 0;
+ }
+ }
+ }
+ glDisable( GL_BLEND );
+
+}
+
+/* only exported for WM */
+void ED_region_do_draw(bContext *C, ARegion *ar)
+{
+ wmWindow *win= CTX_wm_window(C);
+ ScrArea *sa= CTX_wm_area(C);
+ ARegionType *at= ar->type;
+
+ /* if no partial draw rect set, full rect */
+ if(ar->drawrct.xmin == ar->drawrct.xmax)
+ ar->drawrct= ar->winrct;
+
+ /* extra clip for safety */
+ ar->drawrct.xmin= MAX2(ar->winrct.xmin, ar->drawrct.xmin);
+ ar->drawrct.ymin= MAX2(ar->winrct.ymin, ar->drawrct.ymin);
+ ar->drawrct.xmax= MIN2(ar->winrct.xmax, ar->drawrct.xmax);
+ ar->drawrct.ymax= MIN2(ar->winrct.ymax, ar->drawrct.ymax);
+
+ /* note; this sets state, so we can use wmOrtho and friends */
+ wmSubWindowScissorSet(win, ar->swinid, &ar->drawrct);
+
+ /* optional header info instead? */
+ if(ar->headerstr) {
+ float col[3];
+ UI_SetTheme(sa);
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ UI_ThemeColor(TH_MENU_TEXT);
+ glRasterPos2i(20, 6);
+ BMF_DrawString(G.font, ar->headerstr);
+ }
+ else if(at->draw) {
+ UI_SetTheme(sa);
+ at->draw(C, ar);
+ UI_SetTheme(NULL);
+ }
+
+ if(sa)
+ region_draw_emboss(ar);
+
+ uiFreeInactiveBlocks(C, &ar->uiblocks);
+
+ /* XXX test: add convention to end regions always in pixel space, for drawing of borders/gestures etc */
+ ED_region_pixelspace(ar);
+
+ ar->do_draw= 0;
+ memset(&ar->drawrct, 0, sizeof(ar->drawrct));
+}
+
+/* **********************************
+ maybe silly, but let's try for now
+ to keep these tags protected
+ ********************************** */
+
+void ED_region_tag_redraw(ARegion *ar)
+{
+ if(ar) {
+ /* zero region means full region redraw */
+ ar->do_draw= 1;
+ memset(&ar->drawrct, 0, sizeof(ar->drawrct));
+ }
+}
+
+void ED_region_tag_redraw_partial(ARegion *ar, rcti *rct)
+{
+ if(ar) {
+ if(!ar->do_draw) {
+ /* no redraw set yet, set partial region */
+ ar->do_draw= 1;
+ ar->drawrct= *rct;
+ }
+ else if(ar->drawrct.xmin != ar->drawrct.xmax) {
+ /* partial redraw already set, expand region */
+ ar->drawrct.xmin= MIN2(ar->drawrct.xmin, rct->xmin);
+ ar->drawrct.ymin= MIN2(ar->drawrct.ymin, rct->ymin);
+ ar->drawrct.xmax= MAX2(ar->drawrct.xmax, rct->xmax);
+ ar->drawrct.ymax= MAX2(ar->drawrct.ymax, rct->ymax);
+ }
+ }
+}
+
+void ED_area_tag_redraw(ScrArea *sa)
+{
+ ARegion *ar;
+
+ if(sa)
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ ED_region_tag_redraw(ar);
+}
+
+void ED_area_tag_refresh(ScrArea *sa)
+{
+ if(sa)
+ sa->do_refresh= 1;
+}
+
+/* *************************************************************** */
+
+/* use NULL to disable it */
+void ED_area_headerprint(ScrArea *sa, const char *str)
+{
+ ARegion *ar;
+
+ for(ar= sa->regionbase.first; ar; ar= ar->next) {
+ if(ar->regiontype==RGN_TYPE_HEADER) {
+ if(str) {
+ if(ar->headerstr==NULL)
+ ar->headerstr= MEM_mallocN(256, "headerprint");
+ BLI_strncpy(ar->headerstr, str, 256);
+ }
+ else if(ar->headerstr) {
+ MEM_freeN(ar->headerstr);
+ ar->headerstr= NULL;
+ }
+ ED_region_tag_redraw(ar);
+ }
+ }
+}
+
+/* *************************************************************** */
+
+/* dir is direction to check, not the splitting edge direction! */
+static int rct_fits(rcti *rect, char dir, int size)
+{
+ if(dir=='h') {
+ return rect->xmax-rect->xmin - size;
+ }
+ else { // 'v'
+ return rect->ymax-rect->ymin - size;
+ }
+}
+
+static void region_rect_recursive(ARegion *ar, rcti *remainder, int quad)
+{
+ rcti *remainder_prev= remainder;
+ int prefsizex, prefsizey;
+ int alignment;
+
+ if(ar==NULL)
+ return;
+
+ BLI_init_rcti(&ar->winrct, 0, 0, 0, 0);
+
+ /* for test; allow split of previously defined region */
+ if(ar->alignment & RGN_SPLIT_PREV)
+ if(ar->prev)
+ remainder= &ar->prev->winrct;
+
+ alignment = ar->alignment & ~RGN_SPLIT_PREV;
+
+ /* clear state flags first */
+ ar->flag &= ~RGN_FLAG_TOO_SMALL;
+ /* user errors */
+ if(ar->next==NULL && alignment!=RGN_ALIGN_QSPLIT)
+ alignment= RGN_ALIGN_NONE;
+
+ prefsizex= ar->type->minsizex;
+ prefsizey= ar->type->minsizey;
+
+ /* hidden is user flag */
+ if(ar->flag & RGN_FLAG_HIDDEN);
+ /* XXX floating area region, not handled yet here */
+ else if(alignment == RGN_ALIGN_FLOAT);
+ /* remainder is too small for any usage */
+ else if( rct_fits(remainder, 'v', 1)<0 || rct_fits(remainder, 'h', 1) < 0 ) {
+ ar->flag |= RGN_FLAG_TOO_SMALL;
+ }
+ else if(alignment==RGN_ALIGN_NONE) {
+ /* typically last region */
+ ar->winrct= *remainder;
+ BLI_init_rcti(remainder, 0, 0, 0, 0);
+ }
+ else if(alignment==RGN_ALIGN_TOP || alignment==RGN_ALIGN_BOTTOM) {
+
+ if( rct_fits(remainder, 'v', prefsizey) < 0 ) {
+ ar->flag |= RGN_FLAG_TOO_SMALL;
+ }
+ else {
+ int fac= rct_fits(remainder, 'v', prefsizey);
+
+ if(fac < 0 )
+ prefsizey += fac;
+
+ ar->winrct= *remainder;
+
+ if(alignment==RGN_ALIGN_TOP) {
+ ar->winrct.ymin= ar->winrct.ymax - prefsizey + 1;
+ remainder->ymax= ar->winrct.ymin - 1;
+ }
+ else {
+ ar->winrct.ymax= ar->winrct.ymin + prefsizey - 1;
+ remainder->ymin= ar->winrct.ymax + 1;
+ }
+ }
+ }
+ else if( ELEM4(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT, RGN_OVERLAP_LEFT, RGN_OVERLAP_RIGHT)) {
+
+ if( rct_fits(remainder, 'h', prefsizex) < 0 ) {
+ ar->flag |= RGN_FLAG_TOO_SMALL;
+ }
+ else {
+ int fac= rct_fits(remainder, 'h', prefsizex);
+
+ if(fac < 0 )
+ prefsizex += fac;
+
+ ar->winrct= *remainder;
+
+ if(ELEM(alignment, RGN_ALIGN_RIGHT, RGN_OVERLAP_RIGHT)) {
+ ar->winrct.xmin= ar->winrct.xmax - prefsizex + 1;
+ if(alignment==RGN_ALIGN_RIGHT)
+ remainder->xmax= ar->winrct.xmin - 1;
+ }
+ else {
+ ar->winrct.xmax= ar->winrct.xmin + prefsizex - 1;
+ if(alignment==RGN_ALIGN_LEFT)
+ remainder->xmin= ar->winrct.xmax + 1;
+ }
+ }
+ }
+ else if(alignment==RGN_ALIGN_VSPLIT || alignment==RGN_ALIGN_HSPLIT) {
+ /* percentage subdiv*/
+ ar->winrct= *remainder;
+
+ if(alignment==RGN_ALIGN_HSPLIT) {
+ if( rct_fits(remainder, 'h', prefsizex) > 4) {
+ ar->winrct.xmax= (remainder->xmin+remainder->xmax)/2;
+ remainder->xmin= ar->winrct.xmax+1;
+ }
+ else {
+ BLI_init_rcti(remainder, 0, 0, 0, 0);
+ }
+ }
+ else {
+ if( rct_fits(remainder, 'v', prefsizey) > 4) {
+ ar->winrct.ymax= (remainder->ymin+remainder->ymax)/2;
+ remainder->ymin= ar->winrct.ymax+1;
+ }
+ else {
+ BLI_init_rcti(remainder, 0, 0, 0, 0);
+ }
+ }
+ }
+ else if(alignment==RGN_ALIGN_QSPLIT) {
+ ar->winrct= *remainder;
+
+ /* test if there's still 4 regions left */
+ if(quad==0) {
+ ARegion *artest= ar->next;
+ int count= 1;
+
+ while(artest) {
+ artest->alignment= RGN_ALIGN_QSPLIT;
+ artest= artest->next;
+ count++;
+ }
+
+ if(count!=4) {
+ /* let's stop adding regions */
+ BLI_init_rcti(remainder, 0, 0, 0, 0);
+ printf("region quadsplit failed\n");
+ }
+ else quad= 1;
+ }
+ if(quad) {
+ if(quad==1) { /* left bottom */
+ ar->winrct.xmax = (remainder->xmin + remainder->xmax)/2;
+ ar->winrct.ymax = (remainder->ymin + remainder->ymax)/2;
+ }
+ else if(quad==2) { /* left top */
+ ar->winrct.xmax = (remainder->xmin + remainder->xmax)/2;
+ ar->winrct.ymin = 1 + (remainder->ymin + remainder->ymax)/2;
+ }
+ else if(quad==3) { /* right bottom */
+ ar->winrct.xmin = 1 + (remainder->xmin + remainder->xmax)/2;
+ ar->winrct.ymax = (remainder->ymin + remainder->ymax)/2;
+ }
+ else { /* right top */
+ ar->winrct.xmin = 1 + (remainder->xmin + remainder->xmax)/2;
+ ar->winrct.ymin = 1 + (remainder->ymin + remainder->ymax)/2;
+ BLI_init_rcti(remainder, 0, 0, 0, 0);
+ }
+
+ quad++;
+ }
+ }
+
+ /* for speedup */
+ ar->winx= ar->winrct.xmax - ar->winrct.xmin + 1;
+ ar->winy= ar->winrct.ymax - ar->winrct.ymin + 1;
+
+ /* restore test exception */
+ if(ar->alignment & RGN_SPLIT_PREV) {
+ if(ar->prev) {
+ remainder= remainder_prev;
+ ar->prev->winx= ar->prev->winrct.xmax - ar->prev->winrct.xmin + 1;
+ ar->prev->winy= ar->prev->winrct.ymax - ar->prev->winrct.ymin + 1;
+ }
+ }
+ region_rect_recursive(ar->next, remainder, quad);
+}
+
+static void area_calc_totrct(ScrArea *sa, int sizex, int sizey)
+{
+
+ if(sa->v1->vec.x>0) sa->totrct.xmin= sa->v1->vec.x+1;
+ else sa->totrct.xmin= sa->v1->vec.x;
+ if(sa->v4->vec.x<sizex-1) sa->totrct.xmax= sa->v4->vec.x-1;
+ else sa->totrct.xmax= sa->v4->vec.x;
+
+ if(sa->v1->vec.y>0) sa->totrct.ymin= sa->v1->vec.y+1;
+ else sa->totrct.ymin= sa->v1->vec.y;
+ if(sa->v2->vec.y<sizey-1) sa->totrct.ymax= sa->v2->vec.y-1;
+ else sa->totrct.ymax= sa->v2->vec.y;
+
+ /* for speedup */
+ sa->winx= sa->totrct.xmax-sa->totrct.xmin+1;
+ sa->winy= sa->totrct.ymax-sa->totrct.ymin+1;
+}
+
+
+#define AZONESPOT 12
+void area_azone_initialize(ScrArea *sa)
+{
+ AZone *az;
+ if(sa->actionzones.first==NULL) {
+ /* set action zones - should these actually be ARegions? With these we can easier check area hotzones */
+ /* (ton) for time being just area, ARegion split is not foreseen on user level */
+ az= (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
+ BLI_addtail(&(sa->actionzones), az);
+ az->type= AZONE_TRI;
+ az->pos= AZONE_SW;
+
+ az= (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
+ BLI_addtail(&(sa->actionzones), az);
+ az->type= AZONE_TRI;
+ az->pos= AZONE_NE;
+ }
+
+ for(az= sa->actionzones.first; az; az= az->next) {
+ if(az->pos==AZONE_SW) {
+ az->x1= sa->v1->vec.x+1;
+ az->y1= sa->v1->vec.y+1;
+ az->x2= sa->v1->vec.x+AZONESPOT;
+ az->y2= sa->v1->vec.y+AZONESPOT;
+ }
+ else if (az->pos==AZONE_NE) {
+ az->x1= sa->v3->vec.x;
+ az->y1= sa->v3->vec.y;
+ az->x2= sa->v3->vec.x-AZONESPOT;
+ az->y2= sa->v3->vec.y-AZONESPOT;
+ }
+ }
+}
+
+/* used for area initialize below */
+static void region_subwindow(wmWindowManager *wm, wmWindow *win, ARegion *ar)
+{
+ if(ar->flag & (RGN_FLAG_HIDDEN|RGN_FLAG_TOO_SMALL)) {
+ if(ar->swinid)
+ wm_subwindow_close(win, ar->swinid);
+ ar->swinid= 0;
+ }
+ else if(ar->swinid==0)
+ ar->swinid= wm_subwindow_open(win, &ar->winrct);
+ else
+ wm_subwindow_position(win, ar->swinid, &ar->winrct);
+}
+
+static void ed_default_handlers(wmWindowManager *wm, ListBase *handlers, int flag)
+{
+ /* note, add-handler checks if it already exists */
+
+ // XXX it would be good to have boundbox checks for some of these...
+ if(flag & ED_KEYMAP_UI) {
+ UI_add_region_handlers(handlers);
+ }
+ if(flag & ED_KEYMAP_VIEW2D) {
+ ListBase *keymap= WM_keymap_listbase(wm, "View2D", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap);
+ }
+ if(flag & ED_KEYMAP_MARKERS) {
+ ListBase *keymap= WM_keymap_listbase(wm, "Markers", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap);
+ // XXX need boundbox check urgently!!!
+ }
+ if(flag & ED_KEYMAP_ANIMATION) {
+ ListBase *keymap= WM_keymap_listbase(wm, "Animation", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap);
+ }
+ if(flag & ED_KEYMAP_FRAMES) {
+ ListBase *keymap= WM_keymap_listbase(wm, "Frames", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap);
+ }
+}
+
+
+/* called in screen_refresh, or screens_init, also area size changes */
+void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
+{
+ ARegion *ar;
+ rcti rect;
+
+ /* set typedefinitions */
+ sa->type= BKE_spacetype_from_id(sa->spacetype);
+
+ if(sa->type==NULL) {
+ sa->butspacetype= sa->spacetype= SPACE_VIEW3D;
+ sa->type= BKE_spacetype_from_id(sa->spacetype);
+ }
+
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ ar->type= BKE_regiontype_from_id(sa->type, ar->regiontype);
+
+ /* area sizes */
+ area_calc_totrct(sa, win->sizex, win->sizey);
+
+ /* region rect sizes */
+ rect= sa->totrct;
+ region_rect_recursive(sa->regionbase.first, &rect, 0);
+
+ /* default area handlers */
+ ed_default_handlers(wm, &sa->handlers, sa->type->keymapflag);
+ /* checks spacedata, adds own handlers */
+ if(sa->type->init)
+ sa->type->init(wm, sa);
+
+ /* region windows, default and own handlers */
+ for(ar= sa->regionbase.first; ar; ar= ar->next) {
+ region_subwindow(wm, win, ar);
+
+ if(ar->swinid) {
+ /* default region handlers */
+ ed_default_handlers(wm, &ar->handlers, ar->type->keymapflag);
+
+ if(ar->type->init)
+ ar->type->init(wm, ar);
+ }
+ else {
+ /* prevent uiblocks to run */
+ uiFreeBlocks(NULL, &ar->uiblocks);
+ }
+
+ }
+ area_azone_initialize(sa);
+}
+
+/* externally called for floating regions like menus */
+void ED_region_init(bContext *C, ARegion *ar)
+{
+// ARegionType *at= ar->type;
+
+ /* refresh can be called before window opened */
+ region_subwindow(CTX_wm_manager(C), CTX_wm_window(C), ar);
+
+ ar->winx= ar->winrct.xmax - ar->winrct.xmin + 1;
+ ar->winy= ar->winrct.ymax - ar->winrct.ymin + 1;
+}
+
+
+/* sa2 to sa1, we swap spaces for fullscreen to keep all allocated data */
+/* area vertices were set */
+void area_copy_data(ScrArea *sa1, ScrArea *sa2, int swap_space)
+{
+ SpaceType *st;
+ ARegion *ar;
+
+ sa1->headertype= sa2->headertype;
+ sa1->spacetype= sa2->spacetype;
+ sa1->butspacetype= sa2->butspacetype;
+
+ if(swap_space == 1) {
+ SWAP(ListBase, sa1->spacedata, sa2->spacedata);
+ /* exception: ensure preview is reset */
+// if(sa1->spacetype==SPACE_VIEW3D)
+// XXX BIF_view3d_previewrender_free(sa1->spacedata.first);
+ }
+ else if (swap_space == 2) {
+ BKE_spacedata_copylist(&sa1->spacedata, &sa2->spacedata);
+ }
+ else {
+ BKE_spacedata_freelist(&sa1->spacedata);
+ BKE_spacedata_copylist(&sa1->spacedata, &sa2->spacedata);
+ }
+
+ /* Note; SPACE_EMPTY is possible on new screens */
+
+ /* regions */
+ if(swap_space<2) {
+ st= BKE_spacetype_from_id(sa1->spacetype);
+ for(ar= sa1->regionbase.first; ar; ar= ar->next)
+ BKE_area_region_free(st, ar);
+ BLI_freelistN(&sa1->regionbase);
+ }
+
+ st= BKE_spacetype_from_id(sa2->spacetype);
+ for(ar= sa2->regionbase.first; ar; ar= ar->next) {
+ ARegion *newar= BKE_area_region_copy(st, ar);
+ BLI_addtail(&sa1->regionbase, newar);
+ }
+
+#ifndef DISABLE_PYTHON
+ /* scripts */
+ BPY_free_scriptlink(&sa1->scriptlink);
+ sa1->scriptlink= sa2->scriptlink;
+ BPY_copy_scriptlink(&sa1->scriptlink); /* copies internal pointers */
+#endif
+}
+
+/* *********** Space switching code *********** */
+
+void ED_area_swapspace(bContext *C, ScrArea *sa1, ScrArea *sa2)
+{
+ ScrArea *tmp= MEM_callocN(sizeof(ScrArea), "addscrarea");
+
+ ED_area_exit(C, sa1);
+ ED_area_exit(C, sa2);
+
+ tmp->spacetype= sa1->spacetype;
+ tmp->butspacetype= sa1->butspacetype;
+ BKE_spacedata_copyfirst(&tmp->spacedata, &sa1->spacedata);
+
+ area_copy_data(tmp, sa1, 2);
+ area_copy_data(sa1, sa2, 0);
+ area_copy_data(sa2, tmp, 0);
+ ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa1);
+ ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa2);
+
+ BKE_screen_area_free(tmp);
+ MEM_freeN(tmp);
+
+ /* tell WM to refresh, cursor types etc */
+ WM_event_add_mousemove(C);
+
+ ED_area_tag_redraw(sa1);
+ ED_area_tag_refresh(sa1);
+ ED_area_tag_redraw(sa2);
+ ED_area_tag_refresh(sa2);
+}
+
+void ED_area_newspace(bContext *C, ScrArea *sa, int type)
+{
+ if(sa->spacetype != type) {
+ SpaceType *st;
+ SpaceLink *slold;
+ SpaceLink *sl;
+
+ ED_area_exit(C, sa);
+
+ st= BKE_spacetype_from_id(type);
+ slold= sa->spacedata.first;
+
+ sa->spacetype= type;
+ sa->butspacetype= type;
+ sa->type= st;
+
+ /* check previously stored space */
+ for (sl= sa->spacedata.first; sl; sl= sl->next)
+ if(sl->spacetype==type)
+ break;
+
+ /* old spacedata... happened during work on 2.50, remove */
+ if(sl && sl->regionbase.first==NULL) {
+ st->free(sl);
+ BLI_freelinkN(&sa->spacedata, sl);
+ sl= NULL;
+ }
+
+ if (sl) {
+
+ /* swap regions */
+ slold->regionbase= sa->regionbase;
+ sa->regionbase= sl->regionbase;
+ sl->regionbase.first= sl->regionbase.last= NULL;
+
+ /* put in front of list */
+ BLI_remlink(&sa->spacedata, sl);
+ BLI_addhead(&sa->spacedata, sl);
+ }
+ else {
+ /* new space */
+ if(st) {
+ sl= st->new(C);
+ BLI_addhead(&sa->spacedata, sl);
+
+ /* swap regions */
+ if(slold)
+ slold->regionbase= sa->regionbase;
+ sa->regionbase= sl->regionbase;
+ sl->regionbase.first= sl->regionbase.last= NULL;
+ }
+ }
+
+ ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
+
+ /* tell WM to refresh, cursor types etc */
+ WM_event_add_mousemove(C);
+
+ ED_area_tag_redraw(sa);
+ ED_area_tag_refresh(sa);
+ }
+}
+
+void ED_area_prevspace(bContext *C)
+{
+ SpaceLink *sl= CTX_wm_space_data(C);
+ ScrArea *sa= CTX_wm_area(C);
+
+ /* cleanup */
+#if 0 // XXX needs to be space type specific
+ if(sfile->spacetype==SPACE_FILE) {
+ if(sfile->pupmenu) {
+ MEM_freeN(sfile->pupmenu);
+ sfile->pupmenu= NULL;
+ }
+ }
+#endif
+
+ if(sl->next) {
+
+#if 0 // XXX check whether this is still needed
+ if (sfile->spacetype == SPACE_SCRIPT) {
+ SpaceScript *sc = (SpaceScript *)sfile;
+ if (sc->script) sc->script->flags &=~SCRIPT_FILESEL;
+ }
+#endif
+
+ ED_area_newspace(C, sa, sl->next->spacetype);
+ }
+ else {
+ ED_area_newspace(C, sa, SPACE_INFO);
+ }
+ ED_area_tag_redraw(sa);
+}
+
+static char *windowtype_pup(void)
+{
+ return(
+ "Window type:%t" //14
+ "|3D View %x1" //30
+
+ "|%l" // 33
+
+ "|Graph Editor %x2" //54
+ "|DopeSheet %x12" //73
+ "|NLA Editor %x13" //94
+
+ "|%l" //97
+
+ "|UV/Image Editor %x6" //117
+
+ "|Video Sequence Editor %x8" //143
+ "|Timeline %x15" //163
+ "|Audio Window %x11" //163
+ "|Text Editor %x9" //179
+
+ "|%l" //192
+
+
+ "|User Preferences %x7" //213
+ "|Outliner %x3" //232
+ "|Buttons Window %x4" //251
+ "|Node Editor %x16"
+ "|%l" //254
+
+ "|File Browser %x5" //290
+
+ "|%l" //293
+
+ "|Scripts Window %x14"//313
+ );
+}
+
+static void spacefunc(struct bContext *C, void *arg1, void *arg2)
+{
+ ED_area_newspace(C, CTX_wm_area(C), CTX_wm_area(C)->butspacetype);
+ ED_area_tag_redraw(CTX_wm_area(C));
+}
+
+/* returns offset for next button in header */
+int ED_area_header_standardbuttons(const bContext *C, uiBlock *block, int yco)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ uiBut *but;
+ int xco= 8;
+
+ but= uiDefIconTextButC(block, ICONTEXTROW, 0, ICON_VIEW3D,
+ windowtype_pup(), xco, yco, XIC+10, YIC,
+ &(sa->butspacetype), 1.0, SPACEICONMAX, 0, 0,
+ "Displays Current Window Type. "
+ "Click for menu of available types.");
+ uiButSetFunc(but, spacefunc, NULL, NULL);
+
+ xco += XIC + 14;
+
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+ if (sa->flag & HEADER_NO_PULLDOWN) {
+ uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, 0,
+ ICON_DISCLOSURE_TRI_RIGHT,
+ xco,yco,XIC,YIC-2,
+ &(sa->flag), 0, 0, 0, 0,
+ "Show pulldown menus");
+ }
+ else {
+ uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, 0,
+ ICON_DISCLOSURE_TRI_DOWN,
+ xco,yco,XIC,YIC-2,
+ &(sa->flag), 0, 0, 0, 0,
+ "Hide pulldown menus");
+ }
+ xco+=XIC;
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ return xco;
+}
+
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
new file mode 100644
index 00000000000..74e0bc3852e
--- /dev/null
+++ b/source/blender/editors/screen/glutil.c
@@ -0,0 +1,853 @@
+/**
+ * $Id: glutil.c 11920 2007-09-02 17:25:03Z elubie $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_vec_types.h"
+#include "DNA_listBase.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_arithb.h"
+#include "BLI_threads.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#ifndef GL_CLAMP_TO_EDGE
+#define GL_CLAMP_TO_EDGE 0x812F
+#endif
+
+
+/* ******************************************** */
+
+/* defined in BIF_gl.h */
+GLubyte stipple_halftone[128] = {
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55};
+
+
+/* repeat this pattern
+ X000X000
+ 00000000
+ 00X000X0
+ 00000000 */
+
+
+GLubyte stipple_quarttone[128] = {
+ 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0,
+ 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0,
+ 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0,
+ 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0,
+ 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0,
+ 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0,
+ 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0,
+ 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0};
+
+
+void fdrawbezier(float vec[4][3])
+{
+ float dist;
+ float curve_res = 24, spline_step = 0.0f;
+
+ dist= 0.5f*ABS(vec[0][0] - vec[3][0]);
+
+ /* check direction later, for top sockets */
+ vec[1][0]= vec[0][0]+dist;
+ vec[1][1]= vec[0][1];
+
+ vec[2][0]= vec[3][0]-dist;
+ vec[2][1]= vec[3][1];
+ /* we can reuse the dist variable here to increment the GL curve eval amount*/
+ dist = 1.0f/curve_res;
+
+ cpack(0x0);
+ glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, vec[0]);
+ glBegin(GL_LINE_STRIP);
+ while (spline_step < 1.000001f) {
+ /*if(do_shaded)
+ UI_ThemeColorBlend(th_col1, th_col2, spline_step);*/
+ glEvalCoord1f(spline_step);
+ spline_step += dist;
+ }
+ glEnd();
+}
+
+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();
+}
+
+/*
+
+ x1,y2
+ | \
+ | \
+ | \
+ x1,y1-- x2,y1
+
+*/
+
+static void sdrawtripoints(short x1, short y1, short x2, short y2)
+{
+ short v[2];
+ v[0]= x1; v[1]= y1;
+ glVertex2sv(v);
+ v[0]= x1; v[1]= y2;
+ glVertex2sv(v);
+ v[0]= x2; v[1]= y1;
+ glVertex2sv(v);
+}
+
+void sdrawtri(short x1, short y1, short x2, short y2)
+{
+ glBegin(GL_LINE_STRIP);
+ sdrawtripoints(x1, y1, x2, y2);
+ glEnd();
+}
+
+void sdrawtrifill(short x1, short y1, short x2, short y2)
+{
+ glBegin(GL_TRIANGLES);
+ sdrawtripoints(x1, y1, x2, y2);
+ 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();
+}
+
+
+/* ******************************************** */
+
+void setlinestyle(int nr)
+{
+ if(nr==0) {
+ glDisable(GL_LINE_STIPPLE);
+ }
+ else {
+
+ glEnable(GL_LINE_STIPPLE);
+ glLineStipple(nr, 0xAAAA);
+ }
+}
+
+ /* Invert line handling */
+
+#define glToggle(mode, onoff) (((onoff)?glEnable:glDisable)(mode))
+
+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 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};
+
+ /* with builtin memory, max 4 lines */
+
+ 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 fdrawXORellipse(float xofs, float yofs, float hw, float hh)
+{
+ if(hw==0) return;
+
+ set_inverted_drawing(1);
+
+ glPushMatrix();
+ glTranslatef(xofs, yofs, 0.0);
+ glScalef(1,hh/hw,1);
+ glutil_draw_lined_arc(0.0, M_PI*2.0, hw, 20);
+ glPopMatrix();
+
+ set_inverted_drawing(0);
+}
+void fdrawXORcirc(float xofs, float yofs, float rad)
+{
+ set_inverted_drawing(1);
+
+ glPushMatrix();
+ glTranslatef(xofs, yofs, 0.0);
+ glutil_draw_lined_arc(0.0, M_PI*2.0, 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)
+{
+ GLint i;
+ glGetIntegerv(param, &i);
+ return i;
+}
+
+float glaGetOneFloat(int param)
+{
+ GLfloat 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(0, 0, 0, 0, x - known_good_x, y - known_good_y, &dummy);
+}
+
+static int get_cached_work_texture(int *w_r, int *h_r)
+{
+ static GLint 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, (GLuint *)&texid);
+
+ glBindTexture(GL_TEXTURE_2D, texid);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ 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, int format, void *rect)
+{
+ unsigned char *uc_rect= (unsigned char*) rect;
+ float *f_rect= (float *)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;
+
+ /* Specify the color outside this function, and tex will modulate it.
+ * This is useful for changing alpha without using glPixelTransferf()
+ */
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w);
+ glBindTexture(GL_TEXTURE_2D, texid);
+
+ /* don't want nasty border artifacts */
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ 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;
+
+ if(format==GL_FLOAT)
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, GL_RGBA, GL_FLOAT, &f_rect[(subpart_y*tex_w)*img_w*4 + (subpart_x*tex_w)*4]);
+ else
+ 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]);
+
+ glEnable(GL_TEXTURE_2D);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0);
+ glVertex2f(rast_x, rast_y);
+
+ glTexCoord2f((float) (subpart_w-1)/tex_w, 0);
+ glVertex2f(rast_x+subpart_w*xzoom, rast_y);
+
+ glTexCoord2f((float) (subpart_w-1)/tex_w, (float) (subpart_h-1)/tex_h);
+ glVertex2f(rast_x+subpart_w*xzoom, rast_y+subpart_h*yzoom);
+
+ glTexCoord2f(0, (float) (subpart_h-1)/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);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+}
+
+void glaDrawPixelsSafe_to32(float fx, float fy, int img_w, int img_h, int row_w, float *rectf)
+{
+ float *rf;
+ int x, y;
+ char *rect32, *rc;
+
+ /* copy imgw-imgh to a temporal 32 bits rect */
+ if(img_w<1 || img_h<1) return;
+
+ rc= rect32= MEM_mallocN(img_w*img_h*sizeof(int), "temp 32 bits");
+
+ for(y=0; y<img_h; y++) {
+ rf= rectf;
+ for(x=0; x<img_w; x++, rf+=4, rc+=4) {
+ rc[0]= FTOCHAR(rf[0]);
+ rc[1]= FTOCHAR(rf[1]);
+ rc[2]= FTOCHAR(rf[2]);
+ rc[3]= FTOCHAR(rf[3]);
+ }
+ rectf+= 4*row_w;
+ }
+
+ glaDrawPixelsSafe(fx, fy, img_w, img_h, img_w, GL_RGBA, GL_UNSIGNED_BYTE, rect32);
+
+ MEM_freeN(rect32);
+}
+
+void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect)
+{
+ 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= -x/xzoom;
+ float iy= -y/yzoom;
+
+ /* The maximum pixel amounts the image can be cropped
+ * at the lower left without exceeding the origin.
+ */
+ int off_x= floor(MAX2(ix, 0));
+ int off_y= floor(MAX2(iy, 0));
+
+ /* The zoomed space coordinate of the raster position
+ * (starting at the lower left most unclipped pixel).
+ */
+ float rast_x= x + off_x*xzoom;
+ float rast_y= y + off_y*yzoom;
+
+ GLfloat scissor[4];
+ int draw_w, draw_h;
+
+ /* Determine the smallest number of pixels we need to draw
+ * before the image would go off the upper right corner.
+ *
+ * It may seem this is just an optimization but some graphics
+ * cards (ATI) freak out if there is a large zoom factor and
+ * a large number of pixels off the screen (probably at some
+ * level the number of image pixels to draw is getting multiplied
+ * by the zoom and then clamped). Making sure we draw the
+ * fewest pixels possible keeps everyone mostly happy (still
+ * fails if we zoom in on one really huge pixel so that it
+ * covers the entire screen).
+ */
+ glGetFloatv(GL_SCISSOR_BOX, scissor);
+ draw_w = MIN2(img_w-off_x, ceil((scissor[2]-rast_x)/xzoom));
+ draw_h = MIN2(img_h-off_y, ceil((scissor[3]-rast_y)/yzoom));
+
+ if (draw_w>0 && draw_h>0) {
+ int old_row_length = glaGetOneInteger(GL_UNPACK_ROW_LENGTH);
+
+ /* Don't use safe RasterPos (slower) if we can avoid it. */
+ if (rast_x>=0 && rast_y>=0) {
+ glRasterPos2f(rast_x, rast_y);
+ } else {
+ glaRasterPosSafe2f(rast_x, rast_y, 0, 0);
+ }
+
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, row_w);
+ if(format==GL_LUMINANCE || format==GL_RED) {
+ if(type==GL_FLOAT) {
+ float *f_rect= (float *)rect;
+ glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y*row_w + off_x));
+ }
+ else if(type==GL_INT || type==GL_UNSIGNED_INT) {
+ int *i_rect= (int *)rect;
+ glDrawPixels(draw_w, draw_h, format, type, i_rect + (off_y*row_w + off_x));
+ }
+ }
+ else { /* RGBA */
+ if(type==GL_FLOAT) {
+ float *f_rect= (float *)rect;
+ glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y*row_w + off_x)*4);
+ }
+ else if(type==GL_UNSIGNED_BYTE) {
+ unsigned char *uc_rect= (unsigned char *) rect;
+ glDrawPixels(draw_w, draw_h, format, type, uc_rect + (off_y*row_w + 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];
+};
+
+void gla2DGetMap(gla2DDrawInfo *di, rctf *rect)
+{
+ *rect= di->world_rect;
+}
+
+void gla2DSetMap(gla2DDrawInfo *di, rctf *rect)
+{
+ int sc_w, sc_h;
+ float wo_w, wo_h;
+
+ di->world_rect= *rect;
+
+ 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;
+}
+
+
+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, (GLint *)di->orig_vp);
+ glGetIntegerv(GL_SCISSOR_BOX, (GLint *)di->orig_sc);
+ glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *)di->orig_projmat);
+ glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)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);
+}
+
+/* **************** glPoint hack ************************ */
+
+static int curmode=0;
+static int pointhack=0;
+static GLubyte Squaredot[16] = { 0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff};
+
+void bglBegin(int mode)
+{
+ curmode= mode;
+
+ if(mode==GL_POINTS) {
+ float value[4];
+ glGetFloatv(GL_POINT_SIZE_RANGE, value);
+ if(value[1]<2.0) {
+ glGetFloatv(GL_POINT_SIZE, value);
+ pointhack= floor(value[0]+0.5);
+ if(pointhack>4) pointhack= 4;
+ }
+ else glBegin(mode);
+ }
+}
+
+
+void bglVertex3fv(float *vec)
+{
+ switch(curmode) {
+ case GL_POINTS:
+ if(pointhack) {
+ glRasterPos3fv(vec);
+ glBitmap(pointhack, pointhack, (float)pointhack/2.0, (float)pointhack/2.0, 0.0, 0.0, Squaredot);
+ }
+ else glVertex3fv(vec);
+ break;
+ }
+}
+
+void bglVertex3f(float x, float y, float z)
+{
+ switch(curmode) {
+ case GL_POINTS:
+ if(pointhack) {
+ glRasterPos3f(x, y, z);
+ glBitmap(pointhack, pointhack, (float)pointhack/2.0, (float)pointhack/2.0, 0.0, 0.0, Squaredot);
+ }
+ else glVertex3f(x, y, z);
+ break;
+ }
+}
+
+void bglVertex2fv(float *vec)
+{
+ switch(curmode) {
+ case GL_POINTS:
+ if(pointhack) {
+ glRasterPos2fv(vec);
+ glBitmap(pointhack, pointhack, (float)pointhack/2, pointhack/2, 0.0, 0.0, Squaredot);
+ }
+ else glVertex2fv(vec);
+ break;
+ }
+}
+
+
+void bglEnd(void)
+{
+ if(pointhack) pointhack= 0;
+ else glEnd();
+
+}
+
+/* Uses current OpenGL state to get view matrices for gluProject/gluUnProject */
+void bgl_get_mats(bglMats *mats)
+{
+ const double badvalue= 1.0e-6;
+
+ glGetDoublev(GL_MODELVIEW_MATRIX, mats->modelview);
+ glGetDoublev(GL_PROJECTION_MATRIX, mats->projection);
+ glGetIntegerv(GL_VIEWPORT, (GLint *)mats->viewport);
+
+ /* Very strange code here - it seems that certain bad values in the
+ modelview matrix can cause gluUnProject to give bad results. */
+ if(mats->modelview[0] < badvalue &&
+ mats->modelview[0] > -badvalue)
+ mats->modelview[0]= 0;
+ if(mats->modelview[5] < badvalue &&
+ mats->modelview[5] > -badvalue)
+ mats->modelview[5]= 0;
+
+ /* Set up viewport so that gluUnProject will give correct values */
+ mats->viewport[0] = 0;
+ mats->viewport[1] = 0;
+}
+
+/* *************** glPolygonOffset hack ************* */
+
+/* dist is only for ortho now... */
+void bglPolygonOffset(float viewdist, float dist)
+{
+ static float winmat[16], offset=0.0;
+
+ if(dist!=0.0) {
+ float offs;
+
+ // glEnable(GL_POLYGON_OFFSET_FILL);
+ // glPolygonOffset(-1.0, -1.0);
+
+ /* hack below is to mimic polygon offset */
+ glMatrixMode(GL_PROJECTION);
+ glGetFloatv(GL_PROJECTION_MATRIX, (float *)winmat);
+
+ /* dist is from camera to center point */
+
+ if(winmat[15]>0.5) offs= 0.00001*dist*viewdist; // ortho tweaking
+ else offs= 0.0005*dist; // should be clipping value or so...
+
+ winmat[14]-= offs;
+ offset+= offs;
+
+ glLoadMatrixf(winmat);
+ glMatrixMode(GL_MODELVIEW);
+ }
+ else {
+
+ glMatrixMode(GL_PROJECTION);
+ winmat[14]+= offset;
+ offset= 0.0;
+ glLoadMatrixf(winmat);
+ glMatrixMode(GL_MODELVIEW);
+ }
+}
+
+int is_a_really_crappy_intel_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), "Intel Inc.") == 0);
+
+ return well_is_it;
+}
+
+void bglFlush(void)
+{
+ glFlush();
+#ifdef __APPLE__
+// if(is_a_really_crappy_intel_card())
+// XXX myswapbuffers(); //hack to get mac intel graphics to show frontbuffer
+#endif
+}
+
+
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
new file mode 100644
index 00000000000..11d1d019005
--- /dev/null
+++ b/source/blender/editors/screen/screen_context.c
@@ -0,0 +1,85 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_context.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+
+int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ Scene *scene= sc->scene;
+ Base *base;
+
+ if(CTX_data_equals(member, "scene")) {
+ CTX_data_id_pointer_set(result, &scene->id);
+ return 1;
+ }
+ else if(CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
+ int selected_objects= CTX_data_equals(member, "selected_objects");
+
+ for(base=scene->base.first; base; base=base->next) {
+ if((base->flag & SELECT) && (base->lay & scene->lay)) {
+ if(selected_objects)
+ CTX_data_id_list_add(result, &base->object->id);
+ else
+ CTX_data_list_add(result, &scene->id, &RNA_UnknownType, base);
+ }
+ }
+
+ return 1;
+ }
+ else if(CTX_data_equals(member, "active_base")) {
+ if(scene->basact)
+ CTX_data_pointer_set(result, &scene->id, &RNA_UnknownType, &scene->basact);
+
+ return 1;
+ }
+ else if(CTX_data_equals(member, "active_object")) {
+ if(scene->basact)
+ CTX_data_id_pointer_set(result, &scene->basact->object->id);
+
+ return 1;
+ }
+ else if(CTX_data_equals(member, "edit_object")) {
+ /* convenience for now, 1 object per scene in editmode */
+ if(scene->obedit)
+ CTX_data_id_pointer_set(result, &scene->obedit->id);
+
+ return 1;
+ }
+
+ return 0;
+}
+
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
new file mode 100644
index 00000000000..51515f18623
--- /dev/null
+++ b/source/blender/editors/screen/screen_edit.c
@@ -0,0 +1,1500 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_vec_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_node.h"
+#include "BKE_screen.h"
+#include "BKE_scene.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_screen_types.h"
+
+#include "wm_subwindow.h"
+
+#include "screen_intern.h" /* own module include */
+
+
+/* ******************* screen vert, edge, area managing *********************** */
+
+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 (*v1 > *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;
+}
+
+
+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;
+}
+
+void removedouble_scrverts(bScreen *sc)
+{
+ ScrVert *v1, *verg;
+ ScrEdge *se;
+ ScrArea *sa;
+
+ verg= sc->vertbase.first;
+ while(verg) {
+ if(verg->newv==NULL) { /* !!! */
+ v1= verg->next;
+ while(v1) {
+ if(v1->newv==NULL) { /* !?! */
+ 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;
+ }
+
+ /* replace pointers in edges and faces */
+ se= sc->edgebase.first;
+ while(se) {
+ if(se->v1->newv) se->v1= se->v1->newv;
+ if(se->v2->newv) se->v2= se->v2->newv;
+ /* edges changed: so.... */
+ sortscrvert(&(se->v1), &(se->v2));
+ se= se->next;
+ }
+ sa= sc->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;
+ }
+
+ /* remove */
+ verg= sc->vertbase.first;
+ while(verg) {
+ v1= verg->next;
+ if(verg->newv) {
+ BLI_remlink(&sc->vertbase, verg);
+ MEM_freeN(verg);
+ }
+ verg= v1;
+ }
+
+}
+
+void removenotused_scrverts(bScreen *sc)
+{
+ ScrVert *sv, *svn;
+ ScrEdge *se;
+
+ /* we assume edges are ok */
+
+ se= sc->edgebase.first;
+ while(se) {
+ se->v1->flag= 1;
+ se->v2->flag= 1;
+ se= se->next;
+ }
+
+ sv= sc->vertbase.first;
+ while(sv) {
+ svn= sv->next;
+ if(sv->flag==0) {
+ BLI_remlink(&sc->vertbase, sv);
+ MEM_freeN(sv);
+ }
+ else sv->flag= 0;
+ sv= svn;
+ }
+}
+
+void removedouble_scredges(bScreen *sc)
+{
+ ScrEdge *verg, *se, *sn;
+
+ /* compare */
+ verg= sc->edgebase.first;
+ while(verg) {
+ se= verg->next;
+ while(se) {
+ sn= se->next;
+ if(verg->v1==se->v1 && verg->v2==se->v2) {
+ BLI_remlink(&sc->edgebase, se);
+ MEM_freeN(se);
+ }
+ se= sn;
+ }
+ verg= verg->next;
+ }
+}
+
+void removenotused_scredges(bScreen *sc)
+{
+ ScrEdge *se, *sen;
+ ScrArea *sa;
+ int a=0;
+
+ /* sets flags when edge is used in area */
+ sa= sc->areabase.first;
+ while(sa) {
+ se= screen_findedge(sc, sa->v1, sa->v2);
+ if(se==0) printf("error: area %d edge 1 doesn't exist\n", a);
+ else se->flag= 1;
+ se= screen_findedge(sc, sa->v2, sa->v3);
+ if(se==0) printf("error: area %d edge 2 doesn't exist\n", a);
+ else se->flag= 1;
+ se= screen_findedge(sc, sa->v3, sa->v4);
+ if(se==0) printf("error: area %d edge 3 doesn't exist\n", a);
+ else se->flag= 1;
+ se= screen_findedge(sc, sa->v4, sa->v1);
+ if(se==0) printf("error: area %d edge 4 doesn't exist\n", a);
+ else se->flag= 1;
+ sa= sa->next;
+ a++;
+ }
+ se= sc->edgebase.first;
+ while(se) {
+ sen= se->next;
+ if(se->flag==0) {
+ BLI_remlink(&sc->edgebase, se);
+ MEM_freeN(se);
+ }
+ else se->flag= 0;
+ se= sen;
+ }
+}
+
+int scredge_is_horizontal(ScrEdge *se)
+{
+ return (se->v1->vec.y == se->v2->vec.y);
+}
+
+ScrEdge *screen_find_active_scredge(bScreen *sc, int mx, int my)
+{
+ ScrEdge *se;
+
+ for (se= sc->edgebase.first; se; se= se->next) {
+ if (scredge_is_horizontal(se)) {
+ short min, max;
+ min= MIN2(se->v1->vec.x, se->v2->vec.x);
+ max= MAX2(se->v1->vec.x, se->v2->vec.x);
+
+ if (abs(my-se->v1->vec.y)<=2 && mx>=min && mx<=max)
+ return se;
+ }
+ else {
+ short min, max;
+ min= MIN2(se->v1->vec.y, se->v2->vec.y);
+ max= MAX2(se->v1->vec.y, se->v2->vec.y);
+
+ if (abs(mx-se->v1->vec.x)<=2 && my>=min && my<=max)
+ return se;
+ }
+ }
+
+ return NULL;
+}
+
+
+
+/* adds no space data */
+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->v1= v1;
+ sa->v2= v2;
+ sa->v3= v3;
+ sa->v4= v4;
+ sa->headertype= headertype;
+ sa->spacetype= sa->butspacetype= spacetype;
+
+ BLI_addtail(&sc->areabase, sa);
+
+ return sa;
+}
+
+static void screen_delarea(bContext *C, bScreen *sc, ScrArea *sa)
+{
+
+ ED_area_exit(C, sa);
+
+ BKE_screen_area_free(sa);
+
+ BLI_remlink(&sc->areabase, sa);
+ MEM_freeN(sa);
+}
+
+/* return 0: no split possible */
+/* else return (integer) screencoordinate split point */
+static short testsplitpoint(wmWindow *win, ScrArea *sa, char dir, float fac)
+{
+ short x, y;
+
+ // area big enough?
+ if(dir=='v' && (sa->v4->vec.x- sa->v1->vec.x <= 2*AREAMINX)) return 0;
+ if(dir=='h' && (sa->v2->vec.y- sa->v1->vec.y <= 2*AREAMINY)) return 0;
+
+ // to be sure
+ 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(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;
+ }
+}
+
+ScrArea *area_split(wmWindow *win, bScreen *sc, ScrArea *sa, char dir, float fac)
+{
+ ScrArea *newa=NULL;
+ ScrVert *sv1, *sv2;
+ short split;
+
+ if(sa==NULL) return NULL;
+
+ split= testsplitpoint(win, sa, dir, fac);
+ if(split==0) return NULL;
+
+ if(dir=='h') {
+ /* new vertices */
+ sv1= screen_addvert(sc, sa->v1->vec.x, split);
+ sv2= screen_addvert(sc, sa->v4->vec.x, split);
+
+ /* new 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);
+
+ /* new areas: top */
+ newa= screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->headertype, sa->spacetype);
+ area_copy_data(newa, sa, 0);
+
+ /* area below */
+ sa->v2= sv1;
+ sa->v3= sv2;
+
+ }
+ else {
+ /* new vertices */
+ sv1= screen_addvert(sc, split, sa->v1->vec.y);
+ sv2= screen_addvert(sc, split, sa->v2->vec.y);
+
+ /* new 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);
+
+ /* new areas: left */
+ newa= screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->headertype, sa->spacetype);
+ area_copy_data(newa, sa, 0);
+
+ /* area right */
+ sa->v1= sv1;
+ sa->v2= sv2;
+ }
+
+ /* remove double vertices en edges */
+ removedouble_scrverts(sc);
+ removedouble_scredges(sc);
+ removenotused_scredges(sc);
+
+ return newa;
+}
+
+/* empty screen, with 1 dummy area without spacedata */
+/* uses window size */
+bScreen *screen_add(wmWindow *win, Scene *scene, char *name)
+{
+ bScreen *sc;
+ ScrVert *sv1, *sv2, *sv3, *sv4;
+
+ sc= alloc_libblock(&G.main->screen, ID_SCR, name);
+ sc->scene= scene;
+ sc->do_refresh= 1;
+ sc->winid= win->winid;
+
+ sv1= screen_addvert(sc, 0, 0);
+ sv2= screen_addvert(sc, 0, win->sizey-1);
+ sv3= screen_addvert(sc, win->sizex-1, win->sizey-1);
+ sv4= screen_addvert(sc, win->sizex-1, 0);
+
+ screen_addedge(sc, sv1, sv2);
+ screen_addedge(sc, sv2, sv3);
+ screen_addedge(sc, sv3, sv4);
+ screen_addedge(sc, sv4, sv1);
+
+ /* dummy type, no spacedata */
+ screen_addarea(sc, sv1, sv2, sv3, sv4, HEADERDOWN, SPACE_EMPTY);
+
+ return sc;
+}
+
+static void screen_copy(bScreen *to, bScreen *from)
+{
+ ScrVert *s1, *s2;
+ ScrEdge *se;
+ ScrArea *sa, *saf;
+
+ /* free contents of 'to', is from blenkernel screen.c */
+ free_screen(to);
+
+ BLI_duplicatelist(&to->vertbase, &from->vertbase);
+ BLI_duplicatelist(&to->edgebase, &from->edgebase);
+ BLI_duplicatelist(&to->areabase, &from->areabase);
+ to->regionbase.first= to->regionbase.last= NULL;
+
+ s2= to->vertbase.first;
+ for(s1= from->vertbase.first; s1; s1= s1->next, s2= s2->next) {
+ s1->newv= s2;
+ }
+
+ for(se= to->edgebase.first; se; se= se->next) {
+ se->v1= se->v1->newv;
+ se->v2= se->v2->newv;
+ sortscrvert(&(se->v1), &(se->v2));
+ }
+
+ saf= from->areabase.first;
+ for(sa= to->areabase.first; sa; sa= sa->next, saf= saf->next) {
+ sa->v1= sa->v1->newv;
+ sa->v2= sa->v2->newv;
+ sa->v3= sa->v3->newv;
+ sa->v4= sa->v4->newv;
+
+ sa->spacedata.first= sa->spacedata.last= NULL;
+ sa->regionbase.first= sa->regionbase.last= NULL;
+ sa->actionzones.first= sa->actionzones.last= NULL;
+ sa->scriptlink.totscript= 0;
+
+ area_copy_data(sa, saf, 0);
+ }
+
+ /* put at zero (needed?) */
+ for(s1= from->vertbase.first; s1; s1= s1->next)
+ s1->newv= NULL;
+
+}
+
+
+/* with sa as center, sb is located at: 0=W, 1=N, 2=E, 3=S */
+/* -1 = not valid check */
+/* used with join operator */
+int area_getorientation(bScreen *screen, ScrArea *sa, ScrArea *sb)
+{
+ ScrVert *sav1, *sav2, *sav3, *sav4;
+ ScrVert *sbv1, *sbv2, *sbv3, *sbv4;
+
+ if(sa==NULL || sb==NULL) return -1;
+
+ sav1= sa->v1;
+ sav2= sa->v2;
+ sav3= sa->v3;
+ sav4= sa->v4;
+ sbv1= sb->v1;
+ sbv2= sb->v2;
+ sbv3= sb->v3;
+ sbv4= sb->v4;
+
+ if(sav1==sbv4 && sav2==sbv3) { /* sa to right of sb = W */
+ return 0;
+ }
+ else if(sav2==sbv1 && sav3==sbv4) { /* sa to bottom of sb = N */
+ return 1;
+ }
+ else if(sav3==sbv2 && sav4==sbv1) { /* sa to left of sb = E */
+ return 2;
+ }
+ else if(sav1==sbv2 && sav4==sbv3) { /* sa on top of sb = S*/
+ return 3;
+ }
+
+ return -1;
+}
+
+/* Helper function to join 2 areas, it has a return value, 0=failed 1=success
+* used by the split, join operators
+*/
+int screen_area_join(bContext *C, bScreen* scr, ScrArea *sa1, ScrArea *sa2)
+{
+ int dir;
+
+ dir = area_getorientation(scr, sa1, sa2);
+ /*printf("dir is : %i \n", dir);*/
+
+ if (dir < 0)
+ {
+ if (sa1 ) sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
+ if (sa2 ) sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+ return 0;
+ }
+
+ if(dir == 0) {
+ sa1->v1= sa2->v1;
+ sa1->v2= sa2->v2;
+ screen_addedge(scr, sa1->v2, sa1->v3);
+ screen_addedge(scr, sa1->v1, sa1->v4);
+ }
+ else if(dir == 1) {
+ sa1->v2= sa2->v2;
+ sa1->v3= sa2->v3;
+ screen_addedge(scr, sa1->v1, sa1->v2);
+ screen_addedge(scr, sa1->v3, sa1->v4);
+ }
+ else if(dir == 2) {
+ sa1->v3= sa2->v3;
+ sa1->v4= sa2->v4;
+ screen_addedge(scr, sa1->v2, sa1->v3);
+ screen_addedge(scr, sa1->v1, sa1->v4);
+ }
+ else if(dir == 3) {
+ sa1->v1= sa2->v1;
+ sa1->v4= sa2->v4;
+ screen_addedge(scr, sa1->v1, sa1->v2);
+ screen_addedge(scr, sa1->v3, sa1->v4);
+ }
+
+ screen_delarea(C, scr, sa2);
+ removedouble_scrverts(scr);
+ sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
+
+ return 1;
+}
+
+void select_connected_scredge(bScreen *sc, ScrEdge *edge)
+{
+ ScrEdge *se;
+ ScrVert *sv;
+ int oneselected;
+ char dir;
+
+ /* select connected, only in the right direction */
+ /* 'dir' is the direction of 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;
+ }
+ }
+}
+
+/* test if screen vertices should be scaled */
+static void screen_test_scale(bScreen *sc, int winsizex, int winsizey)
+{
+ ScrVert *sv=NULL;
+ ScrArea *sa;
+ int sizex, sizey;
+ float facx, facy, tempf, min[2], max[2];
+
+ /* calculate size */
+ min[0]= min[1]= 10000.0f;
+ max[0]= max[1]= 0.0f;
+
+ for(sv= sc->vertbase.first; sv; sv= sv->next) {
+ 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);
+ }
+
+ /* always make 0.0 left under */
+ for(sv= sc->vertbase.first; sv; sv= sv->next) {
+ sv->vec.x -= min[0];
+ sv->vec.y -= min[1];
+ }
+
+ sizex= max[0]-min[0];
+ sizey= max[1]-min[1];
+
+ if(sizex!= winsizex || sizey!= winsizey) {
+ facx= winsizex;
+ facx/= (float)sizex;
+ facy= winsizey;
+ facy/= (float)sizey;
+
+ /* make sure it fits! */
+ for(sv= sc->vertbase.first; sv; sv= sv->next) {
+ 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, winsizex);
+
+ 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, winsizey);
+ }
+ }
+
+ /* test for collapsed areas. This could happen in some blender version... */
+ /* ton: removed option now, it needs Context... */
+
+ /* make each window at least HEADERY high */
+ for(sa= sc->areabase.first; sa; sa= sa->next) {
+ int headery= HEADERY+1;
+
+ if(sa->v1->vec.y+headery > sa->v2->vec.y) {
+ /* lower edge */
+ ScrEdge *se= screen_findedge(sc, sa->v4, sa->v1);
+ if(se && sa->v1!=sa->v2 ) {
+ int yval;
+
+ 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;
+ }
+ }
+ }
+ }
+
+}
+
+/* *********************** DRAWING **************************************** */
+
+
+#define SCR_BACK 0.55
+#define SCR_ROUND 12
+
+/* draw vertical shape visualising future joining (left as well
+ * right direction of future joining) */
+static void draw_horizontal_join_shape(ScrArea *sa, char dir)
+{
+ vec2f points[10];
+ short i;
+ float w, h;
+ float width = sa->v3->vec.x - sa->v1->vec.x;
+ float height = sa->v3->vec.y - sa->v1->vec.y;
+
+ if(height<width) {
+ h = height/8;
+ w = height/4;
+ }
+ else {
+ h = width/8;
+ w = width/4;
+ }
+
+ points[0].x = sa->v1->vec.x;
+ points[0].y = sa->v1->vec.y + height/2;
+
+ points[1].x = sa->v1->vec.x;
+ points[1].y = sa->v1->vec.y;
+
+ points[2].x = sa->v4->vec.x - w;
+ points[2].y = sa->v4->vec.y;
+
+ points[3].x = sa->v4->vec.x - w;
+ points[3].y = sa->v4->vec.y + height/2 - 2*h;
+
+ points[4].x = sa->v4->vec.x - 2*w;
+ points[4].y = sa->v4->vec.y + height/2;
+
+ points[5].x = sa->v4->vec.x - w;
+ points[5].y = sa->v4->vec.y + height/2 + 2*h;
+
+ points[6].x = sa->v3->vec.x - w;
+ points[6].y = sa->v3->vec.y;
+
+ points[7].x = sa->v2->vec.x;
+ points[7].y = sa->v2->vec.y;
+
+ points[8].x = sa->v4->vec.x;
+ points[8].y = sa->v4->vec.y + height/2 - h;
+
+ points[9].x = sa->v4->vec.x;
+ points[9].y = sa->v4->vec.y + height/2 + h;
+
+ if(dir=='l') {
+ /* when direction is left, then we flip direction of arrow */
+ float cx = sa->v1->vec.x + width;
+ for(i=0;i<10;i++) {
+ points[i].x -= cx;
+ points[i].x = -points[i].x;
+ points[i].x += sa->v1->vec.x;
+ }
+ }
+
+ glBegin(GL_POLYGON);
+ for(i=0;i<5;i++)
+ glVertex2f(points[i].x, points[i].y);
+ glEnd();
+ glBegin(GL_POLYGON);
+ for(i=4;i<8;i++)
+ glVertex2f(points[i].x, points[i].y);
+ glVertex2f(points[0].x, points[0].y);
+ glEnd();
+
+ glRectf(points[2].x, points[2].y, points[8].x, points[8].y);
+ glRectf(points[6].x, points[6].y, points[9].x, points[9].y);
+}
+
+/* draw vertical shape visualising future joining (up/down direction) */
+static void draw_vertical_join_shape(ScrArea *sa, char dir)
+{
+ vec2f points[10];
+ short i;
+ float w, h;
+ float width = sa->v3->vec.x - sa->v1->vec.x;
+ float height = sa->v3->vec.y - sa->v1->vec.y;
+
+ if(height<width) {
+ h = height/4;
+ w = height/8;
+ }
+ else {
+ h = width/4;
+ w = width/8;
+ }
+
+ points[0].x = sa->v1->vec.x + width/2;
+ points[0].y = sa->v3->vec.y;
+
+ points[1].x = sa->v2->vec.x;
+ points[1].y = sa->v2->vec.y;
+
+ points[2].x = sa->v1->vec.x;
+ points[2].y = sa->v1->vec.y + h;
+
+ points[3].x = sa->v1->vec.x + width/2 - 2*w;
+ points[3].y = sa->v1->vec.y + h;
+
+ points[4].x = sa->v1->vec.x + width/2;
+ points[4].y = sa->v1->vec.y + 2*h;
+
+ points[5].x = sa->v1->vec.x + width/2 + 2*w;
+ points[5].y = sa->v1->vec.y + h;
+
+ points[6].x = sa->v4->vec.x;
+ points[6].y = sa->v4->vec.y + h;
+
+ points[7].x = sa->v3->vec.x;
+ points[7].y = sa->v3->vec.y;
+
+ points[8].x = sa->v1->vec.x + width/2 - w;
+ points[8].y = sa->v1->vec.y;
+
+ points[9].x = sa->v1->vec.x + width/2 + w;
+ points[9].y = sa->v1->vec.y;
+
+ if(dir=='u') {
+ /* when direction is up, then we flip direction of arrow */
+ float cy = sa->v1->vec.y + height;
+ for(i=0;i<10;i++) {
+ points[i].y -= cy;
+ points[i].y = -points[i].y;
+ points[i].y += sa->v1->vec.y;
+ }
+ }
+
+ glBegin(GL_POLYGON);
+ for(i=0;i<5;i++)
+ glVertex2f(points[i].x, points[i].y);
+ glEnd();
+ glBegin(GL_POLYGON);
+ for(i=4;i<8;i++)
+ glVertex2f(points[i].x, points[i].y);
+ glVertex2f(points[0].x, points[0].y);
+ glEnd();
+
+ glRectf(points[2].x, points[2].y, points[8].x, points[8].y);
+ glRectf(points[6].x, points[6].y, points[9].x, points[9].y);
+}
+
+/* draw join shape due to direction of joining */
+static void draw_join_shape(ScrArea *sa, char dir)
+{
+ if(dir=='u' || dir=='d')
+ draw_vertical_join_shape(sa, dir);
+ else
+ draw_horizontal_join_shape(sa, dir);
+}
+
+/* draw screen area darker with arrow (visualisation of future joining) */
+static void scrarea_draw_shape_dark(ScrArea *sa, char dir)
+{
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glColor4ub(0, 0, 0, 50);
+ draw_join_shape(sa, dir);
+ glDisable(GL_BLEND);
+}
+
+/* draw screen area ligher with arrow shape ("eraser" of previous dark shape) */
+static void scrarea_draw_shape_light(ScrArea *sa, char dir)
+{
+ glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ /* value 181 was hardly computed: 181~105 */
+ glColor4ub(255, 255, 255, 50);
+ /* draw_join_shape(sa, dir); */
+ glRecti(sa->v1->vec.x, sa->v1->vec.y, sa->v3->vec.x, sa->v3->vec.y);
+ glDisable(GL_BLEND);
+}
+
+/** screen edges drawing **/
+static void drawscredge_area(ScrArea *sa)
+{
+ short x1= sa->v1->vec.x;
+ short y1= sa->v1->vec.y;
+ short x2= sa->v3->vec.x;
+ short y2= sa->v3->vec.y;
+
+ cpack(0x0);
+
+ /* right border area */
+ sdrawline(x2, y1, x2, y2);
+
+ /* left border area */
+ if(x1>0) { /* otherwise it draws the emboss of window over */
+ sdrawline(x1, y1, x1, y2);
+ }
+
+ /* top border area */
+ sdrawline(x1, y2, x2, y2);
+
+ /* bottom border area */
+ sdrawline(x1, y1, x2, y1);
+
+}
+
+/* ****************** EXPORTED API TO OTHER MODULES *************************** */
+
+bScreen *ED_screen_duplicate(wmWindow *win, bScreen *sc)
+{
+ bScreen *newsc;
+
+ if(sc->full != SCREENNORMAL) return NULL; /* XXX handle this case! */
+
+ /* make new empty screen: */
+ newsc= screen_add(win, sc->scene, sc->id.name+2);
+ /* copy all data */
+ screen_copy(newsc, sc);
+ /* set in window */
+ win->screen= newsc;
+
+ /* store identifier */
+ win->screen->winid= win->winid;
+ BLI_strncpy(win->screenname, win->screen->id.name+2, 21);
+
+ return newsc;
+}
+
+/* screen sets cursor based on swinid */
+static void region_cursor_set(wmWindow *win, int swinid)
+{
+ ScrArea *sa= win->screen->areabase.first;
+
+ for(;sa; sa= sa->next) {
+ ARegion *ar= sa->regionbase.first;
+ for(;ar; ar= ar->next) {
+ if(ar->swinid == swinid) {
+ if(ar->type && ar->type->cursor)
+ ar->type->cursor(win, sa, ar);
+ else
+ WM_cursor_set(win, CURSOR_STD);
+ return;
+ }
+ }
+ }
+}
+
+void ED_screen_do_listen(wmWindow *win, wmNotifier *note)
+{
+
+ /* generic notes */
+ switch(note->category) {
+ case NC_WM:
+ if(note->data==ND_FILEREAD)
+ win->screen->do_draw= 1;
+ break;
+ case NC_WINDOW:
+ win->screen->do_draw= 1;
+ break;
+ case NC_SCREEN:
+ if(note->action==NA_EDITED)
+ win->screen->do_draw= win->screen->do_refresh= 1;
+ case NC_SCENE:
+ if(note->data==ND_MODE)
+ region_cursor_set(win, note->swinid);
+ break;
+ }
+}
+
+/* only for edge lines between areas, and the blended join arrows */
+void ED_screen_draw(wmWindow *win)
+{
+ ScrArea *sa;
+ ScrArea *sa1=NULL;
+ ScrArea *sa2=NULL;
+ int dir = -1;
+ int dira = -1;
+
+ wmSubWindowSet(win, win->screen->mainwin);
+
+ for(sa= win->screen->areabase.first; sa; sa= sa->next) {
+ if (sa->flag & AREA_FLAG_DRAWJOINFROM) sa1 = sa;
+ if (sa->flag & AREA_FLAG_DRAWJOINTO) sa2 = sa;
+ drawscredge_area(sa);
+ }
+
+ /* blended join arrow */
+ if (sa1 && sa2) {
+ dir = area_getorientation(win->screen, sa1, sa2);
+ if (dir >= 0) {
+ switch(dir) {
+ case 0: /* W */
+ dir = 'r';
+ dira = 'l';
+ break;
+ case 1: /* N */
+ dir = 'd';
+ dira = 'u';
+ break;
+ case 2: /* E */
+ dir = 'l';
+ dira = 'r';
+ break;
+ case 3: /* S */
+ dir = 'u';
+ dira = 'd';
+ break;
+ }
+ }
+ scrarea_draw_shape_dark(sa2, dir);
+ scrarea_draw_shape_light(sa1, dira);
+ }
+
+// if(G.f & G_DEBUG) printf("draw screen\n");
+ win->screen->do_draw= 0;
+}
+
+/* make this screen usable */
+/* for file read and first use, for scaling window, area moves */
+void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
+{
+ ScrArea *sa;
+ rcti winrct= {0, win->sizex-1, 0, win->sizey-1};
+
+ screen_test_scale(win->screen, win->sizex, win->sizey);
+
+ if(win->screen->mainwin==0)
+ win->screen->mainwin= wm_subwindow_open(win, &winrct);
+ else
+ wm_subwindow_position(win, win->screen->mainwin, &winrct);
+
+ for(sa= win->screen->areabase.first; sa; sa= sa->next) {
+ /* set spacetype and region callbacks, calls init() */
+ /* sets subwindows for regions, adds handlers */
+ ED_area_initialize(wm, win, sa);
+ }
+
+ /* wake up animtimer */
+ if(win->screen->animtimer)
+ WM_event_window_timer_sleep(win, win->screen->animtimer, 0);
+
+ if(G.f & G_DEBUG) printf("set screen\n");
+ win->screen->do_refresh= 0;
+
+ win->screen->context= ed_screen_context;
+}
+
+/* file read, set all screens, ... */
+void ED_screens_initialize(wmWindowManager *wm)
+{
+ wmWindow *win;
+
+ for(win= wm->windows.first; win; win= win->next) {
+
+ if(win->screen==NULL)
+ win->screen= G.main->screen.first;
+
+ ED_screen_refresh(wm, win);
+ }
+}
+
+
+/* *********** exit calls are for closing running stuff ******** */
+
+void ED_region_exit(bContext *C, ARegion *ar)
+{
+ ARegion *prevar= CTX_wm_region(C);
+
+ CTX_wm_region_set(C, ar);
+ WM_event_remove_handlers(C, &ar->handlers);
+ if(ar->swinid)
+ wm_subwindow_close(CTX_wm_window(C), ar->swinid);
+ ar->swinid= 0;
+
+ if(ar->headerstr)
+ MEM_freeN(ar->headerstr);
+ ar->headerstr= NULL;
+
+ CTX_wm_region_set(C, prevar);
+}
+
+void ED_area_exit(bContext *C, ScrArea *sa)
+{
+ ScrArea *prevsa= CTX_wm_area(C);
+ ARegion *ar;
+
+ CTX_wm_area_set(C, sa);
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ ED_region_exit(C, ar);
+
+ WM_event_remove_handlers(C, &sa->handlers);
+ CTX_wm_area_set(C, prevsa);
+}
+
+void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
+{
+ wmWindow *prevwin= CTX_wm_window(C);
+ ScrArea *sa;
+ ARegion *ar;
+
+ CTX_wm_window_set(C, window);
+
+ if(screen->animtimer)
+ WM_event_remove_window_timer(window, screen->animtimer);
+ screen->animtimer= NULL;
+
+ if(screen->mainwin)
+ wm_subwindow_close(window, screen->mainwin);
+ screen->mainwin= 0;
+ screen->subwinactive= 0;
+
+ for(ar= screen->regionbase.first; ar; ar= ar->next)
+ ED_region_exit(C, ar);
+
+ for(sa= screen->areabase.first; sa; sa= sa->next)
+ ED_area_exit(C, sa);
+
+ /* mark it available for use for other windows */
+ screen->winid= 0;
+
+ CTX_wm_window_set(C, prevwin);
+}
+
+/* *********************************** */
+
+/* case when on area-edge or in azones, or outside window */
+static void screen_cursor_set(wmWindow *win, wmEvent *event)
+{
+ ScrArea *sa;
+
+ for(sa= win->screen->areabase.first; sa; sa= sa->next)
+ if(is_in_area_actionzone(sa, event->x, event->y))
+ break;
+
+ if(sa) {
+ WM_cursor_set(win, CURSOR_EDIT);
+ }
+ else {
+ ScrEdge *actedge= screen_find_active_scredge(win->screen, event->x, event->y);
+
+ if (actedge) {
+ if(scredge_is_horizontal(actedge))
+ WM_cursor_set(win, CURSOR_Y_MOVE);
+ else
+ WM_cursor_set(win, CURSOR_X_MOVE);
+ }
+ else
+ WM_cursor_set(win, CURSOR_STD);
+ }
+}
+
+
+/* called in wm_event_system.c. sets state vars in screen, cursors */
+/* event type is mouse move */
+void ED_screen_set_subwinactive(wmWindow *win, wmEvent *event)
+{
+ if(win->screen) {
+ bScreen *scr= win->screen;
+ ScrArea *sa;
+ ARegion *ar;
+ int oldswin= scr->subwinactive;
+
+ for(sa= scr->areabase.first; sa; sa= sa->next) {
+ if(event->x > sa->totrct.xmin && event->x < sa->totrct.xmax)
+ if(event->y > sa->totrct.ymin && event->y < sa->totrct.ymax)
+ if(NULL==is_in_area_actionzone(sa, event->x, event->y))
+ break;
+ }
+ if(sa) {
+ for(ar= sa->regionbase.first; ar; ar= ar->next) {
+ if(BLI_in_rcti(&ar->winrct, event->x, event->y))
+ scr->subwinactive= ar->swinid;
+ }
+ }
+ else
+ scr->subwinactive= scr->mainwin;
+
+ /* check for redraw headers */
+ if(oldswin!=scr->subwinactive) {
+
+ for(sa= scr->areabase.first; sa; sa= sa->next) {
+ int do_draw= 0;
+
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ if(ar->swinid==oldswin || ar->swinid==scr->subwinactive)
+ do_draw= 1;
+
+ if(do_draw) {
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ if(ar->regiontype==RGN_TYPE_HEADER)
+ ED_region_tag_redraw(ar);
+ }
+ }
+ }
+
+ /* cursors, for time being set always on edges, otherwise aregion doesnt switch */
+ if(scr->subwinactive==scr->mainwin) {
+ screen_cursor_set(win, event);
+ }
+ else if(oldswin!=scr->subwinactive) {
+ region_cursor_set(win, scr->subwinactive);
+ }
+ }
+}
+
+int ED_screen_area_active(const bContext *C)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ ScrArea *sa= CTX_wm_area(C);
+
+ if(sc && sa) {
+ ARegion *ar;
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ if(ar->swinid == sc->subwinactive)
+ return 1;
+ }
+ return 0;
+}
+
+/* operator call, WM + Window + screen already existed before */
+/* Do NOT call in area/region queues! */
+void ED_screen_set(bContext *C, bScreen *sc)
+{
+ wmWindow *win= CTX_wm_window(C);
+ bScreen *oldscreen= CTX_wm_screen(C);
+ ID *id;
+
+ /* validate screen, it's called with notifier reference */
+ for(id= CTX_data_main(C)->screen.first; id; id= id->next)
+ if(sc == (bScreen *)id)
+ break;
+ if(id==NULL)
+ return;
+
+ /* check for valid winid */
+ if(sc->winid!=0 && sc->winid!=win->winid)
+ return;
+
+ if(sc->full) { /* find associated full */
+ bScreen *sc1;
+ for(sc1= CTX_data_main(C)->screen.first; sc1; sc1= sc1->id.next) {
+ ScrArea *sa= sc1->areabase.first;
+ if(sa->full==sc) {
+ sc= sc1;
+ break;
+ }
+ }
+ }
+
+ if (oldscreen != sc) {
+ wmTimer *wt= oldscreen->animtimer;
+
+ /* we put timer to sleep, so screen_exit has to think there's no timer */
+ oldscreen->animtimer= NULL;
+ if(wt)
+ WM_event_window_timer_sleep(win, wt, 1);
+
+ ED_screen_exit(C, win, oldscreen);
+ oldscreen->animtimer= wt;
+
+ win->screen= sc;
+ CTX_wm_window_set(C, win); // stores C->wm.screen... hrmf
+
+ /* prevent multiwin errors */
+ sc->winid= win->winid;
+
+ ED_screen_refresh(CTX_wm_manager(C), CTX_wm_window(C));
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ }
+}
+
+/* only call outside of area/region loops */
+void ED_screen_set_scene(bContext *C, Scene *scene)
+{
+ bScreen *sc;
+ bScreen *curscreen= CTX_wm_screen(C);
+
+ for(sc= CTX_data_main(C)->screen.first; sc; sc= sc->id.next) {
+ if((U.flag & USER_SCENEGLOBAL) || sc==curscreen) {
+
+ if(scene != sc->scene) {
+ /* all areas endlocalview */
+ // XXX ScrArea *sa= sc->areabase.first;
+ // while(sa) {
+ // endlocalview(sa);
+ // sa= sa->next;
+ // }
+ sc->scene= scene;
+ }
+
+ }
+ }
+
+ // copy_view3d_lock(0); /* space.c */
+
+ /* are there cameras in the views that are not in the scene? */
+ for(sc= CTX_data_main(C)->screen.first; sc; sc= sc->id.next) {
+ if( (U.flag & USER_SCENEGLOBAL) || sc==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, scene)) {
+ v3d->camera= scene_find_camera(sc->scene);
+ // XXX if (sc==curscreen) handle_view3d_lock();
+ if (!v3d->camera && v3d->persp==V3D_CAMOB)
+ v3d->persp= V3D_PERSP;
+ }
+ }
+ sl= sl->next;
+ }
+ sa= sa->next;
+ }
+ }
+ }
+
+ CTX_data_scene_set(C, scene);
+ set_scene_bg(scene);
+
+ ED_update_for_newframe(C, 1);
+
+// set_radglobal();
+
+ /* complete redraw */
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+}
+
+/* this function toggles: if area is full then the parent will be restored */
+void ed_screen_fullarea(bContext *C, ScrArea *sa)
+{
+ bScreen *sc, *oldscreen;
+
+ if(sa==NULL) {
+ return;
+ }
+ else if(sa->full) {
+ short fulltype;
+
+ sc= sa->full; /* the old screen to restore */
+ oldscreen= CTX_wm_screen(C); /* the one disappearing */
+
+ fulltype = sc->full;
+
+ /* refuse to go out of SCREENAUTOPLAY as long as G_FLAGS_AUTOPLAY
+ is set */
+
+ if (fulltype != SCREENAUTOPLAY || (G.flags & G_FILE_AUTOPLAY) == 0) {
+ ScrArea *old;
+
+ sc->full= 0;
+
+ /* find old area */
+ for(old= sc->areabase.first; old; old= old->next)
+ if(old->full) break;
+ if(old==NULL) {
+ printf("something wrong in areafullscreen\n");
+ return;
+ }
+ // old feature described below (ton)
+ // in autoplay screens the headers are disabled by
+ // default. So use the old headertype instead
+
+ area_copy_data(old, sa, 1); /* 1 = swap spacelist */
+
+ old->full= NULL;
+
+ /* animtimer back */
+ sc->animtimer= oldscreen->animtimer;
+ oldscreen->animtimer= NULL;
+
+ ED_screen_set(C, sc);
+
+ free_screen(oldscreen);
+ free_libblock(&CTX_data_main(C)->screen, oldscreen);
+ }
+ }
+ else {
+ ScrArea *newa;
+
+ oldscreen= CTX_wm_screen(C);
+
+ /* is there only 1 area? */
+ if(oldscreen->areabase.first==oldscreen->areabase.last) return;
+
+ oldscreen->full = SCREENFULL;
+
+ sc= screen_add(CTX_wm_window(C), CTX_data_scene(C), "temp");
+ sc->full = SCREENFULL; // XXX
+
+ /* timer */
+ sc->animtimer= oldscreen->animtimer;
+ oldscreen->animtimer= NULL;
+
+ /* returns the top small area */
+ newa= area_split(CTX_wm_window(C), sc, (ScrArea *)sc->areabase.first, 'h', 0.99f);
+ ED_area_newspace(C, newa, SPACE_INFO);
+
+ /* copy area */
+ newa= newa->prev;
+ area_copy_data(newa, sa, 1); /* 1 = swap spacelist */
+
+ sa->full= oldscreen;
+ newa->full= oldscreen;
+ newa->next->full= oldscreen; // XXX
+
+ ED_screen_set(C, sc);
+ }
+
+ /* XXX bad code: setscreen() ends with first area active. fullscreen render assumes this too */
+ CTX_wm_area_set(C, sc->areabase.first);
+
+ /* XXX retopo_force_update(); */
+
+}
+
+int ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
+{
+ if(sa==NULL)
+ return 0;
+
+ if(sa->full==0)
+ ed_screen_fullarea(C, sa);
+
+ /* CTX_wm_area(C) is new area */
+ ED_area_newspace(C, CTX_wm_area(C), type);
+
+ return 1;
+}
+
+void ED_screen_full_prevspace(bContext *C)
+{
+ ScrArea *sa= CTX_wm_area(C);
+
+ ED_area_prevspace(C);
+
+ if(sa->full)
+ ed_screen_fullarea(C, sa);
+}
+
+void ED_screen_animation_timer(bContext *C, int enable)
+{
+ bScreen *screen= CTX_wm_screen(C);
+ wmWindow *win= CTX_wm_window(C);
+ Scene *scene= CTX_data_scene(C);
+
+ if(screen->animtimer)
+ WM_event_remove_window_timer(win, screen->animtimer);
+ screen->animtimer= NULL;
+
+ if(enable)
+ screen->animtimer= WM_event_add_window_timer(win, TIMER0, (1.0/FPS));
+}
+
+unsigned int ED_screen_view3d_layers(bScreen *screen)
+{
+ if(screen) {
+ unsigned int layer= screen->scene->lay; /* as minimum this */
+ ScrArea *sa;
+
+ /* get all used view3d layers */
+ for(sa= screen->areabase.first; sa; sa= sa->next) {
+ if(sa->spacetype==SPACE_VIEW3D)
+ layer |= ((View3D *)sa->spacedata.first)->lay;
+ }
+ return layer;
+ }
+ return 0;
+}
+
+
+/* results in fully updated anim system */
+/* in future sound should be on WM level, only 1 sound can play! */
+void ED_update_for_newframe(const bContext *C, int mute)
+{
+ bScreen *screen= CTX_wm_screen(C);
+ Scene *scene= screen->scene;
+
+ //extern void audiostream_scrub(unsigned int frame); /* seqaudio.c */
+
+ /* this function applies the changes too */
+ /* XXX future: do all windows */
+ scene_update_for_newframe(scene, ED_screen_view3d_layers(screen)); /* BKE_scene.h */
+
+ //if ( (CFRA>1) && (!mute) && (scene->audio.flag & AUDIO_SCRUB))
+ // audiostream_scrub( CFRA );
+
+ /* 3d window, preview */
+ //BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
+
+ /* all movie/sequence images */
+ //BIF_image_update_frame();
+
+ /* composite */
+ if(scene->use_nodes && scene->nodetree)
+ ntreeCompositTagAnimated(scene->nodetree);
+
+ /* update animated texture nodes */
+ {
+ Tex *tex;
+ for(tex= CTX_data_main(C)->tex.first; tex; tex= tex->id.next)
+ if( tex->use_nodes && tex->nodetree ) {
+ ntreeTexTagAnimated( tex->nodetree );
+ }
+ }
+}
+
+
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
new file mode 100644
index 00000000000..a0804f3e633
--- /dev/null
+++ b/source/blender/editors/screen/screen_intern.h
@@ -0,0 +1,68 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_SCREEN_INTERN_H
+#define ED_SCREEN_INTERN_H
+
+/* internal exports only */
+struct wmWindow;
+struct Scene;
+
+/* area.c */
+void area_copy_data (ScrArea *sa1, ScrArea *sa2, int swap_space);
+
+/* screen_edit.c */
+bScreen *screen_add(struct wmWindow *win, struct Scene *scene, char *name);
+ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2);
+ScrArea *area_split(wmWindow *win, bScreen *sc, ScrArea *sa, char dir, float fac);
+int screen_area_join(bContext *C, bScreen* scr, ScrArea *sa1, ScrArea *sa2);
+int area_getorientation(bScreen *screen, ScrArea *sa, ScrArea *sb);
+void select_connected_scredge(bScreen *sc, ScrEdge *edge);
+
+void removenotused_scrverts(bScreen *sc);
+void removedouble_scrverts(bScreen *sc);
+void removedouble_scredges(bScreen *sc);
+void removenotused_scredges(bScreen *sc);
+int scredge_is_horizontal(ScrEdge *se);
+ScrEdge *screen_find_active_scredge(bScreen *sc, int mx, int my);
+
+AZone *is_in_area_actionzone(ScrArea *sa, int x, int y);
+
+void ed_screen_fullarea(bContext *C, ScrArea *sa);
+
+/* screen_context.c */
+void ed_screen_context(const bContext *C, const char *member, bContextDataResult *result);
+
+/* screendump.c */
+void SCREEN_OT_screenshot(struct wmOperatorType *ot);
+void SCREEN_OT_screencast(struct wmOperatorType *ot);
+
+#endif /* ED_SCREEN_INTERN_H */
+
+
+
+
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
new file mode 100644
index 00000000000..bf57e2e7d52
--- /dev/null
+++ b/source/blender/editors/screen/screen_ops.c
@@ -0,0 +1,2469 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_image_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_blender.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_idprop.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_multires.h"
+#include "BKE_report.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_util.h"
+#include "ED_screen.h"
+#include "ED_mesh.h"
+#include "ED_screen_types.h"
+
+#include "RE_pipeline.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "screen_intern.h" /* own module include */
+
+/* ************** Exported Poll tests ********************** */
+
+int ED_operator_regionactive(bContext *C)
+{
+ if(CTX_wm_window(C)==NULL) return 0;
+ if(CTX_wm_screen(C)==NULL) return 0;
+ if(CTX_wm_region(C)==NULL) return 0;
+ return 1;
+}
+
+int ED_operator_areaactive(bContext *C)
+{
+ if(CTX_wm_window(C)==NULL) return 0;
+ if(CTX_wm_screen(C)==NULL) return 0;
+ if(CTX_wm_area(C)==NULL) return 0;
+ return 1;
+}
+
+int ED_operator_screenactive(bContext *C)
+{
+ if(CTX_wm_window(C)==NULL) return 0;
+ if(CTX_wm_screen(C)==NULL) return 0;
+ return 1;
+}
+
+/* when mouse is over area-edge */
+int ED_operator_screen_mainwinactive(bContext *C)
+{
+ if(CTX_wm_window(C)==NULL) return 0;
+ if(CTX_wm_screen(C)==NULL) return 0;
+ if (CTX_wm_screen(C)->subwinactive!=CTX_wm_screen(C)->mainwin) return 0;
+ return 1;
+}
+
+int ED_operator_scene_editable(bContext *C)
+{
+ Scene *scene= CTX_data_scene(C);
+ if(scene && scene->id.lib==NULL)
+ return 1;
+ return 0;
+}
+
+static int ed_spacetype_test(bContext *C, int type)
+{
+ if(ED_operator_areaactive(C)) {
+ SpaceLink *sl= (SpaceLink *)CTX_wm_space_data(C);
+ return sl && (sl->spacetype == type);
+ }
+ return 0;
+}
+
+int ED_operator_view3d_active(bContext *C)
+{
+ return ed_spacetype_test(C, SPACE_VIEW3D);
+}
+
+int ED_operator_timeline_active(bContext *C)
+{
+ return ed_spacetype_test(C, SPACE_TIME);
+}
+
+int ED_operator_outliner_active(bContext *C)
+{
+ return ed_spacetype_test(C, SPACE_OUTLINER);
+}
+
+int ED_operator_file_active(bContext *C)
+{
+ return ed_spacetype_test(C, SPACE_FILE);
+}
+
+int ED_operator_action_active(bContext *C)
+{
+ return ed_spacetype_test(C, SPACE_ACTION);
+}
+
+int ED_operator_buttons_active(bContext *C)
+{
+ return ed_spacetype_test(C, SPACE_BUTS);
+}
+
+int ED_operator_node_active(bContext *C)
+{
+ if(ed_spacetype_test(C, SPACE_NODE)) {
+ SpaceNode *snode= (SpaceNode *)CTX_wm_space_data(C);
+ if(snode->edittree)
+ return 1;
+ }
+ return 0;
+}
+
+int ED_operator_ipo_active(bContext *C)
+{
+ return ed_spacetype_test(C, SPACE_IPO);
+}
+
+int ED_operator_sequencer_active(bContext *C)
+{
+ return ed_spacetype_test(C, SPACE_SEQ);
+}
+
+int ED_operator_image_active(bContext *C)
+{
+ return ed_spacetype_test(C, SPACE_IMAGE);
+}
+
+int ED_operator_object_active(bContext *C)
+{
+ return NULL != CTX_data_active_object(C);
+}
+
+int ED_operator_editmesh(bContext *C)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ if(obedit && obedit->type==OB_MESH)
+ return NULL != ((Mesh *)obedit->data)->edit_mesh;
+ return 0;
+}
+
+int ED_operator_editarmature(bContext *C)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ if(obedit && obedit->type==OB_ARMATURE)
+ return NULL != ((bArmature *)obedit->data)->edbo;
+ return 0;
+}
+
+int ED_operator_posemode(bContext *C)
+{
+ Object *obact= CTX_data_active_object(C);
+ Object *obedit= CTX_data_edit_object(C);
+
+ if ((obact != obedit) && (obact) && (obact->type==OB_ARMATURE))
+ return (obact->flag & OB_POSEMODE)!=0;
+
+ return 0;
+}
+
+
+int ED_operator_uvedit(bContext *C)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= NULL;
+
+ if(obedit && obedit->type==OB_MESH)
+ em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ if(em && (em->faces.first) && (CustomData_has_layer(&em->fdata, CD_MTFACE))) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return 1;
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return 0;
+}
+
+int ED_operator_uvmap(bContext *C)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= NULL;
+
+ if(obedit && obedit->type==OB_MESH)
+ em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ if(em && (em->faces.first)) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return 1;
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return 0;
+}
+
+int ED_operator_editsurfcurve(bContext *C)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ if(obedit && ELEM(obedit->type, OB_CURVE, OB_SURF))
+ return NULL != ((Curve *)obedit->data)->editnurb;
+ return 0;
+}
+
+
+int ED_operator_editcurve(bContext *C)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ if(obedit && obedit->type==OB_CURVE)
+ return NULL != ((Curve *)obedit->data)->editnurb;
+ return 0;
+}
+
+int ED_operator_editsurf(bContext *C)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ if(obedit && obedit->type==OB_SURF)
+ return NULL != ((Curve *)obedit->data)->editnurb;
+ return 0;
+}
+
+int ED_operator_editfont(bContext *C)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ if(obedit && obedit->type==OB_FONT)
+ return NULL != ((Curve *)obedit->data)->editfont;
+ return 0;
+}
+
+/* *************************** action zone operator ************************** */
+
+/* operator state vars used:
+ none
+
+functions:
+
+ apply() set actionzone event
+
+ exit() free customdata
+
+callbacks:
+
+ exec() never used
+
+ invoke() check if in zone
+ add customdata, put mouseco and area in it
+ add modal handler
+
+ modal() accept modal events while doing it
+ call apply() with gesture info, active window, nonactive window
+ call exit() and remove handler when LMB confirm
+
+*/
+
+typedef struct sActionzoneData {
+ ScrArea *sa1, *sa2;
+ AZone *az;
+ int x, y, gesture_dir, modifier;
+} sActionzoneData;
+
+/* used by other operators too */
+static ScrArea *screen_areahascursor(bScreen *scr, int x, int y)
+{
+ ScrArea *sa= NULL;
+ sa= scr->areabase.first;
+ while(sa) {
+ if(BLI_in_rcti(&sa->totrct, x, y)) break;
+ sa= sa->next;
+ }
+
+ return sa;
+}
+
+
+AZone *is_in_area_actionzone(ScrArea *sa, int x, int y)
+{
+ AZone *az= NULL;
+ int i= 0;
+
+ for(az= sa->actionzones.first, i= 0; az; az= az->next, i++) {
+ if(az->type == AZONE_TRI) {
+ if(IsPointInTri2DInts(az->x1, az->y1, az->x2, az->y2, x, y))
+ break;
+ }
+ if(az->type == AZONE_QUAD) {
+ if(az->x1 < x && x < az->x2 && az->y1 < y && y < az->y2)
+ break;
+ }
+ }
+
+ return az;
+}
+
+static int actionzone_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ AZone *az= is_in_area_actionzone(CTX_wm_area(C), event->x, event->y);
+ sActionzoneData *sad;
+
+ /* quick escape */
+ if(az==NULL)
+ return OPERATOR_PASS_THROUGH;
+
+ /* ok we do the actionzone */
+ sad= op->customdata= MEM_callocN(sizeof(sActionzoneData), "sActionzoneData");
+ sad->sa1= CTX_wm_area(C);
+ sad->az= az;
+ sad->x= event->x; sad->y= event->y;
+
+ /* add modal handler */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void actionzone_exit(bContext *C, wmOperator *op)
+{
+ if(op->customdata)
+ MEM_freeN(op->customdata);
+ op->customdata= NULL;
+}
+
+/* send EVT_ACTIONZONE event */
+static void actionzone_apply(bContext *C, wmOperator *op)
+{
+ wmEvent event;
+ wmWindow *win= CTX_wm_window(C);
+ sActionzoneData *sad= op->customdata;
+ sad->modifier= RNA_int_get(op->ptr, "modifier");
+
+ event= *(win->eventstate); /* XXX huh huh? make api call */
+ event.type= EVT_ACTIONZONE;
+ event.customdata= op->customdata;
+ event.customdatafree= TRUE;
+ op->customdata= NULL;
+
+ wm_event_add(win, &event);
+}
+
+static int actionzone_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sActionzoneData *sad= op->customdata;
+ int deltax, deltay;
+
+ switch(event->type) {
+ case MOUSEMOVE:
+ /* calculate gesture direction */
+ deltax= (event->x - sad->x);
+ deltay= (event->y - sad->y);
+
+ if(deltay > ABS(deltax))
+ sad->gesture_dir= AZONE_N;
+ else if(deltax > ABS(deltay))
+ sad->gesture_dir= AZONE_E;
+ else if(deltay < -ABS(deltax))
+ sad->gesture_dir= AZONE_S;
+ else
+ sad->gesture_dir= AZONE_W;
+
+ /* gesture is large enough? */
+ if(ABS(deltax) > 12 || ABS(deltay) > 12) {
+
+ /* second area, for join */
+ sad->sa2= screen_areahascursor(CTX_wm_screen(C), event->x, event->y);
+ /* apply sends event */
+ actionzone_apply(C, op);
+ actionzone_exit(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+ break;
+ case ESCKEY:
+ case LEFTMOUSE:
+ actionzone_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void SCREEN_OT_actionzone(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Handle area action zones";
+ ot->idname= "SCREEN_OT_actionzone";
+
+ ot->invoke= actionzone_invoke;
+ ot->modal= actionzone_modal;
+
+ ot->poll= ED_operator_areaactive;
+ RNA_def_int(ot->srna, "modifier", 0, 0, 2, "modifier", "modifier state", 0, 2);
+}
+
+/* ************** swap area operator *********************************** */
+
+/* operator state vars used:
+ sa1 start area
+ sa2 area to swap with
+
+ functions:
+
+ init() set custom data for operator, based on actionzone event custom data
+
+ cancel() cancel the operator
+
+ exit() cleanup, send notifier
+
+ callbacks:
+
+ invoke() gets called on shift+lmb drag in actionzone
+ call init(), add handler
+
+ modal() accept modal events while doing it
+
+*/
+
+typedef struct sAreaSwapData {
+ ScrArea *sa1, *sa2;
+} sAreaSwapData;
+
+static int area_swap_init(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sAreaSwapData *sd= NULL;
+ sActionzoneData *sad= event->customdata;
+
+ if(sad==NULL || sad->sa1==NULL)
+ return 0;
+
+ sd= MEM_callocN(sizeof(sAreaSwapData), "sAreaSwapData");
+ sd->sa1= sad->sa1;
+ sd->sa2= sad->sa2;
+ op->customdata= sd;
+
+ return 1;
+}
+
+
+static void area_swap_exit(bContext *C, wmOperator *op)
+{
+ if(op->customdata)
+ MEM_freeN(op->customdata);
+ op->customdata= NULL;
+}
+
+static int area_swap_cancel(bContext *C, wmOperator *op)
+{
+ area_swap_exit(C, op);
+ return OPERATOR_CANCELLED;
+}
+
+static int area_swap_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+
+ if(!area_swap_init(C, op, event))
+ return OPERATOR_PASS_THROUGH;
+
+ /* add modal handler */
+ WM_cursor_modal(CTX_wm_window(C), BC_SWAPAREA_CURSOR);
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+
+}
+
+static int area_swap_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sActionzoneData *sad= op->customdata;
+
+ switch(event->type) {
+ case MOUSEMOVE:
+ /* second area, for join */
+ sad->sa2= screen_areahascursor(CTX_wm_screen(C), event->x, event->y);
+ break;
+ case LEFTMOUSE: /* release LMB */
+ if(event->val==0) {
+ if(sad->sa1 == sad->sa2) {
+
+ return area_swap_cancel(C, op);
+ }
+ ED_area_swapspace(C, sad->sa1, sad->sa2);
+
+ area_swap_exit(C, op);
+
+ WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+ }
+ break;
+
+ case ESCKEY:
+ return area_swap_cancel(C, op);
+ }
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void SCREEN_OT_area_swap(wmOperatorType *ot)
+{
+ ot->name= "Swap areas";
+ ot->idname= "SCREEN_OT_area_swap";
+
+ ot->invoke= area_swap_invoke;
+ ot->modal= area_swap_modal;
+ ot->poll= ED_operator_areaactive;
+}
+
+/* *********** Duplicate area as new window operator ****************** */
+
+/* operator callback */
+static int area_dupli_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ wmWindow *newwin, *win;
+ bScreen *newsc, *sc;
+ ScrArea *sa;
+ rcti rect;
+ sActionzoneData *sad= event->customdata;
+
+ if(sad==NULL)
+ return OPERATOR_PASS_THROUGH;
+
+ win= CTX_wm_window(C);
+ sc= CTX_wm_screen(C);
+ sa= sad->sa1;
+
+ /* poll() checks area context, but we don't accept full-area windows */
+ if(sc->full != SCREENNORMAL) {
+ actionzone_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* adds window to WM */
+ rect= sa->totrct;
+ BLI_translate_rcti(&rect, win->posx, win->posy);
+ newwin= WM_window_open(C, &rect);
+
+ /* allocs new screen and adds to newly created window, using window size */
+ newsc= screen_add(newwin, CTX_data_scene(C), sc->id.name+2);
+ newwin->screen= newsc;
+
+ /* copy area to new screen */
+ area_copy_data((ScrArea *)newsc->areabase.first, sa, 0);
+
+ /* screen, areas init */
+ WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
+
+ actionzone_exit(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCREEN_OT_area_dupli(wmOperatorType *ot)
+{
+ ot->name= "Duplicate Area into New Window";
+ ot->idname= "SCREEN_OT_area_dupli";
+
+ ot->invoke= area_dupli_invoke;
+ ot->poll= ED_operator_areaactive;
+}
+
+
+/* ************** move area edge operator *********************************** */
+
+/* operator state vars used:
+ x, y mouse coord near edge
+ delta movement of edge
+
+ functions:
+
+ init() set default property values, find edge based on mouse coords, test
+ if the edge can be moved, select edges, calculate min and max movement
+
+ apply() apply delta on selection
+
+ exit() cleanup, send notifier
+
+ cancel() cancel moving
+
+ callbacks:
+
+ exec() execute without any user interaction, based on properties
+ call init(), apply(), exit()
+
+ invoke() gets called on mouse click near edge
+ call init(), add handler
+
+ modal() accept modal events while doing it
+ call apply() with delta motion
+ call exit() and remove handler
+
+*/
+
+typedef struct sAreaMoveData {
+ int bigger, smaller, origval;
+ char dir;
+} sAreaMoveData;
+
+/* helper call to move area-edge, sets limits */
+static void area_move_set_limits(bScreen *sc, int dir, int *bigger, int *smaller)
+{
+ ScrArea *sa;
+
+ /* we check all areas and test for free space with MINSIZE */
+ *bigger= *smaller= 100000;
+
+ for(sa= sc->areabase.first; sa; sa= sa->next) {
+ if(dir=='h') {
+ int y1= sa->v2->vec.y - sa->v1->vec.y-AREAMINY;
+
+ /* if top or down edge selected, test height */
+ if(sa->v1->flag && sa->v4->flag)
+ *bigger= MIN2(*bigger, y1);
+ else if(sa->v2->flag && sa->v3->flag)
+ *smaller= MIN2(*smaller, y1);
+ }
+ else {
+ int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
+
+ /* if left or right edge selected, test width */
+ if(sa->v1->flag && sa->v2->flag)
+ *bigger= MIN2(*bigger, x1);
+ else if(sa->v3->flag && sa->v4->flag)
+ *smaller= MIN2(*smaller, x1);
+ }
+ }
+}
+
+/* validate selection inside screen, set variables OK */
+/* return 0: init failed */
+static int area_move_init (bContext *C, wmOperator *op)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ ScrEdge *actedge;
+ sAreaMoveData *md;
+ int x, y;
+
+ /* required properties */
+ x= RNA_int_get(op->ptr, "x");
+ y= RNA_int_get(op->ptr, "y");
+
+ /* setup */
+ actedge= screen_find_active_scredge(sc, x, y);
+ if(actedge==NULL) return 0;
+
+ md= MEM_callocN(sizeof(sAreaMoveData), "sAreaMoveData");
+ op->customdata= md;
+
+ md->dir= scredge_is_horizontal(actedge)?'h':'v';
+ if(md->dir=='h') md->origval= actedge->v1->vec.y;
+ else md->origval= actedge->v1->vec.x;
+
+ select_connected_scredge(sc, actedge);
+ /* now all vertices with 'flag==1' are the ones that can be moved. */
+
+ area_move_set_limits(sc, md->dir, &md->bigger, &md->smaller);
+
+ return 1;
+}
+
+/* moves selected screen edge amount of delta, used by split & move */
+static void area_move_apply_do(bContext *C, int origval, int delta, int dir, int bigger, int smaller)
+{
+ wmWindow *win= CTX_wm_window(C);
+ bScreen *sc= CTX_wm_screen(C);
+ ScrVert *v1;
+
+ delta= CLAMPIS(delta, -smaller, bigger);
+
+ for (v1= sc->vertbase.first; v1; v1= v1->next) {
+ if (v1->flag) {
+ /* that way a nice AREAGRID */
+ if((dir=='v') && v1->vec.x>0 && v1->vec.x<win->sizex-1) {
+ v1->vec.x= origval + delta;
+ if(delta != bigger && delta != -smaller) v1->vec.x-= (v1->vec.x % AREAGRID);
+ }
+ if((dir=='h') && v1->vec.y>0 && v1->vec.y<win->sizey-1) {
+ v1->vec.y= origval + delta;
+
+ v1->vec.y+= AREAGRID-1;
+ v1->vec.y-= (v1->vec.y % AREAGRID);
+
+ /* prevent too small top header */
+ if(v1->vec.y > win->sizey-AREAMINY)
+ v1->vec.y= win->sizey-AREAMINY;
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
+}
+
+static void area_move_apply(bContext *C, wmOperator *op)
+{
+ sAreaMoveData *md= op->customdata;
+ int delta;
+
+ delta= RNA_int_get(op->ptr, "delta");
+ area_move_apply_do(C, md->origval, delta, md->dir, md->bigger, md->smaller);
+}
+
+static void area_move_exit(bContext *C, wmOperator *op)
+{
+ if(op->customdata)
+ MEM_freeN(op->customdata);
+ op->customdata= NULL;
+
+ /* this makes sure aligned edges will result in aligned grabbing */
+ removedouble_scrverts(CTX_wm_screen(C));
+ removedouble_scredges(CTX_wm_screen(C));
+}
+
+static int area_move_exec(bContext *C, wmOperator *op)
+{
+ if(!area_move_init(C, op))
+ return OPERATOR_CANCELLED;
+
+ area_move_apply(C, op);
+ area_move_exit(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+/* interaction callback */
+static int area_move_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ RNA_int_set(op->ptr, "x", event->x);
+ RNA_int_set(op->ptr, "y", event->y);
+
+ if(!area_move_init(C, op))
+ return OPERATOR_PASS_THROUGH;
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int area_move_cancel(bContext *C, wmOperator *op)
+{
+
+ RNA_int_set(op->ptr, "delta", 0);
+ area_move_apply(C, op);
+ area_move_exit(C, op);
+
+ return OPERATOR_CANCELLED;
+}
+
+/* modal callback for while moving edges */
+static int area_move_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sAreaMoveData *md;
+ int delta, x, y;
+
+ md= op->customdata;
+
+ x= RNA_int_get(op->ptr, "x");
+ y= RNA_int_get(op->ptr, "y");
+
+ /* execute the events */
+ switch(event->type) {
+ case MOUSEMOVE:
+ delta= (md->dir == 'v')? event->x - x: event->y - y;
+ RNA_int_set(op->ptr, "delta", delta);
+
+ area_move_apply(C, op);
+ break;
+
+ case LEFTMOUSE:
+ if(event->val==0) {
+ area_move_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ break;
+
+ case ESCKEY:
+ return area_move_cancel(C, op);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void SCREEN_OT_area_move(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Move area edges";
+ ot->idname= "SCREEN_OT_area_move";
+
+ ot->exec= area_move_exec;
+ ot->invoke= area_move_invoke;
+ ot->cancel= area_move_cancel;
+ ot->modal= area_move_modal;
+
+ ot->poll= ED_operator_screen_mainwinactive; /* when mouse is over area-edge */
+
+ /* rna */
+ RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
+}
+
+/* ************** split area operator *********************************** */
+
+/*
+operator state vars:
+ fac spit point
+ dir direction 'v' or 'h'
+
+operator customdata:
+ area pointer to (active) area
+ x, y last used mouse pos
+ (more, see below)
+
+functions:
+
+ init() set default property values, find area based on context
+
+ apply() split area based on state vars
+
+ exit() cleanup, send notifier
+
+ cancel() remove duplicated area
+
+callbacks:
+
+ exec() execute without any user interaction, based on state vars
+ call init(), apply(), exit()
+
+ invoke() gets called on mouse click in action-widget
+ call init(), add modal handler
+ call apply() with initial motion
+
+ modal() accept modal events while doing it
+ call move-areas code with delta motion
+ call exit() or cancel() and remove handler
+
+*/
+
+#define SPLIT_STARTED 1
+#define SPLIT_PROGRESS 2
+
+typedef struct sAreaSplitData
+{
+ int x, y; /* last used mouse position */
+
+ int origval; /* for move areas */
+ int bigger, smaller; /* constraints for moving new edge */
+ int delta; /* delta move edge */
+ int origmin, origsize; /* to calculate fac, for property storage */
+
+ ScrEdge *nedge; /* new edge */
+ ScrArea *sarea; /* start area */
+ ScrArea *narea; /* new area */
+} sAreaSplitData;
+
+/* generic init, no UI stuff here */
+static int area_split_init(bContext *C, wmOperator *op)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ sAreaSplitData *sd;
+ int dir;
+
+ /* required context */
+ if(sa==NULL) return 0;
+
+ /* required properties */
+ dir= RNA_enum_get(op->ptr, "direction");
+
+ /* minimal size */
+ if(dir=='v' && sa->winx < 2*AREAMINX) return 0;
+ if(dir=='h' && sa->winy < 2*AREAMINY) return 0;
+
+ /* custom data */
+ sd= (sAreaSplitData*)MEM_callocN(sizeof (sAreaSplitData), "op_area_split");
+ op->customdata= sd;
+
+ sd->sarea= sa;
+ sd->origsize= dir=='v' ? sa->winx:sa->winy;
+ sd->origmin = dir=='v' ? sa->totrct.xmin:sa->totrct.ymin;
+
+ return 1;
+}
+
+/* with sa as center, sb is located at: 0=W, 1=N, 2=E, 3=S */
+/* used with split operator */
+static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *sa, ScrArea *sb)
+{
+ ScrVert *sav1= sa->v1;
+ ScrVert *sav2= sa->v2;
+ ScrVert *sav3= sa->v3;
+ ScrVert *sav4= sa->v4;
+ ScrVert *sbv1= sb->v1;
+ ScrVert *sbv2= sb->v2;
+ ScrVert *sbv3= sb->v3;
+ ScrVert *sbv4= sb->v4;
+
+ if(sav1==sbv4 && sav2==sbv3) { /* sa to right of sb = W */
+ return screen_findedge(screen, sav1, sav2);
+ }
+ else if(sav2==sbv1 && sav3==sbv4) { /* sa to bottom of sb = N */
+ return screen_findedge(screen, sav2, sav3);
+ }
+ else if(sav3==sbv2 && sav4==sbv1) { /* sa to left of sb = E */
+ return screen_findedge(screen, sav3, sav4);
+ }
+ else if(sav1==sbv2 && sav4==sbv3) { /* sa on top of sb = S*/
+ return screen_findedge(screen, sav1, sav4);
+ }
+
+ return NULL;
+}
+
+
+/* do the split, return success */
+static int area_split_apply(bContext *C, wmOperator *op)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
+ float fac;
+ int dir;
+
+ fac= RNA_float_get(op->ptr, "factor");
+ dir= RNA_enum_get(op->ptr, "direction");
+
+ sd->narea= area_split(CTX_wm_window(C), sc, sd->sarea, dir, fac);
+
+ if(sd->narea) {
+ ScrVert *sv;
+
+ sd->nedge= area_findsharededge(sc, sd->sarea, sd->narea);
+
+ /* select newly created edge, prepare for moving edge */
+ for(sv= sc->vertbase.first; sv; sv= sv->next)
+ sv->flag = 0;
+
+ sd->nedge->v1->flag= 1;
+ sd->nedge->v2->flag= 1;
+
+ if(dir=='h') sd->origval= sd->nedge->v1->vec.y;
+ else sd->origval= sd->nedge->v1->vec.x;
+
+ WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static void area_split_exit(bContext *C, wmOperator *op)
+{
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+ }
+
+ WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
+
+ /* this makes sure aligned edges will result in aligned grabbing */
+ removedouble_scrverts(CTX_wm_screen(C));
+ removedouble_scredges(CTX_wm_screen(C));
+}
+
+
+/* UI callback, adds new handler */
+static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sAreaSplitData *sd;
+
+ if(event->type==EVT_ACTIONZONE) {
+ sActionzoneData *sad= event->customdata;
+ int dir;
+
+ if(sad->modifier>0) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* verify *sad itself */
+ if(sad==NULL || sad->sa1==NULL || sad->az==NULL)
+ return OPERATOR_PASS_THROUGH;
+
+ /* is this our *sad? if areas not equal it should be passed on */
+ if(CTX_wm_area(C)!=sad->sa1 || sad->sa1!=sad->sa2)
+ return OPERATOR_PASS_THROUGH;
+
+ /* prepare operator state vars */
+ if(sad->gesture_dir==AZONE_N || sad->gesture_dir==AZONE_S) {
+ dir= 'h';
+ RNA_float_set(op->ptr, "factor", ((float)(event->x - sad->sa1->v1->vec.x)) / (float)sad->sa1->winx);
+ }
+ else {
+ dir= 'v';
+ RNA_float_set(op->ptr, "factor", ((float)(event->y - sad->sa1->v1->vec.y)) / (float)sad->sa1->winy);
+ }
+ RNA_enum_set(op->ptr, "direction", dir);
+
+ /* general init, also non-UI case, adds customdata, sets area and defaults */
+ if(!area_split_init(C, op))
+ return OPERATOR_PASS_THROUGH;
+
+ sd= (sAreaSplitData *)op->customdata;
+
+ sd->x= event->x;
+ sd->y= event->y;
+
+ /* do the split */
+ if(area_split_apply(C, op)) {
+ area_move_set_limits(CTX_wm_screen(C), dir, &sd->bigger, &sd->smaller);
+
+ /* add temp handler for edge move or cancel */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ }
+ else {
+ /* nonmodal for now */
+ return op->type->exec(C, op);
+ }
+
+ return OPERATOR_PASS_THROUGH;
+}
+
+/* function to be called outside UI context, or for redo */
+static int area_split_exec(bContext *C, wmOperator *op)
+{
+
+ if(!area_split_init(C, op))
+ return OPERATOR_CANCELLED;
+
+ area_split_apply(C, op);
+ area_split_exit(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+
+static int area_split_cancel(bContext *C, wmOperator *op)
+{
+ sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
+
+ if (screen_area_join(C, CTX_wm_screen(C), sd->sarea, sd->narea)) {
+ if (CTX_wm_area(C) == sd->narea) {
+ CTX_wm_area_set(C, NULL);
+ CTX_wm_region_set(C, NULL);
+ }
+ sd->narea = NULL;
+ }
+ area_split_exit(C, op);
+
+ return OPERATOR_CANCELLED;
+}
+
+static int area_split_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
+ float fac;
+ int dir;
+
+ /* execute the events */
+ switch(event->type) {
+ case MOUSEMOVE:
+ dir= RNA_enum_get(op->ptr, "direction");
+
+ sd->delta= (dir == 'v')? event->x - sd->origval: event->y - sd->origval;
+ area_move_apply_do(C, sd->origval, sd->delta, dir, sd->bigger, sd->smaller);
+
+ fac= (dir == 'v') ? event->x-sd->origmin : event->y-sd->origmin;
+ RNA_float_set(op->ptr, "factor", fac / (float)sd->origsize);
+
+ WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
+ break;
+
+ case LEFTMOUSE:
+ if(event->val==0) { /* mouse up */
+ area_split_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ break;
+ case RIGHTMOUSE: /* cancel operation */
+ case ESCKEY:
+ return area_split_cancel(C, op);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static EnumPropertyItem prop_direction_items[] = {
+ {'h', "HORIZONTAL", "Horizontal", ""},
+ {'v', "VERTICAL", "Vertical", ""},
+ {0, NULL, NULL, NULL}};
+
+void SCREEN_OT_area_split(wmOperatorType *ot)
+{
+ ot->name = "Split area";
+ ot->idname = "SCREEN_OT_area_split";
+
+ ot->exec= area_split_exec;
+ ot->invoke= area_split_invoke;
+ ot->modal= area_split_modal;
+
+ ot->poll= ED_operator_areaactive;
+ ot->flag= OPTYPE_REGISTER;
+
+ /* rna */
+ RNA_def_enum(ot->srna, "direction", prop_direction_items, 'h', "Direction", "");
+ RNA_def_float(ot->srna, "factor", 0.5f, 0.0, 1.0, "Factor", "", 0.0, 1.0);
+}
+
+/* ************** frame change operator ***************************** */
+
+
+/* function to be called outside UI context, or for redo */
+static int frame_offset_exec(bContext *C, wmOperator *op)
+{
+ int delta;
+
+ delta = RNA_int_get(op->ptr, "delta");
+
+ CTX_data_scene(C)->r.cfra += delta;
+
+ WM_event_add_notifier(C, NC_SCENE|ND_FRAME, CTX_data_scene(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SCREEN_OT_frame_offset(wmOperatorType *ot)
+{
+ ot->name = "Frame Offset";
+ ot->idname = "SCREEN_OT_frame_offset";
+
+ ot->exec= frame_offset_exec;
+
+ ot->poll= ED_operator_screenactive;
+ ot->flag= 0;
+
+ /* rna */
+ RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
+}
+
+/* ************** switch screen operator ***************************** */
+
+
+/* function to be called outside UI context, or for redo */
+static int screen_set_exec(bContext *C, wmOperator *op)
+{
+ bScreen *screen= CTX_wm_screen(C);
+ ScrArea *sa= CTX_wm_area(C);
+ int tot= BLI_countlist(&CTX_data_main(C)->screen);
+ int delta= RNA_int_get(op->ptr, "delta");
+
+ /* this screen is 'fake', solve later XXX */
+ if(sa && sa->full)
+ return OPERATOR_CANCELLED;
+
+ if(delta==1) {
+ while(tot--) {
+ screen= screen->id.next;
+ if(screen==NULL) screen= CTX_data_main(C)->screen.first;
+ if(screen->winid==0 && screen->full==0)
+ break;
+ }
+ }
+ else if(delta== -1) {
+ while(tot--) {
+ screen= screen->id.prev;
+ if(screen==NULL) screen= CTX_data_main(C)->screen.last;
+ if(screen->winid==0 && screen->full==0)
+ break;
+ }
+ }
+ else {
+ screen= NULL;
+ }
+
+ if(screen) {
+ ED_screen_set(C, screen);
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_CANCELLED;
+}
+
+void SCREEN_OT_screen_set(wmOperatorType *ot)
+{
+ ot->name = "Set Screen";
+ ot->idname = "SCREEN_OT_screen_set";
+
+ ot->exec= screen_set_exec;
+ ot->poll= ED_operator_screenactive;
+
+ /* rna */
+ RNA_def_pointer_runtime(ot->srna, "screen", &RNA_Screen, "Screen", "");
+ RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
+}
+
+/* ************** screen full-area operator ***************************** */
+
+
+/* function to be called outside UI context, or for redo */
+static int screen_full_area_exec(bContext *C, wmOperator *op)
+{
+ ed_screen_fullarea(C, CTX_wm_area(C));
+ return OPERATOR_FINISHED;
+}
+
+void SCREEN_OT_screen_full_area(wmOperatorType *ot)
+{
+ ot->name = "Toggle Make Area Fullscreen";
+ ot->idname = "SCREEN_OT_screen_full_area";
+
+ ot->exec= screen_full_area_exec;
+ ot->poll= ED_operator_areaactive;
+ ot->flag= 0;
+
+}
+
+
+
+/* ************** join area operator ********************************************** */
+
+/* operator state vars used:
+ x1, y1 mouse coord in first area, which will disappear
+ x2, y2 mouse coord in 2nd area, which will become joined
+
+functions:
+
+ init() find edge based on state vars
+ test if the edge divides two areas,
+ store active and nonactive area,
+
+ apply() do the actual join
+
+ exit() cleanup, send notifier
+
+callbacks:
+
+ exec() calls init, apply, exit
+
+ invoke() sets mouse coords in x,y
+ call init()
+ add modal handler
+
+ modal() accept modal events while doing it
+ call apply() with active window and nonactive window
+ call exit() and remove handler when LMB confirm
+
+*/
+
+typedef struct sAreaJoinData
+{
+ ScrArea *sa1; /* first area to be considered */
+ ScrArea *sa2; /* second area to be considered */
+ ScrArea *scr; /* designed for removal */
+
+} sAreaJoinData;
+
+
+/* validate selection inside screen, set variables OK */
+/* return 0: init failed */
+/* XXX todo: find edge based on (x,y) and set other area? */
+static int area_join_init(bContext *C, wmOperator *op)
+{
+ ScrArea *sa1, *sa2;
+ sAreaJoinData* jd= NULL;
+ int x1, y1;
+ int x2, y2;
+
+ /* required properties, make negative to get return 0 if not set by caller */
+ x1= RNA_int_get(op->ptr, "x1");
+ y1= RNA_int_get(op->ptr, "y1");
+ x2= RNA_int_get(op->ptr, "x2");
+ y2= RNA_int_get(op->ptr, "y2");
+
+ sa1 = screen_areahascursor(CTX_wm_screen(C), x1, y1);
+ sa2 = screen_areahascursor(CTX_wm_screen(C), x2, y2);
+ if(sa1==NULL || sa2==NULL || sa1==sa2)
+ return 0;
+
+ jd = (sAreaJoinData*)MEM_callocN(sizeof (sAreaJoinData), "op_area_join");
+
+ jd->sa1 = sa1;
+ jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
+ jd->sa2 = sa2;
+ jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
+
+ op->customdata= jd;
+
+ return 1;
+}
+
+/* apply the join of the areas (space types) */
+static int area_join_apply(bContext *C, wmOperator *op)
+{
+ sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
+ if (!jd) return 0;
+
+ if(!screen_area_join(C, CTX_wm_screen(C), jd->sa1, jd->sa2)){
+ return 0;
+ }
+ if (CTX_wm_area(C) == jd->sa2) {
+ CTX_wm_area_set(C, NULL);
+ CTX_wm_region_set(C, NULL);
+ }
+
+ return 1;
+}
+
+/* finish operation */
+static void area_join_exit(bContext *C, wmOperator *op)
+{
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+ }
+
+ /* this makes sure aligned edges will result in aligned grabbing */
+ removedouble_scredges(CTX_wm_screen(C));
+ removenotused_scredges(CTX_wm_screen(C));
+ removenotused_scrverts(CTX_wm_screen(C));
+}
+
+static int area_join_exec(bContext *C, wmOperator *op)
+{
+ if(!area_join_init(C, op))
+ return OPERATOR_CANCELLED;
+
+ area_join_apply(C, op);
+ area_join_exit(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+/* interaction callback */
+static int area_join_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+
+ if(event->type==EVT_ACTIONZONE) {
+ sActionzoneData *sad= event->customdata;
+
+ if(sad->modifier>0) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* verify *sad itself */
+ if(sad==NULL || sad->sa1==NULL || sad->sa2==NULL)
+ return OPERATOR_PASS_THROUGH;
+
+ /* is this our *sad? if areas equal it should be passed on */
+ if(sad->sa1==sad->sa2)
+ return OPERATOR_PASS_THROUGH;
+
+ /* prepare operator state vars */
+ RNA_int_set(op->ptr, "x1", sad->x);
+ RNA_int_set(op->ptr, "y1", sad->y);
+ RNA_int_set(op->ptr, "x2", event->x);
+ RNA_int_set(op->ptr, "y2", event->y);
+
+ if(!area_join_init(C, op))
+ return OPERATOR_PASS_THROUGH;
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ return OPERATOR_PASS_THROUGH;
+}
+
+static int area_join_cancel(bContext *C, wmOperator *op)
+{
+ sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
+
+ if (jd->sa1) {
+ jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
+ jd->sa1->flag &= ~AREA_FLAG_DRAWJOINTO;
+ }
+ if (jd->sa2) {
+ jd->sa2->flag &= ~AREA_FLAG_DRAWJOINFROM;
+ jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+ }
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+ area_join_exit(C, op);
+
+ return OPERATOR_CANCELLED;
+}
+
+/* modal callback while selecting area (space) that will be removed */
+static int area_join_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
+
+ /* execute the events */
+ switch(event->type) {
+
+ case MOUSEMOVE:
+ {
+ ScrArea *sa = screen_areahascursor(sc, event->x, event->y);
+ int dir;
+
+ if (sa) {
+ if (jd->sa1 != sa) {
+ dir = area_getorientation(sc, jd->sa1, sa);
+ if (dir >= 0) {
+ if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+ jd->sa2 = sa;
+ jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
+ }
+ else {
+ /* we are not bordering on the previously selected area
+ we check if area has common border with the one marked for removal
+ in this case we can swap areas.
+ */
+ dir = area_getorientation(sc, sa, jd->sa2);
+ if (dir >= 0) {
+ if (jd->sa1) jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
+ if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+ jd->sa1 = jd->sa2;
+ jd->sa2 = sa;
+ if (jd->sa1) jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
+ if (jd->sa2) jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
+ }
+ else {
+ if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+ jd->sa2 = NULL;
+ }
+ }
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ }
+ else {
+ /* we are back in the area previously selected for keeping
+ * we swap the areas if possible to allow user to choose */
+ if (jd->sa2 != NULL) {
+ if (jd->sa1) jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
+ if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+ jd->sa1 = jd->sa2;
+ jd->sa2 = sa;
+ if (jd->sa1) jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
+ if (jd->sa2) jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
+ dir = area_getorientation(sc, jd->sa1, jd->sa2);
+ if (dir < 0) {
+ printf("oops, didn't expect that!\n");
+ }
+ }
+ else {
+ dir = area_getorientation(sc, jd->sa1, sa);
+ if (dir >= 0) {
+ if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+ jd->sa2 = sa;
+ jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
+ }
+ }
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ }
+ }
+ }
+ break;
+ case LEFTMOUSE:
+ if(event->val==0) {
+ area_join_apply(C, op);
+ WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
+ area_join_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ break;
+
+ case ESCKEY:
+ return area_join_cancel(C, op);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* Operator for joining two areas (space types) */
+void SCREEN_OT_area_join(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Join area";
+ ot->idname= "SCREEN_OT_area_join";
+
+ /* api callbacks */
+ ot->exec= area_join_exec;
+ ot->invoke= area_join_invoke;
+ ot->modal= area_join_modal;
+
+ ot->poll= ED_operator_areaactive;
+
+ /* rna */
+ RNA_def_int(ot->srna, "x1", -100, INT_MIN, INT_MAX, "X 1", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "y1", -100, INT_MIN, INT_MAX, "Y 1", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "x2", -100, INT_MIN, INT_MAX, "X 2", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "y2", -100, INT_MIN, INT_MAX, "Y 2", "", INT_MIN, INT_MAX);
+}
+
+/* ************** repeat last operator ***************************** */
+
+static int repeat_last_exec(bContext *C, wmOperator *op)
+{
+ wmOperator *lastop= CTX_wm_manager(C)->operators.last;
+
+ if(lastop)
+ WM_operator_repeat(C, lastop);
+
+ return OPERATOR_CANCELLED;
+}
+
+void SCREEN_OT_repeat_last(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Repeat Last";
+ ot->idname= "SCREEN_OT_repeat_last";
+
+ /* api callbacks */
+ ot->exec= repeat_last_exec;
+
+ ot->poll= ED_operator_screenactive;
+
+}
+
+static int repeat_history_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ wmWindowManager *wm= CTX_wm_manager(C);
+ wmOperator *lastop;
+ uiMenuItem *head;
+ int items, i;
+
+ items= BLI_countlist(&wm->operators);
+ if(items==0)
+ return OPERATOR_CANCELLED;
+
+ head= uiPupMenuBegin(op->type->name, 0);
+
+ for (i=items-1, lastop= wm->operators.last; lastop; lastop= lastop->prev, i--)
+ uiMenuItemIntO(head, lastop->type->name, 0, op->type->idname, "index", i);
+
+ uiPupMenuEnd(C, head);
+
+ return OPERATOR_CANCELLED;
+}
+
+static int repeat_history_exec(bContext *C, wmOperator *op)
+{
+ wmWindowManager *wm= CTX_wm_manager(C);
+
+ op= BLI_findlink(&wm->operators, RNA_int_get(op->ptr, "index"));
+ if(op) {
+ /* let's put it as last operator in list */
+ BLI_remlink(&wm->operators, op);
+ BLI_addtail(&wm->operators, op);
+
+ WM_operator_repeat(C, op);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void SCREEN_OT_repeat_history(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Repeat History";
+ ot->idname= "SCREEN_OT_repeat_history";
+
+ /* api callbacks */
+ ot->invoke= repeat_history_invoke;
+ ot->exec= repeat_history_exec;
+
+ ot->poll= ED_operator_screenactive;
+
+ RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000);
+}
+
+/* ********************** redo operator ***************************** */
+
+static int redo_last_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ wmWindowManager *wm= CTX_wm_manager(C);
+ wmOperator *lastop;
+
+ /* only for operators that are registered and did an undo push */
+ for(lastop= wm->operators.last; lastop; lastop= lastop->prev)
+ if((lastop->type->flag & OPTYPE_REGISTER) && (lastop->type->flag & OPTYPE_UNDO))
+ break;
+
+ if(lastop)
+ WM_operator_redo_popup(C, lastop);
+
+ return OPERATOR_CANCELLED;
+}
+
+void SCREEN_OT_redo_last(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Redo Last";
+ ot->idname= "SCREEN_OT_redo_last";
+
+ /* api callbacks */
+ ot->invoke= redo_last_invoke;
+
+ ot->poll= ED_operator_screenactive;
+}
+
+/* ************** region split operator ***************************** */
+
+/* insert a region in the area region list */
+static int region_split_exec(bContext *C, wmOperator *op)
+{
+ ARegion *ar= CTX_wm_region(C);
+
+ if(ar->regiontype==RGN_TYPE_HEADER)
+ BKE_report(op->reports, RPT_ERROR, "Cannot split header");
+ else if(ar->alignment==RGN_ALIGN_QSPLIT)
+ BKE_report(op->reports, RPT_ERROR, "Cannot split further");
+ else {
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *newar= BKE_area_region_copy(sa->type, ar);
+ int dir= RNA_enum_get(op->ptr, "type");
+
+ BLI_insertlinkafter(&sa->regionbase, ar, newar);
+
+ newar->alignment= ar->alignment;
+
+ if(dir=='h')
+ ar->alignment= RGN_ALIGN_HSPLIT;
+ else
+ ar->alignment= RGN_ALIGN_VSPLIT;
+
+ WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void SCREEN_OT_region_split(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Split Region";
+ ot->idname= "SCREEN_OT_region_split";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= region_split_exec;
+ ot->poll= ED_operator_areaactive;
+
+ RNA_def_enum(ot->srna, "type", prop_direction_items, 'h', "Direction", "");
+}
+
+/* ************** region four-split operator ***************************** */
+
+/* insert a region in the area region list */
+static int region_foursplit_exec(bContext *C, wmOperator *op)
+{
+ ARegion *ar= CTX_wm_region(C);
+
+ /* some rules... */
+ if(ar->regiontype!=RGN_TYPE_WINDOW)
+ BKE_report(op->reports, RPT_ERROR, "Only window region can be 4-splitted");
+ else if(ar->alignment==RGN_ALIGN_QSPLIT) {
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *arn;
+
+ /* keep current region */
+ ar->alignment= 0;
+
+ if(sa->spacetype==SPACE_VIEW3D) {
+ RegionView3D *rv3d= ar->regiondata;
+ rv3d->viewlock= 0;
+ rv3d->rflag &= ~RV3D_CLIPPING;
+ }
+
+ for(ar= sa->regionbase.first; ar; ar= arn) {
+ arn= ar->next;
+ if(ar->alignment==RGN_ALIGN_QSPLIT) {
+ ED_region_exit(C, ar);
+ BKE_area_region_free(sa->type, ar);
+ BLI_remlink(&sa->regionbase, ar);
+ MEM_freeN(ar);
+ }
+ }
+ WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
+ }
+ else if(ar->next)
+ BKE_report(op->reports, RPT_ERROR, "Only last region can be 4-splitted");
+ else {
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *newar;
+ int count;
+
+ ar->alignment= RGN_ALIGN_QSPLIT;
+
+ for(count=0; count<3; count++) {
+ newar= BKE_area_region_copy(sa->type, ar);
+ BLI_addtail(&sa->regionbase, newar);
+ }
+
+ /* lock views and set them */
+ if(sa->spacetype==SPACE_VIEW3D) {
+ RegionView3D *rv3d;
+
+ rv3d= ar->regiondata;
+ rv3d->viewlock= RV3D_LOCKED; rv3d->view= V3D_VIEW_FRONT; rv3d->persp= V3D_ORTHO;
+
+ ar= ar->next;
+ rv3d= ar->regiondata;
+ rv3d->viewlock= RV3D_LOCKED; rv3d->view= V3D_VIEW_TOP; rv3d->persp= V3D_ORTHO;
+
+ ar= ar->next;
+ rv3d= ar->regiondata;
+ rv3d->viewlock= RV3D_LOCKED; rv3d->view= V3D_VIEW_RIGHT; rv3d->persp= V3D_ORTHO;
+
+ ar= ar->next;
+ rv3d= ar->regiondata;
+ rv3d->view= V3D_VIEW_CAMERA; rv3d->persp= V3D_CAMOB;
+ }
+
+ WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
+ }
+
+
+ return OPERATOR_FINISHED;
+}
+
+void SCREEN_OT_region_foursplit(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Split Region in 4 Parts";
+ ot->idname= "SCREEN_OT_region_foursplit";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= region_foursplit_exec;
+ ot->poll= ED_operator_areaactive;
+ ot->flag= OPTYPE_REGISTER;
+}
+
+
+
+/* ************** region flip operator ***************************** */
+
+/* flip a region alignment */
+static int region_flip_exec(bContext *C, wmOperator *op)
+{
+ ARegion *ar= CTX_wm_region(C);
+
+ if(ar->alignment==RGN_ALIGN_TOP)
+ ar->alignment= RGN_ALIGN_BOTTOM;
+ else if(ar->alignment==RGN_ALIGN_BOTTOM)
+ ar->alignment= RGN_ALIGN_TOP;
+ else if(ar->alignment==RGN_ALIGN_LEFT)
+ ar->alignment= RGN_ALIGN_RIGHT;
+ else if(ar->alignment==RGN_ALIGN_RIGHT)
+ ar->alignment= RGN_ALIGN_LEFT;
+
+ WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
+ printf("executed region flip\n");
+
+ return OPERATOR_FINISHED;
+}
+
+static void testfunc(bContext *C, void *argv, int arg)
+{
+ printf("arg %d\n", arg);
+}
+
+static void newlevel1(bContext *C, uiMenuItem *head, void *arg)
+{
+ uiMenuFunc(head, testfunc, NULL);
+
+ uiMenuItemVal(head, "First", ICON_PROP_ON, 1);
+ uiMenuItemVal(head, "Second", ICON_PROP_CON, 2);
+ uiMenuItemVal(head, "Third", ICON_SMOOTHCURVE, 3);
+ uiMenuItemVal(head, "Fourth", ICON_SHARPCURVE, 4);
+}
+
+static int testing123(bContext *C, wmOperator *op, wmEvent *event)
+{
+ uiMenuItem *head= uiPupMenuBegin("Hello world", 0);
+
+ uiMenuContext(head, WM_OP_EXEC_DEFAULT);
+ uiMenuItemO(head, ICON_PROP_ON, "SCREEN_OT_region_flip");
+ uiMenuItemO(head, ICON_PROP_CON, "SCREEN_OT_screen_full_area");
+ uiMenuItemO(head, ICON_SMOOTHCURVE, "SCREEN_OT_region_foursplit");
+ uiMenuLevel(head, "Submenu", newlevel1);
+
+ uiPupMenuEnd(C, head);
+
+ /* this operator is only for a menu, not used further */
+ return OPERATOR_CANCELLED;
+}
+
+void SCREEN_OT_region_flip(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Flip Region";
+ ot->idname= "SCREEN_OT_region_flip";
+
+ /* api callbacks */
+ ot->invoke= testing123; // XXX WM_operator_confirm;
+ ot->exec= region_flip_exec;
+
+ ot->poll= ED_operator_areaactive;
+ ot->flag= OPTYPE_REGISTER;
+
+ RNA_def_int(ot->srna, "test", 0, INT_MIN, INT_MAX, "test", "", INT_MIN, INT_MAX);
+
+}
+
+/* ****************** anim player, typically with timer ***************** */
+
+static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
+{
+ bScreen *screen= CTX_wm_screen(C);
+
+ if(screen->animtimer==event->customdata) {
+ Scene *scene= CTX_data_scene(C);
+
+ if(scene->audio.flag & AUDIO_SYNC) {
+ wmTimer *wt= screen->animtimer;
+ int step = floor(wt->duration * FPS);
+ scene->r.cfra += step;
+ wt->duration -= ((float)step)/FPS;
+ }
+ else
+ scene->r.cfra++;
+
+ if (scene->r.psfra) {
+ if(scene->r.cfra > scene->r.pefra)
+ scene->r.cfra= scene->r.psfra;
+ }
+ else {
+ if(scene->r.cfra > scene->r.efra)
+ scene->r.cfra= scene->r.sfra;
+ }
+
+ WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_PASS_THROUGH;
+}
+
+void SCREEN_OT_animation_play(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Animation player";
+ ot->idname= "SCREEN_OT_animation_play";
+
+ /* api callbacks */
+ ot->invoke= screen_animation_play;
+
+ ot->poll= ED_operator_screenactive;
+
+}
+
+/* ************** border select operator (template) ***************************** */
+
+/* operator state vars used: (added by default WM callbacks)
+ xmin, ymin
+ xmax, ymax
+
+ customdata: the wmGesture pointer
+
+callbacks:
+
+ exec() has to be filled in by user
+
+ invoke() default WM function
+ adds modal handler
+
+ modal() default WM function
+ accept modal events while doing it, calls exec(), handles ESC and border drawing
+
+ poll() has to be filled in by user for context
+*/
+#if 0
+static int border_select_do(bContext *C, wmOperator *op)
+{
+ int event_type= RNA_int_get(op->ptr, "event_type");
+
+ if(event_type==LEFTMOUSE)
+ printf("border select do select\n");
+ else if(event_type==RIGHTMOUSE)
+ printf("border select deselect\n");
+ else
+ printf("border select do something\n");
+
+ return 1;
+}
+
+void SCREEN_OT_border_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Border select";
+ ot->idname= "SCREEN_OT_border_select";
+
+ /* api callbacks */
+ ot->exec= border_select_do;
+ ot->invoke= WM_border_select_invoke;
+ ot->modal= WM_border_select_modal;
+
+ ot->poll= ED_operator_areaactive;
+
+ /* rna */
+ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+
+}
+#endif
+
+/* ****************************** render invoking ***************** */
+
+/* set callbacks, exported to sequence render too.
+Only call in foreground (UI) renders. */
+
+/* returns biggest area that is not uv/image editor. Note that it uses buttons */
+/* window as the last possible alternative. */
+static ScrArea *biggest_non_image_area(bContext *C)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ ScrArea *sa, *big= NULL;
+ int size, maxsize= 0, bwmaxsize= 0;
+ short foundwin= 0;
+
+ for(sa= sc->areabase.first; sa; sa= sa->next) {
+ if(sa->winx > 10 && sa->winy > 10) {
+ size= sa->winx*sa->winy;
+ if(sa->spacetype == SPACE_BUTS) {
+ if(foundwin == 0 && size > bwmaxsize) {
+ bwmaxsize= size;
+ big= sa;
+ }
+ }
+ else if(sa->spacetype != SPACE_IMAGE && size > maxsize) {
+ maxsize= size;
+ big= sa;
+ foundwin= 1;
+ }
+ }
+ }
+
+ return big;
+}
+
+static ScrArea *biggest_area(bContext *C)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ ScrArea *sa, *big= NULL;
+ int size, maxsize= 0;
+
+ for(sa= sc->areabase.first; sa; sa= sa->next) {
+ size= sa->winx*sa->winy;
+ if(size > maxsize) {
+ maxsize= size;
+ big= sa;
+ }
+ }
+ return big;
+}
+
+
+static ScrArea *find_area_showing_r_result(bContext *C)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ ScrArea *sa;
+ SpaceImage *sima;
+
+ /* find an imagewindow showing render result */
+ for(sa=sc->areabase.first; sa; sa= sa->next) {
+ if(sa->spacetype==SPACE_IMAGE) {
+ sima= sa->spacedata.first;
+ if(sima->image && sima->image->type==IMA_TYPE_R_RESULT)
+ break;
+ }
+ }
+ return sa;
+}
+
+static void screen_set_image_output(bContext *C)
+{
+ ScrArea *sa;
+ SpaceImage *sima;
+
+ sa= find_area_showing_r_result(C);
+
+ if(sa==NULL) {
+ /* find largest open non-image area */
+ sa= biggest_non_image_area(C);
+ if(sa) {
+ ED_area_newspace(C, sa, SPACE_IMAGE);
+ sima= sa->spacedata.first;
+
+ /* makes ESC go back to prev space */
+ sima->flag |= SI_PREVSPACE;
+ }
+ else {
+ /* use any area of decent size */
+ sa= biggest_area(C);
+ if(sa->spacetype!=SPACE_IMAGE) {
+ // XXX newspace(sa, SPACE_IMAGE);
+ sima= sa->spacedata.first;
+
+ /* makes ESC go back to prev space */
+ sima->flag |= SI_PREVSPACE;
+ }
+ }
+ }
+
+ sima= sa->spacedata.first;
+
+ /* get the correct image, and scale it */
+ sima->image= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
+
+ if(G.displaymode==2) { // XXX
+ if(sa->full==0) {
+ sima->flag |= SI_FULLWINDOW;
+
+ ed_screen_fullarea(C, sa);
+ }
+ }
+
+}
+
+/* executes blocking render */
+static int screen_render_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Render *re= RE_GetRender(scene->id.name);
+
+ if(re==NULL) {
+ re= RE_NewRender(scene->id.name);
+ }
+ RE_test_break_cb(re, NULL, (int (*)(void *)) blender_test_break);
+
+ if(RNA_boolean_get(op->ptr, "anim"))
+ RE_BlenderAnim(re, scene, scene->r.sfra, scene->r.efra, scene->frame_step);
+ else
+ RE_BlenderFrame(re, scene, scene->r.cfra);
+
+ // no redraw needed, we leave state as we entered it
+ ED_update_for_newframe(C, 1);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+typedef struct RenderJob {
+ Scene *scene;
+ Render *re;
+ wmWindow *win;
+ int anim;
+ Image *image;
+ ImageUser iuser;
+ short *stop;
+ short *do_update;
+} RenderJob;
+
+static void render_freejob(void *rjv)
+{
+ RenderJob *rj= rjv;
+
+ MEM_freeN(rj);
+}
+
+/* called inside thread! */
+static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrect)
+{
+ RenderJob *rj= rjv;
+ ImBuf *ibuf;
+ float x1, y1, *rectf= NULL;
+ int ymin, ymax, xmin, xmax;
+ int rymin, rxmin;
+ char *rectc;
+
+ ibuf= BKE_image_get_ibuf(rj->image, &rj->iuser);
+ if(ibuf==NULL) return;
+
+ /* if renrect argument, we only refresh scanlines */
+ if(renrect) {
+ /* if ymax==recty, rendering of layer is ready, we should not draw, other things happen... */
+ if(rr->renlay==NULL || renrect->ymax>=rr->recty)
+ return;
+
+ /* xmin here is first subrect x coord, xmax defines subrect width */
+ xmin = renrect->xmin + rr->crop;
+ xmax = renrect->xmax - xmin - rr->crop;
+ if (xmax<2) return;
+
+ ymin= renrect->ymin + rr->crop;
+ ymax= renrect->ymax - ymin - rr->crop;
+ if(ymax<2)
+ return;
+ renrect->ymin= renrect->ymax;
+
+ }
+ else {
+ xmin = ymin = rr->crop;
+ xmax = rr->rectx - 2*rr->crop;
+ ymax = rr->recty - 2*rr->crop;
+ }
+
+ /* xmin ymin is in tile coords. transform to ibuf */
+ rxmin= rr->tilerect.xmin + xmin;
+ if(rxmin >= ibuf->x) return;
+ rymin= rr->tilerect.ymin + ymin;
+ if(rymin >= ibuf->y) return;
+
+ if(rxmin + xmax > ibuf->x)
+ xmax= ibuf->x - rxmin;
+ if(rymin + ymax > ibuf->y)
+ ymax= ibuf->y - rymin;
+
+ if(xmax < 1 || ymax < 1) return;
+
+ /* find current float rect for display, first case is after composit... still weak */
+ if(rr->rectf)
+ rectf= rr->rectf;
+ else {
+ if(rr->rect32)
+ return;
+ else {
+ if(rr->renlay==NULL || rr->renlay->rectf==NULL) return;
+ rectf= rr->renlay->rectf;
+ }
+ }
+ if(rectf==NULL) return;
+
+ rectf+= 4*(rr->rectx*ymin + xmin);
+ rectc= (char *)(ibuf->rect + ibuf->x*rymin + rxmin);
+
+ for(y1= 0; y1<ymax; y1++) {
+ float *rf= rectf;
+ char *rc= rectc;
+
+ /* XXX temp. because crop offset */
+ if( rectc >= (char *)(ibuf->rect)) {
+ for(x1= 0; x1<xmax; x1++, rf += 4, rc+=4) {
+ rc[0]= FTOCHAR(rf[0]);
+ rc[1]= FTOCHAR(rf[1]);
+ rc[2]= FTOCHAR(rf[2]);
+ rc[3]= FTOCHAR(rf[3]);
+ }
+ }
+ rectf += 4*rr->rectx;
+ rectc += 4*ibuf->x;
+ }
+
+ /* make jobs timer to send notifier */
+ *(rj->do_update)= 1;
+}
+
+static void render_startjob(void *rjv, short *stop, short *do_update)
+{
+ RenderJob *rj= rjv;
+
+ rj->stop= stop;
+ rj->do_update= do_update;
+
+ if(rj->anim)
+ RE_BlenderAnim(rj->re, rj->scene, rj->scene->r.sfra, rj->scene->r.efra, rj->scene->frame_step);
+ else
+ RE_BlenderFrame(rj->re, rj->scene, rj->scene->r.cfra);
+}
+
+/* called by render, check job 'stop' value or the global */
+static int render_breakjob(void *rjv)
+{
+ RenderJob *rj= rjv;
+
+ if(G.afbreek)
+ return 1;
+ if(rj->stop && *(rj->stop))
+ return 1;
+ return 0;
+}
+
+/* catch esc */
+static int screen_render_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ /* no running blender, remove handler and pass through */
+ if(0==WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C)))
+ return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
+
+ /* running render */
+ switch (event->type) {
+ case ESCKEY:
+ return OPERATOR_RUNNING_MODAL;
+ break;
+ }
+ return OPERATOR_PASS_THROUGH;
+}
+
+/* using context, starts job */
+static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ /* new render clears all callbacks */
+ Scene *scene= CTX_data_scene(C);
+ Render *re;
+ wmJob *steve;
+ RenderJob *rj;
+ Image *ima;
+
+ /* only one job at a time */
+ if(WM_jobs_test(CTX_wm_manager(C), scene))
+ return OPERATOR_CANCELLED;
+
+ /* handle UI stuff */
+ WM_cursor_wait(1);
+
+ /* flush multires changes (for sculpt) */
+ multires_force_update(CTX_data_active_object(C));
+
+ // get editmode results
+ // store spare
+ // get view3d layer, local layer, make this nice api call to render
+ // store spare
+
+ /* ensure at least 1 area shows result */
+ screen_set_image_output(C);
+
+ /* job custom data */
+ rj= MEM_callocN(sizeof(RenderJob), "render job");
+ rj->scene= scene;
+ rj->win= CTX_wm_window(C);
+ rj->anim= RNA_boolean_get(op->ptr, "anim");
+ rj->iuser.scene= scene;
+ rj->iuser.ok= 1;
+
+ /* setup job */
+ steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene);
+ WM_jobs_customdata(steve, rj, render_freejob);
+ WM_jobs_timer(steve, 0.2, NC_SCENE|ND_RENDER_RESULT, 0);
+ WM_jobs_callbacks(steve, render_startjob, NULL, NULL);
+
+ /* get a render result image, and make sure it is empty */
+ ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
+ BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
+ rj->image= ima;
+
+ /* setup new render */
+ re= RE_NewRender(scene->id.name);
+ RE_test_break_cb(re, rj, render_breakjob);
+ RE_display_draw_cb(re, rj, image_rect_update);
+ rj->re= re;
+ G.afbreek= 0;
+
+ // BKE_report in render!
+ // RE_error_cb(re, error_cb);
+
+ WM_jobs_start(steve);
+
+ G.afbreek= 0;
+
+ WM_cursor_wait(0);
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);
+
+ /* add modal handler for ESC */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+
+/* contextual render, using current scene, view3d? */
+void SCREEN_OT_render(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Render";
+ ot->idname= "SCREEN_OT_render";
+
+ /* api callbacks */
+ ot->invoke= screen_render_invoke;
+ ot->modal= screen_render_modal;
+ ot->exec= screen_render_exec;
+
+ ot->poll= ED_operator_screenactive;
+
+ RNA_def_int(ot->srna, "layers", 0, 0, INT_MAX, "Layers", "", 0, INT_MAX);
+ RNA_def_boolean(ot->srna, "anim", 0, "Animation", "");
+}
+
+/* *********************** cancel render viewer *************** */
+
+static int render_view_cancel_exec(bContext *C, wmOperator *unused)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceImage *sima= sa->spacedata.first;
+
+ if(sima->flag & SI_PREVSPACE) {
+ sima->flag &= ~SI_PREVSPACE;
+
+ if(sima->flag & SI_FULLWINDOW) {
+ sima->flag &= ~SI_FULLWINDOW;
+ ED_screen_full_prevspace(C);
+ }
+ else
+ ED_area_prevspace(C);
+ }
+ else if(sima->flag & SI_FULLWINDOW) {
+ sima->flag &= ~SI_FULLWINDOW;
+ ed_screen_fullarea(C, sa);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void SCREEN_OT_render_view_cancel(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Cancel Render View";
+ ot->idname= "SCREEN_OT_render_view_cancel";
+
+ /* api callbacks */
+ ot->exec= render_view_cancel_exec;
+ ot->poll= ED_operator_image_active;
+}
+
+
+/* **************** Assigning operatortypes to global list, adding handlers **************** */
+
+/* called in spacetypes.c */
+void ED_operatortypes_screen(void)
+{
+ /* generic UI stuff */
+ WM_operatortype_append(SCREEN_OT_actionzone);
+ WM_operatortype_append(SCREEN_OT_repeat_last);
+ WM_operatortype_append(SCREEN_OT_repeat_history);
+ WM_operatortype_append(SCREEN_OT_redo_last);
+
+ /* screen tools */
+ WM_operatortype_append(SCREEN_OT_area_move);
+ WM_operatortype_append(SCREEN_OT_area_split);
+ WM_operatortype_append(SCREEN_OT_area_join);
+ WM_operatortype_append(SCREEN_OT_area_dupli);
+ WM_operatortype_append(SCREEN_OT_area_swap);
+ WM_operatortype_append(SCREEN_OT_region_split);
+ WM_operatortype_append(SCREEN_OT_region_foursplit);
+ WM_operatortype_append(SCREEN_OT_region_flip);
+ WM_operatortype_append(SCREEN_OT_screen_set);
+ WM_operatortype_append(SCREEN_OT_screen_full_area);
+ WM_operatortype_append(SCREEN_OT_screenshot);
+ WM_operatortype_append(SCREEN_OT_screencast);
+
+ /*frame changes*/
+ WM_operatortype_append(SCREEN_OT_frame_offset);
+ WM_operatortype_append(SCREEN_OT_animation_play);
+
+ /* render */
+ WM_operatortype_append(SCREEN_OT_render);
+ WM_operatortype_append(SCREEN_OT_render_view_cancel);
+
+ /* tools shared by more space types */
+ WM_operatortype_append(ED_OT_undo);
+ WM_operatortype_append(ED_OT_redo);
+
+}
+
+/* called in spacetypes.c */
+void ED_keymap_screen(wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "Screen", 0, 0);
+
+ /* standard timers */
+ WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", TIMER0, KM_ANY, KM_ANY, 0);
+
+ RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "modifier", 0);
+ RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "modifier", 1);
+ RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "modifier", 2);
+
+ /* screen tools */
+ WM_keymap_verify_item(keymap, "SCREEN_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "SCREEN_OT_area_split", EVT_ACTIONZONE, 0, 0, 0);
+ WM_keymap_verify_item(keymap, "SCREEN_OT_area_join", EVT_ACTIONZONE, 0, 0, 0);
+ WM_keymap_verify_item(keymap, "SCREEN_OT_area_dupli", EVT_ACTIONZONE, 0, KM_SHIFT, 0);
+ WM_keymap_verify_item(keymap, "SCREEN_OT_area_swap", EVT_ACTIONZONE, 0, KM_ALT, 0);
+ RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1);
+ RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1);
+ WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", UPARROWKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", DOWNARROWKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "SCREEN_OT_screencast", F3KEY, KM_PRESS, KM_ALT, 0);
+
+ /* tests */
+ WM_keymap_add_item(keymap, "SCREEN_OT_region_split", SKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
+ WM_keymap_add_item(keymap, "SCREEN_OT_region_foursplit", SKEY, KM_PRESS, KM_CTRL|KM_ALT|KM_SHIFT, 0);
+
+ WM_keymap_verify_item(keymap, "SCREEN_OT_repeat_history", F3KEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "SCREEN_OT_repeat_last", F4KEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SCREEN_OT_region_flip", F5KEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "SCREEN_OT_redo_last", F6KEY, KM_PRESS, 0, 0);
+
+ /* files */
+ WM_keymap_add_item(keymap, "FILE_OT_exec", RETKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "FILE_OT_cancel", ESCKEY, KM_PRESS, 0, 0);
+
+ /* undo */
+ WM_keymap_add_item(keymap, "ED_OT_undo", ZKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "ED_OT_undo", ZKEY, KM_PRESS, KM_OSKEY, 0);
+ WM_keymap_add_item(keymap, "ED_OT_redo", ZKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "ED_OT_redo", ZKEY, KM_PRESS, KM_SHIFT|KM_OSKEY, 0);
+
+ /* render */
+ WM_keymap_add_item(keymap, "SCREEN_OT_render", F12KEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SCREEN_OT_render_view_cancel", ESCKEY, KM_PRESS, 0, 0);
+
+ /* frame offsets */
+ keymap= WM_keymap_listbase(wm, "Frames", 0, 0);
+ RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 10);
+ RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -10);
+ RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -1);
+ RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 1);
+
+}
+
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
new file mode 100644
index 00000000000..75b85b9499f
--- /dev/null
+++ b/source/blender/editors/screen/screendump.c
@@ -0,0 +1,335 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * Making screendumps.
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_utildefines.h"
+#include "BKE_writeavi.h"
+
+#include "BIF_gl.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+#include "PIL_time.h"
+
+#include "ED_fileselect.h"
+#include "ED_screen.h"
+#include "ED_screen_types.h"
+
+#include "screen_intern.h"
+
+typedef struct ScreenshotData {
+ unsigned int *dumprect;
+ int dumpsx, dumpsy;
+} ScreenshotData;
+
+static int screenshot_exec(bContext *C, wmOperator *op)
+{
+ ScreenshotData *scd= op->customdata;
+
+ if(scd && scd->dumprect) {
+ Scene *scene= CTX_data_scene(C);
+ ImBuf *ibuf;
+ char filename[FILE_MAX];
+
+ RNA_string_get(op->ptr, "filename", filename);
+
+ strcpy(G.ima, filename);
+ BLI_convertstringcode(filename, G.sce);
+
+ /* BKE_add_image_extension() checks for if extension was already set */
+ if(scene->r.scemode & R_EXTENSION)
+ if(strlen(filename)<FILE_MAXDIR+FILE_MAXFILE-5)
+ BKE_add_image_extension(scene, filename, scene->r.imtype);
+
+ ibuf= IMB_allocImBuf(scd->dumpsx, scd->dumpsy, 24, 0, 0);
+ ibuf->rect= scd->dumprect;
+
+ if(scene->r.planes == 8) IMB_cspace(ibuf, rgb_to_bw);
+
+ BKE_write_ibuf(scene, ibuf, filename, scene->r.imtype, scene->r.subimtype, scene->r.quality);
+
+ IMB_freeImBuf(ibuf);
+
+ MEM_freeN(scd->dumprect);
+ MEM_freeN(scd);
+ op->customdata= NULL;
+ }
+ return OPERATOR_FINISHED;
+}
+
+/* get shot from frontbuffer */
+static unsigned int *screenshot(bContext *C, int *dumpsx, int *dumpsy, int fscreen)
+{
+ wmWindow *win= CTX_wm_window(C);
+ ScrArea *curarea= CTX_wm_area(C);
+ int x=0, y=0;
+ unsigned int *dumprect= NULL;
+
+ if(fscreen) { /* full screen */
+ x= 0;
+ y= 0;
+ *dumpsx= win->sizex;
+ *dumpsy= win->sizey;
+ }
+ else {
+ x= curarea->totrct.xmin;
+ y= curarea->totrct.ymin;
+ *dumpsx= curarea->totrct.xmax-x;
+ *dumpsy= curarea->totrct.ymax-y;
+ }
+
+ if (*dumpsx && *dumpsy) {
+
+ dumprect= MEM_mallocN(sizeof(int) * dumpsx[0] * dumpsy[0], "dumprect");
+ glReadBuffer(GL_FRONT);
+ glReadPixels(x, y, *dumpsx, *dumpsy, GL_RGBA, GL_UNSIGNED_BYTE, dumprect);
+ glFinish();
+ glReadBuffer(GL_BACK);
+ }
+
+ return dumprect;
+}
+
+
+static int screenshot_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ unsigned int *dumprect;
+ int dumpsx, dumpsy;
+
+ dumprect= screenshot(C, &dumpsx, &dumpsy, RNA_boolean_get(op->ptr, "full"));
+ if(dumprect) {
+ ScreenshotData *scd= MEM_callocN(sizeof(ScreenshotData), "screenshot");
+
+ scd->dumpsx= dumpsx;
+ scd->dumpsy= dumpsy;
+ scd->dumprect= dumprect;
+ op->customdata= scd;
+
+ if(RNA_property_is_set(op->ptr, "filename"))
+ return screenshot_exec(C, op);
+
+ RNA_string_set(op->ptr, "filename", G.ima);
+
+ WM_event_add_fileselect(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ return OPERATOR_CANCELLED;
+}
+
+
+void SCREEN_OT_screenshot(wmOperatorType *ot)
+{
+ ot->name= "Save Screenshot"; /* weak: opname starting with 'save' makes filewindow give save-over */
+ ot->idname= "SCREEN_OT_screenshot";
+
+ ot->invoke= screenshot_invoke;
+ ot->exec= screenshot_exec;
+ ot->poll= WM_operator_winactive;
+
+ ot->flag= 0;
+
+ RNA_def_property(ot->srna, "filename", PROP_STRING, PROP_FILEPATH);
+ RNA_def_boolean(ot->srna, "full", 1, "Full Screen", "");
+}
+
+/* *************** screenshot movie job ************************* */
+
+typedef struct ScreenshotJob {
+ Scene *scene;
+ unsigned int *dumprect;
+ int x, y, dumpsx, dumpsy;
+ short *stop;
+ short *do_update;
+} ScreenshotJob;
+
+
+static void screenshot_freejob(void *sjv)
+{
+ ScreenshotJob *sj= sjv;
+
+ if(sj->dumprect)
+ MEM_freeN(sj->dumprect);
+
+ MEM_freeN(sj);
+}
+
+
+/* called before redraw notifiers, copies a new dumprect */
+static void screenshot_updatejob(void *sjv)
+{
+ ScreenshotJob *sj= sjv;
+ unsigned int *dumprect;
+
+ if(sj->dumprect==NULL) {
+ dumprect= MEM_mallocN(sizeof(int) * sj->dumpsx * sj->dumpsy, "dumprect");
+ glReadPixels(sj->x, sj->y, sj->dumpsx, sj->dumpsy, GL_RGBA, GL_UNSIGNED_BYTE, dumprect);
+ glFinish();
+
+ sj->dumprect= dumprect;
+ }
+}
+
+
+/* only this runs inside thread */
+static void screenshot_startjob(void *sjv, short *stop, short *do_update)
+{
+ ScreenshotJob *sj= sjv;
+ RenderData rd= sj->scene->r;
+ bMovieHandle *mh= BKE_get_movie_handle(sj->scene->r.imtype);
+ int cfra= 1;
+
+ /* we need this as local variables for renderdata */
+ rd.frs_sec= 10;
+ rd.frs_sec_base= 1.0f;
+
+ if(BKE_imtype_is_movie(rd.imtype))
+ mh->start_movie(&rd, sj->dumpsx, sj->dumpsy);
+ else
+ mh= NULL;
+
+ sj->stop= stop;
+ sj->do_update= do_update;
+
+ *do_update= 1; // wait for opengl rect
+
+ while(*stop==0) {
+
+ if(sj->dumprect) {
+
+ if(mh) {
+ mh->append_movie(&rd, cfra, sj->dumprect, sj->dumpsx, sj->dumpsy);
+ printf("Append frame %d\n", cfra);
+ }
+ else {
+ ImBuf *ibuf= IMB_allocImBuf(sj->dumpsx, sj->dumpsy, rd.planes, 0, 0);
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+ int ok;
+
+ BKE_makepicstring(sj->scene, name, rd.pic, cfra, rd.imtype);
+
+ ibuf->rect= sj->dumprect;
+ ok= BKE_write_ibuf(sj->scene, ibuf, name, rd.imtype, rd.subimtype, rd.quality);
+
+ if(ok==0) {
+ printf("Write error: cannot save %s\n", name);
+ break;
+ }
+ else printf("Saved: %s\n", name);
+
+ /* imbuf knows which rects are not part of ibuf */
+ IMB_freeImBuf(ibuf);
+ }
+
+ MEM_freeN(sj->dumprect);
+ sj->dumprect= NULL;
+
+ *do_update= 1;
+
+ cfra++;
+ }
+ else
+ PIL_sleep_ms(50);
+ }
+
+ if(mh)
+ mh->end_movie();
+ printf("screencast job stopped\n");
+}
+
+static int screencast_exec(bContext *C, wmOperator *op)
+{
+ bScreen *screen= CTX_wm_screen(C);
+ wmJob *steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), screen);
+ ScreenshotJob *sj= MEM_callocN(sizeof(ScreenshotJob), "screenshot job");
+
+ /* setup sj */
+ if(RNA_boolean_get(op->ptr, "full")) {
+ wmWindow *win= CTX_wm_window(C);
+ sj->x= 0;
+ sj->y= 0;
+ sj->dumpsx= win->sizex;
+ sj->dumpsy= win->sizey;
+ }
+ else {
+ ScrArea *curarea= CTX_wm_area(C);
+ sj->x= curarea->totrct.xmin;
+ sj->y= curarea->totrct.ymin;
+ sj->dumpsx= curarea->totrct.xmax - sj->x;
+ sj->dumpsy= curarea->totrct.ymax - sj->y;
+ }
+ sj->scene= CTX_data_scene(C);
+
+ /* setup job */
+ WM_jobs_customdata(steve, sj, screenshot_freejob);
+ WM_jobs_timer(steve, 0.1, 0, NC_SCREEN|ND_SCREENCAST);
+ WM_jobs_callbacks(steve, screenshot_startjob, NULL, screenshot_updatejob);
+
+ WM_jobs_start(steve);
+
+ WM_event_add_notifier(C, NC_SCREEN|ND_SCREENCAST, screen);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCREEN_OT_screencast(wmOperatorType *ot)
+{
+ ot->name= "Make Screencast";
+ ot->idname= "SCREEN_OT_screencast";
+
+ ot->invoke= WM_operator_confirm;
+ ot->exec= screencast_exec;
+ ot->poll= WM_operator_winactive;
+
+ ot->flag= 0;
+
+ RNA_def_property(ot->srna, "filename", PROP_STRING, PROP_FILEPATH);
+ RNA_def_boolean(ot->srna, "full", 1, "Full Screen", "");
+}
+
+
+
diff --git a/source/blender/editors/sculpt_paint/Makefile b/source/blender/editors/sculpt_paint/Makefile
new file mode 100644
index 00000000000..e810f7efbe4
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/Makefile
@@ -0,0 +1,57 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_sculpt_paint
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+CPPFLAGS += -I$(NAN_BMFONT)/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I$(NAN_ELBEEM)/include
+
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../gpu
+CPPFLAGS += -I../../render/extern/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/sculpt_paint/SConscript b/source/blender/editors/sculpt_paint/SConscript
new file mode 100644
index 00000000000..3e00453e049
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/SConscript
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' ../../render/extern/include #/intern/guardedalloc #intern/bmfont'
+incs += ' ../../gpu ../../makesrna'
+
+env.BlenderLib ( 'bf_editors_sculpt_paint', sources, Split(incs), [], libtype=['core'], priority=[40] )
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
new file mode 100644
index 00000000000..22fb8e61789
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -0,0 +1,5189 @@
+/**
+ * $Id$
+ * imagepaint.c
+ *
+ * Functions to paint images in 2D and 3D.
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: some of this file.
+ *
+ * Contributor(s): Jens Ole Wund (bjornmose), Campbell Barton (ideasman42)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <float.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h"
+#include "BLI_linklist.h"
+#include "BLI_memarena.h"
+#include "PIL_time.h"
+#include "BLI_threads.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_image_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_context.h"
+#include "BKE_brush.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_node.h"
+#include "BKE_utildefines.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_report.h"
+#include "BKE_depsgraph.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "ED_image.h"
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "GPU_draw.h"
+
+#include "paint_intern.h"
+
+/* Defines and Structs */
+
+#define IMAPAINT_CHAR_TO_FLOAT(c) ((c)/255.0f)
+
+#define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { (c)[0]=FTOCHAR((f)[0]); (c)[1]=FTOCHAR((f)[1]); (c)[2]=FTOCHAR((f)[2]); }
+#define IMAPAINT_FLOAT_RGBA_TO_CHAR(c, f) { (c)[0]=FTOCHAR((f)[0]); (c)[1]=FTOCHAR((f)[1]); (c)[2]=FTOCHAR((f)[2]); (c)[3]=FTOCHAR((f)[3]); }
+
+#define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { (f)[0]=IMAPAINT_CHAR_TO_FLOAT((c)[0]); (f)[1]=IMAPAINT_CHAR_TO_FLOAT((c)[1]); (f)[2]=IMAPAINT_CHAR_TO_FLOAT((c)[2]); }
+#define IMAPAINT_CHAR_RGBA_TO_FLOAT(f, c) { (f)[0]=IMAPAINT_CHAR_TO_FLOAT((c)[0]); (f)[1]=IMAPAINT_CHAR_TO_FLOAT((c)[1]); (f)[2]=IMAPAINT_CHAR_TO_FLOAT((c)[2]); (f)[3]=IMAPAINT_CHAR_TO_FLOAT((c)[3]); }
+#define IMAPAINT_FLOAT_RGB_COPY(a, b) VECCOPY(a, b)
+
+#define IMAPAINT_TILE_BITS 6
+#define IMAPAINT_TILE_SIZE (1 << IMAPAINT_TILE_BITS)
+#define IMAPAINT_TILE_NUMBER(size) (((size)+IMAPAINT_TILE_SIZE-1) >> IMAPAINT_TILE_BITS)
+
+#define MAXUNDONAME 64
+
+static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint);
+
+
+typedef struct ImagePaintState {
+ SpaceImage *sima;
+ View2D *v2d;
+ Scene *scene;
+ bScreen *screen;
+
+ Brush *brush;
+ short tool, blend;
+ Image *image;
+ ImBuf *canvas;
+ ImBuf *clonecanvas;
+ short clonefreefloat;
+ char *warnpackedfile;
+ char *warnmultifile;
+
+ /* texture paint only */
+ Object *ob;
+ Mesh *me;
+ int faceindex;
+ float uv[2];
+} ImagePaintState;
+
+typedef struct ImagePaintPartialRedraw {
+ int x1, y1, x2, y2;
+ int enabled;
+} ImagePaintPartialRedraw;
+
+
+/* ProjectionPaint defines */
+
+/* approx the number of buckets to have under the brush,
+ * used with the brush size to set the ps->buckets_x and ps->buckets_y value.
+ *
+ * When 3 - a brush should have ~9 buckets under it at once
+ * ...this helps for threading while painting as well as
+ * avoiding initializing pixels that wont touch the brush */
+#define PROJ_BUCKET_BRUSH_DIV 4
+
+#define PROJ_BUCKET_RECT_MIN 4
+#define PROJ_BUCKET_RECT_MAX 256
+
+#define PROJ_BOUNDBOX_DIV 8
+#define PROJ_BOUNDBOX_SQUARED (PROJ_BOUNDBOX_DIV * PROJ_BOUNDBOX_DIV)
+
+//#define PROJ_DEBUG_PAINT 1
+//#define PROJ_DEBUG_NOSEAMBLEED 1
+//#define PROJ_DEBUG_PRINT_CLIP 1
+#define PROJ_DEBUG_WINCLIP 1
+
+/* projectFaceSeamFlags options */
+//#define PROJ_FACE_IGNORE 1<<0 /* When the face is hidden, backfacing or occluded */
+//#define PROJ_FACE_INIT 1<<1 /* When we have initialized the faces data */
+#define PROJ_FACE_SEAM1 1<<0 /* If this face has a seam on any of its edges */
+#define PROJ_FACE_SEAM2 1<<1
+#define PROJ_FACE_SEAM3 1<<2
+#define PROJ_FACE_SEAM4 1<<3
+
+#define PROJ_FACE_NOSEAM1 1<<4
+#define PROJ_FACE_NOSEAM2 1<<5
+#define PROJ_FACE_NOSEAM3 1<<6
+#define PROJ_FACE_NOSEAM4 1<<7
+
+/* a slightly scaled down face is used to get fake 3D location for edge pixels in the seams
+ * as this number approaches 1.0f the likelihood increases of float precision errors where
+ * it is occluded by an adjacent face */
+#define PROJ_FACE_SCALE_SEAM 0.99f
+
+#define PROJ_BUCKET_NULL 0
+#define PROJ_BUCKET_INIT 1<<0
+// #define PROJ_BUCKET_CLONE_INIT 1<<1
+
+/* used for testing doubles, if a point is on a line etc */
+#define PROJ_GEOM_TOLERANCE 0.0002f
+
+/* vert flags */
+#define PROJ_VERT_CULL 1
+
+#define PI_80_DEG ((M_PI_2 / 9) * 8)
+
+/* This is mainly a convenience struct used so we can keep an array of images we use
+ * Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread
+ * because 'partRedrawRect' and 'touch' values would not be thread safe */
+typedef struct ProjPaintImage {
+ Image *ima;
+ ImBuf *ibuf;
+ ImagePaintPartialRedraw *partRedrawRect;
+ struct UndoTile **undoRect; /* only used to build undo tiles after painting */
+ int touch;
+} ProjPaintImage;
+
+/* Main projection painting struct passed to all projection painting functions */
+typedef struct ProjPaintState {
+ View3D *v3d;
+ RegionView3D *rv3d;
+ ARegion *ar;
+ Scene *scene;
+
+ Brush *brush;
+ short tool, blend;
+ Object *ob;
+ /* end similarities with ImagePaintState */
+
+ DerivedMesh *dm;
+ int dm_totface;
+ int dm_totvert;
+
+ MVert *dm_mvert;
+ MFace *dm_mface;
+ MTFace *dm_mtface;
+ MTFace *dm_mtface_clone; /* other UV layer, use for cloning between layers */
+ MTFace *dm_mtface_mask;
+
+ /* projection painting only */
+ MemArena *arena_mt[BLENDER_MAX_THREADS];/* for multithreading, the first item is sometimes used for non threaded cases too */
+ LinkNode **bucketRect; /* screen sized 2D array, each pixel has a linked list of ProjPixel's */
+ LinkNode **bucketFaces; /* bucketRect aligned array linkList of faces overlapping each bucket */
+ unsigned char *bucketFlags; /* store if the bucks have been initialized */
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ char *faceSeamFlags; /* store info about faces, if they are initialized etc*/
+ float (*faceSeamUVs)[4][2]; /* expanded UVs for faces to use as seams */
+ LinkNode **vertFaces; /* Only needed for when seam_bleed_px is enabled, use to find UV seams */
+ char *vertFlags; /* store options per vert, now only store if the vert is pointing away from the view */
+#endif
+ int buckets_x; /* The size of the bucket grid, the grid span's screenMin/screenMax so you can paint outsize the screen or with 2 brushes at once */
+ int buckets_y;
+
+ ProjPaintImage *projImages;
+
+ int image_tot; /* size of projectImages array */
+
+ float (*screenCoords)[4]; /* verts projected into floating point screen space */
+
+ float screenMin[2]; /* 2D bounds for mesh verts on the screen's plane (screenspace) */
+ float screenMax[2];
+ float screen_width; /* Calculated from screenMin & screenMax */
+ float screen_height;
+
+ /* options for projection painting */
+ int do_layer_clone;
+ int do_layer_mask;
+ int do_layer_mask_inv;
+
+ short do_occlude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/
+ short do_backfacecull; /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */
+ short do_mask_normal; /* mask out pixels based on their normals */
+ float normal_angle; /* what angle to mask at*/
+ float normal_angle_inner;
+ float normal_angle_range; /* difference between normal_angle and normal_angle_inner, for easy access */
+
+ short is_ortho;
+ short is_airbrush; /* only to avoid using (ps.brush->flag & BRUSH_AIRBRUSH) */
+ short is_texbrush; /* only to avoid running */
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ float seam_bleed_px;
+#endif
+ /* clone vars */
+ float cloneOffset[2];
+
+ float projectMat[4][4]; /* Projection matrix, use for getting screen coords */
+ float viewMat[4][4];
+ float viewDir[3]; /* View vector, use for do_backfacecull and for ray casting with an ortho viewport */
+ float viewPos[3]; /* View location in object relative 3D space, so can compare to verts */
+ float clipsta, clipend;
+
+ /* threads */
+ int thread_tot;
+ int bucketMin[2];
+ int bucketMax[2];
+ int context_bucket_x, context_bucket_y; /* must lock threads while accessing these */
+} ProjPaintState;
+
+typedef union pixelPointer
+{
+ float *f_pt; /* float buffer */
+ unsigned int *uint_pt; /* 2 ways to access a char buffer */
+ unsigned char *ch_pt;
+} PixelPointer;
+
+typedef union pixelStore
+{
+ unsigned char ch[4];
+ unsigned int uint;
+ float f[4];
+} PixelStore;
+
+typedef struct ProjPixel {
+ float projCoSS[2]; /* the floating point screen projection of this pixel */
+
+ /* Only used when the airbrush is disabled.
+ * Store the max mask value to avoid painting over an area with a lower opacity
+ * with an advantage that we can avoid touching the pixel at all, if the
+ * new mask value is lower then mask_max */
+ unsigned short mask_max;
+
+ /* for various reasons we may want to mask out painting onto this pixel */
+ unsigned short mask;
+
+ short x_px, y_px;
+
+ PixelStore origColor;
+ PixelStore newColor;
+ PixelPointer pixel;
+
+ short image_index; /* if anyone wants to paint onto more then 32768 images they can bite me */
+ unsigned char bb_cell_index;
+} ProjPixel;
+
+typedef struct ProjPixelClone {
+ struct ProjPixel __pp;
+ PixelStore clonepx;
+} ProjPixelClone;
+
+/* Finish projection painting structs */
+
+
+typedef struct UndoTile {
+ struct UndoTile *next, *prev;
+ ID id;
+ void *rect;
+ int x, y;
+} UndoTile;
+
+typedef struct UndoElem {
+ struct UndoElem *next, *prev;
+ char name[MAXUNDONAME];
+ unsigned long undosize;
+
+ ImBuf *ibuf;
+ ListBase tiles;
+} UndoElem;
+
+static ListBase undobase = {NULL, NULL};
+static UndoElem *curundo = NULL;
+static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0};
+
+/* UNDO */
+
+/* internal functions */
+
+static void undo_copy_tile(UndoTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int restore)
+{
+ /* copy or swap contents of tile->rect and region in ibuf->rect */
+ IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x*IMAPAINT_TILE_SIZE,
+ tile->y*IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+
+ if(ibuf->rect_float) {
+ SWAP(void*, tmpibuf->rect_float, tile->rect);
+ } else {
+ SWAP(void*, tmpibuf->rect, tile->rect);
+ }
+
+ if(restore)
+ IMB_rectcpy(ibuf, tmpibuf, tile->x*IMAPAINT_TILE_SIZE,
+ tile->y*IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+}
+
+static UndoTile *undo_init_tile(ID *id, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile)
+{
+ UndoTile *tile;
+ int allocsize;
+
+ if (*tmpibuf==NULL)
+ *tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat|IB_rect, 0);
+
+ tile= MEM_callocN(sizeof(UndoTile), "ImaUndoTile");
+ tile->id= *id;
+ tile->x= x_tile;
+ tile->y= y_tile;
+
+ allocsize= IMAPAINT_TILE_SIZE*IMAPAINT_TILE_SIZE*4;
+ allocsize *= (ibuf->rect_float)? sizeof(float): sizeof(char);
+ tile->rect= MEM_mapallocN(allocsize, "ImaUndoRect");
+
+ undo_copy_tile(tile, *tmpibuf, ibuf, 0);
+ curundo->undosize += allocsize;
+
+ BLI_addtail(&curundo->tiles, tile);
+
+ return tile;
+}
+
+static void undo_restore(UndoElem *undo)
+{
+ Image *ima = NULL;
+ ImBuf *ibuf, *tmpibuf;
+ UndoTile *tile;
+
+ if(!undo)
+ return;
+
+ tmpibuf= IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32,
+ IB_rectfloat|IB_rect, 0);
+
+ for(tile=undo->tiles.first; tile; tile=tile->next) {
+ /* find image based on name, pointer becomes invalid with global undo */
+ if(ima && strcmp(tile->id.name, ima->id.name)==0);
+ else {
+ for(ima=G.main->image.first; ima; ima=ima->id.next)
+ if(strcmp(tile->id.name, ima->id.name)==0)
+ break;
+ }
+
+ ibuf= BKE_image_get_ibuf(ima, NULL);
+
+ if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float))
+ continue;
+
+ undo_copy_tile(tile, tmpibuf, ibuf, 1);
+
+ GPU_free_image(ima); /* force OpenGL reload */
+ if(ibuf->rect_float)
+ imb_freerectImBuf(ibuf); /* force recreate of char rect */
+ }
+
+ IMB_freeImBuf(tmpibuf);
+}
+
+static void undo_free(UndoElem *undo)
+{
+ UndoTile *tile;
+
+ for(tile=undo->tiles.first; tile; tile=tile->next)
+ MEM_freeN(tile->rect);
+ BLI_freelistN(&undo->tiles);
+}
+
+static void undo_imagepaint_push_begin(char *name)
+{
+ UndoElem *uel;
+ int nr;
+
+ /* Undo push is split up in begin and end, the reason is that as painting
+ * happens more tiles are added to the list, and at the very end we know
+ * how much memory the undo used to remove old undo elements */
+
+ /* remove all undos after (also when curundo==NULL) */
+ while(undobase.last != curundo) {
+ uel= undobase.last;
+ undo_free(uel);
+ BLI_freelinkN(&undobase, uel);
+ }
+
+ /* make new */
+ curundo= uel= MEM_callocN(sizeof(UndoElem), "undo file");
+ BLI_addtail(&undobase, uel);
+
+ /* name can be a dynamic string */
+ strncpy(uel->name, name, MAXUNDONAME-1);
+
+ /* limit amount to the maximum amount*/
+ nr= 0;
+ uel= undobase.last;
+ while(uel) {
+ nr++;
+ if(nr==U.undosteps) break;
+ uel= uel->prev;
+ }
+ if(uel) {
+ while(undobase.first!=uel) {
+ UndoElem *first= undobase.first;
+ undo_free(first);
+ BLI_freelinkN(&undobase, first);
+ }
+ }
+}
+
+static void undo_imagepaint_push_end()
+{
+ UndoElem *uel;
+ unsigned long totmem, maxmem;
+
+ if(U.undomemory != 0) {
+ /* limit to maximum memory (afterwards, we can't know in advance) */
+ totmem= 0;
+ maxmem= ((unsigned long)U.undomemory)*1024*1024;
+
+ uel= undobase.last;
+ while(uel) {
+ totmem+= uel->undosize;
+ if(totmem>maxmem) break;
+ uel= uel->prev;
+ }
+
+ if(uel) {
+ while(undobase.first!=uel) {
+ UndoElem *first= undobase.first;
+ undo_free(first);
+ BLI_freelinkN(&undobase, first);
+ }
+ }
+ }
+}
+
+void undo_imagepaint_step(int step)
+{
+ UndoElem *undo;
+
+ if(step==1) {
+ if(curundo==NULL);
+ else {
+ if(G.f & G_DEBUG) printf("undo %s\n", curundo->name);
+ undo_restore(curundo);
+ curundo= curundo->prev;
+ }
+ }
+ else if(step==-1) {
+ if((curundo!=NULL && curundo->next==NULL) || undobase.first==NULL);
+ else {
+ undo= (curundo && curundo->next)? curundo->next: undobase.first;
+ undo_restore(undo);
+ curundo= undo;
+ if(G.f & G_DEBUG) printf("redo %s\n", undo->name);
+ }
+ }
+}
+
+void undo_imagepaint_clear(void)
+{
+ UndoElem *uel;
+
+ uel= undobase.first;
+ while(uel) {
+ undo_free(uel);
+ uel= uel->next;
+ }
+
+ BLI_freelistN(&undobase);
+ curundo= NULL;
+}
+
+/* fast projection bucket array lookup, use the safe version for bound checking */
+static int project_bucket_offset(const ProjPaintState *ps, const float projCoSS[2])
+{
+ /* If we were not dealing with screenspace 2D coords we could simple do...
+ * ps->bucketRect[x + (y*ps->buckets_y)] */
+
+ /* please explain?
+ * projCoSS[0] - ps->screenMin[0] : zero origin
+ * ... / ps->screen_width : range from 0.0 to 1.0
+ * ... * ps->buckets_x : use as a bucket index
+ *
+ * Second multiplication does similar but for vertical offset
+ */
+ return ( (int)(((projCoSS[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x)) +
+ ( ( (int)(((projCoSS[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y)) * ps->buckets_x);
+}
+
+static int project_bucket_offset_safe(const ProjPaintState *ps, const float projCoSS[2])
+{
+ int bucket_index = project_bucket_offset(ps, projCoSS);
+
+ if (bucket_index < 0 || bucket_index >= ps->buckets_x*ps->buckets_y) {
+ return -1;
+ }
+ else {
+ return bucket_index;
+ }
+}
+
+#define SIDE_OF_LINE(pa, pb, pp) ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1]))
+
+static float AreaSignedF2Dfl(float *v1, float *v2, float *v3)
+{
+ return (float)(0.5f*((v1[0]-v2[0])*(v2[1]-v3[1]) +
+(v1[1]-v2[1])*(v3[0]-v2[0])));
+}
+
+static void BarycentricWeights2f(float pt[2], float v1[2], float v2[2], float v3[2], float w[3])
+{
+ float wtot_inv, wtot;
+
+ w[0] = AreaSignedF2Dfl(v2, v3, pt);
+ w[1] = AreaSignedF2Dfl(v3, v1, pt);
+ w[2] = AreaSignedF2Dfl(v1, v2, pt);
+ wtot = w[0]+w[1]+w[2];
+
+ if (wtot != 0.0f) {
+ wtot_inv = 1.0f/wtot;
+
+ w[0] = w[0]*wtot_inv;
+ w[1] = w[1]*wtot_inv;
+ w[2] = w[2]*wtot_inv;
+ }
+ else /* dummy values for zero area face */
+ w[0] = w[1] = w[2] = 1.0f/3.0f;
+}
+
+/* still use 2D X,Y space but this works for verts transformed by a perspective matrix, using their 4th component as a weight */
+static void BarycentricWeightsPersp2f(float pt[2], float v1[4], float v2[4], float v3[4], float w[3])
+{
+ float wtot_inv, wtot;
+
+ w[0] = AreaSignedF2Dfl(v2, v3, pt) / v1[3];
+ w[1] = AreaSignedF2Dfl(v3, v1, pt) / v2[3];
+ w[2] = AreaSignedF2Dfl(v1, v2, pt) / v3[3];
+ wtot = w[0]+w[1]+w[2];
+
+ if (wtot != 0.0f) {
+ wtot_inv = 1.0f/wtot;
+
+ w[0] = w[0]*wtot_inv;
+ w[1] = w[1]*wtot_inv;
+ w[2] = w[2]*wtot_inv;
+ }
+ else /* dummy values for zero area face */
+ w[0] = w[1] = w[2] = 1.0f/3.0f;
+}
+
+static void VecWeightf(float p[3], const float v1[3], const float v2[3], const float v3[3], const float w[3])
+{
+ p[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2];
+ p[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2];
+ p[2] = v1[2]*w[0] + v2[2]*w[1] + v3[2]*w[2];
+}
+
+static void Vec2Weightf(float p[2], const float v1[2], const float v2[2], const float v3[2], const float w[3])
+{
+ p[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2];
+ p[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2];
+}
+
+static float VecZDepthOrtho(float pt[2], float v1[3], float v2[3], float v3[3], float w[3])
+{
+ BarycentricWeights2f(pt, v1, v2, v3, w);
+ return (v1[2]*w[0]) + (v2[2]*w[1]) + (v3[2]*w[2]);
+}
+
+static float VecZDepthPersp(float pt[2], float v1[3], float v2[3], float v3[3], float w[3])
+{
+ BarycentricWeightsPersp2f(pt, v1, v2, v3, w);
+ return (v1[2]*w[0]) + (v2[2]*w[1]) + (v3[2]*w[2]);
+}
+
+
+/* Return the top-most face index that the screen space coord 'pt' touches (or -1) */
+static int project_paint_PickFace(const ProjPaintState *ps, float pt[2], float w[3], int *side)
+{
+ LinkNode *node;
+ float w_tmp[3];
+ float *v1, *v2, *v3, *v4;
+ int bucket_index;
+ int face_index;
+ int best_side = -1;
+ int best_face_index = -1;
+ float z_depth_best = FLT_MAX, z_depth;
+ MFace *mf;
+
+ bucket_index = project_bucket_offset_safe(ps, pt);
+ if (bucket_index==-1)
+ return -1;
+
+
+
+ /* we could return 0 for 1 face buckets, as long as this function assumes
+ * that the point its testing is only every originated from an existing face */
+
+ for (node= ps->bucketFaces[bucket_index]; node; node= node->next) {
+ face_index = GET_INT_FROM_POINTER(node->link);
+ mf= ps->dm_mface + face_index;
+
+ v1= ps->screenCoords[mf->v1];
+ v2= ps->screenCoords[mf->v2];
+ v3= ps->screenCoords[mf->v3];
+
+ if (IsectPT2Df(pt, v1, v2, v3)) {
+ if (ps->is_ortho) z_depth= VecZDepthOrtho(pt, v1, v2, v3, w_tmp);
+ else z_depth= VecZDepthPersp(pt, v1, v2, v3, w_tmp);
+
+ if (z_depth < z_depth_best) {
+ best_face_index = face_index;
+ best_side = 0;
+ z_depth_best = z_depth;
+ VECCOPY(w, w_tmp);
+ }
+ }
+ else if (mf->v4) {
+ v4= ps->screenCoords[mf->v4];
+
+ if (IsectPT2Df(pt, v1, v3, v4)) {
+ if (ps->is_ortho) z_depth= VecZDepthOrtho(pt, v1, v3, v4, w_tmp);
+ else z_depth= VecZDepthPersp(pt, v1, v3, v4, w_tmp);
+
+ if (z_depth < z_depth_best) {
+ best_face_index = face_index;
+ best_side= 1;
+ z_depth_best = z_depth;
+ VECCOPY(w, w_tmp);
+ }
+ }
+ }
+ }
+
+ *side = best_side;
+ return best_face_index; /* will be -1 or a valid face */
+}
+
+/* Converts a uv coord into a pixel location wrapping if the uv is outside 0-1 range */
+static void uvco_to_wrapped_pxco(float uv[2], int ibuf_x, int ibuf_y, float *x, float *y)
+{
+ /* use */
+ *x = (float)fmod(uv[0], 1.0f);
+ *y = (float)fmod(uv[1], 1.0f);
+
+ if (*x < 0.0f) *x += 1.0f;
+ if (*y < 0.0f) *y += 1.0f;
+
+ *x = *x * ibuf_x - 0.5f;
+ *y = *y * ibuf_y - 0.5f;
+}
+
+/* Set the top-most face color that the screen space coord 'pt' touches (or return 0 if none touch) */
+static int project_paint_PickColor(const ProjPaintState *ps, float pt[2], float *rgba_fp, unsigned char *rgba, const int interp)
+{
+ float w[3], uv[2];
+ int side;
+ int face_index;
+ MTFace *tf;
+ ImBuf *ibuf;
+ int xi, yi;
+
+
+ face_index = project_paint_PickFace(ps, pt, w, &side);
+
+ if (face_index == -1)
+ return 0;
+
+ tf = ps->dm_mtface + face_index;
+
+ if (side == 0) {
+ Vec2Weightf(uv, tf->uv[0], tf->uv[1], tf->uv[2], w);
+ }
+ else { /* QUAD */
+ Vec2Weightf(uv, tf->uv[0], tf->uv[2], tf->uv[3], w);
+ }
+
+ ibuf = BKE_image_get_ibuf((Image *)tf->tpage, NULL); /* TODO - this may be slow, the only way around it is to have an ibuf index per face */
+ if (!ibuf) return 0;
+
+ if (interp) {
+ float x, y;
+ uvco_to_wrapped_pxco(uv, ibuf->x, ibuf->y, &x, &y);
+
+ if (ibuf->rect_float) {
+ if (rgba_fp) {
+ bilinear_interpolation_color(ibuf, NULL, rgba_fp, x, y);
+ }
+ else {
+ float rgba_tmp_f[4];
+ bilinear_interpolation_color(ibuf, NULL, rgba_tmp_f, x, y);
+ IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_f);
+ }
+ }
+ else {
+ if (rgba) {
+ bilinear_interpolation_color(ibuf, rgba, NULL, x, y);
+ }
+ else {
+ unsigned char rgba_tmp[4];
+ bilinear_interpolation_color(ibuf, rgba_tmp, NULL, x, y);
+ IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, rgba_tmp);
+ }
+ }
+ }
+ else {
+ xi = (uv[0]*ibuf->x) + 0.5f;
+ yi = (uv[1]*ibuf->y) + 0.5f;
+
+ //if (xi<0 || xi>=ibuf->x || yi<0 || yi>=ibuf->y) return 0;
+
+ /* wrap */
+ xi = ((int)(uv[0]*ibuf->x)) % ibuf->x;
+ if (xi<0) xi += ibuf->x;
+ yi = ((int)(uv[1]*ibuf->y)) % ibuf->y;
+ if (yi<0) yi += ibuf->y;
+
+
+ if (rgba) {
+ if (ibuf->rect_float) {
+ float *rgba_tmp_fp = ibuf->rect_float + (xi + yi * ibuf->x * 4);
+ IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_fp);
+ }
+ else {
+ *((unsigned int *)rgba) = *(unsigned int *)(((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4));
+ }
+ }
+
+ if (rgba_fp) {
+ if (ibuf->rect_float) {
+ QUATCOPY(rgba_fp, ((float *)ibuf->rect_float + ((xi + yi * ibuf->x) * 4)));
+ }
+ else {
+ char *tmp_ch= ((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4);
+ IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, tmp_ch);
+ }
+ }
+ }
+ return 1;
+}
+
+/* Check if 'pt' is infront of the 3 verts on the Z axis (used for screenspace occlusuion test)
+ * return...
+ * 0 : no occlusion
+ * -1 : no occlusion but 2D intersection is true (avoid testing the other half of a quad)
+ * 1 : occluded
+ 2 : occluded with w[3] weights set (need to know in some cases) */
+
+static int project_paint_occlude_ptv(float pt[3], float v1[3], float v2[3], float v3[3], float w[3], int is_ortho)
+{
+ /* if all are behind us, return false */
+ if(v1[2] > pt[2] && v2[2] > pt[2] && v3[2] > pt[2])
+ return 0;
+
+ /* do a 2D point in try intersection */
+ if (!IsectPT2Df(pt, v1, v2, v3))
+ return 0; /* we know there is */
+
+
+ /* From here on we know there IS an intersection */
+ /* if ALL of the verts are infront of us then we know it intersects ? */
+ if(v1[2] < pt[2] && v2[2] < pt[2] && v3[2] < pt[2]) {
+ return 1;
+ }
+ else {
+ /* we intersect? - find the exact depth at the point of intersection */
+ /* Is this point is occluded by another face? */
+ if (is_ortho) {
+ if (VecZDepthOrtho(pt, v1, v2, v3, w) < pt[2]) return 2;
+ }
+ else {
+ if (VecZDepthPersp(pt, v1, v2, v3, w) < pt[2]) return 2;
+ }
+ }
+ return -1;
+}
+
+
+static int project_paint_occlude_ptv_clip(
+ const ProjPaintState *ps, const MFace *mf,
+ float pt[3], float v1[3], float v2[3], float v3[3],
+ const int side )
+{
+ float w[3], wco[3];
+ int ret = project_paint_occlude_ptv(pt, v1, v2, v3, w, ps->is_ortho);
+
+ if (ret <= 0)
+ return ret;
+
+ if (ret==1) { /* weights not calculated */
+ if (ps->is_ortho) BarycentricWeights2f(pt, v1, v2, v3, w);
+ else BarycentricWeightsPersp2f(pt, v1, v2, v3, w);
+ }
+
+ /* Test if we're in the clipped area, */
+ if (side) VecWeightf(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w);
+ else VecWeightf(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w);
+
+ Mat4MulVecfl(ps->ob->obmat, wco);
+ if(!view3d_test_clipping(ps->rv3d, wco)) {
+ return 1;
+ }
+
+ return -1;
+}
+
+
+/* Check if a screenspace location is occluded by any other faces
+ * check, pixelScreenCo must be in screenspace, its Z-Depth only needs to be used for comparison
+ * and dosn't need to be correct in relation to X and Y coords (this is the case in perspective view) */
+static int project_bucket_point_occluded(const ProjPaintState *ps, LinkNode *bucketFace, const int orig_face, float pixelScreenCo[4])
+{
+ MFace *mf;
+ int face_index;
+ int isect_ret;
+ float w[3]; /* not needed when clipping */
+
+ /* we could return 0 for 1 face buckets, as long as this function assumes
+ * that the point its testing is only every originated from an existing face */
+
+ for (; bucketFace; bucketFace = bucketFace->next) {
+ face_index = GET_INT_FROM_POINTER(bucketFace->link);
+
+ if (orig_face != face_index) {
+ mf = ps->dm_mface + face_index;
+ if(ps->rv3d->rflag & RV3D_CLIPPING)
+ isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], 0);
+ else
+ isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], w, ps->is_ortho);
+
+ /* Note, if isect_ret==-1 then we dont want to test the other side of the quad */
+ if (isect_ret==0 && mf->v4) {
+ if(ps->rv3d->rflag & RV3D_CLIPPING)
+ isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], 1);
+ else
+ isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], w, ps->is_ortho);
+ }
+ if (isect_ret==1) {
+ /* TODO - we may want to cache the first hit,
+ * it is not possible to swap the face order in the list anymore */
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/* basic line intersection, could move to arithb.c, 2 points with a horiz line
+ * 1 for an intersection, 2 if the first point is aligned, 3 if the second point is aligned */
+#define ISECT_TRUE 1
+#define ISECT_TRUE_P1 2
+#define ISECT_TRUE_P2 3
+static int line_isect_y(const float p1[2], const float p2[2], const float y_level, float *x_isect)
+{
+ float y_diff;
+
+ if (y_level==p1[1]) { /* are we touching the first point? - no interpolation needed */
+ *x_isect = p1[0];
+ return ISECT_TRUE_P1;
+ }
+ if (y_level==p2[1]) { /* are we touching the second point? - no interpolation needed */
+ *x_isect = p2[0];
+ return ISECT_TRUE_P2;
+ }
+
+ y_diff= fabs(p1[1]-p2[1]); /* yuck, horizontal line, we cant do much here */
+
+ if (y_diff < 0.000001f) {
+ *x_isect = (p1[0]+p2[0]) * 0.5f;
+ return ISECT_TRUE;
+ }
+
+ if (p1[1] > y_level && p2[1] < y_level) {
+ *x_isect = (p2[0]*(p1[1]-y_level) + p1[0]*(y_level-p2[1])) / y_diff; /*(p1[1]-p2[1]);*/
+ return ISECT_TRUE;
+ }
+ else if (p1[1] < y_level && p2[1] > y_level) {
+ *x_isect = (p2[0]*(y_level-p1[1]) + p1[0]*(p2[1]-y_level)) / y_diff; /*(p2[1]-p1[1]);*/
+ return ISECT_TRUE;
+ }
+ else {
+ return 0;
+ }
+}
+
+static int line_isect_x(const float p1[2], const float p2[2], const float x_level, float *y_isect)
+{
+ float x_diff;
+
+ if (x_level==p1[0]) { /* are we touching the first point? - no interpolation needed */
+ *y_isect = p1[1];
+ return ISECT_TRUE_P1;
+ }
+ if (x_level==p2[0]) { /* are we touching the second point? - no interpolation needed */
+ *y_isect = p2[1];
+ return ISECT_TRUE_P2;
+ }
+
+ x_diff= fabs(p1[0]-p2[0]); /* yuck, horizontal line, we cant do much here */
+
+ if (x_diff < 0.000001) { /* yuck, vertical line, we cant do much here */
+ *y_isect = (p1[0]+p2[0]) * 0.5f;
+ return ISECT_TRUE;
+ }
+
+ if (p1[0] > x_level && p2[0] < x_level) {
+ *y_isect = (p2[1]*(p1[0]-x_level) + p1[1]*(x_level-p2[0])) / x_diff; /*(p1[0]-p2[0]);*/
+ return ISECT_TRUE;
+ }
+ else if (p1[0] < x_level && p2[0] > x_level) {
+ *y_isect = (p2[1]*(x_level-p1[0]) + p1[1]*(p2[0]-x_level)) / x_diff; /*(p2[0]-p1[0]);*/
+ return ISECT_TRUE;
+ }
+ else {
+ return 0;
+ }
+}
+
+/* simple func use for comparing UV locations to check if there are seams.
+ * Its possible this gives incorrect results, when the UVs for 1 face go into the next
+ * tile, but do not do this for the adjacent face, it could return a false positive.
+ * This is so unlikely that Id not worry about it. */
+static int cmp_uv(const float vec2a[2], const float vec2b[2])
+{
+ /* if the UV's are not between 0.0 and 1.0 */
+ float xa = (float)fmod(vec2a[0], 1.0f);
+ float ya = (float)fmod(vec2a[1], 1.0f);
+
+ float xb = (float)fmod(vec2b[0], 1.0f);
+ float yb = (float)fmod(vec2b[1], 1.0f);
+
+ if (xa < 0.0f) xa += 1.0f;
+ if (ya < 0.0f) ya += 1.0f;
+
+ if (xb < 0.0f) xb += 1.0f;
+ if (yb < 0.0f) yb += 1.0f;
+
+ return ((fabs(xa-xb) < PROJ_GEOM_TOLERANCE) && (fabs(ya-yb) < PROJ_GEOM_TOLERANCE)) ? 1:0;
+}
+
+
+/* set min_px and max_px to the image space bounds of the UV coords
+ * return zero if there is no area in the returned rectangle */
+static int pixel_bounds_uv(
+ const float uv1[2], const float uv2[2], const float uv3[2], const float uv4[2],
+ rcti *bounds_px,
+ const int ibuf_x, const int ibuf_y,
+ int is_quad
+) {
+ float min_uv[2], max_uv[2]; /* UV bounds */
+
+ INIT_MINMAX2(min_uv, max_uv);
+
+ DO_MINMAX2(uv1, min_uv, max_uv);
+ DO_MINMAX2(uv2, min_uv, max_uv);
+ DO_MINMAX2(uv3, min_uv, max_uv);
+ if (is_quad)
+ DO_MINMAX2(uv4, min_uv, max_uv);
+
+ bounds_px->xmin = (int)(ibuf_x * min_uv[0]);
+ bounds_px->ymin = (int)(ibuf_y * min_uv[1]);
+
+ bounds_px->xmax = (int)(ibuf_x * max_uv[0]) +1;
+ bounds_px->ymax = (int)(ibuf_y * max_uv[1]) +1;
+
+ /*printf("%d %d %d %d \n", min_px[0], min_px[1], max_px[0], max_px[1]);*/
+
+ /* face uses no UV area when quantized to pixels? */
+ return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1;
+}
+
+static int pixel_bounds_array(float (* uv)[2], rcti *bounds_px, const int ibuf_x, const int ibuf_y, int tot)
+{
+ float min_uv[2], max_uv[2]; /* UV bounds */
+
+ if (tot==0) {
+ return 0;
+ }
+
+ INIT_MINMAX2(min_uv, max_uv);
+
+ while (tot--) {
+ DO_MINMAX2((*uv), min_uv, max_uv);
+ uv++;
+ }
+
+ bounds_px->xmin = (int)(ibuf_x * min_uv[0]);
+ bounds_px->ymin = (int)(ibuf_y * min_uv[1]);
+
+ bounds_px->xmax = (int)(ibuf_x * max_uv[0]) +1;
+ bounds_px->ymax = (int)(ibuf_y * max_uv[1]) +1;
+
+ /*printf("%d %d %d %d \n", min_px[0], min_px[1], max_px[0], max_px[1]);*/
+
+ /* face uses no UV area when quantized to pixels? */
+ return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1;
+}
+
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+
+/* This function returns 1 if this face has a seam along the 2 face-vert indicies
+ * 'orig_i1_fidx' and 'orig_i2_fidx' */
+static int check_seam(const ProjPaintState *ps, const int orig_face, const int orig_i1_fidx, const int orig_i2_fidx, int *other_face, int *orig_fidx)
+{
+ LinkNode *node;
+ int face_index;
+ int i1, i2;
+ int i1_fidx = -1, i2_fidx = -1; /* index in face */
+ MFace *mf;
+ MTFace *tf;
+ const MFace *orig_mf = ps->dm_mface + orig_face;
+ const MTFace *orig_tf = ps->dm_mtface + orig_face;
+
+ /* vert indicies from face vert order indicies */
+ i1 = (*(&orig_mf->v1 + orig_i1_fidx));
+ i2 = (*(&orig_mf->v1 + orig_i2_fidx));
+
+ for (node = ps->vertFaces[i1]; node; node = node->next) {
+ face_index = GET_INT_FROM_POINTER(node->link);
+
+ if (face_index != orig_face) {
+ mf = ps->dm_mface + face_index;
+ /* could check if the 2 faces images match here,
+ * but then there wouldn't be a way to return the opposite face's info */
+
+
+ /* We need to know the order of the verts in the adjacent face
+ * set the i1_fidx and i2_fidx to (0,1,2,3) */
+ if (mf->v1==i1) i1_fidx = 0;
+ else if (mf->v2==i1) i1_fidx = 1;
+ else if (mf->v3==i1) i1_fidx = 2;
+ else if (mf->v4 && mf->v4==i1) i1_fidx = 3;
+
+ if (mf->v1==i2) i2_fidx = 0;
+ else if (mf->v2==i2) i2_fidx = 1;
+ else if (mf->v3==i2) i2_fidx = 2;
+ else if (mf->v4 && mf->v4==i2) i2_fidx = 3;
+
+ /* Only need to check if 'i2_fidx' is valid because we know i1_fidx is the same vert on both faces */
+ if (i2_fidx != -1) {
+ /* This IS an adjacent face!, now lets check if the UVs are ok */
+ tf = ps->dm_mtface + face_index;
+
+ /* set up the other face */
+ *other_face = face_index;
+ *orig_fidx = (i1_fidx < i2_fidx) ? i1_fidx : i2_fidx;
+
+ /* first test if they have the same image */
+ if ( (orig_tf->tpage == tf->tpage) &&
+ cmp_uv(orig_tf->uv[orig_i1_fidx], tf->uv[i1_fidx]) &&
+ cmp_uv(orig_tf->uv[orig_i2_fidx], tf->uv[i2_fidx]) )
+ {
+ // printf("SEAM (NONE)\n");
+ return 0;
+
+ }
+ else {
+ // printf("SEAM (UV GAP)\n");
+ return 1;
+ }
+ }
+ }
+ }
+ // printf("SEAM (NO FACE)\n");
+ *other_face = -1;
+ return 1;
+}
+
+/* TODO - move to arithb.c */
+/* Converts an angle to a length that can be used for maintaining an even margin around UV's */
+static float angleToLength(float angle)
+{
+ // already accounted for
+ if (angle < 0.000001f) {
+ return 1.0f;
+ }
+ else {
+ return fabs(1.0f / cos(angle * (M_PI/180.0f)));
+ }
+}
+
+/* Calculate outset UV's, this is not the same as simply scaling the UVs,
+ * since the outset coords are a margin that keep an even distance from the original UV's,
+ * note that the image aspect is taken into account */
+static void uv_image_outset(float (*orig_uv)[2], float (*outset_uv)[2], const float scaler, const int ibuf_x, const int ibuf_y, const int is_quad)
+{
+ float a1, a2, a3, a4=0.0f;
+ float puv[4][2]; /* pixelspace uv's */
+ float no1[2], no2[2], no3[2], no4[2]; /* normals */
+ float dir1[2], dir2[2], dir3[2], dir4[2];
+ float ibuf_x_inv = 1.0f / (float)ibuf_x;
+ float ibuf_y_inv = 1.0f / (float)ibuf_y;
+
+ /* make UV's in pixel space so we can */
+ puv[0][0] = orig_uv[0][0] * ibuf_x;
+ puv[0][1] = orig_uv[0][1] * ibuf_y;
+
+ puv[1][0] = orig_uv[1][0] * ibuf_x;
+ puv[1][1] = orig_uv[1][1] * ibuf_y;
+
+ puv[2][0] = orig_uv[2][0] * ibuf_x;
+ puv[2][1] = orig_uv[2][1] * ibuf_y;
+
+ if (is_quad) {
+ puv[3][0] = orig_uv[3][0] * ibuf_x;
+ puv[3][1] = orig_uv[3][1] * ibuf_y;
+ }
+
+ /* face edge directions */
+ Vec2Subf(dir1, puv[1], puv[0]);
+ Vec2Subf(dir2, puv[2], puv[1]);
+ Normalize2(dir1);
+ Normalize2(dir2);
+
+ if (is_quad) {
+ Vec2Subf(dir3, puv[3], puv[2]);
+ Vec2Subf(dir4, puv[0], puv[3]);
+ Normalize2(dir3);
+ Normalize2(dir4);
+ }
+ else {
+ Vec2Subf(dir3, puv[0], puv[2]);
+ Normalize2(dir3);
+ }
+
+ if (is_quad) {
+ a1 = angleToLength(NormalizedVecAngle2_2D(dir4, dir1));
+ a2 = angleToLength(NormalizedVecAngle2_2D(dir1, dir2));
+ a3 = angleToLength(NormalizedVecAngle2_2D(dir2, dir3));
+ a4 = angleToLength(NormalizedVecAngle2_2D(dir3, dir4));
+ }
+ else {
+ a1 = angleToLength(NormalizedVecAngle2_2D(dir3, dir1));
+ a2 = angleToLength(NormalizedVecAngle2_2D(dir1, dir2));
+ a3 = angleToLength(NormalizedVecAngle2_2D(dir2, dir3));
+ }
+
+ if (is_quad) {
+ Vec2Subf(no1, dir4, dir1);
+ Vec2Subf(no2, dir1, dir2);
+ Vec2Subf(no3, dir2, dir3);
+ Vec2Subf(no4, dir3, dir4);
+ Normalize2(no1);
+ Normalize2(no2);
+ Normalize2(no3);
+ Normalize2(no4);
+ Vec2Mulf(no1, a1*scaler);
+ Vec2Mulf(no2, a2*scaler);
+ Vec2Mulf(no3, a3*scaler);
+ Vec2Mulf(no4, a4*scaler);
+ Vec2Addf(outset_uv[0], puv[0], no1);
+ Vec2Addf(outset_uv[1], puv[1], no2);
+ Vec2Addf(outset_uv[2], puv[2], no3);
+ Vec2Addf(outset_uv[3], puv[3], no4);
+ outset_uv[0][0] *= ibuf_x_inv;
+ outset_uv[0][1] *= ibuf_y_inv;
+
+ outset_uv[1][0] *= ibuf_x_inv;
+ outset_uv[1][1] *= ibuf_y_inv;
+
+ outset_uv[2][0] *= ibuf_x_inv;
+ outset_uv[2][1] *= ibuf_y_inv;
+
+ outset_uv[3][0] *= ibuf_x_inv;
+ outset_uv[3][1] *= ibuf_y_inv;
+ }
+ else {
+ Vec2Subf(no1, dir3, dir1);
+ Vec2Subf(no2, dir1, dir2);
+ Vec2Subf(no3, dir2, dir3);
+ Normalize2(no1);
+ Normalize2(no2);
+ Normalize2(no3);
+ Vec2Mulf(no1, a1*scaler);
+ Vec2Mulf(no2, a2*scaler);
+ Vec2Mulf(no3, a3*scaler);
+ Vec2Addf(outset_uv[0], puv[0], no1);
+ Vec2Addf(outset_uv[1], puv[1], no2);
+ Vec2Addf(outset_uv[2], puv[2], no3);
+ outset_uv[0][0] *= ibuf_x_inv;
+ outset_uv[0][1] *= ibuf_y_inv;
+
+ outset_uv[1][0] *= ibuf_x_inv;
+ outset_uv[1][1] *= ibuf_y_inv;
+
+ outset_uv[2][0] *= ibuf_x_inv;
+ outset_uv[2][1] *= ibuf_y_inv;
+ }
+}
+
+/*
+ * Be tricky with flags, first 4 bits are PROJ_FACE_SEAM1 to 4, last 4 bits are PROJ_FACE_NOSEAM1 to 4
+ * 1<<i - where i is (0-3)
+ *
+ * If we're multithreadng, make sure threads are locked when this is called
+ */
+static void project_face_seams_init(const ProjPaintState *ps, const int face_index, const int is_quad)
+{
+ int other_face, other_fidx; /* vars for the other face, we also set its flag */
+ int fidx1 = is_quad ? 3 : 2;
+ int fidx2 = 0; /* next fidx in the face (0,1,2,3) -> (1,2,3,0) or (0,1,2) -> (1,2,0) for a tri */
+
+ do {
+ if ((ps->faceSeamFlags[face_index] & (1<<fidx1|16<<fidx1)) == 0) {
+ if (check_seam(ps, face_index, fidx1, fidx2, &other_face, &other_fidx)) {
+ ps->faceSeamFlags[face_index] |= 1<<fidx1;
+ if (other_face != -1)
+ ps->faceSeamFlags[other_face] |= 1<<other_fidx;
+ }
+ else {
+ ps->faceSeamFlags[face_index] |= 16<<fidx1;
+ if (other_face != -1)
+ ps->faceSeamFlags[other_face] |= 16<<other_fidx; /* second 4 bits for disabled */
+ }
+ }
+
+ fidx2 = fidx1;
+ } while (fidx1--);
+}
+#endif // PROJ_DEBUG_NOSEAMBLEED
+
+
+/* TODO - move to arithb.c */
+
+/* little sister we only need to know lambda */
+static float lambda_cp_line2(const float p[2], const float l1[2], const float l2[2])
+{
+ float h[2], u[2];
+
+ u[0] = l2[0] - l1[0];
+ u[1] = l2[1] - l1[1];
+
+ h[0] = p[0] - l1[0];
+ h[1] = p[1] - l1[1];
+
+ return(Inp2f(u, h)/Inp2f(u, u));
+}
+
+
+/* Converts a UV location to a 3D screenspace location
+ * Takes a 'uv' and 3 UV coords, and sets the values of pixelScreenCo
+ *
+ * This is used for finding a pixels location in screenspace for painting */
+static void screen_px_from_ortho(
+ float uv[2],
+ float v1co[3], float v2co[3], float v3co[3], /* Screenspace coords */
+ float uv1co[2], float uv2co[2], float uv3co[2],
+ float pixelScreenCo[4],
+ float w[3])
+{
+ BarycentricWeights2f(uv, uv1co, uv2co, uv3co, w);
+ VecWeightf(pixelScreenCo, v1co, v2co, v3co, w);
+}
+
+/* same as screen_px_from_ortho except we need to take into account
+ * the perspective W coord for each vert */
+static void screen_px_from_persp(
+ float uv[2],
+ float v1co[3], float v2co[3], float v3co[3], /* screenspace coords */
+ float uv1co[2], float uv2co[2], float uv3co[2],
+ float pixelScreenCo[4],
+ float w[3])
+{
+
+ float wtot_inv, wtot;
+ BarycentricWeights2f(uv, uv1co, uv2co, uv3co, w);
+
+ /* re-weight from the 4th coord of each screen vert */
+ w[0] *= v1co[3];
+ w[1] *= v2co[3];
+ w[2] *= v3co[3];
+
+ wtot = w[0]+w[1]+w[2];
+
+ if (wtot > 0.0f) {
+ wtot_inv = 1.0f / wtot;
+ w[0] *= wtot_inv;
+ w[1] *= wtot_inv;
+ w[2] *= wtot_inv;
+ }
+ else {
+ w[0] = w[1] = w[2] = 1.0/3.0; /* dummy values for zero area face */
+ }
+ /* done re-weighting */
+
+ VecWeightf(pixelScreenCo, v1co, v2co, v3co, w);
+}
+
+static void project_face_pixel(const MTFace *tf_other, ImBuf *ibuf_other, const float w[3], int side, unsigned char rgba_ub[4], float rgba_f[4])
+{
+ float *uvCo1, *uvCo2, *uvCo3;
+ float uv_other[2], x, y;
+
+ uvCo1 = (float *)tf_other->uv[0];
+ if (side==1) {
+ uvCo2 = (float *)tf_other->uv[2];
+ uvCo3 = (float *)tf_other->uv[3];
+ }
+ else {
+ uvCo2 = (float *)tf_other->uv[1];
+ uvCo3 = (float *)tf_other->uv[2];
+ }
+
+ Vec2Weightf(uv_other, uvCo1, uvCo2, uvCo3, w);
+
+ /* use */
+ uvco_to_wrapped_pxco(uv_other, ibuf_other->x, ibuf_other->y, &x, &y);
+
+
+ if (ibuf_other->rect_float) { /* from float to float */
+ bilinear_interpolation_color(ibuf_other, NULL, rgba_f, x, y);
+ }
+ else { /* from char to float */
+ bilinear_interpolation_color(ibuf_other, rgba_ub, NULL, x, y);
+ }
+
+}
+
+/* run this outside project_paint_uvpixel_init since pixels with mask 0 dont need init */
+float project_paint_uvpixel_mask(
+ const ProjPaintState *ps,
+ const int face_index,
+ const int side,
+ const float w[3])
+{
+ float mask;
+
+ /* Image Mask */
+ if (ps->do_layer_mask) {
+ /* another UV layers image is masking this one's */
+ ImBuf *ibuf_other;
+ const MTFace *tf_other = ps->dm_mtface_mask + face_index;
+
+ if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf((Image *)tf_other->tpage, NULL))) {
+ /* BKE_image_get_ibuf - TODO - this may be slow */
+ unsigned char rgba_ub[4];
+ float rgba_f[4];
+
+ project_face_pixel(tf_other, ibuf_other, w, side, rgba_ub, rgba_f);
+
+ if (ibuf_other->rect_float) { /* from float to float */
+ mask = ((rgba_f[0]+rgba_f[1]+rgba_f[2])/3.0f) * rgba_f[3];
+ }
+ else { /* from char to float */
+ mask = ((rgba_ub[0]+rgba_ub[1]+rgba_ub[2])/(256*3.0f)) * (rgba_ub[3]/256.0f);
+ }
+
+ if (!ps->do_layer_mask_inv) /* matching the gimps layer mask black/white rules, white==full opacity */
+ mask = (1.0f - mask);
+
+ if (mask == 0.0f) {
+ return 0.0f;
+ }
+ }
+ else {
+ return 0.0f;
+ }
+ } else {
+ mask = 1.0f;
+ }
+
+ /* calculate mask */
+ if (ps->do_mask_normal) {
+ MFace *mf = ps->dm_mface + face_index;
+ short *no1, *no2, *no3;
+ float no[3], angle;
+ no1 = ps->dm_mvert[mf->v1].no;
+ if (side==1) {
+ no2 = ps->dm_mvert[mf->v3].no;
+ no3 = ps->dm_mvert[mf->v4].no;
+ }
+ else {
+ no2 = ps->dm_mvert[mf->v2].no;
+ no3 = ps->dm_mvert[mf->v3].no;
+ }
+
+ no[0] = w[0]*no1[0] + w[1]*no2[0] + w[2]*no3[0];
+ no[1] = w[0]*no1[1] + w[1]*no2[1] + w[2]*no3[1];
+ no[2] = w[0]*no1[2] + w[1]*no2[2] + w[2]*no3[2];
+ Normalize(no);
+
+ /* now we can use the normal as a mask */
+ if (ps->is_ortho) {
+ angle = NormalizedVecAngle2((float *)ps->viewDir, no);
+ }
+ else {
+ /* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */
+ float viewDirPersp[3];
+ float *co1, *co2, *co3;
+ co1 = ps->dm_mvert[mf->v1].co;
+ if (side==1) {
+ co2 = ps->dm_mvert[mf->v3].co;
+ co3 = ps->dm_mvert[mf->v4].co;
+ }
+ else {
+ co2 = ps->dm_mvert[mf->v2].co;
+ co3 = ps->dm_mvert[mf->v3].co;
+ }
+
+ /* Get the direction from the viewPoint to the pixel and normalize */
+ viewDirPersp[0] = (ps->viewPos[0] - (w[0]*co1[0] + w[1]*co2[0] + w[2]*co3[0]));
+ viewDirPersp[1] = (ps->viewPos[1] - (w[0]*co1[1] + w[1]*co2[1] + w[2]*co3[1]));
+ viewDirPersp[2] = (ps->viewPos[2] - (w[0]*co1[2] + w[1]*co2[2] + w[2]*co3[2]));
+ Normalize(viewDirPersp);
+
+ angle = NormalizedVecAngle2(viewDirPersp, no);
+ }
+
+ if (angle >= ps->normal_angle) {
+ return 0.0f; /* outsize the normal limit*/
+ }
+ else if (angle > ps->normal_angle_inner) {
+ mask *= (ps->normal_angle - angle) / ps->normal_angle_range;
+ } /* otherwise no mask normal is needed, were within the limit */
+ }
+
+ // This only works when the opacity dosnt change while painting, stylus pressure messes with this
+ // so dont use it.
+ // if (ps->is_airbrush==0) mask *= ps->brush->alpha;
+
+ return mask;
+}
+
+/* run this function when we know a bucket's, face's pixel can be initialized,
+ * return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */
+static ProjPixel *project_paint_uvpixel_init(
+ const ProjPaintState *ps,
+ MemArena *arena,
+ const ImBuf *ibuf,
+ short x_px, short y_px,
+ const float mask,
+ const int face_index,
+ const int image_index,
+ const float pixelScreenCo[4],
+ const int side,
+ const float w[3])
+{
+ ProjPixel *projPixel;
+ short size;
+
+ /* wrap pixel location */
+ x_px = x_px % ibuf->x;
+ if (x_px<0) x_px += ibuf->x;
+ y_px = y_px % ibuf->y;
+ if (y_px<0) y_px += ibuf->y;
+
+ if (ps->tool==PAINT_TOOL_CLONE) {
+ size = sizeof(ProjPixelClone);
+ }
+ else if (ps->tool==PAINT_TOOL_SMEAR) {
+ size = sizeof(ProjPixelClone);
+ }
+ else {
+ size = sizeof(ProjPixel);
+ }
+
+ projPixel = (ProjPixel *)BLI_memarena_alloc(arena, size);
+ //memset(projPixel, 0, size);
+
+ if (ibuf->rect_float) {
+ projPixel->pixel.f_pt = (float *)ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4);
+ projPixel->origColor.f[0] = projPixel->newColor.f[0] = projPixel->pixel.f_pt[0];
+ projPixel->origColor.f[1] = projPixel->newColor.f[1] = projPixel->pixel.f_pt[1];
+ projPixel->origColor.f[2] = projPixel->newColor.f[2] = projPixel->pixel.f_pt[2];
+ projPixel->origColor.f[3] = projPixel->newColor.f[3] = projPixel->pixel.f_pt[3];
+ }
+ else {
+ projPixel->pixel.ch_pt = ((unsigned char *)ibuf->rect + ((x_px + y_px * ibuf->x) * 4));
+ projPixel->origColor.uint = projPixel->newColor.uint = *projPixel->pixel.uint_pt;
+ }
+
+ /* screenspace unclamped, we could keep its z and w values but dont need them at the moment */
+ VECCOPY2D(projPixel->projCoSS, pixelScreenCo);
+
+ projPixel->x_px = x_px;
+ projPixel->y_px = y_px;
+
+ projPixel->mask = (unsigned short)(mask * 65535);
+ projPixel->mask_max = 0;
+
+ /* which bounding box cell are we in?, needed for undo */
+ projPixel->bb_cell_index = ((int)(((float)x_px/(float)ibuf->x) * PROJ_BOUNDBOX_DIV)) + ((int)(((float)y_px/(float)ibuf->y) * PROJ_BOUNDBOX_DIV)) * PROJ_BOUNDBOX_DIV ;
+
+ /* done with view3d_project_float inline */
+ if (ps->tool==PAINT_TOOL_CLONE) {
+ if (ps->dm_mtface_clone) {
+ ImBuf *ibuf_other;
+ const MTFace *tf_other = ps->dm_mtface_clone + face_index;
+
+ if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf((Image *)tf_other->tpage, NULL))) {
+ /* BKE_image_get_ibuf - TODO - this may be slow */
+
+ if (ibuf->rect_float) {
+ if (ibuf_other->rect_float) { /* from float to float */
+ project_face_pixel(tf_other, ibuf_other, w, side, NULL, ((ProjPixelClone *)projPixel)->clonepx.f);
+ }
+ else { /* from char to float */
+ unsigned char rgba_ub[4];
+ project_face_pixel(tf_other, ibuf_other, w, side, rgba_ub, NULL);
+ IMAPAINT_CHAR_RGBA_TO_FLOAT(((ProjPixelClone *)projPixel)->clonepx.f, rgba_ub);
+ }
+ }
+ else {
+ if (ibuf_other->rect_float) { /* float to char */
+ float rgba[4];
+ project_face_pixel(tf_other, ibuf_other, w, side, NULL, rgba);
+ IMAPAINT_FLOAT_RGBA_TO_CHAR(((ProjPixelClone *)projPixel)->clonepx.ch, rgba)
+ }
+ else { /* char to char */
+ project_face_pixel(tf_other, ibuf_other, w, side, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL);
+ }
+ }
+ }
+ else {
+ if (ibuf->rect_float) {
+ ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0;
+ }
+ else {
+ ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0;
+ }
+ }
+
+ }
+ else {
+ float co[2];
+ Vec2Subf(co, projPixel->projCoSS, (float *)ps->cloneOffset);
+
+ /* no need to initialize the bucket, we're only checking buckets faces and for this
+ * the faces are alredy initialized in project_paint_delayed_face_init(...) */
+ if (ibuf->rect_float) {
+ if (!project_paint_PickColor(ps, co, ((ProjPixelClone *)projPixel)->clonepx.f, NULL, 1)) {
+ ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0; /* zero alpha - ignore */
+ }
+ }
+ else {
+ if (!project_paint_PickColor(ps, co, NULL, ((ProjPixelClone *)projPixel)->clonepx.ch, 1)) {
+ ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0; /* zero alpha - ignore */
+ }
+ }
+ }
+ }
+
+#ifdef PROJ_DEBUG_PAINT
+ if (ibuf->rect_float) projPixel->pixel.f_pt[0] = 0;
+ else projPixel->pixel.ch_pt[0] = 0;
+#endif
+ projPixel->image_index = image_index;
+
+ return projPixel;
+}
+
+static int line_clip_rect2f(
+ rctf *rect,
+ const float l1[2], const float l2[2],
+ float l1_clip[2], float l2_clip[2])
+{
+ /* first account for horizontal, then vertical lines */
+ /* horiz */
+ if (fabs(l1[1]-l2[1]) < PROJ_GEOM_TOLERANCE) {
+ /* is the line out of range on its Y axis? */
+ if (l1[1] < rect->ymin || l1[1] > rect->ymax) {
+ return 0;
+ }
+ /* line is out of range on its X axis */
+ if ((l1[0] < rect->xmin && l2[0] < rect->xmin) || (l1[0] > rect->xmax && l2[0] > rect->xmax)) {
+ return 0;
+ }
+
+
+ if (fabs(l1[0]-l2[0]) < PROJ_GEOM_TOLERANCE) { /* this is a single point (or close to)*/
+ if (BLI_in_rctf(rect, l1[0], l1[1])) {
+ VECCOPY2D(l1_clip, l1);
+ VECCOPY2D(l2_clip, l2);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
+
+ VECCOPY2D(l1_clip, l1);
+ VECCOPY2D(l2_clip, l2);
+ CLAMP(l1_clip[0], rect->xmin, rect->xmax);
+ CLAMP(l2_clip[0], rect->xmin, rect->xmax);
+ return 1;
+ }
+ else if (fabs(l1[0]-l2[0]) < PROJ_GEOM_TOLERANCE) {
+ /* is the line out of range on its X axis? */
+ if (l1[0] < rect->xmin || l1[0] > rect->xmax) {
+ return 0;
+ }
+
+ /* line is out of range on its Y axis */
+ if ((l1[1] < rect->ymin && l2[1] < rect->ymin) || (l1[1] > rect->ymax && l2[1] > rect->ymax)) {
+ return 0;
+ }
+
+ if (fabs(l1[1]-l2[1]) < PROJ_GEOM_TOLERANCE) { /* this is a single point (or close to)*/
+ if (BLI_in_rctf(rect, l1[0], l1[1])) {
+ VECCOPY2D(l1_clip, l1);
+ VECCOPY2D(l2_clip, l2);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
+
+ VECCOPY2D(l1_clip, l1);
+ VECCOPY2D(l2_clip, l2);
+ CLAMP(l1_clip[1], rect->ymin, rect->ymax);
+ CLAMP(l2_clip[1], rect->ymin, rect->ymax);
+ return 1;
+ }
+ else {
+ float isect;
+ short ok1 = 0;
+ short ok2 = 0;
+
+ /* Done with vertical lines */
+
+ /* are either of the points inside the rectangle ? */
+ if (BLI_in_rctf(rect, l1[0], l1[1])) {
+ VECCOPY2D(l1_clip, l1);
+ ok1 = 1;
+ }
+
+ if (BLI_in_rctf(rect, l2[0], l2[1])) {
+ VECCOPY2D(l2_clip, l2);
+ ok2 = 1;
+ }
+
+ /* line inside rect */
+ if (ok1 && ok2) return 1;
+
+ /* top/bottom */
+ if (line_isect_y(l1, l2, rect->ymin, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) {
+ if (l1[1] < l2[1]) { /* line 1 is outside */
+ l1_clip[0] = isect;
+ l1_clip[1] = rect->ymin;
+ ok1 = 1;
+ }
+ else {
+ l2_clip[0] = isect;
+ l2_clip[1] = rect->ymin;
+ ok2 = 2;
+ }
+ }
+
+ if (ok1 && ok2) return 1;
+
+ if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) {
+ if (l1[1] > l2[1]) { /* line 1 is outside */
+ l1_clip[0] = isect;
+ l1_clip[1] = rect->ymax;
+ ok1 = 1;
+ }
+ else {
+ l2_clip[0] = isect;
+ l2_clip[1] = rect->ymax;
+ ok2 = 2;
+ }
+ }
+
+ if (ok1 && ok2) return 1;
+
+ /* left/right */
+ if (line_isect_x(l1, l2, rect->xmin, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) {
+ if (l1[0] < l2[0]) { /* line 1 is outside */
+ l1_clip[0] = rect->xmin;
+ l1_clip[1] = isect;
+ ok1 = 1;
+ }
+ else {
+ l2_clip[0] = rect->xmin;
+ l2_clip[1] = isect;
+ ok2 = 2;
+ }
+ }
+
+ if (ok1 && ok2) return 1;
+
+ if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) {
+ if (l1[0] > l2[0]) { /* line 1 is outside */
+ l1_clip[0] = rect->xmax;
+ l1_clip[1] = isect;
+ ok1 = 1;
+ }
+ else {
+ l2_clip[0] = rect->xmax;
+ l2_clip[1] = isect;
+ ok2 = 2;
+ }
+ }
+
+ if (ok1 && ok2) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
+}
+
+
+
+/* scale the quad & tri about its center
+ * scaling by PROJ_FACE_SCALE_SEAM (0.99x) is used for getting fake UV pixel coords that are on the
+ * edge of the face but slightly inside it occlusion tests dont return hits on adjacent faces */
+static void scale_quad(float insetCos[4][3], float *origCos[4], const float inset)
+{
+ float cent[3];
+ cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0] + origCos[3][0]) / 4.0f;
+ cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1] + origCos[3][1]) / 4.0f;
+ cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2] + origCos[3][2]) / 4.0f;
+
+ VecSubf(insetCos[0], origCos[0], cent);
+ VecSubf(insetCos[1], origCos[1], cent);
+ VecSubf(insetCos[2], origCos[2], cent);
+ VecSubf(insetCos[3], origCos[3], cent);
+
+ VecMulf(insetCos[0], inset);
+ VecMulf(insetCos[1], inset);
+ VecMulf(insetCos[2], inset);
+ VecMulf(insetCos[3], inset);
+
+ VecAddf(insetCos[0], insetCos[0], cent);
+ VecAddf(insetCos[1], insetCos[1], cent);
+ VecAddf(insetCos[2], insetCos[2], cent);
+ VecAddf(insetCos[3], insetCos[3], cent);
+}
+
+
+static void scale_tri(float insetCos[4][3], float *origCos[4], const float inset)
+{
+ float cent[3];
+ cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0]) / 3.0f;
+ cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1]) / 3.0f;
+ cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2]) / 3.0f;
+
+ VecSubf(insetCos[0], origCos[0], cent);
+ VecSubf(insetCos[1], origCos[1], cent);
+ VecSubf(insetCos[2], origCos[2], cent);
+
+ VecMulf(insetCos[0], inset);
+ VecMulf(insetCos[1], inset);
+ VecMulf(insetCos[2], inset);
+
+ VecAddf(insetCos[0], insetCos[0], cent);
+ VecAddf(insetCos[1], insetCos[1], cent);
+ VecAddf(insetCos[2], insetCos[2], cent);
+}
+
+
+static float Vec2Lenf_nosqrt(const float *v1, const float *v2)
+{
+ float x, y;
+
+ x = v1[0]-v2[0];
+ y = v1[1]-v2[1];
+ return x*x+y*y;
+}
+
+static float Vec2Lenf_nosqrt_other(const float *v1, const float v2_1, const float v2_2)
+{
+ float x, y;
+
+ x = v1[0]-v2_1;
+ y = v1[1]-v2_2;
+ return x*x+y*y;
+}
+
+/* note, use a squared value so we can use Vec2Lenf_nosqrt
+ * be sure that you have done a bounds check first or this may fail */
+/* only give bucket_bounds as an arg because we need it elsewhere */
+static int project_bucket_isect_circle(const int bucket_x, const int bucket_y, const float cent[2], const float radius_squared, rctf *bucket_bounds)
+{
+
+ /* Would normally to a simple intersection test, however we know the bounds of these 2 alredy intersect
+ * so we only need to test if the center is inside the vertical or horizontal bounds on either axis,
+ * this is even less work then an intersection test
+ *
+ if (BLI_in_rctf(bucket_bounds, cent[0], cent[1]))
+ return 1;
+ */
+
+ if((bucket_bounds->xmin <= cent[0] && bucket_bounds->xmax >= cent[0]) || (bucket_bounds->ymin <= cent[1] && bucket_bounds->ymax >= cent[1]) ) {
+ return 1;
+ }
+
+ /* out of bounds left */
+ if (cent[0] < bucket_bounds->xmin) {
+ /* lower left out of radius test */
+ if (cent[1] < bucket_bounds->ymin) {
+ return (Vec2Lenf_nosqrt_other(cent, bucket_bounds->xmin, bucket_bounds->ymin) < radius_squared) ? 1 : 0;
+ }
+ /* top left test */
+ else if (cent[1] > bucket_bounds->ymax) {
+ return (Vec2Lenf_nosqrt_other(cent, bucket_bounds->xmin, bucket_bounds->ymax) < radius_squared) ? 1 : 0;
+ }
+ }
+ else if (cent[0] > bucket_bounds->xmax) {
+ /* lower right out of radius test */
+ if (cent[1] < bucket_bounds->ymin) {
+ return (Vec2Lenf_nosqrt_other(cent, bucket_bounds->xmax, bucket_bounds->ymin) < radius_squared) ? 1 : 0;
+ }
+ /* top right test */
+ else if (cent[1] > bucket_bounds->ymax) {
+ return (Vec2Lenf_nosqrt_other(cent, bucket_bounds->xmax, bucket_bounds->ymax) < radius_squared) ? 1 : 0;
+ }
+ }
+
+ return 0;
+}
+
+
+
+/* Note for rect_to_uvspace_ortho() and rect_to_uvspace_persp()
+ * in ortho view this function gives good results when bucket_bounds are outside the triangle
+ * however in some cases, perspective view will mess up with faces that have minimal screenspace area (viewed from the side)
+ *
+ * for this reason its not relyable in this case so we'll use the Simple Barycentric' funcs that only account for points inside the triangle.
+ * however switching back to this for ortho is always an option */
+
+static void rect_to_uvspace_ortho(
+ rctf *bucket_bounds,
+ float *v1coSS, float *v2coSS, float *v3coSS,
+ float *uv1co, float *uv2co, float *uv3co,
+ float bucket_bounds_uv[4][2],
+ const int flip)
+{
+ float uv[2];
+ float w[3];
+
+ /* get the UV space bounding box */
+ uv[0] = bucket_bounds->xmax;
+ uv[1] = bucket_bounds->ymin;
+ BarycentricWeights2f(uv, v1coSS, v2coSS, v3coSS, w);
+ Vec2Weightf(bucket_bounds_uv[flip?3:0], uv1co, uv2co, uv3co, w);
+
+ //uv[0] = bucket_bounds->xmax; // set above
+ uv[1] = bucket_bounds->ymax;
+ BarycentricWeights2f(uv, v1coSS, v2coSS, v3coSS, w);
+ Vec2Weightf(bucket_bounds_uv[flip?2:1], uv1co, uv2co, uv3co, w);
+
+ uv[0] = bucket_bounds->xmin;
+ //uv[1] = bucket_bounds->ymax; // set above
+ BarycentricWeights2f(uv, v1coSS, v2coSS, v3coSS, w);
+ Vec2Weightf(bucket_bounds_uv[flip?1:2], uv1co, uv2co, uv3co, w);
+
+ //uv[0] = bucket_bounds->xmin; // set above
+ uv[1] = bucket_bounds->ymin;
+ BarycentricWeights2f(uv, v1coSS, v2coSS, v3coSS, w);
+ Vec2Weightf(bucket_bounds_uv[flip?0:3], uv1co, uv2co, uv3co, w);
+}
+
+/* same as above but use BarycentricWeightsPersp2f */
+static void rect_to_uvspace_persp(
+ rctf *bucket_bounds,
+ float *v1coSS, float *v2coSS, float *v3coSS,
+ float *uv1co, float *uv2co, float *uv3co,
+ float bucket_bounds_uv[4][2],
+ const int flip
+ )
+{
+ float uv[2];
+ float w[3];
+
+ /* get the UV space bounding box */
+ uv[0] = bucket_bounds->xmax;
+ uv[1] = bucket_bounds->ymin;
+ BarycentricWeightsPersp2f(uv, v1coSS, v2coSS, v3coSS, w);
+ Vec2Weightf(bucket_bounds_uv[flip?3:0], uv1co, uv2co, uv3co, w);
+
+ //uv[0] = bucket_bounds->xmax; // set above
+ uv[1] = bucket_bounds->ymax;
+ BarycentricWeightsPersp2f(uv, v1coSS, v2coSS, v3coSS, w);
+ Vec2Weightf(bucket_bounds_uv[flip?2:1], uv1co, uv2co, uv3co, w);
+
+ uv[0] = bucket_bounds->xmin;
+ //uv[1] = bucket_bounds->ymax; // set above
+ BarycentricWeightsPersp2f(uv, v1coSS, v2coSS, v3coSS, w);
+ Vec2Weightf(bucket_bounds_uv[flip?1:2], uv1co, uv2co, uv3co, w);
+
+ //uv[0] = bucket_bounds->xmin; // set above
+ uv[1] = bucket_bounds->ymin;
+ BarycentricWeightsPersp2f(uv, v1coSS, v2coSS, v3coSS, w);
+ Vec2Weightf(bucket_bounds_uv[flip?0:3], uv1co, uv2co, uv3co, w);
+}
+
+/* This works as we need it to but we can save a few steps and not use it */
+
+#if 0
+static float angle_2d_clockwise(const float p1[2], const float p2[2], const float p3[2])
+{
+ float v1[2], v2[2];
+
+ v1[0] = p1[0]-p2[0]; v1[1] = p1[1]-p2[1];
+ v2[0] = p3[0]-p2[0]; v2[1] = p3[1]-p2[1];
+
+ return -atan2(v1[0]*v2[1] - v1[1]*v2[0], v1[0]*v2[0]+v1[1]*v2[1]);
+}
+#endif
+
+#define ISECT_1 (1)
+#define ISECT_2 (1<<1)
+#define ISECT_3 (1<<2)
+#define ISECT_4 (1<<3)
+#define ISECT_ALL3 ((1<<3)-1)
+#define ISECT_ALL4 ((1<<4)-1)
+
+/* limit must be a fraction over 1.0f */
+static int IsectPT2Df_limit(float pt[2], float v1[2], float v2[2], float v3[2], float limit)
+{
+ return ((AreaF2Dfl(pt,v1,v2) + AreaF2Dfl(pt,v2,v3) + AreaF2Dfl(pt,v3,v1)) / (AreaF2Dfl(v1,v2,v3))) < limit;
+}
+
+/* Clip the face by a bucket and set the uv-space bucket_bounds_uv
+ * so we have the clipped UV's to do pixel intersection tests with
+ * */
+static int float_z_sort_flip(const void *p1, const void *p2) {
+ return (((float *)p1)[2] < ((float *)p2)[2] ? 1:-1);
+}
+
+static int float_z_sort(const void *p1, const void *p2) {
+ return (((float *)p1)[2] < ((float *)p2)[2] ?-1:1);
+}
+
+static void project_bucket_clip_face(
+ const int is_ortho,
+ rctf *bucket_bounds,
+ float *v1coSS, float *v2coSS, float *v3coSS,
+ float *uv1co, float *uv2co, float *uv3co,
+ float bucket_bounds_uv[8][2],
+ int *tot)
+{
+ int inside_bucket_flag = 0;
+ int inside_face_flag = 0;
+ const int flip = ((SIDE_OF_LINE(v1coSS, v2coSS, v3coSS) > 0.0f) != (SIDE_OF_LINE(uv1co, uv2co, uv3co) > 0.0f));
+
+ float bucket_bounds_ss[4][2];
+ float w[3];
+
+ /* get the UV space bounding box */
+ inside_bucket_flag |= BLI_in_rctf(bucket_bounds, v1coSS[0], v1coSS[1]);
+ inside_bucket_flag |= BLI_in_rctf(bucket_bounds, v2coSS[0], v2coSS[1]) << 1;
+ inside_bucket_flag |= BLI_in_rctf(bucket_bounds, v3coSS[0], v3coSS[1]) << 2;
+
+ if (inside_bucket_flag == ISECT_ALL3) {
+ /* all screenspace points are inside the bucket bounding box, this means we dont need to clip and can simply return the UVs */
+ if (flip) { /* facing the back? */
+ VECCOPY2D(bucket_bounds_uv[0], uv3co);
+ VECCOPY2D(bucket_bounds_uv[1], uv2co);
+ VECCOPY2D(bucket_bounds_uv[2], uv1co);
+ }
+ else {
+ VECCOPY2D(bucket_bounds_uv[0], uv1co);
+ VECCOPY2D(bucket_bounds_uv[1], uv2co);
+ VECCOPY2D(bucket_bounds_uv[2], uv3co);
+ }
+
+ *tot = 3;
+ return;
+ }
+
+ /* get the UV space bounding box */
+ /* use IsectPT2Df_limit here so we catch points are are touching the tri edge (or a small fraction over) */
+ bucket_bounds_ss[0][0] = bucket_bounds->xmax;
+ bucket_bounds_ss[0][1] = bucket_bounds->ymin;
+ inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[0], v1coSS, v2coSS, v3coSS, 1+PROJ_GEOM_TOLERANCE) ? ISECT_1 : 0);
+
+ bucket_bounds_ss[1][0] = bucket_bounds->xmax;
+ bucket_bounds_ss[1][1] = bucket_bounds->ymax;
+ inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[1], v1coSS, v2coSS, v3coSS, 1+PROJ_GEOM_TOLERANCE) ? ISECT_2 : 0);
+
+ bucket_bounds_ss[2][0] = bucket_bounds->xmin;
+ bucket_bounds_ss[2][1] = bucket_bounds->ymax;
+ inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[2], v1coSS, v2coSS, v3coSS, 1+PROJ_GEOM_TOLERANCE) ? ISECT_3 : 0);
+
+ bucket_bounds_ss[3][0] = bucket_bounds->xmin;
+ bucket_bounds_ss[3][1] = bucket_bounds->ymin;
+ inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[3], v1coSS, v2coSS, v3coSS, 1+PROJ_GEOM_TOLERANCE) ? ISECT_4 : 0);
+
+ if (inside_face_flag == ISECT_ALL4) {
+ /* bucket is totally inside the screenspace face, we can safely use weights */
+
+ if (is_ortho) rect_to_uvspace_ortho(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip);
+ else rect_to_uvspace_persp(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip);
+
+ *tot = 4;
+ return;
+ }
+ else {
+ /* The Complicated Case!
+ *
+ * The 2 cases above are where the face is inside the bucket or the bucket is inside the face.
+ *
+ * we need to make a convex polyline from the intersection between the screenspace face
+ * and the bucket bounds.
+ *
+ * There are a number of ways this could be done, currently it just collects all intersecting verts,
+ * and line intersections, then sorts them clockwise, this is a lot easier then evaluating the geometry to
+ * do a correct clipping on both shapes. */
+
+
+ /* add a bunch of points, we know must make up the convex hull which is the clipped rect and triangle */
+
+
+
+ /* Maximum possible 6 intersections when using a rectangle and triangle */
+ float isectVCosSS[8][3]; /* The 3rd float is used to store angle for qsort(), NOT as a Z location */
+ float v1_clipSS[2], v2_clipSS[2];
+
+ /* calc center*/
+ float cent[2] = {0.0f, 0.0f};
+ /*float up[2] = {0.0f, 1.0f};*/
+ int i;
+ short doubles;
+
+ (*tot) = 0;
+
+ if (inside_face_flag & ISECT_1) { VECCOPY2D(isectVCosSS[*tot], bucket_bounds_ss[0]); (*tot)++; }
+ if (inside_face_flag & ISECT_2) { VECCOPY2D(isectVCosSS[*tot], bucket_bounds_ss[1]); (*tot)++; }
+ if (inside_face_flag & ISECT_3) { VECCOPY2D(isectVCosSS[*tot], bucket_bounds_ss[2]); (*tot)++; }
+ if (inside_face_flag & ISECT_4) { VECCOPY2D(isectVCosSS[*tot], bucket_bounds_ss[3]); (*tot)++; }
+
+ if (inside_bucket_flag & ISECT_1) { VECCOPY2D(isectVCosSS[*tot], v1coSS); (*tot)++; }
+ if (inside_bucket_flag & ISECT_2) { VECCOPY2D(isectVCosSS[*tot], v2coSS); (*tot)++; }
+ if (inside_bucket_flag & ISECT_3) { VECCOPY2D(isectVCosSS[*tot], v3coSS); (*tot)++; }
+
+ if ((inside_bucket_flag & (ISECT_1|ISECT_2)) != (ISECT_1|ISECT_2)) {
+ if (line_clip_rect2f(bucket_bounds, v1coSS, v2coSS, v1_clipSS, v2_clipSS)) {
+ if ((inside_bucket_flag & ISECT_1)==0) { VECCOPY2D(isectVCosSS[*tot], v1_clipSS); (*tot)++; }
+ if ((inside_bucket_flag & ISECT_2)==0) { VECCOPY2D(isectVCosSS[*tot], v2_clipSS); (*tot)++; }
+ }
+ }
+
+ if ((inside_bucket_flag & (ISECT_2|ISECT_3)) != (ISECT_2|ISECT_3)) {
+ if (line_clip_rect2f(bucket_bounds, v2coSS, v3coSS, v1_clipSS, v2_clipSS)) {
+ if ((inside_bucket_flag & ISECT_2)==0) { VECCOPY2D(isectVCosSS[*tot], v1_clipSS); (*tot)++; }
+ if ((inside_bucket_flag & ISECT_3)==0) { VECCOPY2D(isectVCosSS[*tot], v2_clipSS); (*tot)++; }
+ }
+ }
+
+ if ((inside_bucket_flag & (ISECT_3|ISECT_1)) != (ISECT_3|ISECT_1)) {
+ if (line_clip_rect2f(bucket_bounds, v3coSS, v1coSS, v1_clipSS, v2_clipSS)) {
+ if ((inside_bucket_flag & ISECT_3)==0) { VECCOPY2D(isectVCosSS[*tot], v1_clipSS); (*tot)++; }
+ if ((inside_bucket_flag & ISECT_1)==0) { VECCOPY2D(isectVCosSS[*tot], v2_clipSS); (*tot)++; }
+ }
+ }
+
+
+ if ((*tot) < 3) { /* no intersections to speak of */
+ *tot = 0;
+ }
+
+ /* now we have all points we need, collect their angles and sort them clockwise */
+
+ for(i=0; i<(*tot); i++) {
+ cent[0] += isectVCosSS[i][0];
+ cent[1] += isectVCosSS[i][1];
+ }
+ cent[0] = cent[0] / (float)(*tot);
+ cent[1] = cent[1] / (float)(*tot);
+
+
+
+ /* Collect angles for every point around the center point */
+
+
+#if 0 /* uses a few more cycles then the above loop */
+ for(i=0; i<(*tot); i++) {
+ isectVCosSS[i][2] = angle_2d_clockwise(up, cent, isectVCosSS[i]);
+ }
+#endif
+
+ v1_clipSS[0] = cent[0]; /* Abuse this var for the loop below */
+ v1_clipSS[1] = cent[1] + 1.0f;
+
+ for(i=0; i<(*tot); i++) {
+ v2_clipSS[0] = isectVCosSS[i][0] - cent[0];
+ v2_clipSS[1] = isectVCosSS[i][1] - cent[1];
+ isectVCosSS[i][2] = atan2(v1_clipSS[0]*v2_clipSS[1] - v1_clipSS[1]*v2_clipSS[0], v1_clipSS[0]*v2_clipSS[0]+v1_clipSS[1]*v2_clipSS[1]);
+ }
+
+ if (flip) qsort(isectVCosSS, *tot, sizeof(float)*3, float_z_sort_flip);
+ else qsort(isectVCosSS, *tot, sizeof(float)*3, float_z_sort);
+
+
+ /* remove doubles */
+ /* first/last check */
+ if (fabs(isectVCosSS[0][0]-isectVCosSS[(*tot)-1][0]) < PROJ_GEOM_TOLERANCE && fabs(isectVCosSS[0][1]-isectVCosSS[(*tot)-1][1]) < PROJ_GEOM_TOLERANCE) {
+ (*tot)--;
+ }
+
+ /* its possible there is only a few left after remove doubles */
+ if ((*tot) < 3) {
+ // printf("removed too many doubles A\n");
+ *tot = 0;
+ return;
+ }
+
+ doubles = TRUE;
+ while (doubles==TRUE) {
+ doubles = FALSE;
+ for(i=1; i<(*tot); i++) {
+ if (fabs(isectVCosSS[i-1][0]-isectVCosSS[i][0]) < PROJ_GEOM_TOLERANCE &&
+ fabs(isectVCosSS[i-1][1]-isectVCosSS[i][1]) < PROJ_GEOM_TOLERANCE)
+ {
+ int j;
+ for(j=i+1; j<(*tot); j++) {
+ isectVCosSS[j-1][0] = isectVCosSS[j][0];
+ isectVCosSS[j-1][1] = isectVCosSS[j][1];
+ }
+ doubles = TRUE; /* keep looking for more doubles */
+ (*tot)--;
+ }
+ }
+ }
+
+ /* its possible there is only a few left after remove doubles */
+ if ((*tot) < 3) {
+ // printf("removed too many doubles B\n");
+ *tot = 0;
+ return;
+ }
+
+
+ if (is_ortho) {
+ for(i=0; i<(*tot); i++) {
+ BarycentricWeights2f(isectVCosSS[i], v1coSS, v2coSS, v3coSS, w);
+ Vec2Weightf(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w);
+ }
+ }
+ else {
+ for(i=0; i<(*tot); i++) {
+ BarycentricWeightsPersp2f(isectVCosSS[i], v1coSS, v2coSS, v3coSS, w);
+ Vec2Weightf(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w);
+ }
+ }
+ }
+
+#ifdef PROJ_DEBUG_PRINT_CLIP
+ /* include this at the bottom of the above function to debug the output */
+
+ {
+ /* If there are ever any problems, */
+ float test_uv[4][2];
+ int i;
+ if (is_ortho) rect_to_uvspace_ortho(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip);
+ else rect_to_uvspace_persp(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip);
+ printf("( [(%f,%f), (%f,%f), (%f,%f), (%f,%f)], ", test_uv[0][0], test_uv[0][1], test_uv[1][0], test_uv[1][1], test_uv[2][0], test_uv[2][1], test_uv[3][0], test_uv[3][1]);
+
+ printf(" [(%f,%f), (%f,%f), (%f,%f)], ", uv1co[0], uv1co[1], uv2co[0], uv2co[1], uv3co[0], uv3co[1]);
+
+ printf("[");
+ for (i=0; i < (*tot); i++) {
+ printf("(%f, %f),", bucket_bounds_uv[i][0], bucket_bounds_uv[i][1]);
+ }
+ printf("]),\\\n");
+ }
+#endif
+}
+
+ /*
+# This script creates faces in a blender scene from printed data above.
+
+project_ls = [
+...(output from above block)...
+]
+
+from Blender import Scene, Mesh, Window, sys, Mathutils
+
+import bpy
+
+V = Mathutils.Vector
+
+def main():
+ sce = bpy.data.scenes.active
+
+ for item in project_ls:
+ bb = item[0]
+ uv = item[1]
+ poly = item[2]
+
+ me = bpy.data.meshes.new()
+ ob = sce.objects.new(me)
+
+ me.verts.extend([V(bb[0]).resize3D(), V(bb[1]).resize3D(), V(bb[2]).resize3D(), V(bb[3]).resize3D()])
+ me.faces.extend([(0,1,2,3),])
+ me.verts.extend([V(uv[0]).resize3D(), V(uv[1]).resize3D(), V(uv[2]).resize3D()])
+ me.faces.extend([(4,5,6),])
+
+ vs = [V(p).resize3D() for p in poly]
+ print len(vs)
+ l = len(me.verts)
+ me.verts.extend(vs)
+
+ i = l
+ while i < len(me.verts):
+ ii = i+1
+ if ii==len(me.verts):
+ ii = l
+ me.edges.extend([i, ii])
+ i+=1
+
+if __name__ == '__main__':
+ main()
+ */
+
+
+#undef ISECT_1
+#undef ISECT_2
+#undef ISECT_3
+#undef ISECT_4
+#undef ISECT_ALL3
+#undef ISECT_ALL4
+
+
+/* checks if pt is inside a convex 2D polyline, the polyline must be ordered rotating clockwise
+ * otherwise it would have to test for mixed (SIDE_OF_LINE > 0.0f) cases */
+int IsectPoly2Df(const float pt[2], float uv[][2], const int tot)
+{
+ int i;
+ if (SIDE_OF_LINE(uv[tot-1], uv[0], pt) < 0.0f)
+ return 0;
+
+ for (i=1; i<tot; i++) {
+ if (SIDE_OF_LINE(uv[i-1], uv[i], pt) < 0.0f)
+ return 0;
+
+ }
+
+ return 1;
+}
+
+/* One of the most important function for projectiopn painting, since it selects the pixels to be added into each bucket.
+ * initialize pixels from this face where it intersects with the bucket_index, optionally initialize pixels for removing seams */
+static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, const ImBuf *ibuf)
+{
+ /* Projection vars, to get the 3D locations into screen space */
+ MemArena *arena = ps->arena_mt[thread_index];
+ LinkNode **bucketPixelNodes = ps->bucketRect + bucket_index;
+ LinkNode *bucketFaceNodes = ps->bucketFaces[bucket_index];
+
+ const MFace *mf = ps->dm_mface + face_index;
+ const MTFace *tf = ps->dm_mtface + face_index;
+
+ /* UV/pixel seeking data */
+ int x; /* Image X-Pixel */
+ int y;/* Image Y-Pixel */
+ float mask;
+ float uv[2]; /* Image floating point UV - same as x, y but from 0.0-1.0 */
+
+ int side;
+ float *v1coSS, *v2coSS, *v3coSS; /* vert co screen-space, these will be assigned to mf->v1,2,3 or mf->v1,3,4 */
+
+ float *vCo[4]; /* vertex screenspace coords */
+
+ float w[3], wco[3];
+
+ float *uv1co, *uv2co, *uv3co; /* for convenience only, these will be assigned to tf->uv[0],1,2 or tf->uv[0],2,3 */
+ float pixelScreenCo[4];
+
+ rcti bounds_px; /* ispace bounds */
+ /* vars for getting uvspace bounds */
+
+ float tf_uv_pxoffset[4][2]; /* bucket bounds in UV space so we can init pixels only for this face, */
+ float xhalfpx, yhalfpx;
+ const float ibuf_xf = ibuf->x, ibuf_yf = ibuf->y;
+
+ int has_x_isect = 0, has_isect = 0; /* for early loop exit */
+
+ int i1, i2, i3;
+
+ float uv_clip[8][2];
+ int uv_clip_tot;
+ const short is_ortho = ps->is_ortho;
+
+ vCo[0] = ps->dm_mvert[mf->v1].co;
+ vCo[1] = ps->dm_mvert[mf->v2].co;
+ vCo[2] = ps->dm_mvert[mf->v3].co;
+
+
+ /* Use tf_uv_pxoffset instead of tf->uv so we can offset the UV half a pixel
+ * this is done so we can avoid offseting all the pixels by 0.5 which causes
+ * problems when wrapping negative coords */
+ xhalfpx = 0.5f / ibuf_xf;
+ yhalfpx = 0.5f / ibuf_yf;
+
+ tf_uv_pxoffset[0][0] = tf->uv[0][0] - xhalfpx;
+ tf_uv_pxoffset[0][1] = tf->uv[0][1] - yhalfpx;
+
+ tf_uv_pxoffset[1][0] = tf->uv[1][0] - xhalfpx;
+ tf_uv_pxoffset[1][1] = tf->uv[1][1] - yhalfpx;
+
+ tf_uv_pxoffset[2][0] = tf->uv[2][0] - xhalfpx;
+ tf_uv_pxoffset[2][1] = tf->uv[2][1] - yhalfpx;
+
+ if (mf->v4) {
+ vCo[3] = ps->dm_mvert[ mf->v4 ].co;
+
+ tf_uv_pxoffset[3][0] = tf->uv[3][0] - xhalfpx;
+ tf_uv_pxoffset[3][1] = tf->uv[3][1] - yhalfpx;
+ side = 1;
+ }
+ else {
+ side = 0;
+ }
+
+ do {
+ if (side==1) {
+ i1=0; i2=2; i3=3;
+ }
+ else {
+ i1=0; i2=1; i3=2;
+ }
+
+ uv1co = tf_uv_pxoffset[i1]; // was tf->uv[i1];
+ uv2co = tf_uv_pxoffset[i2]; // was tf->uv[i2];
+ uv3co = tf_uv_pxoffset[i3]; // was tf->uv[i3];
+
+ v1coSS = ps->screenCoords[ (*(&mf->v1 + i1)) ];
+ v2coSS = ps->screenCoords[ (*(&mf->v1 + i2)) ];
+ v3coSS = ps->screenCoords[ (*(&mf->v1 + i3)) ];
+
+
+ /* This funtion gives is a concave polyline in UV space from the clipped quad and tri*/
+ project_bucket_clip_face(
+ is_ortho, bucket_bounds,
+ v1coSS, v2coSS, v3coSS,
+ uv1co, uv2co, uv3co,
+ uv_clip, &uv_clip_tot
+ );
+
+
+ /* sometimes this happens, better just allow for 8 intersectiosn even though there should be max 6 */
+ /*
+ if (uv_clip_tot>6) {
+ printf("this should never happen! %d\n", uv_clip_tot);
+ }*/
+
+
+ if (pixel_bounds_array(uv_clip, &bounds_px, ibuf->x, ibuf->y, uv_clip_tot)) {
+
+ /* clip face and */
+
+ has_isect = 0;
+ for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
+ //uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
+ uv[1] = (float)y / ibuf_yf; /* use pixel offset UV coords instead */
+
+ has_x_isect = 0;
+ for (x = bounds_px.xmin; x < bounds_px.xmax; x++) {
+ //uv[0] = (((float)x) + 0.5f) / ibuf->x;
+ uv[0] = (float)x / ibuf_xf; /* use pixel offset UV coords instead */
+
+ if (IsectPoly2Df(uv, uv_clip, uv_clip_tot)) {
+
+ has_x_isect = has_isect = 1;
+
+ if (is_ortho) screen_px_from_ortho(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
+ else screen_px_from_persp(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
+
+ /* a pitty we need to get the worldspace pixel location here */
+ if(ps->rv3d->rflag & RV3D_CLIPPING) {
+ VecWeightf(wco, ps->dm_mvert[ (*(&mf->v1 + i1)) ].co, ps->dm_mvert[ (*(&mf->v1 + i2)) ].co, ps->dm_mvert[ (*(&mf->v1 + i3)) ].co, w);
+ Mat4MulVecfl(ps->ob->obmat, wco);
+ if(view3d_test_clipping(ps->rv3d, wco)) {
+ continue; /* Watch out that no code below this needs to run */
+ }
+ }
+
+ /* Is this UV visible from the view? - raytrace */
+ /* project_paint_PickFace is less complex, use for testing */
+ //if (project_paint_PickFace(ps, pixelScreenCo, w, &side) == face_index) {
+ if (ps->do_occlude==0 || !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo)) {
+
+ mask = project_paint_uvpixel_mask(ps, face_index, side, w);
+
+ if (mask > 0.0f) {
+ BLI_linklist_prepend_arena(
+ bucketPixelNodes,
+ project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, side, w),
+ arena
+ );
+ }
+ }
+
+ }
+//#if 0
+ else if (has_x_isect) {
+ /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
+ break;
+ }
+//#endif
+ }
+
+
+#if 0 /* TODO - investigate why this dosnt work sometimes! it should! */
+ /* no intersection for this entire row, after some intersection above means we can quit now */
+ if (has_x_isect==0 && has_isect) {
+ break;
+ }
+#endif
+ }
+ }
+ } while(side--);
+
+
+
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ if (ps->seam_bleed_px > 0.0f) {
+ int face_seam_flag;
+
+ if (ps->thread_tot > 1)
+ BLI_lock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
+
+ face_seam_flag = ps->faceSeamFlags[face_index];
+
+ /* are any of our edges un-initialized? */
+ if ((face_seam_flag & (PROJ_FACE_SEAM1|PROJ_FACE_NOSEAM1))==0 ||
+ (face_seam_flag & (PROJ_FACE_SEAM2|PROJ_FACE_NOSEAM2))==0 ||
+ (face_seam_flag & (PROJ_FACE_SEAM3|PROJ_FACE_NOSEAM3))==0 ||
+ (face_seam_flag & (PROJ_FACE_SEAM4|PROJ_FACE_NOSEAM4))==0
+ ) {
+ project_face_seams_init(ps, face_index, mf->v4);
+ face_seam_flag = ps->faceSeamFlags[face_index];
+ //printf("seams - %d %d %d %d\n", flag&PROJ_FACE_SEAM1, flag&PROJ_FACE_SEAM2, flag&PROJ_FACE_SEAM3, flag&PROJ_FACE_SEAM4);
+ }
+
+ if ((face_seam_flag & (PROJ_FACE_SEAM1|PROJ_FACE_SEAM2|PROJ_FACE_SEAM3|PROJ_FACE_SEAM4))==0) {
+
+ if (ps->thread_tot > 1)
+ BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
+
+ }
+ else {
+ /* we have a seam - deal with it! */
+
+ /* Now create new UV's for the seam face */
+ float (*outset_uv)[2] = ps->faceSeamUVs[face_index];
+ float insetCos[4][3]; /* inset face coords. NOTE!!! ScreenSace for ortho, Worldspace in prespective view */
+
+ float *uv_seam_quad[4];
+ float fac;
+ float *vCoSS[4]; /* vertex screenspace coords */
+
+ float bucket_clip_edges[2][2]; /* store the screenspace coords of the face, clipped by the bucket's screen aligned rectangle */
+ float edge_verts_inset_clip[2][3];
+ int fidx1, fidx2; /* face edge pairs - loop throuh these ((0,1), (1,2), (2,3), (3,0)) or ((0,1), (1,2), (2,0)) for a tri */
+
+ float seam_subsection[4][2];
+ float fac1, fac2, ftot;
+
+
+ if (outset_uv[0][0]==FLT_MAX) /* first time initialize */
+ uv_image_outset(tf_uv_pxoffset, outset_uv, ps->seam_bleed_px, ibuf->x, ibuf->y, mf->v4);
+
+ /* ps->faceSeamUVs cant be modified when threading, now this is done we can unlock */
+ if (ps->thread_tot > 1)
+ BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
+
+ vCoSS[0] = ps->screenCoords[mf->v1];
+ vCoSS[1] = ps->screenCoords[mf->v2];
+ vCoSS[2] = ps->screenCoords[mf->v3];
+ if (mf->v4)
+ vCoSS[3] = ps->screenCoords[ mf->v4 ];
+
+ /* PROJ_FACE_SCALE_SEAM must be slightly less then 1.0f */
+ if (is_ortho) {
+ if (mf->v4) scale_quad(insetCos, vCoSS, PROJ_FACE_SCALE_SEAM);
+ else scale_tri(insetCos, vCoSS, PROJ_FACE_SCALE_SEAM);
+ }
+ else {
+ if (mf->v4) scale_quad(insetCos, vCo, PROJ_FACE_SCALE_SEAM);
+ else scale_tri(insetCos, vCo, PROJ_FACE_SCALE_SEAM);
+ }
+
+ side = 0; /* for triangles this wont need to change */
+
+ for (fidx1 = 0; fidx1 < (mf->v4 ? 4 : 3); fidx1++) {
+ if (mf->v4) fidx2 = (fidx1==3) ? 0 : fidx1+1; /* next fidx in the face (0,1,2,3) -> (1,2,3,0) */
+ else fidx2 = (fidx1==2) ? 0 : fidx1+1; /* next fidx in the face (0,1,2) -> (1,2,0) */
+
+ if ( (face_seam_flag & (1<<fidx1)) && /* 1<<fidx1 -> PROJ_FACE_SEAM# */
+ line_clip_rect2f(bucket_bounds, vCoSS[fidx1], vCoSS[fidx2], bucket_clip_edges[0], bucket_clip_edges[1])
+ ) {
+
+ ftot = Vec2Lenf(vCoSS[fidx1], vCoSS[fidx2]); /* screenspace edge length */
+
+ if (ftot > 0.0f) { /* avoid div by zero */
+ if (mf->v4) {
+ if (fidx1==2 || fidx2==2) side= 1;
+ else side= 0;
+ }
+
+ fac1 = Vec2Lenf(vCoSS[fidx1], bucket_clip_edges[0]) / ftot;
+ fac2 = Vec2Lenf(vCoSS[fidx1], bucket_clip_edges[1]) / ftot;
+
+ uv_seam_quad[0] = tf_uv_pxoffset[fidx1];
+ uv_seam_quad[1] = tf_uv_pxoffset[fidx2];
+ uv_seam_quad[2] = outset_uv[fidx2];
+ uv_seam_quad[3] = outset_uv[fidx1];
+
+ Vec2Lerpf(seam_subsection[0], uv_seam_quad[0], uv_seam_quad[1], fac1);
+ Vec2Lerpf(seam_subsection[1], uv_seam_quad[0], uv_seam_quad[1], fac2);
+
+ Vec2Lerpf(seam_subsection[2], uv_seam_quad[3], uv_seam_quad[2], fac2);
+ Vec2Lerpf(seam_subsection[3], uv_seam_quad[3], uv_seam_quad[2], fac1);
+
+ /* if the bucket_clip_edges values Z values was kept we could avoid this
+ * Inset needs to be added so occlusion tests wont hit adjacent faces */
+ VecLerpf(edge_verts_inset_clip[0], insetCos[fidx1], insetCos[fidx2], fac1);
+ VecLerpf(edge_verts_inset_clip[1], insetCos[fidx1], insetCos[fidx2], fac2);
+
+
+ if (pixel_bounds_uv(seam_subsection[0], seam_subsection[1], seam_subsection[2], seam_subsection[3], &bounds_px, ibuf->x, ibuf->y, 1)) {
+ /* bounds between the seam rect and the uvspace bucket pixels */
+
+ has_isect = 0;
+ for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
+ // uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
+ uv[1] = (float)y / ibuf_yf; /* use offset uvs instead */
+
+ has_x_isect = 0;
+ for (x = bounds_px.xmin; x < bounds_px.xmax; x++) {
+ //uv[0] = (((float)x) + 0.5f) / (float)ibuf->x;
+ uv[0] = (float)x / ibuf_xf; /* use offset uvs instead */
+
+ /* test we're inside uvspace bucket and triangle bounds */
+ if (IsectPQ2Df(uv, seam_subsection[0], seam_subsection[1], seam_subsection[2], seam_subsection[3])) {
+
+ /* We need to find the closest point along the face edge,
+ * getting the screen_px_from_*** wont work because our actual location
+ * is not relevent, since we are outside the face, Use VecLerpf to find
+ * our location on the side of the face's UV */
+ /*
+ if (is_ortho) screen_px_from_ortho(ps, uv, v1co, v2co, v3co, uv1co, uv2co, uv3co, pixelScreenCo);
+ else screen_px_from_persp(ps, uv, v1co, v2co, v3co, uv1co, uv2co, uv3co, pixelScreenCo);
+ */
+
+ /* Since this is a seam we need to work out where on the line this pixel is */
+ //fac = lambda_cp_line2(uv, uv_seam_quad[0], uv_seam_quad[1]);
+
+ fac = lambda_cp_line2(uv, seam_subsection[0], seam_subsection[1]);
+ if (fac < 0.0f) { VECCOPY(pixelScreenCo, edge_verts_inset_clip[0]); }
+ else if (fac > 1.0f) { VECCOPY(pixelScreenCo, edge_verts_inset_clip[1]); }
+ else { VecLerpf(pixelScreenCo, edge_verts_inset_clip[0], edge_verts_inset_clip[1], fac); }
+
+ if (!is_ortho) {
+ pixelScreenCo[3] = 1.0f;
+ Mat4MulVec4fl((float(*)[4])ps->projectMat, pixelScreenCo); /* cast because of const */
+ pixelScreenCo[0] = (float)(ps->ar->winx/2.0f)+(ps->ar->winx/2.0f)*pixelScreenCo[0]/pixelScreenCo[3];
+ pixelScreenCo[1] = (float)(ps->ar->winy/2.0f)+(ps->ar->winy/2.0f)*pixelScreenCo[1]/pixelScreenCo[3];
+ pixelScreenCo[2] = pixelScreenCo[2]/pixelScreenCo[3]; /* Use the depth for bucket point occlusion */
+ }
+
+ if (ps->do_occlude==0 || !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo)) {
+
+ /* Only bother calculating the weights if we intersect */
+ if (ps->do_mask_normal || ps->dm_mtface_clone) {
+ /* TODO, this is not QUITE correct since UV is not inside the UV's but good enough for seams */
+ if (side) {
+ BarycentricWeights2f(uv, tf_uv_pxoffset[0], tf_uv_pxoffset[2], tf_uv_pxoffset[3], w);
+ }
+ else {
+ BarycentricWeights2f(uv, tf_uv_pxoffset[0], tf_uv_pxoffset[1], tf_uv_pxoffset[2], w);
+ }
+
+ }
+
+ /* a pitty we need to get the worldspace pixel location here */
+ if(ps->rv3d->rflag & RV3D_CLIPPING) {
+ if (side) VecWeightf(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w);
+ else VecWeightf(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w);
+
+ Mat4MulVecfl(ps->ob->obmat, wco);
+ if(view3d_test_clipping(ps->rv3d, wco)) {
+ continue; /* Watch out that no code below this needs to run */
+ }
+ }
+
+ mask = project_paint_uvpixel_mask(ps, face_index, side, w);
+
+ if (mask > 0.0f) {
+ BLI_linklist_prepend_arena(
+ bucketPixelNodes,
+ project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, side, w),
+ arena
+ );
+ }
+
+ }
+ }
+ else if (has_x_isect) {
+ /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
+ break;
+ }
+ }
+
+#if 0 /* TODO - investigate why this dosnt work sometimes! it should! */
+ /* no intersection for this entire row, after some intersection above means we can quit now */
+ if (has_x_isect==0 && has_isect) {
+ break;
+ }
+#endif
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+#endif // PROJ_DEBUG_NOSEAMBLEED
+}
+
+
+/* takes floating point screenspace min/max and returns int min/max to be used as indicies for ps->bucketRect, ps->bucketFlags */
+static void project_paint_bucket_bounds(const ProjPaintState *ps, const float min[2], const float max[2], int bucketMin[2], int bucketMax[2])
+{
+ /* divide by bucketWidth & bucketHeight so the bounds are offset in bucket grid units */
+ bucketMin[0] = (int)(((float)(min[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 0.5f; /* these offsets of 0.5 and 1.5 seem odd but they are correct */
+ bucketMin[1] = (int)(((float)(min[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 0.5f;
+
+ bucketMax[0] = (int)(((float)(max[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 1.5f;
+ bucketMax[1] = (int)(((float)(max[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 1.5f;
+
+ /* incase the rect is outside the mesh 2d bounds */
+ CLAMP(bucketMin[0], 0, ps->buckets_x);
+ CLAMP(bucketMin[1], 0, ps->buckets_y);
+
+ CLAMP(bucketMax[0], 0, ps->buckets_x);
+ CLAMP(bucketMax[1], 0, ps->buckets_y);
+}
+
+/* set bucket_bounds to a screen space-aligned floating point bound-box */
+static void project_bucket_bounds(const ProjPaintState *ps, const int bucket_x, const int bucket_y, rctf *bucket_bounds)
+{
+ bucket_bounds->xmin = ps->screenMin[0]+((bucket_x)*(ps->screen_width / ps->buckets_x)); /* left */
+ bucket_bounds->xmax = ps->screenMin[0]+((bucket_x+1)*(ps->screen_width / ps->buckets_x)); /* right */
+
+ bucket_bounds->ymin = ps->screenMin[1]+((bucket_y)*(ps->screen_height / ps->buckets_y)); /* bottom */
+ bucket_bounds->ymax = ps->screenMin[1]+((bucket_y+1)*(ps->screen_height / ps->buckets_y)); /* top */
+}
+
+/* Fill this bucket with pixels from the faces that intersect it.
+ *
+ * have bucket_bounds as an argument so we don;t need to give bucket_x/y the rect function needs */
+static void project_bucket_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, rctf *bucket_bounds)
+{
+ LinkNode *node;
+ int face_index, image_index;
+ ImBuf *ibuf = NULL;
+ MTFace *tf;
+
+ Image *tpage_last = NULL;
+
+
+ if (ps->image_tot==1) {
+ /* Simple loop, no context switching */
+ ibuf = ps->projImages[0].ibuf;
+
+ for (node = ps->bucketFaces[bucket_index]; node; node= node->next) {
+ project_paint_face_init(ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, bucket_bounds, ibuf);
+ }
+ }
+ else {
+
+ /* More complicated loop, switch between images */
+ for (node = ps->bucketFaces[bucket_index]; node; node= node->next) {
+ face_index = GET_INT_FROM_POINTER(node->link);
+
+ /* Image context switching */
+ tf = ps->dm_mtface+face_index;
+ if (tpage_last != tf->tpage) {
+ tpage_last = tf->tpage;
+
+ image_index = -1; /* sanity check */
+
+ for (image_index=0; image_index < ps->image_tot; image_index++) {
+ if (ps->projImages[image_index].ima == tpage_last) {
+ ibuf = ps->projImages[image_index].ibuf;
+ break;
+ }
+ }
+ }
+ /* context switching done */
+
+ project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf);
+
+ }
+ }
+
+ ps->bucketFlags[bucket_index] |= PROJ_BUCKET_INIT;
+}
+
+
+/* We want to know if a bucket and a face overlap in screen-space
+ *
+ * Note, if this ever returns false positives its not that bad, since a face in the bounding area will have its pixels
+ * calculated when it might not be needed later, (at the moment at least)
+ * obviously it shouldn't have bugs though */
+
+static int project_bucket_face_isect(ProjPaintState *ps, float min[2], float max[2], int bucket_x, int bucket_y, int bucket_index, const MFace *mf)
+{
+ /* TODO - replace this with a tricker method that uses sideofline for all screenCoords's edges against the closest bucket corner */
+ rctf bucket_bounds;
+ float p1[2], p2[2], p3[2], p4[2];
+ float *v, *v1,*v2,*v3,*v4;
+ int fidx;
+
+ project_bucket_bounds(ps, bucket_x, bucket_y, &bucket_bounds);
+
+ /* Is one of the faces verts in the bucket bounds? */
+
+ fidx = mf->v4 ? 3:2;
+ do {
+ v = ps->screenCoords[ (*(&mf->v1 + fidx)) ];
+ if (BLI_in_rctf(&bucket_bounds, v[0], v[1])) {
+ return 1;
+ }
+ } while (fidx--);
+
+ v1 = ps->screenCoords[mf->v1];
+ v2 = ps->screenCoords[mf->v2];
+ v3 = ps->screenCoords[mf->v3];
+ if (mf->v4) {
+ v4 = ps->screenCoords[mf->v4];
+ }
+
+ p1[0] = bucket_bounds.xmin; p1[1] = bucket_bounds.ymin;
+ p2[0] = bucket_bounds.xmin; p2[1] = bucket_bounds.ymax;
+ p3[0] = bucket_bounds.xmax; p3[1] = bucket_bounds.ymax;
+ p4[0] = bucket_bounds.xmax; p4[1] = bucket_bounds.ymin;
+
+ if (mf->v4) {
+ if( IsectPQ2Df(p1, v1, v2, v3, v4) || IsectPQ2Df(p2, v1, v2, v3, v4) || IsectPQ2Df(p3, v1, v2, v3, v4) || IsectPQ2Df(p4, v1, v2, v3, v4) ||
+ /* we can avoid testing v3,v1 because another intersection MUST exist if this intersects */
+ (IsectLL2Df(p1, p2, v1, v2) || IsectLL2Df(p1, p2, v2, v3) || IsectLL2Df(p1, p2, v3, v4)) ||
+ (IsectLL2Df(p2, p3, v1, v2) || IsectLL2Df(p2, p3, v2, v3) || IsectLL2Df(p2, p3, v3, v4)) ||
+ (IsectLL2Df(p3, p4, v1, v2) || IsectLL2Df(p3, p4, v2, v3) || IsectLL2Df(p3, p4, v3, v4)) ||
+ (IsectLL2Df(p4, p1, v1, v2) || IsectLL2Df(p4, p1, v2, v3) || IsectLL2Df(p4, p1, v3, v4))
+ ) {
+ return 1;
+ }
+ }
+ else {
+ if( IsectPT2Df(p1, v1, v2, v3) || IsectPT2Df(p2, v1, v2, v3) || IsectPT2Df(p3, v1, v2, v3) || IsectPT2Df(p4, v1, v2, v3) ||
+ /* we can avoid testing v3,v1 because another intersection MUST exist if this intersects */
+ (IsectLL2Df(p1, p2, v1, v2) || IsectLL2Df(p1, p2, v2, v3)) ||
+ (IsectLL2Df(p2, p3, v1, v2) || IsectLL2Df(p2, p3, v2, v3)) ||
+ (IsectLL2Df(p3, p4, v1, v2) || IsectLL2Df(p3, p4, v2, v3)) ||
+ (IsectLL2Df(p4, p1, v1, v2) || IsectLL2Df(p4, p1, v2, v3))
+ ) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* Add faces to the bucket but dont initialize its pixels
+ * TODO - when painting occluded, sort the faces on their min-Z and only add faces that faces that are not occluded */
+static void project_paint_delayed_face_init(ProjPaintState *ps, const MFace *mf, const MTFace *tf, const int face_index)
+{
+ float min[2], max[2], *vCoSS;
+ int bucketMin[2], bucketMax[2]; /* for ps->bucketRect indexing */
+ int fidx, bucket_x, bucket_y, bucket_index;
+ int has_x_isect = -1, has_isect = 0; /* for early loop exit */
+ MemArena *arena = ps->arena_mt[0]; /* just use the first thread arena since threading has not started yet */
+
+ INIT_MINMAX2(min, max);
+
+ fidx = mf->v4 ? 3:2;
+ do {
+ vCoSS = ps->screenCoords[ *(&mf->v1 + fidx) ];
+ DO_MINMAX2(vCoSS, min, max);
+ } while (fidx--);
+
+ project_paint_bucket_bounds(ps, min, max, bucketMin, bucketMax);
+
+ for (bucket_y = bucketMin[1]; bucket_y < bucketMax[1]; bucket_y++) {
+ has_x_isect = 0;
+ for (bucket_x = bucketMin[0]; bucket_x < bucketMax[0]; bucket_x++) {
+
+ bucket_index = bucket_x + (bucket_y * ps->buckets_x);
+
+ if (project_bucket_face_isect(ps, min, max, bucket_x, bucket_y, bucket_index, mf)) {
+ BLI_linklist_prepend_arena(
+ &ps->bucketFaces[ bucket_index ],
+ SET_INT_IN_POINTER(face_index), /* cast to a pointer to shut up the compiler */
+ arena
+ );
+
+ has_x_isect = has_isect = 1;
+ }
+ else if (has_x_isect) {
+ /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
+ break;
+ }
+ }
+
+ /* no intersection for this entire row, after some intersection above means we can quit now */
+ if (has_x_isect==0 && has_isect) {
+ break;
+ }
+ }
+
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ if (ps->seam_bleed_px > 0.0f) {
+ if (!mf->v4) {
+ ps->faceSeamFlags[face_index] |= PROJ_FACE_NOSEAM4; /* so this wont show up as an untagged edge */
+ }
+ **ps->faceSeamUVs[face_index] = FLT_MAX; /* set as uninitialized */
+ }
+#endif
+}
+
+/* run once per stroke before projection painting */
+static void project_paint_begin(ProjPaintState *ps)
+{
+ /* Viewport vars */
+ float mat[3][3];
+
+ float no[3];
+
+ float (*projScreenCo)[4]; /* Note, we could have 4D vectors are only needed for */
+ float projMargin;
+ /* Image Vars - keep track of images we have used */
+ LinkNode *image_LinkList = NULL;
+ LinkNode *node;
+
+ ProjPaintImage *projIma;
+ Image *tpage_last = NULL;
+
+ /* Face vars */
+ MFace *mf;
+ MTFace *tf;
+
+ int a, i; /* generic looping vars */
+ int image_index = -1, face_index;
+
+ MemArena *arena; /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */
+
+ /* ---- end defines ---- */
+
+ /* paint onto the derived mesh */
+ ps->dm = mesh_get_derived_final(ps->scene, ps->ob, ps->v3d->customdata_mask);
+
+ if ( !CustomData_has_layer( &ps->dm->faceData, CD_MTFACE) ) {
+ ps->dm = NULL;
+ return;
+ }
+ ps->dm_mvert = ps->dm->getVertArray(ps->dm);
+ ps->dm_mface = ps->dm->getFaceArray(ps->dm);
+ ps->dm_mtface= ps->dm->getFaceDataArray(ps->dm, CD_MTFACE);
+
+ ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
+ ps->dm_totface = ps->dm->getNumFaces(ps->dm);
+
+ /* use clone mtface? */
+
+
+ /* Note, use the original mesh for getting the clone and mask layer index
+ * this avoids re-generating the derived mesh just to get the new index */
+ if (ps->do_layer_clone) {
+ //int layer_num = CustomData_get_clone_layer(&ps->dm->faceData, CD_MTFACE);
+ int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->fdata, CD_MTFACE);
+ if (layer_num != -1)
+ ps->dm_mtface_clone = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
+
+ if (ps->dm_mtface_clone==NULL || ps->dm_mtface_clone==ps->dm_mtface) {
+ ps->do_layer_clone = 0;
+ ps->dm_mtface_clone= NULL;
+ }
+ }
+
+ if (ps->do_layer_mask) {
+ //int layer_num = CustomData_get_mask_layer(&ps->dm->faceData, CD_MTFACE);
+ int layer_num = CustomData_get_mask_layer(&((Mesh *)ps->ob->data)->fdata, CD_MTFACE);
+ if (layer_num != -1)
+ ps->dm_mtface_mask = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
+
+ if (ps->dm_mtface_mask==NULL || ps->dm_mtface_mask==ps->dm_mtface) {
+ ps->do_layer_mask = 0;
+ ps->dm_mtface_mask = NULL;
+ }
+ }
+
+
+
+ ps->viewDir[0] = 0.0f;
+ ps->viewDir[1] = 0.0f;
+ ps->viewDir[2] = 1.0f;
+
+ view3d_get_object_project_mat(ps->rv3d, ps->ob, ps->projectMat, ps->viewMat);
+
+ /* viewDir - object relative */
+ Mat4Invert(ps->ob->imat, ps->ob->obmat);
+ Mat3CpyMat4(mat, ps->rv3d->viewinv);
+ Mat3MulVecfl(mat, ps->viewDir);
+ Mat3CpyMat4(mat, ps->ob->imat);
+ Mat3MulVecfl(mat, ps->viewDir);
+ Normalize(ps->viewDir);
+
+ /* viewPos - object relative */
+ VECCOPY(ps->viewPos, ps->rv3d->viewinv[3]);
+ Mat3CpyMat4(mat, ps->ob->imat);
+ Mat3MulVecfl(mat, ps->viewPos);
+ VecAddf(ps->viewPos, ps->viewPos, ps->ob->imat[3]);
+
+ { /* only use these for running 'get_view3d_viewplane' */
+ rctf viewplane;
+
+ ps->is_ortho = get_view3d_viewplane(ps->v3d, ps->rv3d, ps->ar->winx, ps->ar->winy, &viewplane, &ps->clipsta, &ps->clipend, NULL);
+
+ //printf("%f %f\n", ps->clipsta, ps->clipend);
+ if (ps->is_ortho) { /* only needed for ortho */
+ float fac = 2.0f / (ps->clipend - ps->clipsta);
+ ps->clipsta *= fac;
+ ps->clipend *= fac;
+ }
+ else {
+ /* TODO - can we even adjust for clip start/end? */
+ }
+
+ }
+
+ ps->is_airbrush = (ps->brush->flag & BRUSH_AIRBRUSH) ? 1 : 0;
+
+ ps->is_texbrush = (ps->brush->mtex[ps->brush->texact] && ps->brush->mtex[ps->brush->texact]->tex) ? 1 : 0;
+
+
+ /* calculate vert screen coords
+ * run this early so we can calculate the x/y resolution of our bucket rect */
+ INIT_MINMAX2(ps->screenMin, ps->screenMax);
+
+ ps->screenCoords = MEM_mallocN(sizeof(float) * ps->dm_totvert * 4, "ProjectPaint ScreenVerts");
+ projScreenCo = ps->screenCoords;
+
+ if (ps->is_ortho) {
+ for(a=0; a < ps->dm_totvert; a++, projScreenCo++) {
+ VECCOPY((*projScreenCo), ps->dm_mvert[a].co);
+ Mat4MulVecfl(ps->projectMat, (*projScreenCo));
+
+ /* screen space, not clamped */
+ (*projScreenCo)[0] = (float)(ps->ar->winx/2.0f)+(ps->ar->winx/2.0f)*(*projScreenCo)[0];
+ (*projScreenCo)[1] = (float)(ps->ar->winy/2.0f)+(ps->ar->winy/2.0f)*(*projScreenCo)[1];
+ DO_MINMAX2((*projScreenCo), ps->screenMin, ps->screenMax);
+ }
+ }
+ else {
+ for(a=0; a < ps->dm_totvert; a++, projScreenCo++) {
+ VECCOPY((*projScreenCo), ps->dm_mvert[a].co);
+ (*projScreenCo)[3] = 1.0f;
+
+ Mat4MulVec4fl(ps->projectMat, (*projScreenCo));
+
+
+ if ((*projScreenCo)[3] > ps->clipsta) {
+ /* screen space, not clamped */
+ (*projScreenCo)[0] = (float)(ps->ar->winx/2.0f)+(ps->ar->winx/2.0f)*(*projScreenCo)[0]/(*projScreenCo)[3];
+ (*projScreenCo)[1] = (float)(ps->ar->winy/2.0f)+(ps->ar->winy/2.0f)*(*projScreenCo)[1]/(*projScreenCo)[3];
+ (*projScreenCo)[2] = (*projScreenCo)[2]/(*projScreenCo)[3]; /* Use the depth for bucket point occlusion */
+ DO_MINMAX2((*projScreenCo), ps->screenMin, ps->screenMax);
+ }
+ else {
+ /* TODO - deal with cases where 1 side of a face goes behind the view ?
+ *
+ * After some research this is actually very tricky, only option is to
+ * clip the derived mesh before painting, which is a Pain */
+ (*projScreenCo)[0] = FLT_MAX;
+ }
+ }
+ }
+
+ /* If this border is not added we get artifacts for faces that
+ * have a parallel edge and at the bounds of the the 2D projected verts eg
+ * - a single screen aligned quad */
+ projMargin = (ps->screenMax[0] - ps->screenMin[0]) * 0.000001f;
+ ps->screenMax[0] += projMargin;
+ ps->screenMin[0] -= projMargin;
+ projMargin = (ps->screenMax[1] - ps->screenMin[1]) * 0.000001f;
+ ps->screenMax[1] += projMargin;
+ ps->screenMin[1] -= projMargin;
+
+#ifdef PROJ_DEBUG_WINCLIP
+ CLAMP(ps->screenMin[0], -ps->brush->size, ps->ar->winx + ps->brush->size);
+ CLAMP(ps->screenMax[0], -ps->brush->size, ps->ar->winx + ps->brush->size);
+
+ CLAMP(ps->screenMin[1], -ps->brush->size, ps->ar->winy + ps->brush->size);
+ CLAMP(ps->screenMax[1], -ps->brush->size, ps->ar->winy + ps->brush->size);
+#endif
+
+ /* only for convenience */
+ ps->screen_width = ps->screenMax[0] - ps->screenMin[0];
+ ps->screen_height = ps->screenMax[1] - ps->screenMin[1];
+
+ ps->buckets_x = (int)(ps->screen_width / (((float)ps->brush->size) / PROJ_BUCKET_BRUSH_DIV));
+ ps->buckets_y = (int)(ps->screen_height / (((float)ps->brush->size) / PROJ_BUCKET_BRUSH_DIV));
+
+ printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y);
+
+ /* really high values could cause problems since it has to allocate a few
+ * (ps->buckets_x*ps->buckets_y) sized arrays */
+ CLAMP(ps->buckets_x, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
+ CLAMP(ps->buckets_y, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
+
+ ps->bucketRect = (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketRect");
+ ps->bucketFaces= (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
+
+ ps->bucketFlags= (unsigned char *)MEM_callocN(sizeof(char) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ if (ps->seam_bleed_px > 0.0f) {
+ ps->vertFaces= (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->dm_totvert, "paint-vertFaces");
+ ps->faceSeamFlags = (char *)MEM_callocN(sizeof(char) * ps->dm_totface, "paint-faceSeamFlags");
+ ps->faceSeamUVs= MEM_mallocN(sizeof(float) * ps->dm_totface * 8, "paint-faceSeamUVs");
+ }
+#endif
+
+ /* Thread stuff
+ *
+ * very small brushes run a lot slower multithreaded since the advantage with
+ * threads is being able to fill in multiple buckets at once.
+ * Only use threads for bigger brushes. */
+
+ if (ps->scene->r.mode & R_FIXED_THREADS) {
+ ps->thread_tot = ps->scene->r.threads;
+ }
+ else {
+ ps->thread_tot = BLI_system_thread_count();
+ }
+ for (a=0; a<ps->thread_tot; a++) {
+ ps->arena_mt[a] = BLI_memarena_new(1<<16);
+ }
+
+ arena = ps->arena_mt[0];
+
+ if (ps->do_backfacecull && ps->do_mask_normal) {
+ MVert *v = ps->dm_mvert;
+ float viewDirPersp[3];
+
+ ps->vertFlags = MEM_callocN(sizeof(char) * ps->dm_totvert, "paint-vertFlags");
+
+ for(a=0; a < ps->dm_totvert; a++, v++) {
+ no[0] = (float)(v->no[0] / 32767.0f);
+ no[1] = (float)(v->no[1] / 32767.0f);
+ no[2] = (float)(v->no[2] / 32767.0f);
+
+ if (ps->is_ortho) {
+ if (NormalizedVecAngle2(ps->viewDir, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */
+ ps->vertFlags[a] |= PROJ_VERT_CULL;
+ }
+ }
+ else {
+ VecSubf(viewDirPersp, ps->viewPos, v->co);
+ Normalize(viewDirPersp);
+ if (NormalizedVecAngle2(viewDirPersp, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */
+ ps->vertFlags[a] |= PROJ_VERT_CULL;
+ }
+ }
+ }
+ }
+
+
+ for(face_index = 0, tf = ps->dm_mtface, mf = ps->dm_mface; face_index < ps->dm_totface; mf++, tf++, face_index++) {
+
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ /* add face user if we have bleed enabled, set the UV seam flags later */
+ /* annoying but we need to add all faces even ones we never use elsewhere */
+ if (ps->seam_bleed_px > 0.0f) {
+ BLI_linklist_prepend_arena(&ps->vertFaces[mf->v1], SET_INT_IN_POINTER(face_index), arena);
+ BLI_linklist_prepend_arena(&ps->vertFaces[mf->v2], SET_INT_IN_POINTER(face_index), arena);
+ BLI_linklist_prepend_arena(&ps->vertFaces[mf->v3], SET_INT_IN_POINTER(face_index), arena);
+ if (mf->v4) {
+ BLI_linklist_prepend_arena(&ps->vertFaces[ mf->v4 ], SET_INT_IN_POINTER(face_index), arena);
+ }
+ }
+#endif
+
+ if (tf->tpage && ((G.f & G_FACESELECT)==0 || mf->flag & ME_FACE_SEL)) {
+
+ float *v1coSS, *v2coSS, *v3coSS, *v4coSS;
+
+ v1coSS = ps->screenCoords[mf->v1];
+ v2coSS = ps->screenCoords[mf->v2];
+ v3coSS = ps->screenCoords[mf->v3];
+ if (mf->v4) {
+ v4coSS = ps->screenCoords[mf->v4];
+ }
+
+
+ if (!ps->is_ortho) {
+ if ( v1coSS[0]==FLT_MAX ||
+ v2coSS[0]==FLT_MAX ||
+ v3coSS[0]==FLT_MAX ||
+ (mf->v4 && v4coSS[0]==FLT_MAX)
+ ) {
+ continue;
+ }
+ }
+
+#ifdef PROJ_DEBUG_WINCLIP
+ /* ignore faces outside the view */
+ if (
+ (v1coSS[0] < ps->screenMin[0] &&
+ v2coSS[0] < ps->screenMin[0] &&
+ v3coSS[0] < ps->screenMin[0] &&
+ (mf->v4 && v4coSS[0] < ps->screenMin[0])) ||
+
+ (v1coSS[0] > ps->screenMax[0] &&
+ v2coSS[0] > ps->screenMax[0] &&
+ v3coSS[0] > ps->screenMax[0] &&
+ (mf->v4 && v4coSS[0] > ps->screenMax[0])) ||
+
+ (v1coSS[1] < ps->screenMin[1] &&
+ v2coSS[1] < ps->screenMin[1] &&
+ v3coSS[1] < ps->screenMin[1] &&
+ (mf->v4 && v4coSS[1] < ps->screenMin[1])) ||
+
+ (v1coSS[1] > ps->screenMax[1] &&
+ v2coSS[1] > ps->screenMax[1] &&
+ v3coSS[1] > ps->screenMax[1] &&
+ (mf->v4 && v4coSS[1] > ps->screenMax[1]))
+ ) {
+ continue;
+ }
+
+#endif //PROJ_DEBUG_WINCLIP
+
+
+ if (ps->do_backfacecull) {
+ if (ps->do_mask_normal) {
+ /* Since we are interpolating the normals of faces, we want to make
+ * sure all the verts are pointing away from the view,
+ * not just the face */
+ if ( (ps->vertFlags[mf->v1] & PROJ_VERT_CULL) &&
+ (ps->vertFlags[mf->v2] & PROJ_VERT_CULL) &&
+ (ps->vertFlags[mf->v3] & PROJ_VERT_CULL) &&
+ (mf->v4==0 || ps->vertFlags[mf->v4] & PROJ_VERT_CULL)
+
+ ) {
+ continue;
+ }
+ }
+ else {
+ if (SIDE_OF_LINE(v1coSS, v2coSS, v3coSS) < 0.0f) {
+ continue;
+ }
+
+ }
+ }
+
+ if (tpage_last != tf->tpage) {
+
+ image_index = BLI_linklist_index(image_LinkList, tf->tpage);
+
+ if (image_index==-1 && BKE_image_get_ibuf((Image *)tf->tpage, NULL)) { /* MemArena dosnt have an append func */
+ BLI_linklist_append(&image_LinkList, tf->tpage);
+ image_index = ps->image_tot;
+ ps->image_tot++;
+ }
+
+ tpage_last = tf->tpage;
+ }
+
+ if (image_index != -1) {
+ /* Initialize the faces screen pixels */
+ /* Add this to a list to initialize later */
+ project_paint_delayed_face_init(ps, mf, tf, face_index);
+ }
+ }
+ }
+
+ /* build an array of images we use*/
+ projIma = ps->projImages = (ProjPaintImage *)BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot);
+
+ for (node= image_LinkList, i=0; node; node= node->next, i++, projIma++) {
+ projIma->ima = node->link;
+ // calloced - projIma->touch = 0;
+ projIma->ibuf = BKE_image_get_ibuf(projIma->ima, NULL);
+ projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ // calloced - memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ }
+
+ /* we have built the array, discard the linked list */
+ BLI_linklist_free(image_LinkList, NULL);
+}
+
+static void project_paint_begin_clone(ProjPaintState *ps, int mouse[2])
+{
+ /* setup clone offset */
+ if (ps->tool == PAINT_TOOL_CLONE) {
+ float projCo[4];
+ float *curs= give_cursor(ps->scene, ps->v3d);
+ VECCOPY(projCo, curs);
+ Mat4MulVecfl(ps->ob->imat, projCo);
+
+ projCo[3] = 1.0f;
+ Mat4MulVec4fl(ps->projectMat, projCo);
+ ps->cloneOffset[0] = mouse[0] - ((float)(ps->ar->winx/2.0f)+(ps->ar->winx/2.0f)*projCo[0]/projCo[3]);
+ ps->cloneOffset[1] = mouse[1] - ((float)(ps->ar->winy/2.0f)+(ps->ar->winy/2.0f)*projCo[1]/projCo[3]);
+ }
+}
+
+static void project_paint_end(ProjPaintState *ps)
+{
+ int a;
+
+ /* build undo data from original pixel colors */
+ if(U.uiflag & USER_GLOBALUNDO) {
+ ProjPixel *projPixel;
+ ImBuf *tmpibuf = NULL, *tmpibuf_float = NULL;
+ LinkNode *pixel_node;
+ UndoTile *tile;
+ MemArena *arena = ps->arena_mt[0]; /* threaded arena re-used for non threaded case */
+
+ int bucket_tot = (ps->buckets_x * ps->buckets_y); /* we could get an X/Y but easier to loop through all possible buckets */
+ int bucket_index;
+ int tile_index;
+ int x_round, y_round;
+ int x_tile, y_tile;
+ int is_float = -1;
+
+ /* context */
+ ProjPaintImage *last_projIma;
+ int last_image_index = -1;
+ int last_tile_width;
+
+ for(a=0, last_projIma=ps->projImages; a < ps->image_tot; a++, last_projIma++) {
+ int size = sizeof(UndoTile **) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->y);
+ last_projIma->undoRect = (UndoTile **) BLI_memarena_alloc(arena, size);
+ memset(last_projIma->undoRect, 0, size);
+ }
+
+ for (bucket_index = 0; bucket_index < bucket_tot; bucket_index++) {
+ /* loop through all pixels */
+ for(pixel_node= ps->bucketRect[bucket_index]; pixel_node; pixel_node= pixel_node->next) {
+
+ /* ok we have a pixel, was it modified? */
+ projPixel = (ProjPixel *)pixel_node->link;
+
+ if (last_image_index != projPixel->image_index) {
+ /* set the context */
+ last_image_index = projPixel->image_index;
+ last_projIma = ps->projImages + last_image_index;
+ last_tile_width = IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x);
+ is_float = last_projIma->ibuf->rect_float ? 1 : 0;
+ }
+
+
+ if ( (is_float == 0 && projPixel->origColor.uint != *projPixel->pixel.uint_pt) ||
+
+ (is_float == 1 &&
+ ( projPixel->origColor.f[0] != projPixel->pixel.f_pt[0] ||
+ projPixel->origColor.f[1] != projPixel->pixel.f_pt[1] ||
+ projPixel->origColor.f[2] != projPixel->pixel.f_pt[2] ||
+ projPixel->origColor.f[3] != projPixel->pixel.f_pt[3] ))
+ ) {
+
+ x_tile = projPixel->x_px >> IMAPAINT_TILE_BITS;
+ y_tile = projPixel->y_px >> IMAPAINT_TILE_BITS;
+
+ x_round = x_tile * IMAPAINT_TILE_SIZE;
+ y_round = y_tile * IMAPAINT_TILE_SIZE;
+
+ tile_index = x_tile + y_tile * last_tile_width;
+
+ if (last_projIma->undoRect[tile_index]==NULL) {
+ /* add the undo tile from the modified image, then write the original colors back into it */
+ tile = last_projIma->undoRect[tile_index] = undo_init_tile(&last_projIma->ima->id, last_projIma->ibuf, is_float ? (&tmpibuf_float):(&tmpibuf) , x_tile, y_tile);
+ }
+ else {
+ tile = last_projIma->undoRect[tile_index];
+ }
+
+ /* This is a BIT ODD, but overwrite the undo tiles image info with this pixels original color
+ * because allocating the tiles allong the way slows down painting */
+
+ if (is_float) {
+ float *rgba_fp = (float *)tile->rect + (((projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE)) * 4;
+ QUATCOPY(rgba_fp, projPixel->origColor.f);
+ }
+ else {
+ ((unsigned int *)tile->rect)[ (projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE ] = projPixel->origColor.uint;
+ }
+ }
+ }
+ }
+
+ if (tmpibuf) IMB_freeImBuf(tmpibuf);
+ if (tmpibuf_float) IMB_freeImBuf(tmpibuf_float);
+ }
+ /* done calculating undo data */
+
+ MEM_freeN(ps->screenCoords);
+ MEM_freeN(ps->bucketRect);
+ MEM_freeN(ps->bucketFaces);
+ MEM_freeN(ps->bucketFlags);
+
+ if (ps->seam_bleed_px > 0.0f) {
+ MEM_freeN(ps->vertFaces);
+ MEM_freeN(ps->faceSeamFlags);
+ MEM_freeN(ps->faceSeamUVs);
+ }
+
+ if (ps->vertFlags) MEM_freeN(ps->vertFlags);
+
+
+ for (a=0; a<ps->thread_tot; a++) {
+ BLI_memarena_free(ps->arena_mt[a]);
+ }
+
+ ps->dm->release(ps->dm);
+}
+
+/* 1= an undo, -1 is a redo. */
+static void partial_redraw_array_init(ImagePaintPartialRedraw *pr)
+{
+ int tot = PROJ_BOUNDBOX_SQUARED;
+ while (tot--) {
+ pr->x1 = 10000000;
+ pr->y1 = 10000000;
+
+ pr->x2 = -1;
+ pr->y2 = -1;
+
+ pr->enabled = 1;
+
+ pr++;
+ }
+}
+
+
+static int partial_redraw_array_merge(ImagePaintPartialRedraw *pr, ImagePaintPartialRedraw *pr_other, int tot)
+{
+ int touch;
+ while (tot--) {
+ pr->x1 = MIN2(pr->x1, pr_other->x1);
+ pr->y1 = MIN2(pr->y1, pr_other->y1);
+
+ pr->x2 = MAX2(pr->x2, pr_other->x2);
+ pr->y2 = MAX2(pr->y2, pr_other->y2);
+
+ if (pr->x2 != -1)
+ touch = 1;
+
+ pr++; pr_other++;
+ }
+
+ return touch;
+}
+
+/* Loop over all images on this mesh and update any we have touched */
+static int project_image_refresh_tagged(ProjPaintState *ps)
+{
+ ImagePaintPartialRedraw *pr;
+ ProjPaintImage *projIma;
+ int a,i;
+ int redraw = 0;
+
+
+ for (a=0, projIma=ps->projImages; a < ps->image_tot; a++, projIma++) {
+ if (projIma->touch) {
+ /* look over each bound cell */
+ for (i=0; i<PROJ_BOUNDBOX_SQUARED; i++) {
+ pr = &(projIma->partRedrawRect[i]);
+ if (pr->x2 != -1) { /* TODO - use 'enabled' ? */
+ imapaintpartial = *pr;
+ imapaint_image_update(NULL, projIma->ima, projIma->ibuf, 1); /*last 1 is for texpaint*/
+ redraw = 1;
+ }
+ }
+
+ projIma->touch = 0; /* clear for reuse */
+ }
+ }
+
+ return redraw;
+}
+
+/* run this per painting onto each mouse location */
+static int project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2])
+{
+ float min_brush[2], max_brush[2];
+ float size_half = ((float)ps->brush->size) * 0.5f;
+
+ /* so we dont have a bucket bounds that is way too small to paint into */
+ // if (size_half < 1.0f) size_half = 1.0f; // this dosnt work yet :/
+
+ min_brush[0] = mval_f[0] - size_half;
+ min_brush[1] = mval_f[1] - size_half;
+
+ max_brush[0] = mval_f[0] + size_half;
+ max_brush[1] = mval_f[1] + size_half;
+
+ /* offset to make this a valid bucket index */
+ project_paint_bucket_bounds(ps, min_brush, max_brush, ps->bucketMin, ps->bucketMax);
+
+ /* mouse outside the model areas? */
+ if (ps->bucketMin[0]==ps->bucketMax[0] || ps->bucketMin[1]==ps->bucketMax[1]) {
+ return 0;
+ }
+
+ ps->context_bucket_x = ps->bucketMin[0];
+ ps->context_bucket_y = ps->bucketMin[1];
+ return 1;
+}
+
+static int project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf *bucket_bounds, const float mval[2])
+{
+ if (ps->thread_tot > 1)
+ BLI_lock_thread(LOCK_CUSTOM1);
+
+ //printf("%d %d \n", ps->context_bucket_x, ps->context_bucket_y);
+
+ for ( ; ps->context_bucket_y < ps->bucketMax[1]; ps->context_bucket_y++) {
+ for ( ; ps->context_bucket_x < ps->bucketMax[0]; ps->context_bucket_x++) {
+
+ /* use bucket_bounds for project_bucket_isect_circle and project_bucket_init*/
+ project_bucket_bounds(ps, ps->context_bucket_x, ps->context_bucket_y, bucket_bounds);
+
+ if (project_bucket_isect_circle(ps->context_bucket_x, ps->context_bucket_y, mval, ps->brush->size * ps->brush->size, bucket_bounds)) {
+ *bucket_index = ps->context_bucket_x + (ps->context_bucket_y * ps->buckets_x);
+ ps->context_bucket_x++;
+
+ if (ps->thread_tot > 1)
+ BLI_unlock_thread(LOCK_CUSTOM1);
+
+ return 1;
+ }
+ }
+ ps->context_bucket_x = ps->bucketMin[0];
+ }
+
+ if (ps->thread_tot > 1)
+ BLI_unlock_thread(LOCK_CUSTOM1);
+ return 0;
+}
+
+/* Each thread gets one of these, also used as an argument to pass to project_paint_op */
+typedef struct ProjectHandle {
+ /* args */
+ ProjPaintState *ps;
+ float prevmval[2];
+ float mval[2];
+
+ /* annoying but we need to have image bounds per thread, then merge into ps->projectPartialRedraws */
+ ProjPaintImage *projImages; /* array of partial redraws */
+
+ /* thread settings */
+ int thread_index;
+} ProjectHandle;
+
+static void blend_color_mix(unsigned char *cp, const unsigned char *cp1, const unsigned char *cp2, const int fac)
+{
+ /* this and other blending modes previously used >>8 instead of /255. both
+ are not equivalent (>>8 is /256), and the former results in rounding
+ errors that can turn colors black fast after repeated blending */
+ const int mfac= 255-fac;
+
+ cp[0]= (mfac*cp1[0]+fac*cp2[0])/255;
+ cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
+ cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
+}
+
+static void blend_color_mix_float(float *cp, const float *cp1, const float *cp2, const float fac)
+{
+ const float mfac= 1.0-fac;
+ cp[0]= mfac*cp1[0] + fac*cp2[0];
+ cp[1]= mfac*cp1[1] + fac*cp2[1];
+ cp[2]= mfac*cp1[2] + fac*cp2[2];
+}
+
+static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask)
+{
+ if (ps->is_airbrush==0 && mask < 1.0f) {
+ projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, ((ProjPixelClone*)projPixel)->clonepx.uint, (int)(alpha*255), ps->blend);
+ blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask*255));
+ }
+ else {
+ *projPixel->pixel.uint_pt = IMB_blend_color(*projPixel->pixel.uint_pt, ((ProjPixelClone*)projPixel)->clonepx.uint, (int)(alpha*mask*255), ps->blend);
+ }
+}
+
+static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask)
+{
+ if (ps->is_airbrush==0 && mask < 1.0f) {
+ IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, ((ProjPixelClone *)projPixel)->clonepx.f, alpha, ps->blend);
+ blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, projPixel->newColor.f, mask);
+ }
+ else {
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.f, alpha*mask, ps->blend);
+ }
+}
+
+/* do_projectpaint_smear*
+ *
+ * note, mask is used to modify the alpha here, this is not correct since it allows
+ * accumulation of color greater then 'projPixel->mask' however in the case of smear its not
+ * really that important to be correct as it is with clone and painting
+ */
+static void do_projectpaint_smear(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask, MemArena *smearArena, LinkNode **smearPixels, float co[2])
+{
+ unsigned char rgba_ub[4];
+
+ if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1)==0)
+ return;
+
+ ((ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend);
+ BLI_linklist_prepend_arena(smearPixels, (void *)projPixel, smearArena);
+}
+
+static void do_projectpaint_smear_f(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask, MemArena *smearArena, LinkNode **smearPixels_f, float co[2])
+{
+ unsigned char rgba_ub[4];
+ unsigned char rgba_smear[4];
+
+ if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1)==0)
+ return;
+
+ IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba_smear, projPixel->pixel.f_pt);
+ ((ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*((unsigned int *)rgba_smear), *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend);
+ BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena);
+}
+
+static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask)
+{
+ unsigned char rgba_ub[4];
+
+ if (ps->is_texbrush) {
+ rgba_ub[0] = FTOCHAR(rgba[0] * ps->brush->rgb[0]);
+ rgba_ub[1] = FTOCHAR(rgba[1] * ps->brush->rgb[1]);
+ rgba_ub[2] = FTOCHAR(rgba[2] * ps->brush->rgb[2]);
+ rgba_ub[3] = FTOCHAR(rgba[3]);
+ }
+ else {
+ IMAPAINT_FLOAT_RGB_TO_CHAR(rgba_ub, ps->brush->rgb);
+ rgba_ub[3] = 255;
+ }
+
+ if (ps->is_airbrush==0 && mask < 1.0f) {
+ projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, *((unsigned int *)rgba_ub), (int)(alpha*255), ps->blend);
+ blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask*255));
+ }
+ else {
+ *projPixel->pixel.uint_pt = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend);
+ }
+}
+
+static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask) {
+ if (ps->is_texbrush) {
+ rgba[0] *= ps->brush->rgb[0];
+ rgba[1] *= ps->brush->rgb[1];
+ rgba[2] *= ps->brush->rgb[2];
+ }
+ else {
+ VECCOPY(rgba, ps->brush->rgb);
+ }
+
+ if (ps->is_airbrush==0 && mask < 1.0f) {
+ IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, rgba, alpha, ps->blend);
+ blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, projPixel->newColor.f, mask);
+ }
+ else {
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, alpha*mask, ps->blend);
+ }
+}
+
+
+
+/* run this for single and multithreaded painting */
+static void *do_projectpaint_thread(void *ph_v)
+{
+ /* First unpack args from the struct */
+ ProjPaintState *ps = ((ProjectHandle *)ph_v)->ps;
+ ProjPaintImage *projImages = ((ProjectHandle *)ph_v)->projImages;
+ const float *lastpos = ((ProjectHandle *)ph_v)->prevmval;
+ const float *pos = ((ProjectHandle *)ph_v)->mval;
+ const int thread_index = ((ProjectHandle *)ph_v)->thread_index;
+ /* Done with args from ProjectHandle */
+
+ LinkNode *node;
+ ProjPixel *projPixel;
+
+ int last_index = -1;
+ ProjPaintImage *last_projIma;
+ ImagePaintPartialRedraw *last_partial_redraw_cell;
+
+ float rgba[4], alpha, dist_nosqrt;
+
+ float brush_size_sqared;
+ float falloff;
+ int bucket_index;
+ int is_floatbuf = 0;
+ const short tool = ps->tool;
+ rctf bucket_bounds;
+
+ /* for smear only */
+ float pos_ofs[2];
+ float co[2];
+ float mask = 1.0f; /* airbrush wont use mask */
+ unsigned short mask_short;
+
+ LinkNode *smearPixels = NULL;
+ LinkNode *smearPixels_f = NULL;
+ MemArena *smearArena = NULL; /* mem arena for this brush projection only */
+
+
+ if (tool==PAINT_TOOL_SMEAR) {
+ pos_ofs[0] = pos[0] - lastpos[0];
+ pos_ofs[1] = pos[1] - lastpos[1];
+
+ smearArena = BLI_memarena_new(1<<16);
+ }
+
+ /* avoid a square root with every dist comparison */
+ brush_size_sqared = ps->brush->size * ps->brush->size;
+
+ /* printf("brush bounds %d %d %d %d\n", bucketMin[0], bucketMin[1], bucketMax[0], bucketMax[1]); */
+
+ while (project_bucket_iter_next(ps, &bucket_index, &bucket_bounds, pos)) {
+
+ /* Check this bucket and its faces are initialized */
+ if (ps->bucketFlags[bucket_index] == PROJ_BUCKET_NULL) {
+ /* No pixels initialized */
+ project_bucket_init(ps, thread_index, bucket_index, &bucket_bounds);
+ }
+
+ for (node = ps->bucketRect[bucket_index]; node; node = node->next) {
+
+ projPixel = (ProjPixel *)node->link;
+
+ /*dist = Vec2Lenf(projPixel->projCoSS, pos);*/ /* correct but uses a sqrt */
+ dist_nosqrt = Vec2Lenf_nosqrt(projPixel->projCoSS, pos);
+
+ /*if (dist < s->brush->size) {*/ /* correct but uses a sqrt */
+ if (dist_nosqrt < brush_size_sqared) {
+ falloff = brush_sample_falloff_noalpha(ps->brush, sqrt(dist_nosqrt));
+ if (falloff > 0.0f) {
+ if (ps->is_texbrush) {
+ brush_sample_tex(ps->brush, projPixel->projCoSS, rgba);
+ alpha = rgba[3];
+ } else {
+ alpha = 1.0f;
+ }
+
+ if (ps->is_airbrush) {
+ /* for an aurbrush there is no real mask, so just multiply the alpha by it */
+ alpha *= falloff * ps->brush->alpha;
+ mask = ((float)projPixel->mask)/65535.0f;
+ }
+ else {
+ /* This brush dosnt accumulate so add some curve to the brushes falloff */
+ falloff = 1.0f - falloff;
+ falloff = 1.0f - (falloff * falloff);
+
+ mask_short = projPixel->mask * (ps->brush->alpha * falloff);
+ if (mask_short > projPixel->mask_max) {
+ mask = ((float)mask_short)/65535.0f;
+ projPixel->mask_max = mask_short;
+ }
+ else {
+ /*mask = ((float)projPixel->mask_max)/65535.0f;*/
+
+ /* Go onto the next pixel */
+ continue;
+ }
+ }
+
+ if (alpha > 0.0f) {
+
+ if (last_index != projPixel->image_index) {
+ last_index = projPixel->image_index;
+ last_projIma = projImages + last_index;
+
+ last_projIma->touch = 1;
+ is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0;
+ }
+
+ last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index;
+ last_partial_redraw_cell->x1 = MIN2(last_partial_redraw_cell->x1, projPixel->x_px);
+ last_partial_redraw_cell->y1 = MIN2(last_partial_redraw_cell->y1, projPixel->y_px);
+
+ last_partial_redraw_cell->x2 = MAX2(last_partial_redraw_cell->x2, projPixel->x_px+1);
+ last_partial_redraw_cell->y2 = MAX2(last_partial_redraw_cell->y2, projPixel->y_px+1);
+
+
+ switch(tool) {
+ case PAINT_TOOL_CLONE:
+ if (is_floatbuf) {
+ if (((ProjPixelClone *)projPixel)->clonepx.f[3]) {
+ do_projectpaint_clone_f(ps, projPixel, rgba, alpha, mask);
+ }
+ }
+ else {
+ if (((ProjPixelClone*)projPixel)->clonepx.ch[3]) {
+ do_projectpaint_clone(ps, projPixel, rgba, alpha, mask);
+ }
+ }
+ break;
+ case PAINT_TOOL_SMEAR:
+ Vec2Subf(co, projPixel->projCoSS, pos_ofs);
+
+ if (is_floatbuf) do_projectpaint_smear_f(ps, projPixel, rgba, alpha, mask, smearArena, &smearPixels_f, co);
+ else do_projectpaint_smear(ps, projPixel, rgba, alpha, mask, smearArena, &smearPixels, co);
+ break;
+ default:
+ if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, rgba, alpha, mask);
+ else do_projectpaint_draw(ps, projPixel, rgba, alpha, mask);
+ break;
+ }
+ }
+ /* done painting */
+ }
+ }
+ }
+ }
+
+
+ if (tool==PAINT_TOOL_SMEAR) {
+
+ for (node= smearPixels; node; node= node->next) { /* this wont run for a float image */
+ projPixel = node->link;
+ *projPixel->pixel.uint_pt = ((ProjPixelClone *)projPixel)->clonepx.uint;
+ }
+
+ for (node= smearPixels_f; node; node= node->next) { /* this wont run for a float image */
+ projPixel = node->link;
+ IMAPAINT_CHAR_RGBA_TO_FLOAT(projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.ch);
+ node = node->next;
+ }
+
+ BLI_memarena_free(smearArena);
+ }
+
+ return NULL;
+}
+
+static int project_paint_op(void *state, ImBuf *ibufb, float *lastpos, float *pos)
+{
+ /* First unpack args from the struct */
+ ProjPaintState *ps = (ProjPaintState *)state;
+ int touch_any = 0;
+
+ ProjectHandle handles[BLENDER_MAX_THREADS];
+ ListBase threads;
+ int a,i;
+
+ if (!project_bucket_iter_init(ps, pos)) {
+ return 0;
+ }
+
+ if (ps->thread_tot > 1)
+ BLI_init_threads(&threads, do_projectpaint_thread, ps->thread_tot);
+
+ /* get the threads running */
+ for(a=0; a < ps->thread_tot; a++) {
+
+ /* set defaults in handles */
+ //memset(&handles[a], 0, sizeof(BakeShade));
+
+ handles[a].ps = ps;
+ VECCOPY2D(handles[a].mval, pos);
+ VECCOPY2D(handles[a].prevmval, lastpos);
+
+ /* thread spesific */
+ handles[a].thread_index = a;
+
+ handles[a].projImages = (ProjPaintImage *)BLI_memarena_alloc(ps->arena_mt[a], ps->image_tot * sizeof(ProjPaintImage));
+
+ memcpy(handles[a].projImages, ps->projImages, ps->image_tot * sizeof(ProjPaintImage));
+
+ /* image bounds */
+ for (i=0; i< ps->image_tot; i++) {
+ handles[a].projImages[i].partRedrawRect = (ImagePaintPartialRedraw *)BLI_memarena_alloc(ps->arena_mt[a], sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ memcpy(handles[a].projImages[i].partRedrawRect, ps->projImages[i].partRedrawRect, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ }
+
+ if (ps->thread_tot > 1)
+ BLI_insert_thread(&threads, &handles[a]);
+ }
+
+ if (ps->thread_tot > 1) /* wait for everything to be done */
+ BLI_end_threads(&threads);
+ else
+ do_projectpaint_thread(&handles[0]);
+
+
+ /* move threaded bounds back into ps->projectPartialRedraws */
+ for(i=0; i < ps->image_tot; i++) {
+ int touch = 0;
+ for(a=0; a < ps->thread_tot; a++) {
+ touch |= partial_redraw_array_merge(ps->projImages[i].partRedrawRect, handles[a].projImages[i].partRedrawRect, PROJ_BOUNDBOX_SQUARED);
+ }
+
+ if (touch) {
+ ps->projImages[i].touch = 1;
+ touch_any = 1;
+ }
+ }
+
+ return touch_any;
+}
+
+
+static int project_paint_sub_stroke(ProjPaintState *ps, BrushPainter *painter, int *prevmval_i, int *mval_i, double time, float pressure)
+{
+
+ /* Use mouse coords as floats for projection painting */
+ float pos[2];
+
+ pos[0] = mval_i[0];
+ pos[1] = mval_i[1];
+
+ // we may want to use this later
+ // brush_painter_require_imbuf(painter, ((ibuf->rect_float)? 1: 0), 0, 0);
+
+ if (brush_painter_paint(painter, project_paint_op, pos, time, pressure, ps)) {
+ return 1;
+ }
+ else return 0;
+}
+
+
+static int project_paint_stroke(ProjPaintState *ps, BrushPainter *painter, int *prevmval_i, int *mval_i, double time, float pressure)
+{
+ int a, redraw;
+
+ for (a=0; a < ps->image_tot; a++)
+ partial_redraw_array_init(ps->projImages[a].partRedrawRect);
+
+ redraw= project_paint_sub_stroke(ps, painter, prevmval_i, mval_i, time, pressure);
+
+ if(project_image_refresh_tagged(ps))
+ return redraw;
+
+ return 0;
+}
+
+/* Imagepaint Partial Redraw & Dirty Region */
+
+static void imapaint_clear_partial_redraw()
+{
+ memset(&imapaintpartial, 0, sizeof(imapaintpartial));
+}
+
+static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h)
+{
+ ImBuf *tmpibuf = NULL;
+ UndoTile *tile;
+ int srcx= 0, srcy= 0, origx;
+
+ IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h);
+
+ if (w == 0 || h == 0)
+ return;
+
+ if (!imapaintpartial.enabled) {
+ imapaintpartial.x1 = x;
+ imapaintpartial.y1 = y;
+ imapaintpartial.x2 = x+w;
+ imapaintpartial.y2 = y+h;
+ imapaintpartial.enabled = 1;
+ }
+ else {
+ imapaintpartial.x1 = MIN2(imapaintpartial.x1, x);
+ imapaintpartial.y1 = MIN2(imapaintpartial.y1, y);
+ imapaintpartial.x2 = MAX2(imapaintpartial.x2, x+w);
+ imapaintpartial.y2 = MAX2(imapaintpartial.y2, y+h);
+ }
+
+ w = ((x + w - 1) >> IMAPAINT_TILE_BITS);
+ h = ((y + h - 1) >> IMAPAINT_TILE_BITS);
+ origx = (x >> IMAPAINT_TILE_BITS);
+ y = (y >> IMAPAINT_TILE_BITS);
+
+ for (; y <= h; y++) {
+ for (x=origx; x <= w; x++) {
+ for(tile=curundo->tiles.first; tile; tile=tile->next)
+ if(tile->x == x && tile->y == y && strcmp(tile->id.name, ima->id.name)==0)
+ break;
+
+ if(!tile) {
+ undo_init_tile(&ima->id, ibuf, &tmpibuf, x, y);
+ }
+ }
+ }
+
+ ibuf->userflags |= IB_BITMAPDIRTY;
+
+ if (tmpibuf)
+ IMB_freeImBuf(tmpibuf);
+}
+
+static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint)
+{
+ if(ibuf->rect_float)
+ /* TODO - should just update a portion from imapaintpartial! */
+ imb_freerectImBuf(ibuf); /* force recreate of char rect */
+ if(ibuf->mipmap[0])
+ imb_freemipmapImBuf(ibuf);
+
+ /* todo: should set_tpage create ->rect? */
+ if(texpaint || (sima && sima->lock)) {
+ int w = imapaintpartial.x2 - imapaintpartial.x1;
+ int h = imapaintpartial.y2 - imapaintpartial.y1;
+ GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h);
+ }
+}
+
+/* Image Paint Operations */
+
+static void imapaint_ibuf_get_set_rgb(ImBuf *ibuf, int x, int y, short torus, short set, float *rgb)
+{
+ if (torus) {
+ x %= ibuf->x;
+ if (x < 0) x += ibuf->x;
+ y %= ibuf->y;
+ if (y < 0) y += ibuf->y;
+ }
+
+ if (ibuf->rect_float) {
+ float *rrgbf = ibuf->rect_float + (ibuf->x*y + x)*4;
+
+ if (set) {
+ IMAPAINT_FLOAT_RGB_COPY(rrgbf, rgb);
+ } else {
+ IMAPAINT_FLOAT_RGB_COPY(rgb, rrgbf);
+ }
+ }
+ else {
+ char *rrgb = (char*)ibuf->rect + (ibuf->x*y + x)*4;
+
+ if (set) {
+ IMAPAINT_FLOAT_RGB_TO_CHAR(rrgb, rgb)
+ } else {
+ IMAPAINT_CHAR_RGB_TO_FLOAT(rgb, rrgb)
+ }
+ }
+}
+
+static int imapaint_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, float *outrgb, short torus)
+{
+ float inrgb[3];
+
+ if ((x >= ibuf->x) || (y >= ibuf->y)) {
+ if (torus) imapaint_ibuf_get_set_rgb(ibuf, x, y, 1, 0, inrgb);
+ else return 0;
+ }
+ else imapaint_ibuf_get_set_rgb(ibuf, x, y, 0, 0, inrgb);
+
+ outrgb[0] += inrgb[0];
+ outrgb[1] += inrgb[1];
+ outrgb[2] += inrgb[2];
+
+ return 1;
+}
+
+static void imapaint_lift_soften(ImBuf *ibuf, ImBuf *ibufb, int *pos, short torus)
+{
+ int x, y, count, xi, yi, xo, yo;
+ int out_off[2], in_off[2], dim[2];
+ float outrgb[3];
+
+ dim[0] = ibufb->x;
+ dim[1] = ibufb->y;
+ in_off[0] = pos[0];
+ in_off[1] = pos[1];
+ out_off[0] = out_off[1] = 0;
+
+ if (!torus) {
+ IMB_rectclip(ibuf, ibufb, &in_off[0], &in_off[1], &out_off[0],
+ &out_off[1], &dim[0], &dim[1]);
+
+ if ((dim[0] == 0) || (dim[1] == 0))
+ return;
+ }
+
+ for (y=0; y < dim[1]; y++) {
+ for (x=0; x < dim[0]; x++) {
+ /* get input pixel */
+ xi = in_off[0] + x;
+ yi = in_off[1] + y;
+
+ count = 1;
+ imapaint_ibuf_get_set_rgb(ibuf, xi, yi, torus, 0, outrgb);
+
+ count += imapaint_ibuf_add_if(ibuf, xi-1, yi-1, outrgb, torus);
+ count += imapaint_ibuf_add_if(ibuf, xi-1, yi , outrgb, torus);
+ count += imapaint_ibuf_add_if(ibuf, xi-1, yi+1, outrgb, torus);
+
+ count += imapaint_ibuf_add_if(ibuf, xi , yi-1, outrgb, torus);
+ count += imapaint_ibuf_add_if(ibuf, xi , yi+1, outrgb, torus);
+
+ count += imapaint_ibuf_add_if(ibuf, xi+1, yi-1, outrgb, torus);
+ count += imapaint_ibuf_add_if(ibuf, xi+1, yi , outrgb, torus);
+ count += imapaint_ibuf_add_if(ibuf, xi+1, yi+1, outrgb, torus);
+
+ outrgb[0] /= count;
+ outrgb[1] /= count;
+ outrgb[2] /= count;
+
+ /* write into brush buffer */
+ xo = out_off[0] + x;
+ yo = out_off[1] + y;
+ imapaint_ibuf_get_set_rgb(ibufb, xo, yo, 0, 1, outrgb);
+ }
+ }
+}
+
+static void imapaint_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos)
+{
+ IMB_rectblend_torus(ibufb, ibuf, 0, 0, pos[0], pos[1],
+ ibufb->x, ibufb->y, IMB_BLEND_COPY_RGB);
+}
+
+static ImBuf *imapaint_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos)
+{
+ /* note: allocImbuf returns zero'd memory, so regions outside image will
+ have zero alpha, and hence not be blended onto the image */
+ int w=ibufb->x, h=ibufb->y, destx=0, desty=0, srcx=pos[0], srcy=pos[1];
+ ImBuf *clonebuf= IMB_allocImBuf(w, h, ibufb->depth, ibufb->flags, 0);
+
+ IMB_rectclip(clonebuf, ibuf, &destx, &desty, &srcx, &srcy, &w, &h);
+ IMB_rectblend(clonebuf, ibuf, destx, desty, srcx, srcy, w, h,
+ IMB_BLEND_COPY_RGB);
+ IMB_rectblend(clonebuf, ibufb, destx, desty, destx, desty, w, h,
+ IMB_BLEND_COPY_ALPHA);
+
+ return clonebuf;
+}
+
+static void imapaint_convert_brushco(ImBuf *ibufb, float *pos, int *ipos)
+{
+ ipos[0]= (int)(pos[0] - ibufb->x/2);
+ ipos[1]= (int)(pos[1] - ibufb->y/2);
+}
+
+/* dosnt run for projection painting
+ * only the old style painting in the 3d view */
+static int imapaint_paint_op(void *state, ImBuf *ibufb, float *lastpos, float *pos)
+{
+ ImagePaintState *s= ((ImagePaintState*)state);
+ ImBuf *clonebuf= NULL;
+ short torus= s->brush->flag & BRUSH_TORUS;
+ short blend= s->blend;
+ float *offset= s->brush->clone.offset;
+ float liftpos[2];
+ int bpos[2], blastpos[2], bliftpos[2];
+
+ imapaint_convert_brushco(ibufb, pos, bpos);
+
+ /* lift from canvas */
+ if(s->tool == PAINT_TOOL_SOFTEN) {
+ imapaint_lift_soften(s->canvas, ibufb, bpos, torus);
+ }
+ else if(s->tool == PAINT_TOOL_SMEAR) {
+ if (lastpos[0]==pos[0] && lastpos[1]==pos[1])
+ return 0;
+
+ imapaint_convert_brushco(ibufb, lastpos, blastpos);
+ imapaint_lift_smear(s->canvas, ibufb, blastpos);
+ }
+ else if(s->tool == PAINT_TOOL_CLONE && s->clonecanvas) {
+ liftpos[0]= pos[0] - offset[0]*s->canvas->x;
+ liftpos[1]= pos[1] - offset[1]*s->canvas->y;
+
+ imapaint_convert_brushco(ibufb, liftpos, bliftpos);
+ clonebuf= imapaint_lift_clone(s->clonecanvas, ibufb, bliftpos);
+ }
+
+ imapaint_dirty_region(s->image, s->canvas, bpos[0], bpos[1], ibufb->x, ibufb->y);
+
+ /* blend into canvas */
+ if(torus)
+ IMB_rectblend_torus(s->canvas, (clonebuf)? clonebuf: ibufb,
+ bpos[0], bpos[1], 0, 0, ibufb->x, ibufb->y, blend);
+ else
+ IMB_rectblend(s->canvas, (clonebuf)? clonebuf: ibufb,
+ bpos[0], bpos[1], 0, 0, ibufb->x, ibufb->y, blend);
+
+ if(clonebuf) IMB_freeImBuf(clonebuf);
+
+ return 1;
+}
+
+/* 3D TexturePaint */
+
+static int texpaint_break_stroke(float *prevuv, float *fwuv, float *bkuv, float *uv)
+{
+ float d1[2], d2[2];
+ float mismatch = Vec2Lenf(fwuv, uv);
+ float len1 = Vec2Lenf(prevuv, fwuv);
+ float len2 = Vec2Lenf(bkuv, uv);
+
+ Vec2Subf(d1, fwuv, prevuv);
+ Vec2Subf(d2, uv, bkuv);
+
+ return ((Inp2f(d1, d2) < 0.0f) || (mismatch > MAX2(len1, len2)*2));
+}
+
+/* ImagePaint Common */
+
+static int imapaint_canvas_set(ImagePaintState *s, Image *ima)
+{
+ ImBuf *ibuf= BKE_image_get_ibuf(ima, s->sima? &s->sima->iuser: NULL);
+
+ /* verify that we can paint and set canvas */
+ if(ima->packedfile && ima->rr) {
+ s->warnpackedfile = ima->id.name + 2;
+ return 0;
+ }
+ else if(ibuf && ibuf->channels!=4) {
+ s->warnmultifile = ima->id.name + 2;
+ return 0;
+ }
+ else if(!ima || !ibuf || !(ibuf->rect || ibuf->rect_float))
+ return 0;
+
+ s->image= ima;
+ s->canvas= ibuf;
+
+ /* set clone canvas */
+ if(s->tool == PAINT_TOOL_CLONE) {
+ ima= s->brush->clone.image;
+ ibuf= BKE_image_get_ibuf(ima, s->sima? &s->sima->iuser: NULL);
+
+ if(!ima || !ibuf || !(ibuf->rect || ibuf->rect_float))
+ return 0;
+
+ s->clonecanvas= ibuf;
+
+ if(s->canvas->rect_float && !s->clonecanvas->rect_float) {
+ /* temporarily add float rect for cloning */
+ IMB_float_from_rect(s->clonecanvas);
+ s->clonefreefloat= 1;
+ }
+ else if(!s->canvas->rect_float && !s->clonecanvas->rect)
+ IMB_rect_from_float(s->clonecanvas);
+ }
+
+ return 1;
+}
+
+static void imapaint_canvas_free(ImagePaintState *s)
+{
+ if (s->clonefreefloat)
+ imb_freerectfloatImBuf(s->clonecanvas);
+}
+
+static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, Image *image, short texpaint, float *uv, double time, int update, float pressure)
+{
+ ImBuf *ibuf= BKE_image_get_ibuf(image, s->sima? &s->sima->iuser: NULL);
+ float pos[2];
+
+ if(!ibuf)
+ return 0;
+
+ pos[0] = uv[0]*ibuf->x;
+ pos[1] = uv[1]*ibuf->y;
+
+ brush_painter_require_imbuf(painter, ((ibuf->rect_float)? 1: 0), 0, 0);
+
+ if (brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s)) {
+ if (update)
+ imapaint_image_update(s->sima, image, ibuf, texpaint);
+ return 1;
+ }
+ else return 0;
+}
+
+static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPainter *painter, short texpaint, int *prevmval, int *mval, double time, float pressure)
+{
+ Image *newimage = NULL;
+ float fwuv[2], bkuv[2], newuv[2];
+ unsigned int newfaceindex;
+ int breakstroke = 0, redraw = 0;
+
+ if (texpaint) {
+ /* pick new face and image */
+ if ( imapaint_pick_face(vc, s->me, mval, &newfaceindex) &&
+ ((G.f & G_FACESELECT)==0 || (s->me->mface+newfaceindex)->flag & ME_FACE_SEL)
+ ) {
+ ImBuf *ibuf;
+
+ newimage = (Image*)((s->me->mtface+newfaceindex)->tpage);
+ ibuf= BKE_image_get_ibuf(newimage, s->sima? &s->sima->iuser: NULL);
+
+ if(ibuf && ibuf->rect)
+ imapaint_pick_uv(s->scene, s->ob, s->me, newfaceindex, mval, newuv);
+ else {
+ newimage = NULL;
+ newuv[0] = newuv[1] = 0.0f;
+ }
+ }
+ else
+ newuv[0] = newuv[1] = 0.0f;
+
+ /* see if stroke is broken, and if so finish painting in old position */
+ if (s->image) {
+ imapaint_pick_uv(s->scene, s->ob, s->me, s->faceindex, mval, fwuv);
+ imapaint_pick_uv(s->scene, s->ob, s->me, newfaceindex, prevmval, bkuv);
+
+ if (newimage == s->image)
+ breakstroke= texpaint_break_stroke(s->uv, fwuv, bkuv, newuv);
+ else
+ breakstroke= 1;
+ }
+ else
+ fwuv[0]= fwuv[1]= 0.0f;
+
+ if (breakstroke) {
+ imapaint_pick_uv(s->scene, s->ob, s->me, s->faceindex, mval, fwuv);
+ redraw |= imapaint_paint_sub_stroke(s, painter, s->image, texpaint,
+ fwuv, time, 1, pressure);
+ imapaint_clear_partial_redraw();
+ brush_painter_break_stroke(painter);
+ }
+
+ /* set new canvas */
+ if (newimage && (newimage != s->image))
+ if (!imapaint_canvas_set(s, newimage))
+ newimage = NULL;
+
+ /* paint in new image */
+ if (newimage) {
+ if (breakstroke)
+ redraw|= imapaint_paint_sub_stroke(s, painter, newimage,
+ texpaint, bkuv, time, 0, pressure);
+ redraw|= imapaint_paint_sub_stroke(s, painter, newimage, texpaint,
+ newuv, time, 1, pressure);
+ }
+
+ /* update state */
+ s->image = newimage;
+ s->faceindex = newfaceindex;
+ s->uv[0] = newuv[0];
+ s->uv[1] = newuv[1];
+ }
+ else {
+ UI_view2d_region_to_view(s->v2d, mval[0], mval[1], &newuv[0], &newuv[1]);
+ redraw |= imapaint_paint_sub_stroke(s, painter, s->image, texpaint, newuv,
+ time, 1, pressure);
+ }
+
+ if (redraw)
+ imapaint_clear_partial_redraw();
+
+ return redraw;
+}
+
+/************************ image paint poll ************************/
+
+static Brush *image_paint_brush(bContext *C)
+{
+ Scene *scene= CTX_data_scene(C);
+ ToolSettings *settings= scene->toolsettings;
+
+ return settings->imapaint.brush;
+}
+
+static int image_paint_poll(bContext *C)
+{
+ if(!image_paint_brush(C))
+ return 0;
+
+ if((G.f & G_TEXTUREPAINT) && CTX_wm_region_view3d(C)) {
+ return 1;
+ }
+ else {
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+
+ if(sa && sa->spacetype==SPACE_IMAGE) {
+ ARegion *ar= CTX_wm_region(C);
+
+ if((sima->flag & SI_DRAWTOOL) && ar->regiontype==RGN_TYPE_WINDOW)
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int image_paint_3d_poll(bContext *C)
+{
+ if(CTX_wm_region_view3d(C))
+ return image_paint_poll(C);
+
+ return 0;
+}
+
+static int image_paint_2d_clone_poll(bContext *C)
+{
+ Scene *scene= CTX_data_scene(C);
+ ToolSettings *settings= scene->toolsettings;
+ Brush *brush= image_paint_brush(C);
+
+ if(!CTX_wm_region_view3d(C) && image_paint_poll(C))
+ if(brush && (settings->imapaint.tool == PAINT_TOOL_CLONE))
+ if(brush->clone.image)
+ return 1;
+
+ return 0;
+}
+
+/************************ paint operator ************************/
+
+typedef enum PaintMode {
+ PAINT_MODE_2D,
+ PAINT_MODE_3D,
+ PAINT_MODE_3D_PROJECT
+} PaintMode;
+
+typedef struct PaintOperation {
+ PaintMode mode;
+
+ BrushPainter *painter;
+ ImagePaintState s;
+ ProjPaintState ps;
+
+ int first;
+ int prevmouse[2];
+ double starttime;
+
+ ViewContext vc;
+ wmTimer *timer;
+} PaintOperation;
+
+static void paint_redraw(bContext *C, ImagePaintState *s, int final)
+{
+ if(final) {
+ if(s->image)
+ GPU_free_image(s->image);
+
+ WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, s->image);
+
+ // XXX node update
+#if 0
+ if(!s->sima && s->image) {
+ /* after paint, tag Image or RenderResult nodes changed */
+ if(s->scene->nodetree) {
+ imagepaint_composite_tags(s->scene->nodetree, image, &s->sima->iuser);
+ }
+ /* signal composite (hurmf, need an allqueue?) */
+ if(s->sima->lock) {
+ ScrArea *sa;
+ for(sa=s->screen->areabase.first; sa; sa= sa->next) {
+ if(sa->spacetype==SPACE_NODE) {
+ if(((SpaceNode *)sa->spacedata.first)->treetype==NTREE_COMPOSIT) {
+ addqueue(sa->win, UI_BUT_EVENT, B_NODE_TREE_EXEC);
+ break;
+ }
+ }
+ }
+ }
+ }
+#endif
+ }
+ else {
+ if(!s->sima || !s->sima->lock)
+ ED_region_tag_redraw(CTX_wm_region(C));
+ else
+ WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, s->image);
+ }
+}
+
+static int paint_init(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ ToolSettings *settings= scene->toolsettings;
+ PaintOperation *pop;
+
+ pop= MEM_callocN(sizeof(PaintOperation), "PaintOperation");
+ pop->first= 1;
+ op->customdata= pop;
+
+ /* initialize from context */
+ if(CTX_wm_region_view3d(C)) {
+ pop->ps.v3d= CTX_wm_view3d(C);
+ pop->ps.rv3d= CTX_wm_region_view3d(C);
+ pop->mode= PAINT_MODE_3D;
+
+ if(!(settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE))
+ pop->mode= PAINT_MODE_3D_PROJECT;
+ else
+ view3d_set_viewcontext(C, &pop->vc);
+ }
+ else {
+ pop->s.sima= (SpaceImage*)CTX_wm_space_data(C);
+ pop->s.v2d= &CTX_wm_region(C)->v2d;
+ }
+
+ pop->s.scene= scene;
+ pop->ps.scene= scene;
+ pop->s.screen= CTX_wm_screen(C);
+ pop->ps.ar= CTX_wm_region(C);
+
+ /* intialize brush */
+ pop->s.brush = settings->imapaint.brush;
+ pop->s.tool = settings->imapaint.tool;
+ if(pop->mode == PAINT_MODE_3D && (pop->s.tool == PAINT_TOOL_CLONE))
+ pop->s.tool = PAINT_TOOL_DRAW;
+ pop->s.blend = pop->s.brush->blend;
+
+ if(pop->mode == PAINT_MODE_3D_PROJECT) {
+ pop->ps.brush = pop->s.brush;
+ pop->ps.tool = pop->s.tool;
+ pop->ps.blend = pop->s.blend;
+ }
+
+ if(pop->mode != PAINT_MODE_2D) {
+ pop->ps.ob = pop->s.ob = OBACT;
+ if (!pop->s.ob || !(pop->s.ob->lay & pop->ps.v3d->lay)) return 0;
+ pop->s.me = get_mesh(pop->s.ob);
+ if (!pop->s.me) return 0;
+ }
+ else {
+ pop->s.image = pop->s.sima->image;
+
+ if(!imapaint_canvas_set(&pop->s, pop->s.sima->image)) {
+ if(pop->s.warnmultifile)
+ BKE_report(op->reports, RPT_WARNING, "Image requires 4 color channels to paint");
+ if(pop->s.warnpackedfile)
+ BKE_report(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted");
+
+ return 0;
+ }
+ }
+
+ /* note, if we have no UVs on the derived mesh, then we must return here */
+ if(pop->mode == PAINT_MODE_3D_PROJECT) {
+ /* setup projection painting data */
+ pop->ps.do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1;
+ pop->ps.do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1;
+ pop->ps.do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? 0 : 1;;
+
+ if (pop->ps.tool == PAINT_TOOL_CLONE)
+ pop->ps.do_layer_clone = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE);
+
+ pop->ps.do_layer_mask = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_MASK) ? 1 : 0;
+ pop->ps.do_layer_mask_inv = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_MASK_INV) ? 1 : 0;
+
+
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ pop->ps.seam_bleed_px = settings->imapaint.seam_bleed; /* pixel num to bleed */
+#endif
+
+ if(pop->ps.do_mask_normal) {
+ pop->ps.normal_angle_inner = settings->imapaint.normal_angle;
+ pop->ps.normal_angle = (pop->ps.normal_angle_inner + 90.0f) * 0.5f;
+ }
+ else {
+ pop->ps.normal_angle_inner= pop->ps.normal_angle= settings->imapaint.normal_angle;
+ }
+
+ pop->ps.normal_angle_inner *= M_PI_2 / 90;
+ pop->ps.normal_angle *= M_PI_2 / 90;
+ pop->ps.normal_angle_range = pop->ps.normal_angle - pop->ps.normal_angle_inner;
+
+ if(pop->ps.normal_angle_range <= 0.0f)
+ pop->ps.do_mask_normal = 0; /* no need to do blending */
+
+ project_paint_begin(&pop->ps);
+
+ if(pop->ps.dm==NULL)
+ return 0;
+ }
+
+ settings->imapaint.flag |= IMAGEPAINT_DRAWING;
+ undo_imagepaint_push_begin("Image Paint");
+
+ /* create painter */
+ pop->painter= brush_painter_new(pop->s.brush);
+
+ return 1;
+}
+
+static void paint_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
+{
+ PaintOperation *pop= op->customdata;
+ float time;
+ float pressure;
+ int mouse[2], redraw;
+
+ RNA_int_get_array(itemptr, "mouse", mouse);
+ time= RNA_float_get(itemptr, "time");
+ pressure= RNA_float_get(itemptr, "pressure");
+
+ if(pop->first)
+ project_paint_begin_clone(&pop->ps, mouse);
+
+ if(pop->mode == PAINT_MODE_3D)
+ view3d_operator_needs_opengl(C);
+
+ if(pop->mode == PAINT_MODE_3D_PROJECT) {
+ redraw= project_paint_stroke(&pop->ps, pop->painter, pop->prevmouse, mouse, time, pressure);
+ pop->prevmouse[0]= mouse[0];
+ pop->prevmouse[1]= mouse[1];
+
+ }
+ else {
+ redraw= imapaint_paint_stroke(&pop->vc, &pop->s, pop->painter, pop->mode == PAINT_MODE_3D, pop->prevmouse, mouse, time, pressure);
+ pop->prevmouse[0]= mouse[0];
+ pop->prevmouse[1]= mouse[1];
+ }
+
+ if(redraw)
+ paint_redraw(C, &pop->s, 0);
+
+ pop->first= 0;
+}
+
+static void paint_exit(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ ToolSettings *settings= scene->toolsettings;
+ PaintOperation *pop= op->customdata;
+
+ if(pop->timer)
+ WM_event_remove_window_timer(CTX_wm_window(C), pop->timer);
+
+ settings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
+ imapaint_canvas_free(&pop->s);
+ brush_painter_free(pop->painter);
+
+ if(pop->mode == PAINT_MODE_3D_PROJECT)
+ project_paint_end(&pop->ps);
+
+ paint_redraw(C, &pop->s, 1);
+ undo_imagepaint_push_end();
+
+ if(pop->s.warnmultifile)
+ BKE_reportf(op->reports, RPT_WARNING, "Image requires 4 color channels to paint: %s", pop->s.warnmultifile);
+ if(pop->s.warnpackedfile)
+ BKE_reportf(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted: %s", pop->s.warnpackedfile);
+
+ MEM_freeN(pop);
+}
+
+static int paint_exec(bContext *C, wmOperator *op)
+{
+ if(!paint_init(C, op)) {
+ MEM_freeN(op->customdata);
+ return OPERATOR_CANCELLED;
+ }
+
+ RNA_BEGIN(op->ptr, itemptr, "stroke") {
+ paint_apply(C, op, &itemptr);
+ }
+ RNA_END;
+
+ paint_exit(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ PaintOperation *pop= op->customdata;
+ wmTabletData *wmtab;
+ PointerRNA itemptr;
+ float pressure;
+ double time;
+ int tablet, mouse[2];
+
+ // XXX +1 matches brush location better but
+ // still not exact, find out why and fix ..
+ mouse[0]= event->x - ar->winrct.xmin + 1;
+ mouse[1]= event->y - ar->winrct.ymin + 1;
+
+ time= PIL_check_seconds_timer();
+
+ tablet= 0;
+ pressure= 0;
+ pop->s.blend= pop->s.brush->blend;
+
+ if(event->custom == EVT_DATA_TABLET) {
+ wmtab= event->customdata;
+
+ tablet= (wmtab->Active != EVT_TABLET_NONE);
+ pressure= wmtab->Pressure;
+ if(wmtab->Active == EVT_TABLET_ERASER)
+ pop->s.blend= BRUSH_BLEND_ERASE_ALPHA;
+ }
+ else
+ pressure= 1.0f;
+
+ if(pop->first) {
+ pop->prevmouse[0]= mouse[0];
+ pop->prevmouse[1]= mouse[1];
+ pop->starttime= time;
+
+ /* special exception here for too high pressure values on first touch in
+ windows for some tablets, then we just skip first touch .. */
+ if ((pop->s.brush->flag & (BRUSH_ALPHA_PRESSURE|BRUSH_SIZE_PRESSURE|
+ BRUSH_SPACING_PRESSURE|BRUSH_RAD_PRESSURE)) && tablet && (pressure >= 0.99f))
+ return;
+ }
+
+ /* fill in stroke */
+ RNA_collection_add(op->ptr, "stroke", &itemptr);
+
+ RNA_int_set_array(&itemptr, "mouse", mouse);
+ RNA_float_set(&itemptr, "time", (float)(time - pop->starttime));
+ RNA_float_set(&itemptr, "pressure", pressure);
+
+ /* apply */
+ paint_apply(C, op, &itemptr);
+}
+
+static int paint_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ PaintOperation *pop;
+
+ if(!paint_init(C, op)) {
+ MEM_freeN(op->customdata);
+ return OPERATOR_CANCELLED;
+ }
+
+ paint_apply_event(C, op, event);
+
+ pop= op->customdata;
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ if(pop->s.brush->flag & BRUSH_AIRBRUSH)
+ pop->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.01f);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int paint_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ PaintOperation *pop= op->customdata;
+
+ switch(event->type) {
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE: // XXX hardcoded
+ paint_exit(C, op);
+ return OPERATOR_FINISHED;
+ case MOUSEMOVE:
+ paint_apply_event(C, op, event);
+ break;
+ case TIMER:
+ if(event->customdata == pop->timer)
+ paint_apply_event(C, op, event);
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int paint_cancel(bContext *C, wmOperator *op)
+{
+ paint_exit(C, op);
+
+ return OPERATOR_CANCELLED;
+}
+
+void PAINT_OT_image_paint(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Image Paint";
+ ot->idname= "PAINT_OT_image_paint";
+
+ /* api callbacks */
+ ot->exec= paint_exec;
+ ot->invoke= paint_invoke;
+ ot->modal= paint_modal;
+ ot->cancel= paint_cancel;
+ ot->poll= image_paint_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+}
+
+static int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
+{
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+
+ if(!rv3d) {
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+
+ ED_space_image_zoom(sima, ar, zoomx, zoomy);
+
+ return 1;
+ }
+
+ *zoomx = *zoomy = 1;
+
+ return 0;
+}
+
+/************************ cursor drawing *******************************/
+
+static void brush_drawcursor(bContext *C, int x, int y, void *customdata)
+{
+ Brush *brush= image_paint_brush(C);
+
+ if(brush) {
+ float zoomx, zoomy;
+ glPushMatrix();
+
+ glTranslatef((float)x, (float)y, 0.0f);
+
+ if(get_imapaint_zoom(C, &zoomx, &zoomy))
+ glScalef(zoomx, zoomy, 1.0f);
+
+ glColor4ub(255, 255, 255, 128);
+ glEnable( GL_LINE_SMOOTH );
+ glEnable(GL_BLEND);
+ glutil_draw_lined_arc(0.0, M_PI*2.0, brush->size*0.5f, 40);
+ glDisable(GL_BLEND);
+ glDisable( GL_LINE_SMOOTH );
+
+ glPopMatrix();
+ }
+}
+
+static void toggle_paint_cursor(bContext *C, int enable)
+{
+ ToolSettings *settings= CTX_data_scene(C)->toolsettings;
+
+ if(settings->imapaint.paintcursor && !enable) {
+ WM_paint_cursor_end(CTX_wm_manager(C), settings->imapaint.paintcursor);
+ settings->imapaint.paintcursor = NULL;
+ }
+ else if(enable)
+ settings->imapaint.paintcursor= WM_paint_cursor_activate(CTX_wm_manager(C), image_paint_poll, brush_drawcursor, NULL);
+}
+
+/* ************ image paint radial control *************/
+static int paint_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ float zoom;
+ ToolSettings *ts = CTX_data_scene(C)->toolsettings;
+ get_imapaint_zoom(C, &zoom, &zoom);
+ toggle_paint_cursor(C, !ts->imapaint.paintcursor);
+ brush_radial_control_invoke(op, ts->imapaint.brush, 0.5 * zoom);
+ return WM_radial_control_invoke(C, op, event);
+}
+
+static int paint_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ToolSettings *ts = CTX_data_scene(C)->toolsettings;
+ int ret = WM_radial_control_modal(C, op, event);
+ if(ret != OPERATOR_RUNNING_MODAL)
+ toggle_paint_cursor(C, !ts->imapaint.paintcursor);
+ return ret;
+}
+
+static int paint_radial_control_exec(bContext *C, wmOperator *op)
+{
+ float zoom;
+ int ret;
+ char str[256];
+ get_imapaint_zoom(C, &zoom, &zoom);
+ ret = brush_radial_control_exec(op, CTX_data_scene(C)->toolsettings->imapaint.brush, 2.0 / zoom);
+ WM_radial_control_string(op, str, 256);
+
+ return ret;
+}
+
+void PAINT_OT_image_paint_radial_control(wmOperatorType *ot)
+{
+ WM_OT_radial_control_partial(ot);
+
+ ot->name= "Image Paint Radial Control";
+ ot->idname= "PAINT_OT_image_paint_radial_control";
+
+ ot->invoke= paint_radial_control_invoke;
+ ot->modal= paint_radial_control_modal;
+ ot->exec= paint_radial_control_exec;
+ ot->poll= image_paint_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/************************ grab clone operator ************************/
+
+typedef struct GrabClone {
+ float startoffset[2];
+ int startx, starty;
+} GrabClone;
+
+static void grab_clone_apply(bContext *C, wmOperator *op)
+{
+ Brush *brush= image_paint_brush(C);
+ float delta[2];
+
+ RNA_float_get_array(op->ptr, "delta", delta);
+ brush->clone.offset[0] += delta[0];
+ brush->clone.offset[1] += delta[1];
+
+ ED_region_tag_redraw(CTX_wm_region(C));
+}
+
+static int grab_clone_exec(bContext *C, wmOperator *op)
+{
+ grab_clone_apply(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+static int grab_clone_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Brush *brush= image_paint_brush(C);
+ GrabClone *cmv;
+
+ cmv= MEM_callocN(sizeof(GrabClone), "GrabClone");
+ cmv->startoffset[0]= brush->clone.offset[0];
+ cmv->startoffset[1]= brush->clone.offset[1];
+ cmv->startx= event->x;
+ cmv->starty= event->y;
+ op->customdata= cmv;
+
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int grab_clone_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Brush *brush= image_paint_brush(C);
+ ARegion *ar= CTX_wm_region(C);
+ GrabClone *cmv= op->customdata;
+ float startfx, startfy, fx, fy, delta[2];
+ int xmin= ar->winrct.xmin, ymin= ar->winrct.ymin;
+
+ switch(event->type) {
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE: // XXX hardcoded
+ MEM_freeN(op->customdata);
+ return OPERATOR_FINISHED;
+ case MOUSEMOVE:
+ /* mouse moved, so move the clone image */
+ UI_view2d_region_to_view(&ar->v2d, cmv->startx - xmin, cmv->starty - ymin, &startfx, &startfy);
+ UI_view2d_region_to_view(&ar->v2d, event->x - xmin, event->y - ymin, &fx, &fy);
+
+ delta[0]= fx - startfx;
+ delta[1]= fy - startfy;
+ RNA_float_set_array(op->ptr, "delta", delta);
+
+ brush->clone.offset[0]= cmv->startoffset[0];
+ brush->clone.offset[1]= cmv->startoffset[1];
+
+ grab_clone_apply(C, op);
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int grab_clone_cancel(bContext *C, wmOperator *op)
+{
+ MEM_freeN(op->customdata);
+ return OPERATOR_CANCELLED;
+}
+
+void PAINT_OT_grab_clone(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Grab Clone";
+ ot->idname= "PAINT_OT_grab_clone";
+
+ /* api callbacks */
+ ot->exec= grab_clone_exec;
+ ot->invoke= grab_clone_invoke;
+ ot->modal= grab_clone_modal;
+ ot->cancel= grab_clone_cancel;
+ ot->poll= image_paint_2d_clone_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float_vector(ot->srna, "delta", 2, NULL, -FLT_MAX, FLT_MAX, "Delta", "Delta offset of clone image in 0.0..1.0 coordinates.", -1.0f, 1.0f);
+}
+
+/******************** sample color operator ********************/
+
+static int sample_color_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Brush *brush= image_paint_brush(C);
+ ARegion *ar= CTX_wm_region(C);
+ int location[2];
+
+ RNA_int_get_array(op->ptr, "location", location);
+ paint_sample_color(scene, ar, location[0], location[1]);
+
+ WM_event_add_notifier(C, NC_BRUSH|NA_EDITED, brush);
+
+ return OPERATOR_FINISHED;
+}
+
+static int sample_color_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ int location[2];
+
+ location[0]= event->x - ar->winrct.xmin;
+ location[1]= event->y - ar->winrct.ymin;
+ RNA_int_set_array(op->ptr, "location", location);
+
+ return sample_color_exec(C, op);
+}
+
+void PAINT_OT_sample_color(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Sample Color";
+ ot->idname= "PAINT_OT_sample_color";
+
+ /* api callbacks */
+ ot->exec= sample_color_exec;
+ ot->invoke= sample_color_invoke;
+ ot->poll= image_paint_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "Cursor location in region coordinates.", 0, 16384);
+}
+
+/******************** set clone cursor operator ********************/
+
+static int set_clone_cursor_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ View3D *v3d= CTX_wm_view3d(C);
+ float *cursor= give_cursor(scene, v3d);
+
+ RNA_float_get_array(op->ptr, "location", cursor);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+static int set_clone_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Scene *scene= CTX_data_scene(C);
+ View3D *v3d= CTX_wm_view3d(C);
+ ARegion *ar= CTX_wm_region(C);
+ float location[3];
+ short mval[2];
+
+ mval[0]= event->x - ar->winrct.xmin;
+ mval[1]= event->y - ar->winrct.ymin;
+
+ view3d_operator_needs_opengl(C);
+
+ if(!view_autodist(scene, ar, v3d, mval, location))
+ return OPERATOR_CANCELLED;
+
+ RNA_float_set_array(op->ptr, "location", location);
+
+ return set_clone_cursor_exec(C, op);
+}
+
+void PAINT_OT_clone_cursor_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Clone Cursor";
+ ot->idname= "PAINT_OT_clone_cursor_set";
+
+ /* api callbacks */
+ ot->exec= set_clone_cursor_exec;
+ ot->invoke= set_clone_cursor_invoke;
+ ot->poll= image_paint_3d_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float_vector(ot->srna, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in world space coordinates.", -10000.0f, 10000.0f);
+}
+
+/******************** texture paint toggle operator ********************/
+
+static int texture_paint_toggle_poll(bContext *C)
+{
+ if(CTX_data_edit_object(C))
+ return 0;
+ if(CTX_data_active_object(C)==NULL)
+ return 0;
+
+ return 1;
+}
+
+static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+ Mesh *me= 0;
+
+ if(ob==NULL)
+ return OPERATOR_CANCELLED;
+
+ if (object_data_is_libdata(ob)) {
+ BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata.");
+ return OPERATOR_CANCELLED;
+ }
+
+ me= get_mesh(ob);
+
+ if(!(G.f & G_TEXTUREPAINT) && !me) {
+ BKE_report(op->reports, RPT_ERROR, "Can only enter texture paint mode for mesh objects.");
+ return OPERATOR_CANCELLED;
+ }
+
+ if(G.f & G_TEXTUREPAINT) {
+ G.f &= ~G_TEXTUREPAINT;
+
+ if(U.glreslimit != 0)
+ GPU_free_images();
+ GPU_paint_set_mipmap(1);
+
+ toggle_paint_cursor(C, 0);
+ }
+ else {
+ G.f |= G_TEXTUREPAINT;
+
+ if(me->mtface==NULL)
+ me->mtface= CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT,
+ NULL, me->totface);
+
+ brush_check_exists(&scene->toolsettings->imapaint.brush);
+
+ if(U.glreslimit != 0)
+ GPU_free_images();
+ GPU_paint_set_mipmap(0);
+
+ toggle_paint_cursor(C, 1);
+ }
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void PAINT_OT_texture_paint_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Texture Paint Toggle";
+ ot->idname= "PAINT_OT_texture_paint_toggle";
+
+ /* api callbacks */
+ ot->exec= texture_paint_toggle_exec;
+ ot->poll= texture_paint_toggle_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/************* texture paint radial control *************/
+
+static int texture_paint_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ToolSettings *ts = CTX_data_scene(C)->toolsettings;
+ toggle_paint_cursor(C, !ts->imapaint.paintcursor);
+ brush_radial_control_invoke(op, ts->imapaint.brush, 0.5);
+ return WM_radial_control_invoke(C, op, event);
+}
+
+static int texture_paint_radial_control_exec(bContext *C, wmOperator *op)
+{
+ int ret = brush_radial_control_exec(op, CTX_data_scene(C)->toolsettings->imapaint.brush, 2);
+ char str[256];
+ WM_radial_control_string(op, str, 256);
+
+ return ret;
+}
+
+static int texture_paint_poll(bContext *C)
+{
+ if(texture_paint_toggle_poll(C))
+ if(G.f & G_TEXTUREPAINT)
+ return 1;
+
+ return 0;
+}
+
+void PAINT_OT_texture_paint_radial_control(wmOperatorType *ot)
+{
+ WM_OT_radial_control_partial(ot);
+
+ ot->name= "Texture Paint Radial Control";
+ ot->idname= "PAINT_OT_texture_paint_radial_control";
+
+ ot->invoke= texture_paint_radial_control_invoke;
+ ot->modal= paint_radial_control_modal;
+ ot->exec= texture_paint_radial_control_exec;
+ ot->poll= texture_paint_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
new file mode 100644
index 00000000000..b630975c934
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -0,0 +1,64 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_PAINT_INTERN_H
+#define ED_PAINT_INTERN_H
+
+struct Scene;
+struct Object;
+struct Mesh;
+struct ViewContext;
+struct wmOperatorType;
+struct ARegion;
+
+/* paint_vertex.c */
+void PAINT_OT_weight_paint_toggle(struct wmOperatorType *ot);
+void PAINT_OT_weight_paint_radial_control(struct wmOperatorType *ot);
+void PAINT_OT_weight_paint(struct wmOperatorType *ot);
+
+void PAINT_OT_vertex_paint_radial_control(struct wmOperatorType *ot);
+void PAINT_OT_vertex_paint_toggle(struct wmOperatorType *ot);
+void PAINT_OT_vertex_paint(struct wmOperatorType *ot);
+
+/* paint_image.c */
+void PAINT_OT_image_paint(struct wmOperatorType *ot);
+void PAINT_OT_image_paint_radial_control(struct wmOperatorType *ot);
+void PAINT_OT_grab_clone(struct wmOperatorType *ot);
+void PAINT_OT_sample_color(struct wmOperatorType *ot);
+void PAINT_OT_clone_cursor_set(struct wmOperatorType *ot);
+void PAINT_OT_texture_paint_toggle(struct wmOperatorType *ot);
+void PAINT_OT_texture_paint_radial_control(struct wmOperatorType *ot);
+
+/* paint_utils.c */
+int imapaint_pick_face(struct ViewContext *vc, struct Mesh *me, int *mval, unsigned int *index);
+void imapaint_pick_uv(struct Scene *scene, struct Object *ob, struct Mesh *mesh, unsigned int faceindex, int *xy, float *uv);
+
+void paint_sample_color(struct Scene *scene, struct ARegion *ar, int x, int y);
+
+#endif /* ED_PAINT_INTERN_H */
+
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
new file mode 100644
index 00000000000..e9263ddabf0
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -0,0 +1,32 @@
+
+#include "ED_sculpt.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "paint_intern.h"
+
+/**************************** registration **********************************/
+
+void ED_operatortypes_paint(void)
+{
+ /* image */
+ WM_operatortype_append(PAINT_OT_texture_paint_toggle);
+ WM_operatortype_append(PAINT_OT_texture_paint_radial_control);
+ WM_operatortype_append(PAINT_OT_image_paint);
+ WM_operatortype_append(PAINT_OT_image_paint_radial_control);
+ WM_operatortype_append(PAINT_OT_sample_color);
+ WM_operatortype_append(PAINT_OT_grab_clone);
+ WM_operatortype_append(PAINT_OT_clone_cursor_set);
+
+ /* weight */
+ WM_operatortype_append(PAINT_OT_weight_paint_toggle);
+ WM_operatortype_append(PAINT_OT_weight_paint_radial_control);
+ WM_operatortype_append(PAINT_OT_weight_paint);
+
+ /* vertex */
+ WM_operatortype_append(PAINT_OT_vertex_paint_radial_control);
+ WM_operatortype_append(PAINT_OT_vertex_paint_toggle);
+ WM_operatortype_append(PAINT_OT_vertex_paint);
+}
+
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
new file mode 100644
index 00000000000..85ea55331dc
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -0,0 +1,182 @@
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BLI_arithb.h"
+
+#include "BKE_brush.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+
+#include "ED_view3d.h"
+
+#include "paint_intern.h"
+
+/* 3D Paint */
+
+static void imapaint_project(Object *ob, float *model, float *proj, float *co, float *pco)
+{
+ VECCOPY(pco, co);
+ pco[3]= 1.0f;
+
+ Mat4MulVecfl(ob->obmat, pco);
+ Mat4MulVecfl((float(*)[4])model, pco);
+ Mat4MulVec4fl((float(*)[4])proj, pco);
+}
+
+static void imapaint_tri_weights(Object *ob, float *v1, float *v2, float *v3, float *co, float *w)
+{
+ float pv1[4], pv2[4], pv3[4], h[3], divw;
+ float model[16], proj[16], wmat[3][3], invwmat[3][3];
+ GLint view[4];
+
+ /* compute barycentric coordinates */
+
+ /* get the needed opengl matrices */
+ glGetIntegerv(GL_VIEWPORT, view);
+ glGetFloatv(GL_MODELVIEW_MATRIX, model);
+ glGetFloatv(GL_PROJECTION_MATRIX, proj);
+ view[0] = view[1] = 0;
+
+ /* project the verts */
+ imapaint_project(ob, model, proj, v1, pv1);
+ imapaint_project(ob, model, proj, v2, pv2);
+ imapaint_project(ob, model, proj, v3, pv3);
+
+ /* do inverse view mapping, see gluProject man page */
+ h[0]= (co[0] - view[0])*2.0f/view[2] - 1;
+ h[1]= (co[1] - view[1])*2.0f/view[3] - 1;
+ h[2]= 1.0f;
+
+ /* solve for(w1,w2,w3)/perspdiv in:
+ h*perspdiv = Project*Model*(w1*v1 + w2*v2 + w3*v3) */
+
+ wmat[0][0]= pv1[0]; wmat[1][0]= pv2[0]; wmat[2][0]= pv3[0];
+ wmat[0][1]= pv1[1]; wmat[1][1]= pv2[1]; wmat[2][1]= pv3[1];
+ wmat[0][2]= pv1[3]; wmat[1][2]= pv2[3]; wmat[2][2]= pv3[3];
+
+ Mat3Inv(invwmat, wmat);
+ Mat3MulVecfl(invwmat, h);
+
+ VECCOPY(w, h);
+
+ /* w is still divided by perspdiv, make it sum to one */
+ divw= w[0] + w[1] + w[2];
+ if(divw != 0.0f)
+ VecMulf(w, 1.0f/divw);
+}
+
+/* compute uv coordinates of mouse in face */
+void imapaint_pick_uv(Scene *scene, Object *ob, Mesh *mesh, unsigned int faceindex, int *xy, float *uv)
+{
+ DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ int *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
+ MTFace *tface = dm->getFaceDataArray(dm, CD_MTFACE), *tf;
+ int numfaces = dm->getNumFaces(dm), a;
+ float p[2], w[3], absw, minabsw;
+ MFace mf;
+ MVert mv[4];
+
+ minabsw = 1e10;
+ uv[0] = uv[1] = 0.0;
+
+ /* test all faces in the derivedmesh with the original index of the picked face */
+ for(a = 0; a < numfaces; a++) {
+ if(index[a] == faceindex) {
+ dm->getFace(dm, a, &mf);
+
+ dm->getVert(dm, mf.v1, &mv[0]);
+ dm->getVert(dm, mf.v2, &mv[1]);
+ dm->getVert(dm, mf.v3, &mv[2]);
+ if(mf.v4)
+ dm->getVert(dm, mf.v4, &mv[3]);
+
+ tf= &tface[a];
+
+ p[0]= xy[0];
+ p[1]= xy[1];
+
+ if(mf.v4) {
+ /* the triangle with the largest absolute values is the one
+ with the most negative weights */
+ imapaint_tri_weights(ob, mv[0].co, mv[1].co, mv[3].co, p, w);
+ absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]);
+ if(absw < minabsw) {
+ uv[0]= tf->uv[0][0]*w[0] + tf->uv[1][0]*w[1] + tf->uv[3][0]*w[2];
+ uv[1]= tf->uv[0][1]*w[0] + tf->uv[1][1]*w[1] + tf->uv[3][1]*w[2];
+ minabsw = absw;
+ }
+
+ imapaint_tri_weights(ob, mv[1].co, mv[2].co, mv[3].co, p, w);
+ absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]);
+ if(absw < minabsw) {
+ uv[0]= tf->uv[1][0]*w[0] + tf->uv[2][0]*w[1] + tf->uv[3][0]*w[2];
+ uv[1]= tf->uv[1][1]*w[0] + tf->uv[2][1]*w[1] + tf->uv[3][1]*w[2];
+ minabsw = absw;
+ }
+ }
+ else {
+ imapaint_tri_weights(ob, mv[0].co, mv[1].co, mv[2].co, p, w);
+ absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]);
+ if(absw < minabsw) {
+ uv[0]= tf->uv[0][0]*w[0] + tf->uv[1][0]*w[1] + tf->uv[2][0]*w[2];
+ uv[1]= tf->uv[0][1]*w[0] + tf->uv[1][1]*w[1] + tf->uv[2][1]*w[2];
+ minabsw = absw;
+ }
+ }
+ }
+ }
+
+ dm->release(dm);
+}
+
+///* returns 0 if not found, otherwise 1 */
+int imapaint_pick_face(ViewContext *vc, Mesh *me, int *mval, unsigned int *index)
+{
+ if(!me || me->totface==0)
+ return 0;
+
+ /* sample only on the exact position */
+ *index = view3d_sample_backbuf(vc, mval[0], mval[1]);
+
+ if((*index)<=0 || (*index)>(unsigned int)me->totface)
+ return 0;
+
+ (*index)--;
+
+ return 1;
+}
+
+/* used for both 3d view and image window */
+void paint_sample_color(Scene *scene, ARegion *ar, int x, int y) /* frontbuf */
+{
+ Brush **br = current_brush_source(scene);
+ unsigned int col;
+ char *cp;
+
+ CLAMP(x, 0, ar->winx);
+ CLAMP(y, 0, ar->winy);
+
+ glReadBuffer(GL_FRONT);
+ glReadPixels(x+ar->winrct.xmin, y+ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ glReadBuffer(GL_BACK);
+
+ cp = (char *)&col;
+
+ if(br && *br) {
+ (*br)->rgb[0]= cp[0]/255.0f;
+ (*br)->rgb[1]= cp[1]/255.0f;
+ (*br)->rgb[2]= cp[2]/255.0f;
+ }
+}
+
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
new file mode 100644
index 00000000000..0c20c0cc1cf
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -0,0 +1,1868 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <string.h>
+
+#ifdef WIN32
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "MTC_matrixops.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_brush_types.h"
+#include "DNA_cloth_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_particle_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_userdef_types.h"
+
+#include "RNA_access.h"
+
+#include "BKE_armature.h"
+#include "BKE_brush.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cloth.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_deform.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "ED_mesh.h"
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+#include "ED_view3d.h"
+
+ /* vp->mode */
+#define VP_MIX 0
+#define VP_ADD 1
+#define VP_SUB 2
+#define VP_MUL 3
+#define VP_BLUR 4
+#define VP_LIGHTEN 5
+#define VP_DARKEN 6
+
+#define MAXINDEX 512000
+
+/* XXX */
+static void error() {}
+
+/* polling - retrieve whether cursor should be set or operator should be done */
+
+static int vp_poll(bContext *C)
+{
+ if(G.f & G_VERTEXPAINT) {
+ ScrArea *sa= CTX_wm_area(C);
+ if(sa->spacetype==SPACE_VIEW3D) {
+ ARegion *ar= CTX_wm_region(C);
+ if(ar->regiontype==RGN_TYPE_WINDOW)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int wp_poll(bContext *C)
+{
+ if(G.f & G_WEIGHTPAINT) {
+ ScrArea *sa= CTX_wm_area(C);
+ if(sa->spacetype==SPACE_VIEW3D) {
+ ARegion *ar= CTX_wm_region(C);
+ if(ar->regiontype==RGN_TYPE_WINDOW)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/* Cursors */
+static void vp_drawcursor(bContext *C, int x, int y, void *customdata)
+{
+ ToolSettings *ts= CTX_data_tool_settings(C);
+
+ glTranslatef((float)x, (float)y, 0.0f);
+
+ glColor4ub(255, 255, 255, 128);
+ glEnable( GL_LINE_SMOOTH );
+ glEnable(GL_BLEND);
+ glutil_draw_lined_arc(0.0, M_PI*2.0, ts->vpaint->brush->size, 40);
+ glDisable(GL_BLEND);
+ glDisable( GL_LINE_SMOOTH );
+
+ glTranslatef((float)-x, (float)-y, 0.0f);
+}
+
+static void wp_drawcursor(bContext *C, int x, int y, void *customdata)
+{
+ ToolSettings *ts= CTX_data_tool_settings(C);
+
+ glTranslatef((float)x, (float)y, 0.0f);
+
+ glColor4ub(200, 200, 255, 128);
+ glEnable( GL_LINE_SMOOTH );
+ glEnable(GL_BLEND);
+ glutil_draw_lined_arc(0.0, M_PI*2.0, ts->wpaint->brush->size, 40);
+ glDisable(GL_BLEND);
+ glDisable( GL_LINE_SMOOTH );
+
+ glTranslatef((float)-x, (float)-y, 0.0f);
+}
+
+static void toggle_paint_cursor(bContext *C, int wpaint)
+{
+ ToolSettings *ts = CTX_data_scene(C)->toolsettings;
+ VPaint *vp = wpaint ? ts->wpaint : ts->vpaint;
+
+ if(vp->paintcursor) {
+ WM_paint_cursor_end(CTX_wm_manager(C), vp->paintcursor);
+ vp->paintcursor = NULL;
+ }
+ else {
+ vp->paintcursor = wpaint ?
+ WM_paint_cursor_activate(CTX_wm_manager(C), wp_poll, wp_drawcursor, NULL) :
+ WM_paint_cursor_activate(CTX_wm_manager(C), vp_poll, vp_drawcursor, NULL);
+ }
+}
+
+static VPaint *new_vpaint(int wpaint)
+{
+ VPaint *vp= MEM_callocN(sizeof(VPaint), "VPaint");
+
+ vp->gamma= vp->mul= 1.0f;
+
+ vp->flag= VP_AREA+VP_SOFT+VP_SPRAY;
+
+ if(wpaint)
+ vp->flag= VP_AREA+VP_SOFT;
+
+ return vp;
+}
+
+static int *get_indexarray(void)
+{
+ return MEM_mallocN(sizeof(int)*MAXINDEX + 2, "vertexpaint");
+}
+
+
+/* in contradiction to cpack drawing colors, the MCOL colors (vpaint colors) are per byte!
+ so not endian sensitive. Mcol = ABGR!!! so be cautious with cpack calls */
+
+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;
+
+}
+
+static unsigned int vpaint_get_current_col(VPaint *vp)
+{
+ return rgba_to_mcol(vp->brush->rgb[0], vp->brush->rgb[1], vp->brush->rgb[2], 1.0f);
+}
+
+void do_shared_vertexcol(Mesh *me)
+{
+ /* if no mcol: do not do */
+ /* if tface: only the involved faces, otherwise all */
+ MFace *mface;
+ MTFace *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->mtface;
+ mface= me->mface;
+ mcol= (char *)me->mcol;
+ for(a=me->totface; a>0; a--, mface++, mcol+=16) {
+ if((tface && 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->mtface;
+ mface= me->mface;
+ mcol= (char *)me->mcol;
+ for(a=me->totface; a>0; a--, mface++, mcol+=16) {
+ if((tface && 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(Scene *scene, int shade) /* single ob */
+{
+ Object *ob;
+ Mesh *me;
+
+ if(scene->obedit) {
+ error("Unable to perform function in Edit Mode");
+ return;
+ }
+
+ ob= OBACT;
+ if(!ob || ob->id.lib) return;
+ me= get_mesh(ob);
+ if(me==0) return;
+
+ /* copies from shadedisplist to mcol */
+ if(!me->mcol) {
+ CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface);
+ mesh_update_customdata_pointers(me);
+ }
+
+ if(shade)
+ shadeMeshMCol(scene, ob, me);
+ else
+ memset(me->mcol, 255, 4*sizeof(MCol)*me->totface);
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+}
+
+static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot)
+{
+ if(vp->vpaint_prev) {
+ MEM_freeN(vp->vpaint_prev);
+ vp->vpaint_prev= NULL;
+ }
+ vp->tot= tot;
+
+ if(mcol==NULL || tot==0) return;
+
+ vp->vpaint_prev= MEM_mallocN(4*sizeof(int)*tot, "vpaint_prev");
+ memcpy(vp->vpaint_prev, mcol, 4*sizeof(int)*tot);
+
+}
+
+static void copy_wpaint_prev (VPaint *wp, MDeformVert *dverts, int dcount)
+{
+ if (wp->wpaint_prev) {
+ free_dverts(wp->wpaint_prev, wp->tot);
+ wp->wpaint_prev= NULL;
+ }
+
+ if(dverts && dcount) {
+
+ wp->wpaint_prev = MEM_mallocN (sizeof(MDeformVert)*dcount, "wpaint prev");
+ wp->tot = dcount;
+ copy_dverts (wp->wpaint_prev, dverts, dcount);
+ }
+}
+
+
+void clear_vpaint(Scene *scene)
+{
+ Mesh *me;
+ Object *ob;
+ unsigned int *to, paintcol;
+ int a;
+
+ if((G.f & G_VERTEXPAINT)==0) return;
+
+ ob= OBACT;
+ me= get_mesh(ob);
+ if(!ob || ob->id.lib) return;
+
+ if(me==0 || me->mcol==0 || me->totface==0) return;
+
+ paintcol= vpaint_get_current_col(scene->toolsettings->vpaint);
+
+ to= (unsigned int *)me->mcol;
+ a= 4*me->totface;
+ while(a--) {
+ *to= paintcol;
+ to++;
+ }
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+}
+
+void clear_vpaint_selectedfaces(Scene *scene)
+{
+ Mesh *me;
+ MFace *mf;
+ Object *ob;
+ unsigned int paintcol, *mcol;
+ int i;
+
+ ob= OBACT;
+ me= get_mesh(ob);
+ if(me==0 || me->totface==0) return;
+
+ if(!me->mcol)
+ make_vertexcol(scene, 0);
+
+ paintcol= vpaint_get_current_col(scene->toolsettings->vpaint);
+
+ mf = me->mface;
+ mcol = (unsigned int*)me->mcol;
+ for (i = 0; i < me->totface; i++, mf++, mcol+=4) {
+ if (mf->flag & ME_FACE_SEL) {
+ mcol[0] = paintcol;
+ mcol[1] = paintcol;
+ mcol[2] = paintcol;
+ mcol[3] = paintcol;
+ }
+ }
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+}
+
+
+/* fills in the selected faces with the current weight and vertex group */
+void clear_wpaint_selectedfaces(Scene *scene)
+{
+ VPaint *wp= scene->toolsettings->wpaint;
+ float paintweight= wp->brush->alpha;
+ Mesh *me;
+ MFace *mface;
+ Object *ob;
+ MDeformWeight *dw, *uw;
+ int *indexar;
+ int index, vgroup;
+ unsigned int faceverts[5]={0,0,0,0,0};
+ unsigned char i;
+ int vgroup_mirror= -1;
+
+ ob= OBACT;
+ me= ob->data;
+ if(me==0 || me->totface==0 || me->dvert==0 || !me->mface) return;
+
+ indexar= get_indexarray();
+ for(index=0, mface=me->mface; index<me->totface; index++, mface++) {
+ if((mface->flag & ME_FACE_SEL)==0)
+ indexar[index]= 0;
+ else
+ indexar[index]= index+1;
+ }
+
+ vgroup= ob->actdef-1;
+
+ /* directly copied from weight_paint, should probaby split into a seperate function */
+ /* if mirror painting, find the other group */
+ if(wp->flag & VP_MIRROR_X) {
+ bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1);
+ if(defgroup) {
+ bDeformGroup *curdef;
+ int actdef= 0;
+ char name[32];
+
+ BLI_strncpy(name, defgroup->name, 32);
+ bone_flip_name(name, 0); /* 0 = don't strip off number extensions */
+
+ for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++)
+ if (!strcmp(curdef->name, name))
+ break;
+ if(curdef==NULL) {
+ int olddef= ob->actdef; /* tsk, add_defgroup sets the active defgroup */
+ curdef= add_defgroup_name (ob, name);
+ ob->actdef= olddef;
+ }
+
+ if(curdef && curdef!=defgroup)
+ vgroup_mirror= actdef;
+ }
+ }
+ /* end copy from weight_paint*/
+
+ copy_wpaint_prev(wp, me->dvert, me->totvert);
+
+ for(index=0; index<me->totface; index++) {
+ if(indexar[index] && indexar[index]<=me->totface) {
+ mface= me->mface + (indexar[index]-1);
+ /* just so we can loop through the verts */
+ faceverts[0]= mface->v1;
+ faceverts[1]= mface->v2;
+ faceverts[2]= mface->v3;
+ faceverts[3]= mface->v4;
+ for (i=0; i<3 || faceverts[i]; i++) {
+ if(!((me->dvert+faceverts[i])->flag)) {
+ dw= verify_defweight(me->dvert+faceverts[i], vgroup);
+ if(dw) {
+ uw= verify_defweight(wp->wpaint_prev+faceverts[i], vgroup);
+ uw->weight= dw->weight; /* set the undo weight */
+ dw->weight= paintweight;
+
+ if(wp->flag & VP_MIRROR_X) { /* x mirror painting */
+ int j= mesh_get_x_mirror_vert(ob, faceverts[i]);
+ if(j>=0) {
+ /* copy, not paint again */
+ if(vgroup_mirror != -1) {
+ dw= verify_defweight(me->dvert+j, vgroup_mirror);
+ uw= verify_defweight(wp->wpaint_prev+j, vgroup_mirror);
+ } else {
+ dw= verify_defweight(me->dvert+j, vgroup);
+ uw= verify_defweight(wp->wpaint_prev+j, vgroup);
+ }
+ uw->weight= dw->weight; /* set the undo weight */
+ dw->weight= paintweight;
+ }
+ }
+ }
+ (me->dvert+faceverts[i])->flag= 1;
+ }
+ }
+ }
+ }
+
+ index=0;
+ while (index<me->totvert) {
+ (me->dvert+index)->flag= 0;
+ index++;
+ }
+
+ MEM_freeN(indexar);
+ copy_wpaint_prev(wp, NULL, 0);
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+}
+
+
+void vpaint_dogamma(Scene *scene)
+{
+ VPaint *vp= scene->toolsettings->vpaint;
+ Mesh *me;
+ Object *ob;
+ float igam, fac;
+ int a, temp;
+ unsigned char *cp, gamtab[256];
+
+ if((G.f & G_VERTEXPAINT)==0) return;
+
+ ob= OBACT;
+ me= get_mesh(ob);
+ if(me==0 || me->mcol==0 || me->totface==0) return;
+
+ igam= 1.0/vp->gamma;
+ for(a=0; a<256; a++) {
+
+ fac= ((float)a)/255.0;
+ fac= vp->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= (unsigned char *)me->mcol;
+ while(a--) {
+
+ cp[1]= gamtab[ cp[1] ];
+ cp[2]= gamtab[ cp[2] ];
+ cp[3]= gamtab[ cp[3] ];
+
+ cp+= 4;
+ }
+}
+
+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])/255;
+ cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
+ cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
+
+ 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])/255);
+ if(temp>254) cp[1]= 255; else cp[1]= temp;
+ temp= cp1[2] + ((fac*cp2[2])/255);
+ if(temp>254) cp[2]= 255; else cp[2]= temp;
+ temp= cp1[3] + ((fac*cp2[3])/255);
+ 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])/255);
+ if(temp<0) cp[1]= 0; else cp[1]= temp;
+ temp= cp1[2] - ((fac*cp2[2])/255);
+ if(temp<0) cp[2]= 0; else cp[2]= temp;
+ temp= cp1[3] - ((fac*cp2[3])/255);
+ 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;
+
+ /* first mul, then blend the fac */
+ cp[0]= 255;
+ cp[1]= (mfac*cp1[1] + fac*((cp2[1]*cp1[1])/255) )/255;
+ cp[2]= (mfac*cp1[2] + fac*((cp2[2]*cp1[2])/255) )/255;
+ cp[3]= (mfac*cp1[3] + fac*((cp2[3]*cp1[3])/255) )/255;
+
+
+ return col;
+}
+
+static unsigned int mcol_lighten(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;
+
+ /* See if are lighter, if so mix, else dont do anything.
+ if the paint col is darker then the original, then ignore */
+ if (cp1[1]+cp1[2]+cp1[3] > cp2[1]+cp2[2]+cp2[3])
+ return col1;
+
+ cp[0]= 255;
+ cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
+ cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
+ cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
+
+ return col;
+}
+
+static unsigned int mcol_darken(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;
+
+ /* See if were darker, if so mix, else dont do anything.
+ if the paint col is brighter then the original, then ignore */
+ if (cp1[1]+cp1[2]+cp1[3] < cp2[1]+cp2[2]+cp2[3])
+ return col1;
+
+ cp[0]= 255;
+ cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
+ cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
+ cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
+ return col;
+}
+
+static void vpaint_blend(VPaint *vp, unsigned int *col, unsigned int *colorig, unsigned int paintcol, int alpha)
+{
+
+ if(vp->mode==VP_MIX || vp->mode==VP_BLUR) *col= mcol_blend( *col, paintcol, alpha);
+ else if(vp->mode==VP_ADD) *col= mcol_add( *col, paintcol, alpha);
+ else if(vp->mode==VP_SUB) *col= mcol_sub( *col, paintcol, alpha);
+ else if(vp->mode==VP_MUL) *col= mcol_mul( *col, paintcol, alpha);
+ else if(vp->mode==VP_LIGHTEN) *col= mcol_lighten( *col, paintcol, alpha);
+ else if(vp->mode==VP_DARKEN) *col= mcol_darken( *col, paintcol, alpha);
+
+ /* if no spray, clip color adding with colorig & orig alpha */
+ if((vp->flag & VP_SPRAY)==0) {
+ unsigned int testcol=0, a;
+ char *cp, *ct, *co;
+
+ alpha= (int)(255.0*vp->brush->alpha);
+
+ if(vp->mode==VP_MIX || vp->mode==VP_BLUR) testcol= mcol_blend( *colorig, paintcol, alpha);
+ else if(vp->mode==VP_ADD) testcol= mcol_add( *colorig, paintcol, alpha);
+ else if(vp->mode==VP_SUB) testcol= mcol_sub( *colorig, paintcol, alpha);
+ else if(vp->mode==VP_MUL) testcol= mcol_mul( *colorig, paintcol, alpha);
+ else if(vp->mode==VP_LIGHTEN) testcol= mcol_lighten( *colorig, paintcol, alpha);
+ else if(vp->mode==VP_DARKEN) testcol= mcol_darken( *colorig, paintcol, alpha);
+
+ cp= (char *)col;
+ ct= (char *)&testcol;
+ co= (char *)colorig;
+
+ for(a=0; a<4; a++) {
+ if( ct[a]<co[a] ) {
+ if( cp[a]<ct[a] ) cp[a]= ct[a];
+ else if( cp[a]>co[a] ) cp[a]= co[a];
+ }
+ else {
+ if( cp[a]<co[a] ) cp[a]= co[a];
+ else if( cp[a]>ct[a] ) cp[a]= ct[a];
+ }
+ }
+ }
+}
+
+
+static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x, int y, float size)
+{
+ struct ImBuf *ibuf;
+ int a, tot=0, index;
+
+ if(totface+4>=MAXINDEX) return 0;
+
+ if(size>64.0) size= 64.0;
+
+ ibuf= view3d_read_backbuf(vc, x-size, y-size, x+size, y+size);
+ if(ibuf) {
+ unsigned int *rt= ibuf->rect;
+
+ memset(indexar, 0, sizeof(int)*totface+4); /* plus 2! first element is total, +2 was giving valgrind errors, +4 seems ok */
+
+ size= ibuf->x*ibuf->y;
+ while(size--) {
+
+ if(*rt) {
+ index= WM_framebuffer_to_index(*rt);
+ if(index>0 && index<=totface)
+ indexar[index] = 1;
+ }
+
+ rt++;
+ }
+
+ for(a=1; a<=totface; a++) {
+ if(indexar[a]) indexar[tot++]= a;
+ }
+
+ IMB_freeImBuf(ibuf);
+ }
+
+ return tot;
+}
+
+static int calc_vp_alpha_dl(VPaint *vp, ViewContext *vc, float vpimat[][3], float *vert_nor, short *mval)
+{
+ float fac, dx, dy;
+ int alpha;
+ short vertco[2];
+
+ if(vp->flag & VP_SOFT) {
+ project_short_noclip(vc->ar, vert_nor, vertco);
+ dx= mval[0]-vertco[0];
+ dy= mval[1]-vertco[1];
+
+ fac= sqrt(dx*dx + dy*dy);
+ if(fac > vp->brush->size) return 0;
+ if(vp->flag & VP_HARD)
+ alpha= 255;
+ else
+ alpha= 255.0*vp->brush->alpha*(1.0-fac/vp->brush->size);
+ }
+ else {
+ alpha= 255.0*vp->brush->alpha;
+ }
+
+ if(vp->flag & VP_NORMALS) {
+ float *no= vert_nor+3;
+
+ /* transpose ! */
+ fac= vpimat[2][0]*no[0]+vpimat[2][1]*no[1]+vpimat[2][2]*no[2];
+ if(fac>0.0) {
+ dx= vpimat[0][0]*no[0]+vpimat[0][1]*no[1]+vpimat[0][2]*no[2];
+ dy= vpimat[1][0]*no[0]+vpimat[1][1]*no[1]+vpimat[1][2]*no[2];
+
+ alpha*= fac/sqrt(dx*dx + dy*dy + fac*fac);
+ }
+ else return 0;
+ }
+
+ return alpha;
+}
+
+static void wpaint_blend(VPaint *wp, MDeformWeight *dw, MDeformWeight *uw, float alpha, float paintval)
+{
+
+ if(dw==NULL || uw==NULL) return;
+
+ if(wp->mode==VP_MIX || wp->mode==VP_BLUR)
+ dw->weight = paintval*alpha + dw->weight*(1.0-alpha);
+ else if(wp->mode==VP_ADD)
+ dw->weight += paintval*alpha;
+ else if(wp->mode==VP_SUB)
+ dw->weight -= paintval*alpha;
+ else if(wp->mode==VP_MUL)
+ /* first mul, then blend the fac */
+ dw->weight = ((1.0-alpha) + alpha*paintval)*dw->weight;
+ else if(wp->mode==VP_LIGHTEN) {
+ if (dw->weight < paintval)
+ dw->weight = paintval*alpha + dw->weight*(1.0-alpha);
+ } else if(wp->mode==VP_DARKEN) {
+ if (dw->weight > paintval)
+ dw->weight = paintval*alpha + dw->weight*(1.0-alpha);
+ }
+ CLAMP(dw->weight, 0.0f, 1.0f);
+
+ /* if no spray, clip result with orig weight & orig alpha */
+ if((wp->flag & VP_SPRAY)==0) {
+ float testw=0.0f;
+
+ alpha= wp->brush->alpha;
+ if(wp->mode==VP_MIX || wp->mode==VP_BLUR)
+ testw = paintval*alpha + uw->weight*(1.0-alpha);
+ else if(wp->mode==VP_ADD)
+ testw = uw->weight + paintval*alpha;
+ else if(wp->mode==VP_SUB)
+ testw = uw->weight - paintval*alpha;
+ else if(wp->mode==VP_MUL)
+ /* first mul, then blend the fac */
+ testw = ((1.0-alpha) + alpha*paintval)*uw->weight;
+ else if(wp->mode==VP_LIGHTEN) {
+ if (uw->weight < paintval)
+ testw = paintval*alpha + uw->weight*(1.0-alpha);
+ else
+ testw = uw->weight;
+ } else if(wp->mode==VP_DARKEN) {
+ if (uw->weight > paintval)
+ testw = paintval*alpha + uw->weight*(1.0-alpha);
+ else
+ testw = uw->weight;
+ }
+ CLAMP(testw, 0.0f, 1.0f);
+
+ if( testw<uw->weight ) {
+ if(dw->weight < testw) dw->weight= testw;
+ else if(dw->weight > uw->weight) dw->weight= uw->weight;
+ }
+ else {
+ if(dw->weight > testw) dw->weight= testw;
+ else if(dw->weight < uw->weight) dw->weight= uw->weight;
+ }
+ }
+
+}
+
+/* ----------------------------------------------------- */
+
+/* used for 3d view, on active object, assumes me->dvert exists */
+/* if mode==1: */
+/* samples cursor location, and gives menu with vertex groups to activate */
+/* else */
+/* sets wp->weight to the closest weight value to vertex */
+/* note: we cant sample frontbuf, weight colors are interpolated too unpredictable */
+void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode)
+{
+ ViewContext vc;
+ VPaint *wp= scene->toolsettings->wpaint;
+ Object *ob= OBACT;
+ Mesh *me= get_mesh(ob);
+ int index;
+ short mval[2], sco[2];
+
+ if (!me) return;
+
+// getmouseco_areawin(mval);
+ index= view3d_sample_backbuf(&vc, mval[0], mval[1]);
+
+ if(index && index<=me->totface) {
+ MFace *mface;
+
+ mface= ((MFace *)me->mface) + index-1;
+
+ if(mode==1) { /* sampe which groups are in here */
+ MDeformVert *dv;
+ int a, totgroup;
+
+ totgroup= BLI_countlist(&ob->defbase);
+ if(totgroup) {
+ int totmenu=0;
+ int *groups=MEM_callocN(totgroup*sizeof(int), "groups");
+
+ dv= me->dvert+mface->v1;
+ for(a=0; a<dv->totweight; a++) {
+ if (dv->dw[a].def_nr<totgroup)
+ groups[dv->dw[a].def_nr]= 1;
+ }
+ dv= me->dvert+mface->v2;
+ for(a=0; a<dv->totweight; a++) {
+ if (dv->dw[a].def_nr<totgroup)
+ groups[dv->dw[a].def_nr]= 1;
+ }
+ dv= me->dvert+mface->v3;
+ for(a=0; a<dv->totweight; a++) {
+ if (dv->dw[a].def_nr<totgroup)
+ groups[dv->dw[a].def_nr]= 1;
+ }
+ if(mface->v4) {
+ dv= me->dvert+mface->v4;
+ for(a=0; a<dv->totweight; a++) {
+ if (dv->dw[a].def_nr<totgroup)
+ groups[dv->dw[a].def_nr]= 1;
+ }
+ }
+ for(a=0; a<totgroup; a++)
+ if(groups[a]) totmenu++;
+
+ if(totmenu==0) {
+ //notice("No Vertex Group Selected");
+ }
+ else {
+ bDeformGroup *dg;
+ short val;
+ char item[40], *str= MEM_mallocN(40*totmenu+40, "menu");
+
+ strcpy(str, "Vertex Groups %t");
+ for(a=0, dg=ob->defbase.first; dg && a<totgroup; a++, dg= dg->next) {
+ if(groups[a]) {
+ sprintf(item, "|%s %%x%d", dg->name, a);
+ strcat(str, item);
+ }
+ }
+
+ val= 0; // XXX pupmenu(str);
+ if(val>=0) {
+ ob->actdef= val+1;
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+ MEM_freeN(str);
+ }
+ MEM_freeN(groups);
+ }
+// else notice("No Vertex Groups in Object");
+ }
+ else {
+ DerivedMesh *dm;
+ MDeformWeight *dw;
+ float w1, w2, w3, w4, co[3], fac;
+
+ dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ if(dm->getVertCo==NULL) {
+ //notice("Not supported yet");
+ }
+ else {
+ /* calc 3 or 4 corner weights */
+ dm->getVertCo(dm, mface->v1, co);
+ project_short_noclip(ar, co, sco);
+ w1= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
+
+ dm->getVertCo(dm, mface->v2, co);
+ project_short_noclip(ar, co, sco);
+ w2= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
+
+ dm->getVertCo(dm, mface->v3, co);
+ project_short_noclip(ar, co, sco);
+ w3= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
+
+ if(mface->v4) {
+ dm->getVertCo(dm, mface->v4, co);
+ project_short_noclip(ar, co, sco);
+ w4= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
+ }
+ else w4= 1.0e10;
+
+ fac= MIN4(w1, w2, w3, w4);
+ if(w1==fac) {
+ dw= get_defweight(me->dvert+mface->v1, ob->actdef-1);
+ if(dw) wp->brush->alpha= dw->weight; else wp->brush->alpha= 0.0f;
+ }
+ else if(w2==fac) {
+ dw= get_defweight(me->dvert+mface->v2, ob->actdef-1);
+ if(dw) wp->brush->alpha= dw->weight; else wp->brush->alpha= 0.0f;
+ }
+ else if(w3==fac) {
+ dw= get_defweight(me->dvert+mface->v3, ob->actdef-1);
+ if(dw) wp->brush->alpha= dw->weight; else wp->brush->alpha= 0.0f;
+ }
+ else if(w4==fac) {
+ if(mface->v4) {
+ dw= get_defweight(me->dvert+mface->v4, ob->actdef-1);
+ if(dw) wp->brush->alpha= dw->weight; else wp->brush->alpha= 0.0f;
+ }
+ }
+ }
+ dm->release(dm);
+ }
+
+ }
+
+}
+
+static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index, int alpha, float paintweight, int vgroup_mirror)
+{
+ Mesh *me= ob->data;
+ MDeformWeight *dw, *uw;
+ int vgroup= ob->actdef-1;
+
+ if(wp->flag & VP_ONLYVGROUP) {
+ dw= get_defweight(me->dvert+index, vgroup);
+ uw= get_defweight(wp->wpaint_prev+index, vgroup);
+ }
+ else {
+ dw= verify_defweight(me->dvert+index, vgroup);
+ uw= verify_defweight(wp->wpaint_prev+index, vgroup);
+ }
+ if(dw==NULL || uw==NULL)
+ return;
+
+ wpaint_blend(wp, dw, uw, (float)alpha/255.0, paintweight);
+
+ if(wp->flag & VP_MIRROR_X) { /* x mirror painting */
+ int j= mesh_get_x_mirror_vert(ob, index);
+ if(j>=0) {
+ /* copy, not paint again */
+ if(vgroup_mirror != -1)
+ uw= verify_defweight(me->dvert+j, vgroup_mirror);
+ else
+ uw= verify_defweight(me->dvert+j, vgroup);
+
+ uw->weight= dw->weight;
+ }
+ }
+}
+
+
+/* *************** set wpaint operator ****************** */
+
+static int set_wpaint(bContext *C, wmOperator *op) /* toggle */
+{
+ Object *ob= CTX_data_active_object(C);
+ Scene *scene= CTX_data_scene(C);
+ VPaint *wp= scene->toolsettings->wpaint;
+ Mesh *me;
+
+ me= get_mesh(ob);
+ if(ob->id.lib || me==NULL) return OPERATOR_CANCELLED;
+
+ if(me && me->totface>=MAXINDEX) {
+ error("Maximum number of faces: %d", MAXINDEX-1);
+ G.f &= ~G_WEIGHTPAINT;
+ return OPERATOR_CANCELLED;
+ }
+
+ if(G.f & G_WEIGHTPAINT) G.f &= ~G_WEIGHTPAINT;
+ else G.f |= G_WEIGHTPAINT;
+
+
+ /* Weightpaint works by overriding colors in mesh,
+ * so need to make sure we recalc on enter and
+ * exit (exit needs doing regardless because we
+ * should redeform).
+ */
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+ if(G.f & G_WEIGHTPAINT) {
+ Object *par;
+
+ if(wp==NULL)
+ wp= scene->toolsettings->wpaint= new_vpaint(1);
+
+ brush_check_exists(&wp->brush);
+
+ toggle_paint_cursor(C, 1);
+
+ mesh_octree_table(ob, NULL, NULL, 's');
+
+ /* verify if active weight group is also active bone */
+ par= modifiers_isDeformedByArmature(ob);
+ if(par && (par->flag & OB_POSEMODE)) {
+ bPoseChannel *pchan;
+ for(pchan= par->pose->chanbase.first; pchan; pchan= pchan->next)
+ if(pchan->bone->flag & BONE_ACTIVE)
+ break;
+ if(pchan)
+ vertexgroup_select_by_name(ob, pchan->name);
+ }
+ }
+ else {
+ if(wp)
+ toggle_paint_cursor(C, 1);
+
+ mesh_octree_table(ob, NULL, NULL, 'e');
+ }
+
+ WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+/* for switching to/from mode */
+static int paint_poll_test(bContext *C)
+{
+ if(ED_operator_view3d_active(C)==0)
+ return 0;
+ if(CTX_data_edit_object(C))
+ return 0;
+ if(CTX_data_active_object(C)==NULL)
+ return 0;
+ return 1;
+}
+
+void PAINT_OT_weight_paint_toggle(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Weight Paint Mode";
+ ot->idname= "PAINT_OT_weight_paint_toggle";
+
+ /* api callbacks */
+ ot->exec= set_wpaint;
+ ot->poll= paint_poll_test;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+
+/* ************ paint radial controls *************/
+
+static int vpaint_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ toggle_paint_cursor(C, 0);
+ brush_radial_control_invoke(op, CTX_data_scene(C)->toolsettings->vpaint->brush, 1);
+ return WM_radial_control_invoke(C, op, event);
+}
+
+static int vpaint_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ int ret = WM_radial_control_modal(C, op, event);
+ if(ret != OPERATOR_RUNNING_MODAL)
+ toggle_paint_cursor(C, 0);
+ return ret;
+}
+
+static int vpaint_radial_control_exec(bContext *C, wmOperator *op)
+{
+ return brush_radial_control_exec(op, CTX_data_scene(C)->toolsettings->vpaint->brush, 1);
+}
+
+static int wpaint_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ toggle_paint_cursor(C, 1);
+ brush_radial_control_invoke(op, CTX_data_scene(C)->toolsettings->wpaint->brush, 1);
+ return WM_radial_control_invoke(C, op, event);
+}
+
+static int wpaint_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ int ret = WM_radial_control_modal(C, op, event);
+ if(ret != OPERATOR_RUNNING_MODAL)
+ toggle_paint_cursor(C, 1);
+ return ret;
+}
+
+static int wpaint_radial_control_exec(bContext *C, wmOperator *op)
+{
+ return brush_radial_control_exec(op, CTX_data_scene(C)->toolsettings->wpaint->brush, 1);
+}
+
+void PAINT_OT_weight_paint_radial_control(wmOperatorType *ot)
+{
+ WM_OT_radial_control_partial(ot);
+
+ ot->name= "Weight Paint Radial Control";
+ ot->idname= "PAINT_OT_weight_paint_radial_control";
+
+ ot->invoke= wpaint_radial_control_invoke;
+ ot->modal= wpaint_radial_control_modal;
+ ot->exec= wpaint_radial_control_exec;
+ ot->poll= wp_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+void PAINT_OT_vertex_paint_radial_control(wmOperatorType *ot)
+{
+ WM_OT_radial_control_partial(ot);
+
+ ot->name= "Vertex Paint Radial Control";
+ ot->idname= "PAINT_OT_vertex_paint_radial_control";
+
+ ot->invoke= vpaint_radial_control_invoke;
+ ot->modal= vpaint_radial_control_modal;
+ ot->exec= vpaint_radial_control_exec;
+ ot->poll= vp_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ************ weight paint operator ********** */
+
+struct WPaintData {
+ ViewContext vc;
+ int *indexar;
+ int vgroup_mirror;
+ float *vertexcosnos;
+ float wpimat[3][3];
+};
+
+static void wpaint_exit(bContext *C, wmOperator *op)
+{
+ ToolSettings *ts= CTX_data_tool_settings(C);
+ Object *ob= CTX_data_active_object(C);
+ struct WPaintData *wpd= op->customdata;
+
+ if(wpd->vertexcosnos)
+ MEM_freeN(wpd->vertexcosnos);
+ MEM_freeN(wpd->indexar);
+
+ /* frees prev buffer */
+ copy_wpaint_prev(ts->wpaint, NULL, 0);
+
+ /* and particles too */
+ if(ob->particlesystem.first) {
+ ParticleSystem *psys;
+ int i;
+
+ for(psys= ob->particlesystem.first; psys; psys= psys->next) {
+ for(i=0; i<PSYS_TOT_VG; i++) {
+ if(psys->vgroup[i]==ob->actdef) {
+ psys->recalc |= PSYS_RECALC_HAIR;
+ break;
+ }
+ }
+ }
+ }
+
+ DAG_object_flush_update(CTX_data_scene(C), ob, OB_RECALC_DATA);
+
+ MEM_freeN(wpd);
+ op->customdata= NULL;
+}
+
+
+static int wpaint_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ToolSettings *ts= CTX_data_tool_settings(C);
+ VPaint *wp= ts->wpaint;
+
+ switch(event->type) {
+ case LEFTMOUSE:
+ if(event->val==0) { /* release */
+ wpaint_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ /* pass on, first press gets painted too */
+
+ case MOUSEMOVE:
+ {
+ struct WPaintData *wpd= op->customdata;
+ ViewContext *vc= &wpd->vc;
+ Object *ob= vc->obact;
+ Mesh *me= ob->data;
+ float mat[4][4];
+ float paintweight= wp->brush->alpha;
+ int *indexar= wpd->indexar;
+ int totindex, index, alpha, totw;
+ short mval[2];
+
+ view3d_operator_needs_opengl(C);
+
+ /* load projection matrix */
+ wmMultMatrix(ob->obmat);
+ wmGetSingleMatrix(mat);
+ wmLoadMatrix(wpd->vc.rv3d->viewmat);
+
+ MTC_Mat4SwapMat4(wpd->vc.rv3d->persmat, mat);
+
+ mval[0]= event->x - vc->ar->winrct.xmin;
+ mval[1]= event->y - vc->ar->winrct.ymin;
+
+ /* which faces are involved */
+ if(wp->flag & VP_AREA) {
+ totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], wp->brush->size);
+ }
+ else {
+ indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
+ if(indexar[0]) totindex= 1;
+ else totindex= 0;
+ }
+
+ if(wp->flag & VP_COLINDEX) {
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totface) {
+ MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
+
+ if(mface->mat_nr!=ob->actcol-1) {
+ indexar[index]= 0;
+ }
+ }
+ }
+ }
+
+ if((G.f & G_FACESELECT) && me->mface) {
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totface) {
+ MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
+
+ if((mface->flag & ME_FACE_SEL)==0) {
+ indexar[index]= 0;
+ }
+ }
+ }
+ }
+
+ /* make sure each vertex gets treated only once */
+ /* and calculate filter weight */
+ totw= 0;
+ if(wp->mode==VP_BLUR)
+ paintweight= 0.0f;
+ else
+ paintweight= wp->brush->alpha;
+
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totface) {
+ MFace *mface= me->mface + (indexar[index]-1);
+
+ (me->dvert+mface->v1)->flag= 1;
+ (me->dvert+mface->v2)->flag= 1;
+ (me->dvert+mface->v3)->flag= 1;
+ if(mface->v4) (me->dvert+mface->v4)->flag= 1;
+
+ if(wp->mode==VP_BLUR) {
+ MDeformWeight *dw, *(*dw_func)(MDeformVert *, int) = verify_defweight;
+
+ if(wp->flag & VP_ONLYVGROUP)
+ dw_func= get_defweight;
+
+ dw= dw_func(me->dvert+mface->v1, ob->actdef-1);
+ if(dw) {paintweight+= dw->weight; totw++;}
+ dw= dw_func(me->dvert+mface->v2, ob->actdef-1);
+ if(dw) {paintweight+= dw->weight; totw++;}
+ dw= dw_func(me->dvert+mface->v3, ob->actdef-1);
+ if(dw) {paintweight+= dw->weight; totw++;}
+ if(mface->v4) {
+ dw= dw_func(me->dvert+mface->v4, ob->actdef-1);
+ if(dw) {paintweight+= dw->weight; totw++;}
+ }
+ }
+ }
+ }
+
+ if(wp->mode==VP_BLUR)
+ paintweight/= (float)totw;
+
+ for(index=0; index<totindex; index++) {
+
+ if(indexar[index] && indexar[index]<=me->totface) {
+ MFace *mface= me->mface + (indexar[index]-1);
+
+ if((me->dvert+mface->v1)->flag) {
+ alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v1, mval);
+ if(alpha) {
+ do_weight_paint_vertex(wp, ob, mface->v1, alpha, paintweight, wpd->vgroup_mirror);
+ }
+ (me->dvert+mface->v1)->flag= 0;
+ }
+
+ if((me->dvert+mface->v2)->flag) {
+ alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v2, mval);
+ if(alpha) {
+ do_weight_paint_vertex(wp, ob, mface->v2, alpha, paintweight, wpd->vgroup_mirror);
+ }
+ (me->dvert+mface->v2)->flag= 0;
+ }
+
+ if((me->dvert+mface->v3)->flag) {
+ alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v3, mval);
+ if(alpha) {
+ do_weight_paint_vertex(wp, ob, mface->v3, alpha, paintweight, wpd->vgroup_mirror);
+ }
+ (me->dvert+mface->v3)->flag= 0;
+ }
+
+ if((me->dvert+mface->v4)->flag) {
+ if(mface->v4) {
+ alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v4, mval);
+ if(alpha) {
+ do_weight_paint_vertex(wp, ob, mface->v4, alpha, paintweight, wpd->vgroup_mirror);
+ }
+ (me->dvert+mface->v4)->flag= 0;
+ }
+ }
+ }
+ }
+
+ MTC_Mat4SwapMat4(vc->rv3d->persmat, mat);
+
+ DAG_object_flush_update(vc->scene, ob, OB_RECALC_DATA);
+ ED_region_tag_redraw(vc->ar);
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Scene *scene= CTX_data_scene(C);
+ ToolSettings *ts= CTX_data_tool_settings(C);
+ VPaint *wp= ts->wpaint;
+ Object *ob= CTX_data_active_object(C);
+ struct WPaintData *wpd;
+ Mesh *me;
+ float mat[4][4], imat[4][4];
+
+ if(scene->obedit) return OPERATOR_CANCELLED;
+ // XXX if(multires_level1_test()) return;
+
+ me= get_mesh(ob);
+ if(me==NULL || me->totface==0) return OPERATOR_CANCELLED;
+
+ /* if nothing was added yet, we make dverts and a vertex deform group */
+ if (!me->dvert)
+ create_dverts(&me->id);
+
+ /* make customdata storage */
+ op->customdata= wpd= MEM_callocN(sizeof(struct WPaintData), "WPaintData");
+ view3d_set_viewcontext(C, &wpd->vc);
+ wpd->vgroup_mirror= -1;
+
+ // if(qual & LR_CTRLKEY) {
+ // sample_wpaint(scene, ar, v3d, 0);
+ // return;
+ // }
+ // if(qual & LR_SHIFTKEY) {
+ // sample_wpaint(scene, ar, v3d, 1);
+ // return;
+ // }
+
+ /* ALLOCATIONS! no return after this line */
+ /* painting on subsurfs should give correct points too, this returns me->totvert amount */
+ wpd->vertexcosnos= mesh_get_mapped_verts_nors(scene, ob);
+ wpd->indexar= get_indexarray();
+ copy_wpaint_prev(wp, me->dvert, me->totvert);
+
+ /* this happens on a Bone select, when no vgroup existed yet */
+ if(ob->actdef<=0) {
+ Object *modob;
+ if((modob = modifiers_isDeformedByArmature(ob))) {
+ bPoseChannel *pchan;
+ for(pchan= modob->pose->chanbase.first; pchan; pchan= pchan->next)
+ if(pchan->bone->flag & SELECT)
+ break;
+ if(pchan) {
+ bDeformGroup *dg= get_named_vertexgroup(ob, pchan->name);
+ if(dg==NULL)
+ dg= add_defgroup_name(ob, pchan->name); /* sets actdef */
+ else
+ ob->actdef= get_defgroup_num(ob, dg);
+ }
+ }
+ }
+ if(ob->defbase.first==NULL) {
+ add_defgroup(ob);
+ }
+
+ // if(ob->lay & v3d->lay); else error("Active object is not in this layer");
+
+ /* imat for normals */
+ Mat4MulMat4(mat, ob->obmat, wpd->vc.rv3d->viewmat);
+ Mat4Invert(imat, mat);
+ Mat3CpyMat4(wpd->wpimat, imat);
+
+ /* if mirror painting, find the other group */
+ if(wp->flag & VP_MIRROR_X) {
+ bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1);
+ if(defgroup) {
+ bDeformGroup *curdef;
+ int actdef= 0;
+ char name[32];
+
+ BLI_strncpy(name, defgroup->name, 32);
+ bone_flip_name(name, 0); /* 0 = don't strip off number extensions */
+
+ for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++)
+ if (!strcmp(curdef->name, name))
+ break;
+ if(curdef==NULL) {
+ int olddef= ob->actdef; /* tsk, add_defgroup sets the active defgroup */
+ curdef= add_defgroup_name (ob, name);
+ ob->actdef= olddef;
+ }
+
+ if(curdef && curdef!=defgroup)
+ wpd->vgroup_mirror= actdef;
+ }
+ }
+
+ /* do paint once for click only paint */
+ wpaint_modal(C, op, event);
+
+ /* add modal handler */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void PAINT_OT_weight_paint(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Weight Paint";
+ ot->idname= "PAINT_OT_weight_paint";
+
+ /* api callbacks */
+ ot->invoke= wpaint_invoke;
+ ot->modal= wpaint_modal;
+ /* ot->exec= vpaint_exec; <-- needs stroke property */
+ ot->poll= wp_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+
+/* ************ set / clear vertex paint mode ********** */
+
+
+static int set_vpaint(bContext *C, wmOperator *op) /* toggle */
+{
+ Object *ob= CTX_data_active_object(C);
+ Scene *scene= CTX_data_scene(C);
+ VPaint *vp= scene->toolsettings->vpaint;
+ Mesh *me;
+
+ me= get_mesh(ob);
+
+ if(me==NULL || object_data_is_libdata(ob)) {
+ G.f &= ~G_VERTEXPAINT;
+ return OPERATOR_FINISHED;
+ }
+
+ if(me && me->totface>=MAXINDEX) {
+ error("Maximum number of faces: %d", MAXINDEX-1);
+ G.f &= ~G_VERTEXPAINT;
+ return OPERATOR_FINISHED;
+ }
+
+ if(me && me->mcol==NULL) make_vertexcol(scene, 0);
+
+ /* toggle: end vpaint */
+ if(G.f & G_VERTEXPAINT) {
+
+ G.f &= ~G_VERTEXPAINT;
+
+ if(vp) {
+ toggle_paint_cursor(C, 0);
+ vp->paintcursor= NULL;
+ }
+ }
+ else {
+
+ G.f |= G_VERTEXPAINT;
+ /* Turn off weight painting */
+ if (G.f & G_WEIGHTPAINT)
+ set_wpaint(C, op);
+
+ if(vp==NULL)
+ vp= scene->toolsettings->vpaint= new_vpaint(0);
+
+ toggle_paint_cursor(C, 0);
+ brush_check_exists(&scene->toolsettings->vpaint->brush);
+ }
+
+ if (me)
+ /* update modifier stack for mapping requirements */
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void PAINT_OT_vertex_paint_toggle(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Vertex Paint Mode";
+ ot->idname= "PAINT_OT_vertex_paint_toggle";
+
+ /* api callbacks */
+ ot->exec= set_vpaint;
+ ot->poll= paint_poll_test;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+
+
+
+/* ********************** vertex paint operator ******************* */
+
+/* Implementation notes:
+
+Operator->invoke()
+ - validate context (add mcol)
+ - create customdata storage
+ - call paint once (mouse click)
+ - add modal handler
+
+Operator->modal()
+ - for every mousemove, apply vertex paint
+ - exit on mouse release, free customdata
+ (return OPERATOR_FINISHED also removes handler and operator)
+
+For future:
+ - implement a stroke event (or mousemove with past positons)
+ - revise whether op->customdata should be added in object, in set_vpaint
+
+*/
+
+struct VPaintData {
+ ViewContext vc;
+ unsigned int paintcol;
+ int *indexar;
+ float *vertexcosnos;
+ float vpimat[3][3];
+};
+
+static void vpaint_exit(bContext *C, wmOperator *op)
+{
+ ToolSettings *ts= CTX_data_tool_settings(C);
+ struct VPaintData *vpd= op->customdata;
+
+ if(vpd->vertexcosnos)
+ MEM_freeN(vpd->vertexcosnos);
+ MEM_freeN(vpd->indexar);
+
+ /* frees prev buffer */
+ copy_vpaint_prev(ts->vpaint, NULL, 0);
+
+ MEM_freeN(vpd);
+ op->customdata= NULL;
+}
+
+static int vpaint_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ToolSettings *ts= CTX_data_tool_settings(C);
+ VPaint *vp= ts->vpaint;
+
+ switch(event->type) {
+ case LEFTMOUSE:
+ if(event->val==0) { /* release */
+ vpaint_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ /* pass on, first press gets painted too */
+
+ case MOUSEMOVE:
+ {
+ struct VPaintData *vpd= op->customdata;
+ ViewContext *vc= &vpd->vc;
+ Object *ob= vc->obact;
+ Mesh *me= ob->data;
+ float mat[4][4];
+ int *indexar= vpd->indexar;
+ int totindex, index;
+ short mval[2];
+
+ view3d_operator_needs_opengl(C);
+
+ /* load projection matrix */
+ wmMultMatrix(ob->obmat);
+ wmGetSingleMatrix(mat);
+ wmLoadMatrix(vc->rv3d->viewmat);
+
+ mval[0]= event->x - vc->ar->winrct.xmin;
+ mval[1]= event->y - vc->ar->winrct.ymin;
+
+ /* which faces are involved */
+ if(vp->flag & VP_AREA) {
+ totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], vp->brush->size);
+ }
+ else {
+ indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
+ if(indexar[0]) totindex= 1;
+ else totindex= 0;
+ }
+
+ MTC_Mat4SwapMat4(vc->rv3d->persmat, mat);
+
+ if(vp->flag & VP_COLINDEX) {
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totface) {
+ MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
+
+ if(mface->mat_nr!=ob->actcol-1) {
+ indexar[index]= 0;
+ }
+ }
+ }
+ }
+ if((G.f & G_FACESELECT) && me->mface) {
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totface) {
+ MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
+
+ if((mface->flag & ME_FACE_SEL)==0)
+ indexar[index]= 0;
+ }
+ }
+ }
+
+ for(index=0; index<totindex; index++) {
+
+ if(indexar[index] && indexar[index]<=me->totface) {
+ MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
+ unsigned int *mcol= ( (unsigned int *)me->mcol) + 4*(indexar[index]-1);
+ unsigned int *mcolorig= ( (unsigned int *)vp->vpaint_prev) + 4*(indexar[index]-1);
+ int alpha;
+
+ if(vp->mode==VP_BLUR) {
+ unsigned int fcol1= mcol_blend( mcol[0], mcol[1], 128);
+ if(mface->v4) {
+ unsigned int fcol2= mcol_blend( mcol[2], mcol[3], 128);
+ vpd->paintcol= mcol_blend( fcol1, fcol2, 128);
+ }
+ else {
+ vpd->paintcol= mcol_blend( mcol[2], fcol1, 170);
+ }
+
+ }
+
+ alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v1, mval);
+ if(alpha) vpaint_blend(vp, mcol, mcolorig, vpd->paintcol, alpha);
+
+ alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v2, mval);
+ if(alpha) vpaint_blend(vp, mcol+1, mcolorig+1, vpd->paintcol, alpha);
+
+ alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v3, mval);
+ if(alpha) vpaint_blend(vp, mcol+2, mcolorig+2, vpd->paintcol, alpha);
+
+ if(mface->v4) {
+ alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v4, mval);
+ if(alpha) vpaint_blend(vp, mcol+3, mcolorig+3, vpd->paintcol, alpha);
+ }
+ }
+ }
+
+ MTC_Mat4SwapMat4(vc->rv3d->persmat, mat);
+
+ do_shared_vertexcol(me);
+
+ ED_region_tag_redraw(vc->ar);
+
+ DAG_object_flush_update(vc->scene, ob, OB_RECALC_DATA);
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ToolSettings *ts= CTX_data_tool_settings(C);
+ VPaint *vp= ts->vpaint;
+ struct VPaintData *vpd;
+ Object *ob= CTX_data_active_object(C);
+ Mesh *me;
+ float mat[4][4], imat[4][4];
+
+ /* context checks could be a poll() */
+ me= get_mesh(ob);
+ if(me==NULL || me->totface==0) return OPERATOR_CANCELLED;
+
+ if(me->mcol==NULL) make_vertexcol(CTX_data_scene(C), 0);
+ if(me->mcol==NULL) return OPERATOR_CANCELLED;
+
+ /* make customdata storage */
+ op->customdata= vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData");
+ view3d_set_viewcontext(C, &vpd->vc);
+
+ vpd->vertexcosnos= mesh_get_mapped_verts_nors(vpd->vc.scene, ob);
+ vpd->indexar= get_indexarray();
+ vpd->paintcol= vpaint_get_current_col(vp);
+
+ /* for filtering */
+ copy_vpaint_prev(vp, (unsigned int *)me->mcol, me->totface);
+
+ /* some old cruft to sort out later */
+ Mat4MulMat4(mat, ob->obmat, vpd->vc.rv3d->viewmat);
+ Mat4Invert(imat, mat);
+ Mat3CpyMat4(vpd->vpimat, imat);
+
+ /* do paint once for click only paint */
+ vpaint_modal(C, op, event);
+
+ /* add modal handler */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void PAINT_OT_vertex_paint(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Vertex Paint";
+ ot->idname= "PAINT_OT_vertex_paint";
+
+ /* api callbacks */
+ ot->invoke= vpaint_invoke;
+ ot->modal= vpaint_modal;
+ /* ot->exec= vpaint_exec; <-- needs stroke property */
+ ot->poll= vp_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
new file mode 100644
index 00000000000..8f1e3826314
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -0,0 +1,2150 @@
+/*
+ * $Id: sculptmode.c 18309 2009-01-04 07:47:11Z nicholasbishop $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 by Nicholas Bishop
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Implements the Sculpt Mode tools
+ *
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_brush_types.h"
+#include "DNA_image_types.h"
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_color_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_key.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_multires.h"
+#include "BKE_sculpt.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+#include "BKE_colortools.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "ED_screen.h"
+#include "ED_sculpt.h"
+#include "ED_space_api.h"
+#include "ED_util.h"
+#include "ED_view3d.h"
+#include "sculpt_intern.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "RE_render_ext.h"
+#include "RE_shader_ext.h" /*for multitex_ext*/
+
+#include "GPU_draw.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Number of vertices to average in order to determine the flatten distance */
+#define FLATTEN_SAMPLE_SIZE 10
+
+/* ===== STRUCTS =====
+ *
+ */
+
+/* ActiveData stores an Index into the mvert array of Mesh, plus Fade, which
+ stores how far the vertex is from the brush center, scaled to the range [0,1]. */
+typedef struct ActiveData {
+ struct ActiveData *next, *prev;
+ unsigned int Index;
+ float Fade;
+ float dist;
+} ActiveData;
+
+typedef enum StrokeFlags {
+ CLIP_X = 1,
+ CLIP_Y = 2,
+ CLIP_Z = 4
+} StrokeFlags;
+
+/* Cache stroke properties. Used because
+ RNA property lookup isn't particularly fast.
+
+ For descriptions of these settings, check the operator properties.
+*/
+typedef struct StrokeCache {
+ /* Invariants */
+ float radius;
+ float scale[3];
+ int flag;
+ float clip_tolerance[3];
+ int initial_mouse[2];
+ float depth;
+
+ /* Variants */
+ float true_location[3];
+ float location[3];
+ float flip;
+ float pressure;
+ int mouse[2];
+
+ /* The rest is temporary storage that isn't saved as a property */
+
+ int first_time; /* Beginning of stroke may do some things special */
+
+ ViewContext vc;
+ bglMats *mats;
+
+ float *layer_disps; /* Displacements for each vertex */
+ float (*mesh_store)[3]; /* Copy of the mesh vertices' locations */
+ short (*orig_norms)[3]; /* Copy of the mesh vertices' normals */
+ float rotation; /* Texture rotation (radians) for anchored and rake modes */
+ int pixel_radius, previous_pixel_radius;
+ ListBase grab_active_verts[8]; /* The same list of verts is used throught grab stroke */
+ float grab_delta[3], grab_delta_symmetry[3];
+ float old_grab_location[3];
+ int symmetry; /* Symmetry index between 0 and 7 */
+ float view_normal[3], view_normal_symmetry[3];
+ int last_dot[2]; /* Last location of stroke application */
+ int last_rake[2]; /* Last location of updating rake rotation */
+} StrokeCache;
+
+typedef struct RectNode {
+ struct RectNode *next, *prev;
+ rcti r;
+} RectNode;
+
+/* Used to store to 2D screen coordinates of each vertex in the mesh. */
+typedef struct ProjVert {
+ short co[2];
+
+ /* Used to mark whether a vertex is inside a rough bounding box
+ containing the brush. */
+ char inside;
+} ProjVert;
+
+/* ===== OPENGL =====
+ *
+ * Simple functions to get data from the GL
+ */
+
+/* Uses window coordinates (x,y) and depth component z to find a point in
+ modelspace */
+static void unproject(bglMats *mats, float out[3], const short x, const short y, const float z)
+{
+ double ux, uy, uz;
+
+ gluUnProject(x,y,z, mats->modelview, mats->projection,
+ (GLint *)mats->viewport, &ux, &uy, &uz );
+ out[0] = ux;
+ out[1] = uy;
+ out[2] = uz;
+}
+
+/* Convert a point in model coordinates to 2D screen coordinates. */
+static void projectf(bglMats *mats, const float v[3], float p[2])
+{
+ double ux, uy, uz;
+
+ gluProject(v[0],v[1],v[2], mats->modelview, mats->projection,
+ (GLint *)mats->viewport, &ux, &uy, &uz);
+ p[0]= ux;
+ p[1]= uy;
+}
+
+static void project(bglMats *mats, const float v[3], short p[2])
+{
+ float f[2];
+ projectf(mats, v, f);
+
+ p[0]= f[0];
+ p[1]= f[1];
+}
+
+/* ===== Sculpting =====
+ *
+ */
+
+/* Return modified brush size. Uses current tablet pressure (if available) to
+ shrink the brush. Skipped for grab brush because only the first mouse down
+ size is used, which is small if the user has just touched the pen to the
+ tablet */
+static char brush_size(Sculpt *sd)
+{
+ float size= sd->brush->size;
+
+ if((sd->brush->sculpt_tool != SCULPT_TOOL_GRAB) && (sd->brush->flag & BRUSH_SIZE_PRESSURE))
+ size *= sd->session->cache->pressure;
+
+ return size;
+}
+
+/* Return modified brush strength. Includes the direction of the brush, positive
+ values pull vertices, negative values push. Uses tablet pressure and a
+ special multiplier found experimentally to scale the strength factor. */
+static float brush_strength(Sculpt *sd, StrokeCache *cache)
+{
+ float dir= sd->brush->flag & BRUSH_DIR_IN ? -1 : 1;
+ float pressure= 1;
+ float flip= cache->flip ? -1:1;
+ float anchored = sd->brush->flag & BRUSH_ANCHORED ? 25 : 1;
+
+ if(sd->brush->flag & BRUSH_ALPHA_PRESSURE)
+ pressure *= cache->pressure;
+
+ switch(sd->brush->sculpt_tool){
+ case SCULPT_TOOL_DRAW:
+ case SCULPT_TOOL_LAYER:
+ return sd->brush->alpha / 50.0f * dir * pressure * flip * anchored; /*XXX: not sure why? multiplied by G.vd->grid */;
+ case SCULPT_TOOL_SMOOTH:
+ return sd->brush->alpha / .5 * pressure * anchored;
+ case SCULPT_TOOL_PINCH:
+ return sd->brush->alpha / 10.0f * dir * pressure * flip * anchored;
+ case SCULPT_TOOL_GRAB:
+ return 1;
+ case SCULPT_TOOL_INFLATE:
+ return sd->brush->alpha / 50.0f * dir * pressure * flip * anchored;
+ case SCULPT_TOOL_FLATTEN:
+ return sd->brush->alpha / 5.0f * pressure * anchored;
+ default:
+ return 0;
+ }
+}
+
+/* For clipping against a mirror modifier */
+static void sculpt_clip(StrokeCache *cache, float *co, const float val[3])
+{
+ int i;
+ for(i=0; i<3; ++i) {
+ if((cache->flag & (CLIP_X << i)) && (fabs(co[i]) <= cache->clip_tolerance[i]))
+ co[i]= 0.0f;
+ else
+ co[i]= val[i];
+ }
+}
+
+static void sculpt_axislock(Sculpt *sd, float *co)
+{
+ if(sd->flags == (SCULPT_LOCK_X|SCULPT_LOCK_Y|SCULPT_LOCK_Z))
+ return;
+
+ if(sd->session->cache->vc.v3d->twmode == V3D_MANIP_LOCAL) {
+ float mat[3][3], imat[3][3];
+ Mat3CpyMat4(mat, sd->session->cache->vc.obact->obmat);
+ Mat3Inv(imat, mat);
+ Mat3MulVecfl(mat, co);
+ if (sd->flags & SCULPT_LOCK_X) co[0] = 0.0;
+ if (sd->flags & SCULPT_LOCK_Y) co[1] = 0.0;
+ if (sd->flags & SCULPT_LOCK_Z) co[2] = 0.0;
+ Mat3MulVecfl(imat, co);
+ } else {
+ if (sd->flags & SCULPT_LOCK_X) co[0] = 0.0;
+ if (sd->flags & SCULPT_LOCK_Y) co[1] = 0.0;
+ if (sd->flags & SCULPT_LOCK_Z) co[2] = 0.0;
+ }
+}
+
+static void add_norm_if(float view_vec[3], float out[3], float out_flip[3], const short no[3])
+{
+ float fno[3] = {no[0], no[1], no[2]};
+
+ Normalize(fno);
+
+ if((Inpf(view_vec, fno)) > 0) {
+ VecAddf(out, out, fno);
+ } else {
+ VecAddf(out_flip, out_flip, fno); /* out_flip is used when out is {0,0,0} */
+ }
+}
+
+/* Currently only for the draw brush; finds average normal for all active
+ vertices */
+static void calc_area_normal(Sculpt *sd, float out[3], const ListBase* active_verts)
+{
+ StrokeCache *cache = sd->session->cache;
+ ActiveData *node = active_verts->first;
+ const int view = 0; /* XXX: should probably be a flag, not number: sd->brush_type==SCULPT_TOOL_DRAW ? sculptmode_brush()->view : 0; */
+ float out_flip[3];
+ float *out_dir = cache->view_normal_symmetry;
+
+ out[0]=out[1]=out[2] = out_flip[0]=out_flip[1]=out_flip[2] = 0;
+
+ if(sd->brush->flag & BRUSH_ANCHORED) {
+ for(; node; node = node->next)
+ add_norm_if(out_dir, out, out_flip, cache->orig_norms[node->Index]);
+ }
+ else {
+ for(; node; node = node->next)
+ add_norm_if(out_dir, out, out_flip, sd->session->mvert[node->Index].no);
+ }
+
+ if (out[0]==0.0 && out[1]==0.0 && out[2]==0.0) {
+ VECCOPY(out, out_flip);
+ }
+
+ Normalize(out);
+
+ if(out_dir) {
+ out[0] = out_dir[0] * view + out[0] * (10-view);
+ out[1] = out_dir[1] * view + out[1] * (10-view);
+ out[2] = out_dir[2] * view + out[2] * (10-view);
+ }
+
+ Normalize(out);
+}
+
+static void do_draw_brush(Sculpt *sd, SculptSession *ss, const ListBase* active_verts)
+{
+ float area_normal[3];
+ ActiveData *node= active_verts->first;
+
+ calc_area_normal(sd, area_normal, active_verts);
+
+ sculpt_axislock(sd, area_normal);
+
+ while(node){
+ float *co= ss->mvert[node->Index].co;
+
+ const float val[3]= {co[0]+area_normal[0]*node->Fade*ss->cache->scale[0],
+ co[1]+area_normal[1]*node->Fade*ss->cache->scale[1],
+ co[2]+area_normal[2]*node->Fade*ss->cache->scale[2]};
+
+ sculpt_clip(ss->cache, co, val);
+
+ node= node->next;
+ }
+}
+
+/* For the smooth brush, uses the neighboring vertices around vert to calculate
+ a smoothed location for vert. Skips corner vertices (used by only one
+ polygon.) */
+static void neighbor_average(SculptSession *ss, float avg[3], const int vert)
+{
+ int i, skip= -1, total=0;
+ IndexNode *node= ss->fmap[vert].first;
+ char ncount= BLI_countlist(&ss->fmap[vert]);
+ MFace *f;
+
+ avg[0] = avg[1] = avg[2] = 0;
+
+ /* Don't modify corner vertices */
+ if(ncount==1) {
+ VecCopyf(avg, ss->mvert[vert].co);
+ return;
+ }
+
+ while(node){
+ f= &ss->mface[node->index];
+
+ if(f->v4) {
+ skip= (f->v1==vert?2:
+ f->v2==vert?3:
+ f->v3==vert?0:
+ f->v4==vert?1:-1);
+ }
+
+ for(i=0; i<(f->v4?4:3); ++i) {
+ if(i != skip && (ncount!=2 || BLI_countlist(&ss->fmap[(&f->v1)[i]]) <= 2)) {
+ VecAddf(avg, avg, ss->mvert[(&f->v1)[i]].co);
+ ++total;
+ }
+ }
+
+ node= node->next;
+ }
+
+ if(total>0)
+ VecMulf(avg, 1.0f / total);
+ else
+ VecCopyf(avg, ss->mvert[vert].co);
+}
+
+static void do_smooth_brush(SculptSession *ss, const ListBase* active_verts)
+{
+ ActiveData *node= active_verts->first;
+
+ while(node){
+ float *co= ss->mvert[node->Index].co;
+ float avg[3], val[3];
+
+ neighbor_average(ss, avg, node->Index);
+ val[0] = co[0]+(avg[0]-co[0])*node->Fade;
+ val[1] = co[1]+(avg[1]-co[1])*node->Fade;
+ val[2] = co[2]+(avg[2]-co[2])*node->Fade;
+
+ sculpt_clip(ss->cache, co, val);
+ node= node->next;
+ }
+}
+
+static void do_pinch_brush(SculptSession *ss, const ListBase* active_verts)
+{
+ ActiveData *node= active_verts->first;
+
+ while(node) {
+ float *co= ss->mvert[node->Index].co;
+ const float val[3]= {co[0]+(ss->cache->location[0]-co[0])*node->Fade,
+ co[1]+(ss->cache->location[1]-co[1])*node->Fade,
+ co[2]+(ss->cache->location[2]-co[2])*node->Fade};
+ sculpt_clip(ss->cache, co, val);
+ node= node->next;
+ }
+}
+
+static void do_grab_brush(Sculpt *sd, SculptSession *ss)
+{
+ ActiveData *node= ss->cache->grab_active_verts[ss->cache->symmetry].first;
+ float add[3];
+ float grab_delta[3];
+
+ VecCopyf(grab_delta, ss->cache->grab_delta_symmetry);
+ sculpt_axislock(sd, grab_delta);
+
+ while(node) {
+ float *co= ss->mvert[node->Index].co;
+
+ VecCopyf(add, grab_delta);
+ VecMulf(add, node->Fade);
+ VecAddf(add, add, co);
+ sculpt_clip(ss->cache, co, add);
+
+ node= node->next;
+ }
+
+}
+
+static void do_layer_brush(Sculpt *sd, SculptSession *ss, const ListBase *active_verts)
+{
+ float area_normal[3];
+ ActiveData *node= active_verts->first;
+ const float bstr= brush_strength(sd, ss->cache);
+
+ calc_area_normal(sd, area_normal, active_verts);
+
+ while(node){
+ float *disp= &ss->cache->layer_disps[node->Index];
+
+ if((bstr > 0 && *disp < bstr) ||
+ (bstr < 0 && *disp > bstr)) {
+ float *co= ss->mvert[node->Index].co;
+
+ *disp+= node->Fade;
+
+ if(bstr < 0) {
+ if(*disp < bstr)
+ *disp = bstr;
+ } else {
+ if(*disp > bstr)
+ *disp = bstr;
+ }
+
+ {
+ const float val[3]= {ss->cache->mesh_store[node->Index][0]+area_normal[0] * *disp*ss->cache->scale[0],
+ ss->cache->mesh_store[node->Index][1]+area_normal[1] * *disp*ss->cache->scale[1],
+ ss->cache->mesh_store[node->Index][2]+area_normal[2] * *disp*ss->cache->scale[2]};
+ sculpt_clip(ss->cache, co, val);
+ }
+ }
+
+ node= node->next;
+ }
+}
+
+static void do_inflate_brush(SculptSession *ss, const ListBase *active_verts)
+{
+ ActiveData *node= active_verts->first;
+ float add[3];
+
+ while(node) {
+ float *co= ss->mvert[node->Index].co;
+ short *no= ss->mvert[node->Index].no;
+
+ add[0]= no[0]/ 32767.0f;
+ add[1]= no[1]/ 32767.0f;
+ add[2]= no[2]/ 32767.0f;
+ VecMulf(add, node->Fade);
+ add[0]*= ss->cache->scale[0];
+ add[1]*= ss->cache->scale[1];
+ add[2]*= ss->cache->scale[2];
+ VecAddf(add, add, co);
+
+ sculpt_clip(ss->cache, co, add);
+
+ node= node->next;
+ }
+}
+
+static void calc_flatten_center(SculptSession *ss, ActiveData *node, float co[3])
+{
+ ActiveData *outer[FLATTEN_SAMPLE_SIZE];
+ int i;
+
+ for(i = 0; i < FLATTEN_SAMPLE_SIZE; ++i)
+ outer[i] = node;
+
+ for(; node; node = node->next) {
+ for(i = 0; i < FLATTEN_SAMPLE_SIZE; ++i) {
+ if(node->dist > outer[i]->dist) {
+ outer[i] = node;
+ break;
+ }
+ }
+ }
+
+ co[0] = co[1] = co[2] = 0.0f;
+ for(i = 0; i < FLATTEN_SAMPLE_SIZE; ++i)
+ VecAddf(co, co, ss->mvert[outer[i]->Index].co);
+ VecMulf(co, 1.0f / FLATTEN_SAMPLE_SIZE);
+}
+
+static void do_flatten_brush(Sculpt *sd, SculptSession *ss, const ListBase *active_verts)
+{
+ ActiveData *node= active_verts->first;
+ /* area_normal and cntr define the plane towards which vertices are squashed */
+ float area_normal[3];
+ float cntr[3];
+
+ calc_area_normal(sd, area_normal, active_verts);
+ calc_flatten_center(ss, node, cntr);
+
+ while(node){
+ float *co= ss->mvert[node->Index].co;
+ float p1[3], sub1[3], sub2[3], intr[3], val[3];
+
+ /* Find the intersection between squash-plane and vertex (along the area normal) */
+ VecSubf(p1, co, area_normal);
+ VecSubf(sub1, cntr, p1);
+ VecSubf(sub2, co, p1);
+ VecSubf(intr, co, p1);
+ VecMulf(intr, Inpf(area_normal, sub1) / Inpf(area_normal, sub2));
+ VecAddf(intr, intr, p1);
+
+ VecSubf(val, intr, co);
+ VecMulf(val, node->Fade);
+ VecAddf(val, val, co);
+
+ sculpt_clip(ss->cache, co, val);
+
+ node= node->next;
+ }
+}
+
+
+/* Uses symm to selectively flip any axis of a coordinate. */
+static void flip_coord(float out[3], float in[3], const char symm)
+{
+ if(symm & SCULPT_SYMM_X)
+ out[0]= -in[0];
+ else
+ out[0]= in[0];
+ if(symm & SCULPT_SYMM_Y)
+ out[1]= -in[1];
+ else
+ out[1]= in[1];
+ if(symm & SCULPT_SYMM_Z)
+ out[2]= -in[2];
+ else
+ out[2]= in[2];
+}
+
+/* Get a pixel from the texcache at (px, py) */
+static unsigned char get_texcache_pixel(const SculptSession *ss, int px, int py)
+{
+ unsigned *p;
+ p = ss->texcache + py * ss->texcache_side + px;
+ return ((unsigned char*)(p))[0];
+}
+
+static float get_texcache_pixel_bilinear(const SculptSession *ss, float u, float v)
+{
+ int x, y, x2, y2;
+ const int tc_max = ss->texcache_side - 1;
+ float urat, vrat, uopp;
+
+ if(u < 0) u = 0;
+ else if(u >= ss->texcache_side) u = tc_max;
+ if(v < 0) v = 0;
+ else if(v >= ss->texcache_side) v = tc_max;
+
+ x = floor(u);
+ y = floor(v);
+ x2 = x + 1;
+ y2 = y + 1;
+
+ if(x2 > ss->texcache_side) x2 = tc_max;
+ if(y2 > ss->texcache_side) y2 = tc_max;
+
+ urat = u - x;
+ vrat = v - y;
+ uopp = 1 - urat;
+
+ return ((get_texcache_pixel(ss, x, y) * uopp +
+ get_texcache_pixel(ss, x2, y) * urat) * (1 - vrat) +
+ (get_texcache_pixel(ss, x, y2) * uopp +
+ get_texcache_pixel(ss, x2, y2) * urat) * vrat) / 255.0;
+}
+
+/* Return a multiplier for brush strength on a particular vertex. */
+static float tex_strength(Sculpt *sd, float *point, const float len)
+{
+ SculptSession *ss= sd->session;
+ Brush *br = sd->brush;
+ float avg= 1;
+
+ if(br->texact==-1 || !br->mtex[br->texact])
+ avg= 1;
+ else if(br->tex_mode==BRUSH_TEX_3D) {
+ /* Get strength by feeding the vertex location directly
+ into a texture */
+ float jnk;
+ const float factor= 0.01;
+ MTex mtex;
+ memset(&mtex,0,sizeof(MTex));
+ mtex.tex= br->mtex[br->texact]->tex;
+ mtex.projx= 1;
+ mtex.projy= 2;
+ mtex.projz= 3;
+ VecCopyf(mtex.size, br->mtex[br->texact]->size);
+ VecMulf(mtex.size, factor);
+ if(!sd->texsep)
+ mtex.size[1]= mtex.size[2]= mtex.size[0];
+
+ externtex(&mtex,point,&avg,&jnk,&jnk,&jnk,&jnk);
+ }
+ else if(ss->texcache) {
+ const float bsize= ss->cache->pixel_radius * 2;
+ const float rot= sd->brush->rot + ss->cache->rotation;
+ int px, py;
+ float flip[3], point_2d[2];
+
+ /* If the active area is being applied for symmetry, flip it
+ across the symmetry axis in order to project it. This insures
+ that the brush texture will be oriented correctly. */
+ VecCopyf(flip, point);
+ flip_coord(flip, flip, ss->cache->symmetry);
+ projectf(ss->cache->mats, flip, point_2d);
+
+ /* For Tile and Drag modes, get the 2D screen coordinates of the
+ and scale them up or down to the texture size. */
+ if(br->tex_mode==BRUSH_TEX_TILE) {
+ const int sx= (const int)br->mtex[br->texact]->size[0];
+ const int sy= (const int)sd->texsep ? br->mtex[br->texact]->size[1] : sx;
+
+ float fx= point_2d[0];
+ float fy= point_2d[1];
+
+ float angle= atan2(fy, fx) - rot;
+ float flen= sqrtf(fx*fx + fy*fy);
+
+ if(rot<0.001 && rot>-0.001) {
+ px= point_2d[0];
+ py= point_2d[1];
+ } else {
+ px= flen * cos(angle) + 2000;
+ py= flen * sin(angle) + 2000;
+ }
+ if(sx != 1)
+ px %= sx-1;
+ if(sy != 1)
+ py %= sy-1;
+ avg= get_texcache_pixel_bilinear(ss, ss->texcache_side*px/sx, ss->texcache_side*py/sy);
+ } else {
+ float fx= (point_2d[0] - ss->cache->mouse[0]) / bsize;
+ float fy= (point_2d[1] - ss->cache->mouse[1]) / bsize;
+
+ float angle= atan2(fy, fx) - rot;
+ float flen= sqrtf(fx*fx + fy*fy);
+
+ fx = flen * cos(angle) + 0.5;
+ fy = flen * sin(angle) + 0.5;
+
+ avg= get_texcache_pixel_bilinear(ss, fx * ss->texcache_side, fy * ss->texcache_side);
+ }
+ }
+
+ avg*= brush_curve_strength(sd->brush, len, ss->cache->radius); /* Falloff curve */
+
+ return avg;
+}
+
+/* Mark area around the brush as damaged. projverts are marked if they are
+ inside the area and the damaged rectangle in 2D screen coordinates is
+ added to damaged_rects. */
+static void sculpt_add_damaged_rect(SculptSession *ss)
+{
+ short p[2];
+ RectNode *rn= MEM_mallocN(sizeof(RectNode),"RectNode");
+ const float radius = MAX2(ss->cache->pixel_radius, ss->cache->previous_pixel_radius);
+ unsigned i;
+
+ /* Find center */
+ project(ss->cache->mats, ss->cache->location, p);
+ rn->r.xmin= p[0] - radius;
+ rn->r.ymin= p[1] - radius;
+ rn->r.xmax= p[0] + radius;
+ rn->r.ymax= p[1] + radius;
+
+ BLI_addtail(&ss->damaged_rects, rn);
+
+ /* Update insides */
+ for(i=0; i<ss->totvert; ++i) {
+ if(!ss->projverts[i].inside) {
+ if(ss->projverts[i].co[0] > rn->r.xmin && ss->projverts[i].co[1] > rn->r.ymin &&
+ ss->projverts[i].co[0] < rn->r.xmax && ss->projverts[i].co[1] < rn->r.ymax) {
+ ss->projverts[i].inside= 1;
+ }
+ }
+ // XXX: remember to fix this!
+ // temporary pass
+ ss->projverts[i].inside = 1;
+ }
+}
+
+/* Clears the depth buffer in each modified area. */
+#if 0
+static void sculpt_clear_damaged_areas(SculptSession *ss)
+{
+ RectNode *rn= NULL;
+
+ for(rn = ss->damaged_rects.first; rn; rn = rn->next) {
+ rcti clp = rn->r;
+ rcti *win = NULL; /*XXX: &curarea->winrct; */
+
+ clp.xmin += win->xmin;
+ clp.xmax += win->xmin;
+ clp.ymin += win->ymin;
+ clp.ymax += win->ymin;
+
+ if(clp.xmin < win->xmax && clp.xmax > win->xmin &&
+ clp.ymin < win->ymax && clp.ymax > win->ymin) {
+ if(clp.xmin < win->xmin) clp.xmin = win->xmin;
+ if(clp.ymin < win->ymin) clp.ymin = win->ymin;
+ if(clp.xmax > win->xmax) clp.xmax = win->xmax;
+ if(clp.ymax > win->ymax) clp.ymax = win->ymax;
+
+ glScissor(clp.xmin + 1, clp.ymin + 1,
+ clp.xmax - clp.xmin - 2,
+ clp.ymax - clp.ymin - 2);
+ }
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+ }
+}
+#endif
+static void do_brush_action(Sculpt *sd, StrokeCache *cache)
+{
+ SculptSession *ss = sd->session;
+ float av_dist;
+ ListBase active_verts={0,0};
+ ListBase *grab_active_verts = &ss->cache->grab_active_verts[ss->cache->symmetry];
+ ActiveData *adata= 0;
+ float *vert;
+ Mesh *me= NULL; /*XXX: get_mesh(OBACT); */
+ const float bstrength= brush_strength(sd, cache);
+ KeyBlock *keyblock= NULL; /*XXX: ob_get_keyblock(OBACT); */
+ Brush *b = sd->brush;
+ int i;
+
+ sculpt_add_damaged_rect(ss);
+
+ /* Build a list of all vertices that are potentially within the brush's
+ area of influence. Only do this once for the grab brush. */
+ if((b->sculpt_tool != SCULPT_TOOL_GRAB) || cache->first_time) {
+ for(i=0; i<ss->totvert; ++i) {
+ /* Projverts.inside provides a rough bounding box */
+ if(ss->multires || ss->projverts[i].inside) {
+ //vert= ss->vertexcosnos ? &ss->vertexcosnos[i*6] : a->verts[i].co;
+ vert= ss->mvert[i].co;
+ av_dist= VecLenf(ss->cache->location, vert);
+ if(av_dist < cache->radius) {
+ adata= (ActiveData*)MEM_mallocN(sizeof(ActiveData), "ActiveData");
+
+ adata->Index = i;
+ /* Fade is used to store the final strength at which the brush
+ should modify a particular vertex. */
+ adata->Fade= tex_strength(sd, vert, av_dist) * bstrength;
+ adata->dist = av_dist;
+
+ if(b->sculpt_tool == SCULPT_TOOL_GRAB && cache->first_time)
+ BLI_addtail(grab_active_verts, adata);
+ else
+ BLI_addtail(&active_verts, adata);
+ }
+ }
+ }
+ }
+
+ /* Only act if some verts are inside the brush area */
+ if(active_verts.first || (b->sculpt_tool == SCULPT_TOOL_GRAB && grab_active_verts->first)) {
+ /* Apply one type of brush action */
+ switch(b->sculpt_tool){
+ case SCULPT_TOOL_DRAW:
+ do_draw_brush(sd, ss, &active_verts);
+ break;
+ case SCULPT_TOOL_SMOOTH:
+ do_smooth_brush(ss, &active_verts);
+ break;
+ case SCULPT_TOOL_PINCH:
+ do_pinch_brush(ss, &active_verts);
+ break;
+ case SCULPT_TOOL_INFLATE:
+ do_inflate_brush(ss, &active_verts);
+ break;
+ case SCULPT_TOOL_GRAB:
+ do_grab_brush(sd, ss);
+ break;
+ case SCULPT_TOOL_LAYER:
+ do_layer_brush(sd, ss, &active_verts);
+ break;
+ case SCULPT_TOOL_FLATTEN:
+ do_flatten_brush(sd, ss, &active_verts);
+ break;
+ }
+
+ /* Copy the modified vertices from mesh to the active key */
+ if(keyblock && !ss->multires) {
+ float *co= keyblock->data;
+ if(co) {
+ if(b->sculpt_tool == SCULPT_TOOL_GRAB)
+ adata = grab_active_verts->first;
+ else
+ adata = active_verts.first;
+
+ for(; adata; adata= adata->next)
+ if(adata->Index < keyblock->totelem)
+ VecCopyf(&co[adata->Index*3], me->mvert[adata->Index].co);
+ }
+ }
+
+ if(ss->vertexcosnos && !ss->multires)
+ BLI_freelistN(&active_verts);
+ else {
+ if(b->sculpt_tool != SCULPT_TOOL_GRAB)
+ addlisttolist(&ss->damaged_verts, &active_verts);
+ }
+ }
+}
+
+/* Flip all the editdata across the axis/axes specified by symm. Used to
+ calculate multiple modifications to the mesh when symmetry is enabled. */
+static void calc_brushdata_symm(StrokeCache *cache, const char symm)
+{
+ flip_coord(cache->location, cache->true_location, symm);
+ flip_coord(cache->view_normal_symmetry, cache->view_normal, symm);
+ flip_coord(cache->grab_delta_symmetry, cache->grab_delta, symm);
+ cache->symmetry= symm;
+}
+
+static void do_symmetrical_brush_actions(Sculpt *sd, StrokeCache *cache)
+{
+ const char symm = sd->flags & 7;
+ int i;
+
+ /* Brush spacing: only apply dot if next dot is far enough away */
+ if((sd->brush->flag & BRUSH_SPACE) && !(sd->brush->flag & BRUSH_ANCHORED) && !cache->first_time) {
+ int dx = cache->last_dot[0] - cache->mouse[0];
+ int dy = cache->last_dot[1] - cache->mouse[1];
+ if(sqrt(dx*dx+dy*dy) < sd->brush->spacing)
+ return;
+ }
+ memcpy(cache->last_dot, cache->mouse, sizeof(int) * 2);
+
+ VecCopyf(cache->location, cache->true_location);
+ VecCopyf(cache->grab_delta_symmetry, cache->grab_delta);
+ cache->symmetry = 0;
+ do_brush_action(sd, cache);
+
+ for(i = 1; i <= symm; ++i) {
+ if(symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5))) {
+ calc_brushdata_symm(cache, i);
+ do_brush_action(sd, cache);
+ }
+ }
+
+ cache->first_time = 0;
+}
+
+static void add_face_normal(vec3f *norm, MVert *mvert, const MFace* face, float *fn)
+{
+ vec3f c= {mvert[face->v1].co[0],mvert[face->v1].co[1],mvert[face->v1].co[2]};
+ vec3f b= {mvert[face->v2].co[0],mvert[face->v2].co[1],mvert[face->v2].co[2]};
+ vec3f a= {mvert[face->v3].co[0],mvert[face->v3].co[1],mvert[face->v3].co[2]};
+ vec3f s1, s2;
+ float final[3];
+
+ VecSubf(&s1.x,&a.x,&b.x);
+ VecSubf(&s2.x,&c.x,&b.x);
+
+ final[0] = s1.y * s2.z - s1.z * s2.y;
+ final[1] = s1.z * s2.x - s1.x * s2.z;
+ final[2] = s1.x * s2.y - s1.y * s2.x;
+
+ if(fn)
+ VecCopyf(fn, final);
+
+ norm->x+= final[0];
+ norm->y+= final[1];
+ norm->z+= final[2];
+}
+
+static void update_damaged_vert(SculptSession *ss, ListBase *lb)
+{
+ ActiveData *vert;
+
+ for(vert= lb->first; vert; vert= vert->next) {
+ vec3f norm= {0,0,0};
+ IndexNode *face= ss->fmap[vert->Index].first;
+
+ while(face){
+ float *fn = NULL;
+ if(ss->face_normals)
+ fn = &ss->face_normals[face->index*3];
+ add_face_normal(&norm, ss->mvert, &ss->mface[face->index], fn);
+ face= face->next;
+ }
+ Normalize(&norm.x);
+
+ ss->mvert[vert->Index].no[0]=norm.x*32767;
+ ss->mvert[vert->Index].no[1]=norm.y*32767;
+ ss->mvert[vert->Index].no[2]=norm.z*32767;
+ }
+}
+
+static void calc_damaged_verts(SculptSession *ss)
+{
+ int i;
+
+ for(i=0; i<8; ++i)
+ update_damaged_vert(ss, &ss->cache->grab_active_verts[i]);
+ update_damaged_vert(ss, &ss->damaged_verts);
+ BLI_freelistN(&ss->damaged_verts);
+ ss->damaged_verts.first = ss->damaged_verts.last = NULL;
+}
+
+#if 0
+static void projverts_clear_inside(SculptSession *ss)
+{
+ int i;
+ for(i = 0; i < ss->totvert; ++i)
+ ss->projverts[i].inside = 0;
+}
+#endif
+
+static void sculpt_update_tex(Sculpt *sd)
+{
+ SculptSession *ss= sd->session;
+
+ if(ss->texcache) {
+ MEM_freeN(ss->texcache);
+ ss->texcache= NULL;
+ }
+
+ /* Need to allocate a bigger buffer for bigger brush size */
+ ss->texcache_side = sd->brush->size * 2;
+ if(!ss->texcache || ss->texcache_side > ss->texcache_actual) {
+ ss->texcache = brush_gen_texture_cache(sd->brush, sd->brush->size);
+ ss->texcache_actual = ss->texcache_side;
+ }
+}
+
+void sculptmode_selectbrush_menu(void)
+{
+ /* XXX: I guess menus belong elsewhere too?
+
+ Sculpt *sd= sculpt_data();
+ int val;
+
+ pupmenu_set_active(sd->brush_type);
+
+ val= pupmenu("Select Brush%t|Draw|Smooth|Pinch|Inflate|Grab|Layer|Flatten");
+
+ if(val>0) {
+ sd->brush_type= val;
+
+ allqueue(REDRAWVIEW3D, 1);
+ allqueue(REDRAWBUTSEDIT, 1);
+ }*/
+}
+
+static void sculptmode_update_all_projverts(SculptSession *ss)
+{
+ unsigned i;
+
+ if(!ss->projverts)
+ ss->projverts = MEM_mallocN(sizeof(ProjVert)*ss->totvert,"ProjVerts");
+
+ for(i=0; i<ss->totvert; ++i) {
+ project(ss->cache->mats, ss->vertexcosnos ? &ss->vertexcosnos[i * 6] : ss->mvert[i].co,
+ ss->projverts[i].co);
+ ss->projverts[i].inside= 0;
+ }
+}
+
+/* Checks whether full update mode (slower) needs to be used to work with modifiers */
+char sculpt_modifiers_active(Object *ob)
+{
+ ModifierData *md;
+
+ for(md= modifiers_getVirtualModifierList(ob); md; md= md->next) {
+ if(md->mode & eModifierMode_Realtime && md->type != eModifierType_Multires)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Sculpt mode handles multires differently from regular meshes, but only if
+ it's the last modifier on the stack and it is not on the first level */
+static struct MultiresModifierData *sculpt_multires_active(Object *ob)
+{
+ ModifierData *md;
+
+ for(md= modifiers_getVirtualModifierList(ob); md; md= md->next) {
+ if(md->type == eModifierType_Multires && !md->next) {
+ MultiresModifierData *mmd = (MultiresModifierData*)md;
+ if(mmd->lvl != 1)
+ return mmd;
+ }
+ }
+
+ return NULL;
+}
+
+static void sculpt_update_mesh_elements(bContext *C)
+{
+ SculptSession *ss = CTX_data_tool_settings(C)->sculpt->session;
+ Object *ob = CTX_data_active_object(C);
+
+ if((ss->multires = sculpt_multires_active(ob))) {
+ DerivedMesh *dm = mesh_get_derived_final(CTX_data_scene(C), ob, CD_MASK_BAREMESH);
+ ss->totvert = dm->getNumVerts(dm);
+ ss->totface = dm->getNumFaces(dm);
+ ss->mvert = dm->getVertDataArray(dm, CD_MVERT);
+ ss->mface = dm->getFaceDataArray(dm, CD_MFACE);
+ ss->face_normals = dm->getFaceDataArray(dm, CD_NORMAL);
+ }
+ else {
+ Mesh *me = get_mesh(ob);
+ ss->totvert = me->totvert;
+ ss->totface = me->totface;
+ ss->mvert = me->mvert;
+ ss->mface = me->mface;
+ ss->face_normals = NULL;
+ }
+
+ if(ss->totvert != ss->fmap_size) {
+ if(ss->fmap) MEM_freeN(ss->fmap);
+ if(ss->fmap_mem) MEM_freeN(ss->fmap_mem);
+ create_vert_face_map(&ss->fmap, &ss->fmap_mem, ss->mface, ss->totvert, ss->totface);
+ ss->fmap_size = ss->totvert;
+ }
+}
+
+/* XXX: lots of drawing code (partial redraw), has to go elsewhere */
+#if 0
+void sculptmode_draw_wires(SculptSession *ss, int only_damaged)
+{
+ Mesh *me = get_mesh(OBACT);
+ int i;
+
+ bglPolygonOffset(1.0);
+ glDepthMask(0);
+ BIF_ThemeColor((OBACT==OBACT)?TH_ACTIVE:TH_SELECT);
+
+ for(i=0; i<me->totedge; i++) {
+ MEdge *med= &me->medge[i];
+
+ if((!only_damaged || (ss->projverts[med->v1].inside || ss->projverts[med->v2].inside)) &&
+ (med->flag & ME_EDGEDRAW)) {
+ glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, &med->v1);
+ }
+ }
+
+ glDepthMask(1);
+ bglPolygonOffset(0.0);
+}
+
+void sculptmode_draw_mesh(int only_damaged)
+{
+ int i, j, dt, drawCurrentMat = 1, matnr= -1;
+ SculptSession *ss = sculpt_session();
+
+ sculpt_update_mesh_elements(ss, OBACT);
+
+ persp(PERSP_VIEW);
+ mymultmatrix(OBACT->obmat);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_LIGHTING);
+ /* XXX: GPU_set_object_materials(G.scene, OBACT, 0, NULL); */
+ glEnable(GL_CULL_FACE);
+
+ glShadeModel(GL_SMOOTH);
+
+ glVertexPointer(3, GL_FLOAT, sizeof(MVert), &cache->mvert[0].co);
+ glNormalPointer(GL_SHORT, sizeof(MVert), &cache->mvert[0].no);
+
+ dt= MIN2(G.vd->drawtype, OBACT->dt);
+ if(dt==OB_WIRE)
+ glColorMask(0,0,0,0);
+
+ for(i=0; i<ss->totface; ++i) {
+ MFace *f= &ss->mface[i];
+ char inside= 0;
+ int new_matnr= f->mat_nr + 1;
+
+ if(new_matnr != matnr)
+ drawCurrentMat= GPU_enable_material(matnr = new_matnr, NULL);
+
+ /* If only_damaged!=0, only draw faces that are partially
+ inside the area(s) modified by the brush */
+ if(only_damaged) {
+ for(j=0; j<(f->v4?4:3); ++j) {
+ if(ss->projverts[*((&f->v1)+j)].inside) {
+ inside= 1;
+ break;
+ }
+ }
+ }
+ else
+ inside= 1;
+
+ if(inside && drawCurrentMat)
+ glDrawElements(f->v4?GL_QUADS:GL_TRIANGLES, f->v4?4:3, GL_UNSIGNED_INT, &f->v1);
+ }
+
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glColorMask(1,1,1,1);
+
+ if(dt==OB_WIRE || (OBACT->dtx & OB_DRAWWIRE))
+ sculptmode_draw_wires(ss, only_damaged);
+
+ glDisable(GL_DEPTH_TEST);
+}
+#endif
+
+static int sculpt_poll(bContext *C)
+{
+ return G.f & G_SCULPTMODE && CTX_wm_area(C)->spacetype == SPACE_VIEW3D &&
+ CTX_wm_region(C)->regiontype == RGN_TYPE_WINDOW;
+}
+
+/*** Sculpt Cursor ***/
+static void draw_paint_cursor(bContext *C, int x, int y, void *customdata)
+{
+ Sculpt *sd= CTX_data_tool_settings(C)->sculpt;
+
+ glTranslatef((float)x, (float)y, 0.0f);
+
+ glColor4ub(255, 100, 100, 128);
+ glEnable( GL_LINE_SMOOTH );
+ glEnable(GL_BLEND);
+ glutil_draw_lined_arc(0.0, M_PI*2.0, sd->brush->size, 40);
+ glDisable(GL_BLEND);
+ glDisable( GL_LINE_SMOOTH );
+
+ glTranslatef((float)-x, (float)-y, 0.0f);
+}
+
+static void toggle_paint_cursor(bContext *C)
+{
+ Sculpt *s = CTX_data_scene(C)->toolsettings->sculpt;
+
+ if(s->session->cursor) {
+ WM_paint_cursor_end(CTX_wm_manager(C), s->session->cursor);
+ s->session->cursor = NULL;
+ }
+ else {
+ s->session->cursor =
+ WM_paint_cursor_activate(CTX_wm_manager(C), sculpt_poll, draw_paint_cursor, NULL);
+ }
+}
+
+static void sculpt_undo_push(bContext *C, Sculpt *sd)
+{
+ switch(sd->brush->sculpt_tool) {
+ case SCULPT_TOOL_DRAW:
+ ED_undo_push(C, "Draw Brush"); break;
+ case SCULPT_TOOL_SMOOTH:
+ ED_undo_push(C, "Smooth Brush"); break;
+ case SCULPT_TOOL_PINCH:
+ ED_undo_push(C, "Pinch Brush"); break;
+ case SCULPT_TOOL_INFLATE:
+ ED_undo_push(C, "Inflate Brush"); break;
+ case SCULPT_TOOL_GRAB:
+ ED_undo_push(C, "Grab Brush"); break;
+ case SCULPT_TOOL_LAYER:
+ ED_undo_push(C, "Layer Brush"); break;
+ case SCULPT_TOOL_FLATTEN:
+ ED_undo_push(C, "Flatten Brush"); break;
+ default:
+ ED_undo_push(C, "Sculpting"); break;
+ }
+}
+
+static int sculpt_brush_curve_preset_exec(bContext *C, wmOperator *op)
+{
+ brush_curve_preset(CTX_data_scene(C)->toolsettings->sculpt->brush, RNA_enum_get(op->ptr, "mode"));
+ return OPERATOR_FINISHED;
+}
+
+static void SCULPT_OT_brush_curve_preset(wmOperatorType *ot)
+{
+ static EnumPropertyItem prop_mode_items[] = {
+ {BRUSH_PRESET_SHARP, "SHARP", "Sharp Curve", ""},
+ {BRUSH_PRESET_SMOOTH, "SMOOTH", "Smooth Curve", ""},
+ {BRUSH_PRESET_MAX, "MAX", "Max Curve", ""},
+ {0, NULL, NULL, NULL}};
+
+ ot->name= "Preset";
+ ot->idname= "SCULPT_OT_brush_curve_preset";
+
+ ot->exec= sculpt_brush_curve_preset_exec;
+ ot->poll= sculpt_poll;
+
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "mode", prop_mode_items, BRUSH_PRESET_SHARP, "Mode", "");
+}
+
+/**** Radial control ****/
+static int sculpt_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ toggle_paint_cursor(C);
+ brush_radial_control_invoke(op, CTX_data_scene(C)->toolsettings->sculpt->brush, 1);
+ return WM_radial_control_invoke(C, op, event);
+}
+
+static int sculpt_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ int ret = WM_radial_control_modal(C, op, event);
+ if(ret != OPERATOR_RUNNING_MODAL)
+ toggle_paint_cursor(C);
+ return ret;
+}
+
+static int sculpt_radial_control_exec(bContext *C, wmOperator *op)
+{
+ return brush_radial_control_exec(op, CTX_data_scene(C)->toolsettings->sculpt->brush, 1);
+}
+
+static void SCULPT_OT_radial_control(wmOperatorType *ot)
+{
+ WM_OT_radial_control_partial(ot);
+
+ ot->name= "Sculpt Radial Control";
+ ot->idname= "SCULPT_OT_radial_control";
+
+ ot->invoke= sculpt_radial_control_invoke;
+ ot->modal= sculpt_radial_control_modal;
+ ot->exec= sculpt_radial_control_exec;
+ ot->poll= sculpt_poll;
+
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/**** Operator for applying a stroke (various attributes including mouse path)
+ using the current brush. ****/
+
+static float unproject_brush_radius(SculptSession *ss, float offset)
+{
+ float brush_edge[3];
+
+ /* In anchored mode, brush size changes with mouse loc, otherwise it's fixed using the brush radius */
+ unproject(ss->cache->mats, brush_edge, ss->cache->initial_mouse[0] + offset,
+ ss->cache->initial_mouse[1], ss->cache->depth);
+
+ return VecLenf(ss->cache->true_location, brush_edge);
+}
+
+static void sculpt_cache_free(StrokeCache *cache)
+{
+ if(cache->layer_disps)
+ MEM_freeN(cache->layer_disps);
+ if(cache->mesh_store)
+ MEM_freeN(cache->mesh_store);
+ if(cache->orig_norms)
+ MEM_freeN(cache->orig_norms);
+ if(cache->mats)
+ MEM_freeN(cache->mats);
+ MEM_freeN(cache);
+}
+
+/* Initialize the stroke cache invariants from operator properties */
+static void sculpt_update_cache_invariants(Sculpt *sd, bContext *C, wmOperator *op)
+{
+ StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
+ int i;
+
+ sd->session->cache = cache;
+
+ RNA_float_get_array(op->ptr, "scale", cache->scale);
+ cache->flag = RNA_int_get(op->ptr, "flag");
+ RNA_float_get_array(op->ptr, "clip_tolerance", cache->clip_tolerance);
+ RNA_int_get_array(op->ptr, "initial_mouse", cache->initial_mouse);
+ cache->depth = RNA_float_get(op->ptr, "depth");
+
+ /* Truly temporary data that isn't stored in properties */
+
+ view3d_set_viewcontext(C, &cache->vc);
+
+ cache->mats = MEM_callocN(sizeof(bglMats), "sculpt bglMats");
+ view3d_get_transformation(&cache->vc, cache->vc.obact, cache->mats);
+
+ sculpt_update_mesh_elements(C);
+
+ /* Make copies of the mesh vertex locations and normals for some tools */
+ if(sd->brush->sculpt_tool == SCULPT_TOOL_LAYER || (sd->brush->flag & BRUSH_ANCHORED)) {
+ cache->layer_disps = MEM_callocN(sizeof(float) * sd->session->totvert, "layer brush displacements");
+ cache->mesh_store= MEM_mallocN(sizeof(float) * 3 * sd->session->totvert, "sculpt mesh vertices copy");
+ for(i = 0; i < sd->session->totvert; ++i)
+ VecCopyf(cache->mesh_store[i], sd->session->mvert[i].co);
+
+ if(sd->brush->flag & BRUSH_ANCHORED) {
+ cache->orig_norms= MEM_mallocN(sizeof(short) * 3 * sd->session->totvert, "Sculpt orig norm");
+ for(i = 0; i < sd->session->totvert; ++i) {
+ cache->orig_norms[i][0] = sd->session->mvert[i].no[0];
+ cache->orig_norms[i][1] = sd->session->mvert[i].no[1];
+ cache->orig_norms[i][2] = sd->session->mvert[i].no[2];
+ }
+ }
+ }
+
+ unproject(cache->mats, cache->true_location, cache->initial_mouse[0], cache->initial_mouse[1], cache->depth);
+ cache->radius = unproject_brush_radius(sd->session, brush_size(sd));
+ cache->rotation = 0;
+ cache->first_time = 1;
+}
+
+/* Initialize the stroke cache variants from operator properties */
+static void sculpt_update_cache_variants(Sculpt *sd, PointerRNA *ptr)
+{
+ StrokeCache *cache = sd->session->cache;
+ float grab_location[3];
+ int dx, dy;
+
+ if(!(sd->brush->flag & BRUSH_ANCHORED))
+ RNA_float_get_array(ptr, "location", cache->true_location);
+ cache->flip = RNA_boolean_get(ptr, "flip");
+ RNA_int_get_array(ptr, "mouse", cache->mouse);
+
+ /* Truly temporary data that isn't stored in properties */
+
+ cache->previous_pixel_radius = cache->pixel_radius;
+ cache->pixel_radius = brush_size(sd);
+
+ if(sd->brush->flag & BRUSH_ANCHORED) {
+ dx = cache->mouse[0] - cache->initial_mouse[0];
+ dy = cache->mouse[1] - cache->initial_mouse[1];
+ cache->pixel_radius = sqrt(dx*dx + dy*dy);
+ cache->radius = unproject_brush_radius(sd->session, cache->pixel_radius);
+ cache->rotation = atan2(dy, dx);
+ }
+ else if(sd->brush->flag & BRUSH_RAKE) {
+ int update;
+
+ dx = cache->last_rake[0] - cache->mouse[0];
+ dy = cache->last_rake[1] - cache->mouse[1];
+
+ update = dx*dx + dy*dy > 100;
+
+ /* To prevent jitter, only update the angle if the mouse has moved over 10 pixels */
+ if(update && !cache->first_time)
+ cache->rotation = M_PI_2 + atan2(dy, dx);
+
+ if(update || cache->first_time) {
+ cache->last_rake[0] = cache->mouse[0];
+ cache->last_rake[1] = cache->mouse[1];
+ }
+ }
+
+ /* Find the grab delta */
+ if(sd->brush->sculpt_tool == SCULPT_TOOL_GRAB) {
+ unproject(cache->mats, grab_location, cache->mouse[0], cache->mouse[1], cache->depth);
+ if(!cache->first_time)
+ VecSubf(cache->grab_delta, grab_location, cache->old_grab_location);
+ VecCopyf(cache->old_grab_location, grab_location);
+ }
+}
+
+/* Initialize stroke operator properties */
+static void sculpt_brush_stroke_init_properties(bContext *C, wmOperator *op, wmEvent *event, SculptSession *ss)
+{
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ Object *ob= CTX_data_active_object(C);
+ ModifierData *md;
+ ViewContext vc;
+ float scale[3], clip_tolerance[3] = {0,0,0};
+ int mouse[2], flag = 0;
+
+ /* Set scaling adjustment */
+ scale[0] = 1.0f / ob->size[0];
+ scale[1] = 1.0f / ob->size[1];
+ scale[2] = 1.0f / ob->size[2];
+ RNA_float_set_array(op->ptr, "scale", scale);
+
+ /* Initialize mirror modifier clipping */
+ for(md= ob->modifiers.first; md; md= md->next) {
+ if(md->type==eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) {
+ const MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ /* Mark each axis that needs clipping along with its tolerance */
+ if(mmd->flag & MOD_MIR_CLIPPING) {
+ flag |= CLIP_X << mmd->axis;
+ if(mmd->tolerance > clip_tolerance[mmd->axis])
+ clip_tolerance[mmd->axis] = mmd->tolerance;
+ }
+ }
+ }
+ RNA_int_set(op->ptr, "flag", flag);
+ RNA_float_set_array(op->ptr, "clip_tolerance", clip_tolerance);
+
+ /* Initial mouse location */
+ mouse[0] = event->x;
+ mouse[1] = event->y;
+ RNA_int_set_array(op->ptr, "initial_mouse", mouse);
+
+ /* Initial screen depth under the mouse */
+ view3d_set_viewcontext(C, &vc);
+ RNA_float_set(op->ptr, "depth", read_cached_depth(&vc, event->x, event->y));
+
+ sculpt_update_cache_invariants(sd, C, op);
+}
+
+static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+
+ view3d_operator_needs_opengl(C);
+ sculpt_brush_stroke_init_properties(C, op, event, sd->session);
+
+ sculptmode_update_all_projverts(sd->session);
+
+ /* TODO: Shouldn't really have to do this at the start of every
+ stroke, but sculpt would need some sort of notification when
+ changes are made to the texture. */
+ sculpt_update_tex(sd);
+
+ /* add modal handler */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void sculpt_restore_mesh(Sculpt *sd)
+{
+ StrokeCache *cache = sd->session->cache;
+ int i;
+
+ /* Restore the mesh before continuing with anchored stroke */
+ if((sd->brush->flag & BRUSH_ANCHORED) && cache->mesh_store) {
+ for(i = 0; i < sd->session->totvert; ++i) {
+ VecCopyf(sd->session->mvert[i].co, cache->mesh_store[i]);
+ sd->session->mvert[i].no[0] = cache->orig_norms[i][0];
+ sd->session->mvert[i].no[1] = cache->orig_norms[i][1];
+ sd->session->mvert[i].no[2] = cache->orig_norms[i][2];
+ }
+ }
+}
+
+static void sculpt_post_stroke_free(SculptSession *ss)
+{
+ BLI_freelistN(&ss->damaged_rects);
+ BLI_freelistN(&ss->damaged_verts);
+}
+
+static void sculpt_flush_update(bContext *C)
+{
+ Sculpt *s = CTX_data_tool_settings(C)->sculpt;
+ ARegion *ar = CTX_wm_region(C);
+ MultiresModifierData *mmd = s->session->multires;
+
+ calc_damaged_verts(s->session);
+
+ if(mmd) {
+ if(mmd->undo_verts && mmd->undo_verts != s->session->mvert)
+ MEM_freeN(mmd->undo_verts);
+
+ mmd->undo_verts = s->session->mvert;
+ mmd->undo_verts_tot = s->session->totvert;
+ }
+
+ ED_region_tag_redraw(ar);
+}
+
+static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ PointerRNA itemptr;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ float center[3];
+ int mouse[2] = {event->x, event->y};
+
+ sculpt_update_mesh_elements(C);
+
+ unproject(sd->session->cache->mats, center, event->x, event->y,
+ read_cached_depth(&sd->session->cache->vc, event->x, event->y));
+
+ /* Add to stroke */
+ RNA_collection_add(op->ptr, "stroke", &itemptr);
+ RNA_float_set_array(&itemptr, "location", center);
+ RNA_int_set_array(&itemptr, "mouse", mouse);
+ RNA_boolean_set(&itemptr, "flip", event->shift);
+ sculpt_update_cache_variants(sd, &itemptr);
+
+ sculpt_restore_mesh(sd);
+ do_symmetrical_brush_actions(CTX_data_tool_settings(C)->sculpt, sd->session->cache);
+
+ sculpt_flush_update(C);
+ sculpt_post_stroke_free(sd->session);
+
+ /* Finished */
+ if(event->type == LEFTMOUSE && event->val == 0) {
+ request_depth_update(sd->session->cache->vc.rv3d);
+
+ sculpt_cache_free(sd->session->cache);
+
+ sculpt_undo_push(C, sd);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op)
+{
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+
+ view3d_operator_needs_opengl(C);
+ sculpt_update_cache_invariants(sd, C, op);
+ sculptmode_update_all_projverts(sd->session);
+ sculpt_update_tex(sd);
+
+ RNA_BEGIN(op->ptr, itemptr, "stroke") {
+ sculpt_update_cache_variants(sd, &itemptr);
+
+ sculpt_restore_mesh(sd);
+ do_symmetrical_brush_actions(sd, sd->session->cache);
+
+ sculpt_post_stroke_free(sd->session);
+ }
+ RNA_END;
+
+ sculpt_flush_update(C);
+ sculpt_cache_free(sd->session->cache);
+
+ sculpt_undo_push(C, sd);
+
+ return OPERATOR_FINISHED;
+}
+
+static void SCULPT_OT_brush_stroke(wmOperatorType *ot)
+{
+ ot->flag |= OPTYPE_REGISTER;
+
+ /* identifiers */
+ ot->name= "Sculpt Mode";
+ ot->idname= "SCULPT_OT_brush_stroke";
+
+ /* api callbacks */
+ ot->invoke= sculpt_brush_stroke_invoke;
+ ot->modal= sculpt_brush_stroke_modal;
+ ot->exec= sculpt_brush_stroke_exec;
+ ot->poll= sculpt_poll;
+
+ /* flags (sculpt does own undo? (ton) */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+
+ /* If the object has a scaling factor, brushes also need to be scaled
+ to work as expected. */
+ RNA_def_float_vector(ot->srna, "scale", 3, NULL, 0.0f, FLT_MAX, "Scale", "", 0.0f, 1000.0f);
+
+ RNA_def_int(ot->srna, "flag", 0, 0, INT_MAX, "flag", "", 0, INT_MAX);
+
+ /* For mirror modifiers */
+ RNA_def_float_vector(ot->srna, "clip_tolerance", 3, NULL, 0.0f, FLT_MAX, "clip_tolerance", "", 0.0f, 1000.0f);
+
+ /* The initial 2D location of the mouse */
+ RNA_def_int_vector(ot->srna, "initial_mouse", 2, NULL, INT_MIN, INT_MAX, "initial_mouse", "", INT_MIN, INT_MAX);
+
+ /* The initial screen depth of the mouse */
+ RNA_def_float(ot->srna, "depth", 0.0f, 0.0f, FLT_MAX, "depth", "", 0.0f, FLT_MAX);
+}
+
+/**** Toggle operator for turning sculpt mode on or off ****/
+
+static int sculpt_toggle_mode(bContext *C, wmOperator *op)
+{
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
+ if(G.f & G_SCULPTMODE) {
+ multires_force_update(CTX_data_active_object(C));
+
+ /* Leave sculptmode */
+ G.f &= ~G_SCULPTMODE;
+
+ toggle_paint_cursor(C);
+
+ sculptsession_free(ts->sculpt);
+ }
+ else {
+ MTex *mtex; // XXX: temporary
+
+ /* Enter sculptmode */
+
+ G.f |= G_SCULPTMODE;
+
+ /* Create persistent sculpt mode data */
+ if(!ts->sculpt)
+ ts->sculpt = MEM_callocN(sizeof(Sculpt), "sculpt mode data");
+
+ /* Create sculpt mode session data */
+ if(ts->sculpt->session)
+ MEM_freeN(ts->sculpt->session);
+ ts->sculpt->session = MEM_callocN(sizeof(SculptSession), "sculpt session");
+
+ toggle_paint_cursor(C);
+
+ /* If there's no brush, create one */
+ brush_check_exists(&ts->sculpt->brush);
+
+ /* XXX: testing: set the brush texture to the first available one */
+ if(G.main->tex.first) {
+ Tex *tex = G.main->tex.first;
+ if(tex->type) {
+ mtex = MEM_callocN(sizeof(MTex), "test mtex");
+ ts->sculpt->brush->texact = 0;
+ ts->sculpt->brush->mtex[0] = mtex;
+ mtex->tex = tex;
+ mtex->size[0] = mtex->size[1] = mtex->size[2] = 50;
+ }
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void SCULPT_OT_sculptmode_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Sculpt Mode";
+ ot->idname= "SCULPT_OT_sculptmode_toggle";
+
+ /* api callbacks */
+ ot->exec= sculpt_toggle_mode;
+ ot->poll= ED_operator_object_active;
+
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+void ED_operatortypes_sculpt()
+{
+ WM_operatortype_append(SCULPT_OT_radial_control);
+ WM_operatortype_append(SCULPT_OT_brush_stroke);
+ WM_operatortype_append(SCULPT_OT_sculptmode_toggle);
+ WM_operatortype_append(SCULPT_OT_brush_curve_preset);
+}
+
+void sculpt(Sculpt *sd)
+{
+#if 0
+ SculptSession *ss= sd->session;
+ Object *ob= NULL; /*XXX */
+ Mesh *me;
+ MultiresModifierData *mmd = NULL;
+ /* lastSigMouse is for the rake, to store the last place the mouse movement was significant */
+ short mouse[2], mvalo[2], lastSigMouse[2],firsttime=1, mousebut;
+ short modifier_calculations= 0;
+ BrushAction *a = MEM_callocN(sizeof(BrushAction), "brush action");
+ short spacing= 32000;
+ int scissor_box[4];
+ float offsetRot;
+ int smooth_stroke = 0, i;
+ int anchored, rake = 0 /* XXX: rake = ? */;
+
+ /* XXX: checking that sculpting is allowed
+ if(!(G.f & G_SCULPTMODE) || G.obedit || !ob || ob->id.lib || !get_mesh(ob) || (get_mesh(ob)->totface == 0))
+ return;
+ if(!(ob->lay & G.vd->lay))
+ error("Active object is not in this layer");
+ if(ob_get_keyblock(ob)) {
+ if(!(ob->shapeflag & OB_SHAPE_LOCK)) {
+ error("Cannot sculpt on unlocked shape key");
+ return;
+ }
+ }*/
+
+ anchored = sd->brush->flag & BRUSH_ANCHORED;
+ smooth_stroke = (sd->flags & SCULPT_INPUT_SMOOTH) && (sd->brush->sculpt_tool != SCULPT_TOOL_GRAB) && !anchored;
+
+ if(smooth_stroke)
+ sculpt_stroke_new(256);
+
+ ss->damaged_rects.first = ss->damaged_rects.last = NULL;
+ ss->damaged_verts.first = ss->damaged_verts.last = NULL;
+ ss->vertexcosnos = NULL;
+
+ mmd = sculpt_multires_active(ob);
+
+ /* Check that vertex users are up-to-date */
+ if(ob != active_ob || !ss->vertex_users || ss->vertex_users_size != cache->totvert) {
+ sculpt_vertexusers_free(ss);
+ calc_vertex_users(ss);
+ if(ss->projverts)
+ MEM_freeN(ss->projverts);
+ ss->projverts = NULL;
+ active_ob= ob;
+ }
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ /*XXX:
+ persp(PERSP_VIEW);
+ getmouseco_areawin(mvalo);*/
+
+ /* Init texture
+ FIXME: Shouldn't be doing this every time! */
+ if(sd->tex_mode!=SCULPTREPT_3D)
+ sculptmode_update_tex(sd);
+
+ /*XXX: getmouseco_areawin(mouse); */
+ mvalo[0]= mouse[0];
+ mvalo[1]= mouse[1];
+ lastSigMouse[0]=mouse[0];
+ lastSigMouse[1]=mouse[1];
+ mousebut = 0; /* XXX: L_MOUSE; */
+
+ /* If modifier_calculations is true, then extra time must be spent
+ updating the mesh. This takes a *lot* longer, so it's worth
+ skipping if the modifier stack is empty. */
+ modifier_calculations= sculpt_modifiers_active(ob);
+
+ if(modifier_calculations)
+ ss->vertexcosnos= mesh_get_mapped_verts_nors(NULL, ob); /* XXX: scene = ? */
+ sculptmode_update_all_projverts(ss);
+
+ /* Capture original copy */
+ if(sd->flags & SCULPT_DRAW_FAST)
+ glAccum(GL_LOAD, 1);
+
+ /* Get original scissor box */
+ glGetIntegerv(GL_SCISSOR_BOX, scissor_box);
+
+ /* For raking, get the original angle*/
+ offsetRot=sculpt_tex_angle(sd);
+
+ me = get_mesh(ob);
+
+ while (/*XXX:get_mbut() & mousebut*/0) {
+ /* XXX: getmouseco_areawin(mouse); */
+ /* If rake, and the mouse has moved over 10 pixels (euclidean) (prevents jitter) then get the new angle */
+ if (rake && (pow(lastSigMouse[0]-mouse[0],2)+pow(lastSigMouse[1]-mouse[1],2))>100){
+ /*Nasty looking, but just orig + new angle really*/
+ set_tex_angle(sd, offsetRot+180.+to_deg(atan2((float)(mouse[1]-lastSigMouse[1]),(float)(mouse[0]-lastSigMouse[0]))));
+ lastSigMouse[0]=mouse[0];
+ lastSigMouse[1]=mouse[1];
+ }
+
+ if(firsttime || mouse[0]!=mvalo[0] || mouse[1]!=mvalo[1] ||
+ sd->brush->flag & BRUSH_AIRBRUSH) {
+ a->firsttime = firsttime;
+ firsttime= 0;
+
+ if(smooth_stroke)
+ sculpt_stroke_add_point(ss->stroke, mouse[0], mouse[1]);
+
+ spacing+= sqrt(pow(mvalo[0]-mouse[0],2)+pow(mvalo[1]-mouse[1],2));
+
+ if(modifier_calculations && !ss->vertexcosnos)
+ ss->vertexcosnos= mesh_get_mapped_verts_nors(NULL, ob); /*XXX scene = ? */
+
+ if(sd->brush->sculpt_tool != SCULPT_TOOL_GRAB) {
+ if(anchored) {
+ /* Restore the mesh before continuing with anchored stroke */
+ /*if(a->mesh_store) {
+ for(i = 0; i < cache->totvert; ++i) {
+ VecCopyf(cache->mvert[i].co, &a->mesh_store[i].x);
+ cache->mvert[i].no[0] = a->orig_norms[i][0];
+ cache->mvert[i].no[1] = a->orig_norms[i][1];
+ cache->mvert[i].no[2] = a->orig_norms[i][2];
+ }
+ }*/
+
+ //do_symmetrical_brush_actions(sd, a, mouse, NULL);
+ }
+ else {
+ if(smooth_stroke) {
+ sculpt_stroke_apply(sd, ss->stroke);
+ }
+ else if(sd->spacing==0 || spacing>sd->spacing) {
+ //do_symmetrical_brush_actions(sd, a, mouse, NULL);
+ spacing= 0;
+ }
+ }
+ }
+ else {
+ //do_symmetrical_brush_actions(sd, a, mouse, mvalo);
+ //unproject(ss, sd->pivot, mouse[0], mouse[1], a->depth);
+ }
+
+ if((!ss->multires && modifier_calculations) || ob_get_keyblock(ob)) {
+ /* XXX: DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); */ }
+
+ if(modifier_calculations || sd->brush->sculpt_tool == SCULPT_TOOL_GRAB || !(sd->flags & SCULPT_DRAW_FAST)) {
+ calc_damaged_verts(ss, a);
+ /*XXX: scrarea_do_windraw(curarea);
+ screen_swapbuffers(); */
+ } else { /* Optimized drawing */
+ calc_damaged_verts(ss, a);
+
+ /* Draw the stored image to the screen */
+ glAccum(GL_RETURN, 1);
+
+ sculpt_clear_damaged_areas(ss);
+
+ /* Draw all the polygons that are inside the modified area(s) */
+ glScissor(scissor_box[0], scissor_box[1], scissor_box[2], scissor_box[3]);
+ /* XXX: sculptmode_draw_mesh(1); */
+ glAccum(GL_LOAD, 1);
+
+ projverts_clear_inside(ss);
+
+ /* XXX: persp(PERSP_WIN); */
+ glDisable(GL_DEPTH_TEST);
+
+ /* Draw cursor */
+ if(sd->flags & SCULPT_TOOL_DRAW)
+ fdrawXORcirc((float)mouse[0],(float)mouse[1],sd->brush->size);
+ /* XXX: if(smooth_stroke)
+ sculpt_stroke_draw();
+
+ myswapbuffers(); */
+ }
+
+ BLI_freelistN(&ss->damaged_rects);
+ ss->damaged_rects.first = ss->damaged_rects.last = NULL;
+
+ mvalo[0]= mouse[0];
+ mvalo[1]= mouse[1];
+
+ if(ss->vertexcosnos) {
+ MEM_freeN(ss->vertexcosnos);
+ ss->vertexcosnos= NULL;
+ }
+
+ }
+ else { /*XXX:BIF_wait_for_statechange();*/ }
+ }
+
+ /* Set the rotation of the brush back to what it was before any rake */
+ set_tex_angle(sd, offsetRot);
+
+ if(smooth_stroke) {
+ sculpt_stroke_apply_all(sd, ss->stroke);
+ calc_damaged_verts(ss, a);
+ BLI_freelistN(&ss->damaged_rects);
+ }
+
+ //if(a->layer_disps) MEM_freeN(a->layer_disps);
+ //if(a->mesh_store) MEM_freeN(a->mesh_store);
+ //if(a->orig_norms) MEM_freeN(a->orig_norms);
+ for(i=0; i<8; ++i)
+ BLI_freelistN(&a->grab_active_verts[i]);
+ MEM_freeN(a);
+ sculpt_stroke_free(ss->stroke);
+ ss->stroke = NULL;
+
+ if(mmd) {
+ if(mmd->undo_verts && mmd->undo_verts != cache->mvert)
+ MEM_freeN(mmd->undo_verts);
+
+ mmd->undo_verts = cache->mvert;
+ mmd->undo_verts_tot = cache->totvert;
+ }
+
+ //sculpt_undo_push(sd);
+
+ /* XXX: if(G.vd->depths) G.vd->depths->damaged= 1;
+ allqueue(REDRAWVIEW3D, 0); */
+#endif
+}
+
+/* Partial Mesh Visibility */
+
+/* XXX: Partial vis. always was a mess, have to figure something out */
+#if 0
+/* mode: 0=hide outside selection, 1=hide inside selection */
+static void sculptmode_do_pmv(Object *ob, rcti *hb_2d, int mode)
+{
+ Mesh *me= get_mesh(ob);
+ float hidebox[6][3];
+ vec3f plane_normals[4];
+ float plane_ds[4];
+ unsigned i, j;
+ unsigned ndx_show, ndx_hide;
+ MVert *nve;
+ unsigned face_cnt_show= 0, face_ndx_show= 0;
+ unsigned edge_cnt_show= 0, edge_ndx_show= 0;
+ unsigned *old_map= NULL;
+ const unsigned SHOW= 0, HIDE=1;
+
+ /* Convert hide box from 2D to 3D */
+ unproject(hidebox[0], hb_2d->xmin, hb_2d->ymax, 1);
+ unproject(hidebox[1], hb_2d->xmax, hb_2d->ymax, 1);
+ unproject(hidebox[2], hb_2d->xmax, hb_2d->ymin, 1);
+ unproject(hidebox[3], hb_2d->xmin, hb_2d->ymin, 1);
+ unproject(hidebox[4], hb_2d->xmin, hb_2d->ymax, 0);
+ unproject(hidebox[5], hb_2d->xmax, hb_2d->ymin, 0);
+
+ /* Calculate normals for each side of hide box */
+ CalcNormFloat(hidebox[0], hidebox[1], hidebox[4], &plane_normals[0].x);
+ CalcNormFloat(hidebox[1], hidebox[2], hidebox[5], &plane_normals[1].x);
+ CalcNormFloat(hidebox[2], hidebox[3], hidebox[5], &plane_normals[2].x);
+ CalcNormFloat(hidebox[3], hidebox[0], hidebox[4], &plane_normals[3].x);
+
+ /* Calculate D for each side of hide box */
+ for(i= 0; i<4; ++i)
+ plane_ds[i]= hidebox[i][0]*plane_normals[i].x + hidebox[i][1]*plane_normals[i].y +
+ hidebox[i][2]*plane_normals[i].z;
+
+ /* Add partial visibility to mesh */
+ if(!me->pv) {
+ me->pv= MEM_callocN(sizeof(PartialVisibility),"PartialVisibility");
+ } else {
+ old_map= MEM_callocN(sizeof(unsigned)*me->pv->totvert,"PMV oldmap");
+ for(i=0; i<me->pv->totvert; ++i) {
+ old_map[i]= me->pv->vert_map[i]<me->totvert?0:1;
+ }
+ mesh_pmv_revert(ob, me);
+ }
+
+ /* Kill sculpt data */
+ active_ob= NULL;
+
+ /* Initalize map with which verts are to be hidden */
+ me->pv->vert_map= MEM_mallocN(sizeof(unsigned)*me->totvert, "PMV vertmap");
+ me->pv->totvert= me->totvert;
+ me->totvert= 0;
+ for(i=0; i<me->pv->totvert; ++i) {
+ me->pv->vert_map[i]= mode ? HIDE:SHOW;
+ for(j=0; j<4; ++j) {
+ if(me->mvert[i].co[0] * plane_normals[j].x +
+ me->mvert[i].co[1] * plane_normals[j].y +
+ me->mvert[i].co[2] * plane_normals[j].z < plane_ds[j] ) {
+ me->pv->vert_map[i]= mode ? SHOW:HIDE; /* Vert is outside the hide box */
+ break;
+ }
+ }
+ if(old_map && old_map[i]) me->pv->vert_map[i]= 1;
+ if(!me->pv->vert_map[i]) ++me->totvert;
+
+ }
+ if(old_map) MEM_freeN(old_map);
+
+ /* Find out how many faces to show */
+ for(i=0; i<me->totface; ++i) {
+ if(!me->pv->vert_map[me->mface[i].v1] &&
+ !me->pv->vert_map[me->mface[i].v2] &&
+ !me->pv->vert_map[me->mface[i].v3]) {
+ if(me->mface[i].v4) {
+ if(!me->pv->vert_map[me->mface[i].v4])
+ ++face_cnt_show;
+ }
+ else ++face_cnt_show;
+ }
+ }
+ /* Find out how many edges to show */
+ for(i=0; i<me->totedge; ++i) {
+ if(!me->pv->vert_map[me->medge[i].v1] &&
+ !me->pv->vert_map[me->medge[i].v2])
+ ++edge_cnt_show;
+ }
+
+ /* Create new vert array and reset each vert's map with map[old]=new index */
+ nve= MEM_mallocN(sizeof(MVert)*me->pv->totvert, "PMV verts");
+ ndx_show= 0; ndx_hide= me->totvert;
+ for(i=0; i<me->pv->totvert; ++i) {
+ if(me->pv->vert_map[i]) {
+ me->pv->vert_map[i]= ndx_hide;
+ nve[me->pv->vert_map[i]]= me->mvert[i];
+ ++ndx_hide;
+ } else {
+ me->pv->vert_map[i]= ndx_show;
+ nve[me->pv->vert_map[i]]= me->mvert[i];
+ ++ndx_show;
+ }
+ }
+ CustomData_free_layer_active(&me->vdata, CD_MVERT, me->pv->totvert);
+ me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, nve, me->totvert);
+
+ /* Create new face array */
+ me->pv->old_faces= me->mface;
+ me->pv->totface= me->totface;
+ me->mface= MEM_mallocN(sizeof(MFace)*face_cnt_show, "PMV faces");
+ for(i=0; i<me->totface; ++i) {
+ MFace *pr_f= &me->pv->old_faces[i];
+ char show= 0;
+
+ if(me->pv->vert_map[pr_f->v1] < me->totvert &&
+ me->pv->vert_map[pr_f->v2] < me->totvert &&
+ me->pv->vert_map[pr_f->v3] < me->totvert) {
+ if(pr_f->v4) {
+ if(me->pv->vert_map[pr_f->v4] < me->totvert)
+ show= 1;
+ }
+ else show= 1;
+ }
+
+ if(show) {
+ MFace *cr_f= &me->mface[face_ndx_show];
+ *cr_f= *pr_f;
+ cr_f->v1= me->pv->vert_map[pr_f->v1];
+ cr_f->v2= me->pv->vert_map[pr_f->v2];
+ cr_f->v3= me->pv->vert_map[pr_f->v3];
+ cr_f->v4= pr_f->v4 ? me->pv->vert_map[pr_f->v4] : 0;
+ test_index_face(cr_f,NULL,0,pr_f->v4?4:3);
+ ++face_ndx_show;
+ }
+ }
+ me->totface= face_cnt_show;
+ CustomData_set_layer(&me->fdata, CD_MFACE, me->mface);
+
+ /* Create new edge array */
+ me->pv->old_edges= me->medge;
+ me->pv->totedge= me->totedge;
+ me->medge= MEM_mallocN(sizeof(MEdge)*edge_cnt_show, "PMV edges");
+ me->pv->edge_map= MEM_mallocN(sizeof(int)*me->pv->totedge,"PMV edgemap");
+ for(i=0; i<me->totedge; ++i) {
+ if(me->pv->vert_map[me->pv->old_edges[i].v1] < me->totvert &&
+ me->pv->vert_map[me->pv->old_edges[i].v2] < me->totvert) {
+ MEdge *cr_e= &me->medge[edge_ndx_show];
+ me->pv->edge_map[i]= edge_ndx_show;
+ *cr_e= me->pv->old_edges[i];
+ cr_e->v1= me->pv->vert_map[me->pv->old_edges[i].v1];
+ cr_e->v2= me->pv->vert_map[me->pv->old_edges[i].v2];
+ ++edge_ndx_show;
+ }
+ else me->pv->edge_map[i]= -1;
+ }
+ me->totedge= edge_cnt_show;
+ CustomData_set_layer(&me->edata, CD_MEDGE, me->medge);
+
+ /* XXX: DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA); */
+}
+
+static rcti sculptmode_pmv_box()
+{
+ /*XXX: short down[2], mouse[2];
+ rcti ret;
+
+ getmouseco_areawin(down);
+
+ while((get_mbut()&L_MOUSE) || (get_mbut()&R_MOUSE)) {
+ getmouseco_areawin(mouse);
+
+ scrarea_do_windraw(curarea);
+
+ persp(PERSP_WIN);
+ glLineWidth(2);
+ setlinestyle(2);
+ sdrawXORline(down[0],down[1],mouse[0],down[1]);
+ sdrawXORline(mouse[0],down[1],mouse[0],mouse[1]);
+ sdrawXORline(mouse[0],mouse[1],down[0],mouse[1]);
+ sdrawXORline(down[0],mouse[1],down[0],down[1]);
+ setlinestyle(0);
+ glLineWidth(1);
+ persp(PERSP_VIEW);
+
+ screen_swapbuffers();
+ backdrawview3d(0);
+ }
+
+ ret.xmin= down[0]<mouse[0]?down[0]:mouse[0];
+ ret.ymin= down[1]<mouse[1]?down[1]:mouse[1];
+ ret.xmax= down[0]>mouse[0]?down[0]:mouse[0];
+ ret.ymax= down[1]>mouse[1]?down[1]:mouse[1];
+ return ret;*/
+}
+
+void sculptmode_pmv(int mode)
+{
+ Object *ob= NULL; /*XXX: OBACT; */
+ rcti hb_2d;
+
+ if(ob_get_key(ob)) {
+ error("Cannot hide mesh with shape keys enabled");
+ return;
+ }
+
+ hb_2d= sculptmode_pmv_box(); /* Get 2D hide box */
+
+ sculptmode_correct_state();
+
+ waitcursor(1);
+
+ if(hb_2d.xmax-hb_2d.xmin > 3 && hb_2d.ymax-hb_2d.ymin > 3) {
+ init_sculptmatrices();
+
+ sculptmode_do_pmv(ob,&hb_2d,mode);
+ }
+ else mesh_pmv_off(ob, get_mesh(ob));
+
+ /*XXX: scrarea_do_windraw(curarea); */
+
+ waitcursor(0);
+}
+#endif
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
new file mode 100644
index 00000000000..112da5b4f0f
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -0,0 +1,67 @@
+/*
+ * $Id: BDR_sculptmode.h 13396 2008-01-25 04:17:38Z nicholasbishop $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 by Nicholas Bishop
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BDR_SCULPTMODE_H
+#define BDR_SCULPTMODE_H
+
+#include "DNA_listBase.h"
+#include "DNA_vec_types.h"
+#include "BKE_sculpt.h"
+
+struct Brush;
+struct Mesh;
+struct Object;
+struct Scene;
+struct Sculpt;
+struct SculptStroke;
+
+/* Interface */
+void sculptmode_selectbrush_menu(void);
+void sculptmode_draw_mesh(int);
+void sculpt_paint_brush(char clear);
+void sculpt_stroke_draw(struct SculptStroke *);
+void sculpt_radialcontrol_start(int mode);
+
+struct Brush *sculptmode_brush(void);
+//void do_symmetrical_brush_actions(struct Sculpt *sd, struct wmOperator *wm, struct BrushAction *a, short *, short *);
+
+char sculpt_modifiers_active(struct Object *ob);
+void sculpt(Sculpt *sd);
+
+/* Stroke */
+struct SculptStroke *sculpt_stroke_new(const int max);
+void sculpt_stroke_free(struct SculptStroke *);
+void sculpt_stroke_add_point(struct SculptStroke *, const short x, const short y);
+void sculpt_stroke_apply(struct Sculpt *sd, struct SculptStroke *);
+void sculpt_stroke_apply_all(struct Sculpt *sd, struct SculptStroke *);
+
+/* Partial Mesh Visibility */
+void sculptmode_pmv(int mode);
+
+#endif
diff --git a/source/blender/editors/sculpt_paint/sculpt_stroke.c b/source/blender/editors/sculpt_paint/sculpt_stroke.c
new file mode 100644
index 00000000000..554ff580358
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_stroke.c
@@ -0,0 +1,274 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by Nicholas Bishop
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Storage and manipulation of sculptmode brush strokes.
+ *
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_sculpt.h"
+#include "BLI_blenlib.h"
+#include "BIF_gl.h"
+
+#include "sculpt_intern.h"
+
+#include <math.h>
+
+/* Temporary storage of input stroke control points */
+typedef struct StrokePoint {
+ struct StrokePoint *next, *prev;
+ short x, y;
+} StrokePoint;
+typedef struct SculptStroke {
+ short (*loc)[2];
+ int max;
+ int index;
+ float length;
+ ListBase final;
+ StrokePoint *final_mem;
+ float offset;
+} SculptStroke;
+
+SculptStroke *sculpt_stroke_new(const int max)
+{
+ SculptStroke *stroke = MEM_callocN(sizeof(SculptStroke), "SculptStroke");
+ stroke->loc = MEM_callocN(sizeof(short) * 4 * max, "SculptStroke.loc");
+ stroke->max = max;
+ stroke->index = -1;
+ return stroke;
+}
+
+void sculpt_stroke_free(SculptStroke *stroke)
+{
+ if(stroke) {
+ if(stroke->loc) MEM_freeN(stroke->loc);
+ if(stroke->final_mem) MEM_freeN(stroke->final_mem);
+
+ MEM_freeN(stroke);
+ }
+}
+
+void sculpt_stroke_add_point(SculptStroke *stroke, const short x, const short y)
+{
+ const int next = stroke->index + 1;
+
+ if(stroke->index == -1) {
+ stroke->loc[0][0] = x;
+ stroke->loc[0][1] = y;
+ stroke->index = 0;
+ }
+ else if(next < stroke->max) {
+ const int dx = x - stroke->loc[stroke->index][0];
+ const int dy = y - stroke->loc[stroke->index][1];
+ stroke->loc[next][0] = x;
+ stroke->loc[next][1] = y;
+ stroke->length += sqrt(dx*dx + dy*dy);
+ stroke->index = next;
+ }
+}
+
+static void sculpt_stroke_smooth(SculptStroke *stroke)
+{
+ /* Apply smoothing (exclude the first and last points)*/
+ StrokePoint *p = stroke->final.first;
+ if(p && p->next && p->next->next) {
+ for(p = p->next->next; p && p->next && p->next->next; p = p->next) {
+ p->x = p->prev->prev->x*0.1 + p->prev->x*0.2 + p->x*0.4 + p->next->x*0.2 + p->next->next->x*0.1;
+ p->y = p->prev->prev->y*0.1 + p->prev->y*0.2 + p->y*0.4 + p->next->y*0.2 + p->next->next->y*0.1;
+ }
+ }
+}
+
+static void sculpt_stroke_create_final(SculptStroke *stroke)
+{
+ if(stroke) {
+ StrokePoint *p, *pnext;
+ int i;
+
+ /* Copy loc into final */
+ if(stroke->final_mem)
+ MEM_freeN(stroke->final_mem);
+ stroke->final_mem = MEM_callocN(sizeof(StrokePoint) * (stroke->index + 1) * 2, "SculptStroke.final");
+ stroke->final.first = stroke->final.last = NULL;
+ for(i = 0; i <= stroke->index; ++i) {
+ p = &stroke->final_mem[i];
+ p->x = stroke->loc[i][0];
+ p->y = stroke->loc[i][1];
+ BLI_addtail(&stroke->final, p);
+ }
+
+ /* Remove shortest edges */
+ if(stroke->final.first) {
+ for(p = ((StrokePoint*)stroke->final.first)->next; p && p->next; p = pnext) {
+ const int dx = p->x - p->prev->x;
+ const int dy = p->y - p->prev->y;
+ const float len = sqrt(dx*dx + dy*dy);
+ pnext = p->next;
+ if(len < 10) {
+ BLI_remlink(&stroke->final, p);
+ }
+ }
+ }
+
+ sculpt_stroke_smooth(stroke);
+
+ /* Subdivide edges */
+ for(p = stroke->final.first; p && p->next; p = pnext) {
+ StrokePoint *np = &stroke->final_mem[i++];
+
+ pnext = p->next;
+ np->x = (p->x + p->next->x) / 2;
+ np->y = (p->y + p->next->y) / 2;
+ BLI_insertlink(&stroke->final, p, np);
+ }
+
+ sculpt_stroke_smooth(stroke);
+ }
+}
+
+static float sculpt_stroke_seglen(StrokePoint *p1, StrokePoint *p2)
+{
+ int dx = p2->x - p1->x;
+ int dy = p2->y - p1->y;
+ return sqrt(dx*dx + dy*dy);
+}
+
+static float sculpt_stroke_final_length(SculptStroke *stroke)
+{
+ StrokePoint *p;
+ float len = 0;
+ for(p = stroke->final.first; p && p->next; ++p)
+ len += sculpt_stroke_seglen(p, p->next);
+ return len;
+}
+
+/* If partial is nonzero, cuts off apply after that length has been processed */
+static StrokePoint *sculpt_stroke_apply_generic(Sculpt *sd, SculptStroke *stroke, const int partial)
+{
+ const int sdspace = 0; //XXX: sd->spacing;
+ const short spacing = sdspace > 0 ? sdspace : 2;
+ const int dots = sculpt_stroke_final_length(stroke) / spacing;
+ int i;
+ StrokePoint *p = stroke->final.first;
+ float startloc = stroke->offset;
+
+ for(i = 0; i < dots && p && p->next; ++i) {
+ const float dotloc = spacing * i;
+ short co[2];
+ float len = sculpt_stroke_seglen(p, p->next);
+ float u, v;
+
+ /* Find edge containing dot */
+ while(dotloc > startloc + len && p && p->next && p->next->next) {
+ p = p->next;
+ startloc += len;
+ len = sculpt_stroke_seglen(p, p->next);
+ }
+
+ if(!p || !p->next || dotloc > startloc + len)
+ break;
+
+ if(partial && startloc > partial) {
+ /* Calculate offset for next stroke segment */
+ stroke->offset = startloc + len - dotloc;
+ break;
+ }
+
+ u = (dotloc - startloc) / len;
+ v = 1 - u;
+
+ co[0] = p->x*v + p->next->x*u;
+ co[1] = p->y*v + p->next->y*u;
+
+ //do_symmetrical_brush_actions(sd, a, co, NULL);
+ }
+
+ return p ? p->next : NULL;
+}
+
+void sculpt_stroke_apply(Sculpt *sd, SculptStroke *stroke)
+{
+ /* TODO: make these values user-modifiable? */
+ const int partial_len = 100;
+ const int min_len = 200;
+
+ if(stroke) {
+ sculpt_stroke_create_final(stroke);
+
+ if(sculpt_stroke_final_length(stroke) > min_len) {
+ StrokePoint *p = sculpt_stroke_apply_generic(sd, stroke, partial_len);
+
+ /* Replace remaining values in stroke->loc with remaining stroke->final values */
+ stroke->index = -1;
+ stroke->length = 0;
+ for(; p; p = p->next) {
+ ++stroke->index;
+ stroke->loc[stroke->index][0] = p->x;
+ stroke->loc[stroke->index][1] = p->y;
+ if(p->next) {
+ stroke->length += sculpt_stroke_seglen(p, p->next);
+ }
+ }
+ }
+ }
+}
+
+void sculpt_stroke_apply_all(Sculpt *sd, SculptStroke *stroke)
+{
+ sculpt_stroke_create_final(stroke);
+
+ if(stroke) {
+ sculpt_stroke_apply_generic(sd, stroke, 0);
+ }
+}
+
+/* XXX: drawing goes elsewhere */
+void sculpt_stroke_draw(SculptStroke *stroke)
+{
+ if(stroke) {
+ StrokePoint *p;
+
+ /* Draws the original stroke */
+ /*glColor3f(1, 0, 0);
+ glBegin(GL_LINE_STRIP);
+ for(i = 0; i <= stroke->index; ++i)
+ glVertex2s(stroke->loc[i][0], stroke->loc[i][1]);
+ glEnd();*/
+
+ /* Draws the smoothed stroke */
+ glColor3f(0, 1, 0);
+ glBegin(GL_LINE_STRIP);
+ for(p = stroke->final.first; p; p = p->next)
+ glVertex2s(p->x, p->y);
+ glEnd();
+ }
+}
diff --git a/source/blender/editors/space_action/Makefile b/source/blender/editors/space_action/Makefile
new file mode 100644
index 00000000000..840f31b8a40
--- /dev/null
+++ b/source/blender/editors/space_action/Makefile
@@ -0,0 +1,54 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_action
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/space_action/SConscript b/source/blender/editors/space_action/SConscript
new file mode 100644
index 00000000000..9ef42882b26
--- /dev/null
+++ b/source/blender/editors/space_action/SConscript
@@ -0,0 +1,9 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+
+env.BlenderLib ( 'bf_editors_space_action', sources, Split(incs), [], libtype=['core'], priority=[80] )
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
new file mode 100644
index 00000000000..a551b4f463c
--- /dev/null
+++ b/source/blender/editors/space_action/action_draw.c
@@ -0,0 +1,1246 @@
+/**
+ * $Id: drawaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* System includes ----------------------------------------------------- */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+/* Types --------------------------------------------------------------- */
+
+#include "DNA_listBase.h"
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_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 "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_action.h"
+#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+#include "BKE_global.h" // XXX remove me!
+#include "BKE_context.h"
+#include "BKE_utildefines.h"
+
+/* Everything from source (BIF, BDR, BSE) ------------------------------ */
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_draw.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+#if 0 // XXX old includes for reference only
+ #include "BIF_editaction.h"
+ #include "BIF_editkey.h"
+ #include "BIF_editnla.h"
+ #include "BIF_drawgpencil.h"
+ #include "BIF_keyframing.h"
+ #include "BIF_language.h"
+ #include "BIF_space.h"
+
+ #include "BDR_editcurve.h"
+ #include "BDR_gpencil.h"
+
+ #include "BSE_drawnla.h"
+ #include "BSE_drawipo.h"
+ #include "BSE_drawview.h"
+ #include "BSE_editaction_types.h"
+ #include "BSE_editipo.h"
+ #include "BSE_headerbuttons.h"
+ #include "BSE_time.h"
+ #include "BSE_view.h"
+#endif // XXX old defines for reference only
+
+/* XXX */
+extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);
+
+/********************************** Slider Stuff **************************** */
+
+#if 0 // XXX all of this slider stuff will need a rethink!
+/* sliders for shapekeys */
+static void meshactionbuts(SpaceAction *saction, Object *ob, Key *key)
+{
+ int i;
+ char str[64];
+ float x, y;
+ uiBlock *block;
+ uiBut *but;
+
+ /* lets make the shapekey sliders */
+
+ /* reset the damn myortho2 or the sliders won't draw/redraw
+ * correctly *grumble*
+ */
+ mywinset(curarea->win);
+ myortho2(-0.375f, curarea->winx-0.375f, G.v2d->cur.ymin, G.v2d->cur.ymax);
+
+ sprintf(str, "actionbuttonswin %d", curarea->win);
+ block= uiNewBlock (&curarea->uiblocks, str, UI_EMBOSS);
+
+ x = ACHANNEL_NAMEWIDTH + 1;
+ y = 0.0f;
+
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+
+ if (!(G.saction->flag & SACTION_SLIDERS)) {
+ ACTWIDTH = ACHANNEL_NAMEWIDTH;
+ but=uiDefIconButBitS(block, TOG, SACTION_SLIDERS, B_REDR,
+ ICON_DISCLOSURE_TRI_RIGHT,
+ ACHANNEL_NAMEWIDTH - XIC - 5, (short)y + CHANNELHEIGHT,
+ XIC,YIC-2,
+ &(G.saction->flag), 0, 0, 0, 0,
+ "Show action window sliders");
+ /* no hilite, the winmatrix is not correct later on... */
+ uiButSetFlag(but, UI_NO_HILITE);
+ }
+ else {
+ but= uiDefIconButBitS(block, TOG, SACTION_SLIDERS, B_REDR,
+ ICON_DISCLOSURE_TRI_DOWN,
+ ACHANNEL_NAMEWIDTH - XIC - 5, (short)y + CHANNELHEIGHT,
+ XIC,YIC-2,
+ &(G.saction->flag), 0, 0, 0, 0,
+ "Hide action window sliders");
+ /* no hilite, the winmatrix is not correct later on... */
+ uiButSetFlag(but, UI_NO_HILITE);
+
+ ACTWIDTH = ACHANNEL_NAMEWIDTH + SLIDERWIDTH;
+
+ /* sliders are open so draw them */
+ BIF_ThemeColor(TH_FACE);
+
+ glRects(ACHANNEL_NAMEWIDTH, 0, ACHANNEL_NAMEWIDTH+SLIDERWIDTH, curarea->winy);
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ for (i=1; i < key->totkey; i++) {
+ make_rvk_slider(block, ob, i,
+ (int)x, (int)y, SLIDERWIDTH-2, CHANNELHEIGHT-1, "Slider to control Shape Keys");
+
+ y-=CHANNELHEIGHT+CHANNELSKIP;
+
+ /* see sliderval array in editkey.c */
+ if (i >= 255) break;
+ }
+ }
+ uiDrawBlock(C, block);
+}
+
+static void icu_slider_func(void *voidicu, void *voidignore)
+{
+ /* the callback for the icu sliders ... copies the
+ * value from the icu->curval into a bezier at the
+ * right frame on the right ipo curve (creating both the
+ * ipo curve and the bezier if needed).
+ */
+ IpoCurve *icu= voidicu;
+ BezTriple *bezt=NULL;
+ float cfra, icuval;
+
+ cfra = frame_to_float(CFRA);
+ if (G.saction->pin==0 && OBACT)
+ cfra= get_action_frame(OBACT, cfra);
+
+ /* if the ipocurve exists, try to get a bezier
+ * for this frame
+ */
+ bezt = get_bezt_icu_time(icu, &cfra, &icuval);
+
+ /* create the bezier triple if one doesn't exist,
+ * otherwise modify it's value
+ */
+ if (bezt == NULL) {
+ insert_vert_icu(icu, cfra, icu->curval, 0);
+ }
+ else {
+ bezt->vec[1][1] = icu->curval;
+ }
+
+ /* make sure the Ipo's are properly processed and
+ * redraw as necessary
+ */
+ sort_time_ipocurve(icu);
+ testhandles_ipocurve(icu);
+
+ /* nla-update (in case this affects anything) */
+ synchronize_action_strips();
+
+ /* do redraw pushes, and also the depsgraph flushes */
+ if (OBACT->pose || ob_get_key(OBACT))
+ DAG_object_flush_update(G.scene, OBACT, OB_RECALC);
+ else
+ DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB);
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWIPO, 0);
+ allspace(REMAKEIPO, 0);
+ allqueue(REDRAWBUTSALL, 0);
+}
+
+static void make_icu_slider(uiBlock *block, IpoCurve *icu,
+ int x, int y, int w, int h, char *tip)
+{
+ /* create a slider for the ipo-curve*/
+ uiBut *but;
+
+ if(icu == NULL) return;
+
+ if (IS_EQ(icu->slide_max, icu->slide_min)) {
+ if (IS_EQ(icu->ymax, icu->ymin)) {
+ if (ELEM(icu->blocktype, ID_CO, ID_KE)) {
+ /* hack for constraints and shapekeys (and maybe a few others) */
+ icu->slide_min= 0.0;
+ icu->slide_max= 1.0;
+ }
+ else {
+ icu->slide_min= -100;
+ icu->slide_max= 100;
+ }
+ }
+ else {
+ icu->slide_min= icu->ymin;
+ icu->slide_max= icu->ymax;
+ }
+ }
+ if (icu->slide_min >= icu->slide_max) {
+ SWAP(float, icu->slide_min, icu->slide_max);
+ }
+
+ but=uiDefButF(block, NUMSLI, REDRAWVIEW3D, "",
+ x, y , w, h,
+ &(icu->curval), icu->slide_min, icu->slide_max,
+ 10, 2, tip);
+
+ uiButSetFunc(but, icu_slider_func, icu, NULL);
+
+ // no hilite, the winmatrix is not correct later on...
+ uiButSetFlag(but, UI_NO_HILITE);
+}
+
+/* sliders for ipo-curves of active action-channel */
+static void action_icu_buts(SpaceAction *saction)
+{
+ ListBase act_data = {NULL, NULL};
+ bActListElem *ale;
+ int filter;
+ void *data;
+ short datatype;
+
+ char str[64];
+ float x, y;
+ uiBlock *block;
+
+ /* lets make the action sliders */
+
+ /* reset the damn myortho2 or the sliders won't draw/redraw
+ * correctly *grumble*
+ */
+ mywinset(curarea->win);
+ myortho2(-0.375f, curarea->winx-0.375f, G.v2d->cur.ymin, G.v2d->cur.ymax);
+
+ sprintf(str, "actionbuttonswin %d", curarea->win);
+ block= uiNewBlock (&curarea->uiblocks, str, UI_EMBOSS);
+
+ x = (float)ACHANNEL_NAMEWIDTH + 1;
+ y = 0.0f;
+
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+
+ if (G.saction->flag & SACTION_SLIDERS) {
+ /* sliders are open so draw them */
+
+ /* get editor data */
+ data= get_action_context(&datatype);
+ if (data == NULL) return;
+
+ /* build list of channels to draw */
+ filter= (ACTFILTER_FORDRAWING|ACTFILTER_VISIBLE|ACTFILTER_CHANNELS);
+ actdata_filter(&act_data, filter, data, datatype);
+
+ /* draw backdrop first */
+ BIF_ThemeColor(TH_FACE); // change this color... it's ugly
+ glRects(ACHANNEL_NAMEWIDTH, (short)G.v2d->cur.ymin, ACHANNEL_NAMEWIDTH+SLIDERWIDTH, (short)G.v2d->cur.ymax);
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ for (ale= act_data.first; ale; ale= ale->next) {
+ const float yminc= y-CHANNELHEIGHT/2;
+ const float ymaxc= y+CHANNELHEIGHT/2;
+
+ /* check if visible */
+ if ( IN_RANGE(yminc, G.v2d->cur.ymin, G.v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, G.v2d->cur.ymin, G.v2d->cur.ymax) )
+ {
+ /* determine what needs to be drawn */
+ switch (ale->type) {
+ case ACTTYPE_CONCHAN: /* constraint channel */
+ {
+ bActionChannel *achan = (bActionChannel *)ale->owner;
+ IpoCurve *icu = (IpoCurve *)ale->key_data;
+
+ /* only show if owner is selected */
+ if ((ale->ownertype == ACTTYPE_OBJECT) || SEL_ACHAN(achan)) {
+ make_icu_slider(block, icu,
+ (int)x, (int)y, SLIDERWIDTH-2, CHANNELHEIGHT-2,
+ "Slider to control current value of Constraint Influence");
+ }
+ }
+ break;
+ case ACTTYPE_ICU: /* ipo-curve channel */
+ {
+ bActionChannel *achan = (bActionChannel *)ale->owner;
+ IpoCurve *icu = (IpoCurve *)ale->key_data;
+
+ /* only show if owner is selected */
+ if ((ale->ownertype == ACTTYPE_OBJECT) || SEL_ACHAN(achan)) {
+ make_icu_slider(block, icu,
+ (int)x, (int)y, SLIDERWIDTH-2, CHANNELHEIGHT-2,
+ "Slider to control current value of IPO-Curve");
+ }
+ }
+ break;
+ case ACTTYPE_SHAPEKEY: /* shapekey channel */
+ {
+ Object *ob= (Object *)ale->id;
+ IpoCurve *icu= (IpoCurve *)ale->key_data;
+
+ // TODO: only show if object is active
+ if (icu) {
+ make_icu_slider(block, icu,
+ (int)x, (int)y, SLIDERWIDTH-2, CHANNELHEIGHT-2,
+ "Slider to control ShapeKey");
+ }
+ else if (ob && ale->index) {
+ make_rvk_slider(block, ob, ale->index,
+ (int)x, (int)y, SLIDERWIDTH-2, CHANNELHEIGHT-1, "Slider to control Shape Keys");
+ }
+ }
+ break;
+ }
+ }
+
+ /* adjust y-position for next one */
+ y-=CHANNELHEIGHT+CHANNELSKIP;
+ }
+
+ /* free tempolary channels */
+ BLI_freelistN(&act_data);
+ }
+ uiDrawBlock(C, block);
+}
+
+#endif // XXX all of this slider stuff will need a rethink
+
+
+/* ************************************************************************* */
+/* Channel List */
+
+/* left hand part */
+void draw_channel_names(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ View2D *v2d= &ar->v2d;
+ float x= 0.0f, y= 0.0f;
+ int items, height;
+
+ /* build list of channels to draw */
+ filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
+ items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* Update max-extent of channels here (taking into account scrollers):
+ * - this is done to allow the channel list to be scrollable, but must be done here
+ * to avoid regenerating the list again and/or also because channels list is drawn first
+ * - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
+ * start of list offset, and the second is as a correction for the scrollers.
+ */
+ height= ((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2));
+ if (height > (v2d->mask.ymax - v2d->mask.ymin)) {
+ /* don't use totrect set, as the width stays the same
+ * (NOTE: this is ok here, the configuration is pretty straightforward)
+ */
+ v2d->tot.ymin= (float)(-height);
+ }
+
+ /* loop through channels, and set up drawing depending on their type */
+ y= (float)ACHANNEL_FIRST;
+
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
+ const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
+
+ /* check if visible */
+ if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
+ {
+ bActionGroup *grp = NULL;
+ short indent= 0, offset= 0, sel= 0, group= 0;
+ int expand= -1, protect = -1, special= -1, mute = -1;
+ char name[128];
+
+ /* determine what needs to be drawn */
+ switch (ale->type) {
+ case ANIMTYPE_SCENE: /* scene */
+ {
+ Scene *sce= (Scene *)ale->data;
+
+ group= 4;
+ indent= 0;
+
+ special= ICON_SCENE_DATA;
+
+ /* only show expand if there are any channels */
+ if (EXPANDED_SCEC(sce))
+ expand= ICON_TRIA_DOWN;
+ else
+ expand= ICON_TRIA_RIGHT;
+
+ sel = SEL_SCEC(sce);
+ strcpy(name, sce->id.name+2);
+ }
+ break;
+ case ANIMTYPE_OBJECT: /* object */
+ {
+ Base *base= (Base *)ale->data;
+ Object *ob= base->object;
+
+ group= 4;
+ indent= 0;
+
+ /* icon depends on object-type */
+ if (ob->type == OB_ARMATURE)
+ special= ICON_ARMATURE_DATA;
+ else
+ special= ICON_OBJECT_DATA;
+
+ /* only show expand if there are any channels */
+ if (EXPANDED_OBJC(ob))
+ expand= ICON_TRIA_DOWN;
+ else
+ expand= ICON_TRIA_RIGHT;
+
+ sel = SEL_OBJC(base);
+ strcpy(name, ob->id.name+2);
+ }
+ break;
+ case ANIMTYPE_FILLACTD: /* action widget */
+ {
+ bAction *act= (bAction *)ale->data;
+
+ group = 4;
+ indent= 1;
+ special= ICON_ACTION;
+
+ if (EXPANDED_ACTC(act))
+ expand= ICON_TRIA_DOWN;
+ else
+ expand= ICON_TRIA_RIGHT;
+
+ sel = SEL_ACTC(act);
+ strcpy(name, act->id.name+2);
+ }
+ break;
+ case ANIMTYPE_FILLMATD: /* object materials (dopesheet) expand widget */
+ {
+ Object *ob = (Object *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_MATERIAL_DATA;
+
+ if (FILTER_MAT_OBJC(ob))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, "Materials");
+ }
+ break;
+
+
+ case ANIMTYPE_DSMAT: /* single material (dopesheet) expand widget */
+ {
+ Material *ma = (Material *)ale->data;
+
+ group = 0;
+ indent = 0;
+ special = ICON_MATERIAL_DATA;
+ offset = 21;
+
+ if (FILTER_MAT_OBJD(ma))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, ma->id.name+2);
+ }
+ break;
+ case ANIMTYPE_DSLAM: /* lamp (dopesheet) expand widget */
+ {
+ Lamp *la = (Lamp *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_LAMP_DATA;
+
+ if (FILTER_LAM_OBJD(la))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, la->id.name+2);
+ }
+ break;
+ case ANIMTYPE_DSCAM: /* camera (dopesheet) expand widget */
+ {
+ Camera *ca = (Camera *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_CAMERA_DATA;
+
+ if (FILTER_CAM_OBJD(ca))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, ca->id.name+2);
+ }
+ break;
+ case ANIMTYPE_DSCUR: /* curve (dopesheet) expand widget */
+ {
+ Curve *cu = (Curve *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_CURVE_DATA;
+
+ if (FILTER_CUR_OBJD(cu))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, cu->id.name+2);
+ }
+ break;
+ case ANIMTYPE_DSSKEY: /* shapekeys (dopesheet) expand widget */
+ {
+ Key *key= (Key *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_SHAPEKEY_DATA; // XXX
+
+ if (FILTER_SKE_OBJD(key))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ //sel = SEL_OBJC(base);
+ strcpy(name, "Shape Keys");
+ }
+ break;
+ case ANIMTYPE_DSWOR: /* world (dopesheet) expand widget */
+ {
+ World *wo= (World *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_WORLD_DATA;
+
+ if (FILTER_WOR_SCED(wo))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, wo->id.name+2);
+ }
+ break;
+
+
+ case ANIMTYPE_GROUP: /* action group */
+ {
+ bActionGroup *agrp= (bActionGroup *)ale->data;
+
+ group= 2;
+ indent= 0;
+ special= -1;
+
+ if (ale->id) {
+ /* special exception for materials */
+ if (GS(ale->id->name) == ID_MA)
+ offset= 25;
+ else
+ offset= 14;
+ }
+ else
+ offset= 0;
+
+ /* only show expand if there are any channels */
+ if (agrp->channels.first) {
+ if (EXPANDED_AGRP(agrp))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+ }
+
+ if (EDITABLE_AGRP(agrp))
+ protect = ICON_UNLOCKED;
+ else
+ protect = ICON_LOCKED;
+
+ sel = SEL_AGRP(agrp);
+ strcpy(name, agrp->name);
+ }
+ break;
+ case ANIMTYPE_FCURVE: /* F-Curve channel */
+ {
+ FCurve *fcu = (FCurve *)ale->data;
+
+ indent = 0;
+
+ group= (fcu->grp) ? 1 : 0;
+ grp= fcu->grp;
+
+ if (ale->id) {
+ /* special exception for materials */
+ if (GS(ale->id->name) == ID_MA) {
+ offset= 21;
+ indent= 1;
+ }
+ else
+ offset= 14;
+ }
+ else
+ offset= 0;
+
+ if (fcu->flag & FCURVE_MUTED)
+ mute = ICON_MUTE_IPO_ON;
+ else
+ mute = ICON_MUTE_IPO_OFF;
+
+ if (fcu->bezt) {
+ if (EDITABLE_FCU(fcu))
+ protect = ICON_UNLOCKED;
+ else
+ protect = ICON_LOCKED;
+ }
+ else
+ protect = ICON_ZOOMOUT; // XXX editability is irrelevant here, but this icon is temp...
+
+ sel = SEL_FCU(fcu);
+
+ getname_anim_fcurve(name, ale->id, fcu);
+ }
+ break;
+
+ case ANIMTYPE_SHAPEKEY: /* shapekey channel */
+ {
+ KeyBlock *kb = (KeyBlock *)ale->data;
+
+ indent = 0;
+ special = -1;
+
+ offset= (ale->id) ? 21 : 0;
+
+ if (kb->name[0] == '\0')
+ sprintf(name, "Key %d", ale->index);
+ else
+ strcpy(name, kb->name);
+ }
+ break;
+
+ case ANIMTYPE_GPDATABLOCK: /* gpencil datablock */
+ {
+ bGPdata *gpd = (bGPdata *)ale->data;
+ ScrArea *sa = (ScrArea *)ale->owner;
+
+ indent = 0;
+ group= 3;
+
+ /* only show expand if there are any channels */
+ if (gpd->layers.first) {
+ if (gpd->flag & GP_DATA_EXPAND)
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+ }
+
+ switch (sa->spacetype) {
+ case SPACE_VIEW3D:
+ {
+ /* this shouldn't cause any overflow... */
+ //sprintf(name, "3DView:%s", view3d_get_name(sa->spacedata.first)); // XXX missing func..
+ strcpy(name, "3dView");
+ special= ICON_VIEW3D;
+ }
+ break;
+ case SPACE_NODE:
+ {
+ SpaceNode *snode= sa->spacedata.first;
+ char treetype[12];
+
+ if (snode->treetype == 1)
+ strcpy(treetype, "Composite");
+ else
+ strcpy(treetype, "Material");
+ sprintf(name, "Nodes:%s", treetype);
+
+ special= ICON_NODE;
+ }
+ break;
+ case SPACE_SEQ:
+ {
+ SpaceSeq *sseq= sa->spacedata.first;
+ char imgpreview[10];
+
+ switch (sseq->mainb) {
+ case 1: sprintf(imgpreview, "Image..."); break;
+ case 2: sprintf(imgpreview, "Luma..."); break;
+ case 3: sprintf(imgpreview, "Chroma..."); break;
+ case 4: sprintf(imgpreview, "Histogram"); break;
+
+ default: sprintf(imgpreview, "Sequence"); break;
+ }
+ sprintf(name, "Sequencer:%s", imgpreview);
+
+ special= ICON_SEQUENCE;
+ }
+ break;
+ case SPACE_IMAGE:
+ {
+ SpaceImage *sima= sa->spacedata.first;
+
+ if (sima->image)
+ sprintf(name, "Image:%s", sima->image->id.name+2);
+ else
+ strcpy(name, "Image:<None>");
+
+ special= ICON_IMAGE_COL;
+ }
+ break;
+
+ default:
+ {
+ sprintf(name, "<Unknown GP-Data Source>");
+ special= -1;
+ }
+ break;
+ }
+ }
+ break;
+ case ANIMTYPE_GPLAYER: /* gpencil layer */
+ {
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+
+ indent = 0;
+ special = -1;
+ expand = -1;
+ group = 1;
+
+ if (EDITABLE_GPL(gpl))
+ protect = ICON_UNLOCKED;
+ else
+ protect = ICON_LOCKED;
+
+ if (gpl->flag & GP_LAYER_HIDE)
+ mute = ICON_MUTE_IPO_ON;
+ else
+ mute = ICON_MUTE_IPO_OFF;
+
+ sel = SEL_GPL(gpl);
+ BLI_snprintf(name, 32, gpl->info);
+ }
+ break;
+ }
+
+ /* now, start drawing based on this information */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ /* draw backing strip behind channel name */
+ if (group == 4) {
+ /* only used in dopesheet... */
+ if (ELEM(ale->type, ANIMTYPE_SCENE, ANIMTYPE_OBJECT)) {
+ /* object channel - darker */
+ UI_ThemeColor(TH_DOPESHEET_CHANNELOB);
+ uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
+ gl_round_box(GL_POLYGON, x+offset, yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
+ }
+ else {
+ /* sub-object folders - lighter */
+ UI_ThemeColor(TH_DOPESHEET_CHANNELSUBOB);
+
+ offset += 7 * indent;
+ glBegin(GL_QUADS);
+ glVertex2f(x+offset, yminc);
+ glVertex2f(x+offset, ymaxc);
+ glVertex2f((float)ACHANNEL_NAMEWIDTH, ymaxc);
+ glVertex2f((float)ACHANNEL_NAMEWIDTH, yminc);
+ glEnd();
+
+ /* clear group value, otherwise we cause errors... */
+ group = 0;
+ }
+ }
+ else if (group == 3) {
+ /* only for gp-data channels */
+ UI_ThemeColorShade(TH_GROUP, 20);
+ uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
+ gl_round_box(GL_POLYGON, x+offset, yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
+ }
+ else if (group == 2) {
+ /* only for action group channels */
+ if (ale->flag & AGRP_ACTIVE)
+ UI_ThemeColorShade(TH_GROUP_ACTIVE, 10);
+ else
+ UI_ThemeColorShade(TH_GROUP, 20);
+ uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
+ gl_round_box(GL_POLYGON, x+offset, yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
+ }
+ else {
+ /* for normal channels
+ * - use 3 shades of color group/standard color for 3 indention level
+ * - only use group colors if allowed to, and if actually feasible
+ */
+ if ( !(saction->flag & SACTION_NODRAWGCOLORS) &&
+ (grp) && (grp->customCol) )
+ {
+ char cp[3];
+
+ if (indent == 2) {
+ VECCOPY(cp, grp->cs.solid);
+ }
+ else if (indent == 1) {
+ VECCOPY(cp, grp->cs.select);
+ }
+ else {
+ VECCOPY(cp, grp->cs.active);
+ }
+
+ glColor3ub(cp[0], cp[1], cp[2]);
+ }
+ else
+ UI_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40));
+
+ indent += group;
+ offset += 7 * indent;
+ glBegin(GL_QUADS);
+ glVertex2f(x+offset, yminc);
+ glVertex2f(x+offset, ymaxc);
+ glVertex2f((float)ACHANNEL_NAMEWIDTH, ymaxc);
+ glVertex2f((float)ACHANNEL_NAMEWIDTH, yminc);
+ glEnd();
+ }
+
+ /* draw expand/collapse triangle */
+ if (expand > 0) {
+ UI_icon_draw(x+offset, yminc, expand);
+ offset += 17;
+ }
+
+ /* draw special icon indicating certain data-types */
+ if (special > -1) {
+ if (ELEM(group, 3, 4)) {
+ /* for gpdatablock channels */
+ UI_icon_draw(x+offset, yminc, special);
+ offset += 17;
+ }
+ else {
+ /* for normal channels */
+ UI_icon_draw(x+offset, yminc, special);
+ offset += 17;
+ }
+ }
+ glDisable(GL_BLEND);
+
+ /* draw name */
+ if (sel)
+ UI_ThemeColor(TH_TEXT_HI);
+ else
+ UI_ThemeColor(TH_TEXT);
+ offset += 3;
+ UI_DrawString(x+offset, y-4, name);
+
+ /* reset offset - for RHS of panel */
+ offset = 0;
+
+ /* set blending again, as text drawing may clear it */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ /* draw protect 'lock' */
+ if (protect > -1) {
+ offset = 16;
+ UI_icon_draw((float)ACHANNEL_NAMEWIDTH-offset, yminc, protect);
+ }
+
+ /* draw mute 'eye' */
+ if (mute > -1) {
+ offset += 16;
+ UI_icon_draw((float)(ACHANNEL_NAMEWIDTH-offset), yminc, mute);
+ }
+ glDisable(GL_BLEND);
+ }
+
+ /* adjust y-position for next one */
+ y -= ACHANNEL_STEP;
+ }
+
+ /* free tempolary channels */
+ BLI_freelistN(&anim_data);
+}
+
+/* ************************************************************************* */
+/* Keyframes */
+
+ActKeysInc *init_aki_data(bAnimContext *ac, bAnimListElem *ale)
+{
+ static ActKeysInc aki;
+
+ /* no need to set settings if wrong context */
+ if ((ac->data == NULL) || ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)==0)
+ return NULL;
+
+ /* if strip is mapped, store settings */
+ aki.ob= ANIM_nla_mapping_get(ac, ale);
+
+ if (ac->datatype == ANIMCONT_DOPESHEET)
+ aki.ads= (bDopeSheet *)ac->data;
+ else
+ aki.ads= NULL;
+ aki.actmode= ac->datatype;
+
+ /* always return pointer... */
+ return &aki;
+}
+
+
+/* draw keyframes in each channel */
+void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ View2D *v2d= &ar->v2d;
+ Object *nob= NULL;
+ gla2DDrawInfo *di;
+ rcti scr_rct;
+
+ int act_start, act_end, dummy;
+ int height, items;
+ float y, sta, end;
+
+ char col1[3], col2[3];
+ char col1a[3], col2a[3];
+ char col1b[3], col2b[3];
+
+
+ /* get theme colors */
+ UI_GetThemeColor3ubv(TH_SHADE2, col2);
+ UI_GetThemeColor3ubv(TH_HILITE, col1);
+ UI_GetThemeColor3ubv(TH_GROUP, col2a);
+ UI_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a);
+
+ UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELOB, col1b);
+ UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
+
+ /* set view-mapping rect (only used for x-axis), for NLA-scaling mapping with less calculation */
+ scr_rct.xmin= ar->winrct.xmin + ar->v2d.mask.xmin;
+ scr_rct.ymin= ar->winrct.ymin + ar->v2d.mask.ymin;
+ scr_rct.xmax= ar->winrct.xmin + ar->v2d.hor.xmax;
+ scr_rct.ymax= ar->winrct.ymin + ar->v2d.mask.ymax;
+ di= glaBegin2DDraw(&scr_rct, &v2d->cur);
+
+ /* if in NLA there's a strip active, map the view */
+ if (ac->datatype == ANIMCONT_ACTION) {
+ nob= ANIM_nla_mapping_get(ac, NULL);
+
+ if (nob)
+ ANIM_nla_mapping_draw(di, nob, 0);
+
+ /* start and end of action itself */
+ calc_action_range(ac->data, &sta, &end, 0);
+ gla2DDrawTranslatePt(di, sta, 0.0f, &act_start, &dummy);
+ gla2DDrawTranslatePt(di, end, 0.0f, &act_end, &dummy);
+
+ if (nob)
+ ANIM_nla_mapping_draw(di, nob, 1);
+ }
+
+ /* build list of channels to draw */
+ filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
+ items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* Update max-extent of channels here (taking into account scrollers):
+ * - this is done to allow the channel list to be scrollable, but must be done here
+ * to avoid regenerating the list again and/or also because channels list is drawn first
+ * - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
+ * start of list offset, and the second is as a correction for the scrollers.
+ */
+ height= ((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2));
+ /* don't use totrect set, as the width stays the same
+ * (NOTE: this is ok here, the configuration is pretty straightforward)
+ */
+ v2d->tot.ymin= (float)(-height);
+
+ /* first backdrop strips */
+ y= (float)(-ACHANNEL_HEIGHT);
+ glEnable(GL_BLEND);
+
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
+ const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
+
+ /* check if visible */
+ if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
+ {
+ int frame1_x, channel_y, sel=0;
+
+ /* determine if any need to draw channel */
+ if (ale->datatype != ALE_NONE) {
+ /* determine if channel is selected */
+ switch (ale->type) {
+ case ANIMTYPE_SCENE:
+ {
+ Scene *sce= (Scene *)ale->data;
+ sel = SEL_SCEC(sce);
+ }
+ break;
+ case ANIMTYPE_OBJECT:
+ {
+ Base *base= (Base *)ale->data;
+ sel = SEL_OBJC(base);
+ }
+ break;
+ case ANIMTYPE_GROUP:
+ {
+ bActionGroup *agrp = (bActionGroup *)ale->data;
+ sel = SEL_AGRP(agrp);
+ }
+ break;
+ case ANIMTYPE_FCURVE:
+ {
+ FCurve *fcu = (FCurve *)ale->data;
+ sel = SEL_FCU(fcu);
+ }
+ break;
+ case ANIMTYPE_GPLAYER:
+ {
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+ sel = SEL_GPL(gpl);
+ }
+ break;
+ }
+
+ if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) {
+ gla2DDrawTranslatePt(di, v2d->cur.xmin, y, &frame1_x, &channel_y);
+
+ switch (ale->type) {
+ case ANIMTYPE_SCENE:
+ case ANIMTYPE_OBJECT:
+ {
+ if (sel) glColor4ub(col1b[0], col1b[1], col1b[2], 0x45);
+ else glColor4ub(col1b[0], col1b[1], col1b[2], 0x22);
+ }
+ break;
+
+ case ANIMTYPE_FILLACTD:
+ case ANIMTYPE_FILLMATD:
+ case ANIMTYPE_DSSKEY:
+ case ANIMTYPE_DSWOR:
+ {
+ if (sel) glColor4ub(col2b[0], col2b[1], col2b[2], 0x45);
+ else glColor4ub(col2b[0], col2b[1], col2b[2], 0x22);
+ }
+ break;
+
+ case ANIMTYPE_GROUP:
+ {
+ if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22);
+ else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22);
+ }
+ break;
+
+ default:
+ {
+ if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
+ else glColor4ub(col2[0], col2[1], col2[2], 0x22);
+ }
+ break;
+ }
+
+ /* draw region twice: firstly backdrop, then the current range */
+ glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax, (float)channel_y+ACHANNEL_HEIGHT_HALF);
+
+ if (ac->datatype == ANIMCONT_ACTION)
+ glRectf((float)act_start, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)act_end, (float)channel_y+ACHANNEL_HEIGHT_HALF);
+ }
+ else if (ac->datatype == ANIMCONT_SHAPEKEY) {
+ gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
+
+ /* all frames that have a frame number less than one
+ * get a desaturated orange background
+ */
+ glColor4ub(col2[0], col2[1], col2[2], 0x22);
+ glRectf(0.0f, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)frame1_x, (float)channel_y+ACHANNEL_HEIGHT_HALF);
+
+ /* frames one and higher get a saturated orange background */
+ glColor4ub(col2[0], col2[1], col2[2], 0x44);
+ glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax, (float)channel_y+ACHANNEL_HEIGHT_HALF);
+ }
+ else if (ac->datatype == ANIMCONT_GPENCIL) {
+ gla2DDrawTranslatePt(di, v2d->cur.xmin, y, &frame1_x, &channel_y);
+
+ /* frames less than one get less saturated background */
+ if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
+ else glColor4ub(col2[0], col2[1], col2[2], 0x22);
+ glRectf(0.0f, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)frame1_x, (float)channel_y+ACHANNEL_HEIGHT_HALF);
+
+ /* frames one and higher get a saturated background */
+ if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
+ else glColor4ub(col2[0], col2[1], col2[2], 0x44);
+ glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax, (float)channel_y+ACHANNEL_HEIGHT_HALF);
+ }
+ }
+ }
+
+ /* Increment the step */
+ y -= ACHANNEL_STEP;
+ }
+ glDisable(GL_BLEND);
+
+ /* Draw keyframes
+ * 1) Only channels that are visible in the Action Editor get drawn/evaluated.
+ * This is to try to optimise this for heavier data sets
+ * 2) Keyframes which are out of view horizontally are disregarded
+ */
+ y= (float)(-ACHANNEL_HEIGHT);
+
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
+ const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
+
+ /* check if visible */
+ if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
+ {
+ /* check if anything to show for this channel */
+ if (ale->datatype != ALE_NONE) {
+ ActKeysInc *aki= init_aki_data(ac, ale);
+ nob= ANIM_nla_mapping_get(ac, ale);
+
+ if (nob)
+ ANIM_nla_mapping_draw(di, nob, 0);
+
+ /* draw 'keyframes' for each specific datatype */
+ switch (ale->datatype) {
+ case ALE_SCE:
+ draw_scene_channel(di, aki, ale->key_data, y);
+ break;
+ case ALE_OB:
+ draw_object_channel(di, aki, ale->key_data, y);
+ break;
+ case ALE_ACT:
+ draw_action_channel(di, aki, ale->key_data, y);
+ break;
+ case ALE_GROUP:
+ draw_agroup_channel(di, aki, ale->data, y);
+ break;
+ case ALE_FCURVE:
+ draw_fcurve_channel(di, aki, ale->key_data, y);
+ break;
+ case ALE_GPFRAME:
+ draw_gpl_channel(di, aki, ale->data, y);
+ break;
+ }
+
+ if (nob)
+ ANIM_nla_mapping_draw(di, nob, 1);
+ }
+ }
+
+ y-= ACHANNEL_STEP;
+ }
+
+ /* free tempolary channels used for drawing */
+ BLI_freelistN(&anim_data);
+
+ /* black line marking 'current frame' for Time-Slide transform mode */
+ if (saction->flag & SACTION_MOVING) {
+ int frame1_x;
+
+ gla2DDrawTranslatePt(di, saction->timeslide, 0, &frame1_x, &dummy);
+ cpack(0x0);
+
+ glBegin(GL_LINES);
+ glVertex2f((float)frame1_x, (float)v2d->mask.ymin - 100);
+ glVertex2f((float)frame1_x, (float)v2d->mask.ymax);
+ glEnd();
+ }
+
+ glaEnd2DDraw(di);
+}
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
new file mode 100644
index 00000000000..9e679a5b722
--- /dev/null
+++ b/source/blender/editors/space_action/action_edit.c
@@ -0,0 +1,1315 @@
+/**
+ * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_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 "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "BKE_action.h"
+#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+#include "BKE_context.h"
+#include "BKE_report.h"
+#include "BKE_utildefines.h"
+
+#include "UI_view2d.h"
+
+#include "BIF_transform.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_draw.h"
+#include "ED_keyframes_edit.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "action_intern.h"
+
+/* ************************************************************************** */
+/* KEYFRAME-RANGE STUFF */
+
+/* *************************** Calculate Range ************************** */
+
+/* Get the min/max keyframes*/
+static void get_keyframe_extents (bAnimContext *ac, float *min, float *max)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get data to filter, from Action or Dopesheet */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* set large values to try to override */
+ *min= 999999999.0f;
+ *max= -999999999.0f;
+
+ /* check if any channels to set range with */
+ if (anim_data.first) {
+ /* go through channels, finding max extents */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+ FCurve *fcu= (FCurve *)ale->key_data;
+ float tmin, tmax;
+
+ /* get range and apply necessary scaling before */
+ calc_fcurve_range(fcu, &tmin, &tmax);
+
+ if (nob) {
+ tmin= get_action_frame_inv(nob, tmin);
+ tmax= get_action_frame_inv(nob, tmax);
+ }
+
+ /* try to set cur using these values, if they're more extreme than previously set values */
+ *min= MIN2(*min, tmin);
+ *max= MAX2(*max, tmax);
+ }
+
+ /* free memory */
+ BLI_freelistN(&anim_data);
+ }
+ else {
+ /* set default range */
+ if (ac->scene) {
+ *min= (float)ac->scene->r.sfra;
+ *max= (float)ac->scene->r.efra;
+ }
+ else {
+ *min= -5;
+ *max= 100;
+ }
+ }
+}
+
+/* ****************** Automatic Preview-Range Operator ****************** */
+
+static int actkeys_previewrange_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ Scene *scene;
+ float min, max;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ if (ac.scene == NULL)
+ return OPERATOR_CANCELLED;
+ else
+ scene= ac.scene;
+
+ /* set the range directly */
+ get_keyframe_extents(&ac, &min, &max);
+ scene->r.psfra= (int)floor(min + 0.5f);
+ scene->r.pefra= (int)floor(max + 0.5f);
+
+ /* set notifier that things have changed */
+ // XXX err... there's nothing for frame ranges yet, but this should do fine too
+ WM_event_add_notifier(C, NC_SCENE|ND_FRAME, ac.scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_previewrange_set (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Auto-Set Preview Range";
+ ot->idname= "ACT_OT_previewrange_set";
+
+ /* api callbacks */
+ ot->exec= actkeys_previewrange_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ****************** View-All Operator ****************** */
+
+static int actkeys_viewall_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ View2D *v2d;
+ float extra;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ v2d= &ac.ar->v2d;
+
+ /* set the horizontal range, with an extra offset so that the extreme keys will be in view */
+ get_keyframe_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax);
+
+ extra= 0.1f * (v2d->cur.xmax - v2d->cur.xmin);
+ v2d->cur.xmin -= extra;
+ v2d->cur.xmax += extra;
+
+ /* set vertical range */
+ v2d->cur.ymax= 0.0f;
+ v2d->cur.ymin= (float)-(v2d->mask.ymax - v2d->mask.ymin);
+
+ /* do View2D syncing */
+ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
+
+ /* set notifier that things have changed */
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_view_all (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View All";
+ ot->idname= "ACT_OT_view_all";
+
+ /* api callbacks */
+ ot->exec= actkeys_viewall_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ************************************************************************** */
+/* GENERAL STUFF */
+
+/* ******************** Copy/Paste Keyframes Operator ************************* */
+/* NOTE: the backend code for this is shared with the graph editor */
+
+static short copy_action_keys (bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ int filter, ok=0;
+
+ /* clear buffer first */
+ free_anim_copybuf();
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* copy keyframes */
+ ok= copy_animedit_keys(ac, &anim_data);
+
+ /* clean up */
+ BLI_freelistN(&anim_data);
+
+ return ok;
+}
+
+
+static short paste_action_keys (bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ int filter, ok=0;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* paste keyframes */
+ ok= paste_animedit_keys(ac, &anim_data);
+
+ /* clean up */
+ BLI_freelistN(&anim_data);
+
+ return ok;
+}
+
+/* ------------------- */
+
+static int actkeys_copy_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* copy keyframes */
+ if (ac.datatype == ANIMCONT_GPENCIL) {
+ // FIXME...
+ }
+ else {
+ if (copy_action_keys(&ac)) {
+ BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_copy (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Copy Keyframes";
+ ot->idname= "ACT_OT_keyframes_copy";
+
+ /* api callbacks */
+ ot->exec= actkeys_copy_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+
+static int actkeys_paste_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* paste keyframes */
+ if (ac.datatype == ANIMCONT_GPENCIL) {
+ // FIXME...
+ }
+ else {
+ if (paste_action_keys(&ac)) {
+ BKE_report(op->reports, RPT_ERROR, "No keyframes to paste");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_paste (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Paste Keyframes";
+ ot->idname= "ACT_OT_keyframes_paste";
+
+ /* api callbacks */
+ ot->exec= actkeys_paste_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ******************** Insert Keyframes Operator ************************* */
+
+/* defines for insert keyframes tool */
+EnumPropertyItem prop_actkeys_insertkey_types[] = {
+ {1, "ALL", "All Channels", ""},
+ {2, "SEL", "Only Selected Channels", ""},
+ {3, "GROUP", "In Active Group", ""}, // xxx not in all cases
+ {0, NULL, NULL, NULL}
+};
+
+/* this function is responsible for snapping keyframes to frame-times */
+static void insert_action_keys(bAnimContext *ac, short mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ Scene *scene= ac->scene;
+ float cfra= (float)CFRA;
+ short flag = 0;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ if (mode == 2) filter |= ANIMFILTER_SEL;
+ else if (mode == 3) filter |= ANIMFILTER_ACTGROUPED;
+
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* init keyframing flag */
+ if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX;
+ if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED;
+ // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
+
+ /* insert keyframes */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ //Object *nob= ANIM_nla_mapping_get(ac, ale);
+ FCurve *fcu= (FCurve *)ale->key_data;
+
+ /* adjust current frame for NLA-scaling */
+ //if (nob)
+ // cfra= get_action_frame(nob, CFRA);
+ //else
+ // cfra= (float)CFRA;
+
+ /* if there's an id */
+ if (ale->id)
+ insert_keyframe(ale->id, NULL, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
+ else
+ insert_vert_fcurve(fcu, cfra, fcu->curval, 0);
+ }
+
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_insertkey_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ if (ac.datatype == ANIMCONT_GPENCIL)
+ return OPERATOR_CANCELLED;
+
+ /* get snapping mode */
+ mode= RNA_enum_get(op->ptr, "type");
+
+ /* snap keyframes */
+ insert_action_keys(&ac, mode);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_insert (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Insert Keyframes";
+ ot->idname= "ACT_OT_keyframes_insert";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= actkeys_insertkey_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ RNA_def_enum(ot->srna, "type", prop_actkeys_insertkey_types, 0, "Type", "");
+}
+
+/* ******************** Duplicate Keyframes Operator ************************* */
+
+static void duplicate_action_keys (bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ if (ac->datatype == ANIMCONT_GPENCIL)
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT);
+ else
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through filtered data and delete selected keys */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ //if (ale->type == ANIMTYPE_GPLAYER)
+ // delete_gplayer_frames((bGPDlayer *)ale->data);
+ //else
+ duplicate_fcurve_keys((FCurve *)ale->key_data);
+ }
+
+ /* free filtered list */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_duplicate_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* duplicate keyframes */
+ duplicate_action_keys(&ac);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED; // xxx - start transform
+}
+
+static int actkeys_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ actkeys_duplicate_exec(C, op);
+
+ RNA_int_set(op->ptr, "mode", TFM_TIME_TRANSLATE);
+ WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_duplicate (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Duplicate Keyframes";
+ ot->idname= "ACT_OT_keyframes_duplicate";
+
+ /* api callbacks */
+ ot->invoke= actkeys_duplicate_invoke;
+ ot->exec= actkeys_duplicate_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* to give to transform */
+ RNA_def_int(ot->srna, "mode", TFM_TIME_TRANSLATE, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+}
+
+/* ******************** Delete Keyframes Operator ************************* */
+
+static void delete_action_keys (bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ if (ac->datatype == ANIMCONT_GPENCIL)
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT);
+ else
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through filtered data and delete selected keys */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ //if (ale->type == ANIMTYPE_GPLAYER)
+ // delete_gplayer_frames((bGPDlayer *)ale->data);
+ //else
+ delete_fcurve_keys((FCurve *)ale->key_data); // XXX... this doesn't delete empty curves anymore
+ }
+
+ /* free filtered list */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_delete_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* delete keyframes */
+ delete_action_keys(&ac);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_delete (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete Keyframes";
+ ot->idname= "ACT_OT_keyframes_delete";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= actkeys_delete_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ******************** Clean Keyframes Operator ************************* */
+
+static void clean_action_keys (bAnimContext *ac, float thresh)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through filtered data and clean curves */
+ for (ale= anim_data.first; ale; ale= ale->next)
+ clean_fcurve((FCurve *)ale->key_data, thresh);
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_clean_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ float thresh;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ if (ac.datatype == ANIMCONT_GPENCIL)
+ return OPERATOR_PASS_THROUGH;
+
+ /* get cleaning threshold */
+ thresh= RNA_float_get(op->ptr, "threshold");
+
+ /* clean keyframes */
+ clean_action_keys(&ac, thresh);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_clean (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Clean Keyframes";
+ ot->idname= "ACT_OT_keyframes_clean";
+
+ /* api callbacks */
+ //ot->invoke= // XXX we need that number popup for this!
+ ot->exec= actkeys_clean_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float(ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f);
+}
+
+/* ******************** Sample Keyframes Operator *********************** */
+
+/* little cache for values... */
+typedef struct tempFrameValCache {
+ float frame, val;
+} tempFrameValCache;
+
+/* Evaluates the curves between each selected keyframe on each frame, and keys the value */
+static void sample_action_keys (bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through filtered data and add keys between selected keyframes on every frame */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ FCurve *fcu= (FCurve *)ale->key_data;
+ BezTriple *bezt, *start=NULL, *end=NULL;
+ tempFrameValCache *value_cache, *fp;
+ int sfra, range;
+ int i, n;
+
+ /* find selected keyframes... once pair has been found, add keyframes */
+ for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ /* check if selected, and which end this is */
+ if (BEZSELECTED(bezt)) {
+ if (start) {
+ /* set end */
+ end= bezt;
+
+ /* cache values then add keyframes using these values, as adding
+ * keyframes while sampling will affect the outcome...
+ */
+ range= (int)( ceil(end->vec[1][0] - start->vec[1][0]) );
+ sfra= (int)( floor(start->vec[1][0]) );
+
+ if (range) {
+ value_cache= MEM_callocN(sizeof(tempFrameValCache)*range, "IcuFrameValCache");
+
+ /* sample values */
+ for (n=0, fp=value_cache; n<range && fp; n++, fp++) {
+ fp->frame= (float)(sfra + n);
+ fp->val= evaluate_fcurve(fcu, fp->frame);
+ }
+
+ /* add keyframes with these */
+ for (n=0, fp=value_cache; n<range && fp; n++, fp++) {
+ insert_vert_fcurve(fcu, fp->frame, fp->val, 1);
+ }
+
+ /* free temp cache */
+ MEM_freeN(value_cache);
+
+ /* as we added keyframes, we need to compensate so that bezt is at the right place */
+ bezt = fcu->bezt + i + range - 1;
+ i += (range - 1);
+ }
+
+ /* bezt was selected, so it now marks the start of a whole new chain to search */
+ start= bezt;
+ end= NULL;
+ }
+ else {
+ /* just set start keyframe */
+ start= bezt;
+ end= NULL;
+ }
+ }
+ }
+
+ /* recalculate channel's handles? */
+ calchandles_fcurve(fcu);
+ }
+
+ /* admin and redraws */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_sample_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ if (ac.datatype == ANIMCONT_GPENCIL)
+ return OPERATOR_PASS_THROUGH;
+
+ /* sample keyframes */
+ sample_action_keys(&ac);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_sample (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Sample Keyframes";
+ ot->idname= "ACT_OT_keyframes_sample";
+
+ /* api callbacks */
+ ot->exec= actkeys_sample_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ************************************************************************** */
+/* SETTINGS STUFF */
+
+/* ******************** Set Extrapolation-Type Operator *********************** */
+
+/* defines for set extrapolation-type for selected keyframes tool */
+EnumPropertyItem prop_actkeys_expo_types[] = {
+ {FCURVE_EXTRAPOLATE_CONSTANT, "CONSTANT", "Constant Extrapolation", ""},
+ {FCURVE_EXTRAPOLATE_LINEAR, "LINEAR", "Linear Extrapolation", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* this function is responsible for setting extrapolation mode for keyframes */
+static void setexpo_action_keys(bAnimContext *ac, short mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through setting mode per F-Curve */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ FCurve *fcu= (FCurve *)ale->data;
+ fcu->extend= mode;
+ }
+
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_expo_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ if (ac.datatype == ANIMCONT_GPENCIL)
+ return OPERATOR_PASS_THROUGH;
+
+ /* get handle setting mode */
+ mode= RNA_enum_get(op->ptr, "type");
+
+ /* set handle type */
+ setexpo_action_keys(&ac, mode);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_extrapolation_type_set (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Keyframe Extrapolation";
+ ot->idname= "ACT_OT_keyframes_extrapolation_type_set";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= actkeys_expo_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ RNA_def_enum(ot->srna, "type", prop_actkeys_expo_types, 0, "Type", "");
+}
+
+/* ******************** Set Interpolation-Type Operator *********************** */
+
+/* defines for set ipo-type for selected keyframes tool */
+EnumPropertyItem prop_actkeys_ipo_types[] = {
+ {BEZT_IPO_CONST, "CONSTANT", "Constant Interpolation", ""},
+ {BEZT_IPO_LIN, "LINEAR", "Linear Interpolation", ""},
+ {BEZT_IPO_BEZ, "BEZIER", "Bezier Interpolation", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* this function is responsible for setting interpolation mode for keyframes */
+static void setipo_action_keys(bAnimContext *ac, short mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ BeztEditFunc set_cb= ANIM_editkeyframes_ipo(mode);
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through setting BezTriple interpolation
+ * Note: we do not supply BeztEditData to the looper yet. Currently that's not necessary here...
+ */
+ for (ale= anim_data.first; ale; ale= ale->next)
+ ANIM_fcurve_keys_bezier_loop(NULL, ale->key_data, NULL, set_cb, calchandles_fcurve);
+
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_ipo_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ if (ac.datatype == ANIMCONT_GPENCIL)
+ return OPERATOR_PASS_THROUGH;
+
+ /* get handle setting mode */
+ mode= RNA_enum_get(op->ptr, "type");
+
+ /* set handle type */
+ setipo_action_keys(&ac, mode);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_interpolation_type (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Keyframe Interpolation";
+ ot->idname= "ACT_OT_keyframes_interpolation_type";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= actkeys_ipo_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ RNA_def_enum(ot->srna, "type", prop_actkeys_ipo_types, 0, "Type", "");
+}
+
+/* ******************** Set Handle-Type Operator *********************** */
+
+/* defines for set handle-type for selected keyframes tool */
+EnumPropertyItem prop_actkeys_handletype_types[] = {
+ {HD_AUTO, "AUTO", "Auto Handles", ""},
+ {HD_VECT, "VECTOR", "Vector Handles", ""},
+ {HD_FREE, "FREE", "Free Handles", ""},
+ {HD_ALIGN, "ALIGN", "Aligned Handles", ""},
+// {-1, "TOGGLE", "Toggle between Free and Aligned Handles", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* this function is responsible for setting handle-type of selected keyframes */
+static void sethandles_action_keys(bAnimContext *ac, short mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ BeztEditFunc set_cb= ANIM_editkeyframes_handles(mode);
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through setting flags for handles
+ * Note: we do not supply BeztEditData to the looper yet. Currently that's not necessary here...
+ */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ if (mode == -1) {
+ BeztEditFunc toggle_cb;
+
+ /* check which type of handle to set (free or aligned)
+ * - check here checks for handles with free alignment already
+ */
+ if (ANIM_fcurve_keys_bezier_loop(NULL, ale->key_data, NULL, set_cb, NULL))
+ toggle_cb= ANIM_editkeyframes_handles(HD_FREE);
+ else
+ toggle_cb= ANIM_editkeyframes_handles(HD_ALIGN);
+
+ /* set handle-type */
+ ANIM_fcurve_keys_bezier_loop(NULL, ale->key_data, NULL, toggle_cb, calchandles_fcurve);
+ }
+ else {
+ /* directly set handle-type */
+ ANIM_fcurve_keys_bezier_loop(NULL, ale->key_data, NULL, set_cb, calchandles_fcurve);
+ }
+ }
+
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_handletype_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ if (ac.datatype == ANIMCONT_GPENCIL)
+ return OPERATOR_PASS_THROUGH;
+
+ /* get handle setting mode */
+ mode= RNA_enum_get(op->ptr, "type");
+
+ /* set handle type */
+ sethandles_action_keys(&ac, mode);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_handle_type_set (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Keyframe Handle Type";
+ ot->idname= "ACT_OT_keyframes_handle_type_set";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= actkeys_handletype_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ RNA_def_enum(ot->srna, "type", prop_actkeys_handletype_types, 0, "Type", "");
+}
+
+/* ************************************************************************** */
+/* TRANSFORM STUFF */
+
+/* ***************** Snap Current Frame Operator *********************** */
+
+/* snap current-frame indicator to 'average time' of selected keyframe */
+static int actkeys_cfrasnap_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ ListBase anim_data= {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ BeztEditData bed;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* init edit data */
+ memset(&bed, 0, sizeof(BeztEditData));
+
+ /* loop over action data, averaging values */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale= anim_data.first; ale; ale= ale->next)
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL);
+
+ BLI_freelistN(&anim_data);
+
+ /* set the new current frame value, based on the average time */
+ if (bed.i1) {
+ Scene *scene= ac.scene;
+ CFRA= (int)floor((bed.f1 / bed.i1) + 0.5f);
+ }
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_SCENE|ND_FRAME, ac.scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_cfrasnap (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Snap Current Frame to Keys";
+ ot->idname= "ACT_OT_keyframes_cfrasnap";
+
+ /* api callbacks */
+ ot->exec= actkeys_cfrasnap_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ******************** Snap Keyframes Operator *********************** */
+
+/* defines for snap keyframes tool */
+EnumPropertyItem prop_actkeys_snap_types[] = {
+ {ACTKEYS_SNAP_CFRA, "CFRA", "Current frame", ""},
+ {ACTKEYS_SNAP_NEAREST_FRAME, "NEAREST_FRAME", "Nearest Frame", ""}, // XXX as single entry?
+ {ACTKEYS_SNAP_NEAREST_SECOND, "NEAREST_SECOND", "Nearest Second", ""}, // XXX as single entry?
+ {ACTKEYS_SNAP_NEAREST_MARKER, "NEAREST_MARKER", "Nearest Marker", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* this function is responsible for snapping keyframes to frame-times */
+static void snap_action_keys(bAnimContext *ac, short mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BeztEditData bed;
+ BeztEditFunc edit_cb;
+
+ /* filter data */
+ if (ac->datatype == ANIMCONT_GPENCIL)
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT);
+ else
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get beztriple editing callbacks */
+ edit_cb= ANIM_editkeyframes_snap(mode);
+
+ memset(&bed, 0, sizeof(BeztEditData));
+ bed.scene= ac->scene;
+
+ /* snap keyframes */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ if (nob) {
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
+ }
+ //else if (ale->type == ACTTYPE_GPLAYER)
+ // snap_gplayer_frames(ale->data, mode);
+ else
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+ }
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_snap_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get snapping mode */
+ mode= RNA_enum_get(op->ptr, "type");
+
+ /* snap keyframes */
+ snap_action_keys(&ac, mode);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_snap (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Snap Keys";
+ ot->idname= "ACT_OT_keyframes_snap";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= actkeys_snap_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ RNA_def_enum(ot->srna, "type", prop_actkeys_snap_types, 0, "Type", "");
+}
+
+/* ******************** Mirror Keyframes Operator *********************** */
+
+/* defines for mirror keyframes tool */
+EnumPropertyItem prop_actkeys_mirror_types[] = {
+ {ACTKEYS_MIRROR_CFRA, "CFRA", "Current frame", ""},
+ {ACTKEYS_MIRROR_YAXIS, "YAXIS", "Vertical Axis", ""},
+ {ACTKEYS_MIRROR_XAXIS, "XAXIS", "Horizontal Axis", ""},
+ {ACTKEYS_MIRROR_MARKER, "MARKER", "First Selected Marker", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* this function is responsible for mirroring keyframes */
+static void mirror_action_keys(bAnimContext *ac, short mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BeztEditData bed;
+ BeztEditFunc edit_cb;
+
+ /* get beztriple editing callbacks */
+ edit_cb= ANIM_editkeyframes_mirror(mode);
+
+ memset(&bed, 0, sizeof(BeztEditData));
+ bed.scene= ac->scene;
+
+ /* for 'first selected marker' mode, need to find first selected marker first! */
+ // XXX should this be made into a helper func in the API?
+ if (mode == ACTKEYS_MIRROR_MARKER) {
+ Scene *scene= ac->scene;
+ TimeMarker *marker= NULL;
+
+ /* find first selected marker */
+ for (marker= scene->markers.first; marker; marker=marker->next) {
+ if (marker->flag & SELECT) {
+ break;
+ }
+ }
+
+ /* store marker's time (if available) */
+ if (marker)
+ bed.f1= (float)marker->frame;
+ else
+ return;
+ }
+
+ /* filter data */
+ if (ac->datatype == ANIMCONT_GPENCIL)
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT);
+ else
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* mirror keyframes */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ if (nob) {
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
+ }
+ //else if (ale->type == ACTTYPE_GPLAYER)
+ // snap_gplayer_frames(ale->data, mode);
+ else
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+ }
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_mirror_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get mirroring mode */
+ mode= RNA_enum_get(op->ptr, "type");
+
+ /* mirror keyframes */
+ mirror_action_keys(&ac, mode);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_mirror (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mirror Keys";
+ ot->idname= "ACT_OT_keyframes_mirror";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= actkeys_mirror_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ RNA_def_enum(ot->srna, "type", prop_actkeys_mirror_types, 0, "Type", "");
+}
+
+/* ************************************************************************** */
diff --git a/source/blender/editors/space_action/action_header.c b/source/blender/editors/space_action/action_header.c
new file mode 100644
index 00000000000..fa96e1ea81f
--- /dev/null
+++ b/source/blender/editors/space_action/action_header.c
@@ -0,0 +1,1753 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_key_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_animsys.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_anim_api.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "action_intern.h"
+
+/* ********************************************************* */
+/* Menu Defines... */
+
+/* button events */
+enum {
+ B_REDR = 0,
+ B_ACTCOPYKEYS,
+ B_ACTPASTEKEYS,
+} eActHeader_ButEvents;
+
+/* ------------------------------- */
+/* enums declaring constants that are used as menu event codes */
+
+enum {
+ ACTMENU_VIEW_CENTERVIEW= 0,
+ ACTMENU_VIEW_AUTOUPDATE,
+ ACTMENU_VIEW_PLAY3D,
+ ACTMENU_VIEW_PLAYALL,
+ ACTMENU_VIEW_ALL,
+ ACTMENU_VIEW_MAXIMIZE,
+ ACTMENU_VIEW_LOCK,
+ ACTMENU_VIEW_SLIDERS,
+ ACTMENU_VIEW_NEXTMARKER,
+ ACTMENU_VIEW_PREVMARKER,
+ ACTMENU_VIEW_NEXTKEYFRAME,
+ ACTMENU_VIEW_PREVKEYFRAME,
+ ACTMENU_VIEW_TIME,
+ ACTMENU_VIEW_NOHIDE,
+ ACTMENU_VIEW_FRANUM,
+ ACTMENU_VIEW_TRANSDELDUPS,
+ ACTMENU_VIEW_HORIZOPTIMISE,
+ ACTMENU_VIEW_GCOLORS,
+ ACTMENU_VIEW_PREVRANGESET,
+ ACTMENU_VIEW_PREVRANGECLEAR,
+ ACTMENU_VIEW_PREVRANGEAUTO
+};
+
+enum {
+ ACTMENU_SEL_BORDER = 0,
+ ACTMENU_SEL_BORDERC,
+ ACTMENU_SEL_BORDERM,
+ ACTMENU_SEL_ALL_KEYS,
+ ACTMENU_SEL_ALL_CHAN,
+ ACTMENU_SEL_ALL_MARKERS,
+ ACTMENU_SEL_INVERSE_KEYS,
+ ACTMENU_SEL_INVERSE_MARKERS,
+ ACTMENU_SEL_INVERSE_CHANNELS,
+ ACTMENU_SEL_LEFTKEYS,
+ ACTMENU_SEL_RIGHTKEYS
+};
+
+enum {
+ ACTMENU_SEL_COLUMN_KEYS = 1,
+ ACTMENU_SEL_COLUMN_CFRA,
+ ACTMENU_SEL_COLUMN_MARKERSCOLUMN,
+ ACTMENU_SEL_COLUMN_MARKERSBETWEEN
+};
+
+enum {
+ ACTMENU_CHANNELS_OPENLEVELS = 0,
+ ACTMENU_CHANNELS_CLOSELEVELS,
+ ACTMENU_CHANNELS_EXPANDALL,
+ ACTMENU_CHANNELS_SHOWACHANS,
+ ACTMENU_CHANNELS_DELETE
+};
+
+enum {
+ ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_UP = 0,
+ ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_DOWN,
+ ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_TOP,
+ ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_BOTTOM
+};
+
+enum {
+ ACTMENU_CHANNELS_GROUP_ADD_TOACTIVE = 0,
+ ACTMENU_CHANNELS_GROUP_ADD_TONEW,
+ ACTMENU_CHANNELS_GROUP_REMOVE,
+ ACTMENU_CHANNELS_GROUP_SYNCPOSE
+};
+
+enum {
+ ACTMENU_CHANNELS_SETTINGS_TOGGLE = 0,
+ ACTMENU_CHANNELS_SETTINGS_ENABLE,
+ ACTMENU_CHANNELS_SETTINGS_DISABLE,
+};
+
+enum {
+ ACTMENU_KEY_DUPLICATE = 0,
+ ACTMENU_KEY_DELETE,
+ ACTMENU_KEY_CLEAN,
+ ACTMENU_KEY_SAMPLEKEYS,
+ ACTMENU_KEY_INSERTKEY
+};
+
+enum {
+ ACTMENU_KEY_TRANSFORM_MOVE = 0,
+ ACTMENU_KEY_TRANSFORM_SCALE,
+ ACTMENU_KEY_TRANSFORM_SLIDE,
+ ACTMENU_KEY_TRANSFORM_EXTEND
+};
+
+enum {
+ ACTMENU_KEY_HANDLE_AUTO = 0,
+ ACTMENU_KEY_HANDLE_ALIGN,
+ ACTMENU_KEY_HANDLE_FREE,
+ ACTMENU_KEY_HANDLE_VECTOR
+};
+
+enum {
+ ACTMENU_KEY_INTERP_CONST = 0,
+ ACTMENU_KEY_INTERP_LINEAR,
+ ACTMENU_KEY_INTERP_BEZIER
+};
+
+enum {
+ ACTMENU_KEY_EXTEND_CONST = 0,
+ ACTMENU_KEY_EXTEND_EXTRAPOLATION,
+ ACTMENU_KEY_EXTEND_CYCLIC,
+ ACTMENU_KEY_EXTEND_CYCLICEXTRAPOLATION
+};
+
+enum {
+ ACTMENU_KEY_SNAP_NEARFRAME = 1,
+ ACTMENU_KEY_SNAP_CURFRAME,
+ ACTMENU_KEY_SNAP_NEARMARK,
+ ACTMENU_KEY_SNAP_NEARTIME,
+ ACTMENU_KEY_SNAP_CFRA2KEY,
+};
+
+enum {
+ ACTMENU_KEY_MIRROR_CURFRAME = 1,
+ ACTMENU_KEY_MIRROR_YAXIS,
+ ACTMENU_KEY_MIRROR_XAXIS,
+ ACTMENU_KEY_MIRROR_MARKER
+};
+
+enum {
+ ACTMENU_MARKERS_ADD = 0,
+ ACTMENU_MARKERS_DUPLICATE,
+ ACTMENU_MARKERS_DELETE,
+ ACTMENU_MARKERS_NAME,
+ ACTMENU_MARKERS_MOVE,
+ ACTMENU_MARKERS_LOCALADD,
+ ACTMENU_MARKERS_LOCALRENAME,
+ ACTMENU_MARKERS_LOCALDELETE,
+ ACTMENU_MARKERS_LOCALMOVE
+};
+
+/* ------------------------------- */
+/* macros for easier state testing (only for use here) */
+
+/* test if active action editor is showing any markers */
+#if 0
+ #define SACTION_HASMARKERS \
+ ((saction->action && saction->action->markers.first) \
+ || (scene->markers.first))
+#endif
+
+/* need to find out how to get scene from context */
+#define SACTION_HASMARKERS (saction->action && saction->action->markers.first)
+
+/* ------------------------------- */
+
+/* *************************************************************** */
+/* menus */
+
+/* Key menu --------------------------- */
+
+static void do_keymenu_transformmenu(bContext *C, void *arg, int event)
+{
+ switch (event)
+ {
+ case ACTMENU_KEY_TRANSFORM_MOVE:
+ //transform_action_keys('g', 0);
+ break;
+ case ACTMENU_KEY_TRANSFORM_SCALE:
+ //transform_action_keys('s', 0);
+ break;
+ case ACTMENU_KEY_TRANSFORM_SLIDE:
+ //transform_action_keys('t', 0);
+ break;
+ case ACTMENU_KEY_TRANSFORM_EXTEND:
+ //transform_action_keys('e', 0);
+ break;
+ }
+}
+
+static uiBlock *action_keymenu_transformmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "action_keymenu_transformmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_keymenu_transformmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Grab/Move|G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_TRANSFORM_MOVE, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Grab/Extend from Frame|E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_TRANSFORM_EXTEND, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Scale|S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_TRANSFORM_SCALE, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Time Slide|T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_TRANSFORM_SLIDE, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static void do_keymenu_snapmenu(bContext *C, void *arg, int event)
+{
+ switch(event)
+ {
+ case ACTMENU_KEY_SNAP_NEARFRAME:
+ case ACTMENU_KEY_SNAP_CURFRAME:
+ case ACTMENU_KEY_SNAP_NEARMARK:
+ case ACTMENU_KEY_SNAP_NEARTIME:
+ //snap_action_keys(event);
+ break;
+
+ case ACTMENU_KEY_SNAP_CFRA2KEY:
+ //snap_cfra_action();
+ break;
+ }
+}
+
+static uiBlock *action_keymenu_snapmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+
+ block= uiBeginBlock(C, ar, "action_keymenu_snapmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_keymenu_snapmenu, NULL);
+
+ if (saction->flag & SACTION_DRAWTIME) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Key -> Nearest Second|Shift S, 1", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_SNAP_NEARTIME, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Key -> Current Time|Shift S, 2", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_SNAP_CURFRAME, "");
+
+ }
+ else {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Key -> Nearest Frame|Shift S, 1", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_SNAP_NEARFRAME, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Key -> Current Frame|Shift S, 2", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_SNAP_CURFRAME, "");
+ }
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Key -> Nearest Marker|Shift S, 3", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_SNAP_NEARMARK, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Current Frame -> Key|Ctrl Shift S", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_SNAP_NEARMARK, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static void do_keymenu_mirrormenu(bContext *C, void *arg, int event)
+{
+ switch(event)
+ {
+ case ACTMENU_KEY_MIRROR_CURFRAME:
+ case ACTMENU_KEY_MIRROR_YAXIS:
+ //mirror_action_keys(event);
+ break;
+ }
+
+}
+
+static uiBlock *action_keymenu_mirrormenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "action_keymenu_mirrormenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_keymenu_mirrormenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Current Frame|Shift M, 1", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_MIRROR_CURFRAME, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Vertical Axis|Shift M, 2", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_MIRROR_YAXIS, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Horizontal Axis|Shift M, 3", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_MIRROR_XAXIS, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Selected Marker|Shift M, 4", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_MIRROR_MARKER, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static void do_keymenu_handlemenu(bContext *C, void *arg, int event)
+{
+ switch (event) {
+ case ACTMENU_KEY_HANDLE_AUTO:
+ //sethandles_action_keys(HD_AUTO);
+ break;
+
+ case ACTMENU_KEY_HANDLE_ALIGN:
+ case ACTMENU_KEY_HANDLE_FREE:
+ /* OK, this is kinda dumb, need to fix the
+ * toggle crap in sethandles_ipo_keys()
+ */
+ //sethandles_action_keys(HD_ALIGN);
+ break;
+
+ case ACTMENU_KEY_HANDLE_VECTOR:
+ //sethandles_action_keys(HD_VECT);
+ break;
+ }
+}
+
+static uiBlock *action_keymenu_handlemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "action_keymenu_handlemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_keymenu_handlemenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Auto|Shift H", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_HANDLE_AUTO, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Aligned|H", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_HANDLE_ALIGN, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Free|H", 0, yco-=20, menuwidth,
+ 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_HANDLE_FREE, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Vector|V", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_HANDLE_VECTOR, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static void do_keymenu_extendmenu(bContext *C, void *arg, int event)
+{
+ switch(event)
+ {
+ case ACTMENU_KEY_EXTEND_CONST:
+ //action_set_ipo_flags(SET_EXTEND_MENU, SET_EXTEND_CONSTANT);
+ break;
+ case ACTMENU_KEY_EXTEND_EXTRAPOLATION:
+ //action_set_ipo_flags(SET_EXTEND_MENU, SET_EXTEND_EXTRAPOLATION);
+ break;
+ case ACTMENU_KEY_EXTEND_CYCLIC:
+ //action_set_ipo_flags(SET_EXTEND_MENU, SET_EXTEND_CYCLIC);
+ break;
+ case ACTMENU_KEY_EXTEND_CYCLICEXTRAPOLATION:
+ //action_set_ipo_flags(SET_EXTEND_MENU, SET_EXTEND_CYCLICEXTRAPOLATION);
+ break;
+ }
+}
+
+static uiBlock *action_keymenu_extendmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "action_keymenu_extendmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_keymenu_extendmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Constant", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_EXTEND_CONST, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Extrapolation", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_EXTEND_EXTRAPOLATION, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Cyclic", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_EXTEND_CYCLIC, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Cyclic Extrapolation", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_EXTEND_CYCLICEXTRAPOLATION, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static void do_keymenu_intpolmenu(bContext *C, void *arg, int event)
+{
+ switch(event)
+ {
+ case ACTMENU_KEY_INTERP_CONST:
+ //action_set_ipo_flags(SET_IPO_MENU, SET_IPO_CONSTANT);
+ break;
+ case ACTMENU_KEY_INTERP_LINEAR:
+ //action_set_ipo_flags(SET_IPO_MENU, SET_IPO_LINEAR);
+ break;
+ case ACTMENU_KEY_INTERP_BEZIER:
+ //action_set_ipo_flags(SET_IPO_MENU, SET_IPO_BEZIER);
+ break;
+ }
+}
+
+static uiBlock *action_keymenu_intpolmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "action_keymenu_intpolmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_keymenu_intpolmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Constant|Shift T, 1", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_INTERP_CONST, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Linear|Shift T, 2", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_INTERP_LINEAR, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Bezier|Shift T, 3", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_INTERP_BEZIER, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static void do_action_keymenu(bContext *C, void *arg, int event)
+{
+ SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
+ bAction *act;
+ //Key *key;
+
+ if (!saction) return;
+
+ act = saction->action;
+ //key = get_action_mesh_key();
+
+ switch(event)
+ {
+ case ACTMENU_KEY_DUPLICATE:
+ //duplicate_action_keys();
+ break;
+ case ACTMENU_KEY_DELETE:
+ //delete_action_keys();
+ break;
+ case ACTMENU_KEY_CLEAN:
+ //clean_action();
+ break;
+ case ACTMENU_KEY_SAMPLEKEYS:
+ //sample_action_keys();
+ break;
+ case ACTMENU_KEY_INSERTKEY:
+ //insertkey_action();
+ break;
+ }
+}
+
+static uiBlock *action_keymenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "action_keymenu", UI_EMBOSSP);
+
+
+ uiBlockSetButmFunc(block, do_action_keymenu, NULL);
+
+ uiDefIconTextBlockBut(block, action_keymenu_transformmenu,
+ NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 20, "");
+
+ uiDefIconTextBlockBut(block, action_keymenu_snapmenu,
+ NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 20, "");
+
+ uiDefIconTextBlockBut(block, action_keymenu_mirrormenu,
+ NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, 120, 20, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Insert Key|I", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_INSERTKEY, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Duplicate|Shift D", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_DUPLICATE, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Delete|X", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_DELETE, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Clean Action|O", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_CLEAN, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Sample Keys|Alt O", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_SAMPLEKEYS, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBlockBut(block, action_keymenu_handlemenu,
+ NULL, ICON_RIGHTARROW_THIN,
+ "Handle Type", 0, yco-=20, 120, 20, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBlockBut(block, action_keymenu_extendmenu,
+ NULL, ICON_RIGHTARROW_THIN,
+ "Extend Mode", 0, yco-=20, 120, 20, "");
+ uiDefIconTextBlockBut(block, action_keymenu_intpolmenu,
+ NULL, ICON_RIGHTARROW_THIN,
+ "Interpolation Mode", 0, yco-=20, 120, 20, "");
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+/* Frame menu --------------------------- */
+
+
+// framemenu uses functions from keymenu
+static uiBlock *action_framemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "action_framemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_action_keymenu, NULL);
+
+ uiDefIconTextBlockBut(block, action_keymenu_transformmenu,
+ NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 20, "");
+
+ uiDefIconTextBlockBut(block, action_keymenu_snapmenu,
+ NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 20, "");
+
+ uiDefIconTextBlockBut(block, action_keymenu_mirrormenu,
+ NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, 120, 20, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Duplicate|Shift D", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_DUPLICATE, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Delete|X", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_KEY_DELETE, "");
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+/* Marker menu --------------------------- */
+
+static void do_markermenu(bContext *C, void *arg, int event)
+{
+ switch(event)
+ {
+ case ACTMENU_MARKERS_ADD:
+ //add_marker(CFRA);
+ break;
+ case ACTMENU_MARKERS_DUPLICATE:
+ //duplicate_marker();
+ break;
+ case ACTMENU_MARKERS_DELETE:
+ //remove_marker();
+ break;
+ case ACTMENU_MARKERS_NAME:
+ //rename_marker();
+ break;
+ case ACTMENU_MARKERS_MOVE:
+ //transform_markers('g', 0);
+ break;
+ case ACTMENU_MARKERS_LOCALADD:
+ //action_add_localmarker(G.saction->action, CFRA);
+ break;
+ case ACTMENU_MARKERS_LOCALDELETE:
+ //action_remove_localmarkers(G.saction->action);
+ break;
+ case ACTMENU_MARKERS_LOCALRENAME:
+ //action_rename_localmarker(G.saction->action);
+ break;
+ case ACTMENU_MARKERS_LOCALMOVE:
+ /*G.saction->flag |= SACTION_POSEMARKERS_MOVE;
+ transform_markers('g', 0);
+ G.saction->flag &= ~SACTION_POSEMARKERS_MOVE;*/
+ break;
+ }
+}
+
+static uiBlock *action_markermenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
+ ScrArea *curarea= CTX_wm_area(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "action_markermenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_markermenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Marker|M", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_ADD, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate Marker|Ctrl Shift D", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_DUPLICATE, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Marker|Shift X", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_DELETE, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "(Re)Name Marker|Ctrl M", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_NAME, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move Marker|Ctrl G", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_MOVE, "");
+
+ if (saction->mode == SACTCONT_ACTION) {
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Pose Marker|Shift L", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_LOCALADD, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rename Pose Marker|Ctrl Shift L", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_LOCALRENAME, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Pose Marker|Alt L", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_LOCALDELETE, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move Pose Marker|Ctrl L", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_LOCALMOVE, "");
+ }
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+
+/* Channel menu --------------------------- */
+
+static void do_channelmenu_posmenu(bContext *C, void *arg, int event)
+{
+ switch(event)
+ {
+ case ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_DOWN:
+ //rearrange_action_channels(REARRANGE_ACTCHAN_DOWN);
+ break;
+ case ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_UP:
+ //rearrange_action_channels(REARRANGE_ACTCHAN_UP);
+ break;
+ case ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_TOP:
+ //rearrange_action_channels(REARRANGE_ACTCHAN_TOP);
+ break;
+ case ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_BOTTOM:
+ //rearrange_action_channels(REARRANGE_ACTCHAN_BOTTOM);
+ break;
+ }
+}
+
+static uiBlock *action_channelmenu_posmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "action_channelmenu_posmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_channelmenu_posmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Move Up|Shift Page Up", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_UP, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Move Down|Shift Page Down", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_DOWN, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Move to Top|Ctrl Shift Page Up", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_TOP, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Move to Bottom|Ctrl Shift Page Down", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_BOTTOM, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+
+ return block;
+}
+
+static void do_channelmenu_groupmenu(bContext *C, void *arg, int event)
+{
+ switch(event)
+ {
+ case ACTMENU_CHANNELS_GROUP_ADD_TOACTIVE:
+ //action_groups_group(0);
+ break;
+ case ACTMENU_CHANNELS_GROUP_ADD_TONEW:
+ //action_groups_group(1);
+ break;
+ case ACTMENU_CHANNELS_GROUP_REMOVE:
+ //action_groups_ungroup();
+ break;
+ case ACTMENU_CHANNELS_GROUP_SYNCPOSE: /* Syncronise Pose-data and Action-data */
+ //sync_pchan2achan_grouping();
+ break;
+ }
+}
+
+static uiBlock *action_channelmenu_groupmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "action_channelmenu_groupmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_channelmenu_groupmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Add to Active Group|Shift G", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_CHANNELS_GROUP_ADD_TOACTIVE, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Add to New Group|Ctrl Shift G", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_CHANNELS_GROUP_ADD_TONEW, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Remove From Group|Alt G", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_CHANNELS_GROUP_REMOVE, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Synchronise with Armature", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_CHANNELS_GROUP_SYNCPOSE, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+
+ return block;
+}
+
+static void do_channelmenu_settingsmenu(bContext *C, void *arg, int event)
+{
+ //setflag_action_channels(event);
+}
+
+static uiBlock *action_channelmenu_settingsmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "action_channelmenu_settingsmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_channelmenu_settingsmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Toggle a Setting|Shift W", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_CHANNELS_SETTINGS_TOGGLE, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Enable a Setting|Ctrl Shift W", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_CHANNELS_SETTINGS_ENABLE, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Disable a Setting|Alt W", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_CHANNELS_SETTINGS_DISABLE, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+
+ return block;
+}
+
+static void do_channelmenu(bContext *C, void *arg, int event)
+{
+ SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
+
+ if (saction == NULL) return;
+
+ switch(event)
+ {
+ case ACTMENU_CHANNELS_OPENLEVELS: /* Unfold selected channels one step */
+ //openclose_level_action(1);
+ break;
+ case ACTMENU_CHANNELS_CLOSELEVELS: /* Fold selected channels one step */
+ //openclose_level_action(-1);
+ break;
+ case ACTMENU_CHANNELS_EXPANDALL: /* Expands all channels */
+ //expand_all_action();
+ break;
+ case ACTMENU_CHANNELS_SHOWACHANS: /* Unfold groups that are hiding selected achans */
+ //expand_obscuregroups_action();
+ break;
+ case ACTMENU_CHANNELS_DELETE: /* Deletes selected channels */
+ //delete_action_channels();
+ break;
+ }
+}
+
+static uiBlock *action_channelmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "action_channelmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_channelmenu, NULL);
+
+ uiDefIconTextBlockBut(block, action_channelmenu_groupmenu,
+ NULL, ICON_RIGHTARROW_THIN,
+ "Grouping", 0, yco-=20, 120, 20, "");
+
+ uiDefIconTextBlockBut(block, action_channelmenu_posmenu,
+ NULL, ICON_RIGHTARROW_THIN,
+ "Ordering", 0, yco-=20, 120, 20, "");
+
+ uiDefIconTextBlockBut(block, action_channelmenu_settingsmenu,
+ NULL, ICON_RIGHTARROW_THIN,
+ "Settings", 0, yco-=20, 120, 20, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Delete|X", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_DELETE, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Toggle Show Hierachy|~", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_EXPANDALL, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Show Group-Hidden Channels|Shift ~", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_SHOWACHANS, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Expand One Level|Ctrl NumPad+", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_OPENLEVELS, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Collapse One Level|Ctrl NumPad-", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_CLOSELEVELS, "");
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+/* Grease Pencil --------------------------- */
+
+/* Uses channelmenu functions */
+static uiBlock *action_gplayermenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "action_gplayermenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_channelmenu, NULL);
+
+ uiDefIconTextBlockBut(block, action_channelmenu_settingsmenu,
+ NULL, ICON_RIGHTARROW_THIN,
+ "Settings", 0, yco-=20, 120, 20, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Delete|X", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_DELETE, "");
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+/* Select menu --------------------------- */
+
+static void do_selectmenu_columnmenu(bContext *C, void *arg, int event)
+{
+ switch (event) {
+ case ACTMENU_SEL_COLUMN_MARKERSBETWEEN:
+ //markers_selectkeys_between();
+ break;
+ case ACTMENU_SEL_COLUMN_KEYS:
+ //column_select_action_keys(1);
+ break;
+ case ACTMENU_SEL_COLUMN_MARKERSCOLUMN:
+ //column_select_action_keys(2);
+ break;
+ case ACTMENU_SEL_COLUMN_CFRA:
+ //column_select_action_keys(3);
+ break;
+ }
+}
+
+static uiBlock *action_selectmenu_columnmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "action_selectmenu_columnmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_selectmenu_columnmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "On Selected Keys|K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_SEL_COLUMN_KEYS, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "On Current Frame|Ctrl K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_SEL_COLUMN_CFRA, "");
+
+ if (SACTION_HASMARKERS) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "On Selected Markers|Shift K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_SEL_COLUMN_MARKERSCOLUMN, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Between Selected Markers|Alt K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_SEL_COLUMN_MARKERSBETWEEN, "");
+ }
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+
+ return block;
+}
+
+static void do_selectmenu(bContext *C, void *arg, int event)
+{
+ SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
+ //Key *key;
+
+ if (saction == NULL) return;
+
+ //key = get_action_mesh_key();
+
+ switch(event)
+ {
+ case ACTMENU_SEL_BORDER: /* Border Select */
+ //borderselect_action();
+ break;
+
+ case ACTMENU_SEL_BORDERC: /* Border Select */
+ //borderselect_actionchannels();
+ break;
+
+ case ACTMENU_SEL_BORDERM: /* Border Select */
+ //borderselect_markers();
+ break;
+
+ case ACTMENU_SEL_ALL_KEYS: /* Select/Deselect All Keys */
+ /*deselect_action_keys(1, 1);
+ BIF_undo_push("(De)Select Keys");
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWIPO, 0);*/
+ break;
+
+ case ACTMENU_SEL_ALL_CHAN: /* Select/Deselect All Channels */
+ /*deselect_action_channels(1);
+ BIF_undo_push("(De)Select Action Channels");
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWIPO, 0);*/
+ break;
+
+ case ACTMENU_SEL_ALL_MARKERS: /* select/deselect all markers */
+ /*deselect_markers(1, 0);
+ BIF_undo_push("(De)Select Markers");
+ allqueue(REDRAWMARKER, 0);*/
+ break;
+
+ case ACTMENU_SEL_INVERSE_KEYS: /* invert selection status of keys */
+ /*deselect_action_keys(0, 2);
+ BIF_undo_push("Inverse Keys");
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWIPO, 0);*/
+ break;
+
+ case ACTMENU_SEL_INVERSE_CHANNELS: /* invert selection status of channels */
+ /*deselect_action_channels(2);
+ BIF_undo_push("Inverse Action Channels");
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWIPO, 0);*/
+ break;
+
+ case ACTMENU_SEL_INVERSE_MARKERS: /* invert selection of markers */
+ /*deselect_markers(0, 2);
+ BIF_undo_push("Inverse Action Channels");
+ allqueue(REDRAWMARKER, 0);*/
+ break;
+
+ case ACTMENU_SEL_LEFTKEYS:
+ //selectkeys_leftright(1, SELECT_REPLACE);
+ break;
+
+ case ACTMENU_SEL_RIGHTKEYS:
+ //selectkeys_leftright(0, SELECT_REPLACE);
+ break;
+ }
+}
+
+static uiBlock *action_selectmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "action_selectmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_selectmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Border Select Keys|B", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_SEL_BORDER, "");
+ if (SACTION_HASMARKERS) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Border Select Markers|Ctrl B", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_SEL_BORDERM, "");
+ }
+ if (saction->mode != SACTCONT_SHAPEKEY) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Border Select Channels|B", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_SEL_BORDERC, "");
+ }
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Select/Deselect All Keys|A", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_SEL_ALL_KEYS, "");
+ if (SACTION_HASMARKERS) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Select/Deselect All Markers|Ctrl A", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_SEL_ALL_MARKERS, "");
+ }
+ if (saction->mode != SACTCONT_SHAPEKEY) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Select/Deselect All Channels|A", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_SEL_ALL_CHAN, "");
+ }
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Inverse Keys|Ctrl I", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_SEL_INVERSE_KEYS, "");
+ if (SACTION_HASMARKERS) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Inverse Markers|Ctrl Shift I", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_SEL_INVERSE_MARKERS, "");
+ }
+ if (saction->mode != SACTCONT_SHAPEKEY) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Inverse All Channels|Ctrl I", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_SEL_INVERSE_CHANNELS, "");
+ }
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Back In Time|Alt RMB", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_SEL_LEFTKEYS, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Ahead In Time|Alt RMB", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_SEL_RIGHTKEYS, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBlockBut(block, action_selectmenu_columnmenu,
+ NULL, ICON_RIGHTARROW_THIN, "Column Select Keys", 0, yco-=20, 120, 20, "");
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+/* View menu --------------------------- */
+
+static void do_viewmenu(bContext *C, void *arg, int event)
+{
+ switch(event) {
+ case ACTMENU_VIEW_CENTERVIEW: /* Center View to Current Frame */
+ //center_currframe();
+ break;
+ case ACTMENU_VIEW_AUTOUPDATE: /* Update Automatically */
+ /*if (BTST(G.saction->lock, 0))
+ G.saction->lock = BCLR(G.saction->lock, 0);
+ else
+ G.saction->lock = BSET(G.saction->lock, 0);*/
+ break;
+ case ACTMENU_VIEW_PLAY3D: /* Play Back Animation */
+ //play_anim(0);
+ break;
+ case ACTMENU_VIEW_PLAYALL: /* Play Back Animation in All */
+ //play_anim(1);
+ break;
+ case ACTMENU_VIEW_ALL: /* View All */
+ //do_action_buttons(B_ACTHOME);
+ break;
+ case ACTMENU_VIEW_LOCK:
+ /*G.v2d->flag ^= V2D_VIEWLOCK;
+ if (G.v2d->flag & V2D_VIEWLOCK)
+ view2d_do_locks(curarea, 0);*/
+ break;
+ case ACTMENU_VIEW_SLIDERS: /* Show sliders (when applicable) */
+ //G.saction->flag ^= SACTION_SLIDERS;
+ break;
+ case ACTMENU_VIEW_MAXIMIZE: /* Maximize Window */
+ /* using event B_FULL */
+ break;
+ case ACTMENU_VIEW_NEXTMARKER: /* Jump to next marker */
+ //nextprev_marker(1);
+ break;
+ case ACTMENU_VIEW_PREVMARKER: /* Jump to previous marker */
+ //nextprev_marker(-1);
+ break;
+ case ACTMENU_VIEW_TIME: /* switch between frames and seconds display */
+ //G.saction->flag ^= SACTION_DRAWTIME;
+ break;
+ case ACTMENU_VIEW_NOHIDE: /* Show hidden channels */
+ //G.saction->flag ^= SACTION_NOHIDE;
+ break;
+ case ACTMENU_VIEW_NEXTKEYFRAME: /* Jump to next keyframe */
+ //nextprev_action_keyframe(1);
+ break;
+ case ACTMENU_VIEW_PREVKEYFRAME: /* Jump to previous keyframe */
+ //nextprev_action_keyframe(-1);
+ break;
+ case ACTMENU_VIEW_TRANSDELDUPS: /* Don't delete duplicate/overlapping keyframes after transform */
+ //G.saction->flag ^= SACTION_NOTRANSKEYCULL;
+ break;
+ case ACTMENU_VIEW_HORIZOPTIMISE: /* Include keyframes not in view (horizontally) when preparing to draw */
+ //G.saction->flag ^= SACTION_HORIZOPTIMISEON;
+ break;
+ case ACTMENU_VIEW_GCOLORS: /* Draw grouped-action channels using its group's color */
+ //G.saction->flag ^= SACTION_NODRAWGCOLORS;
+ break;
+ case ACTMENU_VIEW_PREVRANGESET: /* Set preview range */
+ //anim_previewrange_set();
+ break;
+ case ACTMENU_VIEW_PREVRANGECLEAR: /* Clear preview range */
+ //anim_previewrange_clear();
+ break;
+ case ACTMENU_VIEW_PREVRANGEAUTO: /* Auto preview-range length */
+ //action_previewrange_set(G.saction->action);
+ break;
+ }
+}
+
+static uiBlock *action_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
+ View2D *v2d= UI_view2d_fromcontext_rwin(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "viewmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_viewmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Center View to Current Frame|C", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_CENTERVIEW, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if (saction->flag & SACTION_DRAWTIME) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Show Frames|Ctrl T", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_TIME, "");
+ }
+ else {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Show Seconds|Ctrl T", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_TIME, "");
+ }
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if (saction->mode == SACTCONT_GPENCIL) {
+ // this option may get removed in future
+ uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_HORIZOPTIMISEON)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
+ "Cull Out-of-View Keys (Time)|", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_HORIZOPTIMISE, "");
+ }
+ else {
+ uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_SLIDERS)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
+ "Show Sliders|", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_SLIDERS, "");
+
+ uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_NOHIDE)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
+ "Show Hidden Channels|", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_NOHIDE, "");
+
+ uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_NODRAWGCOLORS)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT,
+ "Use Group Colors|", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_GCOLORS, "");
+
+ // this option may get removed in future
+ uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_HORIZOPTIMISEON)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
+ "Cull Out-of-View Keys (Time)|", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_HORIZOPTIMISE, "");
+
+ uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_NOTRANSKEYCULL)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT,
+ "AutoMerge Keyframes|", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_TRANSDELDUPS, "");
+ }
+
+
+ uiDefIconTextBut(block, BUTM, 1, (v2d->flag & V2D_VIEWSYNC_SCREEN_TIME)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
+ "Lock Time to Other Windows|", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_LOCK, "");
+
+ /*uiDefIconTextBut(block, BUTM, 1, BTST(saction->lock, 0)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
+ "Update Automatically|", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_AUTOUPDATE, "");*/
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Jump To Next Marker|PageUp", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_NEXTMARKER, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Jump To Prev Marker|PageDown", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_PREVMARKER, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Jump To Next Keyframe|Ctrl PageUp", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_NEXTKEYFRAME, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Jump To Prev Keyframe|Ctrl PageDown", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_PREVKEYFRAME, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Play Back Animation|Alt A", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_PLAY3D, "");
+ //uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ // "Play Back Animation in 3D View|Alt Shift A", 0, yco-=20,
+ // menuwidth, 19, NULL, 0.0, 0.0, 1,
+ // ACTMENU_VIEW_PLAYALL, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Set Preview Range|Ctrl P", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_PREVRANGESET, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Clear Preview Range|Alt P", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_PREVRANGECLEAR, "");
+
+ if ((saction->mode == SACTCONT_ACTION) && (saction->action)) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Preview Range from Action Length|Ctrl Alt P", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_PREVRANGEAUTO, "");
+ }
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "View All|Home", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_ALL, "");
+
+/* if (!curarea->full)
+ uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1,
+ "Maximize Window|Ctrl UpArrow", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_VIEW_MAXIMIZE, "");
+ else
+ uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1,
+ "Tile Window|Ctrl DownArrow", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 0,
+ ACTMENU_VIEW_MAXIMIZE, "");
+*/
+
+ if (curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+/* ************************ header area region *********************** */
+
+static void do_action_buttons(bContext *C, void *arg, int event)
+{
+ switch(event) {
+ case B_REDR:
+ ED_area_tag_redraw(CTX_wm_area(C));
+ break;
+
+ case B_ACTCOPYKEYS:
+ WM_operator_name_call(C, "ACT_OT_keyframes_copy", WM_OP_EXEC_REGION_WIN, NULL);
+ break;
+ case B_ACTPASTEKEYS:
+ WM_operator_name_call(C, "ACT_OT_keyframes_paste", WM_OP_EXEC_REGION_WIN, NULL);
+ break;
+ }
+}
+
+static void saction_idpoin_handle(bContext *C, ID *id, int event)
+{
+ SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
+ Object *obact= CTX_data_active_object(C);
+
+ printf("actedit do id: \n");
+
+ switch (event) {
+ case UI_ID_BROWSE:
+ printf("browse \n");
+ case UI_ID_DELETE:
+ printf("browse or delete \n");
+ saction->action= (bAction*)id;
+
+ /* we must set this action to be the one used by active object (if not pinned) */
+ if (saction->pin == 0) {
+ AnimData *adt= BKE_id_add_animdata(&obact->id); /* this only adds if non-existant */
+
+ /* set action */
+ printf("\tset action \n");
+ adt->action= saction->action;
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ ED_undo_push(C, "Assign Action");
+ break;
+ case UI_ID_RENAME:
+ printf("actedit rename \n");
+ break;
+ case UI_ID_ADD_NEW:
+ printf("actedit addnew \n");
+ /* XXX not implemented */
+ break;
+ case UI_ID_OPEN:
+ printf("actedit open \n");
+ /* XXX not implemented */
+ break;
+ case UI_ID_ALONE:
+ printf("actedit alone \n");
+ /* XXX not implemented */
+ break;
+ case UI_ID_PIN:
+ printf("actedit pin \n");
+ break;
+ }
+}
+
+void action_header_buttons(const bContext *C, ARegion *ar)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceAction *saction= (SpaceAction *)CTX_wm_space_data(C);
+ bAnimContext ac;
+ uiBlock *block;
+ int xco, yco= 3, xmax;
+
+ block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_action_buttons, NULL);
+
+ xco= ED_area_header_standardbuttons(C, block, yco);
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ /* get context... (also syncs data) */
+ ANIM_animdata_get_context(C, &ac);
+
+ if ((sa->flag & HEADER_NO_PULLDOWN)==0) {
+
+ xmax= GetButStringLength("View");
+ uiDefPulldownBut(block, action_viewmenu, CTX_wm_area(C),
+ "View", xco, yco-2, xmax-3, 24, "");
+ xco+= xmax;
+
+ xmax= GetButStringLength("Select");
+ uiDefPulldownBut(block, action_selectmenu, CTX_wm_area(C),
+ "Select", xco, yco-2, xmax-3, 24, "");
+ xco+= xmax;
+
+ if ( (saction->mode == SACTCONT_DOPESHEET) ||
+ ((saction->action) && (saction->mode==SACTCONT_ACTION)) )
+ {
+ xmax= GetButStringLength("Channel");
+ uiDefPulldownBut(block, action_channelmenu, CTX_wm_area(C),
+ "Channel", xco, yco-2, xmax-3, 24, "");
+ xco+= xmax;
+ }
+ else if (saction->mode==SACTCONT_GPENCIL) {
+ xmax= GetButStringLength("Channel");
+ uiDefPulldownBut(block, action_gplayermenu, CTX_wm_area(C),
+ "Channel", xco, yco-2, xmax-3, 24, "");
+ xco+= xmax;
+ }
+
+ xmax= GetButStringLength("Marker");
+ uiDefPulldownBut(block, action_markermenu, CTX_wm_area(C),
+ "Marker", xco, yco-2, xmax-3, 24, "");
+ xco+= xmax;
+
+ if (saction->mode == SACTCONT_GPENCIL) {
+ xmax= GetButStringLength("Frame");
+ uiDefPulldownBut(block, action_framemenu, CTX_wm_area(C),
+ "Frame", xco, yco-2, xmax-3, 24, "");
+ xco+= xmax;
+ }
+ else {
+ xmax= GetButStringLength("Key");
+ uiDefPulldownBut(block, action_keymenu, CTX_wm_area(C),
+ "Key", xco, yco-2, xmax-3, 24, "");
+ xco+= xmax;
+ }
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ /* MODE SELECTOR */
+ uiDefButC(block, MENU, B_REDR,
+ "Editor Mode %t|DopeSheet %x3|Action Editor %x0|ShapeKey Editor %x1|Grease Pencil %x2",
+ xco,yco,90,YIC, &saction->mode, 0, 1, 0, 0,
+ "Editing modes for this editor");
+
+
+ xco += (90 + 8);
+
+ /*if (ac.data)*/
+ {
+ /* MODE-DEPENDENT DRAWING */
+ if (saction->mode == SACTCONT_DOPESHEET) {
+ /* FILTERING OPTIONS */
+ xco -= 10;
+
+ //uiBlockBeginAlign(block);
+ uiDefIconButBitI(block, TOG, ADS_FILTER_ONLYSEL, B_REDR, ICON_RESTRICT_SELECT_OFF, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Only display selected Objects");
+ //uiBlockEndAlign(block);
+ xco += 5;
+
+ uiBlockBeginAlign(block);
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOSCE, B_REDR, ICON_SCENE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Scene Animation");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOWOR, B_REDR, ICON_WORLD_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display World Animation");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOSHAPEKEYS, B_REDR, ICON_SHAPEKEY_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display ShapeKeys");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOMAT, B_REDR, ICON_MATERIAL_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Materials");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOLAM, B_REDR, ICON_LAMP_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Lamps");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCAM, B_REDR, ICON_CAMERA_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Cameras");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCUR, B_REDR, ICON_CURVE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Curves");
+ uiBlockEndAlign(block);
+ xco += 30;
+ }
+ else if (saction->mode == SACTCONT_ACTION) { // not too appropriate for shapekeys atm...
+ /* NAME ETC */
+ //uiClearButLock();
+
+ /* NAME ETC */
+ xco= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)saction->action, ID_AC, &saction->pin, xco, yco,
+ saction_idpoin_handle, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_DELETE|UI_ID_FAKE_USER|UI_ID_ALONE|UI_ID_PIN);
+
+ xco += 8;
+ }
+
+ /* COPY PASTE */
+ uiBlockBeginAlign(block);
+ uiDefIconBut(block, BUT, B_ACTCOPYKEYS, ICON_COPYDOWN, xco,yco,XIC,YIC, 0, 0, 0, 0, 0, "Copies the selected keyframes from the selected channel(s) to the buffer");
+ uiDefIconBut(block, BUT, B_ACTPASTEKEYS, ICON_PASTEDOWN, xco+=XIC,yco,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the keyframes from the buffer");
+ uiBlockEndAlign(block);
+ xco += (XIC + 8);
+
+ /* draw AUTOSNAP */
+ if (saction->mode != SACTCONT_GPENCIL) {
+ if (saction->flag & SACTION_DRAWTIME) {
+ uiDefButC(block, MENU, B_REDR,
+ "Auto-Snap Keyframes %t|No Snap %x0|Second Step %x1|Nearest Second %x2|Nearest Marker %x3",
+ xco,yco,70,YIC, &(saction->autosnap), 0, 1, 0, 0,
+ "Auto-snapping mode for keyframes when transforming");
+ }
+ else {
+ uiDefButC(block, MENU, B_REDR,
+ "Auto-Snap Keyframes %t|No Snap %x0|Frame Step %x1|Nearest Frame %x2|Nearest Marker %x3",
+ xco,yco,70,YIC, &(saction->autosnap), 0, 1, 0, 0,
+ "Auto-snapping mode for keyframes when transforming");
+ }
+
+ xco += (70 + 8);
+ }
+
+ /* draw LOCK */
+ // XXX this feature is probably not relevant anymore!
+ //uiDefIconButS(block, ICONTOG, B_LOCK, ICON_UNLOCKED, xco, yco, XIC, YIC,
+ // &(saction->lock), 0, 0, 0, 0,
+ // "Updates other affected window spaces automatically "
+ // "to reflect changes in real time");
+ }
+
+ /* always as last */
+ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, (int)(ar->v2d.tot.ymax-ar->v2d.tot.ymin));
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+}
+
+
diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h
new file mode 100644
index 00000000000..b4d2528b3b4
--- /dev/null
+++ b/source/blender/editors/space_action/action_intern.h
@@ -0,0 +1,126 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_ACTION_INTERN_H
+#define ED_ACTION_INTERN_H
+
+struct bContext;
+struct bAnimContext;
+struct SpaceAction;
+struct ARegion;
+struct wmWindowManager;
+struct wmOperatorType;
+struct ActKeysInc;
+struct bAnimListElem;
+
+/* internal exports only */
+
+/* ***************************************** */
+/* action_draw.c */
+void draw_channel_names(struct bAnimContext *ac, struct SpaceAction *saction, struct ARegion *ar);
+void draw_channel_strips(struct bAnimContext *ac, struct SpaceAction *saction, struct ARegion *ar);
+
+struct ActKeysInc *init_aki_data(struct bAnimContext *ac, struct bAnimListElem *ale);
+
+/* ***************************************** */
+/* action_header.c */
+void action_header_buttons(const struct bContext *C, struct ARegion *ar);
+
+/* ***************************************** */
+/* action_select.c */
+
+void ACT_OT_keyframes_select_all_toggle(struct wmOperatorType *ot);
+void ACT_OT_keyframes_select_border(struct wmOperatorType *ot);
+void ACT_OT_keyframes_select_column(struct wmOperatorType *ot);
+void ACT_OT_keyframes_clickselect(struct wmOperatorType *ot);
+
+/* defines for left-right select tool */
+enum {
+ ACTKEYS_LRSEL_TEST = -1,
+ ACTKEYS_LRSEL_NONE,
+ ACTKEYS_LRSEL_LEFT,
+ ACTKEYS_LRSEL_RIGHT,
+} eActKeys_LeftRightSelect_Mode;
+
+/* defines for column-select mode */
+enum {
+ ACTKEYS_COLUMNSEL_KEYS = 0,
+ ACTKEYS_COLUMNSEL_CFRA,
+ ACTKEYS_COLUMNSEL_MARKERS_COLUMN,
+ ACTKEYS_COLUMNSEL_MARKERS_BETWEEN,
+} eActKeys_ColumnSelect_Mode;
+
+/* ***************************************** */
+/* action_edit.c */
+
+void ACT_OT_previewrange_set(struct wmOperatorType *ot);
+void ACT_OT_view_all(struct wmOperatorType *ot);
+
+void ACT_OT_keyframes_copy(struct wmOperatorType *ot);
+void ACT_OT_keyframes_paste(struct wmOperatorType *ot);
+
+void ACT_OT_keyframes_insert(struct wmOperatorType *ot);
+void ACT_OT_keyframes_duplicate(struct wmOperatorType *ot);
+void ACT_OT_keyframes_delete(struct wmOperatorType *ot);
+void ACT_OT_keyframes_clean(struct wmOperatorType *ot);
+void ACT_OT_keyframes_sample(struct wmOperatorType *ot);
+
+void ACT_OT_keyframes_handle_type_set(struct wmOperatorType *ot);
+void ACT_OT_keyframes_interpolation_type(struct wmOperatorType *ot);
+void ACT_OT_keyframes_extrapolation_type_set(struct wmOperatorType *ot);
+
+void ACT_OT_keyframes_cfrasnap(struct wmOperatorType *ot);
+void ACT_OT_keyframes_snap(struct wmOperatorType *ot);
+void ACT_OT_keyframes_mirror(struct wmOperatorType *ot);
+
+/* defines for snap keyframes
+ * NOTE: keep in sync with eEditKeyframes_Snap (in ED_keyframes_edit.h)
+ */
+enum {
+ ACTKEYS_SNAP_CFRA = 1,
+ ACTKEYS_SNAP_NEAREST_FRAME,
+ ACTKEYS_SNAP_NEAREST_SECOND,
+ ACTKEYS_SNAP_NEAREST_MARKER,
+} eActKeys_Snap_Mode;
+
+/* defines for mirror keyframes
+ * NOTE: keep in sync with eEditKeyframes_Mirror (in ED_keyframes_edit.h)
+ */
+enum {
+ ACTKEYS_MIRROR_CFRA = 1,
+ ACTKEYS_MIRROR_YAXIS,
+ ACTKEYS_MIRROR_XAXIS,
+ ACTKEYS_MIRROR_MARKER,
+} eActKeys_Mirror_Mode;
+
+/* ***************************************** */
+/* action_ops.c */
+void action_operatortypes(void);
+void action_keymap(struct wmWindowManager *wm);
+
+#endif /* ED_ACTION_INTERN_H */
+
diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c
new file mode 100644
index 00000000000..49a0befdbe2
--- /dev/null
+++ b/source/blender/editors/space_action/action_ops.c
@@ -0,0 +1,174 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_action_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_utildefines.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "BIF_transform.h"
+
+#include "action_intern.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+
+/* ************************** registration - operator types **********************************/
+
+void action_operatortypes(void)
+{
+ /* keyframes */
+ /* selection */
+ WM_operatortype_append(ACT_OT_keyframes_clickselect);
+ WM_operatortype_append(ACT_OT_keyframes_select_all_toggle);
+ WM_operatortype_append(ACT_OT_keyframes_select_border);
+ WM_operatortype_append(ACT_OT_keyframes_select_column);
+
+ /* editing */
+ WM_operatortype_append(ACT_OT_keyframes_snap);
+ WM_operatortype_append(ACT_OT_keyframes_mirror);
+ WM_operatortype_append(ACT_OT_keyframes_cfrasnap);
+ WM_operatortype_append(ACT_OT_keyframes_handle_type_set);
+ WM_operatortype_append(ACT_OT_keyframes_interpolation_type);
+ WM_operatortype_append(ACT_OT_keyframes_extrapolation_type_set);
+ WM_operatortype_append(ACT_OT_keyframes_sample);
+ WM_operatortype_append(ACT_OT_keyframes_clean);
+ WM_operatortype_append(ACT_OT_keyframes_delete);
+ WM_operatortype_append(ACT_OT_keyframes_duplicate);
+ WM_operatortype_append(ACT_OT_keyframes_insert);
+ WM_operatortype_append(ACT_OT_keyframes_copy);
+ WM_operatortype_append(ACT_OT_keyframes_paste);
+
+ WM_operatortype_append(ACT_OT_previewrange_set);
+ WM_operatortype_append(ACT_OT_view_all);
+}
+
+/* ************************** registration - keymaps **********************************/
+
+static void action_keymap_keyframes (wmWindowManager *wm, ListBase *keymap)
+{
+ wmKeymapItem *kmi;
+
+ /* action_select.c - selection tools */
+ /* click-select */
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, 0, 0);
+ kmi= WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "column", 1);
+ kmi= WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+ kmi= WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT|KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+ RNA_boolean_set(kmi->ptr, "column", 1);
+ kmi= WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "left_right", ACTKEYS_LRSEL_TEST);
+
+ /* deselect all */
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_all_toggle", AKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1);
+
+ /* borderselect */
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_border", BKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_border", BKEY, KM_PRESS, KM_ALT, 0)->ptr, "axis_range", 1);
+
+ /* column select */
+ RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_column", KKEY, KM_PRESS, 0, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_KEYS);
+ RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_column", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_CFRA);
+ RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_column", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_COLUMN);
+ RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_column", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_BETWEEN);
+
+ /* action_edit.c */
+ /* snap - current frame to selected keys */
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_cfrasnap", SKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
+
+ /* menu + single-step transform */
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_mirror", MKEY, KM_PRESS, KM_SHIFT, 0);
+
+ /* menu + set setting */
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_handle_type_set", HKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_interpolation_type", TKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_extrapolation_type_set", EKEY, KM_PRESS, KM_SHIFT, 0);
+
+ /* destructive */
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_clean", OKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_sample", OKEY, KM_PRESS, KM_SHIFT, 0);
+
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_delete", DELKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_insert", IKEY, KM_PRESS, 0, 0);
+
+ /* copy/paste */
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_copy", CKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_paste", VKEY, KM_PRESS, KM_CTRL, 0);
+
+ /* auto-set range */
+ WM_keymap_add_item(keymap, "ACT_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
+ WM_keymap_add_item(keymap, "ACT_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
+
+ /* transform system */
+ transform_keymap_for_space(wm, keymap, SPACE_ACTION);
+}
+
+/* --------------- */
+
+void action_keymap(wmWindowManager *wm)
+{
+ ListBase *keymap;
+
+ /* channels */
+ /* Channels are not directly handled by the Action Editor module, but are inherited from the Animation module.
+ * All the relevant operations, keymaps, drawing, etc. can therefore all be found in that module instead, as these
+ * are all used for the IPO-Editor too.
+ */
+
+ /* keyframes */
+ keymap= WM_keymap_listbase(wm, "Action_Keys", SPACE_ACTION, 0);
+ action_keymap_keyframes(wm, keymap);
+}
+
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
new file mode 100644
index 00000000000..ced80647fec
--- /dev/null
+++ b/source/blender/editors/space_action/action_select.c
@@ -0,0 +1,997 @@
+/**
+ * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_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 "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_world_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "BKE_action.h"
+#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+#include "BKE_context.h"
+#include "BKE_utildefines.h"
+
+#include "UI_view2d.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_draw.h"
+#include "ED_keyframes_edit.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "action_intern.h"
+
+/* ************************************************************************** */
+/* KEYFRAMES STUFF */
+
+/* ******************** Deselect All Operator ***************************** */
+/* This operator works in one of three ways:
+ * 1) (de)select all (AKEY) - test if select all or deselect all
+ * 2) invert all (CTRL-IKEY) - invert selection of all keyframes
+ * 3) (de)select all - no testing is done; only for use internal tools as normal function...
+ */
+
+/* Deselects keyframes in the action editor
+ * - This is called by the deselect all operator, as well as other ones!
+ *
+ * - test: check if select or deselect all
+ * - sel: how to select keyframes
+ * 0 = deselect
+ * 1 = select
+ * 2 = invert
+ */
+static void deselect_action_keys (bAnimContext *ac, short test, short sel)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BeztEditData bed;
+ BeztEditFunc test_cb, sel_cb;
+
+ /* determine type-based settings */
+ if (ac->datatype == ANIMCONT_GPENCIL)
+ filter= (ANIMFILTER_VISIBLE);
+ else
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+
+ /* filter data */
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* init BezTriple looping data */
+ memset(&bed, 0, sizeof(BeztEditData));
+ test_cb= ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
+
+ /* See if we should be selecting or deselecting */
+ if (test) {
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ //if (is_gplayer_frame_selected(ale->data)) {
+ // sel= 0;
+ // break;
+ //}
+ }
+ else {
+ if (ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, test_cb, NULL)) {
+ sel= SELECT_SUBTRACT;
+ break;
+ }
+ }
+ }
+ }
+
+ /* convert sel to selectmode, and use that to get editor */
+ sel_cb= ANIM_editkeyframes_select(sel);
+
+ /* Now set the flags */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ //if (ale->type == ACTTYPE_GPLAYER)
+ // set_gplayer_frame_selection(ale->data, sel);
+ //else
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, sel_cb, NULL);
+ }
+
+ /* Cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_deselectall_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* 'standard' behaviour - check if selected, then apply relevant selection */
+ if (RNA_boolean_get(op->ptr, "invert"))
+ deselect_action_keys(&ac, 0, SELECT_INVERT);
+ else
+ deselect_action_keys(&ac, 1, SELECT_ADD);
+
+ /* set notifier that things have changed */
+ ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_select_all_toggle (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select All";
+ ot->idname= "ACT_OT_keyframes_select_all_toggle";
+
+ /* api callbacks */
+ ot->exec= actkeys_deselectall_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
+}
+
+/* ******************** Border Select Operator **************************** */
+/* This operator currently works in one of three ways:
+ * -> BKEY - 1) all keyframes within region are selected (ACTKEYS_BORDERSEL_ALLKEYS)
+ * -> ALT-BKEY - depending on which axis of the region was larger...
+ * -> 2) x-axis, so select all frames within frame range (ACTKEYS_BORDERSEL_FRAMERANGE)
+ * -> 3) y-axis, so select all frames within channels that region included (ACTKEYS_BORDERSEL_CHANNELS)
+ */
+
+/* defines for borderselect mode */
+enum {
+ ACTKEYS_BORDERSEL_ALLKEYS = 0,
+ ACTKEYS_BORDERSEL_FRAMERANGE,
+ ACTKEYS_BORDERSEL_CHANNELS,
+} eActKeys_BorderSelect_Mode;
+
+
+static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short selectmode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BeztEditData bed;
+ BeztEditFunc ok_cb, select_cb;
+ View2D *v2d= &ac->ar->v2d;
+ rctf rectf;
+ float ymin=0, ymax=(float)(-ACHANNEL_HEIGHT);
+
+ /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
+ UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin+2, &rectf.xmin, &rectf.ymin);
+ UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax-2, &rectf.xmax, &rectf.ymax);
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get beztriple editing/validation funcs */
+ select_cb= ANIM_editkeyframes_select(selectmode);
+
+ if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS))
+ ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
+ else
+ ok_cb= NULL;
+
+ /* init editing data */
+ memset(&bed, 0, sizeof(BeztEditData));
+
+ /* loop over data, doing border select */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ /* get new vertical minimum extent of channel */
+ ymin= ymax - ACHANNEL_STEP;
+
+ /* set horizontal range (if applicable) */
+ if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) {
+ /* if channel is mapped in NLA, apply correction */
+ if (nob) {
+ bed.f1= get_action_frame(nob, rectf.xmin);
+ bed.f2= get_action_frame(nob, rectf.xmax);
+ }
+ else {
+ bed.f1= rectf.xmin;
+ bed.f2= rectf.xmax;
+ }
+ }
+
+ /* perform vertical suitability check (if applicable) */
+ if ( (mode == ACTKEYS_BORDERSEL_FRAMERANGE) ||
+ !((ymax < rectf.ymin) || (ymin > rectf.ymax)) )
+ {
+ /* loop over data selecting */
+ if (ale->key_data) {
+ if (ale->datatype == ALE_FCURVE)
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+ }
+ else if (ale->type == ANIMTYPE_GROUP) {
+ bActionGroup *agrp= ale->data;
+ FCurve *fcu;
+
+ for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next)
+ ANIM_fcurve_keys_bezier_loop(&bed, fcu, ok_cb, select_cb, NULL);
+ }
+ //else if (ale->type == ANIMTYPE_GPLAYER) {
+ // borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode);
+ //}
+ }
+
+ /* set minimum extent to be the maximum of the next channel */
+ ymax=ymin;
+ }
+
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_borderselect_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ rcti rect;
+ short mode=0, selectmode=0;
+ int event;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get settings from operator */
+ rect.xmin= RNA_int_get(op->ptr, "xmin");
+ rect.ymin= RNA_int_get(op->ptr, "ymin");
+ rect.xmax= RNA_int_get(op->ptr, "xmax");
+ rect.ymax= RNA_int_get(op->ptr, "ymax");
+
+ event= RNA_int_get(op->ptr, "event_type");
+ if (event == LEFTMOUSE) // FIXME... hardcoded
+ selectmode = SELECT_ADD;
+ else
+ selectmode = SELECT_SUBTRACT;
+
+ /* selection 'mode' depends on whether borderselect region only matters on one axis */
+ if (RNA_boolean_get(op->ptr, "axis_range")) {
+ /* mode depends on which axis of the range is larger to determine which axis to use
+ * - checking this in region-space is fine, as it's fundamentally still going to be a different rect size
+ * - the frame-range select option is favoured over the channel one (x over y), as frame-range one is often
+ * used for tweaking timing when "blocking", while channels is not that useful...
+ */
+ if ((rect.xmax - rect.xmin) >= (rect.ymax - rect.ymin))
+ mode= ACTKEYS_BORDERSEL_FRAMERANGE;
+ else
+ mode= ACTKEYS_BORDERSEL_CHANNELS;
+ }
+ else
+ mode= ACTKEYS_BORDERSEL_ALLKEYS;
+
+ /* apply borderselect action */
+ borderselect_action(&ac, rect, mode, selectmode);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_select_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Border Select";
+ ot->idname= "ACT_OT_keyframes_select_border";
+
+ /* api callbacks */
+ ot->invoke= WM_border_select_invoke;
+ ot->exec= actkeys_borderselect_exec;
+ ot->modal= WM_border_select_modal;
+
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* rna */
+ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+
+ RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
+}
+
+/* ******************** Column Select Operator **************************** */
+/* This operator works in one of four ways:
+ * - 1) select all keyframes in the same frame as a selected one (KKEY)
+ * - 2) select all keyframes in the same frame as the current frame marker (CTRL-KKEY)
+ * - 3) select all keyframes in the same frame as a selected markers (SHIFT-KKEY)
+ * - 4) select all keyframes that occur between selected markers (ALT-KKEY)
+ */
+
+/* defines for column-select mode */
+static EnumPropertyItem prop_column_select_types[] = {
+ {ACTKEYS_COLUMNSEL_KEYS, "KEYS", "On Selected Keyframes", ""},
+ {ACTKEYS_COLUMNSEL_CFRA, "CFRA", "On Current Frame", ""},
+ {ACTKEYS_COLUMNSEL_MARKERS_COLUMN, "MARKERS_COLUMN", "On Selected Markers", ""},
+ {ACTKEYS_COLUMNSEL_MARKERS_BETWEEN, "MARKERS_BETWEEN", "Between Min/Max Selected Markers", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* ------------------- */
+
+/* Selects all visible keyframes between the specified markers */
+static void markers_selectkeys_between (bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BeztEditFunc select_cb;
+ BeztEditData bed;
+ float min, max;
+
+ /* get extreme markers */
+ //get_minmax_markers(1, &min, &max); // FIXME... add back markers api!
+ min= (float)ac->scene->r.sfra; // xxx temp code
+ max= (float)ac->scene->r.efra; // xxx temp code
+
+ if (min==max) return;
+ min -= 0.5f;
+ max += 0.5f;
+
+ /* get editing funcs + data */
+ select_cb= ANIM_editkeyframes_select(SELECT_ADD);
+ memset(&bed, 0, sizeof(BeztEditData));
+ bed.f1= min;
+ bed.f2= max;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* select keys in-between */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ if (nob) {
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, select_cb, NULL);
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
+ }
+ else {
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, select_cb, NULL);
+ }
+ }
+
+ /* Cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+
+/* helper callback for columnselect_action_keys() -> populate list CfraElems with frame numbers from selected beztriples */
+// TODO: if some other code somewhere needs this, it'll be time to port this over to keyframes_edit.c!!!
+static short bezt_to_cfraelem(BeztEditData *bed, BezTriple *bezt)
+{
+ /* only if selected */
+ if (bezt->f2 & SELECT) {
+ CfraElem *ce= MEM_callocN(sizeof(CfraElem), "cfraElem");
+ BLI_addtail(&bed->list, ce);
+
+ ce->cfra= bezt->vec[1][0];
+ }
+
+ return 0;
+}
+
+/* Selects all visible keyframes in the same frames as the specified elements */
+static void columnselect_action_keys (bAnimContext *ac, short mode)
+{
+ ListBase anim_data= {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ Scene *scene= ac->scene;
+ CfraElem *ce;
+ BeztEditFunc select_cb, ok_cb;
+ BeztEditData bed;
+
+ /* initialise keyframe editing data */
+ memset(&bed, 0, sizeof(BeztEditData));
+
+ /* build list of columns */
+ switch (mode) {
+ case ACTKEYS_COLUMNSEL_KEYS: /* list of selected keys */
+ if (ac->datatype == ANIMCONT_GPENCIL) {
+ filter= (ANIMFILTER_VISIBLE);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ //for (ale= anim_data.first; ale; ale= ale->next)
+ // gplayer_make_cfra_list(ale->data, &elems, 1);
+ }
+ else {
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale= anim_data.first; ale; ale= ale->next)
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_to_cfraelem, NULL);
+ }
+ BLI_freelistN(&anim_data);
+ break;
+
+ case ACTKEYS_COLUMNSEL_CFRA: /* current frame */
+ /* make a single CfraElem for storing this */
+ ce= MEM_callocN(sizeof(CfraElem), "cfraElem");
+ BLI_addtail(&bed.list, ce);
+
+ ce->cfra= (float)CFRA;
+ break;
+
+ case ACTKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
+ // FIXME: markers api needs to be improved for this first!
+ //make_marker_cfra_list(&elems, 1);
+ return; // XXX currently, this does nothing!
+ break;
+
+ default: /* invalid option */
+ return;
+ }
+
+ /* set up BezTriple edit callbacks */
+ select_cb= ANIM_editkeyframes_select(SELECT_ADD);
+ ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAME);
+
+ /* loop through all of the keys and select additional keyframes
+ * based on the keys found to be selected above
+ */
+ if (ac->datatype == ANIMCONT_GPENCIL)
+ filter= (ANIMFILTER_VISIBLE);
+ else
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ /* loop over cfraelems (stored in the BeztEditData->list)
+ * - we need to do this here, as we can apply fewer NLA-mapping conversions
+ */
+ for (ce= bed.list.first; ce; ce= ce->next) {
+ /* set frame for validation callback to refer to */
+ if (nob)
+ bed.f1= get_action_frame(nob, ce->cfra);
+ else
+ bed.f1= ce->cfra;
+
+ /* select elements with frame number matching cfraelem */
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+
+#if 0 // XXX reenable when Grease Pencil stuff is back
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ bGPDlayer *gpl= (bGPDlayer *)ale->data;
+ bGPDframe *gpf;
+
+ for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+ if (ecfra == gpf->framenum)
+ gpf->flag |= GP_FRAME_SELECT;
+ }
+ }
+ //else...
+#endif // XXX reenable when Grease Pencil stuff is back
+ }
+ }
+
+ /* free elements */
+ BLI_freelistN(&bed.list);
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_columnselect_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* action to take depends on the mode */
+ mode= RNA_enum_get(op->ptr, "mode");
+
+ if (mode == ACTKEYS_COLUMNSEL_MARKERS_BETWEEN)
+ markers_selectkeys_between(&ac);
+ else
+ columnselect_action_keys(&ac, mode);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_SELECT);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_select_column (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select All";
+ ot->idname= "ACT_OT_keyframes_select_column";
+
+ /* api callbacks */
+ ot->exec= actkeys_columnselect_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
+}
+
+/* ******************** Mouse-Click Select Operator *********************** */
+/* This operator works in one of three ways:
+ * - 1) keyframe under mouse - no special modifiers
+ * - 2) all keyframes on the same side of current frame indicator as mouse - ALT modifier
+ * - 3) column select all keyframes in frame under mouse - CTRL modifier
+ *
+ * In addition to these basic options, the SHIFT modifier can be used to toggle the
+ * selection mode between replacing the selection (without) and inverting the selection (with).
+ */
+
+/* defines for left-right select tool */
+static EnumPropertyItem prop_actkeys_leftright_select_types[] = {
+ {ACTKEYS_LRSEL_TEST, "CHECK", "Check if Select Left or Right", ""},
+ {ACTKEYS_LRSEL_NONE, "OFF", "Don't select", ""},
+ {ACTKEYS_LRSEL_LEFT, "LEFT", "Before current frame", ""},
+ {ACTKEYS_LRSEL_RIGHT, "RIGHT", "After current frame", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* sensitivity factor for frame-selections */
+#define FRAME_CLICK_THRESH 0.1f
+
+/* ------------------- */
+
+/* option 1) select keyframe directly under mouse */
+static void actkeys_mselect_single (bAnimContext *ac, bAnimListElem *ale, short select_mode, float selx)
+{
+ bDopeSheet *ads= (ac->datatype == ANIMCONT_DOPESHEET) ? ac->data : NULL;
+ int ds_filter = ((ads) ? (ads->filterflag) : (0));
+
+ BeztEditData bed;
+ BeztEditFunc select_cb, ok_cb;
+
+ /* get functions for selecting keyframes */
+ select_cb= ANIM_editkeyframes_select(select_mode);
+ ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAME);
+ memset(&bed, 0, sizeof(BeztEditData));
+ bed.f1= selx;
+
+ /* select the nominated keyframe on the given frame */
+ ANIM_animchannel_keys_bezier_loop(&bed, ale, ok_cb, select_cb, NULL, ds_filter);
+}
+
+/* Option 2) Selects all the keyframes on either side of the current frame (depends on which side the mouse is on) */
+static void actkeys_mselect_leftright (bAnimContext *ac, short leftright, short select_mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BeztEditFunc ok_cb, select_cb;
+ BeztEditData bed;
+ Scene *scene= ac->scene;
+
+ /* if select mode is replace, deselect all keyframes (and channels) first */
+ if (select_mode==SELECT_REPLACE) {
+ select_mode= SELECT_ADD;
+
+ /* deselect all other channels and keyframes */
+ ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ deselect_action_keys(ac, 0, SELECT_SUBTRACT);
+ }
+
+ /* set callbacks and editing data */
+ ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
+ select_cb= ANIM_editkeyframes_select(select_mode);
+
+ memset(&bed, 0, sizeof(BeztEditFunc));
+ if (leftright == ACTKEYS_LRSEL_LEFT) {
+ bed.f1 = -MAXFRAMEF;
+ bed.f2 = (float)(CFRA + FRAME_CLICK_THRESH);
+ }
+ else {
+ bed.f1 = (float)(CFRA - FRAME_CLICK_THRESH);
+ bed.f2 = MAXFRAMEF;
+ }
+
+ /* filter data */
+ if (ac->datatype == ANIMCONT_GPENCIL)
+ filter= (ANIMFILTER_VISIBLE);
+ else
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* select keys on the side where most data occurs */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ if (nob) {
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
+ }
+ //else if (ale->type == ANIMTYPE_GPLAYER)
+ // borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD);
+ else
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+ }
+
+ /* Cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* Option 3) Selects all visible keyframes in the same frame as the mouse click */
+static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float selx)
+{
+ ListBase anim_data= {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BeztEditFunc select_cb, ok_cb;
+ BeztEditData bed;
+
+ /* initialise keyframe editing data */
+ memset(&bed, 0, sizeof(BeztEditData));
+
+ /* set up BezTriple edit callbacks */
+ select_cb= ANIM_editkeyframes_select(select_mode);
+ ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAME);
+
+ /* loop through all of the keys and select additional keyframes
+ * based on the keys found to be selected above
+ */
+ if (ac->datatype == ANIMCONT_GPENCIL)
+ filter= (ANIMFILTER_VISIBLE);
+ else
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ /* set frame for validation callback to refer to */
+ if (nob)
+ bed.f1= get_action_frame(nob, selx);
+ else
+ bed.f1= selx;
+
+ /* select elements with frame number matching cfra */
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+
+#if 0 // XXX reenable when Grease Pencil stuff is back
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ bGPDlayer *gpl= (bGPDlayer *)ale->data;
+ bGPDframe *gpf;
+
+ for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+ if (ecfra == gpf->framenum)
+ gpf->flag |= GP_FRAME_SELECT;
+ }
+ }
+ //else...
+#endif // XXX reenable when Grease Pencil stuff is back
+ }
+
+ /* free elements */
+ BLI_freelistN(&bed.list);
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode, short column)
+{
+ ListBase anim_data = {NULL, NULL};
+ ListBase anim_keys = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ View2D *v2d= &ac->ar->v2d;
+ int channel_index;
+ short found = 0;
+ float selx = 0.0f;
+ float x, y;
+ rctf rectf;
+
+
+ /* use View2D to determine the index of the channel (i.e a row in the list) where keyframe was */
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
+ UI_view2d_listview_view_to_cell(v2d, 0, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index);
+
+ /* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click (size of keyframe icon) */
+ UI_view2d_region_to_view(v2d, mval[0]-7, mval[1], &rectf.xmin, &rectf.ymin);
+ UI_view2d_region_to_view(v2d, mval[0]+7, mval[1], &rectf.xmax, &rectf.ymax);
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* try to get channel */
+ ale= BLI_findlink(&anim_data, channel_index);
+ if (ale == NULL) {
+ /* channel not found */
+ printf("Error: animation channel (index = %d) not found in mouse_action_keys() \n", channel_index);
+ }
+ else {
+ /* found match - must return here... */
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+ ActKeysInc *aki= init_aki_data(ac, ale);
+ ActKeyColumn *ak;
+ float xmin, xmax;
+
+ /* apply NLA-scaling correction? */
+ if (nob) {
+ xmin= get_action_frame(nob, rectf.xmin);
+ xmax= get_action_frame(nob, rectf.xmax);
+ }
+ else {
+ xmin= rectf.xmin;
+ xmax= rectf.xmax;
+ }
+
+ /* make list of keyframes */
+ if (ale->key_data) {
+ switch (ale->datatype) {
+ case ALE_OB:
+ {
+ Object *ob= (Object *)ale->key_data;
+ ob_to_keylist(ob, &anim_keys, NULL, aki);
+ }
+ break;
+ case ALE_ACT:
+ {
+ bAction *act= (bAction *)ale->key_data;
+ action_to_keylist(act, &anim_keys, NULL, aki);
+ }
+ break;
+ case ALE_FCURVE:
+ {
+ FCurve *fcu= (FCurve *)ale->key_data;
+ fcurve_to_keylist(fcu, &anim_keys, NULL, aki);
+ }
+ break;
+ }
+ }
+ else if (ale->type == ANIMTYPE_GROUP) {
+ bActionGroup *agrp= (bActionGroup *)ale->data;
+ agroup_to_keylist(agrp, &anim_keys, NULL, aki);
+ }
+ else if (ale->type == ANIMTYPE_GPDATABLOCK) {
+ /* cleanup */
+ // FIXME:...
+ BLI_freelistN(&anim_data);
+ return;
+ }
+ else if (ale->type == ANIMTYPE_GPLAYER) {
+ bGPDlayer *gpl= (bGPDlayer *)ale->data;
+ gpl_to_keylist(gpl, &anim_keys, NULL, aki);
+ }
+
+ /* loop through keyframes, finding one that was clicked on */
+ for (ak= anim_keys.first; ak; ak= ak->next) {
+ if (IN_RANGE(ak->cfra, xmin, xmax)) {
+ selx= ak->cfra;
+ found= 1;
+ break;
+ }
+ }
+
+ /* remove active channel from list of channels for separate treatment (since it's needed later on) */
+ BLI_remlink(&anim_data, ale);
+
+ /* cleanup temporary lists */
+ BLI_freelistN(&anim_keys);
+ anim_keys.first = anim_keys.last = NULL;
+
+ /* free list of channels, since it's not used anymore */
+ BLI_freelistN(&anim_data);
+ }
+
+ /* for replacing selection, firstly need to clear existing selection */
+ if (select_mode == SELECT_REPLACE) {
+ /* reset selection mode for next steps */
+ select_mode = SELECT_ADD;
+
+ /* deselect all keyframes */
+ deselect_action_keys(ac, 0, SELECT_SUBTRACT);
+
+ /* highlight channel clicked on */
+ if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) {
+ /* deselect all other channels first */
+ ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+
+ /* Highlight Action-Group or F-Curve? */
+ if (ale->type == ANIMTYPE_GROUP) {
+ bActionGroup *agrp= ale->data;
+
+ agrp->flag |= AGRP_SELECTED;
+ ANIM_set_active_channel(ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
+ }
+ else if (ale->type == ANIMTYPE_FCURVE) {
+ FCurve *fcu= ale->data;
+
+ fcu->flag |= FCURVE_SELECTED;
+ ANIM_set_active_channel(ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
+ }
+ }
+ else if (ac->datatype == ANIMCONT_GPENCIL) {
+ ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+
+ /* Highlight gpencil layer */
+ //gpl->flag |= GP_LAYER_SELECT;
+ //gpencil_layer_setactive(gpd, gpl);
+ }
+ }
+
+ /* only select keyframes if we clicked on a valid channel and hit something */
+ if (ale) {
+ /* apply selection to keyframes */
+ if (/*gpl*/0) {
+ /* grease pencil */
+ //select_gpencil_frame(gpl, (int)selx, selectmode);
+ }
+ else if (column) {
+ /* select all keyframes in the same frame as the one we hit on the active channel */
+ actkeys_mselect_column(ac, select_mode, selx);
+ }
+ else {
+ /* select the nominated keyframe on the given frame */
+ actkeys_mselect_single(ac, ale, select_mode, selx);
+ }
+
+ /* free this channel */
+ MEM_freeN(ale);
+ }
+}
+
+/* handle clicking */
+static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ bAnimContext ac;
+ Scene *scene;
+ ARegion *ar;
+ View2D *v2d;
+ short selectmode, column;
+ int mval[2];
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get useful pointers from animation context data */
+ scene= ac.scene;
+ ar= ac.ar;
+ v2d= &ar->v2d;
+
+ /* get mouse coordinates (in region coordinates) */
+ mval[0]= (event->x - ar->winrct.xmin);
+ mval[1]= (event->y - ar->winrct.ymin);
+
+ /* select mode is either replace (deselect all, then add) or add/extend */
+ if (RNA_boolean_get(op->ptr, "extend"))
+ selectmode= SELECT_INVERT;
+ else
+ selectmode= SELECT_REPLACE;
+
+ /* column selection */
+ column= RNA_boolean_get(op->ptr, "column");
+
+ /* figure out action to take */
+ if (RNA_enum_get(op->ptr, "left_right")) {
+ /* select all keys on same side of current frame as mouse */
+ float x;
+
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, NULL);
+ if (x < CFRA)
+ RNA_int_set(op->ptr, "left_right", ACTKEYS_LRSEL_LEFT);
+ else
+ RNA_int_set(op->ptr, "left_right", ACTKEYS_LRSEL_RIGHT);
+
+ actkeys_mselect_leftright(&ac, RNA_enum_get(op->ptr, "left_right"), selectmode);
+ }
+ else {
+ /* select keyframe(s) based upon mouse position*/
+ mouse_action_keys(&ac, mval, selectmode, column);
+ }
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
+
+ /* for tweak grab to work */
+ return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
+}
+
+void ACT_OT_keyframes_clickselect (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mouse Select Keys";
+ ot->idname= "ACT_OT_keyframes_clickselect";
+
+ /* api callbacks - absolutely no exec() this yet... */
+ ot->invoke= actkeys_clickselect_invoke;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ // XXX should we make this into separate operators?
+ RNA_def_enum(ot->srna, "left_right", prop_actkeys_leftright_select_types, 0, "Left Right", ""); // CTRLKEY
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
+ RNA_def_boolean(ot->srna, "column", 0, "Column Select", ""); // ALTKEY
+}
+
+/* ************************************************************************** */
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
new file mode 100644
index 00000000000..b4e43c29c3d
--- /dev/null
+++ b/source/blender/editors/space_action/space_action.c
@@ -0,0 +1,447 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_listBase.h"
+#include "DNA_action_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframes_draw.h"
+#include "ED_markers.h"
+
+#include "action_intern.h" // own include
+
+/* ******************** default callbacks for action space ***************** */
+
+static SpaceLink *action_new(const bContext *C)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceAction *saction;
+ ARegion *ar;
+
+ saction= MEM_callocN(sizeof(SpaceAction), "initaction");
+ saction->spacetype= SPACE_ACTION;
+
+ saction->autosnap = SACTSNAP_FRAME;
+ saction->mode= SACTCONT_DOPESHEET;
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for action");
+
+ BLI_addtail(&saction->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_BOTTOM;
+
+ /* channel list region */
+ ar= MEM_callocN(sizeof(ARegion), "channel area for action");
+ BLI_addtail(&saction->regionbase, ar);
+ ar->regiontype= RGN_TYPE_CHANNELS;
+ ar->alignment= RGN_ALIGN_LEFT;
+
+ /* only need to set scroll settings, as this will use 'listview' v2d configuration */
+ ar->v2d.scroll = V2D_SCROLL_BOTTOM;
+ ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for action");
+
+ BLI_addtail(&saction->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+
+ ar->v2d.tot.xmin= -10.0f;
+ ar->v2d.tot.ymin= (float)(-sa->winy);
+ ar->v2d.tot.xmax= (float)(sa->winx);
+ ar->v2d.tot.ymax= 0.0f;
+
+ ar->v2d.cur = ar->v2d.tot;
+
+ ar->v2d.min[0]= 0.0f;
+ ar->v2d.min[1]= 0.0f;
+
+ ar->v2d.max[0]= MAXFRAMEF;
+ ar->v2d.max[1]= 10000.0f;
+
+ ar->v2d.minzoom= 0.01f;
+ ar->v2d.maxzoom= 50;
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
+ ar->v2d.keepzoom= V2D_LOCKZOOM_Y;
+ ar->v2d.align= V2D_ALIGN_NO_POS_Y;
+ ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
+
+ return (SpaceLink *)saction;
+}
+
+/* not spacelink itself */
+static void action_free(SpaceLink *sl)
+{
+// SpaceAction *saction= (SpaceAction*) sl;
+
+}
+
+
+/* spacetype; init callback */
+static void action_init(struct wmWindowManager *wm, ScrArea *sa)
+{
+
+}
+
+static SpaceLink *action_duplicate(SpaceLink *sl)
+{
+ SpaceAction *sactionn= MEM_dupallocN(sl);
+
+ /* clear or remove stuff from old */
+
+ return (SpaceLink *)sactionn;
+}
+
+
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void action_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "Action_Keys", SPACE_ACTION, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+static void action_main_area_draw(const bContext *C, ARegion *ar)
+{
+ /* draw entirely, view changes should be handled here */
+ SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
+ bAnimContext ac;
+ View2D *v2d= &ar->v2d;
+ View2DGrid *grid;
+ View2DScrollers *scrollers;
+ float col[3];
+ short unit=0, flag=0;
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ UI_view2d_view_ortho(C, v2d);
+
+ /* time grid */
+ unit= (saction->flag & SACTION_DRAWTIME)? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
+ grid= UI_view2d_grid_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy);
+ UI_view2d_grid_draw(C, v2d, grid, V2D_GRIDLINES_ALL);
+ UI_view2d_grid_free(grid);
+
+ /* data */
+ if (ANIM_animdata_get_context(C, &ac)) {
+ draw_channel_strips(&ac, saction, ar);
+ }
+
+ /* current frame */
+ if (saction->flag & SACTION_DRAWTIME) flag |= DRAWCFRA_UNIT_SECONDS;
+ if ((saction->flag & SACTION_NODRAWCFRANUM)==0) flag |= DRAWCFRA_SHOW_NUMBOX;
+ ANIM_draw_cfra(C, v2d, flag);
+
+ /* markers */
+ UI_view2d_view_orthoSpecial(C, v2d, 1);
+ draw_markers_time(C, 0);
+
+ /* preview range */
+ UI_view2d_view_ortho(C, v2d);
+ ANIM_draw_previewrange(C, v2d);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ scrollers= UI_view2d_scrollers_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void action_channel_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "Animation_Channels", 0, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+static void action_channel_area_draw(const bContext *C, ARegion *ar)
+{
+ /* draw entirely, view changes should be handled here */
+ SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
+ bAnimContext ac;
+ View2D *v2d= &ar->v2d;
+ View2DScrollers *scrollers;
+ float col[3];
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ UI_view2d_view_ortho(C, v2d);
+
+ /* data */
+ if (ANIM_animdata_get_context(C, &ac)) {
+ draw_channel_names(&ac, saction, ar);
+ }
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+}
+
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void action_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+}
+
+static void action_header_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ /* clear */
+ if(ED_screen_area_active(C))
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ else
+ UI_GetThemeColor3fv(TH_HEADERDESEL, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ action_header_buttons(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+static void action_channel_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ switch(wmn->data) {
+ case ND_OB_ACTIVE:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch(wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_KEYS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ default:
+ if(wmn->data==ND_KEYS)
+ ED_region_tag_redraw(ar);
+ }
+}
+
+static void action_main_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ switch(wmn->data) {
+ case ND_OB_ACTIVE:
+ case ND_FRAME:
+ case ND_MARKERS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch(wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_KEYS:
+ case ND_TRANSFORM:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ default:
+ if(wmn->data==ND_KEYS)
+ ED_region_tag_redraw(ar);
+ }
+}
+
+/* editor level listener */
+static void action_listener(ScrArea *sa, wmNotifier *wmn)
+{
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SCENE:
+ /*switch (wmn->data) {
+ case ND_OB_ACTIVE:
+ case ND_OB_SELECT:
+ ED_area_tag_refresh(sa);
+ break;
+ }*/
+ ED_area_tag_refresh(sa);
+ break;
+ case NC_OBJECT:
+ /*switch (wmn->data) {
+ case ND_BONE_SELECT:
+ case ND_BONE_ACTIVE:
+ ED_area_tag_refresh(sa);
+ break;
+ }*/
+ ED_area_tag_refresh(sa);
+ break;
+ }
+}
+
+static void action_refresh(const bContext *C, ScrArea *sa)
+{
+ SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
+
+ /* updates to data needed depends on Action Editor mode... */
+ switch (saction->mode) {
+ case SACTCONT_DOPESHEET: /* DopeSheet - for now, just all armatures... */
+ {
+
+ }
+ break;
+
+ case SACTCONT_ACTION: /* Action Editor - just active object will do */
+ {
+ Object *ob= CTX_data_active_object(C);
+
+ /* sync changes to bones to the corresponding action channels */
+ ANIM_pose_to_action_sync(ob, sa);
+ }
+ break;
+ }
+
+ /* region updates? */
+ // XXX resizing y-extents of tot should go here?
+}
+
+/* only called once, from space/spacetypes.c */
+void ED_spacetype_action(void)
+{
+ SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype action");
+ ARegionType *art;
+
+ st->spaceid= SPACE_ACTION;
+
+ st->new= action_new;
+ st->free= action_free;
+ st->init= action_init;
+ st->duplicate= action_duplicate;
+ st->operatortypes= action_operatortypes;
+ st->keymap= action_keymap;
+ st->listener= action_listener;
+ st->refresh= action_refresh;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype action region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init= action_main_area_init;
+ art->draw= action_main_area_draw;
+ art->listener= action_main_area_listener;
+ art->keymapflag= ED_KEYMAP_VIEW2D/*|ED_KEYMAP_MARKERS*/|ED_KEYMAP_ANIMATION|ED_KEYMAP_FRAMES;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype action region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
+
+ art->init= action_header_area_init;
+ art->draw= action_header_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: channels */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype action region");
+ art->regionid = RGN_TYPE_CHANNELS;
+ art->minsizex= 200;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+
+ art->init= action_channel_area_init;
+ art->draw= action_channel_area_draw;
+ art->listener= action_channel_area_listener;
+
+ BLI_addhead(&st->regiontypes, art);
+
+
+ BKE_spacetype_register(st);
+}
+
diff --git a/source/blender/editors/space_api/Makefile b/source/blender/editors/space_api/Makefile
new file mode 100644
index 00000000000..46f926afbc9
--- /dev/null
+++ b/source/blender/editors/space_api/Makefile
@@ -0,0 +1,50 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_space
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/space_api/SConscript b/source/blender/editors/space_api/SConscript
new file mode 100644
index 00000000000..c3105d3e50c
--- /dev/null
+++ b/source/blender/editors/space_api/SConscript
@@ -0,0 +1,15 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna'
+incs += ' ../../windowmanager ../../python ../../makesrna'
+incs += ' #/intern/guardedalloc #/extern/glew/include'
+
+defs = ''
+
+if not env['WITH_BF_PYTHON']:
+ defs += 'DISABLE_PYTHON'
+
+env.BlenderLib ( 'bf_editors_space_api', sources, Split(incs), Split(defs), libtype=['core'], priority=[30] )
diff --git a/source/blender/editors/space_api/space.c b/source/blender/editors/space_api/space.c
new file mode 100644
index 00000000000..3112cfffb22
--- /dev/null
+++ b/source/blender/editors/space_api/space.c
@@ -0,0 +1,45 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_screen.h"
+
+/* */
+
+
+
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
new file mode 100644
index 00000000000..9a4d1f329e8
--- /dev/null
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -0,0 +1,249 @@
+/**
+ * $Id: spacetypes.c
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation, 2008
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "BIF_gl.h"
+
+#include "ED_anim_api.h"
+#include "ED_armature.h"
+#include "ED_curve.h"
+#include "ED_mesh.h"
+#include "ED_markers.h"
+#include "ED_object.h"
+#include "ED_particle.h"
+#include "ED_sculpt.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+#include "ED_uvedit.h"
+
+/* only call once on startup, storage is global in BKE kernel listbase */
+void ED_spacetypes_init(void)
+{
+ const ListBase *spacetypes;
+ SpaceType *type;
+
+ /* create space types */
+ ED_spacetype_outliner();
+ ED_spacetype_time();
+ ED_spacetype_view3d();
+ ED_spacetype_ipo();
+ ED_spacetype_image();
+ ED_spacetype_node();
+ ED_spacetype_buttons();
+ ED_spacetype_info();
+ ED_spacetype_file();
+ ED_spacetype_sound();
+ ED_spacetype_action();
+ ED_spacetype_nla();
+ ED_spacetype_script();
+ ED_spacetype_text();
+ ED_spacetype_sequencer();
+// ...
+
+ /* register operator types for screen and all spaces */
+ ED_operatortypes_screen();
+ ED_operatortypes_anim();
+ ED_operatortypes_animchannels(); // XXX have this as part of anim() ones instead?
+ ED_operatortypes_object();
+ ED_operatortypes_mesh();
+ ED_operatortypes_sculpt();
+ ED_operatortypes_uvedit();
+ ED_operatortypes_paint();
+ ED_operatortypes_particle();
+ ED_operatortypes_curve();
+ ED_operatortypes_armature();
+ ED_marker_operatortypes();
+
+ ui_view2d_operatortypes();
+
+ spacetypes = BKE_spacetypes_list();
+ for(type=spacetypes->first; type; type=type->next)
+ type->operatortypes();
+}
+
+/* called in wm.c */
+/* keymap definitions are registered only once per WM initialize, usually on file read,
+ using the keymap the actual areas/regions add the handlers */
+void ED_spacetypes_keymap(wmWindowManager *wm)
+{
+ const ListBase *spacetypes;
+ SpaceType *stype;
+ ARegionType *atype;
+
+ ED_keymap_screen(wm);
+ ED_keymap_anim(wm);
+ ED_keymap_animchannels(wm);
+ ED_keymap_object(wm);
+ ED_keymap_mesh(wm);
+ ED_keymap_uvedit(wm);
+ ED_keymap_curve(wm);
+ ED_keymap_armature(wm);
+ ED_keymap_particle(wm);
+ ED_marker_keymap(wm);
+
+ UI_view2d_keymap(wm);
+
+ spacetypes = BKE_spacetypes_list();
+ for(stype=spacetypes->first; stype; stype=stype->next) {
+ if(stype->keymap)
+ stype->keymap(wm);
+ for(atype=stype->regiontypes.first; atype; atype=atype->next) {
+ if(atype->keymap)
+ atype->keymap(wm);
+ }
+ }
+}
+
+/* ********************** custom drawcall api ***************** */
+
+/* type */
+#define REGION_DRAW_PRE 1
+#define REGION_DRAW_POST 0
+
+typedef struct RegionDrawCB {
+ struct RegionDrawCB *next, *prev;
+
+ void (*draw)(const struct bContext *, struct ARegion *, void *);
+ void *customdata;
+
+ int type;
+
+} RegionDrawCB;
+
+void *ED_region_draw_cb_activate(ARegionType *art,
+ void (*draw)(const struct bContext *, struct ARegion *, void *),
+ void *customdata, int type)
+{
+ RegionDrawCB *rdc= MEM_callocN(sizeof(RegionDrawCB), "RegionDrawCB");
+
+ BLI_addtail(&art->drawcalls, rdc);
+ rdc->draw= draw;
+ rdc->customdata= customdata;
+ rdc->type= type;
+
+ return rdc;
+}
+
+void ED_region_draw_cb_exit(ARegionType *art, void *handle)
+{
+ RegionDrawCB *rdc;
+
+ for(rdc= art->drawcalls.first; rdc; rdc= rdc->next) {
+ if(rdc==(RegionDrawCB *)handle) {
+ BLI_remlink(&art->drawcalls, rdc);
+ MEM_freeN(rdc);
+ return;
+ }
+ }
+}
+
+void ED_region_draw_cb_draw(const bContext *C, ARegion *ar, int type)
+{
+ RegionDrawCB *rdc;
+
+ for(rdc= ar->type->drawcalls.first; rdc; rdc= rdc->next) {
+ if(rdc->type==type)
+ rdc->draw(C, ar, rdc->customdata);
+ }
+}
+
+
+
+/* ********************* space template *********************** */
+
+/* allocate and init some vars */
+static SpaceLink *xxx_new(const bContext *C)
+{
+ return NULL;
+}
+
+/* not spacelink itself */
+static void xxx_free(SpaceLink *sl)
+{
+
+}
+
+/* spacetype; init callback for usage, should be redoable */
+static void xxx_init(wmWindowManager *wm, ScrArea *sa)
+{
+
+ /* link area to SpaceXXX struct */
+
+ /* define how many regions, the order and types */
+
+ /* add types to regions */
+}
+
+static SpaceLink *xxx_duplicate(SpaceLink *sl)
+{
+
+ return NULL;
+}
+
+static void xxx_operatortypes(void)
+{
+ /* register operator types for this space */
+}
+
+static void xxx_keymap(wmWindowManager *wm)
+{
+ /* add default items to keymap */
+}
+
+/* only called once, from screen/spacetypes.c */
+void ED_spacetype_xxx(void)
+{
+ static SpaceType st;
+
+ st.spaceid= SPACE_VIEW3D;
+
+ st.new= xxx_new;
+ st.free= xxx_free;
+ st.init= xxx_init;
+ st.duplicate= xxx_duplicate;
+ st.operatortypes= xxx_operatortypes;
+ st.keymap= xxx_keymap;
+
+ BKE_spacetype_register(&st);
+}
+
+/* ****************************** end template *********************** */
+
+
+
+
diff --git a/source/blender/editors/space_buttons/Makefile b/source/blender/editors/space_buttons/Makefile
new file mode 100644
index 00000000000..b96d1cc5495
--- /dev/null
+++ b/source/blender/editors/space_buttons/Makefile
@@ -0,0 +1,55 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_buttons
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I../../render/extern/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/space_buttons/SConscript b/source/blender/editors/space_buttons/SConscript
new file mode 100644
index 00000000000..541da52f7f9
--- /dev/null
+++ b/source/blender/editors/space_buttons/SConscript
@@ -0,0 +1,18 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' ../../makesrna ../../render/extern/include'
+
+defs = []
+
+if env['WITH_BF_GAMEENGINE']:
+ defs.append('GAMEBLENDER=1')
+
+ if env['WITH_BF_SOLID']:
+ defs.append('USE_SUMO_SOLID')
+
+env.BlenderLib ( 'bf_editors_space_buttons', sources, Split(incs), defs, libtype=['core'], priority=[120] )
diff --git a/source/blender/editors/space_buttons/buttons_header.c b/source/blender/editors/space_buttons/buttons_header.c
new file mode 100644
index 00000000000..9bec60fcc75
--- /dev/null
+++ b/source/blender/editors/space_buttons/buttons_header.c
@@ -0,0 +1,221 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "buttons_intern.h"
+
+
+/* ************************ header area region *********************** */
+
+static void do_viewmenu(bContext *C, void *arg, int event)
+{
+ SpaceButs *sbuts= (SpaceButs*)CTX_wm_space_data(C);
+ ScrArea *sa= CTX_wm_area(C);
+
+ switch(event) {
+ case 0: /* panel alignment */
+ case 1:
+ case 2:
+ sbuts->align= event;
+ if(sbuts->align)
+ sbuts->re_align= 1;
+ break;
+ }
+
+ ED_area_tag_redraw(sa);
+}
+
+static uiBlock *dummy_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ SpaceButs *sbuts= (SpaceButs*)CTX_wm_space_data(C);
+ ScrArea *sa= CTX_wm_area(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "dummy_viewmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_viewmenu, NULL);
+
+ if (sbuts->align == 1) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Horizontal", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Horizontal", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+
+ if (sbuts->align == 2) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Vertical", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Vertical", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ if (sbuts->align == 0) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Free", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Free", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ if(sa->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+#define B_CONTEXT_SWITCH 101
+#define B_BUTSPREVIEW 102
+#define B_NEWFRAME 103
+
+static void do_buttons_buttons(bContext *C, void *arg, int event)
+{
+ switch(event) {
+ case B_NEWFRAME:
+ WM_event_add_notifier(C, NC_SCENE|ND_FRAME, NULL);
+ break;
+ case B_CONTEXT_SWITCH:
+ ED_area_tag_redraw(CTX_wm_area(C));
+ break;
+ }
+}
+
+
+void buttons_header_buttons(const bContext *C, ARegion *ar)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceButs *sbuts= (SpaceButs*)CTX_wm_space_data(C);
+ uiBlock *block;
+ int xco, yco= 3;
+
+ block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_buttons_buttons, NULL);
+
+ xco= ED_area_header_standardbuttons(C, block, yco);
+
+ if((sa->flag & HEADER_NO_PULLDOWN)==0) {
+ int xmax;
+
+ xmax= GetButStringLength("View");
+ uiDefPulldownBut(block, dummy_viewmenu, CTX_wm_area(C),
+ "View", xco, yco, xmax-3, 20, "");
+
+ xco+=XIC+xmax;
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ uiBlockBeginAlign(block);
+ uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_GAME, xco, yco, XIC, YIC, &(sbuts->mainb), 0.0, (float)CONTEXT_LOGIC, 0, 0, "Logic (F4) ");
+ uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_SCRIPT, xco+=XIC, yco, XIC, YIC, &(sbuts->mainb), 0.0, (float)CONTEXT_SCRIPT, 0, 0, "Script ");
+ uiDefIconButS(block, ROW, B_BUTSPREVIEW, ICON_MATERIAL_DATA,xco+=XIC, yco, XIC, YIC, &(sbuts->mainb), 0.0, (float)CONTEXT_SHADING, 0, 0, "Shading (F5) ");
+ uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_OBJECT_DATA, xco+=XIC, yco, XIC, YIC, &(sbuts->mainb), 0.0, (float)CONTEXT_OBJECT, 0, 0, "Object (F7) ");
+ uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_EDIT, xco+=XIC, yco, XIC, YIC, &(sbuts->mainb), 0.0, (float)CONTEXT_EDITING, 0, 0, "Editing (F9) ");
+ uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_SCENE_DATA, xco+=XIC, yco, XIC, YIC, &(sbuts->mainb), 0.0, (float)CONTEXT_SCENE, 0, 0, "Scene (F10) ");
+
+ xco+= XIC;
+
+ /* select the context to be drawn, per contex/tab the actual context is tested */
+ uiBlockSetEmboss(block, UI_EMBOSS); // normal
+ switch(sbuts->mainb) {
+ case CONTEXT_SCENE:
+ uiBlockBeginAlign(block);
+ uiDefIconButC(block, ROW, B_CONTEXT_SWITCH, ICON_SCENE, xco+=XIC, yco, XIC, YIC, &(sbuts->tab[CONTEXT_SCENE]), 1.0, (float)TAB_SCENE_RENDER, 0, 0, "Render buttons ");
+ uiDefIconButC(block, ROW, B_CONTEXT_SWITCH, ICON_SEQUENCE, xco+=XIC, yco, XIC, YIC, &(sbuts->tab[CONTEXT_SCENE]), 1.0, (float)TAB_SCENE_SEQUENCER, 0, 0, "Sequencer buttons ");
+ uiDefIconButC(block, ROW, B_CONTEXT_SWITCH, ICON_ANIM, xco+=XIC, yco, XIC, YIC, &(sbuts->tab[CONTEXT_SCENE]), 1.0, (float)TAB_SCENE_ANIM, 0, 0, "Anim/playback buttons");
+ uiDefIconButC(block, ROW, B_CONTEXT_SWITCH, ICON_SOUND, xco+=XIC, yco, XIC, YIC, &(sbuts->tab[CONTEXT_SCENE]), 1.0, (float)TAB_SCENE_SOUND, 0, 0, "Sound block buttons");
+
+ break;
+ case CONTEXT_OBJECT:
+ uiBlockBeginAlign(block);
+ uiDefIconButC(block, ROW, B_CONTEXT_SWITCH, ICON_OBJECT_DATA, xco+=XIC, yco, XIC, YIC, &(sbuts->tab[CONTEXT_OBJECT]), 1.0, (float)TAB_OBJECT_OBJECT, 0, 0, "Object buttons ");
+ uiDefIconButC(block, ROW, B_CONTEXT_SWITCH, ICON_PHYSICS, xco+=XIC, yco, XIC, YIC, &(sbuts->tab[CONTEXT_OBJECT]), 1.0, (float)TAB_OBJECT_PHYSICS, 0, 0, "Physics buttons");
+ uiDefIconButC(block, ROW, B_CONTEXT_SWITCH, ICON_PARTICLES, xco+=XIC, yco, XIC, YIC, &(sbuts->tab[CONTEXT_OBJECT]), 1.0, (float)TAB_OBJECT_PARTICLE, 0, 0, "Particle buttons");
+
+ break;
+ case CONTEXT_SHADING:
+ uiBlockBeginAlign(block);
+ uiDefIconButC(block, ROW, B_BUTSPREVIEW, ICON_LAMP, xco+=XIC, yco, XIC, YIC, &(sbuts->tab[CONTEXT_SHADING]), 1.0, (float)TAB_SHADING_LAMP, 0, 0, "Lamp buttons");
+ uiDefIconButC(block, ROW, B_BUTSPREVIEW, ICON_MATERIAL, xco+=XIC, yco, XIC, YIC, &(sbuts->tab[CONTEXT_SHADING]), 1.0, (float)TAB_SHADING_MAT, 0, 0, "Material buttons");
+ uiDefIconButC(block, ROW, B_BUTSPREVIEW, ICON_TEXTURE, xco+=XIC, yco, XIC, YIC, &(sbuts->tab[CONTEXT_SHADING]), 1.0, (float)TAB_SHADING_TEX, 0, 0, "Texture buttons(F6)");
+ uiDefIconButC(block, ROW, B_CONTEXT_SWITCH, ICON_RADIO,xco+=XIC, yco, XIC, YIC, &(sbuts->tab[CONTEXT_SHADING]), 1.0, (float)TAB_SHADING_RAD, 0, 0, "Radiosity buttons");
+ uiDefIconButC(block, ROW, B_BUTSPREVIEW, ICON_WORLD, xco+=XIC, yco, XIC, YIC, &(sbuts->tab[CONTEXT_SHADING]), 1.0, (float)TAB_SHADING_WORLD, 0, 0, "World buttons");
+
+ break;
+ case CONTEXT_EDITING:
+
+ break;
+ case CONTEXT_SCRIPT:
+
+ break;
+ case CONTEXT_LOGIC:
+
+ break;
+ }
+
+ uiBlockEndAlign(block);
+
+ xco+=XIC;
+ uiDefButI(block, NUM, B_NEWFRAME, "", (xco+20),yco,60,YIC, &(CTX_data_scene(C)->r.cfra), 1.0, MAXFRAMEF, 0, 0, "Displays Current Frame of animation. Click to change.");
+ xco+= 80;
+
+// XXX buttons_active_id(&id, &idfrom);
+// sbuts->lockpoin= id;
+
+
+
+ /* always as last */
+ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+}
+
+
diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h
new file mode 100644
index 00000000000..50b4f7ba5eb
--- /dev/null
+++ b/source/blender/editors/space_buttons/buttons_intern.h
@@ -0,0 +1,85 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_BUTTONS_INTERN_H
+#define ED_BUTTONS_INTERN_H
+
+struct ARegion;
+struct ARegionType;
+struct bContext;
+
+/* warning: the values of these defines are used in sbuts->tabs[7] */
+/* buts->mainb new */
+#define CONTEXT_SCENE 0
+#define CONTEXT_OBJECT 1
+#define CONTEXT_TYPES 2
+#define CONTEXT_SHADING 3
+#define CONTEXT_EDITING 4
+#define CONTEXT_SCRIPT 5
+#define CONTEXT_LOGIC 6
+
+/* buts->tab new */
+#define TAB_SHADING_MAT 0
+#define TAB_SHADING_TEX 1
+#define TAB_SHADING_RAD 2
+#define TAB_SHADING_WORLD 3
+#define TAB_SHADING_LAMP 4
+
+#define TAB_OBJECT_OBJECT 0
+#define TAB_OBJECT_PHYSICS 1
+#define TAB_OBJECT_PARTICLE 2
+
+#define TAB_SCENE_RENDER 0
+#define TAB_SCENE_WORLD 1
+#define TAB_SCENE_ANIM 2
+#define TAB_SCENE_SOUND 3
+#define TAB_SCENE_SEQUENCER 4
+
+
+/* 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
+#define BUTS_SENS_STATE 512
+#define BUTS_ACT_STATE 1024
+
+
+/* internal exports only */
+
+/* image_header.c */
+void buttons_header_buttons(const struct bContext *C, struct ARegion *ar);
+void buttons_scene_register(struct ARegionType *art);
+void buttons_object_register(struct ARegionType *art);
+
+#endif /* ED_BUTTONS_INTERN_H */
+
diff --git a/source/blender/editors/space_buttons/buttons_object.c b/source/blender/editors/space_buttons/buttons_object.c
new file mode 100644
index 00000000000..03fd8d7768a
--- /dev/null
+++ b/source/blender/editors/space_buttons/buttons_object.c
@@ -0,0 +1,218 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_group_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BLI_listbase.h"
+
+#include "BKE_context.h"
+#include "BKE_group.h"
+#include "BKE_main.h"
+#include "BKE_screen.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "RNA_access.h"
+
+#include "WM_types.h"
+
+#if 0
+static void object_panel_transform(const bContext *C, Panel *pnl)
+{
+ uiLayout *layout= pnl->layout;
+ Object *ob= CTX_data_active_object(C);
+ PointerRNA obptr;
+
+ RNA_id_pointer_create(&ob->id, &obptr);
+
+ uiTemplateColumnFlow(layout, 3);
+ uiItemR(layout, NULL, 0, &obptr, "location");
+ uiItemR(layout, NULL, 0, &obptr, "rotation");
+ uiItemR(layout, NULL, 0, &obptr, "scale");
+}
+
+static void object_panel_groups(const bContext *C, Panel *pnl)
+{
+ uiLayout *layout= pnl->layout;
+ Main *bmain= CTX_data_main(C);
+ Object *ob= CTX_data_active_object(C);
+ Group *group;
+ PointerRNA obptr, groupptr;
+ uiLayout *sublayout;
+
+ RNA_id_pointer_create(&ob->id, &obptr);
+
+ uiTemplateColumnFlow(layout, 2);
+ uiItemR(layout, NULL, 0, &obptr, "pass_index");
+ uiItemR(layout, NULL, 0, &obptr, "parent");
+
+ /* uiTemplateLeftRight(layout);
+ uiItemO(layout, NULL, 0, "OBJECT_OT_add_group"); */
+
+ for(group=bmain->group.first; group; group=group->id.next) {
+ if(object_in_group(ob, group)) {
+ RNA_id_pointer_create(&group->id, &groupptr);
+
+ sublayout= uiTemplateStack(layout);
+
+ uiTemplateLeftRight(sublayout);
+ uiTemplateSlot(sublayout, UI_TSLOT_LR_LEFT);
+ uiItemR(sublayout, NULL, 0, &groupptr, "name");
+ // uiTemplateSlot(sublayout, UI_TSLOT_RIGHT);
+ // uiItemO(sublayout, "", ICON_X, "OBJECT_OT_remove_group");
+
+ uiTemplateColumnFlow(sublayout, 2);
+ uiItemR(sublayout, NULL, 0, &groupptr, "layer");
+ uiItemR(sublayout, NULL, 0, &groupptr, "dupli_offset");
+ }
+ }
+}
+
+static void object_panel_display(const bContext *C, Panel *pnl)
+{
+ uiLayout *layout= pnl->layout;
+ Object *ob= CTX_data_active_object(C);
+ PointerRNA obptr;
+
+ RNA_id_pointer_create(&ob->id, &obptr);
+
+ uiTemplateColumnFlow(layout, 2);
+ uiItemR(layout, "Type", 0, &obptr, "max_draw_type");
+ uiItemR(layout, "Bounds", 0, &obptr, "draw_bounds_type");
+
+ uiTemplateColumnFlow(layout , 2);
+ uiItemR(layout, "Name", 0, &obptr, "draw_name");
+ uiItemR(layout, "Axis", 0, &obptr, "draw_axis");
+ uiItemR(layout, "Wire", 0, &obptr, "draw_wire");
+ uiItemR(layout, "Texture Space", 0, &obptr, "draw_texture_space");
+ uiItemR(layout, "X-Ray", 0, &obptr, "x_ray");
+ uiItemR(layout, "Transparency", 0, &obptr, "draw_transparent");
+}
+
+static void object_panel_duplication(const bContext *C, Panel *pnl)
+{
+ uiLayout *layout= pnl->layout;
+ Object *ob= CTX_data_active_object(C);
+ PointerRNA obptr;
+
+ RNA_id_pointer_create(&ob->id, &obptr);
+
+ uiTemplateColumn(layout);
+ uiItemR(layout, "", 0, &obptr, "dupli_type");
+
+ if(RNA_enum_get(&obptr, "dupli_type") == OB_DUPLIFRAMES) {
+ uiTemplateColumnFlow(layout, 2);
+ uiItemR(layout, "Start:", 0, &obptr, "dupli_frames_start");
+ uiItemR(layout, "End:", 0, &obptr, "dupli_frames_end");
+
+ uiItemR(layout, "On:", 0, &obptr, "dupli_frames_on");
+ uiItemR(layout, "Off:", 0, &obptr, "dupli_frames_off");
+ }
+}
+
+static void object_panel_animation(const bContext *C, Panel *pnl)
+{
+ uiLayout *layout= pnl->layout;
+ Object *ob= CTX_data_active_object(C);
+ PointerRNA obptr;
+
+ RNA_id_pointer_create(&ob->id, &obptr);
+
+ uiTemplateColumn(layout);
+ uiTemplateSlot(layout, UI_TSLOT_COLUMN_1);
+ uiItemL(layout, "Time Offset:", 0);
+ uiItemR(layout, "Edit", 0, &obptr, "time_offset_edit");
+ uiItemR(layout, "Particle", 0, &obptr, "time_offset_particle");
+ uiItemR(layout, "Parent", 0, &obptr, "time_offset_parent");
+ uiItemR(layout, NULL, 0, &obptr, "slow_parent");
+ uiItemR(layout, "Offset: ", 0, &obptr, "time_offset");
+ uiTemplateSlot(layout, UI_TSLOT_COLUMN_2);
+ uiItemL(layout, "Tracking:", 0);
+ uiItemR(layout, "Axis: ", 0, &obptr, "track_axis");
+ uiItemR(layout, "Up Axis: ", 0, &obptr, "up_axis");
+ uiItemR(layout, "Rotation", 0, &obptr, "track_rotation");
+}
+#endif
+
+void buttons_object_register(ARegionType *art)
+{
+#if 0
+ PanelType *pt;
+
+ /* panels: transform */
+ pt= MEM_callocN(sizeof(PanelType), "spacetype buttons panel");
+ pt->idname= "OBJECT_PT_transform";
+ pt->name= "Transform";
+ pt->context= "object";
+ pt->draw= object_panel_transform;
+ BLI_addtail(&art->paneltypes, pt);
+
+ /* panels: groups */
+ pt= MEM_callocN(sizeof(PanelType), "spacetype buttons panel");
+ pt->idname= "OBJECT_PT_groups";
+ pt->name= "Groups";
+ pt->context= "object";
+ pt->draw= object_panel_groups;
+ BLI_addtail(&art->paneltypes, pt);
+
+ /* panels: display */
+ pt= MEM_callocN(sizeof(PanelType), "spacetype buttons panel");
+ pt->idname= "OBJECT_PT_display";
+ pt->name= "Display";
+ pt->context= "object";
+ pt->draw= object_panel_display;
+ BLI_addtail(&art->paneltypes, pt);
+
+ /* panels: duplication */
+ pt= MEM_callocN(sizeof(PanelType), "spacetype buttons panel");
+ pt->idname= "OBJECT_PT_duplication";
+ pt->name= "Duplication";
+ pt->context= "object";
+ pt->draw= object_panel_duplication;
+ BLI_addtail(&art->paneltypes, pt);
+
+ /* panels: animation */
+ pt= MEM_callocN(sizeof(PanelType), "spacetype buttons panel");
+ pt->idname= "OBJECT_PT_animation";
+ pt->name= "Animation";
+ pt->context= "object";
+ pt->draw= object_panel_animation;
+ BLI_addtail(&art->paneltypes, pt);
+#endif
+}
+
diff --git a/source/blender/editors/space_buttons/buttons_scene.c b/source/blender/editors/space_buttons/buttons_scene.c
new file mode 100644
index 00000000000..6381998674a
--- /dev/null
+++ b/source/blender/editors/space_buttons/buttons_scene.c
@@ -0,0 +1,469 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "BLI_threads.h"
+#include "BLI_listbase.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_screen.h"
+
+#include "RE_pipeline.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+#include "buttons_intern.h"
+
+#define R_DISPLAYIMAGE 0
+#define R_DISPLAYWIN 1
+#define R_DISPLAYSCREEN 2
+
+#if 0
+#if 0
+static void render_panel_output(const bContext *C, ARegion *ar)
+{
+ uiBlock *block;
+ Scene *scene= CTX_data_scene(C);
+ //ID *id;
+ int a,b;
+ //char *strp;
+
+ block= uiBeginBlock(C, ar, "render_panel_output", UI_EMBOSS);
+ if(uiNewPanel(C, ar, block, "Output", "Render", 0, 0, 318, 204)==0) return;
+
+ uiBlockBeginAlign(block);
+ uiDefIconBut(block, BUT, 0, ICON_FILESEL, 10, 190, 20, 20, 0, 0, 0, 0, 0, "Select the directory/name for saving animations");
+ uiDefBut(block, TEX,0,"", 31, 190, 279, 20,scene->r.pic, 0.0,79.0, 0, 0, "Directory/name to save animations, # characters defines the position and length of frame numbers");
+ uiDefIconBut(block, BUT,0, ICON_FILESEL, 10, 168, 20, 20, 0, 0, 0, 0, 0, "Select the directory/name for a Backbuf image");
+ uiDefBut(block, TEX,0,"", 31, 168, 259, 20,scene->r.backbuf, 0.0,79.0, 0, 0, "Image to use as background for rendering");
+ uiDefIconButBitS(block, ICONTOG, R_BACKBUF, 0, ICON_CHECKBOX_HLT-1, 290, 168, 20, 20, &scene->r.bufflag, 0.0, 0.0, 0, 0, "Enable/Disable use of Backbuf image");
+ uiBlockEndAlign(block);
+
+ uiDefButBitI(block, TOG, R_EXTENSION, 0, "Extensions", 10, 142, 100, 20, &scene->r.scemode, 0.0, 0.0, 0, 0, "Adds filetype extensions to the filename when rendering animations");
+
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOG, R_TOUCH, 0, "Touch", 170, 142, 50, 20, &scene->r.mode, 0.0, 0.0, 0, 0, "Create an empty file before rendering each frame, remove if cancelled (and empty)");
+ uiDefButBitI(block, TOG, R_NO_OVERWRITE, 0, "No Overwrite", 220, 142, 90, 20, &scene->r.mode, 0.0, 0.0, 0, 0, "Skip rendering frames when the file exists (image output only)");
+ uiBlockEndAlign(block);
+
+ /* SET BUTTON */
+ uiBlockBeginAlign(block);
+ /*XXX id= (ID *)scene->set;
+ IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->scene), id, &(G.buts->menunr));
+ if(strp[0])
+ uiDefButS(block, MENU, 0, strp, 10, 114, 20, 20, &(G.buts->menunr), 0, 0, 0, 0, "Scene to link as a Set");
+ MEM_freeN(strp);*/
+
+ if(scene->set) {
+ uiBlockSetButLock(block, 1, NULL);
+ //XXX uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 0, "", 31, 114, 100, 20, &(scene->set), "Name of the Set");
+ uiBlockClearButLock(block);
+ uiDefIconBut(block, BUT, 0, ICON_X, 132, 114, 20, 20, 0, 0, 0, 0, 0, "Remove Set link");
+ } else {
+ uiDefBut(block, LABEL, 0, "No Set Scene", 31, 114, 200, 20, 0, 0, 0, 0, 0, "");
+ }
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefIconButBitI(block, TOGN, R_FIXED_THREADS, 0, ICON_AUTO, 10, 63, 20, 20, &scene->r.mode, 0.0, 0.0, 0, 0, "Automatically set the threads to the number of processors on the system");
+ if ((scene->r.mode & R_FIXED_THREADS)==0) {
+ char thread_str[16];
+ sprintf(thread_str, " Threads: %d", BLI_system_thread_count());
+ uiDefBut(block, LABEL, 0, thread_str, 30, 63,80,20, 0, 0, 0, 0, 0, "");
+ } else {
+ uiDefButS(block, NUM, 0, "Threads:", 30, 63, 80, 20, &scene->r.threads, 1, BLENDER_MAX_THREADS, 0, 0, "Amount of threads for render (takes advantage of multi-core and multi-processor computers)");
+ }
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ for(b=2; b>=0; b--)
+ for(a=0; a<3; a++)
+ uiDefButBitS(block, TOG, 1<<(3*b+a), 800,"", (short)(10+18*a),(short)(10+14*b),16,12, &G.winpos, 0, 0, 0, 0, "Render window placement on screen");
+ uiBlockEndAlign(block);
+
+#ifdef WITH_OPENEXR
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOG, R_EXR_TILE_FILE, 0, "Save Buffers", 72, 31, 120, 19, &scene->r.scemode, 0.0, 0.0, 0, 0, "Save tiles for all RenderLayers and used SceneNodes to files in the temp directory (saves memory, allows Full Sampling)");
+ if(scene->r.scemode & R_EXR_TILE_FILE)
+ uiDefButBitI(block, TOG, R_FULL_SAMPLE, 0, "FullSample", 192, 31, 118, 19, &scene->r.scemode, 0.0, 0.0, 0, 0, "Saves for every OSA sample the entire RenderLayer results (Higher quality sampling but slower)");
+ uiBlockEndAlign(block);
+#endif
+
+ uiDefButS(block, MENU, 0, "Render Display %t|Render Window %x1|Image Editor %x0|Full Screen %x2",
+ 72, 10, 120, 19, &G.displaymode, 0.0, (float)R_DISPLAYWIN, 0, 0, "Sets render output display");
+
+ /* Dither control */
+ uiDefButF(block, NUM,0, "Dither:", 10,89,100,19, &scene->r.dither_intensity, 0.0, 2.0, 0, 0, "The amount of dithering noise present in the output image (0.0 = no dithering)");
+
+ /* Toon shading buttons */
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOG, R_EDGE, 0,"Edge", 115, 89, 60, 20, &scene->r.mode, 0, 0, 0, 0, "Enable Toon Edge-enhance");
+ //XXX uiDefBlockBut(block, edge_render_menu, NULL, "Edge Settings", 175, 89, 135, 20, "Display Edge settings");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOG, R_NO_TEX, 0, "Disable Tex", 115, 63, 75, 20, &scene->r.scemode, 0.0, 0.0, 0, 0, "Disables Textures for render");
+ uiDefButBitI(block, TOG, R_FREE_IMAGE, 0, "Free Tex Images", 210, 63, 100, 20, &scene->r.scemode, 0.0, 0.0, 0, 0, "Frees all Images used by Textures after each render");
+ uiBlockEndAlign(block);
+
+ uiEndBlock(C, block);
+}
+#endif
+
+#if 0
+static void do_bake_func(bContext *C, void *unused_v, void *unused_p)
+{
+ //XXX objects_bake_render_ui(0);
+}
+
+static void render_panel_bake(const bContext *C, ARegion *ar)
+{
+ uiBlock *block;
+ Scene *scene= CTX_data_scene(C);
+ uiBut *but;
+
+ block= uiBeginBlock(C, ar, "render_panel_bake", UI_EMBOSS);
+ uiNewPanelTabbed("Anim", "Render");
+ if(uiNewPanel(C, ar, block, "Bake", "Render", 320, 0, 318, 204)==0) return;
+
+ but= uiDefBut(block, BUT, 0, "BAKE", 10, 150, 190,40, 0, 0, 0, 0, 0, "Start the bake render for selected Objects");
+ uiButSetFunc(but, do_bake_func, NULL, NULL);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, R_BAKE_TO_ACTIVE, 0, "Selected to Active", 10,120,190,20,&scene->r.bake_flag, 0.0, 0, 0, 0, "Bake shading on the surface of selected objects to the active object");
+ uiDefButF(block, NUM, 0, "Dist:", 10,100,95,20,&scene->r.bake_maxdist, 0.0, 1000.0, 1, 0, "Maximum distance from active object to other object (in blender units)");
+ uiDefButF(block, NUM, 0, "Bias:", 105,100,95,20,&scene->r.bake_biasdist, 0.0, 1000.0, 1, 0, "Bias towards faces further away from the object (in blender units)");
+ uiBlockEndAlign(block);
+
+ if(scene->r.bake_mode == RE_BAKE_NORMALS)
+ uiDefButS(block, MENU, 0, "Normal Space %t|Camera %x0|World %x1|Object %x2|Tangent %x3",
+ 10,70,190,20, &scene->r.bake_normal_space, 0, 0, 0, 0, "Choose normal space for baking");
+ else if(scene->r.bake_mode == RE_BAKE_AO || scene->r.bake_mode == RE_BAKE_DISPLACEMENT) {
+ uiDefButBitS(block, TOG, R_BAKE_NORMALIZE, 0, "Normalized", 10,70,190,20, &scene->r.bake_flag, 0.0, 0, 0, 0,
+ scene->r.bake_mode == RE_BAKE_AO ?
+ "Bake ambient occlusion normalized, without taking into acount material settings":
+ "Normalized displacement value to fit the 'Dist' range"
+ );
+ }
+
+ uiDefButS(block, MENU, 0, "Quad Split Order%t|Quad Split Auto%x0|Quad Split A (0,1,2) (0,2,3)%x1|Quad Split B (1,2,3) (1,3,0)%x2",
+ 10,10,190,20, &scene->r.bake_quad_split, 0, 0, 0, 0, "Method to divide quads (use A or B for external applications that use a fixed order)");
+
+#if 0
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, R_BAKE_OSA, 0, "OSA", 10,120,190,20, &scene->r.bake_flag, 0, 0, 0, 0, "Enables Oversampling (Anti-aliasing)");
+ uiDefButS(block, ROW,0,"5", 10,100,50,20,&scene->r.bake_osa,2.0,5.0, 0, 0, "Sets oversample level to 5");
+ uiDefButS(block, ROW,0,"8", 60,100,45,20,&scene->r.bake_osa,2.0,8.0, 0, 0, "Sets oversample level to 8");
+ uiDefButS(block, ROW,0,"11", 105,100,45,20,&scene->r.bake_osa,2.0,11.0, 0, 0, "Sets oversample level to 11");
+ uiDefButS(block, ROW,0,"16", 150,100,50,20,&scene->r.bake_osa,2.0,16.0, 0, 0, "Sets oversample level to 16");
+#endif
+ uiBlockBeginAlign(block);
+ uiDefButS(block, ROW,0,"Full Render", 210,170,120,20,&scene->r.bake_mode, 1.0, RE_BAKE_ALL, 0, 0, "");
+ uiDefButS(block, ROW,0,"Ambient Occlusion",210,150,120,20,&scene->r.bake_mode, 1.0, RE_BAKE_AO, 0, 0, "");
+ uiDefButS(block, ROW,0,"Shadow", 210,130,120,20,&scene->r.bake_mode, 1.0, RE_BAKE_SHADOW, 0, 0, "");
+ uiDefButS(block, ROW,0,"Normals", 210,110,120,20,&scene->r.bake_mode, 1.0, RE_BAKE_NORMALS, 0, 0, "");
+ uiDefButS(block, ROW,0,"Textures", 210,90,120,20,&scene->r.bake_mode, 1.0, RE_BAKE_TEXTURE, 0, 0, "");
+ uiDefButS(block, ROW,0,"Displacement", 210,70,120,20,&scene->r.bake_mode, 1.0, RE_BAKE_DISPLACEMENT, 0, 0, "");
+ uiBlockEndAlign(block);
+
+ uiDefButBitS(block, TOG, R_BAKE_CLEAR, 0, "Clear", 210,40,120,20,&scene->r.bake_flag, 0.0, 0, 0, 0, "Clear Images before baking");
+
+ uiDefButS(block, NUM, 0,"Margin:", 210,10,120,20,&scene->r.bake_filter, 0.0, 32.0, 0, 0, "Amount of pixels to extend the baked result with, as post process filter");
+
+ uiEndBlock(C, block);
+}
+#endif
+
+static void render_panel_shading(const bContext *C, Panel *pnl)
+{
+ uiLayout *layout= pnl->layout;
+ Scene *scene= CTX_data_scene(C);
+ PointerRNA sceneptr, renderptr;
+
+ RNA_id_pointer_create(&scene->id, &sceneptr);
+ renderptr = RNA_pointer_get(&sceneptr, "render_data");
+
+ uiTemplateColumnFlow(layout, 2);
+ uiItemR(layout, "Shadow", 0, &renderptr, "render_shadows");
+ uiItemR(layout, "SSS", 0, &renderptr, "render_sss");
+ uiItemR(layout, "EnvMap", 0, &renderptr, "render_envmaps");
+ uiItemR(layout, "Radio", 0, &renderptr, "render_radiosity");
+ uiItemR(layout, "Ray Tracing", 0, &renderptr, "render_raytracing");
+ uiItemR(layout, NULL, 0, &renderptr, "octree_resolution");
+
+ uiTemplateColumn(layout);
+ uiItemR(layout, NULL, 0, &renderptr, "alpha_mode");
+
+}
+static void render_panel_image(const bContext *C, Panel *pnl)
+{
+ uiLayout *layout= pnl->layout;
+ Scene *scene= CTX_data_scene(C);
+ PointerRNA sceneptr, renderptr;
+
+ RNA_id_pointer_create(&scene->id, &sceneptr);
+ renderptr = RNA_pointer_get(&sceneptr, "render_data");
+
+ uiTemplateColumnFlow(layout, 2);
+ uiItemR(layout, "SizeX", 0, &renderptr, "resolution_x");
+ uiItemR(layout, "SizeY", 0, &renderptr, "resolution_y");
+ uiItemR(layout, "AspX", 0, &renderptr, "pixel_aspect_x");
+ uiItemR(layout, "AspY", 0, &renderptr, "pixel_aspect_y");
+
+ uiTemplateColumn(layout);
+ uiItemR(layout, NULL, 0, &renderptr, "crop_to_border");
+
+}
+static void render_panel_antialiasing(const bContext *C, Panel *pnl)
+{
+ uiLayout *layout= pnl->layout;
+ Scene *scene= CTX_data_scene(C);
+ PointerRNA sceneptr, renderptr;
+
+ RNA_id_pointer_create(&scene->id, &sceneptr);
+ renderptr = RNA_pointer_get(&sceneptr, "render_data");
+
+ uiTemplateColumnFlow(layout, 2);
+ uiItemR(layout, "Enable", 0, &renderptr, "antialiasing");
+ uiItemR(layout, "Samples", 0, &renderptr, "antialiasing_samples");
+ uiItemR(layout, NULL, 0, &renderptr, "pixel_filter");
+ uiItemR(layout, NULL, 0, &renderptr, "filter_size");
+
+}
+
+static void render_panel_render(const bContext *C, Panel *pnl)
+{
+ uiLayout *layout= pnl->layout;
+ Scene *scene= CTX_data_scene(C);
+ PointerRNA sceneptr, renderptr;
+
+ RNA_id_pointer_create(&scene->id, &sceneptr);
+ renderptr = RNA_pointer_get(&sceneptr, "render_data");
+
+ uiTemplateColumnFlow(layout, 2);
+ uiItemO(layout, "RENDER", ICON_SCENE, "SCREEN_OT_render");
+ uiItemBooleanO(layout, "ANIM", 0, "SCREEN_OT_render", "anim", 1);
+
+ uiTemplateColumnFlow(layout, 3);
+ uiItemR(layout, "Start", 0, &sceneptr, "start_frame");
+ uiItemR(layout, "End", 0, &sceneptr, "end_frame");
+ uiItemR(layout, "Frame", 0, &sceneptr, "current_frame");
+
+ uiTemplateColumnFlow(layout, 2);
+ uiItemR(layout, NULL, 0, &renderptr, "do_composite");
+ uiItemR(layout, NULL, 0, &renderptr, "do_sequence");
+ uiTemplateColumn(layout);
+ uiItemR(layout, "Camera:", 0, &sceneptr, "camera");
+
+ uiTemplateColumn(layout);
+ uiItemL(layout, "General:", 0);
+ uiTemplateColumn(layout);
+ uiItemR(layout, "Size ", 0, &renderptr, "resolution_percentage");
+ uiItemR(layout, NULL, 0, &renderptr, "dither_intensity");
+
+ uiTemplateColumnFlow(layout, 2);
+ uiItemR(layout, NULL, 0, &renderptr, "parts_x");
+ uiItemR(layout, NULL, 0, &renderptr, "parts_y");
+
+ uiTemplateColumnFlow(layout, 2);
+ uiItemR(layout, NULL, 0, &renderptr, "threads");
+ uiItemR(layout, "", 0, &renderptr, "threads_mode");
+
+ uiTemplateColumnFlow(layout, 3);
+ uiItemR(layout, "Fields", 0, &renderptr, "fields");
+ uiItemR(layout, "Order", 0, &renderptr, "field_order");
+ uiItemR(layout, "Still", 0, &renderptr, "fields_still");
+
+ uiTemplateColumn(layout);
+ uiItemL(layout, "Extra:", 0);
+ uiTemplateColumnFlow(layout, 2);
+ uiItemR(layout, "Border Render", 0, &renderptr, "border");
+ uiItemR(layout, NULL, 0, &renderptr, "panorama");
+
+
+#if 0
+ block= uiBeginBlock(C, ar, "render_panel_render", UI_EMBOSS);
+ if(uiNewPanel(C, ar, block, "Render", "Render", 320, 0, 318, 204)==0) return;
+
+ uiBlockBeginAlign(block);
+ uiDefButO(block, BUT, "SCREEN_OT_render", WM_OP_INVOKE_DEFAULT, "RENDER", 369, 164, 191,37, "Render the current frame (F12)");
+
+#ifndef DISABLE_YAFRAY
+ /* yafray: on request, render engine menu is back again, and moved to Render panel */
+ uiDefButS(block, MENU, 0, "Rendering Engine %t|Blender Internal %x0|YafRay %x1",
+ 369, 142, 191, 20, &scene->r.renderer, 0, 0, 0, 0, "Choose rendering engine");
+#else
+ uiDefButS(block, MENU, 0, "Rendering Engine %t|Blender Internal %x0",
+ 369, 142, 191, 20, &scene->r.renderer, 0, 0, 0, 0, "Choose rendering engine");
+#endif /* disable yafray */
+
+ uiBlockBeginAlign(block);
+ if((scene->r.scemode & R_FULL_SAMPLE) && (scene->r.scemode & R_EXR_TILE_FILE))
+ uiDefButBitI(block, TOG, R_OSA, 0, "FSA", 369,109,122,20,&scene->r.mode, 0, 0, 0, 0, "Saves all samples, then composites, and then merges (for best Anti-aliasing)");
+ else
+ uiDefButBitI(block, TOG, R_OSA, 0, "OSA", 369,109,122,20,&scene->r.mode, 0, 0, 0, 0, "Enables Oversampling (Anti-aliasing)");
+ uiDefButS(block, ROW,0,"5", 369,88,29,20,&scene->r.osa,2.0,5.0, 0, 0, "Render 5 samples per pixel for smooth edges (Fast)");
+ uiDefButS(block, ROW,0,"8", 400,88,29,20,&scene->r.osa,2.0,8.0, 0, 0, "Render 8 samples per pixel for smooth edges (Recommended)");
+ uiDefButS(block, ROW,0,"11", 431,88,29,20,&scene->r.osa,2.0,11.0, 0, 0, "Render 11 samples per pixel for smooth edges (High Quality)");
+ uiDefButS(block, ROW,0,"16", 462,88,29,20,&scene->r.osa,2.0,16.0, 0, 0, "Render 16 samples per pixel for smooth edges (Highest Quality)");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOG, R_MBLUR, 0, "MBLUR", 496,109,64,20,&scene->r.mode, 0, 0, 0, 0, "Enables Motion Blur calculation");
+ uiDefButF(block, NUM,0,"Bf:", 496,88,64,20,&scene->r.blurfac, 0.01, 5.0, 10, 2, "Sets motion blur factor");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButS(block, NUM,0,"Xparts:", 369,46,95,29,&scene->r.xparts,1.0, 512.0, 0, 0, "Sets the number of horizontal parts to render image in (For panorama sets number of camera slices)");
+ uiDefButS(block, NUM,0,"Yparts:", 465,46,95,29,&scene->r.yparts,1.0, 64.0, 0, 0, "Sets the number of vertical parts to render image in");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButS(block, ROW,800,"Sky", 369,13,35,20,&scene->r.alphamode,3.0,0.0, 0, 0, "Fill background with sky");
+ uiDefButS(block, ROW,800,"Premul", 405,13,50,20,&scene->r.alphamode,3.0,1.0, 0, 0, "Multiply alpha in advance");
+ uiDefButS(block, ROW,800,"Key", 456,13,35,20,&scene->r.alphamode,3.0,2.0, 0, 0, "Alpha and color values remain unchanged");
+ uiBlockEndAlign(block);
+
+ uiDefButS(block, MENU, 0,"Octree resolution %t|64 %x64|128 %x128|256 %x256|512 %x512", 496,13,64,20,&scene->r.ocres,0.0,0.0, 0, 0, "Octree resolution for ray tracing and baking, Use higher values for complex scenes");
+
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOG, R_SHADOW, 0,"Shadow", 565,172,52,29, &scene->r.mode, 0, 0, 0, 0, "Enable shadow calculation");
+ uiDefButBitI(block, TOG, R_SSS, 0,"SSS", 617,172,32,29, &scene->r.mode, 0, 0, 0, 0, "Enable subsurface scattering map rendering");
+ uiDefButBitI(block, TOG, R_PANORAMA, 0,"Pano", 649,172,38,29, &scene->r.mode, 0, 0, 0, 0, "Enable panorama rendering (output width is multiplied by Xparts)");
+ uiDefButBitI(block, TOG, R_ENVMAP, 0,"EnvMap", 565,142,52,29, &scene->r.mode, 0, 0, 0, 0, "Enable environment map rendering");
+ uiDefButBitI(block, TOG, R_RAYTRACE, 0,"Ray",617,142,32,29, &scene->r.mode, 0, 0, 0, 0, "Enable ray tracing");
+ uiDefButBitI(block, TOG, R_RADIO, 0,"Radio", 649,142,38,29, &scene->r.mode, 0, 0, 0, 0, "Enable radiosity rendering");
+ uiBlockEndAlign(block);
+
+ uiDefButS(block, NUMSLI, 0, "Size %: ",
+ 565,109,122,20,
+ &(scene->r.size), 1.0, 100.0, 0, 0,
+ "Render at percentage of frame size");
+
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOG, R_FIELDS, 0,"Fields", 565,55,60,20,&scene->r.mode, 0, 0, 0, 0, "Enables field rendering");
+ uiDefButBitI(block, TOG, R_ODDFIELD, 0,"Odd", 627,55,39,20,&scene->r.mode, 0, 0, 0, 0, "Enables Odd field first rendering (Default: Even field)");
+ uiDefButBitI(block, TOG, R_FIELDSTILL, 0,"X", 668,55,19,20,&scene->r.mode, 0, 0, 0, 0, "Disables time difference in field calculations");
+
+ sprintf(str, "Filter%%t|Box %%x%d|Tent %%x%d|Quad %%x%d|Cubic %%x%d|Gauss %%x%d|CatRom %%x%d|Mitch %%x%d", R_FILTER_BOX, R_FILTER_TENT, R_FILTER_QUAD, R_FILTER_CUBIC, R_FILTER_GAUSS, R_FILTER_CATROM, R_FILTER_MITCH);
+ uiDefButS(block, MENU, 0,str, 565,34,60,20, &scene->r.filtertype, 0, 0, 0, 0, "Set sampling filter for antialiasing");
+ uiDefButF(block, NUM,0,"", 627,34,60,20,&scene->r.gauss,0.5, 1.5, 10, 2, "Sets the filter size");
+
+ uiDefButBitI(block, TOG, R_BORDER, 0, "Border", 565,13,122,20, &scene->r.mode, 0, 0, 0, 0, "Render a small cut-out of the image (Shift+B to set in the camera view)");
+ uiBlockEndAlign(block);
+
+ uiEndBlock(C, block);
+#endif
+}
+
+
+void render_panel_anim(const bContext *C, ARegion *ar)
+{
+ Scene *scene= CTX_data_scene(C);
+ uiBlock *block;
+ uiBut *but;
+
+ block= uiBeginBlock(C, ar, "render_panel_anim", UI_EMBOSS);
+ if(uiNewPanel(C, ar, block, "Anim", "Render", 640, 0, 318, 204) == 0) return;
+
+ but= uiDefButO(block, BUT, "SCREEN_OT_render", WM_OP_INVOKE_DEFAULT, "ANIM", 692,142,192,47, "Render the animation to disk from start to end frame, (Ctrl+F12)");
+ RNA_boolean_set(uiButGetOperatorPtrRNA(but), "anim", 1);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOG, R_DOSEQ, 0, "Do Sequence",692,114,192,20, &scene->r.scemode, 0, 0, 0, 0, "Enables sequence output rendering (Default: 3D rendering)");
+ uiDefButBitI(block, TOG, R_DOCOMP, 0, "Do Composite",692,90,192,20, &scene->r.scemode, 0, 0, 0, 0, "Uses compositing nodes for output rendering");
+ uiBlockEndAlign(block);
+
+ uiDefBut(block, BUT, 0, "PLAY",692,50,94,33, 0, 0, 0, 0, 0, "Play rendered images/avi animation (Ctrl+F11), (Play Hotkeys: A-Noskip, P-PingPong)");
+ uiDefButS(block, NUM, 0, "rt:",789,50,95,33, &G.rt, -1000.0, 1000.0, 0, 0, "General testing/debug button");
+
+ uiBlockBeginAlign(block);
+ uiDefButI(block, NUM,0,"Sta:",692,20,94,24, &scene->r.sfra,1.0,MAXFRAMEF, 0, 0, "The start frame of the animation (inclusive)");
+ uiDefButI(block, NUM,0,"End:",789,20,95,24, &scene->r.efra,SFRA,MAXFRAMEF, 0, 0, "The end frame of the animation (inclusive)");
+ uiDefButI(block, NUM,0,"Step:",692,0,192,18, &scene->frame_step, 1.0, MAXFRAMEF, 0, 0, "Frame Step");
+ uiBlockEndAlign(block);
+
+ uiEndBlock(C, block);
+}
+#endif
+
+void buttons_scene_register(ARegionType *art)
+{
+#if 0
+ PanelType *pt;
+
+ /* panels: Render */
+ pt= MEM_callocN(sizeof(PanelType), "spacetype buttons panel");
+ pt->idname= "RENDER_PT_render";
+ pt->name= "Render";
+ pt->context= "render";
+ pt->draw= render_panel_render;
+ BLI_addtail(&art->paneltypes, pt);
+
+ /* panels: Shading */
+ pt= MEM_callocN(sizeof(PanelType), "spacetype buttons panel");
+ pt->idname= "RENDER_PT_image";
+ pt->name= "Image";
+ pt->context= "render";
+ pt->draw= render_panel_image;
+ BLI_addtail(&art->paneltypes, pt);
+
+ /* panels: AntiAliasing */
+ pt= MEM_callocN(sizeof(PanelType), "spacetype buttons panel");
+ pt->idname= "RENDER_PT_antialias";
+ pt->name= "AntiAliasing";
+ pt->context= "render";
+ pt->draw= render_panel_antialiasing;
+ BLI_addtail(&art->paneltypes, pt);
+
+ /* panels: Shading */
+ pt= MEM_callocN(sizeof(PanelType), "spacetype buttons panel");
+ pt->idname= "RENDER_PT_shading";
+ pt->name= "Shading";
+ pt->context= "render";
+ pt->draw= render_panel_shading;
+ BLI_addtail(&art->paneltypes, pt);
+#endif
+}
+
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
new file mode 100644
index 00000000000..018b328836a
--- /dev/null
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -0,0 +1,313 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_previewrender.h"
+
+#include "buttons_intern.h" // own include
+
+/* ******************** default callbacks for buttons space ***************** */
+
+static SpaceLink *buttons_new(const bContext *C)
+{
+ ARegion *ar;
+ SpaceButs *sbuts;
+
+ sbuts= MEM_callocN(sizeof(SpaceButs), "initbuts");
+ sbuts->spacetype= SPACE_BUTS;
+ sbuts->scaflag= BUTS_SENS_LINK|BUTS_SENS_ACT|BUTS_CONT_ACT|BUTS_ACT_ACT|BUTS_ACT_LINK;
+ sbuts->align= BUT_AUTO;
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for buts");
+
+ BLI_addtail(&sbuts->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_BOTTOM;
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for buts");
+
+ BLI_addtail(&sbuts->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+
+#if 0 // disabled, as this currently draws badly in new system
+ /* buts space goes from (0,0) to (1280, 228) */
+ ar->v2d.tot.xmin= 0.0f;
+ ar->v2d.tot.ymin= 0.0f;
+ ar->v2d.tot.xmax= 1279.0f;
+ ar->v2d.tot.ymax= 228.0f;
+
+ ar->v2d.cur= sbuts->v2d.tot;
+
+ ar->v2d.min[0]= 256.0f;
+ ar->v2d.min[1]= 42.0f;
+
+ ar->v2d.max[0]= 2048.0f;
+ ar->v2d.max[1]= 450.0f;
+
+ ar->v2d.minzoom= 0.5f;
+ ar->v2d.maxzoom= 1.21f;
+
+ ar->v2d.scroll= 0; // TODO: will we need scrollbars?
+ ar->v2d.align= V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_NEG_Y;
+ ar->v2d.keepzoom= V2D_KEEPZOOM|V2D_KEEPASPECT;
+ ar->v2d.keeptot= V2D_KEEPTOT_BOUNDS;
+#endif
+
+
+ return (SpaceLink *)sbuts;
+}
+
+/* not spacelink itself */
+static void buttons_free(SpaceLink *sl)
+{
+ SpaceButs *sbuts= (SpaceButs*) sl;
+
+ if(sbuts->ri) {
+ if (sbuts->ri->rect) MEM_freeN(sbuts->ri->rect);
+ MEM_freeN(sbuts->ri);
+ }
+
+}
+
+
+/* spacetype; init callback */
+static void buttons_init(struct wmWindowManager *wm, ScrArea *sa)
+{
+ SpaceButs *sbuts= sa->spacedata.first;
+
+ /* auto-align based on size */
+ if(sbuts->align == BUT_AUTO) {
+ if(sa->winx > sa->winy)
+ sbuts->align= BUT_HORIZONTAL;
+ else
+ sbuts->align= BUT_VERTICAL;
+ }
+}
+
+static SpaceLink *buttons_duplicate(SpaceLink *sl)
+{
+ SpaceButs *sbutsn= MEM_dupallocN(sl);
+
+ /* clear or remove stuff from old */
+ sbutsn->ri= NULL;
+
+ return (SpaceLink *)sbutsn;
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void buttons_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+// ar->v2d.minzoom= ar->v2d.maxzoom= 1.0f;
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "Buttons", SPACE_BUTS, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+static void buttons_main_area_draw(const bContext *C, ARegion *ar)
+{
+ /* draw entirely, view changes should be handled here */
+ SpaceButs *sbuts= (SpaceButs*)CTX_wm_space_data(C);
+ int vertical= (sbuts->align == BUT_VERTICAL);
+ int tab= sbuts->tab[sbuts->mainb];
+
+ if(sbuts->mainb == CONTEXT_OBJECT) {
+ if(tab == TAB_OBJECT_OBJECT)
+ uiRegionPanelLayout(C, ar, vertical, "object");
+ }
+ else if (sbuts->mainb == CONTEXT_SCENE){
+ if(tab == TAB_SCENE_RENDER)
+ uiRegionPanelLayout(C, ar, vertical, "render");
+ }
+ else {
+ View2D *v2d= &ar->v2d;
+ float col[3], fac;
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ UI_view2d_view_ortho(C, v2d);
+
+ /* swapbuffers indicator */
+ fac= BLI_frand();
+ glColor3f(fac, fac, fac);
+ glRecti(20, v2d->cur.ymin+2, 30, v2d->cur.ymin+12);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers? */
+ }
+
+ sbuts->re_align= 0;
+ sbuts->mainbo= sbuts->mainb;
+ sbuts->tabo= sbuts->tab[sbuts->mainb];
+}
+
+void buttons_operatortypes(void)
+{
+
+}
+
+void buttons_keymap(struct wmWindowManager *wm)
+{
+
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void buttons_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+}
+
+static void buttons_header_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ /* clear */
+ if(ED_screen_area_active(C))
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ else
+ UI_GetThemeColor3fv(TH_HEADERDESEL, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ buttons_header_buttons(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+/* reused! */
+static void buttons_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ switch(wmn->data) {
+ case ND_FRAME:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ }
+}
+
+/* only called once, from space/spacetypes.c */
+void ED_spacetype_buttons(void)
+{
+ SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype buttons");
+ ARegionType *art;
+
+ st->spaceid= SPACE_BUTS;
+
+ st->new= buttons_new;
+ st->free= buttons_free;
+ st->init= buttons_init;
+ st->duplicate= buttons_duplicate;
+ st->operatortypes= buttons_operatortypes;
+ st->keymap= buttons_keymap;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype buttons region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init= buttons_main_area_init;
+ art->draw= buttons_main_area_draw;
+ art->listener= buttons_area_listener;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
+
+ buttons_object_register(art);
+ buttons_scene_register(art);
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype buttons region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
+
+ art->init= buttons_header_area_init;
+ art->draw= buttons_header_area_draw;
+ art->listener= buttons_area_listener;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: channels */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype buttons region");
+ art->regionid = RGN_TYPE_CHANNELS;
+ art->minsizex= 80;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+
+// art->init= buttons_channel_area_init;
+// art->draw= buttons_channel_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
+}
+
diff --git a/source/blender/editors/space_file/Makefile b/source/blender/editors/space_file/Makefile
new file mode 100644
index 00000000000..480a4ee3889
--- /dev/null
+++ b/source/blender/editors/space_file/Makefile
@@ -0,0 +1,61 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_file
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_BMFONT)/include
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../render/extern/include
+CPPFLAGS += -I../../python
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
+
+ifeq ($(WITH_OPENJPEG),true)
+ CPPFLAGS += -DWITH_OPENJPEG
+endif
+
diff --git a/source/blender/editors/space_file/SConscript b/source/blender/editors/space_file/SConscript
new file mode 100644
index 00000000000..8302d6eecef
--- /dev/null
+++ b/source/blender/editors/space_file/SConscript
@@ -0,0 +1,16 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../blenloader #intern/bmfont ../../makesrna'
+incs += ' ../../render/extern/include '
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+
+defs = []
+
+if env['WITH_BF_OPENJPEG']:
+ defs.append('WITH_OPENJPEG')
+
+env.BlenderLib ( 'bf_editors_space_file', sources, Split(incs), defs, libtype=['core'], priority=[115] )
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
new file mode 100644
index 00000000000..6184425885e
--- /dev/null
+++ b/source/blender/editors/space_file/file_draw.c
@@ -0,0 +1,612 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h"
+#include "BLI_storage_types.h"
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+#include "BMF_Api.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "RNA_access.h"
+
+#include "ED_fileselect.h"
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "fsmenu.h"
+#include "filelist.h"
+
+#include "file_intern.h" // own include
+
+/* ui geometry */
+#define IMASEL_BUTTONS_HEIGHT 40
+#define TILE_BORDER_X 8
+#define TILE_BORDER_Y 8
+
+/* button events */
+enum {
+ B_REDR = 0,
+ B_FS_EXEC,
+ B_FS_CANCEL,
+ B_FS_PARENT,
+} eFile_ButEvents;
+
+/* XXX very bad, need to check font code */
+static int gFontsize=12;
+
+static void do_file_buttons(bContext *C, void *arg, int event)
+{
+ switch(event) {
+ case B_FS_EXEC:
+ file_exec(C, NULL); /* file_ops.c */
+ break;
+ case B_FS_CANCEL:
+ file_cancel_exec(C, NULL); /* file_ops.c */
+ break;
+ case B_FS_PARENT:
+ file_parent_exec(C, NULL); /* file_ops.c */
+ break;
+ }
+}
+
+/* note; this function uses pixelspace (0, 0, winx, winy), not view2d */
+void file_draw_buttons(const bContext *C, ARegion *ar)
+{
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+ FileSelectParams* params = ED_fileselect_get_params(sfile);
+ uiBlock *block;
+ int loadbutton;
+ char name[20];
+ float slen;
+ int filebuty1, filebuty2;
+
+ float xmin = 8;
+ float xmax = ar->winx - 10;
+
+ filebuty1= ar->winy - IMASEL_BUTTONS_HEIGHT - 12;
+ filebuty2= filebuty1 + IMASEL_BUTTONS_HEIGHT/2 + 4;
+
+ /* HEADER */
+ sprintf(name, "win %p", ar);
+ block = uiBeginBlock(C, ar, name, UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_file_buttons, NULL);
+
+ /* XXXX
+ uiSetButLock( filelist_gettype(simasel->files)==FILE_MAIN && simasel->returnfunc, NULL);
+ */
+
+ /* space available for load/save buttons? */
+ slen = UI_GetStringWidth(sfile->params->title);
+ loadbutton= slen > 60 ? slen + 20 : MAX2(80, 20+UI_GetStringWidth(params->title));
+ if(ar->winx > loadbutton+20) {
+ if(params->title[0]==0) {
+ loadbutton= 0;
+ }
+ }
+ else {
+ loadbutton= 0;
+ }
+
+ uiDefBut(block, TEX, 0 /* XXX B_FS_FILENAME */,"", xmin+2, filebuty1, xmax-xmin-loadbutton-4, 21, params->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
+ uiDefBut(block, TEX, 0 /* XXX B_FS_DIRNAME */,"", xmin+2, filebuty2, xmax-xmin-loadbutton-4, 21, params->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
+
+ if(loadbutton) {
+ uiDefBut(block, BUT, B_FS_EXEC, params->title, xmax-loadbutton, filebuty2, loadbutton, 21, params->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
+ uiDefBut(block, BUT, B_FS_CANCEL, "Cancel", xmax-loadbutton, filebuty1, loadbutton, 21, params->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
+ }
+
+#if 0
+ /* menu[0] = NULL happens when no .Bfs is there, and first time browse
+ disallow external directory browsing for databrowse */
+
+ if(menu[0] && (params->type != FILE_MAIN)) {
+ uiDefButS(block, MENU, 0 /* B_FS_DIR_MENU */, menu, xmin, filebuty2, fsmenubut_width, 21, &params->menu, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT, 0 /* B_FS_BOOKMARK */, "B", xmin, filebuty1, bookmarkbut_width, 21, 0, 0, 0, 0, 0, "Bookmark current directory");
+ }
+
+ MEM_freeN(menu);
+#endif
+
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+}
+
+
+static void draw_tile(short sx, short sy, short width, short height, int colorid, int shade)
+{
+ /* TODO: BIF_ThemeColor seems to need this to show the color, not sure why? - elubie */
+ //glEnable(GL_BLEND);
+ //glColor4ub(0, 0, 0, 100);
+ //glDisable(GL_BLEND);
+ /* I think it was a missing glDisable() - ton */
+
+ UI_ThemeColorShade(colorid, shade);
+ uiSetRoundBox(15);
+ // glRecti(sx, sy - height, sx + width, sy);
+
+ uiRoundBox(sx, sy - height, sx + width, sy, 6);
+}
+
+#define FILE_SHORTEN_END 0
+#define FILE_SHORTEN_FRONT 1
+
+static float shorten_string(char* string, float w, int flag)
+{
+ char temp[FILE_MAX];
+ short shortened = 0;
+ float sw = 0;
+ float pad = 0;
+
+ sw = UI_GetStringWidth(string);
+ if (flag == FILE_SHORTEN_FRONT) {
+ char *s = string;
+ BLI_strncpy(temp, "...", 4);
+ pad = UI_GetStringWidth(temp);
+ while (s && (sw+pad>w)) {
+ s++;
+ sw = UI_GetStringWidth(s);
+ shortened = 1;
+ }
+ if (shortened) {
+ int slen = strlen(s);
+ BLI_strncpy(temp+3, s, slen+1);
+ temp[slen+4] = '\0';
+ BLI_strncpy(string, temp, slen+4);
+ }
+ } else {
+ char *s = string;
+ while (sw>w) {
+ int slen = strlen(string);
+ string[slen-1] = '\0';
+ sw = UI_GetStringWidth(s);
+ shortened = 1;
+ }
+ if (shortened) {
+ int slen = strlen(string);
+ if (slen > 3) {
+ BLI_strncpy(string+slen-3, "...", 4);
+ }
+ }
+ }
+
+ return sw;
+}
+
+static int get_file_icon(struct direntry *file)
+{
+ if (file->type & S_IFDIR)
+ return ICON_FILE_FOLDER;
+ else if (file->flags & BLENDERFILE)
+ return ICON_FILE_BLEND;
+ else if (file->flags & IMAGEFILE)
+ return ICON_FILE_IMAGE;
+ else if (file->flags & MOVIEFILE)
+ return ICON_FILE_MOVIE;
+ else if (file->flags & PYSCRIPTFILE)
+ return ICON_FILE_SCRIPT;
+ else if (file->flags & PYSCRIPTFILE)
+ return ICON_FILE_SCRIPT;
+ else if (file->flags & SOUNDFILE)
+ return ICON_FILE_SOUND;
+ else if (file->flags & FTFONTFILE)
+ return ICON_FILE_FONT;
+ else
+ return ICON_FILE_BLANK;
+}
+
+static void file_draw_icon(short sx, short sy, int icon, short width, short height)
+{
+ float x,y;
+ int blend=0;
+
+ x = (float)(sx);
+ y = (float)(sy-height);
+
+ if (icon == ICON_FILE_BLANK) blend = -80;
+
+ glEnable(GL_BLEND);
+
+ UI_icon_draw_aspect_blended(x, y, icon, 1.f, blend);
+}
+
+static void file_draw_string(short sx, short sy, const char* string, short width, short height, int flag)
+{
+ short soffs;
+ char fname[FILE_MAXFILE];
+ float sw;
+ float x,y;
+
+ BLI_strncpy(fname,string, FILE_MAXFILE);
+ sw = shorten_string(fname, width, flag );
+
+ soffs = (width - sw) / 2;
+ x = (float)(sx);
+ y = (float)(sy-height);
+
+ /* XXX TODO: handling of international fonts.
+ TODO: proper support for utf8 in languages different from ja_JP abd zh_CH
+ needs update of iconv in lib/windows to support getting the system language string
+ */
+ UI_DrawString(x, y, fname);
+
+}
+
+void file_calc_previews(const bContext *C, ARegion *ar)
+{
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+ View2D *v2d= &ar->v2d;
+
+ ED_fileselect_init_layout(sfile, ar);
+ UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height);
+}
+
+void file_draw_previews(const bContext *C, ARegion *ar)
+{
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+ FileSelectParams* params= ED_fileselect_get_params(sfile);
+ FileLayout* layout= ED_fileselect_get_layout(sfile, ar);
+ View2D *v2d= &ar->v2d;
+ struct FileList* files = sfile->files;
+ int numfiles;
+ struct direntry *file;
+ short sx, sy;
+ ImBuf* imb=0;
+ int i;
+ int colorid = 0;
+ int offset;
+ int is_icon;
+
+ if (!files) return;
+
+ filelist_imgsize(files,sfile->layout->prv_w,sfile->layout->prv_h);
+ numfiles = filelist_numfiles(files);
+
+ sx = v2d->cur.xmin + layout->tile_border_x;
+ sy = v2d->cur.ymax - layout->tile_border_y;
+
+ offset = ED_fileselect_layout_offset(layout, 0, 0);
+ if (offset<0) offset=0;
+ for (i=offset; (i < numfiles) && (i < (offset+(layout->rows+2)*layout->columns)); ++i)
+ {
+ ED_fileselect_layout_tilepos(layout, i, &sx, &sy);
+ sx += v2d->tot.xmin+2;
+ sy = v2d->tot.ymax - sy;
+ file = filelist_file(files, i);
+
+ if (file->flags & ACTIVE) {
+ colorid = TH_HILITE;
+ draw_tile(sx - 1, sy, sfile->layout->tile_w + 1, sfile->layout->tile_h, colorid,0);
+ } else if (params->active_file == i) {
+ colorid = TH_ACTIVE;
+ draw_tile(sx - 1, sy, sfile->layout->tile_w + 1, sfile->layout->tile_h, colorid,0);
+ }
+
+ if ( (file->flags & IMAGEFILE) /* || (file->flags & MOVIEFILE) */)
+ {
+ filelist_loadimage(files, i);
+ }
+ is_icon = 0;
+ imb = filelist_getimage(files, i);
+ if (!imb) {
+ imb = filelist_geticon(files,i);
+ is_icon = 1;
+ }
+
+ if (imb) {
+ float fx = ((float)layout->prv_w - (float)imb->x)/2.0f;
+ float fy = ((float)layout->prv_h - (float)imb->y)/2.0f;
+ float dx = (fx + 0.5f + sfile->layout->prv_border_x);
+ float dy = (fy + 0.5f - sfile->layout->prv_border_y);
+ short xco = (float)sx + dx;
+ short yco = (float)sy - sfile->layout->prv_h + dy;
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ /* shadow */
+ if (!is_icon && (file->flags & IMAGEFILE))
+ uiDrawBoxShadow(220, xco, yco, xco + imb->x, yco + imb->y);
+
+ glEnable(GL_BLEND);
+
+ /* the image */
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glaDrawPixelsTex(xco, yco, imb->x, imb->y, GL_UNSIGNED_BYTE, imb->rect);
+
+ /* border */
+ if (!is_icon && (file->flags & IMAGEFILE)) {
+ glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
+ fdrawbox(xco, yco, xco + imb->x, yco + imb->y);
+ }
+
+ glDisable(GL_BLEND);
+ imb = 0;
+ }
+
+ /* shadow */
+ UI_ThemeColorShade(TH_BACK, -20);
+
+
+ if (S_ISDIR(file->type)) {
+ glColor4f(1.0f, 1.0f, 0.9f, 1.0f);
+ }
+ else if (file->flags & IMAGEFILE) {
+ UI_ThemeColor(TH_SEQ_IMAGE);
+ }
+ else if (file->flags & MOVIEFILE) {
+ UI_ThemeColor(TH_SEQ_MOVIE);
+ }
+ else if (file->flags & BLENDERFILE) {
+ UI_ThemeColor(TH_SEQ_SCENE);
+ }
+ else {
+ if (params->active_file == i) {
+ UI_ThemeColor(TH_GRID); /* grid used for active text */
+ } else if (file->flags & ACTIVE) {
+ UI_ThemeColor(TH_TEXT_HI);
+ } else {
+ UI_ThemeColor(TH_TEXT);
+ }
+ }
+
+ file_draw_string(sx + layout->prv_border_x, sy+4, file->relname, layout->tile_w, layout->tile_h, FILE_SHORTEN_END);
+
+ if (!sfile->loadimage_timer)
+ sfile->loadimage_timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER1, 1.0/30.0); /* max 30 frames/sec. */
+
+ }
+
+ uiSetRoundBox(0);
+}
+
+
+void file_draw_list(const bContext *C, ARegion *ar)
+{
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+ FileSelectParams* params = ED_fileselect_get_params(sfile);
+ FileLayout* layout= ED_fileselect_get_layout(sfile, ar);
+ View2D *v2d= &ar->v2d;
+ struct FileList* files = sfile->files;
+ struct direntry *file;
+ int numfiles;
+ int colorid = 0;
+ short sx, sy;
+ int offset;
+ short type;
+ int i;
+ float sw, spos;
+
+ numfiles = filelist_numfiles(files);
+ type = filelist_gettype(files);
+
+ sx = ar->v2d.tot.xmin + layout->tile_border_x/2;
+ sy = ar->v2d.cur.ymax - layout->tile_border_y;
+
+ offset = ED_fileselect_layout_offset(layout, 0, 0);
+ if (offset<0) offset=0;
+
+ /* alternating flat shade background */
+ for (i=0; (i <= layout->rows); ++i)
+ {
+ sx = v2d->cur.xmin;
+ sy = v2d->cur.ymax - i*(layout->tile_h+2*layout->tile_border_y) - layout->tile_border_y;
+
+ if (i % 2) {
+ UI_ThemeColor(TH_BACK);
+ } else {
+ UI_ThemeColorShade(TH_BACK, -7);
+ }
+ glRectf(v2d->cur.xmin, sy, v2d->cur.xmax, sy+layout->tile_h+2*layout->tile_border_y);
+ }
+
+ /* vertical column dividers */
+ sx = v2d->tot.xmin;
+ while (sx < ar->v2d.cur.xmax) {
+ sx += (sfile->layout->tile_w+2*sfile->layout->tile_border_x);
+
+ UI_ThemeColorShade(TH_BACK, 30);
+ sdrawline(sx+1, ar->v2d.cur.ymax - layout->tile_border_y , sx+1, ar->v2d.cur.ymin);
+ UI_ThemeColorShade(TH_BACK, -30);
+ sdrawline(sx, ar->v2d.cur.ymax - layout->tile_border_y , sx, ar->v2d.cur.ymin);
+ }
+
+ sx = ar->v2d.cur.xmin + layout->tile_border_x;
+ sy = ar->v2d.cur.ymax - layout->tile_border_y;
+
+ for (i=offset; (i < numfiles); ++i)
+ {
+ ED_fileselect_layout_tilepos(layout, i, &sx, &sy);
+ sx += v2d->tot.xmin+2;
+ sy = v2d->tot.ymax - sy;
+
+ file = filelist_file(files, i);
+
+ if (params->active_file == i) {
+ if (file->flags & ACTIVE) colorid= TH_HILITE;
+ else colorid = TH_BACK;
+ draw_tile(sx-2, sy-3, layout->tile_w+2, sfile->layout->tile_h+layout->tile_border_y, colorid,20);
+ } else if (file->flags & ACTIVE) {
+ colorid = TH_HILITE;
+ draw_tile(sx-2, sy-3, layout->tile_w+2, sfile->layout->tile_h+layout->tile_border_y, colorid,0);
+ }
+
+ spos = sx;
+ file_draw_icon(spos, sy-3, get_file_icon(file), ICON_DEFAULT_WIDTH, ICON_DEFAULT_WIDTH);
+ spos += ICON_DEFAULT_WIDTH + 4;
+
+ UI_ThemeColor4(TH_TEXT);
+
+
+ sw = UI_GetStringWidth(file->relname);
+ file_draw_string(spos, sy, file->relname, sw, layout->tile_h, FILE_SHORTEN_END);
+ spos += filelist_column_len(sfile->files, COLUMN_NAME) + 10;
+ if (params->display == FILE_SHOWSHORT) {
+ if (!(file->type & S_IFDIR)) {
+ sw = UI_GetStringWidth(file->size);
+ spos += filelist_column_len(sfile->files, COLUMN_SIZE) + 10 - sw;
+ file_draw_string(spos, sy, file->size, sw, layout->tile_h, FILE_SHORTEN_END);
+ }
+ } else {
+#if 0 // XXX TODO: add this for non-windows systems
+ /* rwx rwx rwx */
+ spos += 20;
+ sw = UI_GetStringWidth(file->mode1);
+ file_draw_string(spos, sy, file->mode1, sw, layout->tile_h);
+
+ spos += 30;
+ sw = UI_GetStringWidth(file->mode2);
+ file_draw_string(spos, sy, file->mode2, sw, layout->tile_h);
+
+ spos += 30;
+ sw = UI_GetStringWidth(file->mode3);
+ file_draw_string(spos, sy, file->mode3, sw, layout->tile_h);
+
+ spos += 30;
+ sw = UI_GetStringWidth(file->owner);
+ file_draw_string(spos, sy, file->owner, sw, layout->tile_h);
+#endif
+
+
+ sw = UI_GetStringWidth(file->date);
+ file_draw_string(spos, sy, file->date, sw, layout->tile_h, FILE_SHORTEN_END);
+ spos += filelist_column_len(sfile->files, COLUMN_DATE) + 10;
+
+ sw = UI_GetStringWidth(file->time);
+ file_draw_string(spos, sy, file->time, sw, layout->tile_h, FILE_SHORTEN_END);
+ spos += filelist_column_len(sfile->files, COLUMN_TIME) + 10;
+
+ if (!(file->type & S_IFDIR)) {
+ sw = UI_GetStringWidth(file->size);
+ spos += filelist_column_len(sfile->files, COLUMN_SIZE) + 10 - sw;
+ file_draw_string(spos, sy, file->size, sw, layout->tile_h, FILE_SHORTEN_END);
+ }
+ }
+ }
+}
+
+static void file_draw_fsmenu_category(const bContext *C, ARegion *ar, FSMenuCategory category, const char* category_name, short *starty)
+{
+ struct FSMenu* fsmenu = fsmenu_get();
+ char bookmark[FILE_MAX];
+ int nentries = fsmenu_get_nentries(fsmenu, category);
+ int linestep = gFontsize*2.0f;
+ short sx, sy, xpos, ypos;
+ int bmwidth = ar->v2d.cur.xmax - ar->v2d.cur.xmin - 2*TILE_BORDER_X - ICON_DEFAULT_WIDTH - 4;
+ int fontsize = gFontsize;
+ int i;
+
+
+ sx = ar->v2d.cur.xmin + TILE_BORDER_X;
+ sy = *starty;
+
+ UI_ThemeColor(TH_TEXT_HI);
+ file_draw_string(sx, sy, category_name, bmwidth, fontsize, FILE_SHORTEN_END);
+
+ sy -= linestep;
+
+ for (i=0; i< nentries && (sy > ar->v2d.cur.ymin) ;++i) {
+ char *fname = fsmenu_get_entry(fsmenu, category, i);
+
+ if (fname) {
+ int sl;
+ BLI_strncpy(bookmark, fname, FILE_MAX);
+
+ sl = strlen(bookmark)-1;
+ while (bookmark[sl] == '\\' || bookmark[sl] == '/') {
+ bookmark[sl] = '\0';
+ sl--;
+ }
+ if (fsmenu_is_selected(fsmenu, category, i) ) {
+ UI_ThemeColor(TH_HILITE);
+ //uiSetRoundBox(15);
+ uiRoundBox(sx, sy - linestep, ar->v2d.cur.xmax - TILE_BORDER_X, sy, 4.0f);
+ // glRectf(ar->v2d.cur.xmin, sy-linestep, ar->v2d.cur.xmax + 2*TILE_BORDER_X, sy);
+ UI_ThemeColor(TH_TEXT);
+ } else {
+ UI_ThemeColor(TH_TEXT_HI);
+ }
+
+ xpos = sx;
+ ypos = sy - (TILE_BORDER_Y * 0.5);
+
+ file_draw_icon(xpos, ypos, ICON_FILE_FOLDER, ICON_DEFAULT_WIDTH, ICON_DEFAULT_WIDTH);
+ xpos += ICON_DEFAULT_WIDTH + 4;
+ file_draw_string(xpos, ypos, bookmark, bmwidth, fontsize, FILE_SHORTEN_FRONT);
+ sy -= linestep;
+ fsmenu_set_pos(fsmenu, category, i, xpos, ypos);
+ }
+ }
+
+ *starty = sy;
+}
+
+void file_draw_fsmenu(const bContext *C, ARegion *ar)
+{
+ int linestep = gFontsize*2.0f;
+ short sy= ar->v2d.cur.ymax-2*TILE_BORDER_Y;
+
+ file_draw_fsmenu_category(C, ar, FS_CATEGORY_SYSTEM, "SYSTEM", &sy);
+ sy -= linestep;
+ file_draw_fsmenu_category(C, ar, FS_CATEGORY_BOOKMARKS, "BOOKMARKS", &sy);
+ sy -= linestep;
+ file_draw_fsmenu_category(C, ar, FS_CATEGORY_RECENT, "RECENT", &sy);
+
+}
diff --git a/source/blender/editors/space_file/file_header.c b/source/blender/editors/space_file/file_header.c
new file mode 100644
index 00000000000..b7276c933e6
--- /dev/null
+++ b/source/blender/editors/space_file/file_header.c
@@ -0,0 +1,187 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_global.h"
+
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+#include "ED_fileselect.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "file_intern.h"
+#include "filelist.h"
+
+#define B_SORTIMASELLIST 1
+#define B_RELOADIMASELDIR 2
+#define B_FILTERIMASELDIR 3
+
+/* ************************ header area region *********************** */
+
+static void do_file_header_buttons(bContext *C, void *arg, int event)
+{
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+ switch(event) {
+ case B_SORTIMASELLIST:
+ filelist_sort(sfile->files, sfile->params->sort);
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ break;
+ case B_RELOADIMASELDIR:
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ break;
+ case B_FILTERIMASELDIR:
+ if(sfile->params) {
+ if (sfile->params->flag & FILE_FILTER) {
+ filelist_setfilter(sfile->files,sfile->params->filter);
+ filelist_filter(sfile->files);
+ } else {
+ filelist_setfilter(sfile->files,0);
+ filelist_filter(sfile->files);
+ }
+ }
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ }
+}
+
+
+void file_header_buttons(const bContext *C, ARegion *ar)
+{
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+ FileSelectParams* params = ED_fileselect_get_params(sfile);
+
+ uiBlock *block;
+ int xco, yco= 3;
+ int xcotitle;
+
+ block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_file_header_buttons, NULL);
+
+ xco= ED_area_header_standardbuttons(C, block, yco);
+
+ /*
+ if((sa->flag & HEADER_NO_PULLDOWN)==0) {
+ int xmax;
+
+ xmax= GetButStringLength("View");
+ uiDefPulldownBut(block, dummy_viewmenu, CTX_wm_area(C),
+ "View", xco, yco-2, xmax-3, 24, "");
+ xco+=XIC+xmax;
+ }
+ */
+
+ xco += 5;
+
+ uiBlockBeginAlign(block);
+ uiDefIconButO(block, BUT, "FILE_OT_parent", WM_OP_INVOKE_DEFAULT, ICON_FILE_PARENT, xco+=XIC, yco, 20, 20, "Navigate to Parent Folder");
+ uiDefIconButO(block, BUT, "FILE_OT_refresh", WM_OP_INVOKE_DEFAULT, ICON_FILE_REFRESH, xco+=XIC, yco, 20, 20, "Refresh List of Files");
+ uiBlockEndAlign(block);
+
+ xco += 5;
+
+ if (sfile->params->type != FILE_MAIN) {
+ uiBlockBeginAlign(block);
+ uiDefIconButS(block, ROW, B_RELOADIMASELDIR, ICON_SHORTDISPLAY, xco+=XIC, yco, XIC,YIC, &params->display, 1.0, FILE_SHORTDISPLAY, 0, 0, "Displays short file description");
+ uiDefIconButS(block, ROW, B_RELOADIMASELDIR, ICON_LONGDISPLAY, xco+=XIC, yco, XIC,YIC, &params->display, 1.0, FILE_LONGDISPLAY, 0, 0, "Displays long file description");
+ uiDefIconButS(block, ROW, B_RELOADIMASELDIR, ICON_IMGDISPLAY, xco+=XIC, yco, XIC,YIC, &params->display, 1.0, FILE_IMGDISPLAY, 0, 0, "Displays files as thumbnails");
+ uiBlockEndAlign(block);
+
+ xco+=XIC;
+ }
+
+ uiBlockBeginAlign(block);
+ uiDefIconButS(block, ROW, B_SORTIMASELLIST, ICON_SORTALPHA, xco+=XIC, yco, XIC,YIC, &params->sort, 1.0, 0.0, 0, 0, "Sorts files alphabetically");
+ uiDefIconButS(block, ROW, B_SORTIMASELLIST, ICON_SORTBYEXT, xco+=XIC, yco, XIC,YIC, &params->sort, 1.0, 3.0, 0, 0, "Sorts files by extension");
+ uiDefIconButS(block, ROW, B_SORTIMASELLIST, ICON_SORTTIME, xco+=XIC, yco, XIC,YIC, &params->sort, 1.0, 1.0, 0, 0, "Sorts files by time");
+ uiDefIconButS(block, ROW, B_SORTIMASELLIST, ICON_SORTSIZE, xco+=XIC, yco, XIC,YIC, &params->sort, 1.0, 2.0, 0, 0, "Sorts files by size");
+ uiBlockEndAlign(block);
+
+ xco+=XIC;
+
+ /* replace with consistent sub-region collapsing
+ if (sfile->params->type != FILE_MAIN) {
+ uiBlockBeginAlign(block);
+ // uiDefIconButBitS(block, TOG, FILE_BOOKMARKS, B_RELOADIMASELDIR, ICON_BOOKMARKS,xco+=XIC,0,XIC,YIC, &params->flag, 0, 0, 0, 0, "Toggles Bookmarks on/off");
+ uiDefIconButO(block, TOG, "FILE_OT_bookmark_toggle", WM_OP_INVOKE_DEFAULT, ICON_BOOKMARKS, xco+XIC,yco,20,20, "Toggle Bookmarks");
+ uiBlockEndAlign(block);
+ xco+=XIC;
+ }
+ */
+
+ uiDefIconButBitS(block, TOG, FILE_FILTER, B_FILTERIMASELDIR, ICON_FILTER,xco+=XIC,0,XIC,YIC, &params->flag, 0, 0, 0, 0, "Filter files");
+ if (params->flag & FILE_FILTER) {
+ xco+=4;
+ uiBlockBeginAlign(block);
+ uiDefIconButBitS(block, TOG, IMAGEFILE, B_FILTERIMASELDIR, ICON_FILE_IMAGE,xco+=XIC,0,XIC,YIC, &params->filter, 0, 0, 0, 0, "Show images");
+ uiDefIconButBitS(block, TOG, BLENDERFILE, B_FILTERIMASELDIR, ICON_FILE_BLEND,xco+=XIC,0,XIC,YIC, &params->filter, 0, 0, 0, 0, "Show .blend files");
+ uiDefIconButBitS(block, TOG, MOVIEFILE, B_FILTERIMASELDIR, ICON_FILE_MOVIE,xco+=XIC,0,XIC,YIC, &params->filter, 0, 0, 0, 0, "Show movies");
+ uiDefIconButBitS(block, TOG, PYSCRIPTFILE, B_FILTERIMASELDIR, ICON_FILE_SCRIPT,xco+=XIC,0,XIC,YIC, &params->filter, 0, 0, 0, 0, "Show python scripts");
+ uiDefIconButBitS(block, TOG, FTFONTFILE, B_FILTERIMASELDIR, ICON_FILE_FONT,xco+=XIC,0,XIC,YIC, &params->filter, 0, 0, 0, 0, "Show fonts");
+ uiDefIconButBitS(block, TOG, SOUNDFILE, B_FILTERIMASELDIR, ICON_FILE_SOUND,xco+=XIC,0,XIC,YIC, &params->filter, 0, 0, 0, 0, "Show sound files");
+ uiDefIconButBitS(block, TOG, TEXTFILE, B_FILTERIMASELDIR, ICON_FILE_BLANK,xco+=XIC,0,XIC,YIC, &params->filter, 0, 0, 0, 0, "Show text files");
+ uiDefIconButBitS(block, TOG, FOLDERFILE, B_FILTERIMASELDIR, ICON_FILE_FOLDER,xco+=XIC,0,XIC,YIC, &params->filter, 0, 0, 0, 0, "Show folders");
+ uiBlockEndAlign(block);
+ xco+=XIC;
+ }
+
+ xcotitle= xco;
+ xco+= UI_GetStringWidth(params->title);
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ /* always as last */
+ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+}
+
+
+
diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h
new file mode 100644
index 00000000000..80b7eb21818
--- /dev/null
+++ b/source/blender/editors/space_file/file_intern.h
@@ -0,0 +1,72 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_FILE_INTERN_H
+#define ED_FILE_INTERN_H
+
+/* internal exports only */
+
+
+/* file_header.c */
+void file_header_buttons(const bContext *C, ARegion *ar);
+
+/* file_ops.c */
+struct ARegion *file_buttons_region(struct ScrArea *sa);
+
+/* file_draw.c */
+#define TILE_BORDER_X 8
+#define TILE_BORDER_Y 8
+
+void file_draw_buttons(const bContext *C, ARegion *ar);
+void file_calc_previews(const bContext *C, ARegion *ar);
+void file_draw_previews(const bContext *C, ARegion *ar);
+void file_draw_list(const bContext *C, ARegion *ar);
+void file_draw_fsmenu(const bContext *C, ARegion *ar);
+
+/* file_ops.h */
+struct wmOperatorType;
+struct wmOperator;
+struct wmEvent;
+void FILE_OT_highlight(struct wmOperatorType *ot);
+void FILE_OT_select(struct wmOperatorType *ot);
+void FILE_OT_select_all_toggle(struct wmOperatorType *ot);
+void FILE_OT_select_border(struct wmOperatorType *ot);
+void FILE_OT_select_bookmark(struct wmOperatorType *ot);
+void FILE_OT_loadimages(struct wmOperatorType *ot);
+void FILE_OT_exec(struct wmOperatorType *ot);
+void FILE_OT_cancel(struct wmOperatorType *ot);
+void FILE_OT_parent(struct wmOperatorType *ot);
+void FILE_OT_refresh(struct wmOperatorType *ot);
+void FILE_OT_bookmark_toggle(struct wmOperatorType *ot);
+
+int file_exec(bContext *C, struct wmOperator *unused);
+int file_cancel_exec(bContext *C, struct wmOperator *unused);
+int file_parent_exec(bContext *C, struct wmOperator *unused);
+int file_hilight_set(SpaceFile *sfile, ARegion *ar, int mx, int my);
+
+#endif /* ED_FILE_INTERN_H */
+
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
new file mode 100644
index 00000000000..28a83c4cf80
--- /dev/null
+++ b/source/blender/editors/space_file/file_ops.c
@@ -0,0 +1,644 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Andrea Weikert (c) 2008 Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_global.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_storage_types.h"
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+#include "ED_fileselect.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "file_intern.h"
+#include "filelist.h"
+#include "fsmenu.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+/* for events */
+#define NOTACTIVE 0
+#define ACTIVATE 1
+#define INACTIVATE 2
+
+/* ---------- FILE SELECTION ------------ */
+
+static int find_file_mouse_hor(SpaceFile *sfile, struct ARegion* ar, short x, short y)
+{
+ float fx,fy;
+ int active_file = -1;
+ int numfiles = filelist_numfiles(sfile->files);
+ View2D* v2d = &ar->v2d;
+
+ UI_view2d_region_to_view(v2d, x, y, &fx, &fy);
+
+ active_file = ED_fileselect_layout_offset(sfile->layout, v2d->tot.xmin + fx, v2d->tot.ymax - fy);
+
+ printf("FINDFILE %d\n", active_file);
+ if ( (active_file < 0) || (active_file >= numfiles) )
+ {
+ active_file = -1;
+ }
+ return active_file;
+}
+
+
+static int find_file_mouse_vert(SpaceFile *sfile, struct ARegion* ar, short x, short y)
+{
+ float fx,fy;
+ int active_file = -1;
+ int numfiles = filelist_numfiles(sfile->files);
+ View2D* v2d = &ar->v2d;
+
+ UI_view2d_region_to_view(v2d, x, y, &fx, &fy);
+
+ active_file = ED_fileselect_layout_offset(sfile->layout, v2d->tot.xmin + fx, v2d->tot.ymax - fy);
+
+ if ( (active_file < 0) || (active_file >= numfiles) )
+ {
+ active_file = -1;
+ }
+ return active_file;
+}
+
+static void file_deselect_all(SpaceFile* sfile)
+{
+ int numfiles = filelist_numfiles(sfile->files);
+ int i;
+
+ for ( i=0; i < numfiles; ++i) {
+ struct direntry* file = filelist_file(sfile->files, i);
+ if (file && (file->flags & ACTIVE)) {
+ file->flags &= ~ACTIVE;
+ }
+ }
+}
+
+static void file_select(SpaceFile* sfile, ARegion* ar, const rcti* rect, short val)
+{
+ int first_file = -1;
+ int last_file = -1;
+ int act_file;
+ short selecting = (val == LEFTMOUSE);
+ FileSelectParams *params = ED_fileselect_get_params(sfile);
+ FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
+
+ int numfiles = filelist_numfiles(sfile->files);
+
+ params->selstate = NOTACTIVE;
+ if ( (layout->flag == FILE_LAYOUT_HOR) ) {
+ first_file = find_file_mouse_hor(sfile, ar, rect->xmin, rect->ymax);
+ last_file = find_file_mouse_hor(sfile, ar, rect->xmax, rect->ymin);
+ } else {
+ first_file = find_file_mouse_vert(sfile, ar, rect->xmin, rect->ymax);
+ last_file = find_file_mouse_vert(sfile, ar, rect->xmax, rect->ymin);
+ }
+
+ /* select all valid files between first and last indicated */
+ if ( (first_file >= 0) && (first_file < numfiles) && (last_file >= 0) && (last_file < numfiles) ) {
+ for (act_file = first_file; act_file <= last_file; act_file++) {
+ struct direntry* file = filelist_file(sfile->files, act_file);
+ if (selecting)
+ file->flags |= ACTIVE;
+ else
+ file->flags &= ~ACTIVE;
+ }
+ }
+
+ printf("Selecting %d %d\n", first_file, last_file);
+
+ /* make the last file active */
+ if (last_file >= 0 && last_file < numfiles) {
+ struct direntry* file = filelist_file(sfile->files, last_file);
+ params->active_file = last_file;
+
+ if(file && S_ISDIR(file->type)) {
+ /* the path is too long and we are not going up! */
+ if (strcmp(file->relname, ".") &&
+ strcmp(file->relname, "..") &&
+ strlen(params->dir) + strlen(file->relname) >= FILE_MAX )
+ {
+ // XXX error("Path too long, cannot enter this directory");
+ } else {
+ if (strcmp(file->relname, "..")==0) {
+ /* avoids /../../ */
+ BLI_parent_dir(params->dir);
+ } else {
+ strcat(params->dir, file->relname);
+ strcat(params->dir,"/");
+ params->file[0] = '\0';
+ BLI_cleanup_dir(G.sce, params->dir);
+ }
+ filelist_setdir(sfile->files, params->dir);
+ filelist_free(sfile->files);
+ params->active_file = -1;
+ }
+ }
+ else if (file)
+ {
+ if (file->relname) {
+ BLI_strncpy(params->file, file->relname, FILE_MAXFILE);
+ /* XXX
+ if(event==MIDDLEMOUSE && filelist_gettype(sfile->files))
+ imasel_execute(sfile);
+ */
+ }
+
+ }
+ /* XXX
+ if(BIF_filelist_gettype(sfile->files)==FILE_MAIN) {
+ active_imasel_object(sfile);
+ }
+ */
+ }
+}
+
+
+
+static int file_border_select_exec(bContext *C, wmOperator *op)
+{
+ ARegion *ar= CTX_wm_region(C);
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+ short val;
+ rcti rect;
+
+ val= RNA_int_get(op->ptr, "event_type");
+ rect.xmin= RNA_int_get(op->ptr, "xmin");
+ rect.ymin= RNA_int_get(op->ptr, "ymin");
+ rect.xmax= RNA_int_get(op->ptr, "xmax");
+ rect.ymax= RNA_int_get(op->ptr, "ymax");
+
+ file_select(sfile, ar, &rect, val );
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void FILE_OT_select_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Activate/Select File";
+ ot->idname= "FILE_OT_select_border";
+
+ /* api callbacks */
+ ot->invoke= WM_border_select_invoke;
+ ot->exec= file_border_select_exec;
+ ot->modal= WM_border_select_modal;
+
+ /* rna */
+ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+
+ ot->poll= ED_operator_file_active;
+}
+
+static int file_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+ short val;
+ rcti rect;
+
+ rect.xmin = rect.xmax = event->x - ar->winrct.xmin;
+ rect.ymin = rect.ymax = event->y - ar->winrct.ymin;
+ val = event->val;
+
+ if (BLI_in_rcti(&ar->v2d.mask, rect.xmin, rect.ymin)) {
+
+ /* single select, deselect all selected first */
+ file_deselect_all(sfile);
+ file_select(sfile, ar, &rect, val );
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void FILE_OT_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Activate/Select File";
+ ot->idname= "FILE_OT_select";
+
+ /* api callbacks */
+ ot->invoke= file_select_invoke;
+
+ /* rna */
+
+ ot->poll= ED_operator_file_active;
+}
+
+static int file_select_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+ int numfiles = filelist_numfiles(sfile->files);
+ int i;
+ int select = 1;
+
+ /* if any file is selected, deselect all first */
+ for ( i=0; i < numfiles; ++i) {
+ struct direntry* file = filelist_file(sfile->files, i);
+ if (file && (file->flags & ACTIVE)) {
+ file->flags &= ~ACTIVE;
+ select = 0;
+ ED_area_tag_redraw(sa);
+ }
+ }
+ /* select all only if previously no file was selected */
+ if (select) {
+ for ( i=0; i < numfiles; ++i) {
+ struct direntry* file = filelist_file(sfile->files, i);
+ if(file && !S_ISDIR(file->type)) {
+ file->flags |= ACTIVE;
+ ED_area_tag_redraw(sa);
+ }
+ }
+ }
+ return OPERATOR_FINISHED;
+}
+
+void FILE_OT_select_all_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select/Deselect all files";
+ ot->idname= "FILE_OT_select_all_toggle";
+
+ /* api callbacks */
+ ot->invoke= file_select_all_invoke;
+
+ /* rna */
+
+ ot->poll= ED_operator_file_active;
+}
+
+/* ---------- BOOKMARKS ----------- */
+
+#define MARK_HEIGHT 22
+
+static void set_active_bookmark(FileSelectParams* params, struct ARegion* ar, short x, short y)
+{
+ int nentries = fsmenu_get_nentries(fsmenu_get(), FS_CATEGORY_BOOKMARKS);
+ float fx, fy;
+ short posy;
+
+ UI_view2d_region_to_view(&ar->v2d, x, y, &fx, &fy);
+
+ posy = ar->v2d.cur.ymax - 2*TILE_BORDER_Y - fy;
+ posy -= MARK_HEIGHT; /* header */
+
+ params->active_bookmark = ((float)posy / (MARK_HEIGHT));
+ if (params->active_bookmark < 0 || params->active_bookmark > nentries) {
+ params->active_bookmark = -1;
+ }
+}
+
+static int file_select_bookmark_category(SpaceFile* sfile, ARegion* ar, short x, short y, FSMenuCategory category)
+{
+ struct FSMenu* fsmenu = fsmenu_get();
+ int nentries = fsmenu_get_nentries(fsmenu, category);
+ int linestep = MARK_HEIGHT;
+ short xs, ys;
+ int i;
+ int selected = -1;
+
+ for (i=0; i < nentries; ++i) {
+ fsmenu_get_pos(fsmenu, category, i, &xs, &ys);
+ if ( (y<=ys) && (y>ys-linestep) ) {
+ fsmenu_select_entry(fsmenu, category, i);
+ selected = i;
+ break;
+ }
+ }
+ return selected;
+}
+
+static void file_select_bookmark(SpaceFile* sfile, ARegion* ar, short x, short y)
+{
+ float fx, fy;
+ int selected;
+ FSMenuCategory category = FS_CATEGORY_SYSTEM;
+
+ if (BLI_in_rcti(&ar->v2d.mask, x, y)) {
+ char *entry;
+
+ UI_view2d_region_to_view(&ar->v2d, x, y, &fx, &fy);
+ selected = file_select_bookmark_category(sfile, ar, fx, fy, FS_CATEGORY_SYSTEM);
+ if (selected<0) {
+ category = FS_CATEGORY_BOOKMARKS;
+ selected = file_select_bookmark_category(sfile, ar, fx, fy, category);
+ }
+ if (selected<0) {
+ category = FS_CATEGORY_RECENT;
+ selected = file_select_bookmark_category(sfile, ar, fx, fy, category);
+ }
+
+ if (selected>=0) {
+ entry= fsmenu_get_entry(fsmenu_get(), category, selected);
+ /* which string */
+ if (entry) {
+ FileSelectParams* params = sfile->params;
+ BLI_strncpy(params->dir, entry, sizeof(params->dir));
+ BLI_cleanup_dir(G.sce, params->dir);
+ filelist_free(sfile->files);
+ filelist_setdir(sfile->files, params->dir);
+ params->file[0] = '\0';
+ params->active_file = -1;
+ }
+ }
+ }
+}
+
+static int bookmark_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= CTX_wm_region(C);
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+
+ short x, y;
+
+ x = event->x - ar->winrct.xmin;
+ y = event->y - ar->winrct.ymin;
+
+ file_select_bookmark(sfile, ar, x, y);
+ ED_area_tag_redraw(sa);
+ return OPERATOR_FINISHED;
+}
+
+void FILE_OT_select_bookmark(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Directory";
+ ot->idname= "FILE_OT_select_bookmark";
+
+ /* api callbacks */
+ ot->invoke= bookmark_select_invoke;
+ ot->poll= ED_operator_file_active;
+}
+
+static int loadimages_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+ if (sfile->files) {
+ filelist_loadimage_timer(sfile->files);
+ if (filelist_changed(sfile->files)) {
+ ED_area_tag_redraw(sa);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void FILE_OT_loadimages(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Load Images";
+ ot->idname= "FILE_OT_loadimages";
+
+ /* api callbacks */
+ ot->invoke= loadimages_invoke;
+
+ ot->poll= ED_operator_file_active;
+}
+
+int file_hilight_set(SpaceFile *sfile, ARegion *ar, int mx, int my)
+{
+ FileSelectParams* params;
+ FileLayout* layout;
+ int numfiles, actfile;
+
+ if(sfile==NULL || sfile->files==NULL) return 0;
+
+ numfiles = filelist_numfiles(sfile->files);
+ params = ED_fileselect_get_params(sfile);
+ layout = ED_fileselect_get_layout(sfile, ar);
+
+ if ( (layout->flag == FILE_LAYOUT_HOR)) {
+ actfile = find_file_mouse_hor(sfile, ar, mx , my);
+ } else {
+ actfile = find_file_mouse_vert(sfile, ar, mx, my);
+ }
+
+ if (params && (actfile >= 0) && (actfile < numfiles) ) {
+ params->active_file=actfile;
+ return 1;
+ }
+ return 0;
+}
+
+static int file_highlight_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+
+ if( file_hilight_set(sfile, ar, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin)) {
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void FILE_OT_highlight(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Highlight File";
+ ot->idname= "FILE_OT_highlight";
+
+ /* api callbacks */
+ ot->invoke= file_highlight_invoke;
+ ot->poll= ED_operator_file_active;
+}
+
+int file_cancel_exec(bContext *C, wmOperator *unused)
+{
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+
+ WM_event_fileselect_event(C, sfile->op, EVT_FILESELECT_CANCEL);
+ sfile->op = NULL;
+
+ return OPERATOR_FINISHED;
+}
+
+void FILE_OT_cancel(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Cancel File Load";
+ ot->idname= "FILE_OT_cancel";
+
+ /* api callbacks */
+ ot->exec= file_cancel_exec;
+ ot->poll= ED_operator_file_active;
+}
+
+/* sends events now, so things get handled on windowqueue level */
+int file_exec(bContext *C, wmOperator *unused)
+{
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+ char name[FILE_MAX];
+
+ if(sfile->op) {
+ wmOperator *op= sfile->op;
+
+ sfile->op = NULL;
+ BLI_strncpy(name, sfile->params->dir, sizeof(name));
+ strcat(name, sfile->params->file);
+ RNA_string_set(op->ptr, "filename", name);
+
+ fsmenu_insert_entry(fsmenu_get(), FS_CATEGORY_RECENT, sfile->params->dir,0, 1);
+ BLI_make_file_string(G.sce, name, BLI_gethome(), ".Bfs");
+ fsmenu_write_file(fsmenu_get(), name);
+ WM_event_fileselect_event(C, op, EVT_FILESELECT_EXEC);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void FILE_OT_exec(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Execute File Window";
+ ot->idname= "FILE_OT_exec";
+
+ /* api callbacks */
+ ot->exec= file_exec;
+ ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
+}
+
+
+int file_parent_exec(bContext *C, wmOperator *unused)
+{
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+
+ if(sfile->params) {
+ BLI_parent_dir(sfile->params->dir);
+ filelist_setdir(sfile->files, sfile->params->dir);
+ filelist_free(sfile->files);
+ sfile->params->active_file = -1;
+ }
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+
+}
+
+
+void FILE_OT_parent(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Parent File";
+ ot->idname= "FILE_OT_parent";
+
+ /* api callbacks */
+ ot->exec= file_parent_exec;
+ ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
+}
+
+
+int file_refresh_exec(bContext *C, wmOperator *unused)
+{
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+
+ if(sfile->params) {
+ filelist_setdir(sfile->files, sfile->params->dir);
+ filelist_free(sfile->files);
+ sfile->params->active_file = -1;
+ }
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+
+}
+
+
+void FILE_OT_refresh(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Refresh Filelist";
+ ot->idname= "FILE_OT_refresh";
+
+ /* api callbacks */
+ ot->exec= file_refresh_exec;
+ ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
+}
+
+struct ARegion *file_buttons_region(struct ScrArea *sa)
+{
+ ARegion *ar;
+
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ if(ar->regiontype==RGN_TYPE_CHANNELS)
+ return ar;
+ return NULL;
+}
+
+int file_bookmark_toggle_exec(bContext *C, wmOperator *unused)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= file_buttons_region(sa);
+
+ if(ar) {
+ ar->flag ^= RGN_FLAG_HIDDEN;
+ ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */
+
+ ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
+ ED_area_tag_redraw(sa);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void FILE_OT_bookmark_toggle(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Toggle Bookmarks";
+ ot->idname= "FILE_OT_bookmark_toggle";
+
+ /* api callbacks */
+ ot->exec= file_bookmark_toggle_exec;
+ ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
+}
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
new file mode 100644
index 00000000000..9d7f16000c9
--- /dev/null
+++ b/source/blender/editors/space_file/filelist.c
@@ -0,0 +1,897 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+/* global includes */
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include <direct.h>
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
+#include "BLI_storage_types.h"
+#include "BLI_threads.h"
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BLO_readfile.h"
+
+#include "DNA_space_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_ID.h"
+#include "DNA_object_types.h"
+#include "DNA_listBase.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_world_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+
+#include "ED_datafiles.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_thumbs.h"
+
+#include "PIL_time.h"
+
+#include "UI_interface.h"
+
+#include "filelist.h"
+
+/* Elubie: VERY, really very ugly and evil! Remove asap!!! */
+/* for state of file */
+#define ACTIVE 2
+
+/* max length of library group name within filesel */
+#define GROUP_MAX 32
+
+static void *exec_loadimages(void *list_v);
+
+struct FileList;
+
+typedef struct FileImage {
+ struct FileImage *next, *prev;
+ int index;
+ short lock;
+ short done;
+ struct FileList* filelist;
+} FileImage;
+
+typedef struct FileList
+{
+ struct direntry *filelist;
+ int *fidx;
+
+ int numfiles;
+ int numfiltered;
+ char dir[FILE_MAX];
+ short type;
+ int has_func;
+ short prv_w;
+ short prv_h;
+ short hide_dot;
+ unsigned int filter;
+ short changed;
+ int columns[MAX_FILE_COLUMN];
+ ListBase loadimages;
+ ListBase threads;
+} FileList;
+
+#define SPECIAL_IMG_SIZE 48
+#define SPECIAL_IMG_ROWS 4
+#define SPECIAL_IMG_COLS 4
+
+#define SPECIAL_IMG_FOLDER 0
+#define SPECIAL_IMG_PARENT 1
+#define SPECIAL_IMG_REFRESH 2
+#define SPECIAL_IMG_BLENDFILE 3
+#define SPECIAL_IMG_SOUNDFILE 4
+#define SPECIAL_IMG_MOVIEFILE 5
+#define SPECIAL_IMG_PYTHONFILE 6
+#define SPECIAL_IMG_TEXTFILE 7
+#define SPECIAL_IMG_FONTFILE 8
+#define SPECIAL_IMG_UNKNOWNFILE 9
+#define SPECIAL_IMG_LOADING 10
+#define SPECIAL_IMG_MAX SPECIAL_IMG_LOADING + 1
+
+static ImBuf* gSpecialFileImages[SPECIAL_IMG_MAX];
+
+
+/* ******************* SORT ******************* */
+
+static int compare_name(const void *a1, const void *a2)
+{
+ const struct direntry *entry1=a1, *entry2=a2;
+
+ /* type is is equal to 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);
+
+ /* make sure "." and ".." are always first */
+ if( strcmp(entry1->relname, ".")==0 ) return (-1);
+ if( strcmp(entry2->relname, ".")==0 ) return (1);
+ if( strcmp(entry1->relname, "..")==0 ) return (-1);
+ if( strcmp(entry2->relname, "..")==0 ) return (1);
+
+ return (BLI_strcasecmp(entry1->relname,entry2->relname));
+}
+
+static int compare_date(const void *a1, const void *a2)
+{
+ const struct direntry *entry1=a1, *entry2=a2;
+
+ /* type is equal to 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);
+
+ /* make sure "." and ".." are always first */
+ if( strcmp(entry1->relname, ".")==0 ) return (-1);
+ if( strcmp(entry2->relname, ".")==0 ) return (1);
+ if( strcmp(entry1->relname, "..")==0 ) return (-1);
+ if( strcmp(entry2->relname, "..")==0 ) 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 BLI_strcasecmp(entry1->relname,entry2->relname);
+}
+
+static int compare_size(const void *a1, const void *a2)
+{
+ const struct direntry *entry1=a1, *entry2=a2;
+
+ /* type is equal to 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);
+
+ /* make sure "." and ".." are always first */
+ if( strcmp(entry1->relname, ".")==0 ) return (-1);
+ if( strcmp(entry2->relname, ".")==0 ) return (1);
+ if( strcmp(entry1->relname, "..")==0 ) return (-1);
+ if( strcmp(entry2->relname, "..")==0 ) 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 BLI_strcasecmp(entry1->relname,entry2->relname);
+}
+
+static int compare_extension(const void *a1, const void *a2) {
+ const struct direntry *entry1=a1, *entry2=a2;
+ char *sufix1, *sufix2;
+ char *nil="";
+
+ if (!(sufix1= strstr (entry1->relname, ".blend.gz")))
+ sufix1= strrchr (entry1->relname, '.');
+ if (!(sufix2= strstr (entry2->relname, ".blend.gz")))
+ sufix2= strrchr (entry2->relname, '.');
+ if (!sufix1) sufix1= nil;
+ if (!sufix2) sufix2= nil;
+
+ /* type is is equal to 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);
+
+ /* make sure "." and ".." are always first */
+ if( strcmp(entry1->relname, ".")==0 ) return (-1);
+ if( strcmp(entry2->relname, ".")==0 ) return (1);
+ if( strcmp(entry1->relname, "..")==0 ) return (-1);
+ if( strcmp(entry2->relname, "..")==0 ) return (1);
+
+ return (BLI_strcasecmp(sufix1, sufix2));
+}
+
+void filelist_filter(FileList* filelist)
+{
+ int num_filtered = 0;
+ int i, j;
+
+ if (!filelist->filelist)
+ return;
+
+ if (!filelist->filter) {
+ if (filelist->fidx) {
+ MEM_freeN(filelist->fidx);
+ filelist->fidx = NULL;
+ }
+ filelist->fidx = (int *)MEM_callocN(filelist->numfiles*sizeof(int), "filteridx");
+ for (i = 0; i < filelist->numfiles; ++i) {
+ filelist->fidx[i] = i;
+ }
+ filelist->numfiltered = filelist->numfiles;
+ return;
+ }
+
+ // How many files are left after filter ?
+ for (i = 0; i < filelist->numfiles; ++i) {
+ if (filelist->filelist[i].flags & filelist->filter) {
+ num_filtered++;
+ }
+ else if (filelist->filelist[i].type & S_IFDIR) {
+ if (filelist->filter & FOLDERFILE) {
+ num_filtered++;
+ }
+ }
+ }
+
+ if (filelist->fidx) {
+ MEM_freeN(filelist->fidx);
+ filelist->fidx = NULL;
+ }
+ filelist->fidx = (int *)MEM_callocN(num_filtered*sizeof(int), "filteridx");
+ filelist->numfiltered = num_filtered;
+
+ for (i = 0, j=0; i < filelist->numfiles; ++i) {
+ if (filelist->filelist[i].flags & filelist->filter) {
+ filelist->fidx[j++] = i;
+ }
+ else if (filelist->filelist[i].type & S_IFDIR) {
+ if (filelist->filter & FOLDERFILE) {
+ filelist->fidx[j++] = i;
+ }
+ }
+ }
+}
+
+void filelist_init_icons()
+{
+ short x, y, k;
+ ImBuf *bbuf;
+ ImBuf *ibuf;
+ bbuf = IMB_ibImageFromMemory((int *)datatoc_prvicons, datatoc_prvicons_size, IB_rect);
+ if (bbuf) {
+ for (y=0; y<SPECIAL_IMG_ROWS; y++) {
+ for (x=0; x<SPECIAL_IMG_COLS; x++) {
+ int tile = SPECIAL_IMG_COLS*y + x;
+ if (tile < SPECIAL_IMG_MAX) {
+ ibuf = IMB_allocImBuf(SPECIAL_IMG_SIZE, SPECIAL_IMG_SIZE, 32, IB_rect, 0);
+ for (k=0; k<SPECIAL_IMG_SIZE; k++) {
+ memcpy(&ibuf->rect[k*SPECIAL_IMG_SIZE], &bbuf->rect[(k+y*SPECIAL_IMG_SIZE)*SPECIAL_IMG_SIZE*SPECIAL_IMG_COLS+x*SPECIAL_IMG_SIZE], SPECIAL_IMG_SIZE*sizeof(int));
+ }
+ gSpecialFileImages[tile] = ibuf;
+ }
+ }
+ }
+ IMB_freeImBuf(bbuf);
+ }
+}
+
+void filelist_free_icons()
+{
+ int i;
+ for (i=0; i < SPECIAL_IMG_MAX; ++i) {
+ IMB_freeImBuf(gSpecialFileImages[i]);
+ gSpecialFileImages[i] = NULL;
+ }
+}
+
+struct FileList* filelist_new()
+{
+ FileList* p = MEM_callocN( sizeof(FileList), "filelist" );
+ p->filelist = 0;
+ p->numfiles = 0;
+ p->dir[0] = '\0';
+ p->type = 0;
+ p->has_func = 0;
+ p->filter = 0;
+ return p;
+}
+
+struct FileList* filelist_copy(struct FileList* filelist)
+{
+ FileList* p = filelist_new();
+ BLI_strncpy(p->dir, filelist->dir, FILE_MAX);
+ p->filelist = NULL;
+ p->fidx = NULL;
+ p->type = filelist->type;
+
+ return p;
+}
+
+void filelist_free(struct FileList* filelist)
+{
+ int i;
+
+ if (!filelist) {
+ printf("Attemtping to delete empty filelist.\n");
+ return;
+ }
+
+ BLI_end_threads(&filelist->threads);
+ BLI_freelistN(&filelist->loadimages);
+
+ if (filelist->fidx) {
+ MEM_freeN(filelist->fidx);
+ filelist->fidx = NULL;
+ }
+
+ for (i = 0; i < filelist->numfiles; ++i) {
+ if (filelist->filelist[i].image) {
+ IMB_freeImBuf(filelist->filelist[i].image);
+ }
+ filelist->filelist[i].image = 0;
+ if (filelist->filelist[i].relname)
+ MEM_freeN(filelist->filelist[i].relname);
+ filelist->filelist[i].relname = 0;
+ if (filelist->filelist[i].string)
+ MEM_freeN(filelist->filelist[i].string);
+ filelist->filelist[i].string = 0;
+ }
+
+ filelist->numfiles = 0;
+ free(filelist->filelist);
+ filelist->filelist = 0;
+ filelist->filter = 0;
+ filelist->numfiltered =0;
+}
+
+int filelist_numfiles(struct FileList* filelist)
+{
+ return filelist->numfiltered;
+}
+
+const char * filelist_dir(struct FileList* filelist)
+{
+ return filelist->dir;
+}
+
+void filelist_setdir(struct FileList* filelist, const char *dir)
+{
+ BLI_strncpy(filelist->dir, dir, FILE_MAX);
+}
+
+void filelist_imgsize(struct FileList* filelist, short w, short h)
+{
+ filelist->prv_w = w;
+ filelist->prv_h = h;
+}
+
+
+static void *exec_loadimages(void *list_v)
+{
+ FileImage* img = (FileImage*)list_v;
+ struct FileList *filelist = img->filelist;
+
+ ImBuf *imb = NULL;
+ int fidx = img->index;
+
+ if ( filelist->filelist[fidx].flags & IMAGEFILE ) {
+ imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_IMAGE);
+ } else if ( filelist->filelist[fidx].flags & MOVIEFILE ) {
+ imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_MOVIE);
+ if (!imb) {
+ /* remember that file can't be loaded via IMB_open_anim */
+ filelist->filelist[fidx].flags &= ~MOVIEFILE;
+ filelist->filelist[fidx].flags |= MOVIEFILE_ICON;
+ }
+ }
+ if (imb) {
+ IMB_freeImBuf(imb);
+ }
+ img->done=1;
+ return 0;
+}
+
+short filelist_changed(struct FileList* filelist)
+{
+ return filelist->changed;
+}
+
+void filelist_loadimage_timer(struct FileList* filelist)
+{
+ FileImage *limg = filelist->loadimages.first;
+ short refresh=0;
+
+ // as long as threads are available and there is work to do
+ while (limg) {
+ if (BLI_available_threads(&filelist->threads)>0) {
+ if (!limg->lock) {
+ limg->lock=1;
+ BLI_insert_thread(&filelist->threads, limg);
+ }
+ }
+ if (limg->done) {
+ FileImage *oimg = limg;
+ BLI_remlink(&filelist->loadimages, oimg);
+ BLI_remove_thread(&filelist->threads, oimg);
+ limg = oimg->next;
+ MEM_freeN(oimg);
+ refresh = 1;
+ } else {
+ limg= limg->next;
+ }
+ }
+ filelist->changed=refresh;
+}
+
+void filelist_loadimage(struct FileList* filelist, int index)
+{
+ ImBuf *imb = NULL;
+ int imgwidth = filelist->prv_w;
+ int imgheight = filelist->prv_h;
+ short ex, ey, dx, dy;
+ float scaledx, scaledy;
+ int fidx = 0;
+
+ if ( (index < 0) || (index >= filelist->numfiltered) ) {
+ return;
+ }
+ fidx = filelist->fidx[index];
+
+ if (!filelist->filelist[fidx].image)
+ {
+ if (filelist->type != FILE_MAIN)
+ {
+ if ( (filelist->filelist[fidx].flags & IMAGEFILE) || (filelist->filelist[fidx].flags & MOVIEFILE) ) {
+ imb = IMB_thumb_read(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL);
+ }
+ if (imb) {
+ if (imb->x > imb->y) {
+ scaledx = (float)imgwidth;
+ scaledy = ( (float)imb->y/(float)imb->x )*imgwidth;
+ }
+ else {
+ scaledy = (float)imgheight;
+ scaledx = ( (float)imb->x/(float)imb->y )*imgheight;
+ }
+ ex = (short)scaledx;
+ ey = (short)scaledy;
+
+ dx = imgwidth - ex;
+ dy = imgheight - ey;
+
+ IMB_scaleImBuf(imb, ex, ey);
+ filelist->filelist[fidx].image = imb;
+ } else {
+ /* prevent loading image twice */
+ FileImage* limg = filelist->loadimages.first;
+ short found= 0;
+ while(limg) {
+ if (limg->index == fidx) {
+ found= 1;
+ break;
+ }
+ limg= limg->next;
+ }
+ if (!found) {
+ FileImage* limg = MEM_callocN(sizeof(struct FileImage), "loadimage");
+ limg->index= fidx;
+ limg->lock= 0;
+ limg->filelist= filelist;
+ BLI_addtail(&filelist->loadimages, limg);
+ }
+ }
+ }
+ }
+}
+
+struct ImBuf * filelist_getimage(struct FileList* filelist, int index)
+{
+ ImBuf* ibuf = NULL;
+ int fidx = 0;
+ if ( (index < 0) || (index >= filelist->numfiltered) ) {
+ return NULL;
+ }
+ fidx = filelist->fidx[index];
+ ibuf = filelist->filelist[fidx].image;
+
+ return ibuf;
+}
+
+struct ImBuf * filelist_geticon(struct FileList* filelist, int index)
+{
+ ImBuf* ibuf= NULL;
+ struct direntry *file= NULL;
+ int fidx = 0;
+ if ( (index < 0) || (index >= filelist->numfiltered) ) {
+ return NULL;
+ }
+ fidx = filelist->fidx[index];
+ file = &filelist->filelist[fidx];
+ if (file->type & S_IFDIR) {
+ if ( strcmp(filelist->filelist[fidx].relname, "..") == 0) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
+ } else if ( strcmp(filelist->filelist[fidx].relname, ".") == 0) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
+ } else {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER];
+ }
+ } else {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
+ }
+
+ if (file->flags & BLENDERFILE) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE];
+ } else if ( (file->flags & MOVIEFILE) || (file->flags & MOVIEFILE_ICON) ) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE];
+ } else if (file->flags & SOUNDFILE) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE];
+ } else if (file->flags & PYSCRIPTFILE) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE];
+ } else if (file->flags & FTFONTFILE) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE];
+ } else if (file->flags & TEXTFILE) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE];
+ } else if (file->flags & IMAGEFILE) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING];
+ }
+
+ return ibuf;
+}
+
+struct direntry * filelist_file(struct FileList* filelist, int index)
+{
+ int fidx = 0;
+
+ if ( (index < 0) || (index >= filelist->numfiltered) ) {
+ return NULL;
+ }
+ fidx = filelist->fidx[index];
+
+ return &filelist->filelist[fidx];
+}
+
+int filelist_find(struct FileList* filelist, char *file)
+{
+ int index = -1;
+ int i;
+ int fidx = -1;
+
+ if (!filelist->fidx)
+ return fidx;
+
+
+ for (i = 0; i < filelist->numfiles; ++i) {
+ if ( strcmp(filelist->filelist[i].relname, file) == 0) {
+ index = i;
+ break;
+ }
+ }
+
+ for (i = 0; i < filelist->numfiltered; ++i) {
+ if (filelist->fidx[i] == index) {
+ fidx = i;
+ break;
+ }
+ }
+ return fidx;
+}
+
+void filelist_hidedot(struct FileList* filelist, short hide)
+{
+ filelist->hide_dot = hide;
+}
+
+void filelist_setfilter(struct FileList* filelist, unsigned int filter)
+{
+ filelist->filter = filter;
+}
+
+int filelist_column_len(struct FileList* filelist, FileListColumns column)
+{
+ return filelist->columns[column];
+}
+
+void filelist_readdir(struct FileList* filelist)
+{
+ char wdir[FILE_MAX];
+ int i;
+
+ if (!filelist) return;
+ filelist->fidx = 0;
+ filelist->filelist = 0;
+
+ BLI_getwdN(wdir);
+
+ BLI_cleanup_dir(G.sce, filelist->dir);
+ BLI_hide_dot_files(filelist->hide_dot);
+ filelist->numfiles = BLI_getdir(filelist->dir, &(filelist->filelist));
+
+ chdir(wdir);
+ filelist_setfiletypes(filelist, G.have_quicktime);
+ filelist_filter(filelist);
+
+ if (!filelist->threads.first) {
+ BLI_init_threads(&filelist->threads, exec_loadimages, 2);
+ }
+
+ for (i=0; i<MAX_FILE_COLUMN; ++i) {
+ filelist->columns[i] = 0;
+ }
+
+ for (i=0; (i < filelist->numfiles); ++i)
+ {
+ struct direntry* file = filelist_file(filelist, i);
+ if (file) {
+ int len;
+ len = UI_GetStringWidth(file->relname);
+ if (len > filelist->columns[COLUMN_NAME]) filelist->columns[COLUMN_NAME] = len;
+ len = UI_GetStringWidth(file->date);
+ if (len > filelist->columns[COLUMN_DATE]) filelist->columns[COLUMN_DATE] = len;
+ len = UI_GetStringWidth(file->time);
+ if (len > filelist->columns[COLUMN_TIME]) filelist->columns[COLUMN_TIME] = len;
+ len = UI_GetStringWidth(file->size);
+ if (len > filelist->columns[COLUMN_SIZE]) filelist->columns[COLUMN_SIZE] = len;
+ len = UI_GetStringWidth(file->mode1);
+ if (len > filelist->columns[COLUMN_MODE1]) filelist->columns[COLUMN_MODE1] = len;
+ len = UI_GetStringWidth(file->mode2);
+ if (len > filelist->columns[COLUMN_MODE2]) filelist->columns[COLUMN_MODE2] = len;
+ len = UI_GetStringWidth(file->mode3);
+ if (len > filelist->columns[COLUMN_MODE3]) filelist->columns[COLUMN_MODE3] = len;
+ len = UI_GetStringWidth(file->owner);
+ if (len > filelist->columns[COLUMN_OWNER]) filelist->columns[COLUMN_OWNER] = len;
+ }
+ }
+}
+
+int filelist_empty(struct FileList* filelist)
+{
+ return filelist->filelist == 0;
+}
+
+void filelist_parent(struct FileList* filelist)
+{
+ BLI_parent_dir(filelist->dir);
+ BLI_make_exist(filelist->dir);
+ filelist_readdir(filelist);
+}
+
+void filelist_setfiletypes(struct FileList* filelist, short has_quicktime)
+{
+ struct direntry *file;
+ int num;
+
+ file= filelist->filelist;
+
+ for(num=0; num<filelist->numfiles; num++, file++) {
+ file->flags= 0;
+ file->type= file->s.st_mode; /* restore the mess below */
+
+ /* Don't check extensions for directories */
+ if (file->type & S_IFDIR)
+ continue;
+
+
+
+ if(BLO_has_bfile_extension(file->relname)) {
+ file->flags |= BLENDERFILE;
+ } else if(BLI_testextensie(file->relname, ".py")) {
+ file->flags |= PYSCRIPTFILE;
+ } else if(BLI_testextensie(file->relname, ".txt")) {
+ file->flags |= TEXTFILE;
+ } else if( BLI_testextensie(file->relname, ".ttf")
+ || BLI_testextensie(file->relname, ".ttc")
+ || BLI_testextensie(file->relname, ".pfb")
+ || BLI_testextensie(file->relname, ".otf")
+ || BLI_testextensie(file->relname, ".otc")) {
+ file->flags |= FTFONTFILE;
+ } else if (has_quicktime){
+ if( BLI_testextensie(file->relname, ".int")
+ || BLI_testextensie(file->relname, ".inta")
+ || BLI_testextensie(file->relname, ".jpg")
+#ifdef WITH_OPENJPEG
+ || BLI_testextensie(file->relname, ".jp2")
+#endif
+ || BLI_testextensie(file->relname, ".jpeg")
+ || BLI_testextensie(file->relname, ".tga")
+ || BLI_testextensie(file->relname, ".rgb")
+ || BLI_testextensie(file->relname, ".rgba")
+ || BLI_testextensie(file->relname, ".bmp")
+ || BLI_testextensie(file->relname, ".png")
+ || BLI_testextensie(file->relname, ".iff")
+ || BLI_testextensie(file->relname, ".lbm")
+ || BLI_testextensie(file->relname, ".gif")
+ || BLI_testextensie(file->relname, ".psd")
+ || BLI_testextensie(file->relname, ".tif")
+ || BLI_testextensie(file->relname, ".tiff")
+ || BLI_testextensie(file->relname, ".pct")
+ || BLI_testextensie(file->relname, ".pict")
+ || BLI_testextensie(file->relname, ".pntg") //macpaint
+ || BLI_testextensie(file->relname, ".qtif")
+ || BLI_testextensie(file->relname, ".sgi")
+ || BLI_testextensie(file->relname, ".hdr")
+#ifdef WITH_DDS
+ || BLI_testextensie(file->relname, ".dds")
+#endif
+#ifdef WITH_OPENEXR
+ || BLI_testextensie(file->relname, ".exr")
+#endif
+ ) {
+ file->flags |= IMAGEFILE;
+ }
+ else if(BLI_testextensie(file->relname, ".avi")
+ || BLI_testextensie(file->relname, ".flc")
+ || BLI_testextensie(file->relname, ".mov")
+ || BLI_testextensie(file->relname, ".movie")
+ || BLI_testextensie(file->relname, ".mp4")
+ || BLI_testextensie(file->relname, ".m4v")
+ || BLI_testextensie(file->relname, ".mv")) {
+ file->flags |= MOVIEFILE;
+ }
+ else if(BLI_testextensie(file->relname, ".wav")) {
+ file->flags |= SOUNDFILE;
+ }
+ } else { // no quicktime
+ if(BLI_testextensie(file->relname, ".int")
+ || BLI_testextensie(file->relname, ".inta")
+ || BLI_testextensie(file->relname, ".jpg")
+ || BLI_testextensie(file->relname, ".jpeg")
+#ifdef WITH_OPENJPEG
+ || BLI_testextensie(file->relname, ".jp2")
+#endif
+ || BLI_testextensie(file->relname, ".tga")
+ || BLI_testextensie(file->relname, ".rgb")
+ || BLI_testextensie(file->relname, ".rgba")
+ || BLI_testextensie(file->relname, ".bmp")
+ || BLI_testextensie(file->relname, ".png")
+ || BLI_testextensie(file->relname, ".iff")
+ || BLI_testextensie(file->relname, ".tif")
+ || BLI_testextensie(file->relname, ".tiff")
+ || BLI_testextensie(file->relname, ".hdr")
+#ifdef WITH_DDS
+ || BLI_testextensie(file->relname, ".dds")
+#endif
+#ifdef WITH_OPENEXR
+ || BLI_testextensie(file->relname, ".exr")
+#endif
+ || BLI_testextensie(file->relname, ".lbm")
+ || BLI_testextensie(file->relname, ".sgi")) {
+ file->flags |= IMAGEFILE;
+ }
+ else if(BLI_testextensie(file->relname, ".avi")
+ || BLI_testextensie(file->relname, ".mp4")
+ || BLI_testextensie(file->relname, ".mv")) {
+ file->flags |= MOVIEFILE;
+ }
+ else if(BLI_testextensie(file->relname, ".wav")) {
+ file->flags |= SOUNDFILE;
+ }
+ }
+ }
+}
+
+void filelist_swapselect(struct FileList* filelist)
+{
+ struct direntry *file;
+ int num, act= 0;
+
+ file= filelist->filelist;
+ for(num=0; num<filelist->numfiles; num++, file++) {
+ if(file->flags & ACTIVE) {
+ act= 1;
+ break;
+ }
+ }
+ file= filelist->filelist+2;
+ for(num=2; num<filelist->numfiles; num++, file++) {
+ if(act) file->flags &= ~ACTIVE;
+ else file->flags |= ACTIVE;
+ }
+}
+
+void filelist_settype(struct FileList* filelist, int type)
+{
+ filelist->type = type;
+}
+
+short filelist_gettype(struct FileList* filelist)
+{
+ return filelist->type;
+}
+
+void filelist_sort(struct FileList* filelist, short sort)
+{
+ struct direntry *file;
+ int num;/* , act= 0; */
+
+ switch(sort) {
+ case FILE_SORTALPHA:
+ qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_name);
+ break;
+ case FILE_SORTDATE:
+ qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_date);
+ break;
+ case FILE_SORTSIZE:
+ qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_size);
+ break;
+ case FILE_SORTEXTENS:
+ qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_extension);
+ }
+
+ file= filelist->filelist;
+ for(num=0; num<filelist->numfiles; num++, file++) {
+ file->flags &= ~HILITE;
+ }
+ filelist_filter(filelist);
+}
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
new file mode 100644
index 00000000000..26a2d46f5a7
--- /dev/null
+++ b/source/blender/editors/space_file/filelist.h
@@ -0,0 +1,94 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef FILELIST_H
+#define FILELIST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct FileList;
+struct direntry;
+struct BlendHandle;
+struct Scene;
+
+#define MAX_FILE_COLUMN 8
+
+typedef enum FileListColumns {
+ COLUMN_NAME = 0,
+ COLUMN_DATE,
+ COLUMN_TIME,
+ COLUMN_SIZE,
+ COLUMN_MODE1,
+ COLUMN_MODE2,
+ COLUMN_MODE3,
+ COLUMN_OWNER
+} FileListColumns;
+
+struct FileList * filelist_new();
+void filelist_init_icons();
+void filelist_free_icons();
+struct FileList * filelist_copy(struct FileList* filelist);
+int filelist_find(struct FileList* filelist, char *file);
+void filelist_free(struct FileList* filelist);
+void filelist_freelib(struct FileList* filelist);
+void filelist_sort(struct FileList* filelist, short sort);
+int filelist_numfiles(struct FileList* filelist);
+const char * filelist_dir(struct FileList* filelist);
+void filelist_setdir(struct FileList* filelist, const char *dir);
+struct direntry * filelist_file(struct FileList* filelist, int index);
+void filelist_hidedot(struct FileList* filelist, short hide);
+void filelist_setfilter(struct FileList* filelist, unsigned int filter);
+void filelist_filter(struct FileList* filelist);
+void filelist_swapselect(struct FileList* filelist);
+void filelist_imgsize(struct FileList* filelist, short w, short h);
+void filelist_loadimage(struct FileList* filelist, int index);
+void filelist_loadimage_timer(struct FileList* filelist);
+struct ImBuf * filelist_getimage(struct FileList* filelist, int index);
+struct ImBuf * filelist_geticon(struct FileList* filelist, int index);
+short filelist_changed(struct FileList* filelist);
+void filelist_readdir(struct FileList* filelist);
+int filelist_column_len(struct FileList* filelist, FileListColumns column);
+
+int filelist_empty(struct FileList* filelist);
+void filelist_parent(struct FileList* filelist);
+void filelist_setfiletypes(struct FileList* filelist, short has_quicktime);
+void filelist_settype(struct FileList* filelist, int type);
+short filelist_gettype(struct FileList* filelist);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
new file mode 100644
index 00000000000..126ef69aaec
--- /dev/null
+++ b/source/blender/editors/space_file/filesel.c
@@ -0,0 +1,244 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#ifdef WIN32
+#include <io.h>
+#include <direct.h>
+#include "BLI_winstuff.h"
+#else
+#include <unistd.h>
+#include <sys/times.h>
+#endif
+
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
+#include "BLI_storage_types.h"
+#include "BLI_dynstr.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_global.h"
+
+#include "DNA_userdef_types.h"
+
+#include "ED_screen.h"
+#include "ED_util.h"
+#include "ED_fileselect.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "file_intern.h"
+#include "filelist.h"
+
+
+FileSelectParams* ED_fileselect_get_params(struct SpaceFile *sfile)
+{
+ if (!sfile->params) {
+ ED_fileselect_set_params(sfile, FILE_UNIX, "", "/", 0, FILE_SHORTDISPLAY, 0);
+ }
+ return sfile->params;
+}
+
+short ED_fileselect_set_params(SpaceFile *sfile, int type, const char *title, const char *path,
+ short flag, short display, short filter)
+{
+ char name[FILE_MAX], dir[FILE_MAX], file[FILE_MAX];
+ FileSelectParams *params;
+
+ if (!sfile->params) {
+ sfile->params= MEM_callocN(sizeof(FileSelectParams), "fileselparams");
+ }
+
+ params = sfile->params;
+
+ params->type = type;
+ params->flag = flag;
+ params->display = display;
+ params->filter = filter;
+
+ BLI_strncpy(params->title, title, sizeof(params->title));
+
+ BLI_strncpy(name, path, sizeof(name));
+ BLI_convertstringcode(name, G.sce);
+
+ switch(type) {
+ case FILE_MAIN:
+ break;
+ case FILE_LOADLIB:
+ break;
+ case FILE_BLENDER:
+ case FILE_LOADFONT:
+ default:
+ {
+ BLI_split_dirfile(name, dir, file);
+ BLI_strncpy(params->file, file, sizeof(params->file));
+ BLI_strncpy(params->dir, dir, sizeof(params->dir));
+ BLI_make_file_string(G.sce, params->dir, dir, ""); /* XXX needed ? - also solve G.sce */
+ }
+ break;
+ }
+
+ return 1;
+}
+
+void ED_fileselect_reset_params(SpaceFile *sfile)
+{
+ sfile->params->type = FILE_UNIX;
+ sfile->params->flag = 0;
+ sfile->params->title[0] = '\0';
+}
+
+
+int ED_fileselect_layout_offset(FileLayout* layout, int x, int y)
+{
+ int offsetx, offsety;
+ int active_file;
+
+ offsetx = (x)/(layout->tile_w + 2*layout->tile_border_x);
+ offsety = (y)/(layout->tile_h + 2*layout->tile_border_y);
+
+ if (offsetx > layout->columns-1) offsetx = layout->columns-1 ;
+ if (offsety > layout->rows-1) offsety = layout->rows-1 ;
+
+ if (layout->flag & FILE_LAYOUT_HOR)
+ active_file = layout->rows*offsetx + offsety;
+ else
+ active_file = offsetx + layout->columns*offsety;
+ printf("OFFSET %d %d %d %d %d\n", x,y, offsetx, offsety, active_file);
+ return active_file;
+}
+
+void ED_fileselect_layout_tilepos(FileLayout* layout, int tile, short *x, short *y)
+{
+ if (layout->flag == FILE_LAYOUT_HOR) {
+ *x = layout->tile_border_x + (tile/layout->rows)*(layout->tile_w+2*layout->tile_border_x);
+ *y = layout->tile_border_y + (tile%layout->rows)*(layout->tile_h+2*layout->tile_border_y);
+ } else {
+ *x = layout->tile_border_x + ((tile)%layout->columns)*(layout->tile_w+2*layout->tile_border_x);
+ *y = layout->tile_border_y + ((tile)/layout->columns)*(layout->tile_h+2*layout->tile_border_y);
+ }
+}
+
+
+void ED_fileselect_init_layout(struct SpaceFile *sfile, struct ARegion *ar)
+{
+ FileSelectParams* params = ED_fileselect_get_params(sfile);
+ View2D *v2d= &ar->v2d;
+ int maxlen = 0;
+ int numfiles = filelist_numfiles(sfile->files);
+
+ if (sfile->layout == 0) {
+ sfile->layout = MEM_callocN(sizeof(struct FileLayout), "file_layout");
+ }
+
+ if (params->display == FILE_IMGDISPLAY) {
+ sfile->layout->prv_w = 96;
+ sfile->layout->prv_h = 96;
+ sfile->layout->tile_border_x = 6;
+ sfile->layout->tile_border_y = 6;
+ sfile->layout->prv_border_x = 6;
+ sfile->layout->prv_border_y = 6;
+ sfile->layout->tile_w = sfile->layout->prv_w + 2*sfile->layout->prv_border_x;
+ sfile->layout->tile_h = sfile->layout->prv_h + 2*sfile->layout->prv_border_y + 12; // XXX 12 = font h
+ sfile->layout->width= (v2d->cur.xmax - v2d->cur.xmin - 2*sfile->layout->tile_border_x);
+ sfile->layout->columns= sfile->layout->width / (sfile->layout->tile_w + 2*sfile->layout->tile_border_x);
+ if(sfile->layout->columns > 0)
+ sfile->layout->rows= numfiles/sfile->layout->columns + 1; // XXX dirty, modulo is zero
+ else {
+ sfile->layout->columns = 1;
+ sfile->layout->rows= numfiles + 1; // XXX dirty, modulo is zero
+ }
+ sfile->layout->height= sfile->layout->rows*(sfile->layout->tile_h+2*sfile->layout->tile_border_y) + sfile->layout->tile_border_y*2;
+ sfile->layout->flag = FILE_LAYOUT_VER;
+ } else {
+ sfile->layout->prv_w = 0;
+ sfile->layout->prv_h = 0;
+ sfile->layout->tile_border_x = 8;
+ sfile->layout->tile_border_y = 2;
+ sfile->layout->prv_border_x = 0;
+ sfile->layout->prv_border_y = 0;
+ sfile->layout->tile_h = 12*3/2; // XXX 12 = font h
+ sfile->layout->height= v2d->cur.ymax - v2d->cur.ymin;
+ sfile->layout->rows = sfile->layout->height / (sfile->layout->tile_h + 2*sfile->layout->tile_border_y);;
+
+ if (params->display == FILE_SHORTDISPLAY) {
+ maxlen = filelist_column_len(sfile->files, COLUMN_NAME) +
+ filelist_column_len(sfile->files, COLUMN_SIZE);
+ maxlen += 20+2*10; // for icon and space between columns
+ } else {
+ maxlen = filelist_column_len(sfile->files, COLUMN_NAME) +
+ filelist_column_len(sfile->files, COLUMN_DATE) +
+ filelist_column_len(sfile->files, COLUMN_TIME) +
+ filelist_column_len(sfile->files, COLUMN_SIZE) /* +
+ filelist_column_len(sfile->files, COLUMN_MODE1) +
+ filelist_column_len(sfile->files, COLUMN_MODE2) +
+ filelist_column_len(sfile->files, COLUMN_MODE3) +
+ filelist_column_len(sfile->files, COLUMN_OWNER) */ ;
+ maxlen += 20+4*10; // for icon and space between columns
+ }
+ sfile->layout->tile_w = maxlen + 40;
+ if(sfile->layout->rows > 0)
+ sfile->layout->columns = numfiles/sfile->layout->rows + 1; // XXX dirty, modulo is zero
+ else {
+ sfile->layout->rows = 1;
+ sfile->layout->columns = numfiles + 1; // XXX dirty, modulo is zero
+ }
+ sfile->layout->width = sfile->layout->columns * (sfile->layout->tile_w + 2*sfile->layout->tile_border_x) + sfile->layout->tile_border_x*2;
+ sfile->layout->flag = FILE_LAYOUT_HOR;
+ }
+}
+
+FileLayout* ED_fileselect_get_layout(struct SpaceFile *sfile, struct ARegion *ar)
+{
+ if (!sfile->layout) {
+ ED_fileselect_init_layout(sfile, ar);
+ }
+ return sfile->layout;
+}
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
new file mode 100644
index 00000000000..6ef946c9697
--- /dev/null
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -0,0 +1,349 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Andrea Weikert (c) 2008 Blender Foundation.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
+#include "BLI_dynstr.h"
+
+#ifdef WIN32
+#include <windows.h> /* need to include windows.h so _WIN32_IE is defined */
+#ifndef _WIN32_IE
+#define _WIN32_IE 0x0400 /* minimal requirements for SHGetSpecialFolderPath on MINGW MSVC has this defined already */
+#endif
+#include <shlobj.h> /* for SHGetSpecialFolderPath, has to be done before BLI_winstuff because 'near' is disabled through BLI_windstuff */
+#include "BLI_winstuff.h"
+#endif
+
+#include "fsmenu.h" /* include ourselves */
+
+
+/* FSMENU HANDLING */
+
+ /* FSMenuEntry's without paths indicate seperators */
+typedef struct _FSMenuEntry FSMenuEntry;
+struct _FSMenuEntry {
+ FSMenuEntry *next;
+
+ char *path;
+ short save;
+ short xs, ys;
+};
+
+typedef struct FSMenu
+{
+ FSMenuEntry *fsmenu_system;
+ FSMenuEntry *fsmenu_bookmarks;
+ FSMenuEntry *fsmenu_recent;
+
+ FSMenuCategory selected_category;
+ int selected_entry;
+
+} FSMenu;
+
+static FSMenu *g_fsmenu = NULL;
+
+struct FSMenu* fsmenu_get(void)
+{
+ if (!g_fsmenu) {
+ g_fsmenu=MEM_callocN(sizeof(struct FSMenu), "fsmenu");
+ }
+ return g_fsmenu;
+}
+
+void fsmenu_select_entry(struct FSMenu* fsmenu, FSMenuCategory category, int index)
+{
+ fsmenu->selected_category = category;
+ fsmenu->selected_entry = index;
+}
+
+int fsmenu_is_selected(struct FSMenu* fsmenu, FSMenuCategory category, int index)
+{
+ return (category==fsmenu->selected_category) && (index==fsmenu->selected_entry);
+}
+
+static FSMenuEntry *fsmenu_get_category(struct FSMenu* fsmenu, FSMenuCategory category)
+{
+ FSMenuEntry *fsms = NULL;
+
+ switch(category) {
+ case FS_CATEGORY_SYSTEM:
+ fsms = fsmenu->fsmenu_system;
+ break;
+ case FS_CATEGORY_BOOKMARKS:
+ fsms = fsmenu->fsmenu_bookmarks;
+ break;
+ case FS_CATEGORY_RECENT:
+ fsms = fsmenu->fsmenu_recent;
+ break;
+ }
+ return fsms;
+}
+
+static void fsmenu_set_category(struct FSMenu* fsmenu, FSMenuCategory category, FSMenuEntry *fsms)
+{
+ switch(category) {
+ case FS_CATEGORY_SYSTEM:
+ fsmenu->fsmenu_system = fsms;
+ break;
+ case FS_CATEGORY_BOOKMARKS:
+ fsmenu->fsmenu_bookmarks = fsms;
+ break;
+ case FS_CATEGORY_RECENT:
+ fsmenu->fsmenu_recent = fsms;
+ break;
+ }
+}
+
+int fsmenu_get_nentries(struct FSMenu* fsmenu, FSMenuCategory category)
+{
+ FSMenuEntry *fsme;
+ int count= 0;
+
+ for (fsme= fsmenu_get_category(fsmenu, category); fsme; fsme= fsme->next)
+ count++;
+
+ return count;
+}
+
+char *fsmenu_get_entry(struct FSMenu* fsmenu, FSMenuCategory category, int idx)
+{
+ FSMenuEntry *fsme;
+
+ for (fsme= fsmenu_get_category(fsmenu, category); fsme && idx; fsme= fsme->next)
+ idx--;
+
+ return fsme?fsme->path:NULL;
+}
+
+void fsmenu_set_pos(struct FSMenu* fsmenu, FSMenuCategory category, int idx, short xs, short ys)
+{
+ FSMenuEntry *fsme;
+
+ for (fsme= fsmenu_get_category(fsmenu, category); fsme && idx; fsme= fsme->next)
+ idx--;
+
+ if (fsme) {
+ fsme->xs = xs;
+ fsme->ys = ys;
+ }
+}
+
+int fsmenu_get_pos (struct FSMenu* fsmenu, FSMenuCategory category, int idx, short* xs, short* ys)
+{
+ FSMenuEntry *fsme;
+
+ for (fsme= fsmenu_get_category(fsmenu, category); fsme && idx; fsme= fsme->next)
+ idx--;
+
+ if (fsme) {
+ *xs = fsme->xs;
+ *ys = fsme->ys;
+ return 1;
+ }
+
+ return 0;
+}
+
+
+void fsmenu_insert_entry(struct FSMenu* fsmenu, FSMenuCategory category, char *path, int sorted, short save)
+{
+ FSMenuEntry *prev;
+ FSMenuEntry *fsme;
+ FSMenuEntry *fsms;
+
+ fsms = fsmenu_get_category(fsmenu, category);
+ prev= fsme= fsms;
+
+ 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;
+ }
+ } else {
+ // if we're bookmarking this, file should come
+ // before the last separator, only automatically added
+ // current dir go after the last sep.
+ if (save) {
+ break;
+ }
+ }
+ }
+
+ fsme= MEM_mallocN(sizeof(*fsme), "fsme");
+ fsme->path= BLI_strdup(path);
+ fsme->save = save;
+
+ if (prev) {
+ fsme->next= prev->next;
+ prev->next= fsme;
+ } else {
+ fsme->next= fsms;
+ fsmenu_set_category(fsmenu, category, fsme);
+ }
+}
+
+void fsmenu_remove_entry(struct FSMenu* fsmenu, FSMenuCategory category, int idx)
+{
+ FSMenuEntry *prev= NULL, *fsme= NULL;
+ FSMenuEntry *fsms = fsmenu_get_category(fsmenu, category);
+
+ for (fsme= fsms; fsme && idx; prev= fsme, fsme= fsme->next)
+ idx--;
+
+ if (fsme) {
+ /* you should only be able to remove entries that were
+ not added by default, like windows drives.
+ also separators (where path == NULL) shouldn't be removed */
+ if (fsme->save && fsme->path) {
+
+ /* remove fsme from list */
+ if (prev) {
+ prev->next= fsme->next;
+ } else {
+ fsms= fsme->next;
+ fsmenu_set_category(fsmenu, category, fsms);
+ }
+ /* free entry */
+ MEM_freeN(fsme->path);
+ MEM_freeN(fsme);
+ }
+ }
+}
+
+void fsmenu_write_file(struct FSMenu* fsmenu, const char *filename)
+{
+ FSMenuEntry *fsme= NULL;
+ int count=FSMENU_RECENT_MAX;
+
+ FILE *fp = fopen(filename, "w");
+ if (!fp) return;
+
+ fprintf(fp, "[Bookmarks]\n");
+ for (fsme= fsmenu_get_category(fsmenu, FS_CATEGORY_BOOKMARKS); fsme; fsme= fsme->next) {
+ if (fsme->path && fsme->save) {
+ fprintf(fp, "%s\n", fsme->path);
+ }
+ }
+ fprintf(fp, "[Recent]\n");
+ for (fsme= fsmenu_get_category(fsmenu, FS_CATEGORY_RECENT); fsme && count; fsme= fsme->next, --count) {
+ if (fsme->path && fsme->save) {
+ fprintf(fp, "%s\n", fsme->path);
+ }
+ }
+ fclose(fp);
+}
+
+void fsmenu_read_file(struct FSMenu* fsmenu, const char *filename)
+{
+ char line[256];
+ FSMenuCategory category = FS_CATEGORY_BOOKMARKS;
+ FILE *fp;
+
+ #ifdef WIN32
+ /* Add the drive names to the listing */
+ {
+ __int64 tmp;
+ char folder[256];
+ 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(fsmenu, FS_CATEGORY_SYSTEM, tmps, 1, 0);
+ }
+ }
+
+ /* Adding Desktop and My Documents */
+ SHGetSpecialFolderPath(0, folder, CSIDL_PERSONAL, 0);
+ fsmenu_insert_entry(fsmenu,FS_CATEGORY_BOOKMARKS, folder, 1, 0);
+ SHGetSpecialFolderPath(0, folder, CSIDL_DESKTOPDIRECTORY, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, folder, 1, 0);
+ }
+#endif
+
+ fp = fopen(filename, "r");
+ if (!fp) return;
+
+ while ( fgets ( line, 256, fp ) != NULL ) /* read a line */
+ {
+ if (strncmp(line, "[Bookmarks]", 11)==0){
+ category = FS_CATEGORY_BOOKMARKS;
+ } else if (strncmp(line, "[Recent]", 8)==0){
+ category = FS_CATEGORY_RECENT;
+ } else {
+ int len = strlen(line);
+ if (len>0) {
+ if (line[len-1] == '\n') {
+ line[len-1] = '\0';
+ }
+ fsmenu_insert_entry(fsmenu, category, line, 0, 1);
+ }
+ }
+ }
+ fclose(fp);
+}
+
+static void fsmenu_free_category(struct FSMenu* fsmenu, FSMenuCategory category)
+{
+ FSMenuEntry *fsme= fsmenu_get_category(fsmenu, category);
+
+ while (fsme) {
+ FSMenuEntry *n= fsme->next;
+
+ if (fsme->path) MEM_freeN(fsme->path);
+ MEM_freeN(fsme);
+
+ fsme= n;
+ }
+}
+
+void fsmenu_free(struct FSMenu* fsmenu)
+{
+ fsmenu_free_category(fsmenu, FS_CATEGORY_SYSTEM);
+ fsmenu_free_category(fsmenu, FS_CATEGORY_BOOKMARKS);
+ fsmenu_free_category(fsmenu, FS_CATEGORY_RECENT);
+ MEM_freeN(fsmenu);
+}
+
diff --git a/source/blender/editors/space_file/fsmenu.h b/source/blender/editors/space_file/fsmenu.h
new file mode 100644
index 00000000000..c51c45b7dc4
--- /dev/null
+++ b/source/blender/editors/space_file/fsmenu.h
@@ -0,0 +1,84 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#ifndef BSE_FSMENU_H
+#define BSE_FSMENU_H
+
+/* XXX could become UserPref */
+#define FSMENU_RECENT_MAX 10
+
+typedef enum FSMenuCategory {
+ FS_CATEGORY_SYSTEM,
+ FS_CATEGORY_BOOKMARKS,
+ FS_CATEGORY_RECENT
+} FSMenuCategory;
+
+struct FSMenu;
+
+struct FSMenu* fsmenu_get (void);
+
+ /** Returns the number of entries in the Fileselect Menu */
+int fsmenu_get_nentries (struct FSMenu* fsmenu, FSMenuCategory category);
+
+ /** Returns the fsmenu entry at @a index (or NULL if a bad index)
+ * or a separator.
+ */
+char* fsmenu_get_entry (struct FSMenu* fsmenu, FSMenuCategory category, int index);
+
+void fsmenu_select_entry (struct FSMenu* fsmenu, FSMenuCategory category, int index);
+
+int fsmenu_is_selected (struct FSMenu* fsmenu, FSMenuCategory category, int index);
+
+ /** Sets the position of the fsmenu entry at @a index */
+void fsmenu_set_pos (struct FSMenu* fsmenu, FSMenuCategory category, int index, short xs, short ys);
+
+ /** Returns the position of the fsmenu entry at @a index. return value is 1 if successful, 0 otherwise */
+int fsmenu_get_pos (struct FSMenu* fsmenu, FSMenuCategory category, int index, short* xs, short* ys);
+
+ /** 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 (struct FSMenu* fsmenu, FSMenuCategory category, char *path, int sorted, short save);
+
+ /** Removes the fsmenu entry at the given @a index. */
+void fsmenu_remove_entry (struct FSMenu* fsmenu, FSMenuCategory category, int index);
+
+ /** saves the 'bookmarks' to the specified file */
+void fsmenu_write_file (struct FSMenu* fsmenu, const char *filename);
+
+ /** reads the 'bookmarks' from the specified file */
+void fsmenu_read_file (struct FSMenu* fsmenu, const char *filename);
+
+ /** Free's all the memory associated with the fsmenu */
+void fsmenu_free (struct FSMenu* fsmenu);
+
+#endif
+
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
new file mode 100644
index 00000000000..084fcf1e5f6
--- /dev/null
+++ b/source/blender/editors/space_file/space_file.c
@@ -0,0 +1,447 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BIF_gl.h"
+
+#include "BLO_readfile.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+#include "ED_fileselect.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_thumbs.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+
+#include "ED_markers.h"
+#include "ED_fileselect.h"
+
+#include "file_intern.h" // own include
+#include "fsmenu.h"
+#include "filelist.h"
+
+/* ******************** default callbacks for file space ***************** */
+
+static SpaceLink *file_new(const bContext *C)
+{
+ ARegion *ar;
+ SpaceFile *sfile;
+
+ sfile= MEM_callocN(sizeof(SpaceFile), "initfile");
+ sfile->spacetype= SPACE_FILE;
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for file");
+ BLI_addtail(&sfile->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_TOP;
+
+ /* channel list region */
+ ar= MEM_callocN(sizeof(ARegion), "channel area for file");
+ BLI_addtail(&sfile->regionbase, ar);
+ ar->regiontype= RGN_TYPE_CHANNELS;
+ ar->alignment= RGN_ALIGN_LEFT;
+
+ /* ui list region */
+ ar= MEM_callocN(sizeof(ARegion), "ui area for file");
+ BLI_addtail(&sfile->regionbase, ar);
+ ar->regiontype= RGN_TYPE_UI;
+ ar->alignment= RGN_ALIGN_TOP;
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for file");
+ BLI_addtail(&sfile->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+ ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
+ ar->v2d.align = (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_POS_Y);
+ ar->v2d.keepzoom = (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_KEEPZOOM|V2D_KEEPASPECT);
+ ar->v2d.keeptot= V2D_KEEPTOT_STRICT;
+ ar->v2d.minzoom= ar->v2d.maxzoom= 1.0f;
+
+ return (SpaceLink *)sfile;
+}
+
+/* not spacelink itself */
+static void file_free(SpaceLink *sl)
+{
+ SpaceFile *sfile= (SpaceFile *) sl;
+
+ if(sfile->files) {
+ filelist_free(sfile->files);
+ MEM_freeN(sfile->files);
+ sfile->files= NULL;
+ }
+
+ if (sfile->params) {
+ if(sfile->params->pupmenu)
+ MEM_freeN(sfile->params->pupmenu);
+ MEM_freeN(sfile->params);
+ sfile->params= NULL;
+ }
+
+ if (sfile->layout) {
+ MEM_freeN(sfile->layout);
+ sfile->layout = NULL;
+ }
+}
+
+
+/* spacetype; init callback, area size changes, screen set, etc */
+static void file_init(struct wmWindowManager *wm, ScrArea *sa)
+{
+}
+
+
+static SpaceLink *file_duplicate(SpaceLink *sl)
+{
+ SpaceFile *sfileo= (SpaceFile*)sl;
+ SpaceFile *sfilen= MEM_dupallocN(sl);
+
+ /* clear or remove stuff from old */
+ sfilen->op = NULL; /* file window doesn't own operators */
+
+ sfilen->files = filelist_new();
+
+ if(sfileo->params) {
+ sfilen->params= MEM_dupallocN(sfileo->params);
+
+ filelist_setdir(sfilen->files, sfilen->params->dir);
+ filelist_settype(sfilen->files, sfilen->params->type);
+ }
+ if (sfileo->layout) {
+ sfilen->layout= MEM_dupallocN(sfileo->layout);
+ }
+ return (SpaceLink *)sfilen;
+}
+
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void file_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "File", SPACE_FILE, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+
+
+}
+
+static void file_main_area_draw(const bContext *C, ARegion *ar)
+{
+ /* draw entirely, view changes should be handled here */
+ SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+ FileSelectParams *params = ED_fileselect_get_params(sfile);
+ FileLayout *layout=NULL;
+
+ View2D *v2d= &ar->v2d;
+ View2DScrollers *scrollers;
+ float col[3];
+
+ if (!sfile->files) {
+ sfile->files = filelist_new();
+ filelist_setdir(sfile->files, params->dir);
+ filelist_settype(sfile->files, params->type);
+ params->active_file = -1; // added this so it opens nicer (ton)
+ }
+
+ layout = ED_fileselect_get_layout(sfile, ar);
+
+ if (filelist_empty(sfile->files))
+ {
+ unsigned int filter = 0;
+ filelist_hidedot(sfile->files, params->flag & FILE_HIDE_DOT);
+ if (params->flag & FILE_FILTER) {
+ filter = params->filter ;
+ } else {
+ filter = 0;
+ }
+
+ filelist_setfilter(sfile->files, filter);
+ filelist_readdir(sfile->files);
+
+ if(params->sort!=FILE_SORTALPHA) filelist_sort(sfile->files, params->sort);
+ }
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* Allow dynamically sliders to be set, saves notifiers etc. */
+ if (layout && (layout->flag == FILE_LAYOUT_VER)) {
+ v2d->scroll = V2D_SCROLL_RIGHT;
+ v2d->keepofs &= ~V2D_LOCKOFS_Y;
+ v2d->keepofs |= V2D_LOCKOFS_X;
+ }
+ else {
+ v2d->scroll = V2D_SCROLL_BOTTOM;
+ v2d->keepofs &= ~V2D_LOCKOFS_X;
+ v2d->keepofs |= V2D_LOCKOFS_Y;
+ }
+ /* v2d has initialized flag, so this call will only set the mask correct */
+ UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+
+ /* sets tile/border settings in sfile */
+ file_calc_previews(C, ar);
+
+ /* set view */
+ UI_view2d_view_ortho(C, v2d);
+
+ /* on first read, find active file */
+ if (params->active_file == -1) {
+ wmEvent *event= CTX_wm_window(C)->eventstate;
+ file_hilight_set(sfile, ar, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin);
+ }
+
+ if (params->display == FILE_IMGDISPLAY) {
+ file_draw_previews(C, ar);
+ } else {
+ file_draw_list(C, ar);
+ }
+
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+
+}
+
+void file_operatortypes(void)
+{
+ WM_operatortype_append(FILE_OT_select);
+ WM_operatortype_append(FILE_OT_select_all_toggle);
+ WM_operatortype_append(FILE_OT_select_border);
+ WM_operatortype_append(FILE_OT_select_bookmark);
+ WM_operatortype_append(FILE_OT_loadimages);
+ WM_operatortype_append(FILE_OT_highlight);
+ WM_operatortype_append(FILE_OT_exec);
+ WM_operatortype_append(FILE_OT_cancel);
+ WM_operatortype_append(FILE_OT_parent);
+ WM_operatortype_append(FILE_OT_refresh);
+ WM_operatortype_append(FILE_OT_bookmark_toggle);
+}
+
+/* NOTE: do not add .blend file reading on this level */
+void file_keymap(struct wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "File", SPACE_FILE, 0);
+ WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "FILE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "FILE_OT_select_border", BKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "FILE_OT_highlight", MOUSEMOVE, KM_ANY, 0, 0);
+ WM_keymap_add_item(keymap, "FILE_OT_parent", PKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "FILE_OT_loadimages", TIMER1, KM_ANY, KM_ANY, 0);
+
+ keymap= WM_keymap_listbase(wm, "FileBookmark", SPACE_FILE, 0);
+ WM_keymap_add_item(keymap, "FILE_OT_select_bookmark", LEFTMOUSE, KM_PRESS, 0, 0);
+}
+
+
+static void file_channel_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "FileBookmark", SPACE_FILE, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, NULL, NULL);
+}
+
+static void file_channel_area_draw(const bContext *C, ARegion *ar)
+{
+ View2D *v2d= &ar->v2d;
+ float col[3];
+
+ UI_GetThemeColor3fv(TH_PANEL, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* data... */
+ UI_view2d_view_ortho(C, v2d);
+
+ file_draw_fsmenu(C, ar);
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void file_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+}
+
+static void file_header_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ /* clear */
+ if(ED_screen_area_active(C))
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ else
+ UI_GetThemeColor3fv(TH_HEADERDESEL, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ file_header_buttons(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void file_ui_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+}
+
+static void file_ui_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+ /* clear */
+ UI_GetThemeColor3fv(TH_PANEL, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ file_draw_buttons(C, ar);
+
+ UI_view2d_view_restore(C);
+}
+
+//static void file_main_area_listener(ARegion *ar, wmNotifier *wmn)
+//{
+ /* context changes */
+//}
+
+/* only called once, from space/spacetypes.c */
+void ED_spacetype_file(void)
+{
+ SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype file");
+ ARegionType *art;
+
+ st->spaceid= SPACE_FILE;
+
+ st->new= file_new;
+ st->free= file_free;
+ st->init= file_init;
+ st->duplicate= file_duplicate;
+ st->operatortypes= file_operatortypes;
+ st->keymap= file_keymap;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype file region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init= file_main_area_init;
+ art->draw= file_main_area_draw;
+ // art->listener= file_main_area_listener;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype file region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+ art->init= file_header_area_init;
+ art->draw= file_header_area_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: ui */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype file region");
+ art->regionid = RGN_TYPE_UI;
+ art->minsizey= 60;
+ art->keymapflag= ED_KEYMAP_UI;
+ art->init= file_ui_area_init;
+ art->draw= file_ui_area_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: channels (directories) */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype file region");
+ art->regionid = RGN_TYPE_CHANNELS;
+ art->minsizex= 240;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+ art->init= file_channel_area_init;
+ art->draw= file_channel_area_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
+
+}
+
+void ED_file_init(void)
+{
+ char name[FILE_MAX];
+ BLI_make_file_string("/", name, BLI_gethome(), ".Bfs");
+ fsmenu_read_file(fsmenu_get(), name);
+ filelist_init_icons();
+ IMB_thumb_makedirs();
+}
+
+void ED_file_exit(void)
+{
+ fsmenu_free(fsmenu_get());
+ filelist_free_icons();
+}
diff --git a/source/blender/editors/space_file/writeimage.c b/source/blender/editors/space_file/writeimage.c
new file mode 100644
index 00000000000..25890953320
--- /dev/null
+++ b/source/blender/editors/space_file/writeimage.c
@@ -0,0 +1,252 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_image_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_texture_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_utildefines.h"
+
+#include "RE_pipeline.h"
+
+#include "file_intern.h"
+
+/* XXX */
+static void error() {}
+static void waitcursor() {}
+static void activate_fileselect() {}
+static int saveover() {return 0;}
+/* XXX */
+
+
+/* ------------------------------------------------------------------------- */
+
+
+void BIF_save_envmap(Scene *scene, EnvMap *env, char *str)
+{
+ ImBuf *ibuf;
+/* extern rectcpy(); */
+ int dx;
+
+ /* all interactive stuff is handled in buttons.c */
+ if(env->cube[0]==NULL) return;
+
+ dx= env->cube[0]->x;
+ ibuf= IMB_allocImBuf(3*dx, 2*dx, 24, IB_rect, 0);
+
+ IMB_rectcpy(ibuf, env->cube[0], 0, 0, 0, 0, dx, dx);
+ IMB_rectcpy(ibuf, env->cube[1], dx, 0, 0, 0, dx, dx);
+ IMB_rectcpy(ibuf, env->cube[2], 2*dx, 0, 0, 0, dx, dx);
+ IMB_rectcpy(ibuf, env->cube[3], 0, dx, 0, 0, dx, dx);
+ IMB_rectcpy(ibuf, env->cube[4], dx, dx, 0, 0, dx, dx);
+ IMB_rectcpy(ibuf, env->cube[5], 2*dx, dx, 0, 0, dx, dx);
+
+ BKE_write_ibuf(scene, ibuf, str, scene->r.imtype, scene->r.subimtype, scene->r.quality);
+ IMB_freeImBuf(ibuf);
+}
+
+
+
+/* callback for fileselect to save rendered image, renderresult was checked to exist */
+static void save_rendered_image_cb_real(char *name, int confirm)
+{
+ Scene *scene= NULL; // XXX
+ char str[FILE_MAXDIR+FILE_MAXFILE];
+ int overwrite;
+
+ if(BLI_testextensie(name,".blend")) {
+ error("Wrong filename");
+ return;
+ }
+
+ /* BKE_add_image_extension() checks for if extension was already set */
+ if(scene->r.scemode & R_EXTENSION)
+ if(strlen(name)<FILE_MAXDIR+FILE_MAXFILE-5)
+ BKE_add_image_extension(scene, name, scene->r.imtype);
+
+ strcpy(str, name);
+ BLI_convertstringcode(str, G.sce);
+ BLI_convertstringframe(str, scene->r.cfra); /* TODO - is this even used? */
+
+ if (confirm)
+ overwrite = saveover(str);
+ else
+ overwrite = 1;
+
+ if(overwrite) {
+ if(scene->r.imtype==R_MULTILAYER) {
+ RenderResult *rr= RE_GetResult(RE_GetRender(scene->id.name));
+ if(rr)
+ RE_WriteRenderResult(rr, str, scene->r.quality);
+ }
+ else {
+ RenderResult rres;
+ ImBuf *ibuf;
+
+ RE_GetResultImage(RE_GetRender(scene->id.name), &rres);
+
+ waitcursor(1); /* from screen.c */
+
+ ibuf= IMB_allocImBuf(rres.rectx, rres.recty, scene->r.planes, 0, 0);
+ ibuf->rect= (unsigned int *)rres.rect32;
+ ibuf->rect_float= rres.rectf;
+ ibuf->zbuf_float= rres.rectz;
+
+ /* float factor for random dither, imbuf takes care of it */
+ ibuf->dither= scene->r.dither_intensity;
+
+ BKE_write_ibuf(scene, ibuf, str, scene->r.imtype, scene->r.subimtype, scene->r.quality);
+ IMB_freeImBuf(ibuf); /* imbuf knows rects are not part of ibuf */
+ }
+
+ strcpy(G.ima, name);
+
+ waitcursor(0);
+ }
+}
+
+
+void save_image_filesel_str(Scene *scene, char *str)
+{
+ switch(scene->r.imtype) {
+ case R_RADHDR:
+ strcpy(str, "Save Radiance HDR");
+ break;
+ case R_FFMPEG:
+ case R_PNG:
+ strcpy(str, "Save PNG");
+ break;
+#ifdef WITH_DDS
+ case R_DDS:
+ strcpy(str, "Save DDS");
+ break;
+#endif
+ case R_BMP:
+ strcpy(str, "Save BMP");
+ break;
+ case R_TIFF:
+ if (G.have_libtiff)
+ strcpy(str, "Save TIFF");
+ break;
+#ifdef WITH_OPENEXR
+ case R_OPENEXR:
+ strcpy(str, "Save OpenEXR");
+ break;
+#endif
+ case R_CINEON:
+ strcpy(str, "Save Cineon");
+ break;
+ case R_DPX:
+ strcpy(str, "Save DPX");
+ break;
+ case R_RAWTGA:
+ strcpy(str, "Save Raw Targa");
+ break;
+ case R_IRIS:
+ strcpy(str, "Save IRIS");
+ break;
+ case R_IRIZ:
+ strcpy(str, "Save IRIS");
+ break;
+ case R_HAMX:
+ strcpy(str, "Save HAMX");
+ break;
+ case R_TARGA:
+ strcpy(str, "Save Targa");
+ break;
+ case R_MULTILAYER:
+ strcpy(str, "Save Multi Layer EXR");
+ break;
+#ifdef WITH_OPENJPEG
+ case R_JP2:
+ strcpy(str, "Save JPEG2000");
+ break;
+#endif
+ /* default we save jpeg, also for all movie formats */
+ case R_JPEG90:
+ case R_MOVIE:
+ case R_AVICODEC:
+ case R_AVIRAW:
+ case R_AVIJPEG:
+ default:
+ strcpy(str, "Save JPEG");
+ break;
+ }
+}
+
+static void save_rendered_image_cb(char *name)
+{
+ save_rendered_image_cb_real(name, 1);
+}
+
+/* no fileselect, no confirm */
+void BIF_save_rendered_image(char *name)
+{
+ save_rendered_image_cb_real(name, 0);
+}
+
+/* calls fileselect */
+void BIF_save_rendered_image_fs(Scene *scene)
+{
+ RenderResult rres;
+
+ RE_GetResultImage(RE_GetRender(scene->id.name), &rres);
+
+ if(!rres.rectf && !rres.rect32) {
+ 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);
+ }
+
+ save_image_filesel_str(scene, str);
+ activate_fileselect(FILE_SPECIAL, str, G.ima, save_rendered_image_cb);
+ }
+}
+
+
diff --git a/source/blender/editors/space_graph/Makefile b/source/blender/editors/space_graph/Makefile
new file mode 100644
index 00000000000..340495ecc79
--- /dev/null
+++ b/source/blender/editors/space_graph/Makefile
@@ -0,0 +1,54 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_graph
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/space_graph/SConscript b/source/blender/editors/space_graph/SConscript
new file mode 100644
index 00000000000..cc9812678e9
--- /dev/null
+++ b/source/blender/editors/space_graph/SConscript
@@ -0,0 +1,9 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+
+env.BlenderLib ( 'bf_editors_space_graph', sources, Split(incs), [], libtype=['core'], priority=[50] )
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
new file mode 100644
index 00000000000..357079a2c3c
--- /dev/null
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -0,0 +1,1015 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation, Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <float.h>
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+
+#include "BKE_animsys.h"
+#include "BKE_action.h"
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
+#include "BKE_object.h"
+#include "BKE_global.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "graph_intern.h" // own include
+
+/* XXX */
+
+/* temporary definition for limits of float number buttons (FLT_MAX tends to infinity with old system) */
+#define UI_FLT_MAX 10000.0f
+
+
+/* ******************* graph editor space & buttons ************** */
+
+#define B_NOP 1
+#define B_REDR 2
+
+/* -------------- */
+
+static void do_graph_region_buttons(bContext *C, void *arg, int event)
+{
+ //Scene *scene= CTX_data_scene(C);
+
+ switch(event) {
+
+ }
+
+ /* default for now */
+ //WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+}
+
+static void graph_panel_properties(const bContext *C, ARegion *ar, short cntrl, bAnimListElem *ale)
+{
+ FCurve *fcu= (FCurve *)ale->data;
+ uiBlock *block;
+ char name[128];
+
+ block= uiBeginBlock(C, ar, "graph_panel_properties", UI_EMBOSS);
+ if (uiNewPanel(C, ar, block, "Properties", "Graph", 340, 30, 318, 254)==0) return;
+ uiBlockSetHandleFunc(block, do_graph_region_buttons, NULL);
+
+ /* to force height */
+ uiNewPanelHeight(block, 204);
+
+ /* Info - Active F-Curve */
+ uiDefBut(block, LABEL, 1, "Active F-Curve:", 10, 200, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
+
+ if (ale->id) {
+ // icon of active blocktype - is this really necessary?
+ int icon= geticon_anim_blocktype(GS(ale->id->name));
+
+ // xxx type of icon-but is currently "LABEL", as that one is plain...
+ uiDefIconBut(block, LABEL, 1, icon, 10, 180, 20, 19, NULL, 0, 0, 0, 0, "ID-type that F-Curve belongs to");
+ }
+
+ getname_anim_fcurve(name, ale->id, fcu);
+ uiDefBut(block, LABEL, 1, name, 30, 180, 300, 19, NULL, 0.0, 0.0, 0, 0, "Name of Active F-Curve");
+
+ /* TODO: the following settings could be added here
+ * - F-Curve coloring mode - mode selector + color selector
+ * - Access details (ID-block + RNA-Path + Array Index)
+ * - ...
+ */
+}
+
+/* ******************* drivers ******************************** */
+
+#define B_IPO_DEPCHANGE 10
+
+static void do_graph_region_driver_buttons(bContext *C, void *arg, int event)
+{
+ Scene *scene= CTX_data_scene(C);
+
+ switch (event) {
+ case B_IPO_DEPCHANGE:
+ {
+ /* rebuild depsgraph for the new deps */
+ DAG_scene_sort(scene);
+
+ /* force an update of depsgraph */
+ ED_anim_dag_flush_update(C);
+ }
+ break;
+ }
+
+ /* default for now */
+ WM_event_add_notifier(C, NC_SCENE, scene);
+}
+
+/* callback to remove the active driver */
+static void driver_remove_cb (bContext *C, void *ale_v, void *dummy_v)
+{
+ bAnimListElem *ale= (bAnimListElem *)ale_v;
+ ID *id= ale->id;
+ FCurve *fcu= ale->data;
+
+ /* try to get F-Curve that driver lives on, and ID block which has this AnimData */
+ if (ELEM(NULL, id, fcu))
+ return;
+
+ /* call API method to remove this driver */
+ ANIM_remove_driver(id, fcu->rna_path, fcu->array_index, 0);
+}
+
+/* callback to add a target variable to the active driver */
+static void driver_add_var_cb (bContext *C, void *driver_v, void *dummy_v)
+{
+ ChannelDriver *driver= (ChannelDriver *)driver_v;
+
+ /* add a new var */
+ driver_add_new_target(driver);
+}
+
+/* callback to remove target variable from active driver */
+static void driver_delete_var_cb (bContext *C, void *driver_v, void *dtar_v)
+{
+ ChannelDriver *driver= (ChannelDriver *)driver_v;
+ DriverTarget *dtar= (DriverTarget *)dtar_v;
+
+ /* add a new var */
+ driver_free_target(driver, dtar);
+}
+
+/* callback to reset the driver's flags */
+static void driver_update_flags_cb (bContext *C, void *fcu_v, void *dummy_v)
+{
+ FCurve *fcu= (FCurve *)fcu_v;
+ ChannelDriver *driver= fcu->driver;
+
+ /* clear invalid flags */
+ driver->flag &= ~DRIVER_FLAG_INVALID;
+}
+
+
+static void graph_panel_drivers(const bContext *C, ARegion *ar, short cntrl, bAnimListElem *ale)
+{
+ FCurve *fcu= (FCurve *)ale->data;
+ ChannelDriver *driver= fcu->driver;
+ DriverTarget *dtar;
+
+ PointerRNA rna_ptr;
+ uiBlock *block;
+ uiBut *but;
+ int yco=85, i=0;
+
+ block= uiBeginBlock(C, ar, "graph_panel_drivers", UI_EMBOSS);
+ if (uiNewPanel(C, ar, block, "Drivers", "Graph", 340, 30, 318, 254)==0) return;
+ uiBlockSetHandleFunc(block, do_graph_region_driver_buttons, NULL);
+
+ /* to force height */
+ uiNewPanelHeight(block, 204);
+
+ /* general actions */
+ but= uiDefBut(block, BUT, B_IPO_DEPCHANGE, "Update Dependencies", 10, 200, 180, 22, NULL, 0.0, 0.0, 0, 0, "Force updates of dependencies");
+ uiButSetFunc(but, driver_update_flags_cb, fcu, NULL);
+
+ but= uiDefBut(block, BUT, B_IPO_DEPCHANGE, "Remove Driver", 200, 200, 110, 18, NULL, 0.0, 0.0, 0, 0, "Remove this driver");
+ uiButSetFunc(but, driver_remove_cb, ale, NULL);
+
+ /* type */
+ uiDefBut(block, LABEL, 1, "Type:", 10, 170, 60, 20, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefButI(block, MENU, B_IPO_DEPCHANGE,
+ "Driver Type%t|Normal%x0|Scripted Expression%x1|Rotational Difference%x2",
+ 70,170,240,20, &driver->type, 0, 0, 0, 0, "Driver type");
+
+ /* show expression box if doing scripted drivers */
+ if (driver->type == DRIVER_TYPE_PYTHON) {
+ uiDefBut(block, TEX, B_REDR, "Expr: ", 10,150,300,20, driver->expression, 0, 255, 0, 0, "One-liner Python Expression to use as Scripted Expression");
+
+ /* errors */
+ if (driver->flag & DRIVER_FLAG_INVALID) {
+ uiDefIconBut(block, LABEL, 1, ICON_ERROR, 10, 130, 48, 48, NULL, 0, 0, 0, 0, ""); // a bit larger
+ uiDefBut(block, LABEL, 0, "Error: invalid Python expression",
+ 50,110,230,19, NULL, 0, 0, 0, 0, "");
+ }
+ }
+ else {
+ /* errors */
+ if (driver->flag & DRIVER_FLAG_INVALID) {
+ uiDefIconBut(block, LABEL, 1, ICON_ERROR, 10, 130, 48, 48, NULL, 0, 0, 0, 0, ""); // a bit larger
+ uiDefBut(block, LABEL, 0, "Error: invalid target channel(s)",
+ 50,130,230,19, NULL, 0, 0, 0, 0, "");
+ }
+ }
+
+ but= uiDefBut(block, BUT, B_IPO_DEPCHANGE, "Add Variable", 10, 110, 300, 20, NULL, 0.0, 0.0, 0, 0, "Add a new target variable for this Driver");
+ uiButSetFunc(but, driver_add_var_cb, driver, NULL);
+
+ /* loop over targets, drawing them */
+ for (dtar= driver->targets.first; dtar; dtar= dtar->next) {
+ short height = (dtar->id) ? 80 : 60;
+
+ /* panel behind buttons */
+ uiDefBut(block, ROUNDBOX, B_REDR, "", 5, yco-height+25, 310, height, NULL, 5.0, 0.0, 12.0, 0, "");
+
+ /* variable name */
+ uiDefButC(block, TEX, B_REDR, "Name: ", 10,yco,280,20, dtar->name, 0, 63, 0, 0, "Name of target variable (No spaces or dots are allowed. Also, must not start with a symbol or digit).");
+
+ /* remove button */
+ but= uiDefIconBut(block, BUT, B_REDR, ICON_X, 290, yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Delete target variable.");
+ uiButSetFunc(but, driver_delete_var_cb, driver, dtar);
+
+
+ /* Target Object */
+ uiDefBut(block, LABEL, 1, "Value:", 10, yco-30, 60, 20, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_REDR, "Ob: ", 70, yco-30, 240, 20, &dtar->id, "Object to use as Driver target");
+
+ // XXX should we hide these technical details?
+ if (dtar->id) {
+ uiBlockBeginAlign(block);
+ /* RNA Path */
+ RNA_pointer_create(ale->id, &RNA_DriverTarget, dtar, &rna_ptr);
+ uiDefButR(block, TEX, 0, "Path: ", 10, yco-50, 250, 20, &rna_ptr, "rna_path", 0, 0, 0, -1, -1, "RNA Path (from Driver Object) to property used as Driver.");
+
+ /* Array Index */
+ uiDefButI(block, NUM, B_REDR, "", 260,yco-50,50,20, &dtar->array_index, 0, INT_MAX, 0, 0, "Index to the specific property used as Driver if applicable.");
+ uiBlockEndAlign(block);
+ }
+
+ /* adjust y-coordinate for next target */
+ yco -= height;
+ i++;
+ }
+
+ /* since these buttons can have variable height */
+ if (yco < 0)
+ uiNewPanelHeight(block, (204 - yco));
+ else
+ uiNewPanelHeight(block, 204);
+}
+
+/* ******************* f-modifiers ******************************** */
+
+#define B_FMODIFIER_REDRAW 20
+
+static void do_graph_region_modifier_buttons(bContext *C, void *arg, int event)
+{
+ switch (event) {
+ case B_REDR:
+ case B_FMODIFIER_REDRAW: // XXX this should send depsgraph updates too
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return; /* no notifier! */
+ }
+}
+
+/* macro for use here to draw background box and set height */
+// XXX for now, roundbox has it's callback func set to NULL to not intercept events
+#define DRAW_BACKDROP(height) \
+ { \
+ uiDefBut(block, ROUNDBOX, B_REDR, "", -3, *yco-height, width+3, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, ""); \
+ }
+
+/* callback to verify modifier data */
+static void validate_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v)
+{
+ FModifier *fcm= (FModifier *)fcm_v;
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+
+ /* call the verify callback on the modifier if applicable */
+ if (fmi && fmi->verify_data)
+ fmi->verify_data(fcm);
+}
+
+/* callback to set the active modifier */
+static void activate_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v)
+{
+ FCurve *fcu= (FCurve *)fcu_v;
+ FModifier *fcm= (FModifier *)fcm_v;
+
+ /* call API function to set the active modifier for active F-Curve */
+ fcurve_set_active_modifier(fcu, fcm);
+}
+
+/* callback to remove the given modifier */
+static void delete_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v)
+{
+ FCurve *fcu= (FCurve *)fcu_v;
+ FModifier *fcm= (FModifier *)fcm_v;
+
+ /* remove the given F-Modifier from the F-Curve */
+ fcurve_remove_modifier(fcu, fcm);
+}
+
+/* --------------- */
+
+/* draw settings for generator modifier */
+static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col)
+{
+ FMod_Generator *data= (FMod_Generator *)fcm->data;
+ char gen_mode[]="Generator Type%t|Expanded Polynomial%x0|Factorised Polynomial%x1|Built-In Function%x2|Expression%x3";
+ char fn_type[]="Built-In Function%t|Sin%x0|Cos%x1|Tan%x2|Square Root%x3|Natural Log%x4";
+ int cy= *yco - 30;
+ uiBut *but;
+
+ /* set the height */
+ (*height) = 90;
+ switch (data->mode) {
+ case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
+ (*height) += 20*(data->poly_order+1) + 20;
+ break;
+ case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */
+ (*height) += 20 * data->poly_order + 15;
+ break;
+ case FCM_GENERATOR_FUNCTION: /* builtin function */
+ (*height) += 55; // xxx
+ break;
+ case FCM_GENERATOR_EXPRESSION: /* py-expression */
+ // xxx nothing to draw
+ break;
+ }
+
+ /* basic settings (backdrop + mode selector + some padding) */
+ DRAW_BACKDROP((*height));
+ uiBlockBeginAlign(block);
+ but= uiDefButS(block, MENU, B_FMODIFIER_REDRAW, gen_mode, 10,cy,width-30,19, &data->mode, 0, 0, 0, 0, "Selects type of generator algorithm.");
+ uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm);
+ cy -= 20;
+
+ uiDefButBitS(block, TOG, FCM_GENERATOR_ADDITIVE, B_FMODIFIER_REDRAW, "Additive", 10,cy,width-30,19, &data->flag, 0, 0, 0, 0, "Values generated by this modifier are applied on top of the existing values instead of overwriting them");
+ cy -= 35;
+ uiBlockEndAlign(block);
+
+ /* now add settings for individual modes */
+ switch (data->mode) {
+ case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
+ {
+ float *cp = NULL;
+ char xval[32];
+ unsigned int i;
+
+ /* draw polynomial order selector */
+ but= uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,cy,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1");
+ uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm);
+ cy -= 35;
+
+ /* draw controls for each coefficient and a + sign at end of row */
+ uiDefBut(block, LABEL, 1, "y = ", 0, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, "");
+
+ cp= data->coefficients;
+ for (i=0; (i < data->arraysize) && (cp); i++, cp++) {
+ /* coefficient */
+ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 50, cy, 150, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient for polynomial");
+
+ /* 'x' param (and '+' if necessary) */
+ if (i == 0)
+ strcpy(xval, "");
+ else if (i == 1)
+ strcpy(xval, "x");
+ else
+ sprintf(xval, "x^%d", i);
+ uiDefBut(block, LABEL, 1, xval, 200, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, "Power of x");
+
+ if ( (i != (data->arraysize - 1)) || ((i==0) && data->arraysize==2) )
+ uiDefBut(block, LABEL, 1, "+", 250, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
+
+ cy -= 20;
+ }
+ }
+ break;
+
+ case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial expression */
+ {
+ float *cp = NULL;
+ unsigned int i;
+
+ /* draw polynomial order selector */
+ but= uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,cy,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1");
+ uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm);
+ cy -= 35;
+
+ /* draw controls for each pair of coefficients */
+ uiDefBut(block, LABEL, 1, "y = ", 0, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, "");
+
+ cp= data->coefficients;
+ for (i=0; (i < data->poly_order) && (cp); i++, cp+=2) {
+ /* opening bracket */
+ uiDefBut(block, LABEL, 1, "(", 40, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, "");
+
+ /* coefficients */
+ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 50, cy, 100, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient of x");
+
+ uiDefBut(block, LABEL, 1, "x + ", 150, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 180, cy, 100, 20, cp+1, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Second coefficient");
+
+ /* closing bracket and '+' sign */
+ if ( (i != (data->poly_order - 1)) || ((i==0) && data->poly_order==2) )
+ uiDefBut(block, LABEL, 1, ") ×", 280, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
+ else
+ uiDefBut(block, LABEL, 1, ")", 280, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
+
+ cy -= 20;
+ }
+ }
+ break;
+
+ case FCM_GENERATOR_FUNCTION: /* built-in function */
+ {
+ float *cp= data->coefficients;
+
+ /* draw function selector */
+ but= uiDefButS(block, MENU, B_FMODIFIER_REDRAW, fn_type, 10,cy,width-30,19, &data->func_type, 0, 0, 0, 0, "Built-In Function to use");
+ uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm);
+ cy -= 35;
+
+ /* draw controls for equation of coefficients */
+ /* row 1 */
+ {
+ uiDefBut(block, LABEL, 1, "y = ", 0, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 50, cy, 150, 20, cp+3, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient (D) for function");
+ uiDefBut(block, LABEL, 1, "+", 200, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
+ cy -= 20;
+ }
+
+ /* row 2 */
+ {
+ char func_name[32];
+
+ /* coefficient outside bracket */
+ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5, cy, 80, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient (A) for function");
+
+ /* opening bracket */
+ switch (data->func_type)
+ {
+ case FCM_GENERATOR_FN_SIN: /* sine wave */
+ sprintf(func_name, "sin(");
+ break;
+ case FCM_GENERATOR_FN_COS: /* cosine wave */
+ sprintf(func_name, "cos(");
+ break;
+ case FCM_GENERATOR_FN_TAN: /* tangent wave */
+ sprintf(func_name, "tan(");
+ break;
+ case FCM_GENERATOR_FN_LN: /* natural log */
+ sprintf(func_name, "ln(");
+ break;
+ case FCM_GENERATOR_FN_SQRT: /* square root */
+ sprintf(func_name, "sqrt(");
+ break;
+ default: /* unknown */
+ sprintf(func_name, "<fn?>(");
+ break;
+ }
+ uiDefBut(block, LABEL, 1, func_name, 85, cy, 40, 20, NULL, 0.0, 0.0, 0, 0, "");
+
+ /* coefficients inside bracket */
+ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 120, cy, 75, 20, cp+1, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient (B) of x");
+
+ uiDefBut(block, LABEL, 1, "x+", 195, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 225, cy, 80, 20, cp+2, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient (C) of function");
+
+ /* closing bracket */
+ uiDefBut(block, LABEL, 1, ")", 300, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
+ cy -= 20;
+ }
+ }
+ break;
+
+ case FCM_GENERATOR_EXPRESSION: /* py-expression */
+ // TODO...
+ break;
+ }
+}
+
+/* --------------- */
+
+/* draw settings for cycles modifier */
+static void draw_modifier__cycles(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col)
+{
+ FMod_Cycles *data= (FMod_Cycles *)fcm->data;
+ char cyc_mode[]="Cycling Mode%t|No Cycles%x0|Repeat Motion%x1|Repeat with Offset%x2";
+ int cy= (*yco - 30), cy1= (*yco - 50), cy2= (*yco - 70);
+
+ /* set the height */
+ (*height) = 80;
+
+ /* basic settings (backdrop + some padding) */
+ DRAW_BACKDROP((*height));
+
+ /* 'before' range */
+ uiDefBut(block, LABEL, 1, "Before:", 4, cy, 80, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling before first keyframe");
+ uiBlockBeginAlign(block);
+ uiDefButS(block, MENU, B_FMODIFIER_REDRAW, cyc_mode, 3,cy1,150,20, &data->before_mode, 0, 0, 0, 0, "Cycling mode to use before first keyframe");
+ uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Max Cycles:", 3, cy2, 150, 20, &data->before_cycles, 0, 10000, 10, 3, "Maximum number of cycles to allow (0 = infinite)");
+ uiBlockEndAlign(block);
+
+ /* 'after' range */
+ uiDefBut(block, LABEL, 1, "After:", 155, cy, 80, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling after last keyframe");
+ uiBlockBeginAlign(block);
+ uiDefButS(block, MENU, B_FMODIFIER_REDRAW, cyc_mode, 157,cy1,150,20, &data->after_mode, 0, 0, 0, 0, "Cycling mode to use after first keyframe");
+ uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Max Cycles:", 157, cy2, 150, 20, &data->after_cycles, 0, 10000, 10, 3, "Maximum number of cycles to allow (0 = infinite)");
+ uiBlockEndAlign(block);
+}
+
+/* --------------- */
+
+#define BINARYSEARCH_FRAMEEQ_THRESH 0.0001
+
+/* Binary search algorithm for finding where to insert Envelope Data Point.
+ * Returns the index to insert at (data already at that index will be offset if replace is 0)
+ */
+static int binarysearch_fcm_envelopedata_index (FCM_EnvelopeData array[], float frame, int arraylen, short *exists)
+{
+ int start=0, end=arraylen;
+ int loopbreaker= 0, maxloop= arraylen * 2;
+
+ /* initialise exists-flag first */
+ *exists= 0;
+
+ /* sneaky optimisations (don't go through searching process if...):
+ * - keyframe to be added is to be added out of current bounds
+ * - keyframe to be added would replace one of the existing ones on bounds
+ */
+ if ((arraylen <= 0) || (array == NULL)) {
+ printf("Warning: binarysearch_fcm_envelopedata_index() encountered invalid array \n");
+ return 0;
+ }
+ else {
+ /* check whether to add before/after/on */
+ float framenum;
+
+ /* 'First' Point (when only one point, this case is used) */
+ framenum= array[0].time;
+ if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
+ *exists = 1;
+ return 0;
+ }
+ else if (frame < framenum)
+ return 0;
+
+ /* 'Last' Point */
+ framenum= array[(arraylen-1)].time;
+ if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
+ *exists= 1;
+ return (arraylen - 1);
+ }
+ else if (frame > framenum)
+ return arraylen;
+ }
+
+
+ /* most of the time, this loop is just to find where to put it
+ * - 'loopbreaker' is just here to prevent infinite loops
+ */
+ for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
+ /* compute and get midpoint */
+ int mid = start + ((end - start) / 2); /* we calculate the midpoint this way to avoid int overflows... */
+ float midfra= array[mid].time;
+
+ /* check if exactly equal to midpoint */
+ if (IS_EQT(frame, midfra, BINARYSEARCH_FRAMEEQ_THRESH)) {
+ *exists = 1;
+ return mid;
+ }
+
+ /* repeat in upper/lower half */
+ if (frame > midfra)
+ start= mid + 1;
+ else if (frame < midfra)
+ end= mid - 1;
+ }
+
+ /* print error if loop-limit exceeded */
+ if (loopbreaker == (maxloop-1)) {
+ printf("Error: binarysearch_fcm_envelopedata_index() was taking too long \n");
+
+ // include debug info
+ printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen);
+ }
+
+ /* not found, so return where to place it */
+ return start;
+}
+
+/* callback to add new envelope data point */
+// TODO: should we have a separate file for things like this?
+static void fmod_envelope_addpoint_cb (bContext *C, void *fcm_dv, void *dummy)
+{
+ Scene *scene= CTX_data_scene(C);
+ FMod_Envelope *env= (FMod_Envelope *)fcm_dv;
+ FCM_EnvelopeData *fedn;
+ FCM_EnvelopeData fed;
+
+ /* init template data */
+ fed.min= -1.0f;
+ fed.max= 1.0f;
+ fed.time= (float)scene->r.cfra; // XXX make this int for ease of use?
+ fed.f1= fed.f2= 0;
+
+ /* check that no data exists for the current frame... */
+ if (env->data) {
+ short exists = -1;
+ int i= binarysearch_fcm_envelopedata_index(env->data, (float)(scene->r.cfra), env->totvert, &exists);
+
+ /* binarysearch_...() will set exists by default to 0, so if it is non-zero, that means that the point exists already */
+ if (exists)
+ return;
+
+ /* add new */
+ fedn= MEM_callocN((env->totvert+1)*sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
+
+ /* add the points that should occur before the point to be pasted */
+ if (i > 0)
+ memcpy(fedn, env->data, i*sizeof(FCM_EnvelopeData));
+
+ /* add point to paste at index i */
+ *(fedn + i)= fed;
+
+ /* add the points that occur after the point to be pasted */
+ if (i < env->totvert)
+ memcpy(fedn+i+1, env->data+i, (env->totvert-i)*sizeof(FCM_EnvelopeData));
+
+ /* replace (+ free) old with new */
+ MEM_freeN(env->data);
+ env->data= fedn;
+
+ env->totvert++;
+ }
+ else {
+ env->data= MEM_callocN(sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
+ *(env->data)= fed;
+
+ env->totvert= 1;
+ }
+}
+
+/* callback to remove envelope data point */
+// TODO: should we have a separate file for things like this?
+static void fmod_envelope_deletepoint_cb (bContext *C, void *fcm_dv, void *ind_v)
+{
+ FMod_Envelope *env= (FMod_Envelope *)fcm_dv;
+ FCM_EnvelopeData *fedn;
+ int index= GET_INT_FROM_POINTER(ind_v);
+
+ /* check that no data exists for the current frame... */
+ if (env->totvert > 1) {
+ /* allocate a new smaller array */
+ fedn= MEM_callocN(sizeof(FCM_EnvelopeData)*(env->totvert-1), "FCM_EnvelopeData");
+
+ memcpy(fedn, &env->data, sizeof(FCM_EnvelopeData)*(index));
+ memcpy(&fedn[index], &env->data[index+1], sizeof(FCM_EnvelopeData)*(env->totvert-index-1));
+
+ /* free old array, and set the new */
+ MEM_freeN(env->data);
+ env->data= fedn;
+ env->totvert--;
+ }
+ else {
+ /* just free array, since the only vert was deleted */
+ if (env->data)
+ MEM_freeN(env->data);
+ env->totvert= 0;
+ }
+}
+
+/* draw settings for envelope modifier */
+static void draw_modifier__envelope(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col)
+{
+ FMod_Envelope *env= (FMod_Envelope *)fcm->data;
+ FCM_EnvelopeData *fed;
+ uiBut *but;
+ int cy= (*yco - 28);
+ int i;
+
+ /* set the height:
+ * - basic settings + variable height from envelope controls
+ */
+ (*height) = 115 + (35 * env->totvert);
+
+ /* basic settings (backdrop + general settings + some padding) */
+ DRAW_BACKDROP((*height));
+
+ /* General Settings */
+ uiDefBut(block, LABEL, 1, "Envelope:", 10, cy, 100, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling before first keyframe");
+ cy -= 20;
+
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Reference Val:", 10, cy, 300, 20, &env->midval, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "");
+ cy -= 20;
+
+ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Min:", 10, cy, 150, 20, &env->min, -UI_FLT_MAX, env->max, 10, 3, "Minimum value (relative to Reference Value) that is used as the 'normal' minimum value");
+ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Max:", 160, cy, 150, 20, &env->max, env->min, UI_FLT_MAX, 10, 3, "Maximum value (relative to Reference Value) that is used as the 'normal' maximum value");
+ cy -= 35;
+ uiBlockEndAlign(block);
+
+
+ /* Points header */
+ uiDefBut(block, LABEL, 1, "Control Points:", 10, cy, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
+
+ but= uiDefBut(block, BUT, B_FMODIFIER_REDRAW, "Add Point", 160,cy,150,19, NULL, 0, 0, 0, 0, "Adds a new control-point to the envelope on the current frame");
+ uiButSetFunc(but, fmod_envelope_addpoint_cb, env, NULL);
+ cy -= 35;
+
+ /* Points List */
+ for (i=0, fed=env->data; i < env->totvert; i++, fed++) {
+ uiBlockBeginAlign(block);
+ but=uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Fra:", 2, cy, 90, 20, &fed->time, -UI_FLT_MAX, UI_FLT_MAX, 10, 1, "Frame that envelope point occurs");
+ uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm);
+
+ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Min:", 92, cy, 100, 20, &fed->min, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Minimum bound of envelope at this point");
+ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Max:", 192, cy, 100, 20, &fed->max, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Maximum bound of envelope at this point");
+
+ but= uiDefIconBut(block, BUT, B_FMODIFIER_REDRAW, ICON_X, 292, cy, 18, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Delete envelope control point");
+ uiButSetFunc(but, fmod_envelope_deletepoint_cb, env, SET_INT_IN_POINTER(i));
+ uiBlockBeginAlign(block);
+ cy -= 25;
+ }
+}
+
+/* --------------- */
+
+/* draw settings for limits modifier */
+static void draw_modifier__limits(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col)
+{
+ FMod_Limits *data= (FMod_Limits *)fcm->data;
+ const int togButWidth = 50;
+ const int textButWidth = ((width/2)-togButWidth);
+
+ /* set the height */
+ (*height) = 60;
+
+ /* basic settings (backdrop + some padding) */
+ DRAW_BACKDROP((*height));
+
+ /* Draw Pairs of LimitToggle+LimitValue */
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOGBUT, FCM_LIMIT_XMIN, B_FMODIFIER_REDRAW, "xMin", 5, *yco-30, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x value");
+ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+togButWidth, *yco-30, (textButWidth-5), 18, &data->rect.xmin, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Lowest x value to allow");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOGBUT, FCM_LIMIT_XMAX, B_FMODIFIER_REDRAW, "XMax", 5+(width-(textButWidth-5)-togButWidth), *yco-30, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum x value");
+ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+(width-textButWidth-5), *yco-30, (textButWidth-5), 18, &data->rect.xmax, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Highest x value to allow");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOGBUT, FCM_LIMIT_YMIN, B_FMODIFIER_REDRAW, "yMin", 5, *yco-52, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum y value");
+ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+togButWidth, *yco-52, (textButWidth-5), 18, &data->rect.ymin, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Lowest y value to allow");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOGBUT, FCM_LIMIT_YMAX, B_FMODIFIER_REDRAW, "YMax", 5+(width-(textButWidth-5)-togButWidth), *yco-52, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum y value");
+ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+(width-textButWidth-5), *yco-52, (textButWidth-5), 18, &data->rect.ymax, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Highest y value to allow");
+ uiBlockEndAlign(block);
+}
+
+/* --------------- */
+
+static void graph_panel_modifier_draw(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco)
+{
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+ uiBut *but;
+ short active= (fcm->flag & FMODIFIER_FLAG_ACTIVE);
+ short width= 314;
+ short height = 0;
+ int rb_col;
+
+ /* draw header */
+ {
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+
+ /* rounded header */
+ rb_col= (active)?-20:20;
+ but= uiDefBut(block, ROUNDBOX, B_REDR, "", 0, *yco-2, width, 24, NULL, 5.0, 0.0, 15.0, (float)(rb_col-20), "");
+
+ /* expand */
+ uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_EXPANDED, B_REDR, ICON_TRIA_RIGHT, 5, *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is expanded");
+
+ /* checkbox for 'active' status (for now) */
+ but= uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_ACTIVE, B_REDR, ICON_RADIOBUT_OFF, 25, *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is active one");
+ uiButSetFunc(but, activate_fmodifier_cb, fcu, fcm);
+
+ /* name */
+ if (fmi)
+ but= uiDefBut(block, LABEL, 1, fmi->name, 10+40, *yco, 240, 20, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one.");
+ else
+ but= uiDefBut(block, LABEL, 1, "<Unknown Modifier>", 10+40, *yco, 240, 20, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one.");
+
+ /* delete button */
+ but= uiDefIconBut(block, BUT, B_REDR, ICON_X, 10+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete F-Curve Modifier.");
+ uiButSetFunc(but, delete_fmodifier_cb, fcu, fcm);
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ }
+
+ /* when modifier is expanded, draw settings */
+ if (fcm->flag & FMODIFIER_FLAG_EXPANDED) {
+ /* draw settings for individual modifiers */
+ switch (fcm->type) {
+ case FMODIFIER_TYPE_GENERATOR: /* Generator */
+ draw_modifier__generator(block, fcu, fcm, yco, &height, width, active, rb_col);
+ break;
+
+ case FMODIFIER_TYPE_CYCLES: /* Cycles */
+ draw_modifier__cycles(block, fcu, fcm, yco, &height, width, active, rb_col);
+ break;
+
+ case FMODIFIER_TYPE_ENVELOPE: /* Envelope */
+ draw_modifier__envelope(block, fcu, fcm, yco, &height, width, active, rb_col);
+ break;
+
+ case FMODIFIER_TYPE_LIMITS: /* Limits */
+ draw_modifier__limits(block, fcu, fcm, yco, &height, width, active, rb_col);
+ break;
+
+ default: /* unknown type */
+ height= 96;
+ //DRAW_BACKDROP(height); // XXX buggy...
+ break;
+ }
+ }
+
+ /* adjust height for new to start */
+ (*yco) -= (height + 27);
+}
+
+static void graph_panel_modifiers(const bContext *C, ARegion *ar, short cntrl, bAnimListElem *ale)
+{
+ FCurve *fcu= (FCurve *)ale->data;
+ FModifier *fcm;
+ uiBlock *block;
+ int yco= 190;
+
+ block= uiBeginBlock(C, ar, "graph_panel_modifiers", UI_EMBOSS);
+ if (uiNewPanel(C, ar, block, "Modifiers", "Graph", 340, 30, 318, 254)==0) return;
+ uiBlockSetHandleFunc(block, do_graph_region_modifier_buttons, NULL);
+
+ uiNewPanelHeight(block, 204);
+
+ /* 'add modifier' button at top of panel */
+ // XXX for now, this will be a operator button which calls a temporary 'add modifier' operator
+ uiDefButO(block, BUT, "GRAPHEDIT_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, "Add Modifier", 10, 225, 150, 20, "Adds a new F-Curve Modifier for the active F-Curve");
+
+ /* draw each modifier */
+ for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next)
+ graph_panel_modifier_draw(block, fcu, fcm, &yco);
+
+ /* since these buttons can have variable height */
+ if (yco < 0)
+ uiNewPanelHeight(block, (204 - yco));
+ else
+ uiNewPanelHeight(block, 204);
+}
+
+/* ******************* general ******************************** */
+
+/* Find 'active' F-Curve. It must be editable, since that's the purpose of these buttons (subject to change).
+ * We return the 'wrapper' since it contains valuable context info (about hierarchy), which will need to be freed
+ * when the caller is done with it.
+ */
+// TODO: move this to anim api with another name?
+bAnimListElem *get_active_fcurve_channel (bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ int filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ACTIVE | ANIMFILTER_CURVESONLY);
+ int items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* We take the first F-Curve only, since some other ones may have had 'active' flag set
+ * if they were from linked data.
+ */
+ if (items) {
+ bAnimListElem *ale= (bAnimListElem *)anim_data.first;
+
+ /* remove first item from list, then free the rest of the list and return the stored one */
+ BLI_remlink(&anim_data, ale);
+ BLI_freelistN(&anim_data);
+
+ return ale;
+ }
+
+ /* no active F-Curve */
+ return NULL;
+}
+
+void graph_region_buttons(const bContext *C, ARegion *ar)
+{
+ SpaceIpo *sipo= (SpaceIpo *)CTX_wm_space_data(C);
+ bAnimContext ac;
+ bAnimListElem *ale= NULL;
+
+ /* for now, only draw if we could init the anim-context info (necessary for all animation-related tools)
+ * to work correctly is able to be correctly retrieved. There's no point showing empty panels?
+ */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+
+
+ /* try to find 'active' F-Curve */
+ ale= get_active_fcurve_channel(&ac);
+ if (ale == NULL)
+ return;
+
+ uiBeginPanels(C, ar);
+
+ /* for now, the properties panel displays info about the selected channels */
+ graph_panel_properties(C, ar, 0, ale);
+
+ /* driver settings for active F-Curve (only for 'Drivers' mode) */
+ if (sipo->mode == SIPO_MODE_DRIVERS)
+ graph_panel_drivers(C, ar, 0, ale);
+
+ /* modifiers */
+ graph_panel_modifiers(C, ar, 0, ale);
+
+
+ uiEndPanels(C, ar);
+
+ /* free temp data */
+ MEM_freeN(ale);
+}
+
+
+static int graph_properties(bContext *C, wmOperator *op)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= graph_has_buttons_region(sa);
+
+ if(ar) {
+ ar->flag ^= RGN_FLAG_HIDDEN;
+ ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */
+
+ ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
+ ED_area_tag_redraw(sa);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_properties(wmOperatorType *ot)
+{
+ ot->name= "Properties";
+ ot->idname= "GRAPHEDIT_OT_properties";
+
+ ot->exec= graph_properties;
+ ot->poll= ED_operator_ipo_active; // xxx
+
+ /* flags */
+ ot->flag= 0;
+}
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
new file mode 100644
index 00000000000..6f33a5dd682
--- /dev/null
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -0,0 +1,1397 @@
+/**
+ * $Id: drawipo.c 17512 2008-11-20 05:55:42Z aligorith $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation
+ *
+ * Contributor(s): Joshua Leung (2009 Recode)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <float.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_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 "DNA_userdef_types.h"
+#include "DNA_view2d_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
+#include "BKE_global.h"
+#include "BKE_key.h"
+#include "BKE_object.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "ED_anim_api.h"
+#include "ED_util.h"
+
+#include "graph_intern.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+/* XXX */
+extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);
+
+/* *************************** */
+/* F-Curve Modifier Drawing */
+
+/* Envelope -------------- */
+
+// TODO: draw a shaded poly showing the region of influence too!!!
+static void draw_fcurve_modifier_controls_envelope (FCurve *fcu, FModifier *fcm, View2D *v2d)
+{
+ FMod_Envelope *env= (FMod_Envelope *)fcm->data;
+ FCM_EnvelopeData *fed;
+ const float fac= 0.05f * (v2d->cur.xmax - v2d->cur.xmin);
+ int i;
+
+ /* draw two black lines showing the standard reference levels */
+ glColor3f(0.0f, 0.0f, 0.0f);
+ setlinestyle(5);
+
+ glBegin(GL_LINES);
+ glVertex2f(v2d->cur.xmin, env->midval+env->min);
+ glVertex2f(v2d->cur.xmax, env->midval+env->min);
+
+ glVertex2f(v2d->cur.xmin, env->midval+env->max);
+ glVertex2f(v2d->cur.xmax, env->midval+env->max);
+ glEnd(); // GL_LINES
+ setlinestyle(0);
+
+ /* set size of vertices (non-adjustable for now) */
+ glPointSize(2.0f);
+
+ // for now, point color is fixed, and is white
+ glColor3f(1.0f, 1.0f, 1.0f);
+
+ /* we use bgl points not standard gl points, to workaround vertex
+ * drawing bugs that some drivers have (probably legacy ones only though)
+ */
+ bglBegin(GL_POINTS);
+ for (i=0, fed=env->data; i < env->totvert; i++, fed++) {
+ /* only draw if visible
+ * - min/max here are fixed, not relative
+ */
+ if IN_RANGE(fed->time, (v2d->cur.xmin - fac), (v2d->cur.xmax + fac)) {
+ glVertex2f(fed->time, fed->min);
+ glVertex2f(fed->time, fed->max);
+ }
+ }
+ bglEnd();
+
+ glPointSize(1.0f);
+}
+
+/* *************************** */
+/* F-Curve Drawing */
+
+/* Points ---------------- */
+
+/* helper func - draw keyframe vertices only for an F-Curve */
+static void draw_fcurve_vertices_keyframes (FCurve *fcu, View2D *v2d, short edit, short sel)
+{
+ BezTriple *bezt= fcu->bezt;
+ const float fac= 0.05f * (v2d->cur.xmax - v2d->cur.xmin);
+ int i;
+
+ /* we use bgl points not standard gl points, to workaround vertex
+ * drawing bugs that some drivers have (probably legacy ones only though)
+ */
+ bglBegin(GL_POINTS);
+
+ for (i = 0; i < fcu->totvert; i++, bezt++) {
+ /* as an optimisation step, only draw those in view
+ * - we apply a correction factor to ensure that points don't pop in/out due to slight twitches of view size
+ */
+ if IN_RANGE(bezt->vec[1][0], (v2d->cur.xmin - fac), (v2d->cur.xmax + fac)) {
+ if (edit) {
+ /* 'Keyframe' vertex only, as handle lines and handles have already been drawn
+ * - only draw those with correct selection state for the current drawing color
+ * -
+ */
+ if ((bezt->f2 & SELECT) == sel)
+ bglVertex3fv(bezt->vec[1]);
+ }
+ else {
+ /* no check for selection here, as curve is not editable... */
+ // XXX perhaps we don't want to even draw points? maybe add an option for that later
+ bglVertex3fv(bezt->vec[1]);
+ }
+ }
+ }
+
+ bglEnd();
+}
+
+
+/* helper func - draw handle vertex for an F-Curve as a round unfilled circle */
+static void draw_fcurve_handle_control (float x, float y, float xscale, float yscale, float hsize)
+{
+ static GLuint displist=0;
+
+ /* initialise round circle shape */
+ if (displist == 0) {
+ GLUquadricObj *qobj;
+
+ displist= glGenLists(1);
+ glNewList(displist, GL_COMPILE);
+
+ qobj = gluNewQuadric();
+ gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
+ gluDisk(qobj, 0, 0.7, 8, 1);
+ gluDeleteQuadric(qobj);
+
+ glEndList();
+ }
+
+ /* adjust view transform before starting */
+ glTranslatef(x, y, 0.0f);
+ glScalef(1.0f/xscale*hsize, 1.0f/yscale*hsize, 1.0f);
+
+ /* anti-aliased lines for more consistent appearance */
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+
+ /* draw! */
+ glCallList(displist);
+
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+
+ /* restore view transform */
+ glScalef(xscale/hsize, yscale/hsize, 1.0);
+ glTranslatef(-x, -y, 0.0f);
+}
+
+/* helper func - draw handle vertices only for an F-Curve (if it is not protected) */
+static void draw_fcurve_vertices_handles (FCurve *fcu, View2D *v2d, short sel)
+{
+ BezTriple *bezt= fcu->bezt;
+ BezTriple *prevbezt = NULL;
+ float hsize, xscale, yscale;
+ int i;
+
+ /* get view settings */
+ hsize= UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE);
+ UI_view2d_getscale(v2d, &xscale, &yscale);
+
+ /* set handle color */
+ if (sel) UI_ThemeColor(TH_HANDLE_VERTEX_SELECT);
+ else UI_ThemeColor(TH_HANDLE_VERTEX);
+
+ for (i=0; i < fcu->totvert; i++, prevbezt=bezt, bezt++) {
+ /* Draw the editmode handels for a bezier curve (others don't have handles)
+ * if their selection status matches the selection status we're drawing for
+ * - first handle only if previous beztriple was bezier-mode
+ * - second handle only if current beztriple is bezier-mode
+ */
+ if ( (!prevbezt && (bezt->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ)) ) {
+ if ((bezt->f1 & SELECT) == sel)/* && v2d->cur.xmin < bezt->vec[0][0] < v2d->cur.xmax)*/
+ draw_fcurve_handle_control(bezt->vec[0][0], bezt->vec[0][1], xscale, yscale, hsize);
+ }
+
+ if (bezt->ipo==BEZT_IPO_BEZ) {
+ if ((bezt->f3 & SELECT) == sel)/* && v2d->cur.xmin < bezt->vec[2][0] < v2d->cur.xmax)*/
+ draw_fcurve_handle_control(bezt->vec[2][0], bezt->vec[2][1], xscale, yscale, hsize);
+ }
+ }
+}
+
+/* helper func - set color to draw F-Curve data with */
+static void set_fcurve_vertex_color (SpaceIpo *sipo, FCurve *fcu, short sel)
+{
+#if 0
+ if (sipo->showkey) {
+ if (sel) UI_ThemeColor(TH_TEXT_HI);
+ else UI_ThemeColor(TH_TEXT);
+ }
+#endif
+ if ((fcu->flag & FCURVE_PROTECTED)==0) {
+ /* Curve's points are being edited */
+ if (sel) UI_ThemeColor(TH_VERTEX_SELECT);
+ else UI_ThemeColor(TH_VERTEX);
+ }
+ else {
+ /* Curve's points cannot be edited */
+ if (sel) UI_ThemeColor(TH_TEXT_HI);
+ else UI_ThemeColor(TH_TEXT);
+ }
+}
+
+
+void draw_fcurve_vertices (SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
+{
+ View2D *v2d= &ar->v2d;
+
+ /* only draw points if curve is visible
+ * - draw unselected points before selected points as separate passes to minimise color-changing overhead
+ * (XXX dunno if this is faster than drawing all in one pass though)
+ * and also to make sure in the case of overlapping points that the selected is always visible
+ * - draw handles before keyframes, so that keyframes will overlap handles (keyframes are more important for users)
+ */
+
+ glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+
+ /* draw the two handles first (if they're shown, and if curve is being edited) */
+ if ((fcu->flag & FCURVE_PROTECTED)==0 && (fcu->flag & FCURVE_INT_VALUES)==0 && (sipo->flag & SIPO_NOHANDLES)==0) {
+ set_fcurve_vertex_color(sipo, fcu, 0);
+ draw_fcurve_vertices_handles(fcu, v2d, 0);
+
+ set_fcurve_vertex_color(sipo, fcu, 1);
+ draw_fcurve_vertices_handles(fcu, v2d, 1);
+ }
+
+ /* draw keyframes over the handles */
+ set_fcurve_vertex_color(sipo, fcu, 0);
+ draw_fcurve_vertices_keyframes(fcu, v2d, !(fcu->flag & FCURVE_PROTECTED), 0);
+
+ set_fcurve_vertex_color(sipo, fcu, 1);
+ draw_fcurve_vertices_keyframes(fcu, v2d, !(fcu->flag & FCURVE_PROTECTED), 1);
+
+ glPointSize(1.0f);
+}
+
+/* Handles ---------------- */
+
+/* draw lines for F-Curve handles only (this is only done in EditMode) */
+static void draw_fcurve_handles (SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
+{
+ extern unsigned int nurbcol[];
+ unsigned int *col;
+ int sel, b;
+
+ /* don't draw handle lines if handles are not shown */
+ if ((sipo->flag & SIPO_NOHANDLES) || (fcu->flag & FCURVE_PROTECTED) || (fcu->flag & FCURVE_INT_VALUES))
+ return;
+
+ /* slightly hacky, but we want to draw unselected points before selected ones*/
+ for (sel= 0; sel < 2; sel++) {
+ BezTriple *bezt=fcu->bezt, *prevbezt=NULL;
+ float *fp;
+
+ if (sel) col= nurbcol+4;
+ else col= nurbcol;
+
+ for (b= 0; b < fcu->totvert; b++, prevbezt=bezt, bezt++) {
+ if ((bezt->f2 & SELECT)==sel) {
+ fp= bezt->vec[0];
+
+ /* only draw first handle if previous segment had handles */
+ if ( (!prevbezt && (bezt->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ)) )
+ {
+ cpack(col[(unsigned char)bezt->h1]);
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(fp); glVertex2fv(fp+3);
+ glEnd();
+
+ }
+
+ /* only draw second handle if this segment is bezier */
+ if (bezt->ipo == BEZT_IPO_BEZ)
+ {
+ cpack(col[(unsigned char)bezt->h2]);
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(fp+3); glVertex2fv(fp+6);
+ glEnd();
+ }
+ }
+ else {
+ /* only draw first handle if previous segment was had handles, and selection is ok */
+ if ( ((bezt->f1 & SELECT)==sel) &&
+ ( (!prevbezt && (bezt->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ)) ) )
+ {
+ fp= bezt->vec[0];
+ cpack(col[(unsigned char)bezt->h1]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(fp); glVertex2fv(fp+3);
+ glEnd();
+ }
+
+ /* only draw second handle if this segment is bezier, and selection is ok */
+ if ( ((bezt->f3 & SELECT)==sel) &&
+ (bezt->ipo == BEZT_IPO_BEZ) )
+ {
+ fp= bezt->vec[1];
+ cpack(col[(unsigned char)bezt->h2]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(fp); glVertex2fv(fp+3);
+ glEnd();
+ }
+ }
+ }
+ }
+}
+
+/* Samples ---------------- */
+
+/* helper func - draw sample-range marker for an F-Curve as a cross */
+static void draw_fcurve_sample_control (float x, float y, float xscale, float yscale, float hsize)
+{
+ static GLuint displist=0;
+
+ /* initialise X shape */
+ if (displist == 0) {
+ displist= glGenLists(1);
+ glNewList(displist, GL_COMPILE);
+
+ glBegin(GL_LINES);
+ glVertex2f(-0.7f, -0.7f);
+ glVertex2f(+0.7f, +0.7f);
+
+ glVertex2f(-0.7f, +0.7f);
+ glVertex2f(+0.7f, -0.7f);
+ glEnd(); // GL_LINES
+
+ glEndList();
+ }
+
+ /* adjust view transform before starting */
+ glTranslatef(x, y, 0.0f);
+ glScalef(1.0f/xscale*hsize, 1.0f/yscale*hsize, 1.0f);
+
+ /* anti-aliased lines for more consistent appearance */
+ // XXX needed here?
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+
+ /* draw! */
+ glCallList(displist);
+
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
+
+ /* restore view transform */
+ glScalef(xscale/hsize, yscale/hsize, 1.0);
+ glTranslatef(-x, -y, 0.0f);
+}
+
+/* helper func - draw keyframe vertices only for an F-Curve */
+static void draw_fcurve_samples (SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
+{
+ FPoint *first, *last;
+ float hsize, xscale, yscale;
+
+ /* get view settings */
+ hsize= UI_GetThemeValuef(TH_VERTEX_SIZE);
+ UI_view2d_getscale(&ar->v2d, &xscale, &yscale);
+
+ /* set vertex color */
+ if (fcu->flag & (FCURVE_ACTIVE|FCURVE_SELECTED)) UI_ThemeColor(TH_TEXT_HI);
+ else UI_ThemeColor(TH_TEXT);
+
+ /* get verts */
+ first= fcu->fpt;
+ last= (first) ? (first + (fcu->totvert-1)) : (NULL);
+
+ /* draw */
+ if (first && last) {
+ draw_fcurve_sample_control(first->vec[0], first->vec[1], xscale, yscale, hsize);
+ draw_fcurve_sample_control(last->vec[0], last->vec[1], xscale, yscale, hsize);
+ }
+}
+
+/* Curve ---------------- */
+
+/* minimum pixels per gridstep
+ * XXX: defined in view2d.c - must keep these in sync or relocate to View2D header!
+ */
+#define MINGRIDSTEP 35
+
+/* helper func - just draw the F-Curve by sampling the visible region (for drawing curves with modifiers) */
+static void draw_fcurve_curve (FCurve *fcu, SpaceIpo *sipo, View2D *v2d, View2DGrid *grid)
+{
+ ChannelDriver *driver;
+ float samplefreq, ctime;
+ float stime, etime;
+
+ /* disable any drivers temporarily */
+ driver= fcu->driver;
+ fcu->driver= NULL;
+
+
+ /* Note about sampling frequency:
+ * Ideally, this is chosen such that we have 1-2 pixels = 1 segment
+ * which means that our curves can be as smooth as possible. However,
+ * this does mean that curves may not be fully accurate (i.e. if they have
+ * sudden spikes which happen at the sampling point, we may have problems).
+ * Also, this may introduce lower performance on less densely detailed curves,'
+ * though it is impossible to predict this from the modifiers!
+ *
+ * If the automatically determined sampling frequency is likely to cause an infinite
+ * loop (i.e. too close to FLT_EPSILON), fall back to default of 0.001
+ */
+ /* grid->dx is the first float in View2DGrid struct, so just cast to float pointer, and use it
+ * It represents the number of 'frames' between gridlines, but we divide by MINGRIDSTEP to get pixels-steps
+ */
+ // TODO: perhaps we should have 1.0 frames as upper limit so that curves don't get too distorted?
+ samplefreq= *((float *)grid) / MINGRIDSTEP;
+ if (IS_EQ(samplefreq, 0)) samplefreq= 0.001f;
+
+
+ /* the start/end times are simply the horizontal extents of the 'cur' rect */
+ stime= v2d->cur.xmin;
+ etime= v2d->cur.xmax;
+
+
+ /* at each sampling interval, add a new vertex */
+ glBegin(GL_LINE_STRIP);
+
+ for (ctime= stime; ctime <= etime; ctime += samplefreq)
+ glVertex2f( ctime, evaluate_fcurve(fcu, ctime) );
+
+ glEnd();
+
+ /* restore driver */
+ fcu->driver= driver;
+}
+
+/* helper func - draw a samples-based F-Curve */
+// TODO: add offset stuff...
+static void draw_fcurve_curve_samples (FCurve *fcu, View2D *v2d)
+{
+ FPoint *prevfpt= fcu->fpt;
+ FPoint *fpt= prevfpt + 1;
+ float fac, v[2];
+ int b= fcu->totvert-1;
+
+ glBegin(GL_LINE_STRIP);
+
+ /* extrapolate to left? - left-side of view comes before first keyframe? */
+ if (prevfpt->vec[0] > v2d->cur.xmin) {
+ v[0]= v2d->cur.xmin;
+
+ /* y-value depends on the interpolation */
+ if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert==1)) {
+ /* just extend across the first keyframe's value */
+ v[1]= prevfpt->vec[1];
+ }
+ else {
+ /* extrapolate linear dosnt use the handle, use the next points center instead */
+ fac= (prevfpt->vec[0]-fpt->vec[0])/(prevfpt->vec[0]-v[0]);
+ if (fac) fac= 1.0f/fac;
+ v[1]= prevfpt->vec[1]-fac*(prevfpt->vec[1]-fpt->vec[1]);
+ }
+
+ glVertex2fv(v);
+ }
+
+ /* if only one sample, add it now */
+ if (fcu->totvert == 1)
+ glVertex2fv(prevfpt->vec);
+
+ /* loop over samples, drawing segments */
+ /* draw curve between first and last keyframe (if there are enough to do so) */
+ while (b--) {
+ /* Linear interpolation: just add one point (which should add a new line segment) */
+ glVertex2fv(prevfpt->vec);
+
+ /* get next pointers */
+ prevfpt= fpt;
+ fpt++;
+
+ /* last point? */
+ if (b == 0)
+ glVertex2fv(prevfpt->vec);
+ }
+
+ /* extrapolate to right? (see code for left-extrapolation above too) */
+ if (prevfpt->vec[0] < v2d->cur.xmax) {
+ v[0]= v2d->cur.xmax;
+
+ /* y-value depends on the interpolation */
+ if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert==1)) {
+ /* based on last keyframe's value */
+ v[1]= prevfpt->vec[1];
+ }
+ else {
+ /* extrapolate linear dosnt use the handle, use the previous points center instead */
+ fpt = prevfpt-1;
+ fac= (prevfpt->vec[0]-fpt->vec[0])/(prevfpt->vec[0]-v[0]);
+ if (fac) fac= 1.0f/fac;
+ v[1]= prevfpt->vec[1]-fac*(prevfpt->vec[1]-fpt->vec[1]);
+ }
+
+ glVertex2fv(v);
+ }
+
+ glEnd();
+}
+
+/* helper func - draw one repeat of an F-Curve */
+static void draw_fcurve_curve_bezts (FCurve *fcu, View2D *v2d, View2DGrid *grid)
+{
+ BezTriple *prevbezt= fcu->bezt;
+ BezTriple *bezt= prevbezt+1;
+ float v1[2], v2[2], v3[2], v4[2];
+ float *fp, data[120];
+ float fac= 0.0f;
+ int b= fcu->totvert-1;
+ int resol;
+
+ glBegin(GL_LINE_STRIP);
+
+ /* extrapolate to left? */
+ if (prevbezt->vec[1][0] > v2d->cur.xmin) {
+ /* left-side of view comes before first keyframe, so need to extend as not cyclic */
+ v1[0]= v2d->cur.xmin;
+
+ /* y-value depends on the interpolation */
+ if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (prevbezt->ipo==BEZT_IPO_CONST) || (fcu->totvert==1)) {
+ /* just extend across the first keyframe's value */
+ v1[1]= prevbezt->vec[1][1];
+ }
+ else if (prevbezt->ipo==BEZT_IPO_LIN) {
+ /* extrapolate linear dosnt use the handle, use the next points center instead */
+ fac= (prevbezt->vec[1][0]-bezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
+ if (fac) fac= 1.0f/fac;
+ v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[1][1]-bezt->vec[1][1]);
+ }
+ else {
+ /* based on angle of handle 1 (relative to keyframe) */
+ fac= (prevbezt->vec[0][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
+ if (fac) fac= 1.0f/fac;
+ v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[0][1]-prevbezt->vec[1][1]);
+ }
+
+ glVertex2fv(v1);
+ }
+
+ /* if only one keyframe, add it now */
+ if (fcu->totvert == 1) {
+ v1[0]= prevbezt->vec[1][0];
+ v1[1]= prevbezt->vec[1][1];
+ glVertex2fv(v1);
+ }
+
+ /* draw curve between first and last keyframe (if there are enough to do so) */
+ while (b--) {
+ if (prevbezt->ipo==BEZT_IPO_CONST) {
+ /* Constant-Interpolation: draw segment between previous keyframe and next, but holding same value */
+ v1[0]= prevbezt->vec[1][0];
+ v1[1]= prevbezt->vec[1][1];
+ glVertex2fv(v1);
+
+ v1[0]= bezt->vec[1][0];
+ v1[1]= prevbezt->vec[1][1];
+ glVertex2fv(v1);
+ }
+ else if (prevbezt->ipo==BEZT_IPO_LIN) {
+ /* Linear interpolation: just add one point (which should add a new line segment) */
+ v1[0]= prevbezt->vec[1][0];
+ v1[1]= prevbezt->vec[1][1];
+ glVertex2fv(v1);
+ }
+ else {
+ /* Bezier-Interpolation: draw curve as series of segments between keyframes
+ * - resol determines number of points to sample in between keyframes
+ */
+
+ /* resol not depending on horizontal resolution anymore, drivers for example... */
+ // XXX need to take into account the scale
+ if (fcu->driver)
+ resol= 32;
+ else
+ resol= (int)(3.0*sqrt(bezt->vec[1][0] - prevbezt->vec[1][0]));
+
+ if (resol < 2) {
+ /* only draw one */
+ v1[0]= prevbezt->vec[1][0];
+ v1[1]= prevbezt->vec[1][1];
+ glVertex2fv(v1);
+ }
+ else {
+ /* clamp resolution to max of 32 */
+ if (resol > 32) resol= 32;
+
+ 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);
+
+ forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, 3);
+ forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data+1, resol, 3);
+
+ for (fp= data; resol; resol--, fp+= 3)
+ glVertex2fv(fp);
+ }
+ }
+
+ /* get next pointers */
+ prevbezt= bezt;
+ bezt++;
+
+ /* last point? */
+ if (b == 0) {
+ v1[0]= prevbezt->vec[1][0];
+ v1[1]= prevbezt->vec[1][1];
+ glVertex2fv(v1);
+ }
+ }
+
+ /* extrapolate to right? (see code for left-extrapolation above too) */
+ if (prevbezt->vec[1][0] < v2d->cur.xmax) {
+ v1[0]= v2d->cur.xmax;
+
+ /* y-value depends on the interpolation */
+ if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo==BEZT_IPO_CONST) || (fcu->totvert==1)) {
+ /* based on last keyframe's value */
+ v1[1]= prevbezt->vec[1][1];
+ }
+ else if (prevbezt->ipo==BEZT_IPO_LIN) {
+ /* extrapolate linear dosnt use the handle, use the previous points center instead */
+ bezt = prevbezt-1;
+ fac= (prevbezt->vec[1][0]-bezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
+ if (fac) fac= 1.0f/fac;
+ v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[1][1]-bezt->vec[1][1]);
+ }
+ else {
+ /* based on angle of handle 1 (relative to keyframe) */
+ fac= (prevbezt->vec[2][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
+ if (fac) fac= 1.0f/fac;
+ v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[2][1]-prevbezt->vec[1][1]);
+ }
+
+ glVertex2fv(v1);
+ }
+
+ glEnd();
+}
+
+#if 0
+static void draw_ipokey(SpaceIpo *sipo, ARegion *ar)
+{
+ View2D *v2d= &ar->v2d;
+ IpoKey *ik;
+
+ glBegin(GL_LINES);
+ for (ik= sipo->ipokey.first; ik; ik= ik->next) {
+ if (ik->flag & SELECT) glColor3ub(0xFF, 0xFF, 0x99);
+ else glColor3ub(0xAA, 0xAA, 0x55);
+
+ glVertex2f(ik->val, v2d->cur.ymin);
+ glVertex2f(ik->val, v2d->cur.ymax);
+ }
+ glEnd();
+}
+#endif
+
+/* Public Curve-Drawing API ---------------- */
+
+/* Draw the 'ghost' F-Curves (i.e. snapshots of the curve) */
+void graph_draw_ghost_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid *grid)
+{
+ FCurve *fcu;
+
+ /* draw with thick dotted lines */
+ setlinestyle(1);
+ glLineWidth(3.0f);
+
+ /* anti-aliased lines for less jagged appearance */
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+
+ /* the ghost curves are simply sampled F-Curves stored in sipo->ghostCurves */
+ for (fcu= sipo->ghostCurves.first; fcu; fcu= fcu->next) {
+ /* set whatever color the curve has set
+ * - this is set by the function which creates these
+ * - draw with a fixed opacity of 2
+ */
+ glColor4f(fcu->color[0], fcu->color[1], fcu->color[2], 0.5f);
+
+ /* simply draw the stored samples */
+ draw_fcurve_curve_samples(fcu, &ar->v2d);
+ }
+
+ /* restore settings */
+ setlinestyle(0);
+ glLineWidth(1.0f);
+
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+}
+
+/* This is called twice from space_graph.c -> graph_main_area_draw()
+ * Unselected then selected F-Curves are drawn so that they do not occlude each other.
+ */
+void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid *grid, short sel)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* build list of curves to draw */
+ filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CURVESONLY|ANIMFILTER_CURVEVISIBLE);
+ filter |= ((sel) ? (ANIMFILTER_SEL) : (ANIMFILTER_UNSEL));
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* for each curve:
+ * draw curve, then handle-lines, and finally vertices in this order so that
+ * the data will be layered correctly
+ */
+ for (ale=anim_data.first; ale; ale=ale->next) {
+ FCurve *fcu= (FCurve *)ale->key_data;
+ FModifier *fcm= fcurve_find_active_modifier(fcu);
+ //Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ /* map keyframes for drawing if scaled F-Curve */
+ //if (nob)
+ // ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 0);
+
+ /* draw curve:
+ * - curve line may be result of one or more destructive modifiers or just the raw data,
+ * so we need to check which method should be used
+ * - controls from active modifier take precidence over keyframes
+ * (XXX! editing tools need to take this into account!)
+ */
+
+ /* 1) draw curve line */
+ {
+ /* set color/drawing style for curve itself */
+ if ( ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) || (fcu->flag & FCURVE_PROTECTED) ) {
+ /* protected curves (non editable) are drawn with dotted lines */
+ setlinestyle(2);
+ }
+ if (fcu->flag & FCURVE_MUTED) {
+ /* muted curves are drawn in a greyish hue */
+ // XXX should we have some variations?
+ UI_ThemeColorShade(TH_HEADER, 50);
+ }
+ else {
+ /* set whatever color the curve has set */
+ glColor3fv(fcu->color);
+ }
+
+ /* anti-aliased lines for less jagged appearance */
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+
+ /* draw F-Curve */
+ if ((fcu->modifiers.first) || (fcu->flag & FCURVE_INT_VALUES)) {
+ /* draw a curve affected by modifiers or only allowed to have integer values
+ * by sampling it at various small-intervals over the visible region
+ */
+ draw_fcurve_curve(fcu, sipo, &ar->v2d, grid);
+ }
+ else if ( ((fcu->bezt) || (fcu->fpt)) && (fcu->totvert) ) {
+ /* just draw curve based on defined data (i.e. no modifiers) */
+ if (fcu->bezt)
+ draw_fcurve_curve_bezts(fcu, &ar->v2d, grid);
+ else if (fcu->fpt)
+ draw_fcurve_curve_samples(fcu, &ar->v2d);
+ }
+
+ /* restore settings */
+ setlinestyle(0);
+
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+ }
+
+ /* 2) draw handles and vertices as appropriate based on active */
+ if ( ((fcm) && (fcm->type != FMODIFIER_TYPE_CYCLES)) || (fcu->modifiers.first && !fcm) ) {
+ /* draw controls for the 'active' modifier
+ * - there may not be an 'active' modifier on this curve to draw
+ * - this curve may not be active, so modifier controls shouldn't get drawn either
+ *
+ * NOTE: cycles modifier is currently an exception where the original points can still be edited, so
+ * this branch is skipped... (TODO: set up the generic system for this so that we don't need special hacks like this)
+ */
+ if ((fcu->flag & FCURVE_ACTIVE) && (fcm)) {
+ switch (fcm->type) {
+ case FMODIFIER_TYPE_ENVELOPE: /* envelope */
+ draw_fcurve_modifier_controls_envelope(fcu, fcm, &ar->v2d);
+ break;
+ }
+ }
+ }
+ else if ( ((fcu->bezt) || (fcu->fpt)) && (fcu->totvert) ) {
+ if (fcu->bezt) {
+ /* only draw handles/vertices on keyframes */
+ draw_fcurve_handles(sipo, ar, fcu);
+ draw_fcurve_vertices(sipo, ar, fcu);
+ }
+ else {
+ /* samples: should we only draw two indicators at either end as indicators? */
+ draw_fcurve_samples(sipo, ar, fcu);
+ }
+ }
+
+ /* undo mapping of keyframes for drawing if scaled F-Curve */
+ //if (nob)
+ // ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 0);
+ }
+
+ /* free list of curves */
+ BLI_freelistN(&anim_data);
+}
+
+/* ************************************************************************* */
+/* Channel List */
+
+// XXX quite a few of these need to be kept in sync with their counterparts in Action Editor
+// as they're the same. We have 2 separate copies of this for now to make it easier to develop
+// the diffences between the two editors, but one day these should be merged!
+
+/* left hand part */
+void graph_draw_channel_names(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ View2D *v2d= &ar->v2d;
+ float x= 0.0f, y= 0.0f, height;
+ int items, i=0;
+
+ /* build list of channels to draw */
+ filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
+ items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* Update max-extent of channels here (taking into account scrollers):
+ * - this is done to allow the channel list to be scrollable, but must be done here
+ * to avoid regenerating the list again and/or also because channels list is drawn first
+ * - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
+ * start of list offset, and the second is as a correction for the scrollers.
+ */
+ height= (float)((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2));
+
+#if 0
+ if (height > (v2d->mask.ymax - v2d->mask.ymin)) {
+ /* don't use totrect set, as the width stays the same
+ * (NOTE: this is ok here, the configuration is pretty straightforward)
+ */
+ v2d->tot.ymin= (float)(-height);
+ }
+
+ /* XXX I would call the below line! (ton) */
+#endif
+ UI_view2d_totRect_set(v2d, ar->winx, height);
+
+ /* loop through channels, and set up drawing depending on their type */
+ y= (float)ACHANNEL_FIRST;
+
+ for (ale= anim_data.first, i=0; ale; ale= ale->next, i++) {
+ const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
+ const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
+
+ /* check if visible */
+ if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
+ {
+ bActionGroup *grp = NULL;
+ short indent= 0, offset= 0, sel= 0, group= 0;
+ int expand= -1, protect = -1, special= -1, mute = -1;
+ char name[128];
+
+ /* determine what needs to be drawn */
+ switch (ale->type) {
+ case ANIMTYPE_SCENE: /* scene */
+ {
+ Scene *sce= (Scene *)ale->data;
+
+ group= 4;
+ indent= 0;
+
+ special= ICON_SCENE_DATA;
+
+ /* only show expand if there are any channels */
+ if (EXPANDED_SCEC(sce))
+ expand= ICON_TRIA_DOWN;
+ else
+ expand= ICON_TRIA_RIGHT;
+
+ sel = SEL_SCEC(sce);
+ strcpy(name, sce->id.name+2);
+ }
+ break;
+ case ANIMTYPE_OBJECT: /* object */
+ {
+ Base *base= (Base *)ale->data;
+ Object *ob= base->object;
+
+ group= 4;
+ indent= 0;
+
+ /* icon depends on object-type */
+ if (ob->type == OB_ARMATURE)
+ special= ICON_ARMATURE_DATA;
+ else
+ special= ICON_OBJECT_DATA;
+
+ /* only show expand if there are any channels */
+ if (EXPANDED_OBJC(ob))
+ expand= ICON_TRIA_DOWN;
+ else
+ expand= ICON_TRIA_RIGHT;
+
+ sel = SEL_OBJC(base);
+ strcpy(name, ob->id.name+2);
+ }
+ break;
+ case ANIMTYPE_FILLACTD: /* action widget */
+ {
+ bAction *act= (bAction *)ale->data;
+
+ group = 4;
+ indent= 1;
+ special= ICON_ACTION;
+
+ if (EXPANDED_ACTC(act))
+ expand= ICON_TRIA_DOWN;
+ else
+ expand= ICON_TRIA_RIGHT;
+
+ sel = SEL_ACTC(act);
+ strcpy(name, act->id.name+2);
+ }
+ break;
+ case ANIMTYPE_FILLDRIVERS: /* drivers widget */
+ {
+ AnimData *adt= (AnimData *)ale->data;
+
+ group = 4;
+ indent= 1;
+ special= ICON_ANIM_DATA;
+
+ if (EXPANDED_DRVD(adt))
+ expand= ICON_TRIA_DOWN;
+ else
+ expand= ICON_TRIA_RIGHT;
+
+ strcpy(name, "Drivers");
+ }
+ break;
+ case ANIMTYPE_FILLMATD: /* object materials (dopesheet) expand widget */
+ {
+ Object *ob = (Object *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_MATERIAL_DATA;
+
+ if (FILTER_MAT_OBJC(ob))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, "Materials");
+ }
+ break;
+
+
+ case ANIMTYPE_DSMAT: /* single material (dopesheet) expand widget */
+ {
+ Material *ma = (Material *)ale->data;
+
+ group = 0;
+ indent = 0;
+ special = ICON_MATERIAL_DATA;
+ offset = 21;
+
+ if (FILTER_MAT_OBJD(ma))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, ma->id.name+2);
+ }
+ break;
+ case ANIMTYPE_DSLAM: /* lamp (dopesheet) expand widget */
+ {
+ Lamp *la = (Lamp *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_LAMP_DATA;
+
+ if (FILTER_LAM_OBJD(la))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, la->id.name+2);
+ }
+ break;
+ case ANIMTYPE_DSCAM: /* camera (dopesheet) expand widget */
+ {
+ Camera *ca = (Camera *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_CAMERA_DATA;
+
+ if (FILTER_CAM_OBJD(ca))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, ca->id.name+2);
+ }
+ break;
+ case ANIMTYPE_DSCUR: /* curve (dopesheet) expand widget */
+ {
+ Curve *cu = (Curve *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_CURVE_DATA;
+
+ if (FILTER_CUR_OBJD(cu))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, cu->id.name+2);
+ }
+ break;
+ case ANIMTYPE_DSSKEY: /* shapekeys (dopesheet) expand widget */
+ {
+ Key *key= (Key *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_SHAPEKEY_DATA;
+
+ if (FILTER_SKE_OBJD(key))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ //sel = SEL_OBJC(base);
+ strcpy(name, "Shape Keys");
+ }
+ break;
+ case ANIMTYPE_DSWOR: /* world (dopesheet) expand widget */
+ {
+ World *wo= (World *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_WORLD_DATA;
+
+ if (FILTER_WOR_SCED(wo))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, wo->id.name+2);
+ }
+ break;
+
+
+ case ANIMTYPE_GROUP: /* action group */
+ {
+ bActionGroup *agrp= (bActionGroup *)ale->data;
+
+ group= 2;
+ indent= 0;
+ special= -1;
+
+ if (ale->id) {
+ /* special exception for materials */
+ if (GS(ale->id->name) == ID_MA)
+ offset= 25;
+ else
+ offset= 14;
+ }
+ else
+ offset= 0;
+
+ /* only show expand if there are any channels */
+ if (agrp->channels.first) {
+ if (EXPANDED_AGRP(agrp))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+ }
+
+ if (EDITABLE_AGRP(agrp))
+ protect = ICON_UNLOCKED;
+ else
+ protect = ICON_LOCKED;
+
+ sel = SEL_AGRP(agrp);
+ strcpy(name, agrp->name);
+ }
+ break;
+ case ANIMTYPE_FCURVE: /* F-Curve channel */
+ {
+ FCurve *fcu = (FCurve *)ale->data;
+
+ indent = 0;
+
+ group= (fcu->grp) ? 1 : 0;
+ grp= fcu->grp;
+
+ if (ale->id) {
+ /* special exception for materials */
+ if (GS(ale->id->name) == ID_MA) {
+ offset= 21;
+ indent= 1;
+ }
+ else
+ offset= 14;
+ }
+ else
+ offset= 0;
+
+ /* for now, 'special' (i.e. in front of name) is used to show visibility status */
+ if (fcu->flag & FCURVE_VISIBLE)
+ special= ICON_CHECKBOX_HLT;
+ else
+ special= ICON_CHECKBOX_DEHLT;
+
+ if (fcu->flag & FCURVE_MUTED)
+ mute = ICON_MUTE_IPO_ON;
+ else
+ mute = ICON_MUTE_IPO_OFF;
+
+ if (fcu->bezt) {
+ if (EDITABLE_FCU(fcu))
+ protect = ICON_UNLOCKED;
+ else
+ protect = ICON_LOCKED;
+ }
+ else
+ protect = ICON_ZOOMOUT; // XXX editability is irrelevant here, but this icon is temp...
+
+ sel = SEL_FCU(fcu);
+
+ getname_anim_fcurve(name, ale->id, fcu);
+ }
+ break;
+
+ case ANIMTYPE_SHAPEKEY: /* shapekey channel */
+ {
+ KeyBlock *kb = (KeyBlock *)ale->data;
+
+ indent = 0;
+ special = -1;
+
+ offset= (ale->id) ? 21 : 0;
+
+ if (kb->name[0] == '\0')
+ sprintf(name, "Key %d", ale->index);
+ else
+ strcpy(name, kb->name);
+ }
+ break;
+ }
+
+ /* now, start drawing based on this information */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ /* draw backing strip behind channel name */
+ if (group == 4) {
+ /* only used in dopesheet... */
+ if (ELEM(ale->type, ANIMTYPE_SCENE, ANIMTYPE_OBJECT)) {
+ /* object channel - darker */
+ UI_ThemeColor(TH_DOPESHEET_CHANNELOB);
+ uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
+ gl_round_box(GL_POLYGON, x+offset, yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
+ }
+ else {
+ /* sub-object folders - lighter */
+ UI_ThemeColor(TH_DOPESHEET_CHANNELSUBOB);
+
+ offset += 7 * indent;
+ glBegin(GL_QUADS);
+ glVertex2f(x+offset, yminc);
+ glVertex2f(x+offset, ymaxc);
+ glVertex2f((float)ACHANNEL_NAMEWIDTH, ymaxc);
+ glVertex2f((float)ACHANNEL_NAMEWIDTH, yminc);
+ glEnd();
+
+ /* clear group value, otherwise we cause errors... */
+ group = 0;
+ }
+ }
+ else if (group == 3) {
+ /* only for gp-data channels */
+ UI_ThemeColorShade(TH_GROUP, 20);
+ uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
+ gl_round_box(GL_POLYGON, x+offset, yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
+ }
+ else if (group == 2) {
+ /* only for action group channels */
+ if (ale->flag & AGRP_ACTIVE)
+ UI_ThemeColorShade(TH_GROUP_ACTIVE, 10);
+ else
+ UI_ThemeColorShade(TH_GROUP, 20);
+ uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
+ gl_round_box(GL_POLYGON, x+offset, yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
+ }
+ else {
+ short shadefac= ((indent==0)?20: (indent==1)?-20: -40);
+
+ indent += group;
+ offset += 7 * indent;
+
+ /* draw channel backdrop */
+ UI_ThemeColorShade(TH_HEADER, shadefac);
+
+ glBegin(GL_QUADS);
+ glVertex2f(x+offset, yminc);
+ glVertex2f(x+offset, ymaxc);
+ glVertex2f((float)ACHANNEL_NAMEWIDTH, ymaxc);
+ glVertex2f((float)ACHANNEL_NAMEWIDTH, yminc);
+ glEnd();
+
+ /* most of the time, only F-Curves are going to be drawn here */
+ if (ale->type == ANIMTYPE_FCURVE) {
+ /* F-Curve channels need to have a special 'color code' box drawn, which is colored with whatever
+ * color the curve has stored
+ */
+ FCurve *fcu= (FCurve *)ale->data;
+ glColor3fv(fcu->color);
+
+ // NOTE: only enable the following line for the fading-out gradient
+ //glShadeModel(GL_SMOOTH);
+
+ glBegin(GL_QUADS);
+ /* solid color for the area around the checkbox */
+ glVertex2f(x+offset, yminc);
+ glVertex2f(x+offset, ymaxc);
+ glVertex2f(x+offset+18, ymaxc);
+ glVertex2f(x+offset+18, yminc);
+
+#if 0 // fading out gradient
+ /* fading out gradient for the rest of the box */
+ glVertex2f(x+offset+18, yminc);
+ glVertex2f(x+offset+18, ymaxc);
+
+ UI_ThemeColorShade(TH_HEADER, shadefac); // XXX does this cause any problems on some cards?
+
+ glVertex2f(x+offset+20, ymaxc);
+ glVertex2f(x+offset+20, yminc);
+#endif // fading out gradient
+ glEnd();
+
+ // NOTE: only enable the following line for the fading-out gradient
+ //glShadeModel(GL_FLAT);
+ }
+ }
+
+ /* draw expand/collapse triangle */
+ if (expand > 0) {
+ UI_icon_draw(x+offset, yminc, expand);
+ offset += 17;
+ }
+
+ /* draw special icon indicating certain data-types */
+ if (special > -1) {
+ if (ELEM(group, 3, 4)) {
+ /* for gpdatablock channels */
+ UI_icon_draw(x+offset, yminc, special);
+ offset += 17;
+ }
+ else {
+ /* for normal channels */
+ UI_icon_draw(x+offset, yminc, special);
+ offset += 17;
+ }
+ }
+ glDisable(GL_BLEND);
+
+ /* draw name */
+ if (sel)
+ UI_ThemeColor(TH_TEXT_HI);
+ else
+ UI_ThemeColor(TH_TEXT);
+ offset += 3;
+ UI_DrawString(x+offset, y-4, name);
+
+ /* reset offset - for RHS of panel */
+ offset = 0;
+
+ /* set blending again, as text drawing may clear it */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ /* draw protect 'lock' */
+ if (protect > -1) {
+ offset = 16;
+ UI_icon_draw((float)ACHANNEL_NAMEWIDTH-offset, yminc, protect);
+ }
+
+ /* draw mute 'eye' */
+ if (mute > -1) {
+ offset += 16;
+ UI_icon_draw((float)(ACHANNEL_NAMEWIDTH-offset), yminc, mute);
+ }
+ glDisable(GL_BLEND);
+ }
+
+ /* adjust y-position for next one */
+ y -= ACHANNEL_STEP;
+ }
+
+ /* free tempolary channels */
+ BLI_freelistN(&anim_data);
+}
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
new file mode 100644
index 00000000000..52301ac1b0f
--- /dev/null
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -0,0 +1,1715 @@
+/**
+ * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_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 "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "BKE_action.h"
+#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+#include "BKE_context.h"
+#include "BKE_report.h"
+#include "BKE_utildefines.h"
+
+#include "UI_view2d.h"
+
+#include "BIF_transform.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_draw.h"
+#include "ED_keyframes_edit.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "graph_intern.h"
+
+/* ************************************************************************** */
+/* KEYFRAME-RANGE STUFF */
+
+/* *************************** Calculate Range ************************** */
+
+/* Get the min/max keyframes*/
+static void get_graph_keyframe_extents (bAnimContext *ac, float *xmin, float *xmax, float *ymin, float *ymax)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get data to filter, from Dopesheet */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* set large values to try to override */
+ if (xmin) *xmin= 999999999.0f;
+ if (xmax) *xmax= -999999999.0f;
+ if (ymin) *ymin= 999999999.0f;
+ if (ymax) *ymax= -999999999.0f;
+
+ /* check if any channels to set range with */
+ if (anim_data.first) {
+ /* go through channels, finding max extents */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= NULL; //ANIM_nla_mapping_get(ac, ale);
+ FCurve *fcu= (FCurve *)ale->key_data;
+ float tmin, tmax;
+
+ /* get range and apply necessary scaling before */
+ calc_fcurve_bounds(fcu, &tmin, &tmax, ymin, ymax);
+
+ if (nob) {
+ tmin= get_action_frame_inv(nob, tmin);
+ tmax= get_action_frame_inv(nob, tmax);
+ }
+
+ /* try to set cur using these values, if they're more extreme than previously set values */
+ if (xmin) *xmin= MIN2(*xmin, tmin);
+ if (xmax) *xmax= MAX2(*xmax, tmax);
+ }
+
+ /* free memory */
+ BLI_freelistN(&anim_data);
+ }
+ else {
+ /* set default range */
+ if (ac->scene) {
+ if (xmin) *xmin= (float)ac->scene->r.sfra;
+ if (xmax) *xmax= (float)ac->scene->r.efra;
+ }
+ else {
+ if (xmin) *xmin= -5;
+ if (xmax) *xmax= 100;
+ }
+
+ if (ymin) *ymin= -5;
+ if (ymax) *ymax= 5;
+ }
+}
+
+/* ****************** Automatic Preview-Range Operator ****************** */
+
+static int graphkeys_previewrange_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ Scene *scene;
+ float min, max;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ if (ac.scene == NULL)
+ return OPERATOR_CANCELLED;
+ else
+ scene= ac.scene;
+
+ /* set the range directly */
+ get_graph_keyframe_extents(&ac, &min, &max, NULL, NULL);
+ scene->r.psfra= (int)floor(min + 0.5f);
+ scene->r.pefra= (int)floor(max + 0.5f);
+
+ /* set notifier that things have changed */
+ // XXX err... there's nothing for frame ranges yet, but this should do fine too
+ WM_event_add_notifier(C, NC_SCENE|ND_FRAME, ac.scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_previewrange_set (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Auto-Set Preview Range";
+ ot->idname= "GRAPHEDIT_OT_previewrange_set";
+
+ /* api callbacks */
+ ot->exec= graphkeys_previewrange_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ****************** View-All Operator ****************** */
+
+static int graphkeys_viewall_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ View2D *v2d;
+ float extra;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ v2d= &ac.ar->v2d;
+
+ /* set the horizontal range, with an extra offset so that the extreme keys will be in view */
+ get_graph_keyframe_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, &v2d->cur.ymin, &v2d->cur.ymax);
+
+ extra= 0.1f * (v2d->cur.xmax - v2d->cur.xmin);
+ v2d->cur.xmin -= extra;
+ v2d->cur.xmax += extra;
+
+ extra= 0.1f * (v2d->cur.ymax - v2d->cur.ymin);
+ v2d->cur.ymin -= extra;
+ v2d->cur.ymax += extra;
+
+ /* do View2D syncing */
+ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
+
+ /* set notifier that things have changed */
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_view_all (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View All";
+ ot->idname= "GRAPHEDIT_OT_view_all";
+
+ /* api callbacks */
+ ot->exec= graphkeys_viewall_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ******************** Create Ghost-Curves Operator *********************** */
+/* This operator samples the data of the selected F-Curves to F-Points, storing them
+ * as 'ghost curves' in the active Graph Editor
+ */
+
+/* Bake each F-Curve into a set of samples, and store as a ghost curve */
+static void create_ghost_curves (bAnimContext *ac, int start, int end)
+{
+ SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* free existing ghost curves */
+ free_fcurves(&sipo->ghostCurves);
+
+ /* sanity check */
+ if (start >= end) {
+ printf("Error: Frame range for Ghost F-Curve creation is inappropriate \n");
+ return;
+ }
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through filtered data and add keys between selected keyframes on every frame */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ FCurve *fcu= (FCurve *)ale->key_data;
+ FCurve *gcu= MEM_callocN(sizeof(FCurve), "Ghost FCurve");
+ ChannelDriver *driver= fcu->driver;
+ FPoint *fpt;
+ int cfra;
+
+ /* disable driver so that it don't muck up the sampling process */
+ fcu->driver= NULL;
+
+ /* create samples, but store them in a new curve
+ * - we cannot use fcurve_store_samples() as that will only overwrite the original curve
+ */
+ gcu->fpt= fpt= MEM_callocN(sizeof(FPoint)*(end-start+1), "Ghost FPoint Samples");
+ gcu->totvert= end - start + 1;
+
+ /* use the sampling callback at 1-frame intervals from start to end frames */
+ for (cfra= start; cfra <= end; cfra++, fpt++) {
+ fpt->vec[0]= (float)cfra;
+ fpt->vec[1]= fcurve_samplingcb_evalcurve(fcu, NULL, (float)cfra);
+ }
+
+ /* set color of ghost curve
+ * - make the color slightly darker
+ */
+ gcu->color[0]= fcu->color[0] - 0.07f;
+ gcu->color[1]= fcu->color[1] - 0.07f;
+ gcu->color[2]= fcu->color[2] - 0.07f;
+
+ /* store new ghost curve */
+ BLI_addtail(&sipo->ghostCurves, gcu);
+
+ /* restore driver */
+ fcu->driver= driver;
+ }
+
+ /* admin and redraws */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int graphkeys_create_ghostcurves_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ View2D *v2d;
+ int start, end;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* ghost curves are snapshots of the visible portions of the curves, so set range to be the visible range */
+ v2d= &ac.ar->v2d;
+ start= (int)v2d->cur.xmin;
+ end= (int)v2d->cur.xmax;
+
+ /* bake selected curves into a ghost curve */
+ create_ghost_curves(&ac, start, end);
+
+ /* update this editor only */
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_ghost_curves_create (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Create Ghost Curves";
+ ot->idname= "GRAPHEDIT_OT_ghost_curves_create";
+ ot->description= "Create snapshot (Ghosts) of selected F-Curves as background aid for active Graph Editor.";
+
+ /* api callbacks */
+ ot->exec= graphkeys_create_ghostcurves_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ // todo: add props for start/end frames
+}
+
+/* ******************** Clear Ghost-Curves Operator *********************** */
+/* This operator clears the 'ghost curves' for the active Graph Editor */
+
+static int graphkeys_clear_ghostcurves_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ SpaceIpo *sipo;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ sipo= (SpaceIpo *)ac.sa->spacedata.first;
+
+ /* if no ghost curves, don't do anything */
+ if (sipo->ghostCurves.first == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* free ghost curves */
+ free_fcurves(&sipo->ghostCurves);
+
+ /* update this editor only */
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_ghost_curves_clear (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Create Ghost Curves";
+ ot->idname= "GRAPHEDIT_OT_ghost_curves_clear";
+ ot->description= "Clear F-Curve snapshots (Ghosts) for active Graph Editor.";
+
+ /* api callbacks */
+ ot->exec= graphkeys_clear_ghostcurves_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ************************************************************************** */
+/* GENERAL STUFF */
+
+// TODO: insertkey
+
+/* ******************** Click-Insert Keyframes Operator ************************* */
+
+static int graphkeys_click_insert_exec (bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ bAnimListElem *ale;
+ float frame, val;
+
+ /* get animation context */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get active F-Curve 'anim-list-element' */
+ ale= get_active_fcurve_channel(&ac);
+ if (ELEM(NULL, ale, ale->data)) {
+ if (ale) MEM_freeN(ale);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get frame and value from props */
+ frame= RNA_float_get(op->ptr, "frame");
+ val= RNA_float_get(op->ptr, "value");
+
+ /* insert keyframe on the specified frame + value */
+ insert_vert_fcurve((FCurve *)ale->data, frame, val, 0);
+
+ /* free temp data */
+ MEM_freeN(ale);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+static int graphkeys_click_insert_invoke (bContext *C, wmOperator *op, wmEvent *evt)
+{
+ bAnimContext ac;
+ ARegion *ar;
+ View2D *v2d;
+ int mval[2];
+ float x, y;
+
+ /* get animation context */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* store mouse coordinates in View2D space, into the operator's properties */
+ ar= ac.ar;
+ v2d= &ar->v2d;
+
+ mval[0]= (evt->x - ar->winrct.xmin);
+ mval[1]= (evt->y - ar->winrct.ymin);
+
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
+
+ RNA_float_set(op->ptr, "frame", x);
+ RNA_float_set(op->ptr, "value", y);
+
+ /* run exec now */
+ return graphkeys_click_insert_exec(C, op);
+}
+
+void GRAPHEDIT_OT_keyframes_click_insert (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Click-Insert Keyframes";
+ ot->idname= "GRAPHEDIT_OT_keyframes_click_insert";
+
+ /* api callbacks */
+ ot->invoke= graphkeys_click_insert_invoke;
+ ot->exec= graphkeys_click_insert_exec;
+ ot->poll= ED_operator_areaactive; // XXX active + editable poll
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float(ot->srna, "frame", 1.0f, -FLT_MAX, FLT_MAX, "Frame Number", "Frame to insert keyframe on", 0, 100);
+ RNA_def_float(ot->srna, "value", 1.0f, -FLT_MAX, FLT_MAX, "Value", "Value for keyframe on", 0, 100);
+}
+
+/* ******************** Copy/Paste Keyframes Operator ************************* */
+/* NOTE: the backend code for this is shared with the dopesheet editor */
+
+static short copy_graph_keys (bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ int filter, ok=0;
+
+ /* clear buffer first */
+ free_anim_copybuf();
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* copy keyframes */
+ ok= copy_animedit_keys(ac, &anim_data);
+
+ /* clean up */
+ BLI_freelistN(&anim_data);
+
+ return ok;
+}
+
+static short paste_graph_keys (bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ int filter, ok=0;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* paste keyframes */
+ ok= paste_animedit_keys(ac, &anim_data);
+
+ /* clean up */
+ BLI_freelistN(&anim_data);
+
+ return ok;
+}
+
+/* ------------------- */
+
+static int graphkeys_copy_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* copy keyframes */
+ if (copy_graph_keys(&ac)) {
+ BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_copy (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Copy Keyframes";
+ ot->idname= "GRAPHEDIT_OT_keyframes_copy";
+
+ /* api callbacks */
+ ot->exec= graphkeys_copy_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+
+static int graphkeys_paste_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* paste keyframes */
+ if (paste_graph_keys(&ac)) {
+ BKE_report(op->reports, RPT_ERROR, "No keyframes to paste");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_paste (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Paste Keyframes";
+ ot->idname= "GRAPHEDIT_OT_keyframes_paste";
+
+ /* api callbacks */
+ ot->exec= graphkeys_paste_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ******************** Duplicate Keyframes Operator ************************* */
+
+static void duplicate_graph_keys (bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE| ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through filtered data and delete selected keys */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ duplicate_fcurve_keys((FCurve *)ale->key_data);
+ }
+
+ /* free filtered list */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int graphkeys_duplicate_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* duplicate keyframes */
+ duplicate_graph_keys(&ac);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+static int graphkeys_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ graphkeys_duplicate_exec(C, op);
+
+ RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
+ WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_duplicate (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Duplicate Keyframes";
+ ot->idname= "GRAPHEDIT_OT_keyframes_duplicate";
+
+ /* api callbacks */
+ ot->invoke= graphkeys_duplicate_invoke;
+ ot->exec= graphkeys_duplicate_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* to give to transform */
+ RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+}
+
+/* ******************** Delete Keyframes Operator ************************* */
+
+static void delete_graph_keys (bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE| ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through filtered data and delete selected keys */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ delete_fcurve_keys((FCurve *)ale->key_data); // XXX... this doesn't delete empty curves anymore
+ }
+
+ /* free filtered list */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int graphkeys_delete_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* delete keyframes */
+ delete_graph_keys(&ac);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_delete (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete Keyframes";
+ ot->idname= "GRAPHEDIT_OT_keyframes_delete";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= graphkeys_delete_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ******************** Clean Keyframes Operator ************************* */
+
+static void clean_graph_keys (bAnimContext *ac, float thresh)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE| ANIMFILTER_FOREDIT | ANIMFILTER_SEL | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through filtered data and clean curves */
+ for (ale= anim_data.first; ale; ale= ale->next)
+ clean_fcurve((FCurve *)ale->key_data, thresh);
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int graphkeys_clean_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ float thresh;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get cleaning threshold */
+ thresh= RNA_float_get(op->ptr, "threshold");
+
+ /* clean keyframes */
+ clean_graph_keys(&ac, thresh);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_clean (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Clean Keyframes";
+ ot->idname= "GRAPHEDIT_OT_keyframes_clean";
+
+ /* api callbacks */
+ //ot->invoke= // XXX we need that number popup for this!
+ ot->exec= graphkeys_clean_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float(ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f);
+}
+
+/* ******************** Bake F-Curve Operator *********************** */
+/* This operator bakes the data of the selected F-Curves to F-Points */
+
+/* Bake each F-Curve into a set of samples */
+static void bake_graph_curves (bAnimContext *ac, int start, int end)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through filtered data and add keys between selected keyframes on every frame */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ FCurve *fcu= (FCurve *)ale->key_data;
+ ChannelDriver *driver= fcu->driver;
+
+ /* disable driver so that it don't muck up the sampling process */
+ fcu->driver= NULL;
+
+ /* create samples */
+ fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve);
+
+ /* restore driver */
+ fcu->driver= driver;
+ }
+
+ /* admin and redraws */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int graphkeys_bake_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ Scene *scene= NULL;
+ int start, end;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* for now, init start/end from preview-range extents */
+ // TODO: add properties for this
+ scene= ac.scene;
+ start= PSFRA;
+ end= PEFRA;
+
+ /* bake keyframes */
+ bake_graph_curves(&ac, start, end);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_bake (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Bake Curve";
+ ot->idname= "GRAPHEDIT_OT_keyframes_bake";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm; // FIXME...
+ ot->exec= graphkeys_bake_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ // todo: add props for start/end frames
+}
+
+/* ******************** Sample Keyframes Operator *********************** */
+/* This operator 'bakes' the values of the curve into new keyframes between pairs
+ * of selected keyframes. It is useful for creating keyframes for tweaking overlap.
+ */
+
+// XXX some of the common parts (with DopeSheet) should be unified in animation module...
+
+/* little cache for values... */
+typedef struct tempFrameValCache {
+ float frame, val;
+} tempFrameValCache;
+
+/* Evaluates the curves between each selected keyframe on each frame, and keys the value */
+static void sample_graph_keys (bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE| ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through filtered data and add keys between selected keyframes on every frame */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ FCurve *fcu= (FCurve *)ale->key_data;
+ BezTriple *bezt, *start=NULL, *end=NULL;
+ tempFrameValCache *value_cache, *fp;
+ int sfra, range;
+ int i, n;
+
+ /* find selected keyframes... once pair has been found, add keyframes */
+ for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ /* check if selected, and which end this is */
+ if (BEZSELECTED(bezt)) {
+ if (start) {
+ /* set end */
+ end= bezt;
+
+ /* cache values then add keyframes using these values, as adding
+ * keyframes while sampling will affect the outcome...
+ */
+ range= (int)( ceil(end->vec[1][0] - start->vec[1][0]) );
+ sfra= (int)( floor(start->vec[1][0]) );
+
+ if (range) {
+ value_cache= MEM_callocN(sizeof(tempFrameValCache)*range, "IcuFrameValCache");
+
+ /* sample values */
+ for (n=0, fp=value_cache; n<range && fp; n++, fp++) {
+ fp->frame= (float)(sfra + n);
+ fp->val= evaluate_fcurve(fcu, fp->frame);
+ }
+
+ /* add keyframes with these */
+ for (n=0, fp=value_cache; n<range && fp; n++, fp++) {
+ insert_vert_fcurve(fcu, fp->frame, fp->val, 1);
+ }
+
+ /* free temp cache */
+ MEM_freeN(value_cache);
+
+ /* as we added keyframes, we need to compensate so that bezt is at the right place */
+ bezt = fcu->bezt + i + range - 1;
+ i += (range - 1);
+ }
+
+ /* bezt was selected, so it now marks the start of a whole new chain to search */
+ start= bezt;
+ end= NULL;
+ }
+ else {
+ /* just set start keyframe */
+ start= bezt;
+ end= NULL;
+ }
+ }
+ }
+
+ /* recalculate channel's handles? */
+ calchandles_fcurve(fcu);
+ }
+
+ /* admin and redraws */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int graphkeys_sample_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* sample keyframes */
+ sample_graph_keys(&ac);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_sample (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Sample Keyframes";
+ ot->idname= "GRAPHEDIT_OT_keyframes_sample";
+
+ /* api callbacks */
+ ot->exec= graphkeys_sample_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+/* ************************************************************************** */
+/* SETTINGS STUFF */
+
+/* ******************** Set Extrapolation-Type Operator *********************** */
+
+/* defines for set extrapolation-type for selected keyframes tool */
+EnumPropertyItem prop_graphkeys_expo_types[] = {
+ {FCURVE_EXTRAPOLATE_CONSTANT, "CONSTANT", "Constant Extrapolation", ""},
+ {FCURVE_EXTRAPOLATE_LINEAR, "LINEAR", "Linear Extrapolation", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* this function is responsible for setting extrapolation mode for keyframes */
+static void setexpo_graph_keys(bAnimContext *ac, short mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE| ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through setting mode per F-Curve */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ FCurve *fcu= (FCurve *)ale->data;
+ fcu->extend= mode;
+ }
+
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int graphkeys_expo_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get handle setting mode */
+ mode= RNA_enum_get(op->ptr, "type");
+
+ /* set handle type */
+ setexpo_graph_keys(&ac, mode);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_extrapolation_type (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Keyframe Extrapolation";
+ ot->idname= "GRAPHEDIT_OT_keyframes_extrapolation_type";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= graphkeys_expo_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ RNA_def_enum(ot->srna, "type", prop_graphkeys_expo_types, 0, "Type", "");
+}
+
+/* ******************** Set Interpolation-Type Operator *********************** */
+
+/* defines for set ipo-type for selected keyframes tool */
+EnumPropertyItem prop_graphkeys_ipo_types[] = {
+ {BEZT_IPO_CONST, "CONSTANT", "Constant Interpolation", ""},
+ {BEZT_IPO_LIN, "LINEAR", "Linear Interpolation", ""},
+ {BEZT_IPO_BEZ, "BEZIER", "Bezier Interpolation", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* this function is responsible for setting interpolation mode for keyframes */
+static void setipo_graph_keys(bAnimContext *ac, short mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ BeztEditFunc set_cb= ANIM_editkeyframes_ipo(mode);
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE| ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through setting BezTriple interpolation
+ * Note: we do not supply BeztEditData to the looper yet. Currently that's not necessary here...
+ */
+ for (ale= anim_data.first; ale; ale= ale->next)
+ ANIM_fcurve_keys_bezier_loop(NULL, ale->key_data, NULL, set_cb, calchandles_fcurve);
+
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int graphkeys_ipo_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get handle setting mode */
+ mode= RNA_enum_get(op->ptr, "type");
+
+ /* set handle type */
+ setipo_graph_keys(&ac, mode);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_interpolation_type (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Keyframe Interpolation";
+ ot->idname= "GRAPHEDIT_OT_keyframes_interpolation_type";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= graphkeys_ipo_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ RNA_def_enum(ot->srna, "type", prop_graphkeys_ipo_types, 0, "Type", "");
+}
+
+/* ******************** Set Handle-Type Operator *********************** */
+
+/* defines for set handle-type for selected keyframes tool */
+EnumPropertyItem prop_graphkeys_handletype_types[] = {
+ {HD_AUTO, "AUTO", "Auto Handles", ""},
+ {HD_VECT, "VECTOR", "Vector Handles", ""},
+ {HD_FREE, "FREE", "Free Handles", ""},
+ {HD_ALIGN, "ALIGN", "Aligned Handles", ""},
+// {-1, "TOGGLE", "Toggle between Free and Aligned Handles", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* this function is responsible for setting handle-type of selected keyframes */
+static void sethandles_graph_keys(bAnimContext *ac, short mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ BeztEditFunc set_cb= ANIM_editkeyframes_handles(mode);
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE| ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through setting flags for handles
+ * Note: we do not supply BeztEditData to the looper yet. Currently that's not necessary here...
+ */
+ // XXX we might need to supply BeztEditData to get it to only affect selected handles
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ if (mode == -1) {
+ BeztEditFunc toggle_cb;
+
+ /* check which type of handle to set (free or aligned)
+ * - check here checks for handles with free alignment already
+ */
+ if (ANIM_fcurve_keys_bezier_loop(NULL, ale->key_data, NULL, set_cb, NULL))
+ toggle_cb= ANIM_editkeyframes_handles(HD_FREE);
+ else
+ toggle_cb= ANIM_editkeyframes_handles(HD_ALIGN);
+
+ /* set handle-type */
+ ANIM_fcurve_keys_bezier_loop(NULL, ale->key_data, NULL, toggle_cb, calchandles_fcurve);
+ }
+ else {
+ /* directly set handle-type */
+ ANIM_fcurve_keys_bezier_loop(NULL, ale->key_data, NULL, set_cb, calchandles_fcurve);
+ }
+ }
+
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int graphkeys_handletype_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get handle setting mode */
+ mode= RNA_enum_get(op->ptr, "type");
+
+ /* set handle type */
+ sethandles_graph_keys(&ac, mode);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_handletype (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Keyframe Handle Type";
+ ot->idname= "GRAPHEDIT_OT_keyframes_handletype";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= graphkeys_handletype_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ RNA_def_enum(ot->srna, "type", prop_graphkeys_handletype_types, 0, "Type", "");
+}
+
+/* ************************************************************************** */
+/* TRANSFORM STUFF */
+
+/* ***************** 'Euler Filter' Operator **************************** */
+/* Euler filter tools (as seen in Maya), are necessary for working with 'baked'
+ * rotation curves (with Euler rotations). The main purpose of such tools is to
+ * resolve any discontinuities that may arise in the curves due to the clamping
+ * of values to -180 degrees to 180 degrees.
+ */
+
+#if 0 // XXX this is not ready for the primetime yet
+
+/* set of three euler-rotation F-Curves */
+typedef struct tEulerFilter {
+ ID *id; /* ID-block which owns the channels */
+ FCurve *fcu1, *fcu2, *fcu3; /* x,y,z rotation curves */
+ int i1, i2, i3; /* current index for each curve */
+} tEulerFilter;
+
+static int graphkeys_euler_filter_exec (bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ ListBase anim_data= {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ ListBase eulers = {NULL, NULL};
+ tEulerFilter *euf= NULL;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* The process is done in two passes:
+ * 1) Sets of three related rotation curves are identified from the selected channels,
+ * and are stored as a single 'operation unit' for the next step
+ * 2) Each set of three F-Curves is processed for each keyframe, with the values being
+ * processed according to one of several ways.
+ */
+
+ /* step 1: extract only the rotation f-curves */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ FCurve *fcu = (FCurve *)ale->data;
+
+ /* check if this is an appropriate F-Curve
+ * - only rotation curves
+ * - for pchan curves, make sure we're only using the euler curves
+ */
+ if (ELEM(0, fcu->rna_path, strstr(fcu->rna_path, "rotation")))
+ continue;
+ if (strstr(fcu->rna_path, "pose.pose_channels")) {
+ if (strstr(fcu->rna_path, "euler_rotation") == 0)
+ continue;
+ }
+
+ /* check if current set of 3-curves is suitable to add this curve to
+ * - things like whether the current set of curves is 'full' should be checked later only
+ * - first check if id-blocks are compatible
+ */
+ if ((euf) && (ale->id != euf->id)) {
+
+ }
+ }
+
+ // XXX for now
+ return OPERATOR_CANCELLED;
+}
+
+void GRAPHEDIT_OT_keyframes_euler_filter (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Euler Filter";
+ ot->idname= "GRAPHEDIT_OT_keyframes_euler_filter";
+
+ /* api callbacks */
+ ot->exec= graphkeys_euler_filter_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+#endif // XXX this is not ready for the primetime yet
+
+/* ***************** Snap Current Frame Operator *********************** */
+
+/* snap current-frame indicator to 'average time' of selected keyframe */
+static int graphkeys_cfrasnap_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ ListBase anim_data= {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ BeztEditData bed;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* init edit data */
+ memset(&bed, 0, sizeof(BeztEditData));
+
+ /* loop over action data, averaging values */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE| ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale= anim_data.first; ale; ale= ale->next)
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL);
+
+ BLI_freelistN(&anim_data);
+
+ /* set the new current frame value, based on the average time */
+ if (bed.i1) {
+ Scene *scene= ac.scene;
+ CFRA= (int)floor((bed.f1 / bed.i1) + 0.5f);
+ }
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_SCENE|ND_FRAME, ac.scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_cfrasnap (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Snap Current Frame to Keys";
+ ot->idname= "GRAPHEDIT_OT_keyframes_cfrasnap";
+
+ /* api callbacks */
+ ot->exec= graphkeys_cfrasnap_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ******************** Snap Keyframes Operator *********************** */
+
+/* defines for snap keyframes tool */
+EnumPropertyItem prop_graphkeys_snap_types[] = {
+ {GRAPHKEYS_SNAP_CFRA, "CFRA", "Current frame", ""},
+ {GRAPHKEYS_SNAP_NEAREST_FRAME, "NEAREST_FRAME", "Nearest Frame", ""}, // XXX as single entry?
+ {GRAPHKEYS_SNAP_NEAREST_SECOND, "NEAREST_SECOND", "Nearest Second", ""}, // XXX as single entry?
+ {GRAPHKEYS_SNAP_NEAREST_MARKER, "NEAREST_MARKER", "Nearest Marker", ""},
+ {GRAPHKEYS_SNAP_HORIZONTAL, "HORIZONTAL", "Flatten Handles", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* this function is responsible for snapping keyframes to frame-times */
+static void snap_graph_keys(bAnimContext *ac, short mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BeztEditData bed;
+ BeztEditFunc edit_cb;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE| ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get beztriple editing callbacks */
+ edit_cb= ANIM_editkeyframes_snap(mode);
+
+ memset(&bed, 0, sizeof(BeztEditData));
+ bed.scene= ac->scene;
+
+ /* snap keyframes */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ if (nob) {
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
+ }
+ else
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+ }
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int graphkeys_snap_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get snapping mode */
+ mode= RNA_enum_get(op->ptr, "type");
+
+ /* snap keyframes */
+ snap_graph_keys(&ac, mode);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_snap (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Snap Keys";
+ ot->idname= "GRAPHEDIT_OT_keyframes_snap";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= graphkeys_snap_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ RNA_def_enum(ot->srna, "type", prop_graphkeys_snap_types, 0, "Type", "");
+}
+
+/* ******************** Mirror Keyframes Operator *********************** */
+
+/* defines for mirror keyframes tool */
+EnumPropertyItem prop_graphkeys_mirror_types[] = {
+ {GRAPHKEYS_MIRROR_CFRA, "CFRA", "Current frame", ""},
+ {GRAPHKEYS_MIRROR_YAXIS, "YAXIS", "Vertical Axis", ""},
+ {GRAPHKEYS_MIRROR_XAXIS, "XAXIS", "Horizontal Axis", ""},
+ {GRAPHKEYS_MIRROR_MARKER, "MARKER", "First Selected Marker", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* this function is responsible for mirroring keyframes */
+static void mirror_graph_keys(bAnimContext *ac, short mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BeztEditData bed;
+ BeztEditFunc edit_cb;
+
+ /* get beztriple editing callbacks */
+ edit_cb= ANIM_editkeyframes_mirror(mode);
+
+ memset(&bed, 0, sizeof(BeztEditData));
+ bed.scene= ac->scene;
+
+ /* for 'first selected marker' mode, need to find first selected marker first! */
+ // XXX should this be made into a helper func in the API?
+ if (mode == GRAPHKEYS_MIRROR_MARKER) {
+ Scene *scene= ac->scene;
+ TimeMarker *marker= NULL;
+
+ /* find first selected marker */
+ for (marker= scene->markers.first; marker; marker=marker->next) {
+ if (marker->flag & SELECT) {
+ break;
+ }
+ }
+
+ /* store marker's time (if available) */
+ if (marker)
+ bed.f1= (float)marker->frame;
+ else
+ return;
+ }
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE| ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* mirror keyframes */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ if (nob) {
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
+ }
+ else
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+ }
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int graphkeys_mirror_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get mirroring mode */
+ mode= RNA_enum_get(op->ptr, "type");
+
+ /* mirror keyframes */
+ mirror_graph_keys(&ac, mode);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_mirror (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mirror Keys";
+ ot->idname= "GRAPHEDIT_OT_keyframes_mirror";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= graphkeys_mirror_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ RNA_def_enum(ot->srna, "type", prop_graphkeys_mirror_types, 0, "Type", "");
+}
+
+/* ******************** Smooth Keyframes Operator *********************** */
+
+static int graphkeys_smooth_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE| ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* smooth keyframes */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ /* For now, we can only smooth by flattening handles AND smoothing curve values.
+ * Perhaps the mode argument could be removed, as that functionality is offerred through
+ * Snap->Flatten Handles anyway.
+ */
+ smooth_fcurve(ale->key_data);
+ }
+ BLI_freelistN(&anim_data);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_smooth (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Smooth Keys";
+ ot->idname= "GRAPHEDIT_OT_keyframes_smooth";
+
+ /* api callbacks */
+ ot->exec= graphkeys_smooth_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ************************************************************************** */
+/* F-CURVE MODIFIERS */
+
+/* ******************** Add F-Curve Modifier Operator *********************** */
+
+/* F-Modifier types - duplicate of existing codes... */
+ // XXX how can we have this list from the RNA definitions instead?
+EnumPropertyItem prop_fmodifier_types[] = {
+ {FMODIFIER_TYPE_GENERATOR, "GENERATOR", "Generator", ""},
+ {FMODIFIER_TYPE_ENVELOPE, "ENVELOPE", "Envelope", ""},
+ {FMODIFIER_TYPE_CYCLES, "CYCLES", "Cycles", ""},
+ {FMODIFIER_TYPE_NOISE, "NOISE", "Noise", ""},
+ {FMODIFIER_TYPE_FILTER, "FILTER", "Filter", ""},
+ {FMODIFIER_TYPE_PYTHON, "PYTHON", "Python", ""},
+ {FMODIFIER_TYPE_LIMITS, "LIMITS", "Limits", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int graph_fmodifier_add_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ bAnimListElem *ale;
+ FCurve *fcu;
+ FModifier *fcm;
+ short type;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ // xxx call the raw methods here instead?
+ ale= get_active_fcurve_channel(&ac);
+ if (ale == NULL)
+ return OPERATOR_CANCELLED;
+
+ fcu= (FCurve *)ale->data;
+ MEM_freeN(ale);
+ if (fcu == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* get type of modifier to add */
+ type= RNA_enum_get(op->ptr, "type");
+
+ /* add F-Modifier of specified type to active F-Curve, and make it the active one */
+ fcm= fcurve_add_modifier(fcu, type);
+ if (fcm)
+ fcurve_set_active_modifier(fcu, fcm);
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Modifier couldn't be added. See console for details.");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_fmodifier_add (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add F-Curve Modifier";
+ ot->idname= "GRAPHEDIT_OT_fmodifier_add";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= graph_fmodifier_add_exec;
+ ot->poll= ED_operator_areaactive; // XXX need active F-Curve
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ RNA_def_enum(ot->srna, "type", prop_fmodifier_types, 0, "Type", "");
+}
+
+/* ************************************************************************** */
diff --git a/source/blender/editors/space_graph/graph_header.c b/source/blender/editors/space_graph/graph_header.c
new file mode 100644
index 00000000000..178b4b4562f
--- /dev/null
+++ b/source/blender/editors/space_graph/graph_header.c
@@ -0,0 +1,241 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_anim_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_anim_api.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "graph_intern.h"
+
+/* ********************************************************* */
+/* Menu Defines... */
+
+/* button events */
+enum {
+ B_REDR = 0,
+ B_MODECHANGE,
+} eActHeader_ButEvents;
+
+/* ************************ header area region *********************** */
+
+static void do_viewmenu(bContext *C, void *arg, int event)
+{
+ SpaceIpo *sipo= (SpaceIpo *)CTX_wm_space_data(C);
+
+ switch (event) {
+ case 1: /* Show time/frames */
+ sipo->flag ^= SIPO_DRAWTIME;
+ break;
+ case 2: /* AutoMerge Keyframes */
+ sipo->flag ^= SIPO_NOTRANSKEYCULL;
+ break;
+ case 3: /* Show/Hide handles */
+ sipo->flag ^= SIPO_NOHANDLES;
+ break;
+ case 4: /* Show current frame number beside indicator */
+ sipo->flag ^= SIPO_NODRAWCFRANUM;
+ break;
+ }
+}
+
+static uiBlock *graph_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ SpaceIpo *sipo= (SpaceIpo *)CTX_wm_space_data(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "graph_viewmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_viewmenu, NULL);
+
+ // XXX these options should use new menu-options
+
+ if (sipo->flag & SIPO_DRAWTIME) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Show Frames|Ctrl T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ }
+ else {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Show Seconds|Ctrl T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ }
+
+
+ uiDefIconTextBut(block, BUTM, 1, (sipo->flag & SIPO_NOTRANSKEYCULL)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT,
+ "AutoMerge Keyframes|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, (sipo->flag & SIPO_NOHANDLES)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT,
+ "Show Handles|Ctrl H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, (sipo->flag & SIPO_NODRAWCFRANUM)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT,
+ "Show Current Frame Number|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+
+ if (curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static void do_graph_buttons(bContext *C, void *arg, int event)
+{
+ switch (event) {
+ case B_MODECHANGE: /* change mode with mode selector */
+ ED_area_tag_refresh(CTX_wm_area(C));
+ /* no break, as we need redraw flush too... */
+
+ case B_REDR:
+ ED_area_tag_redraw(CTX_wm_area(C));
+ break;
+ }
+}
+
+
+void graph_header_buttons(const bContext *C, ARegion *ar)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceIpo *sipo= (SpaceIpo *)CTX_wm_space_data(C);
+ uiBlock *block;
+ int xco, yco= 3;
+
+ block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_graph_buttons, NULL);
+
+ xco= ED_area_header_standardbuttons(C, block, yco);
+
+ if ((sa->flag & HEADER_NO_PULLDOWN)==0) {
+ int xmax;
+
+ xmax= GetButStringLength("View");
+ uiDefPulldownBut(block, graph_viewmenu, CTX_wm_area(C),
+ "View", xco, yco-2, xmax-3, 24, "");
+ xco+= xmax;
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ /* mode selector */
+ uiDefButS(block, MENU, B_MODECHANGE,
+ "Editor Mode %t|F-Curve Editor %x0|Drivers %x1",
+ xco,yco,110,YIC, &sipo->mode, 0, 1, 0, 0,
+ "Editing modes for this editor");
+ xco+= 120;
+
+ /* filtering buttons */
+ if (sipo->ads) {
+ //uiBlockBeginAlign(block);
+ uiDefIconButBitI(block, TOG, ADS_FILTER_ONLYSEL, B_REDR, ICON_RESTRICT_SELECT_OFF, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Only display selected Objects");
+ //uiBlockEndAlign(block);
+ xco += 5;
+
+ uiBlockBeginAlign(block);
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOSCE, B_REDR, ICON_SCENE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Display Scene Animation");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOWOR, B_REDR, ICON_WORLD_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Display World Animation");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOSHAPEKEYS, B_REDR, ICON_SHAPEKEY_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Display ShapeKeys");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOMAT, B_REDR, ICON_MATERIAL_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Display Materials");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOLAM, B_REDR, ICON_LAMP_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Display Lamps");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCAM, B_REDR, ICON_CAMERA_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Display Cameras");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCUR, B_REDR, ICON_CURVE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Display Curves");
+ uiBlockEndAlign(block);
+ xco += 15;
+ }
+ else {
+ // XXX this case shouldn't happen at all... for now, just pad out same amount of space
+ xco += 6*XIC + 15;
+ }
+
+ /* copy + paste */
+ uiBlockBeginAlign(block);
+ uiDefIconButO(block, BUT, "GRAPHEDIT_OT_keyframes_copy", WM_OP_INVOKE_REGION_WIN, ICON_COPYDOWN, xco+=XIC,yco,XIC,YIC, "Copies the selected keyframes from the selected channel(s) to the buffer");
+ uiDefIconButO(block, BUT, "GRAPHEDIT_OT_keyframes_paste", WM_OP_INVOKE_REGION_WIN, ICON_PASTEDOWN, xco+=XIC,yco,XIC,YIC, "Pastes the keyframes from the buffer");
+ uiBlockEndAlign(block);
+ xco += (XIC + 8);
+
+ /* auto-snap selector */
+ if (sipo->flag & SIPO_DRAWTIME) {
+ uiDefButS(block, MENU, B_REDR,
+ "Auto-Snap Keyframes %t|No Time-Snap %x0|Nearest Second %x2|Nearest Marker %x3",
+ xco,yco,90,YIC, &sipo->autosnap, 0, 1, 0, 0,
+ "Auto-snapping mode for keyframe times when transforming");
+ }
+ else {
+ uiDefButS(block, MENU, B_REDR,
+ "Auto-Snap Keyframes %t|No Time-Snap %x0|Nearest Frame %x2|Nearest Marker %x3",
+ xco,yco,90,YIC, &sipo->autosnap, 0, 1, 0, 0,
+ "Auto-snapping mode for keyframe times when transforming");
+ }
+ xco += 98;
+
+ /* ghost curves */
+ // XXX these icons need to be changed
+ if (sipo->ghostCurves.first)
+ uiDefIconButO(block, BUT, "GRAPHEDIT_OT_ghost_curves_clear", WM_OP_INVOKE_REGION_WIN, ICON_OUTLINER_DATA_CURVE, xco,yco,XIC,YIC, "Clear F-Curve snapshots (Ghosts) for this Graph Editor instance");
+ else
+ uiDefIconButO(block, BUT, "GRAPHEDIT_OT_ghost_curves_create", WM_OP_INVOKE_REGION_WIN, ICON_OUTLINER_OB_CURVE, xco,yco,XIC,YIC, "Create snapshot (Ghosts) of selected F-Curves as background aid for this Graph Editor instance");
+ xco+= XIC;
+
+
+ /* always as last */
+ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, (int)(ar->v2d.tot.ymax - ar->v2d.tot.ymin));
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+}
+
+
diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h
new file mode 100644
index 00000000000..a06cdddbec8
--- /dev/null
+++ b/source/blender/editors/space_graph/graph_intern.h
@@ -0,0 +1,151 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_GRAPH_INTERN_H
+#define ED_GRAPH_INTERN_H
+
+struct bContext;
+struct wmWindowManager;
+struct bAnimContext;
+struct bAnimListElem;
+struct SpaceIpo;
+struct ScrArea;
+struct ARegion;
+struct View2DGrid;
+
+/* internal exports only */
+
+/* ***************************************** */
+/* space_graph.c */
+struct ARegion *graph_has_buttons_region(struct ScrArea *sa);
+
+/* ***************************************** */
+/* graph_draw.c */
+void graph_draw_channel_names(struct bAnimContext *ac, struct SpaceIpo *sipo, struct ARegion *ar);
+
+void graph_draw_curves(struct bAnimContext *ac, struct SpaceIpo *sipo, struct ARegion *ar, struct View2DGrid *grid, short sel);
+void graph_draw_ghost_curves(struct bAnimContext *ac, struct SpaceIpo *sipo, struct ARegion *ar, struct View2DGrid *grid);
+
+/* ***************************************** */
+/* graph_header.c */
+void graph_header_buttons(const bContext *C, struct ARegion *ar);
+
+/* ***************************************** */
+/* graph_select.c */
+
+void GRAPHEDIT_OT_keyframes_select_all_toggle(struct wmOperatorType *ot);
+void GRAPHEDIT_OT_keyframes_select_border(struct wmOperatorType *ot);
+void GRAPHEDIT_OT_keyframes_columnselect(struct wmOperatorType *ot);
+void GRAPHEDIT_OT_keyframes_clickselect(struct wmOperatorType *ot);
+
+/* defines for left-right select tool */
+enum {
+ GRAPHKEYS_LRSEL_TEST = -1,
+ GRAPHKEYS_LRSEL_NONE,
+ GRAPHKEYS_LRSEL_LEFT,
+ GRAPHKEYS_LRSEL_RIGHT,
+} eGraphKeys_LeftRightSelect_Mode;
+
+/* defines for column-select mode */
+enum {
+ GRAPHKEYS_COLUMNSEL_KEYS = 0,
+ GRAPHKEYS_COLUMNSEL_CFRA,
+ GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN,
+ GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN,
+} eGraphKeys_ColumnSelect_Mode;
+
+/* ***************************************** */
+/* graph_edit.c */
+
+void GRAPHEDIT_OT_previewrange_set(struct wmOperatorType *ot);
+void GRAPHEDIT_OT_view_all(struct wmOperatorType *ot);
+
+void GRAPHEDIT_OT_keyframes_click_insert(struct wmOperatorType *ot);
+
+void GRAPHEDIT_OT_keyframes_copy(struct wmOperatorType *ot);
+void GRAPHEDIT_OT_keyframes_paste(struct wmOperatorType *ot);
+
+void GRAPHEDIT_OT_keyframes_duplicate(struct wmOperatorType *ot);
+void GRAPHEDIT_OT_keyframes_delete(struct wmOperatorType *ot);
+void GRAPHEDIT_OT_keyframes_clean(struct wmOperatorType *ot);
+void GRAPHEDIT_OT_keyframes_sample(struct wmOperatorType *ot);
+void GRAPHEDIT_OT_keyframes_bake(struct wmOperatorType *ot);
+void GRAPHEDIT_OT_keyframes_smooth(struct wmOperatorType *ot);
+
+void GRAPHEDIT_OT_keyframes_handletype(struct wmOperatorType *ot);
+void GRAPHEDIT_OT_keyframes_interpolation_type(struct wmOperatorType *ot);
+void GRAPHEDIT_OT_keyframes_extrapolation_type(struct wmOperatorType *ot);
+
+void GRAPHEDIT_OT_keyframes_cfrasnap(struct wmOperatorType *ot);
+void GRAPHEDIT_OT_keyframes_snap(struct wmOperatorType *ot);
+void GRAPHEDIT_OT_keyframes_mirror(struct wmOperatorType *ot);
+
+/* defines for snap keyframes
+ * NOTE: keep in sync with eEditKeyframes_Snap (in ED_keyframes_edit.h)
+ */
+enum {
+ GRAPHKEYS_SNAP_CFRA = 1,
+ GRAPHKEYS_SNAP_NEAREST_FRAME,
+ GRAPHKEYS_SNAP_NEAREST_SECOND,
+ GRAPHKEYS_SNAP_NEAREST_MARKER,
+ GRAPHKEYS_SNAP_HORIZONTAL,
+} eGraphKeys_Snap_Mode;
+
+/* defines for mirror keyframes
+ * NOTE: keep in sync with eEditKeyframes_Mirror (in ED_keyframes_edit.h)
+ */
+enum {
+ GRAPHKEYS_MIRROR_CFRA = 1,
+ GRAPHKEYS_MIRROR_YAXIS,
+ GRAPHKEYS_MIRROR_XAXIS,
+ GRAPHKEYS_MIRROR_MARKER,
+} eGraphKeys_Mirror_Mode;
+
+/* ----------- */
+
+void GRAPHEDIT_OT_fmodifier_add(struct wmOperatorType *ot);
+
+/* ----------- */
+
+void GRAPHEDIT_OT_ghost_curves_create(struct wmOperatorType *ot);
+void GRAPHEDIT_OT_ghost_curves_clear(struct wmOperatorType *ot);
+
+/* ***************************************** */
+/* graph_buttons.c */
+void GRAPHEDIT_OT_properties(struct wmOperatorType *ot);
+void graph_region_buttons(const struct bContext *C, struct ARegion *ar);
+
+struct bAnimListElem *get_active_fcurve_channel(struct bAnimContext *ac);
+
+/* ***************************************** */
+/* graph_ops.c */
+void graphedit_keymap(struct wmWindowManager *wm);
+void graphedit_operatortypes(void);
+
+
+#endif /* ED_GRAPH_INTERN_H */
+
diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c
new file mode 100644
index 00000000000..a23f0081c04
--- /dev/null
+++ b/source/blender/editors/space_graph/graph_ops.c
@@ -0,0 +1,248 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_action_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_utildefines.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "ED_screen.h"
+
+#include "BIF_transform.h"
+
+#include "graph_intern.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* ************************** view-based operators **********************************/
+// XXX this probably shouldn't be here..
+
+/* Toggle Handles ----------------------------------------------------------------- */
+
+static int view_toggle_handles_exec (bContext *C, wmOperator *op)
+{
+ SpaceIpo *sipo= (SpaceIpo *)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+
+ if (sipo == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* toggle flag to hide handles */
+ sipo->flag ^= SIPO_NOHANDLES;
+
+ /* request refresh of keys area */
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_view_togglehandles (wmOperatorType *ot)
+{
+ /* identification */
+ ot->name= "Show/Hide All Handles";
+ ot->idname= "GRAPHEDIT_OT_handles_view_toggle";
+
+ /* callbacks */
+ ot->exec= view_toggle_handles_exec;
+ ot->poll= ED_operator_areaactive;
+}
+
+/* ************************** registration - operator types **********************************/
+
+void graphedit_operatortypes(void)
+{
+ /* view */
+ WM_operatortype_append(GRAPHEDIT_OT_view_togglehandles);
+ WM_operatortype_append(GRAPHEDIT_OT_previewrange_set);
+ WM_operatortype_append(GRAPHEDIT_OT_view_all);
+ WM_operatortype_append(GRAPHEDIT_OT_properties);
+
+ WM_operatortype_append(GRAPHEDIT_OT_ghost_curves_create);
+ WM_operatortype_append(GRAPHEDIT_OT_ghost_curves_clear);
+
+ /* keyframes */
+ /* selection */
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_clickselect);
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_select_all_toggle);
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_select_border);
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_columnselect);
+
+ /* editing */
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_snap);
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_mirror);
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_cfrasnap);
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_handletype);
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_interpolation_type);
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_extrapolation_type);
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_sample);
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_bake);
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_smooth);
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_clean);
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_delete);
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_duplicate);
+
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_copy);
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_paste);
+
+ WM_operatortype_append(GRAPHEDIT_OT_keyframes_click_insert);
+
+ //TODO: insertkey...
+
+ /* F-Curve Modifiers */
+ // XXX temporary?
+ WM_operatortype_append(GRAPHEDIT_OT_fmodifier_add);
+}
+
+/* ************************** registration - keymaps **********************************/
+
+static void graphedit_keymap_keyframes (wmWindowManager *wm, ListBase *keymap)
+{
+ wmKeymapItem *kmi;
+
+ /* view */
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_handles_view_toggle", HKEY, KM_PRESS, KM_CTRL, 0);
+
+ /* graph_select.c - selection tools */
+ /* click-select */
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, 0, 0);
+ kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "column", 1);
+ kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+ kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT|KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+ RNA_boolean_set(kmi->ptr, "column", 1);
+ kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "left_right", GRAPHKEYS_LRSEL_TEST);
+ kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL|KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "curves", 1);
+ kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL|KM_ALT|KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "curves", 1);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+
+ /* deselect all */
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_select_all_toggle", AKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1);
+
+ /* borderselect */
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_select_border", BKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_select_border", BKEY, KM_PRESS, KM_ALT, 0)->ptr, "axis_range", 1);
+
+ /* column select */
+ // XXX KKEY would be nice to keep for 'keyframe' lines
+ RNA_enum_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_columnselect", KKEY, KM_PRESS, 0, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_KEYS);
+ RNA_enum_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_columnselect", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_CFRA);
+ RNA_enum_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_columnselect", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN);
+ RNA_enum_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_columnselect", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN);
+
+
+ /* graph_edit.c */
+ /* snap - current frame to selected keys */
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_cfrasnap", SKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
+
+ /* menu + single-step transform */
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_mirror", MKEY, KM_PRESS, KM_SHIFT, 0);
+
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_handletype", HKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_interpolation_type", TKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_extrapolation_type", EKEY, KM_PRESS, KM_SHIFT, 0);
+
+
+ /* destructive */
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clean", OKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_smooth", OKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_sample", OKEY, KM_PRESS, KM_SHIFT, 0);
+
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_bake", CKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_delete", DELKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
+
+ /* insertkey */
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_click_insert", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
+
+ /* copy/paste */
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_copy", CKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_paste", VKEY, KM_PRESS, KM_CTRL, 0);
+
+ /* auto-set range */
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
+
+ /* F-Curve Modifiers */
+ // XXX these are temporary? operators...
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
+
+
+ /* transform system */
+ transform_keymap_for_space(wm, keymap, SPACE_IPO);
+}
+
+/* --------------- */
+
+void graphedit_keymap(wmWindowManager *wm)
+{
+ ListBase *keymap;
+
+ /* keymap for all regions */
+ keymap= WM_keymap_listbase(wm, "GraphEdit Generic", SPACE_IPO, 0);
+ WM_keymap_add_item(keymap, "GRAPHEDIT_OT_properties", NKEY, KM_PRESS, 0, 0);
+
+ /* channels */
+ /* Channels are not directly handled by the Graph Editor module, but are inherited from the Animation module.
+ * All the relevant operations, keymaps, drawing, etc. can therefore all be found in that module instead, as these
+ * are all used for the Graph Editor too.
+ */
+
+ /* keyframes */
+ keymap= WM_keymap_listbase(wm, "GraphEdit Keys", SPACE_IPO, 0);
+ graphedit_keymap_keyframes(wm, keymap);
+}
+
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
new file mode 100644
index 00000000000..4b6e55d2a03
--- /dev/null
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -0,0 +1,945 @@
+/**
+ * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_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 "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "BKE_action.h"
+#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+#include "BKE_context.h"
+#include "BKE_utildefines.h"
+
+#include "UI_view2d.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_draw.h"
+#include "ED_keyframes_edit.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "graph_intern.h"
+
+
+/* ************************************************************************** */
+/* KEYFRAMES STUFF */
+
+/* ******************** Deselect All Operator ***************************** */
+/* This operator works in one of three ways:
+ * 1) (de)select all (AKEY) - test if select all or deselect all
+ * 2) invert all (CTRL-IKEY) - invert selection of all keyframes
+ * 3) (de)select all - no testing is done; only for use internal tools as normal function...
+ */
+
+/* Deselects keyframes in the Graph Editor
+ * - This is called by the deselect all operator, as well as other ones!
+ *
+ * - test: check if select or deselect all
+ * - sel: how to select keyframes
+ * 0 = deselect
+ * 1 = select
+ * 2 = invert
+ */
+static void deselect_graph_keys (bAnimContext *ac, short test, short sel)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BeztEditData bed;
+ BeztEditFunc test_cb, sel_cb;
+
+ /* determine type-based settings */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
+
+ /* filter data */
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* init BezTriple looping data */
+ memset(&bed, 0, sizeof(BeztEditData));
+ test_cb= ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
+
+ /* See if we should be selecting or deselecting */
+ if (test) {
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ if (ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, test_cb, NULL)) {
+ sel= SELECT_SUBTRACT;
+ break;
+ }
+ }
+ }
+
+ /* convert sel to selectmode, and use that to get editor */
+ sel_cb= ANIM_editkeyframes_select(sel);
+
+ /* Now set the flags */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ FCurve *fcu= (FCurve *)ale->key_data;
+
+ /* Keyframes First */
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, sel_cb, NULL);
+
+ /* deactivate the F-Curve */
+ fcu->flag &= ~FCURVE_ACTIVE;
+ }
+
+ /* Cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int graphkeys_deselectall_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* 'standard' behaviour - check if selected, then apply relevant selection */
+ if (RNA_boolean_get(op->ptr, "invert"))
+ deselect_graph_keys(&ac, 0, SELECT_INVERT);
+ else
+ deselect_graph_keys(&ac, 1, SELECT_ADD);
+
+ /* set notifier that things have changed */
+ ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_select_all_toggle (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select All";
+ ot->idname= "GRAPHEDIT_OT_keyframes_select_all_toggle";
+
+ /* api callbacks */
+ ot->exec= graphkeys_deselectall_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
+}
+
+/* ******************** Border Select Operator **************************** */
+/* This operator currently works in one of three ways:
+ * -> BKEY - 1) all keyframes within region are selected (validation with BEZT_OK_REGION)
+ * -> ALT-BKEY - depending on which axis of the region was larger...
+ * -> 2) x-axis, so select all frames within frame range (validation with BEZT_OK_FRAMERANGE)
+ * -> 3) y-axis, so select all frames within channels that region included (validation with BEZT_OK_VALUERANGE)
+ */
+
+/* Borderselect only selects keyframes now, as overshooting handles often get caught too,
+ * which means that they may be inadvertantly moved as well.
+ * Also, for convenience, handles should get same status as keyframe (if it was within bounds)
+ */
+static void borderselect_graphkeys (bAnimContext *ac, rcti rect, short mode, short selectmode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BeztEditData bed;
+ BeztEditFunc ok_cb, select_cb;
+ View2D *v2d= &ac->ar->v2d;
+ rctf rectf;
+
+ /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
+ UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
+ UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY | ANIMFILTER_CURVEVISIBLE);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get beztriple editing/validation funcs */
+ select_cb= ANIM_editkeyframes_select(selectmode);
+ ok_cb= ANIM_editkeyframes_ok(mode);
+
+ /* init editing data */
+ memset(&bed, 0, sizeof(BeztEditData));
+ bed.data= &rectf;
+
+ /* loop over data, doing border select */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ /* set horizontal range (if applicable) */
+ if (mode != BEZT_OK_VALUERANGE) {
+ /* if channel is mapped in NLA, apply correction */
+ if (nob) {
+ bed.f1= get_action_frame(nob, rectf.xmin);
+ bed.f2= get_action_frame(nob, rectf.xmax);
+ }
+ else {
+ bed.f1= rectf.xmin;
+ bed.f2= rectf.xmax;
+ }
+ }
+ else {
+ bed.f1= rectf.ymin;
+ bed.f2= rectf.ymax;
+ }
+
+ /* select keyframes that are in the appropriate places */
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+ }
+
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int graphkeys_borderselect_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ rcti rect;
+ short mode=0, selectmode=0;
+ int event;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get settings from operator */
+ rect.xmin= RNA_int_get(op->ptr, "xmin");
+ rect.ymin= RNA_int_get(op->ptr, "ymin");
+ rect.xmax= RNA_int_get(op->ptr, "xmax");
+ rect.ymax= RNA_int_get(op->ptr, "ymax");
+
+ event= RNA_int_get(op->ptr, "event_type");
+ if (event == LEFTMOUSE) // FIXME... hardcoded
+ selectmode = SELECT_ADD;
+ else
+ selectmode = SELECT_SUBTRACT;
+
+ /* selection 'mode' depends on whether borderselect region only matters on one axis */
+ if (RNA_boolean_get(op->ptr, "axis_range")) {
+ /* mode depends on which axis of the range is larger to determine which axis to use
+ * - checking this in region-space is fine, as it's fundamentally still going to be a different rect size
+ * - the frame-range select option is favoured over the channel one (x over y), as frame-range one is often
+ * used for tweaking timing when "blocking", while channels is not that useful...
+ */
+ if ((rect.xmax - rect.xmin) >= (rect.ymax - rect.ymin))
+ mode= BEZT_OK_FRAMERANGE;
+ else
+ mode= BEZT_OK_VALUERANGE;
+ }
+ else
+ mode= BEZT_OK_REGION;
+
+ /* apply borderselect action */
+ borderselect_graphkeys(&ac, rect, mode, selectmode);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_select_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Border Select";
+ ot->idname= "GRAPHEDIT_OT_keyframes_select_border";
+
+ /* api callbacks */
+ ot->invoke= WM_border_select_invoke;
+ ot->exec= graphkeys_borderselect_exec;
+ ot->modal= WM_border_select_modal;
+
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+
+ /* rna */
+ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+
+ RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
+}
+
+/* ******************** Column Select Operator **************************** */
+/* This operator works in one of four ways:
+ * - 1) select all keyframes in the same frame as a selected one (KKEY)
+ * - 2) select all keyframes in the same frame as the current frame marker (CTRL-KKEY)
+ * - 3) select all keyframes in the same frame as a selected markers (SHIFT-KKEY)
+ * - 4) select all keyframes that occur between selected markers (ALT-KKEY)
+ */
+
+/* defines for column-select mode */
+static EnumPropertyItem prop_column_select_types[] = {
+ {GRAPHKEYS_COLUMNSEL_KEYS, "KEYS", "On Selected Keyframes", ""},
+ {GRAPHKEYS_COLUMNSEL_CFRA, "CFRA", "On Current Frame", ""},
+ {GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN, "MARKERS_COLUMN", "On Selected Markers", ""},
+ {GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN, "MARKERS_BETWEEN", "Between Min/Max Selected Markers", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* ------------------- */
+
+/* Selects all visible keyframes between the specified markers */
+static void markers_selectkeys_between (bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BeztEditFunc select_cb;
+ BeztEditData bed;
+ float min, max;
+
+ /* get extreme markers */
+ //get_minmax_markers(1, &min, &max); // FIXME... add back markers api!
+ min= (float)ac->scene->r.sfra; // xxx temp code
+ max= (float)ac->scene->r.efra; // xxx temp code
+
+ if (min==max) return;
+ min -= 0.5f;
+ max += 0.5f;
+
+ /* get editing funcs + data */
+ select_cb= ANIM_editkeyframes_select(SELECT_ADD);
+ memset(&bed, 0, sizeof(BeztEditData));
+ bed.f1= min;
+ bed.f2= max;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* select keys in-between */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ if (nob) {
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, select_cb, NULL);
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
+ }
+ else {
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, select_cb, NULL);
+ }
+ }
+
+ /* Cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+
+/* helper callback for columnselect_graph_keys() -> populate list CfraElems with frame numbers from selected beztriples */
+// TODO: if some other code somewhere needs this, it'll be time to port this over to keyframes_edit.c!!!
+static short bezt_to_cfraelem(BeztEditData *bed, BezTriple *bezt)
+{
+ /* only if selected */
+ if (bezt->f2 & SELECT) {
+ CfraElem *ce= MEM_callocN(sizeof(CfraElem), "cfraElem");
+ BLI_addtail(&bed->list, ce);
+
+ ce->cfra= bezt->vec[1][0];
+ }
+
+ return 0;
+}
+
+/* Selects all visible keyframes in the same frames as the specified elements */
+static void columnselect_graph_keys (bAnimContext *ac, short mode)
+{
+ ListBase anim_data= {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ Scene *scene= ac->scene;
+ CfraElem *ce;
+ BeztEditFunc select_cb, ok_cb;
+ BeztEditData bed;
+
+ /* initialise keyframe editing data */
+ memset(&bed, 0, sizeof(BeztEditData));
+
+ /* build list of columns */
+ switch (mode) {
+ case GRAPHKEYS_COLUMNSEL_KEYS: /* list of selected keys */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale= anim_data.first; ale; ale= ale->next)
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_to_cfraelem, NULL);
+
+ BLI_freelistN(&anim_data);
+ break;
+
+ case GRAPHKEYS_COLUMNSEL_CFRA: /* current frame */
+ /* make a single CfraElem for storing this */
+ ce= MEM_callocN(sizeof(CfraElem), "cfraElem");
+ BLI_addtail(&bed.list, ce);
+
+ ce->cfra= (float)CFRA;
+ break;
+
+ case GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
+ // FIXME: markers api needs to be improved for this first!
+ //make_marker_cfra_list(&elems, 1);
+ return; // XXX currently, this does nothing!
+ break;
+
+ default: /* invalid option */
+ return;
+ }
+
+ /* set up BezTriple edit callbacks */
+ select_cb= ANIM_editkeyframes_select(SELECT_ADD);
+ ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAME);
+
+ /* loop through all of the keys and select additional keyframes
+ * based on the keys found to be selected above
+ */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ /* loop over cfraelems (stored in the BeztEditData->list)
+ * - we need to do this here, as we can apply fewer NLA-mapping conversions
+ */
+ for (ce= bed.list.first; ce; ce= ce->next) {
+ /* set frame for validation callback to refer to */
+ if (nob)
+ bed.f1= get_action_frame(nob, ce->cfra);
+ else
+ bed.f1= ce->cfra;
+
+ /* select elements with frame number matching cfraelem */
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+ }
+ }
+
+ /* free elements */
+ BLI_freelistN(&bed.list);
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int graphkeys_columnselect_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* action to take depends on the mode */
+ mode= RNA_enum_get(op->ptr, "mode");
+
+ if (mode == GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN)
+ markers_selectkeys_between(&ac);
+ else
+ columnselect_graph_keys(&ac, mode);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_SELECT);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPHEDIT_OT_keyframes_columnselect (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select All";
+ ot->idname= "GRAPHEDIT_OT_keyframes_columnselect";
+
+ /* api callbacks */
+ ot->exec= graphkeys_columnselect_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+
+ /* props */
+ RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
+}
+
+/* ******************** Mouse-Click Select Operator *********************** */
+/* This operator works in one of three ways:
+ * - 1) keyframe under mouse - no special modifiers
+ * - 2) all keyframes on the same side of current frame indicator as mouse - ALT modifier
+ * - 3) column select all keyframes in frame under mouse - CTRL modifier
+ *
+ * In addition to these basic options, the SHIFT modifier can be used to toggle the
+ * selection mode between replacing the selection (without) and inverting the selection (with).
+ */
+
+/* defines for left-right select tool */
+static EnumPropertyItem prop_graphkeys_leftright_select_types[] = {
+ {GRAPHKEYS_LRSEL_TEST, "CHECK", "Check if Select Left or Right", ""},
+ {GRAPHKEYS_LRSEL_NONE, "OFF", "Don't select", ""},
+ {GRAPHKEYS_LRSEL_LEFT, "LEFT", "Before current frame", ""},
+ {GRAPHKEYS_LRSEL_RIGHT, "RIGHT", "After current frame", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* ------------------- */
+
+enum {
+ NEAREST_HANDLE_LEFT = 0,
+ NEAREST_HANDLE_KEY,
+ NEAREST_HANDLE_RIGHT
+} eHandleIndex;
+
+/* Find the vertex (either handle (0/2) or the keyframe (1)) that is nearest to the mouse cursor (in area coordinates)
+ * Selected verts get a disadvantage, to make it easier to select handles behind.
+ * Returns eHandleIndex
+ */
+static short findnearest_fcurve_vert (bAnimContext *ac, int mval[2], FCurve **fcurve, BezTriple **bezt)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first;
+ View2D *v2d= &ac->ar->v2d;
+ int hpoint=0, sco[3][2];
+ int dist= 100, temp, i;
+
+ /* clear pointers first */
+ *fcurve= 0;
+ *bezt= 0;
+
+ /* get curves to search through */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ FCurve *fcu= (FCurve *)ale->key_data;
+
+ /* try to progressively get closer to the right point... */
+ if (fcu->bezt) {
+ BezTriple *bezt1=fcu->bezt, *prevbezt=NULL;
+
+ for (i=0; i < fcu->totvert; i++, prevbezt=bezt1, bezt1++) {
+ /* convert beztriple points to screen-space */
+ UI_view2d_to_region_no_clip(v2d, bezt1->vec[0][0], bezt1->vec[0][1], &sco[0][0], &sco[0][1]);
+ UI_view2d_to_region_no_clip(v2d, bezt1->vec[1][0], bezt1->vec[1][1], &sco[1][0], &sco[1][1]);
+ UI_view2d_to_region_no_clip(v2d, bezt1->vec[2][0], bezt1->vec[2][1], &sco[2][0], &sco[2][1]);
+
+ /* keyframe - do select? */
+ temp= abs(mval[0] - sco[1][0]) + abs(mval[1] - sco[1][1]);
+
+ if (bezt1->f2 & SELECT)
+ temp += 5;
+
+ if (temp < dist) {
+ hpoint= NEAREST_HANDLE_KEY;
+ *bezt= bezt1;
+ dist= temp;
+ *fcurve= fcu;
+ }
+
+ /* handles - only do them if they're visible */
+ // XXX also need to check for int-values only?
+ if ((sipo->flag & SIPO_NOHANDLES)==0) {
+ /* first handle only visible if previous segment had handles */
+ if ( (!prevbezt && (bezt1->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ)) )
+ {
+ temp= -3 + abs(mval[0] - sco[0][0]) + abs(mval[1] - sco[0][1]);
+ if (bezt1->f1 & SELECT)
+ temp += 5;
+
+ if (temp < dist) {
+ hpoint= NEAREST_HANDLE_LEFT;
+ *bezt= bezt1;
+ dist= temp;
+ *fcurve= fcu;
+ }
+ }
+
+ /* second handle only visible if this segment is bezier */
+ if (bezt1->ipo == BEZT_IPO_BEZ)
+ {
+ temp= abs(mval[0] - sco[2][0]) + abs(mval[1] - sco[2][1]);
+ if (bezt1->f3 & SELECT)
+ temp += 5;
+
+ if (temp < dist) {
+ hpoint= NEAREST_HANDLE_RIGHT;
+ *bezt=bezt1;
+ dist= temp;
+ *fcurve= fcu;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* free channels */
+ BLI_freelistN(&anim_data);
+
+ /* return handle */
+ return hpoint;
+}
+
+/* option 1) select keyframe directly under mouse */
+static void mouse_graph_keys (bAnimContext *ac, int mval[], short select_mode, short curves_only)
+{
+ FCurve *fcu;
+ BezTriple *bezt;
+ short handle;
+ int filter;
+
+ /* find the beztriple that we're selecting, and the handle that was clicked on */
+ handle= findnearest_fcurve_vert(ac, mval, &fcu, &bezt);
+
+ /* check if anything to select */
+ if (fcu == NULL)
+ return;
+
+ /* deselect all other curves? */
+ if (select_mode == SELECT_REPLACE) {
+ /* reset selection mode */
+ select_mode= SELECT_ADD;
+
+ /* deselect all other channels and keyframes */
+ //ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ deselect_graph_keys(ac, 0, SELECT_SUBTRACT);
+ }
+
+ /* if points can be selected on this F-Curve */
+ // TODO: what about those with no keyframes?
+ if ((curves_only == 0) && ((fcu->flag & FCURVE_PROTECTED)==0)) {
+ /* only if there's keyframe */
+ if (bezt) {
+ /* depends on selection mode */
+ if (select_mode == SELECT_INVERT) {
+ /* keyframe - invert select of all */
+ if (handle == NEAREST_HANDLE_KEY) {
+ if (BEZSELECTED(bezt)) {
+ BEZ_DESEL(bezt);
+ }
+ else {
+ BEZ_SEL(bezt);
+ }
+ }
+
+ /* handles - toggle selection of relevant handle */
+ else if (handle == NEAREST_HANDLE_LEFT) {
+ /* toggle selection */
+ bezt->f1 ^= SELECT;
+ }
+ else {
+ /* toggle selection */
+ bezt->f3 ^= SELECT;
+ }
+ }
+ else {
+ /* if the keyframe was clicked on, select all verts of given beztriple */
+ if (handle == NEAREST_HANDLE_KEY) {
+ BEZ_SEL(bezt);
+ }
+ /* otherwise, select the handle that applied */
+ else if (handle == NEAREST_HANDLE_LEFT)
+ bezt->f1 |= SELECT;
+ else
+ bezt->f3 |= SELECT;
+ }
+ }
+ }
+ else {
+ BeztEditFunc select_cb;
+ BeztEditData bed;
+
+ /* initialise keyframe editing data */
+ memset(&bed, 0, sizeof(BeztEditData));
+
+ /* set up BezTriple edit callbacks */
+ select_cb= ANIM_editkeyframes_select(select_mode);
+
+ /* select all keyframes */
+ ANIM_fcurve_keys_bezier_loop(&bed, fcu, NULL, select_cb, NULL);
+ }
+
+ /* select or deselect curve? */
+ if (select_mode == SELECT_INVERT)
+ fcu->flag ^= FCURVE_SELECTED;
+ else if (select_mode == SELECT_ADD)
+ fcu->flag |= FCURVE_SELECTED;
+
+ /* set active F-Curve (NOTE: sync the filter flags with findnearest_fcurve_vert) */
+ if (fcu->flag & FCURVE_SELECTED) {
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_set_active_channel(ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
+ }
+}
+
+/* Option 2) Selects all the keyframes on either side of the current frame (depends on which side the mouse is on) */
+static void graphkeys_mselect_leftright (bAnimContext *ac, short leftright, short select_mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BeztEditFunc ok_cb, select_cb;
+ BeztEditData bed;
+ Scene *scene= ac->scene;
+
+ /* if select mode is replace, deselect all keyframes (and channels) first */
+ if (select_mode==SELECT_REPLACE) {
+ /* reset selection mode to add to selection */
+ select_mode= SELECT_ADD;
+
+ /* deselect all other channels and keyframes */
+ ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ deselect_graph_keys(ac, 0, SELECT_SUBTRACT);
+ }
+
+ /* set callbacks and editing data */
+ ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
+ select_cb= ANIM_editkeyframes_select(select_mode);
+
+ memset(&bed, 0, sizeof(BeztEditFunc));
+ if (leftright == GRAPHKEYS_LRSEL_LEFT) {
+ bed.f1 = -MAXFRAMEF;
+ bed.f2 = (float)(CFRA + 0.1f);
+ }
+ else {
+ bed.f1 = (float)(CFRA - 0.1f);
+ bed.f2 = MAXFRAMEF;
+ }
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* select keys on the side where most data occurs */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ if (nob) {
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+ ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
+ }
+ else
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+ }
+
+ /* Cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* Option 3) Selects all visible keyframes in the same frame as the mouse click */
+static void graphkeys_mselect_column (bAnimContext *ac, int mval[2], short select_mode)
+{
+ ListBase anim_data= {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BeztEditFunc select_cb, ok_cb;
+ BeztEditData bed;
+ FCurve *fcu;
+ BezTriple *bezt;
+ float selx = (float)ac->scene->r.cfra;
+
+ /* find the beztriple that occurs on this frame, and use his as the frame number we're using */
+ findnearest_fcurve_vert(ac, mval, &fcu, &bezt);
+
+ /* check if anything to select */
+ if (ELEM(NULL, fcu, bezt))
+ return;
+ selx= bezt->vec[1][0];
+
+ /* if select mode is replace, deselect all keyframes (and channels) first */
+ if (select_mode==SELECT_REPLACE) {
+ /* reset selection mode to add to selection */
+ select_mode= SELECT_ADD;
+
+ /* deselect all other channels and keyframes */
+ ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ deselect_graph_keys(ac, 0, SELECT_SUBTRACT);
+ }
+
+ /* initialise keyframe editing data */
+ memset(&bed, 0, sizeof(BeztEditData));
+
+ /* set up BezTriple edit callbacks */
+ select_cb= ANIM_editkeyframes_select(select_mode);
+ ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAME);
+
+ /* loop through all of the keys and select additional keyframes
+ * based on the keys found to be selected above
+ */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ /* set frame for validation callback to refer to */
+ if (nob)
+ bed.f1= get_action_frame(nob, selx);
+ else
+ bed.f1= selx;
+
+ /* select elements with frame number matching cfra */
+ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+ }
+
+ /* free elements */
+ BLI_freelistN(&bed.list);
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+/* handle clicking */
+static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ bAnimContext ac;
+ Scene *scene;
+ ARegion *ar;
+ View2D *v2d;
+ short selectmode;
+ int mval[2];
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get useful pointers from animation context data */
+ scene= ac.scene;
+ ar= ac.ar;
+ v2d= &ar->v2d;
+
+ /* get mouse coordinates (in region coordinates) */
+ mval[0]= (event->x - ar->winrct.xmin);
+ mval[1]= (event->y - ar->winrct.ymin);
+
+ /* select mode is either replace (deselect all, then add) or add/extend */
+ if (RNA_boolean_get(op->ptr, "extend"))
+ selectmode= SELECT_INVERT;
+ else
+ selectmode= SELECT_REPLACE;
+
+ /* figure out action to take */
+ if (RNA_enum_get(op->ptr, "left_right")) {
+ /* select all keys on same side of current frame as mouse */
+ float x;
+
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, NULL);
+ if (x < CFRA)
+ RNA_int_set(op->ptr, "left_right", GRAPHKEYS_LRSEL_LEFT);
+ else
+ RNA_int_set(op->ptr, "left_right", GRAPHKEYS_LRSEL_RIGHT);
+
+ graphkeys_mselect_leftright(&ac, RNA_enum_get(op->ptr, "left_right"), selectmode);
+ }
+ else if (RNA_boolean_get(op->ptr, "column")) {
+ /* select all keyframes in the same frame as the one that was under the mouse */
+ graphkeys_mselect_column(&ac, mval, selectmode);
+ }
+ else if (RNA_boolean_get(op->ptr, "curves")) {
+ /* select all keyframes in F-Curve under mouse */
+ mouse_graph_keys(&ac, mval, selectmode, 1);
+ }
+ else {
+ /* select keyframe under mouse */
+ mouse_graph_keys(&ac, mval, selectmode, 0);
+ }
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
+
+ /* for tweak grab to work */
+ return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
+}
+
+void GRAPHEDIT_OT_keyframes_clickselect (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mouse Select Keys";
+ ot->idname= "GRAPHEDIT_OT_keyframes_clickselect";
+
+ /* api callbacks */
+ ot->invoke= graphkeys_clickselect_invoke;
+ ot->poll= ED_operator_areaactive;
+
+ /* id-props */
+ // XXX should we make this into separate operators?
+ RNA_def_enum(ot->srna, "left_right", prop_graphkeys_leftright_select_types, 0, "Left Right", ""); // CTRLKEY
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
+ RNA_def_boolean(ot->srna, "column", 0, "Column Select", "Select all keyframes that occur on the same frame as the one under the mouse"); // ALTKEY
+ RNA_def_boolean(ot->srna, "curves", 0, "Only Curves", "Select all the keyframes in the curve"); // CTRLKEY + ALTKEY
+}
+
+/* ************************************************************************** */
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
new file mode 100644
index 00000000000..782611aaad7
--- /dev/null
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -0,0 +1,592 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_anim_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_context.h"
+#include "BKE_fcurve.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+#include "ED_anim_api.h"
+#include "ED_markers.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "graph_intern.h" // own include
+
+/* ******************** manage regions ********************* */
+
+ARegion *graph_has_buttons_region(ScrArea *sa)
+{
+ ARegion *ar, *arnew;
+
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ if(ar->regiontype==RGN_TYPE_UI)
+ return ar;
+
+ /* add subdiv level; after channel */
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ if(ar->regiontype==RGN_TYPE_CHANNELS)
+ break;
+
+ /* is error! */
+ if(ar==NULL) return NULL;
+
+ arnew= MEM_callocN(sizeof(ARegion), "buttons for view3d");
+
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype= RGN_TYPE_UI;
+ arnew->alignment= RGN_ALIGN_BOTTOM|RGN_SPLIT_PREV;
+
+ arnew->flag = RGN_FLAG_HIDDEN;
+
+ return arnew;
+}
+
+
+/* ******************** default callbacks for ipo space ***************** */
+
+static SpaceLink *graph_new(const bContext *C)
+{
+ Scene *scene= CTX_data_scene(C);
+ ARegion *ar;
+ SpaceIpo *sipo;
+
+ /* Graph Editor - general stuff */
+ sipo= MEM_callocN(sizeof(SpaceIpo), "init graphedit");
+ sipo->spacetype= SPACE_IPO;
+
+ sipo->autosnap= SACTSNAP_FRAME;
+
+ /* allocate DopeSheet data for Graph Editor */
+ sipo->ads= MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for graphedit");
+
+ BLI_addtail(&sipo->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_BOTTOM;
+
+ /* channels */
+ ar= MEM_callocN(sizeof(ARegion), "main area for graphedit");
+
+ BLI_addtail(&sipo->regionbase, ar);
+ ar->regiontype= RGN_TYPE_CHANNELS;
+ ar->alignment= RGN_ALIGN_LEFT;
+
+ ar->v2d.scroll = (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM);
+
+ /* ui buttons */
+ ar= MEM_callocN(sizeof(ARegion), "main area for graphedit");
+
+ BLI_addtail(&sipo->regionbase, ar);
+ ar->regiontype= RGN_TYPE_UI;
+ ar->alignment= RGN_ALIGN_TOP|RGN_SPLIT_PREV;
+ ar->flag = RGN_FLAG_HIDDEN;
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for graphedit");
+
+ BLI_addtail(&sipo->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+
+ ar->v2d.tot.xmin= 0.0f;
+ ar->v2d.tot.ymin= (float)scene->r.sfra - 10.0f;
+ ar->v2d.tot.xmax= (float)scene->r.efra;
+ ar->v2d.tot.ymax= 10.0f;
+
+ ar->v2d.cur= ar->v2d.tot;
+
+ ar->v2d.min[0]= 0.01f;
+ ar->v2d.min[1]= 0.01f;
+
+ ar->v2d.max[0]= MAXFRAMEF;
+ ar->v2d.max[1]= 50000.0f;
+
+ ar->v2d.scroll= (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.scroll |= (V2D_SCROLL_LEFT|V2D_SCROLL_SCALE_VERTICAL);
+
+ ar->v2d.keeptot= 0;
+
+ return (SpaceLink *)sipo;
+}
+
+/* not spacelink itself */
+static void graph_free(SpaceLink *sl)
+{
+ SpaceIpo *si= (SpaceIpo *)sl;
+
+ if (si->ads) {
+ BLI_freelistN(&si->ads->chanbase);
+ MEM_freeN(si->ads);
+ }
+
+ if (si->ghostCurves.first)
+ free_fcurves(&si->ghostCurves);
+}
+
+
+/* spacetype; init callback */
+static void graph_init(struct wmWindowManager *wm, ScrArea *sa)
+{
+ SpaceIpo *sipo= (SpaceIpo *)sa->spacedata.first;
+
+ /* init dopesheet data if non-existant (i.e. for old files) */
+ if (sipo->ads == NULL)
+ sipo->ads= MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
+
+ ED_area_tag_refresh(sa);
+}
+
+static SpaceLink *graph_duplicate(SpaceLink *sl)
+{
+ SpaceIpo *sipon= MEM_dupallocN(sl);
+
+ /* clear or remove stuff from old */
+ //sipon->ipokey.first= sipon->ipokey.last= NULL;
+ sipon->ads= MEM_dupallocN(sipon->ads);
+
+ return (SpaceLink *)sipon;
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void graph_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "GraphEdit Keys", SPACE_IPO, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap= WM_keymap_listbase(wm, "GraphEdit Generic", SPACE_IPO, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+}
+
+static void graph_main_area_draw(const bContext *C, ARegion *ar)
+{
+ /* draw entirely, view changes should be handled here */
+ SpaceIpo *sipo= (SpaceIpo*)CTX_wm_space_data(C);
+ bAnimContext ac;
+ View2D *v2d= &ar->v2d;
+ View2DGrid *grid;
+ View2DScrollers *scrollers;
+ float col[3];
+ short unitx=0, unity=V2D_UNIT_VALUES, flag=0;
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ UI_view2d_view_ortho(C, v2d);
+
+ /* grid */
+ unitx= (sipo->flag & SIPO_DRAWTIME)? V2D_UNIT_SECONDS : V2D_UNIT_FRAMESCALE;
+ grid= UI_view2d_grid_calc(C, v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP, ar->winx, ar->winy);
+ UI_view2d_grid_draw(C, v2d, grid, V2D_GRIDLINES_ALL);
+
+ /* draw data */
+ if (ANIM_animdata_get_context(C, &ac)) {
+ /* draw ghost curves */
+ graph_draw_ghost_curves(&ac, sipo, ar, grid);
+
+ /* draw curves twice - unselected, then selected, so that the are fewer occlusion problems */
+ graph_draw_curves(&ac, sipo, ar, grid, 0);
+ graph_draw_curves(&ac, sipo, ar, grid, 1);
+ }
+
+ /* only free grid after drawing data, as we need to use it to determine sampling rate */
+ UI_view2d_grid_free(grid);
+
+ /* current frame */
+ if (sipo->flag & SIPO_DRAWTIME) flag |= DRAWCFRA_UNIT_SECONDS;
+ if ((sipo->flag & SIPO_NODRAWCFRANUM)==0) flag |= DRAWCFRA_SHOW_NUMBOX;
+ ANIM_draw_cfra(C, v2d, flag);
+
+ /* markers */
+ UI_view2d_view_orthoSpecial(C, v2d, 1);
+ draw_markers_time(C, 0);
+
+ /* preview range */
+ UI_view2d_view_ortho(C, v2d);
+ ANIM_draw_previewrange(C, v2d);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ // FIXME: args for scrollers depend on the type of data being shown...
+ scrollers= UI_view2d_scrollers_calc(C, v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+}
+
+static void graph_channel_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "Animation_Channels", 0, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap= WM_keymap_listbase(wm, "GraphEdit Generic", SPACE_IPO, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+}
+
+static void graph_channel_area_draw(const bContext *C, ARegion *ar)
+{
+ SpaceIpo *sipo= (SpaceIpo *)CTX_wm_space_data(C);
+ bAnimContext ac;
+ View2D *v2d= &ar->v2d;
+ View2DScrollers *scrollers;
+ float col[3];
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_SHADE2, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ UI_view2d_view_ortho(C, v2d);
+
+ /* draw channels */
+ if (ANIM_animdata_get_context(C, &ac)) {
+ graph_draw_channel_names(&ac, sipo, ar);
+ }
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void graph_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+}
+
+static void graph_header_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ /* clear */
+ if(ED_screen_area_active(C))
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ else
+ UI_GetThemeColor3fv(TH_HEADERDESEL, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ graph_header_buttons(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void graph_buttons_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST_UI, ar->winx, ar->winy);
+
+ keymap= WM_keymap_listbase(wm, "View2D Buttons List", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap= WM_keymap_listbase(wm, "GraphEdit Generic", SPACE_IPO, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+static void graph_buttons_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ /* clear */
+ UI_GetThemeColor3fv(TH_HEADER, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ graph_region_buttons(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+
+static void graph_region_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ switch(wmn->data) {
+ case ND_OB_ACTIVE:
+ case ND_FRAME:
+ case ND_MARKERS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch(wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_KEYS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ default:
+ if(wmn->data==ND_KEYS)
+ ED_region_tag_redraw(ar);
+
+ }
+}
+
+/* editor level listener */
+static void graph_listener(ScrArea *sa, wmNotifier *wmn)
+{
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SCENE:
+ /*switch (wmn->data) {
+ case ND_OB_ACTIVE:
+ case ND_OB_SELECT:
+ ED_area_tag_refresh(sa);
+ break;
+ }*/
+ ED_area_tag_refresh(sa);
+ break;
+ case NC_OBJECT:
+ /*switch (wmn->data) {
+ case ND_BONE_SELECT:
+ case ND_BONE_ACTIVE:
+ ED_area_tag_refresh(sa);
+ break;
+ }*/
+ ED_area_tag_refresh(sa);
+ break;
+ default:
+ if(wmn->data==ND_KEYS)
+ ED_area_tag_refresh(sa);
+ }
+}
+
+
+
+static void graph_refresh(const bContext *C, ScrArea *sa)
+{
+ SpaceIpo *sipo = (SpaceIpo *)sa->spacedata.first;
+ bAnimContext ac;
+
+ /* updates to data needed depends on Graph Editor mode... */
+ switch (sipo->mode) {
+ case SIPO_MODE_ANIMATION: /* all animation */
+ {
+
+ }
+ break;
+
+ case SIPO_MODE_DRIVERS: /* drivers only */
+ {
+
+ }
+ break;
+ }
+
+ /* region updates? */
+ // XXX resizing y-extents of tot should go here?
+
+ /* init/adjust F-Curve colors */
+ if (ANIM_animdata_get_context(C, &ac)) {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ int items, i;
+
+ /* build list of F-Curves which will be visible as channels in channel-region
+ * - we don't include ANIMFILTER_CURVEVISIBLE filter, as that will result in a
+ * mismatch between channel-colors and the drawn curves
+ */
+ filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CURVESONLY);
+ items= ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* loop over F-Curves, assigning colors */
+ for (ale=anim_data.first, i=0; ale; ale= ale->next, i++) {
+ FCurve *fcu= (FCurve *)ale->data;
+
+ /* set color of curve here */
+ switch (fcu->color_mode) {
+ case FCURVE_COLOR_CUSTOM:
+ /* User has defined a custom color for this curve already (we assume it's not going to cause clashes with text colors),
+ * which should be left alone... Nothing needs to be done here.
+ */
+ break;
+
+ case FCURVE_COLOR_AUTO_RGB:
+ {
+ /* F-Curve's array index is automatically mapped to RGB values. This works best of 3-value vectors.
+ * TODO: find a way to module the hue so that not all curves have same color...
+ */
+
+ /* standard table of colors to use */
+ const float _colorsets[4][3]=
+ {
+ {1.0f, 0.0f, 0.0f}, /* red */
+ {0.0f, 1.0f, 0.0f}, /* green */
+ {0.0f, 0.0f, 1.0f}, /* blue */
+ {0.3f, 0.8f, 1.0f}, /* 'unknown' color - bluish so as to not conflict with handles */
+ };
+
+ /* simply copy the relevant color over to the F-Curve */
+ if ((fcu->array_index >= 0) && (fcu->array_index < 3)) {
+ /* if the index is within safe bounds, use index to access table */
+ VECCOPY(fcu->color, _colorsets[fcu->array_index]);
+ }
+ else {
+ /* use the 'unknown' color... */
+ VECCOPY(fcu->color, _colorsets[3]);
+ }
+ }
+ break;
+
+ case FCURVE_COLOR_AUTO_RAINBOW:
+ default:
+ {
+ /* determine color 'automatically' using 'magic function' which uses the given args
+ * of current item index + total items to determine some RGB color
+ */
+ ipo_rainbow(i, items, fcu->color);
+ }
+ break;
+ }
+ }
+
+ /* free temp list */
+ BLI_freelistN(&anim_data);
+ }
+}
+
+/* only called once, from space/spacetypes.c */
+void ED_spacetype_ipo(void)
+{
+ SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype ipo");
+ ARegionType *art;
+
+ st->spaceid= SPACE_IPO;
+
+ st->new= graph_new;
+ st->free= graph_free;
+ st->init= graph_init;
+ st->duplicate= graph_duplicate;
+ st->operatortypes= graphedit_operatortypes;
+ st->keymap= graphedit_keymap;
+ st->listener= graph_listener;
+ st->refresh= graph_refresh;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init= graph_main_area_init;
+ art->draw= graph_main_area_draw;
+ art->listener= graph_region_listener;
+ art->keymapflag= ED_KEYMAP_VIEW2D/*|ED_KEYMAP_MARKERS*/|ED_KEYMAP_ANIMATION|ED_KEYMAP_FRAMES;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
+ art->listener= graph_region_listener;
+ art->init= graph_header_area_init;
+ art->draw= graph_header_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: channels */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
+ art->regionid = RGN_TYPE_CHANNELS;
+ art->minsizex= 200+V2D_SCROLL_WIDTH; /* 200 is the 'standard', but due to scrollers, we want a bit more to fit the lock icons in */
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
+ art->listener= graph_region_listener;
+ art->init= graph_channel_area_init;
+ art->draw= graph_channel_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: UI buttons */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
+ art->regionid = RGN_TYPE_UI;
+ art->minsizey= 200;
+ art->keymapflag= ED_KEYMAP_UI;
+ art->listener= graph_region_listener;
+ art->init= graph_buttons_area_init;
+ art->draw= graph_buttons_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
+}
+
diff --git a/source/blender/editors/space_image/Makefile b/source/blender/editors/space_image/Makefile
new file mode 100644
index 00000000000..44d841a0606
--- /dev/null
+++ b/source/blender/editors/space_image/Makefile
@@ -0,0 +1,55 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_image
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I../../render/extern/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
+
diff --git a/source/blender/editors/space_image/SConscript b/source/blender/editors/space_image/SConscript
new file mode 100644
index 00000000000..3ae638d344d
--- /dev/null
+++ b/source/blender/editors/space_image/SConscript
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' ../../render/extern/include ../../makesrna'
+
+env.BlenderLib ( 'bf_editors_space_image', sources, Split(incs), [], libtype=['core'], priority=[40] )
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
new file mode 100644
index 00000000000..b9407d26352
--- /dev/null
+++ b/source/blender/editors/space_image/image_draw.c
@@ -0,0 +1,693 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2002-2009
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_image_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "PIL_time.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "BKE_colortools.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "ED_image.h"
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "WM_api.h"
+
+#include "image_intern.h"
+
+#define HEADER_HEIGHT 18
+
+#if 0
+static int image_preview_active(SpaceImage *sima, Scene *scene, float *xim, float *yim)
+{
+ /* only when compositor shows, and image handler set */
+ if(sima->image && sima->image->type==IMA_TYPE_COMPOSITE) {
+ /* XXX panels .. */
+#if 0
+ short a;
+
+ for(a=0; a<SPACE_MAXHANDLER; a+=2) {
+ if(sima->blockhandler[a] == IMAGE_HANDLER_PREVIEW) {
+ if(xim) *xim= (scene->r.size*scene->r.xsch)/100;
+ if(yim) *yim= (scene->r.size*scene->r.ysch)/100;
+ return 1;
+ }
+ }
+#endif
+ }
+ return 0;
+}
+#endif
+
+/* are there curves? curves visible? and curves do something? */
+static int image_curves_active(SpaceImage *sima)
+{
+ if(sima->cumap) {
+ if(curvemapping_RGBA_does_something(sima->cumap)) {
+ /* XXX panels .. */
+#if 0
+ short a;
+ for(a=0; a<SPACE_MAXHANDLER; a+=2) {
+ if(sima->blockhandler[a] == IMAGE_HANDLER_CURVES)
+ return 1;
+ }
+#endif
+ }
+ }
+
+ return 0;
+}
+
+static void image_verify_buffer_float(SpaceImage *sima, ImBuf *ibuf)
+{
+ /* detect if we need to redo the curve map.
+ ibuf->rect is zero for compositor and render results after change
+ convert to 32 bits always... drawing float rects isnt supported well (atis)
+
+ NOTE: if float buffer changes, we have to manually remove the rect
+ */
+
+ if(ibuf->rect_float) {
+ if(ibuf->rect==NULL) {
+ if(image_curves_active(sima))
+ curvemapping_do_ibuf(sima->cumap, ibuf);
+ else
+ IMB_rect_from_float(ibuf);
+ }
+ }
+}
+
+static void draw_render_info(SpaceImage *sima, ARegion *ar)
+{
+ rcti rect;
+ float colf[3];
+ int showspare= 0; // XXX BIF_show_render_spare();
+ char *str= "render text"; // XXX BIF_render_text();
+
+ if(str==NULL)
+ return;
+
+ rect= ar->winrct;
+ rect.xmin= 0;
+ rect.ymin= ar->winrct.ymax - ar->winrct.ymin - HEADER_HEIGHT;
+ rect.xmax= ar->winrct.xmax - ar->winrct.xmin;
+ rect.ymax= ar->winrct.ymax - ar->winrct.ymin;
+
+ /* clear header rect */
+ UI_GetThemeColor3fv(TH_BACK, colf);
+ glColor3f(colf[0]+0.1f, colf[1]+0.1f, colf[2]+0.1f);
+ glRecti(rect.xmin, rect.ymin, rect.xmax, rect.ymax+1);
+
+ UI_ThemeColor(TH_TEXT_HI);
+
+ if(showspare) {
+ UI_DrawString(12, rect.ymin + 5, "(Previous)");
+ UI_DrawString(72, rect.ymin + 5, str);
+ }
+ else
+ UI_DrawString(12, rect.ymin + 5, str);
+}
+
+void draw_image_info(ARegion *ar, int channels, int x, int y, char *cp, float *fp, int *zp, float *zpf)
+{
+ char str[256];
+ int ofs;
+
+ ED_region_pixelspace(ar);
+
+ ofs= sprintf(str, "X: %d Y: %d ", x, y);
+ if(cp)
+ ofs+= sprintf(str+ofs, "| R: %d G: %d B: %d A: %d ", cp[0], cp[1], cp[2], cp[3]);
+
+ if(fp) {
+ if(channels==4)
+ ofs+= sprintf(str+ofs, "| R: %.3f G: %.3f B: %.3f A: %.3f ", fp[0], fp[1], fp[2], fp[3]);
+ else if(channels==1)
+ ofs+= sprintf(str+ofs, "| Val: %.3f ", fp[0]);
+ else if(channels==3)
+ ofs+= sprintf(str+ofs, "| R: %.3f G: %.3f B: %.3f ", fp[0], fp[1], fp[2]);
+ }
+
+ if(zp)
+ ofs+= sprintf(str+ofs, "| Z: %.4f ", 0.5+0.5*(((float)*zp)/(float)0x7fffffff));
+ if(zpf)
+ ofs+= sprintf(str+ofs, "| Z: %.3f ", *zpf);
+
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ glColor4f(.0,.0,.0,.25);
+ glRectf(0.0, 0.0, ar->winrct.xmax - ar->winrct.xmin + 1, 30.0);
+ glDisable(GL_BLEND);
+
+ glColor3ub(255, 255, 255);
+
+ UI_DrawString(10, 10, str);
+}
+
+/* image drawing */
+
+static void draw_image_grid(ARegion *ar, float zoomx, float zoomy)
+{
+ float gridsize, gridstep= 1.0f/32.0f;
+ float fac, blendfac;
+ int x1, y1, x2, y2;
+
+ /* the image is located inside (0,0),(1, 1) as set by view2d */
+ UI_ThemeColorShade(TH_BACK, 20);
+
+ UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x1, &y1);
+ UI_view2d_to_region_no_clip(&ar->v2d, 1.0f, 1.0f, &x2, &y2);
+ glRectf(x1, y1, x2, y2);
+
+ /* gridsize adapted to zoom level */
+ gridsize= 0.5f*(zoomx+zoomy);
+ if(gridsize<=0.0f) return;
+
+ if(gridsize<1.0f) {
+ while(gridsize<1.0f) {
+ gridsize*= 4.0;
+ gridstep*= 4.0;
+ }
+ }
+ else {
+ while(gridsize>=4.0f) {
+ gridsize/= 4.0;
+ gridstep/= 4.0;
+ }
+ }
+
+ /* the fine resolution level */
+ blendfac= 0.25*gridsize - floor(0.25*gridsize);
+ CLAMP(blendfac, 0.0, 1.0);
+ UI_ThemeColorShade(TH_BACK, (int)(20.0*(1.0-blendfac)));
+
+ fac= 0.0f;
+ glBegin(GL_LINES);
+ while(fac<1.0f) {
+ glVertex2f(x1, y1*(1.0f-fac) + y2*fac);
+ glVertex2f(x2, y1*(1.0f-fac) + y2*fac);
+ glVertex2f(x1*(1.0f-fac) + x2*fac, y1);
+ glVertex2f(x1*(1.0f-fac) + x2*fac, y2);
+ fac+= gridstep;
+ }
+
+ /* the large resolution level */
+ UI_ThemeColor(TH_BACK);
+
+ fac= 0.0f;
+ while(fac<1.0f) {
+ glVertex2f(x1, y1*(1.0f-fac) + y2*fac);
+ glVertex2f(x2, y1*(1.0f-fac) + y2*fac);
+ glVertex2f(x1*(1.0f-fac) + x2*fac, y1);
+ glVertex2f(x1*(1.0f-fac) + x2*fac, y2);
+ fac+= 4.0f*gridstep;
+ }
+ glEnd();
+}
+
+static void sima_draw_alpha_backdrop(float x1, float y1, float xsize, float ysize, float zoomx, float zoomy)
+{
+ GLubyte checker_stipple[32*32/8] =
+ {
+ 255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0, \
+ 255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0, \
+ 255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0, \
+ 255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0, \
+ 0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255, \
+ 0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255, \
+ 0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255, \
+ 0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255, \
+ };
+
+ glColor3ub(100, 100, 100);
+ glRectf(x1, y1, x1 + zoomx*xsize, y1 + zoomy*ysize);
+ glColor3ub(160, 160, 160);
+
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(checker_stipple);
+ glRectf(x1, y1, x1 + zoomx*xsize, y1 + zoomy*ysize);
+ glDisable(GL_POLYGON_STIPPLE);
+}
+
+static void sima_draw_alpha_pixels(float x1, float y1, int rectx, int recty, unsigned int *recti)
+{
+
+ /* swap bytes, so alpha is most significant one, then just draw it as luminance int */
+ if(ENDIAN_ORDER == B_ENDIAN)
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
+
+ glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_UNSIGNED_INT, recti);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
+}
+
+static void sima_draw_alpha_pixelsf(float x1, float y1, int rectx, int recty, float *rectf)
+{
+ float *trectf= MEM_mallocN(rectx*recty*4, "temp");
+ int a, b;
+
+ for(a= rectx*recty -1, b= 4*a+3; a>=0; a--, b-=4)
+ trectf[a]= rectf[b];
+
+ glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_FLOAT, trectf);
+ MEM_freeN(trectf);
+ /* ogl trick below is slower... (on ATI 9600) */
+// glColorMask(1, 0, 0, 0);
+// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf+3);
+// glColorMask(0, 1, 0, 0);
+// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf+2);
+// glColorMask(0, 0, 1, 0);
+// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf+1);
+// glColorMask(1, 1, 1, 1);
+}
+
+static void sima_draw_zbuf_pixels(float x1, float y1, int rectx, int recty, int *recti)
+{
+ /* zbuffer values are signed, so we need to shift color range */
+ glPixelTransferf(GL_RED_SCALE, 0.5f);
+ glPixelTransferf(GL_GREEN_SCALE, 0.5f);
+ glPixelTransferf(GL_BLUE_SCALE, 0.5f);
+ glPixelTransferf(GL_RED_BIAS, 0.5f);
+ glPixelTransferf(GL_GREEN_BIAS, 0.5f);
+ glPixelTransferf(GL_BLUE_BIAS, 0.5f);
+
+ glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_INT, recti);
+
+ glPixelTransferf(GL_RED_SCALE, 1.0f);
+ glPixelTransferf(GL_GREEN_SCALE, 1.0f);
+ glPixelTransferf(GL_BLUE_SCALE, 1.0f);
+ glPixelTransferf(GL_RED_BIAS, 0.0f);
+ glPixelTransferf(GL_GREEN_BIAS, 0.0f);
+ glPixelTransferf(GL_BLUE_BIAS, 0.0f);
+}
+
+static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rectx, int recty, float *rect_float)
+{
+ float bias, scale, *rectf, clipend;
+ int a;
+
+ if(scene->camera && scene->camera->type==OB_CAMERA) {
+ bias= ((Camera *)scene->camera->data)->clipsta;
+ clipend= ((Camera *)scene->camera->data)->clipend;
+ scale= 1.0f/(clipend-bias);
+ }
+ else {
+ bias= 0.1f;
+ scale= 0.01f;
+ clipend= 100.0f;
+ }
+
+ rectf= MEM_mallocN(rectx*recty*4, "temp");
+ for(a= rectx*recty -1; a>=0; a--) {
+ if(rect_float[a]>clipend)
+ rectf[a]= 0.0f;
+ else if(rect_float[a]<bias)
+ rectf[a]= 1.0f;
+ else {
+ rectf[a]= 1.0f - (rect_float[a]-bias)*scale;
+ rectf[a]*= rectf[a];
+ }
+ }
+ glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_FLOAT, rectf);
+
+ MEM_freeN(rectf);
+}
+
+static void draw_image_buffer(SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy)
+{
+ int x, y;
+
+ /* set zoom */
+ glPixelZoom(zoomx, zoomy);
+
+ /* find window pixel coordinates of origin */
+ UI_view2d_to_region_no_clip(&ar->v2d, fx, fy, &x, &y);
+
+ /* this part is generic image display */
+ if(sima->flag & SI_SHOW_ALPHA) {
+ if(ibuf->rect)
+ sima_draw_alpha_pixels(x, y, ibuf->x, ibuf->y, ibuf->rect);
+ else if(ibuf->rect_float && ibuf->channels==4)
+ sima_draw_alpha_pixelsf(x, y, ibuf->x, ibuf->y, ibuf->rect_float);
+ }
+ else if(sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels==1))) {
+ if(ibuf->zbuf)
+ sima_draw_zbuf_pixels(x, y, ibuf->x, ibuf->y, ibuf->zbuf);
+ else if(ibuf->zbuf_float)
+ sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->zbuf_float);
+ else if(ibuf->channels==1)
+ sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float);
+ }
+ else {
+ if(sima->flag & SI_USE_ALPHA) {
+ sima_draw_alpha_backdrop(x, y, ibuf->x, ibuf->y, zoomx, zoomy);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ /* we don't draw floats buffers directly but
+ * convert them, and optionally apply curves */
+ image_verify_buffer_float(sima, ibuf);
+
+ if(ibuf->rect)
+ glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ /*else
+ glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_FLOAT, ibuf->rect_float);*/
+
+ if(sima->flag & SI_USE_ALPHA)
+ glDisable(GL_BLEND);
+ }
+
+ /* reset zoom */
+ glPixelZoom(1.0f, 1.0f);
+}
+
+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;
+
+ /* the right 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;
+}
+
+static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Image *ima, ImBuf *ibuf, float zoomx, float zoomy)
+{
+ unsigned int *rect;
+ int dx, dy, sx, sy, x, y;
+
+ /* verify valid values, just leave this a while */
+ if(ima->xrep<1) return;
+ if(ima->yrep<1) return;
+
+ glPixelZoom(zoomx, zoomy);
+
+ if(sima->curtile >= ima->xrep*ima->yrep)
+ sima->curtile = ima->xrep*ima->yrep - 1;
+
+ /* create char buffer from float if needed */
+ image_verify_buffer_float(sima, ibuf);
+
+ /* retrieve part of image buffer */
+ dx= ibuf->x/ima->xrep;
+ dy= ibuf->y/ima->yrep;
+ sx= (sima->curtile % ima->xrep)*dx;
+ sy= (sima->curtile / ima->xrep)*dy;
+ rect= get_part_from_ibuf(ibuf, sx, sy, sx+dx, sy+dy);
+
+ /* draw repeated */
+ for(sy=0; sy+dy<=ibuf->y; sy+= dy) {
+ for(sx=0; sx+dx<=ibuf->x; sx+= dx) {
+ UI_view2d_view_to_region(&ar->v2d, (float)sx/(float)ibuf->x, (float)sy/(float)ibuf->y, &x, &y);
+
+ glaDrawPixelsSafe(x, y, dx, dy, dx, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+ }
+ }
+
+ glPixelZoom(1.0f, 1.0f);
+
+ MEM_freeN(rect);
+}
+
+static void draw_image_buffer_repeated(SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float zoomx, float zoomy)
+{
+ float x, y;
+ double time_current;
+
+ time_current = PIL_check_seconds_timer();
+
+ for(x=ar->v2d.cur.xmin; x<ar->v2d.cur.xmax; x += zoomx) {
+ for(y=ar->v2d.cur.ymin; y<ar->v2d.cur.ymax; y += zoomy) {
+ draw_image_buffer(sima, ar, scene, ibuf, x, y, zoomx, zoomy);
+
+ /* only draw until running out of time */
+ if((PIL_check_seconds_timer() - time_current) > 0.25)
+ return;
+ }
+ }
+}
+
+/* draw uv edit */
+
+/* draw grease pencil */
+
+static void draw_image_grease_pencil(SpaceImage *sima, ImBuf *ibuf)
+{
+ /* XXX bring back */
+ /* draw grease-pencil ('image' strokes) */
+ if (sima->flag & SI_DISPGP)
+ ; // XXX draw_gpencil_2dimage(sa, ibuf);
+
+#if 0
+ mywinset(sa->win); /* restore scissor after gla call... */
+ wmOrtho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
+#endif
+
+ /* draw grease-pencil (screen strokes) */
+ if (sima->flag & SI_DISPGP)
+ ; // XXX draw_gpencil_2dview(sa, NULL);
+}
+
+/* XXX becomes WM paint cursor */
+#if 0
+static void draw_image_view_tool(Scene *scene)
+{
+ ToolSettings *settings= scene->toolsettings;
+ Brush *brush= settings->imapaint.brush;
+ short mval[2];
+ float radius;
+ int draw= 0;
+
+ if(brush) {
+ if(settings->imapaint.flag & IMAGEPAINT_DRAWING) {
+ if(settings->imapaint.flag & IMAGEPAINT_DRAW_TOOL_DRAWING)
+ draw= 1;
+ }
+ else if(settings->imapaint.flag & IMAGEPAINT_DRAW_TOOL)
+ draw= 1;
+
+ if(draw) {
+ getmouseco_areawin(mval);
+
+ radius= brush->size*G.sima->zoom/2;
+ fdrawXORcirc(mval[0], mval[1], radius);
+
+ if (brush->innerradius != 1.0) {
+ radius *= brush->innerradius;
+ fdrawXORcirc(mval[0], mval[1], radius);
+ }
+ }
+ }
+}
+#endif
+
+static unsigned char *get_alpha_clone_image(Scene *scene, int *width, int *height)
+{
+ Brush *brush = scene->toolsettings->imapaint.brush;
+ ImBuf *ibuf;
+ unsigned int size, alpha;
+ unsigned char *rect, *cp;
+
+ if(!brush || !brush->clone.image)
+ return NULL;
+
+ ibuf= BKE_image_get_ibuf(brush->clone.image, NULL);
+
+ if(!ibuf || !ibuf->rect)
+ return NULL;
+
+ rect= MEM_dupallocN(ibuf->rect);
+ if(!rect)
+ return NULL;
+
+ *width= ibuf->x;
+ *height= ibuf->y;
+
+ size= (*width)*(*height);
+ alpha= (unsigned char)255*brush->clone.alpha;
+ cp= rect;
+
+ while(size-- > 0) {
+ cp[3]= alpha;
+ cp += 4;
+ }
+
+ return rect;
+}
+
+static void draw_image_paint_helpers(SpaceImage *sima, ARegion *ar, Scene *scene, float zoomx, float zoomy)
+{
+ Brush *brush;
+ int x, y, w, h;
+ unsigned char *clonerect;
+
+ brush= scene->toolsettings->imapaint.brush;
+
+ if(brush && (scene->toolsettings->imapaint.tool == PAINT_TOOL_CLONE)) {
+ /* this is not very efficient, but glDrawPixels doesn't allow
+ drawing with alpha */
+ clonerect= get_alpha_clone_image(scene, &w, &h);
+
+ if(clonerect) {
+ UI_view2d_to_region_no_clip(&ar->v2d, brush->clone.offset[0], brush->clone.offset[1], &x, &y);
+
+ glPixelZoom(zoomx, zoomy);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glaDrawPixelsSafe(x, y, w, h, w, GL_RGBA, GL_UNSIGNED_BYTE, clonerect);
+ glDisable(GL_BLEND);
+
+ glPixelZoom(1.0, 1.0);
+
+ MEM_freeN(clonerect);
+ }
+ }
+}
+
+/* draw main image area */
+
+void draw_image_main(SpaceImage *sima, ARegion *ar, Scene *scene)
+{
+ Image *ima;
+ ImBuf *ibuf;
+ float zoomx, zoomy;
+ int show_viewer, show_render;
+
+ /* XXX can we do this in refresh? */
+#if 0
+ what_image(sima);
+
+ if(sima->image) {
+ ED_image_aspect(sima->image, &xuser_asp, &yuser_asp);
+
+ /* UGLY hack? until now iusers worked fine... but for flipbook viewer we need this */
+ if(sima->image->type==IMA_TYPE_COMPOSITE) {
+ ImageUser *iuser= ntree_get_active_iuser(scene->nodetree);
+ if(iuser) {
+ BKE_image_user_calc_imanr(iuser, scene->r.cfra, 0);
+ sima->iuser= *iuser;
+ }
+ }
+ /* and we check for spare */
+ ibuf= ED_space_image_buffer(sima);
+ }
+#endif
+
+ /* put scene context variable in iuser */
+ sima->iuser.scene= scene;
+ /* retrieve the image and information about it */
+ ima= ED_space_image(sima);
+ ibuf= ED_space_image_buffer(sima);
+ ED_space_image_zoom(sima, ar, &zoomx, &zoomy);
+
+ show_viewer= (ima && ima->source == IMA_SRC_VIEWER);
+ show_render= (show_viewer && ima->type == IMA_TYPE_R_RESULT);
+
+ /* draw the image or grid */
+ if(ibuf==NULL)
+ draw_image_grid(ar, zoomx, zoomy);
+ else if(sima->flag & SI_DRAW_TILE)
+ draw_image_buffer_repeated(sima, ar, scene, ibuf, zoomx, zoomy);
+ else if(ima && (ima->tpageflag & IMA_TILES))
+ draw_image_buffer_tiled(sima, ar, ima, ibuf, zoomx, zoomy);
+ else
+ draw_image_buffer(sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy);
+
+ /* grease pencil */
+ draw_image_grease_pencil(sima, ibuf);
+
+ /* paint helpers */
+ draw_image_paint_helpers(sima, ar, scene, zoomx, zoomy);
+
+ /* render info */
+ if(ibuf && show_render)
+ draw_render_info(sima, ar);
+
+ /* XXX integrate this code */
+#if 0
+ if(ibuf) {
+ float xoffs=0.0f, yoffs= 0.0f;
+
+ if(image_preview_active(sa, &xim, &yim)) {
+ xoffs= scene->r.disprect.xmin;
+ yoffs= scene->r.disprect.ymin;
+ glColor3ub(0,0,0);
+ calc_image_view(sima, 'f');
+ myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
+ glRectf(0.0f, 0.0f, 1.0f, 1.0f);
+ glLoadIdentity();
+ }
+ }
+#endif
+
+#if 0
+ /* it is important to end a view in a transform compatible with buttons */
+ bwin_scalematrix(sa->win, sima->blockscale, sima->blockscale, sima->blockscale);
+ if(!(G.rendering && show_render))
+ image_blockhandlers(sa);
+#endif
+}
+
diff --git a/source/blender/editors/space_image/image_header.c b/source/blender/editors/space_image/image_header.c
new file mode 100644
index 00000000000..288fc76d8e4
--- /dev/null
+++ b/source/blender/editors/space_image/image_header.c
@@ -0,0 +1,969 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_customdata_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_image.h"
+#include "BKE_mesh.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "ED_image.h"
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+#include "BIF_transform.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "RNA_access.h"
+
+#include "RE_pipeline.h"
+
+#include "image_intern.h"
+
+/* ************************ header area region *********************** */
+
+#define B_NOP -1
+#define B_REDR 1
+#define B_SIMAGEPAINTTOOL 4
+#define B_SIMA_USE_ALPHA 5
+#define B_SIMA_SHOW_ALPHA 6
+#define B_SIMA_SHOW_ZBUF 7
+#define B_SIMA_RECORD 8
+#define B_SIMA_PLAY 9
+
+static void image_view_viewnavmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ int a;
+
+ uiMenuItemO(head, 0, "IMAGE_OT_view_zoom_in");
+ uiMenuItemO(head, 0, "IMAGE_OT_view_zoom_out");
+
+ uiMenuSeparator(head);
+
+ for(a=0; a<7; a++) {
+ const int ratios[7][2] = {{1, 8}, {1, 4}, {1, 2}, {1, 1}, {2, 1}, {4, 1}, {8, 1}};
+ char namestr[128];
+
+ sprintf(namestr, "Zoom %d:%d", ratios[a][0], ratios[a][1]);
+ uiMenuItemFloatO(head, namestr, 0, "IMAGE_OT_view_zoom_ratio", "ratio", (float)ratios[a][0]/(float)ratios[a][1]);
+ }
+}
+
+#if 0
+static void do_viewmenu(bContext *C, void *arg, int event)
+{
+ add_blockhandler(curarea, IMAGE_HANDLER_VIEW_PROPERTIES, UI_PNL_UNSTOW);
+ add_blockhandler(curarea, IMAGE_HANDLER_PROPERTIES, UI_PNL_UNSTOW);
+ add_blockhandler(curarea, IMAGE_HANDLER_PAINT, UI_PNL_UNSTOW);
+ add_blockhandler(curarea, IMAGE_HANDLER_CURVES, UI_PNL_UNSTOW);
+
+ toggle_blockhandler(curarea, IMAGE_HANDLER_PREVIEW, 0);
+ scrarea_queue_winredraw(curarea);
+
+ add_blockhandler(curarea, IMAGE_HANDLER_GAME_PROPERTIES, UI_PNL_UNSTOW);
+ add_blockhandler(curarea, IMAGE_HANDLER_GREASEPENCIL, UI_PNL_UNSTOW);
+
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWVIEW3D, 0);
+}
+#endif
+
+static void image_viewmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ PointerRNA spaceptr, uvptr;
+ int show_paint, show_render, show_uvedit;
+
+ /* retrieve state */
+ RNA_pointer_create(&sc->id, &RNA_SpaceImageEditor, sima, &spaceptr);
+ RNA_pointer_create(&sc->id, &RNA_SpaceUVEditor, sima, &uvptr);
+
+ show_render= ED_space_image_show_render(sima);
+ show_paint= ED_space_image_show_paint(sima);
+ show_uvedit= ED_space_image_show_uvedit(sima, CTX_data_edit_object(C));
+
+ /* create menu */
+ uiMenuItemO(head, ICON_MENU_PANEL, "IMAGE_OT_toggle_view_properties_panel"); // View Properties...
+ uiMenuItemO(head, ICON_MENU_PANEL, "IMAGE_OT_toggle_image_properties_panel"); // Image Properties...|N
+ uiMenuItemO(head, ICON_MENU_PANEL, "IMAGE_OT_toggle_realtime_properties_panel"); // Real-time properties...
+ if(show_paint) uiMenuItemO(head, ICON_MENU_PANEL, "IMAGE_OT_toggle_paint_panel"); // Paint Tool...|C
+ uiMenuItemO(head, ICON_MENU_PANEL, "IMAGE_OT_toggle_curves_panel"); // Curves Tool...
+ if(show_render) uiMenuItemO(head, ICON_MENU_PANEL, "IMAGE_OT_toggle_compositing_preview_panel"); // Compositing Preview...|Shift P
+ uiMenuItemO(head, ICON_MENU_PANEL, "IMAGE_OT_toggle_grease_pencil_panel"); // Grease Pencil...
+
+ uiMenuSeparator(head);
+
+ uiMenuItemBooleanR(head, &spaceptr, "update_automatically");
+ // XXX if(show_uvedit) uiMenuItemBooleanR(head, &uvptr, "local_view"); // "UV Local View", Numpad /
+
+ uiMenuSeparator(head);
+
+ uiMenuLevel(head, "View Navigation", image_view_viewnavmenu);
+ if(show_uvedit) uiMenuItemO(head, 0, "IMAGE_OT_view_selected");
+ uiMenuItemO(head, 0, "IMAGE_OT_view_all");
+
+ if(sa->full) uiMenuItemO(head, 0, "SCREEN_OT_screen_full_area"); // "Tile Window", Ctrl UpArrow
+ else uiMenuItemO(head, 0, "SCREEN_OT_screen_full_area"); // "Maximize Window", Ctr DownArrow
+}
+
+static void image_selectmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuItemO(head, 0, "UV_OT_select_border");
+ uiMenuItemBooleanO(head, "Border Select Pinned", 0, "UV_OT_select_border", "pinned", 1); // Border Select Pinned|Shift B
+
+ uiMenuSeparator(head);
+
+ uiMenuItemO(head, 0, "UV_OT_select_all_toggle");
+ uiMenuItemO(head, 0, "UV_OT_select_invert");
+ uiMenuItemO(head, 0, "UV_OT_unlink_selection");
+
+ uiMenuSeparator(head);
+
+ uiMenuItemO(head, 0, "UV_OT_select_pinned");
+ uiMenuItemO(head, 0, "UV_OT_select_linked");
+}
+
+#if 0
+static void do_image_imagemenu(void *arg, int event)
+{
+ /* events >=20 are registered bpython scripts */
+#ifndef DISABLE_PYTHON
+ if (event >= 20) BPY_menu_do_python(PYMENU_IMAGE, event - 20);
+#endif
+}
+#endif
+
+static void image_imagemenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ PointerRNA spaceptr, imaptr;
+ Image *ima;
+ ImBuf *ibuf;
+ int show_render;
+
+ /* retrieve state */
+ ima= ED_space_image(sima);
+ ibuf= ED_space_image_buffer(sima);
+
+ show_render= ED_space_image_show_render(sima);
+
+ RNA_pointer_create(&sc->id, &RNA_SpaceImageEditor, sima, &spaceptr);
+
+ /* create menu */
+ uiMenuItemO(head, 0, "IMAGE_OT_new"); // New...
+ uiMenuItemO(head, 0, "IMAGE_OT_open"); // Open...
+
+ if(ima) {
+ if(!show_render) {
+ uiMenuItemO(head, 0, "IMAGE_OT_replace"); // Replace...
+ uiMenuItemO(head, 0, "IMAGE_OT_reload"); // Reload...
+ }
+ uiMenuItemO(head, 0, "IMAGE_OT_save"); // Save
+ uiMenuItemO(head, 0, "IMAGE_OT_save_as"); // Save As...
+ if(ima->source == IMA_SRC_SEQUENCE)
+ uiMenuItemO(head, 0, "IMAGE_OT_save_sequence"); // Save Changed Sequence Images
+
+ if(!show_render) {
+ uiMenuSeparator(head);
+
+ if(ima->packedfile) uiMenuItemO(head, 0, "IMAGE_OT_unpack"); // Unpack Image...
+ else uiMenuItemO(head, 0, "IMAGE_OT_pack"); // Pack Image
+
+ /* only for dirty && specific image types : XXX poll? */
+ if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY))
+ if(ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_GENERATED) && ima->type != IMA_TYPE_MULTILAYER)
+ uiMenuItemBooleanO(head, "Pack As PNG", 0, "IMAGE_OT_pack", "as_png", 1); // Pack Image As PNG
+
+ uiMenuSeparator(head);
+
+ uiMenuItemBooleanR(head, &spaceptr, "image_painting");
+
+ /* move to realtime properties panel */
+ RNA_id_pointer_create(&ima->id, &imaptr);
+ uiMenuLevelEnumR(head, &imaptr, "mapping");
+ }
+ }
+
+#if 0
+#ifndef DISABLE_PYTHON
+ {
+ BPyMenu *pym;
+ int i = 0;
+
+ /* note that we acount for the N previous entries with i+20: */
+ for (pym = BPyMenuTable[PYMENU_IMAGE]; pym; pym = pym->next, i++) {
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20, menuwidth, 19,
+ NULL, 0.0, 0.0, 1, i+20,
+ pym->tooltip?pym->tooltip:pym->filename);
+ }
+ }
+#endif
+#endif
+}
+
+static void image_uvs_showhidemenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuItemO(head, 0, "UV_OT_reveal");
+ uiMenuItemO(head, 0, "UV_OT_hide");
+ uiMenuItemBooleanO(head, "Hide Unselected", 0, "UV_OT_hide", "unselected", 1);
+}
+
+static void image_uvs_transformmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuItemEnumO(head, "", 0, "TFM_OT_transform", "mode", TFM_TRANSLATION);
+ uiMenuItemEnumO(head, "", 0, "TFM_OT_transform", "mode", TFM_ROTATION);
+ uiMenuItemEnumO(head, "", 0, "TFM_OT_transform", "mode", TFM_RESIZE);
+}
+
+static void image_uvs_mirrormenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuItemEnumO(head, "", 0, "UV_OT_mirror", "axis", 'x'); // "X Axis", M, 1
+ uiMenuItemEnumO(head, "", 0, "UV_OT_mirror", "axis", 'y'); // "Y Axis", M, 2
+}
+
+static void image_uvs_weldalignmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuItemO(head, 0, "UV_OT_weld"); // W, 1
+ uiMenuItemsEnumO(head, "UV_OT_align", "axis"); // W, 2/3/4
+}
+
+#if 0
+#ifndef DISABLE_PYTHON
+static void do_image_uvs_scriptsmenu(void *arg, int event)
+{
+ BPY_menu_do_python(PYMENU_UV, event);
+
+ allqueue(REDRAWIMAGE, 0);
+}
+
+static void image_uvs_scriptsmenu (void *args_unused)
+{
+ uiBlock *block;
+ BPyMenu *pym;
+ int i= 0;
+ short yco = 20, menuwidth = 120;
+
+ block= uiNewBlock(&curarea->uiblocks, "image_uvs_scriptsmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_image_uvs_scriptsmenu, NULL);
+
+ /* note that we acount for the N previous entries with i+20: */
+ for (pym = BPyMenuTable[PYMENU_UV]; pym; pym = pym->next, i++) {
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20, menuwidth, 19,
+ NULL, 0.0, 0.0, 1, i,
+ pym->tooltip?pym->tooltip:pym->filename);
+ }
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+
+ return block;
+}
+#endif /* DISABLE_PYTHON */
+#endif
+
+static void image_uvsmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ Scene *scene= CTX_data_scene(C);
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ PointerRNA uvptr, sceneptr;
+ Image *ima;
+ ImBuf *ibuf;
+
+ /* retrieve state */
+ ima= ED_space_image(sima);
+ ibuf= ED_space_image_buffer(sima);
+
+ RNA_pointer_create(&sc->id, &RNA_SpaceUVEditor, sima, &uvptr);
+ RNA_id_pointer_create(&scene->id, &sceneptr);
+
+ /* create menu */
+ uiMenuItemBooleanR(head, &uvptr, "snap_to_pixels");
+ uiMenuItemBooleanR(head, &uvptr, "constrain_to_image_bounds");
+
+ uiMenuSeparator(head);
+
+ uiMenuItemBooleanR(head, &uvptr, "live_unwrap");
+ uiMenuItemO(head, 0, "UV_OT_unwrap");
+ uiMenuItemBooleanO(head, "Unpin", 0, "UV_OT_pin", "clear", 1);
+ uiMenuItemO(head, 0, "UV_OT_pin");
+
+ uiMenuSeparator(head);
+
+ uiMenuItemO(head, 0, "UV_OT_pack_islands");
+ uiMenuItemO(head, 0, "UV_OT_average_islands_scale");
+ uiMenuItemO(head, 0, "UV_OT_minimize_stretch");
+ uiMenuItemO(head, 0, "UV_OT_stitch");
+
+ uiMenuSeparator(head);
+
+ uiMenuLevel(head, "Transform", image_uvs_transformmenu);
+ uiMenuLevel(head, "Mirror", image_uvs_mirrormenu);
+ uiMenuLevel(head, "Weld/Align", image_uvs_weldalignmenu);
+
+ uiMenuSeparator(head);
+
+ uiMenuItemBooleanR(head, &sceneptr, "proportional_editing");
+ uiMenuLevelEnumR(head, &sceneptr, "proportional_editing_falloff");
+
+ uiMenuSeparator(head);
+
+ uiMenuLevel(head, "Show/Hide Faces", image_uvs_showhidemenu);
+
+#if 0
+#ifndef DISABLE_PYTHON
+ uiMenuSeparator(head);
+
+ uiMenuLevel(head, "Scripts", image_uvs_scriptsmenu);
+#endif
+#endif
+}
+
+static void image_menu_uvlayers(Object *obedit, char *menustr, int *active)
+{
+ Mesh *me= (Mesh*)obedit->data;
+ EditMesh *em= BKE_mesh_get_editmesh(me);
+ CustomDataLayer *layer;
+ int i, count = 0;
+
+ menustr[0]= '\0';
+
+ for(i=0; i<em->fdata.totlayer; i++) {
+ layer = &em->fdata.layers[i];
+
+ if(layer->type == CD_MTFACE) {
+ menustr += sprintf(menustr, "%s%%x%d|", layer->name, count);
+ count++;
+ }
+ }
+
+ *active= CustomData_get_active_layer(&em->fdata, CD_MTFACE);
+
+ BKE_mesh_end_editmesh(me, em);
+}
+
+static void do_image_buttons(bContext *C, void *arg, int event)
+{
+ switch(event) {
+ case B_REDR:
+ ED_area_tag_redraw(CTX_wm_area(C));
+ break;
+ }
+
+#if 0
+ ToolSettings *settings= G.scene->toolsettings;
+ ID *id, *idtest;
+ int nr;
+
+ if(curarea->win==0) return;
+
+ if(event<=100) {
+ if(event<=50) do_global_buttons2(event);
+ else do_global_buttons(event);
+ return;
+ }
+
+ switch(event) {
+ case B_SIMABROWSE:
+ if(sima->imanr== -2) {
+ if(G.qual & LR_CTRLKEY) {
+ activate_databrowse_imasel((ID *)sima->image, ID_IM, 0, B_SIMABROWSE,
+ &sima->imanr, do_image_buttons);
+ } else {
+ activate_databrowse((ID *)sima->image, ID_IM, 0, B_SIMABROWSE,
+ &sima->imanr, do_image_buttons);
+ }
+ return;
+ }
+ if(sima->imanr < 0) break;
+
+ nr= 1;
+ id= (ID *)sima->image;
+
+ idtest= BLI_findlink(&G.main->image, sima->imanr-1);
+ if(idtest==NULL) { /* no new */
+ return;
+ }
+
+ if(idtest!=id) {
+ sima->image= (Image *)idtest;
+ if(idtest->us==0) idtest->us= 1;
+ BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
+ allqueue(REDRAWIMAGE, 0);
+ }
+ /* also when image is the same: assign! 0==no tileflag: */
+ image_changed(sima, (Image *)idtest);
+ BIF_undo_push("Assign image UV");
+
+ break;
+ case B_SIMAGETILE:
+ image_set_tile(sima, 1); /* 1: only tileflag */
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+ break;
+ case B_SIMA3DVIEWDRAW:
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_SIMA_REDR_IMA_3D:
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+ break;
+
+ case B_SIMAPACKIMA:
+ pack_image_sima();
+ break;
+
+ case B_SIMA_REPACK:
+ BKE_image_memorypack(sima->image);
+ allqueue(REDRAWIMAGE, 0);
+ break;
+
+ case B_SIMA_USE_ALPHA:
+ sima->flag &= ~(SI_SHOW_ALPHA|SI_SHOW_ZBUF);
+ scrarea_queue_winredraw(curarea);
+ scrarea_queue_headredraw(curarea);
+ break;
+ case B_SIMA_SHOW_ALPHA:
+ sima->flag &= ~(SI_USE_ALPHA|SI_SHOW_ZBUF);
+ scrarea_queue_winredraw(curarea);
+ scrarea_queue_headredraw(curarea);
+ break;
+ case B_SIMA_SHOW_ZBUF:
+ sima->flag &= ~(SI_SHOW_ALPHA|SI_USE_ALPHA);
+ scrarea_queue_winredraw(curarea);
+ scrarea_queue_headredraw(curarea);
+ break;
+ case B_SIMARELOAD:
+ reload_image_sima();
+ break;
+ case B_SIMAGELOAD:
+ open_image_sima(0);
+ break;
+ case B_SIMANAME:
+ if(sima->image) {
+ Image *ima;
+ char str[FILE_MAXDIR+FILE_MAXFILE];
+
+ /* name in ima has been changed by button! */
+ BLI_strncpy(str, sima->image->name, sizeof(str));
+ ima= BKE_add_image_file(str);
+ if(ima) {
+ BKE_image_signal(ima, &sima->iuser, IMA_SIGNAL_RELOAD);
+ image_changed(sima, ima);
+ }
+ BIF_undo_push("Load image");
+ allqueue(REDRAWIMAGE, 0);
+ }
+ break;
+ case B_SIMAMULTI:
+ if(sima && sima->image) {
+ BKE_image_multilayer_index(sima->image->rr, &sima->iuser);
+ allqueue(REDRAWIMAGE, 0);
+ }
+ break;
+ case B_TRANS_IMAGE:
+ image_editvertex_buts(NULL);
+ break;
+ case B_CURSOR_IMAGE:
+ image_editcursor_buts(NULL);
+ break;
+
+ case B_TWINANIM:
+ {
+ Image *ima;
+ int nr;
+
+ ima = 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);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ break;
+ }
+ case B_SIMACLONEBROWSE:
+ if(settings->imapaint.brush) {
+ Brush *brush= settings->imapaint.brush;
+
+ if(sima->menunr== -2) {
+ if(G.qual & LR_CTRLKEY) {
+ activate_databrowse_imasel((ID *)brush->clone.image, ID_IM, 0, B_SIMACLONEBROWSE,
+ &sima->menunr, do_image_buttons);
+ } else {
+ activate_databrowse((ID *)brush->clone.image, ID_IM, 0, B_SIMACLONEBROWSE,
+ &sima->menunr, do_image_buttons);
+ }
+ break;
+ }
+ if(sima->menunr < 0) break;
+
+ if(brush_clone_image_set_nr(brush, sima->menunr))
+ allqueue(REDRAWIMAGE, 0);
+ }
+ break;
+
+ case B_SIMACLONEDELETE:
+ if (settings->imapaint.brush)
+ if (brush_clone_image_delete(settings->imapaint.brush))
+ allqueue(REDRAWIMAGE, 0);
+ break;
+
+ case B_SIMABRUSHCHANGE:
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ break;
+
+ case B_SIMACURVES:
+ curvemapping_do_ibuf(sima->cumap, imagewindow_get_ibuf(sima));
+ allqueue(REDRAWIMAGE, 0);
+ break;
+
+ case B_SIMARANGE:
+ curvemapping_set_black_white(sima->cumap, NULL, NULL);
+ curvemapping_do_ibuf(sima->cumap, imagewindow_get_ibuf(sima));
+ allqueue(REDRAWIMAGE, 0);
+ break;
+
+ case B_SIMABRUSHBROWSE:
+ if(sima->menunr==-2) {
+ activate_databrowse((ID*)settings->imapaint.brush, ID_BR, 0, B_SIMABRUSHBROWSE, &sima->menunr, do_global_buttons);
+ break;
+ }
+ else if(sima->menunr < 0) break;
+
+ if(brush_set_nr(&settings->imapaint.brush, sima->menunr)) {
+ BIF_undo_push("Browse Brush");
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWIMAGE, 0);
+ }
+ break;
+ case B_SIMABRUSHDELETE:
+ if(brush_delete(&settings->imapaint.brush)) {
+ BIF_undo_push("Unlink Brush");
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ }
+ break;
+ case B_KEEPDATA:
+ brush_toggled_fake_user(settings->imapaint.brush);
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ break;
+ case B_SIMABRUSHLOCAL:
+ if(settings->imapaint.brush && settings->imapaint.brush->id.lib) {
+ if(okee("Make local")) {
+ make_local_brush(settings->imapaint.brush);
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ }
+ }
+ break;
+ case B_SIMABTEXBROWSE:
+ if(settings->imapaint.brush) {
+ Brush *brush= settings->imapaint.brush;
+
+ if(sima->menunr==-2) {
+ MTex *mtex= brush->mtex[brush->texact];
+ ID *id= (ID*)((mtex)? mtex->tex: NULL);
+ if(G.qual & LR_CTRLKEY) {
+ activate_databrowse_imasel(id, ID_TE, 0, B_SIMABTEXBROWSE, &sima->menunr, do_image_buttons);
+ } else {
+ activate_databrowse(id, ID_TE, 0, B_SIMABTEXBROWSE, &sima->menunr, do_image_buttons);
+ }
+ break;
+ }
+ else if(sima->menunr < 0) break;
+
+ if(brush_texture_set_nr(brush, sima->menunr)) {
+ BIF_undo_push("Browse Brush Texture");
+ allqueue(REDRAWBUTSSHADING, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWIMAGE, 0);
+ }
+ }
+ break;
+ case B_SIMABTEXDELETE:
+ if(settings->imapaint.brush) {
+ if (brush_texture_delete(settings->imapaint.brush)) {
+ BIF_undo_push("Unlink Brush Texture");
+ allqueue(REDRAWBUTSSHADING, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWIMAGE, 0);
+ }
+ }
+ break;
+ case B_SIMA_PLAY:
+ play_anim(0);
+ break;
+ case B_SIMA_RECORD:
+ imagespace_composite_flipbook(curarea);
+ break;
+ }
+#endif
+}
+
+#if 0
+static void do_image_buttons_set_uvlayer_callback(void *act, void *data)
+{
+ CustomData_set_layer_active(&G.editMesh->fdata, CD_MTFACE, *((int *)act));
+
+ BIF_undo_push("Set Active UV Texture");
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWIMAGE, 0);
+}
+#endif
+
+static void sima_idpoin_handle(bContext *C, ID *id, int event)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+
+ switch(event) {
+ case UI_ID_BROWSE:
+ case UI_ID_DELETE:
+ ED_space_image_set(C, sima, scene, obedit, (Image*)id);
+ ED_undo_push(C, "Assign Image UV");
+ break;
+ case UI_ID_RENAME:
+ break;
+ case UI_ID_ADD_NEW:
+ WM_operator_name_call(C, "IMAGE_OT_new", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ case UI_ID_OPEN:
+ WM_operator_name_call(C, "IMAGE_OT_open", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ case UI_ID_PIN:
+ ED_area_tag_refresh(CTX_wm_area(C));
+ break;
+ }
+}
+
+void image_header_buttons(const bContext *C, ARegion *ar)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ ScrArea *sa= CTX_wm_area(C);
+ Scene *scene= CTX_data_scene(C);
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Image *ima;
+ ImBuf *ibuf;
+ uiBlock *block;
+ uiBut *but;
+ PointerRNA spaceptr, uvptr, sceneptr;
+ int xco, yco= 3, show_uvedit, show_render, show_paint, pinflag;
+
+ /* retrieve state */
+ ima= ED_space_image(sima);
+ ibuf= ED_space_image_buffer(sima);
+
+ show_render= ED_space_image_show_render(sima);
+ show_paint= ED_space_image_show_paint(sima);
+ show_uvedit= ED_space_image_show_uvedit(sima, CTX_data_edit_object(C));
+
+ RNA_pointer_create(&sc->id, &RNA_SpaceImageEditor, sima, &spaceptr);
+ RNA_pointer_create(&sc->id, &RNA_SpaceUVEditor, sima, &uvptr);
+ RNA_id_pointer_create(&scene->id, &sceneptr);
+
+ /* create block */
+ block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_image_buttons, NULL);
+
+ xco= ED_area_header_standardbuttons(C, block, yco);
+
+ /* create pulldown menus */
+ if((sa->flag & HEADER_NO_PULLDOWN)==0) {
+ char *menuname;
+ int xmax;
+
+ xmax= GetButStringLength("View");
+ uiDefMenuBut(block, image_viewmenu, NULL, "View", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+
+ if(show_uvedit) {
+ xmax= GetButStringLength("Select");
+ uiDefMenuBut(block, image_selectmenu, NULL, "Select", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+ }
+
+ menuname= (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))? "Image*": "Image";
+ xmax= GetButStringLength(menuname);
+ uiDefMenuBut(block, image_imagemenu, NULL, menuname, xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+
+ if(show_uvedit) {
+ xmax= GetButStringLength("UVs");
+ uiDefMenuBut(block, image_uvsmenu, NULL, "UVs", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+ }
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ /* image select */
+
+ pinflag= (show_render)? 0: UI_ID_PIN;
+ xco= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)sima->image, ID_IM, &sima->pin, xco, yco,
+ sima_idpoin_handle, UI_ID_BROWSE|UI_ID_BROWSE_RENDER|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_OPEN|UI_ID_DELETE|pinflag);
+ xco += 8;
+
+ if(ima && !ELEM3(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_VIEWER) && ima->ok) {
+ /* XXX this should not be a static var */
+ static int headerbuttons_packdummy;
+
+ headerbuttons_packdummy = 0;
+
+ if (ima->packedfile) {
+ headerbuttons_packdummy = 1;
+ }
+ if (ima->packedfile && ibuf && (ibuf->userflags & IB_BITMAPDIRTY))
+ uiDefIconButBitI(block, TOG, 1, 0 /* XXX B_SIMA_REPACK */, ICON_UGLYPACKAGE, xco,yco,XIC,YIC, &headerbuttons_packdummy, 0, 0, 0, 0, "Re-Pack this image as PNG");
+ else
+ uiDefIconButBitI(block, TOG, 1, 0 /* XXX B_SIMAPACKIMA */, ICON_PACKAGE, xco,yco,XIC,YIC, &headerbuttons_packdummy, 0, 0, 0, 0, "Pack/Unpack this image");
+
+ xco+= XIC+8;
+ }
+
+ /* uv editing */
+ if(show_uvedit) {
+ /* pivot */
+ uiDefIconTextButS(block, ICONTEXTROW, B_NOP, ICON_ROTATE,
+ "Pivot: %t|Bounding Box Center %x0|Median Point %x3|2D Cursor %x1",
+ xco,yco,XIC+10,YIC, &ar->v2d.around, 0, 3.0, 0, 0,
+ "Rotation/Scaling Pivot (Hotkeys: Comma, Shift Comma, Period)");
+ xco+= XIC + 18;
+
+ /* selection modes */
+ uiDefIconButBitS(block, TOG, UV_SYNC_SELECTION, B_REDR, ICON_EDIT, xco,yco,XIC,YIC, &scene->toolsettings->uv_flag, 0, 0, 0, 0, "Sync UV and Mesh Selection");
+ xco+= XIC+8;
+
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ uiBlockBeginAlign(block);
+
+ uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_REDR, ICON_VERTEXSEL,
+ xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode");
+ uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_REDR, ICON_EDGESEL,
+ xco+=XIC,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Edge select mode");
+ uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_REDR, ICON_FACESEL,
+ xco+=XIC,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Face select mode");
+
+ uiBlockEndAlign(block);
+ }
+ else {
+ uiBlockBeginAlign(block);
+
+ uiDefIconButS(block, ROW, B_REDR, ICON_VERTEXSEL,
+ xco,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_VERTEX, 0, 0, "Vertex select mode");
+ uiDefIconButS(block, ROW, B_REDR, ICON_EDGESEL,
+ xco+=XIC,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_EDGE, 0, 0, "Edge select mode");
+ uiDefIconButS(block, ROW, B_REDR, ICON_FACESEL,
+ xco+=XIC,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_FACE, 0, 0, "Face select mode");
+ uiDefIconButS(block, ROW, B_REDR, ICON_LINKEDSEL,
+ xco+=XIC,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_ISLAND, 0, 0, "Island select mode");
+
+ uiBlockEndAlign(block);
+
+ /* would use these if const's could go in strings
+ * SI_STICKY_LOC SI_STICKY_DISABLE SI_STICKY_VERTEX */
+ but = uiDefIconTextButC(block, ICONTEXTROW, B_REDR, ICON_STICKY_UVS_LOC,
+ "Sticky UV Selection: %t|Disable%x1|Shared Location%x0|Shared Vertex%x2",
+ xco+=XIC+10,yco,XIC+10,YIC, &(sima->sticky), 0, 3.0, 0, 0,
+ "Sticky UV Selection (Hotkeys: Shift C, Alt C, Ctrl C)");
+ }
+
+ xco+= XIC + 16;
+
+ /* snap options, identical to options in 3d view header */
+ uiBlockBeginAlign(block);
+
+ if (scene->snap_flag & SCE_SNAP) {
+ uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Use Snap or Grid (Shift Tab).");
+ xco+= XIC;
+ uiDefButS(block, MENU, B_NOP, "Mode%t|Closest%x0|Center%x1|Median%x2",xco,yco,70,YIC, &scene->snap_target, 0, 0, 0, 0, "Snap Target Mode.");
+ xco+= 70;
+ }
+ else {
+ uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab).");
+ xco+= XIC;
+ }
+
+ uiBlockEndAlign(block);
+ xco+= 8;
+
+ /* uv layers */
+ {
+ Object *obedit= CTX_data_edit_object(C);
+ char menustr[34*MAX_MTFACE];
+ static int act;
+
+ image_menu_uvlayers(obedit, menustr, &act);
+
+ but = uiDefButI(block, MENU, B_NOP, menustr ,xco,yco,85,YIC, &act, 0, 0, 0, 0, "Active UV Layer for editing.");
+ // uiButSetFunc(but, do_image_buttons_set_uvlayer_callback, &act, NULL);
+
+ xco+= 85;
+ }
+
+ xco+= 8;
+ }
+
+ if(ima) {
+ RenderResult *rr;
+
+ /* render layers and passes */
+ rr= BKE_image_get_renderresult(scene, ima);
+ if(rr) {
+ uiBlockBeginAlign(block);
+#if 0
+ uiblock_layer_pass_buttons(block, rr, &sima->iuser, B_REDR, xco, 0, 160);
+#endif
+ uiBlockEndAlign(block);
+ xco+= 166;
+ }
+
+ /* painting */
+ uiDefIconButR(block, TOG, B_REDR, ICON_TPAINT_HLT, xco,yco,XIC,YIC, &spaceptr, "image_painting", 0, 0, 0, 0, 0, NULL);
+ xco+= XIC+8;
+
+ /* image draw options */
+ uiBlockBeginAlign(block);
+ uiDefIconButR(block, ROW, B_REDR, ICON_IMAGE_RGB, xco,yco,XIC,YIC, &spaceptr, "draw_channels", 0, 0, 0, 0, 0, NULL);
+ xco+= XIC;
+ if(ibuf==NULL || ibuf->channels==4) {
+ uiDefIconButR(block, ROW, B_REDR, ICON_IMAGE_RGB_ALPHA, xco,yco,XIC,YIC, &spaceptr, "draw_channels", 0, 0, SI_USE_ALPHA, 0, 0, NULL);
+ xco+= XIC;
+ uiDefIconButR(block, ROW, B_REDR, ICON_IMAGE_ALPHA, xco,yco,XIC,YIC, &spaceptr, "draw_channels", 0, 0, SI_SHOW_ALPHA, 0, 0, NULL);
+ xco+= XIC;
+ }
+ if(ibuf) {
+ if(ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels==1)) {
+ uiDefIconButR(block, ROW, B_REDR, ICON_IMAGE_ZDEPTH, xco,yco,XIC,YIC, &spaceptr, "draw_channels", 0, 0, SI_SHOW_ZBUF, 0, 0, NULL);
+ xco+= XIC;
+ }
+ }
+ xco+= 8;
+
+ /* record & play */
+ uiBlockBeginAlign(block);
+ if(ima->type==IMA_TYPE_COMPOSITE) {
+ uiDefIconButO(block, BUT, "IMAGE_OT_record_composite", WM_OP_INVOKE_REGION_WIN, ICON_REC, xco, yco, XIC, YIC, NULL); // Record Composite
+ xco+= XIC;
+ }
+ if((ima->type==IMA_TYPE_COMPOSITE) || ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
+//XXX uiDefIconButO(block, BUT, "IMAGE_OT_play_composite", WM_OP_INVOKE_REGION_WIN, ICON_PLAY, xco, yco, XIC, YIC, NULL); // PLAY
+ xco+= XIC;
+ }
+ uiBlockEndAlign(block);
+ xco+= 8;
+ }
+
+ /* draw lock */
+ uiDefIconButR(block, ICONTOG, 0, ICON_UNLOCKED, xco,yco,XIC,YIC, &spaceptr, "update_automatically", 0, 0, 0, 0, 0, NULL);
+
+ /* always as last */
+ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+}
+
+/********************** toolbox operator *********************/
+
+static int toolbox_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Object *obedit= CTX_data_edit_object(C);
+ uiMenuItem *head;
+ int show_uvedit;
+
+ show_uvedit= ED_space_image_show_uvedit(sima, obedit);
+
+ head= uiPupMenuBegin("Toolbox", 0);
+
+ uiMenuLevel(head, "View", image_viewmenu);
+ if(show_uvedit) uiMenuLevel(head, "Select", image_selectmenu);
+ uiMenuLevel(head, "Image", image_imagemenu);
+ if(show_uvedit) uiMenuLevel(head, "UVs", image_uvsmenu);
+
+ uiPupMenuEnd(C, head);
+
+ return OPERATOR_CANCELLED;
+}
+
+void IMAGE_OT_toolbox(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Toolbox";
+ ot->idname= "IMAGE_OT_toolbox";
+
+ /* api callbacks */
+ ot->invoke= toolbox_invoke;
+ ot->poll= space_image_main_area_poll;
+}
+
diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h
new file mode 100644
index 00000000000..c592e2cb004
--- /dev/null
+++ b/source/blender/editors/space_image/image_intern.h
@@ -0,0 +1,91 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_IMAGE_INTERN_H
+#define ED_IMAGE_INTERN_H
+
+/* internal exports only */
+struct bContext;
+struct ARegion;
+struct ScrArea;
+struct SpaceImage;
+struct Object;
+struct Image;
+struct ImBuf;
+struct wmOperatorType;
+struct Scene;
+struct bNodeTree;
+
+/* space_image.c */
+struct ARegion *image_has_buttons_region(struct ScrArea *sa);
+
+/* image_header.c */
+void image_header_buttons(const struct bContext *C, struct ARegion *ar);
+
+void IMAGE_OT_toolbox(struct wmOperatorType *ot);
+
+/* image_draw.c */
+void draw_image_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene);
+void draw_image_info(struct ARegion *ar, int channels, int x, int y, char *cp, float *fp, int *zp, float *zpf);
+
+/* image_ops.c */
+int space_image_main_area_poll(struct bContext *C);
+
+void IMAGE_OT_view_all(struct wmOperatorType *ot);
+void IMAGE_OT_view_pan(struct wmOperatorType *ot);
+void IMAGE_OT_view_selected(struct wmOperatorType *ot);
+void IMAGE_OT_view_zoom(struct wmOperatorType *ot);
+void IMAGE_OT_view_zoom_in(struct wmOperatorType *ot);
+void IMAGE_OT_view_zoom_out(struct wmOperatorType *ot);
+void IMAGE_OT_view_zoom_ratio(struct wmOperatorType *ot);
+
+void IMAGE_OT_new(struct wmOperatorType *ot);
+void IMAGE_OT_open(struct wmOperatorType *ot);
+void IMAGE_OT_replace(struct wmOperatorType *ot);
+void IMAGE_OT_reload(struct wmOperatorType *ot);
+void IMAGE_OT_save(struct wmOperatorType *ot);
+void IMAGE_OT_save_as(struct wmOperatorType *ot);
+void IMAGE_OT_save_sequence(struct wmOperatorType *ot);
+void IMAGE_OT_pack(struct wmOperatorType *ot);
+void IMAGE_OT_unpack(struct wmOperatorType *ot);
+
+void IMAGE_OT_sample(struct wmOperatorType *ot);
+void IMAGE_OT_curves_point_set(struct wmOperatorType *ot);
+
+void IMAGE_OT_record_composite(struct wmOperatorType *ot);
+
+/* uvedit_draw.c */
+void draw_uvedit_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct Object *obedit);
+
+/* image_panels.c */
+struct ImageUser *ntree_get_active_iuser(struct bNodeTree *ntree);
+void image_buttons_area_defbuts(const struct bContext *C, struct ARegion *ar);
+void IMAGE_OT_properties(struct wmOperatorType *ot);
+
+#endif /* ED_IMAGE_INTERN_H */
+
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
new file mode 100644
index 00000000000..fcafcd22a3d
--- /dev/null
+++ b/source/blender/editors/space_image/image_ops.c
@@ -0,0 +1,1631 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2002-2009
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_image_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_packedFile_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_image.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_node.h"
+#include "BKE_packedFile.h"
+#include "BKE_report.h"
+#include "BKE_screen.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "RE_pipeline.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_types.h"
+
+#include "ED_image.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+#include "ED_uvedit.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "image_intern.h"
+
+/******************** view navigation utilities *********************/
+
+static void sima_zoom_set(SpaceImage *sima, ARegion *ar, float zoom)
+{
+ float oldzoom= sima->zoom;
+ int width, height;
+
+ sima->zoom= zoom;
+
+ if (sima->zoom > 0.1f && sima->zoom < 4.0f)
+ return;
+
+ /* check zoom limits */
+ ED_space_image_size(sima, &width, &height);
+
+ width *= sima->zoom;
+ height *= sima->zoom;
+
+ if((width < 4) && (height < 4))
+ sima->zoom= oldzoom;
+ else if((ar->winrct.xmax - ar->winrct.xmin) <= sima->zoom)
+ sima->zoom= oldzoom;
+ else if((ar->winrct.ymax - ar->winrct.ymin) <= sima->zoom)
+ sima->zoom= oldzoom;
+}
+
+static void sima_zoom_set_factor(SpaceImage *sima, ARegion *ar, float zoomfac)
+{
+ sima_zoom_set(sima, ar, sima->zoom*zoomfac);
+}
+
+static int space_image_poll(bContext *C)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ if(sima && sima->spacetype==SPACE_IMAGE)
+ if(ED_space_image_buffer(sima))
+ return 1;
+ return 0;
+}
+
+static int space_image_file_exists_poll(bContext *C)
+{
+ if(space_image_poll(C)) {
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ImBuf *ibuf= ED_space_image_buffer(sima);
+
+ if(ibuf && BLI_exists(ibuf->name) && BLI_is_writable(ibuf->name))
+ return 1;
+ }
+ return 0;
+}
+
+
+int space_image_main_area_poll(bContext *C)
+{
+ SpaceLink *slink= CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+
+ if(slink && (slink->spacetype == SPACE_IMAGE))
+ return (ar && ar->type->regionid == RGN_TYPE_WINDOW);
+
+ return 0;
+}
+
+/********************** view pan operator *********************/
+
+typedef struct ViewPanData {
+ float x, y;
+ float xof, yof;
+} ViewPanData;
+
+static void view_pan_init(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ViewPanData *vpd;
+
+ op->customdata= vpd= MEM_callocN(sizeof(ViewPanData), "ImageViewPanData");
+ WM_cursor_modal(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
+
+ vpd->x= event->x;
+ vpd->y= event->y;
+ vpd->xof= sima->xof;
+ vpd->yof= sima->yof;
+
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+}
+
+static void view_pan_exit(bContext *C, wmOperator *op, int cancel)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ViewPanData *vpd= op->customdata;
+
+ if(cancel) {
+ sima->xof= vpd->xof;
+ sima->yof= vpd->yof;
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ WM_cursor_restore(CTX_wm_window(C));
+ MEM_freeN(op->customdata);
+}
+
+static int view_pan_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ float offset[2];
+
+ RNA_float_get_array(op->ptr, "offset", offset);
+ sima->xof += offset[0];
+ sima->yof += offset[1];
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ /* XXX notifier? */
+#if 0
+ if(image_preview_active(curarea, NULL, NULL)) {
+ /* recalculates new preview rect */
+ scrarea_do_windraw(curarea);
+ image_preview_event(2);
+ }
+#endif
+
+ return OPERATOR_FINISHED;
+}
+
+static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ view_pan_init(C, op, event);
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int view_pan_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ViewPanData *vpd= op->customdata;
+ float offset[2];
+
+ switch(event->type) {
+ case MOUSEMOVE:
+ sima->xof= vpd->xof;
+ sima->yof= vpd->yof;
+ offset[0]= (vpd->x - event->x)/sima->zoom;
+ offset[1]= (vpd->y - event->y)/sima->zoom;
+ RNA_float_set_array(op->ptr, "offset", offset);
+ view_pan_exec(C, op);
+ break;
+ case MIDDLEMOUSE:
+ if(event->val==0) {
+ view_pan_exit(C, op, 0);
+ return OPERATOR_FINISHED;
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int view_pan_cancel(bContext *C, wmOperator *op)
+{
+ view_pan_exit(C, op, 1);
+ return OPERATOR_CANCELLED;
+}
+
+void IMAGE_OT_view_pan(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View Pan";
+ ot->idname= "IMAGE_OT_view_pan";
+
+ /* api callbacks */
+ ot->exec= view_pan_exec;
+ ot->invoke= view_pan_invoke;
+ ot->modal= view_pan_modal;
+ ot->cancel= view_pan_cancel;
+ ot->poll= space_image_main_area_poll;
+
+ /* properties */
+ RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX,
+ "Offset", "Offset in floating point units, 1.0 is the width and height of the image.", -FLT_MAX, FLT_MAX);
+}
+
+/********************** view zoom operator *********************/
+
+typedef struct ViewZoomData {
+ float x, y;
+ float zoom;
+} ViewZoomData;
+
+static void view_zoom_init(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ViewZoomData *vpd;
+
+ op->customdata= vpd= MEM_callocN(sizeof(ViewZoomData), "ImageViewZoomData");
+ WM_cursor_modal(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
+
+ vpd->x= event->x;
+ vpd->y= event->y;
+ vpd->zoom= sima->zoom;
+
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+}
+
+static void view_zoom_exit(bContext *C, wmOperator *op, int cancel)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ViewZoomData *vpd= op->customdata;
+
+ if(cancel) {
+ sima->zoom= vpd->zoom;
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ WM_cursor_restore(CTX_wm_window(C));
+ MEM_freeN(op->customdata);
+}
+
+static int view_zoom_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+
+ sima_zoom_set_factor(sima, ar, RNA_float_get(op->ptr, "factor"));
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ /* XXX notifier? */
+#if 0
+ if(image_preview_active(curarea, NULL, NULL)) {
+ /* recalculates new preview rect */
+ scrarea_do_windraw(curarea);
+ image_preview_event(2);
+ }
+#endif
+
+ return OPERATOR_FINISHED;
+}
+
+static int view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ view_zoom_init(C, op, event);
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int view_zoom_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+ ViewZoomData *vpd= op->customdata;
+ float factor;
+
+ switch(event->type) {
+ case MOUSEMOVE:
+ factor= 1.0 + (vpd->x-event->x+vpd->y-event->y)/300.0f;
+ RNA_float_set(op->ptr, "factor", factor);
+ sima_zoom_set(sima, ar, vpd->zoom*factor);
+ ED_area_tag_redraw(CTX_wm_area(C));
+ break;
+ case MIDDLEMOUSE:
+ if(event->val==0) {
+ view_zoom_exit(C, op, 0);
+ return OPERATOR_FINISHED;
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int view_zoom_cancel(bContext *C, wmOperator *op)
+{
+ view_zoom_exit(C, op, 1);
+ return OPERATOR_CANCELLED;
+}
+
+void IMAGE_OT_view_zoom(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View Zoom";
+ ot->idname= "IMAGE_OT_view_zoom";
+
+ /* api callbacks */
+ ot->exec= view_zoom_exec;
+ ot->invoke= view_zoom_invoke;
+ ot->modal= view_zoom_modal;
+ ot->cancel= view_zoom_cancel;
+ ot->poll= space_image_main_area_poll;
+
+ /* properties */
+ RNA_def_float(ot->srna, "factor", 0.0f, 0.0f, FLT_MAX,
+ "Factor", "Zoom factor, values higher than 1.0 zoom in, lower values zoom out.", -FLT_MAX, FLT_MAX);
+}
+
+/********************** view all operator *********************/
+
+/* 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 */
+
+static int view_all_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima;
+ ARegion *ar;
+ Scene *scene;
+ Object *obedit;
+ Image *ima;
+ ImBuf *ibuf;
+ float aspx, aspy, zoomx, zoomy, w, h;
+ int width, height;
+
+ /* retrieve state */
+ sima= (SpaceImage*)CTX_wm_space_data(C);
+ ar= CTX_wm_region(C);
+ scene= (Scene*)CTX_data_scene(C);
+ obedit= CTX_data_edit_object(C);
+
+ ima= ED_space_image(sima);
+ ibuf= ED_space_image_buffer(sima);
+ ED_space_image_size(sima, &width, &height);
+ ED_space_image_aspect(sima, &aspx, &aspy);
+
+ w= width*aspx;
+ h= height*aspy;
+
+ /* check if the image will fit in the image with zoom==1 */
+ width = ar->winrct.xmax - ar->winrct.xmin + 1;
+ height = ar->winrct.ymax - ar->winrct.ymin + 1;
+
+ if((w >= width || h >= height) && (width > 0 && height > 0)) {
+ /* find the zoom value that will fit the image in the image space */
+ zoomx= width/w;
+ zoomy= height/h;
+ sima_zoom_set(sima, ar, 1.0f/power_of_2(1/MIN2(zoomx, zoomy)));
+ }
+ else
+ sima_zoom_set(sima, ar, 1.0f);
+
+ sima->xof= sima->yof= 0.0f;
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_view_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View All";
+ ot->idname= "IMAGE_OT_view_all";
+
+ /* api callbacks */
+ ot->exec= view_all_exec;
+ ot->poll= space_image_main_area_poll;
+}
+
+/********************** view selected operator *********************/
+
+static int view_selected_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima;
+ ARegion *ar;
+ Scene *scene;
+ Object *obedit;
+ Image *ima;
+ ImBuf *ibuf;
+ float size, min[2], max[2], d[2];
+ int width, height;
+
+ /* retrieve state */
+ sima= (SpaceImage*)CTX_wm_space_data(C);
+ ar= CTX_wm_region(C);
+ scene= (Scene*)CTX_data_scene(C);
+ obedit= CTX_data_edit_object(C);
+
+ ima= ED_space_image(sima);
+ ibuf= ED_space_image_buffer(sima);
+ ED_space_image_size(sima, &width, &height);
+
+ /* get bounds */
+ if(!ED_uvedit_minmax(scene, ima, obedit, min, max))
+ return OPERATOR_CANCELLED;
+
+ /* adjust offset and zoom */
+ sima->xof= (int)(((min[0] + max[0])*0.5f - 0.5f)*width);
+ sima->yof= (int)(((min[1] + max[1])*0.5f - 0.5f)*height);
+
+ d[0]= max[0] - min[0];
+ d[1]= max[1] - min[1];
+ size= 0.5*MAX2(d[0], d[1])*MAX2(width, height)/256.0f;
+
+ if(size<=0.01) size= 0.01;
+ sima_zoom_set(sima, ar, 0.7/size);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_view_selected(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View Center";
+ ot->idname= "IMAGE_OT_view_selected";
+
+ /* api callbacks */
+ ot->exec= view_selected_exec;
+ ot->poll= ED_operator_uvedit;
+}
+
+/********************** view zoom in/out operator *********************/
+
+static int view_zoom_in_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+
+ sima_zoom_set_factor(sima, ar, 1.25f);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_view_zoom_in(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View Zoom In";
+ ot->idname= "IMAGE_OT_view_zoom_in";
+
+ /* api callbacks */
+ ot->exec= view_zoom_in_exec;
+ ot->poll= space_image_main_area_poll;
+}
+
+static int view_zoom_out_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+
+ sima_zoom_set_factor(sima, ar, 0.8f);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_view_zoom_out(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View Zoom Out";
+ ot->idname= "IMAGE_OT_view_zoom_out";
+
+ /* api callbacks */
+ ot->exec= view_zoom_out_exec;
+ ot->poll= space_image_main_area_poll;
+}
+
+/********************** view zoom ratio operator *********************/
+
+static int view_zoom_ratio_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+
+ sima_zoom_set(sima, ar, RNA_float_get(op->ptr, "ratio"));
+
+ /* ensure pixel exact locations for draw */
+ sima->xof= (int)sima->xof;
+ sima->yof= (int)sima->yof;
+
+ /* XXX notifier? */
+#if 0
+ if(image_preview_active(curarea, NULL, NULL)) {
+ /* recalculates new preview rect */
+ scrarea_do_windraw(curarea);
+ image_preview_event(2);
+ }
+#endif
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_view_zoom_ratio(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View Zoom Ratio";
+ ot->idname= "IMAGE_OT_view_zoom_ratio";
+
+ /* api callbacks */
+ ot->exec= view_zoom_ratio_exec;
+ ot->poll= space_image_main_area_poll;
+
+ /* properties */
+ RNA_def_float(ot->srna, "ratio", 0.0f, 0.0f, FLT_MAX,
+ "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out.", -FLT_MAX, FLT_MAX);
+}
+
+/**************** load/replace/save callbacks ******************/
+
+static char *filesel_imagetype_string(Image *ima)
+{
+ char *strp, *str= MEM_callocN(14*32, "menu for filesel");
+
+ strp= str;
+ str += sprintf(str, "Save Image as: %%t|");
+ str += sprintf(str, "Targa %%x%d|", R_TARGA);
+ str += sprintf(str, "Targa Raw %%x%d|", R_RAWTGA);
+ str += sprintf(str, "PNG %%x%d|", R_PNG);
+ str += sprintf(str, "BMP %%x%d|", R_BMP);
+ str += sprintf(str, "Jpeg %%x%d|", R_JPEG90);
+ str += sprintf(str, "Iris %%x%d|", R_IRIS);
+ if(G.have_libtiff)
+ str += sprintf(str, "Tiff %%x%d|", R_TIFF);
+ str += sprintf(str, "Radiance HDR %%x%d|", R_RADHDR);
+ str += sprintf(str, "Cineon %%x%d|", R_CINEON);
+ str += sprintf(str, "DPX %%x%d|", R_DPX);
+#ifdef WITH_OPENEXR
+ str += sprintf(str, "OpenEXR %%x%d|", R_OPENEXR);
+ /* saving sequences of multilayer won't work, they copy buffers */
+ if(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER);
+ else str += sprintf(str, "MultiLayer %%x%d|", R_MULTILAYER);
+#endif
+ return strp;
+}
+
+static void image_filesel(bContext *C, wmOperator *op, const char *path)
+{
+ RNA_string_set(op->ptr, "filename", path);
+ WM_event_add_fileselect(C, op);
+}
+
+/******************** open image operator ********************/
+
+static int open_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Image *ima= NULL;
+ char str[FILE_MAX];
+
+ RNA_string_get(op->ptr, "filename", str);
+ ima= BKE_add_image_file(str, scene->r.cfra);
+
+ if(!ima)
+ return OPERATOR_CANCELLED;
+
+ BKE_image_signal(ima, &sima->iuser, IMA_SIGNAL_RELOAD);
+ ED_space_image_set(C, sima, scene, obedit, ima);
+
+ return OPERATOR_FINISHED;
+}
+
+static int open_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ char *path= (sima->image)? sima->image->name: U.textudir;
+
+ if(RNA_property_is_set(op->ptr, "filename"))
+ return open_exec(C, op);
+
+ image_filesel(C, op, path);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void IMAGE_OT_open(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Open";
+ ot->idname= "IMAGE_OT_open";
+
+ /* api callbacks */
+ ot->exec= open_exec;
+ ot->invoke= open_invoke;
+ ot->poll= ED_operator_image_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_string_file_path(ot->srna, "filename", "", FILE_MAX, "Filename", "File path of image to open.");
+}
+
+/******************** replace image operator ********************/
+
+static int replace_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ char str[FILE_MAX];
+
+ if(!sima->image)
+ return OPERATOR_CANCELLED;
+
+ RNA_string_get(op->ptr, "filename", str);
+ BLI_strncpy(sima->image->name, str, sizeof(sima->image->name)-1); /* we cant do much if the str is longer then 240 :/ */
+
+ BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_RELOAD);
+ WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, sima->image);
+
+ return OPERATOR_FINISHED;
+}
+
+static int replace_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ char *path= (sima->image)? sima->image->name: U.textudir;
+
+ if(!sima->image)
+ return OPERATOR_CANCELLED;
+
+ if(RNA_property_is_set(op->ptr, "filename"))
+ return replace_exec(C, op);
+
+ image_filesel(C, op, path);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void IMAGE_OT_replace(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Replace";
+ ot->idname= "IMAGE_OT_replace";
+
+ /* api callbacks */
+ ot->exec= replace_exec;
+ ot->invoke= replace_invoke;
+ ot->poll= space_image_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_string_file_path(ot->srna, "filename", "", FILE_MAX, "Filename", "File path of image to replace current image with.");
+}
+
+/******************** save image as operator ********************/
+
+/* assumes name is FILE_MAX */
+/* ima->name and ibuf->name should end up the same */
+static void save_image_doit(bContext *C, SpaceImage *sima, Scene *scene, wmOperator *op, char *name)
+{
+ Image *ima= ED_space_image(sima);
+ ImBuf *ibuf= ED_space_image_buffer(sima);
+ int len;
+
+ if (ibuf) {
+ BLI_convertstringcode(name, G.sce);
+ BLI_convertstringframe(name, scene->r.cfra);
+
+ if(scene->r.scemode & R_EXTENSION) {
+ BKE_add_image_extension(scene, name, sima->imtypenr);
+ BKE_add_image_extension(scene, name, sima->imtypenr);
+ }
+
+ /* enforce user setting for RGB or RGBA, but skip BW */
+ if(scene->r.planes==32)
+ ibuf->depth= 32;
+ else if(scene->r.planes==24)
+ ibuf->depth= 24;
+
+ WM_cursor_wait(1);
+
+ if(sima->imtypenr==R_MULTILAYER) {
+ RenderResult *rr= BKE_image_get_renderresult(scene, ima);
+ if(rr) {
+ RE_WriteRenderResult(rr, name, scene->r.quality);
+
+ BLI_strncpy(ima->name, name, sizeof(ima->name));
+ BLI_strncpy(ibuf->name, name, sizeof(ibuf->name));
+
+ /* should be function? nevertheless, saving only happens here */
+ for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next)
+ ibuf->userflags &= ~IB_BITMAPDIRTY;
+
+ }
+ else
+ BKE_report(op->reports, RPT_ERROR, "Did not write, no Multilayer Image");
+ }
+ else if (BKE_write_ibuf(scene, ibuf, name, sima->imtypenr, scene->r.subimtype, scene->r.quality)) {
+ BLI_strncpy(ima->name, name, sizeof(ima->name));
+ BLI_strncpy(ibuf->name, name, sizeof(ibuf->name));
+
+ ibuf->userflags &= ~IB_BITMAPDIRTY;
+
+ /* change type? */
+ if( ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER)) {
+ ima->source= IMA_SRC_FILE;
+ ima->type= IMA_TYPE_IMAGE;
+ }
+ if(ima->type==IMA_TYPE_R_RESULT)
+ ima->type= IMA_TYPE_IMAGE;
+
+ /* name image as how we saved it */
+ len= strlen(name);
+ while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\') len--;
+ rename_id(&ima->id, name+len);
+ }
+ else
+ BKE_reportf(op->reports, RPT_ERROR, "Couldn't write image: %s", name);
+
+ WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, sima->image);
+
+ WM_cursor_wait(0);
+ }
+}
+
+static int save_as_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ Image *ima = ED_space_image(sima);
+ char str[FILE_MAX];
+
+ if(!ima)
+ return OPERATOR_CANCELLED;
+
+ RNA_string_get(op->ptr, "filename", str);
+ save_image_doit(C, sima, scene, op, str);
+
+ return OPERATOR_FINISHED;
+}
+
+static int save_as_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Image *ima = ED_space_image(sima);
+ ImBuf *ibuf= ED_space_image_buffer(sima);
+ Scene *scene= CTX_data_scene(C);
+
+ if(RNA_property_is_set(op->ptr, "filename"))
+ return save_as_exec(C, op);
+
+ if(!ima)
+ return OPERATOR_CANCELLED;
+
+ /* always opens fileselect */
+ if(ibuf) {
+ char *strp;
+
+ strp= filesel_imagetype_string(ima); // XXX unused still
+
+ /* cant save multilayer sequence, ima->rr isn't valid for a specific frame */
+ if(ima->rr && !(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER))
+ sima->imtypenr= R_MULTILAYER;
+ else if(ima->type==IMA_TYPE_R_RESULT)
+ sima->imtypenr= scene->r.imtype;
+ else
+ sima->imtypenr= BKE_ftype_to_imtype(ibuf->ftype);
+
+ if(ibuf->name[0]==0)
+ BLI_strncpy(ibuf->name, G.ima, FILE_MAX);
+
+ // XXX note: we can give default menu enums to operator for this
+ image_filesel(C, op, ibuf->name);
+
+ MEM_freeN(strp);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void IMAGE_OT_save_as(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Save As";
+ ot->idname= "IMAGE_OT_save_as";
+
+ /* api callbacks */
+ ot->exec= save_as_exec;
+ ot->invoke= save_as_invoke;
+ ot->poll= space_image_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_string_file_path(ot->srna, "filename", "", FILE_MAX, "Filename", "File path to save image to.");
+}
+
+/******************** save image operator ********************/
+
+static int save_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Image *ima = ED_space_image(sima);
+ ImBuf *ibuf= ED_space_image_buffer(sima);
+ Scene *scene= CTX_data_scene(C);
+ char name[FILE_MAX];
+
+ if(!ima || !ibuf)
+ return OPERATOR_CANCELLED;
+
+ /* if exists, saves over without fileselect */
+
+ BLI_strncpy(name, ibuf->name, FILE_MAX);
+ if(name[0]==0)
+ BLI_strncpy(name, G.ima, FILE_MAX);
+
+ if(BLI_exists(name) && BLI_is_writable(name)) {
+ if(BKE_image_get_renderresult(scene, ima))
+ sima->imtypenr= R_MULTILAYER;
+ else
+ sima->imtypenr= BKE_ftype_to_imtype(ibuf->ftype);
+
+ save_image_doit(C, sima, scene, op, name);
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Can not save image.");
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_save(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Save";
+ ot->idname= "IMAGE_OT_save";
+
+ /* api callbacks */
+ ot->exec= save_exec;
+ ot->poll= space_image_file_exists_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/******************* save sequence operator ********************/
+
+static int save_sequence_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ImBuf *ibuf;
+ int tot= 0;
+ char di[FILE_MAX], fi[FILE_MAX];
+
+ if(sima->image==NULL)
+ return OPERATOR_CANCELLED;
+
+ if(sima->image->source!=IMA_SRC_SEQUENCE) {
+ BKE_report(op->reports, RPT_ERROR, "Can only save sequence on image sequences.");
+ return OPERATOR_CANCELLED;
+ }
+
+ if(sima->image->type==IMA_TYPE_MULTILAYER) {
+ BKE_report(op->reports, RPT_ERROR, "Can't save multilayer sequences.");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get total */
+ for(ibuf= sima->image->ibufs.first; ibuf; ibuf= ibuf->next)
+ if(ibuf->userflags & IB_BITMAPDIRTY)
+ tot++;
+
+ if(tot==0) {
+ BKE_report(op->reports, RPT_WARNING, "No images have been changed.");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get a filename for menu */
+ for(ibuf= sima->image->ibufs.first; ibuf; ibuf= ibuf->next)
+ if(ibuf->userflags & IB_BITMAPDIRTY)
+ break;
+
+ BLI_strncpy(di, ibuf->name, FILE_MAX);
+ BLI_splitdirstring(di, fi);
+
+ BKE_reportf(op->reports, RPT_INFO, "%d Image(s) will be saved in %s", tot, di);
+
+ for(ibuf= sima->image->ibufs.first; ibuf; ibuf= ibuf->next) {
+ if(ibuf->userflags & IB_BITMAPDIRTY) {
+ char name[FILE_MAX];
+ BLI_strncpy(name, ibuf->name, sizeof(name));
+
+ BLI_convertstringcode(name, G.sce);
+
+ if(0 == IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat)) {
+ BKE_reportf(op->reports, RPT_ERROR, "Could not write image %s.", name);
+ break;
+ }
+
+ printf("Saved: %s\n", ibuf->name);
+ ibuf->userflags &= ~IB_BITMAPDIRTY;
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_save_sequence(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Save Sequence";
+ ot->idname= "IMAGE_OT_save_sequence";
+
+ /* api callbacks */
+ ot->exec= save_sequence_exec;
+ ot->poll= space_image_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/******************** reload image operator ********************/
+
+static int reload_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima;
+
+ /* retrieve state */
+ sima= (SpaceImage*)CTX_wm_space_data(C);
+
+ if(!sima->image)
+ return OPERATOR_CANCELLED;
+
+ BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_RELOAD);
+ /* ED_space_image_set(C, sima, scene, obedit, NULL); - do we really need this? */
+
+ // XXX BIF_preview_changed(ID_TE);
+ WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, sima->image);
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_reload(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Reload";
+ ot->idname= "IMAGE_OT_reload";
+
+ /* api callbacks */
+ ot->exec= reload_exec;
+ ot->poll= space_image_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************** new image operator *********************/
+
+static int new_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima;
+ Scene *scene;
+ Object *obedit;
+ Image *ima;
+ char name[22];
+ float color[4];
+ int width, height, floatbuf, uvtestgrid;
+
+ /* retrieve state */
+ sima= (SpaceImage*)CTX_wm_space_data(C);
+ scene= (Scene*)CTX_data_scene(C);
+ obedit= CTX_data_edit_object(C);
+
+ RNA_string_get(op->ptr, "name", name);
+ width= RNA_int_get(op->ptr, "width");
+ height= RNA_int_get(op->ptr, "height");
+ floatbuf= RNA_boolean_get(op->ptr, "float");
+ uvtestgrid= RNA_boolean_get(op->ptr, "uv_test_grid");
+ RNA_float_get_array(op->ptr, "color", color);
+ color[3]= RNA_float_get(op->ptr, "alpha");
+
+ ima = BKE_add_image_size(width, height, name, floatbuf, uvtestgrid, color);
+ BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
+ ED_space_image_set(C, sima, scene, obedit, ima);
+
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_new(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "New";
+ ot->idname= "IMAGE_OT_new";
+
+ /* api callbacks */
+ ot->exec= new_exec;
+ ot->invoke= WM_operator_redo;
+ ot->poll= ED_operator_image_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_string(ot->srna, "name", "Untitled", 21, "Name", "Image datablock name.");
+ RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width.", 1, 16384);
+ RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image height.", 1, 16384);
+ RNA_def_float_color(ot->srna, "color", 3, NULL, 0.0f, FLT_MAX, "Color", "Default fill color.", 0.0f, 1.0f);
+ RNA_def_float(ot->srna, "alpha", 1.0f, 0.0f, 1.0f, "Alpha", "Default fill alpha.", 0.0f, 1.0f);
+ RNA_def_boolean(ot->srna, "uv_test_grid", 0, "UV Test Grid", "Fill the image with a grid for UV map testing.");
+ RNA_def_boolean(ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth.");
+}
+
+/********************* pack operator *********************/
+
+static int pack_test(bContext *C, wmOperator *op)
+{
+ Image *ima= CTX_data_edit_image(C);
+ int as_png= RNA_boolean_get(op->ptr, "as_png");
+
+ if(!ima)
+ return 0;
+ if(!as_png && ima->packedfile)
+ return 0;
+
+ if(ima->source==IMA_SRC_SEQUENCE || ima->source==IMA_SRC_MOVIE) {
+ BKE_report(op->reports, RPT_ERROR, "Can't pack movie or image sequence.");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int pack_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Image *ima= ED_space_image(sima);
+ ImBuf *ibuf= ED_space_image_buffer(sima);
+ int as_png= RNA_boolean_get(op->ptr, "as_png");
+
+ if(!pack_test(C, op))
+ return OPERATOR_CANCELLED;
+
+ if(!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) {
+ BKE_report(op->reports, RPT_ERROR, "Can't pack edited image from disk, only as internal PNG.");
+ return OPERATOR_CANCELLED;
+ }
+
+ if(as_png)
+ BKE_image_memorypack(ima);
+ else
+ ima->packedfile= newPackedFile(ima->name);
+
+ return OPERATOR_FINISHED;
+}
+
+static int pack_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ImBuf *ibuf= ED_space_image_buffer(sima);
+ uiMenuItem *head;
+ int as_png= RNA_boolean_get(op->ptr, "as_png");
+
+ if(!pack_test(C, op))
+ return OPERATOR_CANCELLED;
+
+ if(!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) {
+ head= uiPupMenuBegin("OK", ICON_HELP);
+ uiMenuItemBooleanO(head, "Can't pack edited image from disk. Pack as internal PNG?", 0, op->idname, "as_png", 1);
+ uiPupMenuEnd(C, head);
+
+ return OPERATOR_CANCELLED;
+ }
+
+ return pack_exec(C, op);
+}
+
+void IMAGE_OT_pack(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Pack";
+ ot->idname= "IMAGE_OT_pack";
+
+ /* api callbacks */
+ ot->exec= pack_exec;
+ ot->invoke= pack_invoke;
+ ot->poll= space_image_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "as_png", 0, "Pack As PNG", "Pack image as lossless PNG.");
+}
+
+/********************* unpack operator *********************/
+
+static int unpack_exec(bContext *C, wmOperator *op)
+{
+ Image *ima= CTX_data_edit_image(C);
+
+ if(!ima)
+ return OPERATOR_CANCELLED;
+ if(!ima->packedfile)
+ return OPERATOR_CANCELLED;
+
+ if(ima->source==IMA_SRC_SEQUENCE || ima->source==IMA_SRC_MOVIE) {
+ BKE_report(op->reports, RPT_ERROR, "Can't unpack movie or image sequence.");
+ return OPERATOR_CANCELLED;
+ }
+
+ if(G.fileflags & G_AUTOPACK)
+ BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save.");
+
+ unpackImage(ima, PF_ASK);
+
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_unpack(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Unpack";
+ ot->idname= "IMAGE_OT_unpack";
+
+ /* api callbacks */
+ ot->exec= unpack_exec;
+ ot->poll= space_image_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/******************** sample image operator ********************/
+
+typedef struct ImageSampleInfo {
+ ARegionType *art;
+ void *draw_handle;
+ int x, y;
+
+ char col[4];
+ float colf[4];
+ int z;
+ float zf;
+
+ char *colp;
+ float *colfp;
+ int *zp;
+ float *zfp;
+
+ int draw;
+} ImageSampleInfo;
+
+static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ImBuf *ibuf= ED_space_image_buffer(sima);
+ ImageSampleInfo *info= arg_info;
+
+ if(ibuf == NULL)
+ return;
+
+ draw_image_info(ar, ibuf->channels, info->x, info->y, info->colp,
+ info->colfp, info->zp, info->zfp);
+}
+
+static void sample_apply(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+ ImBuf *ibuf= ED_space_image_buffer(sima);
+ ImageSampleInfo *info= op->customdata;
+ float fx, fy;
+ int x, y;
+
+ if(ibuf == NULL)
+ return;
+
+ x= event->x - ar->winrct.xmin;
+ y= event->y - ar->winrct.ymin;
+ UI_view2d_region_to_view(&ar->v2d, x, y, &fx, &fy);
+
+ if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
+ float *fp;
+ char *cp;
+ int x= (int)(fx*ibuf->x), y= (int)(fy*ibuf->y);
+
+ CLAMP(x, 0, ibuf->x-1);
+ CLAMP(y, 0, ibuf->y-1);
+
+ info->x= x;
+ info->y= y;
+ info->draw= 1;
+
+ info->colp= NULL;
+ info->colfp= NULL;
+ info->zp= NULL;
+ info->zfp= NULL;
+
+ if(ibuf->rect) {
+ cp= (char *)(ibuf->rect + y*ibuf->x + x);
+
+ info->col[0]= cp[0];
+ info->col[1]= cp[1];
+ info->col[2]= cp[2];
+ info->col[3]= cp[3];
+ info->colp= info->col;
+
+ info->colf[0]= (float)cp[0]/255.0f;
+ info->colf[1]= (float)cp[1]/255.0f;
+ info->colf[2]= (float)cp[2]/255.0f;
+ info->colf[3]= (float)cp[3]/255.0f;
+ info->colfp= info->colf;
+ }
+ if(ibuf->rect_float) {
+ fp= (ibuf->rect_float + (ibuf->channels)*(y*ibuf->x + x));
+
+ info->colf[0]= fp[0];
+ info->colf[1]= fp[1];
+ info->colf[2]= fp[2];
+ info->colf[3]= fp[4];
+ info->colfp= info->colf;
+ }
+
+ if(ibuf->zbuf) {
+ info->z= ibuf->zbuf[y*ibuf->x + x];
+ info->zp= &info->z;
+ }
+ if(ibuf->zbuf_float) {
+ info->zf= ibuf->zbuf_float[y*ibuf->x + x];
+ info->zfp= &info->zf;
+ }
+
+ if(sima->cumap && ibuf->channels==4) {
+ /* we reuse this callback for set curves point operators */
+ if(RNA_struct_find_property(op->ptr, "point")) {
+ int point= RNA_enum_get(op->ptr, "point");
+
+ if(point == 1) {
+ curvemapping_set_black_white(sima->cumap, NULL, info->colfp);
+ curvemapping_do_ibuf(sima->cumap, ibuf);
+ }
+ else if(point == 0) {
+ curvemapping_set_black_white(sima->cumap, info->colfp, NULL);
+ curvemapping_do_ibuf(sima->cumap, ibuf);
+ }
+ }
+ }
+
+ // XXX node curve integration ..
+#if 0
+ {
+ ScrArea *sa, *cur= curarea;
+
+ node_curvemap_sample(fp); /* sends global to node editor */
+ for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ if(sa->spacetype==SPACE_NODE) {
+ areawinset(sa->win);
+ scrarea_do_windraw(sa);
+ }
+ }
+ node_curvemap_sample(NULL); /* clears global in node editor */
+ curarea= cur;
+ }
+#endif
+ }
+ else
+ info->draw= 0;
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+}
+
+static void sample_exit(bContext *C, wmOperator *op)
+{
+ ImageSampleInfo *info= op->customdata;
+
+ ED_region_draw_cb_exit(info->art, info->draw_handle);
+ ED_area_tag_redraw(CTX_wm_area(C));
+ MEM_freeN(info);
+}
+
+static int sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+ ImBuf *ibuf= ED_space_image_buffer(sima);
+ ImageSampleInfo *info;
+
+ if(ibuf == NULL)
+ return OPERATOR_CANCELLED;
+
+ info= MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo");
+ info->art= ar->type;
+ info->draw_handle = ED_region_draw_cb_activate(ar->type, sample_draw, info, REGION_DRAW_POST);
+ op->customdata= info;
+
+ sample_apply(C, op, event);
+
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int sample_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ switch(event->type) {
+ case LEFTMOUSE:
+ case RIGHTMOUSE: // XXX hardcoded
+ sample_exit(C, op);
+ return OPERATOR_CANCELLED;
+ case MOUSEMOVE:
+ sample_apply(C, op, event);
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int sample_cancel(bContext *C, wmOperator *op)
+{
+ sample_exit(C, op);
+ return OPERATOR_CANCELLED;
+}
+
+void IMAGE_OT_sample(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Sample";
+ ot->idname= "IMAGE_OT_sample";
+
+ /* api callbacks */
+ ot->invoke= sample_invoke;
+ ot->modal= sample_modal;
+ ot->cancel= sample_cancel;
+ ot->poll= space_image_main_area_poll;
+}
+
+/******************** set curve point operator ********************/
+
+void IMAGE_OT_curves_point_set(wmOperatorType *ot)
+{
+ static EnumPropertyItem point_items[]= {
+ {0, "BLACK_POINT", "Black Point", ""},
+ {1, "WHITE_POINT", "White Point", ""},
+ {0, NULL, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "Set Curves Point";
+ ot->idname= "IMAGE_OT_curves_point_set";
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke= sample_invoke;
+ ot->modal= sample_modal;
+ ot->cancel= sample_cancel;
+ ot->poll= space_image_main_area_poll;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "point", point_items, 0, "Point", "Set black point or white point for curves.");
+}
+
+/******************** record composite operator *********************/
+
+typedef struct RecordCompositeData {
+ wmTimer *timer;
+ int old_cfra;
+ int sfra, efra;
+} RecordCompositeData;
+
+int record_composite_apply(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ RecordCompositeData *rcd= op->customdata;
+ Scene *scene= CTX_data_scene(C);
+ ImBuf *ibuf;
+
+ WM_timecursor(CTX_wm_window(C), scene->r.cfra);
+
+ // XXX scene->nodetree->test_break= blender_test_break;
+ // XXX scene->nodetree->test_break= NULL;
+
+ BKE_image_all_free_anim_ibufs(scene->r.cfra);
+ ntreeCompositTagAnimated(scene->nodetree);
+ ntreeCompositExecTree(scene->nodetree, &scene->r, scene->r.cfra != rcd->old_cfra); /* 1 is no previews */
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser);
+ /* save memory in flipbooks */
+ if(ibuf)
+ imb_freerectfloatImBuf(ibuf);
+
+ scene->r.cfra++;
+
+ return (scene->r.cfra <= rcd->efra);
+}
+
+static int record_composite_init(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ RecordCompositeData *rcd;
+
+ if(sima->iuser.frames < 2)
+ return 0;
+ if(scene->nodetree == NULL)
+ return 0;
+
+ op->customdata= rcd= MEM_callocN(sizeof(RecordCompositeData), "ImageRecordCompositeData");
+
+ rcd->old_cfra= scene->r.cfra;
+ rcd->sfra= sima->iuser.sfra;
+ rcd->efra= sima->iuser.sfra + sima->iuser.frames-1;
+ scene->r.cfra= rcd->sfra;
+
+ return 1;
+}
+
+static void record_composite_exit(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ RecordCompositeData *rcd= op->customdata;
+
+ scene->r.cfra= rcd->old_cfra;
+
+ WM_cursor_restore(CTX_wm_window(C));
+
+ if(rcd->timer)
+ WM_event_remove_window_timer(CTX_wm_window(C), rcd->timer);
+
+ WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, sima->image);
+
+ // XXX play_anim(0);
+ // XXX allqueue(REDRAWNODE, 1);
+
+ MEM_freeN(rcd);
+}
+
+static int record_composite_exec(bContext *C, wmOperator *op)
+{
+ if(!record_composite_init(C, op))
+ return OPERATOR_CANCELLED;
+
+ while(record_composite_apply(C, op))
+ ;
+
+ record_composite_exit(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+static int record_composite_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ RecordCompositeData *rcd= op->customdata;
+
+ if(!record_composite_init(C, op))
+ return OPERATOR_CANCELLED;
+
+ rcd= op->customdata;
+ rcd->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.0f);
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ if(!record_composite_apply(C, op))
+ return OPERATOR_FINISHED;
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int record_composite_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ RecordCompositeData *rcd= op->customdata;
+
+ switch(event->type) {
+ case TIMER:
+ if(rcd->timer == event->customdata) {
+ if(!record_composite_apply(C, op)) {
+ record_composite_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ }
+ break;
+ case ESCKEY:
+ record_composite_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int record_composite_cancel(bContext *C, wmOperator *op)
+{
+ record_composite_exit(C, op);
+ return OPERATOR_CANCELLED;
+}
+
+void IMAGE_OT_record_composite(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Record Composite";
+ ot->idname= "IMAGE_OT_record_composite";
+
+ /* api callbacks */
+ ot->exec= record_composite_exec;
+ ot->invoke= record_composite_invoke;
+ ot->modal= record_composite_modal;
+ ot->cancel= record_composite_cancel;
+ ot->poll= space_image_poll;
+}
+
+/******************** TODO ********************/
+
+/* XXX notifier? */
+#if 0
+/* goes over all ImageUsers, and sets frame numbers if auto-refresh is set */
+void BIF_image_update_frame(void)
+{
+ Tex *tex;
+
+ /* texture users */
+ for(tex= G.main->tex.first; tex; tex= tex->id.next) {
+ if(tex->type==TEX_IMAGE && tex->ima)
+ if(ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE))
+ if(tex->iuser.flag & IMA_ANIM_ALWAYS)
+ BKE_image_user_calc_imanr(&tex->iuser, scene->r.cfra, 0);
+
+ }
+ /* image window, compo node users */
+ if(G.curscreen) {
+ ScrArea *sa;
+ for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ if(sa->spacetype==SPACE_VIEW3D) {
+ View3D *v3d= sa->spacedata.first;
+ if(v3d->bgpic)
+ if(v3d->bgpic->iuser.flag & IMA_ANIM_ALWAYS)
+ BKE_image_user_calc_imanr(&v3d->bgpic->iuser, scene->r.cfra, 0);
+ }
+ else if(sa->spacetype==SPACE_IMAGE) {
+ SpaceImage *sima= sa->spacedata.first;
+ if(sima->iuser.flag & IMA_ANIM_ALWAYS)
+ BKE_image_user_calc_imanr(&sima->iuser, scene->r.cfra, 0);
+ }
+ else if(sa->spacetype==SPACE_NODE) {
+ SpaceNode *snode= sa->spacedata.first;
+ if((snode->treetype==NTREE_COMPOSIT) && (snode->nodetree)) {
+ bNode *node;
+ for(node= snode->nodetree->nodes.first; node; node= node->next) {
+ if(node->id && node->type==CMP_NODE_IMAGE) {
+ Image *ima= (Image *)node->id;
+ ImageUser *iuser= node->storage;
+ if(ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE))
+ if(iuser->flag & IMA_ANIM_ALWAYS)
+ BKE_image_user_calc_imanr(iuser, scene->r.cfra, 0);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+#endif
+
diff --git a/source/blender/editors/space_image/image_panels.c b/source/blender/editors/space_image/image_panels.c
new file mode 100644
index 00000000000..971f3a70a8a
--- /dev/null
+++ b/source/blender/editors/space_image/image_panels.c
@@ -0,0 +1,1463 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2002-2009
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_color_types.h"
+#include "DNA_image_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_packedFile_types.h"
+#include "DNA_node_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_image.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_node.h"
+#include "BKE_packedFile.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "RE_pipeline.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "ED_image.h"
+#include "ED_mesh.h"
+#include "ED_space_api.h"
+#include "ED_screen.h"
+#include "ED_uvedit.h"
+#include "ED_util.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "image_intern.h"
+
+#define B_REDR 1
+#define B_IMAGECHANGED 2
+#define B_TRANS_IMAGE 3
+#define B_CURSOR_IMAGE 4
+#define B_NOP 0
+#define B_TWINANIM 5
+#define B_SIMAGETILE 6
+#define B_IDNAME 10
+#define B_FACESEL_PAINT_TEST 11
+#define B_SIMA_RECORD 12
+#define B_SIMA_PLAY 13
+#define B_SIMARANGE 14
+#define B_SIMACURVES 15
+
+#define B_SIMANOTHING 16
+#define B_SIMABRUSHCHANGE 17
+#define B_SIMABRUSHBROWSE 18
+#define B_SIMABRUSHLOCAL 19
+#define B_SIMABRUSHDELETE 20
+#define B_KEEPDATA 21
+#define B_SIMABTEXBROWSE 22
+#define B_SIMABTEXDELETE 23
+#define B_VPCOLSLI 24
+#define B_SIMACLONEBROWSE 25
+#define B_SIMACLONEDELETE 26
+
+/* XXX */
+static int okee() {return 0;}
+static int simaFaceDraw_Check() {return 0;}
+static int simaUVSel_Check() {return 0;}
+static int is_uv_tface_editing_allowed_silent() {return 0;}
+/* XXX */
+
+/* proto */
+static void image_editvertex_buts(const bContext *C, uiBlock *block);
+static void image_editcursor_buts(const bContext *C, View2D *v2d, uiBlock *block);
+
+
+static void do_image_panel_events(bContext *C, void *arg, int event)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+
+ switch(event) {
+ case B_REDR:
+ break;
+ case B_SIMACURVES:
+ curvemapping_do_ibuf(sima->cumap, ED_space_image_buffer(sima));
+ break;
+ case B_SIMARANGE:
+ curvemapping_set_black_white(sima->cumap, NULL, NULL);
+ curvemapping_do_ibuf(sima->cumap, ED_space_image_buffer(sima));
+ break;
+ case B_TRANS_IMAGE:
+ image_editvertex_buts(C, NULL);
+ break;
+ case B_CURSOR_IMAGE:
+ image_editcursor_buts(C, &ar->v2d, NULL);
+ break;
+ }
+ /* all events now */
+ WM_event_add_notifier(C, NC_IMAGE, sima->image);
+}
+
+
+
+static void image_info(Image *ima, ImBuf *ibuf, char *str)
+{
+ int ofs= 0;
+
+ str[0]= 0;
+
+ if(ima==NULL) return;
+ if(ibuf==NULL) {
+ sprintf(str, "Can not get an image");
+ return;
+ }
+
+ if(ima->source==IMA_SRC_MOVIE) {
+ ofs= sprintf(str, "Movie ");
+ if(ima->anim)
+ ofs+= sprintf(str+ofs, "%d frs", IMB_anim_get_duration(ima->anim));
+ }
+ else
+ ofs= sprintf(str, "Image ");
+
+ ofs+= sprintf(str+ofs, ": size %d x %d,", ibuf->x, ibuf->y);
+
+ if(ibuf->rect_float) {
+ if(ibuf->channels!=4) {
+ sprintf(str+ofs, "%d float channel(s)", ibuf->channels);
+ }
+ else if(ibuf->depth==32)
+ strcat(str, " RGBA float");
+ else
+ strcat(str, " RGB float");
+ }
+ else {
+ if(ibuf->depth==32)
+ strcat(str, " RGBA byte");
+ else
+ strcat(str, " RGB byte");
+ }
+ if(ibuf->zbuf || ibuf->zbuf_float)
+ strcat(str, " + Z");
+
+}
+
+/* gets active viewer user */
+struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
+{
+ bNode *node;
+
+ if(ntree)
+ for(node= ntree->nodes.first; node; node= node->next)
+ if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
+ if(node->flag & NODE_DO_OUTPUT)
+ return node->storage;
+ return NULL;
+}
+
+
+/* ************ panel stuff ************* */
+
+/* this function gets the values for cursor and vertex number buttons */
+static void image_transform_but_attr(SpaceImage *sima, int *imx, int *imy, int *step, int *digits) /*, float *xcoord, float *ycoord)*/
+{
+ ImBuf *ibuf= ED_space_image_buffer(sima);
+ if(ibuf) {
+ *imx= ibuf->x;
+ *imy= ibuf->y;
+ }
+
+ if (sima->flag & SI_COORDFLOATS) {
+ *step= 1;
+ *digits= 3;
+ }
+ else {
+ *step= 100;
+ *digits= 2;
+ }
+}
+
+
+/* is used for both read and write... */
+static void image_editvertex_buts(const bContext *C, uiBlock *block)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Object *obedit= CTX_data_edit_object(C);
+ static float ocent[2];
+ float cent[2]= {0.0, 0.0};
+ int imx= 256, imy= 256;
+ int nactive= 0, step, digits;
+ EditMesh *em;
+ EditFace *efa;
+ MTFace *tf;
+
+ if(obedit==NULL || obedit->type!=OB_MESH) return;
+
+ if( is_uv_tface_editing_allowed_silent()==0 ) return;
+
+ image_transform_but_attr(sima, &imx, &imy, &step, &digits);
+
+ em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ for (efa= em->faces.first; efa; efa= efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if (simaFaceDraw_Check(efa, tf)) {
+
+ if (simaUVSel_Check(efa, tf, 0)) {
+ cent[0]+= tf->uv[0][0];
+ cent[1]+= tf->uv[0][1];
+ nactive++;
+ }
+ if (simaUVSel_Check(efa, tf, 1)) {
+ cent[0]+= tf->uv[1][0];
+ cent[1]+= tf->uv[1][1];
+ nactive++;
+ }
+ if (simaUVSel_Check(efa, tf, 2)) {
+ cent[0]+= tf->uv[2][0];
+ cent[1]+= tf->uv[2][1];
+ nactive++;
+ }
+ if (efa->v4 && simaUVSel_Check(efa, tf, 3)) {
+ cent[0]+= tf->uv[3][0];
+ cent[1]+= tf->uv[3][1];
+ nactive++;
+ }
+ }
+ }
+
+ if(block) { // do the buttons
+ if (nactive) {
+ ocent[0]= cent[0]/nactive;
+ ocent[1]= cent[1]/nactive;
+ if (sima->flag & SI_COORDFLOATS) {
+ } else {
+ ocent[0] *= imx;
+ ocent[1] *= imy;
+ }
+
+ //uiBlockBeginAlign(block);
+ if(nactive==1) {
+ uiDefButF(block, NUM, B_TRANS_IMAGE, "Vertex X:", 10, 10, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
+ uiDefButF(block, NUM, B_TRANS_IMAGE, "Vertex Y:", 165, 10, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
+ }
+ else {
+ uiDefButF(block, NUM, B_TRANS_IMAGE, "Median X:", 10, 10, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
+ uiDefButF(block, NUM, B_TRANS_IMAGE, "Median Y:", 165, 10, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
+ }
+ //uiBlockEndAlign(block);
+ }
+ }
+ else { // apply event
+ float delta[2];
+
+ cent[0]= cent[0]/nactive;
+ cent[1]= cent[1]/nactive;
+
+ if (sima->flag & SI_COORDFLOATS) {
+ delta[0]= ocent[0]-cent[0];
+ delta[1]= ocent[1]-cent[1];
+ }
+ else {
+ delta[0]= ocent[0]/imx - cent[0];
+ delta[1]= ocent[1]/imy - cent[1];
+ }
+
+ for (efa= em->faces.first; efa; efa= efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if (simaFaceDraw_Check(efa, tf)) {
+ if (simaUVSel_Check(efa, tf, 0)) {
+ tf->uv[0][0]+= delta[0];
+ tf->uv[0][1]+= delta[1];
+ }
+ if (simaUVSel_Check(efa, tf, 1)) {
+ tf->uv[1][0]+= delta[0];
+ tf->uv[1][1]+= delta[1];
+ }
+ if (simaUVSel_Check(efa, tf, 2)) {
+ tf->uv[2][0]+= delta[0];
+ tf->uv[2][1]+= delta[1];
+ }
+ if (efa->v4 && simaUVSel_Check(efa, tf, 3)) {
+ tf->uv[3][0]+= delta[0];
+ tf->uv[3][1]+= delta[1];
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_IMAGE, sima->image);
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+}
+
+
+/* is used for both read and write... */
+static void image_editcursor_buts(const bContext *C, View2D *v2d, uiBlock *block)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ static float ocent[2];
+ int imx= 256, imy= 256;
+ int step, digits;
+
+ if( is_uv_tface_editing_allowed_silent()==0 ) return;
+
+ image_transform_but_attr(sima, &imx, &imy, &step, &digits);
+
+ if(block) { // do the buttons
+ ocent[0]= v2d->cursor[0];
+ ocent[1]= v2d->cursor[1];
+ if (sima->flag & SI_COORDFLOATS) {
+ } else {
+ ocent[0] *= imx;
+ ocent[1] *= imy;
+ }
+
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_CURSOR_IMAGE, "Cursor X:", 165, 120, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
+ uiDefButF(block, NUM, B_CURSOR_IMAGE, "Cursor Y:", 165, 100, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
+ uiBlockEndAlign(block);
+ }
+ else { // apply event
+ if (sima->flag & SI_COORDFLOATS) {
+ v2d->cursor[0]= ocent[0];
+ v2d->cursor[1]= ocent[1];
+ }
+ else {
+ v2d->cursor[0]= ocent[0]/imx;
+ v2d->cursor[1]= ocent[1]/imy;
+ }
+ WM_event_add_notifier(C, NC_IMAGE, sima->image);
+ }
+}
+
+static void image_panel_game_properties(const bContext *C, ARegion *ar)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ImBuf *ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser);
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "image_panel_game_properties", UI_EMBOSS);
+ if(uiNewPanel(C, ar, block, "Real-time Properties", "Image", 10, 10, 318, 204)==0)
+ return;
+ uiBlockSetHandleFunc(block, do_image_panel_events, NULL);
+
+ if (ibuf) {
+ char str[128];
+
+ image_info(sima->image, ibuf, str);
+ uiDefBut(block, LABEL, B_NOP, str, 10,180,300,19, 0, 0, 0, 0, 0, "");
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, IMA_TWINANIM, B_TWINANIM, "Anim", 10,150,140,19, &sima->image->tpageflag, 0, 0, 0, 0, "Toggles use of animated texture");
+ uiDefButS(block, NUM, B_TWINANIM, "Start:", 10,130,140,19, &sima->image->twsta, 0.0, 128.0, 0, 0, "Displays the start frame of an animated texture");
+ uiDefButS(block, NUM, B_TWINANIM, "End:", 10,110,140,19, &sima->image->twend, 0.0, 128.0, 0, 0, "Displays the end frame of an animated texture");
+ uiDefButS(block, NUM, B_NOP, "Speed", 10,90,140,19, &sima->image->animspeed, 1.0, 100.0, 0, 0, "Displays Speed of the animation in frames per second");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, IMA_TILES, B_SIMAGETILE, "Tiles", 160,150,140,19, &sima->image->tpageflag, 0, 0, 0, 0, "Toggles use of tilemode for faces (Shift LMB to pick the tile for selected faces)");
+ uiDefButS(block, NUM, B_REDR, "X:", 160,130,70,19, &sima->image->xrep, 1.0, 16.0, 0, 0, "Sets the degree of repetition in the X direction");
+ uiDefButS(block, NUM, B_REDR, "Y:", 230,130,70,19, &sima->image->yrep, 1.0, 16.0, 0, 0, "Sets the degree of repetition in the Y direction");
+ uiBlockBeginAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, IMA_CLAMP_U, B_REDR, "ClampX", 160,100,70,19, &sima->image->tpageflag, 0, 0, 0, 0, "Disable texture repeating horizontaly");
+ uiDefButBitS(block, TOG, IMA_CLAMP_V, B_REDR, "ClampY", 230,100,70,19, &sima->image->tpageflag, 0, 0, 0, 0, "Disable texture repeating vertically");
+ uiBlockEndAlign(block);
+ }
+}
+
+static void image_panel_view_properties(const bContext *C, ARegion *ar)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Object *obedit= CTX_data_edit_object(C);
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "image_view_properties", UI_EMBOSS);
+ if(uiNewPanel(C, ar, block, "View Properties", "Image", 10, 30, 318, 204)==0)
+ return;
+ uiBlockSetHandleFunc(block, do_image_panel_events, NULL);
+
+ uiDefButBitI(block, TOG, SI_DRAW_TILE, B_REDR, "Repeat Image", 10,160,140,19, &sima->flag, 0, 0, 0, 0, "Repeat/Tile the image display");
+ uiDefButBitI(block, TOG, SI_COORDFLOATS, B_REDR, "Normalized Coords", 165,160,145,19, &sima->flag, 0, 0, 0, 0, "Display coords from 0.0 to 1.0 rather then in pixels");
+
+ if (sima->image) {
+ uiDefBut(block, LABEL, B_NOP, "Image Display:", 10,140,140,19, 0, 0, 0, 0, 0, "");
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_REDR, "AspX:", 10,120,140,19, &sima->image->aspx, 0.1, 5000.0, 100, 0, "X Display Aspect for this image, does not affect renderingm 0 disables.");
+ uiDefButF(block, NUM, B_REDR, "AspY:", 10,100,140,19, &sima->image->aspy, 0.1, 5000.0, 100, 0, "X Display Aspect for this image, does not affect rendering 0 disables.");
+ uiBlockEndAlign(block);
+ }
+
+ if (obedit && obedit->type==OB_MESH) {
+ Mesh *me= obedit->data;
+ EditMesh *em= BKE_mesh_get_editmesh(me);
+
+ if(EM_texFaceCheck(em)) {
+ uiDefBut(block, LABEL, B_NOP, "Draw Type:", 10, 80,120,19, 0, 0, 0, 0, 0, "");
+ uiBlockBeginAlign(block);
+ uiDefButC(block, ROW, B_REDR, "Outline", 10,60,58,19, &sima->dt_uv, 0.0, SI_UVDT_OUTLINE, 0, 0, "Outline Wire UV drawtype");
+ uiDefButC(block, ROW, B_REDR, "Dash", 68, 60,58,19, &sima->dt_uv, 0.0, SI_UVDT_DASH, 0, 0, "Dashed Wire UV drawtype");
+ uiDefButC(block, ROW, B_REDR, "Black", 126, 60,58,19, &sima->dt_uv, 0.0, SI_UVDT_BLACK, 0, 0, "Black Wire UV drawtype");
+ uiDefButC(block, ROW, B_REDR, "White", 184,60,58,19, &sima->dt_uv, 0.0, SI_UVDT_WHITE, 0, 0, "White Wire UV drawtype");
+
+ uiBlockEndAlign(block);
+ uiDefButBitI(block, TOG, SI_SMOOTH_UV, B_REDR, "Smooth", 250,60,60,19, &sima->flag, 0, 0, 0, 0, "Display smooth lines in the UV view");
+
+
+ uiDefButBitI(block, TOG, ME_DRAWFACES, B_REDR, "Faces", 10,30,60,19, &me->drawflag, 0, 0, 0, 0, "Displays all faces as shades in the 3d view and UV editor");
+ uiDefButBitI(block, TOG, ME_DRAWEDGES, B_REDR, "Edges", 70, 30,60,19, &me->drawflag, 0, 0, 0, 0, "Displays selected edges using hilights in the 3d view and UV editor");
+
+ uiDefButBitI(block, TOG, SI_DRAWSHADOW, B_REDR, "Final Shadow", 130, 30,110,19, &sima->flag, 0, 0, 0, 0, "Draw the final result from the objects modifiers");
+ uiDefButBitI(block, TOG, SI_DRAW_OTHER, B_REDR, "Other Objs", 230, 30, 80, 19, &sima->flag, 0, 0, 0, 0, "Also draw all 3d view selected mesh objects that use this image");
+
+ uiDefButBitI(block, TOG, SI_DRAW_STRETCH, B_REDR, "UV Stretch", 10,0,100,19, &sima->flag, 0, 0, 0, 0, "Difference between UV's and the 3D coords (blue for low distortion, red is high)");
+ if (sima->flag & SI_DRAW_STRETCH) {
+ uiBlockBeginAlign(block);
+ uiDefButC(block, ROW, B_REDR, "Area", 120,0,60,19, &sima->dt_uvstretch, 0.0, SI_UVDT_STRETCH_AREA, 0, 0, "Area distortion between UV's and 3D coords");
+ uiDefButC(block, ROW, B_REDR, "Angle", 180,0,60,19, &sima->dt_uvstretch, 0.0, SI_UVDT_STRETCH_ANGLE, 0, 0, "Angle distortion between UV's and 3D coords");
+ uiBlockEndAlign(block);
+ }
+ }
+
+ BKE_mesh_end_editmesh(me, em);
+ }
+ image_editcursor_buts(C, &ar->v2d, block);
+}
+
+void brush_buttons(const bContext *C, uiBlock *block, short fromsima,
+ int evt_nop, int evt_change,
+ int evt_browse, int evt_local,
+ int evt_del, int evt_keepdata,
+ int evt_texbrowse, int evt_texdel)
+{
+// SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ToolSettings *settings= CTX_data_tool_settings(C);
+ Brush *brush= settings->imapaint.brush;
+ ID *id;
+ int yco, xco, butw, but_idx;
+// short *menupoin = &(sima->menunr); // XXX : &(G.buts->menunr);
+ short do_project = settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE ? 0:1;
+
+ yco= 160;
+
+ butw = fromsima ? 80 : 106;
+
+ uiBlockBeginAlign(block);
+ but_idx = 0;
+ uiDefButS(block, ROW, evt_change, "Draw", butw*(but_idx++),yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_DRAW, 0, 0, "Draw brush");
+ if (fromsima || do_project==0)
+ uiDefButS(block, ROW, evt_change, "Soften", butw*(but_idx++), yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SOFTEN, 0, 0, "Soften brush");
+ uiDefButS(block, ROW, evt_change, "Smear", butw*(but_idx++), yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SMEAR, 0, 0, "Smear brush");
+ if (fromsima || do_project)
+ uiDefButS(block, ROW, evt_change, "Clone", butw*(but_idx++), yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_CLONE, 0, 0, "Clone brush, use RMB to drag source image");
+
+ uiBlockEndAlign(block);
+ yco -= 30;
+
+ id= (ID*)settings->imapaint.brush;
+ xco= 200; // std_libbuttons(block, 0, yco, 0, NULL, evt_browse, ID_BR, 0, id, NULL, menupoin, 0, evt_local, evt_del, 0, evt_keepdata);
+
+ if(brush && !brush->id.lib) {
+
+ butw= 320-(xco+10);
+
+ uiDefButS(block, MENU, evt_nop, "Mix %x0|Add %x1|Subtract %x2|Multiply %x3|Lighten %x4|Darken %x5|Erase Alpha %x6|Add Alpha %x7", xco+10,yco,butw,19, &brush->blend, 0, 0, 0, 0, "Blending method for applying brushes");
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG|BIT, BRUSH_AIRBRUSH, evt_change, "Airbrush", xco+10,yco-25,butw/2,19, &brush->flag, 0, 0, 0, 0, "Keep applying paint effect while holding mouse (spray)");
+ uiDefButF(block, NUM, evt_nop, "", xco+10 + butw/2,yco-25,butw/2,19, &brush->rate, 0.01, 1.0, 0, 0, "Number of paints per second for Airbrush");
+ uiBlockEndAlign(block);
+
+ if (fromsima) {
+ uiDefButBitS(block, TOG|BIT, BRUSH_TORUS, evt_change, "Wrap", xco+10,yco-45,butw,19, &brush->flag, 0, 0, 0, 0, "Enables torus wrapping");
+ yco -= 25;
+ }
+ else {
+ yco -= 25;
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_DISABLE, B_REDR, "Project Paint", xco+10,yco-25,butw,19, &settings->imapaint.flag, 0, 0, 0, 0, "Use projection painting for improved consistency in the brush strokes");
+
+ if ((settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)==0) {
+ /* Projection Painting */
+
+ uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_XRAY, B_NOP, "Occlude", xco+10,yco-45,butw/2,19, &settings->imapaint.flag, 0, 0, 0, 0, "Only paint onto the faces directly under the brush (slower)");
+ uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_BACKFACE, B_NOP, "Cull", xco+10+butw/2,yco-45,butw/2,19, &settings->imapaint.flag, 0, 0, 0, 0, "Ignore faces pointing away from the view (faster)");
+
+ uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_FLAT, B_NOP, "Normal", xco+10,yco-65,butw/2,19, &settings->imapaint.flag, 0, 0, 0, 0, "Paint most on faces pointing towards the view");
+ uiDefButS(block, NUM, B_NOP, "", xco+10 +(butw/2),yco-65,butw/2,19, &settings->imapaint.normal_angle, 10.0, 90.0, 0, 0, "Paint most on faces pointing towards the view acording to this angle");
+
+ uiDefButS(block, NUM, B_NOP, "Bleed: ", xco+10,yco-85,butw,19, &settings->imapaint.seam_bleed, 0.0, 8.0, 0, 0, "Extend paint beyond the faces UVs to reduce seams (in pixels, slower)");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG|BIT, IMAGEPAINT_PROJECT_LAYER_MASK, B_NOP, "Stencil Layer", xco+10,yco-110,butw-30,19, &settings->imapaint.flag, 0, 0, 0, 0, "Set the mask layer from the UV layer buttons");
+ uiDefButBitS(block, TOG|BIT, IMAGEPAINT_PROJECT_LAYER_MASK_INV, B_NOP, "Inv", xco+10 + butw-30,yco-110,30,19, &settings->imapaint.flag, 0, 0, 0, 0, "Invert the mask");
+ uiBlockEndAlign(block);
+
+ }
+ uiBlockEndAlign(block);
+ }
+
+ uiBlockBeginAlign(block);
+ uiDefButF(block, COL, B_VPCOLSLI, "", 0,yco,200,19, brush->rgb, 0, 0, 0, 0, "");
+ uiDefButF(block, NUMSLI, evt_nop, "Opacity ", 0,yco-20,180,19, &brush->alpha, 0.0, 1.0, 0, 0, "The amount of pressure on the brush");
+ uiDefButBitS(block, TOG|BIT, BRUSH_ALPHA_PRESSURE, evt_nop, "P", 180,yco-20,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets");
+ uiDefButI(block, NUMSLI, evt_nop, "Size ", 0,yco-40,180,19, &brush->size, 1, 200, 0, 0, "The size of the brush");
+ uiDefButBitS(block, TOG|BIT, BRUSH_SIZE_PRESSURE, evt_nop, "P", 180,yco-40,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets");
+ uiDefButF(block, NUMSLI, evt_nop, "Falloff ", 0,yco-60,180,19, &brush->innerradius, 0.0, 1.0, 0, 0, "The fall off radius of the brush");
+ uiDefButBitS(block, TOG|BIT, BRUSH_RAD_PRESSURE, evt_nop, "P", 180,yco-60,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets");
+ uiDefButF(block, NUMSLI, evt_nop, "Spacing ",0,yco-80,180,19, &brush->spacing, 1.0, 100.0, 0, 0, "Repeating paint on %% of brush diameter");
+ uiDefButBitS(block, TOG|BIT, BRUSH_SPACING_PRESSURE, evt_nop, "P", 180,yco-80,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets");
+ uiBlockEndAlign(block);
+
+ yco -= 110;
+
+ if(fromsima && settings->imapaint.tool == PAINT_TOOL_CLONE) {
+ id= (ID*)brush->clone.image;
+ xco= 200; // std_libbuttons(block, 0, yco, 0, NULL, B_SIMACLONEBROWSE, ID_IM, 0, id, 0, menupoin, 0, 0, B_SIMACLONEDELETE, 0, 0);
+ if(id) {
+ butw= 320-(xco+5);
+ uiDefButF(block, NUMSLI, evt_change, "B ",xco+5,yco,butw,19, &brush->clone.alpha , 0.0, 1.0, 0, 0, "Opacity of clone image display");
+ }
+ }
+ else {
+ if (
+ (fromsima==0) && /* 3D View */
+ (settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)==0 && /* Projection Painting */
+ (settings->imapaint.tool == PAINT_TOOL_CLONE)
+ ) {
+ butw = 130;
+ uiDefButBitS(block, TOG|BIT, IMAGEPAINT_PROJECT_LAYER_CLONE, B_REDR, "Clone Layer", 0,yco,butw,20, &settings->imapaint.flag, 0, 0, 0, 0, "Use another UV layer as clone source, otherwise use 3D the cursor as the source");
+ }
+ else {
+ MTex *mtex= brush->mtex[brush->texact];
+
+ id= (mtex)? (ID*)mtex->tex: NULL;
+ xco= 200; // std_libbuttons(block, 0, yco, 0, NULL, evt_texbrowse, ID_TE, 0, id, NULL, menupoin, 0, 0, evt_texdel, 0, 0);
+ /*uiDefButBitS(block, TOG|BIT, BRUSH_FIXED_TEX, evt_change, "Fixed", xco+5,yco,butw,19, &brush->flag, 0, 0, 0, 0, "Keep texture origin in fixed position");*/
+ }
+ }
+ }
+
+#if 0
+ uiDefButBitS(block, TOG|BIT, IMAGEPAINT_DRAW_TOOL_DRAWING, B_SIMABRUSHCHANGE, "TD", 0,1,50,19, &settings->imapaint.flag.flag, 0, 0, 0, 0, "Enables brush shape while drawing");
+ uiDefButBitS(block, TOG|BIT, IMAGEPAINT_DRAW_TOOL, B_SIMABRUSHCHANGE, "TP", 50,1,50,19, &settings->imapaint.flag.flag, 0, 0, 0, 0, "Enables brush shape while not drawing");
+#endif
+}
+
+static void image_panel_paintcolor(const bContext *C, ARegion *ar)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ToolSettings *settings= CTX_data_tool_settings(C);
+ Brush *brush= settings->imapaint.brush;
+ uiBlock *block;
+ static float hsv[3], old[3]; // used as temp mem for picker
+ static char hexcol[128];
+
+ block= uiBeginBlock(C, ar, "image_panel_paintcolor", UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_image_panel_events, NULL);
+ if(uiNewPanel(C, ar, block, "Paint Color", "Image", 10, 22, 318, 204)==0)
+ return;
+
+ if ( (brush && sima->image && (sima->flag & SI_DRAWTOOL))==0) {
+ uiNewPanelHeight(block, 0);
+ return;
+ }
+ uiNewPanelHeight(block, 204);
+
+ uiBlockPickerButtons(block, brush->rgb, hsv, old, hexcol, 'f', B_REDR);
+}
+
+
+
+static void image_panel_paint(const bContext *C, ARegion *ar)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "image_panel_paint", UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_image_panel_events, NULL);
+ if(uiNewPanel(C, ar, block, "Image Paint", "Image", 10, 20, 318, 204)==0)
+ return;
+
+ if ((sima->image && (sima->flag & SI_DRAWTOOL))==0) {
+ uiNewPanelHeight(block, 0);
+ return;
+ }
+ uiNewPanelHeight(block, 204);
+
+ brush_buttons(C, block, 1, B_SIMANOTHING, B_SIMABRUSHCHANGE, B_SIMABRUSHBROWSE, B_SIMABRUSHLOCAL, B_SIMABRUSHDELETE, B_KEEPDATA, B_SIMABTEXBROWSE, B_SIMABTEXDELETE);
+}
+
+static void image_panel_curves_reset(bContext *C, void *cumap_v, void *ibuf_v)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ CurveMapping *cumap = cumap_v;
+ int a;
+
+ for(a=0; a<CM_TOT; a++)
+ curvemap_reset(cumap->cm+a, &cumap->clipr);
+
+ cumap->black[0]=cumap->black[1]=cumap->black[2]= 0.0f;
+ cumap->white[0]=cumap->white[1]=cumap->white[2]= 1.0f;
+ curvemapping_set_black_white(cumap, NULL, NULL);
+
+ curvemapping_changed(cumap, 0);
+ curvemapping_do_ibuf(cumap, ibuf_v);
+
+ WM_event_add_notifier(C, NC_IMAGE, sima->image);
+}
+
+
+static void image_panel_curves(const bContext *C, ARegion *ar)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ ImBuf *ibuf;
+ uiBlock *block;
+ uiBut *bt;
+
+ /* and we check for spare */
+ ibuf= ED_space_image_buffer(sima);
+
+ block= uiBeginBlock(C, ar, "image_panel_curves", UI_EMBOSS);
+ if(uiNewPanel(C, ar, block, "Curves", "Image", 10, 40, 318, 204)==0)
+ return;
+ uiBlockSetHandleFunc(block, do_image_panel_events, NULL);
+
+ if (ibuf) {
+ rctf rect;
+
+ if(sima->cumap==NULL)
+ sima->cumap= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
+
+ rect.xmin= 110; rect.xmax= 310;
+ rect.ymin= 10; rect.ymax= 200;
+ curvemap_buttons(block, sima->cumap, 'c', B_SIMACURVES, B_REDR, &rect);
+
+ /* curvemap min/max only works for RGBA */
+ if(ibuf->channels==4) {
+ bt=uiDefBut(block, BUT, B_SIMARANGE, "Reset", 10, 160, 90, 19, NULL, 0.0f, 0.0f, 0, 0, "Reset Black/White point and curves");
+ uiButSetFunc(bt, image_panel_curves_reset, sima->cumap, ibuf);
+
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_SIMARANGE, "Min R:", 10, 120, 90, 19, sima->cumap->black, -1000.0f, 1000.0f, 10, 2, "Black level");
+ uiDefButF(block, NUM, B_SIMARANGE, "Min G:", 10, 100, 90, 19, sima->cumap->black+1, -1000.0f, 1000.0f, 10, 2, "Black level");
+ uiDefButF(block, NUM, B_SIMARANGE, "Min B:", 10, 80, 90, 19, sima->cumap->black+2, -1000.0f, 1000.0f, 10, 2, "Black level");
+
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_SIMARANGE, "Max R:", 10, 50, 90, 19, sima->cumap->white, -1000.0f, 1000.0f, 10, 2, "White level");
+ uiDefButF(block, NUM, B_SIMARANGE, "Max G:", 10, 30, 90, 19, sima->cumap->white+1, -1000.0f, 1000.0f, 10, 2, "White level");
+ uiDefButF(block, NUM, B_SIMARANGE, "Max B:", 10, 10, 90, 19, sima->cumap->white+2, -1000.0f, 1000.0f, 10, 2, "White level");
+ }
+ }
+}
+
+#if 0
+/* 0: disable preview
+ otherwise refresh preview
+*/
+void image_preview_event(int event)
+{
+ int exec= 0;
+
+ if(event==0) {
+ G.scene->r.scemode &= ~R_COMP_CROP;
+ exec= 1;
+ }
+ else {
+ if(image_preview_active(curarea, NULL, NULL)) {
+ G.scene->r.scemode |= R_COMP_CROP;
+ exec= 1;
+ }
+ else
+ G.scene->r.scemode &= ~R_COMP_CROP;
+ }
+
+ if(exec && G.scene->nodetree) {
+ /* should work when no node editor in screen..., so we execute right away */
+
+ ntreeCompositTagGenerators(G.scene->nodetree);
+
+ G.afbreek= 0;
+ G.scene->nodetree->timecursor= set_timecursor;
+ G.scene->nodetree->test_break= blender_test_break;
+
+ BIF_store_spare();
+
+ ntreeCompositExecTree(G.scene->nodetree, &G.scene->r, 1); /* 1 is do_previews */
+
+ G.scene->nodetree->timecursor= NULL;
+ G.scene->nodetree->test_break= NULL;
+
+ scrarea_do_windraw(curarea);
+ waitcursor(0);
+
+ WM_event_add_notifier(C, NC_IMAGE, ima_v);
+ }
+}
+
+
+/* nothing drawn here, we use it to store values */
+static void preview_cb(struct ScrArea *sa, struct uiBlock *block)
+{
+ SpaceImage *sima= sa->spacedata.first;
+ rctf dispf;
+ rcti *disprect= &G.scene->r.disprect;
+ int winx= (G.scene->r.size*G.scene->r.xsch)/100;
+ int winy= (G.scene->r.size*G.scene->r.ysch)/100;
+ short mval[2];
+
+ if(G.scene->r.mode & R_BORDER) {
+ winx*= (G.scene->r.border.xmax - G.scene->r.border.xmin);
+ winy*= (G.scene->r.border.ymax - G.scene->r.border.ymin);
+ }
+
+ /* while dragging we need to update the rects, otherwise it doesn't end with correct one */
+
+ BLI_init_rctf(&dispf, 15.0f, (block->maxx - block->minx)-15.0f, 15.0f, (block->maxy - block->miny)-15.0f);
+ ui_graphics_to_window_rct(sa->win, &dispf, disprect);
+
+ /* correction for gla draw */
+ BLI_translate_rcti(disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
+
+ calc_image_view(sima, 'p');
+// printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
+ /* map to image space coordinates */
+ mval[0]= disprect->xmin; mval[1]= disprect->ymin;
+ areamouseco_to_ipoco(v2d, mval, &dispf.xmin, &dispf.ymin);
+ mval[0]= disprect->xmax; mval[1]= disprect->ymax;
+ areamouseco_to_ipoco(v2d, mval, &dispf.xmax, &dispf.ymax);
+
+ /* map to render coordinates */
+ disprect->xmin= dispf.xmin;
+ disprect->xmax= dispf.xmax;
+ disprect->ymin= dispf.ymin;
+ disprect->ymax= dispf.ymax;
+
+ CLAMP(disprect->xmin, 0, winx);
+ CLAMP(disprect->xmax, 0, winx);
+ CLAMP(disprect->ymin, 0, winy);
+ CLAMP(disprect->ymax, 0, winy);
+// printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
+
+}
+
+static int is_preview_allowed(ScrArea *cur)
+{
+ SpaceImage *sima= cur->spacedata.first;
+ ScrArea *sa;
+
+ /* check if another areawindow has preview set */
+ for(sa=G.curscreen->areabase.first; sa; sa= sa->next) {
+ if(sa!=cur && sa->spacetype==SPACE_IMAGE) {
+ if(image_preview_active(sa, NULL, NULL))
+ return 0;
+ }
+ }
+ /* check image type */
+ if(sima->image==NULL || sima->image->type!=IMA_TYPE_COMPOSITE)
+ return 0;
+
+ return 1;
+}
+
+
+static void image_panel_preview(ScrArea *sa, short cntrl) // IMAGE_HANDLER_PREVIEW
+{
+ uiBlock *block;
+ SpaceImage *sima= sa->spacedata.first;
+ int ofsx, ofsy;
+
+ if(is_preview_allowed(sa)==0) {
+ rem_blockhandler(sa, IMAGE_HANDLER_PREVIEW);
+ G.scene->r.scemode &= ~R_COMP_CROP; /* quite weak */
+ return;
+ }
+
+ block= uiBeginBlock(C, ar, "image_panel_preview", UI_EMBOSS);
+ uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
+ uiSetPanelHandler(IMAGE_HANDLER_PREVIEW); // for close and esc
+
+ ofsx= -150+(sa->winx/2)/sima->blockscale;
+ ofsy= -100+(sa->winy/2)/sima->blockscale;
+ if(uiNewPanel(C, ar, block, "Preview", "Image", ofsx, ofsy, 300, 200)==0) return;
+
+ uiBlockSetDrawExtraFunc(block, preview_cb);
+
+}
+
+static void image_panel_gpencil(short cntrl) // IMAGE_HANDLER_GREASEPENCIL
+{
+ uiBlock *block;
+ SpaceImage *sima;
+
+ sima= curarea->spacedata.first;
+
+ block= uiBeginBlock(C, ar, "image_panel_gpencil", UI_EMBOSS);
+ uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
+ uiSetPanelHandler(IMAGE_HANDLER_GREASEPENCIL); // for close and esc
+ if (uiNewPanel(C, ar, block, "Grease Pencil", "SpaceImage", 100, 30, 318, 204)==0) return;
+
+ /* allocate memory for gpd if drawing enabled (this must be done first or else we crash) */
+ if (sima->flag & SI_DISPGP) {
+ if (sima->gpd == NULL)
+ gpencil_data_setactive(curarea, gpencil_data_addnew());
+ }
+
+ if (sima->flag & SI_DISPGP) {
+ bGPdata *gpd= sima->gpd;
+ short newheight;
+
+ /* this is a variable height panel, newpanel doesnt force new size on existing panels */
+ /* so first we make it default height */
+ uiNewPanelHeight(block, 204);
+
+ /* draw button for showing gpencil settings and drawings */
+ uiDefButBitI(block, TOG, SI_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sima->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Image/UV Editor (draw using Shift-LMB)");
+
+ /* extend the panel if the contents won't fit */
+ newheight= draw_gpencil_panel(block, gpd, curarea);
+ uiNewPanelHeight(block, newheight);
+ }
+ else {
+ uiDefButBitI(block, TOG, SI_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sima->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Image/UV Editor");
+ uiDefBut(block, LABEL, 1, " ", 160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
+ }
+}
+#endif
+
+
+/* ********************* callbacks for standard image buttons *************** */
+
+/* called from fileselect or button */
+static void load_image_cb(bContext *C, char *str, void *ima_pp_v, void *iuser_v)
+{
+ Image **ima_pp= (Image **)ima_pp_v;
+ Image *ima= NULL;
+
+ ima= BKE_add_image_file(str, 0);
+ if(ima) {
+ if(*ima_pp) {
+ (*ima_pp)->id.us--;
+ }
+ *ima_pp= ima;
+
+ BKE_image_signal(ima, iuser_v, IMA_SIGNAL_RELOAD);
+ WM_event_add_notifier(C, NC_IMAGE, ima);
+
+ /* button event gets lost when it goes via filewindow */
+// if(G.buts && G.buts->lockpoin) {
+// Tex *tex= G.buts->lockpoin;
+// if(GS(tex->id.name)==ID_TE) {
+// BIF_preview_changed(ID_TE);
+// allqueue(REDRAWBUTSSHADING, 0);
+// allqueue(REDRAWVIEW3D, 0);
+// allqueue(REDRAWOOPS, 0);
+// }
+// }
+ }
+
+ ED_undo_push(C, "Load image");
+}
+
+static char *layer_menu(RenderResult *rr, short *curlay)
+{
+ RenderLayer *rl;
+ int len= 64 + 32*BLI_countlist(&rr->layers);
+ short a, nr= 0;
+ char *str= MEM_callocN(len, "menu layers");
+
+ strcpy(str, "Layer %t");
+ a= strlen(str);
+
+ /* compo result */
+ if(rr->rectf) {
+ a+= sprintf(str+a, "|Composite %%x0");
+ nr= 1;
+ }
+ for(rl= rr->layers.first; rl; rl= rl->next, nr++) {
+ a+= sprintf(str+a, "|%s %%x%d", rl->name, nr);
+ }
+
+ /* no curlay clip here, on render (redraws) the amount of layers can be 1 fir single-layer render */
+
+ return str;
+}
+
+/* rl==NULL means composite result */
+static char *pass_menu(RenderLayer *rl, short *curpass)
+{
+ RenderPass *rpass;
+ int len= 64 + 32*(rl?BLI_countlist(&rl->passes):1);
+ short a, nr= 0;
+ char *str= MEM_callocN(len, "menu layers");
+
+ strcpy(str, "Pass %t");
+ a= strlen(str);
+
+ /* rendered results don't have a Combined pass */
+ if(rl==NULL || rl->rectf) {
+ a+= sprintf(str+a, "|Combined %%x0");
+ nr= 1;
+ }
+
+ if(rl)
+ for(rpass= rl->passes.first; rpass; rpass= rpass->next, nr++)
+ a+= sprintf(str+a, "|%s %%x%d", rpass->name, nr);
+
+ if(*curpass >= nr)
+ *curpass= 0;
+
+ return str;
+}
+
+static void set_frames_cb(bContext *C, void *ima_v, void *iuser_v)
+{
+ Scene *scene= CTX_data_scene(C);
+ Image *ima= ima_v;
+ ImageUser *iuser= iuser_v;
+
+ if(ima->anim) {
+ iuser->frames = IMB_anim_get_duration(ima->anim);
+ BKE_image_user_calc_imanr(iuser, scene->r.cfra, 0);
+ }
+}
+
+static void image_src_change_cb(bContext *C, void *ima_v, void *iuser_v)
+{
+ BKE_image_signal(ima_v, iuser_v, IMA_SIGNAL_SRC_CHANGE);
+}
+
+/* buttons have 2 arg callbacks, filewindow has 3 args... so thats why the wrapper below */
+static void image_browse_cb1(bContext *C, void *ima_pp_v, void *iuser_v)
+{
+ Image **ima_pp= (Image **)ima_pp_v;
+ ImageUser *iuser= iuser_v;
+
+ if(ima_pp) {
+ Image *ima= *ima_pp;
+
+ if(iuser->menunr== -2) {
+ // XXX activate_databrowse_args(&ima->id, ID_IM, 0, &iuser->menunr, image_browse_cb1, ima_pp, iuser);
+ }
+ else if (iuser->menunr>0) {
+ Image *newima= (Image*) BLI_findlink(&CTX_data_main(C)->image, iuser->menunr-1);
+
+ if (newima && newima!=ima) {
+ *ima_pp= newima;
+ id_us_plus(&newima->id);
+ if(ima) ima->id.us--;
+
+ BKE_image_signal(newima, iuser, IMA_SIGNAL_USER_NEW_IMAGE);
+
+ ED_undo_push(C, "Browse image");
+ }
+ }
+ }
+}
+
+static void image_browse_cb(bContext *C, void *ima_pp_v, void *iuser_v)
+{
+ image_browse_cb1(C, ima_pp_v, iuser_v);
+}
+
+static void image_reload_cb(bContext *C, void *ima_v, void *iuser_v)
+{
+ if(ima_v) {
+ BKE_image_signal(ima_v, iuser_v, IMA_SIGNAL_RELOAD);
+ }
+}
+
+static void image_field_test(bContext *C, void *ima_v, void *iuser_v)
+{
+ Image *ima= ima_v;
+
+ if(ima) {
+ ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser_v);
+ if(ibuf) {
+ short nr= 0;
+ if( !(ima->flag & IMA_FIELDS) && (ibuf->flags & IB_fields) ) nr= 1;
+ if( (ima->flag & IMA_FIELDS) && !(ibuf->flags & IB_fields) ) nr= 1;
+ if(nr) {
+ BKE_image_signal(ima, iuser_v, IMA_SIGNAL_FREE);
+ }
+ }
+ }
+}
+
+static void image_unlink_cb(bContext *C, void *ima_pp_v, void *unused)
+{
+ Image **ima_pp= (Image **)ima_pp_v;
+
+ if(ima_pp && *ima_pp) {
+ Image *ima= *ima_pp;
+ /* (for time being, texturefaces are no users, conflict in design...) */
+ if(ima->id.us>1)
+ ima->id.us--;
+ *ima_pp= NULL;
+ }
+}
+
+static void image_load_fs_cb(bContext *C, void *ima_pp_v, void *iuser_v)
+{
+ ScrArea *sa= CTX_wm_area(C);
+// Image **ima_pp= (Image **)ima_pp_v;
+
+ if(sa->spacetype==SPACE_IMAGE)
+ WM_operator_name_call(C, "IMAGE_OT_open", WM_OP_INVOKE_REGION_WIN, NULL);
+ else
+ printf("not supported yet\n");
+}
+
+/* 5 layer button callbacks... */
+static void image_multi_cb(bContext *C, void *rr_v, void *iuser_v)
+{
+ BKE_image_multilayer_index(rr_v, iuser_v);
+}
+static void image_multi_inclay_cb(bContext *C, void *rr_v, void *iuser_v)
+{
+ RenderResult *rr= rr_v;
+ ImageUser *iuser= iuser_v;
+ int tot= BLI_countlist(&rr->layers) + (rr->rectf?1:0); /* fake compo result layer */
+ if(iuser->layer<tot-1)
+ iuser->layer++;
+ BKE_image_multilayer_index(rr, iuser);
+}
+static void image_multi_declay_cb(bContext *C, void *rr_v, void *iuser_v)
+{
+ ImageUser *iuser= iuser_v;
+ if(iuser->layer>0)
+ iuser->layer--;
+ BKE_image_multilayer_index(rr_v, iuser);
+}
+static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v)
+{
+ RenderResult *rr= rr_v;
+ ImageUser *iuser= iuser_v;
+ RenderLayer *rl= BLI_findlink(&rr->layers, iuser->layer);
+ if(rl) {
+ int tot= BLI_countlist(&rl->passes) + (rl->rectf?1:0); /* builtin render result has no combined pass in list */
+ if(iuser->pass<tot-1) {
+ iuser->pass++;
+ BKE_image_multilayer_index(rr, iuser);
+ }
+ }
+}
+static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v)
+{
+ ImageUser *iuser= iuser_v;
+ if(iuser->pass>0) {
+ iuser->pass--;
+ BKE_image_multilayer_index(rr_v, iuser);
+ }
+}
+
+static void image_pack_cb(bContext *C, void *ima_v, void *iuser_v)
+{
+ if(ima_v) {
+ Image *ima= ima_v;
+ if(ima->source!=IMA_SRC_SEQUENCE && ima->source!=IMA_SRC_MOVIE) {
+ 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);
+ ED_undo_push(C, "Unpack image");
+ }
+ }
+ else {
+ ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser_v);
+ if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
+ // XXX error("Can't pack painted image. Save image or use Repack as PNG.");
+ } else {
+ ima->packedfile = newPackedFile(ima->name);
+ ED_undo_push(C, "Pack image");
+ }
+ }
+ }
+ }
+}
+
+static void image_load_cb(bContext *C, void *ima_pp_v, void *iuser_v)
+{
+ if(ima_pp_v) {
+ Image *ima= *((Image **)ima_pp_v);
+ ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser_v);
+ char str[FILE_MAX];
+
+ /* name in ima has been changed by button! */
+ BLI_strncpy(str, ima->name, FILE_MAX);
+ if(ibuf) BLI_strncpy(ima->name, ibuf->name, FILE_MAX);
+
+ load_image_cb(C, str, ima_pp_v, iuser_v);
+ }
+}
+
+static void image_freecache_cb(bContext *C, void *ima_v, void *unused)
+{
+ Scene *scene= CTX_data_scene(C);
+ BKE_image_free_anim_ibufs(ima_v, scene->r.cfra);
+ WM_event_add_notifier(C, NC_IMAGE, ima_v);
+}
+
+static void image_generated_change_cb(bContext *C, void *ima_v, void *iuser_v)
+{
+ BKE_image_signal(ima_v, iuser_v, IMA_SIGNAL_FREE);
+}
+
+static void image_user_change(bContext *C, void *iuser_v, void *unused)
+{
+ Scene *scene= CTX_data_scene(C);
+ BKE_image_user_calc_imanr(iuser_v, scene->r.cfra, 0);
+}
+
+static void uiblock_layer_pass_buttons(uiBlock *block, RenderResult *rr, ImageUser *iuser, int event, int x, int y, int w)
+{
+ uiBut *but;
+ RenderLayer *rl= NULL;
+ int wmenu1, wmenu2;
+ char *strp;
+
+ /* layer menu is 1/3 larger than pass */
+ wmenu1= (3*w)/5;
+ wmenu2= (2*w)/5;
+
+ /* menu buts */
+ strp= layer_menu(rr, &iuser->layer);
+ but= uiDefButS(block, MENU, event, strp, x, y, wmenu1, 20, &iuser->layer, 0,0,0,0, "Select Layer");
+ uiButSetFunc(but, image_multi_cb, rr, iuser);
+ MEM_freeN(strp);
+
+ rl= BLI_findlink(&rr->layers, iuser->layer - (rr->rectf?1:0)); /* fake compo layer, return NULL is meant to be */
+ strp= pass_menu(rl, &iuser->pass);
+ but= uiDefButS(block, MENU, event, strp, x+wmenu1, y, wmenu2, 20, &iuser->pass, 0,0,0,0, "Select Pass");
+ uiButSetFunc(but, image_multi_cb, rr, iuser);
+ MEM_freeN(strp);
+}
+
+static void uiblock_layer_pass_arrow_buttons(uiBlock *block, RenderResult *rr, ImageUser *iuser, int imagechanged)
+{
+ uiBut *but;
+
+ if(rr==NULL || iuser==NULL)
+ return;
+ if(rr->layers.first==NULL) {
+ uiDefBut(block, LABEL, 0, "No Layers in Render Result,", 10, 107, 300, 20, NULL, 1, 0, 0, 0, "");
+ return;
+ }
+
+ uiBlockBeginAlign(block);
+
+ /* decrease, increase arrows */
+ but= uiDefIconBut(block, BUT, imagechanged, ICON_TRIA_LEFT, 10,107,17,20, NULL, 0, 0, 0, 0, "Previous Layer");
+ uiButSetFunc(but, image_multi_declay_cb, rr, iuser);
+ but= uiDefIconBut(block, BUT, imagechanged, ICON_TRIA_RIGHT, 27,107,18,20, NULL, 0, 0, 0, 0, "Next Layer");
+ uiButSetFunc(but, image_multi_inclay_cb, rr, iuser);
+
+ uiblock_layer_pass_buttons(block, rr, iuser, imagechanged, 45, 107, 230);
+
+ /* decrease, increase arrows */
+ but= uiDefIconBut(block, BUT, imagechanged, ICON_TRIA_LEFT, 275,107,17,20, NULL, 0, 0, 0, 0, "Previous Pass");
+ uiButSetFunc(but, image_multi_decpass_cb, rr, iuser);
+ but= uiDefIconBut(block, BUT, imagechanged, ICON_TRIA_RIGHT, 292,107,18,20, NULL, 0, 0, 0, 0, "Next Pass");
+ uiButSetFunc(but, image_multi_incpass_cb, rr, iuser);
+
+ uiBlockEndAlign(block);
+
+}
+
+// XXX HACK!
+static int packdummy=0;
+
+/* The general Image panel with the loadsa callbacks! */
+void ED_image_uiblock_panel(const bContext *C, uiBlock *block, Image **ima_pp, ImageUser *iuser,
+ short redraw, short imagechanged)
+{
+ Scene *scene= CTX_data_scene(C);
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Image *ima= *ima_pp;
+ uiBut *but;
+ char str[128], *strp;
+
+ /* different stuff when we show viewer */
+ if(ima && ima->source==IMA_SRC_VIEWER) {
+ ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser);
+
+ image_info(ima, ibuf, str);
+ uiDefBut(block, LABEL, 0, ima->id.name+2, 10, 180, 300, 20, NULL, 1, 0, 0, 0, "");
+ uiDefBut(block, LABEL, 0, str, 10, 160, 300, 20, NULL, 1, 0, 0, 0, "");
+
+ if(ima->type==IMA_TYPE_COMPOSITE) {
+ iuser= ntree_get_active_iuser(scene->nodetree);
+ if(iuser) {
+ uiBlockBeginAlign(block);
+ uiDefIconTextBut(block, BUT, B_SIMA_RECORD, ICON_REC, "Record", 10,120,100,20, 0, 0, 0, 0, 0, "");
+ uiDefIconTextBut(block, BUT, B_SIMA_PLAY, ICON_PLAY, "Play", 110,120,100,20, 0, 0, 0, 0, 0, "");
+ but= uiDefBut(block, BUT, B_NOP, "Free Cache", 210,120,100,20, 0, 0, 0, 0, 0, "");
+ uiButSetFunc(but, image_freecache_cb, ima, NULL);
+
+ if(iuser->frames)
+ sprintf(str, "(%d) Frames:", iuser->framenr);
+ else strcpy(str, "Frames:");
+ uiBlockBeginAlign(block);
+ uiDefButI(block, NUM, imagechanged, str, 10, 90,150, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use");
+ uiDefButI(block, NUM, imagechanged, "StartFr:", 160,90,150,20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie");
+ }
+ }
+ else if(ima->type==IMA_TYPE_R_RESULT) {
+ /* browse layer/passes */
+ uiblock_layer_pass_arrow_buttons(block, RE_GetResult(RE_GetRender(scene->id.name)), iuser, imagechanged);
+ }
+ return;
+ }
+
+ /* the main ima source types */
+ if(ima) {
+// XXX uiSetButLock(ima->id.lib!=NULL, ERROR_LIBDATA_MESSAGE);
+ uiBlockBeginAlign(block);
+ uiBlockSetFunc(block, image_src_change_cb, ima, iuser);
+ uiDefButS(block, ROW, imagechanged, "Still", 10, 180, 60, 20, &ima->source, 0.0, IMA_SRC_FILE, 0, 0, "Single Image file");
+ uiDefButS(block, ROW, imagechanged, "Movie", 70, 180, 60, 20, &ima->source, 0.0, IMA_SRC_MOVIE, 0, 0, "Movie file");
+ uiDefButS(block, ROW, imagechanged, "Sequence", 130, 180, 90, 20, &ima->source, 0.0, IMA_SRC_SEQUENCE, 0, 0, "Multiple Image files, as a sequence");
+ uiDefButS(block, ROW, imagechanged, "Generated", 220, 180, 90, 20, &ima->source, 0.0, IMA_SRC_GENERATED, 0, 0, "Generated Image");
+ uiBlockSetFunc(block, NULL, NULL, NULL);
+ }
+ else
+ uiDefBut(block, LABEL, 0, " ", 10, 180, 300, 20, 0, 0, 0, 0, 0, ""); /* for align in panel */
+
+ /* Browse */
+ IMAnames_to_pupstring(&strp, NULL, NULL, &(CTX_data_main(C)->image), NULL, &iuser->menunr);
+
+ uiBlockBeginAlign(block);
+ but= uiDefButS(block, MENU, imagechanged, strp, 10,155,23,20, &iuser->menunr, 0, 0, 0, 0, "Selects an existing Image or Movie");
+ uiButSetFunc(but, image_browse_cb, ima_pp, iuser);
+
+ MEM_freeN(strp);
+
+ /* name + options, or only load */
+ if(ima) {
+ int drawpack= (ima->source!=IMA_SRC_SEQUENCE && ima->source!=IMA_SRC_MOVIE && ima->ok);
+
+ but= uiDefBut(block, TEX, B_IDNAME, "IM:", 33, 155, 177, 20, ima->id.name+2, 0.0, 21.0, 0, 0, "Current Image Datablock name.");
+ uiButSetFunc(but, test_idbutton_cb, ima->id.name, NULL);
+ but= uiDefBut(block, BUT, imagechanged, "Reload", 210, 155, 60, 20, NULL, 0, 0, 0, 0, "Reloads Image or Movie");
+ uiButSetFunc(but, image_reload_cb, ima, iuser);
+
+ but= uiDefIconBut(block, BUT, imagechanged, ICON_X, 270,155,20,20, 0, 0, 0, 0, 0, "Unlink Image block");
+ uiButSetFunc(but, image_unlink_cb, ima_pp, NULL);
+ sprintf(str, "%d", ima->id.us);
+ uiDefBut(block, BUT, B_NOP, str, 290,155,20,20, 0, 0, 0, 0, 0, "Only displays number of users of Image block");
+
+ but= uiDefIconBut(block, BUT, imagechanged, ICON_FILESEL, 10, 135, 23, 20, 0, 0, 0, 0, 0, "Open Fileselect to load new Image");
+ uiButSetFunc(but, image_load_fs_cb, ima_pp, iuser);
+ but= uiDefBut(block, TEX, imagechanged, "", 33,135,257+(drawpack?0:20),20, ima->name, 0.0, 239.0, 0, 0, "Image/Movie file name, change to load new");
+ uiButSetFunc(but, image_load_cb, ima_pp, iuser);
+
+ if(drawpack) {
+ if (ima->packedfile) packdummy = 1;
+ else packdummy = 0;
+ but= uiDefIconButBitI(block, TOG, 1, redraw, ICON_PACKAGE, 290,135,20,20, &packdummy, 0, 0, 0, 0, "Toggles Packed status of this Image");
+ uiButSetFunc(but, image_pack_cb, ima, iuser);
+ }
+
+ }
+ else {
+ but= uiDefBut(block, BUT, imagechanged, "Load", 33, 155, 100,20, NULL, 0, 0, 0, 0, "Load new Image of Movie");
+ uiButSetFunc(but, image_load_fs_cb, ima_pp, iuser);
+ }
+ uiBlockEndAlign(block);
+
+ if(ima) {
+ ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser);
+
+ /* check for re-render, only buttons */
+ if(imagechanged==B_IMAGECHANGED) {
+ if(iuser->flag & IMA_ANIM_REFRESHED) {
+ iuser->flag &= ~IMA_ANIM_REFRESHED;
+ WM_event_add_notifier(C, NC_IMAGE, ima);
+ }
+ }
+
+ /* multilayer? */
+ if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
+ uiblock_layer_pass_arrow_buttons(block, ima->rr, iuser, imagechanged);
+ }
+ else {
+ image_info(ima, ibuf, str);
+ uiDefBut(block, LABEL, 0, str, 10, 112, 300, 20, NULL, 1, 0, 0, 0, "");
+ }
+
+ /* exception, let's do because we only use this panel 3 times in blender... but not real good code! */
+ if( (FACESEL_PAINT_TEST) && sima && &sima->iuser==iuser)
+ return;
+ /* left side default per-image options, right half the additional options */
+
+ /* fields */
+ uiBlockBeginAlign(block);
+ but= uiDefButBitS(block, TOGBUT, IMA_FIELDS, imagechanged, "Fields", 10, 70, 65, 20, &ima->flag, 0, 0, 0, 0, "Click to enable use of fields in Image");
+ uiButSetFunc(but, image_field_test, ima, iuser);
+ uiDefButBitS(block, TOGBUT, IMA_STD_FIELD, B_NOP, "Odd", 75, 70, 45, 20, &ima->flag, 0, 0, 0, 0, "Standard Field Toggle");
+
+ uiBlockSetFunc(block, image_reload_cb, ima, iuser);
+ uiDefButBitS(block, TOGBUT, IMA_ANTIALI, B_NOP, "Anti", 10, 50, 45, 20, &ima->flag, 0, 0, 0, 0, "Toggles Image anti-aliasing, only works with solid colors");
+ uiDefButBitS(block, TOGBUT, IMA_DO_PREMUL, imagechanged, "Premul", 55, 50, 65, 20, &ima->flag, 0, 0, 0, 0, "Toggles premultiplying alpha");
+ uiBlockEndAlign(block);
+
+ if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
+ sprintf(str, "(%d) Frames:", iuser->framenr);
+
+ uiBlockBeginAlign(block);
+ uiBlockSetFunc(block, image_user_change, iuser, NULL);
+ uiDefButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NOP, "Auto Refresh", 120, 70, 190, 20, &iuser->flag, 0, 0, 0, 0, "Always refresh Image on frame changes");
+
+ if(ima->anim) {
+ uiDefButI(block, NUM, imagechanged, str, 120, 50,170, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use");
+ but= uiDefBut(block, BUT, redraw, "<", 290, 50, 20, 20, 0, 0, 0, 0, 0, "Copies number of frames in movie file to Frames: button");
+ uiButSetFunc(but, set_frames_cb, ima, iuser);
+ }
+ else
+ uiDefButI(block, NUM, imagechanged, str, 120, 50,190, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use");
+
+ uiDefButI(block, NUM, imagechanged, "Offs:", 120,30,100,20, &iuser->offset, -MAXFRAMEF, MAXFRAMEF, 0, 0, "Offsets the number of the frame to use in the animation");
+ uiDefButS(block, NUM, imagechanged, "Fie/Ima:", 220,30,90,20, &iuser->fie_ima, 1.0, 200.0, 0, 0, "The number of fields per rendered frame (2 fields is 1 image)");
+
+ uiDefButI(block, NUM, imagechanged, "StartFr:", 120,10,100,20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie");
+ uiDefButS(block, TOG, imagechanged, "Cyclic", 220,10,90,20, &iuser->cycl, 0.0, 1.0, 0, 0, "Cycle the images in the movie");
+
+ uiBlockSetFunc(block, NULL, iuser, NULL);
+ }
+ else if(ima->source==IMA_SRC_GENERATED) {
+
+ uiBlockBeginAlign(block);
+ uiBlockSetFunc(block, image_generated_change_cb, ima, iuser);
+ uiDefButS(block, NUM, imagechanged, "SizeX:", 120,70,100,20, &ima->gen_x, 1.0, 5000.0, 0, 0, "Image size x");
+ uiDefButS(block, NUM, imagechanged, "SizeY:", 220,70,90,20, &ima->gen_y, 1.0, 5000.0, 0, 0, "Image size y");
+ uiDefButS(block, TOGBUT, imagechanged, "UV Test grid",120,50,190,20, &ima->gen_type, 0.0, 1.0, 0, 0, "");
+ uiBlockSetFunc(block, NULL, NULL, NULL);
+ }
+ }
+ uiBlockEndAlign(block);
+}
+
+
+static void image_panel_properties(const bContext *C, ARegion *ar)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "image_panel_properties", UI_EMBOSS);
+ if(uiNewPanel(C, ar, block, "Image Properties", "Image", 10, 50, 318, 204)==0)
+ return;
+ uiBlockSetHandleFunc(block, do_image_panel_events, NULL);
+
+ /* note, it draws no bottom half in facemode, for vertex buttons */
+ ED_image_uiblock_panel(C, block, &sima->image, &sima->iuser, B_REDR, B_REDR);
+ image_editvertex_buts(C, block);
+
+ uiEndBlock(C, block);
+}
+
+
+
+void image_buttons_area_defbuts(const bContext *C, ARegion *ar)
+{
+ uiBeginPanels(C, ar);
+
+ image_panel_properties(C, ar);
+ image_panel_game_properties(C, ar);
+ image_panel_view_properties(C, ar);
+ image_panel_paint(C, ar);
+ image_panel_paintcolor(C, ar);
+ image_panel_curves(C, ar);
+
+ uiEndPanels(C, ar);
+}
+
+
+static int image_properties(bContext *C, wmOperator *op)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= image_has_buttons_region(sa);
+
+ if(ar) {
+ ar->flag ^= RGN_FLAG_HIDDEN;
+ ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */
+
+ ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
+ ED_area_tag_redraw(sa);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_properties(wmOperatorType *ot)
+{
+ ot->name= "Properties";
+ ot->idname= "IMAGE_OT_properties";
+
+ ot->exec= image_properties;
+ ot->poll= ED_operator_image_active;
+
+ /* flags */
+ ot->flag= 0;
+}
+
+
+
diff --git a/source/blender/editors/space_image/image_render.c b/source/blender/editors/space_image/image_render.c
new file mode 100644
index 00000000000..381e12267c6
--- /dev/null
+++ b/source/blender/editors/space_image/image_render.c
@@ -0,0 +1,177 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2002-2009
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "DNA_image_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_screen.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "ED_screen.h"
+
+#include "RE_pipeline.h"
+
+#include "WM_api.h"
+
+#define HEADER_HEIGHT 18
+
+/* *********************** render callbacks ***************** */
+
+/* set on initialize render, only one render output to imagewindow can exist, so the global isnt dangerous yet :) */
+static ScrArea *image_area= NULL;
+
+/* can get as well the full picture, as the parts while rendering */
+/* XXX will be obsolete, here for reference now */
+void imagewindow_progress(SpaceImage *sima, RenderResult *rr, volatile rcti *renrect)
+{
+ float x1, y1, *rectf= NULL;
+ unsigned int *rect32= NULL;
+ int ymin, ymax, xmin, xmax;
+
+ /* if renrect argument, we only display scanlines */
+ if(renrect) {
+ /* if ymax==recty, rendering of layer is ready, we should not draw, other things happen... */
+ if(rr->renlay==NULL || renrect->ymax>=rr->recty)
+ return;
+
+ /* xmin here is first subrect x coord, xmax defines subrect width */
+ xmin = renrect->xmin;
+ xmax = renrect->xmax - xmin;
+ if (xmax<2) return;
+
+ ymin= renrect->ymin;
+ ymax= renrect->ymax - ymin;
+ if(ymax<2)
+ return;
+ renrect->ymin= renrect->ymax;
+ }
+ else {
+ xmin = ymin = 0;
+ xmax = rr->rectx - 2*rr->crop;
+ ymax = rr->recty - 2*rr->crop;
+ }
+
+ /* image window cruft */
+
+ /* find current float rect for display, first case is after composit... still weak */
+ if(rr->rectf)
+ rectf= rr->rectf;
+ else {
+ if(rr->rect32)
+ rect32= (unsigned int *)rr->rect32;
+ else {
+ if(rr->renlay==NULL || rr->renlay->rectf==NULL) return;
+ rectf= rr->renlay->rectf;
+ }
+ }
+ if(rectf) {
+ /* if scanline updates... */
+ rectf+= 4*(rr->rectx*ymin + xmin);
+
+ /* when rendering more pixels than needed, we crop away cruft */
+ if(rr->crop)
+ rectf+= 4*(rr->crop*rr->rectx + rr->crop);
+ }
+
+ /* tilerect defines drawing offset from (0,0) */
+ /* however, tilerect (xmin, ymin) is first pixel */
+ x1 = sima->centx + (rr->tilerect.xmin + rr->crop + xmin)*sima->zoom;
+ y1 = sima->centy + (rr->tilerect.ymin + rr->crop + ymin)*sima->zoom;
+
+ /* needed for gla draw */
+ // XXX { rcti rct= ar->winrct; rct.ymax-= HEADER_HEIGHT; glaDefine2DArea(&rct);}
+
+ glPixelZoom(sima->zoom, sima->zoom);
+
+ if(rect32)
+ glaDrawPixelsSafe(x1, y1, xmax, ymax, rr->rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect32);
+ else
+ glaDrawPixelsSafe_to32(x1, y1, xmax, ymax, rr->rectx, rectf);
+
+ glPixelZoom(1.0, 1.0);
+
+}
+
+
+/* coming from BIF_toggle_render_display() */
+void imagewindow_toggle_render(bContext *C)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ ScrArea *sa;
+
+ /* check if any imagewindow is showing temporal render output */
+ for(sa=sc->areabase.first; sa; sa= sa->next) {
+ if(sa->spacetype==SPACE_IMAGE) {
+ SpaceImage *sima= sa->spacedata.first;
+
+ if(sima->image && sima->image->type==IMA_TYPE_R_RESULT)
+ if(sima->flag & (SI_PREVSPACE|SI_FULLWINDOW))
+ break;
+ }
+ }
+
+ if(sa) {
+ // XXX addqueue(sa->win, ESCKEY, 1); /* also returns from fullscreen */
+ }
+ else {
+// sa= imagewindow_set_render_display(C);
+ // XXX scrarea_queue_headredraw(sa);
+ // XXX scrarea_queue_winredraw(sa);
+ }
+}
+
+/* NOTE: called while render, so no malloc allowed! */
+static void imagewindow_renderinfo_cb(void *handle, RenderStats *rs)
+{
+ if(image_area) {
+ // XXX BIF_make_render_text(rs);
+
+ // XXX sima_draw_render_info(sima, ar);
+
+ /* no screen_swapbuffers, prevent any other window to draw */
+ // XXX myswapbuffers();
+ }
+}
+
+void ED_space_image_render_callbacks(bContext *C, Render *re)
+{
+
+// RE_display_init_cb(re, C, imagewindow_init_display_cb);
+// RE_display_draw_cb(re, C, imagewindow_progress_display_cb);
+// RE_display_clear_cb(re, C, imagewindow_clear_display_cb);
+ RE_stats_draw_cb(re, C, imagewindow_renderinfo_cb);
+}
+
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
new file mode 100644
index 00000000000..fab9317bbd0
--- /dev/null
+++ b/source/blender/editors/space_image/space_image.c
@@ -0,0 +1,791 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_image_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_image.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "ED_image.h"
+#include "ED_mesh.h"
+#include "ED_space_api.h"
+#include "ED_screen.h"
+#include "ED_uvedit.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "image_intern.h"
+
+/* ******************** manage regions ********************* */
+
+ARegion *image_has_buttons_region(ScrArea *sa)
+{
+ ARegion *ar, *arnew;
+
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ if(ar->regiontype==RGN_TYPE_UI)
+ return ar;
+
+ /* add subdiv level; after header */
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ if(ar->regiontype==RGN_TYPE_HEADER)
+ break;
+
+ /* is error! */
+ if(ar==NULL) return NULL;
+
+ arnew= MEM_callocN(sizeof(ARegion), "buttons for image");
+
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype= RGN_TYPE_UI;
+ arnew->alignment= RGN_ALIGN_LEFT;
+
+ arnew->flag = RGN_FLAG_HIDDEN;
+
+ return arnew;
+}
+
+/* ******************** default callbacks for image space ***************** */
+
+static SpaceLink *image_new(const bContext *C)
+{
+ ARegion *ar;
+ SpaceImage *simage;
+
+ simage= MEM_callocN(sizeof(SpaceImage), "initimage");
+ simage->spacetype= SPACE_IMAGE;
+ simage->zoom= 1;
+
+ simage->iuser.ok= 1;
+ simage->iuser.fie_ima= 2;
+ simage->iuser.frames= 100;
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for image");
+
+ BLI_addtail(&simage->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_BOTTOM;
+
+ /* buttons/list view */
+ ar= MEM_callocN(sizeof(ARegion), "buttons for image");
+
+ BLI_addtail(&simage->regionbase, ar);
+ ar->regiontype= RGN_TYPE_UI;
+ ar->alignment= RGN_ALIGN_LEFT;
+ ar->flag = RGN_FLAG_HIDDEN;
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for image");
+
+ BLI_addtail(&simage->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+
+ return (SpaceLink *)simage;
+}
+
+/* not spacelink itself */
+static void image_free(SpaceLink *sl)
+{
+ SpaceImage *simage= (SpaceImage*) sl;
+
+ if(simage->cumap)
+ curvemapping_free(simage->cumap);
+// if(simage->gpd)
+// XXX free_gpencil_data(simage->gpd);
+
+}
+
+
+/* spacetype; init callback */
+static void image_init(struct wmWindowManager *wm, ScrArea *sa)
+{
+
+}
+
+static SpaceLink *image_duplicate(SpaceLink *sl)
+{
+ SpaceImage *simagen= MEM_dupallocN(sl);
+
+ /* clear or remove stuff from old */
+ if(simagen->cumap)
+ simagen->cumap= curvemapping_copy(simagen->cumap);
+
+ return (SpaceLink *)simagen;
+}
+
+void image_operatortypes(void)
+{
+ WM_operatortype_append(IMAGE_OT_view_all);
+ WM_operatortype_append(IMAGE_OT_view_pan);
+ WM_operatortype_append(IMAGE_OT_view_selected);
+ WM_operatortype_append(IMAGE_OT_view_zoom);
+ WM_operatortype_append(IMAGE_OT_view_zoom_in);
+ WM_operatortype_append(IMAGE_OT_view_zoom_out);
+ WM_operatortype_append(IMAGE_OT_view_zoom_ratio);
+
+ WM_operatortype_append(IMAGE_OT_new);
+ WM_operatortype_append(IMAGE_OT_open);
+ WM_operatortype_append(IMAGE_OT_replace);
+ WM_operatortype_append(IMAGE_OT_reload);
+ WM_operatortype_append(IMAGE_OT_save);
+ WM_operatortype_append(IMAGE_OT_save_as);
+ WM_operatortype_append(IMAGE_OT_save_sequence);
+ WM_operatortype_append(IMAGE_OT_pack);
+ WM_operatortype_append(IMAGE_OT_unpack);
+
+ WM_operatortype_append(IMAGE_OT_sample);
+ WM_operatortype_append(IMAGE_OT_curves_point_set);
+
+ WM_operatortype_append(IMAGE_OT_record_composite);
+
+ WM_operatortype_append(IMAGE_OT_toolbox);
+ WM_operatortype_append(IMAGE_OT_properties);
+}
+
+void image_keymap(struct wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "Image Generic", SPACE_IMAGE, 0);
+
+ WM_keymap_add_item(keymap, "IMAGE_OT_new", NKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "IMAGE_OT_open", OKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "IMAGE_OT_reload", RKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "IMAGE_OT_save", SKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "IMAGE_OT_properties", NKEY, KM_PRESS, 0, 0);
+
+ keymap= WM_keymap_listbase(wm, "Image", SPACE_IMAGE, 0);
+
+ WM_keymap_add_item(keymap, "IMAGE_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "IMAGE_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MIDDLEMOUSE, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_in", WHEELINMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_out", WHEELOUTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_out", PADMINUS, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
+
+ RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD8, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 8.0f);
+ RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD4, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 4.0f);
+ RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD2, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 2.0f);
+ RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD1, KM_PRESS, 0, 0)->ptr, "ratio", 1.0f);
+ RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD2, KM_PRESS, 0, 0)->ptr, "ratio", 0.5f);
+ RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD4, KM_PRESS, 0, 0)->ptr, "ratio", 0.25f);
+ RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD8, KM_PRESS, 0, 0)->ptr, "ratio", 0.125f);
+
+ WM_keymap_add_item(keymap, "PAINT_OT_image_paint", ACTIONMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "PAINT_OT_grab_clone", SELECTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "PAINT_OT_sample_color", SELECTMOUSE, KM_PRESS, 0, 0);
+ RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_image_paint_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_image_paint_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH);
+
+ WM_keymap_add_item(keymap, "IMAGE_OT_sample", ACTIONMOUSE, KM_PRESS, 0, 0);
+ RNA_enum_set(WM_keymap_add_item(keymap, "IMAGE_OT_curves_point_set", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "point", 0);
+ RNA_enum_set(WM_keymap_add_item(keymap, "IMAGE_OT_curves_point_set", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "point", 1);
+
+ WM_keymap_add_item(keymap, "IMAGE_OT_toolbox", SPACEKEY, KM_PRESS, 0, 0);
+}
+
+static void image_refresh(const bContext *C, ScrArea *sa)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Image *ima;
+
+ ima= ED_space_image(sima);
+
+ /* check if we have to set the image from the editmesh */
+ if(ima && (ima->source==IMA_SRC_VIEWER || sima->pin));
+ else if(obedit && obedit->type == OB_MESH) {
+ Mesh *me= (Mesh*)obedit->data;
+ EditMesh *em= BKE_mesh_get_editmesh(me);
+ MTFace *tf;
+
+ if(em && EM_texFaceCheck(em)) {
+ sima->image= ima= NULL;
+
+ tf = EM_get_active_mtface(em, NULL, NULL, 1); /* partially selected face is ok */
+
+ if(tf && (tf->mode & TF_TEX)) {
+ /* don't need to check for pin here, see above */
+ sima->image= ima= tf->tpage;
+
+ if(sima->flag & SI_EDITTILE);
+ else sima->curtile= tf->tile;
+
+ if(ima) {
+ if(tf->mode & TF_TILES)
+ ima->tpageflag |= IMA_TILES;
+ else
+ ima->tpageflag &= ~IMA_TILES;
+ }
+ }
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ }
+}
+
+static void image_listener(ScrArea *sa, wmNotifier *wmn)
+{
+ SpaceImage *sima= sa->spacedata.first;
+
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ switch(wmn->data) {
+ case ND_MODE:
+ case ND_RENDER_RESULT:
+ case ND_COMPO_RESULT:
+ ED_area_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ break;
+ }
+ break;
+ case NC_IMAGE:
+ if(!wmn->reference || wmn->reference == sima->image)
+ ED_area_tag_redraw(sa);
+ break;
+ }
+}
+
+static int image_context(const bContext *C, const char *member, bContextDataResult *result)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+
+ if(CTX_data_equals(member, "edit_image")) {
+ CTX_data_id_pointer_set(result, (ID*)ED_space_image(sima));
+ return 1;
+ }
+
+ return 0;
+}
+
+/************************** main region ***************************/
+
+/* sets up the fields of the View2D from zoom and offset */
+static void image_main_area_set_view2d(SpaceImage *sima, ARegion *ar, Scene *scene)
+{
+ Image *ima= ED_space_image(sima);
+ float x1, y1, w, h;
+ int width, height, winx, winy;
+
+#if 0
+ if(image_preview_active(curarea, &width, &height));
+#endif
+ if(sima->image) {
+ ImBuf *ibuf= ED_space_image_buffer(sima);
+ float xuser_asp, yuser_asp;
+
+ ED_image_aspect(sima->image, &xuser_asp, &yuser_asp);
+ if(ibuf) {
+ width= ibuf->x*xuser_asp;
+ height= ibuf->y*yuser_asp;
+ }
+ else if(sima->image->type==IMA_TYPE_R_RESULT) {
+ /* not very important, just nice */
+ width= (scene->r.xsch*scene->r.size)/100;
+ height= (scene->r.ysch*scene->r.size)/100;
+ }
+ else
+ ED_space_image_size(sima, &width, &height);
+ }
+ else
+ ED_space_image_size(sima, &width, &height);
+
+ w= width;
+ h= height;
+
+ if(ima)
+ h *= ima->aspy/ima->aspx;
+
+ winx= ar->winrct.xmax - ar->winrct.xmin + 1;
+ winy= ar->winrct.ymax - ar->winrct.ymin + 1;
+
+ ar->v2d.tot.xmin= 0;
+ ar->v2d.tot.ymin= 0;
+ ar->v2d.tot.xmax= w;
+ ar->v2d.tot.ymax= h;
+
+ ar->v2d.mask.xmin= ar->v2d.mask.ymin= 0;
+ ar->v2d.mask.xmax= winx;
+ ar->v2d.mask.ymax= winy;
+
+ /* which part of the image space do we see? */
+ /* same calculation as in lrectwrite: area left and down*/
+ x1= ar->winrct.xmin+(winx-sima->zoom*w)/2;
+ y1= ar->winrct.ymin+(winy-sima->zoom*h)/2;
+
+ x1-= sima->zoom*sima->xof;
+ y1-= sima->zoom*sima->yof;
+
+ /* relative display right */
+ ar->v2d.cur.xmin= ((ar->winrct.xmin - (float)x1)/sima->zoom);
+ ar->v2d.cur.xmax= ar->v2d.cur.xmin + ((float)winx/sima->zoom);
+
+ /* relative display left */
+ ar->v2d.cur.ymin= ((ar->winrct.ymin-(float)y1)/sima->zoom);
+ ar->v2d.cur.ymax= ar->v2d.cur.ymin + ((float)winy/sima->zoom);
+
+ /* normalize 0.0..1.0 */
+ ar->v2d.cur.xmin /= w;
+ ar->v2d.cur.xmax /= w;
+ ar->v2d.cur.ymin /= h;
+ ar->v2d.cur.ymax /= h;
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void image_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ // image space manages own v2d
+ // UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
+
+ /* image paint polls for mode */
+ keymap= WM_keymap_listbase(wm, "ImagePaint", SPACE_IMAGE, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+
+ /* own keymaps */
+ keymap= WM_keymap_listbase(wm, "Image Generic", SPACE_IMAGE, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap= WM_keymap_listbase(wm, "Image", SPACE_IMAGE, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+static void image_main_area_draw(const bContext *C, ARegion *ar)
+{
+ /* draw entirely, view changes should be handled here */
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene= CTX_data_scene(C);
+ View2D *v2d= &ar->v2d;
+ //View2DScrollers *scrollers;
+ float col[3];
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* we set view2d from own zoom and offset each time */
+ image_main_area_set_view2d(sima, ar, scene);
+
+ /* we draw image in pixelspace */
+ draw_image_main(sima, ar, scene);
+
+ /* and uvs in 0.0-1.0 space */
+ UI_view2d_view_ortho(C, v2d);
+ draw_uvedit_main(sima, ar, scene, obedit);
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST);
+ UI_view2d_view_restore(C);
+
+ /* scrollers? */
+ /*scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_UNIT_VALUES, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);*/
+}
+
+static void image_modal_keymaps(wmWindowManager *wm, ARegion *ar, int stype)
+{
+ ListBase *keymap;
+
+ keymap= WM_keymap_listbase(wm, "UVEdit", 0, 0);
+
+ if(stype==NS_EDITMODE_MESH)
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+ else
+ WM_event_remove_keymap_handler(&ar->handlers, keymap);
+}
+
+static void image_main_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ switch(wmn->data) {
+ case ND_MODE:
+ image_modal_keymaps(wmn->wm, ar, wmn->subtype);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch(wmn->data) {
+ case ND_GEOM_SELECT:
+ case ND_GEOM_DATA:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ }
+}
+
+/* *********************** buttons region ************************ */
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void image_buttons_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ keymap= WM_keymap_listbase(wm, "View2D Buttons List", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap= WM_keymap_listbase(wm, "Image Generic", SPACE_IMAGE, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST_UI, ar->winx, ar->winy);
+}
+
+static void image_buttons_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ /* clear */
+ UI_GetThemeColor3fv(TH_PANEL, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ image_buttons_area_defbuts(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+static void image_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+
+ }
+}
+
+/************************* header region **************************/
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void image_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+}
+
+static void image_header_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ /* clear */
+ if(ED_screen_area_active(C))
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ else
+ UI_GetThemeColor3fv(TH_HEADERDESEL, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ image_header_buttons(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+/**************************** spacetype *****************************/
+
+/* only called once, from space/spacetypes.c */
+void ED_spacetype_image(void)
+{
+ SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype image");
+ ARegionType *art;
+
+ st->spaceid= SPACE_IMAGE;
+
+ st->new= image_new;
+ st->free= image_free;
+ st->init= image_init;
+ st->duplicate= image_duplicate;
+ st->operatortypes= image_operatortypes;
+ st->keymap= image_keymap;
+ st->refresh= image_refresh;
+ st->listener= image_listener;
+ st->context= image_context;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype image region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->keymapflag= ED_KEYMAP_FRAMES;
+ art->init= image_main_area_init;
+ art->draw= image_main_area_draw;
+ art->listener= image_main_area_listener;
+ art->keymapflag= 0;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: listview/buttons */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype image region");
+ art->regionid = RGN_TYPE_UI;
+ art->minsizex= 220; // XXX
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
+ art->listener= image_buttons_area_listener;
+ art->init= image_buttons_area_init;
+ art->draw= image_buttons_area_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype image region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
+ art->init= image_header_area_init;
+ art->draw= image_header_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+
+ BKE_spacetype_register(st);
+}
+
+/**************************** common state *****************************/
+
+/* note; image_panel_properties() uses pointer to sima->image directly */
+Image *ED_space_image(SpaceImage *sima)
+{
+ return sima->image;
+}
+
+/* called to assign images to UV faces */
+void ED_space_image_set(bContext *C, SpaceImage *sima, Scene *scene, Object *obedit, Image *ima)
+{
+ ED_uvedit_assign_image(scene, obedit, ima, sima->image);
+
+ /* change the space ima after because uvedit_face_visible uses the space ima
+ * to check if the face is displayed in UV-localview */
+ sima->image= ima;
+
+ if(ima == NULL || ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE)
+ sima->flag &= ~SI_DRAWTOOL;
+
+ if(sima->image)
+ BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
+
+ if(sima->image && sima->image->id.us==0)
+ sima->image->id.us= 1;
+
+ if(obedit)
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+}
+
+ImBuf *ED_space_image_buffer(SpaceImage *sima)
+{
+ ImBuf *ibuf;
+
+ if(sima->image) {
+#if 0
+ if(sima->image->type==IMA_TYPE_R_RESULT && BIF_show_render_spare())
+ return BIF_render_spare_imbuf();
+ else
+#endif
+ ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser);
+
+ if(ibuf && (ibuf->rect || ibuf->rect_float))
+ return ibuf;
+ }
+
+ return NULL;
+}
+
+void ED_image_size(Image *ima, int *width, int *height)
+{
+ ImBuf *ibuf;
+
+ ibuf= (ima)? BKE_image_get_ibuf(ima, NULL): NULL;
+
+ if(ibuf && ibuf->x > 0 && ibuf->y > 0) {
+ *width= ibuf->x;
+ *height= ibuf->y;
+ }
+ else {
+ *width= 256;
+ *height= 256;
+ }
+}
+
+void ED_space_image_size(SpaceImage *sima, int *width, int *height)
+{
+ ImBuf *ibuf;
+
+ ibuf= ED_space_image_buffer(sima);
+
+ if(ibuf && ibuf->x > 0 && ibuf->y > 0) {
+ *width= ibuf->x;
+ *height= ibuf->y;
+ }
+ /* I know a bit weak... but preview uses not actual image size */
+ // XXX else if(image_preview_active(sima, width, height));
+ else {
+ *width= 256;
+ *height= 256;
+ }
+}
+
+void ED_image_aspect(Image *ima, float *aspx, float *aspy)
+{
+ *aspx= *aspy= 1.0;
+
+ if((ima == NULL) || (ima->type == IMA_TYPE_R_RESULT) || (ima->type == IMA_TYPE_COMPOSITE) ||
+ (ima->tpageflag & IMA_TILES) || (ima->aspx==0.0 || ima->aspy==0.0))
+ return;
+
+ /* x is always 1 */
+ *aspy = ima->aspy/ima->aspx;
+}
+
+void ED_space_image_aspect(SpaceImage *sima, float *aspx, float *aspy)
+{
+ ED_image_aspect(ED_space_image(sima), aspx, aspy);
+}
+
+void ED_space_image_zoom(SpaceImage *sima, ARegion *ar, float *zoomx, float *zoomy)
+{
+ int width, height;
+
+ ED_space_image_size(sima, &width, &height);
+
+ *zoomx= (float)(ar->winrct.xmax - ar->winrct.xmin)/(float)((ar->v2d.cur.xmax - ar->v2d.cur.xmin)*width);
+ *zoomy= (float)(ar->winrct.ymax - ar->winrct.ymin)/(float)((ar->v2d.cur.ymax - ar->v2d.cur.ymin)*height);
+}
+
+void ED_space_image_uv_aspect(SpaceImage *sima, float *aspx, float *aspy)
+{
+ int w, h;
+
+ ED_space_image_aspect(sima, aspx, aspy);
+ ED_space_image_size(sima, &w, &h);
+
+ *aspx *= (float)w/256.0f;
+ *aspy *= (float)h/256.0f;
+}
+
+void ED_image_uv_aspect(Image *ima, float *aspx, float *aspy)
+{
+ int w, h;
+
+ ED_image_aspect(ima, aspx, aspy);
+ ED_image_size(ima, &w, &h);
+
+ *aspx *= (float)w;
+ *aspy *= (float)h;
+}
+
+int ED_space_image_show_render(SpaceImage *sima)
+{
+ return (sima->image && ELEM(sima->image->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE));
+}
+
+int ED_space_image_show_paint(SpaceImage *sima)
+{
+ if(ED_space_image_show_render(sima))
+ return 0;
+
+ return (sima->flag & SI_DRAWTOOL);
+}
+
+int ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
+{
+ if(ED_space_image_show_render(sima))
+ return 0;
+ if(ED_space_image_show_paint(sima))
+ return 0;
+
+ if(obedit && obedit->type == OB_MESH) {
+ EditMesh *em = BKE_mesh_get_editmesh(obedit->data);
+ int ret;
+
+ ret = EM_texFaceCheck(em);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return ret;
+ }
+
+ return 0;
+}
+
+int ED_space_image_show_uvshadow(SpaceImage *sima, Object *obedit)
+{
+ if(ED_space_image_show_render(sima))
+ return 0;
+
+ if(ED_space_image_show_paint(sima))
+ if(obedit && obedit->type == OB_MESH) {
+ EditMesh *em = BKE_mesh_get_editmesh(obedit->data);
+ int ret;
+
+ ret = EM_texFaceCheck(em);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return ret;
+ }
+
+ return 0;
+}
+
diff --git a/source/blender/editors/space_info/Makefile b/source/blender/editors/space_info/Makefile
new file mode 100644
index 00000000000..bc04ddc7824
--- /dev/null
+++ b/source/blender/editors/space_info/Makefile
@@ -0,0 +1,55 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_info
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I../../blenfont
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/space_info/SConscript b/source/blender/editors/space_info/SConscript
new file mode 100644
index 00000000000..05afcae162e
--- /dev/null
+++ b/source/blender/editors/space_info/SConscript
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf ../../blenfont'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+
+defs = []
+
+if env['WITH_BF_GAMEENGINE']:
+ defs.append('GAMEBLENDER=1')
+
+ if env['WITH_BF_SOLID']:
+ defs.append('USE_SUMO_SOLID')
+
+env.BlenderLib ( 'bf_editors_space_info', sources, Split(incs), defs, libtype=['core'], priority=[70] )
diff --git a/source/blender/editors/space_info/info_header.c b/source/blender/editors/space_info/info_header.c
new file mode 100644
index 00000000000..8b940bd6ca8
--- /dev/null
+++ b/source/blender/editors/space_info/info_header.c
@@ -0,0 +1,455 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_packedFile_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_bpath.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_main.h"
+#include "BKE_packedFile.h"
+#include "BKE_screen.h"
+
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "info_intern.h"
+
+static int pupmenu() {return 0;}
+static int okee() {return 0;}
+static int error() {return 0;}
+
+/* ************************ header area region *********************** */
+
+#define B_STOPRENDER 1
+#define B_STOPCAST 2
+
+static void do_viewmenu(bContext *C, void *arg, int event)
+{
+}
+
+static uiBlock *dummy_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "dummy_viewmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_viewmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static int buttons_do_unpack()
+{
+ int how;
+ char menu[2048];
+ char *line = menu;
+ int ret_value = 1, count = 0;
+
+ count = countPackedFiles();
+
+ if(!count) {
+ pupmenu("No packed files. Autopack disabled");
+ return ret_value;
+ }
+ if (count == 1)
+ line += sprintf(line, "Unpack 1 file%%t");
+ else
+ line += sprintf(line, "Unpack %d files%%t", count);
+
+ line += sprintf(line, "|Use files in current directory (create when necessary)%%x%d", PF_USE_LOCAL);
+ line += sprintf(line, "|Write files to current directory (overwrite existing files)%%x%d", PF_WRITE_LOCAL);
+ line += sprintf(line, "|%%l|Use files in original location (create when necessary)%%x%d", PF_USE_ORIGINAL);
+ line += sprintf(line, "|Write files to original location (overwrite existing files)%%x%d", PF_WRITE_ORIGINAL);
+ line += sprintf(line, "|%%l|Disable AutoPack, keep all packed files %%x%d", PF_KEEP);
+ line += sprintf(line, "|Ask for each file %%x%d", PF_ASK);
+
+ how = pupmenu(menu);
+
+ if(how == -1)
+ ret_value = 0;
+ else {
+ if (how != PF_KEEP) unpackAll(how);
+ G.fileflags &= ~G_AUTOPACK;
+ }
+
+ return ret_value;
+}
+
+static void check_packAll()
+{
+ // first check for dirty images
+ Image *ima;
+
+ for(ima = G.main->image.first; ima; ima= ima->id.next) {
+ if (ima->ibufs.first) { /* XXX FIX */
+ ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
+
+ if (ibuf && (ibuf->userflags &= IB_BITMAPDIRTY))
+ break;
+ }
+ }
+
+ if (ima == NULL || okee("Some images are painted on. These changes will be lost. Continue ?")) {
+ packAll();
+ G.fileflags |= G_AUTOPACK;
+ }
+}
+
+static void do_info_externalfiles(bContext *C, void *arg, int event)
+{
+ switch (event) {
+
+ case 1: /* pack data */
+ check_packAll();
+ break;
+ case 3: /* unpack data */
+ if (buttons_do_unpack() != 0) {
+ /* Clear autopack bit only if user selected one of the unpack options */
+ G.fileflags &= ~G_AUTOPACK;
+ }
+ break;
+ case 10: /* make all paths relative */
+ if (G.relbase_valid) {
+ int tot,changed,failed,linked;
+ char str[512];
+ char txtname[24]; /* text block name */
+ txtname[0] = '\0';
+ makeFilesRelative(txtname, &tot, &changed, &failed, &linked);
+ if (failed) sprintf(str, "Make Relative%%t|Total files %i|Changed %i|Failed %i, See Text \"%s\"|Linked %i", tot, changed, failed, txtname, linked);
+ else sprintf(str, "Make Relative%%t|Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked);
+ pupmenu(str);
+ } else {
+ pupmenu("Can't set relative paths with an unsaved blend file");
+ }
+ break;
+ case 11: /* make all paths absolute */
+ {
+ int tot,changed,failed,linked;
+ char str[512];
+ char txtname[24]; /* text block name */
+ txtname[0] = '\0';
+ makeFilesAbsolute(txtname, &tot, &changed, &failed, &linked);
+ sprintf(str, "Make Absolute%%t|Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked);
+ if (failed) sprintf(str, "Make Absolute%%t|Total files %i|Changed %i|Failed %i, See Text \"%s\"|Linked %i", tot, changed, failed, txtname, linked);
+ else sprintf(str, "Make Absolute%%t|Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked);
+
+ pupmenu(str);
+ }
+ break;
+ case 12: /* check images exist */
+ {
+ char txtname[24]; /* text block name */
+ txtname[0] = '\0';
+
+ /* run the missing file check */
+ checkMissingFiles( txtname );
+
+ if (txtname[0] == '\0') {
+ okee("No external files missing");
+ } else {
+ char str[128];
+ sprintf(str, "Missing files listed in Text \"%s\"", txtname );
+ error(str);
+ }
+ }
+ break;
+ case 13: /* search for referenced files that are not available */
+// XXX if(curarea->spacetype==SPACE_INFO) {
+// ScrArea *sa;
+// sa= closest_bigger_area();
+// areawinset(sa->win);
+// }
+// activate_fileselect(FILE_SPECIAL, "Find Missing Files", "", findMissingFiles);
+ break;
+ }
+
+}
+
+
+uiBlock *info_externalfiles(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "info_externalfiles", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_info_externalfiles, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Pack into .blend file", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Unpack into Files...", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make all Paths Relative", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 10, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make all Paths Absolute", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 11, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Report Missing Files...", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 12, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find Missing Files...", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 13, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+
+
+static void info_filemenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+
+ uiMenuContext(head, WM_OP_EXEC_AREA);
+ uiMenuItemO(head, 0, "WM_OT_read_homefile");
+ uiMenuContext(head, WM_OP_INVOKE_AREA);
+ uiMenuItemO(head, 0, "WM_OT_open_mainfile");
+// uiDefIconTextBlockBut(block, info_openrecentmenu, NULL, ICON_RIGHTARROW_THIN, "Open Recent",0, yco-=20, 120, 19, "");
+// uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Recover Last Session", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
+
+ uiMenuSeparator(head);
+
+ uiMenuContext(head, WM_OP_EXEC_AREA);
+ uiMenuItemO(head, 0, "WM_OT_save_mainfile");
+ uiMenuContext(head, WM_OP_INVOKE_AREA);
+ uiMenuItemO(head, 0, "WM_OT_save_as_mainfile");
+
+#if 0
+ if(U.flag & USER_FILECOMPRESS) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Compress File", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 35, "Enable file compression");
+ } else {
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Compress File", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 35, "Enable file compression");
+ }
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Rendered Image...|F3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Screenshot Subwindow|Ctrl F3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 24, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Screenshot All|Ctrl Shift F3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 25, "");
+#if GAMEBLENDER == 1
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Game As Runtime...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 22, "");
+#endif
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Default Settings|Ctrl U", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 31, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Load Factory Settings", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 32, "");
+
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Append or Link|Shift F1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Append or Link (Image Browser)|Ctrl F1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+// uiDefIconTextBlockBut(block, info_file_importmenu, NULL, ICON_RIGHTARROW_THIN, "Import", 0, yco-=20, menuwidth, 19, "");
+// uiDefIconTextBlockBut(block, info_file_exportmenu, NULL, ICON_RIGHTARROW_THIN, "Export", 0, yco-=20, menuwidth, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBlockBut(block, info_externalfiles, NULL, ICON_RIGHTARROW_THIN, "External Data",0, yco-=20, 120, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Quit Blender|Ctrl Q", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+ uiBlockSetDirection(block, UI_DOWN);
+ uiTextBoundsBlock(block, 80);
+
+ uiEndBlock(C, block);
+ return block;
+#endif
+}
+
+
+static void do_info_buttons(bContext *C, void *arg, int event)
+{
+ switch(event) {
+ case B_STOPRENDER:
+ G.afbreek= 1;
+ break;
+ case B_STOPCAST:
+ WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C));
+ break;
+ }
+}
+
+static void screen_idpoin_handle(bContext *C, ID *id, int event)
+{
+ switch(event) {
+ case UI_ID_BROWSE:
+ /* exception: can't set screens inside of area/region handers */
+ WM_event_add_notifier(C, NC_SCREEN|ND_SCREENBROWSE, id);
+ break;
+ case UI_ID_DELETE:
+ ED_undo_push(C, "");
+ break;
+ case UI_ID_RENAME:
+ break;
+ case UI_ID_ADD_NEW:
+ /* XXX not implemented */
+ break;
+ case UI_ID_OPEN:
+ /* XXX not implemented */
+ break;
+ case UI_ID_ALONE:
+ /* XXX not implemented */
+ break;
+ case UI_ID_PIN:
+ break;
+ }
+}
+
+static void scene_idpoin_handle(bContext *C, ID *id, int event)
+{
+ switch(event) {
+ case UI_ID_BROWSE:
+ /* exception: can't set screens inside of area/region handers */
+ WM_event_add_notifier(C, NC_SCENE|ND_SCENEBROWSE, id);
+ break;
+ case UI_ID_DELETE:
+ ED_undo_push(C, "");
+ break;
+ case UI_ID_RENAME:
+ break;
+ case UI_ID_ADD_NEW:
+ /* XXX not implemented */
+ break;
+ case UI_ID_OPEN:
+ /* XXX not implemented */
+ break;
+ case UI_ID_ALONE:
+ /* XXX not implemented */
+ break;
+ case UI_ID_PIN:
+ break;
+ }
+}
+
+
+void info_header_buttons(const bContext *C, ARegion *ar)
+{
+ wmWindow *win= CTX_wm_window(C);
+ bScreen *screen= CTX_wm_screen(C);
+ ScrArea *sa= CTX_wm_area(C);
+ uiBlock *block;
+ int xco, yco= 3;
+
+ block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_info_buttons, NULL);
+
+ xco= ED_area_header_standardbuttons(C, block, yco);
+
+ if((sa->flag & HEADER_NO_PULLDOWN)==0) {
+ int xmax;
+
+ xmax= GetButStringLength("File");
+ uiDefMenuBut(block, info_filemenu, NULL, "File", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+
+ xmax= GetButStringLength("Add");
+ uiDefPulldownBut(block, dummy_viewmenu, sa, "Add", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+
+ xmax= GetButStringLength("Timeline");
+ uiDefPulldownBut(block, dummy_viewmenu, sa, "Timeline", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+
+ xmax= GetButStringLength("Game");
+ uiDefPulldownBut(block, dummy_viewmenu, sa, "Game", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+
+ xmax= GetButStringLength("Render");
+ uiDefPulldownBut(block, dummy_viewmenu, sa, "Render", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+
+ xmax= GetButStringLength("Help");
+ uiDefPulldownBut(block, dummy_viewmenu, NULL, "Help", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ if(screen->full==0) {
+ xco= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)win->screen, ID_SCR, NULL, xco, yco,
+ screen_idpoin_handle, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_DELETE);
+ xco += 8;
+ xco= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)screen->scene, ID_SCE, NULL, xco, yco,
+ scene_idpoin_handle, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_DELETE);
+ xco += 8;
+ }
+
+ if(WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C))) {
+ uiDefIconTextBut(block, BUT, B_STOPRENDER, ICON_REC, "Render", xco+5,yco,75,19, NULL, 0.0f, 0.0f, 0, 0, "Stop rendering");
+ xco+= 80;
+ }
+ if(WM_jobs_test(CTX_wm_manager(C), CTX_wm_screen(C))) {
+ uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_REC, "Capture", xco+5,yco,85,19, NULL, 0.0f, 0.0f, 0, 0, "Stop screencast");
+ xco+= 90;
+ }
+
+ /* always as last */
+ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+}
+
+
diff --git a/source/blender/editors/space_info/info_intern.h b/source/blender/editors/space_info/info_intern.h
new file mode 100644
index 00000000000..213c0688f20
--- /dev/null
+++ b/source/blender/editors/space_info/info_intern.h
@@ -0,0 +1,39 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_INFO_INTERN_H
+#define ED_INFO_INTERN_H
+
+/* internal exports only */
+
+
+/* info_header.c */
+void info_header_buttons(const bContext *C, ARegion *ar);
+
+
+#endif /* ED_INFO_INTERN_H */
+
diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c
new file mode 100644
index 00000000000..66d807eb69c
--- /dev/null
+++ b/source/blender/editors/space_info/space_info.c
@@ -0,0 +1,283 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_context.h"
+#include "BKE_colortools.h"
+#include "BKE_screen.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "BIF_gl.h"
+#include "BLF_api.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_markers.h"
+
+#include "info_intern.h" // own include
+
+/* ******************** default callbacks for info space ***************** */
+
+static SpaceLink *info_new(const bContext *C)
+{
+ ARegion *ar;
+ SpaceInfo *sinfo;
+
+ sinfo= MEM_callocN(sizeof(SpaceInfo), "initinfo");
+ sinfo->spacetype= SPACE_INFO;
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for info");
+
+ BLI_addtail(&sinfo->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_BOTTOM;
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for info");
+
+ BLI_addtail(&sinfo->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+
+ /* channel list region XXX */
+
+
+ return (SpaceLink *)sinfo;
+}
+
+/* not spacelink itself */
+static void info_free(SpaceLink *sl)
+{
+// SpaceInfo *sinfo= (SpaceInfo*) sl;
+
+}
+
+
+/* spacetype; init callback */
+static void info_init(struct wmWindowManager *wm, ScrArea *sa)
+{
+
+}
+
+static SpaceLink *info_duplicate(SpaceLink *sl)
+{
+ SpaceInfo *sinfon= MEM_dupallocN(sl);
+
+ /* clear or remove stuff from old */
+
+ return (SpaceLink *)sinfon;
+}
+
+
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void info_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "info", SPACE_INFO, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+static void info_main_area_draw(const bContext *C, ARegion *ar)
+{
+ /* draw entirely, view changes should be handled here */
+ // SpaceInfo *sinfo= (SpaceInfo*)CTX_wm_space_data(C);
+ View2D *v2d= &ar->v2d;
+ float col[3];
+ float width, height;
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ UI_view2d_view_ortho(C, v2d);
+
+ /* data... */
+ // XXX 2.50 Testing new font library - Diego
+ glColor3f(1.0, 0.0, 0.0);
+ BLF_aspect(1.0);
+
+ BLF_size(14, 96);
+ BLF_position(5.0, 5.0, 0.0);
+
+ width= BLF_width("Hello Blender, size 14, dpi 96");
+ height= BLF_height("Hello Blender, size 14, dpi 96");
+
+ glRectf(7.0, 20.0, 7.0+width, 20.0+height);
+ glRectf(5.0+width+10.0, 3.0, 5.0+width+10.0+width, 3.0+height);
+ BLF_draw("Hello Blender, size 14, dpi 96");
+
+ glColor3f(0.0, 0.0, 1.0);
+ BLF_size(11, 96);
+ BLF_position(200.0, 50.0, 0.0);
+ BLF_enable(BLF_ROTATION);
+ BLF_rotation(45.0f);
+ BLF_draw("Another Hello Blender, size 11 and dpi 96!!");
+
+ glColor3f(0.8, 0.0, 0.7);
+ BLF_size(12, 72);
+ BLF_position(200.0, 100.0, 0.0);
+ BLF_rotation(180.0f);
+ BLF_draw("Hello World, size 12, dpi 72");
+
+ glColor3f(0.8, 0.7, 0.5);
+ BLF_size(12, 96);
+ BLF_position(5.0, 200.0, 0.0);
+ BLF_disable(BLF_ROTATION);
+ BLF_draw("And this make a new glyph cache!!");
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers? */
+}
+
+void info_operatortypes(void)
+{
+
+}
+
+void info_keymap(struct wmWindowManager *wm)
+{
+
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void info_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+}
+
+static void info_header_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ /* clear */
+ if(ED_screen_area_active(C))
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ else
+ UI_GetThemeColor3fv(TH_HEADERDESEL, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ info_header_buttons(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+static void info_main_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+}
+
+static void info_header_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCREEN:
+ if(wmn->data==ND_SCREENCAST)
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_SCENE:
+ if(wmn->data==ND_RENDER_RESULT)
+ ED_region_tag_redraw(ar);
+ break;
+ }
+
+}
+
+/* only called once, from space/spacetypes.c */
+void ED_spacetype_info(void)
+{
+ SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype info");
+ ARegionType *art;
+
+ st->spaceid= SPACE_INFO;
+
+ st->new= info_new;
+ st->free= info_free;
+ st->init= info_init;
+ st->duplicate= info_duplicate;
+ st->operatortypes= info_operatortypes;
+ st->keymap= info_keymap;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype info region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init= info_main_area_init;
+ art->draw= info_main_area_draw;
+ art->listener= info_main_area_listener;
+ art->keymapflag= ED_KEYMAP_VIEW2D;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype info region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+ art->listener= info_header_listener;
+ art->init= info_header_area_init;
+ art->draw= info_header_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+
+ BKE_spacetype_register(st);
+}
+
diff --git a/source/blender/editors/space_nla/Makefile b/source/blender/editors/space_nla/Makefile
new file mode 100644
index 00000000000..43f010e6adc
--- /dev/null
+++ b/source/blender/editors/space_nla/Makefile
@@ -0,0 +1,54 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_nla
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/space_nla/SConscript b/source/blender/editors/space_nla/SConscript
new file mode 100644
index 00000000000..790e3ad822c
--- /dev/null
+++ b/source/blender/editors/space_nla/SConscript
@@ -0,0 +1,9 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+
+env.BlenderLib ( 'bf_editors_space_nla', sources, Split(incs), [], libtype=['core'], priority=[85] )
diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c
new file mode 100644
index 00000000000..0f6b77da6f5
--- /dev/null
+++ b/source/blender/editors/space_nla/nla_header.c
@@ -0,0 +1,130 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "nla_intern.h"
+
+
+/* ************************ header area region *********************** */
+
+static void do_viewmenu(bContext *C, void *arg, int event)
+{
+
+}
+
+static uiBlock *dummy_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "dummy_viewmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_viewmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static void do_nla_buttons(bContext *C, void *arg, int event)
+{
+ switch(event) {
+ }
+}
+
+
+void nla_header_buttons(const bContext *C, ARegion *ar)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ uiBlock *block;
+ int xco, yco= 3;
+
+ block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_nla_buttons, NULL);
+
+ xco= ED_area_header_standardbuttons(C, block, yco);
+
+ if((sa->flag & HEADER_NO_PULLDOWN)==0) {
+ int xmax;
+
+ xmax= GetButStringLength("View");
+ uiDefPulldownBut(block, dummy_viewmenu, CTX_wm_area(C),
+ "View", xco, yco-2, xmax-3, 24, "");
+ xco+=XIC+xmax;
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ /* always as last */
+ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+}
+
+
diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h
new file mode 100644
index 00000000000..c544bd9a408
--- /dev/null
+++ b/source/blender/editors/space_nla/nla_intern.h
@@ -0,0 +1,39 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_NLA_INTERN_H
+#define ED_NLA_INTERN_H
+
+/* internal exports only */
+
+
+/* nla_header.c */
+void nla_header_buttons(const bContext *C, ARegion *ar);
+
+
+#endif /* ED_NLA_INTERN_H */
+
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
new file mode 100644
index 00000000000..6e1a97dea34
--- /dev/null
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -0,0 +1,297 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_nla_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_markers.h"
+
+#include "nla_intern.h" // own include
+
+/* ******************** default callbacks for nla space ***************** */
+
+static SpaceLink *nla_new(const bContext *C)
+{
+ ARegion *ar;
+ SpaceNla *snla;
+
+ snla= MEM_callocN(sizeof(SpaceNla), "initnla");
+ snla->spacetype= SPACE_NLA;
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for nla");
+
+ BLI_addtail(&snla->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_BOTTOM;
+
+ /* channel list region XXX */
+ ar= MEM_callocN(sizeof(ARegion), "area region from do_versions");
+ BLI_addtail(&snla->regionbase, ar);
+ ar->regiontype= RGN_TYPE_CHANNELS;
+ ar->alignment= RGN_ALIGN_LEFT;
+
+ ar->v2d.scroll = (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM);
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for nla");
+
+ BLI_addtail(&snla->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+
+ ar->v2d.tot.xmin= 1.0f;
+ ar->v2d.tot.ymin= 0.0f;
+ ar->v2d.tot.xmax= 1000.0f;
+ ar->v2d.tot.ymax= 1000.0f;
+
+ ar->v2d.cur.xmin= -5.0f;
+ ar->v2d.cur.ymin= 0.0f;
+ ar->v2d.cur.xmax= 65.0f;
+ ar->v2d.cur.ymax= 1000.0f;
+
+ ar->v2d.min[0]= 0.0f;
+ ar->v2d.min[1]= 0.0f;
+
+ ar->v2d.max[0]= MAXFRAMEF;
+ ar->v2d.max[1]= 1000.0f;
+
+ ar->v2d.minzoom= 0.1f;
+ ar->v2d.maxzoom= 50.0f;
+
+ ar->v2d.scroll |= (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
+ ar->v2d.keepzoom= V2D_LOCKZOOM_Y;
+
+
+ return (SpaceLink *)snla;
+}
+
+/* not spacelink itself */
+static void nla_free(SpaceLink *sl)
+{
+// SpaceNla *snla= (SpaceNla*) sl;
+
+}
+
+
+/* spacetype; init callback */
+static void nla_init(struct wmWindowManager *wm, ScrArea *sa)
+{
+
+}
+
+static SpaceLink *nla_duplicate(SpaceLink *sl)
+{
+ SpaceNla *snlan= MEM_dupallocN(sl);
+
+ /* clear or remove stuff from old */
+
+ return (SpaceLink *)snlan;
+}
+
+static void nla_channel_area_draw(const bContext *C, ARegion *ar)
+{
+ /* draw entirely, view changes should be handled here */
+ // SpaceNla *snla= (SpaceNla*)CTX_wm_space_data(C);
+ // View2D *v2d= &ar->v2d;
+ float col[3];
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ // UI_view2d_view_ortho(C, v2d);
+
+ /* data... */
+
+
+ /* reset view matrix */
+ //UI_view2d_view_restore(C);
+
+ /* scrollers? */
+}
+
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void nla_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "NLA", SPACE_NLA, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+static void nla_main_area_draw(const bContext *C, ARegion *ar)
+{
+ /* draw entirely, view changes should be handled here */
+ // SpaceNla *snla= (SpaceNla*)CTX_wm_space_data(C);
+ View2D *v2d= &ar->v2d;
+ float col[3];
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ UI_view2d_view_ortho(C, v2d);
+
+ /* data... */
+
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers? */
+}
+
+void nla_operatortypes(void)
+{
+
+}
+
+void nla_keymap(struct wmWindowManager *wm)
+{
+
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void nla_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+}
+
+static void nla_header_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ /* clear */
+ if(ED_screen_area_active(C))
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ else
+ UI_GetThemeColor3fv(TH_HEADERDESEL, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ nla_header_buttons(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+static void nla_main_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+}
+
+/* only called once, from space/spacetypes.c */
+void ED_spacetype_nla(void)
+{
+ SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype nla");
+ ARegionType *art;
+
+ st->spaceid= SPACE_NLA;
+
+ st->new= nla_new;
+ st->free= nla_free;
+ st->init= nla_init;
+ st->duplicate= nla_duplicate;
+ st->operatortypes= nla_operatortypes;
+ st->keymap= nla_keymap;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype nla region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init= nla_main_area_init;
+ art->draw= nla_main_area_draw;
+ art->listener= nla_main_area_listener;
+ art->keymapflag= ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype nla region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+
+ art->init= nla_header_area_init;
+ art->draw= nla_header_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: channels */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype nla region");
+ art->regionid = RGN_TYPE_CHANNELS;
+ art->minsizex= 200;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+
+ //art->init= nla_channel_area_init;
+ art->draw= nla_channel_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+
+ BKE_spacetype_register(st);
+}
+
diff --git a/source/blender/editors/space_node/Makefile b/source/blender/editors/space_node/Makefile
new file mode 100644
index 00000000000..233572dbfb1
--- /dev/null
+++ b/source/blender/editors/space_node/Makefile
@@ -0,0 +1,57 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_node
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_BMFONT)/include
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../nodes
+CPPFLAGS += -I../../render/extern/include
+CPPFLAGS += -I../../python
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/space_node/SConscript b/source/blender/editors/space_node/SConscript
new file mode 100644
index 00000000000..babd8dc9080
--- /dev/null
+++ b/source/blender/editors/space_node/SConscript
@@ -0,0 +1,18 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf'
+incs += ' ../../nodes #intern/bmfont ../../render/extern/include'
+incs += ' ../../windowmanager #intern/guardedalloc #extern/glew/include'
+defs = []
+cf = []
+if env['OURPLATFORM'] == 'win32-vc':
+ #cf.append('/WX')
+ pass
+if env['CC'] == 'gcc':
+ #cf.append('-Werror')
+ pass
+
+env.BlenderLib ( 'bf_editors_space_node', sources, Split(incs), defs, libtype=['core'], priority=[55], compileflags=cf )
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
new file mode 100644
index 00000000000..25693009bf2
--- /dev/null
+++ b/source/blender/editors/space_node/drawnode.c
@@ -0,0 +1,2691 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): David Millan Escriva, Juho Vepsäläinen
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_ID.h"
+#include "DNA_node_types.h"
+#include "DNA_image_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_action_types.h"
+#include "DNA_color_types.h"
+#include "DNA_customdata_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_text_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_texture.h"
+#include "BKE_text.h"
+#include "BKE_utildefines.h"
+
+#include "CMP_node.h"
+#include "SHD_node.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "BMF_Api.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "ED_node.h"
+#include "ED_space_api.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_view2d.h"
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "RE_pipeline.h"
+#include "IMB_imbuf_types.h"
+
+#include "node_intern.h"
+
+
+/* autocomplete callback for buttons */
+static void autocomplete_vcol(bContext *C, char *str, void *arg_v)
+{
+ Mesh *me;
+ CustomDataLayer *layer;
+ AutoComplete *autocpl;
+ int a;
+
+ if(str[0]==0)
+ return;
+
+ autocpl= autocomplete_begin(str, 32);
+
+ /* search if str matches the beginning of name */
+ for(me= G.main->mesh.first; me; me=me->id.next)
+ for(a=0, layer= me->fdata.layers; a<me->fdata.totlayer; a++, layer++)
+ if(layer->type == CD_MCOL)
+ autocomplete_do_name(autocpl, layer->name);
+
+ autocomplete_end(autocpl, str);
+}
+
+static int verify_valid_vcol_name(char *str)
+{
+ Mesh *me;
+ CustomDataLayer *layer;
+ int a;
+
+ if(str[0]==0)
+ return 1;
+
+ /* search if str matches the name */
+ for(me= G.main->mesh.first; me; me=me->id.next)
+ for(a=0, layer= me->fdata.layers; a<me->fdata.totlayer; a++, layer++)
+ if(layer->type == CD_MCOL)
+ if(strcmp(layer->name, str)==0)
+ return 1;
+
+ return 0;
+}
+
+/* ****************** GENERAL CALLBACKS FOR NODES ***************** */
+
+static void node_ID_title_cb(bContext *C, void *node_v, void *unused_v)
+{
+ bNode *node= node_v;
+
+ if(node->id) {
+ test_idbutton(node->id->name+2); /* library.c, verifies unique name */
+ BLI_strncpy(node->name, node->id->name+2, 21);
+ }
+}
+
+
+static void node_but_title_cb(bContext *C, void *node_v, void *but_v)
+{
+ // bNode *node= node_v;
+ // XXX uiBut *bt= but_v;
+ // XXX BLI_strncpy(node->name, bt->drawstr, NODE_MAXSTR);
+
+ // allqueue(REDRAWNODE, 0);
+}
+
+#if 0
+/* XXX not used yet, make compiler happy :) */
+static void node_group_alone_cb(bContext *C, void *node_v, void *unused_v)
+{
+ bNode *node= node_v;
+
+ nodeCopyGroup(node);
+
+ // allqueue(REDRAWNODE, 0);
+}
+
+/* ****************** BUTTON CALLBACKS FOR ALL TREES ***************** */
+
+static int node_buts_group(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block && node->id) {
+ uiBut *bt;
+ short width;
+
+ uiBlockBeginAlign(block);
+
+ /* name button */
+ width= (short)(butr->xmax-butr->xmin - (node->id->us>1?19.0f:0.0f));
+ bt= uiDefBut(block, TEX, B_NOP, "NT:",
+ (short)butr->xmin, (short)butr->ymin, width, 19,
+ node->id->name+2, 0.0, 19.0, 0, 0, "NodeTree name");
+ uiButSetFunc(bt, node_ID_title_cb, node, NULL);
+
+ /* user amount */
+ if(node->id->us>1) {
+ char str1[32];
+ sprintf(str1, "%d", node->id->us);
+ bt= uiDefBut(block, BUT, B_NOP, str1,
+ (short)butr->xmax-19, (short)butr->ymin, 19, 19,
+ NULL, 0, 0, 0, 0, "Displays number of users.");
+ uiButSetFunc(bt, node_group_alone_cb, node, NULL);
+ }
+
+ uiBlockEndAlign(block);
+ }
+ return 19;
+}
+#endif
+
+static int node_buts_value(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ bNodeSocket *sock= node->outputs.first; /* first socket stores value */
+
+ uiDefButF(block, NUM, B_NODE_EXEC, "",
+ (short)butr->xmin, (short)butr->ymin, butr->xmax-butr->xmin, 20,
+ sock->ns.vec, sock->ns.min, sock->ns.max, 10, 2, "");
+
+ }
+ return 20;
+}
+
+static int node_buts_rgb(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ bNodeSocket *sock= node->outputs.first; /* first socket stores value */
+ if(sock) {
+ /* enforce square box drawing */
+ uiBlockSetEmboss(block, UI_EMBOSSP);
+
+ uiDefButF(block, HSVCUBE, B_NODE_EXEC, "",
+ (short)butr->xmin, (short)butr->ymin, butr->xmax-butr->xmin, 12,
+ sock->ns.vec, 0.0f, 1.0f, 3, 0, "");
+ uiDefButF(block, HSVCUBE, B_NODE_EXEC, "",
+ (short)butr->xmin, (short)butr->ymin+15, butr->xmax-butr->xmin, butr->ymax-butr->ymin -15 -15,
+ sock->ns.vec, 0.0f, 1.0f, 2, 0, "");
+ uiDefButF(block, COL, B_NOP, "",
+ (short)butr->xmin, (short)butr->ymax-12, butr->xmax-butr->xmin, 12,
+ sock->ns.vec, 0.0, 0.0, -1, 0, "");
+ /* the -1 above prevents col button to popup a color picker */
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ }
+ }
+ return 30 + (int)(node->width-NODE_DY);
+}
+
+static int node_buts_mix_rgb(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ uiBut *bt;
+ int a_but= (ntree->type==NTREE_COMPOSIT);
+
+ /* blend type */
+ uiBlockBeginAlign(block);
+ bt=uiDefButS(block, MENU, B_NODE_EXEC, "Mix %x0|Add %x1|Subtract %x3|Multiply %x2|Screen %x4|Overlay %x9|Divide %x5|Difference %x6|Darken %x7|Lighten %x8|Dodge %x10|Burn %x11|Color %x15|Value %x14|Saturation %x13|Hue %x12",
+ (short)butr->xmin, (short)butr->ymin, butr->xmax-butr->xmin -(a_but?20:0), 20,
+ &node->custom1, 0, 0, 0, 0, "");
+ uiButSetFunc(bt, node_but_title_cb, node, bt);
+ /* Alpha option, composite */
+ if(a_but)
+ uiDefButS(block, TOG, B_NODE_EXEC, "A",
+ (short)butr->xmax-20, (short)butr->ymin, 20, 20,
+ &node->custom2, 0, 0, 0, 0, "Include Alpha of 2nd input in this operation");
+ }
+ return 20;
+}
+
+static int node_buts_time(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ CurveMapping *cumap= node->storage;
+ short dx= (short)((butr->xmax-butr->xmin)/2);
+ butr->ymin += 26;
+
+ curvemap_buttons(block, node->storage, 's', B_NODE_EXEC, B_REDR, butr);
+
+ if(cumap) {
+ //cumap->flag |= CUMA_DRAW_CFRA;
+ //if(node->custom1<node->custom2)
+ // cumap->sample[0]= (float)(CFRA - node->custom1)/(float)(node->custom2-node->custom1);
+ }
+
+ uiBlockBeginAlign(block);
+ uiDefButS(block, NUM, B_NODE_EXEC, "Sta:",
+ (short)butr->xmin, (short)butr->ymin-22, dx, 19,
+ &node->custom1, 1.0, 20000.0, 0, 0, "Start frame");
+ uiDefButS(block, NUM, B_NODE_EXEC, "End:",
+ (short)butr->xmin+dx, (short)butr->ymin-22, dx, 19,
+ &node->custom2, 1.0, 20000.0, 0, 0, "End frame");
+ }
+
+ return node->width-NODE_DY;
+}
+
+static int node_buts_valtorgb(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ if(node->storage) {
+ ; // XXX draw_colorband_buts_small(block, node->storage, butr, B_NODE_EXEC);
+ }
+ }
+ return 40;
+}
+
+static int node_buts_curvevec(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ curvemap_buttons(block, node->storage, 'v', B_NODE_EXEC, B_REDR, butr);
+ }
+ return (int)(node->width-NODE_DY);
+}
+
+static float *_sample_col= NULL; // bad bad, 2.5 will do better?
+void node_curvemap_sample(float *col)
+{
+ _sample_col= col;
+}
+
+static int node_buts_curvecol(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ CurveMapping *cumap= node->storage;
+ if(_sample_col) {
+ cumap->flag |= CUMA_DRAW_SAMPLE;
+ VECCOPY(cumap->sample, _sample_col);
+ }
+ else
+ cumap->flag &= ~CUMA_DRAW_SAMPLE;
+
+ curvemap_buttons(block, node->storage, 'c', B_NODE_EXEC, B_REDR, butr);
+ }
+ return (int)(node->width-NODE_DY);
+}
+
+static int node_buts_normal(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ bNodeSocket *sock= node->outputs.first; /* first socket stores normal */
+
+ uiDefButF(block, BUT_NORMAL, B_NODE_EXEC, "",
+ (short)butr->xmin, (short)butr->ymin, butr->xmax-butr->xmin, butr->ymax-butr->ymin,
+ sock->ns.vec, 0.0f, 1.0f, 0, 0, "");
+
+ }
+ return (int)(node->width-NODE_DY);
+}
+
+static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v)
+{
+ bNodeTree *ntree= ntree_v;
+ bNode *node= node_v;
+ Tex *tex;
+
+ if(node->menunr<1) return;
+
+ if(node->id) {
+ node->id->us--;
+ node->id= NULL;
+ }
+ tex= BLI_findlink(&G.main->tex, node->menunr-1);
+
+ node->id= &tex->id;
+ id_us_plus(node->id);
+ BLI_strncpy(node->name, node->id->name+2, 21);
+
+ nodeSetActive(ntree, node);
+
+ if( ntree->type == NTREE_TEXTURE )
+ ntreeTexCheckCyclics( ntree );
+
+ // allqueue(REDRAWBUTSSHADING, 0);
+ // allqueue(REDRAWNODE, 0);
+ NodeTagChanged(ntree, node);
+
+ node->menunr= 0;
+}
+
+static void node_dynamic_update_cb(bContext *C, void *ntree_v, void *node_v)
+{
+ Material *ma;
+ bNode *node= (bNode *)node_v;
+ ID *id= node->id;
+ int error= 0;
+
+ if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) error= 1;
+
+ /* Users only have to press the "update" button in one pynode
+ * and we also update all others sharing the same script */
+ for (ma= G.main->mat.first; ma; ma= ma->id.next) {
+ if (ma->nodetree) {
+ bNode *nd;
+ for (nd= ma->nodetree->nodes.first; nd; nd= nd->next) {
+ if ((nd->type == NODE_DYNAMIC) && (nd->id == id)) {
+ nd->custom1= 0;
+ nd->custom1= BSET(nd->custom1, NODE_DYNAMIC_REPARSE);
+ nd->menunr= 0;
+ if (error)
+ nd->custom1= BSET(nd->custom1, NODE_DYNAMIC_ERROR);
+ }
+ }
+ }
+ }
+
+ // allqueue(REDRAWBUTSSHADING, 0);
+ // allqueue(REDRAWNODE, 0);
+ // XXX BIF_preview_changed(ID_MA);
+}
+
+static int node_buts_texture(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ short multi = (
+ node->id &&
+ ((Tex*)node->id)->use_nodes &&
+ (node->type != CMP_NODE_TEXTURE) &&
+ (node->type != TEX_NODE_TEXTURE)
+ );
+
+ if(block) {
+ uiBut *bt;
+ char *strp;
+ short width = (short)(butr->xmax - butr->xmin);
+
+ /* browse button texture */
+ uiBlockBeginAlign(block);
+ IDnames_to_pupstring(&strp, NULL, "", &(G.main->tex), NULL, NULL);
+ node->menunr= 0;
+ bt= uiDefButS(block, MENU, B_NODE_EXEC, strp,
+ butr->xmin, butr->ymin+(multi?30:0), 20, 19,
+ &node->menunr, 0, 0, 0, 0, "Browse texture");
+ uiButSetFunc(bt, node_browse_tex_cb, ntree, node);
+ if(strp) MEM_freeN(strp);
+
+ if(node->id) {
+ bt= uiDefBut(block, TEX, B_NOP, "TE:",
+ butr->xmin+19, butr->ymin+(multi?30:0), butr->xmax-butr->xmin-19, 19,
+ node->id->name+2, 0.0, 19.0, 0, 0, "Texture name");
+ uiButSetFunc(bt, node_ID_title_cb, node, NULL);
+ }
+ uiBlockEndAlign(block);
+
+ if(multi) {
+ char *menustr = ntreeTexOutputMenu(((Tex*)node->id)->nodetree);
+ uiDefButS(block, MENU, B_MATPRV, menustr, butr->xmin, butr->ymin, width, 19, &node->custom1, 0, 0, 0, 0, "Which output to use, for multi-output textures");
+ free(menustr);
+ return 50;
+ }
+ return 20;
+ }
+ else return multi? 50: 20;
+}
+
+static int node_buts_math(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ uiBut *bt;
+
+ bt=uiDefButS(block, MENU, B_NODE_EXEC, "Add %x0|Subtract %x1|Multiply %x2|Divide %x3|Sine %x4|Cosine %x5|Tangent %x6|Arcsine %x7|Arccosine %x8|Arctangent %x9|Power %x10|Logarithm %x11|Minimum %x12|Maximum %x13|Round %x14|Less Than %x15|Greater Than %x16", butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, &node->custom1, 0, 0, 0, 0, "");
+ uiButSetFunc(bt, node_but_title_cb, node, bt);
+ }
+ return 20;
+}
+
+
+/* ****************** BUTTON CALLBACKS FOR SHADER NODES ***************** */
+
+static void node_browse_text_cb(bContext *C, void *ntree_v, void *node_v)
+{
+ bNodeTree *ntree= ntree_v;
+ bNode *node= node_v;
+ ID *oldid;
+
+ if(node->menunr<1) return;
+
+ if(node->id) {
+ node->id->us--;
+ }
+ oldid= node->id;
+ node->id= BLI_findlink(&G.main->text, node->menunr-1);
+ id_us_plus(node->id);
+ BLI_strncpy(node->name, node->id->name+2, 21); /* huh? why 21? */
+
+ node->custom1= BSET(node->custom1, NODE_DYNAMIC_NEW);
+
+ nodeSetActive(ntree, node);
+
+ // allqueue(REDRAWBUTSSHADING, 0);
+ // allqueue(REDRAWNODE, 0);
+
+ node->menunr= 0;
+}
+
+static void node_mat_alone_cb(bContext *C, void *node_v, void *unused)
+{
+ bNode *node= node_v;
+
+ node->id= (ID *)copy_material((Material *)node->id);
+
+ //BIF_undo_push("Single user material");
+ // allqueue(REDRAWBUTSSHADING, 0);
+ // allqueue(REDRAWNODE, 0);
+ // allqueue(REDRAWOOPS, 0);
+}
+
+static void node_browse_mat_cb(bContext *C, void *ntree_v, void *node_v)
+{
+ bNodeTree *ntree= ntree_v;
+ bNode *node= node_v;
+
+ if(node->menunr<1) return;
+
+ if(node->menunr==32767) { /* code for Add New */
+ if(node->id) {
+ /* make copy, but make sure it doesnt have the node tag nor nodes */
+ Material *ma= (Material *)node->id;
+ ma->id.us--;
+ ma= copy_material(ma);
+ ma->use_nodes= 0;
+ if(ma->nodetree) {
+ ntreeFreeTree(ma->nodetree);
+ MEM_freeN(ma->nodetree);
+ }
+ ma->nodetree= NULL;
+ node->id= (ID *)ma;
+ }
+ else node->id= (ID *)add_material("MatNode");
+ }
+ else {
+ if(node->id) node->id->us--;
+ node->id= BLI_findlink(&G.main->mat, node->menunr-1);
+ id_us_plus(node->id);
+ }
+ BLI_strncpy(node->name, node->id->name+2, 21);
+
+ nodeSetActive(ntree, node);
+
+ // allqueue(REDRAWBUTSSHADING, 0);
+ // allqueue(REDRAWNODE, 0);
+ // XXX BIF_preview_changed(ID_MA);
+
+ node->menunr= 0;
+}
+
+static void node_new_mat_cb(bContext *C, void *ntree_v, void *node_v)
+{
+ bNodeTree *ntree= ntree_v;
+ bNode *node= node_v;
+
+ node->id= (ID *)add_material("MatNode");
+ BLI_strncpy(node->name, node->id->name+2, 21);
+
+ nodeSetActive(ntree, node);
+
+ // allqueue(REDRAWBUTSSHADING, 0);
+ // allqueue(REDRAWNODE, 0);
+ // XXX BIF_preview_changed(ID_MA);
+
+}
+
+static void node_texmap_cb(bContext *C, void *texmap_v, void *unused_v)
+{
+ init_mapping(texmap_v);
+}
+
+static int node_shader_buts_material(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ uiBut *bt;
+ short dx= (short)((butr->xmax-butr->xmin)/3.0f), has_us= (node->id && node->id->us>1);
+ short dy= (short)butr->ymin;
+ char *strp;
+
+ /* WATCH IT: we use this callback in material buttons, but then only want first row */
+ if(butr->ymax-butr->ymin > 21.0f) dy+= 19;
+
+ uiBlockBeginAlign(block);
+ /* XXX
+ if(node->id==NULL) uiBlockSetCol(block, TH_REDALERT);
+ else if(has_us) uiBlockSetCol(block, TH_BUT_SETTING1);
+ else uiBlockSetCol(block, TH_BUT_SETTING2);
+ */
+
+ /* browse button */
+ IDnames_to_pupstring(&strp, NULL, "ADD NEW %x32767", &(G.main->mat), NULL, NULL);
+ node->menunr= 0;
+ bt= uiDefButS(block, MENU, B_NOP, strp,
+ butr->xmin, dy, 19, 19,
+ &node->menunr, 0, 0, 0, 0, "Browses existing choices or adds NEW");
+ uiButSetFunc(bt, node_browse_mat_cb, ntree, node);
+ if(strp) MEM_freeN(strp);
+
+ /* Add New button */
+ if(node->id==NULL) {
+ bt= uiDefBut(block, BUT, B_NOP, "Add New",
+ butr->xmin+19, dy, (short)(butr->xmax-butr->xmin-19.0f), 19,
+ NULL, 0.0, 0.0, 0, 0, "Add new Material");
+ uiButSetFunc(bt, node_new_mat_cb, ntree, node);
+ }
+ else {
+ /* name button */
+ short width= (short)(butr->xmax-butr->xmin-19.0f - (has_us?19.0f:0.0f));
+ bt= uiDefBut(block, TEX, B_NOP, "MA:",
+ butr->xmin+19, dy, width, 19,
+ node->id->name+2, 0.0, 19.0, 0, 0, "Material name");
+ uiButSetFunc(bt, node_ID_title_cb, node, NULL);
+
+ /* user amount */
+ if(has_us) {
+ char str1[32];
+ sprintf(str1, "%d", node->id->us);
+ bt= uiDefBut(block, BUT, B_NOP, str1,
+ butr->xmax-19, dy, 19, 19,
+ NULL, 0, 0, 0, 0, "Displays number of users. Click to make a single-user copy.");
+ uiButSetFunc(bt, node_mat_alone_cb, node, NULL);
+ }
+
+ /* WATCH IT: we use this callback in material buttons, but then only want first row */
+ if(butr->ymax-butr->ymin > 21.0f) {
+ /* node options */
+ uiDefButBitS(block, TOG, SH_NODE_MAT_DIFF, B_NODE_EXEC, "Diff",
+ butr->xmin, butr->ymin, dx, 19,
+ &node->custom1, 0, 0, 0, 0, "Material Node outputs Diffuse");
+ uiDefButBitS(block, TOG, SH_NODE_MAT_SPEC, B_NODE_EXEC, "Spec",
+ butr->xmin+dx, butr->ymin, dx, 19,
+ &node->custom1, 0, 0, 0, 0, "Material Node outputs Specular");
+ uiDefButBitS(block, TOG, SH_NODE_MAT_NEG, B_NODE_EXEC, "Neg Normal",
+ butr->xmax-dx, butr->ymin, dx, 19,
+ &node->custom1, 0, 0, 0, 0, "Material Node uses inverted Normal");
+ }
+ }
+ uiBlockEndAlign(block);
+ }
+ return 38;
+}
+
+static int node_shader_buts_mapping(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ TexMapping *texmap= node->storage;
+ short dx= (short)((butr->xmax-butr->xmin)/7.0f);
+ short dy= (short)(butr->ymax-19);
+
+ uiBlockSetFunc(block, node_texmap_cb, texmap, NULL); /* all buttons get this */
+
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->loc, -1000.0f, 1000.0f, 10, 2, "");
+ uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->loc+1, -1000.0f, 1000.0f, 10, 2, "");
+ uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->loc+2, -1000.0f, 1000.0f, 10, 2, "");
+ dy-= 19;
+ uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->rot, -1000.0f, 1000.0f, 1000, 1, "");
+ uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->rot+1, -1000.0f, 1000.0f, 1000, 1, "");
+ uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->rot+2, -1000.0f, 1000.0f, 1000, 1, "");
+ dy-= 19;
+ uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->size, -1000.0f, 1000.0f, 10, 2, "");
+ uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->size+1, -1000.0f, 1000.0f, 10, 2, "");
+ uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->size+2, -1000.0f, 1000.0f, 10, 2, "");
+ dy-= 25;
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->min, -10.0f, 10.0f, 100, 2, "");
+ uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->min+1, -10.0f, 10.0f, 100, 2, "");
+ uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->min+2, -10.0f, 10.0f, 100, 2, "");
+ dy-= 19;
+ uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->max, -10.0f, 10.0f, 10, 2, "");
+ uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->max+1, -10.0f, 10.0f, 10, 2, "");
+ uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->max+2, -10.0f, 10.0f, 10, 2, "");
+ uiBlockEndAlign(block);
+
+ /* labels/options */
+
+ dy= (short)(butr->ymax-19);
+ uiDefBut(block, LABEL, B_NOP, "Loc", butr->xmin, dy, dx, 19, NULL, 0.0f, 0.0f, 0, 0, "");
+ dy-= 19;
+ uiDefBut(block, LABEL, B_NOP, "Rot", butr->xmin, dy, dx, 19, NULL, 0.0f, 0.0f, 0, 0, "");
+ dy-= 19;
+ uiDefBut(block, LABEL, B_NOP, "Size", butr->xmin, dy, dx, 19, NULL, 0.0f, 0.0f, 0, 0, "");
+ dy-= 25;
+ uiDefButBitI(block, TOG, TEXMAP_CLIP_MIN, B_NODE_EXEC, "Min", butr->xmin, dy, dx-4, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, "");
+ dy-= 19;
+ uiDefButBitI(block, TOG, TEXMAP_CLIP_MAX, B_NODE_EXEC, "Max", butr->xmin, dy, dx-4, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, "");
+
+ }
+ return 5*19 + 6;
+}
+
+static int node_shader_buts_vect_math(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ uiBut *bt;
+
+ bt=uiDefButS(block, MENU, B_NODE_EXEC, "Add %x0|Subtract %x1|Average %x2|Dot Product %x3 |Cross Product %x4|Normalize %x5", butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, &node->custom1, 0, 0, 0, 0, "");
+ uiButSetFunc(bt, node_but_title_cb, node, bt);
+ }
+ return 20;
+}
+
+static int node_shader_buts_geometry(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ uiBut *but;
+ NodeGeometry *ngeo= (NodeGeometry*)node->storage;
+
+ // XXX if(!verify_valid_uv_name(ngeo->uvname))
+ // XXX uiBlockSetCol(block, TH_REDALERT);
+ but= uiDefBut(block, TEX, B_NODE_EXEC, "UV:", butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20, ngeo->uvname, 0, 31, 0, 0, "Set name of UV layer to use, default is active UV layer");
+ // XXX uiButSetCompleteFunc(but, autocomplete_uv, NULL);
+
+ if(!verify_valid_vcol_name(ngeo->colname));
+// uiBlockSetCol(block, TH_REDALERT);
+ but= uiDefBut(block, TEX, B_NODE_EXEC, "Col:", butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, ngeo->colname, 0, 31, 0, 0, "Set name of vertex color layer to use, default is active vertex color layer");
+ uiButSetCompleteFunc(but, autocomplete_vcol, NULL);
+ }
+
+ return 40;
+}
+
+static int node_shader_buts_dynamic(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if (block) {
+ uiBut *bt;
+ // XXX SpaceNode *snode= curarea->spacedata.first;
+ short dy= (short)butr->ymin;
+ int xoff=0;
+
+ /* B_NODE_EXEC is handled in butspace.c do_node_buts */
+ if(!node->id) {
+ char *strp;
+ IDnames_to_pupstring(&strp, NULL, "", &(G.main->text), NULL, NULL);
+ node->menunr= 0;
+ bt= uiDefButS(block, MENU, B_NODE_EXEC/*+node->nr*/, strp,
+ butr->xmin, dy, 19, 19,
+ &node->menunr, 0, 0, 0, 0, "Browses existing choices");
+ uiButSetFunc(bt, node_browse_text_cb, ntree, node);
+ xoff=19;
+ if(strp) MEM_freeN(strp);
+ }
+ else {
+ bt = uiDefBut(block, BUT, B_NOP, "Update",
+ butr->xmin+xoff, butr->ymin+20, 50, 19,
+ &node->menunr, 0.0, 19.0, 0, 0, "Refresh this node (and all others that use the same script)");
+ uiButSetFunc(bt, node_dynamic_update_cb, ntree, node);
+
+ if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) {
+ // UI_ThemeColor(TH_REDALERT);
+ // XXX ui_rasterpos_safe(butr->xmin + xoff, butr->ymin + 5, snode->aspect);
+ // XXX snode_drawstring(snode, "Error! Check console...", butr->xmax - butr->xmin);
+ ;
+ }
+ }
+ }
+ return 20+19;
+}
+
+/* only once called */
+static void node_shader_set_butfunc(bNodeType *ntype)
+{
+ switch(ntype->type) {
+ /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */
+
+ case SH_NODE_MATERIAL:
+ case SH_NODE_MATERIAL_EXT:
+ ntype->butfunc= node_shader_buts_material;
+ break;
+ case SH_NODE_TEXTURE:
+ ntype->butfunc= node_buts_texture;
+ break;
+ case SH_NODE_NORMAL:
+ ntype->butfunc= node_buts_normal;
+ break;
+ case SH_NODE_CURVE_VEC:
+ ntype->butfunc= node_buts_curvevec;
+ break;
+ case SH_NODE_CURVE_RGB:
+ ntype->butfunc= node_buts_curvecol;
+ break;
+ case SH_NODE_MAPPING:
+ ntype->butfunc= node_shader_buts_mapping;
+ break;
+ case SH_NODE_VALUE:
+ ntype->butfunc= node_buts_value;
+ break;
+ case SH_NODE_RGB:
+ ntype->butfunc= node_buts_rgb;
+ break;
+ case SH_NODE_MIX_RGB:
+ ntype->butfunc= node_buts_mix_rgb;
+ break;
+ case SH_NODE_VALTORGB:
+ ntype->butfunc= node_buts_valtorgb;
+ break;
+ case SH_NODE_MATH:
+ ntype->butfunc= node_buts_math;
+ break;
+ case SH_NODE_VECT_MATH:
+ ntype->butfunc= node_shader_buts_vect_math;
+ break;
+ case SH_NODE_GEOMETRY:
+ ntype->butfunc= node_shader_buts_geometry;
+ break;
+ case NODE_DYNAMIC:
+ ntype->butfunc= node_shader_buts_dynamic;
+ break;
+ default:
+ ntype->butfunc= NULL;
+ }
+}
+
+/* ****************** BUTTON CALLBACKS FOR COMPOSITE NODES ***************** */
+
+
+
+static void node_browse_image_cb(bContext *C, void *ntree_v, void *node_v)
+{
+ bNodeTree *ntree= ntree_v;
+ bNode *node= node_v;
+
+ nodeSetActive(ntree, node);
+
+ if(node->menunr<1) return;
+ if(node->menunr==32767) { /* code for Load New */
+ /// addqueue(curarea->win, UI_BUT_EVENT, B_NODE_LOADIMAGE); XXX
+ }
+ else {
+ if(node->id) node->id->us--;
+ node->id= BLI_findlink(&G.main->image, node->menunr-1);
+ id_us_plus(node->id);
+
+ BLI_strncpy(node->name, node->id->name+2, 21);
+
+ NodeTagChanged(ntree, node);
+ BKE_image_signal((Image *)node->id, node->storage, IMA_SIGNAL_USER_NEW_IMAGE);
+ // addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC); XXX
+ }
+ node->menunr= 0;
+}
+
+static void node_active_cb(bContext *C, void *ntree_v, void *node_v)
+{
+ nodeSetActive(ntree_v, node_v);
+}
+static void node_image_type_cb(bContext *C, void *node_v, void *unused)
+{
+
+ // allqueue(REDRAWNODE, 1);
+}
+
+static char *node_image_type_pup(void)
+{
+ char *str= MEM_mallocN(256, "image type pup");
+ int a;
+
+ str[0]= 0;
+
+ a= sprintf(str, "Image Type %%t|");
+ a+= sprintf(str+a, " Image %%x%d %%i%d|", IMA_SRC_FILE, ICON_IMAGE_DATA);
+ a+= sprintf(str+a, " Movie %%x%d %%i%d|", IMA_SRC_MOVIE, ICON_SEQUENCE);
+ a+= sprintf(str+a, " Sequence %%x%d %%i%d|", IMA_SRC_SEQUENCE, ICON_IMAGE_COL);
+ a+= sprintf(str+a, " Generated %%x%d %%i%d", IMA_SRC_GENERATED, ICON_BLANK1);
+
+ return str;
+}
+
+/* copy from buttons_shading.c */
+static char *layer_menu(RenderResult *rr)
+{
+ RenderLayer *rl;
+ int len= 40 + 40*BLI_countlist(&rr->layers);
+ short a, nr;
+ char *str= MEM_callocN(len, "menu layers");
+
+ strcpy(str, "Layer %t");
+ a= strlen(str);
+ for(nr=0, rl= rr->layers.first; rl; rl= rl->next, nr++) {
+ a+= sprintf(str+a, "|%s %%x%d", rl->name, nr);
+ }
+
+ return str;
+}
+
+static void image_layer_cb(bContext *C, void *ima_v, void *iuser_v)
+{
+ Scene *scene= CTX_data_scene(C);
+
+ ntreeCompositForceHidden(scene->nodetree, scene);
+ BKE_image_multilayer_index(ima_v, iuser_v);
+ // allqueue(REDRAWNODE, 0);
+}
+
+static int node_composit_buts_image(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ ImageUser *iuser= node->storage;
+
+ if(block) {
+ uiBut *bt;
+ short dy= (short)butr->ymax-19;
+ char *strp;
+
+ uiBlockBeginAlign(block);
+
+ /* browse button */
+ IMAnames_to_pupstring(&strp, NULL, "LOAD NEW %x32767", &(G.main->image), NULL, NULL);
+ node->menunr= 0;
+ bt= uiDefButS(block, MENU, B_NOP, strp,
+ butr->xmin, dy, 19, 19,
+ &node->menunr, 0, 0, 0, 0, "Browses existing choices");
+ uiButSetFunc(bt, node_browse_image_cb, ntree, node);
+ if(strp) MEM_freeN(strp);
+
+ /* Add New button */
+ if(node->id==NULL) {
+ bt= uiDefBut(block, BUT, B_NODE_LOADIMAGE, "Load New",
+ butr->xmin+19, dy, (short)(butr->xmax-butr->xmin-19.0f), 19,
+ NULL, 0.0, 0.0, 0, 0, "Add new Image");
+ uiButSetFunc(bt, node_active_cb, ntree, node);
+ }
+ else {
+ /* name button + type */
+ Image *ima= (Image *)node->id;
+ short xmin= (short)butr->xmin, xmax= (short)butr->xmax;
+ short width= xmax - xmin - 45;
+ short icon= ICON_IMAGE_DATA;
+
+ if(ima->source==IMA_SRC_MOVIE) icon= ICON_SEQUENCE;
+ else if(ima->source==IMA_SRC_SEQUENCE) icon= ICON_IMAGE_COL;
+ else if(ima->source==IMA_SRC_GENERATED) icon= ICON_BLANK1;
+
+ bt= uiDefBut(block, TEX, B_NOP, "IM:",
+ xmin+19, dy, width, 19,
+ node->id->name+2, 0.0, 19.0, 0, 0, "Image name");
+ uiButSetFunc(bt, node_ID_title_cb, node, NULL);
+
+ /* buffer type option */
+ strp= node_image_type_pup();
+ bt= uiDefIconTextButS(block, MENU, B_NOP, icon, strp,
+ xmax-26, dy, 26, 19,
+ &ima->source, 0.0, 19.0, 0, 0, "Image type");
+ uiButSetFunc(bt, node_image_type_cb, node, ima);
+ MEM_freeN(strp);
+
+ if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) ) {
+ width= (xmax-xmin)/2;
+
+ dy-= 19;
+ uiDefButI(block, NUM, B_NODE_EXEC, "Frs:",
+ xmin, dy, width, 19,
+ &iuser->frames, 1.0, MAXFRAMEF, 0, 0, "Amount of images used in animation");
+ uiDefButI(block, NUM, B_NODE_EXEC, "SFra:",
+ xmin+width, dy, width, 19,
+ &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Start frame of animation");
+ dy-= 19;
+ uiDefButI(block, NUM, B_NODE_EXEC, "Offs:",
+ xmin, dy, width, 19,
+ &iuser->offset, -MAXFRAMEF, MAXFRAMEF, 0, 0, "Offsets the number of the frame to use in the animation");
+ uiDefButS(block, TOG, B_NODE_EXEC, "Cycl",
+ xmin+width, dy, width-20, 19,
+ &iuser->cycl, 0.0, 0.0, 0, 0, "Make animation go cyclic");
+ uiDefIconButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NODE_EXEC, ICON_AUTO,
+ xmax-20, dy, 20, 19,
+ &iuser->flag, 0.0, 0.0, 0, 0, "Always refresh Image on frame changes");
+ }
+ if( ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
+ RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
+ if(rl) {
+ width= (xmax-xmin);
+ dy-= 19;
+ strp= layer_menu(ima->rr);
+ bt= uiDefButS(block, MENU, B_NODE_EXEC, strp,
+ xmin, dy, width, 19,
+ &iuser->layer, 0.0, 10000.0, 0, 0, "Layer");
+ uiButSetFunc(bt, image_layer_cb, ima->rr, node->storage);
+ MEM_freeN(strp);
+ }
+ }
+ }
+
+ }
+ if(node->id) {
+ Image *ima= (Image *)node->id;
+ int retval= 19;
+
+ /* for each draw we test for anim refresh event */
+ if(iuser->flag & IMA_ANIM_REFRESHED) {
+ iuser->flag &= ~IMA_ANIM_REFRESHED;
+ // addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC); XXX
+ }
+
+ if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) )
+ retval+= 38;
+ if( ima->type==IMA_TYPE_MULTILAYER)
+ retval+= 19;
+ return retval;
+ }
+ else
+ return 19;
+}
+
+/* if we use render layers from other scene, we make a nice title */
+static void set_render_layers_title(bContext *C, void *node_v, void *unused)
+{
+ bNode *node= node_v;
+ Scene *sce;
+ SceneRenderLayer *srl;
+ char str[64];
+
+ if(node->id) {
+ BLI_strncpy(str, node->id->name+2, 21);
+ strcat(str, "|");
+ sce= (Scene *)node->id;
+ }
+ else {
+ str[0]= 0;
+ sce= CTX_data_scene(C);
+ }
+ srl= BLI_findlink(&sce->r.layers, node->custom1);
+ if(srl==NULL) {
+ node->custom1= 0;
+ srl= sce->r.layers.first;
+ }
+
+ strcat(str, srl->name);
+ BLI_strncpy(node->name, str, 32);
+}
+
+static char *scene_layer_menu(Scene *sce)
+{
+ SceneRenderLayer *srl;
+ int len= 40 + 40*BLI_countlist(&sce->r.layers);
+ short a, nr;
+ char *str= MEM_callocN(len, "menu layers");
+
+ strcpy(str, "Active Layer %t");
+ a= strlen(str);
+ for(nr=0, srl= sce->r.layers.first; srl; srl= srl->next, nr++) {
+ a+= sprintf(str+a, "|%s %%x%d", srl->name, nr);
+ }
+
+ return str;
+}
+
+static void node_browse_scene_cb(bContext *C, void *ntree_v, void *node_v)
+{
+ bNodeTree *ntree= ntree_v;
+ bNode *node= node_v;
+ Scene *sce;
+
+ if(node->menunr<1) return;
+
+ if(node->id) {
+ node->id->us--;
+ node->id= NULL;
+ }
+ sce= BLI_findlink(&G.main->scene, node->menunr-1);
+ node->id= &sce->id;
+ id_us_plus(node->id);
+
+ set_render_layers_title(C, node, NULL);
+ nodeSetActive(ntree, node);
+
+ // allqueue(REDRAWBUTSSHADING, 0);
+ // allqueue(REDRAWNODE, 0);
+ NodeTagChanged(ntree, node);
+
+ node->menunr= 0;
+}
+
+
+static int node_composit_buts_renderlayers(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block && node->id) {
+ Scene *scene= (Scene *)node->id;
+ uiBut *bt;
+ char *strp;
+
+ /* browse button scene */
+ uiBlockBeginAlign(block);
+ IDnames_to_pupstring(&strp, NULL, "", &(G.main->scene), NULL, NULL);
+ node->menunr= 0;
+ bt= uiDefButS(block, MENU, B_NOP, strp,
+ butr->xmin, butr->ymin, 20, 19,
+ &node->menunr, 0, 0, 0, 0, "Browse Scene to use RenderLayer from");
+ uiButSetFunc(bt, node_browse_scene_cb, ntree, node);
+ if(strp) MEM_freeN(strp);
+
+ /* browse button layer */
+ strp= scene_layer_menu(node->id?(Scene *)node->id:scene);
+ if(node->id)
+ bt= uiDefIconTextButS(block, MENU, B_NODE_EXEC, ICON_SCENE_DATA, strp,
+ butr->xmin+20, butr->ymin, (butr->xmax-butr->xmin)-40, 19,
+ &node->custom1, 0, 0, 0, 0, "Choose Render Layer");
+ else
+ bt= uiDefButS(block, MENU, B_NODE_EXEC, strp,
+ butr->xmin+20, butr->ymin, (butr->xmax-butr->xmin)-40, 19,
+ &node->custom1, 0, 0, 0, 0, "Choose Render Layer");
+ uiButSetFunc(bt, set_render_layers_title, node, NULL);
+ MEM_freeN(strp);
+
+ /* re-render */
+ /* uses custom2, not the best implementation of the world... but we need it to work now :) */
+ bt= uiDefIconButS(block, TOG, B_NODE_EXEC, ICON_SCENE,
+ butr->xmax-20, butr->ymin, 20, 19,
+ &node->custom2, 0, 0, 0, 0, "Re-render this Layer");
+
+ }
+ return 19;
+}
+
+static void node_blur_relative_cb(bContext *C, void *node, void *poin2)
+{
+ bNode *nodev= node;
+ NodeBlurData *nbd= nodev->storage;
+ if(nbd->image_in_width != 0){
+ if(nbd->relative){ /* convert absolute values to relative */
+ nbd->percentx= (float)(nbd->sizex)/nbd->image_in_width;
+ nbd->percenty= (float)(nbd->sizey)/nbd->image_in_height;
+ }else{ /* convert relative values to absolute */
+ nbd->sizex= (int)(nbd->percentx*nbd->image_in_width);
+ nbd->sizey= (int)(nbd->percenty*nbd->image_in_height);
+ }
+ }
+ // allqueue(REDRAWNODE, 0);
+}
+static void node_blur_update_sizex_cb(bContext *C, void *node, void *poin2)
+{
+ bNode *nodev= node;
+ NodeBlurData *nbd= nodev->storage;
+
+ nbd->sizex= (int)(nbd->percentx*nbd->image_in_width);
+}
+static void node_blur_update_sizey_cb(bContext *C, void *node, void *poin2)
+{
+ bNode *nodev= node;
+ NodeBlurData *nbd= nodev->storage;
+
+ nbd->sizey= (int)(nbd->percenty*nbd->image_in_height);
+}
+static int node_composit_buts_blur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ NodeBlurData *nbd= node->storage;
+ uiBut *bt;
+ short dy= butr->ymin+58;
+ short dx= (butr->xmax-butr->xmin)/2;
+ char str[256];
+
+ uiBlockBeginAlign(block);
+ sprintf(str, "Filter Type%%t|Flat %%x%d|Tent %%x%d|Quad %%x%d|Cubic %%x%d|Gauss %%x%d|Fast Gauss%%x%d|CatRom %%x%d|Mitch %%x%d", R_FILTER_BOX, R_FILTER_TENT, R_FILTER_QUAD, R_FILTER_CUBIC, R_FILTER_GAUSS, R_FILTER_FAST_GAUSS, R_FILTER_CATROM, R_FILTER_MITCH);
+ uiDefButS(block, MENU, B_NODE_EXEC,str,
+ butr->xmin, dy, dx*2, 19,
+ &nbd->filtertype, 0, 0, 0, 0, "Set sampling filter for blur");
+ dy-=19;
+ if (nbd->filtertype != R_FILTER_FAST_GAUSS) {
+ uiDefButC(block, TOG, B_NODE_EXEC, "Bokeh",
+ butr->xmin, dy, dx, 19,
+ &nbd->bokeh, 0, 0, 0, 0, "Uses circular filter, warning it's slow!");
+ uiDefButC(block, TOG, B_NODE_EXEC, "Gamma",
+ butr->xmin+dx, dy, dx, 19,
+ &nbd->gamma, 0, 0, 0, 0, "Applies filter on gamma corrected values");
+ } else {
+ uiBlockEndAlign(block);
+ uiBlockBeginAlign(block);
+ }
+ dy-=19;
+ bt= uiDefButS(block, TOG, B_NOP, "Relative",
+ butr->xmin, dy, dx*2, 19,
+ &nbd->relative, 0, 0, 0, 0, "Use relative (percent) values to define blur radius");
+ uiButSetFunc(bt, node_blur_relative_cb, node, NULL);
+
+ dy-=19;
+ if(nbd->relative) {
+ bt= uiDefButF(block, NUM, B_NODE_EXEC, "X:",
+ butr->xmin, dy, dx, 19,
+ &nbd->percentx, 0.0f, 1.0f, 0, 0, "");
+ uiButSetFunc(bt, node_blur_update_sizex_cb, node, NULL);
+ bt= uiDefButF(block, NUM, B_NODE_EXEC, "Y:",
+ butr->xmin+dx, dy, dx, 19,
+ &nbd->percenty, 0.0f, 1.0f, 0, 0, "");
+ uiButSetFunc(bt, node_blur_update_sizey_cb, node, NULL);
+ }
+ else {
+ uiDefButS(block, NUM, B_NODE_EXEC, "X:",
+ butr->xmin, dy, dx, 19,
+ &nbd->sizex, 0, 256, 0, 0, "");
+ uiDefButS(block, NUM, B_NODE_EXEC, "Y:",
+ butr->xmin+dx, dy, dx, 19,
+ &nbd->sizey, 0, 256, 0, 0, "");
+ }
+ uiBlockEndAlign(block);
+ }
+ return 77;
+}
+
+static int node_composit_buts_dblur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ NodeDBlurData *ndbd = node->storage;
+ short dy = butr->ymin + 171;
+ short dx = butr->xmax - butr->xmin;
+ short halfdx= (short)dx/2;
+
+ uiBlockBeginAlign(block);
+ uiDefButS(block, NUM, B_NODE_EXEC, "Iterations:",
+ butr->xmin, dy, dx, 19,
+ &ndbd->iter, 1, 32, 10, 0, "Amount of iterations");
+ uiDefButC(block, TOG, B_NODE_EXEC, "Wrap",
+ butr->xmin, dy-= 19, dx, 19,
+ &ndbd->wrap, 0, 0, 0, 0, "Wrap blur");
+ uiBlockEndAlign(block);
+
+ dy-= 9;
+
+ uiDefBut(block, LABEL, B_NOP, "Center", butr->xmin, dy-= 19, dx, 19, NULL, 0.0f, 0.0f, 0, 0, "");
+
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_NODE_EXEC, "X:",
+ butr->xmin, dy-= 19, halfdx, 19,
+ &ndbd->center_x, 0.0f, 1.0f, 10, 0, "X center in percents");
+ uiDefButF(block, NUM, B_NODE_EXEC, "Y:",
+ butr->xmin+halfdx, dy, halfdx, 19,
+ &ndbd->center_y, 0.0f, 1.0f, 10, 0, "Y center in percents");
+ uiBlockEndAlign(block);
+
+ dy-= 9;
+
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_NODE_EXEC, "Distance:",
+ butr->xmin, dy-= 19, dx, 19,
+ &ndbd->distance, -1.0f, 1.0f, 10, 0, "Amount of which the image moves");
+ uiDefButF(block, NUM, B_NODE_EXEC, "Angle:",
+ butr->xmin, dy-= 19, dx, 19,
+ &ndbd->angle, 0.0f, 360.0f, 1000, 0, "Angle in which the image will be moved");
+ uiBlockEndAlign(block);
+
+ dy-= 9;
+
+ uiDefButF(block, NUM, B_NODE_EXEC, "Spin:",
+ butr->xmin, dy-= 19, dx, 19,
+ &ndbd->spin, -360.0f, 360.0f, 1000, 0, "Angle that is used to spin the image");
+
+ dy-= 9;
+
+ uiDefButF(block, NUM, B_NODE_EXEC, "Zoom:",
+ butr->xmin, dy-= 19, dx, 19,
+ &ndbd->zoom, 0.0f, 100.0f, 100, 0, "Amount of which the image is zoomed");
+
+ }
+ return 190;
+}
+
+static int node_composit_buts_bilateralblur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ NodeBilateralBlurData *nbbd= node->storage;
+ short dy= butr->ymin+38;
+ short dx= (butr->xmax-butr->xmin);
+
+ uiBlockBeginAlign(block);
+ uiDefButS(block, NUM, B_NODE_EXEC, "Iterations:",
+ butr->xmin, dy, dx, 19,
+ &nbbd->iter, 1, 128, 0, 0, "Amount of iterations");
+ dy-=19;
+ uiDefButF(block, NUM, B_NODE_EXEC, "Color Sigma:",
+ butr->xmin, dy, dx, 19,
+ &nbbd->sigma_color,0.01, 3, 10, 0, "Sigma value used to modify color");
+ dy-=19;
+ uiDefButF(block, NUM, B_NODE_EXEC, "Space Sigma:",
+ butr->xmin, dy, dx, 19,
+ &nbbd->sigma_space ,0.01, 30, 10, 0, "Sigma value used to modify space");
+
+ }
+ return 57;
+}
+
+/* qdn: defocus node */
+static int node_composit_buts_defocus(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ NodeDefocus *nqd = node->storage;
+ short dy = butr->ymin + 209;
+ short dx = butr->xmax - butr->xmin;
+ char* mstr1 = "Bokeh Type%t|Octagon %x8|Heptagon %x7|Hexagon %x6|Pentagon %x5|Square %x4|Triangle %x3|Disk %x0";
+
+ uiDefBut(block, LABEL, B_NOP, "Bokeh Type", butr->xmin, dy, dx, 19, NULL, 0, 0, 0, 0, "");
+ uiDefButC(block, MENU, B_NODE_EXEC, mstr1,
+ butr->xmin, dy-19, dx, 19,
+ &nqd->bktype, 0, 0, 0, 0, "Bokeh type");
+ if (nqd->bktype) { /* for some reason rotating a disk doesn't seem to work... ;) */
+ uiDefButC(block, NUM, B_NODE_EXEC, "Rotate:",
+ butr->xmin, dy-38, dx, 19,
+ &nqd->rotation, 0, 90, 0, 0, "Bokeh shape rotation offset in degrees");
+ }
+ uiDefButC(block, TOG, B_NODE_EXEC, "Gamma Correct",
+ butr->xmin, dy-57, dx, 19,
+ &nqd->gamco, 0, 0, 0, 0, "Enable gamma correction before and after main process");
+ if (nqd->no_zbuf==0) {
+ // only needed for zbuffer input
+ uiDefButF(block, NUM, B_NODE_EXEC, "fStop:",
+ butr->xmin, dy-76, dx, 19,
+ &nqd->fstop, 0.5, 128, 10, 0, "Amount of focal blur, 128=infinity=perfect focus, half the value doubles the blur radius");
+ }
+ uiDefButF(block, NUM, B_NODE_EXEC, "Maxblur:",
+ butr->xmin, dy-95, dx, 19,
+ &nqd->maxblur, 0, 10000, 1000, 0, "blur limit, maximum CoC radius, 0=no limit");
+ uiDefButF(block, NUM, B_NODE_EXEC, "BThreshold:",
+ butr->xmin, dy-114, dx, 19,
+ &nqd->bthresh, 0, 100, 100, 0, "CoC radius threshold, prevents background bleed on in-focus midground, 0=off");
+ uiDefButC(block, TOG, B_NODE_EXEC, "Preview",
+ butr->xmin, dy-142, dx, 19,
+ &nqd->preview, 0, 0, 0, 0, "Enable sampling mode, useful for preview when using low samplecounts");
+ if (nqd->preview) {
+ /* only visible when sampling mode enabled */
+ uiDefButS(block, NUM, B_NODE_EXEC, "Samples:",
+ butr->xmin, dy-161, dx, 19,
+ &nqd->samples, 16, 256, 0, 0, "Number of samples (16=grainy, higher=less noise)");
+ }
+ uiDefButS(block, TOG, B_NODE_EXEC, "No zbuffer",
+ butr->xmin, dy-190, dx, 19,
+ &nqd->no_zbuf, 0, 0, 0, 0, "Enable when using an image as input instead of actual zbuffer (auto enabled if node not image based, eg. time node)");
+ if (nqd->no_zbuf) {
+ uiDefButF(block, NUM, B_NODE_EXEC, "Zscale:",
+ butr->xmin, dy-209, dx, 19,
+ &nqd->scale, 0, 1000, 100, 0, "Scales the Z input when not using a zbuffer, controls maximum blur designated by the color white or input value 1");
+ }
+ }
+ return 228;
+}
+
+
+/* qdn: glare node */
+static int node_composit_buts_glare(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ NodeGlare *ndg = node->storage;
+ short dy = butr->ymin + 152, dx = butr->xmax - butr->xmin;
+ char* mn1 = "Type%t|Ghosts%x3|Streaks%x2|Fog Glow%x1|Simple Star%x0";
+ char* mn2 = "Quality/Speed%t|High/Slow%x0|Medium/Medium%x1|Low/Fast%x2";
+ uiDefButC(block, MENU, B_NODE_EXEC, mn1,
+ butr->xmin, dy, dx, 19,
+ &ndg->type, 0, 0, 0, 0, "Glow/Flare/Bloom type");
+ uiDefButC(block, MENU, B_NODE_EXEC, mn2,
+ butr->xmin, dy-19, dx, 19,
+ &ndg->quality, 0, 0, 0, 0,
+ "Quality speed trade off, if not set to high quality, effect will be applied to low-res copy of source image");
+ if (ndg->type != 1) {
+ uiDefButC(block, NUM, B_NODE_EXEC, "Iterations:",
+ butr->xmin, dy-38, dx, 19,
+ &ndg->iter, 2, 5, 1, 0,
+ "higher values will generate longer/more streaks/ghosts");
+ if (ndg->type != 0)
+ uiDefButF(block, NUM, B_NODE_EXEC, "ColMod:",
+ butr->xmin, dy-57, dx, 19,
+ &ndg->colmod, 0, 1, 10, 0,
+ "Amount of Color Modulation, modulates colors of streaks and ghosts for a spectral dispersion effect");
+ }
+ uiDefButF(block, NUM, B_NODE_EXEC, "Mix:",
+ butr->xmin, dy-76, dx, 19,
+ &ndg->mix, -1, 1, 10, 0,
+ "Mix balance, -1 is original image only, 0 is exact 50/50 mix, 1 is processed image only");
+ uiDefButF(block, NUM, B_NODE_EXEC, "Threshold:",
+ butr->xmin, dy-95, dx, 19,
+ &ndg->threshold, 0, 1000, 10, 0,
+ "Brightness threshold, the glarefilter will be applied only to pixels brighter than this value");
+ if ((ndg->type == 2) || (ndg->type == 0))
+ {
+ if (ndg->type == 2) {
+ uiDefButC(block, NUM, B_NODE_EXEC, "streaks:",
+ butr->xmin, dy-114, dx, 19,
+ &ndg->angle, 2, 16, 1000, 0,
+ "Total number of streaks");
+ uiDefButC(block, NUM, B_NODE_EXEC, "AngOfs:",
+ butr->xmin, dy-133, dx, 19,
+ &ndg->angle_ofs, 0, 180, 1000, 0,
+ "Streak angle rotation offset in degrees");
+ }
+ uiDefButF(block, NUM, B_NODE_EXEC, "Fade:",
+ butr->xmin, dy-152, dx, 19,
+ &ndg->fade, 0.75, 1, 5, 0,
+ "Streak fade out factor");
+ }
+ if (ndg->type == 0)
+ uiDefButC(block, TOG, B_NODE_EXEC, "Rot45",
+ butr->xmin, dy-114, dx, 19,
+ &ndg->angle, 0, 0, 0, 0,
+ "simple star filter, add 45 degree rotation offset");
+ if ((ndg->type == 1) || (ndg->type > 3)) // PBGH and fog glow
+ uiDefButC(block, NUM, B_NODE_EXEC, "Size:",
+ butr->xmin, dy-114, dx, 19,
+ &ndg->size, 6, 9, 1000, 0,
+ "glow/glare size (not actual size, relative to initial size of bright area of pixels)");
+ }
+ return 171;
+}
+
+/* qdn: tonemap node */
+static int node_composit_buts_tonemap(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ NodeTonemap *ntm = node->storage;
+ short dy = butr->ymin + 76, dx = butr->xmax - butr->xmin;
+ char* mn = "Type%t|R/D Photoreceptor%x1|Rh Simple%x0";
+
+ uiBlockBeginAlign(block);
+ uiDefButI(block, MENU, B_NODE_EXEC, mn,
+ butr->xmin, dy, dx, 19,
+ &ntm->type, 0, 0, 0, 0,
+ "Tone mapping type");
+ if (ntm->type == 0) {
+ uiDefButF(block, NUM, B_NODE_EXEC, "Key:",
+ butr->xmin, dy-19, dx, 19,
+ &ntm->key, 0, 1, 5, 0,
+ "The value the average luminance is mapped to");
+ uiDefButF(block, NUM, B_NODE_EXEC, "Offset:",
+ butr->xmin, dy-38, dx, 19,
+ &ntm->offset, 0.001, 10, 5, 0,
+ "Tonemap offset, normally always 1, but can be used as an extra control to alter the brightness curve");
+ uiDefButF(block, NUM, B_NODE_EXEC, "Gamma:",
+ butr->xmin, dy-57, dx, 19,
+ &ntm->gamma, 0.001, 3, 5, 0,
+ "Gamma factor, if not used, set to 1");
+ }
+ else {
+ uiDefButF(block, NUM, B_NODE_EXEC, "Intensity:",
+ butr->xmin, dy-19, dx, 19,
+ &ntm->f, -8, 8, 10, 0, "if less than zero, darkens image, otherwise makes it brighter");
+ uiDefButF(block, NUM, B_NODE_EXEC, "Contrast:",
+ butr->xmin, dy-38, dx, 19,
+ &ntm->m, 0, 1, 5, 0, "Set to 0 to use estimate from input image");
+ uiDefButF(block, NUM, B_NODE_EXEC, "Adaptation:",
+ butr->xmin, dy-57, dx, 19,
+ &ntm->a, 0, 1, 5, 0, "if 0, global, if 1, based on pixel intensity");
+ uiDefButF(block, NUM, B_NODE_EXEC, "ColCorrect:",
+ butr->xmin, dy-76, dx, 19,
+ &ntm->c, 0, 1, 5, 0, "color correction, if 0, same for all channels, if 1, each independent");
+ }
+ uiBlockEndAlign(block);
+ }
+ return 95;
+}
+
+/* qdn: lens distortion node */
+static int node_composit_buts_lensdist(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ NodeLensDist *nld = node->storage;
+ short dy = butr->ymin + 19, dx = butr->xmax - butr->xmin;
+ uiBlockBeginAlign(block);
+ uiDefButS(block, TOG, B_NODE_EXEC, "Projector",
+ butr->xmin, dy, dx, 19,
+ &nld->proj, 0, 0, 0, 0,
+ "Enable/disable projector mode, effect is applied in horizontal direction only");
+ if (!nld->proj) {
+ uiDefButS(block, TOG, B_NODE_EXEC, "Jitter",
+ butr->xmin, dy-19, dx/2, 19,
+ &nld->jit, 0, 0, 0, 0,
+ "Enable/disable jittering, faster, but also noisier");
+ uiDefButS(block, TOG, B_NODE_EXEC, "Fit",
+ butr->xmin+dx/2, dy-19, dx/2, 19,
+ &nld->fit, 0, 0, 0, 0,
+ "For positive distortion factor only, scale image such that black areas are not visible");
+ }
+ uiBlockEndAlign(block);
+ }
+ return 38;
+}
+
+
+static int node_composit_buts_vecblur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ NodeBlurData *nbd= node->storage;
+ short dy= butr->ymin;
+ short dx= (butr->xmax-butr->xmin);
+
+ uiBlockBeginAlign(block);
+ uiDefButS(block, NUM, B_NODE_EXEC, "Samples:",
+ butr->xmin, dy+76, dx, 19,
+ &nbd->samples, 1, 256, 0, 0, "Amount of samples");
+ uiDefButS(block, NUM, B_NODE_EXEC, "MinSpeed:",
+ butr->xmin, dy+57, dx, 19,
+ &nbd->minspeed, 0, 1024, 0, 0, "Minimum speed for a pixel to be blurred, used to separate background from foreground");
+ uiDefButS(block, NUM, B_NODE_EXEC, "MaxSpeed:",
+ butr->xmin, dy+38, dx, 19,
+ &nbd->maxspeed, 0, 1024, 0, 0, "If not zero, maximum speed in pixels");
+ uiDefButF(block, NUM, B_NODE_EXEC, "BlurFac:",
+ butr->xmin, dy+19, dx, 19,
+ &nbd->fac, 0.0f, 2.0f, 10, 2, "Scaling factor for motion vectors, actually 'shutter speed' in frames");
+ uiDefButS(block, TOG, B_NODE_EXEC, "Curved",
+ butr->xmin, dy, dx, 19,
+ &nbd->curved, 0.0f, 2.0f, 10, 2, "Interpolate between frames in a bezier curve, rather than linearly");
+ uiBlockEndAlign(block);
+ }
+ return 95;
+}
+
+static int node_composit_buts_filter(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ uiBut *bt;
+
+ /* blend type */
+ bt=uiDefButS(block, MENU, B_NODE_EXEC, "Soften %x0|Sharpen %x1|Laplace %x2|Sobel %x3|Prewitt %x4|Kirsch %x5|Shadow %x6",
+ butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
+ &node->custom1, 0, 0, 0, 0, "");
+ uiButSetFunc(bt, node_but_title_cb, node, bt);
+ }
+ return 20;
+}
+
+static int node_composit_buts_flip(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ uiBut *bt;
+
+ /* flip x\y */
+ bt=uiDefButS(block, MENU, B_NODE_EXEC, "Flip X %x0|Flip Y %x1|Flip X & Y %x2",
+ butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
+ &node->custom1, 0, 0, 0, 0, "");
+ uiButSetFunc(bt, node_but_title_cb, node, bt);
+ }
+ return 20;
+}
+
+static int node_composit_buts_crop(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ NodeTwoXYs *ntxy= node->storage;
+ char elementheight = 19;
+ short dx= (butr->xmax-butr->xmin)/2;
+ short dy= butr->ymax - elementheight;
+ short xymin= 0, xymax= 10000;
+
+ uiBlockBeginAlign(block);
+
+ /* crop image size toggle */
+ uiDefButS(block, TOG, B_NODE_EXEC, "Crop Image Size",
+ butr->xmin, dy, dx*2, elementheight,
+ &node->custom1, 0, 0, 0, 0, "Crop the size of the input image.");
+
+ dy-=elementheight;
+
+ /* x1 */
+ uiDefButS(block, NUM, B_NODE_EXEC, "X1:",
+ butr->xmin, dy, dx, elementheight,
+ &ntxy->x1, xymin, xymax, 0, 0, "");
+ /* y1 */
+ uiDefButS(block, NUM, B_NODE_EXEC, "Y1:",
+ butr->xmin+dx, dy, dx, elementheight,
+ &ntxy->y1, xymin, xymax, 0, 0, "");
+
+ dy-=elementheight;
+
+ /* x2 */
+ uiDefButS(block, NUM, B_NODE_EXEC, "X2:",
+ butr->xmin, dy, dx, elementheight,
+ &ntxy->x2, xymin, xymax, 0, 0, "");
+ /* y2 */
+ uiDefButS(block, NUM, B_NODE_EXEC, "Y2:",
+ butr->xmin+dx, dy, dx, elementheight,
+ &ntxy->y2, xymin, xymax, 0, 0, "");
+
+ uiBlockEndAlign(block);
+ }
+ return 60;
+}
+
+static int node_composit_buts_splitviewer(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ uiBlockBeginAlign(block);
+
+ uiDefButS(block, ROW, B_NODE_EXEC, "X",
+ butr->xmin, butr->ymin+19, (butr->xmax-butr->xmin)/2, 20,
+ &node->custom2, 0.0, 0.0, 0, 0, "");
+ uiDefButS(block, ROW, B_NODE_EXEC, "Y",
+ butr->xmin+(butr->xmax-butr->xmin)/2, butr->ymin+19, (butr->xmax-butr->xmin)/2, 20,
+ &node->custom2, 0.0, 1.0, 0, 0, "");
+
+ uiDefButS(block, NUMSLI, B_NODE_EXEC, "Split %: ",
+ butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, &node->custom1, 0, 100, 10, 0, "");
+ }
+ return 40;
+}
+
+static int node_composit_buts_map_value(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ TexMapping *texmap= node->storage;
+ short xstart= (short)butr->xmin;
+ short dy= (short)(butr->ymax-19.0f);
+ short dx= (short)(butr->xmax-butr->xmin)/2;
+
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_NODE_EXEC, "Offs:", xstart, dy, 2*dx, 19, texmap->loc, -1000.0f, 1000.0f, 10, 2, "");
+ dy-= 19;
+ uiDefButF(block, NUM, B_NODE_EXEC, "Size:", xstart, dy, 2*dx, 19, texmap->size, -1000.0f, 1000.0f, 10, 3, "");
+ dy-= 23;
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOG, TEXMAP_CLIP_MIN, B_NODE_EXEC, "Min", xstart, dy, dx, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, "");
+ uiDefButF(block, NUM, B_NODE_EXEC, "", xstart+dx, dy, dx, 19, texmap->min, -1000.0f, 1000.0f, 10, 2, "");
+ dy-= 19;
+ uiDefButBitI(block, TOG, TEXMAP_CLIP_MAX, B_NODE_EXEC, "Max", xstart, dy, dx, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, "");
+ uiDefButF(block, NUM, B_NODE_EXEC, "", xstart+dx, dy, dx, 19, texmap->max, -1000.0f, 1000.0f, 10, 2, "");
+ }
+ return 80;
+}
+
+static int node_composit_buts_alphaover(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ NodeTwoFloats *ntf= node->storage;
+
+ /* alpha type */
+ uiDefButS(block, TOG, B_NODE_EXEC, "ConvertPremul",
+ butr->xmin, butr->ymin+19, butr->xmax-butr->xmin, 19,
+ &node->custom1, 0, 0, 0, 0, "");
+ /* mix factor */
+ uiDefButF(block, NUM, B_NODE_EXEC, "Premul: ",
+ butr->xmin, butr->ymin, butr->xmax-butr->xmin, 19,
+ &ntf->x, 0.0f, 1.0f, 100, 0, "");
+ }
+ return 38;
+}
+
+static int node_composit_buts_hue_sat(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ NodeHueSat *nhs= node->storage;
+
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUMSLI, B_NODE_EXEC, "Hue: ",
+ butr->xmin, butr->ymin+40.0f, butr->xmax-butr->xmin, 20,
+ &nhs->hue, 0.0f, 1.0f, 100, 0, "");
+ uiDefButF(block, NUMSLI, B_NODE_EXEC, "Sat: ",
+ butr->xmin, butr->ymin+20.0f, butr->xmax-butr->xmin, 20,
+ &nhs->sat, 0.0f, 2.0f, 100, 0, "");
+ uiDefButF(block, NUMSLI, B_NODE_EXEC, "Val: ",
+ butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
+ &nhs->val, 0.0f, 2.0f, 100, 0, "");
+ }
+ return 60;
+}
+
+static int node_composit_buts_dilateerode(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ uiDefButS(block, NUM, B_NODE_EXEC, "Distance:",
+ butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
+ &node->custom2, -100, 100, 0, 0, "Distance to grow/shrink (number of iterations)");
+ }
+ return 20;
+}
+
+static int node_composit_buts_diff_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ short sx= (butr->xmax-butr->xmin)/4;
+ short dx= (butr->xmax-butr->xmin)/3;
+ NodeChroma *c= node->storage;
+
+ uiBlockBeginAlign(block);
+ /*color space selectors*/
+ uiDefButS(block, ROW,B_NODE_EXEC,"RGB",
+ butr->xmin,butr->ymin+60,sx,20,
+ &node->custom1,1,1, 0, 0, "RGB Color Space");
+ uiDefButS(block, ROW,B_NODE_EXEC,"HSV",
+ butr->xmin+sx,butr->ymin+60,sx,20,
+ &node->custom1,1,2, 0, 0, "HSV Color Space");
+ uiDefButS(block, ROW,B_NODE_EXEC,"YUV",
+ butr->xmin+2*sx,butr->ymin+60,sx,20,
+ &node->custom1,1,3, 0, 0, "YUV Color Space");
+ uiDefButS(block, ROW,B_NODE_EXEC,"YCC",
+ butr->xmin+3*sx,butr->ymin+60,sx,20,
+ &node->custom1,1,4, 0, 0, "YCbCr Color Space");
+ /*channel tolorences*/
+ uiDefButF(block, NUM, B_NODE_EXEC, " ",
+ butr->xmin, butr->ymin+40, dx, 20,
+ &c->t1, 0.0f, 1.0f, 100, 0, "Channel 1 Tolerance");
+ uiDefButF(block, NUM, B_NODE_EXEC, " ",
+ butr->xmin+dx, butr->ymin+40, dx, 20,
+ &c->t2, 0.0f, 1.0f, 100, 0, "Channel 2 Tolorence");
+ uiDefButF(block, NUM, B_NODE_EXEC, " ",
+ butr->xmin+2*dx, butr->ymin+40, dx, 20,
+ &c->t3, 0.0f, 1.0f, 100, 0, "Channel 3 Tolorence");
+ /*falloff parameters*/
+ /*
+ uiDefButF(block, NUMSLI, B_NODE_EXEC, "Falloff Size ",
+ butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20,
+ &c->fsize, 0.0f, 1.0f, 100, 0, "");
+ */
+ uiDefButF(block, NUMSLI, B_NODE_EXEC, "Falloff: ",
+ butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20,
+ &c->fstrength, 0.0f, 1.0f, 100, 0, "");
+ }
+ return 80;
+}
+
+static int node_composit_buts_color_spill(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ short dx= (butr->xmax-butr->xmin)/3;
+
+ NodeChroma *c=node->storage;
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_NODE_EXEC, "Enhance: ",
+ butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20,
+ &c->t1, 0.0f, 0.5f, 100, 2, "Adjusts how much selected channel is affected by color spill algorithm");
+ uiDefButS(block, ROW, B_NODE_EXEC, "R",
+ butr->xmin,butr->ymin,dx,20,
+ &node->custom1,1,1, 0, 0, "Red Spill Suppression");
+ uiDefButS(block, ROW, B_NODE_EXEC, "G",
+ butr->xmin+dx,butr->ymin,dx,20,
+ &node->custom1,1,2, 0, 0, "Green Spill Suppression");
+ uiDefButS(block, ROW, B_NODE_EXEC, "B",
+ butr->xmin+2*dx,butr->ymin,dx,20,
+ &node->custom1, 1, 3, 0, 0, "Blue Spill Suppression");
+ uiBlockEndAlign(block);
+ }
+ return 60;
+}
+
+static int node_composit_buts_chroma_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ short dx=(butr->xmax-butr->xmin)/2;
+ NodeChroma *c= node->storage;
+ uiBlockBeginAlign(block);
+
+ uiDefButF(block, NUMSLI, B_NODE_EXEC, "Acceptance ",
+ butr->xmin, butr->ymin+60, butr->xmax-butr->xmin, 20,
+ &c->t1, 1.0f, 80.0f, 100, 0, "Tolerance for colors to be considered a keying color");
+ uiDefButF(block, NUMSLI, B_NODE_EXEC, "Cutoff ",
+ butr->xmin, butr->ymin+40, butr->xmax-butr->xmin, 20,
+ &c->t2, 0.0f, 30.0f, 100, 0, "Colors below this will be considered as exact matches for keying color");
+
+ uiDefButF(block, NUMSLI, B_NODE_EXEC, "Lift ",
+ butr->xmin, butr->ymin+20, dx, 20,
+ &c->fsize, 0.0f, 1.0f, 100, 0, "Alpha Lift");
+ uiDefButF(block, NUMSLI, B_NODE_EXEC, "Gain ",
+ butr->xmin+dx, butr->ymin+20, dx, 20,
+ &c->fstrength, 0.0f, 1.0f, 100, 0, "Alpha Gain");
+
+ uiDefButF(block, NUMSLI, B_NODE_EXEC, "Shadow Adjust ",
+ butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
+ &c->t3, 0.0f, 1.0f, 100, 0, "Adjusts the brightness of any shadows captured");
+
+ if(c->t2 > c->t1)
+ c->t2=c->t1;
+ }
+ return 80;
+}
+
+static int node_composit_buts_channel_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ short sx= (butr->xmax-butr->xmin)/4;
+ short cx= (butr->xmax-butr->xmin)/3;
+ NodeChroma *c=node->storage;
+ char *c1, *c2, *c3;
+
+ /*color space selectors*/
+ uiBlockBeginAlign(block);
+ uiDefButS(block, ROW,B_NODE_EXEC,"RGB",
+ butr->xmin,butr->ymin+60,sx,20,&node->custom1,1,1, 0, 0, "RGB Color Space");
+ uiDefButS(block, ROW,B_NODE_EXEC,"HSV",
+ butr->xmin+sx,butr->ymin+60,sx,20,&node->custom1,1,2, 0, 0, "HSV Color Space");
+ uiDefButS(block, ROW,B_NODE_EXEC,"YUV",
+ butr->xmin+2*sx,butr->ymin+60,sx,20,&node->custom1,1,3, 0, 0, "YUV Color Space");
+ uiDefButS(block, ROW,B_NODE_EXEC,"YCC",
+ butr->xmin+3*sx,butr->ymin+60,sx,20,&node->custom1,1,4, 0, 0, "YCbCr Color Space");
+
+ if (node->custom1==1) {
+ c1="R"; c2="G"; c3="B";
+ }
+ else if(node->custom1==2){
+ c1="H"; c2="S"; c3="V";
+ }
+ else if(node->custom1==3){
+ c1="Y"; c2="U"; c3="V";
+ }
+ else { // if(node->custom1==4){
+ c1="Y"; c2="Cb"; c3="Cr";
+ }
+
+ /*channel selector */
+ uiDefButS(block, ROW, B_NODE_EXEC, c1,
+ butr->xmin,butr->ymin+40,cx,20,&node->custom2,1, 1, 0, 0, "Channel 1");
+ uiDefButS(block, ROW, B_NODE_EXEC, c2,
+ butr->xmin+cx,butr->ymin+40,cx,20,&node->custom2,1, 2, 0, 0, "Channel 2");
+ uiDefButS(block, ROW, B_NODE_EXEC, c3,
+ butr->xmin+cx+cx,butr->ymin+40,cx,20,&node->custom2, 1, 3, 0, 0, "Channel 3");
+
+ /*tolerance sliders */
+ uiDefButF(block, NUMSLI, B_NODE_EXEC, "High ",
+ butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20,
+ &c->t1, 0.0f, 1.0f, 100, 0, "Values higher than this setting are 100% opaque");
+ uiDefButF(block, NUMSLI, B_NODE_EXEC, "Low ",
+ butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
+ &c->t2, 0.0f, 1.0f, 100, 0, "Values lower than this setting are 100% keyed");
+ uiBlockEndAlign(block);
+
+ /*keep t2 (low) less than t1 (high) */
+ if(c->t2 > c->t1) {
+ c->t2=c->t1;
+ }
+ }
+ return 80;
+}
+
+static int node_composit_buts_luma_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ NodeChroma *c=node->storage;
+
+ /*tolerance sliders */
+ uiDefButF(block, NUMSLI, B_NODE_EXEC, "High ",
+ butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20,
+ &c->t1, 0.0f, 1.0f, 100, 0, "Values higher than this setting are 100% opaque");
+ uiDefButF(block, NUMSLI, B_NODE_EXEC, "Low ",
+ butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
+ &c->t2, 0.0f, 1.0f, 100, 0, "Values lower than this setting are 100% keyed");
+ uiBlockEndAlign(block);
+
+ /*keep t2 (low) less than t1 (high) */
+ if(c->t2 > c->t1) {
+ c->t2=c->t1;
+ }
+ }
+ return 40;
+}
+
+static int node_composit_buts_map_uv(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ uiDefButS(block, NUM, B_NODE_EXEC, "Alpha:",
+ butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
+ &node->custom1, 0, 100, 0, 0, "Conversion percentage of UV differences to Alpha");
+ }
+ return 20;
+}
+
+static int node_composit_buts_id_mask(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ uiDefButS(block, NUM, B_NODE_EXEC, "ID:",
+ butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
+ &node->custom1, 0, 10000, 0, 0, "Pass Index number to convert to Alpha");
+ }
+ return 20;
+}
+
+/* allocate sufficient! */
+static void node_imagetype_string(char *str)
+{
+ str += sprintf(str, "Save Image as: %%t|");
+ str += sprintf(str, "Targa %%x%d|", R_TARGA);
+ str += sprintf(str, "Targa Raw %%x%d|", R_RAWTGA);
+ str += sprintf(str, "PNG %%x%d|", R_PNG);
+ str += sprintf(str, "BMP %%x%d|", R_BMP);
+ str += sprintf(str, "Jpeg %%x%d|", R_JPEG90);
+ str += sprintf(str, "Iris %%x%d|", R_IRIS);
+ str += sprintf(str, "Radiance HDR %%x%d|", R_RADHDR);
+ str += sprintf(str, "Cineon %%x%d|", R_CINEON);
+ str += sprintf(str, "DPX %%x%d|", R_DPX);
+ str += sprintf(str, "OpenEXR %%x%d", R_OPENEXR);
+}
+
+static void node_set_image_cb(bContext *C, void *ntree_v, void *node_v)
+{
+ bNodeTree *ntree= ntree_v;
+ bNode *node= node_v;
+
+ nodeSetActive(ntree, node);
+}
+
+static int node_composit_buts_file_output(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ NodeImageFile *nif= node->storage;
+ uiBut *bt;
+ short x= (short)butr->xmin;
+ short y= (short)butr->ymin;
+ short w= (short)butr->xmax-butr->xmin;
+ char str[320];
+
+ node_imagetype_string(str);
+
+ uiBlockBeginAlign(block);
+
+ bt = uiDefIconBut(block, BUT, B_NODE_SETIMAGE, ICON_FILESEL,
+ x, y+60, 20, 20,
+ 0, 0, 0, 0, 0, "Open Fileselect to get Backbuf image");
+ uiButSetFunc(bt, node_set_image_cb, ntree, node);
+
+ uiDefBut(block, TEX, B_NOP, "",
+ 20+x, y+60, w-20, 20,
+ nif->name, 0.0f, 240.0f, 0, 0, "");
+
+ uiDefButS(block, MENU, B_NOP, str,
+ x, y+40, w, 20,
+ &nif->imtype, 0.0f, 1.0f, 0, 0, "");
+
+ if(nif->imtype==R_OPENEXR) {
+ uiDefButBitS(block, TOG, R_OPENEXR_HALF, B_REDR, "Half",
+ x, y+20, w/2, 20,
+ &nif->subimtype, 0, 0, 0, 0, "");
+
+ uiDefButS(block, MENU,B_NOP, "Codec %t|None %x0|Pxr24 (lossy) %x1|ZIP (lossless) %x2|PIZ (lossless) %x3|RLE (lossless) %x4",
+ x+w/2, y+20, w/2, 20,
+ &nif->codec, 0, 0, 0, 0, "");
+ }
+ else {
+ uiDefButS(block, NUM, B_NOP, "Quality: ",
+ x, y+20, w, 20,
+ &nif->quality, 10.0f, 100.0f, 10, 0, "");
+ }
+
+ /* start frame, end frame */
+ uiDefButI(block, NUM, B_NODE_EXEC, "SFra: ",
+ x, y, w/2, 20,
+ &nif->sfra, 1, MAXFRAMEF, 10, 0, "");
+ uiDefButI(block, NUM, B_NODE_EXEC, "EFra: ",
+ x+w/2, y, w/2, 20,
+ &nif->efra, 1, MAXFRAMEF, 10, 0, "");
+
+ }
+ return 80;
+}
+
+static void node_scale_cb(bContext *C, void *node_v, void *unused_v)
+{
+ bNode *node= node_v;
+ bNodeSocket *nsock;
+
+ /* check the 2 inputs, and set them to reasonable values */
+ for(nsock= node->inputs.first; nsock; nsock= nsock->next) {
+ if(ELEM(node->custom1, CMP_SCALE_RELATIVE, CMP_SCALE_SCENEPERCENT))
+ nsock->ns.vec[0]= 1.0;
+ else {
+ if(nsock->next==NULL)
+ nsock->ns.vec[0]= (float)CTX_data_scene(C)->r.ysch;
+ else
+ nsock->ns.vec[0]= (float)CTX_data_scene(C)->r.xsch;
+ }
+ }
+}
+
+static int node_composit_buts_scale(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ uiBut *bt= uiDefButS(block, MENU, B_NODE_EXEC, "Relative %x0|Absolute %x1|Scene Size % %x2|",
+ butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
+ &node->custom1, 0, 0, 0, 0, "Scale new image to absolute pixel size, size relative to the incoming image, or using the 'percent' size of the scene");
+ uiButSetFunc(bt, node_scale_cb, node, NULL);
+ }
+ return 20;
+}
+
+static int node_composit_buts_invert(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, CMP_CHAN_RGB, B_NODE_EXEC, "RGB",
+ butr->xmin, butr->ymin, (butr->xmax-butr->xmin)/2, 20,
+ &node->custom1, 0, 0, 0, 0, "");
+ uiDefButBitS(block, TOG, CMP_CHAN_A, B_NODE_EXEC, "A",
+ butr->xmin+(butr->xmax-butr->xmin)/2, butr->ymin, (butr->xmax-butr->xmin)/2, 20,
+ &node->custom1, 0, 0, 0, 0, "");
+ uiBlockEndAlign(block);
+ }
+ return 20;
+}
+
+static int node_composit_buts_premulkey(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ uiBut *bt;
+
+ /* blend type */
+ bt=uiDefButS(block, MENU, B_NODE_EXEC, "Key to Premul %x0|Premul to Key %x1",
+ butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
+ &node->custom1, 0, 0, 0, 0, "Conversion between premultiplied alpha and key alpha");
+ }
+ return 20;
+}
+
+/* only once called */
+static void node_composit_set_butfunc(bNodeType *ntype)
+{
+ switch(ntype->type) {
+ /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */
+
+ case CMP_NODE_IMAGE:
+ ntype->butfunc= node_composit_buts_image;
+ break;
+ case CMP_NODE_R_LAYERS:
+ ntype->butfunc= node_composit_buts_renderlayers;
+ break;
+ case CMP_NODE_NORMAL:
+ ntype->butfunc= node_buts_normal;
+ break;
+ case CMP_NODE_CURVE_VEC:
+ ntype->butfunc= node_buts_curvevec;
+ break;
+ case CMP_NODE_CURVE_RGB:
+ ntype->butfunc= node_buts_curvecol;
+ break;
+ case CMP_NODE_VALUE:
+ ntype->butfunc= node_buts_value;
+ break;
+ case CMP_NODE_RGB:
+ ntype->butfunc= node_buts_rgb;
+ break;
+ case CMP_NODE_FLIP:
+ ntype->butfunc= node_composit_buts_flip;
+ break;
+ case CMP_NODE_SPLITVIEWER:
+ ntype->butfunc= node_composit_buts_splitviewer;
+ break;
+ case CMP_NODE_MIX_RGB:
+ ntype->butfunc= node_buts_mix_rgb;
+ break;
+ case CMP_NODE_VALTORGB:
+ ntype->butfunc= node_buts_valtorgb;
+ break;
+ case CMP_NODE_CROP:
+ ntype->butfunc= node_composit_buts_crop;
+ break;
+ case CMP_NODE_BLUR:
+ ntype->butfunc= node_composit_buts_blur;
+ break;
+ case CMP_NODE_DBLUR:
+ ntype->butfunc= node_composit_buts_dblur;
+ break;
+ case CMP_NODE_BILATERALBLUR:
+ ntype->butfunc= node_composit_buts_bilateralblur;
+ break;
+ /* qdn: defocus node */
+ case CMP_NODE_DEFOCUS:
+ ntype->butfunc = node_composit_buts_defocus;
+ break;
+ /* qdn: glare node */
+ case CMP_NODE_GLARE:
+ ntype->butfunc = node_composit_buts_glare;
+ break;
+ /* qdn: tonemap node */
+ case CMP_NODE_TONEMAP:
+ ntype->butfunc = node_composit_buts_tonemap;
+ break;
+ /* qdn: lens distortion node */
+ case CMP_NODE_LENSDIST:
+ ntype->butfunc = node_composit_buts_lensdist;
+ break;
+ case CMP_NODE_VECBLUR:
+ ntype->butfunc= node_composit_buts_vecblur;
+ break;
+ case CMP_NODE_FILTER:
+ ntype->butfunc= node_composit_buts_filter;
+ break;
+ case CMP_NODE_MAP_VALUE:
+ ntype->butfunc= node_composit_buts_map_value;
+ break;
+ case CMP_NODE_TIME:
+ ntype->butfunc= node_buts_time;
+ break;
+ case CMP_NODE_ALPHAOVER:
+ ntype->butfunc= node_composit_buts_alphaover;
+ break;
+ case CMP_NODE_HUE_SAT:
+ ntype->butfunc= node_composit_buts_hue_sat;
+ break;
+ case CMP_NODE_TEXTURE:
+ ntype->butfunc= node_buts_texture;
+ break;
+ case CMP_NODE_DILATEERODE:
+ ntype->butfunc= node_composit_buts_dilateerode;
+ break;
+ case CMP_NODE_OUTPUT_FILE:
+ ntype->butfunc= node_composit_buts_file_output;
+ break;
+
+ case CMP_NODE_DIFF_MATTE:
+ ntype->butfunc=node_composit_buts_diff_matte;
+ break;
+ case CMP_NODE_COLOR_SPILL:
+ ntype->butfunc=node_composit_buts_color_spill;
+ break;
+ case CMP_NODE_CHROMA:
+ ntype->butfunc=node_composit_buts_chroma_matte;
+ break;
+ case CMP_NODE_SCALE:
+ ntype->butfunc= node_composit_buts_scale;
+ break;
+ case CMP_NODE_CHANNEL_MATTE:
+ ntype->butfunc= node_composit_buts_channel_matte;
+ break;
+ case CMP_NODE_LUMA_MATTE:
+ ntype->butfunc= node_composit_buts_luma_matte;
+ break;
+ case CMP_NODE_MAP_UV:
+ ntype->butfunc= node_composit_buts_map_uv;
+ break;
+ case CMP_NODE_ID_MASK:
+ ntype->butfunc= node_composit_buts_id_mask;
+ break;
+ case CMP_NODE_MATH:
+ ntype->butfunc= node_buts_math;
+ break;
+ case CMP_NODE_INVERT:
+ ntype->butfunc= node_composit_buts_invert;
+ break;
+ case CMP_NODE_PREMULKEY:
+ ntype->butfunc= node_composit_buts_premulkey;
+ break;
+ default:
+ ntype->butfunc= NULL;
+ }
+}
+
+/* ****************** BUTTON CALLBACKS FOR TEXTURE NODES ***************** */
+
+static int node_texture_buts_bricks(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ short w = butr->xmax-butr->xmin;
+ short ofw = 32;
+
+ uiBlockBeginAlign(block);
+
+ /* Offset */
+ uiDefButF(
+ block, NUM, B_NODE_EXEC, "Offset",
+ butr->xmin, butr->ymin+20, w-ofw, 20,
+ &node->custom3,
+ 0, 1, 0.25, 2,
+ "Offset amount" );
+ uiDefButS(
+ block, NUM, B_NODE_EXEC, "",
+ butr->xmin+w-ofw, butr->ymin+20, ofw, 20,
+ &node->custom1,
+ 2, 99, 0, 0,
+ "Offset every N rows" );
+
+ /* Squash */
+ uiDefButF(
+ block, NUM, B_NODE_EXEC, "Squash",
+ butr->xmin, butr->ymin+0, w-ofw, 20,
+ &node->custom4,
+ 0, 99, 0.25, 2,
+ "Stretch amount" );
+ uiDefButS(
+ block, NUM, B_NODE_EXEC, "",
+ butr->xmin+w-ofw, butr->ymin+0, ofw, 20,
+ &node->custom2,
+ 2, 99, 0, 0,
+ "Stretch every N rows" );
+
+ uiBlockEndAlign(block);
+ }
+ return 40;
+}
+
+/* Copied from buttons_shading.c -- needs unifying */
+static char* noisebasis_menu()
+{
+ static char nbmenu[256];
+ sprintf(nbmenu, "Noise Basis %%t|Blender Original %%x%d|Original Perlin %%x%d|Improved Perlin %%x%d|Voronoi F1 %%x%d|Voronoi F2 %%x%d|Voronoi F3 %%x%d|Voronoi F4 %%x%d|Voronoi F2-F1 %%x%d|Voronoi Crackle %%x%d|CellNoise %%x%d", TEX_BLENDER, TEX_STDPERLIN, TEX_NEWPERLIN, TEX_VORONOI_F1, TEX_VORONOI_F2, TEX_VORONOI_F3, TEX_VORONOI_F4, TEX_VORONOI_F2F1, TEX_VORONOI_CRACKLE, TEX_CELLNOISE);
+ return nbmenu;
+}
+
+static int node_texture_buts_proc(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ Tex *tex = (Tex *)node->storage;
+ short x,y,w,h;
+
+ if( block ) {
+ x = butr->xmin;
+ y = butr->ymin;
+ w = butr->xmax - x;
+ h = butr->ymax - y;
+ }
+ else
+ return 0;
+
+ switch( tex->type ) {
+ case TEX_BLEND:
+ if( block ) {
+ uiBlockBeginAlign( block );
+ uiDefButS( block, MENU, B_NODE_EXEC,
+ "Linear %x0|Quad %x1|Ease %x2|Diag %x3|Sphere %x4|Halo %x5|Radial %x6",
+ x, y+20, w, 20, &tex->stype, 0, 1, 0, 0, "Blend Type" );
+ uiDefButBitS(block, TOG, TEX_FLIPBLEND, B_NODE_EXEC, "Flip XY", x, y, w, 20,
+ &tex->flag, 0, 0, 0, 0, "Flips the direction of the progression 90 degrees");
+ uiBlockEndAlign( block );
+ }
+ return 40;
+
+
+ case TEX_MARBLE:
+ if( block ) {
+ uiBlockBeginAlign(block);
+
+ uiDefButS(block, ROW, B_NODE_EXEC, "Soft", 0*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SOFT, 0, 0, "Uses soft marble");
+ uiDefButS(block, ROW, B_NODE_EXEC, "Sharp", 1*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SHARP, 0, 0, "Uses more clearly defined marble");
+ uiDefButS(block, ROW, B_NODE_EXEC, "Sharper", 2*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SHARPER, 0, 0, "Uses very clearly defined marble");
+
+ uiDefButS(block, ROW, B_NODE_EXEC, "Soft noise", 0*w/2+x, 20+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise");
+ uiDefButS(block, ROW, B_NODE_EXEC, "Hard noise", 1*w/2+x, 20+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise");
+
+ uiDefButS(block, ROW, B_NODE_EXEC, "Sin", 0*w/3+x, 0+y, w/3, 18, &tex->noisebasis2, 8.0, 0.0, 0, 0, "Uses a sine wave to produce bands.");
+ uiDefButS(block, ROW, B_NODE_EXEC, "Saw", 1*w/3+x, 0+y, w/3, 18, &tex->noisebasis2, 8.0, 1.0, 0, 0, "Uses a saw wave to produce bands");
+ uiDefButS(block, ROW, B_NODE_EXEC, "Tri", 2*w/3+x, 0+y, w/3, 18, &tex->noisebasis2, 8.0, 2.0, 0, 0, "Uses a triangle wave to produce bands");
+
+ uiBlockEndAlign(block);
+ }
+ return 60;
+
+ case TEX_WOOD:
+ if( block ) {
+ uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y+64, w, 18, &tex->noisebasis, 0,0,0,0, "Sets the noise basis used for turbulence");
+
+ uiBlockBeginAlign(block);
+ uiDefButS(block, ROW, B_TEXPRV, "Bands", x, 40+y, w/2, 18, &tex->stype, 2.0, (float)TEX_BANDNOISE, 0, 0, "Uses standard noise");
+ uiDefButS(block, ROW, B_TEXPRV, "Rings", w/2+x, 40+y, w/2, 18, &tex->stype, 2.0, (float)TEX_RINGNOISE, 0, 0, "Lets Noise return RGB value");
+
+ uiDefButS(block, ROW, B_NODE_EXEC, "Sin", 0*w/3+x, 20+y, w/3, 18, &tex->noisebasis2, 8.0, (float)TEX_SIN, 0, 0, "Uses a sine wave to produce bands.");
+ uiDefButS(block, ROW, B_NODE_EXEC, "Saw", 1*w/3+x, 20+y, w/3, 18, &tex->noisebasis2, 8.0, (float)TEX_SAW, 0, 0, "Uses a saw wave to produce bands");
+ uiDefButS(block, ROW, B_NODE_EXEC, "Tri", 2*w/3+x, 20+y, w/3, 18, &tex->noisebasis2, 8.0, (float)TEX_TRI, 0, 0, "Uses a triangle wave to produce bands");
+
+ uiDefButS(block, ROW, B_NODE_EXEC, "Soft noise", 0*w/2+x, 0+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise");
+ uiDefButS(block, ROW, B_NODE_EXEC, "Hard noise", 1*w/2+x, 0+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise");
+ uiBlockEndAlign(block);
+ }
+ return 80;
+
+ case TEX_CLOUDS:
+ if( block ) {
+ uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y+60, w, 18, &tex->noisebasis, 0,0,0,0, "Sets the noise basis used for turbulence");
+
+ uiBlockBeginAlign(block);
+ uiDefButS(block, ROW, B_TEXPRV, "B/W", x, y+38, w/2, 18, &tex->stype, 2.0, (float)TEX_DEFAULT, 0, 0, "Uses standard noise");
+ uiDefButS(block, ROW, B_TEXPRV, "Color", w/2+x, y+38, w/2, 18, &tex->stype, 2.0, (float)TEX_COLOR, 0, 0, "Lets Noise return RGB value");
+ uiDefButS(block, ROW, B_TEXPRV, "Soft", x, y+20, w/2, 18, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise");
+ uiDefButS(block, ROW, B_TEXPRV, "Hard", w/2+x, y+20, w/2, 18, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise");
+ uiBlockEndAlign(block);
+
+ uiDefButS(block, NUM, B_TEXPRV, "Depth:", x, y, w, 18, &tex->noisedepth, 0.0, 6.0, 0, 0, "Sets the depth of the cloud calculation");
+ }
+ return 80;
+
+ case TEX_DISTNOISE:
+ if( block ) {
+ uiBlockBeginAlign(block);
+ uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y+18, w, 18, &tex->noisebasis2, 0,0,0,0, "Sets the noise basis to distort");
+ uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y, w, 18, &tex->noisebasis, 0,0,0,0, "Sets the noise basis which does the distortion");
+ uiBlockEndAlign(block);
+ }
+ return 36;
+ }
+ return 0;
+}
+
+static int node_texture_buts_image(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ char *strp;
+ uiBut *bt;
+
+ if( block ) {
+ uiBlockBeginAlign(block);
+
+ /* browse button */
+ IMAnames_to_pupstring(&strp, NULL, "LOAD NEW %x32767", &(G.main->image), NULL, NULL);
+ node->menunr= 0;
+ bt= uiDefButS(block, MENU, B_NOP, strp,
+ butr->xmin, butr->ymin, 19, 19,
+ &node->menunr, 0, 0, 0, 0, "Browses existing choices");
+ uiButSetFunc(bt, node_browse_image_cb, ntree, node);
+ if(strp) MEM_freeN(strp);
+
+ /* Add New button */
+ if(node->id==NULL) {
+ bt= uiDefBut(block, BUT, B_NODE_LOADIMAGE, "Load New",
+ butr->xmin+19, butr->ymin, (short)(butr->xmax-butr->xmin-19.0f), 19,
+ NULL, 0.0, 0.0, 0, 0, "Add new Image");
+ uiButSetFunc(bt, node_active_cb, ntree, node);
+ }
+ else {
+ /* name button */
+ short xmin= (short)butr->xmin, xmax= (short)butr->xmax;
+ short width= xmax - xmin - 19;
+
+ bt= uiDefBut(block, TEX, B_NOP, "IM:",
+ xmin+19, butr->ymin, width, 19,
+ node->id->name+2, 0.0, 19.0, 0, 0, "Image name");
+ uiButSetFunc(bt, node_ID_title_cb, node, NULL);
+ }
+ }
+ return 20;
+}
+
+static int node_texture_buts_output(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if( block ) {
+ uiBut *bt;
+ short width;
+ char *name = ((TexNodeOutput*)node->storage)->name;
+
+ uiBlockBeginAlign(block);
+
+ width = (short)(butr->xmax - butr->xmin);
+
+ bt = uiDefBut(
+ block, TEX, B_NOP,
+ "Name:",
+ butr->xmin, butr->ymin,
+ width, 19,
+ name, 0, 31,
+ 0, 0,
+ "Name this output"
+ );
+
+ uiBlockEndAlign(block);
+ }
+ return 19;
+}
+
+/* only once called */
+static void node_texture_set_butfunc(bNodeType *ntype)
+{
+ if( ntype->type >= TEX_NODE_PROC && ntype->type < TEX_NODE_PROC_MAX ) {
+ ntype->butfunc = node_texture_buts_proc;
+ }
+ else switch(ntype->type) {
+
+ case TEX_NODE_MATH:
+ ntype->butfunc = node_buts_math;
+ break;
+
+ case TEX_NODE_MIX_RGB:
+ ntype->butfunc = node_buts_mix_rgb;
+ break;
+
+ case TEX_NODE_VALTORGB:
+ ntype->butfunc = node_buts_valtorgb;
+ break;
+
+ case TEX_NODE_CURVE_RGB:
+ ntype->butfunc= node_buts_curvecol;
+ break;
+
+ case TEX_NODE_CURVE_TIME:
+ ntype->butfunc = node_buts_time;
+ break;
+
+ case TEX_NODE_TEXTURE:
+ ntype->butfunc = node_buts_texture;
+ break;
+
+ case TEX_NODE_BRICKS:
+ ntype->butfunc = node_texture_buts_bricks;
+ break;
+
+ case TEX_NODE_IMAGE:
+ ntype->butfunc = node_texture_buts_image;
+ break;
+
+ case TEX_NODE_OUTPUT:
+ ntype->butfunc = node_texture_buts_output;
+ break;
+
+ default:
+ ntype->butfunc= NULL;
+ }
+}
+
+/* ******* init draw callbacks for all tree types, only called in usiblender.c, once ************* */
+
+void ED_init_node_butfuncs(void)
+{
+ bNodeType *ntype;
+
+ /* shader nodes */
+ ntype= node_all_shaders.first;
+ while(ntype) {
+ node_shader_set_butfunc(ntype);
+ ntype= ntype->next;
+ }
+ /* composit nodes */
+ ntype= node_all_composit.first;
+ while(ntype) {
+ node_composit_set_butfunc(ntype);
+ ntype= ntype->next;
+ }
+ ntype = node_all_textures.first;
+ while(ntype) {
+ node_texture_set_butfunc(ntype);
+ ntype= ntype->next;
+ }
+}
+
+/* ************** Generic drawing ************** */
+
+#if 0
+void node_rename_but(char *s)
+{
+ uiBlock *block;
+ ListBase listb={0, 0};
+ int dy, x1, y1, sizex=80, sizey=30;
+ short pivot[2], mval[2], ret=0;
+
+ 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;
+ dy= sizey/2;
+
+ block= uiNewBlock(&listb, "button", UI_EMBOSS, UI_HELV, G.curscreen->mainwin);
+ uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT|UI_BLOCK_ENTER_OK);
+
+ /* buttons have 0 as return event, to prevent menu to close on hotkeys */
+ uiBlockBeginAlign(block);
+
+ uiDefBut(block, TEX, B_NOP, "Name: ", (short)(x1),(short)(y1+dy), 150, 19, s, 0.0, 19.0, 0, 0, "Node user name");
+
+ uiBlockEndAlign(block);
+
+ uiDefBut(block, BUT, 32767, "OK", (short)(x1+150), (short)(y1+dy), 29, 19, NULL, 0, 0, 0, 0, "");
+
+ uiBoundsBlock(block, 2);
+
+ ret= uiDoBlocks(&listb, 0, 0);
+}
+
+#endif
+
+void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode)
+{
+
+ if((snode->flag & SNODE_BACKDRAW) && snode->treetype==NTREE_COMPOSIT) {
+ Image *ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
+ if(ibuf) {
+ float x, y;
+ /* somehow the offset has to be calculated inverse */
+
+ glaDefine2DArea(&ar->winrct);
+ /* ortho at pixel level curarea */
+ wmOrtho2(-0.375, ar->winx-0.375, -0.375, ar->winy-0.375);
+
+ x = (ar->winx-ibuf->x)/2 + snode->xof;
+ y = (ar->winy-ibuf->y)/2 + snode->yof;
+
+ if(ibuf->rect)
+ glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ else if(ibuf->channels==4)
+ glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_FLOAT, ibuf->rect_float);
+
+ /* sort this out, this should not be needed */
+ wmOrtho2(ar->v2d.cur.xmin, ar->v2d.cur.xmax, ar->v2d.cur.ymin, ar->v2d.cur.ymax);
+ glLoadIdentity();
+ }
+ }
+}
+
+#if 0
+/* note: needs to be userpref or opengl profile option */
+static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode)
+{
+
+ draw_nodespace_grid(snode);
+
+ if(snode->flag & SNODE_BACKDRAW) {
+ Image *ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
+ if(ibuf) {
+ int x, y;
+ float zoom = 1.0;
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+
+ glaDefine2DArea(&sa->winrct);
+
+ if(ibuf->x > sa->winx || ibuf->y > sa->winy) {
+ float zoomx, zoomy;
+ zoomx= (float)sa->winx/ibuf->x;
+ zoomy= (float)sa->winy/ibuf->y;
+ zoom = MIN2(zoomx, zoomy);
+ }
+
+ x = (sa->winx-zoom*ibuf->x)/2 + snode->xof;
+ y = (sa->winy-zoom*ibuf->y)/2 + snode->yof;
+
+ glPixelZoom(zoom, zoom);
+
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ if(ibuf->rect)
+ glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect);
+ else if(ibuf->channels==4)
+ glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_FLOAT, ibuf->rect_float);
+
+ glPixelZoom(1.0, 1.0);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+ }
+}
+#endif
+
+/* if v2d not NULL, it clips and returns 0 if not visible */
+int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol)
+{
+ float dist, vec[4][2];
+
+ /* in v0 and v3 we put begin/end points */
+ if(link->fromsock) {
+ vec[0][0]= link->fromsock->locx;
+ vec[0][1]= link->fromsock->locy;
+ }
+ else {
+ if(snode==NULL) return 0;
+ vec[0][0]= snode->mx;
+ vec[0][1]= snode->my;
+ }
+ if(link->tosock) {
+ vec[3][0]= link->tosock->locx;
+ vec[3][1]= link->tosock->locy;
+ }
+ else {
+ if(snode==NULL) return 0;
+ vec[3][0]= snode->mx;
+ vec[3][1]= snode->my;
+ }
+
+ dist= 0.5f*ABS(vec[0][0] - vec[3][0]);
+
+ /* check direction later, for top sockets */
+ vec[1][0]= vec[0][0]+dist;
+ vec[1][1]= vec[0][1];
+
+ vec[2][0]= vec[3][0]-dist;
+ vec[2][1]= vec[3][1];
+
+ if(v2d && MIN4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax); /* clipped */
+ else if (v2d && MAX4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < v2d->cur.xmin); /* clipped */
+ else {
+
+ /* always do all three, to prevent data hanging around */
+ forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0], resol, 2);
+ forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1], coord_array[0]+1, resol, 2);
+
+ return 1;
+ }
+ return 0;
+}
+
+#define LINK_RESOL 24
+void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int th_col2, int do_shaded)
+{
+ float coord_array[LINK_RESOL+1][2];
+
+ if(node_link_bezier_points(v2d, snode, link, coord_array, LINK_RESOL)) {
+ float dist, spline_step = 0.0f;
+ int i;
+
+ /* we can reuse the dist variable here to increment the GL curve eval amount*/
+ dist = 1.0f/(float)LINK_RESOL;
+
+ glBegin(GL_LINE_STRIP);
+ for(i=0; i<=LINK_RESOL; i++) {
+ if(do_shaded) {
+ UI_ThemeColorBlend(th_col1, th_col2, spline_step);
+ spline_step += dist;
+ }
+ glVertex2fv(coord_array[i]);
+ }
+ glEnd();
+ }
+}
+
+/* note; this is used for fake links in groups too */
+void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
+{
+ int do_shaded= 1, th_col1= TH_WIRE, th_col2= TH_WIRE;
+
+ if(link->fromnode==NULL && link->tonode==NULL)
+ return;
+
+ if(link->fromnode==NULL || link->tonode==NULL) {
+ UI_ThemeColor(TH_WIRE);
+ do_shaded= 0;
+ }
+ else {
+ /* going to give issues once... */
+ if(link->tosock->flag & SOCK_UNAVAIL)
+ return;
+ if(link->fromsock->flag & SOCK_UNAVAIL)
+ return;
+
+ /* a bit ugly... but thats how we detect the internal group links */
+ if(link->fromnode==link->tonode) {
+ UI_ThemeColorBlend(TH_BACK, TH_WIRE, 0.25f);
+ do_shaded= 0;
+ }
+ else {
+ /* check cyclic */
+ if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) {
+ if(link->fromnode->flag & SELECT)
+ th_col1= TH_EDGE_SELECT;
+ if(link->tonode->flag & SELECT)
+ th_col2= TH_EDGE_SELECT;
+ }
+ else {
+ UI_ThemeColor(TH_REDALERT);
+ do_shaded= 0;
+ }
+ }
+ }
+
+ node_draw_link_bezier(v2d, snode, link, th_col1, th_col2, do_shaded);
+}
+
+#if 0
+
+static void nodes_panel_gpencil(short cntrl) // NODES_HANDLER_GREASEPENCIL
+{
+ uiBlock *block;
+ SpaceNode *snode;
+
+ snode= curarea->spacedata.first;
+
+ block= uiNewBlock(&curarea->uiblocks, "nodes_panel_gpencil", UI_EMBOSS, UI_HELV, curarea->win);
+ uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
+ uiSetPanelHandler(NODES_HANDLER_GREASEPENCIL); // for close and esc
+ if (uiNewPanel(curarea, block, "Grease Pencil", "SpaceNode", 100, 30, 318, 204)==0) return;
+
+ /* we can only really draw stuff if there are nodes (otherwise no events are handled */
+ if (snode->nodetree == NULL)
+ return;
+
+ /* allocate memory for gpd if drawing enabled (this must be done first or else we crash) */
+ if (snode->flag & SNODE_DISPGP) {
+ if (snode->gpd == NULL)
+ gpencil_data_setactive(curarea, gpencil_data_addnew());
+ }
+
+ if (snode->flag & SNODE_DISPGP) {
+ bGPdata *gpd= snode->gpd;
+ short newheight;
+
+ /* this is a variable height panel, newpanel doesnt force new size on existing panels */
+ /* so first we make it default height */
+ uiNewPanelHeight(block, 204);
+
+ /* draw button for showing gpencil settings and drawings */
+ uiDefButBitS(block, TOG, SNODE_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &snode->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Node Editor (draw using Shift-LMB)");
+
+ /* extend the panel if the contents won't fit */
+ newheight= draw_gpencil_panel(block, gpd, curarea);
+ uiNewPanelHeight(block, newheight);
+ }
+ else {
+ uiDefButBitS(block, TOG, SNODE_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &snode->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Node Editor");
+ uiDefBut(block, LABEL, 1, " ", 160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
+ }
+}
+
+static void nodes_blockhandlers(ScrArea *sa)
+{
+ SpaceNode *snode= sa->spacedata.first;
+ short a;
+
+ for(a=0; a<SPACE_MAXHANDLER; a+=2) {
+ switch(snode->blockhandler[a]) {
+ case NODES_HANDLER_GREASEPENCIL:
+ nodes_panel_gpencil(snode->blockhandler[a+1]);
+ break;
+ }
+
+ /* clear action value for event */
+ snode->blockhandler[a+1]= 0;
+ }
+ uiDrawBlocksPanels(sa, 0);
+}
+#endif
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
new file mode 100644
index 00000000000..ab6d3c245f1
--- /dev/null
+++ b/source/blender/editors/space_node/node_draw.c
@@ -0,0 +1,1138 @@
+/**
+ * $Id: drawnode.c 17439 2008-11-13 09:57:11Z kakbarnf $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ * Contributor(s): Nathan Letwory
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "DNA_ID.h"
+#include "DNA_node_types.h"
+#include "DNA_image_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_action_types.h"
+#include "DNA_color_types.h"
+#include "DNA_customdata_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_text_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "MEM_guardedalloc.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_texture.h"
+#include "BKE_text.h"
+#include "BKE_utildefines.h"
+
+/* #include "BDR_gpencil.h" XXX */
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+#include "BMF_Api.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_util.h"
+#include "ED_types.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "CMP_node.h"
+#include "SHD_node.h"
+
+#include "node_intern.h"
+
+// XXX interface.h
+extern void ui_dropshadow(rctf *rct, float radius, float aspect, int select);
+extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);
+extern void ui_draw_tria_icon(float x, float y, float aspect, char dir);
+
+
+static void node_scaling_widget(int color_id, float aspect, float xmin, float ymin, float xmax, float ymax)
+{
+ float dx;
+ float dy;
+
+ dx= 0.5f*(xmax-xmin);
+ dy= 0.5f*(ymax-ymin);
+
+ UI_ThemeColorShade(color_id, +30);
+ fdrawline(xmin, ymin, xmax, ymax);
+ fdrawline(xmin+dx, ymin, xmax, ymax-dy);
+
+ UI_ThemeColorShade(color_id, -10);
+ fdrawline(xmin, ymin+aspect, xmax, ymax+aspect);
+ fdrawline(xmin+dx, ymin+aspect, xmax, ymax-dy+aspect);
+}
+
+/* based on settings in node, sets drawing rect info. each redraw! */
+static void node_update(bNode *node)
+{
+ bNodeSocket *nsock;
+ float dy= node->locy;
+
+ /* header */
+ dy-= NODE_DY;
+
+ /* little bit space in top */
+ if(node->outputs.first)
+ dy-= NODE_DYS/2;
+
+ /* output sockets */
+ for(nsock= node->outputs.first; nsock; nsock= nsock->next) {
+ if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+ nsock->locx= node->locx + node->width;
+ nsock->locy= dy - NODE_DYS;
+ dy-= NODE_DY;
+ }
+ }
+
+ node->prvr.xmin= node->butr.xmin= node->locx + NODE_DYS;
+ node->prvr.xmax= node->butr.xmax= node->locx + node->width- NODE_DYS;
+
+ /* preview rect? */
+ if(node->flag & NODE_PREVIEW) {
+ /* only recalculate size when there's a preview actually, otherwise we use stored result */
+ if(node->preview && node->preview->rect) {
+ float aspect= 1.0f;
+
+ if(node->preview && node->preview->xsize && node->preview->ysize)
+ aspect= (float)node->preview->ysize/(float)node->preview->xsize;
+
+ dy-= NODE_DYS/2;
+ node->prvr.ymax= dy;
+
+ if(aspect <= 1.0f)
+ node->prvr.ymin= dy - aspect*(node->width-NODE_DY);
+ else {
+ float dx= (node->width - NODE_DYS) - (node->width- NODE_DYS)/aspect; /* width correction of image */
+
+ node->prvr.ymin= dy - (node->width-NODE_DY);
+
+ node->prvr.xmin+= 0.5f*dx;
+ node->prvr.xmax-= 0.5f*dx;
+ }
+
+ dy= node->prvr.ymin - NODE_DYS/2;
+
+ /* make sure that maximums are bigger or equal to minimums */
+ if(node->prvr.xmax < node->prvr.xmin) SWAP(float, node->prvr.xmax, node->prvr.xmin);
+ if(node->prvr.ymax < node->prvr.ymin) SWAP(float, node->prvr.ymax, node->prvr.ymin);
+ }
+ else {
+ float oldh= node->prvr.ymax - node->prvr.ymin;
+ if(oldh==0.0f)
+ oldh= 0.6f*node->width-NODE_DY;
+ dy-= NODE_DYS/2;
+ node->prvr.ymax= dy;
+ node->prvr.ymin= dy - oldh;
+ dy= node->prvr.ymin - NODE_DYS/2;
+ }
+ }
+
+ /* XXX ugly hack, typeinfo for group is generated */
+ if(node->type == NODE_GROUP)
+ ; // XXX node->typeinfo->butfunc= node_buts_group;
+
+ /* buttons rect? */
+ if((node->flag & NODE_OPTIONS) && node->typeinfo->butfunc) {
+ dy-= NODE_DYS/2;
+ node->butr.ymax= dy;
+ node->butr.ymin= dy - (float)node->typeinfo->butfunc(NULL, NULL, node, NULL);
+ dy= node->butr.ymin - NODE_DYS/2;
+ }
+
+ /* input sockets */
+ for(nsock= node->inputs.first; nsock; nsock= nsock->next) {
+ if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+ nsock->locx= node->locx;
+ nsock->locy= dy - NODE_DYS;
+ dy-= NODE_DY;
+ }
+ }
+
+ /* little bit space in end */
+ if(node->inputs.first || (node->flag & (NODE_OPTIONS|NODE_PREVIEW))==0 )
+ dy-= NODE_DYS/2;
+
+ node->totr.xmin= node->locx;
+ node->totr.xmax= node->locx + node->width;
+ node->totr.ymax= node->locy;
+ node->totr.ymin= dy;
+}
+
+/* based on settings in node, sets drawing rect info. each redraw! */
+static void node_update_hidden(bNode *node)
+{
+ bNodeSocket *nsock;
+ float rad, drad, hiddenrad= HIDDEN_RAD;
+ int totin=0, totout=0, tot;
+
+ /* calculate minimal radius */
+ for(nsock= node->inputs.first; nsock; nsock= nsock->next)
+ if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
+ totin++;
+ for(nsock= node->outputs.first; nsock; nsock= nsock->next)
+ if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
+ totout++;
+
+ tot= MAX2(totin, totout);
+ if(tot>4) {
+ hiddenrad += 5.0f*(float)(tot-4);
+ }
+
+ node->totr.xmin= node->locx;
+ node->totr.xmax= node->locx + 3*hiddenrad + node->miniwidth;
+ node->totr.ymax= node->locy + (hiddenrad - 0.5f*NODE_DY);
+ node->totr.ymin= node->totr.ymax - 2*hiddenrad;
+
+ /* output sockets */
+ rad=drad= (float)M_PI/(1.0f + (float)totout);
+
+ for(nsock= node->outputs.first; nsock; nsock= nsock->next) {
+ if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+ nsock->locx= node->totr.xmax - hiddenrad + (float)sin(rad)*hiddenrad;
+ nsock->locy= node->totr.ymin + hiddenrad + (float)cos(rad)*hiddenrad;
+ rad+= drad;
+ }
+ }
+
+ /* input sockets */
+ rad=drad= - (float)M_PI/(1.0f + (float)totin);
+
+ for(nsock= node->inputs.first; nsock; nsock= nsock->next) {
+ if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+ nsock->locx= node->totr.xmin + hiddenrad + (float)sin(rad)*hiddenrad;
+ nsock->locy= node->totr.ymin + hiddenrad + (float)cos(rad)*hiddenrad;
+ rad+= drad;
+ }
+ }
+}
+
+static int node_get_colorid(bNode *node)
+{
+ if(node->typeinfo->nclass==NODE_CLASS_INPUT)
+ return TH_NODE_IN_OUT;
+ if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
+ if(node->flag & NODE_DO_OUTPUT)
+ return TH_NODE_IN_OUT;
+ else
+ return TH_NODE;
+ }
+ if(node->typeinfo->nclass==NODE_CLASS_CONVERTOR)
+ return TH_NODE_CONVERTOR;
+ if(ELEM3(node->typeinfo->nclass, NODE_CLASS_OP_COLOR, NODE_CLASS_OP_VECTOR, NODE_CLASS_OP_FILTER))
+ return TH_NODE_OPERATOR;
+ if(node->typeinfo->nclass==NODE_CLASS_GROUP)
+ return TH_NODE_GROUP;
+ return TH_NODE;
+}
+
+/* based on settings in node, sets drawing rect info. each redraw! */
+/* note: this assumes only 1 group at a time is drawn (linked data) */
+/* in node->totr the entire boundbox for the group is stored */
+static void node_update_group(bNode *gnode)
+{
+ bNodeTree *ngroup= (bNodeTree *)gnode->id;
+ bNode *node;
+ bNodeSocket *nsock;
+ rctf *rect= &gnode->totr;
+ int counter;
+
+ /* center them, is a bit of abuse of locx and locy though */
+ for(node= ngroup->nodes.first; node; node= node->next) {
+ node->locx+= gnode->locx;
+ node->locy+= gnode->locy;
+ if(node->flag & NODE_HIDDEN)
+ node_update_hidden(node);
+ else
+ node_update(node);
+ node->locx-= gnode->locx;
+ node->locy-= gnode->locy;
+ }
+ counter= 1;
+ for(node= ngroup->nodes.first; node; node= node->next) {
+ if(counter) {
+ *rect= node->totr;
+ counter= 0;
+ }
+ else
+ BLI_union_rctf(rect, &node->totr);
+ }
+ if(counter==1) return; /* should be prevented? */
+
+ rect->xmin-= NODE_DY;
+ rect->ymin-= NODE_DY;
+ rect->xmax+= NODE_DY;
+ rect->ymax+= NODE_DY;
+
+ /* output sockets */
+ for(nsock= gnode->outputs.first; nsock; nsock= nsock->next) {
+ nsock->locx= rect->xmax;
+ nsock->locy= nsock->tosock->locy;
+ }
+
+ /* input sockets */
+ for(nsock= gnode->inputs.first; nsock; nsock= nsock->next) {
+ nsock->locx= rect->xmin;
+ nsock->locy= nsock->tosock->locy;
+ }
+}
+
+/* note: in cmp_util.c is similar code, for node_compo_pass_on() */
+static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
+{
+ bNodeSocket *valsock= NULL, *colsock= NULL, *vecsock= NULL;
+ bNodeSocket *sock;
+ bNodeLink link;
+ int a;
+
+ memset(&link, 0, sizeof(bNodeLink));
+
+ /* connect the first value buffer in with first value out */
+ /* connect the first RGBA buffer in with first RGBA out */
+
+ /* test the inputs */
+ for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
+ if(nodeCountSocketLinks(snode->edittree, sock)) {
+ if(sock->type==SOCK_VALUE && valsock==NULL) valsock= sock;
+ if(sock->type==SOCK_VECTOR && vecsock==NULL) vecsock= sock;
+ if(sock->type==SOCK_RGBA && colsock==NULL) colsock= sock;
+ }
+ }
+
+ /* outputs, draw lines */
+ UI_ThemeColor(TH_REDALERT);
+ glEnable(GL_BLEND);
+ glEnable( GL_LINE_SMOOTH );
+
+ if(valsock || colsock || vecsock) {
+ for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
+ if(nodeCountSocketLinks(snode->edittree, sock)) {
+ link.tosock= sock;
+
+ if(sock->type==SOCK_VALUE && valsock) {
+ link.fromsock= valsock;
+ node_draw_link_bezier(v2d, snode, &link, TH_WIRE, TH_WIRE, 0);
+ valsock= NULL;
+ }
+ if(sock->type==SOCK_VECTOR && vecsock) {
+ link.fromsock= vecsock;
+ node_draw_link_bezier(v2d, snode, &link, TH_WIRE, TH_WIRE, 0);
+ vecsock= NULL;
+ }
+ if(sock->type==SOCK_RGBA && colsock) {
+ link.fromsock= colsock;
+ node_draw_link_bezier(v2d, snode, &link, TH_WIRE, TH_WIRE, 0);
+ colsock= NULL;
+ }
+ }
+ }
+ }
+ glDisable(GL_BLEND);
+ glDisable( GL_LINE_SMOOTH );
+}
+
+/* nice AA filled circle */
+/* this might have some more generic use */
+static void circle_draw(float x, float y, float size, int type, int col[3])
+{
+ /* 16 values of sin function */
+ static float si[16] = {
+ 0.00000000f, 0.39435585f,0.72479278f,0.93775213f,
+ 0.99871650f,0.89780453f,0.65137248f,0.29936312f,
+ -0.10116832f,-0.48530196f,-0.79077573f,-0.96807711f,
+ -0.98846832f,-0.84864425f,-0.57126821f,-0.20129852f
+ };
+ /* 16 values of cos function */
+ static float co[16] ={
+ 1.00000000f,0.91895781f,0.68896691f,0.34730525f,
+ -0.05064916f,-0.44039415f,-0.75875812f,-0.95413925f,
+ -0.99486932f,-0.87434661f,-0.61210598f,-0.25065253f,
+ 0.15142777f,0.52896401f,0.82076344f,0.97952994f,
+ };
+ int a;
+
+ glColor3ub(col[0], col[1], col[2]);
+
+ glBegin(GL_POLYGON);
+ for(a=0; a<16; a++)
+ glVertex2f(x+size*si[a], y+size*co[a]);
+ glEnd();
+
+ glColor4ub(0, 0, 0, 150);
+ glEnable(GL_BLEND);
+ glEnable( GL_LINE_SMOOTH );
+ glBegin(GL_LINE_LOOP);
+ for(a=0; a<16; a++)
+ glVertex2f(x+size*si[a], y+size*co[a]);
+ glEnd();
+ glDisable( GL_LINE_SMOOTH );
+ glDisable(GL_BLEND);
+}
+
+static void socket_circle_draw(bNodeSocket *sock, float size)
+{
+ int col[3];
+
+ /* choose color based on sock flags */
+ if(sock->flag & SELECT) {
+ if(sock->flag & SOCK_SEL) {
+ col[0]= 240; col[1]= 200; col[2]= 40;}
+ else if(sock->type==SOCK_VALUE) {
+ col[0]= 200; col[1]= 200; col[2]= 200;}
+ else if(sock->type==SOCK_VECTOR) {
+ col[0]= 140; col[1]= 140; col[2]= 240;}
+ else if(sock->type==SOCK_RGBA) {
+ col[0]= 240; col[1]= 240; col[2]= 100;}
+ else {
+ col[0]= 140; col[1]= 240; col[2]= 140;}
+ }
+ else if(sock->flag & SOCK_SEL) {
+ col[0]= 200; col[1]= 160; col[2]= 0;}
+ else {
+ if(sock->type==-1) {
+ col[0]= 0; col[1]= 0; col[2]= 0;}
+ else if(sock->type==SOCK_VALUE) {
+ col[0]= 160; col[1]= 160; col[2]= 160;}
+ else if(sock->type==SOCK_VECTOR) {
+ col[0]= 100; col[1]= 100; col[2]= 200;}
+ else if(sock->type==SOCK_RGBA) {
+ col[0]= 200; col[1]= 200; col[2]= 40;}
+ else {
+ col[0]= 100; col[1]= 200; col[2]= 100;}
+ }
+
+ circle_draw(sock->locx, sock->locy, size, sock->type, col);
+}
+
+static void node_sync_cb(bContext *C, void *snode_v, void *node_v)
+{
+ SpaceNode *snode= snode_v;
+
+ if(snode->treetype==NTREE_SHADER) {
+ nodeShaderSynchronizeID(node_v, 1);
+ // allqueue(REDRAWBUTSSHADING, 0);
+ }
+}
+
+/* ************** Socket callbacks *********** */
+
+static void socket_vector_menu_cb(bContext *C, void *node_v, void *ntree_v)
+{
+ if(node_v && ntree_v) {
+ NodeTagChanged(ntree_v, node_v);
+ // addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC); XXX
+ }
+}
+
+/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
+static uiBlock *socket_vector_menu(bContext *C, ARegion *ar, void *socket_v)
+{
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ ScrArea *sa= CTX_wm_area(C);
+ bNode *node;
+ bNodeSocket *sock= socket_v;
+ bNodeStack *ns= &sock->ns;
+ uiBlock *block;
+ uiBut *bt;
+
+ /* a bit ugly... retrieve the node the socket comes from */
+ for(node= snode->nodetree->nodes.first; node; node= node->next) {
+ bNodeSocket *sockt;
+ for(sockt= node->inputs.first; sockt; sockt= sockt->next)
+ if(sockt==sock)
+ break;
+ if(sockt)
+ break;
+ }
+
+ block= uiBeginBlock(C, ar, "socket menu", UI_EMBOSS);
+
+ /* use this for a fake extra empy space around the buttons */
+ uiDefBut(block, LABEL, 0, "", -4, -4, 188, 68, NULL, 0, 0, 0, 0, "");
+
+ uiBlockBeginAlign(block);
+ bt= uiDefButF(block, NUMSLI, 0, "X ", 0,40,180,20, ns->vec, ns->min, ns->max, 10, 0, "");
+ uiButSetFunc(bt, socket_vector_menu_cb, node, snode->nodetree);
+ bt= uiDefButF(block, NUMSLI, 0, "Y ", 0,20,180,20, ns->vec+1, ns->min, ns->max, 10, 0, "");
+ uiButSetFunc(bt, socket_vector_menu_cb, node, snode->nodetree);
+ bt= uiDefButF(block, NUMSLI, 0, "Z ", 0,0,180,20, ns->vec+2, ns->min, ns->max, 10, 0, "");
+ uiButSetFunc(bt, socket_vector_menu_cb, node, snode->nodetree);
+
+ uiBlockSetDirection(block, UI_TOP);
+ uiEndBlock(C, block);
+
+ ED_area_tag_redraw(sa);
+
+ return block;
+}
+
+/* not a callback */
+static void node_draw_preview(bNodePreview *preview, rctf *prv)
+{
+ float xscale= (prv->xmax-prv->xmin)/((float)preview->xsize);
+ float yscale= (prv->ymax-prv->ymin)/((float)preview->ysize);
+ float tile= (prv->xmax - prv->xmin) / 10.0f;
+ float x, y;
+
+ /* draw checkerboard backdrop to show alpha */
+ glColor3ub(120, 120, 120);
+ glRectf(prv->xmin, prv->ymin, prv->xmax, prv->ymax);
+ glColor3ub(160, 160, 160);
+
+ for(y=prv->ymin; y<prv->ymax; y+=tile*2) {
+ for(x=prv->xmin; x<prv->xmax; x+=tile*2) {
+ float tilex= tile, tiley= tile;
+
+ if(x+tile > prv->xmax)
+ tilex= prv->xmax-x;
+ if(y+tile > prv->ymax)
+ tiley= prv->ymax-y;
+
+ glRectf(x, y, x + tilex, y + tiley);
+ }
+ }
+ for(y=prv->ymin+tile; y<prv->ymax; y+=tile*2) {
+ for(x=prv->xmin+tile; x<prv->xmax; x+=tile*2) {
+ float tilex= tile, tiley= tile;
+
+ if(x+tile > prv->xmax)
+ tilex= prv->xmax-x;
+ if(y+tile > prv->ymax)
+ tiley= prv->ymax-y;
+
+ glRectf(x, y, x + tilex, y + tiley);
+ }
+ }
+
+#ifdef __APPLE__
+// if(is_a_really_crappy_nvidia_card()) { XXX
+// float zoomx= curarea->winx/(float)(G.v2d->cur.xmax-G.v2d->cur.xmin);
+// float zoomy= curarea->winy/(float)(G.v2d->cur.ymax-G.v2d->cur.ymin);
+// glPixelZoom(zoomx*xscale, zoomy*yscale);
+// }
+// else
+#endif
+ glPixelZoom(xscale, yscale);
+
+ glEnable(GL_BLEND);
+ glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); /* premul graphics */
+
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glaDrawPixelsTex(prv->xmin, prv->ymin, preview->xsize, preview->ysize, GL_FLOAT, preview->rect);
+
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+ glDisable(GL_BLEND);
+ glPixelZoom(1.0f, 1.0f);
+
+ UI_ThemeColorShadeAlpha(TH_BACK, -15, +100);
+ fdrawbox(prv->xmin, prv->ymin, prv->xmax, prv->ymax);
+
+}
+
+static void do_node_internal_buttons(bContext *C, void *node_v, int event)
+{
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+
+ if(event==B_NODE_EXEC) {
+ if(snode->treetype==NTREE_SHADER) {
+ WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, snode->id);
+ }
+ else if(snode->treetype==NTREE_COMPOSIT) {
+ bNode *node= node_v;
+
+ NodeTagChanged(snode->edittree, node);
+ /* don't use NodeTagIDChanged, it gives far too many recomposites for image, scene layers, ... */
+
+ /* not the best implementation of the world... but we need it to work now :) */
+ if(node->type==CMP_NODE_R_LAYERS && node->custom2) {
+ /* add event for this window (after render curarea can be changed) */
+ //addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC);
+
+ //composite_node_render(snode, node);
+ //snode_handle_recalc(snode);
+
+ /* add another event, a render can go fullscreen and open new window */
+ //addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC);
+ }
+ else {
+ node= snode_get_editgroup(snode);
+ if(node)
+ NodeTagIDChanged(snode->nodetree, node->id);
+ }
+ WM_event_add_notifier(C, NC_SCENE|ND_NODES, CTX_data_scene(C));
+ }
+
+ // else if(snode->treetype==NTREE_TEXTURE)
+ // texture_node_event(snode, val);
+ }
+
+}
+
+static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNode *node)
+{
+ bNodeSocket *sock;
+ uiBlock *block;
+ uiBut *bt;
+ rctf *rct= &node->totr;
+ float /*slen,*/ iconofs;
+ int /*ofs,*/ color_id= node_get_colorid(node);
+ char showname[128]; /* 128 used below */
+ View2D *v2d = &ar->v2d;
+ char str[32];
+
+ /* make unique block name, also used for handling blocks in editnode.c */
+ sprintf(str, "node buttons %p", node);
+ block= uiBeginBlock(C, ar, str, UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_node_internal_buttons, node);
+
+ uiSetRoundBox(15-4);
+ ui_dropshadow(rct, BASIS_RAD, snode->aspect, node->flag & SELECT);
+
+ /* header */
+ if(color_id==TH_NODE)
+ UI_ThemeColorShade(color_id, -20);
+ else
+ UI_ThemeColor(color_id);
+
+ uiSetRoundBox(3);
+ uiRoundBox(rct->xmin, rct->ymax-NODE_DY, rct->xmax, rct->ymax, BASIS_RAD);
+
+ /* show/hide icons, note this sequence is copied in editnode.c */
+ iconofs= rct->xmax;
+
+ if(node->typeinfo->flag & NODE_PREVIEW) {
+ int icon_id;
+
+ if(node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT))
+ icon_id= ICON_MATERIAL;
+ else
+ icon_id= ICON_MATERIAL_DATA;
+ iconofs-= 18.0f;
+ glEnable(GL_BLEND);
+ UI_icon_draw_aspect_blended(iconofs, rct->ymax-NODE_DY+2, icon_id, snode->aspect, -60);
+ glDisable(GL_BLEND);
+ }
+ if(node->type == NODE_GROUP) {
+
+ iconofs-= 18.0f;
+ glEnable(GL_BLEND);
+ if(node->id->lib) {
+ glPixelTransferf(GL_GREEN_SCALE, 0.7f);
+ glPixelTransferf(GL_BLUE_SCALE, 0.3f);
+ UI_icon_draw_aspect(iconofs, rct->ymax-NODE_DY+2, ICON_NODE, snode->aspect);
+ glPixelTransferf(GL_GREEN_SCALE, 1.0f);
+ glPixelTransferf(GL_BLUE_SCALE, 1.0f);
+ }
+ else {
+ UI_icon_draw_aspect_blended(iconofs, rct->ymax-NODE_DY+2, ICON_NODE, snode->aspect, -60);
+ }
+ glDisable(GL_BLEND);
+ }
+ if(node->typeinfo->flag & NODE_OPTIONS) {
+ iconofs-= 18.0f;
+ glEnable(GL_BLEND);
+ UI_icon_draw_aspect_blended(iconofs, rct->ymax-NODE_DY+2, ICON_BUTS, snode->aspect, -60);
+ glDisable(GL_BLEND);
+ }
+ { /* always hide/reveal unused sockets */
+ int shade;
+
+ iconofs-= 18.0f;
+ // XXX re-enable
+ /*if(node_has_hidden_sockets(node))
+ shade= -40;
+ else*/
+ shade= -90;
+ glEnable(GL_BLEND);
+ UI_icon_draw_aspect_blended(iconofs, rct->ymax-NODE_DY+2, ICON_PLUS, snode->aspect, shade);
+ glDisable(GL_BLEND);
+ }
+
+ /* title */
+ if(node->flag & SELECT)
+ UI_ThemeColor(TH_TEXT_HI);
+ else
+ UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10);
+
+ /* open/close entirely? */
+ ui_draw_tria_icon(rct->xmin+8.0f, rct->ymax-NODE_DY+4.0f, snode->aspect, 'v');
+
+ if(node->flag & SELECT)
+ UI_ThemeColor(TH_TEXT_HI);
+ else
+ UI_ThemeColor(TH_TEXT);
+
+ if(node->flag & NODE_MUTED)
+ sprintf(showname, "[%s]", node->name);
+ else if(node->username[0])
+ sprintf(showname, "(%s) %s", node->username, node->name);
+ else
+ BLI_strncpy(showname, node->name, 128);
+
+ uiDefBut(block, LABEL, 0, showname, (short)(rct->xmin+15), (short)(rct->ymax-NODE_DY),
+ (int)(iconofs - rct->xmin-18.0f), NODE_DY, NULL, 0, 0, 0, 0, "");
+
+ /* body */
+ UI_ThemeColor4(TH_NODE);
+ glEnable(GL_BLEND);
+ uiSetRoundBox(8);
+ uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax-NODE_DY, BASIS_RAD);
+ glDisable(GL_BLEND);
+
+ /* scaling indicator */
+ node_scaling_widget(TH_NODE, snode->aspect, rct->xmax-BASIS_RAD*snode->aspect, rct->ymin, rct->xmax, rct->ymin+BASIS_RAD*snode->aspect);
+
+ /* outline active emphasis */
+ if(node->flag & NODE_ACTIVE) {
+ glEnable(GL_BLEND);
+ glColor4ub(200, 200, 200, 140);
+ uiSetRoundBox(15-4);
+ gl_round_box(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD);
+ glDisable(GL_BLEND);
+ }
+
+ /* disable lines */
+ if(node->flag & NODE_MUTED)
+ node_draw_mute_line(v2d, snode, node);
+
+
+ /* hurmf... another candidate for callback, have to see how this works first */
+ if(node->id && block && snode->treetype==NTREE_SHADER)
+ nodeShaderSynchronizeID(node, 0);
+
+ /* socket inputs, buttons */
+ for(sock= node->inputs.first; sock; sock= sock->next) {
+ if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+ socket_circle_draw(sock, NODE_SOCKSIZE);
+
+ if(block && sock->link==NULL) {
+ float *butpoin= sock->ns.vec;
+
+ if(sock->type==SOCK_VALUE) {
+ bt= uiDefButF(block, NUM, B_NODE_EXEC, sock->name,
+ (short)sock->locx+NODE_DYS, (short)(sock->locy)-9, (short)node->width-NODE_DY, 17,
+ butpoin, sock->ns.min, sock->ns.max, 10, 2, "");
+ uiButSetFunc(bt, node_sync_cb, snode, node);
+ }
+ else if(sock->type==SOCK_VECTOR) {
+ uiDefBlockBut(block, socket_vector_menu, sock, sock->name,
+ (short)sock->locx+NODE_DYS, (short)sock->locy-9, (short)node->width-NODE_DY, 17,
+ "");
+ }
+ else if(block && sock->type==SOCK_RGBA) {
+ short labelw= (short)node->width-NODE_DY-40, width;
+
+ if(labelw>0) width= 40; else width= (short)node->width-NODE_DY;
+
+ bt= uiDefButF(block, COL, B_NODE_EXEC, "",
+ (short)(sock->locx+NODE_DYS), (short)sock->locy-8, width, 15,
+ butpoin, 0, 0, 0, 0, "");
+ uiButSetFunc(bt, node_sync_cb, snode, node);
+
+ if(labelw>0) uiDefBut(block, LABEL, 0, sock->name,
+ (short)(sock->locx+NODE_DYS) + 40, (short)sock->locy-8, labelw, 15,
+ NULL, 0, 0, 0, 0, "");
+ }
+ }
+ else {
+
+ uiDefBut(block, LABEL, 0, sock->name, (short)(sock->locx+3.0f), (short)(sock->locy-9.0f),
+ (short)(node->width-NODE_DY), NODE_DY, NULL, 0, 0, 0, 0, "");
+ }
+ }
+ }
+
+ /* socket outputs */
+ for(sock= node->outputs.first; sock; sock= sock->next) {
+ if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+ float slen;
+ int ofs= 0;
+
+ socket_circle_draw(sock, NODE_SOCKSIZE);
+
+ UI_ThemeColor(TH_TEXT);
+ slen= snode->aspect*UI_GetStringWidth(sock->name);
+ while(slen > node->width) {
+ ofs++;
+ slen= snode->aspect*UI_GetStringWidth(sock->name+ofs);
+ }
+
+ uiDefBut(block, LABEL, 0, sock->name+ofs, (short)(sock->locx-15.0f-slen), (short)(sock->locy-9.0f),
+ (short)(node->width-NODE_DY), NODE_DY, NULL, 0, 0, 0, 0, "");
+ }
+ }
+
+ /* preview */
+ if(node->flag & NODE_PREVIEW)
+ if(node->preview && node->preview->rect)
+ node_draw_preview(node->preview, &node->prvr);
+
+ /* buttons */
+ if(node->flag & NODE_OPTIONS) {
+ if(block) {
+ if(node->typeinfo->butfunc) {
+ node->typeinfo->butfunc(block, snode->nodetree, node, &node->butr);
+ }
+ }
+ }
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+}
+
+static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNode *node)
+{
+ uiBlock *block;
+ bNodeSocket *sock;
+ rctf *rct= &node->totr;
+ float dx, centy= 0.5f*(rct->ymax+rct->ymin);
+ float hiddenrad= 0.5f*(rct->ymax-rct->ymin);
+ int color_id= node_get_colorid(node);
+ char str[32], showname[128]; /* 128 is used below */
+
+ /* make unique block name, also used for handling blocks in editnode.c */
+ sprintf(str, "node buttons %p", node);
+ block= uiBeginBlock(C, ar, str, UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_node_internal_buttons, node);
+
+ /* shadow */
+ uiSetRoundBox(15);
+ ui_dropshadow(rct, hiddenrad, snode->aspect, node->flag & SELECT);
+
+ /* body */
+ UI_ThemeColor(color_id);
+ uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad);
+
+ /* outline active emphasis */
+ if(node->flag & NODE_ACTIVE) {
+ glEnable(GL_BLEND);
+ glColor4ub(200, 200, 200, 140);
+ gl_round_box(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad);
+ glDisable(GL_BLEND);
+ }
+
+ /* title */
+ if(node->flag & SELECT)
+ UI_ThemeColor(TH_TEXT_HI);
+ else
+ UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10);
+
+ /* open entirely icon */
+ ui_draw_tria_icon(rct->xmin+9.0f, centy-6.0f, snode->aspect, 'h');
+
+ /* disable lines */
+ if(node->flag & NODE_MUTED)
+ node_draw_mute_line(&ar->v2d, snode, node);
+
+ if(node->flag & SELECT)
+ UI_ThemeColor(TH_TEXT_HI);
+ else
+ UI_ThemeColor(TH_TEXT);
+
+ if(node->miniwidth>0.0f) {
+
+ if(node->flag & NODE_MUTED)
+ sprintf(showname, "[%s]", node->name);
+ else if(node->username[0])
+ sprintf(showname, "(%s)%s", node->username, node->name);
+ else
+ BLI_strncpy(showname, node->name, 128);
+
+ uiDefBut(block, LABEL, 0, showname, (short)(rct->xmin+15), (short)(centy-10),
+ (int)(rct->xmax - rct->xmin-18.0f -12.0f), NODE_DY, NULL, 0, 0, 0, 0, "");
+ }
+
+ /* scale widget thing */
+ UI_ThemeColorShade(color_id, -10);
+ dx= 10.0f;
+ fdrawline(rct->xmax-dx, centy-4.0f, rct->xmax-dx, centy+4.0f);
+ fdrawline(rct->xmax-dx-3.0f*snode->aspect, centy-4.0f, rct->xmax-dx-3.0f*snode->aspect, centy+4.0f);
+
+ UI_ThemeColorShade(color_id, +30);
+ dx-= snode->aspect;
+ fdrawline(rct->xmax-dx, centy-4.0f, rct->xmax-dx, centy+4.0f);
+ fdrawline(rct->xmax-dx-3.0f*snode->aspect, centy-4.0f, rct->xmax-dx-3.0f*snode->aspect, centy+4.0f);
+
+ /* sockets */
+ for(sock= node->inputs.first; sock; sock= sock->next) {
+ if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
+ socket_circle_draw(sock, NODE_SOCKSIZE);
+ }
+
+ for(sock= node->outputs.first; sock; sock= sock->next) {
+ if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
+ socket_circle_draw(sock, NODE_SOCKSIZE);
+ }
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+
+}
+
+static void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree)
+{
+ bNode *node;
+ bNodeLink *link;
+ int a;
+
+ if(ntree==NULL) return; /* groups... */
+
+ /* node lines */
+ glEnable(GL_BLEND);
+ glEnable(GL_LINE_SMOOTH);
+ for(link= ntree->links.first; link; link= link->next)
+ node_draw_link(&ar->v2d, snode, link);
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+
+ /* not selected first */
+ for(a=0, node= ntree->nodes.first; node; node= node->next, a++) {
+ node->nr= a; /* index of node in list, used for exec event code */
+ if(!(node->flag & SELECT)) {
+ if(node->flag & NODE_GROUP_EDIT);
+ else if(node->flag & NODE_HIDDEN)
+ node_draw_hidden(C, ar, snode, node);
+ else
+ node_draw_basis(C, ar, snode, node);
+ }
+ }
+
+ /* selected */
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->flag & SELECT) {
+ if(node->flag & NODE_GROUP_EDIT);
+ else if(node->flag & NODE_HIDDEN)
+ node_draw_hidden(C, ar, snode, node);
+ else
+ node_draw_basis(C, ar, snode, node);
+ }
+ }
+}
+
+/* fake links from groupnode to internal nodes */
+static void node_draw_group_links(View2D *v2d, SpaceNode *snode, bNode *gnode)
+{
+ bNodeLink fakelink;
+ bNodeSocket *sock;
+
+ glEnable(GL_BLEND);
+ glEnable(GL_LINE_SMOOTH);
+
+ fakelink.tonode= fakelink.fromnode= gnode;
+
+ for(sock= gnode->inputs.first; sock; sock= sock->next) {
+ if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+ if(sock->tosock) {
+ fakelink.fromsock= sock;
+ fakelink.tosock= sock->tosock;
+ node_draw_link(v2d, snode, &fakelink);
+ }
+ }
+ }
+
+ for(sock= gnode->outputs.first; sock; sock= sock->next) {
+ if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+ if(sock->tosock) {
+ fakelink.tosock= sock;
+ fakelink.fromsock= sock->tosock;
+ node_draw_link(v2d, snode, &fakelink);
+ }
+ }
+ }
+
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
+}
+
+/* groups are, on creation, centered around 0,0 */
+static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bNode *gnode)
+{
+ bNodeTree *ngroup= (bNodeTree *)gnode->id;
+ bNodeSocket *sock;
+ rctf rect= gnode->totr;
+ char showname[128];
+
+ /* backdrop header */
+ glEnable(GL_BLEND);
+ uiSetRoundBox(3);
+ UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
+ gl_round_box(GL_POLYGON, rect.xmin, rect.ymax, rect.xmax, rect.ymax+NODE_DY, BASIS_RAD);
+
+ /* backdrop body */
+ UI_ThemeColorShadeAlpha(TH_BACK, -8, -70);
+ uiSetRoundBox(12);
+ gl_round_box(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, BASIS_RAD);
+
+ /* selection outline */
+ uiSetRoundBox(15);
+ glColor4ub(200, 200, 200, 140);
+ glEnable( GL_LINE_SMOOTH );
+ gl_round_box(GL_LINE_LOOP, rect.xmin, rect.ymin, rect.xmax, rect.ymax+NODE_DY, BASIS_RAD);
+ glDisable( GL_LINE_SMOOTH );
+ glDisable(GL_BLEND);
+
+ /* backdrop title */
+ UI_ThemeColor(TH_TEXT_HI);
+
+ if(gnode->username[0]) {
+ strcpy(showname,"(");
+ strcat(showname, gnode->username);
+ strcat(showname,") ");
+ strcat(showname, ngroup->id.name+2);
+ }
+ else
+ strcpy(showname, ngroup->id.name+2);
+
+ UI_DrawString(rect.xmin+8.0f, rect.ymax+5.0f, showname);
+
+ /* links from groupsockets to the internal nodes */
+ node_draw_group_links(&ar->v2d, snode, gnode);
+
+ /* group sockets */
+ for(sock= gnode->inputs.first; sock; sock= sock->next)
+ if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
+ socket_circle_draw(sock, NODE_SOCKSIZE);
+ for(sock= gnode->outputs.first; sock; sock= sock->next)
+ if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
+ socket_circle_draw(sock, NODE_SOCKSIZE);
+
+ /* and finally the whole tree */
+ node_draw_nodetree(C, ar, snode, ngroup);
+}
+
+void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d)
+{
+ float col[3];
+ View2DScrollers *scrollers;
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ UI_view2d_view_ortho(C, v2d);
+
+ //uiFreeBlocksWin(&sa->uiblocks, sa->win);
+
+ /* only set once */
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+ glEnable(GL_MAP1_VERTEX_3);
+
+ /* aspect+font, set each time */
+ snode->aspect= (v2d->cur.xmax - v2d->cur.xmin)/((float)ar->winx);
+ // XXX snode->curfont= uiSetCurFont_ext(snode->aspect);
+
+ UI_view2d_constant_grid_draw(C, v2d);
+ /* backdrop */
+ draw_nodespace_back_pix(ar, snode);
+
+ /* nodes */
+ snode_set_context(snode, CTX_data_scene(C));
+
+ if(snode->nodetree) {
+ bNode *node;
+
+ /* for now, we set drawing coordinates on each redraw */
+ for(node= snode->nodetree->nodes.first; node; node= node->next) {
+ if(node->flag & NODE_GROUP_EDIT)
+ node_update_group(node);
+ else if(node->flag & NODE_HIDDEN)
+ node_update_hidden(node);
+ else
+ node_update(node);
+ }
+
+ node_draw_nodetree(C, ar, snode, snode->nodetree);
+
+ /* active group */
+ for(node= snode->nodetree->nodes.first; node; node= node->next) {
+ if(node->flag & NODE_GROUP_EDIT)
+ node_draw_group(C, ar, snode, node);
+ }
+ }
+
+ /* draw grease-pencil ('canvas' strokes) */
+ /*if ((snode->flag & SNODE_DISPGP) && (snode->nodetree))
+ draw_gpencil_2dview(sa, 1);*/
+
+ /* restore viewport (not needed yet) */
+ /*mywinset(sa->win);*/
+
+ /* ortho at pixel level curarea */
+ /*myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);*/
+
+ /* draw grease-pencil (screen strokes) */
+ /*if ((snode->flag & SNODE_DISPGP) && (snode->nodetree))
+ draw_gpencil_2dview(sa, 0);*/
+
+ //draw_area_emboss(sa);
+
+ /* it is important to end a view in a transform compatible with buttons */
+ /*bwin_scalematrix(sa->win, snode->blockscale, snode->blockscale, snode->blockscale);
+ nodes_blockhandlers(sa);*/
+
+ //curarea->win_swap= WIN_BACK_OK;
+
+ /* in the end, this is a delayed previewrender test, to allow buttons to be first */
+ /*if(snode->flag & SNODE_DO_PREVIEW) {
+ addafterqueue(sa->win, RENDERPREVIEW, 1);
+ snode->flag &= ~SNODE_DO_PREVIEW;
+ }*/
+
+
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ scrollers= UI_view2d_scrollers_calc(C, v2d, 10, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+}
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
new file mode 100644
index 00000000000..5ee7326cd2f
--- /dev/null
+++ b/source/blender/editors/space_node/node_edit.c
@@ -0,0 +1,2535 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): David Millan Escriva, Juho Vepsäläinen, Nathan Letwory
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_color_types.h"
+#include "DNA_image_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_object_types.h"
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_node_types.h"
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_context.h"
+#include "BKE_colortools.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_node.h"
+#include "BKE_material.h"
+#include "BKE_texture.h"
+#include "BKE_scene.h"
+#include "BKE_utildefines.h"
+
+#include "ED_previewrender.h"
+
+#include "BIF_gl.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_storage_types.h"
+
+#include "RE_pipeline.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_view2d.h"
+
+#include "node_intern.h"
+
+#define SOCK_IN 1
+#define SOCK_OUT 2
+
+/* ***************** composite job manager ********************** */
+
+typedef struct CompoJob {
+ Scene *scene;
+ bNodeTree *ntree;
+ bNodeTree *localtree;
+ short *stop;
+ short *do_update;
+} CompoJob;
+
+/* called by compo, only to check job 'stop' value */
+static int compo_breakjob(void *cjv)
+{
+ CompoJob *cj= cjv;
+
+ return *(cj->stop);
+}
+
+/* called by compo, wmJob sends notifier */
+static void compo_redrawjob(void *cjv, char *str)
+{
+ CompoJob *cj= cjv;
+
+ *(cj->do_update)= 1;
+}
+
+static void compo_freejob(void *cjv)
+{
+ CompoJob *cj= cjv;
+
+ if(cj->localtree) {
+ ntreeLocalMerge(cj->localtree, cj->ntree);
+ }
+ MEM_freeN(cj);
+}
+
+/* only now we copy the nodetree, so adding many jobs while
+ sliding buttons doesn't frustrate */
+static void compo_initjob(void *cjv)
+{
+ CompoJob *cj= cjv;
+
+ cj->localtree= ntreeLocalize(cj->ntree);
+}
+
+/* called before redraw notifiers, it moves finished previews over */
+static void compo_updatejob(void *cjv)
+{
+ CompoJob *cj= cjv;
+
+ ntreeLocalSync(cj->localtree, cj->ntree);
+}
+
+
+/* only this runs inside thread */
+static void compo_startjob(void *cjv, short *stop, short *do_update)
+{
+ CompoJob *cj= cjv;
+ bNodeTree *ntree= cj->localtree;
+
+ if(cj->scene->use_nodes==0)
+ return;
+
+ cj->stop= stop;
+ cj->do_update= do_update;
+
+ ntree->test_break= compo_breakjob;
+ ntree->tbh= cj;
+ ntree->stats_draw= compo_redrawjob;
+ ntree->sdh= cj;
+
+ // XXX BIF_store_spare();
+
+ ntreeCompositExecTree(ntree, &cj->scene->r, 1); /* 1 is do_previews */
+
+ ntree->test_break= NULL;
+ ntree->stats_draw= NULL;
+
+}
+
+void snode_composite_job(const bContext *C, ScrArea *sa)
+{
+ SpaceNode *snode= sa->spacedata.first;
+ wmJob *steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa);
+ CompoJob *cj= MEM_callocN(sizeof(CompoJob), "compo job");
+
+ /* customdata for preview thread */
+ cj->scene= CTX_data_scene(C);
+ cj->ntree= snode->nodetree;
+
+ /* setup job */
+ WM_jobs_customdata(steve, cj, compo_freejob);
+ WM_jobs_timer(steve, 0.1, NC_SCENE, NC_SCENE|ND_COMPO_RESULT);
+ WM_jobs_callbacks(steve, compo_startjob, compo_initjob, compo_updatejob);
+
+ WM_jobs_start(steve);
+
+}
+
+/* ***************************************** */
+
+/* also checks for edited groups */
+bNode *editnode_get_active(bNodeTree *ntree)
+{
+ bNode *node;
+
+ /* check for edited group */
+ for(node= ntree->nodes.first; node; node= node->next)
+ if(node->flag & NODE_GROUP_EDIT)
+ break;
+ if(node)
+ return nodeGetActive((bNodeTree *)node->id);
+ else
+ return nodeGetActive(ntree);
+}
+
+void snode_handle_recalc(bContext *C, SpaceNode *snode)
+{
+ if(snode->treetype==NTREE_SHADER)
+ WM_event_add_notifier(C, NC_MATERIAL|ND_NODES, snode->id);
+ else if(snode->treetype==NTREE_COMPOSIT)
+ WM_event_add_notifier(C, NC_SCENE|ND_NODES, snode->id);
+ else if(snode->treetype==NTREE_TEXTURE) {
+ // ntreeTexUpdatePreviews(snode->nodetree);
+ // XXX BIF_preview_changed(ID_TE);
+ }
+}
+
+#if 0
+static int image_detect_file_sequence(int *start_p, int *frames_p, char *str)
+{
+ SpaceFile *sfile;
+ char name[FILE_MAX], head[FILE_MAX], tail[FILE_MAX], filename[FILE_MAX];
+ int a, frame, totframe, found, minframe;
+ unsigned short numlen;
+
+ sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
+ if(sfile==NULL || sfile->filelist==NULL)
+ return 0;
+
+ /* find first frame */
+ found= 0;
+ minframe= 0;
+
+ for(a=0; a<sfile->totfile; a++) {
+ if(sfile->filelist[a].flags & ACTIVE) {
+ BLI_strncpy(name, sfile->filelist[a].relname, sizeof(name));
+ frame= BLI_stringdec(name, head, tail, &numlen);
+
+ if(!found || frame < minframe) {
+ BLI_strncpy(filename, name, sizeof(name));
+ minframe= frame;
+ found= 1;
+ }
+ }
+ }
+
+ /* not one frame found */
+ if(!found)
+ return 0;
+
+ /* counter number of following frames */
+ found= 1;
+ totframe= 0;
+
+ for(frame=minframe; found; frame++) {
+ found= 0;
+ BLI_strncpy(name, filename, sizeof(name));
+ BLI_stringenc(name, head, tail, numlen, frame);
+
+ for(a=0; a<sfile->totfile; a++) {
+ if(sfile->filelist[a].flags & ACTIVE) {
+ if(strcmp(sfile->filelist[a].relname, name) == 0) {
+ found= 1;
+ totframe++;
+ break;
+ }
+ }
+ }
+ }
+
+ if(totframe > 1) {
+ BLI_strncpy(str, sfile->dir, sizeof(name));
+ strcat(str, filename);
+
+ *start_p= minframe;
+ *frames_p= totframe;
+ return 1;
+ }
+
+ return 0;
+}
+
+static void load_node_image(char *str) /* called from fileselect */
+{
+ SpaceNode *snode= curarea->spacedata.first;
+ bNode *node= nodeGetActive(snode->edittree);
+ Image *ima= NULL;
+ ImageUser *iuser= node->storage;
+ char filename[FILE_MAX];
+ int start=0, frames=0, sequence;
+
+ sequence= image_detect_file_sequence(&start, &frames, filename);
+ if(sequence)
+ str= filename;
+
+ ima= BKE_add_image_file(str);
+ if(ima) {
+ if(node->id)
+ node->id->us--;
+
+ node->id= &ima->id;
+ id_us_plus(node->id);
+
+ BLI_strncpy(node->name, node->id->name+2, 21);
+
+ if(sequence) {
+ ima->source= IMA_SRC_SEQUENCE;
+ iuser->frames= frames;
+ iuser->offset= start-1;
+ }
+
+ BKE_image_signal(ima, node->storage, IMA_SIGNAL_RELOAD);
+
+ NodeTagChanged(snode->edittree, node);
+ // XXX snode_handle_recalc(C, snode);
+ }
+}
+
+static void set_node_imagepath(char *str) /* called from fileselect */
+{
+ SpaceNode *snode= curarea->spacedata.first;
+ bNode *node= nodeGetActive(snode->edittree);
+ BLI_strncpy(((NodeImageFile *)node->storage)->name, str, sizeof( ((NodeImageFile *)node->storage)->name ));
+}
+
+#endif /* 0 */
+
+bNode *snode_get_editgroup(SpaceNode *snode)
+{
+ bNode *gnode;
+
+ /* get the groupnode */
+ for(gnode= snode->nodetree->nodes.first; gnode; gnode= gnode->next)
+ if(gnode->flag & NODE_GROUP_EDIT)
+ break;
+ return gnode;
+}
+
+#if 0
+
+/* node has to be of type 'render layers' */
+/* is a bit clumsy copying renderdata here... scene nodes use render size of current render */
+static void composite_node_render(SpaceNode *snode, bNode *node)
+{
+ RenderData rd;
+ Scene *scene= NULL;
+ int scemode, actlay;
+
+ /* the button press won't show up otherwise, button hilites disabled */
+ force_draw(0);
+
+ if(node->id && node->id!=(ID *)G.scene) {
+ scene= G.scene;
+ set_scene_bg((Scene *)node->id);
+ rd= G.scene->r;
+ G.scene->r.xsch= scene->r.xsch;
+ G.scene->r.ysch= scene->r.ysch;
+ G.scene->r.size= scene->r.size;
+ G.scene->r.mode &= ~(R_BORDER|R_DOCOMP);
+ G.scene->r.mode |= scene->r.mode & R_BORDER;
+ G.scene->r.border= scene->r.border;
+ G.scene->r.cfra= scene->r.cfra;
+ }
+
+ scemode= G.scene->r.scemode;
+ actlay= G.scene->r.actlay;
+
+ G.scene->r.scemode |= R_SINGLE_LAYER|R_COMP_RERENDER;
+ G.scene->r.actlay= node->custom1;
+
+ BIF_do_render(0);
+
+ G.scene->r.scemode= scemode;
+ G.scene->r.actlay= actlay;
+
+ node->custom2= 0;
+
+ if(scene) {
+ G.scene->r= rd;
+ set_scene_bg(scene);
+ }
+}
+
+static void composit_node_event(SpaceNode *snode, short event)
+{
+
+ switch(event) {
+ case B_REDR:
+ // allqueue(REDRAWNODE, 1);
+ break;
+ case B_NODE_LOADIMAGE:
+ {
+ bNode *node= nodeGetActive(snode->edittree);
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+
+ if(node->id)
+ strcpy(name, ((Image *)node->id)->name);
+ else strcpy(name, U.textudir);
+ if (G.qual & LR_CTRLKEY) {
+ activate_imageselect(FILE_SPECIAL, "SELECT IMAGE", name, load_node_image);
+ } else {
+ activate_fileselect(FILE_SPECIAL, "SELECT IMAGE", name, load_node_image);
+ }
+ break;
+ }
+ case B_NODE_SETIMAGE:
+ {
+ bNode *node= nodeGetActive(snode->edittree);
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+
+ strcpy(name, ((NodeImageFile *)node->storage)->name);
+ if (G.qual & LR_CTRLKEY) {
+ activate_imageselect(FILE_SPECIAL, "SELECT OUTPUT DIR", name, set_node_imagepath);
+ } else {
+ activate_fileselect(FILE_SPECIAL, "SELECT OUTPUT DIR", name, set_node_imagepath);
+ }
+ break;
+ }
+ case B_NODE_TREE_EXEC:
+ // XXX snode_handle_recalc(snode);
+ break;
+ default:
+ /* B_NODE_EXEC */
+ {
+ bNode *node= BLI_findlink(&snode->edittree->nodes, event-B_NODE_EXEC);
+ if(node) {
+ NodeTagChanged(snode->edittree, node);
+ /* don't use NodeTagIDChanged, it gives far too many recomposites for image, scene layers, ... */
+
+ /* not the best implementation of the world... but we need it to work now :) */
+ if(node->type==CMP_NODE_R_LAYERS && node->custom2) {
+ /* add event for this window (after render curarea can be changed) */
+ addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC);
+
+ composite_node_render(snode, node);
+ // XXX snode_handle_recalc(snode);
+
+ /* add another event, a render can go fullscreen and open new window */
+ addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC);
+ }
+ else {
+ node= snode_get_editgroup(snode);
+ if(node)
+ NodeTagIDChanged(snode->nodetree, node->id);
+
+ // XXX snode_handle_recalc(snode);
+ }
+ }
+ }
+ }
+}
+
+static void texture_node_event(SpaceNode *snode, short event)
+{
+ switch(event) {
+ case B_REDR:
+ // allqueue(REDRAWNODE, 1);
+ break;
+ case B_NODE_LOADIMAGE:
+ {
+ bNode *node= nodeGetActive(snode->edittree);
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+
+ if(node->id)
+ strcpy(name, ((Image *)node->id)->name);
+ else strcpy(name, U.textudir);
+ if (G.qual & LR_CTRLKEY) {
+ activate_imageselect(FILE_SPECIAL, "SELECT IMAGE", name, load_node_image);
+ } else {
+ activate_fileselect(FILE_SPECIAL, "SELECT IMAGE", name, load_node_image);
+ }
+ break;
+ }
+ default:
+ /* B_NODE_EXEC */
+ ntreeTexCheckCyclics( snode->nodetree );
+ // XXX snode_handle_recalc(snode);
+ // allqueue(REDRAWNODE, 1);
+ break;
+ }
+}
+
+#endif /* 0 */
+/* assumes nothing being done in ntree yet, sets the default in/out node */
+/* called from shading buttons or header */
+void node_shader_default(Material *ma)
+{
+ bNode *in, *out;
+ bNodeSocket *fromsock, *tosock;
+
+ /* but lets check it anyway */
+ if(ma->nodetree) {
+ printf("error in shader initialize\n");
+ return;
+ }
+
+ ma->nodetree= ntreeAddTree(NTREE_SHADER);
+
+ out= nodeAddNodeType(ma->nodetree, SH_NODE_OUTPUT, NULL, NULL);
+ out->locx= 300.0f; out->locy= 300.0f;
+
+ in= nodeAddNodeType(ma->nodetree, SH_NODE_MATERIAL, NULL, NULL);
+ in->locx= 10.0f; in->locy= 300.0f;
+ nodeSetActive(ma->nodetree, in);
+
+ /* only a link from color to color */
+ fromsock= in->outputs.first;
+ tosock= out->inputs.first;
+ nodeAddLink(ma->nodetree, in, fromsock, out, tosock);
+
+ ntreeSolveOrder(ma->nodetree); /* needed for pointers */
+}
+
+/* assumes nothing being done in ntree yet, sets the default in/out node */
+/* called from shading buttons or header */
+void node_composit_default(Scene *sce)
+{
+ bNode *in, *out;
+ bNodeSocket *fromsock, *tosock;
+
+ /* but lets check it anyway */
+ if(sce->nodetree) {
+ printf("error in composit initialize\n");
+ return;
+ }
+
+ sce->nodetree= ntreeAddTree(NTREE_COMPOSIT);
+
+ out= nodeAddNodeType(sce->nodetree, CMP_NODE_COMPOSITE, NULL, NULL);
+ out->locx= 300.0f; out->locy= 400.0f;
+ out->id= &sce->id;
+
+ in= nodeAddNodeType(sce->nodetree, CMP_NODE_R_LAYERS, NULL, NULL);
+ in->locx= 10.0f; in->locy= 400.0f;
+ in->id= &sce->id;
+ nodeSetActive(sce->nodetree, in);
+
+ /* links from color to color */
+ fromsock= in->outputs.first;
+ tosock= out->inputs.first;
+ nodeAddLink(sce->nodetree, in, fromsock, out, tosock);
+
+ ntreeSolveOrder(sce->nodetree); /* needed for pointers */
+
+ // XXX ntreeCompositForceHidden(sce->nodetree);
+}
+
+/* assumes nothing being done in ntree yet, sets the default in/out node */
+/* called from shading buttons or header */
+void node_texture_default(Tex *tx)
+{
+ bNode *in, *out;
+ bNodeSocket *fromsock, *tosock;
+
+ /* but lets check it anyway */
+ if(tx->nodetree) {
+ printf("error in texture initialize\n");
+ return;
+ }
+
+ tx->nodetree= ntreeAddTree(NTREE_TEXTURE);
+
+ out= nodeAddNodeType(tx->nodetree, TEX_NODE_OUTPUT, NULL, NULL);
+ out->locx= 300.0f; out->locy= 300.0f;
+
+ in= nodeAddNodeType(tx->nodetree, TEX_NODE_CHECKER, NULL, NULL);
+ in->locx= 10.0f; in->locy= 300.0f;
+ nodeSetActive(tx->nodetree, in);
+
+ fromsock= in->outputs.first;
+ tosock= out->inputs.first;
+ nodeAddLink(tx->nodetree, in, fromsock, out, tosock);
+
+ ntreeSolveOrder(tx->nodetree); /* needed for pointers */
+ ntreeTexUpdatePreviews(tx->nodetree);
+}
+
+/* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */
+void snode_set_context(SpaceNode *snode, Scene *scene)
+{
+ Object *ob= OBACT;
+ bNode *node= NULL;
+
+ snode->nodetree= NULL;
+ snode->id= snode->from= NULL;
+
+ if(snode->treetype==NTREE_SHADER) {
+ /* need active object, or we allow pinning... */
+ if(ob) {
+ Material *ma= give_current_material(ob, ob->actcol);
+ if(ma) {
+ snode->from= material_from(ob, ob->actcol);
+ snode->id= &ma->id;
+ snode->nodetree= ma->nodetree;
+ }
+ }
+ }
+ else if(snode->treetype==NTREE_COMPOSIT) {
+ snode->from= NULL;
+ snode->id= &scene->id;
+
+ /* bit clumsy but reliable way to see if we draw first time */
+ if(snode->nodetree==NULL)
+ ntreeCompositForceHidden(scene->nodetree, scene);
+
+ snode->nodetree= scene->nodetree;
+ }
+ else if(snode->treetype==NTREE_TEXTURE) {
+ if(ob) {
+ Tex *tx= give_current_texture(ob, ob->actcol);
+ if(tx) {
+ snode->from= (ID*)ob; /* please check this; i have no idea what 'from' is. */
+ snode->id= &tx->id;
+ snode->nodetree= tx->nodetree;
+ }
+ }
+ }
+
+ /* find editable group */
+ if(snode->nodetree)
+ for(node= snode->nodetree->nodes.first; node; node= node->next)
+ if(node->flag & NODE_GROUP_EDIT)
+ break;
+
+ if(node && node->id)
+ snode->edittree= (bNodeTree *)node->id;
+ else
+ snode->edittree= snode->nodetree;
+}
+
+#if 0
+/* on activate image viewer, check if we show it */
+static void node_active_image(Image *ima)
+{
+ ScrArea *sa;
+ SpaceImage *sima= NULL;
+
+ /* find an imagewindow showing render result */
+ for(sa=G.curscreen->areabase.first; sa; sa= sa->next) {
+ if(sa->spacetype==SPACE_IMAGE) {
+ sima= sa->spacedata.first;
+ if(sima->image && sima->image->source!=IMA_SRC_VIEWER)
+ break;
+ }
+ }
+ if(sa && sima) {
+ sima->image= ima;
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+}
+#endif /* 0 */
+
+void node_set_active(SpaceNode *snode, bNode *node)
+{
+
+ nodeSetActive(snode->edittree, node);
+
+ #if 0
+ // XXX
+ if(node->type!=NODE_GROUP) {
+
+ /* tree specific activate calls */
+ if(snode->treetype==NTREE_SHADER) {
+
+ /* when we select a material, active texture is cleared, for buttons */
+ if(node->id && GS(node->id->name)==ID_MA)
+ nodeClearActiveID(snode->edittree, ID_TE);
+ if(node->id)
+ ; // XXX BIF_preview_changed(-1); /* temp hack to force texture preview to update */
+
+ // allqueue(REDRAWBUTSSHADING, 1);
+ // allqueue(REDRAWIPO, 0);
+ }
+ else if(snode->treetype==NTREE_COMPOSIT) {
+ /* make active viewer, currently only 1 supported... */
+ if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ bNode *tnode;
+ int was_output= node->flag & NODE_DO_OUTPUT;
+
+ for(tnode= snode->edittree->nodes.first; tnode; tnode= tnode->next)
+ if( ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
+ tnode->flag &= ~NODE_DO_OUTPUT;
+
+ node->flag |= NODE_DO_OUTPUT;
+ if(was_output==0) {
+ bNode *gnode;
+
+ NodeTagChanged(snode->edittree, node);
+
+ /* if inside group, tag entire group */
+ gnode= snode_get_editgroup(snode);
+ if(gnode)
+ NodeTagIDChanged(snode->nodetree, gnode->id);
+
+ // XXX snode_handle_recalc(snode);
+ }
+
+ /* addnode() doesnt link this yet... */
+ node->id= (ID *)BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ }
+ else if(node->type==CMP_NODE_IMAGE) {
+ if(node->id)
+ node_active_image((Image *)node->id);
+ }
+ else if(node->type==CMP_NODE_R_LAYERS) {
+ if(node->id==NULL || node->id==(ID *)G.scene) {
+ G.scene->r.actlay= node->custom1;
+ // allqueue(REDRAWBUTSSCENE, 0);
+ }
+ }
+ }
+ else if(snode->treetype==NTREE_TEXTURE) {
+ if(node->id)
+ ; // XXX BIF_preview_changed(-1);
+ // allqueue(REDRAWBUTSSHADING, 1);
+ // allqueue(REDRAWIPO, 0);
+ }
+ }
+ #endif /* 0 */
+}
+
+void snode_make_group_editable(SpaceNode *snode, bNode *gnode)
+{
+ bNode *node;
+
+ /* make sure nothing has group editing on */
+ for(node= snode->nodetree->nodes.first; node; node= node->next)
+ node->flag &= ~NODE_GROUP_EDIT;
+
+ if(gnode==NULL) {
+ /* with NULL argument we do a toggle */
+ if(snode->edittree==snode->nodetree)
+ gnode= nodeGetActive(snode->nodetree);
+ }
+
+ if(gnode && gnode->type==NODE_GROUP && gnode->id) {
+ if(gnode->id->lib) {
+ // XXX if(okee("Make Group Local"))
+ // ntreeMakeLocal((bNodeTree *)gnode->id);
+ // else
+ return;
+ }
+ gnode->flag |= NODE_GROUP_EDIT;
+ snode->edittree= (bNodeTree *)gnode->id;
+
+ /* deselect all other nodes, so we can also do grabbing of entire subtree */
+ for(node= snode->nodetree->nodes.first; node; node= node->next)
+ node->flag &= ~SELECT;
+ gnode->flag |= SELECT;
+
+ }
+ else
+ snode->edittree= snode->nodetree;
+
+ ntreeSolveOrder(snode->nodetree);
+
+ /* finally send out events for new active node */
+ if(snode->treetype==NTREE_SHADER) {
+ // allqueue(REDRAWBUTSSHADING, 0);
+
+ // XXX BIF_preview_changed(-1); /* temp hack to force texture preview to update */
+ }
+
+ // allqueue(REDRAWNODE, 0);
+}
+
+#if 0
+
+void node_ungroup(SpaceNode *snode)
+{
+ bNode *gnode;
+
+ /* are we inside of a group? */
+ gnode= snode_get_editgroup(snode);
+ if(gnode)
+ snode_make_group_editable(snode, NULL);
+
+ gnode= nodeGetActive(snode->edittree);
+ if(gnode==NULL) return;
+
+ if(gnode->type!=NODE_GROUP)
+ error("Not a group");
+ else {
+ if(nodeGroupUnGroup(snode->edittree, gnode)) {
+
+ // allqueue(REDRAWNODE, 0);
+ }
+ else
+ error("Can't ungroup");
+ }
+}
+
+#endif /* 0 */
+/* when links in groups change, inputs/outputs change, nodes added/deleted... */
+static void snode_verify_groups(SpaceNode *snode)
+{
+ bNode *gnode;
+
+ gnode= snode_get_editgroup(snode);
+
+ /* does all materials */
+ if(gnode)
+ nodeVerifyGroup((bNodeTree *)gnode->id);
+
+}
+
+#if 0
+
+static void node_addgroup(SpaceNode *snode)
+{
+ bNodeTree *ngroup;
+ int tot= 0, offs, val;
+ char *strp;
+
+ if(snode->edittree!=snode->nodetree) {
+ error("Can not add a Group in a Group");
+ return;
+ }
+
+ /* construct menu with choices */
+ for(ngroup= G.main->nodetree.first; ngroup; ngroup= ngroup->id.next) {
+ if(ngroup->type==snode->treetype)
+ tot++;
+ }
+ if(tot==0) {
+ error("No groups available in database");
+ return;
+ }
+ strp= MEM_mallocN(32*tot+32, "menu");
+ strcpy(strp, "Add Group %t");
+ offs= strlen(strp);
+
+ for(tot=0, ngroup= G.main->nodetree.first; ngroup; ngroup= ngroup->id.next, tot++) {
+ if(ngroup->type==snode->treetype)
+ offs+= sprintf(strp+offs, "|%s %%x%d", ngroup->id.name+2, tot);
+ }
+
+ val= pupmenu(strp);
+ if(val>=0) {
+ ngroup= BLI_findlink(&G.main->nodetree, val);
+ if(ngroup) {
+ bNode *node= nodeAddNodeType(snode->edittree, NODE_GROUP, ngroup, NULL);
+
+ /* generics */
+ if(node) {
+ float locx, locy;
+ short mval[2];
+
+ node_deselectall(snode, 0);
+
+ getmouseco_areawin(mval);
+ areamouseco_to_ipoco(G.v2d, mval, &locx, &locy);
+
+ node->locx= locx;
+ node->locy= locy + 60.0f; // arbitrary.. so its visible
+ node->flag |= SELECT;
+
+ id_us_plus(node->id);
+
+ node_set_active(snode, node);
+ }
+ }
+ }
+ MEM_freeN(strp);
+}
+
+#endif /* 0 */
+
+/* ************************** Node generic ************** */
+
+/* allows to walk the list in order of visibility */
+bNode *next_node(bNodeTree *ntree)
+{
+ static bNode *current=NULL, *last= NULL;
+
+ if(ntree) {
+ /* set current to the first selected node */
+ for(current= ntree->nodes.last; current; current= current->prev)
+ if(current->flag & NODE_SELECT)
+ break;
+
+ /* set last to the first unselected node */
+ for(last= ntree->nodes.last; last; last= last->prev)
+ if((last->flag & NODE_SELECT)==0)
+ break;
+
+ if(current==NULL)
+ current= last;
+
+ return NULL;
+ }
+ /* no nodes, or we are ready */
+ if(current==NULL)
+ return NULL;
+
+ /* now we walk the list backwards, but we always return current */
+ if(current->flag & NODE_SELECT) {
+ bNode *node= current;
+
+ /* find previous selected */
+ current= current->prev;
+ while(current && (current->flag & NODE_SELECT)==0)
+ current= current->prev;
+
+ /* find first unselected */
+ if(current==NULL)
+ current= last;
+
+ return node;
+ }
+ else {
+ bNode *node= current;
+
+ /* find previous unselected */
+ current= current->prev;
+ while(current && (current->flag & NODE_SELECT))
+ current= current->prev;
+
+ return node;
+ }
+
+ return NULL;
+}
+
+/* is rct in visible part of node? */
+static bNode *visible_node(SpaceNode *snode, rctf *rct)
+{
+ bNode *tnode;
+
+ for(next_node(snode->edittree); (tnode=next_node(NULL));) {
+ if(BLI_isect_rctf(&tnode->totr, rct, NULL))
+ break;
+ }
+ return tnode;
+}
+
+void snode_home(ScrArea *sa, ARegion *ar, SpaceNode* snode)
+{
+ bNode *node;
+ rctf *cur, *tot;
+ float oldwidth, oldheight, width, height;
+ int first= 1;
+
+ cur= &ar->v2d.cur;
+ tot= &ar->v2d.tot;
+
+ oldwidth= cur->xmax - cur->xmin;
+ oldheight= cur->ymax - cur->ymin;
+
+ cur->xmin= cur->ymin= 0.0f;
+ cur->xmax=ar->winx;
+ cur->xmax= ar->winy;
+
+ if(snode->edittree) {
+ for(node= snode->edittree->nodes.first; node; node= node->next) {
+ if(first) {
+ first= 0;
+ ar->v2d.cur= node->totr;
+ }
+ else {
+ BLI_union_rctf(cur, &node->totr);
+ }
+ }
+ }
+
+ snode->xof= 0;
+ snode->yof= 0;
+ width= cur->xmax - cur->xmin;
+ height= cur->ymax- cur->ymin;
+ if(width > height) {
+ float newheight;
+ newheight= oldheight * width/oldwidth;
+ cur->ymin= cur->ymin - newheight/4;
+ cur->ymax= cur->ymin + newheight;
+ }
+ else {
+ float newwidth;
+ newwidth= oldwidth * height/oldheight;
+ cur->xmin= cur->xmin - newwidth/4;
+ cur->xmax= cur->xmin + newwidth;
+ }
+
+ ar->v2d.tot= ar->v2d.cur;
+ UI_view2d_curRect_validate(&ar->v2d);
+}
+
+#if 0
+static void snode_bg_viewmove(SpaceNode *snode)
+{
+ ScrArea *sa;
+ Image *ima;
+ ImBuf *ibuf;
+ Window *win;
+ short mval[2], mvalo[2];
+ short rectx, recty, xmin, xmax, ymin, ymax, pad;
+ int oldcursor;
+
+ ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ ibuf= BKE_image_get_ibuf(ima, NULL);
+
+ sa = snode->area;
+
+ if(ibuf) {
+ rectx = ibuf->x;
+ recty = ibuf->y;
+ } else {
+ rectx = recty = 1;
+ }
+
+ pad = 10;
+ xmin = -(sa->winx/2) - rectx/2 + pad;
+ xmax = sa->winx/2 + rectx/2 - pad;
+ ymin = -(sa->winy/2) - recty/2 + pad;
+ ymax = sa->winy/2 + recty/2 - pad;
+
+ getmouseco_sc(mvalo);
+
+ /* store the old cursor to temporarily change it */
+ oldcursor=get_cursor();
+ win=winlay_get_active_window();
+
+ SetBlenderCursor(BC_NSEW_SCROLLCURSOR);
+
+ while(get_mbut()&(L_MOUSE|M_MOUSE)) {
+
+ getmouseco_sc(mval);
+
+ if(mvalo[0]!=mval[0] || mvalo[1]!=mval[1]) {
+
+ snode->xof -= (mvalo[0]-mval[0]);
+ snode->yof -= (mvalo[1]-mval[1]);
+
+ /* prevent dragging image outside of the window and losing it! */
+ CLAMP(snode->xof, xmin, xmax);
+ CLAMP(snode->yof, ymin, ymax);
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+ }
+ else BIF_wait_for_statechange();
+ }
+
+ window_set_cursor(win, oldcursor);
+}
+#endif
+
+/* ********************** size widget operator ******************** */
+
+typedef struct NodeSizeWidget {
+ float mxstart;
+ float oldwidth;
+} NodeSizeWidget;
+
+static int node_resize_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+ bNode *node= editnode_get_active(snode->edittree);
+ NodeSizeWidget *nsw= op->customdata;
+ float mx, my;
+
+ switch (event->type) {
+ case MOUSEMOVE:
+
+ UI_view2d_region_to_view(&ar->v2d, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin,
+ &mx, &my);
+
+ if(node->flag & NODE_HIDDEN) {
+ node->miniwidth= nsw->oldwidth + mx - nsw->mxstart;
+ CLAMP(node->miniwidth, 0.0f, 100.0f);
+ }
+ else {
+ node->width= nsw->oldwidth + mx - nsw->mxstart;
+ CLAMP(node->width, node->typeinfo->minwidth, node->typeinfo->maxwidth);
+ }
+ // XXX
+ if(snode->nodetree->type == NTREE_TEXTURE)
+ ntreeTexUpdatePreviews(snode->nodetree);
+
+ ED_region_tag_redraw(ar);
+
+ break;
+
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE:
+
+ MEM_freeN(nsw);
+ op->customdata= NULL;
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int node_resize_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+ bNode *node= editnode_get_active(snode->edittree);
+
+ if(node) {
+ rctf totr;
+
+ UI_view2d_region_to_view(&ar->v2d, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin,
+ &snode->mx, &snode->my);
+ totr= node->totr;
+ totr.xmin= totr.xmax-10.0f;
+ totr.ymax= totr.ymin+10.0f;
+
+ if(BLI_in_rctf(&totr, snode->mx, snode->my)) {
+ NodeSizeWidget *nsw= MEM_callocN(sizeof(NodeSizeWidget), "size widget op data");
+
+ op->customdata= nsw;
+ nsw->mxstart= snode->mx;
+
+ /* store old */
+ if(node->flag & NODE_HIDDEN)
+ nsw->oldwidth= node->miniwidth;
+ else
+ nsw->oldwidth= node->width;
+
+ /* add modal handler */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+ return OPERATOR_PASS_THROUGH;
+}
+
+void NODE_OT_resize(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Resize Node";
+ ot->idname= "NODE_OT_resize";
+
+ /* api callbacks */
+ ot->invoke= node_resize_invoke;
+ ot->modal= node_resize_modal;
+ ot->poll= ED_operator_node_active;
+
+ /* flags */
+ ot->flag= 0;
+}
+
+
+#if 0
+
+/* ******************** rename ******************* */
+
+void node_rename(SpaceNode *snode)
+{
+ bNode *node, *rename_node;
+ short found_node= 0;
+
+ /* check if a node is selected */
+ for(node= snode->edittree->nodes.first; node; node= node->next) {
+ if(node->flag & SELECT) {
+ found_node= 1;
+ break;
+ }
+ }
+
+ if(found_node) {
+ rename_node= nodeGetActive(snode->edittree);
+ node_rename_but((char *)rename_node->username);
+
+ // allqueue(REDRAWNODE, 1);
+ }
+}
+
+/* ********************** select ******************** */
+
+/* used in buttons to check context, also checks for edited groups */
+bNode *editnode_get_active_idnode(bNodeTree *ntree, short id_code)
+{
+ return nodeGetActiveID(ntree, id_code);
+}
+
+/* used in buttons to check context, also checks for edited groups */
+Material *editnode_get_active_material(Material *ma)
+{
+ if(ma && ma->use_nodes && ma->nodetree) {
+ bNode *node= editnode_get_active_idnode(ma->nodetree, ID_MA);
+ if(node)
+ return (Material *)node->id;
+ else
+ return NULL;
+ }
+ return ma;
+}
+#endif /* 0 */
+
+
+/* no undo here! */
+void node_deselectall(SpaceNode *snode, int swap)
+{
+ bNode *node;
+
+ if(swap) {
+ for(node= snode->edittree->nodes.first; node; node= node->next)
+ if(node->flag & SELECT)
+ break;
+ if(node==NULL) {
+ for(node= snode->edittree->nodes.first; node; node= node->next)
+ node->flag |= SELECT;
+ return;
+ }
+ /* else pass on to deselect */
+ }
+
+ for(node= snode->edittree->nodes.first; node; node= node->next)
+ node->flag &= ~SELECT;
+}
+
+
+int node_has_hidden_sockets(bNode *node)
+{
+ bNodeSocket *sock;
+
+ for(sock= node->inputs.first; sock; sock= sock->next)
+ if(sock->flag & SOCK_HIDDEN)
+ return 1;
+ for(sock= node->outputs.first; sock; sock= sock->next)
+ if(sock->flag & SOCK_HIDDEN)
+ return 1;
+ return 0;
+}
+
+
+static void node_hide_unhide_sockets(SpaceNode *snode, bNode *node)
+{
+ bNodeSocket *sock;
+
+ /* unhide all */
+ if( node_has_hidden_sockets(node) ) {
+ for(sock= node->inputs.first; sock; sock= sock->next)
+ sock->flag &= ~SOCK_HIDDEN;
+ for(sock= node->outputs.first; sock; sock= sock->next)
+ sock->flag &= ~SOCK_HIDDEN;
+ }
+ else {
+ bNode *gnode= snode_get_editgroup(snode);
+
+ /* hiding inside group should not break links in other group users */
+ if(gnode) {
+ nodeGroupSocketUseFlags((bNodeTree *)gnode->id);
+ for(sock= node->inputs.first; sock; sock= sock->next)
+ if(!(sock->flag & SOCK_IN_USE))
+ if(sock->link==NULL)
+ sock->flag |= SOCK_HIDDEN;
+ for(sock= node->outputs.first; sock; sock= sock->next)
+ if(!(sock->flag & SOCK_IN_USE))
+ if(nodeCountSocketLinks(snode->edittree, sock)==0)
+ sock->flag |= SOCK_HIDDEN;
+ }
+ else {
+ /* hide unused sockets */
+ for(sock= node->inputs.first; sock; sock= sock->next) {
+ if(sock->link==NULL)
+ sock->flag |= SOCK_HIDDEN;
+ }
+ for(sock= node->outputs.first; sock; sock= sock->next) {
+ if(nodeCountSocketLinks(snode->edittree, sock)==0)
+ sock->flag |= SOCK_HIDDEN;
+ }
+ }
+ }
+
+ // allqueue(REDRAWNODE, 1);
+ snode_verify_groups(snode);
+
+}
+
+/*static*/ int do_header_node(SpaceNode *snode, bNode *node, float mx, float my)
+{
+ rctf totr= node->totr;
+
+ totr.ymin= totr.ymax-20.0f;
+
+ totr.xmax= totr.xmin+15.0f;
+ if(BLI_in_rctf(&totr, mx, my)) {
+ node->flag |= NODE_HIDDEN;
+ // allqueue(REDRAWNODE, 0);
+ return 1;
+ }
+
+ totr.xmax= node->totr.xmax;
+ totr.xmin= totr.xmax-18.0f;
+ if(node->typeinfo->flag & NODE_PREVIEW) {
+ if(BLI_in_rctf(&totr, mx, my)) {
+ node->flag ^= NODE_PREVIEW;
+ // allqueue(REDRAWNODE, 0);
+ return 1;
+ }
+ totr.xmin-=18.0f;
+ }
+ if(node->type == NODE_GROUP) {
+ if(BLI_in_rctf(&totr, mx, my)) {
+ snode_make_group_editable(snode, node);
+ return 1;
+ }
+ totr.xmin-=18.0f;
+ }
+ if(node->typeinfo->flag & NODE_OPTIONS) {
+ if(BLI_in_rctf(&totr, mx, my)) {
+ node->flag ^= NODE_OPTIONS;
+ // allqueue(REDRAWNODE, 0);
+ return 1;
+ }
+ totr.xmin-=18.0f;
+ }
+ /* hide unused sockets */
+ if(BLI_in_rctf(&totr, mx, my)) {
+ node_hide_unhide_sockets(snode, node);
+ }
+
+
+ totr= node->totr;
+ totr.xmin= totr.xmax-10.0f;
+ totr.ymax= totr.ymin+10.0f;
+ if(BLI_in_rctf(&totr, mx, my)) {
+// scale_node(snode, node);
+ return 1;
+ }
+ return 0;
+}
+
+/*static*/ int do_header_hidden_node(SpaceNode *snode, bNode *node, float mx, float my)
+{
+ rctf totr= node->totr;
+
+ totr.xmax= totr.xmin+15.0f;
+ if(BLI_in_rctf(&totr, mx, my)) {
+ node->flag &= ~NODE_HIDDEN;
+ // allqueue(REDRAWNODE, 0);
+ return 1;
+ }
+
+ totr.xmax= node->totr.xmax;
+ totr.xmin= node->totr.xmax-15.0f;
+ if(BLI_in_rctf(&totr, mx, my)) {
+// scale_node(snode, node);
+ return 1;
+ }
+ return 0;
+}
+
+static void node_link_viewer(SpaceNode *snode, bNode *tonode)
+{
+ bNode *node;
+
+ /* context check */
+ if(tonode==NULL || tonode->outputs.first==NULL)
+ return;
+ if( ELEM(tonode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
+ return;
+
+ /* get viewer */
+ for(node= snode->edittree->nodes.first; node; node= node->next)
+ if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
+ if(node->flag & NODE_DO_OUTPUT)
+ break;
+
+ if(node) {
+ bNodeLink *link;
+
+ /* get link to viewer */
+ for(link= snode->edittree->links.first; link; link= link->next)
+ if(link->tonode==node)
+ break;
+
+ if(link) {
+ link->fromnode= tonode;
+ link->fromsock= tonode->outputs.first;
+ NodeTagChanged(snode->edittree, node);
+
+// XXX snode_handle_recalc(snode);
+ }
+ }
+}
+
+
+void node_active_link_viewer(SpaceNode *snode)
+{
+ bNode *node= editnode_get_active(snode->edittree);
+ if(node)
+ node_link_viewer(snode, node);
+}
+
+/* return 0, nothing done */
+/*static*/ int node_mouse_groupheader(SpaceNode *snode)
+{
+ bNode *gnode;
+ float mx=0, my=0;
+// XXX short mval[2];
+
+ gnode= snode_get_editgroup(snode);
+ if(gnode==NULL) return 0;
+
+// XXX getmouseco_areawin(mval);
+// XXX areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
+
+ /* click in header or outside? */
+ if(BLI_in_rctf(&gnode->totr, mx, my)==0) {
+ rctf rect= gnode->totr;
+
+ rect.ymax += NODE_DY;
+ if(BLI_in_rctf(&rect, mx, my)==0)
+ snode_make_group_editable(snode, NULL); /* toggles, so exits editmode */
+// else
+// XXX transform_nodes(snode->nodetree, 'g', "Move group");
+
+ return 1;
+ }
+ return 0;
+}
+
+/* checks snode->mouse position, and returns found node/socket */
+/* type is SOCK_IN and/or SOCK_OUT */
+static int find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, int in_out)
+{
+ bNode *node;
+ bNodeSocket *sock;
+ rctf rect;
+
+ /* check if we click in a socket */
+ for(node= snode->edittree->nodes.first; node; node= node->next) {
+
+ rect.xmin = snode->mx - NODE_SOCKSIZE+3;
+ rect.ymin = snode->my - NODE_SOCKSIZE+3;
+ rect.xmax = rect.xmin + 2*NODE_SOCKSIZE+6;
+ rect.ymax = rect.ymin + 2*NODE_SOCKSIZE+6;
+
+ if (!(node->flag & NODE_HIDDEN)) {
+ /* extra padding inside and out - allow dragging on the text areas too */
+ if (in_out == SOCK_IN) {
+ rect.xmax += NODE_SOCKSIZE;
+ rect.xmin -= NODE_SOCKSIZE*4;
+ } else if (in_out == SOCK_OUT) {
+ rect.xmax += NODE_SOCKSIZE*4;
+ rect.xmin -= NODE_SOCKSIZE;
+ }
+ }
+
+ if(in_out & SOCK_IN) {
+ for(sock= node->inputs.first; sock; sock= sock->next) {
+ if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+ if(BLI_in_rctf(&rect, sock->locx, sock->locy)) {
+ if(node == visible_node(snode, &rect)) {
+ *nodep= node;
+ *sockp= sock;
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ if(in_out & SOCK_OUT) {
+ for(sock= node->outputs.first; sock; sock= sock->next) {
+ if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+ if(BLI_in_rctf(&rect, sock->locx, sock->locy)) {
+ if(node == visible_node(snode, &rect)) {
+ *nodep= node;
+ *sockp= sock;
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static int node_socket_hilights(SpaceNode *snode, int in_out)
+{
+ bNode *node;
+ bNodeSocket *sock, *tsock, *socksel= NULL;
+ short redraw= 0;
+
+ if(snode->edittree==NULL) return 0;
+
+ /* deselect socks */
+ for(node= snode->edittree->nodes.first; node; node= node->next) {
+ for(sock= node->inputs.first; sock; sock= sock->next) {
+ if(sock->flag & SELECT) {
+ sock->flag &= ~SELECT;
+ redraw++;
+ socksel= sock;
+ }
+ }
+ for(sock= node->outputs.first; sock; sock= sock->next) {
+ if(sock->flag & SELECT) {
+ sock->flag &= ~SELECT;
+ redraw++;
+ socksel= sock;
+ }
+ }
+ }
+
+ // XXX mousepos should be set here!
+
+ if(find_indicated_socket(snode, &node, &tsock, in_out)) {
+ tsock->flag |= SELECT;
+ if(redraw==1 && tsock==socksel) redraw= 0;
+ else redraw= 1;
+ }
+
+ return redraw;
+}
+
+/* ****************** Add *********************** */
+
+void snode_autoconnect(SpaceNode *snode, bNode *node_to, int flag)
+{
+ bNodeSocket *sock, *sockfrom[8];
+ bNode *node, *nodefrom[8];
+ int totsock= 0, socktype=0;
+
+ if(node_to==NULL || node_to->inputs.first==NULL)
+ return;
+
+ /* no inputs for node allowed (code it) */
+
+ /* connect first 1 socket type now */
+ for(sock= node_to->inputs.first; sock; sock= sock->next)
+ if(socktype<sock->type)
+ socktype= sock->type;
+
+
+ /* find potential sockets, max 8 should work */
+ for(node= snode->edittree->nodes.first; node; node= node->next) {
+ if((node->flag & flag) && node!=node_to) {
+ for(sock= node->outputs.first; sock; sock= sock->next) {
+ if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+ sockfrom[totsock]= sock;
+ nodefrom[totsock]= node;
+ totsock++;
+ if(totsock>7)
+ break;
+ }
+ }
+ }
+ if(totsock>7)
+ break;
+ }
+
+ /* now just get matching socket types and create links */
+ for(sock= node_to->inputs.first; sock; sock= sock->next) {
+ int a;
+
+ for(a=0; a<totsock; a++) {
+ if(sockfrom[a]) {
+ if(sock->type==sockfrom[a]->type && sock->type==socktype) {
+ nodeAddLink(snode->edittree, nodefrom[a], sockfrom[a], node_to, sock);
+ sockfrom[a]= NULL;
+ break;
+ }
+ }
+ }
+ }
+
+ ntreeSolveOrder(snode->edittree);
+}
+
+
+/* can be called from menus too, but they should do own undopush and redraws */
+bNode *node_add_node(SpaceNode *snode, Scene *scene, int type, float locx, float locy)
+{
+ bNode *node= NULL, *gnode;
+
+ node_deselectall(snode, 0);
+
+ if(type>=NODE_DYNAMIC_MENU) {
+ node= nodeAddNodeType(snode->edittree, type, NULL, NULL);
+ }
+ else if(type>=NODE_GROUP_MENU) {
+ if(snode->edittree!=snode->nodetree) {
+ // XXX error("Can not add a Group in a Group");
+ return NULL;
+ }
+ else {
+ bNodeTree *ngroup= BLI_findlink(&G.main->nodetree, type-NODE_GROUP_MENU);
+ if(ngroup)
+ node= nodeAddNodeType(snode->edittree, NODE_GROUP, ngroup, NULL);
+ }
+ }
+ else
+ node= nodeAddNodeType(snode->edittree, type, NULL, NULL);
+
+ /* generics */
+ if(node) {
+ node->locx= locx;
+ node->locy= locy + 60.0f; // arbitrary.. so its visible
+ node->flag |= SELECT;
+
+ gnode= snode_get_editgroup(snode);
+ if(gnode) {
+ node->locx -= gnode->locx;
+ node->locy -= gnode->locy;
+ }
+
+ snode_verify_groups(snode);
+ node_set_active(snode, node);
+
+ if(snode->nodetree->type==NTREE_COMPOSIT) {
+ if(ELEM(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE))
+ node->id = &scene->id;
+
+ ntreeCompositForceHidden(snode->edittree, scene);
+ }
+
+ if(node->id)
+ id_us_plus(node->id);
+
+ NodeTagChanged(snode->edittree, node);
+ }
+
+ if(snode->nodetree->type==NTREE_TEXTURE) {
+ ntreeTexCheckCyclics(snode->edittree);
+ ntreeTexUpdatePreviews(snode->edittree);
+ }
+
+ return node;
+}
+
+#if 0
+
+void node_mute(SpaceNode *snode)
+{
+ bNode *node;
+
+ /* no disabling inside of groups */
+ if(snode_get_editgroup(snode))
+ return;
+
+ for(node= snode->edittree->nodes.first; node; node= node->next) {
+ if(node->flag & SELECT) {
+ if(node->inputs.first && node->outputs.first) {
+ if(node->flag & NODE_MUTED)
+ node->flag &= ~NODE_MUTED;
+ else
+ node->flag |= NODE_MUTED;
+ }
+ }
+ }
+
+
+}
+
+void node_adduplicate(SpaceNode *snode)
+{
+
+ ntreeCopyTree(snode->edittree, 1); /* 1 == internally selected nodes */
+
+ ntreeSolveOrder(snode->edittree);
+ snode_verify_groups(snode);
+ // XXX snode_handle_recalc(snode);
+
+// XXX transform_nodes(snode->edittree, 'g', "Duplicate");
+}
+
+static void node_insert_convertor(SpaceNode *snode, bNodeLink *link)
+{
+ bNode *newnode= NULL;
+
+ if(link->fromsock->type==SOCK_RGBA && link->tosock->type==SOCK_VALUE) {
+ if(snode->edittree->type==NTREE_SHADER)
+ newnode= node_add_node(snode, SH_NODE_RGBTOBW, 0.0f, 0.0f);
+ else if(snode->edittree->type==NTREE_COMPOSIT)
+ newnode= node_add_node(snode, CMP_NODE_RGBTOBW, 0.0f, 0.0f);
+ else
+ newnode= NULL;
+ }
+ else if(link->fromsock->type==SOCK_VALUE && link->tosock->type==SOCK_RGBA) {
+ if(snode->edittree->type==NTREE_SHADER)
+ newnode= node_add_node(snode, SH_NODE_VALTORGB, 0.0f, 0.0f);
+ else if(snode->edittree->type==NTREE_COMPOSIT)
+ newnode= node_add_node(snode, CMP_NODE_VALTORGB, 0.0f, 0.0f);
+ else
+ newnode= NULL;
+ }
+
+ if(newnode) {
+ /* dangerous assumption to use first in/out socks, but thats fine for now */
+ newnode->flag |= NODE_HIDDEN;
+ newnode->locx= 0.5f*(link->fromsock->locx + link->tosock->locx);
+ newnode->locy= 0.5f*(link->fromsock->locy + link->tosock->locy) + HIDDEN_RAD;
+
+ nodeAddLink(snode->edittree, newnode, newnode->outputs.first, link->tonode, link->tosock);
+ link->tonode= newnode;
+ link->tosock= newnode->inputs.first;
+ }
+}
+
+
+#endif /* 0 */
+
+/* *************************** add link op ******************** */
+
+/* temp data to pass on to modal */
+typedef struct NodeLinkDrag
+{
+ bNode *node;
+ bNodeSocket *sock;
+ bNodeLink *link;
+ int in_out;
+} NodeLinkDrag;
+
+/*static*/ void reset_sel_socket(SpaceNode *snode, int in_out)
+{
+ bNode *node;
+ bNodeSocket *sock;
+
+ for(node= snode->edittree->nodes.first; node; node= node->next) {
+ if(in_out & SOCK_IN) {
+ for(sock= node->inputs.first; sock; sock= sock->next)
+ if(sock->flag & SOCK_SEL) sock->flag&= ~SOCK_SEL;
+ }
+ if(in_out & SOCK_OUT) {
+ for(sock= node->outputs.first; sock; sock= sock->next)
+ if(sock->flag & SOCK_SEL) sock->flag&= ~SOCK_SEL;
+ }
+ }
+}
+
+
+static void node_remove_extra_links(SpaceNode *snode, bNodeSocket *tsock, bNodeLink *link)
+{
+ bNodeLink *tlink;
+ bNodeSocket *sock;
+
+ if(tsock && nodeCountSocketLinks(snode->edittree, link->tosock) > tsock->limit) {
+
+ for(tlink= snode->edittree->links.first; tlink; tlink= tlink->next) {
+ if(link!=tlink && tlink->tosock==link->tosock)
+ break;
+ }
+ if(tlink) {
+ /* is there a free input socket with same type? */
+ for(sock= tlink->tonode->inputs.first; sock; sock= sock->next) {
+ if(sock->type==tlink->fromsock->type)
+ if(nodeCountSocketLinks(snode->edittree, sock) < sock->limit)
+ break;
+ }
+ if(sock) {
+ tlink->tosock= sock;
+ sock->flag &= ~SOCK_HIDDEN;
+ }
+ else {
+ nodeRemLink(snode->edittree, tlink);
+ }
+ }
+ }
+}
+
+/* loop that adds a nodelink, called by function below */
+/* in_out = starting socket */
+static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+ NodeLinkDrag *nldrag= op->customdata;
+ bNode *tnode, *node;
+ bNodeSocket *tsock= NULL, *sock;
+ bNodeLink *link;
+ int in_out;
+
+ in_out= nldrag->in_out;
+ node= nldrag->node;
+ sock= nldrag->sock;
+ link= nldrag->link;
+
+ UI_view2d_region_to_view(&ar->v2d, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin,
+ &snode->mx, &snode->my);
+
+ switch (event->type) {
+ case MOUSEMOVE:
+
+ if(in_out==SOCK_OUT) {
+ if(find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) {
+ if(nodeFindLink(snode->edittree, sock, tsock)==NULL) {
+ if(tnode!=node && link->tonode!=tnode && link->tosock!= tsock) {
+ link->tonode= tnode;
+ link->tosock= tsock;
+ ntreeSolveOrder(snode->edittree); /* for interactive red line warning */
+ }
+ }
+ }
+ else {
+ link->tonode= NULL;
+ link->tosock= NULL;
+ }
+ }
+ else {
+ if(find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) {
+ if(nodeFindLink(snode->edittree, sock, tsock)==NULL) {
+ if(nodeCountSocketLinks(snode->edittree, tsock) < tsock->limit) {
+ if(tnode!=node && link->fromnode!=tnode && link->fromsock!= tsock) {
+ link->fromnode= tnode;
+ link->fromsock= tsock;
+ ntreeSolveOrder(snode->edittree); /* for interactive red line warning */
+ }
+ }
+ }
+ }
+ else {
+ link->fromnode= NULL;
+ link->fromsock= NULL;
+ }
+ }
+ /* hilight target sockets only */
+ node_socket_hilights(snode, in_out==SOCK_OUT?SOCK_IN:SOCK_OUT);
+ ED_region_tag_redraw(ar);
+ break;
+
+ case LEFTMOUSE:
+ case RIGHTMOUSE:
+ case MIDDLEMOUSE:
+
+ /* remove link? */
+ if(link->tonode==NULL || link->fromnode==NULL) {
+ nodeRemLink(snode->edittree, link);
+ }
+ else {
+ /* send changed events for original tonode and new */
+ if(link->tonode)
+ NodeTagChanged(snode->edittree, link->tonode);
+
+ /* we might need to remove a link */
+ if(in_out==SOCK_OUT) node_remove_extra_links(snode, link->tosock, link);
+ }
+
+ ntreeSolveOrder(snode->edittree);
+ snode_verify_groups(snode);
+ snode_handle_recalc(C, snode);
+
+ MEM_freeN(op->customdata);
+ op->customdata= NULL;
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* return 1 when socket clicked */
+static int node_link_init(SpaceNode *snode, NodeLinkDrag *nldrag)
+{
+ bNodeLink *link;
+
+ /* output indicated? */
+ if(find_indicated_socket(snode, &nldrag->node, &nldrag->sock, SOCK_OUT)) {
+ if(nodeCountSocketLinks(snode->edittree, nldrag->sock) < nldrag->sock->limit)
+ return SOCK_OUT;
+ else {
+ /* find if we break a link */
+ for(link= snode->edittree->links.first; link; link= link->next) {
+ if(link->fromsock==nldrag->sock)
+ break;
+ }
+ if(link) {
+ nldrag->node= link->tonode;
+ nldrag->sock= link->tosock;
+ nodeRemLink(snode->edittree, link);
+ return SOCK_IN;
+ }
+ }
+ }
+ /* or an input? */
+ else if(find_indicated_socket(snode, &nldrag->node, &nldrag->sock, SOCK_IN)) {
+ if(nodeCountSocketLinks(snode->edittree, nldrag->sock) < nldrag->sock->limit)
+ return SOCK_IN;
+ else {
+ /* find if we break a link */
+ for(link= snode->edittree->links.first; link; link= link->next) {
+ if(link->tosock==nldrag->sock)
+ break;
+ }
+ if(link) {
+ /* send changed event to original tonode */
+ if(link->tonode)
+ NodeTagChanged(snode->edittree, link->tonode);
+
+ nldrag->node= link->fromnode;
+ nldrag->sock= link->fromsock;
+ nodeRemLink(snode->edittree, link);
+ return SOCK_OUT;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int node_link_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+ NodeLinkDrag *nldrag= MEM_callocN(sizeof(NodeLinkDrag), "drag link op customdata");
+
+ UI_view2d_region_to_view(&ar->v2d, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin,
+ &snode->mx, &snode->my);
+
+ nldrag->in_out= node_link_init(snode, nldrag);
+
+ if(nldrag->in_out) {
+ op->customdata= nldrag;
+
+ /* we make a temporal link */
+ if(nldrag->in_out==SOCK_OUT)
+ nldrag->link= nodeAddLink(snode->edittree, nldrag->node, nldrag->sock, NULL, NULL);
+ else
+ nldrag->link= nodeAddLink(snode->edittree, NULL, NULL, nldrag->node, nldrag->sock);
+
+ /* add modal handler */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ MEM_freeN(nldrag);
+ return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH;
+ }
+}
+
+void NODE_OT_link(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Link Nodes";
+ ot->idname= "NODE_OT_link";
+
+ /* api callbacks */
+ ot->invoke= node_link_invoke;
+ ot->modal= node_link_modal;
+// ot->exec= node_link_exec;
+ ot->poll= ED_operator_node_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+void node_delete(SpaceNode *snode)
+{
+ bNode *node, *next;
+ bNodeSocket *sock;
+
+ for(node= snode->edittree->nodes.first; node; node= next) {
+ next= node->next;
+ if(node->flag & SELECT) {
+ /* set selin and selout NULL if the sockets belong to a node to be deleted */
+ for(sock= node->inputs.first; sock; sock= sock->next)
+ if(snode->edittree->selin == sock) snode->edittree->selin= NULL;
+
+ for(sock= node->outputs.first; sock; sock= sock->next)
+ if(snode->edittree->selout == sock) snode->edittree->selout= NULL;
+
+ /* check id user here, nodeFreeNode is called for free dbase too */
+ if(node->id)
+ node->id->us--;
+ nodeFreeNode(snode->edittree, node);
+ }
+ }
+
+ snode_verify_groups(snode);
+ // NODE_FIX_ME
+ // snode_handle_recalc(snode);
+ // allqueue(REDRAWNODE, 1);
+}
+
+
+void node_hide(SpaceNode *snode)
+{
+ bNode *node;
+ int nothidden=0, ishidden=0;
+
+ for(node= snode->edittree->nodes.first; node; node= node->next) {
+ if(node->flag & SELECT) {
+ if(node->flag & NODE_HIDDEN)
+ ishidden++;
+ else
+ nothidden++;
+ }
+ }
+ for(node= snode->edittree->nodes.first; node; node= node->next) {
+ if(node->flag & SELECT) {
+ if( (ishidden && nothidden) || ishidden==0)
+ node->flag |= NODE_HIDDEN;
+ else
+ node->flag &= ~NODE_HIDDEN;
+ }
+ }
+}
+
+#if 0
+
+void node_insert_key(SpaceNode *snode)
+{
+ bNode *node= editnode_get_active(snode->edittree);
+
+ if(node == NULL)
+ return;
+
+ if(node->type==CMP_NODE_TIME) {
+ if(node->custom1<node->custom2) {
+
+ CurveMapping *cumap= node->storage;
+ float fval, curval;
+
+ curval= (float)(CFRA - node->custom1)/(float)(node->custom2-node->custom1);
+ fval= curvemapping_evaluateF(cumap, 0, curval);
+
+ if(fbutton(&fval, 0.0f, 1.0f, 10, 10, "Insert Value")) {
+ curvemap_insert(cumap->cm, curval, fval);
+
+ }
+ }
+ }
+}
+
+void node_select_linked(SpaceNode *snode, int out)
+{
+ bNodeLink *link;
+ bNode *node;
+
+ /* NODE_TEST is the free flag */
+ for(node= snode->edittree->nodes.first; node; node= node->next)
+ node->flag &= ~NODE_TEST;
+
+ for(link= snode->edittree->links.first; link; link= link->next) {
+ if(out) {
+ if(link->fromnode->flag & NODE_SELECT)
+ link->tonode->flag |= NODE_TEST;
+ }
+ else {
+ if(link->tonode->flag & NODE_SELECT)
+ link->fromnode->flag |= NODE_TEST;
+ }
+ }
+
+ for(node= snode->edittree->nodes.first; node; node= node->next)
+ if(node->flag & NODE_TEST)
+ node->flag |= NODE_SELECT;
+
+}
+
+/* makes a link between selected output and input sockets */
+void node_make_link(SpaceNode *snode)
+{
+ bNode *fromnode, *tonode;
+ bNodeLink *link;
+ bNodeSocket *outsock= snode->edittree->selout;
+ bNodeSocket *insock= snode->edittree->selin;
+
+ if(!insock || !outsock) return;
+ if(nodeFindLink(snode->edittree, outsock, insock)) return;
+
+ if(nodeFindNode(snode->edittree, outsock, &fromnode, NULL) &&
+ nodeFindNode(snode->edittree, insock, &tonode, NULL)) {
+ link= nodeAddLink(snode->edittree, fromnode, outsock, tonode, insock);
+ NodeTagChanged(snode->edittree, tonode);
+ node_remove_extra_links(snode, insock, link);
+ }
+ else return;
+
+ ntreeSolveOrder(snode->edittree);
+ snode_verify_groups(snode);
+ // XXX snode_handle_recalc(snode);
+
+}
+#endif
+
+/* ********************** Cut Link operator ***************** */
+
+#define LINK_RESOL 12
+static int cut_links_intersect(bNodeLink *link, float mcoords[][2], int tot)
+{
+ float coord_array[LINK_RESOL+1][2];
+ int i, b;
+
+ if(node_link_bezier_points(NULL, NULL, link, coord_array, LINK_RESOL)) {
+
+ for(i=0; i<tot-1; i++)
+ for(b=0; b<LINK_RESOL-1; b++)
+ if(IsectLL2Df(mcoords[i], mcoords[i+1], coord_array[b], coord_array[b+1]) > 0)
+ return 1;
+ }
+ return 0;
+}
+
+static int cut_links_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+ float mcoords[256][2];
+ int i= 0;
+
+ RNA_BEGIN(op->ptr, itemptr, "path") {
+ float loc[2];
+
+ RNA_float_get_array(&itemptr, "loc", loc);
+ UI_view2d_region_to_view(&ar->v2d, (short)loc[0], (short)loc[1],
+ &mcoords[i][0], &mcoords[i][1]);
+ i++;
+ if(i>= 256) break;
+ }
+ RNA_END;
+
+ if(i>1) {
+ bNodeLink *link, *next;
+
+ for(link= snode->edittree->links.first; link; link= link->next) {
+ next= link->next;
+
+ if(cut_links_intersect(link, mcoords, i)) {
+ NodeTagChanged(snode->edittree, link->tonode);
+ nodeRemLink(snode->edittree, link);
+ }
+ }
+
+ ntreeSolveOrder(snode->edittree);
+ snode_verify_groups(snode);
+ snode_handle_recalc(C, snode);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_PASS_THROUGH;;
+}
+
+void NODE_OT_links_cut(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ ot->name= "Cut links";
+ ot->idname= "NODE_OT_links_cut";
+
+ ot->invoke= WM_gesture_lines_invoke;
+ ot->modal= WM_gesture_lines_modal;
+ ot->exec= cut_links_exec;
+
+ ot->poll= ED_operator_node_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
+ /* internal */
+ RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
+}
+
+/* ******************************** */
+
+/* goes over all scenes, reads render layerss */
+void node_read_renderlayers(SpaceNode *snode)
+{
+ Scene *curscene= NULL; // XXX
+ Scene *scene;
+ bNode *node;
+
+ /* first tag scenes unread */
+ for(scene= G.main->scene.first; scene; scene= scene->id.next)
+ scene->id.flag |= LIB_DOIT;
+
+ for(node= snode->edittree->nodes.first; node; node= node->next) {
+ if(node->type==CMP_NODE_R_LAYERS) {
+ ID *id= node->id;
+ if(id->flag & LIB_DOIT) {
+ RE_ReadRenderResult(curscene, (Scene *)id);
+ ntreeCompositTagRender((Scene *)id);
+ id->flag &= ~LIB_DOIT;
+ }
+ }
+ }
+
+ // XXX snode_handle_recalc(snode);
+}
+
+void node_read_fullsamplelayers(SpaceNode *snode)
+{
+ Scene *curscene= NULL; // XXX
+ Render *re= RE_NewRender(curscene->id.name);
+
+ WM_cursor_wait(1);
+
+ //BIF_init_render_callbacks(re, 1);
+ RE_MergeFullSample(re, curscene, snode->nodetree);
+ //BIF_end_render_callbacks();
+
+ // allqueue(REDRAWNODE, 1);
+ // allqueue(REDRAWIMAGE, 1);
+
+ WM_cursor_wait(0);
+}
+
+/* called from header_info, when deleting a scene
+ * goes over all scenes other than the input, checks if they have
+ * render layer nodes referencing the to-be-deleted scene, and
+ * resets them to NULL. */
+
+/* XXX needs to get current scene then! */
+void clear_scene_in_nodes(Scene *sce)
+{
+ Scene *sce1;
+ bNode *node;
+
+ sce1= G.main->scene.first;
+ while(sce1) {
+ if(sce1!=sce) {
+ if (sce1->nodetree) {
+ for(node= sce1->nodetree->nodes.first; node; node= node->next) {
+ if(node->type==CMP_NODE_R_LAYERS) {
+ Scene *nodesce= (Scene *)node->id;
+
+ if (nodesce==sce) node->id = NULL;
+ }
+ }
+ }
+ }
+ sce1= sce1->id.next;
+ }
+}
+
+void imagepaint_composite_tags(bNodeTree *ntree, Image *image, ImageUser *iuser)
+{
+ bNode *node;
+
+ if(ntree==NULL)
+ return;
+
+ /* search for renderresults */
+ if(image->type==IMA_TYPE_R_RESULT) {
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->type==CMP_NODE_R_LAYERS && node->id==NULL) {
+ /* imageuser comes from ImageWin, so indexes are offset 1 */
+ if(node->custom1==iuser->layer-1)
+ NodeTagChanged(ntree, node);
+ }
+ }
+ }
+ else {
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->id== &image->id)
+ NodeTagChanged(ntree, node);
+ }
+ }
+}
+
+/* ********************** */
+
+void node_make_group(SpaceNode *snode)
+{
+ bNode *gnode;
+
+ if(snode->edittree!=snode->nodetree) {
+// XXX error("Can not add a new Group in a Group");
+ return;
+ }
+
+ /* for time being... is too complex to handle */
+ if(snode->treetype==NTREE_COMPOSIT) {
+ for(gnode=snode->nodetree->nodes.first; gnode; gnode= gnode->next) {
+ if(gnode->flag & SELECT)
+ if(gnode->type==CMP_NODE_R_LAYERS)
+ break;
+ }
+ if(gnode) {
+// XXX error("Can not add RenderLayer in a Group");
+ return;
+ }
+ }
+
+ gnode= nodeMakeGroupFromSelected(snode->nodetree);
+ if(gnode==NULL) {
+// XXX error("Can not make Group");
+ }
+ else {
+ nodeSetActive(snode->nodetree, gnode);
+ ntreeSolveOrder(snode->nodetree);
+ }
+}
+
+#if 0
+
+/* ******************** main event loop ****************** */
+
+void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
+{
+ SpaceNode *snode= spacedata;
+ bNode *actnode;
+ bNodeSocket *actsock;
+ unsigned short event= evt->event;
+ short val= evt->val, doredraw=0, fromlib= 0;
+
+ if(sa->win==0) return;
+
+ if(snode->nodetree==NULL) {
+ /* no other events should be handled, but floating panels still should get handled */
+ uiDoBlocks(&curarea->uiblocks, event, 1);
+ return;
+ }
+
+ if(val) {
+ if( node_uiDoBlocks(sa, event)!=UI_NOTHING ) event= 0;
+
+ fromlib= (snode->id && snode->id->lib);
+
+ switch(event) {
+ case LEFTMOUSE:
+ if(gpencil_do_paint(sa, L_MOUSE)) {
+ return;
+ }
+ else if(fromlib) {
+ if(node_mouse_groupheader(snode)==0)
+ //node_mouse_select(snode, event);
+ }
+ else {
+
+ if(G.qual & LR_CTRLKEY)
+ if(gesture())
+ break;
+
+// if(node_add_link(snode)==0)
+ if(node_mouse_groupheader(snode)==0)
+// if(node_mouse_select(snode, event)==0)
+ node_border_link_delete(snode);
+ }
+ break;
+
+ case RIGHTMOUSE:
+ if(gpencil_do_paint(sa, R_MOUSE)) {
+ return;
+ }
+ else if(find_indicated_socket(snode, &actnode, &actsock, SOCK_IN)) {
+ if(actsock->flag & SOCK_SEL) {
+ snode->edittree->selin= NULL;
+ actsock->flag&= ~SOCK_SEL;
+ }
+ else {
+ snode->edittree->selin= actsock;
+ reset_sel_socket(snode, SOCK_IN);
+ actsock->flag|= SOCK_SEL;
+ }
+ }
+ else if(find_indicated_socket(snode, &actnode, &actsock, SOCK_OUT)) {
+ if(actsock->flag & SOCK_SEL) {
+ snode->edittree->selout= NULL;
+ actsock->flag&= ~SOCK_SEL;
+ }
+ else {
+ snode->edittree->selout= actsock;
+ reset_sel_socket(snode, SOCK_OUT);
+ actsock->flag|= SOCK_SEL;
+ }
+ }
+// else if(!node_mouse_select(snode, event))
+// toolbox_n();
+
+ break;
+ case MIDDLEMOUSE:
+ if((snode->flag & SNODE_BACKDRAW) && (snode->treetype==NTREE_COMPOSIT)
+ && (G.qual==LR_SHIFTKEY)) {
+ snode_bg_viewmove(snode);
+ } else {
+ view2dmove(event);
+ }
+ case WHEELUPMOUSE:
+ case WHEELDOWNMOUSE:
+ view2dmove(event); /* in drawipo.c */
+ break;
+
+ case MOUSEY:
+ doredraw= node_socket_hilights(snode, SOCK_IN|SOCK_OUT);
+ break;
+
+ case UI_BUT_EVENT:
+ /* future: handlerize this! */
+ if(snode->treetype==NTREE_SHADER)
+ shader_node_event(snode, val);
+ else if(snode->treetype==NTREE_COMPOSIT)
+ composit_node_event(snode, val);
+ else if(snode->treetype==NTREE_TEXTURE)
+ texture_node_event(snode, val);
+ break;
+
+ case PADPLUSKEY:
+ snode_zoom_in(sa);
+ doredraw= 1;
+ break;
+ case PADMINUS:
+ snode_zoom_out(sa);
+ doredraw= 1;
+ break;
+ case HOMEKEY:
+ snode_home(sa, snode);
+ doredraw= 1;
+ break;
+ case TABKEY:
+ if(fromlib) fromlib= -1;
+ else snode_make_group_editable(snode, NULL);
+ break;
+
+ case AKEY:
+ if(G.qual==LR_SHIFTKEY) {
+ if(fromlib) fromlib= -1;
+ else toolbox_n_add();
+ }
+ else if(G.qual==0) {
+ node_deselectall(snode, 1);
+ }
+ break;
+ case BKEY:
+ if(G.qual==0)
+ node_border_select(snode);
+ break;
+ case CKEY: /* sort again, showing cyclics */
+ ntreeSolveOrder(snode->edittree);
+ doredraw= 1;
+ break;
+ case DKEY:
+ if(G.qual==LR_SHIFTKEY) {
+ if(fromlib) fromlib= -1;
+ else node_adduplicate(snode);
+ }
+ break;
+ case EKEY:
+ // XXX snode_handle_recalc(snode);
+ break;
+ case FKEY:
+ node_make_link(snode);
+ break;
+ case GKEY:
+ if(fromlib) fromlib= -1;
+ else {
+ if(G.qual==LR_CTRLKEY) {
+ if(okee("Make Group"))
+ node_make_group(snode);
+ }
+ else if(G.qual==LR_ALTKEY) {
+ if(okee("Ungroup"))
+ node_ungroup(snode);
+ }
+ else if(G.qual==LR_SHIFTKEY) {
+ node_addgroup(snode);
+ }
+// else
+// XXX transform_nodes(snode->edittree, 'g', "Move Node");
+ }
+ break;
+ case HKEY:
+ node_hide(snode);
+ break;
+ case IKEY:
+ node_insert_key(snode);
+ break;
+ case LKEY:
+ node_select_linked(snode, G.qual==LR_SHIFTKEY);
+ break;
+ case MKEY:
+ node_mute(snode);
+ break;
+ case RKEY:
+ if(G.qual==LR_CTRLKEY) {
+ node_rename(snode);
+ }
+ else if(G.qual==LR_SHIFTKEY) {
+ if(okee("Read saved Full Sample Layers"))
+ node_read_fullsamplelayers(snode);
+ }
+ else {
+ if(okee("Read saved Render Layers"))
+ node_read_renderlayers(snode);
+ }
+ break;
+ case DELKEY:
+ case XKEY:
+ if(G.qual==LR_ALTKEY) {
+ gpencil_delete_menu();
+ }
+ else {
+ if(fromlib) fromlib= -1;
+ else node_delete(snode);
+ }
+ break;
+ }
+ }
+
+ if(fromlib==-1)
+ error_libdata();
+ if(doredraw)
+ scrarea_queue_winredraw(sa);
+ if(doredraw==2)
+ scrarea_queue_headredraw(sa);
+}
+#endif
+
+static int node_delete_selection_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+
+ node_delete(snode);
+ ED_region_tag_redraw(ar);
+ WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); /* Do we need to pass the scene? */
+
+ return OPERATOR_FINISHED;
+}
+
+/* operators */
+
+void NODE_OT_delete(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Delete";
+ ot->idname= "NODE_OT_delete";
+
+ /* api callbacks */
+ ot->exec= node_delete_selection_exec;
+ ot->poll= ED_operator_node_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c
new file mode 100644
index 00000000000..002e4eea681
--- /dev/null
+++ b/source/blender/editors/space_node/node_header.c
@@ -0,0 +1,788 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_space_types.h"
+#include "DNA_node_types.h"
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_node.h"
+#include "BKE_main.h"
+
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "node_intern.h"
+
+/* ************************ header area region *********************** */
+
+static void do_node_selectmenu(bContext *C, void *arg, int event)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+
+ /* functions in editnode.c assume there's a tree */
+ if(snode->nodetree==NULL)
+ return;
+
+ switch(event) {
+ case 1: /* border select */
+ WM_operator_name_call(C, "NODE_OT_select_border", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ case 2: /* select/deselect all */
+ // XXX node_deselectall(snode, 1);
+ break;
+ case 3: /* select linked in */
+ // XXX node_select_linked(snode, 0);
+ break;
+ case 4: /* select linked out */
+ // XXX node_select_linked(snode, 1);
+ break;
+ }
+
+ ED_area_tag_redraw(curarea);
+}
+
+static uiBlock *node_selectmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "node_selectmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_node_selectmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Border Select|B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Linked From|L", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Linked To|Shift L", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+void do_node_addmenu(bContext *C, void *arg, int event)
+{
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ bNode *node;
+
+ /* store selection in temp test flag */
+ for(node= snode->edittree->nodes.first; node; node= node->next) {
+ if(node->flag & NODE_SELECT) node->flag |= NODE_TEST;
+ else node->flag &= ~NODE_TEST;
+ }
+
+ node= node_add_node(snode, CTX_data_scene(C), event, snode->mx, snode->my);
+
+ /* uses test flag */
+ snode_autoconnect(snode, node, NODE_TEST);
+
+ snode_handle_recalc(C, snode);
+}
+
+static void node_make_addmenu(bContext *C, int nodeclass, uiBlock *block)
+{
+ Main *bmain= CTX_data_main(C);
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ bNodeTree *ntree;
+ int tot= 0, a;
+ short yco= 0, menuwidth=120;
+
+ ntree = snode->nodetree;
+ if(ntree) {
+ /* mostly taken from toolbox.c, node_add_sublevel() */
+ if(ntree) {
+ if(nodeclass==NODE_CLASS_GROUP) {
+ bNodeTree *ngroup= bmain->nodetree.first;
+ for(; ngroup; ngroup= ngroup->id.next)
+ if(ngroup->type==ntree->type)
+ tot++;
+ }
+ else {
+ bNodeType *type = ntree->alltypes.first;
+ while(type) {
+ if(type->nclass == nodeclass)
+ tot++;
+ type= type->next;
+ }
+ }
+ }
+
+ if(tot==0) {
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ return;
+ }
+
+ if(nodeclass==NODE_CLASS_GROUP) {
+ bNodeTree *ngroup= bmain->nodetree.first;
+ for(tot=0, a=0; ngroup; ngroup= ngroup->id.next, tot++) {
+ if(ngroup->type==ntree->type) {
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, (ngroup->id.name+2), 0,
+ yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1.0f, (float)(NODE_GROUP_MENU+tot), "");
+ a++;
+ }
+ }
+ }
+ else {
+ bNodeType *type;
+ int script=0;
+ for(a=0, type= ntree->alltypes.first; type; type=type->next) {
+ if( type->nclass == nodeclass && type->name) {
+ if(type->type == NODE_DYNAMIC) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, type->name, 0,
+ yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1.0f, (float)(NODE_DYNAMIC_MENU+script), "");
+ script++;
+ } else {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, type->name, 0,
+ yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1.0f, (float)(type->type), "");
+ }
+ a++;
+ }
+ }
+ }
+ } else {
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ return;
+ }
+}
+
+static uiBlock *node_add_inputmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "node_add_inputmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_node_addmenu, NULL);
+
+ node_make_addmenu(C, NODE_CLASS_INPUT, block);
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+static uiBlock *node_add_outputmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "node_add_outputmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_node_addmenu, NULL);
+
+ node_make_addmenu(C, NODE_CLASS_OUTPUT, block);
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+static uiBlock *node_add_colormenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "node_add_colormenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_node_addmenu, NULL);
+
+ node_make_addmenu(C, NODE_CLASS_OP_COLOR, block);
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+static uiBlock *node_add_vectormenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "node_add_vectormenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_node_addmenu, NULL);
+
+ node_make_addmenu(C, NODE_CLASS_OP_VECTOR, block);
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+static uiBlock *node_add_filtermenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "node_add_filtermenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_node_addmenu, NULL);
+
+ node_make_addmenu(C, NODE_CLASS_OP_FILTER, block);
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+static uiBlock *node_add_convertermenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "node_add_convertermenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_node_addmenu, NULL);
+
+ node_make_addmenu(C, NODE_CLASS_CONVERTOR, block);
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+static uiBlock *node_add_mattemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "node_add_mattemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_node_addmenu, NULL);
+
+ node_make_addmenu(C, NODE_CLASS_MATTE, block);
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+static uiBlock *node_add_distortmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "node_add_distortmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_node_addmenu, NULL);
+
+ node_make_addmenu(C, NODE_CLASS_DISTORT, block);
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+static uiBlock *node_add_patternmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "node_add_patternmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_node_addmenu, NULL);
+
+ node_make_addmenu(C, NODE_CLASS_PATTERN, block);
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+static uiBlock *node_add_texturemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "node_add_texturemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_node_addmenu, NULL);
+
+ node_make_addmenu(C, NODE_CLASS_TEXTURE, block);
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+static uiBlock *node_add_groupmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "node_add_groupmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_node_addmenu, NULL);
+
+ node_make_addmenu(C, NODE_CLASS_GROUP, block);
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static uiBlock *node_add_dynamicmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "node_add_dynamicmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_node_addmenu, NULL);
+
+ node_make_addmenu(C, NODE_CLASS_OP_DYNAMIC, block);
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static uiBlock *node_addmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "node_addmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_node_addmenu, NULL);
+
+ if(snode->treetype==NTREE_SHADER) {
+ uiDefIconTextBlockBut(block, node_add_inputmenu, NULL, ICON_RIGHTARROW_THIN, "Input", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_outputmenu, NULL, ICON_RIGHTARROW_THIN, "Output", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_colormenu, NULL, ICON_RIGHTARROW_THIN, "Color", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_vectormenu, NULL, ICON_RIGHTARROW_THIN, "Vector", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_convertermenu, NULL, ICON_RIGHTARROW_THIN, "Convertor", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_groupmenu, NULL, ICON_RIGHTARROW_THIN, "Group", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_dynamicmenu, NULL, ICON_RIGHTARROW_THIN, "Dynamic", 0, yco-=20, 120, 19, "");
+ }
+ else if(snode->treetype==NTREE_COMPOSIT) {
+ uiDefIconTextBlockBut(block, node_add_inputmenu, NULL, ICON_RIGHTARROW_THIN, "Input", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_outputmenu, NULL, ICON_RIGHTARROW_THIN, "Output", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_colormenu, NULL, ICON_RIGHTARROW_THIN, "Color", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_vectormenu, NULL, ICON_RIGHTARROW_THIN, "Vector", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_filtermenu, NULL, ICON_RIGHTARROW_THIN, "Filter", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_convertermenu, NULL, ICON_RIGHTARROW_THIN, "Convertor", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_mattemenu, NULL, ICON_RIGHTARROW_THIN, "Matte", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_distortmenu, NULL, ICON_RIGHTARROW_THIN, "Distort", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_groupmenu, NULL, ICON_RIGHTARROW_THIN, "Group", 0, yco-=20, 120, 19, "");
+
+ } else if(snode->treetype==NTREE_TEXTURE) {
+ uiDefIconTextBlockBut(block, node_add_inputmenu, NULL, ICON_RIGHTARROW_THIN, "Input", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_outputmenu, NULL, ICON_RIGHTARROW_THIN, "Output", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_colormenu, NULL, ICON_RIGHTARROW_THIN, "Color", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_patternmenu, NULL, ICON_RIGHTARROW_THIN, "Patterns", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_texturemenu, NULL, ICON_RIGHTARROW_THIN, "Textures", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_convertermenu, NULL, ICON_RIGHTARROW_THIN, "Convertor", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_distortmenu, NULL, ICON_RIGHTARROW_THIN, "Distort", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, node_add_groupmenu, NULL, ICON_RIGHTARROW_THIN, "Group", 0, yco-=20, 120, 19, "");
+ }
+ else
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+
+ return block;
+}
+
+static void do_node_nodemenu(bContext *C, void *arg, int event)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ int fromlib=0;
+
+ /* functions in editnode.c assume there's a tree */
+ if(snode->nodetree==NULL)
+ return;
+ fromlib= (snode->id && snode->id->lib);
+
+ switch(event) {
+ case 1: /* grab/move */
+ // XXX node_transform_ext(0,0);
+ break;
+ case 2: /* duplicate */
+ if(fromlib) fromlib= -1;
+ else ; // XXX node_adduplicate(snode);
+ break;
+ case 3: /* delete */
+ if(fromlib) fromlib= -1;
+ else ; // XXX node_delete(snode);
+ break;
+ case 4: /* make group */
+ // XXX node_make_group(snode);
+ break;
+ case 5: /* ungroup */
+ // XXX node_ungroup(snode);
+ break;
+ case 6: /* edit group */
+ if(fromlib) fromlib= -1;
+ else ; // XXX snode_make_group_editable(snode, NULL);
+ break;
+ case 7: /* hide/unhide */
+ // XXX node_hide(snode);
+ break;
+ case 8: /* read saved render layers */
+ // XXX node_read_renderlayers(snode);
+ break;
+ case 9: /* show cyclic */
+ // XXX ntreeSolveOrder(snode->edittree);
+ break;
+ case 10: /* execute */
+ // XXXX addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC);
+ break;
+ case 11: /* make link */
+ // XXX node_make_link(snode);
+ break;
+ case 12: /* rename */
+ // XXX node_rename(snode);
+ break;
+ case 13: /* read saved full sample layers */
+ // XXX node_read_fullsamplelayers(snode);
+ break;
+ case 14: /* connect viewer */
+ // XXX node_active_link_viewer(snode);
+ break;
+
+ }
+
+ // XXX if(fromlib==-1) error_libdata();
+
+ ED_area_tag_redraw(curarea);
+}
+
+static uiBlock *node_nodemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "node_nodemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_node_nodemenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move|G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate|Shift D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete|X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Link|F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Group|Ctrl G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Ungroup|Alt G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Edit Group|Tab", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Hide/Unhide|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rename|Ctrl R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if(snode->treetype==NTREE_COMPOSIT) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Execute Composite|E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Read Saved Render Results|R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Read Saved Full Sample Results|Shift R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Connect Node to Viewer|Ctrl RMB", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ }
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Cyclic Dependencies|C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static void do_node_viewmenu(bContext *C, void *arg, int event)
+{
+// SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+// ARegion *ar= CTX_wm_region(C);
+ ScrArea *sa= CTX_wm_area(C);
+
+ switch(event) {
+ case 1: /* Zoom in */
+ WM_operator_name_call(C, "VIEW2D_OT_zoom_in", WM_OP_EXEC_REGION_WIN, NULL);
+ break;
+ case 2: /* View all */
+ WM_operator_name_call(C, "VIEW2D_OT_zoom_out", WM_OP_EXEC_REGION_WIN, NULL);
+ break;
+ case 3: /* View all */
+ WM_operator_name_call(C, "NODE_OT_view_all", WM_OP_EXEC_REGION_WIN, NULL);
+ break;
+ case 4: /* Grease Pencil */
+ // XXX add_blockhandler(sa, NODES_HANDLER_GREASEPENCIL, UI_PNL_UNSTOW);
+ break;
+ }
+ ED_area_tag_redraw(sa);
+}
+
+static uiBlock *node_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "node_viewmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_node_viewmenu, NULL);
+
+ if (snode->nodetree) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Grease Pencil...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ }
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom In|NumPad +", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom Out|NumPad -", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View All|Home", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ /* XXX if (!curarea->full)
+ uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
+ else
+ uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
+ */
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static void do_node_buttons(bContext *C, void *arg, int event)
+{
+ // NODE_FIX_ME : instead of using "current material/texture/scene", node editor can also pin context?
+ // note: scene context better not gets overridden, that'll clash too much (ton)
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ Material *ma;
+ Tex *tx;
+
+ switch(event) {
+ case B_REDR:
+ ED_area_tag_redraw(CTX_wm_area(C));
+ break;
+ case B_NODE_USEMAT:
+ ma= (Material *)snode->id;
+ if(ma) {
+ if(ma->use_nodes && ma->nodetree==NULL) {
+ node_shader_default(ma);
+ snode_set_context(snode, scene);
+ }
+ }
+ ED_area_tag_redraw(CTX_wm_area(C));
+ break;
+
+ case B_NODE_USESCENE:
+ if(scene->use_nodes) {
+ if(scene->nodetree==NULL)
+ node_composit_default(scene);
+ }
+ snode_set_context(snode, scene);
+ ED_area_tag_redraw(CTX_wm_area(C));
+ break;
+
+ case B_NODE_USETEX:
+ tx = (Tex *)snode->id;
+ if(tx) {
+ tx->type = 0;
+ if(tx->use_nodes && tx->nodetree==NULL) {
+ node_texture_default(tx);
+ snode_set_context(snode, scene);
+ }
+ }
+ ED_area_tag_redraw(CTX_wm_area(C));
+ break;
+ }
+}
+
+void node_header_buttons(const bContext *C, ARegion *ar)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ uiBlock *block;
+ short xco, yco= 3;
+
+ block= uiBeginBlock(C, ar, "header node", UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_node_buttons, NULL);
+
+ xco= ED_area_header_standardbuttons(C, block, yco);
+
+ if((sa->flag & HEADER_NO_PULLDOWN)==0) {
+ int xmax;
+
+ xmax= GetButStringLength("View");
+ uiDefPulldownBut(block, node_viewmenu, NULL,
+ "View", xco, yco-2, xmax-3, 24, "");
+ xco+= xmax;
+
+ xmax= GetButStringLength("Select");
+ uiDefPulldownBut(block, node_selectmenu, NULL,
+ "Select", xco, yco-2, xmax-3, 24, "");
+ xco+= xmax;
+
+ xmax= GetButStringLength("Add");
+ uiDefPulldownBut(block, node_addmenu, NULL,
+ "Add", xco, yco-2, xmax-3, 24, "");
+ xco+= xmax;
+
+ xmax= GetButStringLength("Node");
+ uiDefPulldownBut(block, node_nodemenu, NULL,
+ "Node", xco, yco-2, xmax-3, 24, "");
+ xco+= xmax;
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ /* main type choosing */
+ uiBlockBeginAlign(block);
+ uiDefIconButI(block, ROW, B_REDR, ICON_MATERIAL_DATA, xco,yco,XIC,YIC-2,
+ &(snode->treetype), 2.0f, 0.0f, 0.0f, 0.0f, "Material Nodes");
+ xco+= XIC;
+ uiDefIconButI(block, ROW, B_REDR, ICON_IMAGE_DATA, xco,yco,XIC,YIC-2,
+ &(snode->treetype), 2.0f, 1.0f, 0.0f, 0.0f, "Composite Nodes");
+ xco+= XIC;
+ uiDefIconButI(block, ROW, B_REDR, ICON_TEXTURE_DATA, xco,yco,XIC,YIC-2,
+ &(snode->treetype), 2.0f, 2.0f, 0.0f, 0.0f, "Texture Nodes");
+ xco+= 2*XIC;
+ uiBlockEndAlign(block);
+
+ /* find and set the context */
+ snode_set_context(snode, scene);
+
+ if(snode->treetype==NTREE_SHADER) {
+ if(snode->from) {
+ /* 0, NULL -> pin */
+ // XXX xco= std_libbuttons(block, xco, 0, 0, NULL, B_MATBROWSE, ID_MA, 1, snode->id, snode->from, &(snode->menunr),
+ // B_MATALONE, B_MATLOCAL, B_MATDELETE, B_AUTOMATNAME, B_KEEPDATA);
+
+ if(snode->id) {
+ Material *ma= (Material *)snode->id;
+ uiDefButC(block, TOG, B_NODE_USEMAT, "Use Nodes", xco+5,yco,90,19, &ma->use_nodes, 0.0f, 0.0f, 0, 0, "");
+ xco+=80;
+ }
+ }
+ }
+ else if(snode->treetype==NTREE_COMPOSIT) {
+ int icon;
+
+ if(WM_jobs_test(CTX_wm_manager(C), sa)) icon= ICON_REC; else icon= ICON_BLANK1;
+ uiDefIconTextButS(block, TOG, B_NODE_USESCENE, icon, "Use Nodes", xco+5,yco,100,19, &scene->use_nodes, 0.0f, 0.0f, 0, 0, "Indicate this Scene will use Nodes and execute them while editing");
+ xco+= 100;
+ uiDefButBitI(block, TOG, R_COMP_FREE, B_NOP, "Free Unused", xco+5,yco,100,19, &scene->r.scemode, 0.0f, 0.0f, 0, 0, "Free Nodes that are not used while composite");
+ xco+= 100;
+ uiDefButBitS(block, TOG, SNODE_BACKDRAW, B_REDR, "Backdrop", xco+5,yco,90,19, &snode->flag, 0.0f, 0.0f, 0, 0, "Use active Viewer Node output as backdrop");
+ xco+= 90;
+ }
+ else if(snode->treetype==NTREE_TEXTURE) {
+ if(snode->from) {
+
+ // XXX xco= std_libbuttons(block, xco, 0, 0, NULL, B_TEXBROWSE, ID_TE, 1, snode->id, snode->from, &(snode->menunr),
+ // B_TEXALONE, B_TEXLOCAL, B_TEXDELETE, B_AUTOTEXNAME, B_KEEPDATA);
+
+ if(snode->id) {
+ Tex *tx= (Tex *)snode->id;
+ uiDefButC(block, TOG, B_NODE_USETEX, "Use Nodes", xco+5,yco,90,19, &tx->use_nodes, 0.0f, 0.0f, 0, 0, "");
+ xco+=80;
+ }
+ }
+ }
+
+ UI_view2d_totRect_set(&ar->v2d, xco+XIC+100, (int)(ar->v2d.tot.ymax-ar->v2d.tot.ymin));
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+}
+
+
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
new file mode 100644
index 00000000000..b73f57f935f
--- /dev/null
+++ b/source/blender/editors/space_node/node_intern.h
@@ -0,0 +1,119 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_NODE_INTERN_H
+#define ED_NODE_INTERN_H
+
+/* internal exports only */
+
+struct ARegion;
+struct View2D;
+struct bContext;
+struct wmWindowManager;
+
+/* defines */
+
+#define NODE_SELECT_MOUSE 1
+
+/* border select defines XXX these seem to be hardcode values still in border select invoke, check */
+#define NODE_EXTEND 1
+#define NODE_EXCLUSIVE 3
+
+/* node_header.c */
+void node_header_buttons(const bContext *C, ARegion *ar);
+
+/* node_draw.c */
+void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d);
+
+/* node_ops.c */
+void node_operatortypes(void);
+void node_keymap(wmWindowManager *wm);
+
+/* node_select.c */
+void NODE_OT_select(struct wmOperatorType *ot);
+void NODE_OT_select_extend(struct wmOperatorType *ot);
+void NODE_OT_visibility_toggle(struct wmOperatorType *ot);
+void NODE_OT_view_all(struct wmOperatorType *ot);
+void NODE_OT_select_border(struct wmOperatorType *ot);
+
+/* drawnode.c */
+void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link);
+void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int th_col2, int do_shaded);
+int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol);
+void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode);
+
+/* node_edit.c */
+void snode_handle_recalc(bContext *C, SpaceNode *snode);
+bNode *next_node(bNodeTree *ntree);
+bNode *node_add_node(SpaceNode *snode, Scene *scene, int type, float locx, float locy);
+void snode_set_context(SpaceNode *snode, Scene *scene);
+void snode_make_group_editable(SpaceNode *snode, bNode *gnode);
+void snode_home(ScrArea *sa, ARegion *ar, SpaceNode *snode);
+void node_set_active(SpaceNode *snode, bNode *node);
+void node_deselectall(SpaceNode *snode, int swap);
+void node_shader_default(Material *ma);
+void node_composit_default(Scene *sce);
+void node_texture_default(Tex *tx);
+void snode_composite_job(const struct bContext *C, ScrArea *sa);
+bNode *snode_get_editgroup(SpaceNode *snode);
+void snode_autoconnect(SpaceNode *snode, bNode *node_to, int flag);
+
+void NODE_OT_link(struct wmOperatorType *ot);
+void NODE_OT_delete(struct wmOperatorType *ot);
+void NODE_OT_resize(struct wmOperatorType *ot);
+void NODE_OT_links_cut(struct wmOperatorType *ot);
+
+// XXXXXX
+
+// XXX from BSE_node.h
+#define HIDDEN_RAD 15.0f
+#define BASIS_RAD 8.0f
+#define NODE_DYS 10
+#define NODE_DY 20
+#define NODE_SOCKSIZE 5
+
+// XXX button events (butspace)
+enum {
+ B_NOP = 0,
+ B_REDR = 1,
+ B_NODE_USEMAT,
+ B_NODE_USESCENE,
+ B_NODE_USETEX,
+ B_TEXBROWSE,
+ B_TEXALONE,
+ B_TEXLOCAL,
+ B_TEXDELETE,
+ B_TEXPRV,
+ B_AUTOTEXNAME,
+ B_KEEPDATA,
+ B_NODE_EXEC,
+ B_MATPRV,
+ B_NODE_LOADIMAGE,
+ B_NODE_SETIMAGE,
+} eActHeader_ButEvents;
+
+#endif /* ED_NODE_INTERN_H */
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
new file mode 100644
index 00000000000..7a1cc24fa58
--- /dev/null
+++ b/source/blender/editors/space_node/node_ops.c
@@ -0,0 +1,84 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation, Nathan Letwory
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "DNA_node_types.h"
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+#include "BKE_node.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "BIF_transform.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "node_intern.h"
+
+void node_operatortypes(void)
+{
+ WM_operatortype_append(NODE_OT_select);
+ WM_operatortype_append(NODE_OT_select_extend);
+ WM_operatortype_append(NODE_OT_visibility_toggle);
+ WM_operatortype_append(NODE_OT_view_all);
+ WM_operatortype_append(NODE_OT_select_border);
+ WM_operatortype_append(NODE_OT_delete);
+ WM_operatortype_append(NODE_OT_link);
+ WM_operatortype_append(NODE_OT_resize);
+ WM_operatortype_append(NODE_OT_links_cut);
+}
+
+void node_keymap(struct wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "Node", SPACE_NODE, 0);
+
+ /* mouse select in nodes used to be both keys, it's UI elements... */
+ RNA_enum_set(WM_keymap_add_item(keymap, "NODE_OT_select", ACTIONMOUSE, KM_PRESS, 0, 0)->ptr, "select_type", NODE_SELECT_MOUSE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "NODE_OT_select", SELECTMOUSE, KM_PRESS, 0, 0)->ptr, "select_type", NODE_SELECT_MOUSE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "NODE_OT_select_extend", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "select_type", NODE_SELECT_MOUSE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "NODE_OT_select_extend", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "select_type", NODE_SELECT_MOUSE);
+
+ WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "NODE_OT_resize", LEFTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "NODE_OT_visibility_toggle", LEFTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "NODE_OT_links_cut", LEFTMOUSE, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "NODE_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "NODE_OT_select_border", BKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "NODE_OT_delete", XKEY, KM_PRESS, 0, 0);
+
+ transform_keymap_for_space(wm, keymap, SPACE_NODE);
+}
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
new file mode 100644
index 00000000000..3c37793e8d6
--- /dev/null
+++ b/source/blender/editors/space_node/node_select.c
@@ -0,0 +1,293 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation, Nathan Letwory
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+
+#include "DNA_node_types.h"
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+#include "BKE_node.h"
+#include "BKE_global.h"
+
+#include "BLI_rect.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_view2d.h"
+
+#include "node_intern.h"
+
+static void node_mouse_select(SpaceNode *snode, ARegion *ar, short *mval, short extend)
+{
+ bNode *node;
+ float mx, my;
+
+ mx= (float)mval[0];
+ my= (float)mval[1];
+
+ UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &mx, &my);
+
+ for(next_node(snode->edittree); (node=next_node(NULL));) {
+
+ /* first check for the headers or scaling widget */
+ /* XXX if(node->flag & NODE_HIDDEN) {
+ if(do_header_hidden_node(snode, node, mx, my))
+ return 1;
+ }
+ else {
+ if(do_header_node(snode, node, mx, my))
+ return 1;
+ }*/
+
+ /* node body */
+ if(BLI_in_rctf(&node->totr, mx, my))
+ break;
+ }
+ if(node) {
+ if((extend & KM_SHIFT)==0)
+ node_deselectall(snode, 0);
+
+ if(extend & KM_SHIFT) {
+ if(node->flag & SELECT)
+ node->flag &= ~SELECT;
+ else
+ node->flag |= SELECT;
+ }
+ else
+ node->flag |= SELECT;
+
+ node_set_active(snode, node);
+
+ /* viewer linking */
+ if(extend & KM_CTRL)
+ ;// node_link_viewer(snode, node);
+
+ //std_rmouse_transform(node_transform_ext); /* does undo push for select */
+ }
+}
+
+static int node_select_exec(bContext *C, wmOperator *op)
+{
+ // XXX wmWindow *window= CTX_wm_window(C);
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+ int select_type;
+ short mval[2];
+ short extend;
+
+ select_type = RNA_enum_get(op->ptr, "select_type");
+
+ switch (select_type) {
+ case NODE_SELECT_MOUSE:
+ mval[0] = RNA_int_get(op->ptr, "mouse_x");
+ mval[1] = RNA_int_get(op->ptr, "mouse_y");
+ extend = RNA_boolean_get(op->ptr, "extend");
+ node_mouse_select(snode, ar, mval, extend);
+ break;
+ }
+
+ /* need refresh/a notifier vs compo notifier */
+ // XXX WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); /* Do we need to pass the scene? */
+ ED_region_tag_redraw(ar);
+
+ /* allow tweak event to work too */
+ return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
+}
+
+static int node_select_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ /* execute the events */
+ switch (event->type) {
+ case MOUSEMOVE:
+ printf("%d %d\n", event->x, event->y);
+ break;
+ case SELECTMOUSE:
+ //if (event->val==0) {
+ /* calculate overall delta mouse-movement for redo */
+ printf("done translating\n");
+ //WM_cursor_restore(CTX_wm_window(C));
+
+ return OPERATOR_FINISHED;
+ //}
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int node_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ short mval[2];
+
+ mval[0]= event->x - ar->winrct.xmin;
+ mval[1]= event->y - ar->winrct.ymin;
+
+ RNA_int_set(op->ptr, "mouse_x", mval[0]);
+ RNA_int_set(op->ptr, "mouse_y", mval[1]);
+
+ return node_select_exec(C,op);
+}
+
+static int node_extend_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ RNA_boolean_set(op->ptr, "extend", KM_SHIFT);
+
+ return node_select_invoke(C, op, event);
+}
+
+/* operators */
+
+static EnumPropertyItem prop_select_items[] = {
+ {NODE_SELECT_MOUSE, "NORMAL", "Normal Select", "Select using the mouse"},
+ {0, NULL, NULL, NULL}};
+
+void NODE_OT_select_extend(wmOperatorType *ot)
+{
+ // XXX - Todo - This should just be a toggle option for NODE_OT_select not its own op
+ /* identifiers */
+ ot->name= "Activate/Select (Shift)";
+ ot->idname= "NODE_OT_select_extend";
+
+ /* api callbacks */
+ ot->invoke= node_extend_select_invoke;
+ ot->poll= ED_operator_node_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "select_type", prop_select_items, 0, "Select Type", "");
+
+ RNA_def_int(ot->srna, "mouse_x", 0, INT_MIN, INT_MAX, "Mouse X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "mouse_y", 0, INT_MIN, INT_MAX, "Mouse Y", "", INT_MIN, INT_MAX);
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "");
+}
+
+void NODE_OT_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Activate/Select";
+ ot->idname= "NODE_OT_select";
+
+ /* api callbacks */
+ ot->invoke= node_select_invoke;
+ ot->poll= ED_operator_node_active;
+ ot->modal= node_select_modal;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "select_type", prop_select_items, 0, "Select Type", "");
+
+ RNA_def_int(ot->srna, "mouse_x", 0, INT_MIN, INT_MAX, "Mouse X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "mouse_y", 0, INT_MIN, INT_MAX, "Mouse Y", "", INT_MIN, INT_MAX);
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "");
+}
+
+/* ****** Border Select ****** */
+
+static EnumPropertyItem prop_select_types[] = {
+ {NODE_EXCLUSIVE, "EXCLUSIVE", "Exclusive", ""}, /* right mouse */
+ {NODE_EXTEND, "EXTEND", "Extend", ""}, /* left mouse */
+ {0, NULL, NULL, NULL}
+};
+
+static int node_borderselect_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+ bNode *node;
+ rcti rect;
+ rctf rectf;
+ short val;
+
+ val= RNA_int_get(op->ptr, "event_type");
+
+ rect.xmin= RNA_int_get(op->ptr, "xmin");
+ rect.ymin= RNA_int_get(op->ptr, "ymin");
+ UI_view2d_region_to_view(&ar->v2d, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
+
+ rect.xmax= RNA_int_get(op->ptr, "xmax");
+ rect.ymax= RNA_int_get(op->ptr, "ymax");
+ UI_view2d_region_to_view(&ar->v2d, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
+
+ if (snode->edittree == NULL) // XXX should this be in poll()? - campbell
+ return OPERATOR_FINISHED;
+
+ for(node= snode->edittree->nodes.first; node; node= node->next) {
+ if(BLI_isect_rctf(&rectf, &node->totr, NULL)) {
+ if(val==NODE_EXTEND)
+ node->flag |= SELECT;
+ else
+ node->flag &= ~SELECT;
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); /* Do we need to pass the scene? */
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_select_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Border Select";
+ ot->idname= "NODE_OT_select_border";
+
+ /* api callbacks */
+ ot->invoke= WM_border_select_invoke;
+ ot->exec= node_borderselect_exec;
+ ot->modal= WM_border_select_modal;
+
+ ot->poll= ED_operator_node_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* rna */
+ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+
+ RNA_def_enum(ot->srna, "type", prop_select_types, 0, "Type", "");
+}
diff --git a/source/blender/editors/space_node/node_state.c b/source/blender/editors/space_node/node_state.c
new file mode 100644
index 00000000000..f05a24ef05a
--- /dev/null
+++ b/source/blender/editors/space_node/node_state.c
@@ -0,0 +1,208 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation, Nathan Letwory
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+
+#include "DNA_node_types.h"
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+#include "BKE_node.h"
+#include "BKE_global.h"
+
+#include "BLI_rect.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_view2d.h"
+
+#include "node_intern.h"
+
+
+static int do_header_node(SpaceNode *snode, bNode *node, float mx, float my)
+{
+ rctf totr= node->totr;
+
+ totr.ymin= totr.ymax-20.0f;
+
+ totr.xmax= totr.xmin+15.0f;
+ if(BLI_in_rctf(&totr, mx, my)) {
+ node->flag |= NODE_HIDDEN;
+ return 1;
+ }
+
+ totr.xmax= node->totr.xmax;
+ totr.xmin= totr.xmax-18.0f;
+ if(node->typeinfo->flag & NODE_PREVIEW) {
+ if(BLI_in_rctf(&totr, mx, my)) {
+ node->flag ^= NODE_PREVIEW;
+ return 1;
+ }
+ totr.xmin-=18.0f;
+ }
+ if(node->type == NODE_GROUP) {
+ if(BLI_in_rctf(&totr, mx, my)) {
+ snode_make_group_editable(snode, node);
+ return 1;
+ }
+ totr.xmin-=18.0f;
+ }
+ if(node->typeinfo->flag & NODE_OPTIONS) {
+ if(BLI_in_rctf(&totr, mx, my)) {
+ node->flag ^= NODE_OPTIONS;
+ return 1;
+ }
+ totr.xmin-=18.0f;
+ }
+ /* hide unused sockets */
+ if(BLI_in_rctf(&totr, mx, my)) {
+ // XXX node_hide_unhide_sockets(snode, node);
+ }
+
+ return 0;
+}
+
+static int do_header_hidden_node(SpaceNode *snode, bNode *node, float mx, float my)
+{
+ rctf totr= node->totr;
+
+ totr.xmax= totr.xmin+15.0f;
+ if(BLI_in_rctf(&totr, mx, my)) {
+ node->flag &= ~NODE_HIDDEN;
+ return 1;
+ }
+ return 0;
+}
+
+static int node_toggle_visibility(SpaceNode *snode, ARegion *ar, short *mval)
+{
+ bNode *node;
+ float mx, my;
+
+ mx= (float)mval[0];
+ my= (float)mval[1];
+
+ UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &mx, &my);
+
+ for(next_node(snode->edittree); (node=next_node(NULL));) {
+ if(node->flag & NODE_HIDDEN) {
+ if(do_header_hidden_node(snode, node, mx, my)) {
+ ED_region_tag_redraw(ar);
+ return 1;
+ }
+ }
+ else {
+ if(do_header_node(snode, node, mx, my)) {
+ ED_region_tag_redraw(ar);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int node_toggle_visibility_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+ ARegion *ar= CTX_wm_region(C);
+ short mval[2];
+
+ mval[0] = RNA_int_get(op->ptr, "mouse_x");
+ mval[1] = RNA_int_get(op->ptr, "mouse_y");
+ if(node_toggle_visibility(snode, ar, mval))
+ return OPERATOR_FINISHED;
+ else
+ return OPERATOR_PASS_THROUGH;
+}
+
+static int node_toggle_visibility_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ short mval[2];
+
+ mval[0]= event->x - ar->winrct.xmin;
+ mval[1]= event->y - ar->winrct.ymin;
+
+ RNA_int_set(op->ptr, "mouse_x", mval[0]);
+ RNA_int_set(op->ptr, "mouse_y", mval[1]);
+
+ return node_toggle_visibility_exec(C,op);
+}
+
+void NODE_OT_visibility_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Toggle Visibility";
+ ot->idname= "NODE_OT_visibility_toggle";
+
+ /* api callbacks */
+ ot->invoke= node_toggle_visibility_invoke;
+ ot->poll= ED_operator_node_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "mouse_x", 0, INT_MIN, INT_MAX, "Mouse X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "mouse_y", 0, INT_MIN, INT_MAX, "Mouse Y", "", INT_MIN, INT_MAX);
+}
+
+static int node_fit_all_exec(bContext *C, wmOperator *op)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= CTX_wm_region(C);
+ SpaceNode *snode= (SpaceNode *)CTX_wm_space_data(C);
+ snode_home(sa, ar, snode);
+ ED_region_tag_redraw(ar);
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_view_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Fit All";
+ ot->idname= "NODE_OT_view_all";
+
+ /* api callbacks */
+ ot->exec= node_fit_all_exec;
+ ot->poll= ED_operator_node_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
new file mode 100644
index 00000000000..493ef6954b5
--- /dev/null
+++ b/source/blender/editors/space_node/space_node.c
@@ -0,0 +1,353 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_previewrender.h"
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "RNA_access.h"
+
+#include "node_intern.h" // own include
+
+/* ******************** default callbacks for node space ***************** */
+
+static SpaceLink *node_new(const bContext *C)
+{
+ ARegion *ar;
+ SpaceNode *snode;
+
+ snode= MEM_callocN(sizeof(SpaceNode), "initnode");
+ snode->spacetype= SPACE_NODE;
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for node");
+
+ BLI_addtail(&snode->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_BOTTOM;
+
+ /* channels */
+ ar= MEM_callocN(sizeof(ARegion), "nodetree area for node");
+
+ BLI_addtail(&snode->regionbase, ar);
+ ar->regiontype= RGN_TYPE_CHANNELS;
+ ar->alignment= RGN_ALIGN_LEFT;
+
+ //ar->v2d.scroll = (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM);
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for node");
+
+ BLI_addtail(&snode->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+
+ ar->v2d.tot.xmin= -10.0f;
+ ar->v2d.tot.ymin= -10.0f;
+ ar->v2d.tot.xmax= 512.0f;
+ ar->v2d.tot.ymax= 512.0f;
+
+ ar->v2d.cur.xmin= 0.0f;
+ ar->v2d.cur.ymin= 0.0f;
+ ar->v2d.cur.xmax= 512.0f;
+ ar->v2d.cur.ymax= 512.0f;
+
+ ar->v2d.min[0]= 1.0f;
+ ar->v2d.min[1]= 1.0f;
+
+ ar->v2d.max[0]= 32000.0f;
+ ar->v2d.max[1]= 32000.0f;
+
+ ar->v2d.minzoom= 0.5f;
+ ar->v2d.maxzoom= 1.21f;
+
+ ar->v2d.scroll= (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM);
+ ar->v2d.keepzoom= V2D_KEEPZOOM|V2D_KEEPASPECT;
+ ar->v2d.keeptot= 0;
+
+ return (SpaceLink *)snode;
+}
+
+/* not spacelink itself */
+static void node_free(SpaceLink *sl)
+{
+// SpaceNode *snode= (SpaceNode*) sl;
+
+// XXX if(snode->gpd) free_gpencil_data(snode->gpd);
+}
+
+
+/* spacetype; init callback */
+static void node_init(struct wmWindowManager *wm, ScrArea *sa)
+{
+
+}
+
+static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
+{
+
+ /* preview renders */
+ switch(wmn->category) {
+ case NC_SCENE:
+ if(wmn->data==ND_NODES)
+ ED_area_tag_refresh(sa);
+ break;
+ case NC_WM:
+ if(wmn->data==ND_FILEREAD)
+ ED_area_tag_refresh(sa);
+ break;
+
+ case NC_MATERIAL:
+ /* future: add ID check? */
+ if(wmn->data==ND_SHADING)
+ ED_area_tag_refresh(sa);
+ break;
+ }
+}
+
+static void node_area_refresh(const struct bContext *C, struct ScrArea *sa)
+{
+ /* default now: refresh node is starting preview */
+ SpaceNode *snode= sa->spacedata.first;
+
+ if(snode->nodetree) {
+ if(snode->treetype==NTREE_SHADER) {
+ Material *ma= (Material *)snode->id;
+ if(ma->use_nodes)
+ ED_preview_shader_job(C, sa, snode->id, 100, 100);
+ }
+ else if(snode->treetype==NTREE_COMPOSIT) {
+ Scene *scene= (Scene *)snode->id;
+ if(scene->use_nodes)
+ snode_composite_job(C, sa);
+ }
+ }
+}
+
+static SpaceLink *node_duplicate(SpaceLink *sl)
+{
+ SpaceNode *snoden= MEM_dupallocN(sl);
+
+ /* clear or remove stuff from old */
+ snoden->nodetree= NULL;
+// XXX snoden->gpd= gpencil_data_duplicate(snode->gpd);
+
+ return (SpaceLink *)snoden;
+}
+
+static void node_channel_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+}
+
+static void node_channel_area_draw(const bContext *C, ARegion *ar)
+{
+ View2D *v2d= &ar->v2d;
+ View2DScrollers *scrollers;
+ float col[3];
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_SHADE2, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ UI_view2d_view_ortho(C, v2d);
+
+ /* data... */
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+}
+
+/* Initialise main area, setting handlers. */
+static void node_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "Node", SPACE_NODE, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+static void node_main_area_draw(const bContext *C, ARegion *ar)
+{
+ View2D *v2d= &ar->v2d;
+
+ drawnodespace(C, ar, v2d);
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void node_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+}
+
+static void node_header_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ /* clear */
+ if(ED_screen_area_active(C))
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ else
+ UI_GetThemeColor3fv(TH_HEADERDESEL, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ node_header_buttons(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+/* used for header + main area */
+static void node_region_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_MATERIAL:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+}
+
+static int node_context(const bContext *C, const char *member, bContextDataResult *result)
+{
+ SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
+
+ if(CTX_data_equals(member, "selected_nodes")) {
+ bNode *node;
+
+ for(next_node(snode->edittree); (node=next_node(NULL));) {
+ if(node->flag & SELECT) {
+ CTX_data_list_add(result, &snode->edittree->id, &RNA_Node, node);
+ }
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+/* only called once, from space/spacetypes.c */
+void ED_spacetype_node(void)
+{
+ SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype node");
+ ARegionType *art;
+
+ st->spaceid= SPACE_NODE;
+
+ st->new= node_new;
+ st->free= node_free;
+ st->init= node_init;
+ st->duplicate= node_duplicate;
+ st->operatortypes= node_operatortypes;
+ st->keymap= node_keymap;
+ st->listener= node_area_listener;
+ st->refresh= node_area_refresh;
+ st->context= node_context;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype node region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init= node_main_area_init;
+ art->draw= node_main_area_draw;
+ art->listener= node_region_listener;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype node region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
+ art->listener= node_region_listener;
+ art->init= node_header_area_init;
+ art->draw= node_header_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: channels */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype node region");
+ art->regionid = RGN_TYPE_CHANNELS;
+ art->minsizex= 100;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
+
+ art->init= node_channel_area_init;
+ art->draw= node_channel_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+
+ BKE_spacetype_register(st);
+}
+
diff --git a/source/blender/editors/space_outliner/Makefile b/source/blender/editors/space_outliner/Makefile
new file mode 100644
index 00000000000..19d40a4a31e
--- /dev/null
+++ b/source/blender/editors/space_outliner/Makefile
@@ -0,0 +1,54 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_outliner
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/space_outliner/SConscript b/source/blender/editors/space_outliner/SConscript
new file mode 100644
index 00000000000..a7f487a4149
--- /dev/null
+++ b/source/blender/editors/space_outliner/SConscript
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc ../../makesrna'
+incs += ' #/extern/glew/include'
+
+env.BlenderLib ( 'bf_editors_space_outliner', sources, Split(incs), [], libtype=['core'], priority=[60] )
diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c
new file mode 100644
index 00000000000..6394e38c6e7
--- /dev/null
+++ b/source/blender/editors/space_outliner/outliner.c
@@ -0,0 +1,4475 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_image_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_group_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_nla_types.h"
+#include "DNA_object_types.h"
+#include "DNA_outliner_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_text_types.h"
+#include "DNA_world_types.h"
+#include "DNA_sequence_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_constraint.h"
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_group.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
+#include "BKE_screen.h"
+#include "BKE_scene.h"
+#include "BKE_sequence.h"
+#include "BKE_utildefines.h"
+
+#include "ED_screen.h"
+#include "ED_util.h"
+#include "ED_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "RNA_access.h"
+
+#include "ED_armature.h"
+#include "ED_object.h"
+#include "ED_screen.h"
+
+#include "outliner_intern.h"
+
+#include "PIL_time.h"
+
+
+#define OL_H 19
+#define OL_X 18
+
+#define OL_TOG_RESTRICT_VIEWX 54
+#define OL_TOG_RESTRICT_SELECTX 36
+#define OL_TOG_RESTRICT_RENDERX 18
+
+#define OL_TOGW OL_TOG_RESTRICT_VIEWX
+
+#define OL_RNA_COLX 300
+#define OL_RNA_COL_SIZEX 150
+#define OL_RNA_COL_SPACEX 50
+
+#define TS_CHUNK 128
+
+#define TREESTORE(a) ((a)?soops->treestore->data+(a)->store_index:NULL)
+
+/* ************* XXX **************** */
+
+static void BIF_undo_push() {}
+static void BIF_preview_changed() {}
+static void error() {}
+static int pupmenu() {return 0;}
+
+/* ********************************** */
+
+
+/* ******************** PROTOTYPES ***************** */
+static void outliner_draw_tree_element(Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int startx, int *starty);
+static void outliner_do_object_operation(Scene *scene, SpaceOops *soops, ListBase *lb,
+ void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *));
+
+
+/* ******************** PERSISTANT DATA ***************** */
+
+static void outliner_storage_cleanup(SpaceOops *soops)
+{
+ TreeStore *ts= soops->treestore;
+
+ if(ts) {
+ TreeStoreElem *tselem;
+ int a, unused= 0;
+
+ /* each element used once, for ID blocks with more users to have each a treestore */
+ for(a=0, tselem= ts->data; a<ts->usedelem; a++, tselem++) tselem->used= 0;
+
+ /* cleanup only after reading file or undo step, and always for
+ * RNA datablocks view in order to save memory */
+ if(soops->storeflag & SO_TREESTORE_CLEANUP) {
+
+ for(a=0, tselem= ts->data; a<ts->usedelem; a++, tselem++) {
+ if(tselem->id==NULL) unused++;
+ }
+
+ if(unused) {
+ if(ts->usedelem == unused) {
+ MEM_freeN(ts->data);
+ ts->data= NULL;
+ ts->usedelem= ts->totelem= 0;
+ }
+ else {
+ TreeStoreElem *tsnewar, *tsnew;
+
+ tsnew=tsnewar= MEM_mallocN((ts->usedelem-unused)*sizeof(TreeStoreElem), "new tselem");
+ for(a=0, tselem= ts->data; a<ts->usedelem; a++, tselem++) {
+ if(tselem->id) {
+ *tsnew= *tselem;
+ tsnew++;
+ }
+ }
+ MEM_freeN(ts->data);
+ ts->data= tsnewar;
+ ts->usedelem-= unused;
+ ts->totelem= ts->usedelem;
+ }
+ }
+ }
+ }
+}
+
+static void check_persistant(SpaceOops *soops, TreeElement *te, ID *id, short type, short nr)
+{
+ TreeStore *ts;
+ TreeStoreElem *tselem;
+ int a;
+
+ /* case 1; no TreeStore */
+ if(soops->treestore==NULL) {
+ ts= soops->treestore= MEM_callocN(sizeof(TreeStore), "treestore");
+ }
+ ts= soops->treestore;
+
+ /* check if 'te' is in treestore */
+ tselem= ts->data;
+ for(a=0; a<ts->usedelem; a++, tselem++) {
+ if(tselem->id==id && tselem->used==0) {
+ if((type==0 && tselem->type==0) ||(tselem->type==type && tselem->nr==nr)) {
+ te->store_index= a;
+ tselem->used= 1;
+ return;
+ }
+ }
+ }
+
+ /* add 1 element to treestore */
+ if(ts->usedelem==ts->totelem) {
+ TreeStoreElem *tsnew;
+
+ tsnew= MEM_mallocN((ts->totelem+TS_CHUNK)*sizeof(TreeStoreElem), "treestore data");
+ if(ts->data) {
+ memcpy(tsnew, ts->data, ts->totelem*sizeof(TreeStoreElem));
+ MEM_freeN(ts->data);
+ }
+ ts->data= tsnew;
+ ts->totelem+= TS_CHUNK;
+ }
+
+ tselem= ts->data+ts->usedelem;
+
+ tselem->type= type;
+ if(type) tselem->nr= nr; // we're picky! :)
+ else tselem->nr= 0;
+ tselem->id= id;
+ tselem->used = 0;
+ tselem->flag= TSE_CLOSED;
+ te->store_index= ts->usedelem;
+
+ ts->usedelem++;
+}
+
+/* ******************** TREE MANAGEMENT ****************** */
+
+void outliner_free_tree(ListBase *lb)
+{
+
+ while(lb->first) {
+ TreeElement *te= lb->first;
+
+ outliner_free_tree(&te->subtree);
+ BLI_remlink(lb, te);
+
+ if(te->flag & TE_FREE_NAME) MEM_freeN(te->name);
+ MEM_freeN(te);
+ }
+}
+
+static void outliner_height(SpaceOops *soops, ListBase *lb, int *h)
+{
+ TreeElement *te= lb->first;
+ while(te) {
+ TreeStoreElem *tselem= TREESTORE(te);
+ if((tselem->flag & TSE_CLOSED)==0)
+ outliner_height(soops, &te->subtree, h);
+ (*h) += OL_H;
+ te= te->next;
+ }
+}
+
+#if 0 // XXX this is currently disabled until te->xend is set correctly
+static void outliner_width(SpaceOops *soops, ListBase *lb, int *w)
+{
+ TreeElement *te= lb->first;
+ while(te) {
+// TreeStoreElem *tselem= TREESTORE(te);
+
+ // XXX fixme... te->xend is not set yet
+ if(tselem->flag & TSE_CLOSED) {
+ if (te->xend > *w)
+ *w = te->xend;
+ }
+ outliner_width(soops, &te->subtree, w);
+ te= te->next;
+ }
+}
+#endif
+
+static void outliner_rna_width(SpaceOops *soops, ListBase *lb, int *w, int startx)
+{
+ TreeElement *te= lb->first;
+ while(te) {
+ TreeStoreElem *tselem= TREESTORE(te);
+ // XXX fixme... (currently, we're using a fixed length of 100)!
+ /*if(te->xend) {
+ if(te->xend > *w)
+ *w = te->xend;
+ }*/
+ if(startx+100 > *w)
+ *w = startx+100;
+
+ if((tselem->flag & TSE_CLOSED)==0)
+ outliner_rna_width(soops, &te->subtree, w, startx+OL_X);
+ te= te->next;
+ }
+}
+
+static TreeElement *outliner_find_tree_element(ListBase *lb, int store_index)
+{
+ TreeElement *te= lb->first, *tes;
+ while(te) {
+ if(te->store_index==store_index) return te;
+ tes= outliner_find_tree_element(&te->subtree, store_index);
+ if(tes) return tes;
+ te= te->next;
+ }
+ return NULL;
+}
+
+
+
+static ID *outliner_search_back(SpaceOops *soops, TreeElement *te, short idcode)
+{
+ TreeStoreElem *tselem;
+ te= te->parent;
+
+ while(te) {
+ tselem= TREESTORE(te);
+ if(tselem->type==0 && te->idcode==idcode) return tselem->id;
+ te= te->parent;
+ }
+ return NULL;
+}
+
+struct treesort {
+ TreeElement *te;
+ ID *id;
+ char *name;
+ short idcode;
+};
+
+static int treesort_alpha(const void *v1, const void *v2)
+{
+ const struct treesort *x1= v1, *x2= v2;
+ int comp;
+
+ /* first put objects last (hierarchy) */
+ comp= (x1->idcode==ID_OB);
+ if(x2->idcode==ID_OB) comp+=2;
+
+ if(comp==1) return 1;
+ else if(comp==2) return -1;
+ else if(comp==3) {
+ int comp= strcmp(x1->name, x2->name);
+
+ if( comp>0 ) return 1;
+ else if( comp<0) return -1;
+ return 0;
+ }
+ return 0;
+}
+
+/* this is nice option for later? doesnt look too useful... */
+#if 0
+static int treesort_obtype_alpha(const void *v1, const void *v2)
+{
+ const struct treesort *x1= v1, *x2= v2;
+
+ /* first put objects last (hierarchy) */
+ if(x1->idcode==ID_OB && x2->idcode!=ID_OB) return 1;
+ else if(x2->idcode==ID_OB && x1->idcode!=ID_OB) return -1;
+ else {
+ /* 2nd we check ob type */
+ if(x1->idcode==ID_OB && x2->idcode==ID_OB) {
+ if( ((Object *)x1->id)->type > ((Object *)x2->id)->type) return 1;
+ else if( ((Object *)x1->id)->type > ((Object *)x2->id)->type) return -1;
+ else return 0;
+ }
+ else {
+ int comp= strcmp(x1->name, x2->name);
+
+ if( comp>0 ) return 1;
+ else if( comp<0) return -1;
+ return 0;
+ }
+ }
+}
+#endif
+
+/* sort happens on each subtree individual */
+static void outliner_sort(SpaceOops *soops, ListBase *lb)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+ int totelem=0;
+
+ te= lb->last;
+ if(te==NULL) return;
+ tselem= TREESTORE(te);
+
+ /* sorting rules; only object lists or deformgroups */
+ if( (tselem->type==TSE_DEFGROUP) || (tselem->type==0 && te->idcode==ID_OB)) {
+
+ /* count first */
+ for(te= lb->first; te; te= te->next) totelem++;
+
+ if(totelem>1) {
+ struct treesort *tear= MEM_mallocN(totelem*sizeof(struct treesort), "tree sort array");
+ struct treesort *tp=tear;
+ int skip= 0;
+
+ for(te= lb->first; te; te= te->next, tp++) {
+ tselem= TREESTORE(te);
+ tp->te= te;
+ tp->name= te->name;
+ tp->idcode= te->idcode;
+ if(tselem->type && tselem->type!=TSE_DEFGROUP) tp->idcode= 0; // dont sort this
+ tp->id= tselem->id;
+ }
+ /* keep beginning of list */
+ for(tp= tear, skip=0; skip<totelem; skip++, tp++)
+ if(tp->idcode) break;
+
+ if(skip<totelem)
+ qsort(tear+skip, totelem-skip, sizeof(struct treesort), treesort_alpha);
+
+ lb->first=lb->last= NULL;
+ tp= tear;
+ while(totelem--) {
+ BLI_addtail(lb, tp->te);
+ tp++;
+ }
+ MEM_freeN(tear);
+ }
+ }
+
+ for(te= lb->first; te; te= te->next) {
+ outliner_sort(soops, &te->subtree);
+ }
+}
+
+/* Prototype, see functions below */
+static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *idv,
+ TreeElement *parent, short type, short index);
+
+
+static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, SceneRenderLayer *srl)
+{
+ TreeStoreElem *tselem= TREESTORE(tenla);
+ TreeElement *te;
+
+ te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_COMBINED);
+ te->name= "Combined";
+ te->directdata= &srl->passflag;
+
+ /* save cpu cycles, but we add the first to invoke an open/close triangle */
+ if(tselem->flag & TSE_CLOSED)
+ return;
+
+ te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_Z);
+ te->name= "Z";
+ te->directdata= &srl->passflag;
+
+ te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_VECTOR);
+ te->name= "Vector";
+ te->directdata= &srl->passflag;
+
+ te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_NORMAL);
+ te->name= "Normal";
+ te->directdata= &srl->passflag;
+
+ te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_UV);
+ te->name= "UV";
+ te->directdata= &srl->passflag;
+
+ te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_MIST);
+ te->name= "Mist";
+ te->directdata= &srl->passflag;
+
+ te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_INDEXOB);
+ te->name= "Index Object";
+ te->directdata= &srl->passflag;
+
+ te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_RGBA);
+ te->name= "Color";
+ te->directdata= &srl->passflag;
+
+ te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_DIFFUSE);
+ te->name= "Diffuse";
+ te->directdata= &srl->passflag;
+
+ te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_SPEC);
+ te->name= "Specular";
+ te->directdata= &srl->passflag;
+
+ te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_SHADOW);
+ te->name= "Shadow";
+ te->directdata= &srl->passflag;
+
+ te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_AO);
+ te->name= "AO";
+ te->directdata= &srl->passflag;
+
+ te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_REFLECT);
+ te->name= "Reflection";
+ te->directdata= &srl->passflag;
+
+ te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_REFRACT);
+ te->name= "Refraction";
+ te->directdata= &srl->passflag;
+
+ te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_RADIO);
+ te->name= "Radiosity";
+ te->directdata= &srl->passflag;
+
+}
+
+
+/* special handling of hierarchical non-lib data */
+static void outliner_add_bone(SpaceOops *soops, ListBase *lb, ID *id, Bone *curBone,
+ TreeElement *parent, int *a)
+{
+ TreeElement *te= outliner_add_element(soops, lb, id, parent, TSE_BONE, *a);
+
+ (*a)++;
+ te->name= curBone->name;
+ te->directdata= curBone;
+
+ for(curBone= curBone->childbase.first; curBone; curBone=curBone->next) {
+ outliner_add_bone(soops, &te->subtree, id, curBone, te, a);
+ }
+}
+
+static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *sce, TreeElement *te)
+{
+ SceneRenderLayer *srl;
+ TreeElement *tenla= outliner_add_element(soops, lb, sce, te, TSE_R_LAYER_BASE, 0);
+ int a;
+
+ tenla->name= "RenderLayers";
+ for(a=0, srl= sce->r.layers.first; srl; srl= srl->next, a++) {
+ TreeElement *tenlay= outliner_add_element(soops, &tenla->subtree, sce, te, TSE_R_LAYER, a);
+ tenlay->name= srl->name;
+ tenlay->directdata= &srl->passflag;
+
+ if(srl->light_override)
+ outliner_add_element(soops, &tenlay->subtree, srl->light_override, tenlay, TSE_LINKED_LAMP, 0);
+ if(srl->mat_override)
+ outliner_add_element(soops, &tenlay->subtree, srl->mat_override, tenlay, TSE_LINKED_MAT, 0);
+
+ outliner_add_passes(soops, tenlay, &sce->id, srl);
+ }
+
+ outliner_add_element(soops, lb, sce->world, te, 0, 0);
+
+ if(sce->scriptlink.scripts) {
+ int a= 0;
+ tenla= outliner_add_element(soops, lb, sce, te, TSE_SCRIPT_BASE, 0);
+ tenla->name= "Scripts";
+ for (a=0; a<sce->scriptlink.totscript; a++) {
+ outliner_add_element(soops, &tenla->subtree, sce->scriptlink.scripts[a], tenla, 0, 0);
+ }
+ }
+
+}
+
+static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *idv,
+ TreeElement *parent, short type, short index)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+ ID *id= idv;
+ int a;
+
+ if(ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+ id= ((PointerRNA*)idv)->id.data;
+ if(!id) id= ((PointerRNA*)idv)->data;
+ }
+
+ if(id==NULL) return NULL;
+
+ te= MEM_callocN(sizeof(TreeElement), "tree elem");
+ /* add to the visual tree */
+ BLI_addtail(lb, te);
+ /* add to the storage */
+ check_persistant(soops, te, id, type, index);
+ tselem= TREESTORE(te);
+
+ te->parent= parent;
+ te->index= index; // for data arays
+ if(ELEM3(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP));
+ else if(ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM));
+ else if(type==TSE_ANIM_DATA);
+ else {
+ te->name= id->name+2; // default, can be overridden by Library or non-ID data
+ te->idcode= GS(id->name);
+ }
+
+ if(type==0) {
+
+ /* tuck pointer back in object, to construct hierarchy */
+ if(GS(id->name)==ID_OB) id->newid= (ID *)te;
+
+ /* expand specific data always */
+ switch(GS(id->name)) {
+ case ID_LI:
+ te->name= ((Library *)id)->name;
+ break;
+ case ID_SCE:
+ outliner_add_scene_contents(soops, &te->subtree, (Scene *)id, te);
+ break;
+ case ID_OB:
+ {
+ Object *ob= (Object *)id;
+
+ outliner_add_element(soops, &te->subtree, ob->adt, te, TSE_ANIM_DATA, 0);
+ outliner_add_element(soops, &te->subtree, ob->poselib, te, 0, 0); // XXX FIXME.. add a special type for this
+
+ if(ob->proxy && ob->id.lib==NULL)
+ outliner_add_element(soops, &te->subtree, ob->proxy, te, TSE_PROXY, 0);
+
+ outliner_add_element(soops, &te->subtree, ob->data, te, 0, 0);
+
+ if(ob->pose) {
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+ TreeElement *ten;
+ TreeElement *tenla= outliner_add_element(soops, &te->subtree, ob, te, TSE_POSE_BASE, 0);
+
+ tenla->name= "Pose";
+
+ if(arm->edbo==NULL && (ob->flag & OB_POSEMODE)) { // channels undefined in editmode, but we want the 'tenla' pose icon itself
+ int a= 0, const_index= 1000; /* ensure unique id for bone constraints */
+
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next, a++) {
+ ten= outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_POSE_CHANNEL, a);
+ ten->name= pchan->name;
+ ten->directdata= pchan;
+ pchan->prev= (bPoseChannel *)ten;
+
+ if(pchan->constraints.first) {
+ //Object *target;
+ bConstraint *con;
+ TreeElement *ten1;
+ TreeElement *tenla1= outliner_add_element(soops, &ten->subtree, ob, ten, TSE_CONSTRAINT_BASE, 0);
+ //char *str;
+
+ tenla1->name= "Constraints";
+ for(con= pchan->constraints.first; con; con= con->next, const_index++) {
+ ten1= outliner_add_element(soops, &tenla1->subtree, ob, tenla1, TSE_CONSTRAINT, const_index);
+#if 0 /* disabled as it needs to be reworked for recoded constraints system */
+ target= get_constraint_target(con, &str);
+ if(str && str[0]) ten1->name= str;
+ else if(target) ten1->name= target->id.name+2;
+ else ten1->name= con->name;
+#endif
+ ten1->name= con->name;
+ ten1->directdata= con;
+ /* possible add all other types links? */
+ }
+ }
+ }
+ /* make hierarchy */
+ ten= tenla->subtree.first;
+ while(ten) {
+ TreeElement *nten= ten->next, *par;
+ tselem= TREESTORE(ten);
+ if(tselem->type==TSE_POSE_CHANNEL) {
+ pchan= (bPoseChannel *)ten->directdata;
+ if(pchan->parent) {
+ BLI_remlink(&tenla->subtree, ten);
+ par= (TreeElement *)pchan->parent->prev;
+ BLI_addtail(&par->subtree, ten);
+ ten->parent= par;
+ }
+ }
+ ten= nten;
+ }
+ /* restore prev pointers */
+ pchan= ob->pose->chanbase.first;
+ if(pchan) pchan->prev= NULL;
+ for(; pchan; pchan= pchan->next) {
+ if(pchan->next) pchan->next->prev= pchan;
+ }
+ }
+
+ /* Pose Groups */
+ if(ob->pose->agroups.first) {
+ bActionGroup *agrp;
+ TreeElement *ten;
+ TreeElement *tenla= outliner_add_element(soops, &te->subtree, ob, te, TSE_POSEGRP_BASE, 0);
+ int a= 0;
+
+ tenla->name= "Bone Groups";
+ for (agrp=ob->pose->agroups.first; agrp; agrp=agrp->next, a++) {
+ ten= outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_POSEGRP, a);
+ ten->name= agrp->name;
+ ten->directdata= agrp;
+ }
+ }
+ }
+
+ for(a=0; a<ob->totcol; a++)
+ outliner_add_element(soops, &te->subtree, ob->mat[a], te, 0, a);
+
+ if(ob->constraints.first) {
+ //Object *target;
+ bConstraint *con;
+ TreeElement *ten;
+ TreeElement *tenla= outliner_add_element(soops, &te->subtree, ob, te, TSE_CONSTRAINT_BASE, 0);
+ int a= 0;
+ //char *str;
+
+ tenla->name= "Constraints";
+ for(con= ob->constraints.first; con; con= con->next, a++) {
+ ten= outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_CONSTRAINT, a);
+#if 0 /* disabled due to constraints system targets recode... code here needs review */
+ target= get_constraint_target(con, &str);
+ if(str && str[0]) ten->name= str;
+ else if(target) ten->name= target->id.name+2;
+ else ten->name= con->name;
+#endif
+ ten->name= con->name;
+ ten->directdata= con;
+ /* possible add all other types links? */
+ }
+ }
+
+ if(ob->modifiers.first) {
+ ModifierData *md;
+ TreeElement *temod = outliner_add_element(soops, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0);
+ int index;
+
+ temod->name = "Modifiers";
+ for (index=0,md=ob->modifiers.first; md; index++,md=md->next) {
+ TreeElement *te = outliner_add_element(soops, &temod->subtree, ob, temod, TSE_MODIFIER, index);
+ te->name= md->name;
+ te->directdata = md;
+
+ if (md->type==eModifierType_Lattice) {
+ outliner_add_element(soops, &te->subtree, ((LatticeModifierData*) md)->object, te, TSE_LINKED_OB, 0);
+ } else if (md->type==eModifierType_Curve) {
+ outliner_add_element(soops, &te->subtree, ((CurveModifierData*) md)->object, te, TSE_LINKED_OB, 0);
+ } else if (md->type==eModifierType_Armature) {
+ outliner_add_element(soops, &te->subtree, ((ArmatureModifierData*) md)->object, te, TSE_LINKED_OB, 0);
+ } else if (md->type==eModifierType_Hook) {
+ outliner_add_element(soops, &te->subtree, ((HookModifierData*) md)->object, te, TSE_LINKED_OB, 0);
+ } else if (md->type==eModifierType_ParticleSystem) {
+ TreeElement *ten;
+ ParticleSystem *psys= ((ParticleSystemModifierData*) md)->psys;
+
+ ten = outliner_add_element(soops, &te->subtree, ob, te, TSE_LINKED_PSYS, 0);
+ ten->directdata = psys;
+ ten->name = psys->part->id.name+2;
+ }
+ }
+ }
+ if(ob->defbase.first) {
+ bDeformGroup *defgroup;
+ TreeElement *ten;
+ TreeElement *tenla= outliner_add_element(soops, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0);
+ int a= 0;
+
+ tenla->name= "Vertex Groups";
+ for (defgroup=ob->defbase.first; defgroup; defgroup=defgroup->next, a++) {
+ ten= outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_DEFGROUP, a);
+ ten->name= defgroup->name;
+ ten->directdata= defgroup;
+ }
+ }
+ if(ob->scriptlink.scripts) {
+ TreeElement *tenla= outliner_add_element(soops, &te->subtree, ob, te, TSE_SCRIPT_BASE, 0);
+ int a= 0;
+
+ tenla->name= "Scripts";
+ for (a=0; a<ob->scriptlink.totscript; a++) { /* ** */
+ outliner_add_element(soops, &tenla->subtree, ob->scriptlink.scripts[a], te, 0, 0);
+ }
+ }
+
+ if(ob->dup_group)
+ outliner_add_element(soops, &te->subtree, ob->dup_group, te, 0, 0);
+
+ }
+ break;
+ case ID_ME:
+ {
+ Mesh *me= (Mesh *)id;
+
+ //outliner_add_element(soops, &te->subtree, me->adt, te, TSE_ANIM_DATA, 0);
+
+ outliner_add_element(soops, &te->subtree, me->key, te, 0, 0);
+ for(a=0; a<me->totcol; a++)
+ outliner_add_element(soops, &te->subtree, me->mat[a], te, 0, a);
+ /* could do tfaces with image links, but the images are not grouped nicely.
+ would require going over all tfaces, sort images in use. etc... */
+ }
+ break;
+ case ID_CU:
+ {
+ Curve *cu= (Curve *)id;
+
+ outliner_add_element(soops, &te->subtree, cu->adt, te, TSE_ANIM_DATA, 0);
+
+ for(a=0; a<cu->totcol; a++)
+ outliner_add_element(soops, &te->subtree, cu->mat[a], te, 0, a);
+ }
+ break;
+ case ID_MB:
+ {
+ MetaBall *mb= (MetaBall *)id;
+ for(a=0; a<mb->totcol; a++)
+ outliner_add_element(soops, &te->subtree, mb->mat[a], te, 0, a);
+ }
+ break;
+ case ID_MA:
+ {
+ Material *ma= (Material *)id;
+
+ outliner_add_element(soops, &te->subtree, ma->adt, te, TSE_ANIM_DATA, 0);
+
+ for(a=0; a<MAX_MTEX; a++) {
+ if(ma->mtex[a]) outliner_add_element(soops, &te->subtree, ma->mtex[a]->tex, te, 0, a);
+ }
+ }
+ break;
+ case ID_TE:
+ {
+ Tex *tex= (Tex *)id;
+
+ outliner_add_element(soops, &te->subtree, tex->adt, te, TSE_ANIM_DATA, 0);
+ outliner_add_element(soops, &te->subtree, tex->ima, te, 0, 0);
+ }
+ break;
+ case ID_CA:
+ {
+ Camera *ca= (Camera *)id;
+ outliner_add_element(soops, &te->subtree, ca->adt, te, TSE_ANIM_DATA, 0);
+ }
+ break;
+ case ID_LA:
+ {
+ Lamp *la= (Lamp *)id;
+
+ outliner_add_element(soops, &te->subtree, la->adt, te, TSE_ANIM_DATA, 0);
+
+ for(a=0; a<MAX_MTEX; a++) {
+ if(la->mtex[a]) outliner_add_element(soops, &te->subtree, la->mtex[a]->tex, te, 0, a);
+ }
+ }
+ break;
+ case ID_WO:
+ {
+ World *wrld= (World *)id;
+
+ outliner_add_element(soops, &te->subtree, wrld->adt, te, TSE_ANIM_DATA, 0);
+
+ for(a=0; a<MAX_MTEX; a++) {
+ if(wrld->mtex[a]) outliner_add_element(soops, &te->subtree, wrld->mtex[a]->tex, te, 0, a);
+ }
+ }
+ break;
+ case ID_KE:
+ {
+ Key *key= (Key *)id;
+
+ outliner_add_element(soops, &te->subtree, key->adt, te, TSE_ANIM_DATA, 0);
+ }
+ break;
+ case ID_AC:
+ {
+ // XXX do we want to be exposing the F-Curves here?
+ //bAction *act= (bAction *)id;
+ }
+ break;
+ case ID_AR:
+ {
+ bArmature *arm= (bArmature *)id;
+ int a= 0;
+
+ if(arm->edbo) {
+ EditBone *ebone;
+ TreeElement *ten;
+
+ for (ebone = arm->edbo->first; ebone; ebone=ebone->next, a++) {
+ ten= outliner_add_element(soops, &te->subtree, id, te, TSE_EBONE, a);
+ ten->directdata= ebone;
+ ten->name= ebone->name;
+ ebone->temp= ten;
+ }
+ /* make hierarchy */
+ ten= te->subtree.first;
+ while(ten) {
+ TreeElement *nten= ten->next, *par;
+ ebone= (EditBone *)ten->directdata;
+ if(ebone->parent) {
+ BLI_remlink(&te->subtree, ten);
+ par= ebone->parent->temp;
+ BLI_addtail(&par->subtree, ten);
+ ten->parent= par;
+ }
+ ten= nten;
+ }
+ }
+ else {
+ /* do not extend Armature when we have posemode */
+ tselem= TREESTORE(te->parent);
+ if( GS(tselem->id->name)==ID_OB && ((Object *)tselem->id)->flag & OB_POSEMODE);
+ else {
+ Bone *curBone;
+ for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
+ outliner_add_bone(soops, &te->subtree, id, curBone, te, &a);
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ else if(type==TSE_ANIM_DATA) {
+ AnimData *adt= (AnimData *)idv;
+
+ /* this element's info */
+ te->name= "Animation";
+
+ /* Action */
+ outliner_add_element(soops, &te->subtree, adt->action, te, 0, 0);
+
+ /* Drivers */
+ if (adt->drivers.first) {
+ TreeElement *ted= outliner_add_element(soops, &te->subtree, adt, te, TSE_DRIVER_BASE, 0);
+ ID *lastadded= NULL;
+ FCurve *fcu;
+ DriverTarget *dtar;
+
+ ted->name= "Drivers";
+
+ for (fcu= adt->drivers.first; fcu; fcu= fcu->next) {
+ if (fcu->driver && fcu->driver->targets.first) {
+ for (dtar= fcu->driver->targets.first; dtar; dtar= dtar->next) {
+ if (lastadded != dtar->id) {
+ // XXX this lastadded check is rather lame, and also fails quite badly...
+ outliner_add_element(soops, &ted->subtree, dtar->id, ted, TSE_LINKED_OB, 0);
+ lastadded= dtar->id;
+ }
+ }
+ }
+ }
+ }
+
+ /* NLA Data */
+ if (adt->nla_tracks.first) {
+#if 0
+ TreeElement *tenla= outliner_add_element(soops, &te->subtree, adt, te, TSE_NLA, 0);
+ NlaTrack *nlt;
+ int a= 0;
+
+ tenla->name= "NLA Tracks";
+
+ for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
+ TreeElement *tenlt= outliner_add_element(soops, &te->subtree, nlt, te, TSE_NLA_TRACK, a);
+ bActionStrip *strip;
+ TreeElement *ten;
+ int b= 0;
+
+ for (strip=nlt->strips.first; strip; strip=strip->next, a++) {
+ ten= outliner_add_element(soops, &tenla->subtree, strip->act, tenla, TSE_NLA_ACTION, a);
+ if(ten) ten->directdata= strip;
+ }
+ }
+#endif
+ }
+ }
+ else if(type==TSE_SEQUENCE) {
+ Sequence *seq= (Sequence*) idv;
+ Sequence *p;
+
+ /*
+ * The idcode is a little hack, but the outliner
+ * only check te->idcode if te->type is equal to zero,
+ * so this is "safe".
+ */
+ te->idcode= seq->type;
+ te->directdata= seq;
+
+ if(seq->type<7) {
+ /*
+ * This work like the sequence.
+ * If the sequence have a name (not default name)
+ * show it, in other case put the filename.
+ */
+ if(strcmp(seq->name, "SQ"))
+ te->name= seq->name;
+ else {
+ if((seq->strip) && (seq->strip->stripdata))
+ te->name= seq->strip->stripdata->name;
+ else if((seq->strip) && (seq->strip->tstripdata) && (seq->strip->tstripdata->ibuf))
+ te->name= seq->strip->tstripdata->ibuf->name;
+ else
+ te->name= "SQ None";
+ }
+
+ if(seq->type==SEQ_META) {
+ te->name= "Meta Strip";
+ p= seq->seqbase.first;
+ while(p) {
+ outliner_add_element(soops, &te->subtree, (void*)p, te, TSE_SEQUENCE, index);
+ p= p->next;
+ }
+ }
+ else
+ outliner_add_element(soops, &te->subtree, (void*)seq->strip, te, TSE_SEQ_STRIP, index);
+ }
+ else
+ te->name= "Effect";
+ }
+ else if(type==TSE_SEQ_STRIP) {
+ Strip *strip= (Strip *)idv;
+
+ if(strip->dir)
+ te->name= strip->dir;
+ else
+ te->name= "Strip None";
+ te->directdata= strip;
+ }
+ else if(type==TSE_SEQUENCE_DUP) {
+ Sequence *seq= (Sequence*)idv;
+
+ te->idcode= seq->type;
+ te->directdata= seq;
+ te->name= seq->strip->stripdata->name;
+ }
+ else if(ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+ PointerRNA pptr, propptr, *ptr= (PointerRNA*)idv;
+ PropertyRNA *prop, *iterprop, *nameprop;
+ PropertyType proptype;
+ PropertySubType propsubtype;
+ int a, tot;
+
+ /* we do lazy build, for speed and to avoid infinite recusion */
+
+ if(ptr->data == NULL) {
+ te->name= "(empty)";
+ }
+ else if(type == TSE_RNA_STRUCT) {
+ /* struct */
+ nameprop= RNA_struct_name_property(ptr->type);
+
+ if(nameprop) {
+ te->name= RNA_property_string_get_alloc(ptr, nameprop, NULL, 0);
+ te->flag |= TE_FREE_NAME;
+ }
+ else
+ te->name= (char*)RNA_struct_ui_name(ptr->type);
+
+ iterprop= RNA_struct_iterator_property(ptr->type);
+ tot= RNA_property_collection_length(ptr, iterprop);
+
+ /* auto open these cases */
+ if(!parent || (RNA_property_type(parent->directdata)) == PROP_POINTER)
+ if(!tselem->used)
+ tselem->flag &= ~TSE_CLOSED;
+
+ if(!(tselem->flag & TSE_CLOSED)) {
+ for(a=0; a<tot; a++)
+ outliner_add_element(soops, &te->subtree, (void*)ptr, te, TSE_RNA_PROPERTY, a);
+ }
+ else if(tot)
+ te->flag |= TE_LAZY_CLOSED;
+
+ te->rnaptr= *ptr;
+ }
+ else if(type == TSE_RNA_PROPERTY) {
+ /* property */
+ iterprop= RNA_struct_iterator_property(ptr->type);
+ RNA_property_collection_lookup_int(ptr, iterprop, index, &propptr);
+
+ prop= propptr.data;
+ proptype= RNA_property_type(prop);
+
+ te->name= (char*)RNA_property_ui_name(prop);
+ te->directdata= prop;
+ te->rnaptr= *ptr;
+
+ if(proptype == PROP_POINTER) {
+ pptr= RNA_property_pointer_get(ptr, prop);
+
+ if(pptr.data) {
+ if(!(tselem->flag & TSE_CLOSED))
+ outliner_add_element(soops, &te->subtree, (void*)&pptr, te, TSE_RNA_STRUCT, -1);
+ else
+ te->flag |= TE_LAZY_CLOSED;
+ }
+ }
+ else if(proptype == PROP_COLLECTION) {
+ tot= RNA_property_collection_length(ptr, prop);
+
+ if(!(tselem->flag & TSE_CLOSED)) {
+ for(a=0; a<tot; a++) {
+ RNA_property_collection_lookup_int(ptr, prop, a, &pptr);
+ outliner_add_element(soops, &te->subtree, (void*)&pptr, te, TSE_RNA_STRUCT, -1);
+ }
+ }
+ else if(tot)
+ te->flag |= TE_LAZY_CLOSED;
+ }
+ else if(ELEM3(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
+ tot= RNA_property_array_length(prop);
+
+ if(!(tselem->flag & TSE_CLOSED)) {
+ for(a=0; a<tot; a++)
+ outliner_add_element(soops, &te->subtree, (void*)ptr, te, TSE_RNA_ARRAY_ELEM, a);
+ }
+ else if(tot)
+ te->flag |= TE_LAZY_CLOSED;
+ }
+ }
+ else if(type == TSE_RNA_ARRAY_ELEM) {
+ /* array property element */
+ static char *vectoritem[4]= {" x", " y", " z", " w"};
+ static char *quatitem[4]= {" w", " x", " y", " z"};
+ static char *coloritem[4]= {" r", " g", " b", " a"};
+
+ prop= parent->directdata;
+ proptype= RNA_property_type(prop);
+ propsubtype= RNA_property_subtype(prop);
+ tot= RNA_property_array_length(prop);
+
+ te->directdata= prop;
+ te->rnaptr= *ptr;
+ te->index= index;
+
+ if(tot == 4 && propsubtype == PROP_ROTATION)
+ te->name= quatitem[index];
+ else if(tot <= 4 && (propsubtype == PROP_VECTOR || propsubtype == PROP_ROTATION))
+ te->name= vectoritem[index];
+ else if(tot <= 4 && propsubtype == PROP_COLOR)
+ te->name= coloritem[index];
+ else {
+ te->name= MEM_callocN(sizeof(char)*20, "OutlinerRNAArrayName");
+ sprintf(te->name, " %d", index+1);
+ te->flag |= TE_FREE_NAME;
+ }
+ }
+ }
+
+ return te;
+}
+
+static void outliner_make_hierarchy(SpaceOops *soops, ListBase *lb)
+{
+ TreeElement *te, *ten, *tep;
+ TreeStoreElem *tselem;
+
+ /* build hierarchy */
+ // XXX also, set extents here...
+ te= lb->first;
+ while(te) {
+ ten= te->next;
+ tselem= TREESTORE(te);
+
+ if(tselem->type==0 && te->idcode==ID_OB) {
+ Object *ob= (Object *)tselem->id;
+ if(ob->parent && ob->parent->id.newid) {
+ BLI_remlink(lb, te);
+ tep= (TreeElement *)ob->parent->id.newid;
+ BLI_addtail(&tep->subtree, te);
+ // set correct parent pointers
+ for(te=tep->subtree.first; te; te= te->next) te->parent= tep;
+ }
+ }
+ te= ten;
+ }
+}
+
+/* Helped function to put duplicate sequence in the same tree. */
+int need_add_seq_dup(Sequence *seq)
+{
+ Sequence *p;
+
+ if((!seq->strip) || (!seq->strip->stripdata) || (!seq->strip->stripdata->name))
+ return(1);
+
+ /*
+ * First check backward, if we found a duplicate
+ * sequence before this, don't need it, just return.
+ */
+ p= seq->prev;
+ while(p) {
+ if((!p->strip) || (!p->strip->stripdata) || (!p->strip->stripdata->name)) {
+ p= p->prev;
+ continue;
+ }
+
+ if(!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
+ return(2);
+ p= p->prev;
+ }
+
+ p= seq->next;
+ while(p) {
+ if((!p->strip) || (!p->strip->stripdata) || (!p->strip->stripdata->name)) {
+ p= p->next;
+ continue;
+ }
+
+ if(!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
+ return(0);
+ p= p->next;
+ }
+ return(1);
+}
+
+void add_seq_dup(SpaceOops *soops, Sequence *seq, TreeElement *te, short index)
+{
+ TreeElement *ch;
+ Sequence *p;
+
+ p= seq;
+ while(p) {
+ if((!p->strip) || (!p->strip->stripdata) || (!p->strip->stripdata->name)) {
+ p= p->next;
+ continue;
+ }
+
+ if(!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
+ ch= outliner_add_element(soops, &te->subtree, (void*)p, te, TSE_SEQUENCE, index);
+ p= p->next;
+ }
+}
+
+static void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
+{
+ Base *base;
+ Object *ob;
+ TreeElement *te=NULL, *ten;
+ TreeStoreElem *tselem;
+ int show_opened= (soops->treestore==NULL); /* on first view, we open scenes */
+
+ if(soops->tree.first && (soops->storeflag & SO_TREESTORE_REDRAW))
+ return;
+
+ outliner_free_tree(&soops->tree);
+ outliner_storage_cleanup(soops);
+
+ /* clear ob id.new flags */
+ for(ob= mainvar->object.first; ob; ob= ob->id.next) ob->id.newid= NULL;
+
+ /* options */
+ if(soops->outlinevis == SO_LIBRARIES) {
+ Library *lib;
+
+ for(lib= mainvar->library.first; lib; lib= lib->id.next) {
+ ten= outliner_add_element(soops, &soops->tree, lib, NULL, 0, 0);
+ lib->id.newid= (ID *)ten;
+ }
+ /* make hierarchy */
+ ten= soops->tree.first;
+ while(ten) {
+ TreeElement *nten= ten->next, *par;
+ tselem= TREESTORE(ten);
+ lib= (Library *)tselem->id;
+ if(lib->parent) {
+ BLI_remlink(&soops->tree, ten);
+ par= (TreeElement *)lib->parent->id.newid;
+ BLI_addtail(&par->subtree, ten);
+ ten->parent= par;
+ }
+ ten= nten;
+ }
+ /* restore newid pointers */
+ for(lib= mainvar->library.first; lib; lib= lib->id.next)
+ lib->id.newid= NULL;
+
+ }
+ else if(soops->outlinevis == SO_ALL_SCENES) {
+ Scene *sce;
+ for(sce= mainvar->scene.first; sce; sce= sce->id.next) {
+ te= outliner_add_element(soops, &soops->tree, sce, NULL, 0, 0);
+ tselem= TREESTORE(te);
+ if(sce==scene && show_opened)
+ tselem->flag &= ~TSE_CLOSED;
+
+ for(base= sce->base.first; base; base= base->next) {
+ ten= outliner_add_element(soops, &te->subtree, base->object, te, 0, 0);
+ ten->directdata= base;
+ }
+ outliner_make_hierarchy(soops, &te->subtree);
+ /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */
+ for(base= sce->base.first; base; base= base->next) base->object->id.newid= NULL;
+ }
+ }
+ else if(soops->outlinevis == SO_CUR_SCENE) {
+
+ outliner_add_scene_contents(soops, &soops->tree, scene, NULL);
+
+ for(base= scene->base.first; base; base= base->next) {
+ ten= outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ ten->directdata= base;
+ }
+ outliner_make_hierarchy(soops, &soops->tree);
+ }
+ else if(soops->outlinevis == SO_VISIBLE) {
+ for(base= scene->base.first; base; base= base->next) {
+ if(base->lay & scene->lay)
+ outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ }
+ outliner_make_hierarchy(soops, &soops->tree);
+ }
+ else if(soops->outlinevis == SO_GROUPS) {
+ Group *group;
+ GroupObject *go;
+
+ for(group= mainvar->group.first; group; group= group->id.next) {
+ if(group->id.us) {
+ te= outliner_add_element(soops, &soops->tree, group, NULL, 0, 0);
+ tselem= TREESTORE(te);
+
+ for(go= group->gobject.first; go; go= go->next) {
+ ten= outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0);
+ ten->directdata= NULL; /* eh, why? */
+ }
+ outliner_make_hierarchy(soops, &te->subtree);
+ /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */
+ for(go= group->gobject.first; go; go= go->next) go->ob->id.newid= NULL;
+ }
+ }
+ }
+ else if(soops->outlinevis == SO_SAME_TYPE) {
+ Object *ob= OBACT;
+ if(ob) {
+ for(base= scene->base.first; base; base= base->next) {
+ if(base->object->type==ob->type) {
+ ten= outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ ten->directdata= base;
+ }
+ }
+ outliner_make_hierarchy(soops, &soops->tree);
+ }
+ }
+ else if(soops->outlinevis == SO_SELECTED) {
+ for(base= scene->base.first; base; base= base->next) {
+ if(base->lay & scene->lay) {
+ if(base==BASACT || (base->flag & SELECT)) {
+ ten= outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ ten->directdata= base;
+ }
+ }
+ }
+ outliner_make_hierarchy(soops, &soops->tree);
+ }
+ else if(soops->outlinevis==SO_SEQUENCE) {
+ Sequence *seq;
+ Editing *ed= seq_give_editing(scene, FALSE);
+ int op;
+
+ if(ed==NULL)
+ return;
+
+ seq= ed->seqbasep->first;
+ if(!seq)
+ return;
+
+ while(seq) {
+ op= need_add_seq_dup(seq);
+ if(op==1)
+ ten= outliner_add_element(soops, &soops->tree, (void*)seq, NULL, TSE_SEQUENCE, 0);
+ else if(op==0) {
+ ten= outliner_add_element(soops, &soops->tree, (void*)seq, NULL, TSE_SEQUENCE_DUP, 0);
+ add_seq_dup(soops, seq, ten, 0);
+ }
+ seq= seq->next;
+ }
+ }
+ else if(soops->outlinevis==SO_DATABLOCKS) {
+ PointerRNA mainptr;
+
+ RNA_main_pointer_create(mainvar, &mainptr);
+
+ ten= outliner_add_element(soops, &soops->tree, (void*)&mainptr, NULL, TSE_RNA_STRUCT, -1);
+
+ if(show_opened) {
+ tselem= TREESTORE(ten);
+ tselem->flag &= ~TSE_CLOSED;
+ }
+ }
+ else if(soops->outlinevis==SO_USERDEF) {
+ PointerRNA userdefptr;
+
+ RNA_pointer_create(NULL, &RNA_UserPreferences, &U, &userdefptr);
+
+ ten= outliner_add_element(soops, &soops->tree, (void*)&userdefptr, NULL, TSE_RNA_STRUCT, -1);
+
+ if(show_opened) {
+ tselem= TREESTORE(ten);
+ tselem->flag &= ~TSE_CLOSED;
+ }
+ }
+ else {
+ ten= outliner_add_element(soops, &soops->tree, OBACT, NULL, 0, 0);
+ if(ten) ten->directdata= BASACT;
+ }
+
+ outliner_sort(soops, &soops->tree);
+}
+
+/* **************** INTERACTIVE ************* */
+
+static int outliner_count_levels(SpaceOops *soops, ListBase *lb, int curlevel)
+{
+ TreeElement *te;
+ int level=curlevel, lev;
+
+ for(te= lb->first; te; te= te->next) {
+
+ lev= outliner_count_levels(soops, &te->subtree, curlevel+1);
+ if(lev>level) level= lev;
+ }
+ return level;
+}
+
+static int outliner_has_one_flag(SpaceOops *soops, ListBase *lb, short flag, short curlevel)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+ int level;
+
+ for(te= lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+ if(tselem->flag & flag) return curlevel;
+
+ level= outliner_has_one_flag(soops, &te->subtree, flag, curlevel+1);
+ if(level) return level;
+ }
+ return 0;
+}
+
+static void outliner_set_flag(SpaceOops *soops, ListBase *lb, short flag, short set)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for(te= lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+ if(set==0) tselem->flag &= ~flag;
+ else tselem->flag |= flag;
+ outliner_set_flag(soops, &te->subtree, flag, set);
+ }
+}
+
+void object_toggle_visibility_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
+{
+ Scene *scene= NULL; // XXX
+ Base *base= (Base *)te->directdata;
+
+ if(base==NULL) base= object_in_scene((Object *)tselem->id, scene);
+ if(base) {
+ base->object->restrictflag^=OB_RESTRICT_VIEW;
+ }
+}
+
+void outliner_toggle_visibility(Scene *scene, SpaceOops *soops)
+{
+
+ outliner_do_object_operation(scene, soops, &soops->tree, object_toggle_visibility_cb);
+
+ BIF_undo_push("Outliner toggle selectability");
+
+}
+
+static void object_toggle_selectability_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
+{
+ Scene *scene= NULL; // XXX
+ Base *base= (Base *)te->directdata;
+
+ if(base==NULL) base= object_in_scene((Object *)tselem->id, scene);
+ if(base) {
+ base->object->restrictflag^=OB_RESTRICT_SELECT;
+ }
+}
+
+void outliner_toggle_selectability(Scene *scene, SpaceOops *soops)
+{
+
+ outliner_do_object_operation(scene, soops, &soops->tree, object_toggle_selectability_cb);
+
+ BIF_undo_push("Outliner toggle selectability");
+
+}
+
+void object_toggle_renderability_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
+{
+ Scene *scene= NULL; // XXX
+ Base *base= (Base *)te->directdata;
+
+ if(base==NULL) base= object_in_scene((Object *)tselem->id, scene);
+ if(base) {
+ base->object->restrictflag^=OB_RESTRICT_RENDER;
+ }
+}
+
+void outliner_toggle_renderability(Scene *scene, SpaceOops *soops)
+{
+
+ outliner_do_object_operation(scene, soops, &soops->tree, object_toggle_renderability_cb);
+
+ BIF_undo_push("Outliner toggle renderability");
+
+}
+
+void outliner_toggle_visible(SpaceOops *soops)
+{
+
+ if( outliner_has_one_flag(soops, &soops->tree, TSE_CLOSED, 1))
+ outliner_set_flag(soops, &soops->tree, TSE_CLOSED, 0);
+ else
+ outliner_set_flag(soops, &soops->tree, TSE_CLOSED, 1);
+
+ BIF_undo_push("Outliner toggle visible");
+}
+
+void outliner_toggle_selected(ARegion *ar, SpaceOops *soops)
+{
+
+ if( outliner_has_one_flag(soops, &soops->tree, TSE_SELECTED, 1))
+ outliner_set_flag(soops, &soops->tree, TSE_SELECTED, 0);
+ else
+ outliner_set_flag(soops, &soops->tree, TSE_SELECTED, 1);
+
+ BIF_undo_push("Outliner toggle selected");
+ soops->storeflag |= SO_TREESTORE_REDRAW;
+}
+
+
+static void outliner_openclose_level(SpaceOops *soops, ListBase *lb, int curlevel, int level, int open)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for(te= lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+
+ if(open) {
+ if(curlevel<=level) tselem->flag &= ~TSE_CLOSED;
+ }
+ else {
+ if(curlevel>=level) tselem->flag |= TSE_CLOSED;
+ }
+
+ outliner_openclose_level(soops, &te->subtree, curlevel+1, level, open);
+ }
+}
+
+/* return 1 when levels were opened */
+static int outliner_open_back(SpaceOops *soops, TreeElement *te)
+{
+ TreeStoreElem *tselem;
+ int retval= 0;
+
+ for (te= te->parent; te; te= te->parent) {
+ tselem= TREESTORE(te);
+ if (tselem->flag & TSE_CLOSED) {
+ tselem->flag &= ~TSE_CLOSED;
+ retval= 1;
+ }
+ }
+ return retval;
+}
+
+/* This is not used anywhere at the moment */
+#if 0
+static void outliner_open_reveal(SpaceOops *soops, ListBase *lb, TreeElement *teFind, int *found)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for (te= lb->first; te; te= te->next) {
+ /* check if this tree-element was the one we're seeking */
+ if (te == teFind) {
+ *found= 1;
+ return;
+ }
+
+ /* try to see if sub-tree contains it then */
+ outliner_open_reveal(soops, &te->subtree, teFind, found);
+ if (*found) {
+ tselem= TREESTORE(te);
+ if (tselem->flag & TSE_CLOSED)
+ tselem->flag &= ~TSE_CLOSED;
+ return;
+ }
+ }
+}
+#endif
+
+void outliner_one_level(SpaceOops *soops, int add)
+{
+ int level;
+
+ level= outliner_has_one_flag(soops, &soops->tree, TSE_CLOSED, 1);
+ if(add==1) {
+ if(level) outliner_openclose_level(soops, &soops->tree, 1, level, 1);
+ }
+ else {
+ if(level==0) level= outliner_count_levels(soops, &soops->tree, 0);
+ if(level) outliner_openclose_level(soops, &soops->tree, 1, level-1, 0);
+ }
+
+ BIF_undo_push("Outliner show/hide one level");
+}
+
+void outliner_page_up_down(Scene *scene, ARegion *ar, SpaceOops *soops, int up)
+{
+ int dy= ar->v2d.mask.ymax-ar->v2d.mask.ymin;
+
+ if(up == -1) dy= -dy;
+ ar->v2d.cur.ymin+= dy;
+ ar->v2d.cur.ymax+= dy;
+
+ soops->storeflag |= SO_TREESTORE_REDRAW;
+}
+
+/* **** do clicks on items ******* */
+
+static int tree_element_active_renderlayer(TreeElement *te, TreeStoreElem *tselem, int set)
+{
+ Scene *sce;
+
+ /* paranoia check */
+ if(te->idcode!=ID_SCE)
+ return 0;
+ sce= (Scene *)tselem->id;
+
+ if(set) {
+ sce->r.actlay= tselem->nr;
+ }
+ else {
+ return sce->r.actlay==tselem->nr;
+ }
+ return 0;
+}
+
+static void tree_element_set_active_object(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te)
+{
+ TreeStoreElem *tselem= TREESTORE(te);
+ Scene *sce;
+ Base *base;
+ Object *ob= NULL;
+ int shift= 0; // XXX
+
+ /* if id is not object, we search back */
+ if(te->idcode==ID_OB) ob= (Object *)tselem->id;
+ else {
+ ob= (Object *)outliner_search_back(soops, te, ID_OB);
+ if(ob==OBACT) return;
+ }
+ if(ob==NULL) return;
+
+ sce= (Scene *)outliner_search_back(soops, te, ID_SCE);
+ if(sce && scene != sce) {
+ ED_screen_set_scene(C, sce);
+ }
+
+ /* find associated base in current scene */
+ for(base= FIRSTBASE; base; base= base->next)
+ if(base->object==ob) break;
+ if(base) {
+ if(shift) {
+ /* swap select */
+ if(base->flag & SELECT)
+ ED_base_object_select(base, BA_DESELECT);
+ else
+ ED_base_object_select(base, BA_SELECT);
+ }
+ else {
+ Base *b;
+ /* deleselect all */
+ for(b= FIRSTBASE; b; b= b->next) {
+ b->flag &= ~SELECT;
+ b->object->flag= b->flag;
+ }
+ ED_base_object_select(base, BA_SELECT);
+ }
+ if(C)
+ ED_base_object_activate(C, base); /* adds notifier */
+ }
+
+// XXX if(ob!=obedit) exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR);
+// else countall(); /* exit_editmode calls f() */
+}
+
+static int tree_element_active_material(Scene *scene, SpaceOops *soops, TreeElement *te, int set)
+{
+ TreeElement *tes;
+ Object *ob;
+
+ /* we search for the object parent */
+ ob= (Object *)outliner_search_back(soops, te, ID_OB);
+ if(ob==NULL || ob!=OBACT) return 0; // just paranoia
+
+ /* searching in ob mat array? */
+ tes= te->parent;
+ if(tes->idcode==ID_OB) {
+ if(set) {
+ ob->actcol= te->index+1;
+ ob->colbits |= (1<<te->index); // make ob material active too
+ }
+ else {
+ if(ob->actcol == te->index+1)
+ if(ob->colbits & (1<<te->index)) return 1;
+ }
+ }
+ /* or we search for obdata material */
+ else {
+ if(set) {
+ ob->actcol= te->index+1;
+ ob->colbits &= ~(1<<te->index); // make obdata material active too
+ }
+ else {
+ if(ob->actcol == te->index+1)
+ if( (ob->colbits & (1<<te->index))==0 ) return 1;
+ }
+ }
+ if(set) {
+// XXX extern_set_butspace(F5KEY, 0); // force shading buttons
+ BIF_preview_changed(ID_MA);
+ }
+ return 0;
+}
+
+static int tree_element_active_texture(Scene *scene, SpaceOops *soops, TreeElement *te, int set)
+{
+ TreeElement *tep;
+ TreeStoreElem *tselem, *tselemp;
+ Object *ob=OBACT;
+ SpaceButs *sbuts=NULL;
+
+ if(ob==NULL) return 0; // no active object
+
+ tselem= TREESTORE(te);
+
+ /* find buttons area (note, this is undefined really still, needs recode in blender) */
+ /* XXX removed finding sbuts */
+
+ /* where is texture linked to? */
+ tep= te->parent;
+ tselemp= TREESTORE(tep);
+
+ if(tep->idcode==ID_WO) {
+ World *wrld= (World *)tselemp->id;
+
+ if(set) {
+ if(sbuts) {
+ sbuts->tabo= TAB_SHADING_TEX; // hack from header_buttonswin.c
+ sbuts->texfrom= 1;
+ }
+// XXX extern_set_butspace(F6KEY, 0); // force shading buttons texture
+ wrld->texact= te->index;
+ }
+ else if(tselemp->id == (ID *)(scene->world)) {
+ if(wrld->texact==te->index) return 1;
+ }
+ }
+ else if(tep->idcode==ID_LA) {
+ Lamp *la= (Lamp *)tselemp->id;
+ if(set) {
+ if(sbuts) {
+ sbuts->tabo= TAB_SHADING_TEX; // hack from header_buttonswin.c
+ sbuts->texfrom= 2;
+ }
+// XXX extern_set_butspace(F6KEY, 0); // force shading buttons texture
+ la->texact= te->index;
+ }
+ else {
+ if(tselemp->id == ob->data) {
+ if(la->texact==te->index) return 1;
+ }
+ }
+ }
+ else if(tep->idcode==ID_MA) {
+ Material *ma= (Material *)tselemp->id;
+ if(set) {
+ if(sbuts) {
+ //sbuts->tabo= TAB_SHADING_TEX; // hack from header_buttonswin.c
+ sbuts->texfrom= 0;
+ }
+// XXX extern_set_butspace(F6KEY, 0); // force shading buttons texture
+ ma->texact= (char)te->index;
+
+ /* also set active material */
+ ob->actcol= tep->index+1;
+ }
+ else if(tep->flag & TE_ACTIVE) { // this is active material
+ if(ma->texact==te->index) return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+static int tree_element_active_lamp(Scene *scene, SpaceOops *soops, TreeElement *te, int set)
+{
+ Object *ob;
+
+ /* we search for the object parent */
+ ob= (Object *)outliner_search_back(soops, te, ID_OB);
+ if(ob==NULL || ob!=OBACT) return 0; // just paranoia
+
+ if(set) {
+// XXX extern_set_butspace(F5KEY, 0);
+ BIF_preview_changed(ID_LA);
+ }
+ else return 1;
+
+ return 0;
+}
+
+static int tree_element_active_world(Scene *scene, SpaceOops *soops, TreeElement *te, int set)
+{
+ TreeElement *tep;
+ TreeStoreElem *tselem=NULL;
+ Scene *sce=NULL;
+
+ tep= te->parent;
+ if(tep) {
+ tselem= TREESTORE(tep);
+ sce= (Scene *)tselem->id;
+ }
+
+ if(set) { // make new scene active
+ if(sce && scene != sce) {
+ // XXX ED_screen_set_scene(C, sce);
+ }
+ }
+
+ if(tep==NULL || tselem->id == (ID *)scene) {
+ if(set) {
+// XXX extern_set_butspace(F8KEY, 0);
+ }
+ else {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int tree_element_active_defgroup(Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set)
+{
+ Object *ob;
+
+ /* id in tselem is object */
+ ob= (Object *)tselem->id;
+ if(set) {
+ ob->actdef= te->index+1;
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+ else {
+ if(ob==OBACT)
+ if(ob->actdef== te->index+1) return 1;
+ }
+ return 0;
+}
+
+static int tree_element_active_posegroup(Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set)
+{
+ Object *ob= (Object *)tselem->id;
+
+ if(set) {
+ if (ob->pose) {
+ ob->pose->active_group= te->index+1;
+ }
+ }
+ else {
+ if(ob==OBACT && ob->pose) {
+ if (ob->pose->active_group== te->index+1) return 1;
+ }
+ }
+ return 0;
+}
+
+static int tree_element_active_posechannel(Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set)
+{
+ Object *ob= (Object *)tselem->id;
+ bPoseChannel *pchan= te->directdata;
+
+ if(set) {
+ if(!(pchan->bone->flag & BONE_HIDDEN_P)) {
+
+// XXX if(G.qual & LR_SHIFTKEY) deselectall_posearmature(ob, 2, 0); // 2 = clear active tag
+// else deselectall_posearmature(ob, 0, 0); // 0 = deselect
+ pchan->bone->flag |= BONE_SELECTED|BONE_ACTIVE;
+
+ }
+ }
+ else {
+ if(ob==OBACT && ob->pose) {
+ if (pchan->bone->flag & BONE_SELECTED) return 1;
+ }
+ }
+ return 0;
+}
+
+static int tree_element_active_bone(Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set)
+{
+ bArmature *arm= (bArmature *)tselem->id;
+ Bone *bone= te->directdata;
+
+ if(set) {
+ if(!(bone->flag & BONE_HIDDEN_P)) {
+// XXX if(G.qual & LR_SHIFTKEY) deselectall_posearmature(OBACT, 2, 0); // 2 is clear active tag
+// else deselectall_posearmature(OBACT, 0, 0);
+ bone->flag |= BONE_SELECTED|BONE_ACTIVE;
+
+ }
+ }
+ else {
+ Object *ob= OBACT;
+
+ if(ob && ob->data==arm) {
+ if (bone->flag & BONE_SELECTED) return 1;
+ }
+ }
+ return 0;
+}
+
+
+/* ebones only draw in editmode armature */
+static int tree_element_active_ebone(TreeElement *te, TreeStoreElem *tselem, int set)
+{
+ EditBone *ebone= te->directdata;
+// int shift= 0; // XXX
+
+ if(set) {
+ if(!(ebone->flag & BONE_HIDDEN_A)) {
+
+// XXX if(shift) deselectall_armature(2, 0); // only clear active tag
+// else deselectall_armature(0, 0); // deselect
+
+ ebone->flag |= BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL|BONE_ACTIVE;
+ // flush to parent?
+ if(ebone->parent && (ebone->flag & BONE_CONNECTED)) ebone->parent->flag |= BONE_TIPSEL;
+
+ }
+ }
+ else {
+ if (ebone->flag & BONE_SELECTED) return 1;
+ }
+ return 0;
+}
+
+static int tree_element_active_modifier(TreeElement *te, TreeStoreElem *tselem, int set)
+{
+ if(set) {
+// XXX extern_set_butspace(F9KEY, 0);
+ }
+
+ return 0;
+}
+
+static int tree_element_active_psys(TreeElement *te, TreeStoreElem *tselem, int set)
+{
+ if(set) {
+// Object *ob= (Object *)tselem->id;
+// ParticleSystem *psys= te->directdata;
+
+// XXX PE_change_act_psys(ob, psys);
+// XXX extern_set_butspace(F7KEY, 0);
+ }
+
+ return 0;
+}
+
+static int tree_element_active_constraint(TreeElement *te, TreeStoreElem *tselem, int set)
+{
+ if(set) {
+// XXX extern_set_butspace(F7KEY, 0);
+ }
+
+ return 0;
+}
+
+static int tree_element_active_text(Scene *scene, SpaceOops *soops, TreeElement *te, int set)
+{
+ // XXX removed
+ return 0;
+}
+
+/* generic call for ID data check or make/check active in UI */
+static int tree_element_active(Scene *scene, SpaceOops *soops, TreeElement *te, int set)
+{
+
+ switch(te->idcode) {
+ case ID_MA:
+ return tree_element_active_material(scene, soops, te, set);
+ case ID_WO:
+ return tree_element_active_world(scene, soops, te, set);
+ case ID_LA:
+ return tree_element_active_lamp(scene, soops, te, set);
+ case ID_TE:
+ return tree_element_active_texture(scene, soops, te, set);
+ case ID_TXT:
+ return tree_element_active_text(scene, soops, te, set);
+ }
+ return 0;
+}
+
+static int tree_element_active_pose(TreeElement *te, TreeStoreElem *tselem, int set)
+{
+ Object *ob= (Object *)tselem->id;
+
+ if(set) {
+// XXX if(obedit) exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR);
+// if(ob->flag & OB_POSEMODE) exit_posemode();
+// else enter_posemode();
+ }
+ else {
+ if(ob->flag & OB_POSEMODE) return 1;
+ }
+ return 0;
+}
+
+static int tree_element_active_sequence(TreeElement *te, TreeStoreElem *tselem, int set)
+{
+ Sequence *seq= (Sequence*) te->directdata;
+
+ if(set) {
+// XXX select_single_seq(seq, 1);
+ }
+ else {
+ if(seq->flag & SELECT)
+ return(1);
+ }
+ return(0);
+}
+
+static int tree_element_active_sequence_dup(Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set)
+{
+ Sequence *seq, *p;
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ seq= (Sequence*)te->directdata;
+ if(set==0) {
+ if(seq->flag & SELECT)
+ return(1);
+ return(0);
+ }
+
+// XXX select_single_seq(seq, 1);
+ p= ed->seqbasep->first;
+ while(p) {
+ if((!p->strip) || (!p->strip->stripdata) || (!p->strip->stripdata->name)) {
+ p= p->next;
+ continue;
+ }
+
+// if(!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
+// XXX select_single_seq(p, 0);
+ p= p->next;
+ }
+ return(0);
+}
+
+/* generic call for non-id data to make/check active in UI */
+/* Context can be NULL when set==0 */
+static int tree_element_type_active(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, int set)
+{
+
+ switch(tselem->type) {
+ case TSE_DEFGROUP:
+ return tree_element_active_defgroup(scene, te, tselem, set);
+ case TSE_BONE:
+ return tree_element_active_bone(scene, te, tselem, set);
+ case TSE_EBONE:
+ return tree_element_active_ebone(te, tselem, set);
+ case TSE_MODIFIER:
+ return tree_element_active_modifier(te, tselem, set);
+ case TSE_LINKED_OB:
+ if(set) tree_element_set_active_object(C, scene, soops, te);
+ else if(tselem->id==(ID *)OBACT) return 1;
+ break;
+ case TSE_LINKED_PSYS:
+ return tree_element_active_psys(te, tselem, set);
+ break;
+ case TSE_POSE_BASE:
+ return tree_element_active_pose(te, tselem, set);
+ break;
+ case TSE_POSE_CHANNEL:
+ return tree_element_active_posechannel(scene, te, tselem, set);
+ case TSE_CONSTRAINT:
+ return tree_element_active_constraint(te, tselem, set);
+ case TSE_R_LAYER:
+ return tree_element_active_renderlayer(te, tselem, set);
+ case TSE_POSEGRP:
+ return tree_element_active_posegroup(scene, te, tselem, set);
+ case TSE_SEQUENCE:
+ return tree_element_active_sequence(te, tselem, set);
+ break;
+ case TSE_SEQUENCE_DUP:
+ return tree_element_active_sequence_dup(scene, te, tselem, set);
+ break;
+ }
+ return 0;
+}
+
+static int do_outliner_mouse_event(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, short event, float *mval)
+{
+ int shift= 0, ctrl= 0; // XXX
+
+ if(mval[1]>te->ys && mval[1]<te->ys+OL_H) {
+ TreeStoreElem *tselem= TREESTORE(te);
+ int openclose= 0;
+
+ /* open close icon, three things to check */
+ if(event==RETKEY || event==PADENTER) openclose= 1; // enter opens/closes always
+ else if((te->flag & TE_ICONROW)==0) { // hidden icon, no open/close
+ if( mval[0]>te->xs && mval[0]<te->xs+OL_X) openclose= 1;
+ }
+
+ if(openclose) {
+
+ /* all below close/open? */
+ if(shift) {
+ tselem->flag &= ~TSE_CLOSED;
+ outliner_set_flag(soops, &te->subtree, TSE_CLOSED, !outliner_has_one_flag(soops, &te->subtree, TSE_CLOSED, 1));
+ }
+ else {
+ if(tselem->flag & TSE_CLOSED) tselem->flag &= ~TSE_CLOSED;
+ else tselem->flag |= TSE_CLOSED;
+
+ }
+
+ return 1;
+ }
+ /* name and first icon */
+ else if(mval[0]>te->xs && mval[0]<te->xend) {
+
+ /* activate a name button? */
+ if(event==LEFTMOUSE) {
+
+ if (ctrl) {
+ if(ELEM10(tselem->type, TSE_ANIM_DATA, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE, TSE_SCRIPT_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE, TSE_R_PASS))
+ error("Cannot edit builtin name");
+ else if(ELEM3(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP))
+ error("Cannot edit sequence name");
+ else if(tselem->id->lib) {
+// XXX error_libdata();
+ } else if(te->idcode == ID_LI && te->parent) {
+ error("Cannot edit the path of an indirectly linked library");
+ } else {
+ tselem->flag |= TSE_TEXTBUT;
+ }
+ } else {
+ /* always makes active object */
+ if(tselem->type!=TSE_SEQUENCE && tselem->type!=TSE_SEQ_STRIP && tselem->type!=TSE_SEQUENCE_DUP)
+ tree_element_set_active_object(C, scene, soops, te);
+
+ if(tselem->type==0) { // the lib blocks
+ /* editmode? */
+ if(te->idcode==ID_SCE) {
+ if(scene!=(Scene *)tselem->id) {
+ ED_screen_set_scene(C, (Scene *)tselem->id);
+ }
+ }
+ else if(ELEM5(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) {
+// XXX if(obedit) exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR);
+// else {
+// enter_editmode(EM_WAITCURSOR);
+// extern_set_butspace(F9KEY, 0);
+// }
+ } else { // rest of types
+ tree_element_active(scene, soops, te, 1);
+ }
+
+ }
+ else tree_element_type_active(C, scene, soops, te, tselem, 1);
+ }
+ }
+ else if(event==RIGHTMOUSE) {
+ /* select object that's clicked on and popup context menu */
+ if (!(tselem->flag & TSE_SELECTED)) {
+
+ if ( outliner_has_one_flag(soops, &soops->tree, TSE_SELECTED, 1) )
+ outliner_set_flag(soops, &soops->tree, TSE_SELECTED, 0);
+
+ tselem->flag |= TSE_SELECTED;
+ /* redraw, same as outliner_select function */
+ soops->storeflag |= SO_TREESTORE_REDRAW;
+// XXX screen_swapbuffers();
+ }
+
+ outliner_operation_menu(scene, ar, soops);
+ }
+ return 1;
+ }
+ }
+
+ for(te= te->subtree.first; te; te= te->next) {
+ if(do_outliner_mouse_event(C, scene, ar, soops, te, event, mval)) return 1;
+ }
+ return 0;
+}
+
+/* event can enterkey, then it opens/closes */
+static int outliner_activate_click(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Scene *scene= CTX_data_scene(C);
+ ARegion *ar= CTX_wm_region(C);
+ SpaceOops *soops= (SpaceOops*)CTX_wm_space_data(C);
+ TreeElement *te;
+ float fmval[2];
+
+ UI_view2d_region_to_view(&ar->v2d, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin, fmval, fmval+1);
+
+ for(te= soops->tree.first; te; te= te->next) {
+ if(do_outliner_mouse_event(C, scene, ar, soops, te, event->type, fmval)) break;
+ }
+
+ if(te) {
+ BIF_undo_push("Outliner click event");
+ }
+ else {
+ short selecting= -1;
+ int row;
+
+ /* get row number - 100 here is just a dummy value since we don't need the column */
+ UI_view2d_listview_view_to_cell(&ar->v2d, 1000, OL_H, 0.0f, 0.0f,
+ fmval[0], fmval[1], NULL, &row);
+
+ /* select relevant row */
+ outliner_select(soops, &soops->tree, &row, &selecting);
+
+ // XXX old flag found in old code, do we still use this?
+ //soops->storeflag |= SO_TREESTORE_REDRAW;
+
+ BIF_undo_push("Outliner selection event");
+ }
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_activate_click(wmOperatorType *ot)
+{
+ ot->name= "Activate Click";
+ ot->idname= "OUTLINER_OT_activate_click";
+
+ ot->invoke= outliner_activate_click;
+
+ ot->poll= ED_operator_outliner_active;
+}
+
+
+
+/* recursive helper for function below */
+static void outliner_set_coordinates_element(SpaceOops *soops, TreeElement *te, int startx, int *starty)
+{
+ TreeStoreElem *tselem= TREESTORE(te);
+
+ /* store coord and continue, we need coordinates for elements outside view too */
+ te->xs= (float)startx;
+ te->ys= (float)(*starty);
+ *starty-= OL_H;
+
+ if((tselem->flag & TSE_CLOSED)==0) {
+ TreeElement *ten;
+ for(ten= te->subtree.first; ten; ten= ten->next) {
+ outliner_set_coordinates_element(soops, ten, startx+OL_X, starty);
+ }
+ }
+
+}
+
+/* to retrieve coordinates with redrawing the entire tree */
+static void outliner_set_coordinates(ARegion *ar, SpaceOops *soops)
+{
+ TreeElement *te;
+ int starty= (int)(ar->v2d.tot.ymax)-OL_H;
+ int startx= 0;
+
+ for(te= soops->tree.first; te; te= te->next) {
+ outliner_set_coordinates_element(soops, te, startx, &starty);
+ }
+}
+
+static TreeElement *outliner_find_id(SpaceOops *soops, ListBase *lb, ID *id)
+{
+ TreeElement *te, *tes;
+ TreeStoreElem *tselem;
+
+ for(te= lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+ if(tselem->type==0) {
+ if(tselem->id==id) return te;
+ /* only deeper on scene or object */
+ if( te->idcode==ID_OB || te->idcode==ID_SCE) {
+ tes= outliner_find_id(soops, &te->subtree, id);
+ if(tes) return tes;
+ }
+ }
+ }
+ return NULL;
+}
+
+void outliner_show_active(Scene *scene, ARegion *ar, SpaceOops *so)
+{
+ TreeElement *te;
+ int xdelta, ytop;
+
+ if(OBACT == NULL) return;
+
+ te= outliner_find_id(so, &so->tree, (ID *)OBACT);
+ if(te) {
+ /* make te->ys center of view */
+ ytop= (int)(te->ys + (ar->v2d.mask.ymax-ar->v2d.mask.ymin)/2);
+ if(ytop>0) ytop= 0;
+ ar->v2d.cur.ymax= (float)ytop;
+ ar->v2d.cur.ymin= (float)(ytop-(ar->v2d.mask.ymax-ar->v2d.mask.ymin));
+
+ /* make te->xs ==> te->xend center of view */
+ xdelta = (int)(te->xs - ar->v2d.cur.xmin);
+ ar->v2d.cur.xmin += xdelta;
+ ar->v2d.cur.xmax += xdelta;
+
+ so->storeflag |= SO_TREESTORE_REDRAW;
+ }
+}
+
+void outliner_show_selected(Scene *scene, ARegion *ar, SpaceOops *so)
+{
+ TreeElement *te;
+ int xdelta, ytop;
+
+ te= outliner_find_id(so, &so->tree, (ID *)OBACT);
+ if(te) {
+ /* make te->ys center of view */
+ ytop= (int)(te->ys + (ar->v2d.mask.ymax-ar->v2d.mask.ymin)/2);
+ if(ytop>0) ytop= 0;
+ ar->v2d.cur.ymax= (float)ytop;
+ ar->v2d.cur.ymin= (float)(ytop-(ar->v2d.mask.ymax-ar->v2d.mask.ymin));
+
+ /* make te->xs ==> te->xend center of view */
+ xdelta = (int)(te->xs - ar->v2d.cur.xmin);
+ ar->v2d.cur.xmin += xdelta;
+ ar->v2d.cur.xmax += xdelta;
+
+ so->storeflag |= SO_TREESTORE_REDRAW;
+ }
+}
+
+
+/* find next element that has this name */
+static TreeElement *outliner_find_named(SpaceOops *soops, ListBase *lb, char *name, int flags, TreeElement *prev, int *prevFound)
+{
+ TreeElement *te, *tes;
+
+ for (te= lb->first; te; te= te->next) {
+ int found;
+
+ /* determine if match */
+ if(flags==OL_FIND)
+ found= BLI_strcasestr(te->name, name)!=NULL;
+ else if(flags==OL_FIND_CASE)
+ found= strstr(te->name, name)!=NULL;
+ else if(flags==OL_FIND_COMPLETE)
+ found= BLI_strcasecmp(te->name, name)==0;
+ else
+ found= strcmp(te->name, name)==0;
+
+ if(found) {
+ /* name is right, but is element the previous one? */
+ if (prev) {
+ if ((te != prev) && (*prevFound))
+ return te;
+ if (te == prev) {
+ *prevFound = 1;
+ }
+ }
+ else
+ return te;
+ }
+
+ tes= outliner_find_named(soops, &te->subtree, name, flags, prev, prevFound);
+ if(tes) return tes;
+ }
+
+ /* nothing valid found */
+ return NULL;
+}
+
+/* tse is not in the treestore, we use its contents to find a match */
+static TreeElement *outliner_find_tse(SpaceOops *soops, TreeStoreElem *tse)
+{
+ TreeStore *ts= soops->treestore;
+ TreeStoreElem *tselem;
+ int a;
+
+ if(tse->id==NULL) return NULL;
+
+ /* check if 'tse' is in treestore */
+ tselem= ts->data;
+ for(a=0; a<ts->usedelem; a++, tselem++) {
+ if((tse->type==0 && tselem->type==0) || (tselem->type==tse->type && tselem->nr==tse->nr)) {
+ if(tselem->id==tse->id) {
+ break;
+ }
+ }
+ }
+ if(tselem)
+ return outliner_find_tree_element(&soops->tree, a);
+
+ return NULL;
+}
+
+
+/* Called to find an item based on name.
+ */
+void outliner_find_panel(Scene *scene, ARegion *ar, SpaceOops *soops, int again, int flags)
+{
+ TreeElement *te= NULL;
+ TreeElement *last_find;
+ TreeStoreElem *tselem;
+ int ytop, xdelta, prevFound=0;
+ char name[33];
+
+ /* get last found tree-element based on stored search_tse */
+ last_find= outliner_find_tse(soops, &soops->search_tse);
+
+ /* determine which type of search to do */
+ if (again && last_find) {
+ /* no popup panel - previous + user wanted to search for next after previous */
+ BLI_strncpy(name, soops->search_string, 33);
+ flags= soops->search_flags;
+
+ /* try to find matching element */
+ te= outliner_find_named(soops, &soops->tree, name, flags, last_find, &prevFound);
+ if (te==NULL) {
+ /* no more matches after previous, start from beginning again */
+ prevFound= 1;
+ te= outliner_find_named(soops, &soops->tree, name, flags, last_find, &prevFound);
+ }
+ }
+ else {
+ /* pop up panel - no previous, or user didn't want search after previous */
+ strcpy(name, "");
+// XXX if (sbutton(name, 0, sizeof(name)-1, "Find: ") && name[0]) {
+// te= outliner_find_named(soops, &soops->tree, name, flags, NULL, &prevFound);
+// }
+// else return; /* XXX RETURN! XXX */
+ }
+
+ /* do selection and reveal */
+ if (te) {
+ tselem= TREESTORE(te);
+ if (tselem) {
+ /* expand branches so that it will be visible, we need to get correct coordinates */
+ if( outliner_open_back(soops, te))
+ outliner_set_coordinates(ar, soops);
+
+ /* deselect all visible, and select found element */
+ outliner_set_flag(soops, &soops->tree, TSE_SELECTED, 0);
+ tselem->flag |= TSE_SELECTED;
+
+ /* make te->ys center of view */
+ ytop= (int)(te->ys + (ar->v2d.mask.ymax-ar->v2d.mask.ymin)/2);
+ if(ytop>0) ytop= 0;
+ ar->v2d.cur.ymax= (float)ytop;
+ ar->v2d.cur.ymin= (float)(ytop-(ar->v2d.mask.ymax-ar->v2d.mask.ymin));
+
+ /* make te->xs ==> te->xend center of view */
+ xdelta = (int)(te->xs - ar->v2d.cur.xmin);
+ ar->v2d.cur.xmin += xdelta;
+ ar->v2d.cur.xmax += xdelta;
+
+ /* store selection */
+ soops->search_tse= *tselem;
+
+ BLI_strncpy(soops->search_string, name, 33);
+ soops->search_flags= flags;
+
+ /* redraw */
+ soops->storeflag |= SO_TREESTORE_REDRAW;
+ }
+ }
+ else {
+ /* no tree-element found */
+ error("Not found: %s", name);
+ }
+}
+
+static int subtree_has_objects(SpaceOops *soops, ListBase *lb)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for(te= lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+ if(tselem->type==0 && te->idcode==ID_OB) return 1;
+ if( subtree_has_objects(soops, &te->subtree)) return 1;
+ }
+ return 0;
+}
+
+static void tree_element_show_hierarchy(Scene *scene, SpaceOops *soops, ListBase *lb)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ /* open all object elems, close others */
+ for(te= lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+
+ if(tselem->type==0) {
+ if(te->idcode==ID_SCE) {
+ if(tselem->id!=(ID *)scene) tselem->flag |= TSE_CLOSED;
+ else tselem->flag &= ~TSE_CLOSED;
+ }
+ else if(te->idcode==ID_OB) {
+ if(subtree_has_objects(soops, &te->subtree)) tselem->flag &= ~TSE_CLOSED;
+ else tselem->flag |= TSE_CLOSED;
+ }
+ }
+ else tselem->flag |= TSE_CLOSED;
+
+ if(tselem->flag & TSE_CLOSED); else tree_element_show_hierarchy(scene, soops, &te->subtree);
+ }
+
+}
+
+/* show entire object level hierarchy */
+void outliner_show_hierarchy(Scene *scene, SpaceOops *soops)
+{
+
+ tree_element_show_hierarchy(scene, soops, &soops->tree);
+
+ BIF_undo_push("Outliner show hierarchy");
+}
+
+void outliner_select(SpaceOops *soops, ListBase *lb, int *index, short *selecting)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for (te= lb->first; te && *index >= 0; te=te->next, (*index)--) {
+ tselem= TREESTORE(te);
+
+ /* if we've encountered the right item, set its 'Outliner' selection status */
+ if (*index == 0) {
+ /* this should be the last one, so no need to do anything with index */
+ if ((te->flag & TE_ICONROW)==0) {
+ /* -1 value means toggle testing for now... */
+ if (*selecting == -1) {
+ if (tselem->flag & TSE_SELECTED)
+ *selecting= 0;
+ else
+ *selecting= 1;
+ }
+
+ /* set selection */
+ if (*selecting)
+ tselem->flag |= TSE_SELECTED;
+ else
+ tselem->flag &= ~TSE_SELECTED;
+ }
+ }
+ else if ((tselem->flag & TSE_CLOSED)==0) {
+ /* Only try selecting sub-elements if we haven't hit the right element yet
+ *
+ * Hack warning:
+ * Index must be reduced before supplying it to the sub-tree to try to do
+ * selection, however, we need to increment it again for the next loop to
+ * function correctly
+ */
+ (*index)--;
+ outliner_select(soops, &te->subtree, index, selecting);
+ (*index)++;
+ }
+ }
+}
+
+/* ************ SELECTION OPERATIONS ********* */
+
+static void set_operation_types(SpaceOops *soops, ListBase *lb,
+ int *scenelevel,
+ int *objectlevel,
+ int *idlevel,
+ int *datalevel)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for(te= lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+ if(tselem->flag & TSE_SELECTED) {
+ if(tselem->type) {
+ if(tselem->type==TSE_SEQUENCE)
+ *datalevel= TSE_SEQUENCE;
+ else if(tselem->type==TSE_SEQ_STRIP)
+ *datalevel= TSE_SEQ_STRIP;
+ else if(tselem->type==TSE_SEQUENCE_DUP)
+ *datalevel= TSE_SEQUENCE_DUP;
+ else if(*datalevel!=tselem->type) *datalevel= -1;
+ }
+ else {
+ int idcode= GS(tselem->id->name);
+ switch(idcode) {
+ case ID_SCE:
+ *scenelevel= 1;
+ break;
+ case ID_OB:
+ *objectlevel= 1;
+ break;
+
+ case ID_ME: case ID_CU: case ID_MB: case ID_LT:
+ case ID_LA: case ID_AR: case ID_CA:
+ case ID_MA: case ID_TE: case ID_IP: case ID_IM:
+ case ID_SO: case ID_KE: case ID_WO: case ID_AC:
+ case ID_NLA: case ID_TXT: case ID_GR:
+ if(*idlevel==0) *idlevel= idcode;
+ else if(*idlevel!=idcode) *idlevel= -1;
+ break;
+ }
+ }
+ }
+ if((tselem->flag & TSE_CLOSED)==0) {
+ set_operation_types(soops, &te->subtree,
+ scenelevel, objectlevel, idlevel, datalevel);
+ }
+ }
+}
+
+static void unlink_material_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
+{
+ Material **matar=NULL;
+ int a, totcol=0;
+
+ if( GS(tsep->id->name)==ID_OB) {
+ Object *ob= (Object *)tsep->id;
+ totcol= ob->totcol;
+ matar= ob->mat;
+ }
+ else if( GS(tsep->id->name)==ID_ME) {
+ Mesh *me= (Mesh *)tsep->id;
+ totcol= me->totcol;
+ matar= me->mat;
+ }
+ else if( GS(tsep->id->name)==ID_CU) {
+ Curve *cu= (Curve *)tsep->id;
+ totcol= cu->totcol;
+ matar= cu->mat;
+ }
+ else if( GS(tsep->id->name)==ID_MB) {
+ MetaBall *mb= (MetaBall *)tsep->id;
+ totcol= mb->totcol;
+ matar= mb->mat;
+ }
+
+ for(a=0; a<totcol; a++) {
+ if(a==te->index && matar[a]) {
+ matar[a]->id.us--;
+ matar[a]= NULL;
+ }
+ }
+}
+
+static void unlink_texture_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
+{
+ MTex **mtex= NULL;
+ int a;
+
+ if( GS(tsep->id->name)==ID_MA) {
+ Material *ma= (Material *)tsep->id;
+ mtex= ma->mtex;
+ }
+ else if( GS(tsep->id->name)==ID_LA) {
+ Lamp *la= (Lamp *)tsep->id;
+ mtex= la->mtex;
+ }
+ else if( GS(tsep->id->name)==ID_WO) {
+ World *wrld= (World *)tsep->id;
+ mtex= wrld->mtex;
+ }
+ else return;
+
+ for(a=0; a<MAX_MTEX; a++) {
+ if(a==te->index && mtex[a]) {
+ if(mtex[a]->tex) {
+ mtex[a]->tex->id.us--;
+ mtex[a]->tex= NULL;
+ }
+ }
+ }
+}
+
+static void unlink_group_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
+{
+ Group *group= (Group *)tselem->id;
+
+ if(tsep) {
+ if( GS(tsep->id->name)==ID_OB) {
+ Object *ob= (Object *)tsep->id;
+ ob->dup_group= NULL;
+ group->id.us--;
+ }
+ }
+ else {
+ unlink_group(group);
+ }
+}
+
+static void outliner_do_libdata_operation(SpaceOops *soops, ListBase *lb,
+ void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *))
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for(te=lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+ if(tselem->flag & TSE_SELECTED) {
+ if(tselem->type==0) {
+ TreeStoreElem *tsep= TREESTORE(te->parent);
+ operation_cb(te, tsep, tselem);
+ }
+ }
+ if((tselem->flag & TSE_CLOSED)==0) {
+ outliner_do_libdata_operation(soops, &te->subtree, operation_cb);
+ }
+ }
+}
+
+/* */
+
+static void object_select_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
+{
+ Scene *scene= NULL; // XXX
+ Base *base= (Base *)te->directdata;
+
+ if(base==NULL) base= object_in_scene((Object *)tselem->id, scene);
+ if(base && ((base->object->restrictflag & OB_RESTRICT_VIEW)==0)) {
+ base->flag |= SELECT;
+ base->object->flag |= SELECT;
+ }
+}
+
+static void object_deselect_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
+{
+ Scene *scene= NULL;
+ Base *base= (Base *)te->directdata;
+
+ if(base==NULL) base= object_in_scene((Object *)tselem->id, scene);
+ if(base) {
+ base->flag &= ~SELECT;
+ base->object->flag &= ~SELECT;
+ }
+}
+
+static void object_delete_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
+{
+ Scene *scene= NULL;
+ Base *base= (Base *)te->directdata;
+
+ if(base==NULL) base= object_in_scene((Object *)tselem->id, scene);
+ if(base) {
+ // check also library later
+// XXX if(obedit==base->object) exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR);
+
+ if(base==BASACT) {
+ G.f &= ~(G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT+G_SCULPTMODE);
+// XXX setcursor_space(SPACE_VIEW3D, CURSOR_STD);
+ }
+
+// XXX free_and_unlink_base(base);
+ te->directdata= NULL;
+ tselem->id= NULL;
+ }
+}
+
+static void id_local_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
+{
+ if(tselem->id->lib && (tselem->id->flag & LIB_EXTERN)) {
+ tselem->id->lib= NULL;
+ tselem->id->flag= LIB_LOCAL;
+ new_id(0, tselem->id, 0);
+ }
+}
+
+static void group_linkobs2scene_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
+{
+ Scene *scene= NULL;
+ Group *group= (Group *)tselem->id;
+ GroupObject *gob;
+ Base *base;
+
+ for(gob=group->gobject.first; gob; gob=gob->next) {
+ base= object_in_scene(gob->ob, scene);
+ if (base) {
+ base->object->flag |= SELECT;
+ base->flag |= SELECT;
+ } else {
+ /* link to scene */
+ base= MEM_callocN( sizeof(Base), "add_base");
+ BLI_addhead(&scene->base, base);
+ base->lay= (1<<20)-1; /*v3d->lay;*/ /* would be nice to use the 3d layer but the include's not here */
+ gob->ob->flag |= SELECT;
+ base->flag = gob->ob->flag;
+ base->object= gob->ob;
+ id_lib_extern((ID *)gob->ob); /* incase these are from a linked group */
+ }
+ }
+}
+
+static void outliner_do_object_operation(Scene *scene, SpaceOops *soops, ListBase *lb,
+ void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *))
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for(te=lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+ if(tselem->flag & TSE_SELECTED) {
+ if(tselem->type==0 && te->idcode==ID_OB) {
+ // when objects selected in other scenes... dunno if that should be allowed
+ Scene *sce= (Scene *)outliner_search_back(soops, te, ID_SCE);
+ if(sce && scene != sce) {
+// XXX ED_screen_set_scene(C, sce);
+ }
+
+ operation_cb(te, NULL, tselem);
+ }
+ }
+ if((tselem->flag & TSE_CLOSED)==0) {
+ outliner_do_object_operation(scene, soops, &te->subtree, operation_cb);
+ }
+ }
+}
+
+static void pchan_cb(int event, TreeElement *te, TreeStoreElem *tselem)
+{
+ bPoseChannel *pchan= (bPoseChannel *)te->directdata;
+
+ if(event==1)
+ pchan->bone->flag |= BONE_SELECTED;
+ else if(event==2)
+ pchan->bone->flag &= ~BONE_SELECTED;
+ else if(event==3) {
+ pchan->bone->flag |= BONE_HIDDEN_P;
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ else if(event==4)
+ pchan->bone->flag &= ~BONE_HIDDEN_P;
+}
+
+static void bone_cb(int event, TreeElement *te, TreeStoreElem *tselem)
+{
+ Bone *bone= (Bone *)te->directdata;
+
+ if(event==1)
+ bone->flag |= BONE_SELECTED;
+ else if(event==2)
+ bone->flag &= ~BONE_SELECTED;
+ else if(event==3) {
+ bone->flag |= BONE_HIDDEN_P;
+ bone->flag &= ~BONE_SELECTED;
+ }
+ else if(event==4)
+ bone->flag &= ~BONE_HIDDEN_P;
+}
+
+static void ebone_cb(int event, TreeElement *te, TreeStoreElem *tselem)
+{
+ EditBone *ebone= (EditBone *)te->directdata;
+
+ if(event==1)
+ ebone->flag |= BONE_SELECTED;
+ else if(event==2)
+ ebone->flag &= ~BONE_SELECTED;
+ else if(event==3) {
+ ebone->flag |= BONE_HIDDEN_A;
+ ebone->flag &= ~BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
+ }
+ else if(event==4)
+ ebone->flag &= ~BONE_HIDDEN_A;
+}
+
+static void sequence_cb(int event, TreeElement *te, TreeStoreElem *tselem)
+{
+// Sequence *seq= (Sequence*) te->directdata;
+ if(event==1) {
+// XXX select_single_seq(seq, 1);
+ }
+}
+
+static void outliner_do_data_operation(SpaceOops *soops, int type, int event, ListBase *lb,
+ void (*operation_cb)(int, TreeElement *, TreeStoreElem *))
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for(te=lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+ if(tselem->flag & TSE_SELECTED) {
+ if(tselem->type==type) {
+ operation_cb(event, te, tselem);
+ }
+ }
+ if((tselem->flag & TSE_CLOSED)==0) {
+ outliner_do_data_operation(soops, type, event, &te->subtree, operation_cb);
+ }
+ }
+}
+
+void outliner_del(Scene *scene, ARegion *ar, SpaceOops *soops)
+{
+
+// XXX if(soops->outlinevis==SO_SEQUENCE)
+// del_seq();
+// else {
+// outliner_do_object_operation(scene, soops, &soops->tree, object_delete_cb);
+// DAG_scene_sort(scene);
+// BIF_undo_push("Delete Objects");
+// }
+}
+
+
+void outliner_operation_menu(Scene *scene, ARegion *ar, SpaceOops *soops)
+{
+ int scenelevel=0, objectlevel=0, idlevel=0, datalevel=0;
+
+ set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
+
+ if(scenelevel) {
+ if(objectlevel || datalevel || idlevel) error("Mixed selection");
+ else pupmenu("Scene Operations%t|Delete");
+ }
+ else if(objectlevel) {
+ short event= pupmenu("Select%x1|Deselect%x2|Delete%x4|Toggle Visible%x6|Toggle Selectable%x7|Toggle Renderable%x8"); /* make local: does not work... it doesn't set lib_extern flags... so data gets lost */
+ if(event>0) {
+ char *str="";
+
+ if(event==1) {
+ Scene *sce= scene; // to be able to delete, scenes are set...
+ outliner_do_object_operation(scene, soops, &soops->tree, object_select_cb);
+ if(scene != sce) {
+// XXX ED_screen_set_scene(C, sce);
+ }
+
+ str= "Select Objects";
+ }
+ else if(event==2) {
+ outliner_do_object_operation(scene, soops, &soops->tree, object_deselect_cb);
+ str= "Deselect Objects";
+ }
+ else if(event==4) {
+ outliner_do_object_operation(scene, soops, &soops->tree, object_delete_cb);
+ DAG_scene_sort(scene);
+ str= "Delete Objects";
+ }
+ else if(event==5) { /* disabled, see above (ton) */
+ outliner_do_object_operation(scene, soops, &soops->tree, id_local_cb);
+ str= "Localized Objects";
+ }
+ else if(event==6) {
+ outliner_do_object_operation(scene, soops, &soops->tree, object_toggle_visibility_cb);
+ str= "Toggle Visibility";
+ }
+ else if(event==7) {
+ outliner_do_object_operation(scene, soops, &soops->tree, object_toggle_selectability_cb);
+ str= "Toggle Selectability";
+ }
+ else if(event==8) {
+ outliner_do_object_operation(scene, soops, &soops->tree, object_toggle_renderability_cb);
+ str= "Toggle Renderability";
+ }
+
+ BIF_undo_push(str);
+ }
+ }
+ else if(idlevel) {
+ if(idlevel==-1 || datalevel) error("Mixed selection");
+ else {
+ short event;
+ if (idlevel==ID_GR)
+ event = pupmenu("Unlink %x1|Make Local %x2|Link Group Objects to Scene%x3");
+ else
+ event = pupmenu("Unlink %x1|Make Local %x2");
+
+
+ if(event==1) {
+ switch(idlevel) {
+ case ID_MA:
+ outliner_do_libdata_operation(soops, &soops->tree, unlink_material_cb);
+ BIF_undo_push("Unlink material");
+ break;
+ case ID_TE:
+ outliner_do_libdata_operation(soops, &soops->tree, unlink_texture_cb);
+ BIF_undo_push("Unlink texture");
+ break;
+ case ID_GR:
+ outliner_do_libdata_operation(soops, &soops->tree, unlink_group_cb);
+ BIF_undo_push("Unlink group");
+ break;
+ default:
+ error("Not yet...");
+ }
+ }
+ else if(event==2) {
+ outliner_do_libdata_operation(soops, &soops->tree, id_local_cb);
+ BIF_undo_push("Localized Data");
+ }
+ else if(event==3 && idlevel==ID_GR) {
+ outliner_do_libdata_operation(soops, &soops->tree, group_linkobs2scene_cb);
+ BIF_undo_push("Link Group Objects to Scene");
+ }
+ }
+ }
+ else if(datalevel) {
+ if(datalevel==-1) error("Mixed selection");
+ else {
+ if(datalevel==TSE_POSE_CHANNEL) {
+ short event= pupmenu("PoseChannel Operations%t|Select%x1|Deselect%x2|Hide%x3|Unhide%x4");
+ if(event>0) {
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, pchan_cb);
+ BIF_undo_push("PoseChannel operation");
+ }
+ }
+ else if(datalevel==TSE_BONE) {
+ short event= pupmenu("Bone Operations%t|Select%x1|Deselect%x2|Hide%x3|Unhide%x4");
+ if(event>0) {
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, bone_cb);
+ BIF_undo_push("Bone operation");
+ }
+ }
+ else if(datalevel==TSE_EBONE) {
+ short event= pupmenu("EditBone Operations%t|Select%x1|Deselect%x2|Hide%x3|Unhide%x4");
+ if(event>0) {
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, ebone_cb);
+ BIF_undo_push("EditBone operation");
+ }
+ }
+ else if(datalevel==TSE_SEQUENCE) {
+ short event= pupmenu("Sequence Operations %t|Select %x1");
+ if(event>0) {
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, sequence_cb);
+ }
+ }
+
+ }
+ }
+}
+
+/* ***************** ANIMATO OPERATIONS ********************************** */
+/* KeyingSet and Driver Creation - Helper functions */
+
+/* specialised poll callback for these operators to work in Datablocks view only */
+static int ed_operator_outliner_datablocks_active(bContext *C)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ if ((sa) && (sa->spacetype==SPACE_OUTLINER)) {
+ SpaceOops *so= (SpaceOops *)CTX_wm_space_data(C);
+ return (so->outlinevis == SO_DATABLOCKS);
+ }
+ return 0;
+}
+
+
+/* Helper func to extract an RNA path from selected tree element
+ * NOTE: the caller must zero-out all values of the pointers that it passes here first, as
+ * this function does not do that yet
+ */
+static void tree_element_to_path(SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem,
+ ID **id, char **path, int *array_index, short *flag, short *groupmode)
+{
+ ListBase hierarchy = {NULL, NULL};
+ LinkData *ld;
+ TreeElement *tem, *temnext, *temsub;
+ TreeStoreElem *tse, *tsenext;
+ PointerRNA *ptr, *nextptr;
+ PropertyRNA *prop, *nameprop;
+ char *newpath=NULL;
+
+ /* optimise tricks:
+ * - Don't do anything if the selected item is a 'struct', but arrays are allowed
+ */
+ if (tselem->type == TSE_RNA_STRUCT)
+ return;
+
+ /* Overview of Algorithm:
+ * 1. Go up the chain of parents until we find the 'root', taking note of the
+ * levels encountered in reverse-order (i.e. items are added to the start of the list
+ * for more convenient looping later)
+ * 2. Walk down the chain, adding from the first ID encountered
+ * (which will become the 'ID' for the KeyingSet Path), and build a
+ * path as we step through the chain
+ */
+
+ /* step 1: flatten out hierarchy of parents into a flat chain */
+ for (tem= te->parent; tem; tem= tem->parent) {
+ ld= MEM_callocN(sizeof(LinkData), "LinkData for tree_element_to_path()");
+ ld->data= tem;
+ BLI_addhead(&hierarchy, ld);
+ }
+
+ /* step 2: step down hierarchy building the path (NOTE: addhead in previous loop was needed so that we can loop like this) */
+ for (ld= hierarchy.first; ld; ld= ld->next) {
+ /* get data */
+ tem= (TreeElement *)ld->data;
+ tse= TREESTORE(tem);
+ ptr= &tem->rnaptr;
+ prop= tem->directdata;
+
+ /* check if we're looking for first ID, or appending to path */
+ if (*id) {
+ /* just 'append' property to path
+ * - to prevent memory leaks, we must write to newpath not path, then free old path + swap them
+ */
+ if(tse->type == TSE_RNA_PROPERTY) {
+ if(RNA_property_type(prop) == PROP_POINTER) {
+ /* for pointer we just append property name */
+ newpath= RNA_path_append(*path, ptr, prop, 0, NULL);
+ }
+ else if(RNA_property_type(prop) == PROP_COLLECTION) {
+ temnext= (TreeElement*)(ld->next->data);
+ tsenext= TREESTORE(temnext);
+
+ nextptr= &temnext->rnaptr;
+ nameprop= RNA_struct_name_property(nextptr->type);
+
+ if(nameprop) {
+ /* if possible, use name as a key in the path */
+ char buf[128], *name;
+ name= RNA_property_string_get_alloc(nextptr, nameprop, buf, sizeof(buf));
+
+ newpath= RNA_path_append(*path, NULL, prop, 0, name);
+
+ if(name != buf)
+ MEM_freeN(name);
+ }
+ else {
+ /* otherwise use index */
+ int index= 0;
+
+ for(temsub=tem->subtree.first; temsub; temsub=temsub->next, index++)
+ if(temsub == temnext)
+ break;
+
+ newpath= RNA_path_append(*path, NULL, prop, index, NULL);
+ }
+
+ ld= ld->next;
+ }
+ }
+
+ if(newpath) {
+ if (*path) MEM_freeN(*path);
+ *path= newpath;
+ newpath= NULL;
+ }
+ }
+ else {
+ /* no ID, so check if entry is RNA-struct, and if that RNA-struct is an ID datablock to extract info from */
+ if (tse->type == TSE_RNA_STRUCT) {
+ /* ptr->data not ptr->id.data seems to be the one we want, since ptr->data is sometimes the owner of this ID? */
+ if(RNA_struct_is_ID(ptr->type)) {
+ *id= (ID *)ptr->data;
+
+ /* clear path */
+ if(*path) {
+ MEM_freeN(*path);
+ path= NULL;
+ }
+ }
+ }
+ }
+ }
+
+ /* step 3: if we've got an ID, add the current item to the path */
+ if (*id) {
+ /* add the active property to the path */
+ ptr= &te->rnaptr;
+ prop= te->directdata;
+
+ /* array checks */
+ if (tselem->type == TSE_RNA_ARRAY_ELEM) {
+ /* item is part of an array, so must set the array_index */
+ *array_index= te->index;
+ }
+ else if (RNA_property_array_length(prop)) {
+ /* entire array was selected, so keyframe all */
+ *flag |= KSP_FLAG_WHOLE_ARRAY;
+ }
+
+ /* path */
+ newpath= RNA_path_append(*path, NULL, prop, 0, NULL);
+ if (*path) MEM_freeN(*path);
+ *path= newpath;
+ }
+
+ /* free temp data */
+ BLI_freelistN(&hierarchy);
+}
+
+/* ***************** KEYINGSET OPERATIONS *************** */
+
+/* These operators are only available in databrowser mode for now, as
+ * they depend on having RNA paths and/or hierarchies available.
+ */
+enum {
+ DRIVERS_EDITMODE_ADD = 0,
+ DRIVERS_EDITMODE_REMOVE,
+} eDrivers_EditModes;
+
+/* Utilities ---------------------------------- */
+
+/* Recursively iterate over tree, finding and working on selected items */
+static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, short mode)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for (te= tree->first; te; te=te->next) {
+ tselem= TREESTORE(te);
+
+ /* if item is selected, perform operation */
+ if (tselem->flag & TSE_SELECTED) {
+ ID *id= NULL;
+ char *path= NULL;
+ int array_index= 0;
+ short flag= 0;
+ short groupmode= KSP_GROUP_KSNAME;
+
+ /* check if RNA-property described by this selected element is an animateable prop */
+ if ((tselem->type == TSE_RNA_PROPERTY) && RNA_property_animateable(&te->rnaptr, te->directdata)) {
+ /* get id + path + index info from the selected element */
+ tree_element_to_path(soops, te, tselem,
+ &id, &path, &array_index, &flag, &groupmode);
+ }
+
+ /* only if ID and path were set, should we perform any actions */
+ if (id && path) {
+ /* action depends on mode */
+ switch (mode) {
+ case DRIVERS_EDITMODE_ADD:
+ {
+ /* add a new driver with the information obtained (only if valid) */
+ ANIM_add_driver(id, path, array_index, flag);
+ }
+ break;
+ case DRIVERS_EDITMODE_REMOVE:
+ {
+ /* remove driver matching the information obtained (only if valid) */
+ ANIM_remove_driver(id, path, array_index, flag);
+ }
+ break;
+ }
+
+ /* free path, since it had to be generated */
+ MEM_freeN(path);
+ }
+
+
+ }
+
+ /* go over sub-tree */
+ if ((tselem->flag & TSE_CLOSED)==0)
+ do_outliner_drivers_editop(soops, &te->subtree, mode);
+ }
+}
+
+/* Add Operator ---------------------------------- */
+
+static int outliner_drivers_addsel_exec(bContext *C, wmOperator *op)
+{
+ SpaceOops *soutliner= (SpaceOops*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+
+ /* check for invalid states */
+ if (soutliner == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* recursively go into tree, adding selected items */
+ do_outliner_drivers_editop(soutliner, &soutliner->tree, DRIVERS_EDITMODE_ADD);
+
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_drivers_add(wmOperatorType *ot)
+{
+ /* api callbacks */
+ ot->idname= "OUTLINER_OT_drivers_add";
+ ot->name= "Add Drivers";
+ ot->description= "Add drivers to selected items.";
+
+ /* api callbacks */
+ ot->exec= outliner_drivers_addsel_exec;
+ ot->poll= ed_operator_outliner_datablocks_active;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+}
+
+
+/* Remove Operator ---------------------------------- */
+
+static int outliner_drivers_deletesel_exec(bContext *C, wmOperator *op)
+{
+ SpaceOops *soutliner= (SpaceOops*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+
+ /* check for invalid states */
+ if (soutliner == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* recursively go into tree, adding selected items */
+ do_outliner_drivers_editop(soutliner, &soutliner->tree, DRIVERS_EDITMODE_REMOVE);
+
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_drivers_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->idname= "OUTLINER_OT_drivers_delete";
+ ot->name= "Delete Drivers";
+ ot->description= "Delete drivers assigned to selected items.";
+
+ /* api callbacks */
+ ot->exec= outliner_drivers_deletesel_exec;
+ ot->poll= ed_operator_outliner_datablocks_active;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+}
+
+/* ***************** KEYINGSET OPERATIONS *************** */
+
+/* These operators are only available in databrowser mode for now, as
+ * they depend on having RNA paths and/or hierarchies available.
+ */
+enum {
+ KEYINGSET_EDITMODE_ADD = 0,
+ KEYINGSET_EDITMODE_REMOVE,
+} eKeyingSet_EditModes;
+
+/* Utilities ---------------------------------- */
+
+/* find the 'active' KeyingSet, and add if not found (if adding is allowed) */
+// TODO: should this be an API func?
+static KeyingSet *verify_active_keyingset(Scene *scene, short add)
+{
+ KeyingSet *ks= NULL;
+
+ /* sanity check */
+ if (scene == NULL)
+ return NULL;
+
+ /* try to find one from scene */
+ if (scene->active_keyingset > 0)
+ ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
+
+ /* add if none found */
+ // XXX the default settings have yet to evolve
+ if ((add) && (ks==NULL)) {
+ ks= BKE_keyingset_add(&scene->keyingsets, "Keying Set", KEYINGSET_ABSOLUTE, 0);
+ scene->active_keyingset= BLI_countlist(&scene->keyingsets);
+ }
+
+ return ks;
+}
+
+/* Recursively iterate over tree, finding and working on selected items */
+static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBase *tree, short mode)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for (te= tree->first; te; te=te->next) {
+ tselem= TREESTORE(te);
+
+ /* if item is selected, perform operation */
+ if (tselem->flag & TSE_SELECTED) {
+ ID *id= NULL;
+ char *path= NULL;
+ int array_index= 0;
+ short flag= 0;
+ short groupmode= KSP_GROUP_KSNAME;
+
+ /* check if RNA-property described by this selected element is an animateable prop */
+ if ((tselem->type == TSE_RNA_PROPERTY) && RNA_property_animateable(&te->rnaptr, te->directdata)) {
+ /* get id + path + index info from the selected element */
+ tree_element_to_path(soops, te, tselem,
+ &id, &path, &array_index, &flag, &groupmode);
+ }
+
+ /* only if ID and path were set, should we perform any actions */
+ if (id && path) {
+ /* action depends on mode */
+ switch (mode) {
+ case KEYINGSET_EDITMODE_ADD:
+ {
+ /* add a new path with the information obtained (only if valid) */
+ // TODO: what do we do with group name? for now, we don't supply one, and just let this use the KeyingSet name
+ BKE_keyingset_add_destination(ks, id, NULL, path, array_index, flag, groupmode);
+ }
+ break;
+ case KEYINGSET_EDITMODE_REMOVE:
+ {
+ /* find the relevant path, then remove it from the KeyingSet */
+ KS_Path *ksp= BKE_keyingset_find_destination(ks, id, NULL, path, array_index, groupmode);
+
+ if (ksp) {
+ /* free path's data */
+ // TODO: we probably need an API method for this
+ if (ksp->rna_path) MEM_freeN(ksp->rna_path);
+
+ /* remove path from set */
+ BLI_freelinkN(&ks->paths, ksp);
+ }
+ }
+ break;
+ }
+
+ /* free path, since it had to be generated */
+ MEM_freeN(path);
+ }
+
+
+ }
+
+ /* go over sub-tree */
+ if ((tselem->flag & TSE_CLOSED)==0)
+ do_outliner_keyingset_editop(soops, ks, &te->subtree, mode);
+ }
+}
+
+/* Add Operator ---------------------------------- */
+
+static int outliner_keyingset_additems_exec(bContext *C, wmOperator *op)
+{
+ SpaceOops *soutliner= (SpaceOops*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ KeyingSet *ks= verify_active_keyingset(scene, 1);
+
+ /* check for invalid states */
+ if (ks == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Operation requires an Active Keying Set");
+ return OPERATOR_CANCELLED;
+ }
+ if (soutliner == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* recursively go into tree, adding selected items */
+ do_outliner_keyingset_editop(soutliner, ks, &soutliner->tree, KEYINGSET_EDITMODE_ADD);
+
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_keyingset_add_selected(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->idname= "OUTLINER_OT_keyingset_add_selected";
+ ot->name= "Keyingset Add Selected";
+
+ /* api callbacks */
+ ot->exec= outliner_keyingset_additems_exec;
+ ot->poll= ed_operator_outliner_datablocks_active;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+}
+
+
+/* Remove Operator ---------------------------------- */
+
+static int outliner_keyingset_removeitems_exec(bContext *C, wmOperator *op)
+{
+ SpaceOops *soutliner= (SpaceOops*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ KeyingSet *ks= verify_active_keyingset(scene, 1);
+
+ /* check for invalid states */
+ if (soutliner == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* recursively go into tree, adding selected items */
+ do_outliner_keyingset_editop(soutliner, ks, &soutliner->tree, KEYINGSET_EDITMODE_REMOVE);
+
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_keyingset_remove_selected(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->idname= "OUTLINER_OT_keyingset_remove_selected";
+ ot->name= "Keyingset Remove Selected";
+
+ /* api callbacks */
+ ot->exec= outliner_keyingset_removeitems_exec;
+ ot->poll= ed_operator_outliner_datablocks_active;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+}
+
+/* ***************** DRAW *************** */
+
+static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElement *te)
+{
+ if(tselem->type) {
+ switch( tselem->type) {
+ case TSE_ANIM_DATA:
+ UI_icon_draw(x, y, ICON_ANIM_DATA); break; // xxx
+ case TSE_NLA:
+ UI_icon_draw(x, y, ICON_NLA); break;
+ case TSE_NLA_ACTION:
+ UI_icon_draw(x, y, ICON_ACTION); break;
+ case TSE_DEFGROUP_BASE:
+ UI_icon_draw(x, y, ICON_VGROUP); break;
+ case TSE_BONE:
+ case TSE_EBONE:
+ UI_icon_draw(x, y, ICON_BONE_DATA); break;
+ case TSE_CONSTRAINT_BASE:
+ UI_icon_draw(x, y, ICON_CONSTRAINT); break;
+ case TSE_MODIFIER_BASE:
+ UI_icon_draw(x, y, ICON_MODIFIER); break;
+ case TSE_LINKED_OB:
+ UI_icon_draw(x, y, ICON_OBJECT_DATA); break;
+ case TSE_LINKED_PSYS:
+ UI_icon_draw(x, y, ICON_PARTICLES); break;
+ case TSE_MODIFIER:
+ {
+ Object *ob= (Object *)tselem->id;
+ ModifierData *md= BLI_findlink(&ob->modifiers, tselem->nr);
+ switch(md->type) {
+ case eModifierType_Subsurf:
+ UI_icon_draw(x, y, ICON_MOD_SUBSURF); break;
+ case eModifierType_Armature:
+ UI_icon_draw(x, y, ICON_MOD_ARMATURE); break;
+ case eModifierType_Lattice:
+ UI_icon_draw(x, y, ICON_MOD_LATTICE); break;
+ case eModifierType_Curve:
+ UI_icon_draw(x, y, ICON_MOD_CURVE); break;
+ case eModifierType_Build:
+ UI_icon_draw(x, y, ICON_MOD_BUILD); break;
+ case eModifierType_Mirror:
+ UI_icon_draw(x, y, ICON_MOD_MIRROR); break;
+ case eModifierType_Decimate:
+ UI_icon_draw(x, y, ICON_MOD_DECIM); break;
+ case eModifierType_Wave:
+ UI_icon_draw(x, y, ICON_MOD_WAVE); break;
+ case eModifierType_Hook:
+ UI_icon_draw(x, y, ICON_HOOK); break;
+ case eModifierType_Softbody:
+ UI_icon_draw(x, y, ICON_MOD_SOFT); break;
+ case eModifierType_Boolean:
+ UI_icon_draw(x, y, ICON_MOD_BOOLEAN); break;
+ case eModifierType_ParticleSystem:
+ UI_icon_draw(x, y, ICON_MOD_PARTICLEINSTANCE); break;
+ case eModifierType_ParticleInstance:
+ UI_icon_draw(x, y, ICON_MOD_PARTICLES); break;
+ case eModifierType_EdgeSplit:
+ UI_icon_draw(x, y, ICON_MOD_EDGESPLIT); break;
+ case eModifierType_Array:
+ UI_icon_draw(x, y, ICON_MOD_ARRAY); break;
+ case eModifierType_UVProject:
+ UI_icon_draw(x, y, ICON_MOD_UVPROJECT); break;
+ case eModifierType_Displace:
+ UI_icon_draw(x, y, ICON_MOD_DISPLACE); break;
+ default:
+ UI_icon_draw(x, y, ICON_DOT); break;
+ }
+ break;
+ }
+ case TSE_SCRIPT_BASE:
+ UI_icon_draw(x, y, ICON_TEXT); break;
+ case TSE_POSE_BASE:
+ UI_icon_draw(x, y, ICON_ARMATURE_DATA); break;
+ case TSE_POSE_CHANNEL:
+ UI_icon_draw(x, y, ICON_BONE_DATA); break;
+ case TSE_PROXY:
+ UI_icon_draw(x, y, ICON_GHOST); break;
+ case TSE_R_LAYER_BASE:
+ UI_icon_draw(x, y, ICON_RENDERLAYERS); break;
+ case TSE_R_LAYER:
+ UI_icon_draw(x, y, ICON_RENDER_RESULT); break;
+ case TSE_LINKED_LAMP:
+ UI_icon_draw(x, y, ICON_LAMP_DATA); break;
+ case TSE_LINKED_MAT:
+ UI_icon_draw(x, y, ICON_MATERIAL_DATA); break;
+ case TSE_POSEGRP_BASE:
+ UI_icon_draw(x, y, ICON_VERTEXSEL); break;
+ case TSE_SEQUENCE:
+ if((te->idcode==SEQ_MOVIE) || (te->idcode==SEQ_MOVIE_AND_HD_SOUND))
+ UI_icon_draw(x, y, ICON_SEQUENCE);
+ else if(te->idcode==SEQ_META)
+ UI_icon_draw(x, y, ICON_DOT);
+ else if(te->idcode==SEQ_SCENE)
+ UI_icon_draw(x, y, ICON_SCENE);
+ else if((te->idcode==SEQ_RAM_SOUND) || (te->idcode==SEQ_HD_SOUND))
+ UI_icon_draw(x, y, ICON_SOUND);
+ else if(te->idcode==SEQ_IMAGE)
+ UI_icon_draw(x, y, ICON_IMAGE_COL);
+ else
+ UI_icon_draw(x, y, ICON_PARTICLES);
+ break;
+ case TSE_SEQ_STRIP:
+ UI_icon_draw(x, y, ICON_LIBRARY_DATA_DIRECT);
+ break;
+ case TSE_SEQUENCE_DUP:
+ UI_icon_draw(x, y, ICON_OBJECT_DATA);
+ break;
+ case TSE_RNA_STRUCT:
+ UI_icon_draw(x, y, UI_GetIconRNA(&te->rnaptr));
+ break;
+ default:
+ UI_icon_draw(x, y, ICON_DOT); break;
+ }
+ }
+ else if (GS(tselem->id->name) == ID_OB) {
+ Object *ob= (Object *)tselem->id;
+ switch (ob->type) {
+ case OB_LAMP:
+ UI_icon_draw(x, y, ICON_OUTLINER_OB_LAMP); break;
+ case OB_MESH:
+ UI_icon_draw(x, y, ICON_OUTLINER_OB_MESH); break;
+ case OB_CAMERA:
+ UI_icon_draw(x, y, ICON_OUTLINER_OB_CAMERA); break;
+ case OB_CURVE:
+ UI_icon_draw(x, y, ICON_OUTLINER_OB_CURVE); break;
+ case OB_MBALL:
+ UI_icon_draw(x, y, ICON_OUTLINER_OB_META); break;
+ case OB_LATTICE:
+ UI_icon_draw(x, y, ICON_OUTLINER_OB_LATTICE); break;
+ case OB_ARMATURE:
+ UI_icon_draw(x, y, ICON_OUTLINER_OB_ARMATURE); break;
+ case OB_FONT:
+ UI_icon_draw(x, y, ICON_OUTLINER_OB_FONT); break;
+ case OB_SURF:
+ UI_icon_draw(x, y, ICON_OUTLINER_OB_SURFACE); break;
+ case OB_EMPTY:
+ UI_icon_draw(x, y, ICON_OUTLINER_OB_EMPTY); break;
+
+ }
+ }
+ else {
+ switch( GS(tselem->id->name)) {
+ case ID_SCE:
+ UI_icon_draw(x, y, ICON_SCENE_DATA); break;
+ case ID_ME:
+ UI_icon_draw(x, y, ICON_OUTLINER_DATA_MESH); break;
+ case ID_CU:
+ UI_icon_draw(x, y, ICON_OUTLINER_DATA_CURVE); break;
+ case ID_MB:
+ UI_icon_draw(x, y, ICON_OUTLINER_DATA_META); break;
+ case ID_LT:
+ UI_icon_draw(x, y, ICON_OUTLINER_DATA_LATTICE); break;
+ case ID_LA:
+ UI_icon_draw(x, y, ICON_OUTLINER_DATA_LAMP); break;
+ case ID_MA:
+ UI_icon_draw(x, y, ICON_MATERIAL_DATA); break;
+ case ID_TE:
+ UI_icon_draw(x, y, ICON_TEXTURE_DATA); break;
+ case ID_IM:
+ UI_icon_draw(x, y, ICON_IMAGE_DATA); break;
+ case ID_SO:
+ UI_icon_draw(x, y, ICON_SPEAKER); break;
+ case ID_AR:
+ UI_icon_draw(x, y, ICON_OUTLINER_DATA_ARMATURE); break;
+ case ID_CA:
+ UI_icon_draw(x, y, ICON_OUTLINER_DATA_CAMERA); break;
+ case ID_KE:
+ UI_icon_draw(x, y, ICON_SHAPEKEY_DATA); break;
+ case ID_WO:
+ UI_icon_draw(x, y, ICON_WORLD_DATA); break;
+ case ID_AC:
+ UI_icon_draw(x, y, ICON_ACTION); break;
+ case ID_NLA:
+ UI_icon_draw(x, y, ICON_NLA); break;
+ case ID_TXT:
+ UI_icon_draw(x, y, ICON_SCRIPT); break;
+ case ID_GR:
+ UI_icon_draw(x, y, ICON_GROUP); break;
+ case ID_LI:
+ UI_icon_draw(x, y, ICON_LIBRARY_DATA_DIRECT); break;
+ }
+ }
+}
+
+static void outliner_draw_iconrow(Scene *scene, SpaceOops *soops, ListBase *lb, int level, int *offsx, int ys)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+ int active;
+
+ for(te= lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+
+ /* object hierarchy always, further constrained on level */
+ if(level<1 || (tselem->type==0 && te->idcode==ID_OB)) {
+
+ /* active blocks get white circle */
+ active= 0;
+ if(tselem->type==0) {
+ if(te->idcode==ID_OB) active= (OBACT==(Object *)tselem->id);
+ else if(scene->obedit && scene->obedit->data==tselem->id) active= 1; // XXX use context?
+ else active= tree_element_active(scene, soops, te, 0);
+ }
+ else active= tree_element_type_active(NULL, scene, soops, te, tselem, 0);
+
+ if(active) {
+ uiSetRoundBox(15);
+ glColor4ub(255, 255, 255, 100);
+ uiRoundBox( (float)*offsx-0.5f, (float)ys-1.0f, (float)*offsx+OL_H-3.0f, (float)ys+OL_H-3.0f, OL_H/2.0f-2.0f);
+ glEnable(GL_BLEND);
+ }
+
+ tselem_draw_icon((float)*offsx, (float)ys, tselem, te);
+ te->xs= (float)*offsx;
+ te->ys= (float)ys;
+ te->xend= (short)*offsx+OL_X;
+ te->flag |= TE_ICONROW; // for click
+
+ (*offsx) += OL_X;
+ }
+
+ /* this tree element always has same amount of branches, so dont draw */
+ if(tselem->type!=TSE_R_LAYER)
+ outliner_draw_iconrow(scene, soops, &te->subtree, level+1, offsx, ys);
+ }
+
+}
+
+static void outliner_draw_tree_element(Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int startx, int *starty)
+{
+ TreeElement *ten;
+ TreeStoreElem *tselem;
+ int offsx= 0, active=0; // active=1 active obj, else active data
+
+ tselem= TREESTORE(te);
+
+ if(*starty >= ar->v2d.cur.ymin && *starty<= ar->v2d.cur.ymax) {
+
+ glEnable(GL_BLEND);
+
+ /* colors for active/selected data */
+ if(tselem->type==0) {
+ if(te->idcode==ID_SCE) {
+ if(tselem->id == (ID *)scene) {
+ glColor4ub(255, 255, 255, 100);
+ active= 2;
+ }
+ }
+ else if(te->idcode==ID_OB) {
+ Object *ob= (Object *)tselem->id;
+
+ if(ob==OBACT || (ob->flag & SELECT)) {
+ char col[4];
+
+ active= 2;
+ if(ob==OBACT) {
+ UI_GetThemeColorType4ubv(TH_ACTIVE, SPACE_VIEW3D, col);
+ /* so black text is drawn when active and not selected */
+ if (ob->flag & SELECT) active= 1;
+ }
+ else UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col);
+ col[3]= 100;
+ glColor4ubv((GLubyte *)col);
+ }
+
+ }
+// XXX context? else if(obedit && obedit->data==tselem->id) {
+// glColor4ub(255, 255, 255, 100);
+// active= 2;
+// }
+ else {
+ if(tree_element_active(scene, soops, te, 0)) {
+ glColor4ub(220, 220, 255, 100);
+ active= 2;
+ }
+ }
+ }
+ else {
+ if( tree_element_type_active(NULL, scene, soops, te, tselem, 0) ) active= 2;
+ glColor4ub(220, 220, 255, 100);
+ }
+
+ /* active circle */
+ if(active) {
+ uiSetRoundBox(15);
+ uiRoundBox( (float)startx+OL_H-1.5f, (float)*starty+2.0f, (float)startx+2.0f*OL_H-4.0f, (float)*starty+OL_H-1.0f, OL_H/2.0f-2.0f);
+ glEnable(GL_BLEND); /* roundbox disables it */
+
+ te->flag |= TE_ACTIVE; // for lookup in display hierarchies
+ }
+
+ /* open/close icon, only when sublevels, except for scene */
+ if(te->subtree.first || (tselem->type==0 && te->idcode==ID_SCE) || (te->flag & TE_LAZY_CLOSED)) {
+ int icon_x;
+ if(tselem->type==0 && ELEM(te->idcode, ID_OB, ID_SCE))
+ icon_x = startx;
+ else
+ icon_x = startx+5;
+
+ // icons a bit higher
+ if(tselem->flag & TSE_CLOSED)
+ UI_icon_draw((float)icon_x, (float)*starty+2, ICON_DISCLOSURE_TRI_RIGHT);
+ else
+ UI_icon_draw((float)icon_x, (float)*starty+2, ICON_DISCLOSURE_TRI_DOWN);
+ }
+ offsx+= OL_X;
+
+ /* datatype icon */
+
+ if(!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM))) {
+ // icons a bit higher
+ tselem_draw_icon((float)startx+offsx, (float)*starty+2, tselem, te);
+ offsx+= OL_X;
+ }
+ else
+ offsx+= 2;
+
+ if(tselem->type==0 && tselem->id->lib) {
+ glPixelTransferf(GL_ALPHA_SCALE, 0.5f);
+ if(tselem->id->flag & LIB_INDIRECT)
+ UI_icon_draw((float)startx+offsx, (float)*starty+2, ICON_LIBRARY_DATA_INDIRECT);
+ else
+ UI_icon_draw((float)startx+offsx, (float)*starty+2, ICON_LIBRARY_DATA_DIRECT);
+ glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
+ offsx+= OL_X;
+ }
+ glDisable(GL_BLEND);
+
+ /* name */
+ if(active==1) UI_ThemeColor(TH_TEXT_HI);
+ else if(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.75f);
+ else UI_ThemeColor(TH_TEXT);
+
+ UI_DrawString(startx+offsx, *starty+5, te->name);
+
+ offsx+= (int)(OL_X + UI_GetStringWidth(te->name));
+
+ /* closed item, we draw the icons, not when it's a scene, or master-server list though */
+ if(tselem->flag & TSE_CLOSED) {
+ if(te->subtree.first) {
+ if(tselem->type==0 && te->idcode==ID_SCE);
+ else if(tselem->type!=TSE_R_LAYER) { /* this tree element always has same amount of branches, so dont draw */
+ int tempx= startx+offsx;
+ // divider
+ UI_ThemeColorShade(TH_BACK, -40);
+ glRecti(tempx -10, *starty+4, tempx -8, *starty+OL_H-4);
+
+ glEnable(GL_BLEND);
+ glPixelTransferf(GL_ALPHA_SCALE, 0.5);
+
+ outliner_draw_iconrow(scene, soops, &te->subtree, 0, &tempx, *starty+2);
+
+ glPixelTransferf(GL_ALPHA_SCALE, 1.0);
+ glDisable(GL_BLEND);
+ }
+ }
+ }
+ }
+ /* store coord and continue, we need coordinates for elements outside view too */
+ te->xs= (float)startx;
+ te->ys= (float)*starty;
+ te->xend= startx+offsx;
+
+ *starty-= OL_H;
+
+ if((tselem->flag & TSE_CLOSED)==0) {
+ for(ten= te->subtree.first; ten; ten= ten->next) {
+ outliner_draw_tree_element(scene, ar, soops, ten, startx+OL_X, starty);
+ }
+ }
+}
+
+static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx, int *starty)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+ int y1, y2;
+
+ if(lb->first==NULL) return;
+
+ y1=y2= *starty; /* for vertical lines between objects */
+ for(te=lb->first; te; te= te->next) {
+ y2= *starty;
+ tselem= TREESTORE(te);
+
+ /* horizontal line? */
+ if(tselem->type==0 && (te->idcode==ID_OB || te->idcode==ID_SCE))
+ glRecti(startx, *starty, startx+OL_X, *starty-1);
+
+ *starty-= OL_H;
+
+ if((tselem->flag & TSE_CLOSED)==0)
+ outliner_draw_hierarchy(soops, &te->subtree, startx+OL_X, starty);
+ }
+
+ /* vertical line */
+ te= lb->last;
+ if(te->parent || lb->first!=lb->last) {
+ tselem= TREESTORE(te);
+ if(tselem->type==0 && te->idcode==ID_OB) {
+
+ glRecti(startx, y1+OL_H, startx+1, y2);
+ }
+ }
+}
+
+static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for(te= lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+
+ /* selection status */
+ if((tselem->flag & TSE_CLOSED)==0)
+ if(tselem->type == TSE_RNA_STRUCT)
+ glRecti(0, *starty+1, (int)ar->v2d.cur.xmax, *starty+OL_H-1);
+
+ *starty-= OL_H;
+ if((tselem->flag & TSE_CLOSED)==0) {
+ outliner_draw_struct_marks(ar, soops, &te->subtree, starty);
+ if(tselem->type == TSE_RNA_STRUCT)
+ fdrawline(0, (float)*starty+OL_H-1, ar->v2d.cur.xmax, (float)*starty+OL_H-1);
+ }
+ }
+}
+
+static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for(te= lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+
+ /* selection status */
+ if(tselem->flag & TSE_SELECTED) {
+ glRecti(0, *starty+1, (int)ar->v2d.cur.xmax, *starty+OL_H-1);
+ }
+ *starty-= OL_H;
+ if((tselem->flag & TSE_CLOSED)==0) outliner_draw_selection(ar, soops, &te->subtree, starty);
+ }
+}
+
+
+static void outliner_draw_tree(Scene *scene, ARegion *ar, SpaceOops *soops)
+{
+ TreeElement *te;
+ int starty, startx;
+ float col[4];
+
+#if 0 // XXX was #ifdef INTERNATIONAL
+ FTF_SetFontSize('l');
+ BIF_SetScale(1.0);
+#endif
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // only once
+
+ if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
+ /* struct marks */
+ UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
+ //UI_ThemeColorShade(TH_BACK, -20);
+ starty= (int)ar->v2d.tot.ymax-OL_H;
+ outliner_draw_struct_marks(ar, soops, &soops->tree, &starty);
+ }
+
+ /* always draw selection fill before hierarchy */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glColor3f(col[0]+0.06f, col[1]+0.08f, col[2]+0.10f);
+ starty= (int)ar->v2d.tot.ymax-OL_H;
+ outliner_draw_selection(ar, soops, &soops->tree, &starty);
+
+ // grey hierarchy lines
+ UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.2f);
+ starty= (int)ar->v2d.tot.ymax-OL_H/2;
+ startx= 6;
+ outliner_draw_hierarchy(soops, &soops->tree, startx, &starty);
+
+ // items themselves
+ starty= (int)ar->v2d.tot.ymax-OL_H;
+ startx= 0;
+ for(te= soops->tree.first; te; te= te->next) {
+ outliner_draw_tree_element(scene, ar, soops, te, startx, &starty);
+ }
+}
+
+
+static void outliner_back(ARegion *ar, SpaceOops *soops)
+{
+ int ystart;
+
+ UI_ThemeColorShade(TH_BACK, 6);
+ ystart= (int)ar->v2d.tot.ymax;
+ ystart= OL_H*(ystart/(OL_H));
+
+ while(ystart > ar->v2d.cur.ymin) {
+ glRecti(0, ystart, (int)ar->v2d.cur.xmax, ystart+OL_H);
+ ystart-= 2*OL_H;
+ }
+}
+
+static void outliner_draw_restrictcols(ARegion *ar, SpaceOops *soops)
+{
+ int ystart;
+
+ /* background underneath */
+ UI_ThemeColor(TH_BACK);
+ glRecti((int)ar->v2d.cur.xmax-OL_TOGW, (int)ar->v2d.cur.ymin, (int)ar->v2d.cur.xmax, (int)ar->v2d.cur.ymax);
+
+ UI_ThemeColorShade(TH_BACK, 6);
+ ystart= (int)ar->v2d.tot.ymax;
+ ystart= OL_H*(ystart/(OL_H));
+
+ while(ystart > ar->v2d.cur.ymin) {
+ glRecti((int)ar->v2d.cur.xmax-OL_TOGW, ystart, (int)ar->v2d.cur.xmax, ystart+OL_H);
+ ystart-= 2*OL_H;
+ }
+
+ UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
+
+ /* view */
+ fdrawline(ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX,
+ ar->v2d.cur.ymax,
+ ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX,
+ ar->v2d.cur.ymin);
+
+ /* render */
+ fdrawline(ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX,
+ ar->v2d.cur.ymax,
+ ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX,
+ ar->v2d.cur.ymin);
+
+ /* render */
+ fdrawline(ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX,
+ ar->v2d.cur.ymax,
+ ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX,
+ ar->v2d.cur.ymin);
+}
+
+static void restrictbutton_view_cb(bContext *C, void *poin, void *poin2)
+{
+ Base *base;
+ Scene *scene = (Scene *)poin;
+ Object *ob = (Object *)poin2;
+
+ /* deselect objects that are invisible */
+ if (ob->restrictflag & OB_RESTRICT_VIEW) {
+
+ /* Ouch! There is no backwards pointer from Object to Base,
+ * so have to do loop to find it. */
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(base->object==ob) {
+ base->flag &= ~SELECT;
+ base->object->flag= base->flag;
+ }
+ }
+ }
+
+}
+
+static void restrictbutton_sel_cb(bContext *C, void *poin, void *poin2)
+{
+ Base *base;
+ Scene *scene = (Scene *)poin;
+ Object *ob = (Object *)poin2;
+
+ /* if select restriction has just been turned on */
+ if (ob->restrictflag & OB_RESTRICT_SELECT) {
+
+ /* Ouch! There is no backwards pointer from Object to Base,
+ * so have to do loop to find it. */
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(base->object==ob) {
+ base->flag &= ~SELECT;
+ base->object->flag= base->flag;
+ }
+ }
+ }
+
+}
+
+static void restrictbutton_rend_cb(bContext *C, void *poin, void *poin2)
+{
+}
+
+static void restrictbutton_r_lay_cb(bContext *C, void *poin, void *poin2)
+{
+ /* XXX redraws */
+}
+
+static void restrictbutton_modifier_cb(bContext *C, void *poin, void *poin2)
+{
+ Scene *scene = (Scene *)poin;
+ Object *ob = (Object *)poin2;
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ object_handle_update(scene, ob);
+
+}
+
+static void restrictbutton_bone_cb(bContext *C, void *poin, void *poin2)
+{
+ /* XXX redraws */
+}
+
+static void namebutton_cb(bContext *C, void *tep, void *oldnamep)
+{
+ SpaceOops *soops= NULL; // XXXcurarea->spacedata.first;
+ Scene *scene= NULL; // XXX
+ TreeStore *ts= soops->treestore;
+ TreeElement *te= tep;
+
+ if(ts && te) {
+ TreeStoreElem *tselem= TREESTORE(te);
+
+ if(tselem->type==0) {
+ test_idbutton(tselem->id->name+2); // library.c, unique name and alpha sort
+
+ /* Check the library target exists */
+ if (te->idcode == ID_LI) {
+ char expanded[FILE_MAXDIR + FILE_MAXFILE];
+ BLI_strncpy(expanded, ((Library *)tselem->id)->name, FILE_MAXDIR + FILE_MAXFILE);
+ BLI_convertstringcode(expanded, G.sce);
+ if (!BLI_exists(expanded)) {
+ error("This path does not exist, correct this before saving");
+ }
+ }
+ }
+ else {
+ switch(tselem->type) {
+ case TSE_DEFGROUP:
+ unique_vertexgroup_name(te->directdata, (Object *)tselem->id); // id = object
+ break;
+ case TSE_NLA_ACTION:
+ test_idbutton(tselem->id->name+2);
+ break;
+ case TSE_EBONE:
+ {
+ bArmature *arm= (bArmature *)tselem->id;
+ if(arm->edbo) {
+ EditBone *ebone= te->directdata;
+ char newname[32];
+
+ /* restore bone name */
+ BLI_strncpy(newname, ebone->name, 32);
+ BLI_strncpy(ebone->name, oldnamep, 32);
+// XXX armature_bone_rename(obedit->data, oldnamep, newname);
+ }
+ }
+ break;
+
+ case TSE_BONE:
+ {
+ Bone *bone= te->directdata;
+ Object *ob;
+ char newname[32];
+
+ // always make current object active
+ tree_element_set_active_object(C, scene, soops, te);
+ ob= OBACT;
+
+ /* restore bone name */
+ BLI_strncpy(newname, bone->name, 32);
+ BLI_strncpy(bone->name, oldnamep, 32);
+// XXX armature_bone_rename(ob->data, oldnamep, newname);
+ }
+ break;
+ case TSE_POSE_CHANNEL:
+ {
+ bPoseChannel *pchan= te->directdata;
+ Object *ob;
+ char newname[32];
+
+ // always make current object active
+ tree_element_set_active_object(C, scene, soops, te);
+ ob= OBACT;
+
+ /* restore bone name */
+ BLI_strncpy(newname, pchan->name, 32);
+ BLI_strncpy(pchan->name, oldnamep, 32);
+// XXX armature_bone_rename(ob->data, oldnamep, newname);
+ }
+ break;
+ case TSE_POSEGRP:
+ {
+ Object *ob= (Object *)tselem->id; // id = object
+ bActionGroup *grp= te->directdata;
+
+ BLI_uniquename(&ob->pose->agroups, grp, "Group", '.', offsetof(bActionGroup, name), 32);
+ }
+ break;
+ case TSE_R_LAYER:
+ break;
+ }
+ }
+ }
+}
+
+static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, ListBase *lb)
+{
+ uiBut *bt;
+ TreeElement *te;
+ TreeStoreElem *tselem;
+ Object *ob = NULL;
+
+ for(te= lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+ if(te->ys >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
+ /* objects have toggle-able restriction flags */
+ if(tselem->type==0 && te->idcode==ID_OB) {
+ ob = (Object *)tselem->id;
+
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+ bt= uiDefIconButBitS(block, ICONTOG, OB_RESTRICT_VIEW, 0, ICON_RESTRICT_VIEW_OFF,
+ (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, &(ob->restrictflag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
+ uiButSetFunc(bt, restrictbutton_view_cb, scene, ob);
+ uiButSetFlag(bt, UI_NO_HILITE);
+
+ bt= uiDefIconButBitS(block, ICONTOG, OB_RESTRICT_SELECT, 0, ICON_RESTRICT_SELECT_OFF,
+ (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (short)te->ys, 17, OL_H-1, &(ob->restrictflag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
+ uiButSetFunc(bt, restrictbutton_sel_cb, scene, ob);
+ uiButSetFlag(bt, UI_NO_HILITE);
+
+ bt= uiDefIconButBitS(block, ICONTOG, OB_RESTRICT_RENDER, 0, ICON_RESTRICT_RENDER_OFF,
+ (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX, (short)te->ys, 17, OL_H-1, &(ob->restrictflag), 0, 0, 0, 0, "Restrict/Allow renderability");
+ uiButSetFunc(bt, restrictbutton_rend_cb, NULL, NULL);
+ uiButSetFlag(bt, UI_NO_HILITE);
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ }
+ /* scene render layers and passes have toggle-able flags too! */
+ else if(tselem->type==TSE_R_LAYER) {
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+
+ bt= uiDefIconButBitI(block, ICONTOGN, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT-1,
+ (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, te->directdata, 0, 0, 0, 0, "Render this RenderLayer");
+ uiButSetFunc(bt, restrictbutton_r_lay_cb, NULL, NULL);
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ }
+ else if(tselem->type==TSE_R_PASS) {
+ int *layflag= te->directdata;
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+
+ /* NOTE: tselem->nr is short! */
+ bt= uiDefIconButBitI(block, ICONTOG, tselem->nr, 0, ICON_CHECKBOX_HLT-1,
+ (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, layflag, 0, 0, 0, 0, "Render this Pass");
+ uiButSetFunc(bt, restrictbutton_r_lay_cb, NULL, NULL);
+
+ layflag++; /* is lay_xor */
+ if(ELEM6(tselem->nr, SCE_PASS_SPEC, SCE_PASS_SHADOW, SCE_PASS_AO, SCE_PASS_REFLECT, SCE_PASS_REFRACT, SCE_PASS_RADIO))
+ bt= uiDefIconButBitI(block, TOG, tselem->nr, 0, (*layflag & tselem->nr)?ICON_DOT:ICON_BLANK1,
+ (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (short)te->ys, 17, OL_H-1, layflag, 0, 0, 0, 0, "Exclude this Pass from Combined");
+ uiButSetFunc(bt, restrictbutton_r_lay_cb, NULL, NULL);
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ }
+ else if(tselem->type==TSE_MODIFIER) {
+ ModifierData *md= (ModifierData *)te->directdata;
+ ob = (Object *)tselem->id;
+
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+ bt= uiDefIconButBitI(block, ICONTOGN, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF,
+ (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, &(md->mode), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
+ uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob);
+ uiButSetFlag(bt, UI_NO_HILITE);
+
+ bt= uiDefIconButBitI(block, ICONTOGN, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF,
+ (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX, (short)te->ys, 17, OL_H-1, &(md->mode), 0, 0, 0, 0, "Restrict/Allow renderability");
+ uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob);
+ uiButSetFlag(bt, UI_NO_HILITE);
+ }
+ else if(tselem->type==TSE_POSE_CHANNEL) {
+ bPoseChannel *pchan= (bPoseChannel *)te->directdata;
+ Bone *bone = pchan->bone;
+
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+ bt= uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_P, 0, ICON_RESTRICT_VIEW_OFF,
+ (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
+ uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL);
+ uiButSetFlag(bt, UI_NO_HILITE);
+ }
+ else if(tselem->type==TSE_EBONE) {
+ EditBone *ebone= (EditBone *)te->directdata;
+
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+ bt= uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF,
+ (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
+ uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL);
+ uiButSetFlag(bt, UI_NO_HILITE);
+ }
+ }
+
+ if((tselem->flag & TSE_CLOSED)==0) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree);
+ }
+}
+
+static void outliner_draw_rnacols(ARegion *ar, SpaceOops *soops, int sizex)
+{
+ View2D *v2d= &ar->v2d;
+
+ UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
+
+ /* draw column separator lines */
+ fdrawline((float)sizex,
+ v2d->cur.ymax,
+ (float)sizex,
+ v2d->cur.ymin);
+
+ fdrawline((float)sizex+OL_RNA_COL_SIZEX,
+ v2d->cur.ymax,
+ (float)sizex+OL_RNA_COL_SIZEX,
+ v2d->cur.ymin);
+}
+
+static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, int sizex, ListBase *lb)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+ PointerRNA *ptr;
+ PropertyRNA *prop;
+
+ uiBlockSetEmboss(block, UI_EMBOSST);
+
+ for(te= lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+ if(te->ys >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
+ if(tselem->type == TSE_RNA_PROPERTY) {
+ ptr= &te->rnaptr;
+ prop= te->directdata;
+
+ if(!(RNA_property_type(prop) == PROP_POINTER && (tselem->flag & TSE_CLOSED)==0))
+ uiDefAutoButR(block, ptr, prop, -1, "", 0, sizex, (int)te->ys, OL_RNA_COL_SIZEX, OL_H-1);
+ }
+ else if(tselem->type == TSE_RNA_ARRAY_ELEM) {
+ ptr= &te->rnaptr;
+ prop= te->directdata;
+
+ uiDefAutoButR(block, ptr, prop, te->index, "", 0, sizex, (int)te->ys, OL_RNA_COL_SIZEX, OL_H-1);
+ }
+ }
+
+ if((tselem->flag & TSE_CLOSED)==0) outliner_draw_rnabuts(block, scene, ar, soops, sizex, &te->subtree);
+ }
+}
+
+static void outliner_buttons(uiBlock *block, ARegion *ar, SpaceOops *soops, ListBase *lb)
+{
+ uiBut *bt;
+ TreeElement *te;
+ TreeStoreElem *tselem;
+ int dx, len;
+
+ for(te= lb->first; te; te= te->next) {
+ tselem= TREESTORE(te);
+ if(te->ys >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
+
+ if(tselem->flag & TSE_TEXTBUT) {
+ /* If we add support to rename Sequence.
+ * need change this.
+ */
+ if(tselem->type == TSE_POSE_BASE) continue; // prevent crash when trying to rename 'pose' entry of armature
+
+ if(tselem->type==TSE_EBONE) len = sizeof(((EditBone*) 0)->name);
+ else if (tselem->type==TSE_MODIFIER) len = sizeof(((ModifierData*) 0)->name);
+ else if(tselem->id && GS(tselem->id->name)==ID_LI) len = sizeof(((Library*) 0)->name);
+ else len= sizeof(((ID*) 0)->name)-2;
+
+ dx= (int)UI_GetStringWidth(te->name);
+ if(dx<50) dx= 50;
+
+ bt= uiDefBut(block, TEX, OL_NAMEBUTTON, "", (short)te->xs+2*OL_X-4, (short)te->ys, dx+10, OL_H-1, te->name, 1.0, (float)len-1, 0, 0, "");
+ uiButSetFunc(bt, namebutton_cb, te, NULL);
+
+ // signal for button to open
+// XXX addqueue(curarea->win, BUT_ACTIVATE, OL_NAMEBUTTON);
+
+ /* otherwise keeps open on ESC */
+ tselem->flag &= ~TSE_TEXTBUT;
+ }
+ }
+
+ if((tselem->flag & TSE_CLOSED)==0) outliner_buttons(block, ar, soops, &te->subtree);
+ }
+}
+
+void draw_outliner(const bContext *C)
+{
+ Main *mainvar= CTX_data_main(C);
+ Scene *scene= CTX_data_scene(C);
+ ARegion *ar= CTX_wm_region(C);
+ View2D *v2d= &ar->v2d;
+ SpaceOops *soops= (SpaceOops*)CTX_wm_space_data(C);
+ uiBlock *block;
+ int sizey= 0, sizex= 0, sizex_rna= 0;
+
+ outliner_build_tree(mainvar, scene, soops); // always
+
+ /* get extents of data */
+ outliner_height(soops, &soops->tree, &sizey);
+
+ if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
+ /* RNA has two columns:
+ * - column 1 is (max_width + OL_RNA_COL_SPACEX) or
+ * (OL_RNA_COL_X), whichever is wider...
+ * - column 2 is fixed at OL_RNA_COL_SIZEX
+ *
+ * (*) XXX max width for now is a fixed factor of OL_X*(max_indention+100)
+ */
+
+ /* get actual width of column 1 */
+ outliner_rna_width(soops, &soops->tree, &sizex_rna, 0);
+ sizex_rna= MAX2(OL_RNA_COLX, sizex_rna+OL_RNA_COL_SPACEX);
+
+ /* get width of data (for setting 'tot' rect, this is column 1 + column 2 + a bit extra) */
+ sizex= sizex_rna + OL_RNA_COL_SIZEX + 50;
+ }
+ else {
+ /* width must take into account restriction columns (if visible) so that entries will still be visible */
+ //outliner_width(soops, &soops->tree, &sizex);
+ outliner_rna_width(soops, &soops->tree, &sizex, 0); // XXX should use outliner_width instead when te->xend will be set correctly...
+
+ /* constant offset for restriction columns */
+ // XXX this isn't that great yet...
+ if ((soops->flag & SO_HIDE_RESTRICTCOLS)==0)
+ sizex += OL_TOGW*3;
+ }
+
+ /* update size of tot-rect (extents of data/viewable area) */
+ UI_view2d_totRect_set(v2d, sizex, sizey);
+
+ /* set matrix for 2d-view controls */
+ UI_view2d_view_ortho(C, v2d);
+
+ /* draw outliner stuff (background and hierachy lines) */
+ outliner_back(ar, soops);
+ outliner_draw_tree(scene, ar, soops);
+
+ /* draw icons and names */
+ block= uiBeginBlock(C, ar, "outliner buttons", UI_EMBOSS);
+ outliner_buttons(block, ar, soops, &soops->tree);
+
+ if(ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
+ /* draw rna buttons */
+ outliner_draw_rnacols(ar, soops, sizex_rna);
+ outliner_draw_rnabuts(block, scene, ar, soops, sizex_rna, &soops->tree);
+ }
+ else if (!(soops->flag & SO_HIDE_RESTRICTCOLS)) {
+ /* draw restriction columns */
+ outliner_draw_restrictcols(ar, soops);
+ outliner_draw_restrictbuts(block, scene, ar, soops, &soops->tree);
+ }
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+
+ /* clear flag that allows quick redraws */
+ soops->storeflag &= ~SO_TREESTORE_REDRAW;
+}
+
diff --git a/source/blender/editors/space_outliner/outliner_header.c b/source/blender/editors/space_outliner/outliner_header.c
new file mode 100644
index 00000000000..fe2f054899c
--- /dev/null
+++ b/source/blender/editors/space_outliner/outliner_header.c
@@ -0,0 +1,307 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_ID.h"
+#include "DNA_anim_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_animsys.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_screen.h"
+
+#include "ED_keyframing.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+#include "ED_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "outliner_intern.h"
+
+
+/* ************************ header area region *********************** */
+
+static void do_viewmenu(bContext *C, void *arg, int event)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ SpaceOops *soops= curarea->spacedata.first;
+
+ switch(event) {
+ case 0: /* Shuffle Selected Blocks */
+ //shuffle_oops();
+ break;
+ case 1: /* Shrink Selected Blocks */
+ //shrink_oops();
+ break;
+ case 2: /* View All */
+ //do_oops_buttons(B_OOPSHOME);
+ break;
+ case 3: /* View All */
+ //do_oops_buttons(B_OOPSVIEWSEL);
+ break;
+ case 4: /* Maximize Window */
+ /* using event B_FULL */
+ break;
+ break;
+ case 6:
+ //outliner_toggle_visible(curarea);
+ break;
+ case 7:
+ //outliner_show_hierarchy(curarea);
+ break;
+ case 8:
+ //outliner_show_active(curarea);
+ break;
+ case 9:
+ //outliner_one_level(curarea, 1);
+ break;
+ case 10:
+ //outliner_one_level(curarea, -1);
+ break;
+ case 12:
+ if (soops->flag & SO_HIDE_RESTRICTCOLS) soops->flag &= ~SO_HIDE_RESTRICTCOLS;
+ else soops->flag |= SO_HIDE_RESTRICTCOLS;
+ break;
+ }
+ ED_area_tag_redraw(curarea);
+}
+
+static uiBlock *outliner_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ SpaceOops *soops= curarea->spacedata.first;
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "outliner_viewmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_viewmenu, NULL);
+
+ if (soops->flag & SO_HIDE_RESTRICTCOLS)
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Show Restriction Columns", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
+ else
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Show Restriction Columns", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Expand One Level|NumPad +", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Collapse One Level|NumPad -", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show/Hide All", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Hierarchy|Home", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Active|NumPad .", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
+
+// uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+// if(!curarea->full) uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
+// else uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
+
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+enum {
+ B_REDR = 1,
+
+ B_KEYINGSET_CHANGE,
+ B_KEYINGSET_REMOVE,
+} eOutlinerHeader_Events;
+
+static void do_outliner_buttons(bContext *C, void *arg, int event)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ Scene *scene= CTX_data_scene(C);
+
+ switch(event) {
+ case B_REDR:
+ ED_area_tag_redraw(sa);
+ break;
+
+ case B_KEYINGSET_CHANGE:
+ /* add a new KeyingSet if active is -1 */
+ if (scene->active_keyingset == -1) {
+ // XXX the default settings have yet to evolve... need to keep this in sync with the
+ BKE_keyingset_add(&scene->keyingsets, "KeyingSet", KEYINGSET_ABSOLUTE, 0);
+ scene->active_keyingset= BLI_countlist(&scene->keyingsets);
+ }
+
+ /* redraw regions with KeyingSet info */
+ WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, scene);
+ break;
+
+ case B_KEYINGSET_REMOVE:
+ /* remove the active KeyingSet */
+ if (scene->active_keyingset) {
+ KeyingSet *ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
+
+ /* firstly free KeyingSet's data, then free the KeyingSet itself */
+ if (ks) {
+ BKE_keyingset_free(ks);
+ BLI_freelinkN(&scene->keyingsets, ks);
+ scene->active_keyingset= 0;
+ }
+ }
+
+ /* redraw regions with KeyingSet info */
+ WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, scene);
+ break;
+ }
+}
+
+
+void outliner_header_buttons(const bContext *C, ARegion *ar)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ Scene *scene= CTX_data_scene(C);
+ SpaceOops *soutliner= (SpaceOops*)CTX_wm_space_data(C);
+ uiBlock *block;
+ int xco, yco= 3, xmax;
+
+ block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_outliner_buttons, NULL);
+
+ xco= ED_area_header_standardbuttons(C, block, yco);
+
+ if((sa->flag & HEADER_NO_PULLDOWN)==0) {
+
+ xmax= GetButStringLength("View");
+ uiDefPulldownBut(block, outliner_viewmenu, CTX_wm_area(C),
+ "View", xco, yco-2, xmax-3, 24, "");
+ xco += xmax;
+
+ /* header text */
+ xco += XIC*2;
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ }
+
+ /* data selector*/
+ if(G.main->library.first)
+ uiDefButS(block, MENU, B_REDR, "Outliner Display%t|Libraries %x7|All Scenes %x0|Current Scene %x1|Visible Layers %x2|Groups %x6|Same Types %x5|Selected %x3|Active %x4|Sequence %x10|Datablocks %x11|User Preferences %x12", xco, yco, 120, 20, &soutliner->outlinevis, 0, 0, 0, 0, "");
+ else
+ uiDefButS(block, MENU, B_REDR, "Outliner Display%t|All Scenes %x0|Current Scene %x1|Visible Layers %x2|Groups %x6|Same Types %x5|Selected %x3|Active %x4|Sequence %x10|Datablocks %x11|User Preferences %x12", xco, yco, 120, 20, &soutliner->outlinevis, 0, 0, 0, 0, "");
+ xco += 120;
+
+ /* KeyingSet editing buttons */
+ if ((soutliner->flag & SO_HIDE_KEYINGSETINFO)==0 && (soutliner->outlinevis==SO_DATABLOCKS)) {
+ KeyingSet *ks= NULL;
+ char *menustr= NULL;
+
+ xco+= (int)(XIC*1.5);
+
+ if (scene->active_keyingset)
+ ks= (KeyingSet *)BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
+
+ uiBlockBeginAlign(block);
+ /* currently 'active' KeyingSet */
+ menustr= ANIM_build_keyingsets_menu(&scene->keyingsets, 1);
+ uiDefButI(block, MENU, B_KEYINGSET_CHANGE, menustr, xco,yco, 18,20, &scene->active_keyingset, 0, 0, 0, 0, "Browse Keying Sets");
+ MEM_freeN(menustr);
+ xco += 18;
+
+ /* currently 'active' KeyingSet - change name */
+ if (ks) {
+ /* active KeyingSet */
+ uiDefBut(block, TEX, B_KEYINGSET_CHANGE,"", xco,yco,120,20, ks->name, 0, 63, 0, 0, "Name of Active Keying Set");
+ xco += 120;
+ uiDefIconBut(block, BUT, B_KEYINGSET_REMOVE, VICON_X, xco, yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Remove this Keying Set");
+ xco += 20;
+ }
+ else {
+ /* no active KeyingSet... so placeholder instead */
+ uiDefBut(block, LABEL, 0,"<No Keying Set Active>", xco,yco,140,20, NULL, 0, 63, 0, 0, "Name of Active Keying Set");
+ xco += 140;
+ }
+ uiBlockEndAlign(block);
+
+ /* current 'active' KeyingSet */
+ if (ks) {
+ xco += 5;
+
+ /* operator buttons to add/remove selected items from set */
+ uiBlockBeginAlign(block);
+ // XXX the icons here are temporary
+ uiDefIconButO(block, BUT, "OUTLINER_OT_keyingset_remove_selected", WM_OP_INVOKE_REGION_WIN, ICON_ZOOMOUT, xco,yco,XIC,YIC, "Remove selected properties from active Keying Set (Alt-K)");
+ xco += XIC;
+ uiDefIconButO(block, BUT, "OUTLINER_OT_keyingset_add_selected", WM_OP_INVOKE_REGION_WIN, ICON_ZOOMIN, xco,yco,XIC,YIC, "Add selected properties to active Keying Set (K)");
+ xco += XIC;
+ uiBlockEndAlign(block);
+
+ xco += 10;
+
+ /* operator buttons to insert/delete keyframes for the active set */
+ uiBlockBeginAlign(block);
+ uiDefIconButO(block, BUT, "ANIM_OT_delete_keyframe", WM_OP_INVOKE_REGION_WIN, ICON_KEY_DEHLT, xco,yco,XIC,YIC, "Delete Keyframes for the Active Keying Set (Alt-I)");
+ xco+= XIC;
+ uiDefIconButO(block, BUT, "ANIM_OT_insert_keyframe", WM_OP_INVOKE_REGION_WIN, ICON_KEY_HLT, xco,yco,XIC,YIC, "Insert Keyframes for the Active Keying Set (I)");
+ xco+= XIC;
+ uiBlockEndAlign(block);
+ }
+
+ xco += XIC*2;
+ }
+
+ /* always as last */
+ UI_view2d_totRect_set(&ar->v2d, xco+XIC+100, (int)(ar->v2d.tot.ymax-ar->v2d.tot.ymin));
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+}
+
+
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
new file mode 100644
index 00000000000..48c904121a5
--- /dev/null
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -0,0 +1,146 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_OUTLINER_INTERN_H
+#define ED_OUTLINER_INTERN_H
+
+#include "RNA_types.h"
+
+/* internal exports only */
+
+struct wmWindowManager;
+struct wmOperatorType;
+struct TreeStoreElem;
+struct bContext;
+struct Scene;
+struct ARegion;
+
+typedef struct TreeElement {
+ struct TreeElement *next, *prev, *parent;
+ ListBase subtree;
+ float xs, ys; // do selection
+ int store_index; // offset in tree store
+ short flag, index; // flag for non-saved stuff, index for data arrays
+ short idcode; // from TreeStore id
+ short xend; // width of item display, for select
+ char *name;
+ void *directdata; // Armature Bones, Base, Sequence, Strip...
+ PointerRNA rnaptr; // RNA Pointer
+} TreeElement;
+
+/* TreeElement->flag */
+#define TE_ACTIVE 1
+#define TE_ICONROW 2
+#define TE_LAZY_CLOSED 4
+#define TE_FREE_NAME 8
+
+/* TreeStoreElem types */
+#define TSE_NLA 1
+#define TSE_NLA_ACTION 2
+#define TSE_DEFGROUP_BASE 3
+#define TSE_DEFGROUP 4
+#define TSE_BONE 5
+#define TSE_EBONE 6
+#define TSE_CONSTRAINT_BASE 7
+#define TSE_CONSTRAINT 8
+#define TSE_MODIFIER_BASE 9
+#define TSE_MODIFIER 10
+#define TSE_LINKED_OB 11
+#define TSE_SCRIPT_BASE 12
+#define TSE_POSE_BASE 13
+#define TSE_POSE_CHANNEL 14
+#define TSE_ANIM_DATA 15
+#define TSE_DRIVER_BASE 16
+#define TSE_DRIVER 17
+
+#define TSE_PROXY 18
+#define TSE_R_LAYER_BASE 19
+#define TSE_R_LAYER 20
+#define TSE_R_PASS 21
+#define TSE_LINKED_MAT 22
+/* NOTE, is used for light group */
+#define TSE_LINKED_LAMP 23
+#define TSE_POSEGRP_BASE 24
+#define TSE_POSEGRP 25
+#define TSE_SEQUENCE 26
+#define TSE_SEQ_STRIP 27
+#define TSE_SEQUENCE_DUP 28
+#define TSE_LINKED_PSYS 29
+#define TSE_RNA_STRUCT 30
+#define TSE_RNA_PROPERTY 31
+#define TSE_RNA_ARRAY_ELEM 32
+
+/* outliner search flags */
+#define OL_FIND 0
+#define OL_FIND_CASE 1
+#define OL_FIND_COMPLETE 2
+#define OL_FIND_COMPLETE_CASE 3
+
+/* button events */
+#define OL_NAMEBUTTON 1
+
+
+/* outliner_ops.c */
+void outliner_operatortypes(void);
+void outliner_keymap(struct wmWindowManager *wm);
+
+/* outliner_header.c */
+void outliner_header_buttons(const struct bContext *C, struct ARegion *ar);
+
+/* outliner.c */
+void outliner_free_tree(struct ListBase *lb);
+void outliner_operation_menu(struct Scene *scene, struct ARegion *ar, struct SpaceOops *soops);
+void outliner_select(struct SpaceOops *soops, struct ListBase *lb, int *index, short *selecting);
+void draw_outliner(const struct bContext *C);
+
+void OUTLINER_OT_activate_click(struct wmOperatorType *ot);
+
+void OUTLINER_OT_keyingset_add_selected(struct wmOperatorType *ot);
+void OUTLINER_OT_keyingset_remove_selected(struct wmOperatorType *ot);
+
+void OUTLINER_OT_drivers_add(struct wmOperatorType *ot);
+void OUTLINER_OT_drivers_delete(struct wmOperatorType *ot);
+
+#if 0
+extern void outliner_mouse_event(Scene *scene, ARegion *ar, SpaceOops *soops, short event);
+extern void outliner_toggle_visible(SpaceOops *soops);
+extern void outliner_show_active(ARegion *ar, SpaceOops *soops);
+extern void outliner_show_hierarchy(Scene *scene, SpaceOops *soops);
+extern void outliner_one_level(SpaceOops *soops, int add);
+extern void outliner_select(Scene *scene, SpaceOops *soops);
+extern void outliner_toggle_selected(Scene *scene, SpaceOops *soops);
+extern void outliner_toggle_visibility(Scene *scene, SpaceOops *soops);
+extern void outliner_toggle_selectability(Scene *scene, SpaceOops *soops);
+extern void outliner_toggle_renderability(Scene *scene, SpaceOops *soops);
+extern void outliner_del(Scene *scene, SpaceOops *soops);
+extern void outliner_page_up_down(Scene *scene, ARegion *ar, SpaceOops *soops, int up);
+extern void outliner_find_panel(Scene *scene, ARegion *ar, SpaceOops *soops, int again, int flags);
+#endif
+
+#endif /* ED_OUTLINER_INTERN_H */
+
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
new file mode 100644
index 00000000000..0efbdb06cd2
--- /dev/null
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -0,0 +1,71 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+
+#include "DNA_space_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "ED_screen.h"
+
+#include "outliner_intern.h"
+
+/* ************************** registration **********************************/
+
+
+
+void outliner_operatortypes(void)
+{
+ WM_operatortype_append(OUTLINER_OT_activate_click);
+
+ WM_operatortype_append(OUTLINER_OT_keyingset_add_selected);
+ WM_operatortype_append(OUTLINER_OT_keyingset_remove_selected);
+
+ WM_operatortype_append(OUTLINER_OT_drivers_add);
+ WM_operatortype_append(OUTLINER_OT_drivers_delete);
+}
+
+void outliner_keymap(wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "Outliner", SPACE_OUTLINER, 0);
+
+ WM_keymap_verify_item(keymap, "OUTLINER_OT_activate_click", LEFTMOUSE, KM_PRESS, 0, 0);
+
+ /* keying sets - only for databrowse */
+ WM_keymap_verify_item(keymap, "OUTLINER_OT_keyingset_add_selected", KKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "OUTLINER_OT_keyingset_remove_selected", KKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_verify_item(keymap, "ANIM_OT_insert_keyframe", IKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "ANIM_OT_delete_keyframe", IKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_add", DKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_delete", DKEY, KM_PRESS, KM_ALT, 0);
+}
+
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
new file mode 100644
index 00000000000..8e30db584af
--- /dev/null
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -0,0 +1,288 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_color_types.h"
+#include "DNA_object_types.h"
+#include "DNA_outliner_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_vec_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+
+#include "outliner_intern.h"
+
+static void outliner_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "Outliner", SPACE_OUTLINER, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+static void outliner_main_area_draw(const bContext *C, ARegion *ar)
+{
+ View2D *v2d= &ar->v2d;
+ View2DScrollers *scrollers;
+ float col[3];
+
+ /* clear */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ draw_outliner(C);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+}
+
+
+static void outliner_main_area_free(ARegion *ar)
+{
+}
+
+
+static void outliner_main_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ switch(wmn->data) {
+ case ND_OB_ACTIVE:
+ case ND_OB_SELECT:
+ case ND_MODE:
+ case ND_KEYINGSET:
+ case ND_FRAME:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch(wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_TRANSFORM:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ case NC_GROUP:
+ /* all actions now, todo: check outliner view mode? */
+ ED_region_tag_redraw(ar);
+ break;
+ }
+
+}
+
+
+/* ************************ header outliner area region *********************** */
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void outliner_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+}
+
+static void outliner_header_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ if(ED_screen_area_active(C))
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ else
+ UI_GetThemeColor3fv(TH_HEADERDESEL, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ outliner_header_buttons(C, ar);
+}
+
+static void outliner_header_area_free(ARegion *ar)
+{
+}
+
+static void outliner_header_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ if(wmn->data == ND_KEYINGSET)
+ ED_region_tag_redraw(ar);
+ break;
+ }
+}
+
+/* ******************** default callbacks for outliner space ***************** */
+
+static SpaceLink *outliner_new(const bContext *C)
+{
+ ARegion *ar;
+ SpaceOops *soutliner;
+
+ soutliner= MEM_callocN(sizeof(SpaceOops), "initoutliner");
+ soutliner->spacetype= SPACE_OUTLINER;
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for outliner");
+
+ BLI_addtail(&soutliner->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_BOTTOM;
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for outliner");
+
+ BLI_addtail(&soutliner->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+
+ ar->v2d.scroll = (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM_O);
+ ar->v2d.align = (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_POS_Y);
+ ar->v2d.keepzoom = (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_KEEPZOOM|V2D_KEEPASPECT);
+ ar->v2d.keeptot= V2D_KEEPTOT_STRICT;
+ ar->v2d.minzoom= ar->v2d.maxzoom= 1.0f;
+
+ return (SpaceLink*)soutliner;
+}
+
+/* not spacelink itself */
+static void outliner_free(SpaceLink *sl)
+{
+ SpaceOops *soutliner= (SpaceOops*)sl;
+
+ outliner_free_tree(&soutliner->tree);
+ if(soutliner->treestore) {
+ if(soutliner->treestore->data) MEM_freeN(soutliner->treestore->data);
+ MEM_freeN(soutliner->treestore);
+ }
+
+}
+
+/* spacetype; init callback */
+static void outliner_init(wmWindowManager *wm, ScrArea *sa)
+{
+
+}
+
+static SpaceLink *outliner_duplicate(SpaceLink *sl)
+{
+ SpaceOops *soutliner= (SpaceOops *)sl;
+ SpaceOops *soutlinern= MEM_dupallocN(soutliner);
+
+ soutlinern->tree.first= soutlinern->tree.last= NULL;
+ soutlinern->treestore= NULL;
+
+ return (SpaceLink *)soutlinern;
+}
+
+/* only called once, from space_api/spacetypes.c */
+void ED_spacetype_outliner(void)
+{
+ SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype time");
+ ARegionType *art;
+
+ st->spaceid= SPACE_OUTLINER;
+ strncpy(st->name, "Outliner", BKE_ST_MAXNAME);
+
+ st->new= outliner_new;
+ st->free= outliner_free;
+ st->init= outliner_init;
+ st->duplicate= outliner_duplicate;
+ st->operatortypes= outliner_operatortypes;
+ st->keymap= outliner_keymap;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype time region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+
+ art->init= outliner_main_area_init;
+ art->draw= outliner_main_area_draw;
+ art->free= outliner_main_area_free;
+ art->listener= outliner_main_area_listener;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype time region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+
+ art->init= outliner_header_area_init;
+ art->draw= outliner_header_area_draw;
+ art->free= outliner_header_area_free;
+ art->listener= outliner_header_area_listener;
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
+}
+
diff --git a/source/blender/editors/space_script/Makefile b/source/blender/editors/space_script/Makefile
new file mode 100644
index 00000000000..48e1cd8e861
--- /dev/null
+++ b/source/blender/editors/space_script/Makefile
@@ -0,0 +1,54 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_script
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/space_script/SConscript b/source/blender/editors/space_script/SConscript
new file mode 100644
index 00000000000..a78f1a66762
--- /dev/null
+++ b/source/blender/editors/space_script/SConscript
@@ -0,0 +1,16 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' ../../makesrna'
+incs += ' ../../python'
+
+defs = []
+
+if not env['WITH_BF_PYTHON']:
+ defs.append('DISABLE_PYTHON')
+
+env.BlenderLib ( 'bf_editors_space_script', sources, Split(incs), defs, libtype=['core'], priority=[90] )
diff --git a/source/blender/editors/space_script/script_edit.c b/source/blender/editors/space_script/script_edit.c
new file mode 100644
index 00000000000..cc8764fd67d
--- /dev/null
+++ b/source/blender/editors/space_script/script_edit.c
@@ -0,0 +1,88 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_screen.h"
+#include "ED_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "script_intern.h" // own include
+
+
+#include "BPY_extern.h" /* BPY_run_python_script */
+
+static int run_pyfile_exec(bContext *C, wmOperator *op)
+{
+ ARegion *ar= CTX_wm_region(C);
+
+ char filename[512];
+ RNA_string_get(op->ptr, "filename", filename);
+#ifndef DISABLE_PYTHON
+ BPY_run_python_script(C, filename, NULL);
+#endif
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCRIPT_OT_python_file_run(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Run python file";
+ ot->idname= "SCRIPT_OT_python_file_run";
+
+ /* api callbacks */
+ ot->exec= run_pyfile_exec;
+ ot->poll= ED_operator_areaactive;
+
+ RNA_def_string_file_path(ot->srna, "filename", "", 512, "Filename", "");
+}
+
diff --git a/source/blender/editors/space_script/script_header.c b/source/blender/editors/space_script/script_header.c
new file mode 100644
index 00000000000..d9851df4185
--- /dev/null
+++ b/source/blender/editors/space_script/script_header.c
@@ -0,0 +1,130 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "script_intern.h"
+
+
+/* ************************ header area region *********************** */
+
+static void do_viewmenu(bContext *C, void *arg, int event)
+{
+
+}
+
+static uiBlock *dummy_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "dummy_viewmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_viewmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static void do_script_buttons(bContext *C, void *arg, int event)
+{
+ switch(event) {
+ }
+}
+
+
+void script_header_buttons(const bContext *C, ARegion *ar)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ uiBlock *block;
+ int xco, yco= 3;
+
+ block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_script_buttons, NULL);
+
+ xco= ED_area_header_standardbuttons(C, block, yco);
+
+ if((sa->flag & HEADER_NO_PULLDOWN)==0) {
+ int xmax;
+
+ xmax= GetButStringLength("View");
+ uiDefPulldownBut(block, dummy_viewmenu, CTX_wm_area(C),
+ "View", xco, yco-2, xmax-3, 24, "");
+ xco+=XIC+xmax;
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ /* always as last */
+ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+}
+
+
diff --git a/source/blender/editors/space_script/script_intern.h b/source/blender/editors/space_script/script_intern.h
new file mode 100644
index 00000000000..e39dd168e71
--- /dev/null
+++ b/source/blender/editors/space_script/script_intern.h
@@ -0,0 +1,45 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_SCRIPT_INTERN_H
+#define ED_SCRIPT_INTERN_H
+
+/* internal exports only */
+
+
+/* script_header.c */
+void script_header_buttons(const bContext *C, ARegion *ar);
+
+/* script_ops.c */
+void script_operatortypes(void);
+void script_keymap(struct wmWindowManager *wm);
+
+/* script_edit.c */
+void SCRIPT_OT_python_file_run(struct wmOperatorType *ot);
+
+#endif /* ED_SCRIPT_INTERN_H */
+
diff --git a/source/blender/editors/space_script/script_ops.c b/source/blender/editors/space_script/script_ops.c
new file mode 100644
index 00000000000..d2aa9959a9d
--- /dev/null
+++ b/source/blender/editors/space_script/script_ops.c
@@ -0,0 +1,72 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+
+#include "script_intern.h"
+
+
+/* ************************** registration **********************************/
+
+void script_operatortypes(void)
+{
+ WM_operatortype_append(SCRIPT_OT_python_file_run);
+}
+
+void script_keymap(wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "Script", SPACE_SCRIPT, 0);
+
+ /* TODO - this is just while we have no way to load a text datablock */
+ RNA_string_set(WM_keymap_add_item(keymap, "SCRIPT_OT_python_file_run", PKEY, KM_PRESS, 0, 0)->ptr, "filename", "test.py");
+}
+
diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c
new file mode 100644
index 00000000000..4c17ed16475
--- /dev/null
+++ b/source/blender/editors/space_script/space_script.c
@@ -0,0 +1,249 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_markers.h"
+
+#include "BPY_extern.h"
+
+#include "script_intern.h" // own include
+
+
+//static script_run_python(char *funcname, )
+
+
+/* ******************** default callbacks for script space ***************** */
+
+static SpaceLink *script_new(const bContext *C)
+{
+ ARegion *ar;
+ SpaceScript *sscript;
+
+ sscript= MEM_callocN(sizeof(SpaceScript), "initscript");
+ sscript->spacetype= SPACE_SCRIPT;
+
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for script");
+
+ BLI_addtail(&sscript->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_BOTTOM;
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for script");
+
+ BLI_addtail(&sscript->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+
+ /* channel list region XXX */
+
+
+ return (SpaceLink *)sscript;
+}
+
+/* not spacelink itself */
+static void script_free(SpaceLink *sl)
+{
+ SpaceScript *sscript= (SpaceScript*) sl;
+
+#ifndef DISABLE_PYTHON
+ /*free buttons references*/
+ if (sscript->but_refs) {
+// XXX BPy_Set_DrawButtonsList(sscript->but_refs);
+// BPy_Free_DrawButtonsList();
+ sscript->but_refs = NULL;
+ }
+#endif
+ sscript->script = NULL;
+}
+
+
+/* spacetype; init callback */
+static void script_init(struct wmWindowManager *wm, ScrArea *sa)
+{
+
+}
+
+static SpaceLink *script_duplicate(SpaceLink *sl)
+{
+ SpaceScript *sscriptn= MEM_dupallocN(sl);
+
+ /* clear or remove stuff from old */
+
+ return (SpaceLink *)sscriptn;
+}
+
+
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void script_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "Script", SPACE_SCRIPT, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+static void script_main_area_draw(const bContext *C, ARegion *ar)
+{
+ /* draw entirely, view changes should be handled here */
+ SpaceScript *sscript= (SpaceScript*)CTX_wm_space_data(C);
+ View2D *v2d= &ar->v2d;
+ float col[3];
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ UI_view2d_view_ortho(C, v2d);
+
+ /* data... */
+ // BPY_run_python_script(C, "/root/blender-svn/blender25/test.py", NULL);
+
+#ifndef DISABLE_PYTHON
+ if (sscript->script) {
+ //BPY_run_python_script_space(scpt->script.filename, NULL);
+ BPY_run_script_space_draw(C, sscript);
+ }
+#endif
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers? */
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void script_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+}
+
+static void script_header_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ /* clear */
+ if(ED_screen_area_active(C))
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ else
+ UI_GetThemeColor3fv(TH_HEADERDESEL, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ script_header_buttons(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+static void script_main_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ // XXX - Todo, need the ScriptSpace accessible to get the python script to run.
+ // BPY_run_script_space_listener()
+}
+
+/* only called once, from space/spacetypes.c */
+void ED_spacetype_script(void)
+{
+ SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype script");
+ ARegionType *art;
+
+ st->spaceid= SPACE_SCRIPT;
+
+ st->new= script_new;
+ st->free= script_free;
+ st->init= script_init;
+ st->duplicate= script_duplicate;
+ st->operatortypes= script_operatortypes;
+ st->keymap= script_keymap;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype script region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init= script_main_area_init;
+ art->draw= script_main_area_draw;
+ art->listener= script_main_area_listener;
+ art->keymapflag= ED_KEYMAP_VIEW2D| ED_KEYMAP_UI|ED_KEYMAP_FRAMES; // XXX need to further test this ED_KEYMAP_UI is needed for button interaction
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype script region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+
+ art->init= script_header_area_init;
+ art->draw= script_header_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+
+ BKE_spacetype_register(st);
+}
+
diff --git a/source/blender/editors/space_sequencer/Makefile b/source/blender/editors/space_sequencer/Makefile
new file mode 100644
index 00000000000..c04202cba73
--- /dev/null
+++ b/source/blender/editors/space_sequencer/Makefile
@@ -0,0 +1,56 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_sequencer
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+CPPFLAGS += -I$(NAN_BMFONT)/include
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/space_sequencer/SConscript b/source/blender/editors/space_sequencer/SConscript
new file mode 100644
index 00000000000..1794ef29257
--- /dev/null
+++ b/source/blender/editors/space_sequencer/SConscript
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' #intern/bmfont ../../makesrna'
+
+env.BlenderLib ( 'bf_editors_space_sequencer', sources, Split(incs), [], libtype=['core'], priority=[100] )
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
new file mode 100644
index 00000000000..6e38ff053be
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -0,0 +1,644 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2003-2009, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+#include <sys/types.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_storage_types.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_ipo_types.h"
+#include "DNA_curve_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 "DNA_sound_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_plugin_types.h"
+#include "BKE_sequence.h"
+#include "BKE_scene.h"
+#include "BKE_utildefines.h"
+#include "BKE_report.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+/* for menu/popup icons etc etc*/
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "ED_anim_api.h"
+#include "ED_space_api.h"
+#include "ED_types.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+#include "ED_fileselect.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+/* own include */
+#include "sequencer_intern.h"
+
+/* Generic functions, reused by add strip operators */
+
+/* avoid passing multiple args and be more verbose */
+#define SEQPROP_STARTFRAME 1<<0
+#define SEQPROP_ENDFRAME 1<<1
+#define SEQPROP_FILENAME 1<<2
+
+static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
+{
+ RNA_def_string(ot->srna, "name", "", MAX_ID_NAME-2, "Name", "Name of the new sequence strip");
+
+ if(flag & SEQPROP_STARTFRAME)
+ RNA_def_int(ot->srna, "start_frame", 0, INT_MIN, INT_MAX, "Start Frame", "Start frame of the sequence strip", INT_MIN, INT_MAX);
+
+ if(flag & SEQPROP_ENDFRAME)
+ RNA_def_int(ot->srna, "end_frame", 0, INT_MIN, INT_MAX, "End Frame", "End frame for the color strip", INT_MIN, INT_MAX); /* not useual since most strips have a fixed length */
+
+ RNA_def_int(ot->srna, "channel", 1, 1, MAXSEQ, "Channel", "Channel to place this strip into", 1, MAXSEQ);
+
+ if(flag & SEQPROP_FILENAME)
+ RNA_def_string(ot->srna, "filename", "", FILE_MAX, "Scene Name", "full path to load the strip data from");
+
+ RNA_def_boolean(ot->srna, "replace_sel", 1, "Replace Selection", "replace the current selection");
+}
+
+static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, wmEvent *event, int flag)
+{
+ ARegion *ar= CTX_wm_region(C);
+ View2D *v2d= UI_view2d_fromcontext(C);
+
+ short mval[2];
+ float mval_v2d[2];
+
+
+ mval[0]= event->x - ar->winrct.xmin;
+ mval[1]= event->y - ar->winrct.ymin;
+
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &mval_v2d[0], &mval_v2d[1]);
+
+ RNA_int_set(op->ptr, "channel", (int)mval_v2d[1]+0.5f);
+ RNA_int_set(op->ptr, "start_frame", (int)mval_v2d[0]);
+
+ if ((flag & SEQPROP_ENDFRAME) && RNA_property_is_set(op->ptr, "end_frame")==0)
+ RNA_int_set(op->ptr, "end_frame", (int)mval_v2d[0] + 25); // XXX arbitary but ok for now.
+
+}
+
+/* add scene operator */
+static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, TRUE);
+
+ Scene *sce_seq;
+ char sce_name[MAX_ID_NAME-2];
+
+ Sequence *seq; /* generic strip vars */
+ Strip *strip;
+ StripElem *se;
+
+ int start_frame, channel; /* operator props */
+
+ start_frame= RNA_int_get(op->ptr, "start_frame");
+ channel= RNA_int_get(op->ptr, "channel");
+
+ RNA_string_get(op->ptr, "scene", sce_name);
+
+ sce_seq= (Scene *)find_id("SC", sce_name);
+
+ if (sce_seq==NULL) {
+ BKE_reportf(op->reports, RPT_ERROR, "Scene \"%s\" not found", sce_name);
+ return OPERATOR_CANCELLED;
+ }
+
+ seq = alloc_sequence(ed->seqbasep, start_frame, channel);
+
+ seq->type= SEQ_SCENE;
+ seq->scene= sce_seq;
+
+ /* basic defaults */
+ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+ strip->len = seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1;
+ strip->us= 1;
+
+ strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+
+
+ RNA_string_get(op->ptr, "name", seq->name);
+
+ calc_sequence_disp(seq);
+ sort_seq(scene);
+
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ deselect_all_seq(scene);
+ set_last_seq(scene, seq);
+ seq->flag |= SELECT;
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+
+static int sequencer_add_scene_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sequencer_generic_invoke_xy__internal(C, op, event, 0);
+
+ /* scene can be left default */
+ RNA_string_set(op->ptr, "scene", "Scene"); // XXX should popup a menu but ton says 2.5 will have some better feature for this
+
+ return sequencer_add_scene_strip_exec(C, op);
+}
+
+
+void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Add Scene Strip";
+ ot->idname= "SEQUENCER_OT_scene_strip_add";
+ ot->description= "Add a strip to the sequencer using a blender scene as a source";
+
+ /* api callbacks */
+ ot->invoke= sequencer_add_scene_strip_invoke;
+ ot->exec= sequencer_add_scene_strip_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
+ RNA_def_string(ot->srna, "scene", "", MAX_ID_NAME-2, "Scene Name", "Scene name to add as a strip");
+}
+
+/* add movie operator */
+static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, TRUE);
+
+ struct anim *an;
+ char filename[FILE_MAX];
+
+ Sequence *seq; /* generic strip vars */
+ Strip *strip;
+ StripElem *se;
+
+ int start_frame, channel; /* operator props */
+
+ start_frame= RNA_int_get(op->ptr, "start_frame");
+ channel= RNA_int_get(op->ptr, "channel");
+
+ RNA_string_get(op->ptr, "filename", filename);
+
+ an = openanim(filename, IB_rect);
+
+ if (an==NULL) {
+ BKE_reportf(op->reports, RPT_ERROR, "Filename \"%s\" could not be loaded as a movie", filename);
+ return OPERATOR_CANCELLED;
+ }
+
+ seq = alloc_sequence(ed->seqbasep, start_frame, channel);
+
+ seq->type= SEQ_MOVIE;
+ seq->anim= an;
+ seq->anim_preseek = IMB_anim_get_preseek(an);
+
+ /* basic defaults */
+ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+ strip->len = seq->len = IMB_anim_get_duration( an );
+ strip->us= 1;
+
+ strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+
+ BLI_split_dirfile_basic(filename, strip->dir, se->name);
+
+ RNA_string_get(op->ptr, "name", seq->name);
+
+ calc_sequence_disp(seq);
+ sort_seq(scene);
+
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ deselect_all_seq(scene);
+ set_last_seq(scene, seq);
+ seq->flag |= SELECT;
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+
+static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sequencer_generic_invoke_xy__internal(C, op, event, 0);
+ return WM_operator_filesel(C, op, event);
+ //return sequencer_add_movie_strip_exec(C, op);
+}
+
+
+void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Add Movie Strip";
+ ot->idname= "SEQUENCER_OT_movie_strip_add";
+ ot->description= "Add a movie strip to the sequencer";
+
+ /* api callbacks */
+ ot->invoke= sequencer_add_movie_strip_invoke;
+ ot->exec= sequencer_add_movie_strip_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_FILENAME);
+ RNA_def_boolean(ot->srna, "sound", FALSE, "Sound", "Load hd sound with the movie"); // XXX need to impliment this
+}
+
+
+/* add sound operator */
+static int sequencer_add_sound_strip_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, TRUE);
+
+ bSound *sound;
+
+ char filename[FILE_MAX];
+
+ Sequence *seq; /* generic strip vars */
+ Strip *strip;
+ StripElem *se;
+
+ int start_frame, channel; /* operator props */
+
+ start_frame= RNA_int_get(op->ptr, "start_frame");
+ channel= RNA_int_get(op->ptr, "channel");
+
+ RNA_string_get(op->ptr, "filename", filename);
+
+// XXX sound= sound_new_sound(filename);
+ sound= NULL;
+
+ if (sound==NULL || sound->sample->type == SAMPLE_INVALID) {
+ BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (sound==NULL || sound->sample->bits != 16) {
+ BKE_report(op->reports, RPT_ERROR, "Only 16 bit audio is supported");
+ return OPERATOR_CANCELLED;
+ }
+
+ sound->flags |= SOUND_FLAGS_SEQUENCE;
+// XXX audio_makestream(sound);
+
+ seq = alloc_sequence(ed->seqbasep, start_frame, channel);
+
+ seq->type= SEQ_RAM_SOUND;
+ seq->sound= sound;
+
+ /* basic defaults */
+ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+ strip->len = seq->len = (int) ( ((float)(sound->streamlen-1) / ( (float)scene->r.audio.mixrate*4.0 ))* FPS);
+ strip->us= 1;
+
+ strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+
+ BLI_split_dirfile_basic(filename, strip->dir, se->name);
+
+ RNA_string_get(op->ptr, "name", seq->name);
+
+ calc_sequence_disp(seq);
+ sort_seq(scene);
+
+ /* last active name */
+ strncpy(ed->act_sounddir, strip->dir, FILE_MAXDIR-1);
+
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ deselect_all_seq(scene);
+ set_last_seq(scene, seq);
+ seq->flag |= SELECT;
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+
+static int sequencer_add_sound_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sequencer_generic_invoke_xy__internal(C, op, event, 0);
+ return WM_operator_filesel(C, op, event);
+ //return sequencer_add_sound_strip_exec(C, op);
+}
+
+
+void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Add Sound Strip";
+ ot->idname= "SEQUENCER_OT_sound_strip_add";
+ ot->description= "Add a sound strip to the sequencer";
+
+ /* api callbacks */
+ ot->invoke= sequencer_add_sound_strip_invoke;
+ ot->exec= sequencer_add_sound_strip_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_FILENAME);
+ RNA_def_boolean(ot->srna, "hd", FALSE, "HD Sound", "Load the sound as streaming audio"); // XXX need to impliment this
+}
+
+/* add image operator */
+static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, TRUE);
+
+
+ int tot_images= 1; //XXX FIXME, we need string arrays!
+ //int a;
+
+ char filename[FILE_MAX];
+
+ Sequence *seq; /* generic strip vars */
+ Strip *strip;
+ StripElem *se;
+
+ int start_frame, channel; /* operator props */
+
+ start_frame= RNA_int_get(op->ptr, "start_frame");
+ channel= RNA_int_get(op->ptr, "channel");
+
+ RNA_string_get(op->ptr, "filename", filename);
+
+ seq = alloc_sequence(ed->seqbasep, start_frame, channel);
+
+ seq->type= SEQ_IMAGE;
+
+ /* basic defaults */
+ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+ strip->len = seq->len = tot_images;
+ strip->us= 1;
+
+ strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+
+
+ BLI_split_dirfile_basic(filename, strip->dir, se->name); // XXX se->name assignment should be moved into the loop below
+
+#if 0 // XXX
+ for(a=0; a<seq->len; a++) {
+ strncpy(se->name, name, FILE_MAXFILE-1);
+ se++;
+ }
+#endif
+
+ RNA_string_get(op->ptr, "name", seq->name);
+
+ calc_sequence_disp(seq);
+ sort_seq(scene);
+
+ /* last active name */
+ strncpy(ed->act_imagedir, strip->dir, FILE_MAXDIR-1);
+
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ deselect_all_seq(scene);
+ set_last_seq(scene, seq);
+ seq->flag |= SELECT;
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+
+static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sequencer_generic_invoke_xy__internal(C, op, event, 0);
+ return WM_operator_filesel(C, op, event);
+ //return sequencer_add_image_strip_exec(C, op);
+}
+
+
+void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Add Image Strip";
+ ot->idname= "SEQUENCER_OT_image_strip_add";
+ ot->description= "Add an image or image sequence to the sequencer";
+
+ /* api callbacks */
+ ot->invoke= sequencer_add_image_strip_invoke;
+ ot->exec= sequencer_add_image_strip_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_FILENAME);
+}
+
+
+/* add_effect_strip operator */
+static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, TRUE);
+
+ Sequence *seq; /* generic strip vars */
+ Strip *strip;
+ StripElem *se;
+ struct SeqEffectHandle sh;
+
+ int start_frame, end_frame, channel, type; /* operator props */
+
+ Sequence *seq1, *seq2, *seq3;
+ char *error_msg;
+
+ start_frame= RNA_int_get(op->ptr, "start_frame");
+ end_frame= RNA_int_get(op->ptr, "end_frame");
+ channel= RNA_int_get(op->ptr, "channel");
+
+ type= RNA_enum_get(op->ptr, "type");
+
+ // XXX We need unique names and move to invoke
+ if(!seq_effect_find_selected(scene, NULL, type, &seq1, &seq2, &seq3, &error_msg)) {
+ BKE_report(op->reports, RPT_ERROR, error_msg);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* If seq1 is NULL and no error was rasied it means the seq is standalone
+ * (like color strips) and we need to check its start and end frames are valid */
+ if (seq1==NULL && end_frame <= start_frame) {
+ BKE_report(op->reports, RPT_ERROR, "Start and end frame are not set");
+ return OPERATOR_CANCELLED;
+ }
+
+ seq = alloc_sequence(ed->seqbasep, start_frame, channel);
+ seq->type= type;
+
+ sh = get_sequence_effect(seq);
+
+ seq->seq1= seq1;
+ seq->seq2= seq2;
+ seq->seq3= seq3;
+
+ sh.init(seq);
+
+ if (!seq1) { /* effect has no deps */
+ seq->len= 1;
+ seq_tx_set_final_right(seq, end_frame);
+ }
+
+ calc_sequence(seq);
+
+ /* basic defaults */
+ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+ strip->len = seq->len;
+ strip->us= 1;
+ if(seq->len>0)
+ strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+
+ if (seq->type==SEQ_PLUGIN) {
+ char filename[FILE_MAX];
+ RNA_string_get(op->ptr, "filename", filename);
+
+ sh.init_plugin(seq, filename);
+
+ if(seq->plugin==NULL) {
+ BLI_remlink(ed->seqbasep, seq);
+ seq_free_sequence(ed, seq);
+ BKE_reportf(op->reports, RPT_ERROR, "Sequencer plugin \"%s\" could not load.", filename);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else if (seq->type==SEQ_COLOR) {
+ SolidColorVars *colvars= (SolidColorVars *)seq->effectdata;
+ RNA_float_get_array(op->ptr, "color", colvars->col);
+ }
+
+ if(seq_test_overlap(ed->seqbasep, seq)) shuffle_seq(ed->seqbasep, seq);
+
+ update_changed_seq_and_deps(scene, seq, 1, 1); /* runs calc_sequence */
+
+
+ /* not sure if this is needed with update_changed_seq_and_deps.
+ * it was NOT called in blender 2.4x, but wont hurt */
+ sort_seq(scene);
+
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ deselect_all_seq(scene);
+ set_last_seq(scene, seq);
+ seq->flag |= SELECT;
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return OPERATOR_FINISHED;
+}
+
+
+/* add color */
+static int sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_ENDFRAME);
+
+ if (RNA_property_is_set(op->ptr, "type") && RNA_enum_get(op->ptr, "type")==SEQ_PLUGIN) {
+ /* only plugins need the file selector */
+ return WM_operator_filesel(C, op, event);
+ }
+ else {
+ return sequencer_add_effect_strip_exec(C, op);
+ }
+}
+
+void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Effect Strip";
+ ot->idname= "SEQUENCER_OT_effect_strip_add";
+ ot->description= "Add an effect to the sequencer, most are applied ontop of existing strips";
+
+ /* api callbacks */
+ ot->invoke= sequencer_add_effect_strip_invoke;
+ ot->exec= sequencer_add_effect_strip_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_ENDFRAME|SEQPROP_FILENAME);
+ RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_CROSS, "Type", "Sequencer effect type");
+ RNA_def_float_vector(ot->srna, "color", 3, NULL, 0.0f, 1.0f, "Color", "Initialize the strip with this color (only used when type='COLOR')", 0.0f, 1.0f);
+}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
new file mode 100644
index 00000000000..e71abec8e4b
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -0,0 +1,1096 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2003-2009
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "DNA_gpencil_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 "DNA_userdef_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_plugin_types.h"
+#include "BKE_sequence.h"
+#include "BKE_scene.h"
+#include "BKE_utildefines.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "ED_anim_api.h"
+#include "ED_space_api.h"
+#include "ED_sequencer.h"
+#include "ED_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+/* own include */
+#include "sequencer_intern.h"
+
+#define SEQ_LEFTHANDLE 1
+#define SEQ_RIGHTHANDLE 2
+
+/* Note, Dont use WHILE_SEQ while drawing! - it messes up transform, - Campbell */
+
+int no_rightbox=0, no_leftbox= 0;
+static void draw_shadedstrip(Sequence *seq, char *col, float x1, float y1, float x2, float y2);
+
+
+static void draw_cfra_seq(View2D *v2d, int cfra)
+{
+ glColor3ub(0x30, 0x90, 0x50);
+ glLineWidth(2.0);
+ glBegin(GL_LINES);
+ glVertex2f(cfra, v2d->cur.ymin);
+ glVertex2f(cfra, v2d->cur.ymax);
+ glEnd();
+ glLineWidth(1.0);
+}
+
+static void get_seq_color3ubv(Scene *curscene, Sequence *seq, char *col)
+{
+ char blendcol[3];
+ float hsv[3], rgb[3];
+ SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
+
+ switch(seq->type) {
+ case SEQ_IMAGE:
+ UI_GetThemeColor3ubv(TH_SEQ_IMAGE, col);
+ break;
+ case SEQ_META:
+ UI_GetThemeColor3ubv(TH_SEQ_META, col);
+ break;
+ case SEQ_MOVIE:
+ UI_GetThemeColor3ubv(TH_SEQ_MOVIE, col);
+ break;
+ case SEQ_SCENE:
+ UI_GetThemeColor3ubv(TH_SEQ_SCENE, col);
+
+ if(seq->scene==curscene) {
+ UI_GetColorPtrBlendShade3ubv(col, col, col, 1.0, 20);
+ }
+ break;
+
+ /* transitions */
+ case SEQ_CROSS:
+ case SEQ_GAMCROSS:
+ case SEQ_WIPE:
+ /* slightly offset hue to distinguish different effects */
+ UI_GetThemeColor3ubv(TH_SEQ_TRANSITION, col);
+
+ rgb[0] = col[0]/255.0; rgb[1] = col[1]/255.0; rgb[2] = col[2]/255.0;
+ rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
+
+ if (seq->type == SEQ_CROSS) hsv[0]+= 0.04;
+ if (seq->type == SEQ_GAMCROSS) hsv[0]+= 0.08;
+ if (seq->type == SEQ_WIPE) hsv[0]+= 0.12;
+
+ if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
+ hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
+ col[0] = (char)(rgb[0]*255); col[1] = (char)(rgb[1]*255); col[2] = (char)(rgb[2]*255);
+ break;
+
+ /* effects */
+ case SEQ_TRANSFORM:
+ case SEQ_SPEED:
+ case SEQ_ADD:
+ case SEQ_SUB:
+ case SEQ_MUL:
+ case SEQ_ALPHAOVER:
+ case SEQ_ALPHAUNDER:
+ case SEQ_OVERDROP:
+ case SEQ_GLOW:
+ /* slightly offset hue to distinguish different effects */
+ UI_GetThemeColor3ubv(TH_SEQ_EFFECT, col);
+
+ rgb[0] = col[0]/255.0; rgb[1] = col[1]/255.0; rgb[2] = col[2]/255.0;
+ rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
+
+ if (seq->type == SEQ_ADD) hsv[0]+= 0.04;
+ if (seq->type == SEQ_SUB) hsv[0]+= 0.08;
+ if (seq->type == SEQ_MUL) hsv[0]+= 0.12;
+ if (seq->type == SEQ_ALPHAOVER) hsv[0]+= 0.16;
+ if (seq->type == SEQ_ALPHAUNDER) hsv[0]+= 0.20;
+ if (seq->type == SEQ_OVERDROP) hsv[0]+= 0.24;
+ if (seq->type == SEQ_GLOW) hsv[0]+= 0.28;
+ if (seq->type == SEQ_TRANSFORM) hsv[0]+= 0.36;
+
+ if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
+ hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
+ col[0] = (char)(rgb[0]*255); col[1] = (char)(rgb[1]*255); col[2] = (char)(rgb[2]*255);
+ break;
+ case SEQ_COLOR:
+ if (colvars->col) {
+ col[0]= (char)(colvars->col[0]*255);
+ col[1]= (char)(colvars->col[1]*255);
+ col[2]= (char)(colvars->col[2]*255);
+ } else {
+ col[0] = col[1] = col[2] = 128;
+ }
+ break;
+ case SEQ_PLUGIN:
+ UI_GetThemeColor3ubv(TH_SEQ_PLUGIN, col);
+ break;
+ case SEQ_HD_SOUND:
+ case SEQ_RAM_SOUND:
+ UI_GetThemeColor3ubv(TH_SEQ_AUDIO, col);
+ blendcol[0] = blendcol[1] = blendcol[2] = 128;
+ if(seq->flag & SEQ_MUTE) UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.5, 20);
+ break;
+ default:
+ col[0] = 10; col[1] = 255; col[2] = 40;
+ }
+}
+
+static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, float x2, float y2)
+{
+ /* Note, this used to use WHILE_SEQ, but it messes up the seq->depth value, (needed by transform when doing overlap checks)
+ * so for now, just use the meta's immediate children, could be fixed but its only drawing - Campbell */
+ Sequence *seq;
+ float dx;
+ int nr;
+ char col[3];
+
+ nr= BLI_countlist(&seqm->seqbase);
+
+ dx= (x2-x1)/nr;
+
+ if (seqm->flag & SEQ_MUTE) {
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(stipple_halftone);
+
+ glEnable(GL_LINE_STIPPLE);
+ glLineStipple(1, 0x8888);
+ }
+
+ for (seq= seqm->seqbase.first; seq; seq= seq->next) {
+ get_seq_color3ubv(scene, seq, col);
+
+ glColor3ubv((GLubyte *)col);
+
+ glRectf(x1, y1, x1+0.9*dx, y2);
+
+ UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -30);
+ glColor3ubv((GLubyte *)col);
+
+ fdrawbox(x1, y1, x1+0.9*dx, y2);
+
+ x1+= dx;
+ }
+
+ if (seqm->flag & SEQ_MUTE) {
+ glDisable(GL_POLYGON_STIPPLE);
+ glDisable(GL_LINE_STIPPLE);
+ }
+}
+
+static void drawseqwave(Scene *scene, View2D *v2d, Sequence *seq, float x1, float y1, float x2, float y2, int winx)
+{
+ /*
+ x1 is the starting x value to draw the wave,
+ x2 the end x value, same for y1 and y2
+ winx is the zoom level.
+ */
+
+ float
+ f, /* floating point value used to store the X draw location for the wave lines when openGL drawing*/
+ midy, /* fast access to the middle location (y1+y2)/2 */
+ clipxmin, /* the minimum X value, clip this with the window */
+ clipxmax, /* the maximum X value, clip this with the window */
+ sample_step, /* steps to move per sample, floating value must later translate into an int */
+ fsofs, /* steps to move per sample, floating value must later translate into an int */
+ feofs_sofs, /* */
+ sound_width, /* convenience: x2-x1 */
+ wavemulti; /* scale the samples by this value when GL_LINE drawing so it renders the right height */
+
+ int
+ offset, /* initial offset value for the wave drawing */
+ offset_next, /* when in the wave drawing loop this value is the samples intil the next vert */
+ sofs, /* Constrained offset value (~3) for the wave, start */
+ eofs, /* ditto, end */
+ wavesample, /* inner loop storage if the current wave sample value, used to make the 2 values below */
+ wavesamplemin, /* used for finding the min and max wave peaks */
+ wavesamplemax, /* ditto */
+ subsample_step=4; /* when the sample step is 4 every sample of
+ the wave is evaluated for min and max values used to draw the wave,
+ however this is slow ehrn zoomed out so when the sample step is above
+ 1 (the larger the further out the zoom is) so not evaluate all samples, only some. */
+
+ signed short* s;
+ bSound *sound;
+ uint8_t *stream;
+
+// XXX audio_makestream(seq->sound);
+ if(seq->sound==NULL || seq->sound->stream==NULL) return;
+
+ if (seq->flag & SEQ_MUTE) glColor3ub(0x70, 0x80, 0x80); else glColor3ub(0x70, 0xc0, 0xc0);
+
+ sofs = ((int)( FRA2TIME(seq->startdisp-seq->start+seq->anim_startofs)*(float)scene->r.audio.mixrate*4.0 )) & (~3);
+ eofs = ((int)( FRA2TIME(seq->enddisp-seq->start+seq->anim_startofs)*(float)scene->r.audio.mixrate*4.0 )) & (~3);
+
+ /* clip the drawing area to the screen bounds to save time */
+ sample_step= (v2d->cur.xmax - v2d->cur.xmin)/winx;
+ clipxmin= MAX2(x1, v2d->cur.xmin);
+ clipxmax= MIN2(x2, v2d->cur.xmax);
+
+ if (sample_step > 1)
+ subsample_step= ((int)(subsample_step*sample_step*8)) & (~3);
+
+ /* for speedy access */
+ midy = (y1+y2)/2;
+ fsofs= (float)sofs;
+ feofs_sofs= (float)(eofs-sofs);
+ sound_width= x2-x1;
+ sound = seq->sound;
+ stream = sound->stream;
+ wavemulti = (y2-y1)/196605; /*y2-y1 is the height*/
+ wavesample=0;
+
+ /* we need to get the starting offset value, excuse the duplicate code */
+ f=clipxmin;
+ offset= (int) (fsofs + ((f-x1)/sound_width) * feofs_sofs) & (~3);
+
+ /* start the loop, draw a line per sample_step -sample_step is about 1 line drawn per pixel */
+ glBegin(GL_LINES);
+ for (f=x1+sample_step; f<=clipxmax; f+=sample_step) {
+
+ offset_next = (int) (fsofs + ((f-x1)/sound_width) * feofs_sofs) & (~3);
+ if (f > v2d->cur.xmin) {
+ /* if this is close to the last sample just exit */
+ if (offset_next >= sound->streamlen) break;
+
+ wavesamplemin = 131070;
+ wavesamplemax = -131070;
+
+ /*find with high and low of the waveform for this draw,
+ evaluate small samples to find this range */
+ while (offset < offset_next) {
+ s = (signed short*)(stream+offset);
+
+ wavesample = s[0]*2 + s[1];
+ if (wavesamplemin>wavesample)
+ wavesamplemin=wavesample;
+ if (wavesamplemax<wavesample)
+ wavesamplemax=wavesample;
+ offset+=subsample_step;
+ }
+ /* draw the wave line, looks good up close and zoomed out */
+ glVertex2f(f, midy-(wavemulti*wavesamplemin) );
+ glVertex2f(f, midy-(wavemulti*wavesamplemax) );
+ } else {
+ while (offset < offset_next) offset+=subsample_step;
+ }
+
+ offset=offset_next;
+ }
+ glEnd();
+}
+
+/* draw a handle, for each end of a sequence strip */
+static void draw_seq_handle(SpaceSeq *sseq, Sequence *seq, float pixelx, short direction)
+{
+ float v1[2], v2[2], v3[2], rx1=0, rx2=0; //for triangles and rect
+ float x1, x2, y1, y2;
+ float handsize;
+ float minhandle, maxhandle;
+ char str[32];
+ unsigned int whichsel=0;
+ View2D *v2d;
+
+ x1= seq->startdisp;
+ x2= seq->enddisp;
+
+ y1= seq->machine+SEQ_STRIP_OFSBOTTOM;
+ y2= seq->machine+SEQ_STRIP_OFSTOP;
+
+ v2d = &sseq->v2d;
+
+ /* clamp handles to defined size in pixel space */
+ handsize = seq->handsize;
+ minhandle = 7;
+ maxhandle = 40;
+ CLAMP(handsize, minhandle*pixelx, maxhandle*pixelx);
+
+ /* set up co-ordinates/dimensions for either left or right handle */
+ if (direction == SEQ_LEFTHANDLE) {
+ rx1 = x1;
+ rx2 = x1+handsize*0.75;
+
+ v1[0]= x1+handsize/4; v1[1]= y1+( ((y1+y2)/2.0 - y1)/2);
+ v2[0]= x1+handsize/4; v2[1]= y2-( ((y1+y2)/2.0 - y1)/2);
+ v3[0]= v2[0] + handsize/4; v3[1]= (y1+y2)/2.0;
+
+ whichsel = SEQ_LEFTSEL;
+ } else if (direction == SEQ_RIGHTHANDLE) {
+ rx1 = x2-handsize*0.75;
+ rx2 = x2;
+
+ v1[0]= x2-handsize/4; v1[1]= y1+( ((y1+y2)/2.0 - y1)/2);
+ v2[0]= x2-handsize/4; v2[1]= y2-( ((y1+y2)/2.0 - y1)/2);
+ v3[0]= v2[0] - handsize/4; v3[1]= (y1+y2)/2.0;
+
+ whichsel = SEQ_RIGHTSEL;
+ }
+
+ /* draw! */
+ if(seq->type < SEQ_EFFECT ||
+ get_sequence_effect_num_inputs(seq->type) == 0) {
+ glEnable( GL_BLEND );
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ if(seq->flag & whichsel) glColor4ub(0, 0, 0, 80);
+ else if (seq->flag & SELECT) glColor4ub(255, 255, 255, 30);
+ else glColor4ub(0, 0, 0, 22);
+
+ glRectf(rx1, y1, rx2, y2);
+
+ if(seq->flag & whichsel) glColor4ub(255, 255, 255, 200);
+ else glColor4ub(0, 0, 0, 50);
+
+ glEnable( GL_POLYGON_SMOOTH );
+ glBegin(GL_TRIANGLES);
+ glVertex2fv(v1); glVertex2fv(v2); glVertex2fv(v3);
+ glEnd();
+
+ glDisable( GL_POLYGON_SMOOTH );
+ glDisable( GL_BLEND );
+ }
+
+ if(G.moving || (seq->flag & whichsel)) {
+ cpack(0xFFFFFF);
+ if (direction == SEQ_LEFTHANDLE) {
+ sprintf(str, "%d", seq->startdisp);
+ glRasterPos3f(rx1, y1-0.15, 0.0);
+ } else {
+ sprintf(str, "%d", seq->enddisp - 1);
+ glRasterPos3f((x2-BMF_GetStringWidth(G.fonts, str)*pixelx), y2+0.05, 0.0);
+ }
+ BMF_DrawString(G.fonts, str);
+ }
+}
+
+static void draw_seq_extensions(Scene *scene, SpaceSeq *sseq, Sequence *seq)
+{
+ float x1, x2, y1, y2, pixely, a;
+ char col[3], blendcol[3];
+ View2D *v2d;
+
+ if(seq->type >= SEQ_EFFECT) return;
+
+ x1= seq->startdisp;
+ x2= seq->enddisp;
+
+ y1= seq->machine+SEQ_STRIP_OFSBOTTOM;
+ y2= seq->machine+SEQ_STRIP_OFSTOP;
+
+ v2d = &sseq->v2d;
+ pixely = (v2d->cur.ymax - v2d->cur.ymin)/(v2d->mask.ymax - v2d->mask.ymin);
+
+ blendcol[0] = blendcol[1] = blendcol[2] = 120;
+
+ if(seq->startofs) {
+ glEnable( GL_BLEND );
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ get_seq_color3ubv(scene, seq, col);
+
+ if (seq->flag & SELECT) {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
+ glColor4ub(col[0], col[1], col[2], 170);
+ } else {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
+ glColor4ub(col[0], col[1], col[2], 110);
+ }
+
+ glRectf((float)(seq->start), y1-SEQ_STRIP_OFSBOTTOM, x1, y1);
+
+ if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
+ else glColor4ub(col[0], col[1], col[2], 160);
+
+ fdrawbox((float)(seq->start), y1-SEQ_STRIP_OFSBOTTOM, x1, y1); //outline
+
+ glDisable( GL_BLEND );
+ }
+ if(seq->endofs) {
+ glEnable( GL_BLEND );
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ get_seq_color3ubv(scene, seq, col);
+
+ if (seq->flag & SELECT) {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
+ glColor4ub(col[0], col[1], col[2], 170);
+ } else {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
+ glColor4ub(col[0], col[1], col[2], 110);
+ }
+
+ glRectf(x2, y2, (float)(seq->start+seq->len), y2+SEQ_STRIP_OFSBOTTOM);
+
+ if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
+ else glColor4ub(col[0], col[1], col[2], 160);
+
+ fdrawbox(x2, y2, (float)(seq->start+seq->len), y2+SEQ_STRIP_OFSBOTTOM); //outline
+
+ glDisable( GL_BLEND );
+ }
+ if(seq->startstill) {
+ get_seq_color3ubv(scene, seq, col);
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
+ glColor3ubv((GLubyte *)col);
+
+ draw_shadedstrip(seq, col, x1, y1, (float)(seq->start), y2);
+
+ /* feint pinstripes, helps see exactly which is extended and which isn't,
+ * especially when the extension is very small */
+ if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
+ else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -16);
+
+ glColor3ubv((GLubyte *)col);
+
+ for(a=y1; a< y2; a+= pixely*2.0 ) {
+ fdrawline(x1, a, (float)(seq->start), a);
+ }
+ }
+ if(seq->endstill) {
+ get_seq_color3ubv(scene, seq, col);
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
+ glColor3ubv((GLubyte *)col);
+
+ draw_shadedstrip(seq, col, (float)(seq->start+seq->len), y1, x2, y2);
+
+ /* feint pinstripes, helps see exactly which is extended and which isn't,
+ * especially when the extension is very small */
+ if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
+ else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -16);
+
+ glColor3ubv((GLubyte *)col);
+
+ for(a=y1; a< y2; a+= pixely*2.0 ) {
+ fdrawline((float)(seq->start+seq->len), a, x2, a);
+ }
+ }
+}
+
+/* draw info text on a sequence strip */
+static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float y1, float y2, char *background_col)
+{
+ float v1[2], v2[2];
+ int len, size;
+ char str[32 + FILE_MAXDIR+FILE_MAXFILE], *strp;
+ int mval[2];
+
+ v1[1]= y1;
+ v2[1]= y2;
+
+ v1[0]= x1;
+ UI_view2d_to_region_no_clip(v2d, v1[0], v1[1], mval, mval+1);
+ x1= mval[0];
+ v2[0]= x2;
+ UI_view2d_to_region_no_clip(v2d, v2[0], v2[1], mval, mval+1);
+ x2= mval[0];
+ size= x2-x1;
+
+ if(seq->name[2]) {
+ sprintf(str, "%d | %s: %s", seq->len, give_seqname(seq), seq->name+2);
+ }else{
+ 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_IMAGE) {
+ sprintf(str, "%d | %s%s", seq->len, seq->strip->dir, seq->strip->stripdata->name);
+ }
+ else if(seq->type & SEQ_EFFECT) {
+ int can_float = (seq->type != SEQ_PLUGIN)
+ || (seq->plugin && seq->plugin->version >= 4);
+
+ if(seq->seq3!=seq->seq2 && seq->seq1!=seq->seq3)
+ sprintf(str, "%d | %s: %d>%d (use %d)%s", seq->len, give_seqname(seq), seq->seq1->machine, seq->seq2->machine, seq->seq3->machine, can_float ? "" : " No float, upgrade plugin!");
+ else if (seq->seq1 && seq->seq2)
+ sprintf(str, "%d | %s: %d>%d%s", seq->len, give_seqname(seq), seq->seq1->machine, seq->seq2->machine, can_float ? "" : " No float, upgrade plugin!");
+ else
+ sprintf(str, "%d | %s", seq->len, give_seqname(seq));
+ }
+ else if (seq->type == SEQ_RAM_SOUND) {
+ sprintf(str, "%d | %s", seq->len, seq->strip->stripdata->name);
+ }
+ else if (seq->type == SEQ_HD_SOUND) {
+ sprintf(str, "%d | %s", seq->len, seq->strip->stripdata->name);
+ }
+ else if (seq->type == SEQ_MOVIE) {
+ 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;
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x1, &x2);
+
+ if(seq->flag & SELECT){
+ cpack(0xFFFFFF);
+ }else if ((((int)background_col[0] + (int)background_col[1] + (int)background_col[2]) / 3) < 50){
+ cpack(0x505050); /* use lighter text colour for dark background */
+ }else{
+ cpack(0);
+ }
+ glRasterPos3f(x1, y1+SEQ_STRIP_OFSBOTTOM, 0.0);
+ BMF_DrawString(G.font, strp);
+}
+
+/* draws a shaded strip, made from gradient + flat color + gradient */
+static void draw_shadedstrip(Sequence *seq, char *col, float x1, float y1, float x2, float y2)
+{
+ float ymid1, ymid2;
+
+ if (seq->flag & SEQ_MUTE) {
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(stipple_halftone);
+ }
+
+ ymid1 = (y2-y1)*0.25 + y1;
+ ymid2 = (y2-y1)*0.65 + y1;
+
+ glShadeModel(GL_SMOOTH);
+ glBegin(GL_QUADS);
+
+ if(seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -50);
+ else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 0);
+
+ glColor3ubv((GLubyte *)col);
+
+ glVertex2f(x1,y1);
+ glVertex2f(x2,y1);
+
+ if(seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 5);
+ else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -5);
+
+ glColor3ubv((GLubyte *)col);
+
+ glVertex2f(x2,ymid1);
+ glVertex2f(x1,ymid1);
+
+ glEnd();
+
+ glRectf(x1, ymid1, x2, ymid2);
+
+ glBegin(GL_QUADS);
+
+ glVertex2f(x1,ymid2);
+ glVertex2f(x2,ymid2);
+
+ if(seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -15);
+ else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 25);
+
+ glColor3ubv((GLubyte *)col);
+
+ glVertex2f(x2,y2);
+ glVertex2f(x1,y2);
+
+ glEnd();
+
+ if (seq->flag & SEQ_MUTE) {
+ glDisable(GL_POLYGON_STIPPLE);
+ }
+}
+
+/*
+Draw a sequence strip, bounds check alredy made
+ARegion is currently only used to get the windows width in pixels
+so wave file sample drawing precission is zoom adjusted
+*/
+static void draw_seq_strip(Scene *scene, ARegion *ar, SpaceSeq *sseq, Sequence *seq, int outline_tint, float pixelx)
+{
+ // XXX
+ extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown);
+ View2D *v2d= &ar->v2d;
+ float x1, x2, y1, y2;
+ char col[3], background_col[3], is_single_image;
+
+ /* we need to know if this is a single image/color or not for drawing */
+ is_single_image = (char)check_single_seq(seq);
+
+ /* body */
+ if(seq->startstill) x1= seq->start;
+ else x1= seq->startdisp;
+ y1= seq->machine+SEQ_STRIP_OFSBOTTOM;
+ if(seq->endstill) x2= seq->start+seq->len;
+ else x2= seq->enddisp;
+ y2= seq->machine+SEQ_STRIP_OFSTOP;
+
+
+ /* get the correct color per strip type*/
+ //get_seq_color3ubv(scene, seq, col);
+ get_seq_color3ubv(scene, seq, background_col);
+
+ /* draw the main strip body */
+ if (is_single_image) /* single image */
+ draw_shadedstrip(seq, background_col, seq_tx_get_final_left(seq, 0), y1, seq_tx_get_final_right(seq, 0), y2);
+ else /* normal operation */
+ draw_shadedstrip(seq, background_col, x1, y1, x2, y2);
+
+ /* draw additional info and controls */
+ if (seq->type == SEQ_RAM_SOUND)
+ drawseqwave(scene, v2d, seq, x1, y1, x2, y2, ar->winx);
+
+ if (!is_single_image)
+ draw_seq_extensions(scene, sseq, seq);
+
+ draw_seq_handle(sseq, seq, pixelx, SEQ_LEFTHANDLE);
+ draw_seq_handle(sseq, seq, pixelx, SEQ_RIGHTHANDLE);
+
+ /* draw the strip outline */
+ x1= seq->startdisp;
+ x2= seq->enddisp;
+
+ get_seq_color3ubv(scene, seq, col);
+ if (G.moving && (seq->flag & SELECT)) {
+ if(seq->flag & SEQ_OVERLAP) {
+ col[0]= 255; col[1]= col[2]= 40;
+ } else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 120);
+ }
+
+ UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, outline_tint);
+
+ glColor3ubv((GLubyte *)col);
+
+ if (seq->flag & SEQ_MUTE) {
+ glEnable(GL_LINE_STIPPLE);
+ glLineStipple(1, 0x8888);
+ }
+
+ gl_round_box_shade(GL_LINE_LOOP, x1, y1, x2, y2, 0.0, 0.1, 0.0);
+
+ if (seq->flag & SEQ_MUTE) {
+ glDisable(GL_LINE_STIPPLE);
+ }
+
+ /* calculate if seq is long enough to print a name */
+ x1= seq->startdisp+seq->handsize;
+ x2= seq->enddisp-seq->handsize;
+
+ /* but first the contents of a meta */
+ if(seq->type==SEQ_META) drawmeta_contents(scene, seq, x1, y1+0.15, x2, y2-0.15);
+
+ /* info text on the strip */
+ if(x1<v2d->cur.xmin) x1= v2d->cur.xmin;
+ else if(x1>v2d->cur.xmax) x1= v2d->cur.xmax;
+ if(x2<v2d->cur.xmin) x2= v2d->cur.xmin;
+ else if(x2>v2d->cur.xmax) x2= v2d->cur.xmax;
+
+ /* nice text here would require changing the view matrix for texture text */
+ if( (x2-x1) / pixelx > 32) {
+ draw_seq_text(v2d, seq, x1, x2, y1, y2, background_col);
+ }
+}
+
+static Sequence *special_seq_update= 0;
+
+void set_special_seq_update(int val)
+{
+// int x;
+
+ /* if mouse over a sequence && LEFTMOUSE */
+ if(val) {
+// XXX special_seq_update= find_nearest_seq(&x);
+ }
+ else special_seq_update= 0;
+}
+
+
+static void draw_image_seq(Scene *scene, ARegion *ar, SpaceSeq *sseq)
+{
+ extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);
+ struct ImBuf *ibuf;
+ int x1, y1, rectx, recty;
+ int free_ibuf = 0;
+ static int recursive= 0;
+ float zoom;
+ float zoomx, zoomy;
+
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ rectx= (scene->r.size*scene->r.xsch)/100;
+ recty= (scene->r.size*scene->r.ysch)/100;
+
+ /* BIG PROBLEM: the give_ibuf_seq() can call a rendering, which in turn calls redraws...
+ this shouldn't belong in a window drawing....
+ So: solve this once event based.
+ Now we check for recursion, space type and active area again (ton) */
+
+ if(recursive)
+ return;
+ else {
+ recursive= 1;
+ if (special_seq_update) {
+ ibuf= give_ibuf_seq_direct(scene, rectx, recty, (scene->r.cfra), special_seq_update);
+ }
+ else if (!U.prefetchframes) { // XXX || (G.f & G_PLAYANIM) == 0) {
+ ibuf= (ImBuf *)give_ibuf_seq(scene, rectx, recty, (scene->r.cfra), sseq->chanshown);
+ }
+ else {
+ ibuf= (ImBuf *)give_ibuf_seq_threaded(scene, rectx, recty, (scene->r.cfra), sseq->chanshown);
+ }
+ recursive= 0;
+
+ /* XXX HURMF! the give_ibuf_seq can call image display in this window */
+// if(sa->spacetype!=SPACE_SEQ)
+// return;
+// if(sa!=curarea) {
+// areawinset(sa->win);
+// }
+ }
+
+ if(ibuf==NULL)
+ return;
+
+ if(ibuf->rect==NULL && ibuf->rect_float == NULL)
+ return;
+
+ switch(sseq->mainb != SEQ_DRAW_SEQUENCE) {
+ case SEQ_DRAW_IMG_IMBUF:
+ if (sseq->zebra != 0) {
+ ibuf = make_zebra_view_from_ibuf(ibuf, sseq->zebra);
+ free_ibuf = 1;
+ }
+ break;
+ case SEQ_DRAW_IMG_WAVEFORM:
+ if ((sseq->flag & SEQ_DRAW_COLOR_SEPERATED) != 0) {
+ ibuf = make_sep_waveform_view_from_ibuf(ibuf);
+ } else {
+ ibuf = make_waveform_view_from_ibuf(ibuf);
+ }
+ free_ibuf = 1;
+ break;
+ case SEQ_DRAW_IMG_VECTORSCOPE:
+ ibuf = make_vectorscope_view_from_ibuf(ibuf);
+ free_ibuf = 1;
+ break;
+ case SEQ_DRAW_IMG_HISTOGRAM:
+ ibuf = make_histogram_view_from_ibuf(ibuf);
+ free_ibuf = 1;
+ break;
+ }
+
+ if(ibuf->rect_float && ibuf->rect==NULL)
+ IMB_rect_from_float(ibuf);
+
+ /* needed for gla draw */
+ glaDefine2DArea(&ar->winrct);
+
+ zoom= SEQ_ZOOM_FAC(sseq->zoom);
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
+ zoomx = zoom * ((float)scene->r.xasp / (float)scene->r.yasp);
+ zoomy = zoom;
+ } else {
+ zoomx = zoomy = zoom;
+ }
+
+ /* calc location */
+ x1= (ar->winx-zoomx*ibuf->x)/2 + sseq->xof;
+ y1= (ar->winy-zoomy*ibuf->y)/2 + sseq->yof;
+
+ glPixelZoom(zoomx, zoomy);
+
+ glaDrawPixelsSafe(x1, y1, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+
+ glPixelZoom(1.0, 1.0);
+
+ /* safety border */
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF &&
+ (sseq->flag & SEQ_DRAW_SAFE_MARGINS) != 0) {
+ float fac= 0.1;
+ float x2 = x1 + ibuf->x * zoomx;
+ float y2 = y1 + ibuf->y * zoomy;
+
+ float a= fac*(x2-x1);
+ x1+= a;
+ x2-= a;
+
+ a= fac*(y2-y1);
+ y1+= a;
+ y2-= a;
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ setlinestyle(3);
+
+ UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0);
+
+ uiSetRoundBox(15);
+ gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);
+
+ setlinestyle(0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+
+ /* draw grease-pencil (image aligned) */
+// if (sseq->flag & SEQ_DRAW_GPENCIL)
+// XXX draw_gpencil_2dimage(sa, ibuf);
+
+ if (free_ibuf) {
+ IMB_freeImBuf(ibuf);
+ }
+
+ /* draw grease-pencil (screen aligned) */
+// if (sseq->flag & SEQ_DRAW_GPENCIL)
+// XXX draw_gpencil_2dview(sa, 0);
+
+ /* ortho at pixel level sa */
+// XXX myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
+
+}
+
+void seq_reset_imageofs(SpaceSeq *sseq)
+{
+ sseq->xof = sseq->yof = sseq->zoom = 0;
+}
+
+
+#if 0
+/* XXX - these should really be made to use View2D instead of so wacko private system - Aligorith */
+
+void seq_viewzoom(SpaceSeq *sseq, unsigned short event, int invert)
+{
+
+ if(event==PAD1)
+ sseq->zoom= 1.0;
+ else if(event==PAD2)
+ sseq->zoom= (invert)? 2.0: 0.5;
+ else if(event==PAD4)
+ sseq->zoom= (invert)? 4.0: 0.25;
+ else if(event==PAD8)
+ sseq->zoom= (invert)? 8.0: 0.125;
+
+ /* ensure pixel exact locations for draw */
+ sseq->xof= (int)sseq->xof;
+ sseq->yof= (int)sseq->yof;
+}
+
+void seq_viewmove(Scene *scene, ARegion *ar, SpaceSeq *sseq)
+{
+ short mval[2], mvalo[2];
+ short rectx, recty, xmin, xmax, ymin, ymax, pad;
+ int oldcursor;
+ Window *win;
+
+ sa = sseq->area;
+ rectx= (scene->r.size*scene->r.xsch)/100;
+ recty= (scene->r.size*scene->r.ysch)/100;
+
+ pad = 10;
+ xmin = -(ar->winx/2) - rectx/2 + pad;
+ xmax = ar->winx/2 + rectx/2 - pad;
+ ymin = -(ar->winy/2) - recty/2 + pad;
+ ymax = ar->winy/2 + recty/2 - pad;
+
+ getmouseco_sc(mvalo);
+
+ oldcursor=get_cursor();
+ win=winlay_get_active_window();
+
+ SetBlenderCursor(BC_NSEW_SCROLLCURSOR);
+
+ while(get_mbut()&(L_MOUSE|M_MOUSE)) {
+
+ getmouseco_sc(mval);
+
+ if(mvalo[0]!=mval[0] || mvalo[1]!=mval[1]) {
+
+ sseq->xof -= (mvalo[0]-mval[0]);
+ sseq->yof -= (mvalo[1]-mval[1]);
+
+ /* prevent dragging image outside of the window and losing it! */
+ CLAMP(sseq->xof, xmin, xmax);
+ CLAMP(sseq->yof, ymin, ymax);
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+
+ }
+ }
+}
+#endif
+
+void drawprefetchseqspace(Scene *scene, ARegion *ar, SpaceSeq *sseq)
+{
+ int rectx, recty;
+
+ rectx= (scene->r.size*scene->r.xsch)/100;
+ recty= (scene->r.size*scene->r.ysch)/100;
+
+ if(sseq->mainb != SEQ_DRAW_SEQUENCE) {
+ give_ibuf_prefetch_request(
+ rectx, recty, (scene->r.cfra), sseq->chanshown);
+ }
+}
+
+void drawseqspace(const bContext *C, ARegion *ar)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceSeq *sseq= sa->spacedata.first;
+ Scene *scene= CTX_data_scene(C);
+ View2D *v2d= &ar->v2d;
+ View2DScrollers *scrollers;
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+ float col[3];
+ int i;
+
+
+
+ if(sseq->mainb != SEQ_DRAW_SEQUENCE) {
+ draw_image_seq(scene, ar, sseq);
+ return;
+ }
+
+ UI_GetThemeColor3fv(TH_BACK, col);
+ if(ed && ed->metastack.first) glClearColor(col[0], col[1], col[2]-0.1, 0.0);
+ else glClearColor(col[0], col[1], col[2], 0.0);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ UI_view2d_view_ortho(C, v2d);
+
+ UI_ThemeColorShade(TH_BACK, -20);
+ glRectf(v2d->cur.xmin, 0.0, v2d->cur.xmax, 1.0);
+
+ boundbox_seq(scene, &v2d->tot);
+
+ /* Alternating horizontal stripes */
+ i= MAX2(1, ((int)v2d->cur.ymin)-1);
+
+ glBegin(GL_QUADS);
+ while (i<v2d->cur.ymax) {
+ if (((int)i) & 1)
+ UI_ThemeColorShade(TH_BACK, -15);
+ else
+ UI_ThemeColorShade(TH_BACK, -25);
+
+ glVertex2f(v2d->cur.xmax, i);
+ glVertex2f(v2d->cur.xmin, i);
+ glVertex2f(v2d->cur.xmin, i+1);
+ glVertex2f(v2d->cur.xmax, i+1);
+ i+=1.0;
+ }
+ glEnd();
+
+ /* Force grid lines */
+ i= MAX2(1, ((int)v2d->cur.ymin)-1);
+ glBegin(GL_LINES);
+
+ while (i<v2d->cur.ymax) {
+ UI_ThemeColor(TH_GRID);
+ glVertex2f(v2d->cur.xmax, i);
+ glVertex2f(v2d->cur.xmin, i);
+ i+=1.0;
+ }
+ glEnd();
+
+ UI_view2d_constant_grid_draw(C, v2d);
+
+ draw_cfra_seq(v2d, scene->r.cfra);
+
+ /* sequences: first deselect */
+ if(ed) {
+ Sequence *last_seq = get_last_seq(scene);
+ int sel = 0, j;
+ int outline_tint;
+ float pixelx = (v2d->cur.xmax - v2d->cur.xmin)/(v2d->mask.xmax - v2d->mask.xmin);
+ /* loop through twice, first unselected, then selected */
+ for (j=0; j<2; j++) {
+ seq= ed->seqbasep->first;
+ if (j==0) outline_tint = -150;
+ else outline_tint = -60;
+
+ while(seq) { /* bound box test, dont draw outside the view */
+ if ( ((seq->flag & SELECT) == sel) ||
+ seq == last_seq ||
+ MIN2(seq->startdisp, seq->start) > v2d->cur.xmax ||
+ MAX2(seq->enddisp, seq->start+seq->len) < v2d->cur.xmin ||
+ seq->machine+1.0 < v2d->cur.ymin ||
+ seq->machine > v2d->cur.ymax)
+ {
+ /* dont draw */
+ } else {
+ draw_seq_strip(scene, ar, sseq, seq, outline_tint, pixelx);
+ }
+ seq= seq->next;
+ }
+ sel= SELECT; /* draw selected next time round */
+ }
+ /* draw the last selected last, removes some overlapping error */
+ if (last_seq) {
+ draw_seq_strip(scene, ar, sseq, last_seq, 120, pixelx);
+ }
+ }
+
+ /* Draw markers */
+// draw_markers_timespace(SCE_MARKERS, DRAW_MARKERS_LINES);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_UNIT_SECONDSSEQ, V2D_GRID_CLAMP, V2D_UNIT_VALUES, V2D_GRID_CLAMP);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+}
+
+
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
new file mode 100644
index 00000000000..f6391666cd8
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -0,0 +1,2388 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2003-2009
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+#include <sys/types.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_storage_types.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_ipo_types.h"
+#include "DNA_curve_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 "DNA_sound_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_plugin_types.h"
+#include "BKE_sequence.h"
+#include "BKE_scene.h"
+#include "BKE_utildefines.h"
+#include "BKE_report.h"
+
+#include "BIF_transform.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+/* for menu/popup icons etc etc*/
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "ED_anim_api.h"
+#include "ED_space_api.h"
+#include "ED_types.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+/* own include */
+#include "sequencer_intern.h"
+
+/* XXX */
+//static Sequence *_last_seq=0;
+//static int _last_seq_init=0;
+/* XXX */
+static void error() {}
+static void waitcursor() {}
+static void activate_fileselect() {}
+static int pupmenu() {return 0;}
+static int okee() {return 0;}
+
+
+/* XXX */
+/* RNA Enums, used in multiple files */
+EnumPropertyItem sequencer_prop_effect_types[] = {
+ {SEQ_CROSS, "CROSS", "Crossfade", "Crossfade effect strip type"},
+ {SEQ_ADD, "ADD", "Add", "Add effect strip type"},
+ {SEQ_SUB, "SUBTRACT", "Subtract", "Subtract effect strip type"},
+ {SEQ_ALPHAOVER, "ALPHA_OVER", "Alpha Over", "Alpha Over effect strip type"},
+ {SEQ_ALPHAUNDER, "ALPHA_UNDER", "Alpha Under", "Alpha Under effect strip type"},
+ {SEQ_GAMCROSS, "GAMMA_CROSS", "Gamma Cross", "Gamma Cross effect strip type"},
+ {SEQ_MUL, "MULTIPLY", "Multiply", "Multiply effect strip type"},
+ {SEQ_OVERDROP, "ALPHA_OVER_DROP", "Alpha Over Drop", "Alpha Over Drop effect strip type"},
+ {SEQ_PLUGIN, "PLUGIN", "Plugin", "Plugin effect strip type"},
+ {SEQ_WIPE, "WIPE", "Wipe", "Wipe effect strip type"},
+ {SEQ_GLOW, "GLOW", "Glow", "Glow effect strip type"},
+ {SEQ_TRANSFORM, "TRANSFORM", "Transform", "Transform effect strip type"},
+ {SEQ_COLOR, "COLOR", "Color", "Color effect strip type"},
+ {SEQ_SPEED, "SPEED", "Speed", "Color effect strip type"},
+ {0, NULL, NULL, NULL}
+};
+
+/* mute operator */
+EnumPropertyItem sequencer_prop_operate_types[] = { /* better name? */
+ {SEQ_SELECTED, "SELECTED", "Selected", ""},
+ {SEQ_UNSELECTED, "UNSELECTED", "Unselected ", ""},
+ {0, NULL, NULL, NULL}
+};
+
+ EnumPropertyItem prop_side_types[] = {
+ {SEQ_SIDE_LEFT, "LEFT", "Left", ""},
+ {SEQ_SIDE_RIGHT, "RIGHT", "Right", ""},
+ {SEQ_SIDE_BOTH, "BOTH", "Both", ""},
+ {0, NULL, NULL, NULL}
+};
+
+typedef struct TransSeq {
+ int start, machine;
+ int startstill, endstill;
+ int startdisp, enddisp;
+ int startofs, endofs;
+ int final_left, final_right;
+ int len;
+} TransSeq;
+
+Sequence *get_last_seq(Scene *scene)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ if(ed==NULL) return NULL;
+ return ed->act_seq;
+}
+
+void set_last_seq(Scene *scene, Sequence *seq)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ if(ed==NULL) return;
+
+ ed->act_seq= seq;
+}
+
+Sequence *get_forground_frame_seq(Scene *scene, int frame)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq, *best_seq=NULL;
+ int best_machine = -1;
+
+ if(!ed) return NULL;
+
+ for (seq=ed->seqbasep->first; seq; seq= seq->next) {
+ if(seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame)
+ continue;
+ /* only use elements you can see - not */
+ if (ELEM6(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE, SEQ_MOVIE_AND_HD_SOUND, SEQ_COLOR)) {
+ if (seq->machine > best_machine) {
+ best_seq = seq;
+ best_machine = seq->machine;
+ }
+ }
+ }
+ return best_seq;
+}
+
+void seq_rectf(Sequence *seq, rctf *rectf)
+{
+ if(seq->startstill) rectf->xmin= seq->start;
+ else rectf->xmin= seq->startdisp;
+ rectf->ymin= seq->machine+SEQ_STRIP_OFSBOTTOM;
+ if(seq->endstill) rectf->xmax= seq->start+seq->len;
+ else rectf->xmax= seq->enddisp;
+ rectf->ymax= seq->machine+SEQ_STRIP_OFSTOP;
+}
+
+static void change_plugin_seq(Scene *scene, char *str) /* called from fileselect */
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ struct SeqEffectHandle sh;
+ Sequence *last_seq= get_last_seq(scene);
+
+ if(last_seq && last_seq->type != SEQ_PLUGIN) return;
+
+ sh = get_sequence_effect(last_seq);
+ sh.free(last_seq);
+ sh.init_plugin(last_seq, str);
+
+ last_seq->machine = MAX3(last_seq->seq1->machine,
+ last_seq->seq2->machine,
+ last_seq->seq3->machine);
+
+ if( seq_test_overlap(ed->seqbasep, last_seq) ) shuffle_seq(ed->seqbasep, last_seq);
+
+}
+
+
+void boundbox_seq(Scene *scene, rctf *rect)
+{
+ Sequence *seq;
+ Editing *ed= seq_give_editing(scene, FALSE);
+ float min[2], max[2];
+
+
+ if(ed==NULL) 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;
+ }
+
+ rect->xmin= min[0];
+ rect->xmax= max[0];
+ rect->ymin= min[1];
+ rect->ymax= max[1];
+
+}
+
+int mouse_frame_side(View2D *v2d, short mouse_x, int frame )
+{
+ short mval[2];
+ float mouseloc[2];
+
+ mval[0]= mouse_x;
+ mval[1]= 0;
+
+ /* choose the side based on which side of the playhead the mouse is on */
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseloc[0], &mouseloc[1]);
+
+ return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT;
+}
+
+
+Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int sel)
+{
+ /* sel - 0==unselected, 1==selected, -1==done care*/
+ Sequence *seq;
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ if(ed==NULL) return NULL;
+
+ if (sel>0) sel = SELECT;
+
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ if( (seq!=test) &&
+ (test->machine==seq->machine) &&
+ ((sel == -1) || (sel && (seq->flag & SELECT)) || (sel==0 && (seq->flag & SELECT)==0) ))
+ {
+ switch (lr) {
+ case SEQ_SIDE_LEFT:
+ if (test->startdisp == (seq->enddisp)) {
+ return seq;
+ }
+ break;
+ case SEQ_SIDE_RIGHT:
+ if (test->enddisp == (seq->startdisp)) {
+ return seq;
+ }
+ break;
+ }
+ }
+ }
+ return NULL;
+}
+
+Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel)
+{
+ /* sel - 0==unselected, 1==selected, -1==done care*/
+ Sequence *seq,*best_seq = NULL;
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ int dist, best_dist;
+ best_dist = MAXFRAME*2;
+
+
+ if(ed==NULL) return NULL;
+
+ if (sel) sel = SELECT;
+
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if( (seq!=test) &&
+ (test->machine==seq->machine) &&
+ (test->depth==seq->depth) &&
+ ((sel == -1) || (sel==(seq->flag & SELECT))))
+ {
+ dist = MAXFRAME*2;
+
+ switch (lr) {
+ case SEQ_SIDE_LEFT:
+ if (seq->enddisp <= test->startdisp) {
+ dist = test->enddisp - seq->startdisp;
+ }
+ break;
+ case SEQ_SIDE_RIGHT:
+ if (seq->startdisp >= test->enddisp) {
+ dist = seq->startdisp - test->enddisp;
+ }
+ break;
+ }
+
+ if (dist==0) {
+ best_seq = seq;
+ break;
+ } else if (dist < best_dist) {
+ best_dist = dist;
+ best_seq = seq;
+ }
+ }
+ seq= seq->next;
+ }
+ return best_seq; /* can be null */
+}
+
+
+Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, short mval[2])
+{
+ Sequence *seq;
+ Editing *ed= seq_give_editing(scene, FALSE);
+ float x, y;
+ float pixelx;
+ float handsize;
+ float displen;
+ *hand= SEQ_SIDE_NONE;
+
+
+ if(ed==NULL) return NULL;
+
+ pixelx = (v2d->cur.xmax - v2d->cur.xmin)/(v2d->mask.xmax - v2d->mask.xmin);
+
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
+
+ seq= ed->seqbasep->first;
+
+ while(seq) {
+ if(seq->machine == (int)y) {
+ /* check for both normal strips, and strips that have been flipped horizontally */
+ if( ((seq->startdisp < seq->enddisp) && (seq->startdisp<=x && seq->enddisp>=x)) ||
+ ((seq->startdisp > seq->enddisp) && (seq->startdisp>=x && seq->enddisp<=x)) )
+ {
+ if(seq_tx_test(seq)) {
+
+ /* clamp handles to defined size in pixel space */
+
+ handsize = seq->handsize;
+ displen = (float)abs(seq->startdisp - seq->enddisp);
+
+ if (displen / pixelx > 16) { /* dont even try to grab the handles of small strips */
+ /* Set the max value to handle to 1/3 of the total len when its less then 28.
+ * This is important because otherwise selecting handles happens even when you click in the middle */
+
+ if ((displen/3) < 30*pixelx) {
+ handsize = displen/3;
+ } else {
+ CLAMP(handsize, 7*pixelx, 30*pixelx);
+ }
+
+ if( handsize+seq->startdisp >=x )
+ *hand= SEQ_SIDE_LEFT;
+ else if( -handsize+seq->enddisp <=x )
+ *hand= SEQ_SIDE_RIGHT;
+ }
+ }
+ return seq;
+ }
+ }
+ seq= seq->next;
+ }
+ return 0;
+}
+
+void update_seq_ipo_rect(Scene *scene, View2D *v2d, Sequence *seq)
+{
+ float start;
+ float end;
+
+ if (!seq || !seq->ipo) {
+ return;
+ }
+ start = -5.0;
+ end = 105.0;
+
+
+ /* Adjust IPO window to sequence and
+ avoid annoying snap-back to startframe
+ when Lock Time is on */
+ if (0) { // XXX v2d->flag & V2D_VIEWLOCK) {
+ if ((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
+ start = -5.0 + seq->startdisp;
+ end = 5.0 + seq->enddisp;
+ } else {
+ start = (float)scene->r.sfra - 0.1;
+ end = scene->r.efra;
+ }
+ }
+
+ seq->ipo->cur.xmin= start;
+ seq->ipo->cur.xmax= end;
+}
+
+void update_seq_icu_rects(Sequence * seq)
+{
+ IpoCurve *icu= NULL;
+ struct SeqEffectHandle sh;
+
+ if (!seq || !seq->ipo) {
+ return;
+ }
+
+ if(!(seq->type & SEQ_EFFECT)) {
+ return;
+ }
+
+ sh = get_sequence_effect(seq);
+
+ for(icu= seq->ipo->curve.first; icu; icu= icu->next) {
+ sh.store_icu_yrange(seq, icu->adrcode, &icu->ymin, &icu->ymax);
+ }
+}
+
+
+static int seq_is_parent(Sequence *par, Sequence *seq)
+{
+ return ((par->seq1 == seq) || (par->seq2 == seq) || (par->seq3 == seq));
+}
+
+static int seq_is_predecessor(Sequence *pred, Sequence *seq)
+{
+ if (!pred) return 0;
+ if(pred == seq) return 0;
+ else if(seq_is_parent(pred, seq)) return 1;
+ else if(pred->seq1 && seq_is_predecessor(pred->seq1, seq)) return 1;
+ else if(pred->seq2 && seq_is_predecessor(pred->seq2, seq)) return 1;
+ else if(pred->seq3 && seq_is_predecessor(pred->seq3, seq)) return 1;
+
+ return 0;
+}
+
+void deselect_all_seq(Scene *scene)
+{
+ Sequence *seq;
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+
+ if(ed==NULL) return;
+
+ SEQP_BEGIN(ed, seq) {
+ seq->flag &= SEQ_DESEL;
+ }
+ SEQ_END
+
+}
+
+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;
+ }
+}
+
+Sequence *alloc_sequence(ListBase *lb, int cfra, int machine)
+{
+ Sequence *seq;
+
+ /*ed= scene->ed;*/
+
+ seq= MEM_callocN( sizeof(Sequence), "addseq");
+ BLI_addtail(lb, seq);
+
+ //set_last_seq(scene, seq); // Probably not a great idea at such a low level anyway - Campbell
+
+ *( (short *)seq->name )= ID_SEQ;
+ seq->name[2]= 0;
+
+ seq->flag= SELECT;
+ seq->start= cfra;
+ seq->machine= machine;
+ seq->mul= 1.0;
+ seq->blend_opacity = 100.0;
+
+ return seq;
+}
+
+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;
+ if(event==13) return SEQ_WIPE;
+ if(event==14) return SEQ_GLOW;
+ if(event==15) return SEQ_TRANSFORM;
+ if(event==16) return SEQ_COLOR;
+ if(event==17) return SEQ_SPEED;
+ return 0;
+}
+
+#if 0
+static void reload_sound_strip(Scene *scene, char *name)
+{
+ Editing *ed;
+ Sequence *seq, *seqact;
+ SpaceFile *sfile;
+ Sequence *last_seq= get_last_seq(scene);
+
+ ed= scene->ed;
+
+ if(last_seq==0 || last_seq->type!=SEQ_SOUND) return;
+ seqact= last_seq; /* last_seq changes in alloc_sequence */
+
+ /* search sfile */
+// sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
+ if(sfile==0) return;
+
+ waitcursor(1);
+
+ seq = sfile_to_snd_sequence(sfile, seqact->start, seqact->machine);
+ printf("seq->type: %i\n", seq->type);
+ if(seq && seq!=seqact) {
+ /* i'm not sure about this one, seems to work without it -- sgefant */
+ seq_free_strip(seqact->strip);
+
+ seqact->strip= seq->strip;
+
+ seqact->len= seq->len;
+ calc_sequence(seqact);
+
+ seq->strip= 0;
+ seq_free_sequence(ed, seq);
+ BLI_remlink(ed->seqbasep, seq);
+
+ seq= ed->seqbasep->first;
+
+ }
+
+ waitcursor(0);
+
+}
+#endif
+
+static void reload_image_strip(Scene *scene, char *name)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq=NULL, *seqact;
+ SpaceFile *sfile=NULL;
+ Sequence *last_seq= get_last_seq(scene);
+
+
+
+ if(last_seq==0 || last_seq->type!=SEQ_IMAGE) return;
+ seqact= last_seq; /* last_seq changes in alloc_sequence */
+
+ /* search sfile */
+// sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
+ if(sfile==0) return;
+
+ waitcursor(1);
+
+// seq= sfile_to_sequence(scene, sfile, seqact->start, seqact->machine, 1); // XXX ADD BACK
+ if(seq && seq!=seqact) {
+ seq_free_strip(seqact->strip);
+
+ seqact->strip= seq->strip;
+
+ seqact->len= seq->len;
+ calc_sequence(seqact);
+
+ seq->strip= 0;
+ seq_free_sequence(ed, seq);
+ BLI_remlink(ed->seqbasep, seq);
+
+ update_changed_seq_and_deps(scene, seqact, 1, 1);
+ }
+ waitcursor(0);
+
+}
+
+
+void change_sequence(Scene *scene)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *last_seq= get_last_seq(scene);
+ 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"
+ "|Gamma Cross%x3"
+ "|Add%x4"
+ "|Sub%x5"
+ "|Mul%x6"
+ "|Alpha Over%x7"
+ "|Alpha Under%x8"
+ "|Alpha Over Drop%x9"
+ "|Wipe%x13"
+ "|Glow%x14"
+ "|Transform%x15"
+ "|Color Generator%x16"
+ "|Speed Control%x17");
+ 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: only new_stripdata */
+ else {
+ /* free previous effect and init new effect */
+ struct SeqEffectHandle sh;
+
+ if (get_sequence_effect_num_inputs(
+ last_seq->type)
+ < get_sequence_effect_num_inputs(
+ event_to_efftype(event))) {
+ error("New effect needs more "
+ "input strips!");
+ } else {
+ sh = get_sequence_effect(last_seq);
+ sh.free(last_seq);
+
+ last_seq->type
+ = event_to_efftype(event);
+
+ sh = get_sequence_effect(last_seq);
+ sh.init(last_seq);
+ }
+ }
+
+ update_changed_seq_and_deps(scene, last_seq, 0, 1);
+ }
+ }
+ else if(last_seq->type == SEQ_IMAGE) {
+ if(okee("Change images")) {
+ activate_fileselect(FILE_SPECIAL,
+ "Select Images",
+ ed->act_imagedir,
+ 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;
+
+ /* bad code to change seq->len? update_changed_seq_and_deps() expects the strip->len to be OK */
+ new_tstripdata(last_seq);
+
+ update_changed_seq_and_deps(scene, last_seq, 1, 1);
+
+ }
+ }
+
+}
+
+int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequence **selseq1, Sequence **selseq2, Sequence **selseq3, char **error_str)
+{
+ Editing *ed = seq_give_editing(scene, FALSE);
+ Sequence *seq1= 0, *seq2= 0, *seq3= 0, *seq;
+
+ *error_str= NULL;
+
+ if (!activeseq)
+ seq2= get_last_seq(scene);
+
+ for(seq=ed->seqbasep->first; seq; seq=seq->next) {
+ if(seq->flag & SELECT) {
+ if (seq->type == SEQ_RAM_SOUND || seq->type == SEQ_HD_SOUND) {
+ *error_str= "Can't apply effects to audio sequence strips";
+ return 0;
+ }
+ if((seq != activeseq) && (seq != seq2)) {
+ if(seq2==0) seq2= seq;
+ else if(seq1==0) seq1= seq;
+ else if(seq3==0) seq3= seq;
+ else {
+ *error_str= "Can't apply effect to more than 3 sequence strips";
+ return 0;
+ }
+ }
+ }
+ }
+
+ /* make sequence selection a little bit more intuitive
+ for 3 strips: the last-strip should be sequence3 */
+ if (seq3 != 0 && seq2 != 0) {
+ Sequence *tmp = seq2;
+ seq2 = seq3;
+ seq3 = tmp;
+ }
+
+
+ switch(get_sequence_effect_num_inputs(type)) {
+ case 0:
+ *selseq1 = *selseq2 = *selseq3 = 0;
+ return 1; /* succsess */
+ case 1:
+ if(seq2==0) {
+ *error_str= "Need at least one selected sequence strip";
+ return 0;
+ }
+ if(seq1==0) seq1= seq2;
+ if(seq3==0) seq3= seq2;
+ case 2:
+ if(seq1==0 || seq2==0) {
+ *error_str= "Need 2 selected sequence strips";
+ return 0;
+ }
+ if(seq3==0) seq3= seq2;
+ }
+
+ if (seq1==NULL && seq2==NULL && seq3==NULL) {
+ *error_str= "TODO: in what cases does this happen?";
+ return 0;
+ }
+
+ *selseq1= seq1;
+ *selseq2= seq2;
+ *selseq3= seq3;
+
+ return 1;
+}
+
+void reassign_inputs_seq_effect(Scene *scene)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq1, *seq2, *seq3, *last_seq = get_last_seq(scene);
+ char *error_msg;
+
+ if(last_seq==0 || !(last_seq->type & SEQ_EFFECT)) return;
+ if(ed==NULL) return;
+
+ if(!seq_effect_find_selected(scene, last_seq, last_seq->type, &seq1, &seq2, &seq3, &error_msg)) {
+ //BKE_report(op->reports, RPT_ERROR, error_msg); // XXX operatorify
+ return;
+ }
+ /* see reassigning would create a cycle */
+ if( seq_is_predecessor(seq1, last_seq) ||
+ seq_is_predecessor(seq2, last_seq) ||
+ seq_is_predecessor(seq3, last_seq)
+ ) {
+ //BKE_report(op->reports, RPT_ERROR, "Can't reassign inputs: no cycles allowed"); // XXX operatorify
+ return;
+ }
+
+ last_seq->seq1 = seq1;
+ last_seq->seq2 = seq2;
+ last_seq->seq3 = seq3;
+
+ update_changed_seq_and_deps(scene, last_seq, 1, 1);
+
+}
+
+static Sequence *del_seq_find_replace_recurs(Scene *scene, Sequence *seq)
+{
+ Sequence *seq1, *seq2, *seq3;
+
+ /* try to find a replacement input sequence, and flag for later deletion if
+ no replacement can be found */
+
+ if(!seq)
+ return NULL;
+ else if(!(seq->type & SEQ_EFFECT))
+ return ((seq->flag & SELECT)? NULL: seq);
+ else if(!(seq->flag & SELECT)) {
+ /* try to find replacement for effect inputs */
+ seq1= del_seq_find_replace_recurs(scene, seq->seq1);
+ seq2= del_seq_find_replace_recurs(scene, seq->seq2);
+ seq3= del_seq_find_replace_recurs(scene, seq->seq3);
+
+ if(seq1==seq->seq1 && seq2==seq->seq2 && seq3==seq->seq3);
+ else if(seq1 || seq2 || seq3) {
+ seq->seq1= (seq1)? seq1: (seq2)? seq2: seq3;
+ seq->seq2= (seq2)? seq2: (seq1)? seq1: seq3;
+ seq->seq3= (seq3)? seq3: (seq1)? seq1: seq2;
+
+ update_changed_seq_and_deps(scene, seq, 1, 1);
+ }
+ else
+ seq->flag |= SELECT; /* mark for delete */
+ }
+
+ if (seq->flag & SELECT) {
+ if((seq1 = del_seq_find_replace_recurs(scene, seq->seq1))) return seq1;
+ if((seq2 = del_seq_find_replace_recurs(scene, seq->seq2))) return seq2;
+ if((seq3 = del_seq_find_replace_recurs(scene, seq->seq3))) return seq3;
+ else return NULL;
+ }
+ else
+ return seq;
+}
+
+static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short deleteall)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq, *seqn;
+ Sequence *last_seq = get_last_seq(scene);
+
+ seq= lb->first;
+ while(seq) {
+ seqn= seq->next;
+ if((seq->flag & flag) || deleteall) {
+ if(seq->type==SEQ_RAM_SOUND && seq->sound)
+ seq->sound->id.us--;
+
+ BLI_remlink(lb, seq);
+ if(seq==last_seq) set_last_seq(scene, NULL);
+ if(seq->type==SEQ_META) recurs_del_seq_flag(scene, &seq->seqbase, flag, 1);
+ if(seq->ipo) seq->ipo->id.us--;
+ seq_free_sequence(ed, seq);
+ }
+ seq= seqn;
+ }
+}
+
+static Sequence *dupli_seq(Sequence *seq)
+{
+ Sequence *seqn = MEM_dupallocN(seq);
+
+ seq->tmp = seqn;
+
+ seqn->strip= MEM_dupallocN(seq->strip);
+
+ if(seqn->ipo) seqn->ipo->id.us++;
+
+ seqn->strip->tstripdata = 0;
+ seqn->strip->tstripdata_startstill = 0;
+ seqn->strip->tstripdata_endstill = 0;
+ seqn->strip->ibuf_startstill = 0;
+ seqn->strip->ibuf_endstill = 0;
+
+ if (seq->strip->crop) {
+ seqn->strip->crop = MEM_dupallocN(seq->strip->crop);
+ }
+
+ if (seq->strip->transform) {
+ seqn->strip->transform = MEM_dupallocN(seq->strip->transform);
+ }
+
+ if (seq->strip->proxy) {
+ seqn->strip->proxy = MEM_dupallocN(seq->strip->proxy);
+ }
+
+ if (seq->strip->color_balance) {
+ seqn->strip->color_balance
+ = MEM_dupallocN(seq->strip->color_balance);
+ }
+
+ if(seq->type==SEQ_META) {
+ seqn->strip->stripdata = 0;
+
+ seqn->seqbase.first= seqn->seqbase.last= 0;
+ /* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */
+ /* - recurs_dupli_seq(&seq->seqbase,&seqn->seqbase);*/
+ } else if(seq->type == SEQ_SCENE) {
+ seqn->strip->stripdata = 0;
+ } else if(seq->type == SEQ_MOVIE) {
+ seqn->strip->stripdata =
+ MEM_dupallocN(seq->strip->stripdata);
+ seqn->anim= 0;
+ } else if(seq->type == SEQ_RAM_SOUND) {
+ seqn->strip->stripdata =
+ MEM_dupallocN(seq->strip->stripdata);
+ seqn->sound->id.us++;
+ } else if(seq->type == SEQ_HD_SOUND) {
+ seqn->strip->stripdata =
+ MEM_dupallocN(seq->strip->stripdata);
+ seqn->hdaudio = 0;
+ } else if(seq->type == SEQ_IMAGE) {
+ seqn->strip->stripdata =
+ MEM_dupallocN(seq->strip->stripdata);
+ } else if(seq->type >= SEQ_EFFECT) {
+ if(seq->seq1 && seq->seq1->tmp) seqn->seq1= seq->seq1->tmp;
+ if(seq->seq2 && seq->seq2->tmp) seqn->seq2= seq->seq2->tmp;
+ if(seq->seq3 && seq->seq3->tmp) seqn->seq3= seq->seq3->tmp;
+
+ if (seq->type & SEQ_EFFECT) {
+ struct SeqEffectHandle sh;
+ sh = get_sequence_effect(seq);
+ if(sh.copy)
+ sh.copy(seq, seqn);
+ }
+
+ seqn->strip->stripdata = 0;
+
+ } else {
+ fprintf(stderr, "Aiiiiekkk! sequence type not "
+ "handled in duplicate!\nExpect a crash"
+ " now...\n");
+ }
+
+ return seqn;
+}
+
+static Sequence * deep_dupli_seq(Sequence * seq)
+{
+ Sequence * seqn = dupli_seq(seq);
+ if (seq->type == SEQ_META) {
+ Sequence * s;
+ for(s= seq->seqbase.first; s; s = s->next) {
+ Sequence * n = deep_dupli_seq(s);
+ if (n) {
+ BLI_addtail(&seqn->seqbase, n);
+ }
+ }
+ }
+ return seqn;
+}
+
+
+static void recurs_dupli_seq(Scene *scene, ListBase *old, ListBase *new)
+{
+ Sequence *seq;
+ Sequence *seqn = 0;
+ Sequence *last_seq = get_last_seq(scene);
+
+ for(seq= old->first; seq; seq= seq->next) {
+ seq->tmp= NULL;
+ if(seq->flag & SELECT) {
+ seqn = dupli_seq(seq);
+ if (seqn) { /*should never fail */
+ seq->flag &= SEQ_DESEL;
+ seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL+SEQ_LOCK);
+
+ BLI_addtail(new, seqn);
+ if(seq->type==SEQ_META)
+ recurs_dupli_seq(scene, &seq->seqbase,&seqn->seqbase);
+
+ if (seq == last_seq) {
+ set_last_seq(scene, seqn);
+ }
+ }
+ }
+ }
+}
+
+static Sequence *cut_seq_hard(Scene *scene, Sequence * seq, int cutframe)
+{
+ TransSeq ts;
+ Sequence *seqn = 0;
+ int skip_dup = FALSE;
+
+ /* backup values */
+ ts.start= seq->start;
+ ts.machine= seq->machine;
+ ts.startstill= seq->startstill;
+ ts.endstill= seq->endstill;
+ ts.startdisp= seq->startdisp;
+ ts.enddisp= seq->enddisp;
+ ts.startofs= seq->anim_startofs;
+ ts.endofs= seq->anim_endofs;
+ ts.len= seq->len;
+
+ /* First Strip! */
+ /* strips with extended stillfames before */
+
+ if ((seq->startstill) && (cutframe <seq->start)) {
+ /* don't do funny things with METAs ... */
+ if (seq->type == SEQ_META) {
+ skip_dup = TRUE;
+ seq->startstill = seq->start - cutframe;
+ } else {
+ seq->start= cutframe -1;
+ seq->startstill= cutframe -seq->startdisp -1;
+ seq->anim_endofs += seq->len - 1;
+ seq->endstill= 0;
+ }
+ }
+ /* normal strip */
+ else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) {
+ seq->endofs = 0;
+ seq->endstill = 0;
+ seq->anim_endofs += (seq->start+seq->len) - cutframe;
+ }
+ /* strips with extended stillframes after */
+ else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
+ seq->endstill -= seq->enddisp - cutframe;
+ /* don't do funny things with METAs ... */
+ if (seq->type == SEQ_META) {
+ skip_dup = TRUE;
+ }
+ }
+
+ reload_sequence_new_file(scene, seq);
+ calc_sequence(seq);
+
+ if (!skip_dup) {
+ /* Duplicate AFTER the first change */
+ seqn = deep_dupli_seq(seq);
+ }
+
+ if (seqn) {
+ seqn->flag |= SELECT;
+
+ /* Second Strip! */
+ /* strips with extended stillframes before */
+ if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
+ seqn->start = ts.start;
+ seqn->startstill= ts.start- cutframe;
+ seqn->anim_endofs = ts.endofs;
+ seqn->endstill = ts.endstill;
+ }
+
+ /* normal strip */
+ else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) {
+ seqn->start = cutframe;
+ seqn->startstill = 0;
+ seqn->startofs = 0;
+ seqn->anim_startofs += cutframe - ts.start;
+ seqn->anim_endofs = ts.endofs;
+ seqn->endstill = ts.endstill;
+ }
+
+ /* strips with extended stillframes after */
+ else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) {
+ seqn->start = cutframe;
+ seqn->startofs = 0;
+ seqn->anim_startofs += ts.len-1;
+ seqn->endstill = ts.enddisp - cutframe -1;
+ seqn->startstill = 0;
+ }
+
+ reload_sequence_new_file(scene, seqn);
+ calc_sequence(seqn);
+ }
+ return seqn;
+}
+
+static Sequence *cut_seq_soft(Scene *scene, Sequence * seq, int cutframe)
+{
+ TransSeq ts;
+ Sequence *seqn = 0;
+ int skip_dup = FALSE;
+
+ /* backup values */
+ ts.start= seq->start;
+ ts.machine= seq->machine;
+ ts.startstill= seq->startstill;
+ ts.endstill= seq->endstill;
+ ts.startdisp= seq->startdisp;
+ ts.enddisp= seq->enddisp;
+ ts.startofs= seq->startofs;
+ ts.endofs= seq->endofs;
+ ts.len= seq->len;
+
+ /* First Strip! */
+ /* strips with extended stillfames before */
+
+ if ((seq->startstill) && (cutframe <seq->start)) {
+ /* don't do funny things with METAs ... */
+ if (seq->type == SEQ_META) {
+ skip_dup = TRUE;
+ seq->startstill = seq->start - cutframe;
+ } else {
+ seq->start= cutframe -1;
+ seq->startstill= cutframe -seq->startdisp -1;
+ seq->endofs = seq->len - 1;
+ seq->endstill= 0;
+ }
+ }
+ /* normal strip */
+ else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) {
+ seq->endofs = (seq->start+seq->len) - cutframe;
+ }
+ /* strips with extended stillframes after */
+ else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
+ seq->endstill -= seq->enddisp - cutframe;
+ /* don't do funny things with METAs ... */
+ if (seq->type == SEQ_META) {
+ skip_dup = TRUE;
+ }
+ }
+
+ calc_sequence(seq);
+
+ if (!skip_dup) {
+ /* Duplicate AFTER the first change */
+ seqn = deep_dupli_seq(seq);
+ }
+
+ if (seqn) {
+ seqn->flag |= SELECT;
+
+ /* Second Strip! */
+ /* strips with extended stillframes before */
+ if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
+ seqn->start = ts.start;
+ seqn->startstill= ts.start- cutframe;
+ seqn->endofs = ts.endofs;
+ seqn->endstill = ts.endstill;
+ }
+
+ /* normal strip */
+ else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) {
+ seqn->startstill = 0;
+ seqn->startofs = cutframe - ts.start;
+ seqn->endofs = ts.endofs;
+ seqn->endstill = ts.endstill;
+ }
+
+ /* strips with extended stillframes after */
+ else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) {
+ seqn->start = cutframe - ts.len +1;
+ seqn->startofs = ts.len-1;
+ seqn->endstill = ts.enddisp - cutframe -1;
+ seqn->startstill = 0;
+ }
+
+ calc_sequence(seqn);
+ }
+ return seqn;
+}
+
+
+/* like duplicate, but only duplicate and cut overlapping strips,
+ * strips to the left of the cutframe are ignored and strips to the right are moved into the new list */
+static int cut_seq_list(Scene *scene, ListBase *old, ListBase *new, int cutframe,
+ Sequence * (*cut_seq)(Scene *, Sequence *, int))
+{
+ int did_something = FALSE;
+ Sequence *seq, *seq_next;
+
+ seq= old->first;
+
+ while(seq) {
+ seq_next = seq->next; /* we need this because we may remove seq */
+
+ seq->tmp= NULL;
+ if(seq->flag & SELECT) {
+ if(cutframe > seq->startdisp &&
+ cutframe < seq->enddisp) {
+ Sequence * seqn = cut_seq(scene, seq, cutframe);
+ if (seqn) {
+ BLI_addtail(new, seqn);
+ }
+ did_something = TRUE;
+ } else if (seq->enddisp <= cutframe) {
+ /* do nothing */
+ } else if (seq->startdisp >= cutframe) {
+ /* move into new list */
+ BLI_remlink(old, seq);
+ BLI_addtail(new, seq);
+ }
+ }
+ seq = seq_next;
+ }
+ return did_something;
+}
+
+int insert_gap(Scene *scene, int gap, int cfra)
+{
+ Sequence *seq;
+ Editing *ed= seq_give_editing(scene, FALSE);
+ int done=0;
+
+ /* all strips >= cfra are shifted */
+
+ if(ed==NULL) return 0;
+
+ SEQP_BEGIN(ed, seq) {
+ if(seq->startdisp >= cfra) {
+ seq->start+= gap;
+ calc_sequence(seq);
+ done= 1;
+ }
+ }
+ SEQ_END
+
+ return done;
+}
+
+void touch_seq_files(Scene *scene)
+{
+ Sequence *seq;
+ Editing *ed= seq_give_editing(scene, FALSE);
+ char str[256];
+
+ /* touch all strips with movies */
+
+ if(ed==NULL) return;
+
+ if(okee("Touch and print selected movies")==0) return;
+
+ waitcursor(1);
+
+ SEQP_BEGIN(ed, seq) {
+ 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);
+ }
+ }
+
+ }
+ }
+ SEQ_END
+
+ waitcursor(0);
+}
+
+void set_filter_seq(Scene *scene)
+{
+ Sequence *seq;
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+
+ if(ed==NULL) return;
+
+ if(okee("Set Deinterlace")==0) return;
+
+ SEQP_BEGIN(ed, seq) {
+ if(seq->flag & SELECT) {
+ if(seq->type==SEQ_MOVIE) {
+ seq->flag |= SEQ_FILTERY;
+ reload_sequence_new_file(scene, seq);
+ }
+
+ }
+ }
+ SEQ_END
+
+}
+
+void seq_remap_paths(Scene *scene)
+{
+ Sequence *seq, *last_seq = get_last_seq(scene);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ char from[FILE_MAX], to[FILE_MAX], stripped[FILE_MAX];
+
+
+ if(last_seq==NULL)
+ return;
+
+ BLI_strncpy(from, last_seq->strip->dir, FILE_MAX);
+// XXX if (0==sbutton(from, 0, sizeof(from)-1, "From: "))
+// return;
+
+ strcpy(to, from);
+// XXX if (0==sbutton(to, 0, sizeof(to)-1, "To: "))
+// return;
+
+ if (strcmp(to, from)==0)
+ return;
+
+ SEQP_BEGIN(ed, seq) {
+ if(seq->flag & SELECT) {
+ if(strncmp(seq->strip->dir, from, strlen(from))==0) {
+ printf("found %s\n", seq->strip->dir);
+
+ /* strip off the beginning */
+ stripped[0]= 0;
+ BLI_strncpy(stripped, seq->strip->dir + strlen(from), FILE_MAX);
+
+ /* new path */
+ BLI_strncpy(seq->strip->dir, to, FILE_MAX);
+ strcat(seq->strip->dir, stripped);
+ printf("new %s\n", seq->strip->dir);
+ }
+ }
+ }
+ SEQ_END
+
+}
+
+
+void no_gaps(Scene *scene)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ int cfra, first= 0, done;
+
+
+ if(ed==NULL) return;
+
+ for(cfra= CFRA; cfra<=EFRA; cfra++) {
+ if(first==0) {
+ if( evaluate_seq_frame(scene, cfra) ) first= 1;
+ }
+ else {
+ done= 1;
+ while( evaluate_seq_frame(scene, cfra) == 0) {
+ done= insert_gap(scene, -1, cfra);
+ if(done==0) break;
+ }
+ if(done==0) break;
+ }
+ }
+
+}
+
+#if 0
+static int seq_get_snaplimit(View2D *v2d)
+{
+ /* fake mouse coords to get the snap value
+ a bit lazy but its only done once pre transform */
+ float xmouse, ymouse, x;
+ short mval[2] = {24, 0}; /* 24 screen px snap */
+
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
+ x = xmouse;
+ mval[0] = 0;
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
+ return (int)(x - xmouse);
+}
+#endif
+
+void seq_snap(Scene *scene, short event)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+
+
+ if(ed==NULL) return;
+
+ /* problem: contents of meta's are all shifted to the same position... */
+
+ /* also check metas */
+ SEQP_BEGIN(ed, seq) {
+ if (seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK) &&
+ seq_tx_test(seq)) {
+ if((seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0) {
+ seq->start= CFRA-seq->startofs+seq->startstill;
+ } else {
+ if(seq->flag & SEQ_LEFTSEL) {
+ seq_tx_set_final_left(seq, CFRA);
+ } else { /* SEQ_RIGHTSEL */
+ seq_tx_set_final_right(seq, CFRA);
+ }
+ seq_tx_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
+ }
+ calc_sequence(seq);
+ }
+ }
+ SEQ_END
+
+ /* test for effects and overlap */
+ SEQP_BEGIN(ed, seq) {
+ if(seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK)) {
+ seq->flag &= ~SEQ_OVERLAP;
+ if( seq_test_overlap(ed->seqbasep, seq) ) {
+ shuffle_seq(ed->seqbasep, seq);
+ }
+ }
+ else if(seq->type & SEQ_EFFECT) {
+ if(seq->seq1 && (seq->seq1->flag & SELECT))
+ calc_sequence(seq);
+ else if(seq->seq2 && (seq->seq2->flag & SELECT))
+ calc_sequence(seq);
+ else if(seq->seq3 && (seq->seq3->flag & SELECT))
+ calc_sequence(seq);
+ }
+ }
+ SEQ_END;
+
+ /* as last: */
+ sort_seq(scene);
+
+}
+
+void seq_snap_menu(Scene *scene)
+{
+ short event;
+
+ event= pupmenu("Snap %t|To Current Frame%x1");
+ if(event < 1) return;
+
+ seq_snap(scene, event);
+}
+
+/* Operator functions */
+
+static int sequencer_mute_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+ int selected;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ selected= RNA_enum_is_equal(op->ptr, "type", "SELECTED");
+
+
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ if ((seq->flag & SEQ_LOCK)==0) {
+ if(selected){ /* mute unselected */
+ if (seq->flag & SELECT) {
+ seq->flag |= SEQ_MUTE;
+ }
+ }
+ else {
+ if ((seq->flag & SELECT)==0) {
+ seq->flag |= SEQ_MUTE;
+ }
+ }
+ }
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_mute(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mute Strips";
+ ot->idname= "SEQUENCER_OT_mute";
+
+ /* api callbacks */
+ ot->exec= sequencer_mute_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", sequencer_prop_operate_types, SEQ_SELECTED, "Type", "");
+}
+
+
+/* unmute operator */
+static int sequencer_unmute_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+ int selected;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ selected= RNA_enum_is_equal(op->ptr, "type", "SELECTED");
+
+
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ if ((seq->flag & SEQ_LOCK)==0) {
+ if(selected){ /* unmute unselected */
+ if (seq->flag & SELECT) {
+ seq->flag &= ~SEQ_MUTE;
+ }
+ }
+ else {
+ if ((seq->flag & SELECT)==0) {
+ seq->flag &= ~SEQ_MUTE;
+ }
+ }
+ }
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_unmute(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "UnMute Strips";
+ ot->idname= "SEQUENCER_OT_unmute";
+
+ /* api callbacks */
+ ot->exec= sequencer_unmute_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", sequencer_prop_operate_types, SEQ_SELECTED, "Type", "");
+}
+
+
+/* lock operator */
+static int sequencer_lock_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ if (seq->flag & SELECT) {
+ seq->flag |= SEQ_LOCK;
+ }
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_lock(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Lock Strips";
+ ot->idname= "SEQUENCER_OT_lock";
+
+ /* api callbacks */
+ ot->exec= sequencer_lock_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* unlock operator */
+static int sequencer_unlock_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ if (seq->flag & SELECT) {
+ seq->flag &= ~SEQ_LOCK;
+ }
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_unlock(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "UnLock Strips";
+ ot->idname= "SEQUENCER_OT_unlock";
+
+ /* api callbacks */
+ ot->exec= sequencer_unlock_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* reload operator */
+static int sequencer_reload_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ if(seq->flag & SELECT) {
+ update_changed_seq_and_deps(scene, seq, 0, 1);
+ }
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_reload(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Reload Strips";
+ ot->idname= "SEQUENCER_OT_reload";
+
+ /* api callbacks */
+ ot->exec= sequencer_reload_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* reload operator */
+static int sequencer_refresh_all_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ free_imbuf_seq(&ed->seqbase);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Refresh Sequencer";
+ ot->idname= "SEQUENCER_OT_refresh_all";
+
+ /* api callbacks */
+ ot->exec= sequencer_refresh_all_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* cut operator */
+static EnumPropertyItem prop_cut_types[] = {
+ {SEQ_CUT_SOFT, "SOFT", "Soft", ""},
+ {SEQ_CUT_HARD, "HARD", "Hard", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int sequencer_cut_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ int cut_side, cut_hard, cut_frame;
+
+ ListBase newlist;
+ int changed;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ cut_frame= RNA_int_get(op->ptr, "frame");
+ cut_hard= RNA_enum_get(op->ptr, "type");
+ cut_side= RNA_enum_get(op->ptr, "side");
+
+ newlist.first= newlist.last= NULL;
+
+ if (cut_hard==SEQ_CUT_HARD) {
+ changed = cut_seq_list(scene,
+ ed->seqbasep, &newlist, cut_frame, cut_seq_hard);
+ } else {
+ changed = cut_seq_list(scene,
+ ed->seqbasep, &newlist, cut_frame, cut_seq_soft);
+ }
+
+ if (newlist.first) { /* got new strips ? */
+ Sequence *seq;
+ addlisttolist(ed->seqbasep, &newlist);
+
+ if (cut_side != SEQ_SIDE_BOTH) {
+ SEQP_BEGIN(ed, seq) {
+ if (cut_side==SEQ_SIDE_LEFT) {
+ if ( seq->startdisp >= cut_frame ) {
+ seq->flag &= SEQ_DESEL;
+ }
+ } else {
+ if ( seq->enddisp <= cut_frame ) {
+ seq->flag &= SEQ_DESEL;
+ }
+ }
+ }
+ SEQ_END;
+ }
+ /* as last: */
+ sort_seq(scene);
+ }
+
+ if (changed) {
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+
+static int sequencer_cut_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar= CTX_wm_region(C);
+ View2D *v2d= UI_view2d_fromcontext(C);
+
+ int cut_side, cut_frame;
+
+ cut_frame= CFRA;
+ cut_side= mouse_frame_side(v2d, event->x - ar->winrct.xmin, cut_frame);
+
+ RNA_int_set(op->ptr, "frame", cut_frame);
+ RNA_enum_set(op->ptr, "side", cut_side);
+ /*RNA_enum_set(op->ptr, "type", cut_hard); */ /*This type is set from the key shortcut */
+
+ return sequencer_cut_exec(C, op);
+}
+
+
+void SEQUENCER_OT_cut(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Cut Strips";
+ ot->idname= "SEQUENCER_OT_cut";
+
+ /* api callbacks */
+ ot->invoke= sequencer_cut_invoke;
+ ot->exec= sequencer_cut_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be cut", INT_MIN, INT_MAX);
+ RNA_def_enum(ot->srna, "type", prop_cut_types, SEQ_CUT_SOFT, "Type", "the type of cut operation to perform on strips");
+ RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side that remains selected after cutting");
+}
+
+/* duplicate operator */
+static int sequencer_add_duplicate_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ ListBase new= {NULL, NULL};
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ recurs_dupli_seq(scene, ed->seqbasep, &new);
+ addlisttolist(ed->seqbasep, &new);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+static int sequencer_add_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sequencer_add_duplicate_exec(C, op);
+
+ RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
+ WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_duplicate_add(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Add Duplicate";
+ ot->idname= "SEQUENCER_OT_duplicate_add";
+
+ /* api callbacks */
+ ot->invoke= sequencer_add_duplicate_invoke;
+ ot->exec= sequencer_add_duplicate_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* to give to transform */
+ RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+}
+
+/* delete operator */
+static int sequencer_delete_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+ MetaStack *ms;
+ int nothingSelected = TRUE;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ seq=get_last_seq(scene);
+ if (seq && seq->flag & SELECT) { /* avoid a loop since this is likely to be selected */
+ nothingSelected = FALSE;
+ } else {
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->flag & SELECT) {
+ nothingSelected = FALSE;
+ break;
+ }
+ }
+ }
+
+ if (nothingSelected)
+ return OPERATOR_FINISHED;
+
+ /* free imbufs of all dependent strips */
+ for(seq=ed->seqbasep->first; seq; seq=seq->next)
+ if(seq->flag & SELECT)
+ update_changed_seq_and_deps(scene, seq, 1, 0);
+
+ /* for effects, try to find a replacement input */
+ for(seq=ed->seqbasep->first; seq; seq=seq->next)
+ if((seq->type & SEQ_EFFECT) && !(seq->flag & SELECT))
+ del_seq_find_replace_recurs(scene, seq);
+
+ /* delete all selected strips */
+ recurs_del_seq_flag(scene, ed->seqbasep, SELECT, 0);
+
+ /* updates lengths etc */
+ seq= ed->seqbasep->first;
+ while(seq) {
+ calc_sequence(seq);
+ seq= seq->next;
+ }
+
+ /* free parent metas */
+ ms= ed->metastack.last;
+ while(ms) {
+ ms->parseq->strip->len= 0; /* force new alloc */
+ calc_sequence(ms->parseq);
+ ms= ms->prev;
+ }
+
+ //ED_area_tag_redraw(CTX_wm_area(C));
+ WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, NULL); /* redraw other sequencer views */
+
+ return OPERATOR_FINISHED;
+}
+
+
+void SEQUENCER_OT_delete(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Erase Strips";
+ ot->idname= "SEQUENCER_OT_delete";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= sequencer_delete_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+/* separate_images operator */
+static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ Sequence *seq, *seq_new, *seq_next;
+ Strip *strip_new;
+ StripElem *se, *se_new;
+ int start_ofs, cfra, frame_end;
+ static int step= 1;
+
+// add_numbut(0, NUM|INT, "Image Duration:", 1, 256, &step, NULL);
+// if (!do_clever_numbuts("Separate Images", 1, REDRAW))
+// return;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ seq= ed->seqbasep->first;
+
+ while (seq) {
+ if((seq->flag & SELECT) && (seq->type == SEQ_IMAGE) && (seq->len > 1)) {
+ /* remove seq so overlap tests dont conflict,
+ see seq_free_sequence below for the real free'ing */
+ seq_next = seq->next;
+ BLI_remlink(ed->seqbasep, seq);
+ if(seq->ipo) seq->ipo->id.us--;
+
+ start_ofs = cfra = seq_tx_get_final_left(seq, 0);
+ frame_end = seq_tx_get_final_right(seq, 0);
+
+ while (cfra < frame_end) {
+ /* new seq */
+ se = give_stripelem(seq, cfra);
+
+ seq_new= alloc_sequence(ed->seqbasep, start_ofs, seq->machine);
+ seq_new->type= SEQ_IMAGE;
+ seq_new->len = 1;
+ seq_new->endstill = step-1;
+
+ /* new strip */
+ seq_new->strip= strip_new= MEM_callocN(sizeof(Strip)*1, "strip");
+ strip_new->len= 1;
+ strip_new->us= 1;
+ strncpy(strip_new->dir, seq->strip->dir, FILE_MAXDIR-1);
+
+ /* new stripdata */
+ strip_new->stripdata= se_new= MEM_callocN(sizeof(StripElem)*1, "stripelem");
+ strncpy(se_new->name, se->name, FILE_MAXFILE-1);
+ calc_sequence(seq_new);
+ seq_new->flag &= ~SEQ_OVERLAP;
+ if (seq_test_overlap(ed->seqbasep, seq_new)) {
+ shuffle_seq(ed->seqbasep, seq_new);
+ }
+
+ cfra++;
+ start_ofs += step;
+ }
+
+ seq_free_sequence(ed, seq);
+ seq = seq->next;
+ } else {
+ seq = seq->next;
+ }
+ }
+
+ /* as last: */
+ sort_seq(scene);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+
+void SEQUENCER_OT_images_separate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Separate Images";
+ ot->idname= "SEQUENCER_OT_images_separate";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= sequencer_separate_images_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+/* META Operators */
+
+/* separate_meta_toggle operator */
+static int sequencer_meta_toggle_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *last_seq= get_last_seq(scene);
+ MetaStack *ms;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ if(last_seq && last_seq->type==SEQ_META && last_seq->flag & SELECT) {
+ /* Enter Metastrip */
+ ms= MEM_mallocN(sizeof(MetaStack), "metastack");
+ BLI_addtail(&ed->metastack, ms);
+ ms->parseq= last_seq;
+ ms->oldbasep= ed->seqbasep;
+
+ ed->seqbasep= &last_seq->seqbase;
+
+ set_last_seq(scene, NULL);
+
+ }
+ else {
+ /* Exit Metastrip (if possible) */
+
+ Sequence *seq;
+
+ if(ed->metastack.first==NULL)
+ return OPERATOR_CANCELLED;
+
+ ms= ed->metastack.last;
+ BLI_remlink(&ed->metastack, ms);
+
+ ed->seqbasep= ms->oldbasep;
+
+ /* recalc all: the meta can have effects connected to it */
+ for(seq= ed->seqbasep->first; seq; seq= seq->next)
+ calc_sequence(seq);
+
+ set_last_seq(scene, ms->parseq);
+
+ ms->parseq->flag |= SELECT;
+ recurs_sel_seq(ms->parseq);
+
+ MEM_freeN(ms);
+
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Toggle Meta Strip";
+ ot->idname= "SEQUENCER_OT_meta_toggle";
+
+ /* api callbacks */
+ ot->exec= sequencer_meta_toggle_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+/* separate_meta_make operator */
+static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ Sequence *seq, *seqm, *next;
+
+ int tot;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ /* is there more than 1 select */
+ tot= 0;
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if(seq->flag & SELECT) {
+ tot++;
+ if (seq->type == SEQ_RAM_SOUND) {
+ BKE_report(op->reports, RPT_ERROR, "Can't make Meta Strip from audio");
+ return OPERATOR_CANCELLED;;
+ }
+ }
+ seq= seq->next;
+ }
+ if(tot < 1) return OPERATOR_CANCELLED;;
+
+
+ /* test relationships */
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if(seq->flag & SELECT) {
+ if(seq->type & SEQ_EFFECT) {
+ if(seq->seq1 &&
+ (seq->seq1->flag & SELECT)==0) tot= 0;
+ if(seq->seq2 &&
+ (seq->seq2->flag & SELECT)==0) tot= 0;
+ if(seq->seq3 &&
+ (seq->seq3->flag & SELECT)==0) tot= 0;
+ }
+ }
+ else if(seq->type & SEQ_EFFECT) {
+ if(seq->seq1 &&
+ (seq->seq1->flag & SELECT)) tot= 0;
+ if(seq->seq2 &&
+ (seq->seq2->flag & SELECT)) tot= 0;
+ if(seq->seq3 &&
+ (seq->seq3->flag & SELECT)) tot= 0;
+ }
+ if(tot==0) break;
+ seq= seq->next;
+ }
+
+ if(tot==0) {
+ BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* remove all selected from main list, and put in meta */
+
+ seqm= alloc_sequence(ed->seqbasep, 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;
+
+ set_last_seq(scene, seqm);
+
+ if( seq_test_overlap(ed->seqbasep, seqm) ) shuffle_seq(ed->seqbasep, seqm);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_meta_make(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Make Meta Strip";
+ ot->idname= "SEQUENCER_OT_meta_make";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= sequencer_meta_make_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
+{
+ if (seq == seqm) return 1;
+ else if (seq->seq1 && seq_depends_on_meta(seq->seq1, seqm)) return 1;
+ else if (seq->seq2 && seq_depends_on_meta(seq->seq2, seqm)) return 1;
+ else if (seq->seq3 && seq_depends_on_meta(seq->seq3, seqm)) return 1;
+ else return 0;
+}
+
+/* separate_meta_make operator */
+static int sequencer_meta_separate_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ Sequence *seq, *last_seq = get_last_seq(scene); /* last_seq checks ed==NULL */
+
+ if(last_seq==NULL || last_seq->type!=SEQ_META)
+ return OPERATOR_CANCELLED;
+
+ addlisttolist(ed->seqbasep, &last_seq->seqbase);
+
+ last_seq->seqbase.first= 0;
+ last_seq->seqbase.last= 0;
+
+ BLI_remlink(ed->seqbasep, last_seq);
+ seq_free_sequence(ed, last_seq);
+
+ /* emtpy meta strip, delete all effects depending on it */
+ for(seq=ed->seqbasep->first; seq; seq=seq->next)
+ if((seq->type & SEQ_EFFECT) && seq_depends_on_meta(seq, last_seq))
+ seq->flag |= SEQ_FLAG_DELETE;
+
+ recurs_del_seq_flag(scene, ed->seqbasep, SEQ_FLAG_DELETE, 0);
+
+ /* test for effects and overlap */
+ SEQP_BEGIN(ed, seq) {
+ if(seq->flag & SELECT) {
+ seq->flag &= ~SEQ_OVERLAP;
+ if( seq_test_overlap(ed->seqbasep, seq) ) {
+ shuffle_seq(ed->seqbasep, seq);
+ }
+ }
+ }
+ SEQ_END;
+
+ sort_seq(scene);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "UnMeta Strip";
+ ot->idname= "SEQUENCER_OT_meta_separate";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= sequencer_meta_separate_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* view_all operator */
+static int sequencer_view_all_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ bScreen *sc= CTX_wm_screen(C);
+ ScrArea *area= CTX_wm_area(C);
+ ARegion *ar= CTX_wm_region(C);
+ SpaceSeq *sseq= area->spacedata.first;
+ View2D *v2d= UI_view2d_fromcontext(C);
+
+ if (sseq->mainb==SEQ_DRAW_SEQUENCE) {
+ v2d->cur= v2d->tot;
+ UI_view2d_curRect_validate(v2d);
+ UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
+ } else {
+ /* Like zooming on an image view */
+ float zoomX, zoomY;
+ int width, height, imgwidth, imgheight;
+
+ width = ar->winx;
+ height = ar->winy;
+
+ seq_reset_imageofs(sseq);
+
+ imgwidth= (scene->r.size*scene->r.xsch)/100;
+ imgheight= (scene->r.size*scene->r.ysch)/100;
+
+ /* Apply aspect, dosnt need to be that accurate */
+ imgwidth= (int)(imgwidth * ((float)scene->r.xasp / (float)scene->r.yasp));
+
+ if (((imgwidth >= width) || (imgheight >= height)) &&
+ ((width > 0) && (height > 0))) {
+
+ /* Find the zoom value that will fit the image in the image space */
+ zoomX = ((float)width) / ((float)imgwidth);
+ zoomY = ((float)height) / ((float)imgheight);
+ sseq->zoom= (zoomX < zoomY) ? zoomX : zoomY;
+
+ sseq->zoom = 1.0f / power_of_2(1/ MIN2(zoomX, zoomY) );
+ }
+ else {
+ sseq->zoom= 1.0f;
+ }
+ }
+
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_view_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View All";
+ ot->idname= "SEQUENCER_OT_view_all";
+
+ /* api callbacks */
+ ot->exec= sequencer_view_all_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+
+/* view_all operator */
+static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ View2D *v2d= UI_view2d_fromcontext(C);
+ ScrArea *area= CTX_wm_area(C);
+ bScreen *sc= CTX_wm_screen(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+
+ int xmin= MAXFRAME*2;
+ int xmax= -MAXFRAME*2;
+ int ymin= MAXSEQ+1;
+ int ymax= 0;
+ int orig_height;
+ int ymid;
+ int ymargin= 1;
+ int xmargin= FPS;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ for(seq=ed->seqbasep->first; seq; seq=seq->next) {
+ if(seq->flag & SELECT) {
+ xmin= MIN2(xmin, seq->startdisp);
+ xmax= MAX2(xmax, seq->enddisp);
+
+ ymin= MIN2(ymin, seq->machine);
+ ymax= MAX2(ymax, seq->machine);
+ }
+ }
+
+ if (ymax != 0) {
+
+ xmax += xmargin;
+ xmin -= xmargin;
+ ymax += ymargin;
+ ymin -= ymargin;
+
+ orig_height= v2d->cur.ymax - v2d->cur.ymin;
+
+ v2d->cur.xmin= xmin;
+ v2d->cur.xmax= xmax;
+
+ v2d->cur.ymin= ymin;
+ v2d->cur.ymax= ymax;
+
+ /* only zoom out vertically */
+ if (orig_height > v2d->cur.ymax - v2d->cur.ymin) {
+ ymid= (v2d->cur.ymax + v2d->cur.ymin) / 2;
+
+ v2d->cur.ymin= ymid - (orig_height/2);
+ v2d->cur.ymax= ymid + (orig_height/2);
+ }
+
+ UI_view2d_curRect_validate(v2d);
+ UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_view_selected(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View Selected";
+ ot->idname= "SEQUENCER_OT_view_selected";
+
+ /* api callbacks */
+ ot->exec= sequencer_view_selected_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
diff --git a/source/blender/editors/space_sequencer/sequencer_header.c b/source/blender/editors/space_sequencer/sequencer_header.c
new file mode 100644
index 00000000000..aee589cb982
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_header.c
@@ -0,0 +1,455 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_space_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_sequence.h"
+
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+#include "BIF_transform.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "sequencer_intern.h"
+
+
+/* ************************ header area region *********************** */
+
+#define B_FULL 1
+#define B_VIEW2DZOOM 2
+#define B_REDR 3
+#define B_IPOBORDER 4
+#define B_SEQCLEAR 5
+
+static uiBlock *seq_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceSeq *sseq= sa->spacedata.first;
+ View2D *v2d= UI_view2d_fromcontext(C);
+
+ uiBlock *block= uiBeginBlock(C, ar, "seq_viewmenu", UI_EMBOSSP);
+ short yco= 0, menuwidth=120;
+
+ if (sseq->mainb == SEQ_DRAW_SEQUENCE) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Play Back Animation "
+ "in all Sequence Areas|Alt A", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ }
+ else {
+ uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL,
+ "Grease Pencil...", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+ uiDefMenuSep(block);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Play Back Animation "
+ "in this window|Alt A", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ }
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Play Back Animation in all "
+ "3D Views and Sequence Areas|Alt Shift A",
+ 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiDefMenuSep(block);
+
+ uiDefMenuButO(block, "SEQUENCER_OT_view_all", NULL);
+ uiDefMenuButO(block, "SEQUENCER_OT_view_selected", NULL);
+
+ uiDefMenuSep(block);
+
+ /* Lock Time */
+ uiDefIconTextBut(block, BUTM, 1, (v2d->flag & V2D_VIEWSYNC_SCREEN_TIME)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
+ "Lock Time to Other Windows|", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+
+ /* Draw time or frames.*/
+ uiDefMenuSep(block);
+
+ if(sseq->flag & SEQ_DRAWFRAMES)
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Seconds|Ctrl T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+ else
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Frames|Ctrl T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+
+
+ if(!sa->full) uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,0, "");
+ else uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
+
+
+ if(sa->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+//static uiBlock *seq_selectmenu(bContext *C, ARegion *ar, void *arg_unused)
+static void seq_selectmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuContext(head, WM_OP_INVOKE_REGION_WIN);
+
+ uiMenuItemEnumO(head, "Strips to the Left", 0, "SEQUENCER_OT_select_active_side", "side", SEQ_SIDE_LEFT);
+ uiMenuItemEnumO(head, "Strips to the Right", 0, "SEQUENCER_OT_select_active_side", "side", SEQ_SIDE_RIGHT);
+ uiMenuSeparator(head);
+ uiMenuItemEnumO(head, "Surrounding Handles", 0, "SEQUENCER_OT_select_handles", "side", SEQ_SIDE_BOTH);
+ uiMenuItemEnumO(head, "Left Handles", 0, "SEQUENCER_OT_select_handles", "side", SEQ_SIDE_LEFT);
+ uiMenuItemEnumO(head, "Right Handles", 0, "SEQUENCER_OT_select_handles", "side", SEQ_SIDE_RIGHT);
+ uiMenuSeparator(head);
+ uiMenuItemO(head, 0, "SEQUENCER_OT_select_linked");
+ uiMenuSeparator(head);
+ uiMenuItemO(head, 0, "SEQUENCER_OT_select_linked");
+ uiMenuItemO(head, 0, "SEQUENCER_OT_select_all_toggle");
+ uiMenuItemO(head, 0, "SEQUENCER_OT_select_invert");
+}
+
+static uiBlock *seq_markermenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceSeq *sseq= sa->spacedata.first;
+
+
+ uiBlock *block= uiBeginBlock(C, ar, "seq_markermenu", UI_EMBOSSP);
+ short yco= 0, menuwidth=120;
+
+
+
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Marker|Ctrl Alt M", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate Marker|Ctrl Shift D", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Marker|Shift X", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiDefMenuSep(block);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "(Re)Name Marker|Ctrl M", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move Marker|Ctrl G", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+
+ uiDefMenuSep(block);
+
+ uiDefIconTextBut(block, BUTM, 1, (sseq->flag & SEQ_MARKER_TRANS)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
+ "Transform Markers", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+
+
+ if(sa->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+//static uiBlock *seq_addmenu_effectmenu(bContext *C, ARegion *ar, void *arg_unused)
+static void seq_addmenu_effectmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuContext(head, WM_OP_INVOKE_REGION_WIN);
+
+ uiMenuItemEnumO(head, "", 0, "SEQUENCER_OT_effect_strip_add", "type", SEQ_ADD);
+ uiMenuItemEnumO(head, "", 0, "SEQUENCER_OT_effect_strip_add", "type", SEQ_SUB);
+ uiMenuItemEnumO(head, "", 0, "SEQUENCER_OT_effect_strip_add", "type", SEQ_MUL);
+ uiMenuItemEnumO(head, "", 0, "SEQUENCER_OT_effect_strip_add", "type", SEQ_CROSS);
+ uiMenuItemEnumO(head, "", 0, "SEQUENCER_OT_effect_strip_add", "type", SEQ_GAMCROSS);
+ uiMenuItemEnumO(head, "", 0, "SEQUENCER_OT_effect_strip_add", "type", SEQ_ALPHAOVER);
+ uiMenuItemEnumO(head, "", 0, "SEQUENCER_OT_effect_strip_add", "type", SEQ_ALPHAUNDER);
+ uiMenuItemEnumO(head, "", 0, "SEQUENCER_OT_effect_strip_add", "type", SEQ_OVERDROP);
+ uiMenuItemEnumO(head, "", 0, "SEQUENCER_OT_effect_strip_add", "type", SEQ_WIPE);
+ uiMenuItemEnumO(head, "", 0, "SEQUENCER_OT_effect_strip_add", "type", SEQ_GLOW);
+ uiMenuItemEnumO(head, "", 0, "SEQUENCER_OT_effect_strip_add", "type", SEQ_TRANSFORM);
+ /* Color is an effect but moved to the other menu since its not that exciting */
+ uiMenuItemEnumO(head, "", 0, "SEQUENCER_OT_effect_strip_add", "type", SEQ_SPEED);
+ uiMenuSeparator(head);
+ uiMenuItemEnumO(head, "", 0, "SEQUENCER_OT_effect_strip_add", "type", SEQ_PLUGIN);
+}
+
+
+//static uiBlock *seq_addmenu(bContext *C, ARegion *ar, void *arg_unused)
+static void seq_addmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuLevel(head, "Effects...", seq_addmenu_effectmenu);
+ uiMenuSeparator(head);
+
+ uiMenuContext(head, WM_OP_INVOKE_REGION_WIN);
+
+#ifdef WITH_FFMPEG
+ uiMenuItemBooleanO(head, "Audio (RAM)", 0, "SEQUENCER_OT_sound_strip_add", "hd", FALSE);
+ uiMenuItemBooleanO(head, "Audio (HD)", 0, "SEQUENCER_OT_sound_strip_add", "hd", TRUE);
+#else
+ uiMenuItemO(head, 0, "SEQUENCER_OT_sound_strip_add");
+#endif
+ uiMenuItemEnumO(head, "Add Color Strip", 0, "SEQUENCER_OT_effect_strip_add", "type", SEQ_COLOR);
+
+ uiMenuItemO(head, 0, "SEQUENCER_OT_image_strip_add");
+ uiMenuItemO(head, 0, "SEQUENCER_OT_movie_strip_add");
+ uiMenuItemO(head, 0, "SEQUENCER_OT_scene_strip_add");
+#ifdef WITH_FFMPEG
+ uiMenuItemBooleanO(head, "Movie and Sound", 0, "SEQUENCER_OT_movie_strip_add", "sound", TRUE);
+#endif
+}
+
+//static uiBlock *seq_editmenu(bContext *C, ARegion *ar, void *arg_unused)
+static void seq_editmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ uiMenuContext(head, WM_OP_INVOKE_REGION_WIN);
+
+ uiMenuItemEnumO(head, "", 0, "TFM_OT_transform", "mode", TFM_TRANSLATION);
+ uiMenuItemEnumO(head, "", 0, "TFM_OT_transform", "mode", TFM_TIME_EXTEND);
+
+ // uiMenuItemO(head, 0, "SEQUENCER_OT_strip_snap"); // TODO - add this operator
+
+ uiMenuItemEnumO(head, "Cut Hard", 0, "SEQUENCER_OT_cut", "type", SEQ_CUT_HARD);
+ uiMenuItemEnumO(head, "Cut Soft", 0, "SEQUENCER_OT_cut", "type", SEQ_CUT_SOFT);
+
+ uiMenuItemO(head, 0, "SEQUENCER_OT_images_separate");
+ uiMenuSeparator(head);
+ uiMenuItemO(head, 0, "SEQUENCER_OT_duplicate_add");
+ uiMenuItemO(head, 0, "SEQUENCER_OT_delete");
+
+ if (ed && ed->act_seq) {
+ switch(ed->act_seq->type) {
+ case SEQ_EFFECT:
+ uiMenuSeparator(head);
+ uiMenuItemO(head, 0, "SEQUENCER_OT_effect_change");
+ uiMenuItemO(head, 0, "SEQUENCER_OT_effect_reassign_inputs");
+ break;
+ case SEQ_IMAGE:
+ uiMenuSeparator(head);
+ uiMenuItemO(head, 0, "SEQUENCER_OT_image_change"); // Change Scene...
+ break;
+ case SEQ_SCENE:
+ uiMenuSeparator(head);
+ uiMenuItemO(head, 0, "SEQUENCER_OT_scene_change"); // Remap Paths...
+ break;
+ case SEQ_MOVIE:
+ uiMenuSeparator(head);
+ uiMenuItemO(head, 0, "SEQUENCER_OT_movie_change"); // Remap Paths...
+ break;
+ }
+ }
+
+ uiMenuSeparator(head);
+
+ uiMenuItemO(head, 0, "SEQUENCER_OT_meta_make");
+ uiMenuItemO(head, 0, "SEQUENCER_OT_meta_separate");
+
+ if (ed && (ed->metastack.first || (ed->act_seq && ed->act_seq->type == SEQ_META))) {
+ uiMenuSeparator(head);
+ uiMenuItemO(head, 0, "SEQUENCER_OT_meta_toggle");
+ }
+ uiMenuSeparator(head);
+ uiMenuItemO(head, 0, "SEQUENCER_OT_reload");
+ uiMenuSeparator(head);
+ uiMenuItemO(head, 0, "SEQUENCER_OT_lock");
+ uiMenuItemO(head, 0, "SEQUENCER_OT_unlock");
+ uiMenuItemO(head, 0, "SEQUENCER_OT_mute");
+ uiMenuItemO(head, 0, "SEQUENCER_OT_unmute");
+
+ uiMenuItemEnumO(head, "Mute Deselected Strips", 0, "SEQUENCER_OT_mute", "type", SEQ_UNSELECTED);
+}
+
+void sequencer_header_buttons(const bContext *C, ARegion *ar)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceSeq *sseq= sa->spacedata.first;
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ uiBlock *block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
+ int xco=3, yco= 3;
+
+ xco= ED_area_header_standardbuttons(C, block, yco);
+
+ if((sa->flag & HEADER_NO_PULLDOWN)==0) {
+ int xmax;
+
+ xmax= GetButStringLength("View");
+
+ //uiDefMenuBut(block, seq_viewmenu, NULL, "View", xco, 0, xmax-3, 24, ""); // TODO
+ uiDefPulldownBut(block, seq_viewmenu, sa, "View", xco, 0, xmax-3, 24, "");
+ xco+=xmax;
+
+ xmax= GetButStringLength("Select");
+ uiDefMenuBut(block, seq_selectmenu, NULL, "Select", xco, 0, xmax-3, 24, "");
+ //uiDefPulldownBut(block, seq_selectmenu, sa, "Select", xco, 0, xmax-3, 24, "");
+ xco+=xmax;
+
+ xmax= GetButStringLength("Marker");
+ //uiDefMenuBut(block, seq_markermenu, NULL, "Marker", xco, 0, xmax-3, 24, "");
+ uiDefPulldownBut(block, seq_markermenu, sa, "Marker", xco, 0, xmax-3, 24, ""); // TODO
+ xco+=xmax;
+
+ xmax= GetButStringLength("Add");
+ uiDefMenuBut(block, seq_addmenu, NULL, "Add", xco, 0, xmax-3, 24, "");
+ //uiDefPulldownBut(block, seq_addmenu, sa, "Add", xco, 0, xmax-3, 24, "");
+ xco+=xmax;
+
+ xmax= GetButStringLength("Strip");
+ uiDefMenuBut(block, seq_editmenu, NULL, "Strip", xco, 0, xmax-3, 24, "");
+ //uiDefPulldownBut(block, seq_editmenu, sa, "Strip", xco, 0, xmax-3, 24, "");
+ xco+=xmax;
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ /* IMAGE */
+ uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_SEQ_SEQUENCER,
+ "Image Preview: %t"
+ "|Sequence %x0"
+ "|Image Preview %x1"
+ "|Luma Waveform %x2"
+ "|Chroma Vectorscope %x3"
+ "|Histogram %x4",
+ xco,yco,XIC+10,YIC, &sseq->mainb, 0.0, 3.0,
+ 0, 0,
+ "Shows the sequence output image preview");
+
+ xco+= 8 + XIC+10;
+
+ if(sseq->mainb != SEQ_DRAW_SEQUENCE) {
+ int minchan = 0;
+
+ /* CHANNEL shown in image preview */
+
+ if (ed && ed->metastack.first)
+ minchan = -BLI_countlist(&ed->metastack);
+
+ uiDefButS(block, NUM, B_REDR, "Chan:",
+ xco, yco, 3.5 * XIC,YIC,
+ &sseq->chanshown, minchan, MAXSEQ, 0, 0,
+ "The channel number shown in the image preview. 0 is the result of all strips combined.");
+
+ xco+= 8 + XIC*3.5;
+
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
+ uiDefButS(block, MENU, B_REDR,
+ "Show zebra: %t"
+ "|Z 110 %x110"
+ "|Z 100 %x100"
+ "|Z 95 %x95"
+ "|Z 90 %x90"
+ "|Z 70 %x70"
+ "|Z Off %x0",
+ xco,yco,3.0 * XIC, YIC, &sseq->zebra,
+ 0,0,0,0,
+ "Show overexposed "
+ "areas with zebra stripes");
+
+ xco+= 8 + XIC*3.0;
+
+ uiDefButBitI(block, TOG, SEQ_DRAW_SAFE_MARGINS,
+ B_REDR, "T",
+ xco,yco,XIC,YIC, &sseq->flag,
+ 0, 0, 0, 0,
+ "Draw title safe margins in preview");
+ xco+= 8 + XIC;
+ }
+
+ if (sseq->mainb == SEQ_DRAW_IMG_WAVEFORM) {
+ uiDefButBitI(block, TOG, SEQ_DRAW_COLOR_SEPERATED,
+ B_REDR, "CS",
+ xco,yco,XIC,YIC, &sseq->flag,
+ 0, 0, 0, 0,
+ "Seperate color channels in preview");
+ xco+= 8 + XIC;
+ }
+ } else {
+ /* ZOOM and BORDER */
+ static int viewmovetemp; // XXX dummy var
+
+ uiBlockBeginAlign(block);
+ uiDefIconButI(block, TOG, B_VIEW2DZOOM,
+ ICON_VIEWZOOM,
+ xco,yco,XIC,YIC, &viewmovetemp,
+ 0, 0, 0, 0,
+ "Zooms view in and out (Ctrl MiddleMouse)");
+ xco += XIC;
+ uiDefIconButO(block, BUT, "VIEW2D_OT_zoom_border", WM_OP_INVOKE_REGION_WIN, ICON_BORDERMOVE, xco,yco,XIC,YIC, "Zooms view to fit area");
+
+ uiBlockEndAlign(block);
+ xco += 8 + XIC;
+ }
+
+ uiDefButO(block, BUT, "SEQUENCER_OT_refresh_all", WM_OP_EXEC_DEFAULT, "Refresh", xco, yco, 3*XIC, YIC, "Clears all buffered images in memory");
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ /* always as last */
+ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+}
+
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
new file mode 100644
index 00000000000..df6a848696f
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -0,0 +1,144 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_SEQUENCER_INTERN_H
+#define ED_SEQUENCER_INTERN_H
+
+#include "RNA_access.h"
+#include "DNA_sequence_types.h"
+
+/* internal exports only */
+
+struct Sequence;
+struct bContext;
+struct rctf;
+struct SpaceSeq;
+struct ARegion;
+struct Scene;
+
+/* sequencer_header.c */
+void sequencer_header_buttons(const struct bContext *C, struct ARegion *ar);
+
+/* sequencer_draw.c */
+void drawseqspace(const struct bContext *C, struct ARegion *ar);
+void seq_reset_imageofs(struct SpaceSeq *sseq);
+
+/* sequencer_edit.c */
+struct View2D;
+int check_single_seq(struct Sequence *seq);
+int seq_tx_get_final_left(struct Sequence *seq, int metaclip);
+int seq_tx_get_final_right(struct Sequence *seq, int metaclip);
+void seq_rectf(struct Sequence *seq, struct rctf *rectf);
+void boundbox_seq(struct Scene *scene, struct rctf *rect);
+struct Sequence *get_last_seq(struct Scene *scene);
+struct Sequence *find_nearest_seq(struct Scene *scene, struct View2D *v2d, int *hand, short mval[2]);
+struct Sequence *find_neighboring_sequence(struct Scene *scene, struct Sequence *test, int lr, int sel);
+void deselect_all_seq(struct Scene *scene);
+void recurs_sel_seq(struct Sequence *seqm);
+int event_to_efftype(int event);
+void set_last_seq(struct Scene *scene, struct Sequence *seq);
+int seq_effect_find_selected(struct Scene *scene, struct Sequence *activeseq, int type, struct Sequence **selseq1, struct Sequence **selseq2, struct Sequence **selseq3, char **error_str);
+struct Sequence *alloc_sequence(struct ListBase *lb, int cfra, int machine);
+
+/* externs */
+extern EnumPropertyItem sequencer_prop_effect_types[];
+extern EnumPropertyItem prop_side_types[];
+
+/* operators */
+struct wmOperatorType;
+struct wmWindowManager;
+void SEQUENCER_OT_cut(struct wmOperatorType *ot);
+void SEQUENCER_OT_mute(struct wmOperatorType *ot);
+void SEQUENCER_OT_unmute(struct wmOperatorType *ot);
+void SEQUENCER_OT_lock(struct wmOperatorType *ot);
+void SEQUENCER_OT_unlock(struct wmOperatorType *ot);
+void SEQUENCER_OT_reload(struct wmOperatorType *ot);
+void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot);
+void SEQUENCER_OT_duplicate_add(struct wmOperatorType *ot);
+void SEQUENCER_OT_delete(struct wmOperatorType *ot);
+void SEQUENCER_OT_images_separate(struct wmOperatorType *ot);
+void SEQUENCER_OT_meta_toggle(struct wmOperatorType *ot);
+void SEQUENCER_OT_meta_make(struct wmOperatorType *ot);
+void SEQUENCER_OT_meta_separate(struct wmOperatorType *ot);
+
+void SEQUENCER_OT_view_all(struct wmOperatorType *ot);
+void SEQUENCER_OT_view_selected(struct wmOperatorType *ot);
+
+/* sequencer_select.c */
+void SEQUENCER_OT_select_all_toggle(struct wmOperatorType *ot);
+void SEQUENCER_OT_select(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_more(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_less(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_linked(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_linked_pick(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_handles(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_active_side(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_border(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_invert(struct wmOperatorType *ot);
+
+
+/* sequencer_select.c */
+void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot);
+void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot);
+void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot);
+void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot);
+void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot);
+
+/* RNA enums, just to be more readable */
+enum {
+ SEQ_SIDE_NONE=0,
+ SEQ_SIDE_LEFT,
+ SEQ_SIDE_RIGHT,
+ SEQ_SIDE_BOTH,
+};
+enum {
+ SEQ_CUT_SOFT,
+ SEQ_CUT_HARD,
+};
+enum {
+ SEQ_SELECTED,
+ SEQ_UNSELECTED,
+};
+
+/* defines used internally */
+#define SEQ_ALLSEL (SELECT+SEQ_LEFTSEL+SEQ_RIGHTSEL)
+#define SEQ_DESEL ~SEQ_ALLSEL
+#define SCE_MARKERS 0 // XXX - dummy
+
+/* sequencer_ops.c */
+void sequencer_operatortypes(void);
+void sequencer_keymap(struct wmWindowManager *wm);
+
+/* sequencer_scope.c */
+struct ImBuf *make_waveform_view_from_ibuf(struct ImBuf * ibuf);
+struct ImBuf *make_sep_waveform_view_from_ibuf(struct ImBuf * ibuf);
+struct ImBuf *make_vectorscope_view_from_ibuf(struct ImBuf * ibuf);
+struct ImBuf *make_zebra_view_from_ibuf(struct ImBuf * ibuf, float perc);
+struct ImBuf *make_histogram_view_from_ibuf(struct ImBuf * ibuf);
+
+#endif /* ED_SEQUENCER_INTERN_H */
+
diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c
new file mode 100644
index 00000000000..b131061782a
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -0,0 +1,182 @@
+
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "BIF_transform.h" /* transform keymap */
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+
+#include "sequencer_intern.h"
+
+
+/* ************************** registration **********************************/
+
+
+void sequencer_operatortypes(void)
+{
+ /* sequencer_edit.c */
+ WM_operatortype_append(SEQUENCER_OT_cut);
+ WM_operatortype_append(SEQUENCER_OT_mute);
+ WM_operatortype_append(SEQUENCER_OT_unmute);
+ WM_operatortype_append(SEQUENCER_OT_lock);
+ WM_operatortype_append(SEQUENCER_OT_unlock);
+ WM_operatortype_append(SEQUENCER_OT_reload);
+ WM_operatortype_append(SEQUENCER_OT_refresh_all);
+ WM_operatortype_append(SEQUENCER_OT_duplicate_add);
+ WM_operatortype_append(SEQUENCER_OT_delete);
+ WM_operatortype_append(SEQUENCER_OT_images_separate);
+ WM_operatortype_append(SEQUENCER_OT_meta_toggle);
+ WM_operatortype_append(SEQUENCER_OT_meta_make);
+ WM_operatortype_append(SEQUENCER_OT_meta_separate);
+
+ WM_operatortype_append(SEQUENCER_OT_view_all);
+ WM_operatortype_append(SEQUENCER_OT_view_selected);
+
+ /* sequencer_select.c */
+ WM_operatortype_append(SEQUENCER_OT_select_all_toggle);
+ WM_operatortype_append(SEQUENCER_OT_select_invert);
+ WM_operatortype_append(SEQUENCER_OT_select);
+ WM_operatortype_append(SEQUENCER_OT_select_more);
+ WM_operatortype_append(SEQUENCER_OT_select_less);
+ WM_operatortype_append(SEQUENCER_OT_select_linked_pick);
+ WM_operatortype_append(SEQUENCER_OT_select_linked);
+ WM_operatortype_append(SEQUENCER_OT_select_handles);
+ WM_operatortype_append(SEQUENCER_OT_select_active_side);
+ WM_operatortype_append(SEQUENCER_OT_select_border);
+
+ /* sequencer_add.c */
+ WM_operatortype_append(SEQUENCER_OT_scene_strip_add);
+ WM_operatortype_append(SEQUENCER_OT_movie_strip_add);
+ WM_operatortype_append(SEQUENCER_OT_sound_strip_add);
+ WM_operatortype_append(SEQUENCER_OT_image_strip_add);
+ WM_operatortype_append(SEQUENCER_OT_effect_strip_add);
+}
+
+
+void sequencer_keymap(wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "Sequencer", SPACE_SEQ, 0);
+ wmKeymapItem *kmi;
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_select_invert", IKEY, KM_PRESS, KM_CTRL, 0);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_cut", KKEY, KM_PRESS, 0, 0)->ptr, "type", SEQ_CUT_SOFT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_cut", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", SEQ_CUT_HARD);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_mute", HKEY, KM_PRESS, 0, 0)->ptr, "type", SEQ_SELECTED);
+ RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_mute", HKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", SEQ_UNSELECTED);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_unmute", HKEY, KM_PRESS, KM_ALT, 0)->ptr, "type", SEQ_SELECTED);
+ RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_unmute", HKEY, KM_PRESS, KM_ALT|KM_SHIFT, 0)->ptr, "type", SEQ_UNSELECTED);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_lock", LKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_unlock", HKEY, KM_PRESS, KM_SHIFT|KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_reload", RKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_duplicate_add", DKEY, KM_PRESS, KM_SHIFT, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_delete", DELKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_images_separate", YKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_meta_toggle", TABKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_meta_make", MKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_meta_separate", MKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
+
+
+ /* Mouse selection, a bit verbose :/ */
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "linked_left", 1);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "linked_right", 1);
+
+ kmi= WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_CTRL|KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "linked_left", 1);
+ RNA_boolean_set(kmi->ptr, "linked_right", 1);
+
+ kmi= WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT|KM_CTRL|KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+ RNA_boolean_set(kmi->ptr, "linked_left", 1);
+ RNA_boolean_set(kmi->ptr, "linked_right", 1);
+
+ kmi= WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+ RNA_boolean_set(kmi->ptr, "linked_left", 1);
+
+ kmi= WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT|KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+ RNA_boolean_set(kmi->ptr, "linked_right", 1);
+
+
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_select_linked_pick", LKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_select_linked_pick", LKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_select_border", BKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_verify_item(keymap, "ANIM_OT_change_frame", LEFTMOUSE, KM_PRESS, 0, 0);
+
+ transform_keymap_for_space(wm, keymap, SPACE_SEQ);
+}
+
diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c
new file mode 100644
index 00000000000..e26f445ae44
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_scopes.c
@@ -0,0 +1,701 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Peter Schlaile < peter [at] schlaile [dot] de >
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "BKE_utildefines.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "sequencer_intern.h"
+
+static void rgb_to_yuv(float rgb[3], float yuv[3])
+{
+ yuv[0]= 0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2];
+ yuv[1]= 0.492*(rgb[2] - yuv[0]);
+ yuv[2]= 0.877*(rgb[0] - yuv[0]);
+
+ /* Normalize */
+ yuv[1]*= 255.0/(122*2.0);
+ yuv[1]+= 0.5;
+
+ yuv[2]*= 255.0/(157*2.0);
+ yuv[2]+= 0.5;
+}
+
+static void scope_put_pixel(unsigned char* table, unsigned char * pos)
+{
+ char newval = table[*pos];
+ pos[0] = pos[1] = pos[2] = newval;
+ pos[3] = 255;
+}
+
+static void scope_put_pixel_single(unsigned char* table, unsigned char * pos,
+ int col)
+{
+ char newval = table[pos[col]];
+ pos[col] = newval;
+ pos[3] = 255;
+}
+
+static void wform_put_line(int w,
+ unsigned char * last_pos, unsigned char * new_pos)
+{
+ if (last_pos > new_pos) {
+ unsigned char* temp = new_pos;
+ new_pos = last_pos;
+ last_pos = temp;
+ }
+
+ while (last_pos < new_pos) {
+ if (last_pos[0] == 0) {
+ last_pos[0] = last_pos[1] = last_pos[2] = 32;
+ last_pos[3] = 255;
+ }
+ last_pos += 4*w;
+ }
+}
+
+static void wform_put_line_single(
+ int w, unsigned char * last_pos, unsigned char * new_pos, int col)
+{
+ if (last_pos > new_pos) {
+ unsigned char* temp = new_pos;
+ new_pos = last_pos;
+ last_pos = temp;
+ }
+
+ while (last_pos < new_pos) {
+ if (last_pos[col] == 0) {
+ last_pos[col] = 32;
+ last_pos[3] = 255;
+ }
+ last_pos += 4*w;
+ }
+}
+
+static void wform_put_border(unsigned char * tgt, int w, int h)
+{
+ int x, y;
+
+ for (x = 0; x < w; x++) {
+ unsigned char * p = tgt + 4 * x;
+ p[1] = p[3] = 255.0;
+ p[4 * w + 1] = p[4 * w + 3] = 255.0;
+ p = tgt + 4 * (w * (h - 1) + x);
+ p[1] = p[3] = 255.0;
+ p[-4 * w + 1] = p[-4 * w + 3] = 255.0;
+ }
+
+ for (y = 0; y < h; y++) {
+ unsigned char * p = tgt + 4 * w * y;
+ p[1] = p[3] = 255.0;
+ p[4 + 1] = p[4 + 3] = 255.0;
+ p = tgt + 4 * (w * y + w - 1);
+ p[1] = p[3] = 255.0;
+ p[-4 + 1] = p[-4 + 3] = 255.0;
+ }
+}
+
+static void wform_put_gridrow(unsigned char * tgt, float perc, int w, int h)
+{
+ int i;
+
+ tgt += (int) (perc/100.0 * h) * w * 4;
+
+ for (i = 0; i < w*2; i++) {
+ tgt[0] = 255;
+
+ tgt += 4;
+ }
+}
+
+static void wform_put_grid(unsigned char * tgt, int w, int h)
+{
+ wform_put_gridrow(tgt, 90.0, w, h);
+ wform_put_gridrow(tgt, 70.0, w, h);
+ wform_put_gridrow(tgt, 10.0, w, h);
+}
+
+static struct ImBuf *make_waveform_view_from_ibuf_byte(struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect, 0);
+ int x,y;
+ unsigned char* src = (unsigned char*) ibuf->rect;
+ unsigned char* tgt = (unsigned char*) rval->rect;
+ int w = ibuf->x + 3;
+ int h = 515;
+ float waveform_gamma = 0.2;
+ unsigned char wtable[256];
+
+ wform_put_grid(tgt, w, h);
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
+ waveform_gamma)*255);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ unsigned char * last_p = 0;
+
+ for (x = 0; x < ibuf->x; x++) {
+ unsigned char * rgb = src + 4 * (ibuf->x * y + x);
+ float v = 1.0 *
+ ( 0.299*rgb[0]
+ + 0.587*rgb[1]
+ + 0.114*rgb[2]) / 255.0;
+ unsigned char * p = tgt;
+ p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1);
+
+ scope_put_pixel(wtable, p);
+ p += 4 * w;
+ scope_put_pixel(wtable, p);
+
+ if (last_p != 0) {
+ wform_put_line(w, last_p, p);
+ }
+ last_p = p;
+ }
+ }
+
+ wform_put_border(tgt, w, h);
+
+ return rval;
+}
+
+static struct ImBuf *make_waveform_view_from_ibuf_float(struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect, 0);
+ int x,y;
+ float* src = ibuf->rect_float;
+ unsigned char* tgt = (unsigned char*) rval->rect;
+ int w = ibuf->x + 3;
+ int h = 515;
+ float waveform_gamma = 0.2;
+ unsigned char wtable[256];
+
+ wform_put_grid(tgt, w, h);
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
+ waveform_gamma)*255);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ unsigned char * last_p = 0;
+
+ for (x = 0; x < ibuf->x; x++) {
+ float * rgb = src + 4 * (ibuf->x * y + x);
+ float v = 1.0 *
+ ( 0.299*rgb[0]
+ + 0.587*rgb[1]
+ + 0.114*rgb[2]);
+ unsigned char * p = tgt;
+
+ CLAMP(v, 0.0, 1.0);
+
+ p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1);
+
+ scope_put_pixel(wtable, p);
+ p += 4 * w;
+ scope_put_pixel(wtable, p);
+
+ if (last_p != 0) {
+ wform_put_line(w, last_p, p);
+ }
+ last_p = p;
+ }
+ }
+
+ wform_put_border(tgt, w, h);
+
+ return rval;
+}
+
+struct ImBuf *make_waveform_view_from_ibuf(struct ImBuf * ibuf)
+{
+ if (ibuf->rect_float) {
+ return make_waveform_view_from_ibuf_float(ibuf);
+ } else {
+ return make_waveform_view_from_ibuf_byte(ibuf);
+ }
+}
+
+
+static struct ImBuf *make_sep_waveform_view_from_ibuf_byte(struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(
+ ibuf->x + 3, 515, 32, IB_rect, 0);
+ int x,y;
+ unsigned char* src = (unsigned char*) ibuf->rect;
+ unsigned char* tgt = (unsigned char*) rval->rect;
+ int w = ibuf->x + 3;
+ int sw = ibuf->x/3;
+ int h = 515;
+ float waveform_gamma = 0.2;
+ unsigned char wtable[256];
+
+ wform_put_grid(tgt, w, h);
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
+ waveform_gamma)*255);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ unsigned char * last_p[3] = {0,0,0};
+
+ for (x = 0; x < ibuf->x; x++) {
+ int c;
+ unsigned char * rgb = src + 4 * (ibuf->x * y + x);
+ for (c = 0; c < 3; c++) {
+ unsigned char * p = tgt;
+ p += 4 * (w * ((rgb[c] * (h - 3))/255 + 1)
+ + c * sw + x/3 + 1);
+
+ scope_put_pixel_single(wtable, p, c);
+ p += 4 * w;
+ scope_put_pixel_single(wtable, p, c);
+
+ if (last_p[c] != 0) {
+ wform_put_line_single(
+ w, last_p[c], p, c);
+ }
+ last_p[c] = p;
+ }
+ }
+ }
+
+ wform_put_border(tgt, w, h);
+
+ return rval;
+}
+
+static struct ImBuf *make_sep_waveform_view_from_ibuf_float(
+ struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(
+ ibuf->x + 3, 515, 32, IB_rect, 0);
+ int x,y;
+ float* src = ibuf->rect_float;
+ unsigned char* tgt = (unsigned char*) rval->rect;
+ int w = ibuf->x + 3;
+ int sw = ibuf->x/3;
+ int h = 515;
+ float waveform_gamma = 0.2;
+ unsigned char wtable[256];
+
+ wform_put_grid(tgt, w, h);
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
+ waveform_gamma)*255);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ unsigned char * last_p[3] = {0, 0, 0};
+
+ for (x = 0; x < ibuf->x; x++) {
+ int c;
+ float * rgb = src + 4 * (ibuf->x * y + x);
+ for (c = 0; c < 3; c++) {
+ unsigned char * p = tgt;
+ float v = rgb[c];
+
+ CLAMP(v, 0.0, 1.0);
+
+ p += 4 * (w * ((int) (v * (h - 3)) + 1)
+ + c * sw + x/3 + 1);
+
+ scope_put_pixel_single(wtable, p, c);
+ p += 4 * w;
+ scope_put_pixel_single(wtable, p, c);
+
+ if (last_p[c] != 0) {
+ wform_put_line_single(
+ w, last_p[c], p, c);
+ }
+ last_p[c] = p;
+ }
+ }
+ }
+
+ wform_put_border(tgt, w, h);
+
+ return rval;
+}
+
+struct ImBuf *make_sep_waveform_view_from_ibuf(struct ImBuf * ibuf)
+{
+ if (ibuf->rect_float) {
+ return make_sep_waveform_view_from_ibuf_float(ibuf);
+ } else {
+ return make_sep_waveform_view_from_ibuf_byte(ibuf);
+ }
+}
+
+static void draw_zebra_byte(struct ImBuf * src,struct ImBuf * ibuf, float perc)
+{
+ unsigned int limit = 255 * perc / 100.0;
+ unsigned char * p = (unsigned char*) src->rect;
+ unsigned char * o = (unsigned char*) ibuf->rect;
+ int x;
+ int y;
+
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ unsigned char r = *p++;
+ unsigned char g = *p++;
+ unsigned char b = *p++;
+ unsigned char a = *p++;
+
+ if (r >= limit || g >= limit || b >= limit) {
+ if (((x + y) & 0x08) != 0) {
+ r = 255 - r;
+ g = 255 - g;
+ b = 255 - b;
+ }
+ }
+ *o++ = r;
+ *o++ = g;
+ *o++ = b;
+ *o++ = a;
+ }
+ }
+}
+
+
+static void draw_zebra_float(struct ImBuf * src,struct ImBuf * ibuf,float perc)
+{
+ float limit = perc / 100.0;
+ float * p = src->rect_float;
+ unsigned char * o = (unsigned char*) ibuf->rect;
+ int x;
+ int y;
+
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ float r = *p++;
+ float g = *p++;
+ float b = *p++;
+ float a = *p++;
+
+ if (r >= limit || g >= limit || b >= limit) {
+ if (((x + y) & 0x08) != 0) {
+ r = -r;
+ g = -g;
+ b = -b;
+ }
+ }
+
+ *o++ = FTOCHAR(r);
+ *o++ = FTOCHAR(g);
+ *o++ = FTOCHAR(b);
+ *o++ = FTOCHAR(a);
+ }
+ }
+}
+
+struct ImBuf * make_zebra_view_from_ibuf(struct ImBuf * src, float perc)
+{
+ struct ImBuf * ibuf = IMB_allocImBuf(src->x, src->y, 32, IB_rect, 0);
+
+ if (src->rect_float) {
+ draw_zebra_float(src, ibuf, perc);
+ } else {
+ draw_zebra_byte(src, ibuf, perc);
+ }
+ return ibuf;
+}
+
+static void draw_histogram_marker(struct ImBuf * ibuf, int x)
+{
+ unsigned char * p = (unsigned char*) ibuf->rect;
+ int barh = ibuf->y * 0.1;
+ int i;
+
+ p += 4 * (x + ibuf->x * (ibuf->y - barh + 1));
+
+ for (i = 0; i < barh-1; i++) {
+ p[0] = p[1] = p[2] = 255;
+ p += ibuf->x * 4;
+ }
+}
+
+static void draw_histogram_bar(struct ImBuf * ibuf, int x,float val, int col)
+{
+ unsigned char * p = (unsigned char*) ibuf->rect;
+ int barh = ibuf->y * val * 0.9;
+ int i;
+
+ p += 4 * (x + ibuf->x);
+
+ for (i = 0; i < barh; i++) {
+ p[col] = 255;
+ p += ibuf->x * 4;
+ }
+}
+
+static struct ImBuf *make_histogram_view_from_ibuf_byte(
+ struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(515, 128, 32, IB_rect, 0);
+ int n,c,x,y;
+ unsigned char* src = (unsigned char*) ibuf->rect;
+
+ unsigned int bins[3][256];
+
+ memset(bins, 0, 3 * 256* sizeof(unsigned int));
+
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ bins[0][*src++]++;
+ bins[1][*src++]++;
+ bins[2][*src++]++;
+ src++;
+ }
+ }
+
+ n = 0;
+ for (c = 0; c < 3; c++) {
+ for (x = 0; x < 256; x++) {
+ if (bins[c][x] > n) {
+ n = bins[c][x];
+ }
+ }
+ }
+
+ for (c = 0; c < 3; c++) {
+ for (x = 0; x < 256; x++) {
+ draw_histogram_bar(rval, x*2+1,
+ ((float) bins[c][x])/n, c);
+ draw_histogram_bar(rval, x*2+2,
+ ((float) bins[c][x])/n, c);
+ }
+ }
+
+ wform_put_border((unsigned char*) rval->rect, rval->x, rval->y);
+
+ return rval;
+}
+
+static int get_bin_float(float f)
+{
+ if (f < -0.25) {
+ f = -0.25;
+ } else if (f > 1.25) {
+ f = 1.25;
+ }
+
+ return (int) (((f + 0.25) / 1.5) * 512);
+}
+
+static struct ImBuf *make_histogram_view_from_ibuf_float(
+ struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(515, 128, 32, IB_rect, 0);
+ int n,c,x,y;
+ float* src = ibuf->rect_float;
+
+ unsigned int bins[3][512];
+
+ memset(bins, 0, 3 * 256* sizeof(unsigned int));
+
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ bins[0][get_bin_float(*src++)]++;
+ bins[1][get_bin_float(*src++)]++;
+ bins[2][get_bin_float(*src++)]++;
+ src++;
+ }
+ }
+
+ draw_histogram_marker(rval, get_bin_float(0.0));
+ draw_histogram_marker(rval, get_bin_float(1.0));
+
+ n = 0;
+ for (c = 0; c < 3; c++) {
+ for (x = 0; x < 512; x++) {
+ if (bins[c][x] > n) {
+ n = bins[c][x];
+ }
+ }
+ }
+ for (c = 0; c < 3; c++) {
+ for (x = 0; x < 512; x++) {
+ draw_histogram_bar(rval, x+1, (float) bins[c][x]/n, c);
+ }
+ }
+
+ wform_put_border((unsigned char*) rval->rect, rval->x, rval->y);
+
+ return rval;
+}
+
+struct ImBuf *make_histogram_view_from_ibuf(struct ImBuf * ibuf)
+{
+ if (ibuf->rect_float) {
+ return make_histogram_view_from_ibuf_float(ibuf);
+ } else {
+ return make_histogram_view_from_ibuf_byte(ibuf);
+ }
+}
+
+static void vectorscope_put_cross(unsigned char r, unsigned char g,
+ unsigned char b,
+ char * tgt, int w, int h, int size)
+{
+ float rgb[3], yuv[3];
+ char * p;
+ int x = 0;
+ int y = 0;
+
+ rgb[0]= (float)r/255.0;
+ rgb[1]= (float)g/255.0;
+ rgb[2]= (float)b/255.0;
+ rgb_to_yuv(rgb, yuv);
+
+ p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1))
+ + (int) ((yuv[1] * (w - 3) + 1)));
+
+ if (r == 0 && g == 0 && b == 0) {
+ r = 255;
+ }
+
+ for (y = -size; y <= size; y++) {
+ for (x = -size; x <= size; x++) {
+ char * q = p + 4 * (y * w + x);
+ q[0] = r; q[1] = g; q[2] = b; q[3] = 255;
+ }
+ }
+}
+
+static struct ImBuf *make_vectorscope_view_from_ibuf_byte(struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(515, 515, 32, IB_rect, 0);
+ int x,y;
+ char* src = (char*) ibuf->rect;
+ char* tgt = (char*) rval->rect;
+ float rgb[3], yuv[3];
+ int w = 515;
+ int h = 515;
+ float scope_gamma = 0.2;
+ unsigned char wtable[256];
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
+ scope_gamma)*255);
+ }
+
+ for (x = 0; x <= 255; x++) {
+ vectorscope_put_cross(255 , 0,255 - x, tgt, w, h, 1);
+ vectorscope_put_cross(255 , x, 0, tgt, w, h, 1);
+ vectorscope_put_cross(255- x, 255, 0, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
+ vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ char * src1 = src + 4 * (ibuf->x * y + x);
+ char * p;
+
+ rgb[0]= (float)src1[0]/255.0;
+ rgb[1]= (float)src1[1]/255.0;
+ rgb[2]= (float)src1[2]/255.0;
+ rgb_to_yuv(rgb, yuv);
+
+ p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1))
+ + (int) ((yuv[1] * (w - 3) + 1)));
+ scope_put_pixel(wtable, (unsigned char*)p);
+ }
+ }
+
+ vectorscope_put_cross(0, 0, 0, tgt, w, h, 3);
+
+ return rval;
+}
+
+static struct ImBuf *make_vectorscope_view_from_ibuf_float(struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(515, 515, 32, IB_rect, 0);
+ int x,y;
+ float* src = ibuf->rect_float;
+ char* tgt = (char*) rval->rect;
+ float rgb[3], yuv[3];
+ int w = 515;
+ int h = 515;
+ float scope_gamma = 0.2;
+ unsigned char wtable[256];
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
+ scope_gamma)*255);
+ }
+
+ for (x = 0; x <= 255; x++) {
+ vectorscope_put_cross(255 , 0,255 - x, tgt, w, h, 1);
+ vectorscope_put_cross(255 , x, 0, tgt, w, h, 1);
+ vectorscope_put_cross(255- x, 255, 0, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
+ vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ float * src1 = src + 4 * (ibuf->x * y + x);
+ char * p;
+
+ memcpy(rgb, src1, 3 * sizeof(float));
+
+ CLAMP(rgb[0], 0.0, 1.0);
+ CLAMP(rgb[1], 0.0, 1.0);
+ CLAMP(rgb[2], 0.0, 1.0);
+
+ rgb_to_yuv(rgb, yuv);
+
+ p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1))
+ + (int) ((yuv[1] * (w - 3) + 1)));
+ scope_put_pixel(wtable, (unsigned char*)p);
+ }
+ }
+
+ vectorscope_put_cross(0, 0, 0, tgt, w, h, 3);
+
+ return rval;
+}
+
+struct ImBuf *make_vectorscope_view_from_ibuf(struct ImBuf * ibuf)
+{
+ if (ibuf->rect_float) {
+ return make_vectorscope_view_from_ibuf_float(ibuf);
+ } else {
+ return make_vectorscope_view_from_ibuf_byte(ibuf);
+ }
+}
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
new file mode 100644
index 00000000000..bfd89ccdffb
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -0,0 +1,819 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2003-2009, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+#include <sys/types.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_curve_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_context.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_sequence.h"
+#include "BKE_scene.h"
+#include "BKE_utildefines.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+/* for menu/popup icons etc etc*/
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "ED_anim_api.h"
+#include "ED_space_api.h"
+#include "ED_types.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+/* own include */
+#include "sequencer_intern.h"
+static void *find_nearest_marker() {return NULL;}
+static void deselect_markers() {}
+
+void select_surrounding_handles(Scene *scene, Sequence *test) /* XXX BRING BACK */
+{
+ Sequence *neighbor;
+
+ neighbor=find_neighboring_sequence(scene, test, SEQ_SIDE_LEFT, -1);
+ if (neighbor) {
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_RIGHTSEL;
+ }
+ neighbor=find_neighboring_sequence(scene, test, SEQ_SIDE_RIGHT, -1);
+ if (neighbor) {
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_LEFTSEL;
+ }
+ test->flag |= SELECT;
+}
+
+/* used for mouse selection and for SEQUENCER_OT_select_active_side() */
+static void select_active_side(ListBase *seqbase, int sel_side, int channel, int frame)
+{
+ Sequence *seq;
+
+ for(seq= seqbase->first; seq; seq=seq->next) {
+ if(channel==seq->machine) {
+ switch(sel_side) {
+ case SEQ_SIDE_LEFT:
+ if (frame > (seq->startdisp)) {
+ seq->flag &= ~(SEQ_RIGHTSEL|SEQ_LEFTSEL);
+ seq->flag |= SELECT;
+ }
+ break;
+ case SEQ_SIDE_RIGHT:
+ if (frame < (seq->startdisp)) {
+ seq->flag &= ~(SEQ_RIGHTSEL|SEQ_LEFTSEL);
+ seq->flag |= SELECT;
+ }
+ break;
+ case SEQ_SIDE_BOTH:
+ seq->flag &= ~(SEQ_RIGHTSEL|SEQ_LEFTSEL);
+ break;
+ }
+ }
+ }
+}
+
+#if 0 // BRING BACK
+void select_surround_from_last(Scene *scene)
+{
+ Sequence *seq=get_last_seq(scene);
+
+ if (seq==NULL)
+ return;
+
+ select_surrounding_handles(scene, seq);
+}
+#endif
+
+
+void select_single_seq(Scene *scene, Sequence *seq, int deselect_all) /* BRING BACK */
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ if(deselect_all)
+ deselect_all_seq(scene);
+ set_last_seq(scene, seq);
+
+ if((seq->type==SEQ_IMAGE) || (seq->type==SEQ_MOVIE)) {
+ if(seq->strip)
+ strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR-1);
+ }
+ else if((seq->type==SEQ_HD_SOUND) || (seq->type==SEQ_RAM_SOUND)) {
+ if(seq->strip)
+ strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR-1);
+ }
+ seq->flag|= SELECT;
+ recurs_sel_seq(seq);
+}
+
+// remove this function, replace with invert operator
+//void swap_select_seq(Scene *scene)
+
+void select_neighbor_from_last(Scene *scene, int lr)
+{
+ Sequence *seq=get_last_seq(scene);
+ Sequence *neighbor;
+ int change = 0;
+ if (seq) {
+ neighbor=find_neighboring_sequence(scene, seq, lr, -1);
+ if (neighbor) {
+ switch (lr) {
+ case SEQ_SIDE_LEFT:
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_RIGHTSEL;
+ seq->flag |= SEQ_LEFTSEL;
+ break;
+ case SEQ_SIDE_RIGHT:
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_LEFTSEL;
+ seq->flag |= SEQ_RIGHTSEL;
+ break;
+ }
+ seq->flag |= SELECT;
+ change = 1;
+ }
+ }
+ if (change) {
+ }
+}
+
+
+/* (de)select operator */
+static int sequencer_deselect_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+ int desel = 0;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ for(seq= ed->seqbasep->first; seq; seq=seq->next) {
+ if(seq->flag & SEQ_ALLSEL) {
+ desel= 1;
+ break;
+ }
+ }
+
+ for(seq= ed->seqbasep->first; seq; seq=seq->next) {
+ if (desel) {
+ seq->flag &= SEQ_DESEL;
+ }
+ else {
+ seq->flag &= (SEQ_LEFTSEL+SEQ_RIGHTSEL);
+ seq->flag |= SELECT;
+ }
+ }
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_all_toggle(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "(De)Select All";
+ ot->idname= "SEQUENCER_OT_select_all_toggle";
+
+ /* api callbacks */
+ ot->exec= sequencer_deselect_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+/* (de)select operator */
+static int sequencer_select_invert_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ for(seq= ed->seqbasep->first; seq; seq=seq->next) {
+ if (seq->flag & SELECT) {
+ seq->flag &= SEQ_DESEL;
+ }
+ else {
+ seq->flag &= (SEQ_LEFTSEL+SEQ_RIGHTSEL);
+ seq->flag |= SELECT;
+ }
+ }
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_invert(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Invert";
+ ot->idname= "SEQUENCER_OT_select_invert";
+
+ /* api callbacks */
+ ot->exec= sequencer_select_invert_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int sequencer_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ View2D *v2d= UI_view2d_fromcontext(C);
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ short extend= RNA_boolean_get(op->ptr, "extend");
+ short linked_left= RNA_boolean_get(op->ptr, "linked_left");
+ short linked_right= RNA_boolean_get(op->ptr, "linked_right");
+
+ short mval[2];
+
+ Sequence *seq,*neighbor;
+ int hand,sel_side, shift= 0; // XXX
+ TimeMarker *marker;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ marker=find_nearest_marker(SCE_MARKERS, 1); //XXX - dummy function for now
+
+ mval[0]= event->x - ar->winrct.xmin;
+ mval[1]= event->y - ar->winrct.ymin;
+
+ if (marker) {
+ int oldflag;
+ /* select timeline marker */
+ if (shift) {
+ oldflag= marker->flag;
+ if (oldflag & SELECT)
+ marker->flag &= ~SELECT;
+ else
+ marker->flag |= SELECT;
+ }
+ else {
+ deselect_markers(0, 0);
+ marker->flag |= SELECT;
+ }
+
+ } else {
+
+ seq= find_nearest_seq(scene, v2d, &hand, mval);
+
+ if(extend == 0 && linked_left==0 && linked_right==0)
+ deselect_all_seq(scene);
+
+ if(seq) {
+ set_last_seq(scene, seq);
+
+ if ((seq->type == SEQ_IMAGE) || (seq->type == SEQ_MOVIE)) {
+ if(seq->strip) {
+ strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR-1);
+ }
+ } else
+ if (seq->type == SEQ_HD_SOUND || seq->type == SEQ_RAM_SOUND) {
+ if(seq->strip) {
+ strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR-1);
+ }
+ }
+
+ if(extend && (seq->flag & SELECT)) {
+ switch(hand) {
+ case SEQ_SIDE_NONE:
+ if (linked_left==0 && linked_right==0)
+ seq->flag &= SEQ_DESEL;
+ break;
+ case SEQ_SIDE_LEFT:
+ seq->flag ^= SEQ_LEFTSEL;
+ break;
+ case SEQ_SIDE_RIGHT:
+ seq->flag ^= SEQ_RIGHTSEL;
+ break;
+ }
+ }
+ else {
+ seq->flag |= SELECT;
+ if(hand==SEQ_SIDE_LEFT) seq->flag |= SEQ_LEFTSEL;
+ if(hand==SEQ_SIDE_RIGHT) seq->flag |= SEQ_RIGHTSEL;
+ }
+
+ /* On Ctrl-Alt selection, select the strip and bordering handles */
+ if (linked_left && linked_right) {
+ if(extend==0) deselect_all_seq(scene);
+ seq->flag |= SELECT;
+ select_surrounding_handles(scene, seq);
+ }
+ else if ((linked_left || linked_right) && (seq->flag & SELECT)) {
+ /*
+ * First click selects adjacent handles on that side.
+ * Second click selects all strips in that direction.
+ * If there are no adjacent strips, it just selects all in that direction.
+ */
+ sel_side= linked_left ? SEQ_SIDE_LEFT:SEQ_SIDE_RIGHT;
+ neighbor=find_neighboring_sequence(scene, seq, sel_side, -1);
+ if (neighbor) {
+ switch (sel_side) {
+ case SEQ_SIDE_LEFT:
+ if ((seq->flag & SEQ_LEFTSEL) && (neighbor->flag & SEQ_RIGHTSEL)) {
+ if(extend==0) deselect_all_seq(scene);
+ seq->flag |= SELECT;
+
+ select_active_side(ed->seqbasep, SEQ_SIDE_LEFT, seq->machine, seq->startdisp);
+ } else {
+ if(extend==0) deselect_all_seq(scene);
+ seq->flag |= SELECT;
+
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_RIGHTSEL;
+ seq->flag |= SEQ_LEFTSEL;
+ }
+ break;
+ case SEQ_SIDE_RIGHT:
+ if ((seq->flag & SEQ_RIGHTSEL) && (neighbor->flag & SEQ_LEFTSEL)) {
+ if(extend==0) deselect_all_seq(scene);
+ seq->flag |= SELECT;
+
+ select_active_side(ed->seqbasep, SEQ_SIDE_RIGHT, seq->machine, seq->startdisp);
+ } else {
+ if(extend==0) deselect_all_seq(scene);
+ seq->flag |= SELECT;
+
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_LEFTSEL;
+ seq->flag |= SEQ_RIGHTSEL;
+ }
+ break;
+ }
+ } else {
+ if(extend==0) deselect_all_seq(scene);
+ select_active_side(ed->seqbasep, sel_side, seq->machine, seq->startdisp);
+ }
+ }
+ recurs_sel_seq(seq);
+ }
+ }
+
+ /* marker transform */
+#if 0 // XXX probably need to redo this differently for 2.5
+ if (marker) {
+ short mval[2], xo, yo;
+// getmouseco_areawin(mval);
+ xo= mval[0];
+ yo= mval[1];
+
+ while(get_mbut()) {
+// getmouseco_areawin(mval);
+ if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) {
+ transform_markers('g', 0);
+ return;
+ }
+ }
+ }
+#endif
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ /* allowing tweaks */
+ return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
+}
+
+void SEQUENCER_OT_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Activate/Select";
+ ot->idname= "SEQUENCER_OT_select";
+
+ /* api callbacks */
+ ot->invoke= sequencer_select_invoke;
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "extend the selection");
+ RNA_def_boolean(ot->srna, "linked_left", 0, "Linked Left", "Select strips to the left of the active strip");
+ RNA_def_boolean(ot->srna, "linked_right", 0, "Linked Right", "Select strips to the right of the active strip");
+}
+
+
+
+
+/* run recursivly to select linked */
+static int select_more_less_seq__internal(Scene *scene, int sel, int linked) {
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq, *neighbor;
+ int change=0;
+ int isel;
+
+ if(ed==NULL) return 0;
+
+ if (sel) {
+ sel = SELECT;
+ isel = 0;
+ } else {
+ sel = 0;
+ isel = SELECT;
+ }
+
+ if (!linked) {
+ /* if not linked we only want to touch each seq once, newseq */
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ seq->tmp = NULL;
+ }
+ }
+
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ if((int)(seq->flag & SELECT) == sel) {
+ if ((linked==0 && seq->tmp)==0) {
+ /* only get unselected nabours */
+ neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, isel);
+ if (neighbor) {
+ if (sel) {neighbor->flag |= SELECT; recurs_sel_seq(neighbor);}
+ else neighbor->flag &= ~SELECT;
+ if (linked==0) neighbor->tmp = (Sequence *)1;
+ change = 1;
+ }
+ neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, isel);
+ if (neighbor) {
+ if (sel) {neighbor->flag |= SELECT; recurs_sel_seq(neighbor);}
+ else neighbor->flag &= ~SELECT;
+ if (linked==0) neighbor->tmp = (void *)1;
+ change = 1;
+ }
+ }
+ }
+ }
+
+ return change;
+}
+
+
+
+/* select more operator */
+static int sequencer_select_more_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+
+ if (select_more_less_seq__internal(scene, 0, 0)) {
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_more(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select More";
+ ot->idname= "SEQUENCER_OT_select_more";
+
+ /* api callbacks */
+ ot->exec= sequencer_select_more_exec;
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+}
+
+
+/* select less operator */
+static int sequencer_select_less_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+
+ if (select_more_less_seq__internal(scene, 1, 0)) {
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_less(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select less";
+ ot->idname= "SEQUENCER_OT_select_less";
+
+ /* api callbacks */
+ ot->exec= sequencer_select_less_exec;
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+}
+
+
+/* select pick linked operator (uses the mouse) */
+static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Scene *scene= CTX_data_scene(C);
+ ARegion *ar= CTX_wm_region(C);
+ View2D *v2d= UI_view2d_fromcontext(C);
+
+ short extend= RNA_boolean_get(op->ptr, "extend");
+ short mval[2];
+
+ Sequence *mouse_seq;
+ int selected, hand;
+
+ mval[0]= event->x - ar->winrct.xmin;
+ mval[1]= event->y - ar->winrct.ymin;
+
+ /* this works like UV, not mesh */
+ mouse_seq= find_nearest_seq(scene, v2d, &hand, mval);
+ if (!mouse_seq)
+ return OPERATOR_FINISHED; /* user error as with mesh?? */
+
+ if (extend==0)
+ deselect_all_seq(scene);
+
+ mouse_seq->flag |= SELECT;
+ recurs_sel_seq(mouse_seq);
+
+ selected = 1;
+ while (selected) {
+ selected = select_more_less_seq__internal(scene, 1, 1);
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_linked_pick(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select pick linked";
+ ot->idname= "SEQUENCER_OT_select_linked_pick";
+
+ /* api callbacks */
+ ot->invoke= sequencer_select_linked_pick_invoke;
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "extend the selection");
+}
+
+
+/* select linked operator */
+static int sequencer_select_linked_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ int selected;
+
+ selected = 1;
+ while (selected) {
+ selected = select_more_less_seq__internal(scene, 1, 1);
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select linked";
+ ot->idname= "SEQUENCER_OT_select_linked";
+
+ /* api callbacks */
+ ot->exec= sequencer_select_linked_exec;
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+}
+
+
+/* select handles operator */
+static int sequencer_select_handles_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, 0);
+ Sequence *seq;
+ int sel_side= RNA_enum_get(op->ptr, "side");
+
+ if (ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ for(seq= ed->seqbasep->first; seq; seq=seq->next) {
+ if (seq->flag & SELECT) {
+ switch(sel_side) {
+ case SEQ_SIDE_LEFT:
+ seq->flag &= ~SEQ_RIGHTSEL;
+ seq->flag |= SEQ_LEFTSEL;
+ break;
+ case SEQ_SIDE_RIGHT:
+ seq->flag &= ~SEQ_LEFTSEL;
+ seq->flag |= SEQ_RIGHTSEL;
+ break;
+ case SEQ_SIDE_BOTH:
+ seq->flag |= SEQ_LEFTSEL+SEQ_RIGHTSEL;
+ break;
+ }
+ }
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_handles(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Handles";
+ ot->idname= "SEQUENCER_OT_select_handles";
+
+ /* api callbacks */
+ ot->exec= sequencer_select_handles_exec;
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side of the handle that is selected");
+}
+
+/* select side operator */
+static int sequencer_select_active_side_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, 0);
+ Sequence *seq_act=get_last_seq(scene);
+
+ if (ed==NULL || seq_act==NULL)
+ return OPERATOR_CANCELLED;
+
+ seq_act->flag |= SELECT;
+
+ select_active_side(ed->seqbasep, RNA_enum_get(op->ptr, "side"), seq_act->machine, seq_act->startdisp);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_active_side(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Active Side";
+ ot->idname= "SEQUENCER_OT_select_active_side";
+
+ /* api callbacks */
+ ot->exec= sequencer_select_active_side_exec;
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side of the handle that is selected");
+}
+
+
+/* borderselect operator */
+static int sequencer_borderselect_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ View2D *v2d= UI_view2d_fromcontext(C);
+
+ Sequence *seq;
+ rcti rect;
+ rctf rectf, rq;
+ int val;
+ short mval[2];
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ val= RNA_int_get(op->ptr, "event_type");
+ rect.xmin= RNA_int_get(op->ptr, "xmin");
+ rect.ymin= RNA_int_get(op->ptr, "ymin");
+ rect.xmax= RNA_int_get(op->ptr, "xmax");
+ rect.ymax= RNA_int_get(op->ptr, "ymax");
+
+ mval[0]= rect.xmin;
+ mval[1]= rect.ymin;
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &rectf.xmin, &rectf.ymin);
+ mval[0]= rect.xmax;
+ mval[1]= rect.ymax;
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &rectf.xmax, &rectf.ymax);
+
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ seq_rectf(seq, &rq);
+
+ if(BLI_isect_rctf(&rq, &rectf, 0)) {
+ if(val==LEFTMOUSE) seq->flag |= SELECT;
+ else seq->flag &= SEQ_DESEL;
+ recurs_sel_seq(seq);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+
+/* ****** Border Select ****** */
+void SEQUENCER_OT_select_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Border Select";
+ ot->idname= "SEQUENCER_OT_select_border";
+
+ /* api callbacks */
+ ot->invoke= WM_border_select_invoke;
+ ot->exec= sequencer_borderselect_exec;
+ ot->modal= WM_border_select_modal;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* rna */
+ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+}
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
new file mode 100644
index 00000000000..76273f24441
--- /dev/null
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -0,0 +1,243 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_sequence.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_markers.h"
+
+#include "sequencer_intern.h" // own include
+
+/* ******************** default callbacks for sequencer space ***************** */
+
+static SpaceLink *sequencer_new(const bContext *C)
+{
+ Scene *scene= CTX_data_scene(C);
+ ARegion *ar;
+ SpaceSeq *sseq;
+
+ sseq= MEM_callocN(sizeof(SpaceSeq), "initsequencer");
+ sseq->spacetype= SPACE_SEQ;
+ sseq->zoom= 4;
+ sseq->chanshown = 0;
+
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for sequencer");
+
+ BLI_addtail(&sseq->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_BOTTOM;
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for sequencer");
+
+ BLI_addtail(&sseq->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+
+
+ /* seq space goes from (0,8) to (0, efra) */
+
+ ar->v2d.tot.xmin= 0.0f;
+ ar->v2d.tot.ymin= 0.0f;
+ ar->v2d.tot.xmax= scene->r.efra;
+ ar->v2d.tot.ymax= 8.0f;
+
+ ar->v2d.cur= ar->v2d.tot;
+
+ ar->v2d.min[0]= 10.0f;
+ ar->v2d.min[1]= 4.0f;
+
+ ar->v2d.max[0]= MAXFRAMEF;
+ ar->v2d.max[1]= MAXSEQ;
+
+ ar->v2d.minzoom= 0.01f;
+ ar->v2d.maxzoom= 100.0f;
+
+ ar->v2d.scroll |= (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.scroll |= (V2D_SCROLL_LEFT|V2D_SCROLL_SCALE_VERTICAL);
+ ar->v2d.keepzoom= 0;
+ ar->v2d.keeptot= 0;
+ ar->v2d.align= V2D_ALIGN_NO_NEG_Y;
+
+ return (SpaceLink *)sseq;
+}
+
+/* not spacelink itself */
+static void sequencer_free(SpaceLink *sl)
+{
+// SpaceSeq *sseq= (SpaceSequencer*) sl;
+
+// XXX if(sseq->gpd) free_gpencil_data(sseq->gpd);
+
+}
+
+
+/* spacetype; init callback */
+static void sequencer_init(struct wmWindowManager *wm, ScrArea *sa)
+{
+
+}
+
+static SpaceLink *sequencer_duplicate(SpaceLink *sl)
+{
+ SpaceSeq *sseqn= MEM_dupallocN(sl);
+
+ /* clear or remove stuff from old */
+// XXX sseq->gpd= gpencil_data_duplicate(sseq->gpd);
+
+ return (SpaceLink *)sseqn;
+}
+
+
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void sequencer_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "Sequencer", SPACE_SEQ, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void sequencer_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+}
+
+static void sequencer_header_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ /* clear */
+ if(ED_screen_area_active(C))
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ else
+ UI_GetThemeColor3fv(TH_HEADERDESEL, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ sequencer_header_buttons(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+static void sequencer_main_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ switch(wmn->data) {
+ case ND_FRAME:
+ case ND_MARKERS:
+ case ND_SEQUENCER:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ }
+}
+
+/* only called once, from space/spacetypes.c */
+void ED_spacetype_sequencer(void)
+{
+ SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype sequencer");
+ ARegionType *art;
+
+ st->spaceid= SPACE_SEQ;
+
+ st->new= sequencer_new;
+ st->free= sequencer_free;
+ st->init= sequencer_init;
+ st->duplicate= sequencer_duplicate;
+ st->operatortypes= sequencer_operatortypes;
+ st->keymap= sequencer_keymap;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init= sequencer_main_area_init;
+ art->draw= drawseqspace;
+ art->listener= sequencer_main_area_listener;
+ art->keymapflag= ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
+
+ art->init= sequencer_header_area_init;
+ art->draw= sequencer_header_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+
+ BKE_spacetype_register(st);
+}
+
diff --git a/source/blender/editors/space_sound/Makefile b/source/blender/editors/space_sound/Makefile
new file mode 100644
index 00000000000..4d375282223
--- /dev/null
+++ b/source/blender/editors/space_sound/Makefile
@@ -0,0 +1,54 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_sound
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/space_sound/SConscript b/source/blender/editors/space_sound/SConscript
new file mode 100644
index 00000000000..e4fffb53e4c
--- /dev/null
+++ b/source/blender/editors/space_sound/SConscript
@@ -0,0 +1,9 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+
+env.BlenderLib ( 'bf_editors_space_sound', sources, Split(incs), [], libtype=['core'], priority=[75] )
diff --git a/source/blender/editors/space_sound/sound_header.c b/source/blender/editors/space_sound/sound_header.c
new file mode 100644
index 00000000000..ae3410663c2
--- /dev/null
+++ b/source/blender/editors/space_sound/sound_header.c
@@ -0,0 +1,130 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "sound_intern.h"
+
+
+/* ************************ header area region *********************** */
+
+static void do_viewmenu(bContext *C, void *arg, int event)
+{
+
+}
+
+static uiBlock *dummy_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "dummy_viewmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_viewmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static void do_sound_buttons(bContext *C, void *arg, int event)
+{
+ switch(event) {
+ }
+}
+
+
+void sound_header_buttons(const bContext *C, ARegion *ar)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ uiBlock *block;
+ int xco, yco= 3;
+
+ block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_sound_buttons, NULL);
+
+ xco= ED_area_header_standardbuttons(C, block, yco);
+
+ if((sa->flag & HEADER_NO_PULLDOWN)==0) {
+ int xmax;
+
+ xmax= GetButStringLength("View");
+ uiDefPulldownBut(block, dummy_viewmenu, CTX_wm_area(C),
+ "View", xco, yco-2, xmax-3, 24, "");
+ xco+=XIC+xmax;
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ /* always as last */
+ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+}
+
+
diff --git a/source/blender/editors/space_sound/sound_intern.h b/source/blender/editors/space_sound/sound_intern.h
new file mode 100644
index 00000000000..3b6d2c456bc
--- /dev/null
+++ b/source/blender/editors/space_sound/sound_intern.h
@@ -0,0 +1,39 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_SOUND_INTERN_H
+#define ED_SOUND_INTERN_H
+
+/* internal exports only */
+
+
+/* sound_header.c */
+void sound_header_buttons(const bContext *C, ARegion *ar);
+
+
+#endif /* ED_SOUND_INTERN_H */
+
diff --git a/source/blender/editors/space_sound/space_sound.c b/source/blender/editors/space_sound/space_sound.c
new file mode 100644
index 00000000000..f8ef2b21ae7
--- /dev/null
+++ b/source/blender/editors/space_sound/space_sound.c
@@ -0,0 +1,270 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_sound_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_markers.h"
+
+#include "sound_intern.h" // own include
+
+/* ******************** default callbacks for sound space ***************** */
+
+static SpaceLink *sound_new(const bContext *C)
+{
+ ARegion *ar;
+ SpaceSound *ssound;
+
+ ssound= MEM_callocN(sizeof(SpaceSound), "initsound");
+ ssound->spacetype= SPACE_SOUND;
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for sound");
+
+ BLI_addtail(&ssound->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_BOTTOM;
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for sound");
+
+ BLI_addtail(&ssound->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+
+ ar->v2d.tot.xmin= -4.0f;
+ ar->v2d.tot.ymin= -4.0f;
+ ar->v2d.tot.xmax= 250.0f;
+ ar->v2d.tot.ymax= 255.0f;
+
+ ar->v2d.cur.xmin= -4.0f;
+ ar->v2d.cur.ymin= -4.0f;
+ ar->v2d.cur.xmax= 50.0f;
+ ar->v2d.cur.ymax= 255.0f;
+
+ ar->v2d.min[0]= 1.0f;
+ ar->v2d.min[1]= 259.0f;
+
+ ar->v2d.max[0]= MAXFRAMEF;
+ ar->v2d.max[1]= 259.0f;
+
+ ar->v2d.minzoom= 0.1f;
+ ar->v2d.maxzoom= 10.0f;
+
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.scroll |= (V2D_SCROLL_LEFT);
+ ar->v2d.keepzoom= 0;
+ ar->v2d.keeptot= 0;
+ ar->v2d.keepzoom = V2D_LOCKZOOM_Y;
+
+
+ return (SpaceLink *)ssound;
+}
+
+/* not spacelink itself */
+static void sound_free(SpaceLink *sl)
+{
+// SpaceSound *ssound= (SpaceSound*) sl;
+
+
+}
+
+
+/* spacetype; init callback */
+static void sound_init(struct wmWindowManager *wm, ScrArea *sa)
+{
+
+}
+
+static SpaceLink *sound_duplicate(SpaceLink *sl)
+{
+ SpaceSound *ssoundn= MEM_dupallocN(sl);
+
+ /* clear or remove stuff from old */
+
+ return (SpaceLink *)ssoundn;
+}
+
+
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void sound_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "Sound", SPACE_SOUND, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+static void sound_main_area_draw(const bContext *C, ARegion *ar)
+{
+ /* draw entirely, view changes should be handled here */
+ // SpaceSound *ssound= (SpaceSound*)CTX_wm_space_data(C);
+ View2D *v2d= &ar->v2d;
+ float col[3];
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ UI_view2d_view_ortho(C, v2d);
+
+ /* data... */
+
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers? */
+}
+
+void sound_operatortypes(void)
+{
+
+}
+
+void sound_keymap(struct wmWindowManager *wm)
+{
+
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void sound_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+}
+
+static void sound_header_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ /* clear */
+ if(ED_screen_area_active(C))
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ else
+ UI_GetThemeColor3fv(TH_HEADERDESEL, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ sound_header_buttons(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+static void sound_main_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+}
+
+/* only called once, from space/spacetypes.c */
+void ED_spacetype_sound(void)
+{
+ SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype sound");
+ ARegionType *art;
+
+ st->spaceid= SPACE_SOUND;
+
+ st->new= sound_new;
+ st->free= sound_free;
+ st->init= sound_init;
+ st->duplicate= sound_duplicate;
+ st->operatortypes= sound_operatortypes;
+ st->keymap= sound_keymap;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype sound region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init= sound_main_area_init;
+ art->draw= sound_main_area_draw;
+ art->listener= sound_main_area_listener;
+ art->keymapflag= ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype sound region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+
+ art->init= sound_header_area_init;
+ art->draw= sound_header_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: channels */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype sound region");
+ art->regionid = RGN_TYPE_CHANNELS;
+ art->minsizex= 80;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+
+// art->init= sound_channel_area_init;
+// art->draw= sound_channel_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+
+ BKE_spacetype_register(st);
+}
+
diff --git a/source/blender/editors/space_text/Makefile b/source/blender/editors/space_text/Makefile
new file mode 100644
index 00000000000..33e12dc1abb
--- /dev/null
+++ b/source/blender/editors/space_text/Makefile
@@ -0,0 +1,55 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_text
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../blenfont
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/space_text/SConscript b/source/blender/editors/space_text/SConscript
new file mode 100644
index 00000000000..3d5ccc318e1
--- /dev/null
+++ b/source/blender/editors/space_text/SConscript
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+defs = []
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' #/intern/bmfont ../../python ../../makesrna ../../blenfont'
+
+if not env['WITH_BF_PYTHON']:
+ defs.append('DISABLE_PYTHON')
+
+env.BlenderLib ( 'bf_editors_space_text', sources, Split(incs), defs, libtype=['core'], priority=[95] )
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
new file mode 100644
index 00000000000..89852955ca3
--- /dev/null
+++ b/source/blender/editors/space_text/space_text.c
@@ -0,0 +1,424 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_text_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "RNA_access.h"
+
+#include "ED_markers.h"
+
+#include "text_intern.h" // own include
+
+/* ******************** default callbacks for text space ***************** */
+
+static SpaceLink *text_new(const bContext *C)
+{
+ ARegion *ar;
+ SpaceText *stext;
+
+ stext= MEM_callocN(sizeof(SpaceText), "inittext");
+ stext->spacetype= SPACE_TEXT;
+
+ stext->lheight= 12;
+ stext->tabnumber= 4;
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for text");
+
+ BLI_addtail(&stext->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_BOTTOM;
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for text");
+
+ BLI_addtail(&stext->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+
+ return (SpaceLink *)stext;
+}
+
+/* not spacelink itself */
+static void text_free(SpaceLink *sl)
+{
+ SpaceText *stext= (SpaceText*) sl;
+
+ stext->text= NULL;
+}
+
+
+/* spacetype; init callback */
+static void text_init(struct wmWindowManager *wm, ScrArea *sa)
+{
+
+}
+
+static SpaceLink *text_duplicate(SpaceLink *sl)
+{
+ SpaceText *stextn= MEM_dupallocN(sl);
+
+ /* clear or remove stuff from old */
+
+ return (SpaceLink *)stextn;
+}
+
+static void text_listener(ScrArea *sa, wmNotifier *wmn)
+{
+ SpaceText *st= sa->spacedata.first;
+
+ /* context changes */
+ switch(wmn->category) {
+ case NC_TEXT:
+ if(!wmn->reference || wmn->reference == st->text) {
+ ED_area_tag_redraw(sa);
+
+ if(wmn->data == ND_CURSOR) {
+ ARegion *ar;
+
+ for(ar=sa->regionbase.first; ar; ar= ar->next)
+ if(ar->regiontype==RGN_TYPE_WINDOW)
+ text_update_cursor_moved(st, ar);
+ }
+ }
+ else if(wmn->data == ND_DISPLAY)
+ ED_area_tag_redraw(sa);
+
+ break;
+ }
+}
+
+static void text_operatortypes(void)
+{
+ WM_operatortype_append(TEXT_OT_new);
+ WM_operatortype_append(TEXT_OT_open);
+ WM_operatortype_append(TEXT_OT_reload);
+ WM_operatortype_append(TEXT_OT_save);
+ WM_operatortype_append(TEXT_OT_save_as);
+ WM_operatortype_append(TEXT_OT_make_internal);
+ WM_operatortype_append(TEXT_OT_run_script);
+ WM_operatortype_append(TEXT_OT_refresh_pyconstraints);
+
+ WM_operatortype_append(TEXT_OT_paste);
+ WM_operatortype_append(TEXT_OT_copy);
+ WM_operatortype_append(TEXT_OT_cut);
+
+ WM_operatortype_append(TEXT_OT_convert_whitespace);
+ WM_operatortype_append(TEXT_OT_uncomment);
+ WM_operatortype_append(TEXT_OT_comment);
+ WM_operatortype_append(TEXT_OT_unindent);
+ WM_operatortype_append(TEXT_OT_indent);
+
+ WM_operatortype_append(TEXT_OT_markers_clear);
+ WM_operatortype_append(TEXT_OT_next_marker);
+ WM_operatortype_append(TEXT_OT_previous_marker);
+
+ WM_operatortype_append(TEXT_OT_select_line);
+ WM_operatortype_append(TEXT_OT_select_all);
+
+ WM_operatortype_append(TEXT_OT_jump);
+ WM_operatortype_append(TEXT_OT_move);
+ WM_operatortype_append(TEXT_OT_move_select);
+ WM_operatortype_append(TEXT_OT_delete);
+ WM_operatortype_append(TEXT_OT_overwrite_toggle);
+
+ WM_operatortype_append(TEXT_OT_cursor_set);
+ WM_operatortype_append(TEXT_OT_scroll);
+ WM_operatortype_append(TEXT_OT_scroll_bar);
+ WM_operatortype_append(TEXT_OT_line_number);
+
+ WM_operatortype_append(TEXT_OT_line_break);
+ WM_operatortype_append(TEXT_OT_insert);
+
+ WM_operatortype_append(TEXT_OT_properties);
+
+ WM_operatortype_append(TEXT_OT_find);
+ WM_operatortype_append(TEXT_OT_find_set_selected);
+ WM_operatortype_append(TEXT_OT_replace);
+ WM_operatortype_append(TEXT_OT_replace_set_selected);
+ WM_operatortype_append(TEXT_OT_mark_all);
+
+ WM_operatortype_append(TEXT_OT_to_3d_object);
+
+ WM_operatortype_append(TEXT_OT_resolve_conflict);
+}
+
+static void text_keymap(struct wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "Text", SPACE_TEXT, 0);
+
+ WM_keymap_add_item(keymap, "TEXT_OT_new", NKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_open", OKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_reload", RKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_save", SKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "TEXT_OT_run_script", PKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "TEXT_OT_cut", XKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_cut", XKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_copy", CKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_paste", VKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
+
+ if(U.uiflag & USER_MMB_PASTE) // XXX not dynamic
+ RNA_boolean_set(WM_keymap_add_item(keymap, "TEXT_OT_paste", MIDDLEMOUSE, KM_PRESS, 0, 0)->ptr, "selection", 1);
+
+ WM_keymap_add_item(keymap, "TEXT_OT_jump", JKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_find", FKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_properties", FKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_properties", FKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_replace", HKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_replace", HKEY, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "TEXT_OT_to_3d_object", MKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "TEXT_OT_select_all", AKEY, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "TEXT_OT_indent", TABKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_unindent", TABKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_uncomment", DKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", HOMEKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_BEGIN);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", LEFTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_BEGIN);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", ENDKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_END);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", RIGHTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_BEGIN);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", EKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", LINE_END);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", EKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "type", LINE_END);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", ENDKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_END);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_CHAR);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_CHAR);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", PREV_WORD);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", NEXT_WORD);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_LINE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_LINE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", PAGEUPKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_PAGE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", PAGEDOWNKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_PAGE);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", HOMEKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", LINE_BEGIN);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", ENDKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", LINE_END);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", LEFTARROWKEY, KM_PRESS, KM_SHIFT|KM_OSKEY, 0)->ptr, "type", LINE_BEGIN);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", RIGHTARROWKEY, KM_PRESS, KM_SHIFT|KM_OSKEY, 0)->ptr, "type", LINE_BEGIN);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", LEFTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", PREV_CHAR);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", RIGHTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", NEXT_CHAR);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", LEFTARROWKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0)->ptr, "type", PREV_WORD);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", RIGHTARROWKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0)->ptr, "type", NEXT_WORD);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", UPARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", PREV_LINE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", DOWNARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", NEXT_LINE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", PAGEUPKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", PREV_PAGE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move_select", PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", NEXT_PAGE);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_delete", DELKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_NEXT_CHAR);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_delete", DKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_NEXT_CHAR);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_delete", BACKSPACEKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_PREV_CHAR);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_delete", DELKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_NEXT_WORD);
+ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_delete", BACKSPACEKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_PREV_WORD);
+
+ WM_keymap_add_item(keymap, "TEXT_OT_overwrite_toggle", INSERTKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "TEXT_OT_scroll", MIDDLEMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_scroll_bar", LEFTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_cursor_set", LEFTMOUSE, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "TEXT_OT_cursor_set", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "select", 1);
+ RNA_int_set(WM_keymap_add_item(keymap, "TEXT_OT_scroll", WHEELUPMOUSE, KM_PRESS, 0, 0)->ptr, "lines", -1);
+ RNA_int_set(WM_keymap_add_item(keymap, "TEXT_OT_scroll", WHEELDOWNMOUSE, KM_PRESS, 0, 0)->ptr, "lines", 1);
+
+ WM_keymap_add_item(keymap, "TEXT_OT_to_3d_object", MKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "TEXT_OT_line_break", RETKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_line_number", KM_TEXTINPUT, KM_ANY, KM_ANY, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_insert", KM_TEXTINPUT, KM_ANY, KM_ANY, 0); // last!
+}
+
+static int text_context(const bContext *C, const char *member, bContextDataResult *result)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+
+ if(CTX_data_equals(member, "edit_text")) {
+ CTX_data_id_pointer_set(result, &st->text->id);
+ return 1;
+ }
+
+ return 0;
+}
+
+/********************* main region ********************/
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void text_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "Text", SPACE_TEXT, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+static void text_main_area_draw(const bContext *C, ARegion *ar)
+{
+ /* draw entirely, view changes should be handled here */
+ SpaceText *st= CTX_wm_space_text(C);
+ //View2D *v2d= &ar->v2d;
+ float col[3];
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ // UI_view2d_view_ortho(C, v2d);
+
+ /* data... */
+ draw_text_main(st, ar);
+
+ /* reset view matrix */
+ // UI_view2d_view_restore(C);
+
+ /* scrollers? */
+}
+
+static void text_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
+{
+ WM_cursor_set(win, BC_TEXTEDITCURSOR);
+}
+
+/****************** header region ******************/
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void text_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+ ar->v2d.flag &= ~(V2D_PIXELOFS_X|V2D_PIXELOFS_Y); // XXX temporary
+}
+
+static void text_header_area_draw(const bContext *C, ARegion *ar)
+{
+ uiRegionHeaderLayout(C, ar);
+}
+
+/****************** properties region ******************/
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void text_properties_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
+}
+
+static void text_properties_area_draw(const bContext *C, ARegion *ar)
+{
+ uiRegionPanelLayout(C, ar, 1, NULL);
+}
+
+/********************* registration ********************/
+
+/* only called once, from space/spacetypes.c */
+void ED_spacetype_text(void)
+{
+ SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype text");
+ ARegionType *art;
+
+ st->spaceid= SPACE_TEXT;
+
+ st->new= text_new;
+ st->free= text_free;
+ st->init= text_init;
+ st->duplicate= text_duplicate;
+ st->operatortypes= text_operatortypes;
+ st->keymap= text_keymap;
+ st->listener= text_listener;
+ st->context= text_context;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype text region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init= text_main_area_init;
+ art->draw= text_main_area_draw;
+ art->cursor= text_cursor;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: properties */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype text region");
+ art->regionid = RGN_TYPE_UI;
+ art->minsizex= UI_COMPACT_PANEL_WIDTH;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+
+ art->init= text_properties_area_init;
+ art->draw= text_properties_area_draw;
+
+ text_properties_register(art);
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype text region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+
+ art->init= text_header_area_init;
+ art->draw= text_header_area_draw;
+
+ text_header_register(art);
+
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
+}
+
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
new file mode 100644
index 00000000000..456060d77a7
--- /dev/null
+++ b/source/blender/editors/space_text/text_draw.c
@@ -0,0 +1,1381 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLF_api.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_text_types.h"
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_suggestions.h"
+#include "BKE_text.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "ED_datafiles.h"
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "text_intern.h"
+
+/******************** text font drawing ******************/
+
+static void text_font_begin(SpaceText *st)
+{
+ static int mono= -1; // XXX needs proper storage
+
+ if(mono == -1)
+ mono= BLF_load_mem("monospace", (unsigned char*)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size);
+
+ BLF_set(mono);
+ BLF_aspect(1.0);
+
+ BLF_size(st->lheight, 72);
+}
+
+static void text_font_end(SpaceText *st)
+{
+}
+
+static int text_font_draw(SpaceText *st, int x, int y, char *str)
+{
+ BLF_position(x, y, 0);
+ BLF_draw(str);
+
+ return BLF_width(str);
+}
+
+static int text_font_draw_character(SpaceText *st, int x, int y, char c)
+{
+ char str[2];
+
+ str[0]= c;
+ str[1]= '\0';
+
+ BLF_position(x, y, 0);
+ BLF_draw(str);
+
+ return text_font_width_character(st);
+}
+
+int text_font_width_character(SpaceText *st)
+{
+ // XXX need quick BLF function, or cache it somewhere
+ return (st->lheight == 12)? 7: 8;
+}
+
+int text_font_width(SpaceText *st, char *str)
+{
+ return BLF_width(str);
+}
+
+/****************** flatten string **********************/
+
+static void flatten_string_append(FlattenString *fs, char c, int accum)
+{
+ if(fs->pos>=fs->len && fs->pos>=sizeof(fs->fixedbuf)-1) {
+ char *nbuf; int *naccum;
+ int olen= fs->len;
+
+ if(olen) fs->len*= 2;
+ else fs->len= 256;
+
+ nbuf= MEM_mallocN(sizeof(*fs->buf)*fs->len, "fs->buf");
+ naccum= MEM_mallocN(sizeof(*fs->accum)*fs->len, "fs->accum");
+
+ if(olen) {
+ memcpy(nbuf, fs->buf, olen);
+ memcpy(naccum, fs->accum, olen);
+
+ if(fs->buf != fs->fixedbuf) {
+ MEM_freeN(fs->buf);
+ MEM_freeN(fs->accum);
+ }
+ }
+
+ fs->buf= nbuf;
+ fs->accum= naccum;
+ }
+
+ fs->buf[fs->pos]= c;
+ fs->accum[fs->pos]= accum;
+
+ if(c==0) fs->pos= 0;
+ else fs->pos++;
+}
+
+int flatten_string(SpaceText *st, FlattenString *fs, char *in)
+{
+ int r = 0, i = 0;
+
+ memset(fs, 0, sizeof(FlattenString));
+ fs->buf= fs->fixedbuf;
+ fs->accum= fs->fixedaccum;
+
+ for(r=0, i=0; *in; r++, in++) {
+ if(*in=='\t') {
+ if(fs->pos && *(in-1)=='\t')
+ i= st->tabnumber;
+ else if(st->tabnumber > 0)
+ i= st->tabnumber - (fs->pos%st->tabnumber);
+
+ while(i--)
+ flatten_string_append(fs, ' ', r);
+ }
+ else
+ flatten_string_append(fs, *in, r);
+ }
+
+ return fs->pos;
+}
+
+void flatten_string_free(FlattenString *fs)
+{
+ if(fs->buf != fs->fixedbuf)
+ MEM_freeN(fs->buf);
+ if(fs->accum != fs->fixedaccum)
+ MEM_freeN(fs->accum);
+}
+
+/* Checks the specified source string for a Python built-in function name. This
+ name must start at the beginning of the source string and must be followed by
+ a non-identifier (see text_check_identifier(char)) or null character.
+
+ If a built-in function is found, the length of the matching name is returned.
+ Otherwise, -1 is returned. */
+
+static int find_builtinfunc(char *string)
+{
+ int a, i;
+ char builtinfuncs[][11] = {"and", "as", "assert", "break", "class", "continue", "def",
+ "del", "elif", "else", "except", "exec", "finally",
+ "for", "from", "global", "if", "import", "in",
+ "is", "lambda", "not", "or", "pass", "print",
+ "raise", "return", "try", "while", "yield"};
+ for(a=0; a<30; a++) {
+ i = 0;
+ while(1) {
+ /* If we hit the end of a keyword... (eg. "def") */
+ if(builtinfuncs[a][i]=='\0') {
+ /* If we still have identifier chars in the source (eg. "definate") */
+ if(text_check_identifier(string[i]))
+ i = -1; /* No match */
+ break; /* Next keyword if no match, otherwise we're done */
+
+ /* If chars mismatch, move on to next keyword */
+ }
+ else if(string[i]!=builtinfuncs[a][i]) {
+ i = -1;
+ break; /* Break inner loop, start next keyword */
+ }
+ i++;
+ }
+ if(i>0) break; /* If we have a match, we're done */
+ }
+ return i;
+}
+
+/* Checks the specified source string for a Python special name. This name must
+ start at the beginning of the source string and must be followed by a non-
+ identifier (see text_check_identifier(char)) or null character.
+
+ If a special name is found, the length of the matching name is returned.
+ Otherwise, -1 is returned. */
+
+static int find_specialvar(char *string)
+{
+ int i = 0;
+ /* Check for "def" */
+ if(string[0]=='d' && string[1]=='e' && string[2]=='f')
+ i = 3;
+ /* Check for "class" */
+ else if(string[0]=='c' && string[1]=='l' && string[2]=='a' && string[3]=='s' && string[4]=='s')
+ i = 5;
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ if(i==0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
+}
+
+/* Ensures the format string for the given line is long enough, reallocating
+ as needed. Allocation is done here, alone, to ensure consistency. */
+int text_check_format_len(TextLine *line, unsigned int len)
+{
+ if(line->format) {
+ if(strlen(line->format) < len) {
+ MEM_freeN(line->format);
+ line->format = MEM_mallocN(len+2, "SyntaxFormat");
+ if(!line->format) return 0;
+ }
+ }
+ else {
+ line->format = MEM_mallocN(len+2, "SyntaxFormat");
+ if(!line->format) return 0;
+ }
+
+ return 1;
+}
+
+/* Formats the specified line. If do_next is set, the process will move on to
+ the succeeding line if it is affected (eg. multiline strings). Format strings
+ may contain any of the following characters:
+ '_' Whitespace
+ '#' Comment text
+ '!' Punctuation and other symbols
+ 'n' Numerals
+ 'l' String letters
+ 'v' Special variables (class, def)
+ 'b' Built-in names (print, for, etc.)
+ 'q' Other text (identifiers, etc.)
+ It is terminated with a null-terminator '\0' followed by a continuation
+ flag indicating whether the line is part of a multi-line string. */
+
+static void txt_format_line(SpaceText *st, TextLine *line, int do_next)
+{
+ FlattenString fs;
+ char *str, *fmt, orig, cont, find, prev = ' ';
+ int len, i;
+
+ /* Get continuation from previous line */
+ if(line->prev && line->prev->format != NULL) {
+ fmt= line->prev->format;
+ cont = fmt[strlen(fmt)+1]; /* Just after the null-terminator */
+ }
+ else cont = 0;
+
+ /* Get original continuation from this line */
+ if(line->format != NULL) {
+ fmt= line->format;
+ orig = fmt[strlen(fmt)+1]; /* Just after the null-terminator */
+ }
+ else orig = 0xFF;
+
+ flatten_string(st, &fs, line->line);
+ str = fs.buf;
+ len = strlen(str);
+ if(!text_check_format_len(line, len)) {
+ flatten_string_free(&fs);
+ return;
+ }
+ fmt = line->format;
+
+ while(*str) {
+ /* Handle escape sequences by skipping both \ and next char */
+ if(*str == '\\') {
+ *fmt = prev; fmt++; str++;
+ if(*str == '\0') break;
+ *fmt = prev; fmt++; str++;
+ continue;
+ }
+ /* Handle continuations */
+ else if(cont) {
+ /* Triple strings ("""...""" or '''...''') */
+ if(cont & TXT_TRISTR) {
+ find = (cont & TXT_DBLQUOTSTR) ? '"' : '\'';
+ if(*str==find && *(str+1)==find && *(str+2)==find) {
+ *fmt = 'l'; fmt++; str++;
+ *fmt = 'l'; fmt++; str++;
+ cont = 0;
+ }
+ /* Handle other strings */
+ }
+ else {
+ find = (cont & TXT_DBLQUOTSTR) ? '"' : '\'';
+ if(*str == find) cont = 0;
+ }
+
+ *fmt = 'l';
+ }
+ /* Not in a string... */
+ else {
+ /* Deal with comments first */
+ if(prev == '#' || *str == '#')
+ *fmt = '#';
+ /* Strings */
+ else if(*str == '"' || *str == '\'') {
+ find = *str;
+ cont = (*str== '"') ? TXT_DBLQUOTSTR : TXT_SNGQUOTSTR;
+ if(*(str+1) == find && *(str+2) == find) {
+ *fmt = 'l'; fmt++; str++;
+ *fmt = 'l'; fmt++; str++;
+ cont |= TXT_TRISTR;
+ }
+ *fmt = 'l';
+ }
+ /* Whitespace (all ws. has been converted to spaces) */
+ else if(*str == ' ')
+ *fmt = '_';
+ /* Numbers (digits not part of an identifier and periods followed by digits) */
+ else if((prev != 'q' && text_check_digit(*str)) || (*str == '.' && text_check_digit(*(str+1))))
+ *fmt = 'n';
+ /* Punctuation */
+ else if(text_check_delim(*str))
+ *fmt = '!';
+ /* Identifiers and other text (no previous ws. or delims. so text continues) */
+ else if(prev == 'q')
+ *fmt = 'q';
+ /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
+ else {
+ /* Special vars(v) or built-in keywords(b) */
+ if((i=find_specialvar(str)) != -1)
+ prev = 'v';
+ else if((i=find_builtinfunc(str)) != -1)
+ prev = 'b';
+ if(i>0) {
+ while(i>1) {
+ *fmt = prev; fmt++; str++;
+ i--;
+ }
+ *fmt = prev;
+ }
+ else
+ *fmt = 'q';
+ }
+ }
+ prev = *fmt;
+ fmt++;
+ str++;
+ }
+
+ /* Terminate and add continuation char */
+ *fmt = '\0'; fmt++;
+ *fmt = cont;
+
+ /* Debugging */
+ //print_format(st, line);
+
+ /* If continuation has changed and we're allowed, process the next line */
+ if(cont!=orig && do_next && line->next) {
+ txt_format_line(st, line->next, do_next);
+ }
+
+ flatten_string_free(&fs);
+}
+
+#if 0
+/* Formats every line of the current text */
+static void txt_format_text(SpaceText *st)
+{
+ TextLine *linep;
+
+ if(!st->text) return;
+
+ for(linep=st->text->lines.first; linep; linep=linep->next)
+ txt_format_line(st, linep, 0);
+}
+#endif
+
+/* Sets the current drawing color based on the format character specified */
+static void format_draw_color(char formatchar)
+{
+ switch (formatchar) {
+ case '_': /* Whitespace */
+ break;
+ case '!': /* Symbols */
+ UI_ThemeColorBlend(TH_TEXT, TH_BACK, 0.5f);
+ break;
+ case '#': /* Comments */
+ UI_ThemeColor(TH_SYNTAX_C);
+ break;
+ case 'n': /* Numerals */
+ UI_ThemeColor(TH_SYNTAX_N);
+ break;
+ case 'l': /* Strings */
+ UI_ThemeColor(TH_SYNTAX_L);
+ break;
+ case 'v': /* Specials: class, def */
+ UI_ThemeColor(TH_SYNTAX_V);
+ break;
+ case 'b': /* Keywords: for, print, etc. */
+ UI_ThemeColor(TH_SYNTAX_B);
+ break;
+ case 'q': /* Other text (identifiers) */
+ default:
+ UI_ThemeColor(TH_TEXT);
+ break;
+ }
+}
+
+/*********************** utilities ************************/
+
+int text_check_bracket(char ch)
+{
+ int a;
+ char opens[] = "([{";
+ char close[] = ")]}";
+
+ for(a=0; a<3; a++) {
+ if(ch==opens[a])
+ return a+1;
+ else if(ch==close[a])
+ return -(a+1);
+ }
+ return 0;
+}
+
+int text_check_delim(char ch)
+{
+ int a;
+ char delims[] = "():\"\' ~!%^&*-+=[]{};/<>|.#\t,";
+
+ for(a=0; a<28; a++) {
+ if(ch==delims[a])
+ return 1;
+ }
+ return 0;
+}
+
+int text_check_digit(char ch)
+{
+ if(ch < '0') return 0;
+ if(ch <= '9') return 1;
+ return 0;
+}
+
+int text_check_identifier(char ch)
+{
+ if(ch < '0') return 0;
+ if(ch <= '9') return 1;
+ if(ch < 'A') return 0;
+ if(ch <= 'Z' || ch == '_') return 1;
+ if(ch < 'a') return 0;
+ if(ch <= 'z') return 1;
+ return 0;
+}
+
+int text_check_whitespace(char ch)
+{
+ if(ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
+ return 1;
+ return 0;
+}
+
+/************************** draw text *****************************/
+
+/***********************/ /*
+
+Notes on word-wrap
+--
+All word-wrap functions follow the algorithm below to maintain consistency.
+ line The line to wrap (tabs converted to spaces)
+ view_width The maximum number of characters displayable in the region
+ This equals region_width/font_width for the region
+ wrap_chars Characters that allow wrapping. This equals [' ', '\t', '-']
+
+def wrap(line, view_width, wrap_chars):
+ draw_start = 0
+ draw_end = view_width
+ pos = 0
+ for c in line:
+ if pos-draw_start >= view_width:
+ print line[draw_start:draw_end]
+ draw_start = draw_end
+ draw_end += view_width
+ elif c in wrap_chars:
+ draw_end = pos+1
+ pos += 1
+ print line[draw_start:]
+
+*/ /***********************/
+
+int wrap_width(SpaceText *st, ARegion *ar)
+{
+ int x, max;
+
+ x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ max= (ar->winx-x)/text_font_width_character(st);
+ return max>8 ? max : 8;
+}
+
+/* Sets (offl, offc) for transforming (line, curs) to its wrapped position */
+void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *offl, int *offc)
+{
+ Text *text;
+ TextLine *linep;
+ int i, j, start, end, chars, max, chop;
+ char ch;
+
+ *offl= *offc= 0;
+
+ if(!st->text) return;
+ if(!st->wordwrap) return;
+
+ text= st->text;
+
+ /* Move pointer to first visible line (top) */
+ linep= text->lines.first;
+ i= st->top;
+ while(i>0 && linep) {
+ if(linep == linein) return; /* Line before top */
+ linep= linep->next;
+ i--;
+ }
+
+ max= wrap_width(st, ar);
+
+ while(linep) {
+ start= 0;
+ end= max;
+ chop= 1;
+ chars= 0;
+ *offc= 0;
+ for(i=0, j=0; linep->line[j]!='\0'; j++) {
+
+ /* Mimic replacement of tabs */
+ ch= linep->line[j];
+ if(ch=='\t') {
+ chars= st->tabnumber-i%st->tabnumber;
+ if(linep==linein && i<cursin) cursin += chars-1;
+ ch= ' ';
+ }
+ else
+ chars= 1;
+
+ while(chars--) {
+ if(i-start>=max) {
+ if(chop && linep==linein && i >= cursin)
+ return;
+ (*offl)++;
+ *offc -= end-start;
+ start= end;
+ end += max;
+ chop= 1;
+ }
+ else if(ch==' ' || ch=='-') {
+ end = i+1;
+ chop= 0;
+ if(linep==linein && i >= cursin)
+ return;
+ }
+ i++;
+ }
+ }
+ if(linep==linein) break;
+ linep= linep->next;
+ }
+}
+
+static int get_char_pos(SpaceText *st, char *line, int cur)
+{
+ int a=0, i;
+
+ for(i=0; i<cur && line[i]; i++) {
+ if(line[i]=='\t')
+ a += st->tabnumber-a%st->tabnumber;
+ else
+ a++;
+ }
+ return a;
+}
+
+static int text_draw_wrapped(SpaceText *st, char *str, int x, int y, int w, char *format)
+{
+ FlattenString fs;
+ int basex, i, a, len, start, end, max, lines;
+
+ len= flatten_string(st, &fs, str);
+ str= fs.buf;
+ max= w/text_font_width_character(st);
+ if(max<8) max= 8;
+ basex= x;
+
+ lines= 1;
+ start= 0;
+ end= max;
+ for(i=0; i<len; i++) {
+ if(i-start >= max) {
+ /* Draw the visible portion of text on the overshot line */
+ for(a=start; a<end; a++) {
+ if(st->showsyntax && format) format_draw_color(format[a]);
+ x += text_font_draw_character(st, x, y, str[a]);
+ }
+ y -= st->lheight;
+ x= basex;
+ lines++;
+ start= end;
+ end += max;
+ }
+ else if(str[i]==' ' || str[i]=='-') {
+ end = i+1;
+ }
+ }
+
+ /* Draw the remaining text */
+ for(a=start; a<len; a++) {
+ if(st->showsyntax && format)
+ format_draw_color(format[a]);
+
+ x += text_font_draw_character(st, x, y, str[a]);
+ }
+
+ flatten_string_free(&fs);
+
+ return lines;
+}
+
+static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int draw, int x, int y, char *format)
+{
+ FlattenString fs;
+ int r=0, w= 0;
+ int *acc;
+ char *in;
+
+ w= flatten_string(st, &fs, str);
+ if(w < cshift) {
+ flatten_string_free(&fs);
+ return 0; /* String is shorter than shift */
+ }
+
+ in= fs.buf+cshift;
+ acc= fs.accum+cshift;
+ w= w-cshift;
+
+ if(draw) {
+ if(st->showsyntax && format) {
+ int amount, a;
+ format = format+cshift;
+
+ amount = strlen(in);
+
+ for(a = 0; a < amount; a++) {
+ format_draw_color(format[a]);
+ x += text_font_draw_character(st, x, y, in[a]);
+ }
+ }
+ else
+ text_font_draw(st, x, y, in);
+ }
+ else {
+ while(w-- && *acc++ < maxwidth)
+ r+= text_font_width_character(st);
+ }
+
+ flatten_string_free(&fs);
+
+ if(cshift && r==0)
+ return 0;
+ else if(st->showlinenrs)
+ return r+TXT_OFFSET+TEXTXLOC;
+ else
+ return r+TXT_OFFSET;
+}
+
+/************************ draw scrollbar *****************************/
+
+static void calc_text_rcts(SpaceText *st, ARegion *ar)
+{
+ int lhlstart, lhlend, ltexth;
+ short barheight, barstart, hlstart, hlend, blank_lines;
+ short pix_available, pix_top_margin, pix_bottom_margin, pix_bardiff;
+
+ pix_top_margin = 8;
+ pix_bottom_margin = 4;
+ pix_available = ar->winy - pix_top_margin - pix_bottom_margin;
+ ltexth= txt_get_span(st->text->lines.first, st->text->lines.last);
+ blank_lines = st->viewlines / 2;
+
+ /* when resizing a vieport with the bar at the bottom to a greater height more blank lines will be added */
+ if(ltexth + blank_lines < st->top + st->viewlines) {
+ blank_lines = st->top + st->viewlines - ltexth;
+ }
+
+ ltexth += blank_lines;
+
+ barheight = (ltexth > 0)? (st->viewlines*pix_available)/ltexth: 0;
+ pix_bardiff = 0;
+ if(barheight < 20) {
+ pix_bardiff = 20 - barheight; /* take into account the now non-linear sizing of the bar */
+ barheight = 20;
+ }
+ barstart = (ltexth > 0)? ((pix_available - pix_bardiff) * st->top)/ltexth: 0;
+
+ st->txtbar.xmin = 5;
+ st->txtbar.xmax = 17;
+ st->txtbar.ymax = ar->winy - pix_top_margin - barstart;
+ st->txtbar.ymin = st->txtbar.ymax - barheight;
+
+ CLAMP(st->txtbar.ymin, pix_bottom_margin, ar->winy - pix_top_margin);
+ CLAMP(st->txtbar.ymax, pix_bottom_margin, ar->winy - pix_top_margin);
+
+ st->pix_per_line= (pix_available > 0)? (float) ltexth/pix_available: 0;
+ if(st->pix_per_line<.1) st->pix_per_line=.1f;
+
+ lhlstart = MIN2(txt_get_span(st->text->lines.first, st->text->curl),
+ txt_get_span(st->text->lines.first, st->text->sell));
+ lhlend = MAX2(txt_get_span(st->text->lines.first, st->text->curl),
+ txt_get_span(st->text->lines.first, st->text->sell));
+
+ if(ltexth > 0) {
+ hlstart = (lhlstart * pix_available)/ltexth;
+ hlend = (lhlend * pix_available)/ltexth;
+
+ /* the scrollbar is non-linear sized */
+ if(pix_bardiff > 0) {
+ /* the start of the highlight is in the current viewport */
+ if(ltexth && st->viewlines && lhlstart >= st->top && lhlstart <= st->top + st->viewlines) {
+ /* speed the progresion of the start of the highlight through the scrollbar */
+ hlstart = ( ( (pix_available - pix_bardiff) * lhlstart) / ltexth) + (pix_bardiff * (lhlstart - st->top) / st->viewlines);
+ }
+ else if(lhlstart > st->top + st->viewlines && hlstart < barstart + barheight && hlstart > barstart) {
+ /* push hl start down */
+ hlstart = barstart + barheight;
+ }
+ else if(lhlend > st->top && lhlstart < st->top && hlstart > barstart) {
+ /*fill out start */
+ hlstart = barstart;
+ }
+
+ if(hlend <= hlstart) {
+ hlend = hlstart + 2;
+ }
+
+ /* the end of the highlight is in the current viewport */
+ if(ltexth && st->viewlines && lhlend >= st->top && lhlend <= st->top + st->viewlines) {
+ /* speed the progresion of the end of the highlight through the scrollbar */
+ hlend = (((pix_available - pix_bardiff )*lhlend)/ltexth) + (pix_bardiff * (lhlend - st->top)/st->viewlines);
+ }
+ else if(lhlend < st->top && hlend >= barstart - 2 && hlend < barstart + barheight) {
+ /* push hl end up */
+ hlend = barstart;
+ }
+ else if(lhlend > st->top + st->viewlines && lhlstart < st->top + st->viewlines && hlend < barstart + barheight) {
+ /* fill out end */
+ hlend = barstart + barheight;
+ }
+
+ if(hlend <= hlstart) {
+ hlstart = hlend - 2;
+ }
+ }
+ }
+ else {
+ hlstart = 0;
+ hlend = 0;
+ }
+
+ if(hlend - hlstart < 2) {
+ hlend = hlstart + 2;
+ }
+
+ st->txtscroll.xmin= 5;
+ st->txtscroll.xmax= 17;
+ st->txtscroll.ymax= ar->winy - pix_top_margin - hlstart;
+ st->txtscroll.ymin= ar->winy - pix_top_margin - hlend;
+
+ CLAMP(st->txtscroll.ymin, pix_bottom_margin, ar->winy - pix_top_margin);
+ CLAMP(st->txtscroll.ymax, pix_bottom_margin, ar->winy - pix_top_margin);
+}
+
+static void draw_textscroll(SpaceText *st, ARegion *ar)
+{
+ UI_ThemeColorShade(TH_SHADE1, -20);
+ glRecti(2, 2, 20, ar->winy-6);
+ uiEmboss(2, 2, 20, ar->winy-6, 1);
+
+ UI_ThemeColor(TH_SHADE1);
+ glRecti(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax);
+
+ UI_ThemeColor(TH_SHADE2);
+ 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);
+}
+
+/************************** draw markers **************************/
+
+static void draw_markers(SpaceText *st, ARegion *ar)
+{
+ Text *text= st->text;
+ TextMarker *marker, *next;
+ TextLine *top, *bottom, *line;
+ int offl, offc, i, cy, x1, x2, y1, y2, x, y;
+
+ for(i=st->top, top= text->lines.first; top->next && i>0; i--)
+ top= top->next;
+
+ for(i=st->viewlines-1, bottom=top; bottom->next && i>0; i--)
+ bottom= bottom->next;
+
+ for(marker= text->markers.first; marker; marker= next) {
+ next= marker->next;
+
+ for(cy= 0, line= top; line; cy++, line= line->next) {
+ if(cy+st->top==marker->lineno) {
+ /* Remove broken markers */
+ if(marker->end>line->len || marker->start>marker->end) {
+ BLI_freelinkN(&text->markers, marker);
+ break;
+ }
+
+ wrap_offset(st, ar, line, marker->start, &offl, &offc);
+ x1= get_char_pos(st, line->line, marker->start) - st->left + offc;
+ y1= cy + offl;
+ wrap_offset(st, ar, line, marker->end, &offl, &offc);
+ x2= get_char_pos(st, line->line, marker->end) - st->left + offc;
+ y2= cy + offl;
+
+ glColor3ub(marker->color[0], marker->color[1], marker->color[2]);
+ x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ y= ar->winy-3;
+
+ if(y1==y2) {
+ y -= y1*st->lheight;
+ glBegin(GL_LINE_LOOP);
+ glVertex2i(x+x2*text_font_width_character(st)+1, y);
+ glVertex2i(x+x1*text_font_width_character(st)-2, y);
+ glVertex2i(x+x1*text_font_width_character(st)-2, y-st->lheight);
+ glVertex2i(x+x2*text_font_width_character(st)+1, y-st->lheight);
+ glEnd();
+ }
+ else {
+ y -= y1*st->lheight;
+ glBegin(GL_LINE_STRIP);
+ glVertex2i(ar->winx, y);
+ glVertex2i(x+x1*text_font_width_character(st)-2, y);
+ glVertex2i(x+x1*text_font_width_character(st)-2, y-st->lheight);
+ glVertex2i(ar->winx, y-st->lheight);
+ glEnd();
+ y-=st->lheight;
+
+ for(i=y1+1; i<y2; i++) {
+ glBegin(GL_LINES);
+ glVertex2i(x, y);
+ glVertex2i(ar->winx, y);
+ glVertex2i(x, y-st->lheight);
+ glVertex2i(ar->winx, y-st->lheight);
+ glEnd();
+ y-=st->lheight;
+ }
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2i(x, y);
+ glVertex2i(x+x2*text_font_width_character(st)+1, y);
+ glVertex2i(x+x2*text_font_width_character(st)+1, y-st->lheight);
+ glVertex2i(x, y-st->lheight);
+ glEnd();
+ }
+
+ break;
+ }
+
+ if(line==bottom) break;
+ }
+ }
+}
+
+/*********************** draw documentation *******************************/
+
+static void draw_documentation(SpaceText *st, ARegion *ar)
+{
+ TextLine *tmp;
+ char *docs, buf[DOC_WIDTH+1], *p;
+ int len, i, br, lines;
+ int boxw, boxh, l, x, y, top;
+
+ if(!st || !st->text) return;
+ if(!texttool_text_is_active(st->text)) return;
+
+ docs = texttool_docs_get();
+
+ if(!docs) return;
+
+ /* Count the visible lines to the cursor */
+ for(tmp=st->text->curl, l=-st->top; tmp; tmp=tmp->prev, l++);
+ if(l<0) return;
+
+ if(st->showlinenrs) {
+ x= text_font_width_character(st)*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4;
+ }
+ else {
+ x= text_font_width_character(st)*(st->text->curc-st->left) + TXT_OFFSET - 4;
+ }
+ if(texttool_suggest_first()) {
+ x += SUGG_LIST_WIDTH*text_font_width_character(st) + 50;
+ }
+
+ top= y= ar->winy - st->lheight*l - 2;
+ len= strlen(docs);
+ boxw= DOC_WIDTH*text_font_width_character(st) + 20;
+ boxh= (DOC_HEIGHT+1)*st->lheight;
+
+ /* Draw panel */
+ UI_ThemeColor(TH_BACK);
+ glRecti(x, y, x+boxw, y-boxh);
+ UI_ThemeColor(TH_SHADE1);
+ glBegin(GL_LINE_LOOP);
+ glVertex2i(x, y);
+ glVertex2i(x+boxw, y);
+ glVertex2i(x+boxw, y-boxh);
+ glVertex2i(x, y-boxh);
+ glEnd();
+ glBegin(GL_LINE_LOOP);
+ glVertex2i(x+boxw-10, y-7);
+ glVertex2i(x+boxw-4, y-7);
+ glVertex2i(x+boxw-7, y-2);
+ glEnd();
+ glBegin(GL_LINE_LOOP);
+ glVertex2i(x+boxw-10, y-boxh+7);
+ glVertex2i(x+boxw-4, y-boxh+7);
+ glVertex2i(x+boxw-7, y-boxh+2);
+ glEnd();
+ UI_ThemeColor(TH_TEXT);
+
+ i= 0; br= DOC_WIDTH; lines= 0; // XXX -doc_scroll;
+ for(p=docs; *p; p++) {
+ if(*p == '\r' && *(++p) != '\n') *(--p)= '\n'; /* Fix line endings */
+ if(*p == ' ' || *p == '\t')
+ br= i;
+ else if(*p == '\n') {
+ buf[i]= '\0';
+ if(lines>=0) {
+ y -= st->lheight;
+ text_draw(st, buf, 0, 0, 1, x+4, y-3, NULL);
+ }
+ i= 0; br= DOC_WIDTH; lines++;
+ }
+ buf[i++]= *p;
+ if(i == DOC_WIDTH) { /* Reached the width, go to last break and wrap there */
+ buf[br]= '\0';
+ if(lines>=0) {
+ y -= st->lheight;
+ text_draw(st, buf, 0, 0, 1, x+4, y-3, NULL);
+ }
+ p -= i-br-1; /* Rewind pointer to last break */
+ i= 0; br= DOC_WIDTH; lines++;
+ }
+ if(lines >= DOC_HEIGHT) break;
+ }
+
+ if(0 /* XXX doc_scroll*/ > 0 && lines < DOC_HEIGHT) {
+ // XXX doc_scroll--;
+ draw_documentation(st, ar);
+ }
+}
+
+/*********************** draw suggestion list *******************************/
+
+static void draw_suggestion_list(SpaceText *st, ARegion *ar)
+{
+ SuggItem *item, *first, *last, *sel;
+ TextLine *tmp;
+ char str[SUGG_LIST_WIDTH+1];
+ int w, boxw=0, boxh, i, l, x, y, b, *top;
+
+ if(!st || !st->text) return;
+ if(!texttool_text_is_active(st->text)) return;
+
+ first = texttool_suggest_first();
+ last = texttool_suggest_last();
+
+ if(!first || !last) return;
+
+ text_pop_suggest_list();
+ sel = texttool_suggest_selected();
+ top = texttool_suggest_top();
+
+ /* Count the visible lines to the cursor */
+ for(tmp=st->text->curl, l=-st->top; tmp; tmp=tmp->prev, l++);
+ if(l<0) return;
+
+ if(st->showlinenrs) {
+ x = text_font_width_character(st)*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4;
+ }
+ else {
+ x = text_font_width_character(st)*(st->text->curc-st->left) + TXT_OFFSET - 4;
+ }
+ y = ar->winy - st->lheight*l - 2;
+
+ boxw = SUGG_LIST_WIDTH*text_font_width_character(st) + 20;
+ boxh = SUGG_LIST_SIZE*st->lheight + 8;
+
+ UI_ThemeColor(TH_SHADE1);
+ glRecti(x-1, y+1, x+boxw+1, y-boxh-1);
+ UI_ThemeColor(TH_BACK);
+ glRecti(x, y, x+boxw, y-boxh);
+
+ /* Set the top 'item' of the visible list */
+ for(i=0, item=first; i<*top && item->next; i++, item=item->next);
+
+ for(i=0; i<SUGG_LIST_SIZE && item; i++, item=item->next) {
+
+ y -= st->lheight;
+
+ strncpy(str, item->name, SUGG_LIST_WIDTH);
+ str[SUGG_LIST_WIDTH] = '\0';
+
+ w = text_font_width(st, str);
+
+ if(item == sel) {
+ UI_ThemeColor(TH_SHADE2);
+ glRecti(x+16, y-3, x+16+w, y+st->lheight-3);
+ }
+ b=1; /* b=1 colour block, text is default. b=0 no block, colour text */
+ switch (item->type) {
+ case 'k': UI_ThemeColor(TH_SYNTAX_B); b=0; break;
+ case 'm': UI_ThemeColor(TH_TEXT); break;
+ case 'f': UI_ThemeColor(TH_SYNTAX_L); break;
+ case 'v': UI_ThemeColor(TH_SYNTAX_N); break;
+ case '?': UI_ThemeColor(TH_TEXT); b=0; break;
+ }
+ if(b) {
+ glRecti(x+8, y+2, x+11, y+5);
+ UI_ThemeColor(TH_TEXT);
+ }
+ text_draw(st, str, 0, 0, 1, x+16, y-1, NULL);
+
+ if(item == last) break;
+ }
+}
+
+/*********************** draw cursor ************************/
+
+static void draw_cursor(SpaceText *st, ARegion *ar)
+{
+ Text *text= st->text;
+ int vcurl, vcurc, vsell, vselc, hidden=0;
+ int offl, offc, x, y, w, i;
+
+ /* Draw the selection */
+ if(text->curl!=text->sell || text->curc!=text->selc) {
+ /* Convert all to view space character coordinates */
+ wrap_offset(st, ar, text->curl, text->curc, &offl, &offc);
+ vcurl = txt_get_span(text->lines.first, text->curl) - st->top + offl;
+ vcurc = get_char_pos(st, text->curl->line, text->curc) - st->left + offc;
+ wrap_offset(st, ar, text->sell, text->selc, &offl, &offc);
+ vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl;
+ vselc = get_char_pos(st, text->sell->line, text->selc) - st->left + offc;
+
+ if(vcurc<0) vcurc=0;
+ if(vselc<0) vselc=0, hidden=1;
+
+ UI_ThemeColor(TH_SHADE2);
+ x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ y= ar->winy-2;
+
+ if(vcurl==vsell) {
+ y -= vcurl*st->lheight;
+ if(vcurc < vselc)
+ glRecti(x+vcurc*text_font_width_character(st)-1, y, x+vselc*text_font_width_character(st), y-st->lheight);
+ else
+ glRecti(x+vselc*text_font_width_character(st)-1, y, x+vcurc*text_font_width_character(st), y-st->lheight);
+ }
+ else {
+ int froml, fromc, tol, toc;
+
+ if(vcurl < vsell) {
+ froml= vcurl; tol= vsell;
+ fromc= vcurc; toc= vselc;
+ }
+ else {
+ froml= vsell; tol= vcurl;
+ fromc= vselc; toc= vcurc;
+ }
+
+ y -= froml*st->lheight;
+ glRecti(x+fromc*text_font_width_character(st)-1, y, ar->winx, y-st->lheight); y-=st->lheight;
+ for(i=froml+1; i<tol; i++)
+ glRecti(x-4, y, ar->winx, y-st->lheight), y-=st->lheight;
+
+ glRecti(x-4, y, x+toc*text_font_width_character(st), y-st->lheight); y-=st->lheight;
+ }
+ }
+ else {
+ wrap_offset(st, ar, text->sell, text->selc, &offl, &offc);
+ vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl;
+ vselc = get_char_pos(st, text->sell->line, text->selc) - st->left + offc;
+
+ if(vselc<0) {
+ vselc= 0;
+ hidden= 1;
+ }
+ }
+
+ if(!hidden) {
+ /* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */
+ x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ x += vselc*text_font_width_character(st);
+ y= ar->winy-2 - vsell*st->lheight;
+
+ if(st->overwrite) {
+ char ch= text->sell->line[text->selc];
+ if(!ch) ch= ' ';
+ w= text_font_width_character(st);
+ UI_ThemeColor(TH_HILITE);
+ glRecti(x, y-st->lheight-1, x+w, y-st->lheight+1);
+ }
+ else {
+ UI_ThemeColor(TH_HILITE);
+ glRecti(x-1, y, x+1, y-st->lheight);
+ }
+ }
+}
+
+/******************* draw matching brackets *********************/
+
+static void draw_brackets(SpaceText *st, ARegion *ar)
+{
+ TextLine *startl, *endl, *linep;
+ Text *text = st->text;
+ int b, c, startc, endc, find, stack;
+ int viewc, viewl, offl, offc, x, y;
+ char ch;
+
+ if(!text->curl) return;
+
+ startl= text->curl;
+ startc= text->curc;
+ b= text_check_bracket(startl->line[startc]);
+ if(b==0 && startc>0) b = text_check_bracket(startl->line[--startc]);
+ if(b==0) return;
+
+ linep= startl;
+ c= startc;
+ endl= NULL;
+ endc= -1;
+ find= -b;
+ stack= 0;
+
+ if(b>0) {
+ /* opening bracket, search forward for close */
+ c++;
+ while(linep) {
+ while(c<linep->len) {
+ b= text_check_bracket(linep->line[c]);
+ if(b==find) {
+ if(stack==0) {
+ endl= linep;
+ endc= c;
+ break;
+ }
+ stack--;
+ }
+ else if(b==-find) {
+ stack++;
+ }
+ c++;
+ }
+ if(endl) break;
+ linep= linep->next;
+ c= 0;
+ }
+ }
+ else {
+ /* closing bracket, search backward for open */
+ c--;
+ while(linep) {
+ while(c>=0) {
+ b= text_check_bracket(linep->line[c]);
+ if(b==find) {
+ if(stack==0) {
+ endl= linep;
+ endc= c;
+ break;
+ }
+ stack--;
+ }
+ else if(b==-find) {
+ stack++;
+ }
+ c--;
+ }
+ if(endl) break;
+ linep= linep->prev;
+ if(linep) c= linep->len-1;
+ }
+ }
+
+ if(!endl || endc==-1)
+ return;
+
+ UI_ThemeColor(TH_HILITE);
+ x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ y= ar->winy - st->lheight;
+
+ /* draw opening bracket */
+ ch= startl->line[startc];
+ wrap_offset(st, ar, startl, startc, &offl, &offc);
+ viewc= get_char_pos(st, startl->line, startc) - st->left + offc;
+
+ if(viewc >= 0){
+ viewl= txt_get_span(text->lines.first, startl) - st->top + offl;
+
+ text_font_draw_character(st, x+viewc*text_font_width_character(st), y-viewl*st->lheight, ch);
+ text_font_draw_character(st, x+viewc*text_font_width_character(st)+1, y-viewl*st->lheight, ch);
+ }
+
+ /* draw closing bracket */
+ ch= endl->line[endc];
+ wrap_offset(st, ar, endl, endc, &offl, &offc);
+ viewc= get_char_pos(st, endl->line, endc) - st->left + offc;
+
+ if(viewc >= 0) {
+ viewl= txt_get_span(text->lines.first, endl) - st->top + offl;
+
+ text_font_draw_character(st, x+viewc*text_font_width_character(st), y-viewl*st->lheight, ch);
+ text_font_draw_character(st, x+viewc*text_font_width_character(st)+1, y-viewl*st->lheight, ch);
+ }
+}
+
+/*********************** main area drawing *************************/
+
+void draw_text_main(SpaceText *st, ARegion *ar)
+{
+ Text *text= st->text;
+ TextLine *tmp;
+ char linenr[12];
+ int i, x, y, linecount= 0;
+
+ /* if no text, nothing to do */
+ 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)ar->winy/st->lheight;
+ else st->viewlines= 0;
+
+ /* update rects for scroll */
+ calc_text_rcts(st, ar);
+
+ /* update syntax formatting if needed */
+ tmp= text->lines.first;
+ for(i= 0; i<st->top && tmp; i++) {
+ if(st->showsyntax && !tmp->format)
+ txt_format_line(st, tmp, 0);
+
+ tmp= tmp->next;
+ linecount++;
+ }
+
+ /* draw line numbers background */
+ if(st->showlinenrs) {
+ UI_ThemeColor(TH_GRID);
+ glRecti(23, 0, (st->lheight==15)? 63: 59, ar->winy - 2);
+ }
+
+ text_font_begin(st);
+
+ /* draw cursor */
+ draw_cursor(st, ar);
+
+ /* draw the text */
+ UI_ThemeColor(TH_TEXT);
+
+ y= ar->winy-st->lheight;
+ x= (st->showlinenrs)? TXT_OFFSET + TEXTXLOC: TXT_OFFSET;
+
+ for(i=0; y>0 && i<st->viewlines && tmp; i++, tmp= tmp->next) {
+ if(st->showsyntax && !tmp->format)
+ txt_format_line(st, tmp, 0);
+
+ if(st->showlinenrs) {
+ /* draw line number */
+ if(tmp == text->curl)
+ UI_ThemeColor(TH_HILITE);
+ else
+ UI_ThemeColor(TH_TEXT);
+
+ if(((float)(i + linecount + 1)/10000.0) < 1.0) {
+ sprintf(linenr, "%4d", i + linecount + 1);
+ text_font_draw(st, TXT_OFFSET - 7, y, linenr);
+ }
+ else {
+ sprintf(linenr, "%5d", i + linecount + 1);
+ text_font_draw(st, TXT_OFFSET - 11, y, linenr);
+ }
+
+ UI_ThemeColor(TH_TEXT);
+ }
+
+ if(st->wordwrap) {
+ /* draw word wrapped text */
+ int lines = text_draw_wrapped(st, tmp->line, x, y, ar->winx-x, tmp->format);
+ y -= lines*st->lheight;
+ }
+ else {
+ /* draw unwrapped text */
+ text_draw(st, tmp->line, st->left, 0, 1, x, y, tmp->format);
+ y -= st->lheight;
+ }
+ }
+
+ /* draw other stuff */
+ draw_brackets(st, ar);
+ draw_markers(st, ar);
+ draw_textscroll(st, ar);
+ draw_documentation(st, ar);
+ draw_suggestion_list(st, ar);
+
+ text_font_end(st);
+}
+
+/************************** update ***************************/
+
+/* Moves the view to the cursor location,
+ also used to make sure the view isnt outside the file */
+void text_update_cursor_moved(SpaceText *st, ARegion *ar)
+{
+ Text *text= st->text;
+ int i, x;
+
+ if(!text || !text->curl) return;
+
+ i= txt_get_span(text->lines.first, text->sell);
+ if(st->top+st->viewlines <= i || st->top > i)
+ st->top= i - st->viewlines/2;
+
+ if(st->wordwrap) {
+ st->left= 0;
+ }
+ else {
+ x= text_draw(st, text->sell->line, st->left, text->selc, 0, 0, 0, NULL);
+
+ if(x==0 || x>ar->winx)
+ st->left= text->curc-0.5*(ar->winx)/text_font_width_character(st);
+ }
+
+ if(st->top < 0) st->top= 0;
+ if(st->left <0) st->left= 0;
+}
+
diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c
new file mode 100644
index 00000000000..0ab43cbf455
--- /dev/null
+++ b/source/blender/editors/space_text/text_header.c
@@ -0,0 +1,644 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+/* file time checking */
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_text_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_text.h"
+
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "RNA_access.h"
+
+#ifndef DISABLE_PYTHON
+#include "BPY_extern.h"
+// XXX #include "BPY_menus.h"
+#endif
+
+#include "text_intern.h"
+
+#define HEADER_PATH_MAX 260
+
+/* ************************ header area region *********************** */
+
+#ifndef DISABLE_PYTHON
+static void do_text_template_scriptsmenu(bContext *C, void *arg, int event)
+{
+ // XXX BPY_menu_do_python(PYMENU_SCRIPTTEMPLATE, event);
+}
+
+static uiBlock *text_template_scriptsmenu(bContext *C, void *args_unused)
+{
+ ARegion *ar= CTX_wm_region(C);
+ uiBlock *block;
+ // XXX BPyMenu *pym;
+ // int i= 0;
+ // short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "text_template_scriptsmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_text_template_scriptsmenu, NULL);
+
+ /* note that we acount for the N previous entries with i+20: */
+ /* XXX for (pym = BPyMenuTable[PYMENU_SCRIPTTEMPLATE]; pym; pym = pym->next, i++) {
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20, menuwidth, 19,
+ NULL, 0.0, 0.0, 1, i,
+ pym->tooltip?pym->tooltip:pym->filename);
+ }*/
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+
+ return block;
+}
+
+static void do_text_plugin_scriptsmenu(bContext *C, void *arg, int event)
+{
+ // XXX BPY_menu_do_python(PYMENU_TEXTPLUGIN, event);
+}
+
+static uiBlock *text_plugin_scriptsmenu(bContext *C, void *args_unused)
+{
+ ARegion *ar= CTX_wm_region(C);
+ uiBlock *block;
+ // XXX BPyMenu *pym;
+ // int i= 0;
+ // short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "text_plugin_scriptsmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_text_plugin_scriptsmenu, NULL);
+
+ /* note that we acount for the N previous entries with i+20: */
+ /* XXX for (pym = BPyMenuTable[PYMENU_TEXTPLUGIN]; pym; pym = pym->next, i++) {
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20, menuwidth, 19,
+ NULL, 0.0, 0.0, 1, i,
+ pym->tooltip?pym->tooltip:pym->filename);
+ }*/
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+
+ return block;
+}
+#endif
+
+static void text_editmenu_viewmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuItemEnumO(head, "Top of File", 0, "TEXT_OT_move", "type", FILE_TOP);
+ uiMenuItemEnumO(head, "Bottom of File", 0, "TEXT_OT_move", "type", FILE_BOTTOM);
+}
+
+static void text_editmenu_selectmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuItemO(head, 0, "TEXT_OT_select_all");
+ uiMenuItemO(head, 0, "TEXT_OT_select_line");
+}
+
+static void text_editmenu_markermenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuItemO(head, 0, "TEXT_OT_markers_clear");
+ uiMenuItemO(head, 0, "TEXT_OT_next_marker");
+ uiMenuItemO(head, 0, "TEXT_OT_previous_marker");
+}
+
+static void text_formatmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuItemO(head, 0, "TEXT_OT_indent");
+ uiMenuItemO(head, 0, "TEXT_OT_unindent");
+
+ uiMenuSeparator(head);
+
+ uiMenuItemO(head, 0, "TEXT_OT_comment");
+ uiMenuItemO(head, 0, "TEXT_OT_uncomment");
+
+ uiMenuSeparator(head);
+
+ uiMenuLevelEnumO(head, "TEXT_OT_convert_whitespace", "type");
+}
+
+static void text_editmenu_to3dmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuItemBooleanO(head, "One Object", 0, "TEXT_OT_to_3d_object", "split_lines", 0);
+ uiMenuItemBooleanO(head, "One Object Per Line", 0, "TEXT_OT_to_3d_object", "split_lines", 1);
+}
+
+static int text_menu_edit_poll(bContext *C)
+{
+ return (CTX_data_edit_text(C) != NULL);
+}
+
+static void text_editmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuItemO(head, 0, "ED_OT_undo");
+ uiMenuItemO(head, 0, "ED_OT_redo");
+
+ uiMenuSeparator(head);
+
+ uiMenuItemO(head, 0, "TEXT_OT_cut");
+ uiMenuItemO(head, 0, "TEXT_OT_copy");
+ uiMenuItemO(head, 0, "TEXT_OT_paste");
+
+ uiMenuSeparator(head);
+
+ uiMenuLevel(head, "View", text_editmenu_viewmenu);
+ uiMenuLevel(head, "Select", text_editmenu_selectmenu);
+ uiMenuLevel(head, "Markers", text_editmenu_markermenu);
+
+ uiMenuSeparator(head);
+
+ uiMenuItemO(head, 0, "TEXT_OT_jump");
+ uiMenuItemO(head, 0, "TEXT_OT_properties");
+
+ uiMenuSeparator(head);
+
+ uiMenuLevel(head, "Text to 3D Object", text_editmenu_to3dmenu);
+}
+
+static void text_filemenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ SpaceText *st= (SpaceText*)CTX_wm_space_data(C);
+ Text *text= st->text;
+
+ uiMenuItemO(head, 0, "TEXT_OT_new");
+ uiMenuItemO(head, 0, "TEXT_OT_open");
+
+ if(text) {
+ uiMenuItemO(head, 0, "TEXT_OT_reload");
+
+ uiMenuSeparator(head);
+
+ uiMenuItemO(head, 0, "TEXT_OT_save");
+ uiMenuItemO(head, 0, "TEXT_OT_save_as");
+
+ if(text->name)
+ uiMenuItemO(head, 0, "TEXT_OT_make_internal");
+
+ uiMenuSeparator(head);
+
+ uiMenuItemO(head, 0, "TEXT_OT_run_script");
+
+#ifndef DISABLE_PYTHON
+ if(BPY_is_pyconstraint(text))
+ uiMenuItemO(head, 0, "TEXT_OT_refresh_pyconstraints");
+#endif
+ }
+
+#ifndef DISABLE_PYTHON
+ // XXX uiMenuSeparator(head);
+
+ // XXX uiDefIconTextBlockBut(block, text_template_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Script Templates", 0, yco-=20, 120, 19, "");
+ // XXX uiDefIconTextBlockBut(block, text_plugin_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Text Plugins", 0, yco-=20, 120, 19, "");
+#endif
+}
+
+/*********************** datablock browse *************************/
+
+static void text_unlink(Main *bmain, Text *text)
+{
+ bScreen *scr;
+ ScrArea *area;
+ SpaceLink *sl;
+
+ /* XXX this ifdef is in fact dangerous, if python is
+ * disabled it will leave invalid pointers in files! */
+
+#ifndef DISABLE_PYTHON
+ // XXX BPY_clear_bad_scriptlinks(text);
+ // XXX BPY_free_pyconstraint_links(text);
+ // XXX free_text_controllers(text);
+ // XXX free_dome_warp_text(text);
+
+ /* check if this text was used as script link:
+ * this check function unsets the pointers and returns how many
+ * script links used this Text */
+ if(0) // XXX BPY_text_check_all_scriptlinks (text))
+ ; // XXX notifier: allqueue(REDRAWBUTSSCRIPT, 0);
+
+ /* equivalently for pynodes: */
+ if(0) // XXX nodeDynamicUnlinkText ((ID*)text))
+ ; // XXX notifier: allqueue(REDRAWNODE, 0);
+#endif
+
+ for(scr= bmain->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)
+ ED_area_tag_redraw(area);
+ }
+ }
+ }
+ }
+ }
+
+ free_libblock(&bmain->text, text);
+}
+
+static void text_idpoin_handle(bContext *C, ID *id, int event)
+{
+ SpaceText *st= (SpaceText*)CTX_wm_space_data(C);
+ Text *text;
+
+ switch(event) {
+ case UI_ID_BROWSE:
+ st->text= (Text*)id;
+ st->top= 0;
+
+ text_update_edited(st->text);
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, st->text);
+
+ ED_undo_push(C, "Browse Text");
+ break;
+ case UI_ID_DELETE:
+ text= st->text;
+
+ /* make the previous text active, if its not there make the next text active */
+ if(text->id.prev) {
+ st->text = text->id.prev;
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, st->text);
+ }
+ else if(text->id.next) {
+ st->text = text->id.next;
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, st->text);
+ }
+
+ text_unlink(CTX_data_main(C), text);
+ WM_event_add_notifier(C, NC_TEXT|NA_REMOVED, text);
+
+ ED_undo_push(C, "Delete Text");
+ break;
+ case UI_ID_RENAME:
+ break;
+ case UI_ID_ADD_NEW:
+ WM_operator_name_call(C, "TEXT_OT_new", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ case UI_ID_OPEN:
+ WM_operator_name_call(C, "TEXT_OT_open", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ }
+}
+
+/********************** header buttons ***********************/
+
+static void text_header_draw(const bContext *C, Header *header)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ SpaceText *st= (SpaceText*)CTX_wm_space_data(C);
+ PointerRNA spaceptr;
+ Text *text= st->text;
+ uiLayout *layout= header->layout;
+
+ RNA_pointer_create(&sc->id, &RNA_SpaceTextEditor, st, &spaceptr);
+
+ uiTemplateHeaderMenus(layout);
+ uiItemM(layout, "Text", 0, text_filemenu);
+ if(text) {
+ uiItemM(layout, "Edit", 0, text_editmenu);
+ uiItemM(layout, "Format", 0, text_formatmenu);
+ }
+
+ /* warning button if text is out of date */
+ if(text && text_file_modified(text)) {
+ uiTemplateHeaderButtons(layout);
+ uiTemplateSetColor(layout, TH_REDALERT);
+ uiItemO(layout, "", ICON_HELP, "TEXT_OT_resolve_conflict");
+ }
+
+ uiTemplateHeaderButtons(layout);
+ uiItemR(layout, "", ICON_LINENUMBERS_OFF, &spaceptr, "line_numbers", 0);
+ uiItemR(layout, "", ICON_WORDWRAP_OFF, &spaceptr, "word_wrap", 0);
+ uiItemR(layout, "", ICON_SYNTAX_OFF, &spaceptr, "syntax_highlight", 0);
+ // XXX uiItemR(layout, "", ICON_SCRIPTPLUGINS, &spaceptr, "do_python_plugins", 0);
+
+ uiTemplateHeaderID(layout, &spaceptr, "text",
+ UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_OPEN|UI_ID_DELETE,
+ text_idpoin_handle);
+
+ /* file info */
+ if(text) {
+ char fname[HEADER_PATH_MAX];
+ static char headtxt[HEADER_PATH_MAX+17];
+ int len;
+
+ if(text->name) {
+ len = strlen(text->name);
+ if(len > HEADER_PATH_MAX-1)
+ len = HEADER_PATH_MAX-1;
+ strncpy(fname, text->name, len);
+ fname[len]='\0';
+ if(text->flags & TXT_ISDIRTY)
+ sprintf(headtxt, "File: *%s (unsaved)", fname);
+ else
+ sprintf(headtxt, "File: %s", fname);
+ }
+ else
+ sprintf(headtxt, text->id.lib? "Text: External": "Text: Internal");
+
+ uiTemplateHeaderButtons(layout);
+ uiItemL(layout, headtxt, 0);
+ }
+}
+
+void text_header_register(ARegionType *art)
+{
+ HeaderType *ht;
+
+ /* header */
+ ht= MEM_callocN(sizeof(HeaderType), "spacetype text header");
+ strcpy(ht->idname, "TEXT_HT_header");
+ ht->draw= text_header_draw;
+ BLI_addhead(&art->headertypes, ht);
+}
+
+/************************** properties ******************************/
+
+static void text_properties_panel_draw(const bContext *C, Panel *panel)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ SpaceText *st= CTX_wm_space_text(C);
+ uiLayout *layout= panel->layout;
+ PointerRNA spaceptr;
+
+ RNA_pointer_create(&sc->id, &RNA_SpaceTextEditor, st, &spaceptr);
+
+ uiLayoutColumn(layout);
+ uiItemR(layout, NULL, ICON_LINENUMBERS_OFF, &spaceptr, "line_numbers", 0);
+ uiItemR(layout, NULL, ICON_WORDWRAP_OFF, &spaceptr, "word_wrap", 0);
+ uiItemR(layout, NULL, ICON_SYNTAX_OFF, &spaceptr, "syntax_highlight", 0);
+
+ uiLayoutColumn(layout);
+ uiItemR(layout, NULL, 0, &spaceptr, "font_size", 0);
+ uiItemR(layout, NULL, 0, &spaceptr, "tab_width", 0);
+}
+
+static void text_find_panel_draw(const bContext *C, Panel *panel)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ SpaceText *st= CTX_wm_space_text(C);
+ uiLayout *layout= panel->layout;
+ PointerRNA spaceptr;
+
+ RNA_pointer_create(&sc->id, &RNA_SpaceTextEditor, st, &spaceptr);
+
+ /* find */
+ uiLayoutRow(layout);
+ uiItemR(layout, "", 0, &spaceptr, "find_text", 0);
+ uiItemO(layout, "", ICON_TEXT, "TEXT_OT_find_set_selected");
+ uiLayoutColumn(layout);
+ uiItemO(layout, NULL, 0, "TEXT_OT_find");
+
+ /* replace */
+ uiLayoutRow(layout);
+ uiItemR(layout, "", 0, &spaceptr, "replace_text", 0);
+ uiItemO(layout, "", ICON_TEXT, "TEXT_OT_replace_set_selected");
+ uiLayoutColumn(layout);
+ uiItemO(layout, NULL, 0, "TEXT_OT_replace");
+
+ /* mark */
+ uiLayoutColumn(layout);
+ uiItemO(layout, NULL, 0, "TEXT_OT_mark_all");
+
+ /* settings */
+ uiLayoutColumnFlow(layout, 0);
+ uiItemR(layout, "Wrap", 0, &spaceptr, "find_wrap", 0);
+ uiItemR(layout, "All", 0, &spaceptr, "find_all", 0);
+}
+
+void text_properties_register(ARegionType *art)
+{
+ PanelType *pt;
+
+ /* panels: properties */
+ pt= MEM_callocN(sizeof(PanelType), "spacetype text panel");
+ strcpy(pt->idname, "TEXT_PT_properties");
+ strcpy(pt->label, "Properties");
+ pt->draw= text_properties_panel_draw;
+ BLI_addtail(&art->paneltypes, pt);
+
+ /* panels: find */
+ pt= MEM_callocN(sizeof(PanelType), "spacetype text panel");
+ strcpy(pt->idname, "TEXT_PT_find");
+ strcpy(pt->label, "Find");
+ pt->draw= text_find_panel_draw;
+ BLI_addtail(&art->paneltypes, pt);
+}
+
+ARegion *text_has_properties_region(ScrArea *sa)
+{
+ ARegion *ar, *arnew;
+
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ if(ar->regiontype==RGN_TYPE_UI)
+ return ar;
+
+ /* add subdiv level; after header */
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ if(ar->regiontype==RGN_TYPE_HEADER)
+ break;
+
+ /* is error! */
+ if(ar==NULL) return NULL;
+
+ arnew= MEM_callocN(sizeof(ARegion), "properties region");
+
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype= RGN_TYPE_UI;
+ arnew->alignment= RGN_ALIGN_LEFT;
+
+ arnew->flag = RGN_FLAG_HIDDEN;
+
+ return arnew;
+}
+
+static int properties_poll(bContext *C)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ Text *text= CTX_data_edit_text(C);
+
+ return (st && text);
+}
+
+static int properties_exec(bContext *C, wmOperator *op)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= text_has_properties_region(sa);
+
+ if(ar) {
+ ar->flag ^= RGN_FLAG_HIDDEN;
+ ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */
+
+ ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
+ ED_area_tag_redraw(sa);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_properties(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Properties";
+ ot->idname= "TEXT_OT_properties";
+
+ /* api callbacks */
+ ot->exec= properties_exec;
+ ot->poll= properties_poll;
+}
+
+/******************** XXX popup menus *******************/
+
+#if 0
+{
+ // RMB
+
+ uiMenuItem *head;
+
+ if(text) {
+ head= uiPupMenuBegin("Text", 0);
+ if(txt_has_sel(text)) {
+ uiMenuItemO(head, 0, "TEXT_OT_cut");
+ uiMenuItemO(head, 0, "TEXT_OT_copy");
+ }
+ uiMenuItemO(head, 0, "TEXT_OT_paste");
+ uiMenuItemO(head, 0, "TEXT_OT_new");
+ uiMenuItemO(head, 0, "TEXT_OT_open");
+ uiMenuItemO(head, 0, "TEXT_OT_save");
+ uiMenuItemO(head, 0, "TEXT_OT_save_as");
+ uiMenuItemO(head, 0, "TEXT_OT_run_script");
+ uiPupMenuEnd(C, head);
+ }
+ else {
+ head= uiPupMenuBegin("File", 0);
+ uiMenuItemO(head, 0, "TEXT_OT_new");
+ uiMenuItemO(head, 0, "TEXT_OT_open");
+ uiPupMenuEnd(C, head);
+ }
+}
+
+{
+ // Alt+Shift+E
+
+ uiMenuItem *head;
+
+ head= uiPupMenuBegin("Edit", 0);
+ uiMenuItemO(head, 0, "TEXT_OT_cut");
+ uiMenuItemO(head, 0, "TEXT_OT_copy");
+ uiMenuItemO(head, 0, "TEXT_OT_paste");
+ uiPupMenuEnd(C, head);
+}
+
+{
+ // Alt+Shift+F
+
+ uiMenuItem *head;
+
+ if(text) {
+ head= uiPupMenuBegin("Text", 0);
+ uiMenuItemO(head, 0, "TEXT_OT_new");
+ uiMenuItemO(head, 0, "TEXT_OT_open");
+ uiMenuItemO(head, 0, "TEXT_OT_save");
+ uiMenuItemO(head, 0, "TEXT_OT_save_as");
+ uiMenuItemO(head, 0, "TEXT_OT_run_script");
+ uiPupMenuEnd(C, head);
+ }
+ else {
+ head= uiPupMenuBegin("File", 0);
+ uiMenuItemO(head, 0, "TEXT_OT_new");
+ uiMenuItemO(head, 0, "TEXT_OT_open");
+ uiPupMenuEnd(C, head);
+ }
+}
+
+{
+ // Alt+Shift+V
+
+ uiMenuItem *head;
+
+ head= uiPupMenuBegin("Text", 0);
+ uiMenuItemEnumO(head, "Top of File", 0, "TEXT_OT_move", "type", FILE_TOP);
+ uiMenuItemEnumO(head, "Bottom of File", 0, "TEXT_OT_move", "type", FILE_BOTTOM);
+ uiMenuItemEnumO(head, "Page Up", 0, "TEXT_OT_move", "type", PREV_PAGE);
+ uiMenuItemEnumO(head, "Page Down", 0, "TEXT_OT_move", "type", NEXT_PAGE);
+ uiPupMenuEnd(C, head);
+}
+#endif
+
diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h
new file mode 100644
index 00000000000..7ec75e292ce
--- /dev/null
+++ b/source/blender/editors/space_text/text_intern.h
@@ -0,0 +1,159 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_TEXT_INTERN_H
+#define ED_TEXT_INTERN_H
+
+/* internal exports only */
+
+struct ARegion;
+struct ARegionType;
+struct bContext;
+struct BMF_Font;
+struct ReportList;
+struct ScrArea;
+struct SpaceText;
+struct Text;
+struct TextLine;
+struct wmOperatorType;
+struct wmWindowManager;
+
+/* text_header.c */
+void text_properties_register(struct ARegionType *art);
+void text_header_register(struct ARegionType *art);
+
+/* text_draw.c */
+void draw_text_main(struct SpaceText *st, struct ARegion *ar);
+
+int text_check_bracket(char ch);
+int text_check_delim(char ch);
+int text_check_digit(char ch);
+int text_check_identifier(char ch);
+int text_check_whitespace(char ch);
+
+int text_font_width_character(struct SpaceText *st);
+int text_font_width(struct SpaceText *st, char *str);
+
+void text_update_line_edited(struct Text *text, struct TextLine *line);
+void text_update_edited(struct Text *text);
+void text_update_cursor_moved(struct SpaceText *st, struct ARegion *ar);
+
+#define TEXTXLOC 38
+
+#define SUGG_LIST_SIZE 7
+#define SUGG_LIST_WIDTH 20
+#define DOC_WIDTH 40
+#define DOC_HEIGHT 10
+
+#define TOOL_SUGG_LIST 0x01
+#define TOOL_DOCUMENT 0x02
+
+#define TMARK_GRP_CUSTOM 0x00010000 /* Lower 2 bytes used for Python groups */
+#define TMARK_GRP_FINDALL 0x00020000
+
+typedef struct FlattenString {
+ char fixedbuf[256];
+ int fixedaccum[256];
+
+ char *buf;
+ int *accum;
+ int pos, len;
+} FlattenString;
+
+int flatten_string(struct SpaceText *st, FlattenString *fs, char *in);
+void flatten_string_free(FlattenString *fs);
+
+void unlink_text(struct Text *text);
+
+int wrap_width(struct SpaceText *st, struct ARegion *ar);
+void wrap_offset(struct SpaceText *st, struct ARegion *ar, struct TextLine *linein, int cursin, int *offl, int *offc);
+
+int text_file_modified(struct Text *text);
+
+int text_do_suggest_select(struct SpaceText *st, struct ARegion *ar);
+void text_pop_suggest_list();
+
+
+/* text_ops.c */
+enum { LINE_BEGIN, LINE_END, FILE_TOP, FILE_BOTTOM, PREV_CHAR, NEXT_CHAR,
+ PREV_WORD, NEXT_WORD, PREV_LINE, NEXT_LINE, PREV_PAGE, NEXT_PAGE };
+enum { DEL_NEXT_CHAR, DEL_PREV_CHAR, DEL_NEXT_WORD, DEL_PREV_WORD };
+
+void TEXT_OT_new(struct wmOperatorType *ot);
+void TEXT_OT_open(struct wmOperatorType *ot);
+void TEXT_OT_reload(struct wmOperatorType *ot);
+void TEXT_OT_save(struct wmOperatorType *ot);
+void TEXT_OT_save_as(struct wmOperatorType *ot);
+void TEXT_OT_make_internal(struct wmOperatorType *ot);
+void TEXT_OT_run_script(struct wmOperatorType *ot);
+void TEXT_OT_refresh_pyconstraints(struct wmOperatorType *ot);
+
+void TEXT_OT_paste(struct wmOperatorType *ot);
+void TEXT_OT_copy(struct wmOperatorType *ot);
+void TEXT_OT_cut(struct wmOperatorType *ot);
+
+void TEXT_OT_convert_whitespace(struct wmOperatorType *ot);
+void TEXT_OT_uncomment(struct wmOperatorType *ot);
+void TEXT_OT_comment(struct wmOperatorType *ot);
+void TEXT_OT_unindent(struct wmOperatorType *ot);
+void TEXT_OT_indent(struct wmOperatorType *ot);
+
+void TEXT_OT_line_break(struct wmOperatorType *ot);
+void TEXT_OT_insert(struct wmOperatorType *ot);
+
+void TEXT_OT_markers_clear(struct wmOperatorType *ot);
+void TEXT_OT_next_marker(struct wmOperatorType *ot);
+void TEXT_OT_previous_marker(struct wmOperatorType *ot);
+
+void TEXT_OT_select_line(struct wmOperatorType *ot);
+void TEXT_OT_select_all(struct wmOperatorType *ot);
+
+void TEXT_OT_jump(struct wmOperatorType *ot);
+void TEXT_OT_move(struct wmOperatorType *ot);
+void TEXT_OT_move_select(struct wmOperatorType *ot);
+void TEXT_OT_delete(struct wmOperatorType *ot);
+void TEXT_OT_overwrite_toggle(struct wmOperatorType *ot);
+
+void TEXT_OT_scroll(struct wmOperatorType *ot);
+void TEXT_OT_scroll_bar(struct wmOperatorType *ot);
+void TEXT_OT_cursor_set(struct wmOperatorType *ot);
+void TEXT_OT_line_number(struct wmOperatorType *ot);
+
+void TEXT_OT_properties(struct wmOperatorType *ot);
+
+void TEXT_OT_find(struct wmOperatorType *ot);
+void TEXT_OT_find_set_selected(struct wmOperatorType *ot);
+void TEXT_OT_replace(struct wmOperatorType *ot);
+void TEXT_OT_replace_set_selected(struct wmOperatorType *ot);
+void TEXT_OT_mark_all(struct wmOperatorType *ot);
+
+void TEXT_OT_to_3d_object(struct wmOperatorType *ot);
+
+void TEXT_OT_resolve_conflict(struct wmOperatorType *ot);
+
+#endif /* ED_TEXT_INTERN_H */
+
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
new file mode 100644
index 00000000000..c7fe02975ef
--- /dev/null
+++ b/source/blender/editors/space_text/text_ops.c
@@ -0,0 +1,2547 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h> /* ispunct */
+#include <sys/stat.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_constraint_types.h"
+#include "DNA_object_types.h"
+#include "DNA_action_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_text_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_blenlib.h"
+#include "PIL_time.h"
+
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+#include "BKE_suggestions.h"
+#include "BKE_text.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_curve.h"
+#include "ED_screen.h"
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#ifndef DISABLE_PYTHON
+#include "BPY_extern.h"
+#endif
+
+#include "text_intern.h"
+
+/************************ poll ***************************/
+
+static int text_new_poll(bContext *C)
+{
+ return 1;
+}
+
+static int text_edit_poll(bContext *C)
+{
+ Text *text= CTX_data_edit_text(C);
+
+ if(!text)
+ return 0;
+
+ if(text->id.lib) {
+ // BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int text_space_edit_poll(bContext *C)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ Text *text= CTX_data_edit_text(C);
+
+ if(!st || !text)
+ return 0;
+
+ if(text->id.lib) {
+ // BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int text_region_edit_poll(bContext *C)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ Text *text= CTX_data_edit_text(C);
+ ARegion *ar= CTX_wm_region(C);
+
+ if(!st || !text)
+ return 0;
+
+ if(!ar || ar->regiontype != RGN_TYPE_WINDOW)
+ return 0;
+
+ if(text->id.lib) {
+ // BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata");
+ return 0;
+ }
+
+ return 1;
+}
+
+
+/********************** updates *********************/
+
+void text_update_line_edited(Text *text, TextLine *line)
+{
+ if(!line)
+ return;
+
+ /* we just free format here, and let it rebuild during draw */
+ if(line->format) {
+ MEM_freeN(line->format);
+ line->format= NULL;
+ }
+}
+
+void text_update_edited(Text *text)
+{
+ TextLine *line;
+
+ for(line=text->lines.first; line; line=line->next)
+ text_update_line_edited(text, line);
+}
+
+/******************* new operator *********************/
+
+static int new_exec(bContext *C, wmOperator *op)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ Text *text;
+
+ text= add_empty_text("Text");
+
+ if(st) {
+ st->text= text;
+ st->top= 0;
+ }
+
+ WM_event_add_notifier(C, NC_TEXT|NA_ADDED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_new(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "New";
+ ot->idname= "TEXT_OT_new";
+
+ /* api callbacks */
+ ot->exec= new_exec;
+ ot->poll= text_new_poll;
+}
+
+/******************* open operator *********************/
+
+static int open_exec(bContext *C, wmOperator *op)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ Text *text;
+ char str[FILE_MAX];
+
+ RNA_string_get(op->ptr, "filename", str);
+
+ text= add_text(str, G.sce);
+
+ if(st) {
+ st->text= text;
+ st->top= 0;
+ }
+
+ WM_event_add_notifier(C, NC_TEXT|NA_ADDED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+static int open_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Text *text= CTX_data_edit_text(C);
+ char *path= (text && text->name)? text->name: G.sce;
+
+ if(RNA_property_is_set(op->ptr, "filename"))
+ return open_exec(C, op);
+
+ RNA_string_set(op->ptr, "filename", path);
+ WM_event_add_fileselect(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void TEXT_OT_open(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Open";
+ ot->idname= "TEXT_OT_open";
+
+ /* api callbacks */
+ ot->exec= open_exec;
+ ot->invoke= open_invoke;
+ ot->poll= text_new_poll;
+
+ /* properties */
+ RNA_def_string_file_path(ot->srna, "filename", "", FILE_MAX, "Filename", "File path of image to open.");
+}
+
+/******************* reload operator *********************/
+
+static int reload_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+
+ if(!reopen_text(text)) {
+ BKE_report(op->reports, RPT_ERROR, "Could not reopen file");
+ return OPERATOR_CANCELLED;
+ }
+
+#ifndef DISABLE_PYTHON
+ if(text->compiled)
+ BPY_free_compiled_text(text);
+
+ text->compiled = NULL;
+#endif
+
+ text_update_edited(text);
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_reload(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Reload";
+ ot->idname= "TEXT_OT_reload";
+
+ /* api callbacks */
+ ot->exec= reload_exec;
+ ot->invoke= WM_operator_confirm;
+ ot->poll= text_edit_poll;
+}
+
+/******************* make internal operator *********************/
+
+static int make_internal_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+
+ text->flags |= TXT_ISMEM | TXT_ISDIRTY;
+
+ if(text->name) {
+ MEM_freeN(text->name);
+ text->name= NULL;
+ }
+
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_make_internal(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Make Internal";
+ ot->idname= "TEXT_OT_make_internal";
+
+ /* api callbacks */
+ ot->exec= make_internal_exec;
+ ot->poll= text_edit_poll;
+}
+
+/******************* save operator *********************/
+
+static int save_poll(bContext *C)
+{
+ Text *text= CTX_data_edit_text(C);
+
+ if(!text_edit_poll(C))
+ return 0;
+
+ return (text->name != NULL && !(text->flags & TXT_ISMEM));
+}
+
+static void txt_write_file(Text *text, ReportList *reports)
+{
+ FILE *fp;
+ TextLine *tmp;
+ struct stat st;
+ int res;
+ char file[FILE_MAXDIR+FILE_MAXFILE];
+
+ BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE);
+ BLI_convertstringcode(file, G.sce);
+
+ fp= fopen(file, "w");
+ if(fp==NULL) {
+ BKE_report(reports, RPT_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);
+
+ res= stat(file, &st);
+ text->mtime= st.st_mtime;
+
+ if(text->flags & TXT_ISDIRTY)
+ text->flags ^= TXT_ISDIRTY;
+}
+
+static int save_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+
+ txt_write_file(text, op->reports);
+
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_save(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Save";
+ ot->idname= "TEXT_OT_save";
+
+ /* api callbacks */
+ ot->exec= save_exec;
+ ot->poll= save_poll;
+}
+
+/******************* save as operator *********************/
+
+static int save_as_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+ char str[FILE_MAX];
+
+ if(!text)
+ return OPERATOR_CANCELLED;
+
+ RNA_string_get(op->ptr, "filename", str);
+
+ if(text->name) MEM_freeN(text->name);
+ text->name= BLI_strdup(str);
+ text->flags &= ~TXT_ISMEM;
+
+ txt_write_file(text, op->reports);
+
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+static int save_as_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Text *text= CTX_data_edit_text(C);
+ char *str;
+
+ if(RNA_property_is_set(op->ptr, "filename"))
+ return save_as_exec(C, op);
+
+ if(text->name)
+ str= text->name;
+ else if(text->flags & TXT_ISMEM)
+ str= text->id.name+2;
+ else
+ str= G.sce;
+
+ RNA_string_set(op->ptr, "filename", str);
+ WM_event_add_fileselect(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void TEXT_OT_save_as(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Save As";
+ ot->idname= "TEXT_OT_save_as";
+
+ /* api callbacks */
+ ot->exec= save_as_exec;
+ ot->invoke= save_as_invoke;
+ ot->poll= text_edit_poll;
+
+ /* properties */
+ RNA_def_string_file_path(ot->srna, "filename", "", FILE_MAX, "Filename", "File path to save image to.");
+}
+
+/******************* run script operator *********************/
+
+static int run_script_exec(bContext *C, wmOperator *op)
+{
+#ifdef DISABLE_PYTHON
+ BKE_report(op->reports, RPT_ERROR, "Python disabled in this build");
+
+ return OPERATOR_CANCELLED;
+#else
+ Text *text= CTX_data_edit_text(C);
+
+ if (BPY_run_python_script( C, NULL, text ))
+ return OPERATOR_FINISHED;
+
+ BKE_report(op->reports, RPT_ERROR, "Python script fail, look in the console for now...");
+ return OPERATOR_CANCELLED;
+#endif
+}
+
+void TEXT_OT_run_script(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Run Script";
+ ot->idname= "TEXT_OT_run_script";
+
+ /* api callbacks */
+ ot->exec= run_script_exec;
+ ot->poll= text_edit_poll;
+}
+
+
+/******************* refresh pyconstraints operator *********************/
+
+static int refresh_pyconstraints_exec(bContext *C, wmOperator *op)
+{
+#ifndef DISABLE_PYTHON
+ Text *text= CTX_data_edit_text(C);
+ Scene *scene= CTX_data_scene(C);
+ Object *ob;
+ bConstraint *con;
+ short update;
+
+ /* check all pyconstraints */
+ for(ob= CTX_data_main(C)->object.first; ob; ob= ob->id.next) {
+ update = 0;
+ if(ob->type==OB_ARMATURE && ob->pose) {
+ bPoseChannel *pchan;
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ for(con = pchan->constraints.first; con; con= con->next) {
+ if(con->type==CONSTRAINT_TYPE_PYTHON) {
+ bPythonConstraint *data = con->data;
+ if(data->text==text) BPY_pyconstraint_update(ob, con);
+ update = 1;
+
+ }
+ }
+ }
+ }
+ for(con = ob->constraints.first; con; con= con->next) {
+ if(con->type==CONSTRAINT_TYPE_PYTHON) {
+ bPythonConstraint *data = con->data;
+ if(data->text==text) BPY_pyconstraint_update(ob, con);
+ update = 1;
+ }
+ }
+
+ if(update) {
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+ }
+#endif
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_refresh_pyconstraints(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Refresh PyConstraints";
+ ot->idname= "TEXT_OT_refresh_pyconstraints";
+
+ /* api callbacks */
+ ot->exec= refresh_pyconstraints_exec;
+ ot->poll= text_edit_poll;
+}
+
+/******************* paste operator *********************/
+
+static char *txt_copy_selected(Text *text)
+{
+ TextLine *tmp, *linef, *linel;
+ char *buf= NULL;
+ int charf, charl, length= 0;
+
+ if(!text) return NULL;
+ if(!text->curl) return NULL;
+ if(!text->sell) return NULL;
+
+ if(!txt_has_sel(text)) 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_callocN(length+1, "cut buffera");
+
+ 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_callocN(length+1, "cut bufferb");
+
+ 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;
+}
+
+static int paste_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+ char *buf;
+ int selection= RNA_boolean_get(op->ptr, "selection");
+
+ buf= WM_clipboard_text_get(selection);
+
+ if(!buf)
+ return OPERATOR_CANCELLED;
+
+ txt_insert_buf(text, buf);
+ text_update_edited(text);
+
+ MEM_freeN(buf);
+
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_paste(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Paste";
+ ot->idname= "TEXT_OT_paste";
+
+ /* api callbacks */
+ ot->exec= paste_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "selection", 0, "Selection", "Paste text selected elsewhere rather than copied, X11 only.");
+}
+
+/******************* copy operator *********************/
+
+static void txt_copy_clipboard(Text *text)
+{
+ char *buf;
+
+ buf= txt_copy_selected(text);
+
+ if(buf) {
+ WM_clipboard_text_set(buf, 0);
+ MEM_freeN(buf);
+ }
+}
+
+static int copy_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+
+ txt_copy_clipboard(text);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_copy(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Copy";
+ ot->idname= "TEXT_OT_copy";
+
+ /* api callbacks */
+ ot->exec= copy_exec;
+ ot->poll= text_edit_poll;
+}
+
+/******************* cut operator *********************/
+
+static int cut_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+
+ txt_copy_clipboard(text);
+ txt_delete_selected(text);
+
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_cut(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Cut";
+ ot->idname= "TEXT_OT_cut";
+
+ /* api callbacks */
+ ot->exec= cut_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+/******************* indent operator *********************/
+
+static int indent_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+
+ if(txt_has_sel(text)) {
+ txt_order_cursors(text);
+ indent(text);
+ }
+ else
+ txt_add_char(text, '\t');
+
+ text_update_edited(text);
+
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_indent(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Indent";
+ ot->idname= "TEXT_OT_indent";
+
+ /* api callbacks */
+ ot->exec= indent_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+/******************* unindent operator *********************/
+
+static int unindent_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+
+ if(txt_has_sel(text)) {
+ txt_order_cursors(text);
+ unindent(text);
+
+ text_update_edited(text);
+
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void TEXT_OT_unindent(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Unindent";
+ ot->idname= "TEXT_OT_unindent";
+
+ /* api callbacks */
+ ot->exec= unindent_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+/******************* line break operator *********************/
+
+static int line_break_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+ int a, curtab;
+
+ // double check tabs before splitting the line
+ curtab= setcurr_tab(text);
+ txt_split_curline(text);
+
+ for(a=0; a < curtab; a++)
+ txt_add_char(text, '\t');
+
+ if(text->curl) {
+ if(text->curl->prev)
+ text_update_line_edited(text, text->curl->prev);
+ text_update_line_edited(text, text->curl);
+ }
+
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_CANCELLED;
+}
+
+void TEXT_OT_line_break(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Line Break";
+ ot->idname= "TEXT_OT_line_break";
+
+ /* api callbacks */
+ ot->exec= line_break_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+/******************* comment operator *********************/
+
+static int comment_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+
+ if(txt_has_sel(text)) {
+ txt_order_cursors(text);
+ comment(text);
+ text_update_edited(text);
+
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void TEXT_OT_comment(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Comment";
+ ot->idname= "TEXT_OT_comment";
+
+ /* api callbacks */
+ ot->exec= comment_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+/******************* uncomment operator *********************/
+
+static int uncomment_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+
+ if(txt_has_sel(text)) {
+ txt_order_cursors(text);
+ uncomment(text);
+ text_update_edited(text);
+
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void TEXT_OT_uncomment(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Uncomment";
+ ot->idname= "TEXT_OT_uncomment";
+
+ /* api callbacks */
+ ot->exec= uncomment_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+/******************* convert whitespace operator *********************/
+
+enum { TO_SPACES, TO_TABS };
+static EnumPropertyItem whitespace_type_items[]= {
+ {TO_SPACES, "SPACES", "To Spaces", NULL},
+ {TO_TABS, "TABS", "To Tabs", NULL},
+ {0, NULL, NULL, NULL}};
+
+static int convert_whitespace_exec(bContext *C, wmOperator *op)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ Text *text= CTX_data_edit_text(C);
+ TextLine *tmp;
+ FlattenString fs;
+ size_t a, j;
+ char *text_check_line, *new_line;
+ int extra, number; //unknown for now
+ int type= RNA_enum_get(op->ptr, "type");
+
+ tmp = text->lines.first;
+
+ //first convert to all space, this make it alot easier to convert to tabs because there is no mixtures of ' ' && '\t'
+ while(tmp) {
+ text_check_line = tmp->line;
+ number = flatten_string(st, &fs, text_check_line)+1;
+ flatten_string_free(&fs);
+ new_line = MEM_callocN(number, "Converted_Line");
+ j = 0;
+ for(a=0; a < strlen(text_check_line); a++) { //foreach char in line
+ if(text_check_line[a] == '\t') { //checking for tabs
+ //get the number of spaces this tabs is showing
+ //i dont like doing it this way but will look into it later
+ new_line[j] = '\0';
+ number = flatten_string(st, &fs, new_line);
+ flatten_string_free(&fs);
+ new_line[j] = '\t';
+ new_line[j+1] = '\0';
+ number = flatten_string(st, &fs, new_line)-number;
+ flatten_string_free(&fs);
+
+ for(extra = 0; extra < number; extra++) {
+ new_line[j] = ' ';
+ j++;
+ }
+ }
+ else {
+ new_line[j] = text_check_line[a];
+ ++j;
+ }
+ }
+ new_line[j] = '\0';
+ // put new_line in the tmp->line spot still need to try and set the curc correctly
+ if(tmp->line) MEM_freeN(tmp->line);
+ if(tmp->format) MEM_freeN(tmp->format);
+
+ tmp->line = new_line;
+ tmp->len = strlen(new_line);
+ tmp->format = NULL;
+ tmp = tmp->next;
+ }
+
+ if(type == TO_TABS) // Converting to tabs
+ { //start over from the begining
+ tmp = text->lines.first;
+
+ while(tmp) {
+ text_check_line = tmp->line;
+ extra = 0;
+ for(a = 0; a < strlen(text_check_line); a++) {
+ number = 0;
+ for(j = 0; j < (size_t)st->tabnumber; j++) {
+ if((a+j) <= strlen(text_check_line)) { //check to make sure we are not pass the end of the line
+ if(text_check_line[a+j] != ' ') {
+ number = 1;
+ }
+ }
+ }
+ if(!number) { //found all number of space to equal a tab
+ a = a+(st->tabnumber-1);
+ extra = extra+1;
+ }
+ }
+
+ if( extra > 0 ) { //got tabs make malloc and do what you have to do
+ new_line = MEM_callocN(strlen(text_check_line)-(((st->tabnumber*extra)-extra)-1), "Converted_Line");
+ extra = 0; //reuse vars
+ for(a = 0; a < strlen(text_check_line); a++) {
+ number = 0;
+ for(j = 0; j < (size_t)st->tabnumber; j++) {
+ if((a+j) <= strlen(text_check_line)) { //check to make sure we are not pass the end of the line
+ if(text_check_line[a+j] != ' ') {
+ number = 1;
+ }
+ }
+ }
+
+ if(!number) { //found all number of space to equal a tab
+ new_line[extra] = '\t';
+ a = a+(st->tabnumber-1);
+ ++extra;
+
+ }
+ else { //not adding a tab
+ new_line[extra] = text_check_line[a];
+ ++extra;
+ }
+ }
+ new_line[extra] = '\0';
+ // put new_line in the tmp->line spot still need to try and set the curc correctly
+ if(tmp->line) MEM_freeN(tmp->line);
+ if(tmp->format) MEM_freeN(tmp->format);
+
+ tmp->line = new_line;
+ tmp->len = strlen(new_line);
+ tmp->format = NULL;
+ }
+ tmp = tmp->next;
+ }
+ }
+
+ text_update_edited(text);
+
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_convert_whitespace(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Convert Whitespace";
+ ot->idname= "TEXT_OT_convert_whitespace";
+
+ /* api callbacks */
+ ot->exec= convert_whitespace_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", whitespace_type_items, TO_SPACES, "type", "Type of whitespace to convert to.");
+}
+
+/******************* select all operator *********************/
+
+static int select_all_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+
+ txt_sel_all(text);
+
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_select_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select All";
+ ot->idname= "TEXT_OT_select_all";
+
+ /* api callbacks */
+ ot->exec= select_all_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+/******************* select line operator *********************/
+
+static int select_line_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+
+ txt_sel_line(text);
+
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_select_line(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Line";
+ ot->idname= "TEXT_OT_select_line";
+
+ /* api clinebacks */
+ ot->exec= select_line_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+/******************* previous marker operator *********************/
+
+static int previous_marker_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+ TextMarker *mrk;
+ int lineno;
+
+ lineno= txt_get_span(text->lines.first, text->curl);
+ mrk= text->markers.last;
+ while(mrk && (mrk->lineno>lineno || (mrk->lineno==lineno && mrk->end > text->curc)))
+ mrk= mrk->prev;
+ if(!mrk) mrk= text->markers.last;
+ if(mrk) {
+ txt_move_to(text, mrk->lineno, mrk->start, 0);
+ txt_move_to(text, mrk->lineno, mrk->end, 1);
+ }
+
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_previous_marker(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Previous Marker";
+ ot->idname= "TEXT_OT_previous_marker";
+
+ /* api callbacks */
+ ot->exec= previous_marker_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+/******************* next marker operator *********************/
+
+static int next_marker_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+ TextMarker *mrk;
+ int lineno;
+
+ lineno= txt_get_span(text->lines.first, text->curl);
+ mrk= text->markers.first;
+ while(mrk && (mrk->lineno<lineno || (mrk->lineno==lineno && mrk->start <= text->curc)))
+ mrk= mrk->next;
+ if(!mrk) mrk= text->markers.first;
+ if(mrk) {
+ txt_move_to(text, mrk->lineno, mrk->start, 0);
+ txt_move_to(text, mrk->lineno, mrk->end, 1);
+ }
+
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_next_marker(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Next Marker";
+ ot->idname= "TEXT_OT_next_marker";
+
+ /* api callbacks */
+ ot->exec= next_marker_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+/******************* clear all markers operator *********************/
+
+static int clear_all_markers_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+
+ txt_clear_markers(text, 0, 0);
+
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_markers_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Clear All Markers";
+ ot->idname= "TEXT_OT_markers_clear";
+
+ /* api callbacks */
+ ot->exec= clear_all_markers_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+/************************ move operator ************************/
+
+static EnumPropertyItem move_type_items[]= {
+ {LINE_BEGIN, "LINE_BEGIN", "Line Begin", ""},
+ {LINE_END, "LINE_END", "Line End", ""},
+ {FILE_TOP, "FILE_TOP", "File Top", ""},
+ {FILE_BOTTOM, "FILE_BOTTOM", "File Bottom", ""},
+ {PREV_CHAR, "PREVIOUS_CHARACTER", "Previous Character", ""},
+ {NEXT_CHAR, "NEXT_CHARACTER", "Next Character", ""},
+ {PREV_WORD, "PREVIOUS_WORD", "Previous Word", ""},
+ {NEXT_WORD, "NEXT_WORD", "Next Word", ""},
+ {PREV_LINE, "PREVIOUS_LINE", "Previous Line", ""},
+ {NEXT_LINE, "NEXT_LINE", "Next Line", ""},
+ {PREV_PAGE, "PREVIOUS_PAGE", "Previous Page", ""},
+ {NEXT_PAGE, "NEXT_PAGE", "Next Page", ""},
+ {0, NULL, NULL, NULL}};
+
+static void wrap_move_bol(SpaceText *st, ARegion *ar, short sel)
+{
+ Text *text= st->text;
+ int offl, offc, lin;
+
+ lin= txt_get_span(text->lines.first, text->sell);
+ wrap_offset(st, ar, text->sell, text->selc, &offl, &offc);
+
+ if (sel) {
+ txt_undo_add_toop(text, UNDO_STO, lin, text->selc, lin, -offc);
+ text->selc= -offc;
+ } else {
+ txt_undo_add_toop(text, UNDO_CTO, lin, text->curc, lin, -offc);
+ text->curc= -offc;
+ txt_pop_sel(text);
+ }
+}
+
+static void wrap_move_eol(SpaceText *st, ARegion *ar, short sel)
+{
+ Text *text= st->text;
+ int offl, offc, lin, startl, c;
+
+ lin= txt_get_span(text->lines.first, text->sell);
+ wrap_offset(st, ar, text->sell, text->selc, &offl, &offc);
+ startl= offl;
+ c= text->selc;
+ while (offl==startl && text->sell->line[c]!='\0') {
+ c++;
+ wrap_offset(st, ar, text->sell, c, &offl, &offc);
+ } if (offl!=startl) c--;
+
+ if (sel) {
+ txt_undo_add_toop(text, UNDO_STO, lin, text->selc, lin, c);
+ text->selc= c;
+ } else {
+ txt_undo_add_toop(text, UNDO_CTO, lin, text->curc, lin, c);
+ text->curc= c;
+ txt_pop_sel(text);
+ }
+}
+
+static void wrap_move_up(SpaceText *st, ARegion *ar, short sel)
+{
+ Text *text= st->text;
+ int offl, offl_1, offc, fromline, toline, c, target;
+
+ wrap_offset(st, ar, text->sell, 0, &offl_1, &offc);
+ wrap_offset(st, ar, text->sell, text->selc, &offl, &offc);
+ fromline= toline= txt_get_span(text->lines.first, text->sell);
+ target= text->selc + offc;
+
+ if (offl==offl_1) {
+ if (!text->sell->prev) {
+ txt_move_bol(text, sel);
+ return;
+ }
+ toline--;
+ c= text->sell->prev->len; /* End of prev. line */
+ wrap_offset(st, ar, text->sell->prev, c, &offl, &offc);
+ c= -offc+target;
+ } else {
+ c= -offc-1; /* End of prev. line */
+ wrap_offset(st, ar, text->sell, c, &offl, &offc);
+ c= -offc+target;
+ }
+ if (c<0) c=0;
+
+ if (sel) {
+ txt_undo_add_toop(text, UNDO_STO, fromline, text->selc, toline, c);
+ if (toline<fromline) text->sell= text->sell->prev;
+ if(text->sell) {
+ if (c>text->sell->len) c= text->sell->len;
+ text->selc= c;
+ }
+ }
+ else if(text->curl) {
+ txt_undo_add_toop(text, UNDO_CTO, fromline, text->curc, toline, c);
+ if (toline<fromline) text->curl= text->curl->prev;
+ if(text->curl) {
+ if (c>text->curl->len) c= text->curl->len;
+ text->curc= c;
+ txt_pop_sel(text);
+ }
+ }
+}
+
+static void wrap_move_down(SpaceText *st, ARegion *ar, short sel)
+{
+ Text *text= st->text;
+ int offl, startoff, offc, fromline, toline, c, target;
+
+ wrap_offset(st, ar, text->sell, text->selc, &offl, &offc);
+ fromline= toline= txt_get_span(text->lines.first, text->sell);
+ target= text->selc + offc;
+ startoff= offl;
+ c= text->selc;
+ while (offl==startoff && text->sell->line[c]!='\0') {
+ c++;
+ wrap_offset(st, ar, text->sell, c, &offl, &offc);
+ }
+
+ if (text->sell->line[c]=='\0') {
+ if (!text->sell->next) {
+ txt_move_eol(text, sel);
+ return;
+ }
+ toline++;
+ c= target;
+ } else {
+ c += target;
+ if (c > text->sell->len) c= text->sell->len;
+ }
+ if (c<0) c=0;
+
+ if (sel) {
+ txt_undo_add_toop(text, UNDO_STO, fromline, text->selc, toline, c);
+ if (toline>fromline) text->sell= text->sell->next;
+ if(text->sell) {
+ if (c>text->sell->len) c= text->sell->len;
+ text->selc= c;
+ }
+ }
+ else if(text->curl) {
+ txt_undo_add_toop(text, UNDO_CTO, fromline, text->curc, toline, c);
+ if (toline>fromline) text->curl= text->curl->next;
+ if(text->curl) {
+ if (c > text->curl->len) c= text->curl->len;
+ text->curc= c;
+ txt_pop_sel(text);
+ }
+ }
+}
+
+/* Moves the cursor vertically by the specified number of lines.
+ If the destination line is shorter than the current cursor position, the
+ cursor will be positioned at the end of this line.
+
+ This is to replace screen_skip for PageUp/Down operations.
+ */
+static void cursor_skip(Text *text, int lines, int sel)
+{
+ TextLine **linep;
+ int oldl, oldc, *charp;
+
+ if (sel) linep= &text->sell, charp= &text->selc;
+ else linep= &text->curl, charp= &text->curc;
+ oldl= txt_get_span(text->lines.first, *linep);
+ oldc= *charp;
+
+ while (lines>0 && (*linep)->next) {
+ *linep= (*linep)->next;
+ lines--;
+ }
+ while (lines<0 && (*linep)->prev) {
+ *linep= (*linep)->prev;
+ lines++;
+ }
+
+ if (*charp > (*linep)->len) *charp= (*linep)->len;
+
+ if (!sel) txt_pop_sel(text);
+ txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, oldl, oldc, txt_get_span(text->lines.first, *linep), *charp);
+}
+
+static int move_cursor(bContext *C, int type, int select)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ Text *text= CTX_data_edit_text(C);
+ ARegion *ar= CTX_wm_region(C);
+
+ /* ensure we have the right region, it's optional */
+ if(ar->regiontype != RGN_TYPE_WINDOW)
+ ar= NULL;
+
+ switch(type) {
+ case LINE_BEGIN:
+ if(st && st->wordwrap && ar) wrap_move_bol(st, ar, select);
+ else txt_move_bol(text, select);
+ break;
+
+ case LINE_END:
+ if(st && st->wordwrap && ar) wrap_move_eol(st, ar, select);
+ else txt_move_eol(text, select);
+ break;
+
+ case FILE_TOP:
+ txt_move_bof(text, select);
+ break;
+
+ case FILE_BOTTOM:
+ txt_move_eof(text, select);
+ break;
+
+ case PREV_WORD:
+ txt_jump_left(text, select);
+ break;
+
+ case NEXT_WORD:
+ txt_jump_right(text, select);
+ break;
+
+ case PREV_CHAR:
+ txt_move_left(text, select);
+ break;
+
+ case NEXT_CHAR:
+ txt_move_right(text, select);
+ break;
+
+ case PREV_LINE:
+ if(st && st->wordwrap && ar) wrap_move_up(st, ar, select);
+ else txt_move_up(text, select);
+ break;
+
+ case NEXT_LINE:
+ if(st && st->wordwrap && ar) wrap_move_down(st, ar, select);
+ else txt_move_down(text, select);
+ break;
+
+ case PREV_PAGE:
+ if(st) cursor_skip(text, -st->viewlines, select);
+ else cursor_skip(text, -10, select);
+ break;
+
+ case NEXT_PAGE:
+ if(st) cursor_skip(text, st->viewlines, select);
+ else cursor_skip(text, 10, select);
+ break;
+ }
+
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+static int move_exec(bContext *C, wmOperator *op)
+{
+ int type= RNA_enum_get(op->ptr, "type");
+
+ return move_cursor(C, type, 0);
+}
+
+void TEXT_OT_move(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Move Cursor";
+ ot->idname= "TEXT_OT_move";
+
+ /* api callbacks */
+ ot->exec= move_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to.");
+}
+
+/******************* move select operator ********************/
+
+static int move_select_exec(bContext *C, wmOperator *op)
+{
+ int type= RNA_enum_get(op->ptr, "type");
+
+ return move_cursor(C, type, 1);
+}
+
+void TEXT_OT_move_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Move Select";
+ ot->idname= "TEXT_OT_move_select";
+
+ /* api callbacks */
+ ot->exec= move_select_exec;
+ ot->poll= text_space_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to, to make a selection.");
+}
+
+/******************* jump operator *********************/
+
+static int jump_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+ int line= RNA_int_get(op->ptr, "line");
+ short nlines= txt_get_span(text->lines.first, text->lines.last)+1;
+
+ if(line < 1 || line > nlines)
+ return OPERATOR_CANCELLED;
+
+ txt_move_toline(text, line-1, 0);
+
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
+
+ return OPERATOR_FINISHED;
+}
+
+// XXX invoke
+// short tmp= txt_get_span(text->lines.first, text->curl)+1;
+// button(&tmp, 1, nlines, "Jump to line:"))
+
+void TEXT_OT_jump(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Jump";
+ ot->idname= "TEXT_OT_jump";
+
+ /* api callbacks */
+ ot->exec= jump_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_int(ot->srna, "line", 1, INT_MAX, 1, "Line", "Line number to jump to.", 1, 10000);
+}
+
+/******************* delete operator **********************/
+
+static EnumPropertyItem delete_type_items[]= {
+ {DEL_NEXT_CHAR, "NEXT_CHARACTER", "Next Character", ""},
+ {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", "Previous Character", ""},
+ {DEL_NEXT_WORD, "NEXT_WORD", "Next Word", ""},
+ {DEL_PREV_WORD, "PREVIOUS_WORD", "Previous Word", ""},
+ {0, NULL, NULL, NULL}};
+
+static int delete_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+ int type= RNA_enum_get(op->ptr, "type");
+
+ if(type == DEL_PREV_WORD)
+ txt_backspace_word(text);
+ else if(type == DEL_PREV_CHAR)
+ txt_backspace_char(text);
+ else if(type == DEL_NEXT_WORD)
+ txt_delete_word(text);
+ else if(type == DEL_NEXT_CHAR)
+ txt_delete_char(text);
+
+ text_update_line_edited(text, text->curl);
+
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete";
+ ot->idname= "TEXT_OT_delete";
+
+ /* api callbacks */
+ ot->exec= delete_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", delete_type_items, DEL_NEXT_CHAR, "Type", "Which part of the text to delete.");
+}
+
+/******************* toggle overwrite operator **********************/
+
+static int toggle_overwrite_exec(bContext *C, wmOperator *op)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+
+ st->overwrite= !st->overwrite;
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_overwrite_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Toggle Overwrite";
+ ot->idname= "TEXT_OT_overwrite_toggle";
+
+ /* api callbacks */
+ ot->exec= toggle_overwrite_exec;
+ ot->poll= text_space_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+/******************* scroll operator **********************/
+
+/* Moves the view vertically by the specified number of lines */
+static void screen_skip(SpaceText *st, int lines)
+{
+ int last;
+
+ 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;
+}
+
+typedef struct TextScroll {
+ short old[2];
+ short hold[2];
+ short delta[2];
+
+ int first;
+ int characters;
+ int lines;
+ int scrollbar;
+} TextScroll;
+
+static int scroll_exec(bContext *C, wmOperator *op)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ int lines= RNA_int_get(op->ptr, "lines");
+
+ if(lines == 0)
+ return OPERATOR_CANCELLED;
+
+ screen_skip(st, lines*U.wheellinescroll);
+
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, st->text);
+
+ return OPERATOR_FINISHED;
+}
+
+static int scroll_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ TextScroll *tsc;
+
+ if(RNA_property_is_set(op->ptr, "lines"))
+ return scroll_exec(C, op);
+
+ tsc= MEM_callocN(sizeof(TextScroll), "TextScroll");
+ tsc->first= 1;
+ op->customdata= tsc;
+
+ st->flags|= ST_SCROLL_SELECT;
+
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void scroll_apply(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ TextScroll *tsc= op->customdata;
+ short *mval= event->mval;
+
+ if(tsc->first) {
+ tsc->old[0]= mval[0];
+ tsc->old[1]= mval[1];
+ tsc->hold[0]= mval[0];
+ tsc->hold[1]= mval[1];
+ tsc->first= 0;
+ }
+
+ if(!tsc->scrollbar) {
+ tsc->delta[0]= (tsc->hold[0]-mval[0])/text_font_width_character(st);
+ tsc->delta[1]= (mval[1]-tsc->hold[1])/st->lheight;
+ }
+ else
+ tsc->delta[1]= (tsc->hold[1]-mval[1])*st->pix_per_line;
+
+ if(tsc->delta[0] || tsc->delta[1]) {
+ screen_skip(st, tsc->delta[1]);
+
+ tsc->lines += tsc->delta[1];
+
+ if(st->wordwrap) {
+ st->left= 0;
+ }
+ else {
+ st->left+= tsc->delta[0];
+ if(st->left<0) st->left= 0;
+ }
+
+ tsc->hold[0]= mval[0];
+ tsc->hold[1]= mval[1];
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ tsc->old[0]= mval[0];
+ tsc->old[1]= mval[1];
+}
+
+static void scroll_exit(bContext *C, wmOperator *op)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+
+ st->flags &= ~ST_SCROLL_SELECT;
+ MEM_freeN(op->customdata);
+}
+
+static int scroll_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ switch(event->type) {
+ case MOUSEMOVE:
+ scroll_apply(C, op, event);
+ break;
+ case LEFTMOUSE:
+ case RIGHTMOUSE:
+ case MIDDLEMOUSE:
+ scroll_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int scroll_cancel(bContext *C, wmOperator *op)
+{
+ scroll_exit(C, op);
+
+ return OPERATOR_CANCELLED;
+}
+
+void TEXT_OT_scroll(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Scroll";
+ ot->idname= "TEXT_OT_scroll";
+
+ /* api callbacks */
+ ot->exec= scroll_exec;
+ ot->invoke= scroll_invoke;
+ ot->modal= scroll_modal;
+ ot->cancel= scroll_cancel;
+ ot->poll= text_space_edit_poll;
+
+ /* properties */
+ RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll.", -100, 100);
+}
+
+/******************** scroll bar operator *******************/
+
+static int scroll_bar_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ ARegion *ar= CTX_wm_region(C);
+ TextScroll *tsc;
+ short *mval= event->mval;
+
+ if(RNA_property_is_set(op->ptr, "lines"))
+ return scroll_exec(C, op);
+
+ /* verify we are in the right zone */
+ if(!(mval[0]>2 && mval[0]<20 && mval[1]>2 && mval[1]<ar->winy))
+ return OPERATOR_PASS_THROUGH;
+
+ tsc= MEM_callocN(sizeof(TextScroll), "TextScroll");
+ tsc->first= 1;
+ tsc->scrollbar= 1;
+ op->customdata= tsc;
+
+ st->flags|= ST_SCROLL_SELECT;
+
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void TEXT_OT_scroll_bar(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Scrollbar";
+ ot->idname= "TEXT_OT_scroll_bar";
+
+ /* api callbacks */
+ ot->invoke= scroll_bar_invoke;
+ ot->modal= scroll_modal;
+ ot->cancel= scroll_cancel;
+ ot->poll= text_region_edit_poll;
+
+ /* properties */
+ RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll.", -100, 100);
+}
+
+/******************* set cursor operator **********************/
+
+typedef struct SetCursor {
+ int selecting;
+ int selc, sell;
+ short old[2];
+} SetCursor;
+
+static void set_cursor_to_pos(SpaceText *st, ARegion *ar, int x, int y, int sel)
+{
+ FlattenString fs;
+ Text *text= st->text;
+ TextLine **linep;
+ int *charp;
+ int w;
+
+ if(sel) { linep= &text->sell; charp= &text->selc; }
+ else { linep= &text->curl; charp= &text->curc; }
+
+ y= (ar->winy - y)/st->lheight;
+
+ if(st->showlinenrs)
+ x-= TXT_OFFSET+TEXTXLOC;
+ else
+ x-= TXT_OFFSET;
+
+ if(x<0) x= 0;
+ x = (x/text_font_width_character(st)) + st->left;
+
+ if(st->wordwrap) {
+ int i, j, endj, curs, max, chop, start, end, chars, loop;
+ char ch;
+
+ /* Point to first visible line */
+ *linep= text->lines.first;
+ for(i=0; i<st->top && (*linep)->next; i++) *linep= (*linep)->next;
+
+ max= wrap_width(st, ar);
+
+ loop= 1;
+ while(loop && *linep) {
+ start= 0;
+ end= max;
+ chop= 1;
+ chars= 0;
+ curs= 0;
+ endj= 0;
+ for(i=0, j=0; loop; j++) {
+
+ /* Mimic replacement of tabs */
+ ch= (*linep)->line[j];
+ if(ch=='\t') {
+ chars= st->tabnumber-i%st->tabnumber;
+ ch= ' ';
+ }
+ else
+ chars= 1;
+
+ while(chars--) {
+ /* Gone too far, go back to last wrap point */
+ if(y<0) {
+ *charp= endj;
+ loop= 0;
+ break;
+ /* Exactly at the cursor, done */
+ }
+ else if(y==0 && i-start==x) {
+ *charp= curs= j;
+ loop= 0;
+ break;
+ /* Prepare curs for next wrap */
+ }
+ else if(i-end==x) {
+ curs= j;
+ }
+ if(i-start>=max) {
+ if(chop) endj= j;
+ y--;
+ start= end;
+ end += max;
+ chop= 1;
+ if(y==0 && i-start>=x) {
+ *charp= curs;
+ loop= 0;
+ break;
+ }
+ }
+ else if(ch==' ' || ch=='-' || ch=='\0') {
+ if(y==0 && i-start>=x) {
+ *charp= curs;
+ loop= 0;
+ break;
+ }
+ end = i+1;
+ endj = j;
+ chop= 0;
+ }
+ i++;
+ }
+ if(ch=='\0') break;
+ }
+ if(!loop || y<0) break;
+
+ if(!(*linep)->next) {
+ *charp= (*linep)->len;
+ break;
+ }
+
+ /* On correct line but didn't meet cursor, must be at end */
+ if(y==0) {
+ *charp= (*linep)->len;
+ break;
+ }
+ *linep= (*linep)->next;
+ y--;
+ }
+
+ }
+ else {
+ 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;
+ }
+
+
+ w= flatten_string(st, &fs, (*linep)->line);
+ if(x<w) *charp= fs.accum[x];
+ else *charp= (*linep)->len;
+ flatten_string_free(&fs);
+ }
+ if(!sel) txt_pop_sel(text);
+}
+
+static void set_cursor_apply(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ ARegion *ar= CTX_wm_region(C);
+ SetCursor *scu= op->customdata;
+
+ if(event->mval[1]<0 || event->mval[1]>ar->winy) {
+ int d= (scu->old[1]-event->mval[1])*st->pix_per_line;
+ if(d) screen_skip(st, d);
+
+ set_cursor_to_pos(st, ar, event->mval[0], event->mval[1]<0?0:ar->winy, 1);
+
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, st->text);
+ }
+ else if(!st->wordwrap && (event->mval[0]<0 || event->mval[0]>ar->winx)) {
+ if(event->mval[0]>ar->winx) st->left++;
+ else if(event->mval[0]<0 && st->left>0) st->left--;
+
+ set_cursor_to_pos(st, ar, event->mval[0], event->mval[1], 1);
+
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, st->text);
+ // XXX PIL_sleep_ms(10);
+ }
+ else {
+ set_cursor_to_pos(st, ar, event->mval[0], event->mval[1], 1);
+
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, st->text);
+
+ scu->old[0]= event->mval[0];
+ scu->old[1]= event->mval[1];
+ }
+}
+
+static void set_cursor_exit(bContext *C, wmOperator *op)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ Text *text= st->text;
+ SetCursor *scu= op->customdata;
+ int linep2, charp2;
+ char *buffer;
+
+ if(txt_has_sel(text)) {
+ buffer = txt_sel_to_buf(text);
+ WM_clipboard_text_set(buffer, 1);
+ MEM_freeN(buffer);
+ }
+
+ linep2= txt_get_span(st->text->lines.first, st->text->sell);
+ charp2= st->text->selc;
+
+ if(scu->sell!=linep2 || scu->selc!=charp2)
+ txt_undo_add_toop(st->text, UNDO_STO, scu->sell, scu->selc, linep2, charp2);
+
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, st->text);
+
+ MEM_freeN(scu);
+}
+
+static int set_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ ARegion *ar= CTX_wm_region(C);
+ SetCursor *scu;
+
+ op->customdata= MEM_callocN(sizeof(SetCursor), "SetCursor");
+ scu= op->customdata;
+ scu->selecting= RNA_boolean_get(op->ptr, "select");
+
+ scu->old[0]= event->mval[0];
+ scu->old[1]= event->mval[1];
+
+ if(!scu->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, ar, event->mval[0], event->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);
+ }
+
+ scu->sell= txt_get_span(st->text->lines.first, st->text->sell);
+ scu->selc= st->text->selc;
+
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ set_cursor_apply(C, op, event);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int set_cursor_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ switch(event->type) {
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE:
+ set_cursor_exit(C, op);
+ return OPERATOR_FINISHED;
+ case MOUSEMOVE:
+ set_cursor_apply(C, op, event);
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int set_cursor_cancel(bContext *C, wmOperator *op)
+{
+ set_cursor_exit(C, op);
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_cursor_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Cursor";
+ ot->idname= "TEXT_OT_cursor_set";
+
+ /* api callbacks */
+ ot->invoke= set_cursor_invoke;
+ ot->modal= set_cursor_modal;
+ ot->cancel= set_cursor_cancel;
+ ot->poll= text_region_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "select", 0, "Select", "Set selection end rather than cursor.");
+}
+
+/******************* line number operator **********************/
+
+static int line_number_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ Text *text= CTX_data_edit_text(C);
+ ARegion *ar= CTX_wm_region(C);
+ short *mval= event->mval;
+ double time;
+ static int jump_to= 0;
+ static double last_jump= 0;
+
+ if(!st->showlinenrs)
+ return OPERATOR_PASS_THROUGH;
+
+ if(!(mval[0]>2 && mval[0]<60 && mval[1]>2 && mval[1]<ar->winy-2))
+ return OPERATOR_PASS_THROUGH;
+
+ if(!(event->ascii>='0' && event->ascii<='9'))
+ return OPERATOR_PASS_THROUGH;
+
+ time = PIL_check_seconds_timer();
+ if(last_jump < time-1)
+ jump_to= 0;
+
+ jump_to *= 10;
+ jump_to += (int)(event->ascii-'0');
+
+ txt_move_toline(text, jump_to-1, 0);
+ last_jump= time;
+
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_line_number(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Line Number";
+ ot->idname= "TEXT_OT_line_number";
+
+ /* api callbacks */
+ ot->invoke= line_number_invoke;
+ ot->poll= text_region_edit_poll;
+}
+
+/******************* insert operator **********************/
+
+static int insert_exec(bContext *C, wmOperator *op)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ Text *text= CTX_data_edit_text(C);
+ char *str;
+ int done, ascii;
+
+ str= RNA_string_get_alloc(op->ptr, "text", NULL, 0);
+ ascii= str[0];
+ MEM_freeN(str);
+
+ if(!ascii)
+ return OPERATOR_CANCELLED;
+
+ if(st && st->overwrite)
+ done= txt_replace_char(text, ascii);
+ else
+ done= txt_add_char(text, ascii);
+
+ if(!done)
+ return OPERATOR_CANCELLED;
+
+ text_update_line_edited(text, text->curl);
+
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+
+ return OPERATOR_FINISHED;
+}
+
+static int insert_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ char str[2];
+
+ /* XXX old code from winqreadtextspace, is it still needed somewhere? */
+ /* smartass code to prevent the CTRL/ALT events below from not working! */
+ /*if(qual & (LR_ALTKEY|LR_CTRLKEY))
+ if(!ispunct(ascii))
+ ascii= 0;*/
+
+ str[0]= event->ascii;
+ str[1]= '\0';
+
+ RNA_string_set(op->ptr, "text", str);
+
+ return insert_exec(C, op);
+}
+
+void TEXT_OT_insert(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Insert";
+ ot->idname= "TEXT_OT_insert";
+
+ /* api callbacks */
+ ot->exec= insert_exec;
+ ot->invoke= insert_invoke;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_string(ot->srna, "text", "", 0, "Text", "Text to insert at the cursor position.");
+}
+
+/******************* find operator *********************/
+
+/* mode */
+#define TEXT_FIND 0
+#define TEXT_REPLACE 1
+#define TEXT_MARK_ALL 2
+
+static int find_and_replace(bContext *C, wmOperator *op, short mode)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ Text *start= NULL, *text= st->text;
+ int flags, first= 1;
+ char *tmp;
+
+ if(!st->findstr[0] || (mode == TEXT_REPLACE && !st->replacestr[0]))
+ return OPERATOR_CANCELLED;
+
+ flags= st->flags;
+ if(flags & ST_FIND_ALL)
+ flags ^= ST_FIND_WRAP;
+
+ do {
+ if(first)
+ txt_clear_markers(text, TMARK_GRP_FINDALL, 0);
+
+ first= 0;
+
+ /* Replace current */
+ if(mode!=TEXT_FIND && txt_has_sel(text)) {
+ tmp= txt_sel_to_buf(text);
+
+ if(strcmp(st->findstr, tmp)==0) {
+ if(mode==TEXT_REPLACE) {
+ txt_insert_buf(text, st->replacestr);
+ if(text->curl && text->curl->format) {
+ MEM_freeN(text->curl->format);
+ text->curl->format= NULL;
+ }
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+ }
+ else if(mode==TEXT_MARK_ALL) {
+ char color[4];
+ UI_GetThemeColor4ubv(TH_SHADE2, color);
+
+ if(txt_find_marker(text, text->curl, text->selc, TMARK_GRP_FINDALL, 0)) {
+ if(tmp) MEM_freeN(tmp), tmp=NULL;
+ break;
+ }
+
+ txt_add_marker(text, text->curl, text->curc, text->selc, color, TMARK_GRP_FINDALL, TMARK_EDITALL);
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+ }
+ }
+ MEM_freeN(tmp);
+ tmp= NULL;
+ }
+
+ /* Find next */
+ if(txt_find_string(text, st->findstr, flags & ST_FIND_WRAP)) {
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
+ }
+ else if(flags & ST_FIND_ALL) {
+ if(text==start) break;
+ if(!start) start= text;
+ if(text->id.next)
+ text= st->text= text->id.next;
+ else
+ text= st->text= G.main->text.first;
+ txt_move_toline(text, 0, 0);
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
+ first= 1;
+ }
+ else {
+ BKE_reportf(op->reports, RPT_INFO, "Text not found: %s", st->findstr);
+ break;
+ }
+ } while(mode==TEXT_MARK_ALL);
+
+ return OPERATOR_FINISHED;
+}
+
+static int find_exec(bContext *C, wmOperator *op)
+{
+ return find_and_replace(C, op, TEXT_FIND);
+}
+
+void TEXT_OT_find(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Find";
+ ot->idname= "TEXT_OT_find";
+
+ /* api callbacks */
+ ot->exec= find_exec;
+ ot->poll= text_space_edit_poll;
+}
+
+/******************* replace operator *********************/
+
+static int replace_exec(bContext *C, wmOperator *op)
+{
+ return find_and_replace(C, op, TEXT_REPLACE);
+}
+
+void TEXT_OT_replace(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Replace";
+ ot->idname= "TEXT_OT_replace";
+
+ /* api callbacks */
+ ot->exec= replace_exec;
+ ot->poll= text_space_edit_poll;
+}
+
+/******************* mark all operator *********************/
+
+static int mark_all_exec(bContext *C, wmOperator *op)
+{
+ return find_and_replace(C, op, TEXT_MARK_ALL);
+}
+
+void TEXT_OT_mark_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mark All";
+ ot->idname= "TEXT_OT_mark_all";
+
+ /* api callbacks */
+ ot->exec= mark_all_exec;
+ ot->poll= text_space_edit_poll;
+}
+
+/******************* find set selected *********************/
+
+static int find_set_selected_exec(bContext *C, wmOperator *op)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ Text *text= CTX_data_edit_text(C);
+ char *tmp;
+
+ tmp= txt_sel_to_buf(text);
+ BLI_strncpy(st->findstr, tmp, ST_MAX_FIND_STR);
+ MEM_freeN(tmp);
+
+ if(!st->findstr[0])
+ return OPERATOR_FINISHED;
+
+ return find_and_replace(C, op, TEXT_FIND);
+}
+
+void TEXT_OT_find_set_selected(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Find Set Selected";
+ ot->idname= "TEXT_OT_find_set_selected";
+
+ /* api callbacks */
+ ot->exec= find_set_selected_exec;
+ ot->poll= text_space_edit_poll;
+}
+
+/******************* replace set selected *********************/
+
+static int replace_set_selected_exec(bContext *C, wmOperator *op)
+{
+ SpaceText *st= CTX_wm_space_text(C);
+ Text *text= CTX_data_edit_text(C);
+ char *tmp;
+
+ tmp= txt_sel_to_buf(text);
+ BLI_strncpy(st->replacestr, tmp, ST_MAX_FIND_STR);
+ MEM_freeN(tmp);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_replace_set_selected(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Replace Set Selected";
+ ot->idname= "TEXT_OT_replace_set_selected";
+
+ /* api callbacks */
+ ot->exec= replace_set_selected_exec;
+ ot->poll= text_space_edit_poll;
+}
+
+/****************** resolve conflict operator ******************/
+
+enum { RESOLVE_IGNORE, RESOLVE_RELOAD, RESOLVE_SAVE, RESOLVE_MAKE_INTERNAL };
+static EnumPropertyItem resolution_items[]= {
+ {RESOLVE_IGNORE, "IGNORE", "Ignore", ""},
+ {RESOLVE_RELOAD, "RELOAD", "Reload", ""},
+ {RESOLVE_SAVE, "SAVE", "Save", ""},
+ {RESOLVE_MAKE_INTERNAL, "MAKE_INTERNAL", "Make Internal", ""},
+ {0, NULL, NULL, NULL}};
+
+/* returns 0 if file on disk is the same or Text is in memory only
+ returns 1 if file has been modified on disk since last local edit
+ returns 2 if file on disk has been deleted
+ -1 is returned if an error occurs */
+
+int text_file_modified(Text *text)
+{
+ struct stat st;
+ int result;
+ char file[FILE_MAXDIR+FILE_MAXFILE];
+
+ if(!text || !text->name)
+ return 0;
+
+ BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE);
+ BLI_convertstringcode(file, G.sce);
+
+ if(!BLI_exists(file))
+ return 2;
+
+ result = stat(file, &st);
+
+ if(result == -1)
+ return -1;
+
+ if((st.st_mode & S_IFMT) != S_IFREG)
+ return -1;
+
+ if(st.st_mtime > text->mtime)
+ return 1;
+
+ return 0;
+}
+
+static void text_ignore_modified(Text *text)
+{
+ struct stat st;
+ int result;
+ char file[FILE_MAXDIR+FILE_MAXFILE];
+
+ if(!text || !text->name) return;
+
+ BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE);
+ BLI_convertstringcode(file, G.sce);
+
+ if(!BLI_exists(file)) return;
+
+ result = stat(file, &st);
+
+ if(result == -1 || (st.st_mode & S_IFMT) != S_IFREG)
+ return;
+
+ text->mtime= st.st_mtime;
+}
+
+static int resolve_conflict_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+ int resolution= RNA_enum_get(op->ptr, "resolution");
+
+ switch(resolution) {
+ case RESOLVE_RELOAD:
+ return reload_exec(C, op);
+ case RESOLVE_SAVE:
+ return save_exec(C, op);
+ case RESOLVE_MAKE_INTERNAL:
+ return make_internal_exec(C, op);
+ case RESOLVE_IGNORE:
+ text_ignore_modified(text);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+static int resolve_conflict_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Text *text= CTX_data_edit_text(C);
+ uiMenuItem *head;
+
+ switch(text_file_modified(text)) {
+ case 1:
+ if(text->flags & TXT_ISDIRTY) {
+ /* modified locally and externally, ahhh. offer more possibilites. */
+ head= uiPupMenuBegin("File Modified Outside and Inside Blender", 0);
+ uiMenuItemEnumO(head, "Reload from disk (ignore local changes)", 0, op->type->idname, "resolution", RESOLVE_RELOAD);
+ uiMenuItemEnumO(head, "Save to disk (ignore outside changes)", 0, op->type->idname, "resolution", RESOLVE_SAVE);
+ uiMenuItemEnumO(head, "Make text internal (separate copy)", 0, op->type->idname, "resolution", RESOLVE_MAKE_INTERNAL);
+ uiPupMenuEnd(C, head);
+ }
+ else {
+ head= uiPupMenuBegin("File Modified Outside Blender", 0);
+ uiMenuItemEnumO(head, "Reload from disk", 0, op->type->idname, "resolution", RESOLVE_RELOAD);
+ uiMenuItemEnumO(head, "Make text internal (separate copy)", 0, op->type->idname, "resolution", RESOLVE_MAKE_INTERNAL);
+ uiMenuItemEnumO(head, "Ignore", 0, op->type->idname, "resolution", RESOLVE_IGNORE);
+ uiPupMenuEnd(C, head);
+ }
+ break;
+ case 2:
+ head= uiPupMenuBegin("File Deleted Outside Blender", 0);
+ uiMenuItemEnumO(head, "Make text internal", 0, op->type->idname, "resolution", RESOLVE_MAKE_INTERNAL);
+ uiMenuItemEnumO(head, "Recreate file", 0, op->type->idname, "resolution", RESOLVE_SAVE);
+ uiPupMenuEnd(C, head);
+ break;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void TEXT_OT_resolve_conflict(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Resolve Conflict";
+ ot->idname= "TEXT_OT_resolve_conflict";
+ ot->description= "When external text is out of sync, resolve the conflict.";
+
+ /* api callbacks */
+ ot->exec= resolve_conflict_exec;
+ ot->invoke= resolve_conflict_invoke;
+ ot->poll= save_poll;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "resolution", resolution_items, RESOLVE_IGNORE, "Resolution", "How to solve conflict due to different in internal and external text.");
+}
+
+/********************** to 3d object operator *****************/
+
+static int to_3d_object_exec(bContext *C, wmOperator *op)
+{
+ Text *text= CTX_data_edit_text(C);
+ int split_lines= RNA_boolean_get(op->ptr, "split_lines");
+
+ ED_text_to_object(C, text, split_lines);
+
+ return OPERATOR_FINISHED;
+}
+
+void TEXT_OT_to_3d_object(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "To 3D Object";
+ ot->idname= "TEXT_OT_to_3d_object";
+
+ /* api callbacks */
+ ot->exec= to_3d_object_exec;
+ ot->poll= text_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "split_lines", 0, "Split Lines", "Create one object per line in the text.");
+}
+
+
+/************************ undo ******************************/
+
+void ED_text_undo_step(bContext *C, int step)
+{
+ Text *text= CTX_data_edit_text(C);
+
+ if(!text)
+ return;
+
+ if(step==1)
+ txt_do_undo(text);
+ else if(step==-1)
+ txt_do_redo(text);
+
+ text_update_edited(text);
+
+ WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
+ WM_event_add_notifier(C, NC_TEXT|NA_EDITED, text);
+}
+
diff --git a/source/blender/editors/space_text/text_python.c b/source/blender/editors/space_text/text_python.c
new file mode 100644
index 00000000000..4fa54cdf27b
--- /dev/null
+++ b/source/blender/editors/space_text/text_python.c
@@ -0,0 +1,541 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_text_types.h"
+
+#include "BKE_suggestions.h"
+#include "BKE_text.h"
+
+#include "BLI_blenlib.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "text_intern.h"
+
+int text_do_suggest_select(SpaceText *st, ARegion *ar)
+{
+ SuggItem *item, *first, *last, *sel;
+ TextLine *tmp;
+ int l, x, y, w, h, i;
+ int tgti, *top;
+ short mval[2];
+
+ if(!st || !st->text) return 0;
+ if(!texttool_text_is_active(st->text)) return 0;
+
+ first = texttool_suggest_first();
+ last = texttool_suggest_last();
+ sel = texttool_suggest_selected();
+ top = texttool_suggest_top();
+
+ if(!last || !first)
+ return 0;
+
+ /* Count the visible lines to the cursor */
+ for(tmp=st->text->curl, l=-st->top; tmp; tmp=tmp->prev, l++);
+ if(l<0) return 0;
+
+ if(st->showlinenrs) {
+ x = text_font_width_character(st)*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4;
+ }
+ else {
+ x = text_font_width_character(st)*(st->text->curc-st->left) + TXT_OFFSET - 4;
+ }
+ y = ar->winy - st->lheight*l - 2;
+
+ w = SUGG_LIST_WIDTH*text_font_width_character(st) + 20;
+ h = SUGG_LIST_SIZE*st->lheight + 8;
+
+ // XXX getmouseco_areawin(mval);
+
+ if(mval[0]<x || x+w<mval[0] || mval[1]<y-h || y<mval[1])
+ return 0;
+
+ /* Work out which of the items is at the top of the visible list */
+ for(i=0, item=first; i<*top && item->next; i++, item=item->next);
+
+ /* Work out the target item index in the visible list */
+ tgti = (y-mval[1]-4) / st->lheight;
+ if(tgti<0 || tgti>SUGG_LIST_SIZE)
+ return 1;
+
+ for(i=tgti; i>0 && item->next; i--, item=item->next);
+ if(item)
+ texttool_suggest_select(item);
+ return 1;
+}
+
+void text_pop_suggest_list()
+{
+ SuggItem *item, *sel;
+ int *top, i;
+
+ item= texttool_suggest_first();
+ sel= texttool_suggest_selected();
+ top= texttool_suggest_top();
+
+ i= 0;
+ while(item && item != sel) {
+ item= item->next;
+ i++;
+ }
+ if(i > *top+SUGG_LIST_SIZE-1)
+ *top= i-SUGG_LIST_SIZE+1;
+ else if(i < *top)
+ *top= i;
+}
+
+static void get_suggest_prefix(Text *text, int offset)
+{
+ int i, len;
+ char *line, tmp[256];
+
+ if(!text) return;
+ if(!texttool_text_is_active(text)) return;
+
+ line= text->curl->line;
+ for(i=text->curc-1+offset; i>=0; i--)
+ if(!text_check_identifier(line[i]))
+ break;
+ i++;
+ len= text->curc-i+offset;
+ if(len > 255) {
+ printf("Suggestion prefix too long\n");
+ len = 255;
+ }
+ BLI_strncpy(tmp, line+i, len);
+ tmp[len]= '\0';
+ texttool_suggest_prefix(tmp);
+}
+
+static void confirm_suggestion(Text *text, int skipleft)
+{
+ SuggItem *sel;
+ int i, over=0;
+ char *line;
+
+ if(!text) return;
+ if(!texttool_text_is_active(text)) return;
+
+ sel = texttool_suggest_selected();
+ if(!sel) return;
+
+ line= text->curl->line;
+ i=text->curc-skipleft-1;
+ while(i>=0) {
+ if(!text_check_identifier(line[i]))
+ break;
+ over++;
+ i--;
+ }
+
+ for(i=0; i<skipleft; i++)
+ txt_move_left(text, 0);
+ for(i=0; i<over; i++)
+ txt_move_left(text, 1);
+
+ txt_insert_buf(text, sel->name);
+
+ for(i=0; i<skipleft; i++)
+ txt_move_right(text, 0);
+
+ texttool_text_clear();
+}
+
+// XXX
+#define L_MOUSE 0
+#define M_MOUSE 0
+#define R_MOUSE 0
+#define LR_SHIFTKEY 0
+#define LR_ALTKEY 0
+#define LR_CTRLKEY 0
+#define LR_COMMANDKEY 0
+
+// XXX
+static int doc_scroll= 0;
+
+short do_texttools(SpaceText *st, char ascii, unsigned short evnt, short val)
+{
+ ARegion *ar= NULL; // XXX
+ int qual= 0; // XXX
+ int draw=0, tools=0, swallow=0, scroll=1;
+ if(!texttool_text_is_active(st->text)) return 0;
+ if(!st->text || st->text->id.lib) return 0;
+
+ if(st->doplugins && texttool_text_is_active(st->text)) {
+ if(texttool_suggest_first()) tools |= TOOL_SUGG_LIST;
+ if(texttool_docs_get()) tools |= TOOL_DOCUMENT;
+ }
+
+ if(ascii) {
+ if(tools & TOOL_SUGG_LIST) {
+ if((ascii != '_' && ascii != '*' && ispunct(ascii)) || text_check_whitespace(ascii)) {
+ confirm_suggestion(st->text, 0);
+ text_update_line_edited(st->text, st->text->curl);
+ }
+ else if((st->overwrite && txt_replace_char(st->text, ascii)) || txt_add_char(st->text, ascii)) {
+ get_suggest_prefix(st->text, 0);
+ text_pop_suggest_list();
+ swallow= 1;
+ draw= 1;
+ }
+ }
+ if(tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0, draw= 1;
+
+ }
+ else if(val==1 && evnt) {
+ switch (evnt) {
+ case LEFTMOUSE:
+ if(text_do_suggest_select(st, ar))
+ swallow= 1;
+ else {
+ if(tools & TOOL_SUGG_LIST) texttool_suggest_clear();
+ if(tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0;
+ }
+ draw= 1;
+ break;
+ case MIDDLEMOUSE:
+ if(text_do_suggest_select(st, ar)) {
+ confirm_suggestion(st->text, 0);
+ text_update_line_edited(st->text, st->text->curl);
+ swallow= 1;
+ }
+ else {
+ if(tools & TOOL_SUGG_LIST) texttool_suggest_clear();
+ if(tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0;
+ }
+ draw= 1;
+ break;
+ case ESCKEY:
+ draw= swallow= 1;
+ if(tools & TOOL_SUGG_LIST) texttool_suggest_clear();
+ else if(tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0;
+ else draw= swallow= 0;
+ break;
+ case RETKEY:
+ if(tools & TOOL_SUGG_LIST) {
+ confirm_suggestion(st->text, 0);
+ text_update_line_edited(st->text, st->text->curl);
+ swallow= 1;
+ draw= 1;
+ }
+ if(tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0, draw= 1;
+ break;
+ case LEFTARROWKEY:
+ case BACKSPACEKEY:
+ if(tools & TOOL_SUGG_LIST) {
+ if(qual)
+ texttool_suggest_clear();
+ else {
+ /* Work out which char we are about to delete/pass */
+ if(st->text->curl && st->text->curc > 0) {
+ char ch= st->text->curl->line[st->text->curc-1];
+ if((ch=='_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
+ get_suggest_prefix(st->text, -1);
+ text_pop_suggest_list();
+ }
+ else
+ texttool_suggest_clear();
+ }
+ else
+ texttool_suggest_clear();
+ }
+ }
+ if(tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0;
+ break;
+ case RIGHTARROWKEY:
+ if(tools & TOOL_SUGG_LIST) {
+ if(qual)
+ texttool_suggest_clear();
+ else {
+ /* Work out which char we are about to pass */
+ if(st->text->curl && st->text->curc < st->text->curl->len) {
+ char ch= st->text->curl->line[st->text->curc+1];
+ if((ch=='_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
+ get_suggest_prefix(st->text, 1);
+ text_pop_suggest_list();
+ }
+ else
+ texttool_suggest_clear();
+ }
+ else
+ texttool_suggest_clear();
+ }
+ }
+ if(tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0;
+ break;
+ case PAGEDOWNKEY:
+ scroll= SUGG_LIST_SIZE-1;
+ case WHEELDOWNMOUSE:
+ case DOWNARROWKEY:
+ if(tools & TOOL_DOCUMENT) {
+ doc_scroll++;
+ swallow= 1;
+ draw= 1;
+ break;
+ }
+ else if(tools & TOOL_SUGG_LIST) {
+ SuggItem *sel = texttool_suggest_selected();
+ if(!sel) {
+ texttool_suggest_select(texttool_suggest_first());
+ }
+ else while(sel && sel!=texttool_suggest_last() && sel->next && scroll--) {
+ texttool_suggest_select(sel->next);
+ sel= sel->next;
+ }
+ text_pop_suggest_list();
+ swallow= 1;
+ draw= 1;
+ break;
+ }
+ case PAGEUPKEY:
+ scroll= SUGG_LIST_SIZE-1;
+ case WHEELUPMOUSE:
+ case UPARROWKEY:
+ if(tools & TOOL_DOCUMENT) {
+ if(doc_scroll>0) doc_scroll--;
+ swallow= 1;
+ draw= 1;
+ break;
+ }
+ else if(tools & TOOL_SUGG_LIST) {
+ SuggItem *sel = texttool_suggest_selected();
+ while(sel && sel!=texttool_suggest_first() && sel->prev && scroll--) {
+ texttool_suggest_select(sel->prev);
+ sel= sel->prev;
+ }
+ text_pop_suggest_list();
+ swallow= 1;
+ draw= 1;
+ break;
+ }
+ case RIGHTSHIFTKEY:
+ case LEFTSHIFTKEY:
+ break;
+ default:
+ if(tools & TOOL_SUGG_LIST) texttool_suggest_clear(), draw= 1;
+ if(tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0, draw= 1;
+ }
+ }
+
+ if(draw)
+ ; // XXX redraw_alltext();
+
+ return swallow;
+}
+
+#if 0
+#ifndef DISABLE_PYTHON
+ /* Run text plugin scripts if enabled */
+ if(st->doplugins && event && val) {
+ if(BPY_menu_do_shortcut(PYMENU_TEXTPLUGIN, event, qual)) {
+ do_draw= 1;
+ }
+ }
+#endif
+ if(do_draw)
+ ; // XXX redraw_alltext();
+#endif
+
+short do_textmarkers(SpaceText *st, char ascii, unsigned short evnt, short val)
+{
+ Text *text;
+ TextMarker *marker, *mrk, *nxt;
+ int c, s, draw=0, swallow=0;
+ int qual= 0; // XXX
+
+ text= st->text;
+ if(!text || text->id.lib || text->curl != text->sell) return 0;
+
+ marker= txt_find_marker(text, text->sell, text->selc, 0, 0);
+ if(marker && (marker->start > text->curc || marker->end < text->curc))
+ marker= NULL;
+
+ if(!marker) {
+ /* Find the next temporary marker */
+ if(evnt==TABKEY) {
+ int lineno= txt_get_span(text->lines.first, text->curl);
+ TextMarker *mrk= text->markers.first;
+ while(mrk) {
+ if(!marker && (mrk->flags & TMARK_TEMP)) marker= mrk;
+ if((mrk->flags & TMARK_TEMP) && (mrk->lineno > lineno || (mrk->lineno==lineno && mrk->end > text->curc))) {
+ marker= mrk;
+ break;
+ }
+ mrk= mrk->next;
+ }
+ if(marker) {
+ txt_move_to(text, marker->lineno, marker->start, 0);
+ txt_move_to(text, marker->lineno, marker->end, 1);
+ // XXX WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
+ evnt= ascii= val= 0;
+ draw= 1;
+ swallow= 1;
+ }
+ }
+ else if(evnt==ESCKEY) {
+ if(txt_clear_markers(text, 0, TMARK_TEMP)) swallow= 1;
+ else if(txt_clear_markers(text, 0, 0)) swallow= 1;
+ else return 0;
+ evnt= ascii= val= 0;
+ draw= 1;
+ }
+ if(!swallow) return 0;
+ }
+
+ if(ascii) {
+ if(marker->flags & TMARK_EDITALL) {
+ c= text->curc-marker->start;
+ s= text->selc-marker->start;
+ if(s<0 || s>marker->end-marker->start) return 0;
+
+ mrk= txt_next_marker(text, marker);
+ while(mrk) {
+ nxt=txt_next_marker(text, mrk); /* mrk may become invalid */
+ txt_move_to(text, mrk->lineno, mrk->start+c, 0);
+ if(s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1);
+ if(st->overwrite) {
+ if(txt_replace_char(text, ascii))
+ text_update_line_edited(st->text, st->text->curl);
+ }
+ else {
+ if(txt_add_char(text, ascii)) {
+ text_update_line_edited(st->text, st->text->curl);
+ }
+ }
+
+ if(mrk==marker || mrk==nxt) break;
+ mrk=nxt;
+ }
+ swallow= 1;
+ draw= 1;
+ }
+ }
+ else if(val) {
+ switch(evnt) {
+ case BACKSPACEKEY:
+ if(marker->flags & TMARK_EDITALL) {
+ c= text->curc-marker->start;
+ s= text->selc-marker->start;
+ if(s<0 || s>marker->end-marker->start) return 0;
+
+ mrk= txt_next_marker(text, marker);
+ while(mrk) {
+ nxt= txt_next_marker(text, mrk); /* mrk may become invalid */
+ txt_move_to(text, mrk->lineno, mrk->start+c, 0);
+ if(s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1);
+ txt_backspace_char(text);
+ text_update_line_edited(st->text, st->text->curl);
+ if(mrk==marker || mrk==nxt) break;
+ mrk= nxt;
+ }
+ swallow= 1;
+ draw= 1;
+ }
+ break;
+ case DELKEY:
+ if(marker->flags & TMARK_EDITALL) {
+ c= text->curc-marker->start;
+ s= text->selc-marker->start;
+ if(s<0 || s>marker->end-marker->start) return 0;
+
+ mrk= txt_next_marker(text, marker);
+ while(mrk) {
+ nxt= txt_next_marker(text, mrk); /* mrk may become invalid */
+ txt_move_to(text, mrk->lineno, mrk->start+c, 0);
+ if(s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1);
+ txt_delete_char(text);
+ text_update_line_edited(st->text, st->text->curl);
+ if(mrk==marker || mrk==nxt) break;
+ mrk= nxt;
+ }
+ swallow= 1;
+ draw= 1;
+ }
+ break;
+ case TABKEY:
+ if(qual & LR_SHIFTKEY) {
+ nxt= marker->prev;
+ if(!nxt) nxt= text->markers.last;
+ }
+ else {
+ nxt= marker->next;
+ if(!nxt) nxt= text->markers.first;
+ }
+ if(marker->flags & TMARK_TEMP) {
+ if(nxt==marker) nxt= NULL;
+ BLI_freelinkN(&text->markers, marker);
+ }
+ mrk= nxt;
+ if(mrk) {
+ txt_move_to(text, mrk->lineno, mrk->start, 0);
+ txt_move_to(text, mrk->lineno, mrk->end, 1);
+ // XXX WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
+ }
+ swallow= 1;
+ draw= 1;
+ break;
+
+ /* Events that should clear markers */
+ case UKEY: if(!(qual & LR_ALTKEY)) break;
+ case ZKEY: if(evnt==ZKEY && !(qual & LR_CTRLKEY)) break;
+ case RETKEY:
+ case ESCKEY:
+ if(marker->flags & (TMARK_EDITALL | TMARK_TEMP))
+ txt_clear_markers(text, marker->group, 0);
+ else
+ BLI_freelinkN(&text->markers, marker);
+ swallow= 1;
+ draw= 1;
+ break;
+ case RIGHTMOUSE: /* Marker context menu? */
+ case LEFTMOUSE:
+ break;
+ case FKEY: /* Allow find */
+ if(qual & LR_SHIFTKEY) swallow= 1;
+ break;
+
+ default:
+ if(qual!=0 && qual!=LR_SHIFTKEY)
+ swallow= 1; /* Swallow all other shortcut events */
+ }
+ }
+
+ if(draw)
+ ; // XXX redraw_alltext();
+
+ return swallow;
+}
+
diff --git a/source/blender/editors/space_time/Makefile b/source/blender/editors/space_time/Makefile
new file mode 100644
index 00000000000..20877b48559
--- /dev/null
+++ b/source/blender/editors/space_time/Makefile
@@ -0,0 +1,54 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_time
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/space_time/SConscript b/source/blender/editors/space_time/SConscript
new file mode 100644
index 00000000000..eb3a43a87b7
--- /dev/null
+++ b/source/blender/editors/space_time/SConscript
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' ../../makesrna'
+
+env.BlenderLib ( 'bf_editors_space_time', sources, Split(incs), [], libtype=['core'], priority=[65] )
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
new file mode 100644
index 00000000000..3df57208bbd
--- /dev/null
+++ b/source/blender/editors/space_time/space_time.c
@@ -0,0 +1,335 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_screen.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_markers.h"
+
+#include "time_intern.h"
+
+/* ************************ main time area region *********************** */
+
+/* draws a current frame indicator for the TimeLine */
+static void time_draw_cfra_time(const bContext *C, SpaceTime *stime, ARegion *ar)
+{
+ Scene *scene= CTX_data_scene(C);
+ float vec[2];
+
+ vec[0]= scene->r.cfra*scene->r.framelen;
+
+ UI_ThemeColor(TH_CFRAME); // no theme, should be global color once...
+ glLineWidth(3.0);
+
+ glBegin(GL_LINES);
+ vec[1]= ar->v2d.cur.ymin;
+ glVertex2fv(vec);
+ vec[1]= ar->v2d.cur.ymax;
+ glVertex2fv(vec);
+ glEnd();
+
+ glLineWidth(1.0);
+}
+
+static void time_draw_sfra_efra(const bContext *C, SpaceTime *stime, ARegion *ar)
+{
+ View2D *v2d= UI_view2d_fromcontext(C);
+ Scene *scene= CTX_data_scene(C);
+
+ /* draw darkened area outside of active timeline
+ * frame range used is preview range or scene range */
+ UI_ThemeColorShade(TH_BACK, -25);
+
+ if (PSFRA < PEFRA) {
+ glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
+ glRectf((float)PEFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ }
+ else {
+ glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ }
+
+ UI_ThemeColorShade(TH_BACK, -60);
+ /* thin lines where the actual frames are */
+ fdrawline((float)PSFRA, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
+ fdrawline((float)PEFRA, v2d->cur.ymin, (float)PEFRA, v2d->cur.ymax);
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void time_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "TimeLine", SPACE_TIME, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+
+static void time_main_area_draw(const bContext *C, ARegion *ar)
+{
+ /* draw entirely, view changes should be handled here */
+ SpaceTime *stime= (SpaceTime*)CTX_wm_space_data(C);
+ View2D *v2d= &ar->v2d;
+ View2DGrid *grid;
+ View2DScrollers *scrollers;
+ float col[3];
+ int unit;
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ UI_view2d_view_ortho(C, v2d);
+
+ /* start and end frame */
+ time_draw_sfra_efra(C, stime, ar);
+
+ /* grid */
+ unit= (stime->flag & TIME_DRAWFRAMES)? V2D_UNIT_FRAMES: V2D_UNIT_SECONDS;
+ grid= UI_view2d_grid_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy);
+ UI_view2d_grid_draw(C, v2d, grid, (V2D_VERTICAL_LINES|V2D_VERTICAL_AXIS));
+ UI_view2d_grid_free(grid);
+
+ /* current frame */
+ time_draw_cfra_time(C, stime, ar);
+
+ /* markers */
+ UI_view2d_view_orthoSpecial(C, v2d, 1);
+ draw_markers_time(C, 0);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ scrollers= UI_view2d_scrollers_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+}
+
+static void time_main_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+
+ case NC_SCENE:
+ /* any scene change for now */
+ ED_region_tag_redraw(ar);
+ break;
+ }
+}
+
+/* ************************ header time area region *********************** */
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void time_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+}
+
+static void time_header_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ /* clear */
+ if(ED_screen_area_active(C))
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ else
+ UI_GetThemeColor3fv(TH_HEADERDESEL, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ time_header_buttons(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+static void time_header_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_FRAME:
+ case ND_KEYINGSET:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ }
+}
+
+/* ******************** default callbacks for time space ***************** */
+
+static SpaceLink *time_new(const bContext *C)
+{
+ Scene *scene= CTX_data_scene(C);
+ ARegion *ar;
+ SpaceTime *stime;
+
+ stime= MEM_callocN(sizeof(SpaceTime), "inittime");
+
+ stime->spacetype= SPACE_TIME;
+ stime->redraws= TIME_ALL_3D_WIN|TIME_ALL_ANIM_WIN;
+ stime->flag |= TIME_DRAWFRAMES;
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for time");
+
+ BLI_addtail(&stime->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_BOTTOM;
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for time");
+
+ BLI_addtail(&stime->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+
+ ar->v2d.tot.xmin= (float)(SFRA - 4);
+ ar->v2d.tot.ymin= 0.0f;
+ ar->v2d.tot.xmax= (float)(EFRA + 4);
+ ar->v2d.tot.ymax= 50.0f;
+
+ ar->v2d.cur= ar->v2d.tot;
+
+ ar->v2d.min[0]= 1.0f;
+ ar->v2d.min[1]= 50.0f;
+
+ ar->v2d.max[0]= MAXFRAMEF;
+ ar->v2d.max[1]= 50.0;
+
+ ar->v2d.minzoom= 0.1f;
+ ar->v2d.maxzoom= 10.0;
+
+ ar->v2d.scroll |= (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.align |= V2D_ALIGN_NO_NEG_Y;
+ ar->v2d.keepofs |= V2D_LOCKOFS_Y;
+ ar->v2d.keepzoom |= V2D_LOCKZOOM_Y;
+
+
+ return (SpaceLink*)stime;
+}
+
+/* not spacelink itself */
+static void time_free(SpaceLink *sl)
+{
+}
+
+
+/* spacetype; init callback in ED_area_initialize() */
+/* init is called to (re)initialize an existing editor (file read, screen changes) */
+/* validate spacedata, add own area level handlers */
+static void time_init(wmWindowManager *wm, ScrArea *sa)
+{
+
+}
+
+static SpaceLink *time_duplicate(SpaceLink *sl)
+{
+ SpaceTime *stime= (SpaceTime *)sl;
+ SpaceTime *stimen= MEM_dupallocN(stime);
+
+ return (SpaceLink *)stimen;
+}
+
+/* only called once, from space_api/spacetypes.c */
+/* it defines all callbacks to maintain spaces */
+void ED_spacetype_time(void)
+{
+ SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype time");
+ ARegionType *art;
+
+ st->spaceid= SPACE_TIME;
+ strncpy(st->name, "Timeline", BKE_ST_MAXNAME);
+
+ st->new= time_new;
+ st->free= time_free;
+ st->init= time_init;
+ st->duplicate= time_duplicate;
+ st->operatortypes= time_operatortypes;
+ st->keymap= NULL;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype time region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->keymapflag= ED_KEYMAP_VIEW2D|ED_KEYMAP_MARKERS|ED_KEYMAP_ANIMATION|ED_KEYMAP_FRAMES;
+
+ art->init= time_main_area_init;
+ art->draw= time_main_area_draw;
+ art->listener= time_main_area_listener;
+ art->keymap= time_keymap;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype time region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+
+ art->init= time_header_area_init;
+ art->draw= time_header_area_draw;
+ art->listener= time_header_area_listener;
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
+}
+
diff --git a/source/blender/editors/space_time/time_header.c b/source/blender/editors/space_time/time_header.c
new file mode 100644
index 00000000000..f26e632eb87
--- /dev/null
+++ b/source/blender/editors/space_time/time_header.c
@@ -0,0 +1,572 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_userdef_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_screen.h"
+
+#include "ED_keyframing.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_markers.h"
+
+#include "time_intern.h"
+
+
+/* ************************ header time area region *********************** */
+
+
+static void do_time_redrawmenu(bContext *C, void *arg, int event)
+{
+ SpaceTime *stime= (SpaceTime*)CTX_wm_space_data(C);
+
+ if(event < 1001) {
+
+ stime->redraws ^= event;
+ /* update handler when it's running */
+// if(has_screenhandler(G.curscreen, SCREEN_HANDLER_ANIM))
+// start_animated_screen(stime);
+ }
+ else {
+ if(event==1001) {
+// button(&CTX_data_scene(C)->r.frs_sec,1,120,"FPS:");
+ }
+ }
+}
+
+
+static uiBlock *time_redrawmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ SpaceTime *stime= (SpaceTime*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120, icon;
+ char str[32];
+
+ block= uiBeginBlock(C, ar, "header time_redrawmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_time_redrawmenu, NULL);
+
+ if(stime->redraws & TIME_LEFTMOST_3D_WIN) icon= ICON_CHECKBOX_HLT;
+ else icon= ICON_CHECKBOX_DEHLT;
+ uiDefIconTextBut(block, BUTM, 1, icon, "Top-Left 3D Window", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, TIME_LEFTMOST_3D_WIN, "");
+
+ if(stime->redraws & TIME_ALL_3D_WIN) icon= ICON_CHECKBOX_HLT;
+ else icon= ICON_CHECKBOX_DEHLT;
+ uiDefIconTextBut(block, BUTM, 1, icon, "All 3D Windows", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, TIME_ALL_3D_WIN, "");
+
+ if(stime->redraws & TIME_ALL_ANIM_WIN) icon= ICON_CHECKBOX_HLT;
+ else icon= ICON_CHECKBOX_DEHLT;
+ uiDefIconTextBut(block, BUTM, 1, icon, "Animation Windows", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, TIME_ALL_ANIM_WIN, "");
+
+ if(stime->redraws & TIME_ALL_BUTS_WIN) icon= ICON_CHECKBOX_HLT;
+ else icon= ICON_CHECKBOX_DEHLT;
+ uiDefIconTextBut(block, BUTM, 1, icon, "Buttons Windows", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, TIME_ALL_BUTS_WIN, "");
+
+ if(stime->redraws & TIME_ALL_IMAGE_WIN) icon= ICON_CHECKBOX_HLT;
+ else icon= ICON_CHECKBOX_DEHLT;
+ uiDefIconTextBut(block, BUTM, 1, icon, "Image Windows", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, TIME_ALL_IMAGE_WIN, "");
+
+ /* Add sequencer only redraw*/
+ if(stime->redraws & TIME_SEQ) icon= ICON_CHECKBOX_HLT;
+ else icon= ICON_CHECKBOX_DEHLT;
+ uiDefIconTextBut(block, BUTM, 1, icon, "Sequencer Windows", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, TIME_SEQ, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ sprintf(str, "Set Frames/Sec (%d/%f)", scene->r.frs_sec, scene->r.frs_sec_base);
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, str, 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1001, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if(stime->redraws & TIME_CONTINUE_PHYSICS) icon= ICON_CHECKBOX_HLT;
+ else icon= ICON_CHECKBOX_DEHLT;
+ uiDefIconTextBut(block, BUTM, 1, icon, "Continue Physics", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, TIME_CONTINUE_PHYSICS, "During playblack, continue physics simulations regardless of the frame number");
+
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static void do_time_viewmenu(bContext *C, void *arg, int event)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ SpaceTime *stime= (SpaceTime*)CTX_wm_space_data(C);
+ View2D *v2d= UI_view2d_fromcontext_rwin(C);
+ Scene *scene= CTX_data_scene(C);
+ int first;
+
+ switch(event) {
+ case 2: /* Play Back Animation */
+ //if(!has_screenhandler(G.curscreen, SCREEN_HANDLER_ANIM))
+ // start_animated_screen(stime);
+ break;
+ case 3: /* View All */
+ if(v2d) {
+ first= scene->r.sfra;
+ if(first >= scene->r.efra) first= scene->r.efra;
+ v2d->cur.xmin=v2d->tot.xmin= (float)first-2;
+ v2d->cur.xmax=v2d->tot.xmax= (float)scene->r.efra+2;
+
+ ED_area_tag_redraw(curarea);
+ }
+ break;
+ case 4: /* Maximize Window */
+ /* using event B_FULL */
+ break;
+ case 5: /* show time or frames */
+ stime->flag ^= TIME_DRAWFRAMES;
+ ED_area_tag_redraw(curarea);
+ break;
+ case 6:
+ //nextprev_marker(1);
+ break;
+ case 7:
+ //nextprev_marker(-1);
+ break;
+ case 8:
+ //nextprev_timeline_key(1);
+ break;
+ case 9:
+ //nextprev_timeline_key(-1);
+ break;
+ case 10:
+ //timeline_frame_to_center();
+ break;
+ case 11:
+ if(v2d) {
+ v2d->flag ^= V2D_VIEWSYNC_SCREEN_TIME;
+ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_SET);
+ }
+ break;
+ case 12: /* only show keyframes from selected data */
+ stime->flag ^= TIME_ONLYACTSEL;
+ ED_area_tag_redraw(curarea);
+ break;
+ }
+}
+
+static uiBlock *time_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ SpaceTime *stime= (SpaceTime*)CTX_wm_space_data(C);
+ View2D *v2d= UI_view2d_fromcontext_rwin(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "time_viewmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_time_viewmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Play Back Animation", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if(stime->flag & TIME_DRAWFRAMES)
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Seconds|Ctrl T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ else
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Frames|Ctrl T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+
+ uiDefIconTextBut(block, BUTM, 1, (stime->flag & TIME_ONLYACTSEL)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
+ "Only Selected Data Keys|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Jump To Next Marker|PageUp", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Jump To Prev Marker|PageDown", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Jump To Next Key|Ctrl PageUp", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Jump To Prev Key|Ctrl PageDown", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Center View|C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View All|Home", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, (v2d->flag & V2D_VIEWSYNC_SCREEN_TIME)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
+ "Lock Time to Other Windows|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
+
+// if (!curarea->full)
+// uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
+// else
+// uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static void do_time_framemenu(bContext *C, void *arg, int event)
+{
+ Scene *scene= CTX_data_scene(C);
+
+ switch(event) {
+ case 1: /*Set as Start */
+ if (scene->r.psfra) {
+ if (scene->r.pefra < scene->r.cfra)
+ scene->r.pefra= scene->r.cfra;
+ scene->r.psfra= scene->r.cfra;
+ }
+ else
+ scene->r.sfra = scene->r.cfra;
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+ break;
+ case 2: /* Set as End */
+ if (scene->r.psfra) {
+ if (scene->r.cfra < scene->r.psfra)
+ scene->r.psfra= scene->r.cfra;
+ scene->r.pefra= scene->r.cfra;
+ }
+ else
+ scene->r.efra = scene->r.cfra;
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+ break;
+ case 3: /* Rename Marker */
+ //rename_marker();
+ break;
+ }
+}
+
+static uiBlock *time_framemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *curarea= CTX_wm_area(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "time_framemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_time_framemenu, NULL);
+
+ uiDefIconTextButO(block, BUTM, "MARKER_OT_add", WM_OP_EXEC_REGION_WIN, ICON_BLANK1, "Add Marker",
+ 0, yco-=2, menuwidth, 19, "");
+ uiDefIconTextButO(block, BUTM, "MARKER_OT_duplicate", WM_OP_EXEC_REGION_WIN, ICON_BLANK1, "Duplicate Marker",
+ 0, yco-=20, menuwidth, 19, "");
+ uiDefIconTextButO(block, BUTM, "MARKER_OT_delete", WM_OP_EXEC_REGION_WIN, ICON_BLANK1, "Delete Marker",
+ 0, yco-=20, menuwidth, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Name Marker|Ctrl M",
+ 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextButO(block, BUTM, "MARKER_OT_move", WM_OP_INVOKE_REGION_WIN, ICON_BLANK1, "Grab/Move Marker",
+ 0, yco-=20, menuwidth, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set as Start|S",
+ 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set as End|E",
+ 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+
+#define B_REDRAWALL 750
+#define B_TL_REW 751
+#define B_TL_PLAY 752
+#define B_TL_FF 753
+#define B_TL_PREVKEY 754
+#define B_TL_NEXTKEY 755
+#define B_TL_STOP 756
+#define B_TL_PREVIEWON 757
+#define B_TL_INSERTKEY 758
+#define B_TL_DELETEKEY 759
+
+#define B_FLIPINFOMENU 0
+#define B_NEWFRAME 0
+#define B_DIFF 0
+
+
+void do_time_buttons(bContext *C, void *arg, int event)
+{
+// SpaceTime *stime= (SpaceTime*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+
+ switch(event) {
+ case B_REDRAWALL:
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+ break;
+ case B_NEWFRAME:
+ WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+ break;
+ case B_TL_REW:
+ scene->r.cfra= PSFRA;
+ WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+ //update_for_newframe();
+ break;
+ case B_TL_PLAY:
+ ED_screen_animation_timer(C, 1);
+ break;
+ case B_TL_STOP:
+ ED_screen_animation_timer(C, 0);
+ break;
+ case B_TL_FF:
+ /* end frame */
+ scene->r.cfra= PEFRA;
+ WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+ //update_for_newframe();
+ break;
+ case B_TL_PREVKEY:
+ /* previous keyframe */
+ //nextprev_timeline_key(-1);
+ break;
+ case B_TL_NEXTKEY:
+ /* next keyframe */
+ //nextprev_timeline_key(1);
+ break;
+
+ case B_TL_PREVIEWON:
+ if (scene->r.psfra) {
+ /* turn on preview range */
+ scene->r.psfra= scene->r.sfra;
+ scene->r.pefra= scene->r.efra;
+ }
+ else {
+ /* turn off preview range */
+ scene->r.psfra= 0;
+ scene->r.pefra= 0;
+ }
+ //BIF_undo_push("Set anim-preview range");
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+ break;
+
+ case B_TL_INSERTKEY:
+ /* insert keyframe */
+ //common_insertkey();
+ //allqueue(REDRAWTIME, 1);
+ break;
+ case B_TL_DELETEKEY:
+ /* delete keyframe */
+ //common_deletekey();
+ //allqueue(REDRAWTIME, 1);
+ break;
+ }
+}
+
+
+void time_header_buttons(const bContext *C, ARegion *ar)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceTime *stime= (SpaceTime*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ uiBlock *block;
+ int xco, yco= 3;
+ char *menustr= NULL;
+
+ block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_time_buttons, NULL);
+
+ xco= ED_area_header_standardbuttons(C, block, yco);
+
+ if((sa->flag & HEADER_NO_PULLDOWN)==0) {
+ int xmax;
+
+ xmax= GetButStringLength("View");
+ uiDefPulldownBut(block, time_viewmenu, sa,
+ "View", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+ xmax= GetButStringLength("Frame");
+ uiDefPulldownBut(block, time_framemenu, sa,
+ "Frame", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+
+ xmax= GetButStringLength("Playback");
+ uiDefPulldownBut(block, time_redrawmenu, sa,
+ "Playback", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ uiBlockBeginAlign(block);
+
+ uiDefButI(block, TOG, B_TL_PREVIEWON,"PR",
+ xco,yco, XIC*2, YIC,
+ &scene->r.psfra,0, 1, 0, 0,
+ "Show settings for frame range of animation preview");
+
+ xco += XIC*2;
+
+ if (scene->r.psfra) {
+ uiDefButI(block, NUM, B_REDRAWALL,"Start:",
+ xco,yco, (int)4.5*XIC, YIC,
+ &scene->r.psfra,MINFRAMEF, MAXFRAMEF, 0, 0,
+ "The start frame of the animation preview (inclusive)");
+
+ xco += (int)(4.5*XIC);
+
+ uiDefButI(block, NUM, B_REDRAWALL,"End:",
+ xco,yco, (int)4.5*XIC,YIC,
+ &scene->r.pefra,(float)PSFRA, MAXFRAMEF, 0, 0,
+ "The end frame of the animation preview (inclusive)");
+ }
+ else {
+ uiDefButI(block, NUM, B_REDRAWALL,"Start:",
+ xco,yco, (int)4.5*XIC, YIC,
+ &scene->r.sfra,MINFRAMEF, MAXFRAMEF, 0, 0,
+ "The start frame of the animation (inclusive)");
+
+ xco += (short)(4.5*XIC);
+
+ uiDefButI(block, NUM, B_REDRAWALL,"End:",
+ xco,yco, (int)4.5*XIC,YIC,
+ &scene->r.efra,(float)SFRA, MAXFRAMEF, 0, 0,
+ "The end frame of the animation (inclusive)");
+ }
+ uiBlockEndAlign(block);
+
+ xco += (short)(4.5 * XIC + 16);
+
+ uiDefButI(block, NUM, B_NEWFRAME, "",
+ xco,yco, (int)3.5*XIC,YIC,
+ &(scene->r.cfra), MINFRAMEF, MAXFRAMEF, 0, 0,
+ "Displays Current Frame of animation");
+
+ xco += (short)(3.5 * XIC + 16);
+
+ uiDefIconBut(block, BUT, B_TL_REW, ICON_REW,
+ xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Skip to Start frame (Shift DownArrow)");
+ xco+= XIC+4;
+ uiDefIconBut(block, BUT, B_TL_PREVKEY, ICON_PREV_KEYFRAME,
+ xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Skip to previous keyframe (Ctrl PageDown)");
+ xco+= XIC+4;
+
+ if(CTX_wm_screen(C)->animtimer)
+ uiDefIconBut(block, BUT, B_TL_STOP, ICON_PAUSE,
+ xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Stop Playing Timeline");
+ else
+ uiDefIconBut(block, BUT, B_TL_PLAY, ICON_PLAY,
+ xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Play Timeline ");
+
+ xco+= XIC+4;
+ uiDefIconBut(block, BUT, B_TL_NEXTKEY, ICON_NEXT_KEYFRAME,
+ xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Skip to next keyframe (Ctrl PageUp)");
+ xco+= XIC+4;
+ uiDefIconBut(block, BUT, B_TL_FF, ICON_FF,
+ xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Skip to End frame (Shift UpArrow)");
+ xco+= XIC+8;
+
+ uiBlockBeginAlign(block);
+ uiDefIconButBitS(block, TOG, AUTOKEY_ON, B_REDRAWALL, ICON_REC,
+ xco, yco, XIC, YIC, &(scene->autokey_mode), 0, 0, 0, 0, "Automatic keyframe insertion for Objects and Bones");
+ xco+= XIC;
+ if (IS_AUTOKEY_ON(scene)) {
+ uiDefButS(block, MENU, B_REDRAWALL,
+ "Auto-Keying Mode %t|Add/Replace Keys%x3|Replace Keys %x5",
+ xco, yco, (int)5.5*XIC, YIC, &(scene->autokey_mode), 0, 1, 0, 0,
+ "Mode of automatic keyframe insertion for Objects and Bones");
+ xco+= (6*XIC);
+ }
+ uiBlockEndAlign(block);
+
+ xco+= 16;
+
+
+ menustr= ANIM_build_keyingsets_menu(&scene->keyingsets, 0);
+ uiDefButI(block, MENU, B_DIFF,
+ menustr,
+ xco, yco, (int)5.5*XIC, YIC, &(scene->active_keyingset), 0, 1, 0, 0,
+ "Active Keying Set (i.e. set of channels to Insert Keyframes for)");
+ MEM_freeN(menustr);
+ xco+= (6*XIC);
+
+ uiBlockBeginAlign(block);
+ uiDefIconButO(block, BUT, "ANIM_OT_delete_keyframe", WM_OP_INVOKE_REGION_WIN, ICON_KEY_DEHLT, xco,yco,XIC,YIC, "Delete Keyframes for the Active Keying Set (Alt-I)");
+ xco += XIC;
+ uiDefIconButO(block, BUT, "ANIM_OT_insert_keyframe", WM_OP_INVOKE_REGION_WIN, ICON_KEY_HLT, xco,yco,XIC,YIC, "Insert Keyframes for the Active Keying Set (I)");
+ xco += XIC;
+ uiBlockEndAlign(block);
+
+ xco+= 16;
+
+ uiDefIconButBitI(block, TOG, TIME_WITH_SEQ_AUDIO, B_DIFF, ICON_SPEAKER,
+ xco, yco, XIC, YIC, &(stime->redraws), 0, 0, 0, 0, "Play back and sync with audio from Sequence Editor");
+
+
+ /* always as last */
+ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, (int)(ar->v2d.tot.ymax-ar->v2d.tot.ymin));
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+}
+
+
diff --git a/source/blender/editors/space_time/time_intern.h b/source/blender/editors/space_time/time_intern.h
new file mode 100644
index 00000000000..25f4c63fed1
--- /dev/null
+++ b/source/blender/editors/space_time/time_intern.h
@@ -0,0 +1,44 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_TIME_INTERN_H
+#define ED_TIME_INTERN_H
+
+/* internal exports only */
+
+struct wmWindowManager;
+
+/* time_ops.c */
+void time_operatortypes(void);
+void time_keymap(struct wmWindowManager *wm);
+
+/* time_header.c */
+void time_header_buttons(const bContext *C, ARegion *ar);
+
+#endif /* ED_TIME_INTERN_H */
+
diff --git a/source/blender/editors/space_time/time_ops.c b/source/blender/editors/space_time/time_ops.c
new file mode 100644
index 00000000000..b47afaf0cde
--- /dev/null
+++ b/source/blender/editors/space_time/time_ops.c
@@ -0,0 +1,148 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_utildefines.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "ED_screen.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+
+/* ****************** Start/End Frame Operators *******************************/
+
+static int time_set_sfra_exec (bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ int frame= CFRA;
+
+ if (scene == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* if 'end frame' (Preview Range or Actual) is less than 'frame',
+ * clamp 'frame' to 'end frame'
+ */
+ if (PEFRA < frame) frame= PEFRA;
+
+ /* if Preview Range is defined, set the 'start' frame for that */
+ if (scene->r.psfra)
+ scene->r.psfra= frame;
+ else
+ scene->r.sfra= frame;
+
+ WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void TIME_OT_start_frame_set (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Start Frame";
+ ot->idname= "TIME_OT_start_frame_set";
+
+ /* api callbacks */
+ ot->exec= time_set_sfra_exec;
+ ot->poll= ED_operator_timeline_active;
+
+ // XXX properties???
+}
+
+
+static int time_set_efra_exec (bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ int frame= CFRA;
+
+ if (scene == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* if 'start frame' (Preview Range or Actual) is greater than 'frame',
+ * clamp 'frame' to 'end frame'
+ */
+ if (PSFRA > frame) frame= PSFRA;
+
+ /* if Preview Range is defined, set the 'end' frame for that */
+ if (scene->r.pefra)
+ scene->r.pefra= frame;
+ else
+ scene->r.efra= frame;
+
+ WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void TIME_OT_end_frame_set (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set End Frame";
+ ot->idname= "TIME_OT_end_frame_set";
+
+ /* api callbacks */
+ ot->exec= time_set_efra_exec;
+ ot->poll= ED_operator_timeline_active;
+
+ // XXX properties???
+}
+
+/* ************************** registration **********************************/
+
+void time_operatortypes(void)
+{
+ WM_operatortype_append(TIME_OT_start_frame_set);
+ WM_operatortype_append(TIME_OT_end_frame_set);
+}
+
+void time_keymap(wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "TimeLine", SPACE_TIME, 0);
+
+ WM_keymap_add_item(keymap, "TIME_OT_start_frame_set", SKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "TIME_OT_end_frame_set", EKEY, KM_PRESS, 0, 0);
+}
+
diff --git a/source/blender/editors/space_view3d/Makefile b/source/blender/editors/space_view3d/Makefile
new file mode 100644
index 00000000000..442ab502e65
--- /dev/null
+++ b/source/blender/editors/space_view3d/Makefile
@@ -0,0 +1,58 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_view3d
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+CPPFLAGS += -I$(NAN_BMFONT)/include
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I../../gpu
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../render/extern/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/space_view3d/SConscript b/source/blender/editors/space_view3d/SConscript
new file mode 100644
index 00000000000..c9b29f61e44
--- /dev/null
+++ b/source/blender/editors/space_view3d/SConscript
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' ../../render/extern/include #/intern/guardedalloc #intern/bmfont'
+incs += ' ../../gpu ../../makesrna'
+
+env.BlenderLib ( 'bf_editors_space_view3d', sources, Split(incs), [], libtype=['core'], priority=[40] )
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
new file mode 100644
index 00000000000..5d130cee48d
--- /dev/null
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -0,0 +1,2571 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2005 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_ID.h"
+#include "DNA_nla_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 "DNA_userdef_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_constraint.h"
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "ED_armature.h"
+#include "ED_keyframes_draw.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_resources.h"
+
+#include "view3d_intern.h"
+
+
+/* *************** Armature Drawing - Coloring API ***************************** */
+
+/* global here is reset before drawing each bone */
+static ThemeWireColor *bcolor= NULL;
+
+/* values of colCode for set_pchan_glcolor */
+enum {
+ PCHAN_COLOR_NORMAL = 0, /* normal drawing */
+ PCHAN_COLOR_SOLID, /* specific case where "solid" color is needed */
+ PCHAN_COLOR_CONSTS, /* "constraint" colors (which may/may-not be suppressed) */
+
+ PCHAN_COLOR_SPHEREBONE_BASE, /* for the 'stick' of sphere (envelope) bones */
+ PCHAN_COLOR_SPHEREBONE_END, /* for the ends of sphere (envelope) bones */
+ PCHAN_COLOR_LINEBONE /* for the middle of line-bones */
+};
+
+/* This function sets the color-set for coloring a certain bone */
+static void set_pchan_colorset (Object *ob, bPoseChannel *pchan)
+{
+ bPose *pose= (ob) ? ob->pose : NULL;
+ bArmature *arm= (ob) ? ob->data : NULL;
+ bActionGroup *grp= NULL;
+ short color_index= 0;
+
+ /* sanity check */
+ if (ELEM4(NULL, ob, arm, pose, pchan)) {
+ bcolor= NULL;
+ return;
+ }
+
+ /* only try to set custom color if enabled for armature */
+ if (arm->flag & ARM_COL_CUSTOM) {
+ /* currently, a bone can only use a custom color set if it's group (if it has one),
+ * has been set to use one
+ */
+ if (pchan->agrp_index) {
+ grp= (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1));
+ if (grp)
+ color_index= grp->customCol;
+ }
+ }
+
+ /* bcolor is a pointer to the color set to use. If NULL, then the default
+ * color set (based on the theme colors for 3d-view) is used.
+ */
+ if (color_index > 0) {
+ bTheme *btheme= U.themes.first;
+ bcolor= &btheme->tarm[(color_index - 1)];
+ }
+ else if (color_index == -1) {
+ /* use the group's own custom color set */
+ bcolor= (grp)? &grp->cs : NULL;
+ }
+ else
+ bcolor= NULL;
+}
+
+/* This function is for brightening/darkening a given color (like UI_ThemeColorShade()) */
+static void cp_shade_color3ub (char cp[], int offset)
+{
+ int r, g, b;
+
+ r= offset + (int) cp[0];
+ CLAMP(r, 0, 255);
+ g= offset + (int) cp[1];
+ CLAMP(g, 0, 255);
+ b= offset + (int) cp[2];
+ CLAMP(b, 0, 255);
+
+ cp[0]= r;
+ cp[1]= g;
+ cp[2]= b;
+}
+
+/* This function sets the gl-color for coloring a certain bone (based on bcolor) */
+static short set_pchan_glColor (short colCode, int armflag, int boneflag, int constflag)
+{
+ switch (colCode) {
+ case PCHAN_COLOR_NORMAL:
+ {
+ if (bcolor) {
+ char cp[3];
+
+ if (boneflag & BONE_ACTIVE) {
+ VECCOPY(cp, bcolor->active);
+ }
+ else if (boneflag & BONE_SELECTED) {
+ VECCOPY(cp, bcolor->select);
+ }
+ else {
+ /* a bit darker than solid */
+ VECCOPY(cp, bcolor->solid);
+ cp_shade_color3ub(cp, -50);
+ }
+
+ glColor3ub(cp[0], cp[1], cp[2]);
+ }
+ else {
+ if (boneflag & BONE_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 40);
+ else if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_BONE_POSE);
+ else UI_ThemeColor(TH_WIRE);
+ }
+
+ return 1;
+ }
+ break;
+
+ case PCHAN_COLOR_SOLID:
+ {
+ if (bcolor) {
+ char *cp= bcolor->solid;
+ glColor3ub(cp[0], cp[1], cp[2]);
+ }
+ else
+ UI_ThemeColor(TH_BONE_SOLID);
+
+ return 1;
+ }
+ break;
+
+ case PCHAN_COLOR_CONSTS:
+ {
+ if ( (bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS) ) {
+ if (constflag & PCHAN_HAS_STRIDE) glColor4ub(0, 0, 200, 80);
+ else if (constflag & PCHAN_HAS_TARGET) glColor4ub(255, 150, 0, 80);
+ else if (constflag & PCHAN_HAS_IK) glColor4ub(255, 255, 0, 80);
+ else if (constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 80);
+ else if (constflag) UI_ThemeColor4(TH_BONE_POSE); // PCHAN_HAS_ACTION
+
+ return 1;
+ }
+ else
+ return 0;
+ }
+ break;
+
+ case PCHAN_COLOR_SPHEREBONE_BASE:
+ {
+ if (bcolor) {
+ char cp[3];
+
+ if (boneflag & BONE_ACTIVE) {
+ VECCOPY(cp, bcolor->active);
+ }
+ else if (boneflag & BONE_SELECTED) {
+ VECCOPY(cp, bcolor->select);
+ }
+ else {
+ VECCOPY(cp, bcolor->solid);
+ }
+
+ glColor3ub(cp[0], cp[1], cp[2]);
+ }
+ else {
+ if (boneflag & BONE_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 40);
+ else if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_BONE_POSE);
+ else UI_ThemeColor(TH_BONE_SOLID);
+ }
+
+ return 1;
+ }
+ break;
+ case PCHAN_COLOR_SPHEREBONE_END:
+ {
+ if (bcolor) {
+ char cp[3];
+
+ if (boneflag & BONE_ACTIVE) {
+ VECCOPY(cp, bcolor->active);
+ cp_shade_color3ub(cp, 10);
+ }
+ else if (boneflag & BONE_SELECTED) {
+ VECCOPY(cp, bcolor->select);
+ cp_shade_color3ub(cp, -30);
+ }
+ else {
+ VECCOPY(cp, bcolor->solid);
+ cp_shade_color3ub(cp, -30);
+ }
+
+ glColor3ub(cp[0], cp[1], cp[2]);
+ }
+ else {
+ if (boneflag & BONE_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 10);
+ else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_BONE_POSE, -30);
+ else UI_ThemeColorShade(TH_BONE_SOLID, -30);
+ }
+ }
+ break;
+
+ case PCHAN_COLOR_LINEBONE:
+ {
+ /* inner part in background color or constraint */
+ if ( (constflag) && ((bcolor==NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS)) ) {
+ if (constflag & PCHAN_HAS_STRIDE) glColor3ub(0, 0, 200);
+ else if (constflag & PCHAN_HAS_TARGET) glColor3ub(255, 150, 0);
+ else if (constflag & PCHAN_HAS_IK) glColor3ub(255, 255, 0);
+ else if (constflag & PCHAN_HAS_CONST) glColor3ub(0, 255, 120);
+ else if (constflag) UI_ThemeColor(TH_BONE_POSE); /* PCHAN_HAS_ACTION */
+ }
+ else {
+ if (bcolor) {
+ char *cp= bcolor->solid;
+ glColor4ub(cp[0], cp[1], cp[2], 204);
+ }
+ else
+ UI_ThemeColorShade(TH_BACK, -30);
+ }
+
+ return 1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+/* *************** Armature drawing, helper calls for parts ******************* */
+
+/* half the cube, in Y */
+static float cube[8][3] = {
+{-1.0, 0.0, -1.0},
+{-1.0, 0.0, 1.0},
+{-1.0, 1.0, 1.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},
+{ 1.0, 1.0, -1.0},
+};
+
+static void drawsolidcube_size(float xsize, float ysize, float zsize)
+{
+ static GLuint displist=0;
+ float n[3];
+
+ glScalef(xsize, ysize, zsize);
+
+ n[0]=0; n[1]=0; n[2]=0;
+
+ if(displist==0) {
+ displist= glGenLists(1);
+ glNewList(displist, GL_COMPILE_AND_EXECUTE);
+
+ glBegin(GL_QUADS);
+ n[0]= -1.0;
+ glNormal3fv(n);
+ glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
+ n[0]=0;
+ n[1]= -1.0;
+ glNormal3fv(n);
+ glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
+ n[1]=0;
+ n[0]= 1.0;
+ glNormal3fv(n);
+ glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
+ n[0]=0;
+ n[1]= 1.0;
+ glNormal3fv(n);
+ glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
+ n[1]=0;
+ n[2]= 1.0;
+ glNormal3fv(n);
+ glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
+ n[2]=0;
+ n[2]= -1.0;
+ glNormal3fv(n);
+ glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
+ glEnd();
+
+ glEndList();
+ }
+ else glCallList(displist);
+
+}
+
+static void drawcube_size(float xsize, float ysize, float zsize)
+{
+ static GLuint displist=0;
+
+ glScalef(xsize, ysize, zsize);
+
+ if(displist == 0) {
+ displist= glGenLists(1);
+ glNewList(displist, GL_COMPILE_AND_EXECUTE);
+
+ 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_LINES);
+ glVertex3fv(cube[1]); glVertex3fv(cube[5]);
+ glVertex3fv(cube[2]); glVertex3fv(cube[6]);
+ glVertex3fv(cube[3]); glVertex3fv(cube[7]);
+ glEnd();
+
+ glEndList();
+ }
+ else glCallList(displist);
+
+}
+
+
+static void draw_bonevert(void)
+{
+ static GLuint displist=0;
+
+ if (displist == 0) {
+ GLUquadricObj *qobj;
+
+ displist= glGenLists(1);
+ glNewList(displist, GL_COMPILE_AND_EXECUTE);
+
+ glPushMatrix();
+
+ qobj = gluNewQuadric();
+ gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
+ gluDisk(qobj, 0.0, 0.05, 16, 1);
+
+ glRotatef(90, 0, 1, 0);
+ gluDisk(qobj, 0.0, 0.05, 16, 1);
+
+ glRotatef(90, 1, 0, 0);
+ gluDisk(qobj, 0.0, 0.05, 16, 1);
+
+ gluDeleteQuadric(qobj);
+
+ glPopMatrix();
+ glEndList();
+ }
+ else
+ glCallList(displist);
+}
+
+static void draw_bonevert_solid(void)
+{
+ static GLuint displist=0;
+
+ if (displist == 0) {
+ GLUquadricObj *qobj;
+
+ displist= glGenLists(1);
+ glNewList(displist, GL_COMPILE_AND_EXECUTE);
+
+ qobj = gluNewQuadric();
+ gluQuadricDrawStyle(qobj, GLU_FILL);
+ glShadeModel(GL_SMOOTH);
+ gluSphere(qobj, 0.05, 8, 5);
+ glShadeModel(GL_FLAT);
+ gluDeleteQuadric(qobj);
+
+ glEndList();
+ }
+ else
+ glCallList(displist);
+}
+
+static void draw_bone_octahedral()
+{
+ static GLuint displist=0;
+
+ if (displist == 0) {
+ float vec[6][3];
+
+ displist= glGenLists(1);
+ glNewList(displist, GL_COMPILE_AND_EXECUTE);
+
+ vec[0][0]= vec[0][1]= vec[0][2]= 0.0f;
+ vec[5][0]= vec[5][2]= 0.0f; vec[5][1]= 1.0f;
+
+ vec[1][0]= 0.1f; vec[1][2]= 0.1f; vec[1][1]= 0.1f;
+ vec[2][0]= 0.1f; vec[2][2]= -0.1f; vec[2][1]= 0.1f;
+ vec[3][0]= -0.1f; vec[3][2]= -0.1f; vec[3][1]= 0.1f;
+ vec[4][0]= -0.1f; vec[4][2]= 0.1f; vec[4][1]= 0.1f;
+
+ /* Section 1, sides */
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(vec[0]);
+ glVertex3fv(vec[1]);
+ glVertex3fv(vec[5]);
+ glVertex3fv(vec[3]);
+ glVertex3fv(vec[0]);
+ glVertex3fv(vec[4]);
+ glVertex3fv(vec[5]);
+ glVertex3fv(vec[2]);
+ glEnd();
+
+ /* Section 1, square */
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(vec[1]);
+ glVertex3fv(vec[2]);
+ glVertex3fv(vec[3]);
+ glVertex3fv(vec[4]);
+ glEnd();
+
+ glEndList();
+ }
+ else
+ glCallList(displist);
+}
+
+static void draw_bone_solid_octahedral(void)
+{
+ static GLuint displist=0;
+
+ if (displist == 0) {
+ float vec[6][3], nor[3];
+
+ displist= glGenLists(1);
+ glNewList(displist, GL_COMPILE_AND_EXECUTE);
+
+ vec[0][0]= vec[0][1]= vec[0][2]= 0.0f;
+ vec[5][0]= vec[5][2]= 0.0f; vec[5][1]= 1.0f;
+
+ vec[1][0]= 0.1f; vec[1][2]= 0.1f; vec[1][1]= 0.1f;
+ vec[2][0]= 0.1f; vec[2][2]= -0.1f; vec[2][1]= 0.1f;
+ vec[3][0]= -0.1f; vec[3][2]= -0.1f; vec[3][1]= 0.1f;
+ vec[4][0]= -0.1f; vec[4][2]= 0.1f; vec[4][1]= 0.1f;
+
+
+ glBegin(GL_TRIANGLES);
+ /* bottom */
+ CalcNormFloat(vec[2], vec[1], vec[0], nor);
+ glNormal3fv(nor);
+ glVertex3fv(vec[2]); glVertex3fv(vec[1]); glVertex3fv(vec[0]);
+
+ CalcNormFloat(vec[3], vec[2], vec[0], nor);
+ glNormal3fv(nor);
+ glVertex3fv(vec[3]); glVertex3fv(vec[2]); glVertex3fv(vec[0]);
+
+ CalcNormFloat(vec[4], vec[3], vec[0], nor);
+ glNormal3fv(nor);
+ glVertex3fv(vec[4]); glVertex3fv(vec[3]); glVertex3fv(vec[0]);
+
+ CalcNormFloat(vec[1], vec[4], vec[0], nor);
+ glNormal3fv(nor);
+ glVertex3fv(vec[1]); glVertex3fv(vec[4]); glVertex3fv(vec[0]);
+
+ /* top */
+ CalcNormFloat(vec[5], vec[1], vec[2], nor);
+ glNormal3fv(nor);
+ glVertex3fv(vec[5]); glVertex3fv(vec[1]); glVertex3fv(vec[2]);
+
+ CalcNormFloat(vec[5], vec[2], vec[3], nor);
+ glNormal3fv(nor);
+ glVertex3fv(vec[5]); glVertex3fv(vec[2]); glVertex3fv(vec[3]);
+
+ CalcNormFloat(vec[5], vec[3], vec[4], nor);
+ glNormal3fv(nor);
+ glVertex3fv(vec[5]); glVertex3fv(vec[3]); glVertex3fv(vec[4]);
+
+ CalcNormFloat(vec[5], vec[4], vec[1], nor);
+ glNormal3fv(nor);
+ glVertex3fv(vec[5]); glVertex3fv(vec[4]); glVertex3fv(vec[1]);
+
+ glEnd();
+
+ glEndList();
+ }
+ else
+ glCallList(displist);
+}
+
+/* *************** Armature drawing, bones ******************* */
+
+
+static void draw_bone_points(int dt, int armflag, unsigned int boneflag, int id)
+{
+ /* Draw root point if we are not connected */
+ if ((boneflag & BONE_CONNECTED)==0) {
+ if (id != -1)
+ glLoadName(id | BONESEL_ROOT);
+
+ if(dt <= OB_WIRE) {
+ if (armflag & ARM_EDITMODE) {
+ if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
+ else UI_ThemeColor(TH_VERTEX);
+ }
+ }
+ else {
+ if (armflag & ARM_POSEMODE)
+ set_pchan_glColor(PCHAN_COLOR_SOLID, armflag, boneflag, 0);
+ else
+ UI_ThemeColor(TH_BONE_SOLID);
+ }
+
+ if (dt > OB_WIRE)
+ draw_bonevert_solid();
+ else
+ draw_bonevert();
+ }
+
+ /* Draw tip point */
+ if (id != -1)
+ glLoadName(id | BONESEL_TIP);
+
+ if (dt <= OB_WIRE) {
+ if (armflag & ARM_EDITMODE) {
+ if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
+ else UI_ThemeColor(TH_VERTEX);
+ }
+ }
+ else {
+ if (armflag & ARM_POSEMODE)
+ set_pchan_glColor(PCHAN_COLOR_SOLID, armflag, boneflag, 0);
+ else
+ UI_ThemeColor(TH_BONE_SOLID);
+ }
+
+ glTranslatef(0.0f, 1.0f, 0.0f);
+ if (dt > OB_WIRE)
+ draw_bonevert_solid();
+ else
+ draw_bonevert();
+ glTranslatef(0.0f, -1.0f, 0.0f);
+
+}
+
+/* 16 values of sin function (still same result!) */
+static float si[16] = {
+ 0.00000000f,
+ 0.20129852f, 0.39435585f,
+ 0.57126821f, 0.72479278f,
+ 0.84864425f, 0.93775213f,
+ 0.98846832f, 0.99871650f,
+ 0.96807711f, 0.89780453f,
+ 0.79077573f, 0.65137248f,
+ 0.48530196f, 0.29936312f,
+ 0.10116832f
+};
+/* 16 values of cos function (still same result!) */
+static float co[16] ={
+ 1.00000000f,
+ 0.97952994f, 0.91895781f,
+ 0.82076344f, 0.68896691f,
+ 0.52896401f, 0.34730525f,
+ 0.15142777f, -0.05064916f,
+ -0.25065253f, -0.44039415f,
+ -0.61210598f, -0.75875812f,
+ -0.87434661f, -0.95413925f,
+ -0.99486932f
+};
+
+
+
+/* smat, imat = mat & imat to draw screenaligned */
+static void draw_sphere_bone_dist(float smat[][4], float imat[][4], int boneflag, bPoseChannel *pchan, EditBone *ebone)
+{
+ float head, tail, length, dist;
+ float *headvec, *tailvec, dirvec[3];
+
+ /* figure out the sizes of spheres */
+ if (ebone) {
+ /* this routine doesn't call set_matrix_editbone() that calculates it */
+ ebone->length = VecLenf(ebone->head, ebone->tail);
+
+ length= ebone->length;
+ tail= ebone->rad_tail;
+ dist= ebone->dist;
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED))
+ head= ebone->parent->rad_tail;
+ else
+ head= ebone->rad_head;
+ headvec= ebone->head;
+ tailvec= ebone->tail;
+ }
+ else {
+ length= pchan->bone->length;
+ tail= pchan->bone->rad_tail;
+ dist= pchan->bone->dist;
+ if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED))
+ head= pchan->parent->bone->rad_tail;
+ else
+ head= pchan->bone->rad_head;
+ headvec= pchan->pose_head;
+ tailvec= pchan->pose_tail;
+ }
+
+ /* ***** draw it ***** */
+
+ /* move vector to viewspace */
+ VecSubf(dirvec, tailvec, headvec);
+ Mat4Mul3Vecfl(smat, dirvec);
+ /* clear zcomp */
+ dirvec[2]= 0.0f;
+ /* move vector back */
+ Mat4Mul3Vecfl(imat, dirvec);
+
+ if (0.0f != Normalize(dirvec)) {
+ float norvec[3], vec1[3], vec2[3], vec[3];
+ int a;
+
+ //VecMulf(dirvec, head);
+ Crossf(norvec, dirvec, imat[2]);
+
+ glBegin(GL_QUAD_STRIP);
+
+ for (a=0; a<16; a++) {
+ vec[0]= - *(si+a) * dirvec[0] + *(co+a) * norvec[0];
+ vec[1]= - *(si+a) * dirvec[1] + *(co+a) * norvec[1];
+ vec[2]= - *(si+a) * dirvec[2] + *(co+a) * norvec[2];
+
+ vec1[0]= headvec[0] + head*vec[0];
+ vec1[1]= headvec[1] + head*vec[1];
+ vec1[2]= headvec[2] + head*vec[2];
+ vec2[0]= headvec[0] + (head+dist)*vec[0];
+ vec2[1]= headvec[1] + (head+dist)*vec[1];
+ vec2[2]= headvec[2] + (head+dist)*vec[2];
+
+ glColor4ub(255, 255, 255, 50);
+ glVertex3fv(vec1);
+ //glColor4ub(255, 255, 255, 0);
+ glVertex3fv(vec2);
+ }
+
+ for (a=15; a>=0; a--) {
+ vec[0]= *(si+a) * dirvec[0] + *(co+a) * norvec[0];
+ vec[1]= *(si+a) * dirvec[1] + *(co+a) * norvec[1];
+ vec[2]= *(si+a) * dirvec[2] + *(co+a) * norvec[2];
+
+ vec1[0]= tailvec[0] + tail*vec[0];
+ vec1[1]= tailvec[1] + tail*vec[1];
+ vec1[2]= tailvec[2] + tail*vec[2];
+ vec2[0]= tailvec[0] + (tail+dist)*vec[0];
+ vec2[1]= tailvec[1] + (tail+dist)*vec[1];
+ vec2[2]= tailvec[2] + (tail+dist)*vec[2];
+
+ //glColor4ub(255, 255, 255, 50);
+ glVertex3fv(vec1);
+ //glColor4ub(255, 255, 255, 0);
+ glVertex3fv(vec2);
+ }
+ /* make it cyclic... */
+
+ vec[0]= - *(si) * dirvec[0] + *(co) * norvec[0];
+ vec[1]= - *(si) * dirvec[1] + *(co) * norvec[1];
+ vec[2]= - *(si) * dirvec[2] + *(co) * norvec[2];
+
+ vec1[0]= headvec[0] + head*vec[0];
+ vec1[1]= headvec[1] + head*vec[1];
+ vec1[2]= headvec[2] + head*vec[2];
+ vec2[0]= headvec[0] + (head+dist)*vec[0];
+ vec2[1]= headvec[1] + (head+dist)*vec[1];
+ vec2[2]= headvec[2] + (head+dist)*vec[2];
+
+ //glColor4ub(255, 255, 255, 50);
+ glVertex3fv(vec1);
+ //glColor4ub(255, 255, 255, 0);
+ glVertex3fv(vec2);
+
+ glEnd();
+ }
+}
+
+
+/* smat, imat = mat & imat to draw screenaligned */
+static void draw_sphere_bone_wire(float smat[][4], float imat[][4], int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
+{
+ float head, tail, length;
+ float *headvec, *tailvec, dirvec[3];
+
+ /* figure out the sizes of spheres */
+ if (ebone) {
+ /* this routine doesn't call set_matrix_editbone() that calculates it */
+ ebone->length = VecLenf(ebone->head, ebone->tail);
+
+ length= ebone->length;
+ tail= ebone->rad_tail;
+ if (ebone->parent && (boneflag & BONE_CONNECTED))
+ head= ebone->parent->rad_tail;
+ else
+ head= ebone->rad_head;
+ headvec= ebone->head;
+ tailvec= ebone->tail;
+ }
+ else {
+ length= pchan->bone->length;
+ tail= pchan->bone->rad_tail;
+ if ((pchan->parent) && (boneflag & BONE_CONNECTED))
+ head= pchan->parent->bone->rad_tail;
+ else
+ head= pchan->bone->rad_head;
+ headvec= pchan->pose_head;
+ tailvec= pchan->pose_tail;
+ }
+
+ /* sphere root color */
+ if (armflag & ARM_EDITMODE) {
+ if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
+ else UI_ThemeColor(TH_VERTEX);
+ }
+ else if (armflag & ARM_POSEMODE)
+ set_pchan_glColor(PCHAN_COLOR_NORMAL, armflag, boneflag, constflag);
+
+ /* Draw root point if we are not connected */
+ if ((boneflag & BONE_CONNECTED)==0) {
+ if (id != -1)
+ glLoadName(id | BONESEL_ROOT);
+
+ drawcircball(GL_LINE_LOOP, headvec, head, imat);
+ }
+
+ /* Draw tip point */
+ if (armflag & ARM_EDITMODE) {
+ if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
+ else UI_ThemeColor(TH_VERTEX);
+ }
+
+ if (id != -1)
+ glLoadName(id | BONESEL_TIP);
+
+ drawcircball(GL_LINE_LOOP, tailvec, tail, imat);
+
+ /* base */
+ if (armflag & ARM_EDITMODE) {
+ if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT);
+ else UI_ThemeColor(TH_WIRE);
+ }
+
+ VecSubf(dirvec, tailvec, headvec);
+
+ /* move vector to viewspace */
+ Mat4Mul3Vecfl(smat, dirvec);
+ /* clear zcomp */
+ dirvec[2]= 0.0f;
+ /* move vector back */
+ Mat4Mul3Vecfl(imat, dirvec);
+
+ if (0.0f != Normalize(dirvec)) {
+ float norvech[3], norvect[3], vec[3];
+
+ VECCOPY(vec, dirvec);
+
+ VecMulf(dirvec, head);
+ Crossf(norvech, dirvec, imat[2]);
+
+ VecMulf(vec, tail);
+ Crossf(norvect, vec, imat[2]);
+
+ if (id != -1)
+ glLoadName(id | BONESEL_BONE);
+
+ glBegin(GL_LINES);
+ vec[0]= headvec[0] + norvech[0];
+ vec[1]= headvec[1] + norvech[1];
+ vec[2]= headvec[2] + norvech[2];
+ glVertex3fv(vec);
+ vec[0]= tailvec[0] + norvect[0];
+ vec[1]= tailvec[1] + norvect[1];
+ vec[2]= tailvec[2] + norvect[2];
+ glVertex3fv(vec);
+ vec[0]= headvec[0] - norvech[0];
+ vec[1]= headvec[1] - norvech[1];
+ vec[2]= headvec[2] - norvech[2];
+ glVertex3fv(vec);
+ vec[0]= tailvec[0] - norvect[0];
+ vec[1]= tailvec[1] - norvect[1];
+ vec[2]= tailvec[2] - norvect[2];
+ glVertex3fv(vec);
+
+ glEnd();
+ }
+}
+
+/* does wire only for outline selecting */
+static void draw_sphere_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
+{
+ GLUquadricObj *qobj;
+ float head, tail, length;
+ float fac1, fac2;
+
+ glPushMatrix();
+ qobj = gluNewQuadric();
+
+ /* figure out the sizes of spheres */
+ if (ebone) {
+ length= ebone->length;
+ tail= ebone->rad_tail;
+ if (ebone->parent && (boneflag & BONE_CONNECTED))
+ head= ebone->parent->rad_tail;
+ else
+ head= ebone->rad_head;
+ }
+ else {
+ length= pchan->bone->length;
+ tail= pchan->bone->rad_tail;
+ if (pchan->parent && (boneflag & BONE_CONNECTED))
+ head= pchan->parent->bone->rad_tail;
+ else
+ head= pchan->bone->rad_head;
+ }
+
+ /* move to z-axis space */
+ glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
+
+ if (dt==OB_SOLID) {
+ /* set up solid drawing */
+ glEnable(GL_COLOR_MATERIAL);
+ glEnable(GL_LIGHTING);
+
+ gluQuadricDrawStyle(qobj, GLU_FILL);
+ glShadeModel(GL_SMOOTH);
+ }
+ else {
+ gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
+ }
+
+ /* sphere root color */
+ if (armflag & ARM_EDITMODE) {
+ if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
+ else UI_ThemeColorShade(TH_BONE_SOLID, -30);
+ }
+ else if (armflag & ARM_POSEMODE)
+ set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_END, armflag, boneflag, constflag);
+ else if (dt==OB_SOLID)
+ UI_ThemeColorShade(TH_BONE_SOLID, -30);
+
+ /* Draw root point if we are not connected */
+ if ((boneflag & BONE_CONNECTED)==0) {
+ if (id != -1)
+ glLoadName(id | BONESEL_ROOT);
+ gluSphere(qobj, head, 16, 10);
+ }
+
+ /* Draw tip point */
+ if (armflag & ARM_EDITMODE) {
+ if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
+ else UI_ThemeColorShade(TH_BONE_SOLID, -30);
+ }
+
+ if (id != -1)
+ glLoadName(id | BONESEL_TIP);
+
+ glTranslatef(0.0f, 0.0f, length);
+ gluSphere(qobj, tail, 16, 10);
+ glTranslatef(0.0f, 0.0f, -length);
+
+ /* base */
+ if (armflag & ARM_EDITMODE) {
+ if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT);
+ else UI_ThemeColor(TH_BONE_SOLID);
+ }
+ else if (armflag & ARM_POSEMODE)
+ set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_BASE, armflag, boneflag, constflag);
+ else if (dt == OB_SOLID)
+ UI_ThemeColor(TH_BONE_SOLID);
+
+ fac1= (length-head)/length;
+ fac2= (length-tail)/length;
+
+ if (length > (head+tail)) {
+ if (id != -1)
+ glLoadName (id | BONESEL_BONE);
+
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(-1.0f, -1.0f);
+
+ glTranslatef(0.0f, 0.0f, head);
+ gluCylinder(qobj, fac1*head + (1.0f-fac1)*tail, fac2*tail + (1.0f-fac2)*head, length-head-tail, 16, 1);
+ glTranslatef(0.0f, 0.0f, -head);
+
+ glDisable(GL_POLYGON_OFFSET_FILL);
+
+ /* draw sphere on extrema */
+ glTranslatef(0.0f, 0.0f, length-tail);
+ gluSphere(qobj, fac2*tail + (1.0f-fac2)*head, 16, 10);
+ glTranslatef(0.0f, 0.0f, -length+tail);
+
+ glTranslatef(0.0f, 0.0f, head);
+ gluSphere(qobj, fac1*head + (1.0f-fac1)*tail, 16, 10);
+ }
+ else {
+ /* 1 sphere in center */
+ glTranslatef(0.0f, 0.0f, (head + length-tail)/2.0f);
+ gluSphere(qobj, fac1*head + (1.0f-fac1)*tail, 16, 10);
+ }
+
+ /* restore */
+ if (dt==OB_SOLID) {
+ glShadeModel(GL_FLAT);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
+ }
+
+ glPopMatrix();
+ gluDeleteQuadric(qobj);
+}
+
+static GLubyte bm_dot6[]= {0x0, 0x18, 0x3C, 0x7E, 0x7E, 0x3C, 0x18, 0x0};
+static GLubyte bm_dot8[]= {0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C};
+
+static GLubyte bm_dot5[]= {0x0, 0x0, 0x10, 0x38, 0x7c, 0x38, 0x10, 0x0};
+static GLubyte bm_dot7[]= {0x0, 0x38, 0x7C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38};
+
+
+static void draw_line_bone(int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
+{
+ float length;
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ if (pchan)
+ length= pchan->bone->length;
+ else
+ length= ebone->length;
+
+ glPushMatrix();
+ glScalef(length, length, length);
+
+ /* this chunk not in object mode */
+ if (armflag & (ARM_EDITMODE|ARM_POSEMODE)) {
+ glLineWidth(4.0f);
+ if (armflag & ARM_POSEMODE)
+ set_pchan_glColor(PCHAN_COLOR_NORMAL, armflag, boneflag, constflag);
+ else if (armflag & ARM_EDITMODE) {
+ UI_ThemeColor(TH_WIRE);
+ }
+
+ /* Draw root point if we are not connected */
+ if ((boneflag & BONE_CONNECTED)==0) {
+ if (G.f & G_PICKSEL) { // no bitmap in selection mode, crashes 3d cards...
+ glLoadName (id | BONESEL_ROOT);
+ glBegin(GL_POINTS);
+ glVertex3f(0.0f, 0.0f, 0.0f);
+ glEnd();
+ }
+ else {
+ glRasterPos3f(0.0f, 0.0f, 0.0f);
+ glBitmap(8, 8, 4, 4, 0, 0, bm_dot8);
+ }
+ }
+
+ if (id != -1)
+ glLoadName((GLuint) id|BONESEL_BONE);
+
+ glBegin(GL_LINES);
+ glVertex3f(0.0f, 0.0f, 0.0f);
+ glVertex3f(0.0f, 1.0f, 0.0f);
+ glEnd();
+
+ /* tip */
+ if (G.f & G_PICKSEL) {
+ /* no bitmap in selection mode, crashes 3d cards... */
+ glLoadName(id | BONESEL_TIP);
+ glBegin(GL_POINTS);
+ glVertex3f(0.0f, 1.0f, 0.0f);
+ glEnd();
+ }
+ else {
+ glRasterPos3f(0.0f, 1.0f, 0.0f);
+ glBitmap(8, 8, 4, 4, 0, 0, bm_dot7);
+ }
+
+ /* further we send no names */
+ if (id != -1)
+ glLoadName(id & 0xFFFF); /* object tag, for bordersel optim */
+
+ if (armflag & ARM_POSEMODE)
+ set_pchan_glColor(PCHAN_COLOR_LINEBONE, armflag, boneflag, constflag);
+ }
+
+ glLineWidth(2.0);
+
+ /*Draw root point if we are not connected */
+ if ((boneflag & BONE_CONNECTED)==0) {
+ if ((G.f & G_PICKSEL)==0) {
+ /* no bitmap in selection mode, crashes 3d cards... */
+ if (armflag & ARM_EDITMODE) {
+ if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
+ else UI_ThemeColor(TH_VERTEX);
+ }
+ glRasterPos3f(0.0f, 0.0f, 0.0f);
+ glBitmap(8, 8, 4, 4, 0, 0, bm_dot6);
+ }
+ }
+
+ if (armflag & ARM_EDITMODE) {
+ if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_EDGE_SELECT);
+ else UI_ThemeColorShade(TH_BACK, -30);
+ }
+ glBegin(GL_LINES);
+ glVertex3f(0.0f, 0.0f, 0.0f);
+ glVertex3f(0.0f, 1.0f, 0.0f);
+ glEnd();
+
+ /* tip */
+ if ((G.f & G_PICKSEL)==0) {
+ /* no bitmap in selection mode, crashes 3d cards... */
+ if (armflag & ARM_EDITMODE) {
+ if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
+ else UI_ThemeColor(TH_VERTEX);
+ }
+ glRasterPos3f(0.0f, 1.0f, 0.0f);
+ glBitmap(8, 8, 4, 4, 0, 0, bm_dot5);
+ }
+
+ glLineWidth(1.0);
+
+ glPopMatrix();
+}
+
+static void draw_b_bone_boxes(int dt, bPoseChannel *pchan, float xwidth, float length, float zwidth)
+{
+ int segments= 0;
+
+ if (pchan)
+ segments= pchan->bone->segments;
+
+ if ((segments > 1) && (pchan)) {
+ float dlen= length/(float)segments;
+ Mat4 *bbone= b_bone_spline_setup(pchan, 0);
+ int a;
+
+ for (a=0; a<segments; a++, bbone++) {
+ glPushMatrix();
+ glMultMatrixf(bbone->mat);
+ if (dt==OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth);
+ else drawcube_size(xwidth, dlen, zwidth);
+ glPopMatrix();
+ }
+ }
+ else {
+ glPushMatrix();
+ if (dt==OB_SOLID) drawsolidcube_size(xwidth, length, zwidth);
+ else drawcube_size(xwidth, length, zwidth);
+ glPopMatrix();
+ }
+}
+
+static void draw_b_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
+{
+ float xwidth, length, zwidth;
+
+ if (pchan) {
+ xwidth= pchan->bone->xwidth;
+ length= pchan->bone->length;
+ zwidth= pchan->bone->zwidth;
+ }
+ else {
+ xwidth= ebone->xwidth;
+ length= ebone->length;
+ zwidth= ebone->zwidth;
+ }
+
+ /* draw points only if... */
+ if (armflag & ARM_EDITMODE) {
+ /* move to unitspace */
+ glPushMatrix();
+ glScalef(length, length, length);
+ draw_bone_points(dt, armflag, boneflag, id);
+ glPopMatrix();
+ length*= 0.95f; // make vertices visible
+ }
+
+ /* colors for modes */
+ if (armflag & ARM_POSEMODE) {
+ if (dt <= OB_WIRE)
+ set_pchan_glColor(PCHAN_COLOR_NORMAL, armflag, boneflag, constflag);
+ else
+ set_pchan_glColor(PCHAN_COLOR_SOLID, armflag, boneflag, constflag);
+ }
+ else if (armflag & ARM_EDITMODE) {
+ if (dt==OB_WIRE) {
+ if (boneflag & BONE_ACTIVE) UI_ThemeColor(TH_EDGE_SELECT);
+ else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_EDGE_SELECT, -20);
+ else UI_ThemeColor(TH_WIRE);
+ }
+ else
+ UI_ThemeColor(TH_BONE_SOLID);
+ }
+
+ if (id != -1) {
+ glLoadName ((GLuint) id|BONESEL_BONE);
+ }
+
+ /* set up solid drawing */
+ if (dt > OB_WIRE) {
+ glEnable(GL_COLOR_MATERIAL);
+ glEnable(GL_LIGHTING);
+
+ if (armflag & ARM_POSEMODE)
+ set_pchan_glColor(PCHAN_COLOR_SOLID, armflag, boneflag, constflag);
+ else
+ UI_ThemeColor(TH_BONE_SOLID);
+
+ draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
+
+ /* disable solid drawing */
+ glDisable(GL_COLOR_MATERIAL);
+ glDisable(GL_LIGHTING);
+ }
+ else {
+ /* wire */
+ if (armflag & ARM_POSEMODE) {
+ if (constflag) {
+ /* set constraint colors */
+ if (set_pchan_glColor(PCHAN_COLOR_CONSTS, armflag, boneflag, constflag)) {
+ glEnable(GL_BLEND);
+
+ draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
+
+ glDisable(GL_BLEND);
+ }
+
+ /* restore colors */
+ set_pchan_glColor(PCHAN_COLOR_NORMAL, armflag, boneflag, constflag);
+ }
+ }
+
+ draw_b_bone_boxes(OB_WIRE, pchan, xwidth, length, zwidth);
+ }
+}
+
+static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, float length)
+{
+
+ /* Draw a 3d octahedral bone, we use normalized space based on length,
+ for glDisplayLists */
+
+ glScalef(length, length, length);
+
+ /* set up solid drawing */
+ if (dt > OB_WIRE) {
+ glEnable(GL_COLOR_MATERIAL);
+ glEnable(GL_LIGHTING);
+ UI_ThemeColor(TH_BONE_SOLID);
+ }
+
+ /* colors for posemode */
+ if (armflag & ARM_POSEMODE) {
+ if (dt <= OB_WIRE)
+ set_pchan_glColor(PCHAN_COLOR_NORMAL, armflag, boneflag, constflag);
+ else
+ set_pchan_glColor(PCHAN_COLOR_SOLID, armflag, boneflag, constflag);
+ }
+
+
+ draw_bone_points(dt, armflag, boneflag, id);
+
+ /* now draw the bone itself */
+ if (id != -1) {
+ glLoadName((GLuint) id|BONESEL_BONE);
+ }
+
+ /* wire? */
+ if (dt <= OB_WIRE) {
+ /* colors */
+ if (armflag & ARM_EDITMODE) {
+ if (boneflag & BONE_ACTIVE) UI_ThemeColor(TH_EDGE_SELECT);
+ else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_EDGE_SELECT, -20);
+ else UI_ThemeColor(TH_WIRE);
+ }
+ else if (armflag & ARM_POSEMODE) {
+ if (constflag) {
+ /* draw constraint colors */
+ if (set_pchan_glColor(PCHAN_COLOR_CONSTS, armflag, boneflag, constflag)) {
+ glEnable(GL_BLEND);
+
+ draw_bone_solid_octahedral();
+
+ glDisable(GL_BLEND);
+ }
+
+ /* restore colors */
+ set_pchan_glColor(PCHAN_COLOR_NORMAL, armflag, boneflag, constflag);
+ }
+ }
+ draw_bone_octahedral();
+ }
+ else {
+ /* solid */
+ if (armflag & ARM_POSEMODE)
+ set_pchan_glColor(PCHAN_COLOR_SOLID, armflag, boneflag, constflag);
+ else
+ UI_ThemeColor(TH_BONE_SOLID);
+ draw_bone_solid_octahedral();
+ }
+
+ /* disable solid drawing */
+ if (dt > OB_WIRE) {
+ glDisable(GL_COLOR_MATERIAL);
+ glDisable(GL_LIGHTING);
+ }
+}
+
+static void draw_custom_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int dt, int armflag, int boneflag, unsigned int id, float length)
+{
+ if(ob==NULL) return;
+
+ glScalef(length, length, length);
+
+ /* colors for posemode */
+ if (armflag & ARM_POSEMODE) {
+ set_pchan_glColor(PCHAN_COLOR_NORMAL, armflag, boneflag, 0);
+ }
+
+ if (id != -1) {
+ glLoadName((GLuint) id|BONESEL_BONE);
+ }
+
+ draw_object_instance(scene, v3d, rv3d, ob, dt, armflag & ARM_POSEMODE);
+}
+
+
+static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp)
+{
+ bConstraint *con;
+ bPoseChannel *parchan;
+
+ for (con= pchan->constraints.first; con; con= con->next) {
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
+ bKinematicConstraint *data = (bKinematicConstraint*)con->data;
+ int segcount= 0;
+
+ /* if only_temp, only draw if it is a temporary ik-chain */
+ if ((only_temp) && !(data->flag & CONSTRAINT_IK_TEMP))
+ continue;
+
+ setlinestyle(3);
+ glBegin(GL_LINES);
+
+ /* exclude tip from chain? */
+ if ((data->flag & CONSTRAINT_IK_TIP)==0)
+ parchan= pchan->parent;
+ else
+ parchan= pchan;
+
+ glVertex3fv(parchan->pose_tail);
+
+ /* Find the chain's root */
+ while (parchan->parent) {
+ segcount++;
+ if(segcount==data->rootbone || segcount>255) break; // 255 is weak
+ parchan= parchan->parent;
+ }
+ if (parchan)
+ glVertex3fv(parchan->pose_head);
+
+ glEnd();
+ setlinestyle(0);
+ }
+ }
+}
+
+static void bgl_sphere_project(float ax, float az)
+{
+ float dir[3], sine, q3;
+
+ sine= 1.0f - ax*ax - az*az;
+ q3= (sine < 0.0f)? 0.0f: (float)(2.0*sqrt(sine));
+
+ dir[0]= -az*q3;
+ dir[1]= 1.0f - 2.0f*sine;
+ dir[2]= ax*q3;
+
+ glVertex3fv(dir);
+}
+
+static void draw_dof_ellipse(float ax, float az)
+{
+ static float staticSine[16] = {
+ 0.0f, 0.104528463268f, 0.207911690818f, 0.309016994375f,
+ 0.406736643076f, 0.5f, 0.587785252292f, 0.669130606359f,
+ 0.743144825477f, 0.809016994375f, 0.866025403784f,
+ 0.913545457643f, 0.951056516295f, 0.978147600734f,
+ 0.994521895368f, 1.0f
+ };
+
+ int i, j, n=16;
+ float x, z, px, pz;
+
+ glEnable(GL_BLEND);
+ glDepthMask(0);
+
+ glColor4ub(70, 70, 70, 50);
+
+ glBegin(GL_QUADS);
+ pz= 0.0f;
+ for(i=1; i<n; i++) {
+ z= staticSine[i];
+
+ px= 0.0f;
+ for(j=1; j<n-i+1; j++) {
+ x = staticSine[j];
+
+ if(j == n-i) {
+ glEnd();
+ glBegin(GL_TRIANGLES);
+ bgl_sphere_project(ax*px, az*z);
+ bgl_sphere_project(ax*px, az*pz);
+ bgl_sphere_project(ax*x, az*pz);
+ glEnd();
+ glBegin(GL_QUADS);
+ }
+ else {
+ bgl_sphere_project(ax*x, az*z);
+ bgl_sphere_project(ax*x, az*pz);
+ bgl_sphere_project(ax*px, az*pz);
+ bgl_sphere_project(ax*px, az*z);
+ }
+
+ px= x;
+ }
+ pz= z;
+ }
+ glEnd();
+
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+
+ glColor3ub(0, 0, 0);
+
+ glBegin(GL_LINE_STRIP);
+ for (i=0; i<n; i++)
+ bgl_sphere_project(staticSine[n-i-1]*ax, staticSine[i]*az);
+ glEnd();
+}
+
+static void draw_pose_dofs(Object *ob)
+{
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+ Bone *bone;
+
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ bone= pchan->bone;
+
+ if ( (bone) && !(bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))) {
+ if (bone->flag & BONE_SELECTED) {
+ if (bone->layer & arm->layer) {
+ if (pchan->ikflag & (BONE_IK_XLIMIT|BONE_IK_ZLIMIT)) {
+ if (ED_pose_channel_in_IK_chain(ob, pchan)) {
+ float corner[4][3], posetrans[3], mat[4][4];
+ float phi=0.0f, theta=0.0f, scale;
+ int a, i;
+
+ /* in parent-bone pose, but own restspace */
+ glPushMatrix();
+
+ VECCOPY(posetrans, pchan->pose_mat[3]);
+ glTranslatef(posetrans[0], posetrans[1], posetrans[2]);
+
+ if (pchan->parent) {
+ Mat4CpyMat4(mat, pchan->parent->pose_mat);
+ mat[3][0]= mat[3][1]= mat[3][2]= 0.0f;
+ glMultMatrixf(mat);
+ }
+
+ Mat4CpyMat3(mat, pchan->bone->bone_mat);
+ glMultMatrixf(mat);
+
+ scale= bone->length*pchan->size[1];
+ glScalef(scale, scale, scale);
+
+ if (pchan->ikflag & BONE_IK_XLIMIT) {
+ if (pchan->ikflag & BONE_IK_ZLIMIT) {
+ float amin[3], amax[3];
+
+ for (i=0; i<3; i++) {
+ amin[i]= (float)sin(pchan->limitmin[i]*M_PI/360.0);
+ amax[i]= (float)sin(pchan->limitmax[i]*M_PI/360.0);
+ }
+
+ glScalef(1.0f, -1.0f, 1.0f);
+ if ((amin[0] != 0.0f) && (amin[2] != 0.0f))
+ draw_dof_ellipse(amin[0], amin[2]);
+ if ((amin[0] != 0.0f) && (amax[2] != 0.0f))
+ draw_dof_ellipse(amin[0], amax[2]);
+ if ((amax[0] != 0.0f) && (amin[2] != 0.0f))
+ draw_dof_ellipse(amax[0], amin[2]);
+ if ((amax[0] != 0.0f) && (amax[2] != 0.0f))
+ draw_dof_ellipse(amax[0], amax[2]);
+ glScalef(1.0f, -1.0f, 1.0f);
+ }
+ }
+
+ /* arcs */
+ if (pchan->ikflag & BONE_IK_ZLIMIT) {
+ theta= 0.5f*(pchan->limitmin[2]+pchan->limitmax[2]);
+ glRotatef(theta, 0.0f, 0.0f, 1.0f);
+
+ glColor3ub(50, 50, 255); // blue, Z axis limit
+ glBegin(GL_LINE_STRIP);
+ for (a=-16; a<=16; a++) {
+ float fac= ((float)a)/16.0f;
+
+ phi= fac * (float)(M_PI/360.0f) * (pchan->limitmax[2] - pchan->limitmin[2]);
+
+ i= (a == -16) ? 0 : 1;
+ corner[i][0]= (float)sin(phi);
+ corner[i][1]= (float)cos(phi);
+ corner[i][2]= 0.0f;
+ glVertex3fv(corner[i]);
+ }
+ glEnd();
+
+ glRotatef(-theta, 0.0f, 0.0f, 1.0f);
+ }
+
+ if (pchan->ikflag & BONE_IK_XLIMIT) {
+ theta= 0.5f * (pchan->limitmin[0] + pchan->limitmax[0]);
+ glRotatef(theta, 1.0f, 0.0f, 0.0f);
+
+ glColor3ub(255, 50, 50); // Red, X axis limit
+ glBegin(GL_LINE_STRIP);
+ for (a=-16; a<=16; a++) {
+ float fac= ((float)a)/16.0f;
+ phi= (float)(0.5*M_PI) + fac * (float)(M_PI/360.0f) * (pchan->limitmax[0] - pchan->limitmin[0]);
+
+ i= (a == -16) ? 2 : 3;
+ corner[i][0]= 0.0f;
+ corner[i][1]= (float)sin(phi);
+ corner[i][2]= (float)cos(phi);
+ glVertex3fv(corner[i]);
+ }
+ glEnd();
+
+ glRotatef(-theta, 1.0f, 0.0f, 0.0f);
+ }
+
+ /* out of cone, out of bone */
+ glPopMatrix();
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/* assumes object is Armature with pose */
+static void draw_pose_channels(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt)
+{
+ Object *ob= base->object;
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+ Bone *bone;
+ GLfloat tmp;
+ float smat[4][4], imat[4][4];
+ int index= -1;
+ short do_dashed= 3, draw_wire= 0;
+ short flag, constflag;
+
+ /* hacky... prevent outline select from drawing dashed helplines */
+ glGetFloatv(GL_LINE_WIDTH, &tmp);
+ if (tmp > 1.1) do_dashed &= ~1;
+ if (v3d->flag & V3D_HIDE_HELPLINES) do_dashed &= ~2;
+
+ /* precalc inverse matrix for drawing screen aligned */
+ if (arm->drawtype==ARM_ENVELOPE) {
+ /* precalc inverse matrix for drawing screen aligned */
+ wmGetMatrix(smat);
+ Mat4MulFloat3(smat[0], 1.0f/VecLength(ob->obmat[0]));
+ Mat4Invert(imat, smat);
+
+ /* and draw blended distances */
+ if (arm->flag & ARM_POSEMODE) {
+ glEnable(GL_BLEND);
+ //glShadeModel(GL_SMOOTH);
+
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ bone= pchan->bone;
+ if (bone && !(bone->flag & (BONE_HIDDEN_P|BONE_NO_DEFORM|BONE_HIDDEN_PG))) {
+ if (bone->flag & (BONE_SELECTED)) {
+ if (bone->layer & arm->layer)
+ draw_sphere_bone_dist(smat, imat, bone->flag, pchan, NULL);
+ }
+ }
+ }
+
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ glDisable(GL_BLEND);
+ //glShadeModel(GL_FLAT);
+ }
+ }
+
+ /* little speedup, also make sure transparent only draws once */
+ glCullFace(GL_BACK);
+ glEnable(GL_CULL_FACE);
+
+ /* if solid we draw that first, with selection codes, but without names, axes etc */
+ if (dt > OB_WIRE) {
+ if (arm->flag & ARM_POSEMODE)
+ index= base->selcol;
+
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ bone= pchan->bone;
+
+ if ( (bone) && !(bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG)) ) {
+ if (bone->layer & arm->layer) {
+ glPushMatrix();
+ glMultMatrixf(pchan->pose_mat);
+
+ /* catch exception for bone with hidden parent */
+ flag= bone->flag;
+ if ( (bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG)) )
+ flag &= ~BONE_CONNECTED;
+
+ /* set color-set to use */
+ set_pchan_colorset(ob, pchan);
+
+ if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) {
+ /* if drawwire, don't try to draw in solid */
+ if (pchan->bone->flag & BONE_DRAWWIRE)
+ draw_wire= 1;
+ else
+ draw_custom_bone(scene, v3d, rv3d, pchan->custom, OB_SOLID, arm->flag, flag, index, bone->length);
+ }
+ else if (arm->drawtype==ARM_LINE)
+ ; /* nothing in solid */
+ else if (arm->drawtype==ARM_ENVELOPE)
+ draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
+ else if (arm->drawtype==ARM_B_BONE)
+ draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
+ else
+ draw_bone(OB_SOLID, arm->flag, flag, 0, index, bone->length);
+
+ glPopMatrix();
+ }
+ }
+
+ if (index!= -1)
+ index+= 0x10000; // pose bones count in higher 2 bytes only
+ }
+
+ /* very very confusing... but in object mode, solid draw, we cannot do glLoadName yet,
+ * stick bones and/or wire custom-shapes are drawn in next loop
+ */
+ if ((arm->drawtype != ARM_LINE) && (draw_wire == 0)) {
+ /* object tag, for bordersel optim */
+ glLoadName(index & 0xFFFF);
+ index= -1;
+ }
+ }
+
+ /* draw custom bone shapes as wireframes */
+ if ( !(arm->flag & ARM_NO_CUSTOM) &&
+ ((draw_wire) || (dt <= OB_WIRE)) )
+ {
+ if (arm->flag & ARM_POSEMODE)
+ index= base->selcol;
+
+ /* only draw custom bone shapes that need to be drawn as wires */
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ bone= pchan->bone;
+
+ if ((bone) && !(bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))) {
+ if (bone->layer & arm->layer) {
+ if (pchan->custom) {
+ if ((dt < OB_SOLID) || (bone->flag & BONE_DRAWWIRE)) {
+ glPushMatrix();
+ glMultMatrixf(pchan->pose_mat);
+
+ /* prepare colors */
+ if (arm->flag & ARM_POSEMODE)
+ set_pchan_colorset(ob, pchan);
+ else {
+ if ((scene->basact)==base) {
+ if (base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_ACTIVE);
+ else UI_ThemeColor(TH_WIRE);
+ }
+ else {
+ if (base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_SELECT);
+ else UI_ThemeColor(TH_WIRE);
+ }
+ }
+
+ /* catch exception for bone with hidden parent */
+ flag= bone->flag;
+ if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG)))
+ flag &= ~BONE_CONNECTED;
+
+ draw_custom_bone(scene, v3d, rv3d, pchan->custom, OB_WIRE, arm->flag, flag, index, bone->length);
+
+ glPopMatrix();
+ }
+ }
+ }
+ }
+
+ if (index != -1)
+ index+= 0x10000; // pose bones count in higher 2 bytes only
+ }
+
+ if (draw_wire) {
+ /* object tag, for bordersel optim */
+ glLoadName(index & 0xFFFF);
+ index= -1;
+ }
+ }
+
+ /* wire draw over solid only in posemode */
+ if ((dt <= OB_WIRE) || (arm->flag & ARM_POSEMODE) || (arm->drawtype==ARM_LINE)) {
+ /* draw line check first. we do selection indices */
+ if (arm->drawtype==ARM_LINE) {
+ if (arm->flag & ARM_POSEMODE)
+ index= base->selcol;
+ }
+ /* if solid && posemode, we draw again with polygonoffset */
+ else if ((dt > OB_WIRE) && (arm->flag & ARM_POSEMODE)) {
+ bglPolygonOffset(rv3d->dist, 1.0);
+ }
+ else {
+ /* and we use selection indices if not done yet */
+ if (arm->flag & ARM_POSEMODE)
+ index= base->selcol;
+ }
+
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ bone= pchan->bone;
+
+ if ((bone) && !(bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))) {
+ if (bone->layer & arm->layer) {
+ if ((do_dashed & 1) && (bone->parent)) {
+ /* Draw a line from our root to the parent's tip
+ * - only if V3D_HIDE_HELPLINES is enabled...
+ */
+ if ( (do_dashed & 2) && ((bone->flag & BONE_CONNECTED)==0) ) {
+ if (arm->flag & ARM_POSEMODE) {
+ glLoadName(index & 0xFFFF); // object tag, for bordersel optim
+ UI_ThemeColor(TH_WIRE);
+ }
+ setlinestyle(3);
+ glBegin(GL_LINES);
+ glVertex3fv(pchan->pose_head);
+ glVertex3fv(pchan->parent->pose_tail);
+ glEnd();
+ setlinestyle(0);
+ }
+
+ /* Draw a line to IK root bone
+ * - only if temporary chain (i.e. "autoik")
+ */
+ if (arm->flag & ARM_POSEMODE) {
+ if (pchan->constflag & PCHAN_HAS_IK) {
+ if (bone->flag & BONE_SELECTED) {
+ if (pchan->constflag & PCHAN_HAS_TARGET) glColor3ub(200, 120, 0);
+ else glColor3ub(200, 200, 50); // add theme!
+
+ glLoadName(index & 0xFFFF);
+ pchan_draw_IK_root_lines(pchan, !(do_dashed & 2));
+ }
+ }
+ }
+ }
+
+ glPushMatrix();
+ if (arm->drawtype != ARM_ENVELOPE)
+ glMultMatrixf(pchan->pose_mat);
+
+ /* catch exception for bone with hidden parent */
+ flag= bone->flag;
+ if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG)))
+ flag &= ~BONE_CONNECTED;
+
+ /* extra draw service for pose mode */
+ constflag= pchan->constflag;
+ if (pchan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)) // XXX this is useless crap
+ constflag |= PCHAN_HAS_ACTION;
+ if (pchan->flag & POSE_STRIDE)
+ constflag |= PCHAN_HAS_STRIDE;
+
+ /* set color-set to use */
+ set_pchan_colorset(ob, pchan);
+
+ if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM))
+ ; // custom bone shapes should not be drawn here!
+ else if (arm->drawtype==ARM_ENVELOPE) {
+ if (dt < OB_SOLID)
+ draw_sphere_bone_wire(smat, imat, arm->flag, flag, constflag, index, pchan, NULL);
+ }
+ else if (arm->drawtype==ARM_LINE)
+ draw_line_bone(arm->flag, flag, constflag, index, pchan, NULL);
+ else if (arm->drawtype==ARM_B_BONE)
+ draw_b_bone(OB_WIRE, arm->flag, flag, constflag, index, pchan, NULL);
+ else
+ draw_bone(OB_WIRE, arm->flag, flag, constflag, index, bone->length);
+
+ glPopMatrix();
+ }
+ }
+
+ /* pose bones count in higher 2 bytes only */
+ if (index != -1)
+ index+= 0x10000;
+ }
+ /* restore things */
+ if ((arm->drawtype!=ARM_LINE)&& (dt>OB_WIRE) && (arm->flag & ARM_POSEMODE))
+ bglPolygonOffset(rv3d->dist, 0.0);
+ }
+
+ /* restore */
+ glDisable(GL_CULL_FACE);
+
+ /* draw DoFs */
+ if (arm->flag & ARM_POSEMODE)
+ draw_pose_dofs(ob);
+
+ /* finally names and axes */
+ if (arm->flag & (ARM_DRAWNAMES|ARM_DRAWAXES)) {
+ /* patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing */
+ if ((G.f & G_PICKSEL) == 0) {
+ float vec[3];
+
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+
+ for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+ if ((pchan->bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))==0) {
+ if (pchan->bone->layer & arm->layer) {
+ if (arm->flag & (ARM_EDITMODE|ARM_POSEMODE)) {
+ bone= pchan->bone;
+
+ if (bone->flag & BONE_SELECTED) UI_ThemeColor(TH_TEXT_HI);
+ else UI_ThemeColor(TH_TEXT);
+ }
+ else if (dt > OB_WIRE)
+ UI_ThemeColor(TH_TEXT);
+
+ /* Draw names of bone */
+ if (arm->flag & ARM_DRAWNAMES) {
+ VecMidf(vec, pchan->pose_head, pchan->pose_tail);
+ glRasterPos3fv(vec);
+ BMF_DrawString(G.font, " ");
+ BMF_DrawString(G.font, pchan->name);
+ }
+
+ /* Draw additional axes on the bone tail */
+ if ( (arm->flag & ARM_DRAWAXES) && (arm->flag & ARM_POSEMODE) ) {
+ glPushMatrix();
+ glMultMatrixf(pchan->pose_mat);
+ glTranslatef(0.0f, pchan->bone->length, 0.0f);
+ drawaxes(0.25f*pchan->bone->length, 0, OB_ARROWS);
+ glPopMatrix();
+ }
+ }
+ }
+ }
+
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ }
+ }
+}
+
+/* in editmode, we don't store the bone matrix... */
+static void set_matrix_editbone(EditBone *eBone)
+{
+ float delta[3],offset[3];
+ float mat[3][3], bmat[4][4];
+
+ /* Compose the parent transforms (i.e. their translations) */
+ VECCOPY(offset, eBone->head);
+
+ glTranslatef(offset[0],offset[1],offset[2]);
+
+ VecSubf(delta, eBone->tail, eBone->head);
+
+ eBone->length = (float)sqrt(delta[0]*delta[0] + delta[1]*delta[1] +delta[2]*delta[2]);
+
+ vec_roll_to_mat3(delta, eBone->roll, mat);
+ Mat4CpyMat3(bmat, mat);
+
+ glMultMatrixf(bmat);
+
+}
+
+static void draw_ebones(View3D *v3d, RegionView3D *rv3d, Object *ob, int dt)
+{
+ EditBone *eBone;
+ bArmature *arm= ob->data;
+ float smat[4][4], imat[4][4];
+ unsigned int index;
+ int flag;
+
+ /* envelope (deform distance) */
+ if(arm->drawtype==ARM_ENVELOPE) {
+ /* precalc inverse matrix for drawing screen aligned */
+ wmGetMatrix(smat);
+ Mat4MulFloat3(smat[0], 1.0f/VecLength(ob->obmat[0]));
+ Mat4Invert(imat, smat);
+
+ /* and draw blended distances */
+ glEnable(GL_BLEND);
+ //glShadeModel(GL_SMOOTH);
+
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+
+ for (eBone=arm->edbo->first, index=0; eBone; eBone=eBone->next, index++) {
+ if (eBone->layer & arm->layer) {
+ if ((eBone->flag & (BONE_HIDDEN_A|BONE_NO_DEFORM))==0) {
+ if (eBone->flag & (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL))
+ draw_sphere_bone_dist(smat, imat, eBone->flag, NULL, eBone);
+ }
+ }
+ }
+
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ glDisable(GL_BLEND);
+ //glShadeModel(GL_FLAT);
+ }
+
+ /* if solid we draw it first */
+ if ((dt > OB_WIRE) && (arm->drawtype!=ARM_LINE)) {
+ index= 0;
+ for (eBone=arm->edbo->first, index=0; eBone; eBone=eBone->next, index++) {
+ if (eBone->layer & arm->layer) {
+ if ((eBone->flag & BONE_HIDDEN_A)==0) {
+ glPushMatrix();
+ set_matrix_editbone(eBone);
+
+ /* catch exception for bone with hidden parent */
+ flag= eBone->flag;
+ if ( (eBone->parent) && ((eBone->parent->flag & BONE_HIDDEN_A) || (eBone->parent->layer & arm->layer)==0) )
+ flag &= ~BONE_CONNECTED;
+
+ if (arm->drawtype==ARM_ENVELOPE)
+ draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
+ else if(arm->drawtype==ARM_B_BONE)
+ draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
+ else {
+ draw_bone(OB_SOLID, arm->flag, flag, 0, index, eBone->length);
+ }
+
+ glPopMatrix();
+ }
+ }
+ }
+ }
+
+ /* if wire over solid, set offset */
+ index= -1;
+ glLoadName(-1);
+ if (arm->drawtype==ARM_LINE) {
+ if(G.f & G_PICKSEL)
+ index= 0;
+ }
+ else if (dt > OB_WIRE)
+ bglPolygonOffset(rv3d->dist, 1.0f);
+ else if (arm->flag & ARM_EDITMODE)
+ index= 0; /* do selection codes */
+
+ for (eBone=arm->edbo->first; eBone; eBone=eBone->next) {
+ if (eBone->layer & arm->layer) {
+ if ((eBone->flag & BONE_HIDDEN_A)==0) {
+
+ /* catch exception for bone with hidden parent */
+ flag= eBone->flag;
+ if ( (eBone->parent) && ((eBone->parent->flag & BONE_HIDDEN_A) || (eBone->parent->layer & arm->layer)==0) )
+ flag &= ~BONE_CONNECTED;
+
+ if (arm->drawtype == ARM_ENVELOPE) {
+ if (dt < OB_SOLID)
+ draw_sphere_bone_wire(smat, imat, arm->flag, flag, 0, index, NULL, eBone);
+ }
+ else {
+ glPushMatrix();
+ set_matrix_editbone(eBone);
+
+ if (arm->drawtype == ARM_LINE)
+ draw_line_bone(arm->flag, flag, 0, index, NULL, eBone);
+ else if (arm->drawtype == ARM_B_BONE)
+ draw_b_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone);
+ else
+ draw_bone(OB_WIRE, arm->flag, flag, 0, index, eBone->length);
+
+ glPopMatrix();
+ }
+
+ /* offset to parent */
+ if (eBone->parent) {
+ UI_ThemeColor(TH_WIRE);
+ glLoadName (-1); // -1 here is OK!
+ setlinestyle(3);
+
+ glBegin(GL_LINES);
+ glVertex3fv(eBone->parent->tail);
+ glVertex3fv(eBone->head);
+ glEnd();
+
+ setlinestyle(0);
+ }
+ }
+ }
+ if(index!=-1) index++;
+ }
+
+ /* restore */
+ if (arm->drawtype==ARM_LINE);
+ else if (dt>OB_WIRE) bglPolygonOffset(rv3d->dist, 0.0f);
+
+ /* finally names and axes */
+ if (arm->flag & (ARM_DRAWNAMES|ARM_DRAWAXES)) {
+ // patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing
+ if ((G.f & G_PICKSEL) == 0) {
+ float vec[3];
+
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+
+ for (eBone=arm->edbo->first, index=0; eBone; eBone=eBone->next, index++) {
+ if(eBone->layer & arm->layer) {
+ if ((eBone->flag & BONE_HIDDEN_A)==0) {
+
+ if (eBone->flag & BONE_SELECTED) UI_ThemeColor(TH_TEXT_HI);
+ else UI_ThemeColor(TH_TEXT);
+
+ /* Draw name */
+ if (arm->flag & ARM_DRAWNAMES) {
+ VecMidf(vec, eBone->head, eBone->tail);
+ glRasterPos3fv(vec);
+ BMF_DrawString(G.font, " ");
+ BMF_DrawString(G.font, eBone->name);
+ }
+ /* Draw additional axes */
+ if (arm->flag & ARM_DRAWAXES) {
+ glPushMatrix();
+ set_matrix_editbone(eBone);
+ glTranslatef(0.0f, eBone->length, 0.0f);
+ drawaxes(eBone->length*0.25f, 0, OB_ARROWS);
+ glPopMatrix();
+ }
+
+ }
+ }
+ }
+
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ }
+ }
+}
+
+/* ****************************** Armature Visualisation ******************************** */
+
+/* ---------- Paths --------- */
+
+/* draw bone paths
+ * - in view space
+ */
+static void draw_pose_paths(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
+{
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+ // bAction *act; // XXX old animsys - watch it!
+ // bActionChannel *achan;
+ ActKeyColumn *ak;
+ ListBase keys;
+ float *fp, *fp_start;
+ int a, stepsize;
+ int sfra, efra, len;
+
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+
+ glPushMatrix();
+ glLoadMatrixf(rv3d->viewmat);
+
+ /* version patch here - cannot access frame info from file reading */
+ if (arm->pathsize == 0) arm->pathsize= 1;
+ stepsize = arm->pathsize;
+
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (pchan->bone->layer & arm->layer) {
+ if (pchan->path) {
+ /* version patch here - cannot access frame info from file reading */
+ if ((pchan->pathsf == 0) || (pchan->pathef == 0)) {
+ pchan->pathsf= SFRA;
+ pchan->pathef= EFRA;
+ }
+
+ /* get frame ranges */
+ if (arm->pathflag & ARM_PATH_ACFRA) {
+ int sind;
+
+ /* With "Around Current", we only choose frames from around
+ * the current frame to draw. However, this range is still
+ * restricted by the limits of the original path.
+ */
+ sfra= CFRA - arm->pathbc;
+ efra= CFRA + arm->pathac;
+ if (sfra < pchan->pathsf) sfra= pchan->pathsf;
+ if (efra > pchan->pathef) efra= pchan->pathef;
+
+ len= efra - sfra;
+
+ sind= sfra - pchan->pathsf;
+ fp_start= (pchan->path + (3*sind));
+ }
+ else {
+ sfra= pchan->pathsf;
+ efra = sfra + pchan->pathlen;
+ len = pchan->pathlen;
+ fp_start = pchan->path;
+ }
+
+ /* draw curve-line of path */
+ glShadeModel(GL_SMOOTH);
+
+ glBegin(GL_LINE_STRIP);
+ for (a=0, fp=fp_start; a<len; a++, fp+=3) {
+ float intensity; /* how faint */
+
+ /* set color
+ * - more intense for active/selected bones, less intense for unselected bones
+ * - black for before current frame, green for current frame, blue for after current frame
+ * - intensity decreases as distance from current frame increases
+ */
+ #define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max-min)) + min)
+ if ((a+sfra) < CFRA) {
+ /* black - before cfra */
+ if (pchan->bone->flag & BONE_SELECTED) {
+ // intensity= 0.5f;
+ intensity = SET_INTENSITY(sfra, a, CFRA, 0.25f, 0.75f);
+ }
+ else {
+ //intensity= 0.8f;
+ intensity = SET_INTENSITY(sfra, a, CFRA, 0.68f, 0.92f);
+ }
+ UI_ThemeColorBlend(TH_WIRE, TH_BACK, intensity);
+ }
+ else if ((a+sfra) > CFRA) {
+ /* blue - after cfra */
+ if (pchan->bone->flag & BONE_SELECTED) {
+ //intensity = 0.5f;
+ intensity = SET_INTENSITY(CFRA, a, efra, 0.25f, 0.75f);
+ }
+ else {
+ //intensity = 0.8f;
+ intensity = SET_INTENSITY(CFRA, a, efra, 0.68f, 0.92f);
+ }
+ UI_ThemeColorBlend(TH_BONE_POSE, TH_BACK, intensity);
+ }
+ else {
+ /* green - on cfra */
+ if (pchan->bone->flag & BONE_SELECTED) {
+ intensity= 0.5f;
+ }
+ else {
+ intensity= 0.99f;
+ }
+ UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10);
+ }
+
+ /* draw a vertex with this color */
+ glVertex3fv(fp);
+ }
+
+ glEnd();
+ glShadeModel(GL_FLAT);
+
+ glPointSize(1.0);
+
+ /* draw little black point at each frame
+ * NOTE: this is not really visible/noticable
+ */
+ glBegin(GL_POINTS);
+ for (a=0, fp=fp_start; a<len; a++, fp+=3)
+ glVertex3fv(fp);
+ glEnd();
+
+ /* Draw little white dots at each framestep value */
+ UI_ThemeColor(TH_TEXT_HI);
+ glBegin(GL_POINTS);
+ for (a=0, fp=fp_start; a<len; a+=stepsize, fp+=(stepsize*3))
+ glVertex3fv(fp);
+ glEnd();
+
+ /* Draw frame numbers at each framestep value */
+ if (arm->pathflag & ARM_PATH_FNUMS) {
+ for (a=0, fp=fp_start; a<len; a+=stepsize, fp+=(stepsize*3)) {
+ char str[32];
+
+ /* only draw framenum if several consecutive highlighted points don't occur on same point */
+ if (a == 0) {
+ glRasterPos3fv(fp);
+ sprintf(str, " %d\n", (a+sfra));
+ BMF_DrawString(G.font, str);
+ }
+ else if ((a > stepsize) && (a < len-stepsize)) {
+ if ((VecEqual(fp, fp-(stepsize*3))==0) || (VecEqual(fp, fp+(stepsize*3))==0)) {
+ glRasterPos3fv(fp);
+ sprintf(str, " %d\n", (a+sfra));
+ BMF_DrawString(G.font, str);
+ }
+ }
+ }
+ }
+
+ /* Keyframes - dots and numbers */
+ if (arm->pathflag & ARM_PATH_KFRAS) {
+ /* build list of all keyframes in active action for pchan */
+ keys.first = keys.last = NULL;
+
+ #if 0 // XXX old animation system
+ act= ob->action;
+ if (act) {
+ achan= get_action_channel(act, pchan->name);
+ if (achan)
+ ipo_to_keylist(achan->ipo, &keys, NULL, NULL);
+ }
+ #endif // XXX old animation system
+
+ /* Draw slightly-larger yellow dots at each keyframe */
+ UI_ThemeColor(TH_VERTEX_SELECT);
+ glPointSize(5.0f);
+
+ glBegin(GL_POINTS);
+ for (a=0, fp=fp_start; a<len; a++, fp+=3) {
+ for (ak= keys.first; ak; ak= ak->next) {
+ if (ak->cfra == (a+sfra))
+ glVertex3fv(fp);
+ }
+ }
+ glEnd();
+
+ glPointSize(1.0f);
+
+ /* Draw frame numbers of keyframes */
+ if ((arm->pathflag & ARM_PATH_FNUMS) || (arm->pathflag & ARM_PATH_KFNOS)) {
+ for(a=0, fp=fp_start; a<len; a++, fp+=3) {
+ for (ak= keys.first; ak; ak= ak->next) {
+ if (ak->cfra == (a+sfra)) {
+ char str[32];
+
+ glRasterPos3fv(fp);
+ sprintf(str, " %d\n", (a+sfra));
+ BMF_DrawString(G.font, str);
+ }
+ }
+ }
+ }
+
+ BLI_freelistN(&keys);
+ }
+ }
+ }
+ }
+
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ glPopMatrix();
+}
+
+
+/* ---------- Ghosts --------- */
+
+/* helper function for ghost drawing - sets/removes flags for temporarily
+ * hiding unselected bones while drawing ghosts
+ */
+static void ghost_poses_tag_unselected(Object *ob, short unset)
+{
+ bArmature *arm= ob->data;
+ bPose *pose= ob->pose;
+ bPoseChannel *pchan;
+
+ /* don't do anything if no hiding any bones */
+ if ((arm->flag & ARM_GHOST_ONLYSEL)==0)
+ return;
+
+ /* loop over all pchans, adding/removing tags as appropriate */
+ for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
+ if (unset) {
+ /* remove tags from all pchans if cleaning up */
+ pchan->bone->flag &= ~BONE_HIDDEN_PG;
+ }
+ else {
+ /* set tags on unselected pchans only */
+ if ((pchan->bone->flag & BONE_SELECTED)==0)
+ pchan->bone->flag |= BONE_HIDDEN_PG;
+ }
+ }
+ }
+}
+
+/* draw ghosts that occur within a frame range
+ * note: object should be in posemode
+ */
+static void draw_ghost_poses_range(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base)
+{
+ Object *ob= base->object;
+ bArmature *arm= ob->data;
+ bPose *posen, *poseo;
+ float start, end, stepsize, range, colfac;
+ int cfrao, flago, ipoflago;
+
+ start = (float)arm->ghostsf;
+ end = (float)arm->ghostef;
+ if (end <= start)
+ return;
+
+ stepsize= (float)(arm->ghostsize);
+ range= (float)(end - start);
+
+ /* store values */
+ ob->flag &= ~OB_POSEMODE;
+ cfrao= CFRA;
+ flago= arm->flag;
+ arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
+ ipoflago= ob->ipoflag;
+ ob->ipoflag |= OB_DISABLE_PATH;
+
+ /* copy the pose */
+ poseo= ob->pose;
+ copy_pose(&posen, ob->pose, 1);
+ ob->pose= posen;
+ armature_rebuild_pose(ob, ob->data); /* child pointers for IK */
+ ghost_poses_tag_unselected(ob, 0); /* hide unselected bones if need be */
+
+ glEnable(GL_BLEND);
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+
+ /* draw from first frame of range to last */
+ for (CFRA= (int)start; CFRA < end; CFRA += (int)stepsize) {
+ colfac = (end - (float)CFRA) / range;
+ UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
+
+ //do_all_pose_actions(scene, ob); // XXX old animation system
+ where_is_pose(scene, ob);
+ draw_pose_channels(scene, v3d, rv3d, base, OB_WIRE);
+ }
+ glDisable(GL_BLEND);
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+
+ ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */
+ free_pose(posen);
+
+ /* restore */
+ CFRA= cfrao;
+ ob->pose= poseo;
+ arm->flag= flago;
+ armature_rebuild_pose(ob, ob->data);
+ ob->flag |= OB_POSEMODE;
+ ob->ipoflag= ipoflago;
+}
+
+/* draw ghosts on keyframes in action within range
+ * - object should be in posemode
+ */
+static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base)
+{
+ Object *ob= base->object;
+ bAction *act= ob->action; // XXX old animsys stuff... watch it!
+ bArmature *arm= ob->data;
+ bPose *posen, *poseo;
+ ListBase keys= {NULL, NULL};
+ ActKeysInc aki = {0, 0, 0};
+ ActKeyColumn *ak, *akn;
+ float start, end, range, colfac, i;
+ int cfrao, flago;
+
+ aki.start= start = (float)arm->ghostsf;
+ aki.end= end = (float)arm->ghostef;
+ if (end <= start)
+ return;
+
+ /* get keyframes - then clip to only within range */
+ action_to_keylist(act, &keys, NULL, &aki);
+ range= 0;
+ for (ak= keys.first; ak; ak= akn) {
+ akn= ak->next;
+
+ if ((ak->cfra < start) || (ak->cfra > end))
+ BLI_freelinkN(&keys, ak);
+ else
+ range++;
+ }
+ if (range == 0) return;
+
+ /* store values */
+ ob->flag &= ~OB_POSEMODE;
+ cfrao= CFRA;
+ flago= arm->flag;
+ arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
+ ob->ipoflag |= OB_DISABLE_PATH;
+
+ /* copy the pose */
+ poseo= ob->pose;
+ copy_pose(&posen, ob->pose, 1);
+ ob->pose= posen;
+ armature_rebuild_pose(ob, ob->data); /* child pointers for IK */
+ ghost_poses_tag_unselected(ob, 0); /* hide unselected bones if need be */
+
+ glEnable(GL_BLEND);
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+
+ /* draw from first frame of range to last */
+ for (ak=keys.first, i=0; ak; ak=ak->next, i++) {
+ colfac = i/range;
+ UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
+
+ CFRA= (int)ak->cfra;
+
+ //do_all_pose_actions(scene, ob); // XXX old animation system
+ where_is_pose(scene, ob);
+ draw_pose_channels(scene, v3d, rv3d, base, OB_WIRE);
+ }
+ glDisable(GL_BLEND);
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+
+ ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */
+ BLI_freelistN(&keys);
+ free_pose(posen);
+
+ /* restore */
+ CFRA= cfrao;
+ ob->pose= poseo;
+ arm->flag= flago;
+ armature_rebuild_pose(ob, ob->data);
+ ob->flag |= OB_POSEMODE;
+}
+
+/* draw ghosts around current frame
+ * - object is supposed to be armature in posemode
+ */
+static void draw_ghost_poses(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base)
+{
+ Object *ob= base->object;
+ bArmature *arm= ob->data;
+ bPose *posen, *poseo;
+ //bActionStrip *strip;
+ float cur, start, end, stepsize, range, colfac, actframe, ctime;
+ int cfrao, maptime, flago;
+
+ /* pre conditions, get an action with sufficient frames */
+ //if (ob->action==NULL)
+ // return;
+
+ calc_action_range(ob->action, &start, &end, 0);
+ if (start == end)
+ return;
+
+ stepsize= (float)(arm->ghostsize);
+ range= (float)(arm->ghostep)*stepsize + 0.5f; /* plus half to make the for loop end correct */
+
+#if 0 // XXX old animation system
+ /* we only map time for armature when an active strip exists */
+ for (strip=ob->nlastrips.first; strip; strip=strip->next)
+ if (strip->flag & ACTSTRIP_ACTIVE)
+ break;
+#endif // XXX old animsys
+
+ //maptime= (strip!=NULL);
+ maptime= 0;
+
+ /* store values */
+ ob->flag &= ~OB_POSEMODE;
+ cfrao= CFRA;
+ if (maptime) actframe= get_action_frame(ob, (float)CFRA);
+ else actframe= (float)CFRA;
+ flago= arm->flag;
+ arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
+
+ /* copy the pose */
+ poseo= ob->pose;
+ copy_pose(&posen, ob->pose, 1);
+ ob->pose= posen;
+ armature_rebuild_pose(ob, ob->data); /* child pointers for IK */
+ ghost_poses_tag_unselected(ob, 0); /* hide unselected bones if need be */
+
+ glEnable(GL_BLEND);
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+
+ /* draw from darkest blend to lowest */
+ for(cur= stepsize; cur<range; cur+=stepsize) {
+ ctime= cur - (float)fmod(cfrao, stepsize); /* ensures consistant stepping */
+ colfac= ctime/range;
+ UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
+
+ /* only within action range */
+ if (actframe+ctime >= start && actframe+ctime <= end) {
+ if (maptime) CFRA= (int)get_action_frame_inv(ob, actframe+ctime);
+ else CFRA= (int)floor(actframe+ctime);
+
+ if (CFRA != cfrao) {
+ //do_all_pose_actions(scene, ob); // xxx old animation system crap
+ where_is_pose(scene, ob);
+ draw_pose_channels(scene, v3d, rv3d, base, OB_WIRE);
+ }
+ }
+
+ ctime= cur + (float)fmod((float)cfrao, stepsize) - stepsize+1.0f; /* ensures consistant stepping */
+ colfac= ctime/range;
+ UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
+
+ /* only within action range */
+ if ((actframe-ctime >= start) && (actframe-ctime <= end)) {
+ if (maptime) CFRA= (int)get_action_frame_inv(ob, actframe-ctime);
+ else CFRA= (int)floor(actframe-ctime);
+
+ if (CFRA != cfrao) {
+ //do_all_pose_actions(scene, ob); // XXX old animation system crap...
+ where_is_pose(scene, ob);
+ draw_pose_channels(scene, v3d, rv3d, base, OB_WIRE);
+ }
+ }
+ }
+ glDisable(GL_BLEND);
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+
+ ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */
+ free_pose(posen);
+
+ /* restore */
+ CFRA= cfrao;
+ ob->pose= poseo;
+ arm->flag= flago;
+ armature_rebuild_pose(ob, ob->data);
+ ob->flag |= OB_POSEMODE;
+}
+
+/* ********************************** Armature Drawing - Main ************************* */
+
+/* called from drawobject.c, return 1 if nothing was drawn */
+int draw_armature(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
+{
+ Object *ob= base->object;
+ bArmature *arm= ob->data;
+ int retval= 0;
+
+ if(G.f & G_RENDER_SHADOW)
+ return 1;
+
+ if(dt>OB_WIRE && arm->drawtype!=ARM_LINE) {
+ /* we use color for solid lighting */
+ glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
+ glEnable(GL_COLOR_MATERIAL);
+ glColor3ub(0,0,0); // clear spec
+ glDisable(GL_COLOR_MATERIAL);
+
+ glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+ glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); // only for lighting...
+ }
+
+ /* arm->flag is being used to detect mode... */
+ /* editmode? */
+ if(arm->edbo) {
+ arm->flag |= ARM_EDITMODE;
+ draw_ebones(v3d, rv3d, ob, dt);
+ arm->flag &= ~ARM_EDITMODE;
+ }
+ else{
+ /* Draw Pose */
+ if(ob->pose && ob->pose->chanbase.first) {
+ /* drawing posemode selection indices or colors only in these cases */
+ if(!(base->flag & OB_FROMDUPLI)) {
+ if(G.f & G_PICKSEL) {
+ if(ob->flag & OB_POSEMODE)
+ arm->flag |= ARM_POSEMODE;
+ }
+ else if(ob->flag & OB_POSEMODE) {
+ if (arm->ghosttype == ARM_GHOST_RANGE) {
+ draw_ghost_poses_range(scene, v3d, rv3d, base);
+ }
+ else if (arm->ghosttype == ARM_GHOST_KEYS) {
+ draw_ghost_poses_keys(scene, v3d, rv3d, base);
+ }
+ else if (arm->ghosttype == ARM_GHOST_CUR) {
+ if (arm->ghostep)
+ draw_ghost_poses(scene, v3d, rv3d, base);
+ }
+ if ((flag & DRAW_SCENESET)==0) {
+ if(ob==OBACT)
+ arm->flag |= ARM_POSEMODE;
+ else if(G.f & G_WEIGHTPAINT) {
+ if(OBACT && ob==modifiers_isDeformedByArmature(OBACT))
+ arm->flag |= ARM_POSEMODE;
+ }
+ draw_pose_paths(scene, v3d, rv3d, ob);
+ }
+ }
+ }
+ draw_pose_channels(scene, v3d, rv3d, base, dt);
+ arm->flag &= ~ARM_POSEMODE;
+
+ if(ob->flag & OB_POSEMODE)
+ UI_ThemeColor(TH_WIRE); /* restore, for extra draw stuff */
+ }
+ else retval= 1;
+ }
+ /* restore */
+ glFrontFace(GL_CCW);
+
+ return retval;
+}
+
+/* *************** END Armature drawing ******************* */
+
+
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
new file mode 100644
index 00000000000..1807de9efbb
--- /dev/null
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -0,0 +1,590 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, full update, glsl support
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_edgehash.h"
+#include "BLI_editVert.h"
+
+#include "IMB_imbuf.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_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_property_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_bmfont.h"
+#include "BKE_displist.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_effect.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_property.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_resources.h"
+#include "UI_interface_icons.h"
+
+#include "GPU_extensions.h"
+#include "GPU_draw.h"
+
+#include "ED_mesh.h"
+
+#include "view3d_intern.h" // own include
+
+/***/
+
+ /* Flags for marked edges */
+enum {
+ eEdge_Visible = (1<<0),
+ eEdge_Select = (1<<1),
+};
+
+ /* Creates a hash of edges to flags indicating
+ * adjacent tface select/active/etc flags.
+ */
+static void get_marked_edge_info__orFlags(EdgeHash *eh, int v0, int v1, int flags)
+{
+ int *flags_p;
+
+ if (!BLI_edgehash_haskey(eh, v0, v1)) {
+ BLI_edgehash_insert(eh, v0, v1, 0);
+ }
+
+ flags_p = (int*) BLI_edgehash_lookup_p(eh, v0, v1);
+ *flags_p |= flags;
+}
+
+static EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me)
+{
+ EdgeHash *eh = BLI_edgehash_new();
+ int i;
+ MFace *mf;
+ MTFace *tf = NULL;
+
+ for (i=0; i<me->totface; i++) {
+ mf = &me->mface[i];
+ if (me->mtface)
+ tf = &me->mtface[i];
+
+ if (mf->v3) {
+ if (!(mf->flag&ME_HIDE)) {
+ unsigned int flags = eEdge_Visible;
+ if (mf->flag&ME_FACE_SEL) flags |= eEdge_Select;
+
+ get_marked_edge_info__orFlags(eh, mf->v1, mf->v2, flags);
+ get_marked_edge_info__orFlags(eh, mf->v2, mf->v3, flags);
+ if (mf->v4) {
+ get_marked_edge_info__orFlags(eh, mf->v3, mf->v4, flags);
+ get_marked_edge_info__orFlags(eh, mf->v4, mf->v1, flags);
+ } else {
+ get_marked_edge_info__orFlags(eh, mf->v3, mf->v1, flags);
+ }
+ }
+ }
+ }
+
+ return eh;
+}
+
+
+static int draw_tfaces3D__setHiddenOpts(void *userData, int index)
+{
+ struct { Mesh *me; EdgeHash *eh; } *data = userData;
+ Mesh *me= data->me;
+ MEdge *med = &me->medge[index];
+ uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
+
+ if((me->drawflag & ME_DRAWSEAMS) && (med->flag&ME_SEAM)) {
+ return 0;
+ } else if(me->drawflag & ME_DRAWEDGES){
+ if (me->drawflag & ME_HIDDENEDGES) {
+ return 1;
+ } else {
+ return (flags & eEdge_Visible);
+ }
+ } else {
+ return (flags & eEdge_Select);
+ }
+}
+
+static int draw_tfaces3D__setSeamOpts(void *userData, int index)
+{
+ struct { Mesh *me; EdgeHash *eh; } *data = userData;
+ Mesh *me= data->me;
+ MEdge *med = &data->me->medge[index];
+ uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
+
+ if (med->flag & ME_SEAM) {
+ if (me->drawflag & ME_HIDDENEDGES) {
+ return 1;
+ } else {
+ return (flags & eEdge_Visible);
+ }
+ } else {
+ return 0;
+ }
+}
+
+static int draw_tfaces3D__setSelectOpts(void *userData, int index)
+{
+ struct { Mesh *me; EdgeHash *eh; } *data = userData;
+ MEdge *med = &data->me->medge[index];
+ uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
+
+ return flags & eEdge_Select;
+}
+
+static int draw_tfaces3D__setActiveOpts(void *userData, int index)
+{
+ struct { Mesh *me; EdgeHash *eh; } *data = userData;
+ MEdge *med = &data->me->medge[index];
+ uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
+
+ if (flags & eEdge_Select) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int draw_tfaces3D__drawFaceOpts(void *userData, int index)
+{
+ Mesh *me = (Mesh*)userData;
+
+ MFace *mface = &me->mface[index];
+ if (!(mface->flag&ME_HIDE) && (mface->flag&ME_FACE_SEL))
+ return 2; /* Don't set color */
+ else
+ return 0;
+}
+
+static void draw_tfaces3D(RegionView3D *rv3d, Object *ob, Mesh *me, DerivedMesh *dm)
+{
+ struct { Mesh *me; EdgeHash *eh; } data;
+
+ data.me = me;
+ data.eh = get_tface_mesh_marked_edge_info(me);
+
+ glEnable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ bglPolygonOffset(rv3d->dist, 1.0);
+
+ /* Draw (Hidden) Edges */
+ UI_ThemeColor(TH_EDGE_FACESEL);
+ dm->drawMappedEdges(dm, draw_tfaces3D__setHiddenOpts, &data);
+
+ /* Draw Seams */
+ if(me->drawflag & ME_DRAWSEAMS) {
+ UI_ThemeColor(TH_EDGE_SEAM);
+ glLineWidth(2);
+
+ dm->drawMappedEdges(dm, draw_tfaces3D__setSeamOpts, &data);
+
+ glLineWidth(1);
+ }
+
+ /* Draw Selected Faces */
+ if(me->drawflag & ME_DRAWFACES) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ UI_ThemeColor4(TH_FACE_SELECT);
+
+ dm->drawMappedFacesTex(dm, draw_tfaces3D__drawFaceOpts, (void*)me);
+
+ glDisable(GL_BLEND);
+ }
+
+ bglPolygonOffset(rv3d->dist, 1.0);
+
+ /* Draw Stippled Outline for selected faces */
+ glColor3ub(255, 255, 255);
+ setlinestyle(1);
+ dm->drawMappedEdges(dm, draw_tfaces3D__setSelectOpts, &data);
+ setlinestyle(0);
+
+ dm->drawMappedEdges(dm, draw_tfaces3D__setActiveOpts, &data);
+
+ bglPolygonOffset(rv3d->dist, 0.0); // resets correctly now, even after calling accumulated offsets
+
+ BLI_edgehash_free(data.eh, NULL);
+}
+
+static Material *give_current_material_or_def(Object *ob, int matnr)
+{
+ extern Material defmaterial; // render module abuse...
+ Material *ma= give_current_material(ob, matnr);
+
+ return ma?ma:&defmaterial;
+}
+
+static int set_draw_settings_cached(int clearcache, int textured, MTFace *texface, int lit, Object *litob, int litmatnr, int doublesided)
+{
+ static int c_textured;
+ static int c_lit;
+ static int c_doublesided;
+ static MTFace *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= (MTFace*) -1;
+ c_litob= (Object*) -1;
+ c_litmatnr= -1;
+ c_badtex= 0;
+ }
+
+ if (texface) {
+ lit = lit && (lit==-1 || texface->mode&TF_LIGHT);
+ textured = textured && (texface->mode&TF_TEX);
+ doublesided = texface->mode&TF_TWOSIDE;
+ } else {
+ textured = 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= !GPU_set_tpage(texface);
+ } else {
+ GPU_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+1);
+ 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;
+}
+
+/* Icky globals, fix with userdata parameter */
+
+struct TextureDrawState {
+ Object *ob;
+ int islit, istex;
+ unsigned char obcol[4];
+} Gtexdraw = {NULL, 0, 0, {0, 0, 0, 0}};
+
+static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
+{
+ unsigned char obcol[4];
+ int istex, solidtex= 0;
+
+ // XXX scene->obedit warning
+ if(v3d->drawtype==OB_SOLID || (ob==scene->obedit && v3d->drawtype!=OB_TEXTURE)) {
+ /* draw with default lights in solid draw mode and edit mode */
+ solidtex= 1;
+ Gtexdraw.islit= -1;
+ }
+ else {
+ /* draw with lights in the scene otherwise */
+ Gtexdraw.islit= GPU_scene_object_lights(scene, ob, v3d->lay, rv3d->viewmat, get_view3d_ortho(v3d, rv3d));
+ }
+
+ 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);
+
+ glCullFace(GL_BACK); glEnable(GL_CULL_FACE);
+ if(solidtex || v3d->drawtype==OB_TEXTURE) istex= 1;
+ else istex= 0;
+
+ Gtexdraw.ob = ob;
+ Gtexdraw.istex = istex;
+ memcpy(Gtexdraw.obcol, obcol, sizeof(obcol));
+ set_draw_settings_cached(1, 0, 0, Gtexdraw.islit, 0, 0, 0);
+ glShadeModel(GL_SMOOTH);
+}
+
+static void draw_textured_end()
+{
+ /* switch off textures */
+ GPU_set_tpage(0);
+
+ glShadeModel(GL_FLAT);
+ glDisable(GL_CULL_FACE);
+
+ /* XXX, bad patch - GPU_default_lights() 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();
+ GPU_default_lights();
+ glPopMatrix();
+}
+
+
+static int draw_tface__set_draw(MTFace *tface, MCol *mcol, int matnr)
+{
+ if (tface && (tface->mode&TF_INVISIBLE)) return 0;
+
+ if (tface && set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, matnr, TF_TWOSIDE)) {
+ glColor3ub(0xFF, 0x00, 0xFF);
+ return 2; /* Don't set color */
+ } else if (tface && tface->mode&TF_OBCOL) {
+ glColor3ubv(Gtexdraw.obcol);
+ return 2; /* Don't set color */
+ } else if (!mcol) {
+ if (tface) glColor3f(1.0, 1.0, 1.0);
+ else {
+ Material *ma= give_current_material(Gtexdraw.ob, matnr+1);
+ if(ma) glColor3f(ma->r, ma->g, ma->b);
+ else glColor3f(1.0, 1.0, 1.0);
+ }
+ return 2; /* Don't set color */
+ } else {
+ return 1; /* Set color from mcol */
+ }
+}
+
+static int draw_tface_mapped__set_draw(void *userData, int index)
+{
+ Mesh *me = (Mesh*)userData;
+ MTFace *tface = (me->mtface)? &me->mtface[index]: NULL;
+ MFace *mface = (me->mface)? &me->mface[index]: NULL;
+ MCol *mcol = (me->mcol)? &me->mcol[index]: NULL;
+ int matnr = me->mface[index].mat_nr;
+ if (mface && mface->flag&ME_HIDE) return 0;
+ return draw_tface__set_draw(tface, mcol, matnr);
+}
+
+static int draw_em_tf_mapped__set_draw(void *userData, int index)
+{
+ EditMesh *em = userData;
+ EditFace *efa= EM_get_face_for_index(index);
+ MTFace *tface;
+ MCol *mcol;
+ int matnr;
+
+ if (efa==NULL || efa->h)
+ return 0;
+
+ tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
+ matnr = efa->mat_nr;
+
+ return draw_tface__set_draw(tface, mcol, matnr);
+}
+
+static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
+{
+ Mesh *me = (Mesh*)userData;
+ MTFace *tface = (me->mtface)? &me->mtface[index]: NULL;
+ MFace *mface = (me->mface)? &me->mface[index]: NULL;
+
+ if ((mface->flag&ME_HIDE) || (tface && (tface->mode&TF_INVISIBLE)))
+ return 0;
+
+ *drawSmooth_r = 1;
+ return 1;
+}
+
+void draw_mesh_text(Scene *scene, Object *ob, int glsl)
+{
+ Mesh *me = ob->data;
+ DerivedMesh *ddm;
+ MFace *mf, *mface= me->mface;
+ MTFace *tface= me->mtface;
+ MCol *mcol= me->mcol; /* why does mcol exist? */
+ bProperty *prop = get_ob_property(ob, "Text");
+ GPUVertexAttribs gattribs;
+ int a, totface= me->totface;
+
+ /* don't draw without tfaces */
+ if(!tface)
+ return;
+
+ /* don't draw when editing */
+ if(ob == scene->obedit)
+ return;
+ else if(ob==OBACT)
+ if(FACESEL_PAINT_TEST)
+ return;
+
+ ddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+
+ for(a=0, mf=mface; a<totface; a++, tface++, mf++) {
+ int mode= tface->mode;
+ int matnr= mf->mat_nr;
+ int mf_smooth= mf->flag & ME_SMOOTH;
+
+ if (!(mf->flag&ME_HIDE) && !(mode&TF_INVISIBLE) && (mode&TF_BMFONT)) {
+ float v1[3], v2[3], v3[3], v4[3];
+ char string[MAX_PROPSTRING];
+ int characters, i, glattrib= -1, badtex= 0;
+
+ if(glsl) {
+ GPU_enable_material(matnr+1, &gattribs);
+
+ for(i=0; i<gattribs.totlayer; i++) {
+ if(gattribs.layer[i].type == CD_MTFACE) {
+ glattrib = gattribs.layer[i].glindex;
+ break;
+ }
+ }
+ }
+ else {
+ badtex = set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, matnr, TF_TWOSIDE);
+ if (badtex) {
+ if (mcol) mcol+=4;
+ continue;
+ }
+ }
+
+ ddm->getVertCo(ddm, mf->v1, v1);
+ ddm->getVertCo(ddm, mf->v2, v2);
+ ddm->getVertCo(ddm, mf->v3, v3);
+ if (mf->v4) ddm->getVertCo(ddm, mf->v4, v4);
+
+ // The BM_FONT handling is in the gpu module, shared with the
+ // game engine, was duplicated previously
+
+ set_property_valstr(prop, string);
+ characters = strlen(string);
+
+ if(!BKE_image_get_ibuf(tface->tpage, NULL))
+ characters = 0;
+
+ if (!mf_smooth) {
+ float nor[3];
+
+ CalcNormFloat(v1, v2, v3, nor);
+
+ glNormal3fv(nor);
+ }
+
+ GPU_render_text(tface, tface->mode, string, characters,
+ (unsigned int*)mcol, v1, v2, v3, (mf->v4? v4: NULL), glattrib);
+ }
+ if (mcol) {
+ mcol+=4;
+ }
+ }
+
+ ddm->release(ddm);
+}
+
+void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, int faceselect)
+{
+ Mesh *me= ob->data;
+
+ /* correct for negative scale */
+ if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
+ else glFrontFace(GL_CCW);
+
+ /* draw the textured mesh */
+ draw_textured_begin(scene, v3d, rv3d, ob);
+
+ if(ob == scene->obedit) {
+ dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, me->edit_mesh);
+ } else if(faceselect) {
+ if(G.f & G_WEIGHTPAINT)
+ dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1);
+ else
+ dm->drawMappedFacesTex(dm, draw_tface_mapped__set_draw, me);
+ }
+ else {
+ dm->drawFacesTex(dm, draw_tface__set_draw);
+ }
+
+ /* draw game engine text hack */
+ if(get_ob_property(ob, "Text"))
+ draw_mesh_text(scene, ob, 0);
+
+ draw_textured_end();
+
+ /* draw edges and selected faces over textured mesh */
+ if(!(ob == scene->obedit) && faceselect)
+ draw_tfaces3D(rv3d, ob, me, dm);
+
+ /* reset from negative scale correction */
+ glFrontFace(GL_CCW);
+
+ /* in editmode, the blend mode needs to be set incase it was ADD */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+}
+
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
new file mode 100644
index 00000000000..5276ca8f0a5
--- /dev/null
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -0,0 +1,5407 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, full recode and added functions
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <math.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "IMB_imbuf.h"
+
+
+#include "MTC_matrixops.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_constraint_types.h" // for drawing constraint
+#include "DNA_effect_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_object_fluidsim.h"
+#include "DNA_particle_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_edgehash.h"
+#include "BLI_rand.h"
+
+#include "BKE_anim.h" //for the where_on_path function
+#include "BKE_curve.h"
+#include "BKE_constraint.h" // for the get_constraint_target function
+#include "BKE_DerivedMesh.h"
+#include "BKE_deform.h"
+#include "BKE_displist.h"
+#include "BKE_effect.h"
+#include "BKE_font.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_mesh.h"
+#include "BKE_material.h"
+#include "BKE_mball.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+#include "BKE_property.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "GPU_draw.h"
+#include "GPU_material.h"
+#include "GPU_extensions.h"
+
+#include "ED_particle.h"
+#include "ED_mesh.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "UI_resources.h"
+#include "UI_interface_icons.h"
+
+#include "WM_api.h"
+
+#include "view3d_intern.h" // own include
+
+
+/* this condition has been made more complex since editmode can draw textures */
+#define CHECK_OB_DRAWTEXTURE(vd, dt) \
+((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || \
+ (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
+
+#define CHECK_OB_DRAWFACEDOT(sce, vd, dt) \
+( (sce->selectmode & SCE_SELECT_FACE) && \
+ (vd->drawtype<=OB_SOLID) && \
+ (((vd->drawtype==OB_SOLID) && (dt>=OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX) && (vd->flag & V3D_ZBUF_SELECT)) == 0) \
+ )
+
+
+/* pretty stupid */
+/* editmball.c */
+extern ListBase editelems;
+
+static void draw_bounding_volume(Scene *scene, Object *ob);
+
+static void drawcube_size(float size);
+static void drawcircle_size(float size);
+static void draw_empty_sphere(float size);
+static void draw_empty_cone(float size);
+
+/* check for glsl drawing */
+
+int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
+{
+ if(!GPU_extensions_minimum_support())
+ return 0;
+ if(G.f & G_PICKSEL)
+ return 0;
+ if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
+ return 0;
+ if(ob==OBACT && (G.f & G_WEIGHTPAINT))
+ return 0;
+
+ return ((G.fileflags & G_FILE_GAME_MAT) &&
+ (G.fileflags & G_FILE_GAME_MAT_GLSL) && (dt >= OB_SHADED));
+}
+
+static int check_material_alpha(Base *base, Mesh *me, int glsl)
+{
+ if(base->flag & OB_FROMDUPLI)
+ return 0;
+
+ if(G.f & G_PICKSEL)
+ return 0;
+
+ if(me->edit_mesh)
+ return 0;
+
+ return (glsl || (base->object->dtx & OB_DRAWTRANSP));
+}
+
+ /***/
+static unsigned int colortab[24]=
+ {0x0, 0xFF88FF, 0xFFBBFF,
+ 0x403000, 0xFFFF88, 0xFFFFBB,
+ 0x104040, 0x66CCCC, 0x77CCCC,
+ 0x104010, 0x55BB55, 0x66FF66,
+ 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},
+};
+
+/* ----------------- OpenGL Circle Drawing - Tables for Optimised Drawing Speed ------------------ */
+/* 32 values of sin function (still same result!) */
+static float sinval[32] = {
+ 0.00000000,
+ 0.20129852,
+ 0.39435585,
+ 0.57126821,
+ 0.72479278,
+ 0.84864425,
+ 0.93775213,
+ 0.98846832,
+ 0.99871650,
+ 0.96807711,
+ 0.89780453,
+ 0.79077573,
+ 0.65137248,
+ 0.48530196,
+ 0.29936312,
+ 0.10116832,
+ -0.10116832,
+ -0.29936312,
+ -0.48530196,
+ -0.65137248,
+ -0.79077573,
+ -0.89780453,
+ -0.96807711,
+ -0.99871650,
+ -0.98846832,
+ -0.93775213,
+ -0.84864425,
+ -0.72479278,
+ -0.57126821,
+ -0.39435585,
+ -0.20129852,
+ 0.00000000
+};
+
+/* 32 values of cos function (still same result!) */
+static float cosval[32] ={
+ 1.00000000,
+ 0.97952994,
+ 0.91895781,
+ 0.82076344,
+ 0.68896691,
+ 0.52896401,
+ 0.34730525,
+ 0.15142777,
+ -0.05064916,
+ -0.25065253,
+ -0.44039415,
+ -0.61210598,
+ -0.75875812,
+ -0.87434661,
+ -0.95413925,
+ -0.99486932,
+ -0.99486932,
+ -0.95413925,
+ -0.87434661,
+ -0.75875812,
+ -0.61210598,
+ -0.44039415,
+ -0.25065253,
+ -0.05064916,
+ 0.15142777,
+ 0.34730525,
+ 0.52896401,
+ 0.68896691,
+ 0.82076344,
+ 0.91895781,
+ 0.97952994,
+ 1.00000000
+};
+
+/* flag is same as for draw_object */
+void drawaxes(float size, int flag, char drawtype)
+{
+ int axis;
+ float v1[3]= {0.0, 0.0, 0.0};
+ float v2[3]= {0.0, 0.0, 0.0};
+ float v3[3]= {0.0, 0.0, 0.0};
+
+ if(G.f & G_RENDER_SHADOW)
+ return;
+
+ switch(drawtype) {
+
+ case OB_PLAINAXES:
+ for (axis=0; axis<3; axis++) {
+ float v1[3]= {0.0, 0.0, 0.0};
+ float v2[3]= {0.0, 0.0, 0.0};
+
+ glBegin(GL_LINES);
+
+ v1[axis]= size;
+ v2[axis]= -size;
+ glVertex3fv(v1);
+ glVertex3fv(v2);
+
+ glEnd();
+ }
+ break;
+ case OB_SINGLE_ARROW:
+
+ glBegin(GL_LINES);
+ /* in positive z direction only */
+ v1[2]= size;
+ glVertex3fv(v1);
+ glVertex3fv(v2);
+ glEnd();
+
+ /* square pyramid */
+ glBegin(GL_TRIANGLES);
+
+ v2[0]= size*0.035; v2[1] = size*0.035;
+ v3[0]= size*-0.035; v3[1] = size*0.035;
+ v2[2]= v3[2]= size*0.75;
+
+ for (axis=0; axis<4; axis++) {
+ if (axis % 2 == 1) {
+ v2[0] *= -1;
+ v3[1] *= -1;
+ } else {
+ v2[1] *= -1;
+ v3[0] *= -1;
+ }
+
+ glVertex3fv(v1);
+ glVertex3fv(v2);
+ glVertex3fv(v3);
+
+ }
+ glEnd();
+
+ break;
+ case OB_CUBE:
+ drawcube_size(size);
+ break;
+
+ case OB_CIRCLE:
+ drawcircle_size(size);
+ break;
+
+ case OB_EMPTY_SPHERE:
+ draw_empty_sphere(size);
+ break;
+
+ case OB_EMPTY_CONE:
+ draw_empty_cone(size);
+ break;
+
+ case OB_ARROWS:
+ default:
+ 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);
+
+ // patch for 3d cards crashing on glSelect for text drawing (IBM)
+ if((flag & DRAW_PICKING) == 0) {
+ if (axis==0)
+ BMF_DrawString(G.font, "x");
+ else if (axis==1)
+ BMF_DrawString(G.font, "y");
+ else
+ BMF_DrawString(G.font, "z");
+ }
+ }
+ break;
+ }
+}
+
+void drawcircball(int mode, float *cent, float rad, float tmat[][4])
+{
+ float vec[3], vx[3], vy[3];
+ int a, tot=32;
+
+ VECCOPY(vx, tmat[0]);
+ VECCOPY(vy, tmat[1]);
+ VecMulf(vx, rad);
+ VecMulf(vy, rad);
+
+ glBegin(mode);
+ for(a=0; a<tot; a++) {
+ vec[0]= cent[0] + *(sinval+a) * vx[0] + *(cosval+a) * vy[0];
+ vec[1]= cent[1] + *(sinval+a) * vx[1] + *(cosval+a) * vy[1];
+ vec[2]= cent[2] + *(sinval+a) * vx[2] + *(cosval+a) * vy[2];
+ glVertex3fv(vec);
+ }
+ glEnd();
+}
+
+/* circle for object centers, special_color is for library or ob users */
+static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, float *vec, int selstate, int special_color)
+{
+ float size;
+
+ size= rv3d->persmat[0][3]*vec[0]+ rv3d->persmat[1][3]*vec[1]+ rv3d->persmat[2][3]*vec[2]+ rv3d->persmat[3][3];
+ size*= rv3d->pixsize*((float)U.obcenter_dia*0.5f);
+
+ /* using gldepthfunc guarantees that it does write z values, but not checks for it, so centers remain visible independt order of drawing */
+ if(v3d->zbuf) glDepthFunc(GL_ALWAYS);
+ glEnable(GL_BLEND);
+
+ if(special_color) {
+ if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
+
+ else glColor4ub(0x55, 0xCC, 0xCC, 155);
+ }
+ else {
+ if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
+ else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
+ else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
+ }
+ drawcircball(GL_POLYGON, vec, size, rv3d->viewinv);
+
+ UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
+ drawcircball(GL_LINE_LOOP, vec, size, rv3d->viewinv);
+
+ glDisable(GL_BLEND);
+ if(v3d->zbuf) glDepthFunc(GL_LEQUAL);
+}
+
+
+void drawsolidcube(float size)
+{
+ float n[3];
+
+ glPushMatrix();
+ glScalef(size, size, size);
+
+ 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();
+
+ glPopMatrix();
+}
+
+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();
+}
+
+/* draws a cube on given the scaling of the cube, assuming that
+ * all required matrices have been set (used for drawing empties)
+ */
+static void drawcube_size(float size)
+{
+ glBegin(GL_LINE_STRIP);
+ glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
+ glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);glVertex3f(size,-size,size); glVertex3f(size,size,size);
+ glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3f(-size,size,size); glVertex3f(size,size,size);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
+ glEnd();
+}
+
+/* this is an unused (old) cube-drawing function based on a given size */
+#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 drawshadbuflimits(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];
+ Normalize(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);
+ bglBegin(GL_POINTS);
+ bglVertex3fv(sta);
+ bglVertex3fv(end);
+ bglEnd();
+ glPointSize(1.0);
+}
+
+
+
+static void spotvolume(float *lvec, float *vvec, float inp)
+{
+ /* camera is at 0,0,0 */
+ float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
+
+ Normalize(lvec);
+ Normalize(vvec); /* is this the correct vector ? */
+
+ Crossf(temp,vvec,lvec); /* equation for a plane through vvec en lvec */
+ Crossf(plane,lvec,temp); /* a plane perpendicular to this, parrallel with lvec */
+
+ Normalize(plane);
+
+ /* now we've got two equations: one of a cone and one of a plane, but we have
+ three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
+
+ /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
+ /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
+
+ /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
+
+ q[1] = plane[1] ;
+ q[2] = -plane[0] ;
+ q[3] = 0 ;
+ Normalize(&q[1]);
+
+ angle = saacos(plane[2])/2.0;
+ co = cos(angle);
+ si = sqrt(1-co*co);
+
+ q[0] = co;
+ q[1] *= si;
+ q[2] *= si;
+ q[3] = 0;
+
+ QuatToMat3(q,mat1);
+
+ /* rotate lamp vector now over acos(inp) degrees */
+
+ 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(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
+{
+ Lamp *la;
+ float vec[3], lvec[3], vvec[3], circrad, x,y,z;
+ float pixsize, lampsize;
+ float imat[4][4], curcol[4];
+ char col[4];
+
+ if(G.f & G_RENDER_SHADOW)
+ return;
+
+ la= ob->data;
+
+ /* we first draw only the screen aligned & fixed scale stuff */
+ glPushMatrix();
+ wmLoadMatrix(rv3d->viewmat);
+
+ /* lets calculate the scale: */
+ pixsize= rv3d->persmat[0][3]*ob->obmat[3][0]+ rv3d->persmat[1][3]*ob->obmat[3][1]+ rv3d->persmat[2][3]*ob->obmat[3][2]+ rv3d->persmat[3][3];
+ pixsize*= rv3d->pixsize;
+ lampsize= pixsize*((float)U.obcenter_dia*0.5f);
+
+ /* and view aligned matrix: */
+ Mat4CpyMat4(imat, rv3d->viewinv);
+ Normalize(imat[0]);
+ Normalize(imat[1]);
+
+ /* for AA effects */
+ glGetFloatv(GL_CURRENT_COLOR, curcol);
+ curcol[3]= 0.6;
+ glColor4fv(curcol);
+
+ if(ob->id.us>1) {
+ if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
+ else glColor4ub(0x77, 0xCC, 0xCC, 155);
+ }
+
+ /* Inner Circle */
+ VECCOPY(vec, ob->obmat[3]);
+ glEnable(GL_BLEND);
+ drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
+ glDisable(GL_BLEND);
+ drawcircball(GL_POLYGON, vec, lampsize, imat);
+
+ /* restore */
+ if(ob->id.us>1)
+ glColor4fv(curcol);
+
+ /* Outer circle */
+ circrad = 3.0f*lampsize;
+ drawcircball(GL_LINE_LOOP, vec, circrad, imat);
+
+ setlinestyle(3);
+
+ /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
+ if (la->type!=LA_HEMI) {
+ if ((la->mode & LA_SHAD_RAY) ||
+ ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT)) )
+ {
+ drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
+ }
+ }
+
+ /* draw the pretty sun rays */
+ if(la->type==LA_SUN) {
+ float v1[3], v2[3], mat[3][3];
+ short axis;
+
+ /* setup a 45 degree rotation matrix */
+ VecRotToMat3(imat[2], M_PI/4.0f, mat);
+
+ /* vectors */
+ VECCOPY(v1, imat[0]);
+ VecMulf(v1, circrad*1.2f);
+ VECCOPY(v2, imat[0]);
+ VecMulf(v2, circrad*2.5f);
+
+ /* center */
+ glTranslatef(vec[0], vec[1], vec[2]);
+
+ setlinestyle(3);
+
+ glBegin(GL_LINES);
+ for (axis=0; axis<8; axis++) {
+ glVertex3fv(v1);
+ glVertex3fv(v2);
+ Mat3MulVecfl(mat, v1);
+ Mat3MulVecfl(mat, v2);
+ }
+ glEnd();
+
+ glTranslatef(-vec[0], -vec[1], -vec[2]);
+
+ }
+
+ if (la->type==LA_LOCAL) {
+ if(la->mode & LA_SPHERE) {
+ drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
+ }
+ /* yafray: for photonlight also draw lightcone as for spot */
+ }
+
+ glPopMatrix(); /* back in object space */
+ vec[0]= vec[1]= vec[2]= 0.0f;
+
+ if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
+ lvec[0]=lvec[1]= 0.0;
+ lvec[2] = 1.0;
+ x = rv3d->persmat[0][2];
+ y = rv3d->persmat[1][2];
+ z = rv3d->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;
+
+ /* draw the angled sides of the cone */
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vvec);
+ glVertex3fv(vec);
+ glVertex3fv(lvec);
+ glEnd();
+
+ z = x*sqrt(1.0 - y*y);
+ x *= y;
+
+ /* draw the circle/square at the end of the cone */
+ 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));
+
+ /* draw the circle/square representing spotbl */
+ if(la->type==LA_SPOT) {
+ float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
+ /* make sure the line is always visible - prevent it from reaching the outer border (or 0)
+ * values are kinda arbitrary - just what seemed to work well */
+ if (spotblcirc == 0) spotblcirc = 0.15;
+ else if (spotblcirc == fabs(z)) spotblcirc = fabs(z) - 0.07;
+ circ(0.0, 0.0, spotblcirc);
+ }
+
+ }
+ else if ELEM(la->type, LA_HEMI, LA_SUN) {
+
+ /* draw the line from the circle along the dist */
+ glBegin(GL_LINE_STRIP);
+ vec[2] = -circrad;
+ glVertex3fv(vec);
+ vec[2]= -la->dist;
+ glVertex3fv(vec);
+ glEnd();
+
+ if(la->type==LA_HEMI) {
+ /* draw the hemisphere curves */
+ short axis, steps, dir;
+ float outdist, zdist, mul;
+ vec[0]=vec[1]=vec[2]= 0.0;
+ outdist = 0.14; mul = 1.4; dir = 1;
+
+ setlinestyle(4);
+ /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
+ for (axis=0; axis<4; axis++) {
+ float v[3]= {0.0, 0.0, 0.0};
+ zdist = 0.02;
+
+ glBegin(GL_LINE_STRIP);
+
+ for (steps=0; steps<6; steps++) {
+ if (axis == 0 || axis == 1) { /* x axis up, x axis down */
+ /* make the arcs start at the edge of the energy circle */
+ if (steps == 0) v[0] = dir*circrad;
+ else v[0] = v[0] + dir*(steps*outdist);
+ } else if (axis == 2 || axis == 3) { /* y axis up, y axis down */
+ /* make the arcs start at the edge of the energy circle */
+ if (steps == 0) v[1] = dir*circrad;
+ else v[1] = v[1] + dir*(steps*outdist);
+ }
+
+ v[2] = v[2] - steps*zdist;
+
+ glVertex3fv(v);
+
+ zdist = zdist * mul;
+ }
+
+ glEnd();
+ /* flip the direction */
+ dir = -dir;
+ }
+ }
+ } else if(la->type==LA_AREA) {
+ setlinestyle(3);
+ if(la->area_shape==LA_AREA_SQUARE)
+ fdrawbox(-la->area_size*0.5, -la->area_size*0.5, la->area_size*0.5, la->area_size*0.5);
+ else if(la->area_shape==LA_AREA_RECT)
+ fdrawbox(-la->area_size*0.5, -la->area_sizey*0.5, la->area_size*0.5, la->area_sizey*0.5);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3f(0.0,0.0,-circrad);
+ glVertex3f(0.0,0.0,-la->dist);
+ glEnd();
+ }
+
+ /* and back to viewspace */
+ wmLoadMatrix(rv3d->viewmat);
+ VECCOPY(vec, ob->obmat[3]);
+
+ setlinestyle(0);
+
+ if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
+ drawshadbuflimits(la, ob->obmat);
+ }
+
+ UI_GetThemeColor4ubv(TH_LAMP, col);
+ glColor4ub(col[0], col[1], col[2], col[3]);
+
+ glEnable(GL_BLEND);
+
+ if (vec[2]>0) vec[2] -= circrad;
+ else vec[2] += circrad;
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec);
+ vec[2]= 0;
+ glVertex3fv(vec);
+ glEnd();
+
+ glPointSize(2.0);
+ glBegin(GL_POINTS);
+ glVertex3fv(vec);
+ glEnd();
+ glPointSize(1.0);
+
+ glDisable(GL_BLEND);
+
+ /* restore for drawing extra stuff */
+ glColor3fv(curcol);
+
+}
+
+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);
+}
+
+
+/* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
+/* qdn: now also enabled for Blender to set focus point for defocus composit node */
+static void draw_focus_cross(float dist, float size)
+{
+ glBegin(GL_LINES);
+ glVertex3f(-size, 0.f, -dist);
+ glVertex3f(size, 0.f, -dist);
+ glVertex3f(0.f, -size, -dist);
+ glVertex3f(0.f, size, -dist);
+ glEnd();
+}
+
+/* flag similar to draw_object() */
+static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int flag)
+{
+ /* a standing up pyramid with (0,0,0) as top */
+ Camera *cam;
+ World *wrld;
+ float vec[8][4], tmat[4][4], fac, facx, facy, depth;
+ int i;
+
+ if(G.f & G_RENDER_SHADOW)
+ return;
+
+ cam= ob->data;
+
+ glDisable(GL_LIGHTING);
+ glDisable(GL_CULL_FACE);
+
+ if(rv3d->persp>=2 && cam->type==CAM_ORTHO && ob==v3d->camera) {
+ facx= 0.5*cam->ortho_scale*1.28;
+ facy= 0.5*cam->ortho_scale*1.024;
+ depth= -cam->clipsta-0.1;
+ }
+ else {
+ fac= cam->drawsize;
+ if(rv3d->persp>=2 && ob==v3d->camera) fac= cam->clipsta+0.1; /* that way it's always visible */
+
+ depth= - fac*cam->lens/16.0;
+ facx= fac*1.28;
+ facy= fac*1.024;
+ }
+
+ vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.001; /* GLBUG: for picking at iris Entry (well thats old!) */
+ 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[1]);
+ glVertex3fv(vec[2]);
+ glVertex3fv(vec[3]);
+ glVertex3fv(vec[4]);
+ glEnd();
+
+
+ if(rv3d->persp>=2 && ob==v3d->camera) return;
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec[2]);
+ glVertex3fv(vec[0]);
+ glVertex3fv(vec[1]);
+ glVertex3fv(vec[4]);
+ glVertex3fv(vec[0]);
+ glVertex3fv(vec[3]);
+ glEnd();
+
+
+ /* arrow on top */
+ vec[0][2]= depth;
+
+
+ /* draw an outline arrow for inactive cameras and filled
+ * for active cameras. We actually draw both outline+filled
+ * for active cameras so the wire can be seen side-on */
+ for (i=0;i<2;i++) {
+ if (i==0) glBegin(GL_LINE_LOOP);
+ else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
+ else break;
+
+ vec[0][0]= -0.7*cam->drawsize;
+ vec[0][1]= 1.1*cam->drawsize;
+ glVertex3fv(vec[0]);
+
+ vec[0][0]= 0.0;
+ vec[0][1]= 1.8*cam->drawsize;
+ glVertex3fv(vec[0]);
+
+ vec[0][0]= 0.7*cam->drawsize;
+ vec[0][1]= 1.1*cam->drawsize;
+ glVertex3fv(vec[0]);
+
+ glEnd();
+ }
+
+ if(flag==0) {
+ if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
+ wmLoadMatrix(rv3d->viewmat);
+ Mat4CpyMat4(vec, ob->obmat);
+ Mat4Ortho(vec);
+ wmMultMatrix(vec);
+
+ MTC_Mat4SwapMat4(rv3d->persmat, tmat);
+ wmGetSingleMatrix(rv3d->persmat);
+
+ if(cam->flag & CAM_SHOWLIMITS) {
+ draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
+ /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
+ draw_focus_cross(dof_camera(ob), cam->drawsize);
+ }
+
+ wrld= scene->world;
+ if(cam->flag & CAM_SHOWMIST)
+ if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
+
+ MTC_Mat4SwapMat4(rv3d->persmat, tmat);
+ }
+ }
+}
+
+static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
+{
+ BPoint *bp = lt->def;
+ float *co = dl?dl->verts:NULL;
+ int u, v, w;
+
+ UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
+ glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+ bglBegin(GL_POINTS);
+
+ for(w=0; w<lt->pntsw; w++) {
+ int wxt = (w==0 || w==lt->pntsw-1);
+ for(v=0; v<lt->pntsv; v++) {
+ int vxt = (v==0 || v==lt->pntsv-1);
+ for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
+ int uxt = (u==0 || u==lt->pntsu-1);
+ if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
+ if(bp->hide==0) {
+ if((bp->f1 & SELECT)==sel) {
+ bglVertex3fv(dl?co:bp->vec);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ glPointSize(1.0);
+ bglEnd();
+}
+
+void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
+{
+ Object *obedit= vc->obedit;
+ Lattice *lt= obedit->data;
+ BPoint *bp = lt->editlatt->def;
+ DispList *dl = find_displist(&obedit->disp, DL_VERTS);
+ float *co = dl?dl->verts:NULL;
+ float pmat[4][4], vmat[4][4];
+ int i, N = lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
+ short s[2] = {IS_CLIPPED, 0};
+
+ view3d_get_object_project_mat(vc->rv3d, vc->obedit, pmat, vmat);
+
+ for (i=0; i<N; i++, bp++, co+=3) {
+ if (bp->hide==0) {
+ view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, pmat, vmat);
+ if (s[0] != IS_CLIPPED)
+ func(userData, bp, s[0], s[1]);
+ }
+ }
+}
+
+static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
+{
+ int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
+
+ if(use_wcol) {
+ float col[3];
+ MDeformWeight *mdw= get_defweight (lt->dvert+index, use_wcol-1);
+
+ weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
+ glColor3fv(col);
+
+ }
+
+ if (dl) {
+ glVertex3fv(&dl->verts[index*3]);
+ } else {
+ glVertex3fv(lt->def[index].vec);
+ }
+}
+
+/* lattice color is hardcoded, now also shows weightgroup values in edit mode */
+static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
+{
+ Lattice *lt= ob->data;
+ DispList *dl;
+ int u, v, w;
+ int use_wcol= 0;
+
+ /* now we default make displist, this will modifiers work for non animated case */
+ if(ob->disp.first==NULL)
+ lattice_calc_modifiers(scene, ob);
+ dl= find_displist(&ob->disp, DL_VERTS);
+
+ if(lt->editlatt) {
+ cpack(0x004000);
+
+ if(ob->defbase.first && lt->dvert) {
+ use_wcol= ob->actdef;
+ glShadeModel(GL_SMOOTH);
+ }
+ }
+
+ if(lt->editlatt) lt= lt->editlatt;
+
+ glBegin(GL_LINES);
+ for(w=0; w<lt->pntsw; w++) {
+ int wxt = (w==0 || w==lt->pntsw-1);
+ for(v=0; v<lt->pntsv; v++) {
+ int vxt = (v==0 || v==lt->pntsv-1);
+ for(u=0; u<lt->pntsu; u++) {
+ int uxt = (u==0 || u==lt->pntsu-1);
+
+ if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
+ drawlattice__point(lt, dl, u, v, w-1, use_wcol);
+ drawlattice__point(lt, dl, u, v, w, use_wcol);
+ }
+ if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
+ drawlattice__point(lt, dl, u, v-1, w, use_wcol);
+ drawlattice__point(lt, dl, u, v, w, use_wcol);
+ }
+ if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
+ drawlattice__point(lt, dl, u-1, v, w, use_wcol);
+ drawlattice__point(lt, dl, u, v, w, use_wcol);
+ }
+ }
+ }
+ }
+ glEnd();
+
+ /* restoration for weight colors */
+ if(use_wcol)
+ glShadeModel(GL_FLAT);
+
+ if( ((Lattice *)ob->data)->editlatt ) {
+ if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
+
+ lattice_draw_verts(lt, dl, 0);
+ lattice_draw_verts(lt, dl, 1);
+
+ if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ }
+}
+
+/* ***************** ******************** */
+
+static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
+{
+ struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
+ EditVert *eve = EM_get_vert_for_index(index);
+
+ if (eve->h==0) {
+ short s[2]= {IS_CLIPPED, 0};
+
+ if (data->clipVerts) {
+ view3d_project_short_clip(data->vc.ar, co, s, data->pmat, data->vmat);
+ } else {
+ view3d_project_short_noclip(data->vc.ar, co, s, data->pmat);
+ }
+
+ if (s[0]!=IS_CLIPPED)
+ data->func(data->userData, eve, s[0], s[1], index);
+ }
+}
+
+void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
+{
+ struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
+ DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
+
+ data.vc= *vc;
+ data.func = func;
+ data.userData = userData;
+ data.clipVerts = clipVerts;
+
+ view3d_get_object_project_mat(vc->rv3d, vc->obedit, data.pmat, data.vmat);
+
+ EM_init_index_arrays(vc->em, 1, 0, 0);
+ dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
+ EM_free_index_arrays();
+
+ dm->release(dm);
+}
+
+static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
+{
+ struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
+ EditEdge *eed = EM_get_edge_for_index(index);
+ short s[2][2];
+
+ if (eed->h==0) {
+ if (data->clipVerts==1) {
+ view3d_project_short_clip(data->vc.ar, v0co, s[0], data->pmat, data->vmat);
+ view3d_project_short_clip(data->vc.ar, v1co, s[1], data->pmat, data->vmat);
+ } else {
+ view3d_project_short_noclip(data->vc.ar, v0co, s[0], data->pmat);
+ view3d_project_short_noclip(data->vc.ar, v1co, s[1], data->pmat);
+
+ if (data->clipVerts==2) {
+ if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
+ if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy))
+ return;
+ }
+ }
+
+ data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
+ }
+}
+
+void mesh_foreachScreenEdge(ViewContext *vc, void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts)
+{
+ struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
+ DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
+
+ data.vc= *vc;
+ data.func = func;
+ data.userData = userData;
+ data.clipVerts = clipVerts;
+
+ view3d_get_object_project_mat(vc->rv3d, vc->obedit, data.pmat, data.vmat);
+
+ EM_init_index_arrays(vc->em, 0, 1, 0);
+ dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
+ EM_free_index_arrays();
+
+ dm->release(dm);
+}
+
+static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no)
+{
+ struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; float pmat[4][4], vmat[4][4]; } *data = userData;
+ EditFace *efa = EM_get_face_for_index(index);
+ short s[2];
+
+ if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
+ view3d_project_short_clip(data->vc.ar, cent, s, data->pmat, data->vmat);
+
+ data->func(data->userData, efa, s[0], s[1], index);
+ }
+}
+
+void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
+{
+ struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; float pmat[4][4], vmat[4][4]; } data;
+ DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
+
+ data.vc= *vc;
+ data.func = func;
+ data.userData = userData;
+
+ view3d_get_object_project_mat(vc->rv3d, vc->obedit, data.pmat, data.vmat);
+
+ EM_init_index_arrays(vc->em, 0, 0, 1);
+ dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
+ EM_free_index_arrays();
+
+ dm->release(dm);
+}
+
+void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
+{
+ Curve *cu= vc->obedit->data;
+ float pmat[4][4], vmat[4][4];
+ short s[2] = {IS_CLIPPED, 0};
+ Nurb *nu;
+ int i;
+
+ view3d_get_object_project_mat(vc->rv3d, vc->obedit, pmat, vmat);
+
+ for (nu= cu->editnurb->first; nu; nu=nu->next) {
+ if((nu->type & 7)==CU_BEZIER) {
+ for (i=0; i<nu->pntsu; i++) {
+ BezTriple *bezt = &nu->bezt[i];
+
+ if(bezt->hide==0) {
+ if (G.f & G_HIDDENHANDLES) {
+ view3d_project_short_clip(vc->ar, bezt->vec[1], s, pmat, vmat);
+ if (s[0] != IS_CLIPPED)
+ func(userData, nu, NULL, bezt, 1, s[0], s[1]);
+ } else {
+ view3d_project_short_clip(vc->ar, bezt->vec[0], s, pmat, vmat);
+ if (s[0] != IS_CLIPPED)
+ func(userData, nu, NULL, bezt, 0, s[0], s[1]);
+ view3d_project_short_clip(vc->ar, bezt->vec[1], s, pmat, vmat);
+ if (s[0] != IS_CLIPPED)
+ func(userData, nu, NULL, bezt, 1, s[0], s[1]);
+ view3d_project_short_clip(vc->ar, bezt->vec[2], s, pmat, vmat);
+ if (s[0] != IS_CLIPPED)
+ func(userData, nu, NULL, bezt, 2, s[0], s[1]);
+ }
+ }
+ }
+ }
+ else {
+ for (i=0; i<nu->pntsu*nu->pntsv; i++) {
+ BPoint *bp = &nu->bp[i];
+
+ if(bp->hide==0) {
+ view3d_project_short_clip(vc->ar, bp->vec, s, pmat, vmat);
+ if (s[0] != IS_CLIPPED)
+ func(userData, nu, bp, NULL, -1, s[0], s[1]);
+ }
+ }
+ }
+ }
+}
+
+/* ************** DRAW MESH ****************** */
+
+/* First section is all the "simple" draw routines,
+ * ones that just pass some sort of primitive to GL,
+ * with perhaps various options to control lighting,
+ * color, etc.
+ *
+ * These routines should not have user interface related
+ * logic!!!
+ */
+
+static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
+{
+ Scene *scene= (Scene *)userData;
+ EditFace *efa = EM_get_face_for_index(index);
+
+ if (efa->h==0 && efa->fgonf!=EM_FGON) {
+ glVertex3fv(cent);
+ glVertex3f( cent[0] + no[0]*scene->editbutsize,
+ cent[1] + no[1]*scene->editbutsize,
+ cent[2] + no[2]*scene->editbutsize);
+ }
+}
+static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm)
+{
+ glBegin(GL_LINES);
+ dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
+ glEnd();
+}
+
+static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *no)
+{
+ EditFace *efa = EM_get_face_for_index(index);
+ int sel = *((int*) userData);
+
+ if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
+ bglVertex3fv(cent);
+ }
+}
+static void draw_dm_face_centers(DerivedMesh *dm, int sel)
+{
+ bglBegin(GL_POINTS);
+ dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
+ bglEnd();
+}
+
+static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
+{
+ Scene *scene= (Scene *)userData;
+ EditVert *eve = EM_get_vert_for_index(index);
+
+ if (eve->h==0) {
+ glVertex3fv(co);
+
+ if (no_f) {
+ glVertex3f( co[0] + no_f[0]*scene->editbutsize,
+ co[1] + no_f[1]*scene->editbutsize,
+ co[2] + no_f[2]*scene->editbutsize);
+ } else {
+ glVertex3f( co[0] + no_s[0]*scene->editbutsize/32767.0f,
+ co[1] + no_s[1]*scene->editbutsize/32767.0f,
+ co[2] + no_s[2]*scene->editbutsize/32767.0f);
+ }
+ }
+}
+static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm)
+{
+ glBegin(GL_LINES);
+ dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
+ glEnd();
+}
+
+ /* Draw verts with color set based on selection */
+static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
+{
+ struct { int sel; EditVert *eve_act; } * data = userData;
+ EditVert *eve = EM_get_vert_for_index(index);
+
+ if (eve->h==0 && (eve->f&SELECT)==data->sel) {
+ /* draw active larger - need to stop/start point drawing for this :/ */
+ if (eve==data->eve_act) {
+ float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
+ UI_ThemeColor4(TH_EDITMESH_ACTIVE);
+
+ bglEnd();
+
+ glPointSize(size);
+ bglBegin(GL_POINTS);
+ bglVertex3fv(co);
+ bglEnd();
+
+ UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
+ glPointSize(size);
+ bglBegin(GL_POINTS);
+ } else {
+ bglVertex3fv(co);
+ }
+ }
+}
+static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
+{
+ struct { int sel; EditVert *eve_act; } data;
+ data.sel = sel;
+ data.eve_act = eve_act;
+
+ bglBegin(GL_POINTS);
+ dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
+ bglEnd();
+}
+
+ /* Draw edges with color set based on selection */
+static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
+{
+ EditEdge *eed = EM_get_edge_for_index(index);
+ //unsigned char **cols = userData, *col;
+ struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
+ unsigned char *col;
+
+ if (eed->h==0) {
+ if (eed==data->eed_act) {
+ glColor4ubv(data->actCol);
+ } else {
+ if (eed->f&SELECT) {
+ col = data->selCol;
+ } else {
+ col = data->baseCol;
+ }
+ /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
+ if (col[3]==0) return 0;
+
+ glColor4ubv(col);
+ }
+ return 1;
+ } else {
+ return 0;
+ }
+}
+static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act)
+{
+ struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
+
+ data.baseCol = baseCol;
+ data.selCol = selCol;
+ data.actCol = actCol;
+ data.eed_act = eed_act;
+ dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
+}
+
+ /* Draw edges */
+static int draw_dm_edges__setDrawOptions(void *userData, int index)
+{
+ return EM_get_edge_for_index(index)->h==0;
+}
+static void draw_dm_edges(DerivedMesh *dm)
+{
+ dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
+}
+
+ /* Draw edges with color interpolated based on selection */
+static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
+{
+ return EM_get_edge_for_index(index)->h==0;
+}
+static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
+{
+ EditEdge *eed = EM_get_edge_for_index(index);
+ unsigned char **cols = userData;
+ unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
+ unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
+
+ glColor4ub( col0[0] + (col1[0]-col0[0])*t,
+ col0[1] + (col1[1]-col0[1])*t,
+ col0[2] + (col1[2]-col0[2])*t,
+ col0[3] + (col1[3]-col0[3])*t);
+}
+static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
+{
+ unsigned char *cols[2];
+ cols[0] = baseCol;
+ cols[1] = selCol;
+ dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
+}
+
+ /* Draw only seam edges */
+static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
+{
+ EditEdge *eed = EM_get_edge_for_index(index);
+
+ return (eed->h==0 && eed->seam);
+}
+static void draw_dm_edges_seams(DerivedMesh *dm)
+{
+ dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
+}
+
+ /* Draw only sharp edges */
+static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
+{
+ EditEdge *eed = EM_get_edge_for_index(index);
+
+ return (eed->h==0 && eed->sharp);
+}
+static void draw_dm_edges_sharp(DerivedMesh *dm)
+{
+ dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
+}
+
+
+ /* Draw faces with color set based on selection
+ * return 2 for the active face so it renders with stipple enabled */
+static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r)
+{
+ struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
+ EditFace *efa = EM_get_face_for_index(index);
+ unsigned char *col;
+
+ if (efa->h==0) {
+ if (efa == data->efa_act) {
+ glColor4ubv(data->cols[2]);
+ return 2; /* stipple */
+ } else {
+ col = data->cols[(efa->f&SELECT)?1:0];
+ if (col[3]==0) return 0;
+ glColor4ubv(col);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* also draws the active face */
+static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act)
+{
+ struct { unsigned char *cols[3]; EditFace *efa_act; } data;
+ data.cols[0] = baseCol;
+ data.cols[1] = selCol;
+ data.cols[2] = actCol;
+ data.efa_act = efa_act;
+
+ dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
+}
+
+static int draw_dm_creases__setDrawOptions(void *userData, int index)
+{
+ EditEdge *eed = EM_get_edge_for_index(index);
+
+ if (eed->h==0 && eed->crease!=0.0) {
+ UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+static void draw_dm_creases(DerivedMesh *dm)
+{
+ glLineWidth(3.0);
+ dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
+ glLineWidth(1.0);
+}
+
+static int draw_dm_bweights__setDrawOptions(void *userData, int index)
+{
+ EditEdge *eed = EM_get_edge_for_index(index);
+
+ if (eed->h==0 && eed->bweight!=0.0) {
+ UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
+{
+ EditVert *eve = EM_get_vert_for_index(index);
+
+ if (eve->h==0 && eve->bweight!=0.0) {
+ UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
+ bglVertex3fv(co);
+ }
+}
+static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
+{
+ if (scene->selectmode & SCE_SELECT_VERTEX) {
+ glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
+ bglBegin(GL_POINTS);
+ dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
+ bglEnd();
+ }
+ else {
+ glLineWidth(3.0);
+ dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
+ glLineWidth(1.0);
+ }
+}
+
+/* Second section of routines: Combine first sets to form fancy
+ * drawing routines (for example rendering twice to get overlays).
+ *
+ * Also includes routines that are basic drawing but are too
+ * specialized to be split out (like drawing creases or measurements).
+ */
+
+/* EditMesh drawing routines*/
+
+static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
+{
+ int sel;
+
+ if(v3d->zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select
+
+ for (sel=0; sel<2; sel++) {
+ char col[4], fcol[4];
+ int pass;
+
+ UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
+ UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
+
+ for (pass=0; pass<2; pass++) {
+ float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
+ float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
+
+ if (pass==0) {
+ if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
+ glDisable(GL_DEPTH_TEST);
+
+ glEnable(GL_BLEND);
+ } else {
+ continue;
+ }
+
+ size = (size>2.1?size/2.0:size);
+ fsize = (fsize>2.1?fsize/2.0:fsize);
+ col[3] = fcol[3] = 100;
+ } else {
+ col[3] = fcol[3] = 255;
+ }
+
+ if(scene->selectmode & SCE_SELECT_VERTEX) {
+ glPointSize(size);
+ glColor4ubv((GLubyte *)col);
+ draw_dm_verts(cageDM, sel, eve_act);
+ }
+
+ if( CHECK_OB_DRAWFACEDOT(scene, v3d, obedit->dt) ) {
+ glPointSize(fsize);
+ glColor4ubv((GLubyte *)fcol);
+ draw_dm_face_centers(cageDM, sel);
+ }
+
+ if (pass==0) {
+ glDisable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
+ }
+ }
+ }
+
+ if(v3d->zbuf) glDepthMask(1);
+ glPointSize(1.0);
+}
+
+static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
+{
+ int pass;
+ unsigned char wireCol[4], selCol[4], actCol[4];
+
+ /* since this function does transparant... */
+ UI_GetThemeColor4ubv(TH_EDGE_SELECT, (char *)selCol);
+ UI_GetThemeColor4ubv(TH_WIRE, (char *)wireCol);
+ UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
+
+ /* when sel only is used, dont render wire, only selected, this is used for
+ * textured draw mode when the 'edges' option is disabled */
+ if (sel_only)
+ wireCol[3] = 0;
+
+ for (pass=0; pass<2; pass++) {
+ /* show wires in transparant when no zbuf clipping for select */
+ if (pass==0) {
+ if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
+ glEnable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+ selCol[3] = 85;
+ if (!sel_only) wireCol[3] = 85;
+ } else {
+ continue;
+ }
+ } else {
+ selCol[3] = 255;
+ if (!sel_only) wireCol[3] = 255;
+ }
+
+ if(scene->selectmode == SCE_SELECT_FACE) {
+ draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
+ }
+ else if( (me->drawflag & ME_DRAWEDGES) || (scene->selectmode & SCE_SELECT_EDGE) ) {
+ if(cageDM->drawMappedEdgesInterp && (scene->selectmode & SCE_SELECT_VERTEX)) {
+ glShadeModel(GL_SMOOTH);
+ draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
+ glShadeModel(GL_FLAT);
+ } else {
+ draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
+ }
+ }
+ else {
+ if (!sel_only) {
+ glColor4ubv(wireCol);
+ draw_dm_edges(cageDM);
+ }
+ }
+
+ if (pass==0) {
+ glDisable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
+ }
+ }
+}
+
+static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em)
+{
+ Mesh *me= ob->data;
+ EditEdge *eed;
+ EditFace *efa;
+ float v1[3], v2[3], v3[3], v4[3];
+ float fvec[3];
+ char val[32]; /* Stores the measurement display text here */
+ char conv_float[5]; /* Use a float conversion matching the grid size */
+ float area, col[3]; /* area of the face, color of the text to draw */
+
+ if(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))
+ return;
+
+ /* make the precission of the pronted value proportionate to the gridsize */
+ if ((v3d->grid) < 0.01)
+ strcpy(conv_float, "%.6f");
+ else if ((v3d->grid) < 0.1)
+ strcpy(conv_float, "%.5f");
+ else if ((v3d->grid) < 1.0)
+ strcpy(conv_float, "%.4f");
+ else if ((v3d->grid) < 10.0)
+ strcpy(conv_float, "%.3f");
+ else
+ strcpy(conv_float, "%.2f");
+
+
+ if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
+ glDisable(GL_DEPTH_TEST);
+
+ if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0);
+
+ if(me->drawflag & ME_DRAW_EDGELEN) {
+ UI_GetThemeColor3fv(TH_TEXT, col);
+ /* make color a bit more red */
+ if(col[0]> 0.5) {col[1]*=0.7; col[2]*= 0.7;}
+ else col[0]= col[0]*0.7 + 0.3;
+ glColor3fv(col);
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
+ if((eed->h != EM_FGON) && ((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
+ VECCOPY(v1, eed->v1->co);
+ VECCOPY(v2, eed->v2->co);
+
+ glRasterPos3f( 0.5*(v1[0]+v2[0]), 0.5*(v1[1]+v2[1]), 0.5*(v1[2]+v2[2]));
+
+ if(v3d->flag & V3D_GLOBAL_STATS) {
+ Mat4MulVecfl(ob->obmat, v1);
+ Mat4MulVecfl(ob->obmat, v2);
+ }
+
+ sprintf(val, conv_float, VecLenf(v1, v2));
+ BMF_DrawString( G.fonts, val);
+ }
+ }
+ }
+
+ if(me->drawflag & ME_DRAW_FACEAREA) {
+// XXX extern int faceselectedOR(EditFace *efa, int flag); // editmesh.h shouldn't be in this file... ok for now?
+
+ UI_GetThemeColor3fv(TH_TEXT, col);
+ /* make color a bit more green */
+ if(col[1]> 0.5) {col[0]*=0.7; col[2]*= 0.7;}
+ else col[1]= col[1]*0.7 + 0.3;
+ glColor3fv(col);
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if((efa->f & SELECT)) { // XXX || (G.moving && faceselectedOR(efa, SELECT)) ) {
+ VECCOPY(v1, efa->v1->co);
+ VECCOPY(v2, efa->v2->co);
+ VECCOPY(v3, efa->v3->co);
+ if (efa->v4) {
+ VECCOPY(v4, efa->v4->co);
+ }
+ if(v3d->flag & V3D_GLOBAL_STATS) {
+ Mat4MulVecfl(ob->obmat, v1);
+ Mat4MulVecfl(ob->obmat, v2);
+ Mat4MulVecfl(ob->obmat, v3);
+ if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
+ }
+
+ if (efa->v4)
+ area= AreaQ3Dfl(v1, v2, v3, v4);
+ else
+ area = AreaT3Dfl(v1, v2, v3);
+
+ sprintf(val, conv_float, area);
+ glRasterPos3fv(efa->cent);
+ BMF_DrawString( G.fonts, val);
+ }
+ }
+ }
+
+ if(me->drawflag & ME_DRAW_EDGEANG) {
+ EditEdge *e1, *e2, *e3, *e4;
+
+ UI_GetThemeColor3fv(TH_TEXT, col);
+ /* make color a bit more blue */
+ if(col[2]> 0.5) {col[0]*=0.7; col[1]*= 0.7;}
+ else col[2]= col[2]*0.7 + 0.3;
+ glColor3fv(col);
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ VECCOPY(v1, efa->v1->co);
+ VECCOPY(v2, efa->v2->co);
+ VECCOPY(v3, efa->v3->co);
+ if(efa->v4) {
+ VECCOPY(v4, efa->v4->co);
+ }
+ else {
+ VECCOPY(v4, v3);
+ }
+ if(v3d->flag & V3D_GLOBAL_STATS) {
+ Mat4MulVecfl(ob->obmat, v1);
+ Mat4MulVecfl(ob->obmat, v2);
+ Mat4MulVecfl(ob->obmat, v3);
+ Mat4MulVecfl(ob->obmat, v4);
+ }
+
+ e1= efa->e1;
+ e2= efa->e2;
+ e3= efa->e3;
+ if(efa->e4) e4= efa->e4; else e4= e3;
+
+ /* Calculate the angles */
+
+ if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
+ /* Vec 1 */
+ sprintf(val,"%.3f", VecAngle3(v4, v1, v2));
+ VecLerpf(fvec, efa->cent, efa->v1->co, 0.8);
+ glRasterPos3fv(fvec);
+ BMF_DrawString( G.fonts, val);
+ }
+ if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
+ /* Vec 2 */
+ sprintf(val,"%.3f", VecAngle3(v1, v2, v3));
+ VecLerpf(fvec, efa->cent, efa->v2->co, 0.8);
+ glRasterPos3fv(fvec);
+ BMF_DrawString( G.fonts, val);
+ }
+ if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
+ /* Vec 3 */
+ if(efa->v4)
+ sprintf(val,"%.3f", VecAngle3(v2, v3, v4));
+ else
+ sprintf(val,"%.3f", VecAngle3(v2, v3, v1));
+ VecLerpf(fvec, efa->cent, efa->v3->co, 0.8);
+ glRasterPos3fv(fvec);
+ BMF_DrawString( G.fonts, val);
+ }
+ /* Vec 4 */
+ if(efa->v4) {
+ if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
+ sprintf(val,"%.3f", VecAngle3(v3, v4, v1));
+ VecLerpf(fvec, efa->cent, efa->v4->co, 0.8);
+ glRasterPos3fv(fvec);
+ BMF_DrawString( G.fonts, val);
+ }
+ }
+ }
+ }
+
+ if(v3d->zbuf) {
+ glEnable(GL_DEPTH_TEST);
+ bglPolygonOffset(rv3d->dist, 0.0);
+ }
+}
+
+static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
+{
+ EditFace *efa = EM_get_face_for_index(index);
+
+ if (efa->h==0) {
+ GPU_enable_material(efa->mat_nr+1, NULL);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
+{
+ EditFace *efa = EM_get_face_for_index(index);
+
+ return (efa->h==0);
+}
+
+static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
+{
+ Mesh *me = ob->data;
+ EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
+ EditEdge *eed_act = NULL;
+ EditVert *eve_act = NULL;
+
+ if (em->selected.last) {
+ EditSelection *ese = em->selected.last;
+ /* face is handeled above */
+ /*if (ese->type == EDITFACE ) {
+ efa_act = (EditFace *)ese->data;
+ } else */ if ( ese->type == EDITEDGE ) {
+ eed_act = (EditEdge *)ese->data;
+ } else if ( ese->type == EDITVERT ) {
+ eve_act = (EditVert *)ese->data;
+ }
+ }
+
+ EM_init_index_arrays(em, 1, 1, 1);
+
+ if(dt>OB_WIRE) {
+ if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
+ if(draw_glsl_material(scene, ob, v3d, dt)) {
+ glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
+
+ finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
+ draw_em_fancy__setGLSLFaceOpts, NULL);
+ GPU_disable_material();
+
+ glFrontFace(GL_CCW);
+ }
+ else {
+ draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
+ }
+ }
+ else {
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
+
+ glEnable(GL_LIGHTING);
+ glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
+
+ finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
+
+ glFrontFace(GL_CCW);
+ glDisable(GL_LIGHTING);
+ }
+
+ // Setup for drawing wire over, disable zbuffer
+ // write to show selected edge wires better
+ UI_ThemeColor(TH_WIRE);
+
+ bglPolygonOffset(rv3d->dist, 1.0);
+ glDepthMask(0);
+ }
+ else {
+ if (cageDM!=finalDM) {
+ UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
+ finalDM->drawEdges(finalDM, 1);
+ }
+ }
+
+ if((me->drawflag & (ME_DRAWFACES)) || FACESEL_PAINT_TEST) { /* transp faces */
+ unsigned char col1[4], col2[4], col3[4];
+
+ UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
+ UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
+ UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
+
+ glEnable(GL_BLEND);
+ glDepthMask(0); // disable write in zbuffer, needed for nice transp
+
+ /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
+ if CHECK_OB_DRAWTEXTURE(v3d, dt)
+ col1[3] = 0;
+
+ draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
+
+ glDisable(GL_BLEND);
+ glDepthMask(1); // restore write in zbuffer
+ } else if (efa_act) {
+ /* even if draw faces is off it would be nice to draw the stipple face
+ * Make all other faces zero alpha except for the active
+ * */
+ unsigned char col1[4], col2[4], col3[4];
+ col1[3] = col2[3] = 0; /* dont draw */
+ UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
+
+ glEnable(GL_BLEND);
+ glDepthMask(0); // disable write in zbuffer, needed for nice transp
+
+ draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
+
+ glDisable(GL_BLEND);
+ glDepthMask(1); // restore write in zbuffer
+
+ }
+
+ /* here starts all fancy draw-extra over */
+ if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
+ /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
+
+ /* only draw selected edges otherwise there is no way of telling if a face is selected */
+ draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
+
+ } else {
+ if(me->drawflag & ME_DRAWSEAMS) {
+ UI_ThemeColor(TH_EDGE_SEAM);
+ glLineWidth(2);
+
+ draw_dm_edges_seams(cageDM);
+
+ glColor3ub(0,0,0);
+ glLineWidth(1);
+ }
+
+ if(me->drawflag & ME_DRAWSHARP) {
+ UI_ThemeColor(TH_EDGE_SHARP);
+ glLineWidth(2);
+
+ draw_dm_edges_sharp(cageDM);
+
+ glColor3ub(0,0,0);
+ glLineWidth(1);
+ }
+
+ if(me->drawflag & ME_DRAWCREASES) {
+ draw_dm_creases(cageDM);
+ }
+ if(me->drawflag & ME_DRAWBWEIGHTS) {
+ draw_dm_bweights(scene, cageDM);
+ }
+
+ draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
+ }
+ if(em) {
+// XXX retopo_matrix_update(v3d);
+
+ draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
+
+ if(me->drawflag & ME_DRAWNORMALS) {
+ UI_ThemeColor(TH_NORMAL);
+ draw_dm_face_normals(scene, cageDM);
+ }
+ if(me->drawflag & ME_DRAW_VNORMALS) {
+ UI_ThemeColor(TH_NORMAL);
+ draw_dm_vert_normals(scene, cageDM);
+ }
+
+ if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG))
+ draw_em_measure_stats(v3d, rv3d, ob, em);
+ }
+
+ if(dt>OB_WIRE) {
+ glDepthMask(1);
+ bglPolygonOffset(rv3d->dist, 0.0);
+ GPU_disable_material();
+ }
+
+ EM_free_index_arrays();
+}
+
+/* Mesh drawing routines */
+
+static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
+{
+
+ if(v3d->transp==0) { // not when we draw the transparent pass
+ glLineWidth(2.0);
+ glDepthMask(0);
+
+ /* if transparent, we cannot draw the edges for solid select... edges have no material info.
+ drawFacesSolid() doesn't draw the transparent faces */
+ if(ob->dtx & OB_DRAWTRANSP) {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ dm->drawFacesSolid(dm, GPU_enable_material);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ GPU_disable_material();
+ }
+ else {
+ dm->drawEdges(dm, 0);
+ }
+
+ glLineWidth(1.0);
+ glDepthMask(1);
+ }
+}
+
+static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
+{
+ *drawSmooth_r = 1;
+ return 1;
+}
+
+static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
+{
+ Object *ob= base->object;
+ Mesh *me = ob->data;
+ Material *ma= give_current_material(ob, 1);
+ int hasHaloMat = (ma && (ma->mode&MA_HALO));
+ int draw_wire = 0;
+ int totvert, totedge, totface;
+ DispList *dl;
+ DerivedMesh *dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
+
+ if(!dm)
+ return;
+
+ if (ob->dtx&OB_DRAWWIRE) {
+ draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
+ }
+
+ totvert = dm->getNumVerts(dm);
+ totedge = dm->getNumEdges(dm);
+ totface = dm->getNumFaces(dm);
+
+ /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
+ if(dt!=OB_SHADED)
+ glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
+
+ // Unwanted combination.
+ if (ob==OBACT && FACESEL_PAINT_TEST) draw_wire = 0;
+
+ if(dt==OB_BOUNDBOX) {
+ draw_bounding_volume(scene, ob);
+ }
+ else if(hasHaloMat || (totface==0 && totedge==0)) {
+ glPointSize(1.5);
+ dm->drawVerts(dm);
+ glPointSize(1.0);
+ }
+ else if(dt==OB_WIRE || totface==0) {
+ draw_wire = 1; /* draw wire only, no depth buffer stuff */
+ }
+ else if( (ob==OBACT && (G.f & G_TEXTUREPAINT || FACESEL_PAINT_TEST)) ||
+ CHECK_OB_DRAWTEXTURE(v3d, dt))
+ {
+ int faceselect= (ob==OBACT && FACESEL_PAINT_TEST);
+
+ if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || FACESEL_PAINT_TEST) && !draw_wire) {
+ draw_mesh_object_outline(v3d, ob, dm);
+ }
+
+ if(draw_glsl_material(scene, ob, v3d, dt)) {
+ glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
+
+ dm->drawFacesGLSL(dm, GPU_enable_material);
+// if(get_ob_property(ob, "Text"))
+// XXX draw_mesh_text(ob, 1);
+ GPU_disable_material();
+
+ glFrontFace(GL_CCW);
+ }
+ else {
+ draw_mesh_textured(scene, v3d, rv3d, ob, dm, faceselect);
+ }
+
+ if(!faceselect) {
+ if(base->flag & SELECT)
+ UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
+ else
+ UI_ThemeColor(TH_WIRE);
+
+ dm->drawLooseEdges(dm);
+ }
+ }
+ else if(dt==OB_SOLID) {
+ if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire)
+ draw_mesh_object_outline(v3d, ob, dm);
+
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
+
+ glEnable(GL_LIGHTING);
+ glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
+
+ dm->drawFacesSolid(dm, GPU_enable_material);
+ GPU_disable_material();
+
+ glFrontFace(GL_CCW);
+ glDisable(GL_LIGHTING);
+
+ if(base->flag & SELECT) {
+ UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
+ } else {
+ UI_ThemeColor(TH_WIRE);
+ }
+ dm->drawLooseEdges(dm);
+ }
+ else if(dt==OB_SHADED) {
+ int do_draw= 1; /* to resolve all G.f settings below... */
+
+ if(ob==OBACT) {
+ do_draw= 0;
+ if( (G.f & G_WEIGHTPAINT)) {
+ /* enforce default material settings */
+ GPU_enable_material(0, NULL);
+
+ /* but set default spec */
+ glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
+ glEnable(GL_COLOR_MATERIAL); /* according manpages needed */
+ glColor3ub(120, 120, 120);
+ glDisable(GL_COLOR_MATERIAL);
+ /* diffuse */
+ glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_COLOR_MATERIAL);
+
+ dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
+ glDisable(GL_COLOR_MATERIAL);
+ glDisable(GL_LIGHTING);
+
+ GPU_disable_material();
+ }
+ else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->mcol) {
+ dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
+ }
+ else if(G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) {
+ glColor3f(1.0f, 1.0f, 1.0f);
+ dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
+ }
+ else do_draw= 1;
+ }
+ if(do_draw) {
+ dl = ob->disp.first;
+ if (!dl || !dl->col1) {
+ /* release and reload derivedmesh because it might be freed in
+ shadeDispList due to a different datamask */
+ dm->release(dm);
+ shadeDispList(scene, base);
+ dl = find_displist(&ob->disp, DL_VERTCOL);
+ dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
+ }
+
+ if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
+ draw_mesh_object_outline(v3d, ob, dm);
+ }
+
+ /* False for dupliframe objects */
+ if (dl) {
+ unsigned int *obCol1 = dl->col1;
+ unsigned int *obCol2 = dl->col2;
+
+ dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
+ }
+
+ if(base->flag & SELECT) {
+ UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
+ } else {
+ UI_ThemeColor(TH_WIRE);
+ }
+ dm->drawLooseEdges(dm);
+ }
+ }
+
+ /* set default draw color back for wire or for draw-extra later on */
+ if (dt!=OB_WIRE) {
+ if(base->flag & SELECT) {
+ if(ob==OBACT && ob->flag & OB_FROMGROUP)
+ UI_ThemeColor(TH_GROUP_ACTIVE);
+ else if(ob->flag & OB_FROMGROUP)
+ UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
+ else if(flag!=DRAW_CONSTCOLOR)
+ UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
+ else
+ glColor3ub(80,80,80);
+ } else {
+ if (ob->flag & OB_FROMGROUP)
+ UI_ThemeColor(TH_GROUP);
+ else {
+ if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
+ glColor3ub(80,80,80);
+ else
+ UI_ThemeColor(TH_WIRE);
+ }
+ }
+ }
+ if (draw_wire) {
+ /* If drawing wire and drawtype is not OB_WIRE then we are
+ * overlaying the wires.
+ *
+ * UPDATE bug #10290 - With this wire-only objects can draw
+ * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
+ *
+ * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
+ * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
+ */
+ if (dt!=OB_WIRE && draw_wire==2) {
+ bglPolygonOffset(rv3d->dist, 1.0);
+ glDepthMask(0); // disable write in zbuffer, selected edge wires show better
+ }
+
+ dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
+
+ if (dt!=OB_WIRE && draw_wire==2) {
+ glDepthMask(1);
+ bglPolygonOffset(rv3d->dist, 0.0);
+ }
+ }
+
+ dm->release(dm);
+}
+
+/* returns 1 if nothing was drawn, for detecting to draw an object center */
+static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
+{
+ Object *ob= base->object;
+ Object *obedit= scene->obedit;
+ Mesh *me= ob->data;
+ EditMesh *em= me->edit_mesh;
+ int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
+
+ if(obedit && ob!=obedit && ob->data==obedit->data) {
+ if(ob_get_key(ob));
+ else drawlinked= 1;
+ }
+
+ if(ob==obedit || drawlinked) {
+ DerivedMesh *finalDM, *cageDM;
+
+ if (obedit!=ob)
+ finalDM = cageDM = editmesh_get_derived_base(ob, em);
+ else
+ cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
+ v3d->customdata_mask);
+
+ if(dt>OB_WIRE) {
+ // no transp in editmode, the fancy draw over goes bad then
+ glsl = draw_glsl_material(scene, ob, v3d, dt);
+ GPU_set_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
+ }
+
+ draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
+
+ if (obedit!=ob && finalDM)
+ finalDM->release(finalDM);
+ }
+// else if(!em && (G.f & G_SCULPTMODE) &&(scene->sculptdata.flags & SCULPT_DRAW_FAST) &&
+// OBACT==ob && !sculpt_modifiers_active(ob)) {
+// XXX sculptmode_draw_mesh(0);
+// }
+ else {
+ /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
+ if(me->totface<=4 || boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
+ glsl = draw_glsl_material(scene, ob, v3d, dt);
+ check_alpha = check_material_alpha(base, me, glsl);
+
+ if(dt==OB_SOLID || glsl) {
+ GPU_set_object_materials(v3d, rv3d, scene, ob, glsl,
+ (check_alpha)? &do_alpha_pass: NULL);
+ }
+
+ draw_mesh_fancy(scene, v3d, rv3d, base, dt, flag);
+
+ if(me->totvert==0) retval= 1;
+ }
+ }
+
+ /* GPU_set_object_materials checked if this is needed */
+ if(do_alpha_pass) add_view3d_after(v3d, base, V3D_TRANSP, flag);
+
+ return retval;
+}
+
+/* ************** DRAW DISPLIST ****************** */
+
+static int draw_index_wire= 1;
+static int index3_nors_incr= 1;
+
+/* returns 1 when nothing was drawn */
+static int drawDispListwire(ListBase *dlbase)
+{
+ DispList *dl;
+ int parts, nr;
+ float *data;
+
+ if(dlbase==NULL) return 1;
+
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ for(dl= dlbase->first; dl; dl= dl->next) {
+ if(dl->parts==0 || dl->nr==0)
+ continue;
+
+ data= dl->verts;
+
+ switch(dl->type) {
+ case DL_SEGM:
+
+ glVertexPointer(3, GL_FLOAT, 0, data);
+
+ for(parts=0; parts<dl->parts; parts++)
+ glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
+
+ break;
+ case DL_POLY:
+
+ glVertexPointer(3, GL_FLOAT, 0, data);
+
+ for(parts=0; parts<dl->parts; parts++)
+ glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
+
+ break;
+ case DL_SURF:
+
+ glVertexPointer(3, GL_FLOAT, 0, data);
+
+ for(parts=0; parts<dl->parts; parts++) {
+ if(dl->flag & DL_CYCL_U)
+ glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
+ else
+ glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
+ }
+
+ for(nr=0; nr<dl->nr; nr++) {
+ int ofs= 3*dl->nr;
+
+ data= ( dl->verts )+3*nr;
+ parts= dl->parts;
+
+ if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
+ else glBegin(GL_LINE_STRIP);
+
+ while(parts--) {
+ glVertex3fv(data);
+ data+=ofs;
+ }
+ glEnd();
+
+ /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
+// glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
+// if(dl->flag & DL_CYCL_V)
+// glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
+// else
+// glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
+ }
+ break;
+
+ case DL_INDEX3:
+ if(draw_index_wire) {
+ glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+ glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
+ }
+ break;
+
+ case DL_INDEX4:
+ if(draw_index_wire) {
+ glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+ glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
+ }
+ break;
+ }
+ }
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ return 0;
+}
+
+static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
+{
+ DispList *dl;
+ GPUVertexAttribs gattribs;
+ float *data, curcol[4];
+ float *ndata;
+
+ if(lb==NULL) return;
+
+ /* for drawing wire */
+ glGetFloatv(GL_CURRENT_COLOR, curcol);
+
+ glEnable(GL_LIGHTING);
+
+ if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
+ else glFrontFace(GL_CCW);
+
+ if(ob->type==OB_MBALL) { // mball always smooth shaded
+ glShadeModel(GL_SMOOTH);
+ }
+
+ dl= lb->first;
+ while(dl) {
+ data= dl->verts;
+ ndata= dl->nors;
+
+ switch(dl->type) {
+ case DL_SEGM:
+ if(ob->type==OB_SURF) {
+ int nr;
+
+ glDisable(GL_LIGHTING);
+ glColor3fv(curcol);
+
+ // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+ // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
+
+ glBegin(GL_LINE_STRIP);
+ for(nr= dl->nr; nr; nr--, data+=3)
+ glVertex3fv(data);
+ glEnd();
+
+ glEnable(GL_LIGHTING);
+ }
+ break;
+ case DL_POLY:
+ if(ob->type==OB_SURF) {
+ int nr;
+
+ UI_ThemeColor(TH_WIRE);
+ glDisable(GL_LIGHTING);
+
+ /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
+ //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+ //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
+
+ glBegin(GL_LINE_LOOP);
+ for(nr= dl->nr; nr; nr--, data+=3)
+ glVertex3fv(data);
+ glEnd();
+
+ glEnable(GL_LIGHTING);
+ break;
+ }
+ case DL_SURF:
+
+ if(dl->index) {
+ GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
+
+ if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
+ else glShadeModel(GL_FLAT);
+
+ glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+ glNormalPointer(GL_FLOAT, 0, dl->nors);
+ glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
+ GPU_disable_material();
+ }
+ break;
+
+ case DL_INDEX3:
+ GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
+
+ glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+
+ /* voor polys only one normal needed */
+ if(index3_nors_incr==0) {
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glNormal3fv(ndata);
+ }
+ else
+ glNormalPointer(GL_FLOAT, 0, dl->nors);
+
+ glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
+ GPU_disable_material();
+
+ if(index3_nors_incr==0)
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ break;
+
+ case DL_INDEX4:
+ GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
+
+ glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+ glNormalPointer(GL_FLOAT, 0, dl->nors);
+ glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
+
+ GPU_disable_material();
+
+ break;
+ }
+ dl= dl->next;
+ }
+
+ glShadeModel(GL_FLAT);
+ glDisable(GL_LIGHTING);
+ glFrontFace(GL_CCW);
+}
+
+static void drawDispListshaded(ListBase *lb, Object *ob)
+{
+ DispList *dl, *dlob;
+ unsigned int *cdata;
+
+ if(lb==NULL) return;
+
+ glShadeModel(GL_SMOOTH);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+
+ dl= lb->first;
+ dlob= ob->disp.first;
+ while(dl && dlob) {
+
+ cdata= dlob->col1;
+ if(cdata==NULL) break;
+
+ switch(dl->type) {
+ case DL_SURF:
+ if(dl->index) {
+ glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
+ glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
+ }
+ break;
+
+ case DL_INDEX3:
+
+ glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
+ glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
+ break;
+
+ case DL_INDEX4:
+
+ glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
+ glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
+ break;
+ }
+
+ dl= dl->next;
+ dlob= dlob->next;
+ }
+
+ glShadeModel(GL_FLAT);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+}
+
+/* returns 1 when nothing was drawn */
+static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt)
+{
+ Object *ob= base->object;
+ ListBase *lb=0;
+ DispList *dl;
+ Curve *cu;
+ int solid, retval= 0;
+
+ solid= (dt > OB_WIRE);
+
+ switch(ob->type) {
+ case OB_FONT:
+ case OB_CURVE:
+ cu= ob->data;
+
+ lb= &cu->disp;
+
+ if(solid) {
+ dl= lb->first;
+ if(dl==NULL) return 1;
+
+ if(dl->nors==0) addnormalsDispList(ob, lb);
+ index3_nors_incr= 0;
+
+ if( displist_has_faces(lb)==0) {
+ draw_index_wire= 0;
+ drawDispListwire(lb);
+ draw_index_wire= 1;
+ }
+ else {
+ if(draw_glsl_material(scene, ob, v3d, dt)) {
+ GPU_set_object_materials(v3d, rv3d, scene, ob, 1, NULL);
+ drawDispListsolid(lb, ob, 1);
+ }
+ else if(dt == OB_SHADED) {
+ if(ob->disp.first==0) shadeDispList(scene, base);
+ drawDispListshaded(lb, ob);
+ }
+ else {
+ GPU_set_object_materials(v3d, rv3d, scene, ob, 0, NULL);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
+ drawDispListsolid(lb, ob, 0);
+ }
+ if(cu->editnurb && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0 && cu->ext2 == 0.0) {
+ cpack(0);
+ draw_index_wire= 0;
+ drawDispListwire(lb);
+ draw_index_wire= 1;
+ }
+ }
+ index3_nors_incr= 1;
+ }
+ else {
+ draw_index_wire= 0;
+ retval= drawDispListwire(lb);
+ draw_index_wire= 1;
+ }
+ break;
+ case OB_SURF:
+
+ lb= &((Curve *)ob->data)->disp;
+
+ if(solid) {
+ dl= lb->first;
+ if(dl==NULL) return 1;
+
+ if(dl->nors==NULL) addnormalsDispList(ob, lb);
+
+ if(draw_glsl_material(scene, ob, v3d, dt)) {
+ GPU_set_object_materials(v3d, rv3d, scene, ob, 1, NULL);
+ drawDispListsolid(lb, ob, 1);
+ }
+ else if(dt==OB_SHADED) {
+ if(ob->disp.first==NULL) shadeDispList(scene, base);
+ drawDispListshaded(lb, ob);
+ }
+ else {
+ GPU_set_object_materials(v3d, rv3d, scene, ob, 0, NULL);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
+
+ drawDispListsolid(lb, ob, 0);
+ }
+ }
+ else {
+ retval= drawDispListwire(lb);
+ }
+ break;
+ case OB_MBALL:
+
+ if( is_basis_mball(ob)) {
+ lb= &ob->disp;
+ if(lb->first==NULL) makeDispListMBall(scene, ob);
+ if(lb->first==NULL) return 1;
+
+ if(solid) {
+
+ if(draw_glsl_material(scene, ob, v3d, dt)) {
+ GPU_set_object_materials(v3d, rv3d, scene, ob, 1, NULL);
+ drawDispListsolid(lb, ob, 1);
+ }
+ else if(dt == OB_SHADED) {
+ dl= lb->first;
+ if(dl && dl->col1==0) shadeDispList(scene, base);
+ drawDispListshaded(lb, ob);
+ }
+ else {
+ GPU_set_object_materials(v3d, rv3d, scene, ob, 0, NULL);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
+
+ drawDispListsolid(lb, ob, 0);
+ }
+ }
+ else{
+ /* MetaBalls use DL_INDEX4 type of DispList */
+ retval= drawDispListwire(lb);
+ }
+ }
+ break;
+ }
+
+ return retval;
+}
+
+/* unified drawing of all new particle systems draw types except dupli ob & group */
+/* mostly tries to use vertex arrays for speed */
+
+/* 1. check that everything is ok & updated */
+/* 2. start initialising things */
+/* 3. initialize according to draw type */
+/* 4. allocate drawing data arrays */
+/* 5. start filling the arrays */
+/* 6. draw the arrays */
+/* 7. clean up */
+static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, ParticleSystem *psys, int dt)
+{
+ Object *ob=base->object;
+ ParticleSystemModifierData *psmd;
+ ParticleSettings *part;
+ ParticleData *pars, *pa;
+ ParticleKey state, *states=0;
+ ParticleBillboardData bb;
+ Material *ma;
+ float vel[3], vec[3], vec2[3], imat[4][4], bb_center[3];
+ float timestep, pixsize=1.0, pa_size, pa_time, r_tilt;
+ float cfra= bsystem_time(scene, ob,(float)CFRA,0.0);
+ float *vdata=0, *vedata=0, *cdata=0, *ndata=0, *vd=0, *ved=0, *cd=0, *nd=0, xvec[3], yvec[3], zvec[3];
+ float ma_r=0.0f, ma_g=0.0f, ma_b=0.0f;
+ int a, totpart, totpoint=0, draw_as, totchild=0;
+ int select=ob->flag&SELECT, create_cdata=0;
+ GLint polygonmode[2];
+ char val[32];
+
+/* 1. */
+ if(psys==0)
+ return;
+
+ part=psys->part;
+ pars=psys->particles;
+
+ if(part==0 || !psys_check_enabled(ob, psys))
+ return;
+
+ if(pars==0) return;
+
+ // XXX what logic is this?
+ if(!scene->obedit && psys_in_edit_mode(scene, psys)
+ && psys->flag & PSYS_HAIR_DONE && part->draw_as==PART_DRAW_PATH)
+ return;
+
+ if(part->draw_as==PART_DRAW_NOT) return;
+
+/* 2. */
+ if(part->phystype==PART_PHYS_KEYED){
+ if(psys->flag & PSYS_FIRST_KEYED){
+ if(psys->flag&PSYS_KEYED){
+ select=psys_count_keyed_targets(ob,psys);
+ if(psys->totkeyed==0)
+ return;
+ }
+ }
+ else
+ return;
+ }
+
+ if(select){
+ select=0;
+ if(psys_get_current(ob)==psys)
+ select=1;
+ }
+
+ psys->flag|=PSYS_DRAWING;
+
+ if(part->type==PART_HAIR && !psys->childcache)
+ totchild=0;
+ else
+ totchild=psys->totchild*part->disp/100;
+
+ ma= give_current_material(ob,part->omat);
+
+ if(ma) {
+ ma_r = ma->r;
+ ma_g = ma->g;
+ ma_b = ma->b;
+ }
+
+ if(v3d->zbuf) glDepthMask(1);
+
+ if(select)
+ cpack(0xFFFFFF);
+ else if((ma) && (part->draw&PART_DRAW_MAT_COL)) {
+ glColor3f(ma->r,ma->g,ma->b);
+ create_cdata = 1;
+ }
+ else
+ cpack(0);
+
+ psmd= psys_get_modifier(ob,psys);
+
+ timestep= psys_get_timestep(part);
+
+ wmLoadMatrix(rv3d->viewmat);
+
+ if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) {
+ float mat[4][4];
+ Mat4MulMat4(mat, psys->imat, ob->obmat);
+ wmMultMatrix(mat);
+ }
+
+ totpart=psys->totpart;
+ draw_as=part->draw_as;
+
+ if(part->flag&PART_GLOB_TIME)
+ cfra=bsystem_time(scene, 0, (float)CFRA, 0.0f);
+
+ if(draw_as==PART_DRAW_PATH && psys->pathcache==NULL)
+ draw_as=PART_DRAW_DOT;
+
+/* 3. */
+ switch(draw_as){
+ case PART_DRAW_DOT:
+ if(part->draw_size)
+ glPointSize(part->draw_size);
+ else
+ glPointSize(2.0); /* default dot size */
+ break;
+ case PART_DRAW_CIRC:
+ /* calculate view aligned matrix: */
+ Mat4CpyMat4(imat, rv3d->viewinv);
+ Normalize(imat[0]);
+ Normalize(imat[1]);
+ /* no break! */
+ case PART_DRAW_CROSS:
+ case PART_DRAW_AXIS:
+ /* lets calculate the scale: */
+ pixsize= rv3d->persmat[0][3]*ob->obmat[3][0]+ rv3d->persmat[1][3]*ob->obmat[3][1]+ rv3d->persmat[2][3]*ob->obmat[3][2]+ rv3d->persmat[3][3];
+ pixsize*= rv3d->pixsize;
+ if(part->draw_size==0.0)
+ pixsize*=2.0;
+ else
+ pixsize*=part->draw_size;
+ break;
+ case PART_DRAW_OB:
+ if(part->dup_ob==0)
+ draw_as=PART_DRAW_DOT;
+ else
+ draw_as=0;
+ break;
+ case PART_DRAW_GR:
+ if(part->dup_group==0)
+ draw_as=PART_DRAW_DOT;
+ else
+ draw_as=0;
+ break;
+ case PART_DRAW_BB:
+ if(v3d->camera==0 && part->bb_ob==0){
+ printf("Billboards need an active camera or a target object!\n");
+
+ draw_as=part->draw_as=PART_DRAW_DOT;
+
+ if(part->draw_size)
+ glPointSize(part->draw_size);
+ else
+ glPointSize(2.0); /* default dot size */
+ }
+ else if(part->bb_ob)
+ bb.ob=part->bb_ob;
+ else
+ bb.ob=v3d->camera;
+
+ bb.align = part->bb_align;
+ bb.anim = part->bb_anim;
+ bb.lock = part->draw & PART_DRAW_BB_LOCK;
+ bb.offset[0] = part->bb_offset[0];
+ bb.offset[1] = part->bb_offset[1];
+ break;
+ case PART_DRAW_PATH:
+ break;
+ }
+ if(part->draw & PART_DRAW_SIZE && part->draw_as!=PART_DRAW_CIRC){
+ Mat4CpyMat4(imat, rv3d->viewinv);
+ Normalize(imat[0]);
+ Normalize(imat[1]);
+ }
+
+/* 4. */
+ if(draw_as && draw_as!=PART_DRAW_PATH) {
+ int tot_vec_size = (totpart + totchild) * 3 * sizeof(float);
+
+ if(draw_as!=PART_DRAW_CIRC) {
+ switch(draw_as) {
+ case PART_DRAW_AXIS:
+ case PART_DRAW_CROSS:
+ if(draw_as != PART_DRAW_CROSS || create_cdata)
+ cdata = MEM_callocN(tot_vec_size * 6, "particle_cdata");
+ vdata = MEM_callocN(tot_vec_size * 6, "particle_vdata");
+ break;
+ case PART_DRAW_LINE:
+ if(create_cdata)
+ cdata = MEM_callocN(tot_vec_size * 2, "particle_cdata");
+ vdata = MEM_callocN(tot_vec_size * 2, "particle_vdata");
+ break;
+ case PART_DRAW_BB:
+ if(create_cdata)
+ cdata = MEM_callocN(tot_vec_size * 4, "particle_cdata");
+ vdata = MEM_callocN(tot_vec_size * 4, "particle_vdata");
+ ndata = MEM_callocN(tot_vec_size * 4, "particle_vdata");
+ break;
+ default:
+ if(create_cdata)
+ cdata=MEM_callocN(tot_vec_size, "particle_cdata");
+ vdata=MEM_callocN(tot_vec_size, "particle_vdata");
+ }
+ }
+
+ if(part->draw & PART_DRAW_VEL && draw_as != PART_DRAW_LINE)
+ vedata = MEM_callocN(tot_vec_size * 2, "particle_vedata");
+
+ vd=vdata;
+ ved=vedata;
+ cd=cdata;
+ nd=ndata;
+
+ psys->lattice= psys_get_lattice(scene, ob, psys);
+ }
+
+ if(draw_as){
+/* 5. */
+ for(a=0,pa=pars; a<totpart+totchild; a++, pa++){
+ /* setup per particle individual stuff */
+ if(a<totpart){
+ if(totchild && (part->draw&PART_DRAW_PARENT)==0) continue;
+ if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue;
+
+ pa_time=(cfra-pa->time)/pa->lifetime;
+ pa_size=pa->size;
+
+ if((part->flag&PART_ABS_TIME)==0){
+#if 0 // XXX old animation system
+ if(ma && ma->ipo){
+ IpoCurve *icu;
+
+ /* correction for lifetime */
+ calc_ipo(ma->ipo, 100.0f*pa_time);
+
+ for(icu = ma->ipo->curve.first; icu; icu=icu->next) {
+ if(icu->adrcode == MA_COL_R)
+ ma_r = icu->curval;
+ else if(icu->adrcode == MA_COL_G)
+ ma_g = icu->curval;
+ else if(icu->adrcode == MA_COL_B)
+ ma_b = icu->curval;
+ }
+ }
+ if(part->ipo) {
+ IpoCurve *icu;
+
+ /* correction for lifetime */
+ calc_ipo(part->ipo, 100*pa_time);
+
+ for(icu = part->ipo->curve.first; icu; icu=icu->next) {
+ if(icu->adrcode == PART_SIZE)
+ pa_size = icu->curval;
+ }
+ }
+#endif // XXX old animation system
+ }
+
+ r_tilt=1.0f+pa->r_ave[0];
+ }
+ else{
+ ChildParticle *cpa= &psys->child[a-totpart];
+
+ pa_time=psys_get_child_time(psys,cpa,cfra);
+
+ if((part->flag&PART_ABS_TIME)==0) {
+ if(ma && ma->ipo){
+#if 0 // XXX old animation system
+ IpoCurve *icu;
+
+ /* correction for lifetime */
+ calc_ipo(ma->ipo, 100.0f*pa_time);
+
+ for(icu = ma->ipo->curve.first; icu; icu=icu->next) {
+ if(icu->adrcode == MA_COL_R)
+ ma_r = icu->curval;
+ else if(icu->adrcode == MA_COL_G)
+ ma_g = icu->curval;
+ else if(icu->adrcode == MA_COL_B)
+ ma_b = icu->curval;
+ }
+#endif // XXX old animation system
+ }
+ }
+
+ pa_size=psys_get_child_size(psys,cpa,cfra,0);
+
+ r_tilt=2.0f*cpa->rand[2];
+ }
+
+ if(draw_as!=PART_DRAW_PATH){
+ state.time=cfra;
+ if(psys_get_particle_state(scene,ob,psys,a,&state,0)){
+ /* create actiual particle data */
+ switch(draw_as){
+ case PART_DRAW_DOT:
+ if(vd){
+ VECCOPY(vd,state.co) vd+=3;
+ }
+ if(cd) {
+ cd[0]=ma_r;
+ cd[1]=ma_g;
+ cd[2]=ma_b;
+ cd+=3;
+ }
+ break;
+ case PART_DRAW_CROSS:
+ case PART_DRAW_AXIS:
+ vec[0]=2.0f*pixsize;
+ vec[1]=vec[2]=0.0;
+ QuatMulVecf(state.rot,vec);
+ if(draw_as==PART_DRAW_AXIS){
+ cd[1]=cd[2]=cd[4]=cd[5]=0.0;
+ cd[0]=cd[3]=1.0;
+ cd[6]=cd[8]=cd[9]=cd[11]=0.0;
+ cd[7]=cd[10]=1.0;
+ cd[13]=cd[12]=cd[15]=cd[16]=0.0;
+ cd[14]=cd[17]=1.0;
+ cd+=18;
+
+ VECCOPY(vec2,state.co);
+ }
+ else {
+ if(cd) {
+ cd[0]=cd[3]=cd[6]=cd[9]=cd[12]=cd[15]=ma_r;
+ cd[1]=cd[4]=cd[7]=cd[10]=cd[13]=cd[16]=ma_g;
+ cd[2]=cd[5]=cd[8]=cd[11]=cd[14]=cd[17]=ma_b;
+ cd+=18;
+ }
+ VECSUB(vec2,state.co,vec);
+ }
+
+ VECADD(vec,state.co,vec);
+ VECCOPY(vd,vec); vd+=3;
+ VECCOPY(vd,vec2); vd+=3;
+
+ vec[1]=2.0f*pixsize;
+ vec[0]=vec[2]=0.0;
+ QuatMulVecf(state.rot,vec);
+ if(draw_as==PART_DRAW_AXIS){
+ VECCOPY(vec2,state.co);
+ }
+ else VECSUB(vec2,state.co,vec);
+
+ VECADD(vec,state.co,vec);
+ VECCOPY(vd,vec); vd+=3;
+ VECCOPY(vd,vec2); vd+=3;
+
+ vec[2]=2.0f*pixsize;
+ vec[0]=vec[1]=0.0;
+ QuatMulVecf(state.rot,vec);
+ if(draw_as==PART_DRAW_AXIS){
+ VECCOPY(vec2,state.co);
+ }
+ else VECSUB(vec2,state.co,vec);
+
+ VECADD(vec,state.co,vec);
+
+ VECCOPY(vd,vec); vd+=3;
+ VECCOPY(vd,vec2); vd+=3;
+ break;
+ case PART_DRAW_LINE:
+ VECCOPY(vec,state.vel);
+ Normalize(vec);
+ if(part->draw & PART_DRAW_VEL_LENGTH)
+ VecMulf(vec,VecLength(state.vel));
+ VECADDFAC(vd,state.co,vec,-part->draw_line[0]); vd+=3;
+ VECADDFAC(vd,state.co,vec,part->draw_line[1]); vd+=3;
+ if(cd) {
+ cd[0]=cd[3]=ma_r;
+ cd[1]=cd[4]=ma_g;
+ cd[2]=cd[5]=ma_b;
+ cd+=3;
+ }
+ break;
+ case PART_DRAW_CIRC:
+ if(create_cdata)
+ glColor3f(ma_r,ma_g,ma_b);
+ drawcircball(GL_LINE_LOOP, state.co, pixsize, imat);
+ break;
+ case PART_DRAW_BB:
+ if(cd) {
+ cd[0]=cd[3]=cd[6]=cd[9]=ma_r;
+ cd[1]=cd[4]=cd[7]=cd[10]=ma_g;
+ cd[2]=cd[5]=cd[8]=cd[11]=ma_b;
+ cd+=12;
+ }
+
+ bb.size = pa_size;
+ bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
+ bb.time = pa_time;
+ VECCOPY(bb.vec, state.co);
+ VECCOPY(bb.vel, state.vel);
+
+ psys_make_billboard(&bb, xvec, yvec, zvec, bb_center);
+
+ VECADD(vd,bb_center,xvec);
+ VECADD(vd,vd,yvec); vd+=3;
+
+ VECSUB(vd,bb_center,xvec);
+ VECADD(vd,vd,yvec); vd+=3;
+
+ VECSUB(vd,bb_center,xvec);
+ VECSUB(vd,vd,yvec); vd+=3;
+
+ VECADD(vd,bb_center,xvec);
+ VECSUB(vd,vd,yvec); vd+=3;
+
+ VECCOPY(nd, zvec); nd+=3;
+ VECCOPY(nd, zvec); nd+=3;
+ VECCOPY(nd, zvec); nd+=3;
+ VECCOPY(nd, zvec); nd+=3;
+ break;
+ }
+
+ totpoint++;
+
+ /* additional things to draw for each particle */
+ /* (velocity, size and number) */
+ if(vedata){
+ VECCOPY(ved,state.co);
+ ved+=3;
+ VECCOPY(vel,state.vel);
+ VecMulf(vel,timestep);
+ VECADD(ved,state.co,vel);
+ ved+=3;
+ }
+
+ if(part->draw & PART_DRAW_SIZE){
+ setlinestyle(3);
+ drawcircball(GL_LINE_LOOP, state.co, pa_size, imat);
+ setlinestyle(0);
+ }
+
+ if(part->draw&PART_DRAW_NUM && !(G.f & G_RENDER_SHADOW)){
+ /* in path drawing state.co is the end point */
+ glRasterPos3f(state.co[0], state.co[1], state.co[2]);
+ sprintf(val," %i",a);
+ BMF_DrawString(G.font, val);
+ }
+ }
+ }
+ }
+/* 6. */
+
+ glGetIntegerv(GL_POLYGON_MODE, polygonmode);
+ glDisableClientState(GL_NORMAL_ARRAY);
+
+ if(draw_as==PART_DRAW_PATH){
+ ParticleCacheKey **cache, *path;
+ float *cd2=0,*cdata2=0;
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ /* setup gl flags */
+ if(dt > OB_WIRE) {
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ if(part->draw&PART_DRAW_MAT_COL)
+ glEnableClientState(GL_COLOR_ARRAY);
+
+ glEnable(GL_LIGHTING);
+ glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+ glEnable(GL_COLOR_MATERIAL);
+ }
+ else {
+ glDisableClientState(GL_NORMAL_ARRAY);
+
+ glDisable(GL_COLOR_MATERIAL);
+ glDisable(GL_LIGHTING);
+ UI_ThemeColor(TH_WIRE);
+ }
+
+ if(totchild && (part->draw&PART_DRAW_PARENT)==0)
+ totpart=0;
+
+ /* draw actual/parent particles */
+ cache=psys->pathcache;
+ for(a=0, pa=psys->particles; a<totpart; a++, pa++){
+ path=cache[a];
+ if(path->steps > 0) {
+ glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
+
+ if(dt > OB_WIRE) {
+ glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
+ if(part->draw&PART_DRAW_MAT_COL)
+ glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
+ }
+
+ glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
+ }
+ }
+
+ /* draw child particles */
+ cache=psys->childcache;
+ for(a=0; a<totchild; a++){
+ path=cache[a];
+ glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
+
+ if(dt > OB_WIRE) {
+ glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
+ if(part->draw&PART_DRAW_MAT_COL)
+ glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
+ }
+
+ glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
+ }
+
+
+ /* restore & clean up */
+ if(dt > OB_WIRE) {
+ if(part->draw&PART_DRAW_MAT_COL)
+ glDisable(GL_COLOR_ARRAY);
+ glDisable(GL_COLOR_MATERIAL);
+ }
+
+ if(cdata2)
+ MEM_freeN(cdata2);
+ cd2=cdata2=0;
+
+ glLineWidth(1.0f);
+ }
+ else if(draw_as!=PART_DRAW_CIRC){
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ /* setup created data arrays */
+ if(vdata){
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, vdata);
+ }
+ else
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ if(ndata && dt>OB_WIRE){
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(GL_FLOAT, 0, ndata);
+ glEnable(GL_LIGHTING);
+ }
+ else{
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisable(GL_LIGHTING);
+ }
+
+ if(cdata){
+ glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(3, GL_FLOAT, 0, cdata);
+ }
+
+
+ /* draw created data arrays */
+ switch(draw_as){
+ case PART_DRAW_AXIS:
+ case PART_DRAW_CROSS:
+ glDrawArrays(GL_LINES, 0, 6*totpoint);
+ break;
+ case PART_DRAW_LINE:
+ glDrawArrays(GL_LINES, 0, 2*totpoint);
+ break;
+ case PART_DRAW_BB:
+ if(dt<=OB_WIRE)
+ glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+
+ glDrawArrays(GL_QUADS, 0, 4*totpoint);
+ break;
+ default:
+ glDrawArrays(GL_POINTS, 0, totpoint);
+ break;
+ }
+ }
+
+ if(vedata){
+ glDisableClientState(GL_COLOR_ARRAY);
+ cpack(0xC0C0C0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, vedata);
+
+ glDrawArrays(GL_LINES, 0, 2*totpoint);
+ }
+
+ glPolygonMode(GL_FRONT, polygonmode[0]);
+ glPolygonMode(GL_BACK, polygonmode[1]);
+ }
+
+/* 7. */
+
+ glDisable(GL_LIGHTING);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ if(states)
+ MEM_freeN(states);
+ if(vdata)
+ MEM_freeN(vdata);
+ if(vedata)
+ MEM_freeN(vedata);
+ if(cdata)
+ MEM_freeN(cdata);
+ if(ndata)
+ MEM_freeN(ndata);
+
+ psys->flag &= ~PSYS_DRAWING;
+
+ if(psys->lattice){
+ end_latt_deform(psys->lattice);
+ psys->lattice= NULL;
+ }
+
+ wmLoadMatrix(rv3d->viewmat);
+ wmMultMatrix(ob->obmat); // bring back local matrix for dtx
+}
+
+static void draw_particle_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, ParticleSystem *psys, int dt)
+{
+ ParticleEdit *edit = psys->edit;
+ ParticleData *pa;
+ ParticleCacheKey **path;
+ ParticleEditKey *key;
+ ParticleEditSettings *pset = PE_settings(scene);
+ int i, k, totpart = psys->totpart, totchild=0, timed = pset->draw_timed;
+ char nosel[4], sel[4];
+ float sel_col[3];
+ float nosel_col[3];
+ char val[32];
+
+ /* create path and child path cache if it doesn't exist already */
+ if(psys->pathcache==0){
+ PE_hide_keys_time(scene, psys,CFRA);
+ psys_cache_paths(scene, ob, psys, CFRA,0);
+ }
+ if(psys->pathcache==0)
+ return;
+
+ if(pset->flag & PE_SHOW_CHILD && psys->part->draw_as == PART_DRAW_PATH) {
+ if(psys->childcache==0)
+ psys_cache_child_paths(scene, ob, psys, CFRA, 0);
+ }
+ else if(!(pset->flag & PE_SHOW_CHILD) && psys->childcache)
+ free_child_path_cache(psys);
+
+ /* opengl setup */
+ if((v3d->flag & V3D_ZBUF_SELECT)==0)
+ glDisable(GL_DEPTH_TEST);
+
+ wmLoadMatrix(rv3d->viewmat);
+
+ /* get selection theme colors */
+ UI_GetThemeColor3ubv(TH_VERTEX_SELECT, sel);
+ UI_GetThemeColor3ubv(TH_VERTEX, nosel);
+ sel_col[0]=(float)sel[0]/255.0f;
+ sel_col[1]=(float)sel[1]/255.0f;
+ sel_col[2]=(float)sel[2]/255.0f;
+ nosel_col[0]=(float)nosel[0]/255.0f;
+ nosel_col[1]=(float)nosel[1]/255.0f;
+ nosel_col[2]=(float)nosel[2]/255.0f;
+
+ if(psys->childcache)
+ totchild = psys->totchildcache;
+
+ /* draw paths */
+ if(timed)
+ glEnable(GL_BLEND);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ if(dt > OB_WIRE) {
+ /* solid shaded with lighting */
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+
+ glEnable(GL_COLOR_MATERIAL);
+ glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+ }
+ else {
+ /* flat wire color */
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisable(GL_LIGHTING);
+ UI_ThemeColor(TH_WIRE);
+ }
+
+ /* only draw child paths with lighting */
+ if(dt > OB_WIRE)
+ glEnable(GL_LIGHTING);
+
+ if(psys->part->draw_as == PART_DRAW_PATH) {
+ for(i=0, path=psys->childcache; i<totchild; i++,path++){
+ glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co);
+ if(dt > OB_WIRE) {
+ glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel);
+ glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col);
+ }
+
+ glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1);
+ }
+ }
+
+ if(dt > OB_WIRE)
+ glDisable(GL_LIGHTING);
+
+ if(pset->brushtype == PE_BRUSH_WEIGHT) {
+ glLineWidth(2.0f);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glDisable(GL_LIGHTING);
+ }
+
+ /* draw parents last without lighting */
+ for(i=0, pa=psys->particles, path = psys->pathcache; i<totpart; i++, pa++, path++){
+ glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co);
+ if(dt > OB_WIRE)
+ glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel);
+ if(dt > OB_WIRE || pset->brushtype == PE_BRUSH_WEIGHT)
+ glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col);
+
+ glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1);
+ }
+
+ /* draw edit vertices */
+ if(scene->selectmode!=SCE_SELECT_PATH){
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glDisable(GL_LIGHTING);
+ glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+
+ if(scene->selectmode==SCE_SELECT_POINT){
+ float *cd=0,*cdata=0;
+ cd=cdata=MEM_callocN(edit->totkeys*(timed?4:3)*sizeof(float), "particle edit color data");
+
+ for(i=0, pa=psys->particles; i<totpart; i++, pa++){
+ for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++){
+ if(key->flag&PEK_SELECT){
+ VECCOPY(cd,sel_col);
+ }
+ else{
+ VECCOPY(cd,nosel_col);
+ }
+ if(timed)
+ *(cd+3) = (key->flag&PEK_HIDE)?0.0f:1.0f;
+ cd += (timed?4:3);
+ }
+ }
+ cd=cdata;
+ for(i=0, pa=psys->particles; i<totpart; i++, pa++){
+ if((pa->flag & PARS_HIDE)==0){
+ glVertexPointer(3, GL_FLOAT, sizeof(ParticleEditKey), edit->keys[i]->world_co);
+ glColorPointer((timed?4:3), GL_FLOAT, (timed?4:3)*sizeof(float), cd);
+ glDrawArrays(GL_POINTS, 0, pa->totkey);
+ }
+ cd += (timed?4:3) * pa->totkey;
+
+ if((pset->flag&PE_SHOW_TIME) && (pa->flag&PARS_HIDE)==0 && !(G.f & G_RENDER_SHADOW)){
+ for(k=0, key=edit->keys[i]+k; k<pa->totkey; k++, key++){
+ if(key->flag & PEK_HIDE) continue;
+
+ glRasterPos3fv(key->world_co);
+ sprintf(val," %.1f",*key->time);
+ BMF_DrawString(G.font, val);
+ }
+ }
+ }
+ if(cdata)
+ MEM_freeN(cdata);
+ cd=cdata=0;
+ }
+ else if(scene->selectmode == SCE_SELECT_END){
+ for(i=0, pa=psys->particles; i<totpart; i++, pa++){
+ if((pa->flag & PARS_HIDE)==0){
+ key = edit->keys[i] + pa->totkey - 1;
+ if(key->flag & PEK_SELECT)
+ glColor3fv(sel_col);
+ else
+ glColor3fv(nosel_col);
+ /* has to be like this.. otherwise selection won't work, have try glArrayElement later..*/
+ glBegin(GL_POINTS);
+ glVertex3fv(key->world_co);
+ glEnd();
+
+ if((pset->flag & PE_SHOW_TIME) && !(G.f & G_RENDER_SHADOW)){
+ glRasterPos3fv(key->world_co);
+ sprintf(val," %.1f",*key->time);
+ BMF_DrawString(G.font, val);
+ }
+ }
+ }
+ }
+ }
+
+ glDisable(GL_BLEND);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnable(GL_DEPTH_TEST);
+ glLineWidth(1.0f);
+
+ wmMultMatrix(ob->obmat); // bring back local matrix for dtx
+ glPointSize(1.0);
+}
+
+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 || (G.f & G_HIDDENHANDLES)) return;
+
+ glBegin(GL_LINES);
+
+ if( (nu->type & 7)==CU_BEZIER) {
+ if(sel) col= nurbcol+4;
+ else col= nurbcol;
+
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->hide==0) {
+ if( (bezt->f2 & SELECT)==sel) {
+ fp= bezt->vec[0];
+
+ cpack(col[(int)bezt->h1]);
+ glVertex3fv(fp);
+ glVertex3fv(fp+3);
+
+ cpack(col[(int)bezt->h2]);
+ glVertex3fv(fp+3);
+ glVertex3fv(fp+6);
+ }
+ else if( (bezt->f1 & SELECT)==sel) {
+ fp= bezt->vec[0];
+
+ cpack(col[(int)bezt->h1]);
+ glVertex3fv(fp);
+ glVertex3fv(fp+3);
+ }
+ else if( (bezt->f3 & SELECT)==sel) {
+ fp= bezt->vec[1];
+
+ cpack(col[(int)bezt->h2]);
+ glVertex3fv(fp);
+ glVertex3fv(fp+3);
+ }
+ }
+ bezt++;
+ }
+ }
+ glEnd();
+}
+
+static void tekenvertsN(Nurb *nu, short sel)
+{
+ BezTriple *bezt;
+ BPoint *bp;
+ float size;
+ int a;
+
+ if(nu->hide) return;
+
+ if(sel) UI_ThemeColor(TH_VERTEX_SELECT);
+ else UI_ThemeColor(TH_VERTEX);
+
+ size= UI_GetThemeValuef(TH_VERTEX_SIZE);
+ glPointSize(size);
+
+ bglBegin(GL_POINTS);
+
+ if((nu->type & 7)==CU_BEZIER) {
+
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->hide==0) {
+ if (G.f & G_HIDDENHANDLES) {
+ if((bezt->f2 & SELECT)==sel) bglVertex3fv(bezt->vec[1]);
+ } else {
+ if((bezt->f1 & SELECT)==sel) bglVertex3fv(bezt->vec[0]);
+ if((bezt->f2 & SELECT)==sel) bglVertex3fv(bezt->vec[1]);
+ if((bezt->f3 & SELECT)==sel) bglVertex3fv(bezt->vec[2]);
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp->hide==0) {
+ if((bp->f1 & SELECT)==sel) bglVertex3fv(bp->vec);
+ }
+ bp++;
+ }
+ }
+
+ bglEnd();
+ 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);
+ }
+
+ 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 & SELECT) && ( bp1->f1 & SELECT ) ) {
+ cpack(nurbcol[5]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(bp->vec);
+ glVertex3fv(bp1->vec);
+ glEnd();
+ }
+ }
+ else {
+ if( (bp->f1 & SELECT) && ( bp1->f1 & SELECT) );
+ 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 & SELECT) && ( bp1->f1 & SELECT) ) {
+ cpack(nurbcol[7]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(bp->vec);
+ glVertex3fv(bp1->vec);
+ glEnd();
+ }
+ }
+ else {
+ if( (bp->f1 & SELECT) && ( bp1->f1 & SELECT) );
+ else {
+ cpack(nurbcol[3]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(bp->vec);
+ glVertex3fv(bp1->vec);
+ glEnd();
+ }
+ }
+ }
+ bp1= bp;
+ }
+ }
+
+ }
+ break;
+ }
+ }
+ nu= nu->next;
+ }
+}
+
+static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, int dt)
+{
+ Object *ob= base->object;
+ Curve *cu = ob->data;
+ Nurb *nu;
+ BevList *bl;
+
+// XXX retopo_matrix_update(v3d);
+
+ /* DispList */
+ UI_ThemeColor(TH_WIRE);
+ drawDispList(scene, v3d, rv3d, base, dt);
+
+ if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
+
+ /* first non-selected handles */
+ for(nu=nurb; nu; nu=nu->next) {
+ if((nu->type & 7)==CU_BEZIER) {
+ tekenhandlesN(nu, 0);
+ }
+ }
+ draw_editnurb(ob, nurb, 0);
+ draw_editnurb(ob, nurb, 1);
+ /* selected handles */
+ for(nu=nurb; nu; nu=nu->next) {
+ if((nu->type & 7)==1) tekenhandlesN(nu, 1);
+ tekenvertsN(nu, 0);
+ }
+
+ if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
+
+ /* direction vectors for 3d curve paths
+ when at its lowest, dont render normals */
+ if(cu->flag & CU_3D && scene->editbutsize > 0.0015) {
+ UI_ThemeColor(TH_WIRE);
+ for (bl=cu->bev.first,nu=nurb; nu && bl; bl=bl->next,nu=nu->next) {
+ BevPoint *bevp= (BevPoint *)(bl+1);
+ int nr= bl->nr;
+ int skip= nu->resolu/16;
+
+ while (nr-->0) { /* accounts for empty bevel lists */
+ float fac= bevp->radius * scene->editbutsize;
+ float ox,oy,oz; // Offset perpendicular to the curve
+ float dx,dy,dz; // Delta along the curve
+
+ ox = fac*bevp->mat[0][0];
+ oy = fac*bevp->mat[0][1];
+ oz = fac*bevp->mat[0][2];
+
+ dx = fac*bevp->mat[2][0];
+ dy = fac*bevp->mat[2][1];
+ dz = fac*bevp->mat[2][2];
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3f(bevp->x - ox - dx, bevp->y - oy - dy, bevp->z - oz - dz);
+ glVertex3f(bevp->x, bevp->y, bevp->z);
+ glVertex3f(bevp->x + ox - dx, bevp->y + oy - dy, bevp->z + oz - dz);
+ glEnd();
+
+ bevp += skip+1;
+ nr -= skip;
+ }
+ }
+ }
+
+ if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
+
+ for(nu=nurb; nu; nu=nu->next) {
+ tekenvertsN(nu, 1);
+ }
+
+ if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
+}
+
+/* draw a sphere for use as an empty drawtype */
+static void draw_empty_sphere (float size)
+{
+ static GLuint displist=0;
+
+ if (displist == 0) {
+ GLUquadricObj *qobj;
+
+ displist= glGenLists(1);
+ glNewList(displist, GL_COMPILE_AND_EXECUTE);
+
+ glPushMatrix();
+
+ qobj = gluNewQuadric();
+ gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
+ gluDisk(qobj, 0.0, 1, 16, 1);
+
+ glRotatef(90, 0, 1, 0);
+ gluDisk(qobj, 0.0, 1, 16, 1);
+
+ glRotatef(90, 1, 0, 0);
+ gluDisk(qobj, 0.0, 1, 16, 1);
+
+ gluDeleteQuadric(qobj);
+
+ glPopMatrix();
+ glEndList();
+ }
+
+ glScalef(size, size, size);
+ glCallList(displist);
+ glScalef(1/size, 1/size, 1/size);
+}
+
+/* draw a cone for use as an empty drawtype */
+static void draw_empty_cone (float size)
+{
+ float cent=0;
+ float radius;
+ GLUquadricObj *qobj = gluNewQuadric();
+ gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
+
+
+ glPushMatrix();
+
+ radius = size;
+ glTranslatef(cent,cent, cent);
+ glScalef(radius, 2.0*size, radius);
+ glRotatef(-90., 1.0, 0.0, 0.0);
+ gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
+
+ glPopMatrix();
+
+ gluDeleteQuadric(qobj);
+}
+
+/* draw points on curve speed handles */
+static void curve_draw_speed(Scene *scene, Object *ob)
+{
+#if 0 // XXX old animation system stuff
+ Curve *cu= ob->data;
+ IpoCurve *icu;
+ BezTriple *bezt;
+ float loc[4], dir[3];
+ int a;
+
+ if(cu->ipo==NULL)
+ return;
+
+ icu= cu->ipo->curve.first;
+ if(icu==NULL || icu->totvert<2)
+ return;
+
+ glPointSize( UI_GetThemeValuef(TH_VERTEX_SIZE) );
+ bglBegin(GL_POINTS);
+
+ for(a=0, bezt= icu->bezt; a<icu->totvert; a++, bezt++) {
+ if( where_on_path(ob, bezt->vec[1][1], loc, dir)) {
+ UI_ThemeColor((bezt->f2 & SELECT) && ob==OBACT?TH_VERTEX_SELECT:TH_VERTEX);
+ bglVertex3fv(loc);
+ }
+ }
+
+ glPointSize(1.0);
+ bglEnd();
+#endif // XXX old animation system stuff
+}
+
+
+static void draw_textcurs(float textcurs[][2])
+{
+ cpack(0);
+
+ set_inverted_drawing(1);
+ glBegin(GL_QUADS);
+ glVertex2fv(textcurs[0]);
+ glVertex2fv(textcurs[1]);
+ glVertex2fv(textcurs[2]);
+ glVertex2fv(textcurs[3]);
+ glEnd();
+ set_inverted_drawing(0);
+}
+
+static void drawspiral(float *cent, float rad, float tmat[][4], int start)
+{
+ float vec[3], vx[3], vy[3];
+ int a, tot=32;
+ char inverse=0;
+
+ if (start < 0) {
+ inverse = 1;
+ start *= -1;
+ }
+
+ VECCOPY(vx, tmat[0]);
+ VECCOPY(vy, tmat[1]);
+ VecMulf(vx, rad);
+ VecMulf(vy, rad);
+
+ VECCOPY(vec, cent);
+
+ if (inverse==0) {
+ for(a=0; a<tot; a++) {
+ if (a+start>31)
+ start=-a + 1;
+ glBegin(GL_LINES);
+ glVertex3fv(vec);
+ vec[0]= cent[0] + *(sinval+a+start) * (vx[0] * (float)a/(float)tot) + *(cosval+a+start) * (vy[0] * (float)a/(float)tot);
+ vec[1]= cent[1] + *(sinval+a+start) * (vx[1] * (float)a/(float)tot) + *(cosval+a+start) * (vy[1] * (float)a/(float)tot);
+ vec[2]= cent[2] + *(sinval+a+start) * (vx[2] * (float)a/(float)tot) + *(cosval+a+start) * (vy[2] * (float)a/(float)tot);
+ glVertex3fv(vec);
+ glEnd();
+ }
+ }
+ else {
+ a=0;
+ vec[0]= cent[0] + *(sinval+a+start) * (vx[0] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[0] * (float)(-a+31)/(float)tot);
+ vec[1]= cent[1] + *(sinval+a+start) * (vx[1] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[1] * (float)(-a+31)/(float)tot);
+ vec[2]= cent[2] + *(sinval+a+start) * (vx[2] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[2] * (float)(-a+31)/(float)tot);
+ for(a=0; a<tot; a++) {
+ if (a+start>31)
+ start=-a + 1;
+ glBegin(GL_LINES);
+ glVertex3fv(vec);
+ vec[0]= cent[0] + *(sinval+a+start) * (vx[0] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[0] * (float)(-a+31)/(float)tot);
+ vec[1]= cent[1] + *(sinval+a+start) * (vx[1] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[1] * (float)(-a+31)/(float)tot);
+ vec[2]= cent[2] + *(sinval+a+start) * (vx[2] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[2] * (float)(-a+31)/(float)tot);
+ glVertex3fv(vec);
+ glEnd();
+ }
+ }
+}
+
+/* draws a circle on x-z plane given the scaling of the circle, assuming that
+ * all required matrices have been set (used for drawing empties)
+ */
+static void drawcircle_size(float size)
+{
+ float x, y;
+ short degrees;
+
+ glBegin(GL_LINE_LOOP);
+
+ /* coordinates are: cos(degrees*11.25)=x, sin(degrees*11.25)=y, 0.0f=z */
+ for (degrees=0; degrees<32; degrees++) {
+ x= *(cosval + degrees);
+ y= *(sinval + degrees);
+
+ glVertex3f(x*size, 0.0f, y*size);
+ }
+
+ glEnd();
+
+}
+
+/* needs fixing if non-identity matrice used */
+static void drawtube(float *vec, float radius, float height, float tmat[][4])
+{
+ float cur[3];
+ drawcircball(GL_LINE_LOOP, vec, radius, tmat);
+
+ VecCopyf(cur,vec);
+ cur[2]+=height;
+
+ drawcircball(GL_LINE_LOOP, cur, radius, tmat);
+
+ glBegin(GL_LINES);
+ glVertex3f(vec[0]+radius,vec[1],vec[2]);
+ glVertex3f(cur[0]+radius,cur[1],cur[2]);
+ glVertex3f(vec[0]-radius,vec[1],vec[2]);
+ glVertex3f(cur[0]-radius,cur[1],cur[2]);
+ glVertex3f(vec[0],vec[1]+radius,vec[2]);
+ glVertex3f(cur[0],cur[1]+radius,cur[2]);
+ glVertex3f(vec[0],vec[1]-radius,vec[2]);
+ glVertex3f(cur[0],cur[1]-radius,cur[2]);
+ glEnd();
+}
+/* needs fixing if non-identity matrice used */
+static void drawcone(float *vec, float radius, float height, float tmat[][4])
+{
+ float cur[3];
+
+ VecCopyf(cur,vec);
+ cur[2]+=height;
+
+ drawcircball(GL_LINE_LOOP, cur, radius, tmat);
+
+ glBegin(GL_LINES);
+ glVertex3f(vec[0],vec[1],vec[2]);
+ glVertex3f(cur[0]+radius,cur[1],cur[2]);
+ glVertex3f(vec[0],vec[1],vec[2]);
+ glVertex3f(cur[0]-radius,cur[1],cur[2]);
+ glVertex3f(vec[0],vec[1],vec[2]);
+ glVertex3f(cur[0],cur[1]+radius,cur[2]);
+ glVertex3f(vec[0],vec[1],vec[2]);
+ glVertex3f(cur[0],cur[1]-radius,cur[2]);
+ glEnd();
+}
+/* return 1 if nothing was drawn */
+static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt)
+{
+ Object *ob= base->object;
+ MetaBall *mb;
+ MetaElem *ml;
+ float imat[4][4], tmat[4][4];
+ int code= 1;
+
+ mb= ob->data;
+
+ if(mb->editelems) {
+ UI_ThemeColor(TH_WIRE);
+ if((G.f & G_PICKSEL)==0 ) drawDispList(scene, v3d, rv3d, base, dt);
+ ml= mb->editelems->first;
+ }
+ else {
+ if((base->flag & OB_FROMDUPLI)==0)
+ drawDispList(scene, v3d, rv3d, base, dt);
+ ml= mb->elems.first;
+ }
+
+ if(ml==NULL) return 1;
+
+ /* in case solid draw, reset wire colors */
+ if(mb->editelems && (ob->flag & SELECT)) {
+ if(ob==OBACT) UI_ThemeColor(TH_ACTIVE);
+ else UI_ThemeColor(TH_SELECT);
+ }
+ else UI_ThemeColor(TH_WIRE);
+
+ wmGetMatrix(tmat);
+ Mat4Invert(imat, tmat);
+ Normalize(imat[0]);
+ Normalize(imat[1]);
+
+ while(ml) {
+
+ /* draw radius */
+ if(mb->editelems) {
+ if((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) cpack(0xA0A0F0);
+ else cpack(0x3030A0);
+
+ if(G.f & G_PICKSEL) {
+ ml->selcol1= code;
+ glLoadName(code++);
+ }
+ }
+ drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad, imat);
+
+ /* draw stiffness */
+ if(mb->editelems) {
+ if((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) cpack(0xA0F0A0);
+ else cpack(0x30A030);
+
+ if(G.f & G_PICKSEL) {
+ ml->selcol2= code;
+ glLoadName(code++);
+ }
+ drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad*atan(ml->s)/M_PI_2, imat);
+ }
+
+ ml= ml->next;
+ }
+ return 0;
+}
+
+static void draw_forcefield(Scene *scene, Object *ob)
+{
+ PartDeflect *pd= ob->pd;
+ float imat[4][4], tmat[4][4];
+ float vec[3]= {0.0, 0.0, 0.0};
+ int curcol;
+ float size;
+
+ if(G.f & G_RENDER_SHADOW)
+ return;
+
+ /* XXX why? */
+ if(ob!=scene->obedit && (ob->flag & SELECT)) {
+ if(ob==OBACT) curcol= TH_ACTIVE;
+ else curcol= TH_SELECT;
+ }
+ else curcol= TH_WIRE;
+
+ /* scale size of circle etc with the empty drawsize */
+ if (ob->type == OB_EMPTY) size = ob->empty_drawsize;
+ else size = 1.0;
+
+ /* calculus here, is reused in PFIELD_FORCE */
+ wmGetMatrix(tmat);
+ Mat4Invert(imat, tmat);
+// Normalize(imat[0]); // we don't do this because field doesnt scale either... apart from wind!
+// Normalize(imat[1]);
+
+ if (pd->forcefield == PFIELD_WIND) {
+ float force_val;
+
+ Mat4One(tmat);
+ UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
+
+ //if (has_ipo_code(ob->ipo, OB_PD_FSTR))
+ // force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra);
+ //else
+ force_val = pd->f_strength;
+ force_val*= 0.1;
+ drawcircball(GL_LINE_LOOP, vec, size, tmat);
+ vec[2]= 0.5*force_val;
+ drawcircball(GL_LINE_LOOP, vec, size, tmat);
+ vec[2]= 1.0*force_val;
+ drawcircball(GL_LINE_LOOP, vec, size, tmat);
+ vec[2]= 1.5*force_val;
+ drawcircball(GL_LINE_LOOP, vec, size, tmat);
+ vec[2] = 0; /* reset vec for max dist circle */
+
+ }
+ else if (pd->forcefield == PFIELD_FORCE) {
+ float ffall_val;
+
+ //if (has_ipo_code(ob->ipo, OB_PD_FFALL))
+ // ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, scene->r.cfra);
+ //else
+ ffall_val = pd->f_power;
+
+ UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
+ drawcircball(GL_LINE_LOOP, vec, size, imat);
+ UI_ThemeColorBlend(curcol, TH_BACK, 0.9 - 0.4 / pow(1.5, (double)ffall_val));
+ drawcircball(GL_LINE_LOOP, vec, size*1.5, imat);
+ UI_ThemeColorBlend(curcol, TH_BACK, 0.9 - 0.4 / pow(2.0, (double)ffall_val));
+ drawcircball(GL_LINE_LOOP, vec, size*2.0, imat);
+ }
+ else if (pd->forcefield == PFIELD_VORTEX) {
+ float ffall_val, force_val;
+
+ Mat4One(tmat);
+ //if (has_ipo_code(ob->ipo, OB_PD_FFALL))
+ // ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, scene->r.cfra);
+ //else
+ ffall_val = pd->f_power;
+
+ //if (has_ipo_code(ob->ipo, OB_PD_FSTR))
+ // force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra);
+ //else
+ force_val = pd->f_strength;
+
+ UI_ThemeColorBlend(curcol, TH_BACK, 0.7);
+ if (force_val < 0) {
+ drawspiral(vec, size*1.0, tmat, 1);
+ drawspiral(vec, size*1.0, tmat, 16);
+ }
+ else {
+ drawspiral(vec, size*1.0, tmat, -1);
+ drawspiral(vec, size*1.0, tmat, -16);
+ }
+ }
+ else if (pd->forcefield == PFIELD_GUIDE && ob->type==OB_CURVE) {
+ Curve *cu= ob->data;
+ if((cu->flag & CU_PATH) && cu->path && cu->path->data) {
+ float mindist, guidevec1[4], guidevec2[3];
+
+ //if (has_ipo_code(ob->ipo, OB_PD_FSTR))
+ // mindist = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra);
+ //else
+ mindist = pd->f_strength;
+
+ /*path end*/
+ setlinestyle(3);
+ where_on_path(ob, 1.0f, guidevec1, guidevec2);
+ UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
+ drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
+
+ /*path beginning*/
+ setlinestyle(0);
+ where_on_path(ob, 0.0f, guidevec1, guidevec2);
+ UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
+ drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
+
+ VECCOPY(vec, guidevec1); /* max center */
+ }
+ }
+
+ setlinestyle(3);
+ UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
+
+ if(pd->falloff==PFIELD_FALL_SPHERE){
+ /* as last, guide curve alters it */
+ if(pd->flag & PFIELD_USEMAX)
+ drawcircball(GL_LINE_LOOP, vec, pd->maxdist, imat);
+
+ if(pd->flag & PFIELD_USEMIN)
+ drawcircball(GL_LINE_LOOP, vec, pd->mindist, imat);
+ }
+ else if(pd->falloff==PFIELD_FALL_TUBE){
+ float radius,distance;
+
+ Mat4One(tmat);
+
+ vec[0]=vec[1]=0.0f;
+ radius=(pd->flag&PFIELD_USEMAXR)?pd->maxrad:1.0f;
+ distance=(pd->flag&PFIELD_USEMAX)?pd->maxdist:0.0f;
+ vec[2]=distance;
+ distance=(pd->flag&PFIELD_POSZ)?-distance:-2.0f*distance;
+
+ if(pd->flag & (PFIELD_USEMAX|PFIELD_USEMAXR))
+ drawtube(vec,radius,distance,tmat);
+
+ radius=(pd->flag&PFIELD_USEMINR)?pd->minrad:1.0f;
+ distance=(pd->flag&PFIELD_USEMIN)?pd->mindist:0.0f;
+ vec[2]=distance;
+ distance=(pd->flag&PFIELD_POSZ)?-distance:-2.0f*distance;
+
+ if(pd->flag & (PFIELD_USEMIN|PFIELD_USEMINR))
+ drawtube(vec,radius,distance,tmat);
+ }
+ else if(pd->falloff==PFIELD_FALL_CONE){
+ float radius,distance;
+
+ Mat4One(tmat);
+
+ radius=(pd->flag&PFIELD_USEMAXR)?pd->maxrad:1.0f;
+ radius*=(float)M_PI/180.0f;
+ distance=(pd->flag&PFIELD_USEMAX)?pd->maxdist:0.0f;
+
+ if(pd->flag & (PFIELD_USEMAX|PFIELD_USEMAXR)){
+ drawcone(vec,distance*sin(radius),distance*cos(radius),tmat);
+ if((pd->flag & PFIELD_POSZ)==0)
+ drawcone(vec,distance*sin(radius),-distance*cos(radius),tmat);
+ }
+
+ radius=(pd->flag&PFIELD_USEMINR)?pd->minrad:1.0f;
+ radius*=(float)M_PI/180.0f;
+ distance=(pd->flag&PFIELD_USEMIN)?pd->mindist:0.0f;
+
+ if(pd->flag & (PFIELD_USEMIN|PFIELD_USEMINR)){
+ drawcone(vec,distance*sin(radius),distance*cos(radius),tmat);
+ if((pd->flag & PFIELD_POSZ)==0)
+ drawcone(vec,distance*sin(radius),-distance*cos(radius),tmat);
+ }
+ }
+ setlinestyle(0);
+}
+
+static void draw_box(float vec[8][3])
+{
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec[0]); glVertex3fv(vec[1]);glVertex3fv(vec[2]); glVertex3fv(vec[3]);
+ glVertex3fv(vec[0]); glVertex3fv(vec[4]);glVertex3fv(vec[5]); glVertex3fv(vec[6]);
+ glVertex3fv(vec[7]); glVertex3fv(vec[4]);
+ glEnd();
+
+ glBegin(GL_LINES);
+ glVertex3fv(vec[1]); glVertex3fv(vec[5]);
+ glVertex3fv(vec[2]); glVertex3fv(vec[6]);
+ glVertex3fv(vec[3]); glVertex3fv(vec[7]);
+ glEnd();
+}
+
+/* uses boundbox, function used by Ketsji */
+void get_local_bounds(Object *ob, float *center, float *size)
+{
+ BoundBox *bb= object_get_boundbox(ob);
+
+ if(bb==NULL) {
+ center[0]= center[1]= center[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]);
+
+ center[0]= (bb->vec[0][0] + bb->vec[4][0])/2.0;
+ center[1]= (bb->vec[0][1] + bb->vec[2][1])/2.0;
+ center[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;
+
+ glPushMatrix();
+ 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) {
+ float radius = size[0] > size[1] ? size[0] : size[1];
+ glTranslatef(cent[0], cent[1], cent[2]-size[2]);
+ glScalef(radius, radius, 2.0*size[2]);
+ gluCylinder(qobj, 1.0, 1.0, 1.0, 8, 1);
+ }
+ else if(type==OB_BOUND_CONE) {
+ float radius = size[0] > size[1] ? size[0] : size[1];
+ glTranslatef(cent[0], cent[2]-size[2], cent[1]);
+ glScalef(radius, 2.0*size[2], radius);
+ glRotatef(-90., 1.0, 0.0, 0.0);
+ gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
+ }
+ glPopMatrix();
+
+ gluDeleteQuadric(qobj);
+}
+
+static void draw_bounding_volume(Scene *scene, Object *ob)
+{
+ BoundBox *bb=0;
+
+ if(ob->type==OB_MESH) {
+ bb= mesh_get_bb(ob);
+ }
+ 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==0) {
+ makeDispListMBall(scene, ob);
+ bb= ob->bb;
+ }
+ }
+ else {
+ drawcube();
+ return;
+ }
+
+ if(bb==0) return;
+
+ if(ob->boundtype==OB_BOUND_BOX) draw_box(bb->vec);
+ else draw_bb_quadric(bb, ob->boundtype);
+
+}
+
+static void drawtexspace(Object *ob)
+{
+ float vec[8][3], loc[3], size[3];
+
+ if(ob->type==OB_MESH) {
+ mesh_get_texspace(ob->data, loc, NULL, size);
+ }
+ else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
+ Curve *cu= ob->data;
+ VECCOPY(size, cu->size);
+ VECCOPY(loc, cu->loc);
+ }
+ else if(ob->type==OB_MBALL) {
+ MetaBall *mb= ob->data;
+ VECCOPY(size, mb->size);
+ VECCOPY(loc, mb->loc);
+ }
+ else return;
+
+ vec[0][0]=vec[1][0]=vec[2][0]=vec[3][0]= loc[0]-size[0];
+ vec[4][0]=vec[5][0]=vec[6][0]=vec[7][0]= loc[0]+size[0];
+
+ vec[0][1]=vec[1][1]=vec[4][1]=vec[5][1]= loc[1]-size[1];
+ vec[2][1]=vec[3][1]=vec[6][1]=vec[7][1]= loc[1]+size[1];
+
+ vec[0][2]=vec[3][2]=vec[4][2]=vec[7][2]= loc[2]-size[2];
+ vec[1][2]=vec[2][2]=vec[5][2]=vec[6][2]= loc[2]+size[2];
+
+ setlinestyle(2);
+
+ draw_box(vec);
+
+ setlinestyle(0);
+}
+
+/* draws wire outline */
+static void drawSolidSelect(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base)
+{
+ Object *ob= base->object;
+
+ glLineWidth(2.0);
+ glDepthMask(0);
+
+ if(ELEM3(ob->type, OB_FONT,OB_CURVE, OB_SURF)) {
+ Curve *cu = ob->data;
+ if (displist_has_faces(&cu->disp) && boundbox_clip(rv3d, ob->obmat, cu->bb)) {
+ draw_index_wire= 0;
+ drawDispListwire(&cu->disp);
+ draw_index_wire= 1;
+ }
+ } else if (ob->type==OB_MBALL) {
+ if((base->flag & OB_FROMDUPLI)==0)
+ drawDispListwire(&ob->disp);
+ }
+ else if(ob->type==OB_ARMATURE) {
+ if(!(ob->flag & OB_POSEMODE))
+ draw_armature(scene, v3d, rv3d, base, OB_WIRE, 0);
+ }
+
+ glLineWidth(1.0);
+ glDepthMask(1);
+}
+
+static void drawWireExtra(Scene *scene, RegionView3D *rv3d, Object *ob)
+{
+ if(ob!=scene->obedit && (ob->flag & SELECT)) {
+ if(ob==OBACT) {
+ if(ob->flag & OB_FROMGROUP) UI_ThemeColor(TH_GROUP_ACTIVE);
+ else UI_ThemeColor(TH_ACTIVE);
+ }
+ else if(ob->flag & OB_FROMGROUP)
+ UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
+ else
+ UI_ThemeColor(TH_SELECT);
+ }
+ else {
+ if(ob->flag & OB_FROMGROUP)
+ UI_ThemeColor(TH_GROUP);
+ else {
+ if(ob->dtx & OB_DRAWWIRE) {
+ glColor3ub(80,80,80);
+ } else {
+ UI_ThemeColor(TH_WIRE);
+ }
+ }
+ }
+
+ bglPolygonOffset(rv3d->dist, 1.0);
+ glDepthMask(0); // disable write in zbuffer, selected edge wires show better
+
+ if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
+ Curve *cu = ob->data;
+ if (boundbox_clip(rv3d, ob->obmat, cu->bb)) {
+ if (ob->type==OB_CURVE)
+ draw_index_wire= 0;
+ drawDispListwire(&cu->disp);
+ if (ob->type==OB_CURVE)
+ draw_index_wire= 1;
+ }
+ } else if (ob->type==OB_MBALL) {
+ drawDispListwire(&ob->disp);
+ }
+
+ glDepthMask(1);
+ bglPolygonOffset(rv3d->dist, 0.0);
+}
+
+/* should be called in view space */
+static void draw_hooks(Object *ob)
+{
+ ModifierData *md;
+ float vec[3];
+
+ for (md=ob->modifiers.first; md; md=md->next) {
+ if (md->type==eModifierType_Hook) {
+ HookModifierData *hmd = (HookModifierData*) md;
+
+ VecMat4MulVecfl(vec, ob->obmat, hmd->cent);
+
+ if(hmd->object) {
+ setlinestyle(3);
+ glBegin(GL_LINES);
+ glVertex3fv(hmd->object->obmat[3]);
+ glVertex3fv(vec);
+ glEnd();
+ setlinestyle(0);
+ }
+
+ glPointSize(3.0);
+ bglBegin(GL_POINTS);
+ bglVertex3fv(vec);
+ bglEnd();
+ glPointSize(1.0);
+ }
+ }
+}
+
+//<rcruiz>
+void drawRBpivot(bRigidBodyJointConstraint *data)
+{
+ float radsPerDeg = 6.283185307179586232f / 360.f;
+ int axis;
+ float v1[3]= {data->pivX, data->pivY, data->pivZ};
+ float eu[3]= {radsPerDeg*data->axX, radsPerDeg*data->axY, radsPerDeg*data->axZ};
+ float mat[4][4];
+
+ if(G.f & G_RENDER_SHADOW)
+ return;
+
+ EulToMat4(eu,mat);
+ glLineWidth (4.0f);
+ setlinestyle(2);
+ for (axis=0; axis<3; axis++) {
+ float dir[3] = {0,0,0};
+ float v[3]= {data->pivX, data->pivY, data->pivZ};
+
+ dir[axis] = 1.f;
+ glBegin(GL_LINES);
+ Mat4MulVecfl(mat,dir);
+ v[0] += dir[0];
+ v[1] += dir[1];
+ v[2] += dir[2];
+ glVertex3fv(v1);
+ glVertex3fv(v);
+ glEnd();
+ glRasterPos3fv(v);
+ if (axis==0)
+ BMF_DrawString(G.font, "px");
+ else if (axis==1)
+ BMF_DrawString(G.font, "py");
+ else
+ BMF_DrawString(G.font, "pz");
+ }
+ glLineWidth (1.0f);
+ setlinestyle(0);
+}
+
+/* flag can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET */
+void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
+{
+ static int warning_recursive= 0;
+ Object *ob;
+ Curve *cu;
+ RegionView3D *rv3d= ar->regiondata;
+ //float cfraont;
+ float vec1[3], vec2[3];
+ unsigned int col=0;
+ int /*sel, drawtype,*/ colindex= 0;
+ int i, selstart, selend, empty_object=0;
+ short dt, dtx, zbufoff= 0;
+
+ /* only once set now, will be removed too, should become a global standard */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ ob= base->object;
+
+ if (ob!=scene->obedit) {
+ if (ob->restrictflag & OB_RESTRICT_VIEW)
+ return;
+ }
+
+ /* xray delay? */
+ if((flag & DRAW_PICKING)==0 && (base->flag & OB_FROMDUPLI)==0) {
+ /* don't do xray in particle mode, need the z-buffer */
+ if(!(G.f & G_PARTICLEEDIT)) {
+ /* xray and transp are set when it is drawing the 2nd/3rd pass */
+ if(!v3d->xray && !v3d->transp && (ob->dtx & OB_DRAWXRAY)) {
+ add_view3d_after(v3d, base, V3D_XRAY, flag);
+ return;
+ }
+ }
+ }
+
+ /* draw keys? */
+#if 0 // XXX old animation system
+ if(base==(scene->basact) || (base->flag & (SELECT+BA_WAS_SEL))) {
+ if(flag==0 && warning_recursive==0 && ob!=scene->obedit) {
+ if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
+ ListBase elems;
+ CfraElem *ce;
+ float temp[7][3];
+
+ warning_recursive= 1;
+
+ elems.first= elems.last= 0;
+ // warning: no longer checks for certain ob-keys only... (so does this need to use the proper ipokeys then?)
+ make_cfra_list(ob->ipo, &elems);
+
+ cfraont= (scene->r.cfra);
+ drawtype= v3d->drawtype;
+ if(drawtype>OB_WIRE) v3d->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) {
+ (scene->r.cfra)= ce->cfra/scene->r.framelen;
+
+ base->flag= 0;
+
+ where_is_object_time(scene, ob, (scene->r.cfra));
+ draw_object(scene, ar, v3d, base, 0);
+ }
+ ce= ce->next;
+ }
+ }
+
+ ce= elems.first;
+ while(ce) {
+ if(ce->sel) {
+ (scene->r.cfra)= ce->cfra/scene->r.framelen;
+
+ base->flag= SELECT;
+
+ where_is_object_time(scene, ob, (scene->r.cfra));
+ draw_object(scene, ar, v3d, base, 0);
+ }
+ ce= ce->next;
+ }
+
+ set_no_parent_ipo(0);
+ disable_speed_curve(0);
+
+ base->flag= sel;
+ ob->ipoflag= ipoflag;
+
+ /* restore icu->curval */
+ (scene->r.cfra)= cfraont;
+
+ memcpy(&ob->loc, temp, 7*3*sizeof(float));
+ where_is_object(scene, ob);
+ v3d->drawtype= drawtype;
+
+ BLI_freelistN(&elems);
+
+ warning_recursive= 0;
+ }
+ }
+ }
+#endif // XXX old animation system
+
+ /* patch? children objects with a timeoffs change the parents. How to solve! */
+ /* if( ((int)ob->ctime) != F_(scene->r.cfra)) where_is_object(scene, ob); */
+
+ wmMultMatrix(ob->obmat);
+
+ /* which wire color */
+ if((flag & DRAW_CONSTCOLOR) == 0) {
+ project_short(ar, ob->obmat[3], &base->sx);
+
+ if((G.moving & G_TRANSFORM_OBJ) && (base->flag & (SELECT+BA_WAS_SEL))) UI_ThemeColor(TH_TRANSFORM);
+ else {
+
+ if(ob->type==OB_LAMP) UI_ThemeColor(TH_LAMP);
+ else UI_ThemeColor(TH_WIRE);
+
+ if((scene->basact)==base) {
+ if(base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_ACTIVE);
+ }
+ else {
+ if(base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_SELECT);
+ }
+
+ // no theme yet
+ if(ob->id.lib) {
+ if(base->flag & (SELECT+BA_WAS_SEL)) colindex = 4;
+ else colindex = 3;
+ }
+ else if(warning_recursive==1) {
+ if(base->flag & (SELECT+BA_WAS_SEL)) {
+ if(scene->basact==base) colindex = 8;
+ else colindex= 7;
+ }
+ else colindex = 6;
+ }
+ else if(ob->flag & OB_FROMGROUP) {
+ if(base->flag & (SELECT+BA_WAS_SEL)) {
+ if(scene->basact==base) UI_ThemeColor(TH_GROUP_ACTIVE);
+ else UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
+ }
+ else UI_ThemeColor(TH_GROUP);
+ colindex= 0;
+ }
+
+ }
+
+ if(colindex) {
+ col= colortab[colindex];
+ cpack(col);
+ }
+ }
+
+ /* maximum drawtype */
+ dt= MIN2(v3d->drawtype, ob->dt);
+ if(v3d->zbuf==0 && dt>OB_WIRE) dt= OB_WIRE;
+ dtx= 0;
+
+ /* faceselect exception: also draw solid when dt==wire, except in editmode */
+ if(ob==OBACT && (G.f & (G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT))) {
+ if(ob->type==OB_MESH) {
+
+ if(ob==scene->obedit);
+ else {
+ if(dt<OB_SOLID)
+ zbufoff= 1;
+
+ dt= OB_SHADED;
+ glEnable(GL_DEPTH_TEST);
+ }
+ }
+ else {
+ if(dt<OB_SOLID) {
+ dt= OB_SOLID;
+ glEnable(GL_DEPTH_TEST);
+ zbufoff= 1;
+ }
+ }
+ }
+
+ /* draw-extra supported for boundbox drawmode too */
+ if(dt>=OB_BOUNDBOX ) {
+
+ dtx= ob->dtx;
+ if(scene->obedit==ob) {
+ // the only 2 extra drawtypes alowed in editmode
+ dtx= dtx & (OB_DRAWWIRE|OB_TEXSPACE);
+ }
+
+ }
+
+ /* bad exception, solve this! otherwise outline shows too late */
+ if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ cu= ob->data;
+ /* still needed for curves hidden in other layers. depgraph doesnt handle that yet */
+ if (cu->disp.first==NULL) makeDispListCurveTypes(scene, ob, 0);
+ }
+
+ /* draw outline for selected solid objects, mesh does itself */
+ if((v3d->flag & V3D_SELECT_OUTLINE) && ob->type!=OB_MESH) {
+ if(dt>OB_WIRE && dt<OB_TEXTURE && ob!=scene->obedit && (flag && DRAW_SCENESET)==0) {
+ if (!(ob->dtx&OB_DRAWWIRE) && (ob->flag&SELECT) && !(flag&DRAW_PICKING)) {
+
+ drawSolidSelect(scene, v3d, rv3d, base);
+ }
+ }
+ }
+
+ switch( ob->type) {
+ case OB_MESH:
+ if (!(base->flag&OB_RADIO)) {
+ empty_object= draw_mesh_object(scene, v3d, rv3d, base, dt, flag);
+ if(flag!=DRAW_CONSTCOLOR) dtx &= ~OB_DRAWWIRE; // mesh draws wire itself
+ }
+
+ break;
+ case OB_FONT:
+ cu= ob->data;
+ if(cu->editfont) {
+ draw_textcurs(cu->editfont->textcurs);
+
+ if (cu->flag & CU_FAST) {
+ cpack(0xFFFFFF);
+ set_inverted_drawing(1);
+ drawDispList(scene, v3d, rv3d, base, OB_WIRE);
+ set_inverted_drawing(0);
+ } else {
+ drawDispList(scene, v3d, rv3d, base, dt);
+ }
+
+ if (cu->linewidth != 0.0) {
+ cpack(0xff44ff);
+ UI_ThemeColor(TH_WIRE);
+ VECCOPY(vec1, ob->orig);
+ VECCOPY(vec2, ob->orig);
+ vec1[0] += cu->linewidth;
+ vec2[0] += cu->linewidth;
+ vec1[1] += cu->linedist * cu->fsize;
+ vec2[1] -= cu->lines * cu->linedist * cu->fsize;
+ setlinestyle(3);
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec1);
+ glVertex2fv(vec2);
+ glEnd();
+ setlinestyle(0);
+ }
+
+ setlinestyle(3);
+ for (i=0; i<cu->totbox; i++) {
+ if (cu->tb[i].w != 0.0) {
+ if (i == (cu->actbox-1))
+ UI_ThemeColor(TH_ACTIVE);
+ else
+ UI_ThemeColor(TH_WIRE);
+ vec1[0] = cu->tb[i].x;
+ vec1[1] = cu->tb[i].y + cu->fsize;
+ vec1[2] = 0.001;
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec1);
+ vec1[0] += cu->tb[i].w;
+ glVertex3fv(vec1);
+ vec1[1] -= cu->tb[i].h;
+ glVertex3fv(vec1);
+ vec1[0] -= cu->tb[i].w;
+ glVertex3fv(vec1);
+ vec1[1] += cu->tb[i].h;
+ glVertex3fv(vec1);
+ glEnd();
+ }
+ }
+ setlinestyle(0);
+
+
+ if (BKE_font_getselection(ob, &selstart, &selend) && cu->selboxes) {
+ float selboxw;
+
+ cpack(0xffffff);
+ set_inverted_drawing(1);
+ for (i=0; i<(selend-selstart+1); i++) {
+ SelBox *sb = &(cu->selboxes[i]);
+
+ if (i<(selend-selstart)) {
+ if (cu->selboxes[i+1].y == sb->y)
+ selboxw= cu->selboxes[i+1].x - sb->x;
+ else
+ selboxw= sb->w;
+ }
+ else {
+ selboxw= sb->w;
+ }
+ glBegin(GL_QUADS);
+ glVertex3f(sb->x, sb->y, 0.001);
+ glVertex3f(sb->x+selboxw, sb->y, 0.001);
+ glVertex3f(sb->x+selboxw, sb->y+sb->h, 0.001);
+ glVertex3f(sb->x, sb->y+sb->h, 0.001);
+ glEnd();
+ }
+ set_inverted_drawing(0);
+ }
+ }
+ else if(dt==OB_BOUNDBOX)
+ draw_bounding_volume(scene, ob);
+ else if(boundbox_clip(rv3d, ob->obmat, cu->bb))
+ empty_object= drawDispList(scene, v3d, rv3d, base, dt);
+
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ cu= ob->data;
+
+ if(cu->editnurb) {
+ drawnurb(scene, v3d, rv3d, base, cu->editnurb->first, dt);
+ }
+ else if(dt==OB_BOUNDBOX)
+ draw_bounding_volume(scene, ob);
+ else if(boundbox_clip(rv3d, ob->obmat, cu->bb)) {
+ empty_object= drawDispList(scene, v3d, rv3d, base, dt);
+
+ if(cu->path)
+ curve_draw_speed(scene, ob);
+ }
+ break;
+ case OB_MBALL:
+ {
+ MetaBall *mb= ob->data;
+
+ if(mb->editelems)
+ drawmball(scene, v3d, rv3d, base, dt);
+ else if(dt==OB_BOUNDBOX)
+ draw_bounding_volume(scene, ob);
+ else
+ empty_object= drawmball(scene, v3d, rv3d, base, dt);
+ break;
+ }
+ case OB_EMPTY:
+ drawaxes(ob->empty_drawsize, flag, ob->empty_drawtype);
+ break;
+ case OB_LAMP:
+ drawlamp(scene, v3d, rv3d, ob);
+ if(dtx || (base->flag & SELECT)) wmMultMatrix(ob->obmat);
+ break;
+ case OB_CAMERA:
+ drawcamera(scene, v3d, rv3d, ob, flag);
+ break;
+ case OB_LATTICE:
+ drawlattice(scene, v3d, ob);
+ break;
+ case OB_ARMATURE:
+ if(dt>OB_WIRE) GPU_enable_material(0, NULL); // we use default material
+ empty_object= draw_armature(scene, v3d, rv3d, base, dt, flag);
+ if(dt>OB_WIRE) GPU_disable_material();
+ break;
+ default:
+ drawaxes(1.0, flag, OB_ARROWS);
+ }
+ if(ob->pd && ob->pd->forcefield) draw_forcefield(scene, ob);
+
+ /* code for new particle system */
+ if( (warning_recursive==0) &&
+ (ob->particlesystem.first) &&
+ (flag & DRAW_PICKING)==0 &&
+ (ob!=scene->obedit)
+ ) {
+ ParticleSystem *psys;
+ if(col || (ob->flag & SELECT)) cpack(0xFFFFFF); /* for visibility, also while wpaint */
+ glDepthMask(GL_FALSE);
+
+ for(psys=ob->particlesystem.first; psys; psys=psys->next)
+ draw_new_particle_system(scene, v3d, rv3d, base, psys, dt);
+
+ if(G.f & G_PARTICLEEDIT && ob==OBACT) {
+ psys= PE_get_current(scene, ob);
+ if(psys && !scene->obedit && psys_in_edit_mode(scene, psys))
+ draw_particle_edit(scene, v3d, rv3d, ob, psys, dt);
+ }
+ glDepthMask(GL_TRUE);
+ if(col) cpack(col);
+ }
+
+ {
+ bConstraint *con;
+ for(con=ob->constraints.first; con; con= con->next)
+ {
+ if(con->type==CONSTRAINT_TYPE_RIGIDBODYJOINT)
+ {
+ bRigidBodyJointConstraint *data = (bRigidBodyJointConstraint*)con->data;
+ if(data->flag&CONSTRAINT_DRAW_PIVOT)
+ drawRBpivot(data);
+ }
+ }
+ }
+
+ /* draw extra: after normal draw because of makeDispList */
+ if(dtx && !(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))) {
+ if(dtx & OB_AXIS) {
+ drawaxes(1.0f, flag, OB_ARROWS);
+ }
+ if(dtx & OB_BOUNDBOX) draw_bounding_volume(scene, ob);
+ if(dtx & OB_TEXSPACE) drawtexspace(ob);
+ if(dtx & OB_DRAWNAME) {
+ /* patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing */
+ /* but, we also dont draw names for sets or duplicators */
+ if(flag == 0) {
+ if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
+ glRasterPos3f(0.0, 0.0, 0.0);
+
+ BMF_DrawString(G.font, " ");
+ BMF_DrawString(G.font, ob->id.name+2);
+ if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ }
+ }
+ /*if(dtx & OB_DRAWIMAGE) drawDispListwire(&ob->disp);*/
+ if((dtx & OB_DRAWWIRE) && dt>=OB_SOLID) drawWireExtra(scene, rv3d, ob);
+ }
+
+ if(dt<OB_SHADED) {
+ if((ob->gameflag & OB_DYNAMIC) ||
+ ((ob->gameflag & OB_BOUNDS) && (ob->boundtype == OB_BOUND_SPHERE))) {
+ float tmat[4][4], imat[4][4], vec[3];
+
+ vec[0]= vec[1]= vec[2]= 0.0;
+ wmGetMatrix(tmat);
+ Mat4Invert(imat, tmat);
+
+ setlinestyle(2);
+ drawcircball(GL_LINE_LOOP, vec, ob->inertia, imat);
+ setlinestyle(0);
+ }
+ }
+
+ wmLoadMatrix(rv3d->viewmat);
+
+ if(zbufoff) glDisable(GL_DEPTH_TEST);
+
+ if(warning_recursive) return;
+ if(base->flag & (OB_FROMDUPLI|OB_RADIO)) return;
+ if(G.f & G_RENDER_SHADOW) return;
+
+ /* object centers, need to be drawn in viewmat space for speed, but OK for picking select */
+ if(ob!=OBACT || (G.f & (G_VERTEXPAINT|G_TEXTUREPAINT|G_WEIGHTPAINT))==0) {
+ int do_draw_center= -1; /* defines below are zero or positive... */
+
+ if((scene->basact)==base)
+ do_draw_center= ACTIVE;
+ else if(base->flag & SELECT)
+ do_draw_center= SELECT;
+ else if(empty_object || (v3d->flag & V3D_DRAW_CENTERS))
+ do_draw_center= DESELECT;
+
+ if(do_draw_center != -1) {
+ if(flag & DRAW_PICKING) {
+ /* draw a single point for opengl selection */
+ glBegin(GL_POINTS);
+ glVertex3fv(ob->obmat[3]);
+ glEnd();
+ }
+ else if((flag & DRAW_CONSTCOLOR)==0) {
+ /* we don't draw centers for duplicators and sets */
+ drawcentercircle(v3d, rv3d, ob->obmat[3], do_draw_center, ob->id.lib || ob->id.us>1);
+ }
+ }
+ }
+
+ /* not for sets, duplicators or picking */
+ if(flag==0 && (!(v3d->flag & V3D_HIDE_HELPLINES))) {
+ ListBase *list;
+
+ /* draw hook center and offset line */
+ if(ob!=scene->obedit) draw_hooks(ob);
+
+ /* help lines and so */
+ if(ob!=scene->obedit && ob->parent && (ob->parent->lay & v3d->lay)) {
+ setlinestyle(3);
+ glBegin(GL_LINES);
+ glVertex3fv(ob->obmat[3]);
+ glVertex3fv(ob->orig);
+ glEnd();
+ setlinestyle(0);
+ }
+
+ /* Drawing the constraint lines */
+ list = &ob->constraints;
+ if (list) {
+ bConstraint *curcon;
+ bConstraintOb *cob;
+ char col[4], col2[4];
+
+ UI_GetThemeColor3ubv(TH_GRID, col);
+ make_axis_color(col, col2, 'z');
+ glColor3ubv((GLubyte *)col2);
+
+ cob= constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
+
+ for (curcon = list->first; curcon; curcon=curcon->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if ((curcon->flag & CONSTRAINT_EXPAND) && (cti) && (cti->get_constraint_targets)) {
+ cti->get_constraint_targets(curcon, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ /* calculate target's matrix */
+ if (cti->get_target_matrix)
+ cti->get_target_matrix(curcon, cob, ct, bsystem_time(scene, ob, (float)(scene->r.cfra), give_timeoffset(ob)));
+ else
+ Mat4One(ct->matrix);
+
+ setlinestyle(3);
+ glBegin(GL_LINES);
+ glVertex3fv(ct->matrix[3]);
+ glVertex3fv(ob->obmat[3]);
+ glEnd();
+ setlinestyle(0);
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(curcon, &targets, 1);
+ }
+ }
+
+ constraints_clear_evalob(cob);
+ }
+ }
+
+ free_old_images();
+}
+
+/* ***************** BACKBUF SEL (BBS) ********* */
+
+static void bbs_mesh_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
+{
+ int offset = (intptr_t) userData;
+ EditVert *eve = EM_get_vert_for_index(index);
+
+ if (eve->h==0) {
+ WM_set_framebuffer_index_color(offset+index);
+ bglVertex3fv(co);
+ }
+}
+static void bbs_mesh_verts(DerivedMesh *dm, int offset)
+{
+ glPointSize( UI_GetThemeValuef(TH_VERTEX_SIZE) );
+ bglBegin(GL_POINTS);
+ dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, (void*)(intptr_t) offset);
+ bglEnd();
+ glPointSize(1.0);
+}
+
+static int bbs_mesh_wire__setDrawOptions(void *userData, int index)
+{
+ int offset = (intptr_t) userData;
+ EditEdge *eed = EM_get_edge_for_index(index);
+
+ if (eed->h==0) {
+ WM_set_framebuffer_index_color(offset+index);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+static void bbs_mesh_wire(DerivedMesh *dm, int offset)
+{
+ dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, (void*)(intptr_t) offset);
+}
+
+static int bbs_mesh_solid__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
+{
+ if (EM_get_face_for_index(index)->h==0) {
+ if (userData) {
+ WM_set_framebuffer_index_color(index+1);
+ }
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static void bbs_mesh_solid__drawCenter(void *userData, int index, float *cent, float *no)
+{
+ EditFace *efa = EM_get_face_for_index(index);
+
+ if (efa->h==0 && efa->fgonf!=EM_FGON) {
+ WM_set_framebuffer_index_color(index+1);
+
+ bglVertex3fv(cent);
+ }
+}
+
+/* two options, facecolors or black */
+static void bbs_mesh_solid_EM(Scene *scene, View3D *v3d, Object *ob, DerivedMesh *dm, int facecol)
+{
+ cpack(0);
+
+ if (facecol) {
+ dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*)(intptr_t) 1, 0);
+
+ if( CHECK_OB_DRAWFACEDOT(scene, v3d, ob->dt) ) {
+ glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE));
+
+ bglBegin(GL_POINTS);
+ dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, NULL);
+ bglEnd();
+ }
+
+ } else {
+ dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*) 0, 0);
+ }
+}
+
+static int bbs_mesh_solid__setDrawOpts(void *userData, int index, int *drawSmooth_r)
+{
+ Mesh *me = userData;
+
+ if (!(me->mface[index].flag&ME_HIDE)) {
+ WM_set_framebuffer_index_color(index+1);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/* TODO remove this - since face select mode now only works with painting */
+static void bbs_mesh_solid(Scene *scene, View3D *v3d, Object *ob)
+{
+ DerivedMesh *dm = mesh_get_derived_final(scene, ob, v3d->customdata_mask);
+ Mesh *me = (Mesh*)ob->data;
+
+ glColor3ub(0, 0, 0);
+ dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, me, 0);
+
+ dm->release(dm);
+}
+
+void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
+{
+
+ wmMultMatrix(ob->obmat);
+
+ glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_DEPTH_TEST);
+
+ switch( ob->type) {
+ case OB_MESH:
+ {
+ if(ob == scene->obedit) {
+ Mesh *me= ob->data;
+ EditMesh *em= me->edit_mesh;
+
+ DerivedMesh *dm = editmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH);
+
+ EM_init_index_arrays(em, 1, 1, 1);
+
+ bbs_mesh_solid_EM(scene, v3d, ob, dm, scene->selectmode & SCE_SELECT_FACE);
+ if(scene->selectmode & SCE_SELECT_FACE)
+ em_solidoffs = 1+em->totface;
+ else
+ em_solidoffs= 1;
+
+ bglPolygonOffset(rv3d->dist, 1.0);
+
+ // we draw edges always, for loop (select) tools
+ bbs_mesh_wire(dm, em_solidoffs);
+ em_wireoffs= em_solidoffs + em->totedge;
+
+ // we draw verts if vert select mode or if in transform (for snap).
+ if(scene->selectmode & SCE_SELECT_VERTEX || G.moving & G_TRANSFORM_EDIT) {
+ bbs_mesh_verts(dm, em_wireoffs);
+ em_vertoffs= em_wireoffs + em->totvert;
+ }
+ else em_vertoffs= em_wireoffs;
+
+ bglPolygonOffset(rv3d->dist, 0.0);
+
+ dm->release(dm);
+
+ EM_free_index_arrays();
+ }
+ else bbs_mesh_solid(scene, v3d, ob);
+ }
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ break;
+ }
+
+ wmLoadMatrix(rv3d->viewmat);
+}
+
+
+/* ************* draw object instances for bones, for example ****************** */
+/* assumes all matrices/etc set OK */
+
+/* helper function for drawing object instances - meshes */
+static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d,
+ Object *ob, int dt, int outline)
+{
+ Mesh *me= ob->data;
+ DerivedMesh *dm=NULL, *edm=NULL;
+ int glsl;
+
+ if(ob == scene->obedit)
+ edm= editmesh_get_derived_base(ob, me->edit_mesh);
+ else
+ dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+
+ if(dt<=OB_WIRE) {
+ if(dm)
+ dm->drawEdges(dm, 1);
+ else if(edm)
+ edm->drawEdges(edm, 1);
+ }
+ else {
+ if(outline)
+ draw_mesh_object_outline(v3d, ob, dm?dm:edm);
+
+ if(dm) {
+ glsl = draw_glsl_material(scene, ob, v3d, dt);
+ GPU_set_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
+ }
+ else {
+ glEnable(GL_COLOR_MATERIAL);
+ UI_ThemeColor(TH_BONE_SOLID);
+ glDisable(GL_COLOR_MATERIAL);
+ }
+
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
+ glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
+ glEnable(GL_LIGHTING);
+
+ if(dm) {
+ dm->drawFacesSolid(dm, GPU_enable_material);
+ GPU_disable_material();
+ }
+ else if(edm)
+ edm->drawMappedFaces(edm, NULL, NULL, 0);
+
+ glDisable(GL_LIGHTING);
+ }
+
+ if(edm) edm->release(edm);
+ if(dm) dm->release(dm);
+}
+
+void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int dt, int outline)
+{
+ if (ob == NULL)
+ return;
+
+ switch (ob->type) {
+ case OB_MESH:
+ draw_object_mesh_instance(scene, v3d, rv3d, ob, dt, outline);
+ break;
+ case OB_EMPTY:
+ drawaxes(ob->empty_drawsize, 0, ob->empty_drawtype);
+ break;
+ }
+}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
new file mode 100644
index 00000000000..b7682225fe3
--- /dev/null
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -0,0 +1,804 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_action_types.h"
+#include "DNA_armature_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 "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_action.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "ED_armature.h"
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "RNA_access.h"
+
+#include "view3d_intern.h" // own include
+
+/* ******************** manage regions ********************* */
+
+ARegion *view3d_has_buttons_region(ScrArea *sa)
+{
+ ARegion *ar, *arnew;
+
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ if(ar->regiontype==RGN_TYPE_UI)
+ return ar;
+
+ /* add subdiv level; after header */
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ if(ar->regiontype==RGN_TYPE_HEADER)
+ break;
+
+ /* is error! */
+ if(ar==NULL) return NULL;
+
+ arnew= MEM_callocN(sizeof(ARegion), "buttons for view3d");
+
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype= RGN_TYPE_UI;
+ arnew->alignment= RGN_ALIGN_LEFT;
+
+ arnew->flag = RGN_FLAG_HIDDEN;
+
+ return arnew;
+}
+
+
+/* ******************** default callbacks for view3d space ***************** */
+
+static SpaceLink *view3d_new(const bContext *C)
+{
+ Scene *scene= CTX_data_scene(C);
+ ARegion *ar;
+ View3D *v3d;
+ RegionView3D *rv3d;
+
+ v3d= MEM_callocN(sizeof(View3D), "initview3d");
+ v3d->spacetype= SPACE_VIEW3D;
+ v3d->blockscale= 0.7f;
+ v3d->lay= v3d->layact= 1;
+ if(scene) {
+ v3d->lay= v3d->layact= scene->lay;
+ v3d->camera= scene->camera;
+ }
+ v3d->scenelock= 1;
+ v3d->grid= 1.0f;
+ v3d->gridlines= 16;
+ v3d->gridsubdiv = 10;
+ v3d->drawtype= OB_WIRE;
+
+ v3d->gridflag |= V3D_SHOW_X;
+ v3d->gridflag |= V3D_SHOW_Y;
+ v3d->gridflag |= V3D_SHOW_FLOOR;
+ v3d->gridflag &= ~V3D_SHOW_Z;
+
+ v3d->lens= 35.0f;
+ v3d->near= 0.01f;
+ v3d->far= 500.0f;
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for view3d");
+
+ BLI_addtail(&v3d->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_BOTTOM;
+
+ /* buttons/list view */
+ ar= MEM_callocN(sizeof(ARegion), "buttons for view3d");
+
+ BLI_addtail(&v3d->regionbase, ar);
+ ar->regiontype= RGN_TYPE_UI;
+ ar->alignment= RGN_ALIGN_LEFT;
+ ar->flag = RGN_FLAG_HIDDEN;
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for view3d");
+
+ BLI_addtail(&v3d->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+
+ ar->regiondata= MEM_callocN(sizeof(RegionView3D), "region view3d");
+ rv3d= ar->regiondata;
+ rv3d->viewquat[0]= 1.0f;
+ rv3d->persp= 1;
+ rv3d->view= 7;
+ rv3d->dist= 10.0;
+ Mat4One(rv3d->twmat);
+
+ return (SpaceLink *)v3d;
+}
+
+/* not spacelink itself */
+static void view3d_free(SpaceLink *sl)
+{
+ View3D *vd= (View3D *) sl;
+
+ if(vd->bgpic) {
+ if(vd->bgpic->ima) vd->bgpic->ima->id.us--;
+ MEM_freeN(vd->bgpic);
+ }
+
+ if(vd->localvd) MEM_freeN(vd->localvd);
+
+ if(vd->properties_storage) MEM_freeN(vd->properties_storage);
+
+}
+
+
+/* spacetype; init callback */
+static void view3d_init(struct wmWindowManager *wm, ScrArea *sa)
+{
+
+}
+
+static SpaceLink *view3d_duplicate(SpaceLink *sl)
+{
+ View3D *v3do= (View3D *)sl;
+ View3D *v3dn= MEM_dupallocN(sl);
+
+ /* clear or remove stuff from old */
+
+// XXX BIF_view3d_previewrender_free(v3do);
+
+ if(v3do->localvd) {
+ v3do->localvd= NULL;
+ v3do->properties_storage= NULL;
+ v3do->localview= 0;
+ v3do->lay= v3dn->localvd->lay;
+ v3do->lay &= 0xFFFFFF;
+ }
+
+ /* copy or clear inside new stuff */
+
+ if(v3dn->bgpic) {
+ v3dn->bgpic= MEM_dupallocN(v3dn->bgpic);
+ if(v3dn->bgpic->ima) v3dn->bgpic->ima->id.us++;
+ }
+ v3dn->properties_storage= NULL;
+
+ return (SpaceLink *)v3dn;
+}
+
+static void view3d_modal_keymaps(wmWindowManager *wm, ARegion *ar, int stype)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ ListBase *keymap;
+
+ /* copy last mode, then we can re-init the region maps */
+ rv3d->lastmode= stype;
+
+ keymap= WM_keymap_listbase(wm, "Object Mode", 0, 0);
+ if(ELEM(stype, 0, NS_MODE_OBJECT))
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+ else
+ WM_event_remove_keymap_handler(&ar->handlers, keymap);
+
+ keymap= WM_keymap_listbase(wm, "EditMesh", 0, 0);
+ if(stype==NS_EDITMODE_MESH)
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+ else
+ WM_event_remove_keymap_handler(&ar->handlers, keymap);
+
+ keymap= WM_keymap_listbase(wm, "Curve", 0, 0);
+ if(stype==NS_EDITMODE_CURVE)
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+ else
+ WM_event_remove_keymap_handler(&ar->handlers, keymap);
+
+ keymap= WM_keymap_listbase(wm, "Armature", 0, 0);
+ if(stype==NS_EDITMODE_ARMATURE)
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+ else
+ WM_event_remove_keymap_handler(&ar->handlers, keymap);
+
+ /* armature sketching needs to take over mouse */
+ keymap= WM_keymap_listbase(wm, "Armature_Sketch", 0, 0);
+ if(stype==NS_EDITMODE_TEXT)
+ WM_event_add_keymap_handler_priority(&ar->handlers, keymap, 10);
+ else
+ WM_event_remove_keymap_handler(&ar->handlers, keymap);
+
+ keymap= WM_keymap_listbase(wm, "Particle", 0, 0);
+ if(stype==NS_MODE_PARTICLE)
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+ else
+ WM_event_remove_keymap_handler(&ar->handlers, keymap);
+
+ /* editfont keymap swallows all... */
+ keymap= WM_keymap_listbase(wm, "Font", 0, 0);
+ if(stype==NS_EDITMODE_TEXT)
+ WM_event_add_keymap_handler_priority(&ar->handlers, keymap, 10);
+ else
+ WM_event_remove_keymap_handler(&ar->handlers, keymap);
+
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ ListBase *keymap;
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "View3D Generic", SPACE_VIEW3D, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap= WM_keymap_listbase(wm, "View3D", SPACE_VIEW3D, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+
+ /* object ops. */
+ keymap= WM_keymap_listbase(wm, "Object Non-modal", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+
+ /* pose is not modal, operator poll checks for this */
+ keymap= WM_keymap_listbase(wm, "Pose", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+
+ /* modal ops keymaps */
+ view3d_modal_keymaps(wm, ar, rv3d->lastmode);
+ /* operator poll checks for modes */
+ keymap= WM_keymap_listbase(wm, "ImagePaint", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+}
+
+/* type callback, not region itself */
+static void view3d_main_area_free(ARegion *ar)
+{
+ RegionView3D *rv3d= ar->regiondata;
+
+ if(rv3d) {
+ if(rv3d->localvd) MEM_freeN(rv3d->localvd);
+ if(rv3d->clipbb) MEM_freeN(rv3d->clipbb);
+
+ // XXX retopo_free_view_data(rv3d);
+ if(rv3d->ri) {
+ // XXX BIF_view3d_previewrender_free(rv3d);
+ }
+
+ if(rv3d->depths) {
+ if(rv3d->depths->depths) MEM_freeN(rv3d->depths->depths);
+ MEM_freeN(rv3d->depths);
+ }
+ MEM_freeN(rv3d);
+ ar->regiondata= NULL;
+ }
+}
+
+/* copy regiondata */
+static void *view3d_main_area_duplicate(void *poin)
+{
+ if(poin) {
+ RegionView3D *rv3d= poin, *new;
+
+ new= MEM_dupallocN(rv3d);
+ if(rv3d->localvd)
+ new->localvd= MEM_dupallocN(rv3d->localvd);
+ if(rv3d->clipbb)
+ new->clipbb= MEM_dupallocN(rv3d->clipbb);
+
+ new->depths= NULL;
+ new->retopo_view_data= NULL;
+ new->ri= NULL;
+ new->gpd= NULL;
+ new->sms= NULL;
+ new->smooth_timer= NULL;
+
+ return new;
+ }
+ return NULL;
+}
+
+static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ switch(wmn->data) {
+ case ND_TRANSFORM:
+ case ND_FRAME:
+ case ND_OB_ACTIVE:
+ case ND_OB_SELECT:
+ ED_region_tag_redraw(ar);
+ break;
+ case ND_MODE:
+ view3d_modal_keymaps(wmn->wm, ar, wmn->subtype);
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch(wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_TRANSFORM:
+ case ND_GEOM_SELECT:
+ case ND_GEOM_DATA:
+ case ND_DRAW:
+ case ND_MODIFIER:
+ case ND_KEYS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ case NC_GROUP:
+ /* all group ops for now */
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_MATERIAL:
+ switch(wmn->data) {
+ case ND_SHADING_DRAW:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ case NC_LAMP:
+ switch(wmn->data) {
+ case ND_LIGHTING_DRAW:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ case NC_IMAGE:
+ /* this could be more fine grained checks if we had
+ * more context than just the region */
+ ED_region_tag_redraw(ar);
+ break;
+ }
+}
+
+/* concept is to retrieve cursor type context-less */
+static void view3d_main_area_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
+{
+ Scene *scene= win->screen->scene;
+
+ if(scene->obedit) {
+ WM_cursor_set(win, CURSOR_EDIT);
+ }
+ else {
+ WM_cursor_set(win, CURSOR_STD);
+ }
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void view3d_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "View3D Generic", SPACE_VIEW3D, 0);
+
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+}
+
+static void view3d_header_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ /* clear */
+ if(ED_screen_area_active(C))
+ UI_GetThemeColor3fv(TH_HEADER, col);
+ else
+ UI_GetThemeColor3fv(TH_HEADERDESEL, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ view3d_header_buttons(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+static void view3d_header_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ switch(wmn->data) {
+ case ND_FRAME:
+ case ND_OB_ACTIVE:
+ case ND_OB_SELECT:
+ case ND_MODE:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ }
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void view3d_buttons_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ keymap= WM_keymap_listbase(wm, "View2D Buttons List", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap= WM_keymap_listbase(wm, "View3D Generic", SPACE_VIEW3D, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST_UI, ar->winx, ar->winy);
+}
+
+static void view3d_buttons_area_draw(const bContext *C, ARegion *ar)
+{
+ float col[3];
+
+ /* clear */
+ UI_GetThemeColor3fv(TH_HEADER, col);
+
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(C, &ar->v2d);
+
+ view3d_buttons_area_defbuts(C, ar);
+
+ /* restore view matrix? */
+ UI_view2d_view_restore(C);
+}
+
+static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ switch(wmn->data) {
+ case ND_FRAME:
+ case ND_OB_ACTIVE:
+ case ND_OB_SELECT:
+ case ND_MODE:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch(wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_TRANSFORM:
+ case ND_GEOM_SELECT:
+ case ND_GEOM_DATA:
+ case ND_DRAW:
+ case ND_KEYS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ }
+}
+
+/*
+ * Returns true if the Object is a from an external blend file (libdata)
+ */
+static int object_is_libdata(Object *ob)
+{
+ if (!ob) return 0;
+ if (ob->proxy) return 0;
+ if (ob->id.lib) return 1;
+ return 0;
+}
+
+static int view3d_context(const bContext *C, const char *member, bContextDataResult *result)
+{
+ View3D *v3d= CTX_wm_view3d(C);
+ Scene *scene= CTX_data_scene(C);
+ Base *base;
+
+ if(v3d==NULL) return 0;
+
+ if(CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
+ int selected_objects= CTX_data_equals(member, "selected_objects");
+
+ for(base=scene->base.first; base; base=base->next) {
+ if((base->flag & SELECT) && (base->lay & v3d->lay)) {
+ if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
+ if(selected_objects)
+ CTX_data_id_list_add(result, &base->object->id);
+ else
+ CTX_data_list_add(result, &scene->id, &RNA_UnknownType, base);
+ }
+ }
+ }
+
+ return 1;
+ }
+ else if(CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) {
+ int selected_editable_objects= CTX_data_equals(member, "selected_editable_objects");
+
+ for(base=scene->base.first; base; base=base->next) {
+ if((base->flag & SELECT) && (base->lay & v3d->lay)) {
+ if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
+ if(0==object_is_libdata(base->object)) {
+ if(selected_editable_objects)
+ CTX_data_id_list_add(result, &base->object->id);
+ else
+ CTX_data_list_add(result, &scene->id, &RNA_UnknownType, base);
+ }
+ }
+ }
+ }
+
+ return 1;
+ }
+ else if(CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) {
+ int visible_objects= CTX_data_equals(member, "visible_objects");
+
+ for(base=scene->base.first; base; base=base->next) {
+ if(base->lay & v3d->lay) {
+ if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
+ if(visible_objects)
+ CTX_data_id_list_add(result, &base->object->id);
+ else
+ CTX_data_list_add(result, &scene->id, &RNA_UnknownType, base);
+ }
+ }
+ }
+
+ return 1;
+ }
+ else if(CTX_data_equals(member, "active_base")) {
+ if(scene->basact && (scene->basact->lay & v3d->lay))
+ if((scene->basact->object->restrictflag & OB_RESTRICT_VIEW)==0)
+ CTX_data_pointer_set(result, &scene->id, &RNA_UnknownType, scene->basact);
+
+ return 1;
+ }
+ else if(CTX_data_equals(member, "active_object")) {
+ if(scene->basact && (scene->basact->lay & v3d->lay))
+ if((scene->basact->object->restrictflag & OB_RESTRICT_VIEW)==0)
+ CTX_data_id_pointer_set(result, &scene->basact->object->id);
+
+ return 1;
+ }
+ else if(CTX_data_equals(member, "visible_bones") || CTX_data_equals(member, "editable_bones")) {
+ Object *obedit= scene->obedit; // XXX get from context?
+ bArmature *arm= (obedit) ? obedit->data : NULL;
+ EditBone *ebone, *flipbone=NULL;
+ int editable_bones= CTX_data_equals(member, "editable_bones");
+
+ if (arm && arm->edbo) {
+ /* Attention: X-Axis Mirroring is also handled here... */
+ for (ebone= arm->edbo->first; ebone; ebone= ebone->next) {
+ /* first and foremost, bone must be visible and selected */
+ if (EBONE_VISIBLE(arm, ebone)) {
+ /* Get 'x-axis mirror equivalent' bone if the X-Axis Mirroring option is enabled
+ * so that most users of this data don't need to explicitly check for it themselves.
+ *
+ * We need to make sure that these mirrored copies are not selected, otherwise some
+ * bones will be operated on twice.
+ */
+ if (arm->flag & ARM_MIRROR_EDIT)
+ flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);
+
+ /* if we're filtering for editable too, use the check for that instead, as it has selection check too */
+ if (editable_bones) {
+ /* only selected + editable */
+ if (EBONE_EDITABLE(ebone)) {
+ CTX_data_list_add(result, &arm->id, &RNA_UnknownType, ebone);
+
+ if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
+ CTX_data_list_add(result, &arm->id, &RNA_UnknownType, flipbone);
+ }
+ }
+ else {
+ /* only include bones if visible */
+ CTX_data_list_add(result, &arm->id, &RNA_UnknownType, ebone);
+
+ if ((flipbone) && EBONE_VISIBLE(arm, flipbone)==0)
+ CTX_data_list_add(result, &arm->id, &RNA_UnknownType, flipbone);
+ }
+ }
+ }
+
+ return 1;
+ }
+ }
+ else if(CTX_data_equals(member, "selected_bones") || CTX_data_equals(member, "selected_editable_bones")) {
+ Object *obedit= scene->obedit; // XXX get from context?
+ bArmature *arm= (obedit) ? obedit->data : NULL;
+ EditBone *ebone, *flipbone=NULL;
+ int selected_editable_bones= CTX_data_equals(member, "selected_editable_bones");
+
+ if (arm && arm->edbo) {
+ /* Attention: X-Axis Mirroring is also handled here... */
+ for (ebone= arm->edbo->first; ebone; ebone= ebone->next) {
+ /* first and foremost, bone must be visible and selected */
+ if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_SELECTED)) {
+ /* Get 'x-axis mirror equivalent' bone if the X-Axis Mirroring option is enabled
+ * so that most users of this data don't need to explicitly check for it themselves.
+ *
+ * We need to make sure that these mirrored copies are not selected, otherwise some
+ * bones will be operated on twice.
+ */
+ if (arm->flag & ARM_MIRROR_EDIT)
+ flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);
+
+ /* if we're filtering for editable too, use the check for that instead, as it has selection check too */
+ if (selected_editable_bones) {
+ /* only selected + editable */
+ if (EBONE_EDITABLE(ebone)) {
+ CTX_data_list_add(result, &arm->id, &RNA_UnknownType, ebone);
+
+ if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
+ CTX_data_list_add(result, &arm->id, &RNA_UnknownType, flipbone);
+ }
+ }
+ else {
+ /* only include bones if selected */
+ CTX_data_list_add(result, &arm->id, &RNA_UnknownType, ebone);
+
+ if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
+ CTX_data_list_add(result, &arm->id, &RNA_UnknownType, flipbone);
+ }
+ }
+ }
+
+ return 1;
+ }
+ }
+ else if(CTX_data_equals(member, "visible_pchans")) {
+ Object *obact= OBACT;
+ bArmature *arm= (obact) ? obact->data : NULL;
+ bPoseChannel *pchan;
+
+ if (obact && arm) {
+ for (pchan= obact->pose->chanbase.first; pchan; pchan= pchan->next) {
+ /* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */
+ if ((pchan->bone) && (arm->layer & pchan->bone->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) {
+ CTX_data_list_add(result, &obact->id, &RNA_PoseChannel, pchan);
+ }
+ }
+
+ return 1;
+ }
+ }
+ else if(CTX_data_equals(member, "selected_pchans")) {
+ Object *obact= OBACT;
+ bArmature *arm= (obact) ? obact->data : NULL;
+ bPoseChannel *pchan;
+
+ if (obact && arm) {
+ for (pchan= obact->pose->chanbase.first; pchan; pchan= pchan->next) {
+ /* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */
+ if ((pchan->bone) && (arm->layer & pchan->bone->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) {
+ if (pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE))
+ CTX_data_list_add(result, &obact->id, &RNA_PoseChannel, pchan);
+ }
+ }
+
+ return 1;
+ }
+ }
+ else if(CTX_data_equals(member, "active_bone")) {
+ Object *obedit= scene->obedit; // XXX get from context?
+ bArmature *arm= (obedit) ? obedit->data : NULL;
+ EditBone *ebone;
+
+ if (arm && arm->edbo) {
+ for (ebone= arm->edbo->first; ebone; ebone= ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (ebone->flag & BONE_ACTIVE) {
+ CTX_data_pointer_set(result, &arm->id, &RNA_UnknownType, ebone);
+
+ return 1;
+ }
+ }
+ }
+ }
+
+ }
+ else if(CTX_data_equals(member, "active_pchan")) {
+ Object *obact= OBACT;
+ bPoseChannel *pchan;
+
+ pchan= get_active_posechannel(obact);
+ if (pchan) {
+ CTX_data_pointer_set(result, &obact->id, &RNA_PoseChannel, pchan);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* only called once, from space/spacetypes.c */
+void ED_spacetype_view3d(void)
+{
+ SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype view3d");
+ ARegionType *art;
+
+ st->spaceid= SPACE_VIEW3D;
+
+ st->new= view3d_new;
+ st->free= view3d_free;
+ st->init= view3d_init;
+ st->duplicate= view3d_duplicate;
+ st->operatortypes= view3d_operatortypes;
+ st->keymap= view3d_keymap;
+ st->context= view3d_context;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->keymapflag= ED_KEYMAP_FRAMES;
+ art->draw= view3d_main_area_draw;
+ art->init= view3d_main_area_init;
+ art->free= view3d_main_area_free;
+ art->duplicate= view3d_main_area_duplicate;
+ art->listener= view3d_main_area_listener;
+ art->cursor= view3d_main_area_cursor;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: listview/buttons */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region");
+ art->regionid = RGN_TYPE_UI;
+ art->minsizex= 220; // XXX
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
+ art->listener= view3d_buttons_area_listener;
+ art->init= view3d_buttons_area_init;
+ art->draw= view3d_buttons_area_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
+ art->listener= view3d_header_area_listener;
+ art->init= view3d_header_area_init;
+ art->draw= view3d_header_area_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
+}
+
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
new file mode 100644
index 00000000000..9a9786cebff
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -0,0 +1,1805 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <float.h>
+
+#include "DNA_ID.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+
+#include "BKE_action.h"
+#include "BKE_brush.h"
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_idprop.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_global.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_transform.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_armature.h"
+#include "ED_curve.h"
+#include "ED_image.h"
+#include "ED_keyframing.h"
+#include "ED_mesh.h"
+#include "ED_object.h"
+#include "ED_particle.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "view3d_intern.h" // own include
+
+
+/* ******************* view3d space & buttons ************** */
+#define B_NOP 1
+#define B_REDR 2
+#define B_OBJECTPANELROT 1007
+#define B_OBJECTPANELMEDIAN 1008
+#define B_ARMATUREPANEL1 1009
+#define B_ARMATUREPANEL2 1010
+#define B_OBJECTPANELPARENT 1011
+#define B_OBJECTPANEL 1012
+#define B_ARMATUREPANEL3 1013
+#define B_OBJECTPANELSCALE 1014
+#define B_OBJECTPANELDIMS 1015
+#define B_TRANSFORMSPACEADD 1016
+#define B_TRANSFORMSPACECLEAR 1017
+#define B_SETPT_AUTO 2125
+#define B_SETPT_VECTOR 2126
+#define B_SETPT_ALIGN 2127
+#define B_SETPT_FREE 2128
+#define B_RECALCMBALL 2501
+
+#define B_WEIGHT0_0 2840
+#define B_WEIGHT1_4 2841
+#define B_WEIGHT1_2 2842
+#define B_WEIGHT3_4 2843
+#define B_WEIGHT1_0 2844
+
+#define B_OPA1_8 2845
+#define B_OPA1_4 2846
+#define B_OPA1_2 2847
+#define B_OPA3_4 2848
+#define B_OPA1_0 2849
+
+#define B_CLR_WPAINT 2850
+
+#define B_RV3D_LOCKED 2900
+#define B_RV3D_BOXVIEW 2901
+#define B_RV3D_BOXCLIP 2902
+
+#define B_IDNAME 3000
+
+/* temporary struct for storing transform properties */
+typedef struct {
+ float ob_eul[4]; // used for quat too....
+ float ob_scale[3]; // need temp space due to linked values
+ float ob_dims[3];
+ short link_scale;
+ float ve_median[5];
+ int curdef;
+ float *defweightp;
+} TransformProperties;
+
+
+/* is used for both read and write... */
+static void v3d_editvertex_buts(const bContext *C, uiBlock *block, View3D *v3d, Object *ob, float lim)
+{
+ MDeformVert *dvert=NULL;
+ TransformProperties *tfp= v3d->properties_storage;
+ float median[5], ve_median[5];
+ int tot, totw, totweight, totedge;
+ char defstr[320];
+
+ median[0]= median[1]= median[2]= median[3]= median[4]= 0.0;
+ tot= totw= totweight= totedge= 0;
+ defstr[0]= 0;
+
+ if(ob->type==OB_MESH) {
+ Mesh *me= ob->data;
+ EditMesh *em = BKE_mesh_get_editmesh(me);
+ EditVert *eve, *evedef=NULL;
+ EditEdge *eed;
+
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f & SELECT) {
+ evedef= eve;
+ tot++;
+ VecAddf(median, median, eve->co);
+ }
+ eve= eve->next;
+ }
+ eed= em->edges.first;
+ while(eed) {
+ if((eed->f & SELECT)) {
+ totedge++;
+ median[3]+= eed->crease;
+ }
+ eed= eed->next;
+ }
+
+ /* check for defgroups */
+ if(evedef)
+ dvert= CustomData_em_get(&em->vdata, evedef->data, CD_MDEFORMVERT);
+ if(tot==1 && dvert && dvert->totweight) {
+ bDeformGroup *dg;
+ int i, max=1, init=1;
+ char str[320];
+
+ for (i=0; i<dvert->totweight; i++){
+ dg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr);
+ if(dg) {
+ max+= BLI_snprintf(str, sizeof(str), "%s %%x%d|", dg->name, dvert->dw[i].def_nr);
+ if(max<320) strcat(defstr, str);
+ }
+ else printf("oh no!\n");
+ if(tfp->curdef==dvert->dw[i].def_nr) {
+ init= 0;
+ tfp->defweightp= &dvert->dw[i].weight;
+ }
+ }
+
+ if(init) { // needs new initialized
+ tfp->curdef= dvert->dw[0].def_nr;
+ tfp->defweightp= &dvert->dw[0].weight;
+ }
+ }
+
+ BKE_mesh_end_editmesh(me, em);
+ }
+ else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
+ Curve *cu= ob->data;
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+
+ nu= cu->editnurb->first;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->f2 & SELECT) {
+ VecAddf(median, median, bezt->vec[1]);
+ tot++;
+ median[4]+= bezt->weight;
+ totweight++;
+ }
+ else {
+ if(bezt->f1 & SELECT) {
+ VecAddf(median, median, bezt->vec[0]);
+ tot++;
+ }
+ if(bezt->f3 & SELECT) {
+ VecAddf(median, median, bezt->vec[2]);
+ tot++;
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp->f1 & SELECT) {
+ VecAddf(median, median, bp->vec);
+ median[3]+= bp->vec[3];
+ totw++;
+ tot++;
+ median[4]+= bp->weight;
+ totweight++;
+ }
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ }
+ else if(ob->type==OB_LATTICE) {
+ Lattice *lt= ob->data;
+ BPoint *bp;
+ int a;
+
+ a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
+ bp= lt->editlatt->def;
+ while(a--) {
+ if(bp->f1 & SELECT) {
+ VecAddf(median, median, bp->vec);
+ tot++;
+ median[4]+= bp->weight;
+ totweight++;
+ }
+ bp++;
+ }
+ }
+
+ if(tot==0) return;
+
+ median[0] /= (float)tot;
+ median[1] /= (float)tot;
+ median[2] /= (float)tot;
+ if(totedge) median[3] /= (float)totedge;
+ else if(totw) median[3] /= (float)totw;
+ if(totweight) median[4] /= (float)totweight;
+
+ if(v3d->flag & V3D_GLOBAL_STATS)
+ Mat4MulVecfl(ob->obmat, median);
+
+ if(block) { // buttons
+ int but_y;
+ if((ob->parent) && (ob->partype == PARBONE)) but_y = 135;
+ else but_y = 150;
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 160, but_y, 70, 19, &v3d->flag, 0, 0, 0, 0, "Displays global values");
+ uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 230, but_y, 70, 19, &v3d->flag, 0, 0, 0, 0, "Displays local values");
+ uiBlockEndAlign(block);
+
+ memcpy(tfp->ve_median, median, sizeof(tfp->ve_median));
+
+ uiBlockBeginAlign(block);
+ if(tot==1) {
+ uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex X:", 10, 110, 290, 19, &(tfp->ve_median[0]), -lim, lim, 10, 3, "");
+ uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex Y:", 10, 90, 290, 19, &(tfp->ve_median[1]), -lim, lim, 10, 3, "");
+ uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex Z:", 10, 70, 290, 19, &(tfp->ve_median[2]), -lim, lim, 10, 3, "");
+ if(totw==1)
+ uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex W:", 10, 50, 290, 19, &(tfp->ve_median[3]), 0.01, 100.0, 10, 3, "");
+ uiBlockEndAlign(block);
+
+ if(defstr[0]) {
+ uiDefBut(block, LABEL, 1, "Vertex Deform Groups", 10, 40, 290, 20, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_NOP, "Weight:", 10, 20, 150, 19, tfp->defweightp, 0.0f, 1.0f, 10, 3, "Weight value");
+ uiDefButI(block, MENU, B_REDR, defstr, 160, 20, 140, 19, &tfp->curdef, 0.0, 0.0, 0, 0, "Current Vertex Group");
+ uiBlockEndAlign(block);
+ }
+ else if(totweight)
+ uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 10, 20, 290, 19, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "");
+
+ }
+ else {
+ uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median X:", 10, 110, 290, 19, &(tfp->ve_median[0]), -lim, lim, 10, 3, "");
+ uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Y:", 10, 90, 290, 19, &(tfp->ve_median[1]), -lim, lim, 10, 3, "");
+ uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Z:", 10, 70, 290, 19, &(tfp->ve_median[2]), -lim, lim, 10, 3, "");
+ if(totw==tot)
+ uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median W:", 10, 50, 290, 19, &(tfp->ve_median[3]), 0.01, 100.0, 10, 3, "");
+ uiBlockEndAlign(block);
+ if(totweight)
+ uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 10, 20, 290, 19, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "Weight is used for SoftBody Goal");
+ }
+
+ if(ob->type==OB_CURVE && (totw==0)) { /* bez curves have no w */
+ uiBlockBeginAlign(block);
+ uiDefBut(block, BUT,B_SETPT_AUTO,"Auto", 10, 44, 72, 19, 0, 0, 0, 0, 0, "Auto handles (Shift H)");
+ uiDefBut(block, BUT,B_SETPT_VECTOR,"Vector",82, 44, 73, 19, 0, 0, 0, 0, 0, "Vector handles (V)");
+ uiDefBut(block, BUT,B_SETPT_ALIGN,"Align",155, 44, 73, 19, 0, 0, 0, 0, 0, "Align handles (H Toggles)");
+ uiDefBut(block, BUT,B_SETPT_FREE,"Free", 227, 44, 72, 19, 0, 0, 0, 0, 0, "Align handles (H Toggles)");
+ uiBlockEndAlign(block);
+ }
+
+ if(totedge==1)
+ uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Crease W:", 10, 30, 290, 19, &(tfp->ve_median[3]), 0.0, 1.0, 10, 3, "");
+ else if(totedge>1)
+ uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Crease W:", 10, 30, 290, 19, &(tfp->ve_median[3]), 0.0, 1.0, 10, 3, "");
+
+ }
+ else { // apply
+ memcpy(ve_median, tfp->ve_median, sizeof(tfp->ve_median));
+
+ if(v3d->flag & V3D_GLOBAL_STATS) {
+ Mat4Invert(ob->imat, ob->obmat);
+ Mat4MulVecfl(ob->imat, median);
+ Mat4MulVecfl(ob->imat, ve_median);
+ }
+ VecSubf(median, ve_median, median);
+ median[3]= ve_median[3]-median[3];
+ median[4]= ve_median[4]-median[4];
+
+ if(ob->type==OB_MESH) {
+ Mesh *me= ob->data;
+ EditMesh *em = BKE_mesh_get_editmesh(me);
+ EditVert *eve;
+ EditEdge *eed;
+
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f & SELECT) {
+ VecAddf(eve->co, eve->co, median);
+ }
+ eve= eve->next;
+ }
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f & SELECT) {
+ /* ensure the median can be set to zero or one */
+ if(ve_median[3]==0.0f) eed->crease= 0.0f;
+ else if(ve_median[3]==1.0f) eed->crease= 1.0f;
+ else {
+ eed->crease+= median[3];
+ CLAMP(eed->crease, 0.0, 1.0);
+ }
+ }
+ }
+
+ recalc_editnormals(em);
+
+ BKE_mesh_end_editmesh(me, em);
+ }
+ else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
+ Curve *cu= ob->data;
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+
+ nu= cu->editnurb->first;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->f2 & SELECT) {
+ VecAddf(bezt->vec[0], bezt->vec[0], median);
+ VecAddf(bezt->vec[1], bezt->vec[1], median);
+ VecAddf(bezt->vec[2], bezt->vec[2], median);
+ bezt->weight+= median[4];
+ }
+ else {
+ if(bezt->f1 & SELECT) {
+ VecAddf(bezt->vec[0], bezt->vec[0], median);
+ }
+ if(bezt->f3 & SELECT) {
+ VecAddf(bezt->vec[2], bezt->vec[2], median);
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp->f1 & SELECT) {
+ VecAddf(bp->vec, bp->vec, median);
+ bp->vec[3]+= median[3];
+ bp->weight+= median[4];
+ }
+ bp++;
+ }
+ }
+ test2DNurb(nu);
+ testhandlesNurb(nu); /* test for bezier too */
+
+ nu= nu->next;
+ }
+ }
+ else if(ob->type==OB_LATTICE) {
+ Lattice *lt= ob->data;
+ BPoint *bp;
+ int a;
+
+ a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
+ bp= lt->editlatt->def;
+ while(a--) {
+ if(bp->f1 & SELECT) {
+ VecAddf(bp->vec, bp->vec, median);
+ bp->weight+= median[4];
+ }
+ bp++;
+ }
+ }
+
+// ED_undo_push(C, "Transform properties");
+ }
+}
+
+/* assumes armature active */
+static void validate_bonebutton_cb(bContext *C, void *bonev, void *namev)
+{
+ Object *ob= CTX_data_active_object(C);
+
+ if(ob && ob->type==OB_ARMATURE) {
+ Bone *bone= bonev;
+ char oldname[32], newname[32];
+
+ /* need to be on the stack */
+ BLI_strncpy(newname, bone->name, 32);
+ BLI_strncpy(oldname, (char *)namev, 32);
+ /* restore */
+ BLI_strncpy(bone->name, oldname, 32);
+
+ armature_bone_rename(ob, oldname, newname); // editarmature.c
+ }
+}
+
+static void v3d_posearmature_buts(uiBlock *block, View3D *v3d, Object *ob, float lim)
+{
+ uiBut *but;
+ bArmature *arm;
+ bPoseChannel *pchan;
+ Bone *bone= NULL;
+ TransformProperties *tfp= v3d->properties_storage;
+
+ arm = ob->data;
+ if (!arm || !ob->pose) return;
+
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ bone = pchan->bone;
+ if(bone && (bone->flag & BONE_ACTIVE) && (bone->layer & arm->layer))
+ break;
+ }
+ if (!pchan || !bone) return;
+
+ if((ob->parent) && (ob->partype == PARBONE))
+ but= uiDefBut (block, TEX, B_NOP, "Bone:", 160, 130, 140, 19, bone->name, 1, 31, 0, 0, "");
+ else
+ but= uiDefBut(block, TEX, B_NOP, "Bone:", 160, 140, 140, 19, bone->name, 1, 31, 0, 0, "");
+ uiButSetFunc(but, validate_bonebutton_cb, bone, NULL);
+ uiButSetCompleteFunc(but, autocomplete_bone, (void *)ob);
+
+ QuatToEul(pchan->quat, tfp->ob_eul);
+ tfp->ob_eul[0]*= 180.0/M_PI;
+ tfp->ob_eul[1]*= 180.0/M_PI;
+ tfp->ob_eul[2]*= 180.0/M_PI;
+
+ uiBlockBeginAlign(block);
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCX, B_REDR, ICON_UNLOCKED, 10,140,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_ARMATUREPANEL2, "LocX:", 30, 140, 120, 19, pchan->loc, -lim, lim, 100, 3, "");
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCY, B_REDR, ICON_UNLOCKED, 10,120,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_ARMATUREPANEL2, "LocY:", 30, 120, 120, 19, pchan->loc+1, -lim, lim, 100, 3, "");
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCZ, B_REDR, ICON_UNLOCKED, 10,100,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_ARMATUREPANEL2, "LocZ:", 30, 100, 120, 19, pchan->loc+2, -lim, lim, 100, 3, "");
+
+ uiBlockBeginAlign(block);
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTX, B_REDR, ICON_UNLOCKED, 10,70,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_ARMATUREPANEL3, "RotX:", 30, 70, 120, 19, tfp->ob_eul, -1000.0, 1000.0, 100, 3, "");
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTY, B_REDR, ICON_UNLOCKED, 10,50,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_ARMATUREPANEL3, "RotY:", 30, 50, 120, 19, tfp->ob_eul+1, -1000.0, 1000.0, 100, 3, "");
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTZ, B_REDR, ICON_UNLOCKED, 10,30,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_ARMATUREPANEL3, "RotZ:", 30, 30, 120, 19, tfp->ob_eul+2, -1000.0, 1000.0, 100, 3, "");
+
+ uiBlockBeginAlign(block);
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEX, B_REDR, ICON_UNLOCKED, 160,70,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_ARMATUREPANEL2, "ScaleX:", 180, 70, 120, 19, pchan->size, -lim, lim, 10, 3, "");
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEY, B_REDR, ICON_UNLOCKED, 160,50,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_ARMATUREPANEL2, "ScaleY:", 180, 50, 120, 19, pchan->size+1, -lim, lim, 10, 3, "");
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEZ, B_REDR, ICON_UNLOCKED, 160,30,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_ARMATUREPANEL2, "ScaleZ:", 180, 30, 120, 19, pchan->size+2, -lim, lim, 10, 3, "");
+ uiBlockEndAlign(block);
+}
+
+/* assumes armature editmode */
+void validate_editbonebutton_cb(bContext *C, void *bonev, void *namev)
+{
+ EditBone *eBone= bonev;
+ char oldname[32], newname[32];
+
+ /* need to be on the stack */
+ BLI_strncpy(newname, eBone->name, 32);
+ BLI_strncpy(oldname, (char *)namev, 32);
+ /* restore */
+ BLI_strncpy(eBone->name, oldname, 32);
+
+ armature_bone_rename(CTX_data_edit_object(C), oldname, newname); // editarmature.c
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, CTX_data_edit_object(C)); // XXX fix
+}
+
+static void v3d_editarmature_buts(uiBlock *block, View3D *v3d, Object *ob, float lim)
+{
+ bArmature *arm= ob->data;
+ EditBone *ebone;
+ uiBut *but;
+ TransformProperties *tfp= v3d->properties_storage;
+
+ ebone= arm->edbo->first;
+
+ for (ebone = arm->edbo->first; ebone; ebone=ebone->next){
+ if ((ebone->flag & BONE_ACTIVE) && (ebone->layer & arm->layer))
+ break;
+ }
+
+ if (!ebone)
+ return;
+
+ if((ob->parent) && (ob->partype == PARBONE))
+ but= uiDefBut(block, TEX, B_NOP, "Bone:", 160, 130, 140, 19, ebone->name, 1, 31, 0, 0, "");
+ else
+ but= uiDefBut(block, TEX, B_NOP, "Bone:", 160, 150, 140, 19, ebone->name, 1, 31, 0, 0, "");
+ uiButSetFunc(but, validate_editbonebutton_cb, ebone, NULL);
+
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadX:", 10, 70, 140, 19, ebone->head, -lim, lim, 10, 3, "");
+ uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadY:", 10, 50, 140, 19, ebone->head+1, -lim, lim, 10, 3, "");
+ uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadZ:", 10, 30, 140, 19, ebone->head+2, -lim, lim, 10, 3, "");
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_ARMATUREPANEL1, "TailX:", 160, 70, 140, 19, ebone->tail, -lim, lim, 10, 3, "");
+ uiDefButF(block, NUM, B_ARMATUREPANEL1, "TailY:", 160, 50, 140, 19, ebone->tail+1, -lim, lim, 10, 3, "");
+ uiDefButF(block, NUM, B_ARMATUREPANEL1, "TailZ:", 160, 30, 140, 19, ebone->tail+2, -lim, lim, 10, 3, "");
+ uiBlockEndAlign(block);
+
+ tfp->ob_eul[0]= 180.0*ebone->roll/M_PI;
+ uiDefButF(block, NUM, B_ARMATUREPANEL1, "Roll:", 10, 100, 140, 19, tfp->ob_eul, -lim, lim, 1000, 3, "");
+
+ uiDefButBitI(block, TOG, BONE_EDITMODE_LOCKED, B_REDR, "Lock", 160, 100, 140, 19, &(ebone->flag), 0, 0, 0, 0, "Prevents bone from being transformed in edit mode");
+
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_ARMATUREPANEL1, "TailRadius:", 10, 150, 140, 19, &ebone->rad_tail, 0, lim, 10, 3, "");
+ if (ebone->parent && ebone->flag & BONE_CONNECTED )
+ uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadRadius:", 10, 130, 140, 19, &ebone->parent->rad_tail, 0, lim, 10, 3, "");
+ else
+ uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadRadius:", 10, 130, 140, 19, &ebone->rad_head, 0, lim, 10, 3, "");
+ uiBlockEndAlign(block);
+}
+
+static void v3d_editmetaball_buts(uiBlock *block, Object *ob, float lim)
+{
+ MetaElem *lastelem= NULL; // XXX
+
+ if(lastelem) {
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_RECALCMBALL, "LocX:", 10, 70, 140, 19, &lastelem->x, -lim, lim, 100, 3, "");
+ uiDefButF(block, NUM, B_RECALCMBALL, "LocY:", 10, 50, 140, 19, &lastelem->y, -lim, lim, 100, 3, "");
+ uiDefButF(block, NUM, B_RECALCMBALL, "LocZ:", 10, 30, 140, 19, &lastelem->z, -lim, lim, 100, 3, "");
+
+ uiBlockBeginAlign(block);
+ if(lastelem->type!=MB_BALL)
+ uiDefButF(block, NUM, B_RECALCMBALL, "dx:", 160, 70, 140, 19, &lastelem->expx, 0, lim, 100, 3, "");
+ if((lastelem->type!=MB_BALL) && (lastelem->type!=MB_TUBE))
+ uiDefButF(block, NUM, B_RECALCMBALL, "dy:", 160, 50, 140, 19, &lastelem->expy, 0, lim, 100, 3, "");
+ if((lastelem->type==MB_ELIPSOID) || (lastelem->type==MB_CUBE))
+ uiDefButF(block, NUM, B_RECALCMBALL, "dz:", 160, 30, 140, 19, &lastelem->expz, 0, lim, 100, 3, "");
+
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_RECALCMBALL, "Radius:", 10, 120, 140, 19, &lastelem->rad, 0, lim, 100, 3, "Size of the active metaball");
+ uiDefButF(block, NUM, B_RECALCMBALL, "Stiffness:", 10, 100, 140, 19, &lastelem->s, 0, 10, 100, 3, "Stiffness of the active metaball");
+ uiBlockEndAlign(block);
+
+ uiDefButS(block, MENU, B_RECALCMBALL, "Type%t|Ball%x0|Tube%x4|Plane%x5|Elipsoid%x6|Cube%x7", 160, 120, 140, 19, &lastelem->type, 0.0, 0.0, 0, 0, "Set active element type");
+
+ }
+}
+
+/* test if 'ob' is a parent somewhere in par's parents */
+static int test_parent_loop(Object *par, Object *ob)
+{
+ if(par == NULL) return 0;
+ if(ob == par) return 1;
+ return test_parent_loop(par->parent, ob);
+}
+
+static void do_view3d_region_buttons(bContext *C, void *arg, int event)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ View3D *v3d= CTX_wm_view3d(C);
+ BoundBox *bb;
+ Object *ob= OBACT;
+ TransformProperties *tfp= v3d->properties_storage;
+
+ switch(event) {
+
+ case B_REDR:
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return; /* no notifier! */
+
+ case B_OBJECTPANEL:
+ DAG_object_flush_update(scene, ob, OB_RECALC_OB);
+ break;
+
+ case B_OBJECTPANELROT:
+ if(ob) {
+ ob->rot[0]= M_PI*tfp->ob_eul[0]/180.0;
+ ob->rot[1]= M_PI*tfp->ob_eul[1]/180.0;
+ ob->rot[2]= M_PI*tfp->ob_eul[2]/180.0;
+ DAG_object_flush_update(scene, ob, OB_RECALC_OB);
+ }
+ break;
+
+ case B_OBJECTPANELSCALE:
+ if(ob) {
+
+ /* link scale; figure out which axis changed */
+ if (tfp->link_scale) {
+ float ratio, tmp, max = 0.0;
+ int axis;
+
+ axis = 0;
+ max = fabs(tfp->ob_scale[0] - ob->size[0]);
+ tmp = fabs(tfp->ob_scale[1] - ob->size[1]);
+ if (tmp > max) {
+ axis = 1;
+ max = tmp;
+ }
+ tmp = fabs(tfp->ob_scale[2] - ob->size[2]);
+ if (tmp > max) {
+ axis = 2;
+ max = tmp;
+ }
+
+ if (ob->size[axis] != tfp->ob_scale[axis]) {
+ if (fabs(ob->size[axis]) > FLT_EPSILON) {
+ ratio = tfp->ob_scale[axis] / ob->size[axis];
+ ob->size[0] *= ratio;
+ ob->size[1] *= ratio;
+ ob->size[2] *= ratio;
+ }
+ }
+ }
+ else {
+ VECCOPY(ob->size, tfp->ob_scale);
+
+ }
+ DAG_object_flush_update(scene, ob, OB_RECALC_OB);
+ }
+ break;
+
+ case B_OBJECTPANELDIMS:
+ bb= object_get_boundbox(ob);
+ if(bb) {
+ float old_dims[3], scale[3], ratio, len[3];
+ int axis;
+
+ Mat4ToSize(ob->obmat, scale);
+
+ len[0] = bb->vec[4][0] - bb->vec[0][0];
+ len[1] = bb->vec[2][1] - bb->vec[0][1];
+ len[2] = bb->vec[1][2] - bb->vec[0][2];
+
+ old_dims[0] = fabs(scale[0]) * len[0];
+ old_dims[1] = fabs(scale[1]) * len[1];
+ old_dims[2] = fabs(scale[2]) * len[2];
+
+ /* for each axis changed */
+ for (axis = 0; axis<3; axis++) {
+ if (fabs(old_dims[axis] - tfp->ob_dims[axis]) > 0.0001) {
+ if (old_dims[axis] > 0.0) {
+ ratio = tfp->ob_dims[axis] / old_dims[axis];
+ if (tfp->link_scale) {
+ ob->size[0] *= ratio;
+ ob->size[1] *= ratio;
+ ob->size[2] *= ratio;
+ break;
+ }
+ else {
+ ob->size[axis] *= ratio;
+ }
+ }
+ else {
+ if (len[axis] > 0) {
+ ob->size[axis] = tfp->ob_dims[axis] / len[axis];
+ }
+ }
+ }
+ }
+
+ /* prevent multiple B_OBJECTPANELDIMS events to keep scaling, cycling with TAB on buttons can cause that */
+ VECCOPY(tfp->ob_dims, old_dims);
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_OB);
+ }
+ break;
+
+ case B_OBJECTPANELMEDIAN:
+ if(ob) {
+ v3d_editvertex_buts(C, NULL, v3d, ob, 1.0);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+ break;
+
+ /* note; this case also used for parbone */
+ case B_OBJECTPANELPARENT:
+ if(ob) {
+ if(ob->id.lib || test_parent_loop(ob->parent, ob) )
+ ob->parent= NULL;
+ else {
+ DAG_scene_sort(scene);
+ DAG_object_flush_update(scene, ob, OB_RECALC_OB);
+ }
+ }
+ break;
+
+ case B_ARMATUREPANEL1:
+ {
+ bArmature *arm= obedit->data;
+ EditBone *ebone, *child;
+
+ for (ebone = arm->edbo->first; ebone; ebone=ebone->next){
+ if ((ebone->flag & BONE_ACTIVE) && (ebone->layer & arm->layer))
+ break;
+ }
+ if (ebone) {
+ ebone->roll= M_PI*tfp->ob_eul[0]/180.0;
+ // Update our parent
+ if (ebone->parent && ebone->flag & BONE_CONNECTED){
+ VECCOPY (ebone->parent->tail, ebone->head);
+ }
+
+ // Update our children if necessary
+ for (child = arm->edbo->first; child; child=child->next){
+ if (child->parent == ebone && (child->flag & BONE_CONNECTED)){
+ VECCOPY (child->head, ebone->tail);
+ }
+ }
+ if(arm->flag & ARM_MIRROR_EDIT) {
+ EditBone *eboflip= ED_armature_bone_get_mirrored(arm->edbo, ebone);
+ if(eboflip) {
+ eboflip->roll= -ebone->roll;
+ eboflip->head[0]= -ebone->head[0];
+ eboflip->tail[0]= -ebone->tail[0];
+
+ // Update our parent
+ if (eboflip->parent && eboflip->flag & BONE_CONNECTED){
+ VECCOPY (eboflip->parent->tail, eboflip->head);
+ }
+
+ // Update our children if necessary
+ for (child = arm->edbo->first; child; child=child->next){
+ if (child->parent == eboflip && (child->flag & BONE_CONNECTED)){
+ VECCOPY (child->head, eboflip->tail);
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case B_ARMATUREPANEL3: // rotate button on channel
+ {
+ bArmature *arm;
+ bPoseChannel *pchan;
+ Bone *bone;
+ float eul[3];
+
+ arm = ob->data;
+ if (!arm || !ob->pose) return;
+
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ bone = pchan->bone;
+ if(bone && (bone->flag & BONE_ACTIVE) && (bone->layer & arm->layer))
+ break;
+ }
+ if (!pchan) return;
+
+ /* make a copy to eul[3], to allow TAB on buttons to work */
+ eul[0]= M_PI*tfp->ob_eul[0]/180.0;
+ eul[1]= M_PI*tfp->ob_eul[1]/180.0;
+ eul[2]= M_PI*tfp->ob_eul[2]/180.0;
+ EulToQuat(eul, pchan->quat);
+ }
+ /* no break, pass on */
+ case B_ARMATUREPANEL2:
+ {
+ ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+ break;
+ case B_TRANSFORMSPACEADD:
+ BIF_manageTransformOrientation(C, 1, 0);
+ break;
+ case B_TRANSFORMSPACECLEAR:
+ BIF_clearTransformOrientation(C);
+ break;
+
+#if 0 // XXX
+ case B_WEIGHT0_0:
+ wpaint->weight = 0.0f;
+ break;
+
+ case B_WEIGHT1_4:
+ wpaint->weight = 0.25f;
+ break;
+ case B_WEIGHT1_2:
+ wpaint->weight = 0.5f;
+ break;
+ case B_WEIGHT3_4:
+ wpaint->weight = 0.75f;
+ break;
+ case B_WEIGHT1_0:
+ wpaint->weight = 1.0f;
+ break;
+
+ case B_OPA1_8:
+ wpaint->a = 0.125f;
+ break;
+ case B_OPA1_4:
+ wpaint->a = 0.25f;
+ break;
+ case B_OPA1_2:
+ wpaint->a = 0.5f;
+ break;
+ case B_OPA3_4:
+ wpaint->a = 0.75f;
+ break;
+ case B_OPA1_0:
+ wpaint->a = 1.0f;
+ break;
+#endif
+ case B_CLR_WPAINT:
+// if(!multires_level1_test()) {
+ {
+ bDeformGroup *defGroup = BLI_findlink(&ob->defbase, ob->actdef-1);
+ if(defGroup) {
+ Mesh *me= ob->data;
+ int a;
+ for(a=0; a<me->totvert; a++)
+ remove_vert_defgroup (ob, defGroup, a);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+ }
+ break;
+ case B_RV3D_LOCKED:
+ case B_RV3D_BOXVIEW:
+ case B_RV3D_BOXCLIP:
+ {
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= sa->regionbase.last;
+ RegionView3D *rv3d;
+ short viewlock;
+
+ ar= ar->prev;
+ rv3d= ar->regiondata;
+ viewlock= rv3d->viewlock;
+
+ if((viewlock & RV3D_LOCKED)==0)
+ viewlock= 0;
+ else if((viewlock & RV3D_BOXVIEW)==0)
+ viewlock &= ~RV3D_BOXCLIP;
+
+ for(; ar; ar= ar->prev) {
+ if(ar->alignment==RGN_ALIGN_QSPLIT) {
+ rv3d= ar->regiondata;
+ rv3d->viewlock= viewlock;
+ }
+ }
+
+ if(rv3d->viewlock & RV3D_BOXVIEW)
+ view3d_boxview_copy(sa, sa->regionbase.last);
+
+ ED_area_tag_redraw(sa);
+ }
+ break;
+ }
+
+ /* default for now */
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+}
+
+void removeTransformOrientation_func(bContext *C, void *target, void *unused)
+{
+ BIF_removeTransformOrientation(C, (TransformOrientation *) target);
+}
+
+void selectTransformOrientation_func(bContext *C, void *target, void *unused)
+{
+ BIF_selectTransformOrientation(C, (TransformOrientation *) target);
+}
+
+static void view3d_panel_transform_spaces(const bContext *C, ARegion *ar, short cntrl)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ View3D *v3d= CTX_wm_view3d(C);
+ ListBase *transform_spaces = &scene->transform_spaces;
+ TransformOrientation *ts = transform_spaces->first;
+ uiBlock *block;
+ uiBut *but;
+ int xco = 20, yco = 70, height = 140;
+ int index;
+
+ block= uiBeginBlock(C, ar, "view3d_panel_transform", UI_EMBOSS);
+ if(uiNewPanel(C, ar, block, "Transform Orientations", "View3d", 1000, 0, 318, height)==0) return;
+
+ uiNewPanelHeight(block, height);
+
+ uiBlockBeginAlign(block);
+
+ if (obedit)
+ uiDefBut(block, BUT, B_TRANSFORMSPACEADD, "Add", xco,120,80,20, 0, 0, 0, 0, 0, "Add the selected element as a Transform Orientation");
+ else
+ uiDefBut(block, BUT, B_TRANSFORMSPACEADD, "Add", xco,120,80,20, 0, 0, 0, 0, 0, "Add the active object as a Transform Orientation");
+
+ uiDefBut(block, BUT, B_TRANSFORMSPACECLEAR, "Clear", xco + 80,120,80,20, 0, 0, 0, 0, 0, "Removal all Transform Orientations");
+
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+
+ uiDefButS(block, ROW, B_REDR, "Global", xco, 90, 40,20, &v3d->twmode, 5.0, (float)V3D_MANIP_GLOBAL,0, 0, "Global Transform Orientation");
+ uiDefButS(block, ROW, B_REDR, "Local", xco + 40, 90, 40,20, &v3d->twmode, 5.0, (float)V3D_MANIP_LOCAL, 0, 0, "Local Transform Orientation");
+ uiDefButS(block, ROW, B_REDR, "Normal", xco + 80, 90, 40,20, &v3d->twmode, 5.0, (float)V3D_MANIP_NORMAL,0, 0, "Normal Transform Orientation");
+ uiDefButS(block, ROW, B_REDR, "View", xco + 120, 90, 40,20, &v3d->twmode, 5.0, (float)V3D_MANIP_VIEW, 0, 0, "View Transform Orientation");
+
+ for (index = V3D_MANIP_CUSTOM, ts = transform_spaces->first ; ts ; ts = ts->next, index++) {
+
+ UI_ThemeColor(TH_BUT_ACTION);
+ if (v3d->twmode == index) {
+ but = uiDefIconButS(block,ROW, B_REDR, ICON_CHECKBOX_HLT, xco,yco,XIC,YIC, &v3d->twmode, 5.0, (float)index, 0, 0, "Use this Custom Transform Orientation");
+ }
+ else {
+ but = uiDefIconButS(block,ROW, B_REDR, ICON_CHECKBOX_DEHLT, xco,yco,XIC,YIC, &v3d->twmode, 5.0, (float)index, 0, 0, "Use this Custom Transform Orientation");
+ }
+ uiButSetFunc(but, selectTransformOrientation_func, ts, NULL);
+ uiDefBut(block, TEX, 0, "", xco+=XIC, yco,100+XIC,20, &ts->name, 0, 30, 0, 0, "Edits the name of this Transform Orientation");
+ but = uiDefIconBut(block, BUT, B_REDR, ICON_X, xco+=100+XIC,yco,XIC,YIC, 0, 0, 0, 0, 0, "Deletes this Transform Orientation");
+ uiButSetFunc(but, removeTransformOrientation_func, ts, NULL);
+
+ xco = 20;
+ yco -= 25;
+ }
+ uiBlockEndAlign(block);
+
+ if(yco < 0) uiNewPanelHeight(block, height-yco);
+ uiEndBlock(C, block);
+}
+
+static void weight_paint_buttons(Scene *scene, uiBlock *block)
+{
+ VPaint *wpaint= scene->toolsettings->wpaint;
+ Object *ob;
+ ob= OBACT;
+
+ if(ob==NULL || ob->type!=OB_MESH) return;
+
+ /* XXX
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUMSLI, B_REDR, "Weight:",10,170,225,19, &wpaint->weight, 0, 1, 10, 0, "Sets the current vertex group's bone deformation strength");
+
+ uiDefBut(block, BUT, B_WEIGHT0_0 , "0", 10,150,45,19, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT, B_WEIGHT1_4 , "1/4", 55,150,45,19, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT, B_WEIGHT1_2 , "1/2", 100,150,45,19, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT, B_WEIGHT3_4 , "3/4", 145,150,45,19, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT, B_WEIGHT1_0 , "1", 190,150,45,19, 0, 0, 0, 0, 0, "");
+
+ uiDefButF(block, NUMSLI, B_NOP, "Opacity ", 10,130,225,19, &wpaint->a, 0.0, 1.0, 0, 0, "The amount of pressure on the brush");
+
+ uiDefBut(block, BUT, B_OPA1_8 , "1/8", 10,110,45,19, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT, B_OPA1_4 , "1/4", 55,110,45,19, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT, B_OPA1_2 , "1/2", 100,110,45,19, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT, B_OPA3_4 , "3/4", 145,110,45,19, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT, B_OPA1_0 , "1", 190,110,45,19, 0, 0, 0, 0, 0, "");
+
+ uiDefButF(block, NUMSLI, B_NOP, "Size ", 10,90,225,19, &wpaint->size, 2.0, 64.0, 0, 0, "The size of the brush");
+
+ uiBlockBeginAlign(block);
+ uiDefButS(block, ROW, B_NOP, "Mix", 250,170,60,17, &wpaint->mode, 1.0, 0.0, 0, 0, "Mix the vertex colors");
+ uiDefButS(block, ROW, B_NOP, "Add", 250,152,60,17, &wpaint->mode, 1.0, 1.0, 0, 0, "Add the vertex colors");
+ uiDefButS(block, ROW, B_NOP, "Sub", 250,134,60,17, &wpaint->mode, 1.0, 2.0, 0, 0, "Subtract from the vertex color");
+ uiDefButS(block, ROW, B_NOP, "Mul", 250,116,60,17, &wpaint->mode, 1.0, 3.0, 0, 0, "Multiply the vertex color");
+ uiDefButS(block, ROW, B_NOP, "Blur", 250, 98,60,17, &wpaint->mode, 1.0, 4.0, 0, 0, "Blur the weight with surrounding values");
+ uiDefButS(block, ROW, B_NOP, "Lighter", 250, 80,60,17, &wpaint->mode, 1.0, 5.0, 0, 0, "Paint over darker areas only");
+ uiDefButS(block, ROW, B_NOP, "Darker", 250, 62,60,17, &wpaint->mode, 1.0, 6.0, 0, 0, "Paint over lighter areas only");
+ uiBlockEndAlign(block);
+ */
+
+ /* draw options same as below */
+ uiBlockBeginAlign(block);
+ if (FACESEL_PAINT_TEST) {
+ Mesh *me= ob->data;
+ uiDefButBitI(block, TOG, ME_DRAWFACES, B_REDR, "Faces", 10,45,60,19, &me->drawflag, 0, 0, 0, 0, "Displays all faces as shades");
+ uiDefButBitI(block,TOG, ME_DRAWEDGES, B_REDR,"Edges",70,45,60,19, &me->drawflag, 2.0, 0, 0, 0, "Displays edges of visible faces");
+ uiDefButBitI(block,TOG, ME_HIDDENEDGES, B_REDR,"Hidden Edges",130,45,100,19, &me->drawflag, 2.0, 1.0, 0, 0, "Displays edges of hidden faces");
+ } else{
+ uiDefButBitC(block, TOG, OB_DRAWWIRE, B_REDR, "Wire", 10,45,75,19, &ob->dtx, 0, 0, 0, 0, "Displays the active object's wireframe in shaded drawing modes");
+ }
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, VP_AREA, 0, "All Faces", 10,20,60,19, &wpaint->flag, 0, 0, 0, 0, "Paint on all faces inside brush (otherwise only on face under mouse cursor)");
+ uiDefButBitS(block, TOG, VP_SOFT, 0, "Vert Dist", 70,20,60,19, &wpaint->flag, 0, 0, 0, 0, "Use distances to vertices (instead of all vertices of face)");
+ uiDefButBitS(block, TOGN, VP_HARD, 0, "Soft", 130,20,60,19, &wpaint->flag, 0, 0, 0, 0, "Use a soft brush");
+ uiDefButBitS(block, TOG, VP_NORMALS, 0, "Normals", 190,20,60,19, &wpaint->flag, 0, 0, 0, 0, "Applies the vertex normal before painting");
+ uiDefButBitS(block, TOG, VP_SPRAY, 0, "Spray", 250,20,55,19, &wpaint->flag, 0, 0, 0, 0, "Keep applying paint effect while holding mouse");
+ uiBlockEndAlign(block);
+
+ if(ob) {
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, VP_ONLYVGROUP, B_REDR, "Vgroup", 10,0,100,19, &wpaint->flag, 0, 0, 0, 0, "Only paint on vertices in the selected vertex group.");
+ uiDefButBitS(block, TOG, VP_MIRROR_X, B_REDR, "X-Mirror", 110,0,100,19, &wpaint->flag, 0, 0, 0, 0, "Mirrored Paint, applying on mirrored Weight Group name");
+ uiDefBut(block, BUT, B_CLR_WPAINT, "Clear", 210,0,100,19, NULL, 0, 0, 0, 0, "Removes reference to this deform group from all vertices");
+ uiBlockEndAlign(block);
+ }
+}
+
+static void brush_idpoin_handle(bContext *C, ID *id, int event)
+{
+ Brush **br = current_brush_source(CTX_data_scene(C));
+
+ if(!br)
+ return;
+
+ switch(event) {
+ case UI_ID_BROWSE:
+ (*br) = (Brush*)id;
+ break;
+ case UI_ID_DELETE:
+ brush_delete(br);
+ break;
+ case UI_ID_RENAME:
+ /* XXX ? */
+ break;
+ case UI_ID_ADD_NEW:
+ if(id) {
+ (*br) = copy_brush((Brush*)id);
+ id->us--;
+ }
+ else
+ (*br) = add_brush("Brush");
+ break;
+ case UI_ID_OPEN:
+ /* XXX not implemented */
+ break;
+ }
+}
+
+static void view3d_panel_brush(const bContext *C, ARegion *ar, short cntrl)
+{
+ uiBlock *block;
+ Brush **brp = current_brush_source(CTX_data_scene(C)), *br;
+ short w = 268, h = 400, cx = 10, cy = h;
+ rctf rect;
+
+ if(!brp)
+ return;
+ br = *brp;
+
+ block= uiBeginBlock(C, ar, "view3d_panel_brush", UI_EMBOSS);
+ if(uiNewPanel(C, ar, block, "Brush", "View3d", 340, 10, 318, h)==0) return;
+ uiBlockSetHandleFunc(block, do_view3d_region_buttons, NULL);
+
+ uiBlockBeginAlign(block);
+ uiDefIDPoinButs(block, CTX_data_main(C), NULL, &br->id, ID_BR, NULL, cx, cy,
+ brush_idpoin_handle, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_OPEN|UI_ID_DELETE|UI_ID_ALONE);
+ cy-= 25;
+ uiBlockEndAlign(block);
+
+ if(!br)
+ return;
+
+ if(G.f & G_SCULPTMODE) {
+ uiBlockBeginAlign(block);
+ uiDefButC(block,ROW,B_REDR,"Draw",cx,cy,67,19,&br->sculpt_tool,14.0,SCULPT_TOOL_DRAW,0,0,"Draw lines on the model");
+ uiDefButC(block,ROW,B_REDR,"Smooth",cx+67,cy,67,19,&br->sculpt_tool,14.0,SCULPT_TOOL_SMOOTH,0,0,"Interactively smooth areas of the model");
+ uiDefButC(block,ROW,B_REDR,"Pinch",cx+134,cy,67,19,&br->sculpt_tool,14.0,SCULPT_TOOL_PINCH,0,0,"Interactively pinch areas of the model");
+ uiDefButC(block,ROW,B_REDR,"Inflate",cx+201,cy,67,19,&br->sculpt_tool,14,SCULPT_TOOL_INFLATE,0,0,"Push vertices along the direction of their normals");
+ cy-= 20;
+ uiDefButC(block,ROW,B_REDR,"Grab", cx,cy,89,19,&br->sculpt_tool,14,SCULPT_TOOL_GRAB,0,0,"Grabs a group of vertices and moves them with the mouse");
+ uiDefButC(block,ROW,B_REDR,"Layer", cx+89,cy,89,19,&br->sculpt_tool,14, SCULPT_TOOL_LAYER,0,0,"Adds a layer of depth");
+ uiDefButC(block,ROW,B_REDR,"Flatten", cx+178,cy,90,19,&br->sculpt_tool,14, SCULPT_TOOL_FLATTEN,0,0,"Interactively flatten areas of the model");
+ cy-= 25;
+ uiBlockEndAlign(block);
+ }
+
+ uiBlockBeginAlign(block);
+ uiDefButI(block,NUMSLI,B_NOP,"Size: ",cx,cy,w,19,&br->size,1.0,200.0,0,0,"Set brush radius in pixels");
+ cy-= 20;
+ uiDefButF(block,NUMSLI,B_NOP,"Strength: ",cx,cy,w,19,&br->alpha,0,1.0,0,0,"Set brush strength");
+ cy-= 25;
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+
+ uiDefButBitS(block, TOG, BRUSH_AIRBRUSH, B_NOP, "Airbrush", cx,cy,w/3,19, &br->flag,0,0,0,0, "Brush makes changes without waiting for the mouse to move");
+ uiDefButBitS(block, TOG, BRUSH_ANCHORED, B_NOP, "Rake", cx+w/3,cy,w/3,19, &br->flag,0,0,0,0, "");
+ uiDefButBitS(block, TOG, BRUSH_RAKE, B_NOP, "Anchored", cx+w*2.0/3,cy,w/3,19, &br->flag,0,0,0,0, "");
+ cy-= 20;
+ uiDefButBitS(block, TOG, BRUSH_SPACE, B_NOP, "Space", cx,cy,w/3,19, &br->flag,0,0,0,0, "");
+ uiDefButF(block,NUMSLI,B_NOP,"Spacing: ",cx+w/3,cy,w*2.0/3,19,&br->spacing,1.0,500,0,0,"");
+ cy-= 20;
+ uiBlockEndAlign(block);
+
+ rect.xmin= cx; rect.xmax= cx + w;
+ rect.ymin= cy - 200; rect.ymax= cy;
+ uiBlockBeginAlign(block);
+ curvemap_buttons(block, br->curve, (char)0, B_NOP, 0, &rect);
+ uiBlockEndAlign(block);
+
+ uiEndBlock(C, block);
+}
+
+static void sculptmode_draw_interface_tools(Scene *scene, uiBlock *block, unsigned short cx, unsigned short cy)
+{
+ Sculpt *s = scene->toolsettings->sculpt;
+
+ //XXX if(sd->brush_type != SMOOTH_BRUSH && sd->brush_type != GRAB_BRUSH && sd->brush_type != FLATTEN_BRUSH) {
+ {
+ /*uiDefButBitS(block,ROW,B_NOP,"Add",cx,cy,89,19,&br->dir,15.0,1.0,0, 0,"Add depth to model [Shift]");
+ uiDefButBitS(block,ROW,B_NOP,"Sub",cx+89,cy,89,19,&br->dir,15.0,2.0,0, 0,"Subtract depth from model [Shift]");
+ */}
+ //XXX if(sd->brush_type!=GRAB_BRUSH)
+
+ uiBlockBeginAlign(block);
+ uiDefBut( block,LABEL,B_NOP,"Symmetry",cx,cy,90,19,NULL,0,0,0,0,"");
+ cy-= 20;
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOG, SCULPT_SYMM_X, B_NOP, "X", cx,cy,40,19, &s->flags, 0,0,0,0, "Mirror brush across X axis");
+ uiDefButBitI(block, TOG, SCULPT_SYMM_Y, B_NOP, "Y", cx+40,cy,40,19, &s->flags, 0,0,0,0, "Mirror brush across Y axis");
+ uiDefButBitI(block, TOG, SCULPT_SYMM_Z, B_NOP, "Z", cx+80,cy,40,19, &s->flags, 0,0,0,0, "Mirror brush across Z axis");
+ uiBlockEndAlign(block);
+
+
+ cy+= 20;
+ uiBlockBeginAlign(block);
+ uiDefBut( block,LABEL,B_NOP,"LockAxis",cx+140,cy,90,19,NULL,0,0,0,0,"");
+ cy-= 20;
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOG, SCULPT_LOCK_X, B_NOP, "X", cx+140,cy,40,19, &s->flags, 0,0,0,0, "Constrain X axis");
+ uiDefButBitI(block, TOG, SCULPT_LOCK_Y, B_NOP, "Y", cx+180,cy,40,19, &s->flags, 0,0,0,0, "Constrain Y axis");
+ uiDefButBitI(block, TOG, SCULPT_LOCK_Z, B_NOP, "Z", cx+220,cy,40,19, &s->flags, 0,0,0,0, "Constrain Z axis");
+ uiBlockEndAlign(block);
+
+ cx+= 210;
+}
+
+
+static void view3d_panel_object(const bContext *C, ARegion *ar, short cntrl) // VIEW3D_HANDLER_OBJECT
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ View3D *v3d= CTX_wm_view3d(C);
+ uiBlock *block;
+ uiBut *bt;
+ Object *ob= OBACT;
+ TransformProperties *tfp;
+ float lim;
+ static char hexcol[128];
+
+ if(ob==NULL) return;
+
+ /* make sure we got storage */
+ if(v3d->properties_storage==NULL)
+ v3d->properties_storage= MEM_callocN(sizeof(TransformProperties), "TransformProperties");
+ tfp= v3d->properties_storage;
+
+ block= uiBeginBlock(C, ar, "view3d_panel_object", UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_view3d_region_buttons, NULL);
+
+ if((G.f & G_SCULPTMODE) && !obedit) {
+ if(!uiNewPanel(C, ar, block, "Transform Properties", "View3d", 10, 230, 318, 234))
+ return;
+ } else if(G.f & G_PARTICLEEDIT && !obedit){
+ if(!uiNewPanel(C, ar, block, "Transform Properties", "View3d", 10, 230, 318, 234))
+ return;
+ } else {
+ if(!uiNewPanel(C, ar, block, "Transform Properties", "View3d", 10, 230, 318, 204))
+ return;
+ }
+
+// XXX uiSetButLock(object_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
+
+ if(G.f & (G_VERTEXPAINT|G_TEXTUREPAINT|G_WEIGHTPAINT)) {
+ }
+ else {
+ bt= uiDefBut(block, TEX, B_IDNAME, "OB: ", 10,180,140,20, ob->id.name+2, 0.0, 21.0, 0, 0, "");
+ uiButSetFunc(bt, test_idbutton_cb, ob->id.name, NULL);
+
+ if((G.f & G_PARTICLEEDIT)==0) {
+ uiBlockBeginAlign(block);
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_OBJECTPANELPARENT, "Par:", 160, 180, 140, 20, &ob->parent, "Parent Object");
+ if((ob->parent) && (ob->partype == PARBONE)) {
+ bt= uiDefBut(block, TEX, B_OBJECTPANELPARENT, "ParBone:", 160, 160, 140, 20, ob->parsubstr, 0, 30, 0, 0, "");
+ uiButSetCompleteFunc(bt, autocomplete_bone, (void *)ob->parent);
+ }
+ else {
+ strcpy(ob->parsubstr, "");
+ }
+ uiBlockEndAlign(block);
+ }
+ }
+
+ lim= 10000.0f*MAX2(1.0, v3d->grid);
+
+ if(ob==obedit) {
+ if(ob->type==OB_ARMATURE) v3d_editarmature_buts(block, v3d, ob, lim);
+ if(ob->type==OB_MBALL) v3d_editmetaball_buts(block, ob, lim);
+ else v3d_editvertex_buts(C, block, v3d, ob, lim);
+ }
+ else if(ob->flag & OB_POSEMODE) {
+ v3d_posearmature_buts(block, v3d, ob, lim);
+ }
+ else if(G.f & G_WEIGHTPAINT) {
+ uiNewPanelTitle(block, "Weight Paint Properties");
+ weight_paint_buttons(scene, block);
+ }
+ else if(G.f & (G_VERTEXPAINT|G_TEXTUREPAINT)) {
+ static float hsv[3], old[3]; // used as temp mem for picker
+ Brush **br = current_brush_source(scene);
+
+ uiNewPanelTitle(block, "Paint Properties");
+ if(br && *br)
+ /* 'f' is for floating panel */
+ uiBlockPickerButtons(block, (*br)->rgb, hsv, old, hexcol, 'f', B_REDR);
+ }
+ else if(G.f & G_SCULPTMODE) {
+ uiNewPanelTitle(block, "Sculpt Properties");
+ sculptmode_draw_interface_tools(scene, block, 10, 150);
+ }
+ else if(G.f & G_PARTICLEEDIT){
+ uiNewPanelTitle(block, "Particle Edit Properties");
+// XXX particle_edit_buttons(block);
+ }
+ else {
+ BoundBox *bb = NULL;
+
+ uiBlockBeginAlign(block);
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCX, B_REDR, ICON_UNLOCKED, 10,150,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_OBJECTPANEL, "LocX:", 30, 150, 120, 19, &(ob->loc[0]), -lim, lim, 100, 3, "");
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCY, B_REDR, ICON_UNLOCKED, 10,130,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_OBJECTPANEL, "LocY:", 30, 130, 120, 19, &(ob->loc[1]), -lim, lim, 100, 3, "");
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCZ, B_REDR, ICON_UNLOCKED, 10,110,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_OBJECTPANEL, "LocZ:", 30, 110, 120, 19, &(ob->loc[2]), -lim, lim, 100, 3, "");
+
+ tfp->ob_eul[0]= 180.0*ob->rot[0]/M_PI;
+ tfp->ob_eul[1]= 180.0*ob->rot[1]/M_PI;
+ tfp->ob_eul[2]= 180.0*ob->rot[2]/M_PI;
+
+ uiBlockBeginAlign(block);
+ if ((ob->parent) && (ob->partype == PARBONE)) {
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTX, B_REDR, ICON_UNLOCKED, 160,130,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_OBJECTPANELROT, "RotX:", 180, 130, 120, 19, &(tfp->ob_eul[0]), -lim, lim, 1000, 3, "");
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTY, B_REDR, ICON_UNLOCKED, 160,110,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_OBJECTPANELROT, "RotY:", 180, 110, 120, 19, &(tfp->ob_eul[1]), -lim, lim, 1000, 3, "");
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTZ, B_REDR, ICON_UNLOCKED, 160,90,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_OBJECTPANELROT, "RotZ:", 180, 90, 120, 19, &(tfp->ob_eul[2]), -lim, lim, 1000, 3, "");
+
+ }
+ else {
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTX, B_REDR, ICON_UNLOCKED, 160,150,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_OBJECTPANELROT, "RotX:", 180, 150, 120, 19, &(tfp->ob_eul[0]), -lim, lim, 1000, 3, "");
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTY, B_REDR, ICON_UNLOCKED, 160,130,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_OBJECTPANELROT, "RotY:", 180, 130, 120, 19, &(tfp->ob_eul[1]), -lim, lim, 1000, 3, "");
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTZ, B_REDR, ICON_UNLOCKED, 160,110,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_OBJECTPANELROT, "RotZ:", 180, 110, 120, 19, &(tfp->ob_eul[2]), -lim, lim, 1000, 3, "");
+ }
+
+ tfp->ob_scale[0]= ob->size[0];
+ tfp->ob_scale[1]= ob->size[1];
+ tfp->ob_scale[2]= ob->size[2];
+
+ uiBlockBeginAlign(block);
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEX, B_REDR, ICON_UNLOCKED, 10,80,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_OBJECTPANELSCALE, "ScaleX:", 30, 80, 120, 19, &(tfp->ob_scale[0]), -lim, lim, 10, 3, "");
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEY, B_REDR, ICON_UNLOCKED, 10,60,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_OBJECTPANELSCALE, "ScaleY:", 30, 60, 120, 19, &(tfp->ob_scale[1]), -lim, lim, 10, 3, "");
+ uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEZ, B_REDR, ICON_UNLOCKED, 10,40,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
+ uiDefButF(block, NUM, B_OBJECTPANELSCALE, "ScaleZ:", 30, 40, 120, 19, &(tfp->ob_scale[2]), -lim, lim, 10, 3, "");
+ uiBlockEndAlign(block);
+
+ uiDefButS(block, TOG, B_REDR, "Link Scale", 10, 10, 140, 19, &(tfp->link_scale), 0, 1, 0, 0, "Scale values vary proportionally in all directions");
+
+ bb= object_get_boundbox(ob);
+ if (bb) {
+ float scale[3];
+
+ Mat4ToSize(ob->obmat, scale);
+
+ tfp->ob_dims[0] = fabs(scale[0]) * (bb->vec[4][0] - bb->vec[0][0]);
+ tfp->ob_dims[1] = fabs(scale[1]) * (bb->vec[2][1] - bb->vec[0][1]);
+ tfp->ob_dims[2] = fabs(scale[2]) * (bb->vec[1][2] - bb->vec[0][2]);
+
+ uiBlockBeginAlign(block);
+ if ((ob->parent) && (ob->partype == PARBONE)) {
+ uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimX:", 160, 60, 140, 19, &(tfp->ob_dims[0]), 0.0, lim, 10, 3, "Manipulate bounding box size");
+ uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimY:", 160, 40, 140, 19, &(tfp->ob_dims[1]), 0.0, lim, 10, 3, "Manipulate bounding box size");
+ uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimZ:", 160, 20, 140, 19, &(tfp->ob_dims[2]), 0.0, lim, 10, 3, "Manipulate bounding box size");
+
+ }
+ else {
+ uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimX:", 160, 80, 140, 19, &(tfp->ob_dims[0]), 0.0, lim, 10, 3, "Manipulate bounding box size");
+ uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimY:", 160, 60, 140, 19, &(tfp->ob_dims[1]), 0.0, lim, 10, 3, "Manipulate bounding box size");
+ uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimZ:", 160, 40, 140, 19, &(tfp->ob_dims[2]), 0.0, lim, 10, 3, "Manipulate bounding box size");
+ }
+
+ uiBlockEndAlign(block);
+ }
+ }
+// XXX uiClearButLock();
+ uiEndBlock(C, block);
+}
+
+static void view3d_panel_background(const bContext *C, ARegion *ar, short cntrl) // VIEW3D_HANDLER_BACKGROUND
+{
+ View3D *v3d= CTX_wm_view3d(C);
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "view3d_panel_background", UI_EMBOSS);
+ if(uiNewPanel(C, ar, block, "Background Image", "View3d", 340, 10, 318, 204)==0) return;
+ uiBlockSetHandleFunc(block, do_view3d_region_buttons, NULL);
+
+ if(v3d->flag & V3D_DISPBGPIC) {
+ if(v3d->bgpic==NULL) {
+ v3d->bgpic= MEM_callocN(sizeof(BGpic), "bgpic");
+ v3d->bgpic->size= 5.0;
+ v3d->bgpic->blend= 0.5;
+ v3d->bgpic->iuser.fie_ima= 2;
+ v3d->bgpic->iuser.ok= 1;
+ }
+ }
+
+ if(!(v3d->flag & V3D_DISPBGPIC)) {
+ uiDefButBitS(block, TOG, V3D_DISPBGPIC, B_REDR, "Use Background Image", 10, 180, 150, 20, &v3d->flag, 0, 0, 0, 0, "Display an image in the background of this 3D View");
+ uiDefBut(block, LABEL, 1, " ", 160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
+ }
+ else {
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, V3D_DISPBGPIC, B_REDR, "Use", 10, 225, 50, 20, &v3d->flag, 0, 0, 0, 0, "Display an image in the background of this 3D View");
+ uiDefButF(block, NUMSLI, B_REDR, "Blend:", 60, 225, 150, 20, &v3d->bgpic->blend, 0.0,1.0, 0, 0, "Set the transparency of the background image");
+ uiDefButF(block, NUM, B_REDR, "Size:", 210, 225, 100, 20, &v3d->bgpic->size, 0.1, 250.0*v3d->grid, 100, 0, "Set the size (width) of the background image");
+
+ uiDefButF(block, NUM, B_REDR, "X Offset:", 10, 205, 150, 20, &v3d->bgpic->xof, -250.0*v3d->grid,250.0*v3d->grid, 10, 2, "Set the horizontal offset of the background image");
+ uiDefButF(block, NUM, B_REDR, "Y Offset:", 160, 205, 150, 20, &v3d->bgpic->yof, -250.0*v3d->grid,250.0*v3d->grid, 10, 2, "Set the vertical offset of the background image");
+
+ ED_image_uiblock_panel(C, block, &v3d->bgpic->ima, &v3d->bgpic->iuser, B_REDR, B_REDR);
+ uiBlockEndAlign(block);
+ }
+ uiEndBlock(C, block);
+}
+
+
+static void view3d_panel_properties(const bContext *C, ARegion *ar, short cntrl) // VIEW3D_HANDLER_SETTINGS
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *arlast;
+ Scene *scene= CTX_data_scene(C);
+ View3D *v3d= CTX_wm_view3d(C);
+ RegionView3D *rv3d;
+ uiBlock *block;
+ float *curs;
+
+ block= uiBeginBlock(C, ar, "view3d_panel_properties", UI_EMBOSS);
+ if(uiNewPanel(C, ar, block, "View Properties", "View3d", 340, 30, 318, 254)==0) return;
+ uiBlockSetHandleFunc(block, do_view3d_region_buttons, NULL);
+
+ /* to force height */
+ uiNewPanelHeight(block, 264);
+
+ uiDefBut(block, LABEL, 1, "Grid:", 10, 220, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_REDR, "Spacing:", 10, 200, 140, 19, &v3d->grid, 0.001, 100.0, 10, 0, "Set the distance between grid lines");
+ uiDefButS(block, NUM, B_REDR, "Lines:", 10, 180, 140, 19, &v3d->gridlines, 0.0, 100.0, 100, 0, "Set the number of grid lines in perspective view");
+ uiDefButS(block, NUM, B_REDR, "Divisions:", 10, 160, 140, 19, &v3d->gridsubdiv, 1.0, 100.0, 100, 0, "Set the number of grid lines");
+ uiBlockEndAlign(block);
+
+ uiDefBut(block, LABEL, 1, "3D Display:", 160, 220, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefButBitS(block, TOG, V3D_SHOW_FLOOR, B_REDR, "Grid Floor",160, 200, 150, 19, &v3d->gridflag, 0, 0, 0, 0, "Show the grid floor in free camera mode");
+ uiDefButBitS(block, TOG, V3D_SHOW_X, B_REDR, "X Axis", 160, 176, 48, 19, &v3d->gridflag, 0, 0, 0, 0, "Show the X Axis line");
+ uiDefButBitS(block, TOG, V3D_SHOW_Y, B_REDR, "Y Axis", 212, 176, 48, 19, &v3d->gridflag, 0, 0, 0, 0, "Show the Y Axis line");
+ uiDefButBitS(block, TOG, V3D_SHOW_Z, B_REDR, "Z Axis", 262, 176, 48, 19, &v3d->gridflag, 0, 0, 0, 0, "Show the Z Axis line");
+
+ uiDefBut(block, LABEL, 1, "View Camera:", 10, 140, 140, 19, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefButF(block, NUM, B_REDR, "Lens:", 10, 120, 140, 19, &v3d->lens, 10.0, 120.0, 100, 0, "The lens angle in perspective view");
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_REDR, "Clip Start:", 10, 96, 140, 19, &v3d->near, v3d->grid/100.0, 100.0, 10, 0, "Set the beginning of the range in which 3D objects are displayed (perspective view)");
+ uiDefButF(block, NUM, B_REDR, "Clip End:", 10, 76, 140, 19, &v3d->far, 1.0, 10000.0*v3d->grid, 100, 0, "Set the end of the range in which 3D objects are displayed (perspective view)");
+ uiBlockEndAlign(block);
+
+ uiDefBut(block, LABEL, 1, "3D Cursor:", 160, 150, 140, 19, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiBlockBeginAlign(block);
+ curs= give_cursor(scene, v3d);
+ uiDefButF(block, NUM, B_REDR, "X:", 160, 130, 150, 22, curs, -10000.0*v3d->grid, 10000.0*v3d->grid, 10, 0, "X co-ordinate of the 3D cursor");
+ uiDefButF(block, NUM, B_REDR, "Y:", 160, 108, 150, 22, curs+1, -10000.0*v3d->grid, 10000.0*v3d->grid, 10, 0, "Y co-ordinate of the 3D cursor");
+ uiDefButF(block, NUM, B_REDR, "Z:", 160, 86, 150, 22, curs+2, -10000.0*v3d->grid, 10000.0*v3d->grid, 10, 0, "Z co-ordinate of the 3D cursor");
+ uiBlockEndAlign(block);
+
+ uiDefBut(block, LABEL, 1, "Display:", 10, 50, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, V3D_SELECT_OUTLINE, B_REDR, "Outline Selected", 10, 30, 140, 19, &v3d->flag, 0, 0, 0, 0, "Highlight selected objects with an outline, in Solid, Shaded or Textured viewport shading modes");
+ uiDefButBitS(block, TOG, V3D_DRAW_CENTERS, B_REDR, "All Object Centers", 10, 10, 140, 19, &v3d->flag, 0, 0, 0, 0, "Draw the center points on all objects");
+ uiDefButBitS(block, TOGN, V3D_HIDE_HELPLINES, B_REDR, "Relationship Lines", 10, -10, 140, 19, &v3d->flag, 0, 0, 0, 0, "Draw dashed lines indicating Parent, Constraint, or Hook relationships");
+ uiDefButBitS(block, TOG, V3D_SOLID_TEX, B_REDR, "Solid Tex", 10, -30, 140, 19, &v3d->flag2, 0, 0, 0, 0, "Display textures in Solid draw type (Shift T)");
+ uiBlockEndAlign(block);
+
+ uiDefBut(block, LABEL, 1, "View Locking:", 160, 60, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
+ uiBlockBeginAlign(block);
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_REDR, "Object:", 160, 40, 150, 19, &v3d->ob_centre, "Lock view to center to this Object");
+ uiDefBut(block, TEX, B_REDR, "Bone:", 160, 20, 150, 19, v3d->ob_centre_bone, 1, 31, 0, 0, "If view locked to Object, use this Bone to lock to view to");
+ uiBlockEndAlign(block);
+
+ /* last region is always 3d... a bit weak */
+ arlast= sa->regionbase.last;
+ uiBlockBeginAlign(block);
+ if(arlast->alignment==RGN_ALIGN_QSPLIT) {
+ arlast= arlast->prev;
+ rv3d= arlast->regiondata;
+
+ uiDefButO(block, BUT, "SCREEN_OT_region_foursplit", WM_OP_EXEC_REGION_WIN, "End 4-Split View", 160, -10, 150, 19, "Join the 3D View");
+ uiDefButBitS(block, TOG, RV3D_LOCKED, B_RV3D_LOCKED, "Lock", 160, -30, 50, 19, &rv3d->viewlock, 0, 0, 0, 0, "");
+ uiDefButBitS(block, TOG, RV3D_BOXVIEW, B_RV3D_BOXVIEW, "Box", 210, -30, 50, 19, &rv3d->viewlock, 0, 0, 0, 0, "");
+ uiDefButBitS(block, TOG, RV3D_BOXCLIP, B_RV3D_BOXCLIP, "Clip", 260, -30, 50, 19, &rv3d->viewlock, 0, 0, 0, 0, "");
+ }
+ else
+ uiDefButO(block, BUT, "SCREEN_OT_region_foursplit", WM_OP_EXEC_REGION_WIN, "4-Split View", 160, -10, 150, 19, "Split 3D View in 4 parts");
+
+ uiBlockEndAlign(block);
+
+
+// XXX
+// uiDefBut(block, LABEL, 1, "Keyframe Display:", 160, -2, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
+// uiBlockBeginAlign(block);
+// uiDefButBitS(block, TOG, ANIMFILTER_ACTIVE, B_REDR, "Active",160, -22, 50, 19, &v3d->keyflags, 0, 0, 0, 0, "Show keyframes for active element only (i.e. active bone or active material)");
+// uiDefButBitS(block, TOG, ANIMFILTER_MUTED, B_REDR, "Muted",210, -22, 50, 19, &v3d->keyflags, 0, 0, 0, 0, "Show keyframes in muted channels");
+// uiDefButBitS(block, TOG, ANIMFILTER_LOCAL, B_REDR, "Local",260, -22, 50, 19, &v3d->keyflags, 0, 0, 0, 0, "Show keyframes directly connected to datablock");
+// if ((v3d->keyflags & ANIMFILTER_LOCAL)==0) {
+// uiDefButBitS(block, TOGN, ANIMFILTER_NOMAT, B_REDR, "Material",160, -42, 75, 19, &v3d->keyflags, 0, 0, 0, 0, "Show keyframes for any available Materials");
+// uiDefButBitS(block, TOGN, ANIMFILTER_NOSKEY, B_REDR, "ShapeKey",235, -42, 75, 19, &v3d->keyflags, 0, 0, 0, 0, "Show keyframes for any available Shape Keys");
+// }
+ uiBlockEndAlign(block);
+
+ uiEndBlock(C, block);
+}
+
+#if 0
+static void view3d_panel_preview(bContext *C, ARegion *ar, short cntrl) // VIEW3D_HANDLER_PREVIEW
+{
+ uiBlock *block;
+ View3D *v3d= sa->spacedata.first;
+ int ofsx, ofsy;
+
+ block= uiBeginBlock(C, ar, "view3d_panel_preview", UI_EMBOSS);
+ uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
+ uiSetPanelHandler(VIEW3D_HANDLER_PREVIEW); // for close and esc
+
+ ofsx= -150+(sa->winx/2)/v3d->blockscale;
+ ofsy= -100+(sa->winy/2)/v3d->blockscale;
+ if(uiNewPanel(C, ar, block, "Preview", "View3d", ofsx, ofsy, 300, 200)==0) return;
+
+ uiBlockSetDrawExtraFunc(block, BIF_view3d_previewdraw);
+
+ if(scene->recalc & SCE_PRV_CHANGED) {
+ scene->recalc &= ~SCE_PRV_CHANGED;
+ //printf("found recalc\n");
+ BIF_view3d_previewrender_free(sa->spacedata.first);
+ BIF_preview_changed(0);
+ }
+}
+#endif
+
+static void view3d_panel_gpencil(const bContext *C, ARegion *ar, short cntrl) // VIEW3D_HANDLER_GREASEPENCIL
+{
+ View3D *v3d= CTX_wm_view3d(C);
+ uiBlock *block;
+
+ block= uiBeginBlock(C, ar, "view3d_panel_gpencil", UI_EMBOSS);
+ if (uiNewPanel(C, ar, block, "Grease Pencil", "View3d", 100, 30, 318, 204)==0) return;
+
+ /* allocate memory for gpd if drawing enabled (this must be done first or else we crash) */
+ if (v3d->flag2 & V3D_DISPGP) {
+// if (v3d->gpd == NULL)
+// XXX gpencil_data_setactive(ar, gpencil_data_addnew());
+ }
+
+ if (v3d->flag2 & V3D_DISPGP) {
+// XXX bGPdata *gpd= v3d->gpd;
+ short newheight;
+
+ /* this is a variable height panel, newpanel doesnt force new size on existing panels */
+ /* so first we make it default height */
+ uiNewPanelHeight(block, 204);
+
+ /* draw button for showing gpencil settings and drawings */
+ uiDefButBitS(block, TOG, V3D_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &v3d->flag2, 0, 0, 0, 0, "Display freehand annotations overlay over this 3D View (draw using Shift-LMB)");
+
+ /* extend the panel if the contents won't fit */
+// newheight= draw_gpencil_panel(block, gpd, ar);
+ uiNewPanelHeight(block, newheight);
+ }
+ else {
+ uiDefButBitS(block, TOG, V3D_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &v3d->flag2, 0, 0, 0, 0, "Display freehand annotations overlay over this 3D View");
+ uiDefBut(block, LABEL, 1, " ", 160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
+ }
+ uiEndBlock(C, block);
+}
+
+static void delete_sketch_armature(bContext *C, void *arg1, void *arg2)
+{
+ BIF_deleteSketch(C);
+}
+
+static void convert_sketch_armature(bContext *C, void *arg1, void *arg2)
+{
+ BIF_convertSketch(C);
+}
+
+static void assign_template_sketch_armature(bContext *C, void *arg1, void *arg2)
+{
+ int index = *(int*)arg1;
+ BIF_setTemplate(C, index);
+}
+static void view3d_panel_bonesketch_spaces(const bContext *C, ARegion *ar, short cntrl)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ static int template_index;
+ static char joint_label[128];
+ uiBlock *block;
+ uiBut *but;
+ char *bone_name;
+ int yco = 130, height = 140;
+ int nb_joints;
+
+ /* replace with check call to sketching lib */
+ if (obedit && obedit->type == OB_ARMATURE)
+ {
+ static char subdiv_tooltip[4][64] = {
+ "Subdivide arcs based on a fixed number of bones",
+ "Subdivide arcs in bones of equal length",
+ "Subdivide arcs based on correlation",
+ "Retarget template to stroke"
+ };
+
+
+ block= uiBeginBlock(C, ar, "view3d_panel_bonesketch_spaces", UI_EMBOSS);
+ if(uiNewPanel(C, ar, block, "Bone Sketching", "View3d", 340, 10, 318, height)==0) return;
+ uiBlockSetHandleFunc(block, do_view3d_region_buttons, NULL);
+
+ uiNewPanelHeight(block, height);
+
+ uiBlockBeginAlign(block);
+
+ /* use real flag instead of 1 */
+ uiDefButBitC(block, TOG, BONE_SKETCHING, B_REDR, "Use Bone Sketching", 10, yco, 160, 20, &scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones");
+ uiDefButBitC(block, TOG, BONE_SKETCHING_ADJUST, B_REDR, "A", 170, yco, 20, 20, &scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Adjust strokes by drawing near them");
+ uiDefButBitC(block, TOG, BONE_SKETCHING_QUICK, B_REDR, "Q", 190, yco, 20, 20, &scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Automatically convert and delete on stroke end");
+ yco -= 20;
+
+ but = uiDefBut(block, BUT, B_REDR, "Convert", 10,yco,100,20, 0, 0, 0, 0, 0, "Convert sketch to armature");
+ uiButSetFunc(but, convert_sketch_armature, NULL, NULL);
+
+ but = uiDefBut(block, BUT, B_REDR, "Delete", 110,yco,100,20, 0, 0, 0, 0, 0, "Delete sketch");
+ uiButSetFunc(but, delete_sketch_armature, NULL, NULL);
+ yco -= 20;
+
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+
+ uiDefButC(block, MENU, B_REDR, "Subdivision Method%t|Length%x1|Adaptative%x2|Fixed%x0|Template%x3", 10,yco,60,19, &scene->toolsettings->bone_sketching_convert, 0, 0, 0, 0, subdiv_tooltip[(unsigned char)scene->toolsettings->bone_sketching_convert]);
+
+ switch(scene->toolsettings->bone_sketching_convert)
+ {
+ case SK_CONVERT_CUT_LENGTH:
+ uiDefButF(block, NUM, B_REDR, "Lim:", 70, yco, 140, 19, &scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the subdivided bones");
+ yco -= 20;
+ break;
+ case SK_CONVERT_CUT_ADAPTATIVE:
+ uiDefButF(block, NUM, B_REDR, "Thres:", 70, yco, 140, 19, &scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Correlation threshold for subdivision");
+ yco -= 20;
+ break;
+ default:
+ case SK_CONVERT_CUT_FIXED:
+ uiDefButC(block, NUM, B_REDR, "Num:", 70, yco, 140, 19, &scene->toolsettings->skgen_subdivision_number,1, 100, 1, 5, "Number of subdivided bones");
+ yco -= 20;
+ break;
+ case SK_CONVERT_RETARGET:
+ uiDefButC(block, ROW, B_NOP, "No", 70, yco, 40,19, &scene->toolsettings->skgen_retarget_roll, 0, 0, 0, 0, "No special roll treatment");
+ uiDefButC(block, ROW, B_NOP, "View", 110, yco, 50,19, &scene->toolsettings->skgen_retarget_roll, 0, SK_RETARGET_ROLL_VIEW, 0, 0, "Roll bones perpendicular to view");
+ uiDefButC(block, ROW, B_NOP, "Joint", 160, yco, 50,19, &scene->toolsettings->skgen_retarget_roll, 0, SK_RETARGET_ROLL_JOINT, 0, 0, "Roll bones relative to joint bend");
+ yco -= 30;
+
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ /* button here to select what to do (copy or not), template, ...*/
+
+ BIF_makeListTemplates(C);
+ template_index = BIF_currentTemplate(C);
+
+ but = uiDefButI(block, MENU, B_REDR, BIF_listTemplates(C), 10,yco,200,19, &template_index, 0, 0, 0, 0, "Template");
+ uiButSetFunc(but, assign_template_sketch_armature, &template_index, NULL);
+
+ yco -= 20;
+
+ uiDefButF(block, NUM, B_NOP, "A:", 10, yco, 66,19, &scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0, "Angle Weight");
+ uiDefButF(block, NUM, B_NOP, "L:", 76, yco, 67,19, &scene->toolsettings->skgen_retarget_length_weight, 0, 10, 1, 0, "Length Weight");
+ uiDefButF(block, NUM, B_NOP, "D:", 143,yco, 67,19, &scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0, "Distance Weight");
+ yco -= 20;
+
+ uiDefBut(block, TEX,B_REDR,"S:", 10, yco, 90, 20, scene->toolsettings->skgen_side_string, 0.0, 8.0, 0, 0, "Text to replace &S with");
+ uiDefBut(block, TEX,B_REDR,"N:", 100, yco, 90, 20, scene->toolsettings->skgen_num_string, 0.0, 8.0, 0, 0, "Text to replace &N with");
+ uiDefIconButBitC(block, TOG, SK_RETARGET_AUTONAME, B_NOP, ICON_AUTO,190,yco,20,20, &scene->toolsettings->skgen_retarget_options, 0, 0, 0, 0, "Use Auto Naming");
+ yco -= 20;
+
+ /* auto renaming magic */
+ uiBlockEndAlign(block);
+
+ nb_joints = BIF_nbJointsTemplate(C);
+
+ if (nb_joints == -1)
+ {
+ //XXX
+ //nb_joints = G.totvertsel;
+ }
+
+ bone_name = BIF_nameBoneTemplate(C);
+
+ BLI_snprintf(joint_label, 32, "%i joints: %s", nb_joints, bone_name);
+
+ uiDefBut(block, LABEL, 1, joint_label, 10, yco, 200, 20, NULL, 0.0, 0.0, 0, 0, "");
+ yco -= 20;
+ break;
+ }
+
+ uiBlockEndAlign(block);
+
+ uiDefButBitS(block, TOG, SCE_SNAP_PEEL_OBJECT, B_NOP, "Peel Objects", 10, yco, 200, 20, &scene->snap_flag, 0, 0, 0, 0, "Peel whole objects as one");
+
+ if(yco < 0) uiNewPanelHeight(block, height-yco);
+ }
+}
+
+
+/* op->invoke */
+static void redo_cb(bContext *C, void *arg_op, void *arg2)
+{
+ wmOperator *lastop= arg_op;
+
+ if(lastop) {
+ int retval;
+
+ printf("operator redo %s\n", lastop->type->name);
+ ED_undo_pop(C);
+ retval= WM_operator_repeat(C, lastop);
+ if((retval & OPERATOR_FINISHED)==0) {
+ printf("operator redo failed %s\n", lastop->type->name);
+ ED_undo_redo(C);
+ }
+ }
+}
+
+static void view3d_panel_operator_redo(const bContext *C, ARegion *ar, short cntrl)
+{
+ wmWindowManager *wm= CTX_wm_manager(C);
+ wmOperator *op;
+ PointerRNA ptr;
+ uiBlock *block;
+ int height;
+
+ block= uiBeginBlock(C, ar, "view3d_panel_operator_redo", UI_EMBOSS);
+ if(uiNewPanel(C, ar, block, "Last Operator", "View3d", 340, 10, 318, height)==0) return;
+
+ /* only for operators that are registered and did an undo push */
+ for(op= wm->operators.last; op; op= op->prev)
+ if((op->type->flag & OPTYPE_REGISTER) && (op->type->flag & OPTYPE_UNDO))
+ break;
+
+ if(op==NULL)
+ return;
+
+ uiBlockSetFunc(block, redo_cb, op, NULL);
+
+ if(!op->properties) {
+ IDPropertyTemplate val = {0};
+ op->properties= IDP_New(IDP_GROUP, val, "wmOperatorProperties");
+ }
+
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+ height= uiDefAutoButsRNA(C, block, &ptr);
+
+ uiNewPanelHeight(block, height);
+
+ uiEndBlock(C, block);
+}
+
+
+void view3d_buttons_area_defbuts(const bContext *C, ARegion *ar)
+{
+ uiBeginPanels(C, ar);
+
+ view3d_panel_object(C, ar, 0);
+ view3d_panel_properties(C, ar, 0);
+ view3d_panel_background(C, ar, 0);
+ if(G.f & (G_SCULPTMODE|G_TEXTUREPAINT|G_VERTEXPAINT|G_WEIGHTPAINT))
+ view3d_panel_brush(C, ar, 0);
+ // XXX view3d_panel_preview(C, ar, 0);
+ view3d_panel_transform_spaces(C, ar, 0);
+ if(0)
+ view3d_panel_gpencil(C, ar, 0);
+
+ view3d_panel_bonesketch_spaces(C, ar, 0);
+
+ view3d_panel_operator_redo(C, ar, 0);
+
+ uiEndPanels(C, ar);
+}
+
+
+static int view3d_properties(bContext *C, wmOperator *op)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= view3d_has_buttons_region(sa);
+
+ if(ar) {
+ ar->flag ^= RGN_FLAG_HIDDEN;
+ ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */
+
+ ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
+ ED_area_tag_redraw(sa);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_properties(wmOperatorType *ot)
+{
+ ot->name= "Properties";
+ ot->idname= "VIEW3D_OT_properties";
+
+ ot->exec= view3d_properties;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= 0;
+}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
new file mode 100644
index 00000000000..0a063182368
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -0,0 +1,2118 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_customdata_types.h"
+#include "DNA_group_types.h"
+#include "DNA_key_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_anim.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_image.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_object.h"
+#include "BKE_global.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "RE_pipeline.h" // make_stars
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+#include "BMF_Api.h"
+
+#include "WM_api.h"
+
+#include "ED_armature.h"
+#include "ED_keyframing.h"
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+#include "ED_util.h"
+#include "ED_types.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "GPU_draw.h"
+#include "GPU_material.h"
+
+#include "view3d_intern.h" // own include
+
+
+
+static void star_stuff_init_func(void)
+{
+ cpack(-1);
+ glPointSize(1.0);
+ glBegin(GL_POINTS);
+}
+static void star_stuff_vertex_func(float* i)
+{
+ glVertex3fv(i);
+}
+static void star_stuff_term_func(void)
+{
+ glEnd();
+}
+
+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);
+}
+
+
+/* ********* custom clipping *********** */
+
+static void view3d_draw_clipping(RegionView3D *rv3d)
+{
+ BoundBox *bb= rv3d->clipbb;
+
+ if(bb) {
+ UI_ThemeColorShade(TH_BACK, -8);
+
+ glBegin(GL_QUADS);
+
+ glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[1]); glVertex3fv(bb->vec[2]); glVertex3fv(bb->vec[3]);
+ glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[5]); glVertex3fv(bb->vec[1]);
+ glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[6]); glVertex3fv(bb->vec[5]);
+ glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[3]); glVertex3fv(bb->vec[2]); glVertex3fv(bb->vec[6]);
+ glVertex3fv(bb->vec[1]); glVertex3fv(bb->vec[5]); glVertex3fv(bb->vec[6]); glVertex3fv(bb->vec[2]);
+ glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[3]);
+
+ glEnd();
+ }
+}
+
+void view3d_set_clipping(RegionView3D *rv3d)
+{
+ double plane[4];
+ int a, tot=4;
+
+ if(rv3d->viewlock) tot= 6;
+
+ for(a=0; a<tot; a++) {
+ QUATCOPY(plane, rv3d->clip[a]);
+ glClipPlane(GL_CLIP_PLANE0+a, plane);
+ glEnable(GL_CLIP_PLANE0+a);
+ }
+}
+
+void view3d_clr_clipping(void)
+{
+ int a;
+
+ for(a=0; a<6; a++) {
+ glDisable(GL_CLIP_PLANE0+a);
+ }
+}
+
+int view3d_test_clipping(RegionView3D *rv3d, float *vec)
+{
+ /* vec in world coordinates, returns 1 if clipped */
+ float view[3];
+
+ VECCOPY(view, vec);
+
+ if(0.0f < rv3d->clip[0][3] + INPR(view, rv3d->clip[0]))
+ if(0.0f < rv3d->clip[1][3] + INPR(view, rv3d->clip[1]))
+ if(0.0f < rv3d->clip[2][3] + INPR(view, rv3d->clip[2]))
+ if(0.0f < rv3d->clip[3][3] + INPR(view, rv3d->clip[3]))
+ return 0;
+
+ return 1;
+}
+
+/* ********* end custom clipping *********** */
+
+
+static void drawgrid_draw(ARegion *ar, float wx, float wy, float x, float y, float dx)
+{
+ float fx, fy;
+
+ x+= (wx);
+ y+= (wy);
+ fx= x/dx;
+ fx= x-dx*floor(fx);
+
+ while(fx< ar->winx) {
+ fdrawline(fx, 0.0, fx, (float)ar->winy);
+ fx+= dx;
+ }
+
+ fy= y/dx;
+ fy= y-dx*floor(fy);
+
+
+ while(fy< ar->winy) {
+ fdrawline(0.0, fy, (float)ar->winx, fy);
+ fy+= dx;
+ }
+
+}
+
+// not intern, called in editobject for constraint axis too
+void make_axis_color(char *col, char *col2, char axis)
+{
+ if(axis=='x') {
+ col2[0]= col[0]>219?255:col[0]+36;
+ col2[1]= col[1]<26?0:col[1]-26;
+ col2[2]= col[2]<26?0:col[2]-26;
+ }
+ else if(axis=='y') {
+ col2[0]= col[0]<46?0:col[0]-36;
+ col2[1]= col[1]>189?255:col[1]+66;
+ col2[2]= col[2]<46?0:col[2]-36;
+ }
+ else {
+ col2[0]= col[0]<26?0:col[0]-26;
+ col2[1]= col[1]<26?0:col[1]-26;
+ col2[2]= col[2]>209?255:col[2]+46;
+ }
+
+}
+
+static void drawgrid(ARegion *ar, View3D *v3d)
+{
+ /* extern short bgpicmode; */
+ RegionView3D *rv3d= ar->regiondata;
+ float wx, wy, x, y, fw, fx, fy, dx;
+ float vec4[4];
+ char col[3], col2[3];
+ short sublines = v3d->gridsubdiv;
+
+ vec4[0]=vec4[1]=vec4[2]=0.0;
+ vec4[3]= 1.0;
+ Mat4MulVec4fl(rv3d->persmat, vec4);
+ fx= vec4[0];
+ fy= vec4[1];
+ fw= vec4[3];
+
+ wx= (ar->winx/2.0); /* because of rounding errors, grid at wrong location */
+ wy= (ar->winy/2.0);
+
+ x= (wx)*fx/fw;
+ y= (wy)*fy/fw;
+
+ vec4[0]=vec4[1]=v3d->grid;
+ vec4[2]= 0.0;
+ vec4[3]= 1.0;
+ Mat4MulVec4fl(rv3d->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);
+
+ glDepthMask(0); // disable write in zbuffer
+
+ /* check zoom out */
+ UI_ThemeColor(TH_GRID);
+
+ if(dx<6.0) {
+ v3d->gridview*= sublines;
+ dx*= sublines;
+
+ if(dx<6.0) {
+ v3d->gridview*= sublines;
+ dx*= sublines;
+
+ if(dx<6.0) {
+ v3d->gridview*= sublines;
+ dx*=sublines;
+ if(dx<6.0);
+ else {
+ UI_ThemeColor(TH_GRID);
+ drawgrid_draw(ar, wx, wy, x, y, dx);
+ }
+ }
+ else { // start blending out
+ UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
+ drawgrid_draw(ar, wx, wy, x, y, dx);
+
+ UI_ThemeColor(TH_GRID);
+ drawgrid_draw(ar, wx, wy, x, y, sublines*dx);
+ }
+ }
+ else { // start blending out (6 < dx < 60)
+ UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
+ drawgrid_draw(ar, wx, wy, x, y, dx);
+
+ UI_ThemeColor(TH_GRID);
+ drawgrid_draw(ar, wx, wy, x, y, sublines*dx);
+ }
+ }
+ else {
+ if(dx>60.0) { // start blending in
+ v3d->gridview/= sublines;
+ dx/= sublines;
+ if(dx>60.0) { // start blending in
+ v3d->gridview/= sublines;
+ dx/= sublines;
+ if(dx>60.0) {
+ UI_ThemeColor(TH_GRID);
+ drawgrid_draw(ar, wx, wy, x, y, dx);
+ }
+ else {
+ UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
+ drawgrid_draw(ar, wx, wy, x, y, dx);
+ UI_ThemeColor(TH_GRID);
+ drawgrid_draw(ar, wx, wy, x, y, dx*sublines);
+ }
+ }
+ else {
+ UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
+ drawgrid_draw(ar, wx, wy, x, y, dx);
+ UI_ThemeColor(TH_GRID);
+ drawgrid_draw(ar, wx, wy, x, y, dx*sublines);
+ }
+ }
+ else {
+ UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
+ drawgrid_draw(ar, wx, wy, x, y, dx);
+ UI_ThemeColor(TH_GRID);
+ drawgrid_draw(ar, wx, wy, x, y, dx*sublines);
+ }
+ }
+
+ x+= (wx);
+ y+= (wy);
+ UI_GetThemeColor3ubv(TH_GRID, col);
+
+ setlinestyle(0);
+
+ /* center cross */
+ if( ELEM(rv3d->view, V3D_VIEW_RIGHT, V3D_VIEW_LEFT))
+ make_axis_color(col, col2, 'y');
+ else make_axis_color(col, col2, 'x');
+ glColor3ubv((GLubyte *)col2);
+
+ fdrawline(0.0, y, (float)ar->winx, y);
+
+ if( ELEM(rv3d->view, V3D_VIEW_TOP, V3D_VIEW_BOTTOM))
+ make_axis_color(col, col2, 'y');
+ else make_axis_color(col, col2, 'z');
+ glColor3ubv((GLubyte *)col2);
+
+ fdrawline(x, 0.0, x, (float)ar->winy);
+
+ glDepthMask(1); // enable write in zbuffer
+}
+
+
+static void drawfloor(Scene *scene, View3D *v3d)
+{
+ float vert[3], grid;
+ int a, gridlines, emphasise;
+ char col[3], col2[3];
+ short draw_line = 0;
+
+ vert[2]= 0.0;
+
+ if(v3d->gridlines<3) return;
+
+ if(v3d->zbuf && scene->obedit) glDepthMask(0); // for zbuffer-select
+
+ gridlines= v3d->gridlines/2;
+ grid= gridlines*v3d->grid;
+
+ UI_GetThemeColor3ubv(TH_GRID, col);
+ UI_GetThemeColor3ubv(TH_BACK, col2);
+
+ /* emphasise division lines lighter instead of darker, if background is darker than grid */
+ if ( ((col[0]+col[1]+col[2])/3+10) > (col2[0]+col2[1]+col2[2])/3 )
+ emphasise = 20;
+ else
+ emphasise = -10;
+
+ /* draw the Y axis and/or grid lines */
+ for(a= -gridlines;a<=gridlines;a++) {
+ if(a==0) {
+ /* check for the 'show Y axis' preference */
+ if (v3d->gridflag & V3D_SHOW_Y) {
+ make_axis_color(col, col2, 'y');
+ glColor3ubv((GLubyte *)col2);
+
+ draw_line = 1;
+ } else if (v3d->gridflag & V3D_SHOW_FLOOR) {
+ UI_ThemeColorShade(TH_GRID, emphasise);
+ } else {
+ draw_line = 0;
+ }
+ } else {
+ /* check for the 'show grid floor' preference */
+ if (v3d->gridflag & V3D_SHOW_FLOOR) {
+ if( (a % 10)==0) {
+ UI_ThemeColorShade(TH_GRID, emphasise);
+ }
+ else UI_ThemeColorShade(TH_GRID, 10);
+
+ draw_line = 1;
+ } else {
+ draw_line = 0;
+ }
+ }
+
+ if (draw_line) {
+ glBegin(GL_LINE_STRIP);
+ vert[0]= a*v3d->grid;
+ vert[1]= grid;
+ glVertex3fv(vert);
+ vert[1]= -grid;
+ glVertex3fv(vert);
+ glEnd();
+ }
+ }
+
+ /* draw the X axis and/or grid lines */
+ for(a= -gridlines;a<=gridlines;a++) {
+ if(a==0) {
+ /* check for the 'show X axis' preference */
+ if (v3d->gridflag & V3D_SHOW_X) {
+ make_axis_color(col, col2, 'x');
+ glColor3ubv((GLubyte *)col2);
+
+ draw_line = 1;
+ } else if (v3d->gridflag & V3D_SHOW_FLOOR) {
+ UI_ThemeColorShade(TH_GRID, emphasise);
+ } else {
+ draw_line = 0;
+ }
+ } else {
+ /* check for the 'show grid floor' preference */
+ if (v3d->gridflag & V3D_SHOW_FLOOR) {
+ if( (a % 10)==0) {
+ UI_ThemeColorShade(TH_GRID, emphasise);
+ }
+ else UI_ThemeColorShade(TH_GRID, 10);
+
+ draw_line = 1;
+ } else {
+ draw_line = 0;
+ }
+ }
+
+ if (draw_line) {
+ glBegin(GL_LINE_STRIP);
+ vert[1]= a*v3d->grid;
+ vert[0]= grid;
+ glVertex3fv(vert );
+ vert[0]= -grid;
+ glVertex3fv(vert);
+ glEnd();
+ }
+ }
+
+ /* draw the Z axis line */
+ /* check for the 'show Z axis' preference */
+ if (v3d->gridflag & V3D_SHOW_Z) {
+ make_axis_color(col, col2, 'z');
+ glColor3ubv((GLubyte *)col2);
+
+ glBegin(GL_LINE_STRIP);
+ vert[0]= 0;
+ vert[1]= 0;
+ vert[2]= grid;
+ glVertex3fv(vert );
+ vert[2]= -grid;
+ glVertex3fv(vert);
+ glEnd();
+ }
+
+ if(v3d->zbuf && scene->obedit) glDepthMask(1);
+
+}
+
+static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
+{
+ short mx,my,co[2];
+ int flag;
+
+ /* we dont want the clipping for cursor */
+ flag= v3d->flag;
+ v3d->flag= 0;
+ project_short(ar, give_cursor(scene, v3d), co);
+ v3d->flag= flag;
+
+ mx = co[0];
+ my = co[1];
+
+ if(mx!=IS_CLIPPED) {
+ setlinestyle(0);
+ cpack(0xFF);
+ circ((float)mx, (float)my, 10.0);
+ setlinestyle(4);
+ cpack(0xFFFFFF);
+ circ((float)mx, (float)my, 10.0);
+ setlinestyle(0);
+ cpack(0x0);
+
+ sdrawline(mx-20, my, mx-5, my);
+ sdrawline(mx+5, my, mx+20, my);
+ sdrawline(mx, my-20, mx, my-5);
+ sdrawline(mx, my+5, mx, my+20);
+ }
+}
+
+/* Draw a live substitute of the view icon, which is always shown */
+static void draw_view_axis(RegionView3D *rv3d)
+{
+ const float k = U.rvisize; /* axis size */
+ const float toll = 0.5; /* used to see when view is quasi-orthogonal */
+ const float start = k + 1.0; /* axis center in screen coordinates, x=y */
+ float ydisp = 0.0; /* vertical displacement to allow obj info text */
+
+ /* rvibright ranges approx. from original axis icon color to gizmo color */
+ float bright = U.rvibright / 15.0f;
+
+ unsigned char col[3];
+ unsigned char gridcol[3];
+ float colf[3];
+
+ float vec[4];
+ float dx, dy;
+ float h, s, v;
+
+ /* thickness of lines is proportional to k */
+ /* (log(k)-1) gives a more suitable thickness, but fps decreased by about 3 fps */
+ glLineWidth(k / 10);
+ //glLineWidth(log(k)-1); // a bit slow
+
+ UI_GetThemeColor3ubv(TH_GRID, (char *)gridcol);
+
+ /* X */
+ vec[0] = vec[3] = 1;
+ vec[1] = vec[2] = 0;
+ QuatMulVecf(rv3d->viewquat, vec);
+
+ make_axis_color((char *)gridcol, (char *)col, 'x');
+ rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
+ s = s<0.5 ? s+0.5 : 1.0;
+ v = 0.3;
+ v = (v<1.0-(bright) ? v+bright : 1.0);
+ hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
+ glColor3fv(colf);
+
+ dx = vec[0] * k;
+ dy = vec[1] * k;
+ fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
+ if (fabs(dx) > toll || fabs(dy) > toll) {
+ glRasterPos2i(start + dx + 2, start + dy + ydisp + 2);
+ BMF_DrawString(G.fonts, "x");
+ }
+
+ /* Y */
+ vec[1] = vec[3] = 1;
+ vec[0] = vec[2] = 0;
+ QuatMulVecf(rv3d->viewquat, vec);
+
+ make_axis_color((char *)gridcol, (char *)col, 'y');
+ rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
+ s = s<0.5 ? s+0.5 : 1.0;
+ v = 0.3;
+ v = (v<1.0-(bright) ? v+bright : 1.0);
+ hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
+ glColor3fv(colf);
+
+ dx = vec[0] * k;
+ dy = vec[1] * k;
+ fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
+ if (fabs(dx) > toll || fabs(dy) > toll) {
+ glRasterPos2i(start + dx + 2, start + dy + ydisp + 2);
+ BMF_DrawString(G.fonts, "y");
+ }
+
+ /* Z */
+ vec[2] = vec[3] = 1;
+ vec[1] = vec[0] = 0;
+ QuatMulVecf(rv3d->viewquat, vec);
+
+ make_axis_color((char *)gridcol, (char *)col, 'z');
+ rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
+ s = s<0.5 ? s+0.5 : 1.0;
+ v = 0.5;
+ v = (v<1.0-(bright) ? v+bright : 1.0);
+ hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
+ glColor3fv(colf);
+
+ dx = vec[0] * k;
+ dy = vec[1] * k;
+ fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
+ if (fabs(dx) > toll || fabs(dy) > toll) {
+ glRasterPos2i(start + dx + 2, start + dy + ydisp + 2);
+ BMF_DrawString(G.fonts, "z");
+ }
+
+ /* restore line-width */
+ glLineWidth(1.0);
+}
+
+
+static void draw_view_icon(RegionView3D *rv3d)
+{
+ BIFIconID icon;
+
+ if( ELEM(rv3d->view, V3D_VIEW_TOP, V3D_VIEW_BOTTOM))
+ icon= ICON_AXIS_TOP;
+ else if( ELEM(rv3d->view, V3D_VIEW_FRONT, V3D_VIEW_BACK))
+ icon= ICON_AXIS_FRONT;
+ else if( ELEM(rv3d->view, V3D_VIEW_RIGHT, V3D_VIEW_LEFT))
+ icon= ICON_AXIS_SIDE;
+ else return ;
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ UI_icon_draw(5.0, 5.0, icon);
+
+ glDisable(GL_BLEND);
+}
+
+static char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
+{
+ char *name = NULL;
+
+ switch (rv3d->view) {
+ case V3D_VIEW_FRONT:
+ if (rv3d->persp == V3D_ORTHO) name = "Front Ortho";
+ else name = "Front Persp";
+ break;
+ case V3D_VIEW_BACK:
+ if (rv3d->persp == V3D_ORTHO) name = "Back Ortho";
+ else name = "Back Persp";
+ break;
+ case V3D_VIEW_TOP:
+ if (rv3d->persp == V3D_ORTHO) name = "Top Ortho";
+ else name = "Top Persp";
+ break;
+ case V3D_VIEW_BOTTOM:
+ if (rv3d->persp == V3D_ORTHO) name = "Bottom Ortho";
+ else name = "Bottom Persp";
+ break;
+ case V3D_VIEW_RIGHT:
+ if (rv3d->persp == V3D_ORTHO) name = "Right Ortho";
+ else name = "Right Persp";
+ break;
+ case V3D_VIEW_LEFT:
+ if (rv3d->persp == V3D_ORTHO) name = "Left Ortho";
+ else name = "Left Persp";
+ break;
+
+ default:
+ if (rv3d->persp==V3D_CAMOB) {
+ if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
+ Camera *cam;
+ cam = v3d->camera->data;
+ name = (cam->type != CAM_ORTHO) ? "Camera Persp" : "Camera Ortho";
+ } else {
+ name = "Object as Camera";
+ }
+ } else {
+ name = (rv3d->persp == V3D_ORTHO) ? "User Ortho" : "User Persp";
+ }
+ break;
+ }
+
+ return name;
+}
+
+static void draw_viewport_name(ARegion *ar, View3D *v3d)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ char *name = view3d_get_name(v3d, rv3d);
+ char *printable = NULL;
+
+ if (v3d->localview) {
+ printable = malloc(strlen(name) + strlen(" (Local)_")); /* '_' gives space for '\0' */
+ strcpy(printable, name);
+ strcat(printable, " (Local)");
+ } else {
+ printable = name;
+ }
+
+ if (printable) {
+ UI_ThemeColor(TH_TEXT_HI);
+ glRasterPos2i(10, ar->winy-20);
+ BMF_DrawString(G.fonts, printable);
+ }
+
+ if (v3d->localview) {
+ free(printable);
+ }
+}
+
+
+static char *get_cfra_marker_name(Scene *scene)
+{
+ ListBase *markers= &scene->markers;
+ TimeMarker *m1, *m2;
+
+ /* search through markers for match */
+ for (m1=markers->first, m2=markers->last; m1 && m2; m1=m1->next, m2=m2->prev) {
+ if (m1->frame==CFRA)
+ return m1->name;
+
+ if (m1 == m2)
+ break;
+
+ if (m2->frame==CFRA)
+ return m2->name;
+ }
+
+ return NULL;
+}
+
+/* draw info beside axes in bottom left-corner:
+* framenum, object name, bone name (if available), marker name (if available)
+*/
+static void draw_selected_name(Scene *scene, Object *ob, View3D *v3d)
+{
+ char info[256], *markern;
+ short offset=30;
+
+ /* get name of marker on current frame (if available) */
+ markern= get_cfra_marker_name(scene);
+
+ /* check if there is an object */
+ if(ob) {
+ /* name(s) to display depends on type of object */
+ if(ob->type==OB_ARMATURE) {
+ bArmature *arm= ob->data;
+ char *name= NULL;
+
+ /* show name of active bone too (if possible) */
+ if(arm->edbo) {
+ EditBone *ebo;
+ for (ebo=arm->edbo->first; ebo; ebo=ebo->next){
+ if ((ebo->flag & BONE_ACTIVE) && (ebo->layer & arm->layer)) {
+ name= ebo->name;
+ break;
+ }
+ }
+ }
+ else if(ob->pose && (ob->flag & OB_POSEMODE)) {
+ bPoseChannel *pchan;
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if((pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) {
+ name= pchan->name;
+ break;
+ }
+ }
+ }
+ if(name && markern)
+ sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, name, markern);
+ else if(name)
+ sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, name);
+ else
+ sprintf(info, "(%d) %s", CFRA, ob->id.name+2);
+ }
+ else if(ELEM3(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
+ Key *key= NULL;
+ KeyBlock *kb = NULL;
+ char shapes[75];
+
+ /* try to display active shapekey too */
+ shapes[0] = 0;
+ key = ob_get_key(ob);
+ if(key){
+ kb = BLI_findlink(&key->block, ob->shapenr-1);
+ if(kb){
+ sprintf(shapes, ": %s ", kb->name);
+ if(ob->shapeflag == OB_SHAPE_LOCK){
+ sprintf(shapes, "%s (Pinned)",shapes);
+ }
+ }
+ }
+
+ if(markern)
+ sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, shapes, markern);
+ else
+ sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, shapes);
+ }
+ else {
+ /* standard object */
+ if (markern)
+ sprintf(info, "(%d) %s <%s>", CFRA, ob->id.name+2, markern);
+ else
+ sprintf(info, "(%d) %s", CFRA, ob->id.name+2);
+ }
+
+ /* colour depends on whether there is a keyframe */
+ if (id_frame_has_keyframe((ID *)ob, /*frame_to_float(scene, CFRA)*/(float)(CFRA), v3d->keyflags))
+ UI_ThemeColor(TH_VERTEX_SELECT);
+ else
+ UI_ThemeColor(TH_TEXT_HI);
+ }
+ else {
+ /* no object */
+ if (markern)
+ sprintf(info, "(%d) <%s>", CFRA, markern);
+ else
+ sprintf(info, "(%d)", CFRA);
+
+ /* colour is always white */
+ UI_ThemeColor(TH_TEXT_HI);
+ }
+
+ if (U.uiflag & USER_SHOW_ROTVIEWICON)
+ offset = 14 + (U.rvisize * 2);
+
+ glRasterPos2i(offset, 10);
+ BMF_DrawString(G.fonts, info);
+}
+
+static void view3d_get_viewborder_size(Scene *scene, ARegion *ar, float size_r[2])
+{
+ float winmax= MAX2(ar->winx, ar->winy);
+ float aspect= (float) (scene->r.xsch*scene->r.xasp)/(scene->r.ysch*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(Scene *scene, ARegion *ar, View3D *v3d, rctf *viewborder_r)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ float zoomfac, size[2];
+ float dx= 0.0f, dy= 0.0f;
+
+ view3d_get_viewborder_size(scene, ar, size);
+
+ /* magic zoom calculation, no idea what
+ * it signifies, if you find out, tell me! -zr
+ */
+ /* simple, its magic dude!
+ * well, to be honest, this gives a natural feeling zooming
+ * with multiple keypad presses (ton)
+ */
+
+ zoomfac= (M_SQRT2 + rv3d->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*ar->winx - 0.5*size[0];
+ viewborder_r->ymin= 0.5*ar->winy - 0.5*size[1];
+ viewborder_r->xmax= viewborder_r->xmin + size[0];
+ viewborder_r->ymax= viewborder_r->ymin + size[1];
+
+ dx= ar->winx*rv3d->camdx*zoomfac*2.0f;
+ dy= ar->winy*rv3d->camdy*zoomfac*2.0f;
+
+ /* apply offset */
+ viewborder_r->xmin-= dx;
+ viewborder_r->ymin-= dy;
+ viewborder_r->xmax-= dx;
+ viewborder_r->ymax-= dy;
+
+ if(v3d->camera && v3d->camera->type==OB_CAMERA) {
+ Camera *cam= v3d->camera->data;
+ float w = viewborder_r->xmax - viewborder_r->xmin;
+ float h = viewborder_r->ymax - viewborder_r->ymin;
+ float side = MAX2(w, h);
+
+ viewborder_r->xmin+= cam->shiftx*side;
+ viewborder_r->xmax+= cam->shiftx*side;
+ viewborder_r->ymin+= cam->shifty*side;
+ viewborder_r->ymax+= cam->shifty*side;
+ }
+}
+
+void view3d_set_1_to_1_viewborder(Scene *scene, ARegion *ar)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ float size[2];
+ int im_width= (scene->r.size*scene->r.xsch)/100;
+
+ view3d_get_viewborder_size(scene, ar, size);
+
+ rv3d->camzoom= (sqrt(4.0*im_width/size[0]) - M_SQRT2)*50.0;
+ rv3d->camzoom= CLAMPIS(rv3d->camzoom, -30, 300);
+}
+
+
+static void drawviewborder_flymode(ARegion *ar)
+{
+ /* draws 4 edge brackets that frame the safe area where the
+ mouse can move during fly mode without spinning the view */
+ float x1, x2, y1, y2;
+
+ x1= 0.45*(float)ar->winx;
+ y1= 0.45*(float)ar->winy;
+ x2= 0.55*(float)ar->winx;
+ y2= 0.55*(float)ar->winy;
+ cpack(0);
+
+
+ glBegin(GL_LINES);
+ /* bottom left */
+ glVertex2f(x1,y1);
+ glVertex2f(x1,y1+5);
+
+ glVertex2f(x1,y1);
+ glVertex2f(x1+5,y1);
+
+ /* top right */
+ glVertex2f(x2,y2);
+ glVertex2f(x2,y2-5);
+
+ glVertex2f(x2,y2);
+ glVertex2f(x2-5,y2);
+
+ /* top left */
+ glVertex2f(x1,y2);
+ glVertex2f(x1,y2-5);
+
+ glVertex2f(x1,y2);
+ glVertex2f(x1+5,y2);
+
+ /* bottom right */
+ glVertex2f(x2,y1);
+ glVertex2f(x2,y1+5);
+
+ glVertex2f(x2,y1);
+ glVertex2f(x2-5,y1);
+ glEnd();
+}
+
+
+static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
+{
+ extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad); // interface_panel.c
+ float fac, a;
+ float x1, x2, y1, y2;
+ float x3, y3, x4, y4;
+ rctf viewborder;
+ Camera *ca= NULL;
+
+ if(v3d->camera==NULL)
+ return;
+ if(v3d->camera->type==OB_CAMERA)
+ ca = v3d->camera->data;
+
+ calc_viewborder(scene, ar, v3d, &viewborder);
+ x1= viewborder.xmin;
+ y1= viewborder.ymin;
+ x2= viewborder.xmax;
+ y2= viewborder.ymax;
+
+ /* passepartout, specified in camera edit buttons */
+ if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001) {
+ if (ca->passepartalpha == 1.0) {
+ glColor3f(0, 0, 0);
+ } else {
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+ glEnable(GL_BLEND);
+ glColor4f(0, 0, 0, ca->passepartalpha);
+ }
+ if (x1 > 0.0)
+ glRectf(0.0, (float)ar->winy, x1, 0.0);
+ if (x2 < (float)ar->winx)
+ glRectf(x2, (float)ar->winy, (float)ar->winx, 0.0);
+ if (y2 < (float)ar->winy)
+ glRectf(x1, (float)ar->winy, x2, y2);
+ if (y2 > 0.0)
+ glRectf(x1, y1, x2, 0.0);
+
+ glDisable(GL_BLEND);
+ }
+
+ /* edge */
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ setlinestyle(0);
+ UI_ThemeColor(TH_BACK);
+ glRectf(x1, y1, x2, y2);
+
+ setlinestyle(3);
+ UI_ThemeColor(TH_WIRE);
+ glRectf(x1, y1, x2, y2);
+
+ /* camera name - draw in highlighted text color */
+ if (ca && (ca->flag & CAM_SHOWNAME)) {
+ UI_ThemeColor(TH_TEXT_HI);
+ glRasterPos2f(x1, y1-15);
+
+ BMF_DrawString(G.font, v3d->camera->id.name+2);
+ UI_ThemeColor(TH_WIRE);
+ }
+
+
+ /* border */
+ if(scene->r.mode & R_BORDER) {
+
+ cpack(0);
+ x3= x1+ scene->r.border.xmin*(x2-x1);
+ y3= y1+ scene->r.border.ymin*(y2-y1);
+ x4= x1+ scene->r.border.xmax*(x2-x1);
+ y4= y1+ scene->r.border.ymax*(y2-y1);
+
+ cpack(0x4040FF);
+ glRectf(x3, y3, x4, y4);
+ }
+
+ /* safety border */
+ if (ca && (ca->flag & CAM_SHOWTITLESAFE)) {
+ fac= 0.1;
+
+ a= fac*(x2-x1);
+ x1+= a;
+ x2-= a;
+
+ a= fac*(y2-y1);
+ y1+= a;
+ y2-= a;
+
+ UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0);
+
+ uiSetRoundBox(15);
+ gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);
+ }
+
+ setlinestyle(0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+}
+
+/* *********************** backdraw for selection *************** */
+
+void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ struct Base *base;
+
+/*for 2.43 release, don't use glext and just define the constant.
+ this to avoid possibly breaking platforms before release.*/
+#ifndef GL_MULTISAMPLE_ARB
+ #define GL_MULTISAMPLE_ARB 0x809D
+#endif
+
+#ifdef GL_MULTISAMPLE_ARB
+ int m;
+#endif
+
+ if(G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT);
+ else if((G.f & G_TEXTUREPAINT) && scene->toolsettings && (scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE));
+ else if((G.f & G_PARTICLEEDIT) && v3d->drawtype>OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT));
+ else if(scene->obedit && v3d->drawtype>OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT));
+ else {
+ v3d->flag &= ~V3D_NEEDBACKBUFDRAW;
+ return;
+ }
+
+ if( !(v3d->flag & V3D_NEEDBACKBUFDRAW) ) return;
+
+// if(test) {
+// if(qtest()) {
+// addafterqueue(ar->win, BACKBUFDRAW, 1);
+// return;
+// }
+// }
+
+ /* Disable FSAA for backbuffer selection.
+
+ Only works if GL_MULTISAMPLE_ARB is defined by the header
+ file, which is should be for every OS that supports FSAA.*/
+
+#ifdef GL_MULTISAMPLE_ARB
+ m = glIsEnabled(GL_MULTISAMPLE_ARB);
+ if (m) glDisable(GL_MULTISAMPLE_ARB);
+#endif
+
+ if(v3d->drawtype > OB_WIRE) v3d->zbuf= TRUE;
+
+ glDisable(GL_DITHER);
+
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ if(v3d->zbuf) {
+ glEnable(GL_DEPTH_TEST);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+ else {
+ glClear(GL_COLOR_BUFFER_BIT);
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ if(rv3d->rflag & RV3D_CLIPPING)
+ view3d_set_clipping(rv3d);
+
+ G.f |= G_BACKBUFSEL;
+
+ base= (scene->basact);
+ if(base && (base->lay & v3d->lay)) {
+ draw_object_backbufsel(scene, v3d, rv3d, base->object);
+ }
+
+ v3d->flag &= ~V3D_NEEDBACKBUFDRAW;
+
+ G.f &= ~G_BACKBUFSEL;
+ v3d->zbuf= FALSE;
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_DITHER);
+
+ if(rv3d->rflag & RV3D_CLIPPING)
+ view3d_clr_clipping();
+
+#ifdef GL_MULTISAMPLE_ARB
+ if (m) glEnable(GL_MULTISAMPLE_ARB);
+#endif
+
+ /* it is important to end a view in a transform compatible with buttons */
+// persp(PERSP_WIN); // set ortho
+
+}
+
+void view3d_validate_backbuf(ViewContext *vc)
+{
+ if(vc->v3d->flag & V3D_NEEDBACKBUFDRAW)
+ backdrawview3d(vc->scene, vc->ar, vc->v3d);
+}
+
+/* samples a single pixel (copied from vpaint) */
+unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y)
+{
+ unsigned int col;
+
+ if(x >= vc->ar->winx || y >= vc->ar->winy) return 0;
+ x+= vc->ar->winrct.xmin;
+ y+= vc->ar->winrct.ymin;
+
+ view3d_validate_backbuf(vc);
+
+ glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ glReadBuffer(GL_BACK);
+
+ if(ENDIAN_ORDER==B_ENDIAN) SWITCH_INT(col);
+
+ return WM_framebuffer_to_index(col);
+}
+
+/* reads full rect, converts indices */
+ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
+{
+ unsigned int *dr, *rd;
+ struct ImBuf *ibuf, *ibuf1;
+ int a;
+ short xminc, yminc, xmaxc, ymaxc, xs, ys;
+
+ /* clip */
+ if(xmin<0) xminc= 0; else xminc= xmin;
+ if(xmax >= vc->ar->winx) xmaxc= vc->ar->winx-1; else xmaxc= xmax;
+ if(xminc > xmaxc) return NULL;
+
+ if(ymin<0) yminc= 0; else yminc= ymin;
+ if(ymax >= vc->ar->winy) ymaxc= vc->ar->winy-1; else ymaxc= ymax;
+ if(yminc > ymaxc) return NULL;
+
+ ibuf= IMB_allocImBuf((xmaxc-xminc+1), (ymaxc-yminc+1), 32, IB_rect,0);
+
+ view3d_validate_backbuf(vc);
+
+ glReadPixels(vc->ar->winrct.xmin+xminc, vc->ar->winrct.ymin+yminc, (xmaxc-xminc+1), (ymaxc-yminc+1), GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ glReadBuffer(GL_BACK);
+
+ if(ENDIAN_ORDER==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
+
+ a= (xmaxc-xminc+1)*(ymaxc-yminc+1);
+ dr= ibuf->rect;
+ while(a--) {
+ if(*dr) *dr= WM_framebuffer_to_index(*dr);
+ dr++;
+ }
+
+ /* put clipped result back, if needed */
+ if(xminc==xmin && xmaxc==xmax && yminc==ymin && ymaxc==ymax)
+ return ibuf;
+
+ ibuf1= IMB_allocImBuf( (xmax-xmin+1),(ymax-ymin+1),32,IB_rect,0);
+ rd= ibuf->rect;
+ dr= ibuf1->rect;
+
+ for(ys= ymin; ys<=ymax; ys++) {
+ for(xs= xmin; xs<=xmax; xs++, dr++) {
+ if( xs>=xminc && xs<=xmaxc && ys>=yminc && ys<=ymaxc) {
+ *dr= *rd;
+ rd++;
+ }
+ }
+ }
+ IMB_freeImBuf(ibuf);
+ return ibuf1;
+}
+
+/* smart function to sample a rect spiralling outside, nice for backbuf selection */
+unsigned int view3d_sample_backbuf_rect(ViewContext *vc, short mval[2], int size,
+ unsigned int min, unsigned int max, int *dist, short strict,
+ void *handle, unsigned int (*indextest)(void *handle, unsigned int index))
+{
+ struct ImBuf *buf;
+ unsigned int *bufmin, *bufmax, *tbuf;
+ int minx, miny;
+ int a, b, rc, nr, amount, dirvec[4][2];
+ int distance=0;
+ unsigned int index = 0;
+ short indexok = 0;
+
+ amount= (size-1)/2;
+
+ minx = mval[0]-(amount+1);
+ miny = mval[1]-(amount+1);
+ buf = view3d_read_backbuf(vc, minx, miny, minx+size-1, miny+size-1);
+ if (!buf) return 0;
+
+ 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->rect;
+ tbuf = buf->rect;
+ bufmax = buf->rect + size*size;
+ tbuf+= amount*size+ amount;
+
+ for(nr=1; nr<=size; nr++) {
+
+ for(a=0; a<2; a++) {
+ for(b=0; b<nr; b++, distance++) {
+ if (*tbuf && *tbuf>=min && *tbuf<max) { //we got a hit
+ if(strict){
+ indexok = indextest(handle, *tbuf - min+1);
+ if(indexok){
+ *dist= (short) sqrt( (float)distance );
+ index = *tbuf - min+1;
+ goto exit;
+ }
+ }
+ else{
+ *dist= (short) sqrt( (float)distance ); // XXX, this distance is wrong -
+ index = *tbuf - min+1; // messy yah, but indices start at 1
+ goto exit;
+ }
+ }
+
+ tbuf+= (dirvec[rc][0]+dirvec[rc][1]);
+
+ if(tbuf<bufmin || tbuf>=bufmax) {
+ goto exit;
+ }
+ }
+ rc++;
+ rc &= 3;
+ }
+ }
+
+exit:
+ IMB_freeImBuf(buf);
+ return index;
+}
+
+
+/* ************************************************************* */
+
+static void draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ BGpic *bgpic;
+ Image *ima;
+ ImBuf *ibuf= NULL;
+ float vec[4], fac, asp, zoomx, zoomy;
+ float x1, y1, x2, y2, cx, cy;
+
+ bgpic= v3d->bgpic;
+ if(bgpic==NULL) return;
+
+ ima= bgpic->ima;
+
+ if(ima)
+ ibuf= BKE_image_get_ibuf(ima, &bgpic->iuser);
+ if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL) )
+ return;
+ if(ibuf->channels!=4)
+ return;
+ if(ibuf->rect==NULL)
+ IMB_rect_from_float(ibuf);
+
+ if(rv3d->persp==2) {
+ rctf vb;
+
+ calc_viewborder(scene, ar, v3d, &vb);
+
+ x1= vb.xmin;
+ y1= vb.ymin;
+ x2= vb.xmax;
+ y2= vb.ymax;
+ }
+ else {
+ float sco[2];
+
+ /* calc window coord */
+ initgrabz(rv3d, 0.0, 0.0, 0.0);
+ window_to_3d_delta(ar, vec, 1, 0);
+ fac= MAX3( fabs(vec[0]), fabs(vec[1]), fabs(vec[1]) );
+ fac= 1.0/fac;
+
+ asp= ( (float)ibuf->y)/(float)ibuf->x;
+
+ vec[0] = vec[1] = vec[2] = 0.0;
+ view3d_project_float(ar, vec, sco, rv3d->persmat);
+ cx = sco[0];
+ cy = sco[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);
+ }
+
+ /* complete clip? */
+
+ if(x2 < 0 ) return;
+ if(y2 < 0 ) return;
+ if(x1 > ar->winx ) return;
+ if(y1 > ar->winy ) return;
+
+ zoomx= (x2-x1)/ibuf->x;
+ zoomy= (y2-y1)/ibuf->y;
+
+ /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */
+ if(zoomx < 1.0f || zoomy < 1.0f) {
+ float tzoom= MIN2(zoomx, zoomy);
+ int mip= 0;
+
+ if(ibuf->mipmap[0]==NULL)
+ IMB_makemipmap(ibuf, 0);
+
+ while(tzoom < 1.0f && mip<8 && ibuf->mipmap[mip]) {
+ tzoom*= 2.0f;
+ zoomx*= 2.0f;
+ zoomy*= 2.0f;
+ mip++;
+ }
+ if(mip>0)
+ ibuf= ibuf->mipmap[mip-1];
+ }
+
+ if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+
+ glaDefine2DArea(&ar->winrct);
+
+ glEnable(GL_BLEND);
+
+ glPixelZoom(zoomx, zoomy);
+ glColor4f(1.0, 1.0, 1.0, 1.0-bgpic->blend);
+ glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect);
+
+ glPixelZoom(1.0, 1.0);
+ glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ glDisable(GL_BLEND);
+ if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
+}
+
+/* ****************** View3d afterdraw *************** */
+
+typedef struct View3DAfter {
+ struct View3DAfter *next, *prev;
+ struct Base *base;
+ int type, flag;
+} View3DAfter;
+
+/* temp storage of Objects that need to be drawn as last */
+void add_view3d_after(View3D *v3d, Base *base, int type, int flag)
+{
+ View3DAfter *v3da= MEM_callocN(sizeof(View3DAfter), "View 3d after");
+
+ BLI_addtail(&v3d->afterdraw, v3da);
+ v3da->base= base;
+ v3da->type= type;
+ v3da->flag= flag;
+}
+
+/* clears zbuffer and draws it over */
+static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, int clear)
+{
+ View3DAfter *v3da, *next;
+ int doit= 0;
+
+ for(v3da= v3d->afterdraw.first; v3da; v3da= v3da->next)
+ if(v3da->type==V3D_XRAY) doit= 1;
+
+ if(doit) {
+ if(clear && v3d->zbuf) glClear(GL_DEPTH_BUFFER_BIT);
+ v3d->xray= TRUE;
+
+ for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
+ next= v3da->next;
+ if(v3da->type==V3D_XRAY) {
+ draw_object(scene, ar, v3d, v3da->base, v3da->flag);
+ BLI_remlink(&v3d->afterdraw, v3da);
+ MEM_freeN(v3da);
+ }
+ }
+ v3d->xray= FALSE;
+ }
+}
+
+/* disables write in zbuffer and draws it over */
+static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d)
+{
+ View3DAfter *v3da, *next;
+
+ glDepthMask(0);
+ v3d->transp= TRUE;
+
+ for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
+ next= v3da->next;
+ if(v3da->type==V3D_TRANSP) {
+ draw_object(scene, ar, v3d, v3da->base, v3da->flag);
+ BLI_remlink(&v3d->afterdraw, v3da);
+ MEM_freeN(v3da);
+ }
+ }
+ v3d->transp= FALSE;
+
+ glDepthMask(1);
+
+}
+
+/* *********************** */
+
+/*
+ In most cases call draw_dupli_objects,
+ draw_dupli_objects_color was added because when drawing set dupli's
+ we need to force the color
+ */
+static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int color)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ ListBase *lb;
+ DupliObject *dob;
+ Base tbase;
+ BoundBox *bb= NULL;
+ GLuint displist=0;
+ short transflag, use_displist= -1; /* -1 is initialize */
+ char dt, dtx;
+
+ if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
+
+ tbase.flag= OB_FROMDUPLI|base->flag;
+ lb= object_duplilist(scene, base->object);
+
+ for(dob= lb->first; dob; dob= dob->next) {
+ if(dob->no_draw);
+ else {
+ tbase.object= dob->ob;
+
+ /* extra service: draw the duplicator in drawtype of parent */
+ /* MIN2 for the drawtype to allow bounding box objects in groups for lods */
+ dt= tbase.object->dt; tbase.object->dt= MIN2(tbase.object->dt, base->object->dt);
+ dtx= tbase.object->dtx; tbase.object->dtx= base->object->dtx;
+
+ /* negative scale flag has to propagate */
+ transflag= tbase.object->transflag;
+ if(base->object->transflag & OB_NEG_SCALE)
+ tbase.object->transflag ^= OB_NEG_SCALE;
+
+ UI_ThemeColorBlend(color, TH_BACK, 0.5);
+
+ /* generate displist, test for new object */
+ if(use_displist==1 && dob->prev && dob->prev->ob!=dob->ob) {
+ use_displist= -1;
+ glDeleteLists(displist, 1);
+ }
+ /* generate displist */
+ if(use_displist == -1) {
+
+ /* lamp drawing messes with matrices, could be handled smarter... but this works */
+ if(dob->ob->type==OB_LAMP || dob->type==OB_DUPLIGROUP)
+ use_displist= 0;
+ else {
+ /* disable boundbox check for list creation */
+ object_boundbox_flag(dob->ob, OB_BB_DISABLED, 1);
+ /* need this for next part of code */
+ bb= object_get_boundbox(dob->ob);
+
+ Mat4One(dob->ob->obmat); /* obmat gets restored */
+
+ displist= glGenLists(1);
+ glNewList(displist, GL_COMPILE);
+ draw_object(scene, ar, v3d, &tbase, DRAW_CONSTCOLOR);
+ glEndList();
+
+ use_displist= 1;
+ object_boundbox_flag(dob->ob, OB_BB_DISABLED, 0);
+ }
+ }
+ if(use_displist) {
+ wmMultMatrix(dob->mat);
+ if(boundbox_clip(rv3d, dob->mat, bb))
+ glCallList(displist);
+ wmLoadMatrix(rv3d->viewmat);
+ }
+ else {
+ Mat4CpyMat4(dob->ob->obmat, dob->mat);
+ draw_object(scene, ar, v3d, &tbase, DRAW_CONSTCOLOR);
+ }
+
+ tbase.object->dt= dt;
+ tbase.object->dtx= dtx;
+ tbase.object->transflag= transflag;
+ }
+ }
+
+ /* Transp afterdraw disabled, afterdraw only stores base pointers, and duplis can be same obj */
+
+ free_object_duplilist(lb); /* does restore */
+
+ if(use_displist)
+ glDeleteLists(displist, 1);
+}
+
+static void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base)
+{
+ /* define the color here so draw_dupli_objects_color can be called
+ * from the set loop */
+
+ int color= (base->flag & SELECT)?TH_SELECT:TH_WIRE;
+ /* debug */
+ if(base->object->dup_group && base->object->dup_group->id.us<1)
+ color= TH_REDALERT;
+
+ draw_dupli_objects_color(scene, ar, v3d, base, color);
+}
+
+
+void view3d_update_depths(ARegion *ar, View3D *v3d)
+{
+ RegionView3D *rv3d= ar->regiondata;
+
+ /* Create storage for, and, if necessary, copy depth buffer */
+ if(!rv3d->depths) rv3d->depths= MEM_callocN(sizeof(ViewDepths),"ViewDepths");
+ if(rv3d->depths) {
+ ViewDepths *d= rv3d->depths;
+ if(d->w != ar->winx ||
+ d->h != ar->winy ||
+ !d->depths) {
+ d->w= ar->winx;
+ d->h= ar->winy;
+ if(d->depths)
+ MEM_freeN(d->depths);
+ d->depths= MEM_mallocN(sizeof(float)*d->w*d->h,"View depths");
+ d->damaged= 1;
+ }
+
+ if(d->damaged) {
+ glReadPixels(ar->winrct.xmin,ar->winrct.ymin,d->w,d->h,
+ GL_DEPTH_COMPONENT,GL_FLOAT, d->depths);
+
+ glGetDoublev(GL_DEPTH_RANGE,d->depth_range);
+
+ d->damaged= 0;
+ }
+ }
+}
+
+/* Enable sculpting in wireframe mode by drawing sculpt object only to the depth buffer */
+static void draw_sculpt_depths(Scene *scene, ARegion *ar, View3D *v3d)
+{
+ Object *ob = OBACT;
+
+ int dt= MIN2(v3d->drawtype, ob->dt);
+ if(v3d->zbuf==0 && dt>OB_WIRE)
+ dt= OB_WIRE;
+ if(dt == OB_WIRE) {
+ GLboolean depth_on;
+ int orig_vdt = v3d->drawtype;
+ int orig_zbuf = v3d->zbuf;
+ int orig_odt = ob->dt;
+
+ glGetBooleanv(GL_DEPTH_TEST, &depth_on);
+ v3d->drawtype = ob->dt = OB_SOLID;
+ v3d->zbuf = 1;
+
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ glEnable(GL_DEPTH_TEST);
+ draw_object(scene, ar, v3d, BASACT, 0);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ if(!depth_on)
+ glDisable(GL_DEPTH_TEST);
+
+ v3d->drawtype = orig_vdt;
+ v3d->zbuf = orig_zbuf;
+ ob->dt = orig_odt;
+ }
+}
+
+void draw_depth(Scene *scene, ARegion *ar, View3D *v3d, int (* func)(void *))
+{
+ RegionView3D *rv3d= ar->regiondata;
+ Base *base;
+ Scene *sce;
+ short zbuf, flag;
+ float glalphaclip;
+ /* temp set drawtype to solid */
+
+ /* Setting these temporarily is not nice */
+ zbuf = v3d->zbuf;
+ flag = v3d->flag;
+ glalphaclip = U.glalphaclip;
+
+ U.glalphaclip = 0.5; /* not that nice but means we wont zoom into billboards */
+ v3d->flag &= ~V3D_SELECT_OUTLINE;
+
+ setwinmatrixview3d(ar, v3d, NULL); /* 0= no pick rect */
+ setviewmatrixview3d(scene, v3d, rv3d); /* note: calls where_is_object for camera... */
+
+ Mat4MulMat4(rv3d->persmat, rv3d->viewmat, rv3d->winmat);
+ Mat4Invert(rv3d->persinv, rv3d->persmat);
+ Mat4Invert(rv3d->viewinv, rv3d->viewmat);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ wmLoadMatrix(rv3d->viewmat);
+// persp(PERSP_STORE); // store correct view for persp(PERSP_VIEW) calls
+
+ if(rv3d->rflag & RV3D_CLIPPING) {
+ view3d_set_clipping(rv3d);
+ }
+
+ v3d->zbuf= TRUE;
+ glEnable(GL_DEPTH_TEST);
+
+ /* draw set first */
+ if(scene->set) {
+ for(SETLOOPER(scene->set, base)) {
+ if(v3d->lay & base->lay) {
+ if (func == NULL || func(base)) {
+ draw_object(scene, ar, v3d, base, 0);
+ if(base->object->transflag & OB_DUPLI) {
+ draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE);
+ }
+ }
+ }
+ }
+ }
+
+ for(base= scene->base.first; base; base= base->next) {
+ if(v3d->lay & base->lay) {
+ if (func == NULL || func(base)) {
+ /* dupli drawing */
+ if(base->object->transflag & OB_DUPLI) {
+ draw_dupli_objects(scene, ar, v3d, base);
+ }
+ draw_object(scene, ar, v3d, base, 0);
+ }
+ }
+ }
+
+ /* this isnt that nice, draw xray objects as if they are normal */
+ if (v3d->afterdraw.first) {
+ View3DAfter *v3da, *next;
+ int num = 0;
+ v3d->xray= TRUE;
+
+ glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */
+ for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
+ next= v3da->next;
+ if(v3da->type==V3D_XRAY) {
+ draw_object(scene, ar, v3d, v3da->base, 0);
+ num++;
+ }
+ /* dont remove this time */
+ }
+ v3d->xray= FALSE;
+
+ glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */
+ for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
+ next= v3da->next;
+ if(v3da->type==V3D_XRAY) {
+ v3d->xray= TRUE; v3d->transp= FALSE;
+ } else if (v3da->type==V3D_TRANSP) {
+ v3d->xray= FALSE; v3d->transp= TRUE;
+ }
+
+ draw_object(scene, ar, v3d, v3da->base, 0); /* Draw Xray or Transp objects normally */
+ BLI_remlink(&v3d->afterdraw, v3da);
+ MEM_freeN(v3da);
+ }
+ v3d->xray= FALSE;
+ v3d->transp= FALSE;
+ }
+
+ v3d->zbuf = zbuf;
+ U.glalphaclip = glalphaclip;
+ v3d->flag = flag;
+}
+
+typedef struct View3DShadow {
+ struct View3DShadow *next, *prev;
+ GPULamp *lamp;
+} View3DShadow;
+
+static void gpu_render_lamp_update(Scene *scene, View3D *v3d, Object *ob, Object *par, float obmat[][4], ListBase *shadows)
+{
+ GPULamp *lamp;
+ View3DShadow *shadow;
+
+ lamp = GPU_lamp_from_blender(scene, ob, par);
+
+ if(lamp) {
+ GPU_lamp_update(lamp, ob->lay, obmat);
+
+ if((ob->lay & v3d->lay) && GPU_lamp_has_shadow_buffer(lamp)) {
+ shadow= MEM_callocN(sizeof(View3DShadow), "View3DShadow");
+ shadow->lamp = lamp;
+ BLI_addtail(shadows, shadow);
+ }
+ }
+}
+
+static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
+{
+ ListBase shadows;
+ View3DShadow *shadow;
+ Scene *sce;
+ Base *base;
+ Object *ob;
+
+ shadows.first= shadows.last= NULL;
+
+ /* update lamp transform and gather shadow lamps */
+ for(SETLOOPER(scene, base)) {
+ ob= base->object;
+
+ if(ob->type == OB_LAMP)
+ gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, &shadows);
+
+ if (ob->transflag & OB_DUPLI) {
+ DupliObject *dob;
+ ListBase *lb = object_duplilist(scene, ob);
+
+ for(dob=lb->first; dob; dob=dob->next)
+ if(dob->ob->type==OB_LAMP)
+ gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, &shadows);
+
+ free_object_duplilist(lb);
+ }
+ }
+
+ /* render shadows after updating all lamps, nested object_duplilist
+ * don't work correct since it's replacing object matrices */
+ for(shadow=shadows.first; shadow; shadow=shadow->next) {
+ /* this needs to be done better .. */
+ float viewmat[4][4], winmat[4][4];
+ int drawtype, lay, winsize, flag2;
+
+ drawtype= v3d->drawtype;
+ lay= v3d->lay;
+ flag2= v3d->flag2 & V3D_SOLID_TEX;
+
+ v3d->drawtype = OB_SOLID;
+ v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp);
+ v3d->flag2 &= ~V3D_SOLID_TEX;
+
+ GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat);
+// XXX drawview3d_render(v3d, viewmat, winsize, winsize, winmat, 1);
+ GPU_lamp_shadow_buffer_unbind(shadow->lamp);
+
+ v3d->drawtype= drawtype;
+ v3d->lay= lay;
+ v3d->flag2 |= flag2;
+ }
+
+ BLI_freelistN(&shadows);
+}
+
+/* *********************** customdata **************** */
+
+/* goes over all modes and view3d settings */
+static CustomDataMask get_viewedit_datamask(bScreen *screen)
+{
+ CustomDataMask mask = CD_MASK_BAREMESH;
+ ScrArea *sa;
+
+ /* check if we need tfaces & mcols due to face select or texture paint */
+ if(FACESEL_PAINT_TEST || G.f & G_TEXTUREPAINT)
+ mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
+
+ /* check if we need tfaces & mcols due to view mode */
+ for(sa = screen->areabase.first; sa; sa = sa->next) {
+ if(sa->spacetype == SPACE_VIEW3D) {
+ View3D *view = sa->spacedata.first;
+ if(view->drawtype == OB_SHADED) {
+ /* this includes normals for mesh_create_shadedColors */
+ mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO;
+ }
+ if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) {
+ mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
+
+ if((G.fileflags & G_FILE_GAME_MAT) &&
+ (G.fileflags & G_FILE_GAME_MAT_GLSL)) {
+ mask |= CD_MASK_ORCO;
+ }
+ }
+ }
+ }
+
+ /* check if we need mcols due to vertex paint or weightpaint */
+ if(G.f & G_VERTEXPAINT)
+ mask |= CD_MASK_MCOL;
+ if(G.f & G_WEIGHTPAINT)
+ mask |= CD_MASK_WEIGHT_MCOL;
+
+ if(G.f & G_SCULPTMODE)
+ mask |= CD_MASK_MDISPS;
+
+ return mask;
+}
+
+void view3d_main_area_draw(const bContext *C, ARegion *ar)
+{
+ Scene *scene= CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ Scene *sce;
+ Base *base;
+ Object *ob;
+ int retopo= 0, sculptparticle= 0;
+ Object *obact = OBACT;
+
+ /* from now on all object derived meshes check this */
+ v3d->customdata_mask= get_viewedit_datamask(CTX_wm_screen(C));
+
+ /* shadow buffers, before we setup matrices */
+ if(draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
+ gpu_update_lamps_shadows(scene, v3d);
+
+ setwinmatrixview3d(ar, v3d, NULL); /* 0= no pick rect */
+ setviewmatrixview3d(scene, v3d, rv3d); /* note: calls where_is_object for camera... */
+
+ Mat4MulMat4(rv3d->persmat, rv3d->viewmat, rv3d->winmat);
+ Mat4Invert(rv3d->persinv, rv3d->persmat);
+ Mat4Invert(rv3d->viewinv, rv3d->viewmat);
+
+ /* calculate pixelsize factor once, is used for lamps and obcenters */
+ {
+ float len1, len2, vec[3];
+
+ VECCOPY(vec, rv3d->persinv[0]);
+ len1= Normalize(vec);
+ VECCOPY(vec, rv3d->persinv[1]);
+ len2= Normalize(vec);
+
+ rv3d->pixsize= 2.0f*(len1>len2?len1:len2);
+
+ /* correct for window size */
+ if(ar->winx > ar->winy) rv3d->pixsize/= (float)ar->winx;
+ else rv3d->pixsize/= (float)ar->winy;
+ }
+
+ if(v3d->drawtype > OB_WIRE) {
+ float col[3];
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+
+ glLoadIdentity();
+ }
+ else {
+ float col[3];
+ UI_GetThemeColor3fv(TH_BACK, col);
+ glClearColor(col[0], col[1], col[2], 0.0);
+ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+ }
+
+ wmLoadMatrix(rv3d->viewmat);
+
+ if(rv3d->rflag & RV3D_CLIPPING)
+ view3d_draw_clipping(rv3d);
+
+ /* set zbuffer after we draw clipping region */
+ if(v3d->drawtype > OB_WIRE) {
+ v3d->zbuf= TRUE;
+ glEnable(GL_DEPTH_TEST);
+ }
+
+ // needs to be done always, gridview is adjusted in drawgrid() now
+ v3d->gridview= v3d->grid;
+
+ if(rv3d->view==0 || rv3d->persp!=0) {
+ drawfloor(scene, v3d);
+ if(rv3d->persp==2) {
+ if(scene->world) {
+ if(scene->world->mode & WO_STARS) {
+ RE_make_stars(NULL, scene, star_stuff_init_func, star_stuff_vertex_func,
+ star_stuff_term_func);
+ }
+ }
+ if(v3d->flag & V3D_DISPBGPIC) draw_bgpic(scene, ar, v3d);
+ }
+ }
+ else {
+ ED_region_pixelspace(ar);
+ drawgrid(ar, v3d);
+ /* XXX make function? replaces persp(1) */
+ glMatrixMode(GL_PROJECTION);
+ wmLoadMatrix(rv3d->winmat);
+ glMatrixMode(GL_MODELVIEW);
+ wmLoadMatrix(rv3d->viewmat);
+
+ if(v3d->flag & V3D_DISPBGPIC) {
+ draw_bgpic(scene, ar, v3d);
+ }
+ }
+
+ if(rv3d->rflag & RV3D_CLIPPING)
+ view3d_set_clipping(rv3d);
+
+ /* draw set first */
+ if(scene->set) {
+ for(SETLOOPER(scene->set, base)) {
+
+ if(v3d->lay & base->lay) {
+
+ UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
+ draw_object(scene, ar, v3d, base, DRAW_CONSTCOLOR|DRAW_SCENESET);
+
+ if(base->object->transflag & OB_DUPLI) {
+ draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE);
+ }
+ }
+ }
+
+ /* Transp and X-ray afterdraw stuff for sets is done later */
+ }
+
+ /* extra service in layerbuttons, showing used layers */
+ v3d->lay_used = 0;
+
+ /* then draw not selected and the duplis, but skip editmode object */
+ for(base= scene->base.first; base; base= base->next) {
+ v3d->lay_used |= base->lay;
+
+ if(v3d->lay & base->lay) {
+
+ /* dupli drawing */
+ if(base->object->transflag & OB_DUPLI) {
+ draw_dupli_objects(scene, ar, v3d, base);
+ }
+ if((base->flag & SELECT)==0) {
+ if(base->object!=scene->obedit)
+ draw_object(scene, ar, v3d, base, 0);
+ }
+ }
+ }
+
+// retopo= retopo_mesh_check() || retopo_curve_check();
+ sculptparticle= (G.f & (G_SCULPTMODE|G_PARTICLEEDIT)) && !scene->obedit;
+ if(retopo)
+ view3d_update_depths(ar, v3d);
+
+ /* draw selected and editmode */
+ for(base= scene->base.first; base; base= base->next) {
+ if(v3d->lay & base->lay) {
+ if (base->object==scene->obedit || ( base->flag & SELECT) )
+ draw_object(scene, ar, v3d, base, 0);
+ }
+ }
+
+ if(!retopo && sculptparticle && !(obact && (obact->dtx & OB_DRAWXRAY))) {
+ if(G.f & G_SCULPTMODE)
+ draw_sculpt_depths(scene, ar, v3d);
+ view3d_update_depths(ar, v3d);
+ }
+
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST);
+
+// REEB_draw();
+
+// if(scene->radio) RAD_drawall(v3d->drawtype>=OB_SOLID);
+
+ /* Transp and X-ray afterdraw stuff */
+ view3d_draw_transp(scene, ar, v3d);
+ view3d_draw_xray(scene, ar, v3d, 1); // clears zbuffer if it is used!
+
+ if(!retopo && sculptparticle && (obact && (OBACT->dtx & OB_DRAWXRAY))) {
+ if(G.f & G_SCULPTMODE)
+ draw_sculpt_depths(scene, ar, v3d);
+ view3d_update_depths(ar, v3d);
+ }
+
+ if(rv3d->rflag & RV3D_CLIPPING)
+ view3d_clr_clipping();
+
+// BIF_draw_manipulator(ar);
+
+ if(v3d->zbuf) {
+ v3d->zbuf= FALSE;
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ /* draw grease-pencil stuff */
+// if (v3d->flag2 & V3D_DISPGP)
+// draw_gpencil_3dview(ar, 1);
+
+ BDR_drawSketch(C);
+
+ ED_region_pixelspace(ar);
+
+ /* Draw Sculpt Mode brush XXX (removed) */
+
+// retopo_paint_view_update(v3d);
+// retopo_draw_paint_lines();
+
+ /* Draw particle edit brush XXX (removed) */
+
+ if(rv3d->persp>1) drawviewborder(scene, ar, v3d);
+ if(rv3d->rflag & RV3D_FLYMODE) drawviewborder_flymode(ar);
+
+ /* draw grease-pencil stuff */
+// if (v3d->flag2 & V3D_DISPGP)
+// draw_gpencil_3dview(ar, 0);
+
+ drawcursor(scene, ar, v3d);
+
+ if(U.uiflag & USER_SHOW_ROTVIEWICON)
+ draw_view_axis(rv3d);
+ else
+ draw_view_icon(rv3d);
+
+ /* XXX removed viewport fps */
+ if(U.uiflag & USER_SHOW_VIEWPORTNAME) {
+ draw_viewport_name(ar, v3d);
+ }
+
+ ob= OBACT;
+ if(U.uiflag & USER_DRAWVIEWINFO)
+ draw_selected_name(scene, ob, v3d);
+
+ /* XXX here was the blockhandlers for floating panels */
+
+ if(G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT || G.f & G_TEXTUREPAINT) {
+ v3d->flag |= V3D_NEEDBACKBUFDRAW;
+ // XXX addafterqueue(ar->win, BACKBUFDRAW, 1);
+ }
+
+ if((G.f & G_PARTICLEEDIT) && v3d->drawtype>OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT)) {
+ v3d->flag |= V3D_NEEDBACKBUFDRAW;
+ // XXX addafterqueue(ar->win, BACKBUFDRAW, 1);
+ }
+
+ // test for backbuf select
+ if(scene->obedit && v3d->drawtype>OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT)) {
+
+ v3d->flag |= V3D_NEEDBACKBUFDRAW;
+ // XXX if(afterqtest(ar->win, BACKBUFDRAW)==0) {
+ // addafterqueue(ar->win, BACKBUFDRAW, 1);
+ //}
+ }
+
+#ifndef DISABLE_PYTHON
+ /* XXX here was scriptlink */
+#endif
+}
+
+
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
new file mode 100644
index 00000000000..b4b35be3ef3
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -0,0 +1,2330 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <float.h>
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_action.h"
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_object.h"
+#include "BKE_global.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "RE_pipeline.h" // make_stars
+
+#include "BIF_gl.h"
+#include "BIF_retopo.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_particle.h"
+#include "ED_space_api.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "PIL_time.h" /* smoothview */
+
+#include "view3d_intern.h" // own include
+
+/* ********************** view3d_edit: view manipulations ********************* */
+
+/* ********************* box view support ***************** */
+
+static void view3d_boxview_clip(ScrArea *sa)
+{
+ ARegion *ar;
+ BoundBox *bb = MEM_callocN(sizeof(BoundBox), "clipbb");
+ float clip[6][4];
+ float x1= 0.0f, y1= 0.0f, z1= 0.0f, ofs[3];
+ int val;
+
+ /* create bounding box */
+ for(ar= sa->regionbase.first; ar; ar= ar->next) {
+ if(ar->regiontype==RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d= ar->regiondata;
+
+ if(rv3d->viewlock & RV3D_BOXCLIP) {
+ if(ELEM(rv3d->view, V3D_VIEW_TOP, V3D_VIEW_BOTTOM)) {
+ if(ar->winx>ar->winy) x1= rv3d->dist;
+ else x1= ar->winx*rv3d->dist/ar->winy;
+
+ if(ar->winx>ar->winy) y1= ar->winy*rv3d->dist/ar->winx;
+ else y1= rv3d->dist;
+
+ ofs[0]= rv3d->ofs[0];
+ ofs[1]= rv3d->ofs[1];
+ }
+ else if(ELEM(rv3d->view, V3D_VIEW_FRONT, V3D_VIEW_BACK)) {
+ ofs[2]= rv3d->ofs[2];
+
+ if(ar->winx>ar->winy) z1= ar->winy*rv3d->dist/ar->winx;
+ else z1= rv3d->dist;
+ }
+ }
+ }
+ }
+
+ for(val=0; val<8; val++) {
+ if(ELEM4(val, 0, 3, 4, 7))
+ bb->vec[val][0]= -x1 - ofs[0];
+ else
+ bb->vec[val][0]= x1 - ofs[0];
+
+ if(ELEM4(val, 0, 1, 4, 5))
+ bb->vec[val][1]= -y1 - ofs[1];
+ else
+ bb->vec[val][1]= y1 - ofs[1];
+
+ if(val > 3)
+ bb->vec[val][2]= -z1 - ofs[2];
+ else
+ bb->vec[val][2]= z1 - ofs[2];
+ }
+
+ /* normals for plane equations */
+ CalcNormFloat(bb->vec[0], bb->vec[1], bb->vec[4], clip[0]);
+ CalcNormFloat(bb->vec[1], bb->vec[2], bb->vec[5], clip[1]);
+ CalcNormFloat(bb->vec[2], bb->vec[3], bb->vec[6], clip[2]);
+ CalcNormFloat(bb->vec[3], bb->vec[0], bb->vec[7], clip[3]);
+ CalcNormFloat(bb->vec[4], bb->vec[5], bb->vec[6], clip[4]);
+ CalcNormFloat(bb->vec[0], bb->vec[2], bb->vec[1], clip[5]);
+
+ /* then plane equations */
+ for(val=0; val<5; val++) {
+ clip[val][3]= - clip[val][0]*bb->vec[val][0] - clip[val][1]*bb->vec[val][1] - clip[val][2]*bb->vec[val][2];
+ }
+ clip[5][3]= - clip[5][0]*bb->vec[0][0] - clip[5][1]*bb->vec[0][1] - clip[5][2]*bb->vec[0][2];
+
+ /* create bounding box */
+ for(ar= sa->regionbase.first; ar; ar= ar->next) {
+ if(ar->regiontype==RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d= ar->regiondata;
+
+ if(rv3d->viewlock & RV3D_BOXCLIP) {
+ rv3d->rflag |= RV3D_CLIPPING;
+ memcpy(rv3d->clip, clip, sizeof(clip));
+ }
+ }
+ }
+ MEM_freeN(bb);
+}
+
+/* sync center/zoom view of region to others, for view transforms */
+static void view3d_boxview_sync(ScrArea *sa, ARegion *ar)
+{
+ ARegion *artest;
+ RegionView3D *rv3d= ar->regiondata;
+
+ for(artest= sa->regionbase.first; artest; artest= artest->next) {
+ if(artest!=ar && artest->regiontype==RGN_TYPE_WINDOW) {
+ RegionView3D *rv3dtest= artest->regiondata;
+
+ if(rv3dtest->viewlock) {
+ rv3dtest->dist= rv3d->dist;
+
+ if( ELEM(rv3d->view, V3D_VIEW_TOP, V3D_VIEW_BOTTOM) ) {
+ if( ELEM(rv3dtest->view, V3D_VIEW_FRONT, V3D_VIEW_BACK))
+ rv3dtest->ofs[0]= rv3d->ofs[0];
+ else if( ELEM(rv3dtest->view, V3D_VIEW_RIGHT, V3D_VIEW_LEFT))
+ rv3dtest->ofs[1]= rv3d->ofs[1];
+ }
+ else if( ELEM(rv3d->view, V3D_VIEW_FRONT, V3D_VIEW_BACK) ) {
+ if( ELEM(rv3dtest->view, V3D_VIEW_TOP, V3D_VIEW_BOTTOM))
+ rv3dtest->ofs[0]= rv3d->ofs[0];
+ else if( ELEM(rv3dtest->view, V3D_VIEW_RIGHT, V3D_VIEW_LEFT))
+ rv3dtest->ofs[2]= rv3d->ofs[2];
+ }
+ else if( ELEM(rv3d->view, V3D_VIEW_RIGHT, V3D_VIEW_LEFT) ) {
+ if( ELEM(rv3dtest->view, V3D_VIEW_TOP, V3D_VIEW_BOTTOM))
+ rv3dtest->ofs[1]= rv3d->ofs[1];
+ if( ELEM(rv3dtest->view, V3D_VIEW_FRONT, V3D_VIEW_BACK))
+ rv3dtest->ofs[2]= rv3d->ofs[2];
+ }
+
+ ED_region_tag_redraw(artest);
+ }
+ }
+ }
+ view3d_boxview_clip(sa);
+}
+
+/* for home, center etc */
+void view3d_boxview_copy(ScrArea *sa, ARegion *ar)
+{
+ ARegion *artest;
+ RegionView3D *rv3d= ar->regiondata;
+
+ for(artest= sa->regionbase.first; artest; artest= artest->next) {
+ if(artest!=ar && artest->regiontype==RGN_TYPE_WINDOW) {
+ RegionView3D *rv3dtest= artest->regiondata;
+
+ if(rv3dtest->viewlock) {
+ rv3dtest->dist= rv3d->dist;
+ VECCOPY(rv3dtest->ofs, rv3d->ofs);
+ ED_region_tag_redraw(artest);
+ }
+ }
+ }
+ view3d_boxview_clip(sa);
+}
+
+/* ************************** init for view ops **********************************/
+
+typedef struct ViewOpsData {
+ ScrArea *sa;
+ ARegion *ar;
+ RegionView3D *rv3d;
+
+ float oldquat[4];
+ float trackvec[3];
+ float ofs[3], obofs[3];
+ float reverse, dist0;
+ float grid, far;
+
+ int origx, origy, oldx, oldy;
+ int origkey;
+
+} ViewOpsData;
+
+#define TRACKBALLSIZE (1.1)
+
+static void calctrackballvec(rcti *rect, int mx, int my, float *vec)
+{
+ float x, y, radius, d, z, t;
+
+ radius= TRACKBALLSIZE;
+
+ /* normalize x and y */
+ x= (rect->xmax + rect->xmin)/2 - mx;
+ x/= (float)((rect->xmax - rect->xmin)/4);
+ y= (rect->ymax + rect->ymin)/2 - my;
+ y/= (float)((rect->ymax - rect->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; /* yah yah! */
+}
+
+
+static void viewops_data(bContext *C, wmOperator *op, wmEvent *event)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d;
+ ViewOpsData *vod= MEM_callocN(sizeof(ViewOpsData), "viewops data");
+
+ /* store data */
+ op->customdata= vod;
+ vod->sa= CTX_wm_area(C);
+ vod->ar= CTX_wm_region(C);
+ vod->rv3d= rv3d= vod->ar->regiondata;
+ vod->dist0= rv3d->dist;
+ QUATCOPY(vod->oldquat, rv3d->viewquat);
+ vod->origx= vod->oldx= event->x;
+ vod->origy= vod->oldy= event->y;
+ vod->origkey= event->type;
+
+ /* lookup, we dont pass on v3d to prevent confusement */
+ vod->grid= v3d->grid;
+ vod->far= v3d->far;
+
+ calctrackballvec(&vod->ar->winrct, event->x, event->y, vod->trackvec);
+
+ initgrabz(rv3d, -rv3d->ofs[0], -rv3d->ofs[1], -rv3d->ofs[2]);
+
+ vod->reverse= 1.0f;
+ if (rv3d->persmat[2][1] < 0.0f)
+ vod->reverse= -1.0f;
+
+}
+
+/* ************************** viewrotate **********************************/
+
+static const float thres = 0.93f; //cos(20 deg);
+
+#define COS45 0.70710678118654746
+#define SIN45 COS45
+
+static float snapquats[39][6] = {
+ /*{q0, q1, q3, q4, view, oposite_direction}*/
+{COS45, -SIN45, 0.0, 0.0, V3D_VIEW_FRONT, 0}, //front
+{0.0, 0.0, -SIN45, -SIN45, V3D_VIEW_BACK, 0}, //back
+{1.0, 0.0, 0.0, 0.0, V3D_VIEW_TOP, 0}, //top
+{0.0, -1.0, 0.0, 0.0, V3D_VIEW_BOTTOM, 0}, //bottom
+{0.5, -0.5, -0.5, -0.5, V3D_VIEW_LEFT, 0}, //left
+{0.5, -0.5, 0.5, 0.5, V3D_VIEW_RIGHT, 0}, //right
+
+ /* some more 45 deg snaps */
+{0.65328145027160645, -0.65328145027160645, 0.27059805393218994, 0.27059805393218994, 0, 0},
+{0.92387950420379639, 0.0, 0.0, 0.38268342614173889, 0, 0},
+{0.0, -0.92387950420379639, 0.38268342614173889, 0.0, 0, 0},
+{0.35355335474014282, -0.85355335474014282, 0.35355338454246521, 0.14644660055637360, 0, 0},
+{0.85355335474014282, -0.35355335474014282, 0.14644660055637360, 0.35355338454246521, 0, 0},
+{0.49999994039535522, -0.49999994039535522, 0.49999997019767761, 0.49999997019767761, 0, 0},
+{0.27059802412986755, -0.65328145027160645, 0.65328145027160645, 0.27059802412986755, 0, 0},
+{0.65328145027160645, -0.27059802412986755, 0.27059802412986755, 0.65328145027160645, 0, 0},
+{0.27059799432754517, -0.27059799432754517, 0.65328139066696167, 0.65328139066696167, 0, 0},
+{0.38268336653709412, 0.0, 0.0, 0.92387944459915161, 0, 0},
+{0.0, -0.38268336653709412, 0.92387944459915161, 0.0, 0, 0},
+{0.14644658565521240, -0.35355335474014282, 0.85355335474014282, 0.35355335474014282, 0, 0},
+{0.35355335474014282, -0.14644658565521240, 0.35355335474014282, 0.85355335474014282, 0, 0},
+{0.0, 0.0, 0.92387944459915161, 0.38268336653709412, 0, 0},
+{-0.0, 0.0, 0.38268336653709412, 0.92387944459915161, 0, 0},
+{-0.27059802412986755, 0.27059802412986755, 0.65328133106231689, 0.65328133106231689, 0, 0},
+{-0.38268339633941650, 0.0, 0.0, 0.92387938499450684, 0, 0},
+{0.0, 0.38268339633941650, 0.92387938499450684, 0.0, 0, 0},
+{-0.14644658565521240, 0.35355338454246521, 0.85355329513549805, 0.35355332493782043, 0, 0},
+{-0.35355338454246521, 0.14644658565521240, 0.35355332493782043, 0.85355329513549805, 0, 0},
+{-0.49999991059303284, 0.49999991059303284, 0.49999985098838806, 0.49999985098838806, 0, 0},
+{-0.27059799432754517, 0.65328145027160645, 0.65328139066696167, 0.27059799432754517, 0, 0},
+{-0.65328145027160645, 0.27059799432754517, 0.27059799432754517, 0.65328139066696167, 0, 0},
+{-0.65328133106231689, 0.65328133106231689, 0.27059793472290039, 0.27059793472290039, 0, 0},
+{-0.92387932538986206, 0.0, 0.0, 0.38268333673477173, 0, 0},
+{0.0, 0.92387932538986206, 0.38268333673477173, 0.0, 0, 0},
+{-0.35355329513549805, 0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0, 0},
+{-0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0.35355329513549805, 0, 0},
+{-0.38268330693244934, 0.92387938499450684, 0.0, 0.0, 0, 0},
+{-0.92387938499450684, 0.38268330693244934, 0.0, 0.0, 0, 0},
+{-COS45, 0.0, 0.0, SIN45, 0, 0},
+{COS45, 0.0, 0.0, SIN45, 0, 0},
+{0.0, 0.0, 0.0, 1.0, 0, 0}
+};
+
+
+static void viewrotate_apply(ViewOpsData *vod, int x, int y, int ctrl)
+{
+ RegionView3D *rv3d= vod->rv3d;
+ int use_sel= 0; /* XXX */
+
+ rv3d->view= 0; /* need to reset everytime because of view snapping */
+
+ if (U.flag & USER_TRACKBALL) {
+ float phi, si, q1[4], dvec[3], newvec[3];
+
+ calctrackballvec(&vod->ar->winrct, x, y, newvec);
+
+ VecSubf(dvec, newvec, vod->trackvec);
+
+ si= sqrt(dvec[0]*dvec[0]+ dvec[1]*dvec[1]+ dvec[2]*dvec[2]);
+ si/= (2.0*TRACKBALLSIZE);
+
+ Crossf(q1+1, vod->trackvec, newvec);
+ Normalize(q1+1);
+
+ /* Allow for rotation beyond the interval
+ * [-pi, pi] */
+ while (si > 1.0)
+ si -= 2.0;
+
+ /* This relation is used instead of
+ * phi = asin(si) so that the angle
+ * of rotation is linearly proportional
+ * to the distance that the mouse is
+ * dragged. */
+ phi = si * M_PI / 2.0;
+
+ si= sin(phi);
+ q1[0]= cos(phi);
+ q1[1]*= si;
+ q1[2]*= si;
+ q1[3]*= si;
+ QuatMul(rv3d->viewquat, q1, vod->oldquat);
+
+ if (use_sel) {
+ /* compute the post multiplication quat, to rotate the offset correctly */
+ QUATCOPY(q1, vod->oldquat);
+ QuatConj(q1);
+ QuatMul(q1, q1, rv3d->viewquat);
+
+ QuatConj(q1); /* conj == inv for unit quat */
+ VECCOPY(rv3d->ofs, vod->ofs);
+ VecSubf(rv3d->ofs, rv3d->ofs, vod->obofs);
+ QuatMulVecf(q1, rv3d->ofs);
+ VecAddf(rv3d->ofs, rv3d->ofs, vod->obofs);
+ }
+ }
+ else {
+ /* New turntable view code by John Aughey */
+ float si, phi, q1[4];
+ float m[3][3];
+ float m_inv[3][3];
+ float xvec[3] = {1,0,0};
+ /* Sensitivity will control how fast the viewport rotates. 0.0035 was
+ obtained experimentally by looking at viewport rotation sensitivities
+ on other modeling programs. */
+ /* Perhaps this should be a configurable user parameter. */
+ const float sensitivity = 0.0035;
+
+ /* Get the 3x3 matrix and its inverse from the quaternion */
+ QuatToMat3(rv3d->viewquat, m);
+ Mat3Inv(m_inv,m);
+
+ /* Determine the direction of the x vector (for rotating up and down) */
+ /* This can likely be compuated directly from the quaternion. */
+ Mat3MulVecfl(m_inv,xvec);
+
+ /* Perform the up/down rotation */
+ phi = sensitivity * -(y - vod->oldy);
+ si = sin(phi);
+ q1[0] = cos(phi);
+ q1[1] = si * xvec[0];
+ q1[2] = si * xvec[1];
+ q1[3] = si * xvec[2];
+ QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
+
+ if (use_sel) {
+ QuatConj(q1); /* conj == inv for unit quat */
+ VecSubf(rv3d->ofs, rv3d->ofs, vod->obofs);
+ QuatMulVecf(q1, rv3d->ofs);
+ VecAddf(rv3d->ofs, rv3d->ofs, vod->obofs);
+ }
+
+ /* Perform the orbital rotation */
+ phi = sensitivity * vod->reverse * (x - vod->oldx);
+ q1[0] = cos(phi);
+ q1[1] = q1[2] = 0.0;
+ q1[3] = sin(phi);
+ QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
+
+ if (use_sel) {
+ QuatConj(q1);
+ VecSubf(rv3d->ofs, rv3d->ofs, vod->obofs);
+ QuatMulVecf(q1, rv3d->ofs);
+ VecAddf(rv3d->ofs, rv3d->ofs, vod->obofs);
+ }
+ }
+
+ /* check for view snap */
+ if (ctrl){
+ int i;
+ float viewmat[3][3];
+
+
+ QuatToMat3(rv3d->viewquat, viewmat);
+
+ for (i = 0 ; i < 39; i++){
+ float snapmat[3][3];
+ float view = (int)snapquats[i][4];
+
+ QuatToMat3(snapquats[i], snapmat);
+
+ if ((Inpf(snapmat[0], viewmat[0]) > thres) &&
+ (Inpf(snapmat[1], viewmat[1]) > thres) &&
+ (Inpf(snapmat[2], viewmat[2]) > thres)){
+
+ QUATCOPY(rv3d->viewquat, snapquats[i]);
+
+ rv3d->view = view;
+
+ break;
+ }
+ }
+ }
+ vod->oldx= x;
+ vod->oldy= y;
+
+ ED_region_tag_redraw(vod->ar);
+}
+
+static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ViewOpsData *vod= op->customdata;
+
+ /* execute the events */
+ switch(event->type) {
+ case MOUSEMOVE:
+ viewrotate_apply(vod, event->x, event->y, event->ctrl);
+ break;
+
+ default:
+ if(event->type==vod->origkey && event->val==0) {
+ request_depth_update(CTX_wm_region_view3d(C));
+
+ MEM_freeN(vod);
+ op->customdata= NULL;
+
+ return OPERATOR_FINISHED;
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ ViewOpsData *vod;
+
+ if(rv3d->viewlock)
+ return OPERATOR_CANCELLED;
+
+ /* makes op->customdata */
+ viewops_data(C, op, event);
+ vod= op->customdata;
+
+ /* switch from camera view when: */
+ if(vod->rv3d->persp != V3D_PERSP) {
+
+ if (U.uiflag & USER_AUTOPERSP)
+ vod->rv3d->persp= V3D_PERSP;
+ else if(vod->rv3d->persp==V3D_CAMOB)
+ vod->rv3d->persp= V3D_PERSP;
+ ED_region_tag_redraw(vod->ar);
+ }
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+
+void VIEW3D_OT_viewrotate(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Rotate view";
+ ot->description = "Rotate the view.";
+ ot->idname= "VIEW3D_OT_viewrotate";
+
+ /* api callbacks */
+ ot->invoke= viewrotate_invoke;
+ ot->modal= viewrotate_modal;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+/* ************************ viewmove ******************************** */
+
+static void viewmove_apply(ViewOpsData *vod, int x, int y)
+{
+ if(vod->rv3d->persp==V3D_CAMOB) {
+ float max= (float)MAX2(vod->ar->winx, vod->ar->winy);
+
+ vod->rv3d->camdx += (vod->oldx - x)/(max);
+ vod->rv3d->camdy += (vod->oldy - y)/(max);
+ CLAMP(vod->rv3d->camdx, -1.0f, 1.0f);
+ CLAMP(vod->rv3d->camdy, -1.0f, 1.0f);
+// XXX preview3d_event= 0;
+ }
+ else {
+ float dvec[3];
+
+ window_to_3d_delta(vod->ar, dvec, x-vod->oldx, y-vod->oldy);
+ VecAddf(vod->rv3d->ofs, vod->rv3d->ofs, dvec);
+
+ if(vod->rv3d->viewlock & RV3D_BOXVIEW)
+ view3d_boxview_sync(vod->sa, vod->ar);
+ }
+
+ vod->oldx= x;
+ vod->oldy= y;
+
+ ED_region_tag_redraw(vod->ar);
+}
+
+
+static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ViewOpsData *vod= op->customdata;
+
+ /* execute the events */
+ switch(event->type) {
+ case MOUSEMOVE:
+ viewmove_apply(vod, event->x, event->y);
+ break;
+
+ default:
+ if(event->type==vod->origkey && event->val==0) {
+ request_depth_update(CTX_wm_region_view3d(C));
+
+ MEM_freeN(vod);
+ op->customdata= NULL;
+
+ return OPERATOR_FINISHED;
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ /* makes op->customdata */
+ viewops_data(C, op, event);
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+
+void VIEW3D_OT_viewmove(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Move view";
+ ot->description = "Move the view.";
+ ot->idname= "VIEW3D_OT_viewmove";
+
+ /* api callbacks */
+ ot->invoke= viewmove_invoke;
+ ot->modal= viewmove_modal;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+/* ************************ viewzoom ******************************** */
+
+static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my)
+{
+ RegionView3D *rv3d= ar->regiondata;
+
+ if(U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+ float dvec[3];
+ float tvec[3];
+ float tpos[3];
+ float new_dist;
+ short vb[2], mouseloc[2];
+
+ mouseloc[0]= mx - ar->winrct.xmin;
+ mouseloc[1]= my - ar->winrct.ymin;
+
+ /* find the current window width and height */
+ vb[0] = ar->winx;
+ vb[1] = ar->winy;
+
+ tpos[0] = -rv3d->ofs[0];
+ tpos[1] = -rv3d->ofs[1];
+ tpos[2] = -rv3d->ofs[2];
+
+ /* Project cursor position into 3D space */
+ initgrabz(rv3d, tpos[0], tpos[1], tpos[2]);
+ window_to_3d_delta(ar, dvec, mouseloc[0]-vb[0]/2, mouseloc[1]-vb[1]/2);
+
+ /* Calculate view target position for dolly */
+ tvec[0] = -(tpos[0] + dvec[0]);
+ tvec[1] = -(tpos[1] + dvec[1]);
+ tvec[2] = -(tpos[2] + dvec[2]);
+
+ /* Offset to target position and dolly */
+ new_dist = rv3d->dist * dfac;
+
+ VECCOPY(rv3d->ofs, tvec);
+ rv3d->dist = new_dist;
+
+ /* Calculate final offset */
+ dvec[0] = tvec[0] + dvec[0] * dfac;
+ dvec[1] = tvec[1] + dvec[1] * dfac;
+ dvec[2] = tvec[2] + dvec[2] * dfac;
+
+ VECCOPY(rv3d->ofs, dvec);
+ } else {
+ rv3d->dist *= dfac;
+ }
+}
+
+
+static void viewzoom_apply(ViewOpsData *vod, int x, int y)
+{
+ float zfac=1.0;
+
+ if(U.viewzoom==USER_ZOOM_CONT) {
+ // oldstyle zoom
+ zfac = 1.0+(float)(vod->origx - x + vod->origy - y)/1000.0;
+ }
+ else if(U.viewzoom==USER_ZOOM_SCALE) {
+ int ctr[2], len1, len2;
+ // method which zooms based on how far you move the mouse
+
+ ctr[0] = (vod->ar->winrct.xmax + vod->ar->winrct.xmin)/2;
+ ctr[1] = (vod->ar->winrct.ymax + vod->ar->winrct.ymin)/2;
+
+ len1 = (int)sqrt((ctr[0] - x)*(ctr[0] - x) + (ctr[1] - y)*(ctr[1] - y)) + 5;
+ len2 = (int)sqrt((ctr[0] - vod->origx)*(ctr[0] - vod->origx) + (ctr[1] - vod->origy)*(ctr[1] - vod->origy)) + 5;
+
+ zfac = vod->dist0 * ((float)len2/len1) / vod->rv3d->dist;
+ }
+ else { /* USER_ZOOM_DOLLY */
+ float len1 = (vod->ar->winrct.ymax - y) + 5;
+ float len2 = (vod->ar->winrct.ymax - vod->origy) + 5;
+ zfac = vod->dist0 * (2.0*((len2/len1)-1.0) + 1.0) / vod->rv3d->dist;
+ }
+
+ if(zfac != 1.0 && zfac*vod->rv3d->dist > 0.001*vod->grid &&
+ zfac*vod->rv3d->dist < 10.0*vod->far)
+ view_zoom_mouseloc(vod->ar, zfac, vod->oldx, vod->oldy);
+
+
+ if ((U.uiflag & USER_ORBIT_ZBUF) && (U.viewzoom==USER_ZOOM_CONT) && (vod->rv3d->persp==V3D_PERSP)) {
+ float upvec[3], mat[3][3];
+
+ /* Secret apricot feature, translate the view when in continues mode */
+ upvec[0] = upvec[1] = 0.0f;
+ upvec[2] = (vod->dist0 - vod->rv3d->dist) * vod->grid;
+ vod->rv3d->dist = vod->dist0;
+ Mat3CpyMat4(mat, vod->rv3d->viewinv);
+ Mat3MulVecfl(mat, upvec);
+ VecAddf(vod->rv3d->ofs, vod->rv3d->ofs, upvec);
+ } else {
+ /* these limits were in old code too */
+ if(vod->rv3d->dist<0.001*vod->grid) vod->rv3d->dist= 0.001*vod->grid;
+ if(vod->rv3d->dist>10.0*vod->far) vod->rv3d->dist=10.0*vod->far;
+ }
+
+// XXX if(vod->rv3d->persp==V3D_ORTHO || vod->rv3d->persp==V3D_CAMOB) preview3d_event= 0;
+
+ if(vod->rv3d->viewlock & RV3D_BOXVIEW)
+ view3d_boxview_sync(vod->sa, vod->ar);
+
+ ED_region_tag_redraw(vod->ar);
+}
+
+
+static int viewzoom_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ViewOpsData *vod= op->customdata;
+
+ /* execute the events */
+ switch(event->type) {
+ case MOUSEMOVE:
+ viewzoom_apply(vod, event->x, event->y);
+ break;
+
+ default:
+ if(event->type==vod->origkey && event->val==0) {
+ request_depth_update(CTX_wm_region_view3d(C));
+
+ MEM_freeN(vod);
+ op->customdata= NULL;
+
+ return OPERATOR_FINISHED;
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int viewzoom_exec(bContext *C, wmOperator *op)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ int delta= RNA_int_get(op->ptr, "delta");
+
+ if(delta < 0) {
+ /* this min and max is also in viewmove() */
+ if(rv3d->persp==V3D_CAMOB) {
+ rv3d->camzoom-= 10;
+ if(rv3d->camzoom<-30) rv3d->camzoom= -30;
+ }
+ else if(rv3d->dist<10.0*v3d->far) rv3d->dist*=1.2f;
+ }
+ else {
+ if(rv3d->persp==V3D_CAMOB) {
+ rv3d->camzoom+= 10;
+ if(rv3d->camzoom>300) rv3d->camzoom= 300;
+ }
+ else if(rv3d->dist> 0.001*v3d->grid) rv3d->dist*=.83333f;
+ }
+
+ if(rv3d->viewlock & RV3D_BOXVIEW)
+ view3d_boxview_sync(CTX_wm_area(C), CTX_wm_region(C));
+
+ request_depth_update(CTX_wm_region_view3d(C));
+ ED_region_tag_redraw(CTX_wm_region(C));
+
+ return OPERATOR_FINISHED;
+}
+
+static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ int delta= RNA_int_get(op->ptr, "delta");
+
+ if(delta) {
+ viewzoom_exec(C, op);
+ }
+ else {
+ /* makes op->customdata */
+ viewops_data(C, op, event);
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ return OPERATOR_FINISHED;
+}
+
+
+void VIEW3D_OT_zoom(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Zoom view";
+ ot->description = "Zoom in/out in the view.";
+ ot->idname= "VIEW3D_OT_zoom";
+
+ /* api callbacks */
+ ot->invoke= viewzoom_invoke;
+ ot->exec= viewzoom_exec;
+ ot->modal= viewzoom_modal;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
+}
+
+static int viewhome_exec(bContext *C, wmOperator *op) /* was view3d_home() in 2.4x */
+{
+ ARegion *ar= CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ Scene *scene= CTX_data_scene(C);
+ Base *base;
+
+ int center= RNA_boolean_get(op->ptr, "center");
+
+ float size, min[3], max[3], afm[3];
+ int ok= 1, onedone=0;
+
+ if(center) {
+ min[0]= min[1]= min[2]= 0.0f;
+ max[0]= max[1]= max[2]= 0.0f;
+ }
+ else {
+ INIT_MINMAX(min, max);
+ }
+
+ for(base= scene->base.first; base; base= base->next) {
+ if(base->lay & v3d->lay) {
+ onedone= 1;
+ minmax_object(base->object, min, max);
+ }
+ }
+ if(!onedone) return OPERATOR_FINISHED; /* TODO - should this be cancel? */
+
+ afm[0]= (max[0]-min[0]);
+ afm[1]= (max[1]-min[1]);
+ afm[2]= (max[2]-min[2]);
+ size= 0.7f*MAX3(afm[0], afm[1], afm[2]);
+ if(size==0.0) ok= 0;
+
+ if(ok) {
+ float new_dist;
+ float new_ofs[3];
+
+ new_dist = size;
+ new_ofs[0]= -(min[0]+max[0])/2.0f;
+ new_ofs[1]= -(min[1]+max[1])/2.0f;
+ new_ofs[2]= -(min[2]+max[2])/2.0f;
+
+ // correction for window aspect ratio
+ if(ar->winy>2 && ar->winx>2) {
+ size= (float)ar->winx/(float)ar->winy;
+ if(size<1.0) size= 1.0f/size;
+ new_dist*= size;
+ }
+
+ if (rv3d->persp==V3D_CAMOB) {
+ rv3d->persp= V3D_PERSP;
+ smooth_view(C, NULL, v3d->camera, new_ofs, NULL, &new_dist, NULL);
+ }
+ }
+// XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
+
+ if(rv3d->viewlock & RV3D_BOXVIEW)
+ view3d_boxview_copy(CTX_wm_area(C), ar);
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_viewhome(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View home";
+ ot->description = "View all objects in scene.";
+ ot->idname= "VIEW3D_OT_viewhome";
+
+ /* api callbacks */
+ ot->exec= viewhome_exec;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ RNA_def_boolean(ot->srna, "center", 0, "Center", "");
+}
+
+static int viewcenter_exec(bContext *C, wmOperator *op) /* like a localview without local!, was centerview() in 2.4x */
+{
+ ARegion *ar= CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= OBACT;
+ Object *obedit= CTX_data_edit_object(C);
+ float size, min[3], max[3], afm[3];
+ int ok=0;
+
+ /* SMOOTHVIEW */
+ float new_ofs[3];
+ float new_dist;
+
+ INIT_MINMAX(min, max);
+
+ if (G.f & G_WEIGHTPAINT) {
+ /* hardcoded exception, we look for the one selected armature */
+ /* this is weak code this way, we should make a generic active/selection callback interface once... */
+ Base *base;
+ for(base=scene->base.first; base; base= base->next) {
+ if(TESTBASELIB(v3d, base)) {
+ if(base->object->type==OB_ARMATURE)
+ if(base->object->flag & OB_POSEMODE)
+ break;
+ }
+ }
+ if(base)
+ ob= base->object;
+ }
+
+
+ if(obedit) {
+ ok = minmax_verts(obedit, min, max); /* only selected */
+ }
+ else if(ob && (ob->flag & OB_POSEMODE)) {
+ if(ob->pose) {
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+ float vec[3];
+
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if(pchan->bone->flag & BONE_SELECTED) {
+ if(pchan->bone->layer & arm->layer) {
+ ok= 1;
+ VECCOPY(vec, pchan->pose_head);
+ Mat4MulVecfl(ob->obmat, vec);
+ DO_MINMAX(vec, min, max);
+ VECCOPY(vec, pchan->pose_tail);
+ Mat4MulVecfl(ob->obmat, vec);
+ DO_MINMAX(vec, min, max);
+ }
+ }
+ }
+ }
+ }
+ else if (FACESEL_PAINT_TEST) {
+// XXX ok= minmax_tface(min, max);
+ }
+ else if (G.f & G_PARTICLEEDIT) {
+ ok= PE_minmax(scene, min, max);
+ }
+ else {
+ Base *base= FIRSTBASE;
+ while(base) {
+ if(TESTBASE(v3d, base)) {
+ minmax_object(base->object, min, max);
+ /* account for duplis */
+ minmax_object_duplis(scene, base->object, min, max);
+
+ ok= 1;
+ }
+ base= base->next;
+ }
+ }
+
+ if(ok==0) return OPERATOR_FINISHED;
+
+ 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]);
+ /* perspective should be a bit farther away to look nice */
+ if(rv3d->persp==V3D_ORTHO)
+ size*= 0.7;
+
+ if(size <= v3d->near*1.5f) size= v3d->near*1.5f;
+
+ new_ofs[0]= -(min[0]+max[0])/2.0f;
+ new_ofs[1]= -(min[1]+max[1])/2.0f;
+ new_ofs[2]= -(min[2]+max[2])/2.0f;
+
+ new_dist = size;
+
+ /* correction for window aspect ratio */
+ if(ar->winy>2 && ar->winx>2) {
+ size= (float)ar->winx/(float)ar->winy;
+ if(size<1.0f) size= 1.0f/size;
+ new_dist*= size;
+ }
+
+ v3d->cursor[0]= -new_ofs[0];
+ v3d->cursor[1]= -new_ofs[1];
+ v3d->cursor[2]= -new_ofs[2];
+
+ if (rv3d->persp==V3D_CAMOB) {
+ rv3d->persp= V3D_PERSP;
+ smooth_view(C, v3d->camera, NULL, new_ofs, NULL, &new_dist, NULL);
+ }
+ else {
+ smooth_view(C, NULL, NULL, new_ofs, NULL, &new_dist, NULL);
+ }
+
+// XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
+ if(rv3d->viewlock & RV3D_BOXVIEW)
+ view3d_boxview_copy(CTX_wm_area(C), ar);
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_viewcenter(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "View center";
+ ot->description = "Move the view to the selection center.";
+ ot->idname= "VIEW3D_OT_viewcenter";
+
+ /* api callbacks */
+ ot->exec= viewcenter_exec;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+/* ********************* Set render border operator ****************** */
+
+static int render_border_exec(bContext *C, wmOperator *op)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar= CTX_wm_region(C);
+ Scene *scene= CTX_data_scene(C);
+
+ rcti rect;
+ rctf vb;
+
+ /* get border select values using rna */
+ rect.xmin= RNA_int_get(op->ptr, "xmin");
+ rect.ymin= RNA_int_get(op->ptr, "ymin");
+ rect.xmax= RNA_int_get(op->ptr, "xmax");
+ rect.ymax= RNA_int_get(op->ptr, "ymax");
+
+ /* calculate range */
+ calc_viewborder(scene, ar, v3d, &vb);
+
+ scene->r.border.xmin= ((float)rect.xmin-vb.xmin)/(vb.xmax-vb.xmin);
+ scene->r.border.ymin= ((float)rect.ymin-vb.ymin)/(vb.ymax-vb.ymin);
+ scene->r.border.xmax= ((float)rect.xmax-vb.xmin)/(vb.xmax-vb.xmin);
+ scene->r.border.ymax= ((float)rect.ymax-vb.ymin)/(vb.ymax-vb.ymin);
+
+ /* actually set border */
+ CLAMP(scene->r.border.xmin, 0.0, 1.0);
+ CLAMP(scene->r.border.ymin, 0.0, 1.0);
+ CLAMP(scene->r.border.xmax, 0.0, 1.0);
+ CLAMP(scene->r.border.ymax, 0.0, 1.0);
+
+ /* drawing a border surrounding the entire camera view switches off border rendering
+ * or the border covers no pixels */
+ if ((scene->r.border.xmin <= 0.0 && scene->r.border.xmax >= 1.0 &&
+ scene->r.border.ymin <= 0.0 && scene->r.border.ymax >= 1.0) ||
+ (scene->r.border.xmin == scene->r.border.xmax ||
+ scene->r.border.ymin == scene->r.border.ymax ))
+ {
+ scene->r.mode &= ~R_BORDER;
+ } else {
+ scene->r.mode |= R_BORDER;
+ }
+
+ return OPERATOR_FINISHED;
+
+}
+
+static int view3d_render_border_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+
+ /* if not in camera view do not exec the operator*/
+ if (rv3d->persp == V3D_CAMOB) return WM_border_select_invoke(C, op, event);
+ else return OPERATOR_PASS_THROUGH;
+}
+
+void VIEW3D_OT_render_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Render Border";
+ ot->description = "Set the boundries of the border render and enables border render .";
+ ot->idname= "VIEW3D_OT_render_border";
+
+ /* api callbacks */
+ ot->invoke= view3d_render_border_invoke;
+ ot->exec= render_border_exec;
+ ot->modal= WM_border_select_modal;
+
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* rna */
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+
+}
+/* ********************* Border Zoom operator ****************** */
+
+static int view3d_border_zoom_exec(bContext *C, wmOperator *op)
+{
+ ARegion *ar= CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ Scene *scene= CTX_data_scene(C);
+
+ /* Zooms in on a border drawn by the user */
+ rcti rect;
+ float dvec[3], vb[2], xscale, yscale, scale;
+
+ /* SMOOTHVIEW */
+ float new_dist;
+ float new_ofs[3];
+
+ /* ZBuffer depth vars */
+ bglMats mats;
+ float depth, depth_close= MAXFLOAT;
+ int had_depth = 0;
+ double cent[2], p[3];
+ int xs, ys;
+
+ /* note; otherwise opengl won't work */
+ view3d_operator_needs_opengl(C);
+
+ /* get border select values using rna */
+ rect.xmin= RNA_int_get(op->ptr, "xmin");
+ rect.ymin= RNA_int_get(op->ptr, "ymin");
+ rect.xmax= RNA_int_get(op->ptr, "xmax");
+ rect.ymax= RNA_int_get(op->ptr, "ymax");
+
+ /* Get Z Depths, needed for perspective, nice for ortho */
+ bgl_get_mats(&mats);
+ draw_depth(scene, ar, v3d, NULL);
+
+ /* force updating */
+ if (rv3d->depths) {
+ had_depth = 1;
+ rv3d->depths->damaged = 1;
+ }
+
+ view3d_update_depths(ar, v3d);
+
+ /* Constrain rect to depth bounds */
+ if (rect.xmin < 0) rect.xmin = 0;
+ if (rect.ymin < 0) rect.ymin = 0;
+ if (rect.xmax >= rv3d->depths->w) rect.xmax = rv3d->depths->w-1;
+ if (rect.ymax >= rv3d->depths->h) rect.ymax = rv3d->depths->h-1;
+
+ /* Find the closest Z pixel */
+ for (xs=rect.xmin; xs < rect.xmax; xs++) {
+ for (ys=rect.ymin; ys < rect.ymax; ys++) {
+ depth= rv3d->depths->depths[ys*rv3d->depths->w+xs];
+ if(depth < rv3d->depths->depth_range[1] && depth > rv3d->depths->depth_range[0]) {
+ if (depth_close > depth) {
+ depth_close = depth;
+ }
+ }
+ }
+ }
+
+ if (had_depth==0) {
+ MEM_freeN(rv3d->depths->depths);
+ rv3d->depths->depths = NULL;
+ }
+ rv3d->depths->damaged = 1;
+
+ cent[0] = (((double)rect.xmin)+((double)rect.xmax)) / 2;
+ cent[1] = (((double)rect.ymin)+((double)rect.ymax)) / 2;
+
+ if (rv3d->persp==V3D_PERSP) {
+ double p_corner[3];
+
+ /* no depths to use, we cant do anything! */
+ if (depth_close==MAXFLOAT){
+ BKE_report(op->reports, RPT_ERROR, "Depth Too Large");
+ return OPERATOR_CANCELLED;
+ }
+ /* convert border to 3d coordinates */
+ if (( !gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) ||
+ ( !gluUnProject((double)rect.xmin, (double)rect.ymin, depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p_corner[0], &p_corner[1], &p_corner[2])))
+ return OPERATOR_CANCELLED;
+
+ dvec[0] = p[0]-p_corner[0];
+ dvec[1] = p[1]-p_corner[1];
+ dvec[2] = p[2]-p_corner[2];
+
+ new_dist = VecLength(dvec);
+ if(new_dist <= v3d->near*1.5) new_dist= v3d->near*1.5;
+
+ new_ofs[0] = -p[0];
+ new_ofs[1] = -p[1];
+ new_ofs[2] = -p[2];
+
+ } else { /* othographic */
+ /* find the current window width and height */
+ vb[0] = ar->winx;
+ vb[1] = ar->winy;
+
+ new_dist = rv3d->dist;
+
+ /* convert the drawn rectangle into 3d space */
+ if (depth_close!=MAXFLOAT && gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) {
+ new_ofs[0] = -p[0];
+ new_ofs[1] = -p[1];
+ new_ofs[2] = -p[2];
+ } else {
+ /* We cant use the depth, fallback to the old way that dosnt set the center depth */
+ new_ofs[0] = rv3d->ofs[0];
+ new_ofs[1] = rv3d->ofs[1];
+ new_ofs[2] = rv3d->ofs[2];
+
+ initgrabz(rv3d, -new_ofs[0], -new_ofs[1], -new_ofs[2]);
+
+ window_to_3d_delta(ar, dvec, (rect.xmin+rect.xmax-vb[0])/2, (rect.ymin+rect.ymax-vb[1])/2);
+ /* center the view to the center of the rectangle */
+ VecSubf(new_ofs, new_ofs, dvec);
+ }
+
+ /* work out the ratios, so that everything selected fits when we zoom */
+ xscale = ((rect.xmax-rect.xmin)/vb[0]);
+ yscale = ((rect.ymax-rect.ymin)/vb[1]);
+ scale = (xscale >= yscale)?xscale:yscale;
+
+ /* zoom in as required, or as far as we can go */
+ new_dist = ((new_dist*scale) >= 0.001*v3d->grid)? new_dist*scale:0.001*v3d->grid;
+ }
+
+ smooth_view(C, NULL, NULL, new_ofs, NULL, &new_dist, NULL);
+
+ if(rv3d->viewlock & RV3D_BOXVIEW)
+ view3d_boxview_sync(CTX_wm_area(C), ar);
+
+ return OPERATOR_FINISHED;
+}
+
+static int view3d_border_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+
+ /* if in camera view do not exec the operator so we do not conflict with set render border*/
+ if (rv3d->persp != V3D_CAMOB)
+ return WM_border_select_invoke(C, op, event);
+ else
+ return OPERATOR_PASS_THROUGH;
+}
+
+void VIEW3D_OT_zoom_border(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Border Zoom";
+ ot->description = "Zoom in the view to the nearest object contained in the border.";
+ ot->idname= "VIEW3D_OT_zoom_border";
+
+ /* api callbacks */
+ ot->invoke= view3d_border_zoom_invoke;
+ ot->exec= view3d_border_zoom_exec;
+ ot->modal= WM_border_select_modal;
+
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* rna */
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+
+}
+/* ********************* Changing view operator ****************** */
+
+static EnumPropertyItem prop_view_items[] = {
+ {V3D_VIEW_FRONT, "FRONT", "Front", "View From the Front"},
+ {V3D_VIEW_BACK, "BACK", "Back", "View From the Back"},
+ {V3D_VIEW_LEFT, "LEFT", "Left", "View From the Left"},
+ {V3D_VIEW_RIGHT, "RIGHT", "Right", "View From the Right"},
+ {V3D_VIEW_TOP, "TOP", "Top", "View From the Top"},
+ {V3D_VIEW_BOTTOM, "BOTTOM", "Bottom", "View From the Bottom"},
+ {V3D_VIEW_CAMERA, "CAMERA", "Camera", "View From the active amera"},
+ {0, NULL, NULL, NULL}};
+
+static void axis_set_view(bContext *C, float q1, float q2, float q3, float q4, short view, int perspo)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ float new_quat[4];
+
+ if(rv3d->viewlock) {
+ /* only pass on if */
+ if(rv3d->view==V3D_VIEW_FRONT && view==V3D_VIEW_BACK);
+ else if(rv3d->view==V3D_VIEW_BACK && view==V3D_VIEW_FRONT);
+ else if(rv3d->view==V3D_VIEW_RIGHT && view==V3D_VIEW_LEFT);
+ else if(rv3d->view==V3D_VIEW_LEFT && view==V3D_VIEW_RIGHT);
+ else if(rv3d->view==V3D_VIEW_BOTTOM && view==V3D_VIEW_TOP);
+ else if(rv3d->view==V3D_VIEW_TOP && view==V3D_VIEW_BOTTOM);
+ else return;
+ }
+
+ new_quat[0]= q1; new_quat[1]= q2;
+ new_quat[2]= q3; new_quat[3]= q4;
+
+ rv3d->view= view;
+
+ if(rv3d->viewlock) {
+ ED_region_tag_redraw(CTX_wm_region(C));
+ return;
+ }
+
+ if (rv3d->persp==V3D_CAMOB && v3d->camera) {
+
+ if (U.uiflag & USER_AUTOPERSP) rv3d->persp= V3D_ORTHO;
+ else if(rv3d->persp==V3D_CAMOB) rv3d->persp= perspo;
+
+ smooth_view(C, v3d->camera, NULL, rv3d->ofs, new_quat, NULL, NULL);
+ }
+ else {
+
+ if (U.uiflag & USER_AUTOPERSP) rv3d->persp= V3D_ORTHO;
+ else if(rv3d->persp==V3D_CAMOB) rv3d->persp= perspo;
+
+ smooth_view(C, NULL, NULL, NULL, new_quat, NULL, NULL);
+ }
+
+}
+
+static int viewnumpad_exec(bContext *C, wmOperator *op)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ Scene *scene= CTX_data_scene(C);
+ static int perspo=V3D_PERSP;
+ int viewnum;
+
+ viewnum = RNA_enum_get(op->ptr, "type");
+
+ /* Use this to test if we started out with a camera */
+
+ switch (viewnum) {
+ case V3D_VIEW_BOTTOM :
+ axis_set_view(C, 0.0, -1.0, 0.0, 0.0, viewnum, perspo);
+ break;
+
+ case V3D_VIEW_BACK:
+ axis_set_view(C, 0.0, 0.0, (float)-cos(M_PI/4.0), (float)-cos(M_PI/4.0), viewnum, perspo);
+ break;
+
+ case V3D_VIEW_LEFT:
+ axis_set_view(C, 0.5, -0.5, 0.5, 0.5, viewnum, perspo);
+ break;
+
+ case V3D_VIEW_TOP:
+ axis_set_view(C, 1.0, 0.0, 0.0, 0.0, viewnum, perspo);
+ break;
+
+ case V3D_VIEW_FRONT:
+ axis_set_view(C, (float)cos(M_PI/4.0), (float)-sin(M_PI/4.0), 0.0, 0.0, viewnum, perspo);
+ break;
+
+ case V3D_VIEW_RIGHT:
+ axis_set_view(C, 0.5, -0.5, -0.5, -0.5, viewnum, perspo);
+ break;
+
+ case V3D_VIEW_CAMERA:
+ if(rv3d->viewlock==0) {
+ /* lastview - */
+
+ if(rv3d->persp != V3D_CAMOB) {
+ /* store settings of current view before allowing overwriting with camera view */
+ QUATCOPY(rv3d->lviewquat, rv3d->viewquat);
+ rv3d->lview= rv3d->view;
+ rv3d->lpersp= rv3d->persp;
+
+ #if 0
+ if(G.qual==LR_ALTKEY) {
+ if(oldcamera && is_an_active_object(oldcamera)) {
+ v3d->camera= oldcamera;
+ }
+ handle_view3d_lock();
+ }
+ #endif
+
+ if(BASACT) {
+ /* check both G.vd as G.scene cameras */
+ if((v3d->camera==NULL || scene->camera==NULL) && OBACT->type==OB_CAMERA) {
+ v3d->camera= OBACT;
+ /*handle_view3d_lock();*/
+ }
+ }
+
+ if(v3d->camera==NULL) {
+ v3d->camera= scene_find_camera(scene);
+ /*handle_view3d_lock();*/
+ }
+ rv3d->persp= V3D_CAMOB;
+ smooth_view(C, NULL, v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, &v3d->lens);
+
+ }
+ else{
+ /* return to settings of last view */
+ /* does smooth_view too */
+ axis_set_view(C, rv3d->lviewquat[0], rv3d->lviewquat[1], rv3d->lviewquat[2], rv3d->lviewquat[3], rv3d->lview, rv3d->lpersp);
+ }
+ }
+ break;
+
+ default :
+ break;
+ }
+
+ if(rv3d->persp != V3D_CAMOB) perspo= rv3d->persp;
+
+ return OPERATOR_FINISHED;
+}
+void VIEW3D_OT_viewnumpad(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View numpad";
+ ot->description = "Set the view.";
+ ot->idname= "VIEW3D_OT_viewnumpad";
+
+ /* api callbacks */
+ ot->exec= viewnumpad_exec;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "The Type of view");
+}
+
+static EnumPropertyItem prop_view_orbit_items[] = {
+ {V3D_VIEW_STEPLEFT, "ORBITLEFT", "Orbit Left", "Orbit the view around to the Left"},
+ {V3D_VIEW_STEPRIGHT, "ORBITRIGHT", "Orbit Right", "Orbit the view around to the Right"},
+ {V3D_VIEW_STEPUP, "ORBITUP", "Orbit Up", "Orbit the view Up"},
+ {V3D_VIEW_STEPDOWN, "ORBITDOWN", "Orbit Down", "Orbit the view Down"},
+ {0, NULL, NULL, NULL}};
+
+static int vieworbit_exec(bContext *C, wmOperator *op)
+{
+ ARegion *ar= CTX_wm_region(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ float phi, si, q1[4];
+ int orbitdir;
+
+ orbitdir = RNA_enum_get(op->ptr, "type");
+
+ if(rv3d->viewlock==0) {
+
+ if(rv3d->persp != V3D_CAMOB) {
+ if(orbitdir == V3D_VIEW_STEPLEFT || orbitdir == V3D_VIEW_STEPRIGHT) {
+ /* z-axis */
+ phi= (float)(M_PI/360.0)*U.pad_rot_angle;
+ if(orbitdir == V3D_VIEW_STEPRIGHT) phi= -phi;
+ si= (float)sin(phi);
+ q1[0]= (float)cos(phi);
+ q1[1]= q1[2]= 0.0;
+ q1[3]= si;
+ QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
+ rv3d->view= 0;
+ }
+ if(orbitdir == V3D_VIEW_STEPDOWN || orbitdir == V3D_VIEW_STEPUP) {
+ /* horizontal axis */
+ VECCOPY(q1+1, rv3d->viewinv[0]);
+
+ Normalize(q1+1);
+ phi= (float)(M_PI/360.0)*U.pad_rot_angle;
+ if(orbitdir == V3D_VIEW_STEPDOWN) phi= -phi;
+ si= (float)sin(phi);
+ q1[0]= (float)cos(phi);
+ q1[1]*= si;
+ q1[2]*= si;
+ q1[3]*= si;
+ QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
+ rv3d->view= 0;
+ }
+ ED_region_tag_redraw(ar);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_view_orbit(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View Orbit";
+ ot->description = "Orbit the view.";
+ ot->idname= "VIEW3D_OT_view_orbit";
+
+ /* api callbacks */
+ ot->exec= vieworbit_exec;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+ RNA_def_enum(ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit");
+}
+
+static EnumPropertyItem prop_view_pan_items[] = {
+ {V3D_VIEW_PANLEFT, "PANLEFT", "Pan Left", "Pan the view to the Left"},
+ {V3D_VIEW_PANRIGHT, "PANRIGHT", "Pan Right", "Pan the view to the Right"},
+ {V3D_VIEW_PANUP, "PANUP", "Pan Up", "Pan the view Up"},
+ {V3D_VIEW_PANDOWN, "PANDOWN", "Pan Down", "Pan the view Down"},
+ {0, NULL, NULL, NULL}};
+
+static int viewpan_exec(bContext *C, wmOperator *op)
+{
+ ARegion *ar= CTX_wm_region(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ float vec[3];
+ int pandir;
+
+ pandir = RNA_enum_get(op->ptr, "type");
+
+ initgrabz(rv3d, 0.0, 0.0, 0.0);
+
+ if(pandir == V3D_VIEW_PANRIGHT) window_to_3d_delta(ar, vec, -32, 0);
+ else if(pandir == V3D_VIEW_PANLEFT) window_to_3d_delta(ar, vec, 32, 0);
+ else if(pandir == V3D_VIEW_PANUP) window_to_3d_delta(ar, vec, 0, -25);
+ else if(pandir == V3D_VIEW_PANDOWN) window_to_3d_delta(ar, vec, 0, 25);
+ rv3d->ofs[0]+= vec[0];
+ rv3d->ofs[1]+= vec[1];
+ rv3d->ofs[2]+= vec[2];
+
+ if(rv3d->viewlock & RV3D_BOXVIEW)
+ view3d_boxview_sync(CTX_wm_area(C), ar);
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_view_pan(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View Pan";
+ ot->description = "Pan the view.";
+ ot->idname= "VIEW3D_OT_view_pan";
+
+ /* api callbacks */
+ ot->exec= viewpan_exec;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+ RNA_def_enum(ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction of View Pan");
+}
+
+static int viewpersportho_exec(bContext *C, wmOperator *op)
+{
+ ARegion *ar= CTX_wm_region(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+
+ if(rv3d->viewlock==0) {
+ if(rv3d->persp!=V3D_ORTHO)
+ rv3d->persp=V3D_ORTHO;
+ else rv3d->persp=V3D_PERSP;
+ ED_region_tag_redraw(ar);
+ }
+
+ return OPERATOR_FINISHED;
+
+}
+
+void VIEW3D_OT_view_persportho(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View persp/ortho";
+ ot->description = "Switch the current view from perspective/orthographic.";
+ ot->idname= "VIEW3D_OT_view_persportho";
+
+ /* api callbacks */
+ ot->exec= viewpersportho_exec;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+
+/* ********************* set clipping operator ****************** */
+
+static int view3d_clipping_exec(bContext *C, wmOperator *op)
+{
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ rcti rect;
+ double mvmatrix[16];
+ double projmatrix[16];
+ double xs, ys, p[3];
+ GLint viewport[4];
+ short val;
+
+ rect.xmin= RNA_int_get(op->ptr, "xmin");
+ rect.ymin= RNA_int_get(op->ptr, "ymin");
+ rect.xmax= RNA_int_get(op->ptr, "xmax");
+ rect.ymax= RNA_int_get(op->ptr, "ymax");
+
+ rv3d->rflag |= RV3D_CLIPPING;
+ rv3d->clipbb= MEM_callocN(sizeof(BoundBox), "clipbb");
+
+ /* note; otherwise opengl won't work */
+ view3d_operator_needs_opengl(C);
+
+ /* Get the matrices needed for gluUnProject */
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
+ glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
+
+ /* near zero floating point values can give issues with gluUnProject
+ in side view on some implementations */
+ if(fabs(mvmatrix[0]) < 1e-6) mvmatrix[0]= 0.0;
+ if(fabs(mvmatrix[5]) < 1e-6) mvmatrix[5]= 0.0;
+
+ /* Set up viewport so that gluUnProject will give correct values */
+ viewport[0] = 0;
+ viewport[1] = 0;
+
+ /* four clipping planes and bounding volume */
+ /* first do the bounding volume */
+ for(val=0; val<4; val++) {
+
+ xs= (val==0||val==3)?rect.xmin:rect.xmax;
+ ys= (val==0||val==1)?rect.ymin:rect.ymax;
+
+ gluUnProject(xs, ys, 0.0, mvmatrix, projmatrix, viewport, &p[0], &p[1], &p[2]);
+ VECCOPY(rv3d->clipbb->vec[val], p);
+
+ gluUnProject(xs, ys, 1.0, mvmatrix, projmatrix, viewport, &p[0], &p[1], &p[2]);
+ VECCOPY(rv3d->clipbb->vec[4+val], p);
+ }
+
+ /* then plane equations */
+ for(val=0; val<4; val++) {
+
+ CalcNormFloat(rv3d->clipbb->vec[val], rv3d->clipbb->vec[val==3?0:val+1], rv3d->clipbb->vec[val+4],
+ rv3d->clip[val]);
+
+ rv3d->clip[val][3]= - rv3d->clip[val][0]*rv3d->clipbb->vec[val][0]
+ - rv3d->clip[val][1]*rv3d->clipbb->vec[val][1]
+ - rv3d->clip[val][2]*rv3d->clipbb->vec[val][2];
+ }
+ return OPERATOR_FINISHED;
+}
+
+static int view3d_clipping_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ ARegion *ar= CTX_wm_region(C);
+
+ if(rv3d->rflag & RV3D_CLIPPING) {
+ rv3d->rflag &= ~RV3D_CLIPPING;
+ ED_region_tag_redraw(ar);
+ if(rv3d->clipbb) MEM_freeN(rv3d->clipbb);
+ rv3d->clipbb= NULL;
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return WM_border_select_invoke(C, op, event);
+ }
+}
+
+/* toggles */
+void VIEW3D_OT_clipping(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Clipping Border";
+ ot->description = "Set the view clipping border.";
+ ot->idname= "VIEW3D_OT_clipping";
+
+ /* api callbacks */
+ ot->invoke= view3d_clipping_invoke;
+ ot->exec= view3d_clipping_exec;
+ ot->modal= WM_border_select_modal;
+
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* rna */
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+}
+
+/* ********************* draw type operator ****************** */
+
+static int view3d_drawtype_exec(bContext *C, wmOperator *op)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ int dt, dt_alt;
+
+ dt = RNA_int_get(op->ptr, "draw_type");
+ dt_alt = RNA_int_get(op->ptr, "draw_type_alternate");
+
+ if (dt_alt != -1) {
+ if (v3d->drawtype == dt)
+ v3d->drawtype = dt_alt;
+ else
+ v3d->drawtype = dt;
+ }
+ else
+ v3d->drawtype = dt;
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+static int view3d_drawtype_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ return view3d_drawtype_exec(C, op);
+}
+
+/* toggles */
+void VIEW3D_OT_drawtype(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Change draw type";
+ ot->description = "Change the draw type of the view.";
+ ot->idname= "VIEW3D_OT_drawtype";
+
+ /* api callbacks */
+ ot->invoke= view3d_drawtype_invoke;
+ ot->exec= view3d_drawtype_exec;
+
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* rna XXX should become enum */
+ RNA_def_int(ot->srna, "draw_type", 0, INT_MIN, INT_MAX, "Draw Type", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "draw_type_alternate", -1, INT_MIN, INT_MAX, "Draw Type Alternate", "", INT_MIN, INT_MAX);
+}
+
+/* ***************** 3d cursor cursor op ******************* */
+
+/* mx my in region coords */
+static int set_3dcursor_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Scene *scene= CTX_data_scene(C);
+ ARegion *ar= CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ float dx, dy, fz, *fp = NULL, dvec[3], oldcurs[3];
+ short mx, my, mval[2];
+// short ctrl= 0; // XXX
+
+ fp= give_cursor(scene, v3d);
+
+// if(obedit && ctrl) lr_click= 1;
+ VECCOPY(oldcurs, fp);
+
+ mx= event->x - ar->winrct.xmin;
+ my= event->y - ar->winrct.ymin;
+ project_short_noclip(ar, fp, mval);
+
+ initgrabz(rv3d, fp[0], fp[1], fp[2]);
+
+ if(mval[0]!=IS_CLIPPED) {
+
+ window_to_3d_delta(ar, dvec, mval[0]-mx, mval[1]-my);
+ VecSubf(fp, fp, dvec);
+ }
+ else {
+
+ dx= ((float)(mx-(ar->winx/2)))*rv3d->zfac/(ar->winx/2);
+ dy= ((float)(my-(ar->winy/2)))*rv3d->zfac/(ar->winy/2);
+
+ fz= rv3d->persmat[0][3]*fp[0]+ rv3d->persmat[1][3]*fp[1]+ rv3d->persmat[2][3]*fp[2]+ rv3d->persmat[3][3];
+ fz= fz/rv3d->zfac;
+
+ fp[0]= (rv3d->persinv[0][0]*dx + rv3d->persinv[1][0]*dy+ rv3d->persinv[2][0]*fz)-rv3d->ofs[0];
+ fp[1]= (rv3d->persinv[0][1]*dx + rv3d->persinv[1][1]*dy+ rv3d->persinv[2][1]*fz)-rv3d->ofs[1];
+ fp[2]= (rv3d->persinv[0][2]*dx + rv3d->persinv[1][2]*dy+ rv3d->persinv[2][2]*fz)-rv3d->ofs[2];
+ }
+
+// if(lr_click) {
+ // XXX if(obedit->type==OB_MESH) add_click_mesh();
+ // else if ELEM(obedit->type, OB_CURVE, OB_SURF) addvert_Nurb(0);
+ // else if (obedit->type==OB_ARMATURE) addvert_armature();
+// VECCOPY(fp, oldcurs);
+// }
+ // XXX notifier for scene */
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ /* prevent other mouse ops to fail */
+ return OPERATOR_PASS_THROUGH;
+}
+
+void VIEW3D_OT_cursor3d(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Set 3D Cursor";
+ ot->description = "Set the location of the 3D cursor.";
+ ot->idname= "VIEW3D_OT_cursor3d";
+
+ /* api callbacks */
+ ot->invoke= set_3dcursor_invoke;
+
+ ot->poll= ED_operator_view3d_active;
+
+ /* rna later */
+
+}
+
+
+/* ************************* below the line! *********************** */
+
+
+/* XXX todo Zooms in on a border drawn by the user */
+int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mouse_worldloc[3] ) //, float *autodist )
+{
+ RegionView3D *rv3d= ar->regiondata;
+ bglMats mats; /* ZBuffer depth vars */
+ rcti rect;
+ float depth, depth_close= MAXFLOAT;
+ int had_depth = 0;
+ double cent[2], p[3];
+ int xs, ys;
+
+ rect.xmax = mval[0] + 4;
+ rect.ymax = mval[1] + 4;
+
+ rect.xmin = mval[0] - 4;
+ rect.ymin = mval[1] - 4;
+
+ /* Get Z Depths, needed for perspective, nice for ortho */
+ bgl_get_mats(&mats);
+ draw_depth(scene, ar, v3d, NULL);
+
+ /* force updating */
+ if (rv3d->depths) {
+ had_depth = 1;
+ rv3d->depths->damaged = 1;
+ }
+
+ view3d_update_depths(ar, v3d);
+
+ /* Constrain rect to depth bounds */
+ if (rect.xmin < 0) rect.xmin = 0;
+ if (rect.ymin < 0) rect.ymin = 0;
+ if (rect.xmax >= rv3d->depths->w) rect.xmax = rv3d->depths->w-1;
+ if (rect.ymax >= rv3d->depths->h) rect.ymax = rv3d->depths->h-1;
+
+ /* Find the closest Z pixel */
+ for (xs=rect.xmin; xs < rect.xmax; xs++) {
+ for (ys=rect.ymin; ys < rect.ymax; ys++) {
+ depth= rv3d->depths->depths[ys*rv3d->depths->w+xs];
+ if(depth < rv3d->depths->depth_range[1] && depth > rv3d->depths->depth_range[0]) {
+ if (depth_close > depth) {
+ depth_close = depth;
+ }
+ }
+ }
+ }
+
+ if (depth_close==MAXFLOAT)
+ return 0;
+
+ if (had_depth==0) {
+ MEM_freeN(rv3d->depths->depths);
+ rv3d->depths->depths = NULL;
+ }
+ rv3d->depths->damaged = 1;
+
+ cent[0] = (double)mval[0];
+ cent[1] = (double)mval[1];
+
+ if (!gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2]))
+ return 0;
+
+ mouse_worldloc[0] = (float)p[0];
+ mouse_worldloc[1] = (float)p[1];
+ mouse_worldloc[2] = (float)p[2];
+ return 1;
+}
+
+
+
+/* ********************* NDOF ************************ */
+/* note: this code is confusing and unclear... (ton) */
+/* **************************************************** */
+
+// ndof scaling will be moved to user setting.
+// In the mean time this is just a place holder.
+
+// Note: scaling in the plugin and ghostwinlay.c
+// should be removed. With driver default setting,
+// each axis returns approx. +-200 max deflection.
+
+// The values I selected are based on the older
+// polling i/f. With event i/f, the sensistivity
+// can be increased for improved response from
+// small deflections of the device input.
+
+
+// lukep notes : i disagree on the range.
+// the normal 3Dconnection driver give +/-400
+// on defaut range in other applications
+// and up to +/- 1000 if set to maximum
+// because i remove the scaling by delta,
+// which was a bad idea as it depend of the system
+// speed and os, i changed the scaling values, but
+// those are still not ok
+
+
+float ndof_axis_scale[6] = {
+ +0.01, // Tx
+ +0.01, // Tz
+ +0.01, // Ty
+ +0.0015, // Rx
+ +0.0015, // Rz
+ +0.0015 // Ry
+};
+
+void filterNDOFvalues(float *sbval)
+{
+ int i=0;
+ float max = 0.0;
+
+ for (i =0; i<6;i++)
+ if (fabs(sbval[i]) > max)
+ max = fabs(sbval[i]);
+ for (i =0; i<6;i++)
+ if (fabs(sbval[i]) != max )
+ sbval[i]=0.0;
+}
+
+// statics for controlling rv3d->dist corrections.
+// viewmoveNDOF zeros and adjusts rv3d->ofs.
+// viewmove restores based on dz_flag state.
+
+int dz_flag = 0;
+float m_dist;
+
+void viewmoveNDOFfly(ARegion *ar, View3D *v3d, int mode)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ int i;
+ float phi;
+ float dval[7];
+ // static fval[6] for low pass filter; device input vector is dval[6]
+ static float fval[6];
+ float tvec[3],rvec[3];
+ float q1[4];
+ float mat[3][3];
+ float upvec[3];
+
+
+ /*----------------------------------------------------
+ * sometimes this routine is called from headerbuttons
+ * viewmove needs to refresh the screen
+ */
+// XXX areawinset(ar->win);
+
+
+ // fetch the current state of the ndof device
+// XXX getndof(dval);
+
+ if (v3d->ndoffilter)
+ filterNDOFvalues(fval);
+
+ // Scale input values
+
+// if(dval[6] == 0) return; // guard against divide by zero
+
+ for(i=0;i<6;i++) {
+
+ // user scaling
+ dval[i] = dval[i] * ndof_axis_scale[i];
+ }
+
+
+ // low pass filter with zero crossing reset
+
+ for(i=0;i<6;i++) {
+ if((dval[i] * fval[i]) >= 0)
+ dval[i] = (fval[i] * 15 + dval[i]) / 16;
+ else
+ fval[i] = 0;
+ }
+
+
+ // force perspective mode. This is a hack and is
+ // incomplete. It doesn't actually effect the view
+ // until the first draw and doesn't update the menu
+ // to reflect persp mode.
+
+ rv3d->persp = V3D_PERSP;
+
+
+ // Correct the distance jump if rv3d->dist != 0
+
+ // This is due to a side effect of the original
+ // mouse view rotation code. The rotation point is
+ // set a distance in front of the viewport to
+ // make rotating with the mouse look better.
+ // The distance effect is written at a low level
+ // in the view management instead of the mouse
+ // view function. This means that all other view
+ // movement devices must subtract this from their
+ // view transformations.
+
+ if(rv3d->dist != 0.0) {
+ dz_flag = 1;
+ m_dist = rv3d->dist;
+ upvec[0] = upvec[1] = 0;
+ upvec[2] = rv3d->dist;
+ Mat3CpyMat4(mat, rv3d->viewinv);
+ Mat3MulVecfl(mat, upvec);
+ VecSubf(rv3d->ofs, rv3d->ofs, upvec);
+ rv3d->dist = 0.0;
+ }
+
+
+ // Apply rotation
+ // Rotations feel relatively faster than translations only in fly mode, so
+ // we have no choice but to fix that here (not in the plugins)
+ rvec[0] = -0.5 * dval[3];
+ rvec[1] = -0.5 * dval[4];
+ rvec[2] = -0.5 * dval[5];
+
+ // rotate device x and y by view z
+
+ Mat3CpyMat4(mat, rv3d->viewinv);
+ mat[2][2] = 0.0f;
+ Mat3MulVecfl(mat, rvec);
+
+ // rotate the view
+
+ phi = Normalize(rvec);
+ if(phi != 0) {
+ VecRotToQuat(rvec,phi,q1);
+ QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
+ }
+
+
+ // Apply translation
+
+ tvec[0] = dval[0];
+ tvec[1] = dval[1];
+ tvec[2] = -dval[2];
+
+ // the next three lines rotate the x and y translation coordinates
+ // by the current z axis angle
+
+ Mat3CpyMat4(mat, rv3d->viewinv);
+ mat[2][2] = 0.0f;
+ Mat3MulVecfl(mat, tvec);
+
+ // translate the view
+
+ VecSubf(rv3d->ofs, rv3d->ofs, tvec);
+
+
+ /*----------------------------------------------------
+ * refresh the screen XXX
+ */
+
+ // update render preview window
+
+// XXX BIF_view3d_previewrender_signal(ar, PR_DBASE|PR_DISPRECT);
+}
+
+void viewmoveNDOF(Scene *scene, ARegion *ar, View3D *v3d, int mode)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ float fval[7];
+ float dvec[3];
+ float sbadjust = 1.0f;
+ float len;
+ short use_sel = 0;
+ Object *ob = OBACT;
+ float m[3][3];
+ float m_inv[3][3];
+ float xvec[3] = {1,0,0};
+ float yvec[3] = {0,-1,0};
+ float zvec[3] = {0,0,1};
+ float phi, si;
+ float q1[4];
+ float obofs[3];
+ float reverse;
+ //float diff[4];
+ float d, curareaX, curareaY;
+ float mat[3][3];
+ float upvec[3];
+
+ /* Sensitivity will control how fast the view rotates. The value was
+ * obtained experimentally by tweaking until the author didn't get dizzy watching.
+ * Perhaps this should be a configurable user parameter.
+ */
+ float psens = 0.005f * (float) U.ndof_pan; /* pan sensitivity */
+ float rsens = 0.005f * (float) U.ndof_rotate; /* rotate sensitivity */
+ float zsens = 0.3f; /* zoom sensitivity */
+
+ const float minZoom = -30.0f;
+ const float maxZoom = 300.0f;
+
+ //reset view type
+ rv3d->view = 0;
+//printf("passing here \n");
+//
+ if (scene->obedit==NULL && ob && !(ob->flag & OB_POSEMODE)) {
+ use_sel = 1;
+ }
+
+ if((dz_flag)||rv3d->dist==0) {
+ dz_flag = 0;
+ rv3d->dist = m_dist;
+ upvec[0] = upvec[1] = 0;
+ upvec[2] = rv3d->dist;
+ Mat3CpyMat4(mat, rv3d->viewinv);
+ Mat3MulVecfl(mat, upvec);
+ VecAddf(rv3d->ofs, rv3d->ofs, upvec);
+ }
+
+ /*----------------------------------------------------
+ * sometimes this routine is called from headerbuttons
+ * viewmove needs to refresh the screen
+ */
+// XXX areawinset(curarea->win);
+
+ /*----------------------------------------------------
+ * record how much time has passed. clamp at 10 Hz
+ * pretend the previous frame occured at the clamped time
+ */
+// now = PIL_check_seconds_timer();
+ // frametime = (now - prevTime);
+ // if (frametime > 0.1f){ /* if more than 1/10s */
+ // frametime = 1.0f/60.0; /* clamp at 1/60s so no jumps when starting to move */
+// }
+// prevTime = now;
+ // sbadjust *= 60 * frametime; /* normalize ndof device adjustments to 100Hz for framerate independence */
+
+ /* fetch the current state of the ndof device & enforce dominant mode if selected */
+// XXX getndof(fval);
+ if (v3d->ndoffilter)
+ filterNDOFvalues(fval);
+
+
+ // put scaling back here, was previously in ghostwinlay
+ fval[0] = fval[0] * (1.0f/600.0f);
+ fval[1] = fval[1] * (1.0f/600.0f);
+ fval[2] = fval[2] * (1.0f/1100.0f);
+ fval[3] = fval[3] * 0.00005f;
+ fval[4] =-fval[4] * 0.00005f;
+ fval[5] = fval[5] * 0.00005f;
+ fval[6] = fval[6] / 1000000.0f;
+
+ // scale more if not in perspective mode
+ if (rv3d->persp == V3D_ORTHO) {
+ fval[0] = fval[0] * 0.05f;
+ fval[1] = fval[1] * 0.05f;
+ fval[2] = fval[2] * 0.05f;
+ fval[3] = fval[3] * 0.9f;
+ fval[4] = fval[4] * 0.9f;
+ fval[5] = fval[5] * 0.9f;
+ zsens *= 8;
+ }
+
+ /* set object offset */
+ if (ob) {
+ obofs[0] = -ob->obmat[3][0];
+ obofs[1] = -ob->obmat[3][1];
+ obofs[2] = -ob->obmat[3][2];
+ }
+ else {
+ VECCOPY(obofs, rv3d->ofs);
+ }
+
+ /* calc an adjustment based on distance from camera
+ disabled per patch 14402 */
+ d = 1.0f;
+
+/* if (ob) {
+ VecSubf(diff, obofs, rv3d->ofs);
+ d = VecLength(diff);
+ }
+*/
+
+ reverse = (rv3d->persmat[2][1] < 0.0f) ? -1.0f : 1.0f;
+
+ /*----------------------------------------------------
+ * ndof device pan
+ */
+ psens *= 1.0f + d;
+ curareaX = sbadjust * psens * fval[0];
+ curareaY = sbadjust * psens * fval[1];
+ dvec[0] = curareaX * rv3d->persinv[0][0] + curareaY * rv3d->persinv[1][0];
+ dvec[1] = curareaX * rv3d->persinv[0][1] + curareaY * rv3d->persinv[1][1];
+ dvec[2] = curareaX * rv3d->persinv[0][2] + curareaY * rv3d->persinv[1][2];
+ VecAddf(rv3d->ofs, rv3d->ofs, dvec);
+
+ /*----------------------------------------------------
+ * ndof device dolly
+ */
+ len = zsens * sbadjust * fval[2];
+
+ if (rv3d->persp==V3D_CAMOB) {
+ if(rv3d->persp==V3D_CAMOB) { /* This is stupid, please fix - TODO */
+ rv3d->camzoom+= 10.0f * -len;
+ }
+ if (rv3d->camzoom < minZoom) rv3d->camzoom = minZoom;
+ else if (rv3d->camzoom > maxZoom) rv3d->camzoom = maxZoom;
+ }
+ else if ((rv3d->dist> 0.001*v3d->grid) && (rv3d->dist<10.0*v3d->far)) {
+ rv3d->dist*=(1.0 + len);
+ }
+
+
+ /*----------------------------------------------------
+ * ndof device turntable
+ * derived from the turntable code in viewmove
+ */
+
+ /* Get the 3x3 matrix and its inverse from the quaternion */
+ QuatToMat3(rv3d->viewquat, m);
+ Mat3Inv(m_inv,m);
+
+ /* Determine the direction of the x vector (for rotating up and down) */
+ /* This can likely be compuated directly from the quaternion. */
+ Mat3MulVecfl(m_inv,xvec);
+ Mat3MulVecfl(m_inv,yvec);
+ Mat3MulVecfl(m_inv,zvec);
+
+ /* Perform the up/down rotation */
+ phi = sbadjust * rsens * /*0.5f * */ fval[3]; /* spin vertically half as fast as horizontally */
+ si = sin(phi);
+ q1[0] = cos(phi);
+ q1[1] = si * xvec[0];
+ q1[2] = si * xvec[1];
+ q1[3] = si * xvec[2];
+ QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
+
+ if (use_sel) {
+ QuatConj(q1); /* conj == inv for unit quat */
+ VecSubf(v3d->ofs, v3d->ofs, obofs);
+ QuatMulVecf(q1, rv3d->ofs);
+ VecAddf(rv3d->ofs, rv3d->ofs, obofs);
+ }
+
+ /* Perform the orbital rotation */
+ /* Perform the orbital rotation
+ If the seen Up axis is parallel to the zoom axis, rotation should be
+ achieved with a pure Roll motion (no Spin) on the device. When you start
+ to tilt, moving from Top to Side view, Spinning will increasingly become
+ more relevant while the Roll component will decrease. When a full
+ Side view is reached, rotations around the world's Up axis are achieved
+ with a pure Spin-only motion. In other words the control of the spinning
+ around the world's Up axis should move from the device's Spin axis to the
+ device's Roll axis depending on the orientation of the world's Up axis
+ relative to the screen. */
+ //phi = sbadjust * rsens * reverse * fval[4]; /* spin the knob, y axis */
+ phi = sbadjust * rsens * (yvec[2] * fval[4] + zvec[2] * fval[5]);
+ q1[0] = cos(phi);
+ q1[1] = q1[2] = 0.0;
+ q1[3] = sin(phi);
+ QuatMul(rv3d->viewquat, rv3d->viewquat, q1);
+
+ if (use_sel) {
+ QuatConj(q1);
+ VecSubf(rv3d->ofs, rv3d->ofs, obofs);
+ QuatMulVecf(q1, rv3d->ofs);
+ VecAddf(rv3d->ofs, rv3d->ofs, obofs);
+ }
+
+ /*----------------------------------------------------
+ * refresh the screen
+ */
+// XXX scrarea_do_windraw(curarea);
+}
+
+
+
+
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
new file mode 100644
index 00000000000..36490650415
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -0,0 +1,5581 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004-2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "DNA_armature_types.h"
+#include "DNA_ID.h"
+#include "DNA_image_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_userdef_types.h" /* U.smooth_viewtx */
+#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_access.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_action.h"
+#include "BKE_brush.h"
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_displist.h"
+#include "BKE_effect.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_particle.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h" /* for VECCOPY */
+
+#include "ED_armature.h"
+#include "ED_particle.h"
+#include "ED_object.h"
+#include "ED_mesh.h"
+#include "ED_util.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+#include "BIF_transform.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "BMF_Api.h"
+
+#include "view3d_intern.h"
+
+
+/* View3d->modeselect
+ * This is a bit of a dodgy hack to enable a 'mode' menu with icons+labels
+ * rather than those buttons.
+ * I know the implementation's not good - it's an experiment to see if this
+ * approach would work well
+ *
+ * This can be cleaned when I make some new 'mode' icons.
+ */
+
+#define V3D_OBJECTMODE_SEL ICON_OBJECT_DATA
+#define V3D_EDITMODE_SEL ICON_EDITMODE_HLT
+#define V3D_SCULPTMODE_SEL ICON_SCULPTMODE_HLT
+#define V3D_FACESELECT_SEL ICON_FACESEL_HLT /* this is not a mode anymore - just a switch */
+#define V3D_VERTEXPAINTMODE_SEL ICON_VPAINT_HLT
+#define V3D_TEXTUREPAINTMODE_SEL ICON_TPAINT_HLT
+#define V3D_WEIGHTPAINTMODE_SEL ICON_WPAINT_HLT
+#define V3D_POSEMODE_SEL ICON_POSE_HLT
+#define V3D_PARTICLEEDITMODE_SEL ICON_ANIM
+
+#define TEST_EDITMESH if(obedit==0) return; \
+ if( (v3d->lay & obedit->lay)==0 ) return;
+
+/* XXX port over */
+static void handle_view3d_lock(void) {}
+static void countall(void) {}
+extern void borderselect();
+static int retopo_mesh_paint_check() {return 0;}
+
+/* view3d handler codes */
+#define VIEW3D_HANDLER_BACKGROUND 1
+#define VIEW3D_HANDLER_PROPERTIES 2
+#define VIEW3D_HANDLER_OBJECT 3
+#define VIEW3D_HANDLER_PREVIEW 4
+#define VIEW3D_HANDLER_MULTIRES 5
+#define VIEW3D_HANDLER_TRANSFORM 6
+#define VIEW3D_HANDLER_GREASEPENCIL 7
+#define VIEW3D_HANDLER_BONESKETCH 8
+
+/* end XXX ************* */
+
+
+/* well... in this file a lot of view mode manipulation happens, so let's have it defined here */
+void ED_view3d_exit_paint_modes(bContext *C)
+{
+ if(G.f & G_TEXTUREPAINT)
+ WM_operator_name_call(C, "PAINT_OT_texture_paint_toggle", WM_OP_EXEC_REGION_WIN, NULL);
+ if(G.f & G_VERTEXPAINT)
+ WM_operator_name_call(C, "PAINT_OT_vertex_paint_toggle", WM_OP_EXEC_REGION_WIN, NULL);
+ else if(G.f & G_WEIGHTPAINT)
+ WM_operator_name_call(C, "PAINT_OT_weight_paint_toggle", WM_OP_EXEC_REGION_WIN, NULL);
+
+ if(G.f & G_SCULPTMODE)
+ WM_operator_name_call(C, "SCULPT_OT_sculptmode_toggle", WM_OP_EXEC_REGION_WIN, NULL);
+ if(G.f & G_PARTICLEEDIT)
+ WM_operator_name_call(C, "PARTICLE_OT_particle_edit_toggle", WM_OP_EXEC_REGION_WIN, NULL);
+
+ G.f &= ~(G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT+G_SCULPTMODE+G_PARTICLEEDIT);
+}
+
+
+
+
+
+static void do_view3d_header_buttons(bContext *C, void *arg, int event);
+
+#define B_SCENELOCK 101
+#define B_FULL 102
+#define B_HOME 103
+#define B_VIEWBUT 104
+#define B_PERSP 105
+#define B_VIEWRENDER 106
+#define B_STARTGAME 107
+#define B_MODESELECT 108
+#define B_AROUND 109
+#define B_SEL_VERT 110
+#define B_SEL_EDGE 111
+#define B_SEL_FACE 112
+#define B_SEL_PATH 113
+#define B_SEL_POINT 114
+#define B_SEL_END 115
+#define B_MAN_TRANS 116
+#define B_MAN_ROT 117
+#define B_MAN_SCALE 118
+#define B_NDOF 119
+#define B_MAN_MODE 120
+#define B_VIEW_BUTSEDIT 121
+#define B_REDR 122
+#define B_NOP 123
+#define B_ACTCOPY 124
+#define B_ACTPASTE 125
+#define B_ACTPASTEFLIP 126
+
+#define B_LAY 201
+
+
+static RegionView3D *wm_region_view3d(const bContext *C)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar;
+ /* XXX handle foursplit? */
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ if(ar->regiontype==RGN_TYPE_WINDOW)
+ return ar->regiondata;
+ return NULL;
+}
+
+/* XXX; all this context stuff... should become operator */
+void do_layer_buttons(bContext *C, short event)
+{
+ wmWindow *win= CTX_wm_window(C);
+ Scene *scene= CTX_data_scene(C);
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= sa->spacedata.first;
+ static int oldlay= 1;
+ short shift, alt, ctrl;
+
+ shift= win->eventstate->shift;
+ alt= win->eventstate->alt;
+ ctrl= win->eventstate->ctrl;
+
+ if(v3d==0) return;
+ if(v3d->localview) return;
+
+ if(event==-1 && ctrl) {
+ v3d->scenelock= !v3d->scenelock;
+ do_view3d_header_buttons(C, NULL, B_SCENELOCK);
+ } else if (event<0) {
+ if(v3d->lay== (1<<20)-1) {
+ if(event==-2 || shift) v3d->lay= oldlay;
+ }
+ else {
+ oldlay= v3d->lay;
+ v3d->lay= (1<<20)-1;
+ }
+
+ if(v3d->scenelock) handle_view3d_lock();
+
+ /* new layers might need unflushed events events */
+ DAG_scene_update_flags(scene, v3d->lay); /* tags all that moves and flushes */
+ }
+ else {
+ if(alt) {
+ if(event<11) event+= 10;
+ }
+ if(shift) {
+ if(v3d->lay & (1<<event)) v3d->lay -= (1<<event);
+ else v3d->lay += (1<<event);
+ }
+ do_view3d_header_buttons(C, NULL, event+B_LAY);
+ }
+ ED_area_tag_redraw(sa);
+
+ if(v3d->drawtype == OB_SHADED) reshadeall_displist(scene);
+}
+
+static int layers_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= sa->spacedata.first;
+ int nr= RNA_int_get(op->ptr, "nr");
+
+ if(nr<=0)
+ return OPERATOR_CANCELLED;
+ nr--;
+
+ if(RNA_boolean_get(op->ptr, "extend"))
+ v3d->lay |= (1<<nr);
+ else
+ v3d->lay = (1<<nr);
+
+ if(v3d->scenelock) handle_view3d_lock();
+
+ /* new layers might need unflushed events events */
+ DAG_scene_update_flags(scene, v3d->lay); /* tags all that moves and flushes */
+
+ ED_area_tag_redraw(sa);
+
+ return OPERATOR_FINISHED;
+}
+
+/* applies shift and alt, lazy coding or ok? :) */
+/* the local per-keymap-entry keymap will solve it */
+static int layers_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ if(event->ctrl || event->oskey)
+ return OPERATOR_PASS_THROUGH;
+
+ if(event->shift)
+ RNA_boolean_set(op->ptr, "extend", 1);
+
+ if(event->alt) {
+ int nr= RNA_int_get(op->ptr, "nr") + 10;
+ RNA_int_set(op->ptr, "nr", nr);
+ }
+ layers_exec(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_layers(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Layers";
+ ot->idname= "VIEW3D_OT_layers";
+
+ /* api callbacks */
+ ot->invoke= layers_invoke;
+ ot->exec= layers_exec;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "nr", 1, 0, 20, "Number", "", 0, 20);
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "");
+}
+
+
+#if 0
+static void do_view3d_view_camerasmenu(bContext *C, void *arg, int event)
+{
+ Scene *scene= CTX_data_scene(C);
+ Base *base;
+ int i=1;
+
+ if (event == 1) {
+ /* Set Active Object as Active Camera */
+ /* XXX ugly hack alert */
+// G.qual |= LR_CTRLKEY;
+// persptoetsen(PAD0);
+// G.qual &= ~LR_CTRLKEY;
+ } else {
+
+ for( base = FIRSTBASE; base; base = base->next ) {
+ if (base->object->type == OB_CAMERA) {
+ i++;
+
+ if (event==i) {
+ /* XXX use api call! */
+
+ break;
+ }
+ }
+ }
+ }
+
+}
+
+
+static uiBlock *view3d_view_camerasmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ Scene *scene= CTX_data_scene(C);
+ Base *base;
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+ int i=1;
+ char camname[48];
+
+ block= uiBeginBlock(C, ar, "view3d_view_camerasmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_view_camerasmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Active Object as Active Camera|Ctrl NumPad 0", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, 140, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ for( base = FIRSTBASE; base; base = base->next ) {
+ if (base->object->type == OB_CAMERA) {
+ i++;
+
+ strcpy(camname, base->object->id.name+2);
+ if (base->object == scene->camera) strcat(camname, " (Active)");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, camname, 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, i, "");
+ }
+ }
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+#endif
+
+#if 0
+static void do_view3d_view_cameracontrolsmenu(bContext *C, void *arg, int event)
+{
+ switch(event) {
+ case 0: /* Orbit Left */
+ persptoetsen(PAD4);
+ break;
+ case 1: /* Orbit Right */
+ persptoetsen(PAD6);
+ break;
+ case 2: /* Orbit Up */
+ persptoetsen(PAD8);
+ break;
+ case 3: /* Orbit Down */
+ persptoetsen(PAD2);
+ break;
+ case 4: /* Pan left */
+ /* XXX ugly hack alert */
+// G.qual |= LR_CTRLKEY;
+ persptoetsen(PAD4);
+// G.qual &= ~LR_CTRLKEY;
+ break;
+ case 5: /* Pan right */
+ /* XXX ugly hack alert */
+// G.qual |= LR_CTRLKEY;
+ persptoetsen(PAD6);
+// G.qual &= ~LR_CTRLKEY;
+ break;
+ case 6: /* Pan up */
+ /* ugly hack alert */
+// G.qual |= LR_CTRLKEY;
+ persptoetsen(PAD8);
+// G.qual &= ~LR_CTRLKEY;
+ break;
+ case 7: /* Pan down */
+ /* ugly hack alert */
+// G.qual |= LR_CTRLKEY;
+ persptoetsen(PAD2);
+// G.qual &= ~LR_CTRLKEY;
+ break;
+ case 8: /* Zoom In */
+ persptoetsen(PADPLUSKEY);
+ break;
+ case 9: /* Zoom Out */
+ persptoetsen(PADMINUS);
+ break;
+ case 10: /* Reset Zoom */
+ persptoetsen(PADENTER);
+ break;
+ case 11: /* Camera Fly mode */
+ fly();
+ break;
+ }
+}
+
+
+static uiBlock *view3d_view_cameracontrolsmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+/* static short tog=0; */
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_view_cameracontrolsmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_view_cameracontrolsmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Camera Fly Mode|Shift F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, 140, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Orbit Left|NumPad 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Orbit Right|NumPad 6", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Orbit Up|NumPad 8", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Orbit Down|NumPad 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, 140, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Pan Left|Ctrl NumPad 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Pan Right|Ctrl NumPad 6", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Pan Up|Ctrl NumPad 8", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Pan Down|Ctrl NumPad 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, 140, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom In|NumPad +", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom Out|NumPad -", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Zoom|NumPad Enter", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 10, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+static void do_view3d_view_alignviewmenu(bContext *C, void *arg, int event)
+{
+ Scene *scene= CTX_data_scene(C);
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= sa->spacedata.first;
+ Object *obedit = CTX_data_edit_object(C);
+ float *curs;
+
+ switch(event) {
+
+ case 0: /* Align View to Selected (edit/faceselect mode) */
+ case 1:
+ case 2:
+ if ((obedit) && (obedit->type == OB_MESH)) {
+ editmesh_align_view_to_selected(v3d, event + 1);
+ }
+ else if (FACESEL_PAINT_TEST) {
+ Object *obact= OBACT;
+ if (obact && obact->type==OB_MESH) {
+ Mesh *me= obact->data;
+
+ if (me->mtface) {
+// XXX faceselect_align_view_to_selected(v3d, me, event + 1);
+ ED_area_tag_redraw(sa);
+ }
+ }
+ }
+ break;
+ case 3: /* Center View to Cursor */
+ curs= give_cursor(scene, v3d);
+ v3d->ofs[0]= -curs[0];
+ v3d->ofs[1]= -curs[1];
+ v3d->ofs[2]= -curs[2];
+ ED_area_tag_redraw(sa);
+ break;
+ case 4: /* Align Active Camera to View */
+ /* XXX This ugly hack is a symptom of the nasty persptoetsen function,
+ * but at least it works for now.
+ */
+// G.qual |= LR_CTRLKEY|LR_ALTKEY;
+ persptoetsen(PAD0);
+// G.qual &= ~(LR_CTRLKEY|LR_ALTKEY);
+ break;
+ case 5: /* Align View to Selected (object mode) */
+// XXX mainqenter(PADASTERKEY, 1);
+ break;
+ case 6: /* Center View and Cursor to Origin */
+ WM_operator_name_call(C, "VIEW3D_OT_viewcenter", WM_OP_EXEC_REGION_WIN, NULL);
+ curs= give_cursor(scene, v3d);
+ curs[0]=curs[1]=curs[2]= 0.0;
+ break;
+ }
+}
+
+static uiBlock *view3d_view_alignviewmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+/* static short tog=0; */
+ uiBlock *block;
+ Object *obedit = CTX_data_edit_object(C);
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_view_alignviewmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_view_alignviewmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Center View to Cursor|C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Center Cursor and View All|Shift C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Align Active Camera to View|Ctrl Alt NumPad 0", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
+
+ if (((obedit) && (obedit->type == OB_MESH)) || (FACESEL_PAINT_TEST)) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Align View to Selected (Top)|Shift V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Align View to Selected (Front)|Shift V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Align View to Selected (Side)|Shift V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
+ } else {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Align View to Selected|NumPad *", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
+ }
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+#endif
+
+#if 0
+static uiBlock *view3d_view_spacehandlers(bContext *C, ARegion *ar, void *arg_unused)
+{
+ /* XXX */
+ return NULL;
+}
+
+
+static void do_view3d_viewmenu(bContext *C, void *arg, int event)
+{
+
+ switch(event) {
+ case 0: /* User */
+ break;
+ case 1: /* Camera */
+ break;
+ case 2: /* Top */
+ break;
+ case 3: /* Front */
+ break;
+ case 4: /* Side */
+ break;
+ case 5: /* Perspective */
+ break;
+ case 6: /* Orthographic */
+ break;
+ case 7: /* Local View */
+ break;
+ case 8: /* Global View */
+ break;
+ case 9: /* View All (Home) */
+ WM_operator_name_call(C, "VIEW3D_OT_viewhome", WM_OP_EXEC_REGION_WIN, NULL);
+ break;
+ case 11: /* View Selected */
+ WM_operator_name_call(C, "VIEW3D_OT_viewcenter", WM_OP_EXEC_REGION_WIN, NULL);
+ break;
+ case 13: /* Play Back Animation */
+ break;
+ case 15: /* Background Image... */
+// add_blockhandler(sa, VIEW3D_HANDLER_BACKGROUND, UI_PNL_UNSTOW);
+ break;
+ case 16: /* View Panel */
+// add_blockhandler(sa, VIEW3D_HANDLER_PROPERTIES, UI_PNL_UNSTOW);
+ break;
+ case 17: /* Set Clipping Border */
+ WM_operator_name_call(C, "VIEW3D_OT_clipping", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ case 18: /* render preview */
+// toggle_blockhandler(sa, VIEW3D_HANDLER_PREVIEW, 0);
+ break;
+ case 19: /* zoom within border */
+// view3d_border_zoom();
+ break;
+ case 20: /* Transform Space Panel */
+// add_blockhandler(sa, VIEW3D_HANDLER_TRANSFORM, UI_PNL_UNSTOW);
+ break;
+ case 21: /* Grease Pencil */
+// add_blockhandler(sa, VIEW3D_HANDLER_GREASEPENCIL, UI_PNL_UNSTOW);
+ break;
+ case 22: /* View all layers */
+ do_layer_buttons(C, -2);
+ break;
+ }
+}
+#endif
+
+static void view3d_view_viewnavmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+// uiMenuItemO(head, 0, "VIEW3D_OT_view_fly_mode");
+
+// uiMenuSeparator(head);
+
+ uiMenuItemsEnumO(head, "VIEW3D_OT_view_orbit", "type");
+
+ uiMenuSeparator(head);
+
+ uiMenuItemsEnumO(head, "VIEW3D_OT_view_pan", "type");
+
+ uiMenuSeparator(head);
+
+ uiMenuItemFloatO(head, "Zoom in", 0, "VIEW3D_OT_zoom", "delta", 1.0f);
+ uiMenuItemFloatO(head, "Zoom out", 0, "VIEW3D_OT_zoom", "delta", -1.0f);
+
+}
+static void view3d_view_alignviewmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+
+}
+
+static void view3d_viewmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ ScrArea *sa= CTX_wm_area(C);
+
+// uiMenuItemO(head, ICON_MENU_PANEL, "VIEW3D_OT_toggle_transform_orientations_panel"); // Transform Orientations...
+// uiMenuItemO(head, ICON_MENU_PANEL, "VIEW3D_OT_toggle_render_preview_panel"); // render preview...
+// uiMenuItemO(head, ICON_MENU_PANEL, "VIEW3D_OT_toggle_view_properties_panel"); // View Properties....
+// uiMenuItemO(head, ICON_MENU_PANEL, "VIEW3D_OT_toggle_background_image_panel"); // Background Image....
+// uiMenuItemO(head, ICON_MENU_PANEL, "VIEW3D_OT_toggle_grease_pencil_panel"); // Grease Pencil....
+
+// uiMenuSeparator(head);
+
+ uiMenuItemEnumO(head, "", 0, "VIEW3D_OT_viewnumpad", "type", V3D_VIEW_CAMERA);
+ uiMenuItemEnumO(head, "", 0, "VIEW3D_OT_viewnumpad", "type", V3D_VIEW_TOP);
+ uiMenuItemEnumO(head, "", 0, "VIEW3D_OT_viewnumpad", "type", V3D_VIEW_FRONT);
+ uiMenuItemEnumO(head, "", 0, "VIEW3D_OT_viewnumpad", "type", V3D_VIEW_RIGHT);
+
+ //uiMenuLevel(head, "Cameras", view3d_view_camerasmenu);
+
+ uiMenuSeparator(head);
+
+ uiMenuItemO(head, 0, "VIEW3D_OT_view_persportho");
+
+ uiMenuSeparator(head);
+
+// uiMenuItemO(head, 0, "VIEW3D_OT_view_show_all_layers");
+
+// uiMenuSeparator(head);
+
+// uiMenuItemO(head, 0, "VIEW3D_OT_view_local_view");
+// uiMenuItemO(head, 0, "VIEW3D_OT_view_global_view");
+
+// uiMenuSeparator(head);
+
+ uiMenuLevel(head, "View Navigation", view3d_view_viewnavmenu);
+ uiMenuLevel(head, "Align View", view3d_view_alignviewmenu);
+
+ uiMenuSeparator(head);
+
+ uiMenuContext(head, WM_OP_INVOKE_REGION_WIN);
+
+ uiMenuItemO(head, 0, "VIEW3D_OT_clipping");
+ uiMenuItemO(head, 0, "VIEW3D_OT_zoom_border");
+
+ uiMenuSeparator(head);
+
+ uiMenuItemO(head, 0, "VIEW3D_OT_viewcenter");
+ uiMenuItemO(head, 0, "VIEW3D_OT_viewhome");
+
+ uiMenuSeparator(head);
+
+ if(sa->full) uiMenuItemO(head, 0, "SCREEN_OT_screen_full_area"); // "Tile Window", Ctrl UpArrow
+ else uiMenuItemO(head, 0, "SCREEN_OT_screen_full_area"); // "Maximize Window", Ctr DownArrow
+}
+#if 0
+static uiBlock *view3d_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= sa->spacedata.first;
+ RegionView3D *rv3d= wm_region_view3d(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_viewmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_viewmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Transform Orientations...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 20, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Render Preview...|Shift P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 18, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "View Properties...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 16, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Background Image...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 15, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Grease Pencil...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 21, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if ((rv3d->viewbut == 0) && !(rv3d->persp == V3D_CAMOB)) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "User", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "User", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
+ if (rv3d->persp == V3D_CAMOB) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Camera|NumPad 0", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Camera|NumPad 0", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
+ if (rv3d->viewbut == 1) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Top|NumPad 7", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Top|NumPad 7", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
+ if (rv3d->viewbut == 2) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Front|NumPad 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Front|NumPad 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
+ if (rv3d->viewbut == 3) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Side|NumPad 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Side|NumPad 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
+
+ uiDefIconTextBlockBut(block, view3d_view_camerasmenu, NULL, ICON_RIGHTARROW_THIN, "Cameras", 0, yco-=20, 120, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if(rv3d->persp==V3D_PERSP) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Perspective|NumPad 5", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Perspective|NumPad 5", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
+ if(rv3d->persp==V3D_ORTHO) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Orthographic|NumPad 5", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Orthographic|NumPad 5", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if(v3d->lay== (1<<20)-1) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Previous Layers|Shift ~", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 22, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show All Layers| ~", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 22, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if(v3d->localview) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Local View|NumPad /", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Local View|NumPad /", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
+ if(!v3d->localview) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Global View|NumPad /", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Global View|NumPad /", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBlockBut(block, view3d_view_cameracontrolsmenu, NULL, ICON_RIGHTARROW_THIN, "View Navigation", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_view_alignviewmenu, NULL, ICON_RIGHTARROW_THIN, "Align View", 0, yco-=20, 120, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if(rv3d->rflag & RV3D_CLIPPING)
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Clipping Border|Alt B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 17, "");
+ else
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Clipping Border|Alt B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 17, "");
+ if (rv3d->persp==V3D_ORTHO) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom Within Border...|Shift B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 19, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View Selected|NumPad .", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View All|Home", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, "");
+ if(!sa->full) uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 99, "");
+ else uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 99, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Play Back Animation|Alt A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 13, "");
+
+#ifndef DISABLE_PYTHON
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIconTextBlockBut(block, view3d_view_spacehandlers, NULL, ICON_RIGHTARROW_THIN, "Space Handler Scripts", 0, yco-=20, 120, 19, "");
+#endif
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+
+ return block;
+}
+#endif
+
+#if 0
+void do_view3d_select_object_typemenu(bContext *C, void *arg, int event)
+{
+
+ extern void selectall_type(short obtype);
+
+ switch(event) {
+ case 1: /* Mesh */
+ selectall_type(OB_MESH);
+ break;
+ case 2: /* Curve */
+ selectall_type(OB_CURVE);
+ break;
+ case 3: /* Surface */
+ selectall_type(OB_SURF);
+ break;
+ case 4: /* Meta */
+ selectall_type(OB_MBALL);
+ break;
+ case 5: /* Armature */
+ selectall_type(OB_ARMATURE);
+ break;
+ case 6: /* Lattice */
+ selectall_type(OB_LATTICE);
+ break;
+ case 7: /* Text */
+ selectall_type(OB_FONT);
+ break;
+ case 8: /* Empty */
+ selectall_type(OB_EMPTY);
+ break;
+ case 9: /* Camera */
+ selectall_type(OB_CAMERA);
+ break;
+ case 10: /* Lamp */
+ selectall_type(OB_LAMP);
+ break;
+ case 20:
+ do_layer_buttons(C, -2);
+ break;
+ }
+}
+
+static uiBlock *view3d_select_object_typemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_select_object_typemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_select_object_typemenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Mesh", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Curve", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Surface", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Meta", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Armature", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Lattice", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Text", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Empty", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Camera", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Lamp", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+
+void do_view3d_select_object_layermenu(bContext *C, void *arg, int event)
+{
+// XXX extern void selectall_layer(unsigned int layernum);
+
+ switch(event) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ case 20:
+// XXX selectall_layer(event);
+ break;
+ }
+}
+
+static uiBlock *view3d_select_object_layermenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short xco= 0, yco = 20, menuwidth = 22;
+
+ block= uiBeginBlock(C, ar, "view3d_select_object_layermenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_select_object_layermenu, NULL);
+
+ uiDefBut(block, BUTM, 1, "1", xco, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefBut(block, BUTM, 1, "2", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefBut(block, BUTM, 1, "3", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefBut(block, BUTM, 1, "4", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefBut(block, BUTM, 1, "5", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ xco += 6;
+ uiDefBut(block, BUTM, 1, "6", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+ uiDefBut(block, BUTM, 1, "7", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+ uiDefBut(block, BUTM, 1, "8", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
+ uiDefBut(block, BUTM, 1, "9", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
+ uiDefBut(block, BUTM, 1, "10", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
+ xco = 0;
+ uiDefBut(block, BUTM, 1, "11", xco, yco-=24, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
+ uiDefBut(block, BUTM, 1, "12", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
+ uiDefBut(block, BUTM, 1, "13", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+ uiDefBut(block, BUTM, 1, "14", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, "");
+ uiDefBut(block, BUTM, 1, "15", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
+ xco += 6;
+ uiDefBut(block, BUTM, 1, "16", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, "");
+ uiDefBut(block, BUTM, 1, "17", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, "");
+ uiDefBut(block, BUTM, 1, "18", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, "");
+ uiDefBut(block, BUTM, 1, "19", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, "");
+ uiDefBut(block, BUTM, 1, "20", xco+=(menuwidth+1), yco, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ /*uiTextBoundsBlock(block, 100);*/
+ return block;
+}
+
+void do_view3d_select_object_linkedmenu(bContext *C, void *arg, int event)
+{
+ switch(event) {
+ case 1: /* Object Ipo */
+ case 2: /* ObData */
+ case 3: /* Current Material */
+ case 4: /* Current Texture */
+ selectlinks(event);
+ break;
+ }
+ countall();
+}
+
+static uiBlock *view3d_select_object_linkedmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_select_object_linkedmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_select_object_linkedmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Object Ipo|Shift L, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "ObData|Shift L, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Material|Shift L, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Texture|Shift L, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+void do_view3d_select_object_groupedmenu(bContext *C, void *arg, int event)
+{
+
+ switch(event) {
+ case 1: /* Children */
+ case 2: /* Immediate Children */
+ case 3: /* Parent */
+ case 4: /* Siblings */
+ case 5: /* Type */
+ case 6: /* Objects on Shared Layers */
+ case 7: /* Objects in Same Group */
+ case 8: /* Object Hooks*/
+ case 9: /* Object PassIndex*/
+ case 10: /* Object Color*/
+ case 11: /* Game Properties*/
+ select_object_grouped((short)event);
+ break;
+ }
+}
+
+static uiBlock *view3d_select_object_groupedmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_select_object_groupedmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_select_object_groupedmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Children|Shift G, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Immediate Children|Shift G, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Parent|Shift G, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Siblings (Shared Parent)|Shift G, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Objects of Same Type|Shift G, 5", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Objects on Shared Layers|Shift G, 6", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Objects in Same Group|Shift G, 7", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Object Hooks|Shift G, 8", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Object PassIndex|Shift G, 9", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Object Color|Shift G, 0", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Game Properties|Shift G, Alt+1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+#endif
+
+static uiBlock *view3d_select_objectmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+// short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_select_objectmenu", UI_EMBOSSP);
+
+#if 0
+ uiBlockSetButmFunc(block, do_view3d_select_objectmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Border Select|B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Inverse|Ctrl I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Random", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiDefIconTextBlockBut(block, view3d_select_object_layermenu, NULL, ICON_RIGHTARROW_THIN, "Select All by Layer", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_select_object_typemenu, NULL, ICON_RIGHTARROW_THIN, "Select All by Type", 0, yco-=20, 120, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBlockBut(block, view3d_select_object_linkedmenu, NULL, ICON_RIGHTARROW_THIN, "Linked", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_select_object_groupedmenu, NULL, ICON_RIGHTARROW_THIN, "Grouped", 0, yco-=20, 120, 19, "");
+#endif
+ uiDefMenuButO(block, "VIEW3D_OT_select_border", "Border Select");
+
+ uiDefMenuSep(block);
+
+ uiDefMenuButO(block, "OBJECT_OT_select_all_toggle", "Select/Deselect All");
+ uiDefMenuButO(block, "OBJECT_OT_select_invert", "Inverse");
+ uiDefMenuButO(block, "OBJECT_OT_select_random", "Random");
+ uiDefMenuButO(block, "OBJECT_OT_select_by_layer", "Select All by Layer");
+ uiDefMenuButO(block, "OBJECT_OT_select_by_type", "Select All by Type");
+
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+void do_view3d_select_meshmenu(bContext *C, void *arg, int event)
+{
+#if 0
+/* extern void borderselect(void);*/
+
+ switch(event) {
+
+ case 0: /* border select */
+ borderselect();
+ break;
+ case 2: /* Select/Deselect all */
+ deselectall_mesh();
+ break;
+ case 3: /* Inverse */
+ selectswap_mesh();
+ break;
+ case 4: /* select linked vertices */
+ selectconnected_mesh_all();
+ break;
+ case 5: /* select random */
+ selectrandom_mesh();
+ break;
+ case 7: /* select more */
+ select_more();
+ break;
+ case 8: /* select less */
+ select_less();
+ break;
+ case 9: /* select non-manifold */
+ select_non_manifold();
+ break;
+ case 11: /* select triangles */
+ select_faces_by_numverts(3);
+ break;
+ case 12: /* select quads */
+ select_faces_by_numverts(4);
+ break;
+ case 13: /* select non-triangles/quads */
+ select_faces_by_numverts(5);
+ break;
+ case 14: /* select sharp edges */
+ select_sharp_edges();
+ break;
+ case 15: /* select linked flat faces */
+ select_linked_flat_faces();
+ break;
+
+ case 16: /* path select */
+ pathselect();
+ ED_undo_push(C, "Path Select");
+ break;
+ case 17: /* edge loop select */
+ loop_multiselect(0);
+ break;
+ case 18: /* edge ring select */
+ loop_multiselect(1);
+ break;
+ case 19: /* loop to region */
+ loop_to_region();
+ break;
+ case 20: /* region to loop */
+ region_to_loop();
+ break;
+ case 21: /* Select grouped */
+ select_mesh_group_menu();
+ break;
+ }
+#endif
+}
+
+
+static uiBlock *view3d_select_meshmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_select_meshmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_select_meshmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Border Select|B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Inverse|Ctrl I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Random...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Non-Manifold|Ctrl Alt Shift M",
+ 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Sharp Edges|Ctrl Alt Shift S",
+ 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Linked Flat Faces|Ctrl Alt Shift F",
+ 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Triangles|Ctrl Alt Shift 3",
+ 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Quads|Ctrl Alt Shift 4",
+ 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Non-Triangles/Quads|Ctrl Alt Shift 5",
+ 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+ "Similar to Selection...|Shift G",
+ 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 21, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "More|Ctrl NumPad +",
+ 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Less|Ctrl NumPad -",
+ 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Linked Vertices|Ctrl L", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vertex Path|W Alt 7", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Edge Loop|Ctrl E 6", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Edge Ring|Ctrl E 7", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Loop to Region|Ctrl E 8", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Region to Loop|Ctrl E 9", 0, yco-=20, menuwidth, 20, NULL, 0.0, 0.0, 1, 20, "");
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+static void view3d_select_curvemenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ Object *obedit= CTX_data_edit_object(C);
+
+ uiMenuItemO(head, 0, "VIEW3D_OT_select_border");
+ uiMenuItemO(head, 0, "VIEW3D_OT_select_circle");
+
+ uiMenuSeparator(head);
+
+ uiMenuItemO(head, 0, "CURVE_OT_select_all_toggle");
+ uiMenuItemO(head, 0, "CURVE_OT_select_invert");
+ uiMenuItemO(head, 0, "CURVE_OT_select_random"); // Random...
+ uiMenuItemO(head, 0, "CURVE_OT_select_every_nth"); // Every Nth..
+
+ uiMenuSeparator(head);
+
+ if(obedit->type == OB_SURF) {
+ uiMenuItemO(head, 0, "CURVE_OT_select_row");
+ }
+ else {
+ uiMenuItemO(head, 0, "CURVE_OT_de_select_first");
+ uiMenuItemO(head, 0, "CURVE_OT_de_select_last");
+ uiMenuItemO(head, 0, "CURVE_OT_select_next");
+ uiMenuItemO(head, 0, "CURVE_OT_select_previous");
+ }
+
+ uiMenuSeparator(head);
+
+ uiMenuItemO(head, 0, "CURVE_OT_select_more");
+ uiMenuItemO(head, 0, "CURVE_OT_select_less");
+
+ /* commented out because it seems to only like the LKEY method - based on mouse pointer position :( */
+ /* uiMenuItemO(head, 0, "CURVE_OT_select_linked"); */
+
+#if 0
+ G.qual |= LR_CTRLKEY;
+ select_connected_nurb();
+ G.qual &= ~LR_CTRLKEY;
+ break;*/
+#endif
+}
+
+void do_view3d_select_metaballmenu(bContext *C, void *arg, int event)
+{
+#if 0
+
+ switch(event) {
+ case 0: /* border select */
+ borderselect();
+ break;
+ case 2: /* Select/Deselect all */
+ deselectall_mball();
+ break;
+ case 3: /* Inverse */
+ selectinverse_mball();
+ break;
+ case 4: /* Select Random */
+ selectrandom_mball();
+ break;
+ }
+#endif
+}
+
+
+static uiBlock *view3d_select_metaballmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_select_metaballmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_select_metaballmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Border Select|B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Inverse", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Random...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+static void do_view3d_select_latticemenu(bContext *C, void *arg, int event)
+{
+#if 0
+/* extern void borderselect(void);*/
+
+ switch(event) {
+ case 0: /* border select */
+ borderselect();
+ break;
+ case 2: /* Select/Deselect all */
+ deselectall_Latt();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_select_latticemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_select_latticemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_select_latticemenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Border Select|B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+static void do_view3d_select_armaturemenu(bContext *C, void *arg, int event)
+{
+#if 0
+/* extern void borderselect(void);*/
+
+ switch(event) {
+ case 0: /* border select */
+ borderselect();
+ break;
+ case 2: /* Select/Deselect all */
+ deselectall_armature(1, 1);
+ break;
+ case 3: /* Swap Select All */
+ deselectall_armature(3, 1);
+ break;
+ case 4: /* Select parent */
+ armature_select_hierarchy(BONE_SELECT_PARENT, 0);
+ break;
+ case 5: /* Select child */
+ armature_select_hierarchy(BONE_SELECT_CHILD, 0);
+ break;
+ case 6: /* Extend Select parent */
+ armature_select_hierarchy(BONE_SELECT_PARENT, 1);
+ break;
+ case 7: /* Extend Select child */
+ armature_select_hierarchy(BONE_SELECT_CHILD, 1);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_select_armaturemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_select_armaturemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_select_armaturemenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Border Select|B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Inverse|Ctrl I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Parent|[", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Child|]", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Select Parent|Shift [", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Select Child|Shift ]", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+static void do_view3d_select_pose_armaturemenu(bContext *C, void *arg, int event)
+{
+#if 0
+/* extern void borderselect(void);*/
+
+ switch(event) {
+ case 0: /* border select */
+ borderselect();
+ break;
+ case 2: /* Select/Deselect all */
+ deselectall_posearmature(OBACT, 1, 1);
+ break;
+ case 3: /* Select Target(s) of Constraint(s) */
+ pose_select_constraint_target();
+ break;
+ case 5: /* Swap Select All */
+ deselectall_posearmature(OBACT, 3, 1);
+ break;
+ case 6: /* Select parent */
+ pose_select_hierarchy(BONE_SELECT_PARENT, 0);
+ break;
+ case 7: /* Select child */
+ pose_select_hierarchy(BONE_SELECT_CHILD, 0);
+ break;
+ case 8: /* Extend Select parent */
+ pose_select_hierarchy(BONE_SELECT_PARENT, 1);
+ break;
+ case 9: /* Extend Select child */
+ pose_select_hierarchy(BONE_SELECT_CHILD, 1);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_select_pose_armaturemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_select_pose_armaturemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_select_pose_armaturemenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Border Select|B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Swap Select All|Ctrl I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Constraint Target|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Parent|[", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Child|]", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Select Parent|Shift [", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Select Child|Shift ]", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+void do_view3d_select_faceselmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ /* events >= 6 are registered bpython scripts */
+#ifndef DISABLE_PYTHON
+ if (event >= 6) BPY_menu_do_python(PYMENU_FACESELECT, event - 6);
+#endif
+
+ switch(event) {
+ case 0: /* border select */
+ borderselect();
+ break;
+ case 2: /* Select/Deselect all */
+ deselectall_tface();
+ break;
+ case 3: /* Select Inverse */
+ selectswap_tface();
+ break;
+ case 4: /* Select Linked */
+ select_linked_tfaces(2);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_select_faceselmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+#ifndef DISABLE_PYTHON
+// XXX BPyMenu *pym;
+// int i = 0;
+#endif
+
+ block= uiBeginBlock(C, ar, "view3d_select_faceselmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_select_faceselmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Border Select|B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Inverse", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Linked Faces|Ctrl L", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+
+#ifndef DISABLE_PYTHON
+// uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ /* note that we account for the 6 previous entries with i+6: */
+// for (pym = BPyMenuTable[PYMENU_FACESELECT]; pym; pym = pym->next, i++) {
+// uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20,
+// menuwidth, 19, NULL, 0.0, 0.0, 1, i+6,
+// pym->tooltip?pym->tooltip:pym->filename);
+// }
+#endif
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+void do_view3d_edit_snapmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch (event) {
+ case 1: /*Selection to grid*/
+ snap_sel_to_grid();
+ ED_undo_push(C, "Snap selection to grid");
+ break;
+ case 2: /*Selection to cursor*/
+ snap_sel_to_curs();
+ ED_undo_push(C, "Snap selection to cursor");
+ break;
+ case 3: /*Selection to center of selection*/
+ snap_to_center();
+ ED_undo_push(C, "Snap selection to center");
+ break;
+ case 4: /*Cursor to selection*/
+ snap_curs_to_sel();
+ break;
+ case 5: /*Cursor to grid*/
+ snap_curs_to_grid();
+ break;
+ case 6: /*Cursor to Active*/
+ snap_curs_to_active();
+ ED_undo_push(C, "Snap selection to center");
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_snapmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_snapmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_snapmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Selection -> Grid|Shift S, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Selection -> Cursor|Shift S, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Selection -> Center|Shift S, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cursor -> Selection|Shift S, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cursor -> Grid|Shift S, 5", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cursor -> Active|Shift S, 6", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+
+
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+void do_view3d_transform_moveaxismenu(bContext *C, void *arg, int event)
+{
+#if 0
+ float mat[3][3];
+
+ Mat3One(mat);
+
+ switch(event)
+ {
+ case 0: /* X Global */
+ initTransform(TFM_TRANSLATION, CTX_NONE);
+ BIF_setSingleAxisConstraint(mat[0], " X");
+ Transform();
+ break;
+ case 1: /* Y Global */
+ initTransform(TFM_TRANSLATION, CTX_NONE);
+ BIF_setSingleAxisConstraint(mat[1], " Y");
+ Transform();
+ break;
+ case 2: /* Z Global */
+ initTransform(TFM_TRANSLATION, CTX_NONE);
+ BIF_setSingleAxisConstraint(mat[2], " Z");
+ Transform();
+ break;
+ case 3: /* X Local */
+ initTransform(TFM_TRANSLATION, CTX_NONE);
+ BIF_setLocalAxisConstraint('X', " X");
+ Transform();
+ break;
+ case 4: /* Y Local */
+ initTransform(TFM_TRANSLATION, CTX_NONE);
+ BIF_setLocalAxisConstraint('Y', " Y");
+ Transform();
+ break;
+ case 5: /* Z Local */
+ initTransform(TFM_TRANSLATION, CTX_NONE);
+ BIF_setLocalAxisConstraint('Z', " Z");
+ Transform();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_transform_moveaxismenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_transform_moveaxismenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_transform_moveaxismenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Global|G, X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Global|G, Y", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Global|G, Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|G, X, X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|G, Y, Y", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|G, Z, Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+void do_view3d_transform_rotateaxismenu(bContext *C, void *arg, int event)
+{
+#if 0
+ float mat[3][3];
+
+ Mat3One(mat);
+
+ switch(event)
+ {
+ case 0: /* X Global */
+ initTransform(TFM_ROTATION, CTX_NONE);
+ BIF_setSingleAxisConstraint(mat[0], " X");
+ Transform();
+ break;
+ case 1: /* Y Global */
+ initTransform(TFM_ROTATION, CTX_NONE);
+ BIF_setSingleAxisConstraint(mat[1], " Y");
+ Transform();
+ break;
+ case 2: /* Z Global */
+ initTransform(TFM_ROTATION, CTX_NONE);
+ BIF_setSingleAxisConstraint(mat[2], " Z");
+ Transform();
+ break;
+ case 3: /* X Local */
+ initTransform(TFM_ROTATION, CTX_NONE);
+ BIF_setLocalAxisConstraint('X', " X");
+ Transform();
+ break;
+ case 4: /* Y Local */
+ initTransform(TFM_ROTATION, CTX_NONE);
+ BIF_setLocalAxisConstraint('Y', " Y");
+ Transform();
+ break;
+ case 5: /* Z Local */
+ initTransform(TFM_ROTATION, CTX_NONE);
+ BIF_setLocalAxisConstraint('Z', " Z");
+ Transform();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_transform_rotateaxismenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_transform_rotateaxismenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_transform_rotateaxismenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Global|R, X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Global|R, Y", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Global|R, Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|R, X, X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|R, Y, Y", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|R, Z, Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+void do_view3d_transform_scaleaxismenu(bContext *C, void *arg, int event)
+{
+#if 0
+ float mat[3][3];
+
+ Mat3One(mat);
+
+ switch(event)
+ {
+ case 0: /* X Global */
+ initTransform(TFM_RESIZE, CTX_NONE);
+ BIF_setSingleAxisConstraint(mat[0], " X");
+ Transform();
+ break;
+ case 1: /* Y Global */
+ initTransform(TFM_RESIZE, CTX_NONE);
+ BIF_setSingleAxisConstraint(mat[1], " Y");
+ Transform();
+ break;
+ case 2: /* Z Global */
+ initTransform(TFM_RESIZE, CTX_NONE);
+ BIF_setSingleAxisConstraint(mat[2], " Z");
+ Transform();
+ break;
+ case 3: /* X Local */
+ initTransform(TFM_RESIZE, CTX_NONE);
+ BIF_setLocalAxisConstraint('X', " X");
+ Transform();
+ break;
+ case 4: /* Y Local */
+ initTransform(TFM_RESIZE, CTX_NONE);
+ BIF_setLocalAxisConstraint('X', " X");
+ Transform();
+ break;
+ case 5: /* Z Local */
+ initTransform(TFM_RESIZE, CTX_NONE);
+ BIF_setLocalAxisConstraint('X', " X");
+ Transform();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_transform_scaleaxismenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_transform_scaleaxismenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_transform_scaleaxismenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Global|S, X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Global|S, Y", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Global|S, Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|S, X, X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|S, Y, Y", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|S, Z, Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_transformmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ Scene *scene= CTX_data_scene(C);
+
+ switch(event) {
+ case 1:
+ initTransform(TFM_TRANSLATION, CTX_NONE);
+ Transform();
+ break;
+ case 2:
+ initTransform(TFM_ROTATION, CTX_NONE);
+ Transform();
+ break;
+ case 3:
+ initTransform(TFM_RESIZE, CTX_NONE);
+ Transform();
+ break;
+ case 4:
+ image_aspect();
+ break;
+ case 5:
+ initTransform(TFM_TOSPHERE, CTX_NONE);
+ Transform();
+ break;
+ case 6:
+ initTransform(TFM_SHEAR, CTX_NONE);
+ Transform();
+ break;
+ case 7:
+ initTransform(TFM_WARP, CTX_NONE);
+ Transform();
+ break;
+ case 8:
+ initTransform(TFM_PUSHPULL, CTX_NONE);
+ Transform();
+ break;
+ case 9:
+ if (obedit) {
+ if (obedit->type == OB_MESH)
+ initTransform(TFM_SHRINKFATTEN, CTX_NONE);
+ Transform();
+ } else error("Only meshes can be shrinked/fattened");
+ break;
+ case 10:
+ docenter(0);
+ break;
+ case 11:
+ docenter_new();
+ break;
+ case 12:
+ docenter_cursor();
+ break;
+ case 13:
+ initTransform(TFM_TILT, CTX_NONE);
+ Transform();
+ break;
+ case 14:
+ initTransform(TFM_CURVE_SHRINKFATTEN, CTX_NONE);
+ Transform();
+ break;
+ case 15:
+ scene->snap_flag &= ~SCE_SNAP;
+ break;
+ case 16:
+ scene->snap_flag |= SCE_SNAP;
+ break;
+ case 17:
+ scene->snap_target = SCE_SNAP_TARGET_CLOSEST;
+ break;
+ case 18:
+ scene->snap_target = SCE_SNAP_TARGET_CENTER;
+ break;
+ case 19:
+ scene->snap_target = SCE_SNAP_TARGET_MEDIAN;
+ break;
+ case 20:
+ scene->snap_target = SCE_SNAP_TARGET_ACTIVE;
+ break;
+ case 21:
+ alignmenu();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_transformmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_transformmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_transformmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move|G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBlockBut(block, view3d_transform_moveaxismenu, NULL, ICON_RIGHTARROW_THIN, "Grab/Move on Axis", 0, yco-=20, 120, 19, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rotate|R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBlockBut(block, view3d_transform_rotateaxismenu, NULL, ICON_RIGHTARROW_THIN, "Rotate on Axis", 0, yco-=20, 120, 19, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Scale|S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBlockBut(block, view3d_transform_scaleaxismenu, NULL, ICON_RIGHTARROW_THIN, "Scale on Axis", 0, yco-=20, 120, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if (obedit) {
+ if (obedit->type == OB_MESH)
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Shrink/Fatten Along Normals|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
+ else if (obedit->type == OB_CURVE) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Tilt|T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Shrink/Fatten Radius|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, "");
+ }
+ }
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "To Sphere|Ctrl Shift S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ if (obedit) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Shear|Ctrl S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Shear|Ctrl Shift Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Warp|Shift W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Push/Pull|Shift P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
+
+ if (!obedit) {
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Scale to Image Aspect Ratio|Alt V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ }
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "ObData to Center", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
+ if (!obedit) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Center New", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Center Cursor", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Align to Transform Orientation|Ctrl Alt A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 21, "");
+ }
+
+ if (BIF_snappingSupported(obedit))
+ {
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if (scene->snap_flag & SCE_SNAP)
+ {
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Grid", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, "");
+ }
+ else
+ {
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Grid", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, "");
+ }
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ switch(scene->snap_target)
+ {
+ case SCE_SNAP_TARGET_CLOSEST:
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Closest", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Center", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Median", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Active", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, "");
+ break;
+ case SCE_SNAP_TARGET_CENTER:
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Closest", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Center", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Median", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Active", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, "");
+ break;
+ case SCE_SNAP_TARGET_MEDIAN:
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Closest", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Center", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Median", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Active", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, "");
+ break;
+ case SCE_SNAP_TARGET_ACTIVE:
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Closest", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Center", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Median", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Active", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, "");
+ break;
+ }
+ }
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+void do_view3d_object_mirrormenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch(event) {
+ case 0:
+ initTransform(TFM_MIRROR, CTX_NO_PET);
+ Transform();
+ break;
+ case 1:
+ initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+ BIF_setLocalAxisConstraint('X', " on X axis");
+ Transform();
+ break;
+ case 2:
+ initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+ BIF_setLocalAxisConstraint('Y', " on Y axis");
+ Transform();
+ break;
+ case 3:
+ initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+ BIF_setLocalAxisConstraint('Z', " on Z axis");
+ Transform();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_object_mirrormenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_object_mirrormenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_object_mirrormenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Interactive Mirror|Ctrl M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|Ctrl M, X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|Ctrl M, Y", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|Ctrl M, Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_edit_object_transformmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch(event) {
+ case 0: /* clear origin */
+ clear_object('o');
+ break;
+ case 1: /* clear scale */
+ clear_object('s');
+ break;
+ case 2: /* clear rotation */
+ clear_object('r');
+ break;
+ case 3: /* clear location */
+ clear_object('g');
+ break;
+ case 4:
+ if(OBACT) object_apply_deform(OBACT);
+ break;
+ case 5: /* make duplis real */
+ make_duplilist_real();
+ break;
+ case 6: /* apply scale/rotation or deformation */
+ apply_objects_locrot();
+ break;
+ case 7: /* apply visual matrix to objects loc/size/rot */
+ apply_objects_visual_tx();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_object_transformmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_object_transformmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_object_transformmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Apply Scale/Rotation to ObData|Ctrl A, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Apply Visual Transform|Ctrl A, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Apply Deformation|Ctrl Shift A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Duplicates Real|Ctrl Shift A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Location|Alt G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Rotation|Alt R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Scale|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Origin|Alt O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_edit_object_makelocalmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch(event) {
+ case 1:
+ case 2:
+ case 3:
+ make_local(event);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_object_makelocalmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_object_makelocalmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_object_makelocalmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Selected Objects|L, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Selected Objects and Data|L, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "All|L, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_edit_object_makelinksmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch(event) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ make_links((short)event);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_object_makelinksmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob=NULL;
+
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_object_makelinksmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_object_makelinksmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "To Scene...|Ctrl L, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Object Ipo|Ctrl L, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+
+ if ((ob=OBACT)) {
+
+ if(ob->type==OB_MESH) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Mesh Data|Ctrl L, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Materials|Ctrl L, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ } else if(ob->type==OB_CURVE) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Curve Data|Ctrl L, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Materials|Ctrl L, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ } else if(ob->type==OB_FONT) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Text Data|Ctrl L, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Materials|Ctrl L, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ } else if(ob->type==OB_SURF) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Surface Data|Ctrl L, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Materials|Ctrl L, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ } else if(ob->type==OB_MBALL) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Materials|Ctrl L, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ } else if(ob->type==OB_CAMERA) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Camera Data|Ctrl L, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ } else if(ob->type==OB_LAMP) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Lamp Data|Ctrl L, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ } else if(ob->type==OB_LATTICE) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Lattice Data|Ctrl L, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ } else if(ob->type==OB_ARMATURE) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Armature Data|Ctrl L, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ }
+ }
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_edit_object_singleusermenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch(event) {
+ case 1: /* Object */
+ single_object_users(1);
+ break;
+ case 2: /* Object & ObData */
+ single_object_users(1);
+ single_obdata_users(1);
+ break;
+ case 3: /* Object & ObData & Materials+Tex */
+ single_object_users(1);
+ single_obdata_users(1);
+ single_mat_users(1); /* also tex */
+ break;
+ case 4: /* Materials+Tex */
+ single_mat_users(1);
+ break;
+ case 5: /* Ipo */
+ single_ipo_users(1);
+ break;
+ }
+
+ clear_id_newpoins();
+ countall();
+
+#endif
+}
+
+static uiBlock *view3d_edit_object_singleusermenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_object_singleusermenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_object_singleusermenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Object|U, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Object & ObData|U, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Object & ObData & Materials+Tex|U, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Materials+Tex|U, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Ipos|U, 5", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_edit_object_copyattrmenu(bContext *C, void *arg, int event)
+{
+ switch(event) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 17:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 29:
+ case 30:
+// XXX copy_attr((short)event);
+ break;
+ }
+}
+
+static uiBlock *view3d_edit_object_copyattrmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob=NULL;
+
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_object_copyattrmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_object_copyattrmenu, NULL);
+
+ ob= OBACT;
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Location|Ctrl C, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rotation|Ctrl C, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Size|Ctrl C, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Drawtype|Ctrl C, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Time Offset|Ctrl C, 5", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Dupli|Ctrl C, 6", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Mass|Ctrl C, 7", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Damping|Ctrl C, 8", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "All Physical Attributes|Ctrl C, 11", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Properties|Ctrl C, 9", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Logic Bricks|Ctrl C, 10", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Protected Transform |Ctrl C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 29, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Object Constraints|Ctrl C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 22, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "NLA Strips|Ctrl C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 26, "");
+
+ if (ob) {
+
+ if ((ob->type == OB_MESH) || (ob->type == OB_CURVE) || (ob->type == OB_SURF) ||
+ (ob->type == OB_FONT) || (ob->type == OB_MBALL)) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Texture Space|Ctrl C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, "");
+ }
+
+ if(ob->type == OB_FONT) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Font Settings|Ctrl C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Bevel Settings|Ctrl C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Curve Resolution|Ctrl C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 25, "");
+ }
+ if(ob->type == OB_CURVE) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Bevel Settings|Ctrl C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Curve Resolution|Ctrl C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 25, "");
+ }
+
+ if(ob->type==OB_MESH) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subsurf Settings|Ctrl C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 21, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Modifiers ...|Ctrl C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 24, "");
+ }
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Object Pass Index|Ctrl C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 30, "");
+ }
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+
+static void do_view3d_edit_object_parentmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch(event) {
+ case 0: /* clear parent */
+ clear_parent();
+ break;
+ case 1: /* make parent */
+ make_parent();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_object_parentmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_object_parentmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_object_parentmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Parent...|Ctrl P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Parent...|Alt P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_edit_object_groupmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch(event) {
+ case 1:
+ case 2:
+ case 3:
+ group_operation(event);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_object_groupmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_object_groupmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_object_groupmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add to Existing Group|Ctrl G, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add to New Group|Ctrl G, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Remove from All Groups|Ctrl G, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_edit_object_trackmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch(event) {
+ case 0: /* clear track */
+ clear_track();
+ break;
+ case 1: /* make track */
+ make_track();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_object_trackmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_object_trackmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_object_trackmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Track...|Ctrl T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Track...|Alt T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_edit_object_constraintsmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch(event) {
+ case 1: /* add constraint */
+ add_constraint(0);
+ break;
+ case 2: /* clear constraint */
+ ob_clear_constraints();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_object_constraintsmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_object_constraintsmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_object_constraintsmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Constraint...|Ctrl Alt C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Constraints", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_edit_object_showhidemenu(bContext *C, void *arg, int event)
+{
+#if 0
+
+ switch(event) {
+
+ case 0: /* show objects */
+ show_objects();
+ break;
+ case 1: /* hide selected objects */
+ hide_objects(1);
+ break;
+ case 2: /* hide deselected objects */
+ hide_objects(0);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_object_showhidemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_object_showhidemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_object_showhidemenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Hidden|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Hide Selected|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Hide Unselected|Shift H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+#ifndef DISABLE_PYTHON
+static void do_view3d_edit_object_scriptsmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ BPY_menu_do_python(PYMENU_OBJECT, event);
+
+#endif
+}
+
+static uiBlock *view3d_edit_object_scriptsmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+// short yco = 20, menuwidth = 120;
+// XXX BPyMenu *pym;
+// int i = 0;
+
+ block= uiBeginBlock(C, ar, "v3d_eobject_pymenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_object_scriptsmenu, NULL);
+
+// for (pym = BPyMenuTable[PYMENU_OBJECT]; pym; pym = pym->next, i++) {
+// uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, i, pym->tooltip?pym->tooltip:pym->filename);
+// }
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+
+ return block;
+}
+#endif /* DISABLE_PYTHON */
+
+
+static void do_view3d_edit_objectmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ Scene *scene= CTX_data_scene(C);
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= sa->spacedata.first;
+
+ switch(event) {
+
+ case 0: /* transform properties*/
+// XXX mainqenter(NKEY, 1);
+ break;
+ case 1: /* delete */
+ delete_context_selected();
+ break;
+ case 2: /* duplicate */
+ duplicate_context_selected();
+ break;
+ case 3: /* duplicate linked */
+ adduplicate(0, 0);
+ break;
+ case 5: /* make single user */
+ single_user();
+ break;
+ case 7: /* boolean operation */
+ special_editmenu();
+ break;
+ case 8: /* join objects */
+ join_menu();
+ break;
+ case 9: /* convert object type */
+ convertmenu();
+ break;
+ case 10: /* move to layer */
+ movetolayer();
+ break;
+ case 11: /* insert keyframe */
+ common_insertkey();
+ break;
+ case 15: /* Object Panel */
+ add_blockhandler(sa, VIEW3D_HANDLER_OBJECT, UI_PNL_UNSTOW);
+ break;
+ case 16: /* make proxy object*/
+ make_proxy();
+ break;
+ case 18: /* delete keyframe */
+ common_deletekey();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_objectmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ Scene *scene= CTX_data_scene(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_objectmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_objectmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Transform Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 15, "");
+ uiDefIconTextBlockBut(block, view3d_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_object_mirrormenu, NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, menuwidth, 19, "");
+
+ uiDefIconTextBlockBut(block, view3d_edit_object_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Clear/Apply", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_snapmenu, NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Keyframe|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate|Shift D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate Linked|Alt D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete|X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Proxy|Ctrl Alt P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, "");
+ uiDefIconTextBlockBut(block, view3d_edit_object_makelinksmenu, NULL, ICON_RIGHTARROW_THIN, "Make Links", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_object_singleusermenu, NULL, ICON_RIGHTARROW_THIN, "Make Single User", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_object_makelocalmenu, NULL, ICON_RIGHTARROW_THIN, "Make Local", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_object_copyattrmenu, NULL, ICON_RIGHTARROW_THIN, "Copy Attributes", 0, yco-=20, 120, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBlockBut(block, view3d_edit_object_parentmenu, NULL, ICON_RIGHTARROW_THIN, "Parent", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_object_groupmenu, NULL, ICON_RIGHTARROW_THIN, "Group", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_object_trackmenu, NULL, ICON_RIGHTARROW_THIN, "Track", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_object_constraintsmenu, NULL, ICON_RIGHTARROW_THIN, "Constraints", 0, yco-=20, 120, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if (OBACT && OBACT->type == OB_MESH) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Boolean Operation...|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+ }
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Join Objects|Ctrl J", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Convert Object Type...|Alt C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Move to Layer...|M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
+ uiDefIconTextBlockBut(block, view3d_edit_object_showhidemenu, NULL, ICON_RIGHTARROW_THIN, "Show/Hide Objects", 0, yco-=20, 120, 19, "");
+
+#ifndef DISABLE_PYTHON
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIconTextBlockBut(block, view3d_edit_object_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Scripts", 0, yco-=20, 120, 19, "");
+#endif
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+
+static void do_view3d_edit_propfalloffmenu(bContext *C, void *arg, int event)
+{
+ Scene *scene= CTX_data_scene(C);
+
+ scene->prop_mode= event;
+
+}
+
+static uiBlock *view3d_edit_propfalloffmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ Scene *scene= CTX_data_scene(C);
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_propfalloffmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_propfalloffmenu, NULL);
+
+ if (scene->prop_mode==PROP_SMOOTH) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Smooth|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SMOOTH, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Smooth|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SMOOTH, "");
+ if (scene->prop_mode==PROP_SPHERE) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Sphere|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SPHERE, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Sphere|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SPHERE, "");
+ if (scene->prop_mode==PROP_ROOT) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Root|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_ROOT, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Root|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_ROOT, "");
+ if (scene->prop_mode==PROP_SHARP) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Sharp|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SHARP, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Sharp|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SHARP, "");
+ if (scene->prop_mode==PROP_LIN) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Linear|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_LIN, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Linear|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_LIN, "");
+ if (scene->prop_mode==PROP_RANDOM) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Random|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_RANDOM, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Random|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_RANDOM, "");
+ if (scene->prop_mode==PROP_CONST) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Constant|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_CONST, "");
+ else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Constant|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_CONST, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+
+void do_view3d_edit_mesh_verticesmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ Scene *scene= CTX_data_scene(C);
+
+ switch(event) {
+ int count;
+
+ case 0: /* make vertex parent */
+ make_parent();
+ break;
+ case 1: /* remove doubles */
+ count= removedoublesflag(1, 0, scene->toolsettings->doublimit);
+ notice("Removed: %d", count);
+ if (count) { /* only undo and redraw if an action is taken */
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ ED_undo_push(C, "Rem Doubles");
+ }
+ break;
+ case 2: /* smooth */
+ vertexsmooth();
+ break;
+ case 3: /* separate */
+ separate_mesh();
+ break;
+ case 4: /*split */
+ split_mesh();
+ break;
+ case 5: /*merge */
+ mergemenu();
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ break;
+ case 6: /* add hook */
+ add_hook_menu();
+ break;
+ case 7: /* rip */
+ mesh_rip();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_mesh_verticesmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_mesh_verticesmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_mesh_verticesmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Merge...|Alt M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rip|V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Split|Y", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Separate|P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Smooth|W, Alt 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Remove Doubles|W, 6", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Vertex Parent|Ctrl P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Hook|Ctrl H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+extern void editmesh_mark_sharp(int set); /* declared in editmesh_mods.c */
+
+void do_view3d_edit_mesh_edgesmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ Scene *scene= CTX_data_scene(C);
+ float fac;
+ short randfac;
+
+ switch(event) {
+
+ case 0: /* subdivide smooth */
+ esubdivideflag(1, 0.0, scene->toolsettings->editbutflag | B_SMOOTH,1,0);
+ ED_undo_push(C, "Subdivide Smooth");
+ break;
+ case 1: /*subdivide fractal */
+ randfac= 10;
+ if(button(&randfac, 1, 100, "Rand fac:")==0) return;
+ fac= -( (float)randfac )/100;
+ esubdivideflag(1, fac, scene->toolsettings->editbutflag,1,0);
+ ED_undo_push(C, "Subdivide Fractal");
+ break;
+ case 2: /* subdivide */
+ esubdivideflag(1, 0.0, scene->toolsettings->editbutflag,1,0);
+ ED_undo_push(C, "Subdivide");
+ break;
+ case 3: /* knife subdivide */
+ KnifeSubdivide(KNIFE_PROMPT);
+ break;
+ case 4: /* Loop subdivide */
+ CutEdgeloop(1);
+ break;
+ case 5: /* Make Edge/Face */
+ addedgeface_mesh();
+ break;
+ case 6:
+ bevel_menu();
+ break;
+ case 7: /* Mark Seam */
+ editmesh_mark_seam(0);
+ break;
+ case 8: /* Clear Seam */
+ editmesh_mark_seam(1);
+ break;
+ case 9: /* Crease SubSurf */
+ if(!multires_level1_test()) {
+ initTransform(TFM_CREASE, CTX_EDGE);
+ Transform();
+ }
+ break;
+ case 10: /* Rotate Edge */
+ edge_rotate_selected(2);
+ break;
+ case 11: /* Rotate Edge */
+ edge_rotate_selected(1);
+ break;
+ case 12: /* Edgeslide */
+ EdgeSlide(0,0.0);
+ break;
+ case 13: /* Edge Loop Delete */
+ if(EdgeLoopDelete()) {
+ countall();
+ ED_undo_push(C, "Erase Edge Loop");
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ }
+ break;
+ case 14: /*Collapse Edges*/
+ collapseEdges();
+ ED_undo_push(C, "Collapse");
+ break;
+ case 15:
+ editmesh_mark_sharp(1);
+ ED_undo_push(C, "Mark Sharp");
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ break;
+ case 16:
+ editmesh_mark_sharp(0);
+ ED_undo_push(C, "Clear Sharp");
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ break;
+ case 17: /* Adjust Bevel Weight */
+ if(!multires_level1_test()) {
+ initTransform(TFM_BWEIGHT, CTX_EDGE);
+ Transform();
+ }
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_mesh_edgesmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_mesh_edgesmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_mesh_edgesmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Edge/Face|F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Bevel|W, Alt 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Loop Subdivide...|Ctrl R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Knife Subdivide...|Shift K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide|W, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide Fractal|W, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide Smooth|W, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Mark Seam|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Seam|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Mark Sharp|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Sharp|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Adjust Bevel Weight|Ctrl Shift E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Crease SubSurf|Shift E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rotate Edge CW|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rotate Edge CCW|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Slide Edge |Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Edge Loop|X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Collapse", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, "");
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+void do_view3d_edit_mesh_facesmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ Scene *scene= CTX_data_scene(C);
+
+ switch(event) {
+ case 0: /* Fill Faces */
+ fill_mesh();
+ break;
+ case 1: /* Beauty Fill Faces */
+ beauty_fill();
+ break;
+ case 2: /* Quads to Tris */
+ convert_to_triface(0);
+ countall();
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ break;
+ case 3: /* Tris to Quads */
+ join_triangles();
+ break;
+ case 4: /* Flip triangle edges */
+ edge_flip();
+ break;
+ case 5: /* Make Edge/Face */
+ addedgeface_mesh();
+ break;
+ case 6: /* Set Smooth */
+ mesh_set_smooth_faces(1);
+ break;
+ case 7: /* Set Solid */
+ mesh_set_smooth_faces(0);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_mesh_facesmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_mesh_facesmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_mesh_facesmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Edge/Face|F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Fill|Shift F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Beautify Fill|Alt F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Convert Quads to Triangles|Ctrl T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Convert Triangles to Quads|Alt J", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Flip Triangle Edges|Ctrl Shift F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Smooth|W, Alt 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Solid|W, Alt 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+void do_view3d_edit_mesh_normalsmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch(event) {
+ case 0: /* flip */
+ flip_editnormals();
+ break;
+ case 1: /* recalculate inside */
+ righthandfaces(2);
+ break;
+ case 2: /* recalculate outside */
+ righthandfaces(1);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_mesh_normalsmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_mesh_normalsmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_mesh_normalsmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Recalculate Outside|Ctrl N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Recalculate Inside|Ctrl Shift N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Flip|W, 0", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+void do_view3d_edit_mirrormenu(bContext *C, void *arg, int event)
+{
+#if 0
+ float mat[3][3];
+
+ Mat3One(mat);
+
+ switch(event) {
+ case 0:
+ initTransform(TFM_MIRROR, CTX_NO_PET);
+ Transform();
+ break;
+ case 1:
+ initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+ BIF_setSingleAxisConstraint(mat[0], " on global X axis");
+ Transform();
+ break;
+ case 2:
+ initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+ BIF_setSingleAxisConstraint(mat[1], " on global Y axis");
+ Transform();
+ break;
+ case 3:
+ initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+ BIF_setSingleAxisConstraint(mat[2], "on global Z axis");
+ Transform();
+ break;
+ case 4:
+ initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+ BIF_setLocalAxisConstraint('X', " on local X axis");
+ Transform();
+ break;
+ case 5:
+ initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+ BIF_setLocalAxisConstraint('Y', " on local Y axis");
+ Transform();
+ break;
+ case 6:
+ initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+ BIF_setLocalAxisConstraint('Z', " on local Z axis");
+ Transform();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_mirrormenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_mirrormenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_mirrormenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Interactive Mirror|Ctrl M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Global|Ctrl M, X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Global|Ctrl M, Y", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Global|Ctrl M, Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|Ctrl M, X X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|Ctrl M, Y Y", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|Ctrl M, Z Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_edit_mesh_showhidemenu(bContext *C, void *arg, int event)
+{
+#if 0
+
+ switch(event) {
+
+ case 0: /* show hidden vertices */
+ reveal_mesh();
+ break;
+ case 1: /* hide selected vertices */
+ hide_mesh(0);
+ break;
+ case 2: /* hide deselected vertices */
+ hide_mesh(1);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_mesh_showhidemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_mesh_showhidemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_mesh_showhidemenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Hidden|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Hide Selected|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Hide Unselected|Shift H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+#ifndef DISABLE_PYTHON
+static void do_view3d_edit_mesh_scriptsmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ BPY_menu_do_python(PYMENU_MESH, event);
+
+#endif
+}
+
+static uiBlock *view3d_edit_mesh_scriptsmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+// short yco = 20, menuwidth = 120;
+// XXX BPyMenu *pym;
+// int i = 0;
+
+ block= uiBeginBlock(C, ar, "v3d_emesh_pymenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_mesh_scriptsmenu, NULL);
+
+// for (pym = BPyMenuTable[PYMENU_MESH]; pym; pym = pym->next, i++) {
+// uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, i, pym->tooltip?pym->tooltip:pym->filename);
+// }
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+
+ return block;
+}
+#endif /* DISABLE_PYTHON */
+
+static void do_view3d_edit_meshmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ Scene *scene= CTX_data_scene(C);
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= sa->spacedata.first;
+
+ switch(event) {
+
+ case 0: /* Undo Editing */
+ BIF_undo();
+ break;
+ case 1: /* Redo Editing */
+ BIF_redo();
+ break;
+ case 2: /* transform properties */
+ add_blockhandler(sa, VIEW3D_HANDLER_OBJECT, 0);
+ break;
+ case 4: /* insert keyframe */
+ common_insertkey();
+ break;
+ case 5: /* Extrude */
+ extrude_mesh();
+ break;
+ case 6: /* duplicate */
+ duplicate_context_selected();
+ break;
+ case 7: /* make edge face */
+ addedgeface_mesh();
+ break;
+ case 8: /* delete */
+ delete_context_selected();
+ break;
+ case 9: /* Shrink/Fatten Along Normals */
+ initTransform(TFM_SHRINKFATTEN, CTX_NONE);
+ Transform();
+ break;
+ case 10: /* Shear */
+ initTransform(TFM_SHEAR, CTX_NONE);
+ Transform();
+ break;
+ case 11: /* Warp */
+ initTransform(TFM_WARP, CTX_NONE);
+ Transform();
+ break;
+ case 12: /* proportional edit (toggle) */
+ if(scene->proportional) scene->proportional= 0;
+ else scene->proportional= 1;
+ break;
+ case 13: /* automerge edit (toggle) */
+ if(scene->automerge) scene->automerge= 0;
+ else scene->automerge= 1;
+ break;
+ case 15:
+ uv_autocalc_tface();
+ break;
+ case 16: /* delete keyframe */
+ common_deletekey();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_meshmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_meshmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_meshmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Undo Editing|Ctrl Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Redo Editing|Ctrl Shift Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+// XXX uiDefIconTextBlockBut(block, editmode_undohistorymenu, NULL, ICON_RIGHTARROW_THIN, "Undo History", 0, yco-=20, 120, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Transform Properties...|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBlockBut(block, view3d_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_mirrormenu, NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_snapmenu, NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Keyframe|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "UV Unwrap|U", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extrude|E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate|Shift D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Edge/Face|F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete...|X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBlockBut(block, view3d_edit_mesh_verticesmenu, NULL, ICON_RIGHTARROW_THIN, "Vertices", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_mesh_edgesmenu, NULL, ICON_RIGHTARROW_THIN, "Edges", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_mesh_facesmenu, NULL, ICON_RIGHTARROW_THIN, "Faces", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_mesh_normalsmenu, NULL, ICON_RIGHTARROW_THIN, "Normals", 0, yco-=20, 120, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+
+
+ if(scene->proportional) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Proportional Editing|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
+ } else {
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Proportional Editing|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
+ }
+ uiDefIconTextBlockBut(block, view3d_edit_propfalloffmenu, NULL, ICON_RIGHTARROW_THIN, "Proportional Falloff", 0, yco-=20, 120, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ /* PITA but we should let users know that automerge cant work with multires :/ */
+ uiDefIconTextBut(block, BUTM, 1,
+ scene->automerge ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT,
+ ((Mesh*)obedit->data)->mr ? "AutoMerge Editing (disabled by multires)" : "AutoMerge Editing",
+ 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBlockBut(block, view3d_edit_mesh_showhidemenu, NULL, ICON_RIGHTARROW_THIN, "Show/Hide Vertices", 0, yco-=20, 120, 19, "");
+
+#ifndef DISABLE_PYTHON
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIconTextBlockBut(block, view3d_edit_mesh_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Scripts", 0, yco-=20, 120, 19, "");
+#endif
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+static void view3d_edit_curve_controlpointsmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ Object *obedit= CTX_data_edit_object(C);
+
+ if(obedit->type == OB_CURVE) {
+ uiMenuItemEnumO(head, "", 0, "TFM_OT_transform", "mode", TFM_TILT);
+ uiMenuItemO(head, 0, "CURVE_OT_tilt_clear");
+ uiMenuItemO(head, 0, "CURVE_OT_separate");
+
+ uiMenuSeparator(head);
+
+ uiMenuItemEnumO(head, "", 0, "CURVE_OT_handle_type_set", "type", 1);
+ uiMenuItemEnumO(head, "", 0, "CURVE_OT_handle_type_set", "type", 3);
+ uiMenuItemEnumO(head, "", 0, "CURVE_OT_handle_type_set", "type", 2);
+
+ uiMenuSeparator(head);
+ }
+
+ // XXX uiMenuItemO(head, 0, "OBJECT_OT_make_vertex_parent"); Make VertexParent|Ctrl P
+ // make_parent()
+ // XXX uiMenuItemO(head, 0, "OBJECT_OT_add_hook"); Add Hook| Ctrl H
+ // add_hook_menu()
+}
+
+static void view3d_edit_curve_segmentsmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuItemO(head, 0, "CURVE_OT_subdivide");
+ uiMenuItemO(head, 0, "CURVE_OT_switch_direction");
+}
+
+static void view3d_edit_curve_showhidemenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuItemO(head, 0, "CURVE_OT_reveal");
+ uiMenuItemO(head, 0, "CURVE_OT_hide");
+ uiMenuItemBooleanO(head, "Hide Unselected", 0, "CURVE_OT_hide", "unselected", 1);
+}
+
+static void view3d_edit_curvemenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ PointerRNA sceneptr;
+ Scene *scene= CTX_data_scene(C);
+
+ RNA_id_pointer_create(&scene->id, &sceneptr);
+
+#if 0
+ uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Transform Properties...|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBlockBut(block, view3d_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_mirrormenu, NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, menuwidth, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_snapmenu, NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 19, "");
+
+ uiMenuSeparator(head);
+#endif
+
+ // XXX uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ // common_insertkey();
+ // XXX uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Keyframe|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, "");
+ // common_deletekey();
+
+
+ uiMenuItemO(head, 0, "CURVE_OT_extrude");
+ uiMenuItemO(head, 0, "CURVE_OT_duplicate");
+ uiMenuItemO(head, 0, "CURVE_OT_separate");
+ uiMenuItemO(head, 0, "CURVE_OT_make_segment");
+ uiMenuItemO(head, 0, "CURVE_OT_cyclic_toggle");
+ uiMenuItemO(head, 0, "CURVE_OT_delete"); // Delete...
+
+ uiMenuSeparator(head);
+
+ uiMenuLevel(head, "Control Points", view3d_edit_curve_controlpointsmenu);
+ uiMenuLevel(head, "Segments", view3d_edit_curve_segmentsmenu);
+
+ uiMenuSeparator(head);
+
+ uiMenuItemBooleanR(head, &sceneptr, "proportional_editing"); // |O
+ uiMenuLevelEnumR(head, &sceneptr, "proportional_editing_falloff");
+
+ uiMenuSeparator(head);
+
+ uiMenuLevel(head, "Show/Hide Control Points", view3d_edit_curve_showhidemenu);
+}
+
+static void do_view3d_edit_mball_showhidemenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch(event) {
+ case 10: /* show hidden control points */
+ reveal_mball();
+ break;
+ case 11: /* hide selected control points */
+ hide_mball(0);
+ break;
+ case 12: /* hide selected control points */
+ hide_mball(1);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_mball_showhidemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_mball_showhidemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_mball_showhidemenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Hidden|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Hide Selected|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Hide Unselected|Shift H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+static void do_view3d_edit_metaballmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ Scene *scene= CTX_data_scene(C);
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= sa->spacedata.first;
+
+ switch(event) {
+ case 1: /* undo */
+ BIF_undo();
+ break;
+ case 2: /* redo */
+ BIF_redo();
+ break;
+ case 3: /* duplicate */
+ duplicate_context_selected();
+ break;
+ case 4: /* delete */
+ delete_context_selected();
+ break;
+ case 5: /* Shear */
+ initTransform(TFM_SHEAR, CTX_NONE);
+ Transform();
+ break;
+ case 6: /* Warp */
+ initTransform(TFM_WARP, CTX_NONE);
+ Transform();
+ break;
+ case 7: /* Transform Properties */
+ add_blockhandler(sa, VIEW3D_HANDLER_OBJECT, 0);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_metaballmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_metaballmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_metaballmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Undo Editing|Ctrl Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Redo Editing|Shift Ctrl Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+// XXX uiDefIconTextBlockBut(block, editmode_undohistorymenu, NULL, ICON_RIGHTARROW_THIN, "Undo History", 0, yco-=20, 120, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Transform Properties|N",0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
+ uiDefIconTextBlockBut(block, view3d_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_mirrormenu, NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, menuwidth, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_snapmenu, NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate|Shift D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete...|X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBlockBut(block, view3d_edit_mball_showhidemenu, NULL, ICON_RIGHTARROW_THIN, "Hide MetaElems", 0, yco-=20, 120, 19, "");
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+static void view3d_edit_text_charsmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ /* the character codes are specified in UTF-8 */
+
+ uiMenuItemStringO(head, "Copyright|Alt C", 0, "FONT_OT_text_insert", "text", "\xC2\xA9");
+ uiMenuItemStringO(head, "Registered Trademark|Alt R", 0, "FONT_OT_text_insert", "text", "\xC2\xAE");
+
+ uiMenuSeparator(head);
+
+ uiMenuItemStringO(head, "Degree Sign|Alt G", 0, "FONT_OT_text_insert", "text", "\xC2\xB0");
+ uiMenuItemStringO(head, "Multiplication Sign|Alt x", 0, "FONT_OT_text_insert", "text", "\xC3\x97");
+ uiMenuItemStringO(head, "Circle|Alt .", 0, "FONT_OT_text_insert", "text", "\xC2\x8A");
+ uiMenuItemStringO(head, "Superscript 1|Alt 1", 0, "FONT_OT_text_insert", "text", "\xC2\xB9");
+ uiMenuItemStringO(head, "Superscript 2|Alt 2", 0, "FONT_OT_text_insert", "text", "\xC2\xB2");
+ uiMenuItemStringO(head, "Superscript 3|Alt 3", 0, "FONT_OT_text_insert", "text", "\xC2\xB3");
+ uiMenuItemStringO(head, "Double >>|Alt >", 0, "FONT_OT_text_insert", "text", "\xC2\xBB");
+ uiMenuItemStringO(head, "Double <<|Alt <", 0, "FONT_OT_text_insert", "text", "\xC2\xAB");
+ uiMenuItemStringO(head, "Promillage|Alt %", 0, "FONT_OT_text_insert", "text", "\xE2\x80\xB0");
+
+ uiMenuSeparator(head);
+
+ uiMenuItemStringO(head, "Dutch Florin|Alt F", 0, "FONT_OT_text_insert", "text", "\xC2\xA4");
+ uiMenuItemStringO(head, "British Pound|Alt L", 0, "FONT_OT_text_insert", "text", "\xC2\xA3");
+ uiMenuItemStringO(head, "Japanese Yen|Alt Y", 0, "FONT_OT_text_insert", "text", "\xC2\xA5");
+
+ uiMenuSeparator(head);
+
+ uiMenuItemStringO(head, "German S|Alt S", 0, "FONT_OT_text_insert", "text", "\xC3\x9F");
+ uiMenuItemStringO(head, "Spanish Question Mark|Alt ?", 0, "FONT_OT_text_insert", "text", "\xC2\xBF");
+ uiMenuItemStringO(head, "Spanish Exclamation Mark|Alt !", 0, "FONT_OT_text_insert", "text", "\xC2\xA1");
+}
+
+static void view3d_edit_textmenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuItemO(head, 0, "FONT_OT_file_paste");
+ uiMenuSeparator(head);
+ uiMenuLevel(head, "Special Characters", view3d_edit_text_charsmenu);
+}
+
+static void do_view3d_edit_latticemenu(bContext *C, void *arg, int event)
+{
+#if 0
+ Scene *scene= CTX_data_scene(C);
+
+ switch(event) {
+
+ case 0: /* Undo Editing */
+ remake_editLatt();
+ break;
+ case 2: /* insert keyframe */
+ common_insertkey();
+ break;
+ case 3: /* Shear */
+ initTransform(TFM_SHEAR, CTX_NONE);
+ Transform();
+ break;
+ case 4: /* Warp */
+ initTransform(TFM_WARP, CTX_NONE);
+ Transform();
+ break;
+ case 5: /* proportional edit (toggle) */
+ if(scene->proportional) scene->proportional= 0;
+ else scene->proportional= 1;
+ break;
+ case 7: /* delete keyframe */
+ common_deletekey();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_latticemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ Scene *scene= CTX_data_scene(C);
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_latticemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_latticemenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Undo Editing|U", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBlockBut(block, view3d_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_mirrormenu, NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, menuwidth, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_snapmenu, NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Keyframe|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "UV Unwrap|U", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if(scene->proportional) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Proportional Editing|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ } else {
+ uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Proportional Editing|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ }
+ uiDefIconTextBlockBut(block, view3d_edit_propfalloffmenu, NULL, ICON_RIGHTARROW_THIN, "Proportional Falloff", 0, yco-=20, 120, 19, "");
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+void do_view3d_edit_armature_parentmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch(event) {
+ case 1:
+ make_bone_parent();
+ break;
+ case 2:
+ clear_bone_parent();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_armature_parentmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_armature_parentmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_armature_parentmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Parent...|Ctrl P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Parent...|Alt P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+void do_view3d_edit_armature_rollmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ if (event == 1 || event == 2)
+ /* set roll based on aligning z-axis */
+ auto_align_armature(event);
+ else if (event == 3) {
+ /* interactively set bone roll */
+ initTransform(TFM_BONE_ROLL, CTX_NONE);
+ Transform();
+ }
+#endif
+}
+
+static uiBlock *view3d_edit_armature_rollmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_armature_rollmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_armature_rollmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Roll (Z-Axis Up)|Ctrl N, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Roll to Cursor|Ctrl N, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Roll|Ctrl R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_edit_armaturemenu(bContext *C, void *arg, int event)
+{
+#if 0
+ static short numcuts= 2;
+
+ switch(event) {
+ case 0: /* Undo Editing */
+ remake_editArmature();
+ break;
+ case 1: /* transformation properties */
+// XXX mainqenter(NKEY, 1);
+ break;
+ case 3: /* extrude */
+ extrude_armature(0);
+ break;
+ case 4: /* duplicate */
+ duplicate_context_selected();
+ break;
+ case 5: /* delete */
+ delete_context_selected();
+ break;
+ case 6: /* Shear */
+ initTransform(TFM_SHEAR, CTX_NONE);
+ Transform();
+ break;
+ case 7: /* Warp */
+ initTransform(TFM_WARP, CTX_NONE);
+ Transform();
+ case 10: /* forked! */
+ extrude_armature(1);
+ break;
+ case 12: /* subdivide */
+ subdivide_armature(1);
+ break;
+ case 13: /* flip left and right names */
+ armature_flip_names();
+ break;
+ case 15: /* subdivide multi */
+ if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
+ waitcursor(1);
+ subdivide_armature(numcuts);
+ break;
+ case 16: /* Alt-S transform (BoneSize) */
+ initTransform(TFM_BONESIZE, CTX_NONE);
+ Transform();
+ break;
+ case 17: /* move to layer */
+ pose_movetolayer();
+ break;
+ case 18: /* merge bones */
+ merge_armature();
+ break;
+ case 19: /* auto-extensions */
+ case 20:
+ case 21:
+ armature_autoside_names(event-19);
+ break;
+ case 22: /* separate */
+ separate_armature();
+ break;
+ case 23: /* bone sketching panel */
+ add_blockhandler(curarea, VIEW3D_HANDLER_BONESKETCH, UI_PNL_UNSTOW);
+ break;
+ }
+
+#endif
+}
+
+
+#ifndef DISABLE_PYTHON
+static void do_view3d_scripts_armaturemenu(bContext *C, void *arg, int event)
+{
+#if 0
+ BPY_menu_do_python(PYMENU_ARMATURE, event);
+
+#endif
+}
+
+static uiBlock *view3d_scripts_armaturemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+// XXX BPyMenu *pym;
+// int i= 0;
+// short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_scripts_armaturemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_scripts_armaturemenu, NULL);
+
+ /* note that we acount for the N previous entries with i+20: */
+// for (pym = BPyMenuTable[PYMENU_ARMATURE]; pym; pym = pym->next, i++) {
+//
+// uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20, menuwidth, 19,
+// NULL, 0.0, 0.0, 1, i,
+// pym->tooltip?pym->tooltip:pym->filename);
+// }
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+
+ return block;
+}
+#endif /* DISABLE_PYTHON */
+
+static void do_view3d_armature_settingsmenu(bContext *C, void *arg, int event)
+{
+// XXX setflag_armature(event);
+}
+
+static uiBlock *view3d_armature_settingsmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_armature_settingsmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_armature_settingsmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Toggle a Setting|Shift W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Enable a Setting|Ctrl Shift W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Disable a Setting|Alt W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+
+ return block;
+}
+
+static uiBlock *view3d_edit_armaturemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm= obedit->data;
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_edit_armaturemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_edit_armaturemenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Undo Editing|U", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Transform Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Bone Sketching|P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 23, "");
+ uiDefIconTextBlockBut(block, view3d_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_mirrormenu, NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, menuwidth, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_snapmenu, NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_edit_armature_rollmenu, NULL, ICON_RIGHTARROW_THIN, "Bone Roll", 0, yco-=20, 120, 19, "");
+
+ if (arm->drawtype==ARM_ENVELOPE)
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Scale Envelope Distance|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, "");
+ else if (arm->drawtype==ARM_B_BONE)
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Scale B-Bone Width|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extrude|E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ if (arm->flag & ARM_MIRROR_EDIT)
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extrude Forked|Shift E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate|Shift D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Merge|Alt M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Fill Between Joints|F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete|X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Separate|Ctrl Alt P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 22, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide|W, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide Multi|W, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Flip Left & Right Names|W, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "AutoName Left-Right|W, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "AutoName Front-Back|W, 5", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "AutoName Top-Bottom|W, 6", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 21, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Switch Armature Layers|Shift M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Move Bone To Layer|M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBlockBut(block, view3d_edit_armature_parentmenu, NULL, ICON_RIGHTARROW_THIN, "Parent", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_armature_settingsmenu, NULL, ICON_RIGHTARROW_THIN, "Bone Settings", 0, yco-=20, 120, 19, "");
+
+#ifndef DISABLE_PYTHON
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBlockBut(block, view3d_scripts_armaturemenu, NULL, ICON_RIGHTARROW_THIN, "Scripts", 0, yco-=20, 120, 19, "");
+#endif
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+
+ return block;
+}
+
+static void do_view3d_pose_armature_transformmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
+
+ switch(event) {
+ case 0: /* clear origin */
+ clear_object('o');
+ break;
+ case 1: /* clear scale */
+ clear_object('s');
+ break;
+ case 2: /* clear rotation */
+ clear_object('r');
+ break;
+ case 3: /* clear location */
+ clear_object('g');
+ break;
+ case 4: /* clear user transform */
+ clear_user_transform(scene, ob);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_pose_armature_transformmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_pose_armature_transformmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_pose_armature_transformmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear User Transform|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Location|Alt G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Rotation|Alt R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Scale|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Origin|Alt O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_pose_armature_showhidemenu(bContext *C, void *arg, int event)
+{
+#if 0
+
+ switch(event) {
+
+ case 0: /* show hidden bones */
+ show_all_pose_bones();
+ break;
+ case 1: /* hide selected bones */
+ hide_selected_pose_bones();
+ break;
+ case 2: /* hide deselected bones */
+ hide_unselected_pose_bones();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_pose_armature_showhidemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_pose_armature_showhidemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_pose_armature_showhidemenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Hidden|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Hide Selected|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Hide Unselected|Shift H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_pose_armature_ikmenu(bContext *C, void *arg, int event)
+{
+#if 0
+
+ switch(event) {
+
+ case 1:
+ pose_add_IK();
+ break;
+ case 2:
+ pose_clear_IK();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_pose_armature_ikmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_pose_armature_ikmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_pose_armature_ikmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add IK to Bone...|Shift I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear IK...|Ctrl Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_pose_armature_constraintsmenu(bContext *C, void *arg, int event)
+{
+#if 0
+
+ switch(event) {
+
+ case 1:
+ add_constraint(0);
+ break;
+ case 2:
+ pose_clear_constraints();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_pose_armature_constraintsmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_pose_armature_constraintsmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_pose_armature_constraintsmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Constraint to Bone...|Ctrl Alt C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Constraints...|Alt C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_pose_armature_groupmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch (event) {
+ case 1:
+ pose_assign_to_posegroup(1);
+ break;
+ case 2:
+ pose_assign_to_posegroup(0);
+ break;
+ case 3:
+ pose_add_posegroup();
+ break;
+ case 4:
+ pose_remove_from_posegroups();
+ break;
+ case 5:
+ pose_remove_posegroup();
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_pose_armature_groupmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_pose_armature_groupmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_pose_armature_groupmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Selected to Active Group|Ctrl G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Selected to Group|Ctrl G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add New Group|Ctrl G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Remove from All Groups|Ctrl G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Remove Active Group|Ctrl G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_pose_armature_motionpathsmenu(bContext *C, void *arg, int event)
+{
+#if 0
+
+ switch(event) {
+
+ case 1:
+ pose_calculate_path(OBACT);
+ break;
+ case 2:
+ pose_clear_paths(OBACT);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_pose_armature_motionpathsmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_pose_armature_motionpathsmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_pose_armature_motionpathsmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Calculate Paths|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear All Paths|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_pose_armature_poselibmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ Object *ob= OBACT;
+
+ switch(event) {
+ case 1:
+ poselib_preview_poses(ob, 0);
+ break;
+ case 2:
+ poselib_add_current_pose(ob, 0);
+ break;
+ case 3:
+ poselib_rename_pose(ob);
+ break;
+ case 4:
+ poselib_remove_pose(ob, NULL);
+ break;
+ }
+
+#endif
+}
+
+static uiBlock *view3d_pose_armature_poselibmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_pose_armature_poselibmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_pose_armature_poselibmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Browse Poses|Ctrl L", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add/Replace Pose|Shift L", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rename Pose|Ctrl Shift L", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Remove Pose|Alt L", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_pose_armaturemenu(bContext *C, void *arg, int event)
+{
+#if 0
+ Object *ob;
+ ob=OBACT;
+
+ switch(event) {
+ case 0: /* transform properties */
+// XXX mainqenter(NKEY, 1);
+ break;
+ case 1: /* copy current pose */
+ copy_posebuf();
+ break;
+ case 2: /* paste pose */
+ paste_posebuf(0);
+ break;
+ case 3: /* paste flipped pose */
+ paste_posebuf(1);
+ break;
+ case 4: /* insert keyframe */
+ common_insertkey();
+ break;
+ case 5:
+ pose_copy_menu();
+ break;
+ case 9:
+ pose_flip_names();
+ break;
+ case 13:
+ if(ob && (ob->flag & OB_POSEMODE)) {
+ bArmature *arm= ob->data;
+ if( (arm->drawtype == ARM_B_BONE) || (arm->drawtype == ARM_ENVELOPE)) {
+ initTransform(TFM_BONESIZE, CTX_NONE);
+ Transform();
+ break;
+ }
+ }
+ break;
+ case 14: /* move bone to layer / change armature layer */
+ pose_movetolayer();
+ break;
+ case 15:
+ pose_relax();
+ break;
+ case 16: /* auto-extensions for bones */
+ case 17:
+ case 18:
+ pose_autoside_names(event-16);
+ break;
+ case 19: /* assign pose as restpose */
+ apply_armature_pose2bones();
+ break;
+ case 20: /* delete keyframe */
+ common_deletekey();
+ break;
+ }
+
+#endif
+}
+
+static uiBlock *view3d_pose_armaturemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_pose_armaturemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_pose_armaturemenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Transform Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefIconTextBlockBut(block, view3d_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_pose_armature_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Clear Transform", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Scale Envelope Distance|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Keyframe|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Relax Pose|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Apply Pose as Restpose|Ctrl A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Copy Current Pose", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Paste Pose", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Paste Flipped Pose", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBlockBut(block, view3d_pose_armature_poselibmenu, NULL, ICON_RIGHTARROW_THIN, "Pose Library", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_pose_armature_motionpathsmenu, NULL, ICON_RIGHTARROW_THIN, "Motion Paths", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_pose_armature_groupmenu, NULL, ICON_RIGHTARROW_THIN, "Bone Groups", 0, yco-=20, 120, 19, "");
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIconTextBlockBut(block, view3d_pose_armature_ikmenu, NULL, ICON_RIGHTARROW_THIN, "Inverse Kinematics", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_pose_armature_constraintsmenu, NULL, ICON_RIGHTARROW_THIN, "Constraints", 0, yco-=20, 120, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "AutoName Left-Right|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "AutoName Front-Back|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "AutoName Top-Bottom|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Flip L/R Names|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Copy Attributes...|Ctrl C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Switch Armature Layers|Shift M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Move Bone To Layer|M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBlockBut(block, view3d_pose_armature_showhidemenu,
+ NULL, ICON_RIGHTARROW_THIN, "Show/Hide Bones", 0, yco-=20, 120, 19, "");
+ uiDefIconTextBlockBut(block, view3d_armature_settingsmenu,
+ NULL, ICON_RIGHTARROW_THIN, "Bone Settings", 0, yco-=20, 120, 19, "");
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+
+ return block;
+}
+
+/* vertex paint menu */
+static void do_view3d_vpaintmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ /* events >= 3 are registered bpython scripts */
+#ifndef DISABLE_PYTHON
+ if (event >= 3) BPY_menu_do_python(PYMENU_VERTEXPAINT, event - 3);
+#endif
+ switch(event) {
+ case 0: /* undo vertex painting */
+ BIF_undo();
+ break;
+ case 1: /* set vertex colors/weight */
+ if(FACESEL_PAINT_TEST)
+ clear_vpaint_selectedfaces();
+ else /* we know were in vertex paint mode */
+ clear_vpaint();
+ break;
+ case 2:
+ make_vertexcol(1);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_vpaintmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+#ifndef DISABLE_PYTHON
+// XXX BPyMenu *pym;
+// int i=0;
+#endif
+
+ block= uiBeginBlock(C, ar, "view3d_paintmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_vpaintmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Undo Vertex Painting|U", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Vertex Colors|Shift K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Shaded Vertex Colors", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+#ifndef DISABLE_PYTHON
+ /* note that we account for the 3 previous entries with i+3:
+ even if the last item isnt displayed, it dosent matter */
+// for (pym = BPyMenuTable[PYMENU_VERTEXPAINT]; pym; pym = pym->next, i++) {
+// uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20,
+// menuwidth, 19, NULL, 0.0, 0.0, 1, i+3,
+// pym->tooltip?pym->tooltip:pym->filename);
+// }
+#endif
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+
+/* texture paint menu (placeholder, no items yet??) */
+static void do_view3d_tpaintmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch(event) {
+ case 0: /* undo image painting */
+ undo_imagepaint_step(1);
+ break;
+ }
+
+#endif
+}
+
+static uiBlock *view3d_tpaintmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_paintmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_tpaintmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Undo Texture Painting|U", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+
+static void do_view3d_wpaintmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ Object *ob= OBACT;
+
+ /* events >= 3 are registered bpython scripts */
+#ifndef DISABLE_PYTHON
+ if (event >= 4) BPY_menu_do_python(PYMENU_WEIGHTPAINT, event - 4);
+#endif
+ switch(event) {
+ case 0: /* undo weight painting */
+ BIF_undo();
+ break;
+ case 1: /* set vertex colors/weight */
+ clear_wpaint_selectedfaces();
+ break;
+ case 2: /* vgroups from envelopes */
+ pose_adds_vgroups(ob, 0);
+ break;
+ case 3: /* vgroups from bone heat */
+ pose_adds_vgroups(ob, 1);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_wpaintmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120, menunr=1;
+#ifndef DISABLE_PYTHON
+// XXX BPyMenu *pym;
+// int i=0;
+#endif
+
+ block= uiBeginBlock(C, ar, "view3d_paintmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_wpaintmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Undo Weight Painting|U", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Apply Bone Heat Weights to Vertex Groups|W, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Apply Bone Envelopes to Vertex Groups|W, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ if (FACESEL_PAINT_TEST) {
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Weight|Shift K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ menunr++;
+ }
+
+#ifndef DISABLE_PYTHON
+ /* note that we account for the 4 previous entries with i+4:
+ even if the last item isnt displayed, it dosent matter */
+// for (pym = BPyMenuTable[PYMENU_WEIGHTPAINT]; pym; pym = pym->next, i++) {
+// uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20,
+// menuwidth, 19, NULL, 0.0, 0.0, 1, i+4,
+// pym->tooltip?pym->tooltip:pym->filename);
+// }
+#endif
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+void do_view3d_sculpt_inputmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ Scene *scene= CTX_data_scene(C);
+ SculptData *sd= &scene->sculptdata;
+ short val;
+
+ switch(event) {
+ case 0:
+ sd->flags ^= SCULPT_INPUT_SMOOTH;
+ ED_undo_push(C, "Smooth stroke");
+ break;
+ case 1:
+ val= sd->tablet_size;
+ if(button(&val,0,10,"Tablet Size:")==0) return;
+ sd->tablet_size= val;
+ ED_undo_push(C, "Tablet size");
+ break;
+ case 2:
+ val= sd->tablet_strength;
+ if(button(&val,0,10,"Tablet Strength:")==0) return;
+ sd->tablet_strength= val;
+ ED_undo_push(C, "Tablet strength");
+ break;
+ }
+
+#endif
+}
+
+void do_view3d_sculptmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ Scene *scene= CTX_data_scene(C);
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= sa->spacedata.first;
+ SculptData *sd= &scene->sculptdata;
+ BrushData *br= sculptmode_brush();
+
+ switch(event) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ sd->brush_type= event+1;
+ ED_undo_push(C, "Brush type");
+ break;
+ case 11:
+ if(v3d)
+ v3d->pivot_last= !v3d->pivot_last;
+ break;
+ case 12:
+ sd->flags ^= SCULPT_DRAW_FAST;
+ ED_undo_push(C, "Partial Redraw");
+ break;
+ case 13:
+ sd->flags ^= SCULPT_DRAW_BRUSH;
+ ED_undo_push(C, "Draw Brush");
+ break;
+ case 14:
+ add_blockhandler(sa, VIEW3D_HANDLER_OBJECT, UI_PNL_UNSTOW);
+ break;
+ case 15:
+ sculpt_radialcontrol_start(RADIALCONTROL_ROTATION);
+ break;
+ case 16:
+ sculpt_radialcontrol_start(RADIALCONTROL_STRENGTH);
+ break;
+ case 17:
+ sculpt_radialcontrol_start(RADIALCONTROL_SIZE);
+ break;
+#endif
+}
+
+uiBlock *view3d_sculpt_inputmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth= 120;
+ Sculpt *sd= CTX_data_tool_settings(C)->sculpt;
+
+ block= uiBeginBlock(C, ar, "view3d_sculpt_inputmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_sculpt_inputmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ((sd->flags & SCULPT_INPUT_SMOOTH) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT), "Smooth Stroke|Shift S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Tablet Size Adjust", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Tablet Strength Adjust", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+static void view3d_sculpt_menu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ bScreen *sc= CTX_wm_screen(C);
+ Sculpt *s = CTX_data_tool_settings(C)->sculpt;
+ PointerRNA rna;
+
+ RNA_pointer_create(&sc->id, &RNA_Sculpt, s, &rna);
+
+ uiMenuItemBooleanR(head, &rna, "symmetry_x");
+ uiMenuItemBooleanR(head, &rna, "symmetry_y");
+ uiMenuItemBooleanR(head, &rna, "symmetry_z");
+ uiMenuItemBooleanR(head, &rna, "lock_x");
+ uiMenuItemBooleanR(head, &rna, "lock_y");
+ uiMenuItemBooleanR(head, &rna, "lock_z");
+
+ /* Brush settings */
+ RNA_pointer_create(&sc->id, &RNA_Brush, s->brush, &rna);
+
+ /* Curve */
+ uiMenuSeparator(head);
+ uiMenuItemEnumO(head, "", 0, "SCULPT_OT_brush_curve_preset", "mode", BRUSH_PRESET_SHARP);
+ uiMenuItemEnumO(head, "", 0, "SCULPT_OT_brush_curve_preset", "mode", BRUSH_PRESET_SMOOTH);
+ uiMenuItemEnumO(head, "", 0, "SCULPT_OT_brush_curve_preset", "mode", BRUSH_PRESET_MAX);
+
+ uiMenuSeparator(head);
+
+ uiMenuItemBooleanR(head, &rna, "airbrush");
+ uiMenuItemBooleanR(head, &rna, "rake");
+ uiMenuItemBooleanR(head, &rna, "anchored");
+ uiMenuItemBooleanR(head, &rna, "space");
+
+ uiMenuItemBooleanR(head, &rna, "flip_direction");
+}
+
+uiBlock *view3d_sculptmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= sa->spacedata.first;
+ uiBlock *block;
+ Sculpt *sd= CTX_data_tool_settings(C)->sculpt;
+// XXX const BrushData *br= sculptmode_brush();
+ short yco= 0, menuwidth= 120;
+
+ block= uiBeginBlock(C, ar, "view3d_sculptmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_sculptmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Sculpt Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 14, "");
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIconTextBlockBut(block, view3d_sculpt_inputmenu, NULL, ICON_RIGHTARROW_THIN, "Input Settings", 0, yco-=20, 120, 19, "");
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ((sd->flags & SCULPT_DRAW_BRUSH) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT), "Display Brush", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+ uiDefIconTextBut(block, BUTM, 1, ((sd->flags & SCULPT_DRAW_FAST) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT), "Partial Redraw", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
+ if(v3d)
+ uiDefIconTextBut(block, BUTM, 1, (v3d->pivot_last ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT), "Pivot Last", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Scale Brush|F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Strengthen Brush|Shift F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rotate Brush|Ctrl F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ /* XXX uiDefIconTextBut(block, BUTM, 1, (sd->brush_type==FLATTEN_BRUSH ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT), "Flatten|T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+ uiDefIconTextBut(block, BUTM, 1, (sd->brush_type==LAYER_BRUSH ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT), "Layer|L", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ uiDefIconTextBut(block, BUTM, 1, (sd->brush_type==GRAB_BRUSH ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT), "Grab|G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, (sd->brush_type==INFLATE_BRUSH ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT), "Inflate|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefIconTextBut(block, BUTM, 1, (sd->brush_type==PINCH_BRUSH ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT), "Pinch|P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, (sd->brush_type==SMOOTH_BRUSH ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT), "Smooth|S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefIconTextBut(block, BUTM, 1, (sd->brush_type==DRAW_BRUSH ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT), "Draw|D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");*/
+
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+
+ return block;
+}
+
+static void do_view3d_facesel_showhidemenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch(event) {
+ case 4: /* show hidden faces */
+ reveal_tface();
+ break;
+ case 5: /* hide selected faces */
+ hide_tface();
+ break;
+ case 6: /* XXX hide deselected faces */
+// G.qual |= LR_SHIFTKEY;
+ hide_tface();
+// G.qual &= ~LR_SHIFTKEY;
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_facesel_showhidemenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 20, menuwidth = 120;
+
+ block= uiBeginBlock(C, ar, "view3d_facesel_showhidemenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_facesel_showhidemenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Hidden Faces|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Hide Selected Faces|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Hide Unselected Faces|Shift H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+static void do_view3d_faceselmenu(bContext *C, void *arg, int event)
+{
+#if 0
+ switch(event) {
+ case 0: /* set vertex colors */
+ clear_vpaint_selectedfaces();
+ break;
+ case 1: /* mark border seam */
+ seam_mark_clear_tface(1);
+ break;
+ case 2: /* clear seam */
+ seam_mark_clear_tface(2);
+ break;
+ }
+#endif
+}
+
+static uiBlock *view3d_faceselmenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiBeginBlock(C, ar, "view3d_faceselmenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_view3d_faceselmenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Vertex Colors|Shift K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Seam|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Mark Border Seam|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBlockBut(block, view3d_facesel_showhidemenu, NULL, ICON_RIGHTARROW_THIN, "Show/Hide Faces", 0, yco-=20, 120, 19, "");
+
+ if(ar->alignment==RGN_ALIGN_TOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+ return block;
+}
+
+static void view3d_select_particlemenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ Scene *scene= CTX_data_scene(C);
+
+ uiMenuItemO(head, 0, "VIEW3D_OT_select_border");
+
+ uiMenuSeparator(head);
+
+ uiMenuItemO(head, 0, "PARTICLE_OT_select_all_toggle");
+ uiMenuItemO(head, 0, "PARTICLE_OT_select_linked");
+
+ if(scene->selectmode & SCE_SELECT_POINT) {
+ uiMenuItemO(head, 0, "PARTICLE_OT_select_last"); // |W, 4
+ uiMenuItemO(head, 0, "PARTICLE_OT_select_first"); // |W, 3
+ }
+
+ uiMenuSeparator(head);
+
+ uiMenuItemO(head, 0, "PARTICLE_OT_select_more");
+ uiMenuItemO(head, 0, "PARTICLE_OT_select_less");
+}
+
+static void view3d_particle_showhidemenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ uiMenuItemO(head, 0, "PARTICLE_OT_reveal");
+ uiMenuItemO(head, 0, "PARTICLE_OT_hide");
+ uiMenuItemBooleanO(head, "Hide Unselected", 0, "PARTICLE_OT_hide", "unselected", 1);
+}
+
+static void view3d_particlemenu(bContext *C, uiMenuItem *head, void *arg_unused)
+{
+ Scene *scene= CTX_data_scene(C);
+
+ // XXX uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Particle Edit Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
+ // add_blockhandler(sa, VIEW3D_HANDLER_OBJECT, UI_PNL_UNSTOW);
+ // XXX uiMenuSeparator(head);
+ //
+ // XXX uiDefIconTextBut(block, BUTM, 1, (pset->flag & PE_X_MIRROR)? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT, "X-Axis Mirror Editing", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+ // pset->flag ^= PE_X_MIRROR;
+
+ uiMenuItemO(head, 0, "PARTICLE_OT_mirror"); // |Ctrl M
+
+ uiMenuSeparator(head);
+
+ uiMenuItemO(head, 0, "PARTICLE_OT_remove_doubles"); // |W, 5
+ uiMenuItemO(head, 0, "PARTICLE_OT_delete");
+ if(scene->selectmode & SCE_SELECT_POINT)
+ uiMenuItemO(head, 0, "PARTICLE_OT_subdivide"); // |W, 2
+ uiMenuItemO(head, 0, "PARTICLE_OT_rekey"); // |W, 1
+
+ uiMenuSeparator(head);
+
+ uiMenuLevel(head, "Show/Hide Particles", view3d_particle_showhidemenu);
+}
+
+static char *view3d_modeselect_pup(Scene *scene)
+{
+ Object *ob= OBACT;
+ static char string[1024];
+ static char formatstr[] = "|%s %%x%d %%i%d";
+ char *str = string;
+
+ str += sprintf(str, "Mode: %%t");
+
+ if(ob)
+ str += sprintf(str, formatstr, "Object Mode", V3D_OBJECTMODE_SEL, ICON_OBJECT_DATA);
+ else
+ str += sprintf(str, formatstr, " ", V3D_OBJECTMODE_SEL, ICON_OBJECT_DATA);
+
+ if(ob==NULL) return string;
+
+ /* if active object is editable */
+ if ( ((ob->type == OB_MESH) || (ob->type == OB_ARMATURE)
+ || (ob->type == OB_CURVE) || (ob->type == OB_SURF) || (ob->type == OB_FONT)
+ || (ob->type == OB_MBALL) || (ob->type == OB_LATTICE))) {
+
+ str += sprintf(str, formatstr, "Edit Mode", V3D_EDITMODE_SEL, ICON_EDITMODE_HLT);
+ }
+
+ if (ob->type == OB_MESH) {
+
+ str += sprintf(str, formatstr, "Sculpt Mode", V3D_SCULPTMODE_SEL, ICON_SCULPTMODE_HLT);
+ /*str += sprintf(str, formatstr, "Face Select", V3D_FACESELECTMODE_SEL, ICON_FACESEL_HLT);*/
+ str += sprintf(str, formatstr, "Vertex Paint", V3D_VERTEXPAINTMODE_SEL, ICON_VPAINT_HLT);
+ str += sprintf(str, formatstr, "Texture Paint", V3D_TEXTUREPAINTMODE_SEL, ICON_TPAINT_HLT);
+ str += sprintf(str, formatstr, "Weight Paint", V3D_WEIGHTPAINTMODE_SEL, ICON_WPAINT_HLT);
+ }
+
+
+ /* if active object is an armature */
+ if (ob->type==OB_ARMATURE) {
+ str += sprintf(str, formatstr, "Pose Mode", V3D_POSEMODE_SEL, ICON_POSE_HLT);
+ }
+
+ if (ob->particlesystem.first) {
+ str += sprintf(str, formatstr, "Particle Mode", V3D_PARTICLEEDITMODE_SEL, ICON_PARTICLEMODE);
+ }
+
+ return (string);
+}
+
+
+static char *drawtype_pup(void)
+{
+ static char string[512];
+ char *str = string;
+
+ str += sprintf(str, "%s", "Draw type: %t");
+ str += sprintf(str, "%s", "|Bounding Box %x1");
+ str += sprintf(str, "%s", "|Wireframe %x2");
+ str += sprintf(str, "%s", "|Solid %x3");
+ str += sprintf(str, "%s", "|Shaded %x4");
+ str += sprintf(str, "%s", "|Textured %x5");
+ return string;
+}
+static char *around_pup(const bContext *C)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ static char string[512];
+ char *str = string;
+
+ str += sprintf(str, "%s", "Pivot: %t");
+ str += sprintf(str, "%s", "|Bounding Box Center %x0");
+ str += sprintf(str, "%s", "|Median Point %x3");
+ str += sprintf(str, "%s", "|3D Cursor %x1");
+ str += sprintf(str, "%s", "|Individual Centers %x2");
+ if ((obedit) && (obedit->type == OB_MESH))
+ str += sprintf(str, "%s", "|Active Vert/Edge/Face %x4");
+ else
+ str += sprintf(str, "%s", "|Active Object %x4");
+ return string;
+}
+
+static char *ndof_pup(void)
+{
+ static char string[512];
+ char *str = string;
+
+ str += sprintf(str, "%s", "ndof mode: %t");
+ str += sprintf(str, "%s", "|turntable %x0");
+ str += sprintf(str, "%s", "|fly %x1");
+ str += sprintf(str, "%s", "|transform %x2");
+ return string;
+}
+
+
+static char *snapmode_pup(void)
+{
+ static char string[512];
+ char *str = string;
+
+ str += sprintf(str, "%s", "Snap Element: %t");
+ str += sprintf(str, "%s", "|Vertex%x0");
+ str += sprintf(str, "%s", "|Edge%x1");
+ str += sprintf(str, "%s", "|Face%x2");
+ str += sprintf(str, "%s", "|Volume%x3");
+ return string;
+}
+
+static char *propfalloff_pup(void)
+{
+ static char string[512];
+ char *str = string;
+
+ str += sprintf(str, "%s", "Falloff: %t");
+ str += sprintf(str, "%s", "|Smooth Falloff%x0");
+ str += sprintf(str, "%s", "|Sphere Falloff%x1");
+ str += sprintf(str, "%s", "|Root Falloff%x2");
+ str += sprintf(str, "%s", "|Sharp Falloff%x3");
+ str += sprintf(str, "%s", "|Linear Falloff%x4");
+ str += sprintf(str, "%s", "|Random Falloff%x6");
+ str += sprintf(str, "%s", "|Constant, No Falloff%x5");
+ return string;
+}
+
+
+static void do_view3d_header_buttons(bContext *C, void *arg, int event)
+{
+ wmWindow *win= CTX_wm_window(C);
+ Scene *scene= CTX_data_scene(C);
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= sa->spacedata.first;
+ Base *basact= CTX_data_active_base(C);
+ Object *ob= CTX_data_active_object(C);
+ Object *obedit = CTX_data_edit_object(C);
+ EditMesh *em= NULL;
+ int bit, ctrl= win->eventstate->ctrl, shift= win->eventstate->shift;
+
+ if(obedit && obedit->type==OB_MESH) {
+ em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ }
+ /* watch it: if sa->win does not exist, check that when calling direct drawing routines */
+
+ switch(event) {
+ case B_HOME:
+ WM_operator_name_call(C, "VIEW3D_OT_viewhome", WM_OP_EXEC_REGION_WIN, NULL);
+ break;
+ case B_REDR:
+ ED_area_tag_redraw(sa);
+ break;
+ case B_SCENELOCK:
+ if(v3d->scenelock) {
+ v3d->lay= scene->lay;
+ /* seek for layact */
+ bit= 0;
+ while(bit<32) {
+ if(v3d->lay & (1<<bit)) {
+ v3d->layact= 1<<bit;
+ break;
+ }
+ bit++;
+ }
+ v3d->camera= scene->camera;
+ ED_area_tag_redraw(sa);
+ }
+ break;
+
+ case B_VIEWBUT:
+
+
+ case B_PERSP:
+
+
+ break;
+ case B_VIEWRENDER:
+ if (sa->spacetype==SPACE_VIEW3D) {
+// XXX BIF_do_ogl_render(v3d, shift);
+ }
+ break;
+ case B_STARTGAME:
+// XXX start_game();
+ break;
+ case B_MODESELECT:
+ if (v3d->modeselect == V3D_OBJECTMODE_SEL) {
+
+ v3d->flag &= ~V3D_MODE;
+ ED_view3d_exit_paint_modes(C);
+ ED_armature_exit_posemode(C, basact);
+ if(obedit)
+ ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */
+ }
+ else if (v3d->modeselect == V3D_EDITMODE_SEL) {
+ if(!obedit) {
+ v3d->flag &= ~V3D_MODE;
+ ED_object_enter_editmode(C, EM_WAITCURSOR);
+ ED_undo_push(C, "Original"); /* here, because all over code enter_editmode is abused */
+ }
+ }
+ else if (v3d->modeselect == V3D_SCULPTMODE_SEL) {
+ if (!(G.f & G_SCULPTMODE)) {
+ v3d->flag &= ~V3D_MODE;
+ ED_view3d_exit_paint_modes(C);
+ if(obedit) ED_object_exit_editmode(C, EM_FREEUNDO|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */
+
+ WM_operator_name_call(C, "SCULPT_OT_sculptmode_toggle", WM_OP_EXEC_REGION_WIN, NULL);
+ }
+ }
+ else if (v3d->modeselect == V3D_VERTEXPAINTMODE_SEL) {
+ if (!(G.f & G_VERTEXPAINT)) {
+ v3d->flag &= ~V3D_MODE;
+ ED_view3d_exit_paint_modes(C);
+ if(obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */
+
+ WM_operator_name_call(C, "PAINT_OT_vertex_paint_toggle", WM_OP_EXEC_REGION_WIN, NULL);
+ }
+ }
+ else if (v3d->modeselect == V3D_TEXTUREPAINTMODE_SEL) {
+ if (!(G.f & G_TEXTUREPAINT)) {
+ v3d->flag &= ~V3D_MODE;
+ ED_view3d_exit_paint_modes(C);
+ if(obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */
+
+ WM_operator_name_call(C, "PAINT_OT_texture_paint_toggle", WM_OP_EXEC_REGION_WIN, NULL);
+ }
+ }
+ else if (v3d->modeselect == V3D_WEIGHTPAINTMODE_SEL) {
+ if (!(G.f & G_WEIGHTPAINT) && (ob && ob->type == OB_MESH) ) {
+ v3d->flag &= ~V3D_MODE;
+ ED_view3d_exit_paint_modes(C);
+ if(obedit)
+ ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */
+
+ WM_operator_name_call(C, "PAINT_OT_weight_paint_toggle", WM_OP_EXEC_REGION_WIN, NULL);
+ }
+ }
+ else if (v3d->modeselect == V3D_POSEMODE_SEL) {
+
+ if (ob) {
+ v3d->flag &= ~V3D_MODE;
+ if(obedit)
+ ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */
+
+ ED_armature_enter_posemode(C, basact);
+ }
+ }
+ else if(v3d->modeselect == V3D_PARTICLEEDITMODE_SEL){
+ if (!(G.f & G_PARTICLEEDIT)) {
+ v3d->flag &= ~V3D_MODE;
+ ED_view3d_exit_paint_modes(C);
+ if(obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */
+
+ WM_operator_name_call(C, "PARTICLE_OT_particle_edit_toggle", WM_OP_EXEC_REGION_WIN, NULL);
+ }
+ }
+ break;
+
+ case B_AROUND:
+// XXX handle_view3d_around(); /* copies to other 3d windows */
+ break;
+
+ case B_SEL_VERT:
+ if(em) {
+ if(shift==0 || em->selectmode==0)
+ em->selectmode= SCE_SELECT_VERTEX;
+ scene->selectmode= em->selectmode;
+ EM_selectmode_set(em);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ ED_undo_push(C, "Selectmode Set: Vertex");
+ }
+ break;
+ case B_SEL_EDGE:
+ if(em) {
+ if(shift==0 || em->selectmode==0){
+ if( (em->selectmode ^ SCE_SELECT_EDGE) == SCE_SELECT_VERTEX){
+ if(ctrl) EM_convertsel(em, SCE_SELECT_VERTEX,SCE_SELECT_EDGE);
+ }
+ em->selectmode = SCE_SELECT_EDGE;
+ }
+ scene->selectmode= em->selectmode;
+ EM_selectmode_set(em);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ ED_undo_push(C, "Selectmode Set: Edge");
+ }
+ break;
+ case B_SEL_FACE:
+ if(em) {
+ if( shift==0 || em->selectmode==0){
+ if( ((scene->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || ((scene->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)){
+ if(ctrl) EM_convertsel(em, (scene->selectmode ^ SCE_SELECT_FACE),SCE_SELECT_FACE);
+ }
+ em->selectmode = SCE_SELECT_FACE;
+ }
+ scene->selectmode= em->selectmode;
+ EM_selectmode_set(em);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ ED_undo_push(C, "Selectmode Set: Face");
+ }
+ break;
+
+ case B_SEL_PATH:
+ scene->selectmode= SCE_SELECT_PATH;
+ ED_undo_push(C, "Selectmode Set: Path");
+ break;
+ case B_SEL_POINT:
+ scene->selectmode = SCE_SELECT_POINT;
+ ED_undo_push(C, "Selectmode Set: Point");
+ break;
+ case B_SEL_END:
+ scene->selectmode = SCE_SELECT_END;
+ ED_undo_push(C, "Selectmode Set: End point");
+ break;
+
+ case B_MAN_TRANS:
+ if( shift==0 || v3d->twtype==0)
+ v3d->twtype= V3D_MANIP_TRANSLATE;
+ break;
+ case B_MAN_ROT:
+ if( shift==0 || v3d->twtype==0)
+ v3d->twtype= V3D_MANIP_ROTATE;
+ break;
+ case B_MAN_SCALE:
+ if( shift==0 || v3d->twtype==0)
+ v3d->twtype= V3D_MANIP_SCALE;
+ break;
+ case B_NDOF:
+ break;
+ case B_MAN_MODE:
+ break;
+ case B_VIEW_BUTSEDIT:
+ break;
+
+ default:
+
+ if(event>=B_LAY && event<B_LAY+31) {
+ if(v3d->lay!=0 && shift) {
+
+ /* but do find active layer */
+
+ bit= event-B_LAY;
+ if( v3d->lay & (1<<bit)) v3d->layact= 1<<bit;
+ else {
+ if( (v3d->lay & v3d->layact) == 0) {
+ bit= 0;
+ while(bit<32) {
+ if(v3d->lay & (1<<bit)) {
+ v3d->layact= 1<<bit;
+ break;
+ }
+ bit++;
+ }
+ }
+ }
+ }
+ else {
+ bit= event-B_LAY;
+ v3d->lay= 1<<bit;
+ v3d->layact= v3d->lay;
+ }
+
+ if(v3d->scenelock) handle_view3d_lock();
+
+ ED_area_tag_redraw(sa);
+ countall();
+
+ /* new layers might need unflushed events events */
+ DAG_scene_update_flags(scene, v3d->lay); /* tags all that moves and flushes */
+
+ }
+ break;
+ }
+
+ if(obedit && obedit->type==OB_MESH)
+ BKE_mesh_end_editmesh(obedit->data, em);
+}
+
+static void view3d_header_pulldowns(const bContext *C, uiBlock *block, Object *ob, int *xcoord, int yco)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ RegionView3D *rv3d= wm_region_view3d(C);
+ short xmax, xco= *xcoord;
+
+
+ /* compensate for local mode when setting up the viewing menu/iconrow values */
+ if(rv3d->view==7) rv3d->viewbut= 1;
+ else if(rv3d->view==1) rv3d->viewbut= 2;
+ else if(rv3d->view==3) rv3d->viewbut= 3;
+ else rv3d->viewbut= 0;
+
+ /* the 'xmax - 3' rather than xmax is to prevent some weird flickering where the highlighted
+ * menu is drawn wider than it should be. The ypos of -2 is to make it properly fill the
+ * height of the header */
+
+ xmax= GetButStringLength("View");
+ uiDefMenuBut(block, view3d_viewmenu, NULL, "View", xco, yco, xmax-3, 20, "");
+ //uiDefPulldownBut(block, view3d_viewmenu, NULL, "View", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+
+ xmax= GetButStringLength("Select");
+ if (obedit) {
+ if (ob && ob->type == OB_MESH) {
+ uiDefPulldownBut(block, view3d_select_meshmenu, NULL, "Select", xco,yco, xmax-3, 24, "");
+ } else if (ob && (ob->type == OB_CURVE || ob->type == OB_SURF)) {
+ uiDefMenuBut(block, view3d_select_curvemenu, NULL, "Select", xco, yco, xmax-3, 24, "");
+ } else if (ob && ob->type == OB_FONT) {
+ xmax= 0;
+ } else if (ob && ob->type == OB_MBALL) {
+ uiDefPulldownBut(block, view3d_select_metaballmenu, NULL, "Select", xco,yco, xmax-3, 24, "");
+ } else if (ob && ob->type == OB_LATTICE) {
+ uiDefPulldownBut(block, view3d_select_latticemenu, NULL, "Select", xco,yco, xmax-3, 20, "");
+ } else if (ob && ob->type == OB_ARMATURE) {
+ uiDefPulldownBut(block, view3d_select_armaturemenu, NULL, "Select", xco,yco, xmax-3, 20, "");
+ }
+ } else if (FACESEL_PAINT_TEST) {
+ if (ob && ob->type == OB_MESH) {
+ uiDefPulldownBut(block, view3d_select_faceselmenu, NULL, "Select", xco,yco, xmax-3, 20, "");
+ }
+ } else if ((G.f & G_VERTEXPAINT) || (G.f & G_TEXTUREPAINT) || (G.f & G_WEIGHTPAINT)) {
+ uiDefBut(block, LABEL,0,"", xco, 0, xmax, 20, 0, 0, 0, 0, 0, "");
+ } else if (G.f & G_PARTICLEEDIT) {
+ uiDefMenuBut(block, view3d_select_particlemenu, NULL, "Select", xco,yco, xmax-3, 20, "");
+ } else {
+
+ if (ob && (ob->flag & OB_POSEMODE))
+ uiDefPulldownBut(block, view3d_select_pose_armaturemenu, NULL, "Select", xco,yco, xmax-3, 20, "");
+ else
+ uiDefPulldownBut(block, view3d_select_objectmenu, NULL, "Select", xco,yco, xmax-3, 20, "");
+ }
+ xco+= xmax;
+
+ if (obedit) {
+ if (ob && ob->type == OB_MESH) {
+ xmax= GetButStringLength("Mesh");
+ uiDefPulldownBut(block, view3d_edit_meshmenu, NULL, "Mesh", xco,yco, xmax-3, 20, "");
+ xco+= xmax;
+ } else if (ob && ob->type == OB_CURVE) {
+ xmax= GetButStringLength("Curve");
+ uiDefMenuBut(block, view3d_edit_curvemenu, NULL, "Curve", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+ } else if (ob && ob->type == OB_SURF) {
+ xmax= GetButStringLength("Surface");
+ uiDefMenuBut(block, view3d_edit_curvemenu, NULL, "Surface", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+ } else if (ob && ob->type == OB_FONT) {
+ xmax= GetButStringLength("Text");
+ uiDefMenuBut(block, view3d_edit_textmenu, NULL, "Text", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+ } else if (ob && ob->type == OB_MBALL) {
+ xmax= GetButStringLength("Metaball");
+ uiDefPulldownBut(block, view3d_edit_metaballmenu, NULL, "Metaball", xco,yco, xmax-3, 20, "");
+ xco+= xmax;
+ } else if (ob && ob->type == OB_LATTICE) {
+ xmax= GetButStringLength("Lattice");
+ uiDefPulldownBut(block, view3d_edit_latticemenu, NULL, "Lattice", xco,yco, xmax-3, 20, "");
+ xco+= xmax;
+ } else if (ob && ob->type == OB_ARMATURE) {
+ xmax= GetButStringLength("Armature");
+ uiDefPulldownBut(block, view3d_edit_armaturemenu, NULL, "Armature", xco,yco, xmax-3, 20, "");
+ xco+= xmax;
+ }
+
+ }
+ else if (G.f & G_WEIGHTPAINT) {
+ xmax= GetButStringLength("Paint");
+ uiDefPulldownBut(block, view3d_wpaintmenu, NULL, "Paint", xco,yco, xmax-3, 20, "");
+ xco+= xmax;
+ }
+ else if (G.f & G_VERTEXPAINT) {
+ xmax= GetButStringLength("Paint");
+ uiDefPulldownBut(block, view3d_vpaintmenu, NULL, "Paint", xco,yco, xmax-3, 20, "");
+ xco+= xmax;
+ }
+ else if (G.f & G_TEXTUREPAINT) {
+ xmax= GetButStringLength("Paint");
+ uiDefPulldownBut(block, view3d_tpaintmenu, NULL, "Paint", xco,yco, xmax-3, 20, "");
+ xco+= xmax;
+ }
+ else if( G.f & G_SCULPTMODE) {
+ xmax= GetButStringLength("Sculpt");
+ uiDefMenuBut(block, view3d_sculpt_menu, NULL, "Sculpt", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+ }
+ else if (FACESEL_PAINT_TEST) {
+ if (ob && ob->type == OB_MESH) {
+ xmax= GetButStringLength("Face");
+ uiDefPulldownBut(block, view3d_faceselmenu, NULL, "Face", xco,yco, xmax-3, 20, "");
+ xco+= xmax;
+ }
+ }
+ else if(G.f & G_PARTICLEEDIT) {
+ xmax= GetButStringLength("Particle");
+ uiDefMenuBut(block, view3d_particlemenu, NULL, "Particle", xco,yco, xmax-3, 20, "");
+ xco+= xmax;
+ }
+ else {
+ if (ob && (ob->flag & OB_POSEMODE)) {
+ xmax= GetButStringLength("Pose");
+ uiDefPulldownBut(block, view3d_pose_armaturemenu, NULL, "Pose", xco,yco, xmax-3, 20, "");
+ xco+= xmax;
+ }
+ else {
+ xmax= GetButStringLength("Object");
+ uiDefPulldownBut(block, view3d_edit_objectmenu, NULL, "Object", xco,yco, xmax-3, 20, "");
+ xco+= xmax;
+ }
+ }
+
+ *xcoord= xco;
+}
+
+static int view3d_layer_icon(int but_lay, int ob_lay, int used_lay)
+{
+ if (but_lay & ob_lay)
+ return ICON_LAYER_ACTIVE;
+ else if (but_lay & used_lay)
+ return ICON_LAYER_USED;
+ else
+ return ICON_BLANK1;
+}
+
+void view3d_header_buttons(const bContext *C, ARegion *ar)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= sa->spacedata.first;
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= OBACT;
+ Object *obedit = CTX_data_edit_object(C);
+ uiBlock *block;
+ int a, xco, yco= 3;
+
+ block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
+ uiBlockSetHandleFunc(block, do_view3d_header_buttons, NULL);
+
+ xco= ED_area_header_standardbuttons(C, block, yco);
+
+ if((sa->flag & HEADER_NO_PULLDOWN)==0)
+ view3d_header_pulldowns(C, block, ob, &xco, yco);
+
+ /* other buttons: */
+ uiBlockSetEmboss(block, UI_EMBOSS);
+
+ /* mode */
+ v3d->modeselect = V3D_OBJECTMODE_SEL;
+
+ if (obedit) v3d->modeselect = V3D_EDITMODE_SEL;
+ else if(ob && (ob->flag & OB_POSEMODE)) v3d->modeselect = V3D_POSEMODE_SEL;
+ else if (G.f & G_SCULPTMODE) v3d->modeselect = V3D_SCULPTMODE_SEL;
+ else if (G.f & G_WEIGHTPAINT) v3d->modeselect = V3D_WEIGHTPAINTMODE_SEL;
+ else if (G.f & G_VERTEXPAINT) v3d->modeselect = V3D_VERTEXPAINTMODE_SEL;
+ else if (G.f & G_TEXTUREPAINT) v3d->modeselect = V3D_TEXTUREPAINTMODE_SEL;
+ /*else if(G.f & G_FACESELECT) v3d->modeselect = V3D_FACESELECTMODE_SEL;*/
+ else if(G.f & G_PARTICLEEDIT) v3d->modeselect = V3D_PARTICLEEDITMODE_SEL;
+
+ v3d->flag &= ~V3D_MODE;
+
+ /* not sure what the v3d->flag is useful for now... modeselect is confusing */
+ if(obedit) v3d->flag |= V3D_EDITMODE;
+ if(ob && (ob->flag & OB_POSEMODE)) v3d->flag |= V3D_POSEMODE;
+ if(G.f & G_VERTEXPAINT) v3d->flag |= V3D_VERTEXPAINT;
+ if(G.f & G_WEIGHTPAINT) v3d->flag |= V3D_WEIGHTPAINT;
+ if (G.f & G_TEXTUREPAINT) v3d->flag |= V3D_TEXTUREPAINT;
+ if(FACESEL_PAINT_TEST) v3d->flag |= V3D_FACESELECT;
+
+ uiDefIconTextButS(block, MENU, B_MODESELECT, (v3d->modeselect),view3d_modeselect_pup(scene) ,
+ xco,yco,126,20, &(v3d->modeselect), 0, 0, 0, 0, "Mode (Hotkeys: Tab, V, Ctrl Tab)");
+
+ xco+= 126+8;
+
+ /* DRAWTYPE */
+ uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_BBOX, drawtype_pup(), xco,yco,XIC+10,YIC, &(v3d->drawtype), 1.0, 5.0, 0, 0, "Viewport Shading (Hotkeys: Z, Shift Z, Alt Z)");
+
+ /* around */
+ xco+= XIC+18;
+
+ uiBlockBeginAlign(block);
+
+ if(retopo_mesh_paint_check()) {
+ void *rpd= NULL; // XXX RetopoPaintData *rpd= get_retopo_paint_data();
+ if(rpd) {
+ ToolSettings *ts= scene->toolsettings;
+
+ uiDefButC(block,ROW,B_REDR,"Pen",xco,yco,40,20,&ts->retopo_paint_tool,6.0,RETOPO_PEN,0,0,"");
+ xco+=40;
+ uiDefButC(block,ROW,B_REDR,"Line",xco,yco,40,20,&ts->retopo_paint_tool,6.0,RETOPO_LINE,0,0,"");
+ xco+=40;
+ uiDefButC(block,ROW,B_REDR,"Ellipse",xco,yco,60,20,&ts->retopo_paint_tool,6.0,RETOPO_ELLIPSE,0,0,"");
+ xco+=65;
+
+ uiBlockBeginAlign(block);
+ if(ts->retopo_paint_tool == RETOPO_PEN) {
+ uiDefButC(block,TOG,B_NOP,"Hotspot",xco,yco,60,20, &ts->retopo_hotspot, 0,0,0,0,"Show hotspots at line ends to allow line continuation");
+ xco+=80;
+ }
+ else if(ts->retopo_paint_tool == RETOPO_LINE) {
+ uiDefButC(block,NUM,B_NOP,"LineDiv",xco,yco,80,20,&ts->line_div,1,50,0,0,"Subdivisions per retopo line");
+ xco+=80;
+ }
+ else if(ts->retopo_paint_tool == RETOPO_ELLIPSE) {
+ uiDefButC(block,NUM,B_NOP,"EllDiv",xco,yco,80,20,&ts->ellipse_div,3,50,0,0,"Subdivisions per retopo ellipse");
+ xco+=80;
+ }
+ xco+=5;
+
+ uiBlockEndAlign(block);
+ }
+ } else {
+ if (obedit==NULL && (G.f & (G_VERTEXPAINT|G_WEIGHTPAINT|G_TEXTUREPAINT))) {
+ uiDefIconButBitI(block, TOG, G_FACESELECT, B_VIEW_BUTSEDIT, ICON_FACESEL_HLT,xco,yco,XIC,YIC, &G.f, 0, 0, 0, 0, "Painting Mask (FKey)");
+ xco+= XIC+10;
+ } else {
+ /* Manipulators arnt used in weight paint mode */
+ char *str_menu;
+ uiDefIconTextButS(block, ICONTEXTROW,B_AROUND, ICON_ROTATE, around_pup(C), xco,yco,XIC+10,YIC, &(v3d->around), 0, 3.0, 0, 0, "Rotation/Scaling Pivot (Hotkeys: Comma, Shift Comma, Period, Ctrl Period, Alt Period)");
+
+ xco+= XIC+10;
+
+ uiDefIconButBitS(block, TOG, V3D_ALIGN, B_AROUND, ICON_ALIGN,
+ xco,yco,XIC,YIC,
+ &v3d->flag, 0, 0, 0, 0, "Move object centers only");
+ uiBlockEndAlign(block);
+
+ xco+= XIC+8;
+
+ uiBlockBeginAlign(block);
+
+ /* NDOF */
+ if (G.ndofdevice ==0 ) {
+ uiDefIconTextButC(block, ICONTEXTROW,B_NDOF, ICON_NDOF_TURN, ndof_pup(), xco,yco,XIC+10,YIC, &(v3d->ndofmode), 0, 3.0, 0, 0, "Ndof mode");
+
+ xco+= XIC+10;
+
+ uiDefIconButC(block, TOG, B_NDOF, ICON_NDOF_DOM,
+ xco,yco,XIC,YIC,
+ &v3d->ndoffilter, 0, 1, 0, 0, "dominant axis");
+ uiBlockEndAlign(block);
+
+ xco+= XIC+8;
+ }
+ uiBlockEndAlign(block);
+
+ /* Transform widget / manipulators */
+ uiBlockBeginAlign(block);
+ uiDefIconButBitS(block, TOG, V3D_USE_MANIPULATOR, B_REDR, ICON_MANIPUL,xco,yco,XIC,YIC, &v3d->twflag, 0, 0, 0, 0, "Use 3d transform manipulator (Ctrl Space)");
+ xco+= XIC;
+
+
+ if(v3d->twflag & V3D_USE_MANIPULATOR) {
+ uiDefIconButBitS(block, TOG, V3D_MANIP_TRANSLATE, B_MAN_TRANS, ICON_MAN_TRANS, xco,yco,XIC,YIC, &v3d->twtype, 1.0, 0.0, 0, 0, "Translate manipulator mode (Ctrl Alt G)");
+ xco+= XIC;
+ uiDefIconButBitS(block, TOG, V3D_MANIP_ROTATE, B_MAN_ROT, ICON_MAN_ROT, xco,yco,XIC,YIC, &v3d->twtype, 1.0, 0.0, 0, 0, "Rotate manipulator mode (Ctrl Alt R)");
+ xco+= XIC;
+ uiDefIconButBitS(block, TOG, V3D_MANIP_SCALE, B_MAN_SCALE, ICON_MAN_SCALE, xco,yco,XIC,YIC, &v3d->twtype, 1.0, 0.0, 0, 0, "Scale manipulator mode (Ctrl Alt S)");
+ xco+= XIC;
+ }
+
+ if (v3d->twmode > (BIF_countTransformOrientation(C) - 1) + V3D_MANIP_CUSTOM) {
+ v3d->twmode = 0;
+ }
+
+ str_menu = BIF_menustringTransformOrientation(C, "Orientation");
+ uiDefButS(block, MENU, B_MAN_MODE, str_menu,xco,yco,70,YIC, &v3d->twmode, 0, 0, 0, 0, "Transform Orientation (ALT+Space)");
+ MEM_freeN(str_menu);
+
+ xco+= 70;
+ uiBlockEndAlign(block);
+ xco+= 8;
+ }
+
+ /* LAYERS */
+ if(obedit==NULL && v3d->localview==0) {
+ int ob_lay = ob ? ob->lay : 0;
+ uiBlockBeginAlign(block);
+ for(a=0; a<5; a++) {
+ uiDefIconButBitI(block, TOG, 1<<a, B_LAY+a, view3d_layer_icon(1<<a, ob_lay, v3d->lay_used), (short)(xco+a*(XIC/2)), yco+(short)(YIC/2),(short)(XIC/2),(short)(YIC/2), &(v3d->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)");
+ }
+ for(a=0; a<5; a++) {
+ uiDefIconButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, view3d_layer_icon(1<<(a+10), ob_lay, v3d->lay_used), (short)(xco+a*(XIC/2)), yco, XIC/2, (YIC)/2, &(v3d->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)");
+ }
+ xco+= 5;
+ uiBlockBeginAlign(block);
+ for(a=5; a<10; a++) {
+ uiDefIconButBitI(block, TOG, 1<<a, B_LAY+a, view3d_layer_icon(1<<a, ob_lay, v3d->lay_used), (short)(xco+a*(XIC/2)), yco+(short)(YIC/2),(short)(XIC/2),(short)(YIC/2), &(v3d->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)");
+ }
+ for(a=5; a<10; a++) {
+ uiDefIconButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, view3d_layer_icon(1<<(a+10), ob_lay, v3d->lay_used), (short)(xco+a*(XIC/2)), yco, XIC/2, (YIC)/2, &(v3d->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)");
+ }
+ uiBlockEndAlign(block);
+
+ xco+= (a-2)*(XIC/2)+3;
+
+ /* LOCK */
+ uiDefIconButS(block, ICONTOG, B_SCENELOCK, ICON_LOCKVIEW_OFF, xco+=XIC,yco,XIC,YIC, &(v3d->scenelock), 0, 0, 0, 0, "Locks Active Camera and layers to Scene (Ctrl `)");
+ xco+= XIC+10;
+
+ }
+
+ /* proportional falloff */
+ if((obedit && (obedit->type == OB_MESH || obedit->type == OB_CURVE || obedit->type == OB_SURF || obedit->type == OB_LATTICE)) || G.f & G_PARTICLEEDIT) {
+
+ uiBlockBeginAlign(block);
+ uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_PROP_OFF, "Proportional %t|Off %x0|On %x1|Connected %x2", xco,yco,XIC+10,YIC, &(scene->proportional), 0, 1.0, 0, 0, "Proportional Edit Falloff (Hotkeys: O, Alt O) ");
+ xco+= XIC+10;
+
+ if(scene->proportional) {
+ uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_SMOOTHCURVE, propfalloff_pup(), xco,yco,XIC+10,YIC, &(scene->prop_mode), 0.0, 0.0, 0, 0, "Proportional Edit Falloff (Hotkey: Shift O) ");
+ xco+= XIC+10;
+ }
+ uiBlockEndAlign(block);
+ xco+= 10;
+ }
+
+ /* Snap */
+ if (BIF_snappingSupported(obedit)) {
+ uiBlockBeginAlign(block);
+
+ if (scene->snap_flag & SCE_SNAP) {
+ uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Use Snap or Grid (Shift Tab)");
+ xco+= XIC;
+ uiDefIconButBitS(block, TOG, SCE_SNAP_ROTATE, B_REDR, ICON_SNAP_NORMAL,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Align rotation with the snapping target");
+ xco+= XIC;
+ if (scene->snap_mode == SCE_SNAP_MODE_VOLUME) {
+ uiDefIconButBitS(block, TOG, SCE_SNAP_PEEL_OBJECT, B_REDR, 0 /* XXX 2.5 ICON_SNAP_PEEL_OBJECT */,xco,0,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Consider objects as whole when finding volume center");
+ xco+= XIC;
+ }
+ uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_SNAP_VERTEX, snapmode_pup(), xco,yco,XIC+10,YIC, &(scene->snap_mode), 0.0, 0.0, 0, 0, "Snapping mode");
+ xco+= XIC;
+ uiDefButS(block, MENU, B_NOP, "Snap Mode%t|Closest%x0|Center%x1|Median%x2|Active%x3",xco,yco,70,YIC, &scene->snap_target, 0, 0, 0, 0, "Snap Target Mode");
+ xco+= 70;
+ } else {
+ uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab)");
+ xco+= XIC;
+ }
+
+ uiBlockEndAlign(block);
+ xco+= 10;
+ }
+
+ /* selection modus */
+ if(obedit && (obedit->type == OB_MESH)) {
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ uiBlockBeginAlign(block);
+ uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, xco,yco,XIC,YIC, &em->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode (Ctrl Tab 1)");
+ xco+= XIC;
+ uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, xco,yco,XIC,YIC, &em->selectmode, 1.0, 0.0, 0, 0, "Edge select mode (Ctrl Tab 2)");
+ xco+= XIC;
+ uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, xco,yco,XIC,YIC, &em->selectmode, 1.0, 0.0, 0, 0, "Face select mode (Ctrl Tab 3)");
+ xco+= XIC;
+ uiBlockEndAlign(block);
+ if(v3d->drawtype > OB_WIRE) {
+ uiDefIconButBitS(block, TOG, V3D_ZBUF_SELECT, B_REDR, ICON_ORTHO, xco,yco,XIC,YIC, &v3d->flag, 1.0, 0.0, 0, 0, "Occlude background geometry");
+ xco+= XIC;
+ }
+ uiBlockEndAlign(block);
+ xco+= 20;
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ }
+ else if(G.f & G_PARTICLEEDIT) {
+ uiBlockBeginAlign(block);
+ uiDefIconButBitS(block, TOG, SCE_SELECT_PATH, B_SEL_PATH, ICON_EDGESEL, xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Path edit mode");
+ xco+= XIC;
+ uiDefIconButBitS(block, TOG, SCE_SELECT_POINT, B_SEL_POINT, ICON_VERTEXSEL, xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Point select mode");
+ xco+= XIC;
+ uiDefIconButBitS(block, TOG, SCE_SELECT_END, B_SEL_END, ICON_FACESEL, xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Tip select mode");
+ xco+= XIC;
+ uiBlockEndAlign(block);
+ if(v3d->drawtype > OB_WIRE) {
+ uiDefIconButBitS(block, TOG, V3D_ZBUF_SELECT, B_REDR, ICON_ORTHO, xco,yco,XIC,YIC, &v3d->flag, 1.0, 0.0, 0, 0, "Limit selection to visible (clipped with depth buffer)");
+ xco+= XIC;
+ }
+ uiBlockEndAlign(block);
+ xco+= 20;
+ }
+
+ uiDefIconBut(block, BUT, B_VIEWRENDER, ICON_SCENE, xco,yco,XIC,YIC, NULL, 0, 1.0, 0, 0, "Render this window (Ctrl Click for anim)");
+
+
+ if (ob && (ob->flag & OB_POSEMODE)) {
+ xco+= XIC/2;
+ uiBlockBeginAlign(block);
+
+ uiDefIconBut(block, BUT, B_ACTCOPY, ICON_COPYDOWN,
+ xco+=XIC,yco,XIC,YIC, 0, 0, 0, 0, 0,
+ "Copies the current pose to the buffer");
+ uiBlockSetButLock(block, object_data_is_libdata(ob), "Can't edit external libdata");
+ uiDefIconBut(block, BUT, B_ACTPASTE, ICON_PASTEDOWN,
+ xco+=XIC,yco,XIC,YIC, 0, 0, 0, 0, 0,
+ "Pastes the pose from the buffer");
+ uiDefIconBut(block, BUT, B_ACTPASTEFLIP, ICON_PASTEFLIPDOWN,
+ xco+=XIC,yco,XIC,YIC, 0, 0, 0, 0, 0,
+ "Pastes the mirrored pose from the buffer");
+
+ uiBlockEndAlign(block);
+ }
+ }
+
+ /* always as last */
+ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
+
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+}
+
+
+
+/* edit face toolbox */
+static int editmesh_face_toolbox_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ uiMenuItem *head;
+
+ head= uiPupMenuBegin("Edit Faces", 0);
+
+ uiMenuItemO(head, 0, "MESH_OT_fill");
+ uiMenuItemO(head, 0, "MESH_OT_beauty_fill");
+ uiMenuItemO(head, 0, "MESH_OT_quads_convert_to_tris");
+ uiMenuItemO(head, 0, "MESH_OT_tris_convert_to_quads");
+ uiMenuItemO(head, 0, "MESH_OT_edge_flip");
+ uiMenuItemO(head, 0, "MESH_OT_faces_shade_smooth");
+ uiMenuItemO(head, 0, "MESH_OT_faces_shade_solid");
+ uiPupMenuEnd(C, head);
+
+ return OPERATOR_CANCELLED;
+}
+
+void VIEW3D_OT_editmesh_face_toolbox(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Edit Faces";
+ ot->idname= "VIEW3D_OT_editmesh_face_toolbox";
+
+ /* api callbacks */
+ ot->invoke= editmesh_face_toolbox_invoke;
+ ot->poll= ED_operator_editmesh;
+}
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
new file mode 100644
index 00000000000..ae77b4293bf
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -0,0 +1,156 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_VIEW3D_INTERN_H
+#define ED_VIEW3D_INTERN_H
+
+#include "ED_view3d.h"
+
+/* internal exports only */
+
+struct bScreen;
+struct ARegion;
+struct BoundBox;
+struct Object;
+struct DerivedMesh;
+struct wmOperatorType;
+struct bContext;
+struct wmWindowManager;
+struct EditMesh;
+struct ViewContext;
+
+/* drawing flags: */
+#define DRAW_PICKING 1
+#define DRAW_CONSTCOLOR 2
+#define DRAW_SCENESET 4
+
+#define V3D_XRAY 1
+#define V3D_TRANSP 2
+
+#define V3D_SELECT_MOUSE 1
+
+/* view3d_header.c */
+void view3d_header_buttons(const struct bContext *C, struct ARegion *ar);
+void VIEW3D_OT_layers(struct wmOperatorType *ot);
+
+/* view3d_ops.c */
+void view3d_operatortypes(void);
+void view3d_keymap(struct wmWindowManager *wm);
+
+/* view3d_edit.c */
+void VIEW3D_OT_zoom(struct wmOperatorType *ot);
+void VIEW3D_OT_viewmove(struct wmOperatorType *ot);
+void VIEW3D_OT_viewrotate(struct wmOperatorType *ot);
+void VIEW3D_OT_viewhome(struct wmOperatorType *ot);
+void VIEW3D_OT_viewnumpad(struct wmOperatorType *ot);
+void VIEW3D_OT_viewcenter(struct wmOperatorType *ot);
+void VIEW3D_OT_view_pan(struct wmOperatorType *ot);
+void VIEW3D_OT_view_persportho(struct wmOperatorType *ot);
+void VIEW3D_OT_view_orbit(struct wmOperatorType *ot);
+void VIEW3D_OT_clipping(struct wmOperatorType *ot);
+void VIEW3D_OT_cursor3d(struct wmOperatorType *ot);
+void VIEW3D_OT_render_border(struct wmOperatorType *ot);
+void VIEW3D_OT_zoom_border(struct wmOperatorType *ot);
+void VIEW3D_OT_drawtype(struct wmOperatorType *ot);
+void VIEW3D_OT_editmesh_face_toolbox(struct wmOperatorType *ot);
+
+void view3d_boxview_copy(ScrArea *sa, ARegion *ar);
+
+/* drawobject.c */
+void draw_object(Scene *scene, struct ARegion *ar, View3D *v3d, Base *base, int flag);
+int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt);
+void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int dt, int outline);
+void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob);
+void drawaxes(float size, int flag, char drawtype);
+
+/* drawarmature.c */
+int draw_armature(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag);
+
+/* drawmesh.c */
+void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, struct DerivedMesh *dm, int faceselect);
+
+/* view3d_draw.c */
+void view3d_main_area_draw(const struct bContext *C, struct ARegion *ar);
+void draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, int (* func)(void *));
+void view3d_clr_clipping(void);
+void view3d_set_clipping(RegionView3D *rv3d);
+void add_view3d_after(View3D *v3d, Base *base, int type, int flag);
+void make_axis_color(char *col, char *col2, char axis);
+void calc_viewborder(Scene *scene, struct ARegion *ar, View3D *v3d, rctf *viewborder_r);
+
+void circf(float x, float y, float rad);
+void circ(float x, float y, float rad);
+void view3d_update_depths(struct ARegion *ar, View3D *v3d);
+
+/* view3d_select.c */
+void VIEW3D_OT_select(struct wmOperatorType *ot);
+void VIEW3D_OT_select_extend(struct wmOperatorType *ot);
+void VIEW3D_OT_select_circle(struct wmOperatorType *ot);
+void VIEW3D_OT_select_border(struct wmOperatorType *ot);
+void VIEW3D_OT_select_lasso(struct wmOperatorType *ot);
+
+/* view3d_view.c */
+void VIEW3D_OT_smoothview(struct wmOperatorType *ot);
+void VIEW3D_OT_setcameratoview(struct wmOperatorType *ot);
+void VIEW3D_OT_localview(struct wmOperatorType *ot);
+
+int boundbox_clip(RegionView3D *rv3d, float obmat[][4], struct BoundBox *bb);
+
+void view3d_project_short_clip(struct ARegion *ar, float *vec, short *adr, float projmat[4][4], float wmat[4][4]);
+void view3d_project_short_noclip(struct ARegion *ar, float *vec, short *adr, float mat[4][4]);
+
+void view3d_project_float(struct ARegion *a, float *vec, float *adr, float mat[4][4]);
+
+void centerview(struct ARegion *ar, View3D *v3d);
+
+void smooth_view(struct bContext *C, Object *, Object *, float *ofs, float *quat, float *dist, float *lens);
+
+void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect); /* rect: for picking */
+void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d);
+
+/* view3d_buttons.c */
+void VIEW3D_OT_properties(struct wmOperatorType *ot);
+
+void view3d_buttons_area_defbuts(const struct bContext *C, ARegion *ar);
+
+/* view3d_snap.c */
+int minmax_verts(Object *obedit, float *min, float *max);
+
+void VIEW3D_OT_snap_selected_to_grid(struct wmOperatorType *ot);
+void VIEW3D_OT_snap_selected_to_cursor(struct wmOperatorType *ot);
+void VIEW3D_OT_snap_selected_to_center(struct wmOperatorType *ot);
+void VIEW3D_OT_snap_cursor_to_grid(struct wmOperatorType *ot);
+void VIEW3D_OT_snap_cursor_to_selected(struct wmOperatorType *ot);
+void VIEW3D_OT_snap_cursor_to_active(struct wmOperatorType *ot);
+void VIEW3D_OT_snap_menu(struct wmOperatorType *ot);
+
+/* space_view3d.c */
+ARegion *view3d_has_buttons_region(ScrArea *sa);
+
+
+#endif /* ED_VIEW3D_INTERN_H */
+
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
new file mode 100644
index 00000000000..41ef16bea4a
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -0,0 +1,232 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_transform.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+
+#include "view3d_intern.h"
+
+
+/* ************************** registration **********************************/
+
+void view3d_operatortypes(void)
+{
+ WM_operatortype_append(VIEW3D_OT_viewrotate);
+ WM_operatortype_append(VIEW3D_OT_viewmove);
+ WM_operatortype_append(VIEW3D_OT_zoom);
+ WM_operatortype_append(VIEW3D_OT_viewhome);
+ WM_operatortype_append(VIEW3D_OT_viewnumpad);
+ WM_operatortype_append(VIEW3D_OT_view_orbit);
+ WM_operatortype_append(VIEW3D_OT_view_pan);
+ WM_operatortype_append(VIEW3D_OT_view_persportho);
+ WM_operatortype_append(VIEW3D_OT_viewcenter);
+ WM_operatortype_append(VIEW3D_OT_select);
+ WM_operatortype_append(VIEW3D_OT_select_border);
+ WM_operatortype_append(VIEW3D_OT_clipping);
+ WM_operatortype_append(VIEW3D_OT_select_circle);
+ WM_operatortype_append(VIEW3D_OT_smoothview);
+ WM_operatortype_append(VIEW3D_OT_render_border);
+ WM_operatortype_append(VIEW3D_OT_zoom_border);
+ WM_operatortype_append(VIEW3D_OT_cursor3d);
+ WM_operatortype_append(VIEW3D_OT_select_lasso);
+ WM_operatortype_append(VIEW3D_OT_setcameratoview);
+ WM_operatortype_append(VIEW3D_OT_drawtype);
+ WM_operatortype_append(VIEW3D_OT_editmesh_face_toolbox);
+ WM_operatortype_append(VIEW3D_OT_properties);
+ WM_operatortype_append(VIEW3D_OT_localview);
+ WM_operatortype_append(VIEW3D_OT_layers);
+
+ WM_operatortype_append(VIEW3D_OT_snap_selected_to_grid);
+ WM_operatortype_append(VIEW3D_OT_snap_selected_to_cursor);
+ WM_operatortype_append(VIEW3D_OT_snap_selected_to_center);
+ WM_operatortype_append(VIEW3D_OT_snap_cursor_to_grid);
+ WM_operatortype_append(VIEW3D_OT_snap_cursor_to_selected);
+ WM_operatortype_append(VIEW3D_OT_snap_cursor_to_active);
+ WM_operatortype_append(VIEW3D_OT_snap_menu);
+
+ transform_operatortypes();
+}
+
+void view3d_keymap(wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "View3D Generic", SPACE_VIEW3D, 0);
+ wmKeymapItem *km;
+
+ WM_keymap_add_item(keymap, "PAINT_OT_vertex_paint_toggle", VKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "PAINT_OT_weight_paint_toggle", TABKEY, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "VIEW3D_OT_properties", NKEY, KM_PRESS, 0, 0);
+
+ /* only for region 3D window */
+ keymap= WM_keymap_listbase(wm, "View3D", SPACE_VIEW3D, 0);
+
+ /* paint poll checks mode */
+ WM_keymap_verify_item(keymap, "PAINT_OT_vertex_paint", LEFTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "PAINT_OT_weight_paint", LEFTMOUSE, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "PAINT_OT_sample_color", RIGHTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "PAINT_OT_clone_cursor_set", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
+
+ /* sketch poll checks mode */
+ WM_keymap_add_item(keymap, "SKETCH_OT_gesture", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "SKETCH_OT_draw_stroke", ACTIONMOUSE, KM_PRESS, 0, 0);
+ km = WM_keymap_add_item(keymap, "SKETCH_OT_draw_stroke", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0);
+ RNA_boolean_set(km->ptr, "snap", 1);
+ WM_keymap_add_item(keymap, "SKETCH_OT_draw_preview", MOUSEMOVE, KM_ANY, 0, 0);
+ km = WM_keymap_add_item(keymap, "SKETCH_OT_draw_preview", MOUSEMOVE, KM_ANY, KM_CTRL, 0);
+ RNA_boolean_set(km->ptr, "snap", 1);
+
+ WM_keymap_verify_item(keymap, "VIEW3D_OT_cursor3d", ACTIONMOUSE, KM_PRESS, 0, 0);
+
+ WM_keymap_verify_item(keymap, "VIEW3D_OT_viewrotate", MIDDLEMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "VIEW3D_OT_viewmove", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_verify_item(keymap, "VIEW3D_OT_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_verify_item(keymap, "VIEW3D_OT_viewcenter", PADPERIOD, KM_PRESS, 0, 0);
+
+ WM_keymap_verify_item(keymap, "VIEW3D_OT_smoothview", TIMER1, KM_ANY, KM_ANY, 0);
+
+ RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", PADPLUSKEY, KM_PRESS, 0, 0)->ptr, "delta", 1);
+ RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", PADMINUS, KM_PRESS, 0, 0)->ptr, "delta", -1);
+ RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", WHEELINMOUSE, KM_PRESS, 0, 0)->ptr, "delta", 1);
+ RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", WHEELOUTMOUSE, KM_PRESS, 0, 0)->ptr, "delta", -1);
+
+ RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewhome", HOMEKEY, KM_PRESS, 0, 0)->ptr, "center", 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewhome", CKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "center", 1);
+
+ /* numpad view hotkeys*/
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD0, KM_PRESS, 0, 0)->ptr, "type", V3D_VIEW_CAMERA);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD1, KM_PRESS, 0, 0)->ptr, "type", V3D_VIEW_FRONT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", PAD2, KM_PRESS, 0, 0)->ptr, "type", V3D_VIEW_STEPDOWN);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD3, KM_PRESS, 0, 0)->ptr, "type", V3D_VIEW_RIGHT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", PAD4, KM_PRESS, 0, 0)->ptr, "type", V3D_VIEW_STEPLEFT);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_view_persportho", PAD5, KM_PRESS, 0, 0);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", PAD6, KM_PRESS, 0, 0)->ptr, "type", V3D_VIEW_STEPRIGHT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD7, KM_PRESS, 0, 0)->ptr, "type", V3D_VIEW_TOP);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", PAD8, KM_PRESS, 0, 0)->ptr, "type", V3D_VIEW_STEPUP);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD1, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_BACK);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD3, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_LEFT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD7, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_BOTTOM);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD2, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANDOWN);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD4, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANLEFT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD6, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANRIGHT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD8, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANUP);
+
+ WM_keymap_add_item(keymap, "VIEW3D_OT_localview", PADSLASHKEY, KM_PRESS, 0, 0);
+
+ /* layers, shift + alt are properties set in invoke() */
+ RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ONEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 1);
+ RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", TWOKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 2);
+ RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", THREEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 3);
+ RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", FOURKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 4);
+ RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", FIVEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 5);
+ RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", SIXKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 6);
+ RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", SEVENKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 7);
+ RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", EIGHTKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 8);
+ RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", NINEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 9);
+ RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ZEROKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 10);
+
+ /* drawtype */
+ km = WM_keymap_add_item(keymap, "VIEW3D_OT_drawtype", ZKEY, KM_PRESS, 0, 0);
+ RNA_int_set(km->ptr, "draw_type", OB_SOLID);
+ RNA_int_set(km->ptr, "draw_type_alternate", OB_WIRE);
+
+ km = WM_keymap_add_item(keymap, "VIEW3D_OT_drawtype", ZKEY, KM_PRESS, KM_ALT, 0);
+ RNA_int_set(km->ptr, "draw_type", OB_TEXTURE);
+ RNA_int_set(km->ptr, "draw_type_alternate", OB_SOLID);
+
+ km = WM_keymap_add_item(keymap, "VIEW3D_OT_drawtype", ZKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_int_set(km->ptr, "draw_type", OB_SHADED);
+ RNA_int_set(km->ptr, "draw_type_alternate", OB_WIRE);
+
+ /* selection*/
+ WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "type", 1);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_select_border", BKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_SHIFT|KM_CTRL, 0)->ptr, "type", 1);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_select_circle", CKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "VIEW3D_OT_clipping", BKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_zoom_border", BKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_render_border", BKEY, KM_PRESS, KM_SHIFT, 0);
+
+ WM_keymap_add_item(keymap, "VIEW3D_OT_camera_to_view", PAD0, KM_PRESS, KM_ALT|KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "VIEW3D_OT_snap_menu", SKEY, KM_PRESS, KM_SHIFT, 0);
+
+ /* radial control */
+ RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH);
+ RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", WM_RADIALCONTROL_ANGLE);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_vertex_paint_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_weight_paint_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_texture_paint_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_vertex_paint_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH);
+ RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_weight_paint_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH);
+ RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_texture_paint_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH);
+
+ /* TODO - this is just while we have no way to load a text datablock */
+ RNA_string_set(WM_keymap_add_item(keymap, "SCRIPT_OT_python_file_run", PKEY, KM_PRESS, 0, 0)->ptr, "filename", "test.py");
+
+ transform_keymap_for_space(wm, keymap, SPACE_VIEW3D);
+
+}
+
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
new file mode 100644
index 00000000000..d03586da2d5
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -0,0 +1,1843 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <float.h>
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+
+#include "BKE_action.h"
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_object.h"
+#include "BKE_global.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "RE_pipeline.h" // make_stars
+
+#include "BIF_gl.h"
+#include "BIF_retopo.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_armature.h"
+#include "ED_curve.h"
+#include "ED_particle.h"
+#include "ED_mesh.h"
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "PIL_time.h" /* smoothview */
+
+#include "view3d_intern.h" // own include
+
+
+void view3d_set_viewcontext(bContext *C, ViewContext *vc)
+{
+ memset(vc, 0, sizeof(ViewContext));
+ vc->ar= CTX_wm_region(C);
+ vc->scene= CTX_data_scene(C);
+ vc->v3d= CTX_wm_view3d(C);
+ vc->rv3d= vc->ar->regiondata;
+ vc->obact= CTX_data_active_object(C);
+ vc->obedit= CTX_data_edit_object(C);
+}
+
+void view3d_get_view_aligned_coordinate(ViewContext *vc, float *fp, short mval[2])
+{
+ float dvec[3];
+ short mx, my;
+
+ mx= mval[0];
+ my= mval[1];
+
+ project_short_noclip(vc->ar, fp, mval);
+
+ initgrabz(vc->rv3d, fp[0], fp[1], fp[2]);
+
+ if(mval[0]!=IS_CLIPPED) {
+ window_to_3d_delta(vc->ar, dvec, mval[0]-mx, mval[1]-my);
+ VecSubf(fp, fp, dvec);
+ }
+}
+
+void view3d_get_transformation(ViewContext *vc, Object *ob, bglMats *mats)
+{
+ float cpy[4][4];
+ int i, j;
+
+ Mat4MulMat4(cpy, vc->rv3d->viewmat, ob->obmat);
+
+ for(i = 0; i < 4; ++i) {
+ for(j = 0; j < 4; ++j) {
+ mats->projection[i*4+j] = vc->rv3d->winmat[i][j];
+ mats->modelview[i*4+j] = cpy[i][j];
+ }
+ }
+
+ mats->viewport[0] = vc->ar->winrct.xmin;
+ mats->viewport[1] = vc->ar->winrct.ymin;
+ mats->viewport[2] = vc->ar->winx;
+ mats->viewport[3] = vc->ar->winy;
+}
+
+/* ********************** view3d_select: selection manipulations ********************* */
+
+/* XXX to solve *************** */
+static void BIF_undo_push() {}
+/* XXX end ********************* */
+
+/* local prototypes */
+
+void EM_backbuf_checkAndSelectVerts(EditMesh *em, int select)
+{
+ EditVert *eve;
+ int index= em_wireoffs;
+
+ for(eve= em->verts.first; eve; eve= eve->next, index++) {
+ if(eve->h==0) {
+ if(EM_check_backbuf(index)) {
+ eve->f = select?(eve->f|1):(eve->f&~1);
+ }
+ }
+ }
+}
+
+void EM_backbuf_checkAndSelectEdges(EditMesh *em, int select)
+{
+ EditEdge *eed;
+ int index= em_solidoffs;
+
+ for(eed= em->edges.first; eed; eed= eed->next, index++) {
+ if(eed->h==0) {
+ if(EM_check_backbuf(index)) {
+ EM_select_edge(eed, select);
+ }
+ }
+ }
+}
+
+void EM_backbuf_checkAndSelectFaces(EditMesh *em, int select)
+{
+ EditFace *efa;
+ int index= 1;
+
+ for(efa= em->faces.first; efa; efa= efa->next, index++) {
+ if(efa->h==0) {
+ if(EM_check_backbuf(index)) {
+ EM_select_face_fgon(em, efa, select);
+ }
+ }
+ }
+}
+
+void EM_backbuf_checkAndSelectTFaces(Mesh *me, int select)
+{
+ MFace *mface = me->mface;
+ int a;
+
+ if (mface) {
+ for(a=1; a<=me->totface; a++, mface++) {
+ if(EM_check_backbuf(a)) {
+ mface->flag = select?(mface->flag|ME_FACE_SEL):(mface->flag&~ME_FACE_SEL);
+ }
+ }
+ }
+}
+
+void arrows_move_cursor(unsigned short event)
+{
+#if 0
+ 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]);
+ }
+#endif
+}
+
+
+/* *********************** GESTURE AND LASSO ******************* */
+
+/* helper also for borderselect */
+static int edge_fully_inside_rect(rcti *rect, short x1, short y1, short x2, short y2)
+{
+ return BLI_in_rcti(rect, x1, y1) && BLI_in_rcti(rect, x2, y2);
+}
+
+static int edge_inside_rect(rcti *rect, short x1, short y1, short x2, short y2)
+{
+ int d1, d2, d3, d4;
+
+ /* check points in rect */
+ if(edge_fully_inside_rect(rect, x1, y1, x2, y2)) return 1;
+
+ /* check points completely out rect */
+ if(x1<rect->xmin && x2<rect->xmin) return 0;
+ if(x1>rect->xmax && x2>rect->xmax) return 0;
+ if(y1<rect->ymin && y2<rect->ymin) return 0;
+ if(y1>rect->ymax && y2>rect->ymax) return 0;
+
+ /* simple check lines intersecting. */
+ d1= (y1-y2)*(x1- rect->xmin ) + (x2-x1)*(y1- rect->ymin );
+ d2= (y1-y2)*(x1- rect->xmin ) + (x2-x1)*(y1- rect->ymax );
+ d3= (y1-y2)*(x1- rect->xmax ) + (x2-x1)*(y1- rect->ymax );
+ d4= (y1-y2)*(x1- rect->xmax ) + (x2-x1)*(y1- rect->ymin );
+
+ if(d1<0 && d2<0 && d3<0 && d4<0) return 0;
+ if(d1>0 && d2>0 && d3>0 && d4>0) return 0;
+
+ return 1;
+}
+
+
+#define MOVES_GESTURE 50
+#define MOVES_LASSO 500
+
+int lasso_inside(short mcords[][2], short moves, short sx, short sy)
+{
+ /* we do the angle rule, define that all added angles should be about zero or 2*PI */
+ float angletot=0.0, len, dot, ang, cross, fp1[2], fp2[2];
+ int a;
+ short *p1, *p2;
+
+ if(sx==IS_CLIPPED)
+ return 0;
+
+ p1= mcords[moves-1];
+ p2= mcords[0];
+
+ /* first vector */
+ fp1[0]= (float)(p1[0]-sx);
+ fp1[1]= (float)(p1[1]-sy);
+ len= sqrt(fp1[0]*fp1[0] + fp1[1]*fp1[1]);
+ fp1[0]/= len;
+ fp1[1]/= len;
+
+ for(a=0; a<moves; a++) {
+ /* second vector */
+ fp2[0]= (float)(p2[0]-sx);
+ fp2[1]= (float)(p2[1]-sy);
+ len= sqrt(fp2[0]*fp2[0] + fp2[1]*fp2[1]);
+ fp2[0]/= len;
+ fp2[1]/= len;
+
+ /* dot and angle and cross */
+ dot= fp1[0]*fp2[0] + fp1[1]*fp2[1];
+ ang= fabs(saacos(dot));
+
+ cross= (float)((p1[1]-p2[1])*(p1[0]-sx) + (p2[0]-p1[0])*(p1[1]-sy));
+
+ if(cross<0.0) angletot-= ang;
+ else angletot+= ang;
+
+ /* circulate */
+ fp1[0]= fp2[0]; fp1[1]= fp2[1];
+ p1= p2;
+ p2= mcords[a+1];
+ }
+
+ if( fabs(angletot) > 4.0 ) return 1;
+ return 0;
+}
+
+/* edge version for lasso select. we assume boundbox check was done */
+int lasso_inside_edge(short mcords[][2], short moves, int x0, int y0, int x1, int y1)
+{
+ short v1[2], v2[2];
+ int a;
+
+ if(x0==IS_CLIPPED || x1==IS_CLIPPED)
+ return 0;
+
+ v1[0] = x0, v1[1] = y0;
+ v2[0] = x1, v2[1] = y1;
+
+ /* check points in lasso */
+ if(lasso_inside(mcords, moves, v1[0], v1[1])) return 1;
+ if(lasso_inside(mcords, moves, v2[0], v2[1])) return 1;
+
+ /* no points in lasso, so we have to intersect with lasso edge */
+
+ if( IsectLL2Ds(mcords[0], mcords[moves-1], v1, v2) > 0) return 1;
+ for(a=0; a<moves-1; a++) {
+ if( IsectLL2Ds(mcords[a], mcords[a+1], v1, v2) > 0) return 1;
+ }
+
+ return 0;
+}
+
+
+/* warning; lasso select with backbuffer-check draws in backbuf with persp(PERSP_WIN)
+ and returns with persp(PERSP_VIEW). After lasso select backbuf is not OK
+*/
+static void do_lasso_select_pose(ViewContext *vc, short mcords[][2], short moves, short select)
+{
+ Object *ob= vc->obact;
+ bPoseChannel *pchan;
+ float vec[3];
+ short sco1[2], sco2[2];
+
+ if(ob->type!=OB_ARMATURE || ob->pose==NULL) return;
+
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ VECCOPY(vec, pchan->pose_head);
+ Mat4MulVecfl(ob->obmat, vec);
+ project_short(vc->ar, vec, sco1);
+ VECCOPY(vec, pchan->pose_tail);
+ Mat4MulVecfl(ob->obmat, vec);
+ project_short(vc->ar, vec, sco2);
+
+ if(lasso_inside_edge(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1])) {
+ if(select) pchan->bone->flag |= BONE_SELECTED;
+ else pchan->bone->flag &= ~(BONE_ACTIVE|BONE_SELECTED);
+ }
+ }
+}
+
+
+static void do_lasso_select_objects(ViewContext *vc, short mcords[][2], short moves, short select)
+{
+ Base *base;
+
+ for(base= vc->scene->base.first; base; base= base->next) {
+ if(base->lay & vc->v3d->lay) {
+ project_short(vc->ar, base->object->obmat[3], &base->sx);
+ if(lasso_inside(mcords, moves, base->sx, base->sy)) {
+
+ if(select) ED_base_object_select(base, BA_SELECT);
+ else ED_base_object_select(base, BA_DESELECT);
+ base->object->flag= base->flag;
+ }
+ if(base->object->flag & OB_POSEMODE) {
+ do_lasso_select_pose(vc, mcords, moves, select);
+ }
+ }
+ }
+}
+
+void lasso_select_boundbox(rcti *rect, short mcords[][2], short moves)
+{
+ short a;
+
+ rect->xmin= rect->xmax= mcords[0][0];
+ rect->ymin= rect->ymax= mcords[0][1];
+
+ for(a=1; a<moves; a++) {
+ if(mcords[a][0]<rect->xmin) rect->xmin= mcords[a][0];
+ else if(mcords[a][0]>rect->xmax) rect->xmax= mcords[a][0];
+ if(mcords[a][1]<rect->ymin) rect->ymin= mcords[a][1];
+ else if(mcords[a][1]>rect->ymax) rect->ymax= mcords[a][1];
+ }
+}
+
+static void do_lasso_select_mesh__doSelectVert(void *userData, EditVert *eve, int x, int y, int index)
+{
+ struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } *data = userData;
+
+ if (BLI_in_rcti(data->rect, x, y) && lasso_inside(data->mcords, data->moves, x, y)) {
+ eve->f = data->select?(eve->f|1):(eve->f&~1);
+ }
+}
+static void do_lasso_select_mesh__doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
+{
+ struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } *data = userData;
+
+ if (EM_check_backbuf(em_solidoffs+index)) {
+ if (data->pass==0) {
+ if ( edge_fully_inside_rect(data->rect, x0, y0, x1, y1) &&
+ lasso_inside(data->mcords, data->moves, x0, y0) &&
+ lasso_inside(data->mcords, data->moves, x1, y1)) {
+ EM_select_edge(eed, data->select);
+ data->done = 1;
+ }
+ } else {
+ if (lasso_inside_edge(data->mcords, data->moves, x0, y0, x1, y1)) {
+ EM_select_edge(eed, data->select);
+ }
+ }
+ }
+}
+static void do_lasso_select_mesh__doSelectFace(void *userData, EditFace *efa, int x, int y, int index)
+{
+ struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } *data = userData;
+
+ if (BLI_in_rcti(data->rect, x, y) && lasso_inside(data->mcords, data->moves, x, y)) {
+ EM_select_face_fgon(data->vc.em, efa, data->select);
+ }
+}
+
+static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves, short select)
+{
+ struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } data;
+ rcti rect;
+ int bbsel;
+
+ lasso_select_boundbox(&rect, mcords, moves);
+
+ /* set editmesh */
+ vc->em= ((Mesh *)vc->obedit->data)->edit_mesh;
+
+ data.vc= *vc;
+ data.rect = &rect;
+ data.mcords = mcords;
+ data.moves = moves;
+ data.select = select;
+ data.done = 0;
+ data.pass = 0;
+
+ bbsel= EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+
+ if(vc->scene->selectmode & SCE_SELECT_VERTEX) {
+ if (bbsel) {
+ EM_backbuf_checkAndSelectVerts(vc->em, select);
+ } else {
+ mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, 1);
+ }
+ }
+ if(vc->scene->selectmode & SCE_SELECT_EDGE) {
+ /* Does both bbsel and non-bbsel versions (need screen cos for both) */
+
+ data.pass = 0;
+ mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, 0);
+
+ if (data.done==0) {
+ data.pass = 1;
+ mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, 0);
+ }
+ }
+
+ if(vc->scene->selectmode & SCE_SELECT_FACE) {
+ if (bbsel) {
+ EM_backbuf_checkAndSelectFaces(vc->em, select);
+ } else {
+ mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data);
+ }
+ }
+
+ EM_free_backbuf();
+ EM_selectmode_flush(vc->em);
+}
+
+#if 0
+/* this is an exception in that its the only lasso that dosnt use the 3d view (uses space image view) */
+static void do_lasso_select_mesh_uv(short mcords[][2], short moves, short select)
+{
+ EditFace *efa;
+ MTFace *tf;
+ int screenUV[2], nverts, i, ok = 1;
+ rcti rect;
+
+ lasso_select_boundbox(&rect, mcords, moves);
+
+ if (draw_uvs_face_check()) { /* Face Center Sel */
+ float cent[2];
+ ok = 0;
+ for (efa= em->faces.first; efa; efa= efa->next) {
+ /* assume not touched */
+ efa->tmp.l = 0;
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if ((select) != (simaFaceSel_Check(efa, tf))) {
+ uv_center(tf->uv, cent, (void *)efa->v4);
+ uvco_to_areaco_noclip(cent, screenUV);
+ if (BLI_in_rcti(&rect, screenUV[0], screenUV[1]) && lasso_inside(mcords, moves, screenUV[0], screenUV[1])) {
+ efa->tmp.l = ok = 1;
+ }
+ }
+ }
+ /* (de)selects all tagged faces and deals with sticky modes */
+ if (ok)
+ uvface_setsel__internal(select);
+
+ } else { /* Vert Sel*/
+ for (efa= em->faces.first; efa; efa= efa->next) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if (simaFaceDraw_Check(efa, tf)) {
+ nverts= efa->v4? 4: 3;
+ for(i=0; i<nverts; i++) {
+ if ((select) != (simaUVSel_Check(efa, tf, i))) {
+ uvco_to_areaco_noclip(tf->uv[i], screenUV);
+ if (BLI_in_rcti(&rect, screenUV[0], screenUV[1]) && lasso_inside(mcords, moves, screenUV[0], screenUV[1])) {
+ if (select) {
+ simaUVSel_Set(efa, tf, i);
+ } else {
+ simaUVSel_UnSet(efa, tf, i);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (ok && G.sima->flag & SI_SYNC_UVSEL) {
+ if (select) EM_select_flush(vc->em);
+ else EM_deselect_flush(vc->em);
+ }
+}
+#endif
+
+static void do_lasso_select_curve__doSelect(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y)
+{
+ struct { short (*mcords)[2]; short moves; short select; } *data = userData;
+
+ if (lasso_inside(data->mcords, data->moves, x, y)) {
+ if (bp) {
+ bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT);
+ } else {
+ if (G.f & G_HIDDENHANDLES) {
+ /* can only be beztindex==0 here since handles are hidden */
+ bezt->f1 = bezt->f2 = bezt->f3 = data->select?(bezt->f2|SELECT):(bezt->f2&~SELECT);
+ } else {
+ if (beztindex==0) {
+ bezt->f1 = data->select?(bezt->f1|SELECT):(bezt->f1&~SELECT);
+ } else if (beztindex==1) {
+ bezt->f2 = data->select?(bezt->f2|SELECT):(bezt->f2&~SELECT);
+ } else {
+ bezt->f3 = data->select?(bezt->f3|SELECT):(bezt->f3&~SELECT);
+ }
+ }
+ }
+ }
+}
+
+static void do_lasso_select_curve(ViewContext *vc, short mcords[][2], short moves, short select)
+{
+ struct { short (*mcords)[2]; short moves; short select; } data;
+
+ /* set vc->editnurb */
+ data.mcords = mcords;
+ data.moves = moves;
+ data.select = select;
+
+ nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data);
+}
+
+static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, int x, int y)
+{
+ struct { short (*mcords)[2]; short moves; short select; } *data = userData;
+
+ if (lasso_inside(data->mcords, data->moves, x, y)) {
+ bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT);
+ }
+}
+static void do_lasso_select_lattice(ViewContext *vc, short mcords[][2], short moves, short select)
+{
+ struct { short (*mcords)[2]; short moves; short select; } data;
+
+ /* set editdata in vc */
+ data.mcords = mcords;
+ data.moves = moves;
+ data.select = select;
+
+ lattice_foreachScreenVert(vc, do_lasso_select_lattice__doSelect, &data);
+}
+
+static void do_lasso_select_armature(ViewContext *vc, short mcords[][2], short moves, short select)
+{
+ bArmature *arm= vc->obedit->data;
+ EditBone *ebone;
+ float vec[3];
+ short sco1[2], sco2[2], didpoint;
+
+ /* set editdata in vc */
+
+ for (ebone= arm->edbo->first; ebone; ebone=ebone->next) {
+
+ VECCOPY(vec, ebone->head);
+ Mat4MulVecfl(vc->obedit->obmat, vec);
+ project_short(vc->ar, vec, sco1);
+ VECCOPY(vec, ebone->tail);
+ Mat4MulVecfl(vc->obedit->obmat, vec);
+ project_short(vc->ar, vec, sco2);
+
+ didpoint= 0;
+ if(lasso_inside(mcords, moves, sco1[0], sco1[1])) {
+ if(select) ebone->flag |= BONE_ROOTSEL;
+ else ebone->flag &= ~BONE_ROOTSEL;
+ didpoint= 1;
+ }
+ if(lasso_inside(mcords, moves, sco2[0], sco2[1])) {
+ if(select) ebone->flag |= BONE_TIPSEL;
+ else ebone->flag &= ~BONE_TIPSEL;
+ didpoint= 1;
+ }
+ /* if one of points selected, we skip the bone itself */
+ if(didpoint==0 && lasso_inside_edge(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1])) {
+ if(select) ebone->flag |= BONE_TIPSEL|BONE_ROOTSEL|BONE_SELECTED;
+ else ebone->flag &= ~(BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+ }
+ }
+}
+
+static void do_lasso_select_facemode(ViewContext *vc, short mcords[][2], short moves, short select)
+{
+ Object *ob= vc->obact;
+ Mesh *me= ob?ob->data:NULL;
+ rcti rect;
+
+ if(me==NULL || me->mtface==NULL) return;
+ if(me->totface==0) return;
+
+ em_vertoffs= me->totface+1; /* max index array */
+
+ lasso_select_boundbox(&rect, mcords, moves);
+ EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+
+ EM_backbuf_checkAndSelectTFaces(me, select);
+
+ EM_free_backbuf();
+
+// XXX object_tface_flags_changed(ob, 0);
+}
+
+#if 0
+static void do_lasso_select_node(short mcords[][2], short moves, short select)
+{
+ SpaceNode *snode = sa->spacedata.first;
+
+ bNode *node;
+ rcti rect;
+ short node_cent[2];
+ float node_centf[2];
+
+ lasso_select_boundbox(&rect, mcords, moves);
+
+ /* store selection in temp test flag */
+ for(node= snode->edittree->nodes.first; node; node= node->next) {
+
+ node_centf[0] = (node->totr.xmin+node->totr.xmax)/2;
+ node_centf[1] = (node->totr.ymin+node->totr.ymax)/2;
+
+ ipoco_to_areaco_noclip(G.v2d, node_centf, node_cent);
+ if (BLI_in_rcti(&rect, node_cent[0], node_cent[1]) && lasso_inside(mcords, moves, node_cent[0], node_cent[1])) {
+ if (select) {
+ node->flag |= SELECT;
+ } else {
+ node->flag &= ~SELECT;
+ }
+ }
+ }
+ BIF_undo_push("Lasso select nodes");
+}
+#endif
+
+void view3d_lasso_select(bContext *C, ViewContext *vc, short mcords[][2], short moves, short select)
+{
+ if(vc->obedit==NULL) {
+ if(FACESEL_PAINT_TEST)
+ do_lasso_select_facemode(vc, mcords, moves, select);
+ else if(G.f & (G_VERTEXPAINT|G_TEXTUREPAINT|G_WEIGHTPAINT))
+ ;
+ else if(G.f & G_PARTICLEEDIT)
+ PE_lasso_select(C, mcords, moves, select);
+ else
+ do_lasso_select_objects(vc, mcords, moves, select);
+ }
+ else if(vc->obedit->type==OB_MESH) {
+ do_lasso_select_mesh(vc, mcords, moves, select);
+ } else if(vc->obedit->type==OB_CURVE || vc->obedit->type==OB_SURF)
+ do_lasso_select_curve(vc, mcords, moves, select);
+ else if(vc->obedit->type==OB_LATTICE)
+ do_lasso_select_lattice(vc, mcords, moves, select);
+ else if(vc->obedit->type==OB_ARMATURE)
+ do_lasso_select_armature(vc, mcords, moves, select);
+
+ BIF_undo_push("Lasso select");
+
+}
+
+static EnumPropertyItem lasso_select_types[] = {
+ {0, "SELECT", "Select", ""},
+ {1, "DESELECT", "Deselect", ""},
+ {0, NULL, NULL, NULL}
+};
+
+
+/* lasso operator gives properties, but since old code works
+ with short array we convert */
+static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
+{
+ ViewContext vc;
+ int select, i= 0;
+ short mcords[1024][2];
+
+ RNA_BEGIN(op->ptr, itemptr, "path") {
+ float loc[2];
+
+ RNA_float_get_array(&itemptr, "loc", loc);
+ mcords[i][0]= (short)loc[0];
+ mcords[i][1]= (short)loc[1];
+ i++;
+ if(i>=1024) break;
+ }
+ RNA_END;
+
+ if(i>1) {
+ view3d_operator_needs_opengl(C);
+
+ /* setup view context for argument to callbacks */
+ view3d_set_viewcontext(C, &vc);
+
+ select= RNA_enum_is_equal(op->ptr, "type", "SELECT");
+ view3d_lasso_select(C, &vc, mcords, i, select);
+
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_PASS_THROUGH;
+}
+
+void VIEW3D_OT_select_lasso(wmOperatorType *ot)
+{
+ ot->name= "Lasso Select";
+ ot->idname= "VIEW3D_OT_select_lasso";
+
+ ot->invoke= WM_gesture_lasso_invoke;
+ ot->modal= WM_gesture_lasso_modal;
+ ot->exec= view3d_lasso_select_exec;
+ ot->poll= WM_operator_winactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
+ RNA_def_enum(ot->srna, "type", lasso_select_types, 0, "Type", "");
+}
+
+
+/* ************************************************* */
+
+#if 0
+/* smart function to sample a rect spiralling outside, nice for backbuf selection */
+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; /* if only color dontdo is available, still return dontdo */
+
+ buf+= (dirvec[rc][0]+dirvec[rc][1]);
+
+ if(buf<bufmin || buf>=bufmax) return retval;
+ }
+ rc++;
+ rc &= 3;
+ }
+ }
+ return retval;
+}
+#endif
+
+/* ************************** mouse select ************************* */
+
+
+/* The max number of menu items in an object select menu */
+#define SEL_MENU_SIZE 22
+
+static void deselectall_except(Scene *scene, Base *b) /* deselect all except b */
+{
+ Base *base;
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if (base->flag & SELECT) {
+ if(b!=base) {
+ ED_base_object_select(base, BA_DESELECT);
+ }
+ }
+ }
+}
+
+static Base *mouse_select_menu(ViewContext *vc, unsigned int *buffer, int hits, short *mval)
+{
+ Scene *scene= vc->scene;
+ View3D *v3d= vc->v3d;
+ Base *baseList[SEL_MENU_SIZE]={NULL}; /*baseList is used to store all possible bases to bring up a menu */
+ Base *base;
+ short baseCount = 0;
+ char menuText[20 + SEL_MENU_SIZE*32] = "Select Object%t"; /* max ob name = 22 */
+ char str[32];
+
+ for(base=FIRSTBASE; base; base= base->next) {
+ if (BASE_SELECTABLE(v3d, base)) {
+ baseList[baseCount] = NULL;
+
+ /* two selection methods, the CTRL select uses max dist of 15 */
+ if(buffer) {
+ int a;
+ for(a=0; a<hits; a++) {
+ /* index was converted */
+ if(base->selcol==buffer[ (4 * a) + 3 ]) baseList[baseCount] = base;
+ }
+ }
+ else {
+ int temp, dist=15;
+
+ project_short(vc->ar, base->object->obmat[3], &base->sx);
+
+ temp= abs(base->sx -mval[0]) + abs(base->sy -mval[1]);
+ if(temp<dist ) baseList[baseCount] = base;
+ }
+
+ if(baseList[baseCount]) {
+ if (baseCount < SEL_MENU_SIZE) {
+ baseList[baseCount] = base;
+ sprintf(str, "|%s %%x%d", base->object->id.name+2, baseCount+1); /* max ob name == 22 */
+ strcat(menuText, str);
+ baseCount++;
+ }
+ }
+ }
+ }
+
+ if(baseCount<=1) return baseList[0];
+ else {
+ baseCount = -1; // XXX = pupmenu(menuText);
+
+ if (baseCount != -1) { /* If nothing is selected then dont do anything */
+ return baseList[baseCount-1];
+ }
+ else return NULL;
+ }
+}
+
+/* we want a select buffer with bones, if there are... */
+/* so check three selection levels and compare */
+static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buffer, short *mval)
+{
+ rcti rect;
+ int offs;
+ short a, hits15, hits9=0, hits5=0;
+ short has_bones15=0, has_bones9=0, has_bones5=0;
+
+ BLI_init_rcti(&rect, mval[0]-14, mval[0]+14, mval[1]-14, mval[1]+14);
+ hits15= view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
+ if(hits15>0) {
+ for(a=0; a<hits15; a++) if(buffer[4*a+3] & 0xFFFF0000) has_bones15= 1;
+
+ offs= 4*hits15;
+ BLI_init_rcti(&rect, mval[0]-9, mval[0]+9, mval[1]-9, mval[1]+9);
+ hits9= view3d_opengl_select(vc, buffer+offs, MAXPICKBUF-offs, &rect);
+ if(hits9>0) {
+ for(a=0; a<hits9; a++) if(buffer[offs+4*a+3] & 0xFFFF0000) has_bones9= 1;
+
+ offs+= 4*hits9;
+ BLI_init_rcti(&rect, mval[0]-5, mval[0]+5, mval[1]-5, mval[1]+5);
+ hits5= view3d_opengl_select(vc, buffer+offs, MAXPICKBUF-offs, &rect);
+ if(hits5>0) {
+ for(a=0; a<hits5; a++) if(buffer[offs+4*a+3] & 0xFFFF0000) has_bones5= 1;
+ }
+ }
+
+ if(has_bones5) {
+ offs= 4*hits15 + 4*hits9;
+ memcpy(buffer, buffer+offs, 4*offs);
+ return hits5;
+ }
+ if(has_bones9) {
+ offs= 4*hits15;
+ memcpy(buffer, buffer+offs, 4*offs);
+ return hits9;
+ }
+ if(has_bones15) {
+ return hits15;
+ }
+
+ if(hits5>0) {
+ offs= 4*hits15 + 4*hits9;
+ memcpy(buffer, buffer+offs, 4*offs);
+ return hits5;
+ }
+ if(hits9>0) {
+ offs= 4*hits15;
+ memcpy(buffer, buffer+offs, 4*offs);
+ return hits9;
+ }
+ return hits15;
+ }
+
+ return 0;
+}
+
+
+/* mval is region coords */
+static void mouse_select(bContext *C, short *mval, short extend, short obcenter)
+{
+ ViewContext vc;
+ ARegion *ar= CTX_wm_region(C);
+ View3D *v3d= CTX_wm_view3d(C);
+ Scene *scene= CTX_data_scene(C);
+ Base *base, *startbase=NULL, *basact=NULL, *oldbasact=NULL;
+ unsigned int buffer[4*MAXPICKBUF];
+ int temp, a, dist=100;
+ short hits;
+
+ /* setup view context for argument to callbacks */
+ view3d_set_viewcontext(C, &vc);
+
+ /* always start list from basact in wire mode */
+ startbase= FIRSTBASE;
+ if(BASACT && BASACT->next) startbase= BASACT->next;
+
+ /* This block uses the control key to make the object selected by its center point rather then its contents */
+ /* XXX later on, in editmode do not activate */
+ if(vc.obedit==NULL && obcenter) {
+
+ /* note; shift+alt goes to group-flush-selecting */
+ /* XXX solve */
+ if(0)
+ basact= mouse_select_menu(&vc, NULL, 0, mval);
+ else {
+ base= startbase;
+ while(base) {
+ if (BASE_SELECTABLE(v3d, base)) {
+ project_short(ar, 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 ) {
+
+ dist= temp;
+ basact= base;
+ }
+ }
+ base= base->next;
+
+ if(base==0) base= FIRSTBASE;
+ if(base==startbase) break;
+ }
+ }
+ }
+ else {
+ /* if objects have posemode set, the bones are in the same selection buffer */
+
+ hits= mixed_bones_object_selectbuffer(&vc, buffer, mval);
+
+ if(hits>0) {
+ int has_bones= 0;
+
+ for(a=0; a<hits; a++) if(buffer[4*a+3] & 0xFFFF0000) has_bones= 1;
+
+ /* note; shift+alt goes to group-flush-selecting */
+ if(has_bones==0 && 0)
+ basact= mouse_select_menu(&vc, buffer, hits, mval);
+ else {
+ static short lastmval[2]={-100, -100};
+ int donearest= 0;
+
+ /* define if we use solid nearest select or not */
+ if(v3d->drawtype>OB_WIRE) {
+ donearest= 1;
+ if( ABS(mval[0]-lastmval[0])<3 && ABS(mval[1]-lastmval[1])<3) {
+ if(!has_bones) /* hrms, if theres bones we always do nearest */
+ donearest= 0;
+ }
+ }
+ lastmval[0]= mval[0]; lastmval[1]= mval[1];
+
+ if(donearest) {
+ unsigned int min= 0xFFFFFFFF;
+ int selcol= 0, notcol=0;
+
+
+ if(has_bones) {
+ /* we skip non-bone hits */
+ for(a=0; a<hits; a++) {
+ if( min > buffer[4*a+1] && (buffer[4*a+3] & 0xFFFF0000) ) {
+ min= buffer[4*a+1];
+ selcol= buffer[4*a+3] & 0xFFFF;
+ }
+ }
+ }
+ else {
+ /* only exclude active object when it is selected... */
+ if(BASACT && (BASACT->flag & SELECT) && hits>1) notcol= BASACT->selcol;
+
+ for(a=0; a<hits; a++) {
+ if( min > buffer[4*a+1] && notcol!=(buffer[4*a+3] & 0xFFFF)) {
+ min= buffer[4*a+1];
+ selcol= buffer[4*a+3] & 0xFFFF;
+ }
+ }
+ }
+
+ base= FIRSTBASE;
+ while(base) {
+ if(base->lay & v3d->lay) {
+ if(base->selcol==selcol) break;
+ }
+ base= base->next;
+ }
+ if(base) basact= base;
+ }
+ else {
+
+ base= startbase;
+ while(base) {
+ /* skip objects with select restriction, to prevent prematurely ending this loop
+ * with an un-selectable choice */
+ if (base->object->restrictflag & OB_RESTRICT_SELECT) {
+ base=base->next;
+ if(base==NULL) base= FIRSTBASE;
+ if(base==startbase) break;
+ }
+
+ if(base->lay & v3d->lay) {
+ for(a=0; a<hits; a++) {
+ if(has_bones) {
+ /* skip non-bone objects */
+ if((buffer[4*a+3] & 0xFFFF0000)) {
+ if(base->selcol== (buffer[(4*a)+3] & 0xFFFF))
+ basact= base;
+ }
+ }
+ else {
+ if(base->selcol== (buffer[(4*a)+3] & 0xFFFF))
+ basact= base;
+ }
+ }
+ }
+
+ if(basact) break;
+
+ base= base->next;
+ if(base==NULL) base= FIRSTBASE;
+ if(base==startbase) break;
+ }
+ }
+ }
+
+ if(has_bones && basact) {
+ if(ED_do_pose_selectbuffer(scene, basact, buffer, hits, extend) ) { /* then bone is found */
+
+ /* we make the armature selected:
+ not-selected active object in posemode won't work well for tools */
+ basact->flag|= SELECT;
+ basact->object->flag= basact->flag;
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, basact->object);
+ WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, basact->object);
+
+ /* in weightpaint, we use selected bone to select vertexgroup, so no switch to new active object */
+ if(G.f & G_WEIGHTPAINT) {
+ /* prevent activating */
+ basact= NULL;
+ }
+
+ }
+ /* prevent bone selecting to pass on to object selecting */
+ if(basact==BASACT)
+ basact= NULL;
+ }
+ }
+ }
+
+ /* so, do we have something selected? */
+ if(basact) {
+
+ if(vc.obedit) {
+ /* only do select */
+ deselectall_except(scene, basact);
+ ED_base_object_select(basact, BA_SELECT);
+ }
+ /* also prevent making it active on mouse selection */
+ else if (BASE_SELECTABLE(v3d, basact)) {
+
+ oldbasact= BASACT;
+
+ if(!extend) {
+ deselectall_except(scene, basact);
+ ED_base_object_select(basact, BA_SELECT);
+ }
+ else if(0) {
+ // XXX select_all_from_groups(basact);
+ }
+ else {
+ if(basact->flag & SELECT) {
+ if(basact==oldbasact)
+ ED_base_object_select(basact, BA_DESELECT);
+ }
+ else ED_base_object_select(basact, BA_SELECT);
+ }
+
+ if(oldbasact != basact) {
+ ED_base_object_activate(C, basact); /* adds notifier */
+ }
+
+ WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
+ }
+ }
+}
+
+/* ******************** border and circle ************************************** */
+
+
+int edge_inside_circle(short centx, short centy, short rad, short x1, short y1, short x2, short y2)
+{
+ int radsq= rad*rad;
+ float v1[2], v2[2], v3[2];
+
+ /* check points in circle itself */
+ if( (x1-centx)*(x1-centx) + (y1-centy)*(y1-centy) <= radsq ) return 1;
+ if( (x2-centx)*(x2-centx) + (y2-centy)*(y2-centy) <= radsq ) return 1;
+
+ /* pointdistline */
+ v3[0]= centx;
+ v3[1]= centy;
+ v1[0]= x1;
+ v1[1]= y1;
+ v2[0]= x2;
+ v2[1]= y2;
+
+ if( PdistVL2Dfl(v3, v1, v2) < (float)rad ) return 1;
+
+ return 0;
+}
+
+static void do_nurbs_box_select__doSelect(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y)
+{
+ struct { ViewContext vc; rcti *rect; int select; } *data = userData;
+
+ if (BLI_in_rcti(data->rect, x, y)) {
+ if (bp) {
+ bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT);
+ } else {
+ if (G.f & G_HIDDENHANDLES) {
+ /* can only be beztindex==0 here since handles are hidden */
+ bezt->f1 = bezt->f2 = bezt->f3 = data->select?(bezt->f2|SELECT):(bezt->f2&~SELECT);
+ } else {
+ if (beztindex==0) {
+ bezt->f1 = data->select?(bezt->f1|SELECT):(bezt->f1&~SELECT);
+ } else if (beztindex==1) {
+ bezt->f2 = data->select?(bezt->f2|SELECT):(bezt->f2&~SELECT);
+ } else {
+ bezt->f3 = data->select?(bezt->f3|SELECT):(bezt->f3&~SELECT);
+ }
+ }
+ }
+ }
+}
+static void do_nurbs_box_select(ViewContext *vc, rcti *rect, int select)
+{
+ struct { ViewContext vc; rcti *rect; int select; } data;
+
+ data.vc= *vc;
+ data.rect = rect;
+ data.select = select;
+
+ nurbs_foreachScreenVert(vc, do_nurbs_box_select__doSelect, &data);
+}
+
+static void do_lattice_box_select__doSelect(void *userData, BPoint *bp, int x, int y)
+{
+ struct { ViewContext vc; rcti *rect; int select; } *data = userData;
+
+ if (BLI_in_rcti(data->rect, x, y)) {
+ bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT);
+ }
+}
+static void do_lattice_box_select(ViewContext *vc, rcti *rect, int select)
+{
+ struct { ViewContext vc; rcti *rect; int select, pass, done; } data;
+
+ data.vc= *vc;
+ data.rect = rect;
+ data.select = select;
+
+ lattice_foreachScreenVert(vc, do_lattice_box_select__doSelect, &data);
+}
+
+static void do_mesh_box_select__doSelectVert(void *userData, EditVert *eve, int x, int y, int index)
+{
+ struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData;
+
+ if (BLI_in_rcti(data->rect, x, y)) {
+ eve->f = data->select?(eve->f|1):(eve->f&~1);
+ }
+}
+static void do_mesh_box_select__doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
+{
+ struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData;
+
+ if(EM_check_backbuf(em_solidoffs+index)) {
+ if (data->pass==0) {
+ if (edge_fully_inside_rect(data->rect, x0, y0, x1, y1)) {
+ EM_select_edge(eed, data->select);
+ data->done = 1;
+ }
+ } else {
+ if (edge_inside_rect(data->rect, x0, y0, x1, y1)) {
+ EM_select_edge(eed, data->select);
+ }
+ }
+ }
+}
+static void do_mesh_box_select__doSelectFace(void *userData, EditFace *efa, int x, int y, int index)
+{
+ struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData;
+
+ if (BLI_in_rcti(data->rect, x, y)) {
+ EM_select_face_fgon(data->vc.em, efa, data->select);
+ }
+}
+static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select)
+{
+ struct { ViewContext vc; rcti *rect; short select, pass, done; } data;
+ int bbsel;
+
+ data.vc= *vc;
+ data.rect = rect;
+ data.select = select;
+ data.pass = 0;
+ data.done = 0;
+
+ bbsel= EM_init_backbuf_border(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+
+ if(vc->scene->selectmode & SCE_SELECT_VERTEX) {
+ if (bbsel) {
+ EM_backbuf_checkAndSelectVerts(vc->em, select);
+ } else {
+ mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, 1);
+ }
+ }
+ if(vc->scene->selectmode & SCE_SELECT_EDGE) {
+ /* Does both bbsel and non-bbsel versions (need screen cos for both) */
+
+ data.pass = 0;
+ mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, 0);
+
+ if (data.done==0) {
+ data.pass = 1;
+ mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, 0);
+ }
+ }
+
+ if(vc->scene->selectmode & SCE_SELECT_FACE) {
+ if(bbsel) {
+ EM_backbuf_checkAndSelectFaces(vc->em, select);
+ } else {
+ mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data);
+ }
+ }
+
+ EM_free_backbuf();
+
+ EM_selectmode_flush(vc->em);
+}
+
+static int view3d_borderselect_exec(bContext *C, wmOperator *op)
+{
+ ViewContext vc;
+ Scene *scene= CTX_data_scene(C);
+ ScrArea *sa= CTX_wm_area(C);
+ View3D *v3d= sa->spacedata.first;
+ Object *obedit= CTX_data_edit_object(C);
+ rcti rect;
+ Base *base;
+ MetaElem *ml;
+ unsigned int buffer[4*MAXPICKBUF];
+ int a, index;
+ short hits, val;
+
+ view3d_operator_needs_opengl(C);
+
+ /* setup view context for argument to callbacks */
+ view3d_set_viewcontext(C, &vc);
+
+ val= RNA_int_get(op->ptr, "event_type");
+ rect.xmin= RNA_int_get(op->ptr, "xmin");
+ rect.ymin= RNA_int_get(op->ptr, "ymin");
+ rect.xmax= RNA_int_get(op->ptr, "xmax");
+ rect.ymax= RNA_int_get(op->ptr, "ymax");
+
+ if(obedit==NULL && (FACESEL_PAINT_TEST)) {
+// XXX face_borderselect();
+ return OPERATOR_FINISHED;
+ }
+ else if(obedit==NULL && (G.f & G_PARTICLEEDIT)) {
+ return PE_border_select(C, &rect, (val==LEFTMOUSE));
+ }
+
+ if(obedit) {
+ if(obedit->type==OB_MESH) {
+ Mesh *me= obedit->data;
+ vc.em= me->edit_mesh;
+ do_mesh_box_select(&vc, &rect, (val==LEFTMOUSE));
+// if (EM_texFaceCheck())
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ }
+ else if(ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ do_nurbs_box_select(&vc, &rect, val==LEFTMOUSE);
+ }
+ else if(obedit->type==OB_MBALL) {
+ hits= view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
+
+ ml= NULL; // XXX editelems.first;
+
+ while(ml) {
+ for(a=0; a<hits; a++) {
+ if(ml->selcol1==buffer[ (4 * a) + 3 ]) {
+ ml->flag |= MB_SCALE_RAD;
+ if(val==LEFTMOUSE) ml->flag |= SELECT;
+ else ml->flag &= ~SELECT;
+ break;
+ }
+ if(ml->selcol2==buffer[ (4 * a) + 3 ]) {
+ ml->flag &= ~MB_SCALE_RAD;
+ if(val==LEFTMOUSE) ml->flag |= SELECT;
+ else ml->flag &= ~SELECT;
+ break;
+ }
+ }
+ ml= ml->next;
+ }
+ }
+ else if(obedit->type==OB_ARMATURE) {
+ bArmature *arm= obedit->data;
+ EditBone *ebone;
+
+ /* clear flag we use to detect point was affected */
+ for(ebone= arm->edbo->first; ebone; ebone= ebone->next)
+ ebone->flag &= ~BONE_DONE;
+
+ hits= view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
+
+ /* first we only check points inside the border */
+ for (a=0; a<hits; a++){
+ index = buffer[(4*a)+3];
+ if (index!=-1) {
+ ebone = BLI_findlink(arm->edbo, index & ~(BONESEL_ANY));
+ if (index & BONESEL_TIP) {
+ ebone->flag |= BONE_DONE;
+ if (val==LEFTMOUSE) ebone->flag |= BONE_TIPSEL;
+ else ebone->flag &= ~BONE_TIPSEL;
+ }
+
+ if (index & BONESEL_ROOT) {
+ ebone->flag |= BONE_DONE;
+ if (val==LEFTMOUSE) ebone->flag |= BONE_ROOTSEL;
+ else ebone->flag &= ~BONE_ROOTSEL;
+ }
+ }
+ }
+
+ /* now we have to flush tag from parents... */
+ for(ebone= arm->edbo->first; ebone; ebone= ebone->next) {
+ if(ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ if(ebone->parent->flag & BONE_DONE)
+ ebone->flag |= BONE_DONE;
+ }
+ }
+
+ /* only select/deselect entire bones when no points where in the rect */
+ for (a=0; a<hits; a++){
+ index = buffer[(4*a)+3];
+ if (index!=-1) {
+ ebone = BLI_findlink(arm->edbo, index & ~(BONESEL_ANY));
+ if (index & BONESEL_BONE) {
+ if(!(ebone->flag & BONE_DONE)) {
+ if (val==LEFTMOUSE)
+ ebone->flag |= (BONE_ROOTSEL|BONE_TIPSEL|BONE_SELECTED);
+ else
+ ebone->flag &= ~(BONE_ROOTSEL|BONE_TIPSEL|BONE_SELECTED);
+ }
+ }
+ }
+ }
+
+ }
+ else if(obedit->type==OB_LATTICE) {
+ do_lattice_box_select(&vc, &rect, val==LEFTMOUSE);
+ }
+ }
+ else { /* no editmode, unified for bones and objects */
+ Bone *bone;
+ Object *ob= OBACT;
+ unsigned int *vbuffer=NULL; /* selection buffer */
+ unsigned int *col; /* color in buffer */
+ short selecting = 0;
+ int bone_only;
+ int totobj= MAXPICKBUF; // XXX solve later
+
+ if((ob) && (ob->flag & OB_POSEMODE))
+ bone_only= 1;
+ else
+ bone_only= 0;
+
+ if (val==LEFTMOUSE)
+ selecting = 1;
+
+ /* selection buffer now has bones potentially too, so we add MAXPICKBUF */
+ vbuffer = MEM_mallocN(4 * (totobj+MAXPICKBUF) * sizeof(unsigned int), "selection buffer");
+ hits= view3d_opengl_select(&vc, vbuffer, 4*(totobj+MAXPICKBUF), &rect);
+ /*
+ LOGIC NOTES (theeth):
+ The buffer and ListBase have the same relative order, which makes the selection
+ very simple. Loop through both data sets at the same time, if the color
+ is the same as the object, we have a hit and can move to the next color
+ and object pair, if not, just move to the next object,
+ keeping the same color until we have a hit.
+
+ The buffer order is defined by OGL standard, hopefully no stupid GFX card
+ does it incorrectly.
+ */
+
+ if (hits>0) { /* no need to loop if there's no hit */
+ base= FIRSTBASE;
+ col = vbuffer + 3;
+
+ while(base && hits) {
+ Base *next = base->next;
+ if(base->lay & v3d->lay) {
+ while (base->selcol == (*col & 0xFFFF)) { /* we got an object */
+
+ if(*col & 0xFFFF0000) { /* we got a bone */
+ bone = get_indexed_bone(base->object, *col & ~(BONESEL_ANY));
+ if(bone) {
+ if(selecting) {
+ bone->flag |= BONE_SELECTED;
+// XXX select_actionchannel_by_name(base->object->action, bone->name, 1);
+ }
+ else {
+ bone->flag &= ~(BONE_ACTIVE|BONE_SELECTED);
+// XXX select_actionchannel_by_name(base->object->action, bone->name, 0);
+ }
+ }
+ }
+ else if(!bone_only) {
+ if (selecting)
+ ED_base_object_select(base, BA_SELECT);
+ else
+ ED_base_object_select(base, BA_DESELECT);
+ }
+
+ col+=4; /* next color */
+ hits--;
+ if(hits==0) break;
+ }
+ }
+
+ base= next;
+ }
+
+ WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
+
+ }
+ MEM_freeN(vbuffer);
+ }
+ return OPERATOR_FINISHED;
+}
+
+
+/* *****************Selection Operators******************* */
+static EnumPropertyItem prop_select_types[] = {
+ {0, "EXCLUSIVE", "Exclusive", ""},
+ {1, "EXTEND", "Extend", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* ****** Border Select ****** */
+void VIEW3D_OT_select_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Border Select";
+ ot->idname= "VIEW3D_OT_select_border";
+
+ /* api callbacks */
+ ot->invoke= WM_border_select_invoke;
+ ot->exec= view3d_borderselect_exec;
+ ot->modal= WM_border_select_modal;
+
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* rna */
+ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+
+ RNA_def_enum(ot->srna, "type", prop_select_types, 0, "Type", "");
+}
+
+/* ****** Mouse Select ****** */
+
+
+static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ short extend= RNA_enum_is_equal(op->ptr, "type", "EXTEND");
+
+ view3d_operator_needs_opengl(C);
+
+ if(obedit) {
+ if(obedit->type==OB_MESH)
+ mouse_mesh(C, event->mval, extend);
+ else if(obedit->type==OB_ARMATURE)
+ mouse_armature(C, event->mval, extend);
+ else if(obedit->type==OB_LATTICE)
+ mouse_lattice(C, event->mval, extend);
+ else if(ELEM(obedit->type, OB_CURVE, OB_SURF))
+ mouse_nurb(C, event->mval, extend);
+
+ }
+ else if(G.f & G_PARTICLEEDIT)
+ PE_mouse_particles(C, event->mval, extend);
+ else
+ mouse_select(C, event->mval, extend, 0);
+
+ /* allowing tweaks */
+ return OPERATOR_PASS_THROUGH|OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Activate/Select";
+ ot->idname= "VIEW3D_OT_select";
+
+ /* api callbacks */
+ ot->invoke= view3d_select_invoke;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", prop_select_types, 0, "Type", "");
+}
+
+
+/* -------------------- circle select --------------------------------------------- */
+
+static void mesh_circle_doSelectVert(void *userData, EditVert *eve, int x, int y, int index)
+{
+ struct {ViewContext *vc; short select, mval[2]; float radius; } *data = userData;
+ int mx = x - data->mval[0], my = y - data->mval[1];
+ float r = sqrt(mx*mx + my*my);
+
+ if (r<=data->radius) {
+ eve->f = data->select?(eve->f|1):(eve->f&~1);
+ }
+}
+static void mesh_circle_doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
+{
+ struct {ViewContext *vc; short select, mval[2]; float radius; } *data = userData;
+
+ if (edge_inside_circle(data->mval[0], data->mval[1], (short) data->radius, x0, y0, x1, y1)) {
+ EM_select_edge(eed, data->select);
+ }
+}
+static void mesh_circle_doSelectFace(void *userData, EditFace *efa, int x, int y, int index)
+{
+ struct {ViewContext *vc; short select, mval[2]; float radius; } *data = userData;
+ int mx = x - data->mval[0], my = y - data->mval[1];
+ float r = sqrt(mx*mx + my*my);
+
+ if (r<=data->radius) {
+ EM_select_face_fgon(data->vc->em, efa, data->select);
+ }
+}
+
+static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, float rad)
+{
+ int bbsel;
+
+ if(vc->obedit==NULL && (FACESEL_PAINT_TEST)) {
+ Object *ob= vc->obact;
+ Mesh *me = ob?ob->data:NULL;
+
+ if (me) {
+ em_vertoffs= me->totface+1; /* max index array */
+
+ bbsel= EM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0));
+ EM_backbuf_checkAndSelectTFaces(me, selecting==LEFTMOUSE);
+ EM_free_backbuf();
+
+// XXX object_tface_flags_changed(OBACT, 0);
+ }
+ }
+ else {
+ struct {ViewContext *vc; short select, mval[2]; float radius; } data;
+
+ bbsel= EM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0));
+ vc->em= ((Mesh *)vc->obedit->data)->edit_mesh;
+
+ data.select = selecting;
+ data.mval[0] = mval[0];
+ data.mval[1] = mval[1];
+ data.radius = rad;
+
+ if(vc->scene->selectmode & SCE_SELECT_VERTEX) {
+ if(bbsel) {
+ EM_backbuf_checkAndSelectVerts(vc->em, selecting==LEFTMOUSE);
+ } else {
+ mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, 1);
+ }
+ }
+
+ if(vc->scene->selectmode & SCE_SELECT_EDGE) {
+ if (bbsel) {
+ EM_backbuf_checkAndSelectEdges(vc->em, selecting==LEFTMOUSE);
+ } else {
+ mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, 0);
+ }
+ }
+
+ if(vc->scene->selectmode & SCE_SELECT_FACE) {
+ if(bbsel) {
+ EM_backbuf_checkAndSelectFaces(vc->em, selecting==LEFTMOUSE);
+ } else {
+ mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data);
+ }
+ }
+
+ EM_free_backbuf();
+ EM_selectmode_flush(vc->em);
+ }
+}
+
+
+static void nurbscurve_circle_doSelect(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y)
+{
+ struct {ViewContext *vc; short select, mval[2]; float radius; } *data = userData;
+ int mx = x - data->mval[0], my = y - data->mval[1];
+ float r = sqrt(mx*mx + my*my);
+
+ if (r<=data->radius) {
+ if (bp) {
+ bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT);
+ } else {
+ if (beztindex==0) {
+ bezt->f1 = data->select?(bezt->f1|SELECT):(bezt->f1&~SELECT);
+ } else if (beztindex==1) {
+ bezt->f2 = data->select?(bezt->f2|SELECT):(bezt->f2&~SELECT);
+ } else {
+ bezt->f3 = data->select?(bezt->f3|SELECT):(bezt->f3&~SELECT);
+ }
+ }
+ }
+}
+static void nurbscurve_circle_select(ViewContext *vc, int selecting, short *mval, float rad)
+{
+ struct {ViewContext *vc; short select, mval[2]; float radius; } data;
+
+ /* set vc-> edit data */
+
+ data.select = selecting;
+ data.mval[0] = mval[0];
+ data.mval[1] = mval[1];
+ data.radius = rad;
+
+ nurbs_foreachScreenVert(vc, nurbscurve_circle_doSelect, &data);
+}
+
+
+static void latticecurve_circle_doSelect(void *userData, BPoint *bp, int x, int y)
+{
+ struct {ViewContext *vc; short select, mval[2]; float radius; } *data = userData;
+ int mx = x - data->mval[0], my = y - data->mval[1];
+ float r = sqrt(mx*mx + my*my);
+
+ if (r<=data->radius) {
+ bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT);
+ }
+}
+static void lattice_circle_select(ViewContext *vc, int selecting, short *mval, float rad)
+{
+ struct {ViewContext *vc; short select, mval[2]; float radius; } data;
+
+ /* set vc-> edit data */
+
+ data.select = selecting;
+ data.mval[0] = mval[0];
+ data.mval[1] = mval[1];
+ data.radius = rad;
+
+ lattice_foreachScreenVert(vc, latticecurve_circle_doSelect, &data);
+}
+
+/** Callbacks for circle selection in Editmode */
+
+static void obedit_circle_select(ViewContext *vc, short selecting, short *mval, float rad)
+{
+ switch(vc->obedit->type) {
+ case OB_MESH:
+ mesh_circle_select(vc, selecting, mval, rad);
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ nurbscurve_circle_select(vc, selecting, mval, rad);
+ break;
+ case OB_LATTICE:
+ lattice_circle_select(vc, selecting, mval, rad);
+ break;
+ default:
+ return;
+ }
+}
+
+/* not a real operator, only for circle test */
+static int view3d_circle_select_exec(bContext *C, wmOperator *op)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= CTX_wm_region(C);
+ Scene *scene= CTX_data_scene(C);
+ View3D *v3d= sa->spacedata.first;
+ int x= RNA_int_get(op->ptr, "x");
+ int y= RNA_int_get(op->ptr, "y");
+ int radius= RNA_int_get(op->ptr, "radius");
+
+ if(CTX_data_edit_object(C) || (G.f & G_PARTICLEEDIT)) {
+ ViewContext vc;
+ short mval[2], selecting;
+
+ view3d_operator_needs_opengl(C);
+
+ view3d_set_viewcontext(C, &vc);
+ mval[0]= x;
+ mval[1]= y;
+ selecting= LEFTMOUSE==RNA_int_get(op->ptr, "event_type"); // XXX solve
+
+ if(CTX_data_edit_object(C))
+ obedit_circle_select(&vc, selecting, mval, (float)radius);
+ else
+ return PE_circle_select(C, selecting, mval, (float)radius);
+ }
+ else {
+ Base *base;
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(base->lay & v3d->lay) {
+ project_short(ar, base->object->obmat[3], &base->sx);
+ if(base->sx!=IS_CLIPPED) {
+ int dx= base->sx-x;
+ int dy= base->sy-y;
+ if( dx*dx + dy*dy < radius*radius)
+ ED_base_object_select(base, BA_SELECT);
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_select_circle(wmOperatorType *ot)
+{
+ ot->name= "Circle Select";
+ ot->idname= "VIEW3D_OT_select_circle";
+
+ ot->invoke= WM_gesture_circle_invoke;
+ ot->modal= WM_gesture_circle_modal;
+ ot->exec= view3d_circle_select_exec;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "radius", 0, INT_MIN, INT_MAX, "Radius", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+}
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
new file mode 100644
index 00000000000..ad9d3f85538
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -0,0 +1,1148 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_group_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_modifier_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 "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_linklist.h"
+
+#include "BKE_action.h"
+#include "BKE_anim.h"
+#include "BKE_context.h"
+#include "BKE_armature.h"
+#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_lattice.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_interface.h"
+
+#include "ED_anim_api.h"
+#include "ED_armature.h"
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "view3d_intern.h"
+
+
+/* ************************************************** */
+/* ********************* old transform stuff ******** */
+/* *********** will get replaced with new transform * */
+/* ************************************************** */
+
+typedef struct TransVert {
+ float *loc;
+ float oldloc[3], fac;
+ float *val, oldval;
+ int flag;
+ float *nor;
+} TransVert;
+
+static TransVert *transvmain=NULL;
+static int tottrans= 0;
+
+/* copied from editobject.c, now uses (almost) proper depgraph */
+static void special_transvert_update(Scene *scene, Object *obedit)
+{
+
+ if(obedit) {
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ if(obedit->type==OB_MESH) {
+ Mesh *me= obedit->data;
+ recalc_editnormals(me->edit_mesh); // does face centers too
+ }
+ else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ Curve *cu= obedit->data;
+ Nurb *nu= cu->editnurb->first;
+
+ while(nu) {
+ test2DNurb(nu);
+ testhandlesNurb(nu); /* test for bezier too */
+ nu= nu->next;
+ }
+ }
+ else if(obedit->type==OB_ARMATURE){
+ bArmature *arm= obedit->data;
+ EditBone *ebo;
+ TransVert *tv= transvmain;
+ int a=0;
+
+ /* Ensure all bone tails are correctly adjusted */
+ for (ebo= arm->edbo->first; ebo; ebo=ebo->next) {
+ /* adjust tip if both ends selected */
+ if ((ebo->flag & BONE_ROOTSEL) && (ebo->flag & BONE_TIPSEL)) {
+ if (tv) {
+ float diffvec[3];
+
+ VecSubf(diffvec, tv->loc, tv->oldloc);
+ VecAddf(ebo->tail, ebo->tail, diffvec);
+
+ a++;
+ if (a<tottrans) tv++;
+ }
+ }
+ }
+
+ /* Ensure all bones are correctly adjusted */
+ for (ebo= arm->edbo->first; ebo; ebo=ebo->next) {
+ if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
+ /* If this bone has a parent tip that has been moved */
+ if (ebo->parent->flag & BONE_TIPSEL){
+ VECCOPY (ebo->head, ebo->parent->tail);
+ }
+ /* If this bone has a parent tip that has NOT been moved */
+ else{
+ VECCOPY (ebo->parent->tail, ebo->head);
+ }
+ }
+ }
+ if(arm->flag & ARM_MIRROR_EDIT)
+ transform_armature_mirror_update(obedit);
+ }
+ else if(obedit->type==OB_LATTICE) {
+ Lattice *lt= obedit->data;
+
+ if(lt->editlatt->flag & LT_OUTSIDE)
+ outside_lattice(lt->editlatt);
+ }
+ }
+}
+
+/* copied from editobject.c, needs to be replaced with new transform code still */
+/* mode: 1 = proportional, 2 = all joints (for bones only) */
+static void make_trans_verts(Object *obedit, float *min, float *max, int mode)
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ TransVert *tv=NULL;
+ MetaElem *ml;
+ EditVert *eve;
+ EditBone *ebo;
+ float total, center[3], centroid[3];
+ int a;
+
+ tottrans= 0; // global!
+
+ INIT_MINMAX(min, max);
+ centroid[0]=centroid[1]=centroid[2]= 0.0;
+
+ if(obedit->type==OB_MESH) {
+ Mesh *me= obedit->data;
+ EditMesh *em= me->edit_mesh;
+ int proptrans= 0;
+
+ // transform now requires awareness for select mode, so we tag the f1 flags in verts
+ tottrans= 0;
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->h==0 && (eve->f & SELECT)) {
+ eve->f1= SELECT;
+ tottrans++;
+ }
+ else eve->f1= 0;
+ }
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ EditEdge *eed;
+ for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->h==0 && (eed->f & SELECT)) eed->v1->f1= eed->v2->f1= SELECT;
+ }
+ for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
+ }
+ else {
+ EditFace *efa;
+ for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->h==0 && (efa->f & SELECT)) {
+ efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
+ if(efa->v4) efa->v4->f1= SELECT;
+ }
+ }
+ for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
+ }
+
+ /* proportional edit exception... */
+ if((mode & 1) && tottrans) {
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->h==0) {
+ eve->f1 |= 2;
+ proptrans++;
+ }
+ }
+ if(proptrans>tottrans) tottrans= proptrans;
+ }
+
+ /* and now make transverts */
+ if(tottrans) {
+ tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f1) {
+ VECCOPY(tv->oldloc, eve->co);
+ tv->loc= eve->co;
+ if(eve->no[0]!=0.0 || eve->no[1]!=0.0 ||eve->no[2]!=0.0)
+ tv->nor= eve->no; // note this is a hackish signal (ton)
+ tv->flag= eve->f1 & SELECT;
+ tv++;
+ }
+ }
+ }
+ }
+ else if (obedit->type==OB_ARMATURE){
+ bArmature *arm= obedit->data;
+ int totmalloc= BLI_countlist(arm->edbo);
+
+ tv=transvmain= MEM_callocN(totmalloc*sizeof(TransVert), "maketransverts armature");
+
+ for (ebo= arm->edbo->first; ebo; ebo=ebo->next){
+ if(ebo->layer & arm->layer) {
+ short tipsel= (ebo->flag & BONE_TIPSEL);
+ short rootsel= (ebo->flag & BONE_ROOTSEL);
+ short rootok= (!(ebo->parent && (ebo->flag & BONE_CONNECTED) && ebo->parent->flag & BONE_TIPSEL));
+
+ if ((tipsel && rootsel) || (rootsel)) {
+ /* Don't add the tip (unless mode & 2, for getting all joints),
+ * otherwise we get zero-length bones as tips will snap to the same
+ * location as heads.
+ */
+ if (rootok) {
+ VECCOPY (tv->oldloc, ebo->head);
+ tv->loc= ebo->head;
+ tv->nor= NULL;
+ tv->flag= 1;
+ tv++;
+ tottrans++;
+ }
+
+ if ((mode & 2) && (tipsel)) {
+ VECCOPY (tv->oldloc, ebo->tail);
+ tv->loc= ebo->tail;
+ tv->nor= NULL;
+ tv->flag= 1;
+ tv++;
+ tottrans++;
+ }
+ }
+ else if (tipsel) {
+ VECCOPY (tv->oldloc, ebo->tail);
+ tv->loc= ebo->tail;
+ tv->nor= NULL;
+ tv->flag= 1;
+ tv++;
+ tottrans++;
+ }
+ }
+ }
+ }
+ else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ Curve *cu= obedit->data;
+ int totmalloc= 0;
+
+ for(nu= cu->editnurb->first; nu; nu= nu->next) {
+ if((nu->type & 7)==CU_BEZIER)
+ totmalloc += 3*nu->pntsu;
+ else
+ totmalloc += nu->pntsu*nu->pntsv;
+ }
+ tv=transvmain= MEM_callocN(totmalloc*sizeof(TransVert), "maketransverts curve");
+
+ nu= cu->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 & SELECT)) {
+ VECCOPY(tv->oldloc, bezt->vec[0]);
+ tv->loc= bezt->vec[0];
+ tv->flag= bezt->f1 & SELECT;
+ tv++;
+ tottrans++;
+ }
+ if((mode & 1) || (bezt->f2 & SELECT)) {
+ VECCOPY(tv->oldloc, bezt->vec[1]);
+ tv->loc= bezt->vec[1];
+ tv->val= &(bezt->alfa);
+ tv->oldval= bezt->alfa;
+ tv->flag= bezt->f2 & SELECT;
+ tv++;
+ tottrans++;
+ }
+ if((mode & 1) || (bezt->f3 & SELECT)) {
+ VECCOPY(tv->oldloc, bezt->vec[2]);
+ tv->loc= bezt->vec[2];
+ tv->flag= bezt->f3 & SELECT;
+ tv++;
+ tottrans++;
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ if(bp->hide==0) {
+ if((mode & 1) || (bp->f1 & SELECT)) {
+ VECCOPY(tv->oldloc, bp->vec);
+ tv->loc= bp->vec;
+ tv->val= &(bp->alfa);
+ tv->oldval= bp->alfa;
+ tv->flag= bp->f1 & SELECT;
+ tv++;
+ tottrans++;
+ }
+ }
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ }
+ else if(obedit->type==OB_MBALL) {
+ MetaBall *mb= obedit->data;
+ int totmalloc= BLI_countlist(mb->editelems);
+
+ tv=transvmain= MEM_callocN(totmalloc*sizeof(TransVert), "maketransverts mball");
+
+ ml= mb->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(obedit->type==OB_LATTICE) {
+ Lattice *lt= obedit->data;
+
+ bp= lt->editlatt->def;
+
+ a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
+
+ tv=transvmain= MEM_callocN(a*sizeof(TransVert), "maketransverts curve");
+
+ while(a--) {
+ if((mode & 1) || (bp->f1 & SELECT)) {
+ if(bp->hide==0) {
+ VECCOPY(tv->oldloc, bp->vec);
+ tv->loc= bp->vec;
+ tv->flag= bp->f1 & SELECT;
+ tv++;
+ tottrans++;
+ }
+ }
+ bp++;
+ }
+ }
+
+ /* cent etc */
+ tv= transvmain;
+ total= 0.0;
+ for(a=0; a<tottrans; a++, tv++) {
+ if(tv->flag & SELECT) {
+ centroid[0]+= tv->oldloc[0];
+ centroid[1]+= tv->oldloc[1];
+ centroid[2]+= tv->oldloc[2];
+ total+= 1.0;
+ DO_MINMAX(tv->oldloc, min, max);
+ }
+ }
+ if(total!=0.0) {
+ centroid[0]/= total;
+ centroid[1]/= total;
+ centroid[2]/= total;
+ }
+
+ center[0]= (min[0]+max[0])/2.0;
+ center[1]= (min[1]+max[1])/2.0;
+ center[2]= (min[2]+max[2])/2.0;
+
+}
+
+/* *********************** operators ******************** */
+
+static int snap_sel_to_grid(bContext *C, wmOperator *op)
+{
+ extern float originmat[3][3]; /* XXX object.c */
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene= CTX_data_scene(C);
+ View3D *v3d= CTX_wm_view3d(C);
+ TransVert *tv;
+ Object *ob;
+ float gridf, imat[3][3], bmat[3][3], vec[3];
+ int a;
+
+ gridf= v3d->gridview;
+
+ if(obedit) {
+ tottrans= 0;
+
+ if ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)
+ make_trans_verts(obedit, bmat[0], bmat[1], 0);
+ if(tottrans==0) return OPERATOR_CANCELLED;
+
+ Mat3CpyMat4(bmat, obedit->obmat);
+ Mat3Inv(imat, bmat);
+
+ tv= transvmain;
+ for(a=0; a<tottrans; a++, tv++) {
+
+ VECCOPY(vec, tv->loc);
+ Mat3MulVecfl(bmat, vec);
+ VecAddf(vec, vec, obedit->obmat[3]);
+ vec[0]= v3d->gridview*floor(.5+ vec[0]/gridf);
+ vec[1]= v3d->gridview*floor(.5+ vec[1]/gridf);
+ vec[2]= v3d->gridview*floor(.5+ vec[2]/gridf);
+ VecSubf(vec, vec, obedit->obmat[3]);
+
+ Mat3MulVecfl(imat, vec);
+ VECCOPY(tv->loc, vec);
+ }
+
+ special_transvert_update(scene, obedit);
+
+ MEM_freeN(transvmain);
+ transvmain= NULL;
+
+ }
+ else {
+
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ ob= base->object;
+
+ if(ob->flag & OB_POSEMODE) {
+ bPoseChannel *pchan;
+ bArmature *arm= ob->data;
+
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if(pchan->bone->flag & BONE_SELECTED) {
+ if(pchan->bone->layer & arm->layer) {
+ if((pchan->bone->flag & BONE_CONNECTED)==0) {
+ float vecN[3], nLoc[3];
+
+ /* get nearest grid point to snap to */
+ VECCOPY(nLoc, pchan->pose_mat[3]);
+ vec[0]= gridf * (float)(floor(.5+ nLoc[0]/gridf));
+ vec[1]= gridf * (float)(floor(.5+ nLoc[1]/gridf));
+ vec[2]= gridf * (float)(floor(.5+ nLoc[2]/gridf));
+
+ /* get bone-space location of grid point */
+ armature_loc_pose_to_bone(pchan, vec, vecN);
+
+ /* adjust location */
+ VECCOPY(pchan->loc, vecN);
+ }
+ /* if the bone has a parent and is connected to the parent,
+ * don't do anything - will break chain unless we do auto-ik.
+ */
+ }
+ }
+ }
+ ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
+
+ /* auto-keyframing */
+// XXX autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+ else {
+ ob->recalc |= OB_RECALC_OB;
+
+ vec[0]= -ob->obmat[3][0]+v3d->gridview*floor(.5+ ob->obmat[3][0]/gridf);
+ vec[1]= -ob->obmat[3][1]+v3d->gridview*floor(.5+ ob->obmat[3][1]/gridf);
+ vec[2]= -ob->obmat[3][2]+v3d->gridview*floor(.5+ ob->obmat[3][2]/gridf);
+
+ if(ob->parent) {
+ where_is_object(scene, 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];
+ }
+
+ /* auto-keyframing */
+// XXX autokeyframe_ob_cb_func(ob, TFM_TRANSLATION);
+ }
+ }
+ CTX_DATA_END;
+ }
+ ED_anim_dag_flush_update(C);
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Snap Selection to Grid";
+ ot->idname= "VIEW3D_OT_snap_selected_to_grid";
+
+ /* api callbacks */
+ ot->exec= snap_sel_to_grid;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* *************************************************** */
+
+static int snap_sel_to_curs(bContext *C, wmOperator *op)
+{
+ extern float originmat[3][3]; /* XXX object.c */
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene= CTX_data_scene(C);
+ View3D *v3d= CTX_wm_view3d(C);
+ TransVert *tv;
+ Object *ob;
+ float *curs, imat[3][3], bmat[3][3], vec[3];
+ int a;
+
+ curs= give_cursor(scene, v3d);
+
+ if(obedit) {
+ tottrans= 0;
+
+ if ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)
+ make_trans_verts(obedit, bmat[0], bmat[1], 0);
+ if(tottrans==0) return OPERATOR_CANCELLED;
+
+ Mat3CpyMat4(bmat, obedit->obmat);
+ Mat3Inv(imat, bmat);
+
+ tv= transvmain;
+ for(a=0; a<tottrans; a++, tv++) {
+ vec[0]= curs[0]-obedit->obmat[3][0];
+ vec[1]= curs[1]-obedit->obmat[3][1];
+ vec[2]= curs[2]-obedit->obmat[3][2];
+
+ Mat3MulVecfl(imat, vec);
+ VECCOPY(tv->loc, vec);
+ }
+
+ special_transvert_update(scene, obedit);
+
+ MEM_freeN(transvmain);
+ transvmain= NULL;
+
+ }
+ else {
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ ob= base->object;
+ if(ob->flag & OB_POSEMODE) {
+ bPoseChannel *pchan;
+ bArmature *arm= ob->data;
+ float cursp[3];
+
+ Mat4Invert(ob->imat, ob->obmat);
+ VECCOPY(cursp, curs);
+ Mat4MulVecfl(ob->imat, cursp);
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+ if(pchan->bone->flag & BONE_SELECTED) {
+ if(pchan->bone->layer & arm->layer) {
+ if((pchan->bone->flag & BONE_CONNECTED)==0) {
+ float curspn[3];
+
+ /* get location of cursor in bone-space */
+ armature_loc_pose_to_bone(pchan, cursp, curspn);
+
+ /* calculate new position */
+ VECCOPY(pchan->loc, curspn);
+ }
+ /* if the bone has a parent and is connected to the parent,
+ * don't do anything - will break chain unless we do auto-ik.
+ */
+ }
+ }
+ }
+ ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
+
+ /* auto-keyframing */
+// XXX autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+ else {
+ ob->recalc |= OB_RECALC_OB;
+
+ vec[0]= -ob->obmat[3][0] + curs[0];
+ vec[1]= -ob->obmat[3][1] + curs[1];
+ vec[2]= -ob->obmat[3][2] + curs[2];
+
+ if(ob->parent) {
+ where_is_object(scene, 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];
+ }
+ /* auto-keyframing */
+// XXX autokeyframe_ob_cb_func(ob, TFM_TRANSLATION);
+ }
+ }
+ CTX_DATA_END;
+ }
+ ED_anim_dag_flush_update(C);
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Snap Selection to Cursor";
+ ot->idname= "VIEW3D_OT_snap_selected_to_cursor";
+
+ /* api callbacks */
+ ot->exec= snap_sel_to_curs;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* *************************************************** */
+
+static int snap_curs_to_grid(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ View3D *v3d= CTX_wm_view3d(C);
+ float gridf, *curs;
+
+ gridf= v3d->gridview;
+ curs= give_cursor(scene, v3d);
+
+ curs[0]= v3d->gridview*floor(.5+curs[0]/gridf);
+ curs[1]= v3d->gridview*floor(.5+curs[1]/gridf);
+ curs[2]= v3d->gridview*floor(.5+curs[2]/gridf);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_TRANSFORM, scene); // hrm
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Snap Cursor to Grid";
+ ot->idname= "VIEW3D_OT_snap_cursor_to_grid";
+
+ /* api callbacks */
+ ot->exec= snap_curs_to_grid;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* **************************************************** */
+
+static int snap_curs_to_sel(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene= CTX_data_scene(C);
+ View3D *v3d= CTX_wm_view3d(C);
+ TransVert *tv;
+ float *curs, bmat[3][3], vec[3], min[3], max[3], centroid[3];
+ int count, a;
+
+ curs= give_cursor(scene, v3d);
+
+ count= 0;
+ INIT_MINMAX(min, max);
+ centroid[0]= centroid[1]= centroid[2]= 0.0;
+
+ if(obedit) {
+ tottrans=0;
+
+ if ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)
+ make_trans_verts(obedit, bmat[0], bmat[1], 2);
+ if(tottrans==0) return OPERATOR_CANCELLED;
+
+ Mat3CpyMat4(bmat, obedit->obmat);
+
+ tv= transvmain;
+ for(a=0; a<tottrans; a++, tv++) {
+ VECCOPY(vec, tv->loc);
+ Mat3MulVecfl(bmat, vec);
+ VecAddf(vec, vec, obedit->obmat[3]);
+ VecAddf(centroid, centroid, vec);
+ DO_MINMAX(vec, min, max);
+ }
+
+ if(v3d->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= NULL;
+ }
+ else {
+ Object *ob= OBACT;
+
+ if(ob && (ob->flag & OB_POSEMODE)) {
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+ for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+ if(arm->layer & pchan->bone->layer) {
+ if(pchan->bone->flag & BONE_SELECTED) {
+ VECCOPY(vec, pchan->pose_head);
+ Mat4MulVecfl(ob->obmat, vec);
+ VecAddf(centroid, centroid, vec);
+ DO_MINMAX(vec, min, max);
+ count++;
+ }
+ }
+ }
+ }
+ else {
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ VECCOPY(vec, base->object->obmat[3]);
+ VecAddf(centroid, centroid, vec);
+ DO_MINMAX(vec, min, max);
+ count++;
+ }
+ CTX_DATA_END;
+ }
+ if(count) {
+ if(v3d->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;
+ }
+ }
+ }
+ WM_event_add_notifier(C, NC_SCENE|ND_TRANSFORM, scene); // hrm
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Snap Cursor to Selected";
+ ot->idname= "VIEW3D_OT_snap_cursor_to_selected";
+
+ /* api callbacks */
+ ot->exec= snap_curs_to_sel;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ********************************************** */
+
+static int snap_curs_to_active(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene= CTX_data_scene(C);
+ View3D *v3d= CTX_wm_view3d(C);
+ float *curs;
+
+ curs = give_cursor(scene, v3d);
+
+ if (obedit) {
+ if (obedit->type == OB_MESH) {
+ /* check active */
+ Mesh *me= obedit->data;
+ EditSelection ese;
+
+ if (EM_get_actSelection(me->edit_mesh, &ese)) {
+ EM_editselection_center(curs, &ese);
+ }
+
+ Mat4MulVecfl(obedit->obmat, curs);
+ }
+ }
+ else {
+ if (BASACT) {
+ VECCOPY(curs, BASACT->object->obmat[3]);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCENE|ND_TRANSFORM, scene);
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Snap Cursor to Active";
+ ot->idname= "VIEW3D_OT_snap_cursor_to_active";
+
+ /* api callbacks */
+ ot->exec= snap_curs_to_active;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ************************************** */
+
+static int snap_selected_to_center(bContext *C, wmOperator *op)
+{
+ extern float originmat[3][3]; /* XXX object.c */
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene= CTX_data_scene(C);
+ View3D *v3d= CTX_wm_view3d(C);
+ TransVert *tv;
+ Object *ob;
+ float snaploc[3], imat[3][3], bmat[3][3], vec[3], min[3], max[3], centroid[3];
+ int count, a;
+
+ /*calculate the snaplocation (centerpoint) */
+ count= 0;
+ INIT_MINMAX(min, max);
+ centroid[0]= centroid[1]= centroid[2]= 0.0f;
+ snaploc[0]= snaploc[1]= snaploc[2]= 0.0f;
+
+ if(obedit) {
+ tottrans= 0;
+
+ if ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)
+ make_trans_verts(obedit, bmat[0], bmat[1], 0);
+ if(tottrans==0) return OPERATOR_CANCELLED;
+
+ Mat3CpyMat4(bmat, obedit->obmat);
+ Mat3Inv(imat, bmat);
+
+ tv= transvmain;
+ for(a=0; a<tottrans; a++, tv++) {
+ VECCOPY(vec, tv->loc);
+ Mat3MulVecfl(bmat, vec);
+ VecAddf(vec, vec, obedit->obmat[3]);
+ VecAddf(centroid, centroid, vec);
+ DO_MINMAX(vec, min, max);
+ }
+
+ if(v3d->around==V3D_CENTROID) {
+ VecMulf(centroid, 1.0/(float)tottrans);
+ VECCOPY(snaploc, centroid);
+ }
+ else {
+ snaploc[0]= (min[0]+max[0])/2;
+ snaploc[1]= (min[1]+max[1])/2;
+ snaploc[2]= (min[2]+max[2])/2;
+ }
+
+ MEM_freeN(transvmain);
+ transvmain= NULL;
+ }
+ else {
+
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ ob= base->object;
+ if(ob->flag & OB_POSEMODE) {
+ bPoseChannel *pchan;
+ bArmature *arm= ob->data;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+ if(pchan->bone->flag & BONE_SELECTED) {
+ if(pchan->bone->layer & arm->layer) {
+ VECCOPY(vec, pchan->pose_mat[3]);
+ VecAddf(centroid, centroid, vec);
+ DO_MINMAX(vec, min, max);
+ count++;
+ }
+ }
+ }
+ }
+ else {
+ /* not armature bones (i.e. objects) */
+ VECCOPY(vec, base->object->obmat[3]);
+ VecAddf(centroid, centroid, vec);
+ DO_MINMAX(vec, min, max);
+ count++;
+ }
+ }
+ CTX_DATA_END;
+
+ if(count) {
+ if(v3d->around==V3D_CENTROID) {
+ VecMulf(centroid, 1.0/(float)count);
+ VECCOPY(snaploc, centroid);
+ }
+ else {
+ snaploc[0]= (min[0]+max[0])/2;
+ snaploc[1]= (min[1]+max[1])/2;
+ snaploc[2]= (min[2]+max[2])/2;
+ }
+ }
+ }
+
+ /* Snap the selection to the snaplocation (duh!) */
+ if(obedit) {
+ tottrans= 0;
+
+ if ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)
+ make_trans_verts(obedit, bmat[0], bmat[1], 0);
+ if(tottrans==0) return OPERATOR_CANCELLED;
+
+ Mat3CpyMat4(bmat, obedit->obmat);
+ Mat3Inv(imat, bmat);
+
+ tv= transvmain;
+ for(a=0; a<tottrans; a++, tv++) {
+ vec[0]= snaploc[0]-obedit->obmat[3][0];
+ vec[1]= snaploc[1]-obedit->obmat[3][1];
+ vec[2]= snaploc[2]-obedit->obmat[3][2];
+
+ Mat3MulVecfl(imat, vec);
+ VECCOPY(tv->loc, vec);
+ }
+
+ special_transvert_update(scene, obedit);
+
+ MEM_freeN(transvmain);
+ transvmain= NULL;
+
+ }
+ else {
+
+ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
+ ob= base->object;
+ if(ob->flag & OB_POSEMODE) {
+ bPoseChannel *pchan;
+ bArmature *arm= ob->data;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+ if(pchan->bone->flag & BONE_SELECTED) {
+ if(pchan->bone->layer & arm->layer) {
+ if((pchan->bone->flag & BONE_CONNECTED)==0) {
+ /* get location of cursor in bone-space */
+ armature_loc_pose_to_bone(pchan, snaploc, vec);
+
+ /* calculate new position */
+ VECCOPY(pchan->loc, vec);
+ }
+ /* if the bone has a parent and is connected to the parent,
+ * don't do anything - will break chain unless we do auto-ik.
+ */
+ }
+ }
+ }
+
+ /* auto-keyframing */
+ ob->pose->flag |= POSE_DO_UNLOCK;
+// XXX autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+ else {
+ ob->recalc |= OB_RECALC_OB;
+
+ vec[0]= -ob->obmat[3][0] + snaploc[0];
+ vec[1]= -ob->obmat[3][1] + snaploc[1];
+ vec[2]= -ob->obmat[3][2] + snaploc[2];
+
+ if(ob->parent) {
+ where_is_object(scene, 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];
+ }
+ /* auto-keyframing */
+// XXX autokeyframe_ob_cb_func(ob, TFM_TRANSLATION);
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ ED_anim_dag_flush_update(C);
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_snap_selected_to_center(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Snap Selection to Center";
+ ot->idname= "VIEW3D_OT_snap_selected_to_center";
+
+ /* api callbacks */
+ ot->exec= snap_selected_to_center;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+int minmax_verts(Object *obedit, float *min, float *max)
+{
+ TransVert *tv;
+ float centroid[3], vec[3], bmat[3][3];
+ int a;
+
+ tottrans=0;
+ if ELEM5(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE)
+ make_trans_verts(obedit, bmat[0], bmat[1], 2);
+
+ if(tottrans==0) return 0;
+
+ Mat3CpyMat4(bmat, obedit->obmat);
+
+ tv= transvmain;
+ for(a=0; a<tottrans; a++, tv++) {
+ VECCOPY(vec, tv->loc);
+ Mat3MulVecfl(bmat, vec);
+ VecAddf(vec, vec, obedit->obmat[3]);
+ VecAddf(centroid, centroid, vec);
+ DO_MINMAX(vec, min, max);
+ }
+
+ MEM_freeN(transvmain);
+ transvmain= NULL;
+
+ return 1;
+}
+
+/* ************************************************* */
+
+static int snap_menu_invoke(bContext *C, wmOperator *unused, wmEvent *event)
+{
+ uiMenuItem *head= uiPupMenuBegin("Snap", 0);
+
+ uiMenuItemO(head, 0, "VIEW3D_OT_snap_selected_to_grid");
+ uiMenuItemO(head, 0, "VIEW3D_OT_snap_selected_to_cursor");
+ uiMenuItemO(head, 0, "VIEW3D_OT_snap_selected_to_center");
+ uiMenuSeparator(head);
+ uiMenuItemO(head, 0, "VIEW3D_OT_snap_cursor_to_selected");
+ uiMenuItemO(head, 0, "VIEW3D_OT_snap_cursor_to_grid");
+ uiMenuItemO(head, 0, "VIEW3D_OT_snap_cursor_to_active");
+
+ uiPupMenuEnd(C, head);
+
+ /* this operator is only for a menu, not used further */
+ return OPERATOR_CANCELLED;
+}
+
+/* only used as menu */
+void VIEW3D_OT_snap_menu(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Snap Menu";
+ ot->idname= "VIEW3D_OT_snap_menu";
+
+ /* api callbacks */
+ ot->invoke= snap_menu_invoke;
+
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= 0;
+}
+
+
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
new file mode 100644
index 00000000000..2aade74dcca
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -0,0 +1,1482 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <float.h>
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+
+#include "BKE_anim.h"
+#include "BKE_action.h"
+#include "BKE_context.h"
+#include "BKE_object.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "RE_pipeline.h" // make_stars
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "ED_armature.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "PIL_time.h" /* smoothview */
+
+#include "view3d_intern.h" // own include
+
+#define BL_NEAR_CLIP 0.001
+
+
+
+/* use this call when executing an operator,
+ event system doesn't set for each event the
+ opengl drawing context */
+void view3d_operator_needs_opengl(const bContext *C)
+{
+ ARegion *ar= CTX_wm_region(C);
+
+ /* for debugging purpose, context should always be OK */
+ if(ar->regiontype!=RGN_TYPE_WINDOW)
+ printf("view3d_operator_needs_opengl error, wrong region\n");
+ else {
+ RegionView3D *rv3d= ar->regiondata;
+
+ wmSubWindowSet(CTX_wm_window(C), ar->swinid);
+ glMatrixMode(GL_PROJECTION);
+ wmLoadMatrix(rv3d->winmat);
+ glMatrixMode(GL_MODELVIEW);
+ wmLoadMatrix(rv3d->viewmat);
+ }
+}
+
+float *give_cursor(Scene *scene, View3D *v3d)
+{
+ if(v3d && v3d->localview) return v3d->cursor;
+ else return scene->cursor;
+}
+
+
+/* Gets the lens and clipping values from a camera of lamp type object */
+static void object_lens_clip_settings(Object *ob, float *lens, float *clipsta, float *clipend)
+{
+ if (!ob) return;
+
+ if(ob->type==OB_LAMP ) {
+ Lamp *la = ob->data;
+ if (lens) {
+ float x1, fac;
+ fac= cos( M_PI*la->spotsize/360.0);
+ x1= saacos(fac);
+ *lens= 16.0*fac/sin(x1);
+ }
+ if (clipsta) *clipsta= la->clipsta;
+ if (clipend) *clipend= la->clipend;
+ }
+ else if(ob->type==OB_CAMERA) {
+ Camera *cam= ob->data;
+ if (lens) *lens= cam->lens;
+ if (clipsta) *clipsta= cam->clipsta;
+ if (clipend) *clipend= cam->clipend;
+ }
+ else {
+ if (lens) *lens= 35.0f;
+ }
+}
+
+
+/* Gets the view trasnformation from a camera
+* currently dosnt take camzoom into account
+*
+* The dist is not modified for this function, if NULL its assimed zero
+* */
+static void view_settings_from_ob(Object *ob, float *ofs, float *quat, float *dist, float *lens)
+{
+ float bmat[4][4];
+ float imat[4][4];
+ float tmat[3][3];
+
+ if (!ob) return;
+
+ /* Offset */
+ if (ofs) {
+ VECCOPY(ofs, ob->obmat[3]);
+ VecMulf(ofs, -1.0f); /*flip the vector*/
+ }
+
+ /* Quat */
+ if (quat) {
+ Mat4CpyMat4(bmat, ob->obmat);
+ Mat4Ortho(bmat);
+ Mat4Invert(imat, bmat);
+ Mat3CpyMat4(tmat, imat);
+ Mat3ToQuat(tmat, quat);
+ }
+
+ if (dist) {
+ float vec[3];
+ Mat3CpyMat4(tmat, ob->obmat);
+
+ vec[0]= vec[1] = 0.0;
+ vec[2]= -(*dist);
+ Mat3MulVecfl(tmat, vec);
+ VecSubf(ofs, ofs, vec);
+ }
+
+ /* Lens */
+ if (lens)
+ object_lens_clip_settings(ob, lens, NULL, NULL);
+}
+
+
+/* ****************** smooth view operator ****************** */
+
+struct SmoothViewStore {
+ float orig_dist, new_dist;
+ float orig_lens, new_lens;
+ float orig_quat[4], new_quat[4];
+ float orig_ofs[3], new_ofs[3];
+
+ int to_camera, orig_view;
+
+ double time_allowed;
+};
+
+/* will start timer if appropriate */
+/* the arguments are the desired situation */
+void smooth_view(bContext *C, Object *oldcamera, Object *camera, float *ofs, float *quat, float *dist, float *lens)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ struct SmoothViewStore sms;
+
+ /* initialize sms */
+ VECCOPY(sms.new_ofs, rv3d->ofs);
+ QUATCOPY(sms.new_quat, rv3d->viewquat);
+ sms.new_dist= rv3d->dist;
+ sms.new_lens= v3d->lens;
+ sms.to_camera= 0;
+
+ /* store the options we want to end with */
+ if(ofs) VECCOPY(sms.new_ofs, ofs);
+ if(quat) QUATCOPY(sms.new_quat, quat);
+ if(dist) sms.new_dist= *dist;
+ if(lens) sms.new_lens= *lens;
+
+ if (camera) {
+ view_settings_from_ob(camera, sms.new_ofs, sms.new_quat, &sms.new_dist, &sms.new_lens);
+ sms.to_camera= 1; /* restore view3d values in end */
+ }
+
+ if (C && U.smooth_viewtx) {
+ int changed = 0; /* zero means no difference */
+
+ if (sms.new_dist != rv3d->dist)
+ changed = 1;
+ if (sms.new_lens != v3d->lens)
+ changed = 1;
+
+ if ((sms.new_ofs[0]!=rv3d->ofs[0]) ||
+ (sms.new_ofs[1]!=rv3d->ofs[1]) ||
+ (sms.new_ofs[2]!=rv3d->ofs[2]) )
+ changed = 1;
+
+ if ((sms.new_quat[0]!=rv3d->viewquat[0]) ||
+ (sms.new_quat[1]!=rv3d->viewquat[1]) ||
+ (sms.new_quat[2]!=rv3d->viewquat[2]) ||
+ (sms.new_quat[3]!=rv3d->viewquat[3]) )
+ changed = 1;
+
+ /* The new view is different from the old one
+ * so animate the view */
+ if (changed) {
+
+ sms.time_allowed= (double)U.smooth_viewtx / 1000.0;
+
+ /* if this is view rotation only
+ * we can decrease the time allowed by
+ * the angle between quats
+ * this means small rotations wont lag */
+ if (quat && !ofs && !dist) {
+ float vec1[3], vec2[3];
+
+ VECCOPY(vec1, sms.new_quat);
+ VECCOPY(vec2, sms.orig_quat);
+ Normalize(vec1);
+ Normalize(vec2);
+ /* scale the time allowed by the rotation */
+ sms.time_allowed *= NormalizedVecAngle2(vec1, vec2)/(M_PI/2);
+ }
+
+ /* original values */
+ if (oldcamera) {
+ sms.orig_dist= rv3d->dist; // below function does weird stuff with it...
+ view_settings_from_ob(oldcamera, sms.orig_ofs, sms.orig_quat, &sms.orig_dist, &sms.orig_lens);
+ }
+ else {
+ VECCOPY(sms.orig_ofs, rv3d->ofs);
+ QUATCOPY(sms.orig_quat, rv3d->viewquat);
+ sms.orig_dist= rv3d->dist;
+ sms.orig_lens= v3d->lens;
+ }
+ /* grid draw as floor */
+ sms.orig_view= rv3d->view;
+ rv3d->view= 0;
+
+ /* ensure it shows correct */
+ if(sms.to_camera) rv3d->persp= V3D_PERSP;
+
+ /* keep track of running timer! */
+ if(rv3d->sms==NULL)
+ rv3d->sms= MEM_mallocN(sizeof(struct SmoothViewStore), "smoothview v3d");
+ *rv3d->sms= sms;
+ if(rv3d->smooth_timer)
+ WM_event_remove_window_timer(CTX_wm_window(C), rv3d->smooth_timer);
+ /* TIMER1 is hardcoded in keymap */
+ rv3d->smooth_timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER1, 1.0/30.0); /* max 30 frs/sec */
+
+ return;
+ }
+ }
+
+ /* if we get here nothing happens */
+ if(sms.to_camera==0) {
+ VECCOPY(rv3d->ofs, sms.new_ofs);
+ QUATCOPY(rv3d->viewquat, sms.new_quat);
+ rv3d->dist = sms.new_dist;
+ v3d->lens = sms.new_lens;
+ }
+ ED_region_tag_redraw(CTX_wm_region(C));
+}
+
+/* only meant for timer usage */
+static int view3d_smoothview_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ struct SmoothViewStore *sms= rv3d->sms;
+ double step, step_inv;
+
+ /* escape if not our timer */
+ if(rv3d->smooth_timer==NULL || rv3d->smooth_timer!=event->customdata)
+ return OPERATOR_PASS_THROUGH;
+
+ step = (rv3d->smooth_timer->duration)/sms->time_allowed;
+
+ /* end timer */
+ if(step >= 1.0f) {
+
+ /* if we went to camera, store the original */
+ if(sms->to_camera) {
+ rv3d->persp= V3D_CAMOB;
+ VECCOPY(rv3d->ofs, sms->orig_ofs);
+ QUATCOPY(rv3d->viewquat, sms->orig_quat);
+ rv3d->dist = sms->orig_dist;
+ v3d->lens = sms->orig_lens;
+ }
+ else {
+ VECCOPY(rv3d->ofs, sms->new_ofs);
+ QUATCOPY(rv3d->viewquat, sms->new_quat);
+ rv3d->dist = sms->new_dist;
+ v3d->lens = sms->new_lens;
+ }
+ rv3d->view= sms->orig_view;
+
+ MEM_freeN(rv3d->sms);
+ rv3d->sms= NULL;
+
+ WM_event_remove_window_timer(CTX_wm_window(C), rv3d->smooth_timer);
+ rv3d->smooth_timer= NULL;
+ }
+ else {
+ int i;
+
+ /* ease in/out */
+ if (step < 0.5) step = (float)pow(step*2, 2)/2;
+ else step = (float)1-(pow(2*(1-step),2)/2);
+
+ step_inv = 1.0-step;
+
+ for (i=0; i<3; i++)
+ rv3d->ofs[i] = sms->new_ofs[i]*step + sms->orig_ofs[i]*step_inv;
+
+ QuatInterpol(rv3d->viewquat, sms->orig_quat, sms->new_quat, step);
+
+ rv3d->dist = sms->new_dist*step + sms->orig_dist*step_inv;
+ v3d->lens = sms->new_lens*step + sms->orig_lens*step_inv;
+ }
+
+ ED_region_tag_redraw(CTX_wm_region(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_smoothview(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Smooth View";
+ ot->idname= "VIEW3D_OT_smoothview";
+
+ /* api callbacks */
+ ot->invoke= view3d_smoothview_invoke;
+
+ ot->poll= ED_operator_view3d_active;
+}
+
+static int view3d_setcameratoview_exec(bContext *C, wmOperator *op)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ Object *ob;
+ float dvec[3];
+
+ ob= v3d->camera;
+ dvec[0]= rv3d->dist*rv3d->viewinv[2][0];
+ dvec[1]= rv3d->dist*rv3d->viewinv[2][1];
+ dvec[2]= rv3d->dist*rv3d->viewinv[2][2];
+
+ VECCOPY(ob->loc, dvec);
+ VecSubf(ob->loc, ob->loc, v3d->ofs);
+ rv3d->viewquat[0]= -rv3d->viewquat[0];
+
+ QuatToEul(rv3d->viewquat, ob->rot);
+ rv3d->viewquat[0]= -rv3d->viewquat[0];
+
+ ob->recalc= OB_RECALC_OB;
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, CTX_data_scene(C));
+
+ return OPERATOR_FINISHED;
+
+}
+
+void VIEW3D_OT_setcameratoview(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Align Camera To View";
+ ot->idname= "VIEW3D_OT_camera_to_view";
+
+ /* api callbacks */
+ ot->exec= view3d_setcameratoview_exec;
+ ot->poll= ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ********************************** */
+
+/* create intersection coordinates in view Z direction at mouse coordinates */
+void viewline(ARegion *ar, View3D *v3d, short mval[2], float ray_start[3], float ray_end[3])
+{
+ RegionView3D *rv3d= ar->regiondata;
+ float vec[4];
+
+ if(rv3d->persp != V3D_ORTHO){
+ vec[0]= 2.0f * mval[0] / ar->winx - 1;
+ vec[1]= 2.0f * mval[1] / ar->winy - 1;
+ vec[2]= -1.0f;
+ vec[3]= 1.0f;
+
+ Mat4MulVec4fl(rv3d->persinv, vec);
+ VecMulf(vec, 1.0f / vec[3]);
+
+ VECCOPY(ray_start, rv3d->viewinv[3]);
+ VECSUB(vec, vec, ray_start);
+ Normalize(vec);
+
+ VECADDFAC(ray_start, rv3d->viewinv[3], vec, v3d->near);
+ VECADDFAC(ray_end, rv3d->viewinv[3], vec, v3d->far);
+ }
+ else {
+ vec[0] = 2.0f * mval[0] / ar->winx - 1;
+ vec[1] = 2.0f * mval[1] / ar->winy - 1;
+ vec[2] = 0.0f;
+ vec[3] = 1.0f;
+
+ Mat4MulVec4fl(rv3d->persinv, vec);
+
+ VECADDFAC(ray_start, vec, rv3d->viewinv[2], 1000.0f);
+ VECADDFAC(ray_end, vec, rv3d->viewinv[2], -1000.0f);
+ }
+}
+
+/* create intersection ray in view Z direction at mouse coordinates */
+void viewray(ARegion *ar, View3D *v3d, short mval[2], float ray_start[3], float ray_normal[3])
+{
+ float ray_end[3];
+
+ viewline(ar, v3d, mval, ray_start, ray_end);
+ VecSubf(ray_normal, ray_end, ray_start);
+ Normalize(ray_normal);
+}
+
+
+void initgrabz(RegionView3D *rv3d, float x, float y, float z)
+{
+ if(rv3d==NULL) return;
+ rv3d->zfac= rv3d->persmat[0][3]*x+ rv3d->persmat[1][3]*y+ rv3d->persmat[2][3]*z+ rv3d->persmat[3][3];
+
+ /* if x,y,z is exactly the viewport offset, zfac is 0 and we don't want that
+ * (accounting for near zero values)
+ * */
+ if (rv3d->zfac < 1.e-6f && rv3d->zfac > -1.e-6f) rv3d->zfac = 1.0f;
+
+ /* Negative zfac means x, y, z was behind the camera (in perspective).
+ * This gives flipped directions, so revert back to ok default case.
+ */
+ if (rv3d->zfac < 0.0f) rv3d->zfac = 1.0f;
+}
+
+/* always call initgrabz */
+void window_to_3d(ARegion *ar, float *vec, short mx, short my)
+{
+ RegionView3D *rv3d= ar->regiondata;
+
+ float dx= ((float)(mx-(ar->winx/2)))*rv3d->zfac/(ar->winx/2);
+ float dy= ((float)(my-(ar->winy/2)))*rv3d->zfac/(ar->winy/2);
+
+ float fz= rv3d->persmat[0][3]*vec[0]+ rv3d->persmat[1][3]*vec[1]+ rv3d->persmat[2][3]*vec[2]+ rv3d->persmat[3][3];
+ fz= fz/rv3d->zfac;
+
+ vec[0]= (rv3d->persinv[0][0]*dx + rv3d->persinv[1][0]*dy+ rv3d->persinv[2][0]*fz)-rv3d->ofs[0];
+ vec[1]= (rv3d->persinv[0][1]*dx + rv3d->persinv[1][1]*dy+ rv3d->persinv[2][1]*fz)-rv3d->ofs[1];
+ vec[2]= (rv3d->persinv[0][2]*dx + rv3d->persinv[1][2]*dy+ rv3d->persinv[2][2]*fz)-rv3d->ofs[2];
+
+}
+
+/* always call initgrabz */
+/* only to detect delta motion */
+void window_to_3d_delta(ARegion *ar, float *vec, short mx, short my)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ float dx, dy;
+
+ dx= 2.0f*mx*rv3d->zfac/ar->winx;
+ dy= 2.0f*my*rv3d->zfac/ar->winy;
+
+ vec[0]= (rv3d->persinv[0][0]*dx + rv3d->persinv[1][0]*dy);
+ vec[1]= (rv3d->persinv[0][1]*dx + rv3d->persinv[1][1]*dy);
+ vec[2]= (rv3d->persinv[0][2]*dx + rv3d->persinv[1][2]*dy);
+}
+
+float read_cached_depth(ViewContext *vc, int x, int y)
+{
+ ViewDepths *vd = vc->rv3d->depths;
+
+ x -= vc->ar->winrct.xmin;
+ y -= vc->ar->winrct.ymin;
+
+ if(vd && vd->depths && x > 0 && y > 0 && x < vd->w && y < vd->h)
+ return vd->depths[y * vd->w + x];
+ else
+ return 1;
+}
+
+void request_depth_update(RegionView3D *rv3d)
+{
+ if(rv3d->depths)
+ rv3d->depths->damaged= 1;
+}
+
+void view3d_get_object_project_mat(RegionView3D *rv3d, Object *ob, float pmat[4][4], float vmat[4][4])
+{
+ Mat4MulMat4(vmat, ob->obmat, rv3d->viewmat);
+ Mat4MulMat4(pmat, vmat, rv3d->winmat);
+ Mat4CpyMat4(vmat, ob->obmat);
+}
+
+/* projectmat brings it to window coords, wmat to rotated world space */
+void view3d_project_short_clip(ARegion *ar, float *vec, short *adr, float projmat[4][4], float wmat[4][4])
+{
+ RegionView3D *rv3d= ar->regiondata;
+ float fx, fy, vec4[4];
+
+ adr[0]= IS_CLIPPED;
+
+ /* clipplanes in eye space */
+ if(rv3d->rflag & RV3D_CLIPPING) {
+ VECCOPY(vec4, vec);
+ Mat4MulVecfl(wmat, vec4);
+ if(view3d_test_clipping(rv3d, vec4))
+ return;
+ }
+
+ VECCOPY(vec4, vec);
+ vec4[3]= 1.0;
+
+ Mat4MulVec4fl(projmat, vec4);
+
+ /* clipplanes in window space */
+ if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */
+ fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
+
+ if( fx>0 && fx<ar->winx) {
+
+ fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
+
+ if(fy>0.0 && fy< (float)ar->winy) {
+ adr[0]= (short)floor(fx);
+ adr[1]= (short)floor(fy);
+ }
+ }
+ }
+}
+
+void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr, float mat[4][4])
+{
+ float fx, fy, vec4[4];
+
+ adr[0]= IS_CLIPPED;
+
+ VECCOPY(vec4, vec);
+ vec4[3]= 1.0;
+
+ Mat4MulVec4fl(mat, vec4);
+
+ if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */
+ fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
+
+ if( fx>-32700 && fx<32700) {
+
+ fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
+
+ if(fy>-32700.0 && fy<32700.0) {
+ adr[0]= (short)floor(fx);
+ adr[1]= (short)floor(fy);
+ }
+ }
+ }
+}
+
+void view3d_project_float(ARegion *ar, float *vec, float *adr, float mat[4][4])
+{
+ float vec4[4];
+
+ adr[0]= IS_CLIPPED;
+ VECCOPY(vec4, vec);
+ vec4[3]= 1.0;
+
+ Mat4MulVec4fl(mat, vec4);
+
+ if( vec4[3]>FLT_EPSILON ) {
+ adr[0] = (float)(ar->winx/2.0f)+(ar->winx/2.0f)*vec4[0]/vec4[3];
+ adr[1] = (float)(ar->winy/2.0f)+(ar->winy/2.0f)*vec4[1]/vec4[3];
+ } else {
+ adr[0] = adr[1] = 0.0f;
+ }
+}
+
+int boundbox_clip(RegionView3D *rv3d, float obmat[][4], BoundBox *bb)
+{
+ /* return 1: draw */
+
+ float mat[4][4];
+ float vec[4], min, max;
+ int a, flag= -1, fl;
+
+ if(bb==NULL) return 1;
+ if(bb->flag & OB_BB_DISABLED) return 1;
+
+ Mat4MulMat4(mat, obmat, rv3d->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 project_short(ARegion *ar, float *vec, short *adr) /* clips */
+{
+ RegionView3D *rv3d= ar->regiondata;
+ float fx, fy, vec4[4];
+
+ adr[0]= IS_CLIPPED;
+
+ if(rv3d->rflag & RV3D_CLIPPING) {
+ if(view3d_test_clipping(rv3d, vec))
+ return;
+ }
+
+ VECCOPY(vec4, vec);
+ vec4[3]= 1.0;
+ Mat4MulVec4fl(rv3d->persmat, vec4);
+
+ if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */
+ fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
+
+ if( fx>0 && fx<ar->winx) {
+
+ fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
+
+ if(fy>0.0 && fy< (float)ar->winy) {
+ adr[0]= (short)floor(fx);
+ adr[1]= (short)floor(fy);
+ }
+ }
+ }
+}
+
+void project_int(ARegion *ar, float *vec, int *adr)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ float fx, fy, vec4[4];
+
+ adr[0]= (int)2140000000.0f;
+ VECCOPY(vec4, vec);
+ vec4[3]= 1.0;
+
+ Mat4MulVec4fl(rv3d->persmat, vec4);
+
+ if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */
+ fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
+
+ if( fx>-2140000000.0f && fx<2140000000.0f) {
+ fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
+
+ if(fy>-2140000000.0f && fy<2140000000.0f) {
+ adr[0]= (int)floor(fx);
+ adr[1]= (int)floor(fy);
+ }
+ }
+ }
+}
+
+void project_int_noclip(ARegion *ar, float *vec, int *adr)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ float fx, fy, vec4[4];
+
+ VECCOPY(vec4, vec);
+ vec4[3]= 1.0;
+
+ Mat4MulVec4fl(rv3d->persmat, vec4);
+
+ if( fabs(vec4[3]) > BL_NEAR_CLIP ) {
+ fx = (ar->winx/2)*(1 + vec4[0]/vec4[3]);
+ fy = (ar->winy/2)*(1 + vec4[1]/vec4[3]);
+
+ adr[0] = (int)floor(fx);
+ adr[1] = (int)floor(fy);
+ }
+ else
+ {
+ adr[0] = ar->winx / 2;
+ adr[1] = ar->winy / 2;
+ }
+}
+
+void project_short_noclip(ARegion *ar, float *vec, short *adr)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ float fx, fy, vec4[4];
+
+ adr[0]= IS_CLIPPED;
+ VECCOPY(vec4, vec);
+ vec4[3]= 1.0;
+
+ Mat4MulVec4fl(rv3d->persmat, vec4);
+
+ if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */
+ fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
+
+ if( fx>-32700 && fx<32700) {
+
+ fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
+
+ if(fy>-32700.0 && fy<32700.0) {
+ adr[0]= (short)floor(fx);
+ adr[1]= (short)floor(fy);
+ }
+ }
+ }
+}
+
+void project_float(ARegion *ar, float *vec, float *adr)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ float vec4[4];
+
+ adr[0]= IS_CLIPPED;
+ VECCOPY(vec4, vec);
+ vec4[3]= 1.0;
+
+ Mat4MulVec4fl(rv3d->persmat, vec4);
+
+ if( vec4[3]>BL_NEAR_CLIP ) {
+ adr[0] = (float)(ar->winx/2.0)+(ar->winx/2.0)*vec4[0]/vec4[3];
+ adr[1] = (float)(ar->winy/2.0)+(ar->winy/2.0)*vec4[1]/vec4[3];
+ }
+}
+
+void project_float_noclip(ARegion *ar, float *vec, float *adr)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ float vec4[4];
+
+ VECCOPY(vec4, vec);
+ vec4[3]= 1.0;
+
+ Mat4MulVec4fl(rv3d->persmat, vec4);
+
+ if( fabs(vec4[3]) > BL_NEAR_CLIP ) {
+ adr[0] = (float)(ar->winx/2.0)+(ar->winx/2.0)*vec4[0]/vec4[3];
+ adr[1] = (float)(ar->winy/2.0)+(ar->winy/2.0)*vec4[1]/vec4[3];
+ }
+ else
+ {
+ adr[0] = ar->winx / 2.0f;
+ adr[1] = ar->winy / 2.0f;
+ }
+}
+
+int get_view3d_ortho(View3D *v3d, RegionView3D *rv3d)
+{
+ Camera *cam;
+
+ if(rv3d->persp==V3D_CAMOB) {
+ if(v3d->camera && v3d->camera->type==OB_CAMERA) {
+ cam= v3d->camera->data;
+
+ if(cam && cam->type==CAM_ORTHO)
+ return 1;
+ else
+ return 0;
+ }
+ else
+ return 0;
+ }
+
+ if(rv3d->persp==V3D_ORTHO)
+ return 1;
+
+ return 0;
+}
+
+/* also exposed in previewrender.c */
+int get_view3d_viewplane(View3D *v3d, RegionView3D *rv3d, int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize)
+{
+ Camera *cam=NULL;
+ float lens, fac, x1, y1, x2, y2;
+ float winx= (float)winxi, winy= (float)winyi;
+ int orth= 0;
+
+ lens= v3d->lens;
+
+ *clipsta= v3d->near;
+ *clipend= v3d->far;
+
+ if(rv3d->persp==V3D_CAMOB) {
+ if(v3d->camera) {
+ if(v3d->camera->type==OB_LAMP ) {
+ Lamp *la;
+
+ la= v3d->camera->data;
+ fac= cos( M_PI*la->spotsize/360.0);
+
+ x1= saacos(fac);
+ lens= 16.0*fac/sin(x1);
+
+ *clipsta= la->clipsta;
+ *clipend= la->clipend;
+ }
+ else if(v3d->camera->type==OB_CAMERA) {
+ cam= v3d->camera->data;
+ lens= cam->lens;
+ *clipsta= cam->clipsta;
+ *clipend= cam->clipend;
+ }
+ }
+ }
+
+ if(rv3d->persp==V3D_ORTHO) {
+ if(winx>winy) x1= -rv3d->dist;
+ else x1= -winx*rv3d->dist/winy;
+ x2= -x1;
+
+ if(winx>winy) y1= -winy*rv3d->dist/winx;
+ else y1= -rv3d->dist;
+ y2= -y1;
+
+ *clipend *= 0.5; // otherwise too extreme low zbuffer quality
+ *clipsta= - *clipend;
+ orth= 1;
+ }
+ else {
+ /* fac for zoom, also used for camdx */
+ if(rv3d->persp==V3D_CAMOB) {
+ fac= (1.41421+( (float)rv3d->camzoom )/50.0);
+ fac*= fac;
+ }
+ else fac= 2.0;
+
+ /* viewplane size depends... */
+ if(cam && cam->type==CAM_ORTHO) {
+ /* ortho_scale == 1 means exact 1 to 1 mapping */
+ float dfac= 2.0*cam->ortho_scale/fac;
+
+ if(winx>winy) x1= -dfac;
+ else x1= -winx*dfac/winy;
+ x2= -x1;
+
+ if(winx>winy) y1= -winy*dfac/winx;
+ else y1= -dfac;
+ y2= -y1;
+ orth= 1;
+ }
+ else {
+ float dfac;
+
+ if(winx>winy) dfac= 64.0/(fac*winx*lens);
+ else dfac= 64.0/(fac*winy*lens);
+
+ x1= - *clipsta * winx*dfac;
+ x2= -x1;
+ y1= - *clipsta * winy*dfac;
+ y2= -y1;
+ orth= 0;
+ }
+ /* cam view offset */
+ if(cam) {
+ float dx= 0.5*fac*rv3d->camdx*(x2-x1);
+ float dy= 0.5*fac*rv3d->camdy*(y2-y1);
+ x1+= dx;
+ x2+= dx;
+ y1+= dy;
+ y2+= dy;
+ }
+ }
+
+ if(pixsize) {
+ float viewfac;
+
+ if(orth) {
+ viewfac= (winx >= winy)? winx: winy;
+ *pixsize= 1.0f/viewfac;
+ }
+ else {
+ viewfac= (((winx >= winy)? winx: winy)*lens)/32.0;
+ *pixsize= *clipsta/viewfac;
+ }
+ }
+
+ viewplane->xmin= x1;
+ viewplane->ymin= y1;
+ viewplane->xmax= x2;
+ viewplane->ymax= y2;
+
+ return orth;
+}
+
+void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect) /* rect: for picking */
+{
+ RegionView3D *rv3d= ar->regiondata;
+ rctf viewplane;
+ float clipsta, clipend, x1, y1, x2, y2;
+ int orth;
+
+ orth= get_view3d_viewplane(v3d, rv3d, ar->winx, ar->winy, &viewplane, &clipsta, &clipend, NULL);
+ // printf("%d %d %f %f %f %f %f %f\n", winx, winy, viewplane.xmin, viewplane.ymin, viewplane.xmax, viewplane.ymax, clipsta, clipend);
+ x1= viewplane.xmin;
+ y1= viewplane.ymin;
+ x2= viewplane.xmax;
+ y2= viewplane.ymax;
+
+ if(rect) { /* picking */
+ rect->xmin/= (float)ar->winx;
+ rect->xmin= x1+rect->xmin*(x2-x1);
+ rect->ymin/= (float)ar->winy;
+ rect->ymin= y1+rect->ymin*(y2-y1);
+ rect->xmax/= (float)ar->winx;
+ rect->xmax= x1+rect->xmax*(x2-x1);
+ rect->ymax/= (float)ar->winy;
+ rect->ymax= y1+rect->ymax*(y2-y1);
+
+ if(orth) wmOrtho(rect->xmin, rect->xmax, rect->ymin, rect->ymax, -clipend, clipend);
+ else wmFrustum(rect->xmin, rect->xmax, rect->ymin, rect->ymax, clipsta, clipend);
+
+ }
+ else {
+ if(orth) wmOrtho(x1, x2, y1, y2, clipsta, clipend);
+ else wmFrustum(x1, x2, y1, y2, clipsta, clipend);
+ }
+
+ /* not sure what this was for? (ton) */
+ glMatrixMode(GL_PROJECTION);
+ wmGetMatrix(rv3d->winmat);
+ glMatrixMode(GL_MODELVIEW);
+}
+
+
+static void obmat_to_viewmat(View3D *v3d, RegionView3D *rv3d, Object *ob, short smooth)
+{
+ float bmat[4][4];
+ float tmat[3][3];
+
+ rv3d->view= 0; /* dont show the grid */
+
+ Mat4CpyMat4(bmat, ob->obmat);
+ Mat4Ortho(bmat);
+ Mat4Invert(rv3d->viewmat, bmat);
+
+ /* view quat calculation, needed for add object */
+ Mat3CpyMat4(tmat, rv3d->viewmat);
+ if (smooth) {
+ float new_quat[4];
+ if (rv3d->persp==V3D_CAMOB && v3d->camera) {
+ /* were from a camera view */
+
+ float orig_ofs[3];
+ float orig_dist= rv3d->dist;
+ float orig_lens= v3d->lens;
+ VECCOPY(orig_ofs, rv3d->ofs);
+
+ /* Switch from camera view */
+ Mat3ToQuat(tmat, new_quat);
+
+ rv3d->persp=V3D_PERSP;
+ rv3d->dist= 0.0;
+
+ view_settings_from_ob(v3d->camera, rv3d->ofs, NULL, NULL, &v3d->lens);
+ smooth_view(NULL, NULL, NULL, orig_ofs, new_quat, &orig_dist, &orig_lens); // XXX
+
+ rv3d->persp=V3D_CAMOB; /* just to be polite, not needed */
+
+ } else {
+ Mat3ToQuat(tmat, new_quat);
+ smooth_view(NULL, NULL, NULL, NULL, new_quat, NULL, NULL); // XXX
+ }
+ } else {
+ Mat3ToQuat(tmat, rv3d->viewquat);
+ }
+}
+
+#define QUATSET(a, b, c, d, e) a[0]=b; a[1]=c; a[2]=d; a[3]=e;
+
+static void view3d_viewlock(RegionView3D *rv3d)
+{
+ switch(rv3d->view) {
+ case V3D_VIEW_BOTTOM :
+ QUATSET(rv3d->viewquat,0.0, -1.0, 0.0, 0.0);
+ break;
+
+ case V3D_VIEW_BACK:
+ QUATSET(rv3d->viewquat,0.0, 0.0, (float)-cos(M_PI/4.0), (float)-cos(M_PI/4.0));
+ break;
+
+ case V3D_VIEW_LEFT:
+ QUATSET(rv3d->viewquat,0.5, -0.5, 0.5, 0.5);
+ break;
+
+ case V3D_VIEW_TOP:
+ QUATSET(rv3d->viewquat,1.0, 0.0, 0.0, 0.0);
+ break;
+
+ case V3D_VIEW_FRONT:
+ QUATSET(rv3d->viewquat,(float)cos(M_PI/4.0), (float)-sin(M_PI/4.0), 0.0, 0.0);
+ break;
+
+ case V3D_VIEW_RIGHT:
+ QUATSET(rv3d->viewquat, 0.5, -0.5, -0.5, -0.5);
+ break;
+ }
+}
+
+/* dont set windows active in in here, is used by renderwin too */
+void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d)
+{
+ if(rv3d->persp==V3D_CAMOB) { /* obs/camera */
+ if(v3d->camera) {
+ where_is_object(scene, v3d->camera);
+ obmat_to_viewmat(v3d, rv3d, v3d->camera, 0);
+ }
+ else {
+ QuatToMat4(rv3d->viewquat, rv3d->viewmat);
+ rv3d->viewmat[3][2]-= rv3d->dist;
+ }
+ }
+ else {
+ /* should be moved to better initialize later on XXX */
+ if(rv3d->viewlock)
+ view3d_viewlock(rv3d);
+
+ QuatToMat4(rv3d->viewquat, rv3d->viewmat);
+ if(rv3d->persp==V3D_PERSP) rv3d->viewmat[3][2]-= rv3d->dist;
+ if(v3d->ob_centre) {
+ Object *ob= v3d->ob_centre;
+ float vec[3];
+
+ VECCOPY(vec, ob->obmat[3]);
+ if(ob->type==OB_ARMATURE && v3d->ob_centre_bone[0]) {
+ bPoseChannel *pchan= get_pose_channel(ob->pose, v3d->ob_centre_bone);
+ if(pchan) {
+ VECCOPY(vec, pchan->pose_mat[3]);
+ Mat4MulVecfl(ob->obmat, vec);
+ }
+ }
+ i_translate(-vec[0], -vec[1], -vec[2], rv3d->viewmat);
+ }
+ else i_translate(rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2], rv3d->viewmat);
+ }
+}
+
+/* IGLuint-> GLuint*/
+/* Warning: be sure to account for a negative return value
+* This is an error, "Too many objects in select buffer"
+* and no action should be taken (can crash blender) if this happens
+*/
+short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int bufsize, rcti *input)
+{
+ Scene *scene= vc->scene;
+ View3D *v3d= vc->v3d;
+ ARegion *ar= vc->ar;
+ rctf rect;
+ short code, hits;
+
+ G.f |= G_PICKSEL;
+
+ /* case not a border select */
+ if(input->xmin==input->xmax) {
+ rect.xmin= input->xmin-12; // seems to be default value for bones only now
+ rect.xmax= input->xmin+12;
+ rect.ymin= input->ymin-12;
+ rect.ymax= input->ymin+12;
+ }
+ else {
+ rect.xmin= input->xmin;
+ rect.xmax= input->xmax;
+ rect.ymin= input->ymin;
+ rect.ymax= input->ymax;
+ }
+
+ setwinmatrixview3d(ar, v3d, &rect);
+ Mat4MulMat4(vc->rv3d->persmat, vc->rv3d->viewmat, vc->rv3d->winmat);
+
+ if(v3d->drawtype > OB_WIRE) {
+ v3d->zbuf= TRUE;
+ glEnable(GL_DEPTH_TEST);
+ }
+
+ if(vc->rv3d->rflag & RV3D_CLIPPING)
+ view3d_set_clipping(vc->rv3d);
+
+ glSelectBuffer( bufsize, (GLuint *)buffer);
+ glRenderMode(GL_SELECT);
+ glInitNames(); /* these two calls whatfor? It doesnt work otherwise */
+ glPushName(-1);
+ code= 1;
+
+ if(vc->obedit && vc->obedit->type==OB_MBALL) {
+ draw_object(scene, ar, v3d, BASACT, DRAW_PICKING|DRAW_CONSTCOLOR);
+ }
+ else if((vc->obedit && vc->obedit->type==OB_ARMATURE)) {
+ /* if not drawing sketch, draw bones */
+ if(!BDR_drawSketchNames(vc)) {
+ draw_object(scene, ar, v3d, BASACT, DRAW_PICKING|DRAW_CONSTCOLOR);
+ }
+ }
+ else {
+ Base *base;
+
+ v3d->xray= TRUE; // otherwise it postpones drawing
+ for(base= scene->base.first; base; base= base->next) {
+ if(base->lay & v3d->lay) {
+
+ if (base->object->restrictflag & OB_RESTRICT_SELECT)
+ base->selcol= 0;
+ else {
+ base->selcol= code;
+ glLoadName(code);
+ draw_object(scene, ar, v3d, base, DRAW_PICKING|DRAW_CONSTCOLOR);
+
+ /* we draw group-duplicators for selection too */
+ if((base->object->transflag & OB_DUPLI) && base->object->dup_group) {
+ ListBase *lb;
+ DupliObject *dob;
+ Base tbase;
+
+ tbase.flag= OB_FROMDUPLI;
+ lb= object_duplilist(scene, base->object);
+
+ for(dob= lb->first; dob; dob= dob->next) {
+ tbase.object= dob->ob;
+ Mat4CpyMat4(dob->ob->obmat, dob->mat);
+
+ draw_object(scene, ar, v3d, &tbase, DRAW_PICKING|DRAW_CONSTCOLOR);
+
+ Mat4CpyMat4(dob->ob->obmat, dob->omat);
+ }
+ free_object_duplilist(lb);
+ }
+ code++;
+ }
+ }
+ }
+ v3d->xray= FALSE; // restore
+ }
+
+ glPopName(); /* see above (pushname) */
+ hits= glRenderMode(GL_RENDER);
+
+ G.f &= ~G_PICKSEL;
+ setwinmatrixview3d(ar, v3d, NULL);
+ Mat4MulMat4(vc->rv3d->persmat, vc->rv3d->viewmat, vc->rv3d->winmat);
+
+ if(v3d->drawtype > OB_WIRE) {
+ v3d->zbuf= 0;
+ glDisable(GL_DEPTH_TEST);
+ }
+// XXX persp(PERSP_WIN);
+
+ if(vc->rv3d->rflag & RV3D_CLIPPING)
+ view3d_clr_clipping();
+
+ if(hits<0) printf("Too many objects in select buffer\n"); // XXX make error message
+
+ return hits;
+}
+
+/* ********************** local view operator ******************** */
+
+static unsigned int free_localbit(void)
+{
+ unsigned int lay;
+ ScrArea *sa;
+ bScreen *sc;
+
+ lay= 0;
+
+ /* sometimes we loose a localview: when an area is closed */
+ /* check all areas: which localviews are in use? */
+ for(sc= G.main->screen.first; sc; sc= sc->id.next) {
+ for(sa= sc->areabase.first; sa; sa= sa->next) {
+ SpaceLink *sl= sa->spacedata.first;
+ for(; sl; sl= sl->next) {
+ if(sl->spacetype==SPACE_VIEW3D) {
+ View3D *v3d= (View3D*) sl;
+ lay |= v3d->lay;
+ }
+ }
+ }
+ }
+
+ 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;
+}
+
+
+static void initlocalview(Scene *scene, ScrArea *sa)
+{
+ View3D *v3d= sa->spacedata.first;
+ Base *base;
+ float size = 0.0, min[3], max[3], box[3];
+ unsigned int locallay;
+ int ok=0;
+
+ if(v3d->localvd) return;
+
+ INIT_MINMAX(min, max);
+
+ locallay= free_localbit();
+
+ if(locallay==0) {
+ printf("Sorry, no more than 8 localviews\n"); // XXX error
+ ok= 0;
+ }
+ else {
+ if(scene->obedit) {
+ minmax_object(scene->obedit, min, max);
+
+ ok= 1;
+
+ BASACT->lay |= locallay;
+ scene->obedit->lay= BASACT->lay;
+ }
+ else {
+ for(base= FIRSTBASE; base; base= base->next) {
+ if(TESTBASE(v3d, base)) {
+ minmax_object(base->object, min, max);
+ base->lay |= locallay;
+ base->object->lay= base->lay;
+ ok= 1;
+ }
+ }
+ }
+
+ box[0]= (max[0]-min[0]);
+ box[1]= (max[1]-min[1]);
+ box[2]= (max[2]-min[2]);
+ size= MAX3(box[0], box[1], box[2]);
+ if(size<=0.01) size= 0.01;
+ }
+
+ if(ok) {
+ ARegion *ar;
+
+ v3d->localvd= MEM_mallocN(sizeof(View3D), "localview");
+
+ memcpy(v3d->localvd, v3d, sizeof(View3D));
+
+ for(ar= sa->regionbase.first; ar; ar= ar->next) {
+ if(ar->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d= ar->regiondata;
+
+ rv3d->localvd= MEM_mallocN(sizeof(RegionView3D), "localview region");
+ memcpy(rv3d->localvd, rv3d, sizeof(RegionView3D));
+
+ rv3d->ofs[0]= -(min[0]+max[0])/2.0;
+ rv3d->ofs[1]= -(min[1]+max[1])/2.0;
+ rv3d->ofs[2]= -(min[2]+max[2])/2.0;
+
+ rv3d->dist= size;
+ /* perspective should be a bit farther away to look nice */
+ if(rv3d->persp==V3D_ORTHO)
+ rv3d->dist*= 0.7;
+
+ // correction for window aspect ratio
+ if(ar->winy>2 && ar->winx>2) {
+ float asp= (float)ar->winx/(float)ar->winy;
+ if(asp<1.0) asp= 1.0/asp;
+ rv3d->dist*= asp;
+ }
+
+ if (rv3d->persp==V3D_CAMOB) rv3d->persp= V3D_PERSP;
+
+ v3d->cursor[0]= -rv3d->ofs[0];
+ v3d->cursor[1]= -rv3d->ofs[1];
+ v3d->cursor[2]= -rv3d->ofs[2];
+ }
+ }
+ if (v3d->near> 0.1) v3d->near= 0.1;
+
+ v3d->lay= locallay;
+ }
+ else {
+ /* clear flags */
+ for(base= FIRSTBASE; base; base= base->next) {
+ if( base->lay & locallay ) {
+ base->lay-= locallay;
+ if(base->lay==0) base->lay= v3d->layact;
+ if(base->object != scene->obedit) base->flag |= SELECT;
+ base->object->lay= base->lay;
+ }
+ }
+ v3d->localview= 0;
+ }
+
+}
+
+static void restore_localviewdata(ScrArea *sa, int free)
+{
+ ARegion *ar;
+ View3D *v3d= sa->spacedata.first;
+
+ if(v3d->localvd==NULL) return;
+
+ v3d->near= v3d->localvd->near;
+ v3d->far= v3d->localvd->far;
+ v3d->lay= v3d->localvd->lay;
+ v3d->layact= v3d->localvd->layact;
+ v3d->drawtype= v3d->localvd->drawtype;
+ v3d->camera= v3d->localvd->camera;
+
+ if(free) {
+ MEM_freeN(v3d->localvd);
+ v3d->localvd= NULL;
+ v3d->localview= 0;
+ }
+
+ for(ar= sa->regionbase.first; ar; ar= ar->next) {
+ if(ar->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d= ar->regiondata;
+
+ if(rv3d->localvd) {
+ rv3d->dist= rv3d->localvd->dist;
+ VECCOPY(rv3d->ofs, rv3d->localvd->ofs);
+ QUATCOPY(rv3d->viewquat, rv3d->localvd->viewquat);
+ rv3d->view= rv3d->localvd->view;
+ rv3d->persp= rv3d->localvd->persp;
+ rv3d->camzoom= rv3d->localvd->camzoom;
+
+ if(free) {
+ MEM_freeN(rv3d->localvd);
+ rv3d->localvd= NULL;
+ }
+ }
+ }
+ }
+}
+
+static void endlocalview(Scene *scene, ScrArea *sa)
+{
+ View3D *v3d= sa->spacedata.first;
+ struct Base *base;
+ unsigned int locallay;
+
+ if(v3d->localvd) {
+
+ locallay= v3d->lay & 0xFF000000;
+
+ restore_localviewdata(sa, 1); // 1 = free
+
+ /* for when in other window the layers have changed */
+ if(v3d->scenelock) v3d->lay= scene->lay;
+
+ for(base= FIRSTBASE; base; base= base->next) {
+ if( base->lay & locallay ) {
+ base->lay-= locallay;
+ if(base->lay==0) base->lay= v3d->layact;
+ if(base->object != scene->obedit) {
+ base->flag |= SELECT;
+ base->object->flag |= SELECT;
+ }
+ base->object->lay= base->lay;
+ }
+ }
+ }
+}
+
+static int localview_exec(bContext *C, wmOperator *unused)
+{
+ View3D *v3d= CTX_wm_view3d(C);
+
+ if(v3d->localvd)
+ endlocalview(CTX_data_scene(C), CTX_wm_area(C));
+ else
+ initlocalview(CTX_data_scene(C), CTX_wm_area(C));
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_localview(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Local View";
+ ot->idname= "VIEW3D_OT_localview";
+
+ /* api callbacks */
+ ot->exec= localview_exec;
+
+ ot->poll= ED_operator_view3d_active;
+}
+
+/* ************************************** */
+
+void view3d_align_axis_to_vector(View3D *v3d, RegionView3D *rv3d, int axisidx, float vec[3])
+{
+ float alignaxis[3] = {0.0, 0.0, 0.0};
+ float norm[3], axis[3], angle, new_quat[4];
+
+ if(axisidx > 0) alignaxis[axisidx-1]= 1.0;
+ else alignaxis[-axisidx-1]= -1.0;
+
+ VECCOPY(norm, vec);
+ Normalize(norm);
+
+ angle= (float)acos(Inpf(alignaxis, norm));
+ Crossf(axis, alignaxis, norm);
+ VecRotToQuat(axis, -angle, new_quat);
+
+ rv3d->view= 0;
+
+ if (rv3d->persp==V3D_CAMOB && v3d->camera) {
+ /* switch out of camera view */
+ float orig_ofs[3];
+ float orig_dist= rv3d->dist;
+ float orig_lens= v3d->lens;
+
+ VECCOPY(orig_ofs, rv3d->ofs);
+ rv3d->persp= V3D_PERSP;
+ rv3d->dist= 0.0;
+ view_settings_from_ob(v3d->camera, rv3d->ofs, NULL, NULL, &v3d->lens);
+ smooth_view(NULL, NULL, NULL, orig_ofs, new_quat, &orig_dist, &orig_lens); // XXX
+ } else {
+ if (rv3d->persp==V3D_CAMOB) rv3d->persp= V3D_PERSP; /* switch out of camera mode */
+ smooth_view(NULL, NULL, NULL, NULL, new_quat, NULL, NULL); // XXX
+ }
+}
+
diff --git a/source/blender/editors/transform/Makefile b/source/blender/editors/transform/Makefile
new file mode 100644
index 00000000000..36758190b52
--- /dev/null
+++ b/source/blender/editors/transform/Makefile
@@ -0,0 +1,54 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_transform
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+CPPFLAGS += -I$(NAN_BMFONT)/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/transform/SConscript b/source/blender/editors/transform/SConscript
new file mode 100644
index 00000000000..2c44204afa9
--- /dev/null
+++ b/source/blender/editors/transform/SConscript
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' ../../render/extern/include #/intern/guardedalloc #intern/bmfont'
+incs += ' ../../gpu ../../makesrna'
+
+env.BlenderLib ( 'bf_editors_transform', sources, Split(incs), [], libtype=['core'], priority=[40] ) \ No newline at end of file
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
new file mode 100644
index 00000000000..d588a73789c
--- /dev/null
+++ b/source/blender/editors/transform/transform.c
@@ -0,0 +1,4680 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_action_types.h" /* for some special action-editor settings */
+#include "DNA_constraint_types.h"
+#include "DNA_ipo_types.h" /* some silly ipo flag */
+#include "DNA_listBase.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h" /* PET modes */
+#include "DNA_screen_types.h" /* area dimensions */
+#include "DNA_texture_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_space_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_access.h"
+
+//#include "BIF_editview.h" /* arrows_move_cursor */
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+//#include "BIF_mywindow.h"
+//#include "BIF_resources.h"
+//#include "BIF_screen.h"
+//#include "BIF_space.h" /* undo */
+//#include "BIF_toets.h" /* persptoetsen */
+//#include "BIF_mywindow.h" /* warp_pointer */
+//#include "BIF_toolbox.h" /* notice */
+//#include "BIF_editmesh.h"
+//#include "BIF_editsima.h"
+//#include "BIF_editparticle.h"
+//#include "BIF_editaction.h"
+
+#include "BKE_action.h" /* get_action_frame */
+//#include "BKE_bad_level_calls.h"/* popmenu and error */
+#include "BKE_bmesh.h"
+#include "BKE_context.h"
+#include "BKE_constraint.h"
+#include "BKE_global.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_utildefines.h"
+#include "BKE_context.h"
+
+//#include "BSE_drawipo.h"
+//#include "BSE_editnla_types.h" /* for NLAWIDTH */
+//#include "BSE_editaction_types.h"
+//#include "BSE_time.h"
+//#include "BSE_view.h"
+
+#include "ED_image.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+#include "ED_util.h"
+#include "ED_view3d.h"
+
+#include "UI_view2d.h"
+#include "WM_types.h"
+#include "WM_api.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
+#include "PIL_time.h" /* sleep */
+
+//#include "blendef.h"
+//
+//#include "mydevice.h"
+
+#include "transform.h"
+
+/* ************************** Dashed help line **************************** */
+
+
+/* bad frontbuffer call... because it is used in transform after force_draw() */
+static void helpline(TransInfo *t, float *vec)
+{
+#if 0 // TRANSFORM_FIX_ME
+ float vecrot[3], cent[2];
+ short mval[2];
+
+ VECCOPY(vecrot, vec);
+ if(t->flag & T_EDIT) {
+ Object *ob= t->obedit;
+ if(ob) Mat4MulVecfl(ob->obmat, vecrot);
+ }
+ else if(t->flag & T_POSE) {
+ Object *ob=t->poseobj;
+ if(ob) Mat4MulVecfl(ob->obmat, vecrot);
+ }
+
+ getmouseco_areawin(mval);
+ projectFloatView(t, vecrot, cent); // no overflow in extreme cases
+
+ persp(PERSP_WIN);
+
+ glDrawBuffer(GL_FRONT);
+
+ BIF_ThemeColor(TH_WIRE);
+
+ setlinestyle(3);
+ glBegin(GL_LINE_STRIP);
+ glVertex2sv(mval);
+ glVertex2fv(cent);
+ glEnd();
+ setlinestyle(0);
+
+ persp(PERSP_VIEW);
+ bglFlush(); // flush display for frontbuffer
+ glDrawBuffer(GL_BACK);
+#endif
+}
+
+/* ************************** SPACE DEPENDANT CODE **************************** */
+
+void setTransformViewMatrices(TransInfo *t)
+{
+ if(t->spacetype==SPACE_VIEW3D && t->ar->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = t->ar->regiondata;
+
+ Mat4CpyMat4(t->viewmat, rv3d->viewmat);
+ Mat4CpyMat4(t->viewinv, rv3d->viewinv);
+ Mat4CpyMat4(t->persmat, rv3d->persmat);
+ Mat4CpyMat4(t->persinv, rv3d->persinv);
+ t->persp = rv3d->persp;
+ }
+ else {
+ Mat4One(t->viewmat);
+ Mat4One(t->viewinv);
+ Mat4One(t->persmat);
+ Mat4One(t->persinv);
+ t->persp = V3D_ORTHO;
+ }
+
+ calculateCenter2D(t);
+}
+
+void convertViewVec(TransInfo *t, float *vec, short dx, short dy)
+{
+ if (t->spacetype==SPACE_VIEW3D) {
+ if (t->ar->regiontype == RGN_TYPE_WINDOW)
+ {
+ window_to_3d_delta(t->ar, vec, dx, dy);
+ }
+ }
+ else if(t->spacetype==SPACE_IMAGE) {
+ View2D *v2d = t->view;
+ float divx, divy, aspx, aspy;
+
+ ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
+
+ divx= v2d->mask.xmax-v2d->mask.xmin;
+ divy= v2d->mask.ymax-v2d->mask.ymin;
+
+ vec[0]= aspx*(v2d->cur.xmax-v2d->cur.xmin)*(dx)/divx;
+ vec[1]= aspy*(v2d->cur.ymax-v2d->cur.ymin)*(dy)/divy;
+ vec[2]= 0.0f;
+ }
+ else if(t->spacetype==SPACE_IPO) {
+ View2D *v2d = t->view;
+ float divx, divy;
+
+ divx= v2d->mask.xmax-v2d->mask.xmin;
+ divy= v2d->mask.ymax-v2d->mask.ymin;
+
+ vec[0]= (v2d->cur.xmax-v2d->cur.xmin)*(dx) / (divx);
+ vec[1]= (v2d->cur.ymax-v2d->cur.ymin)*(dy) / (divy);
+ vec[2]= 0.0f;
+ }
+ else if(t->spacetype==SPACE_NODE) {
+ View2D *v2d = &t->ar->v2d;
+ float divx, divy;
+
+ divx= v2d->mask.xmax-v2d->mask.xmin;
+ divy= v2d->mask.ymax-v2d->mask.ymin;
+
+ vec[0]= (v2d->cur.xmax-v2d->cur.xmin)*(dx)/divx;
+ vec[1]= (v2d->cur.ymax-v2d->cur.ymin)*(dy)/divy;
+ vec[2]= 0.0f;
+ }
+ else if(t->spacetype==SPACE_SEQ) {
+ View2D *v2d = &t->ar->v2d;
+ float divx, divy;
+
+ divx= v2d->mask.xmax-v2d->mask.xmin;
+ divy= v2d->mask.ymax-v2d->mask.ymin;
+
+ vec[0]= (v2d->cur.xmax-v2d->cur.xmin)*(dx)/divx;
+ vec[1]= (v2d->cur.ymax-v2d->cur.ymin)*(dy)/divy;
+ vec[2]= 0.0f;
+ }
+}
+
+void projectIntView(TransInfo *t, float *vec, int *adr)
+{
+ if (t->spacetype==SPACE_VIEW3D) {
+ if(t->ar->regiontype == RGN_TYPE_WINDOW)
+ project_int_noclip(t->ar, vec, adr);
+ }
+ else if(t->spacetype==SPACE_IMAGE) {
+ float aspx, aspy, v[2];
+
+ ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
+ v[0]= vec[0]/aspx;
+ v[1]= vec[1]/aspy;
+
+ UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, adr+1);
+ }
+ else if(t->spacetype==SPACE_IPO) {
+ int out[2] = {0, 0};
+
+ UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], out, out+1);
+ adr[0]= out[0];
+ adr[1]= out[1];
+ }
+ else if(t->spacetype==SPACE_SEQ) { /* XXX not tested yet, but should work */
+ int out[2] = {0, 0};
+
+ UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], out, out+1);
+ adr[0]= out[0];
+ adr[1]= out[1];
+ }
+}
+
+void projectFloatView(TransInfo *t, float *vec, float *adr)
+{
+ if (t->spacetype==SPACE_VIEW3D) {
+ if(t->ar->regiontype == RGN_TYPE_WINDOW)
+ project_float_noclip(t->ar, vec, adr);
+ }
+ else if(t->spacetype==SPACE_IMAGE) {
+ int a[2];
+
+ projectIntView(t, vec, a);
+ adr[0]= a[0];
+ adr[1]= a[1];
+ }
+ else if(t->spacetype==SPACE_IPO) {
+ int a[2];
+
+ projectIntView(t, vec, a);
+ adr[0]= a[0];
+ adr[1]= a[1];
+ }
+}
+
+void applyAspectRatio(TransInfo *t, float *vec)
+{
+ SpaceImage *sima= t->sa->spacedata.first;
+
+ if ((t->spacetype==SPACE_IMAGE) && (t->mode==TFM_TRANSLATION)) {
+ float aspx, aspy;
+
+ if((sima->flag & SI_COORDFLOATS)==0) {
+ int width, height;
+ ED_space_image_size(sima, &width, &height);
+
+ vec[0] *= width;
+ vec[1] *= height;
+ }
+
+ ED_space_image_uv_aspect(sima, &aspx, &aspy);
+ vec[0] /= aspx;
+ vec[1] /= aspy;
+ }
+}
+
+void removeAspectRatio(TransInfo *t, float *vec)
+{
+ SpaceImage *sima= t->sa->spacedata.first;
+
+ if ((t->spacetype==SPACE_IMAGE) && (t->mode==TFM_TRANSLATION)) {
+ float aspx, aspy;
+
+ if((sima->flag & SI_COORDFLOATS)==0) {
+ int width, height;
+ ED_space_image_size(sima, &width, &height);
+
+ vec[0] /= width;
+ vec[1] /= height;
+ }
+
+ ED_space_image_uv_aspect(sima, &aspx, &aspy);
+ vec[0] *= aspx;
+ vec[1] *= aspy;
+ }
+}
+
+static void viewRedrawForce(bContext *C, TransInfo *t)
+{
+ if (t->spacetype == SPACE_VIEW3D)
+ {
+ /* Do we need more refined tags? */
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
+
+ // TRANSFORM_FIX_ME
+ if (saction->lock) {
+ // whole window...
+ }
+ else
+ ED_area_tag_redraw(t->sa);
+ }
+ else if (t->spacetype == SPACE_IPO) {
+ SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first;
+
+ // TRANSFORM_FIX_ME
+ if (sipo->lock) {
+ // whole window...
+ }
+ else
+ ED_area_tag_redraw(t->sa);
+ }
+ else if(t->spacetype == SPACE_NODE)
+ {
+ //ED_area_tag_redraw(t->sa);
+ WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL);
+ }
+ else if(t->spacetype == SPACE_SEQ)
+ {
+ WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, NULL);
+ }
+ else if (t->spacetype==SPACE_IMAGE) {
+ // XXX how to deal with lock?
+#if 0
+ SpaceImage *sima= (SpaceImage*)t->sa->spacedata.first;
+ if(sima->lock) force_draw_plus(SPACE_VIEW3D, 0);
+ else force_draw(0);
+#endif
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, t->obedit);
+ }
+}
+
+static void viewRedrawPost(TransInfo *t)
+{
+ ED_area_headerprint(t->sa, NULL);
+
+#if 0 // TRANSFORM_FIX_ME
+ if(t->spacetype==SPACE_VIEW3D) {
+ allqueue(REDRAWBUTSOBJECT, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if(t->spacetype==SPACE_IMAGE) {
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if(ELEM3(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_IPO)) {
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWTIME, 0);
+ allqueue(REDRAWBUTSOBJECT, 0);
+ }
+
+ scrarea_queue_headredraw(curarea);
+#endif
+}
+
+/* ************************** TRANSFORMATIONS **************************** */
+
+void BIF_selectOrientation() {
+#if 0 // TRANSFORM_FIX_ME
+ short val;
+ char *str_menu = BIF_menustringTransformOrientation("Orientation");
+ val= pupmenu(str_menu);
+ MEM_freeN(str_menu);
+
+ if(val >= 0) {
+ G.vd->twmode = val;
+ }
+#endif
+}
+
+static void view_editmove(unsigned short event)
+{
+#if 0 // TRANSFORM_FIX_ME
+ int refresh = 0;
+ /* Regular: Zoom in */
+ /* Shift: Scroll up */
+ /* Ctrl: Scroll right */
+ /* Alt-Shift: Rotate up */
+ /* Alt-Ctrl: Rotate right */
+
+ /* only work in 3D window for now
+ * In the end, will have to send to event to a 2D window handler instead
+ */
+ if (Trans.flag & T_2D_EDIT)
+ return;
+
+ switch(event) {
+ case WHEELUPMOUSE:
+
+ if( G.qual & LR_SHIFTKEY ) {
+ if( G.qual & LR_ALTKEY ) {
+ G.qual &= ~LR_SHIFTKEY;
+ persptoetsen(PAD2);
+ G.qual |= LR_SHIFTKEY;
+ } else {
+ persptoetsen(PAD2);
+ }
+ } else if( G.qual & LR_CTRLKEY ) {
+ if( G.qual & LR_ALTKEY ) {
+ G.qual &= ~LR_CTRLKEY;
+ persptoetsen(PAD4);
+ G.qual |= LR_CTRLKEY;
+ } else {
+ persptoetsen(PAD4);
+ }
+ } else if(U.uiflag & USER_WHEELZOOMDIR)
+ persptoetsen(PADMINUS);
+ else
+ persptoetsen(PADPLUSKEY);
+
+ refresh = 1;
+ break;
+ case WHEELDOWNMOUSE:
+ if( G.qual & LR_SHIFTKEY ) {
+ if( G.qual & LR_ALTKEY ) {
+ G.qual &= ~LR_SHIFTKEY;
+ persptoetsen(PAD8);
+ G.qual |= LR_SHIFTKEY;
+ } else {
+ persptoetsen(PAD8);
+ }
+ } else if( G.qual & LR_CTRLKEY ) {
+ if( G.qual & LR_ALTKEY ) {
+ G.qual &= ~LR_CTRLKEY;
+ persptoetsen(PAD6);
+ G.qual |= LR_CTRLKEY;
+ } else {
+ persptoetsen(PAD6);
+ }
+ } else if(U.uiflag & USER_WHEELZOOMDIR)
+ persptoetsen(PADPLUSKEY);
+ else
+ persptoetsen(PADMINUS);
+
+ refresh = 1;
+ break;
+ }
+
+ if (refresh)
+ setTransformViewMatrices(&Trans);
+#endif
+}
+
+static char *transform_to_undostr(TransInfo *t)
+{
+ switch (t->mode) {
+ case TFM_TRANSLATION:
+ return "Translate";
+ case TFM_ROTATION:
+ return "Rotate";
+ case TFM_RESIZE:
+ return "Scale";
+ case TFM_TOSPHERE:
+ return "To Sphere";
+ case TFM_SHEAR:
+ return "Shear";
+ case TFM_WARP:
+ return "Warp";
+ case TFM_SHRINKFATTEN:
+ return "Shrink/Fatten";
+ case TFM_TILT:
+ return "Tilt";
+ case TFM_TRACKBALL:
+ return "Trackball";
+ case TFM_PUSHPULL:
+ return "Push/Pull";
+ case TFM_BEVEL:
+ return "Bevel";
+ case TFM_BWEIGHT:
+ return "Bevel Weight";
+ case TFM_CREASE:
+ return "Crease";
+ case TFM_BONESIZE:
+ return "Bone Width";
+ case TFM_BONE_ENVELOPE:
+ return "Bone Envelope";
+ case TFM_TIME_TRANSLATE:
+ return "Translate Anim. Data";
+ case TFM_TIME_SCALE:
+ return "Scale Anim. Data";
+ case TFM_TIME_SLIDE:
+ return "Time Slide";
+ case TFM_BAKE_TIME:
+ return "Key Time";
+ case TFM_MIRROR:
+ return "Mirror";
+ }
+ return "Transform";
+}
+
+/* ************************************************* */
+
+void transformEvent(TransInfo *t, wmEvent *event)
+{
+ float mati[3][3] = {{1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}};
+ char cmode = constraintModeToChar(t);
+
+ t->redraw |= handleMouseInput(t, &t->mouse, event);
+
+ if (event->type == MOUSEMOVE)
+ {
+ t->mval[0] = event->x - t->ar->winrct.xmin;
+ t->mval[1] = event->y - t->ar->winrct.ymin;
+
+ t->redraw = 1;
+
+ applyMouseInput(t, &t->mouse, t->mval, t->values);
+ }
+
+ if (event->val) {
+ switch (event->type){
+ /* enforce redraw of transform when modifiers are used */
+ case LEFTCTRLKEY:
+ case RIGHTCTRLKEY:
+ t->modifiers |= MOD_SNAP_GEARS;
+ t->redraw = 1;
+ break;
+
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ t->modifiers |= MOD_CONSTRAINT_PLANE;
+ t->redraw = 1;
+ break;
+
+ case SPACEKEY:
+ if ((t->spacetype==SPACE_VIEW3D) && event->alt) {
+#if 0 // TRANSFORM_FIX_ME
+ short mval[2];
+
+ getmouseco_sc(mval);
+ BIF_selectOrientation();
+ calc_manipulator_stats(curarea);
+ Mat3CpyMat4(t->spacemtx, G.vd->twmat);
+ warp_pointer(mval[0], mval[1]);
+#endif
+ }
+ else {
+ t->state = TRANS_CONFIRM;
+ }
+ break;
+
+ case MIDDLEMOUSE:
+ if ((t->flag & T_NO_CONSTRAINT)==0) {
+ /* exception for switching to dolly, or trackball, in camera view */
+ if (t->flag & T_CAMERA) {
+ if (t->mode==TFM_TRANSLATION)
+ setLocalConstraint(t, (CON_AXIS2), "along local Z");
+ else if (t->mode==TFM_ROTATION) {
+ restoreTransObjects(t);
+ initTrackball(t);
+ }
+ }
+ else {
+ t->modifiers |= MOD_CONSTRAINT_SELECT;
+ if (t->con.mode & CON_APPLY) {
+ stopConstraint(t);
+ }
+ else {
+ if (event->shift) {
+ initSelectConstraint(t, t->spacemtx);
+ }
+ else {
+ /* bit hackish... but it prevents mmb select to print the orientation from menu */
+ strcpy(t->spacename, "global");
+ initSelectConstraint(t, mati);
+ }
+ postSelectConstraint(t);
+ }
+ }
+ t->redraw = 1;
+ }
+ break;
+ case ESCKEY:
+ case RIGHTMOUSE:
+ printf("cancelled\n");
+ t->state = TRANS_CANCEL;
+ break;
+ case LEFTMOUSE:
+ case PADENTER:
+ case RETKEY:
+ t->state = TRANS_CONFIRM;
+ break;
+ case GKEY:
+ /* only switch when... */
+ if( ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL) ) {
+ resetTransRestrictions(t);
+ restoreTransObjects(t);
+ initTranslation(t);
+ t->redraw = 1;
+ }
+ break;
+ case SKEY:
+ /* only switch when... */
+ if( ELEM3(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL) ) {
+ resetTransRestrictions(t);
+ restoreTransObjects(t);
+ initResize(t);
+ t->redraw = 1;
+ }
+ break;
+ case RKEY:
+ /* only switch when... */
+ if( ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) {
+
+ resetTransRestrictions(t);
+
+ if (t->mode == TFM_ROTATION) {
+ restoreTransObjects(t);
+ initTrackball(t);
+ }
+ else {
+ restoreTransObjects(t);
+ initRotation(t);
+ }
+ t->redraw = 1;
+ }
+ break;
+ case CKEY:
+ if (event->alt) {
+ t->flag ^= T_PROP_CONNECTED;
+ sort_trans_data_dist(t);
+ calculatePropRatio(t);
+ t->redraw= 1;
+ }
+ else {
+ stopConstraint(t);
+ t->redraw = 1;
+ }
+ break;
+ case XKEY:
+ if ((t->flag & T_NO_CONSTRAINT)==0) {
+ if (cmode == 'X') {
+ if (t->flag & T_2D_EDIT) {
+ stopConstraint(t);
+ }
+ else {
+ if (t->con.mode & CON_USER) {
+ stopConstraint(t);
+ }
+ else {
+ if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
+ setUserConstraint(t, (CON_AXIS0), "along %s X");
+ else if (t->modifiers & MOD_CONSTRAINT_PLANE)
+ setUserConstraint(t, (CON_AXIS1|CON_AXIS2), "locking %s X");
+ }
+ }
+ }
+ else {
+ if (t->flag & T_2D_EDIT) {
+ setConstraint(t, mati, (CON_AXIS0), "along X axis");
+ }
+ else {
+ if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
+ setConstraint(t, mati, (CON_AXIS0), "along global X");
+ else if (t->modifiers & MOD_CONSTRAINT_PLANE)
+ setConstraint(t, mati, (CON_AXIS1|CON_AXIS2), "locking global X");
+ }
+ }
+ t->redraw = 1;
+ }
+ break;
+ case YKEY:
+ if ((t->flag & T_NO_CONSTRAINT)==0) {
+ if (cmode == 'Y') {
+ if (t->flag & T_2D_EDIT) {
+ stopConstraint(t);
+ }
+ else {
+ if (t->con.mode & CON_USER) {
+ stopConstraint(t);
+ }
+ else {
+ if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
+ setUserConstraint(t, (CON_AXIS1), "along %s Y");
+ else if (t->modifiers & MOD_CONSTRAINT_PLANE)
+ setUserConstraint(t, (CON_AXIS0|CON_AXIS2), "locking %s Y");
+ }
+ }
+ }
+ else {
+ if (t->flag & T_2D_EDIT) {
+ setConstraint(t, mati, (CON_AXIS1), "along Y axis");
+ }
+ else {
+ if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
+ setConstraint(t, mati, (CON_AXIS1), "along global Y");
+ else if (t->modifiers & MOD_CONSTRAINT_PLANE)
+ setConstraint(t, mati, (CON_AXIS0|CON_AXIS2), "locking global Y");
+ }
+ }
+ t->redraw = 1;
+ }
+ break;
+ case ZKEY:
+ if ((t->flag & T_NO_CONSTRAINT)==0) {
+ if (cmode == 'Z') {
+ if (t->con.mode & CON_USER) {
+ stopConstraint(t);
+ }
+ else {
+ if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
+ setUserConstraint(t, (CON_AXIS2), "along %s Z");
+ else if ((t->modifiers & MOD_CONSTRAINT_PLANE) && ((t->flag & T_2D_EDIT)==0))
+ setUserConstraint(t, (CON_AXIS0|CON_AXIS1), "locking %s Z");
+ }
+ }
+ else if ((t->flag & T_2D_EDIT)==0) {
+ if ((t->modifiers & MOD_CONSTRAINT_PLANE) == 0)
+ setConstraint(t, mati, (CON_AXIS2), "along global Z");
+ else if (t->modifiers & MOD_CONSTRAINT_PLANE)
+ setConstraint(t, mati, (CON_AXIS0|CON_AXIS1), "locking global Z");
+ }
+ t->redraw = 1;
+ }
+ break;
+ case OKEY:
+ if (t->flag & T_PROP_EDIT && event->shift) {
+ t->prop_mode = (t->prop_mode + 1) % 6;
+ calculatePropRatio(t);
+ t->redraw = 1;
+ }
+ break;
+ case PADPLUSKEY:
+ if(event->alt && t->flag & T_PROP_EDIT) {
+ t->prop_size *= 1.1f;
+ calculatePropRatio(t);
+ }
+ t->redraw= 1;
+ break;
+ case PAGEUPKEY:
+ case WHEELDOWNMOUSE:
+ if (t->flag & T_AUTOIK) {
+ transform_autoik_update(t, 1);
+ }
+ else if(t->flag & T_PROP_EDIT) {
+ t->prop_size*= 1.1f;
+ calculatePropRatio(t);
+ }
+ else view_editmove(event->type);
+ t->redraw= 1;
+ break;
+ case PADMINUS:
+ if(event->alt && t->flag & T_PROP_EDIT) {
+ t->prop_size*= 0.90909090f;
+ calculatePropRatio(t);
+ }
+ t->redraw= 1;
+ break;
+ case PAGEDOWNKEY:
+ case WHEELUPMOUSE:
+ if (t->flag & T_AUTOIK) {
+ transform_autoik_update(t, -1);
+ }
+ else if (t->flag & T_PROP_EDIT) {
+ t->prop_size*= 0.90909090f;
+ calculatePropRatio(t);
+ }
+ else view_editmove(event->type);
+ t->redraw= 1;
+ break;
+// case NDOFMOTION:
+// viewmoveNDOF(1);
+ // break;
+ }
+
+ // Numerical input events
+ t->redraw |= handleNumInput(&(t->num), event);
+
+ // NDof input events
+ switch(handleNDofInput(&(t->ndof), event))
+ {
+ case NDOF_CONFIRM:
+ if ((t->options & CTX_NDOF) == 0)
+ {
+ /* Confirm on normal transform only */
+ t->state = TRANS_CONFIRM;
+ }
+ break;
+ case NDOF_CANCEL:
+ if (t->options & CTX_NDOF)
+ {
+ /* Cancel on pure NDOF transform */
+ t->state = TRANS_CANCEL;
+ }
+ else
+ {
+ /* Otherwise, just redraw, NDof input was cancelled */
+ t->redraw = 1;
+ }
+ break;
+ case NDOF_NOMOVE:
+ if (t->options & CTX_NDOF)
+ {
+ /* Confirm on pure NDOF transform */
+ t->state = TRANS_CONFIRM;
+ }
+ break;
+ case NDOF_REFRESH:
+ t->redraw = 1;
+ break;
+
+ }
+
+ // Snapping events
+ t->redraw |= handleSnapping(t, event);
+
+ //arrows_move_cursor(event->type);
+ }
+ else {
+ switch (event->type){
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ t->modifiers &= ~MOD_CONSTRAINT_PLANE;
+ t->redraw = 1;
+ break;
+
+ case LEFTCTRLKEY:
+ case RIGHTCTRLKEY:
+ t->modifiers &= ~MOD_SNAP_GEARS;
+ /* no redraw on release modifier keys! this makes sure you can assign the 'grid' still
+ after releasing modifer key */
+ //t->redraw = 1;
+ break;
+ case MIDDLEMOUSE:
+ if ((t->flag & T_NO_CONSTRAINT)==0) {
+ t->modifiers &= ~MOD_CONSTRAINT_SELECT;
+ postSelectConstraint(t);
+ t->redraw = 1;
+ }
+ break;
+ case LEFTMOUSE:
+ case RIGHTMOUSE:
+ if(WM_modal_tweak_exit(event, t->event_type))
+// if (t->options & CTX_TWEAK)
+ t->state = TRANS_CONFIRM;
+ break;
+ }
+ }
+
+ // Per transform event, if present
+ if (t->handleEvent)
+ t->redraw |= t->handleEvent(t, event);
+}
+
+int calculateTransformCenter(bContext *C, wmEvent *event, int centerMode, float *vec)
+{
+ TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data");
+ int success = 1;
+
+ t->state = TRANS_RUNNING;
+
+ t->options = CTX_NONE;
+
+ t->mode = TFM_DUMMY;
+
+ initTransInfo(C, t, NULL, event); // internal data, mouse, vectors
+
+ createTransData(C, t); // make TransData structs from selection
+
+ t->around = centerMode; // override userdefined mode
+
+ if (t->total == 0) {
+ success = 0;
+ }
+ else {
+ success = 1;
+
+ calculateCenter(t);
+
+ // Copy center from constraint center. Transform center can be local
+ VECCOPY(vec, t->con.center);
+ }
+
+ postTrans(t);
+
+ /* aftertrans does insert ipos and action channels, and clears base flags, doesnt read transdata */
+ special_aftertrans_update(t);
+
+ MEM_freeN(t);
+
+ return success;
+}
+
+void drawTransform(const struct bContext *C, struct ARegion *ar, void *arg)
+{
+ TransInfo *t = arg;
+
+ drawConstraint(C, t);
+ drawPropCircle(C, t);
+ drawSnapping(C, t);
+}
+
+void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
+{
+ Scene *sce = CTX_data_scene(C);
+ int constraint_axis[3] = {0, 0, 0};
+ int proportional = 0;
+
+ if (t->flag & T_AUTOVALUES)
+ {
+ RNA_float_set_array(op->ptr, "value", t->auto_values);
+ }
+ else
+ {
+ RNA_float_set_array(op->ptr, "value", t->values);
+ }
+
+ /* XXX convert stupid flag to enum */
+ switch(t->flag & (T_PROP_EDIT|T_PROP_CONNECTED))
+ {
+ case (T_PROP_EDIT|T_PROP_CONNECTED):
+ proportional = 2;
+ break;
+ case T_PROP_EDIT:
+ proportional = 1;
+ break;
+ default:
+ proportional = 0;
+ }
+
+ if (RNA_struct_find_property(op->ptr, "proportional"))
+ {
+ RNA_enum_set(op->ptr, "proportional", proportional);
+ RNA_enum_set(op->ptr, "proportional_editing_falloff", t->prop_mode);
+ RNA_float_set(op->ptr, "proportional_size", t->prop_size);
+ }
+
+ if (RNA_struct_find_property(op->ptr, "mirror"))
+ {
+ RNA_boolean_set(op->ptr, "mirror", t->flag & T_MIRROR);
+ }
+
+ if (RNA_struct_find_property(op->ptr, "constraint_mode"))
+ {
+ RNA_int_set(op->ptr, "constraint_mode", t->con.mode);
+ RNA_int_set(op->ptr, "constraint_orientation", t->current_orientation);
+
+ if (t->con.mode & CON_APPLY)
+ {
+ if (t->con.mode & CON_AXIS0) {
+ constraint_axis[0] = 1;
+ }
+ if (t->con.mode & CON_AXIS1) {
+ constraint_axis[1] = 1;
+ }
+ if (t->con.mode & CON_AXIS2) {
+ constraint_axis[2] = 1;
+ }
+ }
+
+ RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
+ }
+
+ // XXX If modal, save settings back in scene
+ if (t->flag & T_MODAL)
+ {
+ sce->prop_mode = t->prop_mode;
+ sce->proportional = proportional;
+
+ if(t->spacetype == SPACE_VIEW3D)
+ {
+ View3D *v3d = t->view;
+
+ v3d->twmode = t->current_orientation;
+ }
+ }
+}
+
+int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int mode)
+{
+ int options = 0;
+
+ /* added initialize, for external calls to set stuff in TransInfo, like undo string */
+
+ t->state = TRANS_RUNNING;
+
+ t->options = options;
+
+ t->mode = mode;
+
+ if (!initTransInfo(C, t, op, event)) // internal data, mouse, vectors
+ {
+ return 0;
+ }
+
+ initTransformOrientation(C, t);
+
+ if(t->spacetype == SPACE_VIEW3D)
+ {
+ //calc_manipulator_stats(curarea);
+ if (t->ar->regiontype == RGN_TYPE_WINDOW)
+ {
+ RegionView3D *rv3d = t->ar->regiondata;
+ Mat3CpyMat4(t->spacemtx, rv3d->twmat);
+ }
+ Mat3Ortho(t->spacemtx);
+
+ t->draw_handle = ED_region_draw_cb_activate(t->ar->type, drawTransform, t, REGION_DRAW_POST);
+ }
+ else if(t->spacetype == SPACE_IMAGE) {
+ Mat3One(t->spacemtx);
+ t->draw_handle = ED_region_draw_cb_activate(t->ar->type, drawTransform, t, REGION_DRAW_POST);
+ }
+ else
+ Mat3One(t->spacemtx);
+
+ createTransData(C, t); // make TransData structs from selection
+
+ if (t->total == 0) {
+ postTrans(t);
+ return 0;
+ }
+
+ initSnapping(t, op); // Initialize snapping data AFTER mode flags
+
+ /* EVIL! posemode code can switch translation to rotate when 1 bone is selected. will be removed (ton) */
+ /* EVIL2: we gave as argument also texture space context bit... was cleared */
+ /* EVIL3: extend mode for animation editors also switches modes... but is best way to avoid duplicate code */
+ mode = t->mode;
+
+ calculatePropRatio(t);
+ calculateCenter(t);
+
+ initMouseInput(t, &t->mouse, t->center2d, t->imval);
+
+ switch (mode) {
+ case TFM_TRANSLATION:
+ initTranslation(t);
+ break;
+ case TFM_ROTATION:
+ initRotation(t);
+ break;
+ case TFM_RESIZE:
+ initResize(t);
+ break;
+ case TFM_TOSPHERE:
+ initToSphere(t);
+ break;
+ case TFM_SHEAR:
+ initShear(t);
+ break;
+ case TFM_WARP:
+ initWarp(t);
+ break;
+ case TFM_SHRINKFATTEN:
+ initShrinkFatten(t);
+ break;
+ case TFM_TILT:
+ initTilt(t);
+ break;
+ case TFM_CURVE_SHRINKFATTEN:
+ initCurveShrinkFatten(t);
+ break;
+ case TFM_TRACKBALL:
+ initTrackball(t);
+ break;
+ case TFM_PUSHPULL:
+ initPushPull(t);
+ break;
+ case TFM_CREASE:
+ initCrease(t);
+ break;
+ case TFM_BONESIZE:
+ { /* used for both B-Bone width (bonesize) as for deform-dist (envelope) */
+ bArmature *arm= t->poseobj->data;
+ if(arm->drawtype==ARM_ENVELOPE)
+ initBoneEnvelope(t);
+ else
+ initBoneSize(t);
+ }
+ break;
+ case TFM_BONE_ENVELOPE:
+ initBoneEnvelope(t);
+ break;
+ case TFM_BONE_ROLL:
+ initBoneRoll(t);
+ break;
+ case TFM_TIME_TRANSLATE:
+ initTimeTranslate(t);
+ break;
+ case TFM_TIME_SLIDE:
+ initTimeSlide(t);
+ break;
+ case TFM_TIME_SCALE:
+ initTimeScale(t);
+ break;
+ case TFM_TIME_EXTEND:
+ /* now that transdata has been made, do like for TFM_TIME_TRANSLATE (for most Animation
+ * Editors because they have only 1D transforms for time values) or TFM_TRANSLATION
+ * (for Graph Editor only since it uses 'standard' transforms to get 2D movement)
+ * depending on which editor this was called from
+ */
+ if (t->spacetype == SPACE_IPO)
+ initTranslation(t);
+ else
+ initTimeTranslate(t);
+ break;
+ case TFM_BAKE_TIME:
+ initBakeTime(t);
+ break;
+ case TFM_MIRROR:
+ initMirror(t);
+ break;
+ case TFM_BEVEL:
+ initBevel(t);
+ break;
+ case TFM_BWEIGHT:
+ initBevelWeight(t);
+ break;
+ case TFM_ALIGN:
+ initAlign(t);
+ break;
+ }
+
+ /* overwrite initial values if operator supplied a non-null vector */
+ if (RNA_property_is_set(op->ptr, "value"))
+ {
+ float values[4];
+ RNA_float_get_array(op->ptr, "value", values);
+ QUATCOPY(t->values, values);
+ QUATCOPY(t->auto_values, values);
+ t->flag |= T_AUTOVALUES;
+ }
+
+ /* Constraint init from operator */
+ if (RNA_struct_find_property(op->ptr, "constraint_axis") && RNA_property_is_set(op->ptr, "constraint_axis"))
+ {
+ int constraint_axis[3];
+
+ RNA_boolean_get_array(op->ptr, "constraint_axis", constraint_axis);
+
+ if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2])
+ {
+ t->con.mode |= CON_APPLY;
+
+ if (constraint_axis[0]) {
+ t->con.mode |= CON_AXIS0;
+ }
+ if (constraint_axis[1]) {
+ t->con.mode |= CON_AXIS1;
+ }
+ if (constraint_axis[2]) {
+ t->con.mode |= CON_AXIS2;
+ }
+
+ setUserConstraint(t, t->con.mode, "%s");
+ }
+ }
+
+ return 1;
+}
+
+void transformApply(bContext *C, TransInfo *t)
+{
+ if (t->redraw)
+ {
+ if (t->modifiers & MOD_CONSTRAINT_SELECT)
+ t->con.mode |= CON_SELECT;
+
+ selectConstraint(t);
+ if (t->transform) {
+ t->transform(t, t->mval); // calls recalcData()
+ viewRedrawForce(C, t);
+ }
+ t->redraw = 0;
+ }
+
+ /* If auto confirm is on, break after one pass */
+ if (t->options & CTX_AUTOCONFIRM)
+ {
+ t->state = TRANS_CONFIRM;
+ }
+
+ if (BKE_ptcache_get_continue_physics())
+ {
+ // TRANSFORM_FIX_ME
+ //do_screenhandlers(G.curscreen);
+ t->redraw = 1;
+ }
+}
+
+int transformEnd(bContext *C, TransInfo *t)
+{
+ int exit_code = OPERATOR_RUNNING_MODAL;
+
+ if (t->state != TRANS_RUNNING)
+ {
+ /* handle restoring objects */
+ if(t->state == TRANS_CANCEL)
+ {
+ exit_code = OPERATOR_CANCELLED;
+ restoreTransObjects(t); // calls recalcData()
+ }
+ else
+ {
+ exit_code = OPERATOR_FINISHED;
+ }
+
+ /* free data */
+ postTrans(t);
+
+ /* aftertrans does insert keyframes, and clears base flags, doesnt read transdata */
+ special_aftertrans_update(t);
+
+ /* send events out for redraws */
+ viewRedrawPost(t);
+
+ /* Undo as last, certainly after special_trans_update! */
+
+ if(t->state == TRANS_CANCEL) {
+// if(t->undostr) ED_undo_push(C, t->undostr);
+ }
+ else {
+// if(t->undostr) ED_undo_push(C, t->undostr);
+// else ED_undo_push(C, transform_to_undostr(t));
+ }
+ t->undostr= NULL;
+
+ viewRedrawForce(C, t);
+ }
+
+ return exit_code;
+}
+
+/* ************************** Manipulator init and main **************************** */
+
+void initManipulator(int mode)
+{
+#if 0 // TRANSFORM_FIX_ME
+ Trans.state = TRANS_RUNNING;
+
+ Trans.options = CTX_NONE;
+
+ Trans.mode = mode;
+
+ /* automatic switch to scaling bone envelopes */
+ if(mode==TFM_RESIZE && t->obedit && t->obedit->type==OB_ARMATURE) {
+ bArmature *arm= t->obedit->data;
+ if(arm->drawtype==ARM_ENVELOPE)
+ mode= TFM_BONE_ENVELOPE;
+ }
+
+ initTrans(&Trans); // internal data, mouse, vectors
+
+ G.moving |= G_TRANSFORM_MANIP; // signal to draw manipuls while transform
+ createTransData(&Trans); // make TransData structs from selection
+
+ if (Trans.total == 0)
+ return;
+
+ initSnapping(&Trans); // Initialize snapping data AFTER mode flags
+
+ /* EVIL! posemode code can switch translation to rotate when 1 bone is selected. will be removed (ton) */
+ /* EVIL2: we gave as argument also texture space context bit... was cleared */
+ mode = Trans.mode;
+
+ calculatePropRatio(&Trans);
+ calculateCenter(&Trans);
+
+ switch (mode) {
+ case TFM_TRANSLATION:
+ initTranslation(&Trans);
+ break;
+ case TFM_ROTATION:
+ initRotation(&Trans);
+ break;
+ case TFM_RESIZE:
+ initResize(&Trans);
+ break;
+ case TFM_TRACKBALL:
+ initTrackball(&Trans);
+ break;
+ }
+
+ Trans.flag |= T_USES_MANIPULATOR;
+#endif
+}
+
+void ManipulatorTransform()
+{
+#if 0 // TRANSFORM_FIX_ME
+ int mouse_moved = 0;
+ short pmval[2] = {0, 0}, mval[2], val;
+ unsigned short event;
+
+ if (Trans.total == 0)
+ return;
+
+ Trans.redraw = 1; /* initial draw */
+
+ while (Trans.state == TRANS_RUNNING) {
+
+ getmouseco_areawin(mval);
+
+ if (mval[0] != pmval[0] || mval[1] != pmval[1]) {
+ Trans.redraw = 1;
+ }
+ if (Trans.redraw) {
+ pmval[0] = mval[0];
+ pmval[1] = mval[1];
+
+ //selectConstraint(&Trans); needed?
+ if (Trans.transform) {
+ Trans.transform(&Trans, mval);
+ }
+ Trans.redraw = 0;
+ }
+
+ /* essential for idling subloop */
+ if( qtest()==0) PIL_sleep_ms(2);
+
+ while( qtest() ) {
+ event= extern_qread(&val);
+
+ switch (event){
+ case MOUSEX:
+ case MOUSEY:
+ mouse_moved = 1;
+ break;
+ /* enforce redraw of transform when modifiers are used */
+ case LEFTCTRLKEY:
+ case RIGHTCTRLKEY:
+ if(val) Trans.redraw = 1;
+ break;
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ /* shift is modifier for higher resolution transform, works nice to store this mouse position */
+ if(val) {
+ getmouseco_areawin(Trans.shiftmval);
+ Trans.flag |= T_SHIFT_MOD;
+ Trans.redraw = 1;
+ }
+ else Trans.flag &= ~T_SHIFT_MOD;
+ break;
+
+ case ESCKEY:
+ case RIGHTMOUSE:
+ Trans.state = TRANS_CANCEL;
+ break;
+ case LEFTMOUSE:
+ if(mouse_moved==0 && val==0) break;
+ // else we pass on event to next, which cancels
+ case SPACEKEY:
+ case PADENTER:
+ case RETKEY:
+ Trans.state = TRANS_CONFIRM;
+ break;
+ // case NDOFMOTION:
+ // viewmoveNDOF(1);
+ // break;
+ }
+ if(val) {
+ switch(event) {
+ case PADPLUSKEY:
+ if(G.qual & LR_ALTKEY && Trans.flag & T_PROP_EDIT) {
+ Trans.propsize*= 1.1f;
+ calculatePropRatio(&Trans);
+ }
+ Trans.redraw= 1;
+ break;
+ case PAGEUPKEY:
+ case WHEELDOWNMOUSE:
+ if (Trans.flag & T_AUTOIK) {
+ transform_autoik_update(&Trans, 1);
+ }
+ else if(Trans.flag & T_PROP_EDIT) {
+ Trans.propsize*= 1.1f;
+ calculatePropRatio(&Trans);
+ }
+ else view_editmove(event);
+ Trans.redraw= 1;
+ break;
+ case PADMINUS:
+ if(G.qual & LR_ALTKEY && Trans.flag & T_PROP_EDIT) {
+ Trans.propsize*= 0.90909090f;
+ calculatePropRatio(&Trans);
+ }
+ Trans.redraw= 1;
+ break;
+ case PAGEDOWNKEY:
+ case WHEELUPMOUSE:
+ if (Trans.flag & T_AUTOIK) {
+ transform_autoik_update(&Trans, -1);
+ }
+ else if (Trans.flag & T_PROP_EDIT) {
+ Trans.propsize*= 0.90909090f;
+ calculatePropRatio(&Trans);
+ }
+ else view_editmove(event);
+ Trans.redraw= 1;
+ break;
+ }
+
+ // Numerical input events
+ Trans.redraw |= handleNumInput(&(Trans.num), event);
+ }
+ }
+ }
+
+ if(Trans.state == TRANS_CANCEL) {
+ restoreTransObjects(&Trans);
+ }
+
+ /* free data, reset vars */
+ postTrans(&Trans);
+
+ /* aftertrans does insert ipos and action channels, and clears base flags */
+ special_aftertrans_update(&Trans);
+
+ /* send events out for redraws */
+ viewRedrawPost(&Trans);
+
+ if(Trans.state != TRANS_CANCEL) {
+ BIF_undo_push(transform_to_undostr(&Trans));
+ }
+#endif
+}
+
+/* ************************** TRANSFORM LOCKS **************************** */
+
+static void protectedTransBits(short protectflag, float *vec)
+{
+ if(protectflag & OB_LOCK_LOCX)
+ vec[0]= 0.0f;
+ if(protectflag & OB_LOCK_LOCY)
+ vec[1]= 0.0f;
+ if(protectflag & OB_LOCK_LOCZ)
+ vec[2]= 0.0f;
+}
+
+static void protectedSizeBits(short protectflag, float *size)
+{
+ if(protectflag & OB_LOCK_SCALEX)
+ size[0]= 1.0f;
+ if(protectflag & OB_LOCK_SCALEY)
+ size[1]= 1.0f;
+ if(protectflag & OB_LOCK_SCALEZ)
+ size[2]= 1.0f;
+}
+
+static void protectedRotateBits(short protectflag, float *eul, float *oldeul)
+{
+ if(protectflag & OB_LOCK_ROTX)
+ eul[0]= oldeul[0];
+ if(protectflag & OB_LOCK_ROTY)
+ eul[1]= oldeul[1];
+ if(protectflag & OB_LOCK_ROTZ)
+ eul[2]= oldeul[2];
+}
+
+static void protectedQuaternionBits(short protectflag, float *quat, float *oldquat)
+{
+ /* quaternions get limited with euler... */
+ /* this function only does the delta rotation */
+
+ if(protectflag) {
+ float eul[3], oldeul[3], quat1[4];
+
+ QUATCOPY(quat1, quat);
+ QuatToEul(quat, eul);
+ QuatToEul(oldquat, oldeul);
+
+ if(protectflag & OB_LOCK_ROTX)
+ eul[0]= oldeul[0];
+ if(protectflag & OB_LOCK_ROTY)
+ eul[1]= oldeul[1];
+ if(protectflag & OB_LOCK_ROTZ)
+ eul[2]= oldeul[2];
+
+ EulToQuat(eul, quat);
+ /* quaternions flip w sign to accumulate rotations correctly */
+ if( (quat1[0]<0.0f && quat[0]>0.0f) || (quat1[0]>0.0f && quat[0]<0.0f) ) {
+ QuatMulf(quat, -1.0f);
+ }
+ }
+}
+
+/* ******************* TRANSFORM LIMITS ********************** */
+
+static void constraintTransLim(TransInfo *t, TransData *td)
+{
+ if (td->con) {
+ bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT);
+ bConstraintOb cob;
+ bConstraint *con;
+
+ /* Make a temporary bConstraintOb for using these limit constraints
+ * - they only care that cob->matrix is correctly set ;-)
+ * - current space should be local
+ */
+ memset(&cob, 0, sizeof(bConstraintOb));
+ Mat4One(cob.matrix);
+ if (td->tdi) {
+ TransDataIpokey *tdi= td->tdi;
+ cob.matrix[3][0]= tdi->locx[0];
+ cob.matrix[3][1]= tdi->locy[0];
+ cob.matrix[3][2]= tdi->locz[0];
+ }
+ else {
+ VECCOPY(cob.matrix[3], td->loc);
+ }
+
+ /* Evaluate valid constraints */
+ for (con= td->con; con; con= con->next) {
+ float tmat[4][4];
+
+ /* only consider constraint if enabled */
+ if (con->flag & CONSTRAINT_DISABLE) continue;
+ if (con->enforce == 0.0f) continue;
+
+ /* only use it if it's tagged for this purpose (and the right type) */
+ if (con->type == CONSTRAINT_TYPE_LOCLIMIT) {
+ bLocLimitConstraint *data= con->data;
+
+ if ((data->flag2 & LIMIT_TRANSFORM)==0)
+ continue;
+
+ /* do space conversions */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->mtx (this should be ok) */
+ Mat4CpyMat4(tmat, cob.matrix);
+ Mat4MulMat34(cob.matrix, td->mtx, tmat);
+ }
+ else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
+ /* skip... incompatable spacetype */
+ continue;
+ }
+
+ /* do constraint */
+ cti->evaluate_constraint(con, &cob, NULL);
+
+ /* convert spaces again */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->mtx (this should be ok) */
+ Mat4CpyMat4(tmat, cob.matrix);
+ Mat4MulMat34(cob.matrix, td->smtx, tmat);
+ }
+ }
+ }
+
+ /* copy results from cob->matrix */
+ if (td->tdi) {
+ TransDataIpokey *tdi= td->tdi;
+ tdi->locx[0]= cob.matrix[3][0];
+ tdi->locy[0]= cob.matrix[3][1];
+ tdi->locz[0]= cob.matrix[3][2];
+ }
+ else {
+ VECCOPY(td->loc, cob.matrix[3]);
+ }
+ }
+}
+
+static void constraintRotLim(TransInfo *t, TransData *td)
+{
+ if (td->con) {
+ bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_ROTLIMIT);
+ bConstraintOb cob;
+ bConstraint *con;
+
+ /* Make a temporary bConstraintOb for using these limit constraints
+ * - they only care that cob->matrix is correctly set ;-)
+ * - current space should be local
+ */
+ memset(&cob, 0, sizeof(bConstraintOb));
+ if (td->flag & TD_USEQUAT) {
+ /* quats */
+ if (td->ext)
+ QuatToMat4(td->ext->quat, cob.matrix);
+ else
+ return;
+ }
+ else if (td->tdi) {
+ /* ipo-keys eulers */
+ TransDataIpokey *tdi= td->tdi;
+ float eul[3];
+
+ eul[0]= tdi->rotx[0];
+ eul[1]= tdi->roty[0];
+ eul[2]= tdi->rotz[0];
+
+ EulToMat4(eul, cob.matrix);
+ }
+ else {
+ /* eulers */
+ if (td->ext)
+ EulToMat4(td->ext->rot, cob.matrix);
+ else
+ return;
+ }
+
+ /* Evaluate valid constraints */
+ for (con= td->con; con; con= con->next) {
+ /* only consider constraint if enabled */
+ if (con->flag & CONSTRAINT_DISABLE) continue;
+ if (con->enforce == 0.0f) continue;
+
+ /* we're only interested in Limit-Rotation constraints */
+ if (con->type == CONSTRAINT_TYPE_ROTLIMIT) {
+ bRotLimitConstraint *data= con->data;
+ float tmat[4][4];
+
+ /* only use it if it's tagged for this purpose */
+ if ((data->flag2 & LIMIT_TRANSFORM)==0)
+ continue;
+
+ /* do space conversions */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->mtx (this should be ok) */
+ Mat4CpyMat4(tmat, cob.matrix);
+ Mat4MulMat34(cob.matrix, td->mtx, tmat);
+ }
+ else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
+ /* skip... incompatable spacetype */
+ continue;
+ }
+
+ /* do constraint */
+ cti->evaluate_constraint(con, &cob, NULL);
+
+ /* convert spaces again */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->mtx (this should be ok) */
+ Mat4CpyMat4(tmat, cob.matrix);
+ Mat4MulMat34(cob.matrix, td->smtx, tmat);
+ }
+ }
+ }
+
+ /* copy results from cob->matrix */
+ if (td->flag & TD_USEQUAT) {
+ /* quats */
+ Mat4ToQuat(cob.matrix, td->ext->quat);
+ }
+ else if (td->tdi) {
+ /* ipo-keys eulers */
+ TransDataIpokey *tdi= td->tdi;
+ float eul[3];
+
+ Mat4ToEul(cob.matrix, eul);
+
+ tdi->rotx[0]= eul[0];
+ tdi->roty[0]= eul[1];
+ tdi->rotz[0]= eul[2];
+ }
+ else {
+ /* eulers */
+ Mat4ToEul(cob.matrix, td->ext->rot);
+ }
+ }
+}
+
+static void constraintSizeLim(TransInfo *t, TransData *td)
+{
+ if (td->con && td->ext) {
+ bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_SIZELIMIT);
+ bConstraintOb cob;
+ bConstraint *con;
+
+ /* Make a temporary bConstraintOb for using these limit constraints
+ * - they only care that cob->matrix is correctly set ;-)
+ * - current space should be local
+ */
+ memset(&cob, 0, sizeof(bConstraintOb));
+ if (td->tdi) {
+ TransDataIpokey *tdi= td->tdi;
+ float size[3];
+
+ size[0]= tdi->sizex[0];
+ size[1]= tdi->sizey[0];
+ size[2]= tdi->sizez[0];
+ SizeToMat4(size, cob.matrix);
+ }
+ else if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
+ /* scale val and reset size */
+ return; // TODO: fix this case
+ }
+ else {
+ /* Reset val if SINGLESIZE but using a constraint */
+ if (td->flag & TD_SINGLESIZE)
+ return;
+
+ SizeToMat4(td->ext->size, cob.matrix);
+ }
+
+ /* Evaluate valid constraints */
+ for (con= td->con; con; con= con->next) {
+ /* only consider constraint if enabled */
+ if (con->flag & CONSTRAINT_DISABLE) continue;
+ if (con->enforce == 0.0f) continue;
+
+ /* we're only interested in Limit-Scale constraints */
+ if (con->type == CONSTRAINT_TYPE_SIZELIMIT) {
+ bSizeLimitConstraint *data= con->data;
+ float tmat[4][4];
+
+ /* only use it if it's tagged for this purpose */
+ if ((data->flag2 & LIMIT_TRANSFORM)==0)
+ continue;
+
+ /* do space conversions */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->mtx (this should be ok) */
+ Mat4CpyMat4(tmat, cob.matrix);
+ Mat4MulMat34(cob.matrix, td->mtx, tmat);
+ }
+ else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
+ /* skip... incompatable spacetype */
+ continue;
+ }
+
+ /* do constraint */
+ cti->evaluate_constraint(con, &cob, NULL);
+
+ /* convert spaces again */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->mtx (this should be ok) */
+ Mat4CpyMat4(tmat, cob.matrix);
+ Mat4MulMat34(cob.matrix, td->smtx, tmat);
+ }
+ }
+ }
+
+ /* copy results from cob->matrix */
+ if (td->tdi) {
+ TransDataIpokey *tdi= td->tdi;
+ float size[3];
+
+ Mat4ToSize(cob.matrix, size);
+
+ tdi->sizex[0]= size[0];
+ tdi->sizey[0]= size[1];
+ tdi->sizez[0]= size[2];
+ }
+ else if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
+ /* scale val and reset size */
+ return; // TODO: fix this case
+ }
+ else {
+ /* Reset val if SINGLESIZE but using a constraint */
+ if (td->flag & TD_SINGLESIZE)
+ return;
+
+ Mat4ToSize(cob.matrix, td->ext->size);
+ }
+ }
+}
+
+/* ************************** WARP *************************** */
+
+void initWarp(TransInfo *t)
+{
+ float max[3], min[3];
+ int i;
+
+ t->mode = TFM_WARP;
+ t->transform = Warp;
+ t->handleEvent = handleEventWarp;
+
+ initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 5.0f;
+ t->snap[2] = 1.0f;
+
+ t->flag |= T_NO_CONSTRAINT;
+
+ /* we need min/max in view space */
+ for(i = 0; i < t->total; i++) {
+ float center[3];
+ VECCOPY(center, t->data[i].center);
+ Mat3MulVecfl(t->data[i].mtx, center);
+ Mat4MulVecfl(t->viewmat, center);
+ VecSubf(center, center, t->viewmat[3]);
+ if (i)
+ MinMax3(min, max, center);
+ else {
+ VECCOPY(max, center);
+ VECCOPY(min, center);
+ }
+ }
+
+ t->center[0]= (min[0]+max[0])/2.0f;
+ t->center[1]= (min[1]+max[1])/2.0f;
+ t->center[2]= (min[2]+max[2])/2.0f;
+
+ if (max[0] == min[0]) max[0] += 0.1; /* not optimal, but flipping is better than invalid garbage (i.e. division by zero!) */
+ t->val= (max[0]-min[0])/2.0f; /* t->val is X dimension projected boundbox */
+}
+
+int handleEventWarp(TransInfo *t, wmEvent *event)
+{
+ int status = 0;
+
+ if (event->type == MIDDLEMOUSE && event->val)
+ {
+ // Use customData pointer to signal warp direction
+ if (t->customData == 0)
+ t->customData = (void*)1;
+ else
+ t->customData = 0;
+
+ status = 1;
+ }
+
+ return status;
+}
+
+int Warp(TransInfo *t, short mval[2])
+{
+ TransData *td = t->data;
+ float vec[3], circumfac, dist, phi0, co, si, *curs, cursor[3], gcursor[3];
+ int i;
+ char str[50];
+
+ curs= give_cursor(t->scene, t->view);
+ /*
+ * gcursor is the one used for helpline.
+ * It has to be in the same space as the drawing loop
+ * (that means it needs to be in the object's space when in edit mode and
+ * in global space in object mode)
+ *
+ * cursor is used for calculations.
+ * It needs to be in view space, but we need to take object's offset
+ * into account if in Edit mode.
+ */
+ VECCOPY(cursor, curs);
+ VECCOPY(gcursor, cursor);
+ if (t->flag & T_EDIT) {
+ VecSubf(cursor, cursor, t->obedit->obmat[3]);
+ VecSubf(gcursor, gcursor, t->obedit->obmat[3]);
+ Mat3MulVecfl(t->data->smtx, gcursor);
+ }
+ Mat4MulVecfl(t->viewmat, cursor);
+ VecSubf(cursor, cursor, t->viewmat[3]);
+
+ /* amount of degrees for warp */
+ circumfac = 360.0f * t->values[0];
+
+ if (t->customData) /* non-null value indicates reversed input */
+ {
+ circumfac *= -1;
+ }
+
+ snapGrid(t, &circumfac);
+ applyNumInput(&t->num, &circumfac);
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[20];
+
+ outputNumInput(&(t->num), c);
+
+ sprintf(str, "Warp: %s", c);
+ }
+ else {
+ /* default header print */
+ sprintf(str, "Warp: %.3f", circumfac);
+ }
+
+ circumfac*= (float)(-M_PI/360.0);
+
+ for(i = 0; i < t->total; i++, td++) {
+ float loc[3];
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ /* translate point to center, rotate in such a way that outline==distance */
+ VECCOPY(vec, td->iloc);
+ Mat3MulVecfl(td->mtx, vec);
+ Mat4MulVecfl(t->viewmat, vec);
+ VecSubf(vec, vec, t->viewmat[3]);
+
+ dist= vec[0]-cursor[0];
+
+ /* t->val is X dimension projected boundbox */
+ phi0= (circumfac*dist/t->val);
+
+ vec[1]= (vec[1]-cursor[1]);
+
+ co= (float)cos(phi0);
+ si= (float)sin(phi0);
+ loc[0]= -si*vec[1]+cursor[0];
+ loc[1]= co*vec[1]+cursor[1];
+ loc[2]= vec[2];
+
+ Mat4MulVecfl(t->viewinv, loc);
+ VecSubf(loc, loc, t->viewinv[3]);
+ Mat3MulVecfl(td->smtx, loc);
+
+ VecSubf(loc, loc, td->iloc);
+ VecMulf(loc, td->factor);
+ VecAddf(td->loc, td->iloc, loc);
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ helpline(t, gcursor);
+
+ return 1;
+}
+
+/* ************************** SHEAR *************************** */
+
+void initShear(TransInfo *t)
+{
+ t->mode = TFM_SHEAR;
+ t->transform = Shear;
+ t->handleEvent = handleEventShear;
+
+ initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ t->flag |= T_NO_CONSTRAINT;
+}
+
+int handleEventShear(TransInfo *t, wmEvent *event)
+{
+ int status = 0;
+
+ if (event->type == MIDDLEMOUSE && event->val)
+ {
+ // Use customData pointer to signal Shear direction
+ if (t->customData == 0)
+ {
+ initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
+ t->customData = (void*)1;
+ }
+ else
+ {
+ initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
+ t->customData = 0;
+ }
+
+ status = 1;
+ }
+
+ return status;
+}
+
+
+int Shear(TransInfo *t, short mval[2])
+{
+ TransData *td = t->data;
+ float vec[3];
+ float smat[3][3], tmat[3][3], totmat[3][3], persmat[3][3], persinv[3][3];
+ float value;
+ int i;
+ char str[50];
+
+ Mat3CpyMat4(persmat, t->viewmat);
+ Mat3Inv(persinv, persmat);
+
+ value = 0.05f * t->values[0];
+
+ snapGrid(t, &value);
+
+ applyNumInput(&t->num, &value);
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[20];
+
+ outputNumInput(&(t->num), c);
+
+ sprintf(str, "Shear: %s %s", c, t->proptext);
+ }
+ else {
+ /* default header print */
+ sprintf(str, "Shear: %.3f %s", value, t->proptext);
+ }
+
+ Mat3One(smat);
+
+ // Custom data signals shear direction
+ if (t->customData == 0)
+ smat[1][0] = value;
+ else
+ smat[0][1] = value;
+
+ Mat3MulMat3(tmat, smat, persmat);
+ Mat3MulMat3(totmat, persinv, tmat);
+
+ for(i = 0 ; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if (t->obedit) {
+ float mat3[3][3];
+ Mat3MulMat3(mat3, totmat, td->mtx);
+ Mat3MulMat3(tmat, td->smtx, mat3);
+ }
+ else {
+ Mat3CpyMat3(tmat, totmat);
+ }
+ VecSubf(vec, td->center, t->center);
+
+ Mat3MulVecfl(tmat, vec);
+
+ VecAddf(vec, vec, t->center);
+ VecSubf(vec, vec, td->center);
+
+ VecMulf(vec, td->factor);
+
+ VecAddf(td->loc, td->iloc, vec);
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ helpline (t, t->center);
+
+ return 1;
+}
+
+/* ************************** RESIZE *************************** */
+
+void initResize(TransInfo *t)
+{
+ t->mode = TFM_RESIZE;
+ t->transform = Resize;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+
+ t->flag |= T_NULL_ONE;
+ t->num.flag |= NUM_NULL_ONE;
+ t->num.flag |= NUM_AFFECT_ALL;
+ if (!t->obedit) {
+ t->flag |= T_NO_ZERO;
+ t->num.flag |= NUM_NO_ZERO;
+ }
+
+ t->idx_max = 2;
+ t->num.idx_max = 2;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+}
+
+static void headerResize(TransInfo *t, float vec[3], char *str) {
+ char tvec[60];
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec);
+ }
+ else {
+ sprintf(&tvec[0], "%.4f", vec[0]);
+ sprintf(&tvec[20], "%.4f", vec[1]);
+ sprintf(&tvec[40], "%.4f", vec[2]);
+ }
+
+ if (t->con.mode & CON_APPLY) {
+ switch(t->num.idx_max) {
+ case 0:
+ sprintf(str, "Scale: %s%s %s", &tvec[0], t->con.text, t->proptext);
+ break;
+ case 1:
+ sprintf(str, "Scale: %s : %s%s %s", &tvec[0], &tvec[20], t->con.text, t->proptext);
+ break;
+ case 2:
+ sprintf(str, "Scale: %s : %s : %s%s %s", &tvec[0], &tvec[20], &tvec[40], t->con.text, t->proptext);
+ }
+ }
+ else {
+ if (t->flag & T_2D_EDIT)
+ sprintf(str, "Scale X: %s Y: %s%s %s", &tvec[0], &tvec[20], t->con.text, t->proptext);
+ else
+ sprintf(str, "Scale X: %s Y: %s Z: %s%s %s", &tvec[0], &tvec[20], &tvec[40], t->con.text, t->proptext);
+ }
+}
+
+#define SIGN(a) (a<-FLT_EPSILON?1:a>FLT_EPSILON?2:3)
+#define VECSIGNFLIP(a, b) ((SIGN(a[0]) & SIGN(b[0]))==0 || (SIGN(a[1]) & SIGN(b[1]))==0 || (SIGN(a[2]) & SIGN(b[2]))==0)
+
+/* smat is reference matrix, only scaled */
+static void TransMat3ToSize( float mat[][3], float smat[][3], float *size)
+{
+ float vec[3];
+
+ VecCopyf(vec, mat[0]);
+ size[0]= Normalize(vec);
+ VecCopyf(vec, mat[1]);
+ size[1]= Normalize(vec);
+ VecCopyf(vec, mat[2]);
+ size[2]= Normalize(vec);
+
+ /* first tried with dotproduct... but the sign flip is crucial */
+ if( VECSIGNFLIP(mat[0], smat[0]) ) size[0]= -size[0];
+ if( VECSIGNFLIP(mat[1], smat[1]) ) size[1]= -size[1];
+ if( VECSIGNFLIP(mat[2], smat[2]) ) size[2]= -size[2];
+}
+
+
+static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) {
+ float tmat[3][3], smat[3][3], center[3];
+ float vec[3];
+
+ if (t->flag & T_EDIT) {
+ Mat3MulMat3(smat, mat, td->mtx);
+ Mat3MulMat3(tmat, td->smtx, smat);
+ }
+ else {
+ Mat3CpyMat3(tmat, mat);
+ }
+
+ if (t->con.applySize) {
+ t->con.applySize(t, td, tmat);
+ }
+
+ /* local constraint shouldn't alter center */
+ if (t->around == V3D_LOCAL) {
+ if (t->flag & T_OBJECT) {
+ VECCOPY(center, td->center);
+ }
+ else if (t->flag & T_EDIT) {
+
+ if(t->around==V3D_LOCAL && (t->scene->selectmode & SCE_SELECT_FACE)) {
+ VECCOPY(center, td->center);
+ }
+ else {
+ VECCOPY(center, t->center);
+ }
+ }
+ else {
+ VECCOPY(center, t->center);
+ }
+ }
+ else {
+ VECCOPY(center, t->center);
+ }
+
+ if (td->ext) {
+ float fsize[3];
+
+ if (t->flag & (T_OBJECT|T_TEXTURE|T_POSE)) {
+ float obsizemat[3][3];
+ // Reorient the size mat to fit the oriented object.
+ Mat3MulMat3(obsizemat, tmat, td->axismtx);
+ //printmatrix3("obsizemat", obsizemat);
+ TransMat3ToSize(obsizemat, td->axismtx, fsize);
+ //printvecf("fsize", fsize);
+ }
+ else {
+ Mat3ToSize(tmat, fsize);
+ }
+
+ protectedSizeBits(td->protectflag, fsize);
+
+ if ((t->flag & T_V3D_ALIGN)==0) { // align mode doesn't resize objects itself
+ /* handle ipokeys? */
+ if(td->tdi) {
+ TransDataIpokey *tdi= td->tdi;
+ /* calculate delta size (equal for size and dsize) */
+
+ vec[0]= (tdi->oldsize[0])*(fsize[0] -1.0f) * td->factor;
+ vec[1]= (tdi->oldsize[1])*(fsize[1] -1.0f) * td->factor;
+ vec[2]= (tdi->oldsize[2])*(fsize[2] -1.0f) * td->factor;
+
+ add_tdi_poin(tdi->sizex, tdi->oldsize, vec[0]);
+ add_tdi_poin(tdi->sizey, tdi->oldsize+1, vec[1]);
+ add_tdi_poin(tdi->sizez, tdi->oldsize+2, vec[2]);
+
+ }
+ else if((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)){
+ /* scale val and reset size */
+ *td->val = td->ival * fsize[0] * td->factor;
+
+ td->ext->size[0] = td->ext->isize[0];
+ td->ext->size[1] = td->ext->isize[1];
+ td->ext->size[2] = td->ext->isize[2];
+ }
+ else {
+ /* Reset val if SINGLESIZE but using a constraint */
+ if (td->flag & TD_SINGLESIZE)
+ *td->val = td->ival;
+
+ td->ext->size[0] = td->ext->isize[0] * (fsize[0]) * td->factor;
+ td->ext->size[1] = td->ext->isize[1] * (fsize[1]) * td->factor;
+ td->ext->size[2] = td->ext->isize[2] * (fsize[2]) * td->factor;
+ }
+ }
+
+ constraintSizeLim(t, td);
+ }
+
+ /* For individual element center, Editmode need to use iloc */
+ if (t->flag & T_POINTS)
+ VecSubf(vec, td->iloc, center);
+ else
+ VecSubf(vec, td->center, center);
+
+ Mat3MulVecfl(tmat, vec);
+
+ VecAddf(vec, vec, center);
+ if (t->flag & T_POINTS)
+ VecSubf(vec, vec, td->iloc);
+ else
+ VecSubf(vec, vec, td->center);
+
+ VecMulf(vec, td->factor);
+
+ if (t->flag & (T_OBJECT|T_POSE)) {
+ Mat3MulVecfl(td->smtx, vec);
+ }
+
+ protectedTransBits(td->protectflag, vec);
+
+ if(td->tdi) {
+ TransDataIpokey *tdi= td->tdi;
+ add_tdi_poin(tdi->locx, tdi->oldloc, vec[0]);
+ add_tdi_poin(tdi->locy, tdi->oldloc+1, vec[1]);
+ add_tdi_poin(tdi->locz, tdi->oldloc+2, vec[2]);
+ }
+ else VecAddf(td->loc, td->iloc, vec);
+
+ constraintTransLim(t, td);
+}
+
+int Resize(TransInfo *t, short mval[2])
+{
+ TransData *td;
+ float size[3], mat[3][3];
+ float ratio;
+ int i;
+ char str[200];
+
+ /* for manipulator, center handle, the scaling can't be done relative to center */
+ if( (t->flag & T_USES_MANIPULATOR) && t->con.mode==0)
+ {
+ ratio = 1.0f - ((t->imval[0] - mval[0]) + (t->imval[1] - mval[1]))/100.0f;
+ }
+ else
+ {
+ ratio = t->values[0];
+ }
+
+ size[0] = size[1] = size[2] = ratio;
+
+ snapGrid(t, size);
+
+ if (hasNumInput(&t->num)) {
+ applyNumInput(&t->num, size);
+ constraintNumInput(t, size);
+ }
+
+ applySnapping(t, size);
+
+ if (t->flag & T_AUTOVALUES)
+ {
+ VECCOPY(size, t->auto_values);
+ }
+
+ VECCOPY(t->values, size);
+
+ SizeToMat3(size, mat);
+
+ if (t->con.applySize) {
+ t->con.applySize(t, NULL, mat);
+ }
+
+ Mat3CpyMat3(t->mat, mat); // used in manipulator
+
+ headerResize(t, size, str);
+
+ for(i = 0, td=t->data; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ ElementResize(t, td, mat);
+ }
+
+ /* evil hack - redo resize if cliping needed */
+ if (t->flag & T_CLIP_UV && clipUVTransform(t, size, 1)) {
+ SizeToMat3(size, mat);
+
+ if (t->con.applySize)
+ t->con.applySize(t, NULL, mat);
+
+ for(i = 0, td=t->data; i < t->total; i++, td++)
+ ElementResize(t, td, mat);
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
+
+ return 1;
+}
+
+/* ************************** TOSPHERE *************************** */
+
+void initToSphere(TransInfo *t)
+{
+ TransData *td = t->data;
+ int i;
+
+ t->mode = TFM_TOSPHERE;
+ t->transform = ToSphere;
+
+ initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ t->num.flag |= NUM_NULL_ONE | NUM_NO_NEGATIVE;
+ t->flag |= T_NO_CONSTRAINT;
+
+ // Calculate average radius
+ for(i = 0 ; i < t->total; i++, td++) {
+ t->val += VecLenf(t->center, td->iloc);
+ }
+
+ t->val /= (float)t->total;
+}
+
+int ToSphere(TransInfo *t, short mval[2])
+{
+ float vec[3];
+ float ratio, radius;
+ int i;
+ char str[64];
+ TransData *td = t->data;
+
+ ratio = t->values[0];
+
+ snapGrid(t, &ratio);
+
+ applyNumInput(&t->num, &ratio);
+
+ if (ratio < 0)
+ ratio = 0.0f;
+ else if (ratio > 1)
+ ratio = 1.0f;
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[20];
+
+ outputNumInput(&(t->num), c);
+
+ sprintf(str, "To Sphere: %s %s", c, t->proptext);
+ }
+ else {
+ /* default header print */
+ sprintf(str, "To Sphere: %.4f %s", ratio, t->proptext);
+ }
+
+
+ for(i = 0 ; i < t->total; i++, td++) {
+ float tratio;
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ VecSubf(vec, td->iloc, t->center);
+
+ radius = Normalize(vec);
+
+ tratio = ratio * td->factor;
+
+ VecMulf(vec, radius * (1.0f - tratio) + t->val * tratio);
+
+ VecAddf(td->loc, t->center, vec);
+ }
+
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ return 1;
+}
+
+/* ************************** ROTATION *************************** */
+
+
+void initRotation(TransInfo *t)
+{
+ t->mode = TFM_ROTATION;
+ t->transform = Rotation;
+
+ initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+
+ t->ndof.axis = 16;
+ /* Scale down and flip input for rotation */
+ t->ndof.factor[0] = -0.2f;
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = (float)((5.0/180)*M_PI);
+ t->snap[2] = t->snap[1] * 0.2f;
+
+ if (t->flag & T_2D_EDIT)
+ t->flag |= T_NO_CONSTRAINT;
+}
+
+static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short around) {
+ float vec[3], totmat[3][3], smat[3][3];
+ float eul[3], fmat[3][3], quat[4];
+ float *center = t->center;
+
+ /* local constraint shouldn't alter center */
+ if (around == V3D_LOCAL) {
+ if (t->flag & (T_OBJECT|T_POSE)) {
+ center = td->center;
+ }
+ else {
+ /* !TODO! Make this if not rely on G */
+ if(around==V3D_LOCAL && (t->scene->selectmode & SCE_SELECT_FACE)) {
+ center = td->center;
+ }
+ }
+ }
+
+ if (t->flag & T_POINTS) {
+ Mat3MulMat3(totmat, mat, td->mtx);
+ Mat3MulMat3(smat, td->smtx, totmat);
+
+ VecSubf(vec, td->iloc, center);
+ Mat3MulVecfl(smat, vec);
+
+ VecAddf(td->loc, vec, center);
+
+ VecSubf(vec,td->loc,td->iloc);
+ protectedTransBits(td->protectflag, vec);
+ VecAddf(td->loc, td->iloc, vec);
+
+ if(td->flag & TD_USEQUAT) {
+ Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
+ Mat3ToQuat(fmat, quat); // Actual transform
+
+ if(td->ext->quat){
+ QuatMul(td->ext->quat, quat, td->ext->iquat);
+
+ /* is there a reason not to have this here? -jahka */
+ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
+ }
+ }
+ }
+ /**
+ * HACK WARNING
+ *
+ * This is some VERY ugly special case to deal with pose mode.
+ *
+ * The problem is that mtx and smtx include each bone orientation.
+ *
+ * That is needed to rotate each bone properly, HOWEVER, to calculate
+ * the translation component, we only need the actual armature object's
+ * matrix (and inverse). That is not all though. Once the proper translation
+ * has been computed, it has to be converted back into the bone's space.
+ */
+ else if (t->flag & T_POSE) {
+ float pmtx[3][3], imtx[3][3];
+
+ // Extract and invert armature object matrix
+ Mat3CpyMat4(pmtx, t->poseobj->obmat);
+ Mat3Inv(imtx, pmtx);
+
+ if ((td->flag & TD_NO_LOC) == 0)
+ {
+ VecSubf(vec, td->center, center);
+
+ Mat3MulVecfl(pmtx, vec); // To Global space
+ Mat3MulVecfl(mat, vec); // Applying rotation
+ Mat3MulVecfl(imtx, vec); // To Local space
+
+ VecAddf(vec, vec, center);
+ /* vec now is the location where the object has to be */
+
+ VecSubf(vec, vec, td->center); // Translation needed from the initial location
+
+ Mat3MulVecfl(pmtx, vec); // To Global space
+ Mat3MulVecfl(td->smtx, vec);// To Pose space
+
+ protectedTransBits(td->protectflag, vec);
+
+ VecAddf(td->loc, td->iloc, vec);
+
+ constraintTransLim(t, td);
+ }
+
+ /* rotation */
+ if ((t->flag & T_V3D_ALIGN)==0) { // align mode doesn't rotate objects itself
+ /* euler or quaternion? */
+ if (td->flag & TD_USEQUAT) {
+ Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
+
+ Mat3ToQuat(fmat, quat); // Actual transform
+
+ QuatMul(td->ext->quat, quat, td->ext->iquat);
+ /* this function works on end result */
+ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
+ }
+ else {
+ float eulmat[3][3];
+
+ Mat3MulMat3(totmat, mat, td->mtx);
+ Mat3MulMat3(smat, td->smtx, totmat);
+
+ /* calculate the total rotatation in eulers */
+ VECCOPY(eul, td->ext->irot);
+ EulToMat3(eul, eulmat);
+
+ /* mat = transform, obmat = bone rotation */
+ Mat3MulMat3(fmat, smat, eulmat);
+
+ Mat3ToCompatibleEul(fmat, eul, td->ext->rot);
+
+ /* and apply (to end result only) */
+ protectedRotateBits(td->protectflag, eul, td->ext->irot);
+ VECCOPY(td->ext->rot, eul);
+ }
+
+ constraintRotLim(t, td);
+ }
+ }
+ else {
+ if ((td->flag & TD_NO_LOC) == 0)
+ {
+ /* translation */
+ VecSubf(vec, td->center, center);
+ Mat3MulVecfl(mat, vec);
+ VecAddf(vec, vec, center);
+ /* vec now is the location where the object has to be */
+ VecSubf(vec, vec, td->center);
+ Mat3MulVecfl(td->smtx, vec);
+
+ protectedTransBits(td->protectflag, vec);
+
+ if(td->tdi) {
+ TransDataIpokey *tdi= td->tdi;
+ add_tdi_poin(tdi->locx, tdi->oldloc, vec[0]);
+ add_tdi_poin(tdi->locy, tdi->oldloc+1, vec[1]);
+ add_tdi_poin(tdi->locz, tdi->oldloc+2, vec[2]);
+ }
+ else VecAddf(td->loc, td->iloc, vec);
+ }
+
+
+ constraintTransLim(t, td);
+
+ /* rotation */
+ if ((t->flag & T_V3D_ALIGN)==0) { // align mode doesn't rotate objects itself
+ /* euler or quaternion? */
+ if (td->flag & TD_USEQUAT) {
+ Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
+ Mat3ToQuat(fmat, quat); // Actual transform
+
+ QuatMul(td->ext->quat, quat, td->ext->iquat);
+ /* this function works on end result */
+ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
+ }
+ else {
+ float obmat[3][3];
+
+ /* are there ipo keys? */
+ if(td->tdi) {
+ TransDataIpokey *tdi= td->tdi;
+ float current_rot[3];
+ float rot[3];
+
+ /* current IPO value for compatible euler */
+ current_rot[0] = (tdi->rotx) ? tdi->rotx[0] : 0.0f;
+ current_rot[1] = (tdi->roty) ? tdi->roty[0] : 0.0f;
+ current_rot[2] = (tdi->rotz) ? tdi->rotz[0] : 0.0f;
+ VecMulf(current_rot, (float)(M_PI_2 / 9.0));
+
+ /* calculate the total rotatation in eulers */
+ VecAddf(eul, td->ext->irot, td->ext->drot);
+ EulToMat3(eul, obmat);
+ /* mat = transform, obmat = object rotation */
+ Mat3MulMat3(fmat, mat, obmat);
+
+ Mat3ToCompatibleEul(fmat, eul, current_rot);
+
+ /* correct back for delta rot */
+ if(tdi->flag & TOB_IPODROT) {
+ VecSubf(rot, eul, td->ext->irot);
+ }
+ else {
+ VecSubf(rot, eul, td->ext->drot);
+ }
+
+ VecMulf(rot, (float)(9.0/M_PI_2));
+ VecSubf(rot, rot, tdi->oldrot);
+
+ protectedRotateBits(td->protectflag, rot, tdi->oldrot);
+
+ add_tdi_poin(tdi->rotx, tdi->oldrot, rot[0]);
+ add_tdi_poin(tdi->roty, tdi->oldrot+1, rot[1]);
+ add_tdi_poin(tdi->rotz, tdi->oldrot+2, rot[2]);
+ }
+ else {
+ Mat3MulMat3(totmat, mat, td->mtx);
+ Mat3MulMat3(smat, td->smtx, totmat);
+
+ /* calculate the total rotatation in eulers */
+ VecAddf(eul, td->ext->irot, td->ext->drot); /* we have to correct for delta rot */
+ EulToMat3(eul, obmat);
+ /* mat = transform, obmat = object rotation */
+ Mat3MulMat3(fmat, smat, obmat);
+
+ Mat3ToCompatibleEul(fmat, eul, td->ext->rot);
+
+ /* correct back for delta rot */
+ VecSubf(eul, eul, td->ext->drot);
+
+ /* and apply */
+ protectedRotateBits(td->protectflag, eul, td->ext->irot);
+ VECCOPY(td->ext->rot, eul);
+ }
+ }
+
+ constraintRotLim(t, td);
+ }
+ }
+}
+
+static void applyRotation(TransInfo *t, float angle, float axis[3])
+{
+ TransData *td = t->data;
+ float mat[3][3];
+ int i;
+
+ VecRotToMat3(axis, angle, mat);
+
+ for(i = 0 ; i < t->total; i++, td++) {
+
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if (t->con.applyRot) {
+ t->con.applyRot(t, td, axis, NULL);
+ VecRotToMat3(axis, angle * td->factor, mat);
+ }
+ else if (t->flag & T_PROP_EDIT) {
+ VecRotToMat3(axis, angle * td->factor, mat);
+ }
+
+ ElementRotation(t, td, mat, t->around);
+ }
+}
+
+int Rotation(TransInfo *t, short mval[2])
+{
+ char str[64];
+
+ float final;
+
+ float axis[3];
+ float mat[3][3];
+
+ VECCOPY(axis, t->viewinv[2]);
+ VecMulf(axis, -1.0f);
+ Normalize(axis);
+
+ final = t->values[0];
+
+ applyNDofInput(&t->ndof, &final);
+
+ snapGrid(t, &final);
+
+ if (t->con.applyRot) {
+ t->con.applyRot(t, NULL, axis, &final);
+ }
+
+ applySnapping(t, &final);
+
+ if (hasNumInput(&t->num)) {
+ char c[20];
+
+ applyNumInput(&t->num, &final);
+
+ outputNumInput(&(t->num), c);
+
+ sprintf(str, "Rot: %s %s %s", &c[0], t->con.text, t->proptext);
+
+ /* Clamp between -180 and 180 */
+ while (final >= 180.0)
+ final -= 360.0;
+
+ while (final <= -180.0)
+ final += 360.0;
+
+ final *= (float)(M_PI / 180.0);
+ }
+ else {
+ sprintf(str, "Rot: %.2f%s %s", 180.0*final/M_PI, t->con.text, t->proptext);
+ }
+
+ VecRotToMat3(axis, final, mat);
+
+ // TRANSFORM_FIX_ME
+// t->values[0] = final; // used in manipulator
+// Mat3CpyMat3(t->mat, mat); // used in manipulator
+
+ applyRotation(t, final, axis);
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
+
+ return 1;
+}
+
+
+/* ************************** TRACKBALL *************************** */
+
+void initTrackball(TransInfo *t)
+{
+ t->mode = TFM_TRACKBALL;
+ t->transform = Trackball;
+
+ initMouseInputMode(t, &t->mouse, INPUT_TRACKBALL);
+
+ t->ndof.axis = 40;
+ /* Scale down input for rotation */
+ t->ndof.factor[0] = 0.2f;
+ t->ndof.factor[1] = 0.2f;
+
+ t->idx_max = 1;
+ t->num.idx_max = 1;
+ t->snap[0] = 0.0f;
+ t->snap[1] = (float)((5.0/180)*M_PI);
+ t->snap[2] = t->snap[1] * 0.2f;
+
+ t->flag |= T_NO_CONSTRAINT;
+}
+
+static void applyTrackball(TransInfo *t, float axis1[3], float axis2[3], float angles[2])
+{
+ TransData *td = t->data;
+ float mat[3][3], smat[3][3], totmat[3][3];
+ int i;
+
+ VecRotToMat3(axis1, angles[0], smat);
+ VecRotToMat3(axis2, angles[1], totmat);
+
+ Mat3MulMat3(mat, smat, totmat);
+
+ for(i = 0 ; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if (t->flag & T_PROP_EDIT) {
+ VecRotToMat3(axis1, td->factor * angles[0], smat);
+ VecRotToMat3(axis2, td->factor * angles[1], totmat);
+
+ Mat3MulMat3(mat, smat, totmat);
+ }
+
+ ElementRotation(t, td, mat, t->around);
+ }
+}
+
+int Trackball(TransInfo *t, short mval[2])
+{
+ char str[128];
+ float axis1[3], axis2[3];
+ float mat[3][3], totmat[3][3], smat[3][3];
+ float phi[2];
+
+ VECCOPY(axis1, t->persinv[0]);
+ VECCOPY(axis2, t->persinv[1]);
+ Normalize(axis1);
+ Normalize(axis2);
+
+ phi[0] = t->values[0];
+ phi[1] = t->values[1];
+
+ applyNDofInput(&t->ndof, phi);
+
+ snapGrid(t, phi);
+
+ if (hasNumInput(&t->num)) {
+ char c[40];
+
+ applyNumInput(&t->num, phi);
+
+ outputNumInput(&(t->num), c);
+
+ sprintf(str, "Trackball: %s %s %s", &c[0], &c[20], t->proptext);
+
+ phi[0] *= (float)(M_PI / 180.0);
+ phi[1] *= (float)(M_PI / 180.0);
+ }
+ else {
+ sprintf(str, "Trackball: %.2f %.2f %s", 180.0*phi[0]/M_PI, 180.0*phi[1]/M_PI, t->proptext);
+ }
+
+ VecRotToMat3(axis1, phi[0], smat);
+ VecRotToMat3(axis2, phi[1], totmat);
+
+ Mat3MulMat3(mat, smat, totmat);
+
+ // TRANSFORM_FIX_ME
+ //Mat3CpyMat3(t->mat, mat); // used in manipulator
+
+ applyTrackball(t, axis1, axis2, phi);
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
+
+ return 1;
+}
+
+/* ************************** TRANSLATION *************************** */
+
+void initTranslation(TransInfo *t)
+{
+ t->mode = TFM_TRANSLATION;
+ t->transform = Translation;
+
+ initMouseInputMode(t, &t->mouse, INPUT_VECTOR);
+
+ t->idx_max = (t->flag & T_2D_EDIT)? 1: 2;
+ t->num.flag = 0;
+ t->num.idx_max = t->idx_max;
+
+ t->ndof.axis = (t->flag & T_2D_EDIT)? 1|2: 1|2|4;
+
+ if(t->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = t->view;
+
+ t->snap[0] = 0.0f;
+ t->snap[1] = v3d->gridview * 1.0f;
+ t->snap[2] = t->snap[1] * 0.1f;
+ }
+ else if(t->spacetype == SPACE_IMAGE) {
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.125f;
+ t->snap[2] = 0.0625f;
+ }
+ else {
+ t->snap[0] = 0.0f;
+ t->snap[1] = t->snap[2] = 1.0f;
+ }
+}
+
+static void headerTranslation(TransInfo *t, float vec[3], char *str) {
+ char tvec[60];
+ char distvec[20];
+ char autoik[20];
+ float dist;
+
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec);
+ dist = VecLength(t->num.val);
+ }
+ else {
+ float dvec[3];
+
+ VECCOPY(dvec, vec);
+ applyAspectRatio(t, dvec);
+
+ dist = VecLength(vec);
+ sprintf(&tvec[0], "%.4f", dvec[0]);
+ sprintf(&tvec[20], "%.4f", dvec[1]);
+ sprintf(&tvec[40], "%.4f", dvec[2]);
+ }
+
+ if( dist > 1e10 || dist < -1e10 ) /* prevent string buffer overflow */
+ sprintf(distvec, "%.4e", dist);
+ else
+ sprintf(distvec, "%.4f", dist);
+
+ if(t->flag & T_AUTOIK) {
+ short chainlen= t->scene->toolsettings->autoik_chainlen;
+
+ if(chainlen)
+ sprintf(autoik, "AutoIK-Len: %d", chainlen);
+ else
+ strcpy(autoik, "");
+ }
+ else
+ strcpy(autoik, "");
+
+ if (t->con.mode & CON_APPLY) {
+ switch(t->num.idx_max) {
+ case 0:
+ sprintf(str, "D: %s (%s)%s %s %s", &tvec[0], distvec, t->con.text, t->proptext, &autoik[0]);
+ break;
+ case 1:
+ sprintf(str, "D: %s D: %s (%s)%s %s %s", &tvec[0], &tvec[20], distvec, t->con.text, t->proptext, &autoik[0]);
+ break;
+ case 2:
+ sprintf(str, "D: %s D: %s D: %s (%s)%s %s %s", &tvec[0], &tvec[20], &tvec[40], distvec, t->con.text, t->proptext, &autoik[0]);
+ }
+ }
+ else {
+ if(t->flag & T_2D_EDIT)
+ sprintf(str, "Dx: %s Dy: %s (%s)%s %s", &tvec[0], &tvec[20], distvec, t->con.text, t->proptext);
+ else
+ sprintf(str, "Dx: %s Dy: %s Dz: %s (%s)%s %s %s", &tvec[0], &tvec[20], &tvec[40], distvec, t->con.text, t->proptext, &autoik[0]);
+ }
+}
+
+static void applyTranslation(TransInfo *t, float vec[3]) {
+ TransData *td = t->data;
+ float tvec[3];
+ int i;
+
+ for(i = 0 ; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ /* handle snapping rotation before doing the translation */
+ if (usingSnappingNormal(t))
+ {
+ if (validSnappingNormal(t))
+ {
+ float *original_normal = td->axismtx[2];
+ float axis[3];
+ float quat[4];
+ float mat[3][3];
+ float angle;
+
+ Crossf(axis, original_normal, t->tsnap.snapNormal);
+ angle = saacos(Inpf(original_normal, t->tsnap.snapNormal));
+
+ AxisAngleToQuat(quat, axis, angle);
+
+ QuatToMat3(quat, mat);
+
+ ElementRotation(t, td, mat, V3D_LOCAL);
+ }
+ else
+ {
+ float mat[3][3];
+
+ Mat3One(mat);
+
+ ElementRotation(t, td, mat, V3D_LOCAL);
+ }
+ }
+
+ if (t->con.applyVec) {
+ float pvec[3];
+ t->con.applyVec(t, td, vec, tvec, pvec);
+ }
+ else {
+ VECCOPY(tvec, vec);
+ }
+
+ Mat3MulVecfl(td->smtx, tvec);
+ VecMulf(tvec, td->factor);
+
+ protectedTransBits(td->protectflag, tvec);
+
+ /* transdata ipokey */
+ if(td->tdi) {
+ TransDataIpokey *tdi= td->tdi;
+ add_tdi_poin(tdi->locx, tdi->oldloc, tvec[0]);
+ add_tdi_poin(tdi->locy, tdi->oldloc+1, tvec[1]);
+ add_tdi_poin(tdi->locz, tdi->oldloc+2, tvec[2]);
+ }
+ else VecAddf(td->loc, td->iloc, tvec);
+
+ constraintTransLim(t, td);
+ }
+}
+
+/* uses t->vec to store actual translation in */
+int Translation(TransInfo *t, short mval[2])
+{
+ float tvec[3];
+ char str[250];
+
+ if (t->con.mode & CON_APPLY) {
+ float pvec[3] = {0.0f, 0.0f, 0.0f};
+ applySnapping(t, t->values);
+ t->con.applyVec(t, NULL, t->values, tvec, pvec);
+ VECCOPY(t->values, tvec);
+ headerTranslation(t, pvec, str);
+ }
+ else {
+ applyNDofInput(&t->ndof, t->values);
+ snapGrid(t, t->values);
+ applyNumInput(&t->num, t->values);
+ if (hasNumInput(&t->num))
+ {
+ removeAspectRatio(t, t->values);
+ }
+
+ applySnapping(t, t->values);
+ headerTranslation(t, t->values, str);
+ }
+
+ applyTranslation(t, t->values);
+
+ /* evil hack - redo translation if clipping needed */
+ if (t->flag & T_CLIP_UV && clipUVTransform(t, t->values, 0))
+ applyTranslation(t, t->values);
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ return 1;
+}
+
+/* ************************** SHRINK/FATTEN *************************** */
+
+void initShrinkFatten(TransInfo *t)
+{
+ // If not in mesh edit mode, fallback to Resize
+ if (t->obedit==NULL || t->obedit->type != OB_MESH) {
+ initResize(t);
+ }
+ else {
+ t->mode = TFM_SHRINKFATTEN;
+ t->transform = ShrinkFatten;
+
+ initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 1.0f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ t->flag |= T_NO_CONSTRAINT;
+ }
+}
+
+
+
+int ShrinkFatten(TransInfo *t, short mval[2])
+{
+ float vec[3];
+ float distance;
+ int i;
+ char str[64];
+ TransData *td = t->data;
+
+ distance = -t->values[0];
+
+ snapGrid(t, &distance);
+
+ applyNumInput(&t->num, &distance);
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[20];
+
+ outputNumInput(&(t->num), c);
+
+ sprintf(str, "Shrink/Fatten: %s %s", c, t->proptext);
+ }
+ else {
+ /* default header print */
+ sprintf(str, "Shrink/Fatten: %.4f %s", distance, t->proptext);
+ }
+
+
+ for(i = 0 ; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ VECCOPY(vec, td->axismtx[2]);
+ VecMulf(vec, distance);
+ VecMulf(vec, td->factor);
+
+ VecAddf(td->loc, td->iloc, vec);
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ return 1;
+}
+
+/* ************************** TILT *************************** */
+
+void initTilt(TransInfo *t)
+{
+ t->mode = TFM_TILT;
+ t->transform = Tilt;
+
+ initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+
+ t->ndof.axis = 16;
+ /* Scale down and flip input for rotation */
+ t->ndof.factor[0] = -0.2f;
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = (float)((5.0/180)*M_PI);
+ t->snap[2] = t->snap[1] * 0.2f;
+
+ t->flag |= T_NO_CONSTRAINT;
+}
+
+
+
+int Tilt(TransInfo *t, short mval[2])
+{
+ TransData *td = t->data;
+ int i;
+ char str[50];
+
+ float final;
+
+ final = t->values[0];
+
+ applyNDofInput(&t->ndof, &final);
+
+ snapGrid(t, &final);
+
+ if (hasNumInput(&t->num)) {
+ char c[20];
+
+ applyNumInput(&t->num, &final);
+
+ outputNumInput(&(t->num), c);
+
+ sprintf(str, "Tilt: %s %s", &c[0], t->proptext);
+
+ final *= (float)(M_PI / 180.0);
+ }
+ else {
+ sprintf(str, "Tilt: %.2f %s", 180.0*final/M_PI, t->proptext);
+ }
+
+ for(i = 0 ; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if (td->val) {
+ *td->val = td->ival + final * td->factor;
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ helpline (t, t->center);
+
+ return 1;
+}
+
+
+/* ******************** Curve Shrink/Fatten *************** */
+
+void initCurveShrinkFatten(TransInfo *t)
+{
+ t->mode = TFM_CURVE_SHRINKFATTEN;
+ t->transform = CurveShrinkFatten;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ t->flag |= T_NO_CONSTRAINT;
+}
+
+int CurveShrinkFatten(TransInfo *t, short mval[2])
+{
+ TransData *td = t->data;
+ float ratio;
+ int i;
+ char str[50];
+
+ ratio = t->values[0];
+
+ snapGrid(t, &ratio);
+
+ applyNumInput(&t->num, &ratio);
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[20];
+
+ outputNumInput(&(t->num), c);
+ sprintf(str, "Shrink/Fatten: %s", c);
+ }
+ else {
+ sprintf(str, "Shrink/Fatten: %3f", ratio);
+ }
+
+ for(i = 0 ; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if(td->val) {
+ //*td->val= ratio;
+ *td->val= td->ival*ratio;
+ if (*td->val <= 0.0f) *td->val = 0.0001f;
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
+
+ return 1;
+}
+
+/* ************************** PUSH/PULL *************************** */
+
+void initPushPull(TransInfo *t)
+{
+ t->mode = TFM_PUSHPULL;
+ t->transform = PushPull;
+
+ initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
+
+ t->ndof.axis = 4;
+ /* Flip direction */
+ t->ndof.factor[0] = -1.0f;
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 1.0f;
+ t->snap[2] = t->snap[1] * 0.1f;
+}
+
+
+int PushPull(TransInfo *t, short mval[2])
+{
+ float vec[3], axis[3];
+ float distance;
+ int i;
+ char str[128];
+ TransData *td = t->data;
+
+ distance = t->values[0];
+
+ applyNDofInput(&t->ndof, &distance);
+
+ snapGrid(t, &distance);
+
+ applyNumInput(&t->num, &distance);
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[20];
+
+ outputNumInput(&(t->num), c);
+
+ sprintf(str, "Push/Pull: %s%s %s", c, t->con.text, t->proptext);
+ }
+ else {
+ /* default header print */
+ sprintf(str, "Push/Pull: %.4f%s %s", distance, t->con.text, t->proptext);
+ }
+
+ if (t->con.applyRot && t->con.mode & CON_APPLY) {
+ t->con.applyRot(t, NULL, axis, NULL);
+ }
+
+ for(i = 0 ; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ VecSubf(vec, t->center, td->center);
+ if (t->con.applyRot && t->con.mode & CON_APPLY) {
+ t->con.applyRot(t, td, axis, NULL);
+ if (isLockConstraint(t)) {
+ float dvec[3];
+ Projf(dvec, vec, axis);
+ VecSubf(vec, vec, dvec);
+ }
+ else {
+ Projf(vec, vec, axis);
+ }
+ }
+ Normalize(vec);
+ VecMulf(vec, distance);
+ VecMulf(vec, td->factor);
+
+ VecAddf(td->loc, td->iloc, vec);
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ return 1;
+}
+
+/* ************************** BEVEL **************************** */
+
+void initBevel(TransInfo *t)
+{
+ t->transform = Bevel;
+ t->handleEvent = handleEventBevel;
+
+ initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
+
+ t->mode = TFM_BEVEL;
+ t->flag |= T_NO_CONSTRAINT;
+ t->num.flag |= NUM_NO_NEGATIVE;
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ /* DON'T KNOW WHY THIS IS NEEDED */
+ if (G.editBMesh->imval[0] == 0 && G.editBMesh->imval[1] == 0) {
+ /* save the initial mouse co */
+ G.editBMesh->imval[0] = t->imval[0];
+ G.editBMesh->imval[1] = t->imval[1];
+ }
+ else {
+ /* restore the mouse co from a previous call to initTransform() */
+ t->imval[0] = G.editBMesh->imval[0];
+ t->imval[1] = G.editBMesh->imval[1];
+ }
+}
+
+int handleEventBevel(TransInfo *t, wmEvent *event)
+{
+ if (event->val) {
+ if(!G.editBMesh) return 0;
+
+ switch (event->type) {
+ case MIDDLEMOUSE:
+ G.editBMesh->options ^= BME_BEVEL_VERT;
+ t->state = TRANS_CANCEL;
+ return 1;
+ //case PADPLUSKEY:
+ // G.editBMesh->options ^= BME_BEVEL_RES;
+ // G.editBMesh->res += 1;
+ // if (G.editBMesh->res > 4) {
+ // G.editBMesh->res = 4;
+ // }
+ // t->state = TRANS_CANCEL;
+ // return 1;
+ //case PADMINUS:
+ // G.editBMesh->options ^= BME_BEVEL_RES;
+ // G.editBMesh->res -= 1;
+ // if (G.editBMesh->res < 0) {
+ // G.editBMesh->res = 0;
+ // }
+ // t->state = TRANS_CANCEL;
+ // return 1;
+ default:
+ return 0;
+ }
+ }
+ return 0;
+}
+
+int Bevel(TransInfo *t, short mval[2])
+{
+ float distance,d;
+ int i;
+ char str[128];
+ char *mode;
+ TransData *td = t->data;
+
+ mode = (G.editBMesh->options & BME_BEVEL_VERT) ? "verts only" : "normal";
+ distance = t->values[0] / 4; /* 4 just seemed a nice value to me, nothing special */
+
+ distance = fabs(distance);
+
+ snapGrid(t, &distance);
+
+ applyNumInput(&t->num, &distance);
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[20];
+
+ outputNumInput(&(t->num), c);
+
+ sprintf(str, "Bevel - Dist: %s, Mode: %s (MMB to toggle))", c, mode);
+ }
+ else {
+ /* default header print */
+ sprintf(str, "Bevel - Dist: %.4f, Mode: %s (MMB to toggle))", distance, mode);
+ }
+
+ if (distance < 0) distance = -distance;
+ for(i = 0 ; i < t->total; i++, td++) {
+ if (td->axismtx[1][0] > 0 && distance > td->axismtx[1][0]) {
+ d = td->axismtx[1][0];
+ }
+ else {
+ d = distance;
+ }
+ VECADDFAC(td->loc,td->center,td->axismtx[0],(*td->val)*d);
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ return 1;
+}
+
+/* ************************** BEVEL WEIGHT *************************** */
+
+void initBevelWeight(TransInfo *t)
+{
+ t->mode = TFM_BWEIGHT;
+ t->transform = BevelWeight;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ t->flag |= T_NO_CONSTRAINT;
+}
+
+int BevelWeight(TransInfo *t, short mval[2])
+{
+ TransData *td = t->data;
+ float weight;
+ int i;
+ char str[50];
+
+ weight = t->values[0];
+
+ weight -= 1.0f;
+ if (weight > 1.0f) weight = 1.0f;
+
+ snapGrid(t, &weight);
+
+ applyNumInput(&t->num, &weight);
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[20];
+
+ outputNumInput(&(t->num), c);
+
+ if (weight >= 0.0f)
+ sprintf(str, "Bevel Weight: +%s %s", c, t->proptext);
+ else
+ sprintf(str, "Bevel Weight: %s %s", c, t->proptext);
+ }
+ else {
+ /* default header print */
+ if (weight >= 0.0f)
+ sprintf(str, "Bevel Weight: +%.3f %s", weight, t->proptext);
+ else
+ sprintf(str, "Bevel Weight: %.3f %s", weight, t->proptext);
+ }
+
+ for(i = 0 ; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->val) {
+ *td->val = td->ival + weight * td->factor;
+ if (*td->val < 0.0f) *td->val = 0.0f;
+ if (*td->val > 1.0f) *td->val = 1.0f;
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ helpline (t, t->center);
+
+ return 1;
+}
+
+/* ************************** CREASE *************************** */
+
+void initCrease(TransInfo *t)
+{
+ t->mode = TFM_CREASE;
+ t->transform = Crease;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ t->flag |= T_NO_CONSTRAINT;
+}
+
+int Crease(TransInfo *t, short mval[2])
+{
+ TransData *td = t->data;
+ float crease;
+ int i;
+ char str[50];
+
+ crease = t->values[0];
+
+ crease -= 1.0f;
+ if (crease > 1.0f) crease = 1.0f;
+
+ snapGrid(t, &crease);
+
+ applyNumInput(&t->num, &crease);
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[20];
+
+ outputNumInput(&(t->num), c);
+
+ if (crease >= 0.0f)
+ sprintf(str, "Crease: +%s %s", c, t->proptext);
+ else
+ sprintf(str, "Crease: %s %s", c, t->proptext);
+ }
+ else {
+ /* default header print */
+ if (crease >= 0.0f)
+ sprintf(str, "Crease: +%.3f %s", crease, t->proptext);
+ else
+ sprintf(str, "Crease: %.3f %s", crease, t->proptext);
+ }
+
+ for(i = 0 ; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if (td->val) {
+ *td->val = td->ival + crease * td->factor;
+ if (*td->val < 0.0f) *td->val = 0.0f;
+ if (*td->val > 1.0f) *td->val = 1.0f;
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ helpline (t, t->center);
+
+ return 1;
+}
+
+/* ******************** EditBone (B-bone) width scaling *************** */
+
+void initBoneSize(TransInfo *t)
+{
+ t->mode = TFM_BONESIZE;
+ t->transform = BoneSize;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+
+ t->idx_max = 2;
+ t->num.idx_max = 2;
+ t->num.flag |= NUM_NULL_ONE;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+}
+
+static void headerBoneSize(TransInfo *t, float vec[3], char *str) {
+ char tvec[60];
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec);
+ }
+ else {
+ sprintf(&tvec[0], "%.4f", vec[0]);
+ sprintf(&tvec[20], "%.4f", vec[1]);
+ sprintf(&tvec[40], "%.4f", vec[2]);
+ }
+
+ /* hmm... perhaps the y-axis values don't need to be shown? */
+ if (t->con.mode & CON_APPLY) {
+ if (t->num.idx_max == 0)
+ sprintf(str, "ScaleB: %s%s %s", &tvec[0], t->con.text, t->proptext);
+ else
+ sprintf(str, "ScaleB: %s : %s : %s%s %s", &tvec[0], &tvec[20], &tvec[40], t->con.text, t->proptext);
+ }
+ else {
+ sprintf(str, "ScaleB X: %s Y: %s Z: %s%s %s", &tvec[0], &tvec[20], &tvec[40], t->con.text, t->proptext);
+ }
+}
+
+static void ElementBoneSize(TransInfo *t, TransData *td, float mat[3][3])
+{
+ float tmat[3][3], smat[3][3], oldy;
+ float sizemat[3][3];
+
+ Mat3MulMat3(smat, mat, td->mtx);
+ Mat3MulMat3(tmat, td->smtx, smat);
+
+ if (t->con.applySize) {
+ t->con.applySize(t, td, tmat);
+ }
+
+ /* we've tucked the scale in loc */
+ oldy= td->iloc[1];
+ SizeToMat3(td->iloc, sizemat);
+ Mat3MulMat3(tmat, tmat, sizemat);
+ Mat3ToSize(tmat, td->loc);
+ td->loc[1]= oldy;
+}
+
+int BoneSize(TransInfo *t, short mval[2])
+{
+ TransData *td = t->data;
+ float size[3], mat[3][3];
+ float ratio;
+ int i;
+ char str[60];
+
+ // TRANSFORM_FIX_ME MOVE TO MOUSE INPUT
+ /* for manipulator, center handle, the scaling can't be done relative to center */
+ if( (t->flag & T_USES_MANIPULATOR) && t->con.mode==0)
+ {
+ ratio = 1.0f - ((t->imval[0] - mval[0]) + (t->imval[1] - mval[1]))/100.0f;
+ }
+ else
+ {
+ ratio = t->values[0];
+ }
+
+ size[0] = size[1] = size[2] = ratio;
+
+ snapGrid(t, size);
+
+ if (hasNumInput(&t->num)) {
+ applyNumInput(&t->num, size);
+ constraintNumInput(t, size);
+ }
+
+ SizeToMat3(size, mat);
+
+ if (t->con.applySize) {
+ t->con.applySize(t, NULL, mat);
+ }
+
+ Mat3CpyMat3(t->mat, mat); // used in manipulator
+
+ headerBoneSize(t, size, str);
+
+ for(i = 0 ; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ ElementBoneSize(t, td, mat);
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
+
+ return 1;
+}
+
+
+/* ******************** EditBone envelope *************** */
+
+void initBoneEnvelope(TransInfo *t)
+{
+ t->mode = TFM_BONE_ENVELOPE;
+ t->transform = BoneEnvelope;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ t->flag |= T_NO_CONSTRAINT;
+}
+
+int BoneEnvelope(TransInfo *t, short mval[2])
+{
+ TransData *td = t->data;
+ float ratio;
+ int i;
+ char str[50];
+
+ ratio = t->values[0];
+
+ snapGrid(t, &ratio);
+
+ applyNumInput(&t->num, &ratio);
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[20];
+
+ outputNumInput(&(t->num), c);
+ sprintf(str, "Envelope: %s", c);
+ }
+ else {
+ sprintf(str, "Envelope: %3f", ratio);
+ }
+
+ for(i = 0 ; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if (td->val) {
+ /* if the old/original value was 0.0f, then just use ratio */
+ if (td->ival)
+ *td->val= td->ival*ratio;
+ else
+ *td->val= ratio;
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
+
+ return 1;
+}
+
+
+/* ******************** EditBone roll *************** */
+
+void initBoneRoll(TransInfo *t)
+{
+ t->mode = TFM_BONE_ROLL;
+ t->transform = BoneRoll;
+
+ initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = (float)((5.0/180)*M_PI);
+ t->snap[2] = t->snap[1] * 0.2f;
+
+ t->flag |= T_NO_CONSTRAINT;
+}
+
+int BoneRoll(TransInfo *t, short mval[2])
+{
+ TransData *td = t->data;
+ int i;
+ char str[50];
+
+ float final;
+
+ final = t->values[0];
+
+ snapGrid(t, &final);
+
+ if (hasNumInput(&t->num)) {
+ char c[20];
+
+ applyNumInput(&t->num, &final);
+
+ outputNumInput(&(t->num), c);
+
+ sprintf(str, "Roll: %s", &c[0]);
+
+ final *= (float)(M_PI / 180.0);
+ }
+ else {
+ sprintf(str, "Roll: %.2f", 180.0*final/M_PI);
+ }
+
+ /* set roll values */
+ for (i = 0; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ *(td->val) = td->ival - final;
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
+
+ return 1;
+}
+
+/* ************************** BAKE TIME ******************* */
+
+void initBakeTime(TransInfo *t)
+{
+ t->transform = BakeTime;
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 1.0f;
+ t->snap[2] = t->snap[1] * 0.1f;
+}
+
+int BakeTime(TransInfo *t, short mval[2])
+{
+ TransData *td = t->data;
+ float time;
+ int i;
+ char str[50];
+
+ float fac = 0.1f;
+
+ if(t->mouse.precision) {
+ /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
+ time= (float)(t->center2d[0] - t->mouse.precision_mval[0]) * fac;
+ time+= 0.1f*((float)(t->center2d[0]*fac - mval[0]) -time);
+ }
+ else {
+ time = (float)(t->center2d[0] - mval[0])*fac;
+ }
+
+ snapGrid(t, &time);
+
+ applyNumInput(&t->num, &time);
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[20];
+
+ outputNumInput(&(t->num), c);
+
+ if (time >= 0.0f)
+ sprintf(str, "Time: +%s %s", c, t->proptext);
+ else
+ sprintf(str, "Time: %s %s", c, t->proptext);
+ }
+ else {
+ /* default header print */
+ if (time >= 0.0f)
+ sprintf(str, "Time: +%.3f %s", time, t->proptext);
+ else
+ sprintf(str, "Time: %.3f %s", time, t->proptext);
+ }
+
+ for(i = 0 ; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if (td->val) {
+ *td->val = td->ival + time * td->factor;
+ if (td->ext->size && *td->val < *td->ext->size) *td->val = *td->ext->size;
+ if (td->ext->quat && *td->val > *td->ext->quat) *td->val = *td->ext->quat;
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ helpline (t, t->center);
+
+ return 1;
+}
+
+/* ************************** MIRROR *************************** */
+
+void initMirror(TransInfo *t)
+{
+ t->transform = Mirror;
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
+
+ t->flag |= T_NULL_ONE;
+ if (!t->obedit) {
+ t->flag |= T_NO_ZERO;
+ }
+}
+
+int Mirror(TransInfo *t, short mval[2])
+{
+ TransData *td;
+ float size[3], mat[3][3];
+ int i;
+ char str[200];
+
+ /*
+ * OPTIMISATION:
+ * This still recalcs transformation on mouse move
+ * while it should only recalc on constraint change
+ * */
+
+ /* if an axis has been selected */
+ if (t->con.mode & CON_APPLY) {
+ size[0] = size[1] = size[2] = -1;
+
+ SizeToMat3(size, mat);
+
+ if (t->con.applySize) {
+ t->con.applySize(t, NULL, mat);
+ }
+
+ sprintf(str, "Mirror%s", t->con.text);
+
+ for(i = 0, td=t->data; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ ElementResize(t, td, mat);
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+ }
+ else
+ {
+ size[0] = size[1] = size[2] = 1;
+
+ SizeToMat3(size, mat);
+
+ for(i = 0, td=t->data; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ ElementResize(t, td, mat);
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, "Select a mirror axis (X, Y, Z)");
+ }
+
+ return 1;
+}
+
+/* ************************** ALIGN *************************** */
+
+void initAlign(TransInfo *t)
+{
+ t->flag |= T_NO_CONSTRAINT;
+
+ t->transform = Align;
+
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
+}
+
+int Align(TransInfo *t, short mval[2])
+{
+ TransData *td = t->data;
+ float center[3];
+ int i;
+
+ /* saving original center */
+ VECCOPY(center, t->center);
+
+ for(i = 0 ; i < t->total; i++, td++)
+ {
+ float mat[3][3], invmat[3][3];
+
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ /* around local centers */
+ if (t->flag & (T_OBJECT|T_POSE)) {
+ VECCOPY(t->center, td->center);
+ }
+ else {
+ if(t->scene->selectmode & SCE_SELECT_FACE) {
+ VECCOPY(t->center, td->center);
+ }
+ }
+
+ Mat3Inv(invmat, td->axismtx);
+
+ Mat3MulMat3(mat, t->spacemtx, invmat);
+
+ ElementRotation(t, td, mat, t->around);
+ }
+
+ /* restoring original center */
+ VECCOPY(t->center, center);
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, "Align");
+
+ return 1;
+}
+
+/* ************************** ANIM EDITORS - TRANSFORM TOOLS *************************** */
+
+/* ---------------- Special Helpers for Various Settings ------------- */
+
+
+/* This function returns the snapping 'mode' for Animation Editors only
+ * We cannot use the standard snapping due to NLA-strip scaling complexities.
+ */
+// XXX these modifier checks should be keymappable
+static short getAnimEdit_SnapMode(TransInfo *t)
+{
+ short autosnap= SACTSNAP_OFF;
+
+ /* currently, some of these are only for the action editor */
+ if (t->spacetype == SPACE_ACTION) {
+ SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
+
+ if (saction)
+ autosnap= saction->autosnap;
+ }
+ else if (t->spacetype == SPACE_IPO) {
+ SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first;
+
+ if (sipo)
+ autosnap= sipo->autosnap;
+ }
+ else if (t->spacetype == SPACE_NLA) {
+ SpaceNla *snla= (SpaceNla *)t->sa->spacedata.first;
+
+ if (snla)
+ autosnap= snla->autosnap;
+ }
+ else {
+ // TRANSFORM_FIX_ME This needs to use proper defines for t->modifiers
+// // FIXME: this still toggles the modes...
+// if (ctrl)
+// autosnap= SACTSNAP_STEP;
+// else if (shift)
+// autosnap= SACTSNAP_FRAME;
+// else if (alt)
+// autosnap= SACTSNAP_MARKER;
+// else
+ autosnap= SACTSNAP_OFF;
+ }
+
+ return autosnap;
+}
+
+/* This function is used for testing if an Animation Editor is displaying
+ * its data in frames or seconds (and the data needing to be edited as such).
+ * Returns 1 if in seconds, 0 if in frames
+ */
+static short getAnimEdit_DrawTime(TransInfo *t)
+{
+ short drawtime;
+
+ /* currently, some of these are only for the action editor */
+ if (t->spacetype == SPACE_ACTION) {
+ SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
+
+ drawtime = (saction->flag & SACTION_DRAWTIME)? 1 : 0;
+ }
+ else if (t->spacetype == SPACE_NLA) {
+ SpaceNla *snla= (SpaceNla *)t->sa->spacedata.first;
+
+ drawtime = (snla->flag & SNLA_DRAWTIME)? 1 : 0;
+ }
+ else {
+ drawtime = 0;
+ }
+
+ return drawtime;
+}
+
+
+/* This function is used by Animation Editor specific transform functions to do
+ * the Snap Keyframe to Nearest Frame/Marker
+ */
+static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short autosnap)
+{
+ /* snap key to nearest frame? */
+ if (autosnap == SACTSNAP_FRAME) {
+ const Scene *scene= t->scene;
+ const short doTime= getAnimEdit_DrawTime(t);
+ const double secf= FPS;
+ double val;
+
+ /* convert frame to nla-action time (if needed) */
+ if (ob)
+ val= get_action_frame_inv(ob, *(td->val));
+ else
+ val= *(td->val);
+
+ /* do the snapping to nearest frame/second */
+ if (doTime)
+ val= (float)( floor((val/secf) + 0.5f) * secf );
+ else
+ val= (float)( floor(val+0.5f) );
+
+ /* convert frame out of nla-action time */
+ if (ob)
+ *(td->val)= get_action_frame(ob, val);
+ else
+ *(td->val)= val;
+ }
+ /* snap key to nearest marker? */
+ else if (autosnap == SACTSNAP_MARKER) {
+ float val;
+
+ /* convert frame to nla-action time (if needed) */
+ if (ob)
+ val= get_action_frame_inv(ob, *(td->val));
+ else
+ val= *(td->val);
+
+ /* snap to nearest marker */
+ // XXX missing function!
+ //val= (float)find_nearest_marker_time(val);
+
+ /* convert frame out of nla-action time */
+ if (ob)
+ *(td->val)= get_action_frame(ob, val);
+ else
+ *(td->val)= val;
+ }
+}
+
+/* ----------------- Translation ----------------------- */
+
+void initTimeTranslate(TransInfo *t)
+{
+ t->mode = TFM_TIME_TRANSLATE;
+ t->transform = TimeTranslate;
+
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
+
+ /* num-input has max of (n-1) */
+ t->idx_max = 0;
+ t->num.flag = 0;
+ t->num.idx_max = t->idx_max;
+
+ /* initialise snap like for everything else */
+ t->snap[0] = 0.0f;
+ t->snap[1] = t->snap[2] = 1.0f;
+}
+
+static void headerTimeTranslate(TransInfo *t, char *str)
+{
+ char tvec[60];
+
+ /* if numeric input is active, use results from that, otherwise apply snapping to result */
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec);
+ }
+ else {
+ const Scene *scene = t->scene;
+ const short autosnap= getAnimEdit_SnapMode(t);
+ const short doTime = getAnimEdit_DrawTime(t);
+ const double secf= FPS;
+ float val = t->values[0];
+
+ /* apply snapping + frame->seconds conversions */
+ if (autosnap == SACTSNAP_STEP) {
+ if (doTime)
+ val= floor(val/secf + 0.5f);
+ else
+ val= floor(val + 0.5f);
+ }
+ else {
+ if (doTime)
+ val= val / secf;
+ }
+
+ sprintf(&tvec[0], "%.4f", val);
+ }
+
+ sprintf(str, "DeltaX: %s", &tvec[0]);
+}
+
+static void applyTimeTranslate(TransInfo *t, float sval)
+{
+ TransData *td = t->data;
+ Scene *scene = t->scene;
+ int i;
+
+ const short doTime= getAnimEdit_DrawTime(t);
+ const double secf= FPS;
+
+ const short autosnap= getAnimEdit_SnapMode(t);
+
+ float deltax, val;
+
+ /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */
+ for (i = 0 ; i < t->total; i++, td++) {
+ /* it is assumed that td->ob is a pointer to the object,
+ * whose active action is where this keyframe comes from
+ */
+ Object *ob= td->ob;
+
+ /* check if any need to apply nla-scaling */
+ if (ob) {
+ deltax = t->values[0];
+
+ if (autosnap == SACTSNAP_STEP) {
+ if (doTime)
+ deltax= (float)( floor((deltax/secf) + 0.5f) * secf );
+ else
+ deltax= (float)( floor(deltax + 0.5f) );
+ }
+
+ val = get_action_frame_inv(ob, td->ival);
+ val += deltax;
+ *(td->val) = get_action_frame(ob, val);
+ }
+ else {
+ deltax = val = t->values[0];
+
+ if (autosnap == SACTSNAP_STEP) {
+ if (doTime)
+ val= (float)( floor((deltax/secf) + 0.5f) * secf );
+ else
+ val= (float)( floor(val + 0.5f) );
+ }
+
+ *(td->val) = td->ival + val;
+ }
+
+ /* apply nearest snapping */
+ doAnimEdit_SnapFrame(t, td, ob, autosnap);
+ }
+}
+
+int TimeTranslate(TransInfo *t, short mval[2])
+{
+ View2D *v2d = (View2D *)t->view;
+ float cval[2], sval[2];
+ char str[200];
+
+ /* calculate translation amount from mouse movement - in 'time-grid space' */
+ UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]);
+ UI_view2d_region_to_view(v2d, t->imval[0], t->imval[0], &sval[0], &sval[1]);
+
+ /* we only need to calculate effect for time (applyTimeTranslate only needs that) */
+ t->values[0] = cval[0] - sval[0];
+
+ /* handle numeric-input stuff */
+ t->vec[0] = t->values[0];
+ applyNumInput(&t->num, &t->vec[0]);
+ t->values[0] = t->vec[0];
+ headerTimeTranslate(t, str);
+
+ applyTimeTranslate(t, sval[0]);
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ return 1;
+}
+
+/* ----------------- Time Slide ----------------------- */
+
+void initTimeSlide(TransInfo *t)
+{
+ /* this tool is only really available in the Action Editor... */
+ if (t->spacetype == SPACE_ACTION) {
+ SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
+
+ /* set flag for drawing stuff */
+ saction->flag |= SACTION_MOVING;
+ }
+
+ t->mode = TFM_TIME_SLIDE;
+ t->transform = TimeSlide;
+ t->flag |= T_FREE_CUSTOMDATA;
+
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
+
+ /* num-input has max of (n-1) */
+ t->idx_max = 0;
+ t->num.flag = 0;
+ t->num.idx_max = t->idx_max;
+
+ /* initialise snap like for everything else */
+ t->snap[0] = 0.0f;
+ t->snap[1] = t->snap[2] = 1.0f;
+}
+
+static void headerTimeSlide(TransInfo *t, float sval, char *str)
+{
+ char tvec[60];
+
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec);
+ }
+ else {
+ float minx= *((float *)(t->customData));
+ float maxx= *((float *)(t->customData) + 1);
+ float cval= t->values[0];
+ float val;
+
+ val= 2.0f*(cval-sval) / (maxx-minx);
+ CLAMP(val, -1.0f, 1.0f);
+
+ sprintf(&tvec[0], "%.4f", val);
+ }
+
+ sprintf(str, "TimeSlide: %s", &tvec[0]);
+}
+
+static void applyTimeSlide(TransInfo *t, float sval)
+{
+ TransData *td = t->data;
+ int i;
+
+ float minx= *((float *)(t->customData));
+ float maxx= *((float *)(t->customData) + 1);
+
+ /* set value for drawing black line */
+ if (t->spacetype == SPACE_ACTION) {
+ SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
+ float cvalf = t->values[0];
+
+ saction->timeslide= cvalf;
+ }
+
+ /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */
+ for (i = 0 ; i < t->total; i++, td++) {
+ /* it is assumed that td->ob is a pointer to the object,
+ * whose active action is where this keyframe comes from
+ */
+ Object *ob= td->ob;
+ float cval = t->values[0];
+
+ /* apply scaling to necessary values */
+ if (ob)
+ cval= get_action_frame(ob, cval);
+
+ /* only apply to data if in range */
+ if ((sval > minx) && (sval < maxx)) {
+ float cvalc= CLAMPIS(cval, minx, maxx);
+ float timefac;
+
+ /* left half? */
+ if (td->ival < sval) {
+ timefac= (sval - td->ival) / (sval - minx);
+ *(td->val)= cvalc - timefac * (cvalc - minx);
+ }
+ else {
+ timefac= (td->ival - sval) / (maxx - sval);
+ *(td->val)= cvalc + timefac * (maxx - cvalc);
+ }
+ }
+ }
+}
+
+int TimeSlide(TransInfo *t, short mval[2])
+{
+ View2D *v2d = (View2D *)t->view;
+ float cval[2], sval[2];
+ float minx= *((float *)(t->customData));
+ float maxx= *((float *)(t->customData) + 1);
+ char str[200];
+
+ /* calculate mouse co-ordinates */
+ UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]);
+ UI_view2d_region_to_view(v2d, t->imval[0], t->imval[0], &sval[0], &sval[1]);
+
+ /* t->values[0] stores cval[0], which is the current mouse-pointer location (in frames) */
+ t->values[0] = cval[0];
+
+ /* handle numeric-input stuff */
+ t->vec[0] = 2.0f*(cval[0]-sval[0]) / (maxx-minx);
+ applyNumInput(&t->num, &t->vec[0]);
+ t->values[0] = (maxx-minx) * t->vec[0] / 2.0 + sval[0];
+
+ headerTimeSlide(t, sval[0], str);
+ applyTimeSlide(t, sval[0]);
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ return 1;
+}
+
+/* ----------------- Scaling ----------------------- */
+
+void initTimeScale(TransInfo *t)
+{
+ t->mode = TFM_TIME_SCALE;
+ t->transform = TimeScale;
+
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
+
+ t->flag |= T_NULL_ONE;
+ t->num.flag |= NUM_NULL_ONE;
+
+ /* num-input has max of (n-1) */
+ t->idx_max = 0;
+ t->num.flag = 0;
+ t->num.idx_max = t->idx_max;
+
+ /* initialise snap like for everything else */
+ t->snap[0] = 0.0f;
+ t->snap[1] = t->snap[2] = 1.0f;
+}
+
+static void headerTimeScale(TransInfo *t, char *str) {
+ char tvec[60];
+
+ if (hasNumInput(&t->num))
+ outputNumInput(&(t->num), tvec);
+ else
+ sprintf(&tvec[0], "%.4f", t->values[0]);
+
+ sprintf(str, "ScaleX: %s", &tvec[0]);
+}
+
+static void applyTimeScale(TransInfo *t) {
+ Scene *scene = t->scene;
+ TransData *td = t->data;
+ int i;
+
+ const short autosnap= getAnimEdit_SnapMode(t);
+ const short doTime= getAnimEdit_DrawTime(t);
+ const double secf= FPS;
+
+
+ for (i = 0 ; i < t->total; i++, td++) {
+ /* it is assumed that td->ob is a pointer to the object,
+ * whose active action is where this keyframe comes from
+ */
+ Object *ob= td->ob;
+ float startx= CFRA;
+ float fac= t->values[0];
+
+ if (autosnap == SACTSNAP_STEP) {
+ if (doTime)
+ fac= (float)( floor(fac/secf + 0.5f) * secf );
+ else
+ fac= (float)( floor(fac + 0.5f) );
+ }
+
+ /* check if any need to apply nla-scaling */
+ if (ob)
+ startx= get_action_frame(ob, startx);
+
+ /* now, calculate the new value */
+ *(td->val) = td->ival - startx;
+ *(td->val) *= fac;
+ *(td->val) += startx;
+
+ /* apply nearest snapping */
+ doAnimEdit_SnapFrame(t, td, ob, autosnap);
+ }
+}
+
+int TimeScale(TransInfo *t, short mval[2])
+{
+ float cval, sval;
+ float deltax, startx;
+ float width= 0.0f;
+ char str[200];
+
+ sval= t->imval[0];
+ cval= mval[0];
+
+ // XXX ewww... we need a better factor!
+#if 0 // TRANSFORM_FIX_ME
+ switch (t->spacetype) {
+ case SPACE_ACTION:
+ width= ACTWIDTH;
+ break;
+ case SPACE_NLA:
+ width= NLAWIDTH;
+ break;
+ }
+#endif
+
+ /* calculate scaling factor */
+ startx= sval-(width/2+(t->ar->winx)/2);
+ deltax= cval-(width/2+(t->ar->winx)/2);
+ t->values[0] = deltax / startx;
+
+ /* handle numeric-input stuff */
+ t->vec[0] = t->values[0];
+ applyNumInput(&t->num, &t->vec[0]);
+ t->values[0] = t->vec[0];
+ headerTimeScale(t, str);
+
+ applyTimeScale(t);
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ return 1;
+}
+
+/* ************************************ */
+
+void BIF_TransformSetUndo(char *str)
+{
+ // TRANSFORM_FIX_ME
+ //Trans.undostr= str;
+}
+
+
+void NDofTransform()
+{
+#if 0 // TRANSFORM_FIX_ME
+ float fval[7];
+ float maxval = 50.0f; // also serves as threshold
+ int axis = -1;
+ int mode = 0;
+ int i;
+
+ getndof(fval);
+
+ for(i = 0; i < 6; i++)
+ {
+ float val = fabs(fval[i]);
+ if (val > maxval)
+ {
+ axis = i;
+ maxval = val;
+ }
+ }
+
+ switch(axis)
+ {
+ case -1:
+ /* No proper axis found */
+ break;
+ case 0:
+ case 1:
+ case 2:
+ mode = TFM_TRANSLATION;
+ break;
+ case 4:
+ mode = TFM_ROTATION;
+ break;
+ case 3:
+ case 5:
+ mode = TFM_TRACKBALL;
+ break;
+ default:
+ printf("ndof: what we are doing here ?");
+ }
+
+ if (mode != 0)
+ {
+ initTransform(mode, CTX_NDOF);
+ Transform();
+ }
+#endif
+}
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
new file mode 100644
index 00000000000..4ac82fcd73f
--- /dev/null
+++ b/source/blender/editors/transform/transform.h
@@ -0,0 +1,639 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef TRANSFORM_H
+#define TRANSFORM_H
+
+#include "BIF_transform.h"
+
+/* ************************** Types ***************************** */
+
+struct TransInfo;
+struct TransData;
+struct TransSnap;
+struct NumInput;
+struct Object;
+struct View3D;
+struct ScrArea;
+struct Scene;
+struct bPose;
+struct bConstraint;
+struct BezTriple;
+struct wmOperatorType;
+struct wmOperator;
+struct bContext;
+struct wmEvent;
+struct wmTimer;
+struct ARegion;
+
+typedef struct NDofInput {
+ int flag;
+ int axis;
+ float fval[7];
+ float factor[3];
+} NDofInput;
+
+typedef struct NumInput {
+ short idx;
+ short idx_max;
+ short flag; /* Different flags to indicate different behaviors */
+ char inv[3]; /* If the value is inverted or not */
+ float val[3]; /* Direct value of the input */
+ int ctrl[3]; /* Control to indicate what to do with the numbers that are typed */
+} NumInput ;
+
+/*
+ The ctrl value has different meaning:
+ 0 : No value has been typed
+
+ otherwise, |value| - 1 is where the cursor is located after the period
+ Positive : number is positive
+ Negative : number is negative
+*/
+
+typedef struct TransSnap {
+ short modePoint;
+ short modeTarget;
+ short mode;
+ short align;
+ short status;
+ float snapPoint[3]; /* snapping from this point */
+ float snapTarget[3]; /* to this point */
+ float snapNormal[3];
+ float snapTangent[3];
+ float dist; // Distance from snapPoint to snapTarget
+ double last;
+ void (*applySnap)(struct TransInfo *, float *);
+ void (*calcSnap)(struct TransInfo *, float *);
+ void (*targetSnap)(struct TransInfo *);
+ float (*distance)(struct TransInfo *, float p1[3], float p2[3]); // Get the transform distance between two points (used by Closest snap)
+} TransSnap;
+
+typedef struct TransCon {
+ char text[50]; /* Description of the Constraint for header_print */
+ float mtx[3][3]; /* Matrix of the Constraint space */
+ float imtx[3][3]; /* Inverse Matrix of the Constraint space */
+ float pmtx[3][3]; /* Projection Constraint Matrix (same as imtx with some axis == 0) */
+ float center[3]; /* transformation center to define where to draw the view widget
+ ALWAYS in global space. Unlike the transformation center */
+ short imval[2]; /* initial mouse value for visual calculation */
+ /* the one in TransInfo is not garanty to stay the same (Rotates change it) */
+ int mode; /* Mode flags of the Constraint */
+ void (*drawExtra)(struct TransInfo *);
+ /* For constraints that needs to draw differently from the other
+ uses this instead of the generic draw function */
+ void (*applyVec)(struct TransInfo *, struct TransData *, float *, float *, float *);
+ /* Apply function pointer for linear vectorial transformation */
+ /* The last three parameters are pointers to the in/out/printable vectors */
+ void (*applySize)(struct TransInfo *, struct TransData *, float [3][3]);
+ /* Apply function pointer for size transformation */
+ void (*applyRot)(struct TransInfo *, struct TransData *, float [3], float *);
+ /* Apply function pointer for rotation transformation */
+} TransCon;
+
+typedef struct TransDataIpokey {
+ int flag; /* which keys */
+ float *locx, *locy, *locz; /* channel pointers */
+ float *rotx, *roty, *rotz;
+ float *quatx, *quaty, *quatz, *quatw;
+ float *sizex, *sizey, *sizez;
+ float oldloc[9]; /* storage old values */
+ float oldrot[9];
+ float oldsize[9];
+ float oldquat[12];
+} TransDataIpokey;
+
+typedef struct TransDataExtension {
+ float drot[3]; /* Initial object drot */
+ float dsize[3]; /* Initial object dsize */
+ float *rot; /* Rotation of the data to transform (Faculative) */
+ float irot[3]; /* Initial rotation */
+ float *quat; /* Rotation quaternion of the data to transform (Faculative) */
+ float iquat[4]; /* Initial rotation quaternion */
+ float *size; /* Size of the data to transform (Faculative) */
+ float isize[3]; /* Initial size */
+ float obmat[4][4]; /* Object matrix */
+} TransDataExtension;
+
+typedef struct TransData2D {
+ float loc[3]; /* Location of data used to transform (x,y,0) */
+ float *loc2d; /* Pointer to real 2d location of data */
+} TransData2D;
+
+/* we need to store 2 handles for each transdata incase the other handle wasnt selected */
+typedef struct TransDataCurveHandleFlags {
+ char ih1, ih2;
+ char *h1, *h2;
+} TransDataCurveHandleFlags;
+
+/* for sequencer transform */
+typedef struct TransDataSeq {
+ struct Sequence *seq;
+ int flag; /* a copy of seq->flag that may be modified for nested strips */
+ short start_offset; /* use this so we can have transform data at the strips start, but apply correctly to the start frame */
+ short sel_flag; /* one of SELECT, SEQ_LEFTSEL and SEQ_RIGHTSEL */
+
+} TransDataSeq;
+
+typedef struct TransData {
+ float dist; /* Distance needed to affect element (for Proportionnal Editing) */
+ float rdist; /* Distance to the nearest element (for Proportionnal Editing) */
+ float factor; /* Factor of the transformation (for Proportionnal Editing) */
+ float *loc; /* Location of the data to transform */
+ float iloc[3]; /* Initial location */
+ float *val; /* Value pointer for special transforms */
+ float ival; /* Old value*/
+ float center[3]; /* Individual data center */
+ float mtx[3][3]; /* Transformation matrix from data space to global space */
+ float smtx[3][3]; /* Transformation matrix from global space to data space */
+ float axismtx[3][3];/* Axis orientation matrix of the data */
+ struct Object *ob;
+ struct bConstraint *con; /* for objects/bones, the first constraint in its constraint stack */
+ TransDataExtension *ext; /* for objects, poses. 1 single malloc per TransInfo! */
+ TransDataIpokey *tdi; /* for objects, ipo keys. per transdata a malloc */
+ TransDataCurveHandleFlags *hdata; /* for curves, stores handle flags for modification/cancel */
+ void *extra; /* extra data (mirrored element pointer, in editmode mesh to EditVert) (editbone for roll fixing) (...) */
+ short flag; /* Various flags */
+ short protectflag; /* If set, copy of Object or PoseChannel protection */
+} TransData;
+
+typedef struct MouseInput {
+ void (*apply)(struct TransInfo *, struct MouseInput *, short [2], float [3]);
+
+ short imval[2]; /* initial mouse position */
+ char precision;
+ short precision_mval[2]; /* mouse position when precision key was pressed */
+ int center[2];
+ float factor;
+} MouseInput;
+
+typedef struct TransInfo {
+ int mode; /* current mode */
+ int flag; /* generic flags for special behaviors */
+ int modifiers; /* special modifiers, by function, not key */
+ short state; /* current state (running, canceled,...)*/
+ int options; /* current context/options for transform */
+ float val; /* init value for some transformations (and rotation angle) */
+ float fac; /* factor for distance based transform */
+ int (*transform)(struct TransInfo *, short *);
+ /* transform function pointer */
+ int (*handleEvent)(struct TransInfo *, struct wmEvent *);
+ /* event handler function pointer RETURN 1 if redraw is needed */
+ int total; /* total number of transformed data */
+ TransData *data; /* transformed data (array) */
+ TransDataExtension *ext; /* transformed data extension (array) */
+ TransData2D *data2d; /* transformed data for 2d (array) */
+ TransCon con; /* transformed constraint */
+ TransSnap tsnap;
+ NumInput num; /* numerical input */
+ NDofInput ndof; /* ndof input */
+ MouseInput mouse; /* mouse input */
+ char redraw; /* redraw flag */
+ float prop_size; /* proportional circle radius */
+ char proptext[20]; /* proportional falloff text */
+ float center[3]; /* center of transformation */
+ int center2d[2]; /* center in screen coordinates */
+ short imval[2]; /* initial mouse position */
+ short event_type; /* event->type used to invoke transform */
+ short idx_max; /* maximum index on the input vector */
+ float snap[3]; /* Snapping Gears */
+ char frame_side; /* Mouse side of the cfra, 'L', 'R' or 'B' */
+
+ float viewmat[4][4]; /* copy from G.vd, prevents feedback, */
+ float viewinv[4][4]; /* and to make sure we don't have to */
+ float persmat[4][4]; /* access G.vd from other space types */
+ float persinv[4][4];
+ short persp;
+ short around;
+ char spacetype; /* spacetype where transforming is */
+
+ float vec[3]; /* translation, to show for widget */
+ float mat[3][3]; /* rot/rescale, to show for widget */
+
+ char *undostr; /* if set, uses this string for undo */
+ float spacemtx[3][3]; /* orientation matrix of the current space */
+ char spacename[32]; /* name of the current space */
+
+ struct Object *poseobj; /* if t->flag & T_POSE, this denotes pose object */
+
+ void *customData; /* Per Transform custom data */
+
+ /*************** NEW STUFF *********************/
+
+ short current_orientation;
+
+ short prop_mode;
+
+ float values[4];
+ float auto_values[4];
+ void *view;
+ struct ScrArea *sa;
+ struct ARegion *ar;
+ struct Scene *scene;
+ struct wmTimer *animtimer;
+ short mval[2]; /* current mouse position */
+ struct Object *obedit;
+ void *draw_handle;
+} TransInfo;
+
+
+/* ******************** Macros & Prototypes *********************** */
+
+/* NUMINPUT FLAGS */
+#define NUM_NULL_ONE 2
+#define NUM_NO_NEGATIVE 4
+#define NUM_NO_ZERO 8
+#define NUM_NO_FRACTION 16
+#define NUM_AFFECT_ALL 32
+
+/* NDOFINPUT FLAGS */
+#define NDOF_INIT 1
+
+/* transinfo->state */
+#define TRANS_RUNNING 0
+#define TRANS_CONFIRM 1
+#define TRANS_CANCEL 2
+
+/* transinfo->flag */
+#define T_OBJECT (1 << 0)
+#define T_EDIT (1 << 1)
+#define T_POSE (1 << 2)
+#define T_TEXTURE (1 << 3)
+#define T_CAMERA (1 << 4)
+ // trans on points, having no rotation/scale
+#define T_POINTS (1 << 6)
+ // for manipulator exceptions, like scaling using center point, drawing help lines
+#define T_USES_MANIPULATOR (1 << 7)
+
+ /* restrictions flags */
+#define T_ALL_RESTRICTIONS ((1 << 8)|(1 << 9)|(1 << 10))
+#define T_NO_CONSTRAINT (1 << 8)
+#define T_NULL_ONE (1 << 9)
+#define T_NO_ZERO (1 << 10)
+
+#define T_PROP_EDIT (1 << 11)
+#define T_PROP_CONNECTED (1 << 12)
+
+#define T_V3D_ALIGN (1 << 14)
+ /* for 2d views like uv or ipo */
+#define T_2D_EDIT (1 << 15)
+#define T_CLIP_UV (1 << 16)
+
+#define T_FREE_CUSTOMDATA (1 << 17)
+ /* auto-ik is on */
+#define T_AUTOIK (1 << 18)
+
+#define T_MIRROR (1 << 19)
+
+#define T_AUTOVALUES (1 << 20)
+
+ /* to specificy if we save back settings at the end */
+#define T_MODAL (1 << 21)
+
+/* TransInfo->modifiers */
+#define MOD_CONSTRAINT_SELECT 0x01
+#define MOD_PRECISION 0x02
+#define MOD_SNAP_GEARS 0x04
+#define MOD_CONSTRAINT_PLANE 0x08
+
+
+/* ******************************************************************************** */
+
+/* transinfo->con->mode */
+#define CON_APPLY 1
+#define CON_AXIS0 2
+#define CON_AXIS1 4
+#define CON_AXIS2 8
+#define CON_SELECT 16
+#define CON_NOFLIP 32 /* does not reorient vector to face viewport when on */
+#define CON_USER 64
+
+/* transdata->flag */
+#define TD_SELECTED 1
+#define TD_ACTIVE (1 << 1)
+#define TD_NOACTION (1 << 2)
+#define TD_USEQUAT (1 << 3)
+#define TD_NOTCONNECTED (1 << 4)
+#define TD_SINGLESIZE (1 << 5) /* used for scaling of MetaElem->rad */
+#define TD_TIMEONLY (1 << 8)
+#define TD_NOCENTER (1 << 9)
+#define TD_NO_EXT (1 << 10) /* ext abused for particle key timing */
+#define TD_SKIP (1 << 11) /* don't transform this data */
+#define TD_BEZTRIPLE (1 << 12) /* if this is a bez triple, we need to restore the handles, if this is set transdata->misc.hdata needs freeing */
+#define TD_NO_LOC (1 << 13) /* when this is set, don't apply translation changes to this element */
+#define TD_NOTIMESNAP (1 << 14) /* for Graph Editor autosnap, indicates that point should not undergo autosnapping */
+#define TD_INTVALUES (1 << 15) /* for Graph Editor - curves that can only have int-values need their keyframes tagged with this */
+
+/* transsnap->status */
+#define SNAP_ON 1
+#define SNAP_FORCED 2
+#define TARGET_INIT 4
+#define POINT_INIT 8
+
+/* transsnap->modePoint */
+#define SNAP_GRID 0
+#define SNAP_GEO 1
+
+/* transsnap->modeTarget */
+#define SNAP_CLOSEST 0
+#define SNAP_CENTER 1
+#define SNAP_MEDIAN 2
+#define SNAP_ACTIVE 3
+
+
+void TFM_OT_transform(struct wmOperatorType *ot);
+
+int initTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op, struct wmEvent *event, int mode);
+void saveTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op);
+void transformEvent(TransInfo *t, struct wmEvent *event);
+void transformApply(struct bContext *C, TransInfo *t);
+int transformEnd(struct bContext *C, TransInfo *t);
+
+void setTransformViewMatrices(TransInfo *t);
+void convertViewVec(TransInfo *t, float *vec, short dx, short dy);
+void projectIntView(TransInfo *t, float *vec, int *adr);
+void projectFloatView(TransInfo *t, float *vec, float *adr);
+
+void applyAspectRatio(TransInfo *t, float *vec);
+void removeAspectRatio(TransInfo *t, float *vec);
+
+void initWarp(TransInfo *t);
+int handleEventWarp(TransInfo *t, struct wmEvent *event);
+int Warp(TransInfo *t, short mval[2]);
+
+void initShear(TransInfo *t);
+int handleEventShear(TransInfo *t, struct wmEvent *event);
+int Shear(TransInfo *t, short mval[2]);
+
+void initResize(TransInfo *t);
+int Resize(TransInfo *t, short mval[2]);
+
+void initTranslation(TransInfo *t);
+int Translation(TransInfo *t, short mval[2]);
+
+void initToSphere(TransInfo *t);
+int ToSphere(TransInfo *t, short mval[2]);
+
+void initRotation(TransInfo *t);
+int Rotation(TransInfo *t, short mval[2]);
+
+void initShrinkFatten(TransInfo *t);
+int ShrinkFatten(TransInfo *t, short mval[2]);
+
+void initTilt(TransInfo *t);
+int Tilt(TransInfo *t, short mval[2]);
+
+void initCurveShrinkFatten(TransInfo *t);
+int CurveShrinkFatten(TransInfo *t, short mval[2]);
+
+void initTrackball(TransInfo *t);
+int Trackball(TransInfo *t, short mval[2]);
+
+void initPushPull(TransInfo *t);
+int PushPull(TransInfo *t, short mval[2]);
+
+void initBevel(TransInfo *t);
+int handleEventBevel(TransInfo *t, struct wmEvent *event);
+int Bevel(TransInfo *t, short mval[2]);
+
+void initBevelWeight(TransInfo *t);
+int BevelWeight(TransInfo *t, short mval[2]);
+
+void initCrease(TransInfo *t);
+int Crease(TransInfo *t, short mval[2]);
+
+void initBoneSize(TransInfo *t);
+int BoneSize(TransInfo *t, short mval[2]);
+
+void initBoneEnvelope(TransInfo *t);
+int BoneEnvelope(TransInfo *t, short mval[2]);
+
+void initBoneRoll(TransInfo *t);
+int BoneRoll(TransInfo *t, short mval[2]);
+
+void initTimeTranslate(TransInfo *t);
+int TimeTranslate(TransInfo *t, short mval[2]);
+
+void initTimeSlide(TransInfo *t);
+int TimeSlide(TransInfo *t, short mval[2]);
+
+void initTimeScale(TransInfo *t);
+int TimeScale(TransInfo *t, short mval[2]);
+
+void initBakeTime(TransInfo *t);
+int BakeTime(TransInfo *t, short mval[2]);
+
+void initMirror(TransInfo *t);
+int Mirror(TransInfo *t, short mval[2]);
+
+void initAlign(TransInfo *t);
+int Align(TransInfo *t, short mval[2]);
+
+
+void drawPropCircle(const struct bContext *C, TransInfo *t);
+
+/*********************** transform_conversions.c ********** */
+struct ListBase;
+
+void flushTransGPactionData(TransInfo *t);
+void flushTransGraphData(TransInfo *t);
+void remake_graph_transdata(TransInfo *t, struct ListBase *anim_data);
+void flushTransUVs(TransInfo *t);
+void flushTransParticles(TransInfo *t);
+int clipUVTransform(TransInfo *t, float *vec, int resize);
+void flushTransNodes(TransInfo *t);
+void flushTransSeq(TransInfo *t);
+
+/*********************** exported from transform_manipulator.c ********** */
+void draw_manipulator_ext(struct ScrArea *sa, int type, char axis, int col, float vec[3], float mat[][3]);
+int calc_manipulator_stats(struct ScrArea *sa);
+float get_drawsize(struct ARegion *ar, float *co);
+
+/*********************** TransData Creation and General Handling *********** */
+void createTransData(struct bContext *C, TransInfo *t);
+void sort_trans_data_dist(TransInfo *t);
+void add_tdi_poin(float *poin, float *old, float delta);
+void special_aftertrans_update(TransInfo *t);
+
+void transform_autoik_update(TransInfo *t, short mode);
+
+/* auto-keying stuff used by special_aftertrans_update */
+short autokeyframe_cfra_can_key(struct Scene *scene, struct Object *ob);
+void autokeyframe_ob_cb_func(struct Scene *scene, struct View3D *v3d, struct Object *ob, int tmode);
+void autokeyframe_pose_cb_func(struct Scene *scene, struct View3D *v3d, struct Object *ob, int tmode, short targetless_ik);
+
+/*********************** Constraints *****************************/
+
+void drawConstraint(const struct bContext *C, TransInfo *t);
+
+void getConstraintMatrix(TransInfo *t);
+void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[]);
+void setLocalConstraint(TransInfo *t, int mode, const char text[]);
+void setUserConstraint(TransInfo *t, int mode, const char text[]);
+
+void constraintNumInput(TransInfo *t, float vec[3]);
+
+void getConstraintMatrix(TransInfo *t);
+int isLockConstraint(TransInfo *t);
+int getConstraintSpaceDimension(TransInfo *t);
+char constraintModeToChar(TransInfo *t);
+
+void startConstraint(TransInfo *t);
+void stopConstraint(TransInfo *t);
+
+void initSelectConstraint(TransInfo *t, float mtx[3][3]);
+void selectConstraint(TransInfo *t);
+void postSelectConstraint(TransInfo *t);
+
+void setNearestAxis(TransInfo *t);
+
+/*********************** Snapping ********************************/
+
+typedef enum {
+ NO_GEARS = 0,
+ BIG_GEARS = 1,
+ SMALL_GEARS = 2
+} GearsType;
+
+void snapGrid(TransInfo *t, float *val);
+void snapGridAction(TransInfo *t, float *val, GearsType action);
+
+void initSnapping(struct TransInfo *t, struct wmOperator *op);
+void applySnapping(TransInfo *t, float *vec);
+void resetSnapping(TransInfo *t);
+int handleSnapping(TransInfo *t, struct wmEvent *event);
+void drawSnapping(const struct bContext *C, TransInfo *t);
+int usingSnappingNormal(TransInfo *t);
+int validSnappingNormal(TransInfo *t);
+
+/********************** Mouse Input ******************************/
+
+typedef enum {
+ INPUT_NONE,
+ INPUT_VECTOR,
+ INPUT_SPRING,
+ INPUT_SPRING_FLIP,
+ INPUT_ANGLE,
+ INPUT_TRACKBALL,
+ INPUT_HORIZONTAL_RATIO,
+ INPUT_HORIZONTAL_ABSOLUTE,
+ INPUT_VERTICAL_RATIO,
+ INPUT_VERTICAL_ABSOLUTE
+} MouseInputMode;
+
+void initMouseInput(TransInfo *t, MouseInput *mi, int center[2], short mval[2]);
+void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode);
+int handleMouseInput(struct TransInfo *t, struct MouseInput *mi, struct wmEvent *event);
+void applyMouseInput(struct TransInfo *t, struct MouseInput *mi, short mval[2], float output[3]);
+
+/*********************** Generics ********************************/
+
+int initTransInfo(struct bContext *C, TransInfo *t, struct wmOperator *op, struct wmEvent *event);
+void postTrans (TransInfo *t);
+void resetTransRestrictions(TransInfo *t);
+
+void drawLine(TransInfo *t, float *center, float *dir, char axis, short options);
+
+TransDataCurveHandleFlags *initTransDataCurveHandes(TransData *td, struct BezTriple *bezt);
+
+/* DRAWLINE options flags */
+#define DRAWLIGHT 1
+#define DRAWDASHED 2
+#define DRAWBOLD 4
+
+void applyTransObjects(TransInfo *t);
+void restoreTransObjects(TransInfo *t);
+void restoreTransNodes(TransInfo *t);
+void recalcData(TransInfo *t);
+
+void calculateCenter(TransInfo *t);
+void calculateCenter2D(TransInfo *t);
+void calculateCenterBound(TransInfo *t);
+void calculateCenterMedian(TransInfo *t);
+void calculateCenterCursor(TransInfo *t);
+
+void calculateCenterCursor2D(TransInfo *t);
+void calculatePropRatio(TransInfo *t);
+
+void getViewVector(TransInfo *t, float coord[3], float vec[3]);
+
+TransInfo * BIF_GetTransInfo(void);
+
+/*********************** NumInput ********************************/
+
+void initNumInput(NumInput *n);
+void outputNumInput(NumInput *n, char *str);
+short hasNumInput(NumInput *n);
+void applyNumInput(NumInput *n, float *vec);
+char handleNumInput(NumInput *n, struct wmEvent *event);
+
+/*********************** NDofInput ********************************/
+
+void initNDofInput(NDofInput *n);
+int hasNDofInput(NDofInput *n);
+void applyNDofInput(NDofInput *n, float *vec);
+int handleNDofInput(NDofInput *n, struct wmEvent *event);
+
+/* handleNDofInput return values */
+#define NDOF_REFRESH 1
+#define NDOF_NOMOVE 2
+#define NDOF_CONFIRM 3
+#define NDOF_CANCEL 4
+
+
+/*********************** Transform Orientations ******************************/
+
+void initTransformOrientation(struct bContext *C, TransInfo *t);
+
+int manageObjectSpace(struct bContext *C, int confirm, int set);
+int manageMeshSpace(struct bContext *C, int confirm, int set);
+int manageBoneSpace(struct bContext *C, int confirm, int set);
+
+/* Those two fill in mat and return non-zero on success */
+int createSpaceNormal(float mat[3][3], float normal[3]);
+int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]);
+
+int addMatrixSpace(struct bContext *C, float mat[3][3], char name[]);
+int addObjectSpace(struct bContext *C, struct Object *ob);
+void applyTransformOrientation(struct bContext *C, TransInfo *t);
+
+
+#define ORIENTATION_NONE 0
+#define ORIENTATION_NORMAL 1
+#define ORIENTATION_VERT 2
+#define ORIENTATION_EDGE 3
+#define ORIENTATION_FACE 4
+
+int getTransformOrientation(struct bContext *C, float normal[3], float plane[3], int activeOnly);
+int createSpaceNormal(float mat[3][3], float normal[3]);
+int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]);
+
+#endif
+
+
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
new file mode 100644
index 00000000000..7f47bfd25af
--- /dev/null
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -0,0 +1,1113 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_effect_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_meshdata_types.h"
+#include "DNA_meta_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 "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "ED_image.h"
+#include "ED_view3d.h"
+
+#include "BLI_arithb.h"
+
+//#include "blendef.h"
+//
+//#include "mydevice.h"
+
+#include "WM_types.h"
+#include "UI_resources.h"
+
+
+#include "transform.h"
+
+static void drawObjectConstraint(TransInfo *t);
+
+/* ************************** CONSTRAINTS ************************* */
+void constraintAutoValues(TransInfo *t, float vec[3])
+{
+ int mode = t->con.mode;
+ if (mode & CON_APPLY)
+ {
+ float nval = (t->flag & T_NULL_ONE)?1.0f:0.0f;
+
+ if ((mode & CON_AXIS0) == 0)
+ {
+ vec[0] = nval;
+ }
+ if ((mode & CON_AXIS1) == 0)
+ {
+ vec[1] = nval;
+ }
+ if ((mode & CON_AXIS2) == 0)
+ {
+ vec[2] = nval;
+ }
+ }
+}
+
+void constraintNumInput(TransInfo *t, float vec[3])
+{
+ int mode = t->con.mode;
+ if (mode & CON_APPLY) {
+ float nval = (t->flag & T_NULL_ONE)?1.0f:0.0f;
+
+ if (getConstraintSpaceDimension(t) == 2) {
+ int axis = mode & (CON_AXIS0|CON_AXIS1|CON_AXIS2);
+ if (axis == (CON_AXIS0|CON_AXIS1)) {
+ vec[0] = vec[0];
+ vec[1] = vec[1];
+ vec[2] = nval;
+ }
+ else if (axis == (CON_AXIS1|CON_AXIS2)) {
+ vec[2] = vec[1];
+ vec[1] = vec[0];
+ vec[0] = nval;
+ }
+ else if (axis == (CON_AXIS0|CON_AXIS2)) {
+ vec[0] = vec[0];
+ vec[2] = vec[1];
+ vec[1] = nval;
+ }
+ }
+ else if (getConstraintSpaceDimension(t) == 1) {
+ if (mode & CON_AXIS0) {
+ vec[0] = vec[0];
+ vec[1] = nval;
+ vec[2] = nval;
+ }
+ else if (mode & CON_AXIS1) {
+ vec[1] = vec[0];
+ vec[0] = nval;
+ vec[2] = nval;
+ }
+ else if (mode & CON_AXIS2) {
+ vec[2] = vec[0];
+ vec[0] = nval;
+ vec[1] = nval;
+ }
+ }
+ }
+}
+
+static void postConstraintChecks(TransInfo *t, float vec[3], float pvec[3]) {
+ int i = 0;
+
+ Mat3MulVecfl(t->con.imtx, vec);
+
+ snapGrid(t, vec);
+
+ if (t->num.flag & T_NULL_ONE) {
+ if (!(t->con.mode & CON_AXIS0))
+ vec[0] = 1.0f;
+
+ if (!(t->con.mode & CON_AXIS1))
+ vec[1] = 1.0f;
+
+ if (!(t->con.mode & CON_AXIS2))
+ vec[2] = 1.0f;
+ }
+
+ if (hasNumInput(&t->num)) {
+ applyNumInput(&t->num, vec);
+ constraintNumInput(t, vec);
+ }
+
+ /* autovalues is operator param, use that directly but not if snapping is forced */
+ if (t->flag & T_AUTOVALUES && (t->tsnap.status & SNAP_FORCED) == 0)
+ {
+ VECCOPY(vec, t->auto_values);
+ constraintAutoValues(t, vec);
+ }
+
+ if (t->con.mode & CON_AXIS0) {
+ pvec[i++] = vec[0];
+ }
+ if (t->con.mode & CON_AXIS1) {
+ pvec[i++] = vec[1];
+ }
+ if (t->con.mode & CON_AXIS2) {
+ pvec[i++] = vec[2];
+ }
+
+ Mat3MulVecfl(t->con.mtx, vec);
+}
+
+static void axisProjection(TransInfo *t, float axis[3], float in[3], float out[3]) {
+ float norm[3], vec[3], factor;
+
+ if(in[0]==0.0f && in[1]==0.0f && in[2]==0.0f)
+ return;
+
+ /* For when view is parallel to constraint... will cause NaNs otherwise
+ So we take vertical motion in 3D space and apply it to the
+ constraint axis. Nice for camera grab + MMB */
+ if(1.0f - fabs(Inpf(axis, t->viewinv[2])) < 0.000001f) {
+ Projf(vec, in, t->viewinv[1]);
+ factor = Inpf(t->viewinv[1], vec) * 2.0f;
+ /* since camera distance is quite relative, use quadratic relationship. holding shift can compensate */
+ if(factor<0.0f) factor*= -factor;
+ else factor*= factor;
+
+ VECCOPY(out, axis);
+ Normalize(out);
+ VecMulf(out, -factor); /* -factor makes move down going backwards */
+ }
+ else {
+ float cb[3], ab[3];
+
+ VECCOPY(out, axis);
+
+ /* Get view vector on axis to define a plane */
+ VecAddf(vec, t->con.center, in);
+ getViewVector(t, vec, norm);
+
+ Crossf(vec, norm, axis);
+
+ /* Project input vector on the plane passing on axis */
+ Projf(vec, in, vec);
+ VecSubf(vec, in, vec);
+
+ /* intersect the two lines: axis and norm */
+ Crossf(cb, vec, norm);
+ Crossf(ab, axis, norm);
+
+ VecMulf(out, Inpf(cb, ab) / Inpf(ab, ab));
+ }
+}
+
+static void planeProjection(TransInfo *t, float in[3], float out[3]) {
+ float vec[3], factor, norm[3];
+
+ VecAddf(vec, in, t->con.center);
+ getViewVector(t, vec, norm);
+
+ VecSubf(vec, out, in);
+
+ factor = Inpf(vec, norm);
+ if (fabs(factor) <= 0.001) {
+ return; /* prevent divide by zero */
+ }
+ factor = Inpf(vec, vec) / factor;
+
+ VECCOPY(vec, norm);
+ VecMulf(vec, factor);
+
+ VecAddf(out, in, vec);
+}
+
+/*
+ * Generic callback for constant spacial constraints applied to linear motion
+ *
+ * The IN vector in projected into the constrained space and then further
+ * projected along the view vector.
+ * (in perspective mode, the view vector is relative to the position on screen)
+ *
+ */
+
+static void applyAxisConstraintVec(TransInfo *t, TransData *td, float in[3], float out[3], float pvec[3])
+{
+ VECCOPY(out, in);
+ if (!td && t->con.mode & CON_APPLY) {
+ Mat3MulVecfl(t->con.pmtx, out);
+
+ // With snap, a projection is alright, no need to correct for view alignment
+ if ((t->tsnap.status & SNAP_ON) == 0) {
+ if (getConstraintSpaceDimension(t) == 2) {
+ if (out[0] != 0.0f || out[1] != 0.0f || out[2] != 0.0f) {
+ planeProjection(t, in, out);
+ }
+ }
+ else if (getConstraintSpaceDimension(t) == 1) {
+ float c[3];
+
+ if (t->con.mode & CON_AXIS0) {
+ VECCOPY(c, t->con.mtx[0]);
+ }
+ else if (t->con.mode & CON_AXIS1) {
+ VECCOPY(c, t->con.mtx[1]);
+ }
+ else if (t->con.mode & CON_AXIS2) {
+ VECCOPY(c, t->con.mtx[2]);
+ }
+ axisProjection(t, c, in, out);
+ }
+ }
+ postConstraintChecks(t, out, pvec);
+ }
+}
+
+/*
+ * Generic callback for object based spacial constraints applied to linear motion
+ *
+ * At first, the following is applied to the first data in the array
+ * The IN vector in projected into the constrained space and then further
+ * projected along the view vector.
+ * (in perspective mode, the view vector is relative to the position on screen)
+ *
+ * Further down, that vector is mapped to each data's space.
+ */
+
+static void applyObjectConstraintVec(TransInfo *t, TransData *td, float in[3], float out[3], float pvec[3])
+{
+ VECCOPY(out, in);
+ if (t->con.mode & CON_APPLY) {
+ if (!td) {
+ Mat3MulVecfl(t->con.pmtx, out);
+ if (getConstraintSpaceDimension(t) == 2) {
+ if (out[0] != 0.0f || out[1] != 0.0f || out[2] != 0.0f) {
+ planeProjection(t, in, out);
+ }
+ }
+ else if (getConstraintSpaceDimension(t) == 1) {
+ float c[3];
+
+ if (t->con.mode & CON_AXIS0) {
+ VECCOPY(c, t->con.mtx[0]);
+ }
+ else if (t->con.mode & CON_AXIS1) {
+ VECCOPY(c, t->con.mtx[1]);
+ }
+ else if (t->con.mode & CON_AXIS2) {
+ VECCOPY(c, t->con.mtx[2]);
+ }
+ axisProjection(t, c, in, out);
+ }
+ postConstraintChecks(t, out, pvec);
+ VECCOPY(out, pvec);
+ }
+ else {
+ int i=0;
+
+ out[0] = out[1] = out[2] = 0.0f;
+ if (t->con.mode & CON_AXIS0) {
+ out[0] = in[i++];
+ }
+ if (t->con.mode & CON_AXIS1) {
+ out[1] = in[i++];
+ }
+ if (t->con.mode & CON_AXIS2) {
+ out[2] = in[i++];
+ }
+ Mat3MulVecfl(td->axismtx, out);
+ }
+ }
+}
+
+/*
+ * Generic callback for constant spacial constraints applied to resize motion
+ *
+ *
+ */
+
+static void applyAxisConstraintSize(TransInfo *t, TransData *td, float smat[3][3])
+{
+ if (!td && t->con.mode & CON_APPLY) {
+ float tmat[3][3];
+
+ if (!(t->con.mode & CON_AXIS0)) {
+ smat[0][0] = 1.0f;
+ }
+ if (!(t->con.mode & CON_AXIS1)) {
+ smat[1][1] = 1.0f;
+ }
+ if (!(t->con.mode & CON_AXIS2)) {
+ smat[2][2] = 1.0f;
+ }
+
+ Mat3MulMat3(tmat, smat, t->con.imtx);
+ Mat3MulMat3(smat, t->con.mtx, tmat);
+ }
+}
+
+/*
+ * Callback for object based spacial constraints applied to resize motion
+ *
+ *
+ */
+
+static void applyObjectConstraintSize(TransInfo *t, TransData *td, float smat[3][3])
+{
+ if (td && t->con.mode & CON_APPLY) {
+ float tmat[3][3];
+ float imat[3][3];
+
+ Mat3Inv(imat, td->axismtx);
+
+ if (!(t->con.mode & CON_AXIS0)) {
+ smat[0][0] = 1.0f;
+ }
+ if (!(t->con.mode & CON_AXIS1)) {
+ smat[1][1] = 1.0f;
+ }
+ if (!(t->con.mode & CON_AXIS2)) {
+ smat[2][2] = 1.0f;
+ }
+
+ Mat3MulMat3(tmat, smat, imat);
+ Mat3MulMat3(smat, td->axismtx, tmat);
+ }
+}
+
+/*
+ * Generic callback for constant spacial constraints applied to rotations
+ *
+ * The rotation axis is copied into VEC.
+ *
+ * In the case of single axis constraints, the rotation axis is directly the one constrained to.
+ * For planar constraints (2 axis), the rotation axis is the normal of the plane.
+ *
+ * The following only applies when CON_NOFLIP is not set.
+ * The vector is then modified to always point away from the screen (in global space)
+ * This insures that the rotation is always logically following the mouse.
+ * (ie: not doing counterclockwise rotations when the mouse moves clockwise).
+ */
+
+static void applyAxisConstraintRot(TransInfo *t, TransData *td, float vec[3], float *angle)
+{
+ if (!td && t->con.mode & CON_APPLY) {
+ int mode = t->con.mode & (CON_AXIS0|CON_AXIS1|CON_AXIS2);
+
+ switch(mode) {
+ case CON_AXIS0:
+ case (CON_AXIS1|CON_AXIS2):
+ VECCOPY(vec, t->con.mtx[0]);
+ break;
+ case CON_AXIS1:
+ case (CON_AXIS0|CON_AXIS2):
+ VECCOPY(vec, t->con.mtx[1]);
+ break;
+ case CON_AXIS2:
+ case (CON_AXIS0|CON_AXIS1):
+ VECCOPY(vec, t->con.mtx[2]);
+ break;
+ }
+ /* don't flip axis if asked to or if num input */
+ if (angle && (mode & CON_NOFLIP) == 0 && hasNumInput(&t->num) == 0) {
+ if (Inpf(vec, t->viewinv[2]) > 0.0f) {
+ *angle = -(*angle);
+ }
+ }
+ }
+}
+
+/*
+ * Callback for object based spacial constraints applied to rotations
+ *
+ * The rotation axis is copied into VEC.
+ *
+ * In the case of single axis constraints, the rotation axis is directly the one constrained to.
+ * For planar constraints (2 axis), the rotation axis is the normal of the plane.
+ *
+ * The following only applies when CON_NOFLIP is not set.
+ * The vector is then modified to always point away from the screen (in global space)
+ * This insures that the rotation is always logically following the mouse.
+ * (ie: not doing counterclockwise rotations when the mouse moves clockwise).
+ */
+
+static void applyObjectConstraintRot(TransInfo *t, TransData *td, float vec[3], float *angle)
+{
+ if (t->con.mode & CON_APPLY) {
+ int mode = t->con.mode & (CON_AXIS0|CON_AXIS1|CON_AXIS2);
+
+ /* on setup call, use first object */
+ if (td == NULL) {
+ td= t->data;
+ }
+
+ switch(mode) {
+ case CON_AXIS0:
+ case (CON_AXIS1|CON_AXIS2):
+ VECCOPY(vec, td->axismtx[0]);
+ break;
+ case CON_AXIS1:
+ case (CON_AXIS0|CON_AXIS2):
+ VECCOPY(vec, td->axismtx[1]);
+ break;
+ case CON_AXIS2:
+ case (CON_AXIS0|CON_AXIS1):
+ VECCOPY(vec, td->axismtx[2]);
+ break;
+ }
+ if (angle && (mode & CON_NOFLIP) == 0 && hasNumInput(&t->num) == 0) {
+ if (Inpf(vec, t->viewinv[2]) > 0.0f) {
+ *angle = -(*angle);
+ }
+ }
+ }
+}
+
+/*--------------------- INTERNAL SETUP CALLS ------------------*/
+
+void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[]) {
+ strncpy(t->con.text + 1, text, 48);
+ Mat3CpyMat3(t->con.mtx, space);
+ t->con.mode = mode;
+ getConstraintMatrix(t);
+
+ startConstraint(t);
+
+ t->con.drawExtra = NULL;
+ t->con.applyVec = applyAxisConstraintVec;
+ t->con.applySize = applyAxisConstraintSize;
+ t->con.applyRot = applyAxisConstraintRot;
+ t->redraw = 1;
+}
+
+void setLocalConstraint(TransInfo *t, int mode, const char text[]) {
+ if (t->flag & T_EDIT) {
+ float obmat[3][3];
+ Mat3CpyMat4(obmat, t->scene->obedit->obmat);
+ setConstraint(t, obmat, mode, text);
+ }
+ else {
+ if (t->total == 1) {
+ setConstraint(t, t->data->axismtx, mode, text);
+ }
+ else {
+ strncpy(t->con.text + 1, text, 48);
+ Mat3CpyMat3(t->con.mtx, t->data->axismtx);
+ t->con.mode = mode;
+ getConstraintMatrix(t);
+
+ startConstraint(t);
+
+ t->con.drawExtra = drawObjectConstraint;
+ t->con.applyVec = applyObjectConstraintVec;
+ t->con.applySize = applyObjectConstraintSize;
+ t->con.applyRot = applyObjectConstraintRot;
+ t->redraw = 1;
+ }
+ }
+}
+
+/*
+ Set the constraint according to the user defined orientation
+
+ ftext is a format string passed to sprintf. It will add the name of
+ the orientation where %s is (logically).
+*/
+void setUserConstraint(TransInfo *t, int mode, const char ftext[]) {
+ char text[40];
+ //short twmode= (t->spacetype==SPACE_VIEW3D)? ((View3D*)t->view)->twmode: V3D_MANIP_GLOBAL;
+
+ switch(t->current_orientation) {
+ case V3D_MANIP_GLOBAL:
+ {
+ float mtx[3][3];
+ sprintf(text, ftext, "global");
+ Mat3One(mtx);
+ setConstraint(t, mtx, mode, text);
+ }
+ break;
+ case V3D_MANIP_LOCAL:
+ sprintf(text, ftext, "local");
+ setLocalConstraint(t, mode, text);
+ break;
+ case V3D_MANIP_NORMAL:
+ sprintf(text, ftext, "normal");
+ setConstraint(t, t->spacemtx, mode, text);
+ break;
+ case V3D_MANIP_VIEW:
+ sprintf(text, ftext, "view");
+ setConstraint(t, t->spacemtx, mode, text);
+ break;
+ default: /* V3D_MANIP_CUSTOM */
+ sprintf(text, ftext, t->spacename);
+ setConstraint(t, t->spacemtx, mode, text);
+ break;
+ }
+
+ t->con.mode |= CON_USER;
+}
+
+/*--------------------- EXTERNAL SETUP CALLS ------------------*/
+
+void BIF_setLocalLockConstraint(char axis, char *text) {
+ TransInfo *t = BIF_GetTransInfo();
+
+ if (t->total == 0) {
+ return;
+ }
+
+ switch (axis) {
+ case 'x':
+ setLocalConstraint(t, (CON_AXIS1|CON_AXIS2), text);
+ break;
+ case 'y':
+ setLocalConstraint(t, (CON_AXIS0|CON_AXIS2), text);
+ break;
+ case 'z':
+ setLocalConstraint(t, (CON_AXIS0|CON_AXIS1), text);
+ break;
+ }
+}
+
+void BIF_setLocalAxisConstraint(char axis, char *text) {
+ TransInfo *t = BIF_GetTransInfo();
+
+ if (t->total == 0) {
+ return;
+ }
+
+ switch (axis) {
+ case 'X':
+ setLocalConstraint(t, CON_AXIS0, text);
+ break;
+ case 'Y':
+ setLocalConstraint(t, CON_AXIS1, text);
+ break;
+ case 'Z':
+ setLocalConstraint(t, CON_AXIS2, text);
+ break;
+ }
+}
+
+/* text is optional, for header print */
+void BIF_setSingleAxisConstraint(float vec[3], char *text) {
+ TransInfo *t = BIF_GetTransInfo();
+ float space[3][3], v[3];
+
+ if (t->total == 0) {
+ return;
+ }
+
+ VECCOPY(space[0], vec);
+
+ v[0] = vec[2];
+ v[1] = vec[0];
+ v[2] = vec[1];
+
+ Crossf(space[1], vec, v);
+ Crossf(space[2], vec, space[1]);
+ Mat3Ortho(space);
+
+ Mat3CpyMat3(t->con.mtx, space);
+ t->con.mode = CON_AXIS0;
+
+ getConstraintMatrix(t);
+
+ startConstraint(t);
+
+ /* start copying with an offset of 1, to reserve a spot for the SPACE char */
+ if(text)
+ {
+ strncpy(t->con.text+1, text, 48); /* 50 in struct */
+ }
+ else
+ {
+ t->con.text[1] = '\0'; /* No text */
+ }
+
+ t->con.drawExtra = NULL;
+ t->con.applyVec = applyAxisConstraintVec;
+ t->con.applySize = applyAxisConstraintSize;
+ t->con.applyRot = applyAxisConstraintRot;
+ t->redraw = 1;
+}
+
+void BIF_setDualAxisConstraint(float vec1[3], float vec2[3], char *text) {
+ TransInfo *t = BIF_GetTransInfo();
+ float space[3][3];
+
+ if (t->total == 0) {
+ return;
+ }
+
+ VECCOPY(space[0], vec1);
+ VECCOPY(space[1], vec2);
+ Crossf(space[2], space[0], space[1]);
+ Mat3Ortho(space);
+
+ Mat3CpyMat3(t->con.mtx, space);
+ t->con.mode = CON_AXIS0|CON_AXIS1;
+
+ getConstraintMatrix(t);
+
+ startConstraint(t);
+
+ /* start copying with an offset of 1, to reserve a spot for the SPACE char */
+ if(text)
+ {
+ strncpy(t->con.text+1, text, 48); /* 50 in struct */
+ }
+ else
+ {
+ t->con.text[1] = '\0'; /* No text */
+ }
+
+ t->con.drawExtra = NULL;
+ t->con.applyVec = applyAxisConstraintVec;
+ t->con.applySize = applyAxisConstraintSize;
+ t->con.applyRot = applyAxisConstraintRot;
+ t->redraw = 1;
+}
+
+/*----------------- DRAWING CONSTRAINTS -------------------*/
+
+void drawConstraint(const struct bContext *C, TransInfo *t)
+{
+ TransCon *tc = &(t->con);
+
+ if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE))
+ return;
+ if (!(tc->mode & CON_APPLY))
+ return;
+ if (t->flag & T_USES_MANIPULATOR)
+ return;
+ if (t->flag & T_NO_CONSTRAINT)
+ return;
+
+ /* nasty exception for Z constraint in camera view */
+ // TRANSFORM_FIX_ME
+// if((t->flag & T_OBJECT) && G.vd->camera==OBACT && G.vd->persp==V3D_CAMOB)
+// return;
+
+ if (tc->drawExtra) {
+ tc->drawExtra(t);
+ }
+ else {
+ if (tc->mode & CON_SELECT) {
+ float vec[3];
+ char col2[3] = {255,255,255};
+ convertViewVec(t, vec, (short)(t->mval[0] - t->con.imval[0]), (short)(t->mval[1] - t->con.imval[1]));
+ VecAddf(vec, vec, tc->center);
+
+ drawLine(t, tc->center, tc->mtx[0], 'x', 0);
+ drawLine(t, tc->center, tc->mtx[1], 'y', 0);
+ drawLine(t, tc->center, tc->mtx[2], 'z', 0);
+
+ glColor3ubv((GLubyte *)col2);
+
+ glDisable(GL_DEPTH_TEST);
+ setlinestyle(1);
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(tc->center);
+ glVertex3fv(vec);
+ glEnd();
+ setlinestyle(0);
+ // TRANSFORM_FIX_ME
+ //if(G.vd->zbuf)
+ glEnable(GL_DEPTH_TEST);
+ }
+
+ if (tc->mode & CON_AXIS0) {
+ drawLine(t, tc->center, tc->mtx[0], 'x', DRAWLIGHT);
+ }
+ if (tc->mode & CON_AXIS1) {
+ drawLine(t, tc->center, tc->mtx[1], 'y', DRAWLIGHT);
+ }
+ if (tc->mode & CON_AXIS2) {
+ drawLine(t, tc->center, tc->mtx[2], 'z', DRAWLIGHT);
+ }
+ }
+}
+
+/* called from drawview.c, as an extra per-window draw option */
+void drawPropCircle(const struct bContext *C, TransInfo *t)
+{
+ if (t->flag & T_PROP_EDIT) {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float tmat[4][4], imat[4][4];
+
+ UI_ThemeColor(TH_GRID);
+
+ if(t->spacetype == SPACE_VIEW3D && rv3d != NULL)
+ {
+ Mat4CpyMat4(tmat, rv3d->viewmat);
+ Mat4Invert(imat, tmat);
+ }
+ else
+ {
+ Mat4One(tmat);
+ Mat4One(imat);
+ }
+
+ glPushMatrix();
+
+ if((t->spacetype == SPACE_VIEW3D) && t->obedit)
+ {
+ glMultMatrixf(t->obedit->obmat); /* because t->center is in local space */
+ }
+ else if(t->spacetype == SPACE_IMAGE)
+ {
+ float aspx, aspy;
+
+ ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
+ glScalef(1.0f/aspx, 1.0f/aspy, 1.0);
+ }
+
+ set_inverted_drawing(1);
+ drawcircball(GL_LINE_LOOP, t->center, t->prop_size, imat);
+ set_inverted_drawing(0);
+
+ glPopMatrix();
+ }
+}
+
+void BIF_getPropCenter(float *center)
+{
+ TransInfo *t = BIF_GetTransInfo();
+
+ if (t && t->flag & T_PROP_EDIT) {
+ VECCOPY(center, t->center);
+ }
+ else
+ center[0] = center[1] = center[2] = 0.0f;
+}
+
+static void drawObjectConstraint(TransInfo *t) {
+ int i;
+ TransData * td = t->data;
+
+ /* Draw the first one lighter because that's the one who controls the others.
+ Meaning the transformation is projected on that one and just copied on the others
+ constraint space.
+ In a nutshell, the object with light axis is controlled by the user and the others follow.
+ Without drawing the first light, users have little clue what they are doing.
+ */
+ if (t->con.mode & CON_AXIS0) {
+ drawLine(t, td->ob->obmat[3], td->axismtx[0], 'x', DRAWLIGHT);
+ }
+ if (t->con.mode & CON_AXIS1) {
+ drawLine(t, td->ob->obmat[3], td->axismtx[1], 'y', DRAWLIGHT);
+ }
+ if (t->con.mode & CON_AXIS2) {
+ drawLine(t, td->ob->obmat[3], td->axismtx[2], 'z', DRAWLIGHT);
+ }
+
+ td++;
+
+ for(i=1;i<t->total;i++,td++) {
+ if (t->con.mode & CON_AXIS0) {
+ drawLine(t, td->ob->obmat[3], td->axismtx[0], 'x', 0);
+ }
+ if (t->con.mode & CON_AXIS1) {
+ drawLine(t, td->ob->obmat[3], td->axismtx[1], 'y', 0);
+ }
+ if (t->con.mode & CON_AXIS2) {
+ drawLine(t, td->ob->obmat[3], td->axismtx[2], 'z', 0);
+ }
+ }
+}
+
+/*--------------------- START / STOP CONSTRAINTS ---------------------- */
+
+void startConstraint(TransInfo *t) {
+ t->con.mode |= CON_APPLY;
+ *t->con.text = ' ';
+ t->num.idx_max = MIN2(getConstraintSpaceDimension(t) - 1, t->idx_max);
+}
+
+void stopConstraint(TransInfo *t) {
+ t->con.mode &= ~(CON_APPLY|CON_SELECT);
+ *t->con.text = '\0';
+ t->num.idx_max = t->idx_max;
+}
+
+void getConstraintMatrix(TransInfo *t)
+{
+ float mat[3][3];
+ Mat3Inv(t->con.imtx, t->con.mtx);
+ Mat3One(t->con.pmtx);
+
+ if (!(t->con.mode & CON_AXIS0)) {
+ t->con.pmtx[0][0] =
+ t->con.pmtx[0][1] =
+ t->con.pmtx[0][2] = 0.0f;
+ }
+
+ if (!(t->con.mode & CON_AXIS1)) {
+ t->con.pmtx[1][0] =
+ t->con.pmtx[1][1] =
+ t->con.pmtx[1][2] = 0.0f;
+ }
+
+ if (!(t->con.mode & CON_AXIS2)) {
+ t->con.pmtx[2][0] =
+ t->con.pmtx[2][1] =
+ t->con.pmtx[2][2] = 0.0f;
+ }
+
+ Mat3MulMat3(mat, t->con.pmtx, t->con.imtx);
+ Mat3MulMat3(t->con.pmtx, t->con.mtx, mat);
+}
+
+/*------------------------- MMB Select -------------------------------*/
+
+void initSelectConstraint(TransInfo *t, float mtx[3][3])
+{
+ Mat3CpyMat3(t->con.mtx, mtx);
+ t->con.mode |= CON_APPLY;
+ t->con.mode |= CON_SELECT;
+
+ setNearestAxis(t);
+ t->con.drawExtra = NULL;
+ t->con.applyVec = applyAxisConstraintVec;
+ t->con.applySize = applyAxisConstraintSize;
+ t->con.applyRot = applyAxisConstraintRot;
+}
+
+void selectConstraint(TransInfo *t) {
+ if (t->con.mode & CON_SELECT) {
+ setNearestAxis(t);
+ startConstraint(t);
+ }
+}
+
+void postSelectConstraint(TransInfo *t)
+{
+ if (!(t->con.mode & CON_SELECT))
+ return;
+
+ t->con.mode &= ~CON_AXIS0;
+ t->con.mode &= ~CON_AXIS1;
+ t->con.mode &= ~CON_AXIS2;
+ t->con.mode &= ~CON_SELECT;
+
+ setNearestAxis(t);
+
+ startConstraint(t);
+ t->redraw = 1;
+}
+
+static void setNearestAxis2d(TransInfo *t)
+{
+ /* no correction needed... just use whichever one is lower */
+ if ( abs(t->mval[0]-t->con.imval[0]) < abs(t->mval[1]-t->con.imval[1]) ) {
+ t->con.mode |= CON_AXIS1;
+ sprintf(t->con.text, " along Y axis");
+ }
+ else {
+ t->con.mode |= CON_AXIS0;
+ sprintf(t->con.text, " along X axis");
+ }
+}
+
+static void setNearestAxis3d(TransInfo *t)
+{
+ float zfac;
+ float mvec[3], axis[3], proj[3];
+ float len[3];
+ int i, icoord[2];
+
+ /* calculate mouse movement */
+ mvec[0] = (float)(t->mval[0] - t->con.imval[0]);
+ mvec[1] = (float)(t->mval[1] - t->con.imval[1]);
+ mvec[2] = 0.0f;
+
+ /* we need to correct axis length for the current zoomlevel of view,
+ this to prevent projected values to be clipped behind the camera
+ and to overflow the short integers.
+ The formula used is a bit stupid, just a simplification of the substraction
+ of two 2D points 30 pixels apart (that's the last factor in the formula) after
+ projecting them with window_to_3d_delta and then get the length of that vector.
+ */
+ zfac= t->persmat[0][3]*t->center[0]+ t->persmat[1][3]*t->center[1]+ t->persmat[2][3]*t->center[2]+ t->persmat[3][3];
+ zfac = VecLength(t->persinv[0]) * 2.0f/t->ar->winx * zfac * 30.0f;
+
+ for (i = 0; i<3; i++) {
+ VECCOPY(axis, t->con.mtx[i]);
+
+ VecMulf(axis, zfac);
+ /* now we can project to get window coordinate */
+ VecAddf(axis, axis, t->con.center);
+ projectIntView(t, axis, icoord);
+
+ axis[0] = (float)(icoord[0] - t->center2d[0]);
+ axis[1] = (float)(icoord[1] - t->center2d[1]);
+ axis[2] = 0.0f;
+
+ if (Normalize(axis) != 0.0f) {
+ Projf(proj, mvec, axis);
+ VecSubf(axis, mvec, proj);
+ len[i] = Normalize(axis);
+ }
+ else {
+ len[i] = 10000000000.0f;
+ }
+ }
+
+ if (len[0] <= len[1] && len[0] <= len[2]) {
+ if (t->modifiers & MOD_CONSTRAINT_PLANE) {
+ t->con.mode |= (CON_AXIS1|CON_AXIS2);
+ sprintf(t->con.text, " locking %s X axis", t->spacename);
+ }
+ else {
+ t->con.mode |= CON_AXIS0;
+ sprintf(t->con.text, " along %s X axis", t->spacename);
+ }
+ }
+ else if (len[1] <= len[0] && len[1] <= len[2]) {
+ if (t->modifiers & MOD_CONSTRAINT_PLANE) {
+ t->con.mode |= (CON_AXIS0|CON_AXIS2);
+ sprintf(t->con.text, " locking %s Y axis", t->spacename);
+ }
+ else {
+ t->con.mode |= CON_AXIS1;
+ sprintf(t->con.text, " along %s Y axis", t->spacename);
+ }
+ }
+ else if (len[2] <= len[1] && len[2] <= len[0]) {
+ if (t->modifiers & MOD_CONSTRAINT_PLANE) {
+ t->con.mode |= (CON_AXIS0|CON_AXIS1);
+ sprintf(t->con.text, " locking %s Z axis", t->spacename);
+ }
+ else {
+ t->con.mode |= CON_AXIS2;
+ sprintf(t->con.text, " along %s Z axis", t->spacename);
+ }
+ }
+}
+
+void setNearestAxis(TransInfo *t)
+{
+ /* clear any prior constraint flags */
+ t->con.mode &= ~CON_AXIS0;
+ t->con.mode &= ~CON_AXIS1;
+ t->con.mode &= ~CON_AXIS2;
+
+ /* constraint setting - depends on spacetype */
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* 3d-view */
+ setNearestAxis3d(t);
+ }
+ else {
+ /* assume that this means a 2D-Editor */
+ setNearestAxis2d(t);
+ }
+
+ getConstraintMatrix(t);
+}
+
+/*-------------- HELPER FUNCTIONS ----------------*/
+
+char constraintModeToChar(TransInfo *t) {
+ if ((t->con.mode & CON_APPLY)==0) {
+ return '\0';
+ }
+ switch (t->con.mode & (CON_AXIS0|CON_AXIS1|CON_AXIS2)) {
+ case (CON_AXIS0):
+ case (CON_AXIS1|CON_AXIS2):
+ return 'X';
+ case (CON_AXIS1):
+ case (CON_AXIS0|CON_AXIS2):
+ return 'Y';
+ case (CON_AXIS2):
+ case (CON_AXIS0|CON_AXIS1):
+ return 'Z';
+ default:
+ return '\0';
+ }
+}
+
+
+int isLockConstraint(TransInfo *t) {
+ int mode = t->con.mode;
+
+ if ( (mode & (CON_AXIS0|CON_AXIS1)) == (CON_AXIS0|CON_AXIS1))
+ return 1;
+
+ if ( (mode & (CON_AXIS1|CON_AXIS2)) == (CON_AXIS1|CON_AXIS2))
+ return 1;
+
+ if ( (mode & (CON_AXIS0|CON_AXIS2)) == (CON_AXIS0|CON_AXIS2))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Returns the dimension of the constraint space.
+ *
+ * For that reason, the flags always needs to be set to properly evaluate here,
+ * even if they aren't actually used in the callback function. (Which could happen
+ * for weird constraints not yet designed. Along a path for example.)
+ */
+
+int getConstraintSpaceDimension(TransInfo *t)
+{
+ int n = 0;
+
+ if (t->con.mode & CON_AXIS0)
+ n++;
+
+ if (t->con.mode & CON_AXIS1)
+ n++;
+
+ if (t->con.mode & CON_AXIS2)
+ n++;
+
+ return n;
+/*
+ Someone willing to do it criptically could do the following instead:
+
+ return t->con & (CON_AXIS0|CON_AXIS1|CON_AXIS2);
+
+ Based on the assumptions that the axis flags are one after the other and start at 1
+*/
+}
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
new file mode 100644
index 00000000000..6c7aa1ee49d
--- /dev/null
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -0,0 +1,5061 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_image_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_nla_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_particle_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_sequence_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 "DNA_listBase.h"
+#include "DNA_gpencil_types.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_blender.h"
+#include "BKE_cloth.h"
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_constraint.h"
+#include "BKE_depsgraph.h"
+#include "BKE_displist.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_effect.h"
+#include "BKE_font.h"
+#include "BKE_fcurve.h"
+#include "BKE_global.h"
+#include "BKE_lattice.h"
+#include "BKE_key.h"
+#include "BKE_main.h"
+#include "BKE_mball.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+#include "BKE_sequence.h"
+#include "BKE_pointcache.h"
+#include "BKE_softbody.h"
+#include "BKE_utildefines.h"
+#include "BKE_bmesh.h"
+#include "BKE_context.h"
+#include "BKE_report.h"
+
+//#include "BIF_editaction.h"
+//#include "BIF_editview.h"
+//#include "BIF_editlattice.h"
+//#include "BIF_editconstraint.h"
+//#include "BIF_editmesh.h"
+//#include "BIF_editnla.h"
+//#include "BIF_editsima.h"
+//#include "BIF_editparticle.h"
+#include "BIF_gl.h"
+//#include "BIF_keyframing.h"
+//#include "BIF_poseobject.h"
+//#include "BIF_meshtools.h"
+//#include "BIF_mywindow.h"
+//#include "BIF_resources.h"
+#include "BIF_retopo.h"
+//#include "BIF_screen.h"
+//#include "BIF_space.h"
+//#include "BIF_toolbox.h"
+
+#include "ED_anim_api.h"
+#include "ED_armature.h"
+#include "ED_particle.h"
+#include "ED_image.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_edit.h"
+#include "ED_object.h"
+#include "ED_mesh.h"
+#include "ED_types.h"
+#include "ED_uvedit.h"
+#include "ED_view3d.h"
+
+#include "UI_view2d.h"
+
+//#include "BSE_drawipo.h"
+//#include "BSE_edit.h"
+//#include "BSE_editipo.h"
+//#include "BSE_editipo_types.h"
+//#include "BSE_editaction_types.h"
+
+//#include "BDR_drawaction.h" // list of keyframes in action
+//#include "BDR_editobject.h" // reset_slowparents()
+//#include "BDR_gpencil.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
+//#include "editmesh.h"
+//
+//#include "blendef.h"
+//
+//#include "mydevice.h"
+
+extern ListBase editelems;
+
+#include "transform.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+/* local function prototype - for Object/Bone Constraints */
+static short constraints_list_needinv(TransInfo *t, ListBase *list);
+
+/* ************************** Functions *************************** */
+
+static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
+ TransData pivot = *head;
+ TransData *ihead = head;
+ TransData *itail = tail;
+ short connected = t->flag & T_PROP_CONNECTED;
+
+ while (head < tail)
+ {
+ if (connected) {
+ while ((tail->dist >= pivot.dist) && (head < tail))
+ tail--;
+ }
+ else {
+ while ((tail->rdist >= pivot.rdist) && (head < tail))
+ tail--;
+ }
+
+ if (head != tail)
+ {
+ *head = *tail;
+ head++;
+ }
+
+ if (connected) {
+ while ((head->dist <= pivot.dist) && (head < tail))
+ head++;
+ }
+ else {
+ while ((head->rdist <= pivot.rdist) && (head < tail))
+ head++;
+ }
+
+ if (head != tail)
+ {
+ *tail = *head;
+ tail--;
+ }
+ }
+
+ *head = pivot;
+ if (ihead < head) {
+ qsort_trans_data(t, ihead, head-1);
+ }
+ if (itail > head) {
+ qsort_trans_data(t, head+1, itail);
+ }
+}
+
+void sort_trans_data_dist(TransInfo *t) {
+ TransData *start = t->data;
+ int i = 1;
+
+ while(i < t->total && start->flag & TD_SELECTED) {
+ start++;
+ i++;
+ }
+ qsort_trans_data(t, start, t->data + t->total - 1);
+}
+
+static void sort_trans_data(TransInfo *t)
+{
+ TransData *sel, *unsel;
+ TransData temp;
+ unsel = t->data;
+ sel = t->data;
+ sel += t->total - 1;
+ while (sel > unsel) {
+ while (unsel->flag & TD_SELECTED) {
+ unsel++;
+ if (unsel == sel) {
+ return;
+ }
+ }
+ while (!(sel->flag & TD_SELECTED)) {
+ sel--;
+ if (unsel == sel) {
+ return;
+ }
+ }
+ temp = *unsel;
+ *unsel = *sel;
+ *sel = temp;
+ sel--;
+ unsel++;
+ }
+}
+
+/* distance calculated from not-selected vertex to nearest selected vertex
+ warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
+static void set_prop_dist(TransInfo *t, short with_dist)
+{
+ TransData *tob;
+ int a;
+
+ for(a=0, tob= t->data; a<t->total; a++, tob++) {
+
+ tob->rdist= 0.0f; // init, it was mallocced
+
+ if((tob->flag & TD_SELECTED)==0) {
+ TransData *td;
+ int i;
+ float dist, vec[3];
+
+ tob->rdist = -1.0f; // signal for next loop
+
+ for (i = 0, td= t->data; i < t->total; i++, td++) {
+ if(td->flag & TD_SELECTED) {
+ VecSubf(vec, tob->center, td->center);
+ Mat3MulVecfl(tob->mtx, vec);
+ dist = Normalize(vec);
+ if (tob->rdist == -1.0f) {
+ tob->rdist = dist;
+ }
+ else if (dist < tob->rdist) {
+ tob->rdist = dist;
+ }
+ }
+ else break; // by definition transdata has selected items in beginning
+ }
+ if (with_dist) {
+ tob->dist = tob->rdist;
+ }
+ }
+ }
+}
+
+/* ************************** CONVERSIONS ************************* */
+
+/* ********************* texture space ********* */
+
+static void createTransTexspace(bContext *C, TransInfo *t)
+{
+ Scene *scene = CTX_data_scene(C);
+ TransData *td;
+ Object *ob;
+ ID *id;
+ int *texflag;
+
+ ob = OBACT;
+
+ if (ob == NULL) { // Shouldn't logically happen, but still...
+ t->total = 0;
+ return;
+ }
+
+ id = ob->data;
+ if(id == NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
+ t->total = 0;
+ return;
+ }
+
+ t->total = 1;
+ td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
+ td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
+
+ td->flag= TD_SELECTED;
+ VECCOPY(td->center, ob->obmat[3]);
+ td->ob = ob;
+
+ Mat3CpyMat4(td->mtx, ob->obmat);
+ Mat3CpyMat4(td->axismtx, ob->obmat);
+ Mat3Ortho(td->axismtx);
+ Mat3Inv(td->smtx, td->mtx);
+
+ if (give_obdata_texspace(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
+ *texflag &= ~AUTOSPACE;
+ }
+
+ VECCOPY(td->iloc, td->loc);
+ VECCOPY(td->ext->irot, td->ext->rot);
+ VECCOPY(td->ext->isize, td->ext->size);
+}
+
+/* ********************* edge (for crease) ***** */
+
+static void createTransEdge(bContext *C, TransInfo *t) {
+#if 0 // TRANSFORM_FIX_ME
+ TransData *td = NULL;
+ EditEdge *eed;
+ float mtx[3][3], smtx[3][3];
+ int count=0, countsel=0;
+ int propmode = t->flag & T_PROP_EDIT;
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->h==0) {
+ if (eed->f & SELECT) countsel++;
+ if (propmode) count++;
+ }
+ }
+
+ if (countsel == 0)
+ return;
+
+ if(propmode) {
+ t->total = count;
+ }
+ else {
+ t->total = countsel;
+ }
+
+ td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
+
+ Mat3CpyMat4(mtx, t->obedit->obmat);
+ Mat3Inv(smtx, mtx);
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->h==0 && (eed->f & SELECT || propmode)) {
+ /* need to set center for center calculations */
+ VecAddf(td->center, eed->v1->co, eed->v2->co);
+ VecMulf(td->center, 0.5f);
+
+ td->loc= NULL;
+ if (eed->f & SELECT)
+ td->flag= TD_SELECTED;
+ else
+ td->flag= 0;
+
+
+ Mat3CpyMat3(td->smtx, smtx);
+ Mat3CpyMat3(td->mtx, mtx);
+
+ td->ext = NULL;
+ td->tdi = NULL;
+ if (t->mode == TFM_BWEIGHT) {
+ td->val = &(eed->bweight);
+ td->ival = eed->bweight;
+ }
+ else {
+ td->val = &(eed->crease);
+ td->ival = eed->crease;
+ }
+
+ td++;
+ }
+ }
+#endif
+}
+
+/* ********************* pose mode ************* */
+
+static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
+{
+ bConstraint *con= pchan->constraints.first;
+
+ for(;con; con= con->next) {
+ if(con->type==CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
+ bKinematicConstraint *data= con->data;
+
+ if(data->tar==NULL)
+ return data;
+ if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0)
+ return data;
+ }
+ }
+ return NULL;
+}
+
+static short apply_targetless_ik(Object *ob)
+{
+ bPoseChannel *pchan, *parchan, *chanlist[256];
+ bKinematicConstraint *data;
+ int segcount, apply= 0;
+
+ /* now we got a difficult situation... we have to find the
+ target-less IK pchans, and apply transformation to the all
+ pchans that were in the chain */
+
+ for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+ data= has_targetless_ik(pchan);
+ if(data && (data->flag & CONSTRAINT_IK_AUTO)) {
+
+ /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
+ segcount= 0;
+
+ /* exclude tip from chain? */
+ if(!(data->flag & CONSTRAINT_IK_TIP))
+ parchan= pchan->parent;
+ else
+ parchan= pchan;
+
+ /* Find the chain's root & count the segments needed */
+ for (; parchan; parchan=parchan->parent){
+ chanlist[segcount]= parchan;
+ segcount++;
+
+ if(segcount==data->rootbone || segcount>255) break; // 255 is weak
+ }
+ for(;segcount;segcount--) {
+ Bone *bone;
+ float rmat[4][4], tmat[4][4], imat[4][4];
+
+ /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
+ /* we put in channel the entire result of rmat= (channel * constraint * IK) */
+ /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
+ /* rmat = pose_mat(b) * inv( pose_mat(b-1) * offs_bone ) */
+
+ parchan= chanlist[segcount-1];
+ bone= parchan->bone;
+ bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
+
+ if(parchan->parent) {
+ Bone *parbone= parchan->parent->bone;
+ float offs_bone[4][4];
+
+ /* offs_bone = yoffs(b-1) + root(b) + bonemat(b) */
+ Mat4CpyMat3(offs_bone, bone->bone_mat);
+
+ /* The bone's root offset (is in the parent's coordinate system) */
+ VECCOPY(offs_bone[3], bone->head);
+
+ /* Get the length translation of parent (length along y axis) */
+ offs_bone[3][1]+= parbone->length;
+
+ /* pose_mat(b-1) * offs_bone */
+ if(parchan->bone->flag & BONE_HINGE) {
+ /* the rotation of the parent restposition */
+ Mat4CpyMat4(rmat, parbone->arm_mat); /* rmat used as temp */
+
+ /* the location of actual parent transform */
+ VECCOPY(rmat[3], offs_bone[3]);
+ offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
+ Mat4MulVecfl(parchan->parent->pose_mat, rmat[3]);
+
+ Mat4MulMat4(tmat, offs_bone, rmat);
+ }
+ else if(parchan->bone->flag & BONE_NO_SCALE) {
+ Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
+ Mat4Ortho(tmat);
+ }
+ else
+ Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
+
+ Mat4Invert(imat, tmat);
+ }
+ else {
+ Mat4CpyMat3(tmat, bone->bone_mat);
+
+ VECCOPY(tmat[3], bone->head);
+ Mat4Invert(imat, tmat);
+ }
+ /* result matrix */
+ Mat4MulMat4(rmat, parchan->pose_mat, imat);
+
+ /* apply and decompose, doesn't work for constraints or non-uniform scale well */
+ {
+ float rmat3[3][3], qmat[3][3], imat[3][3], smat[3][3];
+
+ Mat3CpyMat4(rmat3, rmat);
+
+ /* quaternion */
+ Mat3ToQuat(rmat3, parchan->quat);
+
+ /* for size, remove rotation */
+ /* causes problems with some constraints (so apply only if needed) */
+ if (data->flag & CONSTRAINT_IK_STRETCH) {
+ QuatToMat3(parchan->quat, qmat);
+ Mat3Inv(imat, qmat);
+ Mat3MulMat3(smat, rmat3, imat);
+ Mat3ToSize(smat, parchan->size);
+ }
+
+ /* causes problems with some constraints (e.g. childof), so disable this */
+ /* as it is IK shouldn't affect location directly */
+ /* VECCOPY(parchan->loc, rmat[3]); */
+ }
+
+ }
+
+ apply= 1;
+ data->flag &= ~CONSTRAINT_IK_AUTO;
+ }
+ }
+
+ return apply;
+}
+
+static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
+{
+ Bone *bone= pchan->bone;
+ float pmat[3][3], omat[3][3];
+ float cmat[3][3], tmat[3][3];
+ float vec[3];
+
+ VECCOPY(vec, pchan->pose_mat[3]);
+ VECCOPY(td->center, vec);
+
+ td->ob = ob;
+ td->flag = TD_SELECTED;
+ if (pchan->rotmode == PCHAN_ROT_QUAT)
+ {
+ td->flag |= TD_USEQUAT;
+ }
+ if (bone->flag & BONE_HINGE_CHILD_TRANSFORM)
+ {
+ td->flag |= TD_NOCENTER;
+ }
+
+ if (bone->flag & BONE_TRANSFORM_CHILD)
+ {
+ td->flag |= TD_NOCENTER;
+ td->flag |= TD_NO_LOC;
+ }
+
+ td->protectflag= pchan->protectflag;
+
+ td->loc = pchan->loc;
+ VECCOPY(td->iloc, pchan->loc);
+
+ td->ext->size= pchan->size;
+ VECCOPY(td->ext->isize, pchan->size);
+
+ if (pchan->rotmode) {
+ td->ext->rot= pchan->eul;
+ td->ext->quat= NULL;
+
+ VECCOPY(td->ext->irot, pchan->eul);
+ }
+ else {
+ td->ext->rot= NULL;
+ td->ext->quat= pchan->quat;
+
+ QUATCOPY(td->ext->iquat, pchan->quat);
+ }
+
+ /* proper way to get parent transform + own transform + constraints transform */
+ Mat3CpyMat4(omat, ob->obmat);
+
+ if (pchan->parent) {
+ if(pchan->bone->flag & BONE_HINGE)
+ Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);
+ else
+ Mat3CpyMat4(pmat, pchan->parent->pose_mat);
+
+ if (constraints_list_needinv(t, &pchan->constraints)) {
+ Mat3CpyMat4(tmat, pchan->constinv);
+ Mat3Inv(cmat, tmat);
+ Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, cmat, 0,0,0,0); // dang mulserie swaps args
+ }
+ else
+ Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0); // dang mulserie swaps args
+ }
+ else {
+ if (constraints_list_needinv(t, &pchan->constraints)) {
+ Mat3CpyMat4(tmat, pchan->constinv);
+ Mat3Inv(cmat, tmat);
+ Mat3MulSerie(td->mtx, pchan->bone->bone_mat, omat, cmat, 0,0,0,0,0); // dang mulserie swaps args
+ }
+ else
+ Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat); // Mat3MulMat3 has swapped args!
+ }
+
+ Mat3Inv(td->smtx, td->mtx);
+
+ /* for axismat we use bone's own transform */
+ Mat3CpyMat4(pmat, pchan->pose_mat);
+ Mat3MulMat3(td->axismtx, omat, pmat);
+ Mat3Ortho(td->axismtx);
+
+ if (t->mode==TFM_BONESIZE) {
+ bArmature *arm= t->poseobj->data;
+
+ if(arm->drawtype==ARM_ENVELOPE) {
+ td->loc= NULL;
+ td->val= &bone->dist;
+ td->ival= bone->dist;
+ }
+ else {
+ // abusive storage of scale in the loc pointer :)
+ td->loc= &bone->xwidth;
+ VECCOPY (td->iloc, td->loc);
+ td->val= NULL;
+ }
+ }
+
+ /* in this case we can do target-less IK grabbing */
+ if (t->mode==TFM_TRANSLATION) {
+ bKinematicConstraint *data= has_targetless_ik(pchan);
+ if(data) {
+ if(data->flag & CONSTRAINT_IK_TIP) {
+ VECCOPY(data->grabtarget, pchan->pose_tail);
+ }
+ else {
+ VECCOPY(data->grabtarget, pchan->pose_head);
+ }
+ td->loc = data->grabtarget;
+ VECCOPY(td->iloc, td->loc);
+ data->flag |= CONSTRAINT_IK_AUTO;
+
+ /* only object matrix correction */
+ Mat3CpyMat3 (td->mtx, omat);
+ Mat3Inv (td->smtx, td->mtx);
+ }
+ }
+
+ /* store reference to first constraint */
+ td->con= pchan->constraints.first;
+}
+
+static void bone_children_clear_transflag(TransInfo *t, ListBase *lb)
+{
+ Bone *bone= lb->first;
+
+ for(;bone;bone= bone->next) {
+ if((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED))
+ {
+ bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
+ }
+ else if (bone->flag & BONE_TRANSFORM && (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL) && t->around == V3D_LOCAL)
+ {
+ bone->flag |= BONE_TRANSFORM_CHILD;
+ }
+ else
+ {
+ bone->flag &= ~BONE_TRANSFORM;
+ }
+
+ bone_children_clear_transflag(t, &bone->childbase);
+ }
+}
+
+/* sets transform flags in the bones, returns total */
+static void set_pose_transflags(TransInfo *t, Object *ob)
+{
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+ Bone *bone;
+ int hastranslation;
+
+ t->total= 0;
+
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ bone= pchan->bone;
+ if(bone->layer & arm->layer) {
+ if(bone->flag & BONE_SELECTED)
+ bone->flag |= BONE_TRANSFORM;
+ else
+ bone->flag &= ~BONE_TRANSFORM;
+
+ bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
+ bone->flag &= ~BONE_TRANSFORM_CHILD;
+ }
+ }
+
+ /* make sure no bone can be transformed when a parent is transformed */
+ /* since pchans are depsgraph sorted, the parents are in beginning of list */
+ if(t->mode!=TFM_BONESIZE) {
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ bone= pchan->bone;
+ if(bone->flag & BONE_TRANSFORM)
+ bone_children_clear_transflag(t, &bone->childbase);
+ }
+ }
+ /* now count, and check if we have autoIK or have to switch from translate to rotate */
+ hastranslation= 0;
+
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ bone= pchan->bone;
+ if(bone->flag & BONE_TRANSFORM) {
+
+ t->total++;
+
+ if(t->mode==TFM_TRANSLATION) {
+ if( has_targetless_ik(pchan)==NULL ) {
+ if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
+ if(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM)
+ hastranslation= 1;
+ }
+ else if((pchan->protectflag & OB_LOCK_LOC)!=OB_LOCK_LOC)
+ hastranslation= 1;
+ }
+ else
+ hastranslation= 1;
+ }
+ }
+ }
+
+ /* if there are no translatable bones, do rotation */
+ if(t->mode==TFM_TRANSLATION && !hastranslation)
+ t->mode= TFM_ROTATION;
+}
+
+
+/* -------- Auto-IK ---------- */
+
+/* adjust pose-channel's auto-ik chainlen */
+static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen)
+{
+ bConstraint *con;
+
+ /* don't bother to search if no valid constraints */
+ if ((pchan->constflag & (PCHAN_HAS_IK|PCHAN_HAS_TARGET))==0)
+ return;
+
+ /* check if pchan has ik-constraint */
+ for (con= pchan->constraints.first; con; con= con->next) {
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
+ bKinematicConstraint *data= con->data;
+
+ /* only accept if a temporary one (for auto-ik) */
+ if (data->flag & CONSTRAINT_IK_TEMP) {
+ /* chainlen is new chainlen, but is limited by maximum chainlen */
+ if ((chainlen==0) || (chainlen > data->max_rootbone))
+ data->rootbone= data->max_rootbone;
+ else
+ data->rootbone= chainlen;
+ }
+ }
+ }
+}
+
+/* change the chain-length of auto-ik */
+void transform_autoik_update (TransInfo *t, short mode)
+{
+ short *chainlen= &t->scene->toolsettings->autoik_chainlen;
+ bPoseChannel *pchan;
+
+ /* mode determines what change to apply to chainlen */
+ if (mode == 1) {
+ /* mode=1 is from WHEELMOUSEDOWN... increases len */
+ (*chainlen)++;
+ }
+ else if (mode == -1) {
+ /* mode==-1 is from WHEELMOUSEUP... decreases len */
+ if (*chainlen > 0) (*chainlen)--;
+ }
+
+ /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
+ if (ELEM(NULL, t->poseobj, t->poseobj->pose))
+ return;
+
+ /* apply to all pose-channels */
+ for (pchan=t->poseobj->pose->chanbase.first; pchan; pchan=pchan->next) {
+ pchan_autoik_adjust(pchan, *chainlen);
+ }
+}
+
+/* frees temporal IKs */
+static void pose_grab_with_ik_clear(Object *ob)
+{
+ bKinematicConstraint *data;
+ bPoseChannel *pchan;
+ bConstraint *con, *next;
+
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ /* clear all temporary lock flags */
+ pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP|BONE_IK_NO_YDOF_TEMP|BONE_IK_NO_ZDOF_TEMP);
+
+ pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
+ /* remove all temporary IK-constraints added */
+ for (con= pchan->constraints.first; con; con= next) {
+ next= con->next;
+ if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
+ data= con->data;
+ if (data->flag & CONSTRAINT_IK_TEMP) {
+ BLI_remlink(&pchan->constraints, con);
+ MEM_freeN(con->data);
+ MEM_freeN(con);
+ continue;
+ }
+ pchan->constflag |= PCHAN_HAS_IK;
+ if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0))
+ pchan->constflag |= PCHAN_HAS_TARGET;
+ }
+ }
+ }
+}
+
+/* adds the IK to pchan - returns if added */
+static short pose_grab_with_ik_add(bPoseChannel *pchan)
+{
+ bKinematicConstraint *data;
+ bConstraint *con;
+ bConstraint *targetless = 0;
+
+ /* Sanity check */
+ if (pchan == NULL)
+ return 0;
+
+ /* Rule: not if there's already an IK on this channel */
+ for (con= pchan->constraints.first; con; con= con->next) {
+ if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
+ bKinematicConstraint *data= con->data;
+ if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0)) {
+ targetless = con;
+ /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
+ if (con->enforce!=0.0f) {
+ targetless->flag |= CONSTRAINT_IK_AUTO;
+ return 0;
+ }
+ }
+ if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0f))
+ return 0;
+ }
+ }
+
+ con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
+ BLI_addtail(&pchan->constraints, con);
+ pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
+ data= con->data;
+ if (targetless) { /* if exists use values from last targetless IK-constraint as base */
+ *data = *((bKinematicConstraint*)targetless->data);
+ }
+ else
+ data->flag= CONSTRAINT_IK_TIP;
+ data->flag |= CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
+ VECCOPY(data->grabtarget, pchan->pose_tail);
+ data->rootbone= 1;
+
+ /* we include only a connected chain */
+ while ((pchan) && (pchan->bone->flag & BONE_CONNECTED)) {
+ /* here, we set ik-settings for bone from pchan->protectflag */
+ if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
+ if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
+ if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
+
+ /* now we count this pchan as being included */
+ data->rootbone++;
+ pchan= pchan->parent;
+ }
+
+ /* make a copy of maximum chain-length */
+ data->max_rootbone= data->rootbone;
+
+ return 1;
+}
+
+/* bone is a candidate to get IK, but we don't do it if it has children connected */
+static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
+{
+ Bone *bonec;
+ short wentdeeper=0, added=0;
+
+ /* go deeper if children & children are connected */
+ for (bonec= bone->childbase.first; bonec; bonec= bonec->next) {
+ if (bonec->flag & BONE_CONNECTED) {
+ wentdeeper= 1;
+ added+= pose_grab_with_ik_children(pose, bonec);
+ }
+ }
+ if (wentdeeper==0) {
+ bPoseChannel *pchan= get_pose_channel(pose, bone->name);
+ if (pchan)
+ added+= pose_grab_with_ik_add(pchan);
+ }
+
+ return added;
+}
+
+/* main call which adds temporal IK chains */
+static short pose_grab_with_ik(Object *ob)
+{
+ bArmature *arm;
+ bPoseChannel *pchan, *parent;
+ Bone *bonec;
+ short tot_ik= 0;
+
+ if ((ob==NULL) || (ob->pose==NULL) || (ob->flag & OB_POSEMODE)==0)
+ return 0;
+
+ arm = ob->data;
+
+ /* Rule: allow multiple Bones (but they must be selected, and only one ik-solver per chain should get added) */
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (pchan->bone->layer & arm->layer) {
+ if (pchan->bone->flag & BONE_SELECTED) {
+ /* Rule: no IK for solitatry (unconnected) bones */
+ for (bonec=pchan->bone->childbase.first; bonec; bonec=bonec->next) {
+ if (bonec->flag & BONE_CONNECTED) {
+ break;
+ }
+ }
+ if ((pchan->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL))
+ continue;
+
+ /* rule: if selected Bone is not a root bone, it gets a temporal IK */
+ if (pchan->parent) {
+ /* only adds if there's no IK yet (and no parent bone was selected) */
+ for (parent= pchan->parent; parent; parent= parent->parent) {
+ if (parent->bone->flag & BONE_SELECTED)
+ break;
+ }
+ if (parent == NULL)
+ tot_ik += pose_grab_with_ik_add(pchan);
+ }
+ else {
+ /* rule: go over the children and add IK to the tips */
+ tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
+ }
+ }
+ }
+ }
+
+ return (tot_ik) ? 1 : 0;
+}
+
+
+/* only called with pose mode active object now */
+static void createTransPose(bContext *C, TransInfo *t, Object *ob)
+{
+ bArmature *arm;
+ bPoseChannel *pchan;
+ TransData *td;
+ TransDataExtension *tdx;
+ short ik_on= 0;
+ int i;
+
+ t->total= 0;
+
+ /* check validity of state */
+ arm= get_armature(ob);
+ if ((arm==NULL) || (ob->pose==NULL)) return;
+
+ if (arm->flag & ARM_RESTPOS) {
+ if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE)==0) {
+ // XXX use transform operator reports
+ // BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled.");
+ return;
+ }
+ }
+
+ /* do we need to add temporal IK chains? */
+ if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) {
+ ik_on= pose_grab_with_ik(ob);
+ if (ik_on) t->flag |= T_AUTOIK;
+ }
+
+ /* set flags and count total (warning, can change transform to rotate) */
+ set_pose_transflags(t, ob);
+
+ if(t->total==0) return;
+
+ t->flag |= T_POSE;
+ t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
+
+ /* init trans data */
+ td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
+ tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
+ for(i=0; i<t->total; i++, td++, tdx++) {
+ td->ext= tdx;
+ td->tdi = NULL;
+ td->val = NULL;
+ }
+
+ /* use pose channels to fill trans data */
+ td= t->data;
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (pchan->bone->flag & BONE_TRANSFORM) {
+ add_pose_transdata(t, pchan, ob, td);
+ td++;
+ }
+ }
+
+ if(td != (t->data+t->total)) {
+ // XXX use transform operator reports
+ // BKE_report(op->reports, RPT_DEBUG, "Bone selection count error.");
+ }
+
+ /* initialise initial auto=ik chainlen's? */
+ if (ik_on) transform_autoik_update(t, 0);
+}
+
+/* ********************* armature ************** */
+
+static void createTransArmatureVerts(bContext *C, TransInfo *t)
+{
+ EditBone *ebo;
+ bArmature *arm= t->obedit->data;
+ ListBase *edbo = arm->edbo;
+ TransData *td;
+ float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
+
+ t->total = 0;
+ for (ebo = edbo->first; ebo; ebo = ebo->next)
+ {
+ if(ebo->layer & arm->layer)
+ {
+ if (t->mode==TFM_BONESIZE)
+ {
+ if (ebo->flag & BONE_SELECTED)
+ t->total++;
+ }
+ else if (t->mode==TFM_BONE_ROLL)
+ {
+ if (ebo->flag & BONE_SELECTED)
+ t->total++;
+ }
+ else
+ {
+ if (ebo->flag & BONE_TIPSEL)
+ t->total++;
+ if (ebo->flag & BONE_ROOTSEL)
+ t->total++;
+ }
+ }
+ }
+
+ if (!t->total) return;
+
+ Mat3CpyMat4(mtx, t->obedit->obmat);
+ Mat3Inv(smtx, mtx);
+
+ td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
+
+ for (ebo = edbo->first; ebo; ebo = ebo->next)
+ {
+ ebo->oldlength = ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
+
+ if(ebo->layer & arm->layer) {
+ if (t->mode==TFM_BONE_ENVELOPE)
+ {
+ if (ebo->flag & BONE_ROOTSEL)
+ {
+ td->val= &ebo->rad_head;
+ td->ival= *td->val;
+
+ VECCOPY (td->center, ebo->head);
+ td->flag= TD_SELECTED;
+
+ Mat3CpyMat3(td->smtx, smtx);
+ Mat3CpyMat3(td->mtx, mtx);
+
+ td->loc = NULL;
+ td->ext = NULL;
+ td->tdi = NULL;
+
+ td++;
+ }
+ if (ebo->flag & BONE_TIPSEL)
+ {
+ td->val= &ebo->rad_tail;
+ td->ival= *td->val;
+ VECCOPY (td->center, ebo->tail);
+ td->flag= TD_SELECTED;
+
+ Mat3CpyMat3(td->smtx, smtx);
+ Mat3CpyMat3(td->mtx, mtx);
+
+ td->loc = NULL;
+ td->ext = NULL;
+ td->tdi = NULL;
+
+ td++;
+ }
+
+ }
+ else if (t->mode==TFM_BONESIZE)
+ {
+ if (ebo->flag & BONE_SELECTED) {
+ if(arm->drawtype==ARM_ENVELOPE)
+ {
+ td->loc= NULL;
+ td->val= &ebo->dist;
+ td->ival= ebo->dist;
+ }
+ else
+ {
+ // abusive storage of scale in the loc pointer :)
+ td->loc= &ebo->xwidth;
+ VECCOPY (td->iloc, td->loc);
+ td->val= NULL;
+ }
+ VECCOPY (td->center, ebo->head);
+ td->flag= TD_SELECTED;
+
+ /* use local bone matrix */
+ VecSubf(delta, ebo->tail, ebo->head);
+ vec_roll_to_mat3(delta, ebo->roll, bonemat);
+ Mat3MulMat3(td->mtx, mtx, bonemat);
+ Mat3Inv(td->smtx, td->mtx);
+
+ Mat3CpyMat3(td->axismtx, td->mtx);
+ Mat3Ortho(td->axismtx);
+
+ td->ext = NULL;
+ td->tdi = NULL;
+
+ td++;
+ }
+ }
+ else if (t->mode==TFM_BONE_ROLL)
+ {
+ if (ebo->flag & BONE_SELECTED)
+ {
+ td->loc= NULL;
+ td->val= &(ebo->roll);
+ td->ival= ebo->roll;
+
+ VECCOPY (td->center, ebo->head);
+ td->flag= TD_SELECTED;
+
+ td->ext = NULL;
+ td->tdi = NULL;
+
+ td++;
+ }
+ }
+ else
+ {
+ if (ebo->flag & BONE_TIPSEL)
+ {
+ VECCOPY (td->iloc, ebo->tail);
+ VECCOPY (td->center, td->iloc);
+ td->loc= ebo->tail;
+ td->flag= TD_SELECTED;
+ if (ebo->flag & BONE_EDITMODE_LOCKED)
+ td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
+
+ Mat3CpyMat3(td->smtx, smtx);
+ Mat3CpyMat3(td->mtx, mtx);
+
+ VecSubf(delta, ebo->tail, ebo->head);
+ vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
+
+ if ((ebo->flag & BONE_ROOTSEL) == 0)
+ {
+ td->extra = ebo;
+ }
+
+ td->ext = NULL;
+ td->tdi = NULL;
+ td->val = NULL;
+
+ td++;
+ }
+ if (ebo->flag & BONE_ROOTSEL)
+ {
+ VECCOPY (td->iloc, ebo->head);
+ VECCOPY (td->center, td->iloc);
+ td->loc= ebo->head;
+ td->flag= TD_SELECTED;
+ if (ebo->flag & BONE_EDITMODE_LOCKED)
+ td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
+
+ Mat3CpyMat3(td->smtx, smtx);
+ Mat3CpyMat3(td->mtx, mtx);
+
+ VecSubf(delta, ebo->tail, ebo->head);
+ vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
+
+ td->extra = ebo; /* to fix roll */
+
+ td->ext = NULL;
+ td->tdi = NULL;
+ td->val = NULL;
+
+ td++;
+ }
+ }
+ }
+ }
+}
+
+/* ********************* meta elements ********* */
+
+static void createTransMBallVerts(bContext *C, TransInfo *t)
+{
+ // TRANSFORM_FIX_ME
+#if 0
+ MetaElem *ml;
+ TransData *td;
+ TransDataExtension *tx;
+ float mtx[3][3], smtx[3][3];
+ int count=0, countsel=0;
+ int propmode = t->flag & T_PROP_EDIT;
+
+ /* count totals */
+ for(ml= editelems.first; ml; ml= ml->next) {
+ if(ml->flag & SELECT) countsel++;
+ if(propmode) count++;
+ }
+
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel==0) return;
+
+ if(propmode) t->total = count;
+ else t->total = countsel;
+
+ td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
+ tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
+
+ Mat3CpyMat4(mtx, t->obedit->obmat);
+ Mat3Inv(smtx, mtx);
+
+ for(ml= editelems.first; ml; ml= ml->next) {
+ if(propmode || (ml->flag & SELECT)) {
+ td->loc= &ml->x;
+ VECCOPY(td->iloc, td->loc);
+ VECCOPY(td->center, td->loc);
+
+ if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
+ else td->flag= TD_USEQUAT;
+
+ Mat3CpyMat3(td->smtx, smtx);
+ Mat3CpyMat3(td->mtx, mtx);
+
+ td->ext = tx;
+ td->tdi = NULL;
+
+ /* Radius of MetaElem (mass of MetaElem influence) */
+ if(ml->flag & MB_SCALE_RAD){
+ td->val = &ml->rad;
+ td->ival = ml->rad;
+ }
+ else{
+ td->val = &ml->s;
+ td->ival = ml->s;
+ }
+
+ /* expx/expy/expz determine "shape" of some MetaElem types */
+ tx->size = &ml->expx;
+ tx->isize[0] = ml->expx;
+ tx->isize[1] = ml->expy;
+ tx->isize[2] = ml->expz;
+
+ /* quat is used for rotation of MetaElem */
+ tx->quat = ml->quat;
+ QUATCOPY(tx->iquat, ml->quat);
+
+ tx->rot = NULL;
+
+ td++;
+ tx++;
+ }
+ }
+#endif
+}
+
+/* ********************* curve/surface ********* */
+
+static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
+ TransData *td, *td_near = NULL;
+ for (td = head; td<=tail; td++) {
+ if (td->flag & TD_SELECTED) {
+ td_near = td;
+ td->dist = 0.0f;
+ }
+ else if(td_near) {
+ float dist;
+ dist = VecLenf(td_near->center, td->center);
+ if (dist < (td-1)->dist) {
+ td->dist = (td-1)->dist;
+ }
+ else {
+ td->dist = dist;
+ }
+ }
+ else {
+ td->dist = MAXFLOAT;
+ td->flag |= TD_NOTCONNECTED;
+ }
+ }
+ td_near = NULL;
+ for (td = tail; td>=head; td--) {
+ if (td->flag & TD_SELECTED) {
+ td_near = td;
+ td->dist = 0.0f;
+ }
+ else if(td_near) {
+ float dist;
+ dist = VecLenf(td_near->center, td->center);
+ if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
+ td->flag &= ~TD_NOTCONNECTED;
+ if (dist < (td+1)->dist) {
+ td->dist = (td+1)->dist;
+ }
+ else {
+ td->dist = dist;
+ }
+ }
+ }
+ }
+}
+
+/* Utility function for getting the handle data from bezier's */
+TransDataCurveHandleFlags *initTransDataCurveHandes(TransData *td, struct BezTriple *bezt) {
+ TransDataCurveHandleFlags *hdata;
+ td->flag |= TD_BEZTRIPLE;
+ hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
+ hdata->ih1 = bezt->h1;
+ hdata->h1 = &bezt->h1;
+ hdata->ih2 = bezt->h2; /* incase the second is not selected */
+ hdata->h2 = &bezt->h2;
+ return hdata;
+}
+
+static void createTransCurveVerts(bContext *C, TransInfo *t)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Curve *cu= obedit->data;
+ TransData *td = NULL;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ float mtx[3][3], smtx[3][3];
+ int a;
+ int count=0, countsel=0;
+ int propmode = t->flag & T_PROP_EDIT;
+
+ /* to be sure */
+ if(cu->editnurb==NULL) return;
+
+ /* count total of vertices, check identical as in 2nd loop for making transdata! */
+ for(nu= cu->editnurb->first; nu; nu= nu->next) {
+ if((nu->type & 7)==CU_BEZIER) {
+ for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
+ if(bezt->hide==0) {
+ if (G.f & G_HIDDENHANDLES) {
+ if(bezt->f2 & SELECT) countsel+=3;
+ if(propmode) count+= 3;
+ } else {
+ if(bezt->f1 & SELECT) countsel++;
+ if(bezt->f2 & SELECT) countsel++;
+ if(bezt->f3 & SELECT) countsel++;
+ if(propmode) count+= 3;
+ }
+ }
+ }
+ }
+ else {
+ for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
+ if(bp->hide==0) {
+ if(propmode) count++;
+ if(bp->f1 & SELECT) countsel++;
+ }
+ }
+ }
+ }
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel==0) return;
+
+ if(propmode) t->total = count;
+ else t->total = countsel;
+ t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
+
+ Mat3CpyMat4(mtx, t->obedit->obmat);
+ Mat3Inv(smtx, mtx);
+
+ td = t->data;
+ for(nu= cu->editnurb->first; nu; nu= nu->next) {
+ if((nu->type & 7)==CU_BEZIER) {
+ TransData *head, *tail;
+ head = tail = td;
+ for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
+ if(bezt->hide==0) {
+ TransDataCurveHandleFlags *hdata = NULL;
+
+ if( propmode ||
+ ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
+ ((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
+ ) {
+ VECCOPY(td->iloc, bezt->vec[0]);
+ td->loc= bezt->vec[0];
+ VECCOPY(td->center, bezt->vec[1]);
+ if (G.f & G_HIDDENHANDLES) {
+ if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
+ else td->flag= 0;
+ } else {
+ if(bezt->f1 & SELECT) td->flag= TD_SELECTED;
+ else td->flag= 0;
+ }
+ td->ext = NULL;
+ td->tdi = NULL;
+ td->val = NULL;
+
+ hdata = initTransDataCurveHandes(td, bezt);
+
+ Mat3CpyMat3(td->smtx, smtx);
+ Mat3CpyMat3(td->mtx, mtx);
+
+ td++;
+ count++;
+ tail++;
+ }
+
+ /* This is the Curve Point, the other two are handles */
+ if(propmode || (bezt->f2 & SELECT)) {
+ VECCOPY(td->iloc, bezt->vec[1]);
+ td->loc= bezt->vec[1];
+ VECCOPY(td->center, td->loc);
+ if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
+ else td->flag= 0;
+ td->ext = NULL;
+ td->tdi = NULL;
+
+ if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
+ td->val = &(bezt->radius);
+ td->ival = bezt->radius;
+ } else if (t->mode==TFM_TILT) {
+ td->val = &(bezt->alfa);
+ td->ival = bezt->alfa;
+ } else {
+ td->val = NULL;
+ }
+
+ Mat3CpyMat3(td->smtx, smtx);
+ Mat3CpyMat3(td->mtx, mtx);
+
+ if ((bezt->f1&SELECT)==0 && (bezt->f3&SELECT)==0)
+ /* If the middle is selected but the sides arnt, this is needed */
+ if (hdata==NULL) { /* if the handle was not saved by the previous handle */
+ hdata = initTransDataCurveHandes(td, bezt);
+ }
+
+ td++;
+ count++;
+ tail++;
+ }
+ if( propmode ||
+ ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
+ ((bezt->f3 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
+ ) {
+ VECCOPY(td->iloc, bezt->vec[2]);
+ td->loc= bezt->vec[2];
+ VECCOPY(td->center, bezt->vec[1]);
+ if (G.f & G_HIDDENHANDLES) {
+ if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
+ else td->flag= 0;
+ } else {
+ if(bezt->f3 & SELECT) td->flag= TD_SELECTED;
+ else td->flag= 0;
+ }
+ td->ext = NULL;
+ td->tdi = NULL;
+ td->val = NULL;
+
+ if (hdata==NULL) { /* if the handle was not saved by the previous handle */
+ hdata = initTransDataCurveHandes(td, bezt);
+ }
+
+ Mat3CpyMat3(td->smtx, smtx);
+ Mat3CpyMat3(td->mtx, mtx);
+
+ td++;
+ count++;
+ tail++;
+ }
+ }
+ else if (propmode && head != tail) {
+ calc_distanceCurveVerts(head, tail-1);
+ head = tail;
+ }
+ }
+ if (propmode && head != tail)
+ calc_distanceCurveVerts(head, tail-1);
+
+ /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandes
+ * but for now just dont change handle types */
+ if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0)
+ testhandlesNurb(nu); /* sets the handles based on their selection, do this after the data is copied to the TransData */
+ }
+ else {
+ TransData *head, *tail;
+ head = tail = td;
+ for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
+ if(bp->hide==0) {
+ if(propmode || (bp->f1 & SELECT)) {
+ VECCOPY(td->iloc, bp->vec);
+ td->loc= bp->vec;
+ VECCOPY(td->center, td->loc);
+ if(bp->f1 & SELECT) td->flag= TD_SELECTED;
+ else td->flag= 0;
+ td->ext = NULL;
+ td->tdi = NULL;
+
+ if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
+ td->val = &(bp->radius);
+ td->ival = bp->radius;
+ } else {
+ td->val = &(bp->alfa);
+ td->ival = bp->alfa;
+ }
+
+ Mat3CpyMat3(td->smtx, smtx);
+ Mat3CpyMat3(td->mtx, mtx);
+
+ td++;
+ count++;
+ tail++;
+ }
+ }
+ else if (propmode && head != tail) {
+ calc_distanceCurveVerts(head, tail-1);
+ head = tail;
+ }
+ }
+ if (propmode && head != tail)
+ calc_distanceCurveVerts(head, tail-1);
+ }
+ }
+}
+
+/* ********************* lattice *************** */
+
+static void createTransLatticeVerts(bContext *C, TransInfo *t)
+{
+ Lattice *latt = ((Lattice*)t->obedit->data)->editlatt;
+ TransData *td = NULL;
+ BPoint *bp;
+ float mtx[3][3], smtx[3][3];
+ int a;
+ int count=0, countsel=0;
+ int propmode = t->flag & T_PROP_EDIT;
+
+ bp = latt->def;
+ a = latt->pntsu * latt->pntsv * latt->pntsw;
+ while(a--) {
+ if(bp->hide==0) {
+ if(bp->f1 & SELECT) countsel++;
+ if(propmode) count++;
+ }
+ bp++;
+ }
+
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel==0) return;
+
+ if(propmode) t->total = count;
+ else t->total = countsel;
+ t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
+
+ Mat3CpyMat4(mtx, t->obedit->obmat);
+ Mat3Inv(smtx, mtx);
+
+ td = t->data;
+ bp = latt->def;
+ a = latt->pntsu * latt->pntsv * latt->pntsw;
+ while(a--) {
+ if(propmode || (bp->f1 & SELECT)) {
+ if(bp->hide==0) {
+ VECCOPY(td->iloc, bp->vec);
+ td->loc= bp->vec;
+ VECCOPY(td->center, td->loc);
+ if(bp->f1 & SELECT) td->flag= TD_SELECTED;
+ else td->flag= 0;
+ Mat3CpyMat3(td->smtx, smtx);
+ Mat3CpyMat3(td->mtx, mtx);
+
+ td->ext = NULL;
+ td->tdi = NULL;
+ td->val = NULL;
+
+ td++;
+ count++;
+ }
+ }
+ bp++;
+ }
+}
+
+/* ******************* particle edit **************** */
+static void createTransParticleVerts(bContext *C, TransInfo *t)
+{
+ TransData *td = NULL;
+ TransDataExtension *tx;
+ Base *base = CTX_data_active_base(C);
+ Object *ob = CTX_data_active_object(C);
+ ParticleSystem *psys = PE_get_current(t->scene, ob);
+ ParticleSystemModifierData *psmd = NULL;
+ ParticleEditSettings *pset = PE_settings(t->scene);
+ ParticleData *pa = NULL;
+ ParticleEdit *edit;
+ ParticleEditKey *key;
+ float mat[4][4];
+ int i,k, totpart, transformparticle;
+ int count = 0, hasselected = 0;
+ int propmode = t->flag & T_PROP_EDIT;
+
+ if(psys==NULL || t->scene->selectmode==SCE_SELECT_PATH) return;
+
+ psmd = psys_get_modifier(ob,psys);
+
+ edit = psys->edit;
+ totpart = psys->totpart;
+ base->flag |= BA_HAS_RECALC_DATA;
+
+ for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
+ pa->flag &= ~PARS_TRANSFORM;
+ transformparticle= 0;
+
+ if((pa->flag & PARS_HIDE)==0) {
+ for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
+ if((key->flag&PEK_HIDE)==0) {
+ if(key->flag&PEK_SELECT) {
+ hasselected= 1;
+ transformparticle= 1;
+ }
+ else if(propmode)
+ transformparticle= 1;
+ }
+ }
+ }
+
+ if(transformparticle) {
+ count += pa->totkey;
+ pa->flag |= PARS_TRANSFORM;
+ }
+ }
+
+ /* note: in prop mode we need at least 1 selected */
+ if (hasselected==0) return;
+
+ t->total = count;
+ td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
+
+ if(t->mode == TFM_BAKE_TIME)
+ tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
+ else
+ tx = t->ext = NULL;
+
+ Mat4One(mat);
+
+ Mat4Invert(ob->imat,ob->obmat);
+
+ for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
+ TransData *head, *tail;
+ head = tail = td;
+
+ if(!(pa->flag & PARS_TRANSFORM)) continue;
+
+ psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
+
+ for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
+ VECCOPY(key->world_co, key->co);
+ Mat4MulVecfl(mat, key->world_co);
+ td->loc = key->world_co;
+
+ VECCOPY(td->iloc, td->loc);
+ VECCOPY(td->center, td->loc);
+
+ if(key->flag & PEK_SELECT)
+ td->flag |= TD_SELECTED;
+ else if(!propmode)
+ td->flag |= TD_SKIP;
+
+ Mat3One(td->mtx);
+ Mat3One(td->smtx);
+
+ /* don't allow moving roots */
+ if(k==0 && pset->flag & PE_LOCK_FIRST)
+ td->protectflag |= OB_LOCK_LOC;
+
+ td->ob = ob;
+ td->ext = tx;
+ td->tdi = NULL;
+ if(t->mode == TFM_BAKE_TIME) {
+ td->val = key->time;
+ td->ival = *(key->time);
+ /* abuse size and quat for min/max values */
+ td->flag |= TD_NO_EXT;
+ if(k==0) tx->size = 0;
+ else tx->size = (key - 1)->time;
+
+ if(k == pa->totkey - 1) tx->quat = 0;
+ else tx->quat = (key + 1)->time;
+ }
+
+ td++;
+ if(tx)
+ tx++;
+ tail++;
+ }
+ if (propmode && head != tail)
+ calc_distanceCurveVerts(head, tail - 1);
+ }
+}
+
+void flushTransParticles(TransInfo *t)
+{
+ Scene *scene = t->scene;
+ Object *ob = OBACT;
+ ParticleSystem *psys = PE_get_current(scene, ob);
+ ParticleSystemModifierData *psmd;
+ ParticleData *pa;
+ ParticleEditKey *key;
+ TransData *td;
+ float mat[4][4], imat[4][4], co[3];
+ int i, k, propmode = t->flag & T_PROP_EDIT;
+
+ psmd = psys_get_modifier(ob, psys);
+
+ /* we do transform in world space, so flush world space position
+ * back to particle local space */
+ td= t->data;
+ for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++, td++) {
+ if(!(pa->flag & PARS_TRANSFORM)) continue;
+
+ psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
+ Mat4Invert(imat,mat);
+
+ for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) {
+ VECCOPY(co, key->world_co);
+ Mat4MulVecfl(imat, co);
+
+ /* optimization for proportional edit */
+ if(!propmode || !FloatCompare(key->co, co, 0.0001f)) {
+ VECCOPY(key->co, co);
+ pa->flag |= PARS_EDIT_RECALC;
+ }
+ }
+ }
+
+ PE_update_object(scene, OBACT, 1);
+}
+
+/* ********************* mesh ****************** */
+
+/* proportional distance based on connectivity */
+#define E_VEC(a) (vectors + (3 * (a)->tmp.l))
+#define E_NEAR(a) (nears[((a)->tmp.l)])
+#define THRESHOLD 0.0001f
+static void editmesh_set_connectivity_distance(EditMesh *em, int total, float *vectors, EditVert **nears)
+{
+ EditVert *eve;
+ EditEdge *eed;
+ int i= 0, done= 1;
+
+ /* f2 flag is used for 'selection' */
+ /* tmp.l is offset on scratch array */
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->h==0) {
+ eve->tmp.l = i++;
+
+ if(eve->f & SELECT) {
+ eve->f2= 2;
+ E_NEAR(eve) = eve;
+ E_VEC(eve)[0] = 0.0f;
+ E_VEC(eve)[1] = 0.0f;
+ E_VEC(eve)[2] = 0.0f;
+ }
+ else {
+ eve->f2 = 0;
+ }
+ }
+ }
+
+
+ /* Floodfill routine */
+ /*
+ At worst this is n*n of complexity where n is number of edges
+ Best case would be n if the list is ordered perfectly.
+ Estimate is n log n in average (so not too bad)
+ */
+ while(done) {
+ done= 0;
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->h==0) {
+ EditVert *v1= eed->v1, *v2= eed->v2;
+ float *vec2 = E_VEC(v2);
+ float *vec1 = E_VEC(v1);
+
+ if (v1->f2 + v2->f2 == 4)
+ continue;
+
+ if (v1->f2) {
+ if (v2->f2) {
+ float nvec[3];
+ float len1 = VecLength(vec1);
+ float len2 = VecLength(vec2);
+ float lenn;
+ /* for v2 if not selected */
+ if (v2->f2 != 2) {
+ VecSubf(nvec, v2->co, E_NEAR(v1)->co);
+ lenn = VecLength(nvec);
+ /* 1 < n < 2 */
+ if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
+ VECCOPY(vec2, nvec);
+ E_NEAR(v2) = E_NEAR(v1);
+ done = 1;
+ }
+ /* n < 1 < 2 */
+ else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
+ VECCOPY(vec2, vec1);
+ E_NEAR(v2) = E_NEAR(v1);
+ done = 1;
+ }
+ }
+ /* for v1 if not selected */
+ if (v1->f2 != 2) {
+ VecSubf(nvec, v1->co, E_NEAR(v2)->co);
+ lenn = VecLength(nvec);
+ /* 2 < n < 1 */
+ if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
+ VECCOPY(vec1, nvec);
+ E_NEAR(v1) = E_NEAR(v2);
+ done = 1;
+ }
+ /* n < 2 < 1 */
+ else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
+ VECCOPY(vec1, vec2);
+ E_NEAR(v1) = E_NEAR(v2);
+ done = 1;
+ }
+ }
+ }
+ else {
+ v2->f2 = 1;
+ VecSubf(vec2, v2->co, E_NEAR(v1)->co);
+ /* 2 < 1 */
+ if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
+ VECCOPY(vec2, vec1);
+ }
+ E_NEAR(v2) = E_NEAR(v1);
+ done = 1;
+ }
+ }
+ else if (v2->f2) {
+ v1->f2 = 1;
+ VecSubf(vec1, v1->co, E_NEAR(v2)->co);
+ /* 2 < 1 */
+ if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
+ VECCOPY(vec1, vec2);
+ }
+ E_NEAR(v1) = E_NEAR(v2);
+ done = 1;
+ }
+ }
+ }
+ }
+}
+
+/* loop-in-a-loop I know, but we need it! (ton) */
+static void get_face_center(float *cent, EditMesh *em, EditVert *eve)
+{
+ EditFace *efa;
+
+ for(efa= em->faces.first; efa; efa= efa->next)
+ if(efa->f & SELECT)
+ if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
+ break;
+ if(efa) {
+ VECCOPY(cent, efa->cent);
+ }
+}
+
+//way to overwrite what data is edited with transform
+//static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
+static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert *eve)
+{
+ td->flag = 0;
+ //if(key)
+ // td->loc = key->co;
+ //else
+ td->loc = eve->co;
+
+ VECCOPY(td->center, td->loc);
+ if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))
+ get_face_center(td->center, em, eve);
+ VECCOPY(td->iloc, td->loc);
+
+ // Setting normals
+ VECCOPY(td->axismtx[2], eve->no);
+ td->axismtx[0][0] =
+ td->axismtx[0][1] =
+ td->axismtx[0][2] =
+ td->axismtx[1][0] =
+ td->axismtx[1][1] =
+ td->axismtx[1][2] = 0.0f;
+
+ td->ext = NULL;
+ td->tdi = NULL;
+ td->val = NULL;
+ td->extra = NULL;
+ if (t->mode == TFM_BWEIGHT) {
+ td->val = &(eve->bweight);
+ td->ival = eve->bweight;
+ }
+}
+
+/* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
+
+static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
+{
+ float *vec = userData;
+
+ vec+= 3*index;
+ VECCOPY(vec, co);
+}
+
+static int modifiers_disable_subsurf_temporary(Object *ob)
+{
+ ModifierData *md;
+ int disabled = 0;
+
+ for(md=ob->modifiers.first; md; md=md->next)
+ if(md->type==eModifierType_Subsurf)
+ if(md->mode & eModifierMode_OnCage) {
+ md->mode ^= eModifierMode_DisableTemporary;
+ disabled= 1;
+ }
+
+ return disabled;
+}
+
+/* disable subsurf temporal, get mapped cos, and enable it */
+static float *get_crazy_mapped_editverts(TransInfo *t)
+{
+ Mesh *me= t->obedit->data;
+ DerivedMesh *dm;
+ float *vertexcos;
+
+ /* disable subsurf temporal, get mapped cos, and enable it */
+ if(modifiers_disable_subsurf_temporary(t->obedit)) {
+ /* need to make new derivemesh */
+ makeDerivedMesh(t->scene, t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
+ }
+
+ /* now get the cage */
+ dm= editmesh_get_derived_cage(t->scene, t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
+
+ vertexcos= MEM_mallocN(3*sizeof(float)*me->edit_mesh->totvert, "vertexcos map");
+ dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
+
+ dm->release(dm);
+
+ /* set back the flag, no new cage needs to be built, transform does it */
+ modifiers_disable_subsurf_temporary(t->obedit);
+
+ return vertexcos;
+}
+
+#define TAN_MAKE_VEC(a, b, c) a[0]= b[0] + 0.2f*(b[0]-c[0]); a[1]= b[1] + 0.2f*(b[1]-c[1]); a[2]= b[2] + 0.2f*(b[2]-c[2])
+static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
+{
+ float vecu[3], vecv[3];
+ float q1[4], q2[4];
+
+ TAN_MAKE_VEC(vecu, v1, v2);
+ TAN_MAKE_VEC(vecv, v1, v3);
+ triatoquat(v1, vecu, vecv, q1);
+
+ TAN_MAKE_VEC(vecu, def1, def2);
+ TAN_MAKE_VEC(vecv, def1, def3);
+ triatoquat(def1, vecu, vecv, q2);
+
+ QuatSub(quat, q2, q1);
+}
+#undef TAN_MAKE_VEC
+
+static void set_crazyspace_quats(EditMesh *em, float *origcos, float *mappedcos, float *quats)
+{
+ EditVert *eve, *prev;
+ EditFace *efa;
+ float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
+ intptr_t index= 0;
+
+ /* two abused locations in vertices */
+ for(eve= em->verts.first; eve; eve= eve->next, index++) {
+ eve->tmp.p = NULL;
+ eve->prev= (EditVert *)index;
+ }
+
+ /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+
+ /* retrieve mapped coordinates */
+ v1= mappedcos + 3*(intptr_t)(efa->v1->prev);
+ v2= mappedcos + 3*(intptr_t)(efa->v2->prev);
+ v3= mappedcos + 3*(intptr_t)(efa->v3->prev);
+
+ co1= (origcos)? origcos + 3*(intptr_t)(efa->v1->prev): efa->v1->co;
+ co2= (origcos)? origcos + 3*(intptr_t)(efa->v2->prev): efa->v2->co;
+ co3= (origcos)? origcos + 3*(intptr_t)(efa->v3->prev): efa->v3->co;
+
+ if(efa->v2->tmp.p==NULL && efa->v2->f1) {
+ set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
+ efa->v2->tmp.p= (void*)quats;
+ quats+= 4;
+ }
+
+ if(efa->v4) {
+ v4= mappedcos + 3*(intptr_t)(efa->v4->prev);
+ co4= (origcos)? origcos + 3*(intptr_t)(efa->v4->prev): efa->v4->co;
+
+ if(efa->v1->tmp.p==NULL && efa->v1->f1) {
+ set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
+ efa->v1->tmp.p= (void*)quats;
+ quats+= 4;
+ }
+ if(efa->v3->tmp.p==NULL && efa->v3->f1) {
+ set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
+ efa->v3->tmp.p= (void*)quats;
+ quats+= 4;
+ }
+ if(efa->v4->tmp.p==NULL && efa->v4->f1) {
+ set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
+ efa->v4->tmp.p= (void*)quats;
+ quats+= 4;
+ }
+ }
+ else {
+ if(efa->v1->tmp.p==NULL && efa->v1->f1) {
+ set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
+ efa->v1->tmp.p= (void*)quats;
+ quats+= 4;
+ }
+ if(efa->v3->tmp.p==NULL && efa->v3->f1) {
+ set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
+ efa->v3->tmp.p= (void*)quats;
+ quats+= 4;
+ }
+ }
+ }
+
+ /* restore abused prev pointer */
+ for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
+ eve->prev= prev;
+
+}
+
+void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
+ BME_Vert *v;
+ BME_TransData *vtd;
+ TransData *tob;
+ int i;
+
+ tob = t->data = MEM_callocN(td->len*sizeof(TransData), "TransObData(Bevel tool)");
+
+ for (i=0,v=bm->verts.first;v;v=v->next) {
+ if ( (vtd = BME_get_transdata(td,v)) ) {
+ tob->loc = vtd->loc;
+ tob->val = &vtd->factor;
+ VECCOPY(tob->iloc,vtd->co);
+ VECCOPY(tob->center,vtd->org);
+ VECCOPY(tob->axismtx[0],vtd->vec);
+ tob->axismtx[1][0] = vtd->max ? *vtd->max : 0;
+ tob++;
+ i++;
+ }
+ }
+ /* since td is a memarena, it can hold more transdata than actual elements
+ * (i.e. we can't depend on td->len to determine the number of actual elements) */
+ t->total = i;
+}
+
+static void createTransEditVerts(bContext *C, TransInfo *t)
+{
+ Scene *scene = CTX_data_scene(C);
+ TransData *tob = NULL;
+ EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
+ EditVert *eve;
+ EditVert **nears = NULL;
+ EditVert *eve_act = NULL;
+ float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
+ float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
+ int count=0, countsel=0, a, totleft;
+ int propmode = t->flag & T_PROP_EDIT;
+ int mirror = 0;
+
+ if (t->flag & T_MIRROR)
+ {
+ mirror = 1;
+ }
+
+ // transform now requires awareness for select mode, so we tag the f1 flags in verts
+ if(scene->selectmode & SCE_SELECT_VERTEX) {
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->h==0 && (eve->f & SELECT))
+ eve->f1= SELECT;
+ else
+ eve->f1= 0;
+ }
+ }
+ else if(scene->selectmode & SCE_SELECT_EDGE) {
+ EditEdge *eed;
+ for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->h==0 && (eed->f & SELECT))
+ eed->v1->f1= eed->v2->f1= SELECT;
+ }
+ }
+ else {
+ EditFace *efa;
+ for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->h==0 && (efa->f & SELECT)) {
+ efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
+ if(efa->v4) efa->v4->f1= SELECT;
+ }
+ }
+ }
+
+ /* now we can count */
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->h==0) {
+ if(eve->f1) countsel++;
+ if(propmode) count++;
+ }
+ }
+
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel==0) return;
+
+ /* check active */
+ if (em->selected.last) {
+ EditSelection *ese = em->selected.last;
+ if ( ese->type == EDITVERT ) {
+ eve_act = (EditVert *)ese->data;
+ }
+ }
+
+
+ if(propmode) {
+ t->total = count;
+
+ /* allocating scratch arrays */
+ vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
+ nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
+ }
+ else t->total = countsel;
+ tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
+
+ Mat3CpyMat4(mtx, t->obedit->obmat);
+ Mat3Inv(smtx, mtx);
+
+ if(propmode) editmesh_set_connectivity_distance(em, t->total, vectors, nears);
+
+ /* detect CrazySpace [tm] */
+ if(propmode==0) {
+ if(modifiers_getCageIndex(t->obedit, NULL)>=0) {
+ if(modifiers_isDeformed(t->scene, t->obedit)) {
+ /* check if we can use deform matrices for modifier from the
+ start up to stack, they are more accurate than quats */
+ totleft= editmesh_get_first_deform_matrices(t->obedit, em, &defmats, &defcos);
+
+ /* if we still have more modifiers, also do crazyspace
+ correction with quats, relative to the coordinates after
+ the modifiers that support deform matrices (defcos) */
+ if(totleft > 0) {
+ mappedcos= get_crazy_mapped_editverts(t);
+ quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
+ set_crazyspace_quats(em, (float*)defcos, mappedcos, quats);
+ if(mappedcos)
+ MEM_freeN(mappedcos);
+ }
+
+ if(defcos)
+ MEM_freeN(defcos);
+ }
+ }
+ }
+
+ /* find out which half we do */
+ if(mirror) {
+ for (eve=em->verts.first; eve; eve=eve->next) {
+ if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
+ if(eve->co[0]<0.0f)
+ mirror = -1;
+ break;
+ }
+ }
+ }
+
+ for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
+ if(eve->h==0) {
+ if(propmode || eve->f1) {
+ VertsToTransData(t, tob, em, eve);
+
+ /* selected */
+ if(eve->f1) tob->flag |= TD_SELECTED;
+
+ /* active */
+ if(eve == eve_act) tob->flag |= TD_ACTIVE;
+
+ if(propmode) {
+ if (eve->f2) {
+ float vec[3];
+ VECCOPY(vec, E_VEC(eve));
+ Mat3MulVecfl(mtx, vec);
+ tob->dist= VecLength(vec);
+ }
+ else {
+ tob->flag |= TD_NOTCONNECTED;
+ tob->dist = MAXFLOAT;
+ }
+ }
+
+ /* CrazySpace */
+ if(defmats || (quats && eve->tmp.p)) {
+ float mat[3][3], imat[3][3], qmat[3][3];
+
+ /* use both or either quat and defmat correction */
+ if(quats && eve->tmp.f) {
+ QuatToMat3(eve->tmp.p, qmat);
+
+ if(defmats)
+ Mat3MulSerie(mat, mtx, qmat, defmats[a],
+ NULL, NULL, NULL, NULL, NULL);
+ else
+ Mat3MulMat3(mat, mtx, qmat);
+ }
+ else
+ Mat3MulMat3(mat, mtx, defmats[a]);
+
+ Mat3Inv(imat, mat);
+
+ Mat3CpyMat3(tob->smtx, imat);
+ Mat3CpyMat3(tob->mtx, mat);
+ }
+ else {
+ Mat3CpyMat3(tob->smtx, smtx);
+ Mat3CpyMat3(tob->mtx, mtx);
+ }
+
+ /* Mirror? */
+ if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
+ EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, tob->iloc); /* initializes octree on first call */
+ if(vmir != eve) tob->extra = vmir;
+ }
+ tob++;
+ }
+ }
+ }
+ if (propmode) {
+ MEM_freeN(vectors);
+ MEM_freeN(nears);
+ }
+ /* crazy space free */
+ if(quats)
+ MEM_freeN(quats);
+ if(defmats)
+ MEM_freeN(defmats);
+}
+
+/* *** NODE EDITOR *** */
+void flushTransNodes(TransInfo *t)
+{
+ int a;
+ TransData2D *td;
+
+ /* flush to 2d vector from internally used 3d vector */
+ for(a=0, td= t->data2d; a<t->total; a++, td++) {
+ td->loc2d[0]= td->loc[0];
+ td->loc2d[1]= td->loc[1];
+ }
+}
+
+/* *** SEQUENCE EDITOR *** */
+void flushTransSeq(TransInfo *t)
+{
+ ListBase *seqbasep= seq_give_editing(t->scene, FALSE)->seqbasep; /* Editing null check alredy done */
+ int a, new_frame;
+ TransData *td= t->data;
+ TransData2D *td2d= t->data2d;
+ TransDataSeq *tdsq= NULL;
+ Sequence *seq;
+
+
+
+ /* prevent updating the same seq twice
+ * if the transdata order is changed this will mess up
+ * but so will TransDataSeq */
+ Sequence *seq_prev= NULL;
+
+ /* flush to 2d vector from internally used 3d vector */
+ for(a=0; a<t->total; a++, td++, td2d++) {
+
+ tdsq= (TransDataSeq *)td->extra;
+ seq= tdsq->seq;
+ new_frame= (int)(td2d->loc[0] + 0.5f);
+
+ switch (tdsq->sel_flag) {
+ case SELECT:
+ if (seq->type != SEQ_META && seq_tx_test(seq)) /* for meta's, their children move */
+ seq->start= new_frame - tdsq->start_offset;
+
+ if (seq->depth==0) {
+ seq->machine= (int)(td2d->loc[1] + 0.5f);
+ CLAMP(seq->machine, 1, MAXSEQ);
+ }
+ break;
+ case SEQ_LEFTSEL: /* no vertical transform */
+ seq_tx_set_final_left(seq, new_frame);
+ seq_tx_handle_xlimits(seq, tdsq->flag&SEQ_LEFTSEL, tdsq->flag&SEQ_RIGHTSEL);
+ fix_single_seq(seq); /* todo - move this into aftertrans update? - old seq tx needed it anyway */
+ break;
+ case SEQ_RIGHTSEL: /* no vertical transform */
+ seq_tx_set_final_right(seq, new_frame);
+ seq_tx_handle_xlimits(seq, tdsq->flag&SEQ_LEFTSEL, tdsq->flag&SEQ_RIGHTSEL);
+ fix_single_seq(seq); /* todo - move this into aftertrans update? - old seq tx needed it anyway */
+ break;
+ }
+
+ if (seq != seq_prev) {
+ if(seq->depth==0) {
+ /* Calculate this strip and all nested strips
+ * children are ALWAYS transformed first
+ * so we dont need to do this in another loop. */
+ calc_sequence(seq);
+
+ /* test overlap, displayes red outline */
+ seq->flag &= ~SEQ_OVERLAP;
+ if( seq_test_overlap(seqbasep, seq) ) {
+ seq->flag |= SEQ_OVERLAP;
+ }
+ }
+ else {
+ calc_sequence_disp(seq);
+ }
+ }
+ seq_prev= seq;
+ }
+
+ if (t->mode == TFM_TIME_TRANSLATE) { /* originally TFM_TIME_EXTEND, transform changes */
+ /* Special annoying case here, need to calc metas with TFM_TIME_EXTEND only */
+ seq= seqbasep->first;
+
+ while(seq) {
+ if (seq->type == SEQ_META && seq->flag & SELECT)
+ calc_sequence(seq);
+ seq= seq->next;
+ }
+ }
+}
+
+/* ********************* UV ****************** */
+
+static void UVsToTransData(SpaceImage *sima, TransData *td, TransData2D *td2d, float *uv, int selected)
+{
+ float aspx, aspy;
+
+ ED_space_image_uv_aspect(sima, &aspx, &aspy);
+
+ /* uv coords are scaled by aspects. this is needed for rotations and
+ proportional editing to be consistent with the stretchted uv coords
+ that are displayed. this also means that for display and numinput,
+ and when the the uv coords are flushed, these are converted each time */
+ td2d->loc[0] = uv[0]*aspx;
+ td2d->loc[1] = uv[1]*aspy;
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = uv;
+
+ td->flag = 0;
+ td->loc = td2d->loc;
+ VECCOPY(td->center, td->loc);
+ VECCOPY(td->iloc, td->loc);
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext= NULL; td->tdi= NULL; td->val= NULL;
+
+ if(selected) {
+ td->flag |= TD_SELECTED;
+ td->dist= 0.0;
+ }
+ else {
+ td->dist= MAXFLOAT;
+ }
+ Mat3One(td->mtx);
+ Mat3One(td->smtx);
+}
+
+static void createTransUVs(bContext *C, TransInfo *t)
+{
+ SpaceImage *sima = (SpaceImage*)CTX_wm_space_data(C);
+ Image *ima = CTX_data_edit_image(C);
+ Scene *scene = CTX_data_scene(C);
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+ MTFace *tf;
+ int count=0, countsel=0;
+ int propmode = t->flag & T_PROP_EDIT;
+
+ EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
+ EditFace *efa;
+
+ if(!ED_uvedit_test(t->obedit)) return;
+
+ /* count */
+ for (efa= em->faces.first; efa; efa= efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ efa->tmp.p = tf;
+
+ if (uvedit_uv_selected(scene, efa, tf, 0)) countsel++;
+ if (uvedit_uv_selected(scene, efa, tf, 1)) countsel++;
+ if (uvedit_uv_selected(scene, efa, tf, 2)) countsel++;
+ if (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) countsel++;
+ if(propmode)
+ count += (efa->v4)? 4: 3;
+ } else {
+ efa->tmp.p = NULL;
+ }
+ }
+
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel==0) return;
+
+ t->total= (propmode)? count: countsel;
+ t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
+ /* for each 2d uv coord a 3d vector is allocated, so that they can be
+ treated just as if they were 3d verts */
+ t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
+
+ if(sima->flag & SI_CLIP_UV)
+ t->flag |= T_CLIP_UV;
+
+ td= t->data;
+ td2d= t->data2d;
+
+ for (efa= em->faces.first; efa; efa= efa->next) {
+ if ((tf=(MTFace *)efa->tmp.p)) {
+ if (propmode) {
+ UVsToTransData(sima, td++, td2d++, tf->uv[0], uvedit_uv_selected(scene, efa, tf, 0));
+ UVsToTransData(sima, td++, td2d++, tf->uv[1], uvedit_uv_selected(scene, efa, tf, 1));
+ UVsToTransData(sima, td++, td2d++, tf->uv[2], uvedit_uv_selected(scene, efa, tf, 2));
+ if(efa->v4)
+ UVsToTransData(sima, td++, td2d++, tf->uv[3], uvedit_uv_selected(scene, efa, tf, 3));
+ } else {
+ if(uvedit_uv_selected(scene, efa, tf, 0)) UVsToTransData(sima, td++, td2d++, tf->uv[0], 1);
+ if(uvedit_uv_selected(scene, efa, tf, 1)) UVsToTransData(sima, td++, td2d++, tf->uv[1], 1);
+ if(uvedit_uv_selected(scene, efa, tf, 2)) UVsToTransData(sima, td++, td2d++, tf->uv[2], 1);
+ if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) UVsToTransData(sima, td++, td2d++, tf->uv[3], 1);
+ }
+ }
+ }
+
+ if (sima->flag & SI_LIVE_UNWRAP)
+ ED_uvedit_live_unwrap_begin(t->scene, t->obedit);
+}
+
+void flushTransUVs(TransInfo *t)
+{
+ SpaceImage *sima = t->sa->spacedata.first;
+ TransData2D *td;
+ int a, width, height;
+ float aspx, aspy, invx, invy;
+
+ ED_space_image_uv_aspect(sima, &aspx, &aspy);
+ ED_space_image_size(sima, &width, &height);
+ invx= 1.0f/aspx;
+ invy= 1.0f/aspy;
+
+ /* flush to 2d vector from internally used 3d vector */
+ for(a=0, td= t->data2d; a<t->total; a++, td++) {
+ td->loc2d[0]= td->loc[0]*invx;
+ td->loc2d[1]= td->loc[1]*invy;
+
+ if((sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
+ td->loc2d[0]= (float)floor(width*td->loc2d[0] + 0.5f)/width;
+ td->loc2d[1]= (float)floor(height*td->loc2d[1] + 0.5f)/height;
+ }
+ }
+}
+
+int clipUVTransform(TransInfo *t, float *vec, int resize)
+{
+ TransData *td;
+ int a, clipx=1, clipy=1;
+ float aspx, aspy, min[2], max[2];
+
+ ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
+ min[0]= min[1]= 0.0f;
+ max[0]= aspx; max[1]= aspy;
+
+ for(a=0, td= t->data; a<t->total; a++, td++) {
+ DO_MINMAX2(td->loc, min, max);
+ }
+
+ if(resize) {
+ if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
+ vec[0] *= t->center[0]/(t->center[0] - min[0]);
+ else if(max[0] > aspx && t->center[0] < aspx)
+ vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
+ else
+ clipx= 0;
+
+ if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
+ vec[1] *= t->center[1]/(t->center[1] - min[1]);
+ else if(max[1] > aspy && t->center[1] < aspy)
+ vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
+ else
+ clipy= 0;
+ }
+ else {
+ if(min[0] < 0.0f)
+ vec[0] -= min[0];
+ else if(max[0] > aspx)
+ vec[0] -= max[0]-aspx;
+ else
+ clipx= 0;
+
+ if(min[1] < 0.0f)
+ vec[1] -= min[1];
+ else if(max[1] > aspy)
+ vec[1] -= max[1]-aspy;
+ else
+ clipy= 0;
+ }
+
+ return (clipx || clipy);
+}
+
+/* ********************* ACTION/NLA EDITOR ****************** */
+
+/* Called by special_aftertrans_update to make sure selected gp-frames replace
+ * any other gp-frames which may reside on that frame (that are not selected).
+ * It also makes sure gp-frames are still stored in chronological order after
+ * transform.
+ */
+static void posttrans_gpd_clean (bGPdata *gpd)
+{
+ bGPDlayer *gpl;
+
+ for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
+ ListBase sel_buffer = {NULL, NULL};
+ bGPDframe *gpf, *gpfn;
+ bGPDframe *gfs, *gfsn;
+
+ /* loop 1: loop through and isolate selected gp-frames to buffer
+ * (these need to be sorted as they are isolated)
+ */
+ for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
+ short added= 0;
+ gpfn= gpf->next;
+
+ if (gpf->flag & GP_FRAME_SELECT) {
+ BLI_remlink(&gpl->frames, gpf);
+
+ /* find place to add them in buffer
+ * - go backwards as most frames will still be in order,
+ * so doing it this way will be faster
+ */
+ for (gfs= sel_buffer.last; gfs; gfs= gfs->prev) {
+ /* if current (gpf) occurs after this one in buffer, add! */
+ if (gfs->framenum < gpf->framenum) {
+ BLI_insertlinkafter(&sel_buffer, gfs, gpf);
+ added= 1;
+ break;
+ }
+ }
+ if (added == 0)
+ BLI_addhead(&sel_buffer, gpf);
+ }
+ }
+
+ /* error checking: it is unlikely, but may be possible to have none selected */
+ if (sel_buffer.first == NULL)
+ continue;
+
+ /* if all were selected (i.e. gpl->frames is empty), then just transfer sel-buf over */
+ if (gpl->frames.first == NULL) {
+ gpl->frames.first= sel_buffer.first;
+ gpl->frames.last= sel_buffer.last;
+
+ continue;
+ }
+
+ /* loop 2: remove duplicates of frames in buffers */
+ for (gpf= gpl->frames.first; gpf && sel_buffer.first; gpf= gpfn) {
+ gpfn= gpf->next;
+
+ /* loop through sel_buffer, emptying stuff from front of buffer if ok */
+ for (gfs= sel_buffer.first; gfs && gpf; gfs= gfsn) {
+ gfsn= gfs->next;
+
+ /* if this buffer frame needs to go before current, add it! */
+ if (gfs->framenum < gpf->framenum) {
+ /* transfer buffer frame to frames list (before current) */
+ BLI_remlink(&sel_buffer, gfs);
+ BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
+ }
+ /* if this buffer frame is on same frame, replace current with it and stop */
+ else if (gfs->framenum == gpf->framenum) {
+ /* transfer buffer frame to frames list (before current) */
+ BLI_remlink(&sel_buffer, gfs);
+ BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
+
+ /* get rid of current frame */
+ // TRANSFORM_FIX_ME
+ //gpencil_layer_delframe(gpl, gpf);
+ }
+ }
+ }
+
+ /* if anything is still in buffer, append to end */
+ for (gfs= sel_buffer.first; gfs; gfs= gfsn) {
+ gfsn= gfs->next;
+
+ BLI_remlink(&sel_buffer, gfs);
+ BLI_addtail(&gpl->frames, gfs);
+ }
+ }
+}
+
+/* Called during special_aftertrans_update to make sure selected keyframes replace
+ * any other keyframes which may reside on that frame (that is not selected).
+ */
+static void posttrans_fcurve_clean (FCurve *fcu)
+{
+ float *selcache; /* cache for frame numbers of selected frames (icu->totvert*sizeof(float)) */
+ int len, index, i; /* number of frames in cache, item index */
+
+ /* allocate memory for the cache */
+ // TODO: investigate using GHash for this instead?
+ if (fcu->totvert == 0)
+ return;
+ selcache= MEM_callocN(sizeof(float)*fcu->totvert, "FCurveSelFrameNums");
+ len= 0;
+ index= 0;
+
+ /* We do 2 loops, 1 for marking keyframes for deletion, one for deleting
+ * as there is no guarantee what order the keyframes are exactly, even though
+ * they have been sorted by time.
+ */
+
+ /* Loop 1: find selected keyframes */
+ for (i = 0; i < fcu->totvert; i++) {
+ BezTriple *bezt= &fcu->bezt[i];
+
+ if (BEZSELECTED(bezt)) {
+ selcache[index]= bezt->vec[1][0];
+ index++;
+ len++;
+ }
+ }
+
+ /* Loop 2: delete unselected keyframes on the same frames (if any keyframes were found) */
+ if (len) {
+ for (i = 0; i < fcu->totvert; i++) {
+ BezTriple *bezt= &fcu->bezt[i];
+
+ if (BEZSELECTED(bezt) == 0) {
+ /* check beztriple should be removed according to cache */
+ for (index= 0; index < len; index++) {
+ if (IS_EQ(bezt->vec[1][0], selcache[index])) {
+ //delete_icu_key(icu, i, 0);
+ break;
+ }
+ else if (bezt->vec[1][0] > selcache[index])
+ break;
+ }
+ }
+ }
+
+ testhandles_fcurve(fcu);
+ }
+
+ /* free cache */
+ MEM_freeN(selcache);
+}
+
+
+/* Called by special_aftertrans_update to make sure selected keyframes replace
+ * any other keyframes which may reside on that frame (that is not selected).
+ * remake_action_ipos should have already been called
+ */
+static void posttrans_action_clean (bAnimContext *ac, bAction *act)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, act, ANIMCONT_ACTION);
+
+ /* loop through relevant data, removing keyframes from the ipo-blocks that were attached
+ * - all keyframes are converted in/out of global time
+ */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ if (nob) {
+ //ANIM_nla_mapping_apply_ipocurve(nob, ale->key_data, 0, 1);
+ posttrans_fcurve_clean(ale->key_data);
+ //ANIM_nla_mapping_apply_ipocurve(nob, ale->key_data, 1, 1);
+ }
+ else
+ posttrans_fcurve_clean(ale->key_data);
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+}
+
+/* ----------------------------- */
+
+/* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
+static short FrameOnMouseSide(char side, float frame, float cframe)
+{
+ /* both sides, so it doesn't matter */
+ if (side == 'B') return 1;
+
+ /* only on the named side */
+ if (side == 'R')
+ return (frame >= cframe) ? 1 : 0;
+ else
+ return (frame <= cframe) ? 1 : 0;
+}
+
+/* fully select selected beztriples, but only include if it's on the right side of cfra */
+static int count_fcurve_keys(FCurve *fcu, char side, float cfra)
+{
+ BezTriple *bezt;
+ int i, count = 0;
+
+ if (ELEM(NULL, fcu, fcu->bezt))
+ return count;
+
+ /* only include points that occur on the right side of cfra */
+ for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (bezt->f2 & SELECT) {
+ /* fully select the other two keys */
+ bezt->f1 |= SELECT;
+ bezt->f3 |= SELECT;
+
+ /* increment by 3, as there are 3 points (3 * x-coordinates) that need transform */
+ if (FrameOnMouseSide(side, bezt->vec[1][0], cfra))
+ count += 3;
+ }
+ }
+
+ return count;
+}
+
+/* fully select selected beztriples, but only include if it's on the right side of cfra */
+static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra)
+{
+ bGPDframe *gpf;
+ int count = 0;
+
+ if (gpl == NULL)
+ return count;
+
+ /* only include points that occur on the right side of cfra */
+ for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+ if (gpf->flag & GP_FRAME_SELECT) {
+ if (FrameOnMouseSide(side, (float)gpf->framenum, cfra))
+ count++;
+ }
+ }
+
+ return count;
+}
+
+/* This function assigns the information to transdata */
+static void TimeToTransData(TransData *td, float *time, Object *ob)
+{
+ /* memory is calloc'ed, so that should zero everything nicely for us */
+ td->val = time;
+ td->ival = *(time);
+
+ /* store the Object where this keyframe exists as a keyframe of the
+ * active action as td->ob. Usually, this member is only used for constraints
+ * drawing
+ */
+ td->ob= ob;
+}
+
+/* This function advances the address to which td points to, so it must return
+ * the new address so that the next time new transform data is added, it doesn't
+ * overwrite the existing ones... i.e. td = IcuToTransData(td, icu, ob, side, cfra);
+ *
+ * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
+ * on the named side are used.
+ */
+static TransData *FCurveToTransData(TransData *td, FCurve *fcu, Object *ob, char side, float cfra)
+{
+ BezTriple *bezt;
+ int i;
+
+ if (fcu == NULL)
+ return td;
+
+ for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ /* only add selected keyframes (for now, proportional edit is not enabled) */
+ if (BEZSELECTED(bezt)) {
+ /* only add if on the right 'side' of the current frame */
+ if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
+ /* each control point needs to be added separetely */
+ TimeToTransData(td, bezt->vec[0], ob);
+ td++;
+
+ TimeToTransData(td, bezt->vec[1], ob);
+ td++;
+
+ TimeToTransData(td, bezt->vec[2], ob);
+ td++;
+ }
+ }
+ }
+
+ return td;
+}
+
+/* helper struct for gp-frame transforms (only used here) */
+typedef struct tGPFtransdata {
+ float val; /* where transdata writes transform */
+ int *sdata; /* pointer to gpf->framenum */
+} tGPFtransdata;
+
+/* This function helps flush transdata written to tempdata into the gp-frames */
+void flushTransGPactionData (TransInfo *t)
+{
+ tGPFtransdata *tfd;
+ int i;
+
+ /* find the first one to start from */
+ if (t->mode == TFM_TIME_SLIDE)
+ tfd= (tGPFtransdata *)( (float *)(t->customData) + 2 );
+ else
+ tfd= (tGPFtransdata *)(t->customData);
+
+ /* flush data! */
+ for (i = 0; i < t->total; i++, tfd++) {
+ *(tfd->sdata)= (int)floor(tfd->val + 0.5);
+ }
+}
+
+/* This function advances the address to which td points to, so it must return
+ * the new address so that the next time new transform data is added, it doesn't
+ * overwrite the existing ones... i.e. td = GPLayerToTransData(td, ipo, ob, side, cfra);
+ *
+ * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
+ * on the named side are used.
+ */
+static int GPLayerToTransData (TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra)
+{
+ bGPDframe *gpf;
+ int count= 0;
+
+ /* check for select frames on right side of current frame */
+ for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+ if (gpf->flag & GP_FRAME_SELECT) {
+ if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) {
+ /* memory is calloc'ed, so that should zero everything nicely for us */
+ td->val= &tfd->val;
+ td->ival= (float)gpf->framenum;
+
+ tfd->val= (float)gpf->framenum;
+ tfd->sdata= &gpf->framenum;
+
+ /* advance td now */
+ td++;
+ tfd++;
+ count++;
+ }
+ }
+ }
+
+ return count;
+}
+
+static void createTransActionData(bContext *C, TransInfo *t)
+{
+ Scene *scene= CTX_data_scene(C);
+ TransData *td = NULL;
+ tGPFtransdata *tfd = NULL;
+
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ int count=0;
+ float cfra;
+ char side;
+
+ /* determine what type of data we are operating on */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+
+ /* filter data */
+ if (ac.datatype == ANIMCONT_GPENCIL)
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT);
+ else
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* which side of the current frame should be allowed */
+ if (t->mode == TFM_TIME_EXTEND) {
+ /* only side on which mouse is gets transformed */
+ float xmouse, ymouse;
+
+ UI_view2d_region_to_view(&ac.ar->v2d, t->imval[0], t->imval[1], &xmouse, &ymouse);
+ side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side
+ }
+ else {
+ /* normal transform - both sides of current frame are considered */
+ side = 'B';
+ }
+
+ /* loop 1: fully select ipo-keys and count how many BezTriples are selected */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(&ac, ale);
+
+ /* convert current-frame to action-time (slightly less accurate, espcially under
+ * higher scaling ratios, but is faster than converting all points)
+ */
+ if (nob)
+ cfra = get_action_frame(nob, (float)CFRA);
+ else
+ cfra = (float)CFRA;
+
+ //if (ale->type == ANIMTYPE_GPLAYER)
+ // count += count_gplayer_frames(ale->data, side, cfra);
+ //else
+ count += count_fcurve_keys(ale->key_data, side, cfra);
+ }
+
+ /* stop if trying to build list if nothing selected */
+ if (count == 0) {
+ /* cleanup temp list */
+ BLI_freelistN(&anim_data);
+ return;
+ }
+
+ /* allocate memory for data */
+ t->total= count;
+
+ t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(Action Editor)");
+ td= t->data;
+
+ if (ac.datatype == ANIMCONT_GPENCIL) {
+ if (t->mode == TFM_TIME_SLIDE) {
+ t->customData= MEM_callocN((sizeof(float)*2)+(sizeof(tGPFtransdata)*count), "TimeSlide + tGPFtransdata");
+ tfd= (tGPFtransdata *)( (float *)(t->customData) + 2 );
+ }
+ else {
+ t->customData= MEM_callocN(sizeof(tGPFtransdata)*count, "tGPFtransdata");
+ tfd= (tGPFtransdata *)(t->customData);
+ }
+ }
+ else if (t->mode == TFM_TIME_SLIDE)
+ t->customData= MEM_callocN(sizeof(float)*2, "TimeSlide Min/Max");
+
+ /* loop 2: build transdata array */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ //if (ale->type == ANIMTYPE_GPLAYER) {
+ // bGPDlayer *gpl= (bGPDlayer *)ale->data;
+ // int i;
+ //
+ // i = GPLayerToTransData(td, tfd, gpl, side, cfra);
+ // td += i;
+ // tfd += i;
+ //}
+ //else {
+ Object *nob= ANIM_nla_mapping_get(&ac, ale);
+ FCurve *fcu= (FCurve *)ale->key_data;
+
+ /* convert current-frame to action-time (slightly less accurate, espcially under
+ * higher scaling ratios, but is faster than converting all points)
+ */
+ if (nob)
+ cfra = get_action_frame(nob, (float)CFRA);
+ else
+ cfra = (float)CFRA;
+
+ td= FCurveToTransData(td, fcu, nob, side, cfra);
+ //}
+ }
+
+ /* check if we're supposed to be setting minx/maxx for TimeSlide */
+ if (t->mode == TFM_TIME_SLIDE) {
+ float min=999999999.0f, max=-999999999.0f;
+ int i;
+
+ td= (t->data + 1);
+ for (i=1; i < count; i+=3, td+=3) {
+ if (min > *(td->val)) min= *(td->val);
+ if (max < *(td->val)) max= *(td->val);
+ }
+
+ /* minx/maxx values used by TimeSlide are stored as a
+ * calloced 2-float array in t->customData. This gets freed
+ * in postTrans (T_FREE_CUSTOMDATA).
+ */
+ *((float *)(t->customData)) = min;
+ *((float *)(t->customData) + 1) = max;
+ }
+
+ /* cleanup temp list */
+ BLI_freelistN(&anim_data);
+}
+
+/* ********************* GRAPH EDITOR ************************* */
+
+
+
+/* Helper function for createTransGraphEditData, which is reponsible for associating
+ * source data with transform data
+ */
+static void bezt_to_transdata (TransData *td, TransData2D *td2d, Object *nob, float *loc, float *cent, short selected, short ishandle, short intvals)
+{
+ /* New location from td gets dumped onto the old-location of td2d, which then
+ * gets copied to the actual data at td2d->loc2d (bezt->vec[n])
+ *
+ * Due to NLA scaling, we apply NLA scaling to some of the verts here,
+ * and then that scaling will be undone after transform is done.
+ */
+
+ if (nob) {
+ td2d->loc[0] = get_action_frame_inv(nob, loc[0]);
+ td2d->loc[1] = loc[1];
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = loc;
+
+ td->loc = td2d->loc;
+ td->center[0] = get_action_frame_inv(nob, cent[0]);
+ td->center[1] = cent[1];
+ td->center[2] = 0.0f;
+
+ VECCOPY(td->iloc, td->loc);
+ }
+ else {
+ td2d->loc[0] = loc[0];
+ td2d->loc[1] = loc[1];
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = loc;
+
+ td->loc = td2d->loc;
+ VECCOPY(td->center, cent);
+ VECCOPY(td->iloc, td->loc);
+ }
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext= NULL; td->tdi= NULL; td->val= NULL;
+
+ if (selected) {
+ td->flag |= TD_SELECTED;
+ td->dist= 0.0f;
+ }
+ else
+ td->dist= MAXFLOAT;
+
+ if (ishandle)
+ td->flag |= TD_NOTIMESNAP;
+ if (intvals)
+ td->flag |= TD_INTVALUES;
+
+ Mat3One(td->mtx);
+ Mat3One(td->smtx);
+}
+
+static void createTransGraphEditData(bContext *C, TransInfo *t)
+{
+ Scene *scene= CTX_data_scene(C);
+ ARegion *ar= CTX_wm_region(C);
+ View2D *v2d= &ar->v2d;
+
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BezTriple *bezt, *prevbezt;
+ int count=0, i;
+ float cfra;
+ char side;
+
+ /* determine what type of data we are operating on */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_CURVEVISIBLE);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* which side of the current frame should be allowed */
+ // XXX we still want this mode, but how to get this using standard transform too?
+ if (t->mode == TFM_TIME_EXTEND) {
+ /* only side on which mouse is gets transformed */
+ float xmouse, ymouse;
+
+ UI_view2d_region_to_view(&ac.ar->v2d, t->imval[0], t->imval[1], &xmouse, &ymouse);
+ side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side
+ }
+ else {
+ /* normal transform - both sides of current frame are considered */
+ side = 'B';
+ }
+
+ /* loop 1: count how many BezTriples (specifically their verts) are selected (or should be edited) */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= NULL; //ANIM_nla_mapping_get(&ac, ale); // XXX we don't handle NLA mapping for now here...
+ FCurve *fcu= (FCurve *)ale->key_data;
+
+ /* convert current-frame to action-time (slightly less accurate, espcially under
+ * higher scaling ratios, but is faster than converting all points)
+ */
+ if (nob)
+ cfra = get_action_frame(nob, (float)CFRA);
+ else
+ cfra = (float)CFRA;
+
+ /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse */
+ if (fcu->bezt) {
+ for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
+ if (v2d->around == V3D_LOCAL) {
+ /* for local-pivot we only need to count the number of selected handles only, so that centerpoitns don't
+ * don't get moved wrong
+ */
+ if (bezt->ipo == BEZT_IPO_BEZ) {
+ if (bezt->f1 & SELECT) count++;
+ if (bezt->f3 & SELECT) count++;
+ }
+ else if (bezt->f2 & SELECT) count++;
+ }
+ else {
+ /* for 'normal' pivots */
+ if (bezt->ipo == BEZT_IPO_BEZ) {
+ if (bezt->f1 & SELECT) count++;
+ if (bezt->f2 & SELECT) count++;
+ if (bezt->f3 & SELECT) count++;
+ }
+ else if (bezt->f2 & SELECT) count++;
+ }
+ }
+ }
+ }
+ }
+
+ /* stop if trying to build list if nothing selected */
+ if (count == 0) {
+ /* cleanup temp list */
+ BLI_freelistN(&anim_data);
+ return;
+ }
+
+ /* allocate memory for data */
+ t->total= count;
+
+ t->data= MEM_callocN(t->total*sizeof(TransData), "TransData (Graph Editor)");
+ /* for each 2d vert a 3d vector is allocated, so that they can be treated just as if they were 3d verts */
+ t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransData2D (Graph Editor)");
+
+ td= t->data;
+ td2d= t->data2d;
+
+ /* loop 2: build transdata arrays */
+ cfra = (float)CFRA;
+
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= NULL; //ANIM_nla_mapping_get(&ac, ale); // XXX we don't handle NLA mapping here yet
+ FCurve *fcu= (FCurve *)ale->key_data;
+ short intvals= (fcu->flag & FCURVE_INT_VALUES);
+
+ /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */
+ bezt= fcu->bezt;
+ prevbezt= NULL;
+
+ for (i=0; i < fcu->totvert; i++, prevbezt=bezt, bezt++) {
+ if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
+ TransDataCurveHandleFlags *hdata = NULL;
+ short h1=1, h2=1;
+
+ /* only include handles if selected, and interpolaton mode uses beztriples */
+ if ( (!prevbezt && (bezt->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ)) ) {
+ if (bezt->f1 & SELECT) {
+ hdata = initTransDataCurveHandes(td, bezt);
+ bezt_to_transdata(td++, td2d++, nob, bezt->vec[0], bezt->vec[1], 1, 1, intvals);
+ }
+ else
+ h1= 0;
+ }
+ if (bezt->ipo == BEZT_IPO_BEZ) {
+ if (bezt->f3 & SELECT) {
+ if (hdata==NULL)
+ hdata = initTransDataCurveHandes(td, bezt);
+ bezt_to_transdata(td++, td2d++, nob, bezt->vec[2], bezt->vec[1], 1, 1, intvals);
+ }
+ else
+ h2= 0;
+ }
+
+ /* only include main vert if selected */
+ if (bezt->f2 & SELECT) {
+ /* if scaling around individuals centers, do no include keyframes */
+ if (v2d->around != V3D_LOCAL) {
+ /* if handles were not selected, store their selection status */
+ if (!(bezt->f1 & SELECT) && !(bezt->f3 & SELECT)) {
+ if (hdata == NULL)
+ hdata = initTransDataCurveHandes(td, bezt);
+ }
+
+ bezt_to_transdata(td++, td2d++, nob, bezt->vec[1], bezt->vec[1], 1, 0, intvals);
+ }
+
+ /* special hack (must be done after initTransDataCurveHandes(), as that stores handle settings to restore...):
+ * - Check if we've got entire BezTriple selected and we're scaling/rotating that point,
+ * then check if we're using auto-handles.
+ * - If so, change them auto-handles to aligned handles so that handles get affected too
+ */
+ if ((bezt->h1 == HD_AUTO) && (bezt->h2 == HD_AUTO) && ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) {
+ if (h1 && h2) {
+ bezt->h1= HD_ALIGN;
+ bezt->h2= HD_ALIGN;
+ }
+ }
+ }
+ }
+ }
+
+ /* Sets handles based on the selection */
+ testhandles_fcurve(fcu);
+ }
+
+ /* cleanup temp list */
+ BLI_freelistN(&anim_data);
+}
+
+
+/* ------------------------ */
+
+/* struct for use in re-sorting BezTriples during IPO transform */
+typedef struct BeztMap {
+ BezTriple *bezt;
+ int oldIndex; /* index of bezt in icu->bezt array before sorting */
+ int newIndex; /* index of bezt in icu->bezt array after sorting */
+ short swapHs; /* swap order of handles (-1=clear; 0=not checked, 1=swap) */
+ char pipo, cipo; /* interpolation of current and next segments */
+} BeztMap;
+
+
+/* This function converts an FCurve's BezTriple array to a BeztMap array
+ * NOTE: this allocates memory that will need to get freed later
+ */
+static BeztMap *bezt_to_beztmaps (BezTriple *bezts, int totvert)
+{
+ BezTriple *bezt= bezts;
+ BezTriple *prevbezt= NULL;
+ BeztMap *bezm, *bezms;
+ int i;
+
+ /* allocate memory for this array */
+ if (totvert==0 || bezts==NULL)
+ return NULL;
+ bezm= bezms= MEM_callocN(sizeof(BeztMap)*totvert, "BeztMaps");
+
+ /* assign beztriples to beztmaps */
+ for (i=0; i < totvert; i++, bezm++, prevbezt=bezt, bezt++) {
+ bezm->bezt= bezt;
+
+ bezm->oldIndex= i;
+ bezm->newIndex= i;
+
+ bezm->pipo= (prevbezt) ? prevbezt->ipo : bezt->ipo;
+ bezm->cipo= bezt->ipo;
+ }
+
+ return bezms;
+}
+
+/* This function copies the code of sort_time_ipocurve, but acts on BeztMap structs instead */
+static void sort_time_beztmaps (BeztMap *bezms, int totvert)
+{
+ BeztMap *bezm;
+ int i, ok= 1;
+
+ /* keep repeating the process until nothing is out of place anymore */
+ while (ok) {
+ ok= 0;
+
+ bezm= bezms;
+ i= totvert;
+ while (i--) {
+ /* is current bezm out of order (i.e. occurs later than next)? */
+ if (i > 0) {
+ if (bezm->bezt->vec[1][0] > (bezm+1)->bezt->vec[1][0]) {
+ bezm->newIndex++;
+ (bezm+1)->newIndex--;
+
+ SWAP(BeztMap, *bezm, *(bezm+1));
+
+ ok= 1;
+ }
+ }
+
+ /* do we need to check if the handles need to be swapped?
+ * optimisation: this only needs to be performed in the first loop
+ */
+ if (bezm->swapHs == 0) {
+ if ( (bezm->bezt->vec[0][0] > bezm->bezt->vec[1][0]) &&
+ (bezm->bezt->vec[2][0] < bezm->bezt->vec[1][0]) )
+ {
+ /* handles need to be swapped */
+ bezm->swapHs = 1;
+ }
+ else {
+ /* handles need to be cleared */
+ bezm->swapHs = -1;
+ }
+ }
+
+ bezm++;
+ }
+ }
+}
+
+/* This function firstly adjusts the pointers that the transdata has to each BezTriple */
+static void beztmap_to_data (TransInfo *t, FCurve *fcu, BeztMap *bezms, int totvert)
+{
+ BezTriple *bezts = fcu->bezt;
+ BeztMap *bezm;
+ TransData2D *td;
+ int i, j;
+ char *adjusted;
+
+ /* dynamically allocate an array of chars to mark whether an TransData's
+ * pointers have been fixed already, so that we don't override ones that are
+ * already done
+ */
+ adjusted= MEM_callocN(t->total, "beztmap_adjusted_map");
+
+ /* for each beztmap item, find if it is used anywhere */
+ bezm= bezms;
+ for (i= 0; i < totvert; i++, bezm++) {
+ /* loop through transdata, testing if we have a hit
+ * for the handles (vec[0]/vec[2]), we must also check if they need to be swapped...
+ */
+ td= t->data2d;
+ for (j= 0; j < t->total; j++, td++) {
+ /* skip item if already marked */
+ if (adjusted[j] != 0) continue;
+
+ /* only selected verts */
+ if (bezm->pipo == BEZT_IPO_BEZ) {
+ if (bezm->bezt->f1 & SELECT) {
+ if (td->loc2d == bezm->bezt->vec[0]) {
+ if (bezm->swapHs == 1)
+ td->loc2d= (bezts + bezm->newIndex)->vec[2];
+ else
+ td->loc2d= (bezts + bezm->newIndex)->vec[0];
+ adjusted[j] = 1;
+ }
+ }
+ }
+ if (bezm->cipo == BEZT_IPO_BEZ) {
+ if (bezm->bezt->f3 & SELECT) {
+ if (td->loc2d == bezm->bezt->vec[2]) {
+ if (bezm->swapHs == 1)
+ td->loc2d= (bezts + bezm->newIndex)->vec[0];
+ else
+ td->loc2d= (bezts + bezm->newIndex)->vec[2];
+ adjusted[j] = 1;
+ }
+ }
+ }
+ if (bezm->bezt->f2 & SELECT) {
+ if (td->loc2d == bezm->bezt->vec[1]) {
+ td->loc2d= (bezts + bezm->newIndex)->vec[1];
+ adjusted[j] = 1;
+ }
+ }
+ }
+
+ }
+
+ /* free temp memory used for 'adjusted' array */
+ MEM_freeN(adjusted);
+}
+
+/* This function is called by recalcData during the Transform loop to recalculate
+ * the handles of curves and sort the keyframes so that the curves draw correctly.
+ * It is only called if some keyframes have moved out of order.
+ *
+ * anim_data is the list of channels (F-Curves) retrieved already containing the
+ * channels to work on. It should not be freed here as it may still need to be used.
+ */
+void remake_graph_transdata (TransInfo *t, ListBase *anim_data)
+{
+ bAnimListElem *ale;
+
+ /* sort and reassign verts */
+ for (ale= anim_data->first; ale; ale= ale->next) {
+ FCurve *fcu= (FCurve *)ale->key_data;
+
+ if (fcu->bezt) {
+ BeztMap *bezm;
+
+ /* adjust transform-data pointers */
+ bezm= bezt_to_beztmaps(fcu->bezt, fcu->totvert);
+ sort_time_beztmaps(bezm, fcu->totvert);
+ beztmap_to_data(t, fcu, bezm, fcu->totvert);
+
+ /* free mapping stuff */
+ MEM_freeN(bezm);
+
+ /* re-sort actual beztriples (perhaps this could be done using the beztmaps to save time?) */
+ sort_time_fcurve(fcu);
+
+ /* make sure handles are all set correctly */
+ testhandles_fcurve(fcu);
+ }
+ }
+}
+
+/* this function is called on recalcData to apply the transforms applied
+ * to the transdata on to the actual keyframe data
+ */
+void flushTransGraphData(TransInfo *t)
+{
+ SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first;
+ TransData *td;
+ TransData2D *td2d;
+ int a;
+
+ /* flush to 2d vector from internally used 3d vector */
+ for (a=0, td= t->data, td2d=t->data2d; a<t->total; a++, td++, td2d++) {
+ /* handle snapping for time values
+ * - we should still be in NLA-mapping timespace
+ * - only apply to keyframes (but never to handles)
+ */
+ if ((td->flag & TD_NOTIMESNAP)==0) {
+ switch (sipo->autosnap) {
+ case SACTSNAP_FRAME: /* snap to nearest frame */
+ td2d->loc[0]= (float)( floor(td2d->loc[0]+0.5f) );
+ break;
+
+ case SACTSNAP_MARKER: /* snap to nearest marker */
+ //td2d->loc[0]= (float)find_nearest_marker_time(td2d->loc[0]);
+ break;
+ }
+ }
+
+ /* we need to unapply the nla-scaling from the time in some situations */
+ //if (NLA_IPO_SCALED)
+ // td2d->loc2d[0]= get_action_frame(OBACT, td2d->loc[0]);
+ //else
+ td2d->loc2d[0]= td2d->loc[0];
+
+ /* if int-values only, truncate to integers */
+ if (td->flag & TD_INTVALUES)
+ td2d->loc2d[1]= (float)((int)td2d->loc[1]);
+ else
+ td2d->loc2d[1]= td2d->loc[1];
+ }
+}
+
+
+/* **************** IpoKey stuff, for Object TransData ********** */
+
+/* while transforming */
+void add_tdi_poin(float *poin, float *old, float delta)
+{
+ if(poin) {
+ poin[0]= old[0]+delta;
+ poin[-3]= old[3]+delta;
+ poin[3]= old[6]+delta;
+ }
+}
+
+#if 0 // TRANSFORM_FIX_ME
+/* storage of bezier triple. thats why -3 and +3! */
+static void set_tdi_old(float *old, float *poin)
+{
+ old[0]= *(poin);
+ old[3]= *(poin-3);
+ old[6]= *(poin+3);
+}
+
+/* fill ipokey transdata with old vals and pointers */
+static void ipokey_to_transdata(IpoKey *ik, TransData *td)
+{
+ extern int ob_ar[]; // blenkernel ipo.c
+ TransDataIpokey *tdi= td->tdi;
+ BezTriple *bezt;
+ int a, delta= 0;
+
+ td->val= NULL; // is read on ESC
+
+ 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:
+ tdi->locx= &(bezt->vec[1][1]); break;
+ case OB_LOC_Y:
+ case OB_DLOC_Y:
+ tdi->locy= &(bezt->vec[1][1]); break;
+ case OB_LOC_Z:
+ case OB_DLOC_Z:
+ tdi->locz= &(bezt->vec[1][1]); break;
+
+ case OB_DROT_X:
+ delta= 1;
+ case OB_ROT_X:
+ tdi->rotx= &(bezt->vec[1][1]); break;
+ case OB_DROT_Y:
+ delta= 1;
+ case OB_ROT_Y:
+ tdi->roty= &(bezt->vec[1][1]); break;
+ case OB_DROT_Z:
+ delta= 1;
+ case OB_ROT_Z:
+ tdi->rotz= &(bezt->vec[1][1]); break;
+
+ case OB_SIZE_X:
+ case OB_DSIZE_X:
+ tdi->sizex= &(bezt->vec[1][1]); break;
+ case OB_SIZE_Y:
+ case OB_DSIZE_Y:
+ tdi->sizey= &(bezt->vec[1][1]); break;
+ case OB_SIZE_Z:
+ case OB_DSIZE_Z:
+ tdi->sizez= &(bezt->vec[1][1]); break;
+ }
+ }
+ }
+
+ /* oldvals for e.g. undo */
+ if(tdi->locx) set_tdi_old(tdi->oldloc, tdi->locx);
+ if(tdi->locy) set_tdi_old(tdi->oldloc+1, tdi->locy);
+ if(tdi->locz) set_tdi_old(tdi->oldloc+2, tdi->locz);
+
+ /* remember, for mapping curves ('1'=10 degrees) */
+ if(tdi->rotx) set_tdi_old(tdi->oldrot, tdi->rotx);
+ if(tdi->roty) set_tdi_old(tdi->oldrot+1, tdi->roty);
+ if(tdi->rotz) set_tdi_old(tdi->oldrot+2, tdi->rotz);
+
+ /* this is not allowed to be dsize! */
+ if(tdi->sizex) set_tdi_old(tdi->oldsize, tdi->sizex);
+ if(tdi->sizey) set_tdi_old(tdi->oldsize+1, tdi->sizey);
+ if(tdi->sizez) set_tdi_old(tdi->oldsize+2, tdi->sizez);
+
+ tdi->flag= TOB_IPO;
+ if(delta) tdi->flag |= TOB_IPODROT;
+}
+#endif
+
+/* *************************** Object Transform data ******************* */
+
+/* Little helper function for ObjectToTransData used to give certain
+ * constraints (ChildOf, FollowPath, and others that may be added)
+ * inverse corrections for transform, so that they aren't in CrazySpace.
+ * These particular constraints benefit from this, but others don't, hence
+ * this semi-hack ;-) - Aligorith
+ */
+static short constraints_list_needinv(TransInfo *t, ListBase *list)
+{
+ bConstraint *con;
+
+ /* loop through constraints, checking if there's one of the mentioned
+ * constraints needing special crazyspace corrections
+ */
+ if (list) {
+ for (con= list->first; con; con=con->next) {
+ /* only consider constraint if it is enabled, and has influence on result */
+ if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0)) {
+ /* (affirmative) returns for specific constraints here... */
+ /* constraints that require this regardless */
+ if (con->type == CONSTRAINT_TYPE_CHILDOF) return 1;
+ if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) return 1;
+ if (con->type == CONSTRAINT_TYPE_CLAMPTO) return 1;
+
+ /* constraints that require this only under special conditions */
+ if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
+ /* CopyRot constraint only does this when rotating, and offset is on */
+ bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
+
+ if ((data->flag & ROTLIKE_OFFSET) && (t->mode == TFM_ROTATION))
+ return 1;
+ }
+ }
+ }
+ }
+
+ /* no appropriate candidates found */
+ return 0;
+}
+
+
+/* This function applies the rules for transforming a strip so duplicate
+ * checks dont need to be added in multiple places.
+ *
+ * recursive, count and flag MUST be set.
+ *
+ * seq->depth must be set before running this function so we know if the strips
+ * are root level or not
+ */
+static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count, int *flag)
+{
+ /* for extend we need to do some tricks */
+ if (t->mode == TFM_TIME_EXTEND) {
+
+ /* *** Extend Transform *** */
+
+ Scene * scene= t->scene;
+ int cfra= CFRA;
+ int left= seq_tx_get_final_left(seq, 0);
+ int right= seq_tx_get_final_right(seq, 0);
+
+ if (seq->depth == 0 && ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK))) {
+ *recursive= 0;
+ *count= 0;
+ *flag= 0;
+ }
+ else if (seq->type ==SEQ_META) {
+
+ /* for meta's we only ever need to extend their children, no matter what depth
+ * just check the meta's are in the bounds */
+ if (t->frame_side=='R' && right <= cfra) *recursive= 0;
+ else if (t->frame_side=='L' && left >= cfra) *recursive= 0;
+ else *recursive= 1;
+
+ *count= 0;
+ *flag= 0;
+ }
+ else {
+
+ *recursive= 0; /* not a meta, so no thinking here */
+ *count= 1; /* unless its set to 0, extend will never set 2 handles at once */
+ *flag= (seq->flag | SELECT) & ~(SEQ_LEFTSEL|SEQ_RIGHTSEL);
+
+ if (t->frame_side=='R') {
+ if (right <= cfra) *count= *flag= 0; /* ignore */
+ else if (left > cfra) ; /* keep the selection */
+ else *flag |= SEQ_RIGHTSEL;
+ }
+ else {
+ if (left >= cfra) *count= *flag= 0; /* ignore */
+ else if (right < cfra) ; /* keep the selection */
+ else *flag |= SEQ_LEFTSEL;
+ }
+ }
+ } else {
+
+ /* *** Normal Transform *** */
+
+ if (seq->depth == 0) {
+
+ /* Count */
+
+ /* Non nested strips (resect selection and handles) */
+ if ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK)) {
+ *recursive= 0;
+ *count= 0;
+ *flag= 0;
+ }
+ else {
+ if ((seq->flag & (SEQ_LEFTSEL|SEQ_RIGHTSEL)) == (SEQ_LEFTSEL|SEQ_RIGHTSEL)) {
+ *flag= seq->flag;
+ *count= 2; /* we need 2 transdata's */
+ } else {
+ *flag= seq->flag;
+ *count= 1; /* selected or with a handle selected */
+ }
+
+ /* Recursive */
+
+ if ((seq->type == SEQ_META) && ((seq->flag & (SEQ_LEFTSEL|SEQ_RIGHTSEL)) == 0)) {
+ /* if any handles are selected, dont recurse */
+ *recursive = 1;
+ }
+ else {
+ *recursive = 0;
+ }
+ }
+ }
+ else {
+ /* Nested, different rules apply */
+
+ if (seq->type == SEQ_META) {
+ /* Meta's can only directly be moved between channels since they
+ * dont have their start and length set directly (children affect that)
+ * since this Meta is nested we dont need any of its data infact.
+ * calc_sequence() will update its settings when run on the toplevel meta */
+ *flag= 0;
+ *count= 0;
+ *recursive = 1;
+ }
+ else {
+ *flag= (seq->flag | SELECT) & ~(SEQ_LEFTSEL|SEQ_RIGHTSEL);
+ *count= 1; /* ignore the selection for nested */
+ *recursive = 0;
+ }
+ }
+ }
+}
+
+
+
+static int SeqTransCount(TransInfo *t, ListBase *seqbase, int depth)
+{
+ Sequence *seq;
+ int tot= 0, recursive, count, flag;
+
+ for (seq= seqbase->first; seq; seq= seq->next) {
+ seq->depth= depth;
+
+ SeqTransInfo(t, seq, &recursive, &count, &flag); /* ignore the flag */
+ tot += count;
+
+ if (recursive) {
+ tot += SeqTransCount(t, &seq->seqbase, depth+1);
+ }
+ }
+
+ return tot;
+}
+
+
+static TransData *SeqToTransData(TransInfo *t, TransData *td, TransData2D *td2d, TransDataSeq *tdsq, Sequence *seq, int flag, int sel_flag)
+{
+ int start_left;
+
+ switch(sel_flag) {
+ case SELECT:
+ /* Use seq_tx_get_final_left() and an offset here
+ * so transform has the left hand location of the strip.
+ * tdsq->start_offset is used when flushing the tx data back */
+ start_left= seq_tx_get_final_left(seq, 0);
+ td2d->loc[0]= start_left;
+ tdsq->start_offset= start_left - seq->start; /* use to apply the original location */
+ break;
+ case SEQ_LEFTSEL:
+ start_left= seq_tx_get_final_left(seq, 0);
+ td2d->loc[0] = start_left;
+ break;
+ case SEQ_RIGHTSEL:
+ td2d->loc[0] = seq_tx_get_final_right(seq, 0);
+ break;
+ }
+
+ td2d->loc[1] = seq->machine; /* channel - Y location */
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = NULL;
+
+
+ tdsq->seq= seq;
+
+ /* Use instead of seq->flag for nested strips and other
+ * cases where the selection may need to be modified */
+ tdsq->flag= flag;
+ tdsq->sel_flag= sel_flag;
+
+
+ td->extra= (void *)tdsq; /* allow us to update the strip from here */
+
+ td->flag = 0;
+ td->loc = td2d->loc;
+ VECCOPY(td->center, td->loc);
+ VECCOPY(td->iloc, td->loc);
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext= NULL; td->tdi= NULL; td->val= NULL;
+
+ td->flag |= TD_SELECTED;
+ td->dist= 0.0;
+
+ Mat3One(td->mtx);
+ Mat3One(td->smtx);
+
+ /* Time Transform (extend) */
+ td->val= td2d->loc;
+ td->ival= td2d->loc[0];
+
+ return td;
+}
+
+static int SeqToTransData_Recursive(TransInfo *t, ListBase *seqbase, TransData *td, TransData2D *td2d, TransDataSeq *tdsq)
+{
+ Sequence *seq;
+ int recursive, count, flag;
+ int tot= 0;
+
+ for (seq= seqbase->first; seq; seq= seq->next) {
+
+ SeqTransInfo(t, seq, &recursive, &count, &flag);
+
+ /* add children first so recalculating metastrips does nested strips first */
+ if (recursive) {
+ int tot_children= SeqToTransData_Recursive(t, &seq->seqbase, td, td2d, tdsq);
+
+ td= td + tot_children;
+ td2d= td2d + tot_children;
+ tdsq= tdsq + tot_children;
+
+ tot += tot_children;
+ }
+
+ /* use 'flag' which is derived from seq->flag but modified for special cases */
+ if (flag & SELECT) {
+ if (flag & (SEQ_LEFTSEL|SEQ_RIGHTSEL)) {
+ if (flag & SEQ_LEFTSEL) {
+ SeqToTransData(t, td++, td2d++, tdsq++, seq, flag, SEQ_LEFTSEL);
+ tot++;
+ }
+ if (flag & SEQ_RIGHTSEL) {
+ SeqToTransData(t, td++, td2d++, tdsq++, seq, flag, SEQ_RIGHTSEL);
+ tot++;
+ }
+ }
+ else {
+ SeqToTransData(t, td++, td2d++, tdsq++, seq, flag, SELECT);
+ tot++;
+ }
+ }
+ }
+
+ return tot;
+}
+
+
+static void createTransSeqData(bContext *C, TransInfo *t)
+{
+
+ View2D *v2d= UI_view2d_fromcontext(C);
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(t->scene, FALSE);
+ TransData *td = NULL;
+ TransData2D *td2d= NULL;
+ TransDataSeq *tdsq= NULL;
+
+ int count=0;
+
+ if (ed==NULL) {
+ t->total= 0;
+ return;
+ }
+
+ /* which side of the current frame should be allowed */
+ if (t->mode == TFM_TIME_EXTEND) {
+ /* only side on which mouse is gets transformed */
+ float xmouse, ymouse;
+
+ UI_view2d_region_to_view(v2d, t->imval[0], t->imval[1], &xmouse, &ymouse);
+ t->frame_side = (xmouse > CFRA) ? 'R' : 'L';
+ }
+ else {
+ /* normal transform - both sides of current frame are considered */
+ t->frame_side = 'B';
+ }
+
+
+ count = SeqTransCount(t, ed->seqbasep, 0);
+
+ /* allocate memory for data */
+ t->total= count;
+
+ /* stop if trying to build list if nothing selected */
+ if (count == 0) {
+ return;
+ }
+
+ td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransSeq TransData");
+ td2d = t->data2d = MEM_callocN(t->total*sizeof(TransData2D), "TransSeq TransData2D");
+ tdsq = t->customData= MEM_callocN(t->total*sizeof(TransDataSeq), "TransSeq TransDataSeq");
+
+
+
+ /* loop 2: build transdata array */
+ SeqToTransData_Recursive(t, ed->seqbasep, td, td2d, tdsq);
+}
+
+
+/* transcribe given object into TransData for Transforming */
+static void ObjectToTransData(bContext *C, TransInfo *t, TransData *td, Object *ob)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *track;
+ ListBase fakecons = {NULL, NULL};
+ float obmtx[3][3];
+ short constinv;
+ short skip_invert = 0;
+
+ /* axismtx has the real orientation */
+ Mat3CpyMat4(td->axismtx, ob->obmat);
+ Mat3Ortho(td->axismtx);
+
+ td->con= ob->constraints.first;
+
+ /* hack: tempolarily disable tracking and/or constraints when getting
+ * object matrix, if tracking is on, or if constraints don't need
+ * inverse correction to stop it from screwing up space conversion
+ * matrix later
+ */
+ constinv = constraints_list_needinv(t, &ob->constraints);
+
+ /* disable constraints inversion for dummy pass */
+ if (t->mode == TFM_DUMMY)
+ skip_invert = 1;
+
+ if (skip_invert == 0 && (ob->track || constinv==0)) {
+ track= ob->track;
+ ob->track= NULL;
+
+ if (constinv == 0) {
+ fakecons.first = ob->constraints.first;
+ fakecons.last = ob->constraints.last;
+ ob->constraints.first = ob->constraints.last = NULL;
+ }
+
+ where_is_object(t->scene, ob);
+
+ if (constinv == 0) {
+ ob->constraints.first = fakecons.first;
+ ob->constraints.last = fakecons.last;
+ }
+
+ ob->track= track;
+ }
+ else
+ where_is_object(t->scene, ob);
+
+ td->ob = ob;
+
+ td->loc = ob->loc;
+ VECCOPY(td->iloc, td->loc);
+
+ td->ext->rot = ob->rot;
+ VECCOPY(td->ext->irot, ob->rot);
+ VECCOPY(td->ext->drot, ob->drot);
+
+ td->ext->size = ob->size;
+ VECCOPY(td->ext->isize, ob->size);
+ VECCOPY(td->ext->dsize, ob->dsize);
+
+ VECCOPY(td->center, ob->obmat[3]);
+
+ Mat4CpyMat4(td->ext->obmat, ob->obmat);
+
+ /* is there a need to set the global<->data space conversion matrices? */
+ if (ob->parent || constinv) {
+ float totmat[3][3], obinv[3][3];
+
+ /* Get the effect of parenting, and/or certain constraints.
+ * NOTE: some Constraints, and also Tracking should never get this
+ * done, as it doesn't work well.
+ */
+ object_to_mat3(ob, obmtx);
+ Mat3CpyMat4(totmat, ob->obmat);
+ Mat3Inv(obinv, totmat);
+ Mat3MulMat3(td->smtx, obmtx, obinv);
+ Mat3Inv(td->mtx, td->smtx);
+ }
+ else {
+ /* no conversion to/from dataspace */
+ Mat3One(td->smtx);
+ Mat3One(td->mtx);
+ }
+
+ /* set active flag */
+ if (ob == OBACT)
+ {
+ td->flag |= TD_ACTIVE;
+ }
+}
+
+
+/* sets flags in Bases to define whether they take part in transform */
+/* it deselects Bases, so we have to call the clear function always after */
+static void set_trans_object_base_flags(bContext *C, TransInfo *t)
+{
+ Scene *sce = CTX_data_scene(C);
+ View3D *v3d = t->view;
+
+ /*
+ if Base selected and has parent selected:
+ base->flag= BA_WAS_SEL
+ */
+ Base *base;
+
+ /* don't do it if we're not actually going to recalculate anything */
+ if(t->mode == TFM_DUMMY)
+ return;
+
+ /* makes sure base flags and object flags are identical */
+ copy_baseflags(t->scene);
+
+ /* handle pending update events, otherwise they got copied below */
+ for (base= sce->base.first; base; base= base->next) {
+ if(base->object->recalc)
+ object_handle_update(t->scene, base->object);
+ }
+
+ for (base= sce->base.first; base; base= base->next) {
+ base->flag &= ~BA_WAS_SEL;
+
+ if(TESTBASELIB(v3d, base)) {
+ Object *ob= base->object;
+ Object *parsel= ob->parent;
+
+ /* if parent selected, deselect */
+ while(parsel) {
+ if(parsel->flag & SELECT) break;
+ parsel= parsel->parent;
+ }
+
+ if(parsel)
+ {
+ if ((t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL) && t->around == V3D_LOCAL)
+ {
+ base->flag |= BA_TRANSFORM_CHILD;
+ }
+ else
+ {
+ base->flag &= ~SELECT;
+ base->flag |= BA_WAS_SEL;
+ }
+ }
+ /* used for flush, depgraph will change recalcs if needed :) */
+ ob->recalc |= OB_RECALC_OB;
+ }
+ }
+
+ /* all recalc flags get flushed to all layers, so a layer flip later on works fine */
+ DAG_scene_flush_update(t->scene, -1, 0);
+
+ /* and we store them temporal in base (only used for transform code) */
+ /* this because after doing updates, the object->recalc is cleared */
+ for (base= sce->base.first; base; base= base->next) {
+ if(base->object->recalc & OB_RECALC_OB)
+ base->flag |= BA_HAS_RECALC_OB;
+ if(base->object->recalc & OB_RECALC_DATA)
+ base->flag |= BA_HAS_RECALC_DATA;
+ }
+}
+
+static void clear_trans_object_base_flags(TransInfo *t)
+{
+ Scene *sce = t->scene;
+ Base *base;
+
+ for (base= sce->base.first; base; base = base->next)
+ {
+ if(base->flag & BA_WAS_SEL)
+ base->flag |= SELECT;
+
+ base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_DO_IPO|BA_TRANSFORM_CHILD);
+ }
+}
+
+/* auto-keyframing feature - checks for whether anything should be done for the current frame */
+// TODO: this should probably be done per channel instead...
+short autokeyframe_cfra_can_key(Scene *scene, Object *ob)
+{
+ float cfra= (float)CFRA; // XXX for now, this will do
+
+ /* only filter if auto-key mode requires this */
+ if (IS_AUTOKEY_ON(scene) == 0)
+ return 0;
+ else if (IS_AUTOKEY_MODE(scene, NORMAL))
+ return 1;
+ else
+ return id_frame_has_keyframe(&ob->id, cfra, ANIMFILTER_KEYS_LOCAL);
+}
+
+/* auto-keyframing feature - for objects
+ * tmode: should be a transform mode
+ */
+void autokeyframe_ob_cb_func(Scene *scene, View3D *v3d, Object *ob, int tmode)
+{
+ ID *id= &ob->id;
+ FCurve *fcu;
+
+ if (autokeyframe_cfra_can_key(scene, ob)) {
+ AnimData *adt= ob->adt;
+ float cfra= (float)CFRA; // xxx this will do for now
+ short flag = 0;
+
+ if (IS_AUTOKEY_FLAG(INSERTNEEDED))
+ flag |= INSERTKEY_NEEDED;
+ if (IS_AUTOKEY_FLAG(AUTOMATKEY))
+ flag |= INSERTKEY_MATRIX;
+
+ if (IS_AUTOKEY_FLAG(INSERTAVAIL)) {
+ /* only key on available channels */
+ if (adt && adt->action) {
+ for (fcu= adt->action->curves.first; fcu; fcu= fcu->next) {
+ fcu->flag &= ~FCURVE_SELECTED;
+ insert_keyframe(id, adt->action, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
+ }
+ }
+ }
+ else if (IS_AUTOKEY_FLAG(INSERTNEEDED)) {
+ short doLoc=0, doRot=0, doScale=0;
+
+ /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */
+ if (tmode == TFM_TRANSLATION) {
+ doLoc = 1;
+ }
+ else if (tmode == TFM_ROTATION) {
+ if (v3d->around == V3D_ACTIVE) {
+ if (ob != OBACT)
+ doLoc = 1;
+ }
+ else if (v3d->around == V3D_CURSOR)
+ doLoc = 1;
+
+ if ((v3d->flag & V3D_ALIGN)==0)
+ doRot = 1;
+ }
+ else if (tmode == TFM_RESIZE) {
+ if (v3d->around == V3D_ACTIVE) {
+ if (ob != OBACT)
+ doLoc = 1;
+ }
+ else if (v3d->around == V3D_CURSOR)
+ doLoc = 1;
+
+ if ((v3d->flag & V3D_ALIGN)==0)
+ doScale = 1;
+ }
+
+ // TODO: the group names here are temporary...
+ // TODO: should this be made to use the builtin KeyingSets instead?
+ if (doLoc) {
+ insert_keyframe(id, NULL, "Object Transform", "location", 0, cfra, flag);
+ insert_keyframe(id, NULL, "Object Transform", "location", 1, cfra, flag);
+ insert_keyframe(id, NULL, "Object Transform", "location", 2, cfra, flag);
+ }
+ if (doRot) {
+ insert_keyframe(id, NULL, "Object Transform", "rotation", 0, cfra, flag);
+ insert_keyframe(id, NULL, "Object Transform", "rotation", 1, cfra, flag);
+ insert_keyframe(id, NULL, "Object Transform", "rotation", 2, cfra, flag);
+ }
+ if (doScale) {
+ insert_keyframe(id, NULL, "Object Transform", "scale", 0, cfra, flag);
+ insert_keyframe(id, NULL, "Object Transform", "scale", 1, cfra, flag);
+ insert_keyframe(id, NULL, "Object Transform", "scale", 2, cfra, flag);
+ }
+ }
+ else {
+ // TODO: the group names here are temporary...
+ // TODO: should this be made to use the builtin KeyingSets instead?
+ insert_keyframe(id, NULL, "Object Transform", "location", 0, cfra, flag);
+ insert_keyframe(id, NULL, "Object Transform", "location", 1, cfra, flag);
+ insert_keyframe(id, NULL, "Object Transform", "location", 2, cfra, flag);
+
+ insert_keyframe(id, NULL, "Object Transform", "rotation", 0, cfra, flag);
+ insert_keyframe(id, NULL, "Object Transform", "rotation", 1, cfra, flag);
+ insert_keyframe(id, NULL, "Object Transform", "rotation", 2, cfra, flag);
+
+ insert_keyframe(id, NULL, "Object Transform", "scale", 0, cfra, flag);
+ insert_keyframe(id, NULL, "Object Transform", "scale", 1, cfra, flag);
+ insert_keyframe(id, NULL, "Object Transform", "scale", 2, cfra, flag);
+ }
+
+ // XXX todo... find a way to send notifiers from here...
+ }
+}
+
+/* auto-keyframing feature - for poses/pose-channels
+ * tmode: should be a transform mode
+ * targetless_ik: has targetless ik been done on any channels?
+ */
+void autokeyframe_pose_cb_func(Scene *scene, View3D *v3d, Object *ob, int tmode, short targetless_ik)
+{
+ ID *id= &ob->id;
+ AnimData *adt= ob->adt;
+ //bArmature *arm= ob->data;
+ bAction *act= (adt) ? adt->action : NULL;
+ bPose *pose= ob->pose;
+ bPoseChannel *pchan;
+ FCurve *fcu;
+
+ if (autokeyframe_cfra_can_key(scene, ob)) {
+ float cfra= (float)CFRA;
+ short flag= 0;
+ char buf[512];
+
+ /* flag is initialised from UserPref keyframing settings
+ * - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get
+ * visual keyframes even if flag not set, as it's not that useful otherwise
+ * (for quick animation recording)
+ */
+ if (IS_AUTOKEY_FLAG(AUTOMATKEY) || (targetless_ik))
+ flag |= INSERTKEY_MATRIX;
+ if (IS_AUTOKEY_FLAG(INSERTNEEDED))
+ flag |= INSERTKEY_NEEDED;
+
+ for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) {
+ if (pchan->bone->flag & BONE_TRANSFORM) {
+ /* clear any 'unkeyed' flag it may have */
+ pchan->bone->flag &= ~BONE_UNKEYED;
+
+ /* only insert into available channels? */
+ if (IS_AUTOKEY_FLAG(INSERTAVAIL)) {
+ if (act) {
+ for (fcu= act->curves.first; fcu; fcu= fcu->next)
+ insert_keyframe(id, act, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
+ }
+ }
+ /* only insert keyframe if needed? */
+ else if (IS_AUTOKEY_FLAG(INSERTNEEDED)) {
+ short doLoc=0, doRot=0, doScale=0;
+
+ /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */
+ if (tmode == TFM_TRANSLATION) {
+ if (targetless_ik)
+ doRot= 1;
+ else
+ doLoc = 1;
+ }
+ else if (tmode == TFM_ROTATION) {
+ if (ELEM(v3d->around, V3D_CURSOR, V3D_ACTIVE))
+ doLoc = 1;
+
+ if ((v3d->flag & V3D_ALIGN)==0)
+ doRot = 1;
+ }
+ else if (tmode == TFM_RESIZE) {
+ if (ELEM(v3d->around, V3D_CURSOR, V3D_ACTIVE))
+ doLoc = 1;
+
+ if ((v3d->flag & V3D_ALIGN)==0)
+ doScale = 1;
+ }
+
+ if (doLoc) {
+ sprintf(buf, "pose.pose_channels[\"%s\"].location", pchan->name);
+ insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag);
+ }
+ if (doRot) {
+ if (pchan->rotmode == PCHAN_ROT_QUAT) {
+ sprintf(buf, "pose.pose_channels[\"%s\"].rotation", pchan->name);
+ insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 3, cfra, flag);
+ }
+ else {
+ sprintf(buf, "pose.pose_channels[\"%s\"].euler_rotation", pchan->name);
+ insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag);
+ }
+ }
+ if (doScale) {
+ sprintf(buf, "pose.pose_channels[\"%s\"].scale", pchan->name);
+ insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag);
+ }
+ }
+ /* insert keyframe in any channel that's appropriate */
+ else {
+ sprintf(buf, "pose.pose_channels[\"%s\"].location", pchan->name);
+ insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag);
+
+ if (pchan->rotmode == PCHAN_ROT_QUAT) {
+ sprintf(buf, "pose.pose_channels[\"%s\"].rotation", pchan->name);
+ insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 3, cfra, flag);
+ }
+ else {
+ sprintf(buf, "pose.pose_channels[\"%s\"].euler_rotation", pchan->name);
+ insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag);
+ }
+
+ sprintf(buf, "pose.pose_channels[\"%s\"].scale", pchan->name);
+ insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag);
+ insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag);
+ }
+ }
+ }
+
+ // XXX todo... figure out way to get appropriate notifiers sent
+
+ /* do the bone paths */
+#if 0 // TRANSFORM_FIX_ME
+ if (arm->pathflag & ARM_PATH_ACFRA) {
+ pose_clear_paths(ob);
+ pose_recalculate_paths(ob);
+ }
+#endif
+ }
+ else {
+ /* tag channels that should have unkeyed data */
+ for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) {
+ if (pchan->bone->flag & BONE_TRANSFORM) {
+ /* tag this channel */
+ pchan->bone->flag |= BONE_UNKEYED;
+ }
+ }
+ }
+}
+
+
+/* inserting keys, refresh ipo-keys, pointcache, redraw events... (ton) */
+/* note: transdata has been freed already! */
+/* note: this runs even when createTransData exits early because (t->total==0), is this correct?... (campbell) */
+void special_aftertrans_update(TransInfo *t)
+{
+ Object *ob;
+// short redrawipo=0, resetslowpar=1;
+ int cancelled= (t->state == TRANS_CANCEL);
+ short duplicate= (t->undostr && strstr(t->undostr, "Duplicate")) ? 1 : 0;
+
+ if (t->spacetype==SPACE_VIEW3D) {
+ if (t->obedit) {
+ if (cancelled==0) {
+#if 0 // TRANSFORM_FIX_ME
+ EM_automerge(1);
+ /* when snapping, delay retopo until after automerge */
+ if (G.qual & LR_CTRLKEY) {
+ retopo_do_all();
+ }
+#endif
+ }
+ }
+ }
+
+ if (t->spacetype == SPACE_SEQ) {
+ Editing *ed= seq_give_editing(t->scene, FALSE);
+ if (ed && !cancelled) {
+ ListBase *seqbasep= ed->seqbasep;
+ Sequence *seq;
+#if 0 // TRANSFORM_FIX_ME, Would prefer to use this since the array takes into
+ // account what where transforming (with extend, locked strips etc)
+ // But at the moment t->data is freed in postTrans so for now re-shuffeling selected strips works ok. - Campbell
+
+ int a;
+ TransData *td= t->data;
+
+ /* prevent updating the same seq twice
+ * if the transdata order is changed this will mess up
+ * but so will TransDataSeq */
+ Sequence *seq_prev= NULL;
+
+ /* flush to 2d vector from internally used 3d vector */
+ for(a=0; a<t->total; a++, td++) {
+ seq= ((TransDataSeq *)td->extra)->seq;
+ if ((seq != seq_prev) && (seq->depth==0) && (seq->flag & SEQ_OVERLAP)) {
+ shuffle_seq(seqbasep, seq);
+ }
+
+ seq_prev= seq;
+ }
+#else // while t->data is not available...
+ int machine, max_machine = 0;
+
+ /* update in order so we always move bottom strips first */
+ for(seq= seqbasep->first; seq; seq= seq->next) {
+ max_machine = MAX2(max_machine, seq->machine);
+ }
+
+ for (machine = 0; machine <= max_machine; machine++)
+ {
+ for(seq= seqbasep->first; seq; seq= seq->next) {
+ if (seq->machine == machine && seq->depth == 0 && (seq->flag & (SELECT|SEQ_LEFTSEL|SEQ_RIGHTSEL)) != 0 && (seq->flag & SEQ_OVERLAP)) {
+ shuffle_seq(seqbasep, seq);
+ }
+ }
+ }
+#endif
+
+ for(seq= seqbasep->first; seq; seq= seq->next) {
+ /* We might want to build a list of effects that need to be updated during transform */
+ if(seq->type & SEQ_EFFECT) {
+ if (seq->seq1 && seq->seq1->flag & SELECT) calc_sequence(seq);
+ else if (seq->seq2 && seq->seq2->flag & SELECT) calc_sequence(seq);
+ else if (seq->seq3 && seq->seq3->flag & SELECT) calc_sequence(seq);
+ }
+ }
+
+ sort_seq(t->scene);
+ }
+
+ if (t->customData)
+ MEM_freeN(t->customData);
+ if (t->data)
+ MEM_freeN(t->data); // XXX postTrans usually does this
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
+ Scene *scene;
+ bAnimContext ac;
+
+ /* initialise relevant anim-context 'context' data from TransInfo data */
+ /* NOTE: sync this with the code in ANIM_animdata_get_context() */
+ memset(&ac, 0, sizeof(bAnimContext));
+
+ scene= ac.scene= t->scene;
+ ob= ac.obact= OBACT;
+ ac.sa= t->sa;
+ ac.ar= t->ar;
+ ac.spacetype= (t->sa)? t->sa->spacetype : 0;
+ ac.regiontype= (t->ar)? t->ar->regiontype : 0;
+
+ if (ANIM_animdata_context_getdata(&ac) == 0)
+ return;
+
+ if (ac.datatype == ANIMCONT_DOPESHEET) {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ short filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+
+ /* get channels to work on */
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* these should all be ipo-blocks */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(&ac, ale);
+ FCurve *fcu= (FCurve *)ale->key_data;
+
+ if ( (saction->flag & SACTION_NOTRANSKEYCULL)==0 &&
+ ((cancelled == 0) || (duplicate)) )
+ {
+ if (nob) {
+ ANIM_nla_mapping_apply_fcurve(nob, fcu, 0, 1);
+ posttrans_fcurve_clean(fcu);
+ ANIM_nla_mapping_apply_fcurve(nob, fcu, 1, 1);
+ }
+ else
+ posttrans_fcurve_clean(fcu);
+ }
+ }
+
+ /* free temp memory */
+ BLI_freelistN(&anim_data);
+ }
+ else if (ac.datatype == ANIMCONT_ACTION) {
+ /* Depending on the lock status, draw necessary views */
+ // fixme... some of this stuff is not good
+ if (ob) {
+ ob->ctime= -1234567.0f;
+
+ if (ob->pose || ob_get_key(ob))
+ DAG_object_flush_update(scene, ob, OB_RECALC);
+ else
+ DAG_object_flush_update(scene, ob, OB_RECALC_OB);
+ }
+
+ /* Do curve cleanups? */
+ if ( (saction->flag & SACTION_NOTRANSKEYCULL)==0 &&
+ ((cancelled == 0) || (duplicate)) )
+ {
+ posttrans_action_clean(&ac, (bAction *)ac.data);
+ }
+ }
+ else if (ac.datatype == ANIMCONT_SHAPEKEY) {
+#if 0 // XXX old animation system
+ /* fix up the Ipocurves and redraw stuff */
+ Key *key= (Key *)ac.data;
+
+ if (key->ipo) {
+ if ( (saction->flag & SACTION_NOTRANSKEYCULL)==0 &&
+ ((cancelled == 0) || (duplicate)) )
+ {
+ posttrans_ipo_clean(key->ipo);
+ }
+ }
+#endif // XXX old animation system
+
+ DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA);
+ }
+#if 0 // XXX future of this is still not clear
+ else if (ac.datatype == ANIMCONT_GPENCIL) {
+ /* remove duplicate frames and also make sure points are in order! */
+ if ((cancelled == 0) || (duplicate))
+ {
+ bScreen *sc= (bScreen *)ac.data;
+ ScrArea *sa;
+
+ /* BAD... we need to loop over all screen areas for current screen...
+ * - sync this with actdata_filter_gpencil() in editaction.c
+ */
+ for (sa= sc->areabase.first; sa; sa= sa->next) {
+ bGPdata *gpd= gpencil_data_getactive(sa);
+
+ if (gpd)
+ posttrans_gpd_clean(gpd);
+ }
+ }
+ }
+#endif // XXX future of this is still not clear
+
+ /* make sure all F-Curves are set correctly */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* clear flag that was set for time-slide drawing */
+ saction->flag &= ~SACTION_MOVING;
+ }
+ else if (t->spacetype == SPACE_IPO) {
+ SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first;
+ Scene *scene;
+ bAnimContext ac;
+
+ /* initialise relevant anim-context 'context' data from TransInfo data */
+ /* NOTE: sync this with the code in ANIM_animdata_get_context() */
+ memset(&ac, 0, sizeof(bAnimContext));
+
+ scene= ac.scene= t->scene;
+ ob= ac.obact= OBACT;
+ ac.sa= t->sa;
+ ac.ar= t->ar;
+ ac.spacetype= (t->sa)? t->sa->spacetype : 0;
+ ac.regiontype= (t->ar)? t->ar->regiontype : 0;
+
+ if (ANIM_animdata_context_getdata(&ac) == 0)
+ return;
+
+ if (ac.datatype)
+ {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ short filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_CURVEVISIBLE);
+
+ /* get channels to work on */
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* these should all be ipo-blocks */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(&ac, ale);
+ FCurve *fcu= (FCurve *)ale->key_data;
+
+ if ( (sipo->flag & SIPO_NOTRANSKEYCULL)==0 &&
+ ((cancelled == 0) || (duplicate)) )
+ {
+ if (nob) {
+ ANIM_nla_mapping_apply_fcurve(nob, fcu, 0, 1);
+ posttrans_fcurve_clean(fcu);
+ ANIM_nla_mapping_apply_fcurve(nob, fcu, 1, 1);
+ }
+ else
+ posttrans_fcurve_clean(fcu);
+ }
+ }
+
+ /* free temp memory */
+ BLI_freelistN(&anim_data);
+ }
+
+ /* make sure all F-Curves are set correctly */
+ ANIM_editkeyframes_refresh(&ac);
+ }
+ else if (t->obedit) {
+ // TRANSFORM_FIX_ME
+// if (t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
+// allqueue(REDRAWBUTSEDIT, 0);
+
+ if (t->obedit->type == OB_MESH)
+ {
+ EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
+ /* table needs to be created for each edit command, since vertices can move etc */
+ mesh_octree_table(t->obedit, em, NULL, 'e');
+ }
+ }
+ else if ((t->flag & T_POSE) && (t->poseobj)) {
+ bArmature *arm;
+ bPose *pose;
+ bPoseChannel *pchan;
+ short targetless_ik= 0;
+
+ ob= t->poseobj;
+ arm= ob->data;
+ pose= ob->pose;
+
+ /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */
+ if (!cancelled && t->mode==TFM_TRANSLATION)
+ targetless_ik= apply_targetless_ik(ob);
+ else {
+ /* not forget to clear the auto flag */
+ for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+ bKinematicConstraint *data= has_targetless_ik(pchan);
+ if(data) data->flag &= ~CONSTRAINT_IK_AUTO;
+ }
+ }
+
+ if (t->mode==TFM_TRANSLATION)
+ pose_grab_with_ik_clear(ob);
+
+ /* automatic inserting of keys and unkeyed tagging - only if transform wasn't cancelled (or TFM_DUMMY) */
+ if (!cancelled && (t->mode != TFM_DUMMY)) {
+ autokeyframe_pose_cb_func(t->scene, (View3D *)t->view, ob, t->mode, targetless_ik);
+ DAG_object_flush_update(t->scene, ob, OB_RECALC_DATA);
+ }
+ else if (arm->flag & ARM_DELAYDEFORM) {
+ /* old optimize trick... this enforces to bypass the depgraph */
+ DAG_object_flush_update(t->scene, ob, OB_RECALC_DATA);
+ ob->recalc= 0; // is set on OK position already by recalcData()
+ }
+ else
+ DAG_object_flush_update(t->scene, ob, OB_RECALC_DATA);
+
+ //if (t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
+ // allqueue(REDRAWBUTSEDIT, 0);
+
+ }
+ else if(G.f & G_PARTICLEEDIT) {
+ ;
+ }
+ else {
+ /* Objects */
+ // XXX ideally, this would go through context iterators, but we don't have context iterator access here,
+ // so we make do with old data + access styles...
+ Scene *scene= t->scene;
+ Base *base;
+
+ for (base= FIRSTBASE; base; base= base->next) {
+ ob= base->object;
+
+ if (base->flag & SELECT && (t->mode != TFM_DUMMY)) {
+ /* pointcache refresh */
+ if (BKE_ptcache_object_reset(ob, PTCACHE_RESET_DEPSGRAPH))
+ ob->recalc |= OB_RECALC_DATA;
+
+ /* Set autokey if necessary */
+ if (!cancelled)
+ autokeyframe_ob_cb_func(t->scene, (View3D *)t->view, ob, t->mode);
+ }
+ }
+ }
+
+#if 0 // TRANSFORM_FIX_ME
+ else if (t->spacetype == SPACE_NLA) {
+ recalc_all_ipos(); // bad
+ synchronize_action_strips();
+
+ /* cleanup */
+ for (base=t->scene->base.first; base; base=base->next)
+ base->flag &= ~(BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA);
+
+ /* after transform, remove duplicate keyframes on a frame that resulted from transform */
+ if ( (G.snla->flag & SNLA_NOTRANSKEYCULL)==0 &&
+ ((cancelled == 0) || (duplicate)) )
+ {
+ posttrans_nla_clean(t);
+ }
+ }
+#endif
+
+ clear_trans_object_base_flags(t);
+
+#if 0 // TRANSFORM_FIX_ME
+ if (redrawipo) {
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWIPO, 0);
+ }
+
+ if(resetslowpar)
+ reset_slowparents();
+
+ /* note; should actually only be done for all objects when a lamp is moved... (ton) */
+ if(t->spacetype==SPACE_VIEW3D && G.vd->drawtype == OB_SHADED)
+ reshadeall_displist();
+#endif
+}
+
+static void createTransObject(bContext *C, TransInfo *t)
+{
+ TransData *td = NULL;
+ TransDataExtension *tx;
+// IpoKey *ik;
+// ListBase elems;
+
+ set_trans_object_base_flags(C, t);
+
+ /* count */
+ CTX_DATA_BEGIN(C, Object*, ob, selected_objects)
+ {
+#if 0 // TRANSFORM_FIX_ME
+ /* store ipo keys? */
+ if ((ob->id.lib == 0) && (ob->ipo) && (ob->ipo->showkey) && (ob->ipoflag & OB_DRAWKEY)) {
+ elems.first= elems.last= NULL;
+ make_ipokey_transform(ob, &elems, 1); /* '1' only selected keys */
+
+ pushdata(&elems, sizeof(ListBase));
+
+ for(ik= elems.first; ik; ik= ik->next)
+ t->total++;
+
+ if(elems.first==NULL)
+ t->total++;
+ }
+#endif
+// else {
+ t->total++;
+// }
+ }
+ CTX_DATA_END;
+
+ if(!t->total) {
+ /* clear here, main transform function escapes too */
+ clear_trans_object_base_flags(t);
+ return;
+ }
+
+ td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransOb");
+ tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransObExtension");
+
+ CTX_DATA_BEGIN(C, Base*, base, selected_bases)
+ {
+ Object *ob= base->object;
+
+ td->flag = TD_SELECTED;
+ td->protectflag= ob->protectflag;
+ td->ext = tx;
+
+ if (base->flag & BA_TRANSFORM_CHILD)
+ {
+ td->flag |= TD_NOCENTER;
+ td->flag |= TD_NO_LOC;
+ }
+
+ /* select linked objects, but skip them later */
+ if (ob->id.lib != 0) {
+ td->flag |= TD_SKIP;
+ }
+
+ /* store ipo keys? */
+ // TRANSFORM_FIX_ME
+#if 0
+ if((ob->id.lib == 0) && (ob->ipo) && (ob->ipo->showkey) && (ob->ipoflag & OB_DRAWKEY)) {
+
+ popfirst(&elems); // bring back pushed listbase
+
+ if(elems.first) {
+ int cfraont;
+ int ipoflag;
+
+ base->flag |= BA_DO_IPO+BA_WAS_SEL;
+ base->flag &= ~SELECT;
+
+ cfraont= CFRA;
+ set_no_parent_ipo(1);
+ ipoflag= ob->ipoflag;
+ ob->ipoflag &= ~OB_OFFS_OB;
+
+ /*
+ * This is really EVIL code that pushes down Object values
+ * (loc, dloc, orig, size, dsize, rot, drot)
+ * */
+
+ pushdata((void*)ob->loc, 7 * 3 * sizeof(float)); // tsk! tsk!
+
+ for(ik= elems.first; ik; ik= ik->next) {
+
+ /* weak... this doesn't correct for floating values, giving small errors */
+ CFRA= (int)(ik->val/t->scene->r.framelen);
+
+ do_ob_ipo(ob);
+ ObjectToTransData(C, t, td, ob); // does where_is_object()
+
+ td->flag= TD_SELECTED;
+
+ td->tdi= MEM_callocN(sizeof(TransDataIpokey), "TransDataIpokey");
+ /* also does tdi->flag and oldvals, needs to be after ob_to_transob()! */
+ ipokey_to_transdata(ik, td);
+
+ td++;
+ tx++;
+ if(ik->next) td->ext= tx; // prevent corrupting mem!
+ }
+ free_ipokey(&elems);
+
+ poplast(ob->loc);
+ set_no_parent_ipo(0);
+
+ CFRA= cfraont;
+ ob->ipoflag= ipoflag;
+
+ where_is_object(t->scene, ob); // restore
+ }
+ else {
+ ObjectToTransData(C, t, td, ob);
+ td->tdi = NULL;
+ td->val = NULL;
+ td++;
+ tx++;
+ }
+ }
+#endif
+// else {
+ ObjectToTransData(C, t, td, ob);
+ td->tdi = NULL;
+ td->val = NULL;
+ td++;
+ tx++;
+// }
+ }
+ CTX_DATA_END;
+}
+
+/* transcribe given node into TransData2D for Transforming */
+static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node)
+// static void NodeToTransData(bContext *C, TransInfo *t, TransData2D *td, bNode *node)
+{
+ td2d->loc[0] = node->locx; /* hold original location */
+ td2d->loc[1] = node->locy;
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = &node->locx; /* current location */
+
+ td->flag = 0;
+ td->loc = td2d->loc;
+ VECCOPY(td->center, td->loc);
+ VECCOPY(td->iloc, td->loc);
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext= NULL; td->tdi= NULL; td->val= NULL;
+
+ td->flag |= TD_SELECTED;
+ td->dist= 0.0;
+
+ Mat3One(td->mtx);
+ Mat3One(td->smtx);
+}
+
+void createTransNodeData(bContext *C, TransInfo *t)
+{
+ TransData *td;
+ TransData2D *td2d;
+
+ t->total= CTX_DATA_COUNT(C, selected_nodes);
+
+ td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransNode TransData");
+ td2d = t->data2d = MEM_callocN(t->total*sizeof(TransData2D), "TransNode TransData2D");
+
+ CTX_DATA_BEGIN(C, bNode *, selnode, selected_nodes)
+ NodeToTransData(td++, td2d++, selnode);
+ CTX_DATA_END
+}
+
+void createTransData(bContext *C, TransInfo *t)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = OBACT;
+
+ if (t->options == CTX_TEXTURE) {
+ t->flag |= T_TEXTURE;
+ createTransTexspace(C, t);
+ }
+ else if (t->options == CTX_EDGE) {
+ t->ext = NULL;
+ t->flag |= T_EDIT;
+ createTransEdge(C, t);
+ if(t->data && t->flag & T_PROP_EDIT) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (t->options == CTX_BMESH) {
+ // TRANSFORM_FIX_ME
+ //createTransBMeshVerts(t, G.editBMesh->bm, G.editBMesh->td);
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ t->flag |= T_POINTS|T_2D_EDIT;
+ createTransUVs(C, t);
+ if(t->data && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ t->flag |= T_POINTS|T_2D_EDIT;
+ createTransActionData(C, t);
+ }
+ else if (t->spacetype == SPACE_NLA) {
+ t->flag |= T_POINTS|T_2D_EDIT;
+ // TRANSFORM_FIX_ME
+ //createTransNlaData(C, t);
+ }
+ else if (t->spacetype == SPACE_SEQ) {
+ t->flag |= T_POINTS|T_2D_EDIT;
+ t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point transformations */
+ createTransSeqData(C, t);
+ }
+ else if (t->spacetype == SPACE_IPO) {
+ t->flag |= T_POINTS|T_2D_EDIT;
+ createTransGraphEditData(C, t);
+#if 0
+ if (t->data && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+#endif
+ }
+ else if(t->spacetype == SPACE_NODE) {
+ t->flag |= T_2D_EDIT|T_POINTS;
+ createTransNodeData(C, t);
+ if (t->data && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (t->obedit) {
+ t->ext = NULL;
+ if (t->obedit->type == OB_MESH) {
+ createTransEditVerts(C, t);
+ }
+ else if ELEM(t->obedit->type, OB_CURVE, OB_SURF) {
+ createTransCurveVerts(C, t);
+ }
+ else if (t->obedit->type==OB_LATTICE) {
+ createTransLatticeVerts(C, t);
+ }
+ else if (t->obedit->type==OB_MBALL) {
+ createTransMBallVerts(C, t);
+ }
+ else if (t->obedit->type==OB_ARMATURE) {
+ t->flag &= ~T_PROP_EDIT;
+ createTransArmatureVerts(C, t);
+ }
+ else {
+ printf("edit type not implemented!\n");
+ }
+
+ if(t->data && t->flag & T_PROP_EDIT) {
+ if (ELEM(t->obedit->type, OB_CURVE, OB_MESH)) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 0);
+ sort_trans_data_dist(t);
+ }
+ else {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
+
+ t->flag |= T_EDIT|T_POINTS;
+
+ /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
+ if(t->mode==TFM_BONESIZE) {
+ t->flag &= ~(T_EDIT|T_POINTS);
+ t->flag |= T_POSE;
+ t->poseobj = ob; /* <- tsk tsk, this is going to give issues one day */
+ }
+ }
+ else if (ob && (ob->flag & OB_POSEMODE)) {
+ // XXX this is currently limited to active armature only...
+ // XXX active-layer checking isn't done as that should probably be checked through context instead
+ createTransPose(C, t, ob);
+ }
+ else if (G.f & G_WEIGHTPAINT) {
+ /* exception, we look for the one selected armature */
+ CTX_DATA_BEGIN(C, Object*, ob_armature, selected_objects)
+ {
+ if(ob_armature->type==OB_ARMATURE)
+ {
+ if(ob_armature->flag & OB_POSEMODE)
+ {
+ createTransPose(C, t, ob_armature);
+ break;
+ }
+ }
+ }
+ CTX_DATA_END;
+ }
+ else if (G.f & G_PARTICLEEDIT && PE_can_edit(PE_get_current(scene, ob))) {
+ createTransParticleVerts(C, t);
+
+ if(t->data && t->flag & T_PROP_EDIT) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+
+ t->flag |= T_POINTS;
+ }
+ else {
+ t->flag &= ~T_PROP_EDIT; /* no proportional edit in object mode */
+ createTransObject(C, t);
+ t->flag |= T_OBJECT;
+
+ if (t->ar->regiontype == RGN_TYPE_WINDOW)
+ {
+ View3D *v3d = t->view;
+ RegionView3D *rv3d = t->ar->regiondata;
+ if((t->flag & T_OBJECT) && v3d->camera == OBACT && rv3d->persp==V3D_CAMOB)
+ {
+ t->flag |= T_CAMERA;
+ }
+ }
+ }
+
+// TRANSFORM_FIX_ME
+// /* temporal...? */
+// t->scene->recalc |= SCE_PRV_CHANGED; /* test for 3d preview */
+}
+
+
+
+
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
new file mode 100644
index 00000000000..27f1a59c14b
--- /dev/null
+++ b/source/blender/editors/transform/transform_generics.c
@@ -0,0 +1,1299 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_nla_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_particle_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_access.h"
+
+//#include "BIF_screen.h"
+//#include "BIF_mywindow.h"
+#include "BIF_gl.h"
+//#include "BIF_editaction.h"
+//#include "BIF_editmesh.h"
+//#include "BIF_editnla.h"
+//#include "BIF_editsima.h"
+//#include "BIF_editparticle.h"
+//#include "BIF_meshtools.h"
+#include "BIF_retopo.h"
+
+#include "BKE_action.h"
+#include "BKE_anim.h"
+#include "BKE_armature.h"
+#include "BKE_cloth.h"
+#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_displist.h"
+#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
+#include "BKE_global.h"
+#include "BKE_group.h"
+#include "BKE_lattice.h"
+#include "BKE_key.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+#include "BKE_context.h"
+
+#include "ED_anim_api.h"
+#include "ED_armature.h"
+#include "ED_image.h"
+#include "ED_keyframing.h"
+#include "ED_mesh.h"
+#include "ED_space_api.h"
+#include "ED_uvedit.h"
+#include "ED_view3d.h"
+
+//#include "BDR_unwrapper.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+
+#include "WM_types.h"
+
+#include "UI_resources.h"
+
+//#include "blendef.h"
+//
+//#include "mydevice.h"
+
+#include "transform.h"
+
+extern ListBase editelems;
+
+extern TransInfo Trans; /* From transform.c */
+
+/* ************************** Functions *************************** */
+
+void getViewVector(TransInfo *t, float coord[3], float vec[3])
+{
+ if (t->persp != V3D_ORTHO)
+ {
+ float p1[4], p2[4];
+
+ VECCOPY(p1, coord);
+ p1[3] = 1.0f;
+ VECCOPY(p2, p1);
+ p2[3] = 1.0f;
+ Mat4MulVec4fl(t->viewmat, p2);
+
+ p2[0] = 2.0f * p2[0];
+ p2[1] = 2.0f * p2[1];
+ p2[2] = 2.0f * p2[2];
+
+ Mat4MulVec4fl(t->viewinv, p2);
+
+ VecSubf(vec, p1, p2);
+ }
+ else {
+ VECCOPY(vec, t->viewinv[2]);
+ }
+ Normalize(vec);
+}
+
+/* ************************** GENERICS **************************** */
+
+static void clipMirrorModifier(TransInfo *t, Object *ob)
+{
+ ModifierData *md= ob->modifiers.first;
+ float tolerance[3] = {0.0f, 0.0f, 0.0f};
+ int axis = 0;
+
+ for (; md; md=md->next) {
+ if (md->type==eModifierType_Mirror) {
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ if(mmd->flag & MOD_MIR_CLIPPING) {
+ axis = 0;
+ if(mmd->flag & MOD_MIR_AXIS_X) {
+ axis |= 1;
+ tolerance[0] = mmd->tolerance;
+ }
+ if(mmd->flag & MOD_MIR_AXIS_Y) {
+ axis |= 2;
+ tolerance[1] = mmd->tolerance;
+ }
+ if(mmd->flag & MOD_MIR_AXIS_Z) {
+ axis |= 4;
+ tolerance[2] = mmd->tolerance;
+ }
+ if (axis) {
+ float mtx[4][4], imtx[4][4];
+ int i;
+ TransData *td = t->data;
+
+ if (mmd->mirror_ob) {
+ float obinv[4][4];
+
+ Mat4Invert(obinv, mmd->mirror_ob->obmat);
+ Mat4MulMat4(mtx, ob->obmat, obinv);
+ Mat4Invert(imtx, mtx);
+ }
+
+ for(i = 0 ; i < t->total; i++, td++) {
+ int clip;
+ float loc[3], iloc[3];
+
+ if (td->flag & TD_NOACTION)
+ break;
+ if (td->loc==NULL)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ VecCopyf(loc, td->loc);
+ VecCopyf(iloc, td->iloc);
+
+ if (mmd->mirror_ob) {
+ VecMat4MulVecfl(loc, mtx, loc);
+ VecMat4MulVecfl(iloc, mtx, iloc);
+ }
+
+ clip = 0;
+ if(axis & 1) {
+ if(fabs(iloc[0])<=tolerance[0] ||
+ loc[0]*iloc[0]<0.0f) {
+ loc[0]= 0.0f;
+ clip = 1;
+ }
+ }
+
+ if(axis & 2) {
+ if(fabs(iloc[1])<=tolerance[1] ||
+ loc[1]*iloc[1]<0.0f) {
+ loc[1]= 0.0f;
+ clip = 1;
+ }
+ }
+ if(axis & 4) {
+ if(fabs(iloc[2])<=tolerance[2] ||
+ loc[2]*iloc[2]<0.0f) {
+ loc[2]= 0.0f;
+ clip = 1;
+ }
+ }
+ if (clip) {
+ if (mmd->mirror_ob) {
+ VecMat4MulVecfl(loc, imtx, loc);
+ }
+ VecCopyf(td->loc, loc);
+ }
+ }
+ }
+
+ }
+ }
+ }
+}
+
+/* assumes obedit set to mesh object */
+static void editmesh_apply_to_mirror(TransInfo *t)
+{
+ TransData *td = t->data;
+ EditVert *eve;
+ int i;
+
+ for(i = 0 ; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+ if (td->loc==NULL)
+ break;
+ if (td->flag & TD_SKIP)
+ continue;
+
+ eve = td->extra;
+ if(eve) {
+ eve->co[0]= -td->loc[0];
+ eve->co[1]= td->loc[1];
+ eve->co[2]= td->loc[2];
+ }
+ }
+}
+
+/* called for updating while transform acts, once per redraw */
+void recalcData(TransInfo *t)
+{
+ Scene *scene = t->scene;
+ Base *base;
+
+#if 0 // TRANSFORM_FIX_ME
+ if (t->spacetype == SPACE_ACTION) {
+ Object *ob= OBACT;
+ void *data;
+ short context;
+
+ /* determine what type of data we are operating on */
+ data = get_action_context(&context);
+ if (data == NULL) return;
+
+ /* always flush data if gpencil context */
+ if (context == ACTCONT_GPENCIL) {
+ flushTransGPactionData(t);
+ }
+
+ if (G.saction->lock) {
+ if (context == ACTCONT_ACTION) {
+ if(ob) {
+ ob->ctime= -1234567.0f;
+ if(ob->pose || ob_get_key(ob))
+ DAG_object_flush_update(G.scene, ob, OB_RECALC);
+ else
+ DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
+ }
+ }
+ else if (context == ACTCONT_SHAPEKEY) {
+ DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB|OB_RECALC_DATA);
+ }
+ }
+ }
+ else if (t->spacetype == SPACE_NLA) {
+ if (G.snla->lock) {
+ for (base=G.scene->base.first; base; base=base->next) {
+ if (base->flag & BA_HAS_RECALC_OB)
+ base->object->recalc |= OB_RECALC_OB;
+ if (base->flag & BA_HAS_RECALC_DATA)
+ base->object->recalc |= OB_RECALC_DATA;
+
+ if (base->object->recalc)
+ base->object->ctime= -1234567.0f; // eveil!
+
+ /* recalculate scale of selected nla-strips */
+ if (base->object->nlastrips.first) {
+ Object *bob= base->object;
+ bActionStrip *strip;
+
+ for (strip= bob->nlastrips.first; strip; strip= strip->next) {
+ if (strip->flag & ACTSTRIP_SELECT) {
+ float actlen= strip->actend - strip->actstart;
+ float len= strip->end - strip->start;
+
+ strip->scale= len / (actlen * strip->repeat);
+ }
+ }
+ }
+ }
+
+ DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0);
+ }
+ else {
+ for (base=G.scene->base.first; base; base=base->next) {
+ /* recalculate scale of selected nla-strips */
+ if (base->object && base->object->nlastrips.first) {
+ Object *bob= base->object;
+ bActionStrip *strip;
+
+ for (strip= bob->nlastrips.first; strip; strip= strip->next) {
+ if (strip->flag & ACTSTRIP_SELECT) {
+ float actlen= strip->actend - strip->actstart;
+ float len= strip->end - strip->start;
+
+ /* prevent 'negative' scaling */
+ if (len < 0) {
+ SWAP(float, strip->start, strip->end);
+ len= fabs(len);
+ }
+
+ /* calculate new scale */
+ strip->scale= len / (actlen * strip->repeat);
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+ if (t->obedit) {
+ }
+ else if(G.f & G_PARTICLEEDIT) {
+ flushTransParticles(t);
+ }
+ if (t->spacetype==SPACE_NODE) {
+ flushTransNodes(t);
+ }
+ else if (t->spacetype==SPACE_SEQ) {
+ flushTransSeq(t);
+ }
+ else if (t->spacetype == SPACE_IPO) {
+ SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first;
+ Scene *scene;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimContext ac;
+ int filter;
+
+ bAnimListElem *ale;
+ int dosort = 0;
+
+
+ /* initialise relevant anim-context 'context' data from TransInfo data */
+ /* NOTE: sync this with the code in ANIM_animdata_get_context() */
+ memset(&ac, 0, sizeof(bAnimContext));
+
+ scene= ac.scene= t->scene;
+ ac.obact= OBACT;
+ ac.sa= t->sa;
+ ac.ar= t->ar;
+ ac.spacetype= (t->sa)? t->sa->spacetype : 0;
+ ac.regiontype= (t->ar)? t->ar->regiontype : 0;
+
+ ANIM_animdata_context_getdata(&ac);
+
+ /* do the flush first */
+ flushTransGraphData(t);
+
+ /* get curves to check if a re-sort is needed */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_CURVEVISIBLE);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* now test if there is a need to re-sort */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ FCurve *fcu= (FCurve *)ale->key_data;
+
+ /* watch it: if the time is wrong: do not correct handles yet */
+ if (test_time_fcurve(fcu))
+ dosort++;
+ else
+ calchandles_fcurve(fcu);
+ }
+
+ /* do resort and other updates? */
+ if (dosort) remake_graph_transdata(t, &anim_data);
+ //if (sipo->showkey) update_ipokey_val();
+
+ /* now free temp channels */
+ BLI_freelistN(&anim_data);
+
+ /* update realtime - not working? */
+ if (sipo->lock) {
+
+ }
+ }
+ else if (t->obedit) {
+ if ELEM(t->obedit->type, OB_CURVE, OB_SURF) {
+ Curve *cu= t->obedit->data;
+ Nurb *nu= cu->editnurb->first;
+
+ DAG_object_flush_update(scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */
+
+ if (t->state == TRANS_CANCEL) {
+ while(nu) {
+ calchandlesNurb(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
+ nu= nu->next;
+ }
+ } else {
+ /* Normal updating */
+ while(nu) {
+ test2DNurb(nu);
+ calchandlesNurb(nu);
+ nu= nu->next;
+ }
+ /* TRANSFORM_FIX_ME */
+ // retopo_do_all();
+ }
+ }
+ else if(t->obedit->type==OB_LATTICE) {
+ Lattice *la= t->obedit->data;
+ DAG_object_flush_update(scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */
+
+ if(la->editlatt->flag & LT_OUTSIDE) outside_lattice(la->editlatt);
+ }
+ else if (t->obedit->type == OB_MESH) {
+ if(t->spacetype==SPACE_IMAGE) {
+ SpaceImage *sima= t->sa->spacedata.first;
+
+ flushTransUVs(t);
+ if(sima->flag & SI_LIVE_UNWRAP)
+ ED_uvedit_live_unwrap_re_solve();
+
+ DAG_object_flush_update(scene, t->obedit, OB_RECALC_DATA);
+ } else {
+ EditMesh *em = ((Mesh*)t->obedit->data)->edit_mesh;
+ /* mirror modifier clipping? */
+ if(t->state != TRANS_CANCEL) {
+ /* TRANSFORM_FIX_ME */
+// if ((G.qual & LR_CTRLKEY)==0) {
+// /* Only retopo if not snapping, Note, this is the only case of G.qual being used, but we have no T_SHIFT_MOD - Campbell */
+// retopo_do_all();
+// }
+ clipMirrorModifier(t, t->obedit);
+ }
+ if((t->options & CTX_NO_MIRROR) == 0 && (t->flag & T_MIRROR))
+ editmesh_apply_to_mirror(t);
+
+ DAG_object_flush_update(scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */
+
+ recalc_editnormals(em);
+ }
+ }
+ else if(t->obedit->type==OB_ARMATURE) { /* no recalc flag, does pose */
+ bArmature *arm= t->obedit->data;
+ ListBase *edbo = arm->edbo;
+ EditBone *ebo;
+ TransData *td = t->data;
+ int i;
+
+ /* Ensure all bones are correctly adjusted */
+ for (ebo = edbo->first; ebo; ebo = ebo->next){
+
+ if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
+ /* If this bone has a parent tip that has been moved */
+ if (ebo->parent->flag & BONE_TIPSEL){
+ VECCOPY (ebo->head, ebo->parent->tail);
+ if(t->mode==TFM_BONE_ENVELOPE) ebo->rad_head= ebo->parent->rad_tail;
+ }
+ /* If this bone has a parent tip that has NOT been moved */
+ else{
+ VECCOPY (ebo->parent->tail, ebo->head);
+ if(t->mode==TFM_BONE_ENVELOPE) ebo->parent->rad_tail= ebo->rad_head;
+ }
+ }
+
+ /* on extrude bones, oldlength==0.0f, so we scale radius of points */
+ ebo->length= VecLenf(ebo->head, ebo->tail);
+ if(ebo->oldlength==0.0f) {
+ ebo->rad_head= 0.25f*ebo->length;
+ ebo->rad_tail= 0.10f*ebo->length;
+ ebo->dist= 0.25f*ebo->length;
+ if(ebo->parent) {
+ if(ebo->rad_head > ebo->parent->rad_tail)
+ ebo->rad_head= ebo->parent->rad_tail;
+ }
+ }
+ else if(t->mode!=TFM_BONE_ENVELOPE) {
+ /* if bones change length, lets do that for the deform distance as well */
+ ebo->dist*= ebo->length/ebo->oldlength;
+ ebo->rad_head*= ebo->length/ebo->oldlength;
+ ebo->rad_tail*= ebo->length/ebo->oldlength;
+ ebo->oldlength= ebo->length;
+ }
+ }
+
+
+ if (t->mode != TFM_BONE_ROLL)
+ {
+ /* fix roll */
+ for(i = 0; i < t->total; i++, td++)
+ {
+ if (td->extra)
+ {
+ float vec[3], up_axis[3];
+ float qrot[4];
+
+ ebo = td->extra;
+ VECCOPY(up_axis, td->axismtx[2]);
+
+ if (t->mode != TFM_ROTATION)
+ {
+ VecSubf(vec, ebo->tail, ebo->head);
+ Normalize(vec);
+ RotationBetweenVectorsToQuat(qrot, td->axismtx[1], vec);
+ QuatMulVecf(qrot, up_axis);
+ }
+ else
+ {
+ Mat3MulVecfl(t->mat, up_axis);
+ }
+
+ ebo->roll = ED_rollBoneToVector(ebo, up_axis);
+ }
+ }
+ }
+
+ if(arm->flag & ARM_MIRROR_EDIT)
+ transform_armature_mirror_update(t->obedit);
+
+ }
+ else
+ DAG_object_flush_update(scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */
+ }
+ else if( (t->flag & T_POSE) && t->poseobj) {
+ Object *ob= t->poseobj;
+ bArmature *arm= ob->data;
+
+ /* if animtimer is running, and the object already has animation data,
+ * check if the auto-record feature means that we should record 'samples'
+ * (i.e. uneditable animation values)
+ */
+ // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
+ // TODO: maybe the ob->adt check isn't really needed? makes it too difficult to use...
+ if (/*(ob->adt) && */(t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
+ short targetless_ik= (t->flag & T_AUTOIK); // XXX this currently doesn't work, since flags aren't set yet!
+ autokeyframe_pose_cb_func(t->scene, (View3D *)t->view, ob, t->mode, targetless_ik);
+ }
+
+ /* old optimize trick... this enforces to bypass the depgraph */
+ if (!(arm->flag & ARM_DELAYDEFORM)) {
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA); /* sets recalc flags */
+ }
+ else
+ where_is_pose(scene, ob);
+ }
+ else {
+ for(base= FIRSTBASE; base; base= base->next) {
+ Object *ob= base->object;
+
+ /* this flag is from depgraph, was stored in initialize phase, handled in drawview.c */
+ if(base->flag & BA_HAS_RECALC_OB)
+ ob->recalc |= OB_RECALC_OB;
+ if(base->flag & BA_HAS_RECALC_DATA)
+ ob->recalc |= OB_RECALC_DATA;
+
+ /* if object/base is selected */
+ if ((base->flag & SELECT) || (ob->flag & SELECT)) {
+ /* if animtimer is running, and the object already has animation data,
+ * check if the auto-record feature means that we should record 'samples'
+ * (i.e. uneditable animation values)
+ */
+ // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
+ // TODO: maybe the ob->adt check isn't really needed? makes it too difficult to use...
+ if (/*(ob->adt) && */(t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
+ autokeyframe_ob_cb_func(t->scene, (View3D *)t->view, ob, t->mode);
+ }
+ }
+
+ /* proxy exception */
+ if(ob->proxy)
+ ob->proxy->recalc |= ob->recalc;
+ if(ob->proxy_group)
+ group_tag_recalc(ob->proxy_group->dup_group);
+ }
+ }
+
+ /* update shaded drawmode while transform */
+ if(t->spacetype==SPACE_VIEW3D && ((View3D*)t->view)->drawtype == OB_SHADED)
+ reshadeall_displist(t->scene);
+}
+
+void drawLine(TransInfo *t, float *center, float *dir, char axis, short options)
+{
+ extern void make_axis_color(char *col, char *col2, char axis); // view3d_draw.c
+ float v1[3], v2[3], v3[3];
+ char col[3], col2[3];
+
+ if (t->spacetype == SPACE_VIEW3D)
+ {
+ View3D *v3d = t->view;
+
+ glPushMatrix();
+
+ //if(t->obedit) glLoadMatrixf(t->obedit->obmat); // sets opengl viewing
+
+
+ VecCopyf(v3, dir);
+ VecMulf(v3, v3d->far);
+
+ VecSubf(v2, center, v3);
+ VecAddf(v1, center, v3);
+
+ if (options & DRAWLIGHT) {
+ col[0] = col[1] = col[2] = 220;
+ }
+ else {
+ UI_GetThemeColor3ubv(TH_GRID, col);
+ }
+ make_axis_color(col, col2, axis);
+ glColor3ubv((GLubyte *)col2);
+
+ setlinestyle(0);
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(v1);
+ glVertex3fv(v2);
+ glEnd();
+
+ glPopMatrix();
+ }
+}
+
+void resetTransRestrictions(TransInfo *t)
+{
+ t->flag &= ~T_ALL_RESTRICTIONS;
+}
+
+int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
+{
+ Scene *sce = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
+ ScrArea *sa = CTX_wm_area(C);
+ Object *obedit = CTX_data_edit_object(C);
+
+ /* moving: is shown in drawobject() (transform color) */
+// TRANSFORM_FIX_ME
+// if(obedit || (t->flag & T_POSE) ) G.moving= G_TRANSFORM_EDIT;
+// else if(G.f & G_PARTICLEEDIT) G.moving= G_TRANSFORM_PARTICLE;
+// else G.moving= G_TRANSFORM_OBJ;
+
+ t->scene = sce;
+ t->sa = sa;
+ t->ar = ar;
+ t->obedit = obedit;
+
+ t->data = NULL;
+ t->ext = NULL;
+
+ t->flag = 0;
+
+ t->redraw = 1; /* redraw first time */
+
+ if (event)
+ {
+ t->imval[0] = event->x - t->ar->winrct.xmin;
+ t->imval[1] = event->y - t->ar->winrct.ymin;
+
+ t->event_type = event->type;
+ }
+ else
+ {
+ t->imval[0] = 0;
+ t->imval[1] = 0;
+ }
+
+ t->con.imval[0] = t->imval[0];
+ t->con.imval[1] = t->imval[1];
+
+ t->mval[0] = t->imval[0];
+ t->mval[1] = t->imval[1];
+
+ t->transform = NULL;
+ t->handleEvent = NULL;
+
+ t->total = 0;
+
+ t->val = 0.0f;
+
+ t->vec[0] =
+ t->vec[1] =
+ t->vec[2] = 0.0f;
+
+ t->center[0] =
+ t->center[1] =
+ t->center[2] = 0.0f;
+
+ Mat3One(t->mat);
+
+ t->spacetype = sa->spacetype;
+ if(t->spacetype == SPACE_VIEW3D)
+ {
+ View3D *v3d = sa->spacedata.first;
+
+ t->view = v3d;
+ t->animtimer= CTX_wm_screen(C)->animtimer;
+
+ if(v3d->flag & V3D_ALIGN) t->flag |= T_V3D_ALIGN;
+ t->around = v3d->around;
+
+ if (op && RNA_struct_find_property(op->ptr, "constraint_axis") && RNA_property_is_set(op->ptr, "constraint_orientation"))
+ {
+ t->current_orientation = RNA_int_get(op->ptr, "constraint_orientation");
+
+ if (t->current_orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C) - 1)
+ {
+ t->current_orientation = V3D_MANIP_GLOBAL;
+ }
+ }
+ else
+ {
+ t->current_orientation = v3d->twmode;
+ }
+ }
+ else if(t->spacetype==SPACE_IMAGE || t->spacetype==SPACE_NODE)
+ {
+ // XXX for now, get View2D from the active region
+ t->view = &ar->v2d;
+ t->around = ar->v2d.around;
+ }
+ else
+ {
+ // XXX for now, get View2D from the active region
+ t->view = &ar->v2d;
+
+ t->around = V3D_CENTER;
+ }
+
+ if (op && RNA_struct_find_property(op->ptr, "mirror") && RNA_property_is_set(op->ptr, "mirror"))
+ {
+ if (RNA_boolean_get(op->ptr, "mirror"))
+ {
+ t->flag |= T_MIRROR;
+ }
+ }
+ // Need stuff to take it from edit mesh or whatnot here
+ else
+ {
+ if (t->obedit && t->obedit->type == OB_MESH && sce->toolsettings->editbutflag & B_MESH_X_MIRROR)
+ {
+ t->flag |= T_MIRROR;
+ }
+ }
+
+ /* setting PET flag */
+ if (op && RNA_struct_find_property(op->ptr, "proportional") && RNA_property_is_set(op->ptr, "proportional"))
+ {
+ switch(RNA_enum_get(op->ptr, "proportional"))
+ {
+ case 2: /* XXX connected constant */
+ t->flag |= T_PROP_CONNECTED;
+ case 1: /* XXX prop on constant */
+ t->flag |= T_PROP_EDIT;
+ break;
+ }
+ }
+ else
+ {
+ if ((t->options & CTX_NO_PET) == 0 && (sce->proportional)) {
+ t->flag |= T_PROP_EDIT;
+
+ if(sce->proportional == 2)
+ t->flag |= T_PROP_CONNECTED; // yes i know, has to become define
+ }
+ }
+
+ if (op && RNA_struct_find_property(op->ptr, "proportional_size") && RNA_property_is_set(op->ptr, "proportional_size"))
+ {
+ t->prop_size = RNA_float_get(op->ptr, "proportional_size");
+ }
+ else
+ {
+ t->prop_size = sce->toolsettings->proportional_size;
+ }
+
+ if (op && RNA_struct_find_property(op->ptr, "proportional_editing_falloff") && RNA_property_is_set(op->ptr, "proportional_editing_falloff"))
+ {
+ t->prop_mode = RNA_enum_get(op->ptr, "proportional_editing_falloff");
+ }
+ else
+ {
+ t->prop_mode = sce->prop_mode;
+ }
+
+ /* TRANSFORM_FIX_ME rna restrictions */
+ if (t->prop_size <= 0)
+ {
+ t->prop_size = 1.0f;
+ }
+
+ setTransformViewMatrices(t);
+ initNumInput(&t->num);
+ initNDofInput(&t->ndof);
+
+ return 1;
+}
+
+/* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
+void postTrans (TransInfo *t)
+{
+ TransData *td;
+
+ if (t->draw_handle)
+ {
+ ED_region_draw_cb_exit(t->ar->type, t->draw_handle);
+ }
+
+ /* postTrans can be called when nothing is selected, so data is NULL already */
+ if (t->data) {
+ int a;
+
+ /* since ipokeys are optional on objects, we mallocced them per trans-data */
+ for(a=0, td= t->data; a<t->total; a++, td++) {
+ if(td->tdi) MEM_freeN(td->tdi);
+ if (td->flag & TD_BEZTRIPLE) MEM_freeN(td->hdata);
+ }
+ MEM_freeN(t->data);
+ }
+
+ if (t->ext) MEM_freeN(t->ext);
+ if (t->data2d) {
+ MEM_freeN(t->data2d);
+ t->data2d= NULL;
+ }
+
+ if(t->spacetype==SPACE_IMAGE) {
+ SpaceImage *sima= t->sa->spacedata.first;
+ if(sima->flag & SI_LIVE_UNWRAP)
+ ED_uvedit_live_unwrap_end(t->state == TRANS_CANCEL);
+ }
+ else if(t->spacetype==SPACE_ACTION) {
+ if (t->customData)
+ MEM_freeN(t->customData);
+ }
+}
+
+void applyTransObjects(TransInfo *t)
+{
+ TransData *td;
+
+ for (td = t->data; td < t->data + t->total; td++) {
+ VECCOPY(td->iloc, td->loc);
+ if (td->ext->rot) {
+ VECCOPY(td->ext->irot, td->ext->rot);
+ }
+ if (td->ext->size) {
+ VECCOPY(td->ext->isize, td->ext->size);
+ }
+ }
+ recalcData(t);
+}
+
+/* helper for below */
+static void restore_ipokey(float *poin, float *old)
+{
+ if(poin) {
+ poin[0]= old[0];
+ poin[-3]= old[3];
+ poin[3]= old[6];
+ }
+}
+
+static void restoreElement(TransData *td) {
+ /* TransData for crease has no loc */
+ if (td->loc) {
+ VECCOPY(td->loc, td->iloc);
+ }
+ if (td->val) {
+ *td->val = td->ival;
+ }
+ if (td->ext && (td->flag&TD_NO_EXT)==0) {
+ if (td->ext->rot) {
+ VECCOPY(td->ext->rot, td->ext->irot);
+ }
+ if (td->ext->size) {
+ VECCOPY(td->ext->size, td->ext->isize);
+ }
+ if(td->flag & TD_USEQUAT) {
+ if (td->ext->quat) {
+ QUATCOPY(td->ext->quat, td->ext->iquat);
+ }
+ }
+ }
+
+ if (td->flag & TD_BEZTRIPLE) {
+ *(td->hdata->h1) = td->hdata->ih1;
+ *(td->hdata->h2) = td->hdata->ih2;
+ }
+
+ if(td->tdi) {
+ TransDataIpokey *tdi= td->tdi;
+
+ restore_ipokey(tdi->locx, tdi->oldloc);
+ restore_ipokey(tdi->locy, tdi->oldloc+1);
+ restore_ipokey(tdi->locz, tdi->oldloc+2);
+
+ restore_ipokey(tdi->rotx, tdi->oldrot);
+ restore_ipokey(tdi->roty, tdi->oldrot+1);
+ restore_ipokey(tdi->rotz, tdi->oldrot+2);
+
+ restore_ipokey(tdi->sizex, tdi->oldsize);
+ restore_ipokey(tdi->sizey, tdi->oldsize+1);
+ restore_ipokey(tdi->sizez, tdi->oldsize+2);
+ }
+}
+
+void restoreTransObjects(TransInfo *t)
+{
+ TransData *td;
+
+ for (td = t->data; td < t->data + t->total; td++) {
+ restoreElement(td);
+ }
+
+ Mat3One(t->mat);
+
+ recalcData(t);
+}
+
+void calculateCenter2D(TransInfo *t)
+{
+ if (t->flag & (T_EDIT|T_POSE)) {
+ Object *ob= t->obedit?t->obedit:t->poseobj;
+ float vec[3];
+
+ VECCOPY(vec, t->center);
+ Mat4MulVecfl(ob->obmat, vec);
+ projectIntView(t, vec, t->center2d);
+ }
+ else {
+ projectIntView(t, t->center, t->center2d);
+ }
+}
+
+void calculateCenterCursor(TransInfo *t)
+{
+ float *cursor;
+
+ cursor = give_cursor(t->scene, t->view);
+ VECCOPY(t->center, cursor);
+
+ /* If edit or pose mode, move cursor in local space */
+ if (t->flag & (T_EDIT|T_POSE)) {
+ Object *ob = t->obedit?t->obedit:t->poseobj;
+ float mat[3][3], imat[3][3];
+
+ VecSubf(t->center, t->center, ob->obmat[3]);
+ Mat3CpyMat4(mat, ob->obmat);
+ Mat3Inv(imat, mat);
+ Mat3MulVecfl(imat, t->center);
+ }
+
+ calculateCenter2D(t);
+}
+
+void calculateCenterCursor2D(TransInfo *t)
+{
+ View2D *v2d= t->view;
+ float aspx=1.0, aspy=1.0;
+
+ if(t->spacetype==SPACE_IMAGE) /* only space supported right now but may change */
+ ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
+
+ if (v2d) {
+ t->center[0] = v2d->cursor[0] * aspx;
+ t->center[1] = v2d->cursor[1] * aspy;
+ }
+
+ calculateCenter2D(t);
+}
+
+void calculateCenterMedian(TransInfo *t)
+{
+ float partial[3] = {0.0f, 0.0f, 0.0f};
+ int total = 0;
+ int i;
+
+ for(i = 0; i < t->total; i++) {
+ if (t->data[i].flag & TD_SELECTED) {
+ if (!(t->data[i].flag & TD_NOCENTER))
+ {
+ VecAddf(partial, partial, t->data[i].center);
+ total++;
+ }
+ }
+ else {
+ /*
+ All the selected elements are at the head of the array
+ which means we can stop when it finds unselected data
+ */
+ break;
+ }
+ }
+ if(i)
+ VecMulf(partial, 1.0f / total);
+ VECCOPY(t->center, partial);
+
+ calculateCenter2D(t);
+}
+
+void calculateCenterBound(TransInfo *t)
+{
+ float max[3];
+ float min[3];
+ int i;
+ for(i = 0; i < t->total; i++) {
+ if (i) {
+ if (t->data[i].flag & TD_SELECTED) {
+ if (!(t->data[i].flag & TD_NOCENTER))
+ MinMax3(min, max, t->data[i].center);
+ }
+ else {
+ /*
+ All the selected elements are at the head of the array
+ which means we can stop when it finds unselected data
+ */
+ break;
+ }
+ }
+ else {
+ VECCOPY(max, t->data[i].center);
+ VECCOPY(min, t->data[i].center);
+ }
+ }
+ VecAddf(t->center, min, max);
+ VecMulf(t->center, 0.5);
+
+ calculateCenter2D(t);
+}
+
+void calculateCenter(TransInfo *t)
+{
+ switch(t->around) {
+ case V3D_CENTER:
+ calculateCenterBound(t);
+ break;
+ case V3D_CENTROID:
+ calculateCenterMedian(t);
+ break;
+ case V3D_CURSOR:
+ if(t->spacetype==SPACE_IMAGE)
+ calculateCenterCursor2D(t);
+ else
+ calculateCenterCursor(t);
+ break;
+ case V3D_LOCAL:
+ /* Individual element center uses median center for helpline and such */
+ calculateCenterMedian(t);
+ break;
+ case V3D_ACTIVE:
+ {
+ /* set median, and if if if... do object center */
+#if 0 // TRANSFORM_FIX_ME
+ EditSelection ese;
+ /* EDIT MODE ACTIVE EDITMODE ELEMENT */
+
+ if (t->obedit && t->obedit->type == OB_MESH && EM_get_actSelection(&ese)) {
+ EM_editselection_center(t->center, &ese);
+ calculateCenter2D(t);
+ break;
+ } /* END EDIT MODE ACTIVE ELEMENT */
+#endif
+
+ calculateCenterMedian(t);
+ if((t->flag & (T_EDIT|T_POSE))==0)
+ {
+ Scene *scene = t->scene;
+ Object *ob= OBACT;
+ if(ob)
+ {
+ VECCOPY(t->center, ob->obmat[3]);
+ projectIntView(t, t->center, t->center2d);
+ }
+ }
+
+ }
+ }
+
+ /* setting constraint center */
+ VECCOPY(t->con.center, t->center);
+ if(t->flag & (T_EDIT|T_POSE))
+ {
+ Object *ob= t->obedit?t->obedit:t->poseobj;
+ Mat4MulVecfl(ob->obmat, t->con.center);
+ }
+
+ /* voor panning from cameraview */
+ if(t->flag & T_OBJECT)
+ {
+ if(t->spacetype==SPACE_VIEW3D)
+ {
+ View3D *v3d = t->view;
+ Scene *scene = t->scene;
+ RegionView3D *rv3d = t->ar->regiondata;
+
+ if(v3d->camera == OBACT && rv3d->persp==V3D_CAMOB)
+ {
+ float axis[3];
+ /* persinv is nasty, use viewinv instead, always right */
+ VECCOPY(axis, t->viewinv[2]);
+ Normalize(axis);
+
+ /* 6.0 = 6 grid units */
+ axis[0]= t->center[0]- 6.0f*axis[0];
+ axis[1]= t->center[1]- 6.0f*axis[1];
+ axis[2]= t->center[2]- 6.0f*axis[2];
+
+ projectIntView(t, axis, t->center2d);
+
+ /* rotate only needs correct 2d center, grab needs initgrabz() value */
+ if(t->mode==TFM_TRANSLATION)
+ {
+ VECCOPY(t->center, axis);
+ VECCOPY(t->con.center, t->center);
+ }
+ }
+ }
+ }
+
+ if(t->spacetype==SPACE_VIEW3D)
+ {
+ /* initgrabz() defines a factor for perspective depth correction, used in window_to_3d_delta() */
+ if(t->flag & (T_EDIT|T_POSE)) {
+ Object *ob= t->obedit?t->obedit:t->poseobj;
+ float vec[3];
+
+ VECCOPY(vec, t->center);
+ Mat4MulVecfl(ob->obmat, vec);
+ initgrabz(t->ar->regiondata, vec[0], vec[1], vec[2]);
+ }
+ else {
+ initgrabz(t->ar->regiondata, t->center[0], t->center[1], t->center[2]);
+ }
+ }
+}
+
+void calculatePropRatio(TransInfo *t)
+{
+ TransData *td = t->data;
+ int i;
+ float dist;
+ short connected = t->flag & T_PROP_CONNECTED;
+
+ if (t->flag & T_PROP_EDIT) {
+ for(i = 0 ; i < t->total; i++, td++) {
+ if (td->flag & TD_SELECTED) {
+ td->factor = 1.0f;
+ }
+ else if ((connected &&
+ (td->flag & TD_NOTCONNECTED || td->dist > t->prop_size))
+ ||
+ (connected == 0 &&
+ td->rdist > t->prop_size)) {
+ /*
+ The elements are sorted according to their dist member in the array,
+ that means we can stop when it finds one element outside of the propsize.
+ */
+ td->flag |= TD_NOACTION;
+ td->factor = 0.0f;
+ restoreElement(td);
+ }
+ else {
+ /* Use rdist for falloff calculations, it is the real distance */
+ td->flag &= ~TD_NOACTION;
+ dist= (t->prop_size-td->rdist)/t->prop_size;
+
+ /*
+ * Clamp to positive numbers.
+ * Certain corner cases with connectivity and individual centers
+ * can give values of rdist larger than propsize.
+ */
+ if (dist < 0.0f)
+ dist = 0.0f;
+
+ switch(t->prop_mode) {
+ case PROP_SHARP:
+ td->factor= dist*dist;
+ break;
+ case PROP_SMOOTH:
+ td->factor= 3.0f*dist*dist - 2.0f*dist*dist*dist;
+ break;
+ case PROP_ROOT:
+ td->factor = (float)sqrt(dist);
+ break;
+ case PROP_LIN:
+ td->factor = dist;
+ break;
+ case PROP_CONST:
+ td->factor = 1.0f;
+ break;
+ case PROP_SPHERE:
+ td->factor = (float)sqrt(2*dist - dist * dist);
+ break;
+ case PROP_RANDOM:
+ BLI_srand( BLI_rand() ); /* random seed */
+ td->factor = BLI_frand()*dist;
+ break;
+ default:
+ td->factor = 1;
+ }
+ }
+ }
+ switch(t->prop_mode) {
+ case PROP_SHARP:
+ strcpy(t->proptext, "(Sharp)");
+ break;
+ case PROP_SMOOTH:
+ strcpy(t->proptext, "(Smooth)");
+ break;
+ case PROP_ROOT:
+ strcpy(t->proptext, "(Root)");
+ break;
+ case PROP_LIN:
+ strcpy(t->proptext, "(Linear)");
+ break;
+ case PROP_CONST:
+ strcpy(t->proptext, "(Constant)");
+ break;
+ case PROP_SPHERE:
+ strcpy(t->proptext, "(Sphere)");
+ break;
+ case PROP_RANDOM:
+ strcpy(t->proptext, "(Random)");
+ break;
+ default:
+ strcpy(t->proptext, "");
+ }
+ }
+ else {
+ for(i = 0 ; i < t->total; i++, td++) {
+ td->factor = 1.0;
+ }
+ strcpy(t->proptext, "");
+ }
+}
+
+TransInfo *BIF_GetTransInfo()
+{
+ return NULL;
+}
+
+float get_drawsize(ARegion *ar, float *co)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ float size, vec[3], len1, len2;
+
+ /* size calculus, depending ortho/persp settings, like initgrabz() */
+ size= rv3d->persmat[0][3]*co[0]+ rv3d->persmat[1][3]*co[1]+ rv3d->persmat[2][3]*co[2]+ rv3d->persmat[3][3];
+
+ VECCOPY(vec, rv3d->persinv[0]);
+ len1= Normalize(vec);
+ VECCOPY(vec, rv3d->persinv[1]);
+ len2= Normalize(vec);
+
+ size*= 0.01f*(len1>len2?len1:len2);
+
+ /* correct for window size to make widgets appear fixed size */
+ if(ar->winx > ar->winy) size*= 1000.0f/(float)ar->winx;
+ else size*= 1000.0f/(float)ar->winy;
+
+ return size;
+}
diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c
new file mode 100644
index 00000000000..3272c35f5fa
--- /dev/null
+++ b/source/blender/editors/transform/transform_input.c
@@ -0,0 +1,329 @@
+/**
+ * $Id: transform_input.c 18142 2008-12-29 07:19:16Z aligorith $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "DNA_screen_types.h"
+
+#include "BLI_arithb.h"
+
+#include "WM_types.h"
+
+#include "transform.h"
+
+
+
+/* ************************** INPUT FROM MOUSE *************************** */
+
+void InputVector(TransInfo *t, MouseInput *mi, short mval[2], float output[3])
+{
+ float vec[3], dvec[3];
+ if(mi->precision)
+ {
+ /* calculate the main translation and the precise one separate */
+ convertViewVec(t, dvec, (short)(mval[0] - mi->precision_mval[0]), (short)(mval[1] - mi->precision_mval[1]));
+ VecMulf(dvec, 0.1f);
+ convertViewVec(t, vec, (short)(mi->precision_mval[0] - t->imval[0]), (short)(mi->precision_mval[1] - t->imval[1]));
+ VecAddf(output, vec, dvec);
+ }
+ else
+ {
+ convertViewVec(t, output, (short)(mval[0] - t->imval[0]), (short)(mval[1] - t->imval[1]));
+ }
+
+}
+
+void InputSpring(TransInfo *t, MouseInput *mi, short mval[2], float output[3])
+{
+ float ratio, precise_ratio, dx, dy;
+ if(mi->precision)
+ {
+ /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
+ dx = (float)(mi->center[0] - mi->precision_mval[0]);
+ dy = (float)(mi->center[1] - mi->precision_mval[1]);
+ ratio = (float)sqrt( dx*dx + dy*dy);
+
+ dx= (float)(mi->center[0] - mval[0]);
+ dy= (float)(mi->center[1] - mval[1]);
+ precise_ratio = (float)sqrt( dx*dx + dy*dy);
+
+ ratio = (ratio + (precise_ratio - ratio) / 10.0f) / mi->factor;
+ }
+ else
+ {
+ dx = (float)(mi->center[0] - mval[0]);
+ dy = (float)(mi->center[1] - mval[1]);
+ ratio = (float)sqrt( dx*dx + dy*dy) / mi->factor;
+ }
+
+ output[0] = ratio;
+}
+
+void InputSpringFlip(TransInfo *t, MouseInput *mi, short mval[2], float output[3])
+{
+ InputSpring(t, mi, mval, output);
+
+ /* flip scale */
+ if ((mi->center[0] - mval[0]) * (mi->center[0] - mi->imval[0]) +
+ (mi->center[1] - mval[1]) * (mi->center[1] - mi->imval[1]) < 0)
+ {
+ output[0] *= -1.0f;
+ }
+}
+
+void InputTrackBall(TransInfo *t, MouseInput *mi, short mval[2], float output[3])
+{
+
+ if(mi->precision)
+ {
+ output[0] = ( mi->imval[1] - mi->precision_mval[1] ) + ( mi->precision_mval[1] - mval[1] ) * 0.1f;
+ output[1] = ( mi->precision_mval[0] - mi->imval[0] ) + ( mval[0] - mi->precision_mval[0] ) * 0.1f;
+ }
+ else
+ {
+ output[0] = (float)( mi->imval[1] - mval[1] );
+ output[1] = (float)( mval[0] - mi->imval[0] );
+ }
+
+ output[0] *= mi->factor;
+ output[1] *= mi->factor;
+}
+
+void InputHorizontalRatio(TransInfo *t, MouseInput *mi, short mval[2], float output[3]) {
+ float x, pad;
+
+ pad = t->ar->winx / 10;
+
+ if (mi->precision)
+ {
+ /* deal with Shift key by adding motion / 10 to motion before shift press */
+ x = mi->precision_mval[0] + (float)(mval[0] - mi->precision_mval[0]) / 10.0f;
+ }
+ else {
+ x = mval[0];
+ }
+
+ output[0] = (x - pad) / (t->ar->winx - 2 * pad);
+}
+
+void InputHorizontalAbsolute(TransInfo *t, MouseInput *mi, short mval[2], float output[3]) {
+ float vec[3];
+
+ InputVector(t, mi, mval, vec);
+ Projf(vec, vec, t->viewinv[0]);
+
+ output[0] = Inpf(t->viewinv[0], vec) * 2.0f;
+}
+
+void InputVerticalRatio(TransInfo *t, MouseInput *mi, short mval[2], float output[3]) {
+ float y, pad;
+
+ pad = t->ar->winy / 10;
+
+ if (mi->precision) {
+ /* deal with Shift key by adding motion / 10 to motion before shift press */
+ y = mi->precision_mval[1] + (float)(mval[1] - mi->precision_mval[1]) / 10.0f;
+ }
+ else {
+ y = mval[0];
+ }
+
+ output[0] = (y - pad) / (t->ar->winy - 2 * pad);
+}
+
+void InputVerticalAbsolute(TransInfo *t, MouseInput *mi, short mval[2], float output[3]) {
+ float vec[3];
+
+ InputVector(t, mi, mval, vec);
+ Projf(vec, vec, t->viewinv[1]);
+
+ output[0] = Inpf(t->viewinv[1], vec) * 2.0f;
+}
+
+void InputAngle(TransInfo *t, MouseInput *mi, short mval[2], float output[3])
+{
+ double dx2 = mval[0] - mi->center[0];
+ double dy2 = mval[1] - mi->center[1];
+ double B = sqrt(dx2*dx2+dy2*dy2);
+
+ double dx1 = mi->imval[0] - mi->center[0];
+ double dy1 = mi->imval[1] - mi->center[1];
+ double A = sqrt(dx1*dx1+dy1*dy1);
+
+ double dx3 = mval[0] - mi->imval[0];
+ double dy3 = mval[1] - mi->imval[1];
+
+ /* use doubles here, to make sure a "1.0" (no rotation) doesnt become 9.999999e-01, which gives 0.02 for acos */
+ double deler = ((dx1*dx1+dy1*dy1)+(dx2*dx2+dy2*dy2)-(dx3*dx3+dy3*dy3))
+ / (2.0 * (A*B?A*B:1.0));
+ /* (A*B?A*B:1.0f) this takes care of potential divide by zero errors */
+
+ float dphi;
+
+ dphi = saacos((float)deler);
+ if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi;
+
+ /* If the angle is zero, because of lack of precision close to the 1.0 value in acos
+ * approximate the angle with the oposite side of the normalized triangle
+ * This is a good approximation here since the smallest acos value seems to be around
+ * 0.02 degree and lower values don't even have a 0.01% error compared to the approximation
+ * */
+ if (dphi == 0)
+ {
+ double dx, dy;
+
+ dx2 /= A;
+ dy2 /= A;
+
+ dx1 /= B;
+ dy1 /= B;
+
+ dx = dx1 - dx2;
+ dy = dy1 - dy2;
+
+ dphi = sqrt(dx*dx + dy*dy);
+ if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi;
+ }
+
+ if(mi->precision) dphi = dphi/30.0f;
+
+ /* if no delta angle, don't update initial position */
+ if (dphi != 0)
+ {
+ mi->imval[0] = mval[0];
+ mi->imval[1] = mval[1];
+ }
+
+ output[0] += dphi;
+}
+
+void initMouseInput(TransInfo *t, MouseInput *mi, int center[2], short mval[2])
+{
+ mi->factor = 0;
+ mi->precision = 0;
+
+ mi->center[0] = center[0];
+ mi->center[1] = center[1];
+
+ mi->imval[0] = mval[0];
+ mi->imval[1] = mval[1];
+}
+
+static void calcSpringFactor(MouseInput *mi)
+{
+ mi->factor = (float)sqrt(
+ (
+ ((float)(mi->center[1] - mi->imval[1]))*((float)(mi->center[1] - mi->imval[1]))
+ +
+ ((float)(mi->center[0] - mi->imval[0]))*((float)(mi->center[0] - mi->imval[0]))
+ ) );
+
+ if (mi->factor==0.0f)
+ mi->factor= 1.0f; /* prevent Inf */
+}
+
+void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
+{
+
+ switch(mode)
+ {
+ case INPUT_VECTOR:
+ mi->apply = InputVector;
+ break;
+ case INPUT_SPRING:
+ calcSpringFactor(mi);
+ mi->apply = InputSpring;
+ break;
+ case INPUT_SPRING_FLIP:
+ calcSpringFactor(mi);
+ mi->apply = InputSpringFlip;
+ break;
+ case INPUT_ANGLE:
+ mi->apply = InputAngle;
+ break;
+ case INPUT_TRACKBALL:
+ /* factor has to become setting or so */
+ mi->factor = 0.1f;
+ mi->apply = InputTrackBall;
+ break;
+ case INPUT_HORIZONTAL_RATIO:
+ mi->factor = (float)(mi->center[0] - mi->imval[0]);
+ mi->apply = InputHorizontalRatio;
+ break;
+ case INPUT_HORIZONTAL_ABSOLUTE:
+ mi->apply = InputHorizontalAbsolute;
+ break;
+ case INPUT_VERTICAL_RATIO:
+ mi->apply = InputVerticalRatio;
+ break;
+ case INPUT_VERTICAL_ABSOLUTE:
+ mi->apply = InputVerticalAbsolute;
+ break;
+ case INPUT_NONE:
+ default:
+ mi->apply = NULL;
+ break;
+ }
+
+ /* bootstrap mouse input with initial values */
+ applyMouseInput(t, mi, mi->imval, t->values);
+}
+
+void applyMouseInput(TransInfo *t, MouseInput *mi, short mval[2], float output[3])
+{
+ if (mi->apply != NULL)
+ {
+ mi->apply(t, mi, mval, output);
+ }
+}
+
+int handleMouseInput(TransInfo *t, MouseInput *mi, wmEvent *event)
+{
+ int redraw = 0;
+
+ switch (event->type)
+ {
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ if (event->val)
+ {
+ t->modifiers |= MOD_PRECISION;
+ /* shift is modifier for higher precision transform
+ * store the mouse position where the normal movement ended */
+ mi->precision_mval[0] = event->x - t->ar->winrct.xmin;
+ mi->precision_mval[1] = event->y - t->ar->winrct.ymin;
+ mi->precision = 1;
+ }
+ else
+ {
+ t->modifiers &= ~MOD_PRECISION;
+ mi->precision = 0;
+ }
+ redraw = 1;
+ break;
+ }
+
+ return redraw;
+}
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
new file mode 100644
index 00000000000..99d7805b938
--- /dev/null
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -0,0 +1,1685 @@
+/**
+* $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+// TRANSFORM_FIX_ME
+// Disable everything here, don't need it for now
+#if 0
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_action_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_armature.h"
+#include "BKE_global.h"
+#include "BKE_lattice.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+#include "BKE_utildefines.h"
+
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "BIF_editarmature.h"
+#include "BIF_gl.h"
+#include "BIF_mywindow.h"
+#include "BIF_resources.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_transform.h"
+#include "BIF_editmesh.h"
+#include "BIF_editparticle.h"
+
+#include "BSE_edit.h"
+#include "BSE_view.h"
+#include "BDR_drawobject.h"
+
+#include "blendef.h"
+#include "transform.h"
+
+/* return codes for select, and drawing flags */
+
+#define MAN_TRANS_X 1
+#define MAN_TRANS_Y 2
+#define MAN_TRANS_Z 4
+#define MAN_TRANS_C 7
+
+#define MAN_ROT_X 8
+#define MAN_ROT_Y 16
+#define MAN_ROT_Z 32
+#define MAN_ROT_V 64
+#define MAN_ROT_T 128
+#define MAN_ROT_C 248
+
+#define MAN_SCALE_X 256
+#define MAN_SCALE_Y 512
+#define MAN_SCALE_Z 1024
+#define MAN_SCALE_C 1792
+
+/* color codes */
+
+#define MAN_RGB 0
+#define MAN_GHOST 1
+#define MAN_MOVECOL 2
+
+/* GLOBAL VARIABLE THAT SHOULD MOVED TO SCREEN MEMBER OR SOMETHING */
+extern TransInfo Trans;
+
+
+static int is_mat4_flipped(float mat[][4])
+{
+ float vec[3];
+
+ Crossf(vec, mat[0], mat[1]);
+ if( Inpf(vec, mat[2]) < 0.0 ) return 1;
+ return 0;
+}
+
+/* transform widget center calc helper for below */
+static void calc_tw_center(float *co)
+{
+ float *twcent= G.scene->twcent;
+ float *min= G.scene->twmin;
+ float *max= G.scene->twmax;
+
+ DO_MINMAX(co, min, max);
+ VecAddf(twcent, twcent, co);
+}
+
+static void protectflag_to_drawflags(short protectflag, short *drawflags)
+{
+ if(protectflag & OB_LOCK_LOCX)
+ *drawflags &= ~MAN_TRANS_X;
+ if(protectflag & OB_LOCK_LOCY)
+ *drawflags &= ~MAN_TRANS_Y;
+ if(protectflag & OB_LOCK_LOCZ)
+ *drawflags &= ~MAN_TRANS_Z;
+
+ if(protectflag & OB_LOCK_ROTX)
+ *drawflags &= ~MAN_ROT_X;
+ if(protectflag & OB_LOCK_ROTY)
+ *drawflags &= ~MAN_ROT_Y;
+ if(protectflag & OB_LOCK_ROTZ)
+ *drawflags &= ~MAN_ROT_Z;
+
+ if(protectflag & OB_LOCK_SCALEX)
+ *drawflags &= ~MAN_SCALE_X;
+ if(protectflag & OB_LOCK_SCALEY)
+ *drawflags &= ~MAN_SCALE_Y;
+ if(protectflag & OB_LOCK_SCALEZ)
+ *drawflags &= ~MAN_SCALE_Z;
+}
+
+/* for pose mode */
+static void stats_pose(View3D *v3d, bPoseChannel *pchan)
+{
+ Bone *bone= pchan->bone;
+
+ if(bone) {
+ if (bone->flag & BONE_TRANSFORM) {
+ calc_tw_center(pchan->pose_head);
+ protectflag_to_drawflags(pchan->protectflag, &v3d->twdrawflag);
+ }
+ }
+}
+
+/* for editmode*/
+static void stats_editbone(View3D *v3d, EditBone *ebo)
+{
+ if (ebo->flag & BONE_EDITMODE_LOCKED)
+ protectflag_to_drawflags(OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE, &v3d->twdrawflag);
+}
+
+/* only counts the parent selection, and tags transform flag */
+/* bad call... should re-use method from transform_conversion once */
+static void count_bone_select(TransInfo *t, bArmature *arm, ListBase *lb, int do_it)
+{
+ Bone *bone;
+ int do_next;
+
+ for(bone= lb->first; bone; bone= bone->next) {
+ bone->flag &= ~BONE_TRANSFORM;
+ do_next= do_it;
+ if(do_it) {
+ if(bone->layer & arm->layer) {
+ if (bone->flag & BONE_SELECTED) {
+ /* We don't let connected children get "grabbed" */
+ if ( (t->mode!=TFM_TRANSLATION) || (bone->flag & BONE_CONNECTED)==0 ) {
+ bone->flag |= BONE_TRANSFORM;
+ t->total++;
+ do_next= 0; // no transform on children if one parent bone is selected
+ }
+ }
+ }
+ }
+ count_bone_select(t, arm, &bone->childbase, do_next);
+ }
+}
+
+/* centroid, boundbox, of selection */
+/* returns total items selected */
+int calc_manipulator_stats(ScrArea *sa)
+{
+ TransInfo *t;
+ View3D *v3d= sa->spacedata.first;
+ Base *base;
+ Object *ob= OBACT;
+ float normal[3]={0.0, 0.0, 0.0};
+ float plane[3]={0.0, 0.0, 0.0};
+ int a, totsel=0;
+
+//XXX t = BIF_GetTransInfo();
+
+ /* transform widget matrix */
+ Mat4One(v3d->twmat);
+
+ v3d->twdrawflag= 0xFFFF;
+
+ /* transform widget centroid/center */
+ G.scene->twcent[0]= G.scene->twcent[1]= G.scene->twcent[2]= 0.0f;
+ INIT_MINMAX(G.scene->twmin, G.scene->twmax);
+
+ if(t->obedit) {
+ ob= t->obedit;
+ if((ob->lay & G.vd->lay)==0) return 0;
+
+ if(t->obedit->type==OB_MESH) {
+ EditMesh *em = NULL; // TRANSFORM_FIX_ME
+ EditVert *eve;
+ EditSelection ese;
+ float vec[3]= {0,0,0};
+
+ /* USE LAST SELECTE WITH ACTIVE */
+ if (G.vd->around==V3D_ACTIVE && EM_get_actSelection(&ese)) {
+ EM_editselection_center(vec, &ese);
+ calc_tw_center(vec);
+ totsel= 1;
+ } else {
+ /* do vertices for center, and if still no normal found, use vertex normals */
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f & SELECT) {
+ totsel++;
+ calc_tw_center(eve->co);
+ }
+ }
+ }
+ } /* end editmesh */
+ else if (t->obedit->type==OB_ARMATURE){
+ bArmature *arm= t->obedit->data;
+ EditBone *ebo;
+ for (ebo=G.edbo.first;ebo;ebo=ebo->next){
+ if(ebo->layer & arm->layer) {
+ if (ebo->flag & BONE_TIPSEL) {
+ calc_tw_center(ebo->tail);
+ totsel++;
+ }
+ if (ebo->flag & BONE_ROOTSEL) {
+ calc_tw_center(ebo->head);
+ totsel++;
+ }
+ if (ebo->flag & BONE_SELECTED) {
+ stats_editbone(v3d, ebo);
+ }
+ }
+ }
+ }
+ else if ELEM(t->obedit->type, OB_CURVE, OB_SURF) {
+ Curve *cu= t->obedit->data;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+
+ nu= cu->editnurb->first;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ /* exceptions
+ * if handles are hidden then only check the center points.
+ * If 2 or more are selected then only use the center point too.
+ */
+ if (G.f & G_HIDDENHANDLES) {
+ if (bezt->f2 & SELECT) {
+ calc_tw_center(bezt->vec[1]);
+ totsel++;
+ }
+ }
+ else if ( (bezt->f1 & SELECT) + (bezt->f2 & SELECT) + (bezt->f3 & SELECT) > SELECT ) {
+ calc_tw_center(bezt->vec[1]);
+ totsel++;
+ }
+ else {
+ if(bezt->f1) {
+ calc_tw_center(bezt->vec[0]);
+ totsel++;
+ }
+ if(bezt->f2) {
+ calc_tw_center(bezt->vec[1]);
+ totsel++;
+ }
+ if(bezt->f3) {
+ calc_tw_center(bezt->vec[2]);
+ totsel++;
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp->f1 & SELECT) {
+ calc_tw_center(bp->vec);
+ totsel++;
+ }
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ }
+ else if(t->obedit->type==OB_MBALL) {
+ /* editmball.c */
+ extern ListBase editelems; /* go away ! */
+ MetaElem *ml, *ml_sel=NULL;
+
+ ml= editelems.first;
+ while(ml) {
+ if(ml->flag & SELECT) {
+ calc_tw_center(&ml->x);
+ ml_sel = ml;
+ totsel++;
+ }
+ ml= ml->next;
+ }
+ }
+ else if(t->obedit->type==OB_LATTICE) {
+ BPoint *bp;
+ bp= editLatt->def;
+
+ a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+ while(a--) {
+ if(bp->f1 & SELECT) {
+ calc_tw_center(bp->vec);
+ totsel++;
+ }
+ bp++;
+ }
+ }
+
+ /* selection center */
+ if(totsel) {
+ VecMulf(G.scene->twcent, 1.0f/(float)totsel); // centroid!
+ Mat4MulVecfl(t->obedit->obmat, G.scene->twcent);
+ Mat4MulVecfl(t->obedit->obmat, G.scene->twmin);
+ Mat4MulVecfl(t->obedit->obmat, G.scene->twmax);
+ }
+ }
+ else if(ob && (ob->flag & OB_POSEMODE)) {
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan;
+ int mode;
+
+ if((ob->lay & G.vd->lay)==0) return 0;
+
+ mode = Trans.mode;
+ Trans.mode = TFM_ROTATION; // mislead counting bones... bah
+
+ /* count total, we use same method as transform will do */
+ Trans.total= 0;
+ count_bone_select(&Trans, arm, &arm->bonebase, 1);
+ totsel = Trans.total;
+ if(totsel) {
+ /* use channels to get stats */
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ stats_pose(v3d, pchan);
+ }
+
+ VecMulf(G.scene->twcent, 1.0f/(float)totsel); // centroid!
+ Mat4MulVecfl(ob->obmat, G.scene->twcent);
+ Mat4MulVecfl(ob->obmat, G.scene->twmin);
+ Mat4MulVecfl(ob->obmat, G.scene->twmax);
+ }
+ /* restore, mode can be TFM_INIT */
+ Trans.mode = mode;
+ }
+ else if(G.f & (G_VERTEXPAINT + G_TEXTUREPAINT + G_WEIGHTPAINT + G_SCULPTMODE)) {
+ ;
+ }
+ else if(G.f & G_PARTICLEEDIT) {
+ ParticleSystem *psys=PE_get_current(OBACT);
+ ParticleData *pa = psys->particles;
+ ParticleEditKey *ek;
+ int k;
+
+ if(psys->edit) {
+ for(a=0; a<psys->totpart; a++,pa++) {
+ if(pa->flag & PARS_HIDE) continue;
+
+ for(k=0, ek=psys->edit->keys[a]; k<pa->totkey; k++, ek++) {
+ if(ek->flag & PEK_SELECT) {
+ calc_tw_center(ek->world_co);
+ totsel++;
+ }
+ }
+ }
+
+ /* selection center */
+ if(totsel)
+ VecMulf(G.scene->twcent, 1.0f/(float)totsel); // centroid!
+ }
+ }
+ else {
+
+ /* we need the one selected object, if its not active */
+ ob= OBACT;
+ if(ob && !(ob->flag & SELECT)) ob= NULL;
+
+ for(base= G.scene->base.first; base; base= base->next) {
+ if TESTBASELIB(base) {
+ if(ob==NULL)
+ ob= base->object;
+ calc_tw_center(base->object->obmat[3]);
+ protectflag_to_drawflags(base->object->protectflag, &v3d->twdrawflag);
+ totsel++;
+ }
+ }
+
+ /* selection center */
+ if(totsel) {
+ VecMulf(G.scene->twcent, 1.0f/(float)totsel); // centroid!
+ }
+ }
+
+ /* global, local or normal orientation? */
+ if(ob && totsel) {
+
+ switch(v3d->twmode) {
+ case V3D_MANIP_GLOBAL:
+ strcpy(t->spacename, "global");
+ break;
+
+ case V3D_MANIP_NORMAL:
+ if(t->obedit || ob->flag & OB_POSEMODE) {
+ float mat[3][3];
+ int type;
+
+ strcpy(t->spacename, "normal");
+
+ type = getTransformOrientation(normal, plane, (G.vd->around == V3D_ACTIVE));
+
+ switch (type)
+ {
+ case ORIENTATION_NORMAL:
+ if (createSpaceNormalTangent(mat, normal, plane) == 0)
+ {
+ type = ORIENTATION_NONE;
+ }
+ break;
+ case ORIENTATION_VERT:
+ if (createSpaceNormal(mat, normal) == 0)
+ {
+ type = ORIENTATION_NONE;
+ }
+ break;
+ case ORIENTATION_EDGE:
+ if (createSpaceNormalTangent(mat, normal, plane) == 0)
+ {
+ type = ORIENTATION_NONE;
+ }
+ break;
+ case ORIENTATION_FACE:
+ if (createSpaceNormalTangent(mat, normal, plane) == 0)
+ {
+ type = ORIENTATION_NONE;
+ }
+ break;
+ }
+
+ if (type == ORIENTATION_NONE)
+ {
+ Mat4One(v3d->twmat);
+ }
+ else
+ {
+ Mat4CpyMat3(v3d->twmat, mat);
+ }
+ break;
+ }
+ /* no break we define 'normal' as 'local' in Object mode */
+ case V3D_MANIP_LOCAL:
+ strcpy(t->spacename, "local");
+ Mat4CpyMat4(v3d->twmat, ob->obmat);
+ Mat4Ortho(v3d->twmat);
+ break;
+
+ case V3D_MANIP_VIEW:
+ {
+ float mat[3][3];
+ strcpy(t->spacename, "view");
+ Mat3CpyMat4(mat, v3d->viewinv);
+ Mat3Ortho(mat);
+ Mat4CpyMat3(v3d->twmat, mat);
+ }
+ break;
+ default: /* V3D_MANIP_CUSTOM */
+ applyTransformOrientation();
+ break;
+ }
+
+ }
+
+ return totsel;
+}
+
+/* ******************** DRAWING STUFFIES *********** */
+
+static float screen_aligned(float mat[][4])
+{
+ float vec[3], size;
+
+ VECCOPY(vec, mat[0]);
+ size= Normalize(vec);
+
+ glTranslatef(mat[3][0], mat[3][1], mat[3][2]);
+
+ /* sets view screen aligned */
+ glRotatef( -360.0f*saacos(G.vd->viewquat[0])/(float)M_PI, G.vd->viewquat[1], G.vd->viewquat[2], G.vd->viewquat[3]);
+
+ return size;
+}
+
+
+/* radring = radius of donut rings
+ radhole = radius hole
+ start = starting segment (based on nrings)
+ end = end segment
+ nsides = amount of points in ring
+ nrigns = amount of rings
+*/
+static void partial_donut(float radring, float radhole, int start, int end, int nsides, int nrings)
+{
+ float theta, phi, theta1;
+ float cos_theta, sin_theta;
+ float cos_theta1, sin_theta1;
+ float ring_delta, side_delta;
+ int i, j, docaps= 1;
+
+ if(start==0 && end==nrings) docaps= 0;
+
+ ring_delta= 2.0f*(float)M_PI/(float)nrings;
+ side_delta= 2.0f*(float)M_PI/(float)nsides;
+
+ theta= (float)M_PI+0.5f*ring_delta;
+ cos_theta= (float)cos(theta);
+ sin_theta= (float)sin(theta);
+
+ for(i= nrings - 1; i >= 0; i--) {
+ theta1= theta + ring_delta;
+ cos_theta1= (float)cos(theta1);
+ sin_theta1= (float)sin(theta1);
+
+ if(docaps && i==start) { // cap
+ glBegin(GL_POLYGON);
+ phi= 0.0;
+ for(j= nsides; j >= 0; j--) {
+ float cos_phi, sin_phi, dist;
+
+ phi += side_delta;
+ cos_phi= (float)cos(phi);
+ sin_phi= (float)sin(phi);
+ dist= radhole + radring * cos_phi;
+
+ glVertex3f(cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi);
+ }
+ glEnd();
+ }
+ if(i>=start && i<=end) {
+ glBegin(GL_QUAD_STRIP);
+ phi= 0.0;
+ for(j= nsides; j >= 0; j--) {
+ float cos_phi, sin_phi, dist;
+
+ phi += side_delta;
+ cos_phi= (float)cos(phi);
+ sin_phi= (float)sin(phi);
+ dist= radhole + radring * cos_phi;
+
+ glVertex3f(cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi);
+ glVertex3f(cos_theta * dist, -sin_theta * dist, radring * sin_phi);
+ }
+ glEnd();
+ }
+
+ if(docaps && i==end) { // cap
+ glBegin(GL_POLYGON);
+ phi= 0.0;
+ for(j= nsides; j >= 0; j--) {
+ float cos_phi, sin_phi, dist;
+
+ phi -= side_delta;
+ cos_phi= (float)cos(phi);
+ sin_phi= (float)sin(phi);
+ dist= radhole + radring * cos_phi;
+
+ glVertex3f(cos_theta * dist, -sin_theta * dist, radring * sin_phi);
+ }
+ glEnd();
+ }
+
+
+ theta= theta1;
+ cos_theta= cos_theta1;
+ sin_theta= sin_theta1;
+ }
+}
+
+/* three colors can be set;
+ grey for ghosting
+ moving: in transform theme color
+ else the red/green/blue
+*/
+static void manipulator_setcolor(char axis, int colcode)
+{
+ float vec[4];
+ char col[4];
+
+ vec[3]= 0.7f; // alpha set on 0.5, can be glEnabled or not
+
+ if(colcode==MAN_GHOST) {
+ glColor4ub(0, 0, 0, 70);
+ }
+ else if(colcode==MAN_MOVECOL) {
+ BIF_GetThemeColor3ubv(TH_TRANSFORM, col);
+ glColor4ub(col[0], col[1], col[2], 128);
+ }
+ else {
+ switch(axis) {
+ case 'c':
+ BIF_GetThemeColor3ubv(TH_TRANSFORM, col);
+ if(G.vd->twmode == V3D_MANIP_LOCAL) {
+ col[0]= col[0]>200?255:col[0]+55;
+ col[1]= col[1]>200?255:col[1]+55;
+ col[2]= col[2]>200?255:col[2]+55;
+ }
+ else if(G.vd->twmode == V3D_MANIP_NORMAL) {
+ col[0]= col[0]<55?0:col[0]-55;
+ col[1]= col[1]<55?0:col[1]-55;
+ col[2]= col[2]<55?0:col[2]-55;
+ }
+ glColor4ub(col[0], col[1], col[2], 128);
+ break;
+ case 'x':
+ glColor4ub(220, 0, 0, 128);
+ break;
+ case 'y':
+ glColor4ub(0, 220, 0, 128);
+ break;
+ case 'z':
+ glColor4ub(30, 30, 220, 128);
+ break;
+ }
+ }
+}
+
+/* viewmatrix should have been set OK, also no shademode! */
+static void draw_manipulator_axes(int colcode, int flagx, int flagy, int flagz)
+{
+
+ /* axes */
+ if(flagx) {
+ manipulator_setcolor('x', colcode);
+ if(flagx & MAN_SCALE_X) glLoadName(MAN_SCALE_X);
+ else if(flagx & MAN_TRANS_X) glLoadName(MAN_TRANS_X);
+ glBegin(GL_LINES);
+ glVertex3f(0.2f, 0.0f, 0.0f);
+ glVertex3f(1.0f, 0.0f, 0.0f);
+ glEnd();
+ }
+ if(flagy) {
+ if(flagy & MAN_SCALE_Y) glLoadName(MAN_SCALE_Y);
+ else if(flagy & MAN_TRANS_Y) glLoadName(MAN_TRANS_Y);
+ manipulator_setcolor('y', colcode);
+ glBegin(GL_LINES);
+ glVertex3f(0.0f, 0.2f, 0.0f);
+ glVertex3f(0.0f, 1.0f, 0.0f);
+ glEnd();
+ }
+ if(flagz) {
+ if(flagz & MAN_SCALE_Z) glLoadName(MAN_SCALE_Z);
+ else if(flagz & MAN_TRANS_Z) glLoadName(MAN_TRANS_Z);
+ manipulator_setcolor('z', colcode);
+ glBegin(GL_LINES);
+ glVertex3f(0.0f, 0.0f, 0.2f);
+ glVertex3f(0.0f, 0.0f, 1.0f);
+ glEnd();
+ }
+}
+
+/* only called while G.moving */
+static void draw_manipulator_rotate_ghost(float mat[][4], int drawflags)
+{
+ GLUquadricObj *qobj;
+ float size, phi, startphi, vec[3], svec[3], matt[4][4], cross[3], tmat[3][3];
+ int arcs= (G.rt!=2);
+
+ glDisable(GL_DEPTH_TEST);
+
+ qobj= gluNewQuadric();
+ gluQuadricDrawStyle(qobj, GLU_FILL);
+
+ glColor4ub(0,0,0,64);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ /* we need both [4][4] transforms, Trans.mat seems to be premul, not post for mat[][4] */
+ Mat4CpyMat4(matt, mat); // to copy the parts outside of [3][3]
+ Mat4MulMat34(matt, Trans.mat, mat);
+
+ /* Screen aligned view rot circle */
+ if(drawflags & MAN_ROT_V) {
+
+ /* prepare for screen aligned draw */
+ glPushMatrix();
+ size= screen_aligned(mat);
+
+ vec[0]= (float)(Trans.con.imval[0] - Trans.center2d[0]);
+ vec[1]= (float)(Trans.con.imval[1] - Trans.center2d[1]);
+ vec[2]= 0.0f;
+ Normalize(vec);
+
+ startphi= saacos( vec[1] );
+ if(vec[0]<0.0) startphi= -startphi;
+
+ phi= (float)fmod(180.0*Trans.val/M_PI, 360.0);
+ if(phi > 180.0) phi-= 360.0;
+ else if(phi<-180.0) phi+= 360.0;
+
+ gluPartialDisk(qobj, 0.0, size, 32, 1, 180.0*startphi/M_PI, phi);
+
+ glPopMatrix();
+ }
+ else if(arcs) {
+ float imat[3][3], ivmat[3][3];
+ /* try to get the start rotation */
+
+ svec[0]= (float)(Trans.con.imval[0] - Trans.center2d[0]);
+ svec[1]= (float)(Trans.con.imval[1] - Trans.center2d[1]);
+ svec[2]= 0.0f;
+
+ /* screen aligned vec transform back to manipulator space */
+ Mat3CpyMat4(ivmat, G.vd->viewinv);
+ Mat3CpyMat4(tmat, mat);
+ Mat3Inv(imat, tmat);
+ Mat3MulMat3(tmat, imat, ivmat);
+
+ Mat3MulVecfl(tmat, svec); // tmat is used further on
+ Normalize(svec);
+ }
+
+ mymultmatrix(mat); // aligns with original widget
+
+ /* Z disk */
+ if(drawflags & MAN_ROT_Z) {
+ if(arcs) {
+ /* correct for squeezed arc */
+ svec[0]+= tmat[2][0];
+ svec[1]+= tmat[2][1];
+ Normalize(svec);
+
+ startphi= (float)atan2(svec[0], svec[1]);
+ }
+ else startphi= 0.5f*(float)M_PI;
+
+ VECCOPY(vec, mat[0]); // use x axis to detect rotation
+ Normalize(vec);
+ Normalize(matt[0]);
+ phi= saacos( Inpf(vec, matt[0]) );
+ if(phi!=0.0) {
+ Crossf(cross, vec, matt[0]); // results in z vector
+ if(Inpf(cross, mat[2]) > 0.0) phi= -phi;
+ gluPartialDisk(qobj, 0.0, 1.0, 32, 1, 180.0*startphi/M_PI, 180.0*(phi)/M_PI);
+ }
+ }
+ /* X disk */
+ if(drawflags & MAN_ROT_X) {
+ if(arcs) {
+ /* correct for squeezed arc */
+ svec[1]+= tmat[2][1];
+ svec[2]+= tmat[2][2];
+ Normalize(svec);
+
+ startphi= (float)(M_PI + atan2(svec[2], -svec[1]));
+ }
+ else startphi= 0.0f;
+
+ VECCOPY(vec, mat[1]); // use y axis to detect rotation
+ Normalize(vec);
+ Normalize(matt[1]);
+ phi= saacos( Inpf(vec, matt[1]) );
+ if(phi!=0.0) {
+ Crossf(cross, vec, matt[1]); // results in x vector
+ if(Inpf(cross, mat[0]) > 0.0) phi= -phi;
+ glRotatef(90.0, 0.0, 1.0, 0.0);
+ gluPartialDisk(qobj, 0.0, 1.0, 32, 1, 180.0*startphi/M_PI, 180.0*phi/M_PI);
+ glRotatef(-90.0, 0.0, 1.0, 0.0);
+ }
+ }
+ /* Y circle */
+ if(drawflags & MAN_ROT_Y) {
+ if(arcs) {
+ /* correct for squeezed arc */
+ svec[0]+= tmat[2][0];
+ svec[2]+= tmat[2][2];
+ Normalize(svec);
+
+ startphi= (float)(M_PI + atan2(-svec[0], svec[2]));
+ }
+ else startphi= (float)M_PI;
+
+ VECCOPY(vec, mat[2]); // use z axis to detect rotation
+ Normalize(vec);
+ Normalize(matt[2]);
+ phi= saacos( Inpf(vec, matt[2]) );
+ if(phi!=0.0) {
+ Crossf(cross, vec, matt[2]); // results in y vector
+ if(Inpf(cross, mat[1]) > 0.0) phi= -phi;
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ gluPartialDisk(qobj, 0.0, 1.0, 32, 1, 180.0*startphi/M_PI, 180.0*phi/M_PI);
+ glRotatef(90.0, 1.0, 0.0, 0.0);
+ }
+ }
+
+ glDisable(GL_BLEND);
+ myloadmatrix(G.vd->viewmat);
+}
+
+static void draw_manipulator_rotate(float mat[][4], int moving, int drawflags, int combo)
+{
+ GLUquadricObj *qobj;
+ double plane[4];
+ float size, vec[3], unitmat[4][4];
+ float cywid= 0.33f*0.01f*(float)U.tw_handlesize;
+ float cusize= cywid*0.65f;
+ int arcs= (G.rt!=2);
+ int colcode;
+
+ if(moving) colcode= MAN_MOVECOL;
+ else colcode= MAN_RGB;
+
+ /* when called while moving in mixed mode, do not draw when... */
+ if((drawflags & MAN_ROT_C)==0) return;
+
+ /* Init stuff */
+ glDisable(GL_DEPTH_TEST);
+ Mat4One(unitmat);
+
+ qobj= gluNewQuadric();
+ gluQuadricDrawStyle(qobj, GLU_FILL);
+
+ /* prepare for screen aligned draw */
+ VECCOPY(vec, mat[0]);
+ size= Normalize(vec);
+ glPushMatrix();
+ glTranslatef(mat[3][0], mat[3][1], mat[3][2]);
+
+ if(arcs) {
+ /* clipplane makes nice handles, calc here because of multmatrix but with translate! */
+ VECCOPY(plane, G.vd->viewinv[2]);
+ plane[3]= -0.02*size; // clip just a bit more
+ glClipPlane(GL_CLIP_PLANE0, plane);
+ }
+ /* sets view screen aligned */
+ glRotatef( -360.0f*saacos(G.vd->viewquat[0])/(float)M_PI, G.vd->viewquat[1], G.vd->viewquat[2], G.vd->viewquat[3]);
+
+ /* Screen aligned help circle */
+ if(arcs) {
+ if((G.f & G_PICKSEL)==0) {
+ BIF_ThemeColorShade(TH_BACK, -30);
+ drawcircball(GL_LINE_LOOP, unitmat[3], size, unitmat);
+ }
+ }
+ /* Screen aligned view rot circle */
+ if(drawflags & MAN_ROT_V) {
+ if(G.f & G_PICKSEL) glLoadName(MAN_ROT_V);
+ BIF_ThemeColor(TH_TRANSFORM);
+ drawcircball(GL_LINE_LOOP, unitmat[3], 1.2f*size, unitmat);
+
+ if(moving) {
+ float vec[3];
+ vec[0]= (float)(Trans.imval[0] - Trans.center2d[0]);
+ vec[1]= (float)(Trans.imval[1] - Trans.center2d[1]);
+ vec[2]= 0.0f;
+ Normalize(vec);
+ VecMulf(vec, 1.2f*size);
+ glBegin(GL_LINES);
+ glVertex3f(0.0f, 0.0f, 0.0f);
+ glVertex3fv(vec);
+ glEnd();
+ }
+ }
+ glPopMatrix();
+
+ /* apply the transform delta */
+ if(moving) {
+ float matt[4][4];
+ Mat4CpyMat4(matt, mat); // to copy the parts outside of [3][3]
+ Mat4MulMat34(matt, Trans.mat, mat);
+ mymultmatrix(matt);
+ glFrontFace( is_mat4_flipped(matt)?GL_CW:GL_CCW);
+ }
+ else {
+ glFrontFace( is_mat4_flipped(mat)?GL_CW:GL_CCW);
+ mymultmatrix(mat);
+ }
+
+ /* axes */
+ if(arcs==0) {
+ if(!(G.f & G_PICKSEL)) {
+ if( (combo & V3D_MANIP_SCALE)==0) {
+ /* axis */
+ glBegin(GL_LINES);
+ if( (drawflags & MAN_ROT_X) || (moving && (drawflags & MAN_ROT_Z)) ) {
+ manipulator_setcolor('x', colcode);
+ glVertex3f(0.2f, 0.0f, 0.0f);
+ glVertex3f(1.0f, 0.0f, 0.0f);
+ }
+ if( (drawflags & MAN_ROT_Y) || (moving && (drawflags & MAN_ROT_X)) ) {
+ manipulator_setcolor('y', colcode);
+ glVertex3f(0.0f, 0.2f, 0.0f);
+ glVertex3f(0.0f, 1.0f, 0.0f);
+ }
+ if( (drawflags & MAN_ROT_Z) || (moving && (drawflags & MAN_ROT_Y)) ) {
+ manipulator_setcolor('z', colcode);
+ glVertex3f(0.0f, 0.0f, 0.2f);
+ glVertex3f(0.0f, 0.0f, 1.0f);
+ }
+ glEnd();
+ }
+ }
+ }
+
+ if(arcs==0 && moving) {
+
+ /* Z circle */
+ if(drawflags & MAN_ROT_Z) {
+ if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
+ manipulator_setcolor('z', colcode);
+ drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
+ }
+ /* X circle */
+ if(drawflags & MAN_ROT_X) {
+ if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
+ glRotatef(90.0, 0.0, 1.0, 0.0);
+ manipulator_setcolor('x', colcode);
+ drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
+ glRotatef(-90.0, 0.0, 1.0, 0.0);
+ }
+ /* Y circle */
+ if(drawflags & MAN_ROT_Y) {
+ if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ manipulator_setcolor('y', colcode);
+ drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
+ glRotatef(90.0, 1.0, 0.0, 0.0);
+ }
+
+ if(arcs) glDisable(GL_CLIP_PLANE0);
+ }
+ // donut arcs
+ if(arcs) {
+ glEnable(GL_CLIP_PLANE0);
+
+ /* Z circle */
+ if(drawflags & MAN_ROT_Z) {
+ if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
+ manipulator_setcolor('z', colcode);
+ partial_donut(cusize/4.0f, 1.0f, 0, 48, 8, 48);
+ }
+ /* X circle */
+ if(drawflags & MAN_ROT_X) {
+ if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
+ glRotatef(90.0, 0.0, 1.0, 0.0);
+ manipulator_setcolor('x', colcode);
+ partial_donut(cusize/4.0f, 1.0f, 0, 48, 8, 48);
+ glRotatef(-90.0, 0.0, 1.0, 0.0);
+ }
+ /* Y circle */
+ if(drawflags & MAN_ROT_Y) {
+ if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ manipulator_setcolor('y', colcode);
+ partial_donut(cusize/4.0f, 1.0f, 0, 48, 8, 48);
+ glRotatef(90.0, 1.0, 0.0, 0.0);
+ }
+
+ glDisable(GL_CLIP_PLANE0);
+ }
+
+ if(arcs==0) {
+
+ /* Z handle on X axis */
+ if(drawflags & MAN_ROT_Z) {
+ glPushMatrix();
+ if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
+ manipulator_setcolor('z', colcode);
+
+ partial_donut(0.7f*cusize, 1.0f, 31, 33, 8, 64);
+
+ glPopMatrix();
+ }
+
+ /* Y handle on X axis */
+ if(drawflags & MAN_ROT_Y) {
+ glPushMatrix();
+ if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
+ manipulator_setcolor('y', colcode);
+
+ glRotatef(90.0, 1.0, 0.0, 0.0);
+ glRotatef(90.0, 0.0, 0.0, 1.0);
+ partial_donut(0.7f*cusize, 1.0f, 31, 33, 8, 64);
+
+ glPopMatrix();
+ }
+
+ /* X handle on Z axis */
+ if(drawflags & MAN_ROT_X) {
+ glPushMatrix();
+ if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
+ manipulator_setcolor('x', colcode);
+
+ glRotatef(-90.0, 0.0, 1.0, 0.0);
+ glRotatef(90.0, 0.0, 0.0, 1.0);
+ partial_donut(0.7f*cusize, 1.0f, 31, 33, 8, 64);
+
+ glPopMatrix();
+ }
+
+ }
+
+ /* restore */
+ myloadmatrix(G.vd->viewmat);
+ gluDeleteQuadric(qobj);
+ if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
+
+}
+
+static void draw_manipulator_scale(float mat[][4], int moving, int drawflags, int combo, int colcode)
+{
+ float cywid= 0.25f*0.01f*(float)U.tw_handlesize;
+ float cusize= cywid*0.75f, dz;
+
+ /* when called while moving in mixed mode, do not draw when... */
+ if((drawflags & MAN_SCALE_C)==0) return;
+
+ glDisable(GL_DEPTH_TEST);
+
+ /* not in combo mode */
+ if( (combo & (V3D_MANIP_TRANSLATE|V3D_MANIP_ROTATE))==0) {
+ float size, unitmat[4][4];
+
+ /* center circle, do not add to selection when shift is pressed (planar constraint) */
+ if( (G.f & G_PICKSEL) && (G.qual & LR_SHIFTKEY)==0) glLoadName(MAN_SCALE_C);
+
+ manipulator_setcolor('c', colcode);
+ glPushMatrix();
+ size= screen_aligned(mat);
+ Mat4One(unitmat);
+ drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f*size, unitmat);
+ glPopMatrix();
+
+ dz= 1.0;
+ }
+ else dz= 1.0f-4.0f*cusize;
+
+ if(moving) {
+ float matt[4][4];
+
+ Mat4CpyMat4(matt, mat); // to copy the parts outside of [3][3]
+ Mat4MulMat34(matt, Trans.mat, mat);
+ mymultmatrix(matt);
+ glFrontFace( is_mat4_flipped(matt)?GL_CW:GL_CCW);
+ }
+ else {
+ mymultmatrix(mat);
+ glFrontFace( is_mat4_flipped(mat)?GL_CW:GL_CCW);
+ }
+
+ /* axis */
+
+ /* in combo mode, this is always drawn as first type */
+ draw_manipulator_axes(colcode, drawflags & MAN_SCALE_X, drawflags & MAN_SCALE_Y, drawflags & MAN_SCALE_Z);
+
+ /* Z cube */
+ glTranslatef(0.0, 0.0, dz);
+ if(drawflags & MAN_SCALE_Z) {
+ if(G.f & G_PICKSEL) glLoadName(MAN_SCALE_Z);
+ manipulator_setcolor('z', colcode);
+ drawsolidcube(cusize);
+ }
+ /* X cube */
+ glTranslatef(dz, 0.0, -dz);
+ if(drawflags & MAN_SCALE_X) {
+ if(G.f & G_PICKSEL) glLoadName(MAN_SCALE_X);
+ manipulator_setcolor('x', colcode);
+ drawsolidcube(cusize);
+ }
+ /* Y cube */
+ glTranslatef(-dz, dz, 0.0);
+ if(drawflags & MAN_SCALE_Y) {
+ if(G.f & G_PICKSEL) glLoadName(MAN_SCALE_Y);
+ manipulator_setcolor('y', colcode);
+ drawsolidcube(cusize);
+ }
+
+ /* if shiftkey, center point as last, for selectbuffer order */
+ if(G.f & G_PICKSEL) {
+ if(G.qual & LR_SHIFTKEY) {
+ glTranslatef(0.0, -dz, 0.0);
+ glLoadName(MAN_SCALE_C);
+ glBegin(GL_POINTS);
+ glVertex3f(0.0, 0.0, 0.0);
+ glEnd();
+ }
+ }
+
+ /* restore */
+ myloadmatrix(G.vd->viewmat);
+
+ if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
+ glFrontFace(GL_CCW);
+}
+
+
+static void draw_cone(GLUquadricObj *qobj, float len, float width)
+{
+ glTranslatef(0.0, 0.0, -0.5f*len);
+ gluCylinder(qobj, width, 0.0, len, 8, 1);
+ gluQuadricOrientation(qobj, GLU_INSIDE);
+ gluDisk(qobj, 0.0, width, 8, 1);
+ gluQuadricOrientation(qobj, GLU_OUTSIDE);
+ glTranslatef(0.0, 0.0, 0.5f*len);
+}
+
+static void draw_cylinder(GLUquadricObj *qobj, float len, float width)
+{
+
+ width*= 0.8f; // just for beauty
+
+ glTranslatef(0.0, 0.0, -0.5f*len);
+ gluCylinder(qobj, width, width, len, 8, 1);
+ gluQuadricOrientation(qobj, GLU_INSIDE);
+ gluDisk(qobj, 0.0, width, 8, 1);
+ gluQuadricOrientation(qobj, GLU_OUTSIDE);
+ glTranslatef(0.0, 0.0, len);
+ gluDisk(qobj, 0.0, width, 8, 1);
+ glTranslatef(0.0, 0.0, -0.5f*len);
+}
+
+
+static void draw_manipulator_translate(float mat[][4], int moving, int drawflags, int combo, int colcode)
+{
+ GLUquadricObj *qobj;
+ float cylen= 0.01f*(float)U.tw_handlesize;
+ float cywid= 0.25f*cylen, dz, size;
+ float unitmat[4][4];
+
+ /* when called while moving in mixed mode, do not draw when... */
+ if((drawflags & MAN_TRANS_C)==0) return;
+
+ if(moving) glTranslatef(Trans.vec[0], Trans.vec[1], Trans.vec[2]);
+ glDisable(GL_DEPTH_TEST);
+
+ qobj= gluNewQuadric();
+ gluQuadricDrawStyle(qobj, GLU_FILL);
+
+ /* center circle, do not add to selection when shift is pressed (planar constraint) */
+ if( (G.f & G_PICKSEL) && (G.qual & LR_SHIFTKEY)==0) glLoadName(MAN_TRANS_C);
+
+ manipulator_setcolor('c', colcode);
+ glPushMatrix();
+ size= screen_aligned(mat);
+ Mat4One(unitmat);
+ drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f*size, unitmat);
+ glPopMatrix();
+
+ /* and now apply matrix, we move to local matrix drawing */
+ mymultmatrix(mat);
+
+ /* axis */
+ glLoadName(-1);
+
+ // translate drawn as last, only axis when no combo with scale, or for ghosting
+ if((combo & V3D_MANIP_SCALE)==0 || colcode==MAN_GHOST)
+ draw_manipulator_axes(colcode, drawflags & MAN_TRANS_X, drawflags & MAN_TRANS_Y, drawflags & MAN_TRANS_Z);
+
+
+ /* offset in combo mode, for rotate a bit more */
+ if(combo & (V3D_MANIP_ROTATE)) dz= 1.0f+2.0f*cylen;
+ else if(combo & (V3D_MANIP_SCALE)) dz= 1.0f+0.5f*cylen;
+ else dz= 1.0f;
+
+ /* Z Cone */
+ glTranslatef(0.0, 0.0, dz);
+ if(drawflags & MAN_TRANS_Z) {
+ if(G.f & G_PICKSEL) glLoadName(MAN_TRANS_Z);
+ manipulator_setcolor('z', colcode);
+ draw_cone(qobj, cylen, cywid);
+ }
+ /* X Cone */
+ glTranslatef(dz, 0.0, -dz);
+ if(drawflags & MAN_TRANS_X) {
+ if(G.f & G_PICKSEL) glLoadName(MAN_TRANS_X);
+ glRotatef(90.0, 0.0, 1.0, 0.0);
+ manipulator_setcolor('x', colcode);
+ draw_cone(qobj, cylen, cywid);
+ glRotatef(-90.0, 0.0, 1.0, 0.0);
+ }
+ /* Y Cone */
+ glTranslatef(-dz, dz, 0.0);
+ if(drawflags & MAN_TRANS_Y) {
+ if(G.f & G_PICKSEL) glLoadName(MAN_TRANS_Y);
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ manipulator_setcolor('y', colcode);
+ draw_cone(qobj, cylen, cywid);
+ }
+
+ gluDeleteQuadric(qobj);
+ myloadmatrix(G.vd->viewmat);
+
+ if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
+
+}
+
+static void draw_manipulator_rotate_cyl(float mat[][4], int moving, int drawflags, int combo, int colcode)
+{
+ GLUquadricObj *qobj;
+ float size;
+ float cylen= 0.01f*(float)U.tw_handlesize;
+ float cywid= 0.25f*cylen;
+
+ /* when called while moving in mixed mode, do not draw when... */
+ if((drawflags & MAN_ROT_C)==0) return;
+
+ /* prepare for screen aligned draw */
+ glPushMatrix();
+ size= screen_aligned(mat);
+
+ glDisable(GL_DEPTH_TEST);
+
+ qobj= gluNewQuadric();
+
+ /* Screen aligned view rot circle */
+ if(drawflags & MAN_ROT_V) {
+ float unitmat[4][4];
+ Mat4One(unitmat);
+
+ if(G.f & G_PICKSEL) glLoadName(MAN_ROT_V);
+ BIF_ThemeColor(TH_TRANSFORM);
+ drawcircball(GL_LINE_LOOP, unitmat[3], 1.2f*size, unitmat);
+
+ if(moving) {
+ float vec[3];
+ vec[0]= (float)(Trans.imval[0] - Trans.center2d[0]);
+ vec[1]= (float)(Trans.imval[1] - Trans.center2d[1]);
+ vec[2]= 0.0f;
+ Normalize(vec);
+ VecMulf(vec, 1.2f*size);
+ glBegin(GL_LINES);
+ glVertex3f(0.0, 0.0, 0.0);
+ glVertex3fv(vec);
+ glEnd();
+ }
+ }
+ glPopMatrix();
+
+ /* apply the transform delta */
+ if(moving) {
+ float matt[4][4];
+ Mat4CpyMat4(matt, mat); // to copy the parts outside of [3][3]
+ if (Trans.flag & T_USES_MANIPULATOR) {
+ Mat4MulMat34(matt, Trans.mat, mat);
+ }
+ mymultmatrix(matt);
+ }
+ else {
+ mymultmatrix(mat);
+ }
+
+ glFrontFace( is_mat4_flipped(mat)?GL_CW:GL_CCW);
+
+ /* axis */
+ if( (G.f & G_PICKSEL)==0 ) {
+
+ // only draw axis when combo didn't draw scale axes
+ if((combo & V3D_MANIP_SCALE)==0)
+ draw_manipulator_axes(colcode, drawflags & MAN_ROT_X, drawflags & MAN_ROT_Y, drawflags & MAN_ROT_Z);
+
+ /* only has to be set when not in picking */
+ gluQuadricDrawStyle(qobj, GLU_FILL);
+ }
+
+ /* Z cyl */
+ glTranslatef(0.0, 0.0, 1.0);
+ if(drawflags & MAN_ROT_Z) {
+ if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
+ manipulator_setcolor('z', colcode);
+ draw_cylinder(qobj, cylen, cywid);
+ }
+ /* X cyl */
+ glTranslatef(1.0, 0.0, -1.0);
+ if(drawflags & MAN_ROT_X) {
+ if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
+ glRotatef(90.0, 0.0, 1.0, 0.0);
+ manipulator_setcolor('x', colcode);
+ draw_cylinder(qobj, cylen, cywid);
+ glRotatef(-90.0, 0.0, 1.0, 0.0);
+ }
+ /* Y cylinder */
+ glTranslatef(-1.0, 1.0, 0.0);
+ if(drawflags & MAN_ROT_Y) {
+ if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ manipulator_setcolor('y', colcode);
+ draw_cylinder(qobj, cylen, cywid);
+ }
+
+ /* restore */
+
+ gluDeleteQuadric(qobj);
+ myloadmatrix(G.vd->viewmat);
+
+ if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
+
+}
+
+
+/* ********************************************* */
+
+static float get_manipulator_drawsize(ARegion *ar)
+{
+ RegionView3D *rv3d= ar->regiondata;
+ float size = get_drawsize(ar, rv3d->twmat[3]);
+
+ size*= (float)U.tw_size;
+
+ return size;
+}
+
+/* exported to transform_constraints.c */
+/* mat, vec = default orientation and location */
+/* type = transform type */
+/* axis = x, y, z, c */
+/* col: 0 = colored, 1 = moving, 2 = ghost */
+void draw_manipulator_ext(ScrArea *sa, int type, char axis, int col, float vec[3], float mat[][3])
+{
+ int drawflags= 0;
+ float mat4[4][4];
+ int colcode;
+
+ Mat4CpyMat3(mat4, mat);
+ VECCOPY(mat4[3], vec);
+
+ Mat4MulFloat3((float *)mat4, get_manipulator_drawsize(sa));
+
+ glEnable(GL_BLEND); // let's do it transparent by default
+ if(col==0) colcode= MAN_RGB;
+ else if(col==1) colcode= MAN_MOVECOL;
+ else colcode= MAN_GHOST;
+
+
+ if(type==TFM_ROTATION) {
+ if(axis=='x') drawflags= MAN_ROT_X;
+ else if(axis=='y') drawflags= MAN_ROT_Y;
+ else if(axis=='z') drawflags= MAN_ROT_Z;
+ else drawflags= MAN_ROT_C;
+
+ draw_manipulator_rotate_cyl(mat4, col, drawflags, V3D_MANIP_ROTATE, colcode);
+ }
+ else if(type==TFM_RESIZE) {
+ if(axis=='x') drawflags= MAN_SCALE_X;
+ else if(axis=='y') drawflags= MAN_SCALE_Y;
+ else if(axis=='z') drawflags= MAN_SCALE_Z;
+ else drawflags= MAN_SCALE_C;
+
+ draw_manipulator_scale(mat4, col, drawflags, V3D_MANIP_SCALE, colcode);
+ }
+ else {
+ if(axis=='x') drawflags= MAN_TRANS_X;
+ else if(axis=='y') drawflags= MAN_TRANS_Y;
+ else if(axis=='z') drawflags= MAN_TRANS_Z;
+ else drawflags= MAN_TRANS_C;
+
+ draw_manipulator_translate(mat4, 0, drawflags, V3D_MANIP_TRANSLATE, colcode);
+ }
+
+
+ glDisable(GL_BLEND);
+}
+
+/* main call, does calc centers & orientation too */
+/* uses global G.moving */
+static int drawflags= 0xFFFF; // only for the calls below, belongs in scene...?
+void BIF_draw_manipulator(ScrArea *sa)
+{
+ View3D *v3d= sa->spacedata.first;
+ int totsel;
+
+ if(!(v3d->twflag & V3D_USE_MANIPULATOR)) return;
+ if(G.moving && (G.moving & G_TRANSFORM_MANIP)==0) return;
+
+ if(G.moving==0) {
+ v3d->twflag &= ~V3D_DRAW_MANIPULATOR;
+
+ totsel= calc_manipulator_stats(sa);
+ if(totsel==0) return;
+ drawflags= v3d->twdrawflag; /* set in calc_manipulator_stats */
+
+ v3d->twflag |= V3D_DRAW_MANIPULATOR;
+
+ /* now we can define center */
+ switch(v3d->around) {
+ case V3D_CENTER:
+ case V3D_ACTIVE:
+ v3d->twmat[3][0]= (G.scene->twmin[0] + G.scene->twmax[0])/2.0f;
+ v3d->twmat[3][1]= (G.scene->twmin[1] + G.scene->twmax[1])/2.0f;
+ v3d->twmat[3][2]= (G.scene->twmin[2] + G.scene->twmax[2])/2.0f;
+ if(v3d->around==V3D_ACTIVE && t->obedit==NULL) {
+ Object *ob= OBACT;
+ if(ob && !(ob->flag & OB_POSEMODE))
+ VECCOPY(v3d->twmat[3], ob->obmat[3]);
+ }
+ break;
+ case V3D_LOCAL:
+ case V3D_CENTROID:
+ VECCOPY(v3d->twmat[3], G.scene->twcent);
+ break;
+ case V3D_CURSOR:
+ VECCOPY(v3d->twmat[3], give_cursor());
+ break;
+ }
+
+ Mat4MulFloat3((float *)v3d->twmat, get_manipulator_drawsize(sa));
+ }
+
+ if(v3d->twflag & V3D_DRAW_MANIPULATOR) {
+
+ if(v3d->twtype & V3D_MANIP_ROTATE) {
+
+ /* rotate has special ghosting draw, for pie chart */
+ if(G.moving) draw_manipulator_rotate_ghost(v3d->twmat, drawflags);
+
+ if(G.moving) glEnable(GL_BLEND);
+
+ if(G.rt==3) {
+ if(G.moving) draw_manipulator_rotate_cyl(v3d->twmat, 1, drawflags, v3d->twtype, MAN_MOVECOL);
+ else draw_manipulator_rotate_cyl(v3d->twmat, 0, drawflags, v3d->twtype, MAN_RGB);
+ }
+ else
+ draw_manipulator_rotate(v3d->twmat, G.moving, drawflags, v3d->twtype);
+
+ glDisable(GL_BLEND);
+ }
+ if(v3d->twtype & V3D_MANIP_SCALE) {
+ if(G.moving) {
+ glEnable(GL_BLEND);
+ draw_manipulator_scale(v3d->twmat, 0, drawflags, v3d->twtype, MAN_GHOST);
+ draw_manipulator_scale(v3d->twmat, 1, drawflags, v3d->twtype, MAN_MOVECOL);
+ glDisable(GL_BLEND);
+ }
+ else draw_manipulator_scale(v3d->twmat, 0, drawflags, v3d->twtype, MAN_RGB);
+ }
+ if(v3d->twtype & V3D_MANIP_TRANSLATE) {
+ if(G.moving) {
+ glEnable(GL_BLEND);
+ draw_manipulator_translate(v3d->twmat, 0, drawflags, v3d->twtype, MAN_GHOST);
+ draw_manipulator_translate(v3d->twmat, 1, drawflags, v3d->twtype, MAN_MOVECOL);
+ glDisable(GL_BLEND);
+ }
+ else draw_manipulator_translate(v3d->twmat, 0, drawflags, v3d->twtype, MAN_RGB);
+ }
+ }
+}
+
+static int manipulator_selectbuf(ScrArea *sa, float hotspot)
+{
+ View3D *v3d= sa->spacedata.first;
+ rctf rect;
+ GLuint buffer[64]; // max 4 items per select, so large enuf
+ short hits, mval[2];
+
+ G.f |= G_PICKSEL;
+
+ getmouseco_areawin(mval);
+ rect.xmin= mval[0]-hotspot;
+ rect.xmax= mval[0]+hotspot;
+ rect.ymin= mval[1]-hotspot;
+ rect.ymax= mval[1]+hotspot;
+
+ /* get rid of overlay button matrix */
+ persp(PERSP_VIEW);
+
+ setwinmatrixview3d(sa->winx, sa->winy, &rect);
+ Mat4MulMat4(v3d->persmat, v3d->viewmat, sa->winmat);
+
+ glSelectBuffer( 64, buffer);
+ glRenderMode(GL_SELECT);
+ glInitNames(); /* these two calls whatfor? It doesnt work otherwise */
+ glPushName(-2);
+
+ /* do the drawing */
+ if(v3d->twtype & V3D_MANIP_ROTATE) {
+ if(G.rt==3) draw_manipulator_rotate_cyl(v3d->twmat, 0, MAN_ROT_C & v3d->twdrawflag, v3d->twtype, MAN_RGB);
+ else draw_manipulator_rotate(v3d->twmat, 0, MAN_ROT_C & v3d->twdrawflag, v3d->twtype);
+ }
+ if(v3d->twtype & V3D_MANIP_SCALE)
+ draw_manipulator_scale(v3d->twmat, 0, MAN_SCALE_C & v3d->twdrawflag, v3d->twtype, MAN_RGB);
+ if(v3d->twtype & V3D_MANIP_TRANSLATE)
+ draw_manipulator_translate(v3d->twmat, 0, MAN_TRANS_C & v3d->twdrawflag, v3d->twtype, MAN_RGB);
+
+ glPopName();
+ hits= glRenderMode(GL_RENDER);
+
+ G.f &= ~G_PICKSEL;
+ setwinmatrixview3d(sa->winx, sa->winy, NULL);
+ Mat4MulMat4(v3d->persmat, v3d->viewmat, sa->winmat);
+
+ persp(PERSP_WIN);
+
+ if(hits==1) return buffer[3];
+ else if(hits>1) {
+ GLuint val, dep, mindep=0, mindeprot=0, minval=0, minvalrot=0;
+ int a;
+
+ /* we compare the hits in buffer, but value centers highest */
+ /* we also store the rotation hits separate (because of arcs) and return hits on other widgets if there are */
+
+ for(a=0; a<hits; a++) {
+ dep= buffer[4*a + 1];
+ val= buffer[4*a + 3];
+
+ if(val==MAN_TRANS_C) return MAN_TRANS_C;
+ else if(val==MAN_SCALE_C) return MAN_SCALE_C;
+ else {
+ if(val & MAN_ROT_C) {
+ if(minvalrot==0 || dep<mindeprot) {
+ mindeprot= dep;
+ minvalrot= val;
+ }
+ }
+ else {
+ if(minval==0 || dep<mindep) {
+ mindep= dep;
+ minval= val;
+ }
+ }
+ }
+ }
+
+ if(minval)
+ return minval;
+ else
+ return minvalrot;
+ }
+ return 0;
+}
+
+/* return 0; nothing happened */
+int BIF_do_manipulator(ScrArea *sa)
+{
+ View3D *v3d= sa->spacedata.first;
+ int val;
+
+ if(!(v3d->twflag & V3D_USE_MANIPULATOR)) return 0;
+ if(!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return 0;
+
+ // find the hotspots first test narrow hotspot
+ val= manipulator_selectbuf(sa, 0.5f*(float)U.tw_hotspot);
+ if(val) {
+ checkFirstTime(); // TEMPORARY, check this before doing any transform call.
+ // drawflags still global, for drawing call above
+ drawflags= manipulator_selectbuf(sa, 0.2f*(float)U.tw_hotspot);
+ if(drawflags==0) drawflags= val;
+
+ if (drawflags & MAN_TRANS_C) {
+ initManipulator(TFM_TRANSLATION);
+ switch(drawflags) {
+ case MAN_TRANS_C:
+ break;
+ case MAN_TRANS_X:
+ if(G.qual & LR_SHIFTKEY) {
+ drawflags= MAN_TRANS_Y|MAN_TRANS_Z;
+ BIF_setDualAxisConstraint(v3d->twmat[1], v3d->twmat[2], " Y+Z");
+ }
+ else
+ BIF_setSingleAxisConstraint(v3d->twmat[0], " X");
+ break;
+ case MAN_TRANS_Y:
+ if(G.qual & LR_SHIFTKEY) {
+ drawflags= MAN_TRANS_X|MAN_TRANS_Z;
+ BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[2], " X+Z");
+ }
+ else
+ BIF_setSingleAxisConstraint(v3d->twmat[1], " Y");
+ break;
+ case MAN_TRANS_Z:
+ if(G.qual & LR_SHIFTKEY) {
+ drawflags= MAN_TRANS_X|MAN_TRANS_Y;
+ BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[1], " X+Y");
+ }
+ else
+ BIF_setSingleAxisConstraint(v3d->twmat[2], " Z");
+ break;
+ }
+ ManipulatorTransform();
+ }
+ else if (drawflags & MAN_SCALE_C) {
+ initManipulator(TFM_RESIZE);
+ switch(drawflags) {
+ case MAN_SCALE_X:
+ if(G.qual & LR_SHIFTKEY) {
+ drawflags= MAN_SCALE_Y|MAN_SCALE_Z;
+ BIF_setDualAxisConstraint(v3d->twmat[1], v3d->twmat[2], " Y+Z");
+ }
+ else
+ BIF_setSingleAxisConstraint(v3d->twmat[0], " X");
+ break;
+ case MAN_SCALE_Y:
+ if(G.qual & LR_SHIFTKEY) {
+ drawflags= MAN_SCALE_X|MAN_SCALE_Z;
+ BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[2], " X+Z");
+ }
+ else
+ BIF_setSingleAxisConstraint(v3d->twmat[1], " Y");
+ break;
+ case MAN_SCALE_Z:
+ if(G.qual & LR_SHIFTKEY) {
+ drawflags= MAN_SCALE_X|MAN_SCALE_Y;
+ BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[1], " X+Y");
+ }
+ else
+ BIF_setSingleAxisConstraint(v3d->twmat[2], " Z");
+ break;
+ }
+ ManipulatorTransform();
+ }
+ else if (drawflags == MAN_ROT_T) { /* trackbal need special case, init is different */
+ initManipulator(TFM_TRACKBALL);
+ ManipulatorTransform();
+ }
+ else if (drawflags & MAN_ROT_C) {
+ initManipulator(TFM_ROTATION);
+ switch(drawflags) {
+ case MAN_ROT_X:
+ BIF_setSingleAxisConstraint(v3d->twmat[0], " X");
+ break;
+ case MAN_ROT_Y:
+ BIF_setSingleAxisConstraint(v3d->twmat[1], " Y");
+ break;
+ case MAN_ROT_Z:
+ BIF_setSingleAxisConstraint(v3d->twmat[2], " Z");
+ break;
+ }
+ ManipulatorTransform();
+ }
+ }
+ /* after transform, restore drawflags */
+ drawflags= 0xFFFF;
+
+ return val;
+}
+
+#endif
diff --git a/source/blender/editors/transform/transform_ndofinput.c b/source/blender/editors/transform/transform_ndofinput.c
new file mode 100644
index 00000000000..c52492ebd6b
--- /dev/null
+++ b/source/blender/editors/transform/transform_ndofinput.c
@@ -0,0 +1,155 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Martin Poirier
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+ #include <math.h> /* fabs */
+#include <stdio.h> /* for sprintf */
+
+#include "BKE_global.h" /* for G */
+#include "BKE_utildefines.h" /* ABS */
+
+#include "DNA_view3d_types.h" /* for G.vd (view3d) */
+
+#include "WM_types.h"
+
+#include "transform.h"
+
+static int updateNDofMotion(NDofInput *n); // return 0 when motion is null
+static void resetNDofInput(NDofInput *n);
+
+void initNDofInput(NDofInput *n)
+{
+ int i;
+
+ n->flag = 0;
+ n->axis = 0;
+
+ resetNDofInput(n);
+
+ for(i = 0; i < 3; i++)
+ {
+ n->factor[i] = 1.0f;
+ }
+}
+
+static void resetNDofInput(NDofInput *n)
+{
+ int i;
+ for(i = 0; i < 6; i++)
+ {
+ n->fval[i] = 0.0f;
+ }
+}
+
+
+int handleNDofInput(NDofInput *n, wmEvent *event)
+{
+ int retval = 0;
+ // TRANSFORM_FIX_ME
+#if 0
+ switch(event)
+ {
+ case NDOFMOTION:
+ if (updateNDofMotion(n) == 0)
+ {
+ retval = NDOF_NOMOVE;
+ }
+ else
+ {
+ retval = NDOF_REFRESH;
+ }
+ break;
+ case NDOFBUTTON:
+ if (val == 1)
+ {
+ retval = NDOF_CONFIRM;
+ }
+ else if (val == 2)
+ {
+ retval = NDOF_CANCEL;
+ resetNDofInput(n);
+ n->flag &= ~NDOF_INIT;
+ }
+ break;
+ }
+#endif
+ return retval;
+}
+
+int hasNDofInput(NDofInput *n)
+{
+ return (n->flag & NDOF_INIT) == NDOF_INIT;
+}
+
+void applyNDofInput(NDofInput *n, float *vec)
+{
+ if (hasNDofInput(n))
+ {
+ int i, j;
+
+ for (i = 0, j = 0; i < 6; i++)
+ {
+ if (n->axis & (1 << i))
+ {
+ vec[j] = n->fval[i] * n->factor[j];
+ j++;
+ }
+ }
+ }
+}
+
+
+static int updateNDofMotion(NDofInput *n)
+{
+ float fval[7];
+ int i;
+ int retval = 0;
+
+// TRANSFORM_FIX_ME
+#if 0
+ getndof(fval);
+
+ if (G.vd->ndoffilter)
+ filterNDOFvalues(fval);
+#endif
+
+ for(i = 0; i < 6; i++)
+ {
+ if (!retval && fval[i] != 0.0f)
+ {
+ retval = 1;
+ }
+
+ n->fval[i] += fval[i] / 1024.0f;
+ }
+
+ n->flag |= NDOF_INIT;
+
+ return retval;
+}
+
+
+
+
diff --git a/source/blender/editors/transform/transform_numinput.c b/source/blender/editors/transform/transform_numinput.c
new file mode 100644
index 00000000000..34976105db3
--- /dev/null
+++ b/source/blender/editors/transform/transform_numinput.c
@@ -0,0 +1,279 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h> /* fabs */
+#include <stdio.h> /* for sprintf */
+
+#include "BKE_global.h" /* for G */
+#include "BKE_utildefines.h" /* ABS */
+
+#include "WM_types.h"
+
+#include "transform.h"
+
+/* ************************** Functions *************************** */
+
+/* ************************** NUMINPUT **************************** */
+
+void initNumInput(NumInput *n)
+{
+ n->flag =
+ n->idx =
+ n->idx_max =
+ n->inv[0] =
+ n->inv[1] =
+ n->inv[2] =
+ n->ctrl[0] =
+ n->ctrl[1] =
+ n->ctrl[2] = 0;
+
+ n->val[0] =
+ n->val[1] =
+ n->val[2] = 0.0f;
+}
+
+void outputNumInput(NumInput *n, char *str)
+{
+ char cur;
+ char inv[] = "1/";
+ short i, j;
+
+ for (j=0; j<=n->idx_max; j++) {
+ /* if AFFECTALL and no number typed and cursor not on number, use first number */
+ if (n->flag & NUM_AFFECT_ALL && n->idx != j && n->ctrl[j] == 0)
+ i = 0;
+ else
+ i = j;
+
+ if (n->idx != i)
+ cur = ' ';
+ else
+ cur = '|';
+
+ if (n->inv[i])
+ inv[0] = '1';
+ else
+ inv[0] = 0;
+
+ if( n->val[i] > 1e10 || n->val[i] < -1e10 )
+ sprintf(&str[j*20], "%s%.4e%c", inv, n->val[i], cur);
+ else
+ switch (n->ctrl[i]) {
+ case 0:
+ sprintf(&str[j*20], "%sNONE%c", inv, cur);
+ break;
+ case 1:
+ case -1:
+ sprintf(&str[j*20], "%s%.0f%c", inv, n->val[i], cur);
+ break;
+ case 10:
+ case -10:
+ sprintf(&str[j*20], "%s%.f.%c", inv, n->val[i], cur);
+ break;
+ case 100:
+ case -100:
+ sprintf(&str[j*20], "%s%.1f%c", inv, n->val[i], cur);
+ break;
+ case 1000:
+ case -1000:
+ sprintf(&str[j*20], "%s%.2f%c", inv, n->val[i], cur);
+ break;
+ case 10000:
+ case -10000:
+ sprintf(&str[j*20], "%s%.3f%c", inv, n->val[i], cur);
+ break;
+ default:
+ sprintf(&str[j*20], "%s%.4e%c", inv, n->val[i], cur);
+ }
+ }
+}
+
+short hasNumInput(NumInput *n)
+{
+ short i;
+
+ for (i=0; i<=n->idx_max; i++) {
+ if (n->ctrl[i])
+ return 1;
+ }
+
+ return 0;
+}
+
+void applyNumInput(NumInput *n, float *vec)
+{
+ short i, j;
+
+ if (hasNumInput(n)) {
+ for (j=0; j<=n->idx_max; j++) {
+ /* if AFFECTALL and no number typed and cursor not on number, use first number */
+ if (n->flag & NUM_AFFECT_ALL && n->idx != j && n->ctrl[j] == 0)
+ i = 0;
+ else
+ i = j;
+
+ if (n->ctrl[i] == 0 && n->flag & NUM_NULL_ONE) {
+ vec[j] = 1.0f;
+ }
+ else if (n->val[i] == 0.0f && n->flag & NUM_NO_ZERO) {
+ vec[j] = 0.0001f;
+ }
+ else {
+ if (n->inv[i])
+ {
+ vec[j] = 1.0f / n->val[i];
+ }
+ else
+ {
+ vec[j] = n->val[i];
+ }
+ }
+ }
+ }
+}
+
+char handleNumInput(NumInput *n, wmEvent *event)
+{
+ float Val = 0;
+ short idx = n->idx, idx_max = n->idx_max;
+
+ switch (event->type) {
+ case BACKSPACEKEY:
+ if (n->ctrl[idx] == 0) {
+ n->val[0] =
+ n->val[1] =
+ n->val[2] = 0.0f;
+ n->ctrl[0] =
+ n->ctrl[1] =
+ n->ctrl[2] = 0;
+ n->inv[0] =
+ n->inv[1] =
+ n->inv[2] = 0;
+ }
+ else {
+ n->val[idx] = 0.0f;
+ n->ctrl[idx] = 0;
+ n->inv[idx] = 0;
+ }
+ break;
+ case PERIODKEY:
+ case PADPERIOD:
+ if (n->flag & NUM_NO_FRACTION)
+ break;
+
+ switch (n->ctrl[idx])
+ {
+ case 0:
+ case 1:
+ n->ctrl[idx] = 10;
+ break;
+ case -1:
+ n->ctrl[idx] = -10;
+ }
+ break;
+ case PADMINUS:
+ if(event->alt)
+ break;
+ case MINUSKEY:
+ if (n->flag & NUM_NO_NEGATIVE)
+ break;
+
+ if (n->ctrl[idx]) {
+ n->ctrl[idx] *= -1;
+ n->val[idx] *= -1;
+ }
+ else
+ n->ctrl[idx] = -1;
+ break;
+ case PADSLASHKEY:
+ case SLASHKEY:
+ n->inv[idx] = !n->inv[idx];
+ break;
+ case TABKEY:
+ idx++;
+ if (idx > idx_max)
+ idx = 0;
+ n->idx = idx;
+ break;
+ case PAD9:
+ case NINEKEY:
+ Val += 1.0f;
+ case PAD8:
+ case EIGHTKEY:
+ Val += 1.0f;
+ case PAD7:
+ case SEVENKEY:
+ Val += 1.0f;
+ case PAD6:
+ case SIXKEY:
+ Val += 1.0f;
+ case PAD5:
+ case FIVEKEY:
+ Val += 1.0f;
+ case PAD4:
+ case FOURKEY:
+ Val += 1.0f;
+ case PAD3:
+ case THREEKEY:
+ Val += 1.0f;
+ case PAD2:
+ case TWOKEY:
+ Val += 1.0f;
+ case PAD1:
+ case ONEKEY:
+ Val += 1.0f;
+ case PAD0:
+ case ZEROKEY:
+ if (!n->ctrl[idx])
+ n->ctrl[idx] = 1;
+
+ if (fabs(n->val[idx]) > 9999999.0f);
+ else if (n->ctrl[idx] == 1) {
+ n->val[idx] *= 10;
+ n->val[idx] += Val;
+ }
+ else if (n->ctrl[idx] == -1) {
+ n->val[idx] *= 10;
+ n->val[idx] -= Val;
+ }
+ else {
+ /* float resolution breaks when over six digits after comma */
+ if( ABS(n->ctrl[idx]) < 10000000) {
+ n->val[idx] += Val / (float)n->ctrl[idx];
+ n->ctrl[idx] *= 10;
+ }
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ /* REDRAW SINCE NUMBERS HAVE CHANGED */
+ return 1;
+}
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
new file mode 100644
index 00000000000..f5a581fc4fd
--- /dev/null
+++ b/source/blender/editors/transform/transform_ops.c
@@ -0,0 +1,642 @@
+/**
+ * $Id: transform_ops.c 17542 2008-11-23 15:27:53Z theeth $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "BLI_arithb.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_context.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+
+#include "ED_screen.h"
+
+#include "transform.h"
+
+typedef struct TransformModeItem
+{
+ char *idname;
+ int mode;
+} TransformModeItem;
+
+static float VecOne[3] = {1, 1, 1};
+
+/* need constants for this */
+EnumPropertyItem proportional_mode_types[] = {
+ {0, "OFF", "Off", ""},
+ {1, "ON", "On", ""},
+ {2, "CONNECTED", "Connected", ""},
+ {0, NULL, NULL, NULL}
+};
+
+EnumPropertyItem snap_mode_types[] = {
+ {SCE_SNAP_TARGET_CLOSEST, "CLOSEST", "Closest", ""},
+ {SCE_SNAP_TARGET_CENTER, "CENTER", "Center", ""},
+ {SCE_SNAP_TARGET_MEDIAN, "MEDIAN", "Median", ""},
+ {SCE_SNAP_TARGET_ACTIVE, "ACTIVE", "Active", ""},
+ {0, NULL, NULL, NULL}
+};
+
+EnumPropertyItem proportional_falloff_types[] = {
+ {PROP_SMOOTH, "SMOOTH", "Smooth", ""},
+ {PROP_SPHERE, "SPHERE", "Sphere", ""},
+ {PROP_ROOT, "ROOT", "Root", ""},
+ {PROP_SHARP, "SHARP", "Sharp", ""},
+ {PROP_LIN, "LINEAR", "Linear", ""},
+ {PROP_CONST, "CONSTANT", "Constant", ""},
+ {PROP_RANDOM, "RANDOM", "Random", ""},
+ {0, NULL, NULL, NULL}
+};
+
+char OP_TRANSLATION[] = "TFM_OT_translation";
+char OP_ROTATION[] = "TFM_OT_rotation";
+char OP_TOSPHERE[] = "TFM_OT_tosphere";
+char OP_RESIZE[] = "TFM_OT_resize";
+char OP_SHEAR[] = "TFM_OT_shear";
+char OP_WARP[] = "TFM_OT_warp";
+char OP_SHRINK_FATTEN[] = "TFM_OT_shrink_fatten";
+char OP_TILT[] = "TFM_OT_tilt";
+
+
+TransformModeItem transform_modes[] =
+{
+ {OP_TRANSLATION, TFM_TRANSLATION},
+ {OP_ROTATION, TFM_ROTATION},
+ {OP_TOSPHERE, TFM_TOSPHERE},
+ {OP_RESIZE, TFM_RESIZE},
+ {OP_SHEAR, TFM_SHEAR},
+ {OP_WARP, TFM_WARP},
+ {OP_SHRINK_FATTEN, TFM_SHRINKFATTEN},
+ {OP_TILT, TFM_TILT},
+ {NULL, 0}
+};
+
+static int select_orientation_exec(bContext *C, wmOperator *op)
+{
+ int orientation = RNA_enum_get(op->ptr, "orientation");
+ int custom_index= RNA_int_get(op->ptr, "custom_index");;
+
+ if(orientation == V3D_MANIP_CUSTOM)
+ orientation += custom_index;
+
+ BIF_selectTransformOrientationValue(C, orientation);
+
+ return OPERATOR_FINISHED;
+}
+
+static int select_orientation_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ uiMenuItem *head;
+
+ head= uiPupMenuBegin("Orientation", 0);
+ BIF_menuTransformOrientation(C, head, NULL);
+ uiPupMenuEnd(C, head);
+
+ return OPERATOR_CANCELLED;
+}
+
+void TFM_OT_select_orientation(struct wmOperatorType *ot)
+{
+ static EnumPropertyItem orientation_items[]= {
+ {V3D_MANIP_GLOBAL, "GLOBAL", "Global", ""},
+ {V3D_MANIP_NORMAL, "NORMAL", "Normal", ""},
+ {V3D_MANIP_LOCAL, "LOCAL", "Local", ""},
+ {V3D_MANIP_VIEW, "VIEW", "View", ""},
+ {V3D_MANIP_CUSTOM, "CUSTOM", "Custom", ""},
+ {0, NULL, NULL, NULL}};
+
+ /* identifiers */
+ ot->name = "Select Orientation";
+ ot->idname = "TFM_OT_select_orientation";
+
+ /* api callbacks */
+ ot->invoke = select_orientation_invoke;
+ ot->exec = select_orientation_exec;
+ ot->poll = ED_operator_areaactive;
+
+ RNA_def_enum(ot->srna, "orientation", orientation_items, V3D_MANIP_CUSTOM, "Orientation", "DOC_BROKEN");
+ RNA_def_int(ot->srna, "custom_index", 0, 0, INT_MAX, "Custom Index", "", 0, INT_MAX);
+}
+
+static void transformops_exit(bContext *C, wmOperator *op)
+{
+ saveTransform(C, op->customdata, op);
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+}
+
+static int transformops_data(bContext *C, wmOperator *op, wmEvent *event)
+{
+ int retval = 1;
+ if (op->customdata == NULL)
+ {
+ TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data");
+ TransformModeItem *tmode;
+ int mode = -1;
+
+ for (tmode = transform_modes; tmode->idname; tmode++)
+ {
+ if (op->type->idname == tmode->idname)
+ {
+ mode = tmode->mode;
+ }
+ }
+
+ if (mode == -1)
+ {
+ mode = RNA_int_get(op->ptr, "mode");
+ }
+
+ retval = initTransform(C, t, op, event, mode);
+
+ /* store data */
+ op->customdata = t;
+ }
+
+ return retval; /* return 0 on error */
+}
+
+static int transform_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ int exit_code;
+
+ TransInfo *t = op->customdata;
+
+ transformEvent(t, event);
+
+ transformApply(C, t);
+
+
+ exit_code = transformEnd(C, t);
+
+ if (exit_code != OPERATOR_RUNNING_MODAL)
+ {
+ transformops_exit(C, op);
+ }
+
+ return exit_code;
+}
+
+static int transform_cancel(bContext *C, wmOperator *op)
+{
+ TransInfo *t = op->customdata;
+
+ t->state = TRANS_CANCEL;
+ transformEnd(C, t);
+ transformops_exit(C, op);
+
+ return OPERATOR_CANCELLED;
+}
+
+static int transform_exec(bContext *C, wmOperator *op)
+{
+ TransInfo *t;
+
+ if (!transformops_data(C, op, NULL))
+ {
+ return OPERATOR_CANCELLED;
+ }
+
+ t = op->customdata;
+
+ t->options |= CTX_AUTOCONFIRM;
+
+ transformApply(C, t);
+
+ transformEnd(C, t);
+
+ transformops_exit(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+static int transform_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ if (!transformops_data(C, op, event))
+ {
+ return OPERATOR_CANCELLED;
+ }
+
+ if(RNA_property_is_set(op->ptr, "value")) {
+ return transform_exec(C, op);
+ }
+ else {
+ TransInfo *t = op->customdata;
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ t->flag |= T_MODAL; // XXX meh maybe somewhere else
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+}
+
+void Properties_Proportional(struct wmOperatorType *ot)
+{
+ RNA_def_enum(ot->srna, "proportional", proportional_mode_types, 0, "Proportional Editing", "");
+ RNA_def_enum(ot->srna, "proportional_editing_falloff", prop_mode_items, 0, "Proportional Editing Falloff", "Falloff type for proportional editing mode.");
+ RNA_def_float(ot->srna, "proportional_size", 1, 0, FLT_MAX, "Proportional Size", "", 0, 100);
+}
+
+void Properties_Snapping(struct wmOperatorType *ot, short align)
+{
+ RNA_def_boolean(ot->srna, "snap", 0, "Snap to Point", "");
+ RNA_def_enum(ot->srna, "snap_mode", snap_mode_types, 0, "Mode", "");
+ RNA_def_float_vector(ot->srna, "snap_point", 3, NULL, -FLT_MAX, FLT_MAX, "Point", "", -FLT_MAX, FLT_MAX);
+
+ if (align)
+ {
+ RNA_def_boolean(ot->srna, "snap_align", 0, "Align with Point Normal", "");
+ RNA_def_float_vector(ot->srna, "snap_normal", 3, NULL, -FLT_MAX, FLT_MAX, "Normal", "", -FLT_MAX, FLT_MAX);
+ }
+}
+
+void Properties_Constraints(struct wmOperatorType *ot)
+{
+ RNA_def_boolean_vector(ot->srna, "constraint_axis", 3, NULL, "Constraint Axis", "");
+ RNA_def_int(ot->srna, "constraint_orientation", 0, 0, INT_MAX, "Constraint Orientation", "", 0, INT_MAX);
+}
+
+void TFM_OT_translation(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Translation";
+ ot->idname = OP_TRANSLATION;
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_areaactive;
+
+ RNA_def_float_vector(ot->srna, "value", 3, NULL, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
+
+ Properties_Proportional(ot);
+
+ RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+
+ Properties_Constraints(ot);
+
+ Properties_Snapping(ot, 1);
+}
+
+void TFM_OT_resize(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Resize";
+ ot->idname = OP_RESIZE;
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_areaactive;
+
+ RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
+
+ Properties_Proportional(ot);
+
+ RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+
+ Properties_Constraints(ot);
+
+ Properties_Snapping(ot, 0);
+}
+
+void TFM_OT_rotation(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Rotation";
+ ot->idname = OP_ROTATION;
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_areaactive;
+
+ RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI*2, M_PI*2);
+
+ Properties_Proportional(ot);
+
+ RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+
+ Properties_Constraints(ot);
+
+ Properties_Snapping(ot, 0);
+}
+
+void TFM_OT_tilt(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Tilt";
+ ot->idname = OP_TILT;
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_editcurve;
+
+ RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI*2, M_PI*2);
+
+ Properties_Proportional(ot);
+
+ RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+
+ Properties_Constraints(ot);
+}
+
+void TFM_OT_warp(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Warp";
+ ot->idname = OP_WARP;
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_areaactive;
+
+ RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", 0, 1);
+
+ Properties_Proportional(ot);
+
+ RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+
+ // XXX Shear axis?
+// Properties_Constraints(ot);
+}
+
+void TFM_OT_shear(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Shear";
+ ot->idname = OP_SHEAR;
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_areaactive;
+
+ RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
+
+ Properties_Proportional(ot);
+
+ RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+
+ // XXX Shear axis?
+// Properties_Constraints(ot);
+}
+
+void TFM_OT_shrink_fatten(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Shrink/Fatten";
+ ot->idname = OP_SHRINK_FATTEN;
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_editmesh;
+
+ RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
+
+ Properties_Proportional(ot);
+
+ RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+}
+
+void TFM_OT_tosphere(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "To Sphere";
+ ot->idname = OP_TOSPHERE;
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_areaactive;
+
+ RNA_def_float_percentage(ot->srna, "value", 0, 0, 1, "Percentage", "", 0, 1);
+
+ Properties_Proportional(ot);
+
+ RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+}
+
+void TFM_OT_transform(struct wmOperatorType *ot)
+{
+ static EnumPropertyItem transform_mode_types[] = {
+ {TFM_INIT, "INIT", "Init", ""},
+ {TFM_DUMMY, "DUMMY", "Dummy", ""},
+ {TFM_TRANSLATION, "TRANSLATION", "Translation", ""},
+ {TFM_ROTATION, "ROTATION", "Rotation", ""},
+ {TFM_RESIZE, "RESIZE", "Resize", ""},
+ {TFM_TOSPHERE, "TOSPHERE", "Tosphere", ""},
+ {TFM_SHEAR, "SHEAR", "Shear", ""},
+ {TFM_WARP, "WARP", "Warp", ""},
+ {TFM_SHRINKFATTEN, "SHRINKFATTEN", "Shrinkfatten", ""},
+ {TFM_TILT, "TILT", "Tilt", ""},
+ {TFM_TRACKBALL, "TRACKBALL", "Trackball", ""},
+ {TFM_PUSHPULL, "PUSHPULL", "Pushpull", ""},
+ {TFM_CREASE, "CREASE", "Crease", ""},
+ {TFM_MIRROR, "MIRROR", "Mirror", ""},
+ {TFM_BONESIZE, "BONESIZE", "Bonesize", ""},
+ {TFM_BONE_ENVELOPE, "BONE_ENVELOPE", "Bone_Envelope", ""},
+ {TFM_CURVE_SHRINKFATTEN, "CURVE_SHRINKFATTEN", "Curve_Shrinkfatten", ""},
+ {TFM_BONE_ROLL, "BONE_ROLL", "Bone_Roll", ""},
+ {TFM_TIME_TRANSLATE, "TIME_TRANSLATE", "Time_Translate", ""},
+ {TFM_TIME_SLIDE, "TIME_SLIDE", "Time_Slide", ""},
+ {TFM_TIME_SCALE, "TIME_SCALE", "Time_Scale", ""},
+ {TFM_TIME_EXTEND, "TIME_EXTEND", "Time_Extend", ""},
+ {TFM_BAKE_TIME, "BAKE_TIME", "Bake_Time", ""},
+ {TFM_BEVEL, "BEVEL", "Bevel", ""},
+ {TFM_BWEIGHT, "BWEIGHT", "Bweight", ""},
+ {TFM_ALIGN, "ALIGN", "Align", ""},
+ {0, NULL, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Transform";
+ ot->idname = "TFM_OT_transform";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_areaactive;
+
+ RNA_def_enum(ot->srna, "mode", transform_mode_types, 0, "Mode", "");
+
+ RNA_def_float_vector(ot->srna, "value", 4, NULL, -FLT_MAX, FLT_MAX, "Values", "", -FLT_MAX, FLT_MAX);
+
+ Properties_Proportional(ot);
+ RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+
+ RNA_def_boolean_vector(ot->srna, "constraint_axis", 3, NULL, "Constraint Axis", "");
+ RNA_def_int(ot->srna, "constraint_orientation", 0, 0, INT_MAX, "Constraint Orientation", "", 0, INT_MAX);
+}
+
+void transform_operatortypes(void)
+{
+ WM_operatortype_append(TFM_OT_transform);
+ WM_operatortype_append(TFM_OT_translation);
+ WM_operatortype_append(TFM_OT_rotation);
+ WM_operatortype_append(TFM_OT_tosphere);
+ WM_operatortype_append(TFM_OT_resize);
+ WM_operatortype_append(TFM_OT_shear);
+ WM_operatortype_append(TFM_OT_warp);
+ WM_operatortype_append(TFM_OT_shrink_fatten);
+ WM_operatortype_append(TFM_OT_tilt);
+
+ WM_operatortype_append(TFM_OT_select_orientation);
+}
+
+void transform_keymap_for_space(struct wmWindowManager *wm, struct ListBase *keymap, int spaceid)
+{
+ wmKeymapItem *km;
+ switch(spaceid)
+ {
+ case SPACE_VIEW3D:
+ km = WM_keymap_add_item(keymap, "TFM_OT_translation", GKEY, KM_PRESS, 0, 0);
+
+ km= WM_keymap_add_item(keymap, "TFM_OT_translation", EVT_TWEAK_S, KM_ANY, 0, 0);
+
+ km = WM_keymap_add_item(keymap, "TFM_OT_rotation", RKEY, KM_PRESS, 0, 0);
+
+ km = WM_keymap_add_item(keymap, "TFM_OT_resize", SKEY, KM_PRESS, 0, 0);
+
+ km = WM_keymap_add_item(keymap, "TFM_OT_warp", WKEY, KM_PRESS, KM_SHIFT, 0);
+
+ km = WM_keymap_add_item(keymap, "TFM_OT_tosphere", SKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
+
+ km = WM_keymap_add_item(keymap, "TFM_OT_shear", SKEY, KM_PRESS, KM_ALT|KM_CTRL|KM_SHIFT, 0);
+
+ km = WM_keymap_add_item(keymap, "TFM_OT_shrink_fatten", SKEY, KM_PRESS, KM_ALT, 0);
+
+ km = WM_keymap_add_item(keymap, "TFM_OT_tilt", TKEY, KM_PRESS, 0, 0);
+
+ km = WM_keymap_add_item(keymap, "TFM_OT_select_orientation", SPACEKEY, KM_PRESS, KM_ALT, 0);
+
+ break;
+ case SPACE_ACTION:
+ km= WM_keymap_add_item(keymap, "TFM_OT_transform", GKEY, KM_PRESS, 0, 0);
+ RNA_int_set(km->ptr, "mode", TFM_TIME_TRANSLATE);
+
+ km= WM_keymap_add_item(keymap, "TFM_OT_transform", EVT_TWEAK_S, KM_ANY, 0, 0);
+ RNA_int_set(km->ptr, "mode", TFM_TIME_TRANSLATE);
+
+ km= WM_keymap_add_item(keymap, "TFM_OT_transform", EKEY, KM_PRESS, 0, 0);
+ RNA_int_set(km->ptr, "mode", TFM_TIME_EXTEND);
+
+ km= WM_keymap_add_item(keymap, "TFM_OT_transform", SKEY, KM_PRESS, 0, 0);
+ RNA_int_set(km->ptr, "mode", TFM_TIME_SCALE);
+
+ km= WM_keymap_add_item(keymap, "TFM_OT_transform", TKEY, KM_PRESS, 0, 0);
+ RNA_int_set(km->ptr, "mode", TFM_TIME_SLIDE);
+ break;
+ case SPACE_IPO:
+ km= WM_keymap_add_item(keymap, "TFM_OT_translation", GKEY, KM_PRESS, 0, 0);
+
+ km= WM_keymap_add_item(keymap, "TFM_OT_translation", EVT_TWEAK_S, KM_ANY, 0, 0);
+
+ // XXX the 'mode' identifier here is not quite right
+ km= WM_keymap_add_item(keymap, "TFM_OT_transform", EKEY, KM_PRESS, 0, 0);
+ RNA_int_set(km->ptr, "mode", TFM_TIME_EXTEND);
+
+ km = WM_keymap_add_item(keymap, "TFM_OT_rotation", RKEY, KM_PRESS, 0, 0);
+
+ km = WM_keymap_add_item(keymap, "TFM_OT_resize", SKEY, KM_PRESS, 0, 0);
+ break;
+ case SPACE_NODE:
+ km= WM_keymap_add_item(keymap, "TFM_OT_translation", GKEY, KM_PRESS, 0, 0);
+
+ km= WM_keymap_add_item(keymap, "TFM_OT_translation", EVT_TWEAK_A, KM_ANY, 0, 0);
+ km= WM_keymap_add_item(keymap, "TFM_OT_translation", EVT_TWEAK_S, KM_ANY, 0, 0);
+
+ km = WM_keymap_add_item(keymap, "TFM_OT_rotation", RKEY, KM_PRESS, 0, 0);
+
+ km = WM_keymap_add_item(keymap, "TFM_OT_resize", SKEY, KM_PRESS, 0, 0);
+ break;
+ case SPACE_SEQ:
+ km= WM_keymap_add_item(keymap, "TFM_OT_translation", GKEY, KM_PRESS, 0, 0);
+
+ km= WM_keymap_add_item(keymap, "TFM_OT_translation", EVT_TWEAK_S, KM_ANY, 0, 0);
+
+ km= WM_keymap_add_item(keymap, "TFM_OT_transform", EKEY, KM_PRESS, 0, 0);
+ RNA_int_set(km->ptr, "mode", TFM_TIME_EXTEND);
+ break;
+ case SPACE_IMAGE:
+ km = WM_keymap_add_item(keymap, "TFM_OT_translation", GKEY, KM_PRESS, 0, 0);
+
+ km= WM_keymap_add_item(keymap, "TFM_OT_translation", EVT_TWEAK_S, KM_ANY, 0, 0);
+
+ km = WM_keymap_add_item(keymap, "TFM_OT_rotation", RKEY, KM_PRESS, 0, 0);
+
+ km = WM_keymap_add_item(keymap, "TFM_OT_resize", SKEY, KM_PRESS, 0, 0);
+
+ km = WM_keymap_add_item(keymap, "TFM_OT_transform", MKEY, KM_PRESS, 0, 0);
+ RNA_int_set(km->ptr, "mode", TFM_MIRROR);
+ break;
+ default:
+ break;
+ }
+}
+
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
new file mode 100644
index 00000000000..df785f92166
--- /dev/null
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -0,0 +1,891 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Martin Poirier
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_action_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_listBase.h"
+#include "DNA_object_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+#include "BKE_armature.h"
+#include "BKE_context.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
+//#include "BIF_editmesh.h"
+//#include "BIF_interface.h"
+//#include "BIF_space.h"
+//#include "BIF_toolbox.h"
+
+#include "ED_armature.h"
+#include "ED_mesh.h"
+#include "ED_util.h"
+
+#include "UI_interface.h"
+
+#include "transform.h"
+
+/* *********************** TransSpace ************************** */
+
+void BIF_clearTransformOrientation(bContext *C)
+{
+ ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
+ BLI_freelistN(transform_spaces);
+
+ // TRANSFORM_FIX_ME
+ // Need to loop over all view3d
+// if (G.vd->twmode >= V3D_MANIP_CUSTOM)
+// G.vd->twmode = V3D_MANIP_GLOBAL; /* fallback to global */
+}
+
+void BIF_manageTransformOrientation(bContext *C, int confirm, int set) {
+ Object *obedit = CTX_data_edit_object(C);
+ Object *ob = CTX_data_active_object(C);
+ int index = -1;
+
+ if (obedit) {
+ if (obedit->type == OB_MESH)
+ index = manageMeshSpace(C, confirm, set);
+ else if (obedit->type == OB_ARMATURE)
+ index = manageBoneSpace(C, confirm, set);
+ }
+ else if (ob && (ob->flag & OB_POSEMODE)) {
+ index = manageBoneSpace(C, confirm, set);
+ }
+ else {
+ index = manageObjectSpace(C, confirm, set);
+ }
+
+ if (set && index != -1)
+ {
+ BIF_selectTransformOrientationValue(C, V3D_MANIP_CUSTOM + index);
+ }
+}
+
+int manageObjectSpace(bContext *C, int confirm, int set) {
+ Base *base = CTX_data_active_base(C);
+
+ if (base == NULL)
+ return -1;
+
+//XXX if (confirm == 0) {
+// if (set && pupmenu("Custom Orientation %t|Add and Use Active Object%x1") != 1) {
+// return -1;
+// }
+// else if (set == 0 && pupmenu("Custom Orientation %t|Add Active Object%x1") != 1) {
+// return -1;
+// }
+// }
+
+ return addObjectSpace(C, base->object);
+}
+
+/* return 1 on confirm */
+int confirmSpace(int set, char text[])
+{
+ char menu[64];
+
+ if (set) {
+ sprintf(menu, "Custom Orientation %%t|Add and Use %s%%x1", text);
+ }
+ else {
+ sprintf(menu, "Custom Orientation %%t|Add %s%%x1", text);
+ }
+
+//XXX if (pupmenu(menu) == 1) {
+ return 1;
+// }
+// else {
+// return 0;
+// }
+}
+
+int manageBoneSpace(bContext *C, int confirm, int set) {
+ float mat[3][3];
+ float normal[3], plane[3];
+ char name[36] = "";
+ int index;
+
+ getTransformOrientation(C, normal, plane, 0);
+
+ if (confirm == 0 && confirmSpace(set, "Bone") == 0) {
+ return -1;
+ }
+
+ if (createSpaceNormalTangent(mat, normal, plane) == 0) {
+//XXX error("Cannot use zero-length bone");
+ return -1;
+ }
+
+ strcpy(name, "Bone");
+
+ /* Input name */
+//XXX sbutton(name, 1, 35, "name: ");
+
+ index = addMatrixSpace(C, mat, name);
+ return index;
+}
+
+int manageMeshSpace(bContext *C, int confirm, int set) {
+ float mat[3][3];
+ float normal[3], plane[3];
+ char name[36] = "";
+ int index;
+ int type;
+
+ type = getTransformOrientation(C, normal, plane, 0);
+
+ switch (type)
+ {
+ case ORIENTATION_VERT:
+ if (confirm == 0 && confirmSpace(set, "vertex") == 0) {
+ return -1;
+ }
+
+ if (createSpaceNormal(mat, normal) == 0) {
+// XXX error("Cannot use vertex with zero-length normal");
+ return -1;
+ }
+
+ strcpy(name, "Vertex");
+ break;
+ case ORIENTATION_EDGE:
+ if (confirm == 0 && confirmSpace(set, "Edge") == 0) {
+ return -1;
+ }
+
+ if (createSpaceNormalTangent(mat, normal, plane) == 0) {
+// XXX error("Cannot use zero-length edge");
+ return -1;
+ }
+
+ strcpy(name, "Edge");
+ break;
+ case ORIENTATION_FACE:
+ if (confirm == 0 && confirmSpace(set, "Face") == 0) {
+ return -1;
+ }
+
+ if (createSpaceNormalTangent(mat, normal, plane) == 0) {
+// XXX error("Cannot use zero-area face");
+ return -1;
+ }
+
+ strcpy(name, "Face");
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ /* Input name */
+//XXX sbutton(name, 1, 35, "name: ");
+
+ index = addMatrixSpace(C, mat, name);
+ return index;
+}
+
+int createSpaceNormal(float mat[3][3], float normal[3])
+{
+ float tangent[3] = {0.0f, 0.0f, 1.0f};
+
+ VECCOPY(mat[2], normal);
+ if (Normalize(mat[2]) == 0.0f) {
+ return 0; /* error return */
+ }
+
+ Crossf(mat[0], mat[2], tangent);
+ if (Inpf(mat[0], mat[0]) == 0.0f) {
+ tangent[0] = 1.0f;
+ tangent[1] = tangent[2] = 0.0f;
+ Crossf(mat[0], tangent, mat[2]);
+ }
+
+ Crossf(mat[1], mat[2], mat[0]);
+
+ Mat3Ortho(mat);
+
+ return 1;
+}
+
+int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3])
+{
+ VECCOPY(mat[2], normal);
+ if (Normalize(mat[2]) == 0.0f) {
+ return 0; /* error return */
+ }
+
+ /* preempt zero length tangent from causing trouble */
+ if (tangent[0] == 0 && tangent[1] == 0 && tangent[2] == 0)
+ {
+ tangent[2] = 1;
+ }
+
+ Crossf(mat[0], mat[2], tangent);
+ if (Normalize(mat[0]) == 0.0f) {
+ return 0; /* error return */
+ }
+
+ Crossf(mat[1], mat[2], mat[0]);
+
+ Mat3Ortho(mat);
+
+ return 1;
+}
+
+
+int addObjectSpace(bContext *C, Object *ob) {
+ float mat[3][3];
+ char name[36] = "";
+
+ Mat3CpyMat4(mat, ob->obmat);
+ Mat3Ortho(mat);
+
+ strncpy(name, ob->id.name+2, 35);
+
+ /* Input name */
+//XXX sbutton(name, 1, 35, "name: ");
+
+ return addMatrixSpace(C, mat, name);
+}
+
+int addMatrixSpace(bContext *C, float mat[3][3], char name[]) {
+ ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
+ TransformOrientation *ts;
+ int index = 0;
+
+ /* if name is found in list, reuse that transform space */
+ for (index = 0, ts = transform_spaces->first; ts; ts = ts->next, index++) {
+ if (strncmp(ts->name, name, 35) == 0) {
+ break;
+ }
+ }
+
+ /* if not, create a new one */
+ if (ts == NULL)
+ {
+ ts = MEM_callocN(sizeof(TransformOrientation), "UserTransSpace from matrix");
+ BLI_addtail(transform_spaces, ts);
+ strncpy(ts->name, name, 35);
+ }
+
+ /* copy matrix into transform space */
+ Mat3CpyMat3(ts->mat, mat);
+
+ ED_undo_push(C, "Add/Update Transform Orientation");
+
+ return index;
+}
+
+void BIF_removeTransformOrientation(bContext *C, TransformOrientation *target) {
+ ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
+ TransformOrientation *ts = transform_spaces->first;
+ //int selected_index = (G.vd->twmode - V3D_MANIP_CUSTOM);
+ int i;
+
+ for (i = 0, ts = transform_spaces->first; ts; ts = ts->next, i++) {
+ if (ts == target) {
+ // Transform_fix_me NEED TO DO THIS FOR ALL VIEW3D
+// if (selected_index == i) {
+// G.vd->twmode = V3D_MANIP_GLOBAL; /* fallback to global */
+// }
+// else if (selected_index > i)
+// G.vd->twmode--;
+
+ BLI_freelinkN(transform_spaces, ts);
+ break;
+ }
+ }
+ ED_undo_push(C, "Remove Transform Orientation");
+}
+
+void BIF_selectTransformOrientation(bContext *C, TransformOrientation *target) {
+ ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
+ View3D *v3d = CTX_wm_view3d(C);
+ TransformOrientation *ts = transform_spaces->first;
+ int i;
+
+ for (i = 0, ts = transform_spaces->first; ts; ts = ts->next, i++) {
+ if (ts == target) {
+ v3d->twmode = V3D_MANIP_CUSTOM + i;
+ break;
+ }
+ }
+}
+
+void BIF_selectTransformOrientationValue(bContext *C, int orientation) {
+ View3D *v3d = CTX_wm_view3d(C);
+ v3d->twmode = orientation;
+}
+
+void BIF_menuTransformOrientation(bContext *C, uiMenuItem *head, void *arg)
+{
+ ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
+ TransformOrientation *ts;
+ int i= V3D_MANIP_CUSTOM;
+
+ uiMenuItemEnumO(head, "", 0, "TFM_OT_select_orientation", "orientation", V3D_MANIP_GLOBAL);
+ uiMenuItemEnumO(head, "", 0, "TFM_OT_select_orientation", "orientation", V3D_MANIP_LOCAL);
+ uiMenuItemEnumO(head, "", 0, "TFM_OT_select_orientation", "orientation", V3D_MANIP_NORMAL);
+ uiMenuItemEnumO(head, "", 0, "TFM_OT_select_orientation", "orientation", V3D_MANIP_VIEW);
+
+ for(ts = transform_spaces->first; ts; ts = ts->next)
+ uiMenuItemIntO(head, ts->name, 0, "TFM_OT_select_orientation", "custom_index", i++);
+}
+
+char * BIF_menustringTransformOrientation(const bContext *C, char *title) {
+ char menu[] = "%t|Global%x0|Local%x1|Normal%x2|View%x3";
+ ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
+ TransformOrientation *ts;
+ int i = V3D_MANIP_CUSTOM;
+ char *str_menu, *p;
+
+
+ str_menu = MEM_callocN(strlen(menu) + strlen(title) + 1 + 40 * BIF_countTransformOrientation(C), "UserTransSpace from matrix");
+ p = str_menu;
+
+ p += sprintf(str_menu, "%s", title);
+ p += sprintf(p, "%s", menu);
+
+ for (ts = transform_spaces->first; ts; ts = ts->next) {
+ p += sprintf(p, "|%s%%x%d", ts->name, i++);
+ }
+
+ return str_menu;
+}
+
+int BIF_countTransformOrientation(const bContext *C) {
+ ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
+ TransformOrientation *ts;
+ int count = 0;
+
+ for (ts = transform_spaces->first; ts; ts = ts->next) {
+ count++;
+ }
+
+ return count;
+}
+
+void applyTransformOrientation(bContext *C, TransInfo *t) {
+ TransformOrientation *ts;
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM);
+ int i;
+
+ if (selected_index >= 0) {
+ for (i = 0, ts = CTX_data_scene(C)->transform_spaces.first; ts; ts = ts->next, i++) {
+ if (selected_index == i) {
+ strcpy(t->spacename, ts->name);
+ Mat3CpyMat3(t->spacemtx, ts->mat);
+ Mat4CpyMat3(rv3d->twmat, ts->mat);
+ break;
+ }
+ }
+ }
+}
+
+static int count_bone_select(bArmature *arm, ListBase *lb, int do_it)
+{
+ Bone *bone;
+ int do_next;
+ int total = 0;
+
+ for(bone= lb->first; bone; bone= bone->next) {
+ bone->flag &= ~BONE_TRANSFORM;
+ do_next = do_it;
+ if(do_it) {
+ if(bone->layer & arm->layer) {
+ if (bone->flag & BONE_SELECTED) {
+ bone->flag |= BONE_TRANSFORM;
+ total++;
+ do_next= 0; // no transform on children if one parent bone is selected
+ }
+ }
+ }
+ total += count_bone_select(arm, &bone->childbase, do_next);
+ }
+
+ return total;
+}
+
+void initTransformOrientation(bContext *C, TransInfo *t)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ Object *ob = CTX_data_active_object(C);
+ Object *obedit = CTX_data_active_object(C);
+ float normal[3]={0.0, 0.0, 0.0};
+ float plane[3]={0.0, 0.0, 0.0};
+
+ if(t->spacetype != SPACE_VIEW3D) return;
+
+ switch(t->current_orientation) {
+ case V3D_MANIP_GLOBAL:
+ strcpy(t->spacename, "global");
+ break;
+
+ case V3D_MANIP_NORMAL:
+ if(obedit || ob->flag & OB_POSEMODE) {
+ float mat[3][3];
+ int type;
+
+ strcpy(t->spacename, "normal");
+
+ type = getTransformOrientation(C, normal, plane, (v3d->around == V3D_ACTIVE));
+
+ switch (type)
+ {
+ case ORIENTATION_NORMAL:
+ if (createSpaceNormalTangent(mat, normal, plane) == 0)
+ {
+ type = ORIENTATION_NONE;
+ }
+ break;
+ case ORIENTATION_VERT:
+ if (createSpaceNormal(mat, normal) == 0)
+ {
+ type = ORIENTATION_NONE;
+ }
+ break;
+ case ORIENTATION_EDGE:
+ if (createSpaceNormalTangent(mat, normal, plane) == 0)
+ {
+ type = ORIENTATION_NONE;
+ }
+ break;
+ case ORIENTATION_FACE:
+ if (createSpaceNormalTangent(mat, normal, plane) == 0)
+ {
+ type = ORIENTATION_NONE;
+ }
+ break;
+ }
+
+ if (type == ORIENTATION_NONE)
+ {
+ Mat4One(rv3d->twmat);
+ }
+ else
+ {
+ Mat4CpyMat3(rv3d->twmat, mat);
+ }
+ break;
+ }
+ /* no break we define 'normal' as 'local' in Object mode */
+ case V3D_MANIP_LOCAL:
+ strcpy(t->spacename, "local");
+ Mat4CpyMat4(rv3d->twmat, ob->obmat);
+ Mat4Ortho(rv3d->twmat);
+ break;
+
+ case V3D_MANIP_VIEW:
+ {
+ float mat[3][3];
+ strcpy(t->spacename, "view");
+ Mat3CpyMat4(mat, rv3d->viewinv);
+ Mat3Ortho(mat);
+ Mat4CpyMat3(rv3d->twmat, mat);
+ }
+ break;
+ default: /* V3D_MANIP_CUSTOM */
+ applyTransformOrientation(C, t);
+ break;
+ }
+}
+
+int getTransformOrientation(bContext *C, float normal[3], float plane[3], int activeOnly)
+{
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Base *base;
+ Object *ob = OBACT;
+ int result = ORIENTATION_NONE;
+
+ normal[0] = normal[1] = normal[2] = 0;
+ plane[0] = plane[1] = plane[2] = 0;
+
+ if(obedit)
+ {
+ float imat[3][3], mat[3][3];
+
+ /* we need the transpose of the inverse for a normal... */
+ Mat3CpyMat4(imat, ob->obmat);
+
+ Mat3Inv(mat, imat);
+ Mat3Transp(mat);
+
+ ob= obedit;
+
+ if(ob->type==OB_MESH)
+ {
+ Mesh *me= ob->data;
+ EditMesh *em = me->edit_mesh;
+ EditVert *eve;
+ EditSelection ese;
+ float vec[3]= {0,0,0};
+
+ /* USE LAST SELECTED WITH ACTIVE */
+ if (activeOnly && EM_get_actSelection(em, &ese))
+ {
+ EM_editselection_normal(normal, &ese);
+ EM_editselection_plane(plane, &ese);
+
+ switch (ese.type)
+ {
+ case EDITVERT:
+ result = ORIENTATION_VERT;
+ break;
+ case EDITEDGE:
+ result = ORIENTATION_EDGE;
+ break;
+ case EDITFACE:
+ result = ORIENTATION_FACE;
+ break;
+ }
+ }
+ else
+ {
+ if (em->totfacesel >= 1)
+ {
+ EditFace *efa;
+
+ for(efa= em->faces.first; efa; efa= efa->next)
+ {
+ if(efa->f & SELECT)
+ {
+ VECADD(normal, normal, efa->n);
+ VecSubf(vec, efa->v2->co, efa->v1->co);
+ VECADD(plane, plane, vec);
+ }
+ }
+
+ result = ORIENTATION_FACE;
+ }
+ else if (em->totvertsel == 3)
+ {
+ EditVert *v1 = NULL, *v2 = NULL, *v3 = NULL;
+ float cotangent[3];
+
+ for (eve = em->verts.first; eve; eve = eve->next)
+ {
+ if ( eve->f & SELECT ) {
+ if (v1 == NULL) {
+ v1 = eve;
+ }
+ else if (v2 == NULL) {
+ v2 = eve;
+ }
+ else {
+ v3 = eve;
+
+ VecSubf(plane, v2->co, v1->co);
+ VecSubf(cotangent, v3->co, v2->co);
+ Crossf(normal, cotangent, plane);
+ break;
+ }
+ }
+ }
+
+ /* if there's an edge available, use that for the tangent */
+ if (em->totedgesel >= 1)
+ {
+ EditEdge *eed = NULL;
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f & SELECT) {
+ VecSubf(plane, eed->v2->co, eed->v1->co);
+ break;
+ }
+ }
+ }
+
+ result = ORIENTATION_FACE;
+ }
+ else if (em->totedgesel == 1)
+ {
+ EditEdge *eed;
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f & SELECT) {
+ /* use average vert normals as plane and edge vector as normal */
+ VECCOPY(plane, eed->v1->no);
+ VECADD(plane, plane, eed->v2->no);
+ VecSubf(normal, eed->v2->co, eed->v1->co);
+ break;
+ }
+ }
+ result = ORIENTATION_EDGE;
+ }
+ else if (em->totvertsel == 2)
+ {
+ EditVert *v1 = NULL, *v2 = NULL;
+
+ for (eve = em->verts.first; eve; eve = eve->next)
+ {
+ if ( eve->f & SELECT ) {
+ if (v1 == NULL) {
+ v1 = eve;
+ }
+ else {
+ v2 = eve;
+
+ VECCOPY(plane, v1->no);
+ VECADD(plane, plane, v2->no);
+ VecSubf(normal, v2->co, v1->co);
+ break;
+ }
+ }
+ }
+ result = ORIENTATION_EDGE;
+ }
+ else if (em->totvertsel == 1)
+ {
+ for (eve = em->verts.first; eve; eve = eve->next)
+ {
+ if ( eve->f & SELECT ) {
+ VECCOPY(normal, eve->no);
+ break;
+ }
+ }
+ result = ORIENTATION_VERT;
+ }
+ else if (em->totvertsel > 3)
+ {
+ normal[0] = normal[1] = normal[2] = 0;
+
+ for (eve = em->verts.first; eve; eve = eve->next)
+ {
+ if ( eve->f & SELECT ) {
+ VecAddf(normal, normal, eve->no);
+ }
+ }
+ Normalize(normal);
+ result = ORIENTATION_VERT;
+ }
+ }
+ } /* end editmesh */
+ else if ELEM(obedit->type, OB_CURVE, OB_SURF)
+ {
+ Curve *cu= obedit->data;
+ Nurb *nu;
+ BezTriple *bezt;
+ int a;
+
+ for (nu = cu->editnurb->first; nu; nu = nu->next)
+ {
+ /* only bezier has a normal */
+ if((nu->type & 7) == CU_BEZIER)
+ {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--)
+ {
+ /* exception */
+ if ( (bezt->f1 & SELECT) + (bezt->f2 & SELECT) + (bezt->f3 & SELECT) > SELECT )
+ {
+ VecSubf(normal, bezt->vec[0], bezt->vec[2]);
+ }
+ else
+ {
+ if(bezt->f1)
+ {
+ VecSubf(normal, bezt->vec[0], bezt->vec[1]);
+ }
+ if(bezt->f2)
+ {
+ VecSubf(normal, bezt->vec[0], bezt->vec[2]);
+ }
+ if(bezt->f3)
+ {
+ VecSubf(normal, bezt->vec[1], bezt->vec[2]);
+ }
+ }
+ bezt++;
+ }
+ }
+ }
+
+ if (normal[0] != 0 || normal[1] != 0 || normal[2] != 0)
+ {
+ result = ORIENTATION_NORMAL;
+ }
+ }
+ else if(obedit->type==OB_MBALL)
+ {
+#if 0 // XXX
+ /* editmball.c */
+ extern ListBase editelems; /* go away ! */
+ MetaElem *ml, *ml_sel = NULL;
+
+ /* loop and check that only one element is selected */
+ for (ml = editelems.first; ml; ml = ml->next)
+ {
+ if (ml->flag & SELECT) {
+ if (ml_sel == NULL)
+ {
+ ml_sel = ml;
+ }
+ else
+ {
+ ml_sel = NULL;
+ break;
+ }
+ }
+ }
+
+ if (ml_sel)
+ {
+ float mat[4][4];
+
+ /* Rotation of MetaElem is stored in quat */
+ QuatToMat4(ml_sel->quat, mat);
+
+ VECCOPY(normal, mat[2]);
+ VECCOPY(plane, mat[1]);
+
+ VecMulf(plane, -1.0);
+
+ result = ORIENTATION_NORMAL;
+ }
+#endif
+
+ }
+ else if (obedit->type == OB_ARMATURE)
+ {
+ bArmature *arm = obedit->data;
+ EditBone *ebone;
+
+ for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
+ if (arm->layer & ebone->layer)
+ {
+ if (ebone->flag & BONE_SELECTED)
+ {
+ float mat[3][3];
+ float vec[3];
+ VecSubf(vec, ebone->tail, ebone->head);
+ Normalize(vec);
+ VecAddf(normal, normal, vec);
+
+ vec_roll_to_mat3(vec, ebone->roll, mat);
+ VecAddf(plane, plane, mat[2]);
+ }
+ }
+ }
+
+ Normalize(normal);
+ Normalize(plane);
+
+ if (plane[0] != 0 || plane[1] != 0 || plane[2] != 0)
+ {
+ result = ORIENTATION_EDGE;
+ }
+
+ }
+
+ /* Vectors from edges don't need the special transpose inverse multiplication */
+ if (result == ORIENTATION_EDGE)
+ {
+ Mat4Mul3Vecfl(ob->obmat, normal);
+ Mat4Mul3Vecfl(ob->obmat, plane);
+ }
+ else
+ {
+ Mat3MulVecfl(mat, normal);
+ Mat3MulVecfl(mat, plane);
+ }
+ }
+ else if(ob && (ob->flag & OB_POSEMODE))
+ {
+ bArmature *arm= ob->data;
+ bPoseChannel *pchan;
+ int totsel;
+
+ totsel = count_bone_select(arm, &arm->bonebase, 1);
+ if(totsel) {
+ float imat[3][3], mat[3][3];
+
+ /* use channels to get stats */
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) {
+ VecAddf(normal, normal, pchan->pose_mat[2]);
+ VecAddf(plane, plane, pchan->pose_mat[1]);
+ }
+ }
+ VecMulf(plane, -1.0);
+
+ /* we need the transpose of the inverse for a normal... */
+ Mat3CpyMat4(imat, ob->obmat);
+
+ Mat3Inv(mat, imat);
+ Mat3Transp(mat);
+ Mat3MulVecfl(mat, normal);
+ Mat3MulVecfl(mat, plane);
+
+ result = ORIENTATION_EDGE;
+ }
+ }
+ else if(G.f & (G_VERTEXPAINT + G_TEXTUREPAINT + G_WEIGHTPAINT + G_SCULPTMODE))
+ {
+ }
+ else if(G.f & G_PARTICLEEDIT)
+ {
+ }
+ else {
+ /* we need the one selected object, if its not active */
+ ob = OBACT;
+ if(ob && !(ob->flag & SELECT)) ob = NULL;
+
+ for(base= scene->base.first; base; base= base->next) {
+ if TESTBASELIB(v3d, base) {
+ if(ob == NULL) {
+ ob= base->object;
+ break;
+ }
+ }
+ }
+
+ VECCOPY(normal, ob->obmat[2]);
+ VECCOPY(plane, ob->obmat[1]);
+ result = ORIENTATION_NORMAL;
+ }
+
+ return result;
+}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
new file mode 100644
index 00000000000..72901110388
--- /dev/null
+++ b/source/blender/editors/transform/transform_snap.c
@@ -0,0 +1,1755 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Martin Poirier
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <float.h>
+#include <stdio.h>
+
+#include "PIL_time.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_meshdata_types.h" // Temporary, for snapping to other unselected meshes
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_access.h"
+
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_blenlib.h"
+
+//#include "BDR_drawobject.h"
+//
+//#include "editmesh.h"
+//#include "BIF_editsima.h"
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+//#include "BIF_mywindow.h"
+//#include "BIF_screen.h"
+//#include "BIF_editsima.h"
+//#include "BIF_drawimage.h"
+//#include "BIF_editmesh.h"
+
+#include "BIF_transform.h"
+
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_object.h"
+#include "BKE_anim.h" /* for duplis */
+#include "BKE_context.h"
+
+#include "ED_armature.h"
+#include "ED_image.h"
+#include "ED_mesh.h"
+#include "ED_uvedit.h"
+#include "ED_view3d.h"
+
+#include "WM_types.h"
+
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "transform.h"
+
+//#include "blendef.h" /* for selection modes */
+
+/********************* PROTOTYPES ***********************/
+
+void setSnappingCallback(TransInfo *t, short snap_target);
+
+void ApplySnapTranslation(TransInfo *t, float vec[3]);
+void ApplySnapRotation(TransInfo *t, float *vec);
+void ApplySnapResize(TransInfo *t, float *vec);
+
+void CalcSnapGrid(TransInfo *t, float *vec);
+void CalcSnapGeometry(TransInfo *t, float *vec);
+
+void TargetSnapMedian(TransInfo *t);
+void TargetSnapCenter(TransInfo *t);
+void TargetSnapClosest(TransInfo *t);
+void TargetSnapActive(TransInfo *t);
+
+float RotationBetween(TransInfo *t, float p1[3], float p2[3]);
+float TranslationBetween(TransInfo *t, float p1[3], float p2[3]);
+float ResizeBetween(TransInfo *t, float p1[3], float p2[3]);
+
+
+/****************** IMPLEMENTATIONS *********************/
+
+int BIF_snappingSupported(Object *obedit)
+{
+ int status = 0;
+
+ if (obedit == NULL || ELEM(obedit->type, OB_MESH, OB_ARMATURE)) /* only support object mesh or armature */
+ {
+ status = 1;
+ }
+
+ return status;
+}
+
+void drawSnapping(const struct bContext *C, TransInfo *t)
+{
+ if ((t->tsnap.status & (SNAP_ON|POINT_INIT|TARGET_INIT)) == (SNAP_ON|POINT_INIT|TARGET_INIT) &&
+ (t->modifiers & MOD_SNAP_GEARS))
+ {
+
+ char col[4] = {1, 0, 1};
+ UI_GetThemeColor3ubv(TH_TRANSFORM, col);
+ glColor4ub(col[0], col[1], col[2], 128);
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float tmat[4][4], imat[4][4];
+ float size;
+
+ glDisable(GL_DEPTH_TEST);
+
+ size = get_drawsize(t->ar, t->tsnap.snapPoint);
+
+ size *= 0.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
+
+ Mat4CpyMat4(tmat, rv3d->viewmat);
+ Mat4Invert(imat, tmat);
+
+ drawcircball(GL_LINE_LOOP, t->tsnap.snapPoint, size, imat);
+
+ /* draw normal if needed */
+ if (usingSnappingNormal(t) && validSnappingNormal(t))
+ {
+ glBegin(GL_LINES);
+ glVertex3f(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]);
+ glVertex3f( t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0],
+ t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1],
+ t->tsnap.snapPoint[2] + t->tsnap.snapNormal[2]);
+ glEnd();
+ }
+
+ if(v3d->zbuf)
+ glEnable(GL_DEPTH_TEST);
+ }
+ else if (t->spacetype==SPACE_IMAGE)
+ {
+ /*This will not draw, and Im nor sure why - campbell */
+
+ /*
+ float xuser_asp, yuser_asp;
+ int wi, hi;
+ float w, h;
+
+ calc_image_view(G.sima, 'f'); // float
+ myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
+ glLoadIdentity();
+
+ ED_space_image_aspect(t->sa->spacedata.first, &xuser_aspx, &yuser_asp);
+ ED_space_image_width(t->sa->spacedata.first, &wi, &hi);
+ w = (((float)wi)/256.0f)*G.sima->zoom * xuser_asp;
+ h = (((float)hi)/256.0f)*G.sima->zoom * yuser_asp;
+
+ cpack(0xFFFFFF);
+ glTranslatef(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], 0.0f);
+
+ //glRectf(0,0,1,1);
+
+ setlinestyle(0);
+ cpack(0x0);
+ fdrawline(-0.020/w, 0, -0.1/w, 0);
+ fdrawline(0.1/w, 0, .020/w, 0);
+ fdrawline(0, -0.020/h, 0, -0.1/h);
+ fdrawline(0, 0.1/h, 0, 0.020/h);
+
+ glTranslatef(-t->tsnap.snapPoint[0], -t->tsnap.snapPoint[1], 0.0f);
+ setlinestyle(0);
+ */
+
+ }
+ }
+}
+
+int handleSnapping(TransInfo *t, wmEvent *event)
+{
+ int status = 0;
+
+ if (BIF_snappingSupported(t->obedit) && event->type == TABKEY && event->shift)
+ {
+ /* toggle snap and reinit */
+ t->scene->snap_flag ^= SCE_SNAP;
+ initSnapping(t, NULL);
+ status = 1;
+ }
+
+ return status;
+}
+
+void applySnapping(TransInfo *t, float *vec)
+{
+ if (t->tsnap.status & SNAP_FORCED)
+ {
+ t->tsnap.targetSnap(t);
+
+ t->tsnap.applySnap(t, vec);
+ }
+ else if ((t->tsnap.status & SNAP_ON) &&
+ (t->modifiers & MOD_SNAP_GEARS))
+ {
+ double current = PIL_check_seconds_timer();
+
+ // Time base quirky code to go around findnearest slowness
+ /* !TODO! add exception for object mode, no need to slow it down then */
+ if (current - t->tsnap.last >= 0.1)
+ {
+ t->tsnap.calcSnap(t, vec);
+ t->tsnap.targetSnap(t);
+
+ t->tsnap.last = current;
+ }
+ if ((t->tsnap.status & (POINT_INIT|TARGET_INIT)) == (POINT_INIT|TARGET_INIT))
+ {
+ t->tsnap.applySnap(t, vec);
+ }
+ }
+}
+
+void resetSnapping(TransInfo *t)
+{
+ t->tsnap.status = 0;
+ t->tsnap.mode = 0;
+ t->tsnap.align = 0;
+ t->tsnap.modePoint = 0;
+ t->tsnap.modeTarget = 0;
+ t->tsnap.last = 0;
+ t->tsnap.applySnap = NULL;
+
+ t->tsnap.snapNormal[0] = 0;
+ t->tsnap.snapNormal[1] = 0;
+ t->tsnap.snapNormal[2] = 0;
+}
+
+int usingSnappingNormal(TransInfo *t)
+{
+ return t->tsnap.align;
+}
+
+int validSnappingNormal(TransInfo *t)
+{
+ if ((t->tsnap.status & (POINT_INIT|TARGET_INIT)) == (POINT_INIT|TARGET_INIT))
+ {
+ if (Inpf(t->tsnap.snapNormal, t->tsnap.snapNormal) > 0)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void initSnapping(TransInfo *t, wmOperator *op)
+{
+ Scene *scene = t->scene;
+ Object *obedit = t->obedit;
+ int snapping = 0;
+ short snap_mode = t->scene->snap_target;
+
+ resetSnapping(t);
+
+ if (op && RNA_struct_find_property(op->ptr, "snap") && RNA_property_is_set(op->ptr, "snap"))
+ {
+ if (RNA_boolean_get(op->ptr, "snap"))
+ {
+ snapping = 1;
+ snap_mode = RNA_enum_get(op->ptr, "snap_mode");
+
+ t->tsnap.status |= SNAP_FORCED|POINT_INIT;
+ RNA_float_get_array(op->ptr, "snap_point", t->tsnap.snapPoint);
+
+ /* snap align only defined in specific cases */
+ if (RNA_struct_find_property(op->ptr, "snap_align"))
+ {
+ t->tsnap.align = RNA_boolean_get(op->ptr, "snap_align");
+ RNA_float_get_array(op->ptr, "snap_normal", t->tsnap.snapNormal);
+ Normalize(t->tsnap.snapNormal);
+ }
+ }
+ }
+ else
+ {
+ snapping = ((scene->snap_flag & SCE_SNAP) == SCE_SNAP);
+ t->tsnap.align = ((t->scene->snap_flag & SCE_SNAP_ROTATE) == SCE_SNAP_ROTATE);
+ }
+
+ if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && // Only 3D view or UV
+ (t->flag & T_CAMERA) == 0) { // Not with camera selected
+ setSnappingCallback(t, snap_mode);
+
+ /* Edit mode */
+ if (t->tsnap.applySnap != NULL && // A snapping function actually exist
+ (snapping) && // Only if the snap flag is on
+ (obedit != NULL && ELEM(obedit->type, OB_MESH, OB_ARMATURE)) ) // Temporary limited to edit mode meshes or armature
+ {
+ t->tsnap.status |= SNAP_ON;
+ t->tsnap.modePoint = SNAP_GEO;
+
+ if (t->flag & T_PROP_EDIT)
+ {
+ t->tsnap.mode = SNAP_NOT_OBEDIT;
+ }
+ else
+ {
+ t->tsnap.mode = SNAP_ALL;
+ }
+ }
+ /* Object mode */
+ else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
+ (snapping) && // Only if the snap flag is on
+ (obedit == NULL) ) // Object Mode
+ {
+ t->tsnap.status |= SNAP_ON;
+ t->tsnap.modePoint = SNAP_GEO;
+ t->tsnap.mode = SNAP_NOT_SELECTED;
+ }
+ else
+ {
+ /* Grid if snap is not possible */
+ t->tsnap.modePoint = SNAP_GRID;
+ }
+ }
+ else
+ {
+ /* Always grid outside of 3D view */
+ t->tsnap.modePoint = SNAP_GRID;
+ }
+}
+
+void setSnappingCallback(TransInfo *t, short snap_target)
+{
+ t->tsnap.calcSnap = CalcSnapGeometry;
+
+ switch(snap_target)
+ {
+ case SCE_SNAP_TARGET_CLOSEST:
+ t->tsnap.modeTarget = SNAP_CLOSEST;
+ t->tsnap.targetSnap = TargetSnapClosest;
+ break;
+ case SCE_SNAP_TARGET_CENTER:
+ t->tsnap.modeTarget = SNAP_CENTER;
+ t->tsnap.targetSnap = TargetSnapCenter;
+ break;
+ case SCE_SNAP_TARGET_MEDIAN:
+ t->tsnap.modeTarget = SNAP_MEDIAN;
+ t->tsnap.targetSnap = TargetSnapMedian;
+ break;
+ case SCE_SNAP_TARGET_ACTIVE:
+ t->tsnap.modeTarget = SNAP_ACTIVE;
+ t->tsnap.targetSnap = TargetSnapActive;
+ break;
+
+ }
+
+ switch (t->mode)
+ {
+ case TFM_TRANSLATION:
+ t->tsnap.applySnap = ApplySnapTranslation;
+ t->tsnap.distance = TranslationBetween;
+ break;
+ case TFM_ROTATION:
+ t->tsnap.applySnap = ApplySnapRotation;
+ t->tsnap.distance = RotationBetween;
+
+ // Can't do TARGET_CENTER with rotation, use TARGET_MEDIAN instead
+ if (snap_target == SCE_SNAP_TARGET_CENTER) {
+ t->tsnap.modeTarget = SNAP_MEDIAN;
+ t->tsnap.targetSnap = TargetSnapMedian;
+ }
+ break;
+ case TFM_RESIZE:
+ t->tsnap.applySnap = ApplySnapResize;
+ t->tsnap.distance = ResizeBetween;
+
+ // Can't do TARGET_CENTER with resize, use TARGET_MEDIAN instead
+ if (snap_target == SCE_SNAP_TARGET_CENTER) {
+ t->tsnap.modeTarget = SNAP_MEDIAN;
+ t->tsnap.targetSnap = TargetSnapMedian;
+ }
+ break;
+ default:
+ t->tsnap.applySnap = NULL;
+ break;
+ }
+}
+
+/********************** APPLY **************************/
+
+void ApplySnapTranslation(TransInfo *t, float vec[3])
+{
+ VecSubf(vec, t->tsnap.snapPoint, t->tsnap.snapTarget);
+}
+
+void ApplySnapRotation(TransInfo *t, float *vec)
+{
+ if (t->tsnap.modeTarget == SNAP_CLOSEST) {
+ *vec = t->tsnap.dist;
+ }
+ else {
+ *vec = RotationBetween(t, t->tsnap.snapTarget, t->tsnap.snapPoint);
+ }
+}
+
+void ApplySnapResize(TransInfo *t, float vec[3])
+{
+ if (t->tsnap.modeTarget == SNAP_CLOSEST) {
+ vec[0] = vec[1] = vec[2] = t->tsnap.dist;
+ }
+ else {
+ vec[0] = vec[1] = vec[2] = ResizeBetween(t, t->tsnap.snapTarget, t->tsnap.snapPoint);
+ }
+}
+
+/********************** DISTANCE **************************/
+
+float TranslationBetween(TransInfo *t, float p1[3], float p2[3])
+{
+ return VecLenf(p1, p2);
+}
+
+float RotationBetween(TransInfo *t, float p1[3], float p2[3])
+{
+ float angle, start[3], end[3], center[3];
+
+ VECCOPY(center, t->center);
+ if(t->flag & (T_EDIT|T_POSE)) {
+ Object *ob= t->obedit?t->obedit:t->poseobj;
+ Mat4MulVecfl(ob->obmat, center);
+ }
+
+ VecSubf(start, p1, center);
+ VecSubf(end, p2, center);
+
+ // Angle around a constraint axis (error prone, will need debug)
+ if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
+ float axis[3], tmp[3];
+
+ t->con.applyRot(t, NULL, axis, NULL);
+
+ Projf(tmp, end, axis);
+ VecSubf(end, end, tmp);
+
+ Projf(tmp, start, axis);
+ VecSubf(start, start, tmp);
+
+ Normalize(end);
+ Normalize(start);
+
+ Crossf(tmp, start, end);
+
+ if (Inpf(tmp, axis) < 0.0)
+ angle = -acos(Inpf(start, end));
+ else
+ angle = acos(Inpf(start, end));
+ }
+ else {
+ float mtx[3][3];
+
+ Mat3CpyMat4(mtx, t->viewmat);
+
+ Mat3MulVecfl(mtx, end);
+ Mat3MulVecfl(mtx, start);
+
+ angle = atan2(start[1],start[0]) - atan2(end[1],end[0]);
+ }
+
+ if (angle > M_PI) {
+ angle = angle - 2 * M_PI;
+ }
+ else if (angle < -(M_PI)) {
+ angle = 2 * M_PI + angle;
+ }
+
+ return angle;
+}
+
+float ResizeBetween(TransInfo *t, float p1[3], float p2[3])
+{
+ float d1[3], d2[3], center[3];
+
+ VECCOPY(center, t->center);
+ if(t->flag & (T_EDIT|T_POSE)) {
+ Object *ob= t->obedit?t->obedit:t->poseobj;
+ Mat4MulVecfl(ob->obmat, center);
+ }
+
+ VecSubf(d1, p1, center);
+ VecSubf(d2, p2, center);
+
+ if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
+ Mat3MulVecfl(t->con.pmtx, d1);
+ Mat3MulVecfl(t->con.pmtx, d2);
+ }
+
+ return VecLength(d2) / VecLength(d1);
+}
+
+/********************** CALC **************************/
+
+void CalcSnapGrid(TransInfo *t, float *vec)
+{
+ snapGridAction(t, t->tsnap.snapPoint, BIG_GEARS);
+}
+
+void CalcSnapGeometry(TransInfo *t, float *vec)
+{
+ if (t->spacetype == SPACE_VIEW3D)
+ {
+ float loc[3];
+ float no[3];
+ int found = 0;
+ int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
+ SnapMode mode;
+
+ if (t->scene->snap_mode == SCE_SNAP_MODE_VOLUME)
+ {
+ ListBase depth_peels;
+ DepthPeel *p1, *p2;
+ float *last_p = NULL;
+ float dist = FLT_MAX;
+ float p[3];
+
+ depth_peels.first = depth_peels.last = NULL;
+
+ peelObjectsTransForm(t, &depth_peels, t->mval);
+
+// if (LAST_SNAP_POINT_VALID)
+// {
+// last_p = LAST_SNAP_POINT;
+// }
+// else
+// {
+ last_p = t->tsnap.snapPoint;
+// }
+
+
+ for (p1 = depth_peels.first; p1; p1 = p1->next)
+ {
+ if (p1->flag == 0)
+ {
+ float vec[3];
+ float new_dist;
+
+ p2 = NULL;
+ p1->flag = 1;
+
+ /* if peeling objects, take the first and last from each object */
+ if (t->scene->snap_flag & SCE_SNAP_PEEL_OBJECT)
+ {
+ DepthPeel *peel;
+ for (peel = p1->next; peel; peel = peel->next)
+ {
+ if (peel->ob == p1->ob)
+ {
+ peel->flag = 1;
+ p2 = peel;
+ }
+ }
+ }
+ /* otherwise, pair first with second and so on */
+ else
+ {
+ for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next)
+ {
+ /* nothing to do here */
+ }
+ }
+
+ if (p2)
+ {
+ p2->flag = 1;
+
+ VecAddf(vec, p1->p, p2->p);
+ VecMulf(vec, 0.5f);
+ }
+ else
+ {
+ VECCOPY(vec, p1->p);
+ }
+
+ if (last_p == NULL)
+ {
+ VECCOPY(p, vec);
+ dist = 0;
+ break;
+ }
+
+ new_dist = VecLenf(last_p, vec);
+
+ if (new_dist < dist)
+ {
+ VECCOPY(p, vec);
+ dist = new_dist;
+ }
+ }
+ }
+
+ if (dist != FLT_MAX)
+ {
+ VECCOPY(loc, p);
+ found = 1;
+ }
+
+ BLI_freelistN(&depth_peels);
+ }
+ else
+ {
+ if (t->obedit == NULL)
+ {
+ mode = SNAP_NOT_SELECTED;
+ }
+ else
+ {
+ mode = SNAP_NOT_OBEDIT;
+ }
+
+ found = snapObjectsTransform(t, t->mval, &dist, loc, no, mode);
+ }
+
+ if (found == 1)
+ {
+ float tangent[3];
+
+ VecSubf(tangent, loc, t->tsnap.snapPoint);
+ tangent[2] = 0;
+
+ if (Inpf(tangent, tangent) > 0)
+ {
+ VECCOPY(t->tsnap.snapTangent, tangent);
+ }
+
+ VECCOPY(t->tsnap.snapPoint, loc);
+ VECCOPY(t->tsnap.snapNormal, no);
+
+ t->tsnap.status |= POINT_INIT;
+ }
+ else
+ {
+ t->tsnap.status &= ~POINT_INIT;
+ }
+ }
+ else if (t->spacetype == SPACE_IMAGE && t->obedit != NULL && t->obedit->type==OB_MESH)
+ { /* same as above but for UV's */
+ /* same as above but for UV's */
+ Image *ima= ED_space_image(t->sa->spacedata.first);
+ float aspx, aspy, co[2];
+
+ UI_view2d_region_to_view(&t->ar->v2d, t->mval[0], t->mval[1], co, co+1);
+
+ if(ED_uvedit_nearest_uv(t->scene, t->obedit, ima, co, t->tsnap.snapPoint))
+ {
+ ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
+ t->tsnap.snapPoint[0] *= aspx;
+ t->tsnap.snapPoint[1] *= aspy;
+
+ Mat4MulVecfl(t->obedit->obmat, t->tsnap.snapPoint);
+
+ t->tsnap.status |= POINT_INIT;
+ }
+ else
+ {
+ t->tsnap.status &= ~POINT_INIT;
+ }
+ }
+}
+
+/********************** TARGET **************************/
+
+void TargetSnapCenter(TransInfo *t)
+{
+ // Only need to calculate once
+ if ((t->tsnap.status & TARGET_INIT) == 0)
+ {
+ VECCOPY(t->tsnap.snapTarget, t->center);
+ if(t->flag & (T_EDIT|T_POSE)) {
+ Object *ob= t->obedit?t->obedit:t->poseobj;
+ Mat4MulVecfl(ob->obmat, t->tsnap.snapTarget);
+ }
+
+ t->tsnap.status |= TARGET_INIT;
+ }
+}
+
+void TargetSnapActive(TransInfo *t)
+{
+ // Only need to calculate once
+ if ((t->tsnap.status & TARGET_INIT) == 0)
+ {
+ TransData *td = NULL;
+ TransData *active_td = NULL;
+ int i;
+
+ for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++)
+ {
+ if (td->flag & TD_ACTIVE)
+ {
+ active_td = td;
+ break;
+ }
+ }
+
+ if (active_td)
+ {
+ VECCOPY(t->tsnap.snapTarget, active_td->center);
+
+ if(t->flag & (T_EDIT|T_POSE)) {
+ Object *ob= t->obedit?t->obedit:t->poseobj;
+ Mat4MulVecfl(ob->obmat, t->tsnap.snapTarget);
+ }
+
+ t->tsnap.status |= TARGET_INIT;
+ }
+ /* No active, default to median */
+ else
+ {
+ t->tsnap.modeTarget = SNAP_MEDIAN;
+ t->tsnap.targetSnap = TargetSnapMedian;
+ TargetSnapMedian(t);
+ }
+ }
+}
+
+void TargetSnapMedian(TransInfo *t)
+{
+ // Only need to calculate once
+ if ((t->tsnap.status & TARGET_INIT) == 0)
+ {
+ TransData *td = NULL;
+ int i;
+
+ t->tsnap.snapTarget[0] = 0;
+ t->tsnap.snapTarget[1] = 0;
+ t->tsnap.snapTarget[2] = 0;
+
+ for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++)
+ {
+ VecAddf(t->tsnap.snapTarget, t->tsnap.snapTarget, td->center);
+ }
+
+ VecMulf(t->tsnap.snapTarget, 1.0 / i);
+
+ if(t->flag & (T_EDIT|T_POSE)) {
+ Object *ob= t->obedit?t->obedit:t->poseobj;
+ Mat4MulVecfl(ob->obmat, t->tsnap.snapTarget);
+ }
+
+ t->tsnap.status |= TARGET_INIT;
+ }
+}
+
+void TargetSnapClosest(TransInfo *t)
+{
+ // Only valid if a snap point has been selected
+ if (t->tsnap.status & POINT_INIT)
+ {
+ TransData *closest = NULL, *td = NULL;
+
+ /* Object mode */
+ if (t->flag & T_OBJECT)
+ {
+ int i;
+ for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++)
+ {
+ struct BoundBox *bb = object_get_boundbox(td->ob);
+
+ /* use boundbox if possible */
+ if (bb)
+ {
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ float loc[3];
+ float dist;
+
+ VECCOPY(loc, bb->vec[j]);
+ Mat4MulVecfl(td->ext->obmat, loc);
+
+ dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
+
+ if (closest == NULL || fabs(dist) < fabs(t->tsnap.dist))
+ {
+ VECCOPY(t->tsnap.snapTarget, loc);
+ closest = td;
+ t->tsnap.dist = dist;
+ }
+ }
+ }
+ /* use element center otherwise */
+ else
+ {
+ float loc[3];
+ float dist;
+
+ VECCOPY(loc, td->center);
+
+ dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
+
+ if (closest == NULL || fabs(dist) < fabs(t->tsnap.dist))
+ {
+ VECCOPY(t->tsnap.snapTarget, loc);
+ closest = td;
+ t->tsnap.dist = dist;
+ }
+ }
+ }
+ }
+ else
+ {
+ int i;
+ for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++)
+ {
+ float loc[3];
+ float dist;
+
+ VECCOPY(loc, td->center);
+
+ if(t->flag & (T_EDIT|T_POSE)) {
+ Object *ob= t->obedit?t->obedit:t->poseobj;
+ Mat4MulVecfl(ob->obmat, loc);
+ }
+
+ dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
+
+ if (closest == NULL || fabs(dist) < fabs(t->tsnap.dist))
+ {
+ VECCOPY(t->tsnap.snapTarget, loc);
+ closest = td;
+ t->tsnap.dist = dist;
+ }
+ }
+ }
+
+ t->tsnap.status |= TARGET_INIT;
+ }
+}
+/*================================================================*/
+
+int snapFace(ARegion *ar, float v1co[3], float v2co[3], float v3co[3], float *v4co, short mval[2], float ray_start[3], float ray_start_local[3], float ray_normal_local[3], float obmat[][4], float timat[][3], float *loc, float *no, int *dist, float *depth)
+{
+ float lambda;
+ int result;
+ int retval = 0;
+
+ result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, v1co, v2co, v3co, &lambda, NULL, 0.001);
+
+ if (result) {
+ float location[3], normal[3];
+ float intersect[3];
+ float new_depth;
+ int screen_loc[2];
+ int new_dist;
+
+ VECCOPY(intersect, ray_normal_local);
+ VecMulf(intersect, lambda);
+ VecAddf(intersect, intersect, ray_start_local);
+
+ VECCOPY(location, intersect);
+
+ if (v4co)
+ CalcNormFloat4(v1co, v2co, v3co, v4co, normal);
+ else
+ CalcNormFloat(v1co, v2co, v3co, normal);
+
+ Mat4MulVecfl(obmat, location);
+
+ new_depth = VecLenf(location, ray_start);
+
+ project_int(ar, location, screen_loc);
+ new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]);
+
+ if (new_dist <= *dist && new_depth < *depth)
+ {
+ *depth = new_depth;
+ retval = 1;
+
+ VECCOPY(loc, location);
+ VECCOPY(no, normal);
+
+ Mat3MulVecfl(timat, no);
+ Normalize(no);
+
+ *dist = new_dist;
+ }
+ }
+
+ return retval;
+}
+
+int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2no[3], short mval[2], float ray_start[3], float ray_start_local[3], float ray_normal_local[3], float obmat[][4], float timat[][3], float *loc, float *no, int *dist, float *depth)
+{
+ float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3];
+ int result;
+ int retval = 0;
+
+ VECCOPY(ray_end, ray_normal_local);
+ VecMulf(ray_end, 2000);
+ VecAddf(ray_end, ray_start_local, ray_end);
+
+ result = LineIntersectLine(v1co, v2co, ray_start_local, ray_end, intersect, dvec); /* dvec used but we don't care about result */
+
+ if (result)
+ {
+ float edge_loc[3], vec[3];
+ float mul;
+
+ /* check for behind ray_start */
+ VecSubf(dvec, intersect, ray_start_local);
+
+ VecSubf(edge_loc, v1co, v2co);
+ VecSubf(vec, intersect, v2co);
+
+ mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc);
+
+ if (mul > 1) {
+ mul = 1;
+ VECCOPY(intersect, v1co);
+ }
+ else if (mul < 0) {
+ mul = 0;
+ VECCOPY(intersect, v2co);
+ }
+
+ if (Inpf(ray_normal_local, dvec) > 0)
+ {
+ float location[3];
+ float new_depth;
+ int screen_loc[2];
+ int new_dist;
+
+ VECCOPY(location, intersect);
+
+ Mat4MulVecfl(obmat, location);
+
+ new_depth = VecLenf(location, ray_start);
+
+ project_int(ar, location, screen_loc);
+ new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]);
+
+ /* 10% threshold if edge is closer but a bit further
+ * this takes care of series of connected edges a bit slanted w.r.t the viewport
+ * otherwise, it would stick to the verts of the closest edge and not slide along merrily
+ * */
+ if (new_dist <= *dist && new_depth < *depth * 1.001)
+ {
+ float n1[3], n2[3];
+
+ *depth = new_depth;
+ retval = 1;
+
+ VecSubf(edge_loc, v1co, v2co);
+ VecSubf(vec, intersect, v2co);
+
+ mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc);
+
+ if (no)
+ {
+ NormalShortToFloat(n1, v1no);
+ NormalShortToFloat(n2, v2no);
+ VecLerpf(no, n2, n1, mul);
+ Mat3MulVecfl(timat, no);
+ Normalize(no);
+ }
+
+ VECCOPY(loc, location);
+
+ *dist = new_dist;
+ }
+ }
+ }
+
+ return retval;
+}
+
+int snapVertex(ARegion *ar, float vco[3], short vno[3], short mval[2], float ray_start[3], float ray_start_local[3], float ray_normal_local[3], float obmat[][4], float timat[][3], float *loc, float *no, int *dist, float *depth)
+{
+ int retval = 0;
+ float dvec[3];
+
+ VecSubf(dvec, vco, ray_start_local);
+
+ if (Inpf(ray_normal_local, dvec) > 0)
+ {
+ float location[3];
+ float new_depth;
+ int screen_loc[2];
+ int new_dist;
+
+ VECCOPY(location, vco);
+
+ Mat4MulVecfl(obmat, location);
+
+ new_depth = VecLenf(location, ray_start);
+
+ project_int(ar, location, screen_loc);
+ new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]);
+
+ if (new_dist <= *dist && new_depth < *depth)
+ {
+ *depth = new_depth;
+ retval = 1;
+
+ VECCOPY(loc, location);
+
+ if (no)
+ {
+ NormalShortToFloat(no, vno);
+ Mat3MulVecfl(timat, no);
+ Normalize(no);
+ }
+
+ *dist = new_dist;
+ }
+ }
+
+ return retval;
+}
+
+int snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth)
+{
+ float imat[4][4];
+ float ray_start_local[3], ray_normal_local[3];
+ int retval = 0;
+
+ Mat4Invert(imat, obmat);
+
+ VECCOPY(ray_start_local, ray_start);
+ VECCOPY(ray_normal_local, ray_normal);
+
+ Mat4MulVecfl(imat, ray_start_local);
+ Mat4Mul3Vecfl(imat, ray_normal_local);
+
+ if(arm->edbo)
+ {
+ EditBone *eBone;
+
+ for (eBone=arm->edbo->first; eBone; eBone=eBone->next) {
+ if (eBone->layer & arm->layer) {
+ /* skip hidden or moving (selected) bones */
+ if ((eBone->flag & (BONE_HIDDEN_A|BONE_ROOTSEL|BONE_TIPSEL))==0) {
+ switch (snap_mode)
+ {
+ case SCE_SNAP_MODE_VERTEX:
+ retval |= snapVertex(ar, eBone->head, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth);
+ retval |= snapVertex(ar, eBone->tail, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth);
+ break;
+ case SCE_SNAP_MODE_EDGE:
+ retval |= snapEdge(ar, eBone->head, NULL, eBone->tail, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth);
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if (ob->pose && ob->pose->chanbase.first)
+ {
+ bPoseChannel *pchan;
+ Bone *bone;
+
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ bone= pchan->bone;
+ /* skip hidden bones */
+ if (bone && !(bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))) {
+ float *head_vec = pchan->pose_head;
+ float *tail_vec = pchan->pose_tail;
+
+ switch (snap_mode)
+ {
+ case SCE_SNAP_MODE_VERTEX:
+ retval |= snapVertex(ar, head_vec, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth);
+ retval |= snapVertex(ar, tail_vec, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth);
+ break;
+ case SCE_SNAP_MODE_EDGE:
+ retval |= snapEdge(ar, head_vec, NULL, tail_vec, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth);
+ break;
+ }
+ }
+ }
+ }
+
+ return retval;
+}
+
+int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, EditMesh *em, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth)
+{
+ int retval = 0;
+ int totvert = dm->getNumVerts(dm);
+ int totface = dm->getNumFaces(dm);
+
+ if (totvert > 0) {
+ float imat[4][4];
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ float ray_start_local[3], ray_normal_local[3];
+ int test = 1;
+
+ Mat4Invert(imat, obmat);
+
+ Mat3CpyMat4(timat, imat);
+ Mat3Transp(timat);
+
+ VECCOPY(ray_start_local, ray_start);
+ VECCOPY(ray_normal_local, ray_normal);
+
+ Mat4MulVecfl(imat, ray_start_local);
+ Mat4Mul3Vecfl(imat, ray_normal_local);
+
+
+ /* If number of vert is more than an arbitrary limit,
+ * test against boundbox first
+ * */
+ if (totface > 16) {
+ struct BoundBox *bb = object_get_boundbox(ob);
+ test = ray_hit_boundbox(bb, ray_start_local, ray_normal_local);
+ }
+
+ if (test == 1) {
+
+ switch (snap_mode)
+ {
+ case SCE_SNAP_MODE_FACE:
+ {
+ MVert *verts = dm->getVertArray(dm);
+ MFace *faces = dm->getFaceArray(dm);
+ int *index_array = NULL;
+ int index = 0;
+ int i;
+
+ if (em != NULL)
+ {
+ index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX);
+ EM_init_index_arrays(em, 0, 0, 1);
+ }
+
+ for( i = 0; i < totface; i++) {
+ EditFace *efa = NULL;
+ MFace *f = faces + i;
+
+ test = 1; /* reset for every face */
+
+ if (em != NULL)
+ {
+ if (index_array)
+ {
+ index = index_array[i];
+ }
+ else
+ {
+ index = i;
+ }
+
+ if (index == ORIGINDEX_NONE)
+ {
+ test = 0;
+ }
+ else
+ {
+ efa = EM_get_face_for_index(index);
+
+ if (efa && (efa->h || (efa->v1->f & SELECT) || (efa->v2->f & SELECT) || (efa->v3->f & SELECT) || (efa->v4 && efa->v4->f & SELECT)))
+ {
+ test = 0;
+ }
+ }
+ }
+
+
+ if (test)
+ {
+ int result;
+ float *v4co = NULL;
+
+ if (f->v4)
+ {
+ v4co = verts[f->v4].co;
+ }
+
+ result = snapFace(ar, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, v4co, mval, ray_start, ray_start_local, ray_normal_local, obmat, timat, loc, no, dist, depth);
+ retval |= result;
+
+ if (f->v4 && result == 0)
+ {
+ retval |= snapFace(ar, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, verts[f->v2].co, mval, ray_start, ray_start_local, ray_normal_local, obmat, timat, loc, no, dist, depth);
+ }
+ }
+ }
+
+ if (em != NULL)
+ {
+ EM_free_index_arrays();
+ }
+ break;
+ }
+ case SCE_SNAP_MODE_VERTEX:
+ {
+ MVert *verts = dm->getVertArray(dm);
+ int *index_array = NULL;
+ int index = 0;
+ int i;
+
+ if (em != NULL)
+ {
+ index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
+ EM_init_index_arrays(em, 1, 0, 0);
+ }
+
+ for( i = 0; i < totvert; i++) {
+ EditVert *eve = NULL;
+ MVert *v = verts + i;
+
+ test = 1; /* reset for every vert */
+
+ if (em != NULL)
+ {
+ if (index_array)
+ {
+ index = index_array[i];
+ }
+ else
+ {
+ index = i;
+ }
+
+ if (index == ORIGINDEX_NONE)
+ {
+ test = 0;
+ }
+ else
+ {
+ eve = EM_get_vert_for_index(index);
+
+ if (eve && (eve->h || (eve->f & SELECT)))
+ {
+ test = 0;
+ }
+ }
+ }
+
+
+ if (test)
+ {
+ retval |= snapVertex(ar, v->co, v->no, mval, ray_start, ray_start_local, ray_normal_local, obmat, timat, loc, no, dist, depth);
+ }
+ }
+
+ if (em != NULL)
+ {
+ EM_free_index_arrays();
+ }
+ break;
+ }
+ case SCE_SNAP_MODE_EDGE:
+ {
+ MVert *verts = dm->getVertArray(dm);
+ MEdge *edges = dm->getEdgeArray(dm);
+ int totedge = dm->getNumEdges(dm);
+ int *index_array = NULL;
+ int index = 0;
+ int i;
+
+ if (em != NULL)
+ {
+ index_array = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
+ EM_init_index_arrays(em, 0, 1, 0);
+ }
+
+ for( i = 0; i < totedge; i++) {
+ EditEdge *eed = NULL;
+ MEdge *e = edges + i;
+
+ test = 1; /* reset for every vert */
+
+ if (em != NULL)
+ {
+ if (index_array)
+ {
+ index = index_array[i];
+ }
+ else
+ {
+ index = i;
+ }
+
+ if (index == ORIGINDEX_NONE)
+ {
+ test = 0;
+ }
+ else
+ {
+ eed = EM_get_edge_for_index(index);
+
+ if (eed && (eed->h || (eed->v1->f & SELECT) || (eed->v2->f & SELECT)))
+ {
+ test = 0;
+ }
+ }
+ }
+
+
+ if (test)
+ {
+ retval |= snapEdge(ar, verts[e->v1].co, verts[e->v1].no, verts[e->v2].co, verts[e->v2].no, mval, ray_start, ray_start_local, ray_normal_local, obmat, timat, loc, no, dist, depth);
+ }
+ }
+
+ if (em != NULL)
+ {
+ EM_free_index_arrays();
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return retval;
+}
+
+int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth)
+{
+ int retval = 0;
+
+ if (ob->type == OB_MESH) {
+ EditMesh *em;
+ DerivedMesh *dm;
+
+ if (editobject)
+ {
+ em = ((Mesh *)ob->data)->edit_mesh;
+ dm = editmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH);
+ }
+ else
+ {
+ em = NULL;
+ dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ }
+
+ retval = snapDerivedMesh(scene->snap_mode, ar, ob, dm, em, obmat, ray_start, ray_normal, mval, loc, no, dist, depth);
+
+ dm->release(dm);
+ }
+ else if (ob->type == OB_ARMATURE)
+ {
+ retval = snapArmature(scene->snap_mode, ar, ob, ob->data, obmat, ray_start, ray_normal, mval, loc, no, dist, depth);
+ }
+
+ return retval;
+}
+
+int snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, short mval[2], int *dist, float *loc, float *no, SnapMode mode) {
+ Base *base;
+ float depth = FLT_MAX;
+ int retval = 0;
+ float ray_start[3], ray_normal[3];
+
+ viewray(ar, v3d, mval, ray_start, ray_normal);
+
+ if (mode == SNAP_ALL && obedit)
+ {
+ Object *ob = obedit;
+
+ retval |= snapObject(scene, ar, ob, 1, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth);
+ }
+
+ base= FIRSTBASE;
+ for ( base = FIRSTBASE; base != NULL; base = base->next ) {
+ if ( BASE_SELECTABLE(v3d, base) && (base->flag & (BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA)) == 0 && ((mode == SNAP_NOT_SELECTED && (base->flag & (SELECT|BA_WAS_SEL)) == 0) || (mode == SNAP_NOT_OBEDIT && base != BASACT)) ) {
+ Object *ob = base->object;
+
+ if (ob->transflag & OB_DUPLI)
+ {
+ DupliObject *dupli_ob;
+ ListBase *lb = object_duplilist(scene, ob);
+
+ for(dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next)
+ {
+ Object *ob = dupli_ob->ob;
+
+ retval |= snapObject(scene, ar, ob, 0, dupli_ob->mat, ray_start, ray_normal, mval, loc, no, dist, &depth);
+ }
+
+ free_object_duplilist(lb);
+ }
+
+ retval |= snapObject(scene, ar, ob, 0, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth);
+ }
+ }
+
+ return retval;
+}
+
+int snapObjectsTransform(TransInfo *t, short mval[2], int *dist, float *loc, float *no, SnapMode mode)
+{
+ return snapObjects(t->scene, t->view, t->ar, t->obedit, mval, dist, loc, no, mode);
+}
+
+int snapObjectsContext(bContext *C, short mval[2], int *dist, float *loc, float *no, SnapMode mode)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ View3D *v3d = sa->spacedata.first;
+
+ return snapObjects(CTX_data_scene(C), v3d, CTX_wm_region(C), CTX_data_edit_object(C), mval, dist, loc, no, mode);
+}
+
+/******************** PEELING *********************************/
+
+
+int cmpPeel(void *arg1, void *arg2)
+{
+ DepthPeel *p1 = arg1;
+ DepthPeel *p2 = arg2;
+ int val = 0;
+
+ if (p1->depth < p2->depth)
+ {
+ val = -1;
+ }
+ else if (p1->depth > p2->depth)
+ {
+ val = 1;
+ }
+
+ return val;
+}
+
+void removeDoublesPeel(ListBase *depth_peels)
+{
+ DepthPeel *peel;
+
+ for (peel = depth_peels->first; peel; peel = peel->next)
+ {
+ DepthPeel *next_peel = peel->next;
+
+ if (peel && next_peel && ABS(peel->depth - next_peel->depth) < 0.0015)
+ {
+ peel->next = next_peel->next;
+
+ if (next_peel->next)
+ {
+ next_peel->next->prev = peel;
+ }
+
+ MEM_freeN(next_peel);
+ }
+ }
+}
+
+void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float no[3], Object *ob)
+{
+ DepthPeel *peel = MEM_callocN(sizeof(DepthPeel), "DepthPeel");
+
+ peel->depth = depth;
+ peel->ob = ob;
+ VECCOPY(peel->p, p);
+ VECCOPY(peel->no, no);
+
+ BLI_addtail(depth_peels, peel);
+
+ peel->flag = 0;
+}
+
+int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], ListBase *depth_peels)
+{
+ int retval = 0;
+ int totvert = dm->getNumVerts(dm);
+ int totface = dm->getNumFaces(dm);
+
+ if (totvert > 0) {
+ float imat[4][4];
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ float ray_start_local[3], ray_normal_local[3];
+ int test = 1;
+
+ Mat4Invert(imat, obmat);
+
+ Mat3CpyMat4(timat, imat);
+ Mat3Transp(timat);
+
+ VECCOPY(ray_start_local, ray_start);
+ VECCOPY(ray_normal_local, ray_normal);
+
+ Mat4MulVecfl(imat, ray_start_local);
+ Mat4Mul3Vecfl(imat, ray_normal_local);
+
+
+ /* If number of vert is more than an arbitrary limit,
+ * test against boundbox first
+ * */
+ if (totface > 16) {
+ struct BoundBox *bb = object_get_boundbox(ob);
+ test = ray_hit_boundbox(bb, ray_start_local, ray_normal_local);
+ }
+
+ if (test == 1) {
+ MVert *verts = dm->getVertArray(dm);
+ MFace *faces = dm->getFaceArray(dm);
+ int i;
+
+ for( i = 0; i < totface; i++) {
+ MFace *f = faces + i;
+ float lambda;
+ int result;
+
+
+ result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL, 0.001);
+
+ if (result) {
+ float location[3], normal[3];
+ float intersect[3];
+ float new_depth;
+
+ VECCOPY(intersect, ray_normal_local);
+ VecMulf(intersect, lambda);
+ VecAddf(intersect, intersect, ray_start_local);
+
+ VECCOPY(location, intersect);
+
+ if (f->v4)
+ CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal);
+ else
+ CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal);
+
+ Mat4MulVecfl(obmat, location);
+
+ new_depth = VecLenf(location, ray_start);
+
+ Mat3MulVecfl(timat, normal);
+ Normalize(normal);
+
+ addDepthPeel(depth_peels, new_depth, location, normal, ob);
+ }
+
+ if (f->v4 && result == 0)
+ {
+ result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL, 0.001);
+
+ if (result) {
+ float location[3], normal[3];
+ float intersect[3];
+ float new_depth;
+
+ VECCOPY(intersect, ray_normal_local);
+ VecMulf(intersect, lambda);
+ VecAddf(intersect, intersect, ray_start_local);
+
+ VECCOPY(location, intersect);
+
+ if (f->v4)
+ CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal);
+ else
+ CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal);
+
+ Mat4MulVecfl(obmat, location);
+
+ new_depth = VecLenf(location, ray_start);
+
+ Mat3MulVecfl(timat, normal);
+ Normalize(normal);
+
+ addDepthPeel(depth_peels, new_depth, location, normal, ob);
+ }
+ }
+ }
+ }
+ }
+
+ return retval;
+}
+
+int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase *depth_peels, short mval[2])
+{
+ Base *base;
+ int retval = 0;
+ float ray_start[3], ray_normal[3];
+
+ viewray(ar, v3d, mval, ray_start, ray_normal);
+
+ for ( base = scene->base.first; base != NULL; base = base->next ) {
+ if ( BASE_SELECTABLE(v3d, base) ) {
+ Object *ob = base->object;
+
+ if (ob->transflag & OB_DUPLI)
+ {
+ DupliObject *dupli_ob;
+ ListBase *lb = object_duplilist(scene, ob);
+
+ for(dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next)
+ {
+ Object *ob = dupli_ob->ob;
+
+ if (ob->type == OB_MESH) {
+ EditMesh *em;
+ DerivedMesh *dm = NULL;
+ int val;
+
+ if (ob != obedit)
+ {
+ dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+
+ val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels);
+ }
+ else
+ {
+ em = ((Mesh *)ob->data)->edit_mesh;
+ dm = editmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH);
+
+ val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels);
+ }
+
+ retval = retval || val;
+
+ dm->release(dm);
+ }
+ }
+
+ free_object_duplilist(lb);
+ }
+
+ if (ob->type == OB_MESH) {
+ EditMesh *em;
+ DerivedMesh *dm = NULL;
+ int val;
+
+ if (ob != obedit)
+ {
+ dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+
+ val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels);
+ }
+ else
+ {
+ em = ((Mesh *)ob->data)->edit_mesh;
+ dm = editmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH);
+
+ val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels);
+ }
+
+ retval = retval || val;
+
+ dm->release(dm);
+ }
+ }
+ }
+
+ BLI_sortlist(depth_peels, cmpPeel);
+ removeDoublesPeel(depth_peels);
+
+ return retval;
+}
+
+int peelObjectsTransForm(TransInfo *t, ListBase *depth_peels, short mval[2])
+{
+ return peelObjects(t->scene, t->view, t->ar, t->obedit, depth_peels, mval);
+}
+
+int peelObjectsContext(bContext *C, ListBase *depth_peels, short mval[2])
+{
+ ScrArea *sa = CTX_wm_area(C);
+ View3D *v3d = sa->spacedata.first;
+
+ return peelObjects(CTX_data_scene(C), v3d, CTX_wm_region(C), CTX_data_edit_object(C), depth_peels, mval);
+}
+
+/*================================================================*/
+
+static void applyGrid(TransInfo *t, float *val, int max_index, float fac[3], GearsType action);
+
+
+void snapGridAction(TransInfo *t, float *val, GearsType action) {
+ float fac[3];
+
+ fac[NO_GEARS] = t->snap[0];
+ fac[BIG_GEARS] = t->snap[1];
+ fac[SMALL_GEARS] = t->snap[2];
+
+ applyGrid(t, val, t->idx_max, fac, action);
+}
+
+
+void snapGrid(TransInfo *t, float *val) {
+ int invert;
+ GearsType action;
+
+ // Only do something if using Snap to Grid
+ if (t->tsnap.modePoint != SNAP_GRID)
+ return;
+
+ if(t->mode==TFM_ROTATION || t->mode==TFM_WARP || t->mode==TFM_TILT || t->mode==TFM_TRACKBALL || t->mode==TFM_BONE_ROLL)
+ invert = U.flag & USER_AUTOROTGRID;
+ else if(t->mode==TFM_RESIZE || t->mode==TFM_SHEAR || t->mode==TFM_BONESIZE || t->mode==TFM_SHRINKFATTEN || t->mode==TFM_CURVE_SHRINKFATTEN)
+ invert = U.flag & USER_AUTOSIZEGRID;
+ else
+ invert = U.flag & USER_AUTOGRABGRID;
+
+ if(invert) {
+ action = (t->modifiers & MOD_SNAP_GEARS) ? NO_GEARS: BIG_GEARS;
+ }
+ else {
+ action = (t->modifiers & MOD_SNAP_GEARS) ? BIG_GEARS : NO_GEARS;
+ }
+
+ if (action == BIG_GEARS && (t->modifiers & MOD_PRECISION)) {
+ action = SMALL_GEARS;
+ }
+
+ snapGridAction(t, val, action);
+}
+
+
+static void applyGrid(TransInfo *t, float *val, int max_index, float fac[3], GearsType action)
+{
+ int i;
+ float asp[3] = {1.0f, 1.0f, 1.0f}; // TODO: Remove hard coded limit here (3)
+
+ // Early bailing out if no need to snap
+ if (fac[action] == 0.0)
+ return;
+
+ /* evil hack - snapping needs to be adapted for image aspect ratio */
+ if((t->spacetype==SPACE_IMAGE) && (t->mode==TFM_TRANSLATION)) {
+ ED_space_image_uv_aspect(t->sa->spacedata.first, asp, asp+1);
+ }
+
+ for (i=0; i<=max_index; i++) {
+ val[i]= fac[action]*asp[i]*(float)floor(val[i]/(fac[action]*asp[i]) +.5);
+ }
+}
diff --git a/source/blender/editors/util/Makefile b/source/blender/editors/util/Makefile
new file mode 100644
index 00000000000..da701dc5d86
--- /dev/null
+++ b/source/blender/editors/util/Makefile
@@ -0,0 +1,54 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_util
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/util/SConscript b/source/blender/editors/util/SConscript
new file mode 100644
index 00000000000..74ca2c89ba2
--- /dev/null
+++ b/source/blender/editors/util/SConscript
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' ../../makesrna'
+
+env.BlenderLib ( 'bf_editors_util', sources, Split(incs), [], libtype=['core'], priority=[130] )
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
new file mode 100644
index 00000000000..5623e538eb4
--- /dev/null
+++ b/source/blender/editors/util/ed_util.c
@@ -0,0 +1,122 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+
+#include "ED_armature.h"
+#include "ED_mesh.h"
+#include "ED_sculpt.h"
+#include "ED_util.h"
+
+#include "UI_interface.h"
+
+/* ********* general editor util funcs, not BKE stuff please! ********* */
+
+void ED_editors_exit(bContext *C)
+{
+ Object *ob= CTX_data_edit_object(C);
+
+ /* frees all editmode undos */
+ undo_editmode_clear();
+ undo_imagepaint_clear();
+
+ /* global in meshtools... */
+ mesh_octree_table(ob, NULL, NULL, 'e');
+
+ if(ob) {
+ if(ob->type==OB_MESH) {
+ Mesh *me= ob->data;
+ if(me->edit_mesh) {
+ free_editMesh(me->edit_mesh);
+ MEM_freeN(me->edit_mesh);
+ me->edit_mesh= NULL;
+ }
+ }
+ else if(ob->type==OB_ARMATURE) {
+ ED_armature_edit_free(ob);
+ }
+ else if(ob->type==OB_FONT) {
+ // free_editText();
+ }
+ // else if(ob->type==OB_MBALL)
+ // BLI_freelistN(&editelems);
+ }
+
+ // free_editLatt();
+ // free_posebuf();
+
+}
+
+
+/* ***** XXX: functions are using old blender names, cleanup later ***** */
+
+
+/* now only used in 2d spaces, like time, ipo, nla, sima... */
+/* XXX shift/ctrl not configurable */
+void apply_keyb_grid(int shift, int ctrl, float *val, float fac1, float fac2, float fac3, int invert)
+{
+ /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */
+ if(invert)
+ ctrl= !ctrl;
+
+ if(ctrl && shift) {
+ 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);
+ }
+}
+
+
+int GetButStringLength(char *str)
+{
+ int rt;
+
+ rt= UI_GetStringWidth(str);
+
+ return rt + 15;
+}
+
diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c
new file mode 100644
index 00000000000..8484ad78bc4
--- /dev/null
+++ b/source/blender/editors/util/editmode_undo.c
@@ -0,0 +1,365 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_object.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h"
+
+#include "BKE_utildefines.h"
+
+#include "ED_util.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+/* ***************** generic editmode undo system ********************* */
+/*
+
+Add this in your local code:
+
+void undo_editmode_push(bContext *C, char *name,
+ void * (*getdata)(bContext *C), // use context to retrieve current editdata
+ void (*freedata)(void *), // pointer to function freeing data
+ void (*to_editmode)(void *, void *), // data to editmode conversion
+ void * (*from_editmode)(void *)) // editmode to data conversion
+ int (*validate_undo)(void *, void *)) // check if undo data is still valid
+
+
+Further exported for UI is:
+
+void undo_editmode_step(bContext *C, int step); // undo and redo
+void undo_editmode_clear(void) // free & clear all data
+void undo_editmode_menu(void) // history menu
+
+
+*/
+/* ********************************************************************* */
+
+/* ****** XXX ***** */
+void error() {}
+/* ****** XXX ***** */
+
+
+#define MAXUNDONAME 64
+typedef struct UndoElem {
+ struct UndoElem *next, *prev;
+ ID id; // copy of editmode object ID
+ Object *ob; // pointer to edited object
+ int type; // type of edited object
+ void *undodata;
+ uintptr_t undosize;
+ char name[MAXUNDONAME];
+ void * (*getdata)(bContext *C);
+ void (*freedata)(void *);
+ void (*to_editmode)(void *, void *);
+ void * (*from_editmode)(void *);
+ int (*validate_undo)(void *, void *);
+} UndoElem;
+
+static ListBase undobase={NULL, NULL};
+static UndoElem *curundo= NULL;
+
+
+/* ********************* xtern api calls ************* */
+
+static void undo_restore(UndoElem *undo, void *editdata)
+{
+ if(undo) {
+ undo->to_editmode(undo->undodata, editdata);
+ }
+}
+
+/* name can be a dynamic string */
+void undo_editmode_push(bContext *C, char *name,
+ void * (*getdata)(bContext *C),
+ void (*freedata)(void *),
+ void (*to_editmode)(void *, void *),
+ void *(*from_editmode)(void *),
+ int (*validate_undo)(void *, void *))
+{
+ UndoElem *uel;
+ Object *obedit= CTX_data_edit_object(C);
+ void *editdata;
+ int nr;
+ uintptr_t memused, totmem, maxmem;
+
+ /* at first here was code to prevent an "original" key to be insterted twice
+ this was giving conflicts for example when mesh changed due to keys or apply */
+
+ /* remove all undos after (also when curundo==NULL) */
+ while(undobase.last != curundo) {
+ uel= undobase.last;
+ uel->freedata(uel->undodata);
+ BLI_freelinkN(&undobase, uel);
+ }
+
+ /* make new */
+ curundo= uel= MEM_callocN(sizeof(UndoElem), "undo editmode");
+ strncpy(uel->name, name, MAXUNDONAME-1);
+ BLI_addtail(&undobase, uel);
+
+ uel->getdata= getdata;
+ uel->freedata= freedata;
+ uel->to_editmode= to_editmode;
+ uel->from_editmode= from_editmode;
+ uel->validate_undo= validate_undo;
+
+ /* limit amount to the maximum amount*/
+ nr= 0;
+ uel= undobase.last;
+ while(uel) {
+ nr++;
+ if(nr==U.undosteps) break;
+ uel= uel->prev;
+ }
+ if(uel) {
+ while(undobase.first!=uel) {
+ UndoElem *first= undobase.first;
+ first->freedata(first->undodata);
+ BLI_freelinkN(&undobase, first);
+ }
+ }
+
+ /* copy */
+ memused= MEM_get_memory_in_use();
+ editdata= getdata(C);
+ curundo->undodata= curundo->from_editmode(editdata);
+ curundo->undosize= MEM_get_memory_in_use() - memused;
+ curundo->ob= obedit;
+ curundo->id= obedit->id;
+ curundo->type= obedit->type;
+
+ if(U.undomemory != 0) {
+ /* limit to maximum memory (afterwards, we can't know in advance) */
+ totmem= 0;
+ maxmem= ((uintptr_t)U.undomemory)*1024*1024;
+
+ uel= undobase.last;
+ while(uel && uel->prev) {
+ totmem+= uel->undosize;
+ if(totmem>maxmem) break;
+ uel= uel->prev;
+ }
+
+ if(uel) {
+ if(uel->prev && uel->prev->prev)
+ uel= uel->prev;
+
+ while(undobase.first!=uel) {
+ UndoElem *first= undobase.first;
+ first->freedata(first->undodata);
+ BLI_freelinkN(&undobase, first);
+ }
+ }
+ }
+}
+
+/* helper to remove clean other objects from undo stack */
+static void undo_clean_stack(bContext *C)
+{
+ UndoElem *uel, *next;
+ Object *obedit= CTX_data_edit_object(C);
+ int mixed= 0;
+
+ /* global undo changes pointers, so we also allow identical names */
+ /* side effect: when deleting/renaming object and start editing new one with same name */
+
+ uel= undobase.first;
+ while(uel) {
+ void *editdata= uel->getdata(C);
+ int isvalid= 0;
+ next= uel->next;
+
+ /* for when objects are converted, renamed, or global undo changes pointers... */
+ if(uel->type==obedit->type) {
+ if(strcmp(uel->id.name, obedit->id.name)==0) {
+ if(uel->validate_undo==NULL)
+ isvalid= 1;
+ else if(uel->validate_undo(uel->undodata, editdata))
+ isvalid= 1;
+ }
+ }
+ if(isvalid)
+ uel->ob= obedit;
+ else {
+ mixed= 1;
+ uel->freedata(uel->undodata);
+ BLI_freelinkN(&undobase, uel);
+ }
+
+ uel= next;
+ }
+
+ if(mixed) curundo= undobase.last;
+}
+
+/* 1= an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation */
+void undo_editmode_step(bContext *C, int step)
+{
+
+ /* prevent undo to happen on wrong object, stack can be a mix */
+ undo_clean_stack(C);
+
+ if(step==0) {
+ undo_restore(curundo, curundo->getdata(C));
+ }
+ else if(step==1) {
+
+ if(curundo==NULL || curundo->prev==NULL) error("No more steps to undo");
+ else {
+ if(G.f & G_DEBUG) printf("undo %s\n", curundo->name);
+ curundo= curundo->prev;
+ undo_restore(curundo, curundo->getdata(C));
+ }
+ }
+ else {
+ /* curundo has to remain current situation! */
+
+ if(curundo==NULL || curundo->next==NULL) error("No more steps to redo");
+ else {
+ undo_restore(curundo->next, curundo->getdata(C));
+ curundo= curundo->next;
+ if(G.f & G_DEBUG) printf("redo %s\n", curundo->name);
+ }
+ }
+
+// DAG_object_flush_update(G.scene, obedit, OB_RECALC_DATA);
+ /* XXX notifiers */
+}
+
+void undo_editmode_clear(void)
+{
+ UndoElem *uel;
+
+ uel= undobase.first;
+ while(uel) {
+ uel->freedata(uel->undodata);
+ uel= uel->next;
+ }
+ BLI_freelistN(&undobase);
+ curundo= NULL;
+}
+
+/* based on index nr it does a restore */
+static void undo_number(bContext *C, int nr)
+{
+ UndoElem *uel;
+ int a=1;
+
+ for(uel= undobase.first; uel; uel= uel->next, a++) {
+ if(a==nr) break;
+ }
+ curundo= uel;
+ undo_editmode_step(C, 0);
+}
+
+/* ************** for interaction with menu/pullown */
+
+void undo_editmode_menu(bContext *C)
+{
+ UndoElem *uel;
+ DynStr *ds= BLI_dynstr_new();
+ short event= 0;
+ char *menu;
+
+ undo_clean_stack(C); // removes other objects from it
+
+ BLI_dynstr_append(ds, "Editmode Undo History %t");
+
+ for(uel= undobase.first; uel; uel= uel->next) {
+ BLI_dynstr_append(ds, "|");
+ BLI_dynstr_append(ds, uel->name);
+ }
+
+ menu= BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+// XXX event= pupmenu_col(menu, 20);
+ MEM_freeN(menu);
+
+ if(event>0) undo_number(C, event);
+}
+
+static void do_editmode_undohistorymenu(bContext *C, void *arg, int event)
+{
+ Object *obedit= CTX_data_edit_object(C);
+
+ if(obedit==NULL || event<1) return;
+
+ undo_number(C, event-1);
+
+}
+
+uiBlock *editmode_undohistorymenu(bContext *C, ARegion *ar, void *arg_unused)
+{
+ uiBlock *block;
+ UndoElem *uel;
+ short yco = 20, menuwidth = 120;
+ short item= 1;
+
+ undo_clean_stack(C); // removes other objects from it
+
+ block= uiBeginBlock(C, ar, "view3d_edit_mesh_undohistorymenu", UI_EMBOSSP);
+ uiBlockSetButmFunc(block, do_editmode_undohistorymenu, NULL);
+
+ for(uel= undobase.first; uel; uel= uel->next, item++) {
+ if (uel==curundo) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, uel->name, 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, (float)item, "");
+ if (uel==curundo) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+ }
+
+ uiBlockSetDirection(block, UI_RIGHT);
+ uiTextBoundsBlock(block, 60);
+ return block;
+}
+
+void *undo_editmode_get_prev(Object *ob)
+{
+ UndoElem *ue= undobase.last;
+ if(ue && ue->prev && ue->prev->ob==ob) return ue->prev->undodata;
+ return NULL;
+}
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
new file mode 100644
index 00000000000..62ce76a7614
--- /dev/null
+++ b/source/blender/editors/util/undo.c
@@ -0,0 +1,242 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_blender.h"
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_object.h"
+#include "BKE_text.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_dynstr.h"
+
+#include "BKE_utildefines.h"
+
+#include "ED_armature.h"
+#include "ED_particle.h"
+#include "ED_curve.h"
+#include "ED_mesh.h"
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_sculpt.h"
+#include "ED_util.h"
+#include "ED_text.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+/* ***************** generic undo system ********************* */
+
+/* ********* XXX **************** */
+static void undo_push_mball() {}
+static void sound_initialize_sounds() {}
+/* ********* XXX **************** */
+
+void ED_undo_push(bContext *C, char *str)
+{
+ wmWindowManager *wm= CTX_wm_manager(C);
+ Object *obedit= CTX_data_edit_object(C);
+
+ if(obedit) {
+ if (U.undosteps == 0) return;
+
+ if(obedit->type==OB_MESH)
+ undo_push_mesh(C, str);
+ else if ELEM(obedit->type, OB_CURVE, OB_SURF)
+ undo_push_curve(C, str);
+ else if (obedit->type==OB_FONT)
+ undo_push_font(C, str);
+ else if (obedit->type==OB_MBALL)
+ undo_push_mball(str);
+ else if (obedit->type==OB_LATTICE)
+ undo_push_lattice(C, str);
+ else if (obedit->type==OB_ARMATURE)
+ undo_push_armature(C, str);
+ }
+ else if(G.f & G_PARTICLEEDIT) {
+ if (U.undosteps == 0) return;
+
+ PE_undo_push(CTX_data_scene(C), str);
+ }
+ else {
+ if(U.uiflag & USER_GLOBALUNDO)
+ BKE_write_undo(C, str);
+ }
+
+ if(wm->file_saved) {
+ wm->file_saved= 0;
+ WM_event_add_notifier(C, NC_WM|ND_DATACHANGED, NULL);
+ }
+}
+
+void ED_undo_push_op(bContext *C, wmOperator *op)
+{
+ /* in future, get undo string info? */
+ ED_undo_push(C, op->type->name);
+}
+
+static int ed_undo_step(bContext *C, int step)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ScrArea *sa= CTX_wm_area(C);
+
+ if(sa && sa->spacetype==SPACE_TEXT) {
+ ED_text_undo_step(C, step);
+ }
+ else if(obedit) {
+ if ELEM7(obedit->type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL, OB_LATTICE, OB_ARMATURE)
+ undo_editmode_step(C, step);
+ }
+ else {
+ int do_glob_undo= 0;
+
+ if(G.f & G_TEXTUREPAINT)
+ undo_imagepaint_step(step);
+ else if(sa && sa->spacetype==SPACE_IMAGE) {
+ SpaceImage *sima= (SpaceImage *)sa->spacedata.first;
+ if(sima->flag & SI_DRAWTOOL)
+ undo_imagepaint_step(step);
+ else
+ do_glob_undo= 1;
+ }
+ else if(G.f & G_PARTICLEEDIT) {
+ if(step==1)
+ PE_undo(CTX_data_scene(C));
+ else
+ PE_redo(CTX_data_scene(C));
+ }
+ else {
+ do_glob_undo= 1;
+ }
+
+ if(do_glob_undo) {
+ if(U.uiflag & USER_GLOBALUNDO) {
+#ifndef DISABLE_PYTHON
+ // XXX BPY_scripts_clear_pyobjects();
+#endif
+ BKE_undo_step(C, step);
+ sound_initialize_sounds();
+ }
+
+ }
+ }
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void ED_undo_pop(bContext *C)
+{
+ ed_undo_step(C, 1);
+}
+void ED_undo_redo(bContext *C)
+{
+ ed_undo_step(C, -1);
+}
+
+static int ed_undo_exec(bContext *C, wmOperator *op)
+{
+ return ed_undo_step(C, 1);
+}
+static int ed_redo_exec(bContext *C, wmOperator *op)
+{
+ return ed_undo_step(C, -1);
+}
+
+void ED_undo_menu(bContext *C)
+{
+ Object *obedit= CTX_data_edit_object(C);
+
+ if(obedit) {
+ //if ELEM7(obedit->type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL, OB_LATTICE, OB_ARMATURE)
+ // undo_editmode_menu();
+ }
+ else {
+ if(G.f & G_PARTICLEEDIT)
+ PE_undo_menu(CTX_data_scene(C), CTX_data_active_object(C));
+ else if(U.uiflag & USER_GLOBALUNDO) {
+ char *menu= BKE_undo_menu_string();
+ if(menu) {
+ short event= 0; // XXX pupmenu_col(menu, 20);
+ MEM_freeN(menu);
+ if(event>0) {
+ BKE_undo_number(C, event);
+ sound_initialize_sounds();
+ }
+ }
+ }
+ }
+}
+
+/* ********************** */
+
+void ED_OT_undo(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Undo";
+ ot->idname= "ED_OT_undo";
+
+ /* api callbacks */
+ ot->exec= ed_undo_exec;
+ ot->poll= ED_operator_screenactive;
+}
+
+void ED_OT_redo(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Redo";
+ ot->idname= "ED_OT_redo";
+
+ /* api callbacks */
+ ot->exec= ed_redo_exec;
+ ot->poll= ED_operator_screenactive;
+}
+
+
diff --git a/source/blender/editors/util/util_intern.h b/source/blender/editors/util/util_intern.h
new file mode 100644
index 00000000000..37e6c5c25e1
--- /dev/null
+++ b/source/blender/editors/util/util_intern.h
@@ -0,0 +1,38 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_UTIL_INTERN_H
+#define ED_UTIL_INTERN_H
+
+/* internal exports only */
+
+/* editmode_undo.c */
+void undo_editmode_clear(void);
+
+#endif /* ED_UTIL_INTERN_H */
+
diff --git a/source/blender/editors/uvedit/Makefile b/source/blender/editors/uvedit/Makefile
new file mode 100644
index 00000000000..b8a8f0bc8af
--- /dev/null
+++ b/source/blender/editors/uvedit/Makefile
@@ -0,0 +1,55 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_uvedit
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../gpu
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I$(NAN_OPENNL)/include
+
+# own include
+
+CPPFLAGS += -I../include
+
diff --git a/source/blender/editors/uvedit/SConscript b/source/blender/editors/uvedit/SConscript
new file mode 100644
index 00000000000..b472b89d23d
--- /dev/null
+++ b/source/blender/editors/uvedit/SConscript
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' ../../makesrna #/intern/opennl/extern ../../gpu'
+
+env.BlenderLib ( 'bf_editors_uvedit', sources, Split(incs), [], libtype=['core'], priority=[45] )
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
new file mode 100644
index 00000000000..aded5a4cff9
--- /dev/null
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -0,0 +1,856 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2002-2009
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <float.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "ED_image.h"
+#include "ED_mesh.h"
+
+#include "UI_resources.h"
+
+#include "uvedit_intern.h"
+
+static void drawcursor_sima(SpaceImage *sima, ARegion *ar)
+{
+ View2D *v2d= &ar->v2d;
+ float zoomx, zoomy, w, h;
+ int width, height;
+
+ ED_space_image_size(sima, &width, &height);
+ ED_space_image_zoom(sima, ar, &zoomx, &zoomy);
+
+ w= zoomx*width/256.0f;
+ h= zoomy*height/256.0f;
+
+ cpack(0xFFFFFF);
+ glTranslatef(v2d->cursor[0], v2d->cursor[1], 0.0f);
+ fdrawline(-0.05/w, 0, 0, 0.05/h);
+ fdrawline(0, 0.05/h, 0.05/w, 0);
+ fdrawline(0.05/w, 0, 0, -0.05/h);
+ fdrawline(0, -0.05/h, -0.05/w, 0);
+
+ setlinestyle(4);
+ cpack(0xFF);
+ fdrawline(-0.05/w, 0, 0, 0.05/h);
+ fdrawline(0, 0.05/h, 0.05/w, 0);
+ fdrawline(0.05/w, 0, 0, -0.05/h);
+ fdrawline(0, -0.05/h, -0.05/w, 0);
+
+
+ setlinestyle(0);
+ cpack(0x0);
+ fdrawline(-0.020/w, 0, -0.1/w, 0);
+ fdrawline(0.1/w, 0, .020/w, 0);
+ fdrawline(0, -0.020/h, 0, -0.1/h);
+ fdrawline(0, 0.1/h, 0, 0.020/h);
+
+ setlinestyle(1);
+ cpack(0xFFFFFF);
+ fdrawline(-0.020/w, 0, -0.1/w, 0);
+ fdrawline(0.1/w, 0, .020/w, 0);
+ fdrawline(0, -0.020/h, 0, -0.1/h);
+ fdrawline(0, 0.1/h, 0, 0.020/h);
+
+ glTranslatef(-v2d->cursor[0], -v2d->cursor[1], 0.0f);
+ setlinestyle(0);
+}
+
+static int draw_uvs_face_check(Scene *scene)
+{
+ /* checks if we are selecting only faces */
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->selectmode == SCE_SELECT_FACE)
+ return 2;
+ else if(scene->selectmode & SCE_SELECT_FACE)
+ return 1;
+ else
+ return 0;
+ }
+ else
+ return (scene->toolsettings->uv_selectmode == UV_SELECT_FACE);
+}
+
+static void draw_uvs_shadow(SpaceImage *sima, Object *obedit)
+{
+ EditMesh *em;
+ EditFace *efa;
+ TFace *tf;
+
+ em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+
+ /* draws the grey mesh when painting */
+ glColor3ub(112, 112, 112);
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2fv(tf->uv[0]);
+ glVertex2fv(tf->uv[1]);
+ glVertex2fv(tf->uv[2]);
+ if(efa->v4) glVertex2fv(tf->uv[3]);
+ glEnd();
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+}
+
+static int draw_uvs_dm_shadow(DerivedMesh *dm)
+{
+ /* draw shadow mesh - this is the mesh with the modifier applied */
+
+ if(dm && dm->drawUVEdges && CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
+ glColor3ub(112, 112, 112);
+ dm->drawUVEdges(dm);
+ return 1;
+ }
+
+ return 0;
+}
+
+static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFace *activetf)
+{
+ EditFace *efa;
+ MTFace *tf;
+ Image *ima= sima->image;
+ float aspx, aspy, col[4], tf_uv[4][2];
+
+ ED_space_image_uv_aspect(sima, &aspx, &aspy);
+
+ switch(sima->dt_uvstretch) {
+ case SI_UVDT_STRETCH_AREA:
+ {
+ float totarea=0.0f, totuvarea=0.0f, areadiff, uvarea, area;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ uv_copy_aspect(tf->uv, tf_uv, aspx, aspy);
+
+ totarea += EM_face_area(efa);
+ //totuvarea += tf_area(tf, efa->v4!=0);
+ totuvarea += uv_area(tf_uv, efa->v4!=0);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ efa->tmp.p = tf;
+ }
+ else {
+ if(tf == activetf)
+ activetf= NULL;
+ efa->tmp.p = NULL;
+ }
+ }
+
+ if(totarea < FLT_EPSILON || totuvarea < FLT_EPSILON) {
+ col[0] = 1.0;
+ col[1] = col[2] = 0.0;
+ glColor3fv(col);
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if((tf=(MTFace *)efa->tmp.p)) {
+ glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
+ glVertex2fv(tf->uv[0]);
+ glVertex2fv(tf->uv[1]);
+ glVertex2fv(tf->uv[2]);
+ if(efa->v4) glVertex2fv(tf->uv[3]);
+ glEnd();
+ }
+ }
+ }
+ else {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if((tf=(MTFace *)efa->tmp.p)) {
+ area = EM_face_area(efa) / totarea;
+ uv_copy_aspect(tf->uv, tf_uv, aspx, aspy);
+ //uvarea = tf_area(tf, efa->v4!=0) / totuvarea;
+ uvarea = uv_area(tf_uv, efa->v4!=0) / totuvarea;
+
+ if(area < FLT_EPSILON || uvarea < FLT_EPSILON)
+ areadiff = 1.0;
+ else if(area>uvarea)
+ areadiff = 1.0-(uvarea/area);
+ else
+ areadiff = 1.0-(area/uvarea);
+
+ weight_to_rgb(areadiff, col, col+1, col+2);
+ glColor3fv(col);
+
+ glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
+ glVertex2fv(tf->uv[0]);
+ glVertex2fv(tf->uv[1]);
+ glVertex2fv(tf->uv[2]);
+ if(efa->v4) glVertex2fv(tf->uv[3]);
+ glEnd();
+ }
+ }
+ }
+ break;
+ }
+ case SI_UVDT_STRETCH_ANGLE:
+ {
+ float uvang1,uvang2,uvang3,uvang4;
+ float ang1,ang2,ang3,ang4;
+ float av1[3], av2[3], av3[3], av4[3]; /* use for 2d and 3d angle vectors */
+ float a;
+
+ col[3] = 0.5; /* hard coded alpha, not that nice */
+
+ glShadeModel(GL_SMOOTH);
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ efa->tmp.p = tf;
+ uv_copy_aspect(tf->uv, tf_uv, aspx, aspy);
+ if(efa->v4) {
+
+#if 0 /* Simple but slow, better reuse normalized vectors */
+ uvang1 = VecAngle3_2D(tf_uv[3], tf_uv[0], tf_uv[1]);
+ ang1 = VecAngle3(efa->v4->co, efa->v1->co, efa->v2->co);
+
+ uvang2 = VecAngle3_2D(tf_uv[0], tf_uv[1], tf_uv[2]);
+ ang2 = VecAngle3(efa->v1->co, efa->v2->co, efa->v3->co);
+
+ uvang3 = VecAngle3_2D(tf_uv[1], tf_uv[2], tf_uv[3]);
+ ang3 = VecAngle3(efa->v2->co, efa->v3->co, efa->v4->co);
+
+ uvang4 = VecAngle3_2D(tf_uv[2], tf_uv[3], tf_uv[0]);
+ ang4 = VecAngle3(efa->v3->co, efa->v4->co, efa->v1->co);
+#endif
+
+ /* uv angles */
+ VECSUB2D(av1, tf_uv[3], tf_uv[0]); Normalize2(av1);
+ VECSUB2D(av2, tf_uv[0], tf_uv[1]); Normalize2(av2);
+ VECSUB2D(av3, tf_uv[1], tf_uv[2]); Normalize2(av3);
+ VECSUB2D(av4, tf_uv[2], tf_uv[3]); Normalize2(av4);
+
+ /* This is the correct angle however we are only comparing angles
+ * uvang1 = 90-((NormalizedVecAngle2_2D(av1, av2) * 180.0/M_PI)-90);*/
+ uvang1 = NormalizedVecAngle2_2D(av1, av2)*180.0/M_PI;
+ uvang2 = NormalizedVecAngle2_2D(av2, av3)*180.0/M_PI;
+ uvang3 = NormalizedVecAngle2_2D(av3, av4)*180.0/M_PI;
+ uvang4 = NormalizedVecAngle2_2D(av4, av1)*180.0/M_PI;
+
+ /* 3d angles */
+ VECSUB(av1, efa->v4->co, efa->v1->co); Normalize(av1);
+ VECSUB(av2, efa->v1->co, efa->v2->co); Normalize(av2);
+ VECSUB(av3, efa->v2->co, efa->v3->co); Normalize(av3);
+ VECSUB(av4, efa->v3->co, efa->v4->co); Normalize(av4);
+
+ /* This is the correct angle however we are only comparing angles
+ * ang1 = 90-((NormalizedVecAngle2(av1, av2) * 180.0/M_PI)-90);*/
+ ang1 = NormalizedVecAngle2(av1, av2)*180.0/M_PI;
+ ang2 = NormalizedVecAngle2(av2, av3)*180.0/M_PI;
+ ang3 = NormalizedVecAngle2(av3, av4)*180.0/M_PI;
+ ang4 = NormalizedVecAngle2(av4, av1)*180.0/M_PI;
+
+ glBegin(GL_QUADS);
+
+ /* This simple makes the angles display worse then they really are ;)
+ * 1.0-pow((1.0-a), 2) */
+
+ a = fabs(uvang1-ang1)/180.0;
+ weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
+ glColor3fv(col);
+ glVertex2fv(tf->uv[0]);
+ a = fabs(uvang2-ang2)/180.0;
+ weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
+ glColor3fv(col);
+ glVertex2fv(tf->uv[1]);
+ a = fabs(uvang3-ang3)/180.0;
+ weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
+ glColor3fv(col);
+ glVertex2fv(tf->uv[2]);
+ a = fabs(uvang4-ang4)/180.0;
+ weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
+ glColor3fv(col);
+ glVertex2fv(tf->uv[3]);
+
+ }
+ else {
+#if 0 /* Simple but slow, better reuse normalized vectors */
+ uvang1 = VecAngle3_2D(tf_uv[2], tf_uv[0], tf_uv[1]);
+ ang1 = VecAngle3(efa->v3->co, efa->v1->co, efa->v2->co);
+
+ uvang2 = VecAngle3_2D(tf_uv[0], tf_uv[1], tf_uv[2]);
+ ang2 = VecAngle3(efa->v1->co, efa->v2->co, efa->v3->co);
+
+ uvang3 = 180-(uvang1+uvang2);
+ ang3 = 180-(ang1+ang2);
+#endif
+
+ /* uv angles */
+ VECSUB2D(av1, tf_uv[2], tf_uv[0]); Normalize2(av1);
+ VECSUB2D(av2, tf_uv[0], tf_uv[1]); Normalize2(av2);
+ VECSUB2D(av3, tf_uv[1], tf_uv[2]); Normalize2(av3);
+
+ /* This is the correct angle however we are only comparing angles
+ * uvang1 = 90-((NormalizedVecAngle2_2D(av1, av2) * 180.0/M_PI)-90); */
+ uvang1 = NormalizedVecAngle2_2D(av1, av2)*180.0/M_PI;
+ uvang2 = NormalizedVecAngle2_2D(av2, av3)*180.0/M_PI;
+ uvang3 = NormalizedVecAngle2_2D(av3, av1)*180.0/M_PI;
+
+ /* 3d angles */
+ VECSUB(av1, efa->v3->co, efa->v1->co); Normalize(av1);
+ VECSUB(av2, efa->v1->co, efa->v2->co); Normalize(av2);
+ VECSUB(av3, efa->v2->co, efa->v3->co); Normalize(av3);
+ /* This is the correct angle however we are only comparing angles
+ * ang1 = 90-((NormalizedVecAngle2(av1, av2) * 180.0/M_PI)-90); */
+ ang1 = NormalizedVecAngle2(av1, av2)*180.0/M_PI;
+ ang2 = NormalizedVecAngle2(av2, av3)*180.0/M_PI;
+ ang3 = NormalizedVecAngle2(av3, av1)*180.0/M_PI;
+
+ /* This simple makes the angles display worse then they really are ;)
+ * 1.0-pow((1.0-a), 2) */
+
+ glBegin(GL_TRIANGLES);
+ a = fabs(uvang1-ang1)/180.0;
+ weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
+ glColor3fv(col);
+ glVertex2fv(tf->uv[0]);
+ a = fabs(uvang2-ang2)/180.0;
+ weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
+ glColor3fv(col);
+ glVertex2fv(tf->uv[1]);
+ a = fabs(uvang3-ang3)/180.0;
+ weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
+ glColor3fv(col);
+ glVertex2fv(tf->uv[2]);
+ }
+ glEnd();
+ }
+ else {
+ if(tf == activetf)
+ activetf= NULL;
+ efa->tmp.p = NULL;
+ }
+ }
+
+ glShadeModel(GL_FLAT);
+ break;
+ }
+ }
+}
+
+static void draw_uvs_other(SpaceImage *sima, Scene *scene, Object *obedit, MTFace *activetf)
+{
+ Base *base;
+ Image *curimage;
+
+ curimage= (activetf)? activetf->tpage: NULL;
+
+ glColor3ub(96, 96, 96);
+
+ for(base=scene->base.first; base; base=base->next) {
+ Object *ob= base->object;
+
+ if(!(base->flag & SELECT)) continue;
+ if(!(base->lay & scene->lay)) continue;
+ if(ob->restrictflag & OB_RESTRICT_VIEW) continue;
+
+ if((ob->type==OB_MESH) && (ob!=obedit)) {
+ Mesh *me= ob->data;
+
+ if(me->mtface) {
+ MFace *mface= me->mface;
+ MTFace *tface= me->mtface;
+ int a;
+
+ for(a=me->totface; a>0; a--, tface++, mface++) {
+ if(tface->tpage == curimage) {
+ glBegin(GL_LINE_LOOP);
+ glVertex2fv(tface->uv[0]);
+ glVertex2fv(tface->uv[1]);
+ glVertex2fv(tface->uv[2]);
+ if(mface->v4) glVertex2fv(tface->uv[3]);
+ glEnd();
+ }
+ }
+ }
+ }
+ }
+}
+
+/* draws uv's in the image space */
+static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
+{
+ ToolSettings *settings;
+ Mesh *me= obedit->data;
+ EditMesh *em;
+ EditFace *efa, *efa_act;
+ MTFace *tf, *activetf = NULL;
+ DerivedMesh *finaldm, *cagedm;
+ char col1[4], col2[4];
+ float pointsize;
+ int drawfaces, interpedges, lastsel, sel;
+ Image *ima= sima->image;
+
+ em= BKE_mesh_get_editmesh(me);
+ activetf= EM_get_active_mtface(em, &efa_act, NULL, 0); /* will be set to NULL if hidden */
+
+ settings= scene->toolsettings;
+
+ drawfaces= draw_uvs_face_check(scene);
+ if(settings->uv_flag & UV_SYNC_SELECTION)
+ interpedges= (scene->selectmode & SCE_SELECT_VERTEX);
+ else
+ interpedges= (settings->uv_selectmode == UV_SELECT_VERTEX);
+
+ /* draw other uvs */
+ if(sima->flag & SI_DRAW_OTHER)
+ draw_uvs_other(sima, scene, obedit, activetf);
+
+ /* 1. draw shadow mesh */
+
+ if(sima->flag & SI_DRAWSHADOW) {
+ /* first try existing derivedmesh */
+ if(!draw_uvs_dm_shadow(em->derivedFinal)) {
+ /* create one if it does not exist */
+ cagedm = editmesh_get_derived_cage_and_final(scene, obedit, em, &finaldm, CD_MASK_BAREMESH|CD_MASK_MTFACE);
+
+ /* when sync selection is enabled, all faces are drawn (except for hidden)
+ * so if cage is the same as the final, theres no point in drawing this */
+ if(!((settings->uv_flag & UV_SYNC_SELECTION) && (cagedm == finaldm)))
+ draw_uvs_dm_shadow(finaldm);
+
+ /* release derivedmesh again */
+ if(cagedm != finaldm) cagedm->release(cagedm);
+ finaldm->release(finaldm);
+ }
+ }
+
+ /* 2. draw colored faces */
+
+ if(sima->flag & SI_DRAW_STRETCH) {
+ draw_uvs_stretch(sima, scene, em, activetf);
+ }
+ else if(me->drawflag & ME_DRAWFACES) {
+ /* draw transparent faces */
+ UI_GetThemeColor4ubv(TH_FACE, col1);
+ UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ efa->tmp.p = tf;
+ if(tf==activetf) continue; /* important the temp pointer is set above */
+
+ if(uvedit_face_selected(scene, efa, tf))
+ glColor4ubv((GLubyte *)col2);
+ else
+ glColor4ubv((GLubyte *)col1);
+
+ glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
+ glVertex2fv(tf->uv[0]);
+ glVertex2fv(tf->uv[1]);
+ glVertex2fv(tf->uv[2]);
+ if(efa->v4) glVertex2fv(tf->uv[3]);
+ glEnd();
+ }
+ else {
+ if(tf == activetf)
+ activetf= NULL;
+ efa->tmp.p = NULL;
+ }
+ }
+ glDisable(GL_BLEND);
+ }
+ else {
+ /* would be nice to do this within a draw loop but most below are optional, so it would involve too many checks */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ efa->tmp.p = tf;
+ }
+ else {
+ if(tf == activetf)
+ activetf= NULL;
+ efa->tmp.p = NULL;
+ }
+ }
+
+ }
+
+ /* 3. draw active face stippled */
+
+ if(activetf) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ UI_ThemeColor4(TH_EDITMESH_ACTIVE);
+
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(stipple_quarttone);
+
+ glBegin(efa_act->v4? GL_QUADS: GL_TRIANGLES);
+ glVertex2fv(activetf->uv[0]);
+ glVertex2fv(activetf->uv[1]);
+ glVertex2fv(activetf->uv[2]);
+ if(efa_act->v4) glVertex2fv(activetf->uv[3]);
+ glEnd();
+
+ glDisable(GL_POLYGON_STIPPLE);
+ glDisable(GL_BLEND);
+ }
+
+ /* 4. draw edges */
+
+ if(sima->flag & SI_SMOOTH_UV) {
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ switch(sima->dt_uv) {
+ case SI_UVDT_DASH:
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+
+ if(tf) {
+ cpack(0x111111);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2fv(tf->uv[0]);
+ glVertex2fv(tf->uv[1]);
+ glVertex2fv(tf->uv[2]);
+ if(efa->v4) glVertex2fv(tf->uv[3]);
+ glEnd();
+
+ setlinestyle(2);
+ cpack(0x909090);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(tf->uv[0]);
+ glVertex2fv(tf->uv[1]);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(tf->uv[0]);
+ if(efa->v4) glVertex2fv(tf->uv[3]);
+ else glVertex2fv(tf->uv[2]);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(tf->uv[1]);
+ glVertex2fv(tf->uv[2]);
+ if(efa->v4) glVertex2fv(tf->uv[3]);
+ glEnd();
+
+ setlinestyle(0);
+ }
+ }
+ break;
+ case SI_UVDT_BLACK: /* black/white */
+ case SI_UVDT_WHITE:
+ cpack((sima->dt_uv==SI_UVDT_WHITE) ? 0xFFFFFF : 0x0);
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+
+ if(tf) {
+ glBegin(GL_LINE_LOOP);
+ glVertex2fv(tf->uv[0]);
+ glVertex2fv(tf->uv[1]);
+ glVertex2fv(tf->uv[2]);
+ if(efa->v4) glVertex2fv(tf->uv[3]);
+ glEnd();
+ }
+ }
+ break;
+ case SI_UVDT_OUTLINE:
+ glLineWidth(3);
+ cpack(0x0);
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+
+ if(tf) {
+ glBegin(GL_LINE_LOOP);
+ glVertex2fv(tf->uv[0]);
+ glVertex2fv(tf->uv[1]);
+ glVertex2fv(tf->uv[2]);
+ if(efa->v4) glVertex2fv(tf->uv[3]);
+ glEnd();
+ }
+ }
+
+ glLineWidth(1);
+ col2[0] = col2[1] = col2[2] = 192; col2[3] = 255;
+ glColor4ubv((unsigned char *)col2);
+
+ if(me->drawflag & ME_DRAWEDGES) {
+ UI_GetThemeColor4ubv(TH_VERTEX_SELECT, col1);
+ lastsel = sel = 0;
+
+ if(interpedges) {
+ glShadeModel(GL_SMOOTH);
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+
+ if(tf) {
+ glBegin(GL_LINE_LOOP);
+ sel = (uvedit_uv_selected(scene, efa, tf, 0)? 1 : 0);
+ if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
+ glVertex2fv(tf->uv[0]);
+
+ sel = uvedit_uv_selected(scene, efa, tf, 1)? 1 : 0;
+ if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
+ glVertex2fv(tf->uv[1]);
+
+ sel = uvedit_uv_selected(scene, efa, tf, 2)? 1 : 0;
+ if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
+ glVertex2fv(tf->uv[2]);
+
+ if(efa->v4) {
+ sel = uvedit_uv_selected(scene, efa, tf, 3)? 1 : 0;
+ if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
+ glVertex2fv(tf->uv[3]);
+ }
+
+ glEnd();
+ }
+ }
+
+ glShadeModel(GL_FLAT);
+ }
+ else {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+
+ if(tf) {
+ glBegin(GL_LINES);
+ sel = (uvedit_edge_selected(scene, efa, tf, 0)? 1 : 0);
+ if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
+ glVertex2fv(tf->uv[0]);
+ glVertex2fv(tf->uv[1]);
+
+ sel = uvedit_edge_selected(scene, efa, tf, 1)? 1 : 0;
+ if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
+ glVertex2fv(tf->uv[1]);
+ glVertex2fv(tf->uv[2]);
+
+ sel = uvedit_edge_selected(scene, efa, tf, 2)? 1 : 0;
+ if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
+ glVertex2fv(tf->uv[2]);
+
+ if(efa->v4) {
+ glVertex2fv(tf->uv[3]);
+
+ sel = uvedit_edge_selected(scene, efa, tf, 3)? 1 : 0;
+ if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
+ glVertex2fv(tf->uv[3]);
+ }
+
+ glVertex2fv(tf->uv[0]);
+
+ glEnd();
+ }
+ }
+ }
+ }
+ else {
+ /* no nice edges */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+
+ if(tf) {
+ glBegin(GL_LINE_LOOP);
+ glVertex2fv(tf->uv[0]);
+ glVertex2fv(tf->uv[1]);
+ glVertex2fv(tf->uv[2]);
+ if(efa->v4) glVertex2fv(tf->uv[3]);
+ glEnd();
+ }
+ }
+ }
+
+ break;
+ }
+
+ if(sima->flag & SI_SMOOTH_UV) {
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+ }
+
+ /* 5. draw face centers */
+
+ if(drawfaces) {
+ float cent[2];
+
+ pointsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
+ glPointSize(pointsize); // TODO - drawobject.c changes this value after - Investigate!
+
+ /* unselected faces */
+ UI_ThemeColor(TH_WIRE);
+
+ bglBegin(GL_POINTS);
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+
+ if(tf && !uvedit_face_selected(scene, efa, tf)) {
+ uv_center(tf->uv, cent, efa->v4 != NULL);
+ bglVertex2fv(cent);
+ }
+ }
+ bglEnd();
+
+ /* selected faces */
+ UI_ThemeColor(TH_FACE_DOT);
+
+ bglBegin(GL_POINTS);
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+
+ if(tf && uvedit_face_selected(scene, efa, tf)) {
+ uv_center(tf->uv, cent, efa->v4 != NULL);
+ bglVertex2fv(cent);
+ }
+ }
+ bglEnd();
+ }
+
+ /* 6. draw uv vertices */
+
+ if(drawfaces != 2) { /* 2 means Mesh Face Mode */
+ /* unselected uvs */
+ UI_ThemeColor(TH_VERTEX);
+ pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
+ glPointSize(pointsize);
+
+ bglBegin(GL_POINTS);
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+
+ if(tf) {
+ if(!uvedit_uv_selected(scene, efa, tf, 0))
+ bglVertex2fv(tf->uv[0]);
+ if(!uvedit_uv_selected(scene, efa, tf, 1))
+ bglVertex2fv(tf->uv[1]);
+ if(!uvedit_uv_selected(scene, efa, tf, 2))
+ bglVertex2fv(tf->uv[2]);
+ if(efa->v4 && !uvedit_uv_selected(scene, efa, tf, 3))
+ bglVertex2fv(tf->uv[3]);
+ }
+ }
+ bglEnd();
+
+ /* pinned uvs */
+ /* give odd pointsizes odd pin pointsizes */
+ glPointSize(pointsize*2 + (((int)pointsize % 2)? (-1): 0));
+ cpack(0xFF);
+
+ bglBegin(GL_POINTS);
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+
+ if(tf) {
+ if(tf->unwrap & TF_PIN1)
+ bglVertex2fv(tf->uv[0]);
+ if(tf->unwrap & TF_PIN2)
+ bglVertex2fv(tf->uv[1]);
+ if(tf->unwrap & TF_PIN3)
+ bglVertex2fv(tf->uv[2]);
+ if(efa->v4 && (tf->unwrap & TF_PIN4))
+ bglVertex2fv(tf->uv[3]);
+ }
+ }
+ bglEnd();
+
+ /* selected uvs */
+ UI_ThemeColor(TH_VERTEX_SELECT);
+ glPointSize(pointsize);
+
+ bglBegin(GL_POINTS);
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+
+ if(tf) {
+ if(uvedit_uv_selected(scene, efa, tf, 0))
+ bglVertex2fv(tf->uv[0]);
+ if(uvedit_uv_selected(scene, efa, tf, 1))
+ bglVertex2fv(tf->uv[1]);
+ if(uvedit_uv_selected(scene, efa, tf, 2))
+ bglVertex2fv(tf->uv[2]);
+ if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
+ bglVertex2fv(tf->uv[3]);
+ }
+ }
+ bglEnd();
+ }
+
+ glPointSize(1.0);
+ BKE_mesh_end_editmesh(obedit->data, em);
+}
+
+void draw_uvedit_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedit)
+{
+ int show_uvedit, show_uvshadow;
+
+ show_uvedit= ED_space_image_show_uvedit(sima, obedit);
+ show_uvshadow= ED_space_image_show_uvshadow(sima, obedit);
+
+ if(show_uvedit || show_uvshadow) {
+ /* this is basically the same object_handle_update as in the 3d view,
+ * here we have to do it as well for the object we are editing if we
+ * are displaying the final result */
+ if(obedit && (sima->flag & SI_DRAWSHADOW))
+ object_handle_update(scene, obedit);
+
+ if(show_uvshadow)
+ draw_uvs_shadow(sima, obedit);
+ else
+ draw_uvs(sima, scene, obedit);
+
+ if(show_uvedit)
+ drawcursor_sima(sima, ar);
+ }
+}
+
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
new file mode 100644
index 00000000000..cca357c8685
--- /dev/null
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -0,0 +1,81 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_UVEDIT_INTERN_H
+#define ED_UVEDIT_INTERN_H
+
+struct SpaceImage;
+struct EditFace;
+struct MTFace;
+struct Scene;
+struct Image;
+struct Object;
+struct wmOperatorType;
+
+#define UV_SELECT_ALL 1
+#define UV_SELECT_PINNED 2
+
+/* id can be from 0 to 3 */
+#define TF_PIN_MASK(id) (TF_PIN1 << id)
+#define TF_SEL_MASK(id) (TF_SEL1 << id)
+
+/* visibility and selection */
+int uvedit_face_visible_nolocal(struct Scene *scene, struct EditFace *efa);
+int uvedit_face_visible(struct Scene *scene, struct Image *ima, struct EditFace *efa, struct MTFace *tf);
+
+int uvedit_face_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf);
+void uvedit_face_select(struct Scene *scene, struct EditFace *efa, struct MTFace *tf);
+void uvedit_face_deselect(struct Scene *scene, struct EditFace *efa, struct MTFace *tf);
+
+int uvedit_edge_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
+void uvedit_edge_select(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
+void uvedit_edge_deselect(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
+
+int uvedit_uv_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
+void uvedit_uv_select(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
+void uvedit_uv_deselect(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
+
+/* geometric utilities */
+void uv_center(float uv[][2], float cent[2], int quad);
+float uv_area(float uv[][2], int quad);
+void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy);
+
+/* operators */
+void UV_OT_average_islands_scale(struct wmOperatorType *ot);
+void UV_OT_cube_project(struct wmOperatorType *ot);
+void UV_OT_cylinder_project(struct wmOperatorType *ot);
+void UV_OT_from_view(struct wmOperatorType *ot);
+void UV_OT_mapping_menu(struct wmOperatorType *ot);
+void UV_OT_minimize_stretch(struct wmOperatorType *ot);
+void UV_OT_pack_islands(struct wmOperatorType *ot);
+void UV_OT_reset(struct wmOperatorType *ot);
+void UV_OT_sphere_project(struct wmOperatorType *ot);
+void UV_OT_unwrap(struct wmOperatorType *ot);
+
+#endif /* ED_UVEDIT_INTERN_H */
+
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
new file mode 100644
index 00000000000..0b82efda7ab
--- /dev/null
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -0,0 +1,3147 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_report.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_transform.h"
+
+#include "ED_image.h"
+#include "ED_mesh.h"
+#include "ED_screen.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_view2d.h"
+
+#include "uvedit_intern.h"
+
+/************************* state testing ************************/
+
+int ED_uvedit_test(Object *obedit)
+{
+ EditMesh *em;
+ int ret;
+
+ if(obedit->type != OB_MESH)
+ return 0;
+
+ em = BKE_mesh_get_editmesh(obedit->data);
+ ret = EM_texFaceCheck(em);
+ BKE_mesh_end_editmesh(obedit->data, em);
+
+ return ret;
+}
+
+/************************* assign image ************************/
+
+void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *previma)
+{
+ EditMesh *em;
+ EditFace *efa;
+ MTFace *tf;
+ int update= 0;
+
+ /* skip assigning these procedural images... */
+ if(ima && (ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE))
+ return;
+
+ /* verify we have a mesh we can work with */
+ if(!obedit || (obedit->type != OB_MESH))
+ return;
+
+ em= BKE_mesh_get_editmesh(((Mesh*)obedit->data));
+ if(!em || !em->faces.first) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return;
+ }
+
+ /* ensure we have a uv layer */
+ if(!CustomData_has_layer(&em->fdata, CD_MTFACE)) {
+ EM_add_data_layer(em, &em->fdata, CD_MTFACE);
+ update= 1;
+ }
+
+ /* now assign to all visible faces */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, previma, efa, tf)) {
+ if(ima) {
+ tf->tpage= ima;
+ tf->mode |= TF_TEX;
+
+ if(ima->tpageflag & IMA_TILES) tf->mode |= TF_TILES;
+ else tf->mode &= ~TF_TILES;
+
+ if(ima->id.us==0) id_us_plus(&ima->id);
+ else id_lib_extern(&ima->id);
+ }
+ else {
+ tf->tpage= NULL;
+ tf->mode &= ~TF_TEX;
+ }
+
+ update = 1;
+ }
+ }
+
+ /* and update depdency graph */
+ if(update)
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+}
+
+/* dotile - 1, set the tile flag (from the space image)
+ * 2, set the tile index for the faces. */
+void ED_uvedit_set_tile(bContext *C, Scene *scene, Object *obedit, Image *ima, int curtile, int dotile)
+{
+ EditMesh *em;
+ EditFace *efa;
+ MTFace *tf;
+
+ /* verify if we have something to do */
+ if(!ima || !ED_uvedit_test(obedit))
+ return;
+
+ /* skip assigning these procedural images... */
+ if(ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE)
+ return;
+
+ em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(efa->h==0 && efa->f & SELECT) {
+ if(dotile==1) {
+ /* set tile flag */
+ if(ima->tpageflag & IMA_TILES)
+ tf->mode |= TF_TILES;
+ else
+ tf->mode &= ~TF_TILES;
+ }
+ else if(dotile==2)
+ tf->tile= curtile; /* set tile index */
+ }
+ }
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+ BKE_mesh_end_editmesh(obedit->data, em);
+}
+
+/*********************** space conversion *********************/
+
+static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist)
+{
+ int width, height;
+
+ ED_space_image_size(sima, &width, &height);
+
+ dist[0]= pixeldist/width;
+ dist[1]= pixeldist/height;
+}
+
+/*************** visibility and selection utilities **************/
+
+int uvedit_face_visible_nolocal(Scene *scene, EditFace *efa)
+{
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION)
+ return (efa->h==0);
+ else
+ return (efa->h==0 && (efa->f & SELECT));
+}
+
+int uvedit_face_visible(Scene *scene, Image *ima, EditFace *efa, MTFace *tf)
+{
+ if(scene->toolsettings->uv_flag & UV_SHOW_SAME_IMAGE)
+ return (tf->tpage==ima)? uvedit_face_visible_nolocal(scene, efa): 0;
+ else
+ return uvedit_face_visible_nolocal(scene, efa);
+}
+
+int uvedit_face_selected(Scene *scene, EditFace *efa, MTFace *tf)
+{
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION)
+ return (efa->f & SELECT);
+ else
+ return (!(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) &&(!efa->v4 || tf->flag & TF_SEL4));
+}
+
+void uvedit_face_select(Scene *scene, EditFace *efa, MTFace *tf)
+{
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION)
+ EM_select_face(efa, 1);
+ else
+ tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+}
+
+void uvedit_face_deselect(Scene *scene, EditFace *efa, MTFace *tf)
+{
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION)
+ EM_select_face(efa, 0);
+ else
+ tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+}
+
+int uvedit_edge_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
+{
+ int nvert= (efa->v4)? 4: 3;
+
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->selectmode == SCE_SELECT_FACE)
+ return (efa->f & SELECT);
+ else if(scene->selectmode == SCE_SELECT_EDGE)
+ return (*(&efa->e1 + i))->f & SELECT;
+ else
+ return (((efa->v1 + i)->f & SELECT) && ((efa->v1 + (i+1)%nvert)->f & SELECT));
+ }
+ else
+ return (tf->flag & TF_SEL_MASK(i)) && (tf->flag & TF_SEL_MASK((i+1)%nvert));
+}
+
+void uvedit_edge_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
+{
+ int nvert= (efa->v4)? 4: 3;
+
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->selectmode == SCE_SELECT_FACE)
+ EM_select_face(efa, 1);
+ else if(scene->selectmode == SCE_SELECT_EDGE)
+ EM_select_edge((*(&efa->e1 + i)), 1);
+ else {
+ (efa->v1 + i)->f |= SELECT;
+ (efa->v1 + (i+1)%nvert)->f |= SELECT;
+ }
+ }
+ else
+ tf->flag |= TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert);
+}
+
+void uvedit_edge_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
+{
+ int nvert= (efa->v4)? 4: 3;
+
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->selectmode == SCE_SELECT_FACE)
+ EM_select_face(efa, 0);
+ else if(scene->selectmode == SCE_SELECT_EDGE)
+ EM_select_edge((*(&efa->e1 + i)), 0);
+ else {
+ (efa->v1 + i)->f &= ~SELECT;
+ (efa->v1 + (i+1)%nvert)->f &= ~SELECT;
+ }
+ }
+ else
+ tf->flag &= ~(TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert));
+}
+
+int uvedit_uv_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
+{
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->selectmode == SCE_SELECT_FACE)
+ return (efa->f & SELECT);
+ else
+ return (*(&efa->v1 + i))->f & SELECT;
+ }
+ else
+ return tf->flag & TF_SEL_MASK(i);
+}
+
+void uvedit_uv_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
+{
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->selectmode == SCE_SELECT_FACE)
+ EM_select_face(efa, 1);
+ else
+ (*(&efa->v1 + i))->f |= SELECT;
+ }
+ else
+ tf->flag |= TF_SEL_MASK(i);
+}
+
+void uvedit_uv_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
+{
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->selectmode == SCE_SELECT_FACE)
+ EM_select_face(efa, 0);
+ else
+ (*(&efa->v1 + i))->f &= ~SELECT;
+ }
+ else
+ tf->flag &= ~TF_SEL_MASK(i);
+}
+
+/*********************** geometric utilities ***********************/
+
+void uv_center(float uv[][2], float cent[2], int quad)
+{
+ if(quad) {
+ cent[0] = (uv[0][0] + uv[1][0] + uv[2][0] + uv[3][0]) / 4.0;
+ cent[1] = (uv[0][1] + uv[1][1] + uv[2][1] + uv[3][1]) / 4.0;
+ }
+ else {
+ cent[0] = (uv[0][0] + uv[1][0] + uv[2][0]) / 3.0;
+ cent[1] = (uv[0][1] + uv[1][1] + uv[2][1]) / 3.0;
+ }
+}
+
+float uv_area(float uv[][2], int quad)
+{
+ if(quad)
+ return AreaF2Dfl(uv[0], uv[1], uv[2]) + AreaF2Dfl(uv[0], uv[2], uv[3]);
+ else
+ return AreaF2Dfl(uv[0], uv[1], uv[2]);
+}
+
+void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy)
+{
+ uv[0][0] = uv_orig[0][0]*aspx;
+ uv[0][1] = uv_orig[0][1]*aspy;
+
+ uv[1][0] = uv_orig[1][0]*aspx;
+ uv[1][1] = uv_orig[1][1]*aspy;
+
+ uv[2][0] = uv_orig[2][0]*aspx;
+ uv[2][1] = uv_orig[2][1]*aspy;
+
+ uv[3][0] = uv_orig[3][0]*aspx;
+ uv[3][1] = uv_orig[3][1]*aspy;
+}
+
+int ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float *min, float *max)
+{
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tf;
+ int sel;
+
+ INIT_MINMAX2(min, max);
+
+ sel= 0;
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ if(uvedit_uv_selected(scene, efa, tf, 0)) { DO_MINMAX2(tf->uv[0], min, max); sel = 1; }
+ if(uvedit_uv_selected(scene, efa, tf, 1)) { DO_MINMAX2(tf->uv[1], min, max); sel = 1; }
+ if(uvedit_uv_selected(scene, efa, tf, 2)) { DO_MINMAX2(tf->uv[2], min, max); sel = 1; }
+ if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3))) { DO_MINMAX2(tf->uv[3], min, max); sel = 1; }
+ }
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return sel;
+}
+
+int uvedit_center(Scene *scene, Image *ima, Object *obedit, float *cent, int mode)
+{
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tf;
+ float min[2], max[2];
+ int change= 0;
+
+ if(mode==0) {
+ if(ED_uvedit_minmax(scene, ima, obedit, min, max))
+ change = 1;
+ }
+ else if(mode==1) {
+ INIT_MINMAX2(min, max);
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ if(uvedit_uv_selected(scene, efa, tf, 0)) { DO_MINMAX2(tf->uv[0], min, max); change= 1;}
+ if(uvedit_uv_selected(scene, efa, tf, 1)) { DO_MINMAX2(tf->uv[1], min, max); change= 1;}
+ if(uvedit_uv_selected(scene, efa, tf, 2)) { DO_MINMAX2(tf->uv[2], min, max); change= 1;}
+ if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3))) { DO_MINMAX2(tf->uv[3], min, max); change= 1;}
+ }
+ }
+ }
+
+ if(change) {
+ cent[0]= (min[0]+max[0])/2.0;
+ cent[1]= (min[1]+max[1])/2.0;
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return 1;
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return 0;
+}
+
+/************************** find nearest ****************************/
+
+typedef struct NearestHit {
+ EditFace *efa;
+ MTFace *tf;
+
+ int vert, uv;
+ int edge, vert2;
+} NearestHit;
+
+static void find_nearest_uv_edge(Scene *scene, Image *ima, EditMesh *em, float co[2], NearestHit *hit)
+{
+ MTFace *tf;
+ EditFace *efa;
+ EditVert *eve;
+ float mindist, dist;
+ int i, nverts;
+
+ mindist= 1e10f;
+ memset(hit, 0, sizeof(*hit));
+
+ for(i=0, eve=em->verts.first; eve; eve=eve->next, i++)
+ eve->tmp.l = i;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ nverts= efa->v4? 4: 3;
+
+ for(i=0; i<nverts; i++) {
+ dist= PdistVL2Dfl(co, tf->uv[i], tf->uv[(i+1)%nverts]);
+
+ if(dist < mindist) {
+ hit->tf= tf;
+ hit->efa= efa;
+ hit->edge= i;
+ mindist= dist;
+
+ hit->vert= (*(&efa->v1 + i))->tmp.l;
+ hit->vert2= (*(&efa->v1 + ((i+1)%nverts)))->tmp.l;
+ }
+ }
+ }
+ }
+}
+
+static void find_nearest_uv_face(Scene *scene, Image *ima, EditMesh *em, float co[2], NearestHit *hit)
+{
+ MTFace *tf;
+ EditFace *efa;
+ float mindist, dist, cent[2];
+ int i, nverts;
+
+ mindist= 1e10f;
+ memset(hit, 0, sizeof(*hit));
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ nverts= efa->v4? 4: 3;
+ cent[0]= cent[1]= 0.0f;
+
+ for(i=0; i<nverts; i++) {
+ cent[0] += tf->uv[i][0];
+ cent[1] += tf->uv[i][1];
+ }
+
+ cent[0] /= nverts;
+ cent[1] /= nverts;
+ dist= fabs(co[0]- cent[0]) + fabs(co[1]- cent[1]);
+
+ if(dist < mindist) {
+ hit->tf= tf;
+ hit->efa= efa;
+ mindist= dist;
+ }
+ }
+ }
+}
+
+static int nearest_uv_between(MTFace *tf, int nverts, int id, float co[2], float uv[2])
+{
+ float m[3], v1[3], v2[3], c1, c2;
+ int id1, id2;
+
+ id1= (id+nverts-1)%nverts;
+ id2= (id+nverts+1)%nverts;
+
+ m[0]= co[0]-uv[0];
+ m[1]= co[1]-uv[1];
+ Vec2Subf(v1, tf->uv[id1], tf->uv[id]);
+ Vec2Subf(v2, tf->uv[id2], tf->uv[id]);
+
+ /* m and v2 on same side of v-v1? */
+ c1= v1[0]*m[1] - v1[1]*m[0];
+ c2= v1[0]*v2[1] - v1[1]*v2[0];
+
+ if(c1*c2 < 0.0f)
+ return 0;
+
+ /* m and v1 on same side of v-v2? */
+ c1= v2[0]*m[1] - v2[1]*m[0];
+ c2= v2[0]*v1[1] - v2[1]*v1[0];
+
+ return (c1*c2 >= 0.0f);
+}
+
+static void find_nearest_uv_vert(Scene *scene, Image *ima, EditMesh *em, float co[2], float penalty[2], NearestHit *hit)
+{
+ EditFace *efa;
+ EditVert *eve;
+ MTFace *tf;
+ float mindist, dist;
+ int i, nverts;
+
+ mindist= 1e10f;
+ memset(hit, 0, sizeof(*hit));
+
+ for(i=0, eve=em->verts.first; eve; eve=eve->next, i++)
+ eve->tmp.l = i;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ nverts= efa->v4? 4: 3;
+
+ for(i=0; i<nverts; i++) {
+ if(penalty && uvedit_uv_selected(scene, efa, tf, i))
+ dist= fabs(co[0]-tf->uv[i][0])+penalty[0] + fabs(co[1]-tf->uv[i][1])+penalty[1];
+ else
+ dist= fabs(co[0]-tf->uv[i][0]) + fabs(co[1]-tf->uv[i][1]);
+
+ if(dist<=mindist) {
+ if(dist==mindist)
+ if(!nearest_uv_between(tf, nverts, i, co, tf->uv[i]))
+ continue;
+
+ mindist= dist;
+
+ hit->uv= i;
+ hit->tf= tf;
+ hit->efa= efa;
+
+ hit->vert= (*(&efa->v1 + i))->tmp.l;
+ }
+ }
+ }
+ }
+}
+
+int ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, float co[2], float uv[2])
+{
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tf;
+ float mindist, dist;
+ int i, nverts, found= 0;
+
+ mindist= 1e10f;
+ uv[0]= co[0];
+ uv[1]= co[1];
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ nverts= efa->v4? 4: 3;
+
+ for(i=0; i<nverts; i++) {
+ dist= fabs(co[0]-tf->uv[i][0]) + fabs(co[1]-tf->uv[i][1]);
+
+ if(dist<=mindist) {
+ mindist= dist;
+
+ uv[0]= tf->uv[i][0];
+ uv[1]= tf->uv[i][1];
+ found= 1;
+ }
+ }
+ }
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return found;
+}
+
+/*********************** loop select ***********************/
+
+static void uv_vertex_loop_flag(UvMapVert *first)
+{
+ UvMapVert *iterv;
+ int count= 0;
+
+ for(iterv=first; iterv; iterv=iterv->next) {
+ if(iterv->separate && iterv!=first)
+ break;
+
+ count++;
+ }
+
+ if(count < 5)
+ first->flag= 1;
+}
+
+static UvMapVert *uv_vertex_map_get(UvVertMap *vmap, EditFace *efa, int a)
+{
+ UvMapVert *iterv, *first;
+
+ first= EM_get_uv_map_vert(vmap, (*(&efa->v1 + a))->tmp.l);
+
+ for(iterv=first; iterv; iterv=iterv->next) {
+ if(iterv->separate)
+ first= iterv;
+ if(iterv->f == efa->tmp.l)
+ return first;
+ }
+
+ return NULL;
+}
+
+static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface)
+{
+ UvMapVert *iterv1, *iterv2;
+ EditFace *efa;
+ int tot = 0;
+
+ /* count number of faces this edge has */
+ for(iterv1=first1; iterv1; iterv1=iterv1->next) {
+ if(iterv1->separate && iterv1 != first1)
+ break;
+
+ for(iterv2=first2; iterv2; iterv2=iterv2->next) {
+ if(iterv2->separate && iterv2 != first2)
+ break;
+
+ if(iterv1->f == iterv2->f) {
+ /* if face already tagged, don't do this edge */
+ efa= EM_get_face_for_index(iterv1->f);
+ if(efa->f1)
+ return 0;
+
+ tot++;
+ break;
+ }
+ }
+ }
+
+ if(*totface == 0) /* start edge */
+ *totface= tot;
+ else if(tot != *totface) /* check for same number of faces as start edge */
+ return 0;
+
+ /* tag the faces */
+ for(iterv1=first1; iterv1; iterv1=iterv1->next) {
+ if(iterv1->separate && iterv1 != first1)
+ break;
+
+ for(iterv2=first2; iterv2; iterv2=iterv2->next) {
+ if(iterv2->separate && iterv2 != first2)
+ break;
+
+ if(iterv1->f == iterv2->f) {
+ efa= EM_get_face_for_index(iterv1->f);
+ efa->f1= 1;
+ break;
+ }
+ }
+ }
+
+ return 1;
+}
+
+static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *hit, float limit[2], int extend)
+{
+ EditVert *eve;
+ EditFace *efa;
+ MTFace *tf;
+ UvVertMap *vmap;
+ UvMapVert *iterv1, *iterv2;
+ int a, count, looking, nverts, starttotf, select;
+
+ /* setup */
+ EM_init_index_arrays(em, 0, 0, 1);
+ vmap= EM_make_uv_vert_map(em, 0, 0, limit);
+
+ for(count=0, eve=em->verts.first; eve; count++, eve= eve->next)
+ eve->tmp.l = count;
+
+ for(count=0, efa= em->faces.first; efa; count++, efa= efa->next) {
+ if(!extend) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ uvedit_face_deselect(scene, efa, tf);
+ }
+
+ efa->tmp.l= count;
+ efa->f1= 0;
+ }
+
+ /* set flags for first face and verts */
+ nverts= (hit->efa->v4)? 4: 3;
+ iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge);
+ iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts);
+ uv_vertex_loop_flag(iterv1);
+ uv_vertex_loop_flag(iterv2);
+
+ starttotf= 0;
+ uv_edge_tag_faces(iterv1, iterv2, &starttotf);
+
+ /* sorry, first edge isnt even ok */
+ if(iterv1->flag==0 && iterv2->flag==0) looking= 0;
+ else looking= 1;
+
+ /* iterate */
+ while(looking) {
+ looking= 0;
+
+ /* find correct valence edges which are not tagged yet, but connect to tagged one */
+ for(efa= em->faces.first; efa; efa=efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(!efa->f1 && uvedit_face_visible(scene, ima, efa, tf)) {
+ nverts= (efa->v4)? 4: 3;
+ for(a=0; a<nverts; a++) {
+ /* check face not hidden and not tagged */
+ iterv1= uv_vertex_map_get(vmap, efa, a);
+ iterv2= uv_vertex_map_get(vmap, efa, (a+1)%nverts);
+
+ /* check if vertex is tagged and has right valence */
+ if(iterv1->flag || iterv2->flag) {
+ if(uv_edge_tag_faces(iterv1, iterv2, &starttotf)) {
+ looking= 1;
+ efa->f1= 1;
+
+ uv_vertex_loop_flag(iterv1);
+ uv_vertex_loop_flag(iterv2);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* do the actual select/deselect */
+ nverts= (hit->efa->v4)? 4: 3;
+ iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge);
+ iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts);
+ iterv1->flag= 1;
+ iterv2->flag= 1;
+
+ if(extend) {
+ tf= CustomData_em_get(&em->fdata, hit->efa->data, CD_MTFACE);
+
+ if(uvedit_uv_selected(scene, hit->efa, tf, hit->edge) && uvedit_uv_selected(scene, hit->efa, tf, hit->edge))
+ select= 0;
+ else
+ select= 1;
+ }
+ else
+ select= 1;
+
+ for(efa= em->faces.first; efa; efa=efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ nverts= (efa->v4)? 4: 3;
+ for(a=0; a<nverts; a++) {
+ iterv1= uv_vertex_map_get(vmap, efa, a);
+
+ if(iterv1->flag) {
+ if(select) uvedit_uv_select(scene, efa, tf, a);
+ else uvedit_uv_deselect(scene, efa, tf, a);
+ }
+ }
+ }
+
+ /* cleanup */
+ EM_free_uv_vert_map(vmap);
+ EM_free_index_arrays();
+
+ return (select)? 1: -1;
+}
+
+/*********************** linked select ***********************/
+
+static void select_linked(Scene *scene, Image *ima, EditMesh *em, float limit[2], NearestHit *hit, int extend)
+{
+ EditFace *efa;
+ MTFace *tf;
+ UvVertMap *vmap;
+ UvMapVert *vlist, *iterv, *startv;
+ int a, i, nverts, j, stacksize= 0, *stack;
+ char *flag;
+
+ vmap= EM_make_uv_vert_map(em, 1, 1, limit);
+ if(vmap == NULL)
+ return;
+
+ stack= MEM_mallocN(sizeof(*stack)* BLI_countlist(&em->faces), "UvLinkStack");
+ flag= MEM_callocN(sizeof(*flag)*BLI_countlist(&em->faces), "UvLinkFlag");
+
+ if(!hit) {
+ for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) {
+ stack[stacksize]= a;
+ stacksize++;
+ flag[a]= 1;
+ }
+ }
+ }
+ }
+ else {
+ for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
+ if(efa == hit->efa) {
+ stack[stacksize]= a;
+ stacksize++;
+ flag[a]= 1;
+ break;
+ }
+ }
+ }
+
+ while(stacksize > 0) {
+ stacksize--;
+ a= stack[stacksize];
+
+ for(j=0, efa= em->faces.first; efa; efa= efa->next, j++)
+ if(j==a)
+ break;
+
+ nverts= efa->v4? 4: 3;
+
+ for(i=0; i<nverts; i++) {
+ /* make_uv_vert_map_EM sets verts tmp.l to the indicies */
+ vlist= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l);
+
+ startv= vlist;
+
+ for(iterv=vlist; iterv; iterv=iterv->next) {
+ if(iterv->separate)
+ startv= iterv;
+ if(iterv->f == a)
+ break;
+ }
+
+ for(iterv=startv; iterv; iterv=iterv->next) {
+ if((startv != iterv) && (iterv->separate))
+ break;
+ else if(!flag[iterv->f]) {
+ flag[iterv->f]= 1;
+ stack[stacksize]= iterv->f;;
+ stacksize++;
+ }
+ }
+ }
+ }
+
+ if(!extend || hit) {
+ for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if(flag[a])
+ tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ else
+ tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ }
+ }
+ else if(extend && hit) {
+ for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
+ if(flag[a]) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if(efa->v4) {
+ if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)))
+ break;
+ }
+ else if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
+ break;
+ }
+ }
+
+ if(efa) {
+ for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
+ if(flag[a]) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ }
+ }
+ }
+ else {
+ for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
+ if(flag[a]) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ }
+ }
+ }
+ }
+
+ MEM_freeN(stack);
+ MEM_freeN(flag);
+ EM_free_uv_vert_map(vmap);
+}
+
+/* ******************** mirror operator **************** */
+
+static int mirror_exec(bContext *C, wmOperator *op)
+{
+ float mat[3][3];
+ int axis;
+
+ Mat3One(mat);
+ axis= RNA_enum_get(op->ptr, "axis");
+
+ if(axis == 'x') {
+ /* XXX initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+ BIF_setSingleAxisConstraint(mat[0], " on X axis");
+ Transform(); */
+ }
+ else {
+ /* XXX initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+ BIF_setSingleAxisConstraint(mat[1], " on Y axis");
+ Transform(); */
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_mirror(wmOperatorType *ot)
+{
+ static EnumPropertyItem axis_items[] = {
+ {'x', "MIRROR_X", "Mirror X", "Mirror UVs over X axis."},
+ {'y', "MIRROR_Y", "Mirror Y", "Mirror UVs over Y axis."},
+ {0, NULL, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "Mirror";
+ ot->idname= "UV_OT_mirror";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= mirror_exec;
+ ot->poll= ED_operator_uvedit;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "axis", axis_items, 'x', "Axis", "Axis to mirror UV locations over.");
+}
+
+/* ******************** align operator **************** */
+
+static void weld_align_uv(bContext *C, int tool)
+{
+ Scene *scene;
+ Object *obedit;
+ Image *ima;
+ EditMesh *em;
+ EditFace *efa;
+ MTFace *tf;
+ float cent[2], min[2], max[2];
+
+ scene= CTX_data_scene(C);
+ obedit= CTX_data_edit_object(C);
+ em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ ima= CTX_data_edit_image(C);
+
+ INIT_MINMAX2(min, max);
+
+ if(tool == 'a') {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ if(uvedit_uv_selected(scene, efa, tf, 0))
+ DO_MINMAX2(tf->uv[0], min, max)
+ if(uvedit_uv_selected(scene, efa, tf, 1))
+ DO_MINMAX2(tf->uv[1], min, max)
+ if(uvedit_uv_selected(scene, efa, tf, 2))
+ DO_MINMAX2(tf->uv[2], min, max)
+ if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
+ DO_MINMAX2(tf->uv[3], min, max)
+ }
+ }
+
+ tool= (max[0]-min[0] >= max[1]-min[1])? 'y': 'x';
+ }
+
+ uvedit_center(scene, ima, obedit, cent, 0);
+
+ if(tool == 'x' || tool == 'w') {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ if(uvedit_uv_selected(scene, efa, tf, 0))
+ tf->uv[0][0]= cent[0];
+ if(uvedit_uv_selected(scene, efa, tf, 1))
+ tf->uv[1][0]= cent[0];
+ if(uvedit_uv_selected(scene, efa, tf, 2))
+ tf->uv[2][0]= cent[0];
+ if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
+ tf->uv[3][0]= cent[0];
+ }
+ }
+ }
+
+ if(tool == 'y' || tool == 'w') {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ if(uvedit_uv_selected(scene, efa, tf, 0))
+ tf->uv[0][1]= cent[1];
+ if(uvedit_uv_selected(scene, efa, tf, 1))
+ tf->uv[1][1]= cent[1];
+ if(uvedit_uv_selected(scene, efa, tf, 2))
+ tf->uv[2][1]= cent[1];
+ if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
+ tf->uv[3][1]= cent[1];
+ }
+ }
+ }
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+}
+
+static int align_exec(bContext *C, wmOperator *op)
+{
+ weld_align_uv(C, RNA_enum_get(op->ptr, "axis"));
+
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_align(wmOperatorType *ot)
+{
+ static EnumPropertyItem axis_items[] = {
+ {'a', "ALIGN_AUTO", "Align Auto", "Automatically choose the axis on which there is most alignment already."},
+ {'x', "ALIGN_X", "Align X", "Align UVs on X axis."},
+ {'y', "ALIGN_Y", "Align Y", "Align UVs on Y axis."},
+ {0, NULL, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "Align";
+ ot->idname= "UV_OT_align";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= align_exec;
+ ot->poll= ED_operator_uvedit;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "axis", axis_items, 'a', "Axis", "Axis to align UV locations on.");
+}
+
+/* ******************** weld operator **************** */
+
+static int weld_exec(bContext *C, wmOperator *op)
+{
+ weld_align_uv(C, 'w');
+
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_weld(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Weld";
+ ot->idname= "UV_OT_weld";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= weld_exec;
+ ot->poll= ED_operator_uvedit;
+}
+
+/* ******************** stitch operator **************** */
+
+/* just for averaging UVs */
+typedef struct UVVertAverage {
+ float uv[2];
+ int count;
+} UVVertAverage;
+
+static int stitch_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima;
+ Scene *scene;
+ Object *obedit;
+ EditMesh *em;
+ EditFace *efa;
+ EditVert *eve;
+ Image *ima;
+ MTFace *tf;
+
+ sima= (SpaceImage*)CTX_wm_space_data(C);
+ scene= CTX_data_scene(C);
+ obedit= CTX_data_edit_object(C);
+ em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ ima= CTX_data_edit_image(C);
+
+ if(RNA_boolean_get(op->ptr, "use_limit")) {
+ UvVertMap *vmap;
+ UvMapVert *vlist, *iterv;
+ float newuv[2], limit[2], pixels;
+ int a, vtot;
+
+ pixels= RNA_float_get(op->ptr, "limit");
+ uvedit_pixel_to_float(sima, limit, pixels);
+
+ EM_init_index_arrays(em, 0, 0, 1);
+ vmap= EM_make_uv_vert_map(em, 1, 0, limit);
+
+ if(vmap == NULL) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ for(a=0, eve= em->verts.first; eve; a++, eve= eve->next) {
+ vlist= EM_get_uv_map_vert(vmap, a);
+
+ while(vlist) {
+ newuv[0]= 0; newuv[1]= 0;
+ vtot= 0;
+
+ for(iterv=vlist; iterv; iterv=iterv->next) {
+ if((iterv != vlist) && iterv->separate)
+ break;
+
+ efa = EM_get_face_for_index(iterv->f);
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_uv_selected(scene, efa, tf, iterv->tfindex)) {
+ newuv[0] += tf->uv[iterv->tfindex][0];
+ newuv[1] += tf->uv[iterv->tfindex][1];
+ vtot++;
+ }
+ }
+
+ if(vtot > 1) {
+ newuv[0] /= vtot; newuv[1] /= vtot;
+
+ for(iterv=vlist; iterv; iterv=iterv->next) {
+ if((iterv != vlist) && iterv->separate)
+ break;
+
+ efa = EM_get_face_for_index(iterv->f);
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_uv_selected(scene, efa, tf, iterv->tfindex)) {
+ tf->uv[iterv->tfindex][0]= newuv[0];
+ tf->uv[iterv->tfindex][1]= newuv[1];
+ }
+ }
+ }
+
+ vlist= iterv;
+ }
+ }
+
+ EM_free_uv_vert_map(vmap);
+ EM_free_index_arrays();
+ }
+ else {
+ UVVertAverage *uv_average, *uvav;
+ int count;
+
+ // index and count verts
+ for(count=0, eve=em->verts.first; eve; count++, eve= eve->next)
+ eve->tmp.l = count;
+
+ uv_average= MEM_callocN(sizeof(UVVertAverage)*count, "Stitch");
+
+ // gather uv averages per vert
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ if(uvedit_uv_selected(scene, efa, tf, 0)) {
+ uvav = uv_average + efa->v1->tmp.l;
+ uvav->count++;
+ uvav->uv[0] += tf->uv[0][0];
+ uvav->uv[1] += tf->uv[0][1];
+ }
+
+ if(uvedit_uv_selected(scene, efa, tf, 1)) {
+ uvav = uv_average + efa->v2->tmp.l;
+ uvav->count++;
+ uvav->uv[0] += tf->uv[1][0];
+ uvav->uv[1] += tf->uv[1][1];
+ }
+
+ if(uvedit_uv_selected(scene, efa, tf, 2)) {
+ uvav = uv_average + efa->v3->tmp.l;
+ uvav->count++;
+ uvav->uv[0] += tf->uv[2][0];
+ uvav->uv[1] += tf->uv[2][1];
+ }
+
+ if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) {
+ uvav = uv_average + efa->v4->tmp.l;
+ uvav->count++;
+ uvav->uv[0] += tf->uv[3][0];
+ uvav->uv[1] += tf->uv[3][1];
+ }
+ }
+ }
+
+ // apply uv welding
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ if(uvedit_uv_selected(scene, efa, tf, 0)) {
+ uvav = uv_average + efa->v1->tmp.l;
+ tf->uv[0][0] = uvav->uv[0]/uvav->count;
+ tf->uv[0][1] = uvav->uv[1]/uvav->count;
+ }
+
+ if(uvedit_uv_selected(scene, efa, tf, 1)) {
+ uvav = uv_average + efa->v2->tmp.l;
+ tf->uv[1][0] = uvav->uv[0]/uvav->count;
+ tf->uv[1][1] = uvav->uv[1]/uvav->count;
+ }
+
+ if(uvedit_uv_selected(scene, efa, tf, 2)) {
+ uvav = uv_average + efa->v3->tmp.l;
+ tf->uv[2][0] = uvav->uv[0]/uvav->count;
+ tf->uv[2][1] = uvav->uv[1]/uvav->count;
+ }
+
+ if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) {
+ uvav = uv_average + efa->v4->tmp.l;
+ tf->uv[3][0] = uvav->uv[0]/uvav->count;
+ tf->uv[3][1] = uvav->uv[1]/uvav->count;
+ }
+ }
+ }
+
+ MEM_freeN(uv_average);
+ }
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_stitch(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Stitch";
+ ot->idname= "UV_OT_stitch";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= stitch_exec;
+ ot->poll= ED_operator_uvedit;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "use_limit", 1, "Use Limit", "Stitch UVs within a specified limit distance.");
+ RNA_def_float(ot->srna, "limit", 20.0, 0.0f, FLT_MAX, "Limit", "Limit distance in image pixels.", -FLT_MAX, FLT_MAX);
+}
+
+/* ******************** (de)select all operator **************** */
+
+static int select_inverse_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene;
+ Object *obedit;
+ EditMesh *em;
+ EditFace *efa;
+ Image *ima;
+ MTFace *tf;
+
+ scene= CTX_data_scene(C);
+ obedit= CTX_data_edit_object(C);
+ em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ ima= CTX_data_edit_image(C);
+
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ EM_select_swap(em);
+ }
+ else {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ tf->flag ^= TF_SEL1;
+ tf->flag ^= TF_SEL2;
+ tf->flag ^= TF_SEL3;
+ if(efa->v4) tf->flag ^= TF_SEL4;
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_select_invert(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Invert";
+ ot->idname= "UV_OT_select_invert";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= select_inverse_exec;
+ ot->poll= ED_operator_uvedit;
+}
+
+/* ******************** (de)select all operator **************** */
+
+static int de_select_all_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene;
+ Object *obedit;
+ EditMesh *em;
+ EditFace *efa;
+ Image *ima;
+ MTFace *tf;
+ int sel;
+
+ scene= CTX_data_scene(C);
+ obedit= CTX_data_edit_object(C);
+ em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ ima= CTX_data_edit_image(C);
+
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ EM_toggle_select_all(em);
+ }
+ else {
+ sel= 0;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ if(tf->flag & (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4)) {
+ sel= 1;
+ break;
+ }
+ }
+ }
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ if(efa->v4) {
+ if(sel) tf->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
+ else tf->flag |= (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
+ }
+ else {
+ if(sel) tf->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
+ else tf->flag |= (TF_SEL1+TF_SEL2+TF_SEL3);
+ }
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_select_all_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select or Deselect All";
+ ot->idname= "UV_OT_select_all_toggle";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= de_select_all_exec;
+ ot->poll= ED_operator_uvedit;
+}
+
+/* ******************** mouse select operator **************** */
+
+static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], float *uv, int sticky)
+{
+ int i;
+
+ /* this function test if some vertex needs to selected
+ * in addition to the existing ones due to sticky select */
+ if(sticky == SI_STICKY_DISABLE)
+ return 0;
+
+ for(i=0; i<4; i++) {
+ if(hitv[i] == v) {
+ if(sticky == SI_STICKY_LOC) {
+ if(fabs(hituv[i][0]-uv[0]) < limit[0] && fabs(hituv[i][1]-uv[1]) < limit[1])
+ return 1;
+ }
+ else if(sticky == SI_STICKY_VERTEX)
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int mouse_select(bContext *C, float co[2], int extend, int loop)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Image *ima= CTX_data_edit_image(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tf;
+ NearestHit hit;
+ int a, i, select = 1, selectmode, sticky, sync, hitv[4], nvert;
+ int flush = 0; /* 0 == dont flush, 1 == sel, -1 == desel; only use when selection sync is enabled */
+ float limit[2], *hituv[4], penalty[2];
+
+ uvedit_pixel_to_float(sima, limit, 0.05f);
+ uvedit_pixel_to_float(sima, penalty, 5.0f);
+
+ /* retrieve operation mode */
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ sync= 1;
+
+ if(scene->selectmode & SCE_SELECT_FACE)
+ selectmode= UV_SELECT_FACE;
+ else if(scene->selectmode & SCE_SELECT_EDGE)
+ selectmode= UV_SELECT_EDGE;
+ else
+ selectmode= UV_SELECT_VERTEX;
+
+ sticky= SI_STICKY_DISABLE;
+ }
+ else {
+ sync= 0;
+ selectmode= scene->toolsettings->uv_selectmode;
+ sticky= sima->sticky;
+ }
+
+ /* find nearest element */
+ if(loop) {
+ /* find edge */
+ find_nearest_uv_edge(scene, ima, em, co, &hit);
+ if(hit.efa == NULL) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else if(selectmode == UV_SELECT_VERTEX) {
+ /* find vertex */
+ find_nearest_uv_vert(scene, ima, em, co, penalty, &hit);
+ if(hit.efa == NULL) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* mark 1 vertex as being hit */
+ for(i=0; i<4; i++)
+ hitv[i]= 0xFFFFFFFF;
+
+ hitv[hit.uv]= hit.vert;
+ hituv[hit.uv]= hit.tf->uv[hit.uv];
+ }
+ else if(selectmode == UV_SELECT_EDGE) {
+ /* find edge */
+ find_nearest_uv_edge(scene, ima, em, co, &hit);
+ if(hit.efa == NULL) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* mark 2 edge vertices as being hit */
+ for(i=0; i<4; i++)
+ hitv[i]= 0xFFFFFFFF;
+
+ nvert= (hit.efa->v4)? 4: 3;
+
+ hitv[hit.edge]= hit.vert;
+ hitv[(hit.edge+1)%nvert]= hit.vert2;
+ hituv[hit.edge]= hit.tf->uv[hit.edge];
+ hituv[(hit.edge+1)%nvert]= hit.tf->uv[(hit.edge+1)%nvert];
+ }
+ else if(selectmode == UV_SELECT_FACE) {
+ /* find face */
+ find_nearest_uv_face(scene, ima, em, co, &hit);
+ if(hit.efa == NULL) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* make active */
+ EM_set_actFace(em, hit.efa);
+
+ /* mark all face vertices as being hit */
+ for(i=0; i<4; i++)
+ hituv[i]= hit.tf->uv[i];
+
+ hitv[0]= hit.efa->v1->tmp.l;
+ hitv[1]= hit.efa->v2->tmp.l;
+ hitv[2]= hit.efa->v3->tmp.l;
+
+ if(hit.efa->v4) hitv[3]= hit.efa->v4->tmp.l;
+ else hitv[3]= 0xFFFFFFFF;
+ }
+ else if(selectmode == UV_SELECT_ISLAND) {
+ find_nearest_uv_vert(scene, ima, em, co, NULL, &hit);
+
+ if(hit.efa==NULL) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* do selection */
+ if(loop) {
+ flush= select_edgeloop(scene, ima, em, &hit, limit, extend);
+ }
+ else if(selectmode == UV_SELECT_ISLAND) {
+ select_linked(scene, ima, em, limit, &hit, extend);
+ }
+ else if(extend) {
+ if(selectmode == UV_SELECT_VERTEX) {
+ /* (de)select uv vertex */
+ if(uvedit_uv_selected(scene, hit.efa, hit.tf, hit.uv)) {
+ uvedit_uv_deselect(scene, hit.efa, hit.tf, hit.uv);
+ select= 0;
+ }
+ else {
+ uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv);
+ select= 1;
+ }
+ flush = 1;
+ }
+ else if(selectmode == UV_SELECT_EDGE) {
+ /* (de)select edge */
+ if(uvedit_edge_selected(scene, hit.efa, hit.tf, hit.edge)) {
+ uvedit_edge_deselect(scene, hit.efa, hit.tf, hit.edge);
+ select= 0;
+ }
+ else {
+ uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge);
+ select= 1;
+ }
+ flush = 1;
+ }
+ else if(selectmode == UV_SELECT_FACE) {
+ /* (de)select face */
+ if(uvedit_face_selected(scene, hit.efa, hit.tf)) {
+ uvedit_face_deselect(scene, hit.efa, hit.tf);
+ select= 0;
+ }
+ else {
+ uvedit_face_select(scene, hit.efa, hit.tf);
+ select= 1;
+ }
+ flush = -1;
+ }
+
+ /* (de)select sticky uv nodes */
+ if(sticky != SI_STICKY_DISABLE) {
+ EditVert *ev;
+
+ for(a=0, ev=em->verts.first; ev; ev = ev->next, a++)
+ ev->tmp.l = a;
+
+ /* deselect */
+ if(select==0) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
+ uvedit_uv_deselect(scene, efa, tf, 0);
+ if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
+ uvedit_uv_deselect(scene, efa, tf, 1);
+ if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
+ uvedit_uv_deselect(scene, efa, tf, 2);
+ if(efa->v4)
+ if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
+ uvedit_uv_deselect(scene, efa, tf, 3);
+ }
+ }
+ flush = -1;
+ }
+ /* select */
+ else {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
+ uvedit_uv_select(scene, efa, tf, 0);
+ if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
+ uvedit_uv_select(scene, efa, tf, 1);
+ if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
+ uvedit_uv_select(scene, efa, tf, 2);
+ if(efa->v4)
+ if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
+ uvedit_uv_select(scene, efa, tf, 3);
+ }
+ }
+
+ flush = 1;
+ }
+ }
+ }
+ else {
+ /* deselect all */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ uvedit_face_deselect(scene, efa, tf);
+ }
+
+ if(selectmode == UV_SELECT_VERTEX) {
+ /* select vertex */
+ uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv);
+ flush= 1;
+ }
+ else if(selectmode == UV_SELECT_EDGE) {
+ /* select edge */
+ uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge);
+ flush= 1;
+ }
+ else if(selectmode == UV_SELECT_FACE) {
+ /* select face */
+ uvedit_face_select(scene, hit.efa, hit.tf);
+ }
+
+ /* select sticky uvs */
+ if(sticky != SI_STICKY_DISABLE) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ if(sticky == SI_STICKY_DISABLE) continue;
+
+ if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
+ uvedit_uv_select(scene, efa, tf, 0);
+ if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
+ uvedit_uv_select(scene, efa, tf, 1);
+ if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
+ uvedit_uv_select(scene, efa, tf, 2);
+ if(efa->v4)
+ if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
+ uvedit_uv_select(scene, efa, tf, 3);
+
+ flush= 1;
+ }
+ }
+ }
+ }
+
+ if(sync) {
+ /* flush for mesh selection */
+ if(scene->selectmode != SCE_SELECT_FACE) {
+ if(flush==1) EM_select_flush(em);
+ else if(flush==-1) EM_deselect_flush(em);
+ }
+ }
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_PASS_THROUGH|OPERATOR_FINISHED;
+}
+
+static int select_exec(bContext *C, wmOperator *op)
+{
+ float co[2];
+ int extend, loop;
+
+ RNA_float_get_array(op->ptr, "location", co);
+ extend= RNA_boolean_get(op->ptr, "extend");
+ loop= 0;
+
+ return mouse_select(C, co, extend, loop);
+}
+
+static int select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ float co[2];
+ int x, y;
+
+ x= event->x - ar->winrct.xmin;
+ y= event->y - ar->winrct.ymin;
+
+ UI_view2d_region_to_view(&ar->v2d, x, y, &co[0], &co[1]);
+ RNA_float_set_array(op->ptr, "location", co);
+
+ return select_exec(C, op);
+}
+
+void UV_OT_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select";
+ ot->idname= "UV_OT_select";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= select_exec;
+ ot->invoke= select_invoke;
+ ot->poll= ED_operator_uvedit;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", 0,
+ "Extend", "Extend selection rather than clearing the existing selection.");
+ RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
+ "Location", "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds.", -100.0f, 100.0f);
+}
+
+/* ******************** loop select operator **************** */
+
+static int select_loop_exec(bContext *C, wmOperator *op)
+{
+ float co[2];
+ int extend, loop;
+
+ RNA_float_get_array(op->ptr, "location", co);
+ extend= RNA_boolean_get(op->ptr, "extend");
+ loop= 1;
+
+ return mouse_select(C, co, extend, loop);
+}
+
+static int select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ float co[2];
+ int x, y;
+
+ x= event->x - ar->winrct.xmin;
+ y= event->y - ar->winrct.ymin;
+
+ UI_view2d_region_to_view(&ar->v2d, x, y, &co[0], &co[1]);
+ RNA_float_set_array(op->ptr, "location", co);
+
+ return select_loop_exec(C, op);
+}
+
+void UV_OT_select_loop(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Loop Select";
+ ot->idname= "UV_OT_select_loop";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= select_loop_exec;
+ ot->invoke= select_loop_invoke;
+ ot->poll= ED_operator_uvedit;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", 0,
+ "Extend", "Extend selection rather than clearing the existing selection.");
+ RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
+ "Location", "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds.", -100.0f, 100.0f);
+}
+
+/* ******************** linked select operator **************** */
+
+static int select_linked_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Image *ima= CTX_data_edit_image(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ float limit[2];
+ int extend;
+
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled.");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ extend= RNA_boolean_get(op->ptr, "extend");
+ uvedit_pixel_to_float(sima, limit, 0.05f);
+ select_linked(scene, ima, em, limit, NULL, extend);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Linked";
+ ot->idname= "UV_OT_select_linked";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= select_linked_exec;
+ ot->poll= ED_operator_uvedit;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", 0,
+ "Extend", "Extend selection rather than clearing the existing selection.");
+}
+
+/* ******************** unlink selection operator **************** */
+
+static int unlink_selection_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Image *ima= CTX_data_edit_image(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tf;
+
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ BKE_report(op->reports, RPT_ERROR, "Can't unlink selection when sync selection is enabled.");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ if(efa->v4) {
+ if(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4))
+ tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ }
+ else {
+ if(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
+ tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3);
+ }
+ }
+ }
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_unlink_selection(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Unlink Selection";
+ ot->idname= "UV_OT_unlink_selection";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= unlink_selection_exec;
+ ot->poll= ED_operator_uvedit;
+}
+
+/* ******************** border select operator **************** */
+
+/* This function sets the selection on tagged faces, need because settings the
+ * selection a face is done in a number of places but it also needs to respect
+ * the sticky modes for the UV verts, so dealing with the sticky modes is best
+ * done in a seperate function.
+ *
+ * De-selects faces that have been tagged on efa->tmp.l. */
+
+static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Object *obedit, short select)
+{
+ /* Selecting UV Faces with some modes requires us to change
+ * the selection in other faces (depending on the sticky mode).
+ *
+ * This only needs to be done when the Mesh is not used for
+ * selection (so for sticky modes, vertex or location based). */
+
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tf;
+ int nverts, i;
+
+ if((scene->toolsettings->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_VERTEX) {
+ /* Tag all verts as untouched, then touch the ones that have a face center
+ * in the loop and select all MTFace UV's that use a touched vert. */
+ EditVert *eve;
+
+ for(eve= em->verts.first; eve; eve= eve->next)
+ eve->tmp.l = 0;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->tmp.l) {
+ if(efa->v4)
+ efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= efa->v4->tmp.l=1;
+ else
+ efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= 1;
+ }
+ }
+
+ /* now select tagged verts */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ nverts= efa->v4? 4: 3;
+ for(i=0; i<nverts; i++) {
+ if((*(&efa->v1 + i))->tmp.l) {
+ if(select)
+ uvedit_uv_select(scene, efa, tf, i);
+ else
+ uvedit_uv_deselect(scene, efa, tf, i);
+ }
+ }
+ }
+ }
+ else if((scene->toolsettings->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_LOC) {
+ EditFace *efa_vlist;
+ MTFace *tf_vlist;
+ UvMapVert *start_vlist=NULL, *vlist_iter;
+ struct UvVertMap *vmap;
+ float limit[2];
+ int efa_index;
+ //EditVert *eve; /* removed vert counting for now */
+ //int a;
+
+ uvedit_pixel_to_float(sima, limit, 0.05);
+
+ EM_init_index_arrays(em, 0, 0, 1);
+ vmap= EM_make_uv_vert_map(em, 0, 0, limit);
+
+ /* verts are numbered above in make_uv_vert_map_EM, make sure this stays true! */
+ /*for(a=0, eve= em->verts.first; eve; a++, eve= eve->next)
+ eve->tmp.l = a; */
+
+ if(vmap == NULL) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return;
+ }
+
+ for(efa_index=0, efa= em->faces.first; efa; efa_index++, efa= efa->next) {
+ if(efa->tmp.l) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ nverts= efa->v4? 4: 3;
+
+ for(i=0; i<nverts; i++) {
+ if(select)
+ uvedit_uv_select(scene, efa, tf, i);
+ else
+ uvedit_uv_deselect(scene, efa, tf, i);
+
+ vlist_iter= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l);
+
+ while (vlist_iter) {
+ if(vlist_iter->separate)
+ start_vlist = vlist_iter;
+
+ if(efa_index == vlist_iter->f)
+ break;
+
+ vlist_iter = vlist_iter->next;
+ }
+
+ vlist_iter = start_vlist;
+ while (vlist_iter) {
+
+ if(vlist_iter != start_vlist && vlist_iter->separate)
+ break;
+
+ if(efa_index != vlist_iter->f) {
+ efa_vlist = EM_get_face_for_index(vlist_iter->f);
+ tf_vlist = CustomData_em_get(&em->fdata, efa_vlist->data, CD_MTFACE);
+
+ if(select)
+ uvedit_uv_select(scene, efa_vlist, tf_vlist, vlist_iter->tfindex);
+ else
+ uvedit_uv_deselect(scene, efa_vlist, tf_vlist, vlist_iter->tfindex);
+ }
+ vlist_iter = vlist_iter->next;
+ }
+ }
+ }
+ }
+ EM_free_index_arrays();
+ EM_free_uv_vert_map(vmap);
+
+ }
+ else { /* SI_STICKY_DISABLE or scene->toolsettings->uv_flag & UV_SYNC_SELECTION */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->tmp.l) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if(select)
+ uvedit_face_select(scene, efa, tf);
+ else
+ uvedit_face_deselect(scene, efa, tf);
+ }
+ }
+ }
+ BKE_mesh_end_editmesh(obedit->data, em);
+}
+
+static int border_select_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Image *ima= CTX_data_edit_image(C);
+ ARegion *ar= CTX_wm_region(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tface;
+ rcti rect;
+ rctf rectf;
+ int change, pinned, select, faces;
+
+ /* get rectangle from operator */
+ rect.xmin= RNA_int_get(op->ptr, "xmin");
+ rect.ymin= RNA_int_get(op->ptr, "ymin");
+ rect.xmax= RNA_int_get(op->ptr, "xmax");
+ rect.ymax= RNA_int_get(op->ptr, "ymax");
+
+ UI_view2d_region_to_view(&ar->v2d, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
+ UI_view2d_region_to_view(&ar->v2d, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
+
+ /* figure out what to select/deselect */
+ select= (RNA_int_get(op->ptr, "event_type") == LEFTMOUSE); // XXX hardcoded
+ pinned= RNA_boolean_get(op->ptr, "pinned");
+
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION)
+ faces= (scene->selectmode == SCE_SELECT_FACE);
+ else
+ faces= (scene->toolsettings->uv_selectmode == UV_SELECT_FACE);
+
+ /* do actual selection */
+ if(faces && !pinned) {
+ /* handle face selection mode */
+ float cent[2];
+
+ change= 0;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ /* assume not touched */
+ efa->tmp.l = 0;
+ tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if(uvedit_face_visible(scene, ima, efa, tface)) {
+ uv_center(tface->uv, cent, efa->v4 != NULL);
+ if(BLI_in_rctf(&rectf, cent[0], cent[1])) {
+ efa->tmp.l = change = 1;
+ }
+ }
+ }
+
+ /* (de)selects all tagged faces and deals with sticky modes */
+ if(change)
+ uv_faces_do_sticky(C, sima, scene, obedit, select);
+ }
+ else {
+ /* other selection modes */
+ change= 1;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if(uvedit_face_visible(scene, ima, efa, tface)) {
+ if(!pinned || (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) ) {
+ /* UV_SYNC_SELECTION - can't do pinned selection */
+ if(BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) {
+ if(select) uvedit_uv_select(scene, efa, tface, 0);
+ else uvedit_uv_deselect(scene, efa, tface, 0);
+ }
+ if(BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) {
+ if(select) uvedit_uv_select(scene, efa, tface, 1);
+ else uvedit_uv_deselect(scene, efa, tface, 1);
+ }
+ if(BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) {
+ if(select) uvedit_uv_select(scene, efa, tface, 2);
+ else uvedit_uv_deselect(scene, efa, tface, 2);
+ }
+ if(efa->v4 && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) {
+ if(select) uvedit_uv_select(scene, efa, tface, 3);
+ else uvedit_uv_deselect(scene, efa, tface, 3);
+ }
+ }
+ else if(pinned) {
+ if((tface->unwrap & TF_PIN1) &&
+ BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) {
+
+ if(select) uvedit_uv_select(scene, efa, tface, 0);
+ else uvedit_uv_deselect(scene, efa, tface, 0);
+ }
+ if((tface->unwrap & TF_PIN2) &&
+ BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) {
+
+ if(select) uvedit_uv_select(scene, efa, tface, 1);
+ else uvedit_uv_deselect(scene, efa, tface, 1);
+ }
+ if((tface->unwrap & TF_PIN3) &&
+ BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) {
+
+ if(select) uvedit_uv_select(scene, efa, tface, 2);
+ else uvedit_uv_deselect(scene, efa, tface, 2);
+ }
+ if((efa->v4) && (tface->unwrap & TF_PIN4) && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) {
+ if(select) uvedit_uv_select(scene, efa, tface, 3);
+ else uvedit_uv_deselect(scene, efa, tface, 3);
+ }
+ }
+ }
+ }
+ }
+
+ if(change) {
+ /* make sure newly selected vert selection is updated*/
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if(scene->selectmode != SCE_SELECT_FACE) {
+ if(select) EM_select_flush(em);
+ else EM_deselect_flush(em);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+}
+
+void UV_OT_select_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Border Select";
+ ot->idname= "UV_OT_select_border";
+
+ /* api callbacks */
+ ot->invoke= WM_border_select_invoke;
+ ot->exec= border_select_exec;
+ ot->modal= WM_border_select_modal;
+ ot->poll= ED_operator_uvedit;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "pinned", 0, "Pinned", "Border select pinned UVs only.");
+
+ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+}
+
+/* ******************** circle select operator **************** */
+
+static void select_uv_inside_ellipse(SpaceImage *sima, Scene *scene, int select, EditFace *efa, MTFace *tface, int index, float *offset, float *ell, int select_index)
+{
+ /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */
+ float x, y, r2, *uv;
+
+ uv= tface->uv[index];
+
+ x= (uv[0] - offset[0])*ell[0];
+ y= (uv[1] - offset[1])*ell[1];
+
+ r2 = x*x + y*y;
+ if(r2 < 1.0) {
+ if(select) uvedit_uv_select(scene, efa, tface, select_index);
+ else uvedit_uv_deselect(scene, efa, tface, select_index);
+ }
+}
+
+int circle_select_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ ARegion *ar= CTX_wm_region(C);
+ EditFace *efa;
+ MTFace *tface;
+ int x, y, radius, width, height, select;
+ float zoomx, zoomy, offset[2], ellipse[2];
+
+ /* get operator properties */
+ select= (RNA_int_get(op->ptr, "event_type") == LEFTMOUSE); // XXX hardcoded
+ x= RNA_int_get(op->ptr, "x");
+ y= RNA_int_get(op->ptr, "y");
+ radius= RNA_int_get(op->ptr, "radius");
+
+ /* compute ellipse size and location, not a circle since we deal
+ * with non square image. ellipse is normalized, r = 1.0. */
+ ED_space_image_size(sima, &width, &height);
+ ED_space_image_zoom(sima, ar, &zoomx, &zoomy);
+
+ ellipse[0]= width*zoomx/radius;
+ ellipse[1]= height*zoomy/radius;
+
+ UI_view2d_region_to_view(&ar->v2d, x, y, &offset[0], &offset[1]);
+
+ /* do selection */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ select_uv_inside_ellipse(sima, scene, select, efa, tface, 0, offset, ellipse, 0);
+ select_uv_inside_ellipse(sima, scene, select, efa, tface, 1, offset, ellipse, 1);
+ select_uv_inside_ellipse(sima, scene, select, efa, tface, 2, offset, ellipse, 2);
+ if(efa->v4)
+ select_uv_inside_ellipse(sima, scene, select, efa, tface, 3, offset, ellipse, 3);
+ }
+
+ if(select) EM_select_flush(em);
+ else EM_deselect_flush(em);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_circle_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Circle Select";
+ ot->idname= "UV_OT_circle_select";
+
+ /* api callbacks */
+ ot->invoke= WM_gesture_circle_invoke;
+ ot->modal= WM_gesture_circle_modal;
+ ot->exec= circle_select_exec;
+ ot->poll= ED_operator_uvedit;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "radius", 0, INT_MIN, INT_MAX, "Radius", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+}
+
+/* ******************** snap cursor operator **************** */
+
+static void snap_uv_to_pixel(float *uvco, float w, float h)
+{
+ uvco[0] = ((float)((int)((uvco[0]*w) + 0.5f)))/w;
+ uvco[1] = ((float)((int)((uvco[1]*h) + 0.5f)))/h;
+}
+
+static void snap_cursor_to_pixels(SpaceImage *sima, View2D *v2d)
+{
+ int width= 0, height= 0;
+
+ ED_space_image_size(sima, &width, &height);
+ snap_uv_to_pixel(v2d->cursor, width, height);
+}
+
+static int snap_cursor_to_selection(Scene *scene, Image *ima, Object *obedit, View2D *v2d)
+{
+ return uvedit_center(scene, ima, obedit, v2d->cursor, 0);
+}
+
+static int snap_cursor_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Image *ima= CTX_data_edit_image(C);
+ ARegion *ar= CTX_wm_region(C);
+ int change= 0;
+
+ switch(RNA_boolean_get(op->ptr, "target")) {
+ case 0:
+ snap_cursor_to_pixels(sima, &ar->v2d);
+ change= 1;
+ break;
+ case 1:
+ change= snap_cursor_to_selection(scene, ima, obedit, &ar->v2d);
+ break;
+ }
+
+ if(!change)
+ return OPERATOR_CANCELLED;
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_snap_cursor(wmOperatorType *ot)
+{
+ static EnumPropertyItem target_items[] = {
+ {0, "PIXELS", "Pixels", ""},
+ {1, "SELECTION", "Selection", ""},
+ {0, NULL, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "Snap Cursor";
+ ot->idname= "UV_OT_snap_cursor";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= snap_cursor_exec;
+ ot->poll= ED_operator_uvedit;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UV's to.");
+}
+
+/* ******************** snap selection operator **************** */
+
+static int snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, View2D *v2d)
+{
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tface;
+ short change= 0;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if(uvedit_face_visible(scene, ima, efa, tface)) {
+ if(uvedit_uv_selected(scene, efa, tface, 0)) VECCOPY2D(tface->uv[0], v2d->cursor);
+ if(uvedit_uv_selected(scene, efa, tface, 1)) VECCOPY2D(tface->uv[1], v2d->cursor);
+ if(uvedit_uv_selected(scene, efa, tface, 2)) VECCOPY2D(tface->uv[2], v2d->cursor);
+ if(efa->v4)
+ if(uvedit_uv_selected(scene, efa, tface, 3)) VECCOPY2D(tface->uv[3], v2d->cursor);
+
+ change= 1;
+ }
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return change;
+}
+
+static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obedit)
+{
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ EditVert *eve;
+ MTFace *tface;
+ short change = 0;
+ int count = 0;
+ float *coords;
+ short *usercount, users;
+
+ /* set all verts to -1 : an unused index*/
+ for(eve= em->verts.first; eve; eve= eve->next)
+ eve->tmp.l=-1;
+
+ /* index every vert that has a selected UV using it, but only once so as to
+ * get unique indicies and to count how much to malloc */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tface)) {
+ if(uvedit_uv_selected(scene, efa, tface, 0) && efa->v1->tmp.l==-1) efa->v1->tmp.l= count++;
+ if(uvedit_uv_selected(scene, efa, tface, 1) && efa->v2->tmp.l==-1) efa->v2->tmp.l= count++;
+ if(uvedit_uv_selected(scene, efa, tface, 2) && efa->v3->tmp.l==-1) efa->v3->tmp.l= count++;
+ if(efa->v4)
+ if(uvedit_uv_selected(scene, efa, tface, 3) && efa->v4->tmp.l==-1) efa->v4->tmp.l= count++;
+
+ change = 1;
+
+ /* optional speedup */
+ efa->tmp.p = tface;
+ }
+ else
+ efa->tmp.p = NULL;
+ }
+
+ coords = MEM_callocN(sizeof(float)*count*2, "snap to adjacent coords");
+ usercount = MEM_callocN(sizeof(short)*count, "snap to adjacent counts");
+
+ /* add all UV coords from visible, unselected UV coords as well as counting them to average later */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if((tface=(MTFace *)efa->tmp.p)) {
+ /* is this an unselected UV we can snap to? */
+ if(efa->v1->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 0))) {
+ coords[efa->v1->tmp.l*2] += tface->uv[0][0];
+ coords[(efa->v1->tmp.l*2)+1] += tface->uv[0][1];
+ usercount[efa->v1->tmp.l]++;
+ change = 1;
+ }
+ if(efa->v2->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 1))) {
+ coords[efa->v2->tmp.l*2] += tface->uv[1][0];
+ coords[(efa->v2->tmp.l*2)+1] += tface->uv[1][1];
+ usercount[efa->v2->tmp.l]++;
+ change = 1;
+ }
+ if(efa->v3->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 2))) {
+ coords[efa->v3->tmp.l*2] += tface->uv[2][0];
+ coords[(efa->v3->tmp.l*2)+1] += tface->uv[2][1];
+ usercount[efa->v3->tmp.l]++;
+ change = 1;
+ }
+
+ if(efa->v4) {
+ if(efa->v4->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 3))) {
+ coords[efa->v4->tmp.l*2] += tface->uv[3][0];
+ coords[(efa->v4->tmp.l*2)+1] += tface->uv[3][1];
+ usercount[efa->v4->tmp.l]++;
+ change = 1;
+ }
+ }
+ }
+ }
+
+ /* no other verts selected, bail out */
+ if(!change) {
+ MEM_freeN(coords);
+ MEM_freeN(usercount);
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return change;
+ }
+
+ /* copy the averaged unselected UVs back to the selected UVs */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if((tface=(MTFace *)efa->tmp.p)) {
+
+ if( uvedit_uv_selected(scene, efa, tface, 0) &&
+ efa->v1->tmp.l >= 0 &&
+ (users = usercount[efa->v1->tmp.l])
+ ) {
+ tface->uv[0][0] = coords[efa->v1->tmp.l*2] / users;
+ tface->uv[0][1] = coords[(efa->v1->tmp.l*2)+1] / users;
+ }
+
+ if( uvedit_uv_selected(scene, efa, tface, 1) &&
+ efa->v2->tmp.l >= 0 &&
+ (users = usercount[efa->v2->tmp.l])
+ ) {
+ tface->uv[1][0] = coords[efa->v2->tmp.l*2] / users;
+ tface->uv[1][1] = coords[(efa->v2->tmp.l*2)+1] / users;
+ }
+
+ if( uvedit_uv_selected(scene, efa, tface, 2) &&
+ efa->v3->tmp.l >= 0 &&
+ (users = usercount[efa->v3->tmp.l])
+ ) {
+ tface->uv[2][0] = coords[efa->v3->tmp.l*2] / users;
+ tface->uv[2][1] = coords[(efa->v3->tmp.l*2)+1] / users;
+ }
+
+ if(efa->v4) {
+ if( uvedit_uv_selected(scene, efa, tface, 3) &&
+ efa->v4->tmp.l >= 0 &&
+ (users = usercount[efa->v4->tmp.l])
+ ) {
+ tface->uv[3][0] = coords[efa->v4->tmp.l*2] / users;
+ tface->uv[3][1] = coords[(efa->v4->tmp.l*2)+1] / users;
+ }
+ }
+ }
+ }
+
+ MEM_freeN(coords);
+ MEM_freeN(usercount);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return change;
+}
+
+static int snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit)
+{
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ Image *ima= sima->image;
+ EditFace *efa;
+ MTFace *tface;
+ int width= 0, height= 0;
+ float w, h;
+ short change = 0;
+
+ ED_space_image_size(sima, &width, &height);
+ w = (float)width;
+ h = (float)height;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if(uvedit_face_visible(scene, ima, efa, tface)) {
+ if(uvedit_uv_selected(scene, efa, tface, 0)) snap_uv_to_pixel(tface->uv[0], w, h);
+ if(uvedit_uv_selected(scene, efa, tface, 1)) snap_uv_to_pixel(tface->uv[1], w, h);
+ if(uvedit_uv_selected(scene, efa, tface, 2)) snap_uv_to_pixel(tface->uv[2], w, h);
+ if(efa->v4)
+ if(uvedit_uv_selected(scene, efa, tface, 3)) snap_uv_to_pixel(tface->uv[3], w, h);
+
+ change = 1;
+ }
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return change;
+}
+
+static int snap_selection_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Image *ima= CTX_data_edit_image(C);
+ ARegion *ar= CTX_wm_region(C);
+ int change= 0;
+
+ switch(RNA_boolean_get(op->ptr, "target")) {
+ case 0:
+ change= snap_uvs_to_pixels(sima, scene, obedit);
+ break;
+ case 1:
+ change= snap_uvs_to_cursor(scene, ima, obedit, &ar->v2d);
+ break;
+ case 2:
+ change= snap_uvs_to_adjacent_unselected(scene, ima, obedit);
+ break;
+ }
+
+ if(!change)
+ return OPERATOR_CANCELLED;
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_snap_selection(wmOperatorType *ot)
+{
+ static EnumPropertyItem target_items[] = {
+ {0, "PIXELS", "Pixels", ""},
+ {1, "CURSOR", "Cursor", ""},
+ {2, "ADJACENT_UNSELECTED", "Adjacent Unselected", ""},
+ {0, NULL, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "Snap Selection";
+ ot->idname= "UV_OT_snap_selection";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= snap_selection_exec;
+ ot->poll= ED_operator_uvedit;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UV's to.");
+}
+
+/* ******************** pin operator **************** */
+
+static int pin_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Image *ima= CTX_data_edit_image(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tface;
+ int clear= RNA_boolean_get(op->ptr, "clear");
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tface)) {
+ if(!clear) {
+ if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap |= TF_PIN1;
+ if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap |= TF_PIN2;
+ if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap |= TF_PIN3;
+ if(efa->v4)
+ if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap |= TF_PIN4;
+ }
+ else {
+ if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap &= ~TF_PIN1;
+ if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap &= ~TF_PIN2;
+ if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap &= ~TF_PIN3;
+ if(efa->v4)
+ if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap &= ~TF_PIN4;
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_pin(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Pin";
+ ot->idname= "UV_OT_pin";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= pin_exec;
+ ot->poll= ED_operator_uvedit;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear pinning for the selection instead of setting it.");
+}
+
+/******************* select pinned operator ***************/
+
+static int select_pinned_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Image *ima= CTX_data_edit_image(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tface;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(uvedit_face_visible(scene, ima, efa, tface)) {
+ if(tface->unwrap & TF_PIN1) uvedit_uv_select(scene, efa, tface, 0);
+ if(tface->unwrap & TF_PIN2) uvedit_uv_select(scene, efa, tface, 1);
+ if(tface->unwrap & TF_PIN3) uvedit_uv_select(scene, efa, tface, 2);
+ if(efa->v4) {
+ if(tface->unwrap & TF_PIN4) uvedit_uv_select(scene, efa, tface, 3);
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_select_pinned(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Selected Pinned";
+ ot->idname= "UV_OT_select_pinned";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= select_pinned_exec;
+ ot->poll= ED_operator_uvedit;
+}
+
+/********************** hide operator *********************/
+
+static int hide_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tf;
+ int swap= RNA_boolean_get(op->ptr, "unselected");
+
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ EM_hide_mesh(em, swap);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+ }
+
+ if(swap) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if(sima->flag & SI_SELACTFACE) {
+ /* Pretend face mode */
+ if(( (efa->v4==NULL &&
+ ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) == (TF_SEL1|TF_SEL2|TF_SEL3) ) ||
+ ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) == (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) ) == 0) {
+
+ if(em->selectmode == SCE_SELECT_FACE) {
+ efa->f &= ~SELECT;
+ /* must re-select after */
+ efa->e1->f &= ~SELECT;
+ efa->e2->f &= ~SELECT;
+ efa->e3->f &= ~SELECT;
+ if(efa->e4) efa->e4->f &= ~SELECT;
+ }
+ else
+ EM_select_face(efa, 0);
+ }
+ tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ }
+ else if(em->selectmode == SCE_SELECT_FACE) {
+ if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))==0) {
+ if(!efa->v4)
+ EM_select_face(efa, 0);
+ else if(!(tf->flag & TF_SEL4))
+ EM_select_face(efa, 0);
+ tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ }
+ }
+ else {
+ /* EM_deselect_flush will deselect the face */
+ if((tf->flag & TF_SEL1)==0) efa->v1->f &= ~SELECT;
+ if((tf->flag & TF_SEL2)==0) efa->v2->f &= ~SELECT;
+ if((tf->flag & TF_SEL3)==0) efa->v3->f &= ~SELECT;
+ if((efa->v4) && (tf->flag & TF_SEL4)==0) efa->v4->f &= ~SELECT;
+
+ tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ }
+ }
+ }
+ }
+ else {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(sima->flag & SI_SELACTFACE) {
+ if( (efa->v4==NULL &&
+ ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) == (TF_SEL1|TF_SEL2|TF_SEL3) ) ||
+ ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) == (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) ) {
+
+ if(em->selectmode == SCE_SELECT_FACE) {
+ efa->f &= ~SELECT;
+ /* must re-select after */
+ efa->e1->f &= ~SELECT;
+ efa->e2->f &= ~SELECT;
+ efa->e3->f &= ~SELECT;
+ if(efa->e4) efa->e4->f &= ~SELECT;
+ }
+ else
+ EM_select_face(efa, 0);
+ }
+
+ tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ }
+ else if(em->selectmode == SCE_SELECT_FACE) {
+ if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
+ EM_select_face(efa, 0);
+ else if(efa->v4 && tf->flag & TF_SEL4)
+ EM_select_face(efa, 0);
+
+ tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ }
+ else {
+ /* EM_deselect_flush will deselect the face */
+ if(tf->flag & TF_SEL1) efa->v1->f &= ~SELECT;
+ if(tf->flag & TF_SEL2) efa->v2->f &= ~SELECT;
+ if(tf->flag & TF_SEL3) efa->v3->f &= ~SELECT;
+ if((efa->v4) && tf->flag & TF_SEL4) efa->v4->f &= ~SELECT;
+
+ tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ }
+ }
+ }
+ }
+
+ /*deselects too many but ok for now*/
+ if(em->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX))
+ EM_deselect_flush(em);
+
+ if(em->selectmode==SCE_SELECT_FACE) {
+ /* de-selected all edges from faces that were de-selected.
+ * now make sure all faces that are selected also have selected edges */
+ for(efa= em->faces.first; efa; efa= efa->next)
+ if(efa->f & SELECT)
+ EM_select_face(efa, 1);
+ }
+
+ EM_validate_selections(em);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_hide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Hide Selected";
+ ot->idname= "UV_OT_hide";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= hide_exec;
+ ot->poll= ED_operator_uvedit;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected.");
+}
+
+/****************** reveal operator ******************/
+
+static int reveal_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tf;
+
+ /* call the mesh function if we are in mesh sync sel */
+ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ EM_reveal_mesh(em);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+ }
+
+ if(sima->flag & SI_SELACTFACE) {
+ if(em->selectmode == SCE_SELECT_FACE) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(!(efa->h) && !(efa->f & SELECT)) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ EM_select_face(efa, 1);
+ tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
+ }
+ }
+ }
+ else {
+ /* enable adjacent faces to have disconnected UV selections if sticky is disabled */
+ if(sima->sticky == SI_STICKY_DISABLE) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(!(efa->h) && !(efa->f & SELECT)) {
+ /* All verts must be unselected for the face to be selected in the UV view */
+ if((efa->v1->f&SELECT)==0 && (efa->v2->f&SELECT)==0 && (efa->v3->f&SELECT)==0 && (efa->v4==0 || (efa->v4->f&SELECT)==0)) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
+ /* Cant use EM_select_face here because it unselects the verts
+ * and we cant tell if the face was totally unselected or not */
+ /*EM_select_face(efa, 1);
+ *
+ * See Loop with EM_select_face() below... */
+ efa->f |= SELECT;
+ }
+ }
+ }
+ }
+ else {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(!(efa->h) && !(efa->f & SELECT)) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if((efa->v1->f & SELECT)==0) {tf->flag |= TF_SEL1;}
+ if((efa->v2->f & SELECT)==0) {tf->flag |= TF_SEL2;}
+ if((efa->v3->f & SELECT)==0) {tf->flag |= TF_SEL3;}
+ if((efa->v4 && (efa->v4->f & SELECT)==0)) {tf->flag |= TF_SEL4;}
+
+ efa->f |= SELECT;
+ }
+ }
+ }
+
+ /* Select all edges and verts now */
+ for(efa= em->faces.first; efa; efa= efa->next)
+ /* we only selected the face flags, and didnt changes edges or verts, fix this now */
+ if(!(efa->h) && (efa->f & SELECT))
+ EM_select_face(efa, 1);
+
+ EM_select_flush(em);
+ }
+ }
+ else if(em->selectmode == SCE_SELECT_FACE) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(!(efa->h) && !(efa->f & SELECT)) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ efa->f |= SELECT;
+ tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
+ }
+ }
+
+ /* Select all edges and verts now */
+ for(efa= em->faces.first; efa; efa= efa->next)
+ /* we only selected the face flags, and didnt changes edges or verts, fix this now */
+ if(!(efa->h) && (efa->f & SELECT))
+ EM_select_face(efa, 1);
+ }
+ else {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(!(efa->h) && !(efa->f & SELECT)) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if((efa->v1->f & SELECT)==0) {tf->flag |= TF_SEL1;}
+ if((efa->v2->f & SELECT)==0) {tf->flag |= TF_SEL2;}
+ if((efa->v3->f & SELECT)==0) {tf->flag |= TF_SEL3;}
+ if((efa->v4 && (efa->v4->f & SELECT)==0)) {tf->flag |= TF_SEL4;}
+
+ efa->f |= SELECT;
+ }
+ }
+
+ /* Select all edges and verts now */
+ for(efa= em->faces.first; efa; efa= efa->next)
+ /* we only selected the face flags, and didnt changes edges or verts, fix this now */
+ if(!(efa->h) && (efa->f & SELECT))
+ EM_select_face(efa, 1);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_reveal(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Reveal Hidden";
+ ot->idname= "UV_OT_reveal";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= reveal_exec;
+ ot->poll= ED_operator_uvedit;
+}
+
+/******************** set 3d cursor operator ********************/
+
+static int set_2d_cursor_exec(bContext *C, wmOperator *op)
+{
+ ARegion *ar= CTX_wm_region(C);
+ float location[2];
+
+ RNA_float_get_array(op->ptr, "location", location);
+ ar->v2d.cursor[0]= location[0];
+ ar->v2d.cursor[1]= location[1];
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+static int set_2d_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ int x, y;
+ float location[2];
+
+ x= event->x - ar->winrct.xmin;
+ y= event->y - ar->winrct.ymin;
+ UI_view2d_region_to_view(&ar->v2d, x, y, &location[0], &location[1]);
+ RNA_float_set_array(op->ptr, "location", location);
+
+ return set_2d_cursor_exec(C, op);
+}
+
+void UV_OT_cursor_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set 3D Cursor";
+ ot->idname= "UV_OT_cursor_set";
+
+ /* api callbacks */
+ ot->exec= set_2d_cursor_exec;
+ ot->invoke= set_2d_cursor_invoke;
+ ot->poll= ED_operator_uvedit;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in 0.0-1.0 coordinates.", -10.0f, 10.0f);
+}
+
+/********************** set tile operator **********************/
+
+static int set_tile_exec(bContext *C, wmOperator *op)
+{
+ Image *ima= CTX_data_edit_image(C);
+ int tile[2];
+
+ if(!ima || !(ima->tpageflag & IMA_TILES))
+ return OPERATOR_CANCELLED;
+
+ RNA_int_get_array(op->ptr, "tile", tile);
+ ED_uvedit_set_tile(C, CTX_data_scene(C), CTX_data_edit_object(C), ima, tile[0] + ima->xrep*tile[1], 1);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+static int set_tile_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
+ Image *ima= CTX_data_edit_image(C);
+ ARegion *ar= CTX_wm_region(C);
+ float fx, fy;
+ int x, y, tile[2];
+
+ if(!ima || !(ima->tpageflag & IMA_TILES))
+ return OPERATOR_CANCELLED;
+
+ x= event->x - ar->winrct.xmin;
+ y= event->y - ar->winrct.ymin;
+ UI_view2d_region_to_view(&ar->v2d, x, y, &fx, &fy);
+
+ if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
+ fx= fx*ima->xrep;
+ fy= fy*ima->yrep;
+
+ tile[0]= fx;
+ tile[1]= fy;
+
+ sima->curtile= tile[1]*ima->xrep + tile[0];
+ RNA_int_set_array(op->ptr, "tile", tile);
+ }
+
+ return set_tile_exec(C, op);
+}
+
+void UV_OT_tile_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Tile";
+ ot->idname= "UV_OT_tile_set";
+
+ /* api callbacks */
+ ot->exec= set_tile_exec;
+ ot->invoke= set_tile_invoke;
+ ot->poll= ED_operator_uvedit;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int_vector(ot->srna, "tile", 2, NULL, 0, INT_MAX, "Tile", "Tile coordinate.", 0, 10);
+}
+
+/* ************************** registration **********************************/
+
+void ED_operatortypes_uvedit(void)
+{
+ WM_operatortype_append(UV_OT_select_all_toggle);
+ WM_operatortype_append(UV_OT_select_invert);
+ WM_operatortype_append(UV_OT_select);
+ WM_operatortype_append(UV_OT_select_loop);
+ WM_operatortype_append(UV_OT_select_linked);
+ WM_operatortype_append(UV_OT_unlink_selection);
+ WM_operatortype_append(UV_OT_select_pinned);
+ WM_operatortype_append(UV_OT_select_border);
+ WM_operatortype_append(UV_OT_circle_select);
+
+ WM_operatortype_append(UV_OT_snap_cursor);
+ WM_operatortype_append(UV_OT_snap_selection);
+
+ WM_operatortype_append(UV_OT_align);
+ WM_operatortype_append(UV_OT_mirror);
+ WM_operatortype_append(UV_OT_stitch);
+ WM_operatortype_append(UV_OT_weld);
+ WM_operatortype_append(UV_OT_pin);
+
+ WM_operatortype_append(UV_OT_average_islands_scale);
+ WM_operatortype_append(UV_OT_cube_project);
+ WM_operatortype_append(UV_OT_cylinder_project);
+ WM_operatortype_append(UV_OT_from_view);
+ WM_operatortype_append(UV_OT_mapping_menu);
+ WM_operatortype_append(UV_OT_minimize_stretch);
+ WM_operatortype_append(UV_OT_pack_islands);
+ WM_operatortype_append(UV_OT_reset);
+ WM_operatortype_append(UV_OT_sphere_project);
+ WM_operatortype_append(UV_OT_unwrap);
+
+ WM_operatortype_append(UV_OT_reveal);
+ WM_operatortype_append(UV_OT_hide);
+
+ WM_operatortype_append(UV_OT_cursor_set);
+ WM_operatortype_append(UV_OT_tile_set);
+}
+
+void ED_keymap_uvedit(wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "UVEdit", 0, 0);
+
+ /* pick selection */
+ WM_keymap_add_item(keymap, "UV_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1);
+ WM_keymap_add_item(keymap, "UV_OT_select_loop", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select_loop", SELECTMOUSE, KM_PRESS, KM_SHIFT|KM_ALT, 0)->ptr, "extend", 1);
+
+ /* border/circle selection */
+ WM_keymap_add_item(keymap, "UV_OT_select_border", BKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select_border", BKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "pinned", 1);
+ WM_keymap_add_item(keymap, "UV_OT_circle_select", CKEY, KM_PRESS, 0, 0);
+
+ /* selection manipulation */
+ WM_keymap_add_item(keymap, "UV_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "UV_OT_unlink_selection", LKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "UV_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "UV_OT_select_invert", IKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "UV_OT_select_pinned", PKEY, KM_PRESS, KM_SHIFT, 0);
+
+ /* uv operations */
+ WM_keymap_add_item(keymap, "UV_OT_stitch", VKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "UV_OT_pin", PKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_pin", PKEY, KM_PRESS, KM_ALT, 0)->ptr, "clear", 1);
+
+ /* unwrap */
+ WM_keymap_add_item(keymap, "UV_OT_unwrap", EKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "UV_OT_minimize_stretch", VKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "UV_OT_pack_islands", PKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "UV_OT_average_islands_scale", AKEY, KM_PRESS, KM_CTRL, 0);
+
+ /* hide */
+ WM_keymap_add_item(keymap, "UV_OT_hide", HKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "unselected", 1);
+ WM_keymap_add_item(keymap, "UV_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
+
+ /* cursor */
+ WM_keymap_add_item(keymap, "UV_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "UV_OT_tile_set", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0);
+
+ transform_keymap_for_space(wm, keymap, SPACE_IMAGE);
+}
+
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
new file mode 100644
index 00000000000..5cc471ebc22
--- /dev/null
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -0,0 +1,4509 @@
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_memarena.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+#include "BLI_heap.h"
+#include "BLI_boxpack2d.h"
+
+#include "BKE_utildefines.h"
+
+#include "ONL_opennl.h"
+
+#include "uvedit_intern.h"
+#include "uvedit_parametrizer.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+#if defined(_WIN32)
+#define M_PI 3.14159265358979323846
+#endif
+
+/* Utils */
+
+#if 0
+ #define param_assert(condition);
+ #define param_warning(message);
+ #define param_test_equals_ptr(condition);
+ #define param_test_equals_int(condition);
+#else
+ #define param_assert(condition) \
+ if (!(condition)) \
+ { /*printf("Assertion %s:%d\n", __FILE__, __LINE__); abort();*/ }
+ #define param_warning(message) \
+ { /*printf("Warning %s:%d: %s\n", __FILE__, __LINE__, message);*/ }
+ #define param_test_equals_ptr(str, a, b) \
+ if (a != b) \
+ { /*printf("Equals %s => %p != %p\n", str, a, b);*/ };
+ #define param_test_equals_int(str, a, b) \
+ if (a != b) \
+ { /*printf("Equals %s => %d != %d\n", str, a, b);*/ };
+#endif
+
+typedef enum PBool {
+ P_TRUE = 1,
+ P_FALSE = 0
+} PBool;
+
+/* Special Purpose Hash */
+
+typedef intptr_t PHashKey;
+
+typedef struct PHashLink {
+ struct PHashLink *next;
+ PHashKey key;
+} PHashLink;
+
+typedef struct PHash {
+ PHashLink **list;
+ PHashLink **buckets;
+ int size, cursize, cursize_id;
+} PHash;
+
+
+
+struct PVert;
+struct PEdge;
+struct PFace;
+struct PChart;
+struct PHandle;
+
+/* Simplices */
+
+typedef struct PVert {
+ struct PVert *nextlink;
+
+ union PVertUnion {
+ PHashKey key; /* construct */
+ int id; /* abf/lscm matrix index */
+ float distortion; /* area smoothing */
+ HeapNode *heaplink; /* edge collapsing */
+ } u;
+
+ struct PEdge *edge;
+ float *co;
+ float uv[2];
+ unsigned char flag;
+
+} PVert;
+
+typedef struct PEdge {
+ struct PEdge *nextlink;
+
+ union PEdgeUnion {
+ PHashKey key; /* construct */
+ int id; /* abf matrix index */
+ HeapNode *heaplink; /* fill holes */
+ struct PEdge *nextcollapse; /* simplification */
+ } u;
+
+ struct PVert *vert;
+ struct PEdge *pair;
+ struct PEdge *next;
+ struct PFace *face;
+ float *orig_uv, old_uv[2];
+ unsigned short flag;
+
+} PEdge;
+
+typedef struct PFace {
+ struct PFace *nextlink;
+
+ union PFaceUnion {
+ PHashKey key; /* construct */
+ int chart; /* construct splitting*/
+ float area3d; /* stretch */
+ int id; /* abf matrix index */
+ } u;
+
+ struct PEdge *edge;
+ unsigned char flag;
+
+} PFace;
+
+enum PVertFlag {
+ PVERT_PIN = 1,
+ PVERT_SELECT = 2,
+ PVERT_INTERIOR = 4,
+ PVERT_COLLAPSE = 8,
+ PVERT_SPLIT = 16
+};
+
+enum PEdgeFlag {
+ PEDGE_SEAM = 1,
+ PEDGE_VERTEX_SPLIT = 2,
+ PEDGE_PIN = 4,
+ PEDGE_SELECT = 8,
+ PEDGE_DONE = 16,
+ PEDGE_FILLED = 32,
+ PEDGE_COLLAPSE = 64,
+ PEDGE_COLLAPSE_EDGE = 128,
+ PEDGE_COLLAPSE_PAIR = 256
+};
+
+/* for flipping faces */
+#define PEDGE_VERTEX_FLAGS (PEDGE_PIN)
+
+enum PFaceFlag {
+ PFACE_CONNECTED = 1,
+ PFACE_FILLED = 2,
+ PFACE_COLLAPSE = 4
+};
+
+/* Chart */
+
+typedef struct PChart {
+ PVert *verts;
+ PEdge *edges;
+ PFace *faces;
+ int nverts, nedges, nfaces;
+
+ PVert *collapsed_verts;
+ PEdge *collapsed_edges;
+ PFace *collapsed_faces;
+
+ union PChartUnion {
+ struct PChartLscm {
+ NLContext context;
+ float *abf_alpha;
+ PVert *pin1, *pin2;
+ } lscm;
+ struct PChartPack {
+ float rescale, area;
+ float size[2], trans[2];
+ } pack;
+ } u;
+
+ unsigned char flag;
+ struct PHandle *handle;
+} PChart;
+
+enum PChartFlag {
+ PCHART_NOPACK = 1
+};
+
+enum PHandleState {
+ PHANDLE_STATE_ALLOCATED,
+ PHANDLE_STATE_CONSTRUCTED,
+ PHANDLE_STATE_LSCM,
+ PHANDLE_STATE_STRETCH
+};
+
+typedef struct PHandle {
+ enum PHandleState state;
+ MemArena *arena;
+
+ PChart *construction_chart;
+ PHash *hash_verts;
+ PHash *hash_edges;
+ PHash *hash_faces;
+
+ PChart **charts;
+ int ncharts;
+
+ float aspx, aspy;
+
+ RNG *rng;
+ float blend;
+} PHandle;
+
+
+/* PHash
+ - special purpose hash that keeps all its elements in a single linked list.
+ - after construction, this hash is thrown away, and the list remains.
+ - removing elements is not possible efficiently.
+*/
+
+static int PHashSizes[] = {
+ 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
+ 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
+ 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459
+};
+
+#define PHASH_hash(ph, item) (((uintptr_t) (item))%((unsigned int) (ph)->cursize))
+#define PHASH_edge(v1, v2) ((v1)^(v2))
+
+static PHash *phash_new(PHashLink **list, int sizehint)
+{
+ PHash *ph = (PHash*)MEM_callocN(sizeof(PHash), "PHash");
+ ph->size = 0;
+ ph->cursize_id = 0;
+ ph->list = list;
+
+ while (PHashSizes[ph->cursize_id] < sizehint)
+ ph->cursize_id++;
+
+ ph->cursize = PHashSizes[ph->cursize_id];
+ ph->buckets = (PHashLink**)MEM_callocN(ph->cursize*sizeof(*ph->buckets), "PHashBuckets");
+
+ return ph;
+}
+
+static void phash_delete(PHash *ph)
+{
+ MEM_freeN(ph->buckets);
+ MEM_freeN(ph);
+}
+
+static int phash_size(PHash *ph)
+{
+ return ph->size;
+}
+
+static void phash_insert(PHash *ph, PHashLink *link)
+{
+ int size = ph->cursize;
+ int hash = PHASH_hash(ph, link->key);
+ PHashLink *lookup = ph->buckets[hash];
+
+ if (lookup == NULL) {
+ /* insert in front of the list */
+ ph->buckets[hash] = link;
+ link->next = *(ph->list);
+ *(ph->list) = link;
+ }
+ else {
+ /* insert after existing element */
+ link->next = lookup->next;
+ lookup->next = link;
+ }
+
+ ph->size++;
+
+ if (ph->size > (size*3)) {
+ PHashLink *next = NULL, *first = *(ph->list);
+
+ ph->cursize = PHashSizes[++ph->cursize_id];
+ MEM_freeN(ph->buckets);
+ ph->buckets = (PHashLink**)MEM_callocN(ph->cursize*sizeof(*ph->buckets), "PHashBuckets");
+ ph->size = 0;
+ *(ph->list) = NULL;
+
+ for (link = first; link; link = next) {
+ next = link->next;
+ phash_insert(ph, link);
+ }
+ }
+}
+
+static PHashLink *phash_lookup(PHash *ph, PHashKey key)
+{
+ PHashLink *link;
+ int hash = PHASH_hash(ph, key);
+
+ for (link = ph->buckets[hash]; link; link = link->next)
+ if (link->key == key)
+ return link;
+ else if (PHASH_hash(ph, link->key) != hash)
+ return NULL;
+
+ return link;
+}
+
+static PHashLink *phash_next(PHash *ph, PHashKey key, PHashLink *link)
+{
+ int hash = PHASH_hash(ph, key);
+
+ for (link = link->next; link; link = link->next)
+ if (link->key == key)
+ return link;
+ else if (PHASH_hash(ph, link->key) != hash)
+ return NULL;
+
+ return link;
+}
+
+/* Geometry */
+
+static float p_vec_angle_cos(float *v1, float *v2, float *v3)
+{
+ float d1[3], d2[3];
+
+ d1[0] = v1[0] - v2[0];
+ d1[1] = v1[1] - v2[1];
+ d1[2] = v1[2] - v2[2];
+
+ d2[0] = v3[0] - v2[0];
+ d2[1] = v3[1] - v2[1];
+ d2[2] = v3[2] - v2[2];
+
+ Normalize(d1);
+ Normalize(d2);
+
+ return d1[0]*d2[0] + d1[1]*d2[1] + d1[2]*d2[2];
+}
+
+static float p_vec_angle(float *v1, float *v2, float *v3)
+{
+ float dot = p_vec_angle_cos(v1, v2, v3);
+
+ if (dot <= -1.0f)
+ return (float)M_PI;
+ else if (dot >= 1.0f)
+ return 0.0f;
+ else
+ return (float)acos(dot);
+}
+
+static float p_vec2_angle(float *v1, float *v2, float *v3)
+{
+ float u1[3], u2[3], u3[3];
+
+ u1[0] = v1[0]; u1[1] = v1[1]; u1[2] = 0.0f;
+ u2[0] = v2[0]; u2[1] = v2[1]; u2[2] = 0.0f;
+ u3[0] = v3[0]; u3[1] = v3[1]; u3[2] = 0.0f;
+
+ return p_vec_angle(u1, u2, u3);
+}
+
+static void p_triangle_angles(float *v1, float *v2, float *v3, float *a1, float *a2, float *a3)
+{
+ *a1 = p_vec_angle(v3, v1, v2);
+ *a2 = p_vec_angle(v1, v2, v3);
+ *a3 = M_PI - *a2 - *a1;
+}
+
+static void p_face_angles(PFace *f, float *a1, float *a2, float *a3)
+{
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+
+ p_triangle_angles(v1->co, v2->co, v3->co, a1, a2, a3);
+}
+
+static float p_face_area(PFace *f)
+{
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+
+ return AreaT3Dfl(v1->co, v2->co, v3->co);
+}
+
+static float p_area_signed(float *v1, float *v2, float *v3)
+{
+ return 0.5f*(((v2[0] - v1[0])*(v3[1] - v1[1])) -
+ ((v3[0] - v1[0])*(v2[1] - v1[1])));
+}
+
+static float p_face_uv_area_signed(PFace *f)
+{
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+
+ return 0.5f*(((v2->uv[0] - v1->uv[0])*(v3->uv[1] - v1->uv[1])) -
+ ((v3->uv[0] - v1->uv[0])*(v2->uv[1] - v1->uv[1])));
+}
+
+static float p_edge_length(PEdge *e)
+{
+ PVert *v1 = e->vert, *v2 = e->next->vert;
+ float d[3];
+
+ d[0] = v2->co[0] - v1->co[0];
+ d[1] = v2->co[1] - v1->co[1];
+ d[2] = v2->co[2] - v1->co[2];
+
+ return sqrt(d[0]*d[0] + d[1]*d[1] + d[2]*d[2]);
+}
+
+static float p_edge_uv_length(PEdge *e)
+{
+ PVert *v1 = e->vert, *v2 = e->next->vert;
+ float d[3];
+
+ d[0] = v2->uv[0] - v1->uv[0];
+ d[1] = v2->uv[1] - v1->uv[1];
+
+ return sqrt(d[0]*d[0] + d[1]*d[1]);
+}
+
+static void p_chart_uv_bbox(PChart *chart, float *minv, float *maxv)
+{
+ PVert *v;
+
+ INIT_MINMAX2(minv, maxv);
+
+ for (v=chart->verts; v; v=v->nextlink) {
+ DO_MINMAX2(v->uv, minv, maxv);
+ }
+}
+
+static void p_chart_uv_scale(PChart *chart, float scale)
+{
+ PVert *v;
+
+ for (v=chart->verts; v; v=v->nextlink) {
+ v->uv[0] *= scale;
+ v->uv[1] *= scale;
+ }
+}
+
+static void p_chart_uv_scale_xy(PChart *chart, float x, float y)
+{
+ PVert *v;
+
+ for (v=chart->verts; v; v=v->nextlink) {
+ v->uv[0] *= x;
+ v->uv[1] *= y;
+ }
+}
+
+static void p_chart_uv_translate(PChart *chart, float trans[2])
+{
+ PVert *v;
+
+ for (v=chart->verts; v; v=v->nextlink) {
+ v->uv[0] += trans[0];
+ v->uv[1] += trans[1];
+ }
+}
+
+static PBool p_intersect_line_2d_dir(float *v1, float *dir1, float *v2, float *dir2, float *isect)
+{
+ float lmbda, div;
+
+ div= dir2[0]*dir1[1] - dir2[1]*dir1[0];
+
+ if (div == 0.0f)
+ return P_FALSE;
+
+ lmbda= ((v1[1]-v2[1])*dir1[0]-(v1[0]-v2[0])*dir1[1])/div;
+ isect[0] = v1[0] + lmbda*dir2[0];
+ isect[1] = v1[1] + lmbda*dir2[1];
+
+ return P_TRUE;
+}
+
+#if 0
+static PBool p_intersect_line_2d(float *v1, float *v2, float *v3, float *v4, float *isect)
+{
+ float dir1[2], dir2[2];
+
+ dir1[0] = v4[0] - v3[0];
+ dir1[1] = v4[1] - v3[1];
+
+ dir2[0] = v2[0] - v1[0];
+ dir2[1] = v2[1] - v1[1];
+
+ if (!p_intersect_line_2d_dir(v1, dir1, v2, dir2, isect)) {
+ /* parallel - should never happen in theory for polygon kernel, but
+ let's give a point nearby in case things go wrong */
+ isect[0] = (v1[0] + v2[0])*0.5f;
+ isect[1] = (v1[1] + v2[1])*0.5f;
+ return P_FALSE;
+ }
+
+ return P_TRUE;
+}
+#endif
+
+/* Topological Utilities */
+
+static PEdge *p_wheel_edge_next(PEdge *e)
+{
+ return e->next->next->pair;
+}
+
+static PEdge *p_wheel_edge_prev(PEdge *e)
+{
+ return (e->pair)? e->pair->next: NULL;
+}
+
+static PEdge *p_boundary_edge_next(PEdge *e)
+{
+ return e->next->vert->edge;
+}
+
+static PEdge *p_boundary_edge_prev(PEdge *e)
+{
+ PEdge *we = e, *last;
+
+ do {
+ last = we;
+ we = p_wheel_edge_next(we);
+ } while (we && (we != e));
+
+ return last->next->next;
+}
+
+static PBool p_vert_interior(PVert *v)
+{
+ return (v->edge->pair != NULL);
+}
+
+static void p_face_flip(PFace *f)
+{
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+ int f1 = e1->flag, f2 = e2->flag, f3 = e3->flag;
+
+ e1->vert = v2;
+ e1->next = e3;
+ e1->flag = (f1 & ~PEDGE_VERTEX_FLAGS) | (f2 & PEDGE_VERTEX_FLAGS);
+
+ e2->vert = v3;
+ e2->next = e1;
+ e2->flag = (f2 & ~PEDGE_VERTEX_FLAGS) | (f3 & PEDGE_VERTEX_FLAGS);
+
+ e3->vert = v1;
+ e3->next = e2;
+ e3->flag = (f3 & ~PEDGE_VERTEX_FLAGS) | (f1 & PEDGE_VERTEX_FLAGS);
+}
+
+#if 0
+static void p_chart_topological_sanity_check(PChart *chart)
+{
+ PVert *v;
+ PEdge *e;
+
+ for (v=chart->verts; v; v=v->nextlink)
+ param_test_equals_ptr("v->edge->vert", v, v->edge->vert);
+
+ for (e=chart->edges; e; e=e->nextlink) {
+ if (e->pair) {
+ param_test_equals_ptr("e->pair->pair", e, e->pair->pair);
+ param_test_equals_ptr("pair->vert", e->vert, e->pair->next->vert);
+ param_test_equals_ptr("pair->next->vert", e->next->vert, e->pair->vert);
+ }
+ }
+}
+#endif
+
+/* Loading / Flushing */
+
+static void p_vert_load_pin_select_uvs(PHandle *handle, PVert *v)
+{
+ PEdge *e;
+ int nedges = 0, npins = 0;
+ float pinuv[2];
+
+ v->uv[0] = v->uv[1] = 0.0f;
+ pinuv[0] = pinuv[1] = 0.0f;
+ e = v->edge;
+ do {
+ if (e->orig_uv) {
+ if (e->flag & PEDGE_SELECT)
+ v->flag |= PVERT_SELECT;
+
+ if (e->flag & PEDGE_PIN) {
+ pinuv[0] += e->orig_uv[0]*handle->aspx;
+ pinuv[1] += e->orig_uv[1]*handle->aspy;
+ npins++;
+ }
+ else {
+ v->uv[0] += e->orig_uv[0]*handle->aspx;
+ v->uv[1] += e->orig_uv[1]*handle->aspy;
+ }
+
+ nedges++;
+ }
+
+ e = p_wheel_edge_next(e);
+ } while (e && e != (v->edge));
+
+ if (npins > 0) {
+ v->uv[0] = pinuv[0]/npins;
+ v->uv[1] = pinuv[1]/npins;
+ v->flag |= PVERT_PIN;
+ }
+ else if (nedges > 0) {
+ v->uv[0] /= nedges;
+ v->uv[1] /= nedges;
+ }
+}
+
+static void p_flush_uvs(PHandle *handle, PChart *chart)
+{
+ PEdge *e;
+
+ for (e=chart->edges; e; e=e->nextlink) {
+ if (e->orig_uv) {
+ e->orig_uv[0] = e->vert->uv[0]/handle->aspx;
+ e->orig_uv[1] = e->vert->uv[1]/handle->aspy;
+ }
+ }
+}
+
+static void p_flush_uvs_blend(PHandle *handle, PChart *chart, float blend)
+{
+ PEdge *e;
+ float invblend = 1.0f - blend;
+
+ for (e=chart->edges; e; e=e->nextlink) {
+ if (e->orig_uv) {
+ e->orig_uv[0] = blend*e->old_uv[0] + invblend*e->vert->uv[0]/handle->aspx;
+ e->orig_uv[1] = blend*e->old_uv[1] + invblend*e->vert->uv[1]/handle->aspy;
+ }
+ }
+}
+
+static void p_face_backup_uvs(PFace *f)
+{
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+
+ if (e1->orig_uv && e2->orig_uv && e3->orig_uv) {
+ e1->old_uv[0] = e1->orig_uv[0];
+ e1->old_uv[1] = e1->orig_uv[1];
+ e2->old_uv[0] = e2->orig_uv[0];
+ e2->old_uv[1] = e2->orig_uv[1];
+ e3->old_uv[0] = e3->orig_uv[0];
+ e3->old_uv[1] = e3->orig_uv[1];
+ }
+}
+
+static void p_face_restore_uvs(PFace *f)
+{
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+
+ if (e1->orig_uv && e2->orig_uv && e3->orig_uv) {
+ e1->orig_uv[0] = e1->old_uv[0];
+ e1->orig_uv[1] = e1->old_uv[1];
+ e2->orig_uv[0] = e2->old_uv[0];
+ e2->orig_uv[1] = e2->old_uv[1];
+ e3->orig_uv[0] = e3->old_uv[0];
+ e3->orig_uv[1] = e3->old_uv[1];
+ }
+}
+
+/* Construction (use only during construction, relies on u.key being set */
+
+static PVert *p_vert_add(PHandle *handle, PHashKey key, float *co, PEdge *e)
+{
+ PVert *v = (PVert*)BLI_memarena_alloc(handle->arena, sizeof *v);
+ v->co = co;
+ v->u.key = key;
+ v->edge = e;
+ v->flag = 0;
+
+ phash_insert(handle->hash_verts, (PHashLink*)v);
+
+ return v;
+}
+
+static PVert *p_vert_lookup(PHandle *handle, PHashKey key, float *co, PEdge *e)
+{
+ PVert *v = (PVert*)phash_lookup(handle->hash_verts, key);
+
+ if (v)
+ return v;
+ else
+ return p_vert_add(handle, key, co, e);
+}
+
+static PVert *p_vert_copy(PChart *chart, PVert *v)
+{
+ PVert *nv = (PVert*)BLI_memarena_alloc(chart->handle->arena, sizeof *nv);
+
+ nv->co = v->co;
+ nv->uv[0] = v->uv[0];
+ nv->uv[1] = v->uv[1];
+ nv->u.key = v->u.key;
+ nv->edge = v->edge;
+ nv->flag = v->flag;
+
+ return nv;
+}
+
+static PEdge *p_edge_lookup(PHandle *handle, PHashKey *vkeys)
+{
+ PHashKey key = PHASH_edge(vkeys[0], vkeys[1]);
+ PEdge *e = (PEdge*)phash_lookup(handle->hash_edges, key);
+
+ while (e) {
+ if ((e->vert->u.key == vkeys[0]) && (e->next->vert->u.key == vkeys[1]))
+ return e;
+ else if ((e->vert->u.key == vkeys[1]) && (e->next->vert->u.key == vkeys[0]))
+ return e;
+
+ e = (PEdge*)phash_next(handle->hash_edges, key, (PHashLink*)e);
+ }
+
+ return NULL;
+}
+
+static PBool p_face_exists(PHandle *handle, PHashKey *vkeys, int i1, int i2, int i3)
+{
+ PHashKey key = PHASH_edge(vkeys[i1], vkeys[i2]);
+ PEdge *e = (PEdge*)phash_lookup(handle->hash_edges, key);
+
+ while (e) {
+ if ((e->vert->u.key == vkeys[i1]) && (e->next->vert->u.key == vkeys[i2])) {
+ if (e->next->next->vert->u.key == vkeys[i3])
+ return P_TRUE;
+ }
+ else if ((e->vert->u.key == vkeys[i2]) && (e->next->vert->u.key == vkeys[i1])) {
+ if (e->next->next->vert->u.key == vkeys[i3])
+ return P_TRUE;
+ }
+
+ e = (PEdge*)phash_next(handle->hash_edges, key, (PHashLink*)e);
+ }
+
+ return P_FALSE;
+}
+
+static PChart *p_chart_new(PHandle *handle)
+{
+ PChart *chart = (PChart*)MEM_callocN(sizeof*chart, "PChart");
+ chart->handle = handle;
+
+ return chart;
+}
+
+static void p_chart_delete(PChart *chart)
+{
+ /* the actual links are free by memarena */
+ MEM_freeN(chart);
+}
+
+static PBool p_edge_implicit_seam(PEdge *e, PEdge *ep)
+{
+ float *uv1, *uv2, *uvp1, *uvp2;
+ float limit[2];
+
+ limit[0] = 0.00001;
+ limit[1] = 0.00001;
+
+ uv1 = e->orig_uv;
+ uv2 = e->next->orig_uv;
+
+ if (e->vert->u.key == ep->vert->u.key) {
+ uvp1 = ep->orig_uv;
+ uvp2 = ep->next->orig_uv;
+ }
+ else {
+ uvp1 = ep->next->orig_uv;
+ uvp2 = ep->orig_uv;
+ }
+
+ if((fabs(uv1[0]-uvp1[0]) > limit[0]) || (fabs(uv1[1]-uvp1[1]) > limit[1])) {
+ e->flag |= PEDGE_SEAM;
+ ep->flag |= PEDGE_SEAM;
+ return P_TRUE;
+ }
+ if((fabs(uv2[0]-uvp2[0]) > limit[0]) || (fabs(uv2[1]-uvp2[1]) > limit[1])) {
+ e->flag |= PEDGE_SEAM;
+ ep->flag |= PEDGE_SEAM;
+ return P_TRUE;
+ }
+
+ return P_FALSE;
+}
+
+static PBool p_edge_has_pair(PHandle *handle, PEdge *e, PEdge **pair, PBool impl)
+{
+ PHashKey key;
+ PEdge *pe;
+ PVert *v1, *v2;
+ PHashKey key1 = e->vert->u.key;
+ PHashKey key2 = e->next->vert->u.key;
+
+ if (e->flag & PEDGE_SEAM)
+ return P_FALSE;
+
+ key = PHASH_edge(key1, key2);
+ pe = (PEdge*)phash_lookup(handle->hash_edges, key);
+ *pair = NULL;
+
+ while (pe) {
+ if (pe != e) {
+ v1 = pe->vert;
+ v2 = pe->next->vert;
+
+ if (((v1->u.key == key1) && (v2->u.key == key2)) ||
+ ((v1->u.key == key2) && (v2->u.key == key1))) {
+
+ /* don't connect seams and t-junctions */
+ if ((pe->flag & PEDGE_SEAM) || *pair ||
+ (impl && p_edge_implicit_seam(e, pe))) {
+ *pair = NULL;
+ return P_FALSE;
+ }
+
+ *pair = pe;
+ }
+ }
+
+ pe = (PEdge*)phash_next(handle->hash_edges, key, (PHashLink*)pe);
+ }
+
+ if (*pair && (e->vert == (*pair)->vert)) {
+ if ((*pair)->next->pair || (*pair)->next->next->pair) {
+ /* non unfoldable, maybe mobius ring or klein bottle */
+ *pair = NULL;
+ return P_FALSE;
+ }
+ }
+
+ return (*pair != NULL);
+}
+
+static PBool p_edge_connect_pair(PHandle *handle, PEdge *e, PEdge ***stack, PBool impl)
+{
+ PEdge *pair = NULL;
+
+ if(!e->pair && p_edge_has_pair(handle, e, &pair, impl)) {
+ if (e->vert == pair->vert)
+ p_face_flip(pair->face);
+
+ e->pair = pair;
+ pair->pair = e;
+
+ if (!(pair->face->flag & PFACE_CONNECTED)) {
+ **stack = pair;
+ (*stack)++;
+ }
+ }
+
+ return (e->pair != NULL);
+}
+
+static int p_connect_pairs(PHandle *handle, PBool impl)
+{
+ PEdge **stackbase = MEM_mallocN(sizeof*stackbase*phash_size(handle->hash_faces), "Pstackbase");
+ PEdge **stack = stackbase;
+ PFace *f, *first;
+ PEdge *e, *e1, *e2;
+ PChart *chart = handle->construction_chart;
+ int ncharts = 0;
+
+ /* connect pairs, count edges, set vertex-edge pointer to a pairless edge */
+ for (first=chart->faces; first; first=first->nextlink) {
+ if (first->flag & PFACE_CONNECTED)
+ continue;
+
+ *stack = first->edge;
+ stack++;
+
+ while (stack != stackbase) {
+ stack--;
+ e = *stack;
+ e1 = e->next;
+ e2 = e1->next;
+
+ f = e->face;
+ f->flag |= PFACE_CONNECTED;
+
+ /* assign verts to charts so we can sort them later */
+ f->u.chart = ncharts;
+
+ if (!p_edge_connect_pair(handle, e, &stack, impl))
+ e->vert->edge = e;
+ if (!p_edge_connect_pair(handle, e1, &stack, impl))
+ e1->vert->edge = e1;
+ if (!p_edge_connect_pair(handle, e2, &stack, impl))
+ e2->vert->edge = e2;
+ }
+
+ ncharts++;
+ }
+
+ MEM_freeN(stackbase);
+
+ return ncharts;
+}
+
+static void p_split_vert(PChart *chart, PEdge *e)
+{
+ PEdge *we, *lastwe = NULL;
+ PVert *v = e->vert;
+ PBool copy = P_TRUE;
+
+ if (e->flag & PEDGE_VERTEX_SPLIT)
+ return;
+
+ /* rewind to start */
+ lastwe = e;
+ for (we = p_wheel_edge_prev(e); we && (we != e); we = p_wheel_edge_prev(we))
+ lastwe = we;
+
+ /* go over all edges in wheel */
+ for (we = lastwe; we; we = p_wheel_edge_next(we)) {
+ if (we->flag & PEDGE_VERTEX_SPLIT)
+ break;
+
+ we->flag |= PEDGE_VERTEX_SPLIT;
+
+ if (we == v->edge) {
+ /* found it, no need to copy */
+ copy = P_FALSE;
+ v->nextlink = chart->verts;
+ chart->verts = v;
+ chart->nverts++;
+ }
+ }
+
+ if (copy) {
+ /* not found, copying */
+ v->flag |= PVERT_SPLIT;
+ v = p_vert_copy(chart, v);
+ v->flag |= PVERT_SPLIT;
+
+ v->nextlink = chart->verts;
+ chart->verts = v;
+ chart->nverts++;
+
+ v->edge = lastwe;
+
+ we = lastwe;
+ do {
+ we->vert = v;
+ we = p_wheel_edge_next(we);
+ } while (we && (we != lastwe));
+ }
+}
+
+static PChart **p_split_charts(PHandle *handle, PChart *chart, int ncharts)
+{
+ PChart **charts = MEM_mallocN(sizeof*charts * ncharts, "PCharts"), *nchart;
+ PFace *f, *nextf;
+ int i;
+
+ for (i = 0; i < ncharts; i++)
+ charts[i] = p_chart_new(handle);
+
+ f = chart->faces;
+ while (f) {
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ nextf = f->nextlink;
+
+ nchart = charts[f->u.chart];
+
+ f->nextlink = nchart->faces;
+ nchart->faces = f;
+ e1->nextlink = nchart->edges;
+ nchart->edges = e1;
+ e2->nextlink = nchart->edges;
+ nchart->edges = e2;
+ e3->nextlink = nchart->edges;
+ nchart->edges = e3;
+
+ nchart->nfaces++;
+ nchart->nedges += 3;
+
+ p_split_vert(nchart, e1);
+ p_split_vert(nchart, e2);
+ p_split_vert(nchart, e3);
+
+ f = nextf;
+ }
+
+ return charts;
+}
+
+static PFace *p_face_add(PHandle *handle)
+{
+ PFace *f;
+ PEdge *e1, *e2, *e3;
+
+ /* allocate */
+ f = (PFace*)BLI_memarena_alloc(handle->arena, sizeof *f);
+ f->flag=0; // init !
+
+ e1 = (PEdge*)BLI_memarena_alloc(handle->arena, sizeof *e1);
+ e2 = (PEdge*)BLI_memarena_alloc(handle->arena, sizeof *e2);
+ e3 = (PEdge*)BLI_memarena_alloc(handle->arena, sizeof *e3);
+
+ /* set up edges */
+ f->edge = e1;
+ e1->face = e2->face = e3->face = f;
+
+ e1->next = e2;
+ e2->next = e3;
+ e3->next = e1;
+
+ e1->pair = NULL;
+ e2->pair = NULL;
+ e3->pair = NULL;
+
+ e1->flag =0;
+ e2->flag =0;
+ e3->flag =0;
+
+ return f;
+}
+
+static PFace *p_face_add_construct(PHandle *handle, ParamKey key, ParamKey *vkeys,
+ float *co[3], float *uv[3], int i1, int i2, int i3,
+ ParamBool *pin, ParamBool *select)
+{
+ PFace *f = p_face_add(handle);
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+
+ e1->vert = p_vert_lookup(handle, vkeys[i1], co[i1], e1);
+ e2->vert = p_vert_lookup(handle, vkeys[i2], co[i2], e2);
+ e3->vert = p_vert_lookup(handle, vkeys[i3], co[i3], e3);
+
+ e1->orig_uv = uv[i1];
+ e2->orig_uv = uv[i2];
+ e3->orig_uv = uv[i3];
+
+ if (pin) {
+ if (pin[i1]) e1->flag |= PEDGE_PIN;
+ if (pin[i2]) e2->flag |= PEDGE_PIN;
+ if (pin[i3]) e3->flag |= PEDGE_PIN;
+ }
+
+ if (select) {
+ if (select[i1]) e1->flag |= PEDGE_SELECT;
+ if (select[i2]) e2->flag |= PEDGE_SELECT;
+ if (select[i3]) e3->flag |= PEDGE_SELECT;
+ }
+
+ /* insert into hash */
+ f->u.key = key;
+ phash_insert(handle->hash_faces, (PHashLink*)f);
+
+ e1->u.key = PHASH_edge(vkeys[i1], vkeys[i2]);
+ e2->u.key = PHASH_edge(vkeys[i2], vkeys[i3]);
+ e3->u.key = PHASH_edge(vkeys[i3], vkeys[i1]);
+
+ phash_insert(handle->hash_edges, (PHashLink*)e1);
+ phash_insert(handle->hash_edges, (PHashLink*)e2);
+ phash_insert(handle->hash_edges, (PHashLink*)e3);
+
+ return f;
+}
+
+static PFace *p_face_add_fill(PChart *chart, PVert *v1, PVert *v2, PVert *v3)
+{
+ PFace *f = p_face_add(chart->handle);
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+
+ e1->vert = v1;
+ e2->vert = v2;
+ e3->vert = v3;
+
+ e1->orig_uv = e2->orig_uv = e3->orig_uv = NULL;
+
+ f->nextlink = chart->faces;
+ chart->faces = f;
+ e1->nextlink = chart->edges;
+ chart->edges = e1;
+ e2->nextlink = chart->edges;
+ chart->edges = e2;
+ e3->nextlink = chart->edges;
+ chart->edges = e3;
+
+ chart->nfaces++;
+ chart->nedges += 3;
+
+ return f;
+}
+
+static PBool p_quad_split_direction(PHandle *handle, float **co, PHashKey *vkeys)
+{
+ float fac= VecLenf(co[0], co[2]) - VecLenf(co[1], co[3]);
+ PBool dir = (fac <= 0.0f);
+
+ /* the face exists check is there because of a special case: when
+ two quads share three vertices, they can each be split into two
+ triangles, resulting in two identical triangles. for example in
+ suzanne's nose. */
+ if (dir) {
+ if (p_face_exists(handle,vkeys,0,1,2) || p_face_exists(handle,vkeys,0,2,3))
+ return !dir;
+ }
+ else {
+ if (p_face_exists(handle,vkeys,0,1,3) || p_face_exists(handle,vkeys,1,2,3))
+ return !dir;
+ }
+
+ return dir;
+}
+
+/* Construction: boundary filling */
+
+static void p_chart_boundaries(PChart *chart, int *nboundaries, PEdge **outer)
+{
+ PEdge *e, *be;
+ float len, maxlen = -1.0;
+
+ if (nboundaries)
+ *nboundaries = 0;
+ if (outer)
+ *outer = NULL;
+
+ for (e=chart->edges; e; e=e->nextlink) {
+ if (e->pair || (e->flag & PEDGE_DONE))
+ continue;
+
+ if (nboundaries)
+ (*nboundaries)++;
+
+ len = 0.0f;
+
+ be = e;
+ do {
+ be->flag |= PEDGE_DONE;
+ len += p_edge_length(be);
+ be = be->next->vert->edge;
+ } while(be != e);
+
+ if (outer && (len > maxlen)) {
+ *outer = e;
+ maxlen = len;
+ }
+ }
+
+ for (e=chart->edges; e; e=e->nextlink)
+ e->flag &= ~PEDGE_DONE;
+}
+
+static float p_edge_boundary_angle(PEdge *e)
+{
+ PEdge *we;
+ PVert *v, *v1, *v2;
+ float angle;
+ int n = 0;
+
+ v = e->vert;
+
+ /* concave angle check -- could be better */
+ angle = M_PI;
+
+ we = v->edge;
+ do {
+ v1 = we->next->vert;
+ v2 = we->next->next->vert;
+ angle -= p_vec_angle(v1->co, v->co, v2->co);
+
+ we = we->next->next->pair;
+ n++;
+ } while (we && (we != v->edge));
+
+ return angle;
+}
+
+static void p_chart_fill_boundary(PChart *chart, PEdge *be, int nedges)
+{
+ PEdge *e, *e1, *e2;
+
+ PFace *f;
+ struct Heap *heap = BLI_heap_new();
+ float angle;
+
+ e = be;
+ do {
+ angle = p_edge_boundary_angle(e);
+ e->u.heaplink = BLI_heap_insert(heap, angle, e);
+
+ e = p_boundary_edge_next(e);
+ } while(e != be);
+
+ if (nedges == 2) {
+ /* no real boundary, but an isolated seam */
+ e = be->next->vert->edge;
+ e->pair = be;
+ be->pair = e;
+
+ BLI_heap_remove(heap, e->u.heaplink);
+ BLI_heap_remove(heap, be->u.heaplink);
+ }
+ else {
+ while (nedges > 2) {
+ PEdge *ne, *ne1, *ne2;
+
+ e = (PEdge*)BLI_heap_popmin(heap);
+
+ e1 = p_boundary_edge_prev(e);
+ e2 = p_boundary_edge_next(e);
+
+ BLI_heap_remove(heap, e1->u.heaplink);
+ BLI_heap_remove(heap, e2->u.heaplink);
+ e->u.heaplink = e1->u.heaplink = e2->u.heaplink = NULL;
+
+ e->flag |= PEDGE_FILLED;
+ e1->flag |= PEDGE_FILLED;
+
+
+
+
+
+ f = p_face_add_fill(chart, e->vert, e1->vert, e2->vert);
+ f->flag |= PFACE_FILLED;
+
+ ne = f->edge->next->next;
+ ne1 = f->edge;
+ ne2 = f->edge->next;
+
+ ne->flag = ne1->flag = ne2->flag = PEDGE_FILLED;
+
+ e->pair = ne;
+ ne->pair = e;
+ e1->pair = ne1;
+ ne1->pair = e1;
+
+ ne->vert = e2->vert;
+ ne1->vert = e->vert;
+ ne2->vert = e1->vert;
+
+ if (nedges == 3) {
+ e2->pair = ne2;
+ ne2->pair = e2;
+ }
+ else {
+ ne2->vert->edge = ne2;
+
+ ne2->u.heaplink = BLI_heap_insert(heap, p_edge_boundary_angle(ne2), ne2);
+ e2->u.heaplink = BLI_heap_insert(heap, p_edge_boundary_angle(e2), e2);
+ }
+
+ nedges--;
+ }
+ }
+
+ BLI_heap_free(heap, NULL);
+}
+
+static void p_chart_fill_boundaries(PChart *chart, PEdge *outer)
+{
+ PEdge *e, *be; /* *enext - as yet unused */
+ int nedges;
+
+ for (e=chart->edges; e; e=e->nextlink) {
+ /* enext = e->nextlink; - as yet unused */
+
+ if (e->pair || (e->flag & PEDGE_FILLED))
+ continue;
+
+ nedges = 0;
+ be = e;
+ do {
+ be->flag |= PEDGE_FILLED;
+ be = be->next->vert->edge;
+ nedges++;
+ } while(be != e);
+
+ if (e != outer)
+ p_chart_fill_boundary(chart, e, nedges);
+ }
+}
+
+#if 0
+/* Polygon kernel for inserting uv's non overlapping */
+
+static int p_polygon_point_in(float *cp1, float *cp2, float *p)
+{
+ if ((cp1[0] == p[0]) && (cp1[1] == p[1]))
+ return 2;
+ else if ((cp2[0] == p[0]) && (cp2[1] == p[1]))
+ return 3;
+ else
+ return (p_area_signed(cp1, cp2, p) >= 0.0f);
+}
+
+static void p_polygon_kernel_clip(float (*oldpoints)[2], int noldpoints, float (*newpoints)[2], int *nnewpoints, float *cp1, float *cp2)
+{
+ float *p2, *p1, isect[2];
+ int i, p2in, p1in;
+
+ p1 = oldpoints[noldpoints-1];
+ p1in = p_polygon_point_in(cp1, cp2, p1);
+ *nnewpoints = 0;
+
+ for (i = 0; i < noldpoints; i++) {
+ p2 = oldpoints[i];
+ p2in = p_polygon_point_in(cp1, cp2, p2);
+
+ if ((p2in >= 2) || (p1in && p2in)) {
+ newpoints[*nnewpoints][0] = p2[0];
+ newpoints[*nnewpoints][1] = p2[1];
+ (*nnewpoints)++;
+ }
+ else if (p1in && !p2in) {
+ if (p1in != 3) {
+ p_intersect_line_2d(p1, p2, cp1, cp2, isect);
+ newpoints[*nnewpoints][0] = isect[0];
+ newpoints[*nnewpoints][1] = isect[1];
+ (*nnewpoints)++;
+ }
+ }
+ else if (!p1in && p2in) {
+ p_intersect_line_2d(p1, p2, cp1, cp2, isect);
+ newpoints[*nnewpoints][0] = isect[0];
+ newpoints[*nnewpoints][1] = isect[1];
+ (*nnewpoints)++;
+
+ newpoints[*nnewpoints][0] = p2[0];
+ newpoints[*nnewpoints][1] = p2[1];
+ (*nnewpoints)++;
+ }
+
+ p1in = p2in;
+ p1 = p2;
+ }
+}
+
+static void p_polygon_kernel_center(float (*points)[2], int npoints, float *center)
+{
+ int i, size, nnewpoints = npoints;
+ float (*oldpoints)[2], (*newpoints)[2], *p1, *p2;
+
+ size = npoints*3;
+ oldpoints = MEM_mallocN(sizeof(float)*2*size, "PPolygonOldPoints");
+ newpoints = MEM_mallocN(sizeof(float)*2*size, "PPolygonNewPoints");
+
+ memcpy(oldpoints, points, sizeof(float)*2*npoints);
+
+ for (i = 0; i < npoints; i++) {
+ p1 = points[i];
+ p2 = points[(i+1)%npoints];
+ p_polygon_kernel_clip(oldpoints, nnewpoints, newpoints, &nnewpoints, p1, p2);
+
+ if (nnewpoints == 0) {
+ /* degenerate case, use center of original polygon */
+ memcpy(oldpoints, points, sizeof(float)*2*npoints);
+ nnewpoints = npoints;
+ break;
+ }
+ else if (nnewpoints == 1) {
+ /* degenerate case, use remaining point */
+ center[0] = newpoints[0][0];
+ center[1] = newpoints[0][1];
+
+ MEM_freeN(oldpoints);
+ MEM_freeN(newpoints);
+
+ return;
+ }
+
+ if (nnewpoints*2 > size) {
+ size *= 2;
+ free(oldpoints);
+ oldpoints = malloc(sizeof(float)*2*size);
+ memcpy(oldpoints, newpoints, sizeof(float)*2*nnewpoints);
+ free(newpoints);
+ newpoints = malloc(sizeof(float)*2*size);
+ }
+ else {
+ float (*sw_points)[2] = oldpoints;
+ oldpoints = newpoints;
+ newpoints = sw_points;
+ }
+ }
+
+ center[0] = center[1] = 0.0f;
+
+ for (i = 0; i < nnewpoints; i++) {
+ center[0] += oldpoints[i][0];
+ center[1] += oldpoints[i][1];
+ }
+
+ center[0] /= nnewpoints;
+ center[1] /= nnewpoints;
+
+ MEM_freeN(oldpoints);
+ MEM_freeN(newpoints);
+}
+#endif
+
+#if 0
+/* Edge Collapser */
+
+int NCOLLAPSE = 1;
+int NCOLLAPSEX = 0;
+
+static float p_vert_cotan(float *v1, float *v2, float *v3)
+{
+ float a[3], b[3], c[3], clen;
+
+ VecSubf(a, v2, v1);
+ VecSubf(b, v3, v1);
+ Crossf(c, a, b);
+
+ clen = VecLength(c);
+
+ if (clen == 0.0f)
+ return 0.0f;
+
+ return Inpf(a, b)/clen;
+}
+
+static PBool p_vert_flipped_wheel_triangle(PVert *v)
+{
+ PEdge *e = v->edge;
+
+ do {
+ if (p_face_uv_area_signed(e->face) < 0.0f)
+ return P_TRUE;
+
+ e = p_wheel_edge_next(e);
+ } while (e && (e != v->edge));
+
+ return P_FALSE;
+}
+
+static PBool p_vert_map_harmonic_weights(PVert *v)
+{
+ float weightsum, positionsum[2], olduv[2];
+
+ weightsum = 0.0f;
+ positionsum[0] = positionsum[1] = 0.0f;
+
+ if (p_vert_interior(v)) {
+ PEdge *e = v->edge;
+
+ do {
+ float t1, t2, weight;
+ PVert *v1, *v2;
+
+ v1 = e->next->vert;
+ v2 = e->next->next->vert;
+ t1 = p_vert_cotan(v2->co, e->vert->co, v1->co);
+
+ v1 = e->pair->next->vert;
+ v2 = e->pair->next->next->vert;
+ t2 = p_vert_cotan(v2->co, e->pair->vert->co, v1->co);
+
+ weight = 0.5f*(t1 + t2);
+ weightsum += weight;
+ positionsum[0] += weight*e->pair->vert->uv[0];
+ positionsum[1] += weight*e->pair->vert->uv[1];
+
+ e = p_wheel_edge_next(e);
+ } while (e && (e != v->edge));
+ }
+ else {
+ PEdge *e = v->edge;
+
+ do {
+ float t1, t2;
+ PVert *v1, *v2;
+
+ v2 = e->next->vert;
+ v1 = e->next->next->vert;
+
+ t1 = p_vert_cotan(v1->co, v->co, v2->co);
+ t2 = p_vert_cotan(v2->co, v->co, v1->co);
+
+ weightsum += t1 + t2;
+ positionsum[0] += (v2->uv[1] - v1->uv[1]) + (t1*v2->uv[0] + t2*v1->uv[0]);
+ positionsum[1] += (v1->uv[0] - v2->uv[0]) + (t1*v2->uv[1] + t2*v1->uv[1]);
+
+ e = p_wheel_edge_next(e);
+ } while (e && (e != v->edge));
+ }
+
+ if (weightsum != 0.0f) {
+ weightsum = 1.0f/weightsum;
+ positionsum[0] *= weightsum;
+ positionsum[1] *= weightsum;
+ }
+
+ olduv[0] = v->uv[0];
+ olduv[1] = v->uv[1];
+ v->uv[0] = positionsum[0];
+ v->uv[1] = positionsum[1];
+
+ if (p_vert_flipped_wheel_triangle(v)) {
+ v->uv[0] = olduv[0];
+ v->uv[1] = olduv[1];
+
+ return P_FALSE;
+ }
+
+ return P_TRUE;
+}
+
+static void p_vert_harmonic_insert(PVert *v)
+{
+ PEdge *e;
+
+ if (!p_vert_map_harmonic_weights(v)) {
+ /* do polygon kernel center insertion: this is quite slow, but should
+ only be needed for 0.01 % of verts or so, when insert with harmonic
+ weights fails */
+
+ int npoints = 0, i;
+ float (*points)[2];
+
+ e = v->edge;
+ do {
+ npoints++;
+ e = p_wheel_edge_next(e);
+ } while (e && (e != v->edge));
+
+ if (e == NULL)
+ npoints++;
+
+ points = MEM_mallocN(sizeof(float)*2*npoints, "PHarmonicPoints");
+
+ e = v->edge;
+ i = 0;
+ do {
+ PEdge *nexte = p_wheel_edge_next(e);
+
+ points[i][0] = e->next->vert->uv[0];
+ points[i][1] = e->next->vert->uv[1];
+
+ if (nexte == NULL) {
+ i++;
+ points[i][0] = e->next->next->vert->uv[0];
+ points[i][1] = e->next->next->vert->uv[1];
+ break;
+ }
+
+ e = nexte;
+ i++;
+ } while (e != v->edge);
+
+ p_polygon_kernel_center(points, npoints, v->uv);
+
+ MEM_freeN(points);
+ }
+
+ e = v->edge;
+ do {
+ if (!(e->next->vert->flag & PVERT_PIN))
+ p_vert_map_harmonic_weights(e->next->vert);
+ e = p_wheel_edge_next(e);
+ } while (e && (e != v->edge));
+
+ p_vert_map_harmonic_weights(v);
+}
+
+static void p_vert_fix_edge_pointer(PVert *v)
+{
+ PEdge *start = v->edge;
+
+ /* set v->edge pointer to the edge with no pair, if there is one */
+ while (v->edge->pair) {
+ v->edge = p_wheel_edge_prev(v->edge);
+
+ if (v->edge == start)
+ break;
+ }
+}
+
+static void p_collapsing_verts(PEdge *edge, PEdge *pair, PVert **newv, PVert **keepv)
+{
+ /* the two vertices that are involved in the collapse */
+ if (edge) {
+ *newv = edge->vert;
+ *keepv = edge->next->vert;
+ }
+ else {
+ *newv = pair->next->vert;
+ *keepv = pair->vert;
+ }
+}
+
+static void p_collapse_edge(PEdge *edge, PEdge *pair)
+{
+ PVert *oldv, *keepv;
+ PEdge *e;
+
+ p_collapsing_verts(edge, pair, &oldv, &keepv);
+
+ /* change e->vert pointers from old vertex to the target vertex */
+ e = oldv->edge;
+ do {
+ if ((e != edge) && !(pair && pair->next == e))
+ e->vert = keepv;
+
+ e = p_wheel_edge_next(e);
+ } while (e && (e != oldv->edge));
+
+ /* set keepv->edge pointer */
+ if ((edge && (keepv->edge == edge->next)) || (keepv->edge == pair)) {
+ if (edge && edge->next->pair)
+ keepv->edge = edge->next->pair->next;
+ else if (pair && pair->next->next->pair)
+ keepv->edge = pair->next->next->pair;
+ else if (edge && edge->next->next->pair)
+ keepv->edge = edge->next->next->pair;
+ else
+ keepv->edge = pair->next->pair->next;
+ }
+
+ /* update pairs and v->edge pointers */
+ if (edge) {
+ PEdge *e1 = edge->next, *e2 = e1->next;
+
+ if (e1->pair)
+ e1->pair->pair = e2->pair;
+
+ if (e2->pair) {
+ e2->pair->pair = e1->pair;
+ e2->vert->edge = p_wheel_edge_prev(e2);
+ }
+ else
+ e2->vert->edge = p_wheel_edge_next(e2);
+
+ p_vert_fix_edge_pointer(e2->vert);
+ }
+
+ if (pair) {
+ PEdge *e1 = pair->next, *e2 = e1->next;
+
+ if (e1->pair)
+ e1->pair->pair = e2->pair;
+
+ if (e2->pair) {
+ e2->pair->pair = e1->pair;
+ e2->vert->edge = p_wheel_edge_prev(e2);
+ }
+ else
+ e2->vert->edge = p_wheel_edge_next(e2);
+
+ p_vert_fix_edge_pointer(e2->vert);
+ }
+
+ p_vert_fix_edge_pointer(keepv);
+
+ /* mark for move to collapsed list later */
+ oldv->flag |= PVERT_COLLAPSE;
+
+ if (edge) {
+ PFace *f = edge->face;
+ PEdge *e1 = edge->next, *e2 = e1->next;
+
+ f->flag |= PFACE_COLLAPSE;
+ edge->flag |= PEDGE_COLLAPSE;
+ e1->flag |= PEDGE_COLLAPSE;
+ e2->flag |= PEDGE_COLLAPSE;
+ }
+
+ if (pair) {
+ PFace *f = pair->face;
+ PEdge *e1 = pair->next, *e2 = e1->next;
+
+ f->flag |= PFACE_COLLAPSE;
+ pair->flag |= PEDGE_COLLAPSE;
+ e1->flag |= PEDGE_COLLAPSE;
+ e2->flag |= PEDGE_COLLAPSE;
+ }
+}
+
+static void p_split_vertex(PEdge *edge, PEdge *pair)
+{
+ PVert *newv, *keepv;
+ PEdge *e;
+
+ p_collapsing_verts(edge, pair, &newv, &keepv);
+
+ /* update edge pairs */
+ if (edge) {
+ PEdge *e1 = edge->next, *e2 = e1->next;
+
+ if (e1->pair)
+ e1->pair->pair = e1;
+ if (e2->pair)
+ e2->pair->pair = e2;
+
+ e2->vert->edge = e2;
+ p_vert_fix_edge_pointer(e2->vert);
+ keepv->edge = e1;
+ }
+
+ if (pair) {
+ PEdge *e1 = pair->next, *e2 = e1->next;
+
+ if (e1->pair)
+ e1->pair->pair = e1;
+ if (e2->pair)
+ e2->pair->pair = e2;
+
+ e2->vert->edge = e2;
+ p_vert_fix_edge_pointer(e2->vert);
+ keepv->edge = pair;
+ }
+
+ p_vert_fix_edge_pointer(keepv);
+
+ /* set e->vert pointers to restored vertex */
+ e = newv->edge;
+ do {
+ e->vert = newv;
+ e = p_wheel_edge_next(e);
+ } while (e && (e != newv->edge));
+}
+
+static PBool p_collapse_allowed_topologic(PEdge *edge, PEdge *pair)
+{
+ PVert *oldv, *keepv;
+
+ p_collapsing_verts(edge, pair, &oldv, &keepv);
+
+ /* boundary edges */
+ if (!edge || !pair) {
+ /* avoid collapsing chart into an edge */
+ if (edge && !edge->next->pair && !edge->next->next->pair)
+ return P_FALSE;
+ else if (pair && !pair->next->pair && !pair->next->next->pair)
+ return P_FALSE;
+ }
+ /* avoid merging two boundaries (oldv and keepv are on the 'other side' of
+ the chart) */
+ else if (!p_vert_interior(oldv) && !p_vert_interior(keepv))
+ return P_FALSE;
+
+ return P_TRUE;
+}
+
+static PBool p_collapse_normal_flipped(float *v1, float *v2, float *vold, float *vnew)
+{
+ float nold[3], nnew[3], sub1[3], sub2[3];
+
+ VecSubf(sub1, vold, v1);
+ VecSubf(sub2, vold, v2);
+ Crossf(nold, sub1, sub2);
+
+ VecSubf(sub1, vnew, v1);
+ VecSubf(sub2, vnew, v2);
+ Crossf(nnew, sub1, sub2);
+
+ return (Inpf(nold, nnew) <= 0.0f);
+}
+
+static PBool p_collapse_allowed_geometric(PEdge *edge, PEdge *pair)
+{
+ PVert *oldv, *keepv;
+ PEdge *e;
+ float angulardefect, angle;
+
+ p_collapsing_verts(edge, pair, &oldv, &keepv);
+
+ angulardefect = 2*M_PI;
+
+ e = oldv->edge;
+ do {
+ float a[3], b[3], minangle, maxangle;
+ PEdge *e1 = e->next, *e2 = e1->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert;
+ int i;
+
+ angle = p_vec_angle(v1->co, oldv->co, v2->co);
+ angulardefect -= angle;
+
+ /* skip collapsing faces */
+ if (v1 == keepv || v2 == keepv) {
+ e = p_wheel_edge_next(e);
+ continue;
+ }
+
+ if (p_collapse_normal_flipped(v1->co, v2->co, oldv->co, keepv->co))
+ return P_FALSE;
+
+ a[0] = angle;
+ a[1] = p_vec_angle(v2->co, v1->co, oldv->co);
+ a[2] = M_PI - a[0] - a[1];
+
+ b[0] = p_vec_angle(v1->co, keepv->co, v2->co);
+ b[1] = p_vec_angle(v2->co, v1->co, keepv->co);
+ b[2] = M_PI - b[0] - b[1];
+
+ /* abf criterion 1: avoid sharp and obtuse angles */
+ minangle = 15.0f*M_PI/180.0f;
+ maxangle = M_PI - minangle;
+
+ for (i = 0; i < 3; i++) {
+ if ((b[i] < a[i]) && (b[i] < minangle))
+ return P_FALSE;
+ else if ((b[i] > a[i]) && (b[i] > maxangle))
+ return P_FALSE;
+ }
+
+ e = p_wheel_edge_next(e);
+ } while (e && (e != oldv->edge));
+
+ if (p_vert_interior(oldv)) {
+ /* hlscm criterion: angular defect smaller than threshold */
+ if (fabs(angulardefect) > (M_PI*30.0/180.0))
+ return P_FALSE;
+ }
+ else {
+ PVert *v1 = p_boundary_edge_next(oldv->edge)->vert;
+ PVert *v2 = p_boundary_edge_prev(oldv->edge)->vert;
+
+ /* abf++ criterion 2: avoid collapsing verts inwards */
+ if (p_vert_interior(keepv))
+ return P_FALSE;
+
+ /* don't collapse significant boundary changes */
+ angle = p_vec_angle(v1->co, oldv->co, v2->co);
+ if (angle < (M_PI*160.0/180.0))
+ return P_FALSE;
+ }
+
+ return P_TRUE;
+}
+
+static PBool p_collapse_allowed(PEdge *edge, PEdge *pair)
+{
+ PVert *oldv, *keepv;
+
+ p_collapsing_verts(edge, pair, &oldv, &keepv);
+
+ if (oldv->flag & PVERT_PIN)
+ return P_FALSE;
+
+ return (p_collapse_allowed_topologic(edge, pair) &&
+ p_collapse_allowed_geometric(edge, pair));
+}
+
+static float p_collapse_cost(PEdge *edge, PEdge *pair)
+{
+ /* based on volume and boundary optimization from:
+ "Fast and Memory Efficient Polygonal Simplification" P. Lindstrom, G. Turk */
+
+ PVert *oldv, *keepv;
+ PEdge *e;
+ PFace *oldf1, *oldf2;
+ float volumecost = 0.0f, areacost = 0.0f, edgevec[3], cost, weight, elen;
+ float shapecost = 0.0f;
+ float shapeold = 0.0f, shapenew = 0.0f;
+ int nshapeold = 0, nshapenew = 0;
+
+ p_collapsing_verts(edge, pair, &oldv, &keepv);
+ oldf1 = (edge)? edge->face: NULL;
+ oldf2 = (pair)? pair->face: NULL;
+
+ VecSubf(edgevec, keepv->co, oldv->co);
+
+ e = oldv->edge;
+ do {
+ float a1, a2, a3;
+ float *co1 = e->next->vert->co;
+ float *co2 = e->next->next->vert->co;
+
+ if ((e->face != oldf1) && (e->face != oldf2)) {
+ float tetrav2[3], tetrav3[3], c[3];
+
+ /* tetrahedron volume = (1/3!)*|a.(b x c)| */
+ VecSubf(tetrav2, co1, oldv->co);
+ VecSubf(tetrav3, co2, oldv->co);
+ Crossf(c, tetrav2, tetrav3);
+
+ volumecost += fabs(Inpf(edgevec, c)/6.0f);
+#if 0
+ shapecost += Inpf(co1, keepv->co);
+
+ if (p_wheel_edge_next(e) == NULL)
+ shapecost += Inpf(co2, keepv->co);
+#endif
+
+ p_triangle_angles(oldv->co, co1, co2, &a1, &a2, &a3);
+ a1 = a1 - M_PI/3.0;
+ a2 = a2 - M_PI/3.0;
+ a3 = a3 - M_PI/3.0;
+ shapeold = (a1*a1 + a2*a2 + a3*a3)/((M_PI/2)*(M_PI/2));
+
+ nshapeold++;
+ }
+ else {
+ p_triangle_angles(keepv->co, co1, co2, &a1, &a2, &a3);
+ a1 = a1 - M_PI/3.0;
+ a2 = a2 - M_PI/3.0;
+ a3 = a3 - M_PI/3.0;
+ shapenew = (a1*a1 + a2*a2 + a3*a3)/((M_PI/2)*(M_PI/2));
+
+ nshapenew++;
+ }
+
+ e = p_wheel_edge_next(e);
+ } while (e && (e != oldv->edge));
+
+ if (!p_vert_interior(oldv)) {
+ PVert *v1 = p_boundary_edge_prev(oldv->edge)->vert;
+ PVert *v2 = p_boundary_edge_next(oldv->edge)->vert;
+
+ areacost = AreaT3Dfl(oldv->co, v1->co, v2->co);
+ }
+
+ elen = VecLength(edgevec);
+ weight = 1.0f; /* 0.2f */
+ cost = weight*volumecost*volumecost + elen*elen*areacost*areacost;
+#if 0
+ cost += shapecost;
+#else
+ shapeold /= nshapeold;
+ shapenew /= nshapenew;
+ shapecost = (shapeold + 0.00001)/(shapenew + 0.00001);
+
+ cost *= shapecost;
+#endif
+
+ return cost;
+}
+
+static void p_collapse_cost_vertex(PVert *vert, float *mincost, PEdge **mine)
+{
+ PEdge *e, *enext, *pair;
+
+ *mine = NULL;
+ *mincost = 0.0f;
+ e = vert->edge;
+ do {
+ if (p_collapse_allowed(e, e->pair)) {
+ float cost = p_collapse_cost(e, e->pair);
+
+ if ((*mine == NULL) || (cost < *mincost)) {
+ *mincost = cost;
+ *mine = e;
+ }
+ }
+
+ enext = p_wheel_edge_next(e);
+
+ if (enext == NULL) {
+ /* the other boundary edge, where we only have the pair halfedge */
+ pair = e->next->next;
+
+ if (p_collapse_allowed(NULL, pair)) {
+ float cost = p_collapse_cost(NULL, pair);
+
+ if ((*mine == NULL) || (cost < *mincost)) {
+ *mincost = cost;
+ *mine = pair;
+ }
+ }
+
+ break;
+ }
+
+ e = enext;
+ } while (e != vert->edge);
+}
+
+static void p_chart_post_collapse_flush(PChart *chart, PEdge *collapsed)
+{
+ /* move to collapsed_ */
+
+ PVert *v, *nextv = NULL, *verts = chart->verts;
+ PEdge *e, *nexte = NULL, *edges = chart->edges, *laste = NULL;
+ PFace *f, *nextf = NULL, *faces = chart->faces;
+
+ chart->verts = chart->collapsed_verts = NULL;
+ chart->edges = chart->collapsed_edges = NULL;
+ chart->faces = chart->collapsed_faces = NULL;
+
+ chart->nverts = chart->nedges = chart->nfaces = 0;
+
+ for (v=verts; v; v=nextv) {
+ nextv = v->nextlink;
+
+ if (v->flag & PVERT_COLLAPSE) {
+ v->nextlink = chart->collapsed_verts;
+ chart->collapsed_verts = v;
+ }
+ else {
+ v->nextlink = chart->verts;
+ chart->verts = v;
+ chart->nverts++;
+ }
+ }
+
+ for (e=edges; e; e=nexte) {
+ nexte = e->nextlink;
+
+ if (!collapsed || !(e->flag & PEDGE_COLLAPSE_EDGE)) {
+ if (e->flag & PEDGE_COLLAPSE) {
+ e->nextlink = chart->collapsed_edges;
+ chart->collapsed_edges = e;
+ }
+ else {
+ e->nextlink = chart->edges;
+ chart->edges = e;
+ chart->nedges++;
+ }
+ }
+ }
+
+ /* these are added last so they can be popped of in the right order
+ for splitting */
+ for (e=collapsed; e; e=e->nextlink) {
+ e->nextlink = e->u.nextcollapse;
+ laste = e;
+ }
+ if (laste) {
+ laste->nextlink = chart->collapsed_edges;
+ chart->collapsed_edges = collapsed;
+ }
+
+ for (f=faces; f; f=nextf) {
+ nextf = f->nextlink;
+
+ if (f->flag & PFACE_COLLAPSE) {
+ f->nextlink = chart->collapsed_faces;
+ chart->collapsed_faces = f;
+ }
+ else {
+ f->nextlink = chart->faces;
+ chart->faces = f;
+ chart->nfaces++;
+ }
+ }
+}
+
+static void p_chart_post_split_flush(PChart *chart)
+{
+ /* move from collapsed_ */
+
+ PVert *v, *nextv = NULL;
+ PEdge *e, *nexte = NULL;
+ PFace *f, *nextf = NULL;
+
+ for (v=chart->collapsed_verts; v; v=nextv) {
+ nextv = v->nextlink;
+ v->nextlink = chart->verts;
+ chart->verts = v;
+ chart->nverts++;
+ }
+
+ for (e=chart->collapsed_edges; e; e=nexte) {
+ nexte = e->nextlink;
+ e->nextlink = chart->edges;
+ chart->edges = e;
+ chart->nedges++;
+ }
+
+ for (f=chart->collapsed_faces; f; f=nextf) {
+ nextf = f->nextlink;
+ f->nextlink = chart->faces;
+ chart->faces = f;
+ chart->nfaces++;
+ }
+
+ chart->collapsed_verts = NULL;
+ chart->collapsed_edges = NULL;
+ chart->collapsed_faces = NULL;
+}
+
+static void p_chart_simplify_compute(PChart *chart)
+{
+ /* Computes a list of edge collapses / vertex splits. The collapsed
+ simplices go in the chart->collapsed_* lists, The original and
+ collapsed may then be view as stacks, where the next collapse/split
+ is at the top of the respective lists. */
+
+ Heap *heap = BLI_heap_new();
+ PVert *v, **wheelverts;
+ PEdge *collapsededges = NULL, *e;
+ int nwheelverts, i, ncollapsed = 0;
+
+ wheelverts = MEM_mallocN(sizeof(PVert*)*chart->nverts, "PChartWheelVerts");
+
+ /* insert all potential collapses into heap */
+ for (v=chart->verts; v; v=v->nextlink) {
+ float cost;
+ PEdge *e = NULL;
+
+ p_collapse_cost_vertex(v, &cost, &e);
+
+ if (e)
+ v->u.heaplink = BLI_heap_insert(heap, cost, e);
+ else
+ v->u.heaplink = NULL;
+ }
+
+ for (e=chart->edges; e; e=e->nextlink)
+ e->u.nextcollapse = NULL;
+
+ /* pop edge collapse out of heap one by one */
+ while (!BLI_heap_empty(heap)) {
+ if (ncollapsed == NCOLLAPSE)
+ break;
+
+ HeapNode *link = BLI_heap_top(heap);
+ PEdge *edge = (PEdge*)BLI_heap_popmin(heap), *pair = edge->pair;
+ PVert *oldv, *keepv;
+ PEdge *wheele, *nexte;
+
+ /* remember the edges we collapsed */
+ edge->u.nextcollapse = collapsededges;
+ collapsededges = edge;
+
+ if (edge->vert->u.heaplink != link) {
+ edge->flag |= (PEDGE_COLLAPSE_EDGE|PEDGE_COLLAPSE_PAIR);
+ edge->next->vert->u.heaplink = NULL;
+ SWAP(PEdge*, edge, pair);
+ }
+ else {
+ edge->flag |= PEDGE_COLLAPSE_EDGE;
+ edge->vert->u.heaplink = NULL;
+ }
+
+ p_collapsing_verts(edge, pair, &oldv, &keepv);
+
+ /* gather all wheel verts and remember them before collapse */
+ nwheelverts = 0;
+ wheele = oldv->edge;
+
+ do {
+ wheelverts[nwheelverts++] = wheele->next->vert;
+ nexte = p_wheel_edge_next(wheele);
+
+ if (nexte == NULL)
+ wheelverts[nwheelverts++] = wheele->next->next->vert;
+
+ wheele = nexte;
+ } while (wheele && (wheele != oldv->edge));
+
+ /* collapse */
+ p_collapse_edge(edge, pair);
+
+ for (i = 0; i < nwheelverts; i++) {
+ float cost;
+ PEdge *collapse = NULL;
+
+ v = wheelverts[i];
+
+ if (v->u.heaplink) {
+ BLI_heap_remove(heap, v->u.heaplink);
+ v->u.heaplink = NULL;
+ }
+
+ p_collapse_cost_vertex(v, &cost, &collapse);
+
+ if (collapse)
+ v->u.heaplink = BLI_heap_insert(heap, cost, collapse);
+ }
+
+ ncollapsed++;
+ }
+
+ MEM_freeN(wheelverts);
+ BLI_heap_free(heap, NULL);
+
+ p_chart_post_collapse_flush(chart, collapsededges);
+}
+
+static void p_chart_complexify(PChart *chart)
+{
+ PEdge *e, *pair, *edge;
+ PVert *newv, *keepv;
+ int x = 0;
+
+ for (e=chart->collapsed_edges; e; e=e->nextlink) {
+ if (!(e->flag & PEDGE_COLLAPSE_EDGE))
+ break;
+
+ edge = e;
+ pair = e->pair;
+
+ if (edge->flag & PEDGE_COLLAPSE_PAIR) {
+ SWAP(PEdge*, edge, pair);
+ }
+
+ p_split_vertex(edge, pair);
+ p_collapsing_verts(edge, pair, &newv, &keepv);
+
+ if (x >= NCOLLAPSEX) {
+ newv->uv[0] = keepv->uv[0];
+ newv->uv[1] = keepv->uv[1];
+ }
+ else {
+ p_vert_harmonic_insert(newv);
+ x++;
+ }
+ }
+
+ p_chart_post_split_flush(chart);
+}
+
+#if 0
+static void p_chart_simplify(PChart *chart)
+{
+ /* Not implemented, needs proper reordering in split_flush. */
+}
+#endif
+#endif
+
+/* ABF */
+
+#define ABF_MAX_ITER 20
+
+typedef struct PAbfSystem {
+ int ninterior, nfaces, nangles;
+ float *alpha, *beta, *sine, *cosine, *weight;
+ float *bAlpha, *bTriangle, *bInterior;
+ float *lambdaTriangle, *lambdaPlanar, *lambdaLength;
+ float (*J2dt)[3], *bstar, *dstar;
+ float minangle, maxangle;
+} PAbfSystem;
+
+static void p_abf_setup_system(PAbfSystem *sys)
+{
+ int i;
+
+ sys->alpha = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFalpha");
+ sys->beta = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFbeta");
+ sys->sine = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFsine");
+ sys->cosine = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFcosine");
+ sys->weight = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFweight");
+
+ sys->bAlpha = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFbalpha");
+ sys->bTriangle = (float*)MEM_mallocN(sizeof(float)*sys->nfaces, "ABFbtriangle");
+ sys->bInterior = (float*)MEM_mallocN(sizeof(float)*2*sys->ninterior, "ABFbinterior");
+
+ sys->lambdaTriangle = (float*)MEM_callocN(sizeof(float)*sys->nfaces, "ABFlambdatri");
+ sys->lambdaPlanar = (float*)MEM_callocN(sizeof(float)*sys->ninterior, "ABFlamdaplane");
+ sys->lambdaLength = (float*)MEM_mallocN(sizeof(float)*sys->ninterior, "ABFlambdalen");
+
+ sys->J2dt = MEM_mallocN(sizeof(float)*sys->nangles*3, "ABFj2dt");
+ sys->bstar = (float*)MEM_mallocN(sizeof(float)*sys->nfaces, "ABFbstar");
+ sys->dstar = (float*)MEM_mallocN(sizeof(float)*sys->nfaces, "ABFdstar");
+
+ for (i = 0; i < sys->ninterior; i++)
+ sys->lambdaLength[i] = 1.0;
+
+ sys->minangle = 7.5f*M_PI/180.0f;
+ sys->maxangle = M_PI - sys->minangle;
+}
+
+static void p_abf_free_system(PAbfSystem *sys)
+{
+ MEM_freeN(sys->alpha);
+ MEM_freeN(sys->beta);
+ MEM_freeN(sys->sine);
+ MEM_freeN(sys->cosine);
+ MEM_freeN(sys->weight);
+ MEM_freeN(sys->bAlpha);
+ MEM_freeN(sys->bTriangle);
+ MEM_freeN(sys->bInterior);
+ MEM_freeN(sys->lambdaTriangle);
+ MEM_freeN(sys->lambdaPlanar);
+ MEM_freeN(sys->lambdaLength);
+ MEM_freeN(sys->J2dt);
+ MEM_freeN(sys->bstar);
+ MEM_freeN(sys->dstar);
+}
+
+static void p_abf_compute_sines(PAbfSystem *sys)
+{
+ int i;
+ float *sine = sys->sine, *cosine = sys->cosine, *alpha = sys->alpha;
+
+ for (i = 0; i < sys->nangles; i++, sine++, cosine++, alpha++) {
+ *sine = sin(*alpha);
+ *cosine = cos(*alpha);
+ }
+}
+
+static float p_abf_compute_sin_product(PAbfSystem *sys, PVert *v, int aid)
+{
+ PEdge *e, *e1, *e2;
+ float sin1, sin2;
+
+ sin1 = sin2 = 1.0;
+
+ e = v->edge;
+ do {
+ e1 = e->next;
+ e2 = e->next->next;
+
+ if (aid == e1->u.id) {
+ /* we are computing a derivative for this angle,
+ so we use cos and drop the other part */
+ sin1 *= sys->cosine[e1->u.id];
+ sin2 = 0.0;
+ }
+ else
+ sin1 *= sys->sine[e1->u.id];
+
+ if (aid == e2->u.id) {
+ /* see above */
+ sin1 = 0.0;
+ sin2 *= sys->cosine[e2->u.id];
+ }
+ else
+ sin2 *= sys->sine[e2->u.id];
+
+ e = e->next->next->pair;
+ } while (e && (e != v->edge));
+
+ return (sin1 - sin2);
+}
+
+static float p_abf_compute_grad_alpha(PAbfSystem *sys, PFace *f, PEdge *e)
+{
+ PVert *v = e->vert, *v1 = e->next->vert, *v2 = e->next->next->vert;
+ float deriv;
+
+ deriv = (sys->alpha[e->u.id] - sys->beta[e->u.id])*sys->weight[e->u.id];
+ deriv += sys->lambdaTriangle[f->u.id];
+
+ if (v->flag & PVERT_INTERIOR) {
+ deriv += sys->lambdaPlanar[v->u.id];
+ }
+
+ if (v1->flag & PVERT_INTERIOR) {
+ float product = p_abf_compute_sin_product(sys, v1, e->u.id);
+ deriv += sys->lambdaLength[v1->u.id]*product;
+ }
+
+ if (v2->flag & PVERT_INTERIOR) {
+ float product = p_abf_compute_sin_product(sys, v2, e->u.id);
+ deriv += sys->lambdaLength[v2->u.id]*product;
+ }
+
+ return deriv;
+}
+
+static float p_abf_compute_gradient(PAbfSystem *sys, PChart *chart)
+{
+ PFace *f;
+ PEdge *e;
+ PVert *v;
+ float norm = 0.0;
+
+ for (f=chart->faces; f; f=f->nextlink) {
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ float gtriangle, galpha1, galpha2, galpha3;
+
+ galpha1 = p_abf_compute_grad_alpha(sys, f, e1);
+ galpha2 = p_abf_compute_grad_alpha(sys, f, e2);
+ galpha3 = p_abf_compute_grad_alpha(sys, f, e3);
+
+ sys->bAlpha[e1->u.id] = -galpha1;
+ sys->bAlpha[e2->u.id] = -galpha2;
+ sys->bAlpha[e3->u.id] = -galpha3;
+
+ norm += galpha1*galpha1 + galpha2*galpha2 + galpha3*galpha3;
+
+ gtriangle = sys->alpha[e1->u.id] + sys->alpha[e2->u.id] + sys->alpha[e3->u.id] - M_PI;
+ sys->bTriangle[f->u.id] = -gtriangle;
+ norm += gtriangle*gtriangle;
+ }
+
+ for (v=chart->verts; v; v=v->nextlink) {
+ if (v->flag & PVERT_INTERIOR) {
+ float gplanar = -2*M_PI, glength;
+
+ e = v->edge;
+ do {
+ gplanar += sys->alpha[e->u.id];
+ e = e->next->next->pair;
+ } while (e && (e != v->edge));
+
+ sys->bInterior[v->u.id] = -gplanar;
+ norm += gplanar*gplanar;
+
+ glength = p_abf_compute_sin_product(sys, v, -1);
+ sys->bInterior[sys->ninterior + v->u.id] = -glength;
+ norm += glength*glength;
+ }
+ }
+
+ return norm;
+}
+
+static PBool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
+{
+ PFace *f;
+ PEdge *e;
+ int i, j, ninterior = sys->ninterior, nvar = 2*sys->ninterior;
+ PBool success;
+
+ nlNewContext();
+ nlSolverParameteri(NL_NB_VARIABLES, nvar);
+
+ nlBegin(NL_SYSTEM);
+
+ nlBegin(NL_MATRIX);
+
+ for (i = 0; i < nvar; i++)
+ nlRightHandSideAdd(0, i, sys->bInterior[i]);
+
+ for (f=chart->faces; f; f=f->nextlink) {
+ float wi1, wi2, wi3, b, si, beta[3], j2[3][3], W[3][3];
+ float row1[6], row2[6], row3[6];
+ int vid[6];
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+
+ wi1 = 1.0/sys->weight[e1->u.id];
+ wi2 = 1.0/sys->weight[e2->u.id];
+ wi3 = 1.0/sys->weight[e3->u.id];
+
+ /* bstar1 = (J1*dInv*bAlpha - bTriangle) */
+ b = sys->bAlpha[e1->u.id]*wi1;
+ b += sys->bAlpha[e2->u.id]*wi2;
+ b += sys->bAlpha[e3->u.id]*wi3;
+ b -= sys->bTriangle[f->u.id];
+
+ /* si = J1*d*J1t */
+ si = 1.0/(wi1 + wi2 + wi3);
+
+ /* J1t*si*bstar1 - bAlpha */
+ beta[0] = b*si - sys->bAlpha[e1->u.id];
+ beta[1] = b*si - sys->bAlpha[e2->u.id];
+ beta[2] = b*si - sys->bAlpha[e3->u.id];
+
+ /* use this later for computing other lambda's */
+ sys->bstar[f->u.id] = b;
+ sys->dstar[f->u.id] = si;
+
+ /* set matrix */
+ W[0][0] = si - sys->weight[e1->u.id]; W[0][1] = si; W[0][2] = si;
+ W[1][0] = si; W[1][1] = si - sys->weight[e2->u.id]; W[1][2] = si;
+ W[2][0] = si; W[2][1] = si; W[2][2] = si - sys->weight[e3->u.id];
+
+ vid[0] = vid[1] = vid[2] = vid[3] = vid[4] = vid[5] = -1;
+
+ if (v1->flag & PVERT_INTERIOR) {
+ vid[0] = v1->u.id;
+ vid[3] = ninterior + v1->u.id;
+
+ sys->J2dt[e1->u.id][0] = j2[0][0] = 1.0*wi1;
+ sys->J2dt[e2->u.id][0] = j2[1][0] = p_abf_compute_sin_product(sys, v1, e2->u.id)*wi2;
+ sys->J2dt[e3->u.id][0] = j2[2][0] = p_abf_compute_sin_product(sys, v1, e3->u.id)*wi3;
+
+ nlRightHandSideAdd(0, v1->u.id, j2[0][0]*beta[0]);
+ nlRightHandSideAdd(0, ninterior + v1->u.id, j2[1][0]*beta[1] + j2[2][0]*beta[2]);
+
+ row1[0] = j2[0][0]*W[0][0];
+ row2[0] = j2[0][0]*W[1][0];
+ row3[0] = j2[0][0]*W[2][0];
+
+ row1[3] = j2[1][0]*W[0][1] + j2[2][0]*W[0][2];
+ row2[3] = j2[1][0]*W[1][1] + j2[2][0]*W[1][2];
+ row3[3] = j2[1][0]*W[2][1] + j2[2][0]*W[2][2];
+ }
+
+ if (v2->flag & PVERT_INTERIOR) {
+ vid[1] = v2->u.id;
+ vid[4] = ninterior + v2->u.id;
+
+ sys->J2dt[e1->u.id][1] = j2[0][1] = p_abf_compute_sin_product(sys, v2, e1->u.id)*wi1;
+ sys->J2dt[e2->u.id][1] = j2[1][1] = 1.0*wi2;
+ sys->J2dt[e3->u.id][1] = j2[2][1] = p_abf_compute_sin_product(sys, v2, e3->u.id)*wi3;
+
+ nlRightHandSideAdd(0, v2->u.id, j2[1][1]*beta[1]);
+ nlRightHandSideAdd(0, ninterior + v2->u.id, j2[0][1]*beta[0] + j2[2][1]*beta[2]);
+
+ row1[1] = j2[1][1]*W[0][1];
+ row2[1] = j2[1][1]*W[1][1];
+ row3[1] = j2[1][1]*W[2][1];
+
+ row1[4] = j2[0][1]*W[0][0] + j2[2][1]*W[0][2];
+ row2[4] = j2[0][1]*W[1][0] + j2[2][1]*W[1][2];
+ row3[4] = j2[0][1]*W[2][0] + j2[2][1]*W[2][2];
+ }
+
+ if (v3->flag & PVERT_INTERIOR) {
+ vid[2] = v3->u.id;
+ vid[5] = ninterior + v3->u.id;
+
+ sys->J2dt[e1->u.id][2] = j2[0][2] = p_abf_compute_sin_product(sys, v3, e1->u.id)*wi1;
+ sys->J2dt[e2->u.id][2] = j2[1][2] = p_abf_compute_sin_product(sys, v3, e2->u.id)*wi2;
+ sys->J2dt[e3->u.id][2] = j2[2][2] = 1.0*wi3;
+
+ nlRightHandSideAdd(0, v3->u.id, j2[2][2]*beta[2]);
+ nlRightHandSideAdd(0, ninterior + v3->u.id, j2[0][2]*beta[0] + j2[1][2]*beta[1]);
+
+ row1[2] = j2[2][2]*W[0][2];
+ row2[2] = j2[2][2]*W[1][2];
+ row3[2] = j2[2][2]*W[2][2];
+
+ row1[5] = j2[0][2]*W[0][0] + j2[1][2]*W[0][1];
+ row2[5] = j2[0][2]*W[1][0] + j2[1][2]*W[1][1];
+ row3[5] = j2[0][2]*W[2][0] + j2[1][2]*W[2][1];
+ }
+
+ for (i = 0; i < 3; i++) {
+ int r = vid[i];
+
+ if (r == -1)
+ continue;
+
+ for (j = 0; j < 6; j++) {
+ int c = vid[j];
+
+ if (c == -1)
+ continue;
+
+ if (i == 0)
+ nlMatrixAdd(r, c, j2[0][i]*row1[j]);
+ else
+ nlMatrixAdd(r + ninterior, c, j2[0][i]*row1[j]);
+
+ if (i == 1)
+ nlMatrixAdd(r, c, j2[1][i]*row2[j]);
+ else
+ nlMatrixAdd(r + ninterior, c, j2[1][i]*row2[j]);
+
+
+ if (i == 2)
+ nlMatrixAdd(r, c, j2[2][i]*row3[j]);
+ else
+ nlMatrixAdd(r + ninterior, c, j2[2][i]*row3[j]);
+ }
+ }
+ }
+
+ nlEnd(NL_MATRIX);
+
+ nlEnd(NL_SYSTEM);
+
+ success = nlSolve();
+
+ if (success) {
+ for (f=chart->faces; f; f=f->nextlink) {
+ float dlambda1, pre[3], dalpha;
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+
+ pre[0] = pre[1] = pre[2] = 0.0;
+
+ if (v1->flag & PVERT_INTERIOR) {
+ float x = nlGetVariable(0, v1->u.id);
+ float x2 = nlGetVariable(0, ninterior + v1->u.id);
+ pre[0] += sys->J2dt[e1->u.id][0]*x;
+ pre[1] += sys->J2dt[e2->u.id][0]*x2;
+ pre[2] += sys->J2dt[e3->u.id][0]*x2;
+ }
+
+ if (v2->flag & PVERT_INTERIOR) {
+ float x = nlGetVariable(0, v2->u.id);
+ float x2 = nlGetVariable(0, ninterior + v2->u.id);
+ pre[0] += sys->J2dt[e1->u.id][1]*x2;
+ pre[1] += sys->J2dt[e2->u.id][1]*x;
+ pre[2] += sys->J2dt[e3->u.id][1]*x2;
+ }
+
+ if (v3->flag & PVERT_INTERIOR) {
+ float x = nlGetVariable(0, v3->u.id);
+ float x2 = nlGetVariable(0, ninterior + v3->u.id);
+ pre[0] += sys->J2dt[e1->u.id][2]*x2;
+ pre[1] += sys->J2dt[e2->u.id][2]*x2;
+ pre[2] += sys->J2dt[e3->u.id][2]*x;
+ }
+
+ dlambda1 = pre[0] + pre[1] + pre[2];
+ dlambda1 = sys->dstar[f->u.id]*(sys->bstar[f->u.id] - dlambda1);
+
+ sys->lambdaTriangle[f->u.id] += dlambda1;
+
+ dalpha = (sys->bAlpha[e1->u.id] - dlambda1);
+ sys->alpha[e1->u.id] += dalpha/sys->weight[e1->u.id] - pre[0];
+
+ dalpha = (sys->bAlpha[e2->u.id] - dlambda1);
+ sys->alpha[e2->u.id] += dalpha/sys->weight[e2->u.id] - pre[1];
+
+ dalpha = (sys->bAlpha[e3->u.id] - dlambda1);
+ sys->alpha[e3->u.id] += dalpha/sys->weight[e3->u.id] - pre[2];
+
+ /* clamp */
+ e = f->edge;
+ do {
+ if (sys->alpha[e->u.id] > M_PI)
+ sys->alpha[e->u.id] = M_PI;
+ else if (sys->alpha[e->u.id] < 0.0f)
+ sys->alpha[e->u.id] = 0.0f;
+ } while (e != f->edge);
+ }
+
+ for (i = 0; i < ninterior; i++) {
+ sys->lambdaPlanar[i] += nlGetVariable(0, i);
+ sys->lambdaLength[i] += nlGetVariable(0, ninterior + i);
+ }
+ }
+
+ nlDeleteContext(nlGetCurrent());
+
+ return success;
+}
+
+static PBool p_chart_abf_solve(PChart *chart)
+{
+ PVert *v;
+ PFace *f;
+ PEdge *e, *e1, *e2, *e3;
+ PAbfSystem sys;
+ int i;
+ float lastnorm, limit = (chart->nfaces > 100)? 1.0f: 0.001f;
+
+ /* setup id's */
+ sys.ninterior = sys.nfaces = sys.nangles = 0;
+
+ for (v=chart->verts; v; v=v->nextlink) {
+ if (p_vert_interior(v)) {
+ v->flag |= PVERT_INTERIOR;
+ v->u.id = sys.ninterior++;
+ }
+ else
+ v->flag &= ~PVERT_INTERIOR;
+ }
+
+ for (f=chart->faces; f; f=f->nextlink) {
+ e1 = f->edge; e2 = e1->next; e3 = e2->next;
+ f->u.id = sys.nfaces++;
+
+ /* angle id's are conveniently stored in half edges */
+ e1->u.id = sys.nangles++;
+ e2->u.id = sys.nangles++;
+ e3->u.id = sys.nangles++;
+ }
+
+ p_abf_setup_system(&sys);
+
+ /* compute initial angles */
+ for (f=chart->faces; f; f=f->nextlink) {
+ float a1, a2, a3;
+
+ e1 = f->edge; e2 = e1->next; e3 = e2->next;
+ p_face_angles(f, &a1, &a2, &a3);
+
+ if (a1 < sys.minangle)
+ a1 = sys.minangle;
+ else if (a1 > sys.maxangle)
+ a1 = sys.maxangle;
+ if (a2 < sys.minangle)
+ a2 = sys.minangle;
+ else if (a2 > sys.maxangle)
+ a2 = sys.maxangle;
+ if (a3 < sys.minangle)
+ a3 = sys.minangle;
+ else if (a3 > sys.maxangle)
+ a3 = sys.maxangle;
+
+ sys.alpha[e1->u.id] = sys.beta[e1->u.id] = a1;
+ sys.alpha[e2->u.id] = sys.beta[e2->u.id] = a2;
+ sys.alpha[e3->u.id] = sys.beta[e3->u.id] = a3;
+
+ sys.weight[e1->u.id] = 2.0/(a1*a1);
+ sys.weight[e2->u.id] = 2.0/(a2*a2);
+ sys.weight[e3->u.id] = 2.0/(a3*a3);
+ }
+
+ for (v=chart->verts; v; v=v->nextlink) {
+ if (v->flag & PVERT_INTERIOR) {
+ float anglesum = 0.0, scale;
+
+ e = v->edge;
+ do {
+ anglesum += sys.beta[e->u.id];
+ e = e->next->next->pair;
+ } while (e && (e != v->edge));
+
+ scale = (anglesum == 0.0f)? 0.0f: 2*M_PI/anglesum;
+
+ e = v->edge;
+ do {
+ sys.beta[e->u.id] = sys.alpha[e->u.id] = sys.beta[e->u.id]*scale;
+ e = e->next->next->pair;
+ } while (e && (e != v->edge));
+ }
+ }
+
+ if (sys.ninterior > 0) {
+ p_abf_compute_sines(&sys);
+
+ /* iteration */
+ lastnorm = 1e10;
+
+ for (i = 0; i < ABF_MAX_ITER; i++) {
+ float norm = p_abf_compute_gradient(&sys, chart);
+
+ lastnorm = norm;
+
+ if (norm < limit)
+ break;
+
+ if (!p_abf_matrix_invert(&sys, chart)) {
+ param_warning("ABF failed to invert matrix.");
+ p_abf_free_system(&sys);
+ return P_FALSE;
+ }
+
+ p_abf_compute_sines(&sys);
+ }
+
+ if (i == ABF_MAX_ITER) {
+ param_warning("ABF maximum iterations reached.");
+ p_abf_free_system(&sys);
+ return P_FALSE;
+ }
+ }
+
+ chart->u.lscm.abf_alpha = MEM_dupallocN(sys.alpha);
+ p_abf_free_system(&sys);
+
+ return P_TRUE;
+}
+
+/* Least Squares Conformal Maps */
+
+static void p_chart_pin_positions(PChart *chart, PVert **pin1, PVert **pin2)
+{
+ if (pin1 == pin2) {
+ /* degenerate case */
+ PFace *f = chart->faces;
+ *pin1 = f->edge->vert;
+ *pin2 = f->edge->next->vert;
+
+ (*pin1)->uv[0] = 0.0f;
+ (*pin1)->uv[1] = 0.5f;
+ (*pin2)->uv[0] = 1.0f;
+ (*pin2)->uv[1] = 0.5f;
+ }
+ else {
+ int diru, dirv, dirx, diry;
+ float sub[3];
+
+ VecSubf(sub, (*pin1)->co, (*pin2)->co);
+ sub[0] = fabs(sub[0]);
+ sub[1] = fabs(sub[1]);
+ sub[2] = fabs(sub[2]);
+
+ if ((sub[0] > sub[1]) && (sub[0] > sub[2])) {
+ dirx = 0;
+ diry = (sub[1] > sub[2])? 1: 2;
+ }
+ else if ((sub[1] > sub[0]) && (sub[1] > sub[2])) {
+ dirx = 1;
+ diry = (sub[0] > sub[2])? 0: 2;
+ }
+ else {
+ dirx = 2;
+ diry = (sub[0] > sub[1])? 0: 1;
+ }
+
+ if (dirx == 2) {
+ diru = 1;
+ dirv = 0;
+ }
+ else {
+ diru = 0;
+ dirv = 1;
+ }
+
+ (*pin1)->uv[diru] = (*pin1)->co[dirx];
+ (*pin1)->uv[dirv] = (*pin1)->co[diry];
+ (*pin2)->uv[diru] = (*pin2)->co[dirx];
+ (*pin2)->uv[dirv] = (*pin2)->co[diry];
+ }
+}
+
+static PBool p_chart_symmetry_pins(PChart *chart, PEdge *outer, PVert **pin1, PVert **pin2)
+{
+ PEdge *be, *lastbe = NULL, *maxe1 = NULL, *maxe2 = NULL, *be1, *be2;
+ PEdge *cure = NULL, *firste1 = NULL, *firste2 = NULL, *nextbe;
+ float maxlen = 0.0f, curlen = 0.0f, totlen = 0.0f, firstlen = 0.0f;
+ float len1, len2;
+
+ /* find longest series of verts split in the chart itself, these are
+ marked during construction */
+ be = outer;
+ lastbe = p_boundary_edge_prev(be);
+ do {
+ float len = p_edge_length(be);
+ totlen += len;
+
+ nextbe = p_boundary_edge_next(be);
+
+ if ((be->vert->flag & PVERT_SPLIT) ||
+ (lastbe->vert->flag & nextbe->vert->flag & PVERT_SPLIT)) {
+ if (!cure) {
+ if (be == outer)
+ firste1 = be;
+ cure = be;
+ }
+ else
+ curlen += p_edge_length(lastbe);
+ }
+ else if (cure) {
+ if (curlen > maxlen) {
+ maxlen = curlen;
+ maxe1 = cure;
+ maxe2 = lastbe;
+ }
+
+ if (firste1 == cure) {
+ firstlen = curlen;
+ firste2 = lastbe;
+ }
+
+ curlen = 0.0f;
+ cure = NULL;
+ }
+
+ lastbe = be;
+ be = nextbe;
+ } while(be != outer);
+
+ /* make sure we also count a series of splits over the starting point */
+ if (cure && (cure != outer)) {
+ firstlen += curlen + p_edge_length(be);
+
+ if (firstlen > maxlen) {
+ maxlen = firstlen;
+ maxe1 = cure;
+ maxe2 = firste2;
+ }
+ }
+
+ if (!maxe1 || !maxe2 || (maxlen < 0.5f*totlen))
+ return P_FALSE;
+
+ /* find pin1 in the split vertices */
+ be1 = maxe1;
+ be2 = maxe2;
+ len1 = 0.0f;
+ len2 = 0.0f;
+
+ do {
+ if (len1 < len2) {
+ len1 += p_edge_length(be1);
+ be1 = p_boundary_edge_next(be1);
+ }
+ else {
+ be2 = p_boundary_edge_prev(be2);
+ len2 += p_edge_length(be2);
+ }
+ } while (be1 != be2);
+
+ *pin1 = be1->vert;
+
+ /* find pin2 outside the split vertices */
+ be1 = maxe1;
+ be2 = maxe2;
+ len1 = 0.0f;
+ len2 = 0.0f;
+
+ do {
+ if (len1 < len2) {
+ be1 = p_boundary_edge_prev(be1);
+ len1 += p_edge_length(be1);
+ }
+ else {
+ len2 += p_edge_length(be2);
+ be2 = p_boundary_edge_next(be2);
+ }
+ } while (be1 != be2);
+
+ *pin2 = be1->vert;
+
+ p_chart_pin_positions(chart, pin1, pin2);
+
+ return P_TRUE;
+}
+
+static void p_chart_extrema_verts(PChart *chart, PVert **pin1, PVert **pin2)
+{
+ float minv[3], maxv[3], dirlen;
+ PVert *v, *minvert[3], *maxvert[3];
+ int i, dir;
+
+ /* find minimum and maximum verts over x/y/z axes */
+ minv[0] = minv[1] = minv[2] = 1e20;
+ maxv[0] = maxv[1] = maxv[2] = -1e20;
+
+ minvert[0] = minvert[1] = minvert[2] = NULL;
+ maxvert[0] = maxvert[1] = maxvert[2] = NULL;
+
+ for (v = chart->verts; v; v=v->nextlink) {
+ for (i = 0; i < 3; i++) {
+ if (v->co[i] < minv[i]) {
+ minv[i] = v->co[i];
+ minvert[i] = v;
+ }
+ if (v->co[i] > maxv[i]) {
+ maxv[i] = v->co[i];
+ maxvert[i] = v;
+ }
+ }
+ }
+
+ /* find axes with longest distance */
+ dir = 0;
+ dirlen = -1.0;
+
+ for (i = 0; i < 3; i++) {
+ if (maxv[i] - minv[i] > dirlen) {
+ dir = i;
+ dirlen = maxv[i] - minv[i];
+ }
+ }
+
+ *pin1 = minvert[dir];
+ *pin2 = maxvert[dir];
+
+ p_chart_pin_positions(chart, pin1, pin2);
+}
+
+static void p_chart_lscm_load_solution(PChart *chart)
+{
+ PVert *v;
+
+ for (v=chart->verts; v; v=v->nextlink) {
+ v->uv[0] = nlGetVariable(0, 2*v->u.id);
+ v->uv[1] = nlGetVariable(0, 2*v->u.id + 1);
+ }
+}
+
+static void p_chart_lscm_begin(PChart *chart, PBool live, PBool abf)
+{
+ PVert *v, *pin1, *pin2;
+ PBool select = P_FALSE, deselect = P_FALSE;
+ int npins = 0, id = 0;
+
+ /* give vertices matrix indices and count pins */
+ for (v=chart->verts; v; v=v->nextlink) {
+ if (v->flag & PVERT_PIN) {
+ npins++;
+ if (v->flag & PVERT_SELECT)
+ select = P_TRUE;
+ }
+
+ if (!(v->flag & PVERT_SELECT))
+ deselect = P_TRUE;
+ }
+
+ if ((live && (!select || !deselect)) || (npins == 1)) {
+ chart->u.lscm.context = NULL;
+ }
+ else {
+#if 0
+ p_chart_simplify_compute(chart);
+ p_chart_topological_sanity_check(chart);
+#endif
+
+ if (abf) {
+ if (!p_chart_abf_solve(chart))
+ param_warning("ABF solving failed: falling back to LSCM.\n");
+ }
+
+ if (npins <= 1) {
+ /* not enough pins, lets find some ourself */
+ PEdge *outer;
+
+ p_chart_boundaries(chart, NULL, &outer);
+
+ if (!p_chart_symmetry_pins(chart, outer, &pin1, &pin2))
+ p_chart_extrema_verts(chart, &pin1, &pin2);
+
+ chart->u.lscm.pin1 = pin1;
+ chart->u.lscm.pin2 = pin2;
+ }
+ else {
+ chart->flag |= PCHART_NOPACK;
+ }
+
+ for (v=chart->verts; v; v=v->nextlink)
+ v->u.id = id++;
+
+ nlNewContext();
+ nlSolverParameteri(NL_NB_VARIABLES, 2*chart->nverts);
+ nlSolverParameteri(NL_NB_ROWS, 2*chart->nfaces);
+ nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
+
+ chart->u.lscm.context = nlGetCurrent();
+ }
+}
+
+static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
+{
+ PVert *v, *pin1 = chart->u.lscm.pin1, *pin2 = chart->u.lscm.pin2;
+ PFace *f;
+ float *alpha = chart->u.lscm.abf_alpha;
+ int row;
+
+ nlMakeCurrent(chart->u.lscm.context);
+
+ nlBegin(NL_SYSTEM);
+
+#if 0
+ /* TODO: make loading pins work for simplify/complexify. */
+#endif
+
+ for (v=chart->verts; v; v=v->nextlink)
+ if (v->flag & PVERT_PIN)
+ p_vert_load_pin_select_uvs(handle, v); /* reload for live */
+
+ if (chart->u.lscm.pin1) {
+ nlLockVariable(2*pin1->u.id);
+ nlLockVariable(2*pin1->u.id + 1);
+ nlLockVariable(2*pin2->u.id);
+ nlLockVariable(2*pin2->u.id + 1);
+
+ nlSetVariable(0, 2*pin1->u.id, pin1->uv[0]);
+ nlSetVariable(0, 2*pin1->u.id + 1, pin1->uv[1]);
+ nlSetVariable(0, 2*pin2->u.id, pin2->uv[0]);
+ nlSetVariable(0, 2*pin2->u.id + 1, pin2->uv[1]);
+ }
+ else {
+ /* set and lock the pins */
+ for (v=chart->verts; v; v=v->nextlink) {
+ if (v->flag & PVERT_PIN) {
+ nlLockVariable(2*v->u.id);
+ nlLockVariable(2*v->u.id + 1);
+
+ nlSetVariable(0, 2*v->u.id, v->uv[0]);
+ nlSetVariable(0, 2*v->u.id + 1, v->uv[1]);
+ }
+ }
+ }
+
+ /* construct matrix */
+
+ nlBegin(NL_MATRIX);
+
+ row = 0;
+ for (f=chart->faces; f; f=f->nextlink) {
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+ float a1, a2, a3, ratio, cosine, sine;
+ float sina1, sina2, sina3, sinmax;
+
+ if (alpha) {
+ /* use abf angles if passed on */
+ a1 = *(alpha++);
+ a2 = *(alpha++);
+ a3 = *(alpha++);
+ }
+ else
+ p_face_angles(f, &a1, &a2, &a3);
+
+ sina1 = sin(a1);
+ sina2 = sin(a2);
+ sina3 = sin(a3);
+
+ sinmax = MAX3(sina1, sina2, sina3);
+
+ /* shift vertices to find most stable order */
+ if (sina3 != sinmax) {
+ SHIFT3(PVert*, v1, v2, v3);
+ SHIFT3(float, a1, a2, a3);
+ SHIFT3(float, sina1, sina2, sina3);
+
+ if (sina2 == sinmax) {
+ SHIFT3(PVert*, v1, v2, v3);
+ SHIFT3(float, a1, a2, a3);
+ SHIFT3(float, sina1, sina2, sina3);
+ }
+ }
+
+ /* angle based lscm formulation */
+ ratio = (sina3 == 0.0f)? 1.0f: sina2/sina3;
+ cosine = cos(a1)*ratio;
+ sine = sina1*ratio;
+
+#if 0
+ nlBegin(NL_ROW);
+ nlCoefficient(2*v1->u.id, cosine - 1.0);
+ nlCoefficient(2*v1->u.id+1, -sine);
+ nlCoefficient(2*v2->u.id, -cosine);
+ nlCoefficient(2*v2->u.id+1, sine);
+ nlCoefficient(2*v3->u.id, 1.0);
+ nlEnd(NL_ROW);
+
+ nlBegin(NL_ROW);
+ nlCoefficient(2*v1->u.id, sine);
+ nlCoefficient(2*v1->u.id+1, cosine - 1.0);
+ nlCoefficient(2*v2->u.id, -sine);
+ nlCoefficient(2*v2->u.id+1, -cosine);
+ nlCoefficient(2*v3->u.id+1, 1.0);
+ nlEnd(NL_ROW);
+#else
+ nlMatrixAdd(row, 2*v1->u.id, cosine - 1.0);
+ nlMatrixAdd(row, 2*v1->u.id+1, -sine);
+ nlMatrixAdd(row, 2*v2->u.id, -cosine);
+ nlMatrixAdd(row, 2*v2->u.id+1, sine);
+ nlMatrixAdd(row, 2*v3->u.id, 1.0);
+ row++;
+
+ nlMatrixAdd(row, 2*v1->u.id, sine);
+ nlMatrixAdd(row, 2*v1->u.id+1, cosine - 1.0);
+ nlMatrixAdd(row, 2*v2->u.id, -sine);
+ nlMatrixAdd(row, 2*v2->u.id+1, -cosine);
+ nlMatrixAdd(row, 2*v3->u.id+1, 1.0);
+ row++;
+#endif
+ }
+
+ nlEnd(NL_MATRIX);
+
+ nlEnd(NL_SYSTEM);
+
+ if (nlSolveAdvanced(NULL, NL_TRUE)) {
+ p_chart_lscm_load_solution(chart);
+ return P_TRUE;
+ }
+ else {
+ for (v=chart->verts; v; v=v->nextlink) {
+ v->uv[0] = 0.0f;
+ v->uv[1] = 0.0f;
+ }
+ }
+
+ return P_FALSE;
+}
+
+static void p_chart_lscm_end(PChart *chart)
+{
+ if (chart->u.lscm.context)
+ nlDeleteContext(chart->u.lscm.context);
+
+ if (chart->u.lscm.abf_alpha) {
+ MEM_freeN(chart->u.lscm.abf_alpha);
+ chart->u.lscm.abf_alpha = NULL;
+ }
+
+ chart->u.lscm.context = NULL;
+ chart->u.lscm.pin1 = NULL;
+ chart->u.lscm.pin2 = NULL;
+}
+
+/* Stretch */
+
+#define P_STRETCH_ITER 20
+
+static void p_stretch_pin_boundary(PChart *chart)
+{
+ PVert *v;
+
+ for(v=chart->verts; v; v=v->nextlink)
+ if (v->edge->pair == NULL)
+ v->flag |= PVERT_PIN;
+ else
+ v->flag &= ~PVERT_PIN;
+}
+
+static float p_face_stretch(PFace *f)
+{
+ float T, w, tmp[3];
+ float Ps[3], Pt[3];
+ float a, c, area;
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+
+ area = p_face_uv_area_signed(f);
+
+ if (area <= 0.0f) /* flipped face -> infinite stretch */
+ return 1e10f;
+
+ w= 1.0f/(2.0f*area);
+
+ /* compute derivatives */
+ VecCopyf(Ps, v1->co);
+ VecMulf(Ps, (v2->uv[1] - v3->uv[1]));
+
+ VecCopyf(tmp, v2->co);
+ VecMulf(tmp, (v3->uv[1] - v1->uv[1]));
+ VecAddf(Ps, Ps, tmp);
+
+ VecCopyf(tmp, v3->co);
+ VecMulf(tmp, (v1->uv[1] - v2->uv[1]));
+ VecAddf(Ps, Ps, tmp);
+
+ VecMulf(Ps, w);
+
+ VecCopyf(Pt, v1->co);
+ VecMulf(Pt, (v3->uv[0] - v2->uv[0]));
+
+ VecCopyf(tmp, v2->co);
+ VecMulf(tmp, (v1->uv[0] - v3->uv[0]));
+ VecAddf(Pt, Pt, tmp);
+
+ VecCopyf(tmp, v3->co);
+ VecMulf(tmp, (v2->uv[0] - v1->uv[0]));
+ VecAddf(Pt, Pt, tmp);
+
+ VecMulf(Pt, w);
+
+ /* Sander Tensor */
+ a= Inpf(Ps, Ps);
+ c= Inpf(Pt, Pt);
+
+ T = sqrt(0.5f*(a + c));
+ if (f->flag & PFACE_FILLED)
+ T *= 0.2;
+
+ return T;
+}
+
+static float p_stretch_compute_vertex(PVert *v)
+{
+ PEdge *e = v->edge;
+ float sum = 0.0f;
+
+ do {
+ sum += p_face_stretch(e->face);
+ e = p_wheel_edge_next(e);
+ } while (e && e != (v->edge));
+
+ return sum;
+}
+
+static void p_chart_stretch_minimize(PChart *chart, RNG *rng)
+{
+ PVert *v;
+ PEdge *e;
+ int j, nedges;
+ float orig_stretch, low, stretch_low, high, stretch_high, mid, stretch;
+ float orig_uv[2], dir[2], random_angle, trusted_radius;
+
+ for(v=chart->verts; v; v=v->nextlink) {
+ if((v->flag & PVERT_PIN) || !(v->flag & PVERT_SELECT))
+ continue;
+
+ orig_stretch = p_stretch_compute_vertex(v);
+ orig_uv[0] = v->uv[0];
+ orig_uv[1] = v->uv[1];
+
+ /* move vertex in a random direction */
+ trusted_radius = 0.0f;
+ nedges = 0;
+ e = v->edge;
+
+ do {
+ trusted_radius += p_edge_uv_length(e);
+ nedges++;
+
+ e = p_wheel_edge_next(e);
+ } while (e && e != (v->edge));
+
+ trusted_radius /= 2 * nedges;
+
+ random_angle = rng_getFloat(rng) * 2.0 * M_PI;
+ dir[0] = trusted_radius * cos(random_angle);
+ dir[1] = trusted_radius * sin(random_angle);
+
+ /* calculate old and new stretch */
+ low = 0;
+ stretch_low = orig_stretch;
+
+ Vec2Addf(v->uv, orig_uv, dir);
+ high = 1;
+ stretch = stretch_high = p_stretch_compute_vertex(v);
+
+ /* binary search for lowest stretch position */
+ for (j = 0; j < P_STRETCH_ITER; j++) {
+ mid = 0.5 * (low + high);
+ v->uv[0]= orig_uv[0] + mid*dir[0];
+ v->uv[1]= orig_uv[1] + mid*dir[1];
+ stretch = p_stretch_compute_vertex(v);
+
+ if (stretch_low < stretch_high) {
+ high = mid;
+ stretch_high = stretch;
+ }
+ else {
+ low = mid;
+ stretch_low = stretch;
+ }
+ }
+
+ /* no luck, stretch has increased, reset to old values */
+ if(stretch >= orig_stretch)
+ Vec2Copyf(v->uv, orig_uv);
+ }
+}
+
+/* Minimum area enclosing rectangle for packing */
+
+static int p_compare_geometric_uv(const void *a, const void *b)
+{
+ PVert *v1 = *(PVert**)a;
+ PVert *v2 = *(PVert**)b;
+
+ if (v1->uv[0] < v2->uv[0])
+ return -1;
+ else if (v1->uv[0] == v2->uv[0]) {
+ if (v1->uv[1] < v2->uv[1])
+ return -1;
+ else if (v1->uv[1] == v2->uv[1])
+ return 0;
+ else
+ return 1;
+ }
+ else
+ return 1;
+}
+
+static PBool p_chart_convex_hull(PChart *chart, PVert ***verts, int *nverts, int *right)
+{
+ /* Graham algorithm, taken from:
+ * http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/117225 */
+
+ PEdge *be, *e;
+ int npoints = 0, i, ulen, llen;
+ PVert **U, **L, **points, **p;
+
+ p_chart_boundaries(chart, NULL, &be);
+
+ if (!be)
+ return P_FALSE;
+
+ e = be;
+ do {
+ npoints++;
+ e = p_boundary_edge_next(e);
+ } while(e != be);
+
+ p = points = (PVert**)MEM_mallocN(sizeof(PVert*)*npoints*2, "PCHullpoints");
+ U = (PVert**)MEM_mallocN(sizeof(PVert*)*npoints, "PCHullU");
+ L = (PVert**)MEM_mallocN(sizeof(PVert*)*npoints, "PCHullL");
+
+ e = be;
+ do {
+ *p = e->vert;
+ p++;
+ e = p_boundary_edge_next(e);
+ } while(e != be);
+
+ qsort(points, npoints, sizeof(PVert*), p_compare_geometric_uv);
+
+ ulen = llen = 0;
+ for (p=points, i = 0; i < npoints; i++, p++) {
+ while ((ulen > 1) && (p_area_signed(U[ulen-2]->uv, (*p)->uv, U[ulen-1]->uv) <= 0))
+ ulen--;
+ while ((llen > 1) && (p_area_signed(L[llen-2]->uv, (*p)->uv, L[llen-1]->uv) >= 0))
+ llen--;
+
+ U[ulen] = *p;
+ ulen++;
+ L[llen] = *p;
+ llen++;
+ }
+
+ npoints = 0;
+ for (p=points, i = 0; i < ulen; i++, p++, npoints++)
+ *p = U[i];
+
+ /* the first and last point in L are left out, since they are also in U */
+ for (i = llen-2; i > 0; i--, p++, npoints++)
+ *p = L[i];
+
+ *verts = points;
+ *nverts = npoints;
+ *right = ulen - 1;
+
+ MEM_freeN(U);
+ MEM_freeN(L);
+
+ return P_TRUE;
+}
+
+static float p_rectangle_area(float *p1, float *dir, float *p2, float *p3, float *p4)
+{
+ /* given 4 points on the rectangle edges and the direction of on edge,
+ compute the area of the rectangle */
+
+ float orthodir[2], corner1[2], corner2[2], corner3[2];
+
+ orthodir[0] = dir[1];
+ orthodir[1] = -dir[0];
+
+ if (!p_intersect_line_2d_dir(p1, dir, p2, orthodir, corner1))
+ return 1e10;
+
+ if (!p_intersect_line_2d_dir(p1, dir, p4, orthodir, corner2))
+ return 1e10;
+
+ if (!p_intersect_line_2d_dir(p3, dir, p4, orthodir, corner3))
+ return 1e10;
+
+ return Vec2Lenf(corner1, corner2)*Vec2Lenf(corner2, corner3);
+}
+
+static float p_chart_minimum_area_angle(PChart *chart)
+{
+ /* minimum area enclosing rectangle with rotating calipers, info:
+ * http://cgm.cs.mcgill.ca/~orm/maer.html */
+
+ float rotated, minarea, minangle, area, len;
+ float *angles, miny, maxy, v[2], a[4], mina;
+ int npoints, right, mini, maxi, i, idx[4], nextidx;
+ PVert **points, *p1, *p2, *p3, *p4, *p1n;
+
+ /* compute convex hull */
+ if (!p_chart_convex_hull(chart, &points, &npoints, &right))
+ return 0.0;
+
+ /* find left/top/right/bottom points, and compute angle for each point */
+ angles = MEM_mallocN(sizeof(float)*npoints, "PMinAreaAngles");
+
+ mini = maxi = 0;
+ miny = 1e10;
+ maxy = -1e10;
+
+ for (i = 0; i < npoints; i++) {
+ p1 = (i == 0)? points[npoints-1]: points[i-1];
+ p2 = points[i];
+ p3 = (i == npoints-1)? points[0]: points[i+1];
+
+ angles[i] = M_PI - p_vec2_angle(p1->uv, p2->uv, p3->uv);
+
+ if (points[i]->uv[1] < miny) {
+ miny = points[i]->uv[1];
+ mini = i;
+ }
+ if (points[i]->uv[1] > maxy) {
+ maxy = points[i]->uv[1];
+ maxi = i;
+ }
+ }
+
+ /* left, top, right, bottom */
+ idx[0] = 0;
+ idx[1] = maxi;
+ idx[2] = right;
+ idx[3] = mini;
+
+ v[0] = points[idx[0]]->uv[0];
+ v[1] = points[idx[0]]->uv[1] + 1.0f;
+ a[0] = p_vec2_angle(points[(idx[0]+1)%npoints]->uv, points[idx[0]]->uv, v);
+
+ v[0] = points[idx[1]]->uv[0] + 1.0f;
+ v[1] = points[idx[1]]->uv[1];
+ a[1] = p_vec2_angle(points[(idx[1]+1)%npoints]->uv, points[idx[1]]->uv, v);
+
+ v[0] = points[idx[2]]->uv[0];
+ v[1] = points[idx[2]]->uv[1] - 1.0f;
+ a[2] = p_vec2_angle(points[(idx[2]+1)%npoints]->uv, points[idx[2]]->uv, v);
+
+ v[0] = points[idx[3]]->uv[0] - 1.0f;
+ v[1] = points[idx[3]]->uv[1];
+ a[3] = p_vec2_angle(points[(idx[3]+1)%npoints]->uv, points[idx[3]]->uv, v);
+
+ /* 4 rotating calipers */
+
+ rotated = 0.0;
+ minarea = 1e10;
+ minangle = 0.0;
+
+ while (rotated <= M_PI/2) { /* INVESTIGATE: how far to rotate? */
+ /* rotate with the smallest angle */
+ mini = 0;
+ mina = 1e10;
+
+ for (i = 0; i < 4; i++)
+ if (a[i] < mina) {
+ mina = a[i];
+ mini = i;
+ }
+
+ rotated += mina;
+ nextidx = (idx[mini]+1)%npoints;
+
+ a[mini] = angles[nextidx];
+ a[(mini+1)%4] = a[(mini+1)%4] - mina;
+ a[(mini+2)%4] = a[(mini+2)%4] - mina;
+ a[(mini+3)%4] = a[(mini+3)%4] - mina;
+
+ /* compute area */
+ p1 = points[idx[mini]];
+ p1n = points[nextidx];
+ p2 = points[idx[(mini+1)%4]];
+ p3 = points[idx[(mini+2)%4]];
+ p4 = points[idx[(mini+3)%4]];
+
+ len = Vec2Lenf(p1->uv, p1n->uv);
+
+ if (len > 0.0f) {
+ len = 1.0/len;
+ v[0] = (p1n->uv[0] - p1->uv[0])*len;
+ v[1] = (p1n->uv[1] - p1->uv[1])*len;
+
+ area = p_rectangle_area(p1->uv, v, p2->uv, p3->uv, p4->uv);
+
+ /* remember smallest area */
+ if (area < minarea) {
+ minarea = area;
+ minangle = rotated;
+ }
+ }
+
+ idx[mini] = nextidx;
+ }
+
+ /* try keeping rotation as small as possible */
+ if (minangle > M_PI/4)
+ minangle -= M_PI/2;
+
+ MEM_freeN(angles);
+ MEM_freeN(points);
+
+ return minangle;
+}
+
+static void p_chart_rotate_minimum_area(PChart *chart)
+{
+ float angle = p_chart_minimum_area_angle(chart);
+ float sine = sin(angle);
+ float cosine = cos(angle);
+ PVert *v;
+
+ for (v = chart->verts; v; v=v->nextlink) {
+ float oldu = v->uv[0], oldv = v->uv[1];
+ v->uv[0] = cosine*oldu - sine*oldv;
+ v->uv[1] = sine*oldu + cosine*oldv;
+ }
+}
+
+/* Area Smoothing */
+
+/* 2d bsp tree for inverse mapping - that's a bit silly */
+
+typedef struct SmoothTriangle {
+ float co1[2], co2[2], co3[2];
+ float oco1[2], oco2[2], oco3[2];
+} SmoothTriangle;
+
+typedef struct SmoothNode {
+ struct SmoothNode *c1, *c2;
+ SmoothTriangle **tri;
+ float split;
+ int axis, ntri;
+} SmoothNode;
+
+static void p_barycentric_2d(float *v1, float *v2, float *v3, float *p, float *b)
+{
+ float a[2], c[2], h[2], div;
+
+ a[0] = v2[0] - v1[0];
+ a[1] = v2[1] - v1[1];
+ c[0] = v3[0] - v1[0];
+ c[1] = v3[1] - v1[1];
+
+ div = a[0]*c[1] - a[1]*c[0];
+
+ if (div == 0.0f) {
+ b[0] = 1.0f/3.0f;
+ b[1] = 1.0f/3.0f;
+ b[2] = 1.0f/3.0f;
+ }
+ else {
+ h[0] = p[0] - v1[0];
+ h[1] = p[1] - v1[1];
+
+ div = 1.0f/div;
+
+ b[1] = (h[0]*c[1] - h[1]*c[0])*div;
+ b[2] = (a[0]*h[1] - a[1]*h[0])*div;
+ b[0] = 1.0 - b[1] - b[2];
+ }
+}
+
+static PBool p_triangle_inside(SmoothTriangle *t, float *co)
+{
+ float b[3];
+
+ p_barycentric_2d(t->co1, t->co2, t->co3, co, b);
+
+ if ((b[0] >= 0.0) && (b[1] >= 0.0) && (b[2] >= 0.0f)) {
+ co[0] = t->oco1[0]*b[0] + t->oco2[0]*b[1] + t->oco3[0]*b[2];
+ co[1] = t->oco1[1]*b[0] + t->oco2[1]*b[1] + t->oco3[1]*b[2];
+ return P_TRUE;
+ }
+
+ return P_FALSE;
+}
+
+static SmoothNode *p_node_new(MemArena *arena, SmoothTriangle **tri, int ntri, float *bmin, float *bmax, int depth)
+{
+ SmoothNode *node = BLI_memarena_alloc(arena, sizeof *node);
+ int axis, i, t1size = 0, t2size = 0;
+ float split, mi, mx;
+ SmoothTriangle **t1, **t2, *t;
+
+ node->tri = tri;
+ node->ntri = ntri;
+
+ if (ntri <= 10 || depth >= 15)
+ return node;
+
+ t1 = MEM_mallocN(sizeof(SmoothTriangle)*ntri, "PNodeTri1");
+ t2 = MEM_mallocN(sizeof(SmoothTriangle)*ntri, "PNodeTri1");
+
+ axis = (bmax[0] - bmin[0] > bmax[1] - bmin[1])? 0: 1;
+ split = 0.5f*(bmin[axis] + bmax[axis]);
+
+ for (i = 0; i < ntri; i++) {
+ t = tri[i];
+
+ if ((t->co1[axis] <= split) || (t->co2[axis] <= split) || (t->co3[axis] <= split)) {
+ t1[t1size] = t;
+ t1size++;
+ }
+ if ((t->co1[axis] >= split) || (t->co2[axis] >= split) || (t->co3[axis] >= split)) {
+ t2[t2size] = t;
+ t2size++;
+ }
+ }
+
+ if ((t1size == t2size) && (t1size == ntri)) {
+ MEM_freeN(t1);
+ MEM_freeN(t2);
+ return node;
+ }
+
+ node->tri = NULL;
+ node->ntri = 0;
+ MEM_freeN(tri);
+
+ node->axis = axis;
+ node->split = split;
+
+ mi = bmin[axis];
+ mx = bmax[axis];
+ bmax[axis] = split;
+ node->c1 = p_node_new(arena, t1, t1size, bmin, bmax, depth+1);
+
+ bmin[axis] = bmax[axis];
+ bmax[axis] = mx;
+ node->c2 = p_node_new(arena, t2, t2size, bmin, bmax, depth+1);
+
+ return node;
+}
+
+static void p_node_delete(SmoothNode *node)
+{
+ if (node->c1)
+ p_node_delete(node->c1);
+ if (node->c2)
+ p_node_delete(node->c2);
+ if (node->tri)
+ MEM_freeN(node->tri);
+}
+
+static PBool p_node_intersect(SmoothNode *node, float *co)
+{
+ int i;
+
+ if (node->tri) {
+ for (i = 0; i < node->ntri; i++)
+ if (p_triangle_inside(node->tri[i], co))
+ return P_TRUE;
+
+ return P_FALSE;
+ }
+ else {
+ if (co[node->axis] < node->split)
+ return p_node_intersect(node->c1, co);
+ else
+ return p_node_intersect(node->c2, co);
+ }
+
+}
+
+/* smooothing */
+
+static int p_compare_float(const void *a, const void *b)
+{
+ if (*((float*)a) < *((float*)b))
+ return -1;
+ else if (*((float*)a) == *((float*)b))
+ return 0;
+ else
+ return 1;
+}
+
+static float p_smooth_median_edge_length(PChart *chart)
+{
+ PEdge *e;
+ float *lengths = MEM_mallocN(sizeof(chart->edges)*chart->nedges, "PMedianLength");
+ float median;
+ int i;
+
+ /* ok, so i'm lazy */
+ for (i=0, e=chart->edges; e; e=e->nextlink, i++)
+ lengths[i] = p_edge_length(e);
+
+ qsort(lengths, i, sizeof(float), p_compare_float);
+
+ median = lengths[i/2];
+ MEM_freeN(lengths);
+
+ return median;
+}
+
+static float p_smooth_distortion(PEdge *e, float avg2d, float avg3d)
+{
+ float len2d = p_edge_uv_length(e)*avg3d;
+ float len3d = p_edge_length(e)*avg2d;
+
+ return (len3d == 0.0f)? 0.0f: len2d/len3d;
+}
+
+static void p_smooth(PChart *chart)
+{
+ PEdge *e;
+ PVert *v;
+ PFace *f;
+ int j, it2, maxiter2, it;
+ int nedges = chart->nedges, nwheel, gridx, gridy;
+ int edgesx, edgesy, nsize, esize, i, x, y, maxiter, totiter;
+ float minv[2], maxv[2], median, invmedian, distortion, avglen2d, avglen3d;
+ float center[2], dx, dy, *nodes, dlimit, d, *oldnodesx, *oldnodesy;
+ float *nodesx, *nodesy, *hedges, *vedges, climit, moved, padding;
+ SmoothTriangle *triangles, *t, *t2, **tri, **trip;
+ SmoothNode *root;
+ MemArena *arena;
+
+ if (nedges == 0)
+ return;
+
+ p_chart_uv_bbox(chart, minv, maxv);
+ median = p_smooth_median_edge_length(chart)*0.10f;
+
+ if (median == 0.0)
+ return;
+
+ invmedian = 1.0/median;
+
+ /* compute edge distortion */
+ distortion = 0.0;
+ avglen2d = avglen3d = 0.0;
+
+ for (e=chart->edges; e; e=e->nextlink) {
+ avglen2d += p_edge_uv_length(e);
+ avglen3d += p_edge_length(e);
+ }
+
+ avglen2d /= nedges;
+ avglen3d /= nedges;
+
+ for (v=chart->verts; v; v=v->nextlink) {
+ v->u.distortion = 0.0;
+ nwheel = 0;
+
+ e = v->edge;
+ do {
+ v->u.distortion += p_smooth_distortion(e, avglen2d, avglen3d);
+ nwheel++;
+
+ e = e->next->next->pair;
+ } while(e && (e != v->edge));
+
+ v->u.distortion /= nwheel;
+ }
+
+ /* need to do excessive grid size checking still */
+ center[0] = 0.5f*(minv[0] + maxv[0]);
+ center[1] = 0.5f*(minv[1] + maxv[1]);
+
+ dx = 0.5f*(maxv[0] - minv[0]);
+ dy = 0.5f*(maxv[1] - minv[1]);
+
+ padding = 0.15f;
+ dx += padding*dx + 2.0f*median;
+ dy += padding*dy + 2.0f*median;
+
+ gridx = (int)(dx*invmedian);
+ gridy = (int)(dy*invmedian);
+
+ minv[0] = center[0] - median*gridx;
+ minv[1] = center[1] - median*gridy;
+ maxv[0] = center[0] + median*gridx;
+ maxv[1] = center[1] + median*gridy;
+
+ /* create grid */
+ gridx = gridx*2 + 1;
+ gridy = gridy*2 + 1;
+
+ if ((gridx <= 2) || (gridy <= 2))
+ return;
+
+ edgesx = gridx-1;
+ edgesy = gridy-1;
+ nsize = gridx*gridy;
+ esize = edgesx*edgesy;
+
+ nodes = MEM_mallocN(sizeof(float)*nsize, "PSmoothNodes");
+ nodesx = MEM_mallocN(sizeof(float)*nsize, "PSmoothNodesX");
+ nodesy = MEM_mallocN(sizeof(float)*nsize, "PSmoothNodesY");
+ oldnodesx = MEM_mallocN(sizeof(float)*nsize, "PSmoothOldNodesX");
+ oldnodesy = MEM_mallocN(sizeof(float)*nsize, "PSmoothOldNodesY");
+ hedges = MEM_mallocN(sizeof(float)*esize, "PSmoothHEdges");
+ vedges = MEM_mallocN(sizeof(float)*esize, "PSmoothVEdges");
+
+ if (!nodes || !nodesx || !nodesy || !oldnodesx || !oldnodesy || !hedges || !vedges) {
+ if (nodes) MEM_freeN(nodes);
+ if (nodesx) MEM_freeN(nodesx);
+ if (nodesy) MEM_freeN(nodesy);
+ if (oldnodesx) MEM_freeN(oldnodesx);
+ if (oldnodesy) MEM_freeN(oldnodesy);
+ if (hedges) MEM_freeN(hedges);
+ if (vedges) MEM_freeN(vedges);
+
+ // printf("Not enough memory for area smoothing grid.");
+ return;
+ }
+
+ for (x = 0; x < gridx; x++) {
+ for (y = 0; y < gridy; y++) {
+ i = x + y*gridx;
+
+ nodesx[i] = minv[0] + median*x;
+ nodesy[i] = minv[1] + median*y;
+
+ nodes[i] = 1.0f;
+ }
+ }
+
+ /* embed in grid */
+ for (f=chart->faces; f; f=f->nextlink) {
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ float fmin[2], fmax[2];
+ int bx1, by1, bx2, by2;
+
+ INIT_MINMAX2(fmin, fmax);
+
+ DO_MINMAX2(e1->vert->uv, fmin, fmax);
+ DO_MINMAX2(e2->vert->uv, fmin, fmax);
+ DO_MINMAX2(e3->vert->uv, fmin, fmax);
+
+ bx1 = (int)((fmin[0] - minv[0])*invmedian);
+ by1 = (int)((fmin[1] - minv[1])*invmedian);
+ bx2 = (int)((fmax[0] - minv[0])*invmedian + 2);
+ by2 = (int)((fmax[1] - minv[1])*invmedian + 2);
+
+ for (x = bx1; x < bx2; x++) {
+ for (y = by1; y < by2; y++) {
+ float p[2], b[3];
+
+ i = x + y*gridx;
+
+ p[0] = nodesx[i];
+ p[1] = nodesy[i];
+
+ p_barycentric_2d(e1->vert->uv, e2->vert->uv, e3->vert->uv, p, b);
+
+ if ((b[0] > 0.0) && (b[1] > 0.0) && (b[2] > 0.0)) {
+ nodes[i] = e1->vert->u.distortion*b[0];
+ nodes[i] += e2->vert->u.distortion*b[1];
+ nodes[i] += e3->vert->u.distortion*b[2];
+ }
+ }
+ }
+ }
+
+ /* smooth the grid */
+ maxiter = 10;
+ totiter = 0;
+ climit = 0.00001f*nsize;
+
+ for (it = 0; it < maxiter; it++) {
+ moved = 0.0f;
+
+ for (x = 0; x < edgesx; x++) {
+ for (y = 0; y < edgesy; y++) {
+ i = x + y*gridx;
+ j = x + y*edgesx;
+
+ hedges[j] = (nodes[i] + nodes[i+1])*0.5f;
+ vedges[j] = (nodes[i] + nodes[i+gridx])*0.5f;
+
+ /* we do *inverse* mapping */
+ hedges[j] = 1.0f/hedges[j];
+ vedges[j] = 1.0f/vedges[j];
+ }
+ }
+
+ maxiter2 = 50;
+ dlimit = 0.0001f;
+
+ for (it2 = 0; it2 < maxiter2; it2++) {
+ d = 0.0f;
+ totiter += 1;
+
+ memcpy(oldnodesx, nodesx, sizeof(float)*nsize);
+ memcpy(oldnodesy, nodesy, sizeof(float)*nsize);
+
+ for (x=1; x < gridx-1; x++) {
+ for (y=1; y < gridy-1; y++) {
+ float p[2], oldp[2], sum1, sum2, diff[2], length;
+
+ i = x + gridx*y;
+ j = x + edgesx*y;
+
+ oldp[0] = oldnodesx[i];
+ oldp[1] = oldnodesy[i];
+
+ sum1 = hedges[j-1]*oldnodesx[i-1];
+ sum1 += hedges[j]*oldnodesx[i+1];
+ sum1 += vedges[j-edgesx]*oldnodesx[i-gridx];
+ sum1 += vedges[j]*oldnodesx[i+gridx];
+
+ sum2 = hedges[j-1];
+ sum2 += hedges[j];
+ sum2 += vedges[j-edgesx];
+ sum2 += vedges[j];
+
+ nodesx[i] = sum1/sum2;
+
+ sum1 = hedges[j-1]*oldnodesy[i-1];
+ sum1 += hedges[j]*oldnodesy[i+1];
+ sum1 += vedges[j-edgesx]*oldnodesy[i-gridx];
+ sum1 += vedges[j]*oldnodesy[i+gridx];
+
+ nodesy[i] = sum1/sum2;
+
+ p[0] = nodesx[i];
+ p[1] = nodesy[i];
+
+ diff[0] = p[0] - oldp[0];
+ diff[1] = p[1] - oldp[1];
+
+ length = sqrt(diff[0]*diff[0] + diff[1]*diff[1]);
+ d = MAX2(d, length);
+ moved += length;
+ }
+ }
+
+ if (d < dlimit)
+ break;
+ }
+
+ if (moved < climit)
+ break;
+ }
+
+ MEM_freeN(oldnodesx);
+ MEM_freeN(oldnodesy);
+ MEM_freeN(hedges);
+ MEM_freeN(vedges);
+
+ /* create bsp */
+ t = triangles = MEM_mallocN(sizeof(SmoothTriangle)*esize*2, "PSmoothTris");
+ trip = tri = MEM_mallocN(sizeof(SmoothTriangle*)*esize*2, "PSmoothTriP");
+
+ if (!triangles || !tri) {
+ MEM_freeN(nodes);
+ MEM_freeN(nodesx);
+ MEM_freeN(nodesy);
+
+ if (triangles) MEM_freeN(triangles);
+ if (tri) MEM_freeN(tri);
+
+ // printf("Not enough memory for area smoothing grid.");
+ return;
+ }
+
+ for (x = 0; x < edgesx; x++) {
+ for (y = 0; y < edgesy; y++) {
+ i = x + y*gridx;
+
+ t->co1[0] = nodesx[i];
+ t->co1[1] = nodesy[i];
+
+ t->co2[0] = nodesx[i+1];
+ t->co2[1] = nodesy[i+1];
+
+ t->co3[0] = nodesx[i+gridx];
+ t->co3[1] = nodesy[i+gridx];
+
+ t->oco1[0] = minv[0] + x*median;
+ t->oco1[1] = minv[1] + y*median;
+
+ t->oco2[0] = minv[0] + (x+1)*median;
+ t->oco2[1] = minv[1] + y*median;
+
+ t->oco3[0] = minv[0] + x*median;
+ t->oco3[1] = minv[1] + (y+1)*median;
+
+ t2 = t+1;
+
+ t2->co1[0] = nodesx[i+gridx+1];
+ t2->co1[1] = nodesy[i+gridx+1];
+
+ t2->oco1[0] = minv[0] + (x+1)*median;
+ t2->oco1[1] = minv[1] + (y+1)*median;
+
+ t2->co2[0] = t->co2[0]; t2->co2[1] = t->co2[1];
+ t2->oco2[0] = t->oco2[0]; t2->oco2[1] = t->oco2[1];
+
+ t2->co3[0] = t->co3[0]; t2->co3[1] = t->co3[1];
+ t2->oco3[0] = t->oco3[0]; t2->oco3[1] = t->oco3[1];
+
+ *trip = t; trip++; t++;
+ *trip = t; trip++; t++;
+ }
+ }
+
+ MEM_freeN(nodes);
+ MEM_freeN(nodesx);
+ MEM_freeN(nodesy);
+
+ arena = BLI_memarena_new(1<<16);
+ root = p_node_new(arena, tri, esize*2, minv, maxv, 0);
+
+ for (v=chart->verts; v; v=v->nextlink)
+ if (!p_node_intersect(root, v->uv))
+ param_warning("area smoothing error: couldn't find mapping triangle\n");
+
+ p_node_delete(root);
+ BLI_memarena_free(arena);
+
+ MEM_freeN(triangles);
+}
+
+/* Exported */
+
+ParamHandle *param_construct_begin()
+{
+ PHandle *handle = MEM_callocN(sizeof*handle, "PHandle");
+ handle->construction_chart = p_chart_new(handle);
+ handle->state = PHANDLE_STATE_ALLOCATED;
+ handle->arena = BLI_memarena_new((1<<16));
+ handle->aspx = 1.0f;
+ handle->aspy = 1.0f;
+
+ handle->hash_verts = phash_new((PHashLink**)&handle->construction_chart->verts, 1);
+ handle->hash_edges = phash_new((PHashLink**)&handle->construction_chart->edges, 1);
+ handle->hash_faces = phash_new((PHashLink**)&handle->construction_chart->faces, 1);
+
+ return (ParamHandle*)handle;
+}
+
+void param_aspect_ratio(ParamHandle *handle, float aspx, float aspy)
+{
+ PHandle *phandle = (PHandle*)handle;
+
+ phandle->aspx = aspx;
+ phandle->aspy = aspy;
+}
+
+void param_delete(ParamHandle *handle)
+{
+ PHandle *phandle = (PHandle*)handle;
+ int i;
+
+ param_assert((phandle->state == PHANDLE_STATE_ALLOCATED) ||
+ (phandle->state == PHANDLE_STATE_CONSTRUCTED));
+
+ for (i = 0; i < phandle->ncharts; i++)
+ p_chart_delete(phandle->charts[i]);
+
+ if (phandle->charts)
+ MEM_freeN(phandle->charts);
+
+ if (phandle->construction_chart) {
+ p_chart_delete(phandle->construction_chart);
+
+ phash_delete(phandle->hash_verts);
+ phash_delete(phandle->hash_edges);
+ phash_delete(phandle->hash_faces);
+ }
+
+ BLI_memarena_free(phandle->arena);
+ MEM_freeN(phandle);
+}
+
+void param_face_add(ParamHandle *handle, ParamKey key, int nverts,
+ ParamKey *vkeys, float **co, float **uv,
+ ParamBool *pin, ParamBool *select)
+{
+ PHandle *phandle = (PHandle*)handle;
+
+ param_assert(phash_lookup(phandle->hash_faces, key) == NULL);
+ param_assert(phandle->state == PHANDLE_STATE_ALLOCATED);
+ param_assert((nverts == 3) || (nverts == 4));
+
+ if (nverts == 4) {
+ if (p_quad_split_direction(phandle, co, vkeys)) {
+ p_face_add_construct(phandle, key, vkeys, co, uv, 0, 1, 2, pin, select);
+ p_face_add_construct(phandle, key, vkeys, co, uv, 0, 2, 3, pin, select);
+ }
+ else {
+ p_face_add_construct(phandle, key, vkeys, co, uv, 0, 1, 3, pin, select);
+ p_face_add_construct(phandle, key, vkeys, co, uv, 1, 2, 3, pin, select);
+ }
+ }
+ else
+ p_face_add_construct(phandle, key, vkeys, co, uv, 0, 1, 2, pin, select);
+}
+
+void param_edge_set_seam(ParamHandle *handle, ParamKey *vkeys)
+{
+ PHandle *phandle = (PHandle*)handle;
+ PEdge *e;
+
+ param_assert(phandle->state == PHANDLE_STATE_ALLOCATED);
+
+ e = p_edge_lookup(phandle, vkeys);
+ if (e)
+ e->flag |= PEDGE_SEAM;
+}
+
+void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool impl)
+{
+ PHandle *phandle = (PHandle*)handle;
+ PChart *chart = phandle->construction_chart;
+ int i, j, nboundaries = 0;
+ PEdge *outer;
+
+ param_assert(phandle->state == PHANDLE_STATE_ALLOCATED);
+
+ phandle->ncharts = p_connect_pairs(phandle, impl);
+ phandle->charts = p_split_charts(phandle, chart, phandle->ncharts);
+
+ p_chart_delete(phandle->construction_chart);
+ phandle->construction_chart = NULL;
+
+ phash_delete(phandle->hash_verts);
+ phash_delete(phandle->hash_edges);
+ phash_delete(phandle->hash_faces);
+ phandle->hash_verts = phandle->hash_edges = phandle->hash_faces = NULL;
+
+ for (i = j = 0; i < phandle->ncharts; i++) {
+ PVert *v;
+ chart = phandle->charts[i];
+
+ p_chart_boundaries(chart, &nboundaries, &outer);
+
+ if (!impl && nboundaries == 0) {
+ p_chart_delete(chart);
+ continue;
+ }
+
+ phandle->charts[j] = chart;
+ j++;
+
+ if (fill && (nboundaries > 1))
+ p_chart_fill_boundaries(chart, outer);
+
+ for (v=chart->verts; v; v=v->nextlink)
+ p_vert_load_pin_select_uvs(handle, v);
+ }
+
+ phandle->ncharts = j;
+
+ phandle->state = PHANDLE_STATE_CONSTRUCTED;
+}
+
+void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf)
+{
+ PHandle *phandle = (PHandle*)handle;
+ PFace *f;
+ int i;
+
+ param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED);
+ phandle->state = PHANDLE_STATE_LSCM;
+
+ for (i = 0; i < phandle->ncharts; i++) {
+ for (f=phandle->charts[i]->faces; f; f=f->nextlink)
+ p_face_backup_uvs(f);
+ p_chart_lscm_begin(phandle->charts[i], live, abf);
+ }
+}
+
+void param_lscm_solve(ParamHandle *handle)
+{
+ PHandle *phandle = (PHandle*)handle;
+ PChart *chart;
+ int i;
+ PBool result;
+
+ param_assert(phandle->state == PHANDLE_STATE_LSCM);
+
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
+
+ if (chart->u.lscm.context) {
+ result = p_chart_lscm_solve(phandle, chart);
+
+ if (result && !(chart->flag & PCHART_NOPACK))
+ p_chart_rotate_minimum_area(chart);
+
+ if (!result || (chart->u.lscm.pin1))
+ p_chart_lscm_end(chart);
+ }
+ }
+}
+
+void param_lscm_end(ParamHandle *handle)
+{
+ PHandle *phandle = (PHandle*)handle;
+ int i;
+
+ param_assert(phandle->state == PHANDLE_STATE_LSCM);
+
+ for (i = 0; i < phandle->ncharts; i++) {
+ p_chart_lscm_end(phandle->charts[i]);
+#if 0
+ p_chart_complexify(phandle->charts[i]);
+#endif
+ }
+
+ phandle->state = PHANDLE_STATE_CONSTRUCTED;
+}
+
+void param_stretch_begin(ParamHandle *handle)
+{
+ PHandle *phandle = (PHandle*)handle;
+ PChart *chart;
+ PVert *v;
+ PFace *f;
+ int i;
+
+ param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED);
+ phandle->state = PHANDLE_STATE_STRETCH;
+
+ phandle->rng = rng_new(31415926);
+ phandle->blend = 0.0f;
+
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
+
+ for (v=chart->verts; v; v=v->nextlink)
+ v->flag &= ~PVERT_PIN; /* don't use user-defined pins */
+
+ p_stretch_pin_boundary(chart);
+
+ for (f=chart->faces; f; f=f->nextlink) {
+ p_face_backup_uvs(f);
+ f->u.area3d = p_face_area(f);
+ }
+ }
+}
+
+void param_stretch_blend(ParamHandle *handle, float blend)
+{
+ PHandle *phandle = (PHandle*)handle;
+
+ param_assert(phandle->state == PHANDLE_STATE_STRETCH);
+ phandle->blend = blend;
+}
+
+void param_stretch_iter(ParamHandle *handle)
+{
+ PHandle *phandle = (PHandle*)handle;
+ PChart *chart;
+ int i;
+
+ param_assert(phandle->state == PHANDLE_STATE_STRETCH);
+
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
+ p_chart_stretch_minimize(chart, phandle->rng);
+ }
+}
+
+void param_stretch_end(ParamHandle *handle)
+{
+ PHandle *phandle = (PHandle*)handle;
+
+ param_assert(phandle->state == PHANDLE_STATE_STRETCH);
+ phandle->state = PHANDLE_STATE_CONSTRUCTED;
+
+ rng_free(phandle->rng);
+ phandle->rng = NULL;
+}
+
+void param_smooth_area(ParamHandle *handle)
+{
+ PHandle *phandle = (PHandle*)handle;
+ int i;
+
+ param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED);
+
+ for (i = 0; i < phandle->ncharts; i++) {
+ PChart *chart = phandle->charts[i];
+ PVert *v;
+
+ for (v=chart->verts; v; v=v->nextlink)
+ v->flag &= ~PVERT_PIN;
+
+ p_smooth(chart);
+ }
+}
+
+void param_pack(ParamHandle *handle, float margin)
+{
+ /* box packing variables */
+ boxPack *boxarray, *box;
+ float tot_width, tot_height, scale;
+
+ PChart *chart;
+ int i, unpacked=0;
+ float trans[2];
+ double area= 0.0;
+
+ PHandle *phandle = (PHandle*)handle;
+
+ if (phandle->ncharts == 0)
+ return;
+
+ if(phandle->aspx != phandle->aspy)
+ param_scale(handle, 1.0f/phandle->aspx, 1.0f/phandle->aspy);
+
+ /* we may not use all these boxes */
+ boxarray = MEM_mallocN( phandle->ncharts*sizeof(boxPack), "boxPack box");
+
+
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
+
+ if (chart->flag & PCHART_NOPACK) {
+ unpacked++;
+ continue;
+ }
+
+ box = boxarray+(i-unpacked);
+
+ p_chart_uv_bbox(chart, trans, chart->u.pack.size);
+
+ trans[0] = -trans[0];
+ trans[1] = -trans[1];
+
+ p_chart_uv_translate(chart, trans);
+
+ box->w = chart->u.pack.size[0] + trans[0];
+ box->h = chart->u.pack.size[1] + trans[1];
+ box->index = i; /* warning this index skips PCHART_NOPACK boxes */
+
+ if(margin>0.0f)
+ area += sqrt(box->w*box->h);
+ }
+
+ if(margin>0.0f) {
+ /* multiply the margin by the area to give pradictable results not dependant on UV scale,
+ * ...Without using the area running pack multiple times also gives a bad feedback loop.
+ * multiply by 0.1 so the margin value from the UI can be from 0.0 to 1.0 but not give a massive margin */
+ margin = (margin*(float)area) * 0.1;
+ unpacked= 0;
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
+
+ if (chart->flag & PCHART_NOPACK) {
+ unpacked++;
+ continue;
+ }
+
+ box = boxarray+(i-unpacked);
+ trans[0] = margin * area;
+ trans[1] = margin * area;
+ p_chart_uv_translate(chart, trans);
+ box->w += (margin * area) *2;
+ box->h += (margin * area) *2;
+ }
+ }
+
+ boxPack2D(boxarray, phandle->ncharts-unpacked, &tot_width, &tot_height);
+
+ if (tot_height>tot_width)
+ scale = 1.0/tot_height;
+ else
+ scale = 1.0/tot_width;
+
+ for (i = 0; i < phandle->ncharts-unpacked; i++) {
+ box = boxarray+i;
+ trans[0] = box->x;
+ trans[1] = box->y;
+
+ chart = phandle->charts[box->index];
+ p_chart_uv_translate(chart, trans);
+ p_chart_uv_scale(chart, scale);
+ }
+ MEM_freeN(boxarray);
+
+ if(phandle->aspx != phandle->aspy)
+ param_scale(handle, phandle->aspx, phandle->aspy);
+}
+
+void param_average(ParamHandle *handle)
+{
+ PChart *chart;
+ int i;
+ float tot_uvarea = 0.0f, tot_facearea = 0.0f;
+ float tot_fac, fac;
+ float minv[2], maxv[2], trans[2];
+ PHandle *phandle = (PHandle*)handle;
+
+ if (phandle->ncharts == 0)
+ return;
+
+ for (i = 0; i < phandle->ncharts; i++) {
+ PFace *f;
+ chart = phandle->charts[i];
+
+ chart->u.pack.area = 0.0f; /* 3d area */
+ chart->u.pack.rescale = 0.0f; /* UV area, abusing rescale for tmp storage, oh well :/ */
+
+ for (f=chart->faces; f; f=f->nextlink) {
+ chart->u.pack.area += p_face_area(f);
+ chart->u.pack.rescale += fabs(p_face_uv_area_signed(f));
+ }
+
+ tot_facearea += chart->u.pack.area;
+ tot_uvarea += chart->u.pack.rescale;
+ }
+
+ if (tot_facearea == tot_uvarea || tot_facearea==0.0f || tot_uvarea==0.0f) {
+ /* nothing to do */
+ return;
+ }
+
+ tot_fac = tot_facearea/tot_uvarea;
+
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
+ if (chart->u.pack.area != 0.0f && chart->u.pack.rescale != 0.0f) {
+ fac = chart->u.pack.area / chart->u.pack.rescale;
+
+ /* Get the island center */
+ p_chart_uv_bbox(chart, minv, maxv);
+ trans[0] = (minv[0] + maxv[0]) /-2.0f;
+ trans[1] = (minv[1] + maxv[1]) /-2.0f;
+
+ /* Move center to 0,0 */
+ p_chart_uv_translate(chart, trans);
+ p_chart_uv_scale(chart, sqrt(fac / tot_fac));
+
+ /* Move to original center */
+ trans[0] = -trans[0];
+ trans[1] = -trans[1];
+ p_chart_uv_translate(chart, trans);
+ }
+ }
+}
+
+void param_scale(ParamHandle *handle, float x, float y)
+{
+ PHandle *phandle = (PHandle*)handle;
+ PChart *chart;
+ int i;
+
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
+ p_chart_uv_scale_xy(chart, x, y);
+ }
+}
+
+void param_flush(ParamHandle *handle)
+{
+ PHandle *phandle = (PHandle*)handle;
+ PChart *chart;
+ int i;
+
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
+
+ if ((phandle->state == PHANDLE_STATE_LSCM) && !chart->u.lscm.context)
+ continue;
+
+ if (phandle->blend == 0.0f)
+ p_flush_uvs(phandle, chart);
+ else
+ p_flush_uvs_blend(phandle, chart, phandle->blend);
+ }
+}
+
+void param_flush_restore(ParamHandle *handle)
+{
+ PHandle *phandle = (PHandle*)handle;
+ PChart *chart;
+ PFace *f;
+ int i;
+
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
+
+ for (f=chart->faces; f; f=f->nextlink)
+ p_face_restore_uvs(f);
+ }
+}
+
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.h b/source/blender/editors/uvedit/uvedit_parametrizer.h
new file mode 100644
index 00000000000..f1454ee3865
--- /dev/null
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.h
@@ -0,0 +1,97 @@
+
+#ifndef __PARAMETRIZER_H__
+#define __PARAMETRIZER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+typedef void ParamHandle; /* handle to a set of charts */
+typedef intptr_t ParamKey; /* (hash) key for identifying verts and faces */
+typedef enum ParamBool {
+ PARAM_TRUE = 1,
+ PARAM_FALSE = 0
+} ParamBool;
+
+/* Chart construction:
+ -------------------
+ - faces and seams may only be added between construct_{begin|end}
+ - the pointers to co and uv are stored, rather than being copied
+ - vertices are implicitly created
+ - in construct_end the mesh will be split up according to the seams
+ - the resulting charts must be:
+ - manifold, connected, open (at least one boundary loop)
+ - output will be written to the uv pointers
+*/
+
+ParamHandle *param_construct_begin();
+
+void param_aspect_ratio(ParamHandle *handle, float aspx, float aspy);
+
+void param_face_add(ParamHandle *handle,
+ ParamKey key,
+ int nverts,
+ ParamKey *vkeys,
+ float **co,
+ float **uv,
+ ParamBool *pin,
+ ParamBool *select);
+
+void param_edge_set_seam(ParamHandle *handle,
+ ParamKey *vkeys);
+
+void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool impl);
+void param_delete(ParamHandle *chart);
+
+/* Least Squares Conformal Maps:
+ -----------------------------
+ - charts with less than two pinned vertices are assigned 2 pins
+ - lscm is divided in three steps:
+ - begin: compute matrix and it's factorization (expensive)
+ - solve using pinned coordinates (cheap)
+ - end: clean up
+ - uv coordinates are allowed to change within begin/end, for
+ quick re-solving
+*/
+
+void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf);
+void param_lscm_solve(ParamHandle *handle);
+void param_lscm_end(ParamHandle *handle);
+
+/* Stretch */
+
+void param_stretch_begin(ParamHandle *handle);
+void param_stretch_blend(ParamHandle *handle, float blend);
+void param_stretch_iter(ParamHandle *handle);
+void param_stretch_end(ParamHandle *handle);
+
+/* Area Smooth */
+
+void param_smooth_area(ParamHandle *handle);
+
+/* Packing */
+
+void param_pack(ParamHandle *handle, float margin);
+
+/* Average area for all charts */
+
+void param_average(ParamHandle *handle);
+
+/* Simple x,y scale */
+
+void param_scale(ParamHandle *handle, float x, float y);
+
+/* Flushing */
+
+void param_flush(ParamHandle *handle);
+void param_flush_restore(ParamHandle *handle);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__PARAMETRIZER_H__*/
+
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
new file mode 100644
index 00000000000..4d12700d98c
--- /dev/null
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -0,0 +1,1343 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_utildefines.h"
+
+#include "BLI_arithb.h"
+#include "BLI_edgehash.h"
+#include "BLI_editVert.h"
+
+#include "PIL_time.h"
+
+#include "ED_image.h"
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_uvedit.h"
+#include "ED_view3d.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "uvedit_intern.h"
+#include "uvedit_parametrizer.h"
+
+static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
+{
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tf;
+
+ if(ED_uvedit_test(obedit)) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return 1;
+ }
+
+ if(em && em->faces.first)
+ EM_add_data_layer(em, &em->fdata, CD_MTFACE);
+
+ if(!ED_uvedit_test(obedit)) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return 0;
+ }
+
+ // XXX this image is not in context in 3d view .. only
+ // way to get would be to find the first image window?
+ ED_uvedit_assign_image(scene, obedit, CTX_data_edit_image(C), NULL);
+
+ /* select new UV's */
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ uvedit_face_select(scene, efa, tf);
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return 1;
+}
+
+/****************** Parametrizer Conversion ***************/
+
+ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short implicit, short fill, short sel, short correct_aspect)
+{
+ ParamHandle *handle;
+ EditFace *efa;
+ EditEdge *eed;
+ EditVert *ev;
+ MTFace *tf;
+ int a;
+
+ handle = param_construct_begin();
+
+ if(correct_aspect) {
+ efa = EM_get_actFace(em, 1);
+
+ if(efa) {
+ MTFace *tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ float aspx, aspy;
+
+ ED_image_uv_aspect(tf->tpage, &aspx, &aspy);
+
+ if(aspx!=aspy)
+ param_aspect_ratio(handle, aspx, aspy);
+ }
+ }
+
+ /* we need the vert indicies */
+ for(ev= em->verts.first, a=0; ev; ev= ev->next, a++)
+ ev->tmp.l = a;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ ParamKey key, vkeys[4];
+ ParamBool pin[4], select[4];
+ float *co[4];
+ float *uv[4];
+ int nverts;
+
+ if((efa->h) || (sel && (efa->f & SELECT)==0))
+ continue;
+
+ tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ if(implicit &&
+ !( uvedit_uv_selected(scene, efa, tf, 0) ||
+ uvedit_uv_selected(scene, efa, tf, 1) ||
+ uvedit_uv_selected(scene, efa, tf, 2) ||
+ (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) )
+ ) {
+ continue;
+ }
+
+ key = (ParamKey)efa;
+ vkeys[0] = (ParamKey)efa->v1->tmp.l;
+ vkeys[1] = (ParamKey)efa->v2->tmp.l;
+ vkeys[2] = (ParamKey)efa->v3->tmp.l;
+
+ co[0] = efa->v1->co;
+ co[1] = efa->v2->co;
+ co[2] = efa->v3->co;
+
+ uv[0] = tf->uv[0];
+ uv[1] = tf->uv[1];
+ uv[2] = tf->uv[2];
+
+ pin[0] = ((tf->unwrap & TF_PIN1) != 0);
+ pin[1] = ((tf->unwrap & TF_PIN2) != 0);
+ pin[2] = ((tf->unwrap & TF_PIN3) != 0);
+
+ select[0] = ((uvedit_uv_selected(scene, efa, tf, 0)) != 0);
+ select[1] = ((uvedit_uv_selected(scene, efa, tf, 1)) != 0);
+ select[2] = ((uvedit_uv_selected(scene, efa, tf, 2)) != 0);
+
+ if(efa->v4) {
+ vkeys[3] = (ParamKey)efa->v4->tmp.l;
+ co[3] = efa->v4->co;
+ uv[3] = tf->uv[3];
+ pin[3] = ((tf->unwrap & TF_PIN4) != 0);
+ select[3] = (uvedit_uv_selected(scene, efa, tf, 3) != 0);
+ nverts = 4;
+ }
+ else
+ nverts = 3;
+
+ param_face_add(handle, key, nverts, vkeys, co, uv, pin, select);
+ }
+
+ if(!implicit) {
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->seam) {
+ ParamKey vkeys[2];
+ vkeys[0] = (ParamKey)eed->v1->tmp.l;
+ vkeys[1] = (ParamKey)eed->v2->tmp.l;
+ param_edge_set_seam(handle, vkeys);
+ }
+ }
+ }
+
+ param_construct_end(handle, fill, implicit);
+
+ return handle;
+}
+
+/* ******************** Minimize Stretch operator **************** */
+
+typedef struct MinStretch {
+ Scene *scene;
+ Object *obedit;
+ EditMesh *em;
+ ParamHandle *handle;
+ float blend;
+ double lasttime;
+ int i, iterations;
+ wmTimer *timer;
+} MinStretch;
+
+static void minimize_stretch_init(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ MinStretch *ms;
+ int fill_holes= RNA_boolean_get(op->ptr, "fill_holes");
+
+ ms= MEM_callocN(sizeof(MinStretch), "MinStretch");
+ ms->scene= scene;
+ ms->obedit= obedit;
+ ms->em= em;
+ ms->blend= RNA_float_get(op->ptr, "blend");
+ ms->iterations= RNA_int_get(op->ptr, "iterations");
+ ms->handle= construct_param_handle(scene, em, 1, fill_holes, 1, 1);
+ ms->lasttime= PIL_check_seconds_timer();
+
+ param_stretch_begin(ms->handle);
+ if(ms->blend != 0.0f)
+ param_stretch_blend(ms->handle, ms->blend);
+
+ op->customdata= ms;
+}
+
+static void minimize_stretch_iteration(bContext *C, wmOperator *op, int interactive)
+{
+ MinStretch *ms= op->customdata;
+ ScrArea *sa= CTX_wm_area(C);
+
+ param_stretch_blend(ms->handle, ms->blend);
+ param_stretch_iter(ms->handle);
+
+ if(interactive && (PIL_check_seconds_timer() - ms->lasttime > 0.5)) {
+ char str[100];
+
+ param_flush(ms->handle);
+
+ if(sa) {
+ sprintf(str, "Minimize Stretch. Blend %.2f.", ms->blend);
+ ED_area_headerprint(sa, str);
+ }
+
+ ms->lasttime = PIL_check_seconds_timer();
+
+ DAG_object_flush_update(ms->scene, ms->obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ms->obedit);
+ }
+}
+
+static void minimize_stretch_exit(bContext *C, wmOperator *op, int cancel)
+{
+ MinStretch *ms= op->customdata;
+ ScrArea *sa= CTX_wm_area(C);
+
+ if(sa)
+ ED_area_headerprint(sa, NULL);
+ if(ms->timer)
+ WM_event_remove_window_timer(CTX_wm_window(C), ms->timer);
+
+ if(cancel)
+ param_flush_restore(ms->handle);
+ else
+ param_flush(ms->handle);
+
+ param_stretch_end(ms->handle);
+ param_delete(ms->handle);
+
+ DAG_object_flush_update(ms->scene, ms->obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ms->obedit);
+
+ MEM_freeN(ms);
+ op->customdata= NULL;
+}
+
+static int minimize_stretch_exec(bContext *C, wmOperator *op)
+{
+ int i, iterations;
+
+ minimize_stretch_init(C, op);
+
+ iterations= RNA_int_get(op->ptr, "iterations");
+ for(i=0; i<iterations; i++)
+ minimize_stretch_iteration(C, op, 0);
+ minimize_stretch_exit(C, op, 0);
+
+ return OPERATOR_FINISHED;
+}
+
+static int minimize_stretch_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ MinStretch *ms;
+
+ minimize_stretch_init(C, op);
+ minimize_stretch_iteration(C, op, 1);
+
+ ms= op->customdata;
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+ ms->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.01f);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int minimize_stretch_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ MinStretch *ms= op->customdata;
+
+ switch(event->type) {
+ case ESCKEY:
+ case RIGHTMOUSE:
+ minimize_stretch_exit(C, op, 1);
+ return OPERATOR_CANCELLED;
+ case RETKEY:
+ case PADENTER:
+ case LEFTMOUSE:
+ minimize_stretch_exit(C, op, 0);
+ return OPERATOR_FINISHED;
+ case PADPLUSKEY:
+ case WHEELUPMOUSE:
+ if(ms->blend < 0.95f) {
+ ms->blend += 0.1f;
+ ms->lasttime= 0.0f;
+ RNA_float_set(op->ptr, "blend", ms->blend);
+ minimize_stretch_iteration(C, op, 1);
+ }
+ break;
+ case PADMINUS:
+ case WHEELDOWNMOUSE:
+ if(ms->blend > 0.05f) {
+ ms->blend -= 0.1f;
+ ms->lasttime= 0.0f;
+ RNA_float_set(op->ptr, "blend", ms->blend);
+ minimize_stretch_iteration(C, op, 1);
+ }
+ break;
+ case TIMER:
+ if(ms->timer == event->customdata) {
+ double start= PIL_check_seconds_timer();
+
+ do {
+ minimize_stretch_iteration(C, op, 1);
+ } while(PIL_check_seconds_timer() - start < 0.01);
+ }
+ break;
+ }
+
+ if(ms->iterations && ms->i >= ms->iterations) {
+ minimize_stretch_exit(C, op, 0);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int minimize_stretch_cancel(bContext *C, wmOperator *op)
+{
+ minimize_stretch_exit(C, op, 1);
+
+ return OPERATOR_CANCELLED;
+}
+
+void UV_OT_minimize_stretch(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Minimize Stretch";
+ ot->idname= "UV_OT_minimize_stretch";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= minimize_stretch_exec;
+ ot->invoke= minimize_stretch_invoke;
+ ot->modal= minimize_stretch_modal;
+ ot->cancel= minimize_stretch_cancel;
+ ot->poll= ED_operator_uvedit;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes", "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry.");
+ RNA_def_float_percentage(ot->srna, "blend", 0.0f, 0.0f, 1.0f, "Blend", "Blend factor between stretch minimized and original.", 0.0f, 1.0f);
+ RNA_def_int(ot->srna, "iterations", 0, 0, INT_MAX, "Iterations", "Number of iterations to run, 0 is unlimited when run interactively.", 0, 100);
+}
+
+/* ******************** Pack Islands operator **************** */
+
+static int pack_islands_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ ParamHandle *handle;
+
+ handle = construct_param_handle(scene, em, 1, 0, 1, 1);
+ param_pack(handle, scene->toolsettings->uvcalc_margin);
+ param_flush(handle);
+ param_delete(handle);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_pack_islands(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Pack Islands";
+ ot->idname= "UV_OT_pack_islands";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= pack_islands_exec;
+ ot->poll= ED_operator_uvedit;
+}
+
+/* ******************** Average Islands Scale operator **************** */
+
+static int average_islands_scale_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ ParamHandle *handle;
+
+ handle= construct_param_handle(scene, em, 1, 0, 1, 1);
+ param_average(handle);
+ param_flush(handle);
+ param_delete(handle);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_average_islands_scale(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Average Islands Scale";
+ ot->idname= "UV_OT_average_islands_scale";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= average_islands_scale_exec;
+ ot->poll= ED_operator_uvedit;
+}
+
+/**************** Live Unwrap *****************/
+
+static ParamHandle *liveHandle = NULL;
+
+void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
+{
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ short abf = scene->toolsettings->unwrapper == 1;
+ short fillholes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
+
+ if(!ED_uvedit_test(obedit)) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return;
+ }
+
+ liveHandle = construct_param_handle(scene, em, 0, fillholes, 1, 1);
+
+ param_lscm_begin(liveHandle, PARAM_TRUE, abf);
+ BKE_mesh_end_editmesh(obedit->data, em);
+}
+
+void ED_uvedit_live_unwrap_re_solve(void)
+{
+ if(liveHandle) {
+ param_lscm_solve(liveHandle);
+ param_flush(liveHandle);
+ }
+}
+
+void ED_uvedit_live_unwrap_end(short cancel)
+{
+ if(liveHandle) {
+ param_lscm_end(liveHandle);
+ if(cancel)
+ param_flush_restore(liveHandle);
+ param_delete(liveHandle);
+ liveHandle = NULL;
+ }
+}
+
+/*************** UV Map Common Transforms *****************/
+
+#define VIEW_ON_EQUATOR 0
+#define VIEW_ON_POLES 1
+#define ALIGN_TO_OBJECT 2
+
+#define POLAR_ZX 0
+#define POLAR_ZY 1
+
+static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, Object *ob, EditMesh *em)
+{
+ EditFace *efa;
+ float min[3], max[3], *cursx;
+ int around= (v3d)? v3d->around: V3D_CENTER;
+
+ /* only operates on the edit object - this is all that's needed now */
+
+ switch(around) {
+ case V3D_CENTER: /* bounding box center */
+ min[0]= min[1]= min[2]= 1e20f;
+ max[0]= max[1]= max[2]= -1e20f;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ DO_MINMAX(efa->v1->co, min, max);
+ DO_MINMAX(efa->v2->co, min, max);
+ DO_MINMAX(efa->v3->co, min, max);
+ if(efa->v4) DO_MINMAX(efa->v4->co, min, max);
+ }
+ }
+ VecMidf(result, min, max);
+ break;
+
+ case V3D_CURSOR: /*cursor center*/
+ cursx= give_cursor(scene, v3d);
+ /* shift to objects world */
+ result[0]= cursx[0]-ob->obmat[3][0];
+ result[1]= cursx[1]-ob->obmat[3][1];
+ result[2]= cursx[2]-ob->obmat[3][2];
+ break;
+
+ case V3D_LOCAL: /*object center*/
+ case V3D_CENTROID: /* multiple objects centers, only one object here*/
+ default:
+ result[0]= result[1]= result[2]= 0.0;
+ break;
+ }
+}
+
+static void uv_map_rotation_matrix(float result[][4], RegionView3D *rv3d, Object *ob, float upangledeg, float sideangledeg, float radius)
+{
+ float rotup[4][4], rotside[4][4], viewmatrix[4][4], rotobj[4][4];
+ float sideangle= 0.0f, upangle= 0.0f;
+ int k;
+
+ /* get rotation of the current view matrix */
+ if(rv3d)
+ Mat4CpyMat4(viewmatrix, rv3d->viewmat);
+ else
+ Mat4One(viewmatrix);
+
+ /* but shifting */
+ for(k=0; k<4; k++)
+ viewmatrix[3][k] =0.0f;
+
+ /* get rotation of the current object matrix */
+ Mat4CpyMat4(rotobj,ob->obmat);
+
+ /* but shifting */
+ for(k=0; k<4; k++)
+ rotobj[3][k] =0.0f;
+
+ Mat4Clr(*rotup);
+ Mat4Clr(*rotside);
+
+ /* compensate front/side.. against opengl x,y,z world definition */
+ /* this is "kanonen gegen spatzen", a few plus minus 1 will do here */
+ /* i wanted to keep the reason here, so we're rotating*/
+ sideangle= (float)M_PI*(sideangledeg + 180.0f)/180.0f;
+ rotside[0][0]= (float)cos(sideangle);
+ rotside[0][1]= -(float)sin(sideangle);
+ rotside[1][0]= (float)sin(sideangle);
+ rotside[1][1]= (float)cos(sideangle);
+ rotside[2][2]= 1.0f;
+
+ upangle= (float)M_PI*upangledeg/180.0f;
+ rotup[1][1]= (float)cos(upangle)/radius;
+ rotup[1][2]= -(float)sin(upangle)/radius;
+ rotup[2][1]= (float)sin(upangle)/radius;
+ rotup[2][2]= (float)cos(upangle)/radius;
+ rotup[0][0]= (float)1.0f/radius;
+
+ /* calculate transforms*/
+ Mat4MulSerie(result, rotup, rotside, viewmatrix, rotobj, NULL, NULL, NULL, NULL);
+}
+
+static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float rotmat[4][4])
+{
+ /* context checks are messy here, making it work in both 3d view and uv editor */
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ View3D *v3d= CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ /* common operator properties */
+ int align= RNA_enum_get(op->ptr, "align");
+ int direction= RNA_enum_get(op->ptr, "direction");
+ float radius= RNA_struct_find_property(op->ptr, "radius")? RNA_float_get(op->ptr, "radius"): 1.0f;
+ float upangledeg, sideangledeg;
+
+ uv_map_transform_center(scene, v3d, center, obedit, em);
+
+ if(direction == VIEW_ON_EQUATOR) {
+ upangledeg= 90.0f;
+ sideangledeg= 0.0f;
+ }
+ else {
+ upangledeg= 0.0f;
+ if(align == POLAR_ZY) sideangledeg= 0.0f;
+ else sideangledeg= 90.0f;
+ }
+
+ /* be compatible to the "old" sphere/cylinder mode */
+ if(direction == ALIGN_TO_OBJECT)
+ Mat4One(rotmat);
+ else
+ uv_map_rotation_matrix(rotmat, rv3d, obedit, upangledeg, sideangledeg, radius);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+}
+
+static void uv_transform_properties(wmOperatorType *ot, int radius)
+{
+ static EnumPropertyItem direction_items[]= {
+ {VIEW_ON_EQUATOR, "VIEW_ON_EQUATOR", "View on Equator", "3D view is on the equator."},
+ {VIEW_ON_POLES, "VIEW_ON_POLES", "View on Poles", "3D view is on the poles."},
+ {ALIGN_TO_OBJECT, "ALIGN_TO_OBJECT", "Align to Object", "Align according to object transform."},
+ {0, NULL, NULL, NULL}
+ };
+ static EnumPropertyItem align_items[]= {
+ {POLAR_ZX, "POLAR_ZX", "Polar ZX", "Polar 0 is X."},
+ {POLAR_ZY, "POLAR_ZY", "Polar ZY", "Polar 0 is Y."},
+ {0, NULL, NULL, NULL}
+ };
+
+ RNA_def_enum(ot->srna, "direction", direction_items, VIEW_ON_EQUATOR, "Direction", "Direction of the sphere or cylinder.");
+ RNA_def_enum(ot->srna, "align", align_items, VIEW_ON_EQUATOR, "Align", "How to determine rotation around the pole.");
+ if(radius)
+ RNA_def_float(ot->srna, "radius", 1.0f, 0.0f, FLT_MAX, "Radius", "Radius of the sphere or cylinder.", 0.0001f, 100.0f);
+}
+
+static void correct_uv_aspect(EditMesh *em)
+{
+ EditFace *efa= EM_get_actFace(em, 1);
+ MTFace *tf;
+ float scale, aspx= 1.0f, aspy=1.0f;
+
+ if(efa) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ ED_image_uv_aspect(tf->tpage, &aspx, &aspy);
+ }
+
+ if(aspx == aspy)
+ return;
+
+ if(aspx > aspy) {
+ scale= aspy/aspx;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ tf->uv[0][0]= ((tf->uv[0][0]-0.5)*scale)+0.5;
+ tf->uv[1][0]= ((tf->uv[1][0]-0.5)*scale)+0.5;
+ tf->uv[2][0]= ((tf->uv[2][0]-0.5)*scale)+0.5;
+ if(efa->v4)
+ tf->uv[3][0]= ((tf->uv[3][0]-0.5)*scale)+0.5;
+ }
+ }
+ }
+ else {
+ scale= aspx/aspy;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ tf->uv[0][1]= ((tf->uv[0][1]-0.5)*scale)+0.5;
+ tf->uv[1][1]= ((tf->uv[1][1]-0.5)*scale)+0.5;
+ tf->uv[2][1]= ((tf->uv[2][1]-0.5)*scale)+0.5;
+ if(efa->v4)
+ tf->uv[3][1]= ((tf->uv[3][1]-0.5)*scale)+0.5;
+ }
+ }
+ }
+}
+
+/******************** Map Clip & Correct ******************/
+
+static void uv_map_clip_correct_properties(wmOperatorType *ot)
+{
+ RNA_def_boolean(ot->srna, "correct_aspect", 1, "Correct Aspect", "Map UV's taking image aspect ratio into account.");
+ RNA_def_boolean(ot->srna, "clip_to_bounds", 0, "Clip to Bounds", "Clip UV coordinates to bounds after unwrapping.");
+ RNA_def_boolean(ot->srna, "scale_to_bounds", 0, "Scale to Bounds", "Scale UV coordinates to bounds after unwrapping.");
+}
+
+static void uv_map_clip_correct(EditMesh *em, wmOperator *op)
+{
+ EditFace *efa;
+ MTFace *tf;
+ float dx, dy, min[2], max[2];
+ int b, nverts;
+ int correct_aspect= RNA_boolean_get(op->ptr, "correct_aspect");
+ int clip_to_bounds= RNA_boolean_get(op->ptr, "clip_to_bounds");
+ int scale_to_bounds= RNA_boolean_get(op->ptr, "scale_to_bounds");
+
+ /* correct for image aspect ratio */
+ if(correct_aspect)
+ correct_uv_aspect(em);
+
+ if(scale_to_bounds) {
+ INIT_MINMAX2(min, max);
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ DO_MINMAX2(tf->uv[0], min, max);
+ DO_MINMAX2(tf->uv[1], min, max);
+ DO_MINMAX2(tf->uv[2], min, max);
+
+ if(efa->v4)
+ DO_MINMAX2(tf->uv[3], min, max);
+ }
+ }
+
+ /* rescale UV to be in 1/1 */
+ dx= (max[0]-min[0]);
+ dy= (max[1]-min[1]);
+
+ if(dx > 0.0f)
+ dx= 1.0f/dx;
+ if(dy > 0.0f)
+ dy= 1.0f/dy;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ nverts= (efa->v4)? 4: 3;
+
+ for(b=0; b<nverts; b++) {
+ tf->uv[b][0]= (tf->uv[b][0]-min[0])*dx;
+ tf->uv[b][1]= (tf->uv[b][1]-min[1])*dy;
+ }
+ }
+ }
+ }
+ else if(clip_to_bounds) {
+ /* clipping and wrapping */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ nverts= (efa->v4)? 4: 3;
+
+ for(b=0; b<nverts; b++) {
+ CLAMP(tf->uv[b][0], 0.0, 1.0);
+ CLAMP(tf->uv[b][1], 0.0, 1.0);
+ }
+ }
+ }
+ }
+}
+
+/* ******************** Unwrap operator **************** */
+
+static int unwrap_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ ParamHandle *handle;
+ int method = RNA_enum_get(op->ptr, "method");
+ int fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
+ int correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
+
+ /* add uvs if they don't exist yet */
+ if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ handle= construct_param_handle(scene, em, 0, fill_holes, 0, correct_aspect);
+
+ param_lscm_begin(handle, PARAM_FALSE, method == 0);
+ param_lscm_solve(handle);
+ param_lscm_end(handle);
+
+ param_pack(handle, scene->toolsettings->uvcalc_margin);
+
+ param_flush(handle);
+
+ param_delete(handle);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_unwrap(wmOperatorType *ot)
+{
+ static EnumPropertyItem method_items[] = {
+ {0, "ANGLE_BASED", "Angle Based", ""},
+ {1, "CONFORMAL", "Conformal", ""},
+ {0, NULL, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "Unwrap";
+ ot->idname= "UV_OT_unwrap";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= unwrap_exec;
+ ot->poll= ED_operator_uvmap;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "method", method_items, 0, "Method", "Unwrapping method. Angle Based usually gives better results than Conformal, while being somewhat slower.");
+ RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes", "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry.");
+ RNA_def_boolean(ot->srna, "correct_aspect", 1, "Correct Aspect", "Map UV's taking image aspect ratio into account.");
+}
+
+/**************** Project From View operator **************/
+
+static void uv_from_view_bounds(float target[2], float source[3], float rotmat[4][4])
+{
+ float pv[3];
+
+ Mat4MulVecfl(rotmat, pv);
+
+ /* ortho projection */
+ target[0] = -pv[0];
+ target[1] = pv[2];
+}
+
+static void uv_from_view(ARegion *ar, float target[2], float source[3], float rotmat[4][4])
+{
+ RegionView3D *rv3d= ar->regiondata;
+ float pv[3], pv4[4], dx, dy, x= 0.0, y= 0.0;
+
+ Mat4MulVecfl(rotmat, pv);
+
+ dx= ar->winx;
+ dy= ar->winy;
+
+ VecCopyf(pv4, source);
+ pv4[3]= 1.0;
+
+ /* rotmat is the object matrix in this case */
+ Mat4MulVec4fl(rotmat, pv4);
+
+ /* almost project_short */
+ Mat4MulVec4fl(rv3d->persmat, pv4);
+ if(fabs(pv4[3]) > 0.00001) { /* avoid division by zero */
+ target[0] = dx/2.0 + (dx/2.0)*pv4[0]/pv4[3];
+ target[1] = dy/2.0 + (dy/2.0)*pv4[1]/pv4[3];
+ }
+ else {
+ /* scaling is lost but give a valid result */
+ target[0] = dx/2.0 + (dx/2.0)*pv4[0];
+ target[1] = dy/2.0 + (dy/2.0)*pv4[1];
+ }
+
+ /* v3d->persmat seems to do this funky scaling */
+ if(dx > dy) {
+ y= (dx-dy)/2.0;
+ dy = dx;
+ }
+ else {
+ x= (dy-dx)/2.0;
+ dx = dy;
+ }
+
+ target[0]= (x + target[0])/dx;
+ target[1]= (y + target[1])/dy;
+}
+
+static int from_view_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ ARegion *ar= CTX_wm_region(C);
+ EditFace *efa;
+ MTFace *tf;
+ float rotmat[4][4];
+
+ /* add uvs if they don't exist yet */
+ if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ if(RNA_boolean_get(op->ptr, "orthographic")) {
+ uv_map_rotation_matrix(rotmat, ar->regiondata, obedit, 90.0f, 0.0f, 1.0f);
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ uv_from_view_bounds(tf->uv[0], efa->v1->co, rotmat);
+ uv_from_view_bounds(tf->uv[1], efa->v2->co, rotmat);
+ uv_from_view_bounds(tf->uv[2], efa->v3->co, rotmat);
+ if(efa->v4)
+ uv_from_view_bounds(tf->uv[3], efa->v4->co, rotmat);
+ }
+ }
+ }
+ else {
+ Mat4CpyMat4(rotmat, obedit->obmat);
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ uv_from_view(ar, tf->uv[0], efa->v1->co, rotmat);
+ uv_from_view(ar, tf->uv[1], efa->v2->co, rotmat);
+ uv_from_view(ar, tf->uv[2], efa->v3->co, rotmat);
+ if(efa->v4)
+ uv_from_view(ar, tf->uv[3], efa->v4->co, rotmat);
+ }
+ }
+ }
+
+ uv_map_clip_correct(em, op);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+static int from_view_poll(bContext *C)
+{
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+
+ if(!ED_operator_uvmap(C))
+ return 0;
+
+ return (rv3d != NULL);
+}
+
+void UV_OT_from_view(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Project From View";
+ ot->idname= "UV_OT_project_from_view";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= from_view_exec;
+ ot->poll= from_view_poll;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "orthographic", 0, "Orthographic", "Use orthographic projection.");
+ uv_map_clip_correct_properties(ot);
+}
+
+/********************** Reset operator ********************/
+
+static int reset_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tf;
+
+ /* add uvs if they don't exist yet */
+ if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ tf->uv[0][0]= 0.0f;
+ tf->uv[0][1]= 0.0f;
+
+ tf->uv[1][0]= 1.0f;
+ tf->uv[1][1]= 0.0f;
+
+ tf->uv[2][0]= 1.0f;
+ tf->uv[2][1]= 1.0f;
+
+ tf->uv[3][0]= 0.0f;
+ tf->uv[3][1]= 1.0f;
+ }
+ }
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_reset(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Reset";
+ ot->idname= "UV_OT_reset";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= reset_exec;
+ ot->poll= ED_operator_uvmap;
+}
+
+/****************** Sphere Project operator ***************/
+
+static void uv_sphere_project(float target[2], float source[3], float center[3], float rotmat[4][4])
+{
+ float pv[3];
+
+ VecSubf(pv, source, center);
+ Mat4MulVecfl(rotmat, pv);
+
+ spheremap(pv[0], pv[1], pv[2], &target[0], &target[1]);
+
+ /* split line is always zero */
+ if(target[0] >= 1.0f)
+ target[0] -= 1.0f;
+}
+
+static void uv_map_mirror(EditFace *efa, MTFace *tf)
+{
+ float dx;
+ int nverts, i, mi;
+
+ nverts= (efa->v4)? 4: 3;
+
+ mi = 0;
+ for(i=1; i<nverts; i++)
+ if(tf->uv[i][0] > tf->uv[mi][0])
+ mi = i;
+
+ for(i=0; i<nverts; i++) {
+ if(i != mi) {
+ dx = tf->uv[mi][0] - tf->uv[i][0];
+ if(dx > 0.5) tf->uv[i][0] += 1.0;
+ }
+ }
+}
+
+static int sphere_project_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tf;
+ float center[3], rotmat[4][4];
+
+ /* add uvs if they don't exist yet */
+ if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ uv_map_transform(C, op, center, rotmat);
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ uv_sphere_project(tf->uv[0], efa->v1->co, center, rotmat);
+ uv_sphere_project(tf->uv[1], efa->v2->co, center, rotmat);
+ uv_sphere_project(tf->uv[2], efa->v3->co, center, rotmat);
+ if(efa->v4)
+ uv_sphere_project(tf->uv[3], efa->v4->co, center, rotmat);
+
+ uv_map_mirror(efa, tf);
+ }
+ }
+
+ uv_map_clip_correct(em, op);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_sphere_project(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Sphere Projection";
+ ot->idname= "UV_OT_sphere_project";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= sphere_project_exec;
+ ot->poll= ED_operator_uvmap;
+
+ /* properties */
+ uv_transform_properties(ot, 0);
+ uv_map_clip_correct_properties(ot);
+}
+
+/***************** Cylinder Project operator **************/
+
+static void uv_cylinder_project(float target[2], float source[3], float center[3], float rotmat[4][4])
+{
+ float pv[3];
+
+ VecSubf(pv, source, center);
+ Mat4MulVecfl(rotmat, pv);
+
+ tubemap(pv[0], pv[1], pv[2], &target[0], &target[1]);
+
+ /* split line is always zero */
+ if(target[0] >= 1.0f)
+ target[0] -= 1.0f;
+}
+
+static int cylinder_project_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tf;
+ float center[3], rotmat[4][4];
+
+ /* add uvs if they don't exist yet */
+ if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ uv_map_transform(C, op, center, rotmat);
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ uv_cylinder_project(tf->uv[0], efa->v1->co, center, rotmat);
+ uv_cylinder_project(tf->uv[1], efa->v2->co, center, rotmat);
+ uv_cylinder_project(tf->uv[2], efa->v3->co, center, rotmat);
+ if(efa->v4)
+ uv_cylinder_project(tf->uv[3], efa->v4->co, center, rotmat);
+
+ uv_map_mirror(efa, tf);
+ }
+ }
+
+ uv_map_clip_correct(em, op);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_cylinder_project(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Cylinder Projection";
+ ot->idname= "UV_OT_cylinder_project";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= cylinder_project_exec;
+ ot->poll= ED_operator_uvmap;
+
+ /* properties */
+ uv_transform_properties(ot, 1);
+ uv_map_clip_correct_properties(ot);
+}
+
+/******************* Cube Project operator ****************/
+
+static int cube_project_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ EditFace *efa;
+ MTFace *tf;
+ float no[3], cube_size, *loc, dx, dy;
+ int cox, coy;
+
+ /* add uvs if they don't exist yet */
+ if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ loc= obedit->obmat[3];
+ cube_size= RNA_float_get(op->ptr, "cube_size");
+
+ /* choose x,y,z axis for projection depending on the largest normal
+ * component, but clusters all together around the center of map. */
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, no);
+
+ no[0]= fabs(no[0]);
+ no[1]= fabs(no[1]);
+ no[2]= fabs(no[2]);
+
+ cox=0; coy= 1;
+ if(no[2]>=no[0] && no[2]>=no[1]);
+ else if(no[1]>=no[0] && no[1]>=no[2]) coy= 2;
+ else { cox= 1; coy= 2; }
+
+ tf->uv[0][0]= 0.5+0.5*cube_size*(loc[cox] + efa->v1->co[cox]);
+ tf->uv[0][1]= 0.5+0.5*cube_size*(loc[coy] + efa->v1->co[coy]);
+ dx = floor(tf->uv[0][0]);
+ dy = floor(tf->uv[0][1]);
+ tf->uv[0][0] -= dx;
+ tf->uv[0][1] -= dy;
+ tf->uv[1][0]= 0.5+0.5*cube_size*(loc[cox] + efa->v2->co[cox]);
+ tf->uv[1][1]= 0.5+0.5*cube_size*(loc[coy] + efa->v2->co[coy]);
+ tf->uv[1][0] -= dx;
+ tf->uv[1][1] -= dy;
+ tf->uv[2][0]= 0.5+0.5*cube_size*(loc[cox] + efa->v3->co[cox]);
+ tf->uv[2][1]= 0.5+0.5*cube_size*(loc[coy] + efa->v3->co[coy]);
+ tf->uv[2][0] -= dx;
+ tf->uv[2][1] -= dy;
+
+ if(efa->v4) {
+ tf->uv[3][0]= 0.5+0.5*cube_size*(loc[cox] + efa->v4->co[cox]);
+ tf->uv[3][1]= 0.5+0.5*cube_size*(loc[coy] + efa->v4->co[coy]);
+ tf->uv[3][0] -= dx;
+ tf->uv[3][1] -= dy;
+ }
+ }
+ }
+
+ uv_map_clip_correct(em, op);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_cube_project(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Cube Projection";
+ ot->idname= "UV_OT_cube_project";
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec= cube_project_exec;
+ ot->poll= ED_operator_uvmap;
+
+ /* properties */
+ RNA_def_float(ot->srna, "cube_size", 1.0f, 0.0f, FLT_MAX, "Cube Size", "Size of the cube to project on.", 0.001f, 100.0f);
+ uv_map_clip_correct_properties(ot);
+}
+
+/******************* Mapping Menu operator ****************/
+
+static int mapping_menu_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ uiMenuItem *head;
+
+ head= uiPupMenuBegin("UV Mapping", 0);
+ uiMenuItemO(head, 0, "UV_OT_unwrap");
+ uiMenuSeparator(head);
+ uiMenuItemO(head, 0, "UV_OT_cube_project");
+ uiMenuItemO(head, 0, "UV_OT_cylinder_project");
+ uiMenuItemO(head, 0, "UV_OT_sphere_project");
+ uiMenuItemO(head, 0, "UV_OT_project_from_view");
+ uiMenuSeparator(head);
+ uiMenuItemO(head, 0, "UV_OT_reset");
+ uiPupMenuEnd(C, head);
+
+ /* XXX python */
+#ifndef DISABLE_PYTHON
+#if 0
+ /* note that we account for the 10 previous entries with i+10: */
+ for(pym = BPyMenuTable[PYMENU_UVCALCULATION]; pym; pym = pym->next, i++) {
+
+ if(!has_pymenu) {
+ strcat(uvmenu, "|%l");
+ has_pymenu = 1;
+ }
+
+ strcat(uvmenu, "|");
+ strcat(uvmenu, pym->name);
+ strcat(uvmenu, " %x");
+ sprintf(menu_number, "%d", i+10);
+ strcat(uvmenu, menu_number);
+ }
+#endif
+#endif
+
+#ifndef DISABLE_PYTHON
+#if 0
+ mode= pupmenu(uvmenu);
+ if(mode >= 10) {
+ BPY_menu_do_python(PYMENU_UVCALCULATION, mode - 10);
+ return;
+ }
+#endif
+#endif
+
+ return OPERATOR_CANCELLED;
+}
+
+void UV_OT_mapping_menu(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mapping Menu";
+ ot->idname= "UV_OT_mapping_menu";
+
+ /* api callbacks */
+ ot->invoke= mapping_menu_invoke;
+ ot->poll= ED_operator_uvmap;
+}
+